From 4af244f4aa0dd97e3e2178a3a1fd4dd53760b529 Mon Sep 17 00:00:00 2001 From: r0qs Date: Fri, 2 Feb 2024 14:55:12 +0100 Subject: [PATCH 0001/1340] Separate nightly-ossfuzz workflow from nightly workflow --- .circleci/config.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 30c022964..9d3105a27 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1978,10 +1978,6 @@ workflows: <<: *on_develop jobs: - # OSSFUZZ builds and (regression) tests - - b_ubu_ossfuzz: *requires_nothing - - t_ubu_ossfuzz: *requires_b_ubu_ossfuzz - # Code Coverage enabled build and tests - b_ubu_codecov: *requires_nothing - t_ubu_codecov: *requires_b_ubu_codecov @@ -1997,3 +1993,15 @@ workflows: - b_ubu_san_clang: *job_b_ubu_ubsan_clang - t_ubu_ubsan_clang_soltest: *requires_b_ubu_ubsan_clang - t_ubu_ubsan_clang_cli: *requires_b_ubu_ubsan_clang + + nightly-ossfuzz: + + triggers: + - schedule: + cron: "0 0 * * *" + <<: *on_develop + + jobs: + # OSSFUZZ builds and (regression) tests + - b_ubu_ossfuzz: *requires_nothing + - t_ubu_ossfuzz: *requires_b_ubu_ossfuzz From 6ee38afed8792dd1dd669612a226bf8080a49ae2 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Thu, 7 Mar 2024 21:19:08 +0100 Subject: [PATCH 0002/1340] [solutil] Add missing include guard. --- libsolutil/cxx20.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libsolutil/cxx20.h b/libsolutil/cxx20.h index c65b0454b..a21a73e68 100644 --- a/libsolutil/cxx20.h +++ b/libsolutil/cxx20.h @@ -15,6 +15,7 @@ along with solidity. If not, see . */ // SPDX-License-Identifier: GPL-3.0 +#pragma once #include From e084f71f7b28294e38576458d72d32855aa4e0e5 Mon Sep 17 00:00:00 2001 From: Cyrus Date: Fri, 8 Mar 2024 12:11:48 +0800 Subject: [PATCH 0003/1340] fix typos --- libevmasm/GasMeter.h | 2 +- libevmasm/Inliner.cpp | 2 +- libsolidity/parsing/Parser.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index e4bb19925..c91e0f097 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -216,7 +216,7 @@ class GasMeter /// @returns an upper bound on the gas consumed by the given instruction and updates /// the state. - /// @param _inculdeExternalCosts if true, include costs caused by other contracts in calls. + /// @param _includeExternalCosts if true, include costs caused by other contracts in calls. GasConsumption estimateMax(AssemblyItem const& _item, bool _includeExternalCosts = true); u256 const& largestMemoryAccess() const { return m_largestMemoryAccess; } diff --git a/libevmasm/Inliner.cpp b/libevmasm/Inliner.cpp index ded5172dd..67918e558 100644 --- a/libevmasm/Inliner.cpp +++ b/libevmasm/Inliner.cpp @@ -44,7 +44,7 @@ using namespace solidity::evmasm; namespace { -/// @returns an estimation of the runtime gas cost of the AsssemblyItems in @a _itemRange. +/// @returns an estimation of the runtime gas cost of the AssemblyItems in @a _itemRange. template u256 executionCost(RangeType const& _itemRange, langutil::EVMVersion _evmVersion) { diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index aedfdb7dd..8f0868ac1 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -223,10 +223,10 @@ class Parser: public langutil::ParserBase /// or an expression; IndexAccessedPath parseIndexAccessedPath(); /// @returns a typename parsed in look-ahead fashion from something like "a.b[8][2**70]", - /// or an empty pointer if an empty @a _pathAndIncides has been supplied. + /// or an empty pointer if an empty @a _pathAndIndices has been supplied. ASTPointer typeNameFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices); /// @returns an expression parsed in look-ahead fashion from something like "a.b[8][2**70]", - /// or an empty pointer if an empty @a _pathAndIncides has been supplied. + /// or an empty pointer if an empty @a _pathAndIndices has been supplied. ASTPointer expressionFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices); ASTPointer expectIdentifierToken(); From 86444080a45f475a1065522ffd0ee32e28120c72 Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 29 Nov 2023 15:46:30 -0300 Subject: [PATCH 0004/1340] Move deprecated evm versions to nightly CI workflow --- .circleci/config.yml | 27 ++++++++++++++++++++++++++- .circleci/soltest_all.sh | 7 +++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 59d00ff41..af5ddef21 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -220,11 +220,18 @@ commands: command: .circleci/soltest.sh run_soltest_all: + parameters: + # NOTE: If not specified, soltest_all.sh will use the default values as specified in the script. + # In other words, it will execute for all EVM versions that are not marked as deprecated. + evm_versions: + description: "List of EVM versions (separated by space)." + type: string + default: "" steps: - run: name: soltest_all no_output_timeout: 30m - command: .circleci/soltest_all.sh + command: .circleci/soltest_all.sh "<< parameters.evm_versions >>" run_cmdline_tests: steps: @@ -1267,6 +1274,20 @@ jobs: steps: - soltest_all + t_ubu_soltest_deprecated_evm_versions: &t_ubu_soltest_deprecated_evm_versions + <<: *base_ubuntu2204_large + parallelism: 50 + steps: + - checkout + - attach_workspace: + at: build + - run_soltest_all: + evm_versions: homestead byzantium + - store_test_results: + path: test_results/ + - store_artifacts_test_results + - matrix_notify_failure_unless_pr + t_ubu_lsp: &t_ubu_lsp <<: *base_ubuntu2204_small steps: @@ -2004,6 +2025,10 @@ workflows: - t_ubu_ubsan_clang_soltest: *requires_b_ubu_ubsan_clang - t_ubu_ubsan_clang_cli: *requires_b_ubu_ubsan_clang + # Deprecated EVM versions tests + - b_ubu: *requires_nothing + - t_ubu_soltest_deprecated_evm_versions: *requires_b_ubu + nightly-ossfuzz: triggers: diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 1e941731d..40ee75b27 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -31,9 +31,12 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" -EVM_VALUES=(homestead byzantium constantinople petersburg istanbul berlin london paris shanghai cancun) +DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shanghai cancun) +# Deserialize the EVM_VALUES array if it was provided as argument or +# set EVM_VALUES to the default values. +IFS=" " read -ra EVM_VALUES <<< "${1:-${DEFAULT_EVM_VALUES[@]}}" + DEFAULT_EVM=shanghai -[[ " ${EVM_VALUES[*]} " =~ $DEFAULT_EVM ]] OPTIMIZE_VALUES=(0 1) # Run for ABI encoder v1, without SMTChecker tests. From 9762ebb24cdb79e22d94215e0ebccc27937c63e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 8 Mar 2024 18:55:33 +0100 Subject: [PATCH 0005/1340] Fix unnecessary compilation when --via-ir is used on its own --- Changelog.md | 1 + libsolidity/interface/CompilerStack.cpp | 2 +- test/cmdlineTests/abi_via_ir/args | 1 + test/cmdlineTests/abi_via_ir/input.sol | 28 ++++ test/cmdlineTests/abi_via_ir/output | 167 ++++++++++++++++++++++++ 5 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 test/cmdlineTests/abi_via_ir/args create mode 100644 test/cmdlineTests/abi_via_ir/input.sol create mode 100644 test/cmdlineTests/abi_via_ir/output diff --git a/Changelog.md b/Changelog.md index 6defb4d72..ab62f25eb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,7 @@ Compiler Features: Bugfixes: * Assembler: Prevent incorrect calculation of tag sizes. + * Commandline Interface: Do not run IR pipeline when ``--via-ir`` is used but no output that depends on the IR is requested. * EVM Assembly Import: Fix handling of missing source locations during import. * SMTChecker: Fix internal error caused by not respecting the sign of an integer type when constructing zero-value SMT expressions. * SMTChecker: Ensure query is properly flushed to a file before calling solver when using SMT-LIB interface. diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 693944175..eca1b50be 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -736,7 +736,7 @@ bool CompilerStack::compile(State _stopAfter) { try { - if (m_viaIR || m_generateIR) + if ((m_generateEvmBytecode && m_viaIR) || m_generateIR) generateIR(*contract); if (m_generateEvmBytecode) { diff --git a/test/cmdlineTests/abi_via_ir/args b/test/cmdlineTests/abi_via_ir/args new file mode 100644 index 000000000..5dc346ecb --- /dev/null +++ b/test/cmdlineTests/abi_via_ir/args @@ -0,0 +1 @@ +--abi --via-ir --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/abi_via_ir/input.sol b/test/cmdlineTests/abi_via_ir/input.sol new file mode 100644 index 000000000..1f5c758f7 --- /dev/null +++ b/test/cmdlineTests/abi_via_ir/input.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +error fileLevelError(uint z); + +library L { + event libraryEvent(uint r); + error libraryError(uint r); + error libraryErrorUnused(uint u); + event libraryEventUnused(uint u); +} + +contract C { + struct S { uint x; } + + event ev(uint y); + event anon_ev(uint y) anonymous; + + error err(uint z, uint w); + + function f(S memory s) public { + emit L.libraryEvent(3); + if (s.x > 1) + revert fileLevelError(3); + else + revert L.libraryError(4); + } +} diff --git a/test/cmdlineTests/abi_via_ir/output b/test/cmdlineTests/abi_via_ir/output new file mode 100644 index 000000000..daf18f349 --- /dev/null +++ b/test/cmdlineTests/abi_via_ir/output @@ -0,0 +1,167 @@ + +======= abi_via_ir/input.sol:C ======= +Contract JSON ABI +[ + { + "inputs": + [ + { + "internalType": "uint256", + "name": "z", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "w", + "type": "uint256" + } + ], + "name": "err", + "type": "error" + }, + { + "inputs": + [ + { + "internalType": "uint256", + "name": "z", + "type": "uint256" + } + ], + "name": "fileLevelError", + "type": "error" + }, + { + "inputs": + [ + { + "internalType": "uint256", + "name": "r", + "type": "uint256" + } + ], + "name": "libraryError", + "type": "error" + }, + { + "anonymous": true, + "inputs": + [ + { + "indexed": false, + "internalType": "uint256", + "name": "y", + "type": "uint256" + } + ], + "name": "anon_ev", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": false, + "internalType": "uint256", + "name": "y", + "type": "uint256" + } + ], + "name": "ev", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": false, + "internalType": "uint256", + "name": "r", + "type": "uint256" + } + ], + "name": "libraryEvent", + "type": "event" + }, + { + "inputs": + [ + { + "components": + [ + { + "internalType": "uint256", + "name": "x", + "type": "uint256" + } + ], + "internalType": "struct C.S", + "name": "s", + "type": "tuple" + } + ], + "name": "f", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] + +======= abi_via_ir/input.sol:L ======= +Contract JSON ABI +[ + { + "inputs": + [ + { + "internalType": "uint256", + "name": "r", + "type": "uint256" + } + ], + "name": "libraryError", + "type": "error" + }, + { + "inputs": + [ + { + "internalType": "uint256", + "name": "u", + "type": "uint256" + } + ], + "name": "libraryErrorUnused", + "type": "error" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": false, + "internalType": "uint256", + "name": "r", + "type": "uint256" + } + ], + "name": "libraryEvent", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": false, + "internalType": "uint256", + "name": "u", + "type": "uint256" + } + ], + "name": "libraryEventUnused", + "type": "event" + } +] From 0c4bca56a176116940740d0de4f371a0b5357484 Mon Sep 17 00:00:00 2001 From: omahs <73983677+omahs@users.noreply.github.com> Date: Fri, 8 Mar 2024 20:46:24 +0100 Subject: [PATCH 0006/1340] fix typo --- test/compilationTests/corion/ico.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/compilationTests/corion/ico.sol b/test/compilationTests/corion/ico.sol index 35960fe43..801b6d402 100644 --- a/test/compilationTests/corion/ico.sol +++ b/test/compilationTests/corion/ico.sol @@ -372,5 +372,5 @@ contract ico is safeMath { return startBlock <= block.number && block.number <= icoDelay && ( ! aborted ) && ( ! closed ); } - event EICO(address indexed Address, uint256 indexed value, address Affiliate, uint256 AffilateValue); + event EICO(address indexed Address, uint256 indexed value, address Affiliate, uint256 AffiliateValue); } From 193a4579aec550f71af7b5355d82ad57a8588d9d Mon Sep 17 00:00:00 2001 From: omahs <73983677+omahs@users.noreply.github.com> Date: Fri, 8 Mar 2024 20:50:22 +0100 Subject: [PATCH 0007/1340] fix typo --- docs/smtchecker.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index f8085b63d..dfdcf4651 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -944,7 +944,7 @@ the arguments. |complex) | | +-----------------------------------+--------------------------------------+ |external functions without |BMC: Erase state knowledge and assume | -|implementation |result is nondeterminisc. | +|implementation |result is nondeterministic. | | |CHC: Nondeterministic summary. | | |Try to infer invariants that hold | | |after the call returns. | From 0219d1e0f2df22cac5ba8e944f26f20860f7a56e Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Tue, 5 Mar 2024 13:14:32 +0100 Subject: [PATCH 0008/1340] SMTChecker: Fix usage of Eldarica with SMT callback Previously, CHC engine with SMT interface would always call Eldarica if it was present in the system, regardless whether user specified model-checker-solver as smtlib2 or eld. Here we make sure Eldarica is called only when it is specified as the solver of choice. The proposed solution is to make SMTSolverCommand modifiable and set it up properly based on the user settings. This requires changes also in UniversalCallback, because in the compiler we must be able to check if the given callback is UniversalCallback provided by CommandLineInterface. This mechanism can be used to migrate also other solvers to the SMTLIB interface by further extending/adapting SMTSolverCommand. Its advantage is that meaning of the callback stays the same, thus there is not need to change anything on the side of solc-js. --- Changelog.md | 3 ++- libsolidity/formal/ModelCheckerSettings.h | 2 +- libsolidity/interface/CompilerStack.cpp | 6 ++++++ libsolidity/interface/SMTSolverCommand.cpp | 23 +++++++++++++++++--- libsolidity/interface/SMTSolverCommand.h | 7 +++--- libsolidity/interface/UniversalCallback.h | 25 +++++++++++++--------- solc/CommandLineInterface.h | 2 +- 7 files changed, 49 insertions(+), 19 deletions(-) diff --git a/Changelog.md b/Changelog.md index 6defb4d72..6564cb9a3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,8 +11,9 @@ Compiler Features: Bugfixes: * Assembler: Prevent incorrect calculation of tag sizes. * EVM Assembly Import: Fix handling of missing source locations during import. - * SMTChecker: Fix internal error caused by not respecting the sign of an integer type when constructing zero-value SMT expressions. * SMTChecker: Ensure query is properly flushed to a file before calling solver when using SMT-LIB interface. + * SMTChecker: Fix internal error caused by not respecting the sign of an integer type when constructing zero-value SMT expressions. + * SMTChecker: Run Eldarica only when explicitly requested with `--model-checker-solvers eld`, even when it is present on the system. ### 0.8.24 (2024-01-25) diff --git a/libsolidity/formal/ModelCheckerSettings.h b/libsolidity/formal/ModelCheckerSettings.h index b645f7c3b..0cfa370c4 100644 --- a/libsolidity/formal/ModelCheckerSettings.h +++ b/libsolidity/formal/ModelCheckerSettings.h @@ -175,7 +175,7 @@ struct ModelCheckerSettings bool showUnsupported = false; smtutil::SMTSolverChoice solvers = smtutil::SMTSolverChoice::Z3(); ModelCheckerTargets targets = ModelCheckerTargets::Default(); - std::optional timeout; + std::optional timeout; // in milliseconds bool operator!=(ModelCheckerSettings const& _other) const noexcept { return !(*this == _other); } bool operator==(ModelCheckerSettings const& _other) const noexcept diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 693944175..e9df59963 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -654,7 +655,12 @@ bool CompilerStack::analyzeLegacy(bool _noErrorsSoFar) // m_modelCheckerSettings is spread to engines and solver interfaces, // so we need to check whether the enabled ones are available before building the classes. if (m_modelCheckerSettings.engine.any()) + { m_modelCheckerSettings.solvers = ModelChecker::checkRequestedSolvers(m_modelCheckerSettings.solvers, m_errorReporter); + if (auto* universalCallback = m_readFile.target()) + if (m_modelCheckerSettings.solvers.eld) + universalCallback->smtCommand().setEldarica(m_modelCheckerSettings.timeout); + } ModelChecker modelChecker(m_errorReporter, *this, m_smtlib2Responses, m_modelCheckerSettings, m_readFile); modelChecker.checkRequestedSourcesAndContracts(allSources); diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index d1c58c0c0..8ef36cb75 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -37,7 +37,17 @@ using solidity::util::errinfo_comment; namespace solidity::frontend { -SMTSolverCommand::SMTSolverCommand(std::string _solverCmd) : m_solverCmd(_solverCmd) {} +void SMTSolverCommand::setEldarica(std::optional timeoutInMilliseconds) +{ + m_arguments.clear(); + m_solverCmd = "eld"; + if (timeoutInMilliseconds) + { + unsigned int timeoutInSeconds = timeoutInMilliseconds.value() / 1000u; + timeoutInSeconds = timeoutInSeconds == 0 ? 1 : timeoutInSeconds; + m_arguments.push_back("-t:" + std::to_string(timeoutInSeconds)); + } +} ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::string const& _query) { @@ -46,6 +56,9 @@ ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::stri if (_kind != ReadCallback::kindString(ReadCallback::Kind::SMTQuery)) solAssert(false, "SMTQuery callback used as callback kind " + _kind); + if (m_solverCmd.empty()) + return ReadCallback::Result{false, "No solver set."}; + auto tempDir = solidity::util::TemporaryDirectory("smt"); util::h256 queryHash = util::keccak256(_query); auto queryFileName = tempDir.path() / ("query_" + queryHash.hex() + ".smt2"); @@ -58,11 +71,15 @@ ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::stri if (eldBin.empty()) return ReadCallback::Result{false, m_solverCmd + " binary not found."}; + auto args = m_arguments; + args.push_back(queryFileName.string()); + boost::process::ipstream pipe; boost::process::child eld( eldBin, - queryFileName, - boost::process::std_out > pipe + args, + boost::process::std_out > pipe, + boost::process::std_err >boost::process::null ); std::vector data; diff --git a/libsolidity/interface/SMTSolverCommand.h b/libsolidity/interface/SMTSolverCommand.h index 56a6ba171..1d1201e49 100644 --- a/libsolidity/interface/SMTSolverCommand.h +++ b/libsolidity/interface/SMTSolverCommand.h @@ -28,8 +28,6 @@ namespace solidity::frontend class SMTSolverCommand { public: - SMTSolverCommand(std::string _solverCmd); - /// Calls an SMT solver with the given query. frontend::ReadCallback::Result solve(std::string const& _kind, std::string const& _query); @@ -38,9 +36,12 @@ class SMTSolverCommand return [this](std::string const& _kind, std::string const& _query) { return solve(_kind, _query); }; } + void setEldarica(std::optional timeoutInMilliseconds); + private: /// The name of the solver's binary. - std::string const m_solverCmd; + std::string m_solverCmd; + std::vector m_arguments; }; } diff --git a/libsolidity/interface/UniversalCallback.h b/libsolidity/interface/UniversalCallback.h index 3fe74c65e..ef5450a1c 100644 --- a/libsolidity/interface/UniversalCallback.h +++ b/libsolidity/interface/UniversalCallback.h @@ -34,22 +34,27 @@ class UniversalCallback m_solver{_solver} {} + ReadCallback::Result operator()(std::string const& _kind, std::string const& _data) + { + if (_kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile)) + if (!m_fileReader) + return ReadCallback::Result{false, "No import callback."}; + else + return m_fileReader->readFile(_kind, _data); + else if (_kind == ReadCallback::kindString(ReadCallback::Kind::SMTQuery)) + return m_solver.solve(_kind, _data); + solAssert(false, "Unknown callback kind."); + } + frontend::ReadCallback::Callback callback() { - return [this](std::string const& _kind, std::string const& _data) -> ReadCallback::Result { - if (_kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile)) - if (!m_fileReader) - return ReadCallback::Result{false, "No import callback."}; - else - return m_fileReader->readFile(_kind, _data); - else if (_kind == ReadCallback::kindString(ReadCallback::Kind::SMTQuery)) - return m_solver.solve(_kind, _data); - solAssert(false, "Unknown callback kind."); - }; + return *this; } void resetImportCallback() { m_fileReader = nullptr; } + SMTSolverCommand& smtCommand() { return m_solver; } + private: FileReader* m_fileReader; SMTSolverCommand& m_solver; diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 906b34d62..1fb4ac00b 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -147,7 +147,7 @@ class CommandLineInterface std::ostream& m_serr; bool m_hasOutput = false; FileReader m_fileReader; - SMTSolverCommand m_solverCommand{"eld"}; + SMTSolverCommand m_solverCommand; UniversalCallback m_universalCallback{&m_fileReader, m_solverCommand}; std::optional m_standardJsonInput; std::unique_ptr m_compiler; From b18b23daf6c4d812211ff9ef329ae8c44999fb17 Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 12 Mar 2024 15:18:39 +0100 Subject: [PATCH 0009/1340] Add missing hardhat networks settings to external tests --- scripts/externalTests/common.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index bab5890aa..de9b8da96 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -332,12 +332,16 @@ function force_hardhat_compiler_settings echo "require('hardhat-gas-reporter');" echo "module.exports.gasReporter = ${gas_reporter_settings};" echo "module.exports.solidity = ${compiler_settings};" + echo "module.exports.networks.hardhat = module.exports.networks.hardhat || { hardfork: '${evm_version}' }" + echo "module.exports.networks.hardhat.hardfork = '${evm_version}'" else [[ $config_file == *\.ts ]] || assertFail [[ $config_var_name != "" ]] || assertFail echo 'import "hardhat-gas-reporter";' echo "${config_var_name}.gasReporter = ${gas_reporter_settings};" echo "${config_var_name}.solidity = {compilers: [${compiler_settings}]};" + echo "${config_var_name}.networks!.hardhat = ${config_var_name}.networks!.hardhat ?? { hardfork: '${evm_version}' };" + echo "${config_var_name}.networks!.hardhat!.hardfork = '${evm_version}'" fi >> "$config_file" } From c82707cae6a085585421f6952eedffccffb7cb56 Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 12 Mar 2024 16:50:51 +0100 Subject: [PATCH 0010/1340] Fix hardhat version to version that supports cancun hardfork --- test/externalTests/brink.sh | 1 + test/externalTests/elementfi.sh | 4 +--- test/externalTests/gnosis.sh | 1 + test/externalTests/pool-together.sh | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/externalTests/brink.sh b/test/externalTests/brink.sh index 48cc4028f..d8ad001ac 100755 --- a/test/externalTests/brink.sh +++ b/test/externalTests/brink.sh @@ -64,6 +64,7 @@ function brink_test # TODO: Remove this when Brink merges https://github.com/brinktrade/brink-core/pull/52 sed -i "s|\(function isValidSignature(bytes \)calldata\( _data, bytes \)calldata\( _signature)\)|\1memory\2memory\3|g" src/Test/MockEIP1271Validator.sol + neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" "$CURRENT_EVM_VERSION" "$extra_settings" "$extra_optimizer_settings" diff --git a/test/externalTests/elementfi.sh b/test/externalTests/elementfi.sh index f3ecbb141..f34a169e9 100755 --- a/test/externalTests/elementfi.sh +++ b/test/externalTests/elementfi.sh @@ -99,9 +99,7 @@ function elementfi_test # "ProviderError: Too Many Requests error received from eth-mainnet.alchemyapi.io" rm test/mockERC20YearnVaultTest.ts - # Several tests fail unless we use the exact versions hard-coded in package-lock.json - #neutralize_package_lock - + neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index 218a5a750..416d36153 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -76,6 +76,7 @@ function gnosis_safe_test sed -i "s|\(it\)\((\"can be used only via DELEGATECALL opcode\"\)|\1.skip\2|g" test/libraries/SignMessageLib.spec.ts sed -i "s|it\((\"can only be called from Safe itself\"\)|it.skip\1|g" test/libraries/Migration.spec.ts + neutralize_package_lock neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" diff --git a/test/externalTests/pool-together.sh b/test/externalTests/pool-together.sh index f841206ef..0fc8aafbd 100755 --- a/test/externalTests/pool-together.sh +++ b/test/externalTests/pool-together.sh @@ -66,6 +66,9 @@ function pool_together_test force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" yarn install + # Hardhat 2.20.0 is the last version that works. Newer versions throw this error: + # Unexpected config HardhatConfig.networks.hardhat.initialBaseFeePerGas found - This field is only valid for networks with EIP-1559. Try a newer hardfork or remove it. + yarn add hardhat@2.20.0 # These come with already compiled artifacts. We want them recompiled with latest compiler. rm -r node_modules/@pooltogether/yield-source-interface/artifacts/ From 6b3ca241105fd9298a3ff7f9dcb62bf1d58f952b Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 12 Mar 2024 18:51:24 +0100 Subject: [PATCH 0011/1340] Disable trident, chainlink and bleeps external tests --- .circleci/config.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index af5ddef21..e437e1d38 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1919,11 +1919,13 @@ workflows: - t_ext: *job_native_test_ext_elementfi - t_ext: *job_native_test_ext_brink - t_ext: *job_native_compile_ext_gp2 - - t_ext: *job_native_compile_ext_trident - t_ext: *job_native_compile_ext_euler - - t_ext: *job_native_compile_ext_bleeps - t_ext: *job_native_compile_ext_pool_together - - t_ext: *job_native_compile_ext_chainlink + # TODO: Dropping the external tests below since they are based on old forks and + # fail after update the default evm version to cancun. + #- t_ext: *job_native_compile_ext_trident + #- t_ext: *job_native_compile_ext_chainlink + #- t_ext: *job_native_compile_ext_bleeps - c_ext_benchmarks: <<: *requires_nothing @@ -1941,11 +1943,13 @@ workflows: # TODO: Dropping prb-math from the benchmarks since it is not implemented yet # in the new Foundry external testing infrastructure. # - t_native_test_ext_prb_math - - t_native_compile_ext_trident - t_native_compile_ext_euler - - t_native_compile_ext_bleeps - t_native_compile_ext_pool_together - - t_native_compile_ext_chainlink + # TODO: Dropping the external tests below since they are based on old forks and + # fail after update the default evm version to cancun. + #- t_native_compile_ext_trident + #- t_native_compile_ext_chainlink + #- t_native_compile_ext_bleeps # Windows build and tests - b_win: *requires_nothing From 7c6f9f1154b757b040b1cbd9e4383caf04ceeaa9 Mon Sep 17 00:00:00 2001 From: Twice Date: Thu, 14 Mar 2024 00:49:02 +0900 Subject: [PATCH 0012/1340] Use move ctor instead of copy ctor in stringOrDefault --- libsolutil/Assertions.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsolutil/Assertions.h b/libsolutil/Assertions.h index 6735cda16..4879299bf 100644 --- a/libsolutil/Assertions.h +++ b/libsolutil/Assertions.h @@ -28,6 +28,7 @@ #include #include +#include namespace solidity::util { @@ -69,7 +70,7 @@ inline std::string stringOrDefault(std::string _string, std::string _defaultStri { // NOTE: Putting this in a function rather than directly in a macro prevents the string from // being evaluated multiple times if it's not just a literal. - return (!_string.empty() ? _string : _defaultString); + return (!_string.empty() ? std::move(_string) : std::move(_defaultString)); } } From ab55b0a49840491cd6e47e87e519360e21e9c518 Mon Sep 17 00:00:00 2001 From: matheusaaguiar <95899911+matheusaaguiar@users.noreply.github.com> Date: Wed, 13 Mar 2024 14:55:48 -0300 Subject: [PATCH 0013/1340] Add multiple source test to ensure transient storage is emitted only once during compilation (#14935) --- ...ore_warning_only_once_multiple_sources.sol | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/tstore_warning_only_once_multiple_sources.sol diff --git a/test/libsolidity/syntaxTests/inlineAssembly/tstore_warning_only_once_multiple_sources.sol b/test/libsolidity/syntaxTests/inlineAssembly/tstore_warning_only_once_multiple_sources.sol new file mode 100644 index 000000000..51e3a19bc --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/tstore_warning_only_once_multiple_sources.sol @@ -0,0 +1,34 @@ +==== Source: A ==== +contract C { + function f() external { + assembly { + tstore(0, 0) + let a := tload(0) + tstore(0, 1) + tstore(1, a) + } + } +} +==== Source: B ==== +import {C as C} from "A"; +contract D { + function g() external { + assembly { + tstore(0, 0) + tstore(0, 1) + } + } +} +==== Source: C ==== +contract X { + function h() external { + assembly { + tstore(0, 0) + tstore(0, 0) + } + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// Warning 2394: (A:72-78): Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. From 7115a63f2d4e159d41a5c517472af92e219d85f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mati=C4=87?= Date: Wed, 13 Mar 2024 20:09:52 +0100 Subject: [PATCH 0014/1340] Update release checklist (#14812) --- ReleaseChecklist.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 167417a95..5db731cfc 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -50,7 +50,7 @@ At least a day before the release: ### Create the Release - [ ] Create a [release on GitHub](https://github.com/ethereum/solidity/releases/new). Set the target to the ``develop`` branch and the tag to the new version, e.g. ``v0.8.5``. - Include the following warning: ``**The release is still in progress and the binaries may not yet be available from all sources.**``. + Include the following warning: ``**The release is still in progress. You may see broken links and binaries may not yet be available from all sources.**``. Do not publish it yet - click the ``Save draft`` button instead. - [ ] Thank voluntary contributors in the GitHub release notes. Use ``scripts/list_contributors.sh v`` to get initial list of names. @@ -68,6 +68,7 @@ At least a day before the release: - [ ] Take the ``github-binaries.tar`` tarball from ``c_release_binaries`` run of the tagged commit in circle-ci and add all binaries from it to the release page. Make sure it contains four binaries: ``solc-windows.exe``, ``solc-macos``, ``solc-static-linux`` and ``soljson.js``. - [ ] Take the ``solc-bin-binaries.tar`` tarball from ``c_release_binaries`` run of the tagged commit in circle-ci and add all binaries from it to solc-bin. + - [ ] Run ``npm install`` if you've got a clean checkout of the solc-bin repo. - [ ] Run ``npm run update -- --reuse-hashes`` in ``solc-bin`` and verify that the script has updated ``list.js``, ``list.txt`` and ``list.json`` files correctly and that symlinks to the new release have been added in ``solc-bin/wasm/`` and ``solc-bin/emscripten-wasm32/``. - [ ] Create a pull request in solc-bin and merge. From a15da0a70f3a06822f9a07f0d991bf8250acfa53 Mon Sep 17 00:00:00 2001 From: Vishwa Mehta Date: Wed, 24 Jan 2024 18:49:14 +0530 Subject: [PATCH 0015/1340] Clean up docs to reflect changes in the behaviour of SELFDESTRUCT as per EIP-6780 --- docs/cheatsheet.rst | 2 +- docs/contracts/function-modifiers.rst | 16 +-- docs/contracts/inheritance.rst | 133 +++++++++++++++-------- docs/examples/micropayment.rst | 101 ++++++++++++----- docs/introduction-to-smart-contracts.rst | 20 +++- docs/metadata.rst | 4 +- docs/style-guide.rst | 9 +- docs/units-and-global-variables.rst | 20 +++- docs/using-the-compiler.rst | 4 +- 9 files changed, 207 insertions(+), 102 deletions(-) diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index e4f7beabd..bc678c647 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -118,7 +118,7 @@ Contract-related - ``this`` (current contract's type): the current contract, explicitly convertible to ``address`` or ``address payable`` - ``super``: a contract one level higher in the inheritance hierarchy -- ``selfdestruct(address payable recipient)``: destroy the current contract, sending its funds to the given address +- ``selfdestruct(address payable recipient)``: send all funds to the given address and (only on EVMs before Cancun or when invoked within the transaction creating the contract) destroy the contract. .. index:: type;name, type;creationCode, type;runtimeCode, type;interfaceId, type;min, type;max diff --git a/docs/contracts/function-modifiers.rst b/docs/contracts/function-modifiers.rst index 454e12ab6..2fd0357db 100644 --- a/docs/contracts/function-modifiers.rst +++ b/docs/contracts/function-modifiers.rst @@ -19,7 +19,6 @@ if they are marked ``virtual``. For details, please see // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.1 <0.9.0; - // This will report a warning due to deprecated selfdestruct contract owned { constructor() { owner = payable(msg.sender); } @@ -41,16 +40,6 @@ if they are marked ``virtual``. For details, please see } } - contract destructible is owned { - // This contract inherits the `onlyOwner` modifier from - // `owned` and applies it to the `destroy` function, which - // causes that calls to `destroy` only have an effect if - // they are made by the stored owner. - function destroy() public onlyOwner { - selfdestruct(owner); - } - } - contract priced { // Modifiers can receive arguments: modifier costs(uint price) { @@ -60,7 +49,7 @@ if they are marked ``virtual``. For details, please see } } - contract Register is priced, destructible { + contract Register is priced, owned { mapping(address => bool) registeredAddresses; uint price; @@ -73,6 +62,9 @@ if they are marked ``virtual``. For details, please see registeredAddresses[msg.sender] = true; } + // This contract inherits the `onlyOwner` modifier from + // the `owned` contract. As a result, calls to `changePrice` will + // only take effect if they are made by the stored owner. function changePrice(uint price_) public onlyOwner { price = price_; } diff --git a/docs/contracts/inheritance.rst b/docs/contracts/inheritance.rst index 02ab19163..fccfee609 100644 --- a/docs/contracts/inheritance.rst +++ b/docs/contracts/inheritance.rst @@ -40,27 +40,27 @@ Details are given in the following example. // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct contract Owned { - constructor() { owner = payable(msg.sender); } address payable owner; + constructor() { owner = payable(msg.sender); } } - // Use `is` to derive from another contract. Derived // contracts can access all non-private members including // internal functions and state variables. These cannot be // accessed externally via `this`, though. - contract Destructible is Owned { + contract Emittable is Owned { + event Emitted(); + // The keyword `virtual` means that the function can change // its behavior in derived classes ("overriding"). - function destroy() virtual public { - if (msg.sender == owner) selfdestruct(owner); + function emitEvent() virtual public { + if (msg.sender == owner) + emit Emitted(); } } - // These abstract contracts are only provided to make the // interface known to the compiler. Note the function // without body. If a contract does not implement all @@ -69,37 +69,35 @@ Details are given in the following example. function lookup(uint id) public virtual returns (address adr); } - abstract contract NameReg { function register(bytes32 name) public virtual; function unregister() public virtual; } - // Multiple inheritance is possible. Note that `Owned` is - // also a base class of `Destructible`, yet there is only a single + // also a base class of `Emittable`, yet there is only a single // instance of `Owned` (as for virtual inheritance in C++). - contract Named is Owned, Destructible { + contract Named is Owned, Emittable { constructor(bytes32 name) { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).register(name); } // Functions can be overridden by another function with the same name and - // the same number/types of inputs. If the overriding function has different + // the same number/types of inputs. If the overriding function has different // types of output parameters, that causes an error. // Both local and message-based function calls take these overrides // into account. // If you want the function to override, you need to use the // `override` keyword. You need to specify the `virtual` keyword again // if you want this function to be overridden again. - function destroy() public virtual override { + function emitEvent() public virtual override { if (msg.sender == owner) { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).unregister(); // It is still possible to call a specific // overridden function. - Destructible.destroy(); + Emittable.emitEvent(); } } } @@ -108,93 +106,132 @@ Details are given in the following example. // If a constructor takes an argument, it needs to be // provided in the header or modifier-invocation-style at // the constructor of the derived contract (see below). - contract PriceFeed is Owned, Destructible, Named("GoldFeed") { + contract PriceFeed is Owned, Emittable, Named("GoldFeed") { + uint info; + function updateInfo(uint newInfo) public { if (msg.sender == owner) info = newInfo; } // Here, we only specify `override` and not `virtual`. // This means that contracts deriving from `PriceFeed` - // cannot change the behavior of `destroy` anymore. - function destroy() public override(Destructible, Named) { Named.destroy(); } + // cannot change the behavior of `emitEvent` anymore. + function emitEvent() public override(Emittable, Named) { Named.emitEvent(); } function get() public view returns(uint r) { return info; } - - uint info; } -Note that above, we call ``Destructible.destroy()`` to "forward" the -destruction request. The way this is done is problematic, as +Note that above, we call ``Emittable.emitEvent()`` to "forward" the +emit event request. The way this is done is problematic, as seen in the following example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract owned { - constructor() { owner = payable(msg.sender); } + contract Owned { address payable owner; + constructor() { owner = payable(msg.sender); } } - contract Destructible is owned { - function destroy() public virtual { - if (msg.sender == owner) selfdestruct(owner); + contract Emittable is Owned { + event Emitted(); + + function emitEvent() virtual public { + if (msg.sender == owner) { + emit Emitted(); + } } } - contract Base1 is Destructible { - function destroy() public virtual override { /* do cleanup 1 */ Destructible.destroy(); } + contract Base1 is Emittable { + event Base1Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base1 logic */ + emit Base1Emitted(); + Emittable.emitEvent(); + } } - contract Base2 is Destructible { - function destroy() public virtual override { /* do cleanup 2 */ Destructible.destroy(); } + contract Base2 is Emittable { + event Base2Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base2 logic */ + emit Base2Emitted(); + Emittable.emitEvent(); + } } contract Final is Base1, Base2 { - function destroy() public override(Base1, Base2) { Base2.destroy(); } + event FinalEmitted(); + function emitEvent() public override(Base1, Base2) { + /* Here, we emit an event to simulate some Final logic */ + emit FinalEmitted(); + Base2.emitEvent(); + } } -A call to ``Final.destroy()`` will call ``Base2.destroy`` because we specify it +A call to ``Final.emitEvent()`` will call ``Base2.emitEvent`` because we specify it explicitly in the final override, but this function will bypass -``Base1.destroy``. The way around this is to use ``super``: +``Base1.emitEvent``, resulting in the following sequence of events: +``FinalEmitted -> Base2Emitted -> Emitted``, instead of the expected sequence: +``FinalEmitted -> Base2Emitted -> Base1Emitted -> Emitted``. +The way around this is to use ``super``: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract owned { - constructor() { owner = payable(msg.sender); } + contract Owned { address payable owner; + constructor() { owner = payable(msg.sender); } } - contract Destructible is owned { - function destroy() virtual public { - if (msg.sender == owner) selfdestruct(owner); + contract Emittable is Owned { + event Emitted(); + + function emitEvent() virtual public { + if (msg.sender == owner) { + emit Emitted(); + } } } - contract Base1 is Destructible { - function destroy() public virtual override { /* do cleanup 1 */ super.destroy(); } + contract Base1 is Emittable { + event Base1Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base1 logic */ + emit Base1Emitted(); + super.emitEvent(); + } } - contract Base2 is Destructible { - function destroy() public virtual override { /* do cleanup 2 */ super.destroy(); } + contract Base2 is Emittable { + event Base2Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base2 logic */ + emit Base2Emitted(); + super.emitEvent(); + } } contract Final is Base1, Base2 { - function destroy() public override(Base1, Base2) { super.destroy(); } + event FinalEmitted(); + function emitEvent() public override(Base1, Base2) { + /* Here, we emit an event to simulate some Final logic */ + emit FinalEmitted(); + super.emitEvent(); + } } -If ``Base2`` calls a function of ``super``, it does not simply +If ``Final`` calls a function of ``super``, it does not simply call this function on one of its base contracts. Rather, it calls this function on the next base contract in the final -inheritance graph, so it will call ``Base1.destroy()`` (note that +inheritance graph, so it will call ``Base1.emitEvent()`` (note that the final inheritance sequence is -- starting with the most -derived contract: Final, Base2, Base1, Destructible, owned). +derived contract: Final, Base2, Base1, Emittable, Owned). The actual function that is called when using super is not known in the context of the class where it is used, although its type is known. This is similar for ordinary diff --git a/docs/examples/micropayment.rst b/docs/examples/micropayment.rst index 50f28005b..c3aef0d65 100644 --- a/docs/examples/micropayment.rst +++ b/docs/examples/micropayment.rst @@ -55,7 +55,7 @@ as it provides a number of other security benefits. What to Sign ------------ -For a contract that fulfils payments, the signed message must include: +For a contract that fulfills payments, the signed message must include: 1. The recipient's address. 2. The amount to be transferred. @@ -80,6 +80,10 @@ the contract's address itself will be accepted. You can find an example of this in the first two lines of the ``claimPayment()`` function of the full contract at the end of this section. +Furthermore, instead of destroying the contract by calling ``selfdestruct``, +which is currently deprecated, we will disable the contract's functionalities by freezing it, +resulting in the reversion of any call after it being frozen. + Packing arguments ----------------- @@ -144,30 +148,54 @@ The full contract // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract ReceiverPays { - address owner = msg.sender; + contract Owned { + address payable owner; + constructor() { + owner = payable(msg.sender); + } + } + + contract Freezable is Owned { + bool private _frozen = false; + + modifier notFrozen() { + require(!_frozen, "Inactive Contract."); + _; + } + + function freeze() internal { + if (msg.sender == owner) + _frozen = true; + } + } + + contract ReceiverPays is Freezable { mapping(uint256 => bool) usedNonces; constructor() payable {} - function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) external { + function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) + external + notFrozen + { require(!usedNonces[nonce]); usedNonces[nonce] = true; // this recreates the message that was signed on the client bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender, amount, nonce, this))); - require(recoverSigner(message, signature) == owner); - payable(msg.sender).transfer(amount); } - /// destroy the contract and reclaim the leftover funds. - function shutdown() external { + /// freeze the contract and reclaim the leftover funds. + function shutdown() + external + notFrozen + { require(msg.sender == owner); - selfdestruct(payable(msg.sender)); + freeze(); + payable(msg.sender).transfer(address(this).balance); } /// signature methods. @@ -196,7 +224,6 @@ The full contract returns (address) { (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); - return ecrecover(message, v, r, s); } @@ -305,7 +332,7 @@ Closing the Payment Channel When Bob is ready to receive his funds, it is time to close the payment channel by calling a ``close`` function on the smart contract. Closing the channel pays the recipient the Ether they are owed and -destroys the contract, sending any remaining Ether back to Alice. To +deactivates the contract by freezing it, sending any remaining Ether back to Alice. To close the channel, Bob needs to provide a message signed by Alice. The smart contract must verify that the message contains a valid signature from the sender. @@ -320,7 +347,7 @@ they could provide a message with a lower amount and cheat the recipient out of The function verifies the signed message matches the given parameters. If everything checks out, the recipient is sent their portion of the Ether, -and the sender is sent the rest via a ``selfdestruct``. +and the sender is sent the remaining funds via a ``transfer``. You can see the ``close`` function in the full contract. Channel Expiration @@ -342,11 +369,24 @@ The full contract // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract SimplePaymentChannel { - address payable public sender; // The account sending payments. - address payable public recipient; // The account receiving the payments. - uint256 public expiration; // Timeout in case the recipient never closes. + + contract Frozeable { + bool private _frozen = false; + + modifier notFrozen() { + require(!_frozen, "Inactive Contract."); + _; + } + + function freeze() internal { + _frozen = true; + } + } + + contract SimplePaymentChannel is Frozeable { + address payable public sender; // The account sending payments. + address payable public recipient; // The account receiving the payments. + uint256 public expiration; // Timeout in case the recipient never closes. constructor (address payable recipientAddress, uint256 duration) payable @@ -359,16 +399,23 @@ The full contract /// the recipient can close the channel at any time by presenting a /// signed amount from the sender. the recipient will be sent that amount, /// and the remainder will go back to the sender - function close(uint256 amount, bytes memory signature) external { + function close(uint256 amount, bytes memory signature) + external + notFrozen + { require(msg.sender == recipient); require(isValidSignature(amount, signature)); recipient.transfer(amount); - selfdestruct(sender); + freeze(); + sender.transfer(address(this).balance); } /// the sender can extend the expiration at any time - function extend(uint256 newExpiration) external { + function extend(uint256 newExpiration) + external + notFrozen + { require(msg.sender == sender); require(newExpiration > expiration); @@ -377,9 +424,13 @@ The full contract /// if the timeout is reached without the recipient closing the channel, /// then the Ether is released back to the sender. - function claimTimeout() external { + function claimTimeout() + external + notFrozen + { require(block.timestamp >= expiration); - selfdestruct(sender); + freeze(); + sender.transfer(address(this).balance); } function isValidSignature(uint256 amount, bytes memory signature) @@ -388,14 +439,12 @@ The full contract returns (bool) { bytes32 message = prefixed(keccak256(abi.encodePacked(this, amount))); - // check that the signature is from the payment sender return recoverSigner(message, signature) == sender; } /// All functions below this are just taken from the chapter /// 'creating and verifying signatures' chapter. - function splitSignature(bytes memory sig) internal pure @@ -411,7 +460,6 @@ The full contract // final byte (first byte of the next 32 bytes) v := byte(0, mload(add(sig, 96))) } - return (v, r, s); } @@ -421,7 +469,6 @@ The full contract returns (address) { (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); - return ecrecover(message, v, r, s); } diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 3c43e5f19..a31b06616 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -563,9 +563,23 @@ idea, but it is potentially dangerous, as if someone sends Ether to removed contracts, the Ether is forever lost. .. warning:: - From version 0.8.18 and up, the use of ``selfdestruct`` in both Solidity and Yul will trigger a - deprecation warning, since the ``SELFDESTRUCT`` opcode will eventually undergo breaking changes in behavior - as stated in `EIP-6049 `_. + From ``EVM >= Cancun`` onwards, ``selfdestruct`` will **only** send all Ether in the account to the given recipient and not destroy the contract. + However, when ``selfdestruct`` is called in the same transaction that creates the contract calling it, + the behaviour of ``selfdestruct`` before Cancun hardfork (i.e., ``EVM <= Shanghai``) is preserved and will destroy the current contract, + deleting any data, including storage keys, code and the account itself. + See `EIP-6780 `_ for more details. + + The new behaviour is the result of a network-wide change that affects all contracts present on + the Ethereum mainnet and testnets. + It is important to note that this change is dependent on the EVM version of the chain on which + the contract is deployed. + The ``--evm-version`` setting used when compiling the contract has no bearing on it. + + Also, note that the ``selfdestruct`` opcode has been deprecated in Solidity version 0.8.18, + as recommended by `EIP-6049 `_. + The deprecation is still in effect and the compiler will still emit warnings on its use. + Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. + Future changes to the EVM might further reduce the functionality of the opcode. .. warning:: Even if a contract is removed by ``selfdestruct``, it is still part of the diff --git a/docs/metadata.rst b/docs/metadata.rst index ede16a73f..a44d98753 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -175,9 +175,9 @@ explanatory purposes. }, // Required: Compilation source files/source units, keys are file paths "sources": { - "destructible": { + "settable": { // Required (unless "url" is used): literal contents of the source file - "content": "contract destructible is owned { function destroy() { if (msg.sender == owner) selfdestruct(owner); } }", + "content": "contract settable is owned { uint256 private x = 0; function set(uint256 _x) public { if (msg.sender == owner) x = _x; } }", // Required: keccak256 hash of the source file "keccak256": "0x234..." }, diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 427ede5ee..0ac890cb3 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -662,10 +662,11 @@ Yes: return balanceOf[from]; } - function shutdown() public onlyOwner { - selfdestruct(owner); + function increment(uint x) public onlyOwner pure returns (uint) { + return x + 1; } + No: .. code-block:: solidity @@ -674,8 +675,8 @@ No: return balanceOf[from]; } - function shutdown() onlyOwner public { - selfdestruct(owner); + function increment(uint x) onlyOwner public pure returns (uint) { + return x + 1; } For long function declarations, it is recommended to drop each argument onto diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index a0422c32d..a743441d5 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -339,9 +339,23 @@ Contract-related Furthermore, all functions of the current contract are callable directly including the current function. .. warning:: - From version 0.8.18 and up, the use of ``selfdestruct`` in both Solidity and Yul will trigger a - deprecation warning, since the ``SELFDESTRUCT`` opcode will eventually undergo breaking changes in behavior - as stated in `EIP-6049 `_. + From ``EVM >= Cancun`` onwards, ``selfdestruct`` will **only** send all Ether in the account to the given recipient and not destroy the contract. + However, when ``selfdestruct`` is called in the same transaction that creates the contract calling it, + the behaviour of ``selfdestruct`` before Cancun hardfork (i.e., ``EVM <= Shanghai``) is preserved and will destroy the current contract, + deleting any data, including storage keys, code and the account itself. + See `EIP-6780 `_ for more details. + + The new behaviour is the result of a network-wide change that affects all contracts present on + the Ethereum mainnet and testnets. + It is important to note that this change is dependent on the EVM version of the chain on which + the contract is deployed. + The ``--evm-version`` setting used when compiling the contract has no bearing on it. + + Also, note that the ``selfdestruct`` opcode has been deprecated in Solidity version 0.8.18, + as recommended by `EIP-6049 `_. + The deprecation is still in effect and the compiler will still emit warnings on its use. + Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. + Future changes to the EVM might further reduce the functionality of the opcode. .. note:: Prior to version 0.5.0, there was a function called ``suicide`` with the same diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 97abbdba9..219c2f42e 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -236,12 +236,12 @@ Input Description // `--allow-paths `. ] }, - "destructible": + "settable": { // Optional: keccak256 hash of the source file "keccak256": "0x234...", // Required (unless "urls" is used): literal contents of the source file - "content": "contract destructible is owned { function shutdown() { if (msg.sender == owner) selfdestruct(owner); } }" + "content": "contract settable is owned { uint256 private x = 0; function set(uint256 _x) public { if (msg.sender == owner) x = _x; } }" }, "myFile.sol_json.ast": { From a547f615c271dc357e753abb5c95c24b9d3d0e0b Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 13 Mar 2024 22:31:14 +0100 Subject: [PATCH 0016/1340] Disable gp2 and zeppelin ext tests --- .circleci/config.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e437e1d38..7fe8967b4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1910,7 +1910,8 @@ workflows: - t_ext: *job_ems_compile_ext_colony - t_ext: *job_native_compile_ext_gnosis - - t_ext: *job_native_test_ext_zeppelin + # TODO: Re-enable once bumped to use Cancun supported hardhat version + # - t_ext: *job_native_test_ext_zeppelin - t_ext: *job_native_test_ext_ens - t_ext: *job_native_test_ext_yield_liquidator - t_ext: *job_native_test_ext_perpetual_pools @@ -1918,7 +1919,8 @@ workflows: - t_ext: *job_native_test_ext_prb_math - t_ext: *job_native_test_ext_elementfi - t_ext: *job_native_test_ext_brink - - t_ext: *job_native_compile_ext_gp2 + # TODO: Re-enable once bumped to use Cancun supported hardhat version + # - t_ext: *job_native_compile_ext_gp2 - t_ext: *job_native_compile_ext_euler - t_ext: *job_native_compile_ext_pool_together # TODO: Dropping the external tests below since they are based on old forks and @@ -1932,14 +1934,16 @@ workflows: requires: - t_ems_compile_ext_colony - t_native_compile_ext_gnosis - - t_native_test_ext_zeppelin + # TODO: Re-enable once bumped to use Cancun supported hardhat version + # - t_native_test_ext_zeppelin - t_native_test_ext_ens - t_native_test_ext_yield_liquidator - t_native_test_ext_perpetual_pools - t_native_test_ext_uniswap - t_native_test_ext_elementfi - t_native_test_ext_brink - - t_native_compile_ext_gp2 + # TODO: Re-enable once bumped to use Cancun supported hardhat version + # - t_native_compile_ext_gp2 # TODO: Dropping prb-math from the benchmarks since it is not implemented yet # in the new Foundry external testing infrastructure. # - t_native_test_ext_prb_math From fbeef890ea61c1d07b716a90c5e7548cf791fba7 Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 13 Mar 2024 02:01:35 +0100 Subject: [PATCH 0017/1340] Set cancun hardfork in hardhat stack traces tests --- .circleci/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7fe8967b4..dc4cec201 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1469,6 +1469,9 @@ jobs: # NOTE: This is expected to work without running `pnpm build` first. cd hardhat/packages/hardhat-core + # TODO: temporarily set hardhat stack traces tests to use cancun hardfork + # Remove this when hardhat switch to cancun by default: https://github.com/NomicFoundation/hardhat/issues/4851 + sed -i 's/hardfork: "shanghai",/hardfork: "cancun",/' test/internal/hardhat-network/stack-traces/execution.ts pnpm test - matrix_notify_failure_unless_pr From a388ccb2c464493ecb62797462df6e9d9e6cf047 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 4 Mar 2024 15:25:05 -0300 Subject: [PATCH 0018/1340] Make cancun the default EVM version --- .circleci/soltest_all.sh | 2 +- Changelog.md | 1 + docs/using-the-compiler.rst | 8 +- liblangutil/EVMVersion.h | 2 +- libyul/AsmAnalysis.cpp | 9 +- scripts/error_codes.py | 1 - scripts/externalTests/common.sh | 2 +- scripts/externalTests/runners/base.py | 2 +- scripts/tests.sh | 2 +- .../debug_info_in_yul_snippet_escaping/output | 22 ++--- test/cmdlineTests/metadata/output | 2 +- test/cmdlineTests/name_simplifier/output | 10 +-- .../standard_metadata/output.json | 2 +- .../output.json | 2 +- .../viair_subobject_optimization/output | 82 +++++++------------ .../output | 2 +- .../yul_string_format_ascii/output.json | 6 +- .../yul_string_format_ascii_long/output.json | 6 +- test/libsolidity/StandardCompiler.cpp | 4 +- test/libsolidity/gasTests/abiv2.sol | 6 +- test/libsolidity/gasTests/abiv2_optimised.sol | 4 +- .../abi_encode_calldata_slice.sol | 12 +-- .../abi_encode_calldata_slice.sol | 12 +-- .../abiEncoderV2/abi_encode_v2.sol | 6 +- .../abiEncoderV2/calldata_array.sol | 2 +- .../calldata_overlapped_dynamic_arrays.sol | 6 +- .../abiEncoderV2/storage_array_encoding.sol | 12 +-- .../abi_decode_simple_storage.sol | 6 +- .../copying/bytes_storage_to_storage.sol | 30 +++---- .../copy_byte_array_in_struct_to_storage.sol | 12 +-- .../function_type_array_to_storage.sol | 12 +-- .../copying/storage_memory_nested_bytes.sol | 6 +- .../array/pop/byte_array_pop_masking_long.sol | 6 +- .../byte_array_to_storage_cleanup.sol | 12 +-- .../bytes_in_constructors_packer.sol | 12 +-- .../bytes_in_constructors_unpacker.sol | 12 +-- .../externalContracts/FixedFeeRegistrar.sol | 12 +-- .../externalContracts/base64.sol | 12 +-- .../externalContracts/deposit_contract.sol | 36 ++++---- .../externalContracts/strings.sol | 12 +-- .../external_call_to_nonexisting.sol | 12 +-- ...ernal_call_to_nonexisting_debugstrings.sol | 12 +-- .../inlineAssembly/blobhash_pre_cancun.sol | 2 +- .../transient_storage_low_level_calls.sol | 6 ++ .../transient_storage_selfdestruct.sol | 10 +++ .../tstore_hidden_staticcall.sol | 3 + .../salted_create/prediction_example.sol | 2 +- .../structs/copy_from_mapping.sol | 6 +- .../copy_substructures_from_mapping.sol | 6 +- .../structs/copy_substructures_to_mapping.sol | 18 ++-- .../semanticTests/structs/copy_to_mapping.sol | 24 +++--- .../semanticTests/various/address_code.sol | 12 +-- .../semanticTests/various/create_calldata.sol | 12 +-- .../various/selfdestruct_post_cancun.sol | 9 +- ...uct_post_cancun_multiple_beneficiaries.sol | 14 ++++ .../selfdestruct_post_cancun_redeploy.sol | 20 +++-- .../skip_dynamic_types_for_structs.sol | 6 +- .../blobhash_pre_cancun_not_declared.sol | 4 +- .../inlineAssembly/mcopy_pre_cancun.sol | 4 +- .../transient_storage_invalid_pre_cancun.sol | 6 +- .../types/magic_block_blobbasefee_error.sol | 2 +- 61 files changed, 298 insertions(+), 299 deletions(-) diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 40ee75b27..009852710 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -36,7 +36,7 @@ DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shang # set EVM_VALUES to the default values. IFS=" " read -ra EVM_VALUES <<< "${1:-${DEFAULT_EVM_VALUES[@]}}" -DEFAULT_EVM=shanghai +DEFAULT_EVM=cancun OPTIMIZE_VALUES=(0 1) # Run for ABI encoder v1, without SMTChecker tests. diff --git a/Changelog.md b/Changelog.md index 8c6df568e..ba5dff678 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Language Features: Compiler Features: * Code Generator: Use ``MCOPY`` instead of ``MLOAD``/``MSTORE`` loop when copying byte arrays. * Yul Analyzer: Emit transient storage warning only for the first occurrence of ``tstore``. + * EVM: Set default EVM version to ``cancun``. Bugfixes: diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 219c2f42e..875c15b09 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -174,9 +174,9 @@ at each version. Backward compatibility is not guaranteed between each version. - The block's base fee (`EIP-3198 `_ and `EIP-1559 `_) can be accessed via the global ``block.basefee`` or ``basefee()`` in inline assembly. - ``paris`` - Introduces ``prevrandao()`` and ``block.prevrandao``, and changes the semantics of the now deprecated ``block.difficulty``, disallowing ``difficulty()`` in inline assembly (see `EIP-4399 `_). -- ``shanghai`` (**default**) +- ``shanghai`` - Smaller code size and gas savings due to the introduction of ``push0`` (see `EIP-3855 `_). -- ``cancun`` +- ``cancun`` (**default**) - The block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) can be accessed via the global ``block.blobbasefee`` or ``blobbasefee()`` in inline assembly. - Introduces ``blobhash()`` in inline assembly and a corresponding global function to retrieve versioned hashes of blobs associated with the transaction (see `EIP-4844 `_). - Opcode ``mcopy`` is available in assembly (see `EIP-5656 `_). @@ -344,8 +344,8 @@ Input Description // Version of the EVM to compile for. // Affects type checking and code generation. Can be homestead, // tangerineWhistle, spuriousDragon, byzantium, constantinople, - // petersburg, istanbul, berlin, london, paris or shanghai (default) - "evmVersion": "shanghai", + // petersburg, istanbul, berlin, london, paris, shanghai or cancun (default) + "evmVersion": "cancun", // Optional: Change compilation pipeline to go through the Yul intermediate representation. // This is false by default. "viaIR": true, diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 992933a89..58b54f3dc 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -119,7 +119,7 @@ class EVMVersion: EVMVersion(Version _version): m_version(_version) {} - Version m_version = Version::Shanghai; + Version m_version = Version::Cancun; }; } diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 0efaa12c2..1972d2674 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -752,14 +752,11 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio else if (_instr == evmasm::Instruction::BLOBBASEFEE && !m_evmVersion.hasBlobBaseFee()) errorForVM(6679_error, "only available for Cancun-compatible"); else if (_instr == evmasm::Instruction::BLOBHASH && !m_evmVersion.hasBlobHash()) - // TODO: Change this assertion to an error, similar to the ones above, when Cancun becomes the default EVM version. - yulAssert(false); + errorForVM(8314_error, "only available for Cancun-compatible"); else if (_instr == evmasm::Instruction::MCOPY && !m_evmVersion.hasMcopy()) - // TODO: Change this assertion to an error, similar to the ones above, when Cancun becomes the default EVM version. - yulAssert(false); + errorForVM(7755_error, "only available for Cancun-compatible"); else if ((_instr == evmasm::Instruction::TSTORE || _instr == evmasm::Instruction::TLOAD) && !m_evmVersion.supportsTransientStorage()) - // TODO: Change this assertion to an error, similar to the ones above, when Cancun becomes the default EVM version. - yulAssert(false); + errorForVM(6243_error, "only available for Cancun-compatible"); else if (_instr == evmasm::Instruction::PC) m_errorReporter.error( 2450_error, diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 8ffb7f216..27e7b1102 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -202,7 +202,6 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "4591", # "There are more than 256 warnings. Ignoring the rest." # Due to 3805, the warning lists look different for different compiler builds. "1834", # Unimplemented feature error, as we do not test it anymore via cmdLineTests - "6679", # blobbasefee being used in inline assembly for EVMVersion < cancun "1180", # SMTChecker, covered by CL tests "2339", # SMTChecker, covered by CL tests "2961", # SMTChecker, covered by CL tests diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index de9b8da96..8bc9bdf7b 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -22,7 +22,7 @@ set -e # Requires $REPO_ROOT to be defined and "${REPO_ROOT}/scripts/common.sh" to be included before. -CURRENT_EVM_VERSION=shanghai +CURRENT_EVM_VERSION=cancun AVAILABLE_PRESETS=( legacy-no-optimize diff --git a/scripts/externalTests/runners/base.py b/scripts/externalTests/runners/base.py index c3807c528..cd94fab6b 100644 --- a/scripts/externalTests/runners/base.py +++ b/scripts/externalTests/runners/base.py @@ -41,7 +41,7 @@ from test_helpers import settings_from_preset from test_helpers import SettingsPreset -CURRENT_EVM_VERSION: str = "shanghai" +CURRENT_EVM_VERSION: str = "cancun" @dataclass class TestConfig: diff --git a/scripts/tests.sh b/scripts/tests.sh index 9df40e385..26eaf4b4b 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -115,7 +115,7 @@ do for vm in $EVM_VERSIONS do FORCE_ABIV1_RUNS="no" - if [[ "$vm" == "shanghai" ]] + if [[ "$vm" == "cancun" ]] then FORCE_ABIV1_RUNS="no yes" # run both in paris fi diff --git a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output index 4c90d9054..0bd6285b7 100644 --- a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output +++ b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output @@ -181,11 +181,7 @@ object "D_27" { function copy_memory_to_memory_with_cleanup(src, dst, length) { - let i := 0 - for { } lt(i, length) { i := add(i, 32) } - { - mstore(add(dst, i), mload(add(src, i))) - } + mcopy(dst, src, length) mstore(add(dst, length), 0) } @@ -470,8 +466,7 @@ object "D_27" { } mstore(_2, newFreePtr) mstore(memPtr, 2) - let _6 := 32 - mstore(add(memPtr, _6), "/*") + mstore(add(memPtr, 32), "/*") let memPtr_1 := mload(_2) let newFreePtr_1 := add(memPtr_1, 96) if or(gt(newFreePtr_1, /** @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." */ _5), /** @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." */ lt(newFreePtr_1, memPtr_1)) @@ -482,17 +477,14 @@ object "D_27" { } mstore(_2, newFreePtr_1) mstore(memPtr_1, 39) - mstore(add(memPtr_1, _6), 0x2f2a2a204073726320303a39363a313635202022636f6e74726163742044207b) + let _6 := add(memPtr_1, 32) + mstore(_6, 0x2f2a2a204073726320303a39363a313635202022636f6e74726163742044207b) mstore(add(memPtr_1, _2), shl(200, 0x2e2e2e22202a2f)) let memPos := mload(_2) - mstore(memPos, _6) + mstore(memPos, 32) let length := mload(memPtr_1) - mstore(add(memPos, _6), length) - let i := 0 - for { } lt(i, length) { i := add(i, _6) } - { - mstore(add(add(memPos, i), _2), mload(add(add(memPtr_1, i), _6))) - } + mstore(add(memPos, 32), length) + mcopy(add(memPos, _2), _6, length) mstore(add(add(memPos, length), _2), 0) return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), _2)) } diff --git a/test/cmdlineTests/metadata/output b/test/cmdlineTests/metadata/output index bf1e750c9..b6a684b84 100644 --- a/test/cmdlineTests/metadata/output +++ b/test/cmdlineTests/metadata/output @@ -1,4 +1,4 @@ ======= metadata/input.sol:C ======= Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"metadata/input.sol":"C"},"evmVersion":"shanghai","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"metadata/input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"metadata/input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"metadata/input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} diff --git a/test/cmdlineTests/name_simplifier/output b/test/cmdlineTests/name_simplifier/output index ed4c6e5c0..0a461e3e4 100644 --- a/test/cmdlineTests/name_simplifier/output +++ b/test/cmdlineTests/name_simplifier/output @@ -98,9 +98,9 @@ object "C_59" { } mstore(_9, newFreePtr_2) mstore(memPtr_1, 100) - mstore(add(memPtr_1, _3), "longstringlongstringlongstringlo") + let _11 := add(memPtr_1, _3) + mstore(_11, "longstringlongstringlongstringlo") mstore(add(memPtr_1, _9), "ngstringlongstringlongstringlong") - let _11 := 96 mstore(add(memPtr_1, 96), "stringlongstringlongstringlongst") mstore(add(memPtr_1, 128), "ring") let memPos := mload(_9) @@ -108,11 +108,7 @@ object "C_59" { mstore(add(memPos, _3), _9) let length := mload(memPtr_1) mstore(add(memPos, _9), length) - let i := 0 - for { } lt(i, length) { i := add(i, _3) } - { - mstore(add(add(memPos, i), _11), mload(add(add(memPtr_1, i), _3))) - } + mcopy(add(memPos, 96), _11, length) mstore(add(add(memPos, length), 96), 0) return(memPos, add(sub(add(memPos, and(add(length, 31), _8)), memPos), 96)) } diff --git a/test/cmdlineTests/standard_metadata/output.json b/test/cmdlineTests/standard_metadata/output.json index 442946667..955d30c34 100644 --- a/test/cmdlineTests/standard_metadata/output.json +++ b/test/cmdlineTests/standard_metadata/output.json @@ -5,7 +5,7 @@ { "C": { - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2\",\"dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS\"]}},\"version\":1}" + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2\",\"dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS\"]}},\"version\":1}" } } }, diff --git a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json index ac01fb1eb..aae6d02f6 100644 --- a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json +++ b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json @@ -40,7 +40,7 @@ "x()": "0c55699c" } }, - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x67a13ebd685e4c6f792e71eb747dac57edb99e94d04d841ee6c979ae517934ce\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://665b000da768823654f680d02686c1e59d682a0b3882e43a77fed9f80ce64ae8\",\"dweb:/ipfs/QmVnKvuidH6KiCdNQpoAQUtDbB8hXkafVLXWMNitUcxnqC\"]}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x67a13ebd685e4c6f792e71eb747dac57edb99e94d04d841ee6c979ae517934ce\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://665b000da768823654f680d02686c1e59d682a0b3882e43a77fed9f80ce64ae8\",\"dweb:/ipfs/QmVnKvuidH6KiCdNQpoAQUtDbB8hXkafVLXWMNitUcxnqC\"]}},\"version\":1}", "storageLayout": { "storage": [], diff --git a/test/cmdlineTests/viair_subobject_optimization/output b/test/cmdlineTests/viair_subobject_optimization/output index 4804d1384..5090c282b 100644 --- a/test/cmdlineTests/viair_subobject_optimization/output +++ b/test/cmdlineTests/viair_subobject_optimization/output @@ -117,77 +117,70 @@ sub_0: assembly { tag_3: jumpi(tag_7, callvalue) jumpi(tag_7, slt(add(not(0x03), calldatasize), 0x00)) - not(0x1f) /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ dataSize(sub_0) /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - 0x3f + swap1 + not(0x1f) + swap1 dup2 + 0x3f + dup5 add - dup3 and - dup4 + dup2 add - swap1 + swap2 + dup2 dup4 - dup3 lt 0xffffffffffffffff - dup4 + dup5 gt or tag_9 jumpi - swap3 - swap1 - 0x40 - swap1 0x40 + swap3 + dup4 mstore /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ dup4 dup3 mstore 0x20 + dup3 + add swap4 dataOffset(sub_0) - 0x20 - dup5 - add + dup6 codecopy /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - mload(0x40) + 0x1f + dup4 + mload + swap5 + dup6 swap4 - dup5 - swap3 /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ 0x20 /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - dup5 + dup6 mstore - dup1 mload - swap3 - dup4 + dup1 + swap2 + dup2 /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ 0x20 /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - dup7 + dup8 add mstore - 0x00 - tag_11: - dup5 - dup2 - lt - tag_12 - jumpi - dup6 - 0x40 - dup2 - dup10 - 0x1f - dup10 + dup7 + dup7 + add + mcopy 0x00 dup6 dup3 @@ -203,25 +196,6 @@ sub_0: assembly { add swap1 return - tag_12: - dup3 - dup2 - add - dup5 - add - mload - dup9 - dup3 - add - dup4 - add - mstore - dup8 - swap6 - pop - dup4 - add - jump(tag_11) tag_9: mstore(0x00, shl(0xe0, 0x4e487b71)) mstore(0x04, 0x41) diff --git a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output index 9ee681079..6873abe60 100644 --- a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output +++ b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output @@ -130,4 +130,4 @@ object "C_28" { } Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"foo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"yul_optimizer_steps_without_optimize_empty_sequence/input.sol":"C"},"evmVersion":"shanghai","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"yul_optimizer_steps_without_optimize_empty_sequence/input.sol":{"keccak256":"0x3fc910e345ce1ee62bfa6b0f66931ee632c08265b25b6139cfbbfe4d2f8d5dd8","license":"GPL-3.0","urls":["bzz-raw://e557e9ad2c2e420a669c06ae456b0b790d77d2d6d492cd8540e6b244388a5140","dweb:/ipfs/QmaNiZmC2Mo3YxGiehs1n3dVTjZwD7FguX7EUtpeshMVuR"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"foo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"yul_optimizer_steps_without_optimize_empty_sequence/input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"yul_optimizer_steps_without_optimize_empty_sequence/input.sol":{"keccak256":"0x3fc910e345ce1ee62bfa6b0f66931ee632c08265b25b6139cfbbfe4d2f8d5dd8","license":"GPL-3.0","urls":["bzz-raw://e557e9ad2c2e420a669c06ae456b0b790d77d2d6d492cd8540e6b244388a5140","dweb:/ipfs/QmaNiZmC2Mo3YxGiehs1n3dVTjZwD7FguX7EUtpeshMVuR"]}},"version":1} diff --git a/test/cmdlineTests/yul_string_format_ascii/output.json b/test/cmdlineTests/yul_string_format_ascii/output.json index 1a9612c77..edb76c0cd 100644 --- a/test/cmdlineTests/yul_string_format_ascii/output.json +++ b/test/cmdlineTests/yul_string_format_ascii/output.json @@ -97,11 +97,7 @@ object \"C_11\" { function copy_memory_to_memory_with_cleanup(src, dst, length) { - let i := 0 - for { } lt(i, length) { i := add(i, 32) } - { - mstore(add(dst, i), mload(add(src, i))) - } + mcopy(dst, src, length) mstore(add(dst, length), 0) } diff --git a/test/cmdlineTests/yul_string_format_ascii_long/output.json b/test/cmdlineTests/yul_string_format_ascii_long/output.json index 5adeabfdf..36d6cfd95 100644 --- a/test/cmdlineTests/yul_string_format_ascii_long/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_long/output.json @@ -97,11 +97,7 @@ object \"C_11\" { function copy_memory_to_memory_with_cleanup(src, dst, length) { - let i := 0 - for { } lt(i, length) { i := add(i, 32) } - { - mstore(add(dst, i), mload(add(src, i))) - } + mcopy(dst, src, length) mstore(add(dst, length), 0) } diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index ab013692d..7fafa2a62 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -1050,9 +1050,11 @@ BOOST_AUTO_TEST_CASE(evm_version) BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"paris\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"shanghai\",")); BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"shanghai\"") != std::string::npos); + result = compile(inputForVersion("\"evmVersion\": \"cancun\",")); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"cancun\"") != std::string::npos); // test default result = compile(inputForVersion("")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"shanghai\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"cancun\"") != std::string::npos); // test invalid result = compile(inputForVersion("\"evmVersion\": \"invalid\",")); BOOST_CHECK(result["errors"][0]["message"].asString() == "Invalid EVM version requested."); diff --git a/test/libsolidity/gasTests/abiv2.sol b/test/libsolidity/gasTests/abiv2.sol index aacb333bf..6fa822fad 100644 --- a/test/libsolidity/gasTests/abiv2.sol +++ b/test/libsolidity/gasTests/abiv2.sol @@ -14,9 +14,9 @@ contract C { } // ---- // creation: -// codeDepositCost: 1213200 -// executionCost: 1259 -// totalCost: 1214459 +// codeDepositCost: 1208000 +// executionCost: 1252 +// totalCost: 1209252 // external: // a(): 2425 // b(uint256): infinite diff --git a/test/libsolidity/gasTests/abiv2_optimised.sol b/test/libsolidity/gasTests/abiv2_optimised.sol index 1ab8803d2..8f407e6ed 100644 --- a/test/libsolidity/gasTests/abiv2_optimised.sol +++ b/test/libsolidity/gasTests/abiv2_optimised.sol @@ -17,9 +17,9 @@ contract C { // optimize-yul: true // ---- // creation: -// codeDepositCost: 639000 +// codeDepositCost: 634600 // executionCost: 668 -// totalCost: 639668 +// totalCost: 635268 // external: // a(): 2283 // b(uint256): 4649 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol index f548c50bc..3dd5dd269 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol @@ -59,10 +59,10 @@ contract C { // EVMVersion: >homestead // ---- // test_bytes() -> -// gas irOptimized: 321332 -// gas legacy: 319111 -// gas legacyOptimized: 269317 +// gas irOptimized: 306908 +// gas legacy: 305827 +// gas legacyOptimized: 255013 // test_uint256() -> -// gas irOptimized: 447646 -// gas legacy: 433627 -// gas legacyOptimized: 365410 +// gas irOptimized: 435054 +// gas legacy: 421315 +// gas legacyOptimized: 352838 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol index 686164de8..5457e7f67 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol @@ -60,10 +60,10 @@ contract C { // EVMVersion: >homestead // ---- // test_bytes() -> -// gas irOptimized: 321332 -// gas legacy: 319111 -// gas legacyOptimized: 269317 +// gas irOptimized: 306908 +// gas legacy: 305827 +// gas legacyOptimized: 255013 // test_uint256() -> -// gas irOptimized: 447646 -// gas legacy: 433627 -// gas legacyOptimized: 365410 +// gas irOptimized: 435054 +// gas legacy: 421315 +// gas legacyOptimized: 352838 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol index 5e50d5e9a..c0d5f5d3f 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol @@ -50,6 +50,6 @@ contract C { // f2() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f3() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f4() -> 0x20, 0x160, 0x1, 0x80, 0xc0, 0x2, 0x3, "abc", 0x7, 0x40, 0x2, 0x2, 0x3 -// gas irOptimized: 112630 -// gas legacy: 114794 -// gas legacyOptimized: 112572 +// gas irOptimized: 111708 +// gas legacy: 113892 +// gas legacyOptimized: 111646 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol index 22aad6749..f749e403b 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol @@ -20,6 +20,6 @@ contract C { // f(uint256[][1]): 32, 32, 0 -> true // f(uint256[][1]): 32, 32, 1, 42 -> true // f(uint256[][1]): 32, 32, 8, 421, 422, 423, 424, 425, 426, 427, 428 -> true -// gas irOptimized: 120043 +// gas irOptimized: 117157 // gas legacy: 101568 // gas legacyOptimized: 119092 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol index a92336097..46df31333 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol @@ -33,8 +33,8 @@ contract C { // f_which(uint256[],uint256[2],uint256): 0x40, 1, 2, 1, 5, 6 -> 0x20, 0x40, 5, 2 // f_which(uint256[],uint256[2],uint256): 0x40, 1, 2, 1 -> FAILURE // f_storage(uint256[],uint256[2]): 0x20, 1, 2 -> 0x20, 0x60, 0x20, 1, 2 -// gas irOptimized: 111642 -// gas legacy: 112944 -// gas legacyOptimized: 112092 +// gas irOptimized: 111395 +// gas legacy: 112709 +// gas legacyOptimized: 111852 // f_storage(uint256[],uint256[2]): 0x40, 1, 2, 5, 6 -> 0x20, 0x80, 0x20, 2, 5, 6 // f_storage(uint256[],uint256[2]): 0x40, 1, 2, 5 -> FAILURE diff --git a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol index 330756753..14699df57 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol @@ -18,10 +18,10 @@ contract C { // EVMVersion: >homestead // ---- // h(uint256[2][]): 0x20, 3, 123, 124, 223, 224, 323, 324 -> 32, 256, 0x20, 3, 123, 124, 223, 224, 323, 324 -// gas irOptimized: 180720 -// gas legacy: 184830 -// gas legacyOptimized: 181493 +// gas irOptimized: 180103 +// gas legacy: 184235 +// gas legacyOptimized: 180873 // i(uint256[2][2]): 123, 124, 223, 224 -> 32, 128, 123, 124, 223, 224 -// gas irOptimized: 112425 -// gas legacy: 115398 -// gas legacyOptimized: 112982 +// gas irOptimized: 112104 +// gas legacy: 115091 +// gas legacyOptimized: 112666 diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol index c06d2b24c..9f59c4315 100644 --- a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol @@ -8,6 +8,6 @@ contract C { } // ---- // f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg" -// gas irOptimized: 135661 -// gas legacy: 137278 -// gas legacyOptimized: 136048 +// gas irOptimized: 135452 +// gas legacy: 137096 +// gas legacyOptimized: 135834 diff --git a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol index 38dbe52bc..24565b4c6 100644 --- a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol @@ -17,25 +17,25 @@ contract c { // ---- // f(uint256): 0 -> 0x20, 0x00 // f(uint256): 31 -> 0x20, 0x1f, 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e00 -// gas irOptimized: 104476 -// gas legacy: 112974 -// gas legacyOptimized: 112717 +// gas irOptimized: 103283 +// gas legacy: 112883 +// gas legacyOptimized: 112629 // f(uint256): 32 -> 0x20, 0x20, 1780731860627700044960722568376592200742329637303199754547598369979440671 -// gas irOptimized: 118962 -// gas legacy: 129034 -// gas legacyOptimized: 128952 +// gas irOptimized: 117740 +// gas legacy: 128943 +// gas legacyOptimized: 128864 // f(uint256): 33 -> 0x20, 33, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x2000000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 125419 -// gas legacy: 136234 -// gas legacyOptimized: 135643 +// gas irOptimized: 124080 +// gas legacy: 136071 +// gas legacyOptimized: 135479 // f(uint256): 63 -> 0x20, 0x3f, 1780731860627700044960722568376592200742329637303199754547598369979440671, 14532552714582660066924456880521368950258152170031413196862950297402215316992 -// gas irOptimized: 129529 -// gas legacy: 148834 -// gas legacyOptimized: 148873 +// gas irOptimized: 127140 +// gas legacy: 148671 +// gas legacyOptimized: 148709 // f(uint256): 12 -> 0x20, 0x0c, 0x0102030405060708090a0b0000000000000000000000000000000000000000 // gas legacy: 59345 // gas legacyOptimized: 57279 // f(uint256): 129 -> 0x20, 0x81, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f, 29063324697304692433803953038474361308315562010425523193971352996434451193439, 0x606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f, -57896044618658097711785492504343953926634992332820282019728792003956564819968 -// gas irOptimized: 421911 -// gas legacy: 459355 -// gas legacyOptimized: 461066 +// gas irOptimized: 416966 +// gas legacy: 458976 +// gas legacyOptimized: 460674 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol index 5482f615f..33a4c7045 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol @@ -35,12 +35,12 @@ contract C { } // ---- // f() -> 0x40, 0x80, 6, 0x6162636465660000000000000000000000000000000000000000000000000000, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000 -// gas irOptimized: 179750 -// gas legacy: 181001 -// gas legacyOptimized: 180018 +// gas irOptimized: 179420 +// gas legacy: 180675 +// gas legacyOptimized: 179700 // g() -> 0x40, 0xc0, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000, 0x11, 0x3132333435363738393233343536373839000000000000000000000000000000 -// gas irOptimized: 106679 -// gas legacy: 109720 -// gas legacyOptimized: 106932 +// gas irOptimized: 106349 +// gas legacy: 109394 +// gas legacyOptimized: 106614 // h() -> 0x40, 0x60, 0x00, 0x00 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol index 275a0fca1..56a415079 100644 --- a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol @@ -46,11 +46,11 @@ contract C { } // ---- // test() -> 0x20, 0x14, "[a called][b called]" -// gas irOptimized: 116645 -// gas legacy: 118936 -// gas legacyOptimized: 116975 +// gas irOptimized: 116546 +// gas legacy: 118845 +// gas legacyOptimized: 116887 // test2() -> 0x20, 0x14, "[b called][a called]" // test3() -> 0x20, 0x14, "[b called][a called]" -// gas irOptimized: 103246 -// gas legacy: 102745 -// gas legacyOptimized: 101669 +// gas irOptimized: 103147 +// gas legacy: 102654 +// gas legacyOptimized: 101581 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol index 211477c55..0e8cff97f 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol @@ -11,6 +11,6 @@ contract C { } // ---- // f() -> 0x20, 0x02, 0x40, 0x80, 3, 0x6162630000000000000000000000000000000000000000000000000000000000, 0x99, 44048183304486788312148433451363384677562265908331949128489393215789685032262, 32241931068525137014058842823026578386641954854143559838526554899205067598957, 49951309422467613961193228765530489307475214998374779756599339590522149884499, 0x54555658595a6162636465666768696a6b6c6d6e6f707172737475767778797a, 0x4142434445464748494a4b4c4d4e4f5051525354555658595a00000000000000 -// gas irOptimized: 202731 -// gas legacy: 204798 -// gas legacyOptimized: 203357 +// gas irOptimized: 202162 +// gas legacy: 204328 +// gas legacyOptimized: 202887 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol index 5b1a61839..674b0841e 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol @@ -9,6 +9,6 @@ contract c { } // ---- // test() -> 0x20, 33, 0x303030303030303030303030303030303030303030303030303030303030303, 0x0300000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 107343 -// gas legacy: 121408 -// gas legacyOptimized: 120534 +// gas irOptimized: 107183 +// gas legacy: 121245 +// gas legacyOptimized: 120370 diff --git a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol index 14130926e..8d0cb0a01 100644 --- a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol +++ b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol @@ -28,12 +28,12 @@ contract C { // compileViaYul: also // ---- // constructor() -> -// gas irOptimized: 82402 -// gas irOptimized code: 361000 -// gas legacy: 101895 -// gas legacy code: 609400 -// gas legacyOptimized: 85378 -// gas legacyOptimized code: 397000 +// gas irOptimized: 81932 +// gas irOptimized code: 355200 +// gas legacy: 101472 +// gas legacy code: 604200 +// gas legacyOptimized: 85004 +// gas legacyOptimized code: 392400 // h() -> 0x20, 0x40, 0x00, 0 // ~ emit ev(uint256[],uint256): 0x40, 0x21, 0x02, 0x00, 0x00 // g() -> 0x20, 0x40, 0, 0x00 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index 7885d3cee..c0b9df16c 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -24,9 +24,9 @@ contract Creator { } // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" -// gas irOptimized: 169902 -// gas irOptimized code: 105200 -// gas legacy: 173433 -// gas legacy code: 245000 -// gas legacyOptimized: 170360 -// gas legacyOptimized code: 121600 +// gas irOptimized: 169361 +// gas irOptimized code: 99200 +// gas legacy: 172944 +// gas legacy code: 239800 +// gas legacyOptimized: 169858 +// gas legacyOptimized code: 117000 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol index 1d6b01127..0918a970e 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol @@ -8,11 +8,11 @@ contract Test { } // ---- // constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> -// gas irOptimized: 182025 -// gas irOptimized code: 87200 -// gas legacy: 196220 -// gas legacy code: 114600 -// gas legacyOptimized: 182604 -// gas legacyOptimized code: 76000 +// gas irOptimized: 180756 +// gas irOptimized code: 79200 +// gas legacy: 195165 +// gas legacy code: 109400 +// gas legacyOptimized: 181600 +// gas legacyOptimized code: 71400 // m_x() -> 7 // m_s() -> 0x20, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index d308d4597..925ed54e6 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -74,12 +74,12 @@ contract FixedFeeRegistrar is Registrar { } // ---- // constructor() -// gas irOptimized: 78006 -// gas irOptimized code: 306600 -// gas legacy: 115817 -// gas legacy code: 797600 -// gas legacyOptimized: 84924 -// gas legacyOptimized code: 392000 +// gas irOptimized: 77654 +// gas irOptimized code: 302200 +// gas legacy: 115395 +// gas legacy code: 792400 +// gas legacyOptimized: 84566 +// gas legacyOptimized code: 387600 // reserve(string), 69 ether: 0x20, 3, "abc" -> // ~ emit Changed(string): #0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 // gas irOptimized: 45967 diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol index b712092ed..aed2a11df 100644 --- a/test/libsolidity/semanticTests/externalContracts/base64.sol +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -33,12 +33,12 @@ contract test { // EVMVersion: >=constantinople // ---- // constructor() -// gas irOptimized: 79428 -// gas irOptimized code: 326400 -// gas legacy: 102450 -// gas legacy code: 632600 -// gas legacyOptimized: 88318 -// gas legacyOptimized code: 434400 +// gas irOptimized: 78952 +// gas irOptimized code: 320600 +// gas legacy: 102034 +// gas legacy code: 627400 +// gas legacyOptimized: 87950 +// gas legacyOptimized code: 429800 // encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 // encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" // encode_inline_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8=" diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index 0ef87edd4..ce77683aa 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -176,38 +176,38 @@ contract DepositContract is IDepositContract, ERC165 { } // ---- // constructor() -// gas irOptimized: 815686 -// gas irOptimized code: 571200 -// gas legacy: 925933 -// gas legacy code: 1442800 -// gas legacyOptimized: 854404 -// gas legacyOptimized code: 885600 +// gas irOptimized: 809248 +// gas irOptimized code: 558000 +// gas legacy: 919945 +// gas legacy code: 1437600 +// gas legacyOptimized: 848464 +// gas legacyOptimized code: 875200 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # // supportsInterface(bytes4): 0x8564090700000000000000000000000000000000000000000000000000000000 -> true # the deposit interface id # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 115231 -// gas legacy: 148205 -// gas legacyOptimized: 122303 +// gas irOptimized: 109009 +// gas legacy: 142735 +// gas legacyOptimized: 117558 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 115231 -// gas legacy: 148205 -// gas legacyOptimized: 122303 +// gas irOptimized: 109009 +// gas legacy: 142735 +// gas legacyOptimized: 117558 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 // get_deposit_root() -> 0x2089653123d9c721215120b6db6738ba273bbc5228ac093b1f983badcdc8a438 -// gas irOptimized: 115216 -// gas legacy: 148214 -// gas legacyOptimized: 122315 +// gas irOptimized: 108994 +// gas legacy: 142744 +// gas legacyOptimized: 117570 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 // get_deposit_root() -> 0x40255975859377d912c53aa853245ebd939bdd2b33a28e084babdcc1ed8238ee -// gas irOptimized: 115216 -// gas legacy: 148214 -// gas legacyOptimized: 122315 +// gas irOptimized: 108994 +// gas legacy: 142744 +// gas legacyOptimized: 117570 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index a4b0f9fd3..102c85ae0 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -49,12 +49,12 @@ contract test { } // ---- // constructor() -// gas irOptimized: 96420 -// gas irOptimized code: 533800 -// gas legacy: 126553 -// gas legacy code: 935400 -// gas legacyOptimized: 102933 -// gas legacyOptimized code: 616000 +// gas irOptimized: 95949 +// gas irOptimized code: 528000 +// gas legacy: 126106 +// gas legacy code: 930200 +// gas legacyOptimized: 102559 +// gas legacyOptimized code: 611400 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22660 // gas legacy: 23190 diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol index 9d521f777..5b254a9f6 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol @@ -22,12 +22,12 @@ contract C { } // ---- // constructor(), 1 ether -> -// gas irOptimized: 89555 -// gas irOptimized code: 172800 -// gas legacy: 103042 -// gas legacy code: 338400 -// gas legacyOptimized: 91862 -// gas legacyOptimized code: 201000 +// gas irOptimized: 89155 +// gas irOptimized code: 167800 +// gas legacy: 102626 +// gas legacy code: 333200 +// gas legacyOptimized: 91471 +// gas legacyOptimized code: 196200 // f(uint256): 0 -> FAILURE // f(uint256): 1 -> FAILURE // f(uint256): 2 -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol index 9baacd812..8bf182a89 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol @@ -25,12 +25,12 @@ contract C { // revertStrings: debug // ---- // constructor(), 1 ether -> -// gas irOptimized: 99264 -// gas irOptimized code: 291200 -// gas legacy: 123585 -// gas legacy code: 686400 -// gas legacyOptimized: 107331 -// gas legacyOptimized code: 391000 +// gas irOptimized: 98842 +// gas irOptimized code: 286000 +// gas legacy: 123163 +// gas legacy code: 681200 +// gas legacyOptimized: 106957 +// gas legacyOptimized code: 386400 // f(uint256): 0 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 1 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 2 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" diff --git a/test/libsolidity/semanticTests/inlineAssembly/blobhash_pre_cancun.sol b/test/libsolidity/semanticTests/inlineAssembly/blobhash_pre_cancun.sol index 8972958e1..d3a41fc07 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/blobhash_pre_cancun.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/blobhash_pre_cancun.sol @@ -15,7 +15,7 @@ contract C { } } // ==== -// EVMVersion: <=shanghai +// EVMVersion: 1 // g() -> 1000 diff --git a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol index f3fe03844..e43fc4757 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol @@ -68,3 +68,9 @@ contract C { // testCall() -> true // tloadAllowedStaticCall() -> true // tstoreNotAllowedStaticCall() -> true +// gas irOptimized: 98419720 +// gas irOptimized code: 19000 +// gas legacy: 98409086 +// gas legacy code: 30000 +// gas legacyOptimized: 98420962 +// gas legacyOptimized code: 17800 diff --git a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol index 935435420..f4975cd4c 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol @@ -40,5 +40,15 @@ contract D { // EVMVersion: >=cancun // ---- // constructor() -> +// gas irOptimized: 127944 +// gas irOptimized code: 225200 +// gas legacy: 149357 +// gas legacy code: 499800 +// gas legacyOptimized: 125830 +// gas legacyOptimized code: 203200 // destroy() -> // createAndDestroy() -> +// gas legacy: 67044 +// gas legacy code: 92600 +// gas legacyOptimized: 65675 +// gas legacyOptimized code: 39400 diff --git a/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol b/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol index bdd9401ee..d64c7dfb5 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol @@ -18,3 +18,6 @@ contract C { // EVMVersion: >=cancun // ---- // test() -> FAILURE +// gas irOptimized: 98437877 +// gas legacy: 98437872 +// gas legacyOptimized: 98437873 diff --git a/test/libsolidity/semanticTests/salted_create/prediction_example.sol b/test/libsolidity/semanticTests/salted_create/prediction_example.sol index 6fa865440..751747293 100644 --- a/test/libsolidity/semanticTests/salted_create/prediction_example.sol +++ b/test/libsolidity/semanticTests/salted_create/prediction_example.sol @@ -26,5 +26,5 @@ contract C { // compileViaYul: also // ---- // createDSalted(bytes32,uint256): 42, 64 -> -// gas legacy: 79241 +// gas legacy: 78574 // gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/structs/copy_from_mapping.sol b/test/libsolidity/semanticTests/structs/copy_from_mapping.sol index 1d1783a16..8ee19a278 100644 --- a/test/libsolidity/semanticTests/structs/copy_from_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_from_mapping.sol @@ -36,8 +36,8 @@ contract C { } // ---- // to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121481 -// gas legacy: 123069 -// gas legacyOptimized: 121756 +// gas irOptimized: 121394 +// gas legacy: 122978 +// gas legacyOptimized: 121648 // to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol index a1b0999ff..9b0fa9207 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol @@ -44,8 +44,8 @@ contract C { } // ---- // to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121598 -// gas legacy: 123208 -// gas legacyOptimized: 121763 +// gas irOptimized: 121511 +// gas legacy: 123117 +// gas legacyOptimized: 121655 // to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol index b88466113..a0834ca5b 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol @@ -52,14 +52,14 @@ contract C { } // ---- // from_memory() -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 123039 -// gas legacy: 130227 -// gas legacyOptimized: 128758 +// gas irOptimized: 122952 +// gas legacy: 130136 +// gas legacyOptimized: 128650 // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121709 -// gas legacy: 123282 -// gas legacyOptimized: 121868 +// gas irOptimized: 121622 +// gas legacy: 123191 +// gas legacyOptimized: 121760 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 115130 -// gas legacy: 122516 -// gas legacyOptimized: 120804 +// gas irOptimized: 115043 +// gas legacy: 122425 +// gas legacyOptimized: 120696 diff --git a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol index e6b569922..033f0f518 100644 --- a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol @@ -45,18 +45,18 @@ contract C { } // ---- // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121686 -// gas legacy: 123144 -// gas legacyOptimized: 121808 +// gas irOptimized: 121599 +// gas legacy: 123053 +// gas legacyOptimized: 121700 // from_storage() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121731 -// gas legacy: 123193 -// gas legacyOptimized: 121860 +// gas irOptimized: 121644 +// gas legacy: 123102 +// gas legacyOptimized: 121752 // from_memory() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 122947 -// gas legacy: 130088 -// gas legacyOptimized: 128754 +// gas irOptimized: 122860 +// gas legacy: 129997 +// gas legacyOptimized: 128646 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 21, 3, 0x666f6f0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 115045 -// gas legacy: 118301 -// gas legacyOptimized: 115432 +// gas irOptimized: 114958 +// gas legacy: 118210 +// gas legacyOptimized: 115324 diff --git a/test/libsolidity/semanticTests/various/address_code.sol b/test/libsolidity/semanticTests/various/address_code.sol index 6a97c0bf7..f283aaeaa 100644 --- a/test/libsolidity/semanticTests/various/address_code.sol +++ b/test/libsolidity/semanticTests/various/address_code.sol @@ -14,12 +14,12 @@ contract C { } // ---- // constructor() -> -// gas irOptimized: 70873 -// gas irOptimized code: 102400 -// gas legacy: 82796 -// gas legacy code: 159000 -// gas legacyOptimized: 69870 -// gas legacyOptimized code: 83800 +// gas irOptimized: 70351 +// gas irOptimized code: 95800 +// gas legacy: 82380 +// gas legacy code: 153800 +// gas legacyOptimized: 69496 +// gas legacyOptimized code: 79200 // initCode() -> 0x20, 0 // f() -> true // g() -> 0 diff --git a/test/libsolidity/semanticTests/various/create_calldata.sol b/test/libsolidity/semanticTests/various/create_calldata.sol index 2db42adeb..b8ec25209 100644 --- a/test/libsolidity/semanticTests/various/create_calldata.sol +++ b/test/libsolidity/semanticTests/various/create_calldata.sol @@ -8,10 +8,10 @@ contract C { } // ---- // constructor(): 42 -> -// gas irOptimized: 68378 -// gas irOptimized code: 77200 -// gas legacy: 78445 -// gas legacy code: 95400 -// gas legacyOptimized: 68677 -// gas legacyOptimized code: 69200 +// gas irOptimized: 67834 +// gas irOptimized code: 70400 +// gas legacy: 78029 +// gas legacy code: 90200 +// gas legacyOptimized: 68321 +// gas legacyOptimized code: 64600 // s() -> 0x20, 0 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol index 85c95be44..263da7133 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol @@ -64,9 +64,12 @@ contract D { // EVMVersion: >=cancun // ---- // constructor(), 1 ether -> -// gas irOptimized: 455954 -// gas legacy: 375495 -// gas legacyOptimized: 507630 +// gas irOptimized: 67028 +// gas irOptimized code: 175400 +// gas legacy: 76163 +// gas legacy code: 297400 +// gas legacyOptimized: 66516 +// gas legacyOptimized code: 168000 // exists() -> false // test_create_and_terminate() -> // exists() -> false diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol index 4bc65b760..16797ee4c 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol @@ -35,16 +35,30 @@ contract D { // EVMVersion: >=cancun // ---- // constructor(), 2 ether -> +// gas irOptimized: 107718 +// gas irOptimized code: 116200 +// gas legacy: 120424 +// gas legacy code: 253600 +// gas legacyOptimized: 109015 +// gas legacyOptimized code: 130800 // balance: 0x1111111111111111111111111111111111111111 -> 0 // balance: 0x2222222222222222222222222222222222222222 -> 0 // balance -> 2000000000000000000 // exists() -> false // test_deploy_and_terminate_twice() -> +// gas irOptimized: 121350 +// gas irOptimized code: 14000 +// gas legacy: 122384 +// gas legacy code: 43200 +// gas legacyOptimized: 121596 +// gas legacyOptimized code: 22800 // exists() -> false // balance: 0x1111111111111111111111111111111111111111 -> 1000000000000000000 // balance: 0x2222222222222222222222222222222222222222 -> 0 // balance -> 1000000000000000000 // deploy() -> +// gas legacy: 58491 +// gas legacy code: 43200 // exists() -> true // balance: 0x1111111111111111111111111111111111111111 -> 1000000000000000000 // balance: 0x2222222222222222222222222222222222222222 -> 0 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol index 473571bf1..1b3022efe 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol @@ -82,14 +82,21 @@ contract D { // EVMVersion: >=cancun // ---- // constructor(), 1 ether -> -// gas irOptimized: 562058 -// gas legacy: 633310 -// gas legacyOptimized: 590051 +// gas irOptimized: 132874 +// gas irOptimized code: 292400 +// gas legacy: 151217 +// gas legacy code: 533400 +// gas legacyOptimized: 131436 +// gas legacyOptimized code: 276600 // exists() -> false // test_deploy_and_terminate() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 118541 -// gas legacyOptimized: 118305 +// gas irOptimized: 96394 +// gas irOptimized code: 20800 +// gas legacy: 97788 +// gas legacy code: 20800 +// gas legacyOptimized: 96044 +// gas legacyOptimized code: 20800 // exists() -> false // deploy_create2() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 @@ -99,3 +106,6 @@ contract D { // test_balance_after_selfdestruct() -> // exists() -> true // deploy_create2() -> FAILURE +// gas irOptimized: 96903654 +// gas legacy: 96903660 +// gas legacyOptimized: 96903641 diff --git a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol index ce8946c55..ef53a4e47 100644 --- a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol +++ b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol @@ -19,6 +19,6 @@ contract C { } // ---- // g() -> 2, 6 -// gas irOptimized: 178475 -// gas legacy: 180839 -// gas legacyOptimized: 179374 +// gas irOptimized: 178263 +// gas legacy: 180657 +// gas legacyOptimized: 179156 diff --git a/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_declared.sol b/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_declared.sol index c0284b330..8f58c77ce 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_declared.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_declared.sol @@ -6,7 +6,7 @@ contract C { } } // ==== -// EVMVersion: <=shanghai +// EVMVersion: =shanghai // ---- -// DeclarationError 4619: (106-114): Function "blobhash" not found. +// TypeError 8314: (106-114): The "blobhash" instruction is only available for Cancun-compatible VMs (you are currently compiling for "shanghai"). // DeclarationError 8678: (99-116): Variable count for assignment to "ret" does not match number of values (1 vs. 0) diff --git a/test/libsolidity/syntaxTests/inlineAssembly/mcopy_pre_cancun.sol b/test/libsolidity/syntaxTests/inlineAssembly/mcopy_pre_cancun.sol index 090e2f628..96be57894 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/mcopy_pre_cancun.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/mcopy_pre_cancun.sol @@ -6,6 +6,6 @@ contract C { } } // ==== -// EVMVersion: Date: Thu, 14 Mar 2024 07:40:36 +0100 Subject: [PATCH 0019/1340] Use specific hardhat version on openzeppelin and gp2 external tests (#14938) --- .circleci/config.yml | 12 ++++-------- test/externalTests/gp2.sh | 9 +++++++++ test/externalTests/zeppelin.sh | 6 ++++++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index dc4cec201..13f0c499f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1913,8 +1913,7 @@ workflows: - t_ext: *job_ems_compile_ext_colony - t_ext: *job_native_compile_ext_gnosis - # TODO: Re-enable once bumped to use Cancun supported hardhat version - # - t_ext: *job_native_test_ext_zeppelin + - t_ext: *job_native_test_ext_zeppelin - t_ext: *job_native_test_ext_ens - t_ext: *job_native_test_ext_yield_liquidator - t_ext: *job_native_test_ext_perpetual_pools @@ -1922,8 +1921,7 @@ workflows: - t_ext: *job_native_test_ext_prb_math - t_ext: *job_native_test_ext_elementfi - t_ext: *job_native_test_ext_brink - # TODO: Re-enable once bumped to use Cancun supported hardhat version - # - t_ext: *job_native_compile_ext_gp2 + - t_ext: *job_native_compile_ext_gp2 - t_ext: *job_native_compile_ext_euler - t_ext: *job_native_compile_ext_pool_together # TODO: Dropping the external tests below since they are based on old forks and @@ -1937,16 +1935,14 @@ workflows: requires: - t_ems_compile_ext_colony - t_native_compile_ext_gnosis - # TODO: Re-enable once bumped to use Cancun supported hardhat version - # - t_native_test_ext_zeppelin + - t_native_test_ext_zeppelin - t_native_test_ext_ens - t_native_test_ext_yield_liquidator - t_native_test_ext_perpetual_pools - t_native_test_ext_uniswap - t_native_test_ext_elementfi - t_native_test_ext_brink - # TODO: Re-enable once bumped to use Cancun supported hardhat version - # - t_native_compile_ext_gp2 + - t_native_compile_ext_gp2 # TODO: Dropping prb-math from the benchmarks since it is not implemented yet # in the new Foundry external testing infrastructure. # - t_native_test_ext_prb_math diff --git a/test/externalTests/gp2.sh b/test/externalTests/gp2.sh index af77f99aa..20ea586f5 100755 --- a/test/externalTests/gp2.sh +++ b/test/externalTests/gp2.sh @@ -66,6 +66,15 @@ function gp2_test force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" force_hardhat_unlimited_contract_size "$config_file" "$config_var" yarn + # We require to install hardhat 2.20.0 due to support for evm version cancun, otherwise we get the following error: + # Invalid value {"blockGasLimit":12500000,"hardfork":"cancun","allowUnlimitedContractSize":true} for HardhatConfig.networks.hardhat - Expected a value of type HardhatNetworkConfig. + # See: https://github.com/NomicFoundation/hardhat/issues/4176 + yarn add hardhat@2.20.0 + + # Ignore bench directory which fails to compile with current hardhat and ethers versions. + # bench/trace/gas.ts:123:19 - error TS2339: Property 'equals' does not exist on type 'Uint8Array'. + jq '. + {"exclude": ["bench"]}' tsconfig.json > temp.json + mv temp.json tsconfig.json # Remove the config section that requires an Etherscan key. We don't need it just to run tests. sed -i '/^ etherscan: {$/,/^ },$/d' hardhat.config.ts diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 655e4814f..64c901f61 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -95,6 +95,8 @@ function zeppelin_test sed -i "s|it(\('calling upgradeToAndCall on the implementation reverts'\)|it.skip(\1|g" test/proxy/utils/UUPSUpgradeable.test.js sed -i "s|it(\('calling upgradeTo from a contract that is not an ERC1967 proxy\)|it.skip(\1|g" test/proxy/utils/UUPSUpgradeable.test.js sed -i "s|it(\('calling upgradeToAndCall from a contract that is not an ERC1967 proxy\)|it.skip(\1|g" test/proxy/utils/UUPSUpgradeable.test.js + sed -i "s|it(\('rejects overflow'\)|it.skip(\1|g" test/token/ERC20/ERC20.test.js + sed -i "s|it(\('decimals overflow'\)|it.skip(\1|g" test/token/ERC20/extensions/ERC4626.test.js # Here only the testToInt(248) and testToInt(256) cases fail so change the loop range to skip them sed -i "s|range(8, 256, 8)\(.forEach(bits => testToInt(bits));\)|range(8, 240, 8)\1|" test/utils/math/SafeCast.test.js @@ -103,6 +105,10 @@ function zeppelin_test force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" npm install + # We require to install hardhat 2.20.0 due to support for evm version cancun, otherwise we get the following error: + # Invalid value {"blockGasLimit":10000000,"allowUnlimitedContractSize":true,"hardfork":"cancun"} for HardhatConfig.networks.hardhat - Expected a value of type HardhatNetworkConfig. + # See: https://github.com/NomicFoundation/hardhat/issues/4176 + npm install hardhat@2.20.0 replace_version_pragmas for preset in $SELECTED_PRESETS; do From b61c2a91b3a478bd53fb831b0e8811668bc0dd05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mati=C4=87?= Date: Thu, 14 Mar 2024 11:29:02 +0100 Subject: [PATCH 0020/1340] Sort changelog and add release date for 0.8.25 (#14939) --- Changelog.md | 7 ++----- docs/bugs_by_version.json | 4 ++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index ba5dff678..6a2e25fa2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,12 +1,9 @@ -### 0.8.25 (unreleased) - -Language Features: - +### 0.8.25 (2023-03-14) Compiler Features: * Code Generator: Use ``MCOPY`` instead of ``MLOAD``/``MSTORE`` loop when copying byte arrays. - * Yul Analyzer: Emit transient storage warning only for the first occurrence of ``tstore``. * EVM: Set default EVM version to ``cancun``. + * Yul Analyzer: Emit transient storage warning only for the first occurrence of ``tstore``. Bugfixes: diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 156b846d0..7022635fd 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1890,6 +1890,10 @@ "bugs": [], "released": "2024-01-25" }, + "0.8.25": { + "bugs": [], + "released": "2023-03-14" + }, "0.8.3": { "bugs": [ "FullInlinerNonExpressionSplitArgumentEvaluationOrder", From 4b748854d76b095ebec51c518ffca63b2494b123 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 14 Mar 2024 11:35:19 +0100 Subject: [PATCH 0021/1340] Set version to 0.8.26 --- CMakeLists.txt | 2 +- Changelog.md | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18af34d26..5e2a2b4a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.25") +set(PROJECT_VERSION "0.8.26") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index 6a2e25fa2..21a58478a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,14 @@ +### 0.8.26 (unreleased) + +Language Features: + + +Compiler Features: + + +Bugfixes: + + ### 0.8.25 (2023-03-14) Compiler Features: From 655a9d806ee7259658f47f3ff29f690cf175c13c Mon Sep 17 00:00:00 2001 From: Zuri Obozuwa Date: Fri, 15 Mar 2024 01:59:46 +0000 Subject: [PATCH 0022/1340] Fix passing of string input parameter to Enable method of DebugInfoSelection struct Use const ref to input string instead of incurring the cost of copying the input string --- liblangutil/DebugInfoSelection.cpp | 2 +- liblangutil/DebugInfoSelection.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/liblangutil/DebugInfoSelection.cpp b/liblangutil/DebugInfoSelection.cpp index 88e09cdb7..ad0b615c1 100644 --- a/liblangutil/DebugInfoSelection.cpp +++ b/liblangutil/DebugInfoSelection.cpp @@ -83,7 +83,7 @@ std::optional DebugInfoSelection::fromComponents( return selection; } -bool DebugInfoSelection::enable(std::string _component) +bool DebugInfoSelection::enable(std::string const& _component) { auto memberIt = componentMap().find(boost::trim_copy(_component)); if (memberIt == componentMap().end()) diff --git a/liblangutil/DebugInfoSelection.h b/liblangutil/DebugInfoSelection.h index 40ba3d6b2..3a9432de6 100644 --- a/liblangutil/DebugInfoSelection.h +++ b/liblangutil/DebugInfoSelection.h @@ -49,7 +49,7 @@ struct DebugInfoSelection std::vector const& _componentNames, bool _acceptWildcards = false ); - bool enable(std::string _component); + bool enable(std::string const& _component); bool all() const noexcept; bool any() const noexcept; From 905c8ae15217a2853dd9378f1445e875b822505a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 15 Mar 2024 17:32:25 +0100 Subject: [PATCH 0023/1340] PPA scripts: Don't use tabs for alignment --- scripts/deps-ppa/static_z3.sh | 8 ++++---- scripts/release_ppa.sh | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/scripts/deps-ppa/static_z3.sh b/scripts/deps-ppa/static_z3.sh index 67cb15ce8..106119917 100755 --- a/scripts/deps-ppa/static_z3.sh +++ b/scripts/deps-ppa/static_z3.sh @@ -9,10 +9,10 @@ ## This requires the following entries in /etc/dput.cf: ## ## [cpp-build-deps] -## fqdn = ppa.launchpad.net -## method = ftp -## incoming = ~ethereum/cpp-build-deps -## login = anonymous +## fqdn = ppa.launchpad.net +## method = ftp +## incoming = ~ethereum/cpp-build-deps +## login = anonymous ## ## To interact with launchpad, you need to set the variables $LAUNCHPAD_EMAIL ## and $LAUNCHPAD_KEYID in the file .release_ppa_auth in the root directory of diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 252fd4c49..e134ed161 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -23,22 +23,22 @@ ## Additionally the following entries in /etc/dput.cf are required: ## ## [ethereum-dev] -## fqdn = ppa.launchpad.net -## method = ftp -## incoming = ~ethereum/ethereum-dev -## login = anonymous +## fqdn = ppa.launchpad.net +## method = ftp +## incoming = ~ethereum/ethereum-dev +## login = anonymous ## ## [ethereum] -## fqdn = ppa.launchpad.net -## method = ftp -## incoming = ~ethereum/ethereum -## login = anonymous +## fqdn = ppa.launchpad.net +## method = ftp +## incoming = ~ethereum/ethereum +## login = anonymous ## ## [ethereum-static] -## fqdn = ppa.launchpad.net -## method = ftp -## incoming = ~ethereum/ethereum-static -## login = anonymous +## fqdn = ppa.launchpad.net +## method = ftp +## incoming = ~ethereum/ethereum-static +## login = anonymous ## ############################################################################## From b74203030ff8a09fa546c1d0c7ccb19fbbbf1a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 15 Mar 2024 17:33:15 +0100 Subject: [PATCH 0024/1340] PPA scripts: Drop lunar from the distribution list --- scripts/deps-ppa/static_z3.sh | 2 +- scripts/release_ppa.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/deps-ppa/static_z3.sh b/scripts/deps-ppa/static_z3.sh index 106119917..be45f4452 100755 --- a/scripts/deps-ppa/static_z3.sh +++ b/scripts/deps-ppa/static_z3.sh @@ -41,7 +41,7 @@ sourcePPAConfig # Sanity check checkDputEntries "\[cpp-build-deps\]" -DISTRIBUTIONS="focal jammy lunar mantic" +DISTRIBUTIONS="focal jammy mantic" for distribution in $DISTRIBUTIONS do diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index e134ed161..6a6fa8f0e 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -68,7 +68,7 @@ packagename=solc # This needs to be a still active release static_build_distribution=focal -DISTRIBUTIONS="focal jammy lunar mantic" +DISTRIBUTIONS="focal jammy mantic" if is_release then From d19991c34910e2c18788d3df78b633af71be80c9 Mon Sep 17 00:00:00 2001 From: Snoppy Date: Tue, 26 Mar 2024 16:32:36 +0800 Subject: [PATCH 0025/1340] fix typos (#14940) --- test/compilationTests/corion/premium.sol | 2 +- test/compilationTests/corion/schelling.sol | 2 +- test/compilationTests/corion/token.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/compilationTests/corion/premium.sol b/test/compilationTests/corion/premium.sol index 8dbe76212..646ab00e1 100644 --- a/test/compilationTests/corion/premium.sol +++ b/test/compilationTests/corion/premium.sol @@ -310,7 +310,7 @@ contract premium is module, safeMath { @addr The address which is needed to be checked. - @success Is the address crontact or not + @success Is the address contract or not */ uint256 _codeLength; assembly { diff --git a/test/compilationTests/corion/schelling.sol b/test/compilationTests/corion/schelling.sol index 2503748b8..96b530d26 100644 --- a/test/compilationTests/corion/schelling.sol +++ b/test/compilationTests/corion/schelling.sol @@ -521,7 +521,7 @@ contract schelling is module, announcementTypes, schellingVars { @aboveW Weight of votes: ABOVE @belowW Weight of votes: BELOW - @uint256 Calculatet weight + @uint256 Calculate weight */ if ( aboveW == belowW ) { return aboveW + belowW; diff --git a/test/compilationTests/corion/token.sol b/test/compilationTests/corion/token.sol index 51c93f120..377e8b68f 100644 --- a/test/compilationTests/corion/token.sol +++ b/test/compilationTests/corion/token.sol @@ -464,7 +464,7 @@ contract token is safeMath, module, announcementTypes { @addr Address to be checked - @success Is the address crontact or not + @success Is the address contract or not */ uint256 _codeLength; assembly { From 06fc835c8383c8ec0a69d9131bc2a552334cccb9 Mon Sep 17 00:00:00 2001 From: InventiveCoder <163831412+InventiveCoder@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:35:10 +0800 Subject: [PATCH 0026/1340] Remove redundant word (#14952) Signed-off-by: InventiveCoder --- libsolidity/codegen/ir/Common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/codegen/ir/Common.h b/libsolidity/codegen/ir/Common.h index 2484ad809..cf5bc69c7 100644 --- a/libsolidity/codegen/ir/Common.h +++ b/libsolidity/codegen/ir/Common.h @@ -81,7 +81,7 @@ std::string dispenseLocationComment(ASTNode const& _node, IRGenerationContext& _ } // Overloading std::less() makes it possible to use YulArity as a map key. We could define operator< -// instead but such an operator would be a bit ambiguous (e.g. YulArity{2, 2} would be be greater than +// instead but such an operator would be a bit ambiguous (e.g. YulArity{2, 2} would be greater than // YulArity{1, 10} in lexicographical order but the latter has greater total number of inputs and outputs). template<> struct std::less From f82f0a1abc29996643c2e2b932fab933d5fa8bf3 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 25 Mar 2024 12:19:05 +0100 Subject: [PATCH 0027/1340] Install latest eldarica release on base ubuntu image --- .../buildpack-deps/Dockerfile.ubuntu2004 | 25 +++++++++++++++---- .../buildpack-deps/Dockerfile.ubuntu2204 | 25 +++++++++++++++---- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index 6ff8d1bd4..45490291a 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -22,14 +22,14 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:focal AS base -LABEL version="21" +LABEL version="22" 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 ; \ + 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 sudo \ @@ -40,7 +40,20 @@ RUN set -ex; \ libcvc4-dev libz3-static-dev z3-static jq \ ; \ apt-get install -qy python3-pip python3-sphinx; \ - pip3 install codecov; \ + pip3 install codecov; + +# Eldarica +RUN set -ex; \ + apt-get update; \ + apt-get install -qy unzip openjdk-11-jre; \ + eldarica_version="2.1"; \ + wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ + test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ + unzip /opt/eld_binaries.zip -d /opt; \ + rm -f /opt/eld_binaries.zip; + +# Cleanup +RUN set -ex; \ rm -rf /var/lib/apt/lists/* FROM base AS libraries @@ -57,3 +70,5 @@ FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin COPY --from=libraries /usr/include /usr/include +COPY --from=libraries /opt/eldarica /opt/eldarica +ENV PATH="$PATH:/opt/eldarica" diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index 6908811f9..d7b925448 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -22,14 +22,14 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="6" +LABEL version="7" 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 ; \ + 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 sudo \ @@ -40,7 +40,20 @@ RUN set -ex; \ libcvc4-dev libz3-static-dev z3-static jq \ libcln-dev zip locales-all; \ apt-get install -qy python3-pip python3-sphinx; \ - pip3 install codecov; \ + pip3 install codecov; + +# Eldarica +RUN set -ex; \ + apt-get update; \ + apt-get install -qy unzip openjdk-11-jre; \ + eldarica_version="2.1"; \ + wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ + test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ + unzip /opt/eld_binaries.zip -d /opt; \ + rm -f /opt/eld_binaries.zip; + +# Cleanup +RUN set -ex; \ rm -rf /var/lib/apt/lists/* FROM base AS libraries @@ -61,3 +74,5 @@ FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin COPY --from=libraries /usr/include /usr/include +COPY --from=libraries /opt/eldarica /opt/eldarica +ENV PATH="$PATH:/opt/eldarica" From 9b0134b9539c4e731d701e29740880792a3cd400 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 25 Mar 2024 17:17:33 +0100 Subject: [PATCH 0028/1340] Install eldarica on OSX machines --- .circleci/osx_install_dependencies.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index 4ca4a31d5..87383ba8f 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -55,6 +55,9 @@ then brew install coreutils brew install diffutils brew install grep + # JRE is required to run eldarica solver + brew install openjdk@11 + brew install unzip # writing to /usr/local/lib need administrative privileges. sudo ./scripts/install_obsolete_jsoncpp_1_7_4.sh @@ -73,6 +76,14 @@ then cd .. sudo rm -rf "$boost_dir" + # eldarica + eldarica_version="2.1" + wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /tmp/eld_binaries.zip + validate_checksum /tmp/eld_binaries.zip 0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c + unzip /tmp/eld_binaries.zip -d /tmp + sudo mv /tmp/eldarica/{eld,eld-client,target,eldEnv} /usr/local/bin + rm -rf /tmp/{eldarica,eld_binaries.zip} + # z3 z3_version="4.12.1" z3_dir="z3-z3-$z3_version" From 77b8ca51d649201be80e17fbc539cf2378f69c1a Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 25 Mar 2024 17:22:27 +0100 Subject: [PATCH 0029/1340] Update `actions/checkout` version to v4 --- .github/workflows/buildpack-deps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index 6a261bd2e..2cd6e5048 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -26,7 +26,7 @@ jobs: image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2204.clang, ubuntu2204] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 From 1fec659620b1e260679bc365a7580cb12c2dc955 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 25 Mar 2024 14:19:38 +0100 Subject: [PATCH 0030/1340] Bump CI docker images --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 13f0c499f..5b6f023cc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,12 +9,12 @@ version: 2.1 parameters: ubuntu-2004-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-21 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:6f64c7b35aabddb416d28f621a3c4bbae768c257d6866f6a7f05f8225acc94f0" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-22 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:212b4d79a89c6e2d9b58ddea2d6296c5618f4ae0b016694a3b159d2b11cbbacc" ubuntu-2204-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-6 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:6eee10420382588b274374c6a18cb2e5d4f8a9fef5cf440b3a1acfc32bf52837" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-7 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:ecbeec36b12fd953bfb6fb3e7ced474bb73945d7ed615e6538960c32bae8126c" ubuntu-2204-clang-docker-image: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-5 From 9ea88304f2658cbe771dc7ce29dfc15e98d3d604 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Tue, 5 Mar 2024 20:13:32 +0100 Subject: [PATCH 0031/1340] SMTChecker: Add command-line test for Eldarica --- test/cmdlineTests/model_checker_solvers_eld/args | 1 + test/cmdlineTests/model_checker_solvers_eld/err | 5 +++++ test/cmdlineTests/model_checker_solvers_eld/input.sol | 7 +++++++ 3 files changed, 13 insertions(+) create mode 100644 test/cmdlineTests/model_checker_solvers_eld/args create mode 100644 test/cmdlineTests/model_checker_solvers_eld/err create mode 100644 test/cmdlineTests/model_checker_solvers_eld/input.sol diff --git a/test/cmdlineTests/model_checker_solvers_eld/args b/test/cmdlineTests/model_checker_solvers_eld/args new file mode 100644 index 000000000..e4acd0b46 --- /dev/null +++ b/test/cmdlineTests/model_checker_solvers_eld/args @@ -0,0 +1 @@ +--model-checker-engine chc --model-checker-solvers eld diff --git a/test/cmdlineTests/model_checker_solvers_eld/err b/test/cmdlineTests/model_checker_solvers_eld/err new file mode 100644 index 000000000..ff7ad37b3 --- /dev/null +++ b/test/cmdlineTests/model_checker_solvers_eld/err @@ -0,0 +1,5 @@ +Warning: CHC: Assertion violation happens here. + --> model_checker_solvers_eld/input.sol:5:3: + | +5 | assert(x > 0); + | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_solvers_eld/input.sol b/test/cmdlineTests/model_checker_solvers_eld/input.sol new file mode 100644 index 000000000..7d05ef6e5 --- /dev/null +++ b/test/cmdlineTests/model_checker_solvers_eld/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract test { + function f(uint x) public pure { + assert(x > 0); + } +} \ No newline at end of file From 1d9ae8703405310b7b2c1c7b4ed551f6deadda54 Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 3 Apr 2024 10:53:10 +0200 Subject: [PATCH 0032/1340] Install Eldarica on Ubuntu Clang images --- .../Dockerfile.ubuntu.clang.ossfuzz | 18 +++++++++++++++++- .../Dockerfile.ubuntu2204.clang | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index fd98de73e..0b2a99b1a 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-clang:latest as base -LABEL version="4" +LABEL version="5" ARG DEBIAN_FRONTEND=noninteractive @@ -73,6 +73,16 @@ RUN set -ex; \ make install; \ rm -rf /usr/src/z3 +# Eldarica +RUN set -ex; \ + apt-get update; \ + apt-get install -qy unzip openjdk-11-jre; \ + eldarica_version="2.1"; \ + wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ + test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ + unzip /opt/eld_binaries.zip -d /opt; \ + rm -f /opt/eld_binaries.zip; + # OSSFUZZ: libprotobuf-mutator RUN set -ex; \ git clone https://github.com/google/libprotobuf-mutator.git \ @@ -137,7 +147,13 @@ RUN set -ex; \ cp abicoder.hpp /usr/include; \ rm -rf /usr/src/Yul-Isabelle +# Cleanup +RUN set -ex; \ + rm -rf /var/lib/apt/lists/* + FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin COPY --from=libraries /usr/include /usr/include +COPY --from=libraries /opt/eldarica /opt/eldarica +ENV PATH="$PATH:/opt/eldarica" diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang index a14bdc113..60d5a599c 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="5" +LABEL version="6" ARG DEBIAN_FRONTEND=noninteractive @@ -39,7 +39,20 @@ RUN set -ex; \ libboost-program-options-dev \ clang \ libz3-static-dev z3-static jq \ - libcln-dev; \ + libcln-dev; + +# Eldarica +RUN set -ex; \ + apt-get update; \ + apt-get install -qy unzip openjdk-11-jre; \ + eldarica_version="2.1"; \ + wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ + test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ + unzip /opt/eld_binaries.zip -d /opt; \ + rm -f /opt/eld_binaries.zip; + +# Cleanup +RUN set -ex; \ rm -rf /var/lib/apt/lists/* FROM base AS libraries @@ -63,3 +76,5 @@ FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin COPY --from=libraries /usr/include /usr/include +COPY --from=libraries /opt/eldarica /opt/eldarica +ENV PATH="$PATH:/opt/eldarica" From f6dd9b0005b00e7a30772b767df223eee82059b8 Mon Sep 17 00:00:00 2001 From: zo9999 <99550525+zo9999@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:05:05 +0100 Subject: [PATCH 0033/1340] Make KnowledgeBase object constructors explicit in order to avoid (#14958) unexpected implicit conversions --- libyul/optimiser/KnowledgeBase.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libyul/optimiser/KnowledgeBase.h b/libyul/optimiser/KnowledgeBase.h index 258f85f5c..f83c5ac66 100644 --- a/libyul/optimiser/KnowledgeBase.h +++ b/libyul/optimiser/KnowledgeBase.h @@ -62,11 +62,11 @@ class KnowledgeBase public: /// Constructor for arbitrary value callback that allows for variable values /// to change in between calls to functions of this class. - KnowledgeBase(std::function _variableValues): + explicit KnowledgeBase(std::function _variableValues): m_variableValues(std::move(_variableValues)) {} /// Constructor to use if source code is in SSA form and values are constant. - KnowledgeBase(std::map const& _ssaValues); + explicit KnowledgeBase(std::map const& _ssaValues); bool knownToBeDifferent(YulString _a, YulString _b); std::optional differenceIfKnownConstant(YulString _a, YulString _b); From c75e63aba9b63f31b608e92263ed8ba6ed40e492 Mon Sep 17 00:00:00 2001 From: Tamas Molnar Date: Wed, 3 Apr 2024 12:01:21 +0200 Subject: [PATCH 0034/1340] docs: Replace outdated Scaffold-ETH link to Scaffold-ETH-2 (#14973) --- docs/resources.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/resources.rst b/docs/resources.rst index 85b3cf9a3..1773859d4 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -110,7 +110,7 @@ Solidity Tools * `leafleth `_ A documentation generator for Solidity smart-contracts. -* `Scaffold-ETH `_ +* `Scaffold-ETH 2 `_ Forkable Ethereum development stack focused on fast product iterations. * `sol2uml `_ From ad5eab88e3d66a98d47853bc0af0da1dfc2d2f70 Mon Sep 17 00:00:00 2001 From: Juliano Penna Date: Wed, 3 Apr 2024 07:04:12 -0300 Subject: [PATCH 0035/1340] Update reference-types.rst (#14949) It isn't "the only possibility for public contract function arguments" since version 0.6.9, as mentioned in the second "Note" of https://docs.soliditylang.org/en/v0.8.24/types.html#data-location --- docs/types/reference-types.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index d2e9300e6..a6c48d241 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -392,8 +392,7 @@ Array Members // Data location for all state variables is storage. bool[2][] pairsOfFlags; - // newPairs is stored in memory - the only possibility - // for public contract function arguments + // newPairs is stored in memory function setAllFlagPairs(bool[2][] memory newPairs) public { // assignment to a storage array performs a copy of ``newPairs`` and // replaces the complete array ``pairsOfFlags``. From 10b1b3c8fc360efdcec7579398409b614c3caae9 Mon Sep 17 00:00:00 2001 From: Vc Date: Wed, 3 Apr 2024 18:17:52 +0800 Subject: [PATCH 0036/1340] Optimize the magicVariableToID function. (#14901) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nikola Matić --- libsolidity/analysis/GlobalContext.cpp | 56 ++++++++++++++------------ 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index 628b90361..c4833689f 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -28,40 +28,46 @@ #include #include #include +#include namespace solidity::frontend { namespace { + /// Magic variables get negative ids for easy differentiation int magicVariableToID(std::string const& _name) { - if (_name == "abi") return -1; - else if (_name == "addmod") return -2; - else if (_name == "assert") return -3; - else if (_name == "block") return -4; - else if (_name == "blockhash") return -5; - else if (_name == "ecrecover") return -6; - else if (_name == "gasleft") return -7; - else if (_name == "keccak256") return -8; - else if (_name == "msg") return -15; - else if (_name == "mulmod") return -16; - else if (_name == "now") return -17; - else if (_name == "require") return -18; - else if (_name == "revert") return -19; - else if (_name == "ripemd160") return -20; - else if (_name == "selfdestruct") return -21; - else if (_name == "sha256") return -22; - else if (_name == "sha3") return -23; - else if (_name == "suicide") return -24; - else if (_name == "super") return -25; - else if (_name == "tx") return -26; - else if (_name == "type") return -27; - else if (_name == "this") return -28; - else if (_name == "blobhash") return -29; - else - solAssert(false, "Unknown magic variable: \"" + _name + "\"."); + static std::unordered_map const magicVariables = { + {"abi", -1}, + {"addmod", -2}, + {"assert", -3}, + {"block", -4}, + {"blockhash", -5}, + {"ecrecover", -6}, + {"gasleft", -7}, + {"keccak256", -8}, + {"msg", -15}, + {"mulmod", -16}, + {"now", -17}, + {"require", -18}, + {"revert", -19}, + {"ripemd160", -20}, + {"selfdestruct", -21}, + {"sha256", -22}, + {"sha3", -23}, + {"suicide", -24}, + {"super", -25}, + {"tx", -26}, + {"type", -27}, + {"this", -28}, + {"blobhash", -29} + }; + + if (auto id = magicVariables.find(_name); id != magicVariables.end()) + return id->second; + solAssert(false, "Unknown magic variable: \"" + _name + "\"."); } inline std::vector> constructMagicVariables(langutil::EVMVersion _evmVersion) From d2cbe963cf50ef9b18f7239ebd27409ec00b7a50 Mon Sep 17 00:00:00 2001 From: wilsoncusack Date: Wed, 3 Apr 2024 06:21:05 -0400 Subject: [PATCH 0037/1340] NatSpec: add error to context for notice, dev, and param tags. (#14970) --- docs/natspec-format.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst index f92958b90..b187ea84c 100644 --- a/docs/natspec-format.rst +++ b/docs/natspec-format.rst @@ -117,9 +117,9 @@ Tag =============== ====================================================================================== ============================= ``@title`` A title that should describe the contract/interface contract, library, interface, struct, enum ``@author`` The name of the author contract, library, interface, struct, enum -``@notice`` Explain to an end user what this does contract, library, interface, function, public state variable, event, struct, enum -``@dev`` Explain to a developer any extra details contract, library, interface, function, state variable, event, struct, enum -``@param`` Documents a parameter just like in Doxygen (must be followed by parameter name) function, event +``@notice`` Explain to an end user what this does contract, library, interface, function, public state variable, event, struct, enum, error +``@dev`` Explain to a developer any extra details contract, library, interface, function, state variable, event, struct, enum, error +``@param`` Documents a parameter just like in Doxygen (must be followed by parameter name) function, event, error ``@return`` Documents the return variables of a contract's function function, public state variable ``@inheritdoc`` Copies all missing tags from the base function (must be followed by the contract name) function, public state variable ``@custom:...`` Custom tag, semantics is application-defined everywhere From ab1f2b83e94515ac09feddeaec85334632801399 Mon Sep 17 00:00:00 2001 From: Ardis Lu Date: Wed, 3 Apr 2024 03:35:02 -0700 Subject: [PATCH 0038/1340] Update precompiled contract address range (#14950) --- docs/introduction-to-smart-contracts.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index a31b06616..de06d684e 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -603,7 +603,7 @@ Precompiled Contracts ===================== There is a small set of contract addresses that are special: -The address range between ``1`` and (including) ``8`` contains +The address range between ``1`` and (including) ``0x0a`` contains "precompiled contracts" that can be called as any other contract but their behavior (and their gas consumption) is not defined by EVM code stored at that address (they do not contain code) From 87bdfd6a70fd20b9fdcb269ab870c1ca09552873 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Thu, 15 Feb 2024 22:59:11 +0100 Subject: [PATCH 0039/1340] [buildsystem] Fix libstdlib to use CMAKE_CURRENT_SOURCE_DIR. --- libstdlib/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libstdlib/CMakeLists.txt b/libstdlib/CMakeLists.txt index 65a3a1cda..b6b22832d 100644 --- a/libstdlib/CMakeLists.txt +++ b/libstdlib/CMakeLists.txt @@ -1,18 +1,18 @@ # This will re-generate the headers if any file within src was modified. -set_directory_properties(PROPERTY CMAKE_CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/stdlib/src/) +set_directory_properties(PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/) set(STDLIB stub) set(GENERATED_STDLIB_HEADERS) foreach(src IN LISTS STDLIB) - set(STDLIB_FILE ${PROJECT_SOURCE_DIR}/libstdlib/src/${src}.sol) + set(STDLIB_FILE ${CMAKE_CURRENT_SOURCE_DIR}/src/${src}.sol) file(READ ${STDLIB_FILE} STDLIB_FILE_CONTENT HEX) string(REGEX MATCHALL ".." STDLIB_FILE_CONTENT "${STDLIB_FILE_CONTENT}") list(REMOVE_ITEM STDLIB_FILE_CONTENT "0d") string(REGEX REPLACE ";" ",\n\t0x" STDLIB_FILE_CONTENT "${STDLIB_FILE_CONTENT}") set(STDLIB_FILE_CONTENT "0x${STDLIB_FILE_CONTENT}") set(STDLIB_FILE_NAME ${src}) - configure_file("${PROJECT_SOURCE_DIR}/libstdlib/stdlib.src.h.in" ${PROJECT_BINARY_DIR}/include/libstdlib/${src}.h NEWLINE_STYLE LF @ONLY) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/stdlib.src.h.in" ${PROJECT_BINARY_DIR}/include/libstdlib/${src}.h NEWLINE_STYLE LF @ONLY) list(APPEND GENERATED_STDLIB_HEADERS ${PROJECT_BINARY_DIR}/include/libstdlib/${src}.h) endforeach() -configure_file("${PROJECT_SOURCE_DIR}/libstdlib/stdlib.h.in" ${PROJECT_BINARY_DIR}/include/libstdlib/stdlib.h NEWLINE_STYLE LF @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/stdlib.h.in" ${PROJECT_BINARY_DIR}/include/libstdlib/stdlib.h NEWLINE_STYLE LF @ONLY) From b60ed2b96a6b00b2d23a2dd9caf98173527fc38f Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Fri, 16 Feb 2024 18:00:41 +0100 Subject: [PATCH 0040/1340] [buildsystem] Add USE_SYSTEM_LIBRARIES option. --- CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e2a2b4a3..6609585a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,16 +37,19 @@ option(SOLC_STATIC_STDLIBS "Link solc against static versions of libgcc and libs option(STRICT_Z3_VERSION "Use the latest version of Z3" ON) option(PEDANTIC "Enable extra warnings and pedantic build flags. Treat all warnings as errors." ON) option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser steps." OFF) +option(USE_SYSTEM_LIBRARIES "Use system libraries" OFF) # Setup cccache. include(EthCcache) # Let's find our dependencies include(EthDependencies) -include(fmtlib) -include(jsoncpp) -include(range-v3) -include_directories(SYSTEM ${JSONCPP_INCLUDE_DIR}) +if (NOT USE_SYSTEM_LIBRARIES) + include(fmtlib) + include(jsoncpp) + include(range-v3) + include_directories(SYSTEM ${JSONCPP_INCLUDE_DIR}) +endif() find_package(Threads) From d178c40102f024f17e64c777b37729aec544409e Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Fri, 16 Feb 2024 19:33:38 +0100 Subject: [PATCH 0041/1340] [buildsystem] Add ONLY_BUILD_SOLIDITY_LIBRARIES option. --- CMakeLists.txt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6609585a7..142e884ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ option(STRICT_Z3_VERSION "Use the latest version of Z3" ON) option(PEDANTIC "Enable extra warnings and pedantic build flags. Treat all warnings as errors." ON) option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser steps." OFF) option(USE_SYSTEM_LIBRARIES "Use system libraries" OFF) +option(ONLY_BUILD_SOLIDITY_LIBRARIES "Only build solidity libraries" OFF) # Setup cccache. include(EthCcache) @@ -144,12 +145,16 @@ add_subdirectory(libyul) add_subdirectory(libsolidity) add_subdirectory(libsolc) add_subdirectory(libstdlib) -add_subdirectory(tools) -if (NOT EMSCRIPTEN) - add_subdirectory(solc) -endif() +if (NOT ONLY_BUILD_SOLIDITY_LIBRARIES) + add_subdirectory(tools) + + if (NOT EMSCRIPTEN) + add_subdirectory(solc) + endif() -if (TESTS AND NOT EMSCRIPTEN) - add_subdirectory(test) + if (TESTS AND NOT EMSCRIPTEN) + add_subdirectory(test) + endif() endif() + From 780018ad21656f04a6737b87965706e9dc4e8058 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Fri, 16 Feb 2024 19:40:56 +0100 Subject: [PATCH 0042/1340] [buildsystem] Add STRICT_JSONCPP_VERSION option. --- CMakeLists.txt | 5 +++++ libsolutil/JSON.cpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 142e884ed..b9f2ddc36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ option(PEDANTIC "Enable extra warnings and pedantic build flags. Treat all warni option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser steps." OFF) option(USE_SYSTEM_LIBRARIES "Use system libraries" OFF) option(ONLY_BUILD_SOLIDITY_LIBRARIES "Only build solidity libraries" OFF) +option(STRICT_JSONCPP_VERSION "Strictly check installed jsoncpp version" ON) # Setup cccache. include(EthCcache) @@ -62,6 +63,10 @@ if (PROFILE_OPTIMIZER_STEPS) add_definitions(-DPROFILE_OPTIMIZER_STEPS) endif() +if (STRICT_JSONCPP_VERSION) + add_definitions(-DSTRICT_JSONCPP_VERSION_CHECK) +endif() + # Figure out what compiler and system are we using include(EthCompilerSettings) diff --git a/libsolutil/JSON.cpp b/libsolutil/JSON.cpp index ea75ada0f..3a2570d47 100644 --- a/libsolutil/JSON.cpp +++ b/libsolutil/JSON.cpp @@ -30,10 +30,12 @@ #include #include +#ifdef STRICT_JSONCPP_VERSION_CHECK static_assert( (JSONCPP_VERSION_MAJOR == 1) && (JSONCPP_VERSION_MINOR == 9) && (JSONCPP_VERSION_PATCH == 3), "Unexpected jsoncpp version: " JSONCPP_VERSION_STRING ". Expecting 1.9.3." ); +#endif namespace solidity::util { From 8b1b65f93f2b48a3d35316caeb9508f56e787f19 Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 3 Apr 2024 12:40:44 +0200 Subject: [PATCH 0043/1340] Bump ubuntu-clang docker images --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5b6f023cc..21b596830 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,12 +17,12 @@ parameters: default: "solbuildpackpusher/solidity-buildpack-deps@sha256:ecbeec36b12fd953bfb6fb3e7ced474bb73945d7ed615e6538960c32bae8126c" ubuntu-2204-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-5 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:e991421ce9f44d6476b29588fc355da1c3b3fedcc424fd12d844bbe310ad7851" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-6 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:1818a56061f39ece4a92138948404214bf939c9deb68f4dc2c68cd82b39e8410" ubuntu-clang-ossfuzz-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-4 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:b122ef9dca71a8f90b74f3ba13cda4453681506e4a4ff047e7bc2130c76b0d1e" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-5 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c21c4c2a591d0702c388d1944539f6498ed8e51c54c1a1cb34693079efd9ab77" emscripten-docker-image: type: string # NOTE: Please remember to update the `build_emscripten.sh` whenever the hash of this image changes. From 95046121317ee9bfc65dbe88aa64ed296cc3e08e Mon Sep 17 00:00:00 2001 From: Pawel Gebal Date: Thu, 4 Apr 2024 17:14:07 +0200 Subject: [PATCH 0044/1340] SMTChecker: Fix internal error when using bitwise operators with an array element as an argument --- Changelog.md | 1 + libsmtutil/Z3Interface.cpp | 2 ++ .../operators/bitwise_and_array.sol | 17 +++++++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 test/libsolidity/smtCheckerTests/operators/bitwise_and_array.sol diff --git a/Changelog.md b/Changelog.md index 21a58478a..c915a1ecf 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: Bugfixes: + * SMTChecker: Fix internal error when using bitwise operators with an array element as argument. ### 0.8.25 (2023-03-14) diff --git a/libsmtutil/Z3Interface.cpp b/libsmtutil/Z3Interface.cpp index a16e75668..1cfbc815f 100644 --- a/libsmtutil/Z3Interface.cpp +++ b/libsmtutil/Z3Interface.cpp @@ -386,6 +386,8 @@ Expression Z3Interface::fromZ3Expr(z3::expr const& _expr) kind == Z3_OP_RECURSIVE ) return Expression(_expr.decl().name().str(), arguments, fromZ3Sort(_expr.get_sort())); + else if (kind == Z3_OP_CONCAT) + return Expression("concat", arguments, sort); smtAssert(false); diff --git a/test/libsolidity/smtCheckerTests/operators/bitwise_and_array.sol b/test/libsolidity/smtCheckerTests/operators/bitwise_and_array.sol new file mode 100644 index 000000000..96e143490 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/bitwise_and_array.sol @@ -0,0 +1,17 @@ +contract C { + function bitwiseXor(int[10] memory p) public pure { + 1 ^ p[0]; + } + + function bitwiseAnd(int[10] memory p) public pure { + 1 & p[0]; + } + + function bitwiseOr(int[10] memory p) public pure { + 1 | p[0]; + } +} +// ==== +// SMTEngine: all +// ---- +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From bcb10f8111ae987ba711f62cdcc308896e7b3332 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Wed, 3 Apr 2024 13:47:18 +0200 Subject: [PATCH 0045/1340] Remove signature removal from macos universal binaries. --- .circleci/config.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 21b596830..0dd960e93 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -249,13 +249,6 @@ commands: # -------------------------------------------------------------------------- # Artifact Commands - remove_signature_from_universal_binary: - description: Remove signature from universal binary - steps: - - run: - name: Remove signature from universal binary - command: codesign --remove-signature build/solc/solc - store_artifacts_solc: description: Store compiled solc executable as artifact steps: @@ -1196,7 +1189,6 @@ jobs: - checkout - install_dependencies_osx - run_build - - remove_signature_from_universal_binary - store_artifacts_solc - store_artifacts_yul_phaser - persist_executables_to_workspace_osx From f6d5a4373e85067b5ba7f54fb6c45e7802c4c067 Mon Sep 17 00:00:00 2001 From: hanghuge Date: Sat, 6 Apr 2024 21:01:34 +0800 Subject: [PATCH 0046/1340] chore: remove repetitive words Signed-off-by: hanghuge --- libsolidity/interface/FileReader.cpp | 2 +- .../yulOptimizerTests/unusedAssignEliminator/for_continue.yul | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index 4197780e6..158d4dd2c 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -271,7 +271,7 @@ boost::filesystem::path FileReader::normalizeCLIPathForVFS( // If the path is on the same drive as the working dir, for portability we prefer not to // include the root name. Do this only for non-UNC paths - my experiments show that on Windows - // when the working dir is an UNC path, / does not not actually refer to the root of the UNC path. + // when the working dir is an UNC path, / does not actually refer to the root of the UNC path. boost::filesystem::path normalizedRootPath = normalizeCLIRootPathForVFS(normalizedPath, canonicalWorkDir); diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue.yul index d3cfb0d84..213ebcaea 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/for_continue.yul @@ -7,7 +7,7 @@ x := 2 // Will not be removed as if-condition can be false. if callvalue() { // This can be removed because x is overwritten both after the - // loop at at the start of the next iteration. + // loop at the start of the next iteration. x := 3 continue } From 37f46544bd2e9eefe85624cd18ce5a2c7b963c77 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Sun, 18 Feb 2024 23:11:48 +0100 Subject: [PATCH 0047/1340] Rename some tests. --- .../args | 0 .../output | 0 .../stdin | 0 .../args | 0 .../output | 0 .../stdin | 0 .../args | 0 .../output | 0 .../stdin | 0 .../args | 0 .../err | 0 .../exit | 0 .../stdin | 0 .../args | 0 .../err | 0 .../exit | 0 .../stdin | 0 .../args | 0 .../err | 0 .../exit | 0 .../stdin | 0 .../args | 0 .../err | 0 .../exit | 0 .../stdin | 0 .../args | 0 .../err | 0 .../exit | 0 .../stdin | 0 .../{asm_json_import_no_value => import_asm_json_no_value}/args | 0 .../{asm_json_import_no_value => import_asm_json_no_value}/err | 0 .../{asm_json_import_no_value => import_asm_json_no_value}/exit | 0 .../{asm_json_import_no_value => import_asm_json_no_value}/stdin | 0 .../args | 0 .../err | 0 .../exit | 0 .../stdin | 0 .../args | 0 .../err | 0 .../exit | 0 .../stdin | 0 .../args | 0 .../err | 0 .../exit | 0 .../stdin | 0 .../args | 0 .../output | 0 .../stdin | 0 .../args | 0 .../err | 0 .../exit | 0 .../stdin | 0 .../args | 0 .../err | 0 .../exit | 0 .../stdin | 0 .../{asm_json_import_verbatim => import_asm_json_verbatim}/args | 0 .../{asm_json_import_verbatim => import_asm_json_verbatim}/output | 0 .../{asm_json_import_verbatim => import_asm_json_verbatim}/stdin | 0 .../args | 0 .../output | 0 .../stdin | 0 .../args | 0 .../output | 0 .../stdin | 0 65 files changed, 0 insertions(+), 0 deletions(-) rename test/cmdlineTests/{asm_json_import_all_valid_flags => import_asm_json_all_valid_flags}/args (100%) rename test/cmdlineTests/{asm_json_import_all_valid_flags => import_asm_json_all_valid_flags}/output (100%) rename test/cmdlineTests/{asm_json_import_all_valid_flags => import_asm_json_all_valid_flags}/stdin (100%) rename test/cmdlineTests/{asm_json_import_difficulty_prevrandao => import_asm_json_difficulty_prevrandao}/args (100%) rename test/cmdlineTests/{asm_json_import_difficulty_prevrandao => import_asm_json_difficulty_prevrandao}/output (100%) rename test/cmdlineTests/{asm_json_import_difficulty_prevrandao => import_asm_json_difficulty_prevrandao}/stdin (100%) rename test/cmdlineTests/{asm_json_import_hex_subassembly_indices => import_asm_json_hex_subassembly_indices}/args (100%) rename test/cmdlineTests/{asm_json_import_hex_subassembly_indices => import_asm_json_hex_subassembly_indices}/output (100%) rename test/cmdlineTests/{asm_json_import_hex_subassembly_indices => import_asm_json_hex_subassembly_indices}/stdin (100%) rename test/cmdlineTests/{asm_json_import_invalid_data_not_hex => import_asm_json_invalid_data_not_hex}/args (100%) rename test/cmdlineTests/{asm_json_import_invalid_data_not_hex => import_asm_json_invalid_data_not_hex}/err (100%) rename test/cmdlineTests/{asm_json_import_invalid_data_not_hex => import_asm_json_invalid_data_not_hex}/exit (100%) rename test/cmdlineTests/{asm_json_import_invalid_data_not_hex => import_asm_json_invalid_data_not_hex}/stdin (100%) rename test/cmdlineTests/{asm_json_import_invalid_data_not_object => import_asm_json_invalid_data_not_object}/args (100%) rename test/cmdlineTests/{asm_json_import_invalid_data_not_object => import_asm_json_invalid_data_not_object}/err (100%) rename test/cmdlineTests/{asm_json_import_invalid_data_not_object => import_asm_json_invalid_data_not_object}/exit (100%) rename test/cmdlineTests/{asm_json_import_invalid_data_not_object => import_asm_json_invalid_data_not_object}/stdin (100%) rename test/cmdlineTests/{asm_json_import_invalid_jumptype_instruction => import_asm_json_invalid_jumptype_instruction}/args (100%) rename test/cmdlineTests/{asm_json_import_invalid_jumptype_instruction => import_asm_json_invalid_jumptype_instruction}/err (100%) rename test/cmdlineTests/{asm_json_import_invalid_jumptype_instruction => import_asm_json_invalid_jumptype_instruction}/exit (100%) rename test/cmdlineTests/{asm_json_import_invalid_jumptype_instruction => import_asm_json_invalid_jumptype_instruction}/stdin (100%) rename test/cmdlineTests/{asm_json_import_invalid_value => import_asm_json_invalid_value}/args (100%) rename test/cmdlineTests/{asm_json_import_invalid_value => import_asm_json_invalid_value}/err (100%) rename test/cmdlineTests/{asm_json_import_invalid_value => import_asm_json_invalid_value}/exit (100%) rename test/cmdlineTests/{asm_json_import_invalid_value => import_asm_json_invalid_value}/stdin (100%) rename test/cmdlineTests/{asm_json_import_missing_subobject_indices => import_asm_json_missing_subobject_indices}/args (100%) rename test/cmdlineTests/{asm_json_import_missing_subobject_indices => import_asm_json_missing_subobject_indices}/err (100%) rename test/cmdlineTests/{asm_json_import_missing_subobject_indices => import_asm_json_missing_subobject_indices}/exit (100%) rename test/cmdlineTests/{asm_json_import_missing_subobject_indices => import_asm_json_missing_subobject_indices}/stdin (100%) rename test/cmdlineTests/{asm_json_import_no_value => import_asm_json_no_value}/args (100%) rename test/cmdlineTests/{asm_json_import_no_value => import_asm_json_no_value}/err (100%) rename test/cmdlineTests/{asm_json_import_no_value => import_asm_json_no_value}/exit (100%) rename test/cmdlineTests/{asm_json_import_no_value => import_asm_json_no_value}/stdin (100%) rename test/cmdlineTests/{asm_json_import_non_unique_sources => import_asm_json_non_unique_sources}/args (100%) rename test/cmdlineTests/{asm_json_import_non_unique_sources => import_asm_json_non_unique_sources}/err (100%) rename test/cmdlineTests/{asm_json_import_non_unique_sources => import_asm_json_non_unique_sources}/exit (100%) rename test/cmdlineTests/{asm_json_import_non_unique_sources => import_asm_json_non_unique_sources}/stdin (100%) rename test/cmdlineTests/{asm_json_import_optimize_not_supported => import_asm_json_optimize_not_supported}/args (100%) rename test/cmdlineTests/{asm_json_import_optimize_not_supported => import_asm_json_optimize_not_supported}/err (100%) rename test/cmdlineTests/{asm_json_import_optimize_not_supported => import_asm_json_optimize_not_supported}/exit (100%) rename test/cmdlineTests/{asm_json_import_optimize_not_supported => import_asm_json_optimize_not_supported}/stdin (100%) rename test/cmdlineTests/{asm_json_import_out_of_range_data_index => import_asm_json_out_of_range_data_index}/args (100%) rename test/cmdlineTests/{asm_json_import_out_of_range_data_index => import_asm_json_out_of_range_data_index}/err (100%) rename test/cmdlineTests/{asm_json_import_out_of_range_data_index => import_asm_json_out_of_range_data_index}/exit (100%) rename test/cmdlineTests/{asm_json_import_out_of_range_data_index => import_asm_json_out_of_range_data_index}/stdin (100%) rename test/cmdlineTests/{asm_json_import_random_order_data_index => import_asm_json_random_order_data_index}/args (100%) rename test/cmdlineTests/{asm_json_import_random_order_data_index => import_asm_json_random_order_data_index}/output (100%) rename test/cmdlineTests/{asm_json_import_random_order_data_index => import_asm_json_random_order_data_index}/stdin (100%) rename test/cmdlineTests/{asm_json_import_unrecognized_field => import_asm_json_unrecognized_field}/args (100%) rename test/cmdlineTests/{asm_json_import_unrecognized_field => import_asm_json_unrecognized_field}/err (100%) rename test/cmdlineTests/{asm_json_import_unrecognized_field => import_asm_json_unrecognized_field}/exit (100%) rename test/cmdlineTests/{asm_json_import_unrecognized_field => import_asm_json_unrecognized_field}/stdin (100%) rename test/cmdlineTests/{asm_json_import_untagged_jumpdest => import_asm_json_untagged_jumpdest}/args (100%) rename test/cmdlineTests/{asm_json_import_untagged_jumpdest => import_asm_json_untagged_jumpdest}/err (100%) rename test/cmdlineTests/{asm_json_import_untagged_jumpdest => import_asm_json_untagged_jumpdest}/exit (100%) rename test/cmdlineTests/{asm_json_import_untagged_jumpdest => import_asm_json_untagged_jumpdest}/stdin (100%) rename test/cmdlineTests/{asm_json_import_verbatim => import_asm_json_verbatim}/args (100%) rename test/cmdlineTests/{asm_json_import_verbatim => import_asm_json_verbatim}/output (100%) rename test/cmdlineTests/{asm_json_import_verbatim => import_asm_json_verbatim}/stdin (100%) rename test/cmdlineTests/{asm_json_import_yul_more_subobjects => import_asm_json_yul_more_subobjects}/args (100%) rename test/cmdlineTests/{asm_json_import_yul_more_subobjects => import_asm_json_yul_more_subobjects}/output (100%) rename test/cmdlineTests/{asm_json_import_yul_more_subobjects => import_asm_json_yul_more_subobjects}/stdin (100%) rename test/cmdlineTests/{asm_json_import_yul_subobjects => import_asm_json_yul_subobjects}/args (100%) rename test/cmdlineTests/{asm_json_import_yul_subobjects => import_asm_json_yul_subobjects}/output (100%) rename test/cmdlineTests/{asm_json_import_yul_subobjects => import_asm_json_yul_subobjects}/stdin (100%) diff --git a/test/cmdlineTests/asm_json_import_all_valid_flags/args b/test/cmdlineTests/import_asm_json_all_valid_flags/args similarity index 100% rename from test/cmdlineTests/asm_json_import_all_valid_flags/args rename to test/cmdlineTests/import_asm_json_all_valid_flags/args diff --git a/test/cmdlineTests/asm_json_import_all_valid_flags/output b/test/cmdlineTests/import_asm_json_all_valid_flags/output similarity index 100% rename from test/cmdlineTests/asm_json_import_all_valid_flags/output rename to test/cmdlineTests/import_asm_json_all_valid_flags/output diff --git a/test/cmdlineTests/asm_json_import_all_valid_flags/stdin b/test/cmdlineTests/import_asm_json_all_valid_flags/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_all_valid_flags/stdin rename to test/cmdlineTests/import_asm_json_all_valid_flags/stdin diff --git a/test/cmdlineTests/asm_json_import_difficulty_prevrandao/args b/test/cmdlineTests/import_asm_json_difficulty_prevrandao/args similarity index 100% rename from test/cmdlineTests/asm_json_import_difficulty_prevrandao/args rename to test/cmdlineTests/import_asm_json_difficulty_prevrandao/args diff --git a/test/cmdlineTests/asm_json_import_difficulty_prevrandao/output b/test/cmdlineTests/import_asm_json_difficulty_prevrandao/output similarity index 100% rename from test/cmdlineTests/asm_json_import_difficulty_prevrandao/output rename to test/cmdlineTests/import_asm_json_difficulty_prevrandao/output diff --git a/test/cmdlineTests/asm_json_import_difficulty_prevrandao/stdin b/test/cmdlineTests/import_asm_json_difficulty_prevrandao/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_difficulty_prevrandao/stdin rename to test/cmdlineTests/import_asm_json_difficulty_prevrandao/stdin diff --git a/test/cmdlineTests/asm_json_import_hex_subassembly_indices/args b/test/cmdlineTests/import_asm_json_hex_subassembly_indices/args similarity index 100% rename from test/cmdlineTests/asm_json_import_hex_subassembly_indices/args rename to test/cmdlineTests/import_asm_json_hex_subassembly_indices/args diff --git a/test/cmdlineTests/asm_json_import_hex_subassembly_indices/output b/test/cmdlineTests/import_asm_json_hex_subassembly_indices/output similarity index 100% rename from test/cmdlineTests/asm_json_import_hex_subassembly_indices/output rename to test/cmdlineTests/import_asm_json_hex_subassembly_indices/output diff --git a/test/cmdlineTests/asm_json_import_hex_subassembly_indices/stdin b/test/cmdlineTests/import_asm_json_hex_subassembly_indices/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_hex_subassembly_indices/stdin rename to test/cmdlineTests/import_asm_json_hex_subassembly_indices/stdin diff --git a/test/cmdlineTests/asm_json_import_invalid_data_not_hex/args b/test/cmdlineTests/import_asm_json_invalid_data_not_hex/args similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_data_not_hex/args rename to test/cmdlineTests/import_asm_json_invalid_data_not_hex/args diff --git a/test/cmdlineTests/asm_json_import_invalid_data_not_hex/err b/test/cmdlineTests/import_asm_json_invalid_data_not_hex/err similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_data_not_hex/err rename to test/cmdlineTests/import_asm_json_invalid_data_not_hex/err diff --git a/test/cmdlineTests/asm_json_import_invalid_data_not_hex/exit b/test/cmdlineTests/import_asm_json_invalid_data_not_hex/exit similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_data_not_hex/exit rename to test/cmdlineTests/import_asm_json_invalid_data_not_hex/exit diff --git a/test/cmdlineTests/asm_json_import_invalid_data_not_hex/stdin b/test/cmdlineTests/import_asm_json_invalid_data_not_hex/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_data_not_hex/stdin rename to test/cmdlineTests/import_asm_json_invalid_data_not_hex/stdin diff --git a/test/cmdlineTests/asm_json_import_invalid_data_not_object/args b/test/cmdlineTests/import_asm_json_invalid_data_not_object/args similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_data_not_object/args rename to test/cmdlineTests/import_asm_json_invalid_data_not_object/args diff --git a/test/cmdlineTests/asm_json_import_invalid_data_not_object/err b/test/cmdlineTests/import_asm_json_invalid_data_not_object/err similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_data_not_object/err rename to test/cmdlineTests/import_asm_json_invalid_data_not_object/err diff --git a/test/cmdlineTests/asm_json_import_invalid_data_not_object/exit b/test/cmdlineTests/import_asm_json_invalid_data_not_object/exit similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_data_not_object/exit rename to test/cmdlineTests/import_asm_json_invalid_data_not_object/exit diff --git a/test/cmdlineTests/asm_json_import_invalid_data_not_object/stdin b/test/cmdlineTests/import_asm_json_invalid_data_not_object/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_data_not_object/stdin rename to test/cmdlineTests/import_asm_json_invalid_data_not_object/stdin diff --git a/test/cmdlineTests/asm_json_import_invalid_jumptype_instruction/args b/test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/args similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_jumptype_instruction/args rename to test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/args diff --git a/test/cmdlineTests/asm_json_import_invalid_jumptype_instruction/err b/test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/err similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_jumptype_instruction/err rename to test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/err diff --git a/test/cmdlineTests/asm_json_import_invalid_jumptype_instruction/exit b/test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/exit similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_jumptype_instruction/exit rename to test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/exit diff --git a/test/cmdlineTests/asm_json_import_invalid_jumptype_instruction/stdin b/test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_jumptype_instruction/stdin rename to test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/stdin diff --git a/test/cmdlineTests/asm_json_import_invalid_value/args b/test/cmdlineTests/import_asm_json_invalid_value/args similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_value/args rename to test/cmdlineTests/import_asm_json_invalid_value/args diff --git a/test/cmdlineTests/asm_json_import_invalid_value/err b/test/cmdlineTests/import_asm_json_invalid_value/err similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_value/err rename to test/cmdlineTests/import_asm_json_invalid_value/err diff --git a/test/cmdlineTests/asm_json_import_invalid_value/exit b/test/cmdlineTests/import_asm_json_invalid_value/exit similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_value/exit rename to test/cmdlineTests/import_asm_json_invalid_value/exit diff --git a/test/cmdlineTests/asm_json_import_invalid_value/stdin b/test/cmdlineTests/import_asm_json_invalid_value/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_invalid_value/stdin rename to test/cmdlineTests/import_asm_json_invalid_value/stdin diff --git a/test/cmdlineTests/asm_json_import_missing_subobject_indices/args b/test/cmdlineTests/import_asm_json_missing_subobject_indices/args similarity index 100% rename from test/cmdlineTests/asm_json_import_missing_subobject_indices/args rename to test/cmdlineTests/import_asm_json_missing_subobject_indices/args diff --git a/test/cmdlineTests/asm_json_import_missing_subobject_indices/err b/test/cmdlineTests/import_asm_json_missing_subobject_indices/err similarity index 100% rename from test/cmdlineTests/asm_json_import_missing_subobject_indices/err rename to test/cmdlineTests/import_asm_json_missing_subobject_indices/err diff --git a/test/cmdlineTests/asm_json_import_missing_subobject_indices/exit b/test/cmdlineTests/import_asm_json_missing_subobject_indices/exit similarity index 100% rename from test/cmdlineTests/asm_json_import_missing_subobject_indices/exit rename to test/cmdlineTests/import_asm_json_missing_subobject_indices/exit diff --git a/test/cmdlineTests/asm_json_import_missing_subobject_indices/stdin b/test/cmdlineTests/import_asm_json_missing_subobject_indices/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_missing_subobject_indices/stdin rename to test/cmdlineTests/import_asm_json_missing_subobject_indices/stdin diff --git a/test/cmdlineTests/asm_json_import_no_value/args b/test/cmdlineTests/import_asm_json_no_value/args similarity index 100% rename from test/cmdlineTests/asm_json_import_no_value/args rename to test/cmdlineTests/import_asm_json_no_value/args diff --git a/test/cmdlineTests/asm_json_import_no_value/err b/test/cmdlineTests/import_asm_json_no_value/err similarity index 100% rename from test/cmdlineTests/asm_json_import_no_value/err rename to test/cmdlineTests/import_asm_json_no_value/err diff --git a/test/cmdlineTests/asm_json_import_no_value/exit b/test/cmdlineTests/import_asm_json_no_value/exit similarity index 100% rename from test/cmdlineTests/asm_json_import_no_value/exit rename to test/cmdlineTests/import_asm_json_no_value/exit diff --git a/test/cmdlineTests/asm_json_import_no_value/stdin b/test/cmdlineTests/import_asm_json_no_value/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_no_value/stdin rename to test/cmdlineTests/import_asm_json_no_value/stdin diff --git a/test/cmdlineTests/asm_json_import_non_unique_sources/args b/test/cmdlineTests/import_asm_json_non_unique_sources/args similarity index 100% rename from test/cmdlineTests/asm_json_import_non_unique_sources/args rename to test/cmdlineTests/import_asm_json_non_unique_sources/args diff --git a/test/cmdlineTests/asm_json_import_non_unique_sources/err b/test/cmdlineTests/import_asm_json_non_unique_sources/err similarity index 100% rename from test/cmdlineTests/asm_json_import_non_unique_sources/err rename to test/cmdlineTests/import_asm_json_non_unique_sources/err diff --git a/test/cmdlineTests/asm_json_import_non_unique_sources/exit b/test/cmdlineTests/import_asm_json_non_unique_sources/exit similarity index 100% rename from test/cmdlineTests/asm_json_import_non_unique_sources/exit rename to test/cmdlineTests/import_asm_json_non_unique_sources/exit diff --git a/test/cmdlineTests/asm_json_import_non_unique_sources/stdin b/test/cmdlineTests/import_asm_json_non_unique_sources/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_non_unique_sources/stdin rename to test/cmdlineTests/import_asm_json_non_unique_sources/stdin diff --git a/test/cmdlineTests/asm_json_import_optimize_not_supported/args b/test/cmdlineTests/import_asm_json_optimize_not_supported/args similarity index 100% rename from test/cmdlineTests/asm_json_import_optimize_not_supported/args rename to test/cmdlineTests/import_asm_json_optimize_not_supported/args diff --git a/test/cmdlineTests/asm_json_import_optimize_not_supported/err b/test/cmdlineTests/import_asm_json_optimize_not_supported/err similarity index 100% rename from test/cmdlineTests/asm_json_import_optimize_not_supported/err rename to test/cmdlineTests/import_asm_json_optimize_not_supported/err diff --git a/test/cmdlineTests/asm_json_import_optimize_not_supported/exit b/test/cmdlineTests/import_asm_json_optimize_not_supported/exit similarity index 100% rename from test/cmdlineTests/asm_json_import_optimize_not_supported/exit rename to test/cmdlineTests/import_asm_json_optimize_not_supported/exit diff --git a/test/cmdlineTests/asm_json_import_optimize_not_supported/stdin b/test/cmdlineTests/import_asm_json_optimize_not_supported/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_optimize_not_supported/stdin rename to test/cmdlineTests/import_asm_json_optimize_not_supported/stdin diff --git a/test/cmdlineTests/asm_json_import_out_of_range_data_index/args b/test/cmdlineTests/import_asm_json_out_of_range_data_index/args similarity index 100% rename from test/cmdlineTests/asm_json_import_out_of_range_data_index/args rename to test/cmdlineTests/import_asm_json_out_of_range_data_index/args diff --git a/test/cmdlineTests/asm_json_import_out_of_range_data_index/err b/test/cmdlineTests/import_asm_json_out_of_range_data_index/err similarity index 100% rename from test/cmdlineTests/asm_json_import_out_of_range_data_index/err rename to test/cmdlineTests/import_asm_json_out_of_range_data_index/err diff --git a/test/cmdlineTests/asm_json_import_out_of_range_data_index/exit b/test/cmdlineTests/import_asm_json_out_of_range_data_index/exit similarity index 100% rename from test/cmdlineTests/asm_json_import_out_of_range_data_index/exit rename to test/cmdlineTests/import_asm_json_out_of_range_data_index/exit diff --git a/test/cmdlineTests/asm_json_import_out_of_range_data_index/stdin b/test/cmdlineTests/import_asm_json_out_of_range_data_index/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_out_of_range_data_index/stdin rename to test/cmdlineTests/import_asm_json_out_of_range_data_index/stdin diff --git a/test/cmdlineTests/asm_json_import_random_order_data_index/args b/test/cmdlineTests/import_asm_json_random_order_data_index/args similarity index 100% rename from test/cmdlineTests/asm_json_import_random_order_data_index/args rename to test/cmdlineTests/import_asm_json_random_order_data_index/args diff --git a/test/cmdlineTests/asm_json_import_random_order_data_index/output b/test/cmdlineTests/import_asm_json_random_order_data_index/output similarity index 100% rename from test/cmdlineTests/asm_json_import_random_order_data_index/output rename to test/cmdlineTests/import_asm_json_random_order_data_index/output diff --git a/test/cmdlineTests/asm_json_import_random_order_data_index/stdin b/test/cmdlineTests/import_asm_json_random_order_data_index/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_random_order_data_index/stdin rename to test/cmdlineTests/import_asm_json_random_order_data_index/stdin diff --git a/test/cmdlineTests/asm_json_import_unrecognized_field/args b/test/cmdlineTests/import_asm_json_unrecognized_field/args similarity index 100% rename from test/cmdlineTests/asm_json_import_unrecognized_field/args rename to test/cmdlineTests/import_asm_json_unrecognized_field/args diff --git a/test/cmdlineTests/asm_json_import_unrecognized_field/err b/test/cmdlineTests/import_asm_json_unrecognized_field/err similarity index 100% rename from test/cmdlineTests/asm_json_import_unrecognized_field/err rename to test/cmdlineTests/import_asm_json_unrecognized_field/err diff --git a/test/cmdlineTests/asm_json_import_unrecognized_field/exit b/test/cmdlineTests/import_asm_json_unrecognized_field/exit similarity index 100% rename from test/cmdlineTests/asm_json_import_unrecognized_field/exit rename to test/cmdlineTests/import_asm_json_unrecognized_field/exit diff --git a/test/cmdlineTests/asm_json_import_unrecognized_field/stdin b/test/cmdlineTests/import_asm_json_unrecognized_field/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_unrecognized_field/stdin rename to test/cmdlineTests/import_asm_json_unrecognized_field/stdin diff --git a/test/cmdlineTests/asm_json_import_untagged_jumpdest/args b/test/cmdlineTests/import_asm_json_untagged_jumpdest/args similarity index 100% rename from test/cmdlineTests/asm_json_import_untagged_jumpdest/args rename to test/cmdlineTests/import_asm_json_untagged_jumpdest/args diff --git a/test/cmdlineTests/asm_json_import_untagged_jumpdest/err b/test/cmdlineTests/import_asm_json_untagged_jumpdest/err similarity index 100% rename from test/cmdlineTests/asm_json_import_untagged_jumpdest/err rename to test/cmdlineTests/import_asm_json_untagged_jumpdest/err diff --git a/test/cmdlineTests/asm_json_import_untagged_jumpdest/exit b/test/cmdlineTests/import_asm_json_untagged_jumpdest/exit similarity index 100% rename from test/cmdlineTests/asm_json_import_untagged_jumpdest/exit rename to test/cmdlineTests/import_asm_json_untagged_jumpdest/exit diff --git a/test/cmdlineTests/asm_json_import_untagged_jumpdest/stdin b/test/cmdlineTests/import_asm_json_untagged_jumpdest/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_untagged_jumpdest/stdin rename to test/cmdlineTests/import_asm_json_untagged_jumpdest/stdin diff --git a/test/cmdlineTests/asm_json_import_verbatim/args b/test/cmdlineTests/import_asm_json_verbatim/args similarity index 100% rename from test/cmdlineTests/asm_json_import_verbatim/args rename to test/cmdlineTests/import_asm_json_verbatim/args diff --git a/test/cmdlineTests/asm_json_import_verbatim/output b/test/cmdlineTests/import_asm_json_verbatim/output similarity index 100% rename from test/cmdlineTests/asm_json_import_verbatim/output rename to test/cmdlineTests/import_asm_json_verbatim/output diff --git a/test/cmdlineTests/asm_json_import_verbatim/stdin b/test/cmdlineTests/import_asm_json_verbatim/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_verbatim/stdin rename to test/cmdlineTests/import_asm_json_verbatim/stdin diff --git a/test/cmdlineTests/asm_json_import_yul_more_subobjects/args b/test/cmdlineTests/import_asm_json_yul_more_subobjects/args similarity index 100% rename from test/cmdlineTests/asm_json_import_yul_more_subobjects/args rename to test/cmdlineTests/import_asm_json_yul_more_subobjects/args diff --git a/test/cmdlineTests/asm_json_import_yul_more_subobjects/output b/test/cmdlineTests/import_asm_json_yul_more_subobjects/output similarity index 100% rename from test/cmdlineTests/asm_json_import_yul_more_subobjects/output rename to test/cmdlineTests/import_asm_json_yul_more_subobjects/output diff --git a/test/cmdlineTests/asm_json_import_yul_more_subobjects/stdin b/test/cmdlineTests/import_asm_json_yul_more_subobjects/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_yul_more_subobjects/stdin rename to test/cmdlineTests/import_asm_json_yul_more_subobjects/stdin diff --git a/test/cmdlineTests/asm_json_import_yul_subobjects/args b/test/cmdlineTests/import_asm_json_yul_subobjects/args similarity index 100% rename from test/cmdlineTests/asm_json_import_yul_subobjects/args rename to test/cmdlineTests/import_asm_json_yul_subobjects/args diff --git a/test/cmdlineTests/asm_json_import_yul_subobjects/output b/test/cmdlineTests/import_asm_json_yul_subobjects/output similarity index 100% rename from test/cmdlineTests/asm_json_import_yul_subobjects/output rename to test/cmdlineTests/import_asm_json_yul_subobjects/output diff --git a/test/cmdlineTests/asm_json_import_yul_subobjects/stdin b/test/cmdlineTests/import_asm_json_yul_subobjects/stdin similarity index 100% rename from test/cmdlineTests/asm_json_import_yul_subobjects/stdin rename to test/cmdlineTests/import_asm_json_yul_subobjects/stdin From c5c0bc534ede889a836c6282f85a2d59d209b3d2 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Mon, 8 Apr 2024 11:21:44 +0200 Subject: [PATCH 0048/1340] Rename additional tests. --- .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 22 files changed, 0 insertions(+), 0 deletions(-) rename test/cmdlineTests/{standard_import_evmasm => standard_import_asm_json}/input.json (100%) rename test/cmdlineTests/{standard_import_evmasm => standard_import_asm_json}/output.json (100%) rename test/cmdlineTests/{standard_import_evmasm_immutable_references => standard_import_asm_json_immutable_references}/input.json (100%) rename test/cmdlineTests/{standard_import_evmasm_immutable_references => standard_import_asm_json_immutable_references}/output.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_input_array => standard_import_asm_json_invalid_input_array}/input.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_input_array => standard_import_asm_json_invalid_input_array}/output.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_key_inside_source => standard_import_asm_json_invalid_key_inside_source}/input.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_key_inside_source => standard_import_asm_json_invalid_key_inside_source}/output.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_key_other_source => standard_import_asm_json_invalid_key_other_source}/input.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_key_other_source => standard_import_asm_json_invalid_key_other_source}/output.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_no_source => standard_import_asm_json_invalid_no_source}/input.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_no_source => standard_import_asm_json_invalid_no_source}/output.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_opcode => standard_import_asm_json_invalid_opcode}/input.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_opcode => standard_import_asm_json_invalid_opcode}/output.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_two_sources => standard_import_asm_json_invalid_two_sources}/input.json (100%) rename test/cmdlineTests/{standard_import_evmasm_invalid_two_sources => standard_import_asm_json_invalid_two_sources}/output.json (100%) rename test/cmdlineTests/{standard_import_evmasm_link_references => standard_import_asm_json_link_references}/input.json (100%) rename test/cmdlineTests/{standard_import_evmasm_link_references => standard_import_asm_json_link_references}/output.json (100%) rename test/cmdlineTests/{standard_import_evmasm_multiple_keys_inside_source => standard_import_asm_json_multiple_keys_inside_source}/input.json (100%) rename test/cmdlineTests/{standard_import_evmasm_multiple_keys_inside_source => standard_import_asm_json_multiple_keys_inside_source}/output.json (100%) rename test/cmdlineTests/{standard_import_evmasm_no_output_selection => standard_import_asm_json_no_output_selection}/input.json (100%) rename test/cmdlineTests/{standard_import_evmasm_no_output_selection => standard_import_asm_json_no_output_selection}/output.json (100%) diff --git a/test/cmdlineTests/standard_import_evmasm/input.json b/test/cmdlineTests/standard_import_asm_json/input.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm/input.json rename to test/cmdlineTests/standard_import_asm_json/input.json diff --git a/test/cmdlineTests/standard_import_evmasm/output.json b/test/cmdlineTests/standard_import_asm_json/output.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm/output.json rename to test/cmdlineTests/standard_import_asm_json/output.json diff --git a/test/cmdlineTests/standard_import_evmasm_immutable_references/input.json b/test/cmdlineTests/standard_import_asm_json_immutable_references/input.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_immutable_references/input.json rename to test/cmdlineTests/standard_import_asm_json_immutable_references/input.json diff --git a/test/cmdlineTests/standard_import_evmasm_immutable_references/output.json b/test/cmdlineTests/standard_import_asm_json_immutable_references/output.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_immutable_references/output.json rename to test/cmdlineTests/standard_import_asm_json_immutable_references/output.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_input_array/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_input_array/input.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_input_array/input.json rename to test/cmdlineTests/standard_import_asm_json_invalid_input_array/input.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_input_array/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_input_array/output.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_input_array/output.json rename to test/cmdlineTests/standard_import_asm_json_invalid_input_array/output.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_key_inside_source/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_key_inside_source/input.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_key_inside_source/input.json rename to test/cmdlineTests/standard_import_asm_json_invalid_key_inside_source/input.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_key_inside_source/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_key_inside_source/output.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_key_inside_source/output.json rename to test/cmdlineTests/standard_import_asm_json_invalid_key_inside_source/output.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_key_other_source/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_key_other_source/input.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_key_other_source/input.json rename to test/cmdlineTests/standard_import_asm_json_invalid_key_other_source/input.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_key_other_source/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_key_other_source/output.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_key_other_source/output.json rename to test/cmdlineTests/standard_import_asm_json_invalid_key_other_source/output.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_no_source/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_no_source/input.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_no_source/input.json rename to test/cmdlineTests/standard_import_asm_json_invalid_no_source/input.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_no_source/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_no_source/output.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_no_source/output.json rename to test/cmdlineTests/standard_import_asm_json_invalid_no_source/output.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_opcode/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_opcode/input.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_opcode/input.json rename to test/cmdlineTests/standard_import_asm_json_invalid_opcode/input.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_opcode/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_opcode/output.json rename to test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_two_sources/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_two_sources/input.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_two_sources/input.json rename to test/cmdlineTests/standard_import_asm_json_invalid_two_sources/input.json diff --git a/test/cmdlineTests/standard_import_evmasm_invalid_two_sources/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_two_sources/output.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_invalid_two_sources/output.json rename to test/cmdlineTests/standard_import_asm_json_invalid_two_sources/output.json diff --git a/test/cmdlineTests/standard_import_evmasm_link_references/input.json b/test/cmdlineTests/standard_import_asm_json_link_references/input.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_link_references/input.json rename to test/cmdlineTests/standard_import_asm_json_link_references/input.json diff --git a/test/cmdlineTests/standard_import_evmasm_link_references/output.json b/test/cmdlineTests/standard_import_asm_json_link_references/output.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_link_references/output.json rename to test/cmdlineTests/standard_import_asm_json_link_references/output.json diff --git a/test/cmdlineTests/standard_import_evmasm_multiple_keys_inside_source/input.json b/test/cmdlineTests/standard_import_asm_json_multiple_keys_inside_source/input.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_multiple_keys_inside_source/input.json rename to test/cmdlineTests/standard_import_asm_json_multiple_keys_inside_source/input.json diff --git a/test/cmdlineTests/standard_import_evmasm_multiple_keys_inside_source/output.json b/test/cmdlineTests/standard_import_asm_json_multiple_keys_inside_source/output.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_multiple_keys_inside_source/output.json rename to test/cmdlineTests/standard_import_asm_json_multiple_keys_inside_source/output.json diff --git a/test/cmdlineTests/standard_import_evmasm_no_output_selection/input.json b/test/cmdlineTests/standard_import_asm_json_no_output_selection/input.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_no_output_selection/input.json rename to test/cmdlineTests/standard_import_asm_json_no_output_selection/input.json diff --git a/test/cmdlineTests/standard_import_evmasm_no_output_selection/output.json b/test/cmdlineTests/standard_import_asm_json_no_output_selection/output.json similarity index 100% rename from test/cmdlineTests/standard_import_evmasm_no_output_selection/output.json rename to test/cmdlineTests/standard_import_asm_json_no_output_selection/output.json From 0c32ddb0d6130b38b70180c4076fbc8123fb401f Mon Sep 17 00:00:00 2001 From: pcw109550 Date: Mon, 8 Apr 2024 11:48:53 -0600 Subject: [PATCH 0049/1340] Fix error msg for hex number combined with unit denomination --- libsolidity/analysis/TypeChecker.cpp | 2 +- .../denominations/combining_hex_and_denomination.sol | 2 +- .../syntaxTests/denominations/invalid_denomination_address.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 5bef2803a..0bcab65d9 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3874,7 +3874,7 @@ void TypeChecker::endVisit(Literal const& _literal) 5145_error, _literal.location(), "Hexadecimal numbers cannot be used with unit denominations. " - "You can use an expression of the form \"0x1234 * 1 day\" instead." + "You can use an expression of the form \"0x1234 * 1 days\" instead." ); if (_literal.subDenomination() == Literal::SubDenomination::Year) diff --git a/test/libsolidity/syntaxTests/denominations/combining_hex_and_denomination.sol b/test/libsolidity/syntaxTests/denominations/combining_hex_and_denomination.sol index 994c0568a..f200b1356 100644 --- a/test/libsolidity/syntaxTests/denominations/combining_hex_and_denomination.sol +++ b/test/libsolidity/syntaxTests/denominations/combining_hex_and_denomination.sol @@ -2,4 +2,4 @@ contract C { uint constant x = 0x01 wei; } // ---- -// TypeError 5145: (32-40): Hexadecimal numbers cannot be used with unit denominations. You can use an expression of the form "0x1234 * 1 day" instead. +// TypeError 5145: (32-40): Hexadecimal numbers cannot be used with unit denominations. You can use an expression of the form "0x1234 * 1 days" instead. diff --git a/test/libsolidity/syntaxTests/denominations/invalid_denomination_address.sol b/test/libsolidity/syntaxTests/denominations/invalid_denomination_address.sol index 8eec22dee..7c1f1e270 100644 --- a/test/libsolidity/syntaxTests/denominations/invalid_denomination_address.sol +++ b/test/libsolidity/syntaxTests/denominations/invalid_denomination_address.sol @@ -2,4 +2,4 @@ contract C { address a = 0x11111122222333334444455555666667777788888 wei; } // ---- -// TypeError 5145: (26-73): Hexadecimal numbers cannot be used with unit denominations. You can use an expression of the form "0x1234 * 1 day" instead. +// TypeError 5145: (26-73): Hexadecimal numbers cannot be used with unit denominations. You can use an expression of the form "0x1234 * 1 days" instead. From 8c320419775e8f207a305c85ee40e6d8717c051b Mon Sep 17 00:00:00 2001 From: looklose Date: Wed, 10 Apr 2024 20:42:50 +0800 Subject: [PATCH 0050/1340] chore: fix typo in comment Signed-off-by: looklose --- libsolc/libsolc.h | 2 +- libsolutil/Keccak256.cpp | 2 +- test/libsolidity/AnalysisFramework.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolc/libsolc.h b/libsolc/libsolc.h index c5b3b3db7..b259ed06a 100644 --- a/libsolc/libsolc.h +++ b/libsolc/libsolc.h @@ -45,7 +45,7 @@ extern "C" { /// @param o_error A pointer to an error message, if there is one. /// /// The file (as well as error) contents that is to be allocated by the callback -/// implementor must use the solidity_alloc() API to allocate its underlying +/// implementer must use the solidity_alloc() API to allocate its underlying /// storage. Ownership is then transferred to the compiler which will take care /// of the deallocation. /// diff --git a/libsolutil/Keccak256.cpp b/libsolutil/Keccak256.cpp index c54dedabe..9cf716354 100644 --- a/libsolutil/Keccak256.cpp +++ b/libsolutil/Keccak256.cpp @@ -35,7 +35,7 @@ namespace * * A single-file implementation of SHA-3 and SHAKE. * - * Implementor: David Leon Gil + * implementer: David Leon Gil * License: CC0, attribution kindly requested. Blame taken too, * but not liability. */ diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h index e7b2c03ec..93581a582 100644 --- a/test/libsolidity/AnalysisFramework.h +++ b/test/libsolidity/AnalysisFramework.h @@ -200,7 +200,7 @@ CHECK_ERROR_OR_WARNING(text, type, substrings, false, true) #define CHECK_WARNING(text, substring) \ CHECK_ERROR_OR_WARNING(text, Warning, std::vector{(substring)}, true, false) -// [checkWarningAllowMulti(text, substring)] aserts that the compilation down to typechecking +// [checkWarningAllowMulti(text, substring)] asserts that the compilation down to typechecking // emits a warning and with a message containing [substring]. // Because of the limitations of the preprocessor, you cannot use {"abc", "def"} as arguments, // but have to replace them by (std::vector{"abc", "def"}) (note the parentheses) From c2d2143dad57319ecb737aa7033a555bafc618e3 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 3 Apr 2024 21:37:15 +0200 Subject: [PATCH 0051/1340] SMTChecker: Add helper method to check for compatibility of sorts The helper method makes clear the intent clear and should be more readable than if-then-else branches with smtAssertions. Moreover, some of the if-conditions were not checking the right thing. --- libsmtutil/SolverInterface.h | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/libsmtutil/SolverInterface.h b/libsmtutil/SolverInterface.h index 82f811133..f9a61e2ec 100644 --- a/libsmtutil/SolverInterface.h +++ b/libsmtutil/SolverInterface.h @@ -189,10 +189,7 @@ class Expression static Expression ite(Expression _condition, Expression _trueValue, Expression _falseValue) { - if (_trueValue.sort->kind == Kind::Int) - smtAssert(_trueValue.sort->kind == _falseValue.sort->kind, ""); - else - smtAssert(*_trueValue.sort == *_falseValue.sort, ""); + smtAssert(areCompatible(*_trueValue.sort, *_falseValue.sort)); SortPointer sort = _trueValue.sort; return Expression("ite", std::vector{ std::move(_condition), std::move(_trueValue), std::move(_falseValue) @@ -216,10 +213,7 @@ class Expression std::shared_ptr arraySort = std::dynamic_pointer_cast(_array.sort); smtAssert(arraySort, ""); smtAssert(_index.sort, ""); - if (arraySort->domain->kind == Kind::Int) - smtAssert(arraySort->domain->kind == _index.sort->kind, ""); - else - smtAssert(*arraySort->domain == *_index.sort, ""); + smtAssert(areCompatible(*arraySort->domain, *_index.sort)); return Expression( "select", std::vector{std::move(_array), std::move(_index)}, @@ -236,10 +230,7 @@ class Expression smtAssert(_index.sort, ""); smtAssert(_element.sort, ""); smtAssert(*arraySort->domain == *_index.sort, ""); - if (arraySort->domain->kind == Kind::Int) - smtAssert(arraySort->range->kind == _element.sort->kind, ""); - else - smtAssert(*arraySort->range == *_element.sort, ""); + smtAssert(areCompatible(*arraySort->range, *_element.sort)); return Expression( "store", std::vector{std::move(_array), std::move(_index), std::move(_element)}, @@ -254,10 +245,7 @@ class Expression auto arraySort = std::dynamic_pointer_cast(sortSort->inner); smtAssert(sortSort && arraySort, ""); smtAssert(_value.sort, ""); - if (arraySort->domain->kind == Kind::Int) - smtAssert(arraySort->range->kind == _value.sort->kind, ""); - else - smtAssert(*arraySort->range == *_value.sort, ""); + smtAssert(areCompatible(*arraySort->range, *_value.sort)); return Expression( "const_array", std::vector{std::move(_sort), std::move(_value)}, @@ -501,6 +489,12 @@ class Expression SortPointer sort; private: + /// Helper method for checking sort compatibility when creating expressions + /// Signed and unsigned Int sorts are compatible even though they are not same + static bool areCompatible(Sort const& s1, Sort const& s2) + { + return s1.kind == Kind::Int ? s1.kind == s2.kind : s1 == s2; + } /// Manual constructors, should only be used by SolverInterface and this class itself. Expression(std::string _name, std::vector _arguments, Kind _kind): Expression(std::move(_name), std::move(_arguments), std::make_shared(_kind)) {} From 60240b489447824c16b54f893a9b76d0ee5678f3 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 3 Apr 2024 21:41:58 +0200 Subject: [PATCH 0052/1340] SMTChecker: Relax assertion for creating array store expression --- libsmtutil/SolverInterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsmtutil/SolverInterface.h b/libsmtutil/SolverInterface.h index f9a61e2ec..13803de6e 100644 --- a/libsmtutil/SolverInterface.h +++ b/libsmtutil/SolverInterface.h @@ -229,7 +229,7 @@ class Expression smtAssert(arraySort, ""); smtAssert(_index.sort, ""); smtAssert(_element.sort, ""); - smtAssert(*arraySort->domain == *_index.sort, ""); + smtAssert(areCompatible(*arraySort->domain, *_index.sort)); smtAssert(areCompatible(*arraySort->range, *_element.sort)); return Expression( "store", From e74472c77d1b8a714c23df14175b0e95aabdfe43 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 3 Apr 2024 21:50:46 +0200 Subject: [PATCH 0053/1340] SMTChecker: Add regression test --- ...pping_integer_signedness_compatibility.sol | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 test/libsolidity/smtCheckerTests/types/mapping_integer_signedness_compatibility.sol diff --git a/test/libsolidity/smtCheckerTests/types/mapping_integer_signedness_compatibility.sol b/test/libsolidity/smtCheckerTests/types/mapping_integer_signedness_compatibility.sol new file mode 100644 index 000000000..a05c8d3e1 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_integer_signedness_compatibility.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-3.0 + + +// Regression for handling signedness, see issue #14792 +contract C { + mapping(int => int) v1; + mapping(int => uint) v2; + mapping(uint => int) v3; + mapping(uint => uint) v4; + mapping(bytes12 => int) v5; + uint[5] a1; + int[5] a2; + + function f() public { + delete v1[0]; + delete v2[0]; + delete v3[0]; + delete v4[0]; + delete v5[0]; + delete a1[0]; + delete a2[0]; + } +} +// ---- +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 0c831e0995fde6aed98c77b8ea6f72c80c941867 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 12 Apr 2024 09:56:32 +0200 Subject: [PATCH 0054/1340] Add a changelog entry about a fixed ICE in SMTChecker --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index c915a1ecf..ccc2de41a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: Bugfixes: + * SMTChecker: Fix internal error on mapping access caused by too strong requirements on sort compatibility of the index and mapping domain. * SMTChecker: Fix internal error when using bitwise operators with an array element as argument. From b958d80eaaebb697c962462e42f7769155211e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 12 Apr 2024 14:27:53 +0200 Subject: [PATCH 0055/1340] gas_diff_stats: Use argparse and adjust description to work better with it --- scripts/gas_diff_stats.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index e593bb9a9..8736e21d7 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -1,26 +1,21 @@ #!/usr/bin/env python3 -"""A script to collect gas statistics and print it. +"""Summarizes gas differences from semantic test diff. -Useful to summarize gas differences to semantic tests for a PR / branch. +The script collects all gas differences present in git diff of semantic tests +and summarizes them in the form of a table that's ready to post in a GitHub comment. +The diff is calculated against the `origin/develop` branch. +Only changes that are already committed are taken into account. +Changes that are only staged or not staged or committed at all are ignored. -Dependencies: Parsec (https://pypi.org/project/parsec/) and Tabulate -(https://pypi.org/project/tabulate/) - - pip install parsec tabulate - -Run from root project dir. - - python3 scripts/gas_diff_stats.py - -Note that the changes to semantic tests have to be committed. - -Assumes that there is a remote named ``origin`` pointing to the Solidity github -repository. The changes are compared against ``origin/develop``. +Useful for reviewing the gas impact of a specific PR / branch. +Instead of tediously going through each individual change, it's recommended to review the table. +Dependencies: parsec, tabulate """ import subprocess import sys +from argparse import ArgumentParser, RawDescriptionHelpFormatter from pathlib import Path from enum import Enum from parsec import generate, ParseError, regex, string, optional @@ -170,6 +165,9 @@ def stat(old, new): print("No differences found.") def main(): + parser = ArgumentParser(description=__doc__, formatter_class=RawDescriptionHelpFormatter) + options = parser.parse_args() + try: semantictest_statistics() except subprocess.CalledProcessError as exception: From 42aa58aa36c3f2ef1dcde1e3e2d4d185b076e6a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 12 Apr 2024 15:29:11 +0200 Subject: [PATCH 0056/1340] gas_diff_stats: Base branch option --- scripts/gas_diff_stats.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 8736e21d7..ecb4cc912 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -3,7 +3,6 @@ The script collects all gas differences present in git diff of semantic tests and summarizes them in the form of a table that's ready to post in a GitHub comment. -The diff is calculated against the `origin/develop` branch. Only changes that are already committed are taken into account. Changes that are only staged or not staged or committed at all are ignored. @@ -100,11 +99,11 @@ def collect_statistics(lines) -> (int, int, int, int, int, int): for _codegen_kind in codegen_kinds ) -def semantictest_statistics(): +def semantictest_statistics(base_branch: str): """Prints the tabulated statistics that can be pasted in github.""" def parse_git_diff(fname): diff_output = subprocess.check_output( - ["git", "diff", "--unified=0", "origin/develop", "HEAD", fname], + ["git", "diff", "--unified=0", base_branch, "HEAD", fname], universal_newlines=True ).splitlines() if len(diff_output) == 0: @@ -166,10 +165,16 @@ def stat(old, new): def main(): parser = ArgumentParser(description=__doc__, formatter_class=RawDescriptionHelpFormatter) + parser.add_argument( + '--base', + dest='base_branch', + default='origin/develop', + help='The base branch to diff against. default: origin/develop', + ) options = parser.parse_args() try: - semantictest_statistics() + semantictest_statistics(options.base_branch) except subprocess.CalledProcessError as exception: sys.exit(f"Error in the git diff:\n{exception.output}") except ParseError as exception: From 54e425236d47a0bbab658bb55d3bf5d3b4565a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 12 Apr 2024 23:10:36 +0200 Subject: [PATCH 0057/1340] Clean up tab/space mix and tabs used for alignment --- CODING_STYLE.md | 2 +- cmake/EthCompilerSettings.cmake | 34 +- cmake/EthDependencies.cmake | 6 +- docs/grammar/SolidityParser.g4 | 4 +- libevmasm/AssemblyItem.cpp | 2 +- libevmasm/Instruction.cpp | 300 ++++++++-------- libevmasm/Instruction.h | 334 +++++++++--------- liblangutil/Token.h | 16 +- libsmtutil/CHCSmtLib2Interface.cpp | 2 +- libsolidity/analysis/TypeChecker.cpp | 2 +- libsolidity/ast/ASTAnnotations.h | 4 +- libsolidity/ast/Types.cpp | 2 +- libsolidity/codegen/ExpressionCompiler.cpp | 2 +- .../experimental/codegen/IRGenerator.cpp | 15 +- .../experimental/codegen/IRGenerator.h | 4 +- libsolidity/formal/BMC.cpp | 4 +- libsolidity/formal/SMTEncoder.h | 2 +- libsolutil/FixedHash.h | 2 +- libsolutil/Result.h | 6 +- libyul/YulString.h | 2 +- .../backends/evm/ControlFlowGraphBuilder.cpp | 2 +- libyul/backends/evm/EVMDialect.cpp | 36 +- libyul/backends/evm/StackLayoutGenerator.cpp | 2 +- libyul/optimiser/ExpressionJoiner.h | 6 +- libyul/optimiser/SSAReverser.h | 34 +- scripts/release_ppa.sh | 4 +- test/EVMHost.cpp | 2 +- test/InteractiveTests.h | 42 +-- .../model_checker_contracts_all/input.sol | 6 +- .../input.json | 4 +- .../input.json | 4 +- .../input.json | 28 +- .../standard_wrong_key_metadata/input.json | 14 +- .../standard_wrong_key_optimizer/input.json | 14 +- .../standard_wrong_key_settings/input.json | 40 +-- test/libevmasm/Optimiser.cpp | 4 +- test/libsolidity/SemanticTest.cpp | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 36 +- test/libsolidity/SolidityOptimizer.cpp | 4 +- test/libsolidity/StandardCompiler.cpp | 2 +- .../dev_multiple_params_mixed_whitespace.sol | 6 +- .../functions/functions_library_internal.sol | 2 +- .../loops/do_while_bmc_iterations_break_6.sol | 2 +- .../loops/do_while_bmc_iterations_break_7.sol | 4 +- ..._while_bmc_iterations_break_continue_1.sol | 4 +- ..._while_bmc_iterations_break_continue_2.sol | 4 +- .../loops/for_loop_bmc_iterations_break_2.sol | 2 +- .../loops/for_loop_bmc_iterations_break_8.sol | 2 +- .../loops/for_loop_bmc_iterations_break_9.sol | 2 +- ...r_loop_bmc_iterations_break_continue_1.sol | 4 +- ...r_loop_bmc_iterations_break_continue_2.sol | 2 +- ...r_loop_bmc_iterations_break_continue_3.sol | 2 +- .../for_loop_bmc_iterations_continue_3.sol | 2 +- .../loops/while_bmc_iterations_8.sol | 2 +- .../loops/while_bmc_iterations_break_4.sol | 2 +- .../loops/while_bmc_iterations_break_6.sol | 2 +- .../loops/while_bmc_iterations_break_7.sol | 4 +- .../while_bmc_iterations_break_continue_1.sol | 4 +- .../while_bmc_iterations_break_continue_2.sol | 4 +- .../while_bmc_iterations_semantics_2.sol | 2 +- .../operators/delete_multid_array.sol | 8 +- .../util/TestFunctionCallTests.cpp | 2 +- test/libyul/Parser.cpp | 8 +- test/libyul/StackShufflingTest.cpp | 24 +- test/libyul/YulOptimizerTestCommon.cpp | 2 +- .../nested_different_names.yul | 8 +- .../nested_same_name.yul | 8 +- .../expressionSimplifier/return_vars_zero.yul | 2 +- .../static_array_slot_computation.yul | 8 +- test/tools/ossfuzz/protoToAbiV2.cpp | 6 +- test/tools/ossfuzz/protoToAbiV2.h | 200 +++++------ test/tools/ossfuzz/protoToYul.h | 8 +- 72 files changed, 686 insertions(+), 687 deletions(-) diff --git a/CODING_STYLE.md b/CODING_STYLE.md index 5b9129fbd..2305ae1ec 100644 --- a/CODING_STYLE.md +++ b/CODING_STYLE.md @@ -20,7 +20,7 @@ Yes: ```cpp if (a == b[i]) - printf("Hello\n"); // NOTE spaces used instead of tab here for clarity - first byte should be '\t'. + printf("Hello\n"); // NOTE spaces used instead of tab here for clarity - first byte should be '\t'. foo->bar( someLongVariableName, anotherLongVariableName, diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 6cfa864c1..5c2802d1f 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -171,25 +171,25 @@ elseif (DEFINED MSVC) # CMAKE_CXX_FLAGS_RELWITHDEBINFO for GCC/Clang does not include NDEBUG string(REPLACE "/DNDEBUG" " " CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - add_compile_options(/MP) # enable parallel compilation - add_compile_options(/EHsc) # specify Exception Handling Model in msvc + add_compile_options(/MP) # enable parallel compilation + add_compile_options(/EHsc) # specify Exception Handling Model in msvc if(PEDANTIC) - add_compile_options(/WX) # enable warnings-as-errors + add_compile_options(/WX) # enable warnings-as-errors endif() - add_compile_options(/wd4068) # disable unknown pragma warning (4068) - add_compile_options(/wd4996) # disable unsafe function warning (4996) - add_compile_options(/wd4503) # disable decorated name length exceeded, name was truncated (4503) - add_compile_options(/wd4267) # disable conversion from 'size_t' to 'type', possible loss of data (4267) - add_compile_options(/wd4180) # disable qualifier applied to function type has no meaning; ignored (4180) - add_compile_options(/wd4290) # disable C++ exception specification ignored except to indicate a function is not __declspec(nothrow) (4290) - add_compile_options(/wd4244) # disable conversion from 'type1' to 'type2', possible loss of data (4244) - add_compile_options(/wd4800) # disable forcing value to bool 'true' or 'false' (performance warning) (4800) - add_compile_options(-D_WIN32_WINNT=0x0600) # declare Windows Vista API requirement - add_compile_options(-DNOMINMAX) # undefine windows.h MAX && MIN macros cause it cause conflicts with std::min && std::max functions - add_compile_options(/utf-8) # enable utf-8 encoding (solves warning 4819) - add_compile_options(-DBOOST_REGEX_NO_LIB) # disable automatic boost::regex library selection - add_compile_options(-D_REGEX_MAX_STACK_COUNT=200000L) # increase std::regex recursion depth limit - add_compile_options(/permissive-) # specify standards conformance mode to the compiler + add_compile_options(/wd4068) # disable unknown pragma warning (4068) + add_compile_options(/wd4996) # disable unsafe function warning (4996) + add_compile_options(/wd4503) # disable decorated name length exceeded, name was truncated (4503) + add_compile_options(/wd4267) # disable conversion from 'size_t' to 'type', possible loss of data (4267) + add_compile_options(/wd4180) # disable qualifier applied to function type has no meaning; ignored (4180) + add_compile_options(/wd4290) # disable C++ exception specification ignored except to indicate a function is not __declspec(nothrow) (4290) + add_compile_options(/wd4244) # disable conversion from 'type1' to 'type2', possible loss of data (4244) + add_compile_options(/wd4800) # disable forcing value to bool 'true' or 'false' (performance warning) (4800) + add_compile_options(-D_WIN32_WINNT=0x0600) # declare Windows Vista API requirement + add_compile_options(-DNOMINMAX) # undefine windows.h MAX && MIN macros cause it cause conflicts with std::min && std::max functions + add_compile_options(/utf-8) # enable utf-8 encoding (solves warning 4819) + add_compile_options(-DBOOST_REGEX_NO_LIB) # disable automatic boost::regex library selection + add_compile_options(-D_REGEX_MAX_STACK_COUNT=200000L) # increase std::regex recursion depth limit + add_compile_options(/permissive-) # specify standards conformance mode to the compiler # disable empty object file warning set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 7a84a01d9..16f30a640 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -10,9 +10,9 @@ if (DEFINED MSVC) else() get_filename_component(DEPS_DIR "${CMAKE_CURRENT_LIST_DIR}/../deps/install" ABSOLUTE) set(ETH_DEPENDENCY_INSTALL_DIR - "${DEPS_DIR}/x64" # Old location for deps. - "${DEPS_DIR}/win64" # New location for deps. - "${DEPS_DIR}/win64/Release/share" # LLVM shared cmake files. + "${DEPS_DIR}/x64" # Old location for deps. + "${DEPS_DIR}/win64" # New location for deps. + "${DEPS_DIR}/win64/Release/share" # LLVM shared cmake files. ) endif() set (CMAKE_PREFIX_PATH ${ETH_DEPENDENCY_INSTALL_DIR} ${CMAKE_PREFIX_PATH}) diff --git a/docs/grammar/SolidityParser.g4 b/docs/grammar/SolidityParser.g4 index c46cefd2f..e6d3ed7cc 100644 --- a/docs/grammar/SolidityParser.g4 +++ b/docs/grammar/SolidityParser.g4 @@ -251,7 +251,7 @@ structMember: type=typeName name=identifier Semicolon; /** * Definition of an enum. Can occur at top-level within a source unit or within a contract, library or interface. */ -enumDefinition: Enum name=identifier LBrace enumValues+=identifier (Comma enumValues+=identifier)* RBrace; +enumDefinition: Enum name=identifier LBrace enumValues+=identifier (Comma enumValues+=identifier)* RBrace; /** * Definition of a user defined value type. Can occur at top-level within a source unit or within a contract, library or interface. */ @@ -400,7 +400,7 @@ expression: | New typeName # NewExpr | tupleExpression # Tuple | inlineArrayExpression # InlineArray - | ( + | ( identifier | literal | literalWithSubDenomination diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 2adaa023a..c88a9663f 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -127,7 +127,7 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision) return 1 + std::max(1, numberEncodingSize(data())); case PushSubSize: case PushProgramSize: - return 1 + 4; // worst case: a 16MB program + return 1 + 4; // worst case: a 16MB program case PushTag: case PushData: case PushSub: diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index ca0dff185..943f34ee4 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -182,156 +182,156 @@ std::map const solidity::evmasm::c_instructions = /// @note InstructionInfo is assumed to be the same across all EVM versions except for the instruction name. static std::map const c_instructionInfo = -{ // Add, Args, Ret, SideEffects, GasPriceTier - { Instruction::STOP, { "STOP", 0, 0, 0, true, Tier::Zero } }, - { Instruction::ADD, { "ADD", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::SUB, { "SUB", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::MUL, { "MUL", 0, 2, 1, false, Tier::Low } }, - { Instruction::DIV, { "DIV", 0, 2, 1, false, Tier::Low } }, - { Instruction::SDIV, { "SDIV", 0, 2, 1, false, Tier::Low } }, - { Instruction::MOD, { "MOD", 0, 2, 1, false, Tier::Low } }, - { Instruction::SMOD, { "SMOD", 0, 2, 1, false, Tier::Low } }, - { Instruction::EXP, { "EXP", 0, 2, 1, false, Tier::Special } }, - { Instruction::NOT, { "NOT", 0, 1, 1, false, Tier::VeryLow } }, - { Instruction::LT, { "LT", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::GT, { "GT", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::SLT, { "SLT", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::SGT, { "SGT", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::EQ, { "EQ", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::ISZERO, { "ISZERO", 0, 1, 1, false, Tier::VeryLow } }, - { Instruction::AND, { "AND", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::OR, { "OR", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::XOR, { "XOR", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::BYTE, { "BYTE", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::SHL, { "SHL", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::SHR, { "SHR", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::SAR, { "SAR", 0, 2, 1, false, Tier::VeryLow } }, - { Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false, Tier::Mid } }, - { Instruction::MULMOD, { "MULMOD", 0, 3, 1, false, Tier::Mid } }, - { Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false, Tier::Low } }, - { Instruction::KECCAK256, { "KECCAK256", 0, 2, 1, true, Tier::Special } }, - { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1, false, Tier::Base } }, - { Instruction::BALANCE, { "BALANCE", 0, 1, 1, false, Tier::Special } }, - { Instruction::ORIGIN, { "ORIGIN", 0, 0, 1, false, Tier::Base } }, - { Instruction::CALLER, { "CALLER", 0, 0, 1, false, Tier::Base } }, - { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1, false, Tier::Base } }, - { Instruction::CALLDATALOAD,{ "CALLDATALOAD", 0, 1, 1, false, Tier::VeryLow } }, - { Instruction::CALLDATASIZE,{ "CALLDATASIZE", 0, 0, 1, false, Tier::Base } }, - { Instruction::CALLDATACOPY,{ "CALLDATACOPY", 0, 3, 0, true, Tier::VeryLow } }, - { Instruction::CODESIZE, { "CODESIZE", 0, 0, 1, false, Tier::Base } }, - { Instruction::CODECOPY, { "CODECOPY", 0, 3, 0, true, Tier::VeryLow } }, - { Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false, Tier::Base } }, - { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false, Tier::Special } }, - { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true, Tier::Special } }, - { Instruction::RETURNDATASIZE, {"RETURNDATASIZE", 0, 0, 1, false, Tier::Base } }, - { Instruction::RETURNDATACOPY, {"RETURNDATACOPY", 0, 3, 0, true, Tier::VeryLow } }, - { Instruction::MCOPY, { "MCOPY", 0, 3, 0, true, Tier::VeryLow } }, - { Instruction::EXTCODEHASH, { "EXTCODEHASH", 0, 1, 1, false, Tier::Special } }, - { Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, Tier::BlockHash } }, - { Instruction::BLOBHASH, { "BLOBHASH", 0, 1, 1, false, Tier::VeryLow } }, - { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } }, - { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, Tier::Base } }, - { Instruction::NUMBER, { "NUMBER", 0, 0, 1, false, Tier::Base } }, - { Instruction::PREVRANDAO, { "PREVRANDAO", 0, 0, 1, false, Tier::Base } }, - { Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false, Tier::Base } }, - { Instruction::CHAINID, { "CHAINID", 0, 0, 1, false, Tier::Base } }, - { Instruction::SELFBALANCE, { "SELFBALANCE", 0, 0, 1, false, Tier::Low } }, - { Instruction::BASEFEE, { "BASEFEE", 0, 0, 1, false, Tier::Base } }, - { Instruction::BLOBBASEFEE, { "BLOBBASEFEE", 0, 0, 1, false, Tier::Base } }, - { Instruction::POP, { "POP", 0, 1, 0, false, Tier::Base } }, - { Instruction::MLOAD, { "MLOAD", 0, 1, 1, true, Tier::VeryLow } }, - { Instruction::MSTORE, { "MSTORE", 0, 2, 0, true, Tier::VeryLow } }, - { Instruction::MSTORE8, { "MSTORE8", 0, 2, 0, true, Tier::VeryLow } }, - { Instruction::SLOAD, { "SLOAD", 0, 1, 1, false, Tier::Special } }, - { Instruction::SSTORE, { "SSTORE", 0, 2, 0, true, Tier::Special } }, - { Instruction::TLOAD, { "TLOAD", 0, 1, 1, false, Tier::WarmAccess} }, - { Instruction::TSTORE, { "TSTORE", 0, 2, 0, true, Tier::WarmAccess} }, - { Instruction::JUMP, { "JUMP", 0, 1, 0, true, Tier::Mid } }, - { Instruction::JUMPI, { "JUMPI", 0, 2, 0, true, Tier::High } }, - { Instruction::PC, { "PC", 0, 0, 1, false, Tier::Base } }, - { Instruction::MSIZE, { "MSIZE", 0, 0, 1, false, Tier::Base } }, - { Instruction::GAS, { "GAS", 0, 0, 1, false, Tier::Base } }, - { Instruction::JUMPDEST, { "JUMPDEST", 0, 0, 0, true, Tier::Special } }, - { Instruction::PUSH0, { "PUSH0", 0, 0, 1, false, Tier::Base } }, - { Instruction::PUSH1, { "PUSH1", 1, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH2, { "PUSH2", 2, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH3, { "PUSH3", 3, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH4, { "PUSH4", 4, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH5, { "PUSH5", 5, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH6, { "PUSH6", 6, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH7, { "PUSH7", 7, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH8, { "PUSH8", 8, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH9, { "PUSH9", 9, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH10, { "PUSH10", 10, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH11, { "PUSH11", 11, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH12, { "PUSH12", 12, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH13, { "PUSH13", 13, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH14, { "PUSH14", 14, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH15, { "PUSH15", 15, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH16, { "PUSH16", 16, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH17, { "PUSH17", 17, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH18, { "PUSH18", 18, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH19, { "PUSH19", 19, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH20, { "PUSH20", 20, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH21, { "PUSH21", 21, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH22, { "PUSH22", 22, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH23, { "PUSH23", 23, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH24, { "PUSH24", 24, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH25, { "PUSH25", 25, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH26, { "PUSH26", 26, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH27, { "PUSH27", 27, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH28, { "PUSH28", 28, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH29, { "PUSH29", 29, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH30, { "PUSH30", 30, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH31, { "PUSH31", 31, 0, 1, false, Tier::VeryLow } }, - { Instruction::PUSH32, { "PUSH32", 32, 0, 1, false, Tier::VeryLow } }, - { Instruction::DUP1, { "DUP1", 0, 1, 2, false, Tier::VeryLow } }, - { Instruction::DUP2, { "DUP2", 0, 2, 3, false, Tier::VeryLow } }, - { Instruction::DUP3, { "DUP3", 0, 3, 4, false, Tier::VeryLow } }, - { Instruction::DUP4, { "DUP4", 0, 4, 5, false, Tier::VeryLow } }, - { Instruction::DUP5, { "DUP5", 0, 5, 6, false, Tier::VeryLow } }, - { Instruction::DUP6, { "DUP6", 0, 6, 7, false, Tier::VeryLow } }, - { Instruction::DUP7, { "DUP7", 0, 7, 8, false, Tier::VeryLow } }, - { Instruction::DUP8, { "DUP8", 0, 8, 9, false, Tier::VeryLow } }, - { Instruction::DUP9, { "DUP9", 0, 9, 10, false, Tier::VeryLow } }, - { Instruction::DUP10, { "DUP10", 0, 10, 11, false, Tier::VeryLow } }, - { Instruction::DUP11, { "DUP11", 0, 11, 12, false, Tier::VeryLow } }, - { Instruction::DUP12, { "DUP12", 0, 12, 13, false, Tier::VeryLow } }, - { Instruction::DUP13, { "DUP13", 0, 13, 14, false, Tier::VeryLow } }, - { Instruction::DUP14, { "DUP14", 0, 14, 15, false, Tier::VeryLow } }, - { Instruction::DUP15, { "DUP15", 0, 15, 16, false, Tier::VeryLow } }, - { Instruction::DUP16, { "DUP16", 0, 16, 17, false, Tier::VeryLow } }, - { Instruction::SWAP1, { "SWAP1", 0, 2, 2, false, Tier::VeryLow } }, - { Instruction::SWAP2, { "SWAP2", 0, 3, 3, false, Tier::VeryLow } }, - { Instruction::SWAP3, { "SWAP3", 0, 4, 4, false, Tier::VeryLow } }, - { Instruction::SWAP4, { "SWAP4", 0, 5, 5, false, Tier::VeryLow } }, - { Instruction::SWAP5, { "SWAP5", 0, 6, 6, false, Tier::VeryLow } }, - { Instruction::SWAP6, { "SWAP6", 0, 7, 7, false, Tier::VeryLow } }, - { Instruction::SWAP7, { "SWAP7", 0, 8, 8, false, Tier::VeryLow } }, - { Instruction::SWAP8, { "SWAP8", 0, 9, 9, false, Tier::VeryLow } }, - { Instruction::SWAP9, { "SWAP9", 0, 10, 10, false, Tier::VeryLow } }, - { Instruction::SWAP10, { "SWAP10", 0, 11, 11, false, Tier::VeryLow } }, - { Instruction::SWAP11, { "SWAP11", 0, 12, 12, false, Tier::VeryLow } }, - { Instruction::SWAP12, { "SWAP12", 0, 13, 13, false, Tier::VeryLow } }, - { Instruction::SWAP13, { "SWAP13", 0, 14, 14, false, Tier::VeryLow } }, - { Instruction::SWAP14, { "SWAP14", 0, 15, 15, false, Tier::VeryLow } }, - { Instruction::SWAP15, { "SWAP15", 0, 16, 16, false, Tier::VeryLow } }, - { Instruction::SWAP16, { "SWAP16", 0, 17, 17, false, Tier::VeryLow } }, - { Instruction::LOG0, { "LOG0", 0, 2, 0, true, Tier::Special } }, - { Instruction::LOG1, { "LOG1", 0, 3, 0, true, Tier::Special } }, - { Instruction::LOG2, { "LOG2", 0, 4, 0, true, Tier::Special } }, - { Instruction::LOG3, { "LOG3", 0, 5, 0, true, Tier::Special } }, - { Instruction::LOG4, { "LOG4", 0, 6, 0, true, Tier::Special } }, - { Instruction::CREATE, { "CREATE", 0, 3, 1, true, Tier::Special } }, - { Instruction::CALL, { "CALL", 0, 7, 1, true, Tier::Special } }, - { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, Tier::Special } }, - { Instruction::RETURN, { "RETURN", 0, 2, 0, true, Tier::Zero } }, - { Instruction::DELEGATECALL, { "DELEGATECALL", 0, 6, 1, true, Tier::Special } }, - { Instruction::STATICCALL, { "STATICCALL", 0, 6, 1, true, Tier::Special } }, - { Instruction::CREATE2, { "CREATE2", 0, 4, 1, true, Tier::Special } }, - { Instruction::REVERT, { "REVERT", 0, 2, 0, true, Tier::Zero } }, - { Instruction::INVALID, { "INVALID", 0, 0, 0, true, Tier::Zero } }, - { Instruction::SELFDESTRUCT, { "SELFDESTRUCT", 0, 1, 0, true, Tier::Special } } +{ // Add Args Ret SideEffects GasPriceTier + {Instruction::STOP, {"STOP", 0, 0, 0, true, Tier::Zero}}, + {Instruction::ADD, {"ADD", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::SUB, {"SUB", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::MUL, {"MUL", 0, 2, 1, false, Tier::Low}}, + {Instruction::DIV, {"DIV", 0, 2, 1, false, Tier::Low}}, + {Instruction::SDIV, {"SDIV", 0, 2, 1, false, Tier::Low}}, + {Instruction::MOD, {"MOD", 0, 2, 1, false, Tier::Low}}, + {Instruction::SMOD, {"SMOD", 0, 2, 1, false, Tier::Low}}, + {Instruction::EXP, {"EXP", 0, 2, 1, false, Tier::Special}}, + {Instruction::NOT, {"NOT", 0, 1, 1, false, Tier::VeryLow}}, + {Instruction::LT, {"LT", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::GT, {"GT", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::SLT, {"SLT", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::SGT, {"SGT", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::EQ, {"EQ", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::ISZERO, {"ISZERO", 0, 1, 1, false, Tier::VeryLow}}, + {Instruction::AND, {"AND", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::OR, {"OR", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::XOR, {"XOR", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::BYTE, {"BYTE", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::SHL, {"SHL", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::SHR, {"SHR", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::SAR, {"SAR", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::ADDMOD, {"ADDMOD", 0, 3, 1, false, Tier::Mid}}, + {Instruction::MULMOD, {"MULMOD", 0, 3, 1, false, Tier::Mid}}, + {Instruction::SIGNEXTEND, {"SIGNEXTEND", 0, 2, 1, false, Tier::Low}}, + {Instruction::KECCAK256, {"KECCAK256", 0, 2, 1, true, Tier::Special}}, + {Instruction::ADDRESS, {"ADDRESS", 0, 0, 1, false, Tier::Base}}, + {Instruction::BALANCE, {"BALANCE", 0, 1, 1, false, Tier::Special}}, + {Instruction::ORIGIN, {"ORIGIN", 0, 0, 1, false, Tier::Base}}, + {Instruction::CALLER, {"CALLER", 0, 0, 1, false, Tier::Base}}, + {Instruction::CALLVALUE, {"CALLVALUE", 0, 0, 1, false, Tier::Base}}, + {Instruction::CALLDATALOAD, {"CALLDATALOAD", 0, 1, 1, false, Tier::VeryLow}}, + {Instruction::CALLDATASIZE, {"CALLDATASIZE", 0, 0, 1, false, Tier::Base}}, + {Instruction::CALLDATACOPY, {"CALLDATACOPY", 0, 3, 0, true, Tier::VeryLow}}, + {Instruction::CODESIZE, {"CODESIZE", 0, 0, 1, false, Tier::Base}}, + {Instruction::CODECOPY, {"CODECOPY", 0, 3, 0, true, Tier::VeryLow}}, + {Instruction::GASPRICE, {"GASPRICE", 0, 0, 1, false, Tier::Base}}, + {Instruction::EXTCODESIZE, {"EXTCODESIZE", 0, 1, 1, false, Tier::Special}}, + {Instruction::EXTCODECOPY, {"EXTCODECOPY", 0, 4, 0, true, Tier::Special}}, + {Instruction::RETURNDATASIZE, {"RETURNDATASIZE", 0, 0, 1, false, Tier::Base}}, + {Instruction::RETURNDATACOPY, {"RETURNDATACOPY", 0, 3, 0, true, Tier::VeryLow}}, + {Instruction::MCOPY, {"MCOPY", 0, 3, 0, true, Tier::VeryLow}}, + {Instruction::EXTCODEHASH, {"EXTCODEHASH", 0, 1, 1, false, Tier::Special}}, + {Instruction::BLOCKHASH, {"BLOCKHASH", 0, 1, 1, false, Tier::BlockHash}}, + {Instruction::BLOBHASH, {"BLOBHASH", 0, 1, 1, false, Tier::VeryLow}}, + {Instruction::COINBASE, {"COINBASE", 0, 0, 1, false, Tier::Base}}, + {Instruction::TIMESTAMP, {"TIMESTAMP", 0, 0, 1, false, Tier::Base}}, + {Instruction::NUMBER, {"NUMBER", 0, 0, 1, false, Tier::Base}}, + {Instruction::PREVRANDAO, {"PREVRANDAO", 0, 0, 1, false, Tier::Base}}, + {Instruction::GASLIMIT, {"GASLIMIT", 0, 0, 1, false, Tier::Base}}, + {Instruction::CHAINID, {"CHAINID", 0, 0, 1, false, Tier::Base}}, + {Instruction::SELFBALANCE, {"SELFBALANCE", 0, 0, 1, false, Tier::Low}}, + {Instruction::BASEFEE, {"BASEFEE", 0, 0, 1, false, Tier::Base}}, + {Instruction::BLOBBASEFEE, {"BLOBBASEFEE", 0, 0, 1, false, Tier::Base}}, + {Instruction::POP, {"POP", 0, 1, 0, false, Tier::Base}}, + {Instruction::MLOAD, {"MLOAD", 0, 1, 1, true, Tier::VeryLow}}, + {Instruction::MSTORE, {"MSTORE", 0, 2, 0, true, Tier::VeryLow}}, + {Instruction::MSTORE8, {"MSTORE8", 0, 2, 0, true, Tier::VeryLow}}, + {Instruction::SLOAD, {"SLOAD", 0, 1, 1, false, Tier::Special}}, + {Instruction::SSTORE, {"SSTORE", 0, 2, 0, true, Tier::Special}}, + {Instruction::TLOAD, {"TLOAD", 0, 1, 1, false, Tier::WarmAccess}}, + {Instruction::TSTORE, {"TSTORE", 0, 2, 0, true, Tier::WarmAccess}}, + {Instruction::JUMP, {"JUMP", 0, 1, 0, true, Tier::Mid}}, + {Instruction::JUMPI, {"JUMPI", 0, 2, 0, true, Tier::High}}, + {Instruction::PC, {"PC", 0, 0, 1, false, Tier::Base}}, + {Instruction::MSIZE, {"MSIZE", 0, 0, 1, false, Tier::Base}}, + {Instruction::GAS, {"GAS", 0, 0, 1, false, Tier::Base}}, + {Instruction::JUMPDEST, {"JUMPDEST", 0, 0, 0, true, Tier::Special}}, + {Instruction::PUSH0, {"PUSH0", 0, 0, 1, false, Tier::Base}}, + {Instruction::PUSH1, {"PUSH1", 1, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH2, {"PUSH2", 2, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH3, {"PUSH3", 3, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH4, {"PUSH4", 4, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH5, {"PUSH5", 5, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH6, {"PUSH6", 6, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH7, {"PUSH7", 7, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH8, {"PUSH8", 8, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH9, {"PUSH9", 9, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH10, {"PUSH10", 10, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH11, {"PUSH11", 11, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH12, {"PUSH12", 12, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH13, {"PUSH13", 13, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH14, {"PUSH14", 14, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH15, {"PUSH15", 15, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH16, {"PUSH16", 16, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH17, {"PUSH17", 17, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH18, {"PUSH18", 18, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH19, {"PUSH19", 19, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH20, {"PUSH20", 20, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH21, {"PUSH21", 21, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH22, {"PUSH22", 22, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH23, {"PUSH23", 23, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH24, {"PUSH24", 24, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH25, {"PUSH25", 25, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH26, {"PUSH26", 26, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH27, {"PUSH27", 27, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH28, {"PUSH28", 28, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH29, {"PUSH29", 29, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH30, {"PUSH30", 30, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH31, {"PUSH31", 31, 0, 1, false, Tier::VeryLow}}, + {Instruction::PUSH32, {"PUSH32", 32, 0, 1, false, Tier::VeryLow}}, + {Instruction::DUP1, {"DUP1", 0, 1, 2, false, Tier::VeryLow}}, + {Instruction::DUP2, {"DUP2", 0, 2, 3, false, Tier::VeryLow}}, + {Instruction::DUP3, {"DUP3", 0, 3, 4, false, Tier::VeryLow}}, + {Instruction::DUP4, {"DUP4", 0, 4, 5, false, Tier::VeryLow}}, + {Instruction::DUP5, {"DUP5", 0, 5, 6, false, Tier::VeryLow}}, + {Instruction::DUP6, {"DUP6", 0, 6, 7, false, Tier::VeryLow}}, + {Instruction::DUP7, {"DUP7", 0, 7, 8, false, Tier::VeryLow}}, + {Instruction::DUP8, {"DUP8", 0, 8, 9, false, Tier::VeryLow}}, + {Instruction::DUP9, {"DUP9", 0, 9, 10, false, Tier::VeryLow}}, + {Instruction::DUP10, {"DUP10", 0, 10, 11, false, Tier::VeryLow}}, + {Instruction::DUP11, {"DUP11", 0, 11, 12, false, Tier::VeryLow}}, + {Instruction::DUP12, {"DUP12", 0, 12, 13, false, Tier::VeryLow}}, + {Instruction::DUP13, {"DUP13", 0, 13, 14, false, Tier::VeryLow}}, + {Instruction::DUP14, {"DUP14", 0, 14, 15, false, Tier::VeryLow}}, + {Instruction::DUP15, {"DUP15", 0, 15, 16, false, Tier::VeryLow}}, + {Instruction::DUP16, {"DUP16", 0, 16, 17, false, Tier::VeryLow}}, + {Instruction::SWAP1, {"SWAP1", 0, 2, 2, false, Tier::VeryLow}}, + {Instruction::SWAP2, {"SWAP2", 0, 3, 3, false, Tier::VeryLow}}, + {Instruction::SWAP3, {"SWAP3", 0, 4, 4, false, Tier::VeryLow}}, + {Instruction::SWAP4, {"SWAP4", 0, 5, 5, false, Tier::VeryLow}}, + {Instruction::SWAP5, {"SWAP5", 0, 6, 6, false, Tier::VeryLow}}, + {Instruction::SWAP6, {"SWAP6", 0, 7, 7, false, Tier::VeryLow}}, + {Instruction::SWAP7, {"SWAP7", 0, 8, 8, false, Tier::VeryLow}}, + {Instruction::SWAP8, {"SWAP8", 0, 9, 9, false, Tier::VeryLow}}, + {Instruction::SWAP9, {"SWAP9", 0, 10, 10, false, Tier::VeryLow}}, + {Instruction::SWAP10, {"SWAP10", 0, 11, 11, false, Tier::VeryLow}}, + {Instruction::SWAP11, {"SWAP11", 0, 12, 12, false, Tier::VeryLow}}, + {Instruction::SWAP12, {"SWAP12", 0, 13, 13, false, Tier::VeryLow}}, + {Instruction::SWAP13, {"SWAP13", 0, 14, 14, false, Tier::VeryLow}}, + {Instruction::SWAP14, {"SWAP14", 0, 15, 15, false, Tier::VeryLow}}, + {Instruction::SWAP15, {"SWAP15", 0, 16, 16, false, Tier::VeryLow}}, + {Instruction::SWAP16, {"SWAP16", 0, 17, 17, false, Tier::VeryLow}}, + {Instruction::LOG0, {"LOG0", 0, 2, 0, true, Tier::Special}}, + {Instruction::LOG1, {"LOG1", 0, 3, 0, true, Tier::Special}}, + {Instruction::LOG2, {"LOG2", 0, 4, 0, true, Tier::Special}}, + {Instruction::LOG3, {"LOG3", 0, 5, 0, true, Tier::Special}}, + {Instruction::LOG4, {"LOG4", 0, 6, 0, true, Tier::Special}}, + {Instruction::CREATE, {"CREATE", 0, 3, 1, true, Tier::Special}}, + {Instruction::CALL, {"CALL", 0, 7, 1, true, Tier::Special}}, + {Instruction::CALLCODE, {"CALLCODE", 0, 7, 1, true, Tier::Special}}, + {Instruction::RETURN, {"RETURN", 0, 2, 0, true, Tier::Zero}}, + {Instruction::DELEGATECALL, {"DELEGATECALL", 0, 6, 1, true, Tier::Special}}, + {Instruction::STATICCALL, {"STATICCALL", 0, 6, 1, true, Tier::Special}}, + {Instruction::CREATE2, {"CREATE2", 0, 4, 1, true, Tier::Special}}, + {Instruction::REVERT, {"REVERT", 0, 2, 0, true, Tier::Zero}}, + {Instruction::INVALID, {"INVALID", 0, 0, 0, true, Tier::Zero}}, + {Instruction::SELFDESTRUCT, {"SELFDESTRUCT", 0, 1, 0, true, Tier::Special}} }; InstructionInfo solidity::evmasm::instructionInfo(Instruction _inst, langutil::EVMVersion _evmVersion) diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 289469b5e..f89c72c89 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -33,167 +33,167 @@ namespace solidity::evmasm /// Virtual machine bytecode instruction. enum class Instruction: uint8_t { - STOP = 0x00, ///< halts execution - ADD, ///< addition operation - MUL, ///< multiplication operation - SUB, ///< subtraction operation - DIV, ///< integer division operation - SDIV, ///< signed integer division operation - MOD, ///< modulo remainder operation - SMOD, ///< signed modulo remainder operation - ADDMOD, ///< unsigned modular addition - MULMOD, ///< unsigned modular multiplication - EXP, ///< exponential operation - SIGNEXTEND, ///< extend length of signed integer - - LT = 0x10, ///< less-than comparison - GT, ///< greater-than comparison - SLT, ///< signed less-than comparison - SGT, ///< signed greater-than comparison - EQ, ///< equality comparison - ISZERO, ///< simple not operator - AND, ///< bitwise AND operation - OR, ///< bitwise OR operation - XOR, ///< bitwise XOR operation - NOT, ///< bitwise NOT operation - BYTE, ///< retrieve single byte from word - SHL, ///< bitwise SHL operation - SHR, ///< bitwise SHR operation - SAR, ///< bitwise SAR operation - - KECCAK256 = 0x20, ///< compute KECCAK-256 hash - - ADDRESS = 0x30, ///< get address of currently executing account - BALANCE, ///< get balance of the given account - ORIGIN, ///< get execution origination address - CALLER, ///< get caller address - CALLVALUE, ///< get deposited value by the instruction/transaction responsible for this execution - CALLDATALOAD, ///< get input data of current environment - CALLDATASIZE, ///< get size of input data in current environment - CALLDATACOPY, ///< copy input data in current environment to memory - CODESIZE, ///< get size of code running in current environment - CODECOPY, ///< copy code running in current environment to memory - GASPRICE, ///< get price of gas in current environment - EXTCODESIZE, ///< get external code size (from another contract) - EXTCODECOPY, ///< copy external code (from another contract) - RETURNDATASIZE = 0x3d, ///< get size of return data buffer - RETURNDATACOPY = 0x3e, ///< copy return data in current environment to memory - EXTCODEHASH = 0x3f, ///< get external code hash (from another contract) - - BLOCKHASH = 0x40, ///< get hash of most recent complete block - COINBASE, ///< get the block's coinbase address - TIMESTAMP, ///< get the block's timestamp - NUMBER, ///< get the block's number - PREVRANDAO, ///< get randomness provided by the beacon chain - GASLIMIT, ///< get the block's gas limit - CHAINID, ///< get the config's chainid param - SELFBALANCE, ///< get balance of the current account - BASEFEE, ///< get the block's basefee - BLOBHASH = 0x49, ///< get a versioned hash of one of the blobs associated with the transaction - BLOBBASEFEE = 0x4a, ///< get the block's blob basefee - - POP = 0x50, ///< remove item from stack - MLOAD, ///< load word from memory - MSTORE, ///< save word to memory - MSTORE8, ///< save byte to memory - SLOAD, ///< load word from storage - SSTORE, ///< save word to storage - JUMP, ///< alter the program counter - JUMPI, ///< conditionally alter the program counter - PC, ///< get the program counter - MSIZE, ///< get the size of active memory - GAS, ///< get the amount of available gas - JUMPDEST, ///< set a potential jump destination - MCOPY = 0x5e, ///< copy between memory areas - - TLOAD = 0x5c, ///< load word from transient storage - TSTORE = 0x5d, ///< save word to transient storage - - PUSH0 = 0x5f, ///< place the value 0 on stack - PUSH1 = 0x60, ///< place 1 byte item on stack - PUSH2, ///< place 2 byte item on stack - PUSH3, ///< place 3 byte item on stack - PUSH4, ///< place 4 byte item on stack - PUSH5, ///< place 5 byte item on stack - PUSH6, ///< place 6 byte item on stack - PUSH7, ///< place 7 byte item on stack - PUSH8, ///< place 8 byte item on stack - PUSH9, ///< place 9 byte item on stack - PUSH10, ///< place 10 byte item on stack - PUSH11, ///< place 11 byte item on stack - PUSH12, ///< place 12 byte item on stack - PUSH13, ///< place 13 byte item on stack - PUSH14, ///< place 14 byte item on stack - PUSH15, ///< place 15 byte item on stack - PUSH16, ///< place 16 byte item on stack - PUSH17, ///< place 17 byte item on stack - PUSH18, ///< place 18 byte item on stack - PUSH19, ///< place 19 byte item on stack - PUSH20, ///< place 20 byte item on stack - PUSH21, ///< place 21 byte item on stack - PUSH22, ///< place 22 byte item on stack - PUSH23, ///< place 23 byte item on stack - PUSH24, ///< place 24 byte item on stack - PUSH25, ///< place 25 byte item on stack - PUSH26, ///< place 26 byte item on stack - PUSH27, ///< place 27 byte item on stack - PUSH28, ///< place 28 byte item on stack - PUSH29, ///< place 29 byte item on stack - PUSH30, ///< place 30 byte item on stack - PUSH31, ///< place 31 byte item on stack - PUSH32, ///< place 32 byte item on stack - - DUP1 = 0x80, ///< copies the highest item in the stack to the top of the stack - DUP2, ///< copies the second highest item in the stack to the top of the stack - DUP3, ///< copies the third highest item in the stack to the top of the stack - DUP4, ///< copies the 4th highest item in the stack to the top of the stack - DUP5, ///< copies the 5th highest item in the stack to the top of the stack - DUP6, ///< copies the 6th highest item in the stack to the top of the stack - DUP7, ///< copies the 7th highest item in the stack to the top of the stack - DUP8, ///< copies the 8th highest item in the stack to the top of the stack - DUP9, ///< copies the 9th highest item in the stack to the top of the stack - DUP10, ///< copies the 10th highest item in the stack to the top of the stack - DUP11, ///< copies the 11th highest item in the stack to the top of the stack - DUP12, ///< copies the 12th highest item in the stack to the top of the stack - DUP13, ///< copies the 13th highest item in the stack to the top of the stack - DUP14, ///< copies the 14th highest item in the stack to the top of the stack - DUP15, ///< copies the 15th highest item in the stack to the top of the stack - DUP16, ///< copies the 16th highest item in the stack to the top of the stack - - SWAP1 = 0x90, ///< swaps the highest and second highest value on the stack - SWAP2, ///< swaps the highest and third highest value on the stack - SWAP3, ///< swaps the highest and 4th highest value on the stack - SWAP4, ///< swaps the highest and 5th highest value on the stack - SWAP5, ///< swaps the highest and 6th highest value on the stack - SWAP6, ///< swaps the highest and 7th highest value on the stack - SWAP7, ///< swaps the highest and 8th highest value on the stack - SWAP8, ///< swaps the highest and 9th highest value on the stack - SWAP9, ///< swaps the highest and 10th highest value on the stack - SWAP10, ///< swaps the highest and 11th highest value on the stack - SWAP11, ///< swaps the highest and 12th highest value on the stack - SWAP12, ///< swaps the highest and 13th highest value on the stack - SWAP13, ///< swaps the highest and 14th highest value on the stack - SWAP14, ///< swaps the highest and 15th highest value on the stack - SWAP15, ///< swaps the highest and 16th highest value on the stack - SWAP16, ///< swaps the highest and 17th highest value on the stack - - LOG0 = 0xa0, ///< Makes a log entry; no topics. - LOG1, ///< Makes a log entry; 1 topic. - LOG2, ///< Makes a log entry; 2 topics. - LOG3, ///< Makes a log entry; 3 topics. - LOG4, ///< Makes a log entry; 4 topics. - - CREATE = 0xf0, ///< create a new account with associated code - CALL, ///< message-call into an account - CALLCODE, ///< message-call with another account's code only - RETURN, ///< halt execution returning output data - DELEGATECALL, ///< like CALLCODE but keeps caller's value and sender - CREATE2 = 0xf5, ///< create new account with associated code at address `sha3(0xff + sender + salt + init code) % 2**160` - STATICCALL = 0xfa, ///< like CALL but disallow state modifications - - REVERT = 0xfd, ///< halt execution, revert state and return output data - INVALID = 0xfe, ///< invalid instruction for expressing runtime errors (e.g., division-by-zero) - SELFDESTRUCT = 0xff ///< halt execution and register account for later deletion + STOP = 0x00, ///< halts execution + ADD, ///< addition operation + MUL, ///< multiplication operation + SUB, ///< subtraction operation + DIV, ///< integer division operation + SDIV, ///< signed integer division operation + MOD, ///< modulo remainder operation + SMOD, ///< signed modulo remainder operation + ADDMOD, ///< unsigned modular addition + MULMOD, ///< unsigned modular multiplication + EXP, ///< exponential operation + SIGNEXTEND, ///< extend length of signed integer + + LT = 0x10, ///< less-than comparison + GT, ///< greater-than comparison + SLT, ///< signed less-than comparison + SGT, ///< signed greater-than comparison + EQ, ///< equality comparison + ISZERO, ///< simple not operator + AND, ///< bitwise AND operation + OR, ///< bitwise OR operation + XOR, ///< bitwise XOR operation + NOT, ///< bitwise NOT operation + BYTE, ///< retrieve single byte from word + SHL, ///< bitwise SHL operation + SHR, ///< bitwise SHR operation + SAR, ///< bitwise SAR operation + + KECCAK256 = 0x20, ///< compute KECCAK-256 hash + + ADDRESS = 0x30, ///< get address of currently executing account + BALANCE, ///< get balance of the given account + ORIGIN, ///< get execution origination address + CALLER, ///< get caller address + CALLVALUE, ///< get deposited value by the instruction/transaction responsible for this execution + CALLDATALOAD, ///< get input data of current environment + CALLDATASIZE, ///< get size of input data in current environment + CALLDATACOPY, ///< copy input data in current environment to memory + CODESIZE, ///< get size of code running in current environment + CODECOPY, ///< copy code running in current environment to memory + GASPRICE, ///< get price of gas in current environment + EXTCODESIZE, ///< get external code size (from another contract) + EXTCODECOPY, ///< copy external code (from another contract) + RETURNDATASIZE = 0x3d, ///< get size of return data buffer + RETURNDATACOPY = 0x3e, ///< copy return data in current environment to memory + EXTCODEHASH = 0x3f, ///< get external code hash (from another contract) + + BLOCKHASH = 0x40, ///< get hash of most recent complete block + COINBASE, ///< get the block's coinbase address + TIMESTAMP, ///< get the block's timestamp + NUMBER, ///< get the block's number + PREVRANDAO, ///< get randomness provided by the beacon chain + GASLIMIT, ///< get the block's gas limit + CHAINID, ///< get the config's chainid param + SELFBALANCE, ///< get balance of the current account + BASEFEE, ///< get the block's basefee + BLOBHASH = 0x49, ///< get a versioned hash of one of the blobs associated with the transaction + BLOBBASEFEE = 0x4a, ///< get the block's blob basefee + + POP = 0x50, ///< remove item from stack + MLOAD, ///< load word from memory + MSTORE, ///< save word to memory + MSTORE8, ///< save byte to memory + SLOAD, ///< load word from storage + SSTORE, ///< save word to storage + JUMP, ///< alter the program counter + JUMPI, ///< conditionally alter the program counter + PC, ///< get the program counter + MSIZE, ///< get the size of active memory + GAS, ///< get the amount of available gas + JUMPDEST, ///< set a potential jump destination + MCOPY = 0x5e, ///< copy between memory areas + + TLOAD = 0x5c, ///< load word from transient storage + TSTORE = 0x5d, ///< save word to transient storage + + PUSH0 = 0x5f, ///< place the value 0 on stack + PUSH1 = 0x60, ///< place 1 byte item on stack + PUSH2, ///< place 2 byte item on stack + PUSH3, ///< place 3 byte item on stack + PUSH4, ///< place 4 byte item on stack + PUSH5, ///< place 5 byte item on stack + PUSH6, ///< place 6 byte item on stack + PUSH7, ///< place 7 byte item on stack + PUSH8, ///< place 8 byte item on stack + PUSH9, ///< place 9 byte item on stack + PUSH10, ///< place 10 byte item on stack + PUSH11, ///< place 11 byte item on stack + PUSH12, ///< place 12 byte item on stack + PUSH13, ///< place 13 byte item on stack + PUSH14, ///< place 14 byte item on stack + PUSH15, ///< place 15 byte item on stack + PUSH16, ///< place 16 byte item on stack + PUSH17, ///< place 17 byte item on stack + PUSH18, ///< place 18 byte item on stack + PUSH19, ///< place 19 byte item on stack + PUSH20, ///< place 20 byte item on stack + PUSH21, ///< place 21 byte item on stack + PUSH22, ///< place 22 byte item on stack + PUSH23, ///< place 23 byte item on stack + PUSH24, ///< place 24 byte item on stack + PUSH25, ///< place 25 byte item on stack + PUSH26, ///< place 26 byte item on stack + PUSH27, ///< place 27 byte item on stack + PUSH28, ///< place 28 byte item on stack + PUSH29, ///< place 29 byte item on stack + PUSH30, ///< place 30 byte item on stack + PUSH31, ///< place 31 byte item on stack + PUSH32, ///< place 32 byte item on stack + + DUP1 = 0x80, ///< copies the highest item in the stack to the top of the stack + DUP2, ///< copies the second highest item in the stack to the top of the stack + DUP3, ///< copies the third highest item in the stack to the top of the stack + DUP4, ///< copies the 4th highest item in the stack to the top of the stack + DUP5, ///< copies the 5th highest item in the stack to the top of the stack + DUP6, ///< copies the 6th highest item in the stack to the top of the stack + DUP7, ///< copies the 7th highest item in the stack to the top of the stack + DUP8, ///< copies the 8th highest item in the stack to the top of the stack + DUP9, ///< copies the 9th highest item in the stack to the top of the stack + DUP10, ///< copies the 10th highest item in the stack to the top of the stack + DUP11, ///< copies the 11th highest item in the stack to the top of the stack + DUP12, ///< copies the 12th highest item in the stack to the top of the stack + DUP13, ///< copies the 13th highest item in the stack to the top of the stack + DUP14, ///< copies the 14th highest item in the stack to the top of the stack + DUP15, ///< copies the 15th highest item in the stack to the top of the stack + DUP16, ///< copies the 16th highest item in the stack to the top of the stack + + SWAP1 = 0x90, ///< swaps the highest and second highest value on the stack + SWAP2, ///< swaps the highest and third highest value on the stack + SWAP3, ///< swaps the highest and 4th highest value on the stack + SWAP4, ///< swaps the highest and 5th highest value on the stack + SWAP5, ///< swaps the highest and 6th highest value on the stack + SWAP6, ///< swaps the highest and 7th highest value on the stack + SWAP7, ///< swaps the highest and 8th highest value on the stack + SWAP8, ///< swaps the highest and 9th highest value on the stack + SWAP9, ///< swaps the highest and 10th highest value on the stack + SWAP10, ///< swaps the highest and 11th highest value on the stack + SWAP11, ///< swaps the highest and 12th highest value on the stack + SWAP12, ///< swaps the highest and 13th highest value on the stack + SWAP13, ///< swaps the highest and 14th highest value on the stack + SWAP14, ///< swaps the highest and 15th highest value on the stack + SWAP15, ///< swaps the highest and 16th highest value on the stack + SWAP16, ///< swaps the highest and 17th highest value on the stack + + LOG0 = 0xa0, ///< Makes a log entry; no topics. + LOG1, ///< Makes a log entry; 1 topic. + LOG2, ///< Makes a log entry; 2 topics. + LOG3, ///< Makes a log entry; 3 topics. + LOG4, ///< Makes a log entry; 4 topics. + + CREATE = 0xf0, ///< create a new account with associated code + CALL, ///< message-call into an account + CALLCODE, ///< message-call with another account's code only + RETURN, ///< halt execution returning output data + DELEGATECALL, ///< like CALLCODE but keeps caller's value and sender + CREATE2 = 0xf5, ///< create new account with associated code at address `sha3(0xff + sender + salt + init code) % 2**160` + STATICCALL = 0xfa, ///< like CALL but disallow state modifications + + REVERT = 0xfd, ///< halt execution, revert state and return output data + INVALID = 0xfe, ///< invalid instruction for expressing runtime errors (e.g., division-by-zero) + SELFDESTRUCT = 0xff ///< halt execution and register account for later deletion }; /// @returns true if the instruction is of the CALL opcode family @@ -309,12 +309,12 @@ enum class Tier /// Information structure for a particular instruction. struct InstructionInfo { - std::string name; ///< The name of the instruction. - int additional; ///< Additional items required in memory for this instructions (only for PUSH). - int args; ///< Number of items required on the stack for this instruction (and, for the purposes of ret, the number taken from the stack). - int ret; ///< Number of items placed (back) on the stack by this instruction, assuming args items were removed. - bool sideEffects; ///< false if the only effect on the execution environment (apart from gas usage) is a change to a topmost segment of the stack - Tier gasPriceTier; ///< Tier for gas pricing. + std::string name; ///< The name of the instruction. + int additional; ///< Additional items required in memory for this instructions (only for PUSH). + int args; ///< Number of items required on the stack for this instruction (and, for the purposes of ret, the number taken from the stack). + int ret; ///< Number of items placed (back) on the stack by this instruction, assuming args items were removed. + bool sideEffects; ///< false if the only effect on the execution environment (apart from gas usage) is a change to a topmost segment of the stack + Tier gasPriceTier; ///< Tier for gas pricing. }; /// Information on all the instructions. diff --git a/liblangutil/Token.h b/liblangutil/Token.h index 0f7c2df08..d1073a872 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -64,11 +64,11 @@ namespace solidity::langutil #define IGNORE_TOKEN(name, string, precedence) -#define TOKEN_LIST(T, K) \ - /* End of source indicator. */ \ - T(EOS, "EOS", 0) \ - \ - /* Punctuators (ECMA-262, section 7.7, page 15). */ \ +#define TOKEN_LIST(T, K) \ + /* End of source indicator. */ \ + T(EOS, "EOS", 0) \ + \ + /* Punctuators (ECMA-262, section 7.7, page 15). */ \ T(LParen, "(", 0) \ T(RParen, ")", 0) \ T(LBrack, "[", 0) \ @@ -82,9 +82,9 @@ namespace solidity::langutil T(DoubleArrow, "=>", 0) \ T(RightArrow, "->", 0) \ \ - /* Assignment operators. */ \ - /* IsAssignmentOp() relies on this block of enum values being */ \ - /* contiguous and sorted in the same order!*/ \ + /* Assignment operators. */ \ + /* IsAssignmentOp() relies on this block of enum values being */ \ + /* contiguous and sorted in the same order!*/ \ T(Assign, "=", 2) \ /* The following have to be in exactly the same order as the simple binary operators*/ \ T(AssignBitOr, "|=", 2) \ diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index ef7c56ac0..ac906e301 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -221,5 +221,5 @@ std::string CHCSmtLib2Interface::createHeaderAndDeclarations() { } std::string CHCSmtLib2Interface::createQueryAssertion(std::string name) { - return "(assert\n(forall " + forall() + "\n" + "(=> " + name + " false)))"; + return "(assert\n(forall " + forall() + "\n" + "(=> " + name + " false)))"; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 0bcab65d9..a7402ba40 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3413,7 +3413,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) annotation.isPure = true; else if ( magicType->kind() == MagicType::Kind::MetaType && - (memberName == "min" || memberName == "max") + (memberName == "min" || memberName == "max") ) annotation.isPure = true; else if (magicType->kind() == MagicType::Kind::Block) diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index f7519250a..81b3b8374 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -65,8 +65,8 @@ struct ASTAnnotation struct DocTag { - std::string content; ///< The text content of the tag. - std::string paramName; ///< Only used for @param, stores the parameter name. + std::string content; ///< The text content of the tag. + std::string paramName; ///< Only used for @param, stores the parameter name. }; struct StructurallyDocumentedAnnotation diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 0af9f105f..d09d03fbe 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1042,7 +1042,7 @@ BoolResult RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) if (category == Category::FixedBytes) return false; else if (auto addressType = dynamic_cast(&_convertTo)) - return (m_value == 0) || + return (m_value == 0) || ((addressType->stateMutability() != StateMutability::Payable) && !isNegative() && !isFractional() && diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 494d106c8..3824d5432 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -942,7 +942,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) else { solAssert(paramTypes[arg - 1]->isValueType(), ""); - if (auto functionType = dynamic_cast(paramTypes[arg - 1])) + if (auto functionType = dynamic_cast(paramTypes[arg - 1])) { auto argumentType = dynamic_cast(arguments[arg-1]->annotation().type); diff --git a/libsolidity/experimental/codegen/IRGenerator.cpp b/libsolidity/experimental/codegen/IRGenerator.cpp index 257bd2be1..40deb38c3 100644 --- a/libsolidity/experimental/codegen/IRGenerator.cpp +++ b/libsolidity/experimental/codegen/IRGenerator.cpp @@ -52,14 +52,13 @@ IRGenerator::IRGenerator( DebugInfoSelection const&, CharStreamProvider const*, Analysis const& _analysis -) -: -m_evmVersion(_evmVersion), -m_eofVersion(_eofVersion), -// m_debugInfoSelection(_debugInfoSelection), -// m_soliditySourceProvider(_soliditySourceProvider), -m_env(_analysis.typeSystem().env().clone()), -m_context{_analysis, &m_env, {}, {}} +): + m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion), + //m_debugInfoSelection(_debugInfoSelection), + //m_soliditySourceProvider(_soliditySourceProvider), + m_env(_analysis.typeSystem().env().clone()), + m_context{_analysis, &m_env, {}, {}} { } diff --git a/libsolidity/experimental/codegen/IRGenerator.h b/libsolidity/experimental/codegen/IRGenerator.h index cce8c7305..7d3baf8f9 100644 --- a/libsolidity/experimental/codegen/IRGenerator.h +++ b/libsolidity/experimental/codegen/IRGenerator.h @@ -63,8 +63,8 @@ class IRGenerator langutil::EVMVersion const m_evmVersion; std::optional const m_eofVersion; OptimiserSettings const m_optimiserSettings; -// langutil::DebugInfoSelection m_debugInfoSelection = {}; -// langutil::CharStreamProvider const* m_soliditySourceProvider = nullptr; + //langutil::DebugInfoSelection m_debugInfoSelection = {}; + //langutil::CharStreamProvider const* m_soliditySourceProvider = nullptr; TypeEnvironment m_env; IRGenerationContext m_context; }; diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index b16182af8..932a315a7 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -349,7 +349,7 @@ bool BMC::visit(WhileStatement const& _node) _node.body().accept(*this); popPathCondition(); - auto brokeInCurrentIteration = mergeVariablesFromLoopCheckpoints(); + auto brokeInCurrentIteration = mergeVariablesFromLoopCheckpoints(); // merges indices modified when accepting loop condition that no longer holds mergeVariables( @@ -414,7 +414,7 @@ bool BMC::visit(ForStatement const& _node) pushPathCondition(forCondition); _node.body().accept(*this); - auto brokeInCurrentIteration = mergeVariablesFromLoopCheckpoints(); + auto brokeInCurrentIteration = mergeVariablesFromLoopCheckpoints(); // accept loop expression if there was no break if (_node.loopExpression()) diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index be676930c..bea3a85ef 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -277,7 +277,7 @@ class SMTEncoder: public ASTConstVisitor /// @returns a pair of expressions representing _left / _right and _left mod _right, respectively. /// Uses slack variables and additional constraints to express the results using only operations /// more friendly to the SMT solver (multiplication, addition, subtraction and comparison). - std::pair divModWithSlacks( + std::pair divModWithSlacks( smtutil::Expression _left, smtutil::Expression _right, IntegerType const& _type diff --git a/libsolutil/FixedHash.h b/libsolutil/FixedHash.h index c4c72e9eb..3aa248480 100644 --- a/libsolutil/FixedHash.h +++ b/libsolutil/FixedHash.h @@ -159,7 +159,7 @@ class FixedHash bytes asBytes() const { return bytes(data(), data() + N); } private: - std::array m_data; ///< The binary data. + std::array m_data; ///< The binary data. }; /// Stream I/O for the FixedHash class. diff --git a/libsolutil/Result.h b/libsolutil/Result.h index ca9563947..bf6bde84b 100644 --- a/libsolutil/Result.h +++ b/libsolutil/Result.h @@ -30,9 +30,9 @@ namespace solidity::util /// /// Result check() /// { -/// if (false) -/// return Result::err("Error message.") -/// return true; +/// if (false) +/// return Result::err("Error message.") +/// return true; /// } /// diff --git a/libyul/YulString.h b/libyul/YulString.h index 5522e3484..7dbaf1b84 100644 --- a/libyul/YulString.h +++ b/libyul/YulString.h @@ -66,7 +66,7 @@ class YulStringRepository return Handle{id, h}; } - std::string const& idToString(size_t _id) const { return *m_strings.at(_id); } + std::string const& idToString(size_t _id) const { return *m_strings.at(_id); } static std::uint64_t hash(std::string const& v) { diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 4b0da1e80..f048e5717 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -103,7 +103,7 @@ void markRecursiveCalls(CFG& _cfg) _addChild(_conditionalJump.nonZero); }, [&](CFG::BasicBlock::FunctionReturn const&) {}, - [&](CFG::BasicBlock::Terminated const&) {}, + [&](CFG::BasicBlock::Terminated const&) {}, }, _block->exit); }); return calls; diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index f3c529bb1..6a3b34f97 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -287,15 +287,15 @@ std::map createBuiltins(langutil::EVMVersion _ 3, 0, SideEffects{ - false, // movable - true, // movableApartFromEffects - false, // canBeRemoved - false, // canBeRemovedIfNotMSize - true, // cannotLoop - SideEffects::None, // otherState - SideEffects::None, // storage - SideEffects::Write, // memory - SideEffects::None // transientStorage + false, // movable + true, // movableApartFromEffects + false, // canBeRemoved + false, // canBeRemovedIfNotMSize + true, // cannotLoop + SideEffects::None, // otherState + SideEffects::None, // storage + SideEffects::Write, // memory + SideEffects::None // transientStorage }, {}, []( @@ -311,15 +311,15 @@ std::map createBuiltins(langutil::EVMVersion _ 3, 0, SideEffects{ - false, // movable - false, // movableApartFromEffects - false, // canBeRemoved - false, // canBeRemovedIfNotMSize - true, // cannotLoop - SideEffects::None, // otherState - SideEffects::None, // storage - SideEffects::Write, // memory - SideEffects::None // transientStorage + false, // movable + false, // movableApartFromEffects + false, // canBeRemoved + false, // canBeRemovedIfNotMSize + true, // cannotLoop + SideEffects::None, // otherState + SideEffects::None, // storage + SideEffects::Write, // memory + SideEffects::None // transientStorage }, {std::nullopt, LiteralKind::String, std::nullopt}, []( diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 88190b45b..51db3a14d 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -539,7 +539,7 @@ void StackLayoutGenerator::stitchConditionalJumps(CFG::BasicBlock const& _block) _addChild(_conditionalJump.zero); _addChild(_conditionalJump.nonZero); }, - [&](CFG::BasicBlock::FunctionReturn const&) {}, + [&](CFG::BasicBlock::FunctionReturn const&) {}, [&](CFG::BasicBlock::Terminated const&) { }, }, _block->exit); }); diff --git a/libyul/optimiser/ExpressionJoiner.h b/libyul/optimiser/ExpressionJoiner.h index eb22ad79f..3a1fdf743 100644 --- a/libyul/optimiser/ExpressionJoiner.h +++ b/libyul/optimiser/ExpressionJoiner.h @@ -91,9 +91,9 @@ class ExpressionJoiner: public ASTModifier bool isLatestStatementVarDeclJoinable(Identifier const& _identifier); private: - Block* m_currentBlock = nullptr; ///< Pointer to current block holding the statement being visited. - size_t m_latestStatementInBlock = 0; ///< Offset to m_currentBlock's statements of the last visited statement. - std::map m_references; ///< Holds reference counts to all variable declarations in current block. + Block* m_currentBlock = nullptr; ///< Pointer to current block holding the statement being visited. + size_t m_latestStatementInBlock = 0; ///< Offset to m_currentBlock's statements of the last visited statement. + std::map m_references; ///< Holds reference counts to all variable declarations in current block. }; } diff --git a/libyul/optimiser/SSAReverser.h b/libyul/optimiser/SSAReverser.h index bb6e98bc8..675c5c4af 100644 --- a/libyul/optimiser/SSAReverser.h +++ b/libyul/optimiser/SSAReverser.h @@ -30,42 +30,42 @@ class AssignmentCounter; * * In particular, the SSA transform will rewrite * - * a := E + * a := E * * to * - * let a_1 := E - * a := a_1 + * let a_1 := E + * a := a_1 * * To undo this kind of transformation, the SSAReverser changes this back to * - * a := E - * let a_1 := a + * a := E + * let a_1 := a * - * In the special case - * let a := E - * a := a + * In the special case + * let a := E + * a := a * - * the redundant assignment "a := a" is removed. + * the redundant assignment "a := a" is removed. * * * Secondly, the SSA transform will rewrite * - * let a := E + * let a := E * to * - * let a_1 := E - * let a := a_1 + * let a_1 := E + * let a := a_1 * * To undo this kind of transformation, the SSAReverser changes this back to * - * let a := E - * let a_1 := a + * let a := E + * let a_1 := a * - * After that the CSE can replace references of a_1 by references to a, - * after which the unused pruner can remove the declaration of a_1. + * After that the CSE can replace references of a_1 by references to a, + * after which the unused pruner can remove the declaration of a_1. * - * Prerequisites: Disambiguator + * Prerequisites: Disambiguator * */ class SSAReverser: public ASTModifier diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 6a6fa8f0e..9a94fbcf2 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -210,8 +210,8 @@ export DH_OPTIONS override_dh_auto_test: #override_dh_installdocs: -# make -C docs html -# dh_installdocs docs/_build/html +# make -C docs html +# dh_installdocs docs/_build/html override_dh_shlibdeps: dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 224375835..4ab9b2b08 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -191,7 +191,7 @@ void EVMHost::newTransactionFrame() for (auto& [slot, value]: account.storage) { value.access_status = EVMC_ACCESS_COLD; // Clear EIP-2929 storage access indicator - value.original = value.current; // Clear EIP-2200 dirty slot + value.original = value.current; // Clear EIP-2200 dirty slot } // Clear transient storage according to EIP 1153 diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index 2519fa86f..42e20d7e3 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -61,27 +61,27 @@ struct Testsuite /// Array of testsuits that can be run interactively as well as automatically Testsuite const g_interactiveTestsuites[] = { /* - Title Path Subpath SMT NeedsVM Creator function */ - {"Yul Optimizer", "libyul", "yulOptimizerTests", false, false, &yul::test::YulOptimizerTest::create}, - {"Yul Interpreter", "libyul", "yulInterpreterTests", false, false, &yul::test::YulInterpreterTest::create}, - {"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create}, - {"Yul Control Flow Graph", "libyul", "yulControlFlowGraph", false, false, &yul::test::ControlFlowGraphTest::create}, - {"Yul Stack Layout", "libyul", "yulStackLayout", false, false, &yul::test::StackLayoutGeneratorTest::create}, - {"Yul Stack Shuffling", "libyul", "yulStackShuffling", false, false, &yul::test::StackShufflingTest::create}, - {"Control Flow Side Effects", "libyul", "controlFlowSideEffects", false, false, &yul::test::ControlFlowSideEffectsTest::create}, - {"Function Side Effects", "libyul", "functionSideEffects", false, false, &yul::test::FunctionSideEffects::create}, - {"Yul Syntax", "libyul", "yulSyntaxTests", false, false, &yul::test::SyntaxTest::create}, - {"EVM Code Transform", "libyul", "evmCodeTransform", false, false, &yul::test::EVMCodeTransformTest::create, {"nooptions"}}, - {"Syntax", "libsolidity", "syntaxTests", false, false, &SyntaxTest::create}, - {"Semantic", "libsolidity", "semanticTests", false, true, &SemanticTest::create}, - {"JSON AST", "libsolidity", "ASTJSON", false, false, &ASTJSONTest::create}, - {"JSON ABI", "libsolidity", "ABIJson", false, false, &ABIJsonTest::create}, - {"JSON Natspec", "libsolidity", "natspecJSON", false, false, &NatspecJSONTest::create}, - {"SMT Checker", "libsolidity", "smtCheckerTests", true, false, &SMTCheckerTest::create}, - {"Gas Estimates", "libsolidity", "gasTests", false, false, &GasTest::create}, - {"Memory Guard", "libsolidity", "memoryGuardTests", false, false, &MemoryGuardTest::create}, - {"AST Properties", "libsolidity", "astPropertyTests", false, false, &ASTPropertyTest::create}, - {"Function Dependency Graph", "libsolidity", "functionDependencyGraphTests", false, false, &FunctionDependencyGraphTest::create}, + Title Path Subpath SMT NeedsVM Creator function */ + {"Yul Optimizer", "libyul", "yulOptimizerTests", false, false, &yul::test::YulOptimizerTest::create}, + {"Yul Interpreter", "libyul", "yulInterpreterTests", false, false, &yul::test::YulInterpreterTest::create}, + {"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create}, + {"Yul Control Flow Graph", "libyul", "yulControlFlowGraph", false, false, &yul::test::ControlFlowGraphTest::create}, + {"Yul Stack Layout", "libyul", "yulStackLayout", false, false, &yul::test::StackLayoutGeneratorTest::create}, + {"Yul Stack Shuffling", "libyul", "yulStackShuffling", false, false, &yul::test::StackShufflingTest::create}, + {"Control Flow Side Effects", "libyul", "controlFlowSideEffects", false, false, &yul::test::ControlFlowSideEffectsTest::create}, + {"Function Side Effects", "libyul", "functionSideEffects", false, false, &yul::test::FunctionSideEffects::create}, + {"Yul Syntax", "libyul", "yulSyntaxTests", false, false, &yul::test::SyntaxTest::create}, + {"EVM Code Transform", "libyul", "evmCodeTransform", false, false, &yul::test::EVMCodeTransformTest::create, {"nooptions"}}, + {"Syntax", "libsolidity", "syntaxTests", false, false, &SyntaxTest::create}, + {"Semantic", "libsolidity", "semanticTests", false, true, &SemanticTest::create}, + {"JSON AST", "libsolidity", "ASTJSON", false, false, &ASTJSONTest::create}, + {"JSON ABI", "libsolidity", "ABIJson", false, false, &ABIJsonTest::create}, + {"JSON Natspec", "libsolidity", "natspecJSON", false, false, &NatspecJSONTest::create}, + {"SMT Checker", "libsolidity", "smtCheckerTests", true, false, &SMTCheckerTest::create}, + {"Gas Estimates", "libsolidity", "gasTests", false, false, &GasTest::create}, + {"Memory Guard", "libsolidity", "memoryGuardTests", false, false, &MemoryGuardTest::create}, + {"AST Properties", "libsolidity", "astPropertyTests", false, false, &ASTPropertyTest::create}, + {"Function Dependency Graph", "libsolidity", "functionDependencyGraphTests", false, false, &FunctionDependencyGraphTest::create}, }; } diff --git a/test/cmdlineTests/model_checker_contracts_all/input.sol b/test/cmdlineTests/model_checker_contracts_all/input.sol index 52b71f2e5..f47f2f31d 100644 --- a/test/cmdlineTests/model_checker_contracts_all/input.sol +++ b/test/cmdlineTests/model_checker_contracts_all/input.sol @@ -2,11 +2,11 @@ pragma solidity >=0.0; contract B { function f(uint x) public pure { - assert(x > 0); + assert(x > 0); } } contract A is B { function g(uint y) public pure { - assert(y > 0); + assert(y > 0); } -} \ No newline at end of file +} diff --git a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/input.json b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/input.json index c1a7209b3..6ff766290 100644 --- a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/input.json +++ b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/input.json @@ -4,11 +4,11 @@ { "C": { - "content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\n\ncontract C\n{\n int constant constVar = 41;\n int immutable immutVar = 42;\n int public stateVar;\n\n constructor(int _init)\n {\n stateVar = _init;\n }\n\n function f() external pure returns (int)\n {\n return constVar + immutVar;\n }\n modifier m()\n {\n stateVar++;\n _;\n }\n function f2() m public returns (int)\n {\n return stateVar + this.f() + immutVar;\n }\n}\n" + "content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\n\ncontract C\n{\n int constant constVar = 41;\n int immutable immutVar = 42;\n int public stateVar;\n\n constructor(int _init)\n {\n stateVar = _init;\n }\n\n function f() external pure returns (int)\n {\n return constVar + immutVar;\n }\n modifier m()\n {\n stateVar++;\n _;\n }\n function f2() m public returns (int)\n {\n return stateVar + this.f() + immutVar;\n }\n}\n" }, "D": { - "content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\nimport \"C\";\n\ncontract D is C(3)\n{\n constructor(int _init2)\n {\n stateVar += _init2;\n }\n}\n" + "content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\nimport \"C\";\n\ncontract D is C(3)\n{\n constructor(int _init2)\n {\n stateVar += _init2;\n }\n}\n" } }, "settings": diff --git a/test/cmdlineTests/standard_debug_info_in_yul_location/input.json b/test/cmdlineTests/standard_debug_info_in_yul_location/input.json index 8ba84239a..47dd4d234 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_location/input.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_location/input.json @@ -4,11 +4,11 @@ { "C": { - "content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\n\ncontract C\n{\n int public constant constVar = 41;\n int immutable immutVar = 42;\n int public stateVar;\n\n constructor(int _init)\n {\n stateVar = _init;\n }\n\n function f() external pure returns (int)\n {\n return constVar + immutVar;\n }\n modifier m()\n {\n stateVar++;\n _;\n }\n function f2() m public returns (int)\n {\n return stateVar + this.f() + immutVar;\n }\n}\n" + "content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\n\ncontract C\n{\n int public constant constVar = 41;\n int immutable immutVar = 42;\n int public stateVar;\n\n constructor(int _init)\n {\n stateVar = _init;\n }\n\n function f() external pure returns (int)\n {\n return constVar + immutVar;\n }\n modifier m()\n {\n stateVar++;\n _;\n }\n function f2() m public returns (int)\n {\n return stateVar + this.f() + immutVar;\n }\n}\n" }, "D": { - "content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\nimport \"C\";\n\ncontract D is C(3)\n{\n constructor(int _init2)\n {\n stateVar += _init2;\n }\n}\n" + "content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\nimport \"C\";\n\ncontract D is C(3)\n{\n constructor(int _init2)\n {\n stateVar += _init2;\n }\n}\n" } }, "settings": diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/input.json index 9de7beea9..8e6add377 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/input.json @@ -1,16 +1,16 @@ { - "language": "Solidity", - "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/in.sol"]} - }, - "settings": { - "optimizer": { - "details": { - "yul": false, - "yulDetails": { - "optimizerSteps": ":" - } - } - } - } + "language": "Solidity", + "sources": { + "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/in.sol"]} + }, + "settings": { + "optimizer": { + "details": { + "yul": false, + "yulDetails": { + "optimizerSteps": ":" + } + } + } + } } diff --git a/test/cmdlineTests/standard_wrong_key_metadata/input.json b/test/cmdlineTests/standard_wrong_key_metadata/input.json index a52d45004..e0906d312 100644 --- a/test/cmdlineTests/standard_wrong_key_metadata/input.json +++ b/test/cmdlineTests/standard_wrong_key_metadata/input.json @@ -10,13 +10,13 @@ "settings": { "optimizer": { - "enabled": true, - "runs": 200 - }, - "evmVersion": "byzantium", - "metadata": { + "enabled": true, + "runs": 200 + }, + "evmVersion": "byzantium", + "metadata": { "key1": "test", - "useLiteralContent": true - } + "useLiteralContent": true + } } } diff --git a/test/cmdlineTests/standard_wrong_key_optimizer/input.json b/test/cmdlineTests/standard_wrong_key_optimizer/input.json index 945c1e346..2d54f09eb 100644 --- a/test/cmdlineTests/standard_wrong_key_optimizer/input.json +++ b/test/cmdlineTests/standard_wrong_key_optimizer/input.json @@ -11,12 +11,12 @@ { "optimizer": { "key1": "test", - "enabled": true, - "runs": 200 - }, - "evmVersion": "byzantium", - "metadata": { - "useLiteralContent": true - } + "enabled": true, + "runs": 200 + }, + "evmVersion": "byzantium", + "metadata": { + "useLiteralContent": true + } } } diff --git a/test/cmdlineTests/standard_wrong_key_settings/input.json b/test/cmdlineTests/standard_wrong_key_settings/input.json index 8f0e1d06b..2ce8871f9 100644 --- a/test/cmdlineTests/standard_wrong_key_settings/input.json +++ b/test/cmdlineTests/standard_wrong_key_settings/input.json @@ -1,22 +1,22 @@ { - "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } - }, - "settings": - { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "evmVersion": "byzantium", - "metadata": { - "useLiteralContent": true - }, - "key1": "test" - } + "language": "Solidity", + "sources": + { + "A": + { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "settings": + { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "evmVersion": "byzantium", + "metadata": { + "useLiteralContent": true + }, + "key1": "test" + } } diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index e1795d391..04d41fffe 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1358,11 +1358,11 @@ BOOST_AUTO_TEST_CASE(cse_verbatim_mload) auto verbatim = AssemblyItem{bytes{1, 2, 3, 4, 5}, 0, 0}; AssemblyItems input{ u256(1000), - Instruction::MLOAD, // Should not be removed + Instruction::MLOAD, // Should not be removed Instruction::POP, verbatim, u256(1000), - Instruction::MLOAD, // Should not be removed + Instruction::MLOAD, // Should not be removed Instruction::POP, }; diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 381ec5bda..63e8a924a 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -157,7 +157,7 @@ std::map SemanticTest::makeBuiltins() { soltestAssert(_call.arguments.parameters.empty(), "No arguments expected."); return toBigEndian(u256(storageEmpty(m_contractAddress) ? 1 : 0)); - } + } }, { "account", diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e34df0307..e321a5298 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1680,29 +1680,29 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi) //BOOST_AUTO_TEST_CASE(assignment_to_const_array_vars) //{ -// char const* sourceCode = R"( -// contract C { -// uint[3] constant x = [uint(1), 2, 3]; -// uint constant y = x[0] + x[1] + x[2]; -// function f() public returns (uint) { return y; } -// } -// )"; -// compileAndRun(sourceCode); -// ABI_CHECK(callContractFunction("f()"), encodeArgs(1 + 2 + 3)); +// char const* sourceCode = R"( +// contract C { +// uint[3] constant x = [uint(1), 2, 3]; +// uint constant y = x[0] + x[1] + x[2]; +// function f() public returns (uint) { return y; } +// } +// )"; +// compileAndRun(sourceCode); +// ABI_CHECK(callContractFunction("f()"), encodeArgs(1 + 2 + 3)); //} // Disabled until https://github.com/ethereum/solidity/issues/715 is implemented //BOOST_AUTO_TEST_CASE(constant_struct) //{ -// char const* sourceCode = R"( -// contract C { -// struct S { uint x; uint[] y; } -// S constant x = S(5, new uint[](4)); -// function f() public returns (uint) { return x.x; } -// } -// )"; -// compileAndRun(sourceCode); -// ABI_CHECK(callContractFunction("f()"), encodeArgs(5)); +// char const* sourceCode = R"( +// contract C { +// struct S { uint x; uint[] y; } +// S constant x = S(5, new uint[](4)); +// function f() public returns (uint) { return x.x; } +// } +// )"; +// compileAndRun(sourceCode); +// ABI_CHECK(callContractFunction("f()"), encodeArgs(5)); //} BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund) diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 27f1a7e84..d52ad6b9c 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches) numSHA3s++; }); // TEST DISABLED - OPTIMIZER IS NOT EFFECTIVE ON THIS ONE ANYMORE -// BOOST_CHECK_EQUAL(1, numSHA3s); +// BOOST_CHECK_EQUAL(1, numSHA3s); } BOOST_AUTO_TEST_CASE(store_tags_as_unions) @@ -334,7 +334,7 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions) numSHA3s++; }); // TEST DISABLED UNTIL 93693404 IS IMPLEMENTED -// BOOST_CHECK_EQUAL(2, numSHA3s); +// BOOST_CHECK_EQUAL(2, numSHA3s); } BOOST_AUTO_TEST_CASE(incorrect_storage_access_bug) diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 7fafa2a62..22db222ea 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -1220,7 +1220,7 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_details_different) BOOST_CHECK( optimizer["details"]["yulDetails"]["optimizerSteps"].asString() == OptimiserSettings::DefaultYulOptimiserSteps + ":"s + OptimiserSettings::DefaultYulOptimiserCleanupSteps - ); + ); BOOST_CHECK_EQUAL(optimizer["details"].getMemberNames().size(), 10); BOOST_CHECK(optimizer["runs"].asUInt() == 600); } diff --git a/test/libsolidity/natspecJSON/dev_multiple_params_mixed_whitespace.sol b/test/libsolidity/natspecJSON/dev_multiple_params_mixed_whitespace.sol index 61f45aa62..fc3fd4d71 100644 --- a/test/libsolidity/natspecJSON/dev_multiple_params_mixed_whitespace.sol +++ b/test/libsolidity/natspecJSON/dev_multiple_params_mixed_whitespace.sol @@ -1,7 +1,7 @@ contract test { - /// @dev Multiplies a number by 7 and adds second parameter - /// @param a Documentation for the first parameter - /// @param second Documentation for the second parameter + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter + /// @param second Documentation for the second parameter function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } diff --git a/test/libsolidity/smtCheckerTests/functions/functions_library_internal.sol b/test/libsolidity/smtCheckerTests/functions/functions_library_internal.sol index 405c3f715..d2f2d6923 100644 --- a/test/libsolidity/smtCheckerTests/functions/functions_library_internal.sol +++ b/test/libsolidity/smtCheckerTests/functions/functions_library_internal.sol @@ -7,7 +7,7 @@ contract C { function f() public { function()internal x; x.value(42); - } + } } // ==== // SMTEngine: all diff --git a/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_6.sol b/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_6.sol index d0a917fa9..4880b3a0d 100644 --- a/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_6.sol +++ b/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_6.sol @@ -4,7 +4,7 @@ contract C { do { ++x; if (x > 0) { - x = 2; + x = 2; break; } if (x > 1) { diff --git a/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_7.sol b/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_7.sol index 52c3270ba..5b4d6579b 100644 --- a/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_7.sol +++ b/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_7.sol @@ -6,11 +6,11 @@ contract C { if (x > 1) { x = 3; break; - } + } if (x > 0) { x = 2; break; - } + } } while (x < 3); assert(x == 2); } diff --git a/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_continue_1.sol b/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_continue_1.sol index 53ce958fa..43a5f91f5 100644 --- a/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_continue_1.sol +++ b/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_continue_1.sol @@ -4,11 +4,11 @@ contract C { do { if (x > 1) { break; - } + } if (x >= 0) { x = 10; continue; - } + } } while (x < 3); assert(x == 10); } diff --git a/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_continue_2.sol b/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_continue_2.sol index 12d6fff6f..eed910118 100644 --- a/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_continue_2.sol +++ b/test/libsolidity/smtCheckerTests/loops/do_while_bmc_iterations_break_continue_2.sol @@ -5,11 +5,11 @@ contract C { if (x > 1) { x = 3; break; - } + } if (x >= 0) { x = 2; continue; - } + } } while (x < 4); assert(x == 3); } diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_2.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_2.sol index cada2d851..e7ff49dae 100644 --- a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_2.sol +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_2.sol @@ -4,7 +4,7 @@ contract C uint x; for (uint i = 0; i < 3; ++i) { ++x; - break; + break; } assert(x == 1); } diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_8.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_8.sol index a88a031e7..de3237838 100644 --- a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_8.sol +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_8.sol @@ -3,7 +3,7 @@ contract C function f() public pure { uint x; for (;;) { - break; + break; ++x; } assert(x == 0); diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_9.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_9.sol index 4ce3d9268..8106ba30f 100644 --- a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_9.sol +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_9.sol @@ -4,7 +4,7 @@ contract C uint x; for (;x < 2;) { ++x; - break; + break; } assert(x == 1); } diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_1.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_1.sol index b999f9cf6..1dbe81a96 100644 --- a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_1.sol +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_1.sol @@ -5,11 +5,11 @@ contract C for (uint i = 0; i < 3; ++i) { if (i > 1) { break; - } + } if (i >= 0) { x = 10; continue; - } + } } assert(x == 10); } diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_2.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_2.sol index 0da0f5d99..1781f77ce 100644 --- a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_2.sol +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_2.sol @@ -6,7 +6,7 @@ contract C if (i > 0) { x = 1; break; - } + } if (i >= 0) { x = 2; continue; diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_3.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_3.sol index 9f762bb43..933612758 100644 --- a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_3.sol +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_continue_3.sol @@ -6,7 +6,7 @@ contract C if (i > 0) { x = 1; break; - } else { + } else { x = 2; continue; } diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_continue_3.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_continue_3.sol index b74709e48..6f999a14c 100644 --- a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_continue_3.sol +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_continue_3.sol @@ -7,7 +7,7 @@ contract C x = 10; continue; } - if (x > 0) { + if (x > 0) { x = 11; continue; } diff --git a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_8.sol b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_8.sol index b7ad4e2ec..69c49d8f8 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_8.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_8.sol @@ -3,7 +3,7 @@ contract C uint256[] y; function f() public view { - uint256 x = 0; + uint256 x = 0; while (x < y.length) { x = 1; } diff --git a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_4.sol b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_4.sol index d1939871b..989130a13 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_4.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_4.sol @@ -4,7 +4,7 @@ contract C { while (x < 3) { ++x; if (x > 0) { - ++x; + ++x; break; } } diff --git a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_6.sol b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_6.sol index 0546e48c0..9f2bdd1aa 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_6.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_6.sol @@ -4,7 +4,7 @@ contract C { while (x < 3) { ++x; if (x > 0) { - x = 2; + x = 2; break; } if (x > 1) { diff --git a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_7.sol b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_7.sol index 8e4d3b626..c1aca1bcc 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_7.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_7.sol @@ -6,11 +6,11 @@ contract C { if (x > 1) { x = 3; break; - } + } if (x > 0) { x = 2; break; - } + } } assert(x == 2); } diff --git a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_continue_1.sol b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_continue_1.sol index bb9554523..6332d20e3 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_continue_1.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_continue_1.sol @@ -4,11 +4,11 @@ contract C { while (x < 3) { if (x > 1) { break; - } + } if (x >= 0) { x = 10; continue; - } + } } assert(x == 10); } diff --git a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_continue_2.sol b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_continue_2.sol index b65404e22..c4e47d528 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_continue_2.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_break_continue_2.sol @@ -5,11 +5,11 @@ contract C { if (x > 1) { x = 3; break; - } + } if (x >= 0) { x = 2; continue; - } + } } assert(x == 3); } diff --git a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_semantics_2.sol b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_semantics_2.sol index a50acf4d2..5b22ca942 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_semantics_2.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_semantics_2.sol @@ -7,7 +7,7 @@ contract C { y = 1; ++x; } - // BMC loop iteration setting is just enough to leave the loop + // BMC loop iteration setting is just enough to leave the loop assert(x == 3); assert(y == 1); // should fail assert(y == 0); diff --git a/test/libsolidity/smtCheckerTests/operators/delete_multid_array.sol b/test/libsolidity/smtCheckerTests/operators/delete_multid_array.sol index 53a1a253e..ea6eb3a9a 100644 --- a/test/libsolidity/smtCheckerTests/operators/delete_multid_array.sol +++ b/test/libsolidity/smtCheckerTests/operators/delete_multid_array.sol @@ -9,21 +9,21 @@ contract C { delete a; assert(a.length == 0); } - function g(uint x, uint y, uint v) public { + function g(uint x, uint y, uint v) public { require(x < b.length); require(y < b[x].length); b[x][y] = v; delete b; assert(b.length == 0); } - function h(uint x, uint y, uint v) public { + function h(uint x, uint y, uint v) public { require(x < b.length); require(y < b[x].length); b[x][y] = v; delete b[x]; assert(b[x].length == 0); } - function i(uint x, uint y, uint v) public { + function i(uint x, uint y, uint v) public { require(x < b.length); require(y < b[x].length); b[x][y] = v; @@ -31,7 +31,7 @@ contract C { delete b[y]; assert(b[y].length == 0); } - function j(uint x, uint y, uint z, uint v) public { + function j(uint x, uint y, uint z, uint v) public { require(x < b.length); require(y < b[x].length); b[x][y] = v; diff --git a/test/libsolidity/util/TestFunctionCallTests.cpp b/test/libsolidity/util/TestFunctionCallTests.cpp index 5741ccd0d..72e5c7393 100644 --- a/test/libsolidity/util/TestFunctionCallTests.cpp +++ b/test/libsolidity/util/TestFunctionCallTests.cpp @@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE(format_unsigned_multiline) call.displayMode = FunctionCall::DisplayMode::MultiLine; TestFunctionCall test{call}; - BOOST_REQUIRE_EQUAL(test.format(), "// f(uint8)\n// -> 1"); + BOOST_REQUIRE_EQUAL(test.format(), "// f(uint8)\n// -> 1"); } BOOST_AUTO_TEST_CASE(format_multiple_unsigned_singleline) diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index c9b9ec072..69314abee 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -450,12 +450,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_3) ErrorReporter reporter(errorList); auto const sourceText = R"( /// @src 1:23:45 - { // Block - { // Block - sstore(0, 1) // FunctionCall + { // Block + { // Block + sstore(0, 1) // FunctionCall /// @src 0:420:680 } - mstore(1, 2) // FunctionCall + mstore(1, 2) // FunctionCall } )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); diff --git a/test/libyul/StackShufflingTest.cpp b/test/libyul/StackShufflingTest.cpp index 7c85a931e..e53eeafbb 100644 --- a/test/libyul/StackShufflingTest.cpp +++ b/test/libyul/StackShufflingTest.cpp @@ -56,12 +56,12 @@ bool StackShufflingTest::parse(std::string const& _source) scanner.next(); std::string functionName = scanner.currentLiteral(); auto call = yul::FunctionCall{ - {}, yul::Identifier{{}, YulString(functionName)}, {} + {}, yul::Identifier{{}, YulString(functionName)}, {} }; stack.emplace_back(FunctionCallReturnLabelSlot{ - m_functions.insert( - make_pair(functionName, call) - ).first->second + m_functions.insert( + make_pair(functionName, call) + ).first->second }); expectToken(Token::RBrack); } @@ -78,14 +78,14 @@ bool StackShufflingTest::parse(std::string const& _source) scanner.next(); std::string functionName = scanner.currentLiteral(); auto call = yul::FunctionCall{ - {}, yul::Identifier{{}, YulString(functionName)}, {} - }; + {}, yul::Identifier{{}, YulString(functionName)}, {} + }; expectToken(Token::Comma); scanner.next(); size_t index = size_t(atoi(scanner.currentLiteral().c_str())); stack.emplace_back(TemporarySlot{ - m_functions.insert(make_pair(functionName, call)).first->second, - index + m_functions.insert(make_pair(functionName, call)).first->second, + index }); expectToken(Token::RBrack); } @@ -104,7 +104,7 @@ bool StackShufflingTest::parse(std::string const& _source) std::string ghostVariableId = scanner.currentLiteral(); Scope::Variable ghostVar = Scope::Variable{""_yulstring, YulString(literal + "[" + ghostVariableId + "]")}; stack.emplace_back(VariableSlot{ - m_variables.insert(std::make_pair(ghostVar.name, ghostVar)).first->second + m_variables.insert(std::make_pair(ghostVar.name, ghostVar)).first->second }); expectToken(Token::RBrack); } @@ -112,9 +112,9 @@ bool StackShufflingTest::parse(std::string const& _source) { Scope::Variable var = Scope::Variable{""_yulstring, YulString(literal)}; stack.emplace_back(VariableSlot{ - m_variables.insert( - make_pair(literal, var) - ).first->second + m_variables.insert( + make_pair(literal, var) + ).first->second }); } scanner.next(); diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index e529f1d95..ea68f8dcd 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -422,7 +422,7 @@ std::string YulOptimizerTestCommon::randomOptimiserStep(unsigned _seed) // Do not fuzz reasoning based simplifier because // it can sometimes drain memory. if ( - optimiserStep == "mainFunction" || + optimiserStep == "mainFunction" || optimiserStep == "wordSizeTransform" ) // "Fullsuite" is fuzzed roughly four times more frequently than diff --git a/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_different_names.yul b/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_different_names.yul index f78b9fb99..2cde783c1 100644 --- a/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_different_names.yul +++ b/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_different_names.yul @@ -1,11 +1,11 @@ { { - function a() -> x { x := b() } - function b() -> y { y := a() } + function a() -> x { x := b() } + function b() -> y { y := a() } } { - function c() -> z { z := d() } - function d() -> w { w := c() } + function c() -> z { z := d() } + function d() -> w { w := c() } } } // ---- diff --git a/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_same_name.yul b/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_same_name.yul index 858a48d85..112f9fdcc 100644 --- a/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_same_name.yul +++ b/test/libyul/yulOptimizerTests/circularReferencesPruner/nested_same_name.yul @@ -1,11 +1,11 @@ { { - function z() -> x { x := y() } - function y() -> x { x := z() } + function z() -> x { x := y() } + function y() -> x { x := z() } } { - function z() -> x { x := y() } - function y() -> x { x := z() } + function z() -> x { x := y() } + function y() -> x { x := z() } } } // ---- diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul index 73a79410d..f9191afb6 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul @@ -1,7 +1,7 @@ // return variables are assumed to be zero initially. { function f() -> c, d { - let y := add(d, add(c, 7)) + let y := add(d, add(c, 7)) sstore(0, y) } let t, v := f() diff --git a/test/libyul/yulOptimizerTests/fullSuite/static_array_slot_computation.yul b/test/libyul/yulOptimizerTests/fullSuite/static_array_slot_computation.yul index bf74af6f4..6dc1d8c94 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/static_array_slot_computation.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/static_array_slot_computation.yul @@ -1,8 +1,8 @@ // The yul code for the following contract -// contract C { -// uint256[] x; -// function f() public { x[10] = 5; } -// } +// contract C { +// uint256[] x; +// function f() public { x[10] = 5; } +// } { let _1 := 0 diff --git a/test/tools/ossfuzz/protoToAbiV2.cpp b/test/tools/ossfuzz/protoToAbiV2.cpp index 98de7dd35..af2e5ede1 100644 --- a/test/tools/ossfuzz/protoToAbiV2.cpp +++ b/test/tools/ossfuzz/protoToAbiV2.cpp @@ -53,8 +53,8 @@ BOOST_PP_REPEAT(32, USINGDECL, 0) ostringstream stream; \ switch (_intWidth) \ { \ - BOOST_PP_REPEAT(32, CASEIMPL, sign) \ - } \ + BOOST_PP_REPEAT(32, CASEIMPL, sign) \ + } \ return stream.str(); using namespace std; @@ -103,7 +103,7 @@ string ProtoConverter::getVarDecl( // One level of indentation for state variable declarations // Two levels of indentation for local variable declarations return Whiskers(R"( - ;)" + ;)" ) ("isLocalVar", !m_isStateVar) ("type", _type) diff --git a/test/tools/ossfuzz/protoToAbiV2.h b/test/tools/ossfuzz/protoToAbiV2.h index be583d497..803c0e7b3 100644 --- a/test/tools/ossfuzz/protoToAbiV2.h +++ b/test/tools/ossfuzz/protoToAbiV2.h @@ -19,116 +19,116 @@ /** * Template of the solidity test program generated by this converter is as follows: * - * pragma solidity >=0.0; - * pragma experimental ABIEncoderV2; + * pragma solidity >=0.0; + * pragma experimental ABIEncoderV2; * - * contract C { - * // State variable - * string sv_0; - * // Test function that is called by the VM. - * // There are 2 variations of this function: one returns - * // the output of test_calldata_coding() and the other - * // returns the output of test_returndata_coding(). The - * // proto field called Test decides which one of the two - * // are chosen for creating a test case. - * function test() public returns (uint) { - * // The protobuf field "Contract.test" decides which of - * // the two internal functions "test_calldata_coding()" - * // and "test_returndata_coding()" are called. Here, - * // we assume that the protobuf field equals "CALLDATA_CODER" - * return this.test_calldata_coding() - * } + * contract C { + * // State variable + * string sv_0; + * // Test function that is called by the VM. + * // There are 2 variations of this function: one returns + * // the output of test_calldata_coding() and the other + * // returns the output of test_returndata_coding(). The + * // proto field called Test decides which one of the two + * // are chosen for creating a test case. + * function test() public returns (uint) { + * // The protobuf field "Contract.test" decides which of + * // the two internal functions "test_calldata_coding()" + * // and "test_returndata_coding()" are called. Here, + * // we assume that the protobuf field equals "CALLDATA_CODER" + * return this.test_calldata_coding() + * } * - * // The following function is generated if the protobuf field - * // "Contract.test" is equal to "RETURNDATA_CODER". - * function test_returndata_coding() internal returns (uint) { - * string memory lv_0, bytes memory lv_1 = test_returndata_external(); - * if (lv_0 != 044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d) - * return 1; - * if (lv_1 != "1") - * return 2; - * return 0; - * } + * // The following function is generated if the protobuf field + * // "Contract.test" is equal to "RETURNDATA_CODER". + * function test_returndata_coding() internal returns (uint) { + * string memory lv_0, bytes memory lv_1 = test_returndata_external(); + * if (lv_0 != 044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d) + * return 1; + * if (lv_1 != "1") + * return 2; + * return 0; + * } * - * // The following function is generated if the protobuf field - * // "Contract.test" is equal to "RETURNDATA_CODER". - * function test_returndata_external() external returns (string memory, bytes memory) - * { - * sv_0 = "044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d"; - * bytes memory lv_0 = "1"; - * return (sv_0, lv_0); - * } + * // The following function is generated if the protobuf field + * // "Contract.test" is equal to "RETURNDATA_CODER". + * function test_returndata_external() external returns (string memory, bytes memory) + * { + * sv_0 = "044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d"; + * bytes memory lv_0 = "1"; + * return (sv_0, lv_0); + * } * - * // The following function is generated if the protobuf field - * // "Contract.test" is equal to "CALLDATA_CODER". - * function test_calldata_coding() internal returns (uint) { - * // Local variable - * bytes lv_1 = "1"; - * sv_0 = "044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d"; - * uint returnVal = this.coder_public(sv_0, lv_1); - * if (returnVal != 0) - * return returnVal; - * // Since the return codes in the public and external coder functions are identical - * // we offset error code by a fixed amount (200000) for differentiation. - * returnVal = this.coder_external(sv_0, lv_1); - * if (returnVal != 0) - * return 200000 + returnVal; - * // Encode parameters - * bytes memory argumentEncoding = abi.encode(); - * returnVal = checkEncodedCall(this.coder_public.selector, argumentEncoding, ); - * // Check if calls to coder_public meet expectations for correctly/incorrectly encoded data. - * if (returnVal != 0) - * return returnVal; + * // The following function is generated if the protobuf field + * // "Contract.test" is equal to "CALLDATA_CODER". + * function test_calldata_coding() internal returns (uint) { + * // Local variable + * bytes lv_1 = "1"; + * sv_0 = "044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d"; + * uint returnVal = this.coder_public(sv_0, lv_1); + * if (returnVal != 0) + * return returnVal; + * // Since the return codes in the public and external coder functions are identical + * // we offset error code by a fixed amount (200000) for differentiation. + * returnVal = this.coder_external(sv_0, lv_1); + * if (returnVal != 0) + * return 200000 + returnVal; + * // Encode parameters + * bytes memory argumentEncoding = abi.encode(); + * returnVal = checkEncodedCall(this.coder_public.selector, argumentEncoding, ); + * // Check if calls to coder_public meet expectations for correctly/incorrectly encoded data. + * if (returnVal != 0) + * return returnVal; * - * returnVal = checkEncodedCall(this.coder_external.selector, argumentEncoding, ); - * // Check if calls to coder_external meet expectations for correctly/incorrectly encoded data. - * // Offset return value to distinguish between failures originating from coder_public and coder_external. - * if (returnVal != 0) - * return uint(200000) + returnVal; - * // Return zero if all checks pass. - * return 0; - * } + * returnVal = checkEncodedCall(this.coder_external.selector, argumentEncoding, ); + * // Check if calls to coder_external meet expectations for correctly/incorrectly encoded data. + * // Offset return value to distinguish between failures originating from coder_public and coder_external. + * if (returnVal != 0) + * return uint(200000) + returnVal; + * // Return zero if all checks pass. + * return 0; + * } * - * /// Accepts function selector, correct argument encoding, and an invalid encoding length as input. - * /// Returns a non-zero value if either call with correct encoding fails or call with incorrect encoding - * /// succeeds. Returns zero if both calls meet expectation. - * function checkEncodedCall(bytes4 funcSelector, bytes memory argumentEncoding, uint invalidLengthFuzz) - * public returns (uint) { - * ... - * } + * /// Accepts function selector, correct argument encoding, and an invalid encoding length as input. + * /// Returns a non-zero value if either call with correct encoding fails or call with incorrect encoding + * /// succeeds. Returns zero if both calls meet expectation. + * function checkEncodedCall(bytes4 funcSelector, bytes memory argumentEncoding, uint invalidLengthFuzz) + * public returns (uint) { + * ... + * } * - * /// Accepts function selector, correct argument encoding, and length of invalid encoding and returns - * /// the correct and incorrect abi encoding for calling the function specified by the function selector. - * function createEncoding(bytes4 funcSelector, bytes memory argumentEncoding, uint invalidLengthFuzz) - * internal pure returns (bytes memory, bytes memory) { - * ... - * } + * /// Accepts function selector, correct argument encoding, and length of invalid encoding and returns + * /// the correct and incorrect abi encoding for calling the function specified by the function selector. + * function createEncoding(bytes4 funcSelector, bytes memory argumentEncoding, uint invalidLengthFuzz) + * internal pure returns (bytes memory, bytes memory) { + * ... + * } * - * /// Compares two dynamically sized bytes arrays for equality. - * function bytesCompare(bytes memory a, bytes memory b) internal pure returns (bool) { - * ... - * } + * /// Compares two dynamically sized bytes arrays for equality. + * function bytesCompare(bytes memory a, bytes memory b) internal pure returns (bool) { + * ... + * } * - * // Public function that is called by test() function. Accepts one or more arguments and returns - * // a uint value (zero if abi en/decoding was successful, non-zero otherwise) - * function coder_public(string memory c_0, bytes memory c_1) public pure returns (uint) { - * if (!bytesCompare(bytes(c_0), "044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d")) - * return 1; - * if (!bytesCompare(c_1, "1")) - * return 2; - * return 0; - * } + * // Public function that is called by test() function. Accepts one or more arguments and returns + * // a uint value (zero if abi en/decoding was successful, non-zero otherwise) + * function coder_public(string memory c_0, bytes memory c_1) public pure returns (uint) { + * if (!bytesCompare(bytes(c_0), "044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d")) + * return 1; + * if (!bytesCompare(c_1, "1")) + * return 2; + * return 0; + * } * - * // External function that is called by test() function. Accepts one or more arguments and returns - * // a uint value (zero if abi en/decoding was successful, non-zero otherwise) - * function coder_external(string calldata c_0, bytes calldata c_1) external pure returns (uint) { - * if (!bytesCompare(bytes(c_0), "044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d")) - * return 1; - * if (!bytesCompare(c_1, "1")) - * return 2; - * return 0; - * } - * } + * // External function that is called by test() function. Accepts one or more arguments and returns + * // a uint value (zero if abi en/decoding was successful, non-zero otherwise) + * function coder_external(string calldata c_0, bytes calldata c_1) external pure returns (uint) { + * if (!bytesCompare(bytes(c_0), "044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d")) + * return 1; + * if (!bytesCompare(c_1, "1")) + * return 2; + * return 0; + * } + * } */ namespace solidity::test::abiv2fuzzer diff --git a/test/tools/ossfuzz/protoToYul.h b/test/tools/ossfuzz/protoToYul.h index c264dd51a..2ae54f68a 100644 --- a/test/tools/ossfuzz/protoToYul.h +++ b/test/tools/ossfuzz/protoToYul.h @@ -199,9 +199,9 @@ class ProtoConverter /// Prints a Yul formatted variable declaration statement to the output /// stream. /// Example 1: createVarDecls(0, 1, true) returns {"x_0"} and prints - /// let x_0 := + /// let x_0 := /// Example 2: createVarDecls(0, 2, false) returns {"x_0", "x_1"} and prints - /// let x_0, x_1 + /// let x_0, x_1 /// @param _start Start index of variable (inclusive) /// @param _end End index of variable (exclusive) /// @param _isAssignment Flag indicating if variable declaration is also @@ -215,7 +215,7 @@ class ProtoConverter /// Prints comma separated variable names to output stream and /// returns a vector containing the printed variable names. /// Example: createVars(0, 2) returns {"x_0", "x_1"} and prints - /// x_0, x_1 + /// x_0, x_1 /// @param _startIdx Start index of variable (inclusive) /// @param _endIdx End index of variable (exclusive) /// @return A vector of strings containing the printed variable names. @@ -264,7 +264,7 @@ class ProtoConverter /// @param _p Enum that decides if the returned token is hex prefixed ("0x") or not /// @return Dictionary token at the index computed using a /// monotonically increasing counter as follows: - /// index = (m_inputSize * m_inputSize + counter) % dictionarySize + /// index = (m_inputSize * m_inputSize + counter) % dictionarySize /// where m_inputSize is the size of the protobuf input and /// dictionarySize is the total number of entries in the dictionary. std::string dictionaryToken(util::HexPrefix _p = util::HexPrefix::Add); From 5cd92b57080bf6aa328c1527ea0fb1213afb0068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 12 Apr 2024 23:33:16 +0200 Subject: [PATCH 0058/1340] Update text expectations --- .../model_checker_contracts_all/err | 12 +- .../output.json | 194 +++++------ .../output.json | 312 +++++++++--------- .../loops/for_loop_bmc_iterations_break_8.sol | 2 +- .../while_bmc_iterations_semantics_2.sol | 2 +- 5 files changed, 261 insertions(+), 261 deletions(-) diff --git a/test/cmdlineTests/model_checker_contracts_all/err b/test/cmdlineTests/model_checker_contracts_all/err index 57b620b49..9135483d5 100644 --- a/test/cmdlineTests/model_checker_contracts_all/err +++ b/test/cmdlineTests/model_checker_contracts_all/err @@ -6,10 +6,10 @@ x = 0 Transaction trace: B.constructor() B.f(0) - --> model_checker_contracts_all/input.sol:5:3: + --> model_checker_contracts_all/input.sol:5:9: | -5 | assert(x > 0); - | ^^^^^^^^^^^^^ +5 | assert(x > 0); + | ^^^^^^^^^^^^^ Warning: CHC: Assertion violation happens here. Counterexample: @@ -19,7 +19,7 @@ y = 0 Transaction trace: A.constructor() A.g(0) - --> model_checker_contracts_all/input.sol:10:3: + --> model_checker_contracts_all/input.sol:10:9: | -10 | assert(y > 0); - | ^^^^^^^^^^^^^ +10 | assert(y > 0); + | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json index 143ad92c3..97041b238 100644 --- a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json @@ -7,7 +7,7 @@ { "evm": { - "assembly": " /* \"C\":79:428 contract C... */ + "assembly": " /* \"C\":79:503 contract C... */ 0xa0 jumpi(tag_5, callvalue) 0x1f @@ -49,10 +49,10 @@ tag_5 jumpi mload - /* \"C\":147:149 42 */ + /* \"C\":153:155 42 */ mstore(0x80, 0x2a) 0x00 - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ sstore mload(0x40) dataSize(sub_0) @@ -61,9 +61,9 @@ dataOffset(sub_0) dup3 codecopy - /* \"C\":147:149 42 */ + /* \"C\":153:155 42 */ 0x80 - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ mload dup2 assignImmutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") @@ -79,7 +79,7 @@ tag_3: stop sub_0: assembly { - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ 0x80 0x40 swap1 @@ -129,21 +129,21 @@ sub_0: assembly { dup2 mload shl(0xe4, 0x026121ff) - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ dup2 mstore - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ swap2 swap1 - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ 0x20 - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ dup4 0x04 dup2 - /* \"C\":403:407 this */ + /* \"C\":475:479 this */ address - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ gas staticcall swap3 @@ -151,50 +151,50 @@ sub_0: assembly { iszero tag_16 jumpi - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ 0x00 - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ swap4 tag_18 jumpi - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ tag_19: - /* \"C\":392:411 stateVar + this.f() */ + /* \"C\":464:483 stateVar + this.f() */ pop tag_20 - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ 0x20 - /* \"C\":392:411 stateVar + this.f() */ + /* \"C\":464:483 stateVar + this.f() */ swap4 - /* \"C\":392:422 stateVar + this.f() + immutVar */ + /* \"C\":464:494 stateVar + this.f() + immutVar */ tag_21 - /* \"C\":392:411 stateVar + this.f() */ + /* \"C\":464:483 stateVar + this.f() */ swap3 tag_1 jump\t// in tag_20: - /* \"C\":414:422 immutVar */ + /* \"C\":486:494 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") - /* \"C\":392:422 stateVar + this.f() + immutVar */ + /* \"C\":464:494 stateVar + this.f() + immutVar */ swap1 tag_1 jump\t// in tag_21: - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ swap1 mload swap1 dup2 mstore return - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ tag_18: swap3 pop 0x20 jumpi(tag_22, gt(0x20, returndatasize)) tag_23: - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ 0x1f dup2 add @@ -211,18 +211,18 @@ sub_0: assembly { or tag_24 jumpi - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ 0x20 - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ swap2 dup6 swap2 dup6 mstore - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ dup2 add - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ sub slt tag_26 @@ -230,30 +230,30 @@ sub_0: assembly { swap2 mload swap2 - /* \"C\":392:411 stateVar + this.f() */ + /* \"C\":464:483 stateVar + this.f() */ tag_20 - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ jump(tag_19) - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ tag_26: 0x00 dup1 revert tag_24: - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ shl(0xe0, 0x4e487b71) - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ 0x00 mstore mstore(0x04, 0x41) revert(0x00, 0x24) - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ tag_22: pop returndatasize jump(tag_23) tag_16: - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ dup3 mload returndatasize @@ -264,23 +264,23 @@ sub_0: assembly { swap1 revert tag_14: - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ shl(0xe0, 0x4e487b71) - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ 0x00 - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ mstore 0x11 - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ 0x04 - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ mstore 0x24 - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ 0x00 - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ revert - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ tag_6: pop jumpi(tag_26, callvalue) @@ -297,9 +297,9 @@ sub_0: assembly { tag_4: jumpi(tag_26, callvalue) jumpi(tag_26, slt(add(not(0x03), calldatasize), 0x00)) - /* \"C\":290:298 immutVar */ + /* \"C\":326:334 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ swap1 dup2 0x29 @@ -311,13 +311,13 @@ sub_0: assembly { and tag_14 jumpi - /* \"C\":79:428 contract C... */ + /* \"C\":79:503 contract C... */ 0x20 swap2 dup2 mstore return - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ tag_1: swap2 swap1 @@ -356,7 +356,7 @@ sub_0: assembly { { "evm": { - "assembly": " /* \"D\":91:166 contract D is C(3)... */ + "assembly": " /* \"D\":91:181 contract D is C(3)... */ 0xa0 jumpi(tag_5, callvalue) 0x1f @@ -398,13 +398,13 @@ sub_0: assembly { tag_5 jumpi mload - /* \"C\":147:149 42 */ + /* \"C\":153:155 42 */ mstore(0x80, 0x2a) - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ dup1 /* \"D\":107:108 3 */ 0x03 - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ add swap1 dup2 @@ -422,9 +422,9 @@ sub_0: assembly { dataOffset(sub_0) dup3 codecopy - /* \"C\":147:149 42 */ + /* \"C\":153:155 42 */ 0x80 - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ mload dup2 assignImmutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") @@ -444,7 +444,7 @@ tag_3: stop sub_0: assembly { - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ 0x80 0x40 swap1 @@ -494,21 +494,21 @@ sub_0: assembly { dup2 mload shl(0xe4, 0x026121ff) - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ dup2 mstore - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ swap2 swap1 - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ 0x20 - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ dup4 0x04 dup2 - /* \"C\":403:407 this */ + /* \"C\":475:479 this */ address - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ gas staticcall swap3 @@ -516,50 +516,50 @@ sub_0: assembly { iszero tag_16 jumpi - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ 0x00 - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ swap4 tag_18 jumpi - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ tag_19: - /* \"C\":392:411 stateVar + this.f() */ + /* \"C\":464:483 stateVar + this.f() */ pop tag_20 - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ 0x20 - /* \"C\":392:411 stateVar + this.f() */ + /* \"C\":464:483 stateVar + this.f() */ swap4 - /* \"C\":392:422 stateVar + this.f() + immutVar */ + /* \"C\":464:494 stateVar + this.f() + immutVar */ tag_21 - /* \"C\":392:411 stateVar + this.f() */ + /* \"C\":464:483 stateVar + this.f() */ swap3 tag_1 jump\t// in tag_20: - /* \"C\":414:422 immutVar */ + /* \"C\":486:494 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") - /* \"C\":392:422 stateVar + this.f() + immutVar */ + /* \"C\":464:494 stateVar + this.f() + immutVar */ swap1 tag_1 jump\t// in tag_21: - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ swap1 mload swap1 dup2 mstore return - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ tag_18: swap3 pop 0x20 jumpi(tag_22, gt(0x20, returndatasize)) tag_23: - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ 0x1f dup2 add @@ -576,18 +576,18 @@ sub_0: assembly { or tag_24 jumpi - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ 0x20 - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ swap2 dup6 swap2 dup6 mstore - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ dup2 add - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ sub slt tag_26 @@ -595,30 +595,30 @@ sub_0: assembly { swap2 mload swap2 - /* \"C\":392:411 stateVar + this.f() */ + /* \"C\":464:483 stateVar + this.f() */ tag_20 - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ jump(tag_19) - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ tag_26: 0x00 dup1 revert tag_24: - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ shl(0xe0, 0x4e487b71) - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ 0x00 mstore mstore(0x04, 0x41) revert(0x00, 0x24) - /* \"C\":403:411 this.f() */ + /* \"C\":475:483 this.f() */ tag_22: pop returndatasize jump(tag_23) tag_16: - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ dup3 mload returndatasize @@ -629,23 +629,23 @@ sub_0: assembly { swap1 revert tag_14: - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ shl(0xe0, 0x4e487b71) - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ 0x00 - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ mstore 0x11 - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ 0x04 - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ mstore 0x24 - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ 0x00 - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ revert - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ tag_6: pop jumpi(tag_26, callvalue) @@ -662,9 +662,9 @@ sub_0: assembly { tag_4: jumpi(tag_26, callvalue) jumpi(tag_26, slt(add(not(0x03), calldatasize), 0x00)) - /* \"C\":290:298 immutVar */ + /* \"C\":326:334 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ swap1 dup2 0x29 @@ -676,13 +676,13 @@ sub_0: assembly { and tag_14 jumpi - /* \"D\":91:166 contract D is C(3)... */ + /* \"D\":91:181 contract D is C(3)... */ 0x20 swap2 dup2 mstore return - /* \"C\":117:119 41 */ + /* \"C\":120:122 41 */ tag_1: swap2 swap1 diff --git a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json index 267116272..54748658f 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json @@ -9,7 +9,7 @@ /// @use-src 0:\"C\" object \"C_54\" { code { - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" mstore(64, memoryguard(160)) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -136,31 +136,31 @@ object \"C_54\" { } /// @ast-id 20 - /// @src 0:182:230 \"constructor(int _init)...\" + /// @src 0:194:254 \"constructor(int _init)...\" function constructor_C_54(var__init_12) { - /// @src 0:182:230 \"constructor(int _init)...\" + /// @src 0:194:254 \"constructor(int _init)...\" - /// @src 0:154:156 \"42\" + /// @src 0:160:162 \"42\" let expr_7 := 0x2a let _3 := convert_t_rational_42_by_1_to_t_int256(expr_7) mstore(128, _3) - /// @src 0:221:226 \"_init\" + /// @src 0:242:247 \"_init\" let _4 := var__init_12 let expr_16 := _4 - /// @src 0:210:226 \"stateVar = _init\" + /// @src 0:231:247 \"stateVar = _init\" update_storage_value_offset_0t_int256_to_t_int256(0x00, expr_16) let expr_17 := expr_16 } - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" } /// @use-src 0:\"C\" object \"C_54_deployed\" { code { - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" mstore(64, memoryguard(128)) if iszero(lt(calldatasize(), 4)) @@ -272,7 +272,7 @@ object \"C_54\" { } /// @ast-id 10 - /// @src 0:159:178 \"int public stateVar\" + /// @src 0:168:187 \"int public stateVar\" function getter_fun_stateVar_10() -> ret { let slot := 0 @@ -281,7 +281,7 @@ object \"C_54\" { ret := read_from_storage_split_dynamic_t_int256(slot, offset) } - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" function external_fun_stateVar_10() { @@ -317,9 +317,9 @@ object \"C_54\" { converted := cleanup_t_int256(identity(cleanup_t_rational_41_by_1(value))) } - /// @src 0:93:126 \"int public constant constVar = 41\" + /// @src 0:96:129 \"int public constant constVar = 41\" function constant_constVar_5() -> ret { - /// @src 0:124:126 \"41\" + /// @src 0:127:129 \"41\" let expr_4 := 0x29 let _1 := convert_t_rational_41_by_1_to_t_int256(expr_4) @@ -327,11 +327,11 @@ object \"C_54\" { } /// @ast-id 5 - /// @src 0:93:126 \"int public constant constVar = 41\" + /// @src 0:96:129 \"int public constant constVar = 41\" function getter_fun_constVar_5() -> ret_0 { ret_0 := constant_constVar_5() } - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" function external_fun_constVar_5() { @@ -373,26 +373,26 @@ object \"C_54\" { } /// @ast-id 30 - /// @src 0:233:309 \"function f() external pure returns (int)...\" + /// @src 0:260:348 \"function f() external pure returns (int)...\" function fun_f_30() -> var__23 { - /// @src 0:269:272 \"int\" + /// @src 0:296:299 \"int\" let zero_t_int256_2 := zero_value_for_split_t_int256() var__23 := zero_t_int256_2 - /// @src 0:286:294 \"constVar\" + /// @src 0:322:330 \"constVar\" let expr_25 := constant_constVar_5() - /// @src 0:297:305 \"immutVar\" + /// @src 0:333:341 \"immutVar\" let _3 := loadimmutable(\"8\") let expr_26 := _3 - /// @src 0:286:305 \"constVar + immutVar\" + /// @src 0:322:341 \"constVar + immutVar\" let expr_27 := checked_add_t_int256(expr_25, expr_26) - /// @src 0:279:305 \"return constVar + immutVar\" + /// @src 0:315:341 \"return constVar + immutVar\" var__23 := expr_27 leave } - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" function shift_right_0_unsigned(value) -> newValue { newValue := @@ -444,20 +444,20 @@ object \"C_54\" { } /// @ast-id 37 - /// @src 0:311:348 \"modifier m()...\" + /// @src 0:353:408 \"modifier m()...\" function modifier_m_40(var__42) -> _5 { _5 := var__42 - /// @src 0:329:339 \"stateVar++\" + /// @src 0:380:390 \"stateVar++\" let _7 := read_from_storage_split_offset_0_t_int256(0x00) let _6 := increment_t_int256(_7) update_storage_value_offset_0t_int256_to_t_int256(0x00, _6) let expr_33 := _7 - /// @src 0:343:344 \"_\" + /// @src 0:400:401 \"_\" _5 := fun_f2_53_inner(var__42) } - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" function cleanup_t_uint160(value) -> cleaned { cleaned := and(value, 0xffffffffffffffffffffffffffffffffffffffff) @@ -539,19 +539,19 @@ object \"C_54\" { revert(pos, returndatasize()) } - /// @src 0:350:433 \"function f2() m public returns (int)...\" + /// @src 0:413:508 \"function f2() m public returns (int)...\" function fun_f2_53_inner(_8) -> var__42 { var__42 := _8 - /// @src 0:399:407 \"stateVar\" + /// @src 0:471:479 \"stateVar\" let _9 := read_from_storage_split_offset_0_t_int256(0x00) let expr_44 := _9 - /// @src 0:410:414 \"this\" + /// @src 0:482:486 \"this\" let expr_45_address := address() - /// @src 0:410:416 \"this.f\" + /// @src 0:482:488 \"this.f\" let expr_46_address := convert_t_contract$_C_$54_to_t_address(expr_45_address) let expr_46_functionSelector := 0x26121ff0 - /// @src 0:410:418 \"this.f()\" + /// @src 0:482:490 \"this.f()\" // storage for arguments and returned data let _10 := allocate_unbounded() @@ -577,32 +577,32 @@ object \"C_54\" { // decode return parameters from external try-call into retVars expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, _13)) } - /// @src 0:399:418 \"stateVar + this.f()\" + /// @src 0:471:490 \"stateVar + this.f()\" let expr_48 := checked_add_t_int256(expr_44, expr_47) - /// @src 0:421:429 \"immutVar\" + /// @src 0:493:501 \"immutVar\" let _14 := loadimmutable(\"8\") let expr_49 := _14 - /// @src 0:399:429 \"stateVar + this.f() + immutVar\" + /// @src 0:471:501 \"stateVar + this.f() + immutVar\" let expr_50 := checked_add_t_int256(expr_48, expr_49) - /// @src 0:392:429 \"return stateVar + this.f() + immutVar\" + /// @src 0:464:501 \"return stateVar + this.f() + immutVar\" var__42 := expr_50 leave } - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" /// @ast-id 53 - /// @src 0:350:433 \"function f2() m public returns (int)...\" + /// @src 0:413:508 \"function f2() m public returns (int)...\" function fun_f2_53() -> var__42 { - /// @src 0:382:385 \"int\" + /// @src 0:445:448 \"int\" let zero_t_int256_4 := zero_value_for_split_t_int256() var__42 := zero_t_int256_4 var__42 := modifier_m_40(var__42) } - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" } @@ -616,7 +616,7 @@ object \"C_54\" { object \"C_54\" { code { { - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" let _1 := memoryguard(0xa0) if callvalue() { revert(0, 0) } let programSize := datasize(\"C_54\") @@ -624,9 +624,9 @@ object \"C_54\" { let newFreePtr := add(_1, and(add(argSize, 31), not(31))) if or(gt(newFreePtr, sub(shl(64, 1), 1)), lt(newFreePtr, _1)) { - mstore(/** @src -1:-1:-1 */ 0, /** @src 0:79:435 \"contract C...\" */ shl(224, 0x4e487b71)) + mstore(/** @src -1:-1:-1 */ 0, /** @src 0:79:510 \"contract C...\" */ shl(224, 0x4e487b71)) mstore(4, 0x41) - revert(/** @src -1:-1:-1 */ 0, /** @src 0:79:435 \"contract C...\" */ 0x24) + revert(/** @src -1:-1:-1 */ 0, /** @src 0:79:510 \"contract C...\" */ 0x24) } mstore(64, newFreePtr) codecopy(_1, programSize, argSize) @@ -634,17 +634,17 @@ object \"C_54\" { { revert(/** @src -1:-1:-1 */ 0, 0) } - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" let value := mload(_1) - /// @src 0:154:156 \"42\" + /// @src 0:160:162 \"42\" mstore(128, 0x2a) - /// @src 0:79:435 \"contract C...\" - sstore(/** @src -1:-1:-1 */ 0, /** @src 0:79:435 \"contract C...\" */ value) + /// @src 0:79:510 \"contract C...\" + sstore(/** @src -1:-1:-1 */ 0, /** @src 0:79:510 \"contract C...\" */ value) let _2 := mload(64) let _3 := datasize(\"C_54_deployed\") codecopy(_2, dataoffset(\"C_54_deployed\"), _3) - setimmutable(_2, \"8\", mload(/** @src 0:154:156 \"42\" */ 128)) - /// @src 0:79:435 \"contract C...\" + setimmutable(_2, \"8\", mload(/** @src 0:160:162 \"42\" */ 128)) + /// @src 0:79:510 \"contract C...\" return(_2, _3) } } @@ -652,7 +652,7 @@ object \"C_54\" { object \"C_54_deployed\" { code { { - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" let _1 := memoryguard(0x80) let _2 := 64 mstore(_2, _1) @@ -662,10 +662,10 @@ object \"C_54\" { case 0x26121ff0 { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - /// @src 0:297:305 \"immutVar\" + /// @src 0:333:341 \"immutVar\" let _3 := loadimmutable(\"8\") - /// @src 0:79:435 \"contract C...\" - let sum := add(/** @src 0:124:126 \"41\" */ 0x29, /** @src 0:79:435 \"contract C...\" */ _3) + /// @src 0:79:510 \"contract C...\" + let sum := add(/** @src 0:127:129 \"41\" */ 0x29, /** @src 0:79:510 \"contract C...\" */ _3) if and(1, slt(sum, _3)) { mstore(0, shl(224, 0x4e487b71)) @@ -695,27 +695,27 @@ object \"C_54\" { } let ret := add(_5, 1) sstore(0, ret) - /// @src 0:410:418 \"this.f()\" - let _6 := /** @src 0:79:435 \"contract C...\" */ mload(_2) - /// @src 0:410:418 \"this.f()\" - mstore(_6, /** @src 0:79:435 \"contract C...\" */ shl(228, 0x026121ff)) - /// @src 0:410:418 \"this.f()\" - let _7 := staticcall(gas(), /** @src 0:410:414 \"this\" */ address(), /** @src 0:410:418 \"this.f()\" */ _6, /** @src 0:79:435 \"contract C...\" */ 4, /** @src 0:410:418 \"this.f()\" */ _6, 32) + /// @src 0:482:490 \"this.f()\" + let _6 := /** @src 0:79:510 \"contract C...\" */ mload(_2) + /// @src 0:482:490 \"this.f()\" + mstore(_6, /** @src 0:79:510 \"contract C...\" */ shl(228, 0x026121ff)) + /// @src 0:482:490 \"this.f()\" + let _7 := staticcall(gas(), /** @src 0:482:486 \"this\" */ address(), /** @src 0:482:490 \"this.f()\" */ _6, /** @src 0:79:510 \"contract C...\" */ 4, /** @src 0:482:490 \"this.f()\" */ _6, 32) if iszero(_7) { - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" let pos := mload(_2) returndatacopy(pos, 0, returndatasize()) revert(pos, returndatasize()) } - /// @src 0:410:418 \"this.f()\" - let expr := /** @src 0:79:435 \"contract C...\" */ 0 - /// @src 0:410:418 \"this.f()\" + /// @src 0:482:490 \"this.f()\" + let expr := /** @src 0:79:510 \"contract C...\" */ 0 + /// @src 0:482:490 \"this.f()\" if _7 { let _8 := 32 if gt(32, returndatasize()) { _8 := returndatasize() } - /// @src 0:79:435 \"contract C...\" + /// @src 0:79:510 \"contract C...\" let newFreePtr := add(_6, and(add(_8, 31), not(31))) if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _6)) { @@ -724,27 +724,27 @@ object \"C_54\" { revert(0, 0x24) } mstore(_2, newFreePtr) - if slt(sub(/** @src 0:410:418 \"this.f()\" */ add(_6, _8), /** @src 0:79:435 \"contract C...\" */ _6), /** @src 0:410:418 \"this.f()\" */ 32) - /// @src 0:79:435 \"contract C...\" + if slt(sub(/** @src 0:482:490 \"this.f()\" */ add(_6, _8), /** @src 0:79:510 \"contract C...\" */ _6), /** @src 0:482:490 \"this.f()\" */ 32) + /// @src 0:79:510 \"contract C...\" { revert(0, 0) } - /// @src 0:410:418 \"this.f()\" - expr := /** @src 0:79:435 \"contract C...\" */ mload(_6) + /// @src 0:482:490 \"this.f()\" + expr := /** @src 0:79:510 \"contract C...\" */ mload(_6) } - /// @src 0:399:418 \"stateVar + this.f()\" + /// @src 0:471:490 \"stateVar + this.f()\" let expr_1 := checked_add_int256(ret, expr) - /// @src 0:392:429 \"return stateVar + this.f() + immutVar\" - let var := /** @src 0:399:429 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:421:429 \"immutVar\" */ loadimmutable(\"8\")) - /// @src 0:79:435 \"contract C...\" + /// @src 0:464:501 \"return stateVar + this.f() + immutVar\" + let var := /** @src 0:471:501 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:493:501 \"immutVar\" */ loadimmutable(\"8\")) + /// @src 0:79:510 \"contract C...\" let memPos_1 := mload(_2) mstore(memPos_1, var) - return(memPos_1, /** @src 0:410:418 \"this.f()\" */ 32) + return(memPos_1, /** @src 0:482:490 \"this.f()\" */ 32) } - case /** @src 0:79:435 \"contract C...\" */ 0xa00b982b { + case /** @src 0:79:510 \"contract C...\" */ 0xa00b982b { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } let memPos_2 := mload(_2) - mstore(memPos_2, /** @src 0:124:126 \"41\" */ 0x29) - /// @src 0:79:435 \"contract C...\" + mstore(memPos_2, /** @src 0:127:129 \"41\" */ 0x29) + /// @src 0:79:510 \"contract C...\" return(memPos_2, 32) } } @@ -777,7 +777,7 @@ object \"C_54\" { /// @use-src 0:\"C\", 1:\"D\" object \"D_72\" { code { - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" mstore(64, memoryguard(160)) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -944,26 +944,26 @@ object \"D_72\" { } /// @ast-id 71 - /// @src 1:113:164 \"constructor(int _init2)...\" + /// @src 1:116:179 \"constructor(int _init2)...\" function constructor_D_72(var__init2_63) { /// @src 1:107:108 \"3\" let expr_60 := 0x03 let _3 := convert_t_rational_3_by_1_to_t_int256(expr_60) - /// @src 1:113:164 \"constructor(int _init2)...\" + /// @src 1:116:179 \"constructor(int _init2)...\" constructor_C_54(_3) - /// @src 1:154:160 \"_init2\" + /// @src 1:166:172 \"_init2\" let _4 := var__init2_63 let expr_67 := _4 - /// @src 1:142:160 \"stateVar += _init2\" + /// @src 1:154:172 \"stateVar += _init2\" let _5 := read_from_storage_split_offset_0_t_int256(0x00) let expr_68 := checked_add_t_int256(_5, expr_67) update_storage_value_offset_0t_int256_to_t_int256(0x00, expr_68) } - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" function cleanup_t_rational_42_by_1(value) -> cleaned { cleaned := value @@ -974,31 +974,31 @@ object \"D_72\" { } /// @ast-id 20 - /// @src 0:182:230 \"constructor(int _init)...\" + /// @src 0:194:254 \"constructor(int _init)...\" function constructor_C_54(var__init_12) { - /// @src 0:182:230 \"constructor(int _init)...\" + /// @src 0:194:254 \"constructor(int _init)...\" - /// @src 0:154:156 \"42\" + /// @src 0:160:162 \"42\" let expr_7 := 0x2a let _6 := convert_t_rational_42_by_1_to_t_int256(expr_7) mstore(128, _6) - /// @src 0:221:226 \"_init\" + /// @src 0:242:247 \"_init\" let _7 := var__init_12 let expr_16 := _7 - /// @src 0:210:226 \"stateVar = _init\" + /// @src 0:231:247 \"stateVar = _init\" update_storage_value_offset_0t_int256_to_t_int256(0x00, expr_16) let expr_17 := expr_16 } - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" } /// @use-src 0:\"C\", 1:\"D\" object \"D_72_deployed\" { code { - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" mstore(64, memoryguard(128)) if iszero(lt(calldatasize(), 4)) @@ -1110,7 +1110,7 @@ object \"D_72\" { } /// @ast-id 10 - /// @src 0:159:178 \"int public stateVar\" + /// @src 0:168:187 \"int public stateVar\" function getter_fun_stateVar_10() -> ret { let slot := 0 @@ -1119,7 +1119,7 @@ object \"D_72\" { ret := read_from_storage_split_dynamic_t_int256(slot, offset) } - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" function external_fun_stateVar_10() { @@ -1155,9 +1155,9 @@ object \"D_72\" { converted := cleanup_t_int256(identity(cleanup_t_rational_41_by_1(value))) } - /// @src 0:93:126 \"int public constant constVar = 41\" + /// @src 0:96:129 \"int public constant constVar = 41\" function constant_constVar_5() -> ret { - /// @src 0:124:126 \"41\" + /// @src 0:127:129 \"41\" let expr_4 := 0x29 let _1 := convert_t_rational_41_by_1_to_t_int256(expr_4) @@ -1165,11 +1165,11 @@ object \"D_72\" { } /// @ast-id 5 - /// @src 0:93:126 \"int public constant constVar = 41\" + /// @src 0:96:129 \"int public constant constVar = 41\" function getter_fun_constVar_5() -> ret_0 { ret_0 := constant_constVar_5() } - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" function external_fun_constVar_5() { @@ -1211,26 +1211,26 @@ object \"D_72\" { } /// @ast-id 30 - /// @src 0:233:309 \"function f() external pure returns (int)...\" + /// @src 0:260:348 \"function f() external pure returns (int)...\" function fun_f_30() -> var__23 { - /// @src 0:269:272 \"int\" + /// @src 0:296:299 \"int\" let zero_t_int256_2 := zero_value_for_split_t_int256() var__23 := zero_t_int256_2 - /// @src 0:286:294 \"constVar\" + /// @src 0:322:330 \"constVar\" let expr_25 := constant_constVar_5() - /// @src 0:297:305 \"immutVar\" + /// @src 0:333:341 \"immutVar\" let _3 := loadimmutable(\"8\") let expr_26 := _3 - /// @src 0:286:305 \"constVar + immutVar\" + /// @src 0:322:341 \"constVar + immutVar\" let expr_27 := checked_add_t_int256(expr_25, expr_26) - /// @src 0:279:305 \"return constVar + immutVar\" + /// @src 0:315:341 \"return constVar + immutVar\" var__23 := expr_27 leave } - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" function shift_right_0_unsigned(value) -> newValue { newValue := @@ -1282,20 +1282,20 @@ object \"D_72\" { } /// @ast-id 37 - /// @src 0:311:348 \"modifier m()...\" + /// @src 0:353:408 \"modifier m()...\" function modifier_m_40(var__42) -> _5 { _5 := var__42 - /// @src 0:329:339 \"stateVar++\" + /// @src 0:380:390 \"stateVar++\" let _7 := read_from_storage_split_offset_0_t_int256(0x00) let _6 := increment_t_int256(_7) update_storage_value_offset_0t_int256_to_t_int256(0x00, _6) let expr_33 := _7 - /// @src 0:343:344 \"_\" + /// @src 0:400:401 \"_\" _5 := fun_f2_53_inner(var__42) } - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" function cleanup_t_uint160(value) -> cleaned { cleaned := and(value, 0xffffffffffffffffffffffffffffffffffffffff) @@ -1377,19 +1377,19 @@ object \"D_72\" { revert(pos, returndatasize()) } - /// @src 0:350:433 \"function f2() m public returns (int)...\" + /// @src 0:413:508 \"function f2() m public returns (int)...\" function fun_f2_53_inner(_8) -> var__42 { var__42 := _8 - /// @src 0:399:407 \"stateVar\" + /// @src 0:471:479 \"stateVar\" let _9 := read_from_storage_split_offset_0_t_int256(0x00) let expr_44 := _9 - /// @src 0:410:414 \"this\" + /// @src 0:482:486 \"this\" let expr_45_address := address() - /// @src 0:410:416 \"this.f\" + /// @src 0:482:488 \"this.f\" let expr_46_address := convert_t_contract$_C_$54_to_t_address(expr_45_address) let expr_46_functionSelector := 0x26121ff0 - /// @src 0:410:418 \"this.f()\" + /// @src 0:482:490 \"this.f()\" // storage for arguments and returned data let _10 := allocate_unbounded() @@ -1415,32 +1415,32 @@ object \"D_72\" { // decode return parameters from external try-call into retVars expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, _13)) } - /// @src 0:399:418 \"stateVar + this.f()\" + /// @src 0:471:490 \"stateVar + this.f()\" let expr_48 := checked_add_t_int256(expr_44, expr_47) - /// @src 0:421:429 \"immutVar\" + /// @src 0:493:501 \"immutVar\" let _14 := loadimmutable(\"8\") let expr_49 := _14 - /// @src 0:399:429 \"stateVar + this.f() + immutVar\" + /// @src 0:471:501 \"stateVar + this.f() + immutVar\" let expr_50 := checked_add_t_int256(expr_48, expr_49) - /// @src 0:392:429 \"return stateVar + this.f() + immutVar\" + /// @src 0:464:501 \"return stateVar + this.f() + immutVar\" var__42 := expr_50 leave } - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" /// @ast-id 53 - /// @src 0:350:433 \"function f2() m public returns (int)...\" + /// @src 0:413:508 \"function f2() m public returns (int)...\" function fun_f2_53() -> var__42 { - /// @src 0:382:385 \"int\" + /// @src 0:445:448 \"int\" let zero_t_int256_4 := zero_value_for_split_t_int256() var__42 := zero_t_int256_4 var__42 := modifier_m_40(var__42) } - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" } @@ -1454,7 +1454,7 @@ object \"D_72\" { object \"D_72\" { code { { - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" let _1 := memoryguard(0xa0) if callvalue() { revert(0, 0) } let programSize := datasize(\"D_72\") @@ -1462,9 +1462,9 @@ object \"D_72\" { let newFreePtr := add(_1, and(add(argSize, 31), not(31))) if or(gt(newFreePtr, sub(shl(64, 1), 1)), lt(newFreePtr, _1)) { - mstore(/** @src -1:-1:-1 */ 0, /** @src 1:91:166 \"contract D is C(3)...\" */ shl(224, 0x4e487b71)) + mstore(/** @src -1:-1:-1 */ 0, /** @src 1:91:181 \"contract D is C(3)...\" */ shl(224, 0x4e487b71)) mstore(4, 0x41) - revert(/** @src -1:-1:-1 */ 0, /** @src 1:91:166 \"contract D is C(3)...\" */ 0x24) + revert(/** @src -1:-1:-1 */ 0, /** @src 1:91:181 \"contract D is C(3)...\" */ 0x24) } mstore(64, newFreePtr) codecopy(_1, programSize, argSize) @@ -1472,24 +1472,24 @@ object \"D_72\" { { revert(/** @src -1:-1:-1 */ 0, 0) } - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" let value := mload(_1) - /// @src 0:154:156 \"42\" + /// @src 0:160:162 \"42\" mstore(128, 0x2a) - /// @src 1:91:166 \"contract D is C(3)...\" - let sum := add(/** @src 1:107:108 \"3\" */ 0x03, /** @src 1:91:166 \"contract D is C(3)...\" */ value) + /// @src 1:91:181 \"contract D is C(3)...\" + let sum := add(/** @src 1:107:108 \"3\" */ 0x03, /** @src 1:91:181 \"contract D is C(3)...\" */ value) if and(1, slt(sum, value)) { - mstore(/** @src -1:-1:-1 */ 0, /** @src 1:91:166 \"contract D is C(3)...\" */ shl(224, 0x4e487b71)) + mstore(/** @src -1:-1:-1 */ 0, /** @src 1:91:181 \"contract D is C(3)...\" */ shl(224, 0x4e487b71)) mstore(4, 0x11) - revert(/** @src -1:-1:-1 */ 0, /** @src 1:91:166 \"contract D is C(3)...\" */ 0x24) + revert(/** @src -1:-1:-1 */ 0, /** @src 1:91:181 \"contract D is C(3)...\" */ 0x24) } - sstore(/** @src -1:-1:-1 */ 0, /** @src 1:91:166 \"contract D is C(3)...\" */ sum) + sstore(/** @src -1:-1:-1 */ 0, /** @src 1:91:181 \"contract D is C(3)...\" */ sum) let _2 := mload(64) let _3 := datasize(\"D_72_deployed\") codecopy(_2, dataoffset(\"D_72_deployed\"), _3) - setimmutable(_2, \"8\", mload(/** @src 0:154:156 \"42\" */ 128)) - /// @src 1:91:166 \"contract D is C(3)...\" + setimmutable(_2, \"8\", mload(/** @src 0:160:162 \"42\" */ 128)) + /// @src 1:91:181 \"contract D is C(3)...\" return(_2, _3) } } @@ -1497,7 +1497,7 @@ object \"D_72\" { object \"D_72_deployed\" { code { { - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" let _1 := memoryguard(0x80) let _2 := 64 mstore(_2, _1) @@ -1507,10 +1507,10 @@ object \"D_72\" { case 0x26121ff0 { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - /// @src 0:297:305 \"immutVar\" + /// @src 0:333:341 \"immutVar\" let _3 := loadimmutable(\"8\") - /// @src 1:91:166 \"contract D is C(3)...\" - let sum := add(/** @src 0:124:126 \"41\" */ 0x29, /** @src 1:91:166 \"contract D is C(3)...\" */ _3) + /// @src 1:91:181 \"contract D is C(3)...\" + let sum := add(/** @src 0:127:129 \"41\" */ 0x29, /** @src 1:91:181 \"contract D is C(3)...\" */ _3) if and(1, slt(sum, _3)) { mstore(0, shl(224, 0x4e487b71)) @@ -1540,27 +1540,27 @@ object \"D_72\" { } let ret := add(_5, 1) sstore(0, ret) - /// @src 0:410:418 \"this.f()\" - let _6 := /** @src 1:91:166 \"contract D is C(3)...\" */ mload(_2) - /// @src 0:410:418 \"this.f()\" - mstore(_6, /** @src 1:91:166 \"contract D is C(3)...\" */ shl(228, 0x026121ff)) - /// @src 0:410:418 \"this.f()\" - let _7 := staticcall(gas(), /** @src 0:410:414 \"this\" */ address(), /** @src 0:410:418 \"this.f()\" */ _6, /** @src 1:91:166 \"contract D is C(3)...\" */ 4, /** @src 0:410:418 \"this.f()\" */ _6, 32) + /// @src 0:482:490 \"this.f()\" + let _6 := /** @src 1:91:181 \"contract D is C(3)...\" */ mload(_2) + /// @src 0:482:490 \"this.f()\" + mstore(_6, /** @src 1:91:181 \"contract D is C(3)...\" */ shl(228, 0x026121ff)) + /// @src 0:482:490 \"this.f()\" + let _7 := staticcall(gas(), /** @src 0:482:486 \"this\" */ address(), /** @src 0:482:490 \"this.f()\" */ _6, /** @src 1:91:181 \"contract D is C(3)...\" */ 4, /** @src 0:482:490 \"this.f()\" */ _6, 32) if iszero(_7) { - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" let pos := mload(_2) returndatacopy(pos, 0, returndatasize()) revert(pos, returndatasize()) } - /// @src 0:410:418 \"this.f()\" - let expr := /** @src 1:91:166 \"contract D is C(3)...\" */ 0 - /// @src 0:410:418 \"this.f()\" + /// @src 0:482:490 \"this.f()\" + let expr := /** @src 1:91:181 \"contract D is C(3)...\" */ 0 + /// @src 0:482:490 \"this.f()\" if _7 { let _8 := 32 if gt(32, returndatasize()) { _8 := returndatasize() } - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 1:91:181 \"contract D is C(3)...\" let newFreePtr := add(_6, and(add(_8, 31), not(31))) if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _6)) { @@ -1569,27 +1569,27 @@ object \"D_72\" { revert(0, 0x24) } mstore(_2, newFreePtr) - if slt(sub(/** @src 0:410:418 \"this.f()\" */ add(_6, _8), /** @src 1:91:166 \"contract D is C(3)...\" */ _6), /** @src 0:410:418 \"this.f()\" */ 32) - /// @src 1:91:166 \"contract D is C(3)...\" + if slt(sub(/** @src 0:482:490 \"this.f()\" */ add(_6, _8), /** @src 1:91:181 \"contract D is C(3)...\" */ _6), /** @src 0:482:490 \"this.f()\" */ 32) + /// @src 1:91:181 \"contract D is C(3)...\" { revert(0, 0) } - /// @src 0:410:418 \"this.f()\" - expr := /** @src 1:91:166 \"contract D is C(3)...\" */ mload(_6) + /// @src 0:482:490 \"this.f()\" + expr := /** @src 1:91:181 \"contract D is C(3)...\" */ mload(_6) } - /// @src 0:399:418 \"stateVar + this.f()\" + /// @src 0:471:490 \"stateVar + this.f()\" let expr_1 := checked_add_int256(ret, expr) - /// @src 0:392:429 \"return stateVar + this.f() + immutVar\" - let var := /** @src 0:399:429 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:421:429 \"immutVar\" */ loadimmutable(\"8\")) - /// @src 1:91:166 \"contract D is C(3)...\" + /// @src 0:464:501 \"return stateVar + this.f() + immutVar\" + let var := /** @src 0:471:501 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:493:501 \"immutVar\" */ loadimmutable(\"8\")) + /// @src 1:91:181 \"contract D is C(3)...\" let memPos_1 := mload(_2) mstore(memPos_1, var) - return(memPos_1, /** @src 0:410:418 \"this.f()\" */ 32) + return(memPos_1, /** @src 0:482:490 \"this.f()\" */ 32) } - case /** @src 1:91:166 \"contract D is C(3)...\" */ 0xa00b982b { + case /** @src 1:91:181 \"contract D is C(3)...\" */ 0xa00b982b { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } let memPos_2 := mload(_2) - mstore(memPos_2, /** @src 0:124:126 \"41\" */ 0x29) - /// @src 1:91:166 \"contract D is C(3)...\" + mstore(memPos_2, /** @src 0:127:129 \"41\" */ 0x29) + /// @src 1:91:181 \"contract D is C(3)...\" return(memPos_2, 32) } } diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_8.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_8.sol index de3237838..1778e22d5 100644 --- a/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_8.sol +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_bmc_iterations_break_8.sol @@ -14,5 +14,5 @@ contract C // SMTSolvers: z3 // BMCLoopIterations: 4 // ---- -// Warning 5740: (78-81): Unreachable code. +// Warning 5740: (77-80): Unreachable code. // Info 6002: BMC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_semantics_2.sol b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_semantics_2.sol index 5b22ca942..157cc61b6 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_semantics_2.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_bmc_iterations_semantics_2.sol @@ -18,5 +18,5 @@ contract C { // SMTSolvers: z3 // BMCLoopIterations: 3 // ---- -// Warning 4661: (220-234): BMC: Assertion violation happens here. +// Warning 4661: (219-233): BMC: Assertion violation happens here. // Info 6002: BMC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 019d45e039b613dddd8edf7771809bcb88c3f838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 12 Apr 2024 16:40:54 +0200 Subject: [PATCH 0059/1340] External tests: Include timing information in the JSON report --- scripts/common.sh | 22 ++++++++++++++++++++++ scripts/externalTests/common.sh | 14 +++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/scripts/common.sh b/scripts/common.sh index d149253bf..81dd2ec49 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -324,3 +324,25 @@ function gnu_grep grep "$@" fi } + +function time_to_json_file +{ + local output_file="$1" + local cmd=("${@:2}") + (( $# >= 2 )) || assertFail + + # $TIMEFORMAT is the format used by built-in `time`. Description is in `man bash`. + local original_timeformat="$TIMEFORMAT" + TIMEFORMAT='{"real": %R, "user": %U, "sys": %S}' + + # We temporarily use descriptors 3 and 4 to preserve stdout and stderr of the original command. + # This allows us to store `time`'s own stderr in a file. Then we restore initial descriptors. + { + { + time { "${cmd[@]}" 1>&3 2>&4; } + } 2> "$output_file" + } 3>&1 4>&2 + + # Restore original format so that it does not spill outside of the function. + TIMEFORMAT="$original_timeformat" +} diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index 8bc9bdf7b..2983b30c2 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -505,14 +505,14 @@ function compile_and_run_test [[ $preset != *" "* ]] || assertFail "Preset names must not contain spaces." printLog "Running compile function..." - time $compile_fn - $verify_fn "$SOLCVERSION_SHORT" "$SOLCVERSION" + time_to_json_file "$(compilation_time_report_path "$preset")" "$compile_fn" + "$verify_fn" "$SOLCVERSION_SHORT" "$SOLCVERSION" if [[ "$COMPILE_ONLY" == 1 || " $compile_only_presets " == *" $preset "* ]]; then printLog "Skipping test function..." else printLog "Running test function..." - $test_fn + "$test_fn" fi } @@ -572,6 +572,13 @@ function gas_report_path echo "${DIR}/gas-report-${preset}.rst" } +function compilation_time_report_path +{ + local preset="$1" + + echo "${DIR}/compilation-time-report-${preset}.json" +} + function gas_report_to_json { cat - | "${REPO_ROOT}/scripts/externalTests/parse_eth_gas_report.py" | jq '{gas: .}' @@ -679,5 +686,6 @@ function store_benchmark_report "bytecode_size_json_from_${framework}_artifacts" | combine_artifact_json project_info_json "$project_url" + echo "{\"compilation_time\": $(cat "$(compilation_time_report_path "$preset")")}" } | jq --slurp "{\"${project_name}\": {\"${preset}\": add}}" --indent 4 --sort-keys > "$output_file" } From d96043f2d33ac4c30cbe0230b5737465ff1668d5 Mon Sep 17 00:00:00 2001 From: Vijay Raj Panchal <42858378+vijayrajpanchall@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:32:57 +0530 Subject: [PATCH 0060/1340] Update Changelog.md Refactor: Update date to reflect current year in version 0.8.25 (2024-03-14) entry --- Changelog.md | 2 +- docs/bugs_by_version.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index ccc2de41a..029f1944d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,7 +11,7 @@ Bugfixes: * SMTChecker: Fix internal error when using bitwise operators with an array element as argument. -### 0.8.25 (2023-03-14) +### 0.8.25 (2024-03-14) Compiler Features: * Code Generator: Use ``MCOPY`` instead of ``MLOAD``/``MSTORE`` loop when copying byte arrays. diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 7022635fd..52b6c9f48 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1892,7 +1892,7 @@ }, "0.8.25": { "bugs": [], - "released": "2023-03-14" + "released": "2024-03-14" }, "0.8.3": { "bugs": [ From 581d81434fa548f0425862d7a3fc68cb3fac9bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 12 Apr 2024 13:04:05 +0200 Subject: [PATCH 0061/1340] time benchmarks: Actually ignore errors from legacy compilation --- test/benchmarks/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/run.sh b/test/benchmarks/run.sh index ef1c146f0..251e5dc3f 100755 --- a/test/benchmarks/run.sh +++ b/test/benchmarks/run.sh @@ -51,7 +51,7 @@ do solc_command_via_ir=("${solc}" --via-ir --optimize --bin --color "${input_path}") # Legacy can fail. - "${time_bin_path}" --output "${result_legacy_file}" --format "%e" "${solc_command_legacy[@]}" >/dev/null 2>>"${warnings_and_errors_file}" + "${time_bin_path}" --output "${result_legacy_file}" --format "%e" "${solc_command_legacy[@]}" >/dev/null 2>>"${warnings_and_errors_file}" || true "${time_bin_path}" --output "${result_via_ir_file}" --format "%e" "${solc_command_via_ir[@]}" >/dev/null 2>>"${warnings_and_errors_file}" time_legacy=$(<"${result_legacy_file}") From d6198ee819f82e8956de55d0c0aa3eb7bb117578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 12 Apr 2024 13:06:49 +0200 Subject: [PATCH 0062/1340] time benchmarks: Add bytecode size measurement --- test/benchmarks/run.sh | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/test/benchmarks/run.sh b/test/benchmarks/run.sh index 251e5dc3f..d97c53252 100755 --- a/test/benchmarks/run.sh +++ b/test/benchmarks/run.sh @@ -26,6 +26,9 @@ set -euo pipefail REPO_ROOT=$(cd "$(dirname "$0")/../../" && pwd) SOLIDITY_BUILD_DIR=${SOLIDITY_BUILD_DIR:-${REPO_ROOT}/build} +# shellcheck source=scripts/common_cmdline.sh +source "${REPO_ROOT}/scripts/common_cmdline.sh" + output_dir=$(mktemp -d -t solc-benchmark-XXXXXX) result_legacy_file="${output_dir}/benchmark-legacy.txt" result_via_ir_file="${output_dir}/benchmark-via-ir.txt" @@ -38,6 +41,12 @@ function cleanup() { trap cleanup SIGINT SIGTERM +function bytecode_size { + local bytecode_chars + bytecode_chars=$(stripCLIDecorations | stripEmptyLines | wc --chars) + echo $(( bytecode_chars / 2 )) +} + solc="${SOLIDITY_BUILD_DIR}/solc/solc" benchmarks_dir="${REPO_ROOT}/test/benchmarks" benchmarks=("chains.sol" "OptimizorClub.sol" "verifier.sol") @@ -51,17 +60,20 @@ do solc_command_via_ir=("${solc}" --via-ir --optimize --bin --color "${input_path}") # Legacy can fail. - "${time_bin_path}" --output "${result_legacy_file}" --format "%e" "${solc_command_legacy[@]}" >/dev/null 2>>"${warnings_and_errors_file}" || true - "${time_bin_path}" --output "${result_via_ir_file}" --format "%e" "${solc_command_via_ir[@]}" >/dev/null 2>>"${warnings_and_errors_file}" + "${time_bin_path}" --output "${result_legacy_file}" --format "%e" "${solc_command_legacy[@]}" >"${output_dir}/bytecode-legacy.bin" 2>>"${warnings_and_errors_file}" || true + "${time_bin_path}" --output "${result_via_ir_file}" --format "%e" "${solc_command_via_ir[@]}" >"${output_dir}/bytecode-via-ir.bin" 2>>"${warnings_and_errors_file}" time_legacy=$(<"${result_legacy_file}") time_via_ir=$(<"${result_via_ir_file}") + bytecode_size_legacy=$(bytecode_size <"${output_dir}/bytecode-legacy.bin") + bytecode_size_via_ir=$(bytecode_size <"${output_dir}/bytecode-via-ir.bin") + echo "=======================================================" echo " ${input_file}" echo "-------------------------------------------------------" - echo "legacy pipeline took ${time_legacy} seconds to execute." - echo "via-ir pipeline took ${time_via_ir} seconds to execute." + echo "legacy pipeline took ${time_legacy} seconds to execute. Bytecode size is ${bytecode_size_legacy} bytes." + echo "via-ir pipeline took ${time_via_ir} seconds to execute. Bytecode size is ${bytecode_size_viar_ir} bytes." echo "=======================================================" done From 1317bcc9baa707fd6edd942b2d9f62322ea89eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 12 Apr 2024 13:13:23 +0200 Subject: [PATCH 0063/1340] time benchmarks: Accept solc binary as argument and add minimal validations --- test/benchmarks/run.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/benchmarks/run.sh b/test/benchmarks/run.sh index d97c53252..8c4a660f8 100755 --- a/test/benchmarks/run.sh +++ b/test/benchmarks/run.sh @@ -26,9 +26,16 @@ set -euo pipefail REPO_ROOT=$(cd "$(dirname "$0")/../../" && pwd) SOLIDITY_BUILD_DIR=${SOLIDITY_BUILD_DIR:-${REPO_ROOT}/build} +# shellcheck source=scripts/common.sh +source "${REPO_ROOT}/scripts/common.sh" # shellcheck source=scripts/common_cmdline.sh source "${REPO_ROOT}/scripts/common_cmdline.sh" +(( $# <= 1 )) || fail "Too many arguments. Usage: run.sh []" + +solc="${1:-${SOLIDITY_BUILD_DIR}/solc/solc}" +command_available "$solc" --version + output_dir=$(mktemp -d -t solc-benchmark-XXXXXX) result_legacy_file="${output_dir}/benchmark-legacy.txt" result_via_ir_file="${output_dir}/benchmark-via-ir.txt" @@ -47,7 +54,6 @@ function bytecode_size { echo $(( bytecode_chars / 2 )) } -solc="${SOLIDITY_BUILD_DIR}/solc/solc" benchmarks_dir="${REPO_ROOT}/test/benchmarks" benchmarks=("chains.sol" "OptimizorClub.sol" "verifier.sol") time_bin_path=$(type -P time) From 50433df2f1f32cf6577718fc45f4ffae2cddf167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 12 Apr 2024 13:40:22 +0200 Subject: [PATCH 0064/1340] time benchmarks: Format results as a markdown table --- test/benchmarks/run.sh | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/test/benchmarks/run.sh b/test/benchmarks/run.sh index 8c4a660f8..8bfd32d43 100755 --- a/test/benchmarks/run.sh +++ b/test/benchmarks/run.sh @@ -58,6 +58,9 @@ benchmarks_dir="${REPO_ROOT}/test/benchmarks" benchmarks=("chains.sol" "OptimizorClub.sol" "verifier.sol") time_bin_path=$(type -P time) +echo "| File | Pipeline | Bytecode size | Time | Exit code |" +echo "|----------------------|----------|--------------:|---------:|----------:|" + for input_file in "${benchmarks[@]}" do input_path="${benchmarks_dir}/${input_file}" @@ -66,21 +69,16 @@ do solc_command_via_ir=("${solc}" --via-ir --optimize --bin --color "${input_path}") # Legacy can fail. - "${time_bin_path}" --output "${result_legacy_file}" --format "%e" "${solc_command_legacy[@]}" >"${output_dir}/bytecode-legacy.bin" 2>>"${warnings_and_errors_file}" || true - "${time_bin_path}" --output "${result_via_ir_file}" --format "%e" "${solc_command_via_ir[@]}" >"${output_dir}/bytecode-via-ir.bin" 2>>"${warnings_and_errors_file}" + "${time_bin_path}" --output "${result_legacy_file}" --quiet --format "%e s | %x" "${solc_command_legacy[@]}" >"${output_dir}/bytecode-legacy.bin" 2>>"${warnings_and_errors_file}" || true + "${time_bin_path}" --output "${result_via_ir_file}" --quiet --format "%e s | %x" "${solc_command_via_ir[@]}" >"${output_dir}/bytecode-via-ir.bin" 2>>"${warnings_and_errors_file}" - time_legacy=$(<"${result_legacy_file}") - time_via_ir=$(<"${result_via_ir_file}") + time_and_status_legacy=$(<"${result_legacy_file}") + time_and_status_via_ir=$(<"${result_via_ir_file}") bytecode_size_legacy=$(bytecode_size <"${output_dir}/bytecode-legacy.bin") bytecode_size_via_ir=$(bytecode_size <"${output_dir}/bytecode-via-ir.bin") - - echo "=======================================================" - echo " ${input_file}" - echo "-------------------------------------------------------" - echo "legacy pipeline took ${time_legacy} seconds to execute. Bytecode size is ${bytecode_size_legacy} bytes." - echo "via-ir pipeline took ${time_via_ir} seconds to execute. Bytecode size is ${bytecode_size_viar_ir} bytes." - echo "=======================================================" + printf '| %-20s | legacy | %7d bytes | %20s |\n' '`'"$input_file"'`' "$bytecode_size_legacy" "$time_and_status_legacy" + printf '| %-20s | via-ir | %7d bytes | %20s |\n' '`'"$input_file"'`' "$bytecode_size_via_ir" "$time_and_status_via_ir" done echo From e6bd63be525380a18c63890986c3c7c3def35c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 12 Apr 2024 14:11:20 +0200 Subject: [PATCH 0065/1340] time benchmarks: Reorder input files from fastest to slowest - --- test/benchmarks/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/run.sh b/test/benchmarks/run.sh index 8bfd32d43..8f873fde4 100755 --- a/test/benchmarks/run.sh +++ b/test/benchmarks/run.sh @@ -55,7 +55,7 @@ function bytecode_size { } benchmarks_dir="${REPO_ROOT}/test/benchmarks" -benchmarks=("chains.sol" "OptimizorClub.sol" "verifier.sol") +benchmarks=("verifier.sol" "OptimizorClub.sol" "chains.sol") time_bin_path=$(type -P time) echo "| File | Pipeline | Bytecode size | Time | Exit code |" From 6b83a43ea0b6c0d631f17544b4b889e07b4b18b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 12 Apr 2024 14:14:04 +0200 Subject: [PATCH 0066/1340] time benchmarks: Refactor to reduce repetitiion --- test/benchmarks/run.sh | 47 ++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/test/benchmarks/run.sh b/test/benchmarks/run.sh index 8f873fde4..1784b3700 100755 --- a/test/benchmarks/run.sh +++ b/test/benchmarks/run.sh @@ -37,9 +37,6 @@ solc="${1:-${SOLIDITY_BUILD_DIR}/solc/solc}" command_available "$solc" --version output_dir=$(mktemp -d -t solc-benchmark-XXXXXX) -result_legacy_file="${output_dir}/benchmark-legacy.txt" -result_via_ir_file="${output_dir}/benchmark-via-ir.txt" -warnings_and_errors_file="${output_dir}/benchmark-warn-err.txt" function cleanup() { rm -r "${output_dir}" @@ -54,7 +51,28 @@ function bytecode_size { echo $(( bytecode_chars / 2 )) } -benchmarks_dir="${REPO_ROOT}/test/benchmarks" +function benchmark_contract { + local pipeline="$1" + local input_path="$2" + + local solc_command=("${solc}" --optimize --bin --color "${input_path}") + [[ $pipeline == via-ir ]] && solc_command+=(--via-ir) + local time_args=(--output "${output_dir}/time-and-status-${pipeline}.txt" --quiet --format '%e s | %x') + + # NOTE: Legacy pipeline may fail with "Stack too deep" in some cases. That's fine. + "$time_bin_path" \ + "${time_args[@]}" \ + "${solc_command[@]}" \ + > "${output_dir}/bytecode-${pipeline}.bin" \ + 2>> "${output_dir}/benchmark-warn-err.txt" || [[ $pipeline == legacy ]] + + printf '| %-20s | %s | %7d bytes | %20s |\n' \ + '`'"$input_file"'`' \ + "$pipeline" \ + "$(bytecode_size < "${output_dir}/bytecode-${pipeline}.bin")" \ + "$(< "${output_dir}/time-and-status-${pipeline}.txt")" +} + benchmarks=("verifier.sol" "OptimizorClub.sol" "chains.sol") time_bin_path=$(type -P time) @@ -63,29 +81,14 @@ echo "|----------------------|----------|--------------:|---------:|----------:| for input_file in "${benchmarks[@]}" do - input_path="${benchmarks_dir}/${input_file}" - - solc_command_legacy=("${solc}" --optimize --bin --color "${input_path}") - solc_command_via_ir=("${solc}" --via-ir --optimize --bin --color "${input_path}") - - # Legacy can fail. - "${time_bin_path}" --output "${result_legacy_file}" --quiet --format "%e s | %x" "${solc_command_legacy[@]}" >"${output_dir}/bytecode-legacy.bin" 2>>"${warnings_and_errors_file}" || true - "${time_bin_path}" --output "${result_via_ir_file}" --quiet --format "%e s | %x" "${solc_command_via_ir[@]}" >"${output_dir}/bytecode-via-ir.bin" 2>>"${warnings_and_errors_file}" - - time_and_status_legacy=$(<"${result_legacy_file}") - time_and_status_via_ir=$(<"${result_via_ir_file}") - bytecode_size_legacy=$(bytecode_size <"${output_dir}/bytecode-legacy.bin") - bytecode_size_via_ir=$(bytecode_size <"${output_dir}/bytecode-via-ir.bin") - - printf '| %-20s | legacy | %7d bytes | %20s |\n' '`'"$input_file"'`' "$bytecode_size_legacy" "$time_and_status_legacy" - printf '| %-20s | via-ir | %7d bytes | %20s |\n' '`'"$input_file"'`' "$bytecode_size_via_ir" "$time_and_status_via_ir" + benchmark_contract legacy "${REPO_ROOT}/test/benchmarks/${input_file}" + benchmark_contract via-ir "${REPO_ROOT}/test/benchmarks/${input_file}" done echo echo "=======================================================" echo "Warnings and errors generated during run:" echo "=======================================================" -echo "$(<"${warnings_and_errors_file}")" +echo "$(< "${output_dir}/benchmark-warn-err.txt")" cleanup - From ac76c40ebc4a7ddea4cb545d5ed7e02a014095d1 Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 16 Apr 2024 19:05:39 +0200 Subject: [PATCH 0067/1340] Prevent pnpm frozen lockfile --- .circleci/config.yml | 2 +- test/externalTests/prb-math.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0dd960e93..8b588740f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1452,7 +1452,7 @@ jobs: name: Install dependencies command: | cd hardhat - pnpm install + pnpm install --no-frozen-lockfile - run: name: Run hardhat-core test suite command: | diff --git a/test/externalTests/prb-math.py b/test/externalTests/prb-math.py index 2d1469fc9..0cfefb843 100755 --- a/test/externalTests/prb-math.py +++ b/test/externalTests/prb-math.py @@ -43,7 +43,7 @@ def configure(self): # Starting from version v4.0.2, the default installation method for PRBMath dependencies # has transitioned from Foundry to Node.js. subprocess.run( - ["pnpm", "install"], + ["pnpm", "install", "--no-frozen-lockfile"], env=self.env, check=True ) From 7f882ef57fc47c5b8d821a7eba8900149362b96b Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 4 Mar 2024 10:13:53 +0100 Subject: [PATCH 0068/1340] Bytecode difference caused by SSA transform Changelog Review comments Unique vector Repro test --- Changelog.md | 1 + libsolutil/CommonData.h | 43 ++++++++++++ libyul/optimiser/SSATransform.cpp | 37 ++++++----- scripts/common/cmdline_helpers.py | 46 +++++++++---- .../inputs.sol | 13 ++++ .../test.py | 65 +++++++++++++++++++ .../ssaTransform/function.yul | 8 +-- 7 files changed, 177 insertions(+), 36 deletions(-) create mode 100644 test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/inputs.sol create mode 100755 test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/test.py diff --git a/Changelog.md b/Changelog.md index 029f1944d..a54afa62c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Compiler Features: Bugfixes: * SMTChecker: Fix internal error on mapping access caused by too strong requirements on sort compatibility of the index and mapping domain. * SMTChecker: Fix internal error when using bitwise operators with an array element as argument. + * Yul Optimizer: Fix the order of assignments generated by ``SSATransform`` being dependent on AST IDs, sometimes resulting in different (but equivalent) bytecode when unrelated files were added to the compilation pipeline. ### 0.8.25 (2024-03-14) diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index f3c168e65..de6873845 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -343,6 +343,49 @@ void joinMap(std::map& _a, std::map&& _b, F _conflictSolver) } } +template +class UniqueVector +{ +public: + std::vector const& contents() const { return m_contents; } + size_t size() const { return m_contents.size(); } + bool empty() const { return m_contents.empty(); } + auto begin() const { return m_contents.begin(); } + auto end() const { return m_contents.end(); } + void clear() { m_contents.clear(); } + bool contains(T const& _value) const + { + return std::find(m_contents.begin(), m_contents.end(), _value) != m_contents.end(); + } + + void pushBack(T _value) + { + if (!contains(_value)) + m_contents.emplace_back(std::move(_value)); + } + + void pushBack(UniqueVector const& _values) + { + for (auto&& value: _values) + pushBack(value); + } + + void removeAll(std::vector const& _values) + { + for (auto const& value: _values) + m_contents.erase(std::find(m_contents.begin(), m_contents.end(), value)); + } + +private: + std::vector m_contents; +}; + +template +void swap(UniqueVector& _lhs, UniqueVector& _rhs) +{ + std::swap(_lhs.contents(), _rhs.contents()); +} + namespace detail { diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index 675d21acc..dba2f6f04 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -166,8 +166,8 @@ class IntroduceControlFlowSSA: public ASTModifier std::set const& m_variablesToReplace; /// Variables (that are to be replaced) currently in scope. std::set m_variablesInScope; - /// Set of variables that do not have a specific value. - std::set m_variablesToReassign; + /// Variables that do not have a specific value. + util::UniqueVector m_variablesToReassign; TypeInfo const& m_typeInfo; }; @@ -175,14 +175,14 @@ void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function) { std::set varsInScope; std::swap(varsInScope, m_variablesInScope); - std::set toReassign; + util::UniqueVector 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); + m_variablesToReassign.pushBack(param.name); } ASTModifier::operator()(_function); @@ -196,8 +196,8 @@ void IntroduceControlFlowSSA::operator()(ForLoop& _for) yulAssert(_for.pre.statements.empty(), "For loop init rewriter not run."); for (auto const& var: assignedVariableNames(_for.body) + assignedVariableNames(_for.post)) - if (m_variablesInScope.count(var)) - m_variablesToReassign.insert(var); + if (util::contains(m_variablesInScope,var)) + m_variablesToReassign.pushBack(var); (*this)(_for.body); (*this)(_for.post); @@ -207,26 +207,26 @@ void IntroduceControlFlowSSA::operator()(Switch& _switch) { yulAssert(m_variablesToReassign.empty(), ""); - std::set toReassign; + util::UniqueVector toReassign; for (auto& c: _switch.cases) { (*this)(c.body); - toReassign += m_variablesToReassign; + toReassign.pushBack(m_variablesToReassign); } - m_variablesToReassign += toReassign; + m_variablesToReassign.pushBack(toReassign); } void IntroduceControlFlowSSA::operator()(Block& _block) { - std::set variablesDeclaredHere; - std::set assignedVariables; + util::UniqueVector variablesDeclaredHere; + util::UniqueVector assignedVariables; util::iterateReplacing( _block.statements, [&](Statement& _s) -> std::optional> { - std::vector toPrepend; + std::vector toPrepend; for (YulString toReassign: m_variablesToReassign) { YulString newName = m_nameDispenser.newName(toReassign); @@ -235,7 +235,7 @@ void IntroduceControlFlowSSA::operator()(Block& _block) {TypedName{debugDataOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}}, std::make_unique(Identifier{debugDataOf(_s), toReassign}) }); - assignedVariables.insert(toReassign); + assignedVariables.pushBack(toReassign); } m_variablesToReassign.clear(); @@ -245,7 +245,7 @@ void IntroduceControlFlowSSA::operator()(Block& _block) for (auto const& var: varDecl.variables) if (m_variablesToReplace.count(var.name)) { - variablesDeclaredHere.insert(var.name); + variablesDeclaredHere.pushBack(var.name); m_variablesInScope.insert(var.name); } } @@ -254,7 +254,7 @@ void IntroduceControlFlowSSA::operator()(Block& _block) Assignment& assignment = std::get(_s); for (auto const& var: assignment.variableNames) if (m_variablesToReplace.count(var.name)) - assignedVariables.insert(var.name); + assignedVariables.pushBack(var.name); } else visit(_s); @@ -268,9 +268,10 @@ void IntroduceControlFlowSSA::operator()(Block& _block) } } ); - m_variablesToReassign += assignedVariables; - m_variablesInScope -= variablesDeclaredHere; - m_variablesToReassign -= variablesDeclaredHere; + + m_variablesToReassign.pushBack(assignedVariables); + m_variablesInScope -= variablesDeclaredHere.contents(); + m_variablesToReassign.removeAll(variablesDeclaredHere.contents()); } /** diff --git a/scripts/common/cmdline_helpers.py b/scripts/common/cmdline_helpers.py index ede9f9385..822cf7f85 100644 --- a/scripts/common/cmdline_helpers.py +++ b/scripts/common/cmdline_helpers.py @@ -11,10 +11,12 @@ from bytecodecompare.prepare_report import parse_cli_output -DEFAULT_PREAMBLE = dedent(""" +DEFAULT_PREAMBLE = dedent( + """ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.0; -""") +""" +) def inside_temporary_dir(prefix): @@ -22,8 +24,10 @@ def inside_temporary_dir(prefix): Creates a temporary directory, enters the directory and executes the function inside it. Restores the previous working directory after executing the function. """ + def tmp_dir_decorator(fn): previous_dir = os.getcwd() + def f(*args, **kwargs): try: tmp_dir = mkdtemp(prefix=prefix) @@ -33,35 +37,49 @@ def f(*args, **kwargs): return result finally: os.chdir(previous_dir) + return f + return tmp_dir_decorator -def solc_bin_report(solc_binary: str, input_files: List[Path], via_ir: bool) -> FileReport: +def solc_bin_report( + solc_binary: str, + input_files: List[Path], + via_ir: bool, + optimize: bool = False, + yul_optimizations: Optional[str] = None, +) -> FileReport: """ Runs the solidity compiler binary """ output = subprocess.check_output( - [solc_binary, '--bin'] + - input_files + - (['--via-ir'] if via_ir else []), - encoding='utf8', + [solc_binary, "--bin"] + + input_files + + (["--via-ir"] if via_ir else []) + + (["--optimize"] if optimize else []) + + (["--yul-optimizations", yul_optimizations] if yul_optimizations else []), + encoding="utf8", ) - return parse_cli_output('', output, 0) + return parse_cli_output("", output, 0) -def save_bytecode(bytecode_path: Path, reports: FileReport, contract: Optional[str] = None): - with open(bytecode_path, 'w', encoding='utf8') as f: +def save_bytecode( + bytecode_path: Path, reports: FileReport, contract: Optional[str] = None +): + with open(bytecode_path, "w", encoding="utf8") as f: for report in reports.contract_reports: if contract is None or report.contract_name == contract: - bytecode = report.bytecode if report.bytecode is not None else '' - f.write(f'{report.contract_name}: {bytecode}\n') + bytecode = ( + report.bytecode if report.bytecode is not None else "" + ) + f.write(f"{report.contract_name}: {bytecode}\n") def add_preamble(source_path: Path, preamble: str = DEFAULT_PREAMBLE): - for source in source_path.glob('**/*.sol'): - with open(source, 'r+', encoding='utf8') as f: + for source in source_path.glob("**/*.sol"): + with open(source, "r+", encoding="utf8") as f: content = f.read() f.seek(0, 0) f.write(preamble + content) diff --git a/test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/inputs.sol b/test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/inputs.sol new file mode 100644 index 000000000..ff982c56d --- /dev/null +++ b/test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/inputs.sol @@ -0,0 +1,13 @@ +==== Source: A.sol ==== +contract DummyContract1 {} +contract DummyContract2 {} +contract DummyContract3 {} + +==== Source: B.sol ==== +contract B { + function f(uint8 a_0, uint8 a_1, uint8 a_2) public pure { + a_1 = 1; + a_2 = 2; + a_0; + } +} diff --git a/test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/test.py b/test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/test.py new file mode 100755 index 000000000..e15293b8e --- /dev/null +++ b/test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/test.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +import os +import sys +from pathlib import Path +from textwrap import dedent + +# pylint: disable=wrong-import-position +PROJECT_ROOT = Path(__file__).parents[3] +sys.path.insert(0, str(PROJECT_ROOT / "scripts")) + +from common.cmdline_helpers import add_preamble +from common.cmdline_helpers import inside_temporary_dir +from common.cmdline_helpers import save_bytecode +from common.cmdline_helpers import solc_bin_report +from common.git_helpers import git_diff +from splitSources import split_sources + + +@inside_temporary_dir(Path(__file__).parent.name) +def test_bytecode_equivalence(): + source_file_path = Path(__file__).parent / "inputs.sol" + split_sources(source_file_path, suppress_output=True) + add_preamble(Path.cwd()) + + solc_binary = os.environ.get("SOLC") + if solc_binary is None: + raise RuntimeError( + dedent( + """\ + `solc` compiler not found. + Please ensure you set the SOLC environment variable + with the correct path to the compiler's binary. + """ + ) + ) + + # Repro for https://github.com/ethereum/solidity/issues/14829 + save_bytecode( + Path("B.bin"), + solc_bin_report( + solc_binary, + [Path("B.sol")], + via_ir=True, + optimize=True, + yul_optimizations="a:", + ), + contract="B", + ) + save_bytecode( + Path("AB.bin"), + solc_bin_report( + solc_binary, + [Path("A.sol"), Path("B.sol")], + via_ir=True, + optimize=True, + yul_optimizations="a:", + ), + contract="B", + ) + return git_diff(Path("B.bin"), Path("AB.bin")) + + +if __name__ == "__main__": + sys.exit(test_bytecode_equivalence()) diff --git a/test/libyul/yulOptimizerTests/ssaTransform/function.yul b/test/libyul/yulOptimizerTests/ssaTransform/function.yul index d41c18b04..341d18cc1 100644 --- a/test/libyul/yulOptimizerTests/ssaTransform/function.yul +++ b/test/libyul/yulOptimizerTests/ssaTransform/function.yul @@ -12,15 +12,15 @@ // { // function f(a, b) -> c, d // { -// let b_5 := b -// let a_6 := a -// let b_1 := add(b_5, a_6) +// let a_5 := a +// let b_6 := b +// let b_1 := add(b_6, a_5) // 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_6, d_3) +// let a_4 := add(a_5, d_3) // a := a_4 // } // } From 04b220da0dc5b82a8db213adc60128b5f696906c Mon Sep 17 00:00:00 2001 From: pcw109550 Date: Wed, 17 Apr 2024 09:17:38 -0600 Subject: [PATCH 0069/1340] Fix string/hex string literal implicit conversion to bytesNN --- docs/types/conversion.rst | 9 ++++----- ...ing_to_bytesNN_different_size_implicit.sol | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 test/libsolidity/syntaxTests/types/hex_string_to_bytesNN_different_size_implicit.sol diff --git a/docs/types/conversion.rst b/docs/types/conversion.rst index dafb336bd..92f0e19dc 100644 --- a/docs/types/conversion.rst +++ b/docs/types/conversion.rst @@ -174,15 +174,14 @@ converted to any fixed-size bytes type: bytes4 g = 0x0; // fine String literals and hex string literals can be implicitly converted to fixed-size byte arrays, -if their number of characters matches the size of the bytes type: +if their number of characters is less than or equal to the size of the bytes type: .. code-block:: solidity bytes2 a = hex"1234"; // fine bytes2 b = "xy"; // fine - bytes2 c = hex"12"; // not allowed - bytes2 d = hex"123"; // not allowed - bytes2 e = "x"; // not allowed + bytes2 c = hex"12"; // fine + bytes2 e = "x"; // fine bytes2 f = "xyz"; // not allowed .. index:: literal;address @@ -199,4 +198,4 @@ An ``address a`` can be converted explicitly to ``address payable`` via ``payabl .. note:: Prior to version 0.8.0, it was possible to explicitly convert from any integer type (of any size, signed or unsigned) to ``address`` or ``address payable``. - Starting with in 0.8.0 only conversion from ``uint160`` is allowed. \ No newline at end of file + Starting with 0.8.0 only conversion from ``uint160`` is allowed. diff --git a/test/libsolidity/syntaxTests/types/hex_string_to_bytesNN_different_size_implicit.sol b/test/libsolidity/syntaxTests/types/hex_string_to_bytesNN_different_size_implicit.sol new file mode 100644 index 000000000..177694af1 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/hex_string_to_bytesNN_different_size_implicit.sol @@ -0,0 +1,20 @@ +contract C { + function f() public pure { + bytes1 b1 = hex""; + bytes1 b2 = hex"1234"; + bytes2 b3 = hex"12"; + bytes2 b4 = hex"1234"; + bytes2 b5 = hex"123456"; + bytes3 b6 = hex"1234"; + bytes3 b7 = hex"123456"; + bytes3 b8 = hex"12345678"; + bytes4 b9 = hex"123456"; + bytes4 b10 = hex"12345678"; + bytes4 b11 = hex"1234567890"; + } +} +// ---- +// TypeError 9574: (72-93): Type literal_string hex"1234" is not implicitly convertible to expected type bytes1. Literal is larger than the type. +// TypeError 9574: (154-177): Type literal_string hex"123456" is not implicitly convertible to expected type bytes2. Literal is larger than the type. +// TypeError 9574: (242-267): Type literal_string hex"12345678" is not implicitly convertible to expected type bytes3. Literal is larger than the type. +// TypeError 9574: (337-365): Type literal_string hex"1234567890" is not implicitly convertible to expected type bytes4. Literal is larger than the type. From a0e1a3e2eacb925a291aa416bae9f130b5d3f893 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 26 Mar 2024 16:26:57 -0300 Subject: [PATCH 0070/1340] fix uncaught ICE when --yul-optimizations is empty/blank --- Changelog.md | 2 ++ docs/internals/optimizer.rst | 2 +- libsolidity/interface/CompilerStack.cpp | 5 +--- libsolidity/interface/StandardCompiler.cpp | 7 ++++- libyul/optimiser/Suite.cpp | 20 ++++--------- solc/CommandLineParser.cpp | 11 +++++-- .../input.json | 25 ++++++++++++++++ .../output.json | 19 ++++++++++++ .../input.json | 25 ++++++++++++++++ .../output.json | 19 ++++++++++++ .../output.json | 4 +-- .../input.json | 19 ++++++++++++ .../output.json | 12 ++++++++ .../input.json | 19 ++++++++++++ .../output.json | 12 ++++++++ .../args | 1 + .../input.sol | 3 ++ .../output | 4 +++ .../yul_optimizer_steps_disabled/err | 2 +- test/solc/CommandLineInterface.cpp | 23 +++++++++++++++ test/solc/CommandLineParser.cpp | 29 ++++++++++++++++--- 21 files changed, 233 insertions(+), 30 deletions(-) create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/input.json create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/input.json create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/input.json create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/output.json create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/input.json create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/output.json create mode 100644 test/cmdlineTests/yul_optimizer_disabled_sequence_empty/args create mode 100644 test/cmdlineTests/yul_optimizer_disabled_sequence_empty/input.sol create mode 100644 test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output diff --git a/Changelog.md b/Changelog.md index a54afa62c..3a7f3ec9a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,8 +7,10 @@ Compiler Features: Bugfixes: + * Commandline Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``--yul-optimizations`` sequence. * SMTChecker: Fix internal error on mapping access caused by too strong requirements on sort compatibility of the index and mapping domain. * SMTChecker: Fix internal error when using bitwise operators with an array element as argument. + * Standard JSON Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``optimizerSteps`` sequence. * Yul Optimizer: Fix the order of assignments generated by ``SSATransform`` being dependent on AST IDs, sometimes resulting in different (but equivalent) bytecode when unrelated files were added to the compilation pipeline. diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index 4588cb483..c1b959a8a 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -46,7 +46,7 @@ for a stand-alone Yul mode. enabled by default and can only be turned off via the :ref:`Standard JSON `. .. note:: - An empty optimizer sequence is accepted even without ``--optimize`` in order to fully disable + An empty optimizer sequence, i.e ``:``, is accepted even without ``--optimize`` in order to fully disable the user-supplied portion of the Yul :ref:`optimizer sequence `, as by default, even when the optimizer is not turned on, the :ref:`unused pruner ` step will be run. diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index baba57d1d..514f3a554 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1722,10 +1722,7 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR details["yulDetails"]["stackAllocation"] = m_optimiserSettings.optimizeStackAllocation; details["yulDetails"]["optimizerSteps"] = m_optimiserSettings.yulOptimiserSteps + ":" + m_optimiserSettings.yulOptimiserCleanupSteps; } - else if ( - OptimiserSuite::isEmptyOptimizerSequence(m_optimiserSettings.yulOptimiserSteps) && - OptimiserSuite::isEmptyOptimizerSequence(m_optimiserSettings.yulOptimiserCleanupSteps) - ) + else if (OptimiserSuite::isEmptyOptimizerSequence(m_optimiserSettings.yulOptimiserSteps + ":" + m_optimiserSettings.yulOptimiserCleanupSteps)) { solAssert(m_optimiserSettings.optimizeStackAllocation == false); details["yulDetails"] = Json::objectValue; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 85a5a5d23..1f7b3fa75 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -465,7 +465,12 @@ std::optional checkOptimizerDetailSteps(Json::Value const& _details { std::string const fullSequence = _details[_name].asString(); if (!_runYulOptimizer && !OptimiserSuite::isEmptyOptimizerSequence(fullSequence)) - return formatFatalError(Error::Type::JSONError, "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted."); + { + std::string errorMessage = + "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted." + " Note that the empty optimizer sequence is properly denoted by \":\"."; + return formatFatalError(Error::Type::JSONError, errorMessage); + } try { diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 545ae4de0..d35cdc256 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -77,6 +77,8 @@ #include #include +#include +#include #include #include @@ -385,21 +387,9 @@ void OptimiserSuite::validateSequence(std::string_view _stepAbbreviations) bool OptimiserSuite::isEmptyOptimizerSequence(std::string const& _sequence) { - size_t delimiterCount{0}; - for (char const step: _sequence) - switch (step) - { - case ':': - if (++delimiterCount > 1) - return false; - break; - case ' ': - case '\n': - break; - default: - return false; - } - return true; + return + ranges::count(_sequence, ':') == 1 && + ranges::none_of(_sequence, [](auto _step) { return _step != ':' && _step != ' ' && _step != '\n'; }); } void OptimiserSuite::runSequence(std::string_view _stepAbbreviations, Block& _ast, bool _repeatUntilStable) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 6216af4a0..824c89911 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -1229,8 +1229,15 @@ void CommandLineParser::processArgs() if (m_args.count(g_strYulOptimizations)) { OptimiserSettings optimiserSettings = m_options.optimiserSettings(); - if (!optimiserSettings.runYulOptimiser && !OptimiserSuite::isEmptyOptimizerSequence(m_args[g_strYulOptimizations].as())) - solThrow(CommandLineValidationError, "--" + g_strYulOptimizations + " is invalid with a non-empty sequence if Yul optimizer is disabled."); + if ( + !optimiserSettings.runYulOptimiser && + !OptimiserSuite::isEmptyOptimizerSequence(m_args[g_strYulOptimizations].as()) + ) + solThrow( + CommandLineValidationError, + "--" + g_strYulOptimizations + " is invalid with a non-empty sequence if Yul optimizer is disabled." + " Note that the empty optimizer sequence is properly denoted by \":\"." + ); try { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/input.json new file mode 100644 index 000000000..e229656ea --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "A": {"content": " + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.0; + contract C { } + "} + }, + "settings": { + "optimizer": { + "details": { + "yul": false, + "yulDetails": { + "optimizerSteps": ":" + } + } + }, + "outputSelection": { + "*": { + "*": ["metadata"] + } + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json new file mode 100644 index 000000000..725822763 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json @@ -0,0 +1,19 @@ +{ + "contracts": + { + "A": + { + "C": + { + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" + } + } + }, + "sources": + { + "A": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/input.json new file mode 100644 index 000000000..ddf2d963f --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "A": {"content": " + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.0; + contract C { } + "} + }, + "settings": { + "optimizer": { + "details": { + "yul": false, + "yulDetails": { + "optimizerSteps": " : " + } + } + }, + "outputSelection": { + "*": { + "*": ["metadata"] + } + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json new file mode 100644 index 000000000..725822763 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json @@ -0,0 +1,19 @@ +{ + "contracts": + { + "A": + { + "C": + { + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" + } + } + }, + "sources": + { + "A": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/output.json index fa3c9d93e..e0b6a26c1 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/output.json @@ -3,8 +3,8 @@ [ { "component": "general", - "formattedMessage": "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted.", - "message": "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted.", + "formattedMessage": "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted. Note that the empty optimizer sequence is properly denoted by \":\".", + "message": "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted. Note that the empty optimizer sequence is properly denoted by \":\".", "severity": "error", "type": "JSONError" } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/input.json new file mode 100644 index 000000000..ad7d7ff14 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/input.json @@ -0,0 +1,19 @@ +{ + "language": "Solidity", + "sources": { + "A": {"content": " + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.0; + "} + }, + "settings": { + "optimizer": { + "details": { + "yul": false, + "yulDetails": { + "optimizerSteps": "" + } + } + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/output.json new file mode 100644 index 000000000..e0b6a26c1 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted. Note that the empty optimizer sequence is properly denoted by \":\".", + "message": "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted. Note that the empty optimizer sequence is properly denoted by \":\".", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/input.json new file mode 100644 index 000000000..85a53fce7 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/input.json @@ -0,0 +1,19 @@ +{ + "language": "Solidity", + "sources": { + "A": {"content": " + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.0; + "} + }, + "settings": { + "optimizer": { + "details": { + "yul": false, + "yulDetails": { + "optimizerSteps": " " + } + } + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/output.json new file mode 100644 index 000000000..e0b6a26c1 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted. Note that the empty optimizer sequence is properly denoted by \":\".", + "message": "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted. Note that the empty optimizer sequence is properly denoted by \":\".", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/args b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/args new file mode 100644 index 000000000..da9301b32 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/args @@ -0,0 +1 @@ +--metadata --yul-optimizations : \ No newline at end of file diff --git a/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/input.sol b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/input.sol new file mode 100644 index 000000000..37cd85bff --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/input.sol @@ -0,0 +1,3 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract C { } \ No newline at end of file diff --git a/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output new file mode 100644 index 000000000..7b948303e --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output @@ -0,0 +1,4 @@ + +======= yul_optimizer_disabled_sequence_empty/input.sol:C ======= +Metadata: +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"yul_optimizer_disabled_sequence_empty/input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"yul_optimizer_disabled_sequence_empty/input.sol":{"keccak256":"0xc2db3500808896ce1e69de2fe20cecab7ae2ffbb47cdf6ba8321296d95f49fc5","license":"GPL-3.0","urls":["bzz-raw://fde21393c068cd9f2d2b10ba4782db54f6f1c9a725074b17fa742531076be8a4","dweb:/ipfs/QmeTD6mR7YrWNyRowKRS7xs6cJNeMF3T49GAHzGM1bquyM"]}},"version":1} diff --git a/test/cmdlineTests/yul_optimizer_steps_disabled/err b/test/cmdlineTests/yul_optimizer_steps_disabled/err index 1abbab8bd..c5a2e506d 100644 --- a/test/cmdlineTests/yul_optimizer_steps_disabled/err +++ b/test/cmdlineTests/yul_optimizer_steps_disabled/err @@ -1 +1 @@ -Error: --yul-optimizations is invalid with a non-empty sequence if Yul optimizer is disabled. +Error: --yul-optimizations is invalid with a non-empty sequence if Yul optimizer is disabled. Note that the empty optimizer sequence is properly denoted by ":". diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 7a4f625c1..73ebb2c54 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -241,6 +241,29 @@ BOOST_AUTO_TEST_CASE(cli_input) BOOST_CHECK_EQUAL(result.reader.allowedDirectories(), expectedAllowedPaths); } +BOOST_AUTO_TEST_CASE(cli_optimizer_disabled_yul_optimization_input_whitespaces_or_empty) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.sol"}); + createFilesWithParentDirs({tempDir.path() / "input.yul"}); + + std::string const expectedMessage = + "--yul-optimizations is invalid with a non-empty sequence if Yul optimizer is disabled." + " Note that the empty optimizer sequence is properly denoted by \":\"."; + std::vector> const commandVariations = { + {"solc", "--strict-assembly", "--yul-optimizations", "", (tempDir.path() / "input.yul").string()}, + {"solc", "--strict-assembly", "--yul-optimizations", " ", (tempDir.path() / "input.yul").string()}, + {"solc", "--yul-optimizations", "", (tempDir.path() / "input.sol").string()}, + {"solc", "--yul-optimizations", " ", (tempDir.path() / "input.sol").string()}, + }; + for (auto const& command: commandVariations) + BOOST_CHECK_EXCEPTION( + parseCommandLineAndReadInputFiles(command), + CommandLineValidationError, + [&](auto const& _exception) { BOOST_TEST(_exception.what() == expectedMessage); return true; } + ); +} + BOOST_AUTO_TEST_CASE(cli_ignore_missing_some_files_exist) { TemporaryDirectory tempDir1(TEST_CASE_NAME); diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index e0592da5d..9fe24bcc6 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -498,6 +498,9 @@ BOOST_AUTO_TEST_CASE(valid_optimiser_sequences) { std::vector validSequenceInputs { ":", // Empty optimization sequence and empty cleanup sequence + " : ", // whitespaces only optimization sequence and whitespaces only cleanup sequence + ": ", // Empty optimization sequence and whitespaces only cleanup sequence + " :", // whitespaces only optimization sequence and empty cleanup sequence ":fDn", // Empty optimization sequence and specified cleanup sequence "dhfoDgvulfnTUtnIf:", // Specified optimization sequence and empty cleanup sequence "dhfoDgvulfnTUtnIf:fDn", // Specified optimization sequence and cleanup sequence @@ -509,6 +512,9 @@ BOOST_AUTO_TEST_CASE(valid_optimiser_sequences) std::vector> const expectedParsedSequences { {"", ""}, + {" ", " "}, + {"", " "}, + {" ", ""}, {"", "fDn"}, {"dhfoDgvulfnTUtnIf", ""}, {"dhfoDgvulfnTUtnIf", "fDn"}, @@ -600,11 +606,26 @@ BOOST_AUTO_TEST_CASE(valid_empty_optimizer_sequences_without_optimize) BOOST_AUTO_TEST_CASE(invalid_optimizer_sequence_without_optimize) { - std::string const invalidSequence{"u: "}; - std::string const expectedErrorMessage{"--yul-optimizations is invalid with a non-empty sequence if Yul optimizer is disabled."}; - std::vector commandLineOptions{"solc", "contract.sol", "--yul-optimizations=" + invalidSequence}; + std::vector const invalidSequenceInputs { + {" "}, + {"u: "}, + {"u:"}, + {":f"}, + {" :f"} + }; + + std::string const expectedErrorMessage{ + "--yul-optimizations is invalid with a non-empty sequence if Yul optimizer is disabled." + " Note that the empty optimizer sequence is properly denoted by \":\"." + }; + auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedErrorMessage; }; - BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage); + + for (auto const& invalidSequence: invalidSequenceInputs) + { + std::vector commandLineOptions{"solc", "contract.sol", "--yul-optimizations=" + invalidSequence}; + BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage); + } } BOOST_AUTO_TEST_SUITE_END() From 00b2e54e1e0d54795adf904186e23dd08329a70f Mon Sep 17 00:00:00 2001 From: pgebal Date: Thu, 18 Apr 2024 18:24:28 +0200 Subject: [PATCH 0071/1340] Fix internal error when using an empty tuple with a ternary operator (#15025) --- Changelog.md | 1 + libsmtutil/Z3Interface.cpp | 6 ++++++ .../ternary_operator_with_functions.sol | 11 +++++++++++ .../operators/ternary_operator_with_tuple.sol | 18 ++++++++++++++++++ 4 files changed, 36 insertions(+) create mode 100644 test/libsolidity/smtCheckerTests/operators/ternary_operator_with_functions.sol create mode 100644 test/libsolidity/smtCheckerTests/operators/ternary_operator_with_tuple.sol diff --git a/Changelog.md b/Changelog.md index a54afa62c..3fdd337aa 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: * SMTChecker: Fix internal error on mapping access caused by too strong requirements on sort compatibility of the index and mapping domain. + * SMTChecker: Fix internal error when using an empty tuple in a conditional operator. * SMTChecker: Fix internal error when using bitwise operators with an array element as argument. * Yul Optimizer: Fix the order of assignments generated by ``SSATransform`` being dependent on AST IDs, sometimes resulting in different (but equivalent) bytecode when unrelated files were added to the compilation pipeline. diff --git a/libsmtutil/Z3Interface.cpp b/libsmtutil/Z3Interface.cpp index 1cfbc815f..4e1d1cec1 100644 --- a/libsmtutil/Z3Interface.cpp +++ b/libsmtutil/Z3Interface.cpp @@ -169,6 +169,12 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr) smtAssert(sortSort, ""); return m_context.constant(n.c_str(), z3Sort(*sortSort->inner)); } + else if (n == "tuple_constructor") + { + auto constructor = z3::func_decl(m_context, Z3_get_tuple_sort_mk_decl(m_context, z3Sort(*_expr.sort))); + smtAssert(constructor.arity() == arguments.size()); + return constructor(); + } else try { diff --git a/test/libsolidity/smtCheckerTests/operators/ternary_operator_with_functions.sol b/test/libsolidity/smtCheckerTests/operators/ternary_operator_with_functions.sol new file mode 100644 index 000000000..8214862e7 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/ternary_operator_with_functions.sol @@ -0,0 +1,11 @@ +contract C { + function f() public {} + function g() public {} + + function test() public { + true ? f() : g(); + } +} +// ==== +// SMTEngine: all +// ---- diff --git a/test/libsolidity/smtCheckerTests/operators/ternary_operator_with_tuple.sol b/test/libsolidity/smtCheckerTests/operators/ternary_operator_with_tuple.sol new file mode 100644 index 000000000..d05d699c3 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/ternary_operator_with_tuple.sol @@ -0,0 +1,18 @@ +contract C { + function empty_tuple() public pure { + true ? () : (); // bug fix test, proper handling of empty tuples + } + + function non_empty_tuple() public pure { + true ? (1, 2) : (3, 4); + } + + function return_empty_tuple() public pure { + return true ? () : (); + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 6133: (53-67): Statement has no effect. +// Warning 6133: (166-188): Statement has no effect. From cc27468bd6eca8fdb1d2a11af15307a57598c271 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Mon, 22 Apr 2024 12:27:36 +0200 Subject: [PATCH 0072/1340] Remove wordSizeTransform. --- test/libyul/YulOptimizerTest.cpp | 3 +-- test/libyul/YulOptimizerTestCommon.cpp | 7 +++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 9fc6712db..82e254980 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -81,8 +81,7 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co auto const printed = (m_object->subObjects.empty() ? AsmPrinter{ *m_dialect }(*m_object->code) : m_object->toString(m_dialect)); // Re-parse new code for compilability - // TODO: support for wordSizeTransform which needs different input and output dialects - if (m_optimizerStep != "wordSizeTransform" && !std::get<0>(parse(_stream, _linePrefix, _formatted, printed))) + if (!std::get<0>(parse(_stream, _linePrefix, _formatted, printed))) { util::AnsiColorized(_stream, _formatted, {util::formatting::BOLD, util::formatting::CYAN}) << _linePrefix << "Result after the optimiser:" << std::endl; diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index ea68f8dcd..091a9a0b6 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -417,13 +417,12 @@ std::string YulOptimizerTestCommon::randomOptimiserStep(unsigned _seed) if (count == idx) { std::string optimiserStep = step.first; - // Do not fuzz mainFunction and wordSizeTransform - // because they do not preserve yul code semantics. + // Do not fuzz mainFunction + // because it does not preserve yul code semantics. // Do not fuzz reasoning based simplifier because // it can sometimes drain memory. if ( - optimiserStep == "mainFunction" || - optimiserStep == "wordSizeTransform" + optimiserStep == "mainFunction" ) // "Fullsuite" is fuzzed roughly four times more frequently than // other steps because of the filtering in place above. From df01dcc7b759f53ba45811979d3286562eab7846 Mon Sep 17 00:00:00 2001 From: pcw109550 Date: Tue, 23 Apr 2024 00:20:34 -0600 Subject: [PATCH 0073/1340] Better error message when consecutive underscores --- libsolidity/analysis/SyntaxChecker.cpp | 2 +- .../parsing/lexer_numbers_with_underscores_decimal_fail.sol | 2 +- .../parsing/lexer_numbers_with_underscores_fixed_fail.sol | 2 +- .../parsing/lexer_numbers_with_underscores_hex_fail.sol | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index ac23ca36a..b083690cc 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -300,7 +300,7 @@ bool SyntaxChecker::visit(Literal const& _literal) if (value.find("__") != ASTString::npos) { - m_errorReporter.syntaxError(2990_error, _literal.location(), "Invalid use of underscores in number literal. Only one consecutive underscores between digits allowed."); + m_errorReporter.syntaxError(2990_error, _literal.location(), "Invalid use of underscores in number literal. Only one consecutive underscore between digits is allowed."); return true; } diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_decimal_fail.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_decimal_fail.sol index 6cbeb217c..279a67ade 100644 --- a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_decimal_fail.sol +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_decimal_fail.sol @@ -8,6 +8,6 @@ contract C { } // ---- // SyntaxError 2090: (56-61): Invalid use of underscores in number literal. No trailing underscores allowed. -// SyntaxError 2990: (77-83): Invalid use of underscores in number literal. Only one consecutive underscores between digits allowed. +// SyntaxError 2990: (77-83): Invalid use of underscores in number literal. Only one consecutive underscore between digits is allowed. // SyntaxError 6415: (99-105): Invalid use of underscores in number literal. No underscore at the end of the mantissa allowed. // SyntaxError 6165: (121-127): Invalid use of underscores in number literal. No underscore in front of exponent allowed. diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed_fail.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed_fail.sol index 49bf042cd..43f0aa948 100644 --- a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed_fail.sol +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed_fail.sol @@ -10,7 +10,7 @@ contract C { } // ---- // SyntaxError 2090: (57-64): Invalid use of underscores in number literal. No trailing underscores allowed. -// SyntaxError 2990: (81-91): Invalid use of underscores in number literal. Only one consecutive underscores between digits allowed. +// SyntaxError 2990: (81-91): Invalid use of underscores in number literal. Only one consecutive underscore between digits is allowed. // SyntaxError 1023: (108-112): Invalid use of underscores in number literal. No underscores in front of the fraction part allowed. // SyntaxError 3891: (129-133): Invalid use of underscores in number literal. No underscores in front of the fraction part allowed. // SyntaxError 6165: (150-157): Invalid use of underscores in number literal. No underscore in front of exponent allowed. diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_hex_fail.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_hex_fail.sol index 5a2e2f5c1..50cfda8e2 100644 --- a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_hex_fail.sol +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_hex_fail.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// SyntaxError 2990: (56-79): Invalid use of underscores in number literal. Only one consecutive underscores between digits allowed. +// SyntaxError 2990: (56-79): Invalid use of underscores in number literal. Only one consecutive underscore between digits is allowed. From f4534b19bd84d4526557e5cb44cfe242f8794040 Mon Sep 17 00:00:00 2001 From: edurivara Date: Fri, 15 Mar 2024 01:11:20 +0100 Subject: [PATCH 0074/1340] Reduce default font weight for readability --- docs/_static/css/toggle.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/_static/css/toggle.css b/docs/_static/css/toggle.css index 6f03e6fb6..c0265bfcb 100644 --- a/docs/_static/css/toggle.css +++ b/docs/_static/css/toggle.css @@ -85,4 +85,8 @@ html.transition *:after { .wy-menu-vertical a:hover { background-color: #0002; +} + +body { + font-weight: 200; } \ No newline at end of file From fb11553a650f6e07299354a867fc80e1c1ba3c0b Mon Sep 17 00:00:00 2001 From: edurivara Date: Tue, 2 Apr 2024 17:13:45 +0200 Subject: [PATCH 0075/1340] Font weight to 200px and letter spacing 0.5px for readability --- docs/_static/css/toggle.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/_static/css/toggle.css b/docs/_static/css/toggle.css index c0265bfcb..d525ab62a 100644 --- a/docs/_static/css/toggle.css +++ b/docs/_static/css/toggle.css @@ -88,5 +88,6 @@ html.transition *:after { } body { - font-weight: 200; + font-weight: 300; + letter-spacing: 0.5px; } \ No newline at end of file From 0711fa3f17f827319c7081312d60cce3c4902199 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 6 Mar 2024 14:17:54 +0100 Subject: [PATCH 0076/1340] Require with custom error Disallow require with error in legacy More tests Docs Use AST ID in generated Yul helper function names Changelog Review comments --- Changelog.md | 1 + docs/contracts/errors.rst | 37 ++- docs/control-structures.rst | 29 +- docs/introduction-to-smart-contracts.rst | 14 +- libsolidity/analysis/GlobalContext.cpp | 1 + libsolidity/analysis/PostTypeChecker.cpp | 27 +- libsolidity/analysis/PostTypeChecker.h | 1 + libsolidity/ast/TypeProvider.cpp | 5 +- libsolidity/ast/TypeProvider.h | 2 +- libsolidity/ast/Types.cpp | 12 +- libsolidity/ast/Types.h | 3 + libsolidity/codegen/ExpressionCompiler.cpp | 6 + libsolidity/codegen/YulUtilFunctions.cpp | 62 ++++ libsolidity/codegen/YulUtilFunctions.h | 4 + .../codegen/ir/IRGeneratorForStatements.cpp | 52 ++-- .../codegen/ir/IRGeneratorForStatements.h | 1 + test/cmdlineTests/require_overload/err | 1 + test/cmdlineTests/require_with_error_ir/args | 1 + .../require_with_error_ir/input.sol | 17 ++ .../cmdlineTests/require_with_error_ir/output | 265 ++++++++++++++++++ .../~documentation_examples/test.sh | 4 + test/libsolidity/ASTJSON/used_errors.json | 8 +- ...quire_different_errors_same_parameters.sol | 21 ++ ...quire_error_function_pointer_parameter.sol | 20 ++ .../require_error_multiple_arguments.sol | 20 ++ .../errors/require_error_string_literal.sol | 20 ++ .../errors/require_error_string_memory.sol | 22 ++ .../errors/require_error_uint256.sol | 20 ++ .../errors/require_evaluation_order.sol | 28 ++ .../errors/require_inherited_error.sol | 17 ++ .../abi_encodeCall_tuple_from_error_event.sol | 2 +- ...encodeCall_tuple_from_invalid_operator.sol | 2 +- .../errors/abi_decode_error_constructor.sol | 9 + .../errors/abi_encode_error_constructor.sol | 8 + .../syntaxTests/errors/assert_with_error.sol | 2 +- .../syntaxTests/errors/require_custom.sol | 3 +- .../errors/require_custom_legacy.sol | 8 + .../syntaxTests/errors/require_nested.sol | 15 + .../errors/selector_on_instance.sol | 2 +- .../revertStatement/error_used_elsewhere.sol | 2 +- .../revertStatement/require_nested.sol | 13 + 41 files changed, 718 insertions(+), 69 deletions(-) create mode 100644 test/cmdlineTests/require_with_error_ir/args create mode 100644 test/cmdlineTests/require_with_error_ir/input.sol create mode 100644 test/cmdlineTests/require_with_error_ir/output create mode 100644 test/libsolidity/semanticTests/errors/require_different_errors_same_parameters.sol create mode 100644 test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol create mode 100644 test/libsolidity/semanticTests/errors/require_error_multiple_arguments.sol create mode 100644 test/libsolidity/semanticTests/errors/require_error_string_literal.sol create mode 100644 test/libsolidity/semanticTests/errors/require_error_string_memory.sol create mode 100644 test/libsolidity/semanticTests/errors/require_error_uint256.sol create mode 100644 test/libsolidity/semanticTests/errors/require_evaluation_order.sol create mode 100644 test/libsolidity/semanticTests/errors/require_inherited_error.sol create mode 100644 test/libsolidity/syntaxTests/errors/abi_decode_error_constructor.sol create mode 100644 test/libsolidity/syntaxTests/errors/abi_encode_error_constructor.sol create mode 100644 test/libsolidity/syntaxTests/errors/require_custom_legacy.sol create mode 100644 test/libsolidity/syntaxTests/errors/require_nested.sol create mode 100644 test/libsolidity/syntaxTests/revertStatement/require_nested.sol diff --git a/Changelog.md b/Changelog.md index c8b448c93..c118e9f24 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.8.26 (unreleased) Language Features: + * Introduce a new overload ``require(bool, Error)`` that allows usage of ``require`` functions with custom errors. This feature is available in the ``via-ir`` pipeline only. Compiler Features: diff --git a/docs/contracts/errors.rst b/docs/contracts/errors.rst index 19577a387..e4955ddae 100644 --- a/docs/contracts/errors.rst +++ b/docs/contracts/errors.rst @@ -1,22 +1,25 @@ -.. index:: ! error, revert, ! selector; of an error +.. index:: ! error, revert, require, ! selector; of an error .. _errors: -******************************* -Errors and the Revert Statement -******************************* +************* +Custom Errors +************* Errors in Solidity provide a convenient and gas-efficient way to explain to the user why an operation failed. They can be defined inside and outside of contracts (including interfaces and libraries). They have to be used together with the :ref:`revert statement ` -which causes -all changes in the current call to be reverted and passes the error data back to the -caller. +or the :ref:`require function `. +In the case of ``revert`` statements, or ``require`` calls where the condition is evaluated to be false, +all changes in the current call are reverted, and the error data passed back to the caller. + +The example below shows custom error usage with the ``revert`` statement in function ``transferWithRevertError``, +as well as the newer approach with ``require`` in function ``transferWithRequireError``. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity ^0.8.4; + pragma solidity ^0.8.26; /// Insufficient balance for transfer. Needed `required` but only /// `available` available. @@ -24,9 +27,10 @@ caller. /// @param required requested amount to transfer. error InsufficientBalance(uint256 available, uint256 required); + // This will only compile via IR contract TestToken { mapping(address => uint) balance; - function transfer(address to, uint256 amount) public { + function transferWithRevertError(address to, uint256 amount) public { if (amount > balance[msg.sender]) revert InsufficientBalance({ available: balance[msg.sender], @@ -35,12 +39,22 @@ caller. balance[msg.sender] -= amount; balance[to] += amount; } + function transferWithRequireError(address to, uint256 amount) public { + require(amount > balance[msg.sender], InsufficientBalance(balance[msg.sender], amount)); + balance[msg.sender] -= amount; + balance[to] += amount; + } // ... } +Another important detail to mention when it comes to using ``require`` with custom errors, is that memory +allocation for the error-based revert reason will only happen in the reverting case, which, along with +optimization of constants and string literals makes this about as gas-efficient as the +``if (!condition) revert CustomError(args)`` pattern. + Errors cannot be overloaded or overridden but are inherited. The same error can be defined in multiple places as long as the scopes are distinct. -Instances of errors can only be created using ``revert`` statements. +Instances of errors can only be created using ``revert`` statements, or as the second argument to ``require`` functions. The error creates data that is then passed to the caller with the revert operation to either return to the off-chain component or catch it in a :ref:`try/catch statement `. @@ -65,8 +79,7 @@ The selector consists of the first four bytes of the keccak256-hash of the signa only the name of the error is relevant, not the contract or file where it is defined. The statement ``require(condition, "description");`` would be equivalent to -``if (!condition) revert Error("description")`` if you could define -``error Error(string)``. +``if (!condition) revert Error("description")`` if you could define ``error Error(string)``. Note, however, that ``Error`` is a built-in type and cannot be defined in user-supplied code. Similarly, a failing ``assert`` or similar conditions will revert with an error diff --git a/docs/control-structures.rst b/docs/control-structures.rst index ea8a9c569..81e62ec57 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -594,6 +594,8 @@ The built-in errors ``Error(string)`` and ``Panic(uint256)`` are used by special functions, as explained below. ``Error`` is used for "regular" error conditions while ``Panic`` is used for errors that should not be present in bug-free code. +.. _assert-and-require-statements: + Panic via ``assert`` and Error via ``require`` ---------------------------------------------- @@ -625,21 +627,24 @@ The error code supplied with the error data indicates the kind of panic. #. 0x41: If you allocate too much memory or create an array that is too large. #. 0x51: If you call a zero-initialized variable of internal function type. -The ``require`` function either creates an error without any data or -an error of type ``Error(string)``. It -should be used to ensure valid conditions -that cannot be detected until execution time. -This includes conditions on inputs -or return values from calls to external contracts. +The ``require`` function provides three overloads: + +1. ``require(bool)`` which will revert without any data (not even an error selector). +2. ``require(bool, string)`` which will revert with an ``Error(string)``. +3. ``require(bool, error)`` which will revert with the custom, user supplied error provided as the second argument. .. note:: + ``require`` arguments are evaluated unconditionally, so take special care to make sure that + they are not expressions with unexpected side-effects. + For example, in ``require(condition, CustomError(f()));`` and ``require(condition, f());``, + function ``f()`` will be called regardless of whether the supplied condition is ``true`` or ``false``. - It is currently not possible to use custom errors in combination - with ``require``. Please use ``if (!condition) revert CustomError();`` instead. +.. note:: + Using custom errors with ``require`` is only supported by the via IR pipeline, i.e. compilation via Yul. + For the legacy pipeline, please use ``if (!condition) revert CustomError();`` instead. An ``Error(string)`` exception (or an exception without data) is generated -by the compiler -in the following situations: +by the compiler in the following situations: #. Calling ``require(x)`` where ``x`` evaluates to ``false``. #. If you use ``revert()`` or ``revert("description")``. @@ -662,10 +667,10 @@ an ``Error`` or a ``Panic`` (or whatever else was given): #. If you create a contract using the ``new`` keyword but the contract creation :ref:`does not finish properly`. -You can optionally provide a message string for ``require``, but not for ``assert``. +You can optionally provide a message string or a custom error to ``require``, but not to ``assert``. .. note:: - If you do not provide a string argument to ``require``, it will revert + If you do not provide a string or custom error argument to ``require``, it will revert with empty error data, not even including the error selector. diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index de06d684e..1c5b87373 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -85,8 +85,9 @@ registering with a username and password, all you need is an Ethereum keypair. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity ^0.8.4; + pragma solidity ^0.8.26; + // This will only compile via IR contract Coin { // The keyword "public" makes variables // accessible from other contracts @@ -118,12 +119,7 @@ registering with a username and password, all you need is an Ethereum keypair. // Sends an amount of existing coins // from any caller to an address function send(address receiver, uint amount) public { - if (amount > balances[msg.sender]) - revert InsufficientBalance({ - requested: amount, - available: balances[msg.sender] - }); - + require(amount > balances[msg.sender], InsufficientBalance(amount, balances[msg.sender])); balances[msg.sender] -= amount; balances[receiver] += amount; emit Sent(msg.sender, receiver, amount); @@ -225,8 +221,8 @@ than the maximum value of ``uint`` (``2**256 - 1``). This is also true for the s :ref:`Errors ` allow you to provide more information to the caller about why a condition or operation failed. Errors are used together with the :ref:`revert statement `. The ``revert`` statement unconditionally -aborts and reverts all changes similar to the ``require`` function, but it also -allows you to provide the name of an error and additional data which will be supplied to the caller +aborts and reverts all changes, much like the :ref:`require function `. +Both approaches allow you to provide the name of an error and additional data which will be supplied to the caller (and eventually to the front-end application or block explorer) so that a failure can more easily be debugged or reacted upon. diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index c4833689f..0c265d245 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -90,6 +90,7 @@ inline std::vector> constructMag magicVarDecl("now", TypeProvider::uint256()), magicVarDecl("require", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Require, StateMutability::Pure)), magicVarDecl("require", TypeProvider::function(strings{"bool", "string memory"}, strings{}, FunctionType::Kind::Require, StateMutability::Pure)), + magicVarDecl("require", TypeProvider::function(TypePointers{TypeProvider::boolean(), TypeProvider::magic(MagicType::Kind::Error)}, TypePointers{}, strings{2, ""}, strings{}, FunctionType::Kind::Require, StateMutability::Pure)), magicVarDecl("revert", TypeProvider::function(strings(), strings(), FunctionType::Kind::Revert, StateMutability::Pure)), magicVarDecl("revert", TypeProvider::function(strings{"string memory"}, strings(), FunctionType::Kind::Revert, StateMutability::Pure)), magicVarDecl("ripemd160", TypeProvider::function(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, StateMutability::Pure)), diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index fe3a59d0c..9731ef3cc 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -103,6 +103,11 @@ bool PostTypeChecker::visit(FunctionCall const& _functionCall) return callVisit(_functionCall); } +void PostTypeChecker::endVisit(FunctionCall const& _functionCall) +{ + callEndVisit(_functionCall); +} + bool PostTypeChecker::visit(Identifier const& _identifier) { return callVisit(_identifier); @@ -304,6 +309,7 @@ struct ModifierContextChecker: public PostTypeChecker::Checker bool m_insideModifierInvocation = false; }; +// TODO: this should either be split into separate emit and error checkers, or at least renamed to include require struct EventOutsideEmitErrorOutsideRevertChecker: public PostTypeChecker::Checker { EventOutsideEmitErrorOutsideRevertChecker(ErrorReporter& _errorReporter): @@ -336,6 +342,11 @@ struct EventOutsideEmitErrorOutsideRevertChecker: public PostTypeChecker::Checke if (*_functionCall.annotation().kind == FunctionCallKind::FunctionCall) if (auto const* functionType = dynamic_cast(_functionCall.expression().annotation().type)) { + if (functionType->kind() == FunctionType::Kind::Require) + { + solAssert(!m_inRequire); + m_inRequire = true; + } // Check for event outside of emit statement if (!dynamic_cast(m_currentStatement) && functionType->kind() == FunctionType::Kind::Event) m_errorReporter.typeError( @@ -343,11 +354,11 @@ struct EventOutsideEmitErrorOutsideRevertChecker: public PostTypeChecker::Checke _functionCall.location(), "Event invocations have to be prefixed by \"emit\"." ); - else if (!dynamic_cast(m_currentStatement) && functionType->kind() == FunctionType::Kind::Error) + else if (!dynamic_cast(m_currentStatement) && !m_inRequire && functionType->kind() == FunctionType::Kind::Error) m_errorReporter.typeError( 7757_error, _functionCall.location(), - "Errors can only be used with revert statements: \"revert MyError();\"." + "Errors can only be used with revert statements: \"revert MyError(args);\", or require functions: \"require(condition, MyError(args))\"." ); } m_currentStatement = nullptr; @@ -355,8 +366,20 @@ struct EventOutsideEmitErrorOutsideRevertChecker: public PostTypeChecker::Checke return true; } + void endVisit(FunctionCall const& _functionCall) override + { + if (*_functionCall.annotation().kind == FunctionCallKind::FunctionCall) + if (auto const* functionType = dynamic_cast(_functionCall.expression().annotation().type)) + if (functionType->kind() == FunctionType::Kind::Require) + { + solAssert(m_inRequire); + m_inRequire = false; + } + } + private: Statement const* m_currentStatement = nullptr; + bool m_inRequire = false; }; struct NoVariablesInInterfaceChecker: public PostTypeChecker::Checker diff --git a/libsolidity/analysis/PostTypeChecker.h b/libsolidity/analysis/PostTypeChecker.h index 178130a35..347f464ed 100644 --- a/libsolidity/analysis/PostTypeChecker.h +++ b/libsolidity/analysis/PostTypeChecker.h @@ -87,6 +87,7 @@ class PostTypeChecker: private ASTConstVisitor void endVisit(RevertStatement const& _revert) override; bool visit(FunctionCall const& _functionCall) override; + void endVisit(FunctionCall const& _functionCall) override; bool visit(Identifier const& _identifier) override; bool visit(MemberAccess const& _identifier) override; diff --git a/libsolidity/ast/TypeProvider.cpp b/libsolidity/ast/TypeProvider.cpp index da5087556..41e103edf 100644 --- a/libsolidity/ast/TypeProvider.cpp +++ b/libsolidity/ast/TypeProvider.cpp @@ -145,11 +145,12 @@ std::array, 32> const TypeProvider::m_bytesM{{ {std::make_unique(32)} }}; -std::array, 4> const TypeProvider::m_magics{{ +std::array, 5> const TypeProvider::m_magics{{ {std::make_unique(MagicType::Kind::Block)}, {std::make_unique(MagicType::Kind::Message)}, {std::make_unique(MagicType::Kind::Transaction)}, - {std::make_unique(MagicType::Kind::ABI)} + {std::make_unique(MagicType::Kind::ABI)}, + {std::make_unique(MagicType::Kind::Error)} // MetaType is stored separately }}; diff --git a/libsolidity/ast/TypeProvider.h b/libsolidity/ast/TypeProvider.h index 02b9eb35d..67b1fc0f2 100644 --- a/libsolidity/ast/TypeProvider.h +++ b/libsolidity/ast/TypeProvider.h @@ -226,7 +226,7 @@ class TypeProvider static std::array, 32> const m_intM; static std::array, 32> const m_uintM; static std::array, 32> const m_bytesM; - static std::array, 4> const m_magics; ///< MagicType's except MetaType + static std::array, 5> const m_magics; ///< MagicType's except MetaType std::map, std::unique_ptr> m_ufixedMxN{}; std::map, std::unique_ptr> m_fixedMxN{}; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index d09d03fbe..028b76673 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2919,13 +2919,15 @@ FunctionType::FunctionType(ErrorDefinition const& _error): m_parameterTypes.push_back(var->annotation().type); } + m_returnParameterNames.push_back(""); + m_returnParameterTypes.push_back(TypeProvider::magic(MagicType::Kind::Error)); + solAssert( m_parameterNames.size() == m_parameterTypes.size(), "Parameter names list must match parameter types list!" ); solAssert( - m_returnParameterNames.size() == 0 && - m_returnParameterTypes.size() == 0, + m_returnParameterNames.size() == m_returnParameterTypes.size(), "" ); } @@ -4091,6 +4093,8 @@ std::string MagicType::richIdentifier() const case Kind::MetaType: solAssert(m_typeArgument, ""); return "t_magic_meta_type_" + m_typeArgument->richIdentifier(); + case Kind::Error: + return "t_error"; } return ""; } @@ -4196,6 +4200,8 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const FunctionType::Options::withArbitraryParameters() )} }); + case Kind::Error: + return {}; case Kind::MetaType: { solAssert( @@ -4259,6 +4265,8 @@ std::string MagicType::toString(bool _withoutDataLocation) const case Kind::MetaType: solAssert(m_typeArgument, ""); return "type(" + m_typeArgument->toString(_withoutDataLocation) + ")"; + case Kind::Error: + return "error"; } solAssert(false, "Unknown kind of magic."); return {}; diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 7bbd2f075..3ab4a1d97 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1661,6 +1661,8 @@ class ModuleType: public Type /** * Special type for magic variables (block, msg, tx, type(...)), similar to a struct but without any reference. + * + * It is also the type shared by all instances of all custom error types. */ class MagicType: public Type { @@ -1670,6 +1672,7 @@ class MagicType: public Type Message, ///< "msg" Transaction, ///< "tx" ABI, ///< "abi" + Error, ///< custom error instance MetaType ///< "type(...)" }; diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 3824d5432..54090f960 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1259,6 +1259,12 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) // function call. solAssert(arguments.size() == 2, ""); solAssert(function.kind() == FunctionType::Kind::Require, ""); + // Check if the function call matches ``require(bool, error)``, and throw an unimplemented error, + // as require with custom errors is not supported in legacy codegen. + auto const* magicType = dynamic_cast(arguments[1]->annotation().type); + if (magicType && magicType->kind() == MagicType::Kind::Error) + solUnimplemented("Require with a custom error is only available using the via-ir pipeline."); + if (m_context.revertStrings() == RevertStrings::Strip) { if (!*arguments.at(1)->annotation().isPure) diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 0dabc8a36..5a135acb7 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -266,6 +267,67 @@ std::string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* }); } +std::string YulUtilFunctions::requireWithErrorFunction(FunctionCall const& errorConstructorCall) +{ + ErrorDefinition const* errorDefinition = dynamic_cast(ASTNode::referencedDeclaration(errorConstructorCall.expression())); + solAssert(errorDefinition); + + std::string const errorSignature = errorDefinition->functionType(true)->externalSignature(); + std::string const signatureHash = formatNumber(util::selectorFromSignatureU256(errorSignature)); + std::string const functionName = [&]() { + // Note that in most cases we'll always generate one function per error definition, + // because types in the constructor call will match the ones in the definition. The only + // exception are calls with types, where each instance has its own type (e.g. literals). + std::string name = "require_helper_t_error_" + std::to_string(errorDefinition->id()) + "_" + errorDefinition->name(); + for (ASTPointer const& argument: errorConstructorCall.sortedArguments()) + { + solAssert(argument->annotation().type); + name += ("_" + argument->annotation().type->identifier()); + } + return name; + }(); + + auto errorArgumentVarsAndTypes = [&]() -> std::tuple, std::vector> { + std::vector errorArgumentVars; + std::vector errorArgumentTypes; + for (ASTPointer const& arg: errorConstructorCall.sortedArguments()) + { + solAssert(arg->annotation().type); + if (arg->annotation().type->sizeOnStack() > 0) + errorArgumentVars += IRVariable(*arg).stackSlots(); + errorArgumentTypes.push_back(arg->annotation().type); + } + return std::make_tuple(std::move(errorArgumentVars), std::move(errorArgumentTypes)); + }(); + + return m_functionCollector.createFunction(functionName, [&]() { + auto [errorArgumentVars, errorArgumentTypes] = errorArgumentVarsAndTypes; + std::string const encodeFunc = ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector) + .tupleEncoder( + errorArgumentTypes, + errorDefinition->functionType(true)->parameterTypes() + ); + + return Whiskers(R"( + function (condition ) { + if iszero(condition) { + let memPtr := () + mstore(memPtr, ) + let end := (add(memPtr, ) ) + revert(memPtr, sub(end, memPtr)) + } + } + )") + ("functionName", functionName) + ("allocateUnbounded", allocateUnboundedFunction()) + ("errorHash", signatureHash) + ("abiEncodeFunc", encodeFunc) + ("hashHeaderSize", std::to_string(4)) + ("errorArguments", joinHumanReadablePrefixed(errorArgumentVars)) + .render(); + }); +} + std::string YulUtilFunctions::leftAlignFunction(Type const& _type) { std::string functionName = std::string("leftAlign_") + _type.identifier(); diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index 7d736df5b..db4c26725 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -94,6 +94,10 @@ class YulUtilFunctions // `assert` or `require` call. std::string requireOrAssertFunction(bool _assert, Type const* _messageType = nullptr); + // @returns function that has equivalent logic of a require function, but with a custom + // error constructor parameter. + std::string requireWithErrorFunction(FunctionCall const& errorConstructorCall); + /// @returns the name of a function that takes a (cleaned) value of the given value type and /// left-aligns it, usually for use in non-padded encoding. std::string leftAlignFunction(Type const& _type); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 57414da93..bf028fce5 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -796,6 +796,17 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation) return false; } +void IRGeneratorForStatements::endVisit(RevertStatement const& _revertStatement) +{ + ErrorDefinition const* error = dynamic_cast(ASTNode::referencedDeclaration(_revertStatement.errorCall().expression())); + solAssert(error); + revertWithError( + error->functionType(true)->externalSignature(), + error->functionType(true)->parameterTypes(), + _revertStatement.errorCall().sortedArguments() + ); +} + bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp) { setLocation(_binOp); @@ -1114,17 +1125,6 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) appendCode() << templ.render(); break; } - case FunctionType::Kind::Error: - { - ErrorDefinition const* error = dynamic_cast(ASTNode::referencedDeclaration(_functionCall.expression())); - solAssert(error); - revertWithError( - error->functionType(true)->externalSignature(), - error->functionType(true)->parameterTypes(), - _functionCall.sortedArguments() - ); - break; - } case FunctionType::Kind::Wrap: case FunctionType::Kind::Unwrap: { @@ -1153,15 +1153,28 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) arguments.size() > 1 && m_context.revertStrings() != RevertStrings::Strip ? arguments[1]->annotation().type : nullptr; - std::string requireOrAssertFunction = m_utils.requireOrAssertFunction( - functionType->kind() == FunctionType::Kind::Assert, - messageArgumentType - ); - appendCode() << std::move(requireOrAssertFunction) << "(" << IRVariable(*arguments[0]).name(); - if (messageArgumentType && messageArgumentType->sizeOnStack() > 0) - appendCode() << ", " << IRVariable(*arguments[1]).commaSeparatedList(); - appendCode() << ")\n"; + auto const* magicType = dynamic_cast(messageArgumentType); + if (magicType && magicType->kind() == MagicType::Kind::Error) + { + auto const& errorConstructorCall = dynamic_cast(*arguments[1]); + appendCode() << m_utils.requireWithErrorFunction(errorConstructorCall) << "(" <annotation().type->sizeOnStack() > 0) + appendCode() << ", " << IRVariable(*argument).commaSeparatedList(); + appendCode() << ")\n"; + } + else + { + std::string requireOrAssertFunction = m_utils.requireOrAssertFunction( + functionType->kind() == FunctionType::Kind::Assert, + messageArgumentType + ); + appendCode() << std::move(requireOrAssertFunction) << "(" << IRVariable(*arguments[0]).name(); + if (messageArgumentType && messageArgumentType->sizeOnStack() > 0) + appendCode() << ", " << IRVariable(*arguments[1]).commaSeparatedList(); + appendCode() << ")\n"; + } break; } @@ -1467,6 +1480,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) ")\n"; break; } + case FunctionType::Kind::Error: case FunctionType::Kind::MetaType: { break; diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index f4ce2a7d0..15ef71f13 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -132,6 +132,7 @@ class IRGeneratorForStatements: public IRGeneratorForStatementsBase void endVisit(IndexRangeAccess const& _indexRangeAccess) override; void endVisit(Identifier const& _identifier) override; bool visit(Literal const& _literal) override; + void endVisit(RevertStatement const& _revertStatement) override; bool visit(TryStatement const& _tryStatement) override; bool visit(TryCatchClause const& _tryCatchClause) override; diff --git a/test/cmdlineTests/require_overload/err b/test/cmdlineTests/require_overload/err index 4c33672d4..184c8c22b 100644 --- a/test/cmdlineTests/require_overload/err +++ b/test/cmdlineTests/require_overload/err @@ -5,3 +5,4 @@ Error: No matching declaration found after argument-dependent lookup. | ^^^^^^^ Note: Candidate: function require(bool) Note: Candidate: function require(bool, string memory) +Note: Candidate: function require(bool, error) diff --git a/test/cmdlineTests/require_with_error_ir/args b/test/cmdlineTests/require_with_error_ir/args new file mode 100644 index 000000000..be08aefb4 --- /dev/null +++ b/test/cmdlineTests/require_with_error_ir/args @@ -0,0 +1 @@ +--ir --debug-info none diff --git a/test/cmdlineTests/require_with_error_ir/input.sol b/test/cmdlineTests/require_with_error_ir/input.sol new file mode 100644 index 000000000..f041b27b7 --- /dev/null +++ b/test/cmdlineTests/require_with_error_ir/input.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +error CustomError(uint256, string); + +contract C +{ + function f(bool condition) external pure + { + require(condition, CustomError(1, "two")); + } + + function g(bool condition) external pure + { + require(condition, CustomError(2, "three")); + } +} diff --git a/test/cmdlineTests/require_with_error_ir/output b/test/cmdlineTests/require_with_error_ir/output new file mode 100644 index 000000000..dacc9fc91 --- /dev/null +++ b/test/cmdlineTests/require_with_error_ir/output @@ -0,0 +1,265 @@ +IR: + +/// @use-src 0:"require_with_error_ir/input.sol" +object "C_36" { + code { + + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_36() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_36_deployed"), datasize("C_36_deployed")) + + return(_1, datasize("C_36_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_36() { + + } + + } + /// @use-src 0:"require_with_error_ir/input.sol" + object "C_36_deployed" { + code { + + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x98c3a6c1 + { + // f(bool) + + external_fun_f_21() + } + + case 0xd48092f7 + { + // g(bool) + + external_fun_g_35() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_bool(value) -> cleaned { + cleaned := iszero(iszero(value)) + } + + function validator_revert_t_bool(value) { + if iszero(eq(value, cleanup_t_bool(value))) { revert(0, 0) } + } + + function abi_decode_t_bool(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_bool(value) + } + + function abi_decode_tuple_t_bool(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_bool(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_f_21() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_bool(4, calldatasize()) + fun_f_21(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function external_fun_g_35() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_bool(4, calldatasize()) + fun_g_35(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_1_by_1(value) -> cleaned { + cleaned := value + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_1_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_1_by_1(value))) + } + + function abi_encode_t_rational_1_by_1_to_t_uint256_fromStack(value, pos) { + mstore(pos, convert_t_rational_1_by_1_to_t_uint256(value)) + } + + function array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, length) -> updated_pos { + mstore(pos, length) + updated_pos := add(pos, 0x20) + } + + function store_literal_in_memory_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720(memPtr) { + + mstore(add(memPtr, 0), "two") + + } + + function abi_encode_t_stringliteral_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720_to_t_string_memory_ptr_fromStack(pos) -> end { + pos := array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, 3) + store_literal_in_memory_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720(pos) + end := add(pos, 32) + } + + function abi_encode_tuple_t_rational_1_by_1_t_stringliteral_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720__to_t_uint256_t_string_memory_ptr__fromStack(headStart , value0) -> tail { + tail := add(headStart, 64) + + abi_encode_t_rational_1_by_1_to_t_uint256_fromStack(value0, add(headStart, 0)) + + mstore(add(headStart, 32), sub(tail, headStart)) + tail := abi_encode_t_stringliteral_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720_to_t_string_memory_ptr_fromStack( tail) + + } + + function require_helper_t_error_7_CustomError_t_rational_1_by_1_t_stringliteral_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720(condition , expr_15) { + if iszero(condition) { + let memPtr := allocate_unbounded() + mstore(memPtr, 0x97ea5a2f00000000000000000000000000000000000000000000000000000000) + let end := abi_encode_tuple_t_rational_1_by_1_t_stringliteral_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720__to_t_uint256_t_string_memory_ptr__fromStack(add(memPtr, 4) , expr_15) + revert(memPtr, sub(end, memPtr)) + } + } + + function fun_f_21(var_condition_9) { + + let _1 := var_condition_9 + let expr_13 := _1 + + let expr_15 := 0x01 + + require_helper_t_error_7_CustomError_t_rational_1_by_1_t_stringliteral_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720(expr_13, expr_15) + + } + + function cleanup_t_rational_2_by_1(value) -> cleaned { + cleaned := value + } + + function convert_t_rational_2_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_2_by_1(value))) + } + + function abi_encode_t_rational_2_by_1_to_t_uint256_fromStack(value, pos) { + mstore(pos, convert_t_rational_2_by_1_to_t_uint256(value)) + } + + function store_literal_in_memory_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5(memPtr) { + + mstore(add(memPtr, 0), "three") + + } + + function abi_encode_t_stringliteral_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5_to_t_string_memory_ptr_fromStack(pos) -> end { + pos := array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, 5) + store_literal_in_memory_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5(pos) + end := add(pos, 32) + } + + function abi_encode_tuple_t_rational_2_by_1_t_stringliteral_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5__to_t_uint256_t_string_memory_ptr__fromStack(headStart , value0) -> tail { + tail := add(headStart, 64) + + abi_encode_t_rational_2_by_1_to_t_uint256_fromStack(value0, add(headStart, 0)) + + mstore(add(headStart, 32), sub(tail, headStart)) + tail := abi_encode_t_stringliteral_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5_to_t_string_memory_ptr_fromStack( tail) + + } + + function require_helper_t_error_7_CustomError_t_rational_2_by_1_t_stringliteral_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5(condition , expr_29) { + if iszero(condition) { + let memPtr := allocate_unbounded() + mstore(memPtr, 0x97ea5a2f00000000000000000000000000000000000000000000000000000000) + let end := abi_encode_tuple_t_rational_2_by_1_t_stringliteral_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5__to_t_uint256_t_string_memory_ptr__fromStack(add(memPtr, 4) , expr_29) + revert(memPtr, sub(end, memPtr)) + } + } + + function fun_g_35(var_condition_23) { + + let _2 := var_condition_23 + let expr_27 := _2 + + let expr_29 := 0x02 + + require_helper_t_error_7_CustomError_t_rational_2_by_1_t_stringliteral_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5(expr_27, expr_29) + + } + + } + + data ".metadata" hex"" + } + +} diff --git a/test/cmdlineTests/~documentation_examples/test.sh b/test/cmdlineTests/~documentation_examples/test.sh index 1acf5e8a7..636f9600d 100755 --- a/test/cmdlineTests/~documentation_examples/test.sh +++ b/test/cmdlineTests/~documentation_examples/test.sh @@ -39,6 +39,10 @@ do then opts+=(--ignore-warnings) fi + if grep "// This will only compile via IR" "$f" >/dev/null + then + opts+=(--via-ir) + fi # Disable the version pragma in code snippets that only work with the current development version. # It's necessary because x.y.z won't match `^x.y.z` or `>=x.y.z` pragmas until it's officially released. diff --git a/test/libsolidity/ASTJSON/used_errors.json b/test/libsolidity/ASTJSON/used_errors.json index 12a59f9cb..cff59a5ef 100644 --- a/test/libsolidity/ASTJSON/used_errors.json +++ b/test/libsolidity/ASTJSON/used_errors.json @@ -57,8 +57,8 @@ "src": "38:1:1", "typeDescriptions": { - "typeIdentifier": "t_function_error_pure$__$returns$__$", - "typeString": "function () pure" + "typeIdentifier": "t_function_error_pure$__$returns$_t_error_$", + "typeString": "function () pure returns (error)" } }, "id": 6, @@ -74,8 +74,8 @@ "tryCall": false, "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" + "typeIdentifier": "t_error", + "typeString": "error" } }, "id": 7, diff --git a/test/libsolidity/semanticTests/errors/require_different_errors_same_parameters.sol b/test/libsolidity/semanticTests/errors/require_different_errors_same_parameters.sol new file mode 100644 index 000000000..37cbb207d --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_different_errors_same_parameters.sol @@ -0,0 +1,21 @@ +error AnError(uint256, string, uint256); +error AnotherError(uint256, string, uint256); + +contract C +{ + function f() external pure + { + require(false, AnError(1, "two", 3)); + } + + function g() external pure + { + require(false, AnotherError(4, "five", 6)); + } +} + +// ==== +// compileViaYul: true +// ---- +// f() -> FAILURE, hex"f55fefe3", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"74776f0000000000000000000000000000000000000000000000000000000000" +// g() -> FAILURE, hex"44a06798", hex"0000000000000000000000000000000000000000000000000000000000000004", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000006", hex"0000000000000000000000000000000000000000000000000000000000000004", hex"6669766500000000000000000000000000000000000000000000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol b/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol new file mode 100644 index 000000000..2e1dcdd58 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol @@ -0,0 +1,20 @@ +error CustomError(function(uint256) external pure returns (uint256)); + +contract C +{ + function e(uint256 x) external pure returns (uint256) + { + return x; + } + + function f() external view + { + // more than one stack slot + require(false, CustomError(this.e)); + } +} + +// ==== +// compileViaYul: true +// ---- +// f() -> FAILURE, hex"271b1dfa", hex"c06afe3a8444fc0004668591e8306bfb9968e79ef37cdc8e0000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_multiple_arguments.sol b/test/libsolidity/semanticTests/errors/require_error_multiple_arguments.sol new file mode 100644 index 000000000..6c8521f9d --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_multiple_arguments.sol @@ -0,0 +1,20 @@ +error CustomError(uint256, string, uint256); + +contract C +{ + function f() external pure + { + require(false, CustomError(1, "two", 3)); + } + + function g() external pure + { + require(false, CustomError(4, "five", 6)); + } +} + +// ==== +// compileViaYul: true +// ---- +// f() -> FAILURE, hex"11a1077e", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"74776f0000000000000000000000000000000000000000000000000000000000" +// g() -> FAILURE, hex"11a1077e", hex"0000000000000000000000000000000000000000000000000000000000000004", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000006", hex"0000000000000000000000000000000000000000000000000000000000000004", hex"6669766500000000000000000000000000000000000000000000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_string_literal.sol b/test/libsolidity/semanticTests/errors/require_error_string_literal.sol new file mode 100644 index 000000000..5a3a140d0 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_string_literal.sol @@ -0,0 +1,20 @@ +error CustomError(string); + +contract C +{ + function f() external pure + { + require(false, CustomError("errorReason")); + } + + function g() external pure + { + require(false, CustomError("anotherReason")); + } +} + +// ==== +// compileViaYul: true +// ---- +// f() -> FAILURE, hex"8d6ea8be", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"000000000000000000000000000000000000000000000000000000000000000b", hex"6572726f72526561736f6e000000000000000000000000000000000000000000" +// g() -> FAILURE, hex"8d6ea8be", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"000000000000000000000000000000000000000000000000000000000000000d", hex"616e6f74686572526561736f6e00000000000000000000000000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_string_memory.sol b/test/libsolidity/semanticTests/errors/require_error_string_memory.sol new file mode 100644 index 000000000..13947d399 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_string_memory.sol @@ -0,0 +1,22 @@ +error CustomError(string); + +contract C +{ + function f() external pure + { + string memory reason = "errorReason"; + require(false, CustomError(reason)); + } + + function g() external pure + { + string memory reason = "anotherReason"; + require(false, CustomError(reason)); + } +} + +// ==== +// compileViaYul: true +// ---- +// f() -> FAILURE, hex"8d6ea8be", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"000000000000000000000000000000000000000000000000000000000000000b", hex"6572726f72526561736f6e000000000000000000000000000000000000000000" +// g() -> FAILURE, hex"8d6ea8be", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"000000000000000000000000000000000000000000000000000000000000000d", hex"616e6f74686572526561736f6e00000000000000000000000000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_uint256.sol b/test/libsolidity/semanticTests/errors/require_error_uint256.sol new file mode 100644 index 000000000..d400e5fa7 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_uint256.sol @@ -0,0 +1,20 @@ +error CustomError(uint256); + +contract C +{ + function f() external pure + { + require(false, CustomError(1)); + } + + function g() external pure + { + require(false, CustomError(2)); + } +} + +// ==== +// compileViaYul: true +// ---- +// f() -> FAILURE, hex"110b3655", hex"0000000000000000000000000000000000000000000000000000000000000001" +// g() -> FAILURE, hex"110b3655", hex"0000000000000000000000000000000000000000000000000000000000000002" diff --git a/test/libsolidity/semanticTests/errors/require_evaluation_order.sol b/test/libsolidity/semanticTests/errors/require_evaluation_order.sol new file mode 100644 index 000000000..4733b3aee --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_evaluation_order.sol @@ -0,0 +1,28 @@ +contract C +{ + error E(uint); + + function r() internal returns (uint) + { + assembly { mstore(0, 7) return (0, 32) } + return 42; + } + + function f() public returns (uint) + { + require(false, E(r())); + return 42; + } + + function g() public returns (uint) + { + require(true, E(r())); + return 42; + } +} + +// ==== +// compileViaYul: true +// ---- +// f() -> 7 +// g() -> 7 diff --git a/test/libsolidity/semanticTests/errors/require_inherited_error.sol b/test/libsolidity/semanticTests/errors/require_inherited_error.sol new file mode 100644 index 000000000..24b544b73 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_inherited_error.sol @@ -0,0 +1,17 @@ +contract Base +{ + error CustomError(uint256, string, uint256); +} + +contract C is Base +{ + function f() external pure + { + require(false, CustomError(1, "two", 3)); + } +} + +// ==== +// compileViaYul: true +// ---- +// f() -> FAILURE, hex"11a1077e", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"74776f0000000000000000000000000000000000000000000000000000000000" diff --git a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_error_event.sol b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_error_event.sol index c96b82909..c309d4c22 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_error_event.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_error_event.sol @@ -12,5 +12,5 @@ contract C { } // ---- // TypeError 9062: (138-142): Expected an inline tuple, not an expression of a tuple type. -// TypeError 9062: (177-181): Expected an inline tuple, not an expression of a tuple type. +// TypeError 7515: (153-182): Expected a tuple with 0 components instead of a single non-tuple parameter. // TypeError 9062: (216-224): Expected an inline tuple, not an expression of a tuple type. diff --git a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_invalid_operator.sol b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_invalid_operator.sol index f6035dd0a..9646acf48 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_invalid_operator.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_invalid_operator.sol @@ -17,7 +17,7 @@ contract C { // ---- // TypeError 2271: (284-299): Built-in binary operator + cannot be applied to types tuple(int_const 1,int_const 1) and tuple(int_const 2,int_const 2). // TypeError 9062: (284-299): Expected an inline tuple, not an expression of a tuple type. -// TypeError 2271: (334-345): Built-in binary operator / cannot be applied to types tuple() and tuple(). +// TypeError 2271: (334-345): Built-in binary operator / cannot be applied to types tuple() and error. // TypeError 9062: (334-345): Expected an inline tuple, not an expression of a tuple type. // TypeError 4907: (380-383): Built-in unary operator ! cannot be applied to type tuple(). // TypeError 9062: (380-383): Expected an inline tuple, not an expression of a tuple type. diff --git a/test/libsolidity/syntaxTests/errors/abi_decode_error_constructor.sol b/test/libsolidity/syntaxTests/errors/abi_decode_error_constructor.sol new file mode 100644 index 000000000..d3d26e6cc --- /dev/null +++ b/test/libsolidity/syntaxTests/errors/abi_decode_error_constructor.sol @@ -0,0 +1,9 @@ +error E(uint); +contract C { + function f() public pure returns (bytes memory) { + return abi.decode(msg.data, (E(1))); + } +} +// ---- +// TypeError 1039: (119-123): Argument has to be a type name. +// TypeError 5132: (90-125): Different number of arguments in return statement than in returns declaration. diff --git a/test/libsolidity/syntaxTests/errors/abi_encode_error_constructor.sol b/test/libsolidity/syntaxTests/errors/abi_encode_error_constructor.sol new file mode 100644 index 000000000..e8a22b08e --- /dev/null +++ b/test/libsolidity/syntaxTests/errors/abi_encode_error_constructor.sol @@ -0,0 +1,8 @@ +error E(uint); +contract C { + function f() public pure returns (bytes memory) { + return abi.encode(E(1)); + } +} +// ---- +// TypeError 2056: (108-112): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/errors/assert_with_error.sol b/test/libsolidity/syntaxTests/errors/assert_with_error.sol index 90f79b40e..16972baaf 100644 --- a/test/libsolidity/syntaxTests/errors/assert_with_error.sol +++ b/test/libsolidity/syntaxTests/errors/assert_with_error.sol @@ -3,4 +3,4 @@ function f() pure { assert(E()); } // ---- -// TypeError 9553: (42-45): Invalid type for argument in function call. Invalid implicit conversion from tuple() to bool requested. +// TypeError 9553: (42-45): Invalid type for argument in function call. Invalid implicit conversion from error to bool requested. diff --git a/test/libsolidity/syntaxTests/errors/require_custom.sol b/test/libsolidity/syntaxTests/errors/require_custom.sol index f139a4fe5..f42839027 100644 --- a/test/libsolidity/syntaxTests/errors/require_custom.sol +++ b/test/libsolidity/syntaxTests/errors/require_custom.sol @@ -4,5 +4,6 @@ contract C { require(c, E(2, 7)); } } +// ==== +// compileViaYul: true // ---- -// TypeError 9322: (83-90): No matching declaration found after argument-dependent lookup. diff --git a/test/libsolidity/syntaxTests/errors/require_custom_legacy.sol b/test/libsolidity/syntaxTests/errors/require_custom_legacy.sol new file mode 100644 index 000000000..334b84739 --- /dev/null +++ b/test/libsolidity/syntaxTests/errors/require_custom_legacy.sol @@ -0,0 +1,8 @@ +error E(uint a, uint b); +contract C { + function f(bool c) public pure { + require(c, E(2, 7)); + } +} +// ---- +// UnimplementedFeatureError: Require with a custom error is only available using the via-ir pipeline. diff --git a/test/libsolidity/syntaxTests/errors/require_nested.sol b/test/libsolidity/syntaxTests/errors/require_nested.sol new file mode 100644 index 000000000..c5dc01824 --- /dev/null +++ b/test/libsolidity/syntaxTests/errors/require_nested.sol @@ -0,0 +1,15 @@ +error CustomError(uint256); + +contract C +{ + function f() public pure returns (uint256) + { + require(false, require(CustomError(1))); + return 2; + } +} + +// ==== +// compileViaYul: true +// ---- +// TypeError 9322: (118-125): No matching declaration found after argument-dependent lookup. diff --git a/test/libsolidity/syntaxTests/errors/selector_on_instance.sol b/test/libsolidity/syntaxTests/errors/selector_on_instance.sol index 3eac5984f..008a94c02 100644 --- a/test/libsolidity/syntaxTests/errors/selector_on_instance.sol +++ b/test/libsolidity/syntaxTests/errors/selector_on_instance.sol @@ -4,4 +4,4 @@ contract C { bytes4 t = E().selector; } // ---- -// TypeError 9582: (40-52): Member "selector" not found or not visible after argument-dependent lookup in tuple(). +// TypeError 9582: (40-52): Member "selector" not found or not visible after argument-dependent lookup in error. diff --git a/test/libsolidity/syntaxTests/revertStatement/error_used_elsewhere.sol b/test/libsolidity/syntaxTests/revertStatement/error_used_elsewhere.sol index 208a7326b..bad026154 100644 --- a/test/libsolidity/syntaxTests/revertStatement/error_used_elsewhere.sol +++ b/test/libsolidity/syntaxTests/revertStatement/error_used_elsewhere.sol @@ -3,4 +3,4 @@ function f() pure { E(); } // ---- -// TypeError 7757: (35-38): Errors can only be used with revert statements: "revert MyError();". +// TypeError 7757: (35-38): Errors can only be used with revert statements: "revert MyError(args);", or require functions: "require(condition, MyError(args))". diff --git a/test/libsolidity/syntaxTests/revertStatement/require_nested.sol b/test/libsolidity/syntaxTests/revertStatement/require_nested.sol new file mode 100644 index 000000000..721c37c25 --- /dev/null +++ b/test/libsolidity/syntaxTests/revertStatement/require_nested.sol @@ -0,0 +1,13 @@ +error Error(uint256); + +contract C +{ + error OtherError(uint256); + + function f() external pure + { + revert Error(require(false, OtherError(1))); + } +} +// ---- +// TypeError 9553: (126-155): Invalid type for argument in function call. Invalid implicit conversion from tuple() to uint256 requested. From 1bf0f386a0fca48cc509f5ea51ad0356d28dd86d Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 19 Apr 2024 12:57:09 +0200 Subject: [PATCH 0077/1340] Refactor revertWithError usage --- libsolidity/codegen/YulUtilFunctions.cpp | 104 ++++++++++-------- libsolidity/codegen/YulUtilFunctions.h | 12 ++ .../codegen/ir/IRGeneratorForStatements.cpp | 31 ++---- .../cmdlineTests/require_with_error_ir/output | 6 +- 4 files changed, 83 insertions(+), 70 deletions(-) diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 5a135acb7..94c2cf8c6 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -216,6 +216,42 @@ std::string YulUtilFunctions::copyLiteralToStorageFunction(std::string const& _l }); } +std::string YulUtilFunctions::revertWithError( + std::string const& _signature, + std::vector const& _parameterTypes, + std::vector> const& _errorArguments, + std::string const& _posVar, + std::string const& _endVar +) +{ + solAssert((!_posVar.empty() && !_endVar.empty()) || (_posVar.empty() && _endVar.empty())); + bool const needsNewVariable = !_posVar.empty() && !_endVar.empty(); + + Whiskers templ(R"({ + let := () + mstore(, ) + let := (add(, 4) ) + revert(, sub(, )) + })"); + templ("pos", needsNewVariable ? _posVar : "memPtr"); + templ("end", needsNewVariable ? _endVar : "end"); + templ("hash", formatNumber(util::selectorFromSignatureU256(_signature))); + templ("allocateUnbounded", allocateUnboundedFunction()); + + std::vector errorArgumentVars; + std::vector errorArgumentTypes; + for (ASTPointer const& arg: _errorArguments) + { + errorArgumentVars += IRVariable(*arg).stackSlots(); + solAssert(arg->annotation().type); + errorArgumentTypes.push_back(arg->annotation().type); + } + templ("argumentVars", joinHumanReadablePrefixed(errorArgumentVars)); + templ("encode", ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector).tupleEncoder(errorArgumentTypes, _parameterTypes)); + + return templ.render(); +} + std::string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* _messageType) { std::string functionName = @@ -273,57 +309,37 @@ std::string YulUtilFunctions::requireWithErrorFunction(FunctionCall const& error solAssert(errorDefinition); std::string const errorSignature = errorDefinition->functionType(true)->externalSignature(); - std::string const signatureHash = formatNumber(util::selectorFromSignatureU256(errorSignature)); - std::string const functionName = [&]() { - // Note that in most cases we'll always generate one function per error definition, - // because types in the constructor call will match the ones in the definition. The only - // exception are calls with types, where each instance has its own type (e.g. literals). - std::string name = "require_helper_t_error_" + std::to_string(errorDefinition->id()) + "_" + errorDefinition->name(); - for (ASTPointer const& argument: errorConstructorCall.sortedArguments()) - { - solAssert(argument->annotation().type); - name += ("_" + argument->annotation().type->identifier()); - } - return name; - }(); + // Note that in most cases we'll always generate one function per error definition, + // because types in the constructor call will match the ones in the definition. The only + // exception are calls with types, where each instance has its own type (e.g. literals). + std::string functionName = "require_helper_t_error_" + std::to_string(errorDefinition->id()) + "_" + errorDefinition->name(); + for (ASTPointer const& argument: errorConstructorCall.sortedArguments()) + { + solAssert(argument->annotation().type); + functionName += ("_" + argument->annotation().type->identifier()); + } - auto errorArgumentVarsAndTypes = [&]() -> std::tuple, std::vector> { - std::vector errorArgumentVars; - std::vector errorArgumentTypes; - for (ASTPointer const& arg: errorConstructorCall.sortedArguments()) - { - solAssert(arg->annotation().type); - if (arg->annotation().type->sizeOnStack() > 0) - errorArgumentVars += IRVariable(*arg).stackSlots(); - errorArgumentTypes.push_back(arg->annotation().type); - } - return std::make_tuple(std::move(errorArgumentVars), std::move(errorArgumentTypes)); - }(); + std::vector functionParameterNames; + for (ASTPointer const& arg: errorConstructorCall.sortedArguments()) + { + solAssert(arg->annotation().type); + if (arg->annotation().type->sizeOnStack() > 0) + functionParameterNames += IRVariable(*arg).stackSlots(); + } return m_functionCollector.createFunction(functionName, [&]() { - auto [errorArgumentVars, errorArgumentTypes] = errorArgumentVarsAndTypes; - std::string const encodeFunc = ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector) - .tupleEncoder( - errorArgumentTypes, - errorDefinition->functionType(true)->parameterTypes() - ); - return Whiskers(R"( - function (condition ) { - if iszero(condition) { - let memPtr := () - mstore(memPtr, ) - let end := (add(memPtr, ) ) - revert(memPtr, sub(end, memPtr)) - } + function (condition ) { + if iszero(condition) + } )") ("functionName", functionName) - ("allocateUnbounded", allocateUnboundedFunction()) - ("errorHash", signatureHash) - ("abiEncodeFunc", encodeFunc) - ("hashHeaderSize", std::to_string(4)) - ("errorArguments", joinHumanReadablePrefixed(errorArgumentVars)) + ("functionParameterNames", joinHumanReadablePrefixed(functionParameterNames)) + // We're creating parameter names from the expressions passed into the constructor call, + // which will result in odd names like `expr_29` that would normally be used for locals. + // Note that this is the naming expected by `revertWithError()`. + ("revertWithError", revertWithError(errorSignature, errorDefinition->functionType(true)->parameterTypes(), errorConstructorCall.sortedArguments())) .render(); }); } diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index db4c26725..58d20dcbf 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -90,6 +90,18 @@ class YulUtilFunctions /// signature: (slot) -> std::string copyLiteralToStorageFunction(std::string const& _literal); + /// @returns statements to revert with an error. + /// Generates code to revert with an error. The error arguments are assumed to + /// be already evaluated and available in local IRVariables, but not yet + /// converted. + std::string revertWithError( + std::string const& _signature, + std::vector const& _parameterTypes, + std::vector> const& _errorArguments, + std::string const& _posVar = {}, + std::string const& _endVar = {} + ); + // @returns the name of a function that has the equivalent logic of an // `assert` or `require` call. std::string requireOrAssertFunction(bool _assert, Type const* _messageType = nullptr); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index bf028fce5..bffd4de68 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -3389,32 +3389,15 @@ void IRGeneratorForStatements::revertWithError( std::vector> const& _errorArguments ) { - Whiskers templ(R"({ - let := () - mstore(, ) - let := (add(, 4) ) - revert(, sub(, )) - })"); - templ("pos", m_context.newYulVariable()); - templ("end", m_context.newYulVariable()); - templ("hash", util::selectorFromSignatureU256(_signature).str()); - templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); - - std::vector errorArgumentVars; - std::vector errorArgumentTypes; - for (ASTPointer const& arg: _errorArguments) - { - errorArgumentVars += IRVariable(*arg).stackSlots(); - solAssert(arg->annotation().type); - errorArgumentTypes.push_back(arg->annotation().type); - } - templ("argumentVars", joinHumanReadablePrefixed(errorArgumentVars)); - templ("encode", m_context.abiFunctions().tupleEncoder(errorArgumentTypes, _parameterTypes)); - - appendCode() << templ.render(); + appendCode() << m_utils.revertWithError( + _signature, + _parameterTypes, + _errorArguments, + m_context.newYulVariable(), + m_context.newYulVariable() + ); } - bool IRGeneratorForStatements::visit(TryCatchClause const& _clause) { _clause.block().accept(*this); diff --git a/test/cmdlineTests/require_with_error_ir/output b/test/cmdlineTests/require_with_error_ir/output index dacc9fc91..232f0d76f 100644 --- a/test/cmdlineTests/require_with_error_ir/output +++ b/test/cmdlineTests/require_with_error_ir/output @@ -184,7 +184,8 @@ object "C_36" { } function require_helper_t_error_7_CustomError_t_rational_1_by_1_t_stringliteral_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720(condition , expr_15) { - if iszero(condition) { + if iszero(condition) + { let memPtr := allocate_unbounded() mstore(memPtr, 0x97ea5a2f00000000000000000000000000000000000000000000000000000000) let end := abi_encode_tuple_t_rational_1_by_1_t_stringliteral_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720__to_t_uint256_t_string_memory_ptr__fromStack(add(memPtr, 4) , expr_15) @@ -238,7 +239,8 @@ object "C_36" { } function require_helper_t_error_7_CustomError_t_rational_2_by_1_t_stringliteral_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5(condition , expr_29) { - if iszero(condition) { + if iszero(condition) + { let memPtr := allocate_unbounded() mstore(memPtr, 0x97ea5a2f00000000000000000000000000000000000000000000000000000000) let end := abi_encode_tuple_t_rational_2_by_1_t_stringliteral_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5__to_t_uint256_t_string_memory_ptr__fromStack(add(memPtr, 4) , expr_29) From ceabc540b65cfff875407d04c179122fd7e02096 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 26 Apr 2024 07:01:18 +0200 Subject: [PATCH 0078/1340] Fix mistake in require condition in docs --- docs/contracts/errors.rst | 2 +- docs/introduction-to-smart-contracts.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contracts/errors.rst b/docs/contracts/errors.rst index e4955ddae..8c57586e9 100644 --- a/docs/contracts/errors.rst +++ b/docs/contracts/errors.rst @@ -40,7 +40,7 @@ as well as the newer approach with ``require`` in function ``transferWithRequire balance[to] += amount; } function transferWithRequireError(address to, uint256 amount) public { - require(amount > balance[msg.sender], InsufficientBalance(balance[msg.sender], amount)); + require(amount <= balance[msg.sender], InsufficientBalance(balance[msg.sender], amount)); balance[msg.sender] -= amount; balance[to] += amount; } diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 1c5b87373..c86005794 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -119,7 +119,7 @@ registering with a username and password, all you need is an Ethereum keypair. // Sends an amount of existing coins // from any caller to an address function send(address receiver, uint amount) public { - require(amount > balances[msg.sender], InsufficientBalance(amount, balances[msg.sender])); + require(amount <= balances[msg.sender], InsufficientBalance(amount, balances[msg.sender])); balances[msg.sender] -= amount; balances[receiver] += amount; emit Sent(msg.sender, receiver, amount); From 351a910b6d8d5642b16428ecde78461c800d5072 Mon Sep 17 00:00:00 2001 From: r0qs Date: Fri, 26 Apr 2024 14:17:41 +0200 Subject: [PATCH 0079/1340] Install python dependencies on buildpack-deps images --- scripts/docker/buildpack-deps/Dockerfile.emscripten | 5 +++-- .../buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz | 11 ++++++----- scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 | 7 ++++--- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 | 7 ++++--- .../docker/buildpack-deps/Dockerfile.ubuntu2204.clang | 8 +++++--- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten index c29fc699a..f72909a24 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -33,13 +33,14 @@ # Using $(em-config CACHE)/sysroot/usr seems to work, though, and still has cmake find the # dependencies automatically. FROM emscripten/emsdk:3.1.19 AS base -LABEL version="16" +LABEL version="17" ADD emscripten.jam /usr/src RUN set -ex && \ \ apt-get update && \ - apt-get install lz4 sudo --no-install-recommends && \ + apt-get install lz4 sudo lsof python3 python3-pip --no-install-recommends && \ + pip3 install requests && \ \ cd /usr/src && \ git clone https://github.com/Z3Prover/z3.git -b z3-4.12.1 --depth 1 && \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index 0b2a99b1a..2775c5c4d 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -22,19 +22,20 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-clang:latest as base -LABEL version="5" +LABEL version="6" ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update; \ apt-get -qqy install --no-install-recommends \ automake libtool bison texinfo \ - build-essential sudo \ + build-essential sudo lsof \ software-properties-common \ - ninja-build git wget \ - libbz2-dev zlib1g-dev git curl uuid-dev \ + ninja-build git wget python3-pip \ + libbz2-dev zlib1g-dev curl uuid-dev \ pkg-config openjdk-8-jdk liblzma-dev unzip mlton m4 jq; \ - apt-get install -qy python3-pip; + pip3 install codecov parsec tabulate pylint z3-solver \ + pygments-lexer-solidity deepdiff colorama requests; # Install cmake 3.21.2 (minimum requirement is cmake 3.10) RUN wget https://github.com/Kitware/CMake/releases/download/v3.21.2/cmake-3.21.2-Linux-x86_64.sh; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index 45490291a..c2d038ee0 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:focal AS base -LABEL version="22" +LABEL version="23" ARG DEBIAN_FRONTEND=noninteractive @@ -34,13 +34,14 @@ RUN set -ex; \ apt-get install -qqy --no-install-recommends \ build-essential sudo \ software-properties-common \ - cmake ninja-build \ + cmake ninja-build lsof \ libboost-filesystem-dev libboost-test-dev libboost-system-dev \ libboost-program-options-dev \ libcvc4-dev libz3-static-dev z3-static jq \ ; \ apt-get install -qy python3-pip python3-sphinx; \ - pip3 install codecov; + pip3 install codecov parsec tabulate pylint z3-solver \ + pygments-lexer-solidity deepdiff colorama requests; # Eldarica RUN set -ex; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index d7b925448..957940914 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="7" +LABEL version="8" ARG DEBIAN_FRONTEND=noninteractive @@ -34,13 +34,14 @@ RUN set -ex; \ apt-get install -qqy --no-install-recommends \ build-essential sudo \ software-properties-common \ - cmake ninja-build \ + cmake ninja-build lsof \ libboost-filesystem-dev libboost-test-dev libboost-system-dev \ libboost-program-options-dev \ libcvc4-dev libz3-static-dev z3-static jq \ libcln-dev zip locales-all; \ apt-get install -qy python3-pip python3-sphinx; \ - pip3 install codecov; + pip3 install codecov parsec tabulate pylint z3-solver \ + pygments-lexer-solidity deepdiff colorama requests; # Eldarica RUN set -ex; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang index 60d5a599c..b26ce3ff5 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="6" +LABEL version="7" ARG DEBIAN_FRONTEND=noninteractive @@ -34,12 +34,14 @@ RUN set -ex; \ apt-get install -qqy --no-install-recommends \ build-essential sudo \ software-properties-common \ - cmake ninja-build \ + cmake ninja-build lsof \ libboost-filesystem-dev libboost-test-dev libboost-system-dev \ libboost-program-options-dev \ clang \ libz3-static-dev z3-static jq \ - libcln-dev; + libcln-dev python3-pip; \ + pip3 install codecov parsec tabulate pylint z3-solver \ + pygments-lexer-solidity deepdiff colorama requests; # Eldarica RUN set -ex; \ From c5bfea2268fa70168f39be634c11b5b5b25876c9 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 26 Apr 2024 10:49:30 +0200 Subject: [PATCH 0080/1340] Refactor requireOrAssert to use revertWithError --- libsolidity/codegen/YulUtilFunctions.cpp | 33 +- libsolidity/codegen/YulUtilFunctions.h | 6 +- .../codegen/ir/IRGeneratorForStatements.cpp | 4 +- .../require_with_error_ir/input.sol | 9 +- test/cmdlineTests/require_with_string_ir/args | 1 + .../require_with_string_ir/input.sol | 13 + .../require_with_string_ir/output | 290 ++++++++++++++++++ 7 files changed, 324 insertions(+), 32 deletions(-) create mode 100644 test/cmdlineTests/require_with_string_ir/args create mode 100644 test/cmdlineTests/require_with_string_ir/input.sol create mode 100644 test/cmdlineTests/require_with_string_ir/output diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 94c2cf8c6..b71dfd566 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -252,7 +252,7 @@ std::string YulUtilFunctions::revertWithError( return templ.render(); } -std::string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* _messageType) +std::string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* _messageType, ASTPointer _stringArgumentExpression) { std::string functionName = std::string(_assert ? "assert_helper" : "require_helper") + @@ -271,34 +271,19 @@ std::string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* ("functionName", functionName) .render(); - int const hashHeaderSize = 4; - u256 const errorHash = util::selectorFromSignatureU256("Error(string)"); - - std::string const encodeFunc = ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector) - .tupleEncoder( - {_messageType}, - {TypeProvider::stringMemory()} - ); + solAssert(_stringArgumentExpression, "Require with string must have a string argument"); + solAssert(_stringArgumentExpression->annotation().type); + std::vector functionParameterNames = IRVariable(*_stringArgumentExpression).stackSlots(); return Whiskers(R"( - function (condition ) { - if iszero(condition) { - let memPtr := () - mstore(memPtr, ) - let end := (add(memPtr, ) ) - revert(memPtr, sub(end, memPtr)) - } + function (condition ) { + if iszero(condition) + } )") ("functionName", functionName) - ("allocateUnbounded", allocateUnboundedFunction()) - ("errorHash", formatNumber(errorHash)) - ("abiEncodeFunc", encodeFunc) - ("hashHeaderSize", std::to_string(hashHeaderSize)) - ("messageVars", - (_messageType->sizeOnStack() > 0 ? ", " : "") + - suffixedVariableNameList("message_", 1, 1 + _messageType->sizeOnStack()) - ) + ("revertWithError", revertWithError("Error(string)", {_messageType}, {_stringArgumentExpression})) + ("functionParameterNames", joinHumanReadablePrefixed(functionParameterNames)) .render(); }); } diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index 58d20dcbf..a1b45b656 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -104,7 +104,11 @@ class YulUtilFunctions // @returns the name of a function that has the equivalent logic of an // `assert` or `require` call. - std::string requireOrAssertFunction(bool _assert, Type const* _messageType = nullptr); + std::string requireOrAssertFunction( + bool _assert, + Type const* _messageType = nullptr, + ASTPointer _stringArgumentExpression = nullptr + ); // @returns function that has equivalent logic of a require function, but with a custom // error constructor parameter. diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index bffd4de68..2464fefc4 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1166,9 +1166,11 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) } else { + ASTPointer stringArgumentExpression = messageArgumentType ? arguments[1] : nullptr; std::string requireOrAssertFunction = m_utils.requireOrAssertFunction( functionType->kind() == FunctionType::Kind::Assert, - messageArgumentType + messageArgumentType, + stringArgumentExpression ); appendCode() << std::move(requireOrAssertFunction) << "(" << IRVariable(*arguments[0]).name(); if (messageArgumentType && messageArgumentType->sizeOnStack() > 0) diff --git a/test/cmdlineTests/require_with_error_ir/input.sol b/test/cmdlineTests/require_with_error_ir/input.sol index f041b27b7..eb0787fcc 100644 --- a/test/cmdlineTests/require_with_error_ir/input.sol +++ b/test/cmdlineTests/require_with_error_ir/input.sol @@ -3,15 +3,12 @@ pragma solidity >=0.0; error CustomError(uint256, string); -contract C -{ - function f(bool condition) external pure - { +contract C { + function f(bool condition) external pure { require(condition, CustomError(1, "two")); } - function g(bool condition) external pure - { + function g(bool condition) external pure { require(condition, CustomError(2, "three")); } } diff --git a/test/cmdlineTests/require_with_string_ir/args b/test/cmdlineTests/require_with_string_ir/args new file mode 100644 index 000000000..be08aefb4 --- /dev/null +++ b/test/cmdlineTests/require_with_string_ir/args @@ -0,0 +1 @@ +--ir --debug-info none diff --git a/test/cmdlineTests/require_with_string_ir/input.sol b/test/cmdlineTests/require_with_string_ir/input.sol new file mode 100644 index 000000000..c47045171 --- /dev/null +++ b/test/cmdlineTests/require_with_string_ir/input.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f(bool condition) external pure { + string memory message = "Condition must be satisfied"; + require(condition, message); + } + + function g(bool condition) external pure { + require(condition, "Condition must be satisfied"); + } +} diff --git a/test/cmdlineTests/require_with_string_ir/output b/test/cmdlineTests/require_with_string_ir/output new file mode 100644 index 000000000..21828ac2a --- /dev/null +++ b/test/cmdlineTests/require_with_string_ir/output @@ -0,0 +1,290 @@ +IR: + +/// @use-src 0:"require_with_string_ir/input.sol" +object "C_28" { + code { + + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_28() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_28_deployed"), datasize("C_28_deployed")) + + return(_1, datasize("C_28_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_28() { + + } + + } + /// @use-src 0:"require_with_string_ir/input.sol" + object "C_28_deployed" { + code { + + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x98c3a6c1 + { + // f(bool) + + external_fun_f_16() + } + + case 0xd48092f7 + { + // g(bool) + + external_fun_g_27() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_bool(value) -> cleaned { + cleaned := iszero(iszero(value)) + } + + function validator_revert_t_bool(value) { + if iszero(eq(value, cleanup_t_bool(value))) { revert(0, 0) } + } + + function abi_decode_t_bool(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_bool(value) + } + + function abi_decode_tuple_t_bool(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_bool(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_f_16() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_bool(4, calldatasize()) + fun_f_16(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function external_fun_g_27() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_bool(4, calldatasize()) + fun_g_27(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function round_up_to_mul_of_32(value) -> result { + result := and(add(value, 31), not(31)) + } + + function panic_error_0x41() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x41) + revert(0, 0x24) + } + + function finalize_allocation(memPtr, size) { + let newFreePtr := add(memPtr, round_up_to_mul_of_32(size)) + // protect against overflow + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() } + mstore(64, newFreePtr) + } + + function allocate_memory(size) -> memPtr { + memPtr := allocate_unbounded() + finalize_allocation(memPtr, size) + } + + function array_allocation_size_t_string_memory_ptr(length) -> size { + // Make sure we can allocate memory without overflow + if gt(length, 0xffffffffffffffff) { panic_error_0x41() } + + size := round_up_to_mul_of_32(length) + + // add length slot + size := add(size, 0x20) + + } + + function allocate_memory_array_t_string_memory_ptr(length) -> memPtr { + let allocSize := array_allocation_size_t_string_memory_ptr(length) + memPtr := allocate_memory(allocSize) + + mstore(memPtr, length) + + } + + function store_literal_in_memory_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46(memPtr) { + + mstore(add(memPtr, 0), "Condition must be satisfied") + + } + + function copy_literal_to_memory_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46() -> memPtr { + memPtr := allocate_memory_array_t_string_memory_ptr(27) + store_literal_in_memory_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46(add(memPtr, 32)) + } + + function convert_t_stringliteral_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46_to_t_string_memory_ptr() -> converted { + converted := copy_literal_to_memory_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46() + } + + function array_length_t_string_memory_ptr(value) -> length { + + length := mload(value) + + } + + function array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, length) -> updated_pos { + mstore(pos, length) + updated_pos := add(pos, 0x20) + } + + function copy_memory_to_memory_with_cleanup(src, dst, length) { + + mcopy(dst, src, length) + mstore(add(dst, length), 0) + + } + + function abi_encode_t_string_memory_ptr_to_t_string_memory_ptr_fromStack(value, pos) -> end { + let length := array_length_t_string_memory_ptr(value) + pos := array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, length) + copy_memory_to_memory_with_cleanup(add(value, 0x20), pos, length) + end := add(pos, round_up_to_mul_of_32(length)) + } + + function abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(headStart , value0) -> tail { + tail := add(headStart, 32) + + mstore(add(headStart, 0), sub(tail, headStart)) + tail := abi_encode_t_string_memory_ptr_to_t_string_memory_ptr_fromStack(value0, tail) + + } + + function require_helper_t_string_memory_ptr(condition , expr_12_mpos) { + if iszero(condition) + { + let memPtr := allocate_unbounded() + mstore(memPtr, 0x08c379a000000000000000000000000000000000000000000000000000000000) + let end := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(add(memPtr, 4) , expr_12_mpos) + revert(memPtr, sub(end, memPtr)) + } + } + + function fun_f_16(var_condition_3) { + + let var_message_7_mpos := convert_t_stringliteral_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46_to_t_string_memory_ptr() + + let _1 := var_condition_3 + let expr_11 := _1 + + let _2_mpos := var_message_7_mpos + let expr_12_mpos := _2_mpos + + require_helper_t_string_memory_ptr(expr_11, expr_12_mpos) + + } + + function abi_encode_t_stringliteral_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46_to_t_string_memory_ptr_fromStack(pos) -> end { + pos := array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, 27) + store_literal_in_memory_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46(pos) + end := add(pos, 32) + } + + function abi_encode_tuple_t_stringliteral_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46__to_t_string_memory_ptr__fromStack(headStart ) -> tail { + tail := add(headStart, 32) + + mstore(add(headStart, 0), sub(tail, headStart)) + tail := abi_encode_t_stringliteral_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46_to_t_string_memory_ptr_fromStack( tail) + + } + + function require_helper_t_stringliteral_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46(condition ) { + if iszero(condition) + { + let memPtr := allocate_unbounded() + mstore(memPtr, 0x08c379a000000000000000000000000000000000000000000000000000000000) + let end := abi_encode_tuple_t_stringliteral_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46__to_t_string_memory_ptr__fromStack(add(memPtr, 4) ) + revert(memPtr, sub(end, memPtr)) + } + } + + function fun_g_27(var_condition_18) { + + let _3 := var_condition_18 + let expr_22 := _3 + + require_helper_t_stringliteral_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46(expr_22) + + } + + } + + data ".metadata" hex"" + } + +} From 700ba0b9b36d65280192a1b5d012c4ae34131276 Mon Sep 17 00:00:00 2001 From: r0qs Date: Fri, 26 Apr 2024 17:04:29 +0200 Subject: [PATCH 0081/1340] Sort packages in alphabetical order and split commands by line --- .../buildpack-deps/Dockerfile.emscripten | 8 +++- .../Dockerfile.ubuntu.clang.ossfuzz | 39 ++++++++++++++---- .../buildpack-deps/Dockerfile.ubuntu2004 | 38 ++++++++++++----- .../buildpack-deps/Dockerfile.ubuntu2204 | 41 ++++++++++++++----- .../Dockerfile.ubuntu2204.clang | 38 ++++++++++++----- 5 files changed, 125 insertions(+), 39 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten index f72909a24..961901f00 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -37,9 +37,13 @@ LABEL version="17" ADD emscripten.jam /usr/src RUN set -ex && \ - \ apt-get update && \ - apt-get install lz4 sudo lsof python3 python3-pip --no-install-recommends && \ + apt-get install -qqy --no-install-recommends \ + lsof \ + lz4 \ + python3 \ + python3-pip \ + sudo && \ pip3 install requests && \ \ cd /usr/src && \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index 2775c5c4d..94b6c247c 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -28,14 +28,39 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update; \ apt-get -qqy install --no-install-recommends \ - automake libtool bison texinfo \ - build-essential sudo lsof \ + automake \ + bison \ + build-essential \ + curl \ + git \ + jq \ + libbz2-dev \ + liblzma-dev \ + libtool \ + lsof \ + m4 \ + mlton \ + ninja-build \ + openjdk-8-jdk \ + pkg-config \ + python3-pip \ software-properties-common \ - ninja-build git wget python3-pip \ - libbz2-dev zlib1g-dev curl uuid-dev \ - pkg-config openjdk-8-jdk liblzma-dev unzip mlton m4 jq; \ - pip3 install codecov parsec tabulate pylint z3-solver \ - pygments-lexer-solidity deepdiff colorama requests; + sudo \ + texinfo \ + unzip \ + uuid-dev \ + wget \ + zlib1g-dev; \ + pip3 install \ + codecov \ + colorama \ + deepdiff \ + parsec \ + pygments-lexer-solidity \ + pylint \ + requests \ + tabulate \ + z3-solver; # Install cmake 3.21.2 (minimum requirement is cmake 3.10) RUN wget https://github.com/Kitware/CMake/releases/download/v3.21.2/cmake-3.21.2-Linux-x86_64.sh; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index c2d038ee0..4b5dbafac 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -32,21 +32,39 @@ RUN set -ex; \ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1c52189c923f6ca9 ; \ apt-get update; \ apt-get install -qqy --no-install-recommends \ - build-essential sudo \ - software-properties-common \ - cmake ninja-build lsof \ - libboost-filesystem-dev libboost-test-dev libboost-system-dev \ + build-essential \ + cmake \ + jq \ + libboost-filesystem-dev \ libboost-program-options-dev \ - libcvc4-dev libz3-static-dev z3-static jq \ - ; \ - apt-get install -qy python3-pip python3-sphinx; \ - pip3 install codecov parsec tabulate pylint z3-solver \ - pygments-lexer-solidity deepdiff colorama requests; + libboost-system-dev \ + libboost-test-dev \ + libcvc4-dev \ + libz3-static-dev \ + lsof \ + ninja-build \ + python3-pip \ + python3-sphinx \ + software-properties-common \ + sudo \ + z3-static; \ + pip3 install \ + codecov \ + colorama \ + deepdiff \ + parsec \ + pygments-lexer-solidity \ + pylint \ + requests \ + tabulate \ + z3-solver; # Eldarica RUN set -ex; \ apt-get update; \ - apt-get install -qy unzip openjdk-11-jre; \ + apt-get install -qqy \ + openjdk-11-jre \ + unzip; \ eldarica_version="2.1"; \ wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index 957940914..92cc20d43 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -32,21 +32,42 @@ RUN set -ex; \ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1c52189c923f6ca9 ; \ apt-get update; \ apt-get install -qqy --no-install-recommends \ - build-essential sudo \ - software-properties-common \ - cmake ninja-build lsof \ - libboost-filesystem-dev libboost-test-dev libboost-system-dev \ + build-essential \ + cmake \ + jq \ + libboost-filesystem-dev \ libboost-program-options-dev \ - libcvc4-dev libz3-static-dev z3-static jq \ - libcln-dev zip locales-all; \ - apt-get install -qy python3-pip python3-sphinx; \ - pip3 install codecov parsec tabulate pylint z3-solver \ - pygments-lexer-solidity deepdiff colorama requests; + libboost-system-dev \ + libboost-test-dev \ + libcln-dev \ + libcvc4-dev \ + libz3-static-dev \ + locales-all \ + lsof \ + ninja-build \ + python3-pip \ + python3-sphinx \ + software-properties-common \ + sudo \ + z3-static \ + zip; \ + pip3 install \ + codecov \ + colorama \ + deepdiff \ + parsec \ + pygments-lexer-solidity \ + pylint \ + requests \ + tabulate \ + z3-solver; # Eldarica RUN set -ex; \ apt-get update; \ - apt-get install -qy unzip openjdk-11-jre; \ + apt-get install -qqy \ + openjdk-11-jre \ + unzip; \ eldarica_version="2.1"; \ wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang index b26ce3ff5..b11f798e8 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang @@ -32,21 +32,39 @@ RUN set -ex; \ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1c52189c923f6ca9 ; \ apt-get update; \ apt-get install -qqy --no-install-recommends \ - build-essential sudo \ - software-properties-common \ - cmake ninja-build lsof \ - libboost-filesystem-dev libboost-test-dev libboost-system-dev \ - libboost-program-options-dev \ + build-essential \ clang \ - libz3-static-dev z3-static jq \ - libcln-dev python3-pip; \ - pip3 install codecov parsec tabulate pylint z3-solver \ - pygments-lexer-solidity deepdiff colorama requests; + cmake \ + jq \ + lsof \ + libboost-filesystem-dev \ + libboost-program-options-dev \ + libboost-system-dev \ + libboost-test-dev \ + libcln-dev \ + libz3-static-dev \ + ninja-build \ + python3-pip \ + software-properties-common \ + sudo \ + z3-static; \ + pip3 install \ + codecov \ + colorama \ + deepdiff \ + parsec \ + pygments-lexer-solidity \ + pylint \ + requests \ + tabulate \ + z3-solver; # Eldarica RUN set -ex; \ apt-get update; \ - apt-get install -qy unzip openjdk-11-jre; \ + apt-get install -qy \ + openjdk-11-jre \ + unzip; \ eldarica_version="2.1"; \ wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ From 9cbd0a1046f4665a830dd402dee69585bba4a214 Mon Sep 17 00:00:00 2001 From: r0qs Date: Fri, 26 Apr 2024 17:06:32 +0200 Subject: [PATCH 0082/1340] Remove superfluous cleanup step --- scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz | 4 ---- scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 | 4 ---- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 | 4 ---- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang | 4 ---- 4 files changed, 16 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index 94b6c247c..f8a4c73ce 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -173,10 +173,6 @@ RUN set -ex; \ cp abicoder.hpp /usr/include; \ rm -rf /usr/src/Yul-Isabelle -# Cleanup -RUN set -ex; \ - rm -rf /var/lib/apt/lists/* - FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index 4b5dbafac..815c93ee8 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -71,10 +71,6 @@ RUN set -ex; \ unzip /opt/eld_binaries.zip -d /opt; \ rm -f /opt/eld_binaries.zip; -# Cleanup -RUN set -ex; \ - rm -rf /var/lib/apt/lists/* - FROM base AS libraries # EVMONE diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index 92cc20d43..254e83b4c 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -74,10 +74,6 @@ RUN set -ex; \ unzip /opt/eld_binaries.zip -d /opt; \ rm -f /opt/eld_binaries.zip; -# Cleanup -RUN set -ex; \ - rm -rf /var/lib/apt/lists/* - FROM base AS libraries # EVMONE diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang index b11f798e8..af6155b6e 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang @@ -71,10 +71,6 @@ RUN set -ex; \ unzip /opt/eld_binaries.zip -d /opt; \ rm -f /opt/eld_binaries.zip; -# Cleanup -RUN set -ex; \ - rm -rf /var/lib/apt/lists/* - FROM base AS libraries ENV CC clang From 9b89c30c06fa20854737a5fee86cc7d3847d7095 Mon Sep 17 00:00:00 2001 From: r0qs Date: Fri, 26 Apr 2024 14:38:21 +0200 Subject: [PATCH 0083/1340] Move python dependencies to docker images Co-authored-by: Tim-Tscheppe --- .circleci/config.yml | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8b588740f..9ca938b9b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -331,9 +331,6 @@ commands: - checkout - attach_workspace: at: build - - run: - name: Install dependencies - command: pip install --user deepdiff colorama - run: name: Executing solc LSP test suite command: test/lsp.py build/solc/solc --non-interactive @@ -925,19 +922,9 @@ jobs: - matrix_notify_failure_unless_pr chk_pylint: - <<: *base_cimg_small + <<: *base_ubuntu2204_small steps: - checkout - - install_python3: - packages: > - pylint - z3-solver - pygments-lexer-solidity - parsec - tabulate - deepdiff - colorama - requests - run: pylint --version - run: name: Linting Python Scripts @@ -974,11 +961,9 @@ jobs: - matrix_notify_failure_unless_pr chk_proofs: - <<: *base_cimg_small + <<: *base_ubuntu2204_small steps: - checkout - - install_python3: - packages: z3-solver - run_proofs - matrix_notify_failure_unless_pr @@ -993,10 +978,6 @@ jobs: <<: *base_ubuntu2204_small steps: - checkout - - run: - # TODO: Add these to the base image - name: Install gas_diff_stats.py dependencies - command: python3 -m pip install --user parsec tabulate - run: name: Python unit tests command: python3 test/pyscriptTests.py @@ -1508,14 +1489,6 @@ jobs: if command -v npm &> /dev/null; then sudo npm install -g pnpm fi - - install_python3: - packages: requests - - run: - name: Install lsof - command: | - # lsof is used by Colony in its stop-blockchain-client.sh script - sudo apt update - sudo apt-get --quiet --assume-yes --no-install-recommends install lsof - when: condition: << parameters.python2 >> steps: From 21dbf834117aec2a8751a7b5abffb640a1cf9336 Mon Sep 17 00:00:00 2001 From: r0qs Date: Fri, 26 Apr 2024 17:59:01 +0200 Subject: [PATCH 0084/1340] Bump CI docker images --- .circleci/config.yml | 22 +++++++++++----------- scripts/build_emscripten.sh | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9ca938b9b..b5b151c58 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,25 +9,25 @@ version: 2.1 parameters: ubuntu-2004-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-22 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:212b4d79a89c6e2d9b58ddea2d6296c5618f4ae0b016694a3b159d2b11cbbacc" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-23 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:84a1fb8771236e8d9aa5c615a425b8929e56a6e4f150a60078c8d74a1ceaa6c2" ubuntu-2204-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-7 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:ecbeec36b12fd953bfb6fb3e7ced474bb73945d7ed615e6538960c32bae8126c" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-8 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:1c3a4118218640b2bf632242979a63d48f3d9c70d48be9574332f2dbbd04b192" ubuntu-2204-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-6 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:1818a56061f39ece4a92138948404214bf939c9deb68f4dc2c68cd82b39e8410" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-7 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:0f47e733e100080c4174381c262cfcf974bc8e7c3c41b8dff611b9641c82f714" ubuntu-clang-ossfuzz-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-5 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c21c4c2a591d0702c388d1944539f6498ed8e51c54c1a1cb34693079efd9ab77" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-6 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:8883fa2845bbc1e0922af60439313666e4ba325f67a117e17d78cca3ea6589b3" emscripten-docker-image: type: string - # NOTE: Please remember to update the `build_emscripten.sh` whenever the hash of this image changes. - # solbuildpackpusher/solidity-buildpack-deps:emscripten-16 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:19fcb5ac029bbc27ec36e10f7d14ea224d8010145f9690562ef084fd16146b0c" + # NOTE: Please remember to update the `scripts/build_emscripten.sh` whenever the hash of this image changes. + # solbuildpackpusher/solidity-buildpack-deps:emscripten-17 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c57f2bfb8c15d70fe290629358dd1c73dc126e3760f443b54764797556b887d4" evm-version: type: string default: london diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index 1b780a427..dc862b1f7 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -33,9 +33,9 @@ if (( $# != 0 )); then params="$(printf "%q " "${@}")" fi -# solbuildpackpusher/solidity-buildpack-deps:emscripten-16 +# solbuildpackpusher/solidity-buildpack-deps:emscripten-17 # NOTE: Without `safe.directory` git would assume it's not safe to operate on /root/project since it's owned by a different user. # See https://github.blog/2022-04-12-git-security-vulnerability-announced/ docker run -v "$(pwd):/root/project" -w /root/project \ - solbuildpackpusher/solidity-buildpack-deps@sha256:19fcb5ac029bbc27ec36e10f7d14ea224d8010145f9690562ef084fd16146b0c \ + solbuildpackpusher/solidity-buildpack-deps@sha256:c57f2bfb8c15d70fe290629358dd1c73dc126e3760f443b54764797556b887d4 \ /bin/bash -c "git config --global --add safe.directory /root/project && ./scripts/ci/build_emscripten.sh ${params}" From 61ced0d9745233dbdb50a3603ceb3be1ddc4cac2 Mon Sep 17 00:00:00 2001 From: Patrick Collins <54278053+PatrickAlphaC@users.noreply.github.com> Date: Sat, 27 Apr 2024 13:39:23 -0400 Subject: [PATCH 0085/1340] Update cheatsheet.rst The documentation currently says: ```` ``abi.encodeCall(function functionPointer, (...)) returns (bytes memory)``: ABI-encodes a call to ``functionPointer`` with the arguments found in the tuple. Performs a full type-check, ensuring the types match the function signature. Result equals ``abi.encodeWithSelector(functionPointer.selector, (...))`` ```` However, this is not correct. `abi.encodeWithSelector` does not take a tuple as a second argument, instead, it takes an unended list of arguments. Saying these two are identical, is then not correct: - `abi.encodeCall(function functionPointer, (...)) ` - `abi.encodeWithSelector(functionPointer.selector, (...))` It should be that these two are identical: - `abi.encodeCall(function functionPointer, (...)) ` - `abi.encodeWithSelector(functionPointer.selector, ...)` subtle, but maybe there is a clearly way to say that `encodeWithSelector` is the same as the unpacked tuple from `encodeCall`. --- docs/cheatsheet.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index bc678c647..6b69b81be 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -23,7 +23,7 @@ ABI Encoding and Decoding Functions - ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)``: :ref:`ABI `-encodes the given arguments starting from the second and prepends the given four-byte selector - ``abi.encodeCall(function functionPointer, (...)) returns (bytes memory)``: ABI-encodes a call to ``functionPointer`` with the arguments found in the - tuple. Performs a full type-check, ensuring the types match the function signature. Result equals ``abi.encodeWithSelector(functionPointer.selector, (...))`` + tuple. Performs a full type-check, ensuring the types match the function signature. Result equals ``abi.encodeWithSelector(functionPointer.selector, ...)`` - ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)`` From 2f5f6b9fb8e888a52c2f6042609df628824a1c96 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 29 Apr 2024 17:50:07 +0200 Subject: [PATCH 0086/1340] Replace yarn with pnpm in the external tests since yarn seems to be unable to resolve Hardhat dependencies --- test/externalTests/brink.sh | 4 ++-- test/externalTests/ens.sh | 2 +- test/externalTests/uniswap.sh | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/externalTests/brink.sh b/test/externalTests/brink.sh index d8ad001ac..02e5fe971 100755 --- a/test/externalTests/brink.sh +++ b/test/externalTests/brink.sh @@ -68,8 +68,8 @@ function brink_test neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" "$CURRENT_EVM_VERSION" "$extra_settings" "$extra_optimizer_settings" - yarn install - yarn add hardhat-gas-reporter + pnpm install + pnpm install hardhat-gas-reporter replace_version_pragmas for preset in $SELECTED_PRESETS; do diff --git a/test/externalTests/ens.sh b/test/externalTests/ens.sh index a011dd2a7..b7a053f6f 100755 --- a/test/externalTests/ens.sh +++ b/test/externalTests/ens.sh @@ -62,7 +62,7 @@ function ens_test neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" - yarn install + pnpm install replace_version_pragmas neutralize_packaged_contracts diff --git a/test/externalTests/uniswap.sh b/test/externalTests/uniswap.sh index 04f27ab3f..f3d78e6e3 100755 --- a/test/externalTests/uniswap.sh +++ b/test/externalTests/uniswap.sh @@ -83,17 +83,17 @@ function uniswap_test # - Newer versions of ethereumjs/tx have an issue with 'gteHardfork()' method. neutralize_package_lock - yarn install - yarn add hardhat-gas-reporter + pnpm install + pnpm install hardhat-gas-reporter # With ethers.js 5.6.2 many tests for revert messages fail. # TODO: Remove when https://github.com/ethers-io/ethers.js/discussions/2849 is resolved. - yarn add ethers@5.6.1 + pnpm install ethers@5.6.1 # We set hardhat version to 2.20.0 since version 2.21.0 has issues with solidity-coverage plugin # that often causes out-of-memory errors. # See hardhat note about the issue here: https://github.com/NomicFoundation/hardhat/releases/tag/hardhat@2.21.0 - yarn add hardhat@2.20.0 + pnpm install hardhat@2.20.0 replace_version_pragmas From 3794bc1825d51f5927b3d99305f3ea97232ec55b Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 29 Apr 2024 17:47:21 +0200 Subject: [PATCH 0087/1340] Remove perpetual-pools external test --- .circleci/config.yml | 9 --- test/externalTests/perpetual-pools.sh | 87 --------------------------- 2 files changed, 96 deletions(-) delete mode 100755 test/externalTests/perpetual-pools.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index b5b151c58..34e2e3393 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -789,13 +789,6 @@ defaults: compile_only: 1 image: cimg/node:18.16 - - job_native_test_ext_perpetual_pools: &job_native_test_ext_perpetual_pools - <<: *requires_b_ubu_static - name: t_native_test_ext_perpetual_pools - project: perpetual-pools - binary_type: native - image: cimg/node:18.16 - - job_native_test_ext_uniswap: &job_native_test_ext_uniswap <<: *requires_b_ubu_static name: t_native_test_ext_uniswap @@ -1881,7 +1874,6 @@ workflows: - t_ext: *job_native_test_ext_zeppelin - t_ext: *job_native_test_ext_ens - t_ext: *job_native_test_ext_yield_liquidator - - t_ext: *job_native_test_ext_perpetual_pools - t_ext: *job_native_test_ext_uniswap - t_ext: *job_native_test_ext_prb_math - t_ext: *job_native_test_ext_elementfi @@ -1903,7 +1895,6 @@ workflows: - t_native_test_ext_zeppelin - t_native_test_ext_ens - t_native_test_ext_yield_liquidator - - t_native_test_ext_perpetual_pools - t_native_test_ext_uniswap - t_native_test_ext_elementfi - t_native_test_ext_brink diff --git a/test/externalTests/perpetual-pools.sh b/test/externalTests/perpetual-pools.sh deleted file mode 100755 index 1d7bb8f33..000000000 --- a/test/externalTests/perpetual-pools.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env bash - -# ------------------------------------------------------------------------------ -# 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 -# -# (c) 2022 solidity contributors. -#------------------------------------------------------------------------------ - -set -e - -source scripts/common.sh -source scripts/externalTests/common.sh - -REPO_ROOT=$(realpath "$(dirname "$0")/../..") - -verify_input "$@" -BINARY_TYPE="$1" -BINARY_PATH="$(realpath "$2")" -SELECTED_PRESETS="$3" - -function compile_fn { yarn build; } -function test_fn { yarn test; } - -function perpetual_pools_test -{ - local repo="https://github.com/solidity-external-tests/perpetual-pools-contracts" - local ref=pools-v2 - local config_file="hardhat.config.ts" - local config_var="config" - - local compile_only_presets=() - local settings_presets=( - "${compile_only_presets[@]}" - ir-no-optimize - ir-optimize-evm-only - ir-optimize-evm+yul - legacy-no-optimize - legacy-optimize-evm-only - legacy-optimize-evm+yul - ) - - [[ $SELECTED_PRESETS != "" ]] || SELECTED_PRESETS=$(circleci_select_steps_multiarg "${settings_presets[@]}") - print_presets_or_exit "$SELECTED_PRESETS" - - setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" - download_project "$repo" "$ref" "$DIR" - - # Disable tests that won't pass on the ir presets due to Hardhat heuristics. Note that this also disables - # them for other presets but that's fine - we want same code run for benchmarks to be comparable. - # TODO: Remove this when Hardhat adjusts heuristics for IR (https://github.com/nomiclabs/hardhat/issues/3365). - sed -i 's|\(it\)\(("Should not allow commits that are too large"\)|\1.skip\2|g' test/PoolCommitter/commit.spec.ts - sed -i 's|\(it\)\(("Should not allow for too many commitments (that bring amount over a user'\''s balance)"\)|\1.skip\2|g' test/PoolCommitter/commit.spec.ts - - neutralize_package_lock - neutralize_package_json_hooks - force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" - force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" - force_hardhat_unlimited_contract_size "$config_file" "$config_var" - - yarn install - # We set hardhat version to 2.20.0 since version 2.21.0 has issues with solidity-coverage plugin - # that often causes out-of-memory errors. - # See hardhat note about the issue here: https://github.com/NomicFoundation/hardhat/releases/tag/hardhat@2.21.0 - yarn add hardhat@2.20.0 - - replace_version_pragmas - - for preset in $SELECTED_PRESETS; do - hardhat_run_test "$config_file" "$preset" "${compile_only_presets[*]}" compile_fn test_fn "$config_var" - store_benchmark_report hardhat perpetual-pools "$repo" "$preset" - done -} - -external_test Tracer-Perpetual-Pools perpetual_pools_test From 007205a27493e11e3a49943f51f0bc3b30e43a2a Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 30 Apr 2024 10:14:30 +0200 Subject: [PATCH 0088/1340] Order `Instructions.h` by opcodes TLOAD/TSTORE was out of order --- libevmasm/Instruction.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index f89c72c89..a3629eec2 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -104,10 +104,9 @@ enum class Instruction: uint8_t MSIZE, ///< get the size of active memory GAS, ///< get the amount of available gas JUMPDEST, ///< set a potential jump destination - MCOPY = 0x5e, ///< copy between memory areas - TLOAD = 0x5c, ///< load word from transient storage TSTORE = 0x5d, ///< save word to transient storage + MCOPY = 0x5e, ///< copy between memory areas PUSH0 = 0x5f, ///< place the value 0 on stack PUSH1 = 0x60, ///< place 1 byte item on stack From 7fb62227cf53bd44199efe80165f369cb22a7498 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 13 Mar 2024 14:12:25 +0100 Subject: [PATCH 0089/1340] SMTChecker: First version of SMTLIB2 parser Parser code was originally written by @chriseth for solsmt, an SMT solver developed internally for Solidity --- libsmtutil/CMakeLists.txt | 2 + libsmtutil/SMTLib2Parser.cpp | 97 ++++++++++++++++++++++++++++++++++++ libsmtutil/SMTLib2Parser.h | 96 +++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 libsmtutil/SMTLib2Parser.cpp create mode 100644 libsmtutil/SMTLib2Parser.h diff --git a/libsmtutil/CMakeLists.txt b/libsmtutil/CMakeLists.txt index af7f47b60..cb222e22c 100644 --- a/libsmtutil/CMakeLists.txt +++ b/libsmtutil/CMakeLists.txt @@ -4,6 +4,8 @@ set(sources Exceptions.h SMTLib2Interface.cpp SMTLib2Interface.h + SMTLib2Parser.cpp + SMTLib2Parser.h SMTPortfolio.cpp SMTPortfolio.h SolverInterface.h diff --git a/libsmtutil/SMTLib2Parser.cpp b/libsmtutil/SMTLib2Parser.cpp new file mode 100644 index 000000000..f3a3bd96a --- /dev/null +++ b/libsmtutil/SMTLib2Parser.cpp @@ -0,0 +1,97 @@ +/* + 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 + +#include + +#include + +#include +#include + + +using namespace solidity::langutil; +using namespace solidity::smtutil; + +std::string SMTLib2Expression::toString() const { + return std::visit(solidity::util::GenericVisitor{ + [](std::string const& _sv) { return _sv; }, + [](std::vector const& _subExpr) { + std::vector formatted; + for (auto const& item: _subExpr) + formatted.emplace_back(item.toString()); + return "(" + solidity::util::joinHumanReadable(formatted, " ") + ")"; + } + }, data); +} + +SMTLib2Expression SMTLib2Parser::parseExpression() { + skipWhitespace(); + if (token() == '(') + { + advance(); + skipWhitespace(); + std::vector subExpressions; + while (token() != 0 && token() != ')') + { + subExpressions.emplace_back(parseExpression()); + skipWhitespace(); + } + if (token() != ')') + throw ParsingException{}; + // Simulate whitespace because we do not want to read the next token since it might block. + m_token = ' '; + return {std::move(subExpressions)}; + } else + return {parseToken()}; +} + +std::string SMTLib2Parser::parseToken() { + std::string result; + + skipWhitespace(); + bool isPipe = token() == '|'; + if (isPipe) + advance(); + while (token() != 0) + { + char c = token(); + if (isPipe && c == '|') + { + advance(); + break; + } else if (!isPipe && (isWhiteSpace(c) || c == '(' || c == ')')) + break; + result.push_back(c); + advance(); + } + return result; +} + +void SMTLib2Parser::advance() { + if (!m_input.good()) + throw ParsingException{}; + m_token = static_cast(m_input.get()); + if (token() == ';') + while (token() != '\n' && token() != 0) + m_token = static_cast(m_input.get()); +} + +void SMTLib2Parser::skipWhitespace() { + while (isWhiteSpace(token())) + advance(); +} diff --git a/libsmtutil/SMTLib2Parser.h b/libsmtutil/SMTLib2Parser.h new file mode 100644 index 000000000..48eb76a13 --- /dev/null +++ b/libsmtutil/SMTLib2Parser.h @@ -0,0 +1,96 @@ +/* + 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 + +#pragma once + +#include + +#include +#include +#include +#include + +/** + * The following is a parser for SMT-LIB2 expressions developed originally by @chriseth as part of solsmt. + */ + +namespace solidity::smtutil +{ + +struct SMTLib2Expression { + using args_t = std::vector; + std::variant data; + + [[nodiscard]] std::string toString() const; +}; + +inline bool isAtom(SMTLib2Expression const& expr) +{ + return std::holds_alternative(expr.data); +} + +inline std::string const& asAtom(SMTLib2Expression const& expr) +{ + smtAssert(isAtom(expr)); + return std::get(expr.data); +} + +inline auto const& asSubExpressions(SMTLib2Expression const& expr) +{ + smtAssert(!isAtom(expr)); + return std::get(expr.data); +} + +inline auto& asSubExpressions(SMTLib2Expression& expr) +{ + smtAssert(!isAtom(expr)); + return std::get(expr.data); +} + +class SMTLib2Parser { +public: + class ParsingException {}; + + explicit SMTLib2Parser(std::istream& _input) : + m_input(_input), + m_token(static_cast(m_input.get())) {} + + SMTLib2Expression parseExpression(); + + bool isEOF() + { + skipWhitespace(); + return m_input.eof(); + } + +private: + std::string parseToken(); + + void skipWhitespace(); + + [[nodiscard]] char token() const + { + return m_token; + } + + void advance(); + + std::istream& m_input; + char m_token = 0; +}; +} From eb118198169796ea3c5b40999a72d7513942da3e Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 13 Mar 2024 19:37:46 +0100 Subject: [PATCH 0090/1340] SMTChecker: Instruct Eldarica to produce invariants if requested --- libsolidity/interface/CompilerStack.cpp | 2 +- libsolidity/interface/SMTSolverCommand.cpp | 4 +++- libsolidity/interface/SMTSolverCommand.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 514f3a554..2d1fd1074 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -659,7 +659,7 @@ bool CompilerStack::analyzeLegacy(bool _noErrorsSoFar) m_modelCheckerSettings.solvers = ModelChecker::checkRequestedSolvers(m_modelCheckerSettings.solvers, m_errorReporter); if (auto* universalCallback = m_readFile.target()) if (m_modelCheckerSettings.solvers.eld) - universalCallback->smtCommand().setEldarica(m_modelCheckerSettings.timeout); + universalCallback->smtCommand().setEldarica(m_modelCheckerSettings.timeout, m_modelCheckerSettings.invariants != ModelCheckerInvariants::None()); } ModelChecker modelChecker(m_errorReporter, *this, m_smtlib2Responses, m_modelCheckerSettings, m_readFile); diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index 8ef36cb75..7d814cd9c 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -37,7 +37,7 @@ using solidity::util::errinfo_comment; namespace solidity::frontend { -void SMTSolverCommand::setEldarica(std::optional timeoutInMilliseconds) +void SMTSolverCommand::setEldarica(std::optional timeoutInMilliseconds, bool computeInvariants) { m_arguments.clear(); m_solverCmd = "eld"; @@ -47,6 +47,8 @@ void SMTSolverCommand::setEldarica(std::optional timeoutInMillisec timeoutInSeconds = timeoutInSeconds == 0 ? 1 : timeoutInSeconds; m_arguments.push_back("-t:" + std::to_string(timeoutInSeconds)); } + if (computeInvariants) + m_arguments.emplace_back("-ssol"); } ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::string const& _query) diff --git a/libsolidity/interface/SMTSolverCommand.h b/libsolidity/interface/SMTSolverCommand.h index 1d1201e49..665c19c1b 100644 --- a/libsolidity/interface/SMTSolverCommand.h +++ b/libsolidity/interface/SMTSolverCommand.h @@ -36,7 +36,7 @@ class SMTSolverCommand return [this](std::string const& _kind, std::string const& _query) { return solve(_kind, _query); }; } - void setEldarica(std::optional timeoutInMilliseconds); + void setEldarica(std::optional timeoutInMilliseconds, bool computeInvariants); private: /// The name of the solver's binary. From 1fcaec5ddce3dc45fd62867a21cd9d97b7ff4db9 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Tue, 16 Apr 2024 13:24:19 +0200 Subject: [PATCH 0091/1340] SMTChecker: Remember sorts already in SMTLibInterface --- libsmtutil/CHCSmtLib2Interface.cpp | 20 +++++++------------- libsmtutil/CHCSmtLib2Interface.h | 6 +++--- libsmtutil/SMTLib2Interface.cpp | 30 +++++++++++++++++++----------- libsmtutil/SMTLib2Interface.h | 9 ++++++++- 4 files changed, 37 insertions(+), 28 deletions(-) diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index ac906e301..7e643abac 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -56,7 +56,7 @@ void CHCSmtLib2Interface::reset() m_accumulatedOutput.clear(); m_variables.clear(); m_unhandledQueries.clear(); - m_sortNames.clear(); + m_smtlib2->reset(); } void CHCSmtLib2Interface::registerRelation(Expression const& _expr) @@ -115,24 +115,18 @@ void CHCSmtLib2Interface::declareVariable(std::string const& _name, SortPointer else if (!m_variables.count(_name)) { m_variables.insert(_name); - write("(declare-var |" + _name + "| " + toSmtLibSort(*_sort) + ')'); + write("(declare-var |" + _name + "| " + toSmtLibSort(_sort) + ')'); } } -std::string CHCSmtLib2Interface::toSmtLibSort(Sort const& _sort) +std::string CHCSmtLib2Interface::toSmtLibSort(SortPointer _sort) { - if (!m_sortNames.count(&_sort)) - m_sortNames[&_sort] = m_smtlib2->toSmtLibSort(_sort); - return m_sortNames.at(&_sort); + return m_smtlib2->toSmtLibSort(_sort); } std::string CHCSmtLib2Interface::toSmtLibSort(std::vector const& _sorts) { - std::string ssort("("); - for (auto const& sort: _sorts) - ssort += toSmtLibSort(*sort) + " "; - ssort += ")"; - return ssort; + return m_smtlib2->toSmtLibSort(_sorts); } std::string CHCSmtLib2Interface::forall() @@ -142,7 +136,7 @@ std::string CHCSmtLib2Interface::forall() { solAssert(sort, ""); if (sort->kind != Kind::Function) - vars += " (" + name + " " + toSmtLibSort(*sort) + ")"; + vars += " (" + name + " " + toSmtLibSort(sort) + ")"; } vars += ")"; return vars; @@ -158,7 +152,7 @@ void CHCSmtLib2Interface::declareFunction(std::string const& _name, SortPointer auto fSort = std::dynamic_pointer_cast(_sort); smtAssert(fSort->codomain); std::string domain = toSmtLibSort(fSort->domain); - std::string codomain = toSmtLibSort(*fSort->codomain); + std::string codomain = toSmtLibSort(fSort->codomain); m_variables.insert(_name); write( "(declare-fun |" + diff --git a/libsmtutil/CHCSmtLib2Interface.h b/libsmtutil/CHCSmtLib2Interface.h index 0f3a68ee4..b133c485e 100644 --- a/libsmtutil/CHCSmtLib2Interface.h +++ b/libsmtutil/CHCSmtLib2Interface.h @@ -57,8 +57,10 @@ class CHCSmtLib2Interface: public CHCSolverInterface SMTLib2Interface* smtlib2Interface() const { return m_smtlib2.get(); } + auto const& sortNames() const { return m_smtlib2->sortNames(); } + private: - std::string toSmtLibSort(Sort const& _sort); + std::string toSmtLibSort(SortPointer _sort); std::string toSmtLibSort(std::vector const& _sort); void writeHeader(); @@ -85,8 +87,6 @@ class CHCSmtLib2Interface: public CHCSolverInterface frontend::ReadCallback::Callback m_smtCallback; SMTSolverChoice m_enabledSolvers; - - std::map m_sortNames; }; } diff --git a/libsmtutil/SMTLib2Interface.cpp b/libsmtutil/SMTLib2Interface.cpp index ac5645bf1..12469a4ae 100644 --- a/libsmtutil/SMTLib2Interface.cpp +++ b/libsmtutil/SMTLib2Interface.cpp @@ -56,6 +56,7 @@ void SMTLib2Interface::reset() m_accumulatedOutput.emplace_back(); m_variables.clear(); m_userSorts.clear(); + m_sortNames.clear(); write("(set-option :produce-models true)"); if (m_queryTimeout) write("(set-option :timeout " + std::to_string(*m_queryTimeout) + ")"); @@ -81,7 +82,7 @@ void SMTLib2Interface::declareVariable(std::string const& _name, SortPointer con else if (!m_variables.count(_name)) { m_variables.emplace(_name, _sort); - write("(declare-fun |" + _name + "| () " + toSmtLibSort(*_sort) + ')'); + write("(declare-fun |" + _name + "| () " + toSmtLibSort(_sort) + ')'); } } @@ -94,7 +95,7 @@ void SMTLib2Interface::declareFunction(std::string const& _name, SortPointer con { auto const& fSort = std::dynamic_pointer_cast(_sort); std::string domain = toSmtLibSort(fSort->domain); - std::string codomain = toSmtLibSort(*fSort->codomain); + std::string codomain = toSmtLibSort(fSort->codomain); m_variables.emplace(_name, _sort); write( "(declare-fun |" + @@ -183,7 +184,7 @@ std::string SMTLib2Interface::toSExpr(Expression const& _expr) smtAssert(sortSort, ""); auto arraySort = std::dynamic_pointer_cast(sortSort->inner); smtAssert(arraySort, ""); - sexpr += "(as const " + toSmtLibSort(*arraySort) + ") "; + sexpr += "(as const " + toSmtLibSort(arraySort) + ") "; sexpr += toSExpr(_expr.arguments.at(1)); } else if (_expr.name == "tuple_get") @@ -212,25 +213,32 @@ std::string SMTLib2Interface::toSExpr(Expression const& _expr) return sexpr; } -std::string SMTLib2Interface::toSmtLibSort(Sort const& _sort) +std::string SMTLib2Interface::toSmtLibSort(solidity::smtutil::SortPointer _sort) { - switch (_sort.kind) + if (!m_sortNames.count(_sort)) + m_sortNames[_sort] = toSmtLibSortInternal(_sort); + return m_sortNames.at(_sort); +} + +std::string SMTLib2Interface::toSmtLibSortInternal(SortPointer _sort) +{ + switch (_sort->kind) { case Kind::Int: return "Int"; case Kind::Bool: return "Bool"; case Kind::BitVector: - return "(_ BitVec " + std::to_string(dynamic_cast(_sort).size) + ")"; + return "(_ BitVec " + std::to_string(dynamic_cast(*_sort).size) + ")"; case Kind::Array: { - auto const& arraySort = dynamic_cast(_sort); + auto const& arraySort = dynamic_cast(*_sort); smtAssert(arraySort.domain && arraySort.range, ""); - return "(Array " + toSmtLibSort(*arraySort.domain) + ' ' + toSmtLibSort(*arraySort.range) + ')'; + return "(Array " + toSmtLibSort(arraySort.domain) + ' ' + toSmtLibSort(arraySort.range) + ')'; } case Kind::Tuple: { - auto const& tupleSort = dynamic_cast(_sort); + auto const& tupleSort = dynamic_cast(*_sort); std::string tupleName = "|" + tupleSort.name + "|"; auto isName = [&](auto entry) { return entry.first == tupleName; }; if (ranges::find_if(m_userSorts, isName) == m_userSorts.end()) @@ -238,7 +246,7 @@ std::string SMTLib2Interface::toSmtLibSort(Sort const& _sort) std::string decl("(declare-datatypes ((" + tupleName + " 0)) (((" + tupleName); smtAssert(tupleSort.members.size() == tupleSort.components.size(), ""); for (unsigned i = 0; i < tupleSort.members.size(); ++i) - decl += " (|" + tupleSort.members.at(i) + "| " + toSmtLibSort(*tupleSort.components.at(i)) + ")"; + decl += " (|" + tupleSort.members.at(i) + "| " + toSmtLibSort(tupleSort.components.at(i)) + ")"; decl += "))))"; m_userSorts.emplace_back(tupleName, decl); write(decl); @@ -255,7 +263,7 @@ std::string SMTLib2Interface::toSmtLibSort(std::vector const& _sort { std::string ssort("("); for (auto const& sort: _sorts) - ssort += toSmtLibSort(*sort) + " "; + ssort += toSmtLibSort(sort) + " "; ssort += ")"; return ssort; } diff --git a/libsmtutil/SMTLib2Interface.h b/libsmtutil/SMTLib2Interface.h index 9ef8e94a8..fbfde664d 100644 --- a/libsmtutil/SMTLib2Interface.h +++ b/libsmtutil/SMTLib2Interface.h @@ -61,12 +61,13 @@ class SMTLib2Interface: public SolverInterface // Used by CHCSmtLib2Interface std::string toSExpr(Expression const& _expr); - std::string toSmtLibSort(Sort const& _sort); + std::string toSmtLibSort(SortPointer _sort); std::string toSmtLibSort(std::vector const& _sort); std::map variables() { return m_variables; } std::vector> const& userSorts() const { return m_userSorts; } + std::map const& sortNames() const { return m_sortNames; } std::string dumpQuery(std::vector const& _expressionsToEvaluate); @@ -81,6 +82,8 @@ class SMTLib2Interface: public SolverInterface /// Communicates with the solver via the callback. Throws SMTSolverError on error. std::string querySolver(std::string const& _input); + std::string toSmtLibSortInternal(SortPointer _sort); + std::vector m_accumulatedOutput; std::map m_variables; @@ -90,6 +93,10 @@ class SMTLib2Interface: public SolverInterface /// otherwise solvers cannot parse the queries. std::vector> m_userSorts; + /// Maps a user sort to SMT-LIB2 sort. + /// Remembers all declared sorts and is used as a cache as well. + std::map m_sortNames; + std::map m_queryResponses; std::vector m_unhandledQueries; From 384f005071afe0da2e209246ee74bc20ed2cdc89 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Tue, 16 Apr 2024 13:52:22 +0200 Subject: [PATCH 0092/1340] SMTChecker: Support retrieving invariants from Eldarica We add support for parsing CHC solver response containing a model, i.e., invariants. We utilise our SMT parser to build S-expression representation which we then interpret using the context we remembered while building the query. We have to rememeber all predicates declared to the solver, and, consequently, all sorts we have declared to the solver. --- libsmtutil/CHCSmtLib2Interface.cpp | 284 ++++++++++++++++++++++++++++- libsmtutil/CHCSmtLib2Interface.h | 3 + 2 files changed, 286 insertions(+), 1 deletion(-) diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index 7e643abac..671ec9b51 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -18,11 +18,17 @@ #include +#include + #include +#include +#include #include #include +#include +#include #include #include @@ -96,7 +102,10 @@ std::tuple CHCSmtLib2Inte CheckResult result; // TODO proper parsing if (boost::starts_with(response, "sat")) - result = CheckResult::UNSATISFIABLE; + { + auto maybeInvariants = invariantsFromSolverResponse(response); + return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; + } else if (boost::starts_with(response, "unsat")) result = CheckResult::SATISFIABLE; else if (boost::starts_with(response, "unknown")) @@ -217,3 +226,276 @@ std::string CHCSmtLib2Interface::createHeaderAndDeclarations() { std::string CHCSmtLib2Interface::createQueryAssertion(std::string name) { return "(assert\n(forall " + forall() + "\n" + "(=> " + name + " false)))"; } + +class SMTLibTranslationContext +{ + CHCSmtLib2Interface const& m_chcInterface; + std::map m_knownVariables; + + static bool isNumber(std::string const& _expr) + { + return ranges::all_of(_expr, [](char c) { return isDigit(c) || c == '.'; }); + } + + +public: + explicit SMTLibTranslationContext(CHCSmtLib2Interface const& _chcInterface) : m_chcInterface(_chcInterface) + { + // fill user defined sorts and constructors + auto const& userSorts = m_chcInterface.smtlib2Interface()->userSorts(); + for (auto const& declaration: userSorts | ranges::views::values) + { + std::stringstream ss(declaration); + SMTLib2Parser parser(ss); + auto expr = parser.parseExpression(); + smtAssert(parser.isEOF()); + smtAssert(!isAtom(expr)); + auto const& args = asSubExpressions(expr); + smtAssert(args.size() == 3); + smtAssert(isAtom(args[0]) && asAtom(args[0]) == "declare-datatypes"); + // args[1] is the name of the type + // args[2] is the constructor with the members + smtAssert(!isAtom(args[2]) && asSubExpressions(args[2]).size() == 1 && !isAtom(asSubExpressions(args[2])[0])); + auto const& constructors = asSubExpressions(asSubExpressions(args[2])[0]); + smtAssert(constructors.size() == 1); + auto const& constructor = constructors[0]; + // constructor is a list: name + members + smtAssert(!isAtom(constructor)); + auto const& constructorArgs = asSubExpressions(constructor); + for (unsigned i = 1u; i < constructorArgs.size(); ++i) + { + auto const& carg = constructorArgs[i]; + smtAssert(!isAtom(carg) && asSubExpressions(carg).size() == 2); + auto const& nameSortPair = asSubExpressions(carg); + m_knownVariables.emplace(asAtom(nameSortPair[0]), toSort(nameSortPair[1])); + } + } + } + + void addVariableDeclaration(std::string name, SortPointer sort) + { + smtAssert(m_knownVariables.find(name) == m_knownVariables.end()); + m_knownVariables.emplace(std::move(name), std::move(sort)); + } + + std::optional lookupKnownTupleSort(std::string const& name) { + auto const& userSorts = m_chcInterface.sortNames(); + std::string quotedName = "|" + name + "|"; + auto it = ranges::find_if(userSorts, [&](auto const& entry) { return entry.second == quotedName; }); + if (it != userSorts.end() && it->first->kind == Kind::Tuple) + { + auto tupleSort = std::dynamic_pointer_cast(it->first); + smtAssert(tupleSort); + return tupleSort; + } + return {}; + } + + SortPointer toSort(SMTLib2Expression const& expr) + { + if (isAtom(expr)) + { + auto const& name = asAtom(expr); + if (name == "Int") + return SortProvider::sintSort; + if (name == "Bool") + return SortProvider::boolSort; + auto tupleSort = lookupKnownTupleSort(name); + if (tupleSort) + return tupleSort.value(); + } else { + auto const& args = asSubExpressions(expr); + if (asAtom(args[0]) == "Array") + { + smtAssert(args.size() == 3); + auto domainSort = toSort(args[1]); + auto codomainSort = toSort(args[2]); + return std::make_shared(std::move(domainSort), std::move(codomainSort)); + } + if (args.size() == 3 && isAtom(args[0]) && asAtom(args[0]) == "_" && isAtom(args[1]) && asAtom(args[1]) == "int2bv") + return std::make_shared(std::stoul(asAtom(args[2]))); + } + smtAssert(false, "Unknown sort encountered"); + } + + smtutil::Expression parseQuantifier( + std::string const& quantifierName, + std::vector const& varList, + SMTLib2Expression const& coreExpression + ) + { + std::vector> boundVariables; + for (auto const& sortedVar: varList) + { + smtAssert(!isAtom(sortedVar)); + auto varSortPair = asSubExpressions(sortedVar); + smtAssert(varSortPair.size() == 2); + boundVariables.emplace_back(asAtom(varSortPair[0]), toSort(varSortPair[1])); + } + for (auto const& [var, sort] : boundVariables) + { + smtAssert(m_knownVariables.find(var) == m_knownVariables.end()); // TODO: deal with shadowing? + m_knownVariables.emplace(var, sort); + } + auto core = toSMTUtilExpression(coreExpression); + for (auto const& [var, sort] : boundVariables) + { + smtAssert(m_knownVariables.find(var) != m_knownVariables.end()); + m_knownVariables.erase(var); + } + return Expression(quantifierName, {core}, SortProvider::boolSort); // TODO: what about the bound variables? + + } + + smtutil::Expression toSMTUtilExpression(SMTLib2Expression const& _expr) + { + return std::visit( + GenericVisitor{ + [&](std::string const& _atom) + { + if (_atom == "true" || _atom == "false") + return smtutil::Expression(_atom == "true"); + else if (isNumber(_atom)) + return smtutil::Expression(_atom, {}, SortProvider::sintSort); + else if (auto it = m_knownVariables.find(_atom); it != m_knownVariables.end()) + return smtutil::Expression(_atom, {}, it->second); + else // assume this is a predicate with sort bool; TODO: Context should be aware of predicates! + return smtutil::Expression(_atom, {}, SortProvider::boolSort); + }, + [&](std::vector const& _subExpr) + { + SortPointer sort; + std::vector arguments; + if (isAtom(_subExpr.front())) + { + std::string const& op = asAtom(_subExpr.front()); + if (op == "!") + { + // named term, we ignore the name + smtAssert(_subExpr.size() > 2); + return toSMTUtilExpression(_subExpr[1]); + } + if (op == "exists" || op == "forall") + { + smtAssert(_subExpr.size() == 3); + smtAssert(!isAtom(_subExpr[1])); + return parseQuantifier(op, asSubExpressions(_subExpr[1]), _subExpr[2]); + } + for (size_t i = 1; i < _subExpr.size(); i++) + arguments.emplace_back(toSMTUtilExpression(_subExpr[i])); + if (auto tupleSort = lookupKnownTupleSort(op); tupleSort) + { + auto sortSort = std::make_shared(tupleSort.value()); + return Expression::tuple_constructor(Expression(sortSort), arguments); + } + if (auto it = m_knownVariables.find(op); it != m_knownVariables.end()) + return smtutil::Expression(op, std::move(arguments), it->second); + else + { + std::set + boolOperators{"and", "or", "not", "=", "<", ">", "<=", ">=", "=>"}; + sort = contains(boolOperators, op) ? SortProvider::boolSort : arguments.back().sort; + return smtutil::Expression(op, std::move(arguments), std::move(sort)); + } + smtAssert(false, "Unhandled case in expression conversion"); + } + else + { + // check for const array + if (_subExpr.size() == 2 and !isAtom(_subExpr[0])) + { + auto const& typeArgs = asSubExpressions(_subExpr.front()); + if (typeArgs.size() == 3 && typeArgs[0].toString() == "as" + && typeArgs[1].toString() == "const") + { + auto arraySort = toSort(typeArgs[2]); + auto sortSort = std::make_shared(arraySort); + return smtutil::Expression:: + const_array(Expression(sortSort), toSMTUtilExpression(_subExpr[1])); + } + if (typeArgs.size() == 3 && typeArgs[0].toString() == "_" + && typeArgs[1].toString() == "int2bv") + { + auto bvSort = std::dynamic_pointer_cast(toSort(_subExpr[0])); + smtAssert(bvSort); + return smtutil::Expression::int2bv(toSMTUtilExpression(_subExpr[1]), bvSort->size); + } + if (typeArgs.size() == 4 && typeArgs[0].toString() == "_" + && typeArgs[1].toString() == "extract") + return smtutil::Expression( + "extract", + {toSMTUtilExpression(typeArgs[2]), toSMTUtilExpression(typeArgs[3])}, + SortProvider::bitVectorSort // TODO: Compute bit size properly? + ); + } + smtAssert(false, "Unhandled case in expression conversion"); + } + } + }, + _expr.data + ); + } +}; + + +#define precondition(CONDITION) if (!(CONDITION)) return {} +std::optional CHCSmtLib2Interface::invariantsFromSolverResponse(std::string const& _response) const +{ + std::stringstream ss(_response); + std::string answer; + ss >> answer; + precondition(answer == "sat"); + SMTLib2Parser parser(ss); + precondition(!parser.isEOF()); // There has to be a model + std::vector parsedOutput; + try + { + while (!parser.isEOF()) + parsedOutput.push_back(parser.parseExpression()); + } + catch(SMTLib2Parser::ParsingException&) + { + return {}; + } + smtAssert(parser.isEOF()); + precondition(!parsedOutput.empty()); + auto& commands = parsedOutput.size() == 1 ? asSubExpressions(parsedOutput[0]) : parsedOutput; + std::vector definitions; + for (auto& command: commands) + { + auto& args = asSubExpressions(command); + precondition(args.size() == 5); + // args[0] = "define-fun" + // args[1] = predicate name + // args[2] = formal arguments of the predicate + // args[3] = return sort + // args[4] = body of the predicate's interpretation + precondition(isAtom(args[0]) && asAtom(args[0]) == "define-fun"); + precondition(isAtom(args[1])); + precondition(!isAtom(args[2])); + precondition(isAtom(args[3]) && asAtom(args[3]) == "Bool"); + auto& interpretation = args[4]; +// inlineLetExpressions(interpretation); + SMTLibTranslationContext context(*this); + auto const& formalArguments = asSubExpressions(args[2]); + std::vector predicateArgs; + for (auto const& formalArgument: formalArguments) + { + precondition(!isAtom(formalArgument)); + auto const& nameSortPair = asSubExpressions(formalArgument); + precondition(nameSortPair.size() == 2); + precondition(isAtom(nameSortPair[0])); + SortPointer varSort = context.toSort(nameSortPair[1]); + context.addVariableDeclaration(asAtom(nameSortPair[0]), varSort); + Expression arg = context.toSMTUtilExpression(nameSortPair[0]); + predicateArgs.push_back(arg); + } + + auto parsedInterpretation = context.toSMTUtilExpression(interpretation); + + Expression predicate(asAtom(args[1]), predicateArgs, SortProvider::boolSort); + definitions.push_back(predicate == parsedInterpretation); + } + return Expression::mkAnd(std::move(definitions)); +} +#undef precondition diff --git a/libsmtutil/CHCSmtLib2Interface.h b/libsmtutil/CHCSmtLib2Interface.h index b133c485e..f7f656fd0 100644 --- a/libsmtutil/CHCSmtLib2Interface.h +++ b/libsmtutil/CHCSmtLib2Interface.h @@ -76,6 +76,9 @@ class CHCSmtLib2Interface: public CHCSolverInterface /// Communicates with the solver via the callback. Throws SMTSolverError on error. std::string querySolver(std::string const& _input); + /// Translates CHC solver response with a model to our representation of invariants. Returns None on error. + std::optional invariantsFromSolverResponse(std::string const& response) const; + /// Used to access toSmtLibSort, SExpr, and handle variables. std::unique_ptr m_smtlib2; From 048ce0b19dc488ad10ac3eb1419f29edfb5e153b Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Tue, 16 Apr 2024 15:03:25 +0200 Subject: [PATCH 0093/1340] SMTChecker: Add command-line test for invariants from Eldarica --- .../model_checker_invariants_contract_eld/args | 1 + .../model_checker_invariants_contract_eld/err | 4 ++++ .../model_checker_invariants_contract_eld/input.sol | 8 ++++++++ 3 files changed, 13 insertions(+) create mode 100644 test/cmdlineTests/model_checker_invariants_contract_eld/args create mode 100644 test/cmdlineTests/model_checker_invariants_contract_eld/err create mode 100644 test/cmdlineTests/model_checker_invariants_contract_eld/input.sol diff --git a/test/cmdlineTests/model_checker_invariants_contract_eld/args b/test/cmdlineTests/model_checker_invariants_contract_eld/args new file mode 100644 index 000000000..7f2a13bfd --- /dev/null +++ b/test/cmdlineTests/model_checker_invariants_contract_eld/args @@ -0,0 +1 @@ +--model-checker-engine chc --model-checker-invariants contract --model-checker-solvers eld diff --git a/test/cmdlineTests/model_checker_invariants_contract_eld/err b/test/cmdlineTests/model_checker_invariants_contract_eld/err new file mode 100644 index 000000000..29c5a5bc8 --- /dev/null +++ b/test/cmdlineTests/model_checker_invariants_contract_eld/err @@ -0,0 +1,4 @@ +Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. + +Info: Contract invariant(s) for model_checker_invariants_contract_eld/input.sol:test: +(x = 0) diff --git a/test/cmdlineTests/model_checker_invariants_contract_eld/input.sol b/test/cmdlineTests/model_checker_invariants_contract_eld/input.sol new file mode 100644 index 000000000..4bee228bd --- /dev/null +++ b/test/cmdlineTests/model_checker_invariants_contract_eld/input.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract test { + uint x; + function f() public view { + assert(x < 10); + } +} From 87d86bfba64d8b88537a4a85c1d71f521986b614 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Tue, 20 Feb 2024 14:23:58 +0100 Subject: [PATCH 0094/1340] Replace internal JSON library jsoncpp with nlohmann::json. --- CMakeLists.txt | 10 +- Changelog.md | 2 + cmake/jsoncpp.cmake | 72 --- cmake/nlohmann-json.cmake | 21 + libevmasm/AbstractAssemblyStack.h | 2 +- libevmasm/Assembly.cpp | 117 ++-- libevmasm/Assembly.h | 11 +- libevmasm/EVMAssemblyStack.cpp | 6 +- libevmasm/EVMAssemblyStack.h | 4 +- libsolidity/ast/AST.h | 3 +- libsolidity/ast/ASTJsonExporter.cpp | 223 ++++--- libsolidity/ast/ASTJsonExporter.h | 46 +- libsolidity/ast/ASTJsonImporter.cpp | 402 ++++++------ libsolidity/ast/ASTJsonImporter.h | 154 ++--- libsolidity/codegen/ir/IRGenerationContext.h | 1 + libsolidity/codegen/ir/IRGenerator.cpp | 3 +- libsolidity/codegen/ir/IRGenerator.h | 4 +- .../experimental/codegen/IRGenerator.h | 2 +- libsolidity/formal/BMC.h | 1 + libsolidity/interface/ABI.cpp | 54 +- libsolidity/interface/ABI.h | 8 +- libsolidity/interface/CompilerStack.cpp | 86 ++- libsolidity/interface/CompilerStack.h | 49 +- libsolidity/interface/Natspec.cpp | 64 +- libsolidity/interface/Natspec.h | 14 +- libsolidity/interface/StandardCompiler.cpp | 611 +++++++++--------- libsolidity/interface/StandardCompiler.h | 20 +- libsolidity/interface/StorageLayout.cpp | 22 +- libsolidity/interface/StorageLayout.h | 9 +- libsolidity/lsp/DocumentHoverHandler.cpp | 6 +- libsolidity/lsp/DocumentHoverHandler.h | 2 +- libsolidity/lsp/GotoDefinition.cpp | 6 +- libsolidity/lsp/GotoDefinition.h | 2 +- libsolidity/lsp/HandlerBase.cpp | 11 +- libsolidity/lsp/HandlerBase.h | 6 +- libsolidity/lsp/LanguageServer.cpp | 273 ++++---- libsolidity/lsp/LanguageServer.h | 32 +- libsolidity/lsp/RenameSymbol.cpp | 18 +- libsolidity/lsp/RenameSymbol.h | 2 +- libsolidity/lsp/SemanticTokensBuilder.cpp | 16 +- libsolidity/lsp/SemanticTokensBuilder.h | 6 +- libsolidity/lsp/Transport.cpp | 29 +- libsolidity/lsp/Transport.h | 15 +- libsolidity/lsp/Utils.cpp | 20 +- libsolidity/lsp/Utils.h | 10 +- libsolutil/CMakeLists.txt | 2 +- libsolutil/Exceptions.h | 1 + libsolutil/JSON.cpp | 248 ++++--- libsolutil/JSON.h | 98 ++- libyul/AsmJsonConverter.cpp | 84 ++- libyul/AsmJsonConverter.h | 42 +- libyul/AsmJsonImporter.cpp | 98 +-- libyul/AsmJsonImporter.h | 48 +- libyul/Object.cpp | 14 +- libyul/Object.h | 8 +- libyul/YulStack.cpp | 2 +- libyul/YulStack.h | 5 +- libyul/backends/evm/StackLayoutGenerator.cpp | 2 +- solc/CommandLineInterface.cpp | 78 +-- solc/CommandLineInterface.h | 2 +- test/Metadata.cpp | 28 +- test/Metadata.h | 2 +- .../standard_import_with_comments/input.json | 95 +++ .../standard_import_with_comments/output.json | 97 +++ .../input.json | 85 +++ .../output.json | 97 +++ .../input.json | 29 + .../output.json | 12 + .../standard_non_utf8_filename/input.json | 17 + .../standard_non_utf8_filename/output.json | 12 + .../standard_non_utf8_filename2/input.json | 17 + .../standard_non_utf8_filename2/output.json | 12 + .../standard_raw_utf16_filename/input.json | Bin 0 -> 297 bytes .../standard_raw_utf16_filename/output.json | 12 + test/libevmasm/Assembler.cpp | 2 +- test/libsolidity/ASTPropertyTest.cpp | 36 +- test/libsolidity/ASTPropertyTest.h | 2 +- test/libsolidity/GasTest.cpp | 18 +- test/libsolidity/LibSolc.cpp | 32 +- test/libsolidity/Metadata.cpp | 56 +- test/libsolidity/NatspecJSONTest.cpp | 4 +- test/libsolidity/NatspecJSONTest.h | 2 +- test/libsolidity/SemanticTest.cpp | 2 +- test/libsolidity/StandardCompiler.cpp | 610 ++++++++--------- test/libsolidity/util/ContractABIUtils.cpp | 16 +- test/libsolidity/util/ContractABIUtils.h | 7 +- test/libsolidity/util/TestFunctionCall.cpp | 2 +- test/libsolidity/util/TestFunctionCall.h | 6 +- test/libsolutil/JSON.cpp | 278 ++++---- test/solc/CommandLineInterface.cpp | 11 +- test/tools/fuzzer_common.cpp | 18 +- .../tools/ossfuzz/SolidityEvmoneInterface.cpp | 6 +- test/tools/ossfuzz/SolidityEvmoneInterface.h | 4 +- test/yulPhaser/Program.cpp | 2 +- tools/yulPhaser/Program.cpp | 2 +- 95 files changed, 2734 insertions(+), 2104 deletions(-) delete mode 100644 cmake/jsoncpp.cmake create mode 100644 cmake/nlohmann-json.cmake create mode 100644 test/cmdlineTests/standard_import_with_comments/input.json create mode 100644 test/cmdlineTests/standard_import_with_comments/output.json create mode 100644 test/cmdlineTests/standard_import_with_comments_simple/input.json create mode 100644 test/cmdlineTests/standard_import_with_comments_simple/output.json create mode 100644 test/cmdlineTests/standard_import_with_invalid_utf8/input.json create mode 100644 test/cmdlineTests/standard_import_with_invalid_utf8/output.json create mode 100644 test/cmdlineTests/standard_non_utf8_filename/input.json create mode 100644 test/cmdlineTests/standard_non_utf8_filename/output.json create mode 100644 test/cmdlineTests/standard_non_utf8_filename2/input.json create mode 100644 test/cmdlineTests/standard_non_utf8_filename2/output.json create mode 100644 test/cmdlineTests/standard_raw_utf16_filename/input.json create mode 100644 test/cmdlineTests/standard_raw_utf16_filename/output.json diff --git a/CMakeLists.txt b/CMakeLists.txt index b9f2ddc36..3e2332b92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ option(PEDANTIC "Enable extra warnings and pedantic build flags. Treat all warni option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser steps." OFF) option(USE_SYSTEM_LIBRARIES "Use system libraries" OFF) option(ONLY_BUILD_SOLIDITY_LIBRARIES "Only build solidity libraries" OFF) -option(STRICT_JSONCPP_VERSION "Strictly check installed jsoncpp version" ON) +option(STRICT_NLOHMANN_JSON_VERSION "Strictly check installed nlohmann json version" ON) # Setup cccache. include(EthCcache) @@ -48,9 +48,8 @@ include(EthCcache) include(EthDependencies) if (NOT USE_SYSTEM_LIBRARIES) include(fmtlib) - include(jsoncpp) + include(nlohmann-json) include(range-v3) - include_directories(SYSTEM ${JSONCPP_INCLUDE_DIR}) endif() find_package(Threads) @@ -63,8 +62,8 @@ if (PROFILE_OPTIMIZER_STEPS) add_definitions(-DPROFILE_OPTIMIZER_STEPS) endif() -if (STRICT_JSONCPP_VERSION) - add_definitions(-DSTRICT_JSONCPP_VERSION_CHECK) +if (STRICT_NLOHMANN_JSON_VERSION) + add_definitions(-DSTRICT_NLOHMANN_JSON_VERSION_CHECK) endif() # Figure out what compiler and system are we using @@ -162,4 +161,3 @@ if (NOT ONLY_BUILD_SOLIDITY_LIBRARIES) add_subdirectory(test) endif() endif() - diff --git a/Changelog.md b/Changelog.md index c118e9f24..0f26cacfc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -32,6 +32,8 @@ Bugfixes: * SMTChecker: Fix internal error caused by not respecting the sign of an integer type when constructing zero-value SMT expressions. * SMTChecker: Run Eldarica only when explicitly requested with `--model-checker-solvers eld`, even when it is present on the system. +Build System: + * Replace internal JSON library jsoncpp with nlohmann::json. ### 0.8.24 (2024-01-25) diff --git a/cmake/jsoncpp.cmake b/cmake/jsoncpp.cmake deleted file mode 100644 index c47c2697a..000000000 --- a/cmake/jsoncpp.cmake +++ /dev/null @@ -1,72 +0,0 @@ -include(ExternalProject) - -if (${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten") - set(JSONCPP_CMAKE_COMMAND emcmake cmake) -else() - set(JSONCPP_CMAKE_COMMAND ${CMAKE_COMMAND}) -endif() - -set(prefix "${PROJECT_BINARY_DIR}/deps") -set(JSONCPP_LIBRARY "${prefix}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}jsoncpp${CMAKE_STATIC_LIBRARY_SUFFIX}") -set(JSONCPP_INCLUDE_DIR "${prefix}/include") - -# TODO: Investigate why this breaks some emscripten builds and -# check whether this can be removed after updating the emscripten -# versions used in the CI runs. -if(EMSCRIPTEN) - # Do not include all flags in CMAKE_CXX_FLAGS for emscripten, - # but only use -std=c++17. Using all flags causes build failures - # at the moment. - set(JSONCPP_CXX_FLAGS -std=c++17) -else() - # jsoncpp uses implicit casts for comparing integer and - # floating point numbers. This causes clang-10 (used by ossfuzz builder) - # to error on the implicit conversions. Here, we request jsoncpp - # to unconditionally use static casts for these conversions by defining the - # JSON_USE_INT64_DOUBLE_CONVERSION preprocessor macro. Doing so, - # not only gets rid of the implicit conversion error that clang-10 produces - # but also forces safer behavior in general. - set(JSONCPP_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DJSON_USE_INT64_DOUBLE_CONVERSION") -endif() - -set(byproducts "") -if(CMAKE_VERSION VERSION_GREATER 3.1) - set(byproducts BUILD_BYPRODUCTS "${JSONCPP_LIBRARY}") -endif() - -# Propagate CMAKE_MSVC_RUNTIME_LIBRARY on Windows builds, if set. -if (WIN32 AND POLICY CMP0091 AND CMAKE_MSVC_RUNTIME_LIBRARY) - list(APPEND JSONCPP_CMAKE_ARGS "-DCMAKE_POLICY_DEFAULT_CMP0091:STRING=NEW") - list(APPEND JSONCPP_CMAKE_ARGS "-DCMAKE_MSVC_RUNTIME_LIBRARY=${CMAKE_MSVC_RUNTIME_LIBRARY}") -endif() - -string(REPLACE ";" "$" CMAKE_OSX_ARCHITECTURES_ "${CMAKE_OSX_ARCHITECTURES}") -ExternalProject_Add(jsoncpp-project - PREFIX "${prefix}" - DOWNLOAD_DIR "${PROJECT_SOURCE_DIR}/deps/downloads" - DOWNLOAD_NAME jsoncpp-1.9.3.tar.gz - URL https://github.com/open-source-parsers/jsoncpp/archive/1.9.3.tar.gz - URL_HASH SHA256=8593c1d69e703563d94d8c12244e2e18893eeb9a8a9f8aa3d09a327aa45c8f7d - CMAKE_COMMAND ${JSONCPP_CMAKE_COMMAND} - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} - -DCMAKE_INSTALL_LIBDIR=lib - # Build static lib but suitable to be included in a shared lib. - -DCMAKE_POSITION_INDEPENDENT_CODE=${BUILD_SHARED_LIBS} - -DJSONCPP_WITH_EXAMPLE=OFF - -DJSONCPP_WITH_TESTS=OFF - -DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF - -DCMAKE_CXX_FLAGS=${JSONCPP_CXX_FLAGS} - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES_} - ${JSONCPP_CMAKE_ARGS} - ${byproducts} -) - -# Create jsoncpp imported library -add_library(jsoncpp STATIC IMPORTED) -file(MAKE_DIRECTORY ${JSONCPP_INCLUDE_DIR}) # Must exist. -set_property(TARGET jsoncpp PROPERTY IMPORTED_LOCATION ${JSONCPP_LIBRARY}) -set_property(TARGET jsoncpp PROPERTY INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${JSONCPP_INCLUDE_DIR}) -set_property(TARGET jsoncpp PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${JSONCPP_INCLUDE_DIR}) -add_dependencies(jsoncpp jsoncpp-project) diff --git a/cmake/nlohmann-json.cmake b/cmake/nlohmann-json.cmake new file mode 100644 index 000000000..02891e6a7 --- /dev/null +++ b/cmake/nlohmann-json.cmake @@ -0,0 +1,21 @@ +include(ExternalProject) + +ExternalProject_Add(nlohmann-json-project + DOWNLOAD_DIR "${CMAKE_SOURCE_DIR}/deps/nlohmann/nlohmann" + DOWNLOAD_NAME json.hpp + DOWNLOAD_NO_EXTRACT 1 + URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.hpp + URL_HASH SHA256=9bea4c8066ef4a1c206b2be5a36302f8926f7fdc6087af5d20b417d0cf103ea6 + CMAKE_COMMAND true + BUILD_COMMAND true + INSTALL_COMMAND true +) + +# Create nlohmann-json imported library +add_library(nlohmann-json INTERFACE IMPORTED) +file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/nlohmann) # Must exist. +set_target_properties(nlohmann-json PROPERTIES + INTERFACE_COMPILE_OPTIONS "\$<\$:/permissive->" + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/nlohmann + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/nlohmann) +add_dependencies(nlohmann-json nlohmann-json-project) \ No newline at end of file diff --git a/libevmasm/AbstractAssemblyStack.h b/libevmasm/AbstractAssemblyStack.h index 6be78cbc7..278edf5c2 100644 --- a/libevmasm/AbstractAssemblyStack.h +++ b/libevmasm/AbstractAssemblyStack.h @@ -40,7 +40,7 @@ class AbstractAssemblyStack virtual std::string const* sourceMapping(std::string const& _contractName) const = 0; virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const = 0; - virtual Json::Value assemblyJSON(std::string const& _contractName) const = 0; + virtual Json assemblyJSON(std::string const& _contractName) const = 0; virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const = 0; virtual std::string const filesystemFriendlyName(std::string const& _contractName) const = 0; diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 067e23034..356a2818a 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -80,10 +80,10 @@ unsigned Assembly::codeSize(unsigned subTagSize) const } } -void Assembly::importAssemblyItemsFromJSON(Json::Value const& _code, std::vector const& _sourceList) +void Assembly::importAssemblyItemsFromJSON(Json const& _code, std::vector const& _sourceList) { solAssert(m_items.empty()); - solRequire(_code.isArray(), AssemblyImportException, "Supplied JSON is not an array."); + solRequire(_code.is_array(), AssemblyImportException, "Supplied JSON is not an array."); for (auto jsonItemIter = std::begin(_code); jsonItemIter != std::end(_code); ++jsonItemIter) { AssemblyItem const& newItem = m_items.emplace_back(createAssemblyItemFromJSON(*jsonItemIter, _sourceList)); @@ -98,11 +98,11 @@ void Assembly::importAssemblyItemsFromJSON(Json::Value const& _code, std::vector } } -AssemblyItem Assembly::createAssemblyItemFromJSON(Json::Value const& _json, std::vector const& _sourceList) +AssemblyItem Assembly::createAssemblyItemFromJSON(Json const& _json, std::vector const& _sourceList) { - solRequire(_json.isObject(), AssemblyImportException, "Supplied JSON is not an object."); + solRequire(_json.is_object(), AssemblyImportException, "Supplied JSON is not an object."); static std::set const validMembers{"name", "begin", "end", "source", "value", "modifierDepth", "jumpType"}; - for (std::string const& member: _json.getMemberNames()) + for (auto const& [member, _]: _json.items()) solRequire( validMembers.count(member), AssemblyImportException, @@ -124,14 +124,14 @@ AssemblyItem Assembly::createAssemblyItemFromJSON(Json::Value const& _json, std: solRequire(!name.empty(), AssemblyImportException, "Member 'name' is empty."); SourceLocation location; - if (_json.isMember("begin")) + if (_json.contains("begin")) location.start = get(_json["begin"]); - if (_json.isMember("end")) + if (_json.contains("end")) location.end = get(_json["end"]); - int srcIndex = getOrDefault(_json["source"], -1); - size_t modifierDepth = static_cast(getOrDefault(_json["modifierDepth"], 0)); - std::string value = getOrDefault(_json["value"], ""); - std::string jumpType = getOrDefault(_json["jumpType"], ""); + int srcIndex = getOrDefault(_json, "source", -1); + size_t modifierDepth = static_cast(getOrDefault(_json, "modifierDepth", 0)); + std::string value = getOrDefault(_json, "value", ""); + std::string jumpType = getOrDefault(_json, "jumpType", ""); auto updateUsedTags = [&](u256 const& data) { @@ -429,11 +429,11 @@ std::string Assembly::assemblyString( return tmp.str(); } -Json::Value Assembly::assemblyJSON(std::map const& _sourceIndices, bool _includeSourceList) const +Json Assembly::assemblyJSON(std::map const& _sourceIndices, bool _includeSourceList) const { - Json::Value root; - root[".code"] = Json::arrayValue; - Json::Value& code = root[".code"]; + Json root; + root[".code"] = Json::array(); + Json& code = root[".code"]; for (AssemblyItem const& item: m_items) { int sourceIndex = -1; @@ -445,7 +445,7 @@ Json::Value Assembly::assemblyJSON(std::map const& _sourc } auto [name, data] = item.nameAndData(m_evmVersion); - Json::Value jsonItem; + Json jsonItem; jsonItem["name"] = name; jsonItem["begin"] = item.location().start; jsonItem["end"] = item.location().end; @@ -461,32 +461,32 @@ Json::Value Assembly::assemblyJSON(std::map const& _sourc if (!data.empty()) jsonItem["value"] = data; jsonItem["source"] = sourceIndex; - code.append(std::move(jsonItem)); + code.emplace_back(std::move(jsonItem)); if (item.type() == AssemblyItemType::Tag) { - Json::Value jumpdest; + Json jumpdest; jumpdest["name"] = "JUMPDEST"; jumpdest["begin"] = item.location().start; jumpdest["end"] = item.location().end; jumpdest["source"] = sourceIndex; if (item.m_modifierDepth != 0) jumpdest["modifierDepth"] = static_cast(item.m_modifierDepth); - code.append(std::move(jumpdest)); + code.emplace_back(std::move(jumpdest)); } } if (_includeSourceList) { - root["sourceList"] = Json::arrayValue; - Json::Value& jsonSourceList = root["sourceList"]; + root["sourceList"] = Json::array(); + Json& jsonSourceList = root["sourceList"]; for (auto const& [name, index]: _sourceIndices) jsonSourceList[index] = name; } if (!m_data.empty() || !m_subs.empty()) { - root[".data"] = Json::objectValue; - Json::Value& data = root[".data"]; + root[".data"] = Json::object(); + Json& data = root[".data"]; for (auto const& i: m_data) if (u256(i.first) >= m_subs.size()) data[util::toHex(toBigEndian((u256)i.first), util::HexPrefix::DontAdd, util::HexCase::Upper)] = util::toHex(i.second); @@ -506,110 +506,107 @@ Json::Value Assembly::assemblyJSON(std::map const& _sourc } std::pair, std::vector> Assembly::fromJSON( - Json::Value const& _json, + Json const& _json, std::vector const& _sourceList, size_t _level ) { - solRequire(_json.isObject(), AssemblyImportException, "Supplied JSON is not an object."); + solRequire(_json.is_object(), AssemblyImportException, "Supplied JSON is not an object."); static std::set const validMembers{".code", ".data", ".auxdata", "sourceList"}; - for (std::string const& attribute: _json.getMemberNames()) + for (auto const& [attribute, _]: _json.items()) solRequire(validMembers.count(attribute), AssemblyImportException, "Unknown attribute '" + attribute + "'."); if (_level == 0) { - if (_json.isMember("sourceList")) + if (_json.contains("sourceList")) { - solRequire(_json["sourceList"].isArray(), AssemblyImportException, "Optional member 'sourceList' is not an array."); - for (Json::Value const& sourceName: _json["sourceList"]) - solRequire(sourceName.isString(), AssemblyImportException, "The 'sourceList' array contains an item that is not a string."); + solRequire(_json["sourceList"].is_array(), AssemblyImportException, "Optional member 'sourceList' is not an array."); + for (Json const& sourceName: _json["sourceList"]) + solRequire(sourceName.is_string(), AssemblyImportException, "The 'sourceList' array contains an item that is not a string."); } } else solRequire( - !_json.isMember("sourceList"), + !_json.contains("sourceList"), AssemblyImportException, "Member 'sourceList' may only be present in the root JSON object." ); auto result = std::make_shared(EVMVersion{}, _level == 0 /* _creation */, "" /* _name */); std::vector parsedSourceList; - if (_json.isMember("sourceList")) + if (_json.contains("sourceList")) { solAssert(_level == 0); solAssert(_sourceList.empty()); - for (Json::Value const& sourceName: _json["sourceList"]) + for (Json const& sourceName: _json["sourceList"]) { solRequire( - std::find(parsedSourceList.begin(), parsedSourceList.end(), sourceName.asString()) == parsedSourceList.end(), + std::find(parsedSourceList.begin(), parsedSourceList.end(), sourceName.get()) == parsedSourceList.end(), AssemblyImportException, "Items in 'sourceList' array are not unique." ); - parsedSourceList.emplace_back(sourceName.asString()); + parsedSourceList.emplace_back(sourceName.get()); } } - solRequire(_json.isMember(".code"), AssemblyImportException, "Member '.code' is missing."); - solRequire(_json[".code"].isArray(), AssemblyImportException, "Member '.code' is not an array."); - for (Json::Value const& codeItem: _json[".code"]) - solRequire(codeItem.isObject(), AssemblyImportException, "The '.code' array contains an item that is not an object."); + solRequire(_json.contains(".code"), AssemblyImportException, "Member '.code' is missing."); + solRequire(_json[".code"].is_array(), AssemblyImportException, "Member '.code' is not an array."); + for (Json const& codeItem: _json[".code"]) + solRequire(codeItem.is_object(), AssemblyImportException, "The '.code' array contains an item that is not an object."); result->importAssemblyItemsFromJSON(_json[".code"], _level == 0 ? parsedSourceList : _sourceList); - if (_json.isMember(".auxdata")) + if (_json.contains(".auxdata")) { - solRequire(_json[".auxdata"].isString(), AssemblyImportException, "Optional member '.auxdata' is not a string."); - result->m_auxiliaryData = fromHex(_json[".auxdata"].asString()); + solRequire(_json[".auxdata"].is_string(), AssemblyImportException, "Optional member '.auxdata' is not a string."); + result->m_auxiliaryData = fromHex(_json[".auxdata"].get()); solRequire(!result->m_auxiliaryData.empty(), AssemblyImportException, "Optional member '.auxdata' is not a valid hexadecimal string."); } - if (_json.isMember(".data")) + if (_json.contains(".data")) { - solRequire(_json[".data"].isObject(), AssemblyImportException, "Optional member '.data' is not an object."); - Json::Value const& data = _json[".data"]; + solRequire(_json[".data"].is_object(), AssemblyImportException, "Optional member '.data' is not an object."); + Json const& data = _json[".data"]; std::map> subAssemblies; - for (Json::ValueConstIterator dataIter = data.begin(); dataIter != data.end(); dataIter++) + for (auto const& [key, value] : data.items()) { - solAssert(dataIter.key().isString()); - std::string dataItemID = dataIter.key().asString(); - Json::Value const& dataItem = data[dataItemID]; - if (dataItem.isString()) + if (value.is_string()) { solRequire( - dataItem.asString().empty() || !fromHex(dataItem.asString()).empty(), + value.get().empty() || !fromHex(value.get()).empty(), AssemblyImportException, - "The value for key '" + dataItemID + "' inside '.data' is not a valid hexadecimal string." + "The value for key '" + key + "' inside '.data' is not a valid hexadecimal string." ); - result->m_data[h256(fromHex(dataItemID))] = fromHex(dataItem.asString()); + result->m_data[h256(fromHex(key))] = fromHex(value.get()); } - else if (dataItem.isObject()) + else if (value.is_object()) { size_t index{}; try { // Using signed variant because stoul() still accepts negative numbers and // just lets them wrap around. - int parsedDataItemID = std::stoi(dataItemID, nullptr, 16); - solRequire(parsedDataItemID >= 0, AssemblyImportException, "The key '" + dataItemID + "' inside '.data' is out of the supported integer range."); + int parsedDataItemID = std::stoi(key, nullptr, 16); + solRequire(parsedDataItemID >= 0, AssemblyImportException, "The key '" + key + "' inside '.data' is out of the supported integer range."); index = static_cast(parsedDataItemID); } catch (std::invalid_argument const&) { - solThrow(AssemblyImportException, "The key '" + dataItemID + "' inside '.data' is not an integer."); + solThrow(AssemblyImportException, "The key '" + key + "' inside '.data' is not an integer."); } catch (std::out_of_range const&) { - solThrow(AssemblyImportException, "The key '" + dataItemID + "' inside '.data' is out of the supported integer range."); + solThrow(AssemblyImportException, "The key '" + key + "' inside '.data' is out of the supported integer range."); } - auto [subAssembly, emptySourceList] = Assembly::fromJSON(dataItem, _level == 0 ? parsedSourceList : _sourceList, _level + 1); + auto [subAssembly, emptySourceList] = Assembly::fromJSON(value, _level == 0 ? parsedSourceList : _sourceList, _level + 1); solAssert(subAssembly); solAssert(emptySourceList.empty()); solAssert(subAssemblies.count(index) == 0); subAssemblies[index] = subAssembly; } else - solThrow(AssemblyImportException, "The value of key '" + dataItemID + "' inside '.data' is neither a hex string nor an object."); + solThrow(AssemblyImportException, "The value of key '" + key + "' inside '.data' is neither a hex string nor an object."); } if (!subAssemblies.empty()) diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 6e9002825..123d7f3dd 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -30,11 +30,10 @@ #include #include #include +#include #include -#include - #include #include #include @@ -150,7 +149,7 @@ class Assembly ) const; /// Create a JSON representation of the assembly. - Json::Value assemblyJSON(std::map const& _sourceIndices, bool _includeSourceList = true) const; + Json assemblyJSON(std::map const& _sourceIndices, bool _includeSourceList = true) const; /// Constructs an @a Assembly from the serialized JSON representation. /// @param _json JSON object containing assembly in the format produced by assemblyJSON(). @@ -163,7 +162,7 @@ class Assembly /// @returns Created @a Assembly and the source list read from the 'sourceList' field of the root /// assembly or an empty list (in recursive calls). static std::pair, std::vector> fromJSON( - Json::Value const& _json, + Json const& _json, std::vector const& _sourceList = {}, size_t _level = 0 ); @@ -188,13 +187,13 @@ class Assembly /// the code array. This method only works on clean Assembly objects that don't have any items defined yet. /// @param _json JSON array that contains assembly items (e.g. json['.code']) /// @param _sourceList List of source names. - void importAssemblyItemsFromJSON(Json::Value const& _code, std::vector const& _sourceList); + void importAssemblyItemsFromJSON(Json const& _code, std::vector const& _sourceList); /// Creates an AssemblyItem from a given JSON representation. /// @param _json JSON object that consists a single assembly item /// @param _sourceList List of source names. /// @returns AssemblyItem of _json argument. - AssemblyItem createAssemblyItemFromJSON(Json::Value const& _json, std::vector const& _sourceList); + AssemblyItem createAssemblyItemFromJSON(Json const& _json, std::vector const& _sourceList); private: bool m_invalid = false; diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index a06044256..20605ee35 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -36,12 +36,12 @@ namespace solidity::evmasm void EVMAssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string const& _source) { - Json::Value assemblyJson; + Json assemblyJson; solRequire(jsonParseStrict(_source, assemblyJson), AssemblyImportException, "Could not parse JSON file."); analyze(_sourceName, assemblyJson); } -void EVMAssemblyStack::analyze(std::string const& _sourceName, Json::Value const& _assemblyJson) +void EVMAssemblyStack::analyze(std::string const& _sourceName, Json const& _assemblyJson) { solAssert(!m_evmAssembly); m_name = _sourceName; @@ -99,7 +99,7 @@ std::string const* EVMAssemblyStack::runtimeSourceMapping(std::string const& _co return &m_runtimeSourceMapping; } -Json::Value EVMAssemblyStack::assemblyJSON(std::string const& _contractName) const +Json EVMAssemblyStack::assemblyJSON(std::string const& _contractName) const { solAssert(_contractName == m_name); solAssert(m_evmAssembly); diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index 7fe77e7d2..f2516c0b8 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -43,7 +43,7 @@ class EVMAssemblyStack: public AbstractAssemblyStack /// Runs analysis steps. /// Multiple calls overwrite the previous state. /// @throws AssemblyImportException, if JSON could not be validated. - void analyze(std::string const& _sourceName, Json::Value const& _assemblyJson); + void analyze(std::string const& _sourceName, Json const& _assemblyJson); void assemble(); @@ -58,7 +58,7 @@ class EVMAssemblyStack: public AbstractAssemblyStack virtual std::string const* sourceMapping(std::string const& _contractName) const override; virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const override; - virtual Json::Value assemblyJSON(std::string const& _contractName) const override; + virtual Json assemblyJSON(std::string const& _contractName) const override; virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const override; virtual std::string const filesystemFriendlyName(std::string const& _contractName) const override; diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 27926721a..d8b178377 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -34,8 +34,7 @@ #include #include #include - -#include +#include #include #include diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index c54a2d013..f94b91674 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -46,12 +46,13 @@ using namespace std::string_literals; using namespace solidity::langutil; +using namespace solidity; namespace { template typename C> -void addIfSet(std::vector>& _attributes, std::string const& _name, C const& _value) +void addIfSet(std::vector>& _attributes, std::string const& _name, C const& _value) { if constexpr (std::is_same_v, solidity::util::SetOnce>) { @@ -82,23 +83,23 @@ ASTJsonExporter::ASTJsonExporter(CompilerStack::State _stackState, std::map>&& _attributes + std::initializer_list>&& _attributes ) { ASTJsonExporter::setJsonNode( _node, _nodeName, - std::vector>(std::move(_attributes)) + std::vector>(std::move(_attributes)) ); } void ASTJsonExporter::setJsonNode( ASTNode const& _node, std::string const& _nodeType, - std::vector>&& _attributes + std::vector>&& _attributes ) { - m_currentValue = Json::objectValue; + m_currentValue = Json::object(); m_currentValue["id"] = nodeId(_node); m_currentValue["src"] = sourceLocationToString(_node.location()); if (auto const* documented = dynamic_cast(&_node)) @@ -126,12 +127,12 @@ std::string ASTJsonExporter::sourceLocationToString(SourceLocation const& _locat return std::to_string(_location.start) + ":" + std::to_string(length) + ":" + (sourceIndexOpt.has_value() ? std::to_string(sourceIndexOpt.value()) : "-1"); } -Json::Value ASTJsonExporter::sourceLocationsToJson(std::vector const& _sourceLocations) const +Json ASTJsonExporter::sourceLocationsToJson(std::vector const& _sourceLocations) const { - Json::Value locations = Json::arrayValue; + Json locations = Json::array(); for (SourceLocation const& location: _sourceLocations) - locations.append(sourceLocationToString(location)); + locations.emplace_back(sourceLocationToString(location)); return locations; } @@ -141,33 +142,33 @@ std::string ASTJsonExporter::namePathToString(std::vector const& _nam return boost::algorithm::join(_namePath, "."s); } -Json::Value ASTJsonExporter::typePointerToJson(Type const* _tp, bool _withoutDataLocation) +Json ASTJsonExporter::typePointerToJson(Type const* _tp, bool _withoutDataLocation) { - Json::Value typeDescriptions(Json::objectValue); - typeDescriptions["typeString"] = _tp ? Json::Value(_tp->toString(_withoutDataLocation)) : Json::nullValue; - typeDescriptions["typeIdentifier"] = _tp ? Json::Value(_tp->identifier()) : Json::nullValue; + Json typeDescriptions; + typeDescriptions["typeString"] = _tp ? Json(_tp->toString(_withoutDataLocation)) : Json(); + typeDescriptions["typeIdentifier"] = _tp ? Json(_tp->identifier()) : Json(); return typeDescriptions; } -Json::Value ASTJsonExporter::typePointerToJson(std::optional const& _tps) +Json ASTJsonExporter::typePointerToJson(std::optional const& _tps) { if (_tps) { - Json::Value arguments(Json::arrayValue); + Json arguments = Json::array(); for (auto const& tp: _tps->types) appendMove(arguments, typePointerToJson(tp)); return arguments; } else - return Json::nullValue; + return Json(); } void ASTJsonExporter::appendExpressionAttributes( - std::vector>& _attributes, + std::vector>& _attributes, ExpressionAnnotation const& _annotation ) { - std::vector> exprAttributes = { + std::vector> exprAttributes = { std::make_pair("typeDescriptions", typePointerToJson(_annotation.type)), std::make_pair("argumentTypes", typePointerToJson(_annotation.arguments)) }; @@ -182,18 +183,18 @@ void ASTJsonExporter::appendExpressionAttributes( _attributes += exprAttributes; } -Json::Value ASTJsonExporter::inlineAssemblyIdentifierToJson(std::pair _info) const +Json ASTJsonExporter::inlineAssemblyIdentifierToJson(std::pair _info) const { - Json::Value tuple(Json::objectValue); + Json tuple; tuple["src"] = sourceLocationToString(nativeLocationOf(*_info.first)); tuple["declaration"] = idOrNull(_info.second.declaration); - tuple["isSlot"] = Json::Value(_info.second.suffix == "slot"); - tuple["isOffset"] = Json::Value(_info.second.suffix == "offset"); + tuple["isSlot"] = Json(_info.second.suffix == "slot"); + tuple["isOffset"] = Json(_info.second.suffix == "offset"); if (!_info.second.suffix.empty()) - tuple["suffix"] = Json::Value(_info.second.suffix); + tuple["suffix"] = Json(_info.second.suffix); - tuple["valueSize"] = Json::Value(Json::LargestUInt(_info.second.valueSize)); + tuple["valueSize"] = Json(static_cast(_info.second.valueSize)); return tuple; } @@ -203,7 +204,7 @@ void ASTJsonExporter::print(std::ostream& _stream, ASTNode const& _node, util::J _stream << util::jsonPrint(toJson(_node), _format); } -Json::Value ASTJsonExporter::toJson(ASTNode const& _node) +Json ASTJsonExporter::toJson(ASTNode const& _node) { _node.accept(*this); return util::removeNullMembers(std::move(m_currentValue)); @@ -211,22 +212,22 @@ Json::Value ASTJsonExporter::toJson(ASTNode const& _node) bool ASTJsonExporter::visit(SourceUnit const& _node) { - std::vector> attributes = { - std::make_pair("license", _node.licenseString() ? Json::Value(*_node.licenseString()) : Json::nullValue), + std::vector> attributes = { + std::make_pair("license", _node.licenseString() ? Json(*_node.licenseString()) : Json()), std::make_pair("nodes", toJson(_node.nodes())), }; if (_node.experimentalSolidity()) - attributes.emplace_back("experimentalSolidity", Json::Value(_node.experimentalSolidity())); + attributes.emplace_back("experimentalSolidity", Json(_node.experimentalSolidity())); if (_node.annotation().exportedSymbols.set()) { - Json::Value exportedSymbols = Json::objectValue; + Json exportedSymbols = Json::object(); for (auto const& sym: *_node.annotation().exportedSymbols) { - exportedSymbols[sym.first] = Json::arrayValue; + exportedSymbols[sym.first] = Json::array(); for (Declaration const* overload: sym.second) - exportedSymbols[sym.first].append(nodeId(*overload)); + exportedSymbols[sym.first].emplace_back(nodeId(*overload)); } attributes.emplace_back("exportedSymbols", exportedSymbols); @@ -241,9 +242,9 @@ bool ASTJsonExporter::visit(SourceUnit const& _node) bool ASTJsonExporter::visit(PragmaDirective const& _node) { - Json::Value literals(Json::arrayValue); + Json literals = Json::array(); for (auto const& literal: _node.literals()) - literals.append(literal); + literals.emplace_back(literal); setJsonNode(_node, "PragmaDirective", { std::make_pair("literals", std::move(literals)) }); @@ -252,7 +253,7 @@ bool ASTJsonExporter::visit(PragmaDirective const& _node) bool ASTJsonExporter::visit(ImportDirective const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("file", _node.path()), std::make_pair("sourceUnit", idOrNull(_node.annotation().sourceUnit)), std::make_pair("scope", idOrNull(_node.scope())) @@ -261,17 +262,17 @@ bool ASTJsonExporter::visit(ImportDirective const& _node) addIfSet(attributes, "absolutePath", _node.annotation().absolutePath); attributes.emplace_back("unitAlias", _node.name()); - attributes.emplace_back("nameLocation", Json::Value(sourceLocationToString(_node.nameLocation()))); + attributes.emplace_back("nameLocation", Json(sourceLocationToString(_node.nameLocation()))); - Json::Value symbolAliases(Json::arrayValue); + Json symbolAliases = Json::array(); for (auto const& symbolAlias: _node.symbolAliases()) { - Json::Value tuple(Json::objectValue); + Json tuple; solAssert(symbolAlias.symbol, ""); tuple["foreign"] = toJson(*symbolAlias.symbol); - tuple["local"] = symbolAlias.alias ? Json::Value(*symbolAlias.alias) : Json::nullValue; + tuple["local"] = symbolAlias.alias ? Json(*symbolAlias.alias) : Json(); tuple["nameLocation"] = sourceLocationToString(_node.nameLocation()); - symbolAliases.append(tuple); + symbolAliases.emplace_back(tuple); } attributes.emplace_back("symbolAliases", std::move(symbolAliases)); setJsonNode(_node, "ImportDirective", std::move(attributes)); @@ -280,10 +281,10 @@ bool ASTJsonExporter::visit(ImportDirective const& _node) bool ASTJsonExporter::visit(ContractDefinition const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("contractKind", contractKind(_node.contractKind())), std::make_pair("abstract", _node.abstract()), std::make_pair("baseContracts", toJson(_node.baseContracts())), @@ -303,7 +304,7 @@ bool ASTJsonExporter::visit(ContractDefinition const& _node) if (!_node.annotation().internalFunctionIDs.empty()) { - Json::Value internalFunctionIDs(Json::objectValue); + Json internalFunctionIDs; for (auto const& [functionDefinition, internalFunctionID]: _node.annotation().internalFunctionIDs) internalFunctionIDs[std::to_string(functionDefinition->id())] = internalFunctionID; attributes.emplace_back("internalFunctionIDs", std::move(internalFunctionIDs)); @@ -315,10 +316,10 @@ bool ASTJsonExporter::visit(ContractDefinition const& _node) bool ASTJsonExporter::visit(IdentifierPath const& _node) { - Json::Value nameLocations = Json::arrayValue; + Json nameLocations = Json::array(); for (SourceLocation location: _node.pathLocations()) - nameLocations.append(sourceLocationToString(location)); + nameLocations.emplace_back(sourceLocationToString(location)); setJsonNode(_node, "IdentifierPath", { std::make_pair("name", namePathToString(_node.path())), @@ -332,23 +333,23 @@ bool ASTJsonExporter::visit(InheritanceSpecifier const& _node) { setJsonNode(_node, "InheritanceSpecifier", { std::make_pair("baseName", toJson(_node.name())), - std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue) + std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json()) }); return false; } bool ASTJsonExporter::visit(UsingForDirective const& _node) { - std::vector> attributes = { - std::make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json::nullValue) + std::vector> attributes = { + std::make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json()) }; if (_node.usesBraces()) { - Json::Value functionList; + Json functionList = Json::array(); for (auto&& [function, op]: _node.functionsAndOperators()) { - Json::Value functionNode; + Json functionNode; if (!op.has_value()) functionNode["function"] = toJson(*function); else @@ -356,7 +357,7 @@ bool ASTJsonExporter::visit(UsingForDirective const& _node) functionNode["definition"] = toJson(*function); functionNode["operator"] = std::string(TokenTraits::toString(*op)); } - functionList.append(std::move(functionNode)); + functionList.emplace_back(std::move(functionNode)); } attributes.emplace_back("functionList", std::move(functionList)); } @@ -376,10 +377,10 @@ bool ASTJsonExporter::visit(UsingForDirective const& _node) bool ASTJsonExporter::visit(StructDefinition const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())), std::make_pair("members", toJson(_node.members())), std::make_pair("scope", idOrNull(_node.scope())) @@ -394,10 +395,10 @@ bool ASTJsonExporter::visit(StructDefinition const& _node) bool ASTJsonExporter::visit(EnumDefinition const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("members", toJson(_node.members())) }; @@ -420,7 +421,7 @@ bool ASTJsonExporter::visit(EnumValue const& _node) bool ASTJsonExporter::visit(UserDefinedValueTypeDefinition const& _node) { solAssert(_node.underlyingType(), ""); - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), std::make_pair("underlyingType", toJson(*_node.underlyingType())) @@ -450,18 +451,18 @@ bool ASTJsonExporter::visit(OverrideSpecifier const& _node) bool ASTJsonExporter::visit(FunctionDefinition const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("kind", _node.isFree() ? "freeFunction" : TokenTraits::toString(_node.kind())), std::make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())), std::make_pair("virtual", _node.markedVirtual()), - std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue), + std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json()), std::make_pair("parameters", toJson(_node.parameterList())), std::make_pair("returnParameters", toJson(*_node.returnParameterList())), std::make_pair("modifiers", toJson(_node.modifiers())), - std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue), + std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json()), std::make_pair("implemented", _node.isImplemented()), std::make_pair("scope", idOrNull(_node.scope())) }; @@ -489,7 +490,7 @@ bool ASTJsonExporter::visit(FunctionDefinition const& _node) bool ASTJsonExporter::visit(VariableDeclaration const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), std::make_pair("typeName", toJson(_node.typeName())), @@ -497,9 +498,9 @@ bool ASTJsonExporter::visit(VariableDeclaration const& _node) std::make_pair("mutability", VariableDeclaration::mutabilityToString(_node.mutability())), std::make_pair("stateVariable", _node.isStateVariable()), std::make_pair("storageLocation", location(_node.referenceLocation())), - std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue), + std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json()), std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())), - std::make_pair("value", _node.value() ? toJson(*_node.value()) : Json::nullValue), + std::make_pair("value", _node.value() ? toJson(*_node.value()) : Json()), std::make_pair("scope", idOrNull(_node.scope())), std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) }; @@ -517,15 +518,15 @@ bool ASTJsonExporter::visit(VariableDeclaration const& _node) bool ASTJsonExporter::visit(ModifierDefinition const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())), std::make_pair("parameters", toJson(_node.parameterList())), std::make_pair("virtual", _node.markedVirtual()), - std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue), - std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue) + std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json()), + std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json()) }; if (!_node.annotation().baseFunctions.empty()) attributes.emplace_back(std::make_pair("baseModifiers", getContainerIds(_node.annotation().baseFunctions, true))); @@ -535,9 +536,9 @@ bool ASTJsonExporter::visit(ModifierDefinition const& _node) bool ASTJsonExporter::visit(ModifierInvocation const& _node) { - std::vector> attributes{ + std::vector> attributes{ std::make_pair("modifierName", toJson(_node.name())), - std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue) + std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json()) }; if (Declaration const* declaration = _node.name().annotation().referencedDeclaration) { @@ -553,10 +554,10 @@ bool ASTJsonExporter::visit(ModifierInvocation const& _node) bool ASTJsonExporter::visit(EventDefinition const& _node) { m_inEvent = true; - std::vector> _attributes = { + std::vector> _attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("parameters", toJson(_node.parameterList())), std::make_pair("anonymous", _node.isAnonymous()) }; @@ -573,10 +574,10 @@ bool ASTJsonExporter::visit(EventDefinition const& _node) bool ASTJsonExporter::visit(ErrorDefinition const& _node) { - std::vector> _attributes = { + std::vector> _attributes = { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), - std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), + std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()), std::make_pair("parameters", toJson(_node.parameterList())) }; if (m_stackState >= CompilerStack::State::AnalysisSuccessful) @@ -588,7 +589,7 @@ bool ASTJsonExporter::visit(ErrorDefinition const& _node) bool ASTJsonExporter::visit(ElementaryTypeName const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("name", _node.typeName().toString()), std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) }; @@ -648,7 +649,7 @@ bool ASTJsonExporter::visit(ArrayTypeName const& _node) bool ASTJsonExporter::visit(InlineAssembly const& _node) { - std::vector> externalReferences; + std::vector> externalReferences; for (auto const& it: _node.annotation().externalReferences) if (it.first) @@ -657,26 +658,26 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) inlineAssemblyIdentifierToJson(it) )); - Json::Value externalReferencesJson = Json::arrayValue; + Json externalReferencesJson = Json::array(); std::sort(externalReferences.begin(), externalReferences.end()); - for (Json::Value& it: externalReferences | ranges::views::values) - externalReferencesJson.append(std::move(it)); + for (Json& it: externalReferences | ranges::views::values) + externalReferencesJson.emplace_back(std::move(it)); - std::vector> attributes = { - std::make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))), + std::vector> attributes = { + std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))), std::make_pair("externalReferences", std::move(externalReferencesJson)), std::make_pair("evmVersion", dynamic_cast(_node.dialect()).evmVersion().name()) }; if (_node.flags()) { - Json::Value flags(Json::arrayValue); + Json flags = Json::array(); for (auto const& flag: *_node.flags()) if (flag) - flags.append(*flag); + flags.emplace_back(*flag); else - flags.append(Json::nullValue); + flags.emplace_back(Json()); attributes.emplace_back(std::make_pair("flags", std::move(flags))); } setJsonNode(_node, "InlineAssembly", std::move(attributes)); @@ -743,7 +744,7 @@ bool ASTJsonExporter::visit(WhileStatement const& _node) bool ASTJsonExporter::visit(ForStatement const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("initializationExpression", toJsonOrNull(_node.initializationExpression())), std::make_pair("condition", toJsonOrNull(_node.condition())), std::make_pair("loopExpression", toJsonOrNull(_node.loopExpression())), @@ -802,7 +803,7 @@ bool ASTJsonExporter::visit(RevertStatement const& _node) bool ASTJsonExporter::visit(VariableDeclarationStatement const& _node) { - Json::Value varDecs(Json::arrayValue); + Json varDecs = Json::array(); for (auto const& v: _node.declarations()) appendMove(varDecs, idOrNull(v.get())); setJsonNode(_node, "VariableDeclarationStatement", { @@ -823,7 +824,7 @@ bool ASTJsonExporter::visit(ExpressionStatement const& _node) bool ASTJsonExporter::visit(Conditional const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("condition", toJson(_node.condition())), std::make_pair("trueExpression", toJson(_node.trueExpression())), std::make_pair("falseExpression", toJson(_node.falseExpression())) @@ -835,7 +836,7 @@ bool ASTJsonExporter::visit(Conditional const& _node) bool ASTJsonExporter::visit(Assignment const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("operator", TokenTraits::toString(_node.assignmentOperator())), std::make_pair("leftHandSide", toJson(_node.leftHandSide())), std::make_pair("rightHandSide", toJson(_node.rightHandSide())) @@ -847,8 +848,8 @@ bool ASTJsonExporter::visit(Assignment const& _node) bool ASTJsonExporter::visit(TupleExpression const& _node) { - std::vector> attributes = { - std::make_pair("isInlineArray", Json::Value(_node.isInlineArray())), + std::vector> attributes = { + std::make_pair("isInlineArray", Json(_node.isInlineArray())), std::make_pair("components", toJson(_node.components())), }; appendExpressionAttributes(attributes, _node.annotation()); @@ -858,7 +859,7 @@ bool ASTJsonExporter::visit(TupleExpression const& _node) bool ASTJsonExporter::visit(UnaryOperation const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("prefix", _node.isPrefixOperation()), std::make_pair("operator", TokenTraits::toString(_node.getOperator())), std::make_pair("subExpression", toJson(_node.subExpression())) @@ -873,7 +874,7 @@ bool ASTJsonExporter::visit(UnaryOperation const& _node) bool ASTJsonExporter::visit(BinaryOperation const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("operator", TokenTraits::toString(_node.getOperator())), std::make_pair("leftExpression", toJson(_node.leftExpression())), std::make_pair("rightExpression", toJson(_node.rightExpression())), @@ -889,10 +890,10 @@ bool ASTJsonExporter::visit(BinaryOperation const& _node) bool ASTJsonExporter::visit(FunctionCall const& _node) { - Json::Value names(Json::arrayValue); + Json names = Json::array(); for (auto const& name: _node.names()) - names.append(Json::Value(*name)); - std::vector> attributes = { + names.push_back(Json(*name)); + std::vector> attributes = { std::make_pair("expression", toJson(_node.expression())), std::make_pair("names", std::move(names)), std::make_pair("nameLocations", sourceLocationsToJson(_node.nameLocations())), @@ -913,11 +914,11 @@ bool ASTJsonExporter::visit(FunctionCall const& _node) bool ASTJsonExporter::visit(FunctionCallOptions const& _node) { - Json::Value names(Json::arrayValue); + Json names = Json::array(); for (auto const& name: _node.names()) - names.append(Json::Value(*name)); + names.emplace_back(Json(*name)); - std::vector> attributes = { + std::vector> attributes = { std::make_pair("expression", toJson(_node.expression())), std::make_pair("names", std::move(names)), std::make_pair("options", toJson(_node.options())), @@ -930,7 +931,7 @@ bool ASTJsonExporter::visit(FunctionCallOptions const& _node) bool ASTJsonExporter::visit(NewExpression const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("typeName", toJson(_node.typeName())) }; appendExpressionAttributes(attributes, _node.annotation()); @@ -940,9 +941,9 @@ bool ASTJsonExporter::visit(NewExpression const& _node) bool ASTJsonExporter::visit(MemberAccess const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("memberName", _node.memberName()), - std::make_pair("memberLocation", Json::Value(sourceLocationToString(_node.memberLocation()))), + std::make_pair("memberLocation", Json(sourceLocationToString(_node.memberLocation()))), std::make_pair("expression", toJson(_node.expression())), std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), }; @@ -953,7 +954,7 @@ bool ASTJsonExporter::visit(MemberAccess const& _node) bool ASTJsonExporter::visit(IndexAccess const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("baseExpression", toJson(_node.baseExpression())), std::make_pair("indexExpression", toJsonOrNull(_node.indexExpression())), }; @@ -964,7 +965,7 @@ bool ASTJsonExporter::visit(IndexAccess const& _node) bool ASTJsonExporter::visit(IndexRangeAccess const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("baseExpression", toJson(_node.baseExpression())), std::make_pair("startExpression", toJsonOrNull(_node.startExpression())), std::make_pair("endExpression", toJsonOrNull(_node.endExpression())), @@ -976,9 +977,9 @@ bool ASTJsonExporter::visit(IndexRangeAccess const& _node) bool ASTJsonExporter::visit(Identifier const& _node) { - Json::Value overloads(Json::arrayValue); + Json overloads = Json::array(); for (auto const& dec: _node.annotation().overloadedDeclarations) - overloads.append(nodeId(*dec)); + overloads.emplace_back(nodeId(*dec)); setJsonNode(_node, "Identifier", { std::make_pair("name", _node.name()), std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), @@ -991,7 +992,7 @@ bool ASTJsonExporter::visit(Identifier const& _node) bool ASTJsonExporter::visit(ElementaryTypeNameExpression const& _node) { - std::vector> attributes = { + std::vector> attributes = { std::make_pair("typeName", toJson(_node.type())) }; appendExpressionAttributes(attributes, _node.annotation()); @@ -1001,19 +1002,19 @@ bool ASTJsonExporter::visit(ElementaryTypeNameExpression const& _node) bool ASTJsonExporter::visit(Literal const& _node) { - Json::Value value{_node.value()}; + Json value = _node.value(); if (!util::validateUTF8(_node.value())) - value = Json::nullValue; + value = Json(); Token subdenomination = Token(_node.subDenomination()); - std::vector> attributes = { + std::vector> attributes = { std::make_pair("kind", literalTokenKind(_node.token())), std::make_pair("value", value), std::make_pair("hexValue", util::toHex(util::asBytes(_node.value()))), std::make_pair( "subdenomination", subdenomination == Token::Illegal ? - Json::nullValue : - Json::Value{TokenTraits::toString(subdenomination)} + Json() : + Json(TokenTraits::toString(subdenomination)) ) }; appendExpressionAttributes(attributes, _node.annotation()); @@ -1023,16 +1024,14 @@ bool ASTJsonExporter::visit(Literal const& _node) bool ASTJsonExporter::visit(StructuredDocumentation const& _node) { - Json::Value text{*_node.text()}; - std::vector> attributes = { + Json text = *_node.text(); + std::vector> attributes = { std::make_pair("text", text) }; setJsonNode(_node, "StructuredDocumentation", std::move(attributes)); return false; } - - void ASTJsonExporter::endVisit(EventDefinition const&) { m_inEvent = false; diff --git a/libsolidity/ast/ASTJsonExporter.h b/libsolidity/ast/ASTJsonExporter.h index ff3b94fa2..c7933120a 100644 --- a/libsolidity/ast/ASTJsonExporter.h +++ b/libsolidity/ast/ASTJsonExporter.h @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -60,16 +59,16 @@ class ASTJsonExporter: public ASTConstVisitor ); /// Output the json representation of the AST to _stream. void print(std::ostream& _stream, ASTNode const& _node, util::JsonFormat const& _format); - Json::Value toJson(ASTNode const& _node); + Json toJson(ASTNode const& _node); template - Json::Value toJson(std::vector> const& _nodes) + Json toJson(std::vector> const& _nodes) { - Json::Value ret(Json::arrayValue); + Json ret = Json::array(); for (auto const& n: _nodes) if (n) appendMove(ret, toJson(*n)); else - ret.append(Json::nullValue); + ret.emplace_back(Json()); return ret; } bool visit(SourceUnit const& _node) override; @@ -135,27 +134,27 @@ class ASTJsonExporter: public ASTConstVisitor void setJsonNode( ASTNode const& _node, std::string const& _nodeName, - std::initializer_list>&& _attributes + std::initializer_list>&& _attributes ); void setJsonNode( ASTNode const& _node, std::string const& _nodeName, - std::vector>&& _attributes + std::vector>&& _attributes ); /// Maps source location to an index, if source is valid and a mapping does exist, otherwise returns std::nullopt. std::optional sourceIndexFromLocation(langutil::SourceLocation const& _location) const; std::string sourceLocationToString(langutil::SourceLocation const& _location) const; - Json::Value sourceLocationsToJson(std::vector const& _sourceLocations) const; + Json sourceLocationsToJson(std::vector const& _sourceLocations) const; static std::string namePathToString(std::vector const& _namePath); - static Json::Value idOrNull(ASTNode const* _pt) + static Json idOrNull(ASTNode const* _pt) { - return _pt ? Json::Value(nodeId(*_pt)) : Json::nullValue; + return _pt ? Json(nodeId(*_pt)) : Json(); } - Json::Value toJsonOrNull(ASTNode const* _node) + Json toJsonOrNull(ASTNode const* _node) { - return _node ? toJson(*_node) : Json::nullValue; + return _node ? toJson(*_node) : Json(); } - Json::Value inlineAssemblyIdentifierToJson(std::pair _info) const; + Json inlineAssemblyIdentifierToJson(std::pair _info) const; static std::string location(VariableDeclaration::Location _location); static std::string contractKind(ContractKind _kind); static std::string functionCallKind(FunctionCallKind _kind); @@ -167,7 +166,7 @@ class ASTJsonExporter: public ASTConstVisitor return _node.id(); } template - static Json::Value getContainerIds(Container const& _container, bool _order = false) + static Json getContainerIds(Container const& _container, bool _order = false) { std::vector tmp; @@ -178,28 +177,27 @@ class ASTJsonExporter: public ASTConstVisitor } if (_order) std::sort(tmp.begin(), tmp.end()); - Json::Value json(Json::arrayValue); + Json json = Json::array(); for (int64_t val: tmp) - json.append(val); - + json.emplace_back(val); return json; } - static Json::Value typePointerToJson(Type const* _tp, bool _withoutDataLocation = false); - static Json::Value typePointerToJson(std::optional const& _tps); + static Json typePointerToJson(Type const* _tp, bool _withoutDataLocation = false); + static Json typePointerToJson(std::optional const& _tps); void appendExpressionAttributes( - std::vector> &_attributes, + std::vector> &_attributes, ExpressionAnnotation const& _annotation ); - static void appendMove(Json::Value& _array, Json::Value&& _value) + static void appendMove(Json& _array, Json&& _value) { - solAssert(_array.isArray(), ""); - _array.append(std::move(_value)); + solAssert(_array.is_array(), ""); + _array.emplace_back(std::move(_value)); } CompilerStack::State m_stackState = CompilerStack::State::Empty; ///< Used to only access information that already exists bool m_inEvent = false; ///< whether we are currently inside an event or not - Json::Value m_currentValue; + Json m_currentValue; std::map m_sourceIndices; }; diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 6e6dd9eb5..5c1d4bdc0 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -43,9 +43,9 @@ namespace solidity::frontend using SourceLocation = langutil::SourceLocation; template -ASTPointer ASTJsonImporter::nullOrCast(Json::Value const& _json) +ASTPointer ASTJsonImporter::nullOrCast(Json const& _json) { - if (_json.isNull()) + if (_json.is_null()) return nullptr; else return std::dynamic_pointer_cast(convertJsonToASTNode(_json)); @@ -54,13 +54,13 @@ ASTPointer ASTJsonImporter::nullOrCast(Json::Value const& _json) // ============ public =========================== -std::map> ASTJsonImporter::jsonToSourceUnit(std::map const& _sourceList) +std::map> ASTJsonImporter::jsonToSourceUnit(std::map const& _sourceList) { for (auto const& src: _sourceList) m_sourceNames.emplace_back(std::make_shared(src.first)); for (auto const& srcPair: _sourceList) { - astAssert(!srcPair.second.isNull()); + astAssert(!srcPair.second.is_null()); astAssert(member(srcPair.second,"nodeType") == "SourceUnit", "The 'nodeType' of the highest node must be 'SourceUnit'."); m_sourceUnits[srcPair.first] = createSourceUnit(srcPair.second, srcPair.first); } @@ -71,11 +71,12 @@ std::map> ASTJsonImporter::jsonToSourceUnit( // =========== general creation functions ============== template -ASTPointer ASTJsonImporter::createASTNode(Json::Value const& _node, Args&&... _args) +ASTPointer ASTJsonImporter::createASTNode(Json const& _node, Args&&... _args) { - astAssert(member(_node, "id").isInt64(), "'id'-field must be 64bit integer."); + static_assert(std::is_same_v); + astAssert(member(_node, "id").is_number_integer(), "'id'-field must be 64bit integer."); - int64_t id = _node["id"].asInt64(); + int64_t id = static_cast(_node["id"]); astAssert(m_usedIDs.insert(id).second, "Found duplicate node ID!"); @@ -87,50 +88,50 @@ ASTPointer ASTJsonImporter::createASTNode(Json::Value const& _node, Args&&... return n; } -SourceLocation const ASTJsonImporter::createSourceLocation(Json::Value const& _node) +SourceLocation const ASTJsonImporter::createSourceLocation(Json const& _node) { - astAssert(member(_node, "src").isString(), "'src' must be a string"); + astAssert(member(_node, "src").is_string(), "'src' must be a string"); - return solidity::langutil::parseSourceLocation(_node["src"].asString(), m_sourceNames); + return solidity::langutil::parseSourceLocation(_node["src"].get(), m_sourceNames); } -std::optional> ASTJsonImporter::createSourceLocations(Json::Value const& _node) const +std::optional> ASTJsonImporter::createSourceLocations(Json const& _node) const { std::vector locations; - if (_node.isMember("nameLocations") && _node["nameLocations"].isArray()) + if (_node.contains("nameLocations") && _node["nameLocations"].is_array()) { for (auto const& val: _node["nameLocations"]) - locations.emplace_back(langutil::parseSourceLocation(val.asString(), m_sourceNames)); + locations.emplace_back(langutil::parseSourceLocation(val.get(), m_sourceNames)); return locations; } return std::nullopt; } -SourceLocation ASTJsonImporter::createNameSourceLocation(Json::Value const& _node) +SourceLocation ASTJsonImporter::createNameSourceLocation(Json const& _node) { - astAssert(member(_node, "nameLocation").isString(), "'nameLocation' must be a string"); + astAssert(member(_node, "nameLocation").is_string(), "'nameLocation' must be a string"); - return solidity::langutil::parseSourceLocation(_node["nameLocation"].asString(), m_sourceNames); + return solidity::langutil::parseSourceLocation(_node["nameLocation"].get(), m_sourceNames); } -SourceLocation ASTJsonImporter::createKeyNameSourceLocation(Json::Value const& _node) +SourceLocation ASTJsonImporter::createKeyNameSourceLocation(Json const& _node) { - astAssert(member(_node, "keyNameLocation").isString(), "'keyNameLocation' must be a string"); + astAssert(member(_node, "keyNameLocation").is_string(), "'keyNameLocation' must be a string"); - return solidity::langutil::parseSourceLocation(_node["keyNameLocation"].asString(), m_sourceNames); + return solidity::langutil::parseSourceLocation(_node["keyNameLocation"].get(), m_sourceNames); } -SourceLocation ASTJsonImporter::createValueNameSourceLocation(Json::Value const& _node) +SourceLocation ASTJsonImporter::createValueNameSourceLocation(Json const& _node) { - astAssert(member(_node, "valueNameLocation").isString(), "'valueNameLocation' must be a string"); + astAssert(member(_node, "valueNameLocation").is_string(), "'valueNameLocation' must be a string"); - return solidity::langutil::parseSourceLocation(_node["valueNameLocation"].asString(), m_sourceNames); + return solidity::langutil::parseSourceLocation(_node["valueNameLocation"].get(), m_sourceNames); } template -ASTPointer ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node) +ASTPointer ASTJsonImporter::convertJsonToASTNode(Json const& _node) { ASTPointer ret = std::dynamic_pointer_cast(convertJsonToASTNode(_node)); astAssert(ret, "cast of converted json-node must not be nullptr"); @@ -138,10 +139,10 @@ ASTPointer ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node) } -ASTPointer ASTJsonImporter::convertJsonToASTNode(Json::Value const& _json) +ASTPointer ASTJsonImporter::convertJsonToASTNode(Json const& _json) { - astAssert(_json["nodeType"].isString() && _json.isMember("id"), "JSON-Node needs to have 'nodeType' and 'id' fields."); - std::string nodeType = _json["nodeType"].asString(); + astAssert(_json["nodeType"].is_string() && _json.contains("id"), "JSON-Node needs to have 'nodeType' and 'id' fields."); + std::string nodeType = _json["nodeType"].get(); if (nodeType == "PragmaDirective") return createPragmaDirective(_json); if (nodeType == "ImportDirective") @@ -263,15 +264,15 @@ ASTPointer ASTJsonImporter::convertJsonToASTNode(Json::Value const& _js // ============ functions to instantiate the AST-Nodes from Json-Nodes ============== -ASTPointer ASTJsonImporter::createSourceUnit(Json::Value const& _node, std::string const& _srcName) +ASTPointer ASTJsonImporter::createSourceUnit(Json const& _node, std::string const& _srcName) { std::optional license; - if (_node.isMember("license") && !_node["license"].isNull()) - license = _node["license"].asString(); + if (_node.contains("license") && !_node["license"].is_null()) + license = _node["license"].get(); bool experimentalSolidity = false; - if (_node.isMember("experimentalSolidity") && !_node["experimentalSolidity"].isNull()) - experimentalSolidity = _node["experimentalSolidity"].asBool(); + if (_node.contains("experimentalSolidity") && !_node["experimentalSolidity"].is_null()) + experimentalSolidity = _node["experimentalSolidity"].get(); std::vector> nodes; for (auto& child: member(_node, "nodes")) @@ -282,20 +283,20 @@ ASTPointer ASTJsonImporter::createSourceUnit(Json::Value const& _nod return tmp; } -ASTPointer ASTJsonImporter::createPragmaDirective(Json::Value const& _node) +ASTPointer ASTJsonImporter::createPragmaDirective(Json const& _node) { std::vector tokens; std::vector literals; for (auto const& lit: member(_node, "literals")) { - std::string l = lit.asString(); + std::string l = lit.get(); literals.push_back(l); tokens.push_back(scanSingleToken(l)); } return createASTNode(_node, tokens, literals); } -ASTPointer ASTJsonImporter::createImportDirective(Json::Value const& _node) +ASTPointer ASTJsonImporter::createImportDirective(Json const& _node) { ASTPointer unitAlias = memberAsASTString(_node, "unitAlias"); ASTPointer path = memberAsASTString(_node, "file"); @@ -303,11 +304,11 @@ ASTPointer ASTJsonImporter::createImportDirective(Json::Value c for (auto& tuple: member(_node, "symbolAliases")) { - astAssert(tuple["local"].isNull() || tuple["local"].isString(), "expected 'local' to be a string or null!"); + astAssert(tuple["local"].is_null() || tuple["local"].is_string(), "expected 'local' to be a string or null!"); symbolAliases.push_back({ createIdentifier(tuple["foreign"]), - tuple["local"].isNull() ? nullptr : std::make_shared(tuple["local"].asString()), + tuple["local"].is_null() ? nullptr : std::make_shared(tuple["local"].get()), createSourceLocation(tuple["foreign"])} ); } @@ -319,15 +320,15 @@ ASTPointer ASTJsonImporter::createImportDirective(Json::Value c std::move(symbolAliases) ); - astAssert(_node["absolutePath"].isString(), "Expected 'absolutePath' to be a string!"); + astAssert(_node["absolutePath"].is_string(), "Expected 'absolutePath' to be a string!"); - tmp->annotation().absolutePath = _node["absolutePath"].asString(); + tmp->annotation().absolutePath = _node["absolutePath"].get(); return tmp; } -ASTPointer ASTJsonImporter::createContractDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createContractDefinition(Json const& _node) { - astAssert(_node["name"].isString(), "Expected 'name' to be a string!"); + astAssert(_node["name"].is_string(), "Expected 'name' to be a string!"); std::vector> baseContracts; @@ -341,9 +342,9 @@ ASTPointer ASTJsonImporter::createContractDefinition(Json::V return createASTNode( _node, - std::make_shared(_node["name"].asString()), + std::make_shared(_node["name"].get()), createNameSourceLocation(_node), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, baseContracts, subNodes, contractKind(_node), @@ -351,14 +352,14 @@ ASTPointer ASTJsonImporter::createContractDefinition(Json::V ); } -ASTPointer ASTJsonImporter::createIdentifierPath(Json::Value const& _node) +ASTPointer ASTJsonImporter::createIdentifierPath(Json const& _node) { - astAssert(_node["name"].isString(), "Expected 'name' to be a string!"); + astAssert(_node["name"].is_string(), "Expected 'name' to be a string!"); std::vector namePath; std::vector namePathLocations; std::vector strs; - std::string nameString = member(_node, "name").asString(); + std::string nameString = member(_node, "name").get(); boost::algorithm::split(strs, nameString, boost::is_any_of(".")); astAssert(!strs.empty(), "Expected at least one element in IdentifierPath."); for (std::string s: strs) @@ -367,9 +368,9 @@ ASTPointer ASTJsonImporter::createIdentifierPath(Json::Value con namePath.emplace_back(s); } - if (_node.isMember("nameLocations") && _node["nameLocations"].isArray()) + if (_node.contains("nameLocations") && _node["nameLocations"].is_array()) for (auto const& val: _node["nameLocations"]) - namePathLocations.emplace_back(langutil::parseSourceLocation(val.asString(), m_sourceNames)); + namePathLocations.emplace_back(langutil::parseSourceLocation(val.get(), m_sourceNames)); else namePathLocations.resize(namePath.size()); @@ -385,7 +386,7 @@ ASTPointer ASTJsonImporter::createIdentifierPath(Json::Value con ); } -ASTPointer ASTJsonImporter::createInheritanceSpecifier(Json::Value const& _node) +ASTPointer ASTJsonImporter::createInheritanceSpecifier(Json const& _node) { std::vector> arguments; for (auto& arg: member(_node, "arguments")) @@ -393,36 +394,36 @@ ASTPointer ASTJsonImporter::createInheritanceSpecifier(Jso return createASTNode( _node, createIdentifierPath(member(_node, "baseName")), - member(_node, "arguments").isNull() ? nullptr : std::make_unique>>(arguments) + member(_node, "arguments").is_null() ? nullptr : std::make_unique>>(arguments) ); } -ASTPointer ASTJsonImporter::createUsingForDirective(Json::Value const& _node) +ASTPointer ASTJsonImporter::createUsingForDirective(Json const& _node) { std::vector> functions; std::vector> operators; - if (_node.isMember("libraryName")) + if (_node.contains("libraryName")) { - astAssert(!_node["libraryName"].isArray()); - astAssert(!_node["libraryName"]["operator"]); + astAssert(!_node["libraryName"].is_array()); + astAssert(!_node["libraryName"].contains("operator")); functions.emplace_back(createIdentifierPath(_node["libraryName"])); operators.emplace_back(std::nullopt); } - else if (_node.isMember("functionList")) - for (Json::Value const& function: _node["functionList"]) + else if (_node.contains("functionList")) + for (Json const& function: _node["functionList"]) { - if (function.isMember("function")) + if (function.contains("function")) { - astAssert(!function.isMember("operator")); - astAssert(!function.isMember("definition")); + astAssert(!function.contains("operator")); + astAssert(!function.contains("definition")); functions.emplace_back(createIdentifierPath(function["function"])); operators.emplace_back(std::nullopt); } else { - astAssert(function.isMember("operator")); - astAssert(function.isMember("definition")); + astAssert(function.contains("operator")); + astAssert(function.contains("definition")); Token const operatorName = scanSingleToken(function["operator"]); astAssert(util::contains(frontend::userDefinableOperators, operatorName)); @@ -436,13 +437,13 @@ ASTPointer ASTJsonImporter::createUsingForDirective(Json::Val _node, std::move(functions), std::move(operators), - !_node.isMember("libraryName"), - _node["typeName"].isNull() ? nullptr : convertJsonToASTNode(_node["typeName"]), + !_node.contains("libraryName"), + (_node.contains("typeName") && !_node["typeName"].is_null()) ? convertJsonToASTNode(_node["typeName"]) : nullptr, memberAsBool(_node, "global") ); } -ASTPointer ASTJsonImporter::createStructDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createStructDefinition(Json const& _node) { std::vector> members; for (auto& member: _node["members"]) @@ -452,11 +453,11 @@ ASTPointer ASTJsonImporter::createStructDefinition(Json::Value const& _ memberAsASTString(_node, "name"), createNameSourceLocation(_node), members, - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")) + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr ); } -ASTPointer ASTJsonImporter::createEnumDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createEnumDefinition(Json const& _node) { std::vector> members; for (auto& member: _node["members"]) @@ -466,11 +467,11 @@ ASTPointer ASTJsonImporter::createEnumDefinition(Json::Value con memberAsASTString(_node, "name"), createNameSourceLocation(_node), members, - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")) + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr ); } -ASTPointer ASTJsonImporter::createEnumValue(Json::Value const& _node) +ASTPointer ASTJsonImporter::createEnumValue(Json const& _node) { return createASTNode( _node, @@ -478,7 +479,7 @@ ASTPointer ASTJsonImporter::createEnumValue(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createUserDefinedValueTypeDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createUserDefinedValueTypeDefinition(Json const& _node) { return createASTNode( _node, @@ -488,7 +489,7 @@ ASTPointer ASTJsonImporter::createUserDefinedVal ); } -ASTPointer ASTJsonImporter::createParameterList(Json::Value const& _node) +ASTPointer ASTJsonImporter::createParameterList(Json const& _node) { std::vector> parameters; for (auto& param: _node["parameters"]) @@ -499,12 +500,13 @@ ASTPointer ASTJsonImporter::createParameterList(Json::Value const ); } -ASTPointer ASTJsonImporter::createOverrideSpecifier(Json::Value const& _node) +ASTPointer ASTJsonImporter::createOverrideSpecifier(Json const& _node) { std::vector> overrides; - for (auto& param: _node["overrides"]) - overrides.push_back(createIdentifierPath(param)); + if ( _node.contains("overrides")) + for (auto& param: _node["overrides"]) + overrides.push_back(createIdentifierPath(param)); return createASTNode( _node, @@ -512,13 +514,13 @@ ASTPointer ASTJsonImporter::createOverrideSpecifier(Json::Val ); } -ASTPointer ASTJsonImporter::createFunctionDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createFunctionDefinition(Json const& _node) { - astAssert(_node["kind"].isString(), "Expected 'kind' to be a string!"); + astAssert(_node["kind"].is_string(), "Expected 'kind' to be a string!"); Token kind; bool freeFunction = false; - std::string kindStr = member(_node, "kind").asString(); + std::string kindStr = member(_node, "kind").get(); if (kindStr == "constructor") kind = Token::Constructor; @@ -555,8 +557,8 @@ ASTPointer ASTJsonImporter::createFunctionDefinition(Json::V freeFunction, kind, memberAsBool(_node, "virtual"), - _node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), + (_node.contains("overrides") && !_node["overrides"].is_null()) ? createOverrideSpecifier(member(_node, "overrides")) : nullptr, + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, createParameterList(member(_node, "parameters")), modifiers, createParameterList(member(_node, "returnParameters")), @@ -564,13 +566,13 @@ ASTPointer ASTJsonImporter::createFunctionDefinition(Json::V ); } -ASTPointer ASTJsonImporter::createVariableDeclaration(Json::Value const& _node) +ASTPointer ASTJsonImporter::createVariableDeclaration(Json const& _node) { - astAssert(_node["name"].isString(), "Expected 'name' to be a string!"); + astAssert(_node["name"].is_string(), "Expected 'name' to be a string!"); VariableDeclaration::Mutability mutability{}; - astAssert(member(_node, "mutability").isString(), "'mutability' expected to be string."); - std::string const mutabilityStr = member(_node, "mutability").asString(); + astAssert(member(_node, "mutability").is_string(), "'mutability' expected to be string."); + std::string const mutabilityStr = member(_node, "mutability").get(); if (mutabilityStr == "constant") { mutability = VariableDeclaration::Mutability::Constant; @@ -590,33 +592,33 @@ ASTPointer ASTJsonImporter::createVariableDeclaration(Json: return createASTNode( _node, nullOrCast(member(_node, "typeName")), - std::make_shared(member(_node, "name").asString()), + std::make_shared(member(_node, "name").get()), createNameSourceLocation(_node), nullOrCast(member(_node, "value")), visibility(_node), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), - _node.isMember("indexed") ? memberAsBool(_node, "indexed") : false, + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, + (_node.contains("indexed") && !_node["indexed"].is_null()) ? memberAsBool(_node, "indexed") : false, mutability, - _node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")), + (_node.contains("overrides") && !_node["overrides"].is_null()) ? createOverrideSpecifier(member(_node, "overrides")) : nullptr, location(_node) ); } -ASTPointer ASTJsonImporter::createModifierDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createModifierDefinition(Json const& _node) { return createASTNode( _node, memberAsASTString(_node, "name"), createNameSourceLocation(_node), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, createParameterList(member(_node, "parameters")), memberAsBool(_node, "virtual"), - _node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")), - _node["body"].isNull() ? nullptr: createBlock(member(_node, "body"), false) + (_node.contains("overrides") && !_node["overrides"].is_null()) ? createOverrideSpecifier(member(_node, "overrides")) : nullptr, + (_node.contains("body") && !_node["body"].is_null()) ? createBlock(member(_node, "body"), false) : nullptr ); } -ASTPointer ASTJsonImporter::createModifierInvocation(Json::Value const& _node) +ASTPointer ASTJsonImporter::createModifierInvocation(Json const& _node) { std::vector> arguments; for (auto& arg: member(_node, "arguments")) @@ -624,53 +626,53 @@ ASTPointer ASTJsonImporter::createModifierInvocation(Json::V return createASTNode( _node, createIdentifierPath(member(_node, "modifierName")), - member(_node, "arguments").isNull() ? nullptr : std::make_unique>>(arguments) + member(_node, "arguments").is_null() ? nullptr : std::make_unique>>(arguments) ); } -ASTPointer ASTJsonImporter::createEventDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createEventDefinition(Json const& _node) { return createASTNode( _node, memberAsASTString(_node, "name"), createNameSourceLocation(_node), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, createParameterList(member(_node, "parameters")), memberAsBool(_node, "anonymous") ); } -ASTPointer ASTJsonImporter::createErrorDefinition(Json::Value const& _node) +ASTPointer ASTJsonImporter::createErrorDefinition(Json const& _node) { return createASTNode( _node, memberAsASTString(_node, "name"), createNameSourceLocation(_node), - _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")), + (_node.contains("documentation") && !_node["documentation"].is_null()) ? createDocumentation(member(_node, "documentation")) : nullptr, createParameterList(member(_node, "parameters")) ); } -ASTPointer ASTJsonImporter::createElementaryTypeName(Json::Value const& _node) +ASTPointer ASTJsonImporter::createElementaryTypeName(Json const& _node) { unsigned short firstNum; unsigned short secondNum; - astAssert(_node["name"].isString(), "Expected 'name' to be a string!"); + astAssert(_node["name"].is_string(), "Expected 'name' to be a string!"); - std::string name = member(_node, "name").asString(); + std::string name = member(_node, "name").get(); Token token; std::tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(name); ElementaryTypeNameToken elem(token, firstNum, secondNum); std::optional mutability = {}; - if (_node.isMember("stateMutability")) + if (_node.contains("stateMutability")) mutability = stateMutability(_node); return createASTNode(_node, elem, mutability); } -ASTPointer ASTJsonImporter::createUserDefinedTypeName(Json::Value const& _node) +ASTPointer ASTJsonImporter::createUserDefinedTypeName(Json const& _node) { return createASTNode( _node, @@ -678,7 +680,7 @@ ASTPointer ASTJsonImporter::createUserDefinedTypeName(Json: ); } -ASTPointer ASTJsonImporter::createFunctionTypeName(Json::Value const& _node) +ASTPointer ASTJsonImporter::createFunctionTypeName(Json const& _node) { return createASTNode( _node, @@ -689,7 +691,7 @@ ASTPointer ASTJsonImporter::createFunctionTypeName(Json::Value ); } -ASTPointer ASTJsonImporter::createMapping(Json::Value const& _node) +ASTPointer ASTJsonImporter::createMapping(Json const& _node) { return createASTNode( _node, @@ -702,7 +704,7 @@ ASTPointer ASTJsonImporter::createMapping(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createArrayTypeName(Json::Value const& _node) +ASTPointer ASTJsonImporter::createArrayTypeName(Json const& _node) { return createASTNode( _node, @@ -711,24 +713,24 @@ ASTPointer ASTJsonImporter::createArrayTypeName(Json::Value const ); } -ASTPointer ASTJsonImporter::createInlineAssembly(Json::Value const& _node) +ASTPointer ASTJsonImporter::createInlineAssembly(Json const& _node) { - astAssert(_node["evmVersion"].isString(), "Expected evmVersion to be a string!"); - auto evmVersion = langutil::EVMVersion::fromString(_node["evmVersion"].asString()); + astAssert(_node["evmVersion"].is_string(), "Expected evmVersion to be a string!"); + auto evmVersion = langutil::EVMVersion::fromString(_node["evmVersion"].get()); astAssert(evmVersion.has_value(), "Invalid EVM version!"); astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!"); yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value()); ASTPointer>> flags; - if (_node.isMember("flags")) + if (_node.contains("flags")) { flags = std::make_shared>>(); - Json::Value const& flagsNode = _node["flags"]; - astAssert(flagsNode.isArray(), "Assembly flags must be an array."); - for (Json::ArrayIndex i = 0; i < flagsNode.size(); ++i) + Json const& flagsNode = _node["flags"]; + astAssert(flagsNode.is_array(), "Assembly flags must be an array."); + for (auto const& flag: flagsNode) { - astAssert(flagsNode[i].isString(), "Assembly flag must be a string."); - flags->emplace_back(std::make_shared(flagsNode[i].asString())); + astAssert(flag.is_string(), "Assembly flag must be a string."); + flags->emplace_back(std::make_shared(flag.get())); } } std::shared_ptr operations = std::make_shared(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST"))); @@ -741,7 +743,7 @@ ASTPointer ASTJsonImporter::createInlineAssembly(Json::Value con ); } -ASTPointer ASTJsonImporter::createBlock(Json::Value const& _node, bool _unchecked) +ASTPointer ASTJsonImporter::createBlock(Json const& _node, bool _unchecked) { std::vector> statements; for (auto& stat: member(_node, "statements")) @@ -754,7 +756,7 @@ ASTPointer ASTJsonImporter::createBlock(Json::Value const& _node, bool _u ); } -ASTPointer ASTJsonImporter::createPlaceholderStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createPlaceholderStatement(Json const& _node) { return createASTNode( _node, @@ -762,7 +764,7 @@ ASTPointer ASTJsonImporter::createPlaceholderStatement(Jso ); } -ASTPointer ASTJsonImporter::createIfStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createIfStatement(Json const& _node) { return createASTNode( _node, @@ -773,7 +775,7 @@ ASTPointer ASTJsonImporter::createIfStatement(Json::Value const& _ ); } -ASTPointer ASTJsonImporter::createTryCatchClause(Json::Value const& _node) +ASTPointer ASTJsonImporter::createTryCatchClause(Json const& _node) { return createASTNode( _node, @@ -783,7 +785,7 @@ ASTPointer ASTJsonImporter::createTryCatchClause(Json::Value con ); } -ASTPointer ASTJsonImporter::createTryStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createTryStatement(Json const& _node) { std::vector> clauses; @@ -798,7 +800,7 @@ ASTPointer ASTJsonImporter::createTryStatement(Json::Value const& ); } -ASTPointer ASTJsonImporter::createWhileStatement(Json::Value const& _node, bool _isDoWhile=false) +ASTPointer ASTJsonImporter::createWhileStatement(Json const& _node, bool _isDoWhile=false) { return createASTNode( _node, @@ -809,7 +811,7 @@ ASTPointer ASTJsonImporter::createWhileStatement(Json::Value con ); } -ASTPointer ASTJsonImporter::createForStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createForStatement(Json const& _node) { return createASTNode( _node, @@ -821,7 +823,7 @@ ASTPointer ASTJsonImporter::createForStatement(Json::Value const& ); } -ASTPointer ASTJsonImporter::createContinue(Json::Value const& _node) +ASTPointer ASTJsonImporter::createContinue(Json const& _node) { return createASTNode( _node, @@ -829,7 +831,7 @@ ASTPointer ASTJsonImporter::createContinue(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createBreak(Json::Value const& _node) +ASTPointer ASTJsonImporter::createBreak(Json const& _node) { return createASTNode( _node, @@ -837,7 +839,7 @@ ASTPointer ASTJsonImporter::createBreak(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createReturn(Json::Value const& _node) +ASTPointer ASTJsonImporter::createReturn(Json const& _node) { return createASTNode( _node, @@ -846,7 +848,7 @@ ASTPointer ASTJsonImporter::createReturn(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createThrow(Json::Value const& _node) +ASTPointer ASTJsonImporter::createThrow(Json const& _node) { return createASTNode( _node, @@ -854,7 +856,7 @@ ASTPointer ASTJsonImporter::createThrow(Json::Value const& _node) ); } -ASTPointer ASTJsonImporter::createEmitStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createEmitStatement(Json const& _node) { return createASTNode( _node, @@ -863,7 +865,7 @@ ASTPointer ASTJsonImporter::createEmitStatement(Json::Value const ); } -ASTPointer ASTJsonImporter::createRevertStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createRevertStatement(Json const& _node) { return createASTNode( _node, @@ -872,11 +874,11 @@ ASTPointer ASTJsonImporter::createRevertStatement(Json::Value c ); } -ASTPointer ASTJsonImporter::createVariableDeclarationStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createVariableDeclarationStatement(Json const& _node) { std::vector> variables; for (auto& var: member(_node, "declarations")) - variables.push_back(var.isNull() ? nullptr : createVariableDeclaration(var)); //unnamed components are empty pointers + variables.push_back(var.is_null() ? nullptr : createVariableDeclaration(var)); //unnamed components are empty pointers return createASTNode( _node, nullOrASTString(_node, "documentation"), @@ -885,7 +887,7 @@ ASTPointer ASTJsonImporter::createVariableDeclarat ); } -ASTPointer ASTJsonImporter::createExpressionStatement(Json::Value const& _node) +ASTPointer ASTJsonImporter::createExpressionStatement(Json const& _node) { return createASTNode( _node, @@ -894,7 +896,7 @@ ASTPointer ASTJsonImporter::createExpressionStatement(Json: ); } -ASTPointer ASTJsonImporter::createConditional(Json::Value const& _node) +ASTPointer ASTJsonImporter::createConditional(Json const& _node) { return createASTNode( _node, @@ -904,7 +906,7 @@ ASTPointer ASTJsonImporter::createConditional(Json::Value const& _ ); } -ASTPointer ASTJsonImporter::createAssignment(Json::Value const& _node) +ASTPointer ASTJsonImporter::createAssignment(Json const& _node) { return createASTNode( _node, @@ -914,7 +916,7 @@ ASTPointer ASTJsonImporter::createAssignment(Json::Value const& _no ); } -ASTPointer ASTJsonImporter::createTupleExpression(Json::Value const& _node) +ASTPointer ASTJsonImporter::createTupleExpression(Json const& _node) { std::vector> components; for (auto& comp: member(_node, "components")) @@ -926,7 +928,7 @@ ASTPointer ASTJsonImporter::createTupleExpression(Json::Value c ); } -ASTPointer ASTJsonImporter::createUnaryOperation(Json::Value const& _node) +ASTPointer ASTJsonImporter::createUnaryOperation(Json const& _node) { return createASTNode( _node, @@ -936,7 +938,7 @@ ASTPointer ASTJsonImporter::createUnaryOperation(Json::Value con ); } -ASTPointer ASTJsonImporter::createBinaryOperation(Json::Value const& _node) +ASTPointer ASTJsonImporter::createBinaryOperation(Json const& _node) { return createASTNode( _node, @@ -946,7 +948,7 @@ ASTPointer ASTJsonImporter::createBinaryOperation(Json::Value c ); } -ASTPointer ASTJsonImporter::createFunctionCall(Json::Value const& _node) +ASTPointer ASTJsonImporter::createFunctionCall(Json const& _node) { std::vector> arguments; for (auto& arg: member(_node, "arguments")) @@ -954,8 +956,8 @@ ASTPointer ASTJsonImporter::createFunctionCall(Json::Value const& std::vector> names; for (auto& name: member(_node, "names")) { - astAssert(name.isString(), "Expected 'names' members to be strings!"); - names.push_back(std::make_shared(name.asString())); + astAssert(name.is_string(), "Expected 'names' members to be strings!"); + names.push_back(std::make_shared(name.get())); } std::optional> sourceLocations = createSourceLocations(_node); @@ -971,7 +973,7 @@ ASTPointer ASTJsonImporter::createFunctionCall(Json::Value const& ); } -ASTPointer ASTJsonImporter::createFunctionCallOptions(Json::Value const& _node) +ASTPointer ASTJsonImporter::createFunctionCallOptions(Json const& _node) { std::vector> options; for (auto& option: member(_node, "options")) @@ -979,8 +981,8 @@ ASTPointer ASTJsonImporter::createFunctionCallOptions(Json: std::vector> names; for (auto& name: member(_node, "names")) { - astAssert(name.isString(), "Expected 'names' members to be strings!"); - names.push_back(std::make_shared(name.asString())); + astAssert(name.is_string(), "Expected 'names' members to be strings!"); + names.push_back(std::make_shared(name.get())); } return createASTNode( @@ -991,7 +993,7 @@ ASTPointer ASTJsonImporter::createFunctionCallOptions(Json: ); } -ASTPointer ASTJsonImporter::createNewExpression(Json::Value const& _node) +ASTPointer ASTJsonImporter::createNewExpression(Json const& _node) { return createASTNode( _node, @@ -999,11 +1001,11 @@ ASTPointer ASTJsonImporter::createNewExpression(Json::Value const ); } -ASTPointer ASTJsonImporter::createMemberAccess(Json::Value const& _node) +ASTPointer ASTJsonImporter::createMemberAccess(Json const& _node) { SourceLocation memberLocation; - if (member(_node, "memberLocation").isString()) - memberLocation = solidity::langutil::parseSourceLocation(_node["memberLocation"].asString(), m_sourceNames); + if (member(_node, "memberLocation").is_string()) + memberLocation = solidity::langutil::parseSourceLocation(_node["memberLocation"].get(), m_sourceNames); return createASTNode( _node, @@ -1013,7 +1015,7 @@ ASTPointer ASTJsonImporter::createMemberAccess(Json::Value const& ); } -ASTPointer ASTJsonImporter::createIndexAccess(Json::Value const& _node) +ASTPointer ASTJsonImporter::createIndexAccess(Json const& _node) { return createASTNode( _node, @@ -1022,7 +1024,7 @@ ASTPointer ASTJsonImporter::createIndexAccess(Json::Value const& _n ); } -ASTPointer ASTJsonImporter::createIndexRangeAccess(Json::Value const& _node) +ASTPointer ASTJsonImporter::createIndexRangeAccess(Json const& _node) { return createASTNode( _node, @@ -1032,12 +1034,12 @@ ASTPointer ASTJsonImporter::createIndexRangeAccess(Json::Value ); } -ASTPointer ASTJsonImporter::createIdentifier(Json::Value const& _node) +ASTPointer ASTJsonImporter::createIdentifier(Json const& _node) { return createASTNode(_node, memberAsASTString(_node, "name")); } -ASTPointer ASTJsonImporter::createElementaryTypeNameExpression(Json::Value const& _node) +ASTPointer ASTJsonImporter::createElementaryTypeNameExpression(Json const& _node) { return createASTNode( _node, @@ -1045,116 +1047,116 @@ ASTPointer ASTJsonImporter::createElementaryTypeNa ); } -ASTPointer ASTJsonImporter::createLiteral(Json::Value const& _node) +ASTPointer ASTJsonImporter::createLiteral(Json const& _node) { static std::string const valStr = "value"; static std::string const hexValStr = "hexValue"; - astAssert(member(_node, valStr).isString() || member(_node, hexValStr).isString(), "Literal-value is unset."); + astAssert(member(_node, valStr).is_string() || member(_node, hexValStr).is_string(), "Literal-value is unset."); - ASTPointer value = _node.isMember(hexValStr) ? - std::make_shared(util::asString(util::fromHex(_node[hexValStr].asString()))) : - std::make_shared(_node[valStr].asString()); + ASTPointer value = _node.contains(hexValStr) ? + std::make_shared(util::asString(util::fromHex(_node[hexValStr].get()))) : + std::make_shared(_node[valStr].get()); return createASTNode( _node, literalTokenKind(_node), value, - member(_node, "subdenomination").isNull() ? Literal::SubDenomination::None : subdenomination(_node) + member(_node, "subdenomination").is_null() ? Literal::SubDenomination::None : subdenomination(_node) ); } -ASTPointer ASTJsonImporter::createDocumentation(Json::Value const& _node) +ASTPointer ASTJsonImporter::createDocumentation(Json const& _node) { static std::string const textString = "text"; - astAssert(member(_node, textString).isString(), "'text' must be a string"); + astAssert(member(_node, textString).is_string(), "'text' must be a string"); return createASTNode( _node, - std::make_shared(_node[textString].asString()) + std::make_shared(_node[textString].get()) ); } // ===== helper functions ========== -Json::Value ASTJsonImporter::member(Json::Value const& _node, std::string const& _name) +Json ASTJsonImporter::member(Json const& _node, std::string const& _name) { - if (!_node.isMember(_name)) - return Json::nullValue; + if (!_node.contains(_name)) + return Json(); return _node[_name]; } -Token ASTJsonImporter::scanSingleToken(Json::Value const& _node) +Token ASTJsonImporter::scanSingleToken(Json const& _node) { - langutil::CharStream charStream(_node.asString(), ""); + langutil::CharStream charStream(_node.get(), ""); langutil::Scanner scanner{charStream}; astAssert(scanner.peekNextToken() == Token::EOS, "Token string is too long."); return scanner.currentToken(); } -ASTPointer ASTJsonImporter::nullOrASTString(Json::Value const& _json, std::string const& _name) +ASTPointer ASTJsonImporter::nullOrASTString(Json const& _json, std::string const& _name) { - return _json[_name].isString() ? memberAsASTString(_json, _name) : nullptr; + return (_json.contains(_name) && (_json[_name].is_string())) ? memberAsASTString(_json, _name) : nullptr; } -ASTPointer ASTJsonImporter::memberAsASTString(Json::Value const& _node, std::string const& _name) +ASTPointer ASTJsonImporter::memberAsASTString(Json const& _node, std::string const& _name) { - Json::Value value = member(_node, _name); - astAssert(value.isString(), "field " + _name + " must be of type string."); - return std::make_shared(_node[_name].asString()); + Json value = member(_node, _name); + astAssert(value.is_string(), "field " + _name + " must be of type string."); + return std::make_shared(_node[_name].get()); } -bool ASTJsonImporter::memberAsBool(Json::Value const& _node, std::string const& _name) +bool ASTJsonImporter::memberAsBool(Json const& _node, std::string const& _name) { - Json::Value value = member(_node, _name); - astAssert(value.isBool(), "field " + _name + " must be of type boolean."); - return _node[_name].asBool(); + Json value = member(_node, _name); + astAssert(value.is_boolean(), "field " + _name + " must be of type boolean."); + return _node[_name].get(); } // =========== JSON to definition helpers ======================= -ContractKind ASTJsonImporter::contractKind(Json::Value const& _node) +ContractKind ASTJsonImporter::contractKind(Json const& _node) { ContractKind kind; - astAssert(!member(_node, "contractKind").isNull(), "'Contract-kind' can not be null."); - if (_node["contractKind"].asString() == "interface") + astAssert(!member(_node, "contractKind").is_null(), "'Contract-kind' can not be null."); + if (_node["contractKind"].get() == "interface") kind = ContractKind::Interface; - else if (_node["contractKind"].asString() == "contract") + else if (_node["contractKind"].get() == "contract") kind = ContractKind::Contract; - else if (_node["contractKind"].asString() == "library") + else if (_node["contractKind"].get() == "library") kind = ContractKind::Library; else astAssert(false, "Unknown ContractKind"); return kind; } -Token ASTJsonImporter::literalTokenKind(Json::Value const& _node) +Token ASTJsonImporter::literalTokenKind(Json const& _node) { - astAssert(member(_node, "kind").isString(), "Token-'kind' expected to be a string."); + astAssert(member(_node, "kind").is_string(), "Token-'kind' expected to be a string."); Token tok; - if (_node["kind"].asString() == "number") + if (_node["kind"].get() == "number") tok = Token::Number; - else if (_node["kind"].asString() == "string") + else if (_node["kind"].get() == "string") tok = Token::StringLiteral; - else if (_node["kind"].asString() == "unicodeString") + else if (_node["kind"].get() == "unicodeString") tok = Token::UnicodeStringLiteral; - else if (_node["kind"].asString() == "hexString") + else if (_node["kind"].get() == "hexString") tok = Token::HexStringLiteral; - else if (_node["kind"].asString() == "bool") - tok = (member(_node, "value").asString() == "true") ? Token::TrueLiteral : Token::FalseLiteral; + else if (_node["kind"].get() == "bool") + tok = (member(_node, "value").get() == "true") ? Token::TrueLiteral : Token::FalseLiteral; else astAssert(false, "Unknown kind of literalString"); return tok; } -Visibility ASTJsonImporter::visibility(Json::Value const& _node) +Visibility ASTJsonImporter::visibility(Json const& _node) { - Json::Value visibility = member(_node, "visibility"); - astAssert(visibility.isString(), "'visibility' expected to be a string."); + Json visibility = member(_node, "visibility"); + astAssert(visibility.is_string(), "'visibility' expected to be a string."); - std::string const visibilityStr = visibility.asString(); + std::string const visibilityStr = visibility.get(); if (visibilityStr == "default") return Visibility::Default; @@ -1173,12 +1175,12 @@ Visibility ASTJsonImporter::visibility(Json::Value const& _node) util::unreachable(); } -VariableDeclaration::Location ASTJsonImporter::location(Json::Value const& _node) +VariableDeclaration::Location ASTJsonImporter::location(Json const& _node) { - Json::Value storageLoc = member(_node, "storageLocation"); - astAssert(storageLoc.isString(), "'storageLocation' expected to be a string."); + Json storageLoc = member(_node, "storageLocation"); + astAssert(storageLoc.is_string(), "'storageLocation' expected to be a string."); - std::string const storageLocStr = storageLoc.asString(); + std::string const storageLocStr = storageLoc.get(); if (storageLocStr == "default") return VariableDeclaration::Location::Unspecified; @@ -1195,16 +1197,16 @@ VariableDeclaration::Location ASTJsonImporter::location(Json::Value const& _node util::unreachable(); } -Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _node) +Literal::SubDenomination ASTJsonImporter::subdenomination(Json const& _node) { - Json::Value subDen = member(_node, "subdenomination"); + Json subDen = member(_node, "subdenomination"); - if (subDen.isNull()) + if (subDen.is_null()) return Literal::SubDenomination::None; - astAssert(subDen.isString(), "'subDenomination' expected to be string."); + astAssert(subDen.is_string(), "'subDenomination' expected to be string."); - std::string const subDenStr = subDen.asString(); + std::string const subDenStr = subDen.get(); if (subDenStr == "wei") return Literal::SubDenomination::Wei; @@ -1231,10 +1233,10 @@ Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _no util::unreachable(); } -StateMutability ASTJsonImporter::stateMutability(Json::Value const& _node) +StateMutability ASTJsonImporter::stateMutability(Json const& _node) { - astAssert(member(_node, "stateMutability").isString(), "StateMutability' expected to be string."); - std::string const mutabilityStr = member(_node, "stateMutability").asString(); + astAssert(member(_node, "stateMutability").is_string(), "StateMutability' expected to be string."); + std::string const mutabilityStr = member(_node, "stateMutability").get(); if (mutabilityStr == "pure") return StateMutability::Pure; diff --git a/libsolidity/ast/ASTJsonImporter.h b/libsolidity/ast/ASTJsonImporter.h index b9a4d4950..943415df9 100644 --- a/libsolidity/ast/ASTJsonImporter.h +++ b/libsolidity/ast/ASTJsonImporter.h @@ -24,8 +24,8 @@ #pragma once #include +#include #include -#include #include #include #include @@ -47,7 +47,7 @@ class ASTJsonImporter /// Converts the AST from JSON-format to ASTPointer /// @a _sourceList used to provide source names for the ASTs /// @returns map of sourcenames to their respective ASTs - std::map> jsonToSourceUnit(std::map const& _sourceList); + std::map> jsonToSourceUnit(std::map const& _sourceList); private: @@ -56,105 +56,105 @@ class ASTJsonImporter /// Sets the source location and nodeID /// @returns the ASTNode Object class of the respective JSON node, template - ASTPointer createASTNode(Json::Value const& _node, Args&&... _args); + ASTPointer createASTNode(Json const& _node, Args&&... _args); /// @returns the sourceLocation-object created from the string in the JSON node - langutil::SourceLocation const createSourceLocation(Json::Value const& _node); - std::optional> createSourceLocations(Json::Value const& _node) const; + langutil::SourceLocation const createSourceLocation(Json const& _node); + std::optional> createSourceLocations(Json const& _node) const; /// Creates an ASTNode for a given JSON-ast of unknown type /// @returns Pointer to a new created ASTNode - ASTPointer convertJsonToASTNode(Json::Value const& _ast); + ASTPointer convertJsonToASTNode(Json const& _ast); /// @returns a pointer to the more specific subclass of ASTNode /// as indicated by the nodeType field of the json template - ASTPointer convertJsonToASTNode(Json::Value const& _node); + ASTPointer convertJsonToASTNode(Json const& _node); - langutil::SourceLocation createNameSourceLocation(Json::Value const& _node); + langutil::SourceLocation createNameSourceLocation(Json const& _node); /// @returns source location of a mapping key name - langutil::SourceLocation createKeyNameSourceLocation(Json::Value const& _node); + langutil::SourceLocation createKeyNameSourceLocation(Json const& _node); /// @returns source location of a mapping value name - langutil::SourceLocation createValueNameSourceLocation(Json::Value const& _node); + langutil::SourceLocation createValueNameSourceLocation(Json const& _node); /// \defgroup nodeCreators JSON to AST-Nodes ///@{ - ASTPointer createSourceUnit(Json::Value const& _node, std::string const& _srcName); - ASTPointer createPragmaDirective(Json::Value const& _node); - ASTPointer createImportDirective(Json::Value const& _node); - ASTPointer createContractDefinition(Json::Value const& _node); - ASTPointer createIdentifierPath(Json::Value const& _node); - ASTPointer createInheritanceSpecifier(Json::Value const& _node); - ASTPointer createUsingForDirective(Json::Value const& _node); - ASTPointer createStructDefinition(Json::Value const& _node); - ASTPointer createEnumDefinition(Json::Value const& _node); - ASTPointer createEnumValue(Json::Value const& _node); - ASTPointer createUserDefinedValueTypeDefinition(Json::Value const& _node); - ASTPointer createParameterList(Json::Value const& _node); - ASTPointer createOverrideSpecifier(Json::Value const& _node); - ASTPointer createFunctionDefinition(Json::Value const& _node); - ASTPointer createVariableDeclaration(Json::Value const& _node); - ASTPointer createModifierDefinition(Json::Value const& _node); - ASTPointer createModifierInvocation(Json::Value const& _node); - ASTPointer createEventDefinition(Json::Value const& _node); - ASTPointer createErrorDefinition(Json::Value const& _node); - ASTPointer createElementaryTypeName(Json::Value const& _node); - ASTPointer createUserDefinedTypeName(Json::Value const& _node); - ASTPointer createFunctionTypeName(Json::Value const& _node); - ASTPointer createMapping(Json::Value const& _node); - ASTPointer createArrayTypeName(Json::Value const& _node); - ASTPointer createInlineAssembly(Json::Value const& _node); - ASTPointer createBlock(Json::Value const& _node, bool _unchecked); - ASTPointer createPlaceholderStatement(Json::Value const& _node); - ASTPointer createIfStatement(Json::Value const& _node); - ASTPointer createTryCatchClause(Json::Value const& _node); - ASTPointer createTryStatement(Json::Value const& _node); - ASTPointer createWhileStatement(Json::Value const& _node, bool _isDoWhile); - ASTPointer createForStatement(Json::Value const& _node); - ASTPointer createContinue(Json::Value const& _node); - ASTPointer createBreak(Json::Value const& _node); - ASTPointer createReturn(Json::Value const& _node); - ASTPointer createThrow(Json::Value const& _node); - ASTPointer createEmitStatement(Json::Value const& _node); - ASTPointer createRevertStatement(Json::Value const& _node); - ASTPointer createVariableDeclarationStatement(Json::Value const& _node); - ASTPointer createExpressionStatement(Json::Value const& _node); - ASTPointer createConditional(Json::Value const& _node); - ASTPointer createAssignment(Json::Value const& _node); - ASTPointer createTupleExpression(Json::Value const& _node); - ASTPointer createUnaryOperation(Json::Value const& _node); - ASTPointer createBinaryOperation(Json::Value const& _node); - ASTPointer createFunctionCall(Json::Value const& _node); - ASTPointer createFunctionCallOptions(Json::Value const& _node); - ASTPointer createNewExpression(Json::Value const& _node); - ASTPointer createMemberAccess(Json::Value const& _node); - ASTPointer createIndexAccess(Json::Value const& _node); - ASTPointer createIndexRangeAccess(Json::Value const& _node); - ASTPointer createIdentifier(Json::Value const& _node); - ASTPointer createElementaryTypeNameExpression(Json::Value const& _node); - ASTPointer createLiteral(Json::Value const& _node); - ASTPointer createDocumentation(Json::Value const& _node); + ASTPointer createSourceUnit(Json const& _node, std::string const& _srcName); + ASTPointer createPragmaDirective(Json const& _node); + ASTPointer createImportDirective(Json const& _node); + ASTPointer createContractDefinition(Json const& _node); + ASTPointer createIdentifierPath(Json const& _node); + ASTPointer createInheritanceSpecifier(Json const& _node); + ASTPointer createUsingForDirective(Json const& _node); + ASTPointer createStructDefinition(Json const& _node); + ASTPointer createEnumDefinition(Json const& _node); + ASTPointer createEnumValue(Json const& _node); + ASTPointer createUserDefinedValueTypeDefinition(Json const& _node); + ASTPointer createParameterList(Json const& _node); + ASTPointer createOverrideSpecifier(Json const& _node); + ASTPointer createFunctionDefinition(Json const& _node); + ASTPointer createVariableDeclaration(Json const& _node); + ASTPointer createModifierDefinition(Json const& _node); + ASTPointer createModifierInvocation(Json const& _node); + ASTPointer createEventDefinition(Json const& _node); + ASTPointer createErrorDefinition(Json const& _node); + ASTPointer createElementaryTypeName(Json const& _node); + ASTPointer createUserDefinedTypeName(Json const& _node); + ASTPointer createFunctionTypeName(Json const& _node); + ASTPointer createMapping(Json const& _node); + ASTPointer createArrayTypeName(Json const& _node); + ASTPointer createInlineAssembly(Json const& _node); + ASTPointer createBlock(Json const& _node, bool _unchecked); + ASTPointer createPlaceholderStatement(Json const& _node); + ASTPointer createIfStatement(Json const& _node); + ASTPointer createTryCatchClause(Json const& _node); + ASTPointer createTryStatement(Json const& _node); + ASTPointer createWhileStatement(Json const& _node, bool _isDoWhile); + ASTPointer createForStatement(Json const& _node); + ASTPointer createContinue(Json const& _node); + ASTPointer createBreak(Json const& _node); + ASTPointer createReturn(Json const& _node); + ASTPointer createThrow(Json const& _node); + ASTPointer createEmitStatement(Json const& _node); + ASTPointer createRevertStatement(Json const& _node); + ASTPointer createVariableDeclarationStatement(Json const& _node); + ASTPointer createExpressionStatement(Json const& _node); + ASTPointer createConditional(Json const& _node); + ASTPointer createAssignment(Json const& _node); + ASTPointer createTupleExpression(Json const& _node); + ASTPointer createUnaryOperation(Json const& _node); + ASTPointer createBinaryOperation(Json const& _node); + ASTPointer createFunctionCall(Json const& _node); + ASTPointer createFunctionCallOptions(Json const& _node); + ASTPointer createNewExpression(Json const& _node); + ASTPointer createMemberAccess(Json const& _node); + ASTPointer createIndexAccess(Json const& _node); + ASTPointer createIndexRangeAccess(Json const& _node); + ASTPointer createIdentifier(Json const& _node); + ASTPointer createElementaryTypeNameExpression(Json const& _node); + ASTPointer createLiteral(Json const& _node); + ASTPointer createDocumentation(Json const& _node); ///@} // =============== general helper functions =================== /// @returns the member of a given JSON object, throws if member does not exist - Json::Value member(Json::Value const& _node, std::string const& _name); + Json member(Json const& _node, std::string const& _name); /// @returns the appropriate TokenObject used in parsed Strings (pragma directive or operator) - Token scanSingleToken(Json::Value const& _node); + Token scanSingleToken(Json const& _node); template ///@returns nullptr or an ASTPointer cast to a specific Class - ASTPointer nullOrCast(Json::Value const& _json); + ASTPointer nullOrCast(Json const& _json); /// @returns nullptr or ASTString, given an JSON string or an empty field - ASTPointer nullOrASTString(Json::Value const& _json, std::string const& _name); + ASTPointer nullOrASTString(Json const& _json, std::string const& _name); // ============== JSON to definition helpers =============== /// \defgroup typeHelpers Json to ast-datatype helpers /// {@ - ASTPointer memberAsASTString(Json::Value const& _node, std::string const& _name); - bool memberAsBool(Json::Value const& _node, std::string const& _name); - Visibility visibility(Json::Value const& _node); - StateMutability stateMutability(Json::Value const& _node); - VariableDeclaration::Location location(Json::Value const& _node); - ContractKind contractKind(Json::Value const& _node); - Token literalTokenKind(Json::Value const& _node); - Literal::SubDenomination subdenomination(Json::Value const& _node); + ASTPointer memberAsASTString(Json const& _node, std::string const& _name); + bool memberAsBool(Json const& _node, std::string const& _name); + Visibility visibility(Json const& _node); + StateMutability stateMutability(Json const& _node); + VariableDeclaration::Location location(Json const& _node); + ContractKind contractKind(Json const& _node); + Token literalTokenKind(Json const& _node); + Literal::SubDenomination subdenomination(Json const& _node); ///@} // =========== member variables =============== diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index a80a18a62..8e03a378b 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -37,6 +37,7 @@ #include #include #include +#include namespace solidity::frontend { diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index b84fbc357..59585c762 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -37,8 +37,7 @@ #include #include #include - -#include +#include #include #include diff --git a/libsolidity/codegen/ir/IRGenerator.h b/libsolidity/codegen/ir/IRGenerator.h index 9026954d6..9f01b74fc 100644 --- a/libsolidity/codegen/ir/IRGenerator.h +++ b/libsolidity/codegen/ir/IRGenerator.h @@ -23,6 +23,8 @@ #pragma once +#include + #include #include #include @@ -32,8 +34,6 @@ #include #include -#include - #include namespace solidity::frontend diff --git a/libsolidity/experimental/codegen/IRGenerator.h b/libsolidity/experimental/codegen/IRGenerator.h index 7d3baf8f9..5da6f9f6f 100644 --- a/libsolidity/experimental/codegen/IRGenerator.h +++ b/libsolidity/experimental/codegen/IRGenerator.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include diff --git a/libsolidity/formal/BMC.h b/libsolidity/formal/BMC.h index 9daa16837..1f97cbeef 100644 --- a/libsolidity/formal/BMC.h +++ b/libsolidity/formal/BMC.h @@ -41,6 +41,7 @@ #include #include #include +#include using solidity::util::h256; diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp index cf6e863bb..e06f4b582 100644 --- a/libsolidity/interface/ABI.cpp +++ b/libsolidity/interface/ABI.cpp @@ -38,12 +38,14 @@ bool anyDataStoredInStorage(TypePointers const& _pointers) } } -Json::Value ABI::generate(ContractDefinition const& _contractDef) +Json ABI::generate(ContractDefinition const& _contractDef) { - auto compare = [](Json::Value const& _a, Json::Value const& _b) -> bool { - return std::make_tuple(_a["type"], _a["name"]) < std::make_tuple(_b["type"], _b["name"]); + auto compare = [](Json const& _a, Json const& _b) -> bool + { + return std::make_tuple(_a.value("type", Json()), _a.value("name", Json())) < + std::make_tuple(_b.value("type", Json()), _b.value("name", Json())); }; - std::multiset abi(compare); + std::multiset abi(compare); for (auto it: _contractDef.interfaceFunctions()) { @@ -55,7 +57,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) FunctionType const* externalFunctionType = it.second->interfaceFunctionType(); solAssert(!!externalFunctionType, ""); - Json::Value method{Json::objectValue}; + Json method; method["type"] = "function"; method["name"] = it.second->declaration().name(); method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); @@ -79,7 +81,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) FunctionType constrType(*constructor); FunctionType const* externalFunctionType = constrType.interfaceFunctionType(); solAssert(!!externalFunctionType, ""); - Json::Value method{Json::objectValue}; + Json method; method["type"] = "constructor"; method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); method["inputs"] = formatTypeList( @@ -95,25 +97,25 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) { auto const* externalFunctionType = FunctionType(*fallbackOrReceive).interfaceFunctionType(); solAssert(!!externalFunctionType, ""); - Json::Value method{Json::objectValue}; + Json method; method["type"] = TokenTraits::toString(fallbackOrReceive->kind()); method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); abi.emplace(std::move(method)); } for (auto const& it: _contractDef.interfaceEvents()) { - Json::Value event{Json::objectValue}; + Json event; event["type"] = "event"; event["name"] = it->name(); event["anonymous"] = it->isAnonymous(); - Json::Value params{Json::arrayValue}; + Json params = Json::array(); for (auto const& p: it->parameters()) { Type const* type = p->annotation().type->interfaceType(false); solAssert(type, ""); auto param = formatType(p->name(), *type, *p->annotation().type, false); param["indexed"] = p->isIndexed(); - params.append(std::move(param)); + params.emplace_back(param); } event["inputs"] = std::move(params); abi.emplace(std::move(event)); @@ -121,53 +123,53 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) for (ErrorDefinition const* error: _contractDef.interfaceErrors()) { - Json::Value errorJson{Json::objectValue}; + Json errorJson; errorJson["type"] = "error"; errorJson["name"] = error->name(); - errorJson["inputs"] = Json::arrayValue; + errorJson["inputs"] = Json::array(); for (auto const& p: error->parameters()) { Type const* type = p->annotation().type->interfaceType(false); solAssert(type, ""); - errorJson["inputs"].append( + errorJson["inputs"].emplace_back( formatType(p->name(), *type, *p->annotation().type, false) ); } abi.emplace(std::move(errorJson)); } - Json::Value abiJson{Json::arrayValue}; + Json abiJson = Json::array(); for (auto& f: abi) - abiJson.append(std::move(f)); + abiJson.emplace_back(std::move(f)); return abiJson; } -Json::Value ABI::formatTypeList( +Json ABI::formatTypeList( std::vector const& _names, std::vector const& _encodingTypes, std::vector const& _solidityTypes, bool _forLibrary ) { - Json::Value params{Json::arrayValue}; + Json params = Json::array(); solAssert(_names.size() == _encodingTypes.size(), "Names and types vector size does not match"); solAssert(_names.size() == _solidityTypes.size(), ""); for (unsigned i = 0; i < _names.size(); ++i) { solAssert(_encodingTypes[i], ""); - params.append(formatType(_names[i], *_encodingTypes[i], *_solidityTypes[i], _forLibrary)); + params.emplace_back(formatType(_names[i], *_encodingTypes[i], *_solidityTypes[i], _forLibrary)); } return params; } -Json::Value ABI::formatType( +Json ABI::formatType( std::string const& _name, Type const& _encodingType, Type const& _solidityType, bool _forLibrary ) { - Json::Value ret{Json::objectValue}; + Json ret; ret["name"] = _name; ret["internalType"] = _solidityType.toString(true); std::string suffix = (_forLibrary && _encodingType.dataStoredIn(DataLocation::Storage)) ? " storage" : ""; @@ -185,31 +187,31 @@ Json::Value ABI::formatType( else suffix = std::string("[") + arrayType->length().str() + "]"; solAssert(arrayType->baseType(), ""); - Json::Value subtype = formatType( + Json subtype = formatType( "", *arrayType->baseType(), *dynamic_cast(_solidityType).baseType(), _forLibrary ); - if (subtype.isMember("components")) + if (subtype.contains("components")) { - ret["type"] = subtype["type"].asString() + suffix; + ret["type"] = subtype["type"].get() + suffix; ret["components"] = subtype["components"]; } else - ret["type"] = subtype["type"].asString() + suffix; + ret["type"] = subtype["type"].get() + suffix; } } else if (StructType const* structType = dynamic_cast(&_encodingType)) { ret["type"] = "tuple"; - ret["components"] = Json::arrayValue; + ret["components"] = Json::array(); for (auto const& member: structType->members(nullptr)) { solAssert(member.type, ""); Type const* t = member.type->interfaceType(_forLibrary); solAssert(t, ""); - ret["components"].append(formatType(member.name, *t, *member.type, _forLibrary)); + ret["components"].emplace_back(formatType(member.name, *t, *member.type, _forLibrary)); } } else diff --git a/libsolidity/interface/ABI.h b/libsolidity/interface/ABI.h index e95661449..22e306c43 100644 --- a/libsolidity/interface/ABI.h +++ b/libsolidity/interface/ABI.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include @@ -38,14 +38,14 @@ class ABI /// Get the ABI Interface of the contract /// @param _contractDef The contract definition /// @return A JSONrepresentation of the contract's ABI Interface - static Json::Value generate(ContractDefinition const& _contractDef); + static Json generate(ContractDefinition const& _contractDef); private: /// @returns a json value suitable for a list of types in function input or output /// parameters or other places. If @a _forLibrary is true, complex types are referenced /// by name, otherwise they are anonymously expanded. /// @a _solidityTypes is the list of original Solidity types where @a _encodingTypes is the list of /// ABI types used for the actual encoding. - static Json::Value formatTypeList( + static Json formatTypeList( std::vector const& _names, std::vector const& _encodingTypes, std::vector const& _solidityTypes, @@ -56,7 +56,7 @@ class ABI /// If it is possible to express the type as a single string, it is allowed to return a single string. /// @a _solidityType is the original Solidity type and @a _encodingTypes is the /// ABI type used for the actual encoding. - static Json::Value formatType( + static Json formatType( std::string const& _name, Type const& _encodingType, Type const& _solidityType, diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 2d1fd1074..2a9005680 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -85,8 +85,6 @@ #include #include -#include - #include #include @@ -426,7 +424,7 @@ bool CompilerStack::parse() return true; } -void CompilerStack::importASTs(std::map const& _sources) +void CompilerStack::importASTs(std::map const& _sources) { if (m_stackState != Empty) solThrow(CompilerError, "Must call importASTs only before the SourcesSet state."); @@ -843,18 +841,18 @@ evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(std::string con return currentContract.evmRuntimeAssembly ? ¤tContract.evmRuntimeAssembly->items() : nullptr; } -Json::Value CompilerStack::generatedSources(std::string const& _contractName, bool _runtime) const +Json CompilerStack::generatedSources(std::string const& _contractName, bool _runtime) const { if (m_stackState != CompilationSuccessful) solThrow(CompilerError, "Compilation was not successful."); Contract const& c = contract(_contractName); - util::LazyInit const& sources = + util::LazyInit const& sources = _runtime ? c.runtimeGeneratedSources : c.generatedSources; return sources.init([&]{ - Json::Value sources{Json::arrayValue}; + Json sources = Json::array(); // If there is no compiler, then no bytecode was generated and thus no // sources were generated (or we compiled "via IR"). if (c.compiler) @@ -947,7 +945,7 @@ std::string const& CompilerStack::yulIR(std::string const& _contractName) const return contract(_contractName).yulIR; } -Json::Value const& CompilerStack::yulIRAst(std::string const& _contractName) const +Json const& CompilerStack::yulIRAst(std::string const& _contractName) const { if (m_stackState != CompilationSuccessful) solThrow(CompilerError, "Compilation was not successful."); @@ -965,7 +963,7 @@ std::string const& CompilerStack::yulIROptimized(std::string const& _contractNam return contract(_contractName).yulIROptimized; } -Json::Value const& CompilerStack::yulIROptimizedAst(std::string const& _contractName) const +Json const& CompilerStack::yulIROptimizedAst(std::string const& _contractName) const { if (m_stackState != CompilationSuccessful) solThrow(CompilerError, "Compilation was not successful."); @@ -1005,7 +1003,7 @@ std::string CompilerStack::assemblyString(std::string const& _contractName, Stri } /// TODO: cache the JSON -Json::Value CompilerStack::assemblyJSON(std::string const& _contractName) const +Json CompilerStack::assemblyJSON(std::string const& _contractName) const { if (m_stackState != CompilationSuccessful) solThrow(CompilerError, "Compilation was not successful."); @@ -1016,7 +1014,7 @@ Json::Value CompilerStack::assemblyJSON(std::string const& _contractName) const if (currentContract.evmAssembly) return currentContract.evmAssembly->assemblyJSON(sourceIndices()); else - return Json::Value(); + return Json(); } std::vector CompilerStack::sourceNames() const @@ -1035,7 +1033,7 @@ std::map CompilerStack::sourceIndices() const return indices; } -Json::Value const& CompilerStack::contractABI(std::string const& _contractName) const +Json const& CompilerStack::contractABI(std::string const& _contractName) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1043,7 +1041,7 @@ Json::Value const& CompilerStack::contractABI(std::string const& _contractName) return contractABI(contract(_contractName)); } -Json::Value const& CompilerStack::contractABI(Contract const& _contract) const +Json const& CompilerStack::contractABI(Contract const& _contract) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1054,7 +1052,7 @@ Json::Value const& CompilerStack::contractABI(Contract const& _contract) const return _contract.abi.init([&]{ return ABI::generate(*_contract.contract); }); } -Json::Value const& CompilerStack::storageLayout(std::string const& _contractName) const +Json const& CompilerStack::storageLayout(std::string const& _contractName) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1062,7 +1060,7 @@ Json::Value const& CompilerStack::storageLayout(std::string const& _contractName return storageLayout(contract(_contractName)); } -Json::Value const& CompilerStack::storageLayout(Contract const& _contract) const +Json const& CompilerStack::storageLayout(Contract const& _contract) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1073,7 +1071,7 @@ Json::Value const& CompilerStack::storageLayout(Contract const& _contract) const return _contract.storageLayout.init([&]{ return StorageLayout().generate(*_contract.contract); }); } -Json::Value const& CompilerStack::natspecUser(std::string const& _contractName) const +Json const& CompilerStack::natspecUser(std::string const& _contractName) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1081,7 +1079,7 @@ Json::Value const& CompilerStack::natspecUser(std::string const& _contractName) return natspecUser(contract(_contractName)); } -Json::Value const& CompilerStack::natspecUser(Contract const& _contract) const +Json const& CompilerStack::natspecUser(Contract const& _contract) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1092,7 +1090,7 @@ Json::Value const& CompilerStack::natspecUser(Contract const& _contract) const return _contract.userDocumentation.init([&]{ return Natspec::userDocumentation(*_contract.contract); }); } -Json::Value const& CompilerStack::natspecDev(std::string const& _contractName) const +Json const& CompilerStack::natspecDev(std::string const& _contractName) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1100,7 +1098,7 @@ Json::Value const& CompilerStack::natspecDev(std::string const& _contractName) c return natspecDev(contract(_contractName)); } -Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const +Json const& CompilerStack::natspecDev(Contract const& _contract) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); @@ -1112,16 +1110,16 @@ Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const return _contract.devDocumentation.init([&]{ return Natspec::devDocumentation(*_contract.contract); }); } -Json::Value CompilerStack::interfaceSymbols(std::string const& _contractName) const +Json CompilerStack::interfaceSymbols(std::string const& _contractName) const { if (m_stackState < AnalysisSuccessful) solThrow(CompilerError, "Analysis was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); - Json::Value interfaceSymbols(Json::objectValue); + Json interfaceSymbols; // Always have a methods object - interfaceSymbols["methods"] = Json::objectValue; + interfaceSymbols["methods"] = Json::object(); for (auto const& it: contractDefinition(_contractName).interfaceFunctions()) interfaceSymbols["methods"][it.second->externalSignature()] = it.first.hex(); @@ -1650,7 +1648,7 @@ CompilerStack::Source const& CompilerStack::source(std::string const& _sourceNam std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR) const { - Json::Value meta{Json::objectValue}; + Json meta; meta["version"] = 1; std::string sourceType; switch (m_compilationSourceType) @@ -1671,7 +1669,7 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR for (auto const sourceUnit: _contract.contract->sourceUnit().referencedSourceUnits(true)) referencedSources.insert(*sourceUnit->annotation().path); - meta["sources"] = Json::objectValue; + meta["sources"] = Json::object(); for (auto const& s: m_sources) { if (!referencedSources.count(s.first)) @@ -1685,15 +1683,15 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR meta["sources"][s.first]["content"] = s.second.charStream->source(); else { - meta["sources"][s.first]["urls"] = Json::arrayValue; - meta["sources"][s.first]["urls"].append("bzz-raw://" + util::toHex(s.second.swarmHash().asBytes())); - meta["sources"][s.first]["urls"].append(s.second.ipfsUrl()); + meta["sources"][s.first]["urls"] = Json::array(); + meta["sources"][s.first]["urls"].emplace_back("bzz-raw://" + util::toHex(s.second.swarmHash().asBytes())); + meta["sources"][s.first]["urls"].emplace_back(s.second.ipfsUrl()); } } - static_assert(sizeof(m_optimiserSettings.expectedExecutionsPerDeployment) <= sizeof(Json::LargestUInt), "Invalid word size."); - solAssert(static_cast(m_optimiserSettings.expectedExecutionsPerDeployment) < std::numeric_limits::max(), ""); - meta["settings"]["optimizer"]["runs"] = Json::Value(Json::LargestUInt(m_optimiserSettings.expectedExecutionsPerDeployment)); + static_assert(sizeof(m_optimiserSettings.expectedExecutionsPerDeployment) <= sizeof(Json::number_integer_t), "Invalid word size."); + solAssert(static_cast(m_optimiserSettings.expectedExecutionsPerDeployment) < std::numeric_limits::max(), ""); + meta["settings"]["optimizer"]["runs"] = Json::number_integer_t(m_optimiserSettings.expectedExecutionsPerDeployment); /// Backwards compatibility: If set to one of the default settings, do not provide details. OptimiserSettings settingsWithoutRuns = m_optimiserSettings; @@ -1705,7 +1703,7 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR meta["settings"]["optimizer"]["enabled"] = true; else { - Json::Value details{Json::objectValue}; + Json details = Json::object(); details["orderLiterals"] = m_optimiserSettings.runOrderLiterals; details["inliner"] = m_optimiserSettings.runInliner; @@ -1718,14 +1716,14 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR details["yul"] = m_optimiserSettings.runYulOptimiser; if (m_optimiserSettings.runYulOptimiser) { - details["yulDetails"] = Json::objectValue; + details["yulDetails"] = Json::object(); details["yulDetails"]["stackAllocation"] = m_optimiserSettings.optimizeStackAllocation; details["yulDetails"]["optimizerSteps"] = m_optimiserSettings.yulOptimiserSteps + ":" + m_optimiserSettings.yulOptimiserCleanupSteps; } else if (OptimiserSuite::isEmptyOptimizerSequence(m_optimiserSettings.yulOptimiserSteps + ":" + m_optimiserSettings.yulOptimiserCleanupSteps)) { solAssert(m_optimiserSettings.optimizeStackAllocation == false); - details["yulDetails"] = Json::objectValue; + details["yulDetails"] = Json::object(); details["yulDetails"]["optimizerSteps"] = ":"; } else @@ -1758,14 +1756,14 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR meta["settings"]["compilationTarget"][_contract.contract->sourceUnitName()] = *_contract.contract->annotation().canonicalName; - meta["settings"]["remappings"] = Json::arrayValue; + meta["settings"]["remappings"] = Json::array(); std::set remappings; for (auto const& r: m_importRemapper.remappings()) remappings.insert(r.context + ":" + r.prefix + "=" + r.target); for (auto const& r: remappings) - meta["settings"]["remappings"].append(r); + meta["settings"]["remappings"].emplace_back(r); - meta["settings"]["libraries"] = Json::objectValue; + meta["settings"]["libraries"] = Json::object(); for (auto const& library: m_libraries) meta["settings"]["libraries"][library.first] = "0x" + util::toHex(library.second.asBytes()); @@ -1897,17 +1895,17 @@ bytes CompilerStack::createCBORMetadata(Contract const& _contract, bool _forIR) namespace { -Json::Value gasToJson(GasEstimator::GasConsumption const& _gas) +Json gasToJson(GasEstimator::GasConsumption const& _gas) { if (_gas.isInfinite) - return Json::Value("infinite"); + return Json("infinite"); else - return Json::Value(util::toString(_gas.value)); + return Json(util::toString(_gas.value)); } } -Json::Value CompilerStack::gasEstimates(std::string const& _contractName) const +Json CompilerStack::gasEstimates(std::string const& _contractName) const { if (m_stackState != CompilationSuccessful) solThrow(CompilerError, "Compilation was not successful."); @@ -1915,18 +1913,18 @@ Json::Value CompilerStack::gasEstimates(std::string const& _contractName) const solUnimplementedAssert(!isExperimentalSolidity()); if (!assemblyItems(_contractName) && !runtimeAssemblyItems(_contractName)) - return Json::Value(); + return Json(); using Gas = GasEstimator::GasConsumption; GasEstimator gasEstimator(m_evmVersion); - Json::Value output(Json::objectValue); + Json output = Json::object(); if (evmasm::AssemblyItems const* items = assemblyItems(_contractName)) { Gas executionGas = gasEstimator.functionalEstimation(*items); Gas codeDepositGas{evmasm::GasMeter::dataGas(runtimeObject(_contractName).bytecode, false, m_evmVersion)}; - Json::Value creation(Json::objectValue); + Json creation = Json::object(); creation["codeDepositCost"] = gasToJson(codeDepositGas); creation["executionCost"] = gasToJson(executionGas); /// TODO: implement + overload to avoid the need of += @@ -1939,7 +1937,7 @@ Json::Value CompilerStack::gasEstimates(std::string const& _contractName) const { /// External functions ContractDefinition const& contract = contractDefinition(_contractName); - Json::Value externalFunctions(Json::objectValue); + Json externalFunctions = Json::object(); for (auto it: contract.interfaceFunctions()) { std::string sig = it.second->externalSignature(); @@ -1956,7 +1954,7 @@ Json::Value CompilerStack::gasEstimates(std::string const& _contractName) const output["external"] = externalFunctions; /// Internal functions - Json::Value internalFunctions(Json::objectValue); + Json internalFunctions = Json::object(); for (auto const& it: contract.definedFunctions()) { /// Exclude externally visible functions, constructor, fallback and receive ether function diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 57d30e602..ef76764fa 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -47,8 +47,7 @@ #include #include #include - -#include +#include #include #include @@ -221,7 +220,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// Imports given SourceUnits so they can be analyzed. Leads to the same internal state as parse(). /// Will throw errors if the import fails - void importASTs(std::map const& _sources); + void importASTs(std::map const& _sources); /// Performs the analysis steps (imports, scopesetting, syntaxCheck, referenceResolving, /// typechecking, staticAnalysis) on previously parsed sources. @@ -277,13 +276,13 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac std::string const& yulIR(std::string const& _contractName) const; /// @returns the IR representation of a contract AST in format. - Json::Value const& yulIRAst(std::string const& _contractName) const; + Json const& yulIRAst(std::string const& _contractName) const; /// @returns the optimized IR representation of a contract. std::string const& yulIROptimized(std::string const& _contractName) const; /// @returns the optimized IR representation of a contract AST in JSON format. - Json::Value const& yulIROptimizedAst(std::string const& _contractName) const; + Json const& yulIROptimizedAst(std::string const& _contractName) const; /// @returns the assembled object for a contract. virtual evmasm::LinkerObject const& object(std::string const& _contractName) const override; @@ -299,7 +298,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// @returns an array containing all utility sources generated during compilation. /// Format: [ { name: string, id: number, language: "Yul", contents: string }, ... ] - Json::Value generatedSources(std::string const& _contractName, bool _runtime = false) const; + Json generatedSources(std::string const& _contractName, bool _runtime = false) const; /// @returns the string that provides a mapping between bytecode and sourcecode or a nullptr /// if the contract does not (yet) have bytecode. @@ -317,26 +316,26 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// @returns a JSON representation of the assembly. /// @arg _sourceCodes is the map of input files to source code strings /// Prerequisite: Successful compilation. - virtual Json::Value assemblyJSON(std::string const& _contractName) const override; + virtual Json assemblyJSON(std::string const& _contractName) const override; /// @returns a JSON representing the contract ABI. /// Prerequisite: Successful call to parse or compile. - Json::Value const& contractABI(std::string const& _contractName) const; + Json const& contractABI(std::string const& _contractName) const; /// @returns a JSON representing the storage layout of the contract. /// Prerequisite: Successful call to parse or compile. - Json::Value const& storageLayout(std::string const& _contractName) const; + Json const& storageLayout(std::string const& _contractName) const; /// @returns a JSON representing the contract's user documentation. /// Prerequisite: Successful call to parse or compile. - Json::Value const& natspecUser(std::string const& _contractName) const; + Json const& natspecUser(std::string const& _contractName) const; /// @returns a JSON representing the contract's developer documentation. /// Prerequisite: Successful call to parse or compile. - Json::Value const& natspecDev(std::string const& _contractName) const; + Json const& natspecDev(std::string const& _contractName) const; /// @returns a JSON object with the three members ``methods``, ``events``, ``errors``. Each is a map, mapping identifiers (hashes) to function names. - Json::Value interfaceSymbols(std::string const& _contractName) const; + Json interfaceSymbols(std::string const& _contractName) const; /// @returns the Contract Metadata matching the pipeline selected using the viaIR setting. std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); } @@ -350,7 +349,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac bytes cborMetadata(std::string const& _contractName, bool _forIR) const; /// @returns a JSON representing the estimated gas usage for contract creation, internal and external functions - Json::Value gasEstimates(std::string const& _contractName) const; + Json gasEstimates(std::string const& _contractName) const; /// Changes the format of the metadata appended at the end of the bytecode. void setMetadataFormat(MetadataFormat _metadataFormat) { m_metadataFormat = _metadataFormat; } @@ -390,15 +389,15 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac evmasm::LinkerObject runtimeObject; ///< Runtime object. std::string yulIR; ///< Yul IR code. std::string yulIROptimized; ///< Optimized Yul IR code. - Json::Value yulIRAst; ///< JSON AST of Yul IR code. - Json::Value yulIROptimizedAst; ///< JSON AST of optimized Yul IR code. + Json yulIRAst; ///< JSON AST of Yul IR code. + Json yulIROptimizedAst; ///< JSON AST of optimized Yul IR code. util::LazyInit metadata; ///< The metadata json that will be hashed into the chain. - util::LazyInit abi; - util::LazyInit storageLayout; - util::LazyInit userDocumentation; - util::LazyInit devDocumentation; - util::LazyInit generatedSources; - util::LazyInit runtimeGeneratedSources; + util::LazyInit abi; + util::LazyInit storageLayout; + util::LazyInit userDocumentation; + util::LazyInit devDocumentation; + util::LazyInit generatedSources; + util::LazyInit runtimeGeneratedSources; mutable std::optional sourceMapping; mutable std::optional runtimeSourceMapping; }; @@ -479,19 +478,19 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// @returns the contract ABI as a JSON object. /// This will generate the JSON object and store it in the Contract object if it is not present yet. - Json::Value const& contractABI(Contract const&) const; + Json const& contractABI(Contract const&) const; /// @returns the storage layout of the contract as a JSON object. /// This will generate the JSON object and store it in the Contract object if it is not present yet. - Json::Value const& storageLayout(Contract const&) const; + Json const& storageLayout(Contract const&) const; /// @returns the Natspec User documentation as a JSON object. /// This will generate the JSON object and store it in the Contract object if it is not present yet. - Json::Value const& natspecUser(Contract const&) const; + Json const& natspecUser(Contract const&) const; /// @returns the Natspec Developer documentation as a JSON object. /// This will generate the JSON object and store it in the Contract object if it is not present yet. - Json::Value const& natspecDev(Contract const&) const; + Json const& natspecDev(Contract const&) const; /// @returns the Contract Metadata matching the pipeline selected using the viaIR setting. /// This will generate the metadata and store it in the Contract object if it is not present yet. diff --git a/libsolidity/interface/Natspec.cpp b/libsolidity/interface/Natspec.cpp index 539a3573f..a0da7b54b 100644 --- a/libsolidity/interface/Natspec.cpp +++ b/libsolidity/interface/Natspec.cpp @@ -33,13 +33,13 @@ using namespace solidity; using namespace solidity::frontend; -Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef) +Json Natspec::userDocumentation(ContractDefinition const& _contractDef) { - Json::Value doc{Json::objectValue}; + Json doc; - doc["version"] = Json::Value(c_natspecVersion); - doc["kind"] = Json::Value("user"); - doc["methods"] = Json::objectValue; + doc["version"] = Json(c_natspecVersion); + doc["kind"] = Json("user"); + doc["methods"] = Json::object(); auto constructorDefinition(_contractDef.constructor()); if (constructorDefinition) @@ -48,15 +48,15 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef) if (!value.empty()) { // add the constructor, only if we have any documentation to add - Json::Value user{Json::objectValue}; - user["notice"] = Json::Value(value); + Json user; + user["notice"] = Json(value); doc["methods"]["constructor"] = user; } } std::string notice = extractDoc(_contractDef.annotation().docTags, "notice"); if (!notice.empty()) - doc["notice"] = Json::Value(notice); + doc["notice"] = Json(notice); for (auto const& it: _contractDef.interfaceFunctions()) if (it.second->hasDeclaration()) @@ -88,21 +88,21 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef) std::string value = extractDoc(error->annotation().docTags, "notice"); if (!value.empty()) { - Json::Value errorDoc{Json::objectValue}; + Json errorDoc; errorDoc["notice"] = value; - doc["errors"][error->functionType(true)->externalSignature()].append(std::move(errorDoc)); + doc["errors"][error->functionType(true)->externalSignature()].emplace_back(std::move(errorDoc)); } } return doc; } -Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef) +Json Natspec::devDocumentation(ContractDefinition const& _contractDef) { - Json::Value doc = extractCustomDoc(_contractDef.annotation().docTags); + Json doc = extractCustomDoc(_contractDef.annotation().docTags); - doc["version"] = Json::Value(c_natspecVersion); - doc["kind"] = Json::Value("dev"); + doc["version"] = Json(c_natspecVersion); + doc["kind"] = Json("dev"); auto author = extractDoc(_contractDef.annotation().docTags, "author"); if (!author.empty()) @@ -112,13 +112,13 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef) doc["title"] = title; auto dev = extractDoc(_contractDef.annotation().docTags, "dev"); if (!dev.empty()) - doc["details"] = Json::Value(dev); + doc["details"] = Json(dev); - doc["methods"] = Json::objectValue; + doc["methods"] = Json::object(); auto constructorDefinition(_contractDef.constructor()); if (constructorDefinition) { - Json::Value constructor(devDocumentation(constructorDefinition->annotation().docTags)); + Json constructor(devDocumentation(constructorDefinition->annotation().docTags)); if (!constructor.empty()) // add the constructor, only if we have any documentation to add doc["methods"]["constructor"] = constructor; @@ -130,9 +130,9 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef) continue; if (auto fun = dynamic_cast(&it.second->declaration())) { - Json::Value method(devDocumentation(fun->annotation().docTags)); + Json method(devDocumentation(fun->annotation().docTags)); // add the function, only if we have any documentation to add - Json::Value jsonReturn = extractReturnParameterDocs( + Json jsonReturn = extractReturnParameterDocs( fun->annotation().docTags, fun->functionType(false)->returnParameterNames() ); @@ -150,7 +150,7 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef) if (auto devDoc = devDocumentation(varDecl->annotation().docTags); !devDoc.empty()) doc["stateVariables"][varDecl->name()] = devDoc; - auto const assignIfNotEmpty = [&](std::string const& _name, Json::Value const& _content) + auto const assignIfNotEmpty = [&](std::string const& _name, Json const& _content) { if (!_content.empty()) doc["stateVariables"][varDecl->name()][_name] = _content; @@ -171,14 +171,14 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef) doc["events"][event->functionType(true)->externalSignature()] = devDoc; for (auto const& error: _contractDef.interfaceErrors()) if (auto devDoc = devDocumentation(error->annotation().docTags); !devDoc.empty()) - doc["errors"][error->functionType(true)->externalSignature()].append(devDoc); + doc["errors"][error->functionType(true)->externalSignature()].emplace_back(devDoc); return doc; } -Json::Value Natspec::extractReturnParameterDocs(std::multimap const& _tags, std::vector const& _returnParameterNames) +Json Natspec::extractReturnParameterDocs(std::multimap const& _tags, std::vector const& _returnParameterNames) { - Json::Value jsonReturn{Json::objectValue}; + Json jsonReturn; auto returnDocs = _tags.equal_range("return"); if (!_returnParameterNames.empty()) @@ -199,7 +199,7 @@ Json::Value Natspec::extractReturnParameterDocs(std::multimap const& _tags, return value; } -Json::Value Natspec::extractCustomDoc(std::multimap const& _tags) +Json Natspec::extractCustomDoc(std::multimap const& _tags) { std::map concatenated; for (auto const& [tag, value]: _tags) @@ -224,28 +224,28 @@ Json::Value Natspec::extractCustomDoc(std::multimap const& concatenated[tag] += value.content; // We do not want to create an object if there are no custom tags found. if (concatenated.empty()) - return Json::nullValue; - Json::Value result{Json::objectValue}; + return Json(); + Json result; for (auto& [tag, value]: concatenated) result[tag] = std::move(value); return result; } -Json::Value Natspec::devDocumentation(std::multimap const& _tags) +Json Natspec::devDocumentation(std::multimap const& _tags) { - Json::Value json = extractCustomDoc(_tags); + Json json = extractCustomDoc(_tags); auto dev = extractDoc(_tags, "dev"); if (!dev.empty()) - json["details"] = Json::Value(dev); + json["details"] = Json(dev); auto author = extractDoc(_tags, "author"); if (!author.empty()) json["author"] = author; - Json::Value params(Json::objectValue); + Json params; auto paramRange = _tags.equal_range("param"); for (auto i = paramRange.first; i != paramRange.second; ++i) - params[i->second.paramName] = Json::Value(i->second.content); + params[i->second.paramName] = Json(i->second.content); if (!params.empty()) json["params"] = params; diff --git a/libsolidity/interface/Natspec.h b/libsolidity/interface/Natspec.h index e75485097..994f1350c 100644 --- a/libsolidity/interface/Natspec.h +++ b/libsolidity/interface/Natspec.h @@ -26,10 +26,10 @@ #pragma once -#include +#include +#include #include #include -#include namespace solidity::frontend { @@ -46,32 +46,32 @@ class Natspec /// Get the User documentation of the contract /// @param _contractDef The contract definition /// @return A JSON representation of the contract's user documentation - static Json::Value userDocumentation(ContractDefinition const& _contractDef); + static Json userDocumentation(ContractDefinition const& _contractDef); /// Generates the Developer's documentation of the contract /// @param _contractDef The contract definition /// @return A JSON representation /// of the contract's developer documentation - static Json::Value devDocumentation(ContractDefinition const& _contractDef); + static Json devDocumentation(ContractDefinition const& _contractDef); private: /// @returns concatenation of all content under the given tag name. static std::string extractDoc(std::multimap const& _tags, std::string const& _name); /// Extract all custom tags from @a _tags. - static Json::Value extractCustomDoc(std::multimap const& _tags); + static Json extractCustomDoc(std::multimap const& _tags); /// Helper-function that will create a json object with dev specific annotations, if present. /// @param _tags docTags that are used. /// @return A JSON representation /// of the contract's developer documentation - static Json::Value devDocumentation(std::multimap const& _tags); + static Json devDocumentation(std::multimap const& _tags); /// Helper-function that will create a json object for the "returns" field for a given function definition. /// @param _tags docTags that are used. /// @param _returnParameterNames names of the return parameters /// @return A JSON representation /// of a method's return notice documentation - static Json::Value extractReturnParameterDocs(std::multimap const& _tags, std::vector const& _returnParameterNames); + static Json extractReturnParameterDocs(std::multimap const& _tags, std::vector const& _returnParameterNames); /// Temporary function until https://github.com/ethereum/solidity/issues/11114 is implemented. /// @return all events defined in the contract and its base contracts and all events diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 1f7b3fa75..a54a9aa10 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -54,64 +54,64 @@ using namespace std::string_literals; namespace { -Json::Value formatError( +Json formatError( Error::Type _type, std::string const& _component, std::string const& _message, std::string const& _formattedMessage = "", - Json::Value const& _sourceLocation = Json::Value(), - Json::Value const& _secondarySourceLocation = Json::Value() + Json const& _sourceLocation = Json(), + Json const& _secondarySourceLocation = Json() ) { - Json::Value error{Json::objectValue}; + Json error; error["type"] = Error::formatErrorType(_type); error["component"] = _component; error["severity"] = Error::formatErrorSeverityLowercase(Error::errorSeverity(_type)); error["message"] = _message; error["formattedMessage"] = (_formattedMessage.length() > 0) ? _formattedMessage : _message; - if (_sourceLocation.isObject()) + if (_sourceLocation.is_object()) error["sourceLocation"] = _sourceLocation; - if (_secondarySourceLocation.isArray()) + if (_secondarySourceLocation.is_array()) error["secondarySourceLocations"] = _secondarySourceLocation; return error; } -Json::Value formatFatalError(Error::Type _type, std::string const& _message) +Json formatFatalError(Error::Type _type, std::string const& _message) { - Json::Value output{Json::objectValue}; - output["errors"] = Json::arrayValue; - output["errors"].append(formatError(_type, "general", _message)); + Json output; + output["errors"] = Json::array(); + output["errors"].emplace_back(formatError(_type, "general", _message)); return output; } -Json::Value formatSourceLocation(SourceLocation const* location) +Json formatSourceLocation(SourceLocation const* location) { if (!location || !location->sourceName) - return Json::nullValue; + return Json(); - Json::Value sourceLocation{Json::objectValue}; + Json sourceLocation; sourceLocation["file"] = *location->sourceName; sourceLocation["start"] = location->start; sourceLocation["end"] = location->end; return sourceLocation; } -Json::Value formatSecondarySourceLocation(SecondarySourceLocation const* _secondaryLocation) +Json formatSecondarySourceLocation(SecondarySourceLocation const* _secondaryLocation) { if (!_secondaryLocation) - return Json::nullValue; + return Json(); - Json::Value secondarySourceLocation{Json::arrayValue}; + Json secondarySourceLocation = Json::array(); for (auto const& location: _secondaryLocation->infos) { - Json::Value msg = formatSourceLocation(&location.second); + Json msg = formatSourceLocation(&location.second); msg["message"] = location.first; - secondarySourceLocation.append(msg); + secondarySourceLocation.emplace_back(msg); } return secondarySourceLocation; } -Json::Value formatErrorWithException( +Json formatErrorWithException( CharStreamProvider const& _charStreamProvider, util::Exception const& _exception, Error::Type _type, @@ -134,7 +134,7 @@ Json::Value formatErrorWithException( else message = _message; - Json::Value error = formatError( + Json error = formatError( _type, _component, message, @@ -149,13 +149,13 @@ Json::Value formatErrorWithException( return error; } -std::map> requestedContractNames(Json::Value const& _outputSelection) +std::map> requestedContractNames(Json const& _outputSelection) { std::map> contracts; - for (auto const& sourceName: _outputSelection.getMemberNames()) + for (auto const& [sourceName, _]: _outputSelection.items()) { std::string key = (sourceName == "*") ? "" : sourceName; - for (auto const& contractName: _outputSelection[sourceName].getMemberNames()) + for (auto const& [contractName, _]: _outputSelection[sourceName].items()) { std::string value = (contractName == "*") ? "" : contractName; contracts[key].insert(value); @@ -177,12 +177,12 @@ bool hashMatchesContent(std::string const& _hash, std::string const& _content) } } -bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& _artifact, bool _wildcardMatchesExperimental) +bool isArtifactRequested(Json const& _outputSelection, std::string const& _artifact, bool _wildcardMatchesExperimental) { static std::set experimental{"ir", "irAst", "irOptimized", "irOptimizedAst"}; for (auto const& selectedArtifactJson: _outputSelection) { - std::string const& selectedArtifact = selectedArtifactJson.asString(); + std::string const& selectedArtifact = selectedArtifactJson.get(); if ( _artifact == selectedArtifact || boost::algorithm::starts_with(_artifact, selectedArtifact + ".") @@ -211,13 +211,13 @@ bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& /// /// @TODO optimise this. Perhaps flatten the structure upfront. /// -bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& _file, std::string const& _contract, std::string const& _artifact, bool _wildcardMatchesExperimental) +bool isArtifactRequested(Json const& _outputSelection, std::string const& _file, std::string const& _contract, std::string const& _artifact, bool _wildcardMatchesExperimental) { - if (!_outputSelection.isObject()) + if (!_outputSelection.is_object()) return false; for (auto const& file: { _file, std::string("*") }) - if (_outputSelection.isMember(file) && _outputSelection[file].isObject()) + if (_outputSelection.contains(file) && _outputSelection[file].is_object()) { /// For SourceUnit-level targets (such as AST) only allow empty name, otherwise /// for Contract-level targets try both contract name and wildcard @@ -226,8 +226,8 @@ bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& contracts.emplace_back("*"); for (auto const& contract: contracts) if ( - _outputSelection[file].isMember(contract) && - _outputSelection[file][contract].isArray() && + _outputSelection[file].contains(contract) && + _outputSelection[file][contract].is_array() && isArtifactRequested(_outputSelection[file][contract], _artifact, _wildcardMatchesExperimental) ) return true; @@ -236,7 +236,7 @@ bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& return false; } -bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& _file, std::string const& _contract, std::vector const& _artifacts, bool _wildcardMatchesExperimental) +bool isArtifactRequested(Json const& _outputSelection, std::string const& _file, std::string const& _contract, std::vector const& _artifacts, bool _wildcardMatchesExperimental) { for (auto const& artifact: _artifacts) if (isArtifactRequested(_outputSelection, _file, _contract, artifact, _wildcardMatchesExperimental)) @@ -255,9 +255,9 @@ std::vector evmObjectComponents(std::string const& _objectKind) } /// @returns true if any binary was requested, i.e. we actually have to perform compilation. -bool isBinaryRequested(Json::Value const& _outputSelection) +bool isBinaryRequested(Json const& _outputSelection) { - if (!_outputSelection.isObject()) + if (!_outputSelection.is_object()) return false; // This does not include "evm.methodIdentifiers" on purpose! @@ -276,9 +276,9 @@ bool isBinaryRequested(Json::Value const& _outputSelection) } /// @returns true if EVM bytecode was requested, i.e. we have to run the old code generator. -bool isEvmBytecodeRequested(Json::Value const& _outputSelection) +bool isEvmBytecodeRequested(Json const& _outputSelection) { - if (!_outputSelection.isObject()) + if (!_outputSelection.is_object()) return false; static std::vector const outputsThatRequireEvmBinaries = std::vector{ @@ -296,9 +296,9 @@ bool isEvmBytecodeRequested(Json::Value const& _outputSelection) /// @returns true if any Yul IR was requested. Note that as an exception, '*' does not /// yet match "ir", "irAst", "irOptimized" or "irOptimizedAst" -bool isIRRequested(Json::Value const& _outputSelection) +bool isIRRequested(Json const& _outputSelection) { - if (!_outputSelection.isObject()) + if (!_outputSelection.is_object()) return false; for (auto const& fileRequests: _outputSelection) @@ -315,9 +315,9 @@ bool isIRRequested(Json::Value const& _outputSelection) return false; } -Json::Value formatLinkReferences(std::map const& linkReferences) +Json formatLinkReferences(std::map const& linkReferences) { - Json::Value ret{Json::objectValue}; + Json ret = Json::object(); for (auto const& ref: linkReferences) { @@ -329,14 +329,14 @@ Json::Value formatLinkReferences(std::map const& linkRefere std::string file = (colon != std::string::npos ? fullname.substr(0, colon) : ""); std::string name = (colon != std::string::npos ? fullname.substr(colon + 1) : fullname); - Json::Value fileObject = ret.get(file, Json::objectValue); - Json::Value libraryArray = fileObject.get(name, Json::arrayValue); + Json fileObject = ret.value(file, Json::object()); + Json libraryArray = fileObject.value(name, Json::array()); - Json::Value entry{Json::objectValue}; - entry["start"] = Json::UInt(ref.first); + Json entry; + entry["start"] = Json(ref.first); entry["length"] = 20; - libraryArray.append(entry); + libraryArray.emplace_back(entry); fileObject[name] = libraryArray; ret[file] = fileObject; } @@ -344,20 +344,20 @@ Json::Value formatLinkReferences(std::map const& linkRefere return ret; } -Json::Value formatImmutableReferences(std::map>> const& _immutableReferences) +Json formatImmutableReferences(std::map>> const& _immutableReferences) { - Json::Value ret{Json::objectValue}; + Json ret = Json::object(); for (auto const& immutableReference: _immutableReferences) { auto const& [identifier, byteOffsets] = immutableReference.second; - Json::Value array(Json::arrayValue); + Json array = Json::array(); for (size_t byteOffset: byteOffsets) { - Json::Value byteRange{Json::objectValue}; - byteRange["start"] = Json::UInt(byteOffset); - byteRange["length"] = Json::UInt(32); // immutable references are currently always 32 bytes wide - array.append(byteRange); + Json byteRange; + byteRange["start"] = Json::number_unsigned_t(byteOffset); + byteRange["length"] = Json::number_unsigned_t(32); // immutable references are currently always 32 bytes wide + array.emplace_back(byteRange); } ret[identifier] = array; } @@ -365,16 +365,16 @@ Json::Value formatImmutableReferences(std::map const& _artifactRequested ) { - Json::Value output{Json::objectValue}; + Json output; if (_artifactRequested("object")) output["object"] = _object.toHex(); if (_artifactRequested("opcodes")) @@ -392,78 +392,78 @@ Json::Value collectEVMObject( return output; } -std::optional checkKeys(Json::Value const& _input, std::set const& _keys, std::string const& _name) +std::optional checkKeys(Json const& _input, std::set const& _keys, std::string const& _name) { - if (!!_input && !_input.isObject()) + if (!_input.empty() && !_input.is_object()) return formatFatalError(Error::Type::JSONError, "\"" + _name + "\" must be an object"); - for (auto const& member: _input.getMemberNames()) + for (auto const& [member, _]: _input.items()) if (!_keys.count(member)) return formatFatalError(Error::Type::JSONError, "Unknown key \"" + member + "\""); return std::nullopt; } -std::optional checkRootKeys(Json::Value const& _input) +std::optional checkRootKeys(Json const& _input) { static std::set keys{"auxiliaryInput", "language", "settings", "sources"}; return checkKeys(_input, keys, "root"); } -std::optional checkSourceKeys(Json::Value const& _input, std::string const& _name) +std::optional checkSourceKeys(Json const& _input, std::string const& _name) { static std::set keys{"content", "keccak256", "urls"}; return checkKeys(_input, keys, "sources." + _name); } -std::optional checkAuxiliaryInputKeys(Json::Value const& _input) +std::optional checkAuxiliaryInputKeys(Json const& _input) { static std::set keys{"smtlib2responses"}; return checkKeys(_input, keys, "auxiliaryInput"); } -std::optional checkSettingsKeys(Json::Value const& _input) +std::optional checkSettingsKeys(Json const& _input) { static std::set keys{"debug", "evmVersion", "libraries", "metadata", "modelChecker", "optimizer", "outputSelection", "remappings", "stopAfter", "viaIR"}; return checkKeys(_input, keys, "settings"); } -std::optional checkModelCheckerSettingsKeys(Json::Value const& _input) +std::optional checkModelCheckerSettingsKeys(Json const& _input) { static std::set keys{"bmcLoopIterations", "contracts", "divModNoSlacks", "engine", "extCalls", "invariants", "printQuery", "showProvedSafe", "showUnproved", "showUnsupported", "solvers", "targets", "timeout"}; return checkKeys(_input, keys, "modelChecker"); } -std::optional checkOptimizerKeys(Json::Value const& _input) +std::optional checkOptimizerKeys(Json const& _input) { static std::set keys{"details", "enabled", "runs"}; return checkKeys(_input, keys, "settings.optimizer"); } -std::optional checkOptimizerDetailsKeys(Json::Value const& _input) +std::optional checkOptimizerDetailsKeys(Json const& _input) { static std::set keys{"peephole", "inliner", "jumpdestRemover", "orderLiterals", "deduplicate", "cse", "constantOptimizer", "yul", "yulDetails", "simpleCounterForLoopUncheckedIncrement"}; return checkKeys(_input, keys, "settings.optimizer.details"); } -std::optional checkOptimizerDetail(Json::Value const& _details, std::string const& _name, bool& _setting) +std::optional checkOptimizerDetail(Json const& _details, std::string const& _name, bool& _setting) { - if (_details.isMember(_name)) + if (_details.contains(_name)) { - if (!_details[_name].isBool()) + if (!_details[_name].is_boolean()) return formatFatalError(Error::Type::JSONError, "\"settings.optimizer.details." + _name + "\" must be Boolean"); - _setting = _details[_name].asBool(); + _setting = _details[_name].get(); } return {}; } -std::optional checkOptimizerDetailSteps(Json::Value const& _details, std::string const& _name, std::string& _optimiserSetting, std::string& _cleanupSetting, bool _runYulOptimizer) +std::optional checkOptimizerDetailSteps(Json const& _details, std::string const& _name, std::string& _optimiserSetting, std::string& _cleanupSetting, bool _runYulOptimizer) { - if (_details.isMember(_name)) + if (_details.contains(_name)) { - if (_details[_name].isString()) + if (_details[_name].is_string()) { - std::string const fullSequence = _details[_name].asString(); + std::string const fullSequence = _details[_name].get(); if (!_runYulOptimizer && !OptimiserSuite::isEmptyOptimizerSequence(fullSequence)) { std::string errorMessage = @@ -474,7 +474,7 @@ std::optional checkOptimizerDetailSteps(Json::Value const& _details try { - yul::OptimiserSuite::validateSequence(_details[_name].asString()); + yul::OptimiserSuite::validateSequence(_details[_name].get()); } catch (yul::OptimizerException const& _exception) { @@ -499,43 +499,39 @@ std::optional checkOptimizerDetailSteps(Json::Value const& _details return {}; } -std::optional checkMetadataKeys(Json::Value const& _input) +std::optional checkMetadataKeys(Json const& _input) { - if (_input.isObject()) + if (_input.is_object()) { - if (_input.isMember("appendCBOR") && !_input["appendCBOR"].isBool()) + if (_input.contains("appendCBOR") && !_input["appendCBOR"].is_boolean()) return formatFatalError(Error::Type::JSONError, "\"settings.metadata.appendCBOR\" must be Boolean"); - if (_input.isMember("useLiteralContent") && !_input["useLiteralContent"].isBool()) + if (_input.contains("useLiteralContent") && !_input["useLiteralContent"].is_boolean()) return formatFatalError(Error::Type::JSONError, "\"settings.metadata.useLiteralContent\" must be Boolean"); static std::set hashes{"ipfs", "bzzr1", "none"}; - if (_input.isMember("bytecodeHash") && !hashes.count(_input["bytecodeHash"].asString())) + if (_input.contains("bytecodeHash") && !hashes.count(_input["bytecodeHash"].get())) return formatFatalError(Error::Type::JSONError, "\"settings.metadata.bytecodeHash\" must be \"ipfs\", \"bzzr1\" or \"none\""); } static std::set keys{"appendCBOR", "useLiteralContent", "bytecodeHash"}; return checkKeys(_input, keys, "settings.metadata"); } -std::optional checkOutputSelection(Json::Value const& _outputSelection) +std::optional checkOutputSelection(Json const& _outputSelection) { - if (!!_outputSelection && !_outputSelection.isObject()) + if (!_outputSelection.empty() && !_outputSelection.is_object()) return formatFatalError(Error::Type::JSONError, "\"settings.outputSelection\" must be an object"); - for (auto const& sourceName: _outputSelection.getMemberNames()) + for (auto const& [sourceName, sourceVal]: _outputSelection.items()) { - auto const& sourceVal = _outputSelection[sourceName]; - - if (!sourceVal.isObject()) + if (!sourceVal.is_object()) return formatFatalError( Error::Type::JSONError, "\"settings.outputSelection." + sourceName + "\" must be an object" ); - for (auto const& contractName: sourceVal.getMemberNames()) + for (auto const& [contractName, contractVal]: sourceVal.items()) { - auto const& contractVal = sourceVal[contractName]; - - if (!contractVal.isArray()) + if (!contractVal.is_array()) return formatFatalError( Error::Type::JSONError, "\"settings.outputSelection." + @@ -546,7 +542,7 @@ std::optional checkOutputSelection(Json::Value const& _outputSelect ); for (auto const& output: contractVal) - if (!output.isString()) + if (!output.is_string()) return formatFatalError( Error::Type::JSONError, "\"settings.outputSelection." + @@ -563,32 +559,32 @@ std::optional checkOutputSelection(Json::Value const& _outputSelect /// Validates the optimizer settings and returns them in a parsed object. /// On error returns the json-formatted error message. -std::variant parseOptimizerSettings(Json::Value const& _jsonInput) +std::variant parseOptimizerSettings(Json const& _jsonInput) { if (auto result = checkOptimizerKeys(_jsonInput)) return *result; OptimiserSettings settings = OptimiserSettings::minimal(); - if (_jsonInput.isMember("enabled")) + if (_jsonInput.contains("enabled")) { - if (!_jsonInput["enabled"].isBool()) + if (!_jsonInput["enabled"].is_boolean()) return formatFatalError(Error::Type::JSONError, "The \"enabled\" setting must be a Boolean."); - if (_jsonInput["enabled"].asBool()) + if (_jsonInput["enabled"].get()) settings = OptimiserSettings::standard(); } - if (_jsonInput.isMember("runs")) + if (_jsonInput.contains("runs")) { - if (!_jsonInput["runs"].isUInt()) + if (!_jsonInput["runs"].is_number_unsigned()) return formatFatalError(Error::Type::JSONError, "The \"runs\" setting must be an unsigned number."); - settings.expectedExecutionsPerDeployment = _jsonInput["runs"].asUInt(); + settings.expectedExecutionsPerDeployment = _jsonInput["runs"].get(); } - if (_jsonInput.isMember("details")) + if (_jsonInput.contains("details")) { - Json::Value const& details = _jsonInput["details"]; + Json const& details = _jsonInput["details"]; if (auto result = checkOptimizerDetailsKeys(details)) return *result; @@ -611,7 +607,7 @@ std::variant parseOptimizerSettings(Json::Value if (auto error = checkOptimizerDetail(details, "simpleCounterForLoopUncheckedIncrement", settings.simpleCounterForLoopUncheckedIncrement)) return *error; settings.optimizeStackAllocation = settings.runYulOptimiser; - if (details.isMember("yulDetails")) + if (details.contains("yulDetails")) { if (!settings.runYulOptimiser) { @@ -635,45 +631,46 @@ std::variant parseOptimizerSettings(Json::Value } -std::variant StandardCompiler::parseInput(Json::Value const& _input) +std::variant StandardCompiler::parseInput(Json const& _input) { InputsAndSettings ret; - if (!_input.isObject()) + if (!_input.is_object()) return formatFatalError(Error::Type::JSONError, "Input is not a JSON object."); if (auto result = checkRootKeys(_input)) return *result; - ret.language = _input["language"].asString(); + ret.language = _input.value("language", ""); - Json::Value const& sources = _input["sources"]; + Json const& sources = _input.value("sources", Json()); - if (!sources.isObject() && !sources.isNull()) + if (!sources.is_object() && !sources.is_null()) return formatFatalError(Error::Type::JSONError, "\"sources\" is not a JSON object."); if (sources.empty()) return formatFatalError(Error::Type::JSONError, "No input sources specified."); - ret.errors = Json::arrayValue; + ret.errors = Json::array(); + ret.sources = Json::object(); if (ret.language == "Solidity" || ret.language == "Yul") { - for (auto const& sourceName: sources.getMemberNames()) + for (auto const& [sourceName, sourceValue]: sources.items()) { std::string hash; - if (auto result = checkSourceKeys(sources[sourceName], sourceName)) + if (auto result = checkSourceKeys(sourceValue, sourceName)) return *result; - if (sources[sourceName]["keccak256"].isString()) - hash = sources[sourceName]["keccak256"].asString(); + if (sourceValue.contains("keccak256") && sourceValue["keccak256"].is_string()) + hash = sourceValue["keccak256"].get(); - if (sources[sourceName]["content"].isString()) + if (sourceValue.contains("content") && sourceValue["content"].is_string()) { - std::string content = sources[sourceName]["content"].asString(); + std::string content = sourceValue["content"].get(); if (!hash.empty() && !hashMatchesContent(hash, content)) - ret.errors.append(formatError( + ret.errors.emplace_back(formatError( Error::Type::IOError, "general", "Mismatch between content and supplied hash for \"" + sourceName + "\"" @@ -681,7 +678,7 @@ std::variant StandardCompiler: else ret.sources[sourceName] = content; } - else if (sources[sourceName]["urls"].isArray()) + else if (sourceValue["urls"].is_array()) { if (!m_readFile) return formatFatalError( @@ -691,18 +688,18 @@ std::variant StandardCompiler: std::vector failures; bool found = false; - for (auto const& url: sources[sourceName]["urls"]) + for (auto const& url: sourceValue["urls"]) { - if (!url.isString()) + if (!url.is_string()) return formatFatalError(Error::Type::JSONError, "URL must be a string."); - ReadCallback::Result result = m_readFile(ReadCallback::kindString(ReadCallback::Kind::ReadFile), url.asString()); + ReadCallback::Result result = m_readFile(ReadCallback::kindString(ReadCallback::Kind::ReadFile), url.get()); if (result.success) { if (!hash.empty() && !hashMatchesContent(hash, result.responseOrErrorMessage)) - ret.errors.append(formatError( + ret.errors.emplace_back(formatError( Error::Type::IOError, "general", - "Mismatch between content and supplied hash for \"" + sourceName + "\" at \"" + url.asString() + "\"" + "Mismatch between content and supplied hash for \"" + sourceName + "\" at \"" + url.get() + "\"" )); else { @@ -713,14 +710,14 @@ std::variant StandardCompiler: } else failures.push_back( - "Cannot import url (\"" + url.asString() + "\"): " + result.responseOrErrorMessage + "Cannot import url (\"" + url.get() + "\"): " + result.responseOrErrorMessage ); } for (auto const& failure: failures) { /// If the import succeeded, let mark all the others as warnings, otherwise all of them are errors. - ret.errors.append(formatError( + ret.errors.emplace_back(formatError( found ? Error::Type::Warning : Error::Type::IOError, "general", failure @@ -733,25 +730,25 @@ std::variant StandardCompiler: } else if (ret.language == "SolidityAST") { - for (auto const& sourceName: sources.getMemberNames()) - ret.sources[sourceName] = util::jsonCompactPrint(sources[sourceName]); + for (auto const& [sourceName, sourceValue]: sources.items()) + ret.sources[sourceName] = util::jsonCompactPrint(sourceValue); } else if (ret.language == "EVMAssembly") { - for (std::string const& sourceName: sources.getMemberNames()) + for (auto const& [sourceName, sourceValue]: sources.items()) { - solAssert(sources.isMember(sourceName)); + solAssert(sources.contains(sourceName)); if ( - !sources[sourceName].isMember("assemblyJson") || - !sources[sourceName]["assemblyJson"].isObject() || - sources[sourceName].size() != 1 + !sourceValue.contains("assemblyJson") || + !sourceValue["assemblyJson"].is_object() || + sourceValue.size() != 1 ) return formatFatalError( Error::Type::JSONError, "Invalid input source specified. Expected exactly one object, named 'assemblyJson', inside $.sources." + sourceName ); - ret.jsonSources[sourceName] = sources[sourceName]["assemblyJson"]; + ret.jsonSources[sourceName] = sourceValue["assemblyJson"]; } if (ret.jsonSources.size() != 1) return formatFatalError( @@ -759,20 +756,20 @@ std::variant StandardCompiler: "EVMAssembly import only supports exactly one input file." ); } - Json::Value const& auxInputs = _input["auxiliaryInput"]; + Json const& auxInputs = _input.value("auxiliaryInput", Json::object()); if (auto result = checkAuxiliaryInputKeys(auxInputs)) return *result; - if (!!auxInputs) + if (!auxInputs.empty()) { - Json::Value const& smtlib2Responses = auxInputs["smtlib2responses"]; - if (!!smtlib2Responses) + Json const& smtlib2Responses = auxInputs.value("smtlib2responses", Json::object()); + if (!smtlib2Responses.empty()) { - if (!smtlib2Responses.isObject()) + if (!smtlib2Responses.is_object()) return formatFatalError(Error::Type::JSONError, "\"auxiliaryInput.smtlib2responses\" must be an object."); - for (auto const& hashString: smtlib2Responses.getMemberNames()) + for (auto const& [hashString, response]: smtlib2Responses.items()) { util::h256 hash; try @@ -784,49 +781,49 @@ std::variant StandardCompiler: return formatFatalError(Error::Type::JSONError, "Invalid hex encoding of SMTLib2 auxiliary input."); } - if (!smtlib2Responses[hashString].isString()) + if (!response.is_string()) return formatFatalError( Error::Type::JSONError, "\"smtlib2Responses." + hashString + "\" must be a string." ); - ret.smtLib2Responses[hash] = smtlib2Responses[hashString].asString(); + ret.smtLib2Responses[hash] = response.get(); } } } - Json::Value const& settings = _input.get("settings", Json::Value()); + Json const& settings = _input.value("settings", Json::object()); if (auto result = checkSettingsKeys(settings)) return *result; - if (settings.isMember("stopAfter")) + if (settings.contains("stopAfter")) { - if (!settings["stopAfter"].isString()) + if (!settings["stopAfter"].is_string()) return formatFatalError(Error::Type::JSONError, "\"settings.stopAfter\" must be a string."); - if (settings["stopAfter"].asString() != "parsing") + if (settings["stopAfter"].get() != "parsing") return formatFatalError(Error::Type::JSONError, "Invalid value for \"settings.stopAfter\". Only valid value is \"parsing\"."); ret.stopAfter = CompilerStack::State::Parsed; } - if (settings.isMember("viaIR")) + if (settings.contains("viaIR")) { - if (!settings["viaIR"].isBool()) + if (!settings["viaIR"].is_boolean()) return formatFatalError(Error::Type::JSONError, "\"settings.viaIR\" must be a Boolean."); - ret.viaIR = settings["viaIR"].asBool(); + ret.viaIR = settings["viaIR"].get(); } - if (settings.isMember("evmVersion")) + if (settings.contains("evmVersion")) { - if (!settings["evmVersion"].isString()) + if (!settings["evmVersion"].is_string()) return formatFatalError(Error::Type::JSONError, "evmVersion must be a string."); - std::optional version = langutil::EVMVersion::fromString(settings["evmVersion"].asString()); + std::optional version = langutil::EVMVersion::fromString(settings["evmVersion"].get()); if (!version) return formatFatalError(Error::Type::JSONError, "Invalid EVM version requested."); if (version < EVMVersion::constantinople()) - ret.errors.append(formatError( + ret.errors.emplace_back(formatError( Error::Type::Warning, "general", "Support for EVM versions older than constantinople is deprecated and will be removed in the future." @@ -834,26 +831,26 @@ std::variant StandardCompiler: ret.evmVersion = *version; } - if (settings.isMember("eofVersion")) + if (settings.contains("eofVersion")) { - if (!settings["eofVersion"].isUInt()) + if (!settings["eofVersion"].is_number_unsigned()) return formatFatalError(Error::Type::JSONError, "eofVersion must be an unsigned integer."); - auto eofVersion = settings["evmVersion"].asUInt(); + auto eofVersion = settings["evmVersion"].get(); if (eofVersion != 1) return formatFatalError(Error::Type::JSONError, "Invalid EOF version requested."); ret.eofVersion = 1; } - if (settings.isMember("debug")) + if (settings.contains("debug")) { if (auto result = checkKeys(settings["debug"], {"revertStrings", "debugInfo"}, "settings.debug")) return *result; - if (settings["debug"].isMember("revertStrings")) + if (settings["debug"].contains("revertStrings")) { - if (!settings["debug"]["revertStrings"].isString()) + if (!settings["debug"]["revertStrings"].is_string()) return formatFatalError(Error::Type::JSONError, "settings.debug.revertStrings must be a string."); - std::optional revertStrings = revertStringsFromString(settings["debug"]["revertStrings"].asString()); + std::optional revertStrings = revertStringsFromString(settings["debug"]["revertStrings"].get()); if (!revertStrings) return formatFatalError(Error::Type::JSONError, "Invalid value for settings.debug.revertStrings."); if (*revertStrings == RevertStrings::VerboseDebug) @@ -864,14 +861,14 @@ std::variant StandardCompiler: ret.revertStrings = *revertStrings; } - if (settings["debug"].isMember("debugInfo")) + if (settings["debug"].contains("debugInfo")) { - if (!settings["debug"]["debugInfo"].isArray()) + if (!settings["debug"]["debugInfo"].is_array()) return formatFatalError(Error::Type::JSONError, "settings.debug.debugInfo must be an array."); std::vector components; - for (Json::Value const& arrayValue: settings["debug"]["debugInfo"]) - components.push_back(arrayValue.asString()); + for (Json const& arrayValue: settings["debug"]["debugInfo"]) + components.push_back(arrayValue.get()); std::optional debugInfoSelection = DebugInfoSelection::fromComponents( components, @@ -890,41 +887,40 @@ std::variant StandardCompiler: } } - if (settings.isMember("remappings") && !settings["remappings"].isArray()) + if (settings.contains("remappings") && !settings["remappings"].is_array()) return formatFatalError(Error::Type::JSONError, "\"settings.remappings\" must be an array of strings."); - for (auto const& remapping: settings.get("remappings", Json::Value())) + for (auto const& remapping: settings.value("remappings", Json::object())) { - if (!remapping.isString()) + if (!remapping.is_string()) return formatFatalError(Error::Type::JSONError, "\"settings.remappings\" must be an array of strings"); - if (auto r = ImportRemapper::parseRemapping(remapping.asString())) + if (auto r = ImportRemapper::parseRemapping(remapping.get())) ret.remappings.emplace_back(std::move(*r)); else - return formatFatalError(Error::Type::JSONError, "Invalid remapping: \"" + remapping.asString() + "\""); + return formatFatalError(Error::Type::JSONError, "Invalid remapping: \"" + remapping.get() + "\""); } - if (settings.isMember("optimizer")) + if (settings.contains("optimizer")) { auto optimiserSettings = parseOptimizerSettings(settings["optimizer"]); - if (std::holds_alternative(optimiserSettings)) - return std::get(std::move(optimiserSettings)); // was an error + if (std::holds_alternative(optimiserSettings)) + return std::get(std::move(optimiserSettings)); // was an error else ret.optimiserSettings = std::get(std::move(optimiserSettings)); } - Json::Value jsonLibraries = settings.get("libraries", Json::Value(Json::objectValue)); - if (!jsonLibraries.isObject()) + Json const& jsonLibraries = settings.value("libraries", Json::object()); + if (!jsonLibraries.is_object()) return formatFatalError(Error::Type::JSONError, "\"libraries\" is not a JSON object."); - for (auto const& sourceName: jsonLibraries.getMemberNames()) + for (auto const& [sourceName, jsonSourceName]: jsonLibraries.items()) { - auto const& jsonSourceName = jsonLibraries[sourceName]; - if (!jsonSourceName.isObject()) + if (!jsonSourceName.is_object()) return formatFatalError(Error::Type::JSONError, "Library entry is not a JSON object."); - for (auto const& library: jsonSourceName.getMemberNames()) + for (auto const& [library, libraryValue]: jsonSourceName.items()) { - if (!jsonSourceName[library].isString()) + if (!libraryValue.is_string()) return formatFatalError(Error::Type::JSONError, "Library address must be a string."); - std::string address = jsonSourceName[library].asString(); + std::string address = libraryValue.get(); if (!boost::starts_with(address, "0x")) return formatFatalError( @@ -952,21 +948,24 @@ std::variant StandardCompiler: } } - Json::Value metadataSettings = settings.get("metadata", Json::Value()); + Json const& metadataSettings = settings.value("metadata", Json::object()); if (auto result = checkMetadataKeys(metadataSettings)) return *result; solAssert(CompilerStack::defaultMetadataFormat() != CompilerStack::MetadataFormat::NoMetadata, ""); ret.metadataFormat = - metadataSettings.get("appendCBOR", Json::Value(true)).asBool() ? + metadataSettings.value("appendCBOR", Json(true)) ? CompilerStack::defaultMetadataFormat() : CompilerStack::MetadataFormat::NoMetadata; - ret.metadataLiteralSources = metadataSettings.get("useLiteralContent", Json::Value(false)).asBool(); - if (metadataSettings.isMember("bytecodeHash")) + ret.metadataLiteralSources = + metadataSettings.contains("useLiteralContent") && + metadataSettings["useLiteralContent"].is_boolean() && + metadataSettings["useLiteralContent"].get(); + if (metadataSettings.contains("bytecodeHash")) { - auto metadataHash = metadataSettings["bytecodeHash"].asString(); + auto metadataHash = metadataSettings["bytecodeHash"].get(); ret.metadataHash = metadataHash == "ipfs" ? CompilerStack::MetadataHash::IPFS : @@ -982,12 +981,12 @@ std::variant StandardCompiler: ); } - Json::Value outputSelection = settings.get("outputSelection", Json::Value()); + Json const& outputSelection = settings.value("outputSelection", Json::object()); if (auto jsonError = checkOutputSelection(outputSelection)) return *jsonError; - ret.outputSelection = std::move(outputSelection); + ret.outputSelection = outputSelection; if (ret.stopAfter != CompilerStack::State::CompilationSuccessful && isBinaryRequested(ret.outputSelection)) return formatFatalError( @@ -995,34 +994,33 @@ std::variant StandardCompiler: "Requested output selection conflicts with \"settings.stopAfter\"." ); - Json::Value const& modelCheckerSettings = settings.get("modelChecker", Json::Value()); + Json const& modelCheckerSettings = settings.value("modelChecker", Json::object()); if (auto result = checkModelCheckerSettingsKeys(modelCheckerSettings)) return *result; - if (modelCheckerSettings.isMember("contracts")) + if (modelCheckerSettings.contains("contracts")) { auto const& sources = modelCheckerSettings["contracts"]; - if (!sources.isObject() && !sources.isNull()) + if (!sources.is_object() && !sources.is_null()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.contracts is not a JSON object."); std::map> sourceContracts; - for (auto const& source: sources.getMemberNames()) + for (auto const& [source, contracts]: sources.items()) { if (source.empty()) return formatFatalError(Error::Type::JSONError, "Source name cannot be empty."); - auto const& contracts = sources[source]; - if (!contracts.isArray()) + if (!contracts.is_array()) return formatFatalError(Error::Type::JSONError, "Source contracts must be an array."); for (auto const& contract: contracts) { - if (!contract.isString()) + if (!contract.is_string()) return formatFatalError(Error::Type::JSONError, "Every contract in settings.modelChecker.contracts must be a string."); - if (contract.asString().empty()) + if (contract.get().empty()) return formatFatalError(Error::Type::JSONError, "Contract name cannot be empty."); - sourceContracts[source].insert(contract.asString()); + sourceContracts[source].insert(contract.get()); } if (sourceContracts[source].empty()) @@ -1031,56 +1029,56 @@ std::variant StandardCompiler: ret.modelCheckerSettings.contracts = {std::move(sourceContracts)}; } - if (modelCheckerSettings.isMember("divModNoSlacks")) + if (modelCheckerSettings.contains("divModNoSlacks")) { auto const& divModNoSlacks = modelCheckerSettings["divModNoSlacks"]; - if (!divModNoSlacks.isBool()) + if (!divModNoSlacks.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.divModNoSlacks must be a Boolean."); - ret.modelCheckerSettings.divModNoSlacks = divModNoSlacks.asBool(); + ret.modelCheckerSettings.divModNoSlacks = divModNoSlacks.get(); } - if (modelCheckerSettings.isMember("engine")) + if (modelCheckerSettings.contains("engine")) { - if (!modelCheckerSettings["engine"].isString()) + if (!modelCheckerSettings["engine"].is_string()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.engine must be a string."); - std::optional engine = ModelCheckerEngine::fromString(modelCheckerSettings["engine"].asString()); + std::optional engine = ModelCheckerEngine::fromString(modelCheckerSettings["engine"].get()); if (!engine) return formatFatalError(Error::Type::JSONError, "Invalid model checker engine requested."); ret.modelCheckerSettings.engine = *engine; } - if (modelCheckerSettings.isMember("bmcLoopIterations")) + if (modelCheckerSettings.contains("bmcLoopIterations")) { if (!ret.modelCheckerSettings.engine.bmc) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.bmcLoopIterations requires the BMC engine to be enabled."); - if (modelCheckerSettings["bmcLoopIterations"].isUInt()) - ret.modelCheckerSettings.bmcLoopIterations = modelCheckerSettings["bmcLoopIterations"].asUInt(); + if (modelCheckerSettings["bmcLoopIterations"].is_number_unsigned()) + ret.modelCheckerSettings.bmcLoopIterations = modelCheckerSettings["bmcLoopIterations"].get(); else return formatFatalError(Error::Type::JSONError, "settings.modelChecker.bmcLoopIterations must be an unsigned integer."); } - if (modelCheckerSettings.isMember("extCalls")) + if (modelCheckerSettings.contains("extCalls")) { - if (!modelCheckerSettings["extCalls"].isString()) + if (!modelCheckerSettings["extCalls"].is_string()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.extCalls must be a string."); - std::optional extCalls = ModelCheckerExtCalls::fromString(modelCheckerSettings["extCalls"].asString()); + std::optional extCalls = ModelCheckerExtCalls::fromString(modelCheckerSettings["extCalls"].get()); if (!extCalls) return formatFatalError(Error::Type::JSONError, "Invalid model checker extCalls requested."); ret.modelCheckerSettings.externalCalls = *extCalls; } - if (modelCheckerSettings.isMember("invariants")) + if (modelCheckerSettings.contains("invariants")) { auto const& invariantsArray = modelCheckerSettings["invariants"]; - if (!invariantsArray.isArray()) + if (!invariantsArray.is_array()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.invariants must be an array."); ModelCheckerInvariants invariants; for (auto const& i: invariantsArray) { - if (!i.isString()) + if (!i.is_string()) return formatFatalError(Error::Type::JSONError, "Every invariant type in settings.modelChecker.invariants must be a string."); - if (!invariants.setFromString(i.asString())) + if (!invariants.setFromString(i.get())) return formatFatalError(Error::Type::JSONError, "Invalid model checker invariants requested."); } @@ -1090,72 +1088,72 @@ std::variant StandardCompiler: ret.modelCheckerSettings.invariants = invariants; } - if (modelCheckerSettings.isMember("showProvedSafe")) + if (modelCheckerSettings.contains("showProvedSafe")) { auto const& showProvedSafe = modelCheckerSettings["showProvedSafe"]; - if (!showProvedSafe.isBool()) + if (!showProvedSafe.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.showProvedSafe must be a Boolean value."); - ret.modelCheckerSettings.showProvedSafe = showProvedSafe.asBool(); + ret.modelCheckerSettings.showProvedSafe = showProvedSafe.get(); } - if (modelCheckerSettings.isMember("showUnproved")) + if (modelCheckerSettings.contains("showUnproved")) { auto const& showUnproved = modelCheckerSettings["showUnproved"]; - if (!showUnproved.isBool()) + if (!showUnproved.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.showUnproved must be a Boolean value."); - ret.modelCheckerSettings.showUnproved = showUnproved.asBool(); + ret.modelCheckerSettings.showUnproved = showUnproved.get(); } - if (modelCheckerSettings.isMember("showUnsupported")) + if (modelCheckerSettings.contains("showUnsupported")) { auto const& showUnsupported = modelCheckerSettings["showUnsupported"]; - if (!showUnsupported.isBool()) + if (!showUnsupported.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.showUnsupported must be a Boolean value."); - ret.modelCheckerSettings.showUnsupported = showUnsupported.asBool(); + ret.modelCheckerSettings.showUnsupported = showUnsupported.get(); } - if (modelCheckerSettings.isMember("solvers")) + if (modelCheckerSettings.contains("solvers")) { auto const& solversArray = modelCheckerSettings["solvers"]; - if (!solversArray.isArray()) + if (!solversArray.is_array()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.solvers must be an array."); smtutil::SMTSolverChoice solvers; for (auto const& s: solversArray) { - if (!s.isString()) + if (!s.is_string()) return formatFatalError(Error::Type::JSONError, "Every target in settings.modelChecker.solvers must be a string."); - if (!solvers.setSolver(s.asString())) + if (!solvers.setSolver(s.get())) return formatFatalError(Error::Type::JSONError, "Invalid model checker solvers requested."); } ret.modelCheckerSettings.solvers = solvers; } - if (modelCheckerSettings.isMember("printQuery")) + if (modelCheckerSettings.contains("printQuery")) { auto const& printQuery = modelCheckerSettings["printQuery"]; - if (!printQuery.isBool()) + if (!printQuery.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.printQuery must be a Boolean value."); if (!(ret.modelCheckerSettings.solvers == smtutil::SMTSolverChoice::SMTLIB2())) return formatFatalError(Error::Type::JSONError, "Only SMTLib2 solver can be enabled to print queries"); - ret.modelCheckerSettings.printQuery = printQuery.asBool(); + ret.modelCheckerSettings.printQuery = printQuery.get(); } - if (modelCheckerSettings.isMember("targets")) + if (modelCheckerSettings.contains("targets")) { auto const& targetsArray = modelCheckerSettings["targets"]; - if (!targetsArray.isArray()) + if (!targetsArray.is_array()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.targets must be an array."); ModelCheckerTargets targets; for (auto const& t: targetsArray) { - if (!t.isString()) + if (!t.is_string()) return formatFatalError(Error::Type::JSONError, "Every target in settings.modelChecker.targets must be a string."); - if (!targets.setFromString(t.asString())) + if (!targets.setFromString(t.get())) return formatFatalError(Error::Type::JSONError, "Invalid model checker targets requested."); } @@ -1165,45 +1163,45 @@ std::variant StandardCompiler: ret.modelCheckerSettings.targets = targets; } - if (modelCheckerSettings.isMember("timeout")) + if (modelCheckerSettings.contains("timeout")) { - if (!modelCheckerSettings["timeout"].isUInt()) + if (!modelCheckerSettings["timeout"].is_number_unsigned()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.timeout must be an unsigned integer."); - ret.modelCheckerSettings.timeout = modelCheckerSettings["timeout"].asUInt(); + ret.modelCheckerSettings.timeout = modelCheckerSettings["timeout"].get(); } return {std::move(ret)}; } -std::map StandardCompiler::parseAstFromInput(StringMap const& _sources) +std::map StandardCompiler::parseAstFromInput(StringMap const& _sources) { - std::map sourceJsons; + std::map sourceJsons; for (auto const& [sourceName, sourceCode]: _sources) { - Json::Value ast; + Json ast; astAssert(util::jsonParseStrict(sourceCode, ast), "Input file could not be parsed to JSON"); - std::string astKey = ast.isMember("ast") ? "ast" : "AST"; + std::string astKey = ast.contains("ast") ? "ast" : "AST"; - astAssert(ast.isMember(astKey), "astkey is not member"); - astAssert(ast[astKey]["nodeType"].asString() == "SourceUnit", "Top-level node should be a 'SourceUnit'"); + astAssert(ast.contains(astKey), "astkey is not member"); + astAssert(ast[astKey]["nodeType"].get() == "SourceUnit", "Top-level node should be a 'SourceUnit'"); astAssert(sourceJsons.count(sourceName) == 0, "All sources must have unique names"); sourceJsons.emplace(sourceName, std::move(ast[astKey])); } return sourceJsons; } -Json::Value StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _inputsAndSettings) +Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _inputsAndSettings) { solAssert(_inputsAndSettings.language == "EVMAssembly"); solAssert(_inputsAndSettings.sources.empty()); solAssert(_inputsAndSettings.jsonSources.size() == 1); if (!isBinaryRequested(_inputsAndSettings.outputSelection)) - return Json::objectValue; + return Json::object(); evmasm::EVMAssemblyStack stack(_inputsAndSettings.evmVersion); std::string const& sourceName = _inputsAndSettings.jsonSources.begin()->first; // result of structured binding can only be used within lambda from C++20 on. - Json::Value const& sourceJson = _inputsAndSettings.jsonSources.begin()->second; + Json const& sourceJson = _inputsAndSettings.jsonSources.begin()->second; try { stack.analyze(sourceName, sourceJson); @@ -1226,11 +1224,11 @@ Json::Value StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSetti ); } if (!stack.compilationSuccessful()) - return Json::objectValue; + return Json::object(); // EVM bool const wildcardMatchesExperimental = false; - Json::Value evmData = Json::objectValue; + Json evmData; if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "evm.assembly", wildcardMatchesExperimental)) evmData["assembly"] = stack.assemblyString(sourceName, {}); if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "evm.legacyAssembly", wildcardMatchesExperimental)) @@ -1284,18 +1282,18 @@ Json::Value StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSetti } ); - Json::Value contractData = Json::objectValue; + Json contractData; if (!evmData.empty()) contractData["evm"] = evmData; - Json::Value contractsOutput = Json::objectValue; + Json contractsOutput; contractsOutput[sourceName][""] = contractData; - Json::Value output = Json::objectValue; + Json output; output["contracts"] = contractsOutput; return util::removeNullMembers(output); } -Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inputsAndSettings) +Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inputsAndSettings) { solAssert(_inputsAndSettings.jsonSources.empty()); @@ -1323,7 +1321,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting compilerStack.enableEvmBytecodeGeneration(isEvmBytecodeRequested(_inputsAndSettings.outputSelection)); compilerStack.enableIRGeneration(isIRRequested(_inputsAndSettings.outputSelection)); - Json::Value errors = std::move(_inputsAndSettings.errors); + Json errors = std::move(_inputsAndSettings.errors); bool const binariesRequested = isBinaryRequested(_inputsAndSettings.outputSelection); @@ -1335,7 +1333,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting { compilerStack.importASTs(parseAstFromInput(sourceList)); if (!compilerStack.analyze()) - errors.append(formatError(Error::Type::FatalError, "general", "Analysis of the AST failed.")); + errors.emplace_back(formatError(Error::Type::FatalError, "general", "Analysis of the AST failed.")); if (binariesRequested) compilerStack.compile(); } @@ -1352,7 +1350,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting compilerStack.parseAndAnalyze(_inputsAndSettings.stopAfter); for (auto const& error: compilerStack.errors()) - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, *error, error->type(), @@ -1365,7 +1363,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting /// This is only thrown in a very few locations. catch (Error const& _error) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _error, _error.type(), @@ -1376,7 +1374,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting /// This should not be leaked from compile(). catch (FatalError const& _exception) { - errors.append(formatError( + errors.emplace_back(formatError( Error::Type::FatalError, "general", "Uncaught fatal error: " + boost::diagnostic_information(_exception) @@ -1384,7 +1382,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (CompilerError const& _exception) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _exception, Error::Type::CompilerError, @@ -1394,7 +1392,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (InternalCompilerError const& _exception) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _exception, Error::Type::InternalCompilerError, @@ -1404,7 +1402,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (UnimplementedFeatureError const& _exception) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _exception, Error::Type::UnimplementedFeatureError, @@ -1414,7 +1412,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (yul::YulException const& _exception) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _exception, Error::Type::YulException, @@ -1424,7 +1422,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (smtutil::SMTLogicError const& _exception) { - errors.append(formatErrorWithException( + errors.emplace_back(formatErrorWithException( compilerStack, _exception, Error::Type::SMTLogicException, @@ -1434,7 +1432,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (util::Exception const& _exception) { - errors.append(formatError( + errors.emplace_back(formatError( Error::Type::Exception, "general", "Exception during compilation: " + boost::diagnostic_information(_exception) @@ -1442,7 +1440,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (std::exception const& _exception) { - errors.append(formatError( + errors.emplace_back(formatError( Error::Type::Exception, "general", "Unknown exception during compilation: " + boost::diagnostic_information(_exception) @@ -1450,7 +1448,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } catch (...) { - errors.append(formatError( + errors.emplace_back(formatError( Error::Type::Exception, "general", "Unknown exception during compilation: " + boost::current_exception_diagnostic_information() @@ -1473,7 +1471,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting ) return formatFatalError(Error::Type::InternalCompilerError, "No error reported, but compilation failed."); - Json::Value output = Json::objectValue; + Json output; if (errors.size() > 0) output["errors"] = std::move(errors); @@ -1484,21 +1482,21 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting bool const wildcardMatchesExperimental = false; - output["sources"] = Json::objectValue; + output["sources"] = Json::object(); unsigned sourceIndex = 0; // NOTE: A case that will pass `parsingSuccess && !analysisFailed` but not `analysisSuccess` is // stopAfter: parsing with no parsing errors. if (parsingSuccess && !analysisFailed) for (std::string const& sourceName: compilerStack.sourceNames()) { - Json::Value sourceResult = Json::objectValue; + Json sourceResult; sourceResult["id"] = sourceIndex++; if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "ast", wildcardMatchesExperimental)) sourceResult["ast"] = ASTJsonExporter(compilerStack.state(), compilerStack.sourceIndices()).toJson(compilerStack.ast(sourceName)); output["sources"][sourceName] = sourceResult; } - Json::Value contractsOutput = Json::objectValue; + Json contractsOutput; for (std::string const& contractName: analysisSuccess ? compilerStack.contractNames() : std::vector()) { size_t colon = contractName.rfind(':'); @@ -1507,7 +1505,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting std::string name = contractName.substr(colon + 1); // ABI, storage layout, documentation and metadata - Json::Value contractData(Json::objectValue); + Json contractData; if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "abi", wildcardMatchesExperimental)) contractData["abi"] = compilerStack.contractABI(contractName); if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "storageLayout", false)) @@ -1530,7 +1528,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting contractData["irOptimizedAst"] = compilerStack.yulIROptimizedAst(contractName); // EVM - Json::Value evmData(Json::objectValue); + Json evmData; if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.assembly", wildcardMatchesExperimental)) evmData["assembly"] = compilerStack.assemblyString(contractName, sourceList); if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.legacyAssembly", wildcardMatchesExperimental)) @@ -1589,8 +1587,8 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting if (!contractData.empty()) { - if (!contractsOutput.isMember(file)) - contractsOutput[file] = Json::objectValue; + if (!contractsOutput.contains(file)) + contractsOutput[file] = Json::object(); contractsOutput[file][name] = contractData; } } @@ -1601,16 +1599,16 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting } -Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) +Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) { solAssert(_inputsAndSettings.jsonSources.empty()); - Json::Value output = Json::objectValue; + Json output; output["errors"] = std::move(_inputsAndSettings.errors); if (_inputsAndSettings.sources.size() != 1) { - output["errors"].append(formatError( + output["errors"].emplace_back(formatError( Error::Type::JSONError, "general", "Yul mode only supports exactly one input file." @@ -1619,7 +1617,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) } if (!_inputsAndSettings.smtLib2Responses.empty()) { - output["errors"].append(formatError( + output["errors"].emplace_back(formatError( Error::Type::JSONError, "general", "Yul mode does not support smtlib2responses." @@ -1628,7 +1626,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) } if (!_inputsAndSettings.remappings.empty()) { - output["errors"].append(formatError( + output["errors"].emplace_back(formatError( Error::Type::JSONError, "general", "Field \"settings.remappings\" cannot be used for Yul." @@ -1637,7 +1635,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) } if (_inputsAndSettings.revertStrings != RevertStrings::Default) { - output["errors"].append(formatError( + output["errors"].emplace_back(formatError( Error::Type::JSONError, "general", "Field \"settings.debug.revertStrings\" cannot be used for Yul." @@ -1660,7 +1658,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) // Inconsistent state - stop here to receive error reports from users if (!stack.parseAndAnalyze(sourceName, sourceContents) && stack.errors().empty()) { - output["errors"].append(formatError( + output["errors"].emplace_back(formatError( Error::Type::InternalCompilerError, "general", "No error reported, but compilation failed." @@ -1674,7 +1672,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) { auto err = std::dynamic_pointer_cast(error); - output["errors"].append(formatErrorWithException( + output["errors"].emplace_back(formatErrorWithException( stack, *error, err->type(), @@ -1693,7 +1691,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ast", wildcardMatchesExperimental)) { - Json::Value sourceResult = Json::objectValue; + Json sourceResult; sourceResult["id"] = 0; sourceResult["ast"] = stack.astJson(); output["sources"][sourceName] = sourceResult; @@ -1725,7 +1723,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) _inputsAndSettings.evmVersion, *o.bytecode, o.sourceMappings.get(), - Json::arrayValue, + Json::array(), isDeployed, [&, kind = kind](std::string const& _element) { return isArtifactRequested( _inputsAndSettings.outputSelection, @@ -1745,16 +1743,15 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) return output; } - -Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept +Json StandardCompiler::compile(Json const& _input) noexcept { YulStringRepository::reset(); try { auto parsed = parseInput(_input); - if (std::holds_alternative(parsed)) - return std::get(std::move(parsed)); + if (std::holds_alternative(parsed)) + return std::get(std::move(parsed)); InputsAndSettings settings = std::get(std::move(parsed)); if (settings.language == "Solidity") return compileSolidity(std::move(settings)); @@ -1767,13 +1764,29 @@ Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept else return formatFatalError(Error::Type::JSONError, "Only \"Solidity\", \"Yul\", \"SolidityAST\" or \"EVMAssembly\" is supported as a language."); } - catch (Json::LogicError const& _exception) + catch (Json::parse_error const& _exception) + { + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON parse_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); + } + catch (Json::invalid_iterator const& _exception) + { + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON invalid_iterator exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); + } + catch (Json::type_error const& _exception) + { + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON type_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); + } + catch (Json::out_of_range const& _exception) { - return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON logic exception: ") + _exception.what()); + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON out_of_range exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); } - catch (Json::RuntimeError const& _exception) + catch (Json::other_error const& _exception) { - return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON runtime exception: ") + _exception.what()); + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON other_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); + } + catch (Json::exception const& _exception) + { + return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON runtime exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); } catch (util::Exception const& _exception) { @@ -1787,7 +1800,7 @@ Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept std::string StandardCompiler::compile(std::string const& _input) noexcept { - Json::Value input; + Json input; std::string errors; try { @@ -1796,12 +1809,15 @@ std::string StandardCompiler::compile(std::string const& _input) noexcept } catch (...) { - return "{\"errors\":[{\"type\":\"JSONError\",\"component\":\"general\",\"severity\":\"error\",\"message\":\"Error parsing input JSON.\"}]}"; + if (errors.empty()) + return "{\"errors\":[{\"type\":\"JSONError\",\"component\":\"general\",\"severity\":\"error\",\"message\":\"Error parsing input JSON.\"}]}"; + else + return "{\"errors\":[{\"type\":\"JSONError\",\"component\":\"general\",\"severity\":\"error\",\"message\":\"Error parsing input JSON: " + errors + "\"}]}"; } - // cout << "Input: " << input.toStyledString() << endl; - Json::Value output = compile(input); - // cout << "Output: " << output.toStyledString() << endl; +// std::cout << "Input: " << solidity::util::jsonPrettyPrint(input) << std::endl; + Json output = compile(input); +// std::cout << "Output: " << solidity::util::jsonPrettyPrint(output) << std::endl; try { @@ -1813,24 +1829,25 @@ std::string StandardCompiler::compile(std::string const& _input) noexcept } } -Json::Value StandardCompiler::formatFunctionDebugData( +Json StandardCompiler::formatFunctionDebugData( std::map const& _debugInfo ) { - Json::Value ret(Json::objectValue); + static_assert(std::is_same_v); + Json ret = Json::object(); for (auto const& [name, info]: _debugInfo) { - Json::Value fun; + Json fun = Json::object(); if (info.sourceID) - fun["id"] = Json::UInt64(*info.sourceID); + fun["id"] = Json::number_unsigned_t(*info.sourceID); else - fun["id"] = Json::nullValue; + fun["id"] = Json(); if (info.bytecodeOffset) - fun["entryPoint"] = Json::UInt64(*info.bytecodeOffset); + fun["entryPoint"] = Json::number_unsigned_t(*info.bytecodeOffset); else - fun["entryPoint"] = Json::nullValue; - fun["parameterSlots"] = Json::UInt64(info.params); - fun["returnSlots"] = Json::UInt64(info.returns); + fun["entryPoint"] = Json(); + fun["parameterSlots"] = Json::number_unsigned_t(info.params); + fun["returnSlots"] = Json::number_unsigned_t(info.returns); ret[name] = std::move(fun); } diff --git a/libsolidity/interface/StandardCompiler.h b/libsolidity/interface/StandardCompiler.h index 03bdc7f12..590d96b9c 100644 --- a/libsolidity/interface/StandardCompiler.h +++ b/libsolidity/interface/StandardCompiler.h @@ -58,12 +58,12 @@ class StandardCompiler /// Sets all input parameters according to @a _input which conforms to the standardized input /// format, performs compilation and returns a standardized output. - Json::Value compile(Json::Value const& _input) noexcept; + Json compile(Json const& _input) noexcept; /// Parses input as JSON and performs the above processing steps, returning a serialized JSON /// output. Parsing errors are returned as regular errors. std::string compile(std::string const& _input) noexcept; - static Json::Value formatFunctionDebugData( + static Json formatFunctionDebugData( std::map const& _debugInfo ); @@ -71,10 +71,10 @@ class StandardCompiler struct InputsAndSettings { std::string language; - Json::Value errors; + Json errors; CompilerStack::State stopAfter = CompilerStack::State::CompilationSuccessful; std::map sources; - std::map jsonSources; + std::map jsonSources; std::map smtLib2Responses; langutil::EVMVersion evmVersion; std::optional eofVersion; @@ -86,19 +86,19 @@ class StandardCompiler bool metadataLiteralSources = false; CompilerStack::MetadataFormat metadataFormat = CompilerStack::defaultMetadataFormat(); CompilerStack::MetadataHash metadataHash = CompilerStack::MetadataHash::IPFS; - Json::Value outputSelection; + Json outputSelection; ModelCheckerSettings modelCheckerSettings = ModelCheckerSettings{}; bool viaIR = false; }; /// Parses the input json (and potentially invokes the read callback) and either returns /// it in condensed form or an error as a json object. - std::variant parseInput(Json::Value const& _input); + std::variant parseInput(Json const& _input); - std::map parseAstFromInput(StringMap const& _sources); - Json::Value importEVMAssembly(InputsAndSettings _inputsAndSettings); - Json::Value compileSolidity(InputsAndSettings _inputsAndSettings); - Json::Value compileYul(InputsAndSettings _inputsAndSettings); + std::map parseAstFromInput(StringMap const& _sources); + Json importEVMAssembly(InputsAndSettings _inputsAndSettings); + Json compileSolidity(InputsAndSettings _inputsAndSettings); + Json compileYul(InputsAndSettings _inputsAndSettings); ReadCallback::Callback m_readFile; diff --git a/libsolidity/interface/StorageLayout.cpp b/libsolidity/interface/StorageLayout.cpp index 8e1d0eed1..7f344f6ed 100644 --- a/libsolidity/interface/StorageLayout.cpp +++ b/libsolidity/interface/StorageLayout.cpp @@ -23,7 +23,7 @@ using namespace solidity; using namespace solidity::frontend; -Json::Value StorageLayout::generate(ContractDefinition const& _contractDef) +Json StorageLayout::generate(ContractDefinition const& _contractDef) { solAssert(!m_contract, ""); m_contract = &_contractDef; @@ -34,19 +34,19 @@ Json::Value StorageLayout::generate(ContractDefinition const& _contractDef) auto contractType = dynamic_cast(typeType->actualType()); solAssert(contractType, ""); - Json::Value variables(Json::arrayValue); + Json variables = Json::array(); for (auto [var, slot, offset]: contractType->stateVariables()) - variables.append(generate(*var, slot, offset)); + variables.emplace_back(generate(*var, slot, offset)); - Json::Value layout; + Json layout; layout["storage"] = std::move(variables); layout["types"] = std::move(m_types); return layout; } -Json::Value StorageLayout::generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset) +Json StorageLayout::generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset) { - Json::Value varEntry; + Json varEntry; Type const* varType = _var.type(); varEntry["label"] = _var.name(); @@ -63,22 +63,22 @@ Json::Value StorageLayout::generate(VariableDeclaration const& _var, u256 const& void StorageLayout::generate(Type const* _type) { - if (m_types.isMember(typeKeyName(_type))) + if (m_types.contains(typeKeyName(_type))) return; // Register it now to cut recursive visits. - Json::Value& typeInfo = m_types[typeKeyName(_type)]; + Json& typeInfo = m_types[typeKeyName(_type)]; typeInfo["label"] = _type->toString(true); typeInfo["numberOfBytes"] = u256(_type->storageBytes() * _type->storageSize()).str(); if (auto structType = dynamic_cast(_type)) { - Json::Value members(Json::arrayValue); + Json members = Json::array(); auto const& structDef = structType->structDefinition(); for (auto const& member: structDef.members()) { auto const& offsets = structType->storageOffsetsOfMember(member->name()); - members.append(generate(*member, offsets.first, offsets.second)); + members.emplace_back(generate(*member, offsets.first, offsets.second)); } typeInfo["members"] = std::move(members); typeInfo["encoding"] = "inplace"; @@ -108,7 +108,7 @@ void StorageLayout::generate(Type const* _type) typeInfo["encoding"] = "inplace"; } - solAssert(typeInfo.isMember("encoding"), ""); + solAssert(typeInfo.contains("encoding"), ""); } std::string StorageLayout::typeKeyName(Type const* _type) diff --git a/libsolidity/interface/StorageLayout.h b/libsolidity/interface/StorageLayout.h index ffe8e6b5a..b0b2d70b6 100644 --- a/libsolidity/interface/StorageLayout.h +++ b/libsolidity/interface/StorageLayout.h @@ -21,11 +21,10 @@ #pragma once +#include #include #include -#include - namespace solidity::frontend { @@ -35,11 +34,11 @@ class StorageLayout /// Generates the storage layout of the contract /// @param _contractDef The contract definition /// @return A JSON representation of the contract's storage layout. - Json::Value generate(ContractDefinition const& _contractDef); + Json generate(ContractDefinition const& _contractDef); private: /// Generates the JSON information for a variable and its storage location. - Json::Value generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset); + Json generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset); /// Generates the JSON information for @param _type void generate(Type const* _type); @@ -47,7 +46,7 @@ class StorageLayout /// The key for the JSON object describing a type. std::string typeKeyName(Type const* _type); - Json::Value m_types; + Json m_types; /// Current analyzed contract ContractDefinition const* m_contract = nullptr; diff --git a/libsolidity/lsp/DocumentHoverHandler.cpp b/libsolidity/lsp/DocumentHoverHandler.cpp index 39d1d72c3..e5991b765 100644 --- a/libsolidity/lsp/DocumentHoverHandler.cpp +++ b/libsolidity/lsp/DocumentHoverHandler.cpp @@ -55,7 +55,7 @@ struct MarkdownBuilder } -void DocumentHoverHandler::operator()(MessageID _id, Json::Value const& _args) +void DocumentHoverHandler::operator()(MessageID _id, Json const& _args) { auto const [sourceUnitName, lineColumn] = HandlerBase(*this).extractSourceUnitNameAndLineColumn(_args); auto const [sourceNode, sourceOffset] = m_server.astNodeAndOffsetAtSourceLocation(sourceUnitName, lineColumn); @@ -108,11 +108,11 @@ void DocumentHoverHandler::operator()(MessageID _id, Json::Value const& _args) if (tooltipText.empty()) { - client().reply(_id, Json::nullValue); + client().reply(_id, Json()); return; } - Json::Value reply = Json::objectValue; + Json reply; reply["range"] = rangeToHighlight; reply["contents"]["kind"] = "markdown"; reply["contents"]["value"] = std::move(tooltipText); diff --git a/libsolidity/lsp/DocumentHoverHandler.h b/libsolidity/lsp/DocumentHoverHandler.h index 9bb4084c2..e35e85609 100644 --- a/libsolidity/lsp/DocumentHoverHandler.h +++ b/libsolidity/lsp/DocumentHoverHandler.h @@ -26,7 +26,7 @@ class DocumentHoverHandler: public HandlerBase public: using HandlerBase::HandlerBase; - void operator()(MessageID, Json::Value const&); + void operator()(MessageID, Json const&); }; } diff --git a/libsolidity/lsp/GotoDefinition.cpp b/libsolidity/lsp/GotoDefinition.cpp index 136e4d7c3..07b0c6f0b 100644 --- a/libsolidity/lsp/GotoDefinition.cpp +++ b/libsolidity/lsp/GotoDefinition.cpp @@ -31,7 +31,7 @@ using namespace solidity::frontend; using namespace solidity::langutil; using namespace solidity::lsp; -void GotoDefinition::operator()(MessageID _id, Json::Value const& _args) +void GotoDefinition::operator()(MessageID _id, Json const& _args) { auto const [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args); @@ -58,8 +58,8 @@ void GotoDefinition::operator()(MessageID _id, Json::Value const& _args) locations.emplace_back(SourceLocation{0, 0, std::make_shared(path)}); } - Json::Value reply = Json::arrayValue; + Json reply = Json::array(); for (SourceLocation const& location: locations) - reply.append(toJson(location)); + reply.emplace_back(toJson(location)); client().reply(_id, reply); } diff --git a/libsolidity/lsp/GotoDefinition.h b/libsolidity/lsp/GotoDefinition.h index 453da3f15..4ffd64e7f 100644 --- a/libsolidity/lsp/GotoDefinition.h +++ b/libsolidity/lsp/GotoDefinition.h @@ -25,7 +25,7 @@ class GotoDefinition: public HandlerBase public: explicit GotoDefinition(LanguageServer& _server): HandlerBase(_server) {} - void operator()(MessageID, Json::Value const&); + void operator()(MessageID, Json const&); }; } diff --git a/libsolidity/lsp/HandlerBase.cpp b/libsolidity/lsp/HandlerBase.cpp index a23e43a83..c49bce1dd 100644 --- a/libsolidity/lsp/HandlerBase.cpp +++ b/libsolidity/lsp/HandlerBase.cpp @@ -29,8 +29,9 @@ using namespace solidity::langutil; using namespace solidity::lsp; using namespace solidity::util; +using namespace solidity; -Json::Value HandlerBase::toRange(SourceLocation const& _location) const +Json HandlerBase::toRange(SourceLocation const& _location) const { if (!_location.hasText()) return toJsonRange({}, {}); @@ -42,18 +43,18 @@ Json::Value HandlerBase::toRange(SourceLocation const& _location) const return toJsonRange(start, end); } -Json::Value HandlerBase::toJson(SourceLocation const& _location) const +Json HandlerBase::toJson(SourceLocation const& _location) const { solAssert(_location.sourceName); - Json::Value item = Json::objectValue; + Json item; item["uri"] = fileRepository().sourceUnitNameToUri(*_location.sourceName); item["range"] = toRange(_location); return item; } -std::pair HandlerBase::extractSourceUnitNameAndLineColumn(Json::Value const& _args) const +std::pair HandlerBase::extractSourceUnitNameAndLineColumn(Json const& _args) const { - std::string const uri = _args["textDocument"]["uri"].asString(); + std::string const uri = _args["textDocument"]["uri"].get(); std::string const sourceUnitName = fileRepository().uriToSourceUnitName(uri); if (!fileRepository().sourceUnits().count(sourceUnitName)) BOOST_THROW_EXCEPTION( diff --git a/libsolidity/lsp/HandlerBase.h b/libsolidity/lsp/HandlerBase.h index e2ccb88d8..718d15c5f 100644 --- a/libsolidity/lsp/HandlerBase.h +++ b/libsolidity/lsp/HandlerBase.h @@ -38,12 +38,12 @@ class HandlerBase public: explicit HandlerBase(LanguageServer& _server): m_server{_server} {} - Json::Value toRange(langutil::SourceLocation const& _location) const; - Json::Value toJson(langutil::SourceLocation const& _location) const; + Json toRange(langutil::SourceLocation const& _location) const; + Json toJson(langutil::SourceLocation const& _location) const; /// @returns source unit name and the line column position as extracted /// from the JSON-RPC parameters. - std::pair extractSourceUnitNameAndLineColumn(Json::Value const& _params) const; + std::pair extractSourceUnitNameAndLineColumn(Json const& _params) const; langutil::CharStreamProvider const& charStreamProvider() const noexcept { return m_server.compilerStack(); } FileRepository& fileRepository() const noexcept { return m_server.fileRepository(); } diff --git a/libsolidity/lsp/LanguageServer.cpp b/libsolidity/lsp/LanguageServer.cpp index 2b8b62706..d726139e3 100644 --- a/libsolidity/lsp/LanguageServer.cpp +++ b/libsolidity/lsp/LanguageServer.cpp @@ -52,6 +52,7 @@ using namespace std::placeholders; using namespace solidity::lsp; using namespace solidity::langutil; using namespace solidity::frontend; +using namespace solidity; namespace fs = boost::filesystem; @@ -85,44 +86,44 @@ int toDiagnosticSeverity(Error::Type _errorType) return -1; } -Json::Value semanticTokensLegend() +Json semanticTokensLegend() { - Json::Value legend = Json::objectValue; + Json legend; // NOTE! The (alphabetical) order and items must match exactly the items of // their respective enum class members. - Json::Value tokenTypes = Json::arrayValue; - tokenTypes.append("class"); - tokenTypes.append("comment"); - tokenTypes.append("enum"); - tokenTypes.append("enumMember"); - tokenTypes.append("event"); - tokenTypes.append("function"); - tokenTypes.append("interface"); - tokenTypes.append("keyword"); - tokenTypes.append("macro"); - tokenTypes.append("method"); - tokenTypes.append("modifier"); - tokenTypes.append("number"); - tokenTypes.append("operator"); - tokenTypes.append("parameter"); - tokenTypes.append("property"); - tokenTypes.append("std::string"); - tokenTypes.append("struct"); - tokenTypes.append("type"); - tokenTypes.append("typeParameter"); - tokenTypes.append("variable"); + Json tokenTypes = Json::array(); + tokenTypes.emplace_back("class"); + tokenTypes.emplace_back("comment"); + tokenTypes.emplace_back("enum"); + tokenTypes.emplace_back("enumMember"); + tokenTypes.emplace_back("event"); + tokenTypes.emplace_back("function"); + tokenTypes.emplace_back("interface"); + tokenTypes.emplace_back("keyword"); + tokenTypes.emplace_back("macro"); + tokenTypes.emplace_back("method"); + tokenTypes.emplace_back("modifier"); + tokenTypes.emplace_back("number"); + tokenTypes.emplace_back("operator"); + tokenTypes.emplace_back("parameter"); + tokenTypes.emplace_back("property"); + tokenTypes.emplace_back("std::string"); + tokenTypes.emplace_back("struct"); + tokenTypes.emplace_back("type"); + tokenTypes.emplace_back("typeParameter"); + tokenTypes.emplace_back("variable"); legend["tokenTypes"] = tokenTypes; - Json::Value tokenModifiers = Json::arrayValue; - tokenModifiers.append("abstract"); - tokenModifiers.append("declaration"); - tokenModifiers.append("definition"); - tokenModifiers.append("deprecated"); - tokenModifiers.append("documentation"); - tokenModifiers.append("modification"); - tokenModifiers.append("readonly"); + Json tokenModifiers = Json::array(); + tokenModifiers.emplace_back("abstract"); + tokenModifiers.emplace_back("declaration"); + tokenModifiers.emplace_back("definition"); + tokenModifiers.emplace_back("deprecated"); + tokenModifiers.emplace_back("documentation"); + tokenModifiers.emplace_back("modification"); + tokenModifiers.emplace_back("readonly"); legend["tokenModifiers"] = tokenModifiers; return legend; @@ -138,7 +139,7 @@ LanguageServer::LanguageServer(Transport& _transport): {"exit", [this](auto, auto) { m_state = (m_state == State::ShutdownRequested ? State::ExitRequested : State::ExitWithoutShutdown); }}, {"initialize", std::bind(&LanguageServer::handleInitialize, this, _1, _2)}, {"initialized", std::bind(&LanguageServer::handleInitialized, this, _1, _2)}, - {"$/setTrace", [this](auto, Json::Value const& args) { setTrace(args["value"]); }}, + {"$/setTrace", [this](auto, Json const& args) { setTrace(args["value"]); }}, {"shutdown", [this](auto, auto) { m_state = State::ShutdownRequested; }}, {"textDocument/definition", GotoDefinition(*this) }, {"textDocument/didOpen", std::bind(&LanguageServer::handleTextDocumentDidOpen, this, _2)}, @@ -155,17 +156,17 @@ LanguageServer::LanguageServer(Transport& _transport): { } -Json::Value LanguageServer::toRange(SourceLocation const& _location) +Json LanguageServer::toRange(SourceLocation const& _location) { return HandlerBase(*this).toRange(_location); } -Json::Value LanguageServer::toJson(SourceLocation const& _location) +Json LanguageServer::toJson(SourceLocation const& _location) { return HandlerBase(*this).toJson(_location); } -void LanguageServer::changeConfiguration(Json::Value const& _settings) +void LanguageServer::changeConfiguration(Json const& _settings) { // The settings item: "file-load-strategy" (enum) defaults to "project-directory" if not (or not correctly) set. // It can be overridden during client's handshake or at runtime, as usual. @@ -176,9 +177,9 @@ void LanguageServer::changeConfiguration(Json::Value const& _settings) // // If this value is set to "directly-opened-and-on-import", then only currently directly opened files and // those files being imported directly or indirectly will be included in operations. - if (_settings["file-load-strategy"]) + if (_settings.contains("file-load-strategy")) { - auto const text = _settings["file-load-strategy"].asString(); + auto const text = _settings["file-load-strategy"].get(); if (text == "project-directory") m_fileLoadStrategy = FileLoadStrategy::ProjectDirectory; else if (text == "directly-opened-and-on-import") @@ -188,18 +189,18 @@ void LanguageServer::changeConfiguration(Json::Value const& _settings) } m_settingsObject = _settings; - Json::Value jsonIncludePaths = _settings["include-paths"]; + Json jsonIncludePaths = _settings.contains("include-paths") ? _settings["include-paths"] : Json::object(); - if (jsonIncludePaths) + if (!jsonIncludePaths.empty()) { int typeFailureCount = 0; - if (jsonIncludePaths.isArray()) + if (jsonIncludePaths.is_array()) { std::vector includePaths; - for (Json::Value const& jsonPath: jsonIncludePaths) + for (Json const& jsonPath: jsonIncludePaths) { - if (jsonPath.isString()) - includePaths.emplace_back(boost::filesystem::path(jsonPath.asString())); + if (jsonPath.is_string()) + includePaths.emplace_back(jsonPath.get()); else typeFailureCount++; } @@ -274,11 +275,11 @@ void LanguageServer::compileAndUpdateDiagnostics() // These are the source units we will sent diagnostics to the client for sure, // even if it is just to clear previous diagnostics. - std::map diagnosticsBySourceUnit; + std::map diagnosticsBySourceUnit; for (std::string const& sourceUnitName: m_fileRepository.sourceUnits() | ranges::views::keys) - diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue; + diagnosticsBySourceUnit[sourceUnitName] = Json::array(); for (std::string const& sourceUnitName: m_nonemptyDiagnostics) - diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue; + diagnosticsBySourceUnit[sourceUnitName] = Json::array(); for (std::shared_ptr const& error: m_compilerStack.errors()) { @@ -287,10 +288,10 @@ void LanguageServer::compileAndUpdateDiagnostics() // LSP only has diagnostics applied to individual files. continue; - Json::Value jsonDiag; + Json jsonDiag; jsonDiag["source"] = "solc"; jsonDiag["severity"] = toDiagnosticSeverity(error->type()); - jsonDiag["code"] = Json::UInt64{error->errorId().error}; + jsonDiag["code"] = Json(error->errorId().error); std::string message = Error::formatErrorType(error->type()) + ":"; if (std::string const* comment = error->comment()) message += " " + *comment; @@ -300,26 +301,26 @@ void LanguageServer::compileAndUpdateDiagnostics() if (auto const* secondary = error->secondarySourceLocation()) for (auto&& [secondaryMessage, secondaryLocation]: secondary->infos) { - Json::Value jsonRelated; + Json jsonRelated; jsonRelated["message"] = secondaryMessage; jsonRelated["location"] = toJson(secondaryLocation); - jsonDiag["relatedInformation"].append(jsonRelated); + jsonDiag["relatedInformation"].emplace_back(jsonRelated); } - diagnosticsBySourceUnit[*location->sourceName].append(jsonDiag); + diagnosticsBySourceUnit[*location->sourceName].emplace_back(jsonDiag); } if (m_client.traceValue() != TraceValue::Off) { - Json::Value extra; - extra["openFileCount"] = Json::UInt64(diagnosticsBySourceUnit.size()); + Json extra; + extra["openFileCount"] = Json(diagnosticsBySourceUnit.size()); m_client.trace("Number of currently open files: " + std::to_string(diagnosticsBySourceUnit.size()), extra); } m_nonemptyDiagnostics.clear(); for (auto&& [sourceUnitName, diagnostics]: diagnosticsBySourceUnit) { - Json::Value params; + Json params; params["uri"] = m_fileRepository.sourceUnitNameToUri(sourceUnitName); if (!diagnostics.empty()) m_nonemptyDiagnostics.insert(sourceUnitName); @@ -335,14 +336,15 @@ bool LanguageServer::run() MessageID id; try { - std::optional const jsonMessage = m_client.receive(); + std::optional const jsonMessage = m_client.receive(); if (!jsonMessage) continue; - if ((*jsonMessage)["method"].isString()) + if ((*jsonMessage).contains("method") && (*jsonMessage)["method"].is_string()) { - std::string const methodName = (*jsonMessage)["method"].asString(); - id = (*jsonMessage)["id"]; + std::string const methodName = (*jsonMessage)["method"].get(); + if ((*jsonMessage).contains("id")) + id = (*jsonMessage)["id"]; lspDebug(fmt::format("received method call: {}", methodName)); if (auto handler = util::valueOrDefault(m_handlers, methodName)) @@ -353,7 +355,7 @@ bool LanguageServer::run() else m_client.error({}, ErrorCode::ParseError, "\"method\" has to be a string."); } - catch (Json::Exception const&) + catch (Json::exception const&) { m_client.error(id, ErrorCode::InvalidParams, "JSON object access error. Most likely due to a badly formatted JSON request message."s); } @@ -378,7 +380,7 @@ void LanguageServer::requireServerInitialized() ); } -void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args) +void LanguageServer::handleInitialize(MessageID _id, Json const& _args) { lspRequire( m_state == State::Started, @@ -391,9 +393,9 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args) // The default of FileReader is to use `.`, but the path from where the LSP was started // should not matter. std::string rootPath("/"); - if (Json::Value uri = _args["rootUri"]) + if (_args.contains("rootUri") && _args["rootUri"].is_string()) { - rootPath = uri.asString(); + rootPath = _args["rootUri"].get(); lspRequire( boost::starts_with(rootPath, "file://"), ErrorCode::InvalidParams, @@ -401,17 +403,17 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args) ); rootPath = stripFileUriSchemePrefix(rootPath); } - else if (Json::Value rootPath = _args["rootPath"]) - rootPath = rootPath.asString(); + else if (_args.contains("rootPath")) + rootPath = _args["rootPath"].get(); - if (_args["trace"]) + if (_args.contains("trace")) setTrace(_args["trace"]); m_fileRepository = FileRepository(rootPath, {}); - if (_args["initializationOptions"].isObject()) + if (_args.contains("initializationOptions") && _args["initializationOptions"].is_object()) changeConfiguration(_args["initializationOptions"]); - Json::Value replyArgs; + Json replyArgs; replyArgs["serverInfo"]["name"] = "solc"; replyArgs["serverInfo"]["version"] = std::string(VersionNumber); replyArgs["capabilities"]["definitionProvider"] = true; @@ -427,44 +429,49 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args) m_client.reply(_id, std::move(replyArgs)); } -void LanguageServer::handleInitialized(MessageID, Json::Value const&) +void LanguageServer::handleInitialized(MessageID, Json const&) { if (m_fileLoadStrategy == FileLoadStrategy::ProjectDirectory) compileAndUpdateDiagnostics(); } -void LanguageServer::semanticTokensFull(MessageID _id, Json::Value const& _args) +void LanguageServer::semanticTokensFull(MessageID _id, Json const& _args) { - auto uri = _args["textDocument"]["uri"]; + if (_args.contains("textDocument") && _args["textDocument"].contains("uri")) + { + auto uri = _args["textDocument"]["uri"]; - compile(); + compile(); - auto const sourceName = m_fileRepository.uriToSourceUnitName(uri.as()); - SourceUnit const& ast = m_compilerStack.ast(sourceName); - m_compilerStack.charStream(sourceName); - Json::Value data = SemanticTokensBuilder().build(ast, m_compilerStack.charStream(sourceName)); + auto const sourceName = m_fileRepository.uriToSourceUnitName(uri.get()); + SourceUnit const& ast = m_compilerStack.ast(sourceName); + m_compilerStack.charStream(sourceName); + Json data = SemanticTokensBuilder().build(ast, m_compilerStack.charStream(sourceName)); - Json::Value reply = Json::objectValue; - reply["data"] = data; + Json reply; + reply["data"] = data; - m_client.reply(_id, std::move(reply)); + m_client.reply(_id, std::move(reply)); + } + else + m_client.error(_id, ErrorCode::InvalidParams, "Invalid parameter: textDocument.uri expected."); } -void LanguageServer::handleWorkspaceDidChangeConfiguration(Json::Value const& _args) +void LanguageServer::handleWorkspaceDidChangeConfiguration(Json const& _args) { requireServerInitialized(); - if (_args["settings"].isObject()) + if (_args.contains("settings") && _args["settings"].is_object()) changeConfiguration(_args["settings"]); } -void LanguageServer::setTrace(Json::Value const& _args) +void LanguageServer::setTrace(Json const& _args) { - if (!_args.isString()) + if (!_args.is_string()) // Simply ignore invalid parameter. return; - std::string const stringValue = _args.asString(); + std::string const stringValue = _args.get(); if (stringValue == "off") m_client.setTrace(TraceValue::Off); else if (stringValue == "messages") @@ -473,78 +480,90 @@ void LanguageServer::setTrace(Json::Value const& _args) m_client.setTrace(TraceValue::Verbose); } -void LanguageServer::handleTextDocumentDidOpen(Json::Value const& _args) +void LanguageServer::handleTextDocumentDidOpen(Json const& _args) { requireServerInitialized(); lspRequire( - _args["textDocument"], + _args.contains("textDocument"), ErrorCode::RequestFailed, "Text document parameter missing." ); - std::string text = _args["textDocument"]["text"].asString(); - std::string uri = _args["textDocument"]["uri"].asString(); - m_openFiles.insert(uri); - m_fileRepository.setSourceByUri(uri, std::move(text)); - compileAndUpdateDiagnostics(); + if (_args["textDocument"].contains("text") && _args["textDocument"].contains("uri")) + { + std::string text = _args["textDocument"]["text"].get(); + std::string uri = _args["textDocument"]["uri"].get(); + m_openFiles.insert(uri); + m_fileRepository.setSourceByUri(uri, std::move(text)); + compileAndUpdateDiagnostics(); + } } -void LanguageServer::handleTextDocumentDidChange(Json::Value const& _args) +void LanguageServer::handleTextDocumentDidChange(Json const& _args) { requireServerInitialized(); - std::string const uri = _args["textDocument"]["uri"].asString(); - - for (Json::Value jsonContentChange: _args["contentChanges"]) + if (_args.contains("textDocument") && _args["textDocument"].contains("uri")) { - lspRequire( - jsonContentChange.isObject(), - ErrorCode::RequestFailed, - "Invalid content reference." - ); - - std::string const sourceUnitName = m_fileRepository.uriToSourceUnitName(uri); - lspRequire( - m_fileRepository.sourceUnits().count(sourceUnitName), - ErrorCode::RequestFailed, - "Unknown file: " + uri - ); + std::string const uri = _args["textDocument"]["uri"].get(); - std::string text = jsonContentChange["text"].asString(); - if (jsonContentChange["range"].isObject()) // otherwise full content update - { - std::optional change = parseRange(m_fileRepository, sourceUnitName, jsonContentChange["range"]); - lspRequire( - change && change->hasText(), - ErrorCode::RequestFailed, - "Invalid source range: " + util::jsonCompactPrint(jsonContentChange["range"]) - ); + if (_args.contains("contentChanges")) + for (auto const& [_, jsonContentChange]: _args["contentChanges"].items()) + { + lspRequire(jsonContentChange.is_object(), ErrorCode::RequestFailed, "Invalid content reference."); + + std::string const sourceUnitName = m_fileRepository.uriToSourceUnitName(uri); + lspRequire( + m_fileRepository.sourceUnits().count(sourceUnitName), + ErrorCode::RequestFailed, + "Unknown file: " + uri); + + if (jsonContentChange.contains("text")) + { + std::string text = jsonContentChange["text"].get(); + if (jsonContentChange.contains("range") + && jsonContentChange["range"].is_object()) // otherwise full content update + { + std::optional change + = parseRange(m_fileRepository, sourceUnitName, jsonContentChange["range"]); + lspRequire( + change && change->hasText(), + ErrorCode::RequestFailed, + "Invalid source range: " + util::jsonCompactPrint(jsonContentChange["range"])); + + std::string buffer = m_fileRepository.sourceUnits().at(sourceUnitName); + buffer.replace( + static_cast(change->start), + static_cast(change->end - change->start), + std::move(text)); + text = std::move(buffer); + } + m_fileRepository.setSourceByUri(uri, std::move(text)); + } + } - std::string buffer = m_fileRepository.sourceUnits().at(sourceUnitName); - buffer.replace(static_cast(change->start), static_cast(change->end - change->start), std::move(text)); - text = std::move(buffer); - } - m_fileRepository.setSourceByUri(uri, std::move(text)); + compileAndUpdateDiagnostics(); } - - compileAndUpdateDiagnostics(); } -void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args) +void LanguageServer::handleTextDocumentDidClose(Json const& _args) { requireServerInitialized(); lspRequire( - _args["textDocument"], + _args.contains("textDocument"), ErrorCode::RequestFailed, "Text document parameter missing." ); - std::string uri = _args["textDocument"]["uri"].asString(); - m_openFiles.erase(uri); + if (_args["textDocument"].contains("uri")) + { + std::string uri = _args["textDocument"]["uri"].get(); + m_openFiles.erase(uri); - compileAndUpdateDiagnostics(); + compileAndUpdateDiagnostics(); + } } ASTNode const* LanguageServer::astNodeAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos) diff --git a/libsolidity/lsp/LanguageServer.h b/libsolidity/lsp/LanguageServer.h index d80f8e879..4bea5809f 100644 --- a/libsolidity/lsp/LanguageServer.h +++ b/libsolidity/lsp/LanguageServer.h @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include @@ -85,29 +85,29 @@ class LanguageServer /// Checks if the server is initialized (to be used by messages that need it to be initialized). /// Reports an error and returns false if not. void requireServerInitialized(); - void handleInitialize(MessageID _id, Json::Value const& _args); - void handleInitialized(MessageID _id, Json::Value const& _args); - void handleWorkspaceDidChangeConfiguration(Json::Value const& _args); - void setTrace(Json::Value const& _args); - void handleTextDocumentDidOpen(Json::Value const& _args); - void handleTextDocumentDidChange(Json::Value const& _args); - void handleTextDocumentDidClose(Json::Value const& _args); - void handleRename(Json::Value const& _args); - void handleGotoDefinition(MessageID _id, Json::Value const& _args); - void semanticTokensFull(MessageID _id, Json::Value const& _args); + void handleInitialize(MessageID _id, Json const& _args); + void handleInitialized(MessageID _id, Json const& _args); + void handleWorkspaceDidChangeConfiguration(Json const& _args); + void setTrace(Json const& _args); + void handleTextDocumentDidOpen(Json const& _args); + void handleTextDocumentDidChange(Json const& _args); + void handleTextDocumentDidClose(Json const& _args); + void handleRename(Json const& _args); + void handleGotoDefinition(MessageID _id, Json const& _args); + void semanticTokensFull(MessageID _id, Json const& _args); /// Invoked when the server user-supplied configuration changes (initiated by the client). - void changeConfiguration(Json::Value const&); + void changeConfiguration(Json const&); /// Compile everything until after analysis phase. void compile(); std::vector allSolidityFilesFromProject() const; - using MessageHandler = std::function; + using MessageHandler = std::function; - Json::Value toRange(langutil::SourceLocation const& _location); - Json::Value toJson(langutil::SourceLocation const& _location); + Json toRange(langutil::SourceLocation const& _location); + Json toJson(langutil::SourceLocation const& _location); // LSP related member fields @@ -127,7 +127,7 @@ class LanguageServer frontend::CompilerStack m_compilerStack; /// User-supplied custom configuration settings (such as EVM version). - Json::Value m_settingsObject; + Json m_settingsObject; }; } diff --git a/libsolidity/lsp/RenameSymbol.cpp b/libsolidity/lsp/RenameSymbol.cpp index 75f032fcc..497ee50fb 100644 --- a/libsolidity/lsp/RenameSymbol.cpp +++ b/libsolidity/lsp/RenameSymbol.cpp @@ -47,11 +47,11 @@ CallableDeclaration const* extractCallableDeclaration(FunctionCall const& _funct } -void RenameSymbol::operator()(MessageID _id, Json::Value const& _args) +void RenameSymbol::operator()(MessageID _id, Json const& _args) { auto const&& [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args); - std::string const newName = _args["newName"].asString(); - std::string const uri = _args["textDocument"]["uri"].asString(); + std::string const newName = _args["newName"].get(); + std::string const uri = _args["textDocument"]["uri"].get(); ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn); @@ -90,10 +90,10 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args) // Apply changes in reverse order (will iterate in reverse) sort(m_locations.begin(), m_locations.end()); - Json::Value reply = Json::objectValue; - reply["changes"] = Json::objectValue; + Json reply; + reply["changes"] = Json::object(); - Json::Value edits = Json::arrayValue; + Json edits = Json::array(); for (auto i = m_locations.rbegin(); i != m_locations.rend(); i++) { @@ -105,16 +105,16 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args) buffer.replace((size_t)i->start, (size_t)(i->end - i->start), newName); fileRepository().setSourceByUri(uri, std::move(buffer)); - Json::Value edit = Json::objectValue; + Json edit; edit["range"] = toRange(*i); edit["newText"] = newName; // Record changes for the client - edits.append(edit); + edits.emplace_back(edit); if (i + 1 == m_locations.rend() || (i + 1)->sourceName != i->sourceName) { reply["changes"][uri] = edits; - edits = Json::arrayValue; + edits = Json::array(); // Reset. } } diff --git a/libsolidity/lsp/RenameSymbol.h b/libsolidity/lsp/RenameSymbol.h index cafa8c067..c4a2ac98f 100644 --- a/libsolidity/lsp/RenameSymbol.h +++ b/libsolidity/lsp/RenameSymbol.h @@ -27,7 +27,7 @@ class RenameSymbol: public HandlerBase public: explicit RenameSymbol(LanguageServer& _server): HandlerBase(_server) {} - void operator()(MessageID, Json::Value const&); + void operator()(MessageID, Json const&); protected: // Nested class because otherwise `RenameSymbol` couldn't be easily used // with LanguageServer::m_handlers as `ASTConstVisitor` deletes required diff --git a/libsolidity/lsp/SemanticTokensBuilder.cpp b/libsolidity/lsp/SemanticTokensBuilder.cpp index 2f4435418..be0796860 100644 --- a/libsolidity/lsp/SemanticTokensBuilder.cpp +++ b/libsolidity/lsp/SemanticTokensBuilder.cpp @@ -70,7 +70,7 @@ SemanticTokenType semanticTokenTypeForExpression(frontend::Type const* _type) } // end namespace -Json::Value SemanticTokensBuilder::build(SourceUnit const& _sourceUnit, CharStream const& _charStream) +Json SemanticTokensBuilder::build(SourceUnit const& _sourceUnit, CharStream const& _charStream) { reset(&_charStream); _sourceUnit.accept(*this); @@ -79,7 +79,7 @@ Json::Value SemanticTokensBuilder::build(SourceUnit const& _sourceUnit, CharStre void SemanticTokensBuilder::reset(CharStream const* _charStream) { - m_encodedTokens = Json::arrayValue; + m_encodedTokens = Json::array(); m_charStream = _charStream; m_lastLine = 0; m_lastStartChar = 0; @@ -120,14 +120,14 @@ void SemanticTokensBuilder::encode( lspDebug(fmt::format("encode [{}:{}..{}] {}", line, startChar, length, static_cast(_tokenType))); - m_encodedTokens.append(line - m_lastLine); + m_encodedTokens.emplace_back(line - m_lastLine); if (line == m_lastLine) - m_encodedTokens.append(startChar - m_lastStartChar); + m_encodedTokens.emplace_back(startChar - m_lastStartChar); else - m_encodedTokens.append(startChar); - m_encodedTokens.append(length); - m_encodedTokens.append(static_cast(_tokenType)); - m_encodedTokens.append(static_cast(_modifiers)); + m_encodedTokens.emplace_back(startChar); + m_encodedTokens.emplace_back(length); + m_encodedTokens.emplace_back(static_cast(_tokenType)); + m_encodedTokens.emplace_back(static_cast(_modifiers)); m_lastLine = line; m_lastStartChar = startChar; diff --git a/libsolidity/lsp/SemanticTokensBuilder.h b/libsolidity/lsp/SemanticTokensBuilder.h index ca3c48d1c..3facb99e2 100644 --- a/libsolidity/lsp/SemanticTokensBuilder.h +++ b/libsolidity/lsp/SemanticTokensBuilder.h @@ -17,7 +17,7 @@ // SPDX-License-Identifier: GPL-3.0 #include #include -#include +#include #include @@ -87,7 +87,7 @@ constexpr SemanticTokenModifiers operator|(SemanticTokenModifiers a, SemanticTok class SemanticTokensBuilder: public frontend::ASTConstVisitor { public: - Json::Value build(frontend::SourceUnit const& _sourceUnit, langutil::CharStream const& _charStream); + Json build(frontend::SourceUnit const& _sourceUnit, langutil::CharStream const& _charStream); void reset(langutil::CharStream const* _charStream); void encode( @@ -114,7 +114,7 @@ class SemanticTokensBuilder: public frontend::ASTConstVisitor bool visit(frontend::VariableDeclaration const&) override; private: - Json::Value m_encodedTokens; + Json m_encodedTokens; langutil::CharStream const* m_charStream; int m_lastLine; int m_lastStartChar; diff --git a/libsolidity/lsp/Transport.cpp b/libsolidity/lsp/Transport.cpp index 7f8eb2283..743ad6d66 100644 --- a/libsolidity/lsp/Transport.cpp +++ b/libsolidity/lsp/Transport.cpp @@ -38,9 +38,10 @@ #endif using namespace solidity::lsp; +using namespace solidity; // {{{ Transport -std::optional Transport::receive() +std::optional Transport::receive() { auto const headers = parseHeaders(); if (!headers) @@ -57,10 +58,10 @@ std::optional Transport::receive() std::string const data = readBytes(stoul(headers->at("content-length"))); - Json::Value jsonMessage; + Json jsonMessage; std::string jsonParsingErrors; solidity::util::jsonParseStrict(data, jsonMessage, &jsonParsingErrors); - if (!jsonParsingErrors.empty() || !jsonMessage || !jsonMessage.isObject()) + if (!jsonParsingErrors.empty() || jsonMessage.empty() || !jsonMessage.is_object()) { error({}, ErrorCode::ParseError, "Could not parse RPC JSON payload. " + jsonParsingErrors); return std::nullopt; @@ -69,12 +70,12 @@ std::optional Transport::receive() return {std::move(jsonMessage)}; } -void Transport::trace(std::string _message, Json::Value _extra) +void Transport::trace(std::string _message, Json _extra) { if (m_logTrace != TraceValue::Off) { - Json::Value params; - if (_extra.isObject()) + Json params; + if (_extra.is_object()) params = std::move(_extra); params["message"] = std::move(_message); notify("$/logTrace", std::move(params)); @@ -103,34 +104,34 @@ std::optional> Transport::parseHeaders() return {std::move(headers)}; } -void Transport::notify(std::string _method, Json::Value _message) +void Transport::notify(std::string _method, Json _message) { - Json::Value json; + Json json; json["method"] = std::move(_method); json["params"] = std::move(_message); send(std::move(json)); } -void Transport::reply(MessageID _id, Json::Value _message) +void Transport::reply(MessageID _id, Json _message) { - Json::Value json; + Json json; json["result"] = std::move(_message); send(std::move(json), _id); } void Transport::error(MessageID _id, ErrorCode _code, std::string _message) { - Json::Value json; + Json json; json["error"]["code"] = static_cast(_code); json["error"]["message"] = std::move(_message); send(std::move(json), _id); } -void Transport::send(Json::Value _json, MessageID _id) +void Transport::send(Json _json, MessageID _id) { - solAssert(_json.isObject()); + solAssert(_json.is_object()); _json["jsonrpc"] = "2.0"; - if (_id != Json::nullValue) + if (_id != Json()) _json["id"] = _id; // Trailing CRLF only for easier readability. diff --git a/libsolidity/lsp/Transport.h b/libsolidity/lsp/Transport.h index e3b03bcc7..e76cb5f7d 100644 --- a/libsolidity/lsp/Transport.h +++ b/libsolidity/lsp/Transport.h @@ -18,8 +18,7 @@ #pragma once #include - -#include +#include #include #include @@ -32,7 +31,7 @@ namespace solidity::lsp { -using MessageID = Json::Value; +using MessageID = Json; enum class TraceValue { @@ -98,14 +97,14 @@ class Transport public: virtual ~Transport() = default; - std::optional receive(); - void notify(std::string _method, Json::Value _params); - void reply(MessageID _id, Json::Value _result); + std::optional receive(); + void notify(std::string _method, Json _params); + void reply(MessageID _id, Json _result); void error(MessageID _id, ErrorCode _code, std::string _message); virtual bool closed() const noexcept = 0; - void trace(std::string _message, Json::Value _extra = Json::nullValue); + void trace(std::string _message, Json _extra = Json{}); TraceValue traceValue() const noexcept { return m_logTrace; } void setTrace(TraceValue _value) noexcept { m_logTrace = _value; } @@ -135,7 +134,7 @@ class Transport /// Sends an arbitrary raw message to the client. /// /// Used by the notify/reply/error function family. - virtual void send(Json::Value _message, MessageID _id = Json::nullValue); + virtual void send(Json _message, MessageID _id = Json{}); }; /** diff --git a/libsolidity/lsp/Utils.cpp b/libsolidity/lsp/Utils.cpp index 85e27a4fd..7667ce688 100644 --- a/libsolidity/lsp/Utils.cpp +++ b/libsolidity/lsp/Utils.cpp @@ -31,26 +31,26 @@ namespace solidity::lsp using namespace frontend; using namespace langutil; -std::optional parseLineColumn(Json::Value const& _lineColumn) +std::optional parseLineColumn(Json const& _lineColumn) { - if (_lineColumn.isObject() && _lineColumn["line"].isInt() && _lineColumn["character"].isInt()) - return LineColumn{_lineColumn["line"].asInt(), _lineColumn["character"].asInt()}; + if (_lineColumn.is_object() && _lineColumn["line"].is_number_integer() && _lineColumn["character"].is_number_integer()) + return LineColumn{_lineColumn["line"].get(), _lineColumn["character"].get()}; else return std::nullopt; } -Json::Value toJson(LineColumn const& _pos) +Json toJson(LineColumn const& _pos) { - Json::Value json = Json::objectValue; + Json json; json["line"] = std::max(_pos.line, 0); json["character"] = std::max(_pos.column, 0); return json; } -Json::Value toJsonRange(LineColumn const& _start, LineColumn const& _end) +Json toJsonRange(LineColumn const& _start, LineColumn const& _end) { - Json::Value json; + Json json; json["start"] = toJson(_start); json["end"] = toJson(_end); return json; @@ -86,7 +86,7 @@ std::optional declarationLocation(Declaration const* _declaratio std::optional parsePosition( FileRepository const& _fileRepository, std::string const& _sourceUnitName, - Json::Value const& _position + Json const& _position ) { if (!_fileRepository.sourceUnits().count(_sourceUnitName)) @@ -101,9 +101,9 @@ std::optional parsePosition( return std::nullopt; } -std::optional parseRange(FileRepository const& _fileRepository, std::string const& _sourceUnitName, Json::Value const& _range) +std::optional parseRange(FileRepository const& _fileRepository, std::string const& _sourceUnitName, Json const& _range) { - if (!_range.isObject()) + if (!_range.is_object()) return std::nullopt; std::optional start = parsePosition(_fileRepository, _sourceUnitName, _range["start"]); std::optional end = parsePosition(_fileRepository, _sourceUnitName, _range["end"]); diff --git a/libsolidity/lsp/Utils.h b/libsolidity/lsp/Utils.h index c6d40213e..318cdc87d 100644 --- a/libsolidity/lsp/Utils.h +++ b/libsolidity/lsp/Utils.h @@ -44,16 +44,16 @@ namespace solidity::lsp class FileRepository; -std::optional parseLineColumn(Json::Value const& _lineColumn); -Json::Value toJson(langutil::LineColumn const& _pos); -Json::Value toJsonRange(langutil::LineColumn const& _start, langutil::LineColumn const& _end); +std::optional parseLineColumn(Json const& _lineColumn); +Json toJson(langutil::LineColumn const& _pos); +Json toJsonRange(langutil::LineColumn const& _start, langutil::LineColumn const& _end); /// @returns the source location given a source unit name and an LSP Range object, /// or nullopt on failure. std::optional parsePosition( FileRepository const& _fileRepository, std::string const& _sourceUnitName, - Json::Value const& _position + Json const& _position ); /// @returns the source location given a source unit name and an LSP Range object, @@ -61,7 +61,7 @@ std::optional parsePosition( std::optional parseRange( FileRepository const& _fileRepository, std::string const& _sourceUnitName, - Json::Value const& _range + Json const& _range ); /// Strips the file:// URI prefix off the given path, if present, diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index f97d61b67..0fdb23b04 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -43,7 +43,7 @@ set(sources ) add_library(solutil ${sources}) -target_link_libraries(solutil PUBLIC jsoncpp Boost::boost Boost::filesystem Boost::system range-v3 fmt::fmt-header-only) +target_link_libraries(solutil PUBLIC Boost::boost Boost::filesystem Boost::system range-v3 fmt::fmt-header-only nlohmann-json) target_include_directories(solutil PUBLIC "${PROJECT_SOURCE_DIR}") add_dependencies(solutil solidity_BuildInfo.h) diff --git a/libsolutil/Exceptions.h b/libsolutil/Exceptions.h index 9d73a0012..7dd9b6769 100644 --- a/libsolutil/Exceptions.h +++ b/libsolutil/Exceptions.h @@ -76,6 +76,7 @@ DEV_SIMPLE_EXCEPTION(FileNotFound); DEV_SIMPLE_EXCEPTION(NotAFile); DEV_SIMPLE_EXCEPTION(DataTooLong); DEV_SIMPLE_EXCEPTION(StringTooLong); +DEV_SIMPLE_EXCEPTION(InvalidType); // error information to be added to exceptions using errinfo_comment = boost::error_info; diff --git a/libsolutil/JSON.cpp b/libsolutil/JSON.cpp index 3a2570d47..63746c865 100644 --- a/libsolutil/JSON.cpp +++ b/libsolutil/JSON.cpp @@ -22,19 +22,18 @@ #include -#include +#include -#include +#include +#include -#include #include -#include +#include -#ifdef STRICT_JSONCPP_VERSION_CHECK +#ifdef STRICT_NLOHMANN_JSON_VERSION_CHECK static_assert( - (JSONCPP_VERSION_MAJOR == 1) && (JSONCPP_VERSION_MINOR == 9) && (JSONCPP_VERSION_PATCH == 3), - "Unexpected jsoncpp version: " JSONCPP_VERSION_STRING ". Expecting 1.9.3." -); + (NLOHMANN_JSON_VERSION_MAJOR == 3) && (NLOHMANN_JSON_VERSION_MINOR == 11) && (NLOHMANN_JSON_VERSION_PATCH == 3), + "Unexpected nlohmann-json version. Expecting 3.11.3."); #endif namespace solidity::util @@ -43,116 +42,209 @@ namespace solidity::util namespace { -/// StreamWriterBuilder that can be constructed with specific settings -class StreamWriterBuilder: public Json::StreamWriterBuilder +/// Takes a JSON value (@ _json) and removes all its members with value 'null' recursively. +void removeNullMembersHelper(Json& _json) { -public: - explicit StreamWriterBuilder(std::map const& _settings) + if (_json.is_array()) { - for (auto const& iter: _settings) - this->settings_[iter.first] = iter.second; + for (auto& child: _json) + removeNullMembersHelper(child); } -}; - -/// CharReaderBuilder with strict-mode settings -class StrictModeCharReaderBuilder: public Json::CharReaderBuilder -{ -public: - StrictModeCharReaderBuilder() + else if (_json.is_object()) { - Json::CharReaderBuilder::strictMode(&this->settings_); + for (auto it = _json.begin(); it != _json.end();) + { + if (it->is_null()) + it = _json.erase(it); + else + { + removeNullMembersHelper(*it); + ++it; + } + } } -}; +} -/// Serialise the JSON object (@a _input) with specific builder (@a _builder) -/// \param _input JSON input string -/// \param _builder StreamWriterBuilder that is used to create new Json::StreamWriter -/// \return serialized json object -std::string print(Json::Value const& _input, Json::StreamWriterBuilder const& _builder) +std::string trimRightAllLines(std::string const& input) { - std::stringstream stream; - std::unique_ptr writer(_builder.newStreamWriter()); - writer->write(_input, &stream); - return stream.str(); + std::vector lines; + std::string output; + boost::split(lines, input, boost::is_any_of("\n")); + for (auto& line: lines) + { + boost::trim_right(line); + if (!line.empty()) + output += line + "\n"; + } + return boost::trim_right_copy(output); } -/// Parse a JSON string (@a _input) with specified builder (@ _builder) and writes resulting JSON object to (@a _json) -/// \param _builder CharReaderBuilder that is used to create new Json::CharReaders -/// \param _input JSON input string -/// \param _json [out] resulting JSON object -/// \param _errs [out] Formatted error messages -/// \return \c true if the document was successfully parsed, \c false if an error occurred. -bool parse(Json::CharReaderBuilder& _builder, std::string const& _input, Json::Value& _json, std::string* _errs) +std::string formatLikeJsoncpp(std::string const& _dumped, JsonFormat const& _format) { - std::unique_ptr reader(_builder.newCharReader()); - return reader->parse(_input.c_str(), _input.c_str() + _input.length(), &_json, _errs); + uint32_t indentLevel = 0; + std::stringstream reformatted; + bool inQuotes = false; + for (size_t i = 0; i < _dumped.size(); ++i) + { + char c = _dumped[i]; + bool emptyThing = false; + + if (c == '"' && (i == 0 || _dumped[i - 1] != '\\')) + inQuotes = !inQuotes; + + if (!inQuotes) + { + if (i < _dumped.size() - 1) + { + char nc = _dumped[i + 1]; + if ((c == '[' && nc == ']') || (c == '{' && nc == '}')) + emptyThing = true; + } + if (c == '[' || c == '{') + { + if (i > 0 && _dumped[i - 1] != '\n') + if (!emptyThing) + reformatted << '\n' << std::string(indentLevel * _format.indent, ' '); + indentLevel++; + } + else if (c == ']' || c == '}') + { + indentLevel--; + if (i + 1 < _dumped.size() && _dumped[i + 1] != '\n' + && (_dumped[i + 1] == ']' || _dumped[i + 1] == '}')) + reformatted << '\n' << std::string(indentLevel * _format.indent, ' '); + } + } + reformatted << c; + if (!emptyThing && !inQuotes && (c == '[' || c == '{') && indentLevel > 0 && i + 1 < _dumped.size() + && _dumped[i + 1] != '\n') + reformatted << '\n' << std::string(indentLevel * _format.indent, ' '); + } + return trimRightAllLines(reformatted.str()); } -/// Takes a JSON value (@ _json) and removes all its members with value 'null' recursively. -void removeNullMembersHelper(Json::Value& _json) +std::string escapeNewlinesAndTabsWithinStringLiterals(std::string const& _json) { - if (_json.type() == Json::ValueType::arrayValue) - for (auto& child: _json) - removeNullMembersHelper(child); - else if (_json.type() == Json::ValueType::objectValue) - for (auto const& key: _json.getMemberNames()) + std::stringstream fixed; + bool inQuotes = false; + for (size_t i = 0; i < _json.size(); ++i) + { + char c = _json[i]; + + // Originally we had just this here: + // if (c == '"' && (i == 0 || _json[i - 1] != '\\')) + // inQuotes = !inQuotes; + // However, this is not working if the escape character itself was escaped. e.g. "\n\r'\"\\". + + if (c == '"') + { + size_t backslashCount = 0; + size_t j = i; + while (j > 0 && _json[j - 1] == '\\') + { + backslashCount++; + j--; + } + if (backslashCount % 2 == 0) + { + inQuotes = !inQuotes; + fixed << c; + continue; + } + } + + if (inQuotes) { - Json::Value& value = _json[key]; - if (value.isNull()) - _json.removeMember(key); + if (c == '\n') + fixed << "\\n"; + else if (c == '\t') + fixed << "\\t"; else - removeNullMembersHelper(value); + fixed << c; } + else + fixed << c; + } + return fixed.str(); } } // end anonymous namespace -Json::Value removeNullMembers(Json::Value _json) +Json removeNullMembers(Json _json) { removeNullMembersHelper(_json); return _json; } -std::string jsonPrettyPrint(Json::Value const& _input) +std::string removeNlohmannInternalErrorIdentifier(std::string const& _input) { - return jsonPrint(_input, JsonFormat{ JsonFormat::Pretty }); -} + std::string result = _input; + std::size_t startPos = result.find('['); + std::size_t endPos = result.find(']', startPos); -std::string jsonCompactPrint(Json::Value const& _input) -{ - return jsonPrint(_input, JsonFormat{ JsonFormat::Compact }); + if (startPos != std::string::npos && endPos != std::string::npos) + result.erase(startPos, endPos - startPos + 1); + + return boost::trim_copy(result); } -std::string jsonPrint(Json::Value const& _input, JsonFormat const& _format) +std::string jsonPrettyPrint(Json const& _input) { return jsonPrint(_input, JsonFormat{JsonFormat::Pretty}); } + +std::string jsonCompactPrint(Json const& _input) { return jsonPrint(_input, JsonFormat{JsonFormat::Compact}); } + +std::string jsonPrint(Json const& _input, JsonFormat const& _format) { - std::map settings; - if (_format.format == JsonFormat::Pretty) - { - settings["indentation"] = std::string(_format.indent, ' '); - settings["enableYAMLCompatibility"] = true; - } - else - settings["indentation"] = ""; - StreamWriterBuilder writerBuilder(settings); - std::string result = print(_input, writerBuilder); + // NOTE: -1 here means no new lines (it is also the default setting) + std::string dumped = _input.dump( + /* indent */ (_format.format == JsonFormat::Pretty) ? static_cast(_format.indent) : -1, + /* indent_char */ ' ', + /* ensure_ascii */ true + ); + + // let's remove this once all test-cases having the correct output. if (_format.format == JsonFormat::Pretty) - boost::replace_all(result, " \n", "\n"); - return result; + dumped = formatLikeJsoncpp(dumped, _format); + + return dumped; } -bool jsonParseStrict(std::string const& _input, Json::Value& _json, std::string* _errs /* = nullptr */) +bool jsonParseStrict(std::string const& _input, Json& _json, std::string* _errs /* = nullptr */) { - static StrictModeCharReaderBuilder readerBuilder; - return parse(readerBuilder, _input, _json, _errs); + try + { + _json = Json::parse( + // TODO: remove this in the next breaking release? + escapeNewlinesAndTabsWithinStringLiterals(_input), + /* callback */ nullptr, + /* allow exceptions */ true, + /* ignore_comments */true + ); + _errs = {}; + return true; + } + catch (Json::parse_error const& e) + { + if (_errs) + { + std::stringstream escaped; + for (char c: removeNlohmannInternalErrorIdentifier(e.what())) + if (std::isprint(c)) + escaped << c; + else + escaped << "\\x" + toHex(static_cast(c)); + *_errs = escaped.str(); + } + return false; + } } -std::optional jsonValueByPath(Json::Value const& _node, std::string_view _jsonPath) +std::optional jsonValueByPath(Json const& _node, std::string_view _jsonPath) { - if (!_node.isObject() || _jsonPath.empty()) + if (!_node.is_object() || _jsonPath.empty()) return {}; std::string memberName = std::string(_jsonPath.substr(0, _jsonPath.find_first_of('.'))); - if (!_node.isMember(memberName)) + if (!_node.contains(memberName)) return {}; if (memberName == _jsonPath) diff --git a/libsolutil/JSON.h b/libsolutil/JSON.h index f368739e1..2cdac70c7 100644 --- a/libsolutil/JSON.h +++ b/libsolutil/JSON.h @@ -23,17 +23,26 @@ #pragma once -#include +#include +#include #include #include #include +#include + +namespace solidity +{ + +using Json = nlohmann::json; + +} // namespace solidity namespace solidity::util { /// Removes members with null value recursively from (@a _json). -Json::Value removeNullMembers(Json::Value _json); +Json removeNullMembers(Json _json); /// JSON printing format. struct JsonFormat @@ -54,27 +63,29 @@ struct JsonFormat }; /// Serialise the JSON object (@a _input) with indentation -std::string jsonPrettyPrint(Json::Value const& _input); +std::string jsonPrettyPrint(Json const& _input); /// Serialise the JSON object (@a _input) without indentation -std::string jsonCompactPrint(Json::Value const& _input); +std::string jsonCompactPrint(Json const& _input); /// Serialise the JSON object (@a _input) using specified format (@a _format) -std::string jsonPrint(Json::Value const& _input, JsonFormat const& _format); +std::string jsonPrint(Json const& _input, JsonFormat const& _format); /// Parse a JSON string (@a _input) with enabled strict-mode and writes resulting JSON object to (@a _json) /// \param _input JSON input string /// \param _json [out] resulting JSON object /// \param _errs [out] Formatted error messages /// \return \c true if the document was successfully parsed, \c false if an error occurred. -bool jsonParseStrict(std::string const& _input, Json::Value& _json, std::string* _errs = nullptr); +bool jsonParseStrict(std::string const& _input, Json& _json, std::string* _errs = nullptr); /// Retrieves the value specified by @p _jsonPath by from a series of nested JSON dictionaries. /// @param _jsonPath A dot-separated series of dictionary keys. /// @param _node The node representing the start of the path. /// @returns The value of the last key on the path. @a nullptr if any node on the path descends /// into something that is not a dictionary or the key is not present. -std::optional jsonValueByPath(Json::Value const& _node, std::string_view _jsonPath); +std::optional jsonValueByPath(Json const& _node, std::string_view _jsonPath); + +std::string removeNlohmannInternalErrorIdentifier(std::string const& _input); namespace detail { @@ -82,60 +93,95 @@ namespace detail template struct helper; -template +template struct helper_impl { - static bool isOfType(Json::Value const& _input) + static bool isOfType(Json const& _input) { return (_input.*checkMember)(); } - static T get(Json::Value const& _input) + static T get(Json const& _input) { + assertThrow(isOfType(_input), InvalidType, ""); return (_input.*convertMember)(); } - static T getOrDefault(Json::Value const& _input, T _default = {}) + static T getOrDefault(Json const& _input, std::string const& _name, T _default = {}) { T result = _default; - if (isOfType(_input)) - result = (_input.*convertMember)(); + if (_input.contains(_name) && isOfType(_input[_name])) + result = (_input[_name].*convertMember)(); return result; } }; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; -template<> struct helper: helper_impl {}; +template +struct helper_impl_with_range_check +{ + static bool isOfType(Json const& _input) + { + if ( (_input.*checkMember)()) + { + T value = (_input.*convertMember)(); + return (value >= std::numeric_limits::min() && value <= std::numeric_limits::max()); + } + return false; + } + + static RT get(Json const& _input) + { + assertThrow(isOfType(_input), InvalidType, ""); + return static_cast((_input.*convertMember)()); + } + + static RT getOrDefault(Json const& _input, std::string const& _name, RT _default = {}) + { + RT value = _default; + if (_input.contains(_name) && isOfType(_input[_name])) + value = static_cast((_input[_name].*convertMember)()); + return value; + } +}; + +template<> struct helper: helper_impl> {}; +template<> struct helper: helper_impl> {}; +template<> struct helper: helper_impl> {}; +template<> struct helper: helper_impl> {}; +template<> struct helper: helper_impl> {}; + +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; +template<> struct helper: helper_impl_with_range_check> {}; } // namespace detail template -bool isOfType(Json::Value const& _input) +bool isOfType(Json const& _input) { return detail::helper::isOfType(_input); } template -bool isOfTypeIfExists(Json::Value const& _input, std::string const& _name) +bool isOfTypeIfExists(Json const& _input, std::string const& _name) { - if (_input.isMember(_name)) + if (_input.contains(_name)) return isOfType(_input[_name]); return true; } template -T get(Json::Value const& _input) +T get(Json const& _input) { return detail::helper::get(_input); } template -T getOrDefault(Json::Value const& _input, T _default = {}) +T getOrDefault(Json const& _input, std::string const& _name, T _default = {}) { - return detail::helper::getOrDefault(_input, _default); + return detail::helper::getOrDefault(_input, _name, _default); } } // namespace solidity::util diff --git a/libyul/AsmJsonConverter.cpp b/libyul/AsmJsonConverter.cpp index bf2468b4e..a89e4967a 100644 --- a/libyul/AsmJsonConverter.cpp +++ b/libyul/AsmJsonConverter.cpp @@ -29,25 +29,25 @@ namespace solidity::yul { -Json::Value AsmJsonConverter::operator()(Block const& _node) const +Json AsmJsonConverter::operator()(Block const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulBlock"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulBlock"); ret["statements"] = vectorOfVariantsToJson(_node.statements); return ret; } -Json::Value AsmJsonConverter::operator()(TypedName const& _node) const +Json AsmJsonConverter::operator()(TypedName const& _node) const { yulAssert(!_node.name.empty(), "Invalid variable name."); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulTypedName"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulTypedName"); ret["name"] = _node.name.str(); ret["type"] = _node.type.str(); return ret; } -Json::Value AsmJsonConverter::operator()(Literal const& _node) const +Json AsmJsonConverter::operator()(Literal const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulLiteral"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulLiteral"); switch (_node.kind) { case LiteralKind::Number: @@ -71,94 +71,92 @@ Json::Value AsmJsonConverter::operator()(Literal const& _node) const return ret; } -Json::Value AsmJsonConverter::operator()(Identifier const& _node) const +Json AsmJsonConverter::operator()(Identifier const& _node) const { yulAssert(!_node.name.empty(), "Invalid identifier"); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIdentifier"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIdentifier"); ret["name"] = _node.name.str(); return ret; } -Json::Value AsmJsonConverter::operator()(Assignment const& _node) const +Json AsmJsonConverter::operator()(Assignment const& _node) const { yulAssert(_node.variableNames.size() >= 1, "Invalid assignment syntax"); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulAssignment"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulAssignment"); for (auto const& var: _node.variableNames) - ret["variableNames"].append((*this)(var)); - ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json::nullValue; + ret["variableNames"].emplace_back((*this)(var)); + ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json(); return ret; } -Json::Value AsmJsonConverter::operator()(FunctionCall const& _node) const +Json AsmJsonConverter::operator()(FunctionCall const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionCall"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionCall"); ret["functionName"] = (*this)(_node.functionName); ret["arguments"] = vectorOfVariantsToJson(_node.arguments); return ret; } -Json::Value AsmJsonConverter::operator()(ExpressionStatement const& _node) const +Json AsmJsonConverter::operator()(ExpressionStatement const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulExpressionStatement"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulExpressionStatement"); ret["expression"] = std::visit(*this, _node.expression); return ret; } -Json::Value AsmJsonConverter::operator()(VariableDeclaration const& _node) const +Json AsmJsonConverter::operator()(VariableDeclaration const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulVariableDeclaration"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulVariableDeclaration"); for (auto const& var: _node.variables) - ret["variables"].append((*this)(var)); - - ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json::nullValue; - + ret["variables"].emplace_back((*this)(var)); + ret["value"] = _node.value ? std::visit(*this, *_node.value) : Json(); return ret; } -Json::Value AsmJsonConverter::operator()(FunctionDefinition const& _node) const +Json AsmJsonConverter::operator()(FunctionDefinition const& _node) const { yulAssert(!_node.name.empty(), "Invalid function name."); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionDefinition"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionDefinition"); ret["name"] = _node.name.str(); for (auto const& var: _node.parameters) - ret["parameters"].append((*this)(var)); + ret["parameters"].emplace_back((*this)(var)); for (auto const& var: _node.returnVariables) - ret["returnVariables"].append((*this)(var)); + ret["returnVariables"].emplace_back((*this)(var)); ret["body"] = (*this)(_node.body); return ret; } -Json::Value AsmJsonConverter::operator()(If const& _node) const +Json AsmJsonConverter::operator()(If const& _node) const { yulAssert(_node.condition, "Invalid if condition."); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIf"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIf"); ret["condition"] = std::visit(*this, *_node.condition); ret["body"] = (*this)(_node.body); return ret; } -Json::Value AsmJsonConverter::operator()(Switch const& _node) const +Json AsmJsonConverter::operator()(Switch const& _node) const { yulAssert(_node.expression, "Invalid expression pointer."); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulSwitch"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulSwitch"); ret["expression"] = std::visit(*this, *_node.expression); for (auto const& var: _node.cases) - ret["cases"].append((*this)(var)); + ret["cases"].emplace_back((*this)(var)); return ret; } -Json::Value AsmJsonConverter::operator()(Case const& _node) const +Json AsmJsonConverter::operator()(Case const& _node) const { - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulCase"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulCase"); ret["value"] = _node.value ? (*this)(*_node.value) : "default"; ret["body"] = (*this)(_node.body); return ret; } -Json::Value AsmJsonConverter::operator()(ForLoop const& _node) const +Json AsmJsonConverter::operator()(ForLoop const& _node) const { yulAssert(_node.condition, "Invalid for loop condition."); - Json::Value ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulForLoop"); + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulForLoop"); ret["pre"] = (*this)(_node.pre); ret["condition"] = std::visit(*this, *_node.condition); ret["post"] = (*this)(_node.post); @@ -166,24 +164,24 @@ Json::Value AsmJsonConverter::operator()(ForLoop const& _node) const return ret; } -Json::Value AsmJsonConverter::operator()(Break const& _node) const +Json AsmJsonConverter::operator()(Break const& _node) const { return createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulBreak"); } -Json::Value AsmJsonConverter::operator()(Continue const& _node) const +Json AsmJsonConverter::operator()(Continue const& _node) const { return createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulContinue"); } -Json::Value AsmJsonConverter::operator()(Leave const& _node) const +Json AsmJsonConverter::operator()(Leave const& _node) const { return createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulLeave"); } -Json::Value AsmJsonConverter::createAstNode(langutil::SourceLocation const& _originLocation, langutil::SourceLocation const& _nativeLocation, std::string _nodeType) const +Json AsmJsonConverter::createAstNode(langutil::SourceLocation const& _originLocation, langutil::SourceLocation const& _nativeLocation, std::string _nodeType) const { - Json::Value ret{Json::objectValue}; + Json ret; ret["nodeType"] = std::move(_nodeType); auto srcLocation = [&](int start, int end) -> std::string { @@ -196,11 +194,11 @@ Json::Value AsmJsonConverter::createAstNode(langutil::SourceLocation const& _ori } template -Json::Value AsmJsonConverter::vectorOfVariantsToJson(std::vector const& _vec) const +Json AsmJsonConverter::vectorOfVariantsToJson(std::vector const& _vec) const { - Json::Value ret{Json::arrayValue}; + Json ret = Json::array(); for (auto const& var: _vec) - ret.append(std::visit(*this, var)); + ret.emplace_back(std::visit(*this, var)); return ret; } diff --git a/libyul/AsmJsonConverter.h b/libyul/AsmJsonConverter.h index 236ecbba5..9c4b5d5e8 100644 --- a/libyul/AsmJsonConverter.h +++ b/libyul/AsmJsonConverter.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include @@ -36,35 +36,35 @@ namespace solidity::yul /** * Converter of the yul AST into JSON format */ -class AsmJsonConverter: public boost::static_visitor +class AsmJsonConverter: public boost::static_visitor { public: /// Create a converter to JSON for any block of inline assembly /// @a _sourceIndex to be used to abbreviate source name in the source locations explicit AsmJsonConverter(std::optional _sourceIndex): m_sourceIndex(_sourceIndex) {} - Json::Value operator()(Block const& _node) const; - Json::Value operator()(TypedName const& _node) const; - Json::Value operator()(Literal const& _node) const; - Json::Value operator()(Identifier const& _node) const; - Json::Value operator()(Assignment const& _node) const; - Json::Value operator()(VariableDeclaration const& _node) const; - Json::Value operator()(FunctionDefinition const& _node) const; - Json::Value operator()(FunctionCall const& _node) const; - Json::Value operator()(If const& _node) const; - Json::Value operator()(Switch const& _node) const; - Json::Value operator()(Case const& _node) const; - Json::Value operator()(ForLoop const& _node) const; - Json::Value operator()(Break const& _node) const; - Json::Value operator()(Continue const& _node) const; - Json::Value operator()(Leave const& _node) const; - Json::Value operator()(ExpressionStatement const& _node) const; - Json::Value operator()(Label const& _node) const; + Json operator()(Block const& _node) const; + Json operator()(TypedName const& _node) const; + Json operator()(Literal const& _node) const; + Json operator()(Identifier const& _node) const; + Json operator()(Assignment const& _node) const; + Json operator()(VariableDeclaration const& _node) const; + Json operator()(FunctionDefinition const& _node) const; + Json operator()(FunctionCall const& _node) const; + Json operator()(If const& _node) const; + Json operator()(Switch const& _node) const; + Json operator()(Case const& _node) const; + Json operator()(ForLoop const& _node) const; + Json operator()(Break const& _node) const; + Json operator()(Continue const& _node) const; + Json operator()(Leave const& _node) const; + Json operator()(ExpressionStatement const& _node) const; + Json operator()(Label const& _node) const; private: - Json::Value createAstNode(langutil::SourceLocation const& _originLocation, langutil::SourceLocation const& _nativeLocation, std::string _nodeType) const; + Json createAstNode(langutil::SourceLocation const& _originLocation, langutil::SourceLocation const& _nativeLocation, std::string _nodeType) const; template - Json::Value vectorOfVariantsToJson(std::vector const& vec) const; + Json vectorOfVariantsToJson(std::vector const& vec) const; std::optional const m_sourceIndex; }; diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index 190dcda21..41e065853 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -41,15 +41,15 @@ namespace solidity::yul using SourceLocation = langutil::SourceLocation; -SourceLocation const AsmJsonImporter::createSourceLocation(Json::Value const& _node) +SourceLocation const AsmJsonImporter::createSourceLocation(Json const& _node) { - yulAssert(member(_node, "src").isString(), "'src' must be a string"); + yulAssert(member(_node, "src").is_string(), "'src' must be a string"); - return solidity::langutil::parseSourceLocation(_node["src"].asString(), m_sourceNames); + return solidity::langutil::parseSourceLocation(_node["src"].get(), m_sourceNames); } template -T AsmJsonImporter::createAsmNode(Json::Value const& _node) +T AsmJsonImporter::createAsmNode(Json const& _node) { T r; SourceLocation nativeLocation = createSourceLocation(_node); @@ -61,26 +61,26 @@ T AsmJsonImporter::createAsmNode(Json::Value const& _node) return r; } -Json::Value AsmJsonImporter::member(Json::Value const& _node, std::string const& _name) +Json AsmJsonImporter::member(Json const& _node, std::string const& _name) { - if (!_node.isMember(_name)) - return Json::nullValue; + if (!_node.contains(_name)) + return Json(); return _node[_name]; } -TypedName AsmJsonImporter::createTypedName(Json::Value const& _node) +TypedName AsmJsonImporter::createTypedName(Json const& _node) { auto typedName = createAsmNode(_node); - typedName.type = YulString{member(_node, "type").asString()}; - typedName.name = YulString{member(_node, "name").asString()}; + typedName.type = YulString{member(_node, "type").get()}; + typedName.name = YulString{member(_node, "name").get()}; return typedName; } -Statement AsmJsonImporter::createStatement(Json::Value const& _node) +Statement AsmJsonImporter::createStatement(Json const& _node) { - Json::Value jsonNodeType = member(_node, "nodeType"); - yulAssert(jsonNodeType.isString(), "Expected \"nodeType\" to be of type string!"); - std::string nodeType = jsonNodeType.asString(); + Json jsonNodeType = member(_node, "nodeType"); + yulAssert(jsonNodeType.is_string(), "Expected \"nodeType\" to be of type string!"); + std::string nodeType = jsonNodeType.get(); yulAssert(nodeType.substr(0, 3) == "Yul", "Invalid nodeType prefix"); nodeType = nodeType.substr(3); @@ -114,11 +114,11 @@ Statement AsmJsonImporter::createStatement(Json::Value const& _node) util::unreachable(); } -Expression AsmJsonImporter::createExpression(Json::Value const& _node) +Expression AsmJsonImporter::createExpression(Json const& _node) { - Json::Value jsonNodeType = member(_node, "nodeType"); - yulAssert(jsonNodeType.isString(), "Expected \"nodeType\" to be of type string!"); - std::string nodeType = jsonNodeType.asString(); + Json jsonNodeType = member(_node, "nodeType"); + yulAssert(jsonNodeType.is_string(), "Expected \"nodeType\" to be of type string!"); + std::string nodeType = jsonNodeType.get(); yulAssert(nodeType.substr(0, 3) == "Yul", "Invalid nodeType prefix"); nodeType = nodeType.substr(3); @@ -136,7 +136,7 @@ Expression AsmJsonImporter::createExpression(Json::Value const& _node) util::unreachable(); } -std::vector AsmJsonImporter::createExpressionVector(Json::Value const& _array) +std::vector AsmJsonImporter::createExpressionVector(Json const& _array) { std::vector ret; for (auto& var: _array) @@ -144,7 +144,7 @@ std::vector AsmJsonImporter::createExpressionVector(Json::Value cons return ret; } -std::vector AsmJsonImporter::createStatementVector(Json::Value const& _array) +std::vector AsmJsonImporter::createStatementVector(Json const& _array) { std::vector ret; for (auto& var: _array) @@ -152,25 +152,25 @@ std::vector AsmJsonImporter::createStatementVector(Json::Value const& return ret; } -Block AsmJsonImporter::createBlock(Json::Value const& _node) +Block AsmJsonImporter::createBlock(Json const& _node) { auto block = createAsmNode(_node); block.statements = createStatementVector(_node["statements"]); return block; } -Literal AsmJsonImporter::createLiteral(Json::Value const& _node) +Literal AsmJsonImporter::createLiteral(Json const& _node) { auto lit = createAsmNode(_node); - std::string kind = member(_node, "kind").asString(); + std::string kind = member(_node, "kind").get(); - solAssert(member(_node, "hexValue").isString() || member(_node, "value").isString(), ""); - if (_node.isMember("hexValue")) - lit.value = YulString{util::asString(util::fromHex(member(_node, "hexValue").asString()))}; + solAssert(member(_node, "hexValue").is_string() || member(_node, "value").is_string(), ""); + if (_node.contains("hexValue")) + lit.value = YulString{util::asString(util::fromHex(member(_node, "hexValue").get()))}; else - lit.value = YulString{member(_node, "value").asString()}; + lit.value = YulString{member(_node, "value").get()}; - lit.type= YulString{member(_node, "type").asString()}; + lit.type= YulString{member(_node, "type").get()}; if (kind == "number") { @@ -207,23 +207,23 @@ Literal AsmJsonImporter::createLiteral(Json::Value const& _node) return lit; } -Leave AsmJsonImporter::createLeave(Json::Value const& _node) +Leave AsmJsonImporter::createLeave(Json const& _node) { return createAsmNode(_node); } -Identifier AsmJsonImporter::createIdentifier(Json::Value const& _node) +Identifier AsmJsonImporter::createIdentifier(Json const& _node) { auto identifier = createAsmNode(_node); - identifier.name = YulString(member(_node, "name").asString()); + identifier.name = YulString(member(_node, "name").get()); return identifier; } -Assignment AsmJsonImporter::createAssignment(Json::Value const& _node) +Assignment AsmJsonImporter::createAssignment(Json const& _node) { auto assignment = createAsmNode(_node); - if (_node.isMember("variableNames")) + if (_node.contains("variableNames")) for (auto const& var: member(_node, "variableNames")) assignment.variableNames.emplace_back(createIdentifier(var)); @@ -231,7 +231,7 @@ Assignment AsmJsonImporter::createAssignment(Json::Value const& _node) return assignment; } -FunctionCall AsmJsonImporter::createFunctionCall(Json::Value const& _node) +FunctionCall AsmJsonImporter::createFunctionCall(Json const& _node) { auto functionCall = createAsmNode(_node); @@ -243,35 +243,35 @@ FunctionCall AsmJsonImporter::createFunctionCall(Json::Value const& _node) return functionCall; } -ExpressionStatement AsmJsonImporter::createExpressionStatement(Json::Value const& _node) +ExpressionStatement AsmJsonImporter::createExpressionStatement(Json const& _node) { auto statement = createAsmNode(_node); statement.expression = createExpression(member(_node, "expression")); return statement; } -VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json::Value const& _node) +VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json const& _node) { auto varDec = createAsmNode(_node); for (auto const& var: member(_node, "variables")) varDec.variables.emplace_back(createTypedName(var)); - if (_node.isMember("value")) + if (_node.contains("value")) varDec.value = std::make_unique(createExpression(member(_node, "value"))); return varDec; } -FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json::Value const& _node) +FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json const& _node) { auto funcDef = createAsmNode(_node); - funcDef.name = YulString{member(_node, "name").asString()}; + funcDef.name = YulString{member(_node, "name").get()}; - if (_node.isMember("parameters")) + if (_node.contains("parameters")) for (auto const& var: member(_node, "parameters")) funcDef.parameters.emplace_back(createTypedName(var)); - if (_node.isMember("returnVariables")) + if (_node.contains("returnVariables")) for (auto const& var: member(_node, "returnVariables")) funcDef.returnVariables.emplace_back(createTypedName(var)); @@ -279,7 +279,7 @@ FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json::Value const& return funcDef; } -If AsmJsonImporter::createIf(Json::Value const& _node) +If AsmJsonImporter::createIf(Json const& _node) { auto ifStatement = createAsmNode(_node); ifStatement.condition = std::make_unique(createExpression(member(_node, "condition"))); @@ -287,19 +287,19 @@ If AsmJsonImporter::createIf(Json::Value const& _node) return ifStatement; } -Case AsmJsonImporter::createCase(Json::Value const& _node) +Case AsmJsonImporter::createCase(Json const& _node) { auto caseStatement = createAsmNode(_node); auto const& value = member(_node, "value"); - if (value.isString()) - yulAssert(value.asString() == "default", "Expected default case"); + if (value.is_string()) + yulAssert(value.get() == "default", "Expected default case"); else caseStatement.value = std::make_unique(createLiteral(value)); caseStatement.body = createBlock(member(_node, "body")); return caseStatement; } -Switch AsmJsonImporter::createSwitch(Json::Value const& _node) +Switch AsmJsonImporter::createSwitch(Json const& _node) { auto switchStatement = createAsmNode(_node); switchStatement.expression = std::make_unique(createExpression(member(_node, "expression"))); @@ -308,7 +308,7 @@ Switch AsmJsonImporter::createSwitch(Json::Value const& _node) return switchStatement; } -ForLoop AsmJsonImporter::createForLoop(Json::Value const& _node) +ForLoop AsmJsonImporter::createForLoop(Json const& _node) { auto forLoop = createAsmNode(_node); forLoop.pre = createBlock(member(_node, "pre")); @@ -318,12 +318,12 @@ ForLoop AsmJsonImporter::createForLoop(Json::Value const& _node) return forLoop; } -Break AsmJsonImporter::createBreak(Json::Value const& _node) +Break AsmJsonImporter::createBreak(Json const& _node) { return createAsmNode(_node); } -Continue AsmJsonImporter::createContinue(Json::Value const& _node) +Continue AsmJsonImporter::createContinue(Json const& _node) { return createAsmNode(_node); } diff --git a/libyul/AsmJsonImporter.h b/libyul/AsmJsonImporter.h index 506352fa4..87933761a 100644 --- a/libyul/AsmJsonImporter.h +++ b/libyul/AsmJsonImporter.h @@ -23,7 +23,7 @@ #pragma once -#include +#include #include #include @@ -41,36 +41,36 @@ class AsmJsonImporter explicit AsmJsonImporter(std::vector> const& _sourceNames): m_sourceNames(_sourceNames) {} - yul::Block createBlock(Json::Value const& _node); + yul::Block createBlock(Json const& _node); private: - langutil::SourceLocation const createSourceLocation(Json::Value const& _node); + langutil::SourceLocation const createSourceLocation(Json const& _node); template - T createAsmNode(Json::Value const& _node); + T createAsmNode(Json const& _node); /// helper function to access member functions of the JSON /// and throw an error if it does not exist - Json::Value member(Json::Value const& _node, std::string const& _name); + Json member(Json const& _node, std::string const& _name); - yul::Statement createStatement(Json::Value const& _node); - yul::Expression createExpression(Json::Value const& _node); - std::vector createStatementVector(Json::Value const& _array); - std::vector createExpressionVector(Json::Value const& _array); + yul::Statement createStatement(Json const& _node); + yul::Expression createExpression(Json const& _node); + std::vector createStatementVector(Json const& _array); + std::vector createExpressionVector(Json const& _array); - yul::TypedName createTypedName(Json::Value const& _node); - yul::Literal createLiteral(Json::Value const& _node); - yul::Leave createLeave(Json::Value const& _node); - yul::Identifier createIdentifier(Json::Value const& _node); - yul::Assignment createAssignment(Json::Value const& _node); - yul::FunctionCall createFunctionCall(Json::Value const& _node); - yul::ExpressionStatement createExpressionStatement(Json::Value const& _node); - yul::VariableDeclaration createVariableDeclaration(Json::Value const& _node); - yul::FunctionDefinition createFunctionDefinition(Json::Value const& _node); - yul::If createIf(Json::Value const& _node); - yul::Case createCase(Json::Value const& _node); - yul::Switch createSwitch(Json::Value const& _node); - yul::ForLoop createForLoop(Json::Value const& _node); - yul::Break createBreak(Json::Value const& _node); - yul::Continue createContinue(Json::Value const& _node); + yul::TypedName createTypedName(Json const& _node); + yul::Literal createLiteral(Json const& _node); + yul::Leave createLeave(Json const& _node); + yul::Identifier createIdentifier(Json const& _node); + yul::Assignment createAssignment(Json const& _node); + yul::FunctionCall createFunctionCall(Json const& _node); + yul::ExpressionStatement createExpressionStatement(Json const& _node); + yul::VariableDeclaration createVariableDeclaration(Json const& _node); + yul::FunctionDefinition createFunctionDefinition(Json const& _node); + yul::If createIf(Json const& _node); + yul::Case createCase(Json const& _node); + yul::Switch createSwitch(Json const& _node); + yul::ForLoop createForLoop(Json const& _node); + yul::Break createBreak(Json const& _node); + yul::Continue createContinue(Json const& _node); std::vector> const& m_sourceNames; }; diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 0d3d66c8e..260cb7330 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -75,27 +75,27 @@ std::string Object::toString( return useSrcComment + "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}"; } -Json::Value Data::toJson() const +Json Data::toJson() const { - Json::Value ret{Json::objectValue}; + Json ret; ret["nodeType"] = "YulData"; ret["value"] = util::toHex(data); return ret; } -Json::Value Object::toJson() const +Json Object::toJson() const { yulAssert(code, "No code"); - Json::Value codeJson{Json::objectValue}; + Json codeJson; codeJson["nodeType"] = "YulCode"; codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */)(*code); - Json::Value subObjectsJson{Json::arrayValue}; + Json subObjectsJson = Json::array(); for (std::shared_ptr const& subObject: subObjects) - subObjectsJson.append(subObject->toJson()); + subObjectsJson.emplace_back(subObject->toJson()); - Json::Value ret{Json::objectValue}; + Json ret; ret["nodeType"] = "YulObject"; ret["name"] = name.str(); ret["code"] = codeJson; diff --git a/libyul/Object.h b/libyul/Object.h index 5f88d3bc7..54a8080d0 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -28,11 +28,11 @@ #include #include +#include #include #include #include -#include namespace solidity::yul { @@ -58,7 +58,7 @@ struct ObjectNode langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const = 0; - virtual Json::Value toJson() const = 0; + virtual Json toJson() const = 0; }; /** @@ -75,7 +75,7 @@ struct Data: public ObjectNode langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const override; - Json::Value toJson() const override; + Json toJson() const override; }; @@ -98,7 +98,7 @@ struct Object: public ObjectNode langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ) const; /// @returns a compact JSON representation of the AST. - Json::Value toJson() const; + Json toJson() const; /// @returns the set of names of data objects accessible from within the code of /// this object, including the name of object itself /// Handles all names containing dots as reserved identifiers, not accessible as data. diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 6c89cadbd..a4341cba3 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -312,7 +312,7 @@ std::string YulStack::print( return m_parserResult->toString(&languageToDialect(m_language, m_evmVersion), m_debugInfoSelection, _soliditySourceProvider) + "\n"; } -Json::Value YulStack::astJson() const +Json YulStack::astJson() const { yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); diff --git a/libyul/YulStack.h b/libyul/YulStack.h index 700fd2b3b..27f530b44 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -33,8 +34,6 @@ #include -#include - #include #include @@ -132,7 +131,7 @@ class YulStack: public langutil::CharStreamProvider std::string print( langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ) const; - Json::Value astJson() const; + Json astJson() const; /// Return the parsed and analyzed object. std::shared_ptr parserResult() const; diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 51db3a14d..954c9f2af 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -771,7 +771,7 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi yulAssert(util::contains(m_currentFunctionInfo->returnVariables, std::get(_slot))); // Strictly speaking the cost of the PUSH0 depends on the targeted EVM version, but the difference // will not matter here. - opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(0), langutil::EVMVersion());; + opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(0), langutil::EVMVersion()); } } }; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 4c08efb51..514f84c20 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -353,23 +353,23 @@ void CommandLineInterface::handleSignatureHashes(std::string const& _contract) if (!m_options.compiler.outputs.signatureHashes) return; - Json::Value interfaceSymbols = m_compiler->interfaceSymbols(_contract); + Json interfaceSymbols = m_compiler->interfaceSymbols(_contract); std::string out = "Function signatures:\n"; - for (auto const& name: interfaceSymbols["methods"].getMemberNames()) - out += interfaceSymbols["methods"][name].asString() + ": " + name + "\n"; + for (auto const& [name, value]: interfaceSymbols["methods"].items()) + out += value.get() + ": " + name + "\n"; - if (interfaceSymbols.isMember("errors")) + if (interfaceSymbols.contains("errors")) { out += "\nError signatures:\n"; - for (auto const& name: interfaceSymbols["errors"].getMemberNames()) - out += interfaceSymbols["errors"][name].asString() + ": " + name + "\n"; + for (auto const& [name, value]: interfaceSymbols["errors"].items()) + out += value.get() + ": " + name + "\n"; } - if (interfaceSymbols.isMember("events")) + if (interfaceSymbols.contains("events")) { out += "\nEvent signatures:\n"; - for (auto const& name: interfaceSymbols["events"].getMemberNames()) - out += interfaceSymbols["events"][name].asString() + ": " + name + "\n"; + for (auto const& [name, value]: interfaceSymbols["events"].items()) + out += value.get() + ": " + name + "\n"; } if (!m_options.output.dir.empty()) @@ -467,40 +467,40 @@ void CommandLineInterface::handleGasEstimation(std::string const& _contract) { solAssert(CompilerInputModes.count(m_options.input.mode) == 1); - Json::Value estimates = m_compiler->gasEstimates(_contract); + Json estimates = m_compiler->gasEstimates(_contract); sout() << "Gas estimation:" << std::endl; - if (estimates["creation"].isObject()) + if (estimates["creation"].is_object()) { - Json::Value creation = estimates["creation"]; + Json creation = estimates["creation"]; sout() << "construction:" << std::endl; - sout() << " " << creation["executionCost"].asString(); - sout() << " + " << creation["codeDepositCost"].asString(); - sout() << " = " << creation["totalCost"].asString() << std::endl; + sout() << " " << creation["executionCost"].get(); + sout() << " + " << creation["codeDepositCost"].get(); + sout() << " = " << creation["totalCost"].get() << std::endl; } - if (estimates["external"].isObject()) + if (estimates["external"].is_object()) { - Json::Value externalFunctions = estimates["external"]; + Json externalFunctions = estimates["external"]; sout() << "external:" << std::endl; - for (auto const& name: externalFunctions.getMemberNames()) + for (auto const& [name, value]: externalFunctions.items()) { if (name.empty()) sout() << " fallback:\t"; else sout() << " " << name << ":\t"; - sout() << externalFunctions[name].asString() << std::endl; + sout() << value.get() << std::endl; } } - if (estimates["internal"].isObject()) + if (estimates["internal"].is_object()) { - Json::Value internalFunctions = estimates["internal"]; + Json internalFunctions = estimates["internal"]; sout() << "internal:" << std::endl; - for (auto const& name: internalFunctions.getMemberNames()) + for (auto const& [name, value]: internalFunctions.items()) { sout() << " " << name << ":\t"; - sout() << internalFunctions[name].asString() << std::endl; + sout() << value.get() << std::endl; } } } @@ -613,27 +613,27 @@ void CommandLineInterface::readInputFiles() solThrow(CommandLineValidationError, "All specified input files either do not exist or are not regular files."); } -std::map CommandLineInterface::parseAstFromInput() +std::map CommandLineInterface::parseAstFromInput() { solAssert(m_options.input.mode == InputMode::CompilerWithASTImport); - std::map sourceJsons; + std::map sourceJsons; std::map tmpSources; for (SourceCode const& sourceCode: m_fileReader.sourceUnits() | ranges::views::values) { - Json::Value ast; + Json ast; astAssert(jsonParseStrict(sourceCode, ast), "Input file could not be parsed to JSON"); - astAssert(ast.isMember("sources"), "Invalid Format for import-JSON: Must have 'sources'-object"); + astAssert(ast.contains("sources"), "Invalid Format for import-JSON: Must have 'sources'-object"); - for (auto& src: ast["sources"].getMemberNames()) + for (auto const& [src, value]: ast["sources"].items()) { - std::string astKey = ast["sources"][src].isMember("ast") ? "ast" : "AST"; + std::string astKey = value.contains("ast") ? "ast" : "AST"; - astAssert(ast["sources"][src].isMember(astKey), "astkey is not member"); - astAssert(ast["sources"][src][astKey]["nodeType"].asString() == "SourceUnit", "Top-level node should be a 'SourceUnit'"); + astAssert(ast["sources"][src].contains(astKey), "astkey is not member"); + astAssert(ast["sources"][src][astKey]["nodeType"].get() == "SourceUnit", "Top-level node should be a 'SourceUnit'"); astAssert(sourceJsons.count(src) == 0, "All sources must have unique names"); - sourceJsons.emplace(src, std::move(ast["sources"][src][astKey])); + sourceJsons.emplace(src, std::move(value[astKey])); tmpSources[src] = util::jsonCompactPrint(ast); } } @@ -942,16 +942,16 @@ void CommandLineInterface::handleCombinedJSON() if (!m_options.compiler.combinedJsonRequests.has_value()) return; - Json::Value output(Json::objectValue); + Json output; output[g_strVersion] = frontend::VersionString; std::vector contracts = m_assemblyStack->contractNames(); if (!contracts.empty()) - output[g_strContracts] = Json::Value(Json::objectValue); + output[g_strContracts] = Json::object(); for (std::string const& contractName: contracts) { - Json::Value& contractData = output[g_strContracts][contractName] = Json::objectValue; + Json& contractData = output[g_strContracts][contractName] = Json::object(); // NOTE: The state checks here are more strict that in Standard JSON. There we allow // requesting certain outputs even if compilation fails as long as analysis went ok. @@ -1013,19 +1013,19 @@ void CommandLineInterface::handleCombinedJSON() if (needsSourceList) { // Indices into this array are used to abbreviate source names in source locations. - output[g_strSourceList] = Json::Value(Json::arrayValue); + output[g_strSourceList] = Json::array(); for (auto const& source: m_assemblyStack->sourceNames()) - output[g_strSourceList].append(source); + output[g_strSourceList].emplace_back(source); } if (m_options.compiler.combinedJsonRequests->ast) { solAssert(m_compiler); - output[g_strSources] = Json::Value(Json::objectValue); + output[g_strSources] = Json::object(); for (auto const& sourceCode: m_fileReader.sourceUnits()) { - output[g_strSources][sourceCode.first] = Json::Value(Json::objectValue); + output[g_strSources][sourceCode.first] = Json::object(); output[g_strSources][sourceCode.first]["AST"] = ASTJsonExporter( m_compiler->state(), m_compiler->sourceIndices() diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 1fb4ac00b..bcebcbcfd 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -120,7 +120,7 @@ class CommandLineInterface /// such that they can be imported into the compiler (importASTs()) /// (produced by --combined-json ast /// or standard-json output - std::map parseAstFromInput(); + std::map parseAstFromInput(); /// Create a file in the given directory /// @arg _fileName the name of the file diff --git a/test/Metadata.cpp b/test/Metadata.cpp index 2fea65c65..cdfcdfb19 100644 --- a/test/Metadata.cpp +++ b/test/Metadata.cpp @@ -172,33 +172,33 @@ std::optional> parseCBORMetadata(bytes const& bool isValidMetadata(std::string const& _serialisedMetadata) { - Json::Value metadata; + Json metadata; if (!util::jsonParseStrict(_serialisedMetadata, metadata)) return false; return isValidMetadata(metadata); } -bool isValidMetadata(Json::Value const& _metadata) +bool isValidMetadata(Json const& _metadata) { if ( - !_metadata.isObject() || - !_metadata.isMember("version") || - !_metadata.isMember("language") || - !_metadata.isMember("compiler") || - !_metadata.isMember("settings") || - !_metadata.isMember("sources") || - !_metadata.isMember("output") || - !_metadata["settings"].isMember("evmVersion") || - !_metadata["settings"].isMember("metadata") || - !_metadata["settings"]["metadata"].isMember("bytecodeHash") + !_metadata.is_object() || + !_metadata.contains("version") || + !_metadata.contains("language") || + !_metadata.contains("compiler") || + !_metadata.contains("settings") || + !_metadata.contains("sources") || + !_metadata.contains("output") || + !_metadata["settings"].contains("evmVersion") || + !_metadata["settings"].contains("metadata") || + !_metadata["settings"]["metadata"].contains("bytecodeHash") ) return false; - if (!_metadata["version"].isNumeric() || _metadata["version"] != 1) + if (!_metadata["version"].is_number() || _metadata["version"] != 1) return false; - if (!_metadata["language"].isString() || _metadata["language"].asString() != "Solidity") + if (!_metadata["language"].is_string() || _metadata["language"].get() != "Solidity") return false; /// @TODO add more strict checks diff --git a/test/Metadata.h b/test/Metadata.h index 86b43e245..f3dae0cbd 100644 --- a/test/Metadata.h +++ b/test/Metadata.h @@ -53,6 +53,6 @@ std::optional> parseCBORMetadata(bytes const& bool isValidMetadata(std::string const& _serialisedMetadata); /// Expects a deserialised metadata JSON and returns true if the content is valid metadata. -bool isValidMetadata(Json::Value const& _metadata); +bool isValidMetadata(Json const& _metadata); } // end namespaces diff --git a/test/cmdlineTests/standard_import_with_comments/input.json b/test/cmdlineTests/standard_import_with_comments/input.json new file mode 100644 index 000000000..4ed88177c --- /dev/null +++ b/test/cmdlineTests/standard_import_with_comments/input.json @@ -0,0 +1,95 @@ +{ + "language": "SolidityAST", + "sources": { // this is a comment + "A": { + "ast": { + "absolutePath": "A", + "exportedSymbols": { + "C": [ + 6 /* and this another comment */ + ] + }, + "id": 7, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": /* and this is a comment too */[ + // this is a comment + { + /*this is a comment*/"id"/* and this is another comment too*/: 1, + "literals": [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 6, + "linearizedBaseContracts": [ + 6 + ], + "name": "C", + "nameLocation": "68:1:0", + "nodeType": "ContractDefinition", + "nodes": [ + { + "body": { + "id": 4, + "nodeType": "Block", + "src": "97:2:0", + "statements": [] + }, + "functionSelector": "26121ff0", + "id": 5, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f", + "nameLocation": "81:1:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 2, + "nodeType": "ParameterList", + "parameters": [], + "src": "82:2:0" + }, + "returnParameters": { + "id": 3, + "nodeType": "ParameterList", + "parameters": [], + "src": "97:0:0" + }, + "scope": 6, + "src": "72:27:0", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + } + ], + "scope": 7, + "src": "59:42:0", + "usedErrors": [] + } + ], + "src": "36:65:0" + }, + "id": 0 + } + }, + "settings": { + "outputSelection": { + "*": { + "": [ + "ast" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_with_comments/output.json b/test/cmdlineTests/standard_import_with_comments/output.json new file mode 100644 index 000000000..6ecac5ca3 --- /dev/null +++ b/test/cmdlineTests/standard_import_with_comments/output.json @@ -0,0 +1,97 @@ +{ + "sources": + { + "A": + { + "ast": + { + "absolutePath": "A", + "exportedSymbols": + { + "C": + [ + 6 + ] + }, + "id": 7, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": + [ + { + "id": 1, + "literals": + [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 6, + "linearizedBaseContracts": + [ + 6 + ], + "name": "C", + "nameLocation": "68:1:0", + "nodeType": "ContractDefinition", + "nodes": + [ + { + "body": + { + "id": 4, + "nodeType": "Block", + "src": "97:2:0", + "statements": [] + }, + "functionSelector": "26121ff0", + "id": 5, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f", + "nameLocation": "81:1:0", + "nodeType": "FunctionDefinition", + "parameters": + { + "id": 2, + "nodeType": "ParameterList", + "parameters": [], + "src": "82:2:0" + }, + "returnParameters": + { + "id": 3, + "nodeType": "ParameterList", + "parameters": [], + "src": "97:0:0" + }, + "scope": 6, + "src": "72:27:0", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + } + ], + "scope": 7, + "src": "59:42:0", + "usedErrors": [], + "usedEvents": [] + } + ], + "src": "36:65:0" + }, + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_import_with_comments_simple/input.json b/test/cmdlineTests/standard_import_with_comments_simple/input.json new file mode 100644 index 000000000..21faca8c6 --- /dev/null +++ b/test/cmdlineTests/standard_import_with_comments_simple/input.json @@ -0,0 +1,85 @@ +{ + "language": "SolidityAST", + "sources": { + // this is a comment + "A": { + "ast": { + "absolutePath": "A", + "exportedSymbols": { + "C": [6 /* and this another comment */] + }, + "id": 7, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1, + "literals": ["solidity", ">=", "0.0"], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 6, + "linearizedBaseContracts": [6], + "name": "C", + "nameLocation": "68:1:0", + "nodeType": "ContractDefinition", + "nodes": [ + { + "body": { + "id": 4, + "nodeType": "Block", + "src": "97:2:0", + "statements": [] + }, + "functionSelector": "26121ff0", + "id": 5, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f", + "nameLocation": "81:1:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 2, + "nodeType": "ParameterList", + "parameters": [], + "src": "82:2:0" + }, + "returnParameters": { + "id": 3, + "nodeType": "ParameterList", + "parameters": [], + "src": "97:0:0" + }, + "scope": 6, + "src": "72:27:0", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + } + ], + "scope": 7, + "src": "59:42:0", + "usedErrors": [] + } + ], + "src": "36:65:0" + }, + "id": 0 + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["ast"] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_with_comments_simple/output.json b/test/cmdlineTests/standard_import_with_comments_simple/output.json new file mode 100644 index 000000000..6ecac5ca3 --- /dev/null +++ b/test/cmdlineTests/standard_import_with_comments_simple/output.json @@ -0,0 +1,97 @@ +{ + "sources": + { + "A": + { + "ast": + { + "absolutePath": "A", + "exportedSymbols": + { + "C": + [ + 6 + ] + }, + "id": 7, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": + [ + { + "id": 1, + "literals": + [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 6, + "linearizedBaseContracts": + [ + 6 + ], + "name": "C", + "nameLocation": "68:1:0", + "nodeType": "ContractDefinition", + "nodes": + [ + { + "body": + { + "id": 4, + "nodeType": "Block", + "src": "97:2:0", + "statements": [] + }, + "functionSelector": "26121ff0", + "id": 5, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f", + "nameLocation": "81:1:0", + "nodeType": "FunctionDefinition", + "parameters": + { + "id": 2, + "nodeType": "ParameterList", + "parameters": [], + "src": "82:2:0" + }, + "returnParameters": + { + "id": 3, + "nodeType": "ParameterList", + "parameters": [], + "src": "97:0:0" + }, + "scope": 6, + "src": "72:27:0", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + } + ], + "scope": 7, + "src": "59:42:0", + "usedErrors": [], + "usedEvents": [] + } + ], + "src": "36:65:0" + }, + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_import_with_invalid_utf8/input.json b/test/cmdlineTests/standard_import_with_invalid_utf8/input.json new file mode 100644 index 000000000..7b54aebfb --- /dev/null +++ b/test/cmdlineTests/standard_import_with_invalid_utf8/input.json @@ -0,0 +1,29 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { + "begin": 36, + "end": 51, + "name": "PUSH", + "source": 0, + "value": "\ud800" + } + ], + "sourceList": [ + "" + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": [ + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_with_invalid_utf8/output.json b/test/cmdlineTests/standard_import_with_invalid_utf8/output.json new file mode 100644 index 000000000..057e4fe16 --- /dev/null +++ b/test/cmdlineTests/standard_import_with_invalid_utf8/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "parse error at line 12, column 23: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\ud800\"'", + "message": "parse error at line 12, column 23: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\ud800\"'", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_non_utf8_filename/input.json b/test/cmdlineTests/standard_non_utf8_filename/input.json new file mode 100644 index 000000000..b0f7d5957 --- /dev/null +++ b/test/cmdlineTests/standard_non_utf8_filename/input.json @@ -0,0 +1,17 @@ +{ + "language": "Solidity", + "sources": + { + "": + { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; pragma abicoder v2; contract C { function f() public pure {} }" + } + }, + "settings": + { + "outputSelection": + { + "*": { "*": ["ir"] } + } + } +} diff --git a/test/cmdlineTests/standard_non_utf8_filename/output.json b/test/cmdlineTests/standard_non_utf8_filename/output.json new file mode 100644 index 000000000..a74a83a98 --- /dev/null +++ b/test/cmdlineTests/standard_non_utf8_filename/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: ill-formed UTF-8 byte; last read: '\"\\xff'; expected string literal", + "message": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: ill-formed UTF-8 byte; last read: '\"\\xff'; expected string literal", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_non_utf8_filename2/input.json b/test/cmdlineTests/standard_non_utf8_filename2/input.json new file mode 100644 index 000000000..7310c1472 --- /dev/null +++ b/test/cmdlineTests/standard_non_utf8_filename2/input.json @@ -0,0 +1,17 @@ +{ + "language": "Solidity", + "sources": + { + "": + { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; pragma abicoder v2; contract C { function f() public pure {} }" + } + }, + "settings": + { + "outputSelection": + { + "*": { "*": ["ir"] } + } + } +} diff --git a/test/cmdlineTests/standard_non_utf8_filename2/output.json b/test/cmdlineTests/standard_non_utf8_filename2/output.json new file mode 100644 index 000000000..a74a83a98 --- /dev/null +++ b/test/cmdlineTests/standard_non_utf8_filename2/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: ill-formed UTF-8 byte; last read: '\"\\xff'; expected string literal", + "message": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: ill-formed UTF-8 byte; last read: '\"\\xff'; expected string literal", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_raw_utf16_filename/input.json b/test/cmdlineTests/standard_raw_utf16_filename/input.json new file mode 100644 index 0000000000000000000000000000000000000000..1c4a1b3232cf6ae00d16546bd94afcc8ee2d4fd6 GIT binary patch literal 297 zcmYk1O-sZu5QckAe#I~+mF;fPTNk~opu!#&dQeag*>qY4Vp7sXkkG%qXVX$phGCcw zo_XIS1sY}hsCvR0uyKZ44nMfbi_t}|X~bHJB!$4@xwsT2$EA2()90?850(po+Sx!h z%&6TCn$zQ3d1Os?r1GWB3+|YF4Ns?IdAF@T?BG@ZrC?m&!oz*Ft@f~v)tR+x$;0>U z9%i&xI=}%EbkXX-&O&!}4MRK|*133sG{J;f&LqXOc%Ts2_J1Z^3_}bJ8Cn4UwBKaa R32-j&$R0l-Ll%&n'; expected string literal", + "message": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: control character U+0000 (NUL) must be escaped to \\u0000; last read: '\"'; expected string literal", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 2b01ae03c..afad9d13d 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) "{\"begin\":8,\"end\":18,\"name\":\"MSTORE\",\"source\":2}" "]},\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"},\"sourceList\":[\"root.asm\",\"sub.asm\",\"verbatim.asm\"]}" }; - Json::Value jsonValue; + Json jsonValue; BOOST_CHECK(util::jsonParseStrict(json, jsonValue)); BOOST_CHECK_EQUAL(util::jsonCompactPrint(_assembly.assemblyJSON(indices)), util::jsonCompactPrint(jsonValue)); } diff --git a/test/libsolidity/ASTPropertyTest.cpp b/test/libsolidity/ASTPropertyTest.cpp index 8dc2c2930..05c9b8786 100644 --- a/test/libsolidity/ASTPropertyTest.cpp +++ b/test/libsolidity/ASTPropertyTest.cpp @@ -108,20 +108,20 @@ void ASTPropertyTest::readExpectations() m_expectation = formatExpectations(false /* _obtainedResult */); } -void ASTPropertyTest::extractTestsFromAST(Json::Value const& _astJson) +void ASTPropertyTest::extractTestsFromAST(Json const& _astJson) { - std::queue nodesToVisit; + std::queue nodesToVisit; nodesToVisit.push(_astJson); while (!nodesToVisit.empty()) { - Json::Value& node = nodesToVisit.front(); + Json& node = nodesToVisit.front(); - if (node.isArray()) + if (node.is_array()) for (auto&& member: node) nodesToVisit.push(member); - else if (node.isObject()) - for (std::string const& memberName: node.getMemberNames()) + else if (node.is_object()) + for (auto const& [memberName, value]: node.items()) { if (memberName != "documentation") { @@ -129,9 +129,8 @@ void ASTPropertyTest::extractTestsFromAST(Json::Value const& _astJson) continue; } - std::string nodeDocstring = node["documentation"].isObject() ? - node["documentation"]["text"].asString() : - node["documentation"].asString(); + std::string nodeDocstring = value.is_object() ? + value["text"].get() : value.get(); soltestAssert(!nodeDocstring.empty()); std::vector pairs = readKeyValuePairs(nodeDocstring); @@ -150,17 +149,22 @@ void ASTPropertyTest::extractTestsFromAST(Json::Value const& _astJson) ); m_tests[testId].property = testedProperty; - soltestAssert(node.isMember("nodeType")); - std::optional propertyNode = jsonValueByPath(node, testedProperty); + soltestAssert(node.contains("nodeType")); + std::optional propertyNode = jsonValueByPath(node, testedProperty); soltestAssert( propertyNode.has_value(), - node["nodeType"].asString() + " node does not have a property named \""s + testedProperty + "\"" + node["nodeType"].get() + " node does not have a property named \""s + testedProperty + "\"" ); soltestAssert( - !propertyNode->isObject() && !propertyNode->isArray(), + !propertyNode->is_object() && !propertyNode->is_array(), "Property \"" + testedProperty + "\" is an object or an array." ); - m_tests[testId].obtainedValue = propertyNode->asString(); + if (propertyNode->is_string()) + m_tests[testId].obtainedValue = propertyNode->get(); + else if (propertyNode->is_boolean()) + m_tests[testId].obtainedValue = fmt::format("{}", propertyNode->get()); + else + soltestAssert(false); } } @@ -195,8 +199,8 @@ TestCase::TestResult ASTPropertyTest::run(std::ostream& _stream, std::string con SourceReferenceFormatter::formatErrorInformation(compiler.errors(), compiler, _formatted) )); - Json::Value astJson = ASTJsonExporter(compiler.state()).toJson(compiler.ast("A")); - soltestAssert(astJson); + Json astJson = ASTJsonExporter(compiler.state()).toJson(compiler.ast("A")); + soltestAssert(!astJson.empty()); extractTestsFromAST(astJson); diff --git a/test/libsolidity/ASTPropertyTest.h b/test/libsolidity/ASTPropertyTest.h index e4cec0528..6130cedb2 100644 --- a/test/libsolidity/ASTPropertyTest.h +++ b/test/libsolidity/ASTPropertyTest.h @@ -56,7 +56,7 @@ class ASTPropertyTest: public TestCase void readExpectations(); std::vector readKeyValuePairs(std::string const& _input); - void extractTestsFromAST(Json::Value const& _astJson); + void extractTestsFromAST(Json const& _astJson); std::string formatExpectations(bool _obtainedResult = true); std::vector m_testOrder; diff --git a/test/libsolidity/GasTest.cpp b/test/libsolidity/GasTest.cpp index 4786a2a86..14722535e 100644 --- a/test/libsolidity/GasTest.cpp +++ b/test/libsolidity/GasTest.cpp @@ -82,18 +82,18 @@ void GasTest::parseExpectations(std::istream& _stream) void GasTest::printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const { - Json::Value estimates = compiler().gasEstimates(compiler().lastContractName()); - for (auto groupIt = estimates.begin(); groupIt != estimates.end(); ++groupIt) + Json estimates = compiler().gasEstimates(compiler().lastContractName()); + for (auto& [key, group] : estimates.items()) { - _stream << _linePrefix << groupIt.key().asString() << ":" << std::endl; - for (auto it = groupIt->begin(); it != groupIt->end(); ++it) + _stream << _linePrefix << key << ":" << std::endl; + for (auto& [elementKey, value] : group.items()) { _stream << _linePrefix << " "; - if (it.key().asString().empty()) + if (elementKey.empty()) _stream << "fallback"; else - _stream << it.key().asString(); - _stream << ": " << it->asString() << std::endl; + _stream << elementKey; + _stream << ": " << value.get() << std::endl; } } } @@ -128,14 +128,14 @@ TestCase::TestResult GasTest::run(std::ostream& _stream, std::string const& _lin return TestResult::FatalError; } - Json::Value estimateGroups = compiler().gasEstimates(compiler().lastContractName()); + Json estimateGroups = compiler().gasEstimates(compiler().lastContractName()); if ( m_expectations.size() == estimateGroups.size() && boost::all(m_expectations, [&](auto const& expectations) { auto const& estimates = estimateGroups[expectations.first]; return estimates.size() == expectations.second.size() && boost::all(expectations.second, [&](auto const& entry) { - return entry.second == estimates[entry.first].asString(); + return entry.second == estimates[entry.first].template get(); }); }) ) diff --git a/test/libsolidity/LibSolc.cpp b/test/libsolidity/LibSolc.cpp index 1a7a6ba69..f7a434dcf 100644 --- a/test/libsolidity/LibSolc.cpp +++ b/test/libsolidity/LibSolc.cpp @@ -36,30 +36,30 @@ namespace /// TODO: share this between StandardCompiler.cpp /// Helper to match a specific error type and message -bool containsError(Json::Value const& _compilerResult, std::string const& _type, std::string const& _message) +bool containsError(Json const& _compilerResult, std::string const& _type, std::string const& _message) { - if (!_compilerResult.isMember("errors")) + if (!_compilerResult.contains("errors")) return false; for (auto const& error: _compilerResult["errors"]) { - BOOST_REQUIRE(error.isObject()); - BOOST_REQUIRE(error["type"].isString()); - BOOST_REQUIRE(error["message"].isString()); - if ((error["type"].asString() == _type) && (error["message"].asString() == _message)) + BOOST_REQUIRE(error.is_object()); + BOOST_REQUIRE(error["type"].is_string()); + BOOST_REQUIRE(error["message"].is_string()); + if ((error["type"].get() == _type) && (error["message"].get() == _message)) return true; } return false; } -Json::Value compile(std::string const& _input, CStyleReadFileCallback _callback = nullptr) +Json compile(std::string const& _input, CStyleReadFileCallback _callback = nullptr) { char* output_ptr = solidity_compile(_input.c_str(), _callback, nullptr); std::string output(output_ptr); solidity_free(output_ptr); solidity_reset(); - Json::Value ret; + Json ret; BOOST_REQUIRE(util::jsonParseStrict(output, ret)); return ret; } @@ -100,14 +100,14 @@ BOOST_AUTO_TEST_CASE(standard_compilation) } } )"; - Json::Value result = compile(input); - BOOST_REQUIRE(result.isObject()); + Json result = compile(input); + BOOST_REQUIRE(result.is_object()); // Only tests some assumptions. The StandardCompiler is tested properly in another suite. - BOOST_CHECK(result.isMember("sources")); + BOOST_CHECK(result.contains("sources")); // This used to test that it is a member, but we did not actually request any output, // so there should not be a contract member. - BOOST_CHECK(!result.isMember("contracts")); + BOOST_CHECK(!result.contains("contracts")); } BOOST_AUTO_TEST_CASE(missing_callback) @@ -122,8 +122,8 @@ BOOST_AUTO_TEST_CASE(missing_callback) } } )"; - Json::Value result = compile(input); - BOOST_REQUIRE(result.isObject()); + Json result = compile(input); + BOOST_REQUIRE(result.is_object()); BOOST_CHECK(containsError(result, "ParserError", "Source \"missing.sol\" not found: File not supplied initially.")); } @@ -168,8 +168,8 @@ BOOST_AUTO_TEST_CASE(with_callback) } }; - Json::Value result = compile(input, callback); - BOOST_REQUIRE(result.isObject()); + Json result = compile(input, callback); + BOOST_REQUIRE(result.is_object()); // This ensures that "found.sol" was properly loaded which triggered the second import statement. BOOST_CHECK(containsError(result, "ParserError", "Source \"missing.sol\" not found: Missing file.")); diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index 029419af1..94687f990 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -57,17 +57,17 @@ std::optional compileAndCheckLicenseMetadata(std::string const& _co BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata(_contractName); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK_EQUAL(metadata["sources"].size(), 1); - BOOST_REQUIRE(metadata["sources"].isMember("A.sol")); + BOOST_REQUIRE(metadata["sources"].contains("A.sol")); - if (metadata["sources"]["A.sol"].isMember("license")) + if (metadata["sources"]["A.sol"].contains("license")) { - BOOST_REQUIRE(metadata["sources"]["A.sol"]["license"].isString()); - return metadata["sources"]["A.sol"]["license"].asString(); + BOOST_REQUIRE(metadata["sources"]["A.sol"]["license"].is_string()); + return metadata["sources"]["A.sol"]["license"].get(); } else return std::nullopt; @@ -288,12 +288,12 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources) BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("A"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK_EQUAL(metadata["sources"].size(), 1); - BOOST_CHECK(metadata["sources"].isMember("A")); + BOOST_CHECK(metadata["sources"].contains("A")); } BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports) @@ -329,14 +329,14 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports) BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("C"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); BOOST_CHECK_EQUAL(metadata["sources"].size(), 3); - BOOST_CHECK(metadata["sources"].isMember("A")); - BOOST_CHECK(metadata["sources"].isMember("B")); - BOOST_CHECK(metadata["sources"].isMember("C")); + BOOST_CHECK(metadata["sources"].contains("A")); + BOOST_CHECK(metadata["sources"].contains("B")); + BOOST_CHECK(metadata["sources"].contains("C")); } BOOST_AUTO_TEST_CASE(metadata_useLiteralContent) @@ -357,16 +357,16 @@ BOOST_AUTO_TEST_CASE(metadata_useLiteralContent) compilerStack.useMetadataLiteralSources(_literal); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string metadata_str = compilerStack.metadata("test"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(metadata_str, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); - BOOST_CHECK(metadata.isMember("settings")); - BOOST_CHECK(metadata["settings"].isMember("metadata")); - BOOST_CHECK(metadata["settings"]["metadata"].isMember("bytecodeHash")); + BOOST_CHECK(metadata.contains("settings")); + BOOST_CHECK(metadata["settings"].contains("metadata")); + BOOST_CHECK(metadata["settings"]["metadata"].contains("bytecodeHash")); if (_literal) { - BOOST_CHECK(metadata["settings"]["metadata"].isMember("useLiteralContent")); - BOOST_CHECK(metadata["settings"]["metadata"]["useLiteralContent"].asBool()); + BOOST_CHECK(metadata["settings"]["metadata"].contains("useLiteralContent")); + BOOST_CHECK(metadata["settings"]["metadata"]["useLiteralContent"].get()); } }; @@ -391,17 +391,17 @@ BOOST_AUTO_TEST_CASE(metadata_viair) compilerStack.setViaIR(_viaIR); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(compilerStack.metadata("test"), metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); - BOOST_CHECK(metadata.isMember("settings")); + BOOST_CHECK(metadata.contains("settings")); if (_viaIR) { - BOOST_CHECK(metadata["settings"].isMember("viaIR")); - BOOST_CHECK(metadata["settings"]["viaIR"].asBool()); + BOOST_CHECK(metadata["settings"].contains("viaIR")); + BOOST_CHECK(metadata["settings"]["viaIR"].get()); } else - BOOST_CHECK(!metadata["settings"].isMember("viaIR")); + BOOST_CHECK(!metadata["settings"].contains("viaIR")); BOOST_CHECK(compilerStack.cborMetadata("test") == compilerStack.cborMetadata("test", _viaIR)); BOOST_CHECK(compilerStack.cborMetadata("test") != compilerStack.cborMetadata("test", !_viaIR)); @@ -431,7 +431,7 @@ BOOST_AUTO_TEST_CASE(metadata_revert_strings) BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("A"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); @@ -469,14 +469,14 @@ BOOST_AUTO_TEST_CASE(metadata_optimiser_sequence) BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); std::string const& serialisedMetadata = compilerStack.metadata("C"); - Json::Value metadata; + Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); - BOOST_CHECK(metadata["settings"]["optimizer"].isMember("details")); - BOOST_CHECK(metadata["settings"]["optimizer"]["details"].isMember("yulDetails")); - BOOST_CHECK(metadata["settings"]["optimizer"]["details"]["yulDetails"].isMember("optimizerSteps")); + BOOST_CHECK(metadata["settings"]["optimizer"].contains("details")); + BOOST_CHECK(metadata["settings"]["optimizer"]["details"].contains("yulDetails")); + BOOST_CHECK(metadata["settings"]["optimizer"]["details"]["yulDetails"].contains("optimizerSteps")); - std::string const metadataOptimizerSteps = metadata["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"].asString(); + std::string const metadataOptimizerSteps = metadata["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"].get(); std::string const expectedMetadataOptimiserSteps = _optimizerSequence + ":" + _optimizerCleanupSequence; BOOST_CHECK_EQUAL(metadataOptimizerSteps, expectedMetadataOptimiserSteps); }; diff --git a/test/libsolidity/NatspecJSONTest.cpp b/test/libsolidity/NatspecJSONTest.cpp index 9f1ba1d7d..7dff638f0 100644 --- a/test/libsolidity/NatspecJSONTest.cpp +++ b/test/libsolidity/NatspecJSONTest.cpp @@ -67,7 +67,7 @@ void NatspecJSONTest::parseCustomExpectations(std::istream& _stream) std::string rawJSON = extractExpectationJSON(_stream); std::string jsonErrors; - Json::Value parsedJSON; + Json parsedJSON; bool jsonParsingSuccessful = jsonParseStrict(rawJSON, parsedJSON, &jsonErrors); if (!jsonParsingSuccessful) BOOST_THROW_EXCEPTION(std::runtime_error(fmt::format( @@ -86,7 +86,7 @@ void NatspecJSONTest::parseCustomExpectations(std::istream& _stream) bool NatspecJSONTest::expectationsMatch() { - // NOTE: Comparing pretty printed Json::Values to avoid using its operator==, which fails to + // NOTE: Comparing pretty printed Jsons to avoid using its operator==, which fails to // compare equal numbers as equal. For example, for 'version' field the value is sometimes int, // sometimes uint and they compare as different even when both are 1. return diff --git a/test/libsolidity/NatspecJSONTest.h b/test/libsolidity/NatspecJSONTest.h index 762b88d10..619ece83b 100644 --- a/test/libsolidity/NatspecJSONTest.h +++ b/test/libsolidity/NatspecJSONTest.h @@ -44,7 +44,7 @@ enum class NatspecJSONKind std::ostream& operator<<(std::ostream& _output, NatspecJSONKind _kind); -using NatspecMap = std::map>; +using NatspecMap = std::map>; using SerializedNatspecMap = std::map>; class NatspecJSONTest: public SyntaxTest diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 63e8a924a..b0bdb95cb 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -429,7 +429,7 @@ TestCase::TestResult SemanticTest::runTest( { soltestAssert( m_allowNonExistingFunctions || - m_compiler.interfaceSymbols(m_compiler.lastContractName(m_sources.mainSourceFile))["methods"].isMember(test.call().signature), + m_compiler.interfaceSymbols(m_compiler.lastContractName(m_sources.mainSourceFile))["methods"].contains(test.call().signature), "The function " + test.call().signature + " is not known to the compiler" ); diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 22db222ea..cdb6c5bd2 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -55,97 +56,97 @@ langutil::Error::Severity str2Severity(std::string const& _cat) } /// Helper to match a specific error type and message -bool containsError(Json::Value const& _compilerResult, std::string const& _type, std::string const& _message) +bool containsError(Json const& _compilerResult, std::string const& _type, std::string const& _message) { - if (!_compilerResult.isMember("errors")) + if (!_compilerResult.contains("errors")) return false; for (auto const& error: _compilerResult["errors"]) { - BOOST_REQUIRE(error.isObject()); - BOOST_REQUIRE(error["type"].isString()); - BOOST_REQUIRE(error["message"].isString()); - if ((error["type"].asString() == _type) && (error["message"].asString() == _message)) + BOOST_REQUIRE(error.is_object()); + BOOST_REQUIRE(error["type"].is_string()); + BOOST_REQUIRE(error["message"].is_string()); + if ((error["type"].get() == _type) && (error["message"].get() == _message)) return true; } return false; } -bool containsAtMostWarnings(Json::Value const& _compilerResult) +bool containsAtMostWarnings(Json const& _compilerResult) { - if (!_compilerResult.isMember("errors")) + if (!_compilerResult.contains("errors")) return true; for (auto const& error: _compilerResult["errors"]) { - BOOST_REQUIRE(error.isObject()); - BOOST_REQUIRE(error["severity"].isString()); - if (langutil::Error::isError(str2Severity(error["severity"].asString()))) + BOOST_REQUIRE(error.is_object()); + BOOST_REQUIRE(error["severity"].is_string()); + if (langutil::Error::isError(str2Severity(error["severity"].get()))) return false; } return true; } -Json::Value getContractResult(Json::Value const& _compilerResult, std::string const& _file, std::string const& _name) +Json getContractResult(Json const& _compilerResult, std::string const& _file, std::string const& _name) { - if ( - !_compilerResult["contracts"].isObject() || - !_compilerResult["contracts"][_file].isObject() || - !_compilerResult["contracts"][_file][_name].isObject() + if (!_compilerResult.contains("contracts") || + !_compilerResult["contracts"].is_object() || + !_compilerResult["contracts"][_file].is_object() || + !_compilerResult["contracts"][_file][_name].is_object() ) - return Json::Value(); + return Json(); return _compilerResult["contracts"][_file][_name]; } -void checkLinkReferencesSchema(Json::Value const& _contractResult) +void checkLinkReferencesSchema(Json const& _contractResult) { - BOOST_TEST_REQUIRE(_contractResult.isObject()); - BOOST_TEST_REQUIRE(_contractResult["evm"]["bytecode"].isObject()); + BOOST_TEST_REQUIRE(_contractResult.is_object()); + BOOST_TEST_REQUIRE(_contractResult["evm"]["bytecode"].is_object()); - Json::Value const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"]; - BOOST_TEST_REQUIRE(linkReferenceResult.isObject()); + Json const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"]; + BOOST_TEST_REQUIRE(linkReferenceResult.is_object()); - for (std::string const& fileName: linkReferenceResult.getMemberNames()) + for (auto const& [fileName, references]: linkReferenceResult.items()) { - BOOST_TEST_REQUIRE(linkReferenceResult[fileName].isObject()); - for (std::string const& libraryName: linkReferenceResult[fileName].getMemberNames()) + BOOST_TEST_REQUIRE(references.is_object()); + for (auto const& [libraryName, libraryValue]: references.items()) { - BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName].isArray()); - BOOST_TEST_REQUIRE(!linkReferenceResult[fileName][libraryName].empty()); - for (int i = 0; i < static_cast(linkReferenceResult.size()); ++i) + BOOST_TEST_REQUIRE(libraryValue.is_array()); + BOOST_TEST_REQUIRE(!libraryValue.empty()); + for (size_t i = 0; i < static_cast(linkReferenceResult.size()); ++i) { - BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i].isObject()); - BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i].size() == 2); - BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i]["length"].isUInt()); - BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i]["start"].isUInt()); + BOOST_TEST_REQUIRE(libraryValue[i].is_object()); + BOOST_TEST_REQUIRE(libraryValue[i].size() == 2); + BOOST_TEST_REQUIRE(libraryValue[i]["length"].is_number_unsigned()); + BOOST_TEST_REQUIRE(libraryValue[i]["start"].is_number_unsigned()); } } } } -void expectLinkReferences(Json::Value const& _contractResult, std::map> const& _expectedLinkReferences) +void expectLinkReferences(Json const& _contractResult, std::map> const& _expectedLinkReferences) { checkLinkReferencesSchema(_contractResult); - Json::Value const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"]; + Json const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"]; BOOST_TEST(linkReferenceResult.size() == _expectedLinkReferences.size()); for (auto const& [fileName, libraries]: _expectedLinkReferences) { - BOOST_TEST(linkReferenceResult.isMember(fileName)); + BOOST_TEST(linkReferenceResult.contains(fileName)); BOOST_TEST(linkReferenceResult[fileName].size() == libraries.size()); for (std::string const& libraryName: libraries) - BOOST_TEST(linkReferenceResult[fileName].isMember(libraryName)); + BOOST_TEST(linkReferenceResult[fileName].contains(libraryName)); } } -Json::Value compile(std::string _input) +Json compile(std::string _input) { StandardCompiler compiler; std::string output = compiler.compile(std::move(_input)); - Json::Value ret; + Json ret; BOOST_REQUIRE(util::jsonParseStrict(output, ret)); return ret; } @@ -156,25 +157,24 @@ BOOST_AUTO_TEST_SUITE(StandardCompiler) BOOST_AUTO_TEST_CASE(assume_object_input) { - Json::Value result; + Json result; /// Use the native JSON interface of StandardCompiler to trigger these frontend::StandardCompiler compiler; - result = compiler.compile(Json::Value()); + result = compiler.compile(Json()); BOOST_CHECK(containsError(result, "JSONError", "Input is not a JSON object.")); - result = compiler.compile(Json::Value("INVALID")); + result = compiler.compile(Json("INVALID")); BOOST_CHECK(containsError(result, "JSONError", "Input is not a JSON object.")); /// Use the string interface of StandardCompiler to trigger these result = compile(""); - BOOST_CHECK(containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n* Line 1, Column 1\n A valid JSON document must be either an array or an object value.\n")); + BOOST_CHECK(containsError(result, "JSONError", "parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON")); result = compile("invalid"); - BOOST_CHECK(containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n* Line 1, Column 2\n Extra non-whitespace after JSON value.\n")); + BOOST_CHECK(containsError(result, "JSONError", "parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'i'")); result = compile("\"invalid\""); - BOOST_CHECK(containsError(result, "JSONError", "* Line 1, Column 1\n A valid JSON document must be either an array or an object value.\n")); - BOOST_CHECK(!containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n")); + BOOST_CHECK(containsError(result, "JSONError", "Input is not a JSON object.")); result = compile("{}"); - BOOST_CHECK(!containsError(result, "JSONError", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n")); + BOOST_CHECK(containsError(result, "JSONError", "No input sources specified.")); BOOST_CHECK(!containsAtMostWarnings(result)); } @@ -186,7 +186,7 @@ BOOST_AUTO_TEST_CASE(invalid_language) "sources": { "name": { "content": "abc" } } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Only \"Solidity\", \"Yul\", \"SolidityAST\" or \"EVMAssembly\" is supported as a language.")); } @@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE(valid_language) "language": "Solidity" } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(!containsError(result, "JSONError", "Only \"Solidity\" or \"Yul\" is supported as a language.")); } @@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(no_sources) "language": "Solidity" } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "No input sources specified.")); } @@ -220,7 +220,7 @@ BOOST_AUTO_TEST_CASE(no_sources_empty_object) "sources": {} } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "No input sources specified.")); } @@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE(no_sources_empty_array) "sources": [] } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "\"sources\" is not a JSON object.")); } @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(sources_is_array) "sources": ["aa", "bb"] } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "\"sources\" is not a JSON object.")); } @@ -262,8 +262,8 @@ BOOST_AUTO_TEST_CASE(unexpected_trailing_test) } } )"; - Json::Value result = compile(input); - BOOST_CHECK(containsError(result, "JSONError", "* Line 10, Column 2\n Extra non-whitespace after JSON value.\n")); + Json result = compile(input); + BOOST_CHECK(containsError(result, "JSONError", "parse error at line 10, column 2: syntax error while parsing value - unexpected '}'; expected end of input")); } BOOST_AUTO_TEST_CASE(smoke_test) @@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); } @@ -299,7 +299,7 @@ BOOST_AUTO_TEST_CASE(optimizer_enabled_not_boolean) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "The \"enabled\" setting must be a Boolean.")); } @@ -321,7 +321,7 @@ BOOST_AUTO_TEST_CASE(optimizer_runs_not_a_number) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "The \"runs\" setting must be an unsigned number.")); } @@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(optimizer_runs_not_an_unsigned_number) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "The \"runs\" setting must be an unsigned number.")); } @@ -367,28 +367,28 @@ BOOST_AUTO_TEST_CASE(basic_compilation) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); - BOOST_CHECK(contract["devdoc"].isObject()); + BOOST_CHECK(contract["devdoc"].is_object()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["devdoc"]), R"({"kind":"dev","methods":{},"version":1})"); - BOOST_CHECK(contract["userdoc"].isObject()); + BOOST_CHECK(contract["userdoc"].is_object()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["userdoc"]), R"({"kind":"user","methods":{},"version":1})"); - BOOST_CHECK(contract["evm"].isObject()); + BOOST_CHECK(contract["evm"].is_object()); /// @TODO check evm.methodIdentifiers, legacyAssembly, bytecode, deployedBytecode - BOOST_CHECK(contract["evm"]["bytecode"].isObject()); - BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString()); + BOOST_CHECK(contract["evm"]["bytecode"].is_object()); + BOOST_CHECK(contract["evm"]["bytecode"]["object"].is_string()); BOOST_CHECK_EQUAL( - solidity::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].asString()), + solidity::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].get()), std::string("6080604052348015600e575f80fd5b5060") + (VersionIsRelease ? "3e" : util::toHex(bytes{uint8_t(60 + VersionStringStrict.size())})) + "80601a5f395ff3fe60806040525f80fdfe" ); - BOOST_CHECK(contract["evm"]["assembly"].isString()); - BOOST_CHECK(contract["evm"]["assembly"].asString().find( + BOOST_CHECK(contract["evm"]["assembly"].is_string()); + BOOST_CHECK(contract["evm"]["assembly"].get().find( " /* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x80)\n " "callvalue\n dup1\n " "iszero\n tag_1\n jumpi\n " @@ -400,22 +400,22 @@ BOOST_AUTO_TEST_CASE(basic_compilation) "0x00\n " "dup1\n revert\n\n auxdata: 0xa26469706673582212" ) == 0); - BOOST_CHECK(contract["evm"]["gasEstimates"].isObject()); + BOOST_CHECK(contract["evm"]["gasEstimates"].is_object()); BOOST_CHECK_EQUAL(contract["evm"]["gasEstimates"].size(), 1); - BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"].isObject()); + BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"].is_object()); BOOST_CHECK_EQUAL(contract["evm"]["gasEstimates"]["creation"].size(), 3); - BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["codeDepositCost"].isString()); - BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["executionCost"].isString()); - BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["totalCost"].isString()); + BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["codeDepositCost"].is_string()); + BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["executionCost"].is_string()); + BOOST_CHECK(contract["evm"]["gasEstimates"]["creation"]["totalCost"].is_string()); BOOST_CHECK_EQUAL( - u256(contract["evm"]["gasEstimates"]["creation"]["codeDepositCost"].asString()) + - u256(contract["evm"]["gasEstimates"]["creation"]["executionCost"].asString()), - u256(contract["evm"]["gasEstimates"]["creation"]["totalCost"].asString()) + u256(contract["evm"]["gasEstimates"]["creation"]["codeDepositCost"].get()) + + u256(contract["evm"]["gasEstimates"]["creation"]["executionCost"].get()), + u256(contract["evm"]["gasEstimates"]["creation"]["totalCost"].get()) ); // Lets take the top level `.code` section (the "deployer code"), that should expose most of the features of // the assembly JSON. What we want to check here is Operation, Push, PushTag, PushSub, PushSubSize and Tag. - BOOST_CHECK(contract["evm"]["legacyAssembly"].isObject()); - BOOST_CHECK(contract["evm"]["legacyAssembly"][".code"].isArray()); + BOOST_CHECK(contract["evm"]["legacyAssembly"].is_object()); + BOOST_CHECK(contract["evm"]["legacyAssembly"][".code"].is_array()); BOOST_CHECK_EQUAL( util::jsonCompactPrint(contract["evm"]["legacyAssembly"][".code"]), "[{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"source\":0,\"value\":\"80\"}," @@ -440,11 +440,11 @@ BOOST_AUTO_TEST_CASE(basic_compilation) "{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"source\":0,\"value\":\"0\"}," "{\"begin\":0,\"end\":14,\"name\":\"RETURN\",\"source\":0}]" ); - BOOST_CHECK(contract["metadata"].isString()); - BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].asString())); - BOOST_CHECK(result["sources"].isObject()); - BOOST_CHECK(result["sources"]["fileA"].isObject()); - BOOST_CHECK(result["sources"]["fileA"]["ast"].isObject()); + BOOST_CHECK(contract["metadata"].is_string()); + BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].get())); + BOOST_CHECK(result["sources"].is_object()); + BOOST_CHECK(result["sources"]["fileA"].is_object()); + BOOST_CHECK(result["sources"]["fileA"]["ast"].is_object()); BOOST_CHECK_EQUAL( util::jsonCompactPrint(result["sources"]["fileA"]["ast"]), "{\"absolutePath\":\"fileA\",\"exportedSymbols\":{\"A\":[1]},\"id\":2,\"nodeType\":\"SourceUnit\",\"nodes\":[{\"abstract\":false," @@ -476,14 +476,14 @@ BOOST_AUTO_TEST_CASE(compilation_error) } } )"; - Json::Value result = compile(input); - BOOST_CHECK(result.isMember("errors")); + Json result = compile(input); + BOOST_CHECK(result.contains("errors")); BOOST_CHECK(result["errors"].size() >= 1); for (auto const& error: result["errors"]) { - BOOST_REQUIRE(error.isObject()); - BOOST_REQUIRE(error["message"].isString()); - if (error["message"].asString().find("pre-release compiler") == std::string::npos) + BOOST_REQUIRE(error.is_object()); + BOOST_REQUIRE(error["message"].is_string()); + if (error["message"].get().find("pre-release compiler") == std::string::npos) { BOOST_CHECK_EQUAL( util::jsonCompactPrint(error), @@ -516,11 +516,11 @@ BOOST_AUTO_TEST_CASE(output_selection_explicit) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); } @@ -545,11 +545,11 @@ BOOST_AUTO_TEST_CASE(output_selection_all_contracts) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); } @@ -574,11 +574,11 @@ BOOST_AUTO_TEST_CASE(output_selection_all_files_single_contract) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); } @@ -603,11 +603,11 @@ BOOST_AUTO_TEST_CASE(output_selection_all_files_all_contracts) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); } @@ -632,11 +632,11 @@ BOOST_AUTO_TEST_CASE(output_selection_dependent_contract) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[{\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"); } @@ -664,11 +664,11 @@ BOOST_AUTO_TEST_CASE(output_selection_dependent_contract_with_import) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[{\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"); } @@ -693,11 +693,11 @@ BOOST_AUTO_TEST_CASE(filename_with_colon) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "http://github.com/ethereum/solidity/std/StandardToken.sol", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["abi"].isArray()); + Json contract = getContractResult(result, "http://github.com/ethereum/solidity/std/StandardToken.sol", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); } @@ -725,10 +725,10 @@ BOOST_AUTO_TEST_CASE(library_filename_with_colon) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); expectLinkReferences(contract, {{"git:library.sol", {"L"}}}); } @@ -747,7 +747,7 @@ BOOST_AUTO_TEST_CASE(libraries_invalid_top_level) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "\"libraries\" is not a JSON object.")); } @@ -768,7 +768,7 @@ BOOST_AUTO_TEST_CASE(libraries_invalid_entry) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Library entry is not a JSON object.")); } @@ -791,7 +791,7 @@ BOOST_AUTO_TEST_CASE(libraries_invalid_hex) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Invalid library address (\"0x4200000000000000000000000000000000000xx1\") supplied.")); } @@ -815,7 +815,7 @@ BOOST_AUTO_TEST_CASE(libraries_invalid_length) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Library address is of invalid length.")); } @@ -838,7 +838,7 @@ BOOST_AUTO_TEST_CASE(libraries_missing_hex_prefix) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Library address is not prefixed with \"0x\".")); } @@ -874,9 +874,9 @@ BOOST_AUTO_TEST_CASE(library_linking) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_TEST(containsAtMostWarnings(result)); - Json::Value contractResult = getContractResult(result, "fileA", "A"); + Json contractResult = getContractResult(result, "fileA", "A"); expectLinkReferences(contractResult, {{"library2.sol", {"L2"}}}); } @@ -906,9 +906,9 @@ BOOST_AUTO_TEST_CASE(linking_yul) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_TEST(containsAtMostWarnings(result)); - Json::Value contractResult = getContractResult(result, "fileA", "a"); + Json contractResult = getContractResult(result, "fileA", "a"); expectLinkReferences(contractResult, {}); } @@ -938,9 +938,9 @@ BOOST_AUTO_TEST_CASE(linking_yul_empty_link_reference) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_TEST(containsAtMostWarnings(result)); - Json::Value contractResult = getContractResult(result, "fileA", "a"); + Json contractResult = getContractResult(result, "fileA", "a"); expectLinkReferences(contractResult, {{"", {""}}}); } @@ -970,9 +970,9 @@ BOOST_AUTO_TEST_CASE(linking_yul_no_filename_in_link_reference) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_TEST(containsAtMostWarnings(result)); - Json::Value contractResult = getContractResult(result, "fileA", "a"); + Json contractResult = getContractResult(result, "fileA", "a"); expectLinkReferences(contractResult, {{"", {"L"}}}); } @@ -1002,9 +1002,9 @@ BOOST_AUTO_TEST_CASE(linking_yul_same_library_name_different_files) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_TEST(containsAtMostWarnings(result)); - Json::Value contractResult = getContractResult(result, "fileA", "a"); + Json contractResult = getContractResult(result, "fileA", "a"); expectLinkReferences(contractResult, {{"fileC", {"L"}}}); } @@ -1027,37 +1027,37 @@ BOOST_AUTO_TEST_CASE(evm_version) } )"; }; - Json::Value result; + Json result; result = compile(inputForVersion("\"evmVersion\": \"homestead\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"homestead\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"homestead\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"tangerineWhistle\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"tangerineWhistle\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"tangerineWhistle\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"spuriousDragon\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"spuriousDragon\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"spuriousDragon\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"byzantium\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"byzantium\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"byzantium\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"constantinople\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"constantinople\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"constantinople\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"petersburg\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"petersburg\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"petersburg\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"istanbul\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"istanbul\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"istanbul\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"berlin\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"berlin\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"berlin\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"london\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"london\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"london\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"paris\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"paris\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"paris\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"shanghai\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"shanghai\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"shanghai\"") != std::string::npos); result = compile(inputForVersion("\"evmVersion\": \"cancun\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"cancun\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"cancun\"") != std::string::npos); // test default result = compile(inputForVersion("")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"cancun\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"cancun\"") != std::string::npos); // test invalid result = compile(inputForVersion("\"evmVersion\": \"invalid\",")); - BOOST_CHECK(result["errors"][0]["message"].asString() == "Invalid EVM version requested."); + BOOST_CHECK(result["errors"][0]["message"].get() == "Invalid EVM version requested."); } BOOST_AUTO_TEST_CASE(optimizer_settings_default_disabled) @@ -1077,19 +1077,19 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_default_disabled) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - Json::Value metadata; - BOOST_CHECK(util::jsonParseStrict(contract["metadata"].asString(), metadata)); - - Json::Value const& optimizer = metadata["settings"]["optimizer"]; - BOOST_CHECK(optimizer.isMember("enabled")); - BOOST_CHECK(optimizer["enabled"].asBool() == false); - BOOST_CHECK(!optimizer.isMember("details")); - BOOST_CHECK(optimizer["runs"].asUInt() == 200); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + Json metadata; + BOOST_CHECK(util::jsonParseStrict(contract["metadata"].get(), metadata)); + + Json const& optimizer = metadata["settings"]["optimizer"]; + BOOST_CHECK(optimizer.contains("enabled")); + BOOST_CHECK(optimizer["enabled"].get() == false); + BOOST_CHECK(!optimizer.contains("details")); + BOOST_CHECK(optimizer["runs"].get() == 200); } BOOST_AUTO_TEST_CASE(optimizer_settings_default_enabled) @@ -1110,19 +1110,19 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_default_enabled) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - Json::Value metadata; - BOOST_CHECK(util::jsonParseStrict(contract["metadata"].asString(), metadata)); - - Json::Value const& optimizer = metadata["settings"]["optimizer"]; - BOOST_CHECK(optimizer.isMember("enabled")); - BOOST_CHECK(optimizer["enabled"].asBool() == true); - BOOST_CHECK(!optimizer.isMember("details")); - BOOST_CHECK(optimizer["runs"].asUInt() == 200); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + Json metadata; + BOOST_CHECK(util::jsonParseStrict(contract["metadata"].get(), metadata)); + + Json const& optimizer = metadata["settings"]["optimizer"]; + BOOST_CHECK(optimizer.contains("enabled")); + BOOST_CHECK(optimizer["enabled"].get() == true); + BOOST_CHECK(!optimizer.contains("details")); + BOOST_CHECK(optimizer["runs"].get() == 200); } BOOST_AUTO_TEST_CASE(optimizer_settings_details_exactly_as_default_disabled) @@ -1150,20 +1150,20 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_details_exactly_as_default_disabled) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - Json::Value metadata; - BOOST_CHECK(util::jsonParseStrict(contract["metadata"].asString(), metadata)); - - Json::Value const& optimizer = metadata["settings"]["optimizer"]; - BOOST_CHECK(optimizer.isMember("enabled")); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + Json metadata; + BOOST_CHECK(util::jsonParseStrict(contract["metadata"].get(), metadata)); + + Json const& optimizer = metadata["settings"]["optimizer"]; + BOOST_CHECK(optimizer.contains("enabled")); // enabled is switched to false instead! - BOOST_CHECK(optimizer["enabled"].asBool() == false); - BOOST_CHECK(!optimizer.isMember("details")); - BOOST_CHECK(optimizer["runs"].asUInt() == 200); + BOOST_CHECK(optimizer["enabled"].get() == false); + BOOST_CHECK(!optimizer.contains("details")); + BOOST_CHECK(optimizer["runs"].get() == 200); } BOOST_AUTO_TEST_CASE(optimizer_settings_details_different) @@ -1193,36 +1193,36 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_details_different) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - Json::Value metadata; - BOOST_CHECK(util::jsonParseStrict(contract["metadata"].asString(), metadata)); - - Json::Value const& optimizer = metadata["settings"]["optimizer"]; - BOOST_CHECK(!optimizer.isMember("enabled")); - BOOST_CHECK(optimizer.isMember("details")); - BOOST_CHECK(optimizer["details"]["constantOptimizer"].asBool() == true); - BOOST_CHECK(optimizer["details"]["cse"].asBool() == false); - BOOST_CHECK(optimizer["details"]["deduplicate"].asBool() == true); - BOOST_CHECK(optimizer["details"]["jumpdestRemover"].asBool() == true); - BOOST_CHECK(optimizer["details"]["orderLiterals"].asBool() == false); - BOOST_CHECK(optimizer["details"]["peephole"].asBool() == true); - BOOST_CHECK(optimizer["details"]["yul"].asBool() == true); - BOOST_CHECK(optimizer["details"]["yulDetails"].isObject()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + Json metadata; + BOOST_CHECK(util::jsonParseStrict(contract["metadata"].get(), metadata)); + + Json const& optimizer = metadata["settings"]["optimizer"]; + BOOST_CHECK(!optimizer.contains("enabled")); + BOOST_CHECK(optimizer.contains("details")); + BOOST_CHECK(optimizer["details"]["constantOptimizer"].get() == true); + BOOST_CHECK(optimizer["details"]["cse"].get() == false); + BOOST_CHECK(optimizer["details"]["deduplicate"].get() == true); + BOOST_CHECK(optimizer["details"]["jumpdestRemover"].get() == true); + BOOST_CHECK(optimizer["details"]["orderLiterals"].get() == false); + BOOST_CHECK(optimizer["details"]["peephole"].get() == true); + BOOST_CHECK(optimizer["details"]["yul"].get() == true); + BOOST_CHECK(optimizer["details"]["yulDetails"].is_object()); +// BOOST_CHECK( +// util::convertContainer>(optimizer["details"]["yulDetails"].getMemberNames()) == +// (std::set{"stackAllocation", "optimizerSteps"}) +// ); + BOOST_CHECK(optimizer["details"]["yulDetails"]["stackAllocation"].get() == true); BOOST_CHECK( - util::convertContainer>(optimizer["details"]["yulDetails"].getMemberNames()) == - (std::set{"stackAllocation", "optimizerSteps"}) - ); - BOOST_CHECK(optimizer["details"]["yulDetails"]["stackAllocation"].asBool() == true); - BOOST_CHECK( - optimizer["details"]["yulDetails"]["optimizerSteps"].asString() == + optimizer["details"]["yulDetails"]["optimizerSteps"].get() == OptimiserSettings::DefaultYulOptimiserSteps + ":"s + OptimiserSettings::DefaultYulOptimiserCleanupSteps - ); - BOOST_CHECK_EQUAL(optimizer["details"].getMemberNames().size(), 10); - BOOST_CHECK(optimizer["runs"].asUInt() == 600); + ); + BOOST_CHECK_EQUAL(optimizer["details"].size(), 10); + BOOST_CHECK(optimizer["runs"].get() == 600); } BOOST_AUTO_TEST_CASE(metadata_without_compilation) @@ -1250,12 +1250,12 @@ BOOST_AUTO_TEST_CASE(metadata_without_compilation) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].asString())); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].get())); } @@ -1281,13 +1281,13 @@ BOOST_AUTO_TEST_CASE(license_in_metadata) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - Json::Value metadata; - BOOST_REQUIRE(util::jsonParseStrict(contract["metadata"].asString(), metadata)); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + Json metadata; + BOOST_REQUIRE(util::jsonParseStrict(contract["metadata"].get(), metadata)); BOOST_CHECK_EQUAL(metadata["sources"]["fileA"]["license"], "GPL-3.0"); BOOST_CHECK_EQUAL(metadata["sources"]["fileB"]["license"], "MIT"); BOOST_CHECK_EQUAL(metadata["sources"]["fileC"]["license"], "MIT AND GPL-3.0"); @@ -1317,14 +1317,14 @@ BOOST_AUTO_TEST_CASE(common_pattern) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_CHECK(contract.isObject()); - BOOST_CHECK(contract["metadata"].isString()); - BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].asString())); - BOOST_CHECK(contract["evm"]["bytecode"].isObject()); - BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString()); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_CHECK(contract.is_object()); + BOOST_CHECK(contract["metadata"].is_string()); + BOOST_CHECK(solidity::test::isValidMetadata(contract["metadata"].get())); + BOOST_CHECK(contract["evm"]["bytecode"].is_object()); + BOOST_CHECK(contract["evm"]["bytecode"]["object"].is_string()); } BOOST_AUTO_TEST_CASE(use_stack_optimization) @@ -1375,17 +1375,17 @@ BOOST_AUTO_TEST_CASE(use_stack_optimization) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); BOOST_CHECK(containsAtMostWarnings(result)); - Json::Value contract = getContractResult(result, "fileA", "A"); - BOOST_REQUIRE(contract.isObject()); - BOOST_REQUIRE(contract["evm"]["bytecode"]["object"].isString()); - BOOST_CHECK(contract["evm"]["bytecode"]["object"].asString().length() > 20); + Json contract = getContractResult(result, "fileA", "A"); + BOOST_REQUIRE(contract.is_object()); + BOOST_REQUIRE(contract["evm"]["bytecode"]["object"].is_string()); + BOOST_CHECK(contract["evm"]["bytecode"]["object"].get().length() > 20); // Now disable stack optimizations and UnusedFunctionParameterPruner (p) // results in "stack too deep" @@ -1398,10 +1398,10 @@ BOOST_AUTO_TEST_CASE(use_stack_optimization) parsedInput["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"] = optimiserSteps; result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["errors"].isArray()); + BOOST_REQUIRE(result["errors"].is_array()); BOOST_CHECK(result["errors"][0]["severity"] == "error"); - BOOST_REQUIRE(result["errors"][0]["message"].isString()); - BOOST_CHECK(result["errors"][0]["message"].asString().find("When compiling inline assembly") != std::string::npos); + BOOST_REQUIRE(result["errors"][0]["message"].is_string()); + BOOST_CHECK(result["errors"][0]["message"].get().find("When compiling inline assembly") != std::string::npos); BOOST_CHECK(result["errors"][0]["type"] == "CompilerError"); } @@ -1427,22 +1427,22 @@ BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"]["A"].isObject()); + BOOST_REQUIRE(result["contracts"]["A"].is_object()); BOOST_REQUIRE(result["contracts"]["A"].size() == 1); - BOOST_REQUIRE(result["contracts"]["A"]["C"].isObject()); - BOOST_REQUIRE(result["contracts"]["A"]["C"]["evm"].isObject()); - BOOST_REQUIRE(result["contracts"]["A"]["C"]["evm"]["bytecode"].isObject()); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["contracts"]["A"]["C"].is_object()); + BOOST_REQUIRE(result["contracts"]["A"]["C"]["evm"].is_object()); + BOOST_REQUIRE(result["contracts"]["A"]["C"]["evm"]["bytecode"].is_object()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 1); - BOOST_REQUIRE(result["sources"]["A"].isObject()); + BOOST_REQUIRE(result["sources"]["A"].is_object()); } @@ -1468,22 +1468,22 @@ BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard_colon_source) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"][":A"].isObject()); + BOOST_REQUIRE(result["contracts"][":A"].is_object()); BOOST_REQUIRE(result["contracts"][":A"].size() == 1); - BOOST_REQUIRE(result["contracts"][":A"]["C"].isObject()); - BOOST_REQUIRE(result["contracts"][":A"]["C"]["evm"].isObject()); - BOOST_REQUIRE(result["contracts"][":A"]["C"]["evm"]["bytecode"].isObject()); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["contracts"][":A"]["C"].is_object()); + BOOST_REQUIRE(result["contracts"][":A"]["C"]["evm"].is_object()); + BOOST_REQUIRE(result["contracts"][":A"]["C"]["evm"]["bytecode"].is_object()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 1); - BOOST_REQUIRE(result["sources"][":A"].isObject()); + BOOST_REQUIRE(result["sources"][":A"].is_object()); } BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard_empty_source) @@ -1508,22 +1508,22 @@ BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard_empty_source) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"][""].isObject()); + BOOST_REQUIRE(result["contracts"][""].is_object()); BOOST_REQUIRE(result["contracts"][""].size() == 1); - BOOST_REQUIRE(result["contracts"][""]["C"].isObject()); - BOOST_REQUIRE(result["contracts"][""]["C"]["evm"].isObject()); - BOOST_REQUIRE(result["contracts"][""]["C"]["evm"]["bytecode"].isObject()); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["contracts"][""]["C"].is_object()); + BOOST_REQUIRE(result["contracts"][""]["C"]["evm"].is_object()); + BOOST_REQUIRE(result["contracts"][""]["C"]["evm"]["bytecode"].is_object()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 1); - BOOST_REQUIRE(result["sources"][""].isObject()); + BOOST_REQUIRE(result["sources"][""].is_object()); } BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard_multiple_sources) @@ -1552,23 +1552,23 @@ BOOST_AUTO_TEST_CASE(standard_output_selection_wildcard_multiple_sources) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"]["B"].isObject()); + BOOST_REQUIRE(result["contracts"]["B"].is_object()); BOOST_REQUIRE(result["contracts"]["B"].size() == 1); - BOOST_REQUIRE(result["contracts"]["B"]["D"].isObject()); - BOOST_REQUIRE(result["contracts"]["B"]["D"]["evm"].isObject()); - BOOST_REQUIRE(result["contracts"]["B"]["D"]["evm"]["bytecode"].isObject()); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["contracts"]["B"]["D"].is_object()); + BOOST_REQUIRE(result["contracts"]["B"]["D"]["evm"].is_object()); + BOOST_REQUIRE(result["contracts"]["B"]["D"]["evm"]["bytecode"].is_object()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 2); - BOOST_REQUIRE(result["sources"]["A"].isObject()); - BOOST_REQUIRE(result["sources"]["B"].isObject()); + BOOST_REQUIRE(result["sources"]["A"].is_object()); + BOOST_REQUIRE(result["sources"]["B"].is_object()); } BOOST_AUTO_TEST_CASE(stopAfter_invalid_value) @@ -1588,7 +1588,7 @@ BOOST_AUTO_TEST_CASE(stopAfter_invalid_value) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Invalid value for \"settings.stopAfter\". Only valid value is \"parsing\".")); } @@ -1609,7 +1609,7 @@ BOOST_AUTO_TEST_CASE(stopAfter_invalid_type) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "\"settings.stopAfter\" must be a string.")); } @@ -1630,7 +1630,7 @@ BOOST_AUTO_TEST_CASE(stopAfter_bin_conflict) } } )"; - Json::Value result = compile(input); + Json result = compile(input); BOOST_CHECK(containsError(result, "JSONError", "Requested output selection conflicts with \"settings.stopAfter\".")); } @@ -1650,10 +1650,10 @@ BOOST_AUTO_TEST_CASE(stopAfter_ast_output) } } )"; - Json::Value result = compile(input); - BOOST_CHECK(result["sources"].isObject()); - BOOST_CHECK(result["sources"]["a.sol"].isObject()); - BOOST_CHECK(result["sources"]["a.sol"]["ast"].isObject()); + Json result = compile(input); + BOOST_CHECK(result["sources"].is_object()); + BOOST_CHECK(result["sources"]["a.sol"].is_object()); + BOOST_CHECK(result["sources"]["a.sol"]["ast"].is_object()); } BOOST_AUTO_TEST_CASE(dependency_tracking_of_abstract_contract) @@ -1679,21 +1679,21 @@ BOOST_AUTO_TEST_CASE(dependency_tracking_of_abstract_contract) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"].isObject()); + BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"].is_object()); BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"].size() == 1); - BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"].isObject()); - BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["evm"].isObject()); - BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["ir"].isString()); - BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["evm"]["bytecode"].isObject()); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"].is_object()); + BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["evm"].is_object()); + BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["ir"].is_string()); + BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["evm"]["bytecode"].is_object()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 2); } @@ -1717,20 +1717,20 @@ BOOST_AUTO_TEST_CASE(dependency_tracking_of_abstract_contract_yul) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - BOOST_REQUIRE(result["contracts"].isObject()); + BOOST_REQUIRE(result["contracts"].is_object()); BOOST_REQUIRE(result["contracts"].size() == 1); - BOOST_REQUIRE(result["contracts"]["A.sol"].isObject()); + BOOST_REQUIRE(result["contracts"]["A.sol"].is_object()); BOOST_REQUIRE(result["contracts"]["A.sol"].size() == 1); - BOOST_REQUIRE(result["contracts"]["A.sol"]["C"].isObject()); - BOOST_REQUIRE(result["contracts"]["A.sol"]["C"]["ir"].isString()); + BOOST_REQUIRE(result["contracts"]["A.sol"]["C"].is_object()); + BOOST_REQUIRE(result["contracts"]["A.sol"]["C"]["ir"].is_string()); - const std::string& irCode = result["contracts"]["A.sol"]["C"]["ir"].asString(); + const std::string& irCode = result["contracts"]["A.sol"]["C"]["ir"].get(); // Make sure C and B contracts are deployed BOOST_REQUIRE(irCode.find("object \"C") != std::string::npos); @@ -1742,7 +1742,7 @@ BOOST_AUTO_TEST_CASE(dependency_tracking_of_abstract_contract_yul) BOOST_REQUIRE(irCode.find("object \"D") == std::string::npos); - BOOST_REQUIRE(result["sources"].isObject()); + BOOST_REQUIRE(result["sources"].is_object()); BOOST_REQUIRE(result["sources"].size() == 1); } @@ -1766,13 +1766,13 @@ BOOST_AUTO_TEST_CASE(source_location_of_bare_block) } )"; - Json::Value parsedInput; + Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); solidity::frontend::StandardCompiler compiler; - Json::Value result = compiler.compile(parsedInput); + Json result = compiler.compile(parsedInput); - std::string sourceMap = result["contracts"]["A.sol"]["A"]["evm"]["bytecode"]["sourceMap"].asString(); + std::string sourceMap = result["contracts"]["A.sol"]["A"]["evm"]["bytecode"]["sourceMap"].get(); // Check that the bare block's source location is referenced. std::string sourceRef = diff --git a/test/libsolidity/util/ContractABIUtils.cpp b/test/libsolidity/util/ContractABIUtils.cpp index 641c9107d..fb2f4eb62 100644 --- a/test/libsolidity/util/ContractABIUtils.cpp +++ b/test/libsolidity/util/ContractABIUtils.cpp @@ -140,16 +140,16 @@ std::optional isFixedPoint(std::string const& type) return fixedPointType; } -std::string functionSignatureFromABI(Json::Value const& _functionABI) +std::string functionSignatureFromABI(Json const& _functionABI) { auto inputs = _functionABI["inputs"]; - std::string signature = {_functionABI["name"].asString() + "("}; + std::string signature = {_functionABI["name"].get() + "("}; size_t parameterCount = 0; for (auto const& input: inputs) { parameterCount++; - signature += input["type"].asString(); + signature += input["type"].get(); if (parameterCount < inputs.size()) signature += ","; } @@ -161,11 +161,11 @@ std::string functionSignatureFromABI(Json::Value const& _functionABI) std::optional ContractABIUtils::parametersFromJsonOutputs( ErrorReporter& _errorReporter, - Json::Value const& _contractABI, + Json const& _contractABI, std::string const& _functionSignature ) { - if (!_contractABI) + if (_contractABI.empty()) return std::nullopt; for (auto const& function: _contractABI) @@ -177,7 +177,7 @@ std::optional ContractABIUtils::paramet for (auto const& output: function["outputs"]) { - std::string type = output["type"].asString(); + std::string type = output["type"].get(); ABITypes inplaceTypes; ABITypes dynamicTypes; @@ -209,13 +209,13 @@ std::optional ContractABIUtils::paramet } bool ContractABIUtils::appendTypesFromName( - Json::Value const& _functionOutput, + Json const& _functionOutput, ABITypes& _inplaceTypes, ABITypes& _dynamicTypes, bool _isCompoundType ) { - std::string type = _functionOutput["type"].asString(); + std::string type = _functionOutput["type"].get(); if (isBool(type)) _inplaceTypes.push_back(ABIType{ABIType::Boolean}); else if (isUint(type)) diff --git a/test/libsolidity/util/ContractABIUtils.h b/test/libsolidity/util/ContractABIUtils.h index 209eca423..3f0b1b04e 100644 --- a/test/libsolidity/util/ContractABIUtils.h +++ b/test/libsolidity/util/ContractABIUtils.h @@ -19,8 +19,7 @@ #include #include - -#include +#include namespace solidity::frontend::test { @@ -40,7 +39,7 @@ class ContractABIUtils /// auto-correction during interactive update routine. static std::optional parametersFromJsonOutputs( ErrorReporter& _errorReporter, - Json::Value const& _contractABI, + Json const& _contractABI, std::string const& _functionSignature ); @@ -86,7 +85,7 @@ class ContractABIUtils /// `bytes` -> [`Unsigned`, `Unsigned`, `HexString`] /// ... static bool appendTypesFromName( - Json::Value const& _functionOutput, + Json const& _functionOutput, ABITypes& _inplaceTypes, ABITypes& _dynamicTypes, bool _isCompoundType = false diff --git a/test/libsolidity/util/TestFunctionCall.cpp b/test/libsolidity/util/TestFunctionCall.cpp index dd74d4035..3e0d3e873 100644 --- a/test/libsolidity/util/TestFunctionCall.cpp +++ b/test/libsolidity/util/TestFunctionCall.cpp @@ -413,7 +413,7 @@ void TestFunctionCall::reset() { m_rawBytes = bytes{}; m_failure = true; - m_contractABI = Json::Value{}; + m_contractABI = Json(); m_calledNonExistingFunction = false; } diff --git a/test/libsolidity/util/TestFunctionCall.h b/test/libsolidity/util/TestFunctionCall.h index 724cb8286..9a63262cc 100644 --- a/test/libsolidity/util/TestFunctionCall.h +++ b/test/libsolidity/util/TestFunctionCall.h @@ -23,8 +23,6 @@ #include #include -#include - #include #include #include @@ -99,7 +97,7 @@ class TestFunctionCall void setRawBytes(const bytes _rawBytes) { m_rawBytes = _rawBytes; } void setGasCostExcludingCode(std::string const& _runType, u256 const& _gasCost) { m_gasCostsExcludingCode[_runType] = _gasCost; } void setCodeDepositGasCost(std::string const& _runType, u256 const& _gasCost) { m_codeDepositGasCosts[_runType] = _gasCost; } - void setContractABI(Json::Value _contractABI) { m_contractABI = std::move(_contractABI); } + void setContractABI(Json _contractABI) { m_contractABI = std::move(_contractABI); } void setSideEffects(std::vector _sideEffects) { m_call.actualSideEffects = _sideEffects; } private: @@ -154,7 +152,7 @@ class TestFunctionCall bool m_failure = true; /// JSON object which holds the contract ABI and that is used to set the output formatting /// in the interactive update routine. - Json::Value m_contractABI = Json::Value{}; + Json m_contractABI = Json{}; /// Flags that the test failed because the called function is not known to exist on the contract. bool m_calledNonExistingFunction = false; }; diff --git a/test/libsolutil/JSON.cpp b/test/libsolutil/JSON.cpp index da10c0b3c..91e6771ac 100644 --- a/test/libsolutil/JSON.cpp +++ b/test/libsolutil/JSON.cpp @@ -34,50 +34,50 @@ BOOST_AUTO_TEST_SUITE(JsonTest, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_CASE(json_types) { - auto check = [](Json::Value value, std::string const& expectation) { + auto check = [](Json value, std::string const& expectation) { BOOST_CHECK(jsonCompactPrint(value) == expectation); }; - Json::Value value; + Json value; BOOST_CHECK(value.empty()); value = {}; BOOST_CHECK(value.empty()); - value = Json::Value(); + value = Json(); BOOST_CHECK(value.empty()); - value = Json::nullValue; + value = Json(); BOOST_CHECK(value.empty()); check(value, "null"); check({}, "null"); - check(Json::Value(), "null"); - check(Json::nullValue, "null"); - check(Json::objectValue, "{}"); - check(Json::arrayValue, "[]"); - check(Json::UInt(1), "1"); - check(Json::UInt(-1), "4294967295"); - check(Json::UInt64(1), "1"); - check(Json::UInt64(-1), "18446744073709551615"); - check(Json::LargestUInt(1), "1"); - check(Json::LargestUInt(-1), "18446744073709551615"); - check(Json::LargestUInt(0xffffffff), "4294967295"); - check(Json::Value("test"), "\"test\""); + check(Json(), "null"); + check(Json(), "null"); + check(Json::object(), "{}"); + check(Json::array(), "[]"); + check(1, "1"); + check(static_cast(-1), "4294967295"); + check(1, "1"); + check(static_cast(-1), "18446744073709551615"); + check(1, "1"); + check(static_cast(-1), "18446744073709551615"); + check(0xffffffff, "4294967295"); + check(Json("test"), "\"test\""); check("test", "\"test\""); check(true, "true"); - value = Json::objectValue; + value = Json::object(); value["key"] = "value"; check(value, "{\"key\":\"value\"}"); - value = Json::arrayValue; - value.append(1); - value.append(2); + value = Json::array(); + value.push_back(1); + value.push_back(2); check(value, "[1,2]"); } BOOST_AUTO_TEST_CASE(json_pretty_print) { - Json::Value json; - Json::Value jsonChild; + Json json; + Json jsonChild; jsonChild["3.1"] = "3.1"; jsonChild["3.2"] = 2; @@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE(json_pretty_print) json["2"] = "2"; json["3"] = jsonChild; json["4"] = "ऑ ऒ ओ औ क ख"; - json["5"] = "\xff"; + json["5"] = "\\xff\\xfe"; BOOST_CHECK( "{\n" @@ -97,14 +97,14 @@ BOOST_AUTO_TEST_CASE(json_pretty_print) " \"3.2\": 2\n" " },\n" " \"4\": \"\\u0911 \\u0912 \\u0913 \\u0914 \\u0915 \\u0916\",\n" - " \"5\": \"\\ufffd\"\n" + " \"5\": \"\\\\xff\\\\xfe\"\n" "}" == jsonPrettyPrint(json)); } BOOST_AUTO_TEST_CASE(json_compact_print) { - Json::Value json; - Json::Value jsonChild; + Json json; + Json jsonChild; jsonChild["3.1"] = "3.1"; jsonChild["3.2"] = 2; @@ -112,9 +112,10 @@ BOOST_AUTO_TEST_CASE(json_compact_print) json["2"] = "2"; json["3"] = jsonChild; json["4"] = "ऑ ऒ ओ औ क ख"; - json["5"] = "\xff"; + json["5"] = "\x10"; + json["6"] = "\u4e2d"; - BOOST_CHECK("{\"1\":1,\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":2},\"4\":\"\\u0911 \\u0912 \\u0913 \\u0914 \\u0915 \\u0916\",\"5\":\"\\ufffd\"}" == jsonCompactPrint(json)); + BOOST_CHECK(R"({"1":1,"2":"2","3":{"3.1":"3.1","3.2":2},"4":"\u0911 \u0912 \u0913 \u0914 \u0915 \u0916","5":"\u0010","6":"\u4e2d"})" == jsonCompactPrint(json)); } BOOST_AUTO_TEST_CASE(parse_json_strict) @@ -122,7 +123,7 @@ BOOST_AUTO_TEST_CASE(parse_json_strict) // In this test we check conformance against JSON.parse (https://tc39.es/ecma262/multipage/structured-data.html#sec-json.parse) // and ECMA-404 (https://www.ecma-international.org/publications-and-standards/standards/ecma-404/) - Json::Value json; + Json json; std::string errors; // Just parse a valid json input @@ -135,179 +136,202 @@ BOOST_AUTO_TEST_CASE(parse_json_strict) // Trailing garbage is not allowed in ECMA-262 BOOST_CHECK(!jsonParseStrict("{\"1\":2,\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":3}}}}}}}}}}", json, &errors)); - // Comments are not allowed in ECMA-262 - // ... but JSONCPP allows them - BOOST_CHECK(jsonParseStrict( - "{\"1\":3, // awesome comment\n\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":5}}", json, &errors - )); - BOOST_CHECK(json["1"] == 3); - BOOST_CHECK(json["2"] == "2"); - BOOST_CHECK(json["3"]["3.1"] == "3.1"); - BOOST_CHECK(json["3"]["3.2"] == 5); - // According to ECMA-404 object, array, number, string, true, false, null are allowed // ... but JSONCPP disallows value types BOOST_CHECK(jsonParseStrict("[]", json, &errors)); - BOOST_CHECK(json.isArray()); + BOOST_CHECK(json.is_array()); BOOST_CHECK(jsonParseStrict("{}", json, &errors)); - BOOST_CHECK(json.isObject()); - BOOST_CHECK(!jsonParseStrict("1", json, &errors)); - // BOOST_CHECK(json.isNumeric()); - BOOST_CHECK(!jsonParseStrict("\"hello\"", json, &errors)); - // BOOST_CHECK(json.isString()); - BOOST_CHECK(!jsonParseStrict("true", json, &errors)); - // BOOST_CHECK(json.isBool()); - BOOST_CHECK(!jsonParseStrict("null", json, &errors)); - // BOOST_CHECK(json.isNull()); + BOOST_CHECK(json.is_object()); + BOOST_CHECK(jsonParseStrict("1", json, &errors)); + BOOST_CHECK(json.is_number()); + BOOST_CHECK(jsonParseStrict("\"hello\"", json, &errors)); + BOOST_CHECK(json.is_string()); + BOOST_CHECK(jsonParseStrict("true", json, &errors)); + BOOST_CHECK(json.is_boolean()); + BOOST_CHECK(jsonParseStrict("null", json, &errors)); + BOOST_CHECK(json.is_null()); // Single quotes are also disallowed by ECMA-404 BOOST_CHECK(!jsonParseStrict("'hello'", json, &errors)); - // BOOST_CHECK(json.isString()); + // BOOST_CHECK(json.is_string()); // Only string keys in objects are allowed in ECMA-404 BOOST_CHECK(!jsonParseStrict("{ 42: \"hello\" }", json, &errors)); // According to ECMA-404 hex escape sequences are not allowed, only unicode (\uNNNN) and // a few control characters (\b, \f, \n, \r, \t) - // - // More lenient parsers allow hex escapes as long as they translate to a valid UTF-8 encoding. - // - // ... but JSONCPP allows any hex escapes - BOOST_CHECK(jsonParseStrict("[ \"\x80\xec\x80\" ]", json, &errors)); - BOOST_CHECK(json.isArray()); - BOOST_CHECK(json[0] == "\x80\xec\x80"); - - // This would be valid more lenient parsers. + BOOST_CHECK(jsonParseStrict("[ \"\xF0\x9F\x98\x8A\" ]", json, &errors)); - BOOST_CHECK(json.isArray()); + BOOST_CHECK(json.is_array()); BOOST_CHECK(json[0] == "😊"); + BOOST_CHECK(json[0] == "\xF0\x9F\x98\x8A"); } BOOST_AUTO_TEST_CASE(json_isOfType) { - Json::Value json; + Json json; json["float"] = 3.1f; json["double"] = 3.1; json["int"] = 2; - json["int64"] = Json::Int64{0x4000000000000000}; + json["int64"] = 0x4000000000000000; json["string"] = "Hello World!"; BOOST_CHECK(isOfType(json["float"])); BOOST_CHECK(isOfType(json["double"])); BOOST_CHECK(isOfType(json["int"])); - BOOST_CHECK(isOfType(json["int"])); - BOOST_CHECK(isOfType(json["int"])); - BOOST_CHECK(isOfType(json["int"])); - BOOST_CHECK(isOfType(json["int64"])); - BOOST_CHECK(isOfType(json["int64"])); + BOOST_CHECK(isOfType(json["int"])); + BOOST_CHECK(isOfType(json["int"])); + BOOST_CHECK(isOfType(json["int"])); + BOOST_CHECK(isOfType(json["int"])); + BOOST_CHECK(isOfType(json["int64"])); + BOOST_CHECK(isOfType(json["int64"])); + BOOST_CHECK(isOfType(json["int64"])); BOOST_CHECK(isOfType(json["string"])); - BOOST_CHECK(!isOfType(json["int64"])); + BOOST_CHECK(!isOfType(json["int64"])); BOOST_CHECK(!isOfType(json["double"])); BOOST_CHECK(!isOfType(json["string"])); BOOST_CHECK(!isOfType(json["string"])); - BOOST_CHECK(!isOfType(json["string"])); - BOOST_CHECK(!isOfType(json["string"])); - BOOST_CHECK(!isOfType(json["string"])); - BOOST_CHECK(!isOfType(json["string"])); + BOOST_CHECK(!isOfType(json["string"])); + BOOST_CHECK(!isOfType(json["string"])); + BOOST_CHECK(!isOfType(json["string"])); + BOOST_CHECK(!isOfType(json["string"])); } BOOST_AUTO_TEST_CASE(json_isisOfTypeIfExists) { - Json::Value json; + Json json; json["float"] = 3.1f; json["double"] = 3.1; json["int"] = 2; - json["int64"] = Json::Int64{0x4000000000000000}; + json["uint"] = 2u; + json["int64"] = 0x4000000000000000; + json["uint64"] = 0x4000000000000000u; json["string"] = "Hello World!"; BOOST_CHECK(isOfTypeIfExists(json, "float")); BOOST_CHECK(isOfTypeIfExists(json, "double")); BOOST_CHECK(isOfTypeIfExists(json, "int")); - BOOST_CHECK(isOfTypeIfExists(json, "int")); - BOOST_CHECK(isOfTypeIfExists(json, "int")); - BOOST_CHECK(isOfTypeIfExists(json, "int")); - BOOST_CHECK(isOfTypeIfExists(json, "int64")); - BOOST_CHECK(isOfTypeIfExists(json, "int64")); + BOOST_CHECK(isOfTypeIfExists(json, "int")); + BOOST_CHECK(isOfTypeIfExists(json, "uint")); + BOOST_CHECK(isOfTypeIfExists(json, "int")); + BOOST_CHECK(isOfTypeIfExists(json, "int64")); + BOOST_CHECK(isOfTypeIfExists(json, "uint64")); BOOST_CHECK(isOfTypeIfExists(json, "string")); - BOOST_CHECK(!isOfTypeIfExists(json, "int64")); + BOOST_CHECK(!isOfTypeIfExists(json, "int64")); BOOST_CHECK(!isOfTypeIfExists(json, "double")); BOOST_CHECK(!isOfTypeIfExists(json, "string")); BOOST_CHECK(!isOfTypeIfExists(json, "string")); - BOOST_CHECK(!isOfTypeIfExists(json, "string")); - BOOST_CHECK(!isOfTypeIfExists(json, "string")); - BOOST_CHECK(!isOfTypeIfExists(json, "string")); - BOOST_CHECK(!isOfTypeIfExists(json, "string")); - BOOST_CHECK(isOfTypeIfExists(json, "NOT_EXISTING")); + BOOST_CHECK(!isOfTypeIfExists(json, "string")); + BOOST_CHECK(!isOfTypeIfExists(json, "string")); + BOOST_CHECK(!isOfTypeIfExists(json, "string")); + BOOST_CHECK(!isOfTypeIfExists(json, "string")); + BOOST_CHECK(isOfTypeIfExists(json, "NOT_EXISTING")); } BOOST_AUTO_TEST_CASE(json_getOrDefault) { - Json::Value json; + Json json; json["float"] = 3.1f; json["double"] = 3.1; json["int"] = 2; - json["int64"] = Json::Int64{0x4000000000000000}; - json["uint64"] = Json::UInt64{0x5000000000000000}; + json["int64"] = 0x4000000000000000; + json["uint64"] = 0x5000000000000000; json["string"] = "Hello World!"; - BOOST_CHECK(getOrDefault(json["float"]) == 3.1f); - BOOST_CHECK(getOrDefault(json["float"], -1.1f) == 3.1f); - BOOST_CHECK(getOrDefault(json["no_float"], -1.1f) == -1.1f); - BOOST_CHECK(getOrDefault(json["double"]) == 3.1); - BOOST_CHECK(getOrDefault(json["double"], -1) == 3.1); - BOOST_CHECK(getOrDefault(json["no_double"], -1.1) == -1.1); - BOOST_CHECK(getOrDefault(json["int"]) == 2); - BOOST_CHECK(getOrDefault(json["int"], -1) == 2); - BOOST_CHECK(getOrDefault(json["no_int"], -1) == -1); - BOOST_CHECK(getOrDefault(json["int"]) == 2); - BOOST_CHECK(getOrDefault(json["int"], -1) == 2); - BOOST_CHECK(getOrDefault(json["no_int"], -1) == -1); - BOOST_CHECK(getOrDefault(json["int"]) == 2); - BOOST_CHECK(getOrDefault(json["int"], 1) == 2); - BOOST_CHECK(getOrDefault(json["no_int"], 1) == 1); - BOOST_CHECK(getOrDefault(json["int"]) == 2); - BOOST_CHECK(getOrDefault(json["int"], -1) == 2); - BOOST_CHECK(getOrDefault(json["no_int"], -1) == -1); - BOOST_CHECK(getOrDefault(json["int64"]) == 0x4000000000000000); - BOOST_CHECK(getOrDefault(json["int64"], -1) == 0x4000000000000000); - BOOST_CHECK(getOrDefault(json["no_int64"], -1) == -1); - BOOST_CHECK(getOrDefault(json["int64"]) == 0x4000000000000000); - BOOST_CHECK(getOrDefault(json["int64"], 1) == 0x4000000000000000); - BOOST_CHECK(getOrDefault(json["no_int64"], 1) == 1); - BOOST_CHECK(getOrDefault(json["uint64"]) == 0x5000000000000000); - BOOST_CHECK(getOrDefault(json["uint64"], 1) == 0x5000000000000000); - BOOST_CHECK(getOrDefault(json["no_uint64"], 1) == 1); - BOOST_CHECK(getOrDefault(json["string"], "ERROR") == "Hello World!"); - BOOST_CHECK(getOrDefault(json["no_string"]).empty()); - BOOST_CHECK(getOrDefault(json["no_string"], "ERROR") == "ERROR"); + BOOST_CHECK(getOrDefault(json, "float") == 3.1f); + BOOST_CHECK(getOrDefault(json, "float", -1.1f) == 3.1f); + BOOST_CHECK(getOrDefault(json, "no_float", -1.1f) == -1.1f); + BOOST_CHECK(getOrDefault(json, "double") == 3.1); + BOOST_CHECK(getOrDefault(json, "double", -1) == 3.1); + BOOST_CHECK(getOrDefault(json, "no_double", -1.1) == -1.1); + BOOST_CHECK(getOrDefault(json, "int") == 2); + BOOST_CHECK(getOrDefault(json, "int", -1) == 2); + BOOST_CHECK(getOrDefault(json, "no_int", -1) == -1); + BOOST_CHECK(getOrDefault(json, "int") == 2); + BOOST_CHECK(getOrDefault(json, "int", -1) == 2); + BOOST_CHECK(getOrDefault(json, "no_int", -1) == -1); + BOOST_CHECK(getOrDefault(json, "int") == 2); + BOOST_CHECK(getOrDefault(json, "int", 1) == 2); + BOOST_CHECK(getOrDefault(json, "no_int", 1) == 1); + BOOST_CHECK(getOrDefault(json, "int") == 2); + BOOST_CHECK(getOrDefault(json, "int", -1) == 2); + BOOST_CHECK(getOrDefault(json, "no_int", -1) == -1); + BOOST_CHECK(getOrDefault(json, "int64") == 0x4000000000000000); + BOOST_CHECK(getOrDefault(json, "int64", -1) == 0x4000000000000000); + BOOST_CHECK(getOrDefault(json, "no_int64", -1) == -1); + BOOST_CHECK(getOrDefault(json, "int64") == 0x4000000000000000); + BOOST_CHECK(getOrDefault(json, "int64", 1) == 0x4000000000000000); + BOOST_CHECK(getOrDefault(json, "no_int64", 1) == 1); + BOOST_CHECK(getOrDefault(json, "uint64") == 0x5000000000000000); + BOOST_CHECK(getOrDefault(json, "uint64", 1) == 0x5000000000000000); + BOOST_CHECK(getOrDefault(json, "no_uint64", 1) == 1); + BOOST_CHECK(getOrDefault(json, "string", "ERROR") == "Hello World!"); + BOOST_CHECK(getOrDefault(json, "no_string").empty()); + BOOST_CHECK(getOrDefault(json, "no_string", "ERROR") == "ERROR"); } BOOST_AUTO_TEST_CASE(json_get) { - Json::Value json; + Json json; json["float"] = 3.1f; json["double"] = 3.1; json["int"] = 2; - json["int64"] = Json::Int64{0x4000000000000000}; - json["uint64"] = Json::UInt64{0x5000000000000000}; + json["int64"] = 0x4000000000000000; + json["uint64"] = 0x5000000000000000; json["string"] = "Hello World!"; BOOST_CHECK(get(json["float"]) == 3.1f); BOOST_CHECK(get(json["double"]) == 3.1); BOOST_CHECK(get(json["int"]) == 2); - BOOST_CHECK(get(json["int"]) == 2); - BOOST_CHECK(get(json["int"]) == 2); - BOOST_CHECK(get(json["int"]) == 2); - BOOST_CHECK(get(json["int64"]) == 0x4000000000000000); - BOOST_CHECK(get(json["int64"]) == 0x4000000000000000); - BOOST_CHECK(get(json["uint64"]) == 0x5000000000000000); + BOOST_CHECK(get(json["int"]) == 2); + BOOST_CHECK(get(json["int"]) == 2); + BOOST_CHECK(get(json["int"]) == 2); + BOOST_CHECK(get(json["int64"]) == 0x4000000000000000); + BOOST_CHECK(get(json["int64"]) == 0x4000000000000000); + BOOST_CHECK(get(json["uint64"]) == 0x5000000000000000); BOOST_CHECK(get(json["string"]) == "Hello World!"); } +template +void json_test_int_range() +{ + Json max = {{"v", std::numeric_limits::max()}}; + Json min = {{"v", std::numeric_limits::min()}}; + Json overflow = {{"v", static_cast(std::numeric_limits::max()) + 1}}; + Json underflow = {{"v", static_cast(std::numeric_limits::min()) - 1}}; + BOOST_CHECK(getOrDefault(max, "v", 0) == std::numeric_limits::max()); + BOOST_CHECK(getOrDefault(min, "v", 0) == std::numeric_limits::min()); + BOOST_CHECK(getOrDefault(overflow, "v", 0) == 0); + BOOST_CHECK(getOrDefault(underflow, "v", 0) == 0); + BOOST_CHECK(get(max["v"]) == std::numeric_limits::max()); + BOOST_CHECK(get(min["v"]) == std::numeric_limits::min()); + BOOST_CHECK_THROW(get(overflow["v"]), InvalidType); + BOOST_CHECK_THROW(get(underflow["v"]), InvalidType); +} + +BOOST_AUTO_TEST_CASE(json_range_checks) +{ + json_test_int_range(); + json_test_int_range(); + json_test_int_range(); + json_test_int_range(); + json_test_int_range(); + json_test_int_range(); + + Json overflow = {{"v", static_cast(std::numeric_limits::max()) * 2}}; + Json underflow = {{"v", static_cast(std::numeric_limits::min()) / 2}}; + BOOST_CHECK(getOrDefault({{"v", std::numeric_limits::max()}}, "v", 0) == std::numeric_limits::max()); + BOOST_CHECK(getOrDefault({{"v", std::numeric_limits::min()}}, "v", 0) == std::numeric_limits::min()); + BOOST_CHECK(getOrDefault(overflow, "v", 0) == 0); + BOOST_CHECK(getOrDefault(underflow, "v", 0) == 0); + BOOST_CHECK_THROW(get(overflow["v"]), InvalidType); + BOOST_CHECK_THROW(get(underflow["v"]), InvalidType); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 73ebb2c54..b3b93cb3a 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -1180,15 +1180,20 @@ BOOST_AUTO_TEST_CASE(standard_json_include_paths) OptionsReaderAndMessages result = runCLI(commandLine, standardJsonInput); - Json::Value parsedStdout; + Json parsedStdout; std::string jsonParsingErrors; BOOST_TEST(util::jsonParseStrict(result.stdoutContent, parsedStdout, &jsonParsingErrors)); BOOST_TEST(jsonParsingErrors == ""); - for (Json::Value const& errorDict: parsedStdout["errors"]) + for (Json const& errorDict: parsedStdout["errors"]) // The error list might contain pre-release compiler warning BOOST_TEST(errorDict["severity"] != "error"); + // we might be able to use ranges again, but the nlohmann::json support is not yet fully there. + // (parsedStdout["sources"].items() | ranges::views::keys | ranges::to) + std::set sources; + for (auto const& [key, _]: parsedStdout["sources"].items()) + sources.insert(key); BOOST_TEST( - (parsedStdout["sources"].getMemberNames() | ranges::to) == + sources == (expectedSources | ranges::views::keys | ranges::to) + std::set{"main.sol"} ); diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index 1bb04bf66..c7e94f40b 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -58,13 +58,13 @@ void FuzzerUtil::testCompilerJsonInterface(string const& _input, bool _optimize, if (!_quiet) cout << "Testing compiler " << (_optimize ? "with" : "without") << " optimizer." << endl; - Json::Value config = Json::objectValue; + Json config; config["language"] = "Solidity"; - config["sources"] = Json::objectValue; - config["sources"][""] = Json::objectValue; + config["sources"] = Json::object(); + config["sources"][""] = Json::object(); config["sources"][""]["content"] = _input; - config["settings"] = Json::objectValue; - config["settings"]["optimizer"] = Json::objectValue; + config["settings"] = Json::object(); + config["settings"]["optimizer"] = Json::object(); config["settings"]["optimizer"]["enabled"] = _optimize; config["settings"]["optimizer"]["runs"] = static_cast(OptimiserSettings{}.expectedExecutionsPerDeployment); config["settings"]["evmVersion"] = "berlin"; @@ -155,23 +155,23 @@ void FuzzerUtil::runCompiler(string const& _input, bool _quiet) // This should be safe given the above copies the output. solidity_reset(); - Json::Value output; + Json output; if (!jsonParseStrict(outputString, output)) { string msg{"Compiler produced invalid JSON output."}; cout << msg << endl; BOOST_THROW_EXCEPTION(std::runtime_error(std::move(msg))); } - if (output.isMember("errors")) + if (output.contains("errors")) for (auto const& error: output["errors"]) { - string invalid = findAnyOf(error["type"].asString(), vector{ + string invalid = findAnyOf(error["type"].get(), vector{ "Exception", "InternalCompilerError" }); if (!invalid.empty()) { - string msg = "Invalid error: \"" + error["type"].asString() + "\""; + string msg = "Invalid error: \"" + error["type"].get() + "\""; cout << msg << endl; BOOST_THROW_EXCEPTION(std::runtime_error(std::move(msg))); } diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp index 341470908..9d98190dd 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp @@ -57,7 +57,7 @@ optional SolidityCompilationFramework::compileContract() else contractName = m_compilerInput.contractName; evmasm::LinkerObject obj = m_compiler.object(contractName); - Json::Value methodIdentifiers = m_compiler.interfaceSymbols(contractName)["methods"]; + Json methodIdentifiers = m_compiler.interfaceSymbols(contractName)["methods"]; return CompilerOutput{obj.bytecode, methodIdentifiers}; } } @@ -164,10 +164,10 @@ evmc::Result EvmoneUtility::compileDeployAndExecute(string _fuzzIsabelle) // isabelle test entry point. At the moment, we are sure that the // entry point is the second method in the contract (hence the ++) // but not its name. - methodName = (++cOutput->methodIdentifiersInContract.begin())->asString() + + methodName = (++cOutput->methodIdentifiersInContract.begin())->get() + _fuzzIsabelle.substr(2, _fuzzIsabelle.size()); else - methodName = cOutput->methodIdentifiersInContract[m_methodName].asString(); + methodName = cOutput->methodIdentifiersInContract[m_methodName].get(); return deployAndExecute( cOutput->byteCode, diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.h b/test/tools/ossfuzz/SolidityEvmoneInterface.h index ea684ea72..00582c681 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.h +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.h @@ -35,7 +35,7 @@ struct CompilerOutput /// EVM bytecode returned by compiler solidity::bytes byteCode; /// Method identifiers in a contract - Json::Value methodIdentifiersInContract; + Json methodIdentifiersInContract; }; struct CompilerInput @@ -89,7 +89,7 @@ class SolidityCompilationFramework m_compilerInput.libraryAddresses = std::move(_libraryAddresses); } /// @returns method identifiers in contract called @param _contractName. - Json::Value methodIdentifiers(std::string const& _contractName) + Json methodIdentifiers(std::string const& _contractName) { return m_compiler.interfaceSymbols(_contractName)["methods"]; } diff --git a/test/yulPhaser/Program.cpp b/test/yulPhaser/Program.cpp index a54bf09af..018de32ee 100644 --- a/test/yulPhaser/Program.cpp +++ b/test/yulPhaser/Program.cpp @@ -380,7 +380,7 @@ BOOST_AUTO_TEST_CASE(toJson) CharStream sourceStream(sourceCode, current_test_case().p_name); Program program = get(Program::load(sourceStream)); - Json::Value parsingResult; + Json parsingResult; std::string errors; BOOST_TEST(jsonParseStrict(program.toJson(), parsingResult, &errors)); BOOST_TEST(errors.empty()); diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 3089591ed..f24f5e03f 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -111,7 +111,7 @@ ostream& phaser::operator<<(ostream& _stream, Program const& _program) string Program::toJson() const { - Json::Value serializedAst = AsmJsonConverter(0)(*m_ast); + Json serializedAst = AsmJsonConverter(0)(*m_ast); return jsonPrettyPrint(removeNullMembers(std::move(serializedAst))); } From dd07096a98e48430143596ed0d6acab9f7282157 Mon Sep 17 00:00:00 2001 From: clonker Date: Thu, 2 May 2024 16:12:46 +0200 Subject: [PATCH 0095/1340] StaticAnalyzer: Only raise a compile time error for division and modulo by zero when it's between literals. --- Changelog.md | 1 + libsolidity/analysis/StaticAnalyzer.cpp | 3 ++- .../literalOperations/division_by_zero_complex_compound.sol | 5 +++++ .../literalOperations/division_by_zero_compound.sol | 5 +++++ .../literalOperations/division_by_zero_nonliteral.sol | 4 ++++ .../literalOperations/mod_zero_complex_compound.sol | 5 +++++ .../syntaxTests/literalOperations/mod_zero_compound.sol | 5 +++++ .../syntaxTests/literalOperations/mod_zero_nonliteral.sol | 4 ++++ 8 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/literalOperations/division_by_zero_complex_compound.sol create mode 100644 test/libsolidity/syntaxTests/literalOperations/division_by_zero_compound.sol create mode 100644 test/libsolidity/syntaxTests/literalOperations/division_by_zero_nonliteral.sol create mode 100644 test/libsolidity/syntaxTests/literalOperations/mod_zero_complex_compound.sol create mode 100644 test/libsolidity/syntaxTests/literalOperations/mod_zero_compound.sol create mode 100644 test/libsolidity/syntaxTests/literalOperations/mod_zero_nonliteral.sol diff --git a/Changelog.md b/Changelog.md index c118e9f24..16e42aff2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Bugfixes: * SMTChecker: Fix internal error when using an empty tuple in a conditional operator. * SMTChecker: Fix internal error when using bitwise operators with an array element as argument. * Standard JSON Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``optimizerSteps`` sequence. + * StaticAnalyzer: Only raise a compile time error for division and modulo by zero when it's between literals. * Yul Optimizer: Fix the order of assignments generated by ``SSATransform`` being dependent on AST IDs, sometimes resulting in different (but equivalent) bytecode when unrelated files were added to the compilation pipeline. diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp index 10c2c922c..563295e23 100644 --- a/libsolidity/analysis/StaticAnalyzer.cpp +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -298,7 +298,8 @@ bool StaticAnalyzer::visit(BinaryOperation const& _operation) { if ( *_operation.rightExpression().annotation().isPure && - (_operation.getOperator() == Token::Div || _operation.getOperator() == Token::Mod) + (_operation.getOperator() == Token::Div || _operation.getOperator() == Token::Mod) && + ConstantEvaluator::evaluate(m_errorReporter, _operation.leftExpression()) ) if (auto rhs = ConstantEvaluator::evaluate(m_errorReporter, _operation.rightExpression())) if (rhs->value == 0) diff --git a/test/libsolidity/syntaxTests/literalOperations/division_by_zero_complex_compound.sol b/test/libsolidity/syntaxTests/literalOperations/division_by_zero_complex_compound.sol new file mode 100644 index 000000000..c3a51cc29 --- /dev/null +++ b/test/libsolidity/syntaxTests/literalOperations/division_by_zero_complex_compound.sol @@ -0,0 +1,5 @@ +contract A { + uint a; + constructor() { a /= (((2)*2)%4); } +} +// ---- diff --git a/test/libsolidity/syntaxTests/literalOperations/division_by_zero_compound.sol b/test/libsolidity/syntaxTests/literalOperations/division_by_zero_compound.sol new file mode 100644 index 000000000..9404f0ce9 --- /dev/null +++ b/test/libsolidity/syntaxTests/literalOperations/division_by_zero_compound.sol @@ -0,0 +1,5 @@ +contract A { + uint a = 5; + constructor() { a /= uint(0); } +} +// ---- diff --git a/test/libsolidity/syntaxTests/literalOperations/division_by_zero_nonliteral.sol b/test/libsolidity/syntaxTests/literalOperations/division_by_zero_nonliteral.sol new file mode 100644 index 000000000..66540568f --- /dev/null +++ b/test/libsolidity/syntaxTests/literalOperations/division_by_zero_nonliteral.sol @@ -0,0 +1,4 @@ +contract A { + constructor() { uint a; a / 0; } +} +// ---- diff --git a/test/libsolidity/syntaxTests/literalOperations/mod_zero_complex_compound.sol b/test/libsolidity/syntaxTests/literalOperations/mod_zero_complex_compound.sol new file mode 100644 index 000000000..1e9f1e1fa --- /dev/null +++ b/test/libsolidity/syntaxTests/literalOperations/mod_zero_complex_compound.sol @@ -0,0 +1,5 @@ +contract A { + uint a = 5; + constructor() { a %= uint(((2)*2)%4); } +} +// ---- diff --git a/test/libsolidity/syntaxTests/literalOperations/mod_zero_compound.sol b/test/libsolidity/syntaxTests/literalOperations/mod_zero_compound.sol new file mode 100644 index 000000000..2fb6e1df0 --- /dev/null +++ b/test/libsolidity/syntaxTests/literalOperations/mod_zero_compound.sol @@ -0,0 +1,5 @@ +contract A { + uint a; + constructor() { a = 5; a %= 0; } +} +// ---- diff --git a/test/libsolidity/syntaxTests/literalOperations/mod_zero_nonliteral.sol b/test/libsolidity/syntaxTests/literalOperations/mod_zero_nonliteral.sol new file mode 100644 index 000000000..0722a096f --- /dev/null +++ b/test/libsolidity/syntaxTests/literalOperations/mod_zero_nonliteral.sol @@ -0,0 +1,4 @@ +contract A { + constructor() { uint a; a % 0; } +} +// ---- From cb783989c78f67dca4208fa269544ab720846143 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Tue, 7 May 2024 16:37:00 +0200 Subject: [PATCH 0096/1340] Correct changelog. --- Changelog.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index 193f5bb46..59284486b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -17,6 +17,10 @@ Bugfixes: * Yul Optimizer: Fix the order of assignments generated by ``SSATransform`` being dependent on AST IDs, sometimes resulting in different (but equivalent) bytecode when unrelated files were added to the compilation pipeline. +Build System: +* Replace internal JSON library jsoncpp with nlohmann::json. + + ### 0.8.25 (2024-03-14) Compiler Features: @@ -33,9 +37,6 @@ Bugfixes: * SMTChecker: Fix internal error caused by not respecting the sign of an integer type when constructing zero-value SMT expressions. * SMTChecker: Run Eldarica only when explicitly requested with `--model-checker-solvers eld`, even when it is present on the system. -Build System: - * Replace internal JSON library jsoncpp with nlohmann::json. - ### 0.8.24 (2024-01-25) Language Features: From 6cc75270d996e1af22c9318a29cff64bed5b6191 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Tue, 7 May 2024 17:08:24 +0200 Subject: [PATCH 0097/1340] Mark embedding options as advanced. --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e2332b92..91c1056ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,9 @@ option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser ste option(USE_SYSTEM_LIBRARIES "Use system libraries" OFF) option(ONLY_BUILD_SOLIDITY_LIBRARIES "Only build solidity libraries" OFF) option(STRICT_NLOHMANN_JSON_VERSION "Strictly check installed nlohmann json version" ON) +mark_as_advanced(USE_SYSTEM_LIBRARIES) +mark_as_advanced(ONLY_BUILD_SOLIDITY_LIBRARIES) +mark_as_advanced(STRICT_NLOHMANN_JSON_VERSION) # Setup cccache. include(EthCcache) From 3485bc94cf1c8bd4152fee33b3161c0b5649a69b Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Tue, 7 May 2024 14:58:41 +0200 Subject: [PATCH 0098/1340] Reformat tests in nlohmann::json style. --- libsolutil/JSON.cpp | 64 -- test/cmdlineTests/abi_via_ir/output | 36 +- test/cmdlineTests/asm_json/output | 15 +- .../ast_compact_json_with_base_path/output | 27 +- test/cmdlineTests/ast_ir/output | 345 +++---- test/cmdlineTests/combined_json_abi/output | 6 +- .../combined_json_generated_sources/output | 333 +++---- .../combined_json_stop_after_parsing/output | 21 +- .../combined_json_with_base_path/output | 48 +- .../combined_json_with_devdoc/output | 15 +- .../combined_json_with_userdoc/output | 15 +- test/cmdlineTests/events_in_abi/output | 9 +- test/cmdlineTests/function_debug_info/output | 36 +- .../function_debug_info_via_yul/output | 6 +- .../import_asm_json_all_valid_flags/output | 42 +- .../output | 105 +-- .../linking_standard_solidity/output.json | 21 +- .../output.json | 21 +- .../output.json | 30 +- .../linking_standard_yul/output.json | 15 +- .../output.json | 15 +- .../output.json | 24 +- .../no_contract_combined_json/output | 18 +- .../output_selection_all_A1/output.json | 36 +- .../output_selection_all_A2/output.json | 24 +- .../output_selection_all_blank/output.json | 9 +- .../output_selection_all_star/output.json | 54 +- .../output_selection_single_A1/output.json | 24 +- .../output_selection_single_B1/output.json | 24 +- .../output_selection_single_all/output.json | 33 +- .../pretty_json_indent_only/output.json | 6 +- .../pretty_json_standard/output.json | 6 +- .../pretty_json_standard_indent/output.json | 6 +- .../output.json | 30 +- .../output.json | 18 +- .../output.json | 18 +- .../output.json | 18 +- .../output.json | 3 +- .../output.json | 24 +- .../standard_default_success/output.json | 6 +- .../standard_empty_file_name/output.json | 6 +- .../output.json | 9 +- .../output.json | 6 +- .../standard_function_debug_info/output.json | 93 +- .../standard_generatedSources/output.json | 852 ++++++------------ .../standard_immutable_references/output.json | 27 +- .../standard_import_asm_json/output.json | 27 +- .../output.json | 24 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 27 +- .../output.json | 3 +- .../standard_import_ast/output.json | 36 +- .../output.json | 21 +- .../standard_import_with_comments/output.json | 36 +- .../output.json | 36 +- .../output.json | 3 +- .../output.json | 198 ++-- .../output.json | 15 +- .../standard_ir_ast_requested/output.json | 246 ++--- .../standard_ir_requested/output.json | 15 +- .../standard_metadata/output.json | 15 +- .../output.json | 21 +- .../output.json | 18 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 3 +- .../output.json | 15 +- .../output.json | 15 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 15 +- .../output.json | 21 +- .../output.json | 15 +- .../output.json | 9 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 15 +- .../output.json | 9 +- .../output.json | 15 +- .../output.json | 3 +- .../output.json | 12 +- .../output.json | 15 +- .../output.json | 12 +- .../output.json | 6 +- .../output.json | 3 +- .../output.json | 12 +- .../output.json | 12 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 9 +- .../output.json | 15 +- .../output.json | 12 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 15 +- .../output.json | 15 +- .../output.json | 15 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 12 +- .../output.json | 12 +- .../output.json | 12 +- .../output.json | 12 +- .../output.json | 12 +- .../output.json | 12 +- .../output.json | 18 +- .../output.json | 18 +- .../output.json | 18 +- .../output.json | 3 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 18 +- .../output.json | 15 +- .../output.json | 12 +- .../output.json | 3 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 12 +- .../output.json | 12 +- .../output.json | 12 +- .../output.json | 3 +- .../output.json | 9 +- .../output.json | 15 +- .../output.json | 12 +- .../output.json | 12 +- .../output.json | 15 +- .../output.json | 12 +- .../output.json | 15 +- .../output.json | 6 +- .../output.json | 15 +- .../output.json | 6 +- .../output.json | 33 +- .../output.json | 33 +- .../output.json | 21 +- .../output.json | 15 +- .../output.json | 12 +- .../output.json | 3 +- .../output.json | 6 +- .../output.json | 12 +- .../output.json | 15 +- .../output.json | 12 +- .../output.json | 6 +- .../output.json | 12 +- .../output.json | 15 +- .../output.json | 12 +- .../output.json | 27 +- .../output.json | 18 +- .../output.json | 21 +- .../output.json | 15 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 9 +- .../output.json | 3 +- .../output.json | 3 +- .../standard_no_append_cbor/output.json | 21 +- .../output.json | 3 +- .../standard_no_import_callback/output.json | 6 +- .../standard_non_utf8_filename/output.json | 3 +- .../standard_non_utf8_filename2/output.json | 3 +- .../standard_only_ast_requested/output.json | 36 +- .../output.json | 522 ++++------- .../output.json | 3 +- .../output.json | 3 +- .../standard_optimizer_no_yul/output.json | 6 +- .../standard_optimizer_yul/output.json | 6 +- .../standard_optimizer_yulDetails/output.json | 6 +- .../output.json | 3 +- .../output.json | 6 +- .../output.json | 15 +- .../output.json | 15 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 6 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 6 +- .../output.json | 6 +- .../output.json | 6 +- .../output.json | 6 +- .../output.json | 6 +- .../output.json | 6 +- .../output.json | 3 +- .../output.json | 6 +- .../output.json | 6 +- .../output.json | 6 +- .../output.json | 108 +-- .../output.json | 6 +- .../output.json | 27 +- .../standard_raw_utf16_filename/output.json | 3 +- .../output.json | 9 +- .../output.json | 15 +- .../output.json | 3 +- .../output.json | 6 +- .../output.json | 9 +- .../standard_urls_missing/output.json | 3 +- .../standard_viair_requested/output.json | 42 +- .../output.json | 3 +- .../standard_wrong_key_metadata/output.json | 3 +- .../standard_wrong_key_optimizer/output.json | 3 +- .../standard_wrong_key_root/output.json | 3 +- .../standard_wrong_key_settings/output.json | 3 +- .../standard_wrong_key_source/output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../standard_wrong_type_metadata/output.json | 3 +- .../standard_wrong_type_optimizer/output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 3 +- .../standard_wrong_type_root/output.json | 3 +- .../standard_wrong_type_settings/output.json | 3 +- .../standard_wrong_type_source/output.json | 3 +- .../standard_wrong_type_sources/output.json | 3 +- .../output.json | 3 +- test/cmdlineTests/standard_yul/output.json | 60 +- .../output.json | 12 +- .../output.json | 12 +- .../output.json | 12 +- .../output.json | 3 +- .../output.json | 3 +- .../output.json | 24 +- .../standard_yul_multiple_files/output.json | 3 +- .../output.json | 3 +- .../standard_yul_object/output.json | 63 +- .../output.json | 6 +- .../standard_yul_object_name/output.json | 84 +- .../standard_yul_optimiserSteps/output.json | 60 +- .../standard_yul_optimized/output.json | 60 +- .../output.json | 3 +- .../standard_yul_stack_opt/output.json | 12 +- .../output.json | 12 +- .../stop_after_parsing_ast/output | 6 +- .../storage_layout_bytes/output.json | 27 +- .../storage_layout_dyn_array/output.json | 36 +- .../storage_layout_many/output.json | 60 +- .../storage_layout_mapping/output.json | 39 +- .../storage_layout_smoke/output.json | 18 +- .../output.json | 21 +- .../storage_layout_string/output.json | 27 +- .../storage_layout_struct/output.json | 42 +- .../storage_layout_struct_packed/output.json | 45 +- .../storage_layout_user_defined/output | 12 +- .../storage_layout_value_types/output.json | 33 +- .../output.json | 39 +- .../strict_asm_ast_compact_json/output | 21 +- .../yul_string_format_ascii/output.json | 15 +- .../output.json | 15 +- .../output.json | 15 +- .../yul_string_format_ascii_long/output.json | 15 +- .../yul_string_format_hex/output.json | 15 +- test/libsolidity/ABIJson/basic_test.sol | 6 +- test/libsolidity/ABIJson/constructor_abi.sol | 3 +- ...ty_name_input_parameter_with_named_one.sol | 6 +- .../ABIJson/empty_name_return_parameters.sol | 6 +- test/libsolidity/ABIJson/errors.sol | 15 +- .../libsolidity/ABIJson/errors_referenced.sol | 9 +- .../ABIJson/event_emited_in_base_contract.sol | 9 +- .../event_emitted_from_foreign_contract.sol | 18 +- test/libsolidity/ABIJson/event_file_level.sol | 9 +- test/libsolidity/ABIJson/event_structs.sol | 12 +- test/libsolidity/ABIJson/events.sol | 12 +- test/libsolidity/ABIJson/events_indirect.sol | 9 +- test/libsolidity/ABIJson/function_type.sol | 3 +- .../ABIJson/function_type_extended.sol | 3 +- test/libsolidity/ABIJson/global_struct.sol | 12 +- test/libsolidity/ABIJson/inherited.sol | 27 +- test/libsolidity/ABIJson/library_function.sol | 6 +- test/libsolidity/ABIJson/mapping.sol | 18 +- test/libsolidity/ABIJson/multiple_methods.sol | 12 +- .../ABIJson/multiple_methods_order.sol | 12 +- test/libsolidity/ABIJson/multiple_params.sol | 6 +- .../ABIJson/payable_constructor_abi.sol | 3 +- test/libsolidity/ABIJson/pure_function.sol | 12 +- .../ABIJson/return_param_in_abi.sol | 6 +- test/libsolidity/ABIJson/return_structs.sol | 9 +- .../ABIJson/return_structs_with_contracts.sol | 6 +- .../ABIJson/structs_and_arrays.sol | 3 +- .../ABIJson/structs_in_libraries.sol | 9 +- .../ABIJson/user_defined_value_type.sol | 30 +- test/libsolidity/ABIJson/view_function.sol | 12 +- .../ASTJSON/abstract_contract.json | 24 +- .../libsolidity/ASTJSON/abstract_contract.sol | 1 + .../ASTJSON/abstract_contract_parseOnly.json | 15 +- test/libsolidity/ASTJSON/address_payable.json | 210 ++--- test/libsolidity/ASTJSON/address_payable.sol | 1 + .../ASTJSON/address_payable_parseOnly.json | 111 +-- test/libsolidity/ASTJSON/array_type_name.json | 30 +- .../ASTJSON/array_type_name_parseOnly.json | 12 +- test/libsolidity/ASTJSON/assembly/call.json | 48 +- test/libsolidity/ASTJSON/assembly/call.sol | 1 + .../ASTJSON/assembly/call_parseOnly.json | 39 +- .../ASTJSON/assembly/empty_block.json | 33 +- .../ASTJSON/assembly/empty_block.sol | 1 + .../assembly/empty_block_parseOnly.json | 24 +- .../empty_let_variable_declaration.json | 36 +- .../empty_let_variable_declaration.sol | 1 + ...ty_let_variable_declaration_parseOnly.json | 27 +- .../ASTJSON/assembly/function.json | 60 +- .../libsolidity/ASTJSON/assembly/function.sol | 1 + .../ASTJSON/assembly/function_parseOnly.json | 51 +- test/libsolidity/ASTJSON/assembly/leave.json | 39 +- test/libsolidity/ASTJSON/assembly/leave.sol | 1 + .../ASTJSON/assembly/leave_parseOnly.json | 30 +- test/libsolidity/ASTJSON/assembly/loop.json | 66 +- test/libsolidity/ASTJSON/assembly/loop.sol | 1 + .../ASTJSON/assembly/loop_parseOnly.json | 57 +- .../ASTJSON/assembly/nested_functions.json | 63 +- .../ASTJSON/assembly/nested_functions.sol | 1 + .../assembly/nested_functions_parseOnly.json | 45 +- .../ASTJSON/assembly/slot_offset.json | 81 +- .../ASTJSON/assembly/slot_offset.sol | 1 + .../assembly/slot_offset_parseOnly.json | 57 +- .../ASTJSON/assembly/stringlit.json | 39 +- .../ASTJSON/assembly/stringlit.sol | 1 + .../ASTJSON/assembly/stringlit_parseOnly.json | 30 +- test/libsolidity/ASTJSON/assembly/switch.json | 75 +- test/libsolidity/ASTJSON/assembly/switch.sol | 1 + .../ASTJSON/assembly/switch_default.json | 48 +- .../ASTJSON/assembly/switch_default.sol | 1 + .../assembly/switch_default_parseOnly.json | 39 +- .../ASTJSON/assembly/switch_parseOnly.json | 66 +- .../ASTJSON/assembly/var_access.json | 57 +- .../ASTJSON/assembly/var_access.sol | 1 + .../assembly/var_access_parseOnly.json | 39 +- ...nternal_function_different_ids_export.json | 333 +++---- ...internal_function_different_ids_export.sol | 3 - .../ast_internal_function_id_export.json | 477 ++++------ .../ASTJSON/base_constructor_call.json | 78 +- .../base_constructor_call_parseOnly.json | 54 +- test/libsolidity/ASTJSON/constructor.json | 24 +- test/libsolidity/ASTJSON/constructor.sol | 1 + .../ASTJSON/constructor_parseOnly.json | 15 +- .../ASTJSON/contract_dep_order.json | 72 +- .../ASTJSON/contract_dep_order_parseOnly.json | 39 +- test/libsolidity/ASTJSON/documentation.json | 90 +- test/libsolidity/ASTJSON/documentation.sol | 4 +- .../ASTJSON/documentation_local_variable.json | 174 ++-- ...ocumentation_local_variable_parseOnly.json | 102 +-- .../ASTJSON/documentation_on_statements.json | 138 +-- ...documentation_on_statements_parseOnly.json | 78 +- .../ASTJSON/documentation_parseOnly.json | 51 +- .../ASTJSON/documentation_triple.json | 141 +-- .../documentation_triple_parseOnly.json | 78 +- test/libsolidity/ASTJSON/enum_natspec.json | 15 +- .../ASTJSON/enum_natspec_parseOnly.json | 9 +- test/libsolidity/ASTJSON/enum_value.json | 18 +- .../ASTJSON/enum_value_declaration.json | 57 +- .../enum_value_declaration_parseOnly.json | 36 +- .../ASTJSON/enum_value_parseOnly.json | 9 +- .../ASTJSON/event_aggregated_contract.json | 138 +-- .../libsolidity/ASTJSON/event_definition.json | 21 +- .../ASTJSON/event_definition_parseOnly.json | 9 +- .../event_emited_in_base_contract.json | 102 +-- .../event_emitted_from_foreign_contract.json | 102 +-- ...itted_from_foreign_contract_parseOnly.json | 51 +- .../ASTJSON/event_inheritance.json | 69 +- ...event_with_variables_of_internal_types.sol | 1 + ...variables_of_internal_types_parseOnly.json | 21 +- .../ASTJSON/fail_after_parsing.sol | 5 +- .../ASTJSON/fail_after_parsing_parseOnly.json | 87 +- test/libsolidity/ASTJSON/fallback.json | 24 +- test/libsolidity/ASTJSON/fallback.sol | 1 + .../ASTJSON/fallback_and_receive_ether.json | 33 +- .../ASTJSON/fallback_and_receive_ether.sol | 1 + .../fallback_and_receive_ether_parseOnly.json | 24 +- .../ASTJSON/fallback_parseOnly.json | 15 +- .../libsolidity/ASTJSON/fallback_payable.json | 24 +- test/libsolidity/ASTJSON/fallback_payable.sol | 1 + .../ASTJSON/fallback_payable_parseOnly.json | 15 +- test/libsolidity/ASTJSON/function_type.json | 84 +- .../ASTJSON/function_type_parseOnly.json | 51 +- test/libsolidity/ASTJSON/global_enum.json | 12 +- .../ASTJSON/global_enum_parseOnly.json | 6 +- test/libsolidity/ASTJSON/global_struct.json | 21 +- .../ASTJSON/global_struct_parseOnly.json | 9 +- test/libsolidity/ASTJSON/indirect_event.json | 102 +-- .../ASTJSON/indirect_event_parseOnly.json | 60 +- .../ASTJSON/inheritance_specifier.json | 27 +- .../inheritance_specifier_parseOnly.json | 12 +- test/libsolidity/ASTJSON/license.json | 12 +- .../ASTJSON/license_parseOnly.json | 3 +- .../long_type_name_binary_operation.json | 63 +- ..._type_name_binary_operation_parseOnly.json | 36 +- .../ASTJSON/long_type_name_identifier.json | 69 +- .../long_type_name_identifier_parseOnly.json | 39 +- test/libsolidity/ASTJSON/mappings.json | 114 +-- test/libsolidity/ASTJSON/mappings.sol | 1 + .../ASTJSON/mappings_parseOnly.json | 57 +- .../ASTJSON/modifier_definition.json | 60 +- .../modifier_definition_parseOnly.json | 42 +- .../ASTJSON/modifier_invocation.json | 60 +- .../modifier_invocation_parseOnly.json | 42 +- test/libsolidity/ASTJSON/mutability.json | 60 +- test/libsolidity/ASTJSON/mutability.sol | 1 + .../ASTJSON/mutability_parseOnly.json | 24 +- test/libsolidity/ASTJSON/non_utf8.json | 84 +- .../ASTJSON/non_utf8_parseOnly.json | 48 +- .../ASTJSON/not_existing_import.sol | 2 +- .../not_existing_import_parseOnly.json | 33 +- test/libsolidity/ASTJSON/override.json | 111 +-- test/libsolidity/ASTJSON/override.sol | 1 + .../ASTJSON/override_parseOnly.json | 81 +- .../ASTJSON/placeholder_statement.json | 24 +- .../placeholder_statement_parseOnly.json | 15 +- ...ragma_experimental_solidity_parseOnly.json | 6 +- test/libsolidity/ASTJSON/receive_ether.json | 24 +- test/libsolidity/ASTJSON/receive_ether.sol | 1 + .../ASTJSON/receive_ether_parseOnly.json | 15 +- test/libsolidity/ASTJSON/short_type_name.json | 48 +- .../ASTJSON/short_type_name_parseOnly.json | 30 +- .../ASTJSON/short_type_name_ref.json | 54 +- .../short_type_name_ref_parseOnly.json | 33 +- test/libsolidity/ASTJSON/smoke.json | 12 +- test/libsolidity/ASTJSON/smoke_parseOnly.json | 3 +- test/libsolidity/ASTJSON/source_location.json | 60 +- .../ASTJSON/source_location_parseOnly.json | 36 +- test/libsolidity/ASTJSON/string.json | 48 +- .../libsolidity/ASTJSON/string_parseOnly.json | 30 +- test/libsolidity/ASTJSON/struct_natspec.json | 42 +- .../ASTJSON/struct_natspec_parseOnly.json | 18 +- .../ASTJSON/two_base_functions.json | 90 +- .../ASTJSON/two_base_functions.sol | 1 + .../ASTJSON/two_base_functions_parseOnly.json | 66 +- test/libsolidity/ASTJSON/unicode.json | 48 +- .../ASTJSON/unicode_parseOnly.json | 30 +- test/libsolidity/ASTJSON/used_errors.json | 78 +- test/libsolidity/ASTJSON/used_errors.sol | 1 + .../ASTJSON/used_errors_parseOnly.json | 48 +- .../ASTJSON/userDefinedValueType.json | 135 +-- .../ASTJSON/userDefinedValueType.sol | 1 + .../userDefinedValueType_parseOnly.json | 81 +- .../ASTJSON/user_defined_operator.json | 252 ++---- .../ASTJSON/user_defined_operator.sol | 1 + .../ASTJSON/using_for_directive.json | 66 +- .../using_for_directive_parseOnly.json | 39 +- test/libsolidity/ASTJSON/yul_hex_literal.json | 51 +- test/libsolidity/ASTJSON/yul_hex_literal.sol | 1 + .../ASTJSON/yul_hex_literal_parseOnly.json | 42 +- test/libsolutil/JSON.cpp | 3 +- 470 files changed, 4707 insertions(+), 9427 deletions(-) diff --git a/libsolutil/JSON.cpp b/libsolutil/JSON.cpp index 63746c865..055024edb 100644 --- a/libsolutil/JSON.cpp +++ b/libsolutil/JSON.cpp @@ -25,9 +25,7 @@ #include #include -#include -#include #include #ifdef STRICT_NLOHMANN_JSON_VERSION_CHECK @@ -65,64 +63,6 @@ void removeNullMembersHelper(Json& _json) } } -std::string trimRightAllLines(std::string const& input) -{ - std::vector lines; - std::string output; - boost::split(lines, input, boost::is_any_of("\n")); - for (auto& line: lines) - { - boost::trim_right(line); - if (!line.empty()) - output += line + "\n"; - } - return boost::trim_right_copy(output); -} - -std::string formatLikeJsoncpp(std::string const& _dumped, JsonFormat const& _format) -{ - uint32_t indentLevel = 0; - std::stringstream reformatted; - bool inQuotes = false; - for (size_t i = 0; i < _dumped.size(); ++i) - { - char c = _dumped[i]; - bool emptyThing = false; - - if (c == '"' && (i == 0 || _dumped[i - 1] != '\\')) - inQuotes = !inQuotes; - - if (!inQuotes) - { - if (i < _dumped.size() - 1) - { - char nc = _dumped[i + 1]; - if ((c == '[' && nc == ']') || (c == '{' && nc == '}')) - emptyThing = true; - } - if (c == '[' || c == '{') - { - if (i > 0 && _dumped[i - 1] != '\n') - if (!emptyThing) - reformatted << '\n' << std::string(indentLevel * _format.indent, ' '); - indentLevel++; - } - else if (c == ']' || c == '}') - { - indentLevel--; - if (i + 1 < _dumped.size() && _dumped[i + 1] != '\n' - && (_dumped[i + 1] == ']' || _dumped[i + 1] == '}')) - reformatted << '\n' << std::string(indentLevel * _format.indent, ' '); - } - } - reformatted << c; - if (!emptyThing && !inQuotes && (c == '[' || c == '{') && indentLevel > 0 && i + 1 < _dumped.size() - && _dumped[i + 1] != '\n') - reformatted << '\n' << std::string(indentLevel * _format.indent, ' '); - } - return trimRightAllLines(reformatted.str()); -} - std::string escapeNewlinesAndTabsWithinStringLiterals(std::string const& _json) { std::stringstream fixed; @@ -201,10 +141,6 @@ std::string jsonPrint(Json const& _input, JsonFormat const& _format) /* ensure_ascii */ true ); - // let's remove this once all test-cases having the correct output. - if (_format.format == JsonFormat::Pretty) - dumped = formatLikeJsoncpp(dumped, _format); - return dumped; } diff --git a/test/cmdlineTests/abi_via_ir/output b/test/cmdlineTests/abi_via_ir/output index daf18f349..56ba01a4a 100644 --- a/test/cmdlineTests/abi_via_ir/output +++ b/test/cmdlineTests/abi_via_ir/output @@ -3,8 +3,7 @@ Contract JSON ABI [ { - "inputs": - [ + "inputs": [ { "internalType": "uint256", "name": "z", @@ -20,8 +19,7 @@ Contract JSON ABI "type": "error" }, { - "inputs": - [ + "inputs": [ { "internalType": "uint256", "name": "z", @@ -32,8 +30,7 @@ Contract JSON ABI "type": "error" }, { - "inputs": - [ + "inputs": [ { "internalType": "uint256", "name": "r", @@ -45,8 +42,7 @@ Contract JSON ABI }, { "anonymous": true, - "inputs": - [ + "inputs": [ { "indexed": false, "internalType": "uint256", @@ -59,8 +55,7 @@ Contract JSON ABI }, { "anonymous": false, - "inputs": - [ + "inputs": [ { "indexed": false, "internalType": "uint256", @@ -73,8 +68,7 @@ Contract JSON ABI }, { "anonymous": false, - "inputs": - [ + "inputs": [ { "indexed": false, "internalType": "uint256", @@ -86,11 +80,9 @@ Contract JSON ABI "type": "event" }, { - "inputs": - [ + "inputs": [ { - "components": - [ + "components": [ { "internalType": "uint256", "name": "x", @@ -113,8 +105,7 @@ Contract JSON ABI Contract JSON ABI [ { - "inputs": - [ + "inputs": [ { "internalType": "uint256", "name": "r", @@ -125,8 +116,7 @@ Contract JSON ABI "type": "error" }, { - "inputs": - [ + "inputs": [ { "internalType": "uint256", "name": "u", @@ -138,8 +128,7 @@ Contract JSON ABI }, { "anonymous": false, - "inputs": - [ + "inputs": [ { "indexed": false, "internalType": "uint256", @@ -152,8 +141,7 @@ Contract JSON ABI }, { "anonymous": false, - "inputs": - [ + "inputs": [ { "indexed": false, "internalType": "uint256", diff --git a/test/cmdlineTests/asm_json/output b/test/cmdlineTests/asm_json/output index f6a0a4b19..38d9c9fdf 100644 --- a/test/cmdlineTests/asm_json/output +++ b/test/cmdlineTests/asm_json/output @@ -2,8 +2,7 @@ ======= asm_json/input.sol:C ======= EVM assembly: { - ".code": - [ + ".code": [ { "begin": 60, "end": 160, @@ -140,13 +139,10 @@ EVM assembly: "source": 0 } ], - ".data": - { - "0": - { + ".data": { + "0": { ".auxdata": "", - ".code": - [ + ".code": [ { "begin": 60, "end": 160, @@ -1570,8 +1566,7 @@ EVM assembly: ] } }, - "sourceList": - [ + "sourceList": [ "asm_json/input.sol", "#utility.yul" ] diff --git a/test/cmdlineTests/ast_compact_json_with_base_path/output b/test/cmdlineTests/ast_compact_json_with_base_path/output index 5c5c6ffd5..c61502020 100644 --- a/test/cmdlineTests/ast_compact_json_with_base_path/output +++ b/test/cmdlineTests/ast_compact_json_with_base_path/output @@ -4,22 +4,18 @@ JSON AST (compact format): ======= ast_compact_json_with_base_path/c.sol ======= { "absolutePath": "ast_compact_json_with_base_path/c.sol", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ] }, "id": 6, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 4, - "literals": - [ + "literals": [ "solidity", ">=", "0.0" @@ -35,8 +31,7 @@ JSON AST (compact format): "contractKind": "contract", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "C", @@ -54,22 +49,18 @@ JSON AST (compact format): ======= ast_compact_json_with_base_path/input.sol ======= { "absolutePath": "ast_compact_json_with_base_path/input.sol", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ] }, "id": 3, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", ">=", "0.0" diff --git a/test/cmdlineTests/ast_ir/output b/test/cmdlineTests/ast_ir/output index cca31349e..c68c77872 100644 --- a/test/cmdlineTests/ast_ir/output +++ b/test/cmdlineTests/ast_ir/output @@ -1,19 +1,14 @@ IR AST: { - "code": - { - "block": - { + "code": { + "block": { "nativeSrc": "59:790:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "118:2:0", @@ -23,8 +18,7 @@ IR AST: "value": "64" }, { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "134:3:0", @@ -34,8 +28,7 @@ IR AST: "value": "128" } ], - "functionName": - { + "functionName": { "name": "memoryguard", "nativeSrc": "122:11:0", "nodeType": "YulIdentifier", @@ -46,8 +39,7 @@ IR AST: "src": "60:13:0" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "111:6:0", "nodeType": "YulIdentifier", @@ -62,19 +54,15 @@ IR AST: "src": "60:13:0" }, { - "body": - { + "body": { "nativeSrc": "163:83:0", "nodeType": "YulBlock", "src": "60:13:0", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", "nativeSrc": "165:77:0", "nodeType": "YulIdentifier", @@ -90,11 +78,9 @@ IR AST: } ] }, - "condition": - { + "condition": { "arguments": [], - "functionName": - { + "functionName": { "name": "callvalue", "nativeSrc": "151:9:0", "nodeType": "YulIdentifier", @@ -109,11 +95,9 @@ IR AST: "src": "60:13:0" }, { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "constructor_C_2", "nativeSrc": "256:15:0", "nodeType": "YulIdentifier", @@ -131,11 +115,9 @@ IR AST: "nativeSrc": "283:30:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", - "value": - { + "value": { "arguments": [], - "functionName": - { + "functionName": { "name": "allocate_unbounded", "nativeSrc": "293:18:0", "nodeType": "YulIdentifier", @@ -145,8 +127,7 @@ IR AST: "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "variables": - [ + "variables": [ { "name": "_1", "nativeSrc": "287:2:0", @@ -157,10 +138,8 @@ IR AST: ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "_1", "nativeSrc": "331:2:0", @@ -168,8 +147,7 @@ IR AST: "src": "60:13:0" }, { - "arguments": - [ + "arguments": [ { "hexValue": "435f325f6465706c6f796564", "kind": "string", @@ -180,8 +158,7 @@ IR AST: "value": "C_2_deployed" } ], - "functionName": - { + "functionName": { "name": "dataoffset", "nativeSrc": "335:10:0", "nodeType": "YulIdentifier", @@ -192,8 +169,7 @@ IR AST: "src": "60:13:0" }, { - "arguments": - [ + "arguments": [ { "hexValue": "435f325f6465706c6f796564", "kind": "string", @@ -204,8 +180,7 @@ IR AST: "value": "C_2_deployed" } ], - "functionName": - { + "functionName": { "name": "datasize", "nativeSrc": "363:8:0", "nodeType": "YulIdentifier", @@ -216,8 +191,7 @@ IR AST: "src": "60:13:0" } ], - "functionName": - { + "functionName": { "name": "codecopy", "nativeSrc": "322:8:0", "nodeType": "YulIdentifier", @@ -232,10 +206,8 @@ IR AST: "src": "60:13:0" }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "_1", "nativeSrc": "405:2:0", @@ -243,8 +215,7 @@ IR AST: "src": "60:13:0" }, { - "arguments": - [ + "arguments": [ { "hexValue": "435f325f6465706c6f796564", "kind": "string", @@ -255,8 +226,7 @@ IR AST: "value": "C_2_deployed" } ], - "functionName": - { + "functionName": { "name": "datasize", "nativeSrc": "409:8:0", "nodeType": "YulIdentifier", @@ -267,8 +237,7 @@ IR AST: "src": "60:13:0" } ], - "functionName": - { + "functionName": { "name": "return", "nativeSrc": "398:6:0", "nodeType": "YulIdentifier", @@ -283,21 +252,17 @@ IR AST: "src": "60:13:0" }, { - "body": - { + "body": { "nativeSrc": "484:43:0", "nodeType": "YulBlock", "src": "60:13:0", - "statements": - [ + "statements": [ { "nativeSrc": "498:19:0", "nodeType": "YulAssignment", "src": "60:13:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "514:2:0", @@ -307,8 +272,7 @@ IR AST: "value": "64" } ], - "functionName": - { + "functionName": { "name": "mload", "nativeSrc": "508:5:0", "nodeType": "YulIdentifier", @@ -318,8 +282,7 @@ IR AST: "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "variableNames": - [ + "variableNames": [ { "name": "memPtr", "nativeSrc": "498:6:0", @@ -333,8 +296,7 @@ IR AST: "name": "allocate_unbounded", "nativeSrc": "444:83:0", "nodeType": "YulFunctionDefinition", - "returnVariables": - [ + "returnVariables": [ { "name": "memPtr", "nativeSrc": "477:6:0", @@ -346,18 +308,14 @@ IR AST: "src": "60:13:0" }, { - "body": - { + "body": { "nativeSrc": "626:36:0", "nodeType": "YulBlock", "src": "60:13:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "647:1:0", @@ -375,8 +333,7 @@ IR AST: "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "640:6:0", "nodeType": "YulIdentifier", @@ -398,8 +355,7 @@ IR AST: "src": "60:13:0" }, { - "body": - { + "body": { "nativeSrc": "741:59:0", "nodeType": "YulBlock", "src": "60:13:0", @@ -416,23 +372,17 @@ IR AST: }, "name": "C_2", "nodeType": "YulObject", - "subObjects": - [ + "subObjects": [ { - "code": - { - "block": - { + "code": { + "block": { "nativeSrc": "929:588:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "996:2:0", @@ -442,8 +392,7 @@ IR AST: "value": "64" }, { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "1012:3:0", @@ -453,8 +402,7 @@ IR AST: "value": "128" } ], - "functionName": - { + "functionName": { "name": "memoryguard", "nativeSrc": "1000:11:0", "nodeType": "YulIdentifier", @@ -465,8 +413,7 @@ IR AST: "src": "60:13:0" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "989:6:0", "nodeType": "YulIdentifier", @@ -481,11 +428,9 @@ IR AST: "src": "60:13:0" }, { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", "nativeSrc": "1031:77:0", "nodeType": "YulIdentifier", @@ -500,21 +445,17 @@ IR AST: "src": "60:13:0" }, { - "body": - { + "body": { "nativeSrc": "1177:77:0", "nodeType": "YulBlock", "src": "60:13:0", - "statements": - [ + "statements": [ { "nativeSrc": "1195:44:0", "nodeType": "YulAssignment", "src": "60:13:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "1228:3:0", @@ -530,8 +471,7 @@ IR AST: "src": "60:13:0" } ], - "functionName": - { + "functionName": { "name": "shr", "nativeSrc": "1224:3:0", "nodeType": "YulIdentifier", @@ -541,8 +481,7 @@ IR AST: "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "variableNames": - [ + "variableNames": [ { "name": "newValue", "nativeSrc": "1195:8:0", @@ -556,8 +495,7 @@ IR AST: "name": "shift_right_224_unsigned", "nativeSrc": "1124:130:0", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "value", "nativeSrc": "1158:5:0", @@ -566,8 +504,7 @@ IR AST: "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "newValue", "nativeSrc": "1168:8:0", @@ -579,21 +516,17 @@ IR AST: "src": "60:13:0" }, { - "body": - { + "body": { "nativeSrc": "1308:51:0", "nodeType": "YulBlock", "src": "60:13:0", - "statements": - [ + "statements": [ { "nativeSrc": "1326:19:0", "nodeType": "YulAssignment", "src": "60:13:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "1342:2:0", @@ -603,8 +536,7 @@ IR AST: "value": "64" } ], - "functionName": - { + "functionName": { "name": "mload", "nativeSrc": "1336:5:0", "nodeType": "YulIdentifier", @@ -614,8 +546,7 @@ IR AST: "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "variableNames": - [ + "variableNames": [ { "name": "memPtr", "nativeSrc": "1326:6:0", @@ -629,8 +560,7 @@ IR AST: "name": "allocate_unbounded", "nativeSrc": "1268:91:0", "nodeType": "YulFunctionDefinition", - "returnVariables": - [ + "returnVariables": [ { "name": "memPtr", "nativeSrc": "1301:6:0", @@ -642,18 +572,14 @@ IR AST: "src": "60:13:0" }, { - "body": - { + "body": { "nativeSrc": "1462:44:0", "nodeType": "YulBlock", "src": "60:13:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "1487:1:0", @@ -671,8 +597,7 @@ IR AST: "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "1480:6:0", "nodeType": "YulIdentifier", @@ -699,8 +624,7 @@ IR AST: }, "name": "C_2_deployed", "nodeType": "YulObject", - "subObjects": - [ + "subObjects": [ { "nodeType": "YulData", "value": "" @@ -711,29 +635,23 @@ IR AST: } Optimized IR AST: { - "code": - { - "block": - { + "code": { + "block": { "nativeSrc": "59:790:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { "nativeSrc": "59:790:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { "nativeSrc": "122:16:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "134:3:0", @@ -743,8 +661,7 @@ Optimized IR AST: "value": "0x80" } ], - "functionName": - { + "functionName": { "name": "memoryguard", "nativeSrc": "122:11:0", "nodeType": "YulIdentifier", @@ -754,8 +671,7 @@ Optimized IR AST: "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "variables": - [ + "variables": [ { "name": "_1", "nativeSrc": "122:16:0", @@ -766,10 +682,8 @@ Optimized IR AST: ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "118:2:0", @@ -785,8 +699,7 @@ Optimized IR AST: "src": "60:13:0" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "111:6:0", "nodeType": "YulIdentifier", @@ -801,18 +714,14 @@ Optimized IR AST: "src": "60:13:0" }, { - "body": - { + "body": { "nativeSrc": "163:83:0", "nodeType": "YulBlock", "src": "60:13:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "650:1:0", @@ -830,8 +739,7 @@ Optimized IR AST: "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "640:6:0", "nodeType": "YulIdentifier", @@ -847,11 +755,9 @@ Optimized IR AST: } ] }, - "condition": - { + "condition": { "arguments": [], - "functionName": - { + "functionName": { "name": "callvalue", "nativeSrc": "151:9:0", "nodeType": "YulIdentifier", @@ -869,10 +775,8 @@ Optimized IR AST: "nativeSrc": "363:24:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "hexValue": "435f325f6465706c6f796564", "kind": "string", @@ -883,8 +787,7 @@ Optimized IR AST: "value": "C_2_deployed" } ], - "functionName": - { + "functionName": { "name": "datasize", "nativeSrc": "363:8:0", "nodeType": "YulIdentifier", @@ -894,8 +797,7 @@ Optimized IR AST: "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "variables": - [ + "variables": [ { "name": "_2", "nativeSrc": "363:24:0", @@ -906,10 +808,8 @@ Optimized IR AST: ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "_1", "nativeSrc": "331:2:0", @@ -917,8 +817,7 @@ Optimized IR AST: "src": "60:13:0" }, { - "arguments": - [ + "arguments": [ { "hexValue": "435f325f6465706c6f796564", "kind": "string", @@ -929,8 +828,7 @@ Optimized IR AST: "value": "C_2_deployed" } ], - "functionName": - { + "functionName": { "name": "dataoffset", "nativeSrc": "335:10:0", "nodeType": "YulIdentifier", @@ -947,8 +845,7 @@ Optimized IR AST: "src": "60:13:0" } ], - "functionName": - { + "functionName": { "name": "codecopy", "nativeSrc": "322:8:0", "nodeType": "YulIdentifier", @@ -963,10 +860,8 @@ Optimized IR AST: "src": "60:13:0" }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "_1", "nativeSrc": "405:2:0", @@ -980,8 +875,7 @@ Optimized IR AST: "src": "60:13:0" } ], - "functionName": - { + "functionName": { "name": "return", "nativeSrc": "398:6:0", "nodeType": "YulIdentifier", @@ -1003,29 +897,22 @@ Optimized IR AST: }, "name": "C_2", "nodeType": "YulObject", - "subObjects": - [ + "subObjects": [ { - "code": - { - "block": - { + "code": { + "block": { "nativeSrc": "929:588:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { "nativeSrc": "929:588:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "1490:1:0", @@ -1043,8 +930,7 @@ Optimized IR AST: "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "1480:6:0", "nodeType": "YulIdentifier", @@ -1066,8 +952,7 @@ Optimized IR AST: }, "name": "C_2_deployed", "nodeType": "YulObject", - "subObjects": - [ + "subObjects": [ { "nodeType": "YulData", "value": "" diff --git a/test/cmdlineTests/combined_json_abi/output b/test/cmdlineTests/combined_json_abi/output index c775c6d72..79b539db7 100644 --- a/test/cmdlineTests/combined_json_abi/output +++ b/test/cmdlineTests/combined_json_abi/output @@ -1,8 +1,6 @@ { - "contracts": - { - "combined_json_abi/input.sol:C": - { + "contracts": { + "combined_json_abi/input.sol:C": { "abi": [] } }, diff --git a/test/cmdlineTests/combined_json_generated_sources/output b/test/cmdlineTests/combined_json_generated_sources/output index 5ef9078d6..db7c86ce1 100644 --- a/test/cmdlineTests/combined_json_generated_sources/output +++ b/test/cmdlineTests/combined_json_generated_sources/output @@ -1,35 +1,26 @@ { - "contracts": - { - "combined_json_generated_sources/input.sol:C": - { + "contracts": { + "combined_json_generated_sources/input.sol:C": { "generated-sources": [], - "generated-sources-runtime": - [ + "generated-sources-runtime": [ { - "ast": - { + "ast": { "nativeSrc": "0:1856:1", "nodeType": "YulBlock", "src": "0:1856:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "47:35:1", "nodeType": "YulBlock", "src": "47:35:1", - "statements": - [ + "statements": [ { "nativeSrc": "57:19:1", "nodeType": "YulAssignment", "src": "57:19:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "73:2:1", @@ -39,8 +30,7 @@ "value": "64" } ], - "functionName": - { + "functionName": { "name": "mload", "nativeSrc": "67:5:1", "nodeType": "YulIdentifier", @@ -50,8 +40,7 @@ "nodeType": "YulFunctionCall", "src": "67:9:1" }, - "variableNames": - [ + "variableNames": [ { "name": "memPtr", "nativeSrc": "57:6:1", @@ -65,8 +54,7 @@ "name": "allocate_unbounded", "nativeSrc": "7:75:1", "nodeType": "YulFunctionDefinition", - "returnVariables": - [ + "returnVariables": [ { "name": "memPtr", "nativeSrc": "40:6:1", @@ -78,18 +66,14 @@ "src": "7:75:1" }, { - "body": - { + "body": { "nativeSrc": "177:28:1", "nodeType": "YulBlock", "src": "177:28:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "194:1:1", @@ -107,8 +91,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "187:6:1", "nodeType": "YulIdentifier", @@ -130,18 +113,14 @@ "src": "88:117:1" }, { - "body": - { + "body": { "nativeSrc": "300:28:1", "nodeType": "YulBlock", "src": "300:28:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "317:1:1", @@ -159,8 +138,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "310:6:1", "nodeType": "YulIdentifier", @@ -182,18 +160,14 @@ "src": "211:117:1" }, { - "body": - { + "body": { "nativeSrc": "423:28:1", "nodeType": "YulBlock", "src": "423:28:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "440:1:1", @@ -211,8 +185,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "433:6:1", "nodeType": "YulIdentifier", @@ -234,18 +207,14 @@ "src": "334:117:1" }, { - "body": - { + "body": { "nativeSrc": "546:28:1", "nodeType": "YulBlock", "src": "546:28:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "563:1:1", @@ -263,8 +232,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "556:6:1", "nodeType": "YulIdentifier", @@ -286,18 +254,14 @@ "src": "457:117:1" }, { - "body": - { + "body": { "nativeSrc": "669:28:1", "nodeType": "YulBlock", "src": "669:28:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "686:1:1", @@ -315,8 +279,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "679:6:1", "nodeType": "YulIdentifier", @@ -338,27 +301,21 @@ "src": "580:117:1" }, { - "body": - { + "body": { "nativeSrc": "810:478:1", "nodeType": "YulBlock", "src": "810:478:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "859:83:1", "nodeType": "YulBlock", "src": "859:83:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_1b9f4a0a5773e33b91aa01db23bf8c55fce1411167c872835e7fa00a4f17d46d", "nativeSrc": "861:77:1", "nodeType": "YulIdentifier", @@ -374,16 +331,12 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { - "arguments": - [ + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "offset", "nativeSrc": "838:6:1", @@ -399,8 +352,7 @@ "value": "0x1f" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "834:3:1", "nodeType": "YulIdentifier", @@ -417,8 +369,7 @@ "src": "853:3:1" } ], - "functionName": - { + "functionName": { "name": "slt", "nativeSrc": "830:3:1", "nodeType": "YulIdentifier", @@ -429,8 +380,7 @@ "src": "830:27:1" } ], - "functionName": - { + "functionName": { "name": "iszero", "nativeSrc": "823:6:1", "nodeType": "YulIdentifier", @@ -448,10 +398,8 @@ "nativeSrc": "951:30:1", "nodeType": "YulAssignment", "src": "951:30:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "offset", "nativeSrc": "974:6:1", @@ -459,8 +407,7 @@ "src": "974:6:1" } ], - "functionName": - { + "functionName": { "name": "calldataload", "nativeSrc": "961:12:1", "nodeType": "YulIdentifier", @@ -470,8 +417,7 @@ "nodeType": "YulFunctionCall", "src": "961:20:1" }, - "variableNames": - [ + "variableNames": [ { "name": "length", "nativeSrc": "951:6:1", @@ -481,19 +427,15 @@ ] }, { - "body": - { + "body": { "nativeSrc": "1024:83:1", "nodeType": "YulBlock", "src": "1024:83:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_15abf5612cd996bc235ba1e55a4a30ac60e6bb601ff7ba4ad3f179b6be8d0490", "nativeSrc": "1026:77:1", "nodeType": "YulIdentifier", @@ -509,10 +451,8 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { "name": "length", "nativeSrc": "996:6:1", @@ -528,8 +468,7 @@ "value": "0xffffffffffffffff" } ], - "functionName": - { + "functionName": { "name": "gt", "nativeSrc": "993:2:1", "nodeType": "YulIdentifier", @@ -547,10 +486,8 @@ "nativeSrc": "1116:29:1", "nodeType": "YulAssignment", "src": "1116:29:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "offset", "nativeSrc": "1132:6:1", @@ -566,8 +503,7 @@ "value": "0x20" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "1128:3:1", "nodeType": "YulIdentifier", @@ -577,8 +513,7 @@ "nodeType": "YulFunctionCall", "src": "1128:17:1" }, - "variableNames": - [ + "variableNames": [ { "name": "arrayPos", "nativeSrc": "1116:8:1", @@ -588,19 +523,15 @@ ] }, { - "body": - { + "body": { "nativeSrc": "1199:83:1", "nodeType": "YulBlock", "src": "1199:83:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_81385d8c0b31fffe14be1da910c8bd3a80be4cfa248e04f42ec0faea3132a8ef", "nativeSrc": "1201:77:1", "nodeType": "YulIdentifier", @@ -616,13 +547,10 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "arrayPos", "nativeSrc": "1164:8:1", @@ -630,8 +558,7 @@ "src": "1164:8:1" }, { - "arguments": - [ + "arguments": [ { "name": "length", "nativeSrc": "1178:6:1", @@ -647,8 +574,7 @@ "value": "0x20" } ], - "functionName": - { + "functionName": { "name": "mul", "nativeSrc": "1174:3:1", "nodeType": "YulIdentifier", @@ -659,8 +585,7 @@ "src": "1174:17:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "1160:3:1", "nodeType": "YulIdentifier", @@ -677,8 +602,7 @@ "src": "1194:3:1" } ], - "functionName": - { + "functionName": { "name": "gt", "nativeSrc": "1157:2:1", "nodeType": "YulIdentifier", @@ -697,8 +621,7 @@ "name": "abi_decode_t_array$_t_uint256_$dyn_calldata_ptr", "nativeSrc": "720:568:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "offset", "nativeSrc": "777:6:1", @@ -714,8 +637,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "arrayPos", "nativeSrc": "793:8:1", @@ -734,27 +656,21 @@ "src": "720:568:1" }, { - "body": - { + "body": { "nativeSrc": "1395:458:1", "nodeType": "YulBlock", "src": "1395:458:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "1441:83:1", "nodeType": "YulBlock", "src": "1441:83:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", "nativeSrc": "1443:77:1", "nodeType": "YulIdentifier", @@ -770,13 +686,10 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "dataEnd", "nativeSrc": "1416:7:1", @@ -790,8 +703,7 @@ "src": "1425:9:1" } ], - "functionName": - { + "functionName": { "name": "sub", "nativeSrc": "1412:3:1", "nodeType": "YulIdentifier", @@ -810,8 +722,7 @@ "value": "32" } ], - "functionName": - { + "functionName": { "name": "slt", "nativeSrc": "1408:3:1", "nodeType": "YulIdentifier", @@ -829,19 +740,15 @@ "nativeSrc": "1534:312:1", "nodeType": "YulBlock", "src": "1534:312:1", - "statements": - [ + "statements": [ { "nativeSrc": "1549:45:1", "nodeType": "YulVariableDeclaration", "src": "1549:45:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "headStart", "nativeSrc": "1580:9:1", @@ -857,8 +764,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "1576:3:1", "nodeType": "YulIdentifier", @@ -869,8 +775,7 @@ "src": "1576:17:1" } ], - "functionName": - { + "functionName": { "name": "calldataload", "nativeSrc": "1563:12:1", "nodeType": "YulIdentifier", @@ -880,8 +785,7 @@ "nodeType": "YulFunctionCall", "src": "1563:31:1" }, - "variables": - [ + "variables": [ { "name": "offset", "nativeSrc": "1553:6:1", @@ -892,19 +796,15 @@ ] }, { - "body": - { + "body": { "nativeSrc": "1641:83:1", "nodeType": "YulBlock", "src": "1641:83:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db", "nativeSrc": "1643:77:1", "nodeType": "YulIdentifier", @@ -920,10 +820,8 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { "name": "offset", "nativeSrc": "1613:6:1", @@ -939,8 +837,7 @@ "value": "0xffffffffffffffff" } ], - "functionName": - { + "functionName": { "name": "gt", "nativeSrc": "1610:2:1", "nodeType": "YulIdentifier", @@ -958,13 +855,10 @@ "nativeSrc": "1738:98:1", "nodeType": "YulAssignment", "src": "1738:98:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "headStart", "nativeSrc": "1808:9:1", @@ -978,8 +872,7 @@ "src": "1819:6:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "1804:3:1", "nodeType": "YulIdentifier", @@ -996,8 +889,7 @@ "src": "1828:7:1" } ], - "functionName": - { + "functionName": { "name": "abi_decode_t_array$_t_uint256_$dyn_calldata_ptr", "nativeSrc": "1756:47:1", "nodeType": "YulIdentifier", @@ -1007,8 +899,7 @@ "nodeType": "YulFunctionCall", "src": "1756:80:1" }, - "variableNames": - [ + "variableNames": [ { "name": "value0", "nativeSrc": "1738:6:1", @@ -1030,8 +921,7 @@ "name": "abi_decode_tuple_t_array$_t_uint256_$dyn_calldata_ptr", "nativeSrc": "1294:559:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "headStart", "nativeSrc": "1357:9:1", @@ -1047,8 +937,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "value0", "nativeSrc": "1380:6:1", diff --git a/test/cmdlineTests/combined_json_stop_after_parsing/output b/test/cmdlineTests/combined_json_stop_after_parsing/output index 32cdd019b..64e66e3f1 100644 --- a/test/cmdlineTests/combined_json_stop_after_parsing/output +++ b/test/cmdlineTests/combined_json_stop_after_parsing/output @@ -1,28 +1,21 @@ { - "contracts": - { + "contracts": { "combined_json_stop_after_parsing/input.sol:C": {} }, - "sourceList": - [ + "sourceList": [ "combined_json_stop_after_parsing/input.sol" ], - "sources": - { - "combined_json_stop_after_parsing/input.sol": - { - "AST": - { + "sources": { + "combined_json_stop_after_parsing/input.sol": { + "AST": { "absolutePath": "combined_json_stop_after_parsing/input.sol", "id": 3, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", "*" ], diff --git a/test/cmdlineTests/combined_json_with_base_path/output b/test/cmdlineTests/combined_json_with_base_path/output index ec9bbcbcb..0a3add37e 100644 --- a/test/cmdlineTests/combined_json_with_base_path/output +++ b/test/cmdlineTests/combined_json_with_base_path/output @@ -1,36 +1,27 @@ { - "contracts": - { + "contracts": { "combined_json_with_base_path/c.sol:C": {} }, - "sourceList": - [ + "sourceList": [ "combined_json_with_base_path/c.sol", "combined_json_with_base_path/input.sol" ], - "sources": - { - "combined_json_with_base_path/c.sol": - { - "AST": - { + "sources": { + "combined_json_with_base_path/c.sol": { + "AST": { "absolutePath": "combined_json_with_base_path/c.sol", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ] }, "id": 6, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 4, - "literals": - [ + "literals": [ "solidity", ">=", "0.0" @@ -46,8 +37,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "C", @@ -64,27 +54,21 @@ }, "id": 0 }, - "combined_json_with_base_path/input.sol": - { - "AST": - { + "combined_json_with_base_path/input.sol": { + "AST": { "absolutePath": "combined_json_with_base_path/input.sol", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ] }, "id": 3, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", ">=", "0.0" diff --git a/test/cmdlineTests/combined_json_with_devdoc/output b/test/cmdlineTests/combined_json_with_devdoc/output index d3df44a90..817018ea6 100644 --- a/test/cmdlineTests/combined_json_with_devdoc/output +++ b/test/cmdlineTests/combined_json_with_devdoc/output @@ -1,20 +1,15 @@ { - "contracts": - { - "combined_json_with_devdoc/input.sol:C": - { - "devdoc": - { + "contracts": { + "combined_json_with_devdoc/input.sol:C": { + "devdoc": { "details": "This is devdoc.", "kind": "dev", "methods": {}, "version": 1 } }, - "combined_json_with_devdoc/input.sol:D": - { - "devdoc": - { + "combined_json_with_devdoc/input.sol:D": { + "devdoc": { "kind": "dev", "methods": {}, "version": 1 diff --git a/test/cmdlineTests/combined_json_with_userdoc/output b/test/cmdlineTests/combined_json_with_userdoc/output index 650981d67..4eb56fe24 100644 --- a/test/cmdlineTests/combined_json_with_userdoc/output +++ b/test/cmdlineTests/combined_json_with_userdoc/output @@ -1,20 +1,15 @@ { - "contracts": - { - "combined_json_with_userdoc/input.sol:C": - { - "userdoc": - { + "contracts": { + "combined_json_with_userdoc/input.sol:C": { + "userdoc": { "kind": "user", "methods": {}, "notice": "Description for users.", "version": 1 } }, - "combined_json_with_userdoc/input.sol:D": - { - "userdoc": - { + "combined_json_with_userdoc/input.sol:D": { + "userdoc": { "kind": "user", "methods": {}, "version": 1 diff --git a/test/cmdlineTests/events_in_abi/output b/test/cmdlineTests/events_in_abi/output index 6c18a1752..ab246ef24 100644 --- a/test/cmdlineTests/events_in_abi/output +++ b/test/cmdlineTests/events_in_abi/output @@ -4,8 +4,7 @@ Contract JSON ABI [ { "anonymous": false, - "inputs": - [ + "inputs": [ { "indexed": false, "internalType": "uint256", @@ -18,8 +17,7 @@ Contract JSON ABI }, { "anonymous": false, - "inputs": - [ + "inputs": [ { "indexed": true, "internalType": "uint256", @@ -44,8 +42,7 @@ Contract JSON ABI [ { "anonymous": false, - "inputs": - [ + "inputs": [ { "indexed": false, "internalType": "uint256", diff --git a/test/cmdlineTests/function_debug_info/output b/test/cmdlineTests/function_debug_info/output index c359d4e1c..bd7ba1197 100644 --- a/test/cmdlineTests/function_debug_info/output +++ b/test/cmdlineTests/function_debug_info/output @@ -1,57 +1,45 @@ { - "contracts": - { - "function_debug_info/input.sol:C": - { - "function-debug": - { - "@_34": - { + "contracts": { + "function_debug_info/input.sol:C": { + "function-debug": { + "@_34": { "id": 34, "parameterSlots": 1, "returnSlots": 0 }, - "abi_decode_tuple_t_uint256_fromMemory": - { + "abi_decode_tuple_t_uint256_fromMemory": { "entryPoint": 88, "parameterSlots": 2, "returnSlots": 1 } }, - "function-debug-runtime": - { - "@f_14": - { + "function-debug-runtime": { + "@f_14": { "entryPoint": 124, "id": 14, "parameterSlots": 2, "returnSlots": 1 }, - "@t_22": - { + "@t_22": { "id": 22, "parameterSlots": 0, "returnSlots": 0 }, - "abi_decode_tuple_t_array$_t_uint256_$dyn_calldata_ptr": - { + "abi_decode_tuple_t_array$_t_uint256_$dyn_calldata_ptr": { "entryPoint": 158, "parameterSlots": 2, "returnSlots": 2 }, - "abi_decode_tuple_t_uint256": - { + "abi_decode_tuple_t_uint256": { "entryPoint": 269, "parameterSlots": 2, "returnSlots": 1 }, - "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed": - { + "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed": { "parameterSlots": 2, "returnSlots": 1 }, - "panic_error_0x32": - { + "panic_error_0x32": { "entryPoint": 292, "parameterSlots": 0, "returnSlots": 0 diff --git a/test/cmdlineTests/function_debug_info_via_yul/output b/test/cmdlineTests/function_debug_info_via_yul/output index 5af245ce4..05c2da48c 100644 --- a/test/cmdlineTests/function_debug_info_via_yul/output +++ b/test/cmdlineTests/function_debug_info_via_yul/output @@ -1,8 +1,6 @@ { - "contracts": - { - "function_debug_info_via_yul/input.sol:C": - { + "contracts": { + "function_debug_info_via_yul/input.sol:C": { "function-debug": {}, "function-debug-runtime": {} } diff --git a/test/cmdlineTests/import_asm_json_all_valid_flags/output b/test/cmdlineTests/import_asm_json_all_valid_flags/output index 837187d19..c96001047 100644 --- a/test/cmdlineTests/import_asm_json_all_valid_flags/output +++ b/test/cmdlineTests/import_asm_json_all_valid_flags/output @@ -1,12 +1,8 @@ { - "contracts": - { - "": - { - "asm": - { - ".code": - [ + "contracts": { + "": { + "asm": { + ".code": [ { "begin": -1, "end": -1, @@ -15,12 +11,9 @@ "value": "0" } ], - ".data": - { - "0": - { - ".code": - [ + ".data": { + "0": { + ".code": [ { "begin": -1, "end": -1, @@ -31,8 +24,7 @@ ] } }, - "sourceList": - [ + "sourceList": [ "contract.sol", "#utility.yul" ] @@ -44,8 +36,7 @@ "srcmap-runtime": ":::-:0" } }, - "sourceList": - [ + "sourceList": [ "contract.sol", "#utility.yul" ], @@ -57,8 +48,7 @@ Binary of the runtime part: 6001 EVM assembly: { - ".code": - [ + ".code": [ { "begin": -1, "end": -1, @@ -67,12 +57,9 @@ EVM assembly: "value": "0" } ], - ".data": - { - "0": - { - ".code": - [ + ".data": { + "0": { + ".code": [ { "begin": -1, "end": -1, @@ -83,8 +70,7 @@ EVM assembly: ] } }, - "sourceList": - [ + "sourceList": [ "contract.sol", "#utility.yul" ] diff --git a/test/cmdlineTests/inline_assembly_function_name_clash/output b/test/cmdlineTests/inline_assembly_function_name_clash/output index 8becb87ae..d7c7bf9e0 100644 --- a/test/cmdlineTests/inline_assembly_function_name_clash/output +++ b/test/cmdlineTests/inline_assembly_function_name_clash/output @@ -1,204 +1,169 @@ { - "contracts": - { - "inline_assembly_function_name_clash/input.sol:C": - { - "function-debug-runtime": - { - "abi_decode": - { + "contracts": { + "inline_assembly_function_name_clash/input.sol:C": { + "function-debug-runtime": { + "abi_decode": { "entryPoint": 80, "parameterSlots": 2, "returnSlots": 0 }, - "abi_encode_uint256": - { + "abi_encode_uint256": { "entryPoint": 111, "parameterSlots": 2, "returnSlots": 1 }, - "abi_encode_uint256_to_uint256": - { + "abi_encode_uint256_to_uint256": { "entryPoint": 98, "parameterSlots": 2, "returnSlots": 0 }, - "allocate_unbounded": - { + "allocate_unbounded": { "entryPoint": 66, "parameterSlots": 0, "returnSlots": 1 }, - "cleanup_uint256": - { + "cleanup_uint256": { "entryPoint": 95, "parameterSlots": 1, "returnSlots": 1 }, - "convert_uint256_to_uint256": - { + "convert_uint256_to_uint256": { "entryPoint": 276, "parameterSlots": 1, "returnSlots": 1 }, - "external_fun_f": - { + "external_fun_f": { "entryPoint": 132, "parameterSlots": 0, "returnSlots": 0 }, - "external_fun_g": - { + "external_fun_g": { "entryPoint": 185, "parameterSlots": 0, "returnSlots": 0 }, - "fun_f": - { + "fun_f": { "entryPoint": 442, "id": 25, "parameterSlots": 0, "returnSlots": 1 }, - "fun_f_inner": - { + "fun_f_inner": { "entryPoint": 430, "parameterSlots": 1, "returnSlots": 1 }, - "fun_g": - { + "fun_g": { "entryPoint": 564, "id": 36, "parameterSlots": 0, "returnSlots": 1 }, - "fun_g_inner": - { + "fun_g_inner": { "entryPoint": 552, "parameterSlots": 1, "returnSlots": 1 }, - "identity": - { + "identity": { "entryPoint": 273, "parameterSlots": 1, "returnSlots": 1 }, - "modifier_m": - { + "modifier_m": { "entryPoint": 509, "id": 14, "parameterSlots": 1, "returnSlots": 1 }, - "modifier_m_17": - { + "modifier_m_17": { "entryPoint": 344, "id": 14, "parameterSlots": 1, "returnSlots": 1 }, - "modifier_m_19": - { + "modifier_m_19": { "entryPoint": 387, "id": 14, "parameterSlots": 1, "returnSlots": 1 }, - "modifier_m_28": - { + "modifier_m_28": { "entryPoint": 466, "id": 14, "parameterSlots": 1, "returnSlots": 1 }, - "prepare_store_uint256": - { + "prepare_store_uint256": { "entryPoint": 304, "parameterSlots": 1, "returnSlots": 1 }, - "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": - { + "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { "entryPoint": 238, "parameterSlots": 0, "returnSlots": 0 }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": - { + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { "entryPoint": 72, "parameterSlots": 0, "returnSlots": 0 }, - "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": - { + "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { "entryPoint": 76, "parameterSlots": 0, "returnSlots": 0 }, - "shift_left": - { + "shift_left": { "entryPoint": 246, "parameterSlots": 1, "returnSlots": 1 }, - "shift_right_unsigned": - { + "shift_right_unsigned": { "entryPoint": 60, "parameterSlots": 1, "returnSlots": 1 }, - "update_byte_slice_shift": - { + "update_byte_slice_shift": { "entryPoint": 251, "parameterSlots": 2, "returnSlots": 1 }, - "update_storage_value_offsett_uint256_to_uint256": - { + "update_storage_value_offsett_uint256_to_uint256": { "entryPoint": 307, "parameterSlots": 2, "returnSlots": 0 }, - "usr$f": - { + "usr$f": { "entryPoint": 339, "parameterSlots": 0, "returnSlots": 1 }, - "usr$f_17": - { + "usr$f_17": { "entryPoint": 382, "parameterSlots": 0, "returnSlots": 1 }, - "usr$f_22": - { + "usr$f_22": { "entryPoint": 425, "parameterSlots": 0, "returnSlots": 1 }, - "usr$f_26": - { + "usr$f_26": { "entryPoint": 461, "parameterSlots": 0, "returnSlots": 1 }, - "usr$f_32": - { + "usr$f_32": { "entryPoint": 504, "parameterSlots": 0, "returnSlots": 1 }, - "usr$f_37": - { + "usr$f_37": { "entryPoint": 547, "parameterSlots": 0, "returnSlots": 1 }, - "zero_value_for_split_uint256": - { + "zero_value_for_split_uint256": { "entryPoint": 242, "parameterSlots": 0, "returnSlots": 1 diff --git a/test/cmdlineTests/linking_standard_solidity/output.json b/test/cmdlineTests/linking_standard_solidity/output.json index 83813d806..1e49af2ca 100644 --- a/test/cmdlineTests/linking_standard_solidity/output.json +++ b/test/cmdlineTests/linking_standard_solidity/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "A": - { - "C": - { - "evm": - { - "bytecode": - { + "contracts": { + "A": { + "C": { + "evm": { + "bytecode": { "linkReferences": {}, "object": "" } @@ -16,10 +11,8 @@ } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/linking_standard_solidity_quote_in_file_name/output.json b/test/cmdlineTests/linking_standard_solidity_quote_in_file_name/output.json index 38e0a1b5a..87e80b8d1 100644 --- a/test/cmdlineTests/linking_standard_solidity_quote_in_file_name/output.json +++ b/test/cmdlineTests/linking_standard_solidity_quote_in_file_name/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "A\"B": - { - "C": - { - "evm": - { - "bytecode": - { + "contracts": { + "A\"B": { + "C": { + "evm": { + "bytecode": { "linkReferences": {}, "object": "" } @@ -16,10 +11,8 @@ } } }, - "sources": - { - "A\"B": - { + "sources": { + "A\"B": { "id": 0 } } diff --git a/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json b/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json index 3a69e3e2d..71c17347a 100644 --- a/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json +++ b/test/cmdlineTests/linking_standard_solidity_unresolved_references/output.json @@ -1,20 +1,12 @@ { - "contracts": - { - "A": - { - "C": - { - "evm": - { - "bytecode": - { - "linkReferences": - { - "A": - { - "L2": - [ + "contracts": { + "A": { + "C": { + "evm": { + "bytecode": { + "linkReferences": { + "A": { + "L2": [ { "length": 20, "start": 173 @@ -32,10 +24,8 @@ } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/linking_standard_yul/output.json b/test/cmdlineTests/linking_standard_yul/output.json index b9059bdfd..90445cfe0 100644 --- a/test/cmdlineTests/linking_standard_yul/output.json +++ b/test/cmdlineTests/linking_standard_yul/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "A": - { - "a": - { - "evm": - { - "bytecode": - { + "contracts": { + "A": { + "a": { + "evm": { + "bytecode": { "linkReferences": {}, "object": "" } diff --git a/test/cmdlineTests/linking_standard_yul_quote_in_file_name/output.json b/test/cmdlineTests/linking_standard_yul_quote_in_file_name/output.json index b9059bdfd..90445cfe0 100644 --- a/test/cmdlineTests/linking_standard_yul_quote_in_file_name/output.json +++ b/test/cmdlineTests/linking_standard_yul_quote_in_file_name/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "A": - { - "a": - { - "evm": - { - "bytecode": - { + "contracts": { + "A": { + "a": { + "evm": { + "bytecode": { "linkReferences": {}, "object": "" } diff --git a/test/cmdlineTests/linking_standard_yul_unresolved_references/output.json b/test/cmdlineTests/linking_standard_yul_unresolved_references/output.json index ac1250cd4..041e8206b 100644 --- a/test/cmdlineTests/linking_standard_yul_unresolved_references/output.json +++ b/test/cmdlineTests/linking_standard_yul_unresolved_references/output.json @@ -1,20 +1,12 @@ { - "contracts": - { - "A": - { - "a": - { - "evm": - { - "bytecode": - { - "linkReferences": - { - "contract/test.sol": - { - "L2": - [ + "contracts": { + "A": { + "a": { + "evm": { + "bytecode": { + "linkReferences": { + "contract/test.sol": { + "L2": [ { "length": 20, "start": 22 diff --git a/test/cmdlineTests/no_contract_combined_json/output b/test/cmdlineTests/no_contract_combined_json/output index e0caa6fa1..8c454e341 100644 --- a/test/cmdlineTests/no_contract_combined_json/output +++ b/test/cmdlineTests/no_contract_combined_json/output @@ -1,25 +1,19 @@ { - "sourceList": - [ + "sourceList": [ "no_contract_combined_json/input.sol" ], - "sources": - { - "no_contract_combined_json/input.sol": - { - "AST": - { + "sources": { + "no_contract_combined_json/input.sol": { + "AST": { "absolutePath": "no_contract_combined_json/input.sol", "exportedSymbols": {}, "id": 2, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", ">=", "0.0" diff --git a/test/cmdlineTests/output_selection_all_A1/output.json b/test/cmdlineTests/output_selection_all_A1/output.json index b21b632bd..e28a8af25 100644 --- a/test/cmdlineTests/output_selection_all_A1/output.json +++ b/test/cmdlineTests/output_selection_all_A1/output.json @@ -1,41 +1,29 @@ { - "contracts": - { - "a.sol": - { - "A1": - { - "evm": - { - "bytecode": - { + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { "object": "" } } } }, - "b.sol": - { - "A1": - { - "evm": - { - "bytecode": - { + "b.sol": { + "A1": { + "evm": { + "bytecode": { "object": "" } } } } }, - "sources": - { - "a.sol": - { + "sources": { + "a.sol": { "id": 0 }, - "b.sol": - { + "b.sol": { "id": 1 } } diff --git a/test/cmdlineTests/output_selection_all_A2/output.json b/test/cmdlineTests/output_selection_all_A2/output.json index c33941c2f..9e6ea3b0e 100644 --- a/test/cmdlineTests/output_selection_all_A2/output.json +++ b/test/cmdlineTests/output_selection_all_A2/output.json @@ -1,28 +1,20 @@ { - "contracts": - { - "a.sol": - { - "A2": - { - "evm": - { - "bytecode": - { + "contracts": { + "a.sol": { + "A2": { + "evm": { + "bytecode": { "object": "" } } } } }, - "sources": - { - "a.sol": - { + "sources": { + "a.sol": { "id": 0 }, - "b.sol": - { + "b.sol": { "id": 1 } } diff --git a/test/cmdlineTests/output_selection_all_blank/output.json b/test/cmdlineTests/output_selection_all_blank/output.json index b4c60911c..d05ed608c 100644 --- a/test/cmdlineTests/output_selection_all_blank/output.json +++ b/test/cmdlineTests/output_selection_all_blank/output.json @@ -1,12 +1,9 @@ { - "sources": - { - "a.sol": - { + "sources": { + "a.sol": { "id": 0 }, - "b.sol": - { + "b.sol": { "id": 1 } } diff --git a/test/cmdlineTests/output_selection_all_star/output.json b/test/cmdlineTests/output_selection_all_star/output.json index f70963621..668c4b423 100644 --- a/test/cmdlineTests/output_selection_all_star/output.json +++ b/test/cmdlineTests/output_selection_all_star/output.json @@ -1,61 +1,43 @@ { - "contracts": - { - "a.sol": - { - "A1": - { - "evm": - { - "bytecode": - { + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { "object": "" } } }, - "A2": - { - "evm": - { - "bytecode": - { + "A2": { + "evm": { + "bytecode": { "object": "" } } } }, - "b.sol": - { - "A1": - { - "evm": - { - "bytecode": - { + "b.sol": { + "A1": { + "evm": { + "bytecode": { "object": "" } } }, - "B2": - { - "evm": - { - "bytecode": - { + "B2": { + "evm": { + "bytecode": { "object": "" } } } } }, - "sources": - { - "a.sol": - { + "sources": { + "a.sol": { "id": 0 }, - "b.sol": - { + "b.sol": { "id": 1 } } diff --git a/test/cmdlineTests/output_selection_single_A1/output.json b/test/cmdlineTests/output_selection_single_A1/output.json index ab44a2d54..137b19cc0 100644 --- a/test/cmdlineTests/output_selection_single_A1/output.json +++ b/test/cmdlineTests/output_selection_single_A1/output.json @@ -1,28 +1,20 @@ { - "contracts": - { - "a.sol": - { - "A1": - { - "evm": - { - "bytecode": - { + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { "object": "" } } } } }, - "sources": - { - "a.sol": - { + "sources": { + "a.sol": { "id": 0 }, - "b.sol": - { + "b.sol": { "id": 1 } } diff --git a/test/cmdlineTests/output_selection_single_B1/output.json b/test/cmdlineTests/output_selection_single_B1/output.json index ffaf266b4..87dd70b3a 100644 --- a/test/cmdlineTests/output_selection_single_B1/output.json +++ b/test/cmdlineTests/output_selection_single_B1/output.json @@ -1,28 +1,20 @@ { - "contracts": - { - "b.sol": - { - "B2": - { - "evm": - { - "bytecode": - { + "contracts": { + "b.sol": { + "B2": { + "evm": { + "bytecode": { "object": "" } } } } }, - "sources": - { - "a.sol": - { + "sources": { + "a.sol": { "id": 0 }, - "b.sol": - { + "b.sol": { "id": 1 } } diff --git a/test/cmdlineTests/output_selection_single_all/output.json b/test/cmdlineTests/output_selection_single_all/output.json index 52d04cb18..123f43713 100644 --- a/test/cmdlineTests/output_selection_single_all/output.json +++ b/test/cmdlineTests/output_selection_single_all/output.json @@ -1,38 +1,27 @@ { - "contracts": - { - "a.sol": - { - "A1": - { - "evm": - { - "bytecode": - { + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { "object": "" } } }, - "A2": - { - "evm": - { - "bytecode": - { + "A2": { + "evm": { + "bytecode": { "object": "" } } } } }, - "sources": - { - "a.sol": - { + "sources": { + "a.sol": { "id": 0 }, - "b.sol": - { + "b.sol": { "id": 1 } } diff --git a/test/cmdlineTests/pretty_json_indent_only/output.json b/test/cmdlineTests/pretty_json_indent_only/output.json index 80d51c4f1..eeefefbd7 100644 --- a/test/cmdlineTests/pretty_json_indent_only/output.json +++ b/test/cmdlineTests/pretty_json_indent_only/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/pretty_json_standard/output.json b/test/cmdlineTests/pretty_json_standard/output.json index 29185e758..96281af4e 100644 --- a/test/cmdlineTests/pretty_json_standard/output.json +++ b/test/cmdlineTests/pretty_json_standard/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/pretty_json_standard_indent/output.json b/test/cmdlineTests/pretty_json_standard_indent/output.json index 80d51c4f1..eeefefbd7 100644 --- a/test/cmdlineTests/pretty_json_standard_indent/output.json +++ b/test/cmdlineTests/pretty_json_standard_indent/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json index 97041b238..642d07f49 100644 --- a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "C": - { - "C": - { - "evm": - { + "contracts": { + "C": { + "C": { + "evm": { "assembly": " /* \"C\":79:503 contract C... */ 0xa0 jumpi(tag_5, callvalue) @@ -350,12 +346,9 @@ sub_0: assembly { } } }, - "D": - { - "D": - { - "evm": - { + "D": { + "D": { + "evm": { "assembly": " /* \"D\":91:181 contract D is C(3)... */ 0xa0 jumpi(tag_5, callvalue) @@ -716,14 +709,11 @@ sub_0: assembly { } } }, - "sources": - { - "C": - { + "sources": { + "C": { "id": 0 }, - "D": - { + "D": { "id": 1 } } diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json index ee958b55b..9489a75bf 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "C": - { - "C": - { - "evm": - { + "contracts": { + "C": { + "C": { + "evm": { "assembly": " /* \"C\":60:101 contract C {... */ mstore(0x40, 0x80) callvalue @@ -211,10 +207,8 @@ object \"C_6\" { } } }, - "sources": - { - "C": - { + "sources": { + "C": { "id": 0 } } diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json index 007b7fc62..f8f2958b0 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "C": - { - "C": - { - "evm": - { + "contracts": { + "C": { + "C": { + "evm": { "assembly": " /* \"C\":60:101 */ mstore(0x40, 0x80) callvalue @@ -210,10 +206,8 @@ object \"C_6\" { } } }, - "sources": - { - "C": - { + "sources": { + "C": { "id": 0 } } diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json index 884da9eb9..2a5a2bc2a 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "C": - { - "C": - { - "evm": - { + "contracts": { + "C": { + "C": { + "evm": { "assembly": " mstore(0x40, 0x80) callvalue dup1 @@ -199,10 +195,8 @@ object \"C_6\" { } } }, - "sources": - { - "C": - { + "sources": { + "C": { "id": 0 } } diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/output.json index fb7f199a7..7f48fd4e9 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "To use 'snippet' with settings.debug.debugInfo you must select also 'location'.", diff --git a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json index 54748658f..3e687cc1a 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json @@ -1,10 +1,7 @@ { - "contracts": - { - "C": - { - "C": - { + "contracts": { + "C": { + "C": { "ir": " /// @use-src 0:\"C\" object \"C_54\" { @@ -769,10 +766,8 @@ object \"C_54\" { " } }, - "D": - { - "D": - { + "D": { + "D": { "ir": " /// @use-src 0:\"C\", 1:\"D\" object \"D_72\" { @@ -1615,14 +1610,11 @@ object \"D_72\" { } } }, - "sources": - { - "C": - { + "sources": { + "C": { "id": 0 }, - "D": - { + "D": { "id": 1 } } diff --git a/test/cmdlineTests/standard_default_success/output.json b/test/cmdlineTests/standard_default_success/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_default_success/output.json +++ b/test/cmdlineTests/standard_default_success/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_empty_file_name/output.json b/test/cmdlineTests/standard_empty_file_name/output.json index 4e4d84c41..1fd016e54 100644 --- a/test/cmdlineTests/standard_empty_file_name/output.json +++ b/test/cmdlineTests/standard_empty_file_name/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2904", @@ -9,8 +8,7 @@ ", "message": "Declaration \"A\" not found in \"\" (referenced as \".\").", "severity": "error", - "sourceLocation": - { + "sourceLocation": { "end": 79, "file": "", "start": 59 diff --git a/test/cmdlineTests/standard_evm_version_byzantium/output.json b/test/cmdlineTests/standard_evm_version_byzantium/output.json index b2428b105..36570f9c2 100644 --- a/test/cmdlineTests/standard_evm_version_byzantium/output.json +++ b/test/cmdlineTests/standard_evm_version_byzantium/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Support for EVM versions older than constantinople is deprecated and will be removed in the future.", @@ -9,10 +8,8 @@ "type": "Warning" } ], - "sources": - { - "input.sol": - { + "sources": { + "input.sol": { "id": 0 } } diff --git a/test/cmdlineTests/standard_evm_version_constantinople/output.json b/test/cmdlineTests/standard_evm_version_constantinople/output.json index 1ce414a4c..81fa23ff6 100644 --- a/test/cmdlineTests/standard_evm_version_constantinople/output.json +++ b/test/cmdlineTests/standard_evm_version_constantinople/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "input.sol": - { + "sources": { + "input.sol": { "id": 0 } } diff --git a/test/cmdlineTests/standard_function_debug_info/output.json b/test/cmdlineTests/standard_function_debug_info/output.json index bbbb6b96f..645e1646a 100644 --- a/test/cmdlineTests/standard_function_debug_info/output.json +++ b/test/cmdlineTests/standard_function_debug_info/output.json @@ -1,169 +1,140 @@ { - "contracts": - { - "a.sol": - { - "A": - { - "evm": - { - "bytecode": - { + "contracts": { + "a.sol": { + "A": { + "evm": { + "bytecode": { "functionDebugData": {} }, - "deployedBytecode": - { - "functionDebugData": - { - "@f_19": - { + "deployedBytecode": { + "functionDebugData": { + "@f_19": { "entryPoint": 93, "id": 19, "parameterSlots": 1, "returnSlots": 1 }, - "abi_decode_available_length_t_array$_t_uint256_$dyn_memory_ptr": - { + "abi_decode_available_length_t_array$_t_uint256_$dyn_memory_ptr": { "entryPoint": 421, "id": null, "parameterSlots": 3, "returnSlots": 1 }, - "abi_decode_t_array$_t_uint256_$dyn_memory_ptr": - { + "abi_decode_t_array$_t_uint256_$dyn_memory_ptr": { "entryPoint": 525, "id": null, "parameterSlots": 2, "returnSlots": 1 }, - "abi_decode_t_uint256": - { + "abi_decode_t_uint256": { "entryPoint": 401, "id": null, "parameterSlots": 2, "returnSlots": 1 }, - "abi_decode_tuple_t_array$_t_uint256_$dyn_memory_ptr": - { + "abi_decode_tuple_t_array$_t_uint256_$dyn_memory_ptr": { "entryPoint": 570, "id": null, "parameterSlots": 2, "returnSlots": 1 }, - "abi_encode_t_uint256_to_t_uint256_fromStack": - { + "abi_encode_t_uint256_to_t_uint256_fromStack": { "entryPoint": 641, "id": null, "parameterSlots": 2, "returnSlots": 0 }, - "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed": - { + "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed": { "entryPoint": 656, "id": null, "parameterSlots": 2, "returnSlots": 1 }, - "allocate_memory": - { + "allocate_memory": { "entryPoint": 297, "id": null, "parameterSlots": 1, "returnSlots": 1 }, - "allocate_unbounded": - { + "allocate_unbounded": { "entryPoint": 166, "id": null, "parameterSlots": 0, "returnSlots": 1 }, - "array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr": - { + "array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr": { "entryPoint": 323, "id": null, "parameterSlots": 1, "returnSlots": 1 }, - "checked_add_t_uint256": - { + "checked_add_t_uint256": { "entryPoint": 771, "id": null, "parameterSlots": 2, "returnSlots": 1 }, - "cleanup_t_uint256": - { + "cleanup_t_uint256": { "entryPoint": 370, "id": null, "parameterSlots": 1, "returnSlots": 1 }, - "finalize_allocation": - { + "finalize_allocation": { "entryPoint": 248, "id": null, "parameterSlots": 2, "returnSlots": 0 }, - "panic_error_0x11": - { + "panic_error_0x11": { "entryPoint": 726, "id": null, "parameterSlots": 0, "returnSlots": 0 }, - "panic_error_0x32": - { + "panic_error_0x32": { "entryPoint": 681, "id": null, "parameterSlots": 0, "returnSlots": 0 }, - "panic_error_0x41": - { + "panic_error_0x41": { "entryPoint": 203, "id": null, "parameterSlots": 0, "returnSlots": 0 }, - "revert_error_1b9f4a0a5773e33b91aa01db23bf8c55fce1411167c872835e7fa00a4f17d46d": - { + "revert_error_1b9f4a0a5773e33b91aa01db23bf8c55fce1411167c872835e7fa00a4f17d46d": { "entryPoint": 183, "id": null, "parameterSlots": 0, "returnSlots": 0 }, - "revert_error_81385d8c0b31fffe14be1da910c8bd3a80be4cfa248e04f42ec0faea3132a8ef": - { + "revert_error_81385d8c0b31fffe14be1da910c8bd3a80be4cfa248e04f42ec0faea3132a8ef": { "entryPoint": 366, "id": null, "parameterSlots": 0, "returnSlots": 0 }, - "revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db": - { + "revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db": { "entryPoint": 179, "id": null, "parameterSlots": 0, "returnSlots": 0 }, - "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": - { + "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { "entryPoint": 175, "id": null, "parameterSlots": 0, "returnSlots": 0 }, - "round_up_to_mul_of_32": - { + "round_up_to_mul_of_32": { "entryPoint": 187, "id": null, "parameterSlots": 1, "returnSlots": 1 }, - "validator_revert_t_uint256": - { + "validator_revert_t_uint256": { "entryPoint": 379, "id": null, "parameterSlots": 1, @@ -175,10 +146,8 @@ } } }, - "sources": - { - "a.sol": - { + "sources": { + "a.sol": { "id": 0 } } diff --git a/test/cmdlineTests/standard_generatedSources/output.json b/test/cmdlineTests/standard_generatedSources/output.json index 350d10899..4fb0b3dcc 100644 --- a/test/cmdlineTests/standard_generatedSources/output.json +++ b/test/cmdlineTests/standard_generatedSources/output.json @@ -1,45 +1,32 @@ { - "contracts": - { - "a.sol": - { - "A": - { - "evm": - { - "bytecode": - { + "contracts": { + "a.sol": { + "A": { + "evm": { + "bytecode": { "generatedSources": [], "object": "" }, - "deployedBytecode": - { - "generatedSources": - [ + "deployedBytecode": { + "generatedSources": [ { - "ast": - { + "ast": { "nativeSrc": "0:3989:1", "nodeType": "YulBlock", "src": "0:3989:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "47:35:1", "nodeType": "YulBlock", "src": "47:35:1", - "statements": - [ + "statements": [ { "nativeSrc": "57:19:1", "nodeType": "YulAssignment", "src": "57:19:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "73:2:1", @@ -49,8 +36,7 @@ "value": "64" } ], - "functionName": - { + "functionName": { "name": "mload", "nativeSrc": "67:5:1", "nodeType": "YulIdentifier", @@ -60,8 +46,7 @@ "nodeType": "YulFunctionCall", "src": "67:9:1" }, - "variableNames": - [ + "variableNames": [ { "name": "memPtr", "nativeSrc": "57:6:1", @@ -75,8 +60,7 @@ "name": "allocate_unbounded", "nativeSrc": "7:75:1", "nodeType": "YulFunctionDefinition", - "returnVariables": - [ + "returnVariables": [ { "name": "memPtr", "nativeSrc": "40:6:1", @@ -88,18 +72,14 @@ "src": "7:75:1" }, { - "body": - { + "body": { "nativeSrc": "177:28:1", "nodeType": "YulBlock", "src": "177:28:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "194:1:1", @@ -117,8 +97,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "187:6:1", "nodeType": "YulIdentifier", @@ -140,18 +119,14 @@ "src": "88:117:1" }, { - "body": - { + "body": { "nativeSrc": "300:28:1", "nodeType": "YulBlock", "src": "300:28:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "317:1:1", @@ -169,8 +144,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "310:6:1", "nodeType": "YulIdentifier", @@ -192,18 +166,14 @@ "src": "211:117:1" }, { - "body": - { + "body": { "nativeSrc": "423:28:1", "nodeType": "YulBlock", "src": "423:28:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "440:1:1", @@ -221,8 +191,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "433:6:1", "nodeType": "YulIdentifier", @@ -244,24 +213,19 @@ "src": "334:117:1" }, { - "body": - { + "body": { "nativeSrc": "505:54:1", "nodeType": "YulBlock", "src": "505:54:1", - "statements": - [ + "statements": [ { "nativeSrc": "515:38:1", "nodeType": "YulAssignment", "src": "515:38:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "value", "nativeSrc": "533:5:1", @@ -277,8 +241,7 @@ "value": "31" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "529:3:1", "nodeType": "YulIdentifier", @@ -289,8 +252,7 @@ "src": "529:14:1" }, { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "549:2:1", @@ -300,8 +262,7 @@ "value": "31" } ], - "functionName": - { + "functionName": { "name": "not", "nativeSrc": "545:3:1", "nodeType": "YulIdentifier", @@ -312,8 +273,7 @@ "src": "545:7:1" } ], - "functionName": - { + "functionName": { "name": "and", "nativeSrc": "525:3:1", "nodeType": "YulIdentifier", @@ -323,8 +283,7 @@ "nodeType": "YulFunctionCall", "src": "525:28:1" }, - "variableNames": - [ + "variableNames": [ { "name": "result", "nativeSrc": "515:6:1", @@ -338,8 +297,7 @@ "name": "round_up_to_mul_of_32", "nativeSrc": "457:102:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "value", "nativeSrc": "488:5:1", @@ -348,8 +306,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "result", "nativeSrc": "498:6:1", @@ -361,18 +318,14 @@ "src": "457:102:1" }, { - "body": - { + "body": { "nativeSrc": "593:152:1", "nodeType": "YulBlock", "src": "593:152:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "610:1:1", @@ -390,8 +343,7 @@ "value": "35408467139433450592217433187231851964531694900788300625387963629091585785856" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "603:6:1", "nodeType": "YulIdentifier", @@ -406,10 +358,8 @@ "src": "603:88:1" }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "707:1:1", @@ -427,8 +377,7 @@ "value": "0x41" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "700:6:1", "nodeType": "YulIdentifier", @@ -443,10 +392,8 @@ "src": "700:15:1" }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "731:1:1", @@ -464,8 +411,7 @@ "value": "0x24" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "724:6:1", "nodeType": "YulIdentifier", @@ -487,21 +433,17 @@ "src": "565:180:1" }, { - "body": - { + "body": { "nativeSrc": "794:238:1", "nodeType": "YulBlock", "src": "794:238:1", - "statements": - [ + "statements": [ { "nativeSrc": "804:58:1", "nodeType": "YulVariableDeclaration", "src": "804:58:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "memPtr", "nativeSrc": "826:6:1", @@ -509,8 +451,7 @@ "src": "826:6:1" }, { - "arguments": - [ + "arguments": [ { "name": "size", "nativeSrc": "856:4:1", @@ -518,8 +459,7 @@ "src": "856:4:1" } ], - "functionName": - { + "functionName": { "name": "round_up_to_mul_of_32", "nativeSrc": "834:21:1", "nodeType": "YulIdentifier", @@ -530,8 +470,7 @@ "src": "834:27:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "822:3:1", "nodeType": "YulIdentifier", @@ -541,8 +480,7 @@ "nodeType": "YulFunctionCall", "src": "822:40:1" }, - "variables": - [ + "variables": [ { "name": "newFreePtr", "nativeSrc": "808:10:1", @@ -553,19 +491,15 @@ ] }, { - "body": - { + "body": { "nativeSrc": "973:22:1", "nodeType": "YulBlock", "src": "973:22:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "panic_error_0x41", "nativeSrc": "975:16:1", "nodeType": "YulIdentifier", @@ -581,13 +515,10 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "newFreePtr", "nativeSrc": "916:10:1", @@ -603,8 +534,7 @@ "value": "0xffffffffffffffff" } ], - "functionName": - { + "functionName": { "name": "gt", "nativeSrc": "913:2:1", "nodeType": "YulIdentifier", @@ -615,8 +545,7 @@ "src": "913:34:1" }, { - "arguments": - [ + "arguments": [ { "name": "newFreePtr", "nativeSrc": "952:10:1", @@ -630,8 +559,7 @@ "src": "964:6:1" } ], - "functionName": - { + "functionName": { "name": "lt", "nativeSrc": "949:2:1", "nodeType": "YulIdentifier", @@ -642,8 +570,7 @@ "src": "949:22:1" } ], - "functionName": - { + "functionName": { "name": "or", "nativeSrc": "910:2:1", "nodeType": "YulIdentifier", @@ -658,10 +585,8 @@ "src": "907:88:1" }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "1011:2:1", @@ -677,8 +602,7 @@ "src": "1015:10:1" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "1004:6:1", "nodeType": "YulIdentifier", @@ -697,8 +621,7 @@ "name": "finalize_allocation", "nativeSrc": "751:281:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "memPtr", "nativeSrc": "780:6:1", @@ -717,22 +640,18 @@ "src": "751:281:1" }, { - "body": - { + "body": { "nativeSrc": "1079:88:1", "nodeType": "YulBlock", "src": "1079:88:1", - "statements": - [ + "statements": [ { "nativeSrc": "1089:30:1", "nodeType": "YulAssignment", "src": "1089:30:1", - "value": - { + "value": { "arguments": [], - "functionName": - { + "functionName": { "name": "allocate_unbounded", "nativeSrc": "1099:18:1", "nodeType": "YulIdentifier", @@ -742,8 +661,7 @@ "nodeType": "YulFunctionCall", "src": "1099:20:1" }, - "variableNames": - [ + "variableNames": [ { "name": "memPtr", "nativeSrc": "1089:6:1", @@ -753,10 +671,8 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "memPtr", "nativeSrc": "1148:6:1", @@ -770,8 +686,7 @@ "src": "1156:4:1" } ], - "functionName": - { + "functionName": { "name": "finalize_allocation", "nativeSrc": "1128:19:1", "nodeType": "YulIdentifier", @@ -790,8 +705,7 @@ "name": "allocate_memory", "nativeSrc": "1038:129:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "size", "nativeSrc": "1063:4:1", @@ -800,8 +714,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "memPtr", "nativeSrc": "1072:6:1", @@ -813,27 +726,21 @@ "src": "1038:129:1" }, { - "body": - { + "body": { "nativeSrc": "1255:229:1", "nodeType": "YulBlock", "src": "1255:229:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "1360:22:1", "nodeType": "YulBlock", "src": "1360:22:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "panic_error_0x41", "nativeSrc": "1362:16:1", "nodeType": "YulIdentifier", @@ -849,10 +756,8 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { "name": "length", "nativeSrc": "1332:6:1", @@ -868,8 +773,7 @@ "value": "0xffffffffffffffff" } ], - "functionName": - { + "functionName": { "name": "gt", "nativeSrc": "1329:2:1", "nodeType": "YulIdentifier", @@ -887,10 +791,8 @@ "nativeSrc": "1392:25:1", "nodeType": "YulAssignment", "src": "1392:25:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "length", "nativeSrc": "1404:6:1", @@ -906,8 +808,7 @@ "value": "0x20" } ], - "functionName": - { + "functionName": { "name": "mul", "nativeSrc": "1400:3:1", "nodeType": "YulIdentifier", @@ -917,8 +818,7 @@ "nodeType": "YulFunctionCall", "src": "1400:17:1" }, - "variableNames": - [ + "variableNames": [ { "name": "size", "nativeSrc": "1392:4:1", @@ -931,10 +831,8 @@ "nativeSrc": "1454:23:1", "nodeType": "YulAssignment", "src": "1454:23:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "size", "nativeSrc": "1466:4:1", @@ -950,8 +848,7 @@ "value": "0x20" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "1462:3:1", "nodeType": "YulIdentifier", @@ -961,8 +858,7 @@ "nodeType": "YulFunctionCall", "src": "1462:15:1" }, - "variableNames": - [ + "variableNames": [ { "name": "size", "nativeSrc": "1454:4:1", @@ -976,8 +872,7 @@ "name": "array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr", "nativeSrc": "1173:311:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "length", "nativeSrc": "1239:6:1", @@ -986,8 +881,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "size", "nativeSrc": "1250:4:1", @@ -999,18 +893,14 @@ "src": "1173:311:1" }, { - "body": - { + "body": { "nativeSrc": "1579:28:1", "nodeType": "YulBlock", "src": "1579:28:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "1596:1:1", @@ -1028,8 +918,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "1589:6:1", "nodeType": "YulIdentifier", @@ -1051,26 +940,22 @@ "src": "1490:117:1" }, { - "body": - { + "body": { "nativeSrc": "1658:32:1", "nodeType": "YulBlock", "src": "1658:32:1", - "statements": - [ + "statements": [ { "nativeSrc": "1668:16:1", "nodeType": "YulAssignment", "src": "1668:16:1", - "value": - { + "value": { "name": "value", "nativeSrc": "1679:5:1", "nodeType": "YulIdentifier", "src": "1679:5:1" }, - "variableNames": - [ + "variableNames": [ { "name": "cleaned", "nativeSrc": "1668:7:1", @@ -1084,8 +969,7 @@ "name": "cleanup_t_uint256", "nativeSrc": "1613:77:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "value", "nativeSrc": "1640:5:1", @@ -1094,8 +978,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "cleaned", "nativeSrc": "1650:7:1", @@ -1107,26 +990,20 @@ "src": "1613:77:1" }, { - "body": - { + "body": { "nativeSrc": "1739:79:1", "nodeType": "YulBlock", "src": "1739:79:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "1796:16:1", "nodeType": "YulBlock", "src": "1796:16:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "1805:1:1", @@ -1144,8 +1021,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "1798:6:1", "nodeType": "YulIdentifier", @@ -1161,13 +1037,10 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "value", "nativeSrc": "1762:5:1", @@ -1175,8 +1048,7 @@ "src": "1762:5:1" }, { - "arguments": - [ + "arguments": [ { "name": "value", "nativeSrc": "1787:5:1", @@ -1184,8 +1056,7 @@ "src": "1787:5:1" } ], - "functionName": - { + "functionName": { "name": "cleanup_t_uint256", "nativeSrc": "1769:17:1", "nodeType": "YulIdentifier", @@ -1196,8 +1067,7 @@ "src": "1769:24:1" } ], - "functionName": - { + "functionName": { "name": "eq", "nativeSrc": "1759:2:1", "nodeType": "YulIdentifier", @@ -1208,8 +1078,7 @@ "src": "1759:35:1" } ], - "functionName": - { + "functionName": { "name": "iszero", "nativeSrc": "1752:6:1", "nodeType": "YulIdentifier", @@ -1228,8 +1097,7 @@ "name": "validator_revert_t_uint256", "nativeSrc": "1696:122:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "value", "nativeSrc": "1732:5:1", @@ -1241,21 +1109,17 @@ "src": "1696:122:1" }, { - "body": - { + "body": { "nativeSrc": "1876:87:1", "nodeType": "YulBlock", "src": "1876:87:1", - "statements": - [ + "statements": [ { "nativeSrc": "1886:29:1", "nodeType": "YulAssignment", "src": "1886:29:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "offset", "nativeSrc": "1908:6:1", @@ -1263,8 +1127,7 @@ "src": "1908:6:1" } ], - "functionName": - { + "functionName": { "name": "calldataload", "nativeSrc": "1895:12:1", "nodeType": "YulIdentifier", @@ -1274,8 +1137,7 @@ "nodeType": "YulFunctionCall", "src": "1895:20:1" }, - "variableNames": - [ + "variableNames": [ { "name": "value", "nativeSrc": "1886:5:1", @@ -1285,10 +1147,8 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "value", "nativeSrc": "1951:5:1", @@ -1296,8 +1156,7 @@ "src": "1951:5:1" } ], - "functionName": - { + "functionName": { "name": "validator_revert_t_uint256", "nativeSrc": "1924:26:1", "nodeType": "YulIdentifier", @@ -1316,8 +1175,7 @@ "name": "abi_decode_t_uint256", "nativeSrc": "1824:139:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "offset", "nativeSrc": "1854:6:1", @@ -1333,8 +1191,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "value", "nativeSrc": "1870:5:1", @@ -1346,24 +1203,19 @@ "src": "1824:139:1" }, { - "body": - { + "body": { "nativeSrc": "2088:608:1", "nodeType": "YulBlock", "src": "2088:608:1", - "statements": - [ + "statements": [ { "nativeSrc": "2098:90:1", "nodeType": "YulAssignment", "src": "2098:90:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "length", "nativeSrc": "2180:6:1", @@ -1371,8 +1223,7 @@ "src": "2180:6:1" } ], - "functionName": - { + "functionName": { "name": "array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr", "nativeSrc": "2123:56:1", "nodeType": "YulIdentifier", @@ -1383,8 +1234,7 @@ "src": "2123:64:1" } ], - "functionName": - { + "functionName": { "name": "allocate_memory", "nativeSrc": "2107:15:1", "nodeType": "YulIdentifier", @@ -1394,8 +1244,7 @@ "nodeType": "YulFunctionCall", "src": "2107:81:1" }, - "variableNames": - [ + "variableNames": [ { "name": "array", "nativeSrc": "2098:5:1", @@ -1408,15 +1257,13 @@ "nativeSrc": "2197:16:1", "nodeType": "YulVariableDeclaration", "src": "2197:16:1", - "value": - { + "value": { "name": "array", "nativeSrc": "2208:5:1", "nodeType": "YulIdentifier", "src": "2208:5:1" }, - "variables": - [ + "variables": [ { "name": "dst", "nativeSrc": "2201:3:1", @@ -1427,10 +1274,8 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "array", "nativeSrc": "2230:5:1", @@ -1444,8 +1289,7 @@ "src": "2237:6:1" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "2223:6:1", "nodeType": "YulIdentifier", @@ -1463,10 +1307,8 @@ "nativeSrc": "2253:23:1", "nodeType": "YulAssignment", "src": "2253:23:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "array", "nativeSrc": "2264:5:1", @@ -1482,8 +1324,7 @@ "value": "0x20" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "2260:3:1", "nodeType": "YulIdentifier", @@ -1493,8 +1334,7 @@ "nodeType": "YulFunctionCall", "src": "2260:16:1" }, - "variableNames": - [ + "variableNames": [ { "name": "dst", "nativeSrc": "2253:3:1", @@ -1507,10 +1347,8 @@ "nativeSrc": "2286:44:1", "nodeType": "YulVariableDeclaration", "src": "2286:44:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "offset", "nativeSrc": "2304:6:1", @@ -1518,8 +1356,7 @@ "src": "2304:6:1" }, { - "arguments": - [ + "arguments": [ { "name": "length", "nativeSrc": "2316:6:1", @@ -1535,8 +1372,7 @@ "value": "0x20" } ], - "functionName": - { + "functionName": { "name": "mul", "nativeSrc": "2312:3:1", "nodeType": "YulIdentifier", @@ -1547,8 +1383,7 @@ "src": "2312:17:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "2300:3:1", "nodeType": "YulIdentifier", @@ -1558,8 +1393,7 @@ "nodeType": "YulFunctionCall", "src": "2300:30:1" }, - "variables": - [ + "variables": [ { "name": "srcEnd", "nativeSrc": "2290:6:1", @@ -1570,19 +1404,15 @@ ] }, { - "body": - { + "body": { "nativeSrc": "2358:103:1", "nodeType": "YulBlock", "src": "2358:103:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_81385d8c0b31fffe14be1da910c8bd3a80be4cfa248e04f42ec0faea3132a8ef", "nativeSrc": "2372:77:1", "nodeType": "YulIdentifier", @@ -1598,10 +1428,8 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { "name": "srcEnd", "nativeSrc": "2345:6:1", @@ -1615,8 +1443,7 @@ "src": "2353:3:1" } ], - "functionName": - { + "functionName": { "name": "gt", "nativeSrc": "2342:2:1", "nodeType": "YulIdentifier", @@ -1631,26 +1458,22 @@ "src": "2339:122:1" }, { - "body": - { + "body": { "nativeSrc": "2546:144:1", "nodeType": "YulBlock", "src": "2546:144:1", - "statements": - [ + "statements": [ { "nativeSrc": "2561:21:1", "nodeType": "YulVariableDeclaration", "src": "2561:21:1", - "value": - { + "value": { "name": "src", "nativeSrc": "2579:3:1", "nodeType": "YulIdentifier", "src": "2579:3:1" }, - "variables": - [ + "variables": [ { "name": "elementPos", "nativeSrc": "2565:10:1", @@ -1661,10 +1484,8 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "dst", "nativeSrc": "2603:3:1", @@ -1672,8 +1493,7 @@ "src": "2603:3:1" }, { - "arguments": - [ + "arguments": [ { "name": "elementPos", "nativeSrc": "2629:10:1", @@ -1687,8 +1507,7 @@ "src": "2641:3:1" } ], - "functionName": - { + "functionName": { "name": "abi_decode_t_uint256", "nativeSrc": "2608:20:1", "nodeType": "YulIdentifier", @@ -1699,8 +1518,7 @@ "src": "2608:37:1" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "2596:6:1", "nodeType": "YulIdentifier", @@ -1718,10 +1536,8 @@ "nativeSrc": "2659:21:1", "nodeType": "YulAssignment", "src": "2659:21:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "dst", "nativeSrc": "2670:3:1", @@ -1737,8 +1553,7 @@ "value": "0x20" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "2666:3:1", "nodeType": "YulIdentifier", @@ -1748,8 +1563,7 @@ "nodeType": "YulFunctionCall", "src": "2666:14:1" }, - "variableNames": - [ + "variableNames": [ { "name": "dst", "nativeSrc": "2659:3:1", @@ -1760,10 +1574,8 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { "name": "src", "nativeSrc": "2499:3:1", @@ -1777,8 +1589,7 @@ "src": "2504:6:1" } ], - "functionName": - { + "functionName": { "name": "lt", "nativeSrc": "2496:2:1", "nodeType": "YulIdentifier", @@ -1790,21 +1601,17 @@ }, "nativeSrc": "2470:220:1", "nodeType": "YulForLoop", - "post": - { + "post": { "nativeSrc": "2512:25:1", "nodeType": "YulBlock", "src": "2512:25:1", - "statements": - [ + "statements": [ { "nativeSrc": "2514:21:1", "nodeType": "YulAssignment", "src": "2514:21:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "src", "nativeSrc": "2525:3:1", @@ -1820,8 +1627,7 @@ "value": "0x20" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "2521:3:1", "nodeType": "YulIdentifier", @@ -1831,8 +1637,7 @@ "nodeType": "YulFunctionCall", "src": "2521:14:1" }, - "variableNames": - [ + "variableNames": [ { "name": "src", "nativeSrc": "2514:3:1", @@ -1843,26 +1648,22 @@ } ] }, - "pre": - { + "pre": { "nativeSrc": "2474:21:1", "nodeType": "YulBlock", "src": "2474:21:1", - "statements": - [ + "statements": [ { "nativeSrc": "2476:17:1", "nodeType": "YulVariableDeclaration", "src": "2476:17:1", - "value": - { + "value": { "name": "offset", "nativeSrc": "2487:6:1", "nodeType": "YulIdentifier", "src": "2487:6:1" }, - "variables": - [ + "variables": [ { "name": "src", "nativeSrc": "2480:3:1", @@ -1881,8 +1682,7 @@ "name": "abi_decode_available_length_t_array$_t_uint256_$dyn_memory_ptr", "nativeSrc": "1986:710:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "offset", "nativeSrc": "2058:6:1", @@ -1905,8 +1705,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "array", "nativeSrc": "2082:5:1", @@ -1918,27 +1717,21 @@ "src": "1986:710:1" }, { - "body": - { + "body": { "nativeSrc": "2796:293:1", "nodeType": "YulBlock", "src": "2796:293:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "2845:83:1", "nodeType": "YulBlock", "src": "2845:83:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_1b9f4a0a5773e33b91aa01db23bf8c55fce1411167c872835e7fa00a4f17d46d", "nativeSrc": "2847:77:1", "nodeType": "YulIdentifier", @@ -1954,16 +1747,12 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { - "arguments": - [ + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "offset", "nativeSrc": "2824:6:1", @@ -1979,8 +1768,7 @@ "value": "0x1f" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "2820:3:1", "nodeType": "YulIdentifier", @@ -1997,8 +1785,7 @@ "src": "2839:3:1" } ], - "functionName": - { + "functionName": { "name": "slt", "nativeSrc": "2816:3:1", "nodeType": "YulIdentifier", @@ -2009,8 +1796,7 @@ "src": "2816:27:1" } ], - "functionName": - { + "functionName": { "name": "iszero", "nativeSrc": "2809:6:1", "nodeType": "YulIdentifier", @@ -2028,10 +1814,8 @@ "nativeSrc": "2937:34:1", "nodeType": "YulVariableDeclaration", "src": "2937:34:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "offset", "nativeSrc": "2964:6:1", @@ -2039,8 +1823,7 @@ "src": "2964:6:1" } ], - "functionName": - { + "functionName": { "name": "calldataload", "nativeSrc": "2951:12:1", "nodeType": "YulIdentifier", @@ -2050,8 +1833,7 @@ "nodeType": "YulFunctionCall", "src": "2951:20:1" }, - "variables": - [ + "variables": [ { "name": "length", "nativeSrc": "2941:6:1", @@ -2065,13 +1847,10 @@ "nativeSrc": "2980:103:1", "nodeType": "YulAssignment", "src": "2980:103:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "offset", "nativeSrc": "3056:6:1", @@ -2087,8 +1866,7 @@ "value": "0x20" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "3052:3:1", "nodeType": "YulIdentifier", @@ -2111,8 +1889,7 @@ "src": "3079:3:1" } ], - "functionName": - { + "functionName": { "name": "abi_decode_available_length_t_array$_t_uint256_$dyn_memory_ptr", "nativeSrc": "2989:62:1", "nodeType": "YulIdentifier", @@ -2122,8 +1899,7 @@ "nodeType": "YulFunctionCall", "src": "2989:94:1" }, - "variableNames": - [ + "variableNames": [ { "name": "array", "nativeSrc": "2980:5:1", @@ -2137,8 +1913,7 @@ "name": "abi_decode_t_array$_t_uint256_$dyn_memory_ptr", "nativeSrc": "2719:370:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "offset", "nativeSrc": "2774:6:1", @@ -2154,8 +1929,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "array", "nativeSrc": "2790:5:1", @@ -2167,27 +1941,21 @@ "src": "2719:370:1" }, { - "body": - { + "body": { "nativeSrc": "3186:448:1", "nodeType": "YulBlock", "src": "3186:448:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "3232:83:1", "nodeType": "YulBlock", "src": "3232:83:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", "nativeSrc": "3234:77:1", "nodeType": "YulIdentifier", @@ -2203,13 +1971,10 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "dataEnd", "nativeSrc": "3207:7:1", @@ -2223,8 +1988,7 @@ "src": "3216:9:1" } ], - "functionName": - { + "functionName": { "name": "sub", "nativeSrc": "3203:3:1", "nodeType": "YulIdentifier", @@ -2243,8 +2007,7 @@ "value": "32" } ], - "functionName": - { + "functionName": { "name": "slt", "nativeSrc": "3199:3:1", "nodeType": "YulIdentifier", @@ -2262,19 +2025,15 @@ "nativeSrc": "3325:302:1", "nodeType": "YulBlock", "src": "3325:302:1", - "statements": - [ + "statements": [ { "nativeSrc": "3340:45:1", "nodeType": "YulVariableDeclaration", "src": "3340:45:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "headStart", "nativeSrc": "3371:9:1", @@ -2290,8 +2049,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "3367:3:1", "nodeType": "YulIdentifier", @@ -2302,8 +2060,7 @@ "src": "3367:17:1" } ], - "functionName": - { + "functionName": { "name": "calldataload", "nativeSrc": "3354:12:1", "nodeType": "YulIdentifier", @@ -2313,8 +2070,7 @@ "nodeType": "YulFunctionCall", "src": "3354:31:1" }, - "variables": - [ + "variables": [ { "name": "offset", "nativeSrc": "3344:6:1", @@ -2325,19 +2081,15 @@ ] }, { - "body": - { + "body": { "nativeSrc": "3432:83:1", "nodeType": "YulBlock", "src": "3432:83:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db", "nativeSrc": "3434:77:1", "nodeType": "YulIdentifier", @@ -2353,10 +2105,8 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { "name": "offset", "nativeSrc": "3404:6:1", @@ -2372,8 +2122,7 @@ "value": "0xffffffffffffffff" } ], - "functionName": - { + "functionName": { "name": "gt", "nativeSrc": "3401:2:1", "nodeType": "YulIdentifier", @@ -2391,13 +2140,10 @@ "nativeSrc": "3529:88:1", "nodeType": "YulAssignment", "src": "3529:88:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "headStart", "nativeSrc": "3589:9:1", @@ -2411,8 +2157,7 @@ "src": "3600:6:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "3585:3:1", "nodeType": "YulIdentifier", @@ -2429,8 +2174,7 @@ "src": "3609:7:1" } ], - "functionName": - { + "functionName": { "name": "abi_decode_t_array$_t_uint256_$dyn_memory_ptr", "nativeSrc": "3539:45:1", "nodeType": "YulIdentifier", @@ -2440,8 +2184,7 @@ "nodeType": "YulFunctionCall", "src": "3539:78:1" }, - "variableNames": - [ + "variableNames": [ { "name": "value0", "nativeSrc": "3529:6:1", @@ -2457,8 +2200,7 @@ "name": "abi_decode_tuple_t_array$_t_uint256_$dyn_memory_ptr", "nativeSrc": "3095:539:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "headStart", "nativeSrc": "3156:9:1", @@ -2474,8 +2216,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "value0", "nativeSrc": "3179:6:1", @@ -2487,18 +2228,14 @@ "src": "3095:539:1" }, { - "body": - { + "body": { "nativeSrc": "3705:53:1", "nodeType": "YulBlock", "src": "3705:53:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "pos", "nativeSrc": "3722:3:1", @@ -2506,8 +2243,7 @@ "src": "3722:3:1" }, { - "arguments": - [ + "arguments": [ { "name": "value", "nativeSrc": "3745:5:1", @@ -2515,8 +2251,7 @@ "src": "3745:5:1" } ], - "functionName": - { + "functionName": { "name": "cleanup_t_uint256", "nativeSrc": "3727:17:1", "nodeType": "YulIdentifier", @@ -2527,8 +2262,7 @@ "src": "3727:24:1" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "3715:6:1", "nodeType": "YulIdentifier", @@ -2547,8 +2281,7 @@ "name": "abi_encode_t_uint256_to_t_uint256_fromStack", "nativeSrc": "3640:118:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "value", "nativeSrc": "3693:5:1", @@ -2567,21 +2300,17 @@ "src": "3640:118:1" }, { - "body": - { + "body": { "nativeSrc": "3862:124:1", "nodeType": "YulBlock", "src": "3862:124:1", - "statements": - [ + "statements": [ { "nativeSrc": "3872:26:1", "nodeType": "YulAssignment", "src": "3872:26:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "headStart", "nativeSrc": "3884:9:1", @@ -2597,8 +2326,7 @@ "value": "32" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "3880:3:1", "nodeType": "YulIdentifier", @@ -2608,8 +2336,7 @@ "nodeType": "YulFunctionCall", "src": "3880:18:1" }, - "variableNames": - [ + "variableNames": [ { "name": "tail", "nativeSrc": "3872:4:1", @@ -2619,10 +2346,8 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "value0", "nativeSrc": "3952:6:1", @@ -2630,8 +2355,7 @@ "src": "3952:6:1" }, { - "arguments": - [ + "arguments": [ { "name": "headStart", "nativeSrc": "3965:9:1", @@ -2647,8 +2371,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "3961:3:1", "nodeType": "YulIdentifier", @@ -2659,8 +2382,7 @@ "src": "3961:17:1" } ], - "functionName": - { + "functionName": { "name": "abi_encode_t_uint256_to_t_uint256_fromStack", "nativeSrc": "3908:43:1", "nodeType": "YulIdentifier", @@ -2679,8 +2401,7 @@ "name": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed", "nativeSrc": "3764:222:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "headStart", "nativeSrc": "3834:9:1", @@ -2696,8 +2417,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "tail", "nativeSrc": "3857:4:1", @@ -2843,8 +2563,7 @@ } } }, - "errors": - [ + "errors": [ { "component": "general", "errorCode": "3420", @@ -2854,8 +2573,7 @@ ", "message": "Source file does not specify required compiler version!", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": -1, "file": "a.sol", "start": -1 @@ -2863,10 +2581,8 @@ "type": "Warning" } ], - "sources": - { - "a.sol": - { + "sources": { + "a.sol": { "id": 0 } } diff --git a/test/cmdlineTests/standard_immutable_references/output.json b/test/cmdlineTests/standard_immutable_references/output.json index e25a911ff..cfa087bce 100644 --- a/test/cmdlineTests/standard_immutable_references/output.json +++ b/test/cmdlineTests/standard_immutable_references/output.json @@ -1,18 +1,11 @@ { - "contracts": - { - "a.sol": - { - "A": - { - "evm": - { - "deployedBytecode": - { - "immutableReferences": - { - "6": - [ + "contracts": { + "a.sol": { + "A": { + "evm": { + "deployedBytecode": { + "immutableReferences": { + "6": [ { "length": 32, "start": 75 @@ -24,10 +17,8 @@ } } }, - "sources": - { - "a.sol": - { + "sources": { + "a.sol": { "id": 0 } } diff --git a/test/cmdlineTests/standard_import_asm_json/output.json b/test/cmdlineTests/standard_import_asm_json/output.json index 5b7cdf3bb..1db287960 100644 --- a/test/cmdlineTests/standard_import_asm_json/output.json +++ b/test/cmdlineTests/standard_import_asm_json/output.json @@ -1,25 +1,19 @@ { - "contracts": - { - "A": - { - "": - { - "evm": - { + "contracts": { + "A": { + "": { + "evm": { "assembly": " /* \"\":36:51 */ 0x00 ", - "bytecode": - { + "bytecode": { "functionDebugData": {}, "linkReferences": {}, "object": "", "opcodes":"", "sourceMap":"" }, - "deployedBytecode": - { + "deployedBytecode": { "functionDebugData": {}, "immutableReferences": {}, "linkReferences": {}, @@ -27,10 +21,8 @@ "opcodes": "", "sourceMap": "" }, - "legacyAssembly": - { - ".code": - [ + "legacyAssembly": { + ".code": [ { "begin": 36, "end": 51, @@ -39,8 +31,7 @@ "value": "0" } ], - "sourceList": - [ + "sourceList": [ "" ] } diff --git a/test/cmdlineTests/standard_import_asm_json_immutable_references/output.json b/test/cmdlineTests/standard_import_asm_json_immutable_references/output.json index 05a6ff7d5..f0554d8c6 100644 --- a/test/cmdlineTests/standard_import_asm_json_immutable_references/output.json +++ b/test/cmdlineTests/standard_import_asm_json_immutable_references/output.json @@ -1,27 +1,19 @@ { - "contracts": - { - "A": - { - "": - { - "evm": - { - "bytecode": - { + "contracts": { + "A": { + "": { + "evm": { + "bytecode": { "functionDebugData": {}, "linkReferences": {}, "object": "", "opcodes":"", "sourceMap":"" }, - "deployedBytecode": - { + "deployedBytecode": { "functionDebugData": {}, - "immutableReferences": - { - "6": - [ + "immutableReferences": { + "6": [ { "length": 32, "start": 1 diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_input_array/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_input_array/output.json index 2a075efd0..489a41933 100644 --- a/test/cmdlineTests/standard_import_asm_json_invalid_input_array/output.json +++ b/test/cmdlineTests/standard_import_asm_json_invalid_input_array/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid input source specified. Expected exactly one object, named 'assemblyJson', inside $.sources.A", diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_key_inside_source/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_key_inside_source/output.json index 2a075efd0..489a41933 100644 --- a/test/cmdlineTests/standard_import_asm_json_invalid_key_inside_source/output.json +++ b/test/cmdlineTests/standard_import_asm_json_invalid_key_inside_source/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid input source specified. Expected exactly one object, named 'assemblyJson', inside $.sources.A", diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_key_other_source/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_key_other_source/output.json index 2a075efd0..489a41933 100644 --- a/test/cmdlineTests/standard_import_asm_json_invalid_key_other_source/output.json +++ b/test/cmdlineTests/standard_import_asm_json_invalid_key_other_source/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid input source specified. Expected exactly one object, named 'assemblyJson', inside $.sources.A", diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_no_source/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_no_source/output.json index 3495a7411..135ec60de 100644 --- a/test/cmdlineTests/standard_import_asm_json_invalid_no_source/output.json +++ b/test/cmdlineTests/standard_import_asm_json_invalid_no_source/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "No input sources specified.", diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json index 6314f8b05..cccd241d9 100644 --- a/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json +++ b/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Assembly import error: InvalidOpcode", diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_two_sources/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_two_sources/output.json index affe4c34e..9e85128bb 100644 --- a/test/cmdlineTests/standard_import_asm_json_invalid_two_sources/output.json +++ b/test/cmdlineTests/standard_import_asm_json_invalid_two_sources/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "EVMAssembly import only supports exactly one input file.", diff --git a/test/cmdlineTests/standard_import_asm_json_link_references/output.json b/test/cmdlineTests/standard_import_asm_json_link_references/output.json index 864f65a53..fed476e62 100644 --- a/test/cmdlineTests/standard_import_asm_json_link_references/output.json +++ b/test/cmdlineTests/standard_import_asm_json_link_references/output.json @@ -1,30 +1,21 @@ { - "contracts": - { - "A": - { - "": - { - "evm": - { - "bytecode": - { + "contracts": { + "A": { + "": { + "evm": { + "bytecode": { "functionDebugData": {}, "linkReferences": {}, "object": "", "opcodes":"", "sourceMap": "" }, - "deployedBytecode": - { + "deployedBytecode": { "functionDebugData": {}, "immutableReferences": {}, - "linkReferences": - { - "test.sol": - { - "L": - [ + "linkReferences": { + "test.sol": { + "L": [ { "length": 20, "start": 1 diff --git a/test/cmdlineTests/standard_import_asm_json_multiple_keys_inside_source/output.json b/test/cmdlineTests/standard_import_asm_json_multiple_keys_inside_source/output.json index 2a075efd0..489a41933 100644 --- a/test/cmdlineTests/standard_import_asm_json_multiple_keys_inside_source/output.json +++ b/test/cmdlineTests/standard_import_asm_json_multiple_keys_inside_source/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid input source specified. Expected exactly one object, named 'assemblyJson', inside $.sources.A", diff --git a/test/cmdlineTests/standard_import_ast/output.json b/test/cmdlineTests/standard_import_ast/output.json index 6ecac5ca3..d54da1750 100644 --- a/test/cmdlineTests/standard_import_ast/output.json +++ b/test/cmdlineTests/standard_import_ast/output.json @@ -1,27 +1,20 @@ { - "sources": - { - "A": - { - "ast": - { + "sources": { + "A": { + "ast": { "absolutePath": "A", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", ">=", "0.0" @@ -37,18 +30,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "68:1:0", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "97:2:0", @@ -62,15 +52,13 @@ "name": "f", "nameLocation": "81:1:0", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], "src": "82:2:0" }, - "returnParameters": - { + "returnParameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], diff --git a/test/cmdlineTests/standard_import_ast_select_bytecode/output.json b/test/cmdlineTests/standard_import_ast_select_bytecode/output.json index 0fca3f271..c060efd97 100644 --- a/test/cmdlineTests/standard_import_ast_select_bytecode/output.json +++ b/test/cmdlineTests/standard_import_ast_select_bytecode/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "A": - { - "test": - { - "evm": - { - "bytecode": - { + "contracts": { + "A": { + "test": { + "evm": { + "bytecode": { "functionDebugData": {}, "generatedSources": [], "linkReferences": {}, @@ -20,10 +15,8 @@ } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_import_with_comments/output.json b/test/cmdlineTests/standard_import_with_comments/output.json index 6ecac5ca3..d54da1750 100644 --- a/test/cmdlineTests/standard_import_with_comments/output.json +++ b/test/cmdlineTests/standard_import_with_comments/output.json @@ -1,27 +1,20 @@ { - "sources": - { - "A": - { - "ast": - { + "sources": { + "A": { + "ast": { "absolutePath": "A", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", ">=", "0.0" @@ -37,18 +30,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "68:1:0", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "97:2:0", @@ -62,15 +52,13 @@ "name": "f", "nameLocation": "81:1:0", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], "src": "82:2:0" }, - "returnParameters": - { + "returnParameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], diff --git a/test/cmdlineTests/standard_import_with_comments_simple/output.json b/test/cmdlineTests/standard_import_with_comments_simple/output.json index 6ecac5ca3..d54da1750 100644 --- a/test/cmdlineTests/standard_import_with_comments_simple/output.json +++ b/test/cmdlineTests/standard_import_with_comments_simple/output.json @@ -1,27 +1,20 @@ { - "sources": - { - "A": - { - "ast": - { + "sources": { + "A": { + "ast": { "absolutePath": "A", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", ">=", "0.0" @@ -37,18 +30,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "68:1:0", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "97:2:0", @@ -62,15 +52,13 @@ "name": "f", "nameLocation": "81:1:0", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], "src": "82:2:0" }, - "returnParameters": - { + "returnParameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], diff --git a/test/cmdlineTests/standard_import_with_invalid_utf8/output.json b/test/cmdlineTests/standard_import_with_invalid_utf8/output.json index 057e4fe16..e168f8797 100644 --- a/test/cmdlineTests/standard_import_with_invalid_utf8/output.json +++ b/test/cmdlineTests/standard_import_with_invalid_utf8/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "parse error at line 12, column 23: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\ud800\"'", diff --git a/test/cmdlineTests/standard_irOptimized_ast_requested/output.json b/test/cmdlineTests/standard_irOptimized_ast_requested/output.json index 200b653ff..91d0e87f3 100644 --- a/test/cmdlineTests/standard_irOptimized_ast_requested/output.json +++ b/test/cmdlineTests/standard_irOptimized_ast_requested/output.json @@ -1,32 +1,22 @@ { - "contracts": - { - "C": - { - "C": - { - "irOptimizedAst": - { - "code": - { - "block": - { + "contracts": { + "C": { + "C": { + "irOptimizedAst": { + "code": { + "block": { "nativeSrc": "44:790:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { "nativeSrc": "44:790:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "103:2:0", @@ -36,8 +26,7 @@ "value": "64" }, { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "119:3:0", @@ -47,8 +36,7 @@ "value": "0x80" } ], - "functionName": - { + "functionName": { "name": "memoryguard", "nativeSrc": "107:11:0", "nodeType": "YulIdentifier", @@ -59,8 +47,7 @@ "src": "56:13:0" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "96:6:0", "nodeType": "YulIdentifier", @@ -75,19 +62,15 @@ "src": "56:13:0" }, { - "body": - { + "body": { "nativeSrc": "148:83:0", "nodeType": "YulBlock", "src": "56:13:0", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", "nativeSrc": "150:77:0", "nodeType": "YulIdentifier", @@ -103,11 +86,9 @@ } ] }, - "condition": - { + "condition": { "arguments": [], - "functionName": - { + "functionName": { "name": "callvalue", "nativeSrc": "136:9:0", "nodeType": "YulIdentifier", @@ -125,11 +106,9 @@ "nativeSrc": "268:30:0", "nodeType": "YulVariableDeclaration", "src": "56:13:0", - "value": - { + "value": { "arguments": [], - "functionName": - { + "functionName": { "name": "allocate_unbounded", "nativeSrc": "278:18:0", "nodeType": "YulIdentifier", @@ -139,8 +118,7 @@ "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "variables": - [ + "variables": [ { "name": "_1", "nativeSrc": "272:2:0", @@ -151,10 +129,8 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "_1", "nativeSrc": "316:2:0", @@ -162,8 +138,7 @@ "src": "56:13:0" }, { - "arguments": - [ + "arguments": [ { "hexValue": "435f325f6465706c6f796564", "kind": "string", @@ -174,8 +149,7 @@ "value": "C_2_deployed" } ], - "functionName": - { + "functionName": { "name": "dataoffset", "nativeSrc": "320:10:0", "nodeType": "YulIdentifier", @@ -186,8 +160,7 @@ "src": "56:13:0" }, { - "arguments": - [ + "arguments": [ { "hexValue": "435f325f6465706c6f796564", "kind": "string", @@ -198,8 +171,7 @@ "value": "C_2_deployed" } ], - "functionName": - { + "functionName": { "name": "datasize", "nativeSrc": "348:8:0", "nodeType": "YulIdentifier", @@ -210,8 +182,7 @@ "src": "56:13:0" } ], - "functionName": - { + "functionName": { "name": "codecopy", "nativeSrc": "307:8:0", "nodeType": "YulIdentifier", @@ -226,10 +197,8 @@ "src": "56:13:0" }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "_1", "nativeSrc": "390:2:0", @@ -237,8 +206,7 @@ "src": "56:13:0" }, { - "arguments": - [ + "arguments": [ { "hexValue": "435f325f6465706c6f796564", "kind": "string", @@ -249,8 +217,7 @@ "value": "C_2_deployed" } ], - "functionName": - { + "functionName": { "name": "datasize", "nativeSrc": "394:8:0", "nodeType": "YulIdentifier", @@ -261,8 +228,7 @@ "src": "56:13:0" } ], - "functionName": - { + "functionName": { "name": "return", "nativeSrc": "383:6:0", "nodeType": "YulIdentifier", @@ -279,21 +245,17 @@ ] }, { - "body": - { + "body": { "nativeSrc": "469:43:0", "nodeType": "YulBlock", "src": "56:13:0", - "statements": - [ + "statements": [ { "nativeSrc": "483:19:0", "nodeType": "YulAssignment", "src": "56:13:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "499:2:0", @@ -303,8 +265,7 @@ "value": "64" } ], - "functionName": - { + "functionName": { "name": "mload", "nativeSrc": "493:5:0", "nodeType": "YulIdentifier", @@ -314,8 +275,7 @@ "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "variableNames": - [ + "variableNames": [ { "name": "memPtr", "nativeSrc": "483:6:0", @@ -329,8 +289,7 @@ "name": "allocate_unbounded", "nativeSrc": "429:83:0", "nodeType": "YulFunctionDefinition", - "returnVariables": - [ + "returnVariables": [ { "name": "memPtr", "nativeSrc": "462:6:0", @@ -342,18 +301,14 @@ "src": "56:13:0" }, { - "body": - { + "body": { "nativeSrc": "611:36:0", "nodeType": "YulBlock", "src": "56:13:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "632:1:0", @@ -371,8 +326,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "625:6:0", "nodeType": "YulIdentifier", @@ -399,29 +353,22 @@ }, "name": "C_2", "nodeType": "YulObject", - "subObjects": - [ + "subObjects": [ { - "code": - { - "block": - { + "code": { + "block": { "nativeSrc": "899:588:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { "nativeSrc": "899:588:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "966:2:0", @@ -431,8 +378,7 @@ "value": "64" }, { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "982:3:0", @@ -442,8 +388,7 @@ "value": "0x80" } ], - "functionName": - { + "functionName": { "name": "memoryguard", "nativeSrc": "970:11:0", "nodeType": "YulIdentifier", @@ -454,8 +399,7 @@ "src": "56:13:0" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "959:6:0", "nodeType": "YulIdentifier", @@ -470,11 +414,9 @@ "src": "56:13:0" }, { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", "nativeSrc": "1001:77:0", "nodeType": "YulIdentifier", @@ -491,18 +433,14 @@ ] }, { - "body": - { + "body": { "nativeSrc": "1432:44:0", "nodeType": "YulBlock", "src": "56:13:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "1457:1:0", @@ -520,8 +458,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "1450:6:0", "nodeType": "YulIdentifier", @@ -548,8 +485,7 @@ }, "name": "C_2_deployed", "nodeType": "YulObject", - "subObjects": - [ + "subObjects": [ { "nodeType": "YulData", "value": "" @@ -561,10 +497,8 @@ } } }, - "sources": - { - "C": - { + "sources": { + "C": { "id": 0 } } diff --git a/test/cmdlineTests/standard_irOptimized_requested/output.json b/test/cmdlineTests/standard_irOptimized_requested/output.json index 88ce64895..849b436b2 100644 --- a/test/cmdlineTests/standard_irOptimized_requested/output.json +++ b/test/cmdlineTests/standard_irOptimized_requested/output.json @@ -1,10 +1,7 @@ { - "contracts": - { - "A": - { - "C": - { + "contracts": { + "A": { + "C": { "irOptimized": "/// @use-src 0:\"A\" object \"C_7\" { code { @@ -77,10 +74,8 @@ object \"C_7\" { } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_ir_ast_requested/output.json b/test/cmdlineTests/standard_ir_ast_requested/output.json index f949d7b30..b2e1c0c7d 100644 --- a/test/cmdlineTests/standard_ir_ast_requested/output.json +++ b/test/cmdlineTests/standard_ir_ast_requested/output.json @@ -1,26 +1,17 @@ { - "contracts": - { - "C": - { - "C": - { - "irAst": - { - "code": - { - "block": - { + "contracts": { + "C": { + "C": { + "irAst": { + "code": { + "block": { "nativeSrc": "44:790:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "103:2:0", @@ -30,8 +21,7 @@ "value": "64" }, { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "119:3:0", @@ -41,8 +31,7 @@ "value": "128" } ], - "functionName": - { + "functionName": { "name": "memoryguard", "nativeSrc": "107:11:0", "nodeType": "YulIdentifier", @@ -53,8 +42,7 @@ "src": "56:13:0" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "96:6:0", "nodeType": "YulIdentifier", @@ -69,19 +57,15 @@ "src": "56:13:0" }, { - "body": - { + "body": { "nativeSrc": "148:83:0", "nodeType": "YulBlock", "src": "56:13:0", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", "nativeSrc": "150:77:0", "nodeType": "YulIdentifier", @@ -97,11 +81,9 @@ } ] }, - "condition": - { + "condition": { "arguments": [], - "functionName": - { + "functionName": { "name": "callvalue", "nativeSrc": "136:9:0", "nodeType": "YulIdentifier", @@ -116,11 +98,9 @@ "src": "56:13:0" }, { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "constructor_C_2", "nativeSrc": "241:15:0", "nodeType": "YulIdentifier", @@ -138,11 +118,9 @@ "nativeSrc": "268:30:0", "nodeType": "YulVariableDeclaration", "src": "56:13:0", - "value": - { + "value": { "arguments": [], - "functionName": - { + "functionName": { "name": "allocate_unbounded", "nativeSrc": "278:18:0", "nodeType": "YulIdentifier", @@ -152,8 +130,7 @@ "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "variables": - [ + "variables": [ { "name": "_1", "nativeSrc": "272:2:0", @@ -164,10 +141,8 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "_1", "nativeSrc": "316:2:0", @@ -175,8 +150,7 @@ "src": "56:13:0" }, { - "arguments": - [ + "arguments": [ { "hexValue": "435f325f6465706c6f796564", "kind": "string", @@ -187,8 +161,7 @@ "value": "C_2_deployed" } ], - "functionName": - { + "functionName": { "name": "dataoffset", "nativeSrc": "320:10:0", "nodeType": "YulIdentifier", @@ -199,8 +172,7 @@ "src": "56:13:0" }, { - "arguments": - [ + "arguments": [ { "hexValue": "435f325f6465706c6f796564", "kind": "string", @@ -211,8 +183,7 @@ "value": "C_2_deployed" } ], - "functionName": - { + "functionName": { "name": "datasize", "nativeSrc": "348:8:0", "nodeType": "YulIdentifier", @@ -223,8 +194,7 @@ "src": "56:13:0" } ], - "functionName": - { + "functionName": { "name": "codecopy", "nativeSrc": "307:8:0", "nodeType": "YulIdentifier", @@ -239,10 +209,8 @@ "src": "56:13:0" }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "_1", "nativeSrc": "390:2:0", @@ -250,8 +218,7 @@ "src": "56:13:0" }, { - "arguments": - [ + "arguments": [ { "hexValue": "435f325f6465706c6f796564", "kind": "string", @@ -262,8 +229,7 @@ "value": "C_2_deployed" } ], - "functionName": - { + "functionName": { "name": "datasize", "nativeSrc": "394:8:0", "nodeType": "YulIdentifier", @@ -274,8 +240,7 @@ "src": "56:13:0" } ], - "functionName": - { + "functionName": { "name": "return", "nativeSrc": "383:6:0", "nodeType": "YulIdentifier", @@ -290,21 +255,17 @@ "src": "56:13:0" }, { - "body": - { + "body": { "nativeSrc": "469:43:0", "nodeType": "YulBlock", "src": "56:13:0", - "statements": - [ + "statements": [ { "nativeSrc": "483:19:0", "nodeType": "YulAssignment", "src": "56:13:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "499:2:0", @@ -314,8 +275,7 @@ "value": "64" } ], - "functionName": - { + "functionName": { "name": "mload", "nativeSrc": "493:5:0", "nodeType": "YulIdentifier", @@ -325,8 +285,7 @@ "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "variableNames": - [ + "variableNames": [ { "name": "memPtr", "nativeSrc": "483:6:0", @@ -340,8 +299,7 @@ "name": "allocate_unbounded", "nativeSrc": "429:83:0", "nodeType": "YulFunctionDefinition", - "returnVariables": - [ + "returnVariables": [ { "name": "memPtr", "nativeSrc": "462:6:0", @@ -353,18 +311,14 @@ "src": "56:13:0" }, { - "body": - { + "body": { "nativeSrc": "611:36:0", "nodeType": "YulBlock", "src": "56:13:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "632:1:0", @@ -382,8 +336,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "625:6:0", "nodeType": "YulIdentifier", @@ -405,8 +358,7 @@ "src": "56:13:0" }, { - "body": - { + "body": { "nativeSrc": "726:59:0", "nodeType": "YulBlock", "src": "56:13:0", @@ -423,23 +375,17 @@ }, "name": "C_2", "nodeType": "YulObject", - "subObjects": - [ + "subObjects": [ { - "code": - { - "block": - { + "code": { + "block": { "nativeSrc": "899:588:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "966:2:0", @@ -449,8 +395,7 @@ "value": "64" }, { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "982:3:0", @@ -460,8 +405,7 @@ "value": "128" } ], - "functionName": - { + "functionName": { "name": "memoryguard", "nativeSrc": "970:11:0", "nodeType": "YulIdentifier", @@ -472,8 +416,7 @@ "src": "56:13:0" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "959:6:0", "nodeType": "YulIdentifier", @@ -488,11 +431,9 @@ "src": "56:13:0" }, { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", "nativeSrc": "1001:77:0", "nodeType": "YulIdentifier", @@ -507,21 +448,17 @@ "src": "56:13:0" }, { - "body": - { + "body": { "nativeSrc": "1147:77:0", "nodeType": "YulBlock", "src": "56:13:0", - "statements": - [ + "statements": [ { "nativeSrc": "1165:44:0", "nodeType": "YulAssignment", "src": "56:13:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "1198:3:0", @@ -537,8 +474,7 @@ "src": "56:13:0" } ], - "functionName": - { + "functionName": { "name": "shr", "nativeSrc": "1194:3:0", "nodeType": "YulIdentifier", @@ -548,8 +484,7 @@ "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "variableNames": - [ + "variableNames": [ { "name": "newValue", "nativeSrc": "1165:8:0", @@ -563,8 +498,7 @@ "name": "shift_right_224_unsigned", "nativeSrc": "1094:130:0", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "value", "nativeSrc": "1128:5:0", @@ -573,8 +507,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "newValue", "nativeSrc": "1138:8:0", @@ -586,21 +519,17 @@ "src": "56:13:0" }, { - "body": - { + "body": { "nativeSrc": "1278:51:0", "nodeType": "YulBlock", "src": "56:13:0", - "statements": - [ + "statements": [ { "nativeSrc": "1296:19:0", "nodeType": "YulAssignment", "src": "56:13:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "1312:2:0", @@ -610,8 +539,7 @@ "value": "64" } ], - "functionName": - { + "functionName": { "name": "mload", "nativeSrc": "1306:5:0", "nodeType": "YulIdentifier", @@ -621,8 +549,7 @@ "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "variableNames": - [ + "variableNames": [ { "name": "memPtr", "nativeSrc": "1296:6:0", @@ -636,8 +563,7 @@ "name": "allocate_unbounded", "nativeSrc": "1238:91:0", "nodeType": "YulFunctionDefinition", - "returnVariables": - [ + "returnVariables": [ { "name": "memPtr", "nativeSrc": "1271:6:0", @@ -649,18 +575,14 @@ "src": "56:13:0" }, { - "body": - { + "body": { "nativeSrc": "1432:44:0", "nodeType": "YulBlock", "src": "56:13:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "1457:1:0", @@ -678,8 +600,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "1450:6:0", "nodeType": "YulIdentifier", @@ -706,8 +627,7 @@ }, "name": "C_2_deployed", "nodeType": "YulObject", - "subObjects": - [ + "subObjects": [ { "nodeType": "YulData", "value": "" @@ -719,10 +639,8 @@ } } }, - "sources": - { - "C": - { + "sources": { + "C": { "id": 0 } } diff --git a/test/cmdlineTests/standard_ir_requested/output.json b/test/cmdlineTests/standard_ir_requested/output.json index ab38f0a58..e359d5ca5 100644 --- a/test/cmdlineTests/standard_ir_requested/output.json +++ b/test/cmdlineTests/standard_ir_requested/output.json @@ -1,10 +1,7 @@ { - "contracts": - { - "A": - { - "C": - { + "contracts": { + "A": { + "C": { "ir": " /// @use-src 0:\"A\" object \"C_7\" { @@ -122,10 +119,8 @@ object \"C_7\" { } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_metadata/output.json b/test/cmdlineTests/standard_metadata/output.json index 955d30c34..5b9c8504f 100644 --- a/test/cmdlineTests/standard_metadata/output.json +++ b/test/cmdlineTests/standard_metadata/output.json @@ -1,18 +1,13 @@ { - "contracts": - { - "C": - { - "C": - { + "contracts": { + "C": { + "C": { "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2\",\"dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS\"]}},\"version\":1}" } } }, - "sources": - { - "C": - { + "sources": { + "C": { "id": 0 } } diff --git a/test/cmdlineTests/standard_method_identifiers_requested/output.json b/test/cmdlineTests/standard_method_identifiers_requested/output.json index 35d4f5002..df1e81f73 100644 --- a/test/cmdlineTests/standard_method_identifiers_requested/output.json +++ b/test/cmdlineTests/standard_method_identifiers_requested/output.json @@ -1,24 +1,17 @@ { - "contracts": - { - "A": - { - "C": - { - "evm": - { - "methodIdentifiers": - { + "contracts": { + "A": { + "C": { + "evm": { + "methodIdentifiers": { "f()": "26121ff0" } } } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_method_identifiers_requested_empty/output.json b/test/cmdlineTests/standard_method_identifiers_requested_empty/output.json index f90a33351..1d3245c20 100644 --- a/test/cmdlineTests/standard_method_identifiers_requested_empty/output.json +++ b/test/cmdlineTests/standard_method_identifiers_requested_empty/output.json @@ -1,21 +1,15 @@ { - "contracts": - { - "A": - { - "C": - { - "evm": - { + "contracts": { + "A": { + "C": { + "evm": { "methodIdentifiers": {} } } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_missing_key_useLiteralContent/output.json b/test/cmdlineTests/standard_missing_key_useLiteralContent/output.json index f3a09c9e7..d18ad81fa 100644 --- a/test/cmdlineTests/standard_missing_key_useLiteralContent/output.json +++ b/test/cmdlineTests/standard_missing_key_useLiteralContent/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Support for EVM versions older than constantinople is deprecated and will be removed in the future.", @@ -9,10 +8,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_bmc_loop_iterations/output.json b/test/cmdlineTests/standard_model_checker_bmc_loop_iterations/output.json index 139b0825b..ffaa2823b 100644 --- a/test/cmdlineTests/standard_model_checker_bmc_loop_iterations/output.json +++ b/test/cmdlineTests/standard_model_checker_bmc_loop_iterations/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6002", @@ -12,10 +11,8 @@ "type": "Info" } ], - "sources": - { - "Source": - { + "sources": { + "Source": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_bmc_loop_iterations_invalid_arg/output.json b/test/cmdlineTests/standard_model_checker_bmc_loop_iterations_invalid_arg/output.json index 971973d85..05b835e56 100644 --- a/test/cmdlineTests/standard_model_checker_bmc_loop_iterations_invalid_arg/output.json +++ b/test/cmdlineTests/standard_model_checker_bmc_loop_iterations_invalid_arg/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.bmcLoopIterations must be an unsigned integer.", diff --git a/test/cmdlineTests/standard_model_checker_contracts_all/output.json b/test/cmdlineTests/standard_model_checker_contracts_all/output.json index b4bfd66b8..e9fc1b4cf 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_all/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_all/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -27,8 +26,7 @@ Transaction trace: B.constructor() B.g(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 137, "file": "Source", "start": 124 @@ -61,8 +59,7 @@ Transaction trace: A.constructor() A.f(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 231, "file": "Source", "start": 218 @@ -70,10 +67,8 @@ A.f(0)", "type": "Warning" } ], - "sources": - { - "Source": - { + "sources": { + "Source": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_contracts_all_explicit/output.json b/test/cmdlineTests/standard_model_checker_contracts_all_explicit/output.json index b4bfd66b8..e9fc1b4cf 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_all_explicit/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_all_explicit/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -27,8 +26,7 @@ Transaction trace: B.constructor() B.g(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 137, "file": "Source", "start": 124 @@ -61,8 +59,7 @@ Transaction trace: A.constructor() A.f(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 231, "file": "Source", "start": 218 @@ -70,10 +67,8 @@ A.f(0)", "type": "Warning" } ], - "sources": - { - "Source": - { + "sources": { + "Source": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_contracts_empty_array/output.json b/test/cmdlineTests/standard_model_checker_contracts_empty_array/output.json index ada440ad3..fe1bdb97d 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_empty_array/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_empty_array/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Source contracts must be a non-empty array.", diff --git a/test/cmdlineTests/standard_model_checker_contracts_empty_contract/output.json b/test/cmdlineTests/standard_model_checker_contracts_empty_contract/output.json index c3b171e99..e31326ff8 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_empty_contract/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_empty_contract/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Contract name cannot be empty.", diff --git a/test/cmdlineTests/standard_model_checker_contracts_empty_source/output.json b/test/cmdlineTests/standard_model_checker_contracts_empty_source/output.json index 98dcc1afa..b4495bb22 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_empty_source/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_empty_source/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Source name cannot be empty.", diff --git a/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json b/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json index 7ff30950c..22d5f32de 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "7400", @@ -37,8 +36,7 @@ Transaction trace: B.constructor() B.g(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 137, "file": "Source", "start": 124 @@ -71,8 +69,7 @@ Transaction trace: A.constructor() A.f(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 231, "file": "Source", "start": 218 @@ -80,10 +77,8 @@ A.f(0)", "type": "Warning" } ], - "sources": - { - "Source": - { + "sources": { + "Source": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json b/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json index cb18875e1..fe287f833 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -27,8 +26,7 @@ Transaction trace: B.constructor() B.g(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 137, "file": "Source", "start": 124 @@ -61,8 +59,7 @@ Transaction trace: A.constructor() A.f(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 231, "file": "Source", "start": 218 @@ -95,8 +92,7 @@ Transaction trace: C.constructor() C.h(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 165, "file": "Source2", "start": 150 @@ -104,14 +100,11 @@ C.h(0)", "type": "Warning" } ], - "sources": - { - "Source": - { + "sources": { + "Source": { "id": 0 }, - "Source2": - { + "Source2": { "id": 1 } } diff --git a/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json b/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json index b4bfd66b8..e9fc1b4cf 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -27,8 +26,7 @@ Transaction trace: B.constructor() B.g(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 137, "file": "Source", "start": 124 @@ -61,8 +59,7 @@ Transaction trace: A.constructor() A.f(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 231, "file": "Source", "start": 218 @@ -70,10 +67,8 @@ A.f(0)", "type": "Warning" } ], - "sources": - { - "Source": - { + "sources": { + "Source": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources/output.json b/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources/output.json index d38ad1b59..b792b6d93 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "9134", @@ -12,10 +11,8 @@ "type": "Warning" } ], - "sources": - { - "Source": - { + "sources": { + "Source": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_2/output.json b/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_2/output.json index 98365d1bf..05bab3733 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_2/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_2/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.contracts is not a JSON object.", diff --git a/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_3/output.json b/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_3/output.json index 567db80af..d07d645f4 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_3/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_3/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Source contracts must be an array.", diff --git a/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_4/output.json b/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_4/output.json index 30d4c2dcf..90790a859 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_4/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_wrong_key_sources_4/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Every contract in settings.modelChecker.contracts must be a string.", diff --git a/test/cmdlineTests/standard_model_checker_divModSlacks_default_all/output.json b/test/cmdlineTests/standard_model_checker_divModSlacks_default_all/output.json index b8637143b..82ee5a107 100644 --- a/test/cmdlineTests/standard_model_checker_divModSlacks_default_all/output.json +++ b/test/cmdlineTests/standard_model_checker_divModSlacks_default_all/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "1391", @@ -12,10 +11,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_divModSlacks_default_bmc/output.json b/test/cmdlineTests/standard_model_checker_divModSlacks_default_bmc/output.json index a6ce9b3c9..dfba53364 100644 --- a/test/cmdlineTests/standard_model_checker_divModSlacks_default_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_divModSlacks_default_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6002", @@ -12,10 +11,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_divModSlacks_default_chc/output.json b/test/cmdlineTests/standard_model_checker_divModSlacks_default_chc/output.json index b8637143b..82ee5a107 100644 --- a/test/cmdlineTests/standard_model_checker_divModSlacks_default_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_divModSlacks_default_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "1391", @@ -12,10 +11,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json b/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json index f7ecf690d..eefa60785 100644 --- a/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json +++ b/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "1218", @@ -13,8 +12,7 @@ ", "message": "CHC: Error trying to invoke SMT solver.", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 182, "file": "A", "start": 177 @@ -33,8 +31,7 @@ ", "message": "CHC: Error trying to invoke SMT solver.", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 189, "file": "A", "start": 184 @@ -62,10 +59,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_divModSlacks_false_bmc/output.json b/test/cmdlineTests/standard_model_checker_divModSlacks_false_bmc/output.json index a6ce9b3c9..dfba53364 100644 --- a/test/cmdlineTests/standard_model_checker_divModSlacks_false_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_divModSlacks_false_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6002", @@ -12,10 +11,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json b/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json index fccd15838..16fb77513 100644 --- a/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "1218", @@ -13,8 +12,7 @@ ", "message": "CHC: Error trying to invoke SMT solver.", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 182, "file": "A", "start": 177 @@ -33,8 +31,7 @@ ", "message": "CHC: Error trying to invoke SMT solver.", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 189, "file": "A", "start": 184 @@ -52,10 +49,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_divModSlacks_wrong/output.json b/test/cmdlineTests/standard_model_checker_divModSlacks_wrong/output.json index 457fb1ba0..dae639c64 100644 --- a/test/cmdlineTests/standard_model_checker_divModSlacks_wrong/output.json +++ b/test/cmdlineTests/standard_model_checker_divModSlacks_wrong/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.divModNoSlacks must be a Boolean.", diff --git a/test/cmdlineTests/standard_model_checker_engine_all/output.json b/test/cmdlineTests/standard_model_checker_engine_all/output.json index 2a2c394fd..be51d6b2e 100644 --- a/test/cmdlineTests/standard_model_checker_engine_all/output.json +++ b/test/cmdlineTests/standard_model_checker_engine_all/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -27,8 +26,7 @@ Transaction trace: C.constructor() C.f(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 119, "file": "A", "start": 106 @@ -36,10 +34,8 @@ C.f(0)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_engine_bmc/output.json b/test/cmdlineTests/standard_model_checker_engine_bmc/output.json index 75e679ef4..4727ea083 100644 --- a/test/cmdlineTests/standard_model_checker_engine_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_engine_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "4661", @@ -17,8 +16,7 @@ Note: ", "message": "BMC: Assertion violation happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: x = 0 @@ -32,8 +30,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 119, "file": "A", "start": 106 @@ -41,10 +38,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_engine_chc/output.json b/test/cmdlineTests/standard_model_checker_engine_chc/output.json index 2a2c394fd..be51d6b2e 100644 --- a/test/cmdlineTests/standard_model_checker_engine_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_engine_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -27,8 +26,7 @@ Transaction trace: C.constructor() C.f(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 119, "file": "A", "start": 106 @@ -36,10 +34,8 @@ C.f(0)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_engine_none/output.json b/test/cmdlineTests/standard_model_checker_engine_none/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_model_checker_engine_none/output.json +++ b/test/cmdlineTests/standard_model_checker_engine_none/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/output.json b/test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/output.json index 4e214a37b..34d69504d 100644 --- a/test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/output.json +++ b/test/cmdlineTests/standard_model_checker_ext_calls_empty_arg/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid model checker extCalls requested.", diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/output.json b/test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/output.json index 7f3993410..16bfff9b7 100644 --- a/test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_ext_calls_trusted_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2018", @@ -13,8 +12,7 @@ ", "message": "Function state mutability can be restricted to pure", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 152, "file": "A", "start": 85 @@ -32,10 +30,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/output.json b/test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/output.json index c6b072a85..858d225e6 100644 --- a/test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_ext_calls_untrusted_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -31,8 +30,7 @@ test.constructor() test.g(0) e.f() -- untrusted external call", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 254, "file": "A", "start": 240 @@ -40,10 +38,8 @@ test.g(0) "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/output.json b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/output.json index 4e214a37b..34d69504d 100644 --- a/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/output.json +++ b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_1/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid model checker extCalls requested.", diff --git a/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/output.json b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/output.json index e869637ed..5daa6a447 100644 --- a/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/output.json +++ b/test/cmdlineTests/standard_model_checker_ext_calls_wrong_arg_2/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.extCalls must be a string.", diff --git a/test/cmdlineTests/standard_model_checker_invariants_contract/output.json b/test/cmdlineTests/standard_model_checker_invariants_contract/output.json index 314b66aae..f3cd0758c 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_contract/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_contract/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "1391", @@ -26,10 +25,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json b/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json index 5a83ba7ac..d46fdda8a 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "9302", @@ -13,8 +12,7 @@ ", "message": "Return value of low-level calls not used.", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 143, "file": "A", "start": 132 @@ -51,8 +49,7 @@ State: x = 0 test.f(0x0) _a.call(\"\") -- untrusted external call", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 166, "file": "A", "start": 151 @@ -60,10 +57,8 @@ test.f(0x0) "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json index feb586a3e..bf6b296cd 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "9302", @@ -13,8 +12,7 @@ ", "message": "Return value of low-level calls not used.", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 143, "file": "A", "start": 132 @@ -50,10 +48,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_invariants_wrong_key/output.json b/test/cmdlineTests/standard_model_checker_invariants_wrong_key/output.json index 45fcfbe98..06b42cb6f 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_wrong_key/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_wrong_key/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid model checker invariants requested.", diff --git a/test/cmdlineTests/standard_model_checker_invariants_wrong_type/output.json b/test/cmdlineTests/standard_model_checker_invariants_wrong_type/output.json index d1992e464..c59605d2c 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_wrong_type/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_wrong_type/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Every invariant type in settings.modelChecker.invariants must be a string.", diff --git a/test/cmdlineTests/standard_model_checker_invariants_wrong_type_2/output.json b/test/cmdlineTests/standard_model_checker_invariants_wrong_type_2/output.json index 078edfc1d..eaa736025 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_wrong_type_2/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_wrong_type_2/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.invariants must be an array.", diff --git a/test/cmdlineTests/standard_model_checker_print_query_all/output.json b/test/cmdlineTests/standard_model_checker_print_query_all/output.json index b8e11ced7..16ff42e0c 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_all/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_all/output.json @@ -1,8 +1,6 @@ { - "auxiliaryInputRequested": - { - "smtlib2queries": - { + "auxiliaryInputRequested": { + "smtlib2queries": { "0x1880095c52d8681601c6821e4a5c29740649509af99947bce54102546dd3376a": "(set-option :timeout 1000) (set-logic HORN) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) @@ -159,8 +157,7 @@ " } }, - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2339", @@ -530,10 +527,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json index f7b4dc7e2..1c9826ad2 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json @@ -1,8 +1,6 @@ { - "auxiliaryInputRequested": - { - "smtlib2queries": - { + "auxiliaryInputRequested": { + "smtlib2queries": { "0x8704a7b848b706ef33cbfc06e4f185636f568a29621126b7244355dd0de956bb": "(set-option :produce-models true) (set-logic ALL) (declare-fun |error_0| () Int) @@ -32,8 +30,7 @@ " } }, - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6240", @@ -119,10 +116,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json index 9ef925b20..a9b0df0fb 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json @@ -1,8 +1,6 @@ { - "auxiliaryInputRequested": - { - "smtlib2queries": - { + "auxiliaryInputRequested": { + "smtlib2queries": { "0x1880095c52d8681601c6821e4a5c29740649509af99947bce54102546dd3376a": "(set-option :timeout 1000) (set-logic HORN) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) @@ -129,8 +127,7 @@ " } }, - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2339", @@ -410,10 +407,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_print_query_invalid_arg/output.json b/test/cmdlineTests/standard_model_checker_print_query_invalid_arg/output.json index 00c389f7a..a9f44c912 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_invalid_arg/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_invalid_arg/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.printQuery must be a Boolean value.", diff --git a/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/output.json b/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/output.json index 42d4b5b2d..d675499f9 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Only SMTLib2 solver can be enabled to print queries", diff --git a/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/output.json b/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/output.json index 42d4b5b2d..d675499f9 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Only SMTLib2 solver can be enabled to print queries", diff --git a/test/cmdlineTests/standard_model_checker_show_proved_safe_default_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_proved_safe_default_all_engines/output.json index b8118ba16..4c57da460 100644 --- a/test/cmdlineTests/standard_model_checker_show_proved_safe_default_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_proved_safe_default_all_engines/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2018", @@ -13,8 +12,7 @@ ", "message": "Function state mutability can be restricted to pure", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 162, "file": "A", "start": 81 @@ -32,10 +30,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_proved_safe_default_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_proved_safe_default_bmc/output.json index eb6ed6e27..6d9dbb409 100644 --- a/test/cmdlineTests/standard_model_checker_show_proved_safe_default_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_proved_safe_default_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2018", @@ -13,8 +12,7 @@ ", "message": "Function state mutability can be restricted to pure", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 162, "file": "A", "start": 81 @@ -32,10 +30,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_proved_safe_default_chc/output.json b/test/cmdlineTests/standard_model_checker_show_proved_safe_default_chc/output.json index b8118ba16..4c57da460 100644 --- a/test/cmdlineTests/standard_model_checker_show_proved_safe_default_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_proved_safe_default_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2018", @@ -13,8 +12,7 @@ ", "message": "Function state mutability can be restricted to pure", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 162, "file": "A", "start": 81 @@ -32,10 +30,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_proved_safe_false_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_proved_safe_false_all_engines/output.json index b8118ba16..4c57da460 100644 --- a/test/cmdlineTests/standard_model_checker_show_proved_safe_false_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_proved_safe_false_all_engines/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2018", @@ -13,8 +12,7 @@ ", "message": "Function state mutability can be restricted to pure", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 162, "file": "A", "start": 81 @@ -32,10 +30,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_proved_safe_false_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_proved_safe_false_bmc/output.json index eb6ed6e27..6d9dbb409 100644 --- a/test/cmdlineTests/standard_model_checker_show_proved_safe_false_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_proved_safe_false_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2018", @@ -13,8 +12,7 @@ ", "message": "Function state mutability can be restricted to pure", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 162, "file": "A", "start": 81 @@ -32,10 +30,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_proved_safe_false_chc/output.json b/test/cmdlineTests/standard_model_checker_show_proved_safe_false_chc/output.json index b8118ba16..4c57da460 100644 --- a/test/cmdlineTests/standard_model_checker_show_proved_safe_false_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_proved_safe_false_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2018", @@ -13,8 +12,7 @@ ", "message": "Function state mutability can be restricted to pure", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 162, "file": "A", "start": 81 @@ -32,10 +30,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_proved_safe_true_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_proved_safe_true_all_engines/output.json index 848229855..22f863b12 100644 --- a/test/cmdlineTests/standard_model_checker_show_proved_safe_true_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_proved_safe_true_all_engines/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2018", @@ -13,8 +12,7 @@ ", "message": "Function state mutability can be restricted to pure", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 162, "file": "A", "start": 81 @@ -33,8 +31,7 @@ ", "message": "CHC: Assertion violation check is safe!", "severity": "info", - "sourceLocation": - { + "sourceLocation": { "end": 130, "file": "A", "start": 116 @@ -53,8 +50,7 @@ ", "message": "CHC: Assertion violation check is safe!", "severity": "info", - "sourceLocation": - { + "sourceLocation": { "end": 154, "file": "A", "start": 138 @@ -62,10 +58,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_proved_safe_true_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_proved_safe_true_bmc/output.json index 20ddce1fd..2788a64a8 100644 --- a/test/cmdlineTests/standard_model_checker_show_proved_safe_true_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_proved_safe_true_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2018", @@ -13,8 +12,7 @@ ", "message": "Function state mutability can be restricted to pure", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 162, "file": "A", "start": 81 @@ -33,8 +31,7 @@ ", "message": "BMC: Assertion violation check is safe!", "severity": "info", - "sourceLocation": - { + "sourceLocation": { "end": 130, "file": "A", "start": 116 @@ -53,8 +50,7 @@ ", "message": "BMC: Assertion violation check is safe!", "severity": "info", - "sourceLocation": - { + "sourceLocation": { "end": 154, "file": "A", "start": 138 @@ -62,10 +58,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_proved_safe_true_chc/output.json b/test/cmdlineTests/standard_model_checker_show_proved_safe_true_chc/output.json index 848229855..22f863b12 100644 --- a/test/cmdlineTests/standard_model_checker_show_proved_safe_true_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_proved_safe_true_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2018", @@ -13,8 +12,7 @@ ", "message": "Function state mutability can be restricted to pure", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 162, "file": "A", "start": 81 @@ -33,8 +31,7 @@ ", "message": "CHC: Assertion violation check is safe!", "severity": "info", - "sourceLocation": - { + "sourceLocation": { "end": 130, "file": "A", "start": 116 @@ -53,8 +50,7 @@ ", "message": "CHC: Assertion violation check is safe!", "severity": "info", - "sourceLocation": - { + "sourceLocation": { "end": 154, "file": "A", "start": 138 @@ -62,10 +58,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_proved_safe_wrong/output.json b/test/cmdlineTests/standard_model_checker_show_proved_safe_wrong/output.json index 7c8ccff6e..b5811ff03 100644 --- a/test/cmdlineTests/standard_model_checker_show_proved_safe_wrong/output.json +++ b/test/cmdlineTests/standard_model_checker_show_proved_safe_wrong/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.showProvedSafe must be a Boolean value.", diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json index fb599d21d..da3b3dcad 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5840", @@ -22,10 +21,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json index fb599d21d..da3b3dcad 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5840", @@ -22,10 +21,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json index 4554ec69e..67f8df731 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2788", @@ -12,10 +11,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_false_chc/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_false_chc/output.json index 7f0e676cb..66cdf505c 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_false_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_false_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5840", @@ -12,10 +11,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json index ecb157f88..b6153de5e 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -13,8 +12,7 @@ ", "message": "CHC: Assertion violation might happen here.", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 201, "file": "A", "start": 186 @@ -33,15 +31,13 @@ Note: ", "message": "BMC: Assertion violation might happen here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "" } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 201, "file": "A", "start": 186 @@ -49,10 +45,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json index 116af8dce..6c3b57c79 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "7812", @@ -13,15 +12,13 @@ Note: ", "message": "BMC: Assertion violation might happen here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "" } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 201, "file": "A", "start": 186 @@ -29,10 +26,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_true_chc/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_true_chc/output.json index 58956287f..78efcad94 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_true_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_true_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -13,8 +12,7 @@ ", "message": "CHC: Assertion violation might happen here.", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 201, "file": "A", "start": 186 @@ -22,10 +20,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_wrong/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_wrong/output.json index a9342cddf..49b97bab5 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_wrong/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_wrong/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.showUnproved must be a Boolean value.", diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_default_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_default_all_engines/output.json index 23cf80def..b8f8515b8 100644 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_default_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unsupported_default_all_engines/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5724", @@ -12,10 +11,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_default_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_default_bmc/output.json index 23cf80def..b8f8515b8 100644 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_default_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unsupported_default_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5724", @@ -12,10 +11,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_default_chc/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_default_chc/output.json index 23cf80def..b8f8515b8 100644 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_default_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unsupported_default_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5724", @@ -12,10 +11,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/output.json index 23cf80def..b8f8515b8 100644 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5724", @@ -12,10 +11,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_false_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_false_bmc/output.json index 23cf80def..b8f8515b8 100644 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_false_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unsupported_false_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5724", @@ -12,10 +11,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_false_chc/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_false_chc/output.json index 23cf80def..b8f8515b8 100644 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_false_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unsupported_false_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5724", @@ -12,10 +11,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_true_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_true_all_engines/output.json index 13d327d40..e9eb877ea 100644 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_true_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unsupported_true_all_engines/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "7737", @@ -13,8 +12,7 @@ ", "message": "Inline assembly may cause SMTChecker to produce spurious warnings (false positives).", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 127, "file": "A", "start": 116 @@ -22,10 +20,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_true_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_true_bmc/output.json index 13d327d40..e9eb877ea 100644 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_true_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unsupported_true_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "7737", @@ -13,8 +12,7 @@ ", "message": "Inline assembly may cause SMTChecker to produce spurious warnings (false positives).", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 127, "file": "A", "start": 116 @@ -22,10 +20,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_true_chc/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_true_chc/output.json index 13d327d40..e9eb877ea 100644 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_true_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unsupported_true_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "7737", @@ -13,8 +12,7 @@ ", "message": "Inline assembly may cause SMTChecker to produce spurious warnings (false positives).", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 127, "file": "A", "start": 116 @@ -22,10 +20,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_wrong/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_wrong/output.json index 997b005ef..068c3a872 100644 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_wrong/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unsupported_wrong/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.showUnsupported must be a Boolean value.", diff --git a/test/cmdlineTests/standard_model_checker_solvers_none/output.json b/test/cmdlineTests/standard_model_checker_solvers_none/output.json index e5d356ce5..e8de49d1e 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_none/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_none/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "7649", @@ -22,10 +21,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json index ebeca53f5..d3bdc6b7e 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json @@ -1,8 +1,6 @@ { - "auxiliaryInputRequested": - { - "smtlib2queries": - { + "auxiliaryInputRequested": { + "smtlib2queries": { "0x75b95497d56c30e254a59358d72ddd4e78f9e90db621cfe677e85d05b2252411": "(set-option :produce-models true) (set-logic ALL) (declare-fun |x_3_3| () Int) @@ -155,8 +153,7 @@ " } }, - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5840", @@ -198,10 +195,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_solvers_z3/output.json b/test/cmdlineTests/standard_model_checker_solvers_z3/output.json index 2a2c394fd..be51d6b2e 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_z3/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_z3/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -27,8 +26,7 @@ Transaction trace: C.constructor() C.f(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 119, "file": "A", "start": 106 @@ -36,10 +34,8 @@ C.f(0)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_solvers_z3_smtlib2/output.json b/test/cmdlineTests/standard_model_checker_solvers_z3_smtlib2/output.json index 2a2c394fd..be51d6b2e 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_z3_smtlib2/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_z3_smtlib2/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -27,8 +26,7 @@ Transaction trace: C.constructor() C.f(0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 119, "file": "A", "start": 106 @@ -36,10 +34,8 @@ C.f(0)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_assert_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_assert_bmc/output.json index 18452ccbc..9e90ec538 100644 --- a/test/cmdlineTests/standard_model_checker_targets_assert_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_assert_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "4661", @@ -18,8 +17,7 @@ Note: ", "message": "BMC: Assertion violation happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: a = 0 @@ -34,8 +32,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 258, "file": "A", "start": 245 @@ -43,10 +40,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json index 5c43fe6b5..bf4fa6626 100644 --- a/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6328", @@ -31,8 +30,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 258, "file": "A", "start": 245 @@ -40,10 +38,8 @@ test.f(0x0, 1)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_balance_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_balance_bmc/output.json index 9ee51daba..6c2c90c98 100644 --- a/test/cmdlineTests/standard_model_checker_targets_balance_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_balance_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "1236", @@ -18,8 +17,7 @@ Note: ", "message": "BMC: Insufficient funds happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: a = 0 @@ -34,8 +32,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 237, "file": "A", "start": 224 @@ -43,10 +40,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_constantCondition_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_constantCondition_bmc/output.json index 94ba81c2b..9bfdf0b02 100644 --- a/test/cmdlineTests/standard_model_checker_targets_constantCondition_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_constantCondition_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6838", @@ -13,15 +12,13 @@ Note: Callstack: ", "message": "BMC: Condition is always true.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Callstack:" } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 165, "file": "A", "start": 159 @@ -29,10 +26,8 @@ Note: Callstack: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json b/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json index 4c967fa5d..2318e5adf 100644 --- a/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "4281", @@ -31,8 +30,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 216, "file": "A", "start": 211 @@ -69,8 +67,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 258, "file": "A", "start": 245 @@ -107,8 +104,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 275, "file": "A", "start": 266 @@ -145,8 +141,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 289, "file": "A", "start": 283 @@ -165,15 +160,13 @@ Note: Callstack: ", "message": "BMC: Condition is always true.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Callstack:" } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 165, "file": "A", "start": 159 @@ -197,8 +190,7 @@ Note: ", "message": "BMC: Insufficient funds happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: a = 0 @@ -213,8 +205,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 237, "file": "A", "start": 224 @@ -222,10 +213,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_default_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_default_bmc/output.json index 1be99ca45..e055d38d2 100644 --- a/test/cmdlineTests/standard_model_checker_targets_default_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_default_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6838", @@ -13,15 +12,13 @@ Note: Callstack: ", "message": "BMC: Condition is always true.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Callstack:" } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 165, "file": "A", "start": 159 @@ -46,8 +43,7 @@ Note: ", "message": "BMC: Division by zero happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: = 0 @@ -63,8 +59,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 216, "file": "A", "start": 211 @@ -88,8 +83,7 @@ Note: ", "message": "BMC: Insufficient funds happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: a = 0 @@ -104,8 +98,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 237, "file": "A", "start": 224 @@ -129,8 +122,7 @@ Note: ", "message": "BMC: Assertion violation happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: a = 0 @@ -145,8 +137,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 258, "file": "A", "start": 245 @@ -154,10 +145,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json index c3df366c9..eb39e0271 100644 --- a/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "4281", @@ -31,8 +30,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 216, "file": "A", "start": 211 @@ -69,8 +67,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 258, "file": "A", "start": 245 @@ -107,8 +104,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 275, "file": "A", "start": 266 @@ -145,8 +141,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 289, "file": "A", "start": 283 @@ -154,10 +149,8 @@ test.f(0x0, 1)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_bmc/output.json index 05ce12ca2..6ba0e6f82 100644 --- a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "3046", @@ -19,8 +18,7 @@ Note: ", "message": "BMC: Division by zero happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: = 0 @@ -36,8 +34,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 216, "file": "A", "start": 211 @@ -45,10 +42,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json index 5c09175e7..0789c7999 100644 --- a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "4281", @@ -31,8 +30,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 216, "file": "A", "start": 211 @@ -40,10 +38,8 @@ test.f(0x0, 1)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_empty_array/output.json b/test/cmdlineTests/standard_model_checker_targets_empty_array/output.json index 312af9741..6b5c6e068 100644 --- a/test/cmdlineTests/standard_model_checker_targets_empty_array/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_empty_array/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.targets must be a non-empty array.", diff --git a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_bmc/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_bmc/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json index b87480e74..f5f49fb50 100644 --- a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6368", @@ -31,8 +30,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 289, "file": "A", "start": 283 @@ -40,10 +38,8 @@ test.f(0x0, 1)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_overflow_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_overflow_bmc/output.json index 09c1cdb5f..8d34765cd 100644 --- a/test/cmdlineTests/standard_model_checker_targets_overflow_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_overflow_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2661", @@ -19,8 +18,7 @@ Note: ", "message": "BMC: Overflow (resulting value larger than 2**256 - 1) happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: = 2**256 @@ -36,8 +34,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 203, "file": "A", "start": 185 @@ -45,10 +42,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json index b700a938e..9beb30a35 100644 --- a/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "4984", @@ -31,8 +30,7 @@ test.constructor() State: arr = [] test.f(0x0, 2)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 203, "file": "A", "start": 185 @@ -40,10 +38,8 @@ test.f(0x0, 2)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_pop_empty_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_pop_empty_bmc/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_model_checker_targets_pop_empty_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_pop_empty_bmc/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json index c670bb4f6..4cccf8456 100644 --- a/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2529", @@ -31,8 +30,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 275, "file": "A", "start": 266 @@ -40,10 +38,8 @@ test.f(0x0, 1)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_bmc/output.json index c656eda21..df17886b2 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "4144", @@ -19,8 +18,7 @@ Note: ", "message": "BMC: Underflow (resulting value less than 0) happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: = (- 1) @@ -36,8 +34,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 177, "file": "A", "start": 174 @@ -45,10 +42,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json index 600d7fe6b..442f2f47a 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "3944", @@ -31,8 +30,7 @@ test.constructor() State: arr = [] test.f(0x0, 0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 177, "file": "A", "start": 174 @@ -40,10 +38,8 @@ test.f(0x0, 0)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_bmc/output.json index 004b98128..c80d3e22a 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "4144", @@ -19,8 +18,7 @@ Note: ", "message": "BMC: Underflow (resulting value less than 0) happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: = (- 1) @@ -36,8 +34,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 177, "file": "A", "start": 174 @@ -62,8 +59,7 @@ Note: ", "message": "BMC: Overflow (resulting value larger than 2**256 - 1) happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: = 2**256 @@ -79,8 +75,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 203, "file": "A", "start": 185 @@ -104,8 +99,7 @@ Note: ", "message": "BMC: Assertion violation happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: a = 0 @@ -120,8 +114,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 258, "file": "A", "start": 245 @@ -129,10 +122,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json index 5afeeaa94..e5719640a 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "3944", @@ -31,8 +30,7 @@ test.constructor() State: arr = [] test.f(0x0, 0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 177, "file": "A", "start": 174 @@ -69,8 +67,7 @@ test.constructor() State: arr = [] test.f(0x0, 2)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 203, "file": "A", "start": 185 @@ -107,8 +104,7 @@ test.constructor() State: arr = [] test.f(0x0, 1)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 258, "file": "A", "start": 245 @@ -116,10 +112,8 @@ test.f(0x0, 1)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_bmc/output.json index 8a9452a7b..de02d57c9 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "4144", @@ -19,8 +18,7 @@ Note: ", "message": "BMC: Underflow (resulting value less than 0) happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: = (- 1) @@ -36,8 +34,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 177, "file": "A", "start": 174 @@ -62,8 +59,7 @@ Note: ", "message": "BMC: Overflow (resulting value larger than 2**256 - 1) happens here.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "message": "Counterexample: = 2**256 @@ -79,8 +75,7 @@ Note: } ], "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 203, "file": "A", "start": 185 @@ -88,10 +83,8 @@ Note: "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json index 9a07b669a..6fb8762e4 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "3944", @@ -31,8 +30,7 @@ test.constructor() State: arr = [] test.f(0x0, 0)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 177, "file": "A", "start": 174 @@ -69,8 +67,7 @@ test.constructor() State: arr = [] test.f(0x0, 2)", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 203, "file": "A", "start": 185 @@ -78,10 +75,8 @@ test.f(0x0, 2)", "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_targets_wrong_target_types/output.json b/test/cmdlineTests/standard_model_checker_targets_wrong_target_types/output.json index 6e2af863e..fee6f2195 100644 --- a/test/cmdlineTests/standard_model_checker_targets_wrong_target_types/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_wrong_target_types/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Every target in settings.modelChecker.targets must be a string.", diff --git a/test/cmdlineTests/standard_model_checker_targets_wrong_target_types_2/output.json b/test/cmdlineTests/standard_model_checker_targets_wrong_target_types_2/output.json index c1e7759b5..996d75e70 100644 --- a/test/cmdlineTests/standard_model_checker_targets_wrong_target_types_2/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_wrong_target_types_2/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.targets must be an array.", diff --git a/test/cmdlineTests/standard_model_checker_targets_wrong_targets/output.json b/test/cmdlineTests/standard_model_checker_targets_wrong_targets/output.json index d0bf7f56d..e51a85258 100644 --- a/test/cmdlineTests/standard_model_checker_targets_wrong_targets/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_wrong_targets/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid model checker targets requested.", diff --git a/test/cmdlineTests/standard_model_checker_timeout_all/output.json b/test/cmdlineTests/standard_model_checker_timeout_all/output.json index 73b117145..2da324f33 100644 --- a/test/cmdlineTests/standard_model_checker_timeout_all/output.json +++ b/test/cmdlineTests/standard_model_checker_timeout_all/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5840", @@ -32,10 +31,8 @@ "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_timeout_bmc/output.json b/test/cmdlineTests/standard_model_checker_timeout_bmc/output.json index a709ec062..f813782d7 100644 --- a/test/cmdlineTests/standard_model_checker_timeout_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_timeout_bmc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2788", @@ -22,10 +21,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_timeout_chc/output.json b/test/cmdlineTests/standard_model_checker_timeout_chc/output.json index 553a1b93b..1ff515e25 100644 --- a/test/cmdlineTests/standard_model_checker_timeout_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_timeout_chc/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "5840", @@ -22,10 +21,8 @@ "type": "Info" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_model_checker_timeout_wrong_key/output.json b/test/cmdlineTests/standard_model_checker_timeout_wrong_key/output.json index 137562f41..afa05c3a8 100644 --- a/test/cmdlineTests/standard_model_checker_timeout_wrong_key/output.json +++ b/test/cmdlineTests/standard_model_checker_timeout_wrong_key/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Unknown key \"atimeout\"", diff --git a/test/cmdlineTests/standard_model_checker_timeout_wrong_value/output.json b/test/cmdlineTests/standard_model_checker_timeout_wrong_value/output.json index ce630905c..7fbdfbbe8 100644 --- a/test/cmdlineTests/standard_model_checker_timeout_wrong_value/output.json +++ b/test/cmdlineTests/standard_model_checker_timeout_wrong_value/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "settings.modelChecker.timeout must be an unsigned integer.", diff --git a/test/cmdlineTests/standard_no_append_cbor/output.json b/test/cmdlineTests/standard_no_append_cbor/output.json index 0fca3f271..c060efd97 100644 --- a/test/cmdlineTests/standard_no_append_cbor/output.json +++ b/test/cmdlineTests/standard_no_append_cbor/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "A": - { - "test": - { - "evm": - { - "bytecode": - { + "contracts": { + "A": { + "test": { + "evm": { + "bytecode": { "functionDebugData": {}, "generatedSources": [], "linkReferences": {}, @@ -20,10 +15,8 @@ } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_no_append_cbor_with_metadata_hash/output.json b/test/cmdlineTests/standard_no_append_cbor_with_metadata_hash/output.json index 0c264f898..a31841944 100644 --- a/test/cmdlineTests/standard_no_append_cbor_with_metadata_hash/output.json +++ b/test/cmdlineTests/standard_no_append_cbor_with_metadata_hash/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "When the parameter \"appendCBOR\" is set to false, the parameter \"bytecodeHash\" cannot be set to \"ipfs\". The parameter \"bytecodeHash\" should either be skipped, or set to \"none\".", diff --git a/test/cmdlineTests/standard_no_import_callback/output.json b/test/cmdlineTests/standard_no_import_callback/output.json index a4e2d8d3a..3c16f1caa 100644 --- a/test/cmdlineTests/standard_no_import_callback/output.json +++ b/test/cmdlineTests/standard_no_import_callback/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "6275", @@ -13,8 +12,7 @@ ", "message": "Source \"standard_no_import_callback/B.sol\" not found: No import callback.", "severity": "error", - "sourceLocation": - { + "sourceLocation": { "end": 102, "file": "A", "start": 59 diff --git a/test/cmdlineTests/standard_non_utf8_filename/output.json b/test/cmdlineTests/standard_non_utf8_filename/output.json index a74a83a98..5dc1b6f1b 100644 --- a/test/cmdlineTests/standard_non_utf8_filename/output.json +++ b/test/cmdlineTests/standard_non_utf8_filename/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: ill-formed UTF-8 byte; last read: '\"\\xff'; expected string literal", diff --git a/test/cmdlineTests/standard_non_utf8_filename2/output.json b/test/cmdlineTests/standard_non_utf8_filename2/output.json index a74a83a98..5dc1b6f1b 100644 --- a/test/cmdlineTests/standard_non_utf8_filename2/output.json +++ b/test/cmdlineTests/standard_non_utf8_filename2/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: ill-formed UTF-8 byte; last read: '\"\\xff'; expected string literal", diff --git a/test/cmdlineTests/standard_only_ast_requested/output.json b/test/cmdlineTests/standard_only_ast_requested/output.json index 6ecac5ca3..d54da1750 100644 --- a/test/cmdlineTests/standard_only_ast_requested/output.json +++ b/test/cmdlineTests/standard_only_ast_requested/output.json @@ -1,27 +1,20 @@ { - "sources": - { - "A": - { - "ast": - { + "sources": { + "A": { + "ast": { "absolutePath": "A", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", ">=", "0.0" @@ -37,18 +30,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "68:1:0", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "97:2:0", @@ -62,15 +52,13 @@ "name": "f", "nameLocation": "81:1:0", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], "src": "82:2:0" }, - "returnParameters": - { + "returnParameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], diff --git a/test/cmdlineTests/standard_optimizer_generatedSources/output.json b/test/cmdlineTests/standard_optimizer_generatedSources/output.json index da2c31cbe..0f8c3d4ea 100644 --- a/test/cmdlineTests/standard_optimizer_generatedSources/output.json +++ b/test/cmdlineTests/standard_optimizer_generatedSources/output.json @@ -1,29 +1,20 @@ { - "contracts": - { - "a.sol": - { - "A": - { - "evm": - { - "bytecode": - { + "contracts": { + "a.sol": { + "A": { + "evm": { + "bytecode": { "generatedSources": [], "object": "" }, - "deployedBytecode": - { - "generatedSources": - [ + "deployedBytecode": { + "generatedSources": [ { - "ast": - { + "ast": { "nativeSrc": "0:1445:1", "nodeType": "YulBlock", "src": "0:1445:1", - "statements": - [ + "statements": [ { "nativeSrc": "6:3:1", "nodeType": "YulBlock", @@ -31,18 +22,14 @@ "statements": [] }, { - "body": - { + "body": { "nativeSrc": "46:95:1", "nodeType": "YulBlock", "src": "46:95:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "63:1:1", @@ -52,8 +39,7 @@ "value": "0" }, { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "70:3:1", @@ -71,8 +57,7 @@ "value": "0x4e487b71" } ], - "functionName": - { + "functionName": { "name": "shl", "nativeSrc": "66:3:1", "nodeType": "YulIdentifier", @@ -83,8 +68,7 @@ "src": "66:20:1" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "56:6:1", "nodeType": "YulIdentifier", @@ -99,10 +83,8 @@ "src": "56:31:1" }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "103:1:1", @@ -120,8 +102,7 @@ "value": "0x41" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "96:6:1", "nodeType": "YulIdentifier", @@ -136,10 +117,8 @@ "src": "96:15:1" }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "127:1:1", @@ -157,8 +136,7 @@ "value": "0x24" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "120:6:1", "nodeType": "YulIdentifier", @@ -180,19 +158,16 @@ "src": "14:127:1" }, { - "body": - { + "body": { "nativeSrc": "241:1020:1", "nodeType": "YulBlock", "src": "241:1020:1", - "statements": - [ + "statements": [ { "nativeSrc": "251:12:1", "nodeType": "YulVariableDeclaration", "src": "251:12:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "261:2:1", "nodeType": "YulLiteral", @@ -200,8 +175,7 @@ "type": "", "value": "32" }, - "variables": - [ + "variables": [ { "name": "_1", "nativeSrc": "255:2:1", @@ -212,18 +186,14 @@ ] }, { - "body": - { + "body": { "nativeSrc": "308:16:1", "nodeType": "YulBlock", "src": "308:16:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "317:1:1", @@ -241,8 +211,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "310:6:1", "nodeType": "YulIdentifier", @@ -258,13 +227,10 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "dataEnd", "nativeSrc": "283:7:1", @@ -278,8 +244,7 @@ "src": "292:9:1" } ], - "functionName": - { + "functionName": { "name": "sub", "nativeSrc": "279:3:1", "nodeType": "YulIdentifier", @@ -296,8 +261,7 @@ "src": "304:2:1" } ], - "functionName": - { + "functionName": { "name": "slt", "nativeSrc": "275:3:1", "nodeType": "YulIdentifier", @@ -315,10 +279,8 @@ "nativeSrc": "333:37:1", "nodeType": "YulVariableDeclaration", "src": "333:37:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "headStart", "nativeSrc": "360:9:1", @@ -326,8 +288,7 @@ "src": "360:9:1" } ], - "functionName": - { + "functionName": { "name": "calldataload", "nativeSrc": "347:12:1", "nodeType": "YulIdentifier", @@ -337,8 +298,7 @@ "nodeType": "YulFunctionCall", "src": "347:23:1" }, - "variables": - [ + "variables": [ { "name": "offset", "nativeSrc": "337:6:1", @@ -352,8 +312,7 @@ "nativeSrc": "379:28:1", "nodeType": "YulVariableDeclaration", "src": "379:28:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "389:18:1", "nodeType": "YulLiteral", @@ -361,8 +320,7 @@ "type": "", "value": "0xffffffffffffffff" }, - "variables": - [ + "variables": [ { "name": "_2", "nativeSrc": "383:2:1", @@ -373,18 +331,14 @@ ] }, { - "body": - { + "body": { "nativeSrc": "434:16:1", "nodeType": "YulBlock", "src": "434:16:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "443:1:1", @@ -402,8 +356,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "436:6:1", "nodeType": "YulIdentifier", @@ -419,10 +372,8 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { "name": "offset", "nativeSrc": "422:6:1", @@ -436,8 +387,7 @@ "src": "430:2:1" } ], - "functionName": - { + "functionName": { "name": "gt", "nativeSrc": "419:2:1", "nodeType": "YulIdentifier", @@ -455,10 +405,8 @@ "nativeSrc": "459:32:1", "nodeType": "YulVariableDeclaration", "src": "459:32:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "headStart", "nativeSrc": "473:9:1", @@ -472,8 +420,7 @@ "src": "484:6:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "469:3:1", "nodeType": "YulIdentifier", @@ -483,8 +430,7 @@ "nodeType": "YulFunctionCall", "src": "469:22:1" }, - "variables": - [ + "variables": [ { "name": "_3", "nativeSrc": "463:2:1", @@ -495,18 +441,14 @@ ] }, { - "body": - { + "body": { "nativeSrc": "539:16:1", "nodeType": "YulBlock", "src": "539:16:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "548:1:1", @@ -524,8 +466,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "541:6:1", "nodeType": "YulIdentifier", @@ -541,16 +482,12 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { - "arguments": - [ + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "_3", "nativeSrc": "518:2:1", @@ -566,8 +503,7 @@ "value": "0x1f" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "514:3:1", "nodeType": "YulIdentifier", @@ -584,8 +520,7 @@ "src": "529:7:1" } ], - "functionName": - { + "functionName": { "name": "slt", "nativeSrc": "510:3:1", "nodeType": "YulIdentifier", @@ -596,8 +531,7 @@ "src": "510:27:1" } ], - "functionName": - { + "functionName": { "name": "iszero", "nativeSrc": "503:6:1", "nodeType": "YulIdentifier", @@ -615,10 +549,8 @@ "nativeSrc": "564:26:1", "nodeType": "YulVariableDeclaration", "src": "564:26:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "_3", "nativeSrc": "587:2:1", @@ -626,8 +558,7 @@ "src": "587:2:1" } ], - "functionName": - { + "functionName": { "name": "calldataload", "nativeSrc": "574:12:1", "nodeType": "YulIdentifier", @@ -637,8 +568,7 @@ "nodeType": "YulFunctionCall", "src": "574:16:1" }, - "variables": - [ + "variables": [ { "name": "_4", "nativeSrc": "568:2:1", @@ -649,19 +579,15 @@ ] }, { - "body": - { + "body": { "nativeSrc": "613:22:1", "nodeType": "YulBlock", "src": "613:22:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "panic_error_0x41", "nativeSrc": "615:16:1", "nodeType": "YulIdentifier", @@ -677,10 +603,8 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { "name": "_4", "nativeSrc": "605:2:1", @@ -694,8 +618,7 @@ "src": "609:2:1" } ], - "functionName": - { + "functionName": { "name": "gt", "nativeSrc": "602:2:1", "nodeType": "YulIdentifier", @@ -713,10 +636,8 @@ "nativeSrc": "644:20:1", "nodeType": "YulVariableDeclaration", "src": "644:20:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "658:1:1", @@ -732,8 +653,7 @@ "src": "661:2:1" } ], - "functionName": - { + "functionName": { "name": "shl", "nativeSrc": "654:3:1", "nodeType": "YulIdentifier", @@ -743,8 +663,7 @@ "nodeType": "YulFunctionCall", "src": "654:10:1" }, - "variables": - [ + "variables": [ { "name": "_5", "nativeSrc": "648:2:1", @@ -758,10 +677,8 @@ "nativeSrc": "673:23:1", "nodeType": "YulVariableDeclaration", "src": "673:23:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "693:2:1", @@ -771,8 +688,7 @@ "value": "64" } ], - "functionName": - { + "functionName": { "name": "mload", "nativeSrc": "687:5:1", "nodeType": "YulIdentifier", @@ -782,8 +698,7 @@ "nodeType": "YulFunctionCall", "src": "687:9:1" }, - "variables": - [ + "variables": [ { "name": "memPtr", "nativeSrc": "677:6:1", @@ -797,10 +712,8 @@ "nativeSrc": "705:56:1", "nodeType": "YulVariableDeclaration", "src": "705:56:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "memPtr", "nativeSrc": "727:6:1", @@ -808,11 +721,9 @@ "src": "727:6:1" }, { - "arguments": - [ + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "_5", "nativeSrc": "743:2:1", @@ -828,8 +739,7 @@ "value": "63" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "739:3:1", "nodeType": "YulIdentifier", @@ -840,8 +750,7 @@ "src": "739:11:1" }, { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "756:2:1", @@ -851,8 +760,7 @@ "value": "31" } ], - "functionName": - { + "functionName": { "name": "not", "nativeSrc": "752:3:1", "nodeType": "YulIdentifier", @@ -863,8 +771,7 @@ "src": "752:7:1" } ], - "functionName": - { + "functionName": { "name": "and", "nativeSrc": "735:3:1", "nodeType": "YulIdentifier", @@ -875,8 +782,7 @@ "src": "735:25:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "723:3:1", "nodeType": "YulIdentifier", @@ -886,8 +792,7 @@ "nodeType": "YulFunctionCall", "src": "723:38:1" }, - "variables": - [ + "variables": [ { "name": "newFreePtr", "nativeSrc": "709:10:1", @@ -898,19 +803,15 @@ ] }, { - "body": - { + "body": { "nativeSrc": "820:22:1", "nodeType": "YulBlock", "src": "820:22:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "panic_error_0x41", "nativeSrc": "822:16:1", "nodeType": "YulIdentifier", @@ -926,13 +827,10 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "newFreePtr", "nativeSrc": "779:10:1", @@ -946,8 +844,7 @@ "src": "791:2:1" } ], - "functionName": - { + "functionName": { "name": "gt", "nativeSrc": "776:2:1", "nodeType": "YulIdentifier", @@ -958,8 +855,7 @@ "src": "776:18:1" }, { - "arguments": - [ + "arguments": [ { "name": "newFreePtr", "nativeSrc": "799:10:1", @@ -973,8 +869,7 @@ "src": "811:6:1" } ], - "functionName": - { + "functionName": { "name": "lt", "nativeSrc": "796:2:1", "nodeType": "YulIdentifier", @@ -985,8 +880,7 @@ "src": "796:22:1" } ], - "functionName": - { + "functionName": { "name": "or", "nativeSrc": "773:2:1", "nodeType": "YulIdentifier", @@ -1001,10 +895,8 @@ "src": "770:72:1" }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "858:2:1", @@ -1020,8 +912,7 @@ "src": "862:10:1" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "851:6:1", "nodeType": "YulIdentifier", @@ -1039,15 +930,13 @@ "nativeSrc": "882:17:1", "nodeType": "YulVariableDeclaration", "src": "882:17:1", - "value": - { + "value": { "name": "memPtr", "nativeSrc": "893:6:1", "nodeType": "YulIdentifier", "src": "893:6:1" }, - "variables": - [ + "variables": [ { "name": "dst", "nativeSrc": "886:3:1", @@ -1058,10 +947,8 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "memPtr", "nativeSrc": "915:6:1", @@ -1075,8 +962,7 @@ "src": "923:2:1" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "908:6:1", "nodeType": "YulIdentifier", @@ -1094,10 +980,8 @@ "nativeSrc": "935:22:1", "nodeType": "YulAssignment", "src": "935:22:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "memPtr", "nativeSrc": "946:6:1", @@ -1111,8 +995,7 @@ "src": "954:2:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "942:3:1", "nodeType": "YulIdentifier", @@ -1122,8 +1005,7 @@ "nodeType": "YulFunctionCall", "src": "942:15:1" }, - "variableNames": - [ + "variableNames": [ { "name": "dst", "nativeSrc": "935:3:1", @@ -1136,13 +1018,10 @@ "nativeSrc": "966:34:1", "nodeType": "YulVariableDeclaration", "src": "966:34:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "_3", "nativeSrc": "988:2:1", @@ -1156,8 +1035,7 @@ "src": "992:2:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "984:3:1", "nodeType": "YulIdentifier", @@ -1174,8 +1052,7 @@ "src": "997:2:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "980:3:1", "nodeType": "YulIdentifier", @@ -1185,8 +1062,7 @@ "nodeType": "YulFunctionCall", "src": "980:20:1" }, - "variables": - [ + "variables": [ { "name": "srcEnd", "nativeSrc": "970:6:1", @@ -1197,18 +1073,14 @@ ] }, { - "body": - { + "body": { "nativeSrc": "1032:16:1", "nodeType": "YulBlock", "src": "1032:16:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "1041:1:1", @@ -1226,8 +1098,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "1034:6:1", "nodeType": "YulIdentifier", @@ -1243,10 +1114,8 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { "name": "srcEnd", "nativeSrc": "1015:6:1", @@ -1260,8 +1129,7 @@ "src": "1023:7:1" } ], - "functionName": - { + "functionName": { "name": "gt", "nativeSrc": "1012:2:1", "nodeType": "YulIdentifier", @@ -1279,10 +1147,8 @@ "nativeSrc": "1057:22:1", "nodeType": "YulVariableDeclaration", "src": "1057:22:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "_3", "nativeSrc": "1072:2:1", @@ -1296,8 +1162,7 @@ "src": "1076:2:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "1068:3:1", "nodeType": "YulIdentifier", @@ -1307,8 +1172,7 @@ "nodeType": "YulFunctionCall", "src": "1068:11:1" }, - "variables": - [ + "variables": [ { "name": "src", "nativeSrc": "1061:3:1", @@ -1319,18 +1183,14 @@ ] }, { - "body": - { + "body": { "nativeSrc": "1144:86:1", "nodeType": "YulBlock", "src": "1144:86:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "dst", "nativeSrc": "1165:3:1", @@ -1338,8 +1198,7 @@ "src": "1165:3:1" }, { - "arguments": - [ + "arguments": [ { "name": "src", "nativeSrc": "1183:3:1", @@ -1347,8 +1206,7 @@ "src": "1183:3:1" } ], - "functionName": - { + "functionName": { "name": "calldataload", "nativeSrc": "1170:12:1", "nodeType": "YulIdentifier", @@ -1359,8 +1217,7 @@ "src": "1170:17:1" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "1158:6:1", "nodeType": "YulIdentifier", @@ -1378,10 +1235,8 @@ "nativeSrc": "1201:19:1", "nodeType": "YulAssignment", "src": "1201:19:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "dst", "nativeSrc": "1212:3:1", @@ -1395,8 +1250,7 @@ "src": "1217:2:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "1208:3:1", "nodeType": "YulIdentifier", @@ -1406,8 +1260,7 @@ "nodeType": "YulFunctionCall", "src": "1208:12:1" }, - "variableNames": - [ + "variableNames": [ { "name": "dst", "nativeSrc": "1201:3:1", @@ -1418,10 +1271,8 @@ } ] }, - "condition": - { - "arguments": - [ + "condition": { + "arguments": [ { "name": "src", "nativeSrc": "1099:3:1", @@ -1435,8 +1286,7 @@ "src": "1104:6:1" } ], - "functionName": - { + "functionName": { "name": "lt", "nativeSrc": "1096:2:1", "nodeType": "YulIdentifier", @@ -1448,21 +1298,17 @@ }, "nativeSrc": "1088:142:1", "nodeType": "YulForLoop", - "post": - { + "post": { "nativeSrc": "1112:23:1", "nodeType": "YulBlock", "src": "1112:23:1", - "statements": - [ + "statements": [ { "nativeSrc": "1114:19:1", "nodeType": "YulAssignment", "src": "1114:19:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "src", "nativeSrc": "1125:3:1", @@ -1476,8 +1322,7 @@ "src": "1130:2:1" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "1121:3:1", "nodeType": "YulIdentifier", @@ -1487,8 +1332,7 @@ "nodeType": "YulFunctionCall", "src": "1121:12:1" }, - "variableNames": - [ + "variableNames": [ { "name": "src", "nativeSrc": "1114:3:1", @@ -1499,8 +1343,7 @@ } ] }, - "pre": - { + "pre": { "nativeSrc": "1092:3:1", "nodeType": "YulBlock", "src": "1092:3:1", @@ -1512,15 +1355,13 @@ "nativeSrc": "1239:16:1", "nodeType": "YulAssignment", "src": "1239:16:1", - "value": - { + "value": { "name": "memPtr", "nativeSrc": "1249:6:1", "nodeType": "YulIdentifier", "src": "1249:6:1" }, - "variableNames": - [ + "variableNames": [ { "name": "value0", "nativeSrc": "1239:6:1", @@ -1534,8 +1375,7 @@ "name": "abi_decode_tuple_t_array$_t_uint256_$dyn_memory_ptr", "nativeSrc": "146:1115:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "headStart", "nativeSrc": "207:9:1", @@ -1551,8 +1391,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "value0", "nativeSrc": "230:6:1", @@ -1564,21 +1403,17 @@ "src": "146:1115:1" }, { - "body": - { + "body": { "nativeSrc": "1367:76:1", "nodeType": "YulBlock", "src": "1367:76:1", - "statements": - [ + "statements": [ { "nativeSrc": "1377:26:1", "nodeType": "YulAssignment", "src": "1377:26:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "headStart", "nativeSrc": "1389:9:1", @@ -1594,8 +1429,7 @@ "value": "32" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "1385:3:1", "nodeType": "YulIdentifier", @@ -1605,8 +1439,7 @@ "nodeType": "YulFunctionCall", "src": "1385:18:1" }, - "variableNames": - [ + "variableNames": [ { "name": "tail", "nativeSrc": "1377:4:1", @@ -1616,10 +1449,8 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "name": "headStart", "nativeSrc": "1419:9:1", @@ -1633,8 +1464,7 @@ "src": "1430:6:1" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "1412:6:1", "nodeType": "YulIdentifier", @@ -1653,8 +1483,7 @@ "name": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed", "nativeSrc": "1266:177:1", "nodeType": "YulFunctionDefinition", - "parameters": - [ + "parameters": [ { "name": "headStart", "nativeSrc": "1336:9:1", @@ -1670,8 +1499,7 @@ "type": "" } ], - "returnVariables": - [ + "returnVariables": [ { "name": "tail", "nativeSrc": "1358:4:1", @@ -1737,10 +1565,8 @@ } } }, - "sources": - { - "a.sol": - { + "sources": { + "a.sol": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_invalid_detail_type/output.json b/test/cmdlineTests/standard_optimizer_invalid_detail_type/output.json index 2601dea6c..10ba5e396 100644 --- a/test/cmdlineTests/standard_optimizer_invalid_detail_type/output.json +++ b/test/cmdlineTests/standard_optimizer_invalid_detail_type/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.optimizer.details.peephole\" must be Boolean", diff --git a/test/cmdlineTests/standard_optimizer_invalid_details/output.json b/test/cmdlineTests/standard_optimizer_invalid_details/output.json index c7dfaf314..79b0de4e8 100644 --- a/test/cmdlineTests/standard_optimizer_invalid_details/output.json +++ b/test/cmdlineTests/standard_optimizer_invalid_details/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Unknown key \"notThere\"", diff --git a/test/cmdlineTests/standard_optimizer_no_yul/output.json b/test/cmdlineTests/standard_optimizer_no_yul/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_optimizer_no_yul/output.json +++ b/test/cmdlineTests/standard_optimizer_no_yul/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yul/output.json b/test/cmdlineTests/standard_optimizer_yul/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_optimizer_yul/output.json +++ b/test/cmdlineTests/standard_optimizer_yul/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails/output.json b/test/cmdlineTests/standard_optimizer_yulDetails/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_no_object/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/output.json index 86a0c8698..c658301e9 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_no_object/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.optimizer.details.yulDetails\" must be an object", diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json index 725822763..c461a1485 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json @@ -1,18 +1,13 @@ { - "contracts": - { - "A": - { - "C": - { + "contracts": { + "A": { + "C": { "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json index 725822763..c461a1485 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json @@ -1,18 +1,13 @@ { - "contracts": - { - "A": - { - "C": - { + "contracts": { + "A": { + "C": { "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/output.json index d4f6ef3a7..267a8c360 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": 'b' is not a valid step abbreviation", diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nested_delimiter/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nested_delimiter/output.json index f44ca7e2e..ea101d2e1 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nested_delimiter/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nested_delimiter/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Cleanup sequence delimiter cannot be placed inside the brackets", diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_mutliple_delimiters/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_mutliple_delimiters/output.json index 16cba14d7..595049f41 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_mutliple_delimiters/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_mutliple_delimiters/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Too many cleanup sequence delimiters", diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/output.json index e06e14205..25fc97e47 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Brackets nested too deep", diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/output.json index e0b6a26c1..322a7e25b 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted. Note that the empty optimizer sequence is properly denoted by \":\".", diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/output.json index e0b6a26c1..322a7e25b 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted. Note that the empty optimizer sequence is properly denoted by \":\".", diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/output.json index e0b6a26c1..322a7e25b 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted. Note that the empty optimizer sequence is properly denoted by \":\".", diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/output.json index d6f9a9df8..a1e5151c1 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.optimizer.details.optimizerSteps\" must be a string", diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/output.json index 316529b0d..3f93509f2 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Unbalanced brackets", diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/output.json index 316529b0d..3f93509f2 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Unbalanced brackets", diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_cleanup_sequence/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_cleanup_sequence/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_cleanup_sequence/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_cleanup_sequence/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_cleanup_sequence/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_cleanup_sequence/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_cleanup_sequence/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_cleanup_sequence/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_optimisation_sequence/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_optimisation_sequence/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_optimisation_sequence/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_optimisation_sequence/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_whitespace_newline_sequence_no_yul/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_whitespace_newline_sequence_no_yul/output.json index acf3b74ef..f047ff70a 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_whitespace_newline_sequence_no_yul/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_whitespace_newline_sequence_no_yul/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/output.json index 2470015e1..1da39084e 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Only optimizerSteps can be set in yulDetails when Yul optimizer is disabled.", diff --git a/test/cmdlineTests/standard_outputs_on_analysis_error_fatal/output.json b/test/cmdlineTests/standard_outputs_on_analysis_error_fatal/output.json index 51d12668f..e0c839753 100644 --- a/test/cmdlineTests/standard_outputs_on_analysis_error_fatal/output.json +++ b/test/cmdlineTests/standard_outputs_on_analysis_error_fatal/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "3644", @@ -13,8 +12,7 @@ ", "message": "This parameter has a type that can only be used internally. You can make the contract abstract to avoid this problem.", "severity": "error", - "sourceLocation": - { + "sourceLocation": { "end": 258, "file": "C", "start": 244 diff --git a/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/output.json b/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/output.json index d47ded5d4..d6357a5b1 100644 --- a/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/output.json +++ b/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "8297", @@ -13,8 +12,7 @@ ", "message": "The \"immutable\" keyword can only be used for state variables.", "severity": "error", - "sourceLocation": - { + "sourceLocation": { "end": 259, "file": "C", "start": 243 diff --git a/test/cmdlineTests/standard_outputs_on_analysis_error_non_fatal/output.json b/test/cmdlineTests/standard_outputs_on_analysis_error_non_fatal/output.json index 2f3aaae44..2dcecead0 100644 --- a/test/cmdlineTests/standard_outputs_on_analysis_error_non_fatal/output.json +++ b/test/cmdlineTests/standard_outputs_on_analysis_error_non_fatal/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "7407", @@ -13,8 +12,7 @@ ", "message": "Type uint256 is not implicitly convertible to expected type string storage ref.", "severity": "error", - "sourceLocation": - { + "sourceLocation": { "end": 235, "file": "C", "start": 234 diff --git a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json index aae6d02f6..09f4afc4e 100644 --- a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json +++ b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "C": - { - "C": - { - "abi": - [ + "contracts": { + "C": { + "C": { + "abi": [ { "inputs": [], "stateMutability": "nonpayable", @@ -15,8 +11,7 @@ { "inputs": [], "name": "x", - "outputs": - [ + "outputs": [ { "internalType": "uint256", "name": "", @@ -27,27 +22,22 @@ "type": "function" } ], - "devdoc": - { + "devdoc": { "kind": "dev", "methods": {}, "version": 1 }, - "evm": - { - "methodIdentifiers": - { + "evm": { + "methodIdentifiers": { "x()": "0c55699c" } }, "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x67a13ebd685e4c6f792e71eb747dac57edb99e94d04d841ee6c979ae517934ce\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://665b000da768823654f680d02686c1e59d682a0b3882e43a77fed9f80ce64ae8\",\"dweb:/ipfs/QmVnKvuidH6KiCdNQpoAQUtDbB8hXkafVLXWMNitUcxnqC\"]}},\"version\":1}", - "storageLayout": - { + "storageLayout": { "storage": [], "types": null }, - "userdoc": - { + "userdoc": { "kind": "user", "methods": {}, "version": 1 @@ -55,8 +45,7 @@ } } }, - "errors": - [ + "errors": [ { "component": "general", "errorCode": "1284", @@ -68,29 +57,22 @@ "type": "CodeGenerationError" } ], - "sources": - { - "C": - { - "ast": - { + "sources": { + "C": { + "ast": { "absolutePath": "C", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 15 ] }, "id": 16, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", "*" ], @@ -105,15 +87,13 @@ "contractKind": "contract", "fullyImplemented": true, "id": 15, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 15 ], "name": "C", "nameLocation": "65:1:0", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "functionSelector": "0c55699c", @@ -126,19 +106,16 @@ "src": "228:23:0", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 2, "name": "uint", "nodeType": "ElementaryTypeName", "src": "228:4:0", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -146,39 +123,33 @@ "visibility": "public" }, { - "body": - { + "body": { "id": 13, "nodeType": "Block", "src": "272:46:0", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "id": 8, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, - "leftHandSide": - { + "leftHandSide": { "id": 6, "name": "x", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 3, "src": "282:1:0", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "Assignment", "operator": "=", - "rightHandSide": - { + "rightHandSide": { "hexValue": "30", "id": 7, "isConstant": false, @@ -188,16 +159,14 @@ "lValueRequested": false, "nodeType": "Literal", "src": "286:1:0", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_0_by_1", "typeString": "int_const 0" }, "value": "0" }, "src": "282:5:0", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -207,15 +176,13 @@ "src": "282:5:0" }, { - "body": - { + "body": { "id": 11, "nodeType": "Block", "src": "310:2:0", "statements": [] }, - "condition": - { + "condition": { "hexValue": "74727565", "id": 10, "isConstant": false, @@ -225,8 +192,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "304:4:0", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" }, @@ -245,15 +211,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], "src": "269:2:0" }, - "returnParameters": - { + "returnParameters": { "id": 5, "nodeType": "ParameterList", "parameters": [], diff --git a/test/cmdlineTests/standard_outputs_on_parsing_error/output.json b/test/cmdlineTests/standard_outputs_on_parsing_error/output.json index 8c1f6c0db..6730d772e 100644 --- a/test/cmdlineTests/standard_outputs_on_parsing_error/output.json +++ b/test/cmdlineTests/standard_outputs_on_parsing_error/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "7858", @@ -13,8 +12,7 @@ ", "message": "Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition.", "severity": "error", - "sourceLocation": - { + "sourceLocation": { "end": 121, "file": "C", "start": 120 diff --git a/test/cmdlineTests/standard_parsing_import_absolute_paths/output.json b/test/cmdlineTests/standard_parsing_import_absolute_paths/output.json index 1982561ef..1be9f4b0d 100644 --- a/test/cmdlineTests/standard_parsing_import_absolute_paths/output.json +++ b/test/cmdlineTests/standard_parsing_import_absolute_paths/output.json @@ -1,20 +1,15 @@ { - "sources": - { - "/lib/L.sol": - { - "ast": - { + "sources": { + "/lib/L.sol": { + "ast": { "absolutePath": "/lib/L.sol", "id": 2, "license": "GPL-2.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", ">=", "0.0" @@ -27,20 +22,16 @@ }, "id": 0 }, - "/project/../C.sol": - { - "ast": - { + "/project/../C.sol": { + "ast": { "absolutePath": "/project/../C.sol", "id": 5, "license": "GPL-2.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 3, - "literals": - [ + "literals": [ "solidity", ">=", "0.0" diff --git a/test/cmdlineTests/standard_raw_utf16_filename/output.json b/test/cmdlineTests/standard_raw_utf16_filename/output.json index a370472f2..cebd87943 100644 --- a/test/cmdlineTests/standard_raw_utf16_filename/output.json +++ b/test/cmdlineTests/standard_raw_utf16_filename/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "parse error at line 5, column 4: syntax error while parsing object key - invalid string: control character U+0000 (NUL) must be escaped to \\u0000; last read: '\"'; expected string literal", diff --git a/test/cmdlineTests/standard_secondary_source_location/output.json b/test/cmdlineTests/standard_secondary_source_location/output.json index 6423769aa..ea47eeaad 100644 --- a/test/cmdlineTests/standard_secondary_source_location/output.json +++ b/test/cmdlineTests/standard_secondary_source_location/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "errorCode": "3364", @@ -22,8 +21,7 @@ Note: Second constructor call is here: ", "message": "Base constructor arguments given twice.", - "secondarySourceLocations": - [ + "secondarySourceLocations": [ { "end": 112, "file": "A", @@ -38,8 +36,7 @@ Note: Second constructor call is here: } ], "severity": "error", - "sourceLocation": - { + "sourceLocation": { "end": 160, "file": "A", "start": 139 diff --git a/test/cmdlineTests/standard_stop_after_parsing_ast_requested/output.json b/test/cmdlineTests/standard_stop_after_parsing_ast_requested/output.json index 6907d4780..3bddad829 100644 --- a/test/cmdlineTests/standard_stop_after_parsing_ast_requested/output.json +++ b/test/cmdlineTests/standard_stop_after_parsing_ast_requested/output.json @@ -1,20 +1,15 @@ { - "sources": - { - "C": - { - "ast": - { + "sources": { + "C": { + "ast": { "absolutePath": "C", "id": 4, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", "*" ], diff --git a/test/cmdlineTests/standard_stop_after_parsing_bytecode_requested/output.json b/test/cmdlineTests/standard_stop_after_parsing_bytecode_requested/output.json index 371953096..1699ed880 100644 --- a/test/cmdlineTests/standard_stop_after_parsing_bytecode_requested/output.json +++ b/test/cmdlineTests/standard_stop_after_parsing_bytecode_requested/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Requested output selection conflicts with \"settings.stopAfter\".", diff --git a/test/cmdlineTests/standard_stop_after_parsing_non_binary_output_requested/output.json b/test/cmdlineTests/standard_stop_after_parsing_non_binary_output_requested/output.json index 5b64763be..264cd37be 100644 --- a/test/cmdlineTests/standard_stop_after_parsing_non_binary_output_requested/output.json +++ b/test/cmdlineTests/standard_stop_after_parsing_non_binary_output_requested/output.json @@ -1,8 +1,6 @@ { - "sources": - { - "C": - { + "sources": { + "C": { "id": 0 } } diff --git a/test/cmdlineTests/standard_urls_existing_and_missing/output.json b/test/cmdlineTests/standard_urls_existing_and_missing/output.json index 87db5f4db..e9db1135d 100644 --- a/test/cmdlineTests/standard_urls_existing_and_missing/output.json +++ b/test/cmdlineTests/standard_urls_existing_and_missing/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Cannot import url (\"standard_urls_existing_and_missing/non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".", @@ -9,10 +8,8 @@ "type": "Warning" } ], - "sources": - { - "url_not_found.sol": - { + "sources": { + "url_not_found.sol": { "id": 0 } } diff --git a/test/cmdlineTests/standard_urls_missing/output.json b/test/cmdlineTests/standard_urls_missing/output.json index 267618ee9..7e2bb3dd5 100644 --- a/test/cmdlineTests/standard_urls_missing/output.json +++ b/test/cmdlineTests/standard_urls_missing/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Cannot import url (\"standard_urls_missing/non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".", diff --git a/test/cmdlineTests/standard_viair_requested/output.json b/test/cmdlineTests/standard_viair_requested/output.json index 3e459c56f..0105ea972 100644 --- a/test/cmdlineTests/standard_viair_requested/output.json +++ b/test/cmdlineTests/standard_viair_requested/output.json @@ -1,19 +1,13 @@ { - "contracts": - { - "A": - { - "C": - { - "evm": - { - "bytecode": - { + "contracts": { + "A": { + "C": { + "evm": { + "bytecode": { "generatedSources": [], "object": "" }, - "deployedBytecode": - { + "deployedBytecode": { "object": "" } }, @@ -81,17 +75,13 @@ object \"C_3\" { " }, - "D": - { - "evm": - { - "bytecode": - { + "D": { + "evm": { + "bytecode": { "generatedSources": [], "object": "" }, - "deployedBytecode": - { + "deployedBytecode": { "object": "" } }, @@ -299,8 +289,7 @@ object \"D_16\" { } } }, - "errors": - [ + "errors": [ { "component": "general", "errorCode": "2072", @@ -313,8 +302,7 @@ object \"D_16\" { ", "message": "Unused local variable.", "severity": "warning", - "sourceLocation": - { + "sourceLocation": { "end": 131, "file": "A", "start": 128 @@ -322,10 +310,8 @@ object \"D_16\" { "type": "Warning" } ], - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/standard_wrong_key_auxiliary_input/output.json b/test/cmdlineTests/standard_wrong_key_auxiliary_input/output.json index 1e846d19c..e1ac73e8f 100644 --- a/test/cmdlineTests/standard_wrong_key_auxiliary_input/output.json +++ b/test/cmdlineTests/standard_wrong_key_auxiliary_input/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Unknown key \"key1\"", diff --git a/test/cmdlineTests/standard_wrong_key_metadata/output.json b/test/cmdlineTests/standard_wrong_key_metadata/output.json index 1e846d19c..e1ac73e8f 100644 --- a/test/cmdlineTests/standard_wrong_key_metadata/output.json +++ b/test/cmdlineTests/standard_wrong_key_metadata/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Unknown key \"key1\"", diff --git a/test/cmdlineTests/standard_wrong_key_optimizer/output.json b/test/cmdlineTests/standard_wrong_key_optimizer/output.json index 1e846d19c..e1ac73e8f 100644 --- a/test/cmdlineTests/standard_wrong_key_optimizer/output.json +++ b/test/cmdlineTests/standard_wrong_key_optimizer/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Unknown key \"key1\"", diff --git a/test/cmdlineTests/standard_wrong_key_root/output.json b/test/cmdlineTests/standard_wrong_key_root/output.json index 1e846d19c..e1ac73e8f 100644 --- a/test/cmdlineTests/standard_wrong_key_root/output.json +++ b/test/cmdlineTests/standard_wrong_key_root/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Unknown key \"key1\"", diff --git a/test/cmdlineTests/standard_wrong_key_settings/output.json b/test/cmdlineTests/standard_wrong_key_settings/output.json index 1e846d19c..e1ac73e8f 100644 --- a/test/cmdlineTests/standard_wrong_key_settings/output.json +++ b/test/cmdlineTests/standard_wrong_key_settings/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Unknown key \"key1\"", diff --git a/test/cmdlineTests/standard_wrong_key_source/output.json b/test/cmdlineTests/standard_wrong_key_source/output.json index 1e846d19c..e1ac73e8f 100644 --- a/test/cmdlineTests/standard_wrong_key_source/output.json +++ b/test/cmdlineTests/standard_wrong_key_source/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Unknown key \"key1\"", diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input/output.json b/test/cmdlineTests/standard_wrong_type_auxiliary_input/output.json index 877ecad4d..efe3d722e 100644 --- a/test/cmdlineTests/standard_wrong_type_auxiliary_input/output.json +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"auxiliaryInput\" must be an object", diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses/output.json b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses/output.json index c28238145..ec3c7a804 100644 --- a/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses/output.json +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"auxiliaryInput.smtlib2responses\" must be an object.", diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member/output.json b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member/output.json index 6676998c6..0cbceafda 100644 --- a/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member/output.json +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"smtlib2Responses.abc\" must be a string.", diff --git a/test/cmdlineTests/standard_wrong_type_metadata/output.json b/test/cmdlineTests/standard_wrong_type_metadata/output.json index df9f8cae3..38b2ffca6 100644 --- a/test/cmdlineTests/standard_wrong_type_metadata/output.json +++ b/test/cmdlineTests/standard_wrong_type_metadata/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.metadata\" must be an object", diff --git a/test/cmdlineTests/standard_wrong_type_optimizer/output.json b/test/cmdlineTests/standard_wrong_type_optimizer/output.json index d7ce30326..c6bc5cc3f 100644 --- a/test/cmdlineTests/standard_wrong_type_optimizer/output.json +++ b/test/cmdlineTests/standard_wrong_type_optimizer/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.optimizer\" must be an object", diff --git a/test/cmdlineTests/standard_wrong_type_output_selection/output.json b/test/cmdlineTests/standard_wrong_type_output_selection/output.json index d7d8f563f..346590a7c 100644 --- a/test/cmdlineTests/standard_wrong_type_output_selection/output.json +++ b/test/cmdlineTests/standard_wrong_type_output_selection/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.outputSelection\" must be an object", diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_contract/output.json b/test/cmdlineTests/standard_wrong_type_output_selection_contract/output.json index 5a35419ef..dbb4af997 100644 --- a/test/cmdlineTests/standard_wrong_type_output_selection_contract/output.json +++ b/test/cmdlineTests/standard_wrong_type_output_selection_contract/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.outputSelection.fileA.A\" must be a string array", diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_file/output.json b/test/cmdlineTests/standard_wrong_type_output_selection_file/output.json index 888efc75b..4a7385834 100644 --- a/test/cmdlineTests/standard_wrong_type_output_selection_file/output.json +++ b/test/cmdlineTests/standard_wrong_type_output_selection_file/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.outputSelection.fileA\" must be an object", diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_output/output.json b/test/cmdlineTests/standard_wrong_type_output_selection_output/output.json index 5a35419ef..dbb4af997 100644 --- a/test/cmdlineTests/standard_wrong_type_output_selection_output/output.json +++ b/test/cmdlineTests/standard_wrong_type_output_selection_output/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.outputSelection.fileA.A\" must be a string array", diff --git a/test/cmdlineTests/standard_wrong_type_remappings/output.json b/test/cmdlineTests/standard_wrong_type_remappings/output.json index b94919077..a4c327048 100644 --- a/test/cmdlineTests/standard_wrong_type_remappings/output.json +++ b/test/cmdlineTests/standard_wrong_type_remappings/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.remappings\" must be an array of strings.", diff --git a/test/cmdlineTests/standard_wrong_type_remappings_entry/output.json b/test/cmdlineTests/standard_wrong_type_remappings_entry/output.json index d083c85be..75162fd05 100644 --- a/test/cmdlineTests/standard_wrong_type_remappings_entry/output.json +++ b/test/cmdlineTests/standard_wrong_type_remappings_entry/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.remappings\" must be an array of strings", diff --git a/test/cmdlineTests/standard_wrong_type_root/output.json b/test/cmdlineTests/standard_wrong_type_root/output.json index da8fefdf5..59f7778b1 100644 --- a/test/cmdlineTests/standard_wrong_type_root/output.json +++ b/test/cmdlineTests/standard_wrong_type_root/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Input is not a JSON object.", diff --git a/test/cmdlineTests/standard_wrong_type_settings/output.json b/test/cmdlineTests/standard_wrong_type_settings/output.json index a25071c85..d75283112 100644 --- a/test/cmdlineTests/standard_wrong_type_settings/output.json +++ b/test/cmdlineTests/standard_wrong_type_settings/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings\" must be an object", diff --git a/test/cmdlineTests/standard_wrong_type_source/output.json b/test/cmdlineTests/standard_wrong_type_source/output.json index 98496c643..0da063fb1 100644 --- a/test/cmdlineTests/standard_wrong_type_source/output.json +++ b/test/cmdlineTests/standard_wrong_type_source/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"sources.A\" must be an object", diff --git a/test/cmdlineTests/standard_wrong_type_sources/output.json b/test/cmdlineTests/standard_wrong_type_sources/output.json index 3f5f51fce..abf248c00 100644 --- a/test/cmdlineTests/standard_wrong_type_sources/output.json +++ b/test/cmdlineTests/standard_wrong_type_sources/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"sources\" is not a JSON object.", diff --git a/test/cmdlineTests/standard_wrong_type_useLiteralContent/output.json b/test/cmdlineTests/standard_wrong_type_useLiteralContent/output.json index 7135c9856..def6ad69e 100644 --- a/test/cmdlineTests/standard_wrong_type_useLiteralContent/output.json +++ b/test/cmdlineTests/standard_wrong_type_useLiteralContent/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "\"settings.metadata.useLiteralContent\" must be Boolean", diff --git a/test/cmdlineTests/standard_yul/output.json b/test/cmdlineTests/standard_yul/output.json index c1b22726f..8d2ab0074 100644 --- a/test/cmdlineTests/standard_yul/output.json +++ b/test/cmdlineTests/standard_yul/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "A": - { - "object": - { - "evm": - { + "contracts": { + "A": { + "object": { + "evm": { "assembly": " /* \"A\":38:39 */ 0x00 /* \"A\":11:19 */ @@ -20,8 +16,7 @@ /* \"A\":0:42 */ stop ", - "bytecode": - { + "bytecode": { "functionDebugData": {}, "generatedSources": [], "linkReferences": {}, @@ -49,29 +44,21 @@ } } }, - "sources": - { - "A": - { - "ast": - { - "code": - { - "block": - { + "sources": { + "A": { + "ast": { + "code": { + "block": { "nativeSrc": "0:42:0", "nodeType": "YulBlock", "src": "0:42:0", - "statements": - [ + "statements": [ { "nativeSrc": "2:17:0", "nodeType": "YulVariableDeclaration", "src": "2:17:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "17:1:0", @@ -81,8 +68,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "mload", "nativeSrc": "11:5:0", "nodeType": "YulIdentifier", @@ -92,8 +78,7 @@ "nodeType": "YulFunctionCall", "src": "11:8:0" }, - "variables": - [ + "variables": [ { "name": "x", "nativeSrc": "6:1:0", @@ -104,13 +89,10 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "x", "nativeSrc": "31:1:0", @@ -126,8 +108,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "27:3:0", "nodeType": "YulIdentifier", @@ -146,8 +127,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "sstore", "nativeSrc": "20:6:0", "nodeType": "YulIdentifier", diff --git a/test/cmdlineTests/standard_yul_debug_info_print_all/output.json b/test/cmdlineTests/standard_yul_debug_info_print_all/output.json index 9d675a069..c994baf4f 100644 --- a/test/cmdlineTests/standard_yul_debug_info_print_all/output.json +++ b/test/cmdlineTests/standard_yul_debug_info_print_all/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "C": - { - "C_6_deployed": - { - "evm": - { + "contracts": { + "C": { + "C_6_deployed": { + "evm": { "assembly": " /* \"input.sol\":60:101 */ mstore(0x40, 0x80) tag_2 diff --git a/test/cmdlineTests/standard_yul_debug_info_print_location_only/output.json b/test/cmdlineTests/standard_yul_debug_info_print_location_only/output.json index 8cbbd326c..54b37f8ef 100644 --- a/test/cmdlineTests/standard_yul_debug_info_print_location_only/output.json +++ b/test/cmdlineTests/standard_yul_debug_info_print_location_only/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "C": - { - "C_6_deployed": - { - "evm": - { + "contracts": { + "C": { + "C_6_deployed": { + "evm": { "assembly": " /* \"input.sol\":60:101 */ mstore(0x40, 0x80) tag_2 diff --git a/test/cmdlineTests/standard_yul_debug_info_print_none/output.json b/test/cmdlineTests/standard_yul_debug_info_print_none/output.json index d1e4cff4c..5b8cc709f 100644 --- a/test/cmdlineTests/standard_yul_debug_info_print_none/output.json +++ b/test/cmdlineTests/standard_yul_debug_info_print_none/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "C": - { - "C_6_deployed": - { - "evm": - { + "contracts": { + "C": { + "C_6_deployed": { + "evm": { "assembly": " mstore(0x40, 0x80) tag_2 tag_1 diff --git a/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/output.json b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/output.json index fb7f199a7..7f48fd4e9 100644 --- a/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/output.json +++ b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "To use 'snippet' with settings.debug.debugInfo you must select also 'location'.", diff --git a/test/cmdlineTests/standard_yul_evm_version_byzantium/output.json b/test/cmdlineTests/standard_yul_evm_version_byzantium/output.json index 9fff56279..bbe178353 100644 --- a/test/cmdlineTests/standard_yul_evm_version_byzantium/output.json +++ b/test/cmdlineTests/standard_yul_evm_version_byzantium/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Support for EVM versions older than constantinople is deprecated and will be removed in the future.", diff --git a/test/cmdlineTests/standard_yul_immutable_references/output.json b/test/cmdlineTests/standard_yul_immutable_references/output.json index 1f75e8ad2..7bfbb076a 100644 --- a/test/cmdlineTests/standard_yul_immutable_references/output.json +++ b/test/cmdlineTests/standard_yul_immutable_references/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "A": - { - "YulTest": - { - "evm": - { - "bytecode": - { + "contracts": { + "A": { + "YulTest": { + "evm": { + "bytecode": { "functionDebugData": {}, "generatedSources": [], "linkReferences": {}, @@ -16,14 +11,11 @@ "opcodes":"", "sourceMap":"" }, - "deployedBytecode": - { + "deployedBytecode": { "functionDebugData": {}, "generatedSources": [], - "immutableReferences": - { - "test": - [ + "immutableReferences": { + "test": [ { "length": 32, "start": 1 diff --git a/test/cmdlineTests/standard_yul_multiple_files/output.json b/test/cmdlineTests/standard_yul_multiple_files/output.json index cdef28c26..88f390204 100644 --- a/test/cmdlineTests/standard_yul_multiple_files/output.json +++ b/test/cmdlineTests/standard_yul_multiple_files/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Yul mode only supports exactly one input file.", diff --git a/test/cmdlineTests/standard_yul_multiple_files_selected/output.json b/test/cmdlineTests/standard_yul_multiple_files_selected/output.json index cdef28c26..88f390204 100644 --- a/test/cmdlineTests/standard_yul_multiple_files_selected/output.json +++ b/test/cmdlineTests/standard_yul_multiple_files_selected/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Yul mode only supports exactly one input file.", diff --git a/test/cmdlineTests/standard_yul_object/output.json b/test/cmdlineTests/standard_yul_object/output.json index 1404cd3aa..87d0cab8f 100644 --- a/test/cmdlineTests/standard_yul_object/output.json +++ b/test/cmdlineTests/standard_yul_object/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "A": - { - "NamedObject": - { - "evm": - { + "contracts": { + "A": { + "NamedObject": { + "evm": { "assembly": " /* \"A\":80:81 */ 0x00 /* \"A\":39:61 */ @@ -21,8 +17,7 @@ stop data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 ", - "bytecode": - { + "bytecode": { "functionDebugData": {}, "generatedSources": [], "linkReferences": {}, @@ -52,29 +47,21 @@ data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 } } }, - "sources": - { - "A": - { - "ast": - { - "code": - { - "block": - { + "sources": { + "A": { + "ast": { + "code": { + "block": { "nativeSrc": "28:56:0", "nodeType": "YulBlock", "src": "28:56:0", - "statements": - [ + "statements": [ { "nativeSrc": "30:31:0", "nodeType": "YulVariableDeclaration", "src": "30:31:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "hexValue": "446174614e616d65", "kind": "string", @@ -85,8 +72,7 @@ data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 "value": "DataName" } ], - "functionName": - { + "functionName": { "name": "dataoffset", "nativeSrc": "39:10:0", "nodeType": "YulIdentifier", @@ -96,8 +82,7 @@ data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 "nodeType": "YulFunctionCall", "src": "39:22:0" }, - "variables": - [ + "variables": [ { "name": "x", "nativeSrc": "34:1:0", @@ -108,13 +93,10 @@ data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "x", "nativeSrc": "73:1:0", @@ -130,8 +112,7 @@ data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 "value": "0" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "69:3:0", "nodeType": "YulIdentifier", @@ -150,8 +131,7 @@ data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 "value": "0" } ], - "functionName": - { + "functionName": { "name": "sstore", "nativeSrc": "62:6:0", "nodeType": "YulIdentifier", @@ -171,8 +151,7 @@ data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 }, "name": "NamedObject", "nodeType": "YulObject", - "subObjects": - [ + "subObjects": [ { "nodeType": "YulData", "value": "616263" diff --git a/test/cmdlineTests/standard_yul_object_invalid_sub/output.json b/test/cmdlineTests/standard_yul_object_invalid_sub/output.json index 98522145a..fea1aa169 100644 --- a/test/cmdlineTests/standard_yul_object_invalid_sub/output.json +++ b/test/cmdlineTests/standard_yul_object_invalid_sub/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "TypeError: Unknown data object \"NamedObject.\". @@ -12,8 +11,7 @@ ", "message": "Unknown data object \"NamedObject.\".", "severity": "error", - "sourceLocation": - { + "sourceLocation": { "end": 64, "file": "A", "start": 50 diff --git a/test/cmdlineTests/standard_yul_object_name/output.json b/test/cmdlineTests/standard_yul_object_name/output.json index 6803c322d..c6e98130d 100644 --- a/test/cmdlineTests/standard_yul_object_name/output.json +++ b/test/cmdlineTests/standard_yul_object_name/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "A": - { - "NamedObject": - { - "evm": - { + "contracts": { + "A": { + "NamedObject": { + "evm": { "assembly": " /* \"A\":80:81 */ 0x00 /* \"A\":39:61 */ @@ -29,8 +25,7 @@ sub_0: assembly { revert } ", - "bytecode": - { + "bytecode": { "functionDebugData": {}, "generatedSources": [], "linkReferences": {}, @@ -38,8 +33,7 @@ sub_0: assembly { "opcodes":"", "sourceMap":"" }, - "deployedBytecode": - { + "deployedBytecode": { "functionDebugData": {}, "generatedSources": [], "immutableReferences": {}, @@ -76,29 +70,21 @@ sub_0: assembly { } } }, - "sources": - { - "A": - { - "ast": - { - "code": - { - "block": - { + "sources": { + "A": { + "ast": { + "code": { + "block": { "nativeSrc": "28:56:0", "nodeType": "YulBlock", "src": "28:56:0", - "statements": - [ + "statements": [ { "nativeSrc": "30:31:0", "nodeType": "YulVariableDeclaration", "src": "30:31:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "hexValue": "446174614e616d65", "kind": "string", @@ -109,8 +95,7 @@ sub_0: assembly { "value": "DataName" } ], - "functionName": - { + "functionName": { "name": "dataoffset", "nativeSrc": "39:10:0", "nodeType": "YulIdentifier", @@ -120,8 +105,7 @@ sub_0: assembly { "nodeType": "YulFunctionCall", "src": "39:22:0" }, - "variables": - [ + "variables": [ { "name": "x", "nativeSrc": "34:1:0", @@ -132,13 +116,10 @@ sub_0: assembly { ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "x", "nativeSrc": "73:1:0", @@ -154,8 +135,7 @@ sub_0: assembly { "value": "0" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "69:3:0", "nodeType": "YulIdentifier", @@ -174,8 +154,7 @@ sub_0: assembly { "value": "0" } ], - "functionName": - { + "functionName": { "name": "sstore", "nativeSrc": "62:6:0", "nodeType": "YulIdentifier", @@ -195,27 +174,21 @@ sub_0: assembly { }, "name": "NamedObject", "nodeType": "YulObject", - "subObjects": - [ + "subObjects": [ { "nodeType": "YulData", "value": "616263" }, { - "code": - { - "block": - { + "code": { + "block": { "nativeSrc": "135:16:0", "nodeType": "YulBlock", "src": "135:16:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "144:1:0", @@ -233,8 +206,7 @@ sub_0: assembly { "value": "0" } ], - "functionName": - { + "functionName": { "name": "revert", "nativeSrc": "137:6:0", "nodeType": "YulIdentifier", diff --git a/test/cmdlineTests/standard_yul_optimiserSteps/output.json b/test/cmdlineTests/standard_yul_optimiserSteps/output.json index 85a34261f..1c72379c6 100644 --- a/test/cmdlineTests/standard_yul_optimiserSteps/output.json +++ b/test/cmdlineTests/standard_yul_optimiserSteps/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "A": - { - "object": - { - "evm": - { + "contracts": { + "A": { + "object": { + "evm": { "assembly": " /* \"A\":38:39 */ 0x00 /* \"A\":11:19 */ @@ -17,8 +13,7 @@ /* \"A\":0:42 */ stop ", - "bytecode": - { + "bytecode": { "functionDebugData": {}, "generatedSources": [], "linkReferences": {}, @@ -46,29 +41,21 @@ } } }, - "sources": - { - "A": - { - "ast": - { - "code": - { - "block": - { + "sources": { + "A": { + "ast": { + "code": { + "block": { "nativeSrc": "0:42:0", "nodeType": "YulBlock", "src": "0:42:0", - "statements": - [ + "statements": [ { "nativeSrc": "2:17:0", "nodeType": "YulVariableDeclaration", "src": "2:17:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "17:1:0", @@ -78,8 +65,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "mload", "nativeSrc": "11:5:0", "nodeType": "YulIdentifier", @@ -89,8 +75,7 @@ "nodeType": "YulFunctionCall", "src": "11:8:0" }, - "variables": - [ + "variables": [ { "name": "x", "nativeSrc": "6:1:0", @@ -101,13 +86,10 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "x", "nativeSrc": "31:1:0", @@ -123,8 +105,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "27:3:0", "nodeType": "YulIdentifier", @@ -143,8 +124,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "sstore", "nativeSrc": "20:6:0", "nodeType": "YulIdentifier", diff --git a/test/cmdlineTests/standard_yul_optimized/output.json b/test/cmdlineTests/standard_yul_optimized/output.json index d580ef6ae..c443b2863 100644 --- a/test/cmdlineTests/standard_yul_optimized/output.json +++ b/test/cmdlineTests/standard_yul_optimized/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "A": - { - "object": - { - "evm": - { + "contracts": { + "A": { + "object": { + "evm": { "assembly": " /* \"A\":17:18 */ 0x00 /* \"A\":11:19 */ @@ -17,8 +13,7 @@ /* \"A\":0:42 */ stop ", - "bytecode": - { + "bytecode": { "functionDebugData": {}, "generatedSources": [], "linkReferences": {}, @@ -41,29 +36,21 @@ } } }, - "sources": - { - "A": - { - "ast": - { - "code": - { - "block": - { + "sources": { + "A": { + "ast": { + "code": { + "block": { "nativeSrc": "0:42:0", "nodeType": "YulBlock", "src": "0:42:0", - "statements": - [ + "statements": [ { "nativeSrc": "2:17:0", "nodeType": "YulVariableDeclaration", "src": "2:17:0", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "kind": "number", "nativeSrc": "17:1:0", @@ -73,8 +60,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "mload", "nativeSrc": "11:5:0", "nodeType": "YulIdentifier", @@ -84,8 +70,7 @@ "nodeType": "YulFunctionCall", "src": "11:8:0" }, - "variables": - [ + "variables": [ { "name": "x", "nativeSrc": "6:1:0", @@ -96,13 +81,10 @@ ] }, { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "name": "x", "nativeSrc": "31:1:0", @@ -118,8 +100,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "add", "nativeSrc": "27:3:0", "nodeType": "YulIdentifier", @@ -138,8 +119,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "sstore", "nativeSrc": "20:6:0", "nodeType": "YulIdentifier", diff --git a/test/cmdlineTests/standard_yul_single_file_via_urls/output.json b/test/cmdlineTests/standard_yul_single_file_via_urls/output.json index a97057c88..e76d039f5 100644 --- a/test/cmdlineTests/standard_yul_single_file_via_urls/output.json +++ b/test/cmdlineTests/standard_yul_single_file_via_urls/output.json @@ -1,6 +1,5 @@ { - "errors": - [ + "errors": [ { "component": "general", "formattedMessage": "Cannot import url (\"in.yul\"): File not found. Searched the following locations: \"\".", diff --git a/test/cmdlineTests/standard_yul_stack_opt/output.json b/test/cmdlineTests/standard_yul_stack_opt/output.json index e10ef0c17..9d89edfb4 100644 --- a/test/cmdlineTests/standard_yul_stack_opt/output.json +++ b/test/cmdlineTests/standard_yul_stack_opt/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "A": - { - "object": - { - "evm": - { + "contracts": { + "A": { + "object": { + "evm": { "assembly": " /* \"A\":16:17 */ 0x01 /* \"A\":27:28 */ diff --git a/test/cmdlineTests/standard_yul_stack_opt_disabled/output.json b/test/cmdlineTests/standard_yul_stack_opt_disabled/output.json index 8d58cf320..f0752b812 100644 --- a/test/cmdlineTests/standard_yul_stack_opt_disabled/output.json +++ b/test/cmdlineTests/standard_yul_stack_opt_disabled/output.json @@ -1,12 +1,8 @@ { - "contracts": - { - "A": - { - "object": - { - "evm": - { + "contracts": { + "A": { + "object": { + "evm": { "assembly": " /* \"A\":16:17 */ 0x01 /* \"A\":27:28 */ diff --git a/test/cmdlineTests/stop_after_parsing_ast/output b/test/cmdlineTests/stop_after_parsing_ast/output index 163941860..6cca9557d 100644 --- a/test/cmdlineTests/stop_after_parsing_ast/output +++ b/test/cmdlineTests/stop_after_parsing_ast/output @@ -7,12 +7,10 @@ JSON AST (compact format): "id": 4, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "solidity", "*" ], diff --git a/test/cmdlineTests/storage_layout_bytes/output.json b/test/cmdlineTests/storage_layout_bytes/output.json index c2ca7813c..67091e974 100644 --- a/test/cmdlineTests/storage_layout_bytes/output.json +++ b/test/cmdlineTests/storage_layout_bytes/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "fileA": - { - "A": - { - "storageLayout": - { - "storage": - [ + "contracts": { + "fileA": { + "A": { + "storageLayout": { + "storage": [ { "astId": 4, "contract": "fileA:A", @@ -26,10 +21,8 @@ "type": "t_bytes_storage" } ], - "types": - { - "t_bytes_storage": - { + "types": { + "t_bytes_storage": { "encoding": "bytes", "label": "bytes", "numberOfBytes": "32" @@ -39,10 +32,8 @@ } } }, - "sources": - { - "fileA": - { + "sources": { + "fileA": { "id": 0 } } diff --git a/test/cmdlineTests/storage_layout_dyn_array/output.json b/test/cmdlineTests/storage_layout_dyn_array/output.json index fa7ed04ba..f4468c411 100644 --- a/test/cmdlineTests/storage_layout_dyn_array/output.json +++ b/test/cmdlineTests/storage_layout_dyn_array/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "fileA": - { - "A": - { - "storageLayout": - { - "storage": - [ + "contracts": { + "fileA": { + "A": { + "storageLayout": { + "storage": [ { "astId": 4, "contract": "fileA:A", @@ -26,30 +21,25 @@ "type": "t_array(t_bool)dyn_storage" } ], - "types": - { - "t_array(t_bool)dyn_storage": - { + "types": { + "t_array(t_bool)dyn_storage": { "base": "t_bool", "encoding": "dynamic_array", "label": "bool[]", "numberOfBytes": "32" }, - "t_array(t_uint256)dyn_storage": - { + "t_array(t_uint256)dyn_storage": { "base": "t_uint256", "encoding": "dynamic_array", "label": "uint256[]", "numberOfBytes": "32" }, - "t_bool": - { + "t_bool": { "encoding": "inplace", "label": "bool", "numberOfBytes": "1" }, - "t_uint256": - { + "t_uint256": { "encoding": "inplace", "label": "uint256", "numberOfBytes": "32" @@ -59,10 +49,8 @@ } } }, - "sources": - { - "fileA": - { + "sources": { + "fileA": { "id": 0 } } diff --git a/test/cmdlineTests/storage_layout_many/output.json b/test/cmdlineTests/storage_layout_many/output.json index 68cb00682..fa1b6f13e 100644 --- a/test/cmdlineTests/storage_layout_many/output.json +++ b/test/cmdlineTests/storage_layout_many/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "fileA": - { - "A": - { - "storageLayout": - { - "storage": - [ + "contracts": { + "fileA": { + "A": { + "storageLayout": { + "storage": [ { "astId": 15, "contract": "fileA:A", @@ -74,68 +69,57 @@ "type": "t_bytes_storage" } ], - "types": - { - "t_address": - { + "types": { + "t_address": { "encoding": "inplace", "label": "address", "numberOfBytes": "20" }, - "t_array(t_uint256)2_storage": - { + "t_array(t_uint256)2_storage": { "base": "t_uint256", "encoding": "inplace", "label": "uint256[2]", "numberOfBytes": "64" }, - "t_array(t_uint256)dyn_storage": - { + "t_array(t_uint256)dyn_storage": { "base": "t_uint256", "encoding": "dynamic_array", "label": "uint256[]", "numberOfBytes": "32" }, - "t_bool": - { + "t_bool": { "encoding": "inplace", "label": "bool", "numberOfBytes": "1" }, - "t_bytes_storage": - { + "t_bytes_storage": { "encoding": "bytes", "label": "bytes", "numberOfBytes": "32" }, - "t_mapping(t_address,t_bool)": - { + "t_mapping(t_address,t_bool)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => bool)", "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint256,t_mapping(t_address,t_bool))": - { + "t_mapping(t_uint256,t_mapping(t_address,t_bool))": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => mapping(address => bool))", "numberOfBytes": "32", "value": "t_mapping(t_address,t_bool)" }, - "t_string_storage": - { + "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(S)13_storage": - { + "t_struct(S)13_storage": { "encoding": "inplace", "label": "struct A.S", - "members": - [ + "members": [ { "astId": 3, "contract": "fileA:A", @@ -171,14 +155,12 @@ ], "numberOfBytes": "128" }, - "t_uint128": - { + "t_uint128": { "encoding": "inplace", "label": "uint128", "numberOfBytes": "16" }, - "t_uint256": - { + "t_uint256": { "encoding": "inplace", "label": "uint256", "numberOfBytes": "32" @@ -188,10 +170,8 @@ } } }, - "sources": - { - "fileA": - { + "sources": { + "fileA": { "id": 0 } } diff --git a/test/cmdlineTests/storage_layout_mapping/output.json b/test/cmdlineTests/storage_layout_mapping/output.json index 8d13fb34b..9fb9f847c 100644 --- a/test/cmdlineTests/storage_layout_mapping/output.json +++ b/test/cmdlineTests/storage_layout_mapping/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "fileA": - { - "A": - { - "storageLayout": - { - "storage": - [ + "contracts": { + "fileA": { + "A": { + "storageLayout": { + "storage": [ { "astId": 3, "contract": "fileA:A", @@ -34,38 +29,32 @@ "type": "t_mapping(t_uint256,t_mapping(t_address,t_bool))" } ], - "types": - { - "t_address": - { + "types": { + "t_address": { "encoding": "inplace", "label": "address", "numberOfBytes": "20" }, - "t_bool": - { + "t_bool": { "encoding": "inplace", "label": "bool", "numberOfBytes": "1" }, - "t_mapping(t_address,t_bool)": - { + "t_mapping(t_address,t_bool)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => bool)", "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint256,t_mapping(t_address,t_bool))": - { + "t_mapping(t_uint256,t_mapping(t_address,t_bool))": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => mapping(address => bool))", "numberOfBytes": "32", "value": "t_mapping(t_address,t_bool)" }, - "t_uint256": - { + "t_uint256": { "encoding": "inplace", "label": "uint256", "numberOfBytes": "32" @@ -75,10 +64,8 @@ } } }, - "sources": - { - "fileA": - { + "sources": { + "fileA": { "id": 0 } } diff --git a/test/cmdlineTests/storage_layout_smoke/output.json b/test/cmdlineTests/storage_layout_smoke/output.json index 9fe46bb67..e2eaee500 100644 --- a/test/cmdlineTests/storage_layout_smoke/output.json +++ b/test/cmdlineTests/storage_layout_smoke/output.json @@ -1,22 +1,16 @@ { - "contracts": - { - "fileA": - { - "A": - { - "storageLayout": - { + "contracts": { + "fileA": { + "A": { + "storageLayout": { "storage": [], "types": null } } } }, - "sources": - { - "fileA": - { + "sources": { + "fileA": { "id": 0 } } diff --git a/test/cmdlineTests/storage_layout_smoke_two_contracts/output.json b/test/cmdlineTests/storage_layout_smoke_two_contracts/output.json index fc4e422a5..2b9448459 100644 --- a/test/cmdlineTests/storage_layout_smoke_two_contracts/output.json +++ b/test/cmdlineTests/storage_layout_smoke_two_contracts/output.json @@ -1,26 +1,19 @@ { - "contracts": - { - "fileA": - { - "A": - { - "storageLayout": - { + "contracts": { + "fileA": { + "A": { + "storageLayout": { "storage": [], "types": null } } } }, - "sources": - { - "fileA": - { + "sources": { + "fileA": { "id": 0 }, - "fileB": - { + "fileB": { "id": 1 } } diff --git a/test/cmdlineTests/storage_layout_string/output.json b/test/cmdlineTests/storage_layout_string/output.json index 20c6f64cc..2fcb974db 100644 --- a/test/cmdlineTests/storage_layout_string/output.json +++ b/test/cmdlineTests/storage_layout_string/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "fileA": - { - "A": - { - "storageLayout": - { - "storage": - [ + "contracts": { + "fileA": { + "A": { + "storageLayout": { + "storage": [ { "astId": 4, "contract": "fileA:A", @@ -26,10 +21,8 @@ "type": "t_string_storage" } ], - "types": - { - "t_string_storage": - { + "types": { + "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" @@ -39,10 +32,8 @@ } } }, - "sources": - { - "fileA": - { + "sources": { + "fileA": { "id": 0 } } diff --git a/test/cmdlineTests/storage_layout_struct/output.json b/test/cmdlineTests/storage_layout_struct/output.json index f682d9634..1fadb220e 100644 --- a/test/cmdlineTests/storage_layout_struct/output.json +++ b/test/cmdlineTests/storage_layout_struct/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "fileA": - { - "A": - { - "storageLayout": - { - "storage": - [ + "contracts": { + "fileA": { + "A": { + "storageLayout": { + "storage": [ { "astId": 15, "contract": "fileA:A", @@ -42,34 +37,28 @@ "type": "t_address" } ], - "types": - { - "t_address": - { + "types": { + "t_address": { "encoding": "inplace", "label": "address", "numberOfBytes": "20" }, - "t_array(t_uint256)2_storage": - { + "t_array(t_uint256)2_storage": { "base": "t_uint256", "encoding": "inplace", "label": "uint256[2]", "numberOfBytes": "64" }, - "t_array(t_uint256)dyn_storage": - { + "t_array(t_uint256)dyn_storage": { "base": "t_uint256", "encoding": "dynamic_array", "label": "uint256[]", "numberOfBytes": "32" }, - "t_struct(S)13_storage": - { + "t_struct(S)13_storage": { "encoding": "inplace", "label": "struct A.S", - "members": - [ + "members": [ { "astId": 3, "contract": "fileA:A", @@ -105,8 +94,7 @@ ], "numberOfBytes": "160" }, - "t_uint256": - { + "t_uint256": { "encoding": "inplace", "label": "uint256", "numberOfBytes": "32" @@ -116,10 +104,8 @@ } } }, - "sources": - { - "fileA": - { + "sources": { + "fileA": { "id": 0 } } diff --git a/test/cmdlineTests/storage_layout_struct_packed/output.json b/test/cmdlineTests/storage_layout_struct_packed/output.json index 7731bd223..f91a9a0cd 100644 --- a/test/cmdlineTests/storage_layout_struct_packed/output.json +++ b/test/cmdlineTests/storage_layout_struct_packed/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "fileA": - { - "A": - { - "storageLayout": - { - "storage": - [ + "contracts": { + "fileA": { + "A": { + "storageLayout": { + "storage": [ { "astId": 15, "contract": "fileA:A", @@ -42,34 +37,28 @@ "type": "t_address" } ], - "types": - { - "t_address": - { + "types": { + "t_address": { "encoding": "inplace", "label": "address", "numberOfBytes": "20" }, - "t_array(t_uint256)2_storage": - { + "t_array(t_uint256)2_storage": { "base": "t_uint256", "encoding": "inplace", "label": "uint256[2]", "numberOfBytes": "64" }, - "t_array(t_uint256)dyn_storage": - { + "t_array(t_uint256)dyn_storage": { "base": "t_uint256", "encoding": "dynamic_array", "label": "uint256[]", "numberOfBytes": "32" }, - "t_struct(S)13_storage": - { + "t_struct(S)13_storage": { "encoding": "inplace", "label": "struct A.S", - "members": - [ + "members": [ { "astId": 3, "contract": "fileA:A", @@ -105,14 +94,12 @@ ], "numberOfBytes": "128" }, - "t_uint128": - { + "t_uint128": { "encoding": "inplace", "label": "uint128", "numberOfBytes": "16" }, - "t_uint256": - { + "t_uint256": { "encoding": "inplace", "label": "uint256", "numberOfBytes": "32" @@ -122,10 +109,8 @@ } } }, - "sources": - { - "fileA": - { + "sources": { + "fileA": { "id": 0 } } diff --git a/test/cmdlineTests/storage_layout_user_defined/output b/test/cmdlineTests/storage_layout_user_defined/output index f79b8413e..bb7819c66 100644 --- a/test/cmdlineTests/storage_layout_user_defined/output +++ b/test/cmdlineTests/storage_layout_user_defined/output @@ -2,8 +2,7 @@ ======= storage_layout_user_defined/input.sol:C ======= Contract Storage Layout: { - "storage": - [ + "storage": [ { "astId": 7, "contract": "storage_layout_user_defined/input.sol:C", @@ -69,16 +68,13 @@ Contract Storage Layout: "type": "t_userDefinedValueType(MyInt8)4" } ], - "types": - { - "t_userDefinedValueType(MyInt128)2": - { + "types": { + "t_userDefinedValueType(MyInt128)2": { "encoding": "inplace", "label": "MyInt128", "numberOfBytes": "16" }, - "t_userDefinedValueType(MyInt8)4": - { + "t_userDefinedValueType(MyInt8)4": { "encoding": "inplace", "label": "MyInt8", "numberOfBytes": "1" diff --git a/test/cmdlineTests/storage_layout_value_types/output.json b/test/cmdlineTests/storage_layout_value_types/output.json index 10fbd762b..b737adc97 100644 --- a/test/cmdlineTests/storage_layout_value_types/output.json +++ b/test/cmdlineTests/storage_layout_value_types/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "fileA": - { - "A": - { - "storageLayout": - { - "storage": - [ + "contracts": { + "fileA": { + "A": { + "storageLayout": { + "storage": [ { "astId": 3, "contract": "fileA:A", @@ -42,23 +37,19 @@ "type": "t_array(t_uint256)2_storage" } ], - "types": - { - "t_address": - { + "types": { + "t_address": { "encoding": "inplace", "label": "address", "numberOfBytes": "20" }, - "t_array(t_uint256)2_storage": - { + "t_array(t_uint256)2_storage": { "base": "t_uint256", "encoding": "inplace", "label": "uint256[2]", "numberOfBytes": "64" }, - "t_uint256": - { + "t_uint256": { "encoding": "inplace", "label": "uint256", "numberOfBytes": "32" @@ -68,10 +59,8 @@ } } }, - "sources": - { - "fileA": - { + "sources": { + "fileA": { "id": 0 } } diff --git a/test/cmdlineTests/storage_layout_value_types_packed/output.json b/test/cmdlineTests/storage_layout_value_types_packed/output.json index eefb69e66..cea9bc81c 100644 --- a/test/cmdlineTests/storage_layout_value_types_packed/output.json +++ b/test/cmdlineTests/storage_layout_value_types_packed/output.json @@ -1,14 +1,9 @@ { - "contracts": - { - "fileA": - { - "A": - { - "storageLayout": - { - "storage": - [ + "contracts": { + "fileA": { + "A": { + "storageLayout": { + "storage": [ { "astId": 3, "contract": "fileA:A", @@ -50,35 +45,29 @@ "type": "t_array(t_uint256)2_storage" } ], - "types": - { - "t_address": - { + "types": { + "t_address": { "encoding": "inplace", "label": "address", "numberOfBytes": "20" }, - "t_array(t_uint256)2_storage": - { + "t_array(t_uint256)2_storage": { "base": "t_uint256", "encoding": "inplace", "label": "uint256[2]", "numberOfBytes": "64" }, - "t_uint128": - { + "t_uint128": { "encoding": "inplace", "label": "uint128", "numberOfBytes": "16" }, - "t_uint256": - { + "t_uint256": { "encoding": "inplace", "label": "uint256", "numberOfBytes": "32" }, - "t_uint64": - { + "t_uint64": { "encoding": "inplace", "label": "uint64", "numberOfBytes": "8" @@ -88,10 +77,8 @@ } } }, - "sources": - { - "fileA": - { + "sources": { + "fileA": { "id": 0 } } diff --git a/test/cmdlineTests/strict_asm_ast_compact_json/output b/test/cmdlineTests/strict_asm_ast_compact_json/output index 98afddcfa..b4c6dc142 100644 --- a/test/cmdlineTests/strict_asm_ast_compact_json/output +++ b/test/cmdlineTests/strict_asm_ast_compact_json/output @@ -3,26 +3,20 @@ AST: { - "code": - { - "block": - { + "code": { + "block": { "nativeSrc": "60:246:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { "nativeSrc": "60:246:0", "nodeType": "YulBlock", "src": "-1:-1:0", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { "kind": "number", "nativeSrc": "122:2:0", @@ -40,8 +34,7 @@ AST: "value": "128" } ], - "functionName": - { + "functionName": { "name": "mstore", "nativeSrc": "115:6:0", "nodeType": "YulIdentifier", diff --git a/test/cmdlineTests/yul_string_format_ascii/output.json b/test/cmdlineTests/yul_string_format_ascii/output.json index edb76c0cd..6847228b5 100644 --- a/test/cmdlineTests/yul_string_format_ascii/output.json +++ b/test/cmdlineTests/yul_string_format_ascii/output.json @@ -1,10 +1,7 @@ { - "contracts": - { - "A": - { - "C": - { + "contracts": { + "A": { + "C": { "ir": " /// @use-src 0:\"A\" object \"C_11\" { @@ -217,10 +214,8 @@ object \"C_11\" { } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json b/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json index bfe775ca4..2e077e859 100644 --- a/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json @@ -1,10 +1,7 @@ { - "contracts": - { - "A": - { - "C": - { + "contracts": { + "A": { + "C": { "ir": " /// @use-src 0:\"A\" object \"C_11\" { @@ -147,10 +144,8 @@ object \"C_11\" { } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json index f4b14aadc..d2044189a 100644 --- a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json @@ -1,10 +1,7 @@ { - "contracts": - { - "A": - { - "C": - { + "contracts": { + "A": { + "C": { "ir": " /// @use-src 0:\"A\" object \"C_11\" { @@ -160,10 +157,8 @@ object \"C_11\" { } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/yul_string_format_ascii_long/output.json b/test/cmdlineTests/yul_string_format_ascii_long/output.json index 36d6cfd95..20644f3a3 100644 --- a/test/cmdlineTests/yul_string_format_ascii_long/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_long/output.json @@ -1,10 +1,7 @@ { - "contracts": - { - "A": - { - "C": - { + "contracts": { + "A": { + "C": { "ir": " /// @use-src 0:\"A\" object \"C_11\" { @@ -221,10 +218,8 @@ object \"C_11\" { } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/cmdlineTests/yul_string_format_hex/output.json b/test/cmdlineTests/yul_string_format_hex/output.json index 5568fc7a0..a120fa4c9 100644 --- a/test/cmdlineTests/yul_string_format_hex/output.json +++ b/test/cmdlineTests/yul_string_format_hex/output.json @@ -1,10 +1,7 @@ { - "contracts": - { - "A": - { - "C": - { + "contracts": { + "A": { + "C": { "ir": " /// @use-src 0:\"A\" object \"C_11\" { @@ -160,10 +157,8 @@ object \"C_11\" { } } }, - "sources": - { - "A": - { + "sources": { + "A": { "id": 0 } } diff --git a/test/libsolidity/ABIJson/basic_test.sol b/test/libsolidity/ABIJson/basic_test.sol index 37c833bcf..8f60eb728 100644 --- a/test/libsolidity/ABIJson/basic_test.sol +++ b/test/libsolidity/ABIJson/basic_test.sol @@ -5,8 +5,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "a", @@ -14,8 +13,7 @@ contract test { // } // ], // "name": "f", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "d", diff --git a/test/libsolidity/ABIJson/constructor_abi.sol b/test/libsolidity/ABIJson/constructor_abi.sol index ae07c9401..406927f0a 100644 --- a/test/libsolidity/ABIJson/constructor_abi.sol +++ b/test/libsolidity/ABIJson/constructor_abi.sol @@ -5,8 +5,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "param1", diff --git a/test/libsolidity/ABIJson/empty_name_input_parameter_with_named_one.sol b/test/libsolidity/ABIJson/empty_name_input_parameter_with_named_one.sol index d412e755a..c3ba37b0e 100644 --- a/test/libsolidity/ABIJson/empty_name_input_parameter_with_named_one.sol +++ b/test/libsolidity/ABIJson/empty_name_input_parameter_with_named_one.sol @@ -9,8 +9,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "", @@ -23,8 +22,7 @@ contract test { // } // ], // "name": "f", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "ret_k", diff --git a/test/libsolidity/ABIJson/empty_name_return_parameters.sol b/test/libsolidity/ABIJson/empty_name_return_parameters.sol index 1415276fd..56c4de8a2 100644 --- a/test/libsolidity/ABIJson/empty_name_return_parameters.sol +++ b/test/libsolidity/ABIJson/empty_name_return_parameters.sol @@ -7,8 +7,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "k", @@ -16,8 +15,7 @@ contract test { // } // ], // "name": "f", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "", diff --git a/test/libsolidity/ABIJson/errors.sol b/test/libsolidity/ABIJson/errors.sol index 91c76ce6f..86b16dd85 100644 --- a/test/libsolidity/ABIJson/errors.sol +++ b/test/libsolidity/ABIJson/errors.sol @@ -13,8 +13,7 @@ contract X { // :X // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "", @@ -25,8 +24,7 @@ contract X { // "type": "error" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "a", @@ -42,8 +40,7 @@ contract X { // "type": "error" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "a", @@ -59,11 +56,9 @@ contract X { // "type": "error" // }, // { -// "inputs": -// [ +// "inputs": [ // { -// "components": -// [ +// "components": [ // { // "internalType": "uint256", // "name": "x", diff --git a/test/libsolidity/ABIJson/errors_referenced.sol b/test/libsolidity/ABIJson/errors_referenced.sol index ecb5b1003..a624bda10 100644 --- a/test/libsolidity/ABIJson/errors_referenced.sol +++ b/test/libsolidity/ABIJson/errors_referenced.sol @@ -34,8 +34,7 @@ contract X is C { // :D // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "", @@ -61,8 +60,7 @@ contract X is C { // "type": "error" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "", @@ -78,8 +76,7 @@ contract X is C { // "type": "error" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "x", diff --git a/test/libsolidity/ABIJson/event_emited_in_base_contract.sol b/test/libsolidity/ABIJson/event_emited_in_base_contract.sol index f9c3d2019..043b92d55 100644 --- a/test/libsolidity/ABIJson/event_emited_in_base_contract.sol +++ b/test/libsolidity/ABIJson/event_emited_in_base_contract.sol @@ -18,8 +18,7 @@ contract C is B {} // }, // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint8", @@ -37,8 +36,7 @@ contract C is B {} // [ // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint8", @@ -56,8 +54,7 @@ contract C is B {} // [ // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint8", diff --git a/test/libsolidity/ABIJson/event_emitted_from_foreign_contract.sol b/test/libsolidity/ABIJson/event_emitted_from_foreign_contract.sol index 30c115669..1603519c0 100644 --- a/test/libsolidity/ABIJson/event_emitted_from_foreign_contract.sol +++ b/test/libsolidity/ABIJson/event_emitted_from_foreign_contract.sol @@ -17,8 +17,7 @@ contract D { // [ // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": true, // "internalType": "address", @@ -36,8 +35,7 @@ contract D { // [ // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint256", @@ -50,8 +48,7 @@ contract D { // }, // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": true, // "internalType": "address", @@ -64,8 +61,7 @@ contract D { // }, // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": true, // "internalType": "address", @@ -77,8 +73,7 @@ contract D { // "type": "event" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "address", // "name": "sender", @@ -97,8 +92,7 @@ contract D { // [ // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint256", diff --git a/test/libsolidity/ABIJson/event_file_level.sol b/test/libsolidity/ABIJson/event_file_level.sol index 5b5c39a82..65e260d66 100644 --- a/test/libsolidity/ABIJson/event_file_level.sol +++ b/test/libsolidity/ABIJson/event_file_level.sol @@ -32,8 +32,7 @@ contract D is C { // }, // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint256", @@ -64,8 +63,7 @@ contract D is C { // }, // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint256", @@ -78,8 +76,7 @@ contract D is C { // }, // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "string", diff --git a/test/libsolidity/ABIJson/event_structs.sol b/test/libsolidity/ABIJson/event_structs.sol index 83431907a..6c1ec3b17 100644 --- a/test/libsolidity/ABIJson/event_structs.sol +++ b/test/libsolidity/ABIJson/event_structs.sol @@ -9,11 +9,9 @@ contract C { // [ // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { -// "components": -// [ +// "components": [ // { // "internalType": "uint256[2]", // "name": "x", @@ -26,16 +24,14 @@ contract C { // "type": "tuple" // }, // { -// "components": -// [ +// "components": [ // { // "internalType": "uint256", // "name": "a", // "type": "uint256" // }, // { -// "components": -// [ +// "components": [ // { // "internalType": "uint256[2]", // "name": "x", diff --git a/test/libsolidity/ABIJson/events.sol b/test/libsolidity/ABIJson/events.sol index bab6a7436..8c8cfc4a2 100644 --- a/test/libsolidity/ABIJson/events.sol +++ b/test/libsolidity/ABIJson/events.sol @@ -10,8 +10,7 @@ contract test { // [ // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint256", @@ -36,8 +35,7 @@ contract test { // }, // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint256", @@ -55,8 +53,7 @@ contract test { // "type": "event" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "a", @@ -64,8 +61,7 @@ contract test { // } // ], // "name": "f", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "d", diff --git a/test/libsolidity/ABIJson/events_indirect.sol b/test/libsolidity/ABIJson/events_indirect.sol index 86368028c..0d11f79ec 100644 --- a/test/libsolidity/ABIJson/events_indirect.sol +++ b/test/libsolidity/ABIJson/events_indirect.sol @@ -15,8 +15,7 @@ contract test { // [ // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint256", @@ -35,8 +34,7 @@ contract test { // }, // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint256", @@ -60,8 +58,7 @@ contract test { // [ // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": false, // "internalType": "uint256", diff --git a/test/libsolidity/ABIJson/function_type.sol b/test/libsolidity/ABIJson/function_type.sol index 51e36b92b..ab20bbb14 100644 --- a/test/libsolidity/ABIJson/function_type.sol +++ b/test/libsolidity/ABIJson/function_type.sol @@ -5,8 +5,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "function (uint256) external returns (uint256)", // "name": "x", diff --git a/test/libsolidity/ABIJson/function_type_extended.sol b/test/libsolidity/ABIJson/function_type_extended.sol index 6257bb4c4..cac235d6c 100644 --- a/test/libsolidity/ABIJson/function_type_extended.sol +++ b/test/libsolidity/ABIJson/function_type_extended.sol @@ -5,8 +5,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "function (contract test) external returns (contract test[])", // "name": "x", diff --git a/test/libsolidity/ABIJson/global_struct.sol b/test/libsolidity/ABIJson/global_struct.sol index 11ce8246f..960cda232 100644 --- a/test/libsolidity/ABIJson/global_struct.sol +++ b/test/libsolidity/ABIJson/global_struct.sol @@ -8,11 +8,9 @@ contract C { // :C // [ // { -// "inputs": -// [ +// "inputs": [ // { -// "components": -// [ +// "components": [ // { // "internalType": "uint256", // "name": "a", @@ -30,11 +28,9 @@ contract C { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { -// "components": -// [ +// "components": [ // { // "internalType": "uint256", // "name": "a", diff --git a/test/libsolidity/ABIJson/inherited.sol b/test/libsolidity/ABIJson/inherited.sol index cdd8296d8..681cc892b 100644 --- a/test/libsolidity/ABIJson/inherited.sol +++ b/test/libsolidity/ABIJson/inherited.sol @@ -11,8 +11,7 @@ contract Derived is Base { // [ // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": true, // "internalType": "bytes32", @@ -24,8 +23,7 @@ contract Derived is Base { // "type": "event" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "p", @@ -33,8 +31,7 @@ contract Derived is Base { // } // ], // "name": "baseFunction", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "i", @@ -51,8 +48,7 @@ contract Derived is Base { // [ // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": true, // "internalType": "bytes32", @@ -65,8 +61,7 @@ contract Derived is Base { // }, // { // "anonymous": false, -// "inputs": -// [ +// "inputs": [ // { // "indexed": true, // "internalType": "uint256", @@ -78,8 +73,7 @@ contract Derived is Base { // "type": "event" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "p", @@ -87,8 +81,7 @@ contract Derived is Base { // } // ], // "name": "baseFunction", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "i", @@ -99,8 +92,7 @@ contract Derived is Base { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "bytes32", // "name": "p", @@ -108,8 +100,7 @@ contract Derived is Base { // } // ], // "name": "derivedFunction", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "bytes32", // "name": "i", diff --git a/test/libsolidity/ABIJson/library_function.sol b/test/libsolidity/ABIJson/library_function.sol index 5fe404e95..2a27729fc 100644 --- a/test/libsolidity/ABIJson/library_function.sol +++ b/test/libsolidity/ABIJson/library_function.sol @@ -12,8 +12,7 @@ library test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256[]", // "name": "c", @@ -26,8 +25,7 @@ library test { // } // ], // "name": "f1", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256[]", // "name": "e", diff --git a/test/libsolidity/ABIJson/mapping.sol b/test/libsolidity/ABIJson/mapping.sol index e84b716f2..1c5e29fd8 100644 --- a/test/libsolidity/ABIJson/mapping.sol +++ b/test/libsolidity/ABIJson/mapping.sol @@ -7,8 +7,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "address", // "name": "owner", @@ -21,8 +20,7 @@ contract test { // } // ], // "name": "allowance", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "value", @@ -33,8 +31,7 @@ contract test { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "bytes32", // "name": "", @@ -42,8 +39,7 @@ contract test { // } // ], // "name": "commits", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "address", // "name": "sender", @@ -54,8 +50,7 @@ contract test { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "bytes32", // "name": "", @@ -63,8 +58,7 @@ contract test { // } // ], // "name": "something", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "bytes32", // "name": "", diff --git a/test/libsolidity/ABIJson/multiple_methods.sol b/test/libsolidity/ABIJson/multiple_methods.sol index f4738e6ea..6ff81c4a6 100644 --- a/test/libsolidity/ABIJson/multiple_methods.sol +++ b/test/libsolidity/ABIJson/multiple_methods.sol @@ -6,8 +6,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "a", @@ -15,8 +14,7 @@ contract test { // } // ], // "name": "f", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "d", @@ -27,8 +25,7 @@ contract test { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "b", @@ -36,8 +33,7 @@ contract test { // } // ], // "name": "g", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "e", diff --git a/test/libsolidity/ABIJson/multiple_methods_order.sol b/test/libsolidity/ABIJson/multiple_methods_order.sol index 606c80db3..fdc9b6d64 100644 --- a/test/libsolidity/ABIJson/multiple_methods_order.sol +++ b/test/libsolidity/ABIJson/multiple_methods_order.sol @@ -7,8 +7,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "b", @@ -16,8 +15,7 @@ contract test { // } // ], // "name": "c", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "e", @@ -28,8 +26,7 @@ contract test { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "a", @@ -37,8 +34,7 @@ contract test { // } // ], // "name": "f", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "d", diff --git a/test/libsolidity/ABIJson/multiple_params.sol b/test/libsolidity/ABIJson/multiple_params.sol index e223fc3eb..9657905c9 100644 --- a/test/libsolidity/ABIJson/multiple_params.sol +++ b/test/libsolidity/ABIJson/multiple_params.sol @@ -5,8 +5,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "a", @@ -19,8 +18,7 @@ contract test { // } // ], // "name": "f", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "d", diff --git a/test/libsolidity/ABIJson/payable_constructor_abi.sol b/test/libsolidity/ABIJson/payable_constructor_abi.sol index 579e83efb..aa74e2a3f 100644 --- a/test/libsolidity/ABIJson/payable_constructor_abi.sol +++ b/test/libsolidity/ABIJson/payable_constructor_abi.sol @@ -5,8 +5,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "param1", diff --git a/test/libsolidity/ABIJson/pure_function.sol b/test/libsolidity/ABIJson/pure_function.sol index c98431eb2..38c51ebf5 100644 --- a/test/libsolidity/ABIJson/pure_function.sol +++ b/test/libsolidity/ABIJson/pure_function.sol @@ -6,8 +6,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint32", // "name": "a", @@ -15,8 +14,7 @@ contract test { // } // ], // "name": "boo", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "b", @@ -27,8 +25,7 @@ contract test { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "a", @@ -41,8 +38,7 @@ contract test { // } // ], // "name": "foo", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "d", diff --git a/test/libsolidity/ABIJson/return_param_in_abi.sol b/test/libsolidity/ABIJson/return_param_in_abi.sol index 23995d62a..754c474a0 100644 --- a/test/libsolidity/ABIJson/return_param_in_abi.sol +++ b/test/libsolidity/ABIJson/return_param_in_abi.sol @@ -11,8 +11,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "enum test.ActionChoices", // "name": "param", @@ -25,8 +24,7 @@ contract test { // { // "inputs": [], // "name": "ret", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "enum test.ActionChoices", // "name": "", diff --git a/test/libsolidity/ABIJson/return_structs.sol b/test/libsolidity/ABIJson/return_structs.sol index 9a1e493d5..a0bcb84b4 100644 --- a/test/libsolidity/ABIJson/return_structs.sol +++ b/test/libsolidity/ABIJson/return_structs.sol @@ -11,24 +11,21 @@ contract C { // { // "inputs": [], // "name": "f", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "x", // "type": "uint256" // }, // { -// "components": -// [ +// "components": [ // { // "internalType": "uint256", // "name": "a", // "type": "uint256" // }, // { -// "components": -// [ +// "components": [ // { // "internalType": "uint256[2]", // "name": "x", diff --git a/test/libsolidity/ABIJson/return_structs_with_contracts.sol b/test/libsolidity/ABIJson/return_structs_with_contracts.sol index 135c3295f..9c8e81d14 100644 --- a/test/libsolidity/ABIJson/return_structs_with_contracts.sol +++ b/test/libsolidity/ABIJson/return_structs_with_contracts.sol @@ -10,11 +10,9 @@ contract C { // { // "inputs": [], // "name": "f", -// "outputs": -// [ +// "outputs": [ // { -// "components": -// [ +// "components": [ // { // "internalType": "contract C[]", // "name": "x", diff --git a/test/libsolidity/ABIJson/structs_and_arrays.sol b/test/libsolidity/ABIJson/structs_and_arrays.sol index b2c6bc0ad..a4f1bc4d6 100644 --- a/test/libsolidity/ABIJson/structs_and_arrays.sol +++ b/test/libsolidity/ABIJson/structs_and_arrays.sol @@ -6,8 +6,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "string", // "name": "a", diff --git a/test/libsolidity/ABIJson/structs_in_libraries.sol b/test/libsolidity/ABIJson/structs_in_libraries.sol index 3f278337f..edc76327a 100644 --- a/test/libsolidity/ABIJson/structs_in_libraries.sol +++ b/test/libsolidity/ABIJson/structs_in_libraries.sol @@ -9,19 +9,16 @@ library L { // :L // [ // { -// "inputs": -// [ +// "inputs": [ // { -// "components": -// [ +// "components": [ // { // "internalType": "uint256", // "name": "a", // "type": "uint256" // }, // { -// "components": -// [ +// "components": [ // { // "internalType": "uint256[2]", // "name": "x", diff --git a/test/libsolidity/ABIJson/user_defined_value_type.sol b/test/libsolidity/ABIJson/user_defined_value_type.sol index 3bd034e6a..d20ff9903 100644 --- a/test/libsolidity/ABIJson/user_defined_value_type.sol +++ b/test/libsolidity/ABIJson/user_defined_value_type.sol @@ -33,8 +33,7 @@ contract C { // { // "inputs": [], // "name": "myAddress", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "C.MyAddress", // "name": "", @@ -47,8 +46,7 @@ contract C { // { // "inputs": [], // "name": "myByte1", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "MyByte1", // "name": "", @@ -61,8 +59,7 @@ contract C { // { // "inputs": [], // "name": "myBytes32", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "C.MyBytes32", // "name": "", @@ -75,8 +72,7 @@ contract C { // { // "inputs": [], // "name": "myInt", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "MyInt", // "name": "", @@ -89,8 +85,7 @@ contract C { // { // "inputs": [], // "name": "myUInt8", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "C.MyUInt8", // "name": "", @@ -101,8 +96,7 @@ contract C { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "C.MyAddress", // "name": "a", @@ -115,8 +109,7 @@ contract C { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "MyByte1", // "name": "a", @@ -129,8 +122,7 @@ contract C { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "C.MyBytes32", // "name": "a", @@ -143,8 +135,7 @@ contract C { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "MyInt", // "name": "a", @@ -157,8 +148,7 @@ contract C { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "C.MyUInt8", // "name": "a", diff --git a/test/libsolidity/ABIJson/view_function.sol b/test/libsolidity/ABIJson/view_function.sol index d5f54ecde..88f03d636 100644 --- a/test/libsolidity/ABIJson/view_function.sol +++ b/test/libsolidity/ABIJson/view_function.sol @@ -6,8 +6,7 @@ contract test { // :test // [ // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint32", // "name": "a", @@ -15,8 +14,7 @@ contract test { // } // ], // "name": "boo", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "b", @@ -27,8 +25,7 @@ contract test { // "type": "function" // }, // { -// "inputs": -// [ +// "inputs": [ // { // "internalType": "uint256", // "name": "a", @@ -41,8 +38,7 @@ contract test { // } // ], // "name": "foo", -// "outputs": -// [ +// "outputs": [ // { // "internalType": "uint256", // "name": "d", diff --git a/test/libsolidity/ASTJSON/abstract_contract.json b/test/libsolidity/ASTJSON/abstract_contract.json index 48c20b435..fb82b35b2 100644 --- a/test/libsolidity/ASTJSON/abstract_contract.json +++ b/test/libsolidity/ASTJSON/abstract_contract.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ] }, "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": true, "baseContracts": [], @@ -19,18 +16,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "C", "nameLocation": "18:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "37:4:1", @@ -43,15 +37,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "34:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/abstract_contract.sol b/test/libsolidity/ASTJSON/abstract_contract.sol index 3ef96612f..bddbc1779 100644 --- a/test/libsolidity/ASTJSON/abstract_contract.sol +++ b/test/libsolidity/ASTJSON/abstract_contract.sol @@ -2,4 +2,5 @@ abstract contract C { constructor() { } } + // ---- diff --git a/test/libsolidity/ASTJSON/abstract_contract_parseOnly.json b/test/libsolidity/ASTJSON/abstract_contract_parseOnly.json index d9ba04e6c..fedcbd99e 100644 --- a/test/libsolidity/ASTJSON/abstract_contract_parseOnly.json +++ b/test/libsolidity/ASTJSON/abstract_contract_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": true, "baseContracts": [], @@ -13,11 +12,9 @@ "name": "C", "nameLocation": "18:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "37:4:1", @@ -30,15 +27,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "34:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/address_payable.json b/test/libsolidity/ASTJSON/address_payable.json index adf79823e..3e8c7955a 100644 --- a/test/libsolidity/ASTJSON/address_payable.json +++ b/test/libsolidity/ASTJSON/address_payable.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 39 ] }, "id": 40, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,15 +16,13 @@ "contractKind": "contract", "fullyImplemented": true, "id": 39, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 39 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "functionSelector": "97682884", @@ -40,46 +35,39 @@ "src": "17:44:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_address_$_t_address_payable_$", "typeString": "mapping(address => address payable)" }, - "typeName": - { + "typeName": { "id": 3, "keyName": "", "keyNameLocation": "-1:-1:-1", - "keyType": - { + "keyType": { "id": 1, "name": "address", "nodeType": "ElementaryTypeName", "src": "25:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } }, "nodeType": "Mapping", "src": "17:35:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_address_$_t_address_payable_$", "typeString": "mapping(address => address payable)" }, "valueName": "", "valueNameLocation": "-1:-1:-1", - "valueType": - { + "valueType": { "id": 2, "name": "address", "nodeType": "ElementaryTypeName", "src": "36:15:1", "stateMutability": "payable", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } @@ -88,20 +76,16 @@ "visibility": "public" }, { - "body": - { + "body": { "id": 37, "nodeType": "Block", "src": "134:122:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 12 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 12, @@ -113,20 +97,17 @@ "src": "144:17:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" }, - "typeName": - { + "typeName": { "id": 11, "name": "address", "nodeType": "ElementaryTypeName", "src": "144:15:1", "stateMutability": "payable", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } @@ -135,33 +116,28 @@ } ], "id": 16, - "initialValue": - { - "baseExpression": - { + "initialValue": { + "baseExpression": { "id": 13, "name": "m", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 4, "src": "164:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_address_$_t_address_payable_$", "typeString": "mapping(address => address payable)" } }, "id": 15, - "indexExpression": - { + "indexExpression": { "id": 14, "name": "arg", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 6, "src": "166:3:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } @@ -172,8 +148,7 @@ "lValueRequested": false, "nodeType": "IndexAccess", "src": "164:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } @@ -182,46 +157,40 @@ "src": "144:26:1" }, { - "expression": - { + "expression": { "id": 19, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, - "leftHandSide": - { + "leftHandSide": { "id": 17, "name": "r", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 9, "src": "180:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } }, "nodeType": "Assignment", "operator": "=", - "rightHandSide": - { + "rightHandSide": { "id": 18, "name": "arg", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 6, "src": "184:3:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } }, "src": "180:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } @@ -231,12 +200,10 @@ "src": "180:7:1" }, { - "assignments": - [ + "assignments": [ 22 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 22, @@ -248,20 +215,17 @@ "src": "197:9:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" }, - "typeName": - { + "typeName": { "id": 21, "name": "address", "nodeType": "ElementaryTypeName", "src": "197:7:1", "stateMutability": "nonpayable", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } @@ -270,10 +234,8 @@ } ], "id": 27, - "initialValue": - { - "arguments": - [ + "initialValue": { + "arguments": [ { "id": 25, "name": "this", @@ -281,17 +243,14 @@ "overloadedDeclarations": [], "referencedDeclaration": -28, "src": "217:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_contract$_C_$39", "typeString": "contract C" } } ], - "expression": - { - "argumentTypes": - [ + "expression": { + "argumentTypes": [ { "typeIdentifier": "t_contract$_C_$39", "typeString": "contract C" @@ -304,13 +263,11 @@ "lValueRequested": false, "nodeType": "ElementaryTypeNameExpression", "src": "209:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_address_$", "typeString": "type(address)" }, - "typeName": - { + "typeName": { "id": 23, "name": "address", "nodeType": "ElementaryTypeName", @@ -329,8 +286,7 @@ "nodeType": "FunctionCall", "src": "209:13:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } @@ -339,40 +295,34 @@ "src": "197:25:1" }, { - "expression": - { + "expression": { "id": 35, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, - "leftHandSide": - { - "baseExpression": - { + "leftHandSide": { + "baseExpression": { "id": 28, "name": "m", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 4, "src": "232:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_address_$_t_address_payable_$", "typeString": "mapping(address => address payable)" } }, "id": 30, - "indexExpression": - { + "indexExpression": { "id": 29, "name": "c", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 22, "src": "234:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } @@ -383,18 +333,15 @@ "lValueRequested": true, "nodeType": "IndexAccess", "src": "232:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } }, "nodeType": "Assignment", "operator": "=", - "rightHandSide": - { - "arguments": - [ + "rightHandSide": { + "arguments": [ { "hexValue": "30", "id": 33, @@ -405,18 +352,15 @@ "lValueRequested": false, "nodeType": "Literal", "src": "247:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_0_by_1", "typeString": "int_const 0" }, "value": "0" } ], - "expression": - { - "argumentTypes": - [ + "expression": { + "argumentTypes": [ { "typeIdentifier": "t_rational_0_by_1", "typeString": "int_const 0" @@ -429,13 +373,11 @@ "lValueRequested": false, "nodeType": "ElementaryTypeNameExpression", "src": "239:8:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_address_payable_$", "typeString": "type(address payable)" }, - "typeName": - { + "typeName": { "id": 31, "name": "address", "nodeType": "ElementaryTypeName", @@ -455,15 +397,13 @@ "nodeType": "FunctionCall", "src": "239:10:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } }, "src": "232:17:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } @@ -482,12 +422,10 @@ "name": "f", "nameLocation": "76:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 6, @@ -499,20 +437,17 @@ "src": "78:19:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" }, - "typeName": - { + "typeName": { "id": 5, "name": "address", "nodeType": "ElementaryTypeName", "src": "78:15:1", "stateMutability": "payable", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } @@ -522,12 +457,10 @@ ], "src": "77:21:1" }, - "returnParameters": - { + "returnParameters": { "id": 10, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 9, @@ -539,20 +472,17 @@ "src": "115:17:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" }, - "typeName": - { + "typeName": { "id": 8, "name": "address", "nodeType": "ElementaryTypeName", "src": "115:15:1", "stateMutability": "payable", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address_payable", "typeString": "address payable" } diff --git a/test/libsolidity/ASTJSON/address_payable.sol b/test/libsolidity/ASTJSON/address_payable.sol index f9ebb124e..28c9c8a20 100644 --- a/test/libsolidity/ASTJSON/address_payable.sol +++ b/test/libsolidity/ASTJSON/address_payable.sol @@ -7,4 +7,5 @@ contract C { m[c] = payable(0); } } + // ---- diff --git a/test/libsolidity/ASTJSON/address_payable_parseOnly.json b/test/libsolidity/ASTJSON/address_payable_parseOnly.json index 02b809cc9..84e60f1cd 100644 --- a/test/libsolidity/ASTJSON/address_payable_parseOnly.json +++ b/test/libsolidity/ASTJSON/address_payable_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 40, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,8 +12,7 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 4, @@ -26,13 +24,11 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 3, "keyName": "", "keyNameLocation": "-1:-1:-1", - "keyType": - { + "keyType": { "id": 1, "name": "address", "nodeType": "ElementaryTypeName", @@ -44,8 +40,7 @@ "typeDescriptions": {}, "valueName": "", "valueNameLocation": "-1:-1:-1", - "valueType": - { + "valueType": { "id": 2, "name": "address", "nodeType": "ElementaryTypeName", @@ -57,20 +52,16 @@ "visibility": "public" }, { - "body": - { + "body": { "id": 37, "nodeType": "Block", "src": "134:122:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 12 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 12, @@ -82,8 +73,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 11, "name": "address", "nodeType": "ElementaryTypeName", @@ -95,10 +85,8 @@ } ], "id": 16, - "initialValue": - { - "baseExpression": - { + "initialValue": { + "baseExpression": { "id": 13, "name": "m", "nodeType": "Identifier", @@ -107,8 +95,7 @@ "typeDescriptions": {} }, "id": 15, - "indexExpression": - { + "indexExpression": { "id": 14, "name": "arg", "nodeType": "Identifier", @@ -124,11 +111,9 @@ "src": "144:26:1" }, { - "expression": - { + "expression": { "id": 19, - "leftHandSide": - { + "leftHandSide": { "id": 17, "name": "r", "nodeType": "Identifier", @@ -138,8 +123,7 @@ }, "nodeType": "Assignment", "operator": "=", - "rightHandSide": - { + "rightHandSide": { "id": 18, "name": "arg", "nodeType": "Identifier", @@ -155,12 +139,10 @@ "src": "180:7:1" }, { - "assignments": - [ + "assignments": [ 22 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 22, @@ -172,8 +154,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 21, "name": "address", "nodeType": "ElementaryTypeName", @@ -185,10 +166,8 @@ } ], "id": 27, - "initialValue": - { - "arguments": - [ + "initialValue": { + "arguments": [ { "id": 25, "name": "this", @@ -198,14 +177,12 @@ "typeDescriptions": {} } ], - "expression": - { + "expression": { "id": 24, "nodeType": "ElementaryTypeNameExpression", "src": "209:7:1", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 23, "name": "address", "nodeType": "ElementaryTypeName", @@ -225,13 +202,10 @@ "src": "197:25:1" }, { - "expression": - { + "expression": { "id": 35, - "leftHandSide": - { - "baseExpression": - { + "leftHandSide": { + "baseExpression": { "id": 28, "name": "m", "nodeType": "Identifier", @@ -240,8 +214,7 @@ "typeDescriptions": {} }, "id": 30, - "indexExpression": - { + "indexExpression": { "id": 29, "name": "c", "nodeType": "Identifier", @@ -255,10 +228,8 @@ }, "nodeType": "Assignment", "operator": "=", - "rightHandSide": - { - "arguments": - [ + "rightHandSide": { + "arguments": [ { "hexValue": "30", "id": 33, @@ -269,14 +240,12 @@ "value": "0" } ], - "expression": - { + "expression": { "id": 32, "nodeType": "ElementaryTypeNameExpression", "src": "239:8:1", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 31, "name": "address", "nodeType": "ElementaryTypeName", @@ -309,12 +278,10 @@ "name": "f", "nameLocation": "76:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 6, @@ -326,8 +293,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 5, "name": "address", "nodeType": "ElementaryTypeName", @@ -340,12 +306,10 @@ ], "src": "77:21:1" }, - "returnParameters": - { + "returnParameters": { "id": 10, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 9, @@ -357,8 +321,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 8, "name": "address", "nodeType": "ElementaryTypeName", diff --git a/test/libsolidity/ASTJSON/array_type_name.json b/test/libsolidity/ASTJSON/array_type_name.json index 1cd97e176..e87f505f0 100644 --- a/test/libsolidity/ASTJSON/array_type_name.json +++ b/test/libsolidity/ASTJSON/array_type_name.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 4 ] }, "id": 5, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,15 +16,13 @@ "contractKind": "contract", "fullyImplemented": true, "id": 4, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 4 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 3, @@ -39,21 +34,17 @@ "src": "13:8:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_uint256_$dyn_storage", "typeString": "uint256[]" }, - "typeName": - { - "baseType": - { + "typeName": { + "baseType": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", "src": "13:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -61,8 +52,7 @@ "id": 2, "nodeType": "ArrayTypeName", "src": "13:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_uint256_$dyn_storage_ptr", "typeString": "uint256[]" } diff --git a/test/libsolidity/ASTJSON/array_type_name_parseOnly.json b/test/libsolidity/ASTJSON/array_type_name_parseOnly.json index 1e0b72ca0..6c61e8d7d 100644 --- a/test/libsolidity/ASTJSON/array_type_name_parseOnly.json +++ b/test/libsolidity/ASTJSON/array_type_name_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 5, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,8 +12,7 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 3, @@ -26,10 +24,8 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { - "baseType": - { + "typeName": { + "baseType": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", diff --git a/test/libsolidity/ASTJSON/assembly/call.json b/test/libsolidity/ASTJSON/assembly/call.json index d92cf05fe..6d5ffe9b6 100644 --- a/test/libsolidity/ASTJSON/assembly/call.json +++ b/test/libsolidity/ASTJSON/assembly/call.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,39 +16,30 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "37:59:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "56:34:1", "nodeType": "YulBlock", "src": "56:34:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "67:1:1", @@ -109,8 +97,7 @@ "value": "6" } ], - "functionName": - { + "functionName": { "name": "call", "nativeSrc": "62:4:1", "nodeType": "YulIdentifier", @@ -121,8 +108,7 @@ "src": "62:25:1" } ], - "functionName": - { + "functionName": { "name": "pop", "nativeSrc": "58:3:1", "nodeType": "YulIdentifier", @@ -154,15 +140,13 @@ "name": "j", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/call.sol b/test/libsolidity/ASTJSON/assembly/call.sol index 1735fd7f7..09d1ce184 100644 --- a/test/libsolidity/ASTJSON/assembly/call.sol +++ b/test/libsolidity/ASTJSON/assembly/call.sol @@ -3,4 +3,5 @@ contract C { assembly { pop(call(0, 1, 2, 3, 4, 5, 6)) } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/call_parseOnly.json b/test/libsolidity/ASTJSON/assembly/call_parseOnly.json index 803a1e4f5..1e7c5b1f8 100644 --- a/test/libsolidity/ASTJSON/assembly/call_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/call_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,32 +12,24 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "37:59:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "56:34:1", "nodeType": "YulBlock", "src": "56:34:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "67:1:1", @@ -96,8 +87,7 @@ "value": "6" } ], - "functionName": - { + "functionName": { "name": "call", "nativeSrc": "62:4:1", "nodeType": "YulIdentifier", @@ -108,8 +98,7 @@ "src": "62:25:1" } ], - "functionName": - { + "functionName": { "name": "pop", "nativeSrc": "58:3:1", "nodeType": "YulIdentifier", @@ -140,15 +129,13 @@ "name": "j", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/empty_block.json b/test/libsolidity/ASTJSON/assembly/empty_block.json index 3ec3c2eec..1829d057d 100644 --- a/test/libsolidity/ASTJSON/assembly/empty_block.json +++ b/test/libsolidity/ASTJSON/assembly/empty_block.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,31 +16,25 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "42:31:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "61:6:1", "nodeType": "YulBlock", "src": "61:6:1", - "statements": - [ + "statements": [ { "nativeSrc": "63:2:1", "nodeType": "YulBlock", @@ -68,15 +59,13 @@ "name": "g", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/empty_block.sol b/test/libsolidity/ASTJSON/assembly/empty_block.sol index 33bb796ea..23c2babbe 100644 --- a/test/libsolidity/ASTJSON/assembly/empty_block.sol +++ b/test/libsolidity/ASTJSON/assembly/empty_block.sol @@ -3,4 +3,5 @@ contract C { assembly { {} } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/empty_block_parseOnly.json b/test/libsolidity/ASTJSON/assembly/empty_block_parseOnly.json index ee8e7b733..92404c15f 100644 --- a/test/libsolidity/ASTJSON/assembly/empty_block_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/empty_block_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,24 +12,19 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "42:31:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "61:6:1", "nodeType": "YulBlock", "src": "61:6:1", - "statements": - [ + "statements": [ { "nativeSrc": "63:2:1", "nodeType": "YulBlock", @@ -54,15 +48,13 @@ "name": "g", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration.json b/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration.json index 9d64279da..b9435a41c 100644 --- a/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration.json +++ b/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,37 +16,30 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "39:30:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "52:14:1", "nodeType": "YulBlock", "src": "52:14:1", - "statements": - [ + "statements": [ { "nativeSrc": "57:5:1", "nodeType": "YulVariableDeclaration", "src": "57:5:1", - "variables": - [ + "variables": [ { "name": "x", "nativeSrc": "61:1:1", @@ -77,15 +67,13 @@ "name": "f", "nameLocation": "23:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "24:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration.sol b/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration.sol index 5b396dd44..bfc5ff95f 100644 --- a/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration.sol +++ b/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration.sol @@ -5,4 +5,5 @@ contract C { } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration_parseOnly.json b/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration_parseOnly.json index 5f12f280b..bba11cc63 100644 --- a/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/empty_let_variable_declaration_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,30 +12,24 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "39:30:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "52:14:1", "nodeType": "YulBlock", "src": "52:14:1", - "statements": - [ + "statements": [ { "nativeSrc": "57:5:1", "nodeType": "YulVariableDeclaration", "src": "57:5:1", - "variables": - [ + "variables": [ { "name": "x", "nativeSrc": "61:1:1", @@ -63,15 +56,13 @@ "name": "f", "nameLocation": "23:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "24:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/function.json b/test/libsolidity/ASTJSON/assembly/function.json index a3b908ac1..c409d615e 100644 --- a/test/libsolidity/ASTJSON/assembly/function.json +++ b/test/libsolidity/ASTJSON/assembly/function.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,47 +16,36 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "42:68:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "61:43:1", "nodeType": "YulBlock", "src": "61:43:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "76:22:1", "nodeType": "YulBlock", "src": "76:22:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "92:2:1", @@ -69,8 +55,7 @@ "value": "20" } ], - "functionName": - { + "functionName": { "name": "blockhash", "nativeSrc": "82:9:1", "nodeType": "YulIdentifier", @@ -81,8 +66,7 @@ "src": "82:13:1" } ], - "functionName": - { + "functionName": { "name": "pop", "nativeSrc": "78:3:1", "nodeType": "YulIdentifier", @@ -104,11 +88,9 @@ "src": "63:35:1" }, { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "g", "nativeSrc": "99:1:1", "nodeType": "YulIdentifier", @@ -140,15 +122,13 @@ "name": "h", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/function.sol b/test/libsolidity/ASTJSON/assembly/function.sol index 1edf2f2de..6020f1f51 100644 --- a/test/libsolidity/ASTJSON/assembly/function.sol +++ b/test/libsolidity/ASTJSON/assembly/function.sol @@ -3,4 +3,5 @@ contract C { assembly { function g() { pop(blockhash(20)) } g() } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/function_parseOnly.json b/test/libsolidity/ASTJSON/assembly/function_parseOnly.json index 04f5c2721..2e681ed63 100644 --- a/test/libsolidity/ASTJSON/assembly/function_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/function_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,40 +12,30 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "42:68:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "61:43:1", "nodeType": "YulBlock", "src": "61:43:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "76:22:1", "nodeType": "YulBlock", "src": "76:22:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "92:2:1", @@ -56,8 +45,7 @@ "value": "20" } ], - "functionName": - { + "functionName": { "name": "blockhash", "nativeSrc": "82:9:1", "nodeType": "YulIdentifier", @@ -68,8 +56,7 @@ "src": "82:13:1" } ], - "functionName": - { + "functionName": { "name": "pop", "nativeSrc": "78:3:1", "nodeType": "YulIdentifier", @@ -91,11 +78,9 @@ "src": "63:35:1" }, { - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "g", "nativeSrc": "99:1:1", "nodeType": "YulIdentifier", @@ -126,15 +111,13 @@ "name": "h", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/leave.json b/test/libsolidity/ASTJSON/assembly/leave.json index 51c94f542..e7fbf9f6f 100644 --- a/test/libsolidity/ASTJSON/assembly/leave.json +++ b/test/libsolidity/ASTJSON/assembly/leave.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,39 +16,31 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "37:51:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "56:26:1", "nodeType": "YulBlock", "src": "56:26:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "71:9:1", "nodeType": "YulBlock", "src": "71:9:1", - "statements": - [ + "statements": [ { "nativeSrc": "73:5:1", "nodeType": "YulLeave", @@ -82,15 +71,13 @@ "name": "l", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/leave.sol b/test/libsolidity/ASTJSON/assembly/leave.sol index 39f1cafed..5ae4a9e0d 100644 --- a/test/libsolidity/ASTJSON/assembly/leave.sol +++ b/test/libsolidity/ASTJSON/assembly/leave.sol @@ -3,4 +3,5 @@ contract C { assembly { function f() { leave } } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/leave_parseOnly.json b/test/libsolidity/ASTJSON/assembly/leave_parseOnly.json index ee34743ea..c71ffd3fe 100644 --- a/test/libsolidity/ASTJSON/assembly/leave_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/leave_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,32 +12,25 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "37:51:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "56:26:1", "nodeType": "YulBlock", "src": "56:26:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "71:9:1", "nodeType": "YulBlock", "src": "71:9:1", - "statements": - [ + "statements": [ { "nativeSrc": "73:5:1", "nodeType": "YulLeave", @@ -68,15 +60,13 @@ "name": "l", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/loop.json b/test/libsolidity/ASTJSON/assembly/loop.json index d3d20992d..01efb79e6 100644 --- a/test/libsolidity/ASTJSON/assembly/loop.json +++ b/test/libsolidity/ASTJSON/assembly/loop.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,39 +16,31 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "42:74:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "61:49:1", "nodeType": "YulBlock", "src": "61:49:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "90:18:1", "nodeType": "YulBlock", "src": "90:18:1", - "statements": - [ + "statements": [ { "nativeSrc": "92:5:1", "nodeType": "YulBreak", @@ -64,8 +53,7 @@ } ] }, - "condition": - { + "condition": { "kind": "number", "nativeSrc": "70:1:1", "nodeType": "YulLiteral", @@ -75,21 +63,16 @@ }, "nativeSrc": "63:45:1", "nodeType": "YulForLoop", - "post": - { + "post": { "nativeSrc": "72:17:1", "nodeType": "YulBlock", "src": "72:17:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "84:1:1", @@ -99,8 +82,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "sload", "nativeSrc": "78:5:1", "nodeType": "YulIdentifier", @@ -111,8 +93,7 @@ "src": "78:8:1" } ], - "functionName": - { + "functionName": { "name": "pop", "nativeSrc": "74:3:1", "nodeType": "YulIdentifier", @@ -128,8 +109,7 @@ } ] }, - "pre": - { + "pre": { "nativeSrc": "67:2:1", "nodeType": "YulBlock", "src": "67:2:1", @@ -155,15 +135,13 @@ "name": "g", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/loop.sol b/test/libsolidity/ASTJSON/assembly/loop.sol index baa45e62c..bba8d282f 100644 --- a/test/libsolidity/ASTJSON/assembly/loop.sol +++ b/test/libsolidity/ASTJSON/assembly/loop.sol @@ -3,4 +3,5 @@ contract C { assembly { for {} 1 { pop(sload(0)) } { break continue } } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/loop_parseOnly.json b/test/libsolidity/ASTJSON/assembly/loop_parseOnly.json index 24dbbdc4e..8fecb9dfd 100644 --- a/test/libsolidity/ASTJSON/assembly/loop_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/loop_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,32 +12,25 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "42:74:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "61:49:1", "nodeType": "YulBlock", "src": "61:49:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "90:18:1", "nodeType": "YulBlock", "src": "90:18:1", - "statements": - [ + "statements": [ { "nativeSrc": "92:5:1", "nodeType": "YulBreak", @@ -51,8 +43,7 @@ } ] }, - "condition": - { + "condition": { "kind": "number", "nativeSrc": "70:1:1", "nodeType": "YulLiteral", @@ -62,21 +53,16 @@ }, "nativeSrc": "63:45:1", "nodeType": "YulForLoop", - "post": - { + "post": { "nativeSrc": "72:17:1", "nodeType": "YulBlock", "src": "72:17:1", - "statements": - [ + "statements": [ { - "expression": - { - "arguments": - [ + "expression": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "kind": "number", "nativeSrc": "84:1:1", @@ -86,8 +72,7 @@ "value": "0" } ], - "functionName": - { + "functionName": { "name": "sload", "nativeSrc": "78:5:1", "nodeType": "YulIdentifier", @@ -98,8 +83,7 @@ "src": "78:8:1" } ], - "functionName": - { + "functionName": { "name": "pop", "nativeSrc": "74:3:1", "nodeType": "YulIdentifier", @@ -115,8 +99,7 @@ } ] }, - "pre": - { + "pre": { "nativeSrc": "67:2:1", "nodeType": "YulBlock", "src": "67:2:1", @@ -141,15 +124,13 @@ "name": "g", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/nested_functions.json b/test/libsolidity/ASTJSON/assembly/nested_functions.json index 3c9fd53ec..c4c2b0ae4 100644 --- a/test/libsolidity/ASTJSON/assembly/nested_functions.json +++ b/test/libsolidity/ASTJSON/assembly/nested_functions.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 8 ] }, "id": 9, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,42 +16,33 @@ "contractKind": "contract", "fullyImplemented": true, "id": 8, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 8 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 6, "nodeType": "Block", "src": "57:95:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "72:76:1", "nodeType": "YulBlock", "src": "72:76:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "94:35:1", "nodeType": "YulBlock", "src": "94:35:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "118:3:1", "nodeType": "YulBlock", "src": "118:3:1", @@ -76,8 +64,7 @@ "nativeSrc": "136:6:1", "nodeType": "YulAssignment", "src": "136:6:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "141:1:1", "nodeType": "YulLiteral", @@ -85,8 +72,7 @@ "type": "", "value": "2" }, - "variableNames": - [ + "variableNames": [ { "name": "x", "nativeSrc": "136:1:1", @@ -98,8 +84,7 @@ ] }, "evmVersion": %EVMVERSION%, - "externalReferences": - [ + "externalReferences": [ { "declaration": 3, "isOffset": false, @@ -122,19 +107,16 @@ "name": "f", "nameLocation": "24:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "25:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 4, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 3, @@ -146,19 +128,16 @@ "src": "49:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 2, "name": "uint", "nodeType": "ElementaryTypeName", "src": "49:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } diff --git a/test/libsolidity/ASTJSON/assembly/nested_functions.sol b/test/libsolidity/ASTJSON/assembly/nested_functions.sol index 42479fa94..396efa0bf 100644 --- a/test/libsolidity/ASTJSON/assembly/nested_functions.sol +++ b/test/libsolidity/ASTJSON/assembly/nested_functions.sol @@ -8,4 +8,5 @@ contract C { } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/nested_functions_parseOnly.json b/test/libsolidity/ASTJSON/assembly/nested_functions_parseOnly.json index b924b42cf..acb05ca86 100644 --- a/test/libsolidity/ASTJSON/assembly/nested_functions_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/nested_functions_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 9, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,35 +12,27 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 6, "nodeType": "Block", "src": "57:95:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "72:76:1", "nodeType": "YulBlock", "src": "72:76:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "94:35:1", "nodeType": "YulBlock", "src": "94:35:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "nativeSrc": "118:3:1", "nodeType": "YulBlock", "src": "118:3:1", @@ -63,8 +54,7 @@ "nativeSrc": "136:6:1", "nodeType": "YulAssignment", "src": "136:6:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "141:1:1", "nodeType": "YulLiteral", @@ -72,8 +62,7 @@ "type": "", "value": "2" }, - "variableNames": - [ + "variableNames": [ { "name": "x", "nativeSrc": "136:1:1", @@ -99,19 +88,16 @@ "name": "f", "nameLocation": "24:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "25:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 4, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 3, @@ -123,8 +109,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 2, "name": "uint", "nodeType": "ElementaryTypeName", diff --git a/test/libsolidity/ASTJSON/assembly/slot_offset.json b/test/libsolidity/ASTJSON/assembly/slot_offset.json index 799239b3a..8599bf3a8 100644 --- a/test/libsolidity/ASTJSON/assembly/slot_offset.json +++ b/test/libsolidity/ASTJSON/assembly/slot_offset.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 12 ] }, "id": 13, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,20 +16,17 @@ "contractKind": "contract", "fullyImplemented": true, "id": 12, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 12 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "canonicalName": "C.S", "id": 3, - "members": - [ + "members": [ { "constant": false, "id": 2, @@ -44,19 +38,16 @@ "src": "28:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", "src": "28:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -82,21 +73,17 @@ "src": "42:3:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_struct$_S_$3_storage", "typeString": "struct C.S" }, - "typeName": - { + "typeName": { "id": 5, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 4, "name": "S", - "nameLocations": - [ + "nameLocations": [ "42:1:1" ], "nodeType": "IdentifierPath", @@ -105,8 +92,7 @@ }, "referencedDeclaration": 3, "src": "42:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_struct$_S_$3_storage_ptr", "typeString": "struct C.S" } @@ -114,34 +100,28 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 10, "nodeType": "Block", "src": "76:70:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "95:45:1", "nodeType": "YulBlock", "src": "95:45:1", - "statements": - [ + "statements": [ { "nativeSrc": "97:17:1", "nodeType": "YulVariableDeclaration", "src": "97:17:1", - "value": - { + "value": { "name": "s.offset", "nativeSrc": "106:8:1", "nodeType": "YulIdentifier", "src": "106:8:1" }, - "variables": - [ + "variables": [ { "name": "x", "nativeSrc": "101:1:1", @@ -155,10 +135,8 @@ "nativeSrc": "115:23:1", "nodeType": "YulVariableDeclaration", "src": "115:23:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "s.slot", "nativeSrc": "128:6:1", @@ -174,8 +152,7 @@ "value": "2" } ], - "functionName": - { + "functionName": { "name": "mul", "nativeSrc": "124:3:1", "nodeType": "YulIdentifier", @@ -185,8 +162,7 @@ "nodeType": "YulFunctionCall", "src": "124:14:1" }, - "variables": - [ + "variables": [ { "name": "y", "nativeSrc": "119:1:1", @@ -199,8 +175,7 @@ ] }, "evmVersion": %EVMVERSION%, - "externalReferences": - [ + "externalReferences": [ { "declaration": 6, "isOffset": true, @@ -232,15 +207,13 @@ "name": "e", "nameLocation": "60:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", "parameters": [], "src": "61:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 8, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/slot_offset.sol b/test/libsolidity/ASTJSON/assembly/slot_offset.sol index 0cc2b07c1..d3c8f7554 100644 --- a/test/libsolidity/ASTJSON/assembly/slot_offset.sol +++ b/test/libsolidity/ASTJSON/assembly/slot_offset.sol @@ -5,4 +5,5 @@ contract C { assembly { let x := s.offset let y := mul(s.slot, 2) } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/slot_offset_parseOnly.json b/test/libsolidity/ASTJSON/assembly/slot_offset_parseOnly.json index ef8dc8b0a..5363931c4 100644 --- a/test/libsolidity/ASTJSON/assembly/slot_offset_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/slot_offset_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 13, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,12 +12,10 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "id": 3, - "members": - [ + "members": [ { "constant": false, "id": 2, @@ -30,8 +27,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", @@ -58,16 +54,13 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 5, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 4, "name": "S", - "nameLocations": - [ + "nameLocations": [ "42:1:1" ], "nodeType": "IdentifierPath", @@ -79,34 +72,28 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 10, "nodeType": "Block", "src": "76:70:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "95:45:1", "nodeType": "YulBlock", "src": "95:45:1", - "statements": - [ + "statements": [ { "nativeSrc": "97:17:1", "nodeType": "YulVariableDeclaration", "src": "97:17:1", - "value": - { + "value": { "name": "s.offset", "nativeSrc": "106:8:1", "nodeType": "YulIdentifier", "src": "106:8:1" }, - "variables": - [ + "variables": [ { "name": "x", "nativeSrc": "101:1:1", @@ -120,10 +107,8 @@ "nativeSrc": "115:23:1", "nodeType": "YulVariableDeclaration", "src": "115:23:1", - "value": - { - "arguments": - [ + "value": { + "arguments": [ { "name": "s.slot", "nativeSrc": "128:6:1", @@ -139,8 +124,7 @@ "value": "2" } ], - "functionName": - { + "functionName": { "name": "mul", "nativeSrc": "124:3:1", "nodeType": "YulIdentifier", @@ -150,8 +134,7 @@ "nodeType": "YulFunctionCall", "src": "124:14:1" }, - "variables": - [ + "variables": [ { "name": "y", "nativeSrc": "119:1:1", @@ -178,15 +161,13 @@ "name": "e", "nameLocation": "60:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", "parameters": [], "src": "61:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 8, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/stringlit.json b/test/libsolidity/ASTJSON/assembly/stringlit.json index ab27a3d16..2a27e55b2 100644 --- a/test/libsolidity/ASTJSON/assembly/stringlit.json +++ b/test/libsolidity/ASTJSON/assembly/stringlit.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,37 +16,30 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "37:43:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "56:18:1", "nodeType": "YulBlock", "src": "56:18:1", - "statements": - [ + "statements": [ { "nativeSrc": "58:14:1", "nodeType": "YulVariableDeclaration", "src": "58:14:1", - "value": - { + "value": { "hexValue": "616263", "kind": "string", "nativeSrc": "67:5:1", @@ -58,8 +48,7 @@ "type": "", "value": "abc" }, - "variables": - [ + "variables": [ { "name": "x", "nativeSrc": "62:1:1", @@ -87,15 +76,13 @@ "name": "m", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/stringlit.sol b/test/libsolidity/ASTJSON/assembly/stringlit.sol index 6f5278ac1..e382095ad 100644 --- a/test/libsolidity/ASTJSON/assembly/stringlit.sol +++ b/test/libsolidity/ASTJSON/assembly/stringlit.sol @@ -3,4 +3,5 @@ contract C { assembly { let x := "abc" } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/stringlit_parseOnly.json b/test/libsolidity/ASTJSON/assembly/stringlit_parseOnly.json index 3cb2a9072..3d021620e 100644 --- a/test/libsolidity/ASTJSON/assembly/stringlit_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/stringlit_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,30 +12,24 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "37:43:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "56:18:1", "nodeType": "YulBlock", "src": "56:18:1", - "statements": - [ + "statements": [ { "nativeSrc": "58:14:1", "nodeType": "YulVariableDeclaration", "src": "58:14:1", - "value": - { + "value": { "hexValue": "616263", "kind": "string", "nativeSrc": "67:5:1", @@ -45,8 +38,7 @@ "type": "", "value": "abc" }, - "variables": - [ + "variables": [ { "name": "x", "nativeSrc": "62:1:1", @@ -73,15 +65,13 @@ "name": "m", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/switch.json b/test/libsolidity/ASTJSON/assembly/switch.json index 99c69e048..1a418931b 100644 --- a/test/libsolidity/ASTJSON/assembly/switch.json +++ b/test/libsolidity/ASTJSON/assembly/switch.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,37 +16,30 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "42:154:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "61:129:1", "nodeType": "YulBlock", "src": "61:129:1", - "statements": - [ + "statements": [ { "nativeSrc": "75:10:1", "nodeType": "YulVariableDeclaration", "src": "75:10:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "84:1:1", "nodeType": "YulLiteral", @@ -57,8 +47,7 @@ "type": "", "value": "0" }, - "variables": - [ + "variables": [ { "name": "v", "nativeSrc": "79:1:1", @@ -69,22 +58,18 @@ ] }, { - "cases": - [ + "cases": [ { - "body": - { + "body": { "nativeSrc": "139:10:1", "nodeType": "YulBlock", "src": "139:10:1", - "statements": - [ + "statements": [ { "nativeSrc": "141:6:1", "nodeType": "YulAssignment", "src": "141:6:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "146:1:1", "nodeType": "YulLiteral", @@ -92,8 +77,7 @@ "type": "", "value": "1" }, - "variableNames": - [ + "variableNames": [ { "name": "v", "nativeSrc": "141:1:1", @@ -107,8 +91,7 @@ "nativeSrc": "132:17:1", "nodeType": "YulCase", "src": "132:17:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "137:1:1", "nodeType": "YulLiteral", @@ -118,19 +101,16 @@ } }, { - "body": - { + "body": { "nativeSrc": "170:10:1", "nodeType": "YulBlock", "src": "170:10:1", - "statements": - [ + "statements": [ { "nativeSrc": "172:6:1", "nodeType": "YulAssignment", "src": "172:6:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "177:1:1", "nodeType": "YulLiteral", @@ -138,8 +118,7 @@ "type": "", "value": "2" }, - "variableNames": - [ + "variableNames": [ { "name": "v", "nativeSrc": "172:1:1", @@ -156,11 +135,9 @@ "value": "default" } ], - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "calldatasize", "nativeSrc": "105:12:1", "nodeType": "YulIdentifier", @@ -192,15 +169,13 @@ "name": "f", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/switch.sol b/test/libsolidity/ASTJSON/assembly/switch.sol index a7a23d26a..c04d311b0 100644 --- a/test/libsolidity/ASTJSON/assembly/switch.sol +++ b/test/libsolidity/ASTJSON/assembly/switch.sol @@ -8,4 +8,5 @@ contract C { } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/switch_default.json b/test/libsolidity/ASTJSON/assembly/switch_default.json index 07f804f3c..9d016e261 100644 --- a/test/libsolidity/ASTJSON/assembly/switch_default.json +++ b/test/libsolidity/ASTJSON/assembly/switch_default.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 6 ] }, "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,37 +16,29 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "42:58:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "61:33:1", "nodeType": "YulBlock", "src": "61:33:1", - "statements": - [ + "statements": [ { - "cases": - [ + "cases": [ { - "body": - { + "body": { "nativeSrc": "79:2:1", "nodeType": "YulBlock", "src": "79:2:1", @@ -58,8 +47,7 @@ "nativeSrc": "72:9:1", "nodeType": "YulCase", "src": "72:9:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "77:1:1", "nodeType": "YulLiteral", @@ -69,8 +57,7 @@ } }, { - "body": - { + "body": { "nativeSrc": "90:2:1", "nodeType": "YulBlock", "src": "90:2:1", @@ -82,8 +69,7 @@ "value": "default" } ], - "expression": - { + "expression": { "kind": "number", "nativeSrc": "70:1:1", "nodeType": "YulLiteral", @@ -113,15 +99,13 @@ "name": "g", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/switch_default.sol b/test/libsolidity/ASTJSON/assembly/switch_default.sol index 0760bb7df..1f61896fe 100644 --- a/test/libsolidity/ASTJSON/assembly/switch_default.sol +++ b/test/libsolidity/ASTJSON/assembly/switch_default.sol @@ -3,4 +3,5 @@ contract C { assembly { switch 0 case 0 {} default {} } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/switch_default_parseOnly.json b/test/libsolidity/ASTJSON/assembly/switch_default_parseOnly.json index 2ec302770..22523b478 100644 --- a/test/libsolidity/ASTJSON/assembly/switch_default_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/switch_default_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,30 +12,23 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "42:58:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "61:33:1", "nodeType": "YulBlock", "src": "61:33:1", - "statements": - [ + "statements": [ { - "cases": - [ + "cases": [ { - "body": - { + "body": { "nativeSrc": "79:2:1", "nodeType": "YulBlock", "src": "79:2:1", @@ -45,8 +37,7 @@ "nativeSrc": "72:9:1", "nodeType": "YulCase", "src": "72:9:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "77:1:1", "nodeType": "YulLiteral", @@ -56,8 +47,7 @@ } }, { - "body": - { + "body": { "nativeSrc": "90:2:1", "nodeType": "YulBlock", "src": "90:2:1", @@ -69,8 +59,7 @@ "value": "default" } ], - "expression": - { + "expression": { "kind": "number", "nativeSrc": "70:1:1", "nodeType": "YulLiteral", @@ -99,15 +88,13 @@ "name": "g", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/switch_parseOnly.json b/test/libsolidity/ASTJSON/assembly/switch_parseOnly.json index 2412ea48d..dc16d43f9 100644 --- a/test/libsolidity/ASTJSON/assembly/switch_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/switch_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,30 +12,24 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "42:154:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "61:129:1", "nodeType": "YulBlock", "src": "61:129:1", - "statements": - [ + "statements": [ { "nativeSrc": "75:10:1", "nodeType": "YulVariableDeclaration", "src": "75:10:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "84:1:1", "nodeType": "YulLiteral", @@ -44,8 +37,7 @@ "type": "", "value": "0" }, - "variables": - [ + "variables": [ { "name": "v", "nativeSrc": "79:1:1", @@ -56,22 +48,18 @@ ] }, { - "cases": - [ + "cases": [ { - "body": - { + "body": { "nativeSrc": "139:10:1", "nodeType": "YulBlock", "src": "139:10:1", - "statements": - [ + "statements": [ { "nativeSrc": "141:6:1", "nodeType": "YulAssignment", "src": "141:6:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "146:1:1", "nodeType": "YulLiteral", @@ -79,8 +67,7 @@ "type": "", "value": "1" }, - "variableNames": - [ + "variableNames": [ { "name": "v", "nativeSrc": "141:1:1", @@ -94,8 +81,7 @@ "nativeSrc": "132:17:1", "nodeType": "YulCase", "src": "132:17:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "137:1:1", "nodeType": "YulLiteral", @@ -105,19 +91,16 @@ } }, { - "body": - { + "body": { "nativeSrc": "170:10:1", "nodeType": "YulBlock", "src": "170:10:1", - "statements": - [ + "statements": [ { "nativeSrc": "172:6:1", "nodeType": "YulAssignment", "src": "172:6:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "177:1:1", "nodeType": "YulLiteral", @@ -125,8 +108,7 @@ "type": "", "value": "2" }, - "variableNames": - [ + "variableNames": [ { "name": "v", "nativeSrc": "172:1:1", @@ -143,11 +125,9 @@ "value": "default" } ], - "expression": - { + "expression": { "arguments": [], - "functionName": - { + "functionName": { "name": "calldatasize", "nativeSrc": "105:12:1", "nodeType": "YulIdentifier", @@ -178,15 +158,13 @@ "name": "f", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/var_access.json b/test/libsolidity/ASTJSON/assembly/var_access.json index ae7845815..86bc76fa7 100644 --- a/test/libsolidity/ASTJSON/assembly/var_access.json +++ b/test/libsolidity/ASTJSON/assembly/var_access.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 9 ] }, "id": 10, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,30 +16,24 @@ "contractKind": "contract", "fullyImplemented": true, "id": 9, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 9 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 7, "nodeType": "Block", "src": "42:51:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -54,19 +45,16 @@ "src": "52:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 3, "name": "uint", "nodeType": "ElementaryTypeName", "src": "52:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -79,19 +67,16 @@ "src": "52:6:1" }, { - "AST": - { + "AST": { "nativeSrc": "77:10:1", "nodeType": "YulBlock", "src": "77:10:1", - "statements": - [ + "statements": [ { "nativeSrc": "79:6:1", "nodeType": "YulAssignment", "src": "79:6:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "84:1:1", "nodeType": "YulLiteral", @@ -99,8 +84,7 @@ "type": "", "value": "7" }, - "variableNames": - [ + "variableNames": [ { "name": "x", "nativeSrc": "79:1:1", @@ -112,8 +96,7 @@ ] }, "evmVersion": %EVMVERSION%, - "externalReferences": - [ + "externalReferences": [ { "declaration": 4, "isOffset": false, @@ -136,15 +119,13 @@ "name": "f", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/assembly/var_access.sol b/test/libsolidity/ASTJSON/assembly/var_access.sol index e4b7423fd..768f38c33 100644 --- a/test/libsolidity/ASTJSON/assembly/var_access.sol +++ b/test/libsolidity/ASTJSON/assembly/var_access.sol @@ -4,4 +4,5 @@ contract C { assembly { x := 7 } } } + // ---- diff --git a/test/libsolidity/ASTJSON/assembly/var_access_parseOnly.json b/test/libsolidity/ASTJSON/assembly/var_access_parseOnly.json index ca3fcf92c..129104bbc 100644 --- a/test/libsolidity/ASTJSON/assembly/var_access_parseOnly.json +++ b/test/libsolidity/ASTJSON/assembly/var_access_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 10, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,23 +12,18 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 7, "nodeType": "Block", "src": "42:51:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -41,8 +35,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 3, "name": "uint", "nodeType": "ElementaryTypeName", @@ -57,19 +50,16 @@ "src": "52:6:1" }, { - "AST": - { + "AST": { "nativeSrc": "77:10:1", "nodeType": "YulBlock", "src": "77:10:1", - "statements": - [ + "statements": [ { "nativeSrc": "79:6:1", "nodeType": "YulAssignment", "src": "79:6:1", - "value": - { + "value": { "kind": "number", "nativeSrc": "84:1:1", "nodeType": "YulLiteral", @@ -77,8 +67,7 @@ "type": "", "value": "7" }, - "variableNames": - [ + "variableNames": [ { "name": "x", "nativeSrc": "79:1:1", @@ -104,15 +93,13 @@ "name": "f", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/ast_internal_function_different_ids_export.json b/test/libsolidity/ASTJSON/ast_internal_function_different_ids_export.json index 07886a166..f94345ffc 100644 --- a/test/libsolidity/ASTJSON/ast_internal_function_different_ids_export.json +++ b/test/libsolidity/ASTJSON/ast_internal_function_different_ids_export.json @@ -1,28 +1,22 @@ [ { "absolutePath": "L", - "exportedSymbols": - { - "L": - [ + "exportedSymbols": { + "L": [ 78 ], - "free1": - [ + "free1": [ 65 ], - "free2": - [ + "free2": [ 69 ] }, "id": 79, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 64, "nodeType": "Block", "src": "17:2:1", @@ -35,15 +29,13 @@ "name": "free1", "nameLocation": "9:5:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 62, "nodeType": "ParameterList", "parameters": [], "src": "14:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 63, "nodeType": "ParameterList", "parameters": [], @@ -56,8 +48,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 68, "nodeType": "Block", "src": "37:2:1", @@ -70,15 +61,13 @@ "name": "free2", "nameLocation": "29:5:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 66, "nodeType": "ParameterList", "parameters": [], "src": "34:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 67, "nodeType": "ParameterList", "parameters": [], @@ -98,18 +87,15 @@ "contractKind": "library", "fullyImplemented": true, "id": 78, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 78 ], "name": "L", "nameLocation": "48:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 72, "nodeType": "Block", "src": "78:2:1", @@ -122,15 +108,13 @@ "name": "g", "nameLocation": "65:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 70, "nodeType": "ParameterList", "parameters": [], "src": "66:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 71, "nodeType": "ParameterList", "parameters": [], @@ -143,8 +127,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 76, "nodeType": "Block", "src": "107:2:1", @@ -157,15 +140,13 @@ "name": "h", "nameLocation": "94:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 74, "nodeType": "ParameterList", "parameters": [], "src": "95:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 75, "nodeType": "ParameterList", "parameters": [], @@ -188,33 +169,26 @@ }, { "absolutePath": "A", - "exportedSymbols": - { - "A": - [ + "exportedSymbols": { + "A": [ 22 ], - "B": - [ + "B": [ 37 ], - "L": - [ + "L": [ 78 ], - "free1": - [ + "free1": [ 65 ], - "free2": - [ + "free2": [ 69 ] }, "id": 38, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "absolutePath": "L", "file": "L", @@ -235,49 +209,39 @@ "contractKind": "contract", "fullyImplemented": true, "id": 22, - "internalFunctionIDs": - { + "internalFunctionIDs": { "69": 1, "73": 2, "77": 3 }, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 22 ], "name": "A", "nameLocation": "21:1:2", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 20, "nodeType": "Block", "src": "49:60:2", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { - "expression": - { + "expression": { "id": 4, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 78, "src": "60:1:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$78_$", "typeString": "type(library L)" } @@ -292,8 +256,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 73, "src": "60:3:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -307,8 +270,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "59:5:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -324,8 +286,7 @@ "nodeType": "FunctionCall", "src": "59:7:2", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -335,14 +296,11 @@ "src": "59:7:2" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { "id": 10, "name": "free2", @@ -350,8 +308,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 69, "src": "77:5:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -365,8 +322,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "76:7:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -382,8 +338,7 @@ "nodeType": "FunctionCall", "src": "76:9:2", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -393,25 +348,20 @@ "src": "76:9:2" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { - "expression": - { + "expression": { "id": 14, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 78, "src": "96:1:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$78_$", "typeString": "type(library L)" } @@ -426,8 +376,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 77, "src": "96:3:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -441,8 +390,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "95:5:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -458,8 +406,7 @@ "nodeType": "FunctionCall", "src": "95:7:2", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -478,15 +425,13 @@ "name": "f", "nameLocation": "38:1:2", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], "src": "39:2:2" }, - "returnParameters": - { + "returnParameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], @@ -512,48 +457,38 @@ "contractKind": "contract", "fullyImplemented": true, "id": 37, - "internalFunctionIDs": - { + "internalFunctionIDs": { "69": 1, "77": 2 }, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 37 ], "name": "B", "nameLocation": "121:1:2", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 35, "nodeType": "Block", "src": "149:43:2", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { - "expression": - { + "expression": { "id": 25, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 78, "src": "160:1:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$78_$", "typeString": "type(library L)" } @@ -568,8 +503,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 77, "src": "160:3:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -583,8 +517,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "159:5:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -600,8 +533,7 @@ "nodeType": "FunctionCall", "src": "159:7:2", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -611,14 +543,11 @@ "src": "159:7:2" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { "id": 31, "name": "free2", @@ -626,8 +555,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 69, "src": "177:5:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -641,8 +569,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "176:7:2", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -658,8 +585,7 @@ "nodeType": "FunctionCall", "src": "176:9:2", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -678,15 +604,13 @@ "name": "f", "nameLocation": "138:1:2", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 23, "nodeType": "ParameterList", "parameters": [], "src": "139:2:2" }, - "returnParameters": - { + "returnParameters": { "id": 24, "nodeType": "ParameterList", "parameters": [], @@ -709,29 +633,23 @@ }, { "absolutePath": "C", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 60 ], - "L": - [ + "L": [ 78 ], - "free1": - [ + "free1": [ 65 ], - "free2": - [ + "free2": [ 69 ] }, "id": 61, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "absolutePath": "L", "file": "L", @@ -752,49 +670,39 @@ "contractKind": "contract", "fullyImplemented": true, "id": 60, - "internalFunctionIDs": - { + "internalFunctionIDs": { "69": 1, "73": 2, "77": 3 }, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 60 ], "name": "C", "nameLocation": "21:1:3", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 58, "nodeType": "Block", "src": "49:60:3", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { - "expression": - { + "expression": { "id": 42, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 78, "src": "60:1:3", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$78_$", "typeString": "type(library L)" } @@ -809,8 +717,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 73, "src": "60:3:3", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -824,8 +731,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "59:5:3", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -841,8 +747,7 @@ "nodeType": "FunctionCall", "src": "59:7:3", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -852,14 +757,11 @@ "src": "59:7:3" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { "id": 48, "name": "free2", @@ -867,8 +769,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 69, "src": "77:5:3", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -882,8 +783,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "76:7:3", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -899,8 +799,7 @@ "nodeType": "FunctionCall", "src": "76:9:3", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -910,25 +809,20 @@ "src": "76:9:3" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { - "expression": - { + "expression": { "id": 52, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 78, "src": "96:1:3", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$78_$", "typeString": "type(library L)" } @@ -943,8 +837,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 77, "src": "96:3:3", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -958,8 +851,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "95:5:3", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -975,8 +867,7 @@ "nodeType": "FunctionCall", "src": "95:7:3", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -995,15 +886,13 @@ "name": "f", "nameLocation": "38:1:3", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 40, "nodeType": "ParameterList", "parameters": [], "src": "39:2:3" }, - "returnParameters": - { + "returnParameters": { "id": 41, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/ast_internal_function_different_ids_export.sol b/test/libsolidity/ASTJSON/ast_internal_function_different_ids_export.sol index 6e0b28c82..bf3222902 100644 --- a/test/libsolidity/ASTJSON/ast_internal_function_different_ids_export.sol +++ b/test/libsolidity/ASTJSON/ast_internal_function_different_ids_export.sol @@ -1,5 +1,4 @@ ==== Source: L ==== - function free1() {} function free2() {} library L { @@ -8,7 +7,6 @@ library L { } ==== Source: A ==== - import "L"; contract A { function f() public { @@ -25,7 +23,6 @@ contract B { } ==== Source: C ==== - import "L"; contract C { function f() public { diff --git a/test/libsolidity/ASTJSON/ast_internal_function_id_export.json b/test/libsolidity/ASTJSON/ast_internal_function_id_export.json index d452f2d99..cbbc962c0 100644 --- a/test/libsolidity/ASTJSON/ast_internal_function_id_export.json +++ b/test/libsolidity/ASTJSON/ast_internal_function_id_export.json @@ -1,39 +1,30 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 128 ], - "D": - [ + "D": [ 141 ], - "L": - [ + "L": [ 53 ], - "free1": - [ + "free1": [ 4 ], - "free2": - [ + "free2": [ 8 ], - "free3": - [ + "free3": [ 12 ] }, "id": 142, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "17:2:1", @@ -46,15 +37,13 @@ "name": "free1", "nameLocation": "9:5:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "14:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], @@ -67,8 +56,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 7, "nodeType": "Block", "src": "37:2:1", @@ -81,15 +69,13 @@ "name": "free2", "nameLocation": "29:5:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 5, "nodeType": "ParameterList", "parameters": [], "src": "34:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 6, "nodeType": "ParameterList", "parameters": [], @@ -102,8 +88,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 11, "nodeType": "Block", "src": "57:2:1", @@ -116,15 +101,13 @@ "name": "free3", "nameLocation": "49:5:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 9, "nodeType": "ParameterList", "parameters": [], "src": "54:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 10, "nodeType": "ParameterList", "parameters": [], @@ -144,25 +127,21 @@ "contractKind": "library", "fullyImplemented": true, "id": 53, - "internalFunctionIDs": - { + "internalFunctionIDs": { "20": 3, "24": 4, "4": 1, "8": 2 }, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 53 ], "name": "L", "nameLocation": "68:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 15, "nodeType": "Block", "src": "100:2:1", @@ -176,15 +155,13 @@ "name": "ext", "nameLocation": "85:3:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 13, "nodeType": "ParameterList", "parameters": [], "src": "88:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 14, "nodeType": "ParameterList", "parameters": [], @@ -197,8 +174,7 @@ "visibility": "external" }, { - "body": - { + "body": { "id": 19, "nodeType": "Block", "src": "132:2:1", @@ -211,15 +187,13 @@ "name": "inr1", "nameLocation": "116:4:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 17, "nodeType": "ParameterList", "parameters": [], "src": "120:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 18, "nodeType": "ParameterList", "parameters": [], @@ -232,8 +206,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 23, "nodeType": "Block", "src": "164:2:1", @@ -246,15 +219,13 @@ "name": "inr2", "nameLocation": "148:4:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 21, "nodeType": "ParameterList", "parameters": [], "src": "152:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 22, "nodeType": "ParameterList", "parameters": [], @@ -267,8 +238,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 27, "nodeType": "Block", "src": "196:2:1", @@ -281,15 +251,13 @@ "name": "inr3", "nameLocation": "180:4:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 25, "nodeType": "ParameterList", "parameters": [], "src": "184:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 26, "nodeType": "ParameterList", "parameters": [], @@ -302,24 +270,20 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 39, "nodeType": "Block", "src": "228:51:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "id": 31, "name": "free1", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 4, "src": "238:5:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -329,16 +293,14 @@ "src": "238:5:1" }, { - "expression": - { + "expression": { "id": 33, "name": "inr1", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 20, "src": "253:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -348,18 +310,15 @@ "src": "253:4:1" }, { - "expression": - { - "expression": - { + "expression": { + "expression": { "id": 35, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 53, "src": "267:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$53_$", "typeString": "type(library L)" } @@ -374,8 +333,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 16, "src": "267:5:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_delegatecall_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -394,15 +352,13 @@ "name": "access", "nameLocation": "212:6:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 29, "nodeType": "ParameterList", "parameters": [], "src": "218:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 30, "nodeType": "ParameterList", "parameters": [], @@ -415,22 +371,17 @@ "visibility": "public" }, { - "body": - { + "body": { "id": 51, "nodeType": "Block", "src": "313:44:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { "id": 43, "name": "free2", @@ -438,8 +389,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 8, "src": "324:5:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -453,8 +403,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "323:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -470,8 +419,7 @@ "nodeType": "FunctionCall", "src": "323:9:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -481,14 +429,11 @@ "src": "323:9:1" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { "id": 47, "name": "inr2", @@ -496,8 +441,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 24, "src": "343:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -511,8 +455,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "342:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -528,8 +471,7 @@ "nodeType": "FunctionCall", "src": "342:8:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -548,15 +490,13 @@ "name": "expression", "nameLocation": "293:10:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 41, "nodeType": "ParameterList", "parameters": [], "src": "303:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 42, "nodeType": "ParameterList", "parameters": [], @@ -582,8 +522,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 128, - "internalFunctionIDs": - { + "internalFunctionIDs": { "20": 3, "24": 4, "4": 1, @@ -591,18 +530,15 @@ "73": 6, "8": 2 }, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 128 ], "name": "C", "nameLocation": "369:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 56, "nodeType": "Block", "src": "402:2:1", @@ -616,15 +552,13 @@ "name": "ext1", "nameLocation": "386:4:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 54, "nodeType": "ParameterList", "parameters": [], "src": "390:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 55, "nodeType": "ParameterList", "parameters": [], @@ -637,8 +571,7 @@ "visibility": "external" }, { - "body": - { + "body": { "id": 60, "nodeType": "Block", "src": "434:2:1", @@ -652,15 +585,13 @@ "name": "ext2", "nameLocation": "418:4:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 58, "nodeType": "ParameterList", "parameters": [], "src": "422:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 59, "nodeType": "ParameterList", "parameters": [], @@ -673,8 +604,7 @@ "visibility": "external" }, { - "body": - { + "body": { "id": 64, "nodeType": "Block", "src": "466:2:1", @@ -688,15 +618,13 @@ "name": "ext3", "nameLocation": "450:4:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 62, "nodeType": "ParameterList", "parameters": [], "src": "454:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 63, "nodeType": "ParameterList", "parameters": [], @@ -709,8 +637,7 @@ "visibility": "external" }, { - "body": - { + "body": { "id": 68, "nodeType": "Block", "src": "498:2:1", @@ -723,15 +650,13 @@ "name": "inr1", "nameLocation": "482:4:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 66, "nodeType": "ParameterList", "parameters": [], "src": "486:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 67, "nodeType": "ParameterList", "parameters": [], @@ -744,8 +669,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 72, "nodeType": "Block", "src": "530:2:1", @@ -758,15 +682,13 @@ "name": "inr2", "nameLocation": "514:4:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 70, "nodeType": "ParameterList", "parameters": [], "src": "518:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 71, "nodeType": "ParameterList", "parameters": [], @@ -779,8 +701,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 76, "nodeType": "Block", "src": "562:2:1", @@ -793,15 +714,13 @@ "name": "inr3", "nameLocation": "546:4:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 74, "nodeType": "ParameterList", "parameters": [], "src": "550:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 75, "nodeType": "ParameterList", "parameters": [], @@ -814,26 +733,21 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 96, "nodeType": "Block", "src": "594:86:1", - "statements": - [ + "statements": [ { - "expression": - { - "expression": - { + "expression": { + "expression": { "id": 80, "name": "this", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": -28, "src": "604:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_contract$_C_$128", "typeString": "contract C" } @@ -848,8 +762,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 57, "src": "604:9:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_external_nonpayable$__$returns$__$", "typeString": "function () external" } @@ -859,16 +772,14 @@ "src": "604:9:1" }, { - "expression": - { + "expression": { "id": 84, "name": "inr1", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 69, "src": "623:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -878,16 +789,14 @@ "src": "623:4:1" }, { - "expression": - { + "expression": { "id": 86, "name": "free1", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 4, "src": "637:5:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -897,18 +806,15 @@ "src": "637:5:1" }, { - "expression": - { - "expression": - { + "expression": { + "expression": { "id": 88, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 53, "src": "652:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$53_$", "typeString": "type(library L)" } @@ -923,8 +829,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 20, "src": "652:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -934,18 +839,15 @@ "src": "652:6:1" }, { - "expression": - { - "expression": - { + "expression": { + "expression": { "id": 92, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 53, "src": "668:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$53_$", "typeString": "type(library L)" } @@ -960,8 +862,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 16, "src": "668:5:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_delegatecall_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -980,15 +881,13 @@ "name": "access", "nameLocation": "578:6:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 78, "nodeType": "ParameterList", "parameters": [], "src": "584:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 79, "nodeType": "ParameterList", "parameters": [], @@ -1001,33 +900,26 @@ "visibility": "public" }, { - "body": - { + "body": { "id": 126, "nodeType": "Block", "src": "714:106:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { - "expression": - { + "expression": { "id": 100, "name": "this", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": -28, "src": "725:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_contract$_C_$128", "typeString": "contract C" } @@ -1042,8 +934,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 61, "src": "725:9:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_external_nonpayable$__$returns$__$", "typeString": "function () external" } @@ -1057,8 +948,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "724:11:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_external_nonpayable$__$returns$__$", "typeString": "function () external" } @@ -1074,8 +964,7 @@ "nodeType": "FunctionCall", "src": "724:13:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -1085,14 +974,11 @@ "src": "724:13:1" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { "id": 106, "name": "inr2", @@ -1100,8 +986,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 73, "src": "748:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -1115,8 +1000,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "747:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -1132,8 +1016,7 @@ "nodeType": "FunctionCall", "src": "747:8:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -1143,14 +1026,11 @@ "src": "747:8:1" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { "id": 110, "name": "free2", @@ -1158,8 +1038,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 8, "src": "766:5:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -1173,8 +1052,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "765:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -1190,8 +1068,7 @@ "nodeType": "FunctionCall", "src": "765:9:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -1201,25 +1078,20 @@ "src": "765:9:1" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { - "expression": - { + "expression": { "id": 114, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 53, "src": "785:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$53_$", "typeString": "type(library L)" } @@ -1234,8 +1106,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 24, "src": "785:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -1249,8 +1120,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "784:8:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -1266,8 +1136,7 @@ "nodeType": "FunctionCall", "src": "784:10:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -1277,25 +1146,20 @@ "src": "784:10:1" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "components": - [ + "components": [ { - "expression": - { + "expression": { "id": 120, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 53, "src": "805:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$53_$", "typeString": "type(library L)" } @@ -1310,8 +1174,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 16, "src": "805:5:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_delegatecall_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -1325,8 +1188,7 @@ "lValueRequested": false, "nodeType": "TupleExpression", "src": "804:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_delegatecall_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -1342,8 +1204,7 @@ "nodeType": "FunctionCall", "src": "804:9:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -1362,15 +1223,13 @@ "name": "expression", "nameLocation": "694:10:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 98, "nodeType": "ParameterList", "parameters": [], "src": "704:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 99, "nodeType": "ParameterList", "parameters": [], @@ -1390,15 +1249,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 129, "name": "C", - "nameLocations": - [ + "nameLocations": [ "837:1:1" ], "nodeType": "IdentifierPath", @@ -1415,8 +1271,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 141, - "internalFunctionIDs": - { + "internalFunctionIDs": { "20": 3, "24": 4, "4": 1, @@ -1424,30 +1279,24 @@ "73": 6, "8": 2 }, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 141, 128 ], "name": "D", "nameLocation": "832:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 139, "nodeType": "Block", "src": "859:47:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], "id": 133, "name": "access", @@ -1455,8 +1304,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 97, "src": "869:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -1472,8 +1320,7 @@ "nodeType": "FunctionCall", "src": "869:8:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -1483,11 +1330,9 @@ "src": "869:8:1" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], "id": 136, "name": "expression", @@ -1495,8 +1340,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 127, "src": "887:10:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -1512,8 +1356,7 @@ "nodeType": "FunctionCall", "src": "887:12:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -1531,15 +1374,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 131, "nodeType": "ParameterList", "parameters": [], "src": "856:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 132, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/base_constructor_call.json b/test/libsolidity/ASTJSON/base_constructor_call.json index 2c3c68c40..408cb9477 100644 --- a/test/libsolidity/ASTJSON/base_constructor_call.json +++ b/test/libsolidity/ASTJSON/base_constructor_call.json @@ -1,20 +1,16 @@ { "absolutePath": "a", - "exportedSymbols": - { - "A": - [ + "exportedSymbols": { + "A": [ 7 ], - "C": - [ + "C": [ 17 ] }, "id": 18, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -23,18 +19,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 7, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 7 ], "name": "A", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 5, "nodeType": "Block", "src": "31:2:1", @@ -47,12 +40,10 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 2, @@ -64,19 +55,16 @@ "src": "25:4:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", "src": "25:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -86,8 +74,7 @@ ], "src": "24:6:1" }, - "returnParameters": - { + "returnParameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], @@ -107,15 +94,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 8, "name": "A", - "nameLocations": - [ + "nameLocations": [ "50:1:1" ], "nodeType": "IdentifierPath", @@ -132,19 +116,16 @@ "contractKind": "contract", "fullyImplemented": true, "id": 17, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 17, 7 ], "name": "C", "nameLocation": "45:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 15, "nodeType": "Block", "src": "73:2:1", @@ -153,11 +134,9 @@ "id": 16, "implemented": true, "kind": "constructor", - "modifiers": - [ + "modifiers": [ { - "arguments": - [ + "arguments": [ { "hexValue": "32", "id": 12, @@ -168,8 +147,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "70:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_2_by_1", "typeString": "int_const 2" }, @@ -178,12 +156,10 @@ ], "id": 13, "kind": "baseConstructorSpecifier", - "modifierName": - { + "modifierName": { "id": 11, "name": "A", - "nameLocations": - [ + "nameLocations": [ "68:1:1" ], "nodeType": "IdentifierPath", @@ -197,15 +173,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 10, "nodeType": "ParameterList", "parameters": [], "src": "65:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 14, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/base_constructor_call_parseOnly.json b/test/libsolidity/ASTJSON/base_constructor_call_parseOnly.json index 730a05178..07a57a9db 100644 --- a/test/libsolidity/ASTJSON/base_constructor_call_parseOnly.json +++ b/test/libsolidity/ASTJSON/base_constructor_call_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 18, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,11 +12,9 @@ "name": "A", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 5, "nodeType": "Block", "src": "31:2:1", @@ -30,12 +27,10 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 2, @@ -47,8 +42,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", @@ -60,8 +54,7 @@ ], "src": "24:6:1" }, - "returnParameters": - { + "returnParameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], @@ -78,15 +71,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 8, "name": "A", - "nameLocations": - [ + "nameLocations": [ "50:1:1" ], "nodeType": "IdentifierPath", @@ -103,11 +93,9 @@ "name": "C", "nameLocation": "45:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 15, "nodeType": "Block", "src": "73:2:1", @@ -116,11 +104,9 @@ "id": 16, "implemented": true, "kind": "constructor", - "modifiers": - [ + "modifiers": [ { - "arguments": - [ + "arguments": [ { "hexValue": "32", "id": 12, @@ -132,12 +118,10 @@ } ], "id": 13, - "modifierName": - { + "modifierName": { "id": 11, "name": "A", - "nameLocations": - [ + "nameLocations": [ "68:1:1" ], "nodeType": "IdentifierPath", @@ -150,15 +134,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 10, "nodeType": "ParameterList", "parameters": [], "src": "65:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 14, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/constructor.json b/test/libsolidity/ASTJSON/constructor.json index 53e622b5d..2c18d73f2 100644 --- a/test/libsolidity/ASTJSON/constructor.json +++ b/test/libsolidity/ASTJSON/constructor.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ] }, "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,18 +16,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "28:4:1", @@ -43,15 +37,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "25:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/constructor.sol b/test/libsolidity/ASTJSON/constructor.sol index b48aa1be3..b2b1c6460 100644 --- a/test/libsolidity/ASTJSON/constructor.sol +++ b/test/libsolidity/ASTJSON/constructor.sol @@ -2,4 +2,5 @@ contract C { constructor() { } } + // ---- diff --git a/test/libsolidity/ASTJSON/constructor_parseOnly.json b/test/libsolidity/ASTJSON/constructor_parseOnly.json index 9b1d4cfc4..4645d6d3b 100644 --- a/test/libsolidity/ASTJSON/constructor_parseOnly.json +++ b/test/libsolidity/ASTJSON/constructor_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,11 +12,9 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "28:4:1", @@ -30,15 +27,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "25:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/contract_dep_order.json b/test/libsolidity/ASTJSON/contract_dep_order.json index 67eff600b..396957617 100644 --- a/test/libsolidity/ASTJSON/contract_dep_order.json +++ b/test/libsolidity/ASTJSON/contract_dep_order.json @@ -1,32 +1,25 @@ { "absolutePath": "a", - "exportedSymbols": - { - "A": - [ + "exportedSymbols": { + "A": [ 1 ], - "B": - [ + "B": [ 4 ], - "C": - [ + "C": [ 7 ], - "D": - [ + "D": [ 10 ], - "E": - [ + "E": [ 13 ] }, "id": 14, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -35,8 +28,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 1, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 1 ], "name": "A", @@ -50,15 +42,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 2, "name": "A", - "nameLocations": - [ + "nameLocations": [ "29:1:1" ], "nodeType": "IdentifierPath", @@ -75,8 +64,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 4, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 4, 1 ], @@ -91,15 +79,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 5, "name": "B", - "nameLocations": - [ + "nameLocations": [ "49:1:1" ], "nodeType": "IdentifierPath", @@ -116,8 +101,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 7, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 7, 4, 1 @@ -133,15 +117,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 8, "name": "C", - "nameLocations": - [ + "nameLocations": [ "69:1:1" ], "nodeType": "IdentifierPath", @@ -158,8 +139,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 10, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 10, 7, 4, @@ -176,15 +156,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 11, "name": "D", - "nameLocations": - [ + "nameLocations": [ "89:1:1" ], "nodeType": "IdentifierPath", @@ -201,8 +178,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 13, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 13, 10, 7, diff --git a/test/libsolidity/ASTJSON/contract_dep_order_parseOnly.json b/test/libsolidity/ASTJSON/contract_dep_order_parseOnly.json index ba8c377cf..022d93b9e 100644 --- a/test/libsolidity/ASTJSON/contract_dep_order_parseOnly.json +++ b/test/libsolidity/ASTJSON/contract_dep_order_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 14, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -20,15 +19,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 2, "name": "A", - "nameLocations": - [ + "nameLocations": [ "29:1:1" ], "nodeType": "IdentifierPath", @@ -52,15 +48,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 5, "name": "B", - "nameLocations": - [ + "nameLocations": [ "49:1:1" ], "nodeType": "IdentifierPath", @@ -84,15 +77,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 8, "name": "C", - "nameLocations": - [ + "nameLocations": [ "69:1:1" ], "nodeType": "IdentifierPath", @@ -116,15 +106,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 11, "name": "D", - "nameLocations": - [ + "nameLocations": [ "89:1:1" ], "nodeType": "IdentifierPath", diff --git a/test/libsolidity/ASTJSON/documentation.json b/test/libsolidity/ASTJSON/documentation.json index 43224bc64..9558eb3fc 100644 --- a/test/libsolidity/ASTJSON/documentation.json +++ b/test/libsolidity/ASTJSON/documentation.json @@ -1,25 +1,21 @@ [ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 2 ] }, "id": 3, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], "canonicalName": "C", "contractDependencies": [], "contractKind": "contract", - "documentation": - { + "documentation": { "id": 1, "nodeType": "StructuredDocumentation", "src": "0:27:1", @@ -27,8 +23,7 @@ }, "fullyImplemented": true, "id": 2, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 2 ], "name": "C", @@ -45,25 +40,21 @@ }, { "absolutePath": "b", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ] }, "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], "canonicalName": "C", "contractDependencies": [], "contractKind": "contract", - "documentation": - { + "documentation": { "id": 4, "nodeType": "StructuredDocumentation", "src": "0:61:2", @@ -71,8 +62,7 @@ }, "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "C", @@ -89,17 +79,14 @@ }, { "absolutePath": "c", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 23 ] }, "id": 24, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -108,19 +95,16 @@ "contractKind": "contract", "fullyImplemented": true, "id": 23, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 23 ], "name": "C", "nameLocation": "9:1:3", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, - "documentation": - { + "documentation": { "id": 7, "nodeType": "StructuredDocumentation", "src": "15:32:3", @@ -136,19 +120,16 @@ "src": "48:17:3", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 8, "name": "uint", "nodeType": "ElementaryTypeName", "src": "48:4:3", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -157,8 +138,7 @@ }, { "anonymous": false, - "documentation": - { + "documentation": { "id": 10, "nodeType": "StructuredDocumentation", "src": "69:26:3", @@ -169,8 +149,7 @@ "name": "Evt", "nameLocation": "102:3:3", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 11, "nodeType": "ParameterList", "parameters": [], @@ -179,13 +158,11 @@ "src": "96:12:3" }, { - "body": - { + "body": { "id": 16, "nodeType": "Block", "src": "153:6:3", - "statements": - [ + "statements": [ { "id": 15, "nodeType": "PlaceholderStatement", @@ -193,8 +170,7 @@ } ] }, - "documentation": - { + "documentation": { "id": 13, "nodeType": "StructuredDocumentation", "src": "111:26:3", @@ -204,8 +180,7 @@ "name": "mod", "nameLocation": "147:3:3", "nodeType": "ModifierDefinition", - "parameters": - { + "parameters": { "id": 14, "nodeType": "ParameterList", "parameters": [], @@ -216,15 +191,13 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 21, "nodeType": "Block", "src": "209:2:3", "statements": [] }, - "documentation": - { + "documentation": { "id": 18, "nodeType": "StructuredDocumentation", "src": "162:25:3", @@ -238,15 +211,13 @@ "name": "fn", "nameLocation": "197:2:3", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 19, "nodeType": "ParameterList", "parameters": [], "src": "199:2:3" }, - "returnParameters": - { + "returnParameters": { "id": 20, "nodeType": "ParameterList", "parameters": [], @@ -262,8 +233,7 @@ "scope": 24, "src": "0:213:3", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 12 ] } diff --git a/test/libsolidity/ASTJSON/documentation.sol b/test/libsolidity/ASTJSON/documentation.sol index 6bbf4042a..471b7a476 100644 --- a/test/libsolidity/ASTJSON/documentation.sol +++ b/test/libsolidity/ASTJSON/documentation.sol @@ -1,19 +1,17 @@ ==== Source: a ==== - /**This contract is empty*/ contract C {} ==== Source: b ==== - /**This contract is empty and has a line-breaking comment.*/ contract C {} ==== Source: c ==== - contract C { /** Some comment on state var.*/ uint public state; /** Some comment on Evt.*/ event Evt(); /** Some comment on mod.*/ modifier mod() { _; } /** Some comment on fn.*/ function fn() public {} } + // ---- diff --git a/test/libsolidity/ASTJSON/documentation_local_variable.json b/test/libsolidity/ASTJSON/documentation_local_variable.json index 62d76e782..1e22c9161 100644 --- a/test/libsolidity/ASTJSON/documentation_local_variable.json +++ b/test/libsolidity/ASTJSON/documentation_local_variable.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 41 ] }, "id": 42, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,30 +16,24 @@ "contractKind": "contract", "fullyImplemented": true, "id": 41, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 41 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 26, "nodeType": "Block", "src": "42:330:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 5 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 5, @@ -54,19 +45,16 @@ "src": "109:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 4, "name": "uint", "nodeType": "ElementaryTypeName", "src": "109:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -76,8 +64,7 @@ ], "documentation": "Documentation for x; will appear in ast json", "id": 7, - "initialValue": - { + "initialValue": { "hexValue": "31", "id": 6, "isConstant": false, @@ -87,8 +74,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "118:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_1_by_1", "typeString": "int_const 1" }, @@ -98,20 +84,16 @@ "src": "109:10:1" }, { - "body": - { + "body": { "id": 24, "nodeType": "Block", "src": "270:96:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 21 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 21, @@ -123,19 +105,16 @@ "src": "345:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 20, "name": "uint", "nodeType": "ElementaryTypeName", "src": "345:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -145,8 +124,7 @@ ], "documentation": "documentation for j; will appear in ast json", "id": 23, - "initialValue": - { + "initialValue": { "hexValue": "30", "id": 22, "isConstant": false, @@ -156,8 +134,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "354:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_0_by_1", "typeString": "int_const 0" }, @@ -168,10 +145,8 @@ } ] }, - "condition": - { - "commonType": - { + "condition": { + "commonType": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, @@ -180,24 +155,21 @@ "isLValue": false, "isPure": false, "lValueRequested": false, - "leftExpression": - { + "leftExpression": { "id": 13, "name": "i", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 10, "src": "236:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "BinaryOperation", "operator": "<", - "rightExpression": - { + "rightExpression": { "hexValue": "3130", "id": 14, "isConstant": false, @@ -207,29 +179,24 @@ "lValueRequested": false, "nodeType": "Literal", "src": "240:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_10_by_1", "typeString": "int_const 10" }, "value": "10" }, "src": "236:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } }, "id": 25, - "initializationExpression": - { - "assignments": - [ + "initializationExpression": { + "assignments": [ 10 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 10, @@ -241,19 +208,16 @@ "src": "212:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 9, "name": "uint", "nodeType": "ElementaryTypeName", "src": "212:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -262,8 +226,7 @@ } ], "id": 12, - "initialValue": - { + "initialValue": { "hexValue": "30", "id": 11, "isConstant": false, @@ -273,8 +236,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "221:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_0_by_1", "typeString": "int_const 0" }, @@ -284,10 +246,8 @@ "src": "212:10:1" }, "isSimpleCounterLoop": true, - "loopExpression": - { - "expression": - { + "loopExpression": { + "expression": { "id": 17, "isConstant": false, "isLValue": false, @@ -297,22 +257,19 @@ "operator": "++", "prefix": true, "src": "256:3:1", - "subExpression": - { + "subExpression": { "id": 16, "name": "i", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 10, "src": "258:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -334,15 +291,13 @@ "name": "f", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], @@ -355,8 +310,7 @@ "visibility": "public" }, { - "body": - { + "body": { "id": 39, "nodeType": "Block", "src": "662:2:1", @@ -370,12 +324,10 @@ "name": "g", "nameLocation": "386:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 37, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 30, @@ -387,19 +339,16 @@ "src": "463:11:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 29, "name": "uint", "nodeType": "ElementaryTypeName", "src": "463:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -417,19 +366,16 @@ "src": "550:11:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 32, "name": "uint", "nodeType": "ElementaryTypeName", "src": "550:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -447,19 +393,16 @@ "src": "637:11:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 35, "name": "uint", "nodeType": "ElementaryTypeName", "src": "637:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -469,8 +412,7 @@ ], "src": "387:267:1" }, - "returnParameters": - { + "returnParameters": { "id": 38, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/documentation_local_variable_parseOnly.json b/test/libsolidity/ASTJSON/documentation_local_variable_parseOnly.json index 872583839..97939eaa1 100644 --- a/test/libsolidity/ASTJSON/documentation_local_variable_parseOnly.json +++ b/test/libsolidity/ASTJSON/documentation_local_variable_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 42, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,23 +12,18 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 26, "nodeType": "Block", "src": "42:330:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 5 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 5, @@ -41,8 +35,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 4, "name": "uint", "nodeType": "ElementaryTypeName", @@ -54,8 +47,7 @@ ], "documentation": "Documentation for x; will appear in ast json", "id": 7, - "initialValue": - { + "initialValue": { "hexValue": "31", "id": 6, "kind": "number", @@ -68,20 +60,16 @@ "src": "109:10:1" }, { - "body": - { + "body": { "id": 24, "nodeType": "Block", "src": "270:96:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 21 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 21, @@ -93,8 +81,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 20, "name": "uint", "nodeType": "ElementaryTypeName", @@ -106,8 +93,7 @@ ], "documentation": "documentation for j; will appear in ast json", "id": 23, - "initialValue": - { + "initialValue": { "hexValue": "30", "id": 22, "kind": "number", @@ -121,12 +107,10 @@ } ] }, - "condition": - { + "condition": { "commonType": {}, "id": 15, - "leftExpression": - { + "leftExpression": { "id": 13, "name": "i", "nodeType": "Identifier", @@ -136,8 +120,7 @@ }, "nodeType": "BinaryOperation", "operator": "<", - "rightExpression": - { + "rightExpression": { "hexValue": "3130", "id": 14, "kind": "number", @@ -150,14 +133,11 @@ "typeDescriptions": {} }, "id": 25, - "initializationExpression": - { - "assignments": - [ + "initializationExpression": { + "assignments": [ 10 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 10, @@ -169,8 +149,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 9, "name": "uint", "nodeType": "ElementaryTypeName", @@ -181,8 +160,7 @@ } ], "id": 12, - "initialValue": - { + "initialValue": { "hexValue": "30", "id": 11, "kind": "number", @@ -194,17 +172,14 @@ "nodeType": "VariableDeclarationStatement", "src": "212:10:1" }, - "loopExpression": - { - "expression": - { + "loopExpression": { + "expression": { "id": 17, "nodeType": "UnaryOperation", "operator": "++", "prefix": true, "src": "256:3:1", - "subExpression": - { + "subExpression": { "id": 16, "name": "i", "nodeType": "Identifier", @@ -230,15 +205,13 @@ "name": "f", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], @@ -250,8 +223,7 @@ "visibility": "public" }, { - "body": - { + "body": { "id": 39, "nodeType": "Block", "src": "662:2:1", @@ -264,12 +236,10 @@ "name": "g", "nameLocation": "386:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 37, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 30, @@ -281,8 +251,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 29, "name": "uint", "nodeType": "ElementaryTypeName", @@ -302,8 +271,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 32, "name": "uint", "nodeType": "ElementaryTypeName", @@ -323,8 +291,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 35, "name": "uint", "nodeType": "ElementaryTypeName", @@ -336,8 +303,7 @@ ], "src": "387:267:1" }, - "returnParameters": - { + "returnParameters": { "id": 38, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/documentation_on_statements.json b/test/libsolidity/ASTJSON/documentation_on_statements.json index cc4a1ef3c..350d78686 100644 --- a/test/libsolidity/ASTJSON/documentation_on_statements.json +++ b/test/libsolidity/ASTJSON/documentation_on_statements.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 27 ] }, "id": 28, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,15 +16,13 @@ "contractKind": "contract", "fullyImplemented": true, "id": 27, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 27 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 2, @@ -39,19 +34,16 @@ "src": "45:6:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", "src": "45:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -59,47 +51,39 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 25, "nodeType": "Block", "src": "99:229:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "id": 21, "nodeType": "Block", "src": "156:66:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "id": 19, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, - "leftHandSide": - { + "leftHandSide": { "id": 17, "name": "x", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 5, "src": "205:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "Assignment", "operator": "*=", - "rightHandSide": - { + "rightHandSide": { "hexValue": "32", "id": 18, "isConstant": false, @@ -109,16 +93,14 @@ "lValueRequested": false, "nodeType": "Literal", "src": "210:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_2_by_1", "typeString": "int_const 2" }, "value": "2" }, "src": "205:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -129,10 +111,8 @@ } ] }, - "condition": - { - "commonType": - { + "condition": { + "commonType": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, @@ -141,24 +121,21 @@ "isLValue": false, "isPure": false, "lValueRequested": false, - "leftExpression": - { + "leftExpression": { "id": 11, "name": "i", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 8, "src": "143:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "BinaryOperation", "operator": "<", - "rightExpression": - { + "rightExpression": { "hexValue": "3230", "id": 12, "isConstant": false, @@ -168,29 +145,24 @@ "lValueRequested": false, "nodeType": "Literal", "src": "147:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_20_by_1", "typeString": "int_const 20" }, "value": "20" }, "src": "143:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } }, "id": 22, - "initializationExpression": - { - "assignments": - [ + "initializationExpression": { + "assignments": [ 8 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 8, @@ -202,19 +174,16 @@ "src": "131:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 7, "name": "uint", "nodeType": "ElementaryTypeName", "src": "131:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -223,8 +192,7 @@ } ], "id": 10, - "initialValue": - { + "initialValue": { "hexValue": "30", "id": 9, "isConstant": false, @@ -234,8 +202,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "140:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_0_by_1", "typeString": "int_const 0" }, @@ -245,10 +212,8 @@ "src": "131:10:1" }, "isSimpleCounterLoop": true, - "loopExpression": - { - "expression": - { + "loopExpression": { + "expression": { "id": 15, "isConstant": false, "isLValue": false, @@ -258,22 +223,19 @@ "operator": "++", "prefix": false, "src": "151:3:1", - "subExpression": - { + "subExpression": { "id": 14, "name": "i", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 8, "src": "151:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -286,16 +248,14 @@ "src": "126:96:1" }, { - "expression": - { + "expression": { "id": 23, "name": "x", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 5, "src": "320:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -315,19 +275,16 @@ "name": "f", "nameLocation": "66:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], "src": "67:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 6, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 5, @@ -339,19 +296,16 @@ "src": "91:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 4, "name": "uint", "nodeType": "ElementaryTypeName", "src": "91:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } diff --git a/test/libsolidity/ASTJSON/documentation_on_statements_parseOnly.json b/test/libsolidity/ASTJSON/documentation_on_statements_parseOnly.json index 3872027cb..e266c2e5b 100644 --- a/test/libsolidity/ASTJSON/documentation_on_statements_parseOnly.json +++ b/test/libsolidity/ASTJSON/documentation_on_statements_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 28, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,8 +12,7 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 2, @@ -26,8 +24,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", @@ -37,27 +34,21 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 25, "nodeType": "Block", "src": "99:229:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "id": 21, "nodeType": "Block", "src": "156:66:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "id": 19, - "leftHandSide": - { + "leftHandSide": { "id": 17, "name": "x", "nodeType": "Identifier", @@ -67,8 +58,7 @@ }, "nodeType": "Assignment", "operator": "*=", - "rightHandSide": - { + "rightHandSide": { "hexValue": "32", "id": 18, "kind": "number", @@ -86,12 +76,10 @@ } ] }, - "condition": - { + "condition": { "commonType": {}, "id": 13, - "leftExpression": - { + "leftExpression": { "id": 11, "name": "i", "nodeType": "Identifier", @@ -101,8 +89,7 @@ }, "nodeType": "BinaryOperation", "operator": "<", - "rightExpression": - { + "rightExpression": { "hexValue": "3230", "id": 12, "kind": "number", @@ -115,14 +102,11 @@ "typeDescriptions": {} }, "id": 22, - "initializationExpression": - { - "assignments": - [ + "initializationExpression": { + "assignments": [ 8 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 8, @@ -134,8 +118,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 7, "name": "uint", "nodeType": "ElementaryTypeName", @@ -146,8 +129,7 @@ } ], "id": 10, - "initialValue": - { + "initialValue": { "hexValue": "30", "id": 9, "kind": "number", @@ -159,17 +141,14 @@ "nodeType": "VariableDeclarationStatement", "src": "131:10:1" }, - "loopExpression": - { - "expression": - { + "loopExpression": { + "expression": { "id": 15, "nodeType": "UnaryOperation", "operator": "++", "prefix": false, "src": "151:3:1", - "subExpression": - { + "subExpression": { "id": 14, "name": "i", "nodeType": "Identifier", @@ -187,8 +166,7 @@ "src": "126:96:1" }, { - "expression": - { + "expression": { "id": 23, "name": "x", "nodeType": "Identifier", @@ -209,19 +187,16 @@ "name": "f", "nameLocation": "66:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], "src": "67:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 6, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 5, @@ -233,8 +208,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 4, "name": "uint", "nodeType": "ElementaryTypeName", diff --git a/test/libsolidity/ASTJSON/documentation_parseOnly.json b/test/libsolidity/ASTJSON/documentation_parseOnly.json index 7f446279b..c6215818d 100644 --- a/test/libsolidity/ASTJSON/documentation_parseOnly.json +++ b/test/libsolidity/ASTJSON/documentation_parseOnly.json @@ -3,15 +3,13 @@ "absolutePath": "a", "id": 3, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], "contractDependencies": [], "contractKind": "contract", - "documentation": - { + "documentation": { "id": 1, "nodeType": "StructuredDocumentation", "src": "0:27:1", @@ -33,15 +31,13 @@ "absolutePath": "b", "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], "contractDependencies": [], "contractKind": "contract", - "documentation": - { + "documentation": { "id": 4, "nodeType": "StructuredDocumentation", "src": "0:61:2", @@ -63,8 +59,7 @@ "absolutePath": "c", "id": 24, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -74,8 +69,7 @@ "name": "C", "nameLocation": "9:1:3", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 9, @@ -87,8 +81,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 8, "name": "uint", "nodeType": "ElementaryTypeName", @@ -99,8 +92,7 @@ }, { "anonymous": false, - "documentation": - { + "documentation": { "id": 10, "nodeType": "StructuredDocumentation", "src": "69:26:3", @@ -110,8 +102,7 @@ "name": "Evt", "nameLocation": "102:3:3", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 11, "nodeType": "ParameterList", "parameters": [], @@ -120,13 +111,11 @@ "src": "96:12:3" }, { - "body": - { + "body": { "id": 16, "nodeType": "Block", "src": "153:6:3", - "statements": - [ + "statements": [ { "id": 15, "nodeType": "PlaceholderStatement", @@ -134,8 +123,7 @@ } ] }, - "documentation": - { + "documentation": { "id": 13, "nodeType": "StructuredDocumentation", "src": "111:26:3", @@ -145,8 +133,7 @@ "name": "mod", "nameLocation": "147:3:3", "nodeType": "ModifierDefinition", - "parameters": - { + "parameters": { "id": 14, "nodeType": "ParameterList", "parameters": [], @@ -157,15 +144,13 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 21, "nodeType": "Block", "src": "209:2:3", "statements": [] }, - "documentation": - { + "documentation": { "id": 18, "nodeType": "StructuredDocumentation", "src": "162:25:3", @@ -178,15 +163,13 @@ "name": "fn", "nameLocation": "197:2:3", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 19, "nodeType": "ParameterList", "parameters": [], "src": "199:2:3" }, - "returnParameters": - { + "returnParameters": { "id": 20, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/documentation_triple.json b/test/libsolidity/ASTJSON/documentation_triple.json index cd44bd4eb..bc3c3d887 100644 --- a/test/libsolidity/ASTJSON/documentation_triple.json +++ b/test/libsolidity/ASTJSON/documentation_triple.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 28 ] }, "id": 29, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,19 +16,16 @@ "contractKind": "contract", "fullyImplemented": true, "id": 28, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 28 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, - "documentation": - { + "documentation": { "id": 1, "nodeType": "StructuredDocumentation", "src": "17:8:1", @@ -46,19 +40,16 @@ "src": "30:6:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 2, "name": "uint", "nodeType": "ElementaryTypeName", "src": "30:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -66,48 +57,40 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 26, "nodeType": "Block", "src": "84:181:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "id": 22, "nodeType": "Block", "src": "142:75:1", - "statements": - [ + "statements": [ { "documentation": "tee\n s \"t\" 3", - "expression": - { + "expression": { "id": 20, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, - "leftHandSide": - { + "leftHandSide": { "id": 18, "name": "x", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 6, "src": "200:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "Assignment", "operator": "*=", - "rightHandSide": - { + "rightHandSide": { "hexValue": "32", "id": 19, "isConstant": false, @@ -117,16 +100,14 @@ "lValueRequested": false, "nodeType": "Literal", "src": "205:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_2_by_1", "typeString": "int_const 2" }, "value": "2" }, "src": "200:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -137,10 +118,8 @@ } ] }, - "condition": - { - "commonType": - { + "condition": { + "commonType": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, @@ -149,24 +128,21 @@ "isLValue": false, "isPure": false, "lValueRequested": false, - "leftExpression": - { + "leftExpression": { "id": 12, "name": "i", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 9, "src": "129:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "BinaryOperation", "operator": "<", - "rightExpression": - { + "rightExpression": { "hexValue": "3230", "id": 13, "isConstant": false, @@ -176,30 +152,25 @@ "lValueRequested": false, "nodeType": "Literal", "src": "133:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_20_by_1", "typeString": "int_const 20" }, "value": "20" }, "src": "129:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } }, "documentation": "test2", "id": 23, - "initializationExpression": - { - "assignments": - [ + "initializationExpression": { + "assignments": [ 9 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 9, @@ -211,19 +182,16 @@ "src": "117:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 8, "name": "uint", "nodeType": "ElementaryTypeName", "src": "117:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -232,8 +200,7 @@ } ], "id": 11, - "initialValue": - { + "initialValue": { "hexValue": "30", "id": 10, "isConstant": false, @@ -243,8 +210,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "126:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_0_by_1", "typeString": "int_const 0" }, @@ -254,10 +220,8 @@ "src": "117:10:1" }, "isSimpleCounterLoop": true, - "loopExpression": - { - "expression": - { + "loopExpression": { + "expression": { "id": 16, "isConstant": false, "isLValue": false, @@ -267,22 +231,19 @@ "operator": "++", "prefix": false, "src": "137:3:1", - "subExpression": - { + "subExpression": { "id": 15, "name": "i", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 9, "src": "137:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -296,16 +257,14 @@ }, { "documentation": "tes \"t4\" ", - "expression": - { + "expression": { "id": 24, "name": "x", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 6, "src": "257:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -325,19 +284,16 @@ "name": "f", "nameLocation": "51:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], "src": "52:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 7, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 6, @@ -349,19 +305,16 @@ "src": "76:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 5, "name": "uint", "nodeType": "ElementaryTypeName", "src": "76:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } diff --git a/test/libsolidity/ASTJSON/documentation_triple_parseOnly.json b/test/libsolidity/ASTJSON/documentation_triple_parseOnly.json index 5ccc2631c..7f24ded91 100644 --- a/test/libsolidity/ASTJSON/documentation_triple_parseOnly.json +++ b/test/libsolidity/ASTJSON/documentation_triple_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 29, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,8 +12,7 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 3, @@ -26,8 +24,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 2, "name": "uint", "nodeType": "ElementaryTypeName", @@ -37,28 +34,22 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 26, "nodeType": "Block", "src": "84:181:1", - "statements": - [ + "statements": [ { - "body": - { + "body": { "id": 22, "nodeType": "Block", "src": "142:75:1", - "statements": - [ + "statements": [ { "documentation": "tee\n s \"t\" 3", - "expression": - { + "expression": { "id": 20, - "leftHandSide": - { + "leftHandSide": { "id": 18, "name": "x", "nodeType": "Identifier", @@ -68,8 +59,7 @@ }, "nodeType": "Assignment", "operator": "*=", - "rightHandSide": - { + "rightHandSide": { "hexValue": "32", "id": 19, "kind": "number", @@ -87,12 +77,10 @@ } ] }, - "condition": - { + "condition": { "commonType": {}, "id": 14, - "leftExpression": - { + "leftExpression": { "id": 12, "name": "i", "nodeType": "Identifier", @@ -102,8 +90,7 @@ }, "nodeType": "BinaryOperation", "operator": "<", - "rightExpression": - { + "rightExpression": { "hexValue": "3230", "id": 13, "kind": "number", @@ -117,14 +104,11 @@ }, "documentation": "test2", "id": 23, - "initializationExpression": - { - "assignments": - [ + "initializationExpression": { + "assignments": [ 9 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 9, @@ -136,8 +120,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 8, "name": "uint", "nodeType": "ElementaryTypeName", @@ -148,8 +131,7 @@ } ], "id": 11, - "initialValue": - { + "initialValue": { "hexValue": "30", "id": 10, "kind": "number", @@ -161,17 +143,14 @@ "nodeType": "VariableDeclarationStatement", "src": "117:10:1" }, - "loopExpression": - { - "expression": - { + "loopExpression": { + "expression": { "id": 16, "nodeType": "UnaryOperation", "operator": "++", "prefix": false, "src": "137:3:1", - "subExpression": - { + "subExpression": { "id": 15, "name": "i", "nodeType": "Identifier", @@ -190,8 +169,7 @@ }, { "documentation": "tes \"t4\" ", - "expression": - { + "expression": { "id": 24, "name": "x", "nodeType": "Identifier", @@ -212,19 +190,16 @@ "name": "f", "nameLocation": "51:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], "src": "52:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 7, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 6, @@ -236,8 +211,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 5, "name": "uint", "nodeType": "ElementaryTypeName", diff --git a/test/libsolidity/ASTJSON/enum_natspec.json b/test/libsolidity/ASTJSON/enum_natspec.json index f3cc7b8df..e55e3705d 100644 --- a/test/libsolidity/ASTJSON/enum_natspec.json +++ b/test/libsolidity/ASTJSON/enum_natspec.json @@ -1,28 +1,23 @@ { "absolutePath": "a", - "exportedSymbols": - { - "Color": - [ + "exportedSymbols": { + "Color": [ 4 ] }, "id": 5, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "canonicalName": "Color", - "documentation": - { + "documentation": { "id": 1, "nodeType": "StructuredDocumentation", "src": "0:112:1", "text": "@title example of title\n @author example of author\n @notice example of notice\n @dev example of dev" }, "id": 4, - "members": - [ + "members": [ { "id": 2, "name": "Red", diff --git a/test/libsolidity/ASTJSON/enum_natspec_parseOnly.json b/test/libsolidity/ASTJSON/enum_natspec_parseOnly.json index b5a38af6c..723df77c1 100644 --- a/test/libsolidity/ASTJSON/enum_natspec_parseOnly.json +++ b/test/libsolidity/ASTJSON/enum_natspec_parseOnly.json @@ -2,19 +2,16 @@ "absolutePath": "a", "id": 5, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { - "documentation": - { + "documentation": { "id": 1, "nodeType": "StructuredDocumentation", "src": "0:112:1", "text": "@title example of title\n @author example of author\n @notice example of notice\n @dev example of dev" }, "id": 4, - "members": - [ + "members": [ { "id": 2, "name": "Red", diff --git a/test/libsolidity/ASTJSON/enum_value.json b/test/libsolidity/ASTJSON/enum_value.json index 31615f657..de507a79e 100644 --- a/test/libsolidity/ASTJSON/enum_value.json +++ b/test/libsolidity/ASTJSON/enum_value.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 4 ] }, "id": 5, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,20 +16,17 @@ "contractKind": "contract", "fullyImplemented": true, "id": 4, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 4 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "canonicalName": "C.E", "id": 3, - "members": - [ + "members": [ { "id": 1, "name": "A", diff --git a/test/libsolidity/ASTJSON/enum_value_declaration.json b/test/libsolidity/ASTJSON/enum_value_declaration.json index acdcc736e..324911fa9 100644 --- a/test/libsolidity/ASTJSON/enum_value_declaration.json +++ b/test/libsolidity/ASTJSON/enum_value_declaration.json @@ -1,25 +1,20 @@ { "absolutePath": "a", - "exportedSymbols": - { - "A": - [ + "exportedSymbols": { + "A": [ 3 ], - "f": - [ + "f": [ 13 ] }, "id": 14, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "canonicalName": "A", "id": 3, - "members": - [ + "members": [ { "id": 1, "name": "X", @@ -41,26 +36,21 @@ "src": "0:15:1" }, { - "body": - { + "body": { "id": 12, "nodeType": "Block", "src": "46:15:1", - "statements": - [ + "statements": [ { - "expression": - { - "expression": - { + "expression": { + "expression": { "id": 9, "name": "A", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 3, "src": "55:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_enum$_A_$3_$", "typeString": "type(enum A)" } @@ -75,8 +65,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 1, "src": "55:3:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_enum$_A_$3", "typeString": "enum A" } @@ -95,19 +84,16 @@ "name": "f", "nameLocation": "25:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], "src": "26:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 8, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 7, @@ -119,21 +105,17 @@ "src": "43:1:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_enum$_A_$3", "typeString": "enum A" }, - "typeName": - { + "typeName": { "id": 6, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 5, "name": "A", - "nameLocations": - [ + "nameLocations": [ "43:1:1" ], "nodeType": "IdentifierPath", @@ -142,8 +124,7 @@ }, "referencedDeclaration": 3, "src": "43:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_enum$_A_$3", "typeString": "enum A" } diff --git a/test/libsolidity/ASTJSON/enum_value_declaration_parseOnly.json b/test/libsolidity/ASTJSON/enum_value_declaration_parseOnly.json index 8fa574fa7..93499e815 100644 --- a/test/libsolidity/ASTJSON/enum_value_declaration_parseOnly.json +++ b/test/libsolidity/ASTJSON/enum_value_declaration_parseOnly.json @@ -2,12 +2,10 @@ "absolutePath": "a", "id": 14, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 3, - "members": - [ + "members": [ { "id": 1, "name": "X", @@ -29,18 +27,14 @@ "src": "0:15:1" }, { - "body": - { + "body": { "id": 12, "nodeType": "Block", "src": "46:15:1", - "statements": - [ + "statements": [ { - "expression": - { - "expression": - { + "expression": { + "expression": { "id": 9, "name": "A", "nodeType": "Identifier", @@ -68,19 +62,16 @@ "name": "f", "nameLocation": "25:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], "src": "26:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 8, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 7, @@ -92,16 +83,13 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 6, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 5, "name": "A", - "nameLocations": - [ + "nameLocations": [ "43:1:1" ], "nodeType": "IdentifierPath", diff --git a/test/libsolidity/ASTJSON/enum_value_parseOnly.json b/test/libsolidity/ASTJSON/enum_value_parseOnly.json index 006e2db36..564c71273 100644 --- a/test/libsolidity/ASTJSON/enum_value_parseOnly.json +++ b/test/libsolidity/ASTJSON/enum_value_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 5, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,12 +12,10 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "id": 3, - "members": - [ + "members": [ { "id": 1, "name": "A", diff --git a/test/libsolidity/ASTJSON/event_aggregated_contract.json b/test/libsolidity/ASTJSON/event_aggregated_contract.json index e312320c1..d1bf17c75 100644 --- a/test/libsolidity/ASTJSON/event_aggregated_contract.json +++ b/test/libsolidity/ASTJSON/event_aggregated_contract.json @@ -1,20 +1,16 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 10 ], - "D": - [ + "D": [ 30 ] }, "id": 31, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -23,15 +19,13 @@ "contractKind": "contract", "fullyImplemented": true, "id": 10, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 10 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "eventSelector": "ffae15ba29768297c9b951e2e14bc33dc84599d1572acc234266fc70392babc8", @@ -39,8 +33,7 @@ "name": "e", "nameLocation": "23:1:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], @@ -49,19 +42,15 @@ "src": "17:10:1" }, { - "body": - { + "body": { "id": 8, "nodeType": "Block", "src": "52:25:1", - "statements": - [ + "statements": [ { - "eventCall": - { + "eventCall": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], "id": 5, "name": "e", @@ -69,8 +58,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 2, "src": "67:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_event_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -86,8 +74,7 @@ "nodeType": "FunctionCall", "src": "67:3:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -106,15 +93,13 @@ "name": "f", "nameLocation": "41:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], "src": "42:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], @@ -130,8 +115,7 @@ "scope": 31, "src": "0:79:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 2 ] }, @@ -139,22 +123,19 @@ "abstract": false, "baseContracts": [], "canonicalName": "D", - "contractDependencies": - [ + "contractDependencies": [ 10 ], "contractKind": "contract", "fullyImplemented": true, "id": 30, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 30 ], "name": "D", "nameLocation": "89:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 13, @@ -166,21 +147,17 @@ "src": "97:3:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_contract$_C_$10", "typeString": "contract C" }, - "typeName": - { + "typeName": { "id": 12, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 11, "name": "C", - "nameLocations": - [ + "nameLocations": [ "97:1:1" ], "nodeType": "IdentifierPath", @@ -189,8 +166,7 @@ }, "referencedDeclaration": 10, "src": "97:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_contract$_C_$10", "typeString": "contract C" } @@ -198,42 +174,35 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 28, "nodeType": "Block", "src": "120:43:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "id": 21, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, - "leftHandSide": - { + "leftHandSide": { "id": 16, "name": "c", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 13, "src": "130:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_contract$_C_$10", "typeString": "contract C" } }, "nodeType": "Assignment", "operator": "=", - "rightHandSide": - { + "rightHandSide": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], "id": 19, "isConstant": false, @@ -242,21 +211,17 @@ "lValueRequested": false, "nodeType": "NewExpression", "src": "134:5:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_creation_nonpayable$__$returns$_t_contract$_C_$10_$", "typeString": "function () returns (contract C)" }, - "typeName": - { + "typeName": { "id": 18, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 17, "name": "C", - "nameLocations": - [ + "nameLocations": [ "138:1:1" ], "nodeType": "IdentifierPath", @@ -265,8 +230,7 @@ }, "referencedDeclaration": 10, "src": "138:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_contract$_C_$10", "typeString": "contract C" } @@ -283,15 +247,13 @@ "nodeType": "FunctionCall", "src": "134:7:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_contract$_C_$10", "typeString": "contract C" } }, "src": "130:11:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_contract$_C_$10", "typeString": "contract C" } @@ -301,22 +263,18 @@ "src": "130:11:1" }, { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "expression": - { + "expression": { "id": 23, "name": "c", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 13, "src": "151:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_contract$_C_$10", "typeString": "contract C" } @@ -331,8 +289,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 9, "src": "151:3:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_external_nonpayable$__$returns$__$", "typeString": "function () external" } @@ -348,8 +305,7 @@ "nodeType": "FunctionCall", "src": "151:5:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -367,15 +323,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 14, "nodeType": "ParameterList", "parameters": [], "src": "117:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 15, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/event_definition.json b/test/libsolidity/ASTJSON/event_definition.json index b59164fcb..cdbe3041e 100644 --- a/test/libsolidity/ASTJSON/event_definition.json +++ b/test/libsolidity/ASTJSON/event_definition.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 3 ] }, "id": 4, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,15 +16,13 @@ "contractKind": "contract", "fullyImplemented": true, "id": 3, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 3 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "eventSelector": "92bbf6e823a631f3c8e09b1c8df90f378fb56f7fbc9701827e1ff8aad7f6a028", @@ -35,8 +30,7 @@ "name": "E", "nameLocation": "19:1:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], @@ -48,8 +42,7 @@ "scope": 4, "src": "0:25:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 2 ] } diff --git a/test/libsolidity/ASTJSON/event_definition_parseOnly.json b/test/libsolidity/ASTJSON/event_definition_parseOnly.json index 9116b3d2d..25745fdc6 100644 --- a/test/libsolidity/ASTJSON/event_definition_parseOnly.json +++ b/test/libsolidity/ASTJSON/event_definition_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 4, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,16 +12,14 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "id": 2, "name": "E", "nameLocation": "19:1:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/event_emited_in_base_contract.json b/test/libsolidity/ASTJSON/event_emited_in_base_contract.json index 6b183b493..40bb3bae4 100644 --- a/test/libsolidity/ASTJSON/event_emited_in_base_contract.json +++ b/test/libsolidity/ASTJSON/event_emited_in_base_contract.json @@ -1,24 +1,19 @@ { "absolutePath": "a", - "exportedSymbols": - { - "B": - [ + "exportedSymbols": { + "B": [ 16 ], - "C": - [ + "C": [ 19 ], - "L": - [ + "L": [ 5 ] }, "id": 20, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -27,15 +22,13 @@ "contractKind": "library", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "L", "nameLocation": "10:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "eventSelector": "870e3024466c178150e2490c7cfb455e33c0db877113af040f89189d07946664", @@ -43,12 +36,10 @@ "name": "E", "nameLocation": "20:1:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 2, @@ -61,19 +52,16 @@ "src": "22:5:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint8", "typeString": "uint8" }, - "typeName": - { + "typeName": { "id": 1, "name": "uint8", "nodeType": "ElementaryTypeName", "src": "22:5:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint8", "typeString": "uint8" } @@ -89,8 +77,7 @@ "scope": 20, "src": "0:31:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 4 ] }, @@ -102,28 +89,22 @@ "contractKind": "contract", "fullyImplemented": true, "id": 16, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 16 ], "name": "B", "nameLocation": "41:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 14, "nodeType": "Block", "src": "63:28:1", - "statements": - [ + "statements": [ { - "eventCall": - { - "arguments": - [ + "eventCall": { + "arguments": [ { "hexValue": "30", "id": 11, @@ -134,33 +115,28 @@ "lValueRequested": false, "nodeType": "Literal", "src": "82:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_0_by_1", "typeString": "int_const 0" }, "value": "0" } ], - "expression": - { - "argumentTypes": - [ + "expression": { + "argumentTypes": [ { "typeIdentifier": "t_rational_0_by_1", "typeString": "int_const 0" } ], - "expression": - { + "expression": { "id": 8, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 5, "src": "78:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$5_$", "typeString": "type(library L)" } @@ -175,8 +151,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 4, "src": "78:3:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_event_nonpayable$_t_uint8_$returns$__$", "typeString": "function (uint8)" } @@ -192,8 +167,7 @@ "nodeType": "FunctionCall", "src": "78:6:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -211,15 +185,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 6, "nodeType": "ParameterList", "parameters": [], "src": "60:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 7, "nodeType": "ParameterList", "parameters": [], @@ -235,22 +207,18 @@ "scope": 20, "src": "32:61:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 4 ] }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 17, "name": "B", - "nameLocations": - [ + "nameLocations": [ "108:1:1" ], "nodeType": "IdentifierPath", @@ -267,8 +235,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 19, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 19, 16 ], @@ -279,8 +246,7 @@ "scope": 20, "src": "94:18:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 4 ] } diff --git a/test/libsolidity/ASTJSON/event_emitted_from_foreign_contract.json b/test/libsolidity/ASTJSON/event_emitted_from_foreign_contract.json index 2d70e2f9f..92de58cf8 100644 --- a/test/libsolidity/ASTJSON/event_emitted_from_foreign_contract.json +++ b/test/libsolidity/ASTJSON/event_emitted_from_foreign_contract.json @@ -1,20 +1,16 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ], - "D": - [ + "D": [ 19 ] }, "id": 20, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -23,15 +19,13 @@ "contractKind": "contract", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "eventSelector": "bd1155618a34fd53d1a2de9f705f42f3582842cba0b985b25c59888d86e0c929", @@ -39,12 +33,10 @@ "name": "E", "nameLocation": "23:1:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 2, @@ -57,20 +49,17 @@ "src": "25:22:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" }, - "typeName": - { + "typeName": { "id": 1, "name": "address", "nodeType": "ElementaryTypeName", "src": "25:7:1", "stateMutability": "nonpayable", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } @@ -86,8 +75,7 @@ "scope": 20, "src": "0:51:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 4 ] }, @@ -99,39 +87,31 @@ "contractKind": "contract", "fullyImplemented": true, "id": 19, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 19 ], "name": "D", "nameLocation": "61:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 17, "nodeType": "Block", "src": "106:37:1", - "statements": - [ + "statements": [ { - "eventCall": - { - "arguments": - [ + "eventCall": { + "arguments": [ { - "expression": - { + "expression": { "id": 13, "name": "msg", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": -15, "src": "125:3:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_magic_message", "typeString": "msg" } @@ -145,32 +125,27 @@ "memberName": "sender", "nodeType": "MemberAccess", "src": "125:10:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } } ], - "expression": - { - "argumentTypes": - [ + "expression": { + "argumentTypes": [ { "typeIdentifier": "t_address", "typeString": "address" } ], - "expression": - { + "expression": { "id": 10, "name": "C", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 5, "src": "121:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_C_$5_$", "typeString": "type(contract C)" } @@ -185,8 +160,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 4, "src": "121:3:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_event_nonpayable$_t_address_$returns$__$", "typeString": "function (address)" } @@ -202,8 +176,7 @@ "nodeType": "FunctionCall", "src": "121:15:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -222,12 +195,10 @@ "name": "test", "nameLocation": "78:4:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 8, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 7, @@ -239,20 +210,17 @@ "src": "83:14:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" }, - "typeName": - { + "typeName": { "id": 6, "name": "address", "nodeType": "ElementaryTypeName", "src": "83:7:1", "stateMutability": "nonpayable", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } @@ -262,8 +230,7 @@ ], "src": "82:16:1" }, - "returnParameters": - { + "returnParameters": { "id": 9, "nodeType": "ParameterList", "parameters": [], @@ -279,8 +246,7 @@ "scope": 20, "src": "52:93:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 4 ] } diff --git a/test/libsolidity/ASTJSON/event_emitted_from_foreign_contract_parseOnly.json b/test/libsolidity/ASTJSON/event_emitted_from_foreign_contract_parseOnly.json index b6c0ca5e0..60ccdff44 100644 --- a/test/libsolidity/ASTJSON/event_emitted_from_foreign_contract_parseOnly.json +++ b/test/libsolidity/ASTJSON/event_emitted_from_foreign_contract_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 20, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,20 +12,17 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "id": 4, "name": "E", "nameLocation": "23:1:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 2, @@ -39,8 +35,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 1, "name": "address", "nodeType": "ElementaryTypeName", @@ -69,24 +64,18 @@ "name": "D", "nameLocation": "61:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 17, "nodeType": "Block", "src": "106:37:1", - "statements": - [ + "statements": [ { - "eventCall": - { - "arguments": - [ + "eventCall": { + "arguments": [ { - "expression": - { + "expression": { "id": 13, "name": "msg", "nodeType": "Identifier", @@ -102,10 +91,8 @@ "typeDescriptions": {} } ], - "expression": - { - "expression": - { + "expression": { + "expression": { "id": 10, "name": "C", "nodeType": "Identifier", @@ -141,12 +128,10 @@ "name": "test", "nameLocation": "78:4:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 8, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 7, @@ -158,8 +143,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 6, "name": "address", "nodeType": "ElementaryTypeName", @@ -172,8 +156,7 @@ ], "src": "82:16:1" }, - "returnParameters": - { + "returnParameters": { "id": 9, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/event_inheritance.json b/test/libsolidity/ASTJSON/event_inheritance.json index afa79e916..d9a78da03 100644 --- a/test/libsolidity/ASTJSON/event_inheritance.json +++ b/test/libsolidity/ASTJSON/event_inheritance.json @@ -1,24 +1,19 @@ { "absolutePath": "a", - "exportedSymbols": - { - "B": - [ + "exportedSymbols": { + "B": [ 3 ], - "C": - [ + "C": [ 8 ], - "D": - [ + "D": [ 13 ] }, "id": 14, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -27,15 +22,13 @@ "contractKind": "interface", "fullyImplemented": true, "id": 3, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 3 ], "name": "B", "nameLocation": "10:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "eventSelector": "dbec0351ad6bb0c1f07ea56e236e3e692fde2259f0165fd422f241da339b7e4f", @@ -43,8 +36,7 @@ "name": "EB", "nameLocation": "24:2:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], @@ -56,22 +48,18 @@ "scope": 14, "src": "0:31:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 2 ] }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 4, "name": "B", - "nameLocations": - [ + "nameLocations": [ "46:1:1" ], "nodeType": "IdentifierPath", @@ -88,16 +76,14 @@ "contractKind": "contract", "fullyImplemented": true, "id": 8, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 8, 3 ], "name": "C", "nameLocation": "41:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "eventSelector": "a08b3367d3fa83ea27f8951ffb5d9d160cbfadbd80816b47f677e7699d76f5a0", @@ -105,8 +91,7 @@ "name": "EC", "nameLocation": "60:2:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 6, "nodeType": "ParameterList", "parameters": [], @@ -118,23 +103,19 @@ "scope": 14, "src": "32:35:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 2, 7 ] }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 9, "name": "C", - "nameLocations": - [ + "nameLocations": [ "82:1:1" ], "nodeType": "IdentifierPath", @@ -151,8 +132,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 13, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 13, 8, 3 @@ -160,8 +140,7 @@ "name": "D", "nameLocation": "77:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "eventSelector": "caa54b91a2314ab89b39714b1cd283762e53a2f59cfb997d6770e2824c39db0d", @@ -169,8 +148,7 @@ "name": "ED", "nameLocation": "96:2:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 11, "nodeType": "ParameterList", "parameters": [], @@ -182,8 +160,7 @@ "scope": 14, "src": "68:35:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 2, 7, 12 diff --git a/test/libsolidity/ASTJSON/event_with_variables_of_internal_types.sol b/test/libsolidity/ASTJSON/event_with_variables_of_internal_types.sol index 6fe58c39c..a22910570 100644 --- a/test/libsolidity/ASTJSON/event_with_variables_of_internal_types.sol +++ b/test/libsolidity/ASTJSON/event_with_variables_of_internal_types.sol @@ -1,4 +1,5 @@ contract C { event E(function() internal); } + // ---- diff --git a/test/libsolidity/ASTJSON/event_with_variables_of_internal_types_parseOnly.json b/test/libsolidity/ASTJSON/event_with_variables_of_internal_types_parseOnly.json index 3ff426cb2..44c1fb536 100644 --- a/test/libsolidity/ASTJSON/event_with_variables_of_internal_types_parseOnly.json +++ b/test/libsolidity/ASTJSON/event_with_variables_of_internal_types_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 8, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,20 +12,17 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "id": 6, "name": "E", "nameLocation": "23:1:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 5, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 4, @@ -39,19 +35,16 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 3, "nodeType": "FunctionTypeName", - "parameterTypes": - { + "parameterTypes": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "33:2:1" }, - "returnParameterTypes": - { + "returnParameterTypes": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/fail_after_parsing.sol b/test/libsolidity/ASTJSON/fail_after_parsing.sol index 882b4c950..052900e93 100644 --- a/test/libsolidity/ASTJSON/fail_after_parsing.sol +++ b/test/libsolidity/ASTJSON/fail_after_parsing.sol @@ -1,15 +1,12 @@ function g() public; - interface I { struct S { S s; } - function f(E storage e) { error E; emit E(); - ++c; uint calldata c = 123.4; } } + // ---- -// failAfter: Parsed diff --git a/test/libsolidity/ASTJSON/fail_after_parsing_parseOnly.json b/test/libsolidity/ASTJSON/fail_after_parsing_parseOnly.json index f1d958617..6f841649c 100644 --- a/test/libsolidity/ASTJSON/fail_after_parsing_parseOnly.json +++ b/test/libsolidity/ASTJSON/fail_after_parsing_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 30, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 3, "implemented": false, @@ -12,15 +11,13 @@ "name": "g", "nameLocation": "9:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "10:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], @@ -40,12 +37,10 @@ "name": "I", "nameLocation": "31:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "id": 7, - "members": - [ + "members": [ { "constant": false, "id": 6, @@ -57,16 +52,13 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 5, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 4, "name": "S", - "nameLocations": - [ + "nameLocations": [ "50:1:1" ], "nodeType": "IdentifierPath", @@ -85,20 +77,16 @@ "visibility": "public" }, { - "body": - { + "body": { "id": 27, "nodeType": "Block", "src": "85:88:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 15 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 15, @@ -110,16 +98,13 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 14, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 13, "name": "error", - "nameLocations": - [ + "nameLocations": [ "95:5:1" ], "nodeType": "IdentifierPath", @@ -136,11 +121,9 @@ "src": "95:7:1" }, { - "eventCall": - { + "eventCall": { "arguments": [], - "expression": - { + "expression": { "id": 17, "name": "E", "nodeType": "Identifier", @@ -161,15 +144,13 @@ "src": "112:8:1" }, { - "expression": - { + "expression": { "id": 21, "nodeType": "UnaryOperation", "operator": "++", "prefix": true, "src": "130:3:1", - "subExpression": - { + "subExpression": { "id": 20, "name": "c", "nodeType": "Identifier", @@ -184,12 +165,10 @@ "src": "130:3:1" }, { - "assignments": - [ + "assignments": [ 24 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 24, @@ -201,8 +180,7 @@ "stateVariable": false, "storageLocation": "calldata", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 23, "name": "uint", "nodeType": "ElementaryTypeName", @@ -213,8 +191,7 @@ } ], "id": 26, - "initialValue": - { + "initialValue": { "hexValue": "3132332e34", "id": 25, "kind": "number", @@ -235,12 +212,10 @@ "name": "f", "nameLocation": "70:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 11, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 10, @@ -252,16 +227,13 @@ "stateVariable": false, "storageLocation": "storage", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 9, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 8, "name": "E", - "nameLocations": - [ + "nameLocations": [ "72:1:1" ], "nodeType": "IdentifierPath", @@ -275,8 +247,7 @@ ], "src": "71:13:1" }, - "returnParameters": - { + "returnParameters": { "id": 12, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/fallback.json b/test/libsolidity/ASTJSON/fallback.json index f68c72ce6..93646f2af 100644 --- a/test/libsolidity/ASTJSON/fallback.json +++ b/test/libsolidity/ASTJSON/fallback.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ] }, "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,18 +16,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "43:5:1", @@ -43,15 +37,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/fallback.sol b/test/libsolidity/ASTJSON/fallback.sol index 170e77958..219d85db5 100644 --- a/test/libsolidity/ASTJSON/fallback.sol +++ b/test/libsolidity/ASTJSON/fallback.sol @@ -2,4 +2,5 @@ contract C { fallback() external payable { } } + // ---- diff --git a/test/libsolidity/ASTJSON/fallback_and_receive_ether.json b/test/libsolidity/ASTJSON/fallback_and_receive_ether.json index f41559d2a..5504719ec 100644 --- a/test/libsolidity/ASTJSON/fallback_and_receive_ether.json +++ b/test/libsolidity/ASTJSON/fallback_and_receive_ether.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 9 ] }, "id": 10, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,18 +16,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 9, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 9 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "42:5:1", @@ -43,15 +37,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "22:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], @@ -64,8 +56,7 @@ "visibility": "external" }, { - "body": - { + "body": { "id": 7, "nodeType": "Block", "src": "78:5:1", @@ -78,15 +69,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 5, "nodeType": "ParameterList", "parameters": [], "src": "58:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 6, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/fallback_and_receive_ether.sol b/test/libsolidity/ASTJSON/fallback_and_receive_ether.sol index 7eb712582..89acccf5a 100644 --- a/test/libsolidity/ASTJSON/fallback_and_receive_ether.sol +++ b/test/libsolidity/ASTJSON/fallback_and_receive_ether.sol @@ -4,4 +4,5 @@ contract C { fallback() external payable { } } + // ---- diff --git a/test/libsolidity/ASTJSON/fallback_and_receive_ether_parseOnly.json b/test/libsolidity/ASTJSON/fallback_and_receive_ether_parseOnly.json index 215bf3a83..34260824f 100644 --- a/test/libsolidity/ASTJSON/fallback_and_receive_ether_parseOnly.json +++ b/test/libsolidity/ASTJSON/fallback_and_receive_ether_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 10, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,11 +12,9 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "42:5:1", @@ -30,15 +27,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "22:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], @@ -50,8 +45,7 @@ "visibility": "external" }, { - "body": - { + "body": { "id": 7, "nodeType": "Block", "src": "78:5:1", @@ -64,15 +58,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 5, "nodeType": "ParameterList", "parameters": [], "src": "58:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 6, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/fallback_parseOnly.json b/test/libsolidity/ASTJSON/fallback_parseOnly.json index eb81fafbe..6991b32b4 100644 --- a/test/libsolidity/ASTJSON/fallback_parseOnly.json +++ b/test/libsolidity/ASTJSON/fallback_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,11 +12,9 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "43:5:1", @@ -30,15 +27,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/fallback_payable.json b/test/libsolidity/ASTJSON/fallback_payable.json index 790351764..e3eacc1ec 100644 --- a/test/libsolidity/ASTJSON/fallback_payable.json +++ b/test/libsolidity/ASTJSON/fallback_payable.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ] }, "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,18 +16,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "34:2:1", @@ -43,15 +37,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "22:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/fallback_payable.sol b/test/libsolidity/ASTJSON/fallback_payable.sol index 7eff747af..d66d378af 100644 --- a/test/libsolidity/ASTJSON/fallback_payable.sol +++ b/test/libsolidity/ASTJSON/fallback_payable.sol @@ -1,4 +1,5 @@ contract C { fallback() external {} } + // ---- diff --git a/test/libsolidity/ASTJSON/fallback_payable_parseOnly.json b/test/libsolidity/ASTJSON/fallback_payable_parseOnly.json index e1810828a..f14d2f1ed 100644 --- a/test/libsolidity/ASTJSON/fallback_payable_parseOnly.json +++ b/test/libsolidity/ASTJSON/fallback_payable_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,11 +12,9 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "34:2:1", @@ -30,15 +27,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "22:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/function_type.json b/test/libsolidity/ASTJSON/function_type.json index e1a5156cf..563b65438 100644 --- a/test/libsolidity/ASTJSON/function_type.json +++ b/test/libsolidity/ASTJSON/function_type.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 17 ] }, "id": 18, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,18 +16,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 17, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 17 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 15, "nodeType": "Block", "src": "127:2:1", @@ -44,12 +38,10 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 6, @@ -61,28 +53,23 @@ "src": "24:44:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_external_payable$__$returns$_t_uint256_$", "typeString": "function () payable external returns (uint256)" }, - "typeName": - { + "typeName": { "id": 5, "nodeType": "FunctionTypeName", - "parameterTypes": - { + "parameterTypes": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "32:2:1" }, - "returnParameterTypes": - { + "returnParameterTypes": { "id": 4, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 3, @@ -94,19 +81,16 @@ "src": "61:4:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 2, "name": "uint", "nodeType": "ElementaryTypeName", "src": "61:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -118,8 +102,7 @@ }, "src": "24:44:1", "stateMutability": "payable", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_external_payable$__$returns$_t_uint256_$", "typeString": "function () payable external returns (uint256)" }, @@ -130,12 +113,10 @@ ], "src": "23:46:1" }, - "returnParameters": - { + "returnParameters": { "id": 14, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 13, @@ -147,28 +128,23 @@ "src": "86:40:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_external_view$__$returns$_t_uint256_$", "typeString": "function () view external returns (uint256)" }, - "typeName": - { + "typeName": { "id": 12, "nodeType": "FunctionTypeName", - "parameterTypes": - { + "parameterTypes": { "id": 8, "nodeType": "ParameterList", "parameters": [], "src": "94:2:1" }, - "returnParameterTypes": - { + "returnParameterTypes": { "id": 11, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 10, @@ -180,19 +156,16 @@ "src": "120:4:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 9, "name": "uint", "nodeType": "ElementaryTypeName", "src": "120:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -204,8 +177,7 @@ }, "src": "86:40:1", "stateMutability": "view", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_external_view$__$returns$_t_uint256_$", "typeString": "function () view external returns (uint256)" }, diff --git a/test/libsolidity/ASTJSON/function_type_parseOnly.json b/test/libsolidity/ASTJSON/function_type_parseOnly.json index 64b09d5d9..765c51780 100644 --- a/test/libsolidity/ASTJSON/function_type_parseOnly.json +++ b/test/libsolidity/ASTJSON/function_type_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 18, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,11 +12,9 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 15, "nodeType": "Block", "src": "127:2:1", @@ -30,12 +27,10 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 6, @@ -47,23 +42,19 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 5, "nodeType": "FunctionTypeName", - "parameterTypes": - { + "parameterTypes": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "32:2:1" }, - "returnParameterTypes": - { + "returnParameterTypes": { "id": 4, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 3, @@ -75,8 +66,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 2, "name": "uint", "nodeType": "ElementaryTypeName", @@ -98,12 +88,10 @@ ], "src": "23:46:1" }, - "returnParameters": - { + "returnParameters": { "id": 14, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 13, @@ -115,23 +103,19 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 12, "nodeType": "FunctionTypeName", - "parameterTypes": - { + "parameterTypes": { "id": 8, "nodeType": "ParameterList", "parameters": [], "src": "94:2:1" }, - "returnParameterTypes": - { + "returnParameterTypes": { "id": 11, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 10, @@ -143,8 +127,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 9, "name": "uint", "nodeType": "ElementaryTypeName", diff --git a/test/libsolidity/ASTJSON/global_enum.json b/test/libsolidity/ASTJSON/global_enum.json index 0b673cffb..17a92954f 100644 --- a/test/libsolidity/ASTJSON/global_enum.json +++ b/test/libsolidity/ASTJSON/global_enum.json @@ -1,21 +1,17 @@ { "absolutePath": "a", - "exportedSymbols": - { - "E": - [ + "exportedSymbols": { + "E": [ 2 ] }, "id": 3, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "canonicalName": "E", "id": 2, - "members": - [ + "members": [ { "id": 1, "name": "A", diff --git a/test/libsolidity/ASTJSON/global_enum_parseOnly.json b/test/libsolidity/ASTJSON/global_enum_parseOnly.json index 887d5997c..c390db5b3 100644 --- a/test/libsolidity/ASTJSON/global_enum_parseOnly.json +++ b/test/libsolidity/ASTJSON/global_enum_parseOnly.json @@ -2,12 +2,10 @@ "absolutePath": "a", "id": 3, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 2, - "members": - [ + "members": [ { "id": 1, "name": "A", diff --git a/test/libsolidity/ASTJSON/global_struct.json b/test/libsolidity/ASTJSON/global_struct.json index 2c14a5e41..f7f937d04 100644 --- a/test/libsolidity/ASTJSON/global_struct.json +++ b/test/libsolidity/ASTJSON/global_struct.json @@ -1,21 +1,17 @@ { "absolutePath": "a", - "exportedSymbols": - { - "S": - [ + "exportedSymbols": { + "S": [ 3 ] }, "id": 4, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "canonicalName": "S", "id": 3, - "members": - [ + "members": [ { "constant": false, "id": 2, @@ -27,19 +23,16 @@ "src": "11:9:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 1, "name": "uint256", "nodeType": "ElementaryTypeName", "src": "11:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } diff --git a/test/libsolidity/ASTJSON/global_struct_parseOnly.json b/test/libsolidity/ASTJSON/global_struct_parseOnly.json index 418cb79fa..5f90ab8a1 100644 --- a/test/libsolidity/ASTJSON/global_struct_parseOnly.json +++ b/test/libsolidity/ASTJSON/global_struct_parseOnly.json @@ -2,12 +2,10 @@ "absolutePath": "a", "id": 4, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 3, - "members": - [ + "members": [ { "constant": false, "id": 2, @@ -19,8 +17,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 1, "name": "uint256", "nodeType": "ElementaryTypeName", diff --git a/test/libsolidity/ASTJSON/indirect_event.json b/test/libsolidity/ASTJSON/indirect_event.json index fcbe81756..691e814e5 100644 --- a/test/libsolidity/ASTJSON/indirect_event.json +++ b/test/libsolidity/ASTJSON/indirect_event.json @@ -1,21 +1,17 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 25 ], - "L": - [ + "L": [ 10 ] }, "id": 26, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -24,15 +20,13 @@ "contractKind": "library", "fullyImplemented": true, "id": 10, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 10 ], "name": "L", "nameLocation": "44:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "eventSelector": "92bbf6e823a631f3c8e09b1c8df90f378fb56f7fbc9701827e1ff8aad7f6a028", @@ -40,8 +34,7 @@ "name": "E", "nameLocation": "58:1:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], @@ -50,19 +43,15 @@ "src": "52:10:1" }, { - "body": - { + "body": { "id": 8, "nodeType": "Block", "src": "89:13:1", - "statements": - [ + "statements": [ { - "eventCall": - { + "eventCall": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], "id": 5, "name": "E", @@ -70,8 +59,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 2, "src": "96:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_event_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -87,8 +75,7 @@ "nodeType": "FunctionCall", "src": "96:3:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -106,15 +93,13 @@ "name": "f", "nameLocation": "76:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], "src": "77:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], @@ -130,8 +115,7 @@ "scope": 26, "src": "36:68:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 2 ] }, @@ -143,15 +127,13 @@ "contractKind": "contract", "fullyImplemented": true, "id": 25, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 25 ], "name": "C", "nameLocation": "114:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "eventSelector": "70a5d861ef9816388422765f41d618eb3abdf490acb37354b539729e37b09f0e", @@ -159,8 +141,7 @@ "name": "H", "nameLocation": "128:1:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 11, "nodeType": "ParameterList", "parameters": [], @@ -169,30 +150,24 @@ "src": "122:10:1" }, { - "body": - { + "body": { "id": 23, "nodeType": "Block", "src": "157:20:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], - "expression": - { + "expression": { "id": 15, "name": "L", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 10, "src": "159:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_L_$10_$", "typeString": "type(library L)" } @@ -207,8 +182,7 @@ "nodeType": "MemberAccess", "referencedDeclaration": 9, "src": "159:3:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -224,8 +198,7 @@ "nodeType": "FunctionCall", "src": "159:5:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -235,11 +208,9 @@ "src": "159:5:1" }, { - "eventCall": - { + "eventCall": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], "id": 20, "name": "H", @@ -247,8 +218,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 12, "src": "171:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_event_nonpayable$__$returns$__$", "typeString": "function ()" } @@ -264,8 +234,7 @@ "nodeType": "FunctionCall", "src": "171:3:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -284,15 +253,13 @@ "name": "g", "nameLocation": "146:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 13, "nodeType": "ParameterList", "parameters": [], "src": "147:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 14, "nodeType": "ParameterList", "parameters": [], @@ -308,8 +275,7 @@ "scope": 26, "src": "105:74:1", "usedErrors": [], - "usedEvents": - [ + "usedEvents": [ 2, 12 ] diff --git a/test/libsolidity/ASTJSON/indirect_event_parseOnly.json b/test/libsolidity/ASTJSON/indirect_event_parseOnly.json index 17ca036d3..82ce0cd15 100644 --- a/test/libsolidity/ASTJSON/indirect_event_parseOnly.json +++ b/test/libsolidity/ASTJSON/indirect_event_parseOnly.json @@ -3,8 +3,7 @@ "id": 26, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -14,16 +13,14 @@ "name": "L", "nameLocation": "44:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "id": 2, "name": "E", "nameLocation": "58:1:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], @@ -32,19 +29,15 @@ "src": "52:10:1" }, { - "body": - { + "body": { "id": 8, "nodeType": "Block", "src": "89:13:1", - "statements": - [ + "statements": [ { - "eventCall": - { + "eventCall": { "arguments": [], - "expression": - { + "expression": { "id": 5, "name": "E", "nodeType": "Identifier", @@ -73,15 +66,13 @@ "name": "f", "nameLocation": "76:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], "src": "77:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], @@ -106,16 +97,14 @@ "name": "C", "nameLocation": "114:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "anonymous": false, "id": 12, "name": "H", "nameLocation": "128:1:1", "nodeType": "EventDefinition", - "parameters": - { + "parameters": { "id": 11, "nodeType": "ParameterList", "parameters": [], @@ -124,21 +113,16 @@ "src": "122:10:1" }, { - "body": - { + "body": { "id": 23, "nodeType": "Block", "src": "157:20:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "expression": - { - "expression": - { + "expression": { + "expression": { "id": 15, "name": "L", "nodeType": "Identifier", @@ -166,11 +150,9 @@ "src": "159:5:1" }, { - "eventCall": - { + "eventCall": { "arguments": [], - "expression": - { + "expression": { "id": 20, "name": "H", "nodeType": "Identifier", @@ -199,15 +181,13 @@ "name": "g", "nameLocation": "146:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 13, "nodeType": "ParameterList", "parameters": [], "src": "147:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 14, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/inheritance_specifier.json b/test/libsolidity/ASTJSON/inheritance_specifier.json index ae210c949..4365a9e43 100644 --- a/test/libsolidity/ASTJSON/inheritance_specifier.json +++ b/test/libsolidity/ASTJSON/inheritance_specifier.json @@ -1,20 +1,16 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C1": - [ + "exportedSymbols": { + "C1": [ 1 ], - "C2": - [ + "C2": [ 4 ] }, "id": 5, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -23,8 +19,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 1, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 1 ], "name": "C1", @@ -38,15 +33,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 2, "name": "C1", - "nameLocations": - [ + "nameLocations": [ "30:2:1" ], "nodeType": "IdentifierPath", @@ -63,8 +55,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 4, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 4, 1 ], diff --git a/test/libsolidity/ASTJSON/inheritance_specifier_parseOnly.json b/test/libsolidity/ASTJSON/inheritance_specifier_parseOnly.json index 171391b36..a334485a9 100644 --- a/test/libsolidity/ASTJSON/inheritance_specifier_parseOnly.json +++ b/test/libsolidity/ASTJSON/inheritance_specifier_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 5, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -20,15 +19,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 2, "name": "C1", - "nameLocations": - [ + "nameLocations": [ "30:2:1" ], "nodeType": "IdentifierPath", diff --git a/test/libsolidity/ASTJSON/license.json b/test/libsolidity/ASTJSON/license.json index 4c0882637..f12ed7e3e 100644 --- a/test/libsolidity/ASTJSON/license.json +++ b/test/libsolidity/ASTJSON/license.json @@ -1,17 +1,14 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 1 ] }, "id": 2, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -20,8 +17,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 1, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 1 ], "name": "C", diff --git a/test/libsolidity/ASTJSON/license_parseOnly.json b/test/libsolidity/ASTJSON/license_parseOnly.json index f2958f15f..def7f2c62 100644 --- a/test/libsolidity/ASTJSON/license_parseOnly.json +++ b/test/libsolidity/ASTJSON/license_parseOnly.json @@ -3,8 +3,7 @@ "id": 2, "license": "GPL-3.0", "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], diff --git a/test/libsolidity/ASTJSON/long_type_name_binary_operation.json b/test/libsolidity/ASTJSON/long_type_name_binary_operation.json index 9bcd5e8fd..f5a6aad08 100644 --- a/test/libsolidity/ASTJSON/long_type_name_binary_operation.json +++ b/test/libsolidity/ASTJSON/long_type_name_binary_operation.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "c": - [ + "exportedSymbols": { + "c": [ 11 ] }, "id": 12, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,30 +16,24 @@ "contractKind": "contract", "fullyImplemented": true, "id": 11, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 11 ], "name": "c", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 9, "nodeType": "Block", "src": "33:19:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -54,19 +45,16 @@ "src": "35:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 3, "name": "uint", "nodeType": "ElementaryTypeName", "src": "35:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -75,10 +63,8 @@ } ], "id": 8, - "initialValue": - { - "commonType": - { + "initialValue": { + "commonType": { "typeIdentifier": "t_rational_5_by_1", "typeString": "int_const 5" }, @@ -87,8 +73,7 @@ "isLValue": false, "isPure": true, "lValueRequested": false, - "leftExpression": - { + "leftExpression": { "hexValue": "32", "id": 5, "isConstant": false, @@ -98,8 +83,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "44:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_2_by_1", "typeString": "int_const 2" }, @@ -107,8 +91,7 @@ }, "nodeType": "BinaryOperation", "operator": "+", - "rightExpression": - { + "rightExpression": { "hexValue": "33", "id": 6, "isConstant": false, @@ -118,16 +101,14 @@ "lValueRequested": false, "nodeType": "Literal", "src": "48:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_3_by_1", "typeString": "int_const 3" }, "value": "3" }, "src": "44:5:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_5_by_1", "typeString": "int_const 5" } @@ -145,15 +126,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/long_type_name_binary_operation_parseOnly.json b/test/libsolidity/ASTJSON/long_type_name_binary_operation_parseOnly.json index 2cb372dd2..56587809e 100644 --- a/test/libsolidity/ASTJSON/long_type_name_binary_operation_parseOnly.json +++ b/test/libsolidity/ASTJSON/long_type_name_binary_operation_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 12, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,23 +12,18 @@ "name": "c", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 9, "nodeType": "Block", "src": "33:19:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -41,8 +35,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 3, "name": "uint", "nodeType": "ElementaryTypeName", @@ -53,12 +46,10 @@ } ], "id": 8, - "initialValue": - { + "initialValue": { "commonType": {}, "id": 7, - "leftExpression": - { + "leftExpression": { "hexValue": "32", "id": 5, "kind": "number", @@ -69,8 +60,7 @@ }, "nodeType": "BinaryOperation", "operator": "+", - "rightExpression": - { + "rightExpression": { "hexValue": "33", "id": 6, "kind": "number", @@ -94,15 +84,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier.json b/test/libsolidity/ASTJSON/long_type_name_identifier.json index c22aeb40c..d3e76eaac 100644 --- a/test/libsolidity/ASTJSON/long_type_name_identifier.json +++ b/test/libsolidity/ASTJSON/long_type_name_identifier.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "c": - [ + "exportedSymbols": { + "c": [ 15 ] }, "id": 16, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,15 +16,13 @@ "contractKind": "contract", "fullyImplemented": true, "id": 15, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 15 ], "name": "c", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 3, @@ -39,21 +34,17 @@ "src": "13:8:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_uint256_$dyn_storage", "typeString": "uint256[]" }, - "typeName": - { - "baseType": - { + "typeName": { + "baseType": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", "src": "13:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -61,8 +52,7 @@ "id": 2, "nodeType": "ArrayTypeName", "src": "13:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_uint256_$dyn_storage_ptr", "typeString": "uint256[]" } @@ -70,20 +60,16 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 13, "nodeType": "Block", "src": "43:25:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 10 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 10, @@ -95,21 +81,17 @@ "src": "45:16:1", "stateVariable": false, "storageLocation": "storage", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_uint256_$dyn_storage_ptr", "typeString": "uint256[]" }, - "typeName": - { - "baseType": - { + "typeName": { + "baseType": { "id": 8, "name": "uint", "nodeType": "ElementaryTypeName", "src": "45:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -117,8 +99,7 @@ "id": 9, "nodeType": "ArrayTypeName", "src": "45:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_uint256_$dyn_storage_ptr", "typeString": "uint256[]" } @@ -127,16 +108,14 @@ } ], "id": 12, - "initialValue": - { + "initialValue": { "id": 11, "name": "a", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 3, "src": "64:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_uint256_$dyn_storage", "typeString": "uint256[] storage ref" } @@ -154,15 +133,13 @@ "name": "f", "nameLocation": "32:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], "src": "33:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 5, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier_parseOnly.json b/test/libsolidity/ASTJSON/long_type_name_identifier_parseOnly.json index 1bf50bed6..597bd383b 100644 --- a/test/libsolidity/ASTJSON/long_type_name_identifier_parseOnly.json +++ b/test/libsolidity/ASTJSON/long_type_name_identifier_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 16, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,8 +12,7 @@ "name": "c", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 3, @@ -26,10 +24,8 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { - "baseType": - { + "typeName": { + "baseType": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", @@ -44,20 +40,16 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 13, "nodeType": "Block", "src": "43:25:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 10 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 10, @@ -69,10 +61,8 @@ "stateVariable": false, "storageLocation": "storage", "typeDescriptions": {}, - "typeName": - { - "baseType": - { + "typeName": { + "baseType": { "id": 8, "name": "uint", "nodeType": "ElementaryTypeName", @@ -88,8 +78,7 @@ } ], "id": 12, - "initialValue": - { + "initialValue": { "id": 11, "name": "a", "nodeType": "Identifier", @@ -109,15 +98,13 @@ "name": "f", "nameLocation": "32:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], "src": "33:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 5, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/mappings.json b/test/libsolidity/ASTJSON/mappings.json index 81bf19db1..c1b9cfc48 100644 --- a/test/libsolidity/ASTJSON/mappings.json +++ b/test/libsolidity/ASTJSON/mappings.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 23 ] }, "id": 24, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,20 +16,17 @@ "contractKind": "contract", "fullyImplemented": true, "id": 23, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 23 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "canonicalName": "C.E", "id": 4, - "members": - [ + "members": [ { "id": 1, "name": "A", @@ -71,26 +65,21 @@ "src": "40:20:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_contract$_C_$23_$_t_bool_$", "typeString": "mapping(contract C => bool)" }, - "typeName": - { + "typeName": { "id": 8, "keyName": "", "keyNameLocation": "-1:-1:-1", - "keyType": - { + "keyType": { "id": 6, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 5, "name": "C", - "nameLocations": - [ + "nameLocations": [ "48:1:1" ], "nodeType": "IdentifierPath", @@ -99,29 +88,25 @@ }, "referencedDeclaration": 23, "src": "48:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_contract$_C_$23", "typeString": "contract C" } }, "nodeType": "Mapping", "src": "40:18:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_contract$_C_$23_$_t_bool_$", "typeString": "mapping(contract C => bool)" }, "valueName": "", "valueNameLocation": "-1:-1:-1", - "valueType": - { + "valueType": { "id": 7, "name": "bool", "nodeType": "ElementaryTypeName", "src": "53:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } @@ -140,45 +125,38 @@ "src": "66:26:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_address_$_t_bool_$", "typeString": "mapping(address => bool)" }, - "typeName": - { + "typeName": { "id": 12, "keyName": "", "keyNameLocation": "-1:-1:-1", - "keyType": - { + "keyType": { "id": 10, "name": "address", "nodeType": "ElementaryTypeName", "src": "74:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } }, "nodeType": "Mapping", "src": "66:24:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_address_$_t_bool_$", "typeString": "mapping(address => bool)" }, "valueName": "", "valueNameLocation": "-1:-1:-1", - "valueType": - { + "valueType": { "id": 11, "name": "bool", "nodeType": "ElementaryTypeName", "src": "85:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } @@ -197,26 +175,21 @@ "src": "98:20:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_enum$_E_$4_$_t_bool_$", "typeString": "mapping(enum C.E => bool)" }, - "typeName": - { + "typeName": { "id": 17, "keyName": "", "keyNameLocation": "-1:-1:-1", - "keyType": - { + "keyType": { "id": 15, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 14, "name": "E", - "nameLocations": - [ + "nameLocations": [ "106:1:1" ], "nodeType": "IdentifierPath", @@ -225,29 +198,25 @@ }, "referencedDeclaration": 4, "src": "106:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_enum$_E_$4", "typeString": "enum C.E" } }, "nodeType": "Mapping", "src": "98:18:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_enum$_E_$4_$_t_bool_$", "typeString": "mapping(enum C.E => bool)" }, "valueName": "", "valueNameLocation": "-1:-1:-1", - "valueType": - { + "valueType": { "id": 16, "name": "bool", "nodeType": "ElementaryTypeName", "src": "111:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } @@ -266,45 +235,38 @@ "src": "124:46:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_address_$_t_uint256_$", "typeString": "mapping(address => uint256)" }, - "typeName": - { + "typeName": { "id": 21, "keyName": "keyAddress", "keyNameLocation": "140:10:1", - "keyType": - { + "keyType": { "id": 19, "name": "address", "nodeType": "ElementaryTypeName", "src": "132:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } }, "nodeType": "Mapping", "src": "124:44:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_address_$_t_uint256_$", "typeString": "mapping(address => uint256)" }, "valueName": "value", "valueNameLocation": "162:5:1", - "valueType": - { + "valueType": { "id": 20, "name": "uint256", "nodeType": "ElementaryTypeName", "src": "154:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } diff --git a/test/libsolidity/ASTJSON/mappings.sol b/test/libsolidity/ASTJSON/mappings.sol index 5412ca601..05912d21f 100644 --- a/test/libsolidity/ASTJSON/mappings.sol +++ b/test/libsolidity/ASTJSON/mappings.sol @@ -5,4 +5,5 @@ contract C { mapping(E => bool) c; mapping(address keyAddress => uint256 value) d; } + // ---- diff --git a/test/libsolidity/ASTJSON/mappings_parseOnly.json b/test/libsolidity/ASTJSON/mappings_parseOnly.json index 84cfb4004..4edc75ffd 100644 --- a/test/libsolidity/ASTJSON/mappings_parseOnly.json +++ b/test/libsolidity/ASTJSON/mappings_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 24, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,12 +12,10 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "id": 4, - "members": - [ + "members": [ { "id": 1, "name": "A", @@ -57,21 +54,17 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 8, "keyName": "", "keyNameLocation": "-1:-1:-1", - "keyType": - { + "keyType": { "id": 6, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 5, "name": "C", - "nameLocations": - [ + "nameLocations": [ "48:1:1" ], "nodeType": "IdentifierPath", @@ -85,8 +78,7 @@ "typeDescriptions": {}, "valueName": "", "valueNameLocation": "-1:-1:-1", - "valueType": - { + "valueType": { "id": 7, "name": "bool", "nodeType": "ElementaryTypeName", @@ -107,13 +99,11 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 12, "keyName": "", "keyNameLocation": "-1:-1:-1", - "keyType": - { + "keyType": { "id": 10, "name": "address", "nodeType": "ElementaryTypeName", @@ -125,8 +115,7 @@ "typeDescriptions": {}, "valueName": "", "valueNameLocation": "-1:-1:-1", - "valueType": - { + "valueType": { "id": 11, "name": "bool", "nodeType": "ElementaryTypeName", @@ -147,21 +136,17 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 17, "keyName": "", "keyNameLocation": "-1:-1:-1", - "keyType": - { + "keyType": { "id": 15, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 14, "name": "E", - "nameLocations": - [ + "nameLocations": [ "106:1:1" ], "nodeType": "IdentifierPath", @@ -175,8 +160,7 @@ "typeDescriptions": {}, "valueName": "", "valueNameLocation": "-1:-1:-1", - "valueType": - { + "valueType": { "id": 16, "name": "bool", "nodeType": "ElementaryTypeName", @@ -197,13 +181,11 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 21, "keyName": "keyAddress", "keyNameLocation": "140:10:1", - "keyType": - { + "keyType": { "id": 19, "name": "address", "nodeType": "ElementaryTypeName", @@ -215,8 +197,7 @@ "typeDescriptions": {}, "valueName": "value", "valueNameLocation": "162:5:1", - "valueType": - { + "valueType": { "id": 20, "name": "uint256", "nodeType": "ElementaryTypeName", diff --git a/test/libsolidity/ASTJSON/modifier_definition.json b/test/libsolidity/ASTJSON/modifier_definition.json index 30ebcb7c2..485e0f0c1 100644 --- a/test/libsolidity/ASTJSON/modifier_definition.json +++ b/test/libsolidity/ASTJSON/modifier_definition.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 14 ] }, "id": 15, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,23 +16,19 @@ "contractKind": "contract", "fullyImplemented": true, "id": 14, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 14 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 5, "nodeType": "Block", "src": "32:6:1", - "statements": - [ + "statements": [ { "id": 4, "nodeType": "PlaceholderStatement", @@ -47,12 +40,10 @@ "name": "M", "nameLocation": "22:1:1", "nodeType": "ModifierDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 2, @@ -64,19 +55,16 @@ "src": "24:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", "src": "24:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -91,8 +79,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 12, "nodeType": "Block", "src": "64:2:1", @@ -102,11 +89,9 @@ "id": 13, "implemented": true, "kind": "function", - "modifiers": - [ + "modifiers": [ { - "arguments": - [ + "arguments": [ { "hexValue": "31", "id": 9, @@ -117,8 +102,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "54:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_1_by_1", "typeString": "int_const 1" }, @@ -127,12 +111,10 @@ ], "id": 10, "kind": "modifierInvocation", - "modifierName": - { + "modifierName": { "id": 8, "name": "M", - "nameLocations": - [ + "nameLocations": [ "52:1:1" ], "nodeType": "IdentifierPath", @@ -146,15 +128,13 @@ "name": "F", "nameLocation": "48:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", "parameters": [], "src": "49:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 11, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/modifier_definition_parseOnly.json b/test/libsolidity/ASTJSON/modifier_definition_parseOnly.json index f8067952a..22ed7bdc6 100644 --- a/test/libsolidity/ASTJSON/modifier_definition_parseOnly.json +++ b/test/libsolidity/ASTJSON/modifier_definition_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 15, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,16 +12,13 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 5, "nodeType": "Block", "src": "32:6:1", - "statements": - [ + "statements": [ { "id": 4, "nodeType": "PlaceholderStatement", @@ -34,12 +30,10 @@ "name": "M", "nameLocation": "22:1:1", "nodeType": "ModifierDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 2, @@ -51,8 +45,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", @@ -69,8 +62,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 12, "nodeType": "Block", "src": "64:2:1", @@ -79,11 +71,9 @@ "id": 13, "implemented": true, "kind": "function", - "modifiers": - [ + "modifiers": [ { - "arguments": - [ + "arguments": [ { "hexValue": "31", "id": 9, @@ -95,12 +85,10 @@ } ], "id": 10, - "modifierName": - { + "modifierName": { "id": 8, "name": "M", - "nameLocations": - [ + "nameLocations": [ "52:1:1" ], "nodeType": "IdentifierPath", @@ -113,15 +101,13 @@ "name": "F", "nameLocation": "48:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", "parameters": [], "src": "49:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 11, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/modifier_invocation.json b/test/libsolidity/ASTJSON/modifier_invocation.json index 30ebcb7c2..485e0f0c1 100644 --- a/test/libsolidity/ASTJSON/modifier_invocation.json +++ b/test/libsolidity/ASTJSON/modifier_invocation.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 14 ] }, "id": 15, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,23 +16,19 @@ "contractKind": "contract", "fullyImplemented": true, "id": 14, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 14 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 5, "nodeType": "Block", "src": "32:6:1", - "statements": - [ + "statements": [ { "id": 4, "nodeType": "PlaceholderStatement", @@ -47,12 +40,10 @@ "name": "M", "nameLocation": "22:1:1", "nodeType": "ModifierDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 2, @@ -64,19 +55,16 @@ "src": "24:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", "src": "24:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -91,8 +79,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 12, "nodeType": "Block", "src": "64:2:1", @@ -102,11 +89,9 @@ "id": 13, "implemented": true, "kind": "function", - "modifiers": - [ + "modifiers": [ { - "arguments": - [ + "arguments": [ { "hexValue": "31", "id": 9, @@ -117,8 +102,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "54:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_1_by_1", "typeString": "int_const 1" }, @@ -127,12 +111,10 @@ ], "id": 10, "kind": "modifierInvocation", - "modifierName": - { + "modifierName": { "id": 8, "name": "M", - "nameLocations": - [ + "nameLocations": [ "52:1:1" ], "nodeType": "IdentifierPath", @@ -146,15 +128,13 @@ "name": "F", "nameLocation": "48:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", "parameters": [], "src": "49:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 11, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/modifier_invocation_parseOnly.json b/test/libsolidity/ASTJSON/modifier_invocation_parseOnly.json index f8067952a..22ed7bdc6 100644 --- a/test/libsolidity/ASTJSON/modifier_invocation_parseOnly.json +++ b/test/libsolidity/ASTJSON/modifier_invocation_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 15, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,16 +12,13 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 5, "nodeType": "Block", "src": "32:6:1", - "statements": - [ + "statements": [ { "id": 4, "nodeType": "PlaceholderStatement", @@ -34,12 +30,10 @@ "name": "M", "nameLocation": "22:1:1", "nodeType": "ModifierDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 2, @@ -51,8 +45,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", @@ -69,8 +62,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 12, "nodeType": "Block", "src": "64:2:1", @@ -79,11 +71,9 @@ "id": 13, "implemented": true, "kind": "function", - "modifiers": - [ + "modifiers": [ { - "arguments": - [ + "arguments": [ { "hexValue": "31", "id": 9, @@ -95,12 +85,10 @@ } ], "id": 10, - "modifierName": - { + "modifierName": { "id": 8, "name": "M", - "nameLocations": - [ + "nameLocations": [ "52:1:1" ], "nodeType": "IdentifierPath", @@ -113,15 +101,13 @@ "name": "F", "nameLocation": "48:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", "parameters": [], "src": "49:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 11, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/mutability.json b/test/libsolidity/ASTJSON/mutability.json index b6318d84e..cb7ace3b3 100644 --- a/test/libsolidity/ASTJSON/mutability.json +++ b/test/libsolidity/ASTJSON/mutability.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 10 ] }, "id": 11, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,15 +16,13 @@ "contractKind": "contract", "fullyImplemented": true, "id": 10, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 10 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "functionSelector": "0dbe671f", @@ -40,25 +35,21 @@ "src": "17:27:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", "src": "17:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, - "value": - { + "value": { "hexValue": "34", "id": 2, "isConstant": false, @@ -68,8 +59,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "43:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_4_by_1", "typeString": "int_const 4" }, @@ -89,25 +79,21 @@ "src": "50:26:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 4, "name": "uint", "nodeType": "ElementaryTypeName", "src": "50:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, - "value": - { + "value": { "hexValue": "32", "id": 5, "isConstant": false, @@ -117,8 +103,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "75:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_2_by_1", "typeString": "int_const 2" }, @@ -138,25 +123,21 @@ "src": "82:17:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 7, "name": "uint", "nodeType": "ElementaryTypeName", "src": "82:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, - "value": - { + "value": { "hexValue": "33", "id": 8, "isConstant": false, @@ -166,8 +147,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "98:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_3_by_1", "typeString": "int_const 3" }, diff --git a/test/libsolidity/ASTJSON/mutability.sol b/test/libsolidity/ASTJSON/mutability.sol index 3f67c29e0..7688186e7 100644 --- a/test/libsolidity/ASTJSON/mutability.sol +++ b/test/libsolidity/ASTJSON/mutability.sol @@ -4,4 +4,5 @@ contract C uint public constant b = 2; uint public c = 3; } + // ---- diff --git a/test/libsolidity/ASTJSON/mutability_parseOnly.json b/test/libsolidity/ASTJSON/mutability_parseOnly.json index 637f8e114..74ae78f84 100644 --- a/test/libsolidity/ASTJSON/mutability_parseOnly.json +++ b/test/libsolidity/ASTJSON/mutability_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 11, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,8 +12,7 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 3, @@ -26,16 +24,14 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 1, "name": "uint", "nodeType": "ElementaryTypeName", "src": "17:4:1", "typeDescriptions": {} }, - "value": - { + "value": { "hexValue": "34", "id": 2, "kind": "number", @@ -57,16 +53,14 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 4, "name": "uint", "nodeType": "ElementaryTypeName", "src": "50:4:1", "typeDescriptions": {} }, - "value": - { + "value": { "hexValue": "32", "id": 5, "kind": "number", @@ -88,16 +82,14 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 7, "name": "uint", "nodeType": "ElementaryTypeName", "src": "82:4:1", "typeDescriptions": {} }, - "value": - { + "value": { "hexValue": "33", "id": 8, "kind": "number", diff --git a/test/libsolidity/ASTJSON/non_utf8.json b/test/libsolidity/ASTJSON/non_utf8.json index 0058e56eb..b13ab7f8a 100644 --- a/test/libsolidity/ASTJSON/non_utf8.json +++ b/test/libsolidity/ASTJSON/non_utf8.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 15 ] }, "id": 16, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,30 +16,24 @@ "contractKind": "contract", "fullyImplemented": true, "id": 15, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 15 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 13, "nodeType": "Block", "src": "33:45:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -54,19 +45,16 @@ "src": "35:15:1", "stateVariable": false, "storageLocation": "memory", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_string_memory_ptr", "typeString": "string" }, - "typeName": - { + "typeName": { "id": 3, "name": "string", "nodeType": "ElementaryTypeName", "src": "35:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_string_storage_ptr", "typeString": "string" } @@ -75,13 +63,10 @@ } ], "id": 12, - "initialValue": - { - "arguments": - [ + "initialValue": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "hexValue": "ff", "id": 9, @@ -92,17 +77,14 @@ "lValueRequested": false, "nodeType": "Literal", "src": "66:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_stringliteral_8b1a944cf13a9a1c08facb2c9e98623ef3254d2ddb48113885c3e8e97fec8db9", "typeString": "literal_string hex\"ff\"" } } ], - "expression": - { - "argumentTypes": - [ + "expression": { + "argumentTypes": [ { "typeIdentifier": "t_stringliteral_8b1a944cf13a9a1c08facb2c9e98623ef3254d2ddb48113885c3e8e97fec8db9", "typeString": "literal_string hex\"ff\"" @@ -115,13 +97,11 @@ "lValueRequested": false, "nodeType": "ElementaryTypeNameExpression", "src": "60:5:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_bytes_storage_ptr_$", "typeString": "type(bytes storage pointer)" }, - "typeName": - { + "typeName": { "id": 7, "name": "bytes", "nodeType": "ElementaryTypeName", @@ -140,17 +120,14 @@ "nodeType": "FunctionCall", "src": "60:14:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_bytes_memory_ptr", "typeString": "bytes memory" } } ], - "expression": - { - "argumentTypes": - [ + "expression": { + "argumentTypes": [ { "typeIdentifier": "t_bytes_memory_ptr", "typeString": "bytes memory" @@ -163,13 +140,11 @@ "lValueRequested": false, "nodeType": "ElementaryTypeNameExpression", "src": "53:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_type$_t_string_storage_ptr_$", "typeString": "type(string storage pointer)" }, - "typeName": - { + "typeName": { "id": 5, "name": "string", "nodeType": "ElementaryTypeName", @@ -188,8 +163,7 @@ "nodeType": "FunctionCall", "src": "53:22:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_string_memory_ptr", "typeString": "string memory" } @@ -207,15 +181,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/non_utf8_parseOnly.json b/test/libsolidity/ASTJSON/non_utf8_parseOnly.json index bbc350f96..34a99dba3 100644 --- a/test/libsolidity/ASTJSON/non_utf8_parseOnly.json +++ b/test/libsolidity/ASTJSON/non_utf8_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 16, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,23 +12,18 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 13, "nodeType": "Block", "src": "33:45:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -41,8 +35,7 @@ "stateVariable": false, "storageLocation": "memory", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 3, "name": "string", "nodeType": "ElementaryTypeName", @@ -53,13 +46,10 @@ } ], "id": 12, - "initialValue": - { - "arguments": - [ + "initialValue": { + "arguments": [ { - "arguments": - [ + "arguments": [ { "hexValue": "ff", "id": 9, @@ -69,14 +59,12 @@ "typeDescriptions": {} } ], - "expression": - { + "expression": { "id": 8, "nodeType": "ElementaryTypeNameExpression", "src": "60:5:1", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 7, "name": "bytes", "nodeType": "ElementaryTypeName", @@ -93,14 +81,12 @@ "typeDescriptions": {} } ], - "expression": - { + "expression": { "id": 6, "nodeType": "ElementaryTypeNameExpression", "src": "53:6:1", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 5, "name": "string", "nodeType": "ElementaryTypeName", @@ -128,15 +114,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/not_existing_import.sol b/test/libsolidity/ASTJSON/not_existing_import.sol index ad3c100c4..6353c7527 100644 --- a/test/libsolidity/ASTJSON/not_existing_import.sol +++ b/test/libsolidity/ASTJSON/not_existing_import.sol @@ -4,5 +4,5 @@ contract C is NotExisting.X NotExisting.SomeStruct public myStruct; constructor() {} } + // ---- -// failAfter: Parsed diff --git a/test/libsolidity/ASTJSON/not_existing_import_parseOnly.json b/test/libsolidity/ASTJSON/not_existing_import_parseOnly.json index ea08150fd..04c5c69ab 100644 --- a/test/libsolidity/ASTJSON/not_existing_import_parseOnly.json +++ b/test/libsolidity/ASTJSON/not_existing_import_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 12, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "absolutePath": "notexisting.sol", "file": "notexisting.sol", @@ -16,15 +15,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 2, "name": "NotExisting.X", - "nameLocations": - [ + "nameLocations": [ "55:11:1", "67:1:1" ], @@ -42,8 +38,7 @@ "name": "C", "nameLocation": "50:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "constant": false, "id": 6, @@ -55,16 +50,13 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 5, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 4, "name": "NotExisting.SomeStruct", - "nameLocations": - [ + "nameLocations": [ "72:11:1", "84:10:1" ], @@ -77,8 +69,7 @@ "visibility": "public" }, { - "body": - { + "body": { "id": 9, "nodeType": "Block", "src": "127:2:1", @@ -91,15 +82,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", "parameters": [], "src": "124:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 8, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/override.json b/test/libsolidity/ASTJSON/override.json index 35d36eac4..927d0d498 100644 --- a/test/libsolidity/ASTJSON/override.json +++ b/test/libsolidity/ASTJSON/override.json @@ -1,24 +1,19 @@ { "absolutePath": "a", - "exportedSymbols": - { - "A": - [ + "exportedSymbols": { + "A": [ 5 ], - "B": - [ + "B": [ 16 ], - "C": - [ + "C": [ 29 ] }, "id": 30, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -27,18 +22,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "A", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "44:2:1", @@ -52,15 +44,13 @@ "name": "faa", "nameLocation": "23:3:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "26:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], @@ -80,15 +70,12 @@ }, { "abstract": true, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 6, "name": "A", - "nameLocations": - [ + "nameLocations": [ "72:1:1" ], "nodeType": "IdentifierPath", @@ -105,16 +92,14 @@ "contractKind": "contract", "fullyImplemented": false, "id": 16, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 16, 5 ], "name": "B", "nameLocation": "67:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "functionSelector": "c2985578", "id": 10, @@ -124,15 +109,13 @@ "name": "foo", "nameLocation": "86:3:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 8, "nodeType": "ParameterList", "parameters": [], "src": "89:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 9, "nodeType": "ParameterList", "parameters": [], @@ -145,12 +128,10 @@ "visibility": "public" }, { - "baseFunctions": - [ + "baseFunctions": [ 4 ], - "body": - { + "body": { "id": 14, "nodeType": "Block", "src": "148:2:1", @@ -164,22 +145,19 @@ "name": "faa", "nameLocation": "118:3:1", "nodeType": "FunctionDefinition", - "overrides": - { + "overrides": { "id": 12, "nodeType": "OverrideSpecifier", "overrides": [], "src": "139:8:1" }, - "parameters": - { + "parameters": { "id": 11, "nodeType": "ParameterList", "parameters": [], "src": "121:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 13, "nodeType": "ParameterList", "parameters": [], @@ -199,15 +177,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 17, "name": "B", - "nameLocations": - [ + "nameLocations": [ "167:1:1" ], "nodeType": "IdentifierPath", @@ -224,8 +199,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 29, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 29, 16, 5 @@ -233,15 +207,12 @@ "name": "C", "nameLocation": "162:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "baseFunctions": - [ + "baseFunctions": [ 10 ], - "body": - { + "body": { "id": 22, "nodeType": "Block", "src": "203:3:1", @@ -255,22 +226,19 @@ "name": "foo", "nameLocation": "181:3:1", "nodeType": "FunctionDefinition", - "overrides": - { + "overrides": { "id": 20, "nodeType": "OverrideSpecifier", "overrides": [], "src": "194:8:1" }, - "parameters": - { + "parameters": { "id": 19, "nodeType": "ParameterList", "parameters": [], "src": "184:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 21, "nodeType": "ParameterList", "parameters": [], @@ -283,12 +251,10 @@ "visibility": "public" }, { - "baseFunctions": - [ + "baseFunctions": [ 15 ], - "body": - { + "body": { "id": 27, "nodeType": "Block", "src": "239:3:1", @@ -302,22 +268,19 @@ "name": "faa", "nameLocation": "217:3:1", "nodeType": "FunctionDefinition", - "overrides": - { + "overrides": { "id": 25, "nodeType": "OverrideSpecifier", "overrides": [], "src": "230:8:1" }, - "parameters": - { + "parameters": { "id": 24, "nodeType": "ParameterList", "parameters": [], "src": "220:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 26, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/override.sol b/test/libsolidity/ASTJSON/override.sol index a03244985..1aaa58c60 100644 --- a/test/libsolidity/ASTJSON/override.sol +++ b/test/libsolidity/ASTJSON/override.sol @@ -9,4 +9,5 @@ contract C is B { function foo() public override { } function faa() public override { } } + // ---- diff --git a/test/libsolidity/ASTJSON/override_parseOnly.json b/test/libsolidity/ASTJSON/override_parseOnly.json index 3a927f5f2..7b9bcd268 100644 --- a/test/libsolidity/ASTJSON/override_parseOnly.json +++ b/test/libsolidity/ASTJSON/override_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 30, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,11 +12,9 @@ "name": "A", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "44:2:1", @@ -30,15 +27,13 @@ "name": "faa", "nameLocation": "23:3:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "26:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], @@ -56,15 +51,12 @@ }, { "abstract": true, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 6, "name": "A", - "nameLocations": - [ + "nameLocations": [ "72:1:1" ], "nodeType": "IdentifierPath", @@ -81,8 +73,7 @@ "name": "B", "nameLocation": "67:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "id": 10, "implemented": false, @@ -91,15 +82,13 @@ "name": "foo", "nameLocation": "86:3:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 8, "nodeType": "ParameterList", "parameters": [], "src": "89:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 9, "nodeType": "ParameterList", "parameters": [], @@ -111,8 +100,7 @@ "visibility": "public" }, { - "body": - { + "body": { "id": 14, "nodeType": "Block", "src": "148:2:1", @@ -125,22 +113,19 @@ "name": "faa", "nameLocation": "118:3:1", "nodeType": "FunctionDefinition", - "overrides": - { + "overrides": { "id": 12, "nodeType": "OverrideSpecifier", "overrides": [], "src": "139:8:1" }, - "parameters": - { + "parameters": { "id": 11, "nodeType": "ParameterList", "parameters": [], "src": "121:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 13, "nodeType": "ParameterList", "parameters": [], @@ -158,15 +143,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 17, "name": "B", - "nameLocations": - [ + "nameLocations": [ "167:1:1" ], "nodeType": "IdentifierPath", @@ -183,11 +165,9 @@ "name": "C", "nameLocation": "162:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 22, "nodeType": "Block", "src": "203:3:1", @@ -200,22 +180,19 @@ "name": "foo", "nameLocation": "181:3:1", "nodeType": "FunctionDefinition", - "overrides": - { + "overrides": { "id": 20, "nodeType": "OverrideSpecifier", "overrides": [], "src": "194:8:1" }, - "parameters": - { + "parameters": { "id": 19, "nodeType": "ParameterList", "parameters": [], "src": "184:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 21, "nodeType": "ParameterList", "parameters": [], @@ -227,8 +204,7 @@ "visibility": "public" }, { - "body": - { + "body": { "id": 27, "nodeType": "Block", "src": "239:3:1", @@ -241,22 +217,19 @@ "name": "faa", "nameLocation": "217:3:1", "nodeType": "FunctionDefinition", - "overrides": - { + "overrides": { "id": 25, "nodeType": "OverrideSpecifier", "overrides": [], "src": "230:8:1" }, - "parameters": - { + "parameters": { "id": 24, "nodeType": "ParameterList", "parameters": [], "src": "220:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 26, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/placeholder_statement.json b/test/libsolidity/ASTJSON/placeholder_statement.json index 96a46c148..dbc9bdd1d 100644 --- a/test/libsolidity/ASTJSON/placeholder_statement.json +++ b/test/libsolidity/ASTJSON/placeholder_statement.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ] }, "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,23 +16,19 @@ "contractKind": "contract", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "24:6:1", - "statements": - [ + "statements": [ { "id": 2, "nodeType": "PlaceholderStatement", @@ -47,8 +40,7 @@ "name": "M", "nameLocation": "22:1:1", "nodeType": "ModifierDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/placeholder_statement_parseOnly.json b/test/libsolidity/ASTJSON/placeholder_statement_parseOnly.json index 8af170402..58610047d 100644 --- a/test/libsolidity/ASTJSON/placeholder_statement_parseOnly.json +++ b/test/libsolidity/ASTJSON/placeholder_statement_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,16 +12,13 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "24:6:1", - "statements": - [ + "statements": [ { "id": 2, "nodeType": "PlaceholderStatement", @@ -34,8 +30,7 @@ "name": "M", "nameLocation": "22:1:1", "nodeType": "ModifierDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/pragma_experimental_solidity_parseOnly.json b/test/libsolidity/ASTJSON/pragma_experimental_solidity_parseOnly.json index b1ac937a2..a962a1cc1 100644 --- a/test/libsolidity/ASTJSON/pragma_experimental_solidity_parseOnly.json +++ b/test/libsolidity/ASTJSON/pragma_experimental_solidity_parseOnly.json @@ -3,12 +3,10 @@ "experimentalSolidity": true, "id": 2, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 1, - "literals": - [ + "literals": [ "experimental", "solidity" ], diff --git a/test/libsolidity/ASTJSON/receive_ether.json b/test/libsolidity/ASTJSON/receive_ether.json index 279049399..d02c84a49 100644 --- a/test/libsolidity/ASTJSON/receive_ether.json +++ b/test/libsolidity/ASTJSON/receive_ether.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 5 ] }, "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,18 +16,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "42:5:1", @@ -43,15 +37,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "22:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/receive_ether.sol b/test/libsolidity/ASTJSON/receive_ether.sol index 1e59dc131..f75a43b2d 100644 --- a/test/libsolidity/ASTJSON/receive_ether.sol +++ b/test/libsolidity/ASTJSON/receive_ether.sol @@ -2,4 +2,5 @@ contract C { receive() external payable { } } + // ---- diff --git a/test/libsolidity/ASTJSON/receive_ether_parseOnly.json b/test/libsolidity/ASTJSON/receive_ether_parseOnly.json index f9aede155..9f0c4f60a 100644 --- a/test/libsolidity/ASTJSON/receive_ether_parseOnly.json +++ b/test/libsolidity/ASTJSON/receive_ether_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 6, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,11 +12,9 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "42:5:1", @@ -30,15 +27,13 @@ "name": "", "nameLocation": "-1:-1:-1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "22:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/short_type_name.json b/test/libsolidity/ASTJSON/short_type_name.json index 1c1138cba..f5b8bcf06 100644 --- a/test/libsolidity/ASTJSON/short_type_name.json +++ b/test/libsolidity/ASTJSON/short_type_name.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "c": - [ + "exportedSymbols": { + "c": [ 11 ] }, "id": 12, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,30 +16,24 @@ "contractKind": "contract", "fullyImplemented": true, "id": 11, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 11 ], "name": "c", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 9, "nodeType": "Block", "src": "33:20:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 7 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 7, @@ -54,21 +45,17 @@ "src": "35:15:1", "stateVariable": false, "storageLocation": "memory", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_uint256_$dyn_memory_ptr", "typeString": "uint256[]" }, - "typeName": - { - "baseType": - { + "typeName": { + "baseType": { "id": 5, "name": "uint", "nodeType": "ElementaryTypeName", "src": "35:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -76,8 +63,7 @@ "id": 6, "nodeType": "ArrayTypeName", "src": "35:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_uint256_$dyn_storage_ptr", "typeString": "uint256[]" } @@ -99,15 +85,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/short_type_name_parseOnly.json b/test/libsolidity/ASTJSON/short_type_name_parseOnly.json index 3c4acfa77..27e1919c2 100644 --- a/test/libsolidity/ASTJSON/short_type_name_parseOnly.json +++ b/test/libsolidity/ASTJSON/short_type_name_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 12, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,23 +12,18 @@ "name": "c", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 9, "nodeType": "Block", "src": "33:20:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 7 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 7, @@ -41,10 +35,8 @@ "stateVariable": false, "storageLocation": "memory", "typeDescriptions": {}, - "typeName": - { - "baseType": - { + "typeName": { + "baseType": { "id": 5, "name": "uint", "nodeType": "ElementaryTypeName", @@ -72,15 +64,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/short_type_name_ref.json b/test/libsolidity/ASTJSON/short_type_name_ref.json index 447b1e5b7..59ce1f39d 100644 --- a/test/libsolidity/ASTJSON/short_type_name_ref.json +++ b/test/libsolidity/ASTJSON/short_type_name_ref.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "c": - [ + "exportedSymbols": { + "c": [ 12 ] }, "id": 13, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,30 +16,24 @@ "contractKind": "contract", "fullyImplemented": true, "id": 12, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 12 ], "name": "c", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 10, "nodeType": "Block", "src": "33:25:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 8 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 8, @@ -54,23 +45,18 @@ "src": "35:20:1", "stateVariable": false, "storageLocation": "memory", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_array$_t_uint256_$dyn_memory_ptr_$dyn_memory_ptr", "typeString": "uint256[][]" }, - "typeName": - { - "baseType": - { - "baseType": - { + "typeName": { + "baseType": { + "baseType": { "id": 5, "name": "uint", "nodeType": "ElementaryTypeName", "src": "35:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -78,8 +64,7 @@ "id": 6, "nodeType": "ArrayTypeName", "src": "35:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_uint256_$dyn_storage_ptr", "typeString": "uint256[]" } @@ -87,8 +72,7 @@ "id": 7, "nodeType": "ArrayTypeName", "src": "35:8:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_array$_t_array$_t_uint256_$dyn_storage_$dyn_storage_ptr", "typeString": "uint256[][]" } @@ -110,15 +94,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/short_type_name_ref_parseOnly.json b/test/libsolidity/ASTJSON/short_type_name_ref_parseOnly.json index 07c782d47..9a7e6fccf 100644 --- a/test/libsolidity/ASTJSON/short_type_name_ref_parseOnly.json +++ b/test/libsolidity/ASTJSON/short_type_name_ref_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 13, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,23 +12,18 @@ "name": "c", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 10, "nodeType": "Block", "src": "33:25:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 8 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 8, @@ -41,12 +35,9 @@ "stateVariable": false, "storageLocation": "memory", "typeDescriptions": {}, - "typeName": - { - "baseType": - { - "baseType": - { + "typeName": { + "baseType": { + "baseType": { "id": 5, "name": "uint", "nodeType": "ElementaryTypeName", @@ -79,15 +70,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/smoke.json b/test/libsolidity/ASTJSON/smoke.json index d3b114bbc..d1fc5b13b 100644 --- a/test/libsolidity/ASTJSON/smoke.json +++ b/test/libsolidity/ASTJSON/smoke.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 1 ] }, "id": 2, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,8 +16,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 1, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 1 ], "name": "C", diff --git a/test/libsolidity/ASTJSON/smoke_parseOnly.json b/test/libsolidity/ASTJSON/smoke_parseOnly.json index 1160fea91..22b597ce9 100644 --- a/test/libsolidity/ASTJSON/smoke_parseOnly.json +++ b/test/libsolidity/ASTJSON/smoke_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 2, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], diff --git a/test/libsolidity/ASTJSON/source_location.json b/test/libsolidity/ASTJSON/source_location.json index caeaf027a..526069063 100644 --- a/test/libsolidity/ASTJSON/source_location.json +++ b/test/libsolidity/ASTJSON/source_location.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 12 ] }, "id": 13, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,30 +16,24 @@ "contractKind": "contract", "fullyImplemented": true, "id": 12, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 12 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 10, "nodeType": "Block", "src": "33:20:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -54,19 +45,16 @@ "src": "35:6:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 3, "name": "uint", "nodeType": "ElementaryTypeName", "src": "35:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -75,8 +63,7 @@ } ], "id": 6, - "initialValue": - { + "initialValue": { "hexValue": "32", "id": 5, "isConstant": false, @@ -86,8 +73,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "44:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_rational_2_by_1", "typeString": "int_const 2" }, @@ -97,8 +83,7 @@ "src": "35:10:1" }, { - "expression": - { + "expression": { "id": 8, "isConstant": false, "isLValue": false, @@ -108,22 +93,19 @@ "operator": "++", "prefix": false, "src": "47:3:1", - "subExpression": - { + "subExpression": { "id": 7, "name": "x", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 4, "src": "47:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -142,15 +124,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/source_location_parseOnly.json b/test/libsolidity/ASTJSON/source_location_parseOnly.json index ec25111bd..877092a04 100644 --- a/test/libsolidity/ASTJSON/source_location_parseOnly.json +++ b/test/libsolidity/ASTJSON/source_location_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 13, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,23 +12,18 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 10, "nodeType": "Block", "src": "33:20:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -41,8 +35,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 3, "name": "uint", "nodeType": "ElementaryTypeName", @@ -53,8 +46,7 @@ } ], "id": 6, - "initialValue": - { + "initialValue": { "hexValue": "32", "id": 5, "kind": "number", @@ -67,15 +59,13 @@ "src": "35:10:1" }, { - "expression": - { + "expression": { "id": 8, "nodeType": "UnaryOperation", "operator": "++", "prefix": false, "src": "47:3:1", - "subExpression": - { + "subExpression": { "id": 7, "name": "x", "nodeType": "Identifier", @@ -98,15 +88,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/string.json b/test/libsolidity/ASTJSON/string.json index c7706e3bf..d4b37e2e1 100644 --- a/test/libsolidity/ASTJSON/string.json +++ b/test/libsolidity/ASTJSON/string.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 9 ] }, "id": 10, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,30 +16,24 @@ "contractKind": "contract", "fullyImplemented": true, "id": 9, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 9 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 7, "nodeType": "Block", "src": "33:36:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -54,19 +45,16 @@ "src": "35:15:1", "stateVariable": false, "storageLocation": "memory", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_string_memory_ptr", "typeString": "string" }, - "typeName": - { + "typeName": { "id": 3, "name": "string", "nodeType": "ElementaryTypeName", "src": "35:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_string_storage_ptr", "typeString": "string" } @@ -75,8 +63,7 @@ } ], "id": 6, - "initialValue": - { + "initialValue": { "hexValue": "48656c6c6f20576f726c64", "id": 5, "isConstant": false, @@ -86,8 +73,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "53:13:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_stringliteral_592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba", "typeString": "literal_string \"Hello World\"" }, @@ -106,15 +92,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/string_parseOnly.json b/test/libsolidity/ASTJSON/string_parseOnly.json index 5f97eb1f9..4f8006e57 100644 --- a/test/libsolidity/ASTJSON/string_parseOnly.json +++ b/test/libsolidity/ASTJSON/string_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 10, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,23 +12,18 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 7, "nodeType": "Block", "src": "33:36:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -41,8 +35,7 @@ "stateVariable": false, "storageLocation": "memory", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 3, "name": "string", "nodeType": "ElementaryTypeName", @@ -53,8 +46,7 @@ } ], "id": 6, - "initialValue": - { + "initialValue": { "hexValue": "48656c6c6f20576f726c64", "id": 5, "kind": "string", @@ -75,15 +67,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/struct_natspec.json b/test/libsolidity/ASTJSON/struct_natspec.json index d8b38a803..0a17909df 100644 --- a/test/libsolidity/ASTJSON/struct_natspec.json +++ b/test/libsolidity/ASTJSON/struct_natspec.json @@ -1,28 +1,23 @@ { "absolutePath": "a", - "exportedSymbols": - { - "Example": - [ + "exportedSymbols": { + "Example": [ 8 ] }, "id": 9, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "canonicalName": "Example", - "documentation": - { + "documentation": { "id": 1, "nodeType": "StructuredDocumentation", "src": "0:112:1", "text": "@title example of title\n @author example of author\n @notice example of notice\n @dev example of dev" }, "id": 8, - "members": - [ + "members": [ { "constant": false, "id": 3, @@ -34,19 +29,16 @@ "src": "133:11:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_string_storage_ptr", "typeString": "string" }, - "typeName": - { + "typeName": { "id": 2, "name": "string", "nodeType": "ElementaryTypeName", "src": "133:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_string_storage_ptr", "typeString": "string" } @@ -64,19 +56,16 @@ "src": "150:10:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" }, - "typeName": - { + "typeName": { "id": 4, "name": "bool", "nodeType": "ElementaryTypeName", "src": "150:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } @@ -94,19 +83,16 @@ "src": "166:13:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 6, "name": "uint256", "nodeType": "ElementaryTypeName", "src": "166:7:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } diff --git a/test/libsolidity/ASTJSON/struct_natspec_parseOnly.json b/test/libsolidity/ASTJSON/struct_natspec_parseOnly.json index b80aaf377..6ba465580 100644 --- a/test/libsolidity/ASTJSON/struct_natspec_parseOnly.json +++ b/test/libsolidity/ASTJSON/struct_natspec_parseOnly.json @@ -2,19 +2,16 @@ "absolutePath": "a", "id": 9, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { - "documentation": - { + "documentation": { "id": 1, "nodeType": "StructuredDocumentation", "src": "0:112:1", "text": "@title example of title\n @author example of author\n @notice example of notice\n @dev example of dev" }, "id": 8, - "members": - [ + "members": [ { "constant": false, "id": 3, @@ -26,8 +23,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 2, "name": "string", "nodeType": "ElementaryTypeName", @@ -47,8 +43,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 4, "name": "bool", "nodeType": "ElementaryTypeName", @@ -68,8 +63,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 6, "name": "uint256", "nodeType": "ElementaryTypeName", diff --git a/test/libsolidity/ASTJSON/two_base_functions.json b/test/libsolidity/ASTJSON/two_base_functions.json index 0ed997a32..132a7a907 100644 --- a/test/libsolidity/ASTJSON/two_base_functions.json +++ b/test/libsolidity/ASTJSON/two_base_functions.json @@ -1,24 +1,19 @@ { "absolutePath": "a", - "exportedSymbols": - { - "A": - [ + "exportedSymbols": { + "A": [ 5 ], - "B": - [ + "B": [ 10 ], - "C": - [ + "C": [ 22 ] }, "id": 23, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -27,18 +22,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 5, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 5 ], "name": "A", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "45:2:1", @@ -52,15 +44,13 @@ "name": "f", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], @@ -86,18 +76,15 @@ "contractKind": "contract", "fullyImplemented": true, "id": 10, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 10 ], "name": "B", "nameLocation": "59:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 8, "nodeType": "Block", "src": "95:2:1", @@ -111,15 +98,13 @@ "name": "f", "nameLocation": "76:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 6, "nodeType": "ParameterList", "parameters": [], "src": "77:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 7, "nodeType": "ParameterList", "parameters": [], @@ -139,15 +124,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 11, "name": "A", - "nameLocations": - [ + "nameLocations": [ "114:1:1" ], "nodeType": "IdentifierPath", @@ -159,12 +141,10 @@ "src": "114:1:1" }, { - "baseName": - { + "baseName": { "id": 13, "name": "B", - "nameLocations": - [ + "nameLocations": [ "117:1:1" ], "nodeType": "IdentifierPath", @@ -181,8 +161,7 @@ "contractKind": "contract", "fullyImplemented": true, "id": 22, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 22, 10, 5 @@ -190,16 +169,13 @@ "name": "C", "nameLocation": "109:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "baseFunctions": - [ + "baseFunctions": [ 4, 9 ], - "body": - { + "body": { "id": 20, "nodeType": "Block", "src": "160:2:1", @@ -213,17 +189,14 @@ "name": "f", "nameLocation": "134:1:1", "nodeType": "FunctionDefinition", - "overrides": - { + "overrides": { "id": 18, "nodeType": "OverrideSpecifier", - "overrides": - [ + "overrides": [ { "id": 16, "name": "A", - "nameLocations": - [ + "nameLocations": [ "154:1:1" ], "nodeType": "IdentifierPath", @@ -233,8 +206,7 @@ { "id": 17, "name": "B", - "nameLocations": - [ + "nameLocations": [ "157:1:1" ], "nodeType": "IdentifierPath", @@ -244,15 +216,13 @@ ], "src": "145:14:1" }, - "parameters": - { + "parameters": { "id": 15, "nodeType": "ParameterList", "parameters": [], "src": "135:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 19, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/two_base_functions.sol b/test/libsolidity/ASTJSON/two_base_functions.sol index 0a00bcc14..89c8e207a 100644 --- a/test/libsolidity/ASTJSON/two_base_functions.sol +++ b/test/libsolidity/ASTJSON/two_base_functions.sol @@ -7,4 +7,5 @@ contract B { contract C is A, B { function f() public override(A, B) {} } + // ---- diff --git a/test/libsolidity/ASTJSON/two_base_functions_parseOnly.json b/test/libsolidity/ASTJSON/two_base_functions_parseOnly.json index e448be836..2e9691ac9 100644 --- a/test/libsolidity/ASTJSON/two_base_functions_parseOnly.json +++ b/test/libsolidity/ASTJSON/two_base_functions_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 23, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,11 +12,9 @@ "name": "A", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 3, "nodeType": "Block", "src": "45:2:1", @@ -30,15 +27,13 @@ "name": "f", "nameLocation": "26:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "27:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], @@ -63,11 +58,9 @@ "name": "B", "nameLocation": "59:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 8, "nodeType": "Block", "src": "95:2:1", @@ -80,15 +73,13 @@ "name": "f", "nameLocation": "76:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 6, "nodeType": "ParameterList", "parameters": [], "src": "77:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 7, "nodeType": "ParameterList", "parameters": [], @@ -106,15 +97,12 @@ }, { "abstract": false, - "baseContracts": - [ + "baseContracts": [ { - "baseName": - { + "baseName": { "id": 11, "name": "A", - "nameLocations": - [ + "nameLocations": [ "114:1:1" ], "nodeType": "IdentifierPath", @@ -125,12 +113,10 @@ "src": "114:1:1" }, { - "baseName": - { + "baseName": { "id": 13, "name": "B", - "nameLocations": - [ + "nameLocations": [ "117:1:1" ], "nodeType": "IdentifierPath", @@ -147,11 +133,9 @@ "name": "C", "nameLocation": "109:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 20, "nodeType": "Block", "src": "160:2:1", @@ -164,17 +148,14 @@ "name": "f", "nameLocation": "134:1:1", "nodeType": "FunctionDefinition", - "overrides": - { + "overrides": { "id": 18, "nodeType": "OverrideSpecifier", - "overrides": - [ + "overrides": [ { "id": 16, "name": "A", - "nameLocations": - [ + "nameLocations": [ "154:1:1" ], "nodeType": "IdentifierPath", @@ -183,8 +164,7 @@ { "id": 17, "name": "B", - "nameLocations": - [ + "nameLocations": [ "157:1:1" ], "nodeType": "IdentifierPath", @@ -193,15 +173,13 @@ ], "src": "145:14:1" }, - "parameters": - { + "parameters": { "id": 15, "nodeType": "ParameterList", "parameters": [], "src": "135:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 19, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/unicode.json b/test/libsolidity/ASTJSON/unicode.json index 0ff1426f1..2521e690e 100644 --- a/test/libsolidity/ASTJSON/unicode.json +++ b/test/libsolidity/ASTJSON/unicode.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 9 ] }, "id": 10, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,30 +16,24 @@ "contractKind": "contract", "fullyImplemented": true, "id": 9, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 9 ], "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 7, "nodeType": "Block", "src": "33:42:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -54,19 +45,16 @@ "src": "35:15:1", "stateVariable": false, "storageLocation": "memory", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_string_memory_ptr", "typeString": "string" }, - "typeName": - { + "typeName": { "id": 3, "name": "string", "nodeType": "ElementaryTypeName", "src": "35:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_string_storage_ptr", "typeString": "string" } @@ -75,8 +63,7 @@ } ], "id": 6, - "initialValue": - { + "initialValue": { "hexValue": "48656c6c6f20f09f9883", "id": 5, "isConstant": false, @@ -86,8 +73,7 @@ "lValueRequested": false, "nodeType": "Literal", "src": "53:19:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_stringliteral_cd7a99177cebb3d14b8cc54e313dbf76867c71cd6fbb9a33ce3870dc80e9992b", "typeString": "literal_string hex\"48656c6c6f20f09f9883\"" }, @@ -106,15 +92,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/unicode_parseOnly.json b/test/libsolidity/ASTJSON/unicode_parseOnly.json index c8fb780c4..0567c08a0 100644 --- a/test/libsolidity/ASTJSON/unicode_parseOnly.json +++ b/test/libsolidity/ASTJSON/unicode_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 10, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,23 +12,18 @@ "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 7, "nodeType": "Block", "src": "33:42:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 4 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 4, @@ -41,8 +35,7 @@ "stateVariable": false, "storageLocation": "memory", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 3, "name": "string", "nodeType": "ElementaryTypeName", @@ -53,8 +46,7 @@ } ], "id": 6, - "initialValue": - { + "initialValue": { "hexValue": "48656c6c6f20f09f9883", "id": 5, "kind": "unicodeString", @@ -75,15 +67,13 @@ "name": "f", "nameLocation": "22:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "23:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/used_errors.json b/test/libsolidity/ASTJSON/used_errors.json index cff59a5ef..9db7b6a98 100644 --- a/test/libsolidity/ASTJSON/used_errors.json +++ b/test/libsolidity/ASTJSON/used_errors.json @@ -1,32 +1,26 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 19 ], - "X": - [ + "X": [ 2 ], - "f": - [ + "f": [ 9 ] }, "id": 20, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "errorSelector": "c1599bd9", "id": 2, "name": "X", "nameLocation": "6:1:1", "nodeType": "ErrorDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], @@ -35,19 +29,15 @@ "src": "0:10:1" }, { - "body": - { + "body": { "id": 8, "nodeType": "Block", "src": "29:15:1", - "statements": - [ + "statements": [ { - "errorCall": - { + "errorCall": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], "id": 5, "name": "X", @@ -55,8 +45,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 2, "src": "38:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_error_pure$__$returns$_t_error_$", "typeString": "function () pure returns (error)" } @@ -72,8 +61,7 @@ "nodeType": "FunctionCall", "src": "38:3:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_error", "typeString": "error" } @@ -91,15 +79,13 @@ "name": "f", "nameLocation": "20:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], "src": "21:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], @@ -119,23 +105,20 @@ "contractKind": "contract", "fullyImplemented": true, "id": 19, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 19 ], "name": "C", "nameLocation": "54:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "errorSelector": "2bc80f3a", "id": 11, "name": "T", "nameLocation": "68:1:1", "nodeType": "ErrorDefinition", - "parameters": - { + "parameters": { "id": 10, "nodeType": "ParameterList", "parameters": [], @@ -144,19 +127,15 @@ "src": "62:10:1" }, { - "body": - { + "body": { "id": 17, "nodeType": "Block", "src": "97:8:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "argumentTypes": [], "id": 14, "name": "f", @@ -164,8 +143,7 @@ "overloadedDeclarations": [], "referencedDeclaration": 9, "src": "99:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_function_internal_pure$__$returns$__$", "typeString": "function () pure" } @@ -181,8 +159,7 @@ "nodeType": "FunctionCall", "src": "99:3:1", "tryCall": false, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } @@ -201,15 +178,13 @@ "name": "h", "nameLocation": "86:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 12, "nodeType": "ParameterList", "parameters": [], "src": "87:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 13, "nodeType": "ParameterList", "parameters": [], @@ -224,8 +199,7 @@ ], "scope": 20, "src": "45:62:1", - "usedErrors": - [ + "usedErrors": [ 2, 11 ], diff --git a/test/libsolidity/ASTJSON/used_errors.sol b/test/libsolidity/ASTJSON/used_errors.sol index 97f7a27f4..24c03982f 100644 --- a/test/libsolidity/ASTJSON/used_errors.sol +++ b/test/libsolidity/ASTJSON/used_errors.sol @@ -4,4 +4,5 @@ contract C { error T(); function h() public { f(); } } + // ---- diff --git a/test/libsolidity/ASTJSON/used_errors_parseOnly.json b/test/libsolidity/ASTJSON/used_errors_parseOnly.json index 115ea2aee..402291f29 100644 --- a/test/libsolidity/ASTJSON/used_errors_parseOnly.json +++ b/test/libsolidity/ASTJSON/used_errors_parseOnly.json @@ -2,15 +2,13 @@ "absolutePath": "a", "id": 20, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 2, "name": "X", "nameLocation": "6:1:1", "nodeType": "ErrorDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], @@ -19,19 +17,15 @@ "src": "0:10:1" }, { - "body": - { + "body": { "id": 8, "nodeType": "Block", "src": "29:15:1", - "statements": - [ + "statements": [ { - "errorCall": - { + "errorCall": { "arguments": [], - "expression": - { + "expression": { "id": 5, "name": "X", "nodeType": "Identifier", @@ -60,15 +54,13 @@ "name": "f", "nameLocation": "20:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 3, "nodeType": "ParameterList", "parameters": [], "src": "21:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 4, "nodeType": "ParameterList", "parameters": [], @@ -88,15 +80,13 @@ "name": "C", "nameLocation": "54:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "id": 11, "name": "T", "nameLocation": "68:1:1", "nodeType": "ErrorDefinition", - "parameters": - { + "parameters": { "id": 10, "nodeType": "ParameterList", "parameters": [], @@ -105,19 +95,15 @@ "src": "62:10:1" }, { - "body": - { + "body": { "id": 17, "nodeType": "Block", "src": "97:8:1", - "statements": - [ + "statements": [ { - "expression": - { + "expression": { "arguments": [], - "expression": - { + "expression": { "id": 14, "name": "f", "nodeType": "Identifier", @@ -146,15 +132,13 @@ "name": "h", "nameLocation": "86:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 12, "nodeType": "ParameterList", "parameters": [], "src": "87:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 13, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/userDefinedValueType.json b/test/libsolidity/ASTJSON/userDefinedValueType.json index adf1172f0..51f8ee553 100644 --- a/test/libsolidity/ASTJSON/userDefinedValueType.json +++ b/test/libsolidity/ASTJSON/userDefinedValueType.json @@ -1,28 +1,22 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 27 ], - "MyAddress": - [ + "MyAddress": [ 2 ], - "MyUInt": - [ + "MyUInt": [ 4 ], - "f": - [ + "f": [ 16 ] }, "id": 28, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "canonicalName": "MyAddress", "id": 2, @@ -30,15 +24,13 @@ "nameLocation": "5:9:1", "nodeType": "UserDefinedValueTypeDefinition", "src": "0:26:1", - "underlyingType": - { + "underlyingType": { "id": 1, "name": "address", "nodeType": "ElementaryTypeName", "src": "18:7:1", "stateMutability": "nonpayable", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } @@ -51,34 +43,28 @@ "nameLocation": "32:6:1", "nodeType": "UserDefinedValueTypeDefinition", "src": "27:20:1", - "underlyingType": - { + "underlyingType": { "id": 3, "name": "uint", "nodeType": "ElementaryTypeName", "src": "42:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } } }, { - "body": - { + "body": { "id": 15, "nodeType": "Block", "src": "61:34:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 9 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 9, @@ -90,21 +76,17 @@ "src": "67:11:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_MyAddress_$2", "typeString": "MyAddress" }, - "typeName": - { + "typeName": { "id": 8, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 7, "name": "MyAddress", - "nameLocations": - [ + "nameLocations": [ "67:9:1" ], "nodeType": "IdentifierPath", @@ -113,8 +95,7 @@ }, "referencedDeclaration": 2, "src": "67:9:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_MyAddress_$2", "typeString": "MyAddress" } @@ -127,12 +108,10 @@ "src": "67:11:1" }, { - "assignments": - [ + "assignments": [ 13 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 13, @@ -144,21 +123,17 @@ "src": "84:8:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_MyUInt_$4", "typeString": "MyUInt" }, - "typeName": - { + "typeName": { "id": 12, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 11, "name": "MyUInt", - "nameLocations": - [ + "nameLocations": [ "84:6:1" ], "nodeType": "IdentifierPath", @@ -167,8 +142,7 @@ }, "referencedDeclaration": 4, "src": "84:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_MyUInt_$4", "typeString": "MyUInt" } @@ -189,15 +163,13 @@ "name": "f", "nameLocation": "57:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 5, "nodeType": "ParameterList", "parameters": [], "src": "58:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 6, "nodeType": "ParameterList", "parameters": [], @@ -217,15 +189,13 @@ "contractKind": "contract", "fullyImplemented": true, "id": 27, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 27 ], "name": "C", "nameLocation": "105:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "canonicalName": "C.MyAddress", "id": 18, @@ -233,15 +203,13 @@ "nameLocation": "118:9:1", "nodeType": "UserDefinedValueTypeDefinition", "src": "113:26:1", - "underlyingType": - { + "underlyingType": { "id": 17, "name": "address", "nodeType": "ElementaryTypeName", "src": "131:7:1", "stateMutability": "nonpayable", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } @@ -254,14 +222,12 @@ "nameLocation": "149:6:1", "nodeType": "UserDefinedValueTypeDefinition", "src": "144:20:1", - "underlyingType": - { + "underlyingType": { "id": 19, "name": "uint", "nodeType": "ElementaryTypeName", "src": "159:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -279,26 +245,21 @@ "src": "169:37:1", "stateVariable": true, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_userDefinedValueType$_MyAddress_$18_$_t_userDefinedValueType$_MyUInt_$20_$", "typeString": "mapping(C.MyAddress => C.MyUInt)" }, - "typeName": - { + "typeName": { "id": 25, "keyName": "", "keyNameLocation": "-1:-1:-1", - "keyType": - { + "keyType": { "id": 22, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 21, "name": "MyAddress", - "nameLocations": - [ + "nameLocations": [ "177:9:1" ], "nodeType": "IdentifierPath", @@ -307,31 +268,26 @@ }, "referencedDeclaration": 18, "src": "177:9:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_MyAddress_$18", "typeString": "C.MyAddress" } }, "nodeType": "Mapping", "src": "169:28:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_mapping$_t_userDefinedValueType$_MyAddress_$18_$_t_userDefinedValueType$_MyUInt_$20_$", "typeString": "mapping(C.MyAddress => C.MyUInt)" }, "valueName": "", "valueNameLocation": "-1:-1:-1", - "valueType": - { + "valueType": { "id": 24, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 23, "name": "MyUInt", - "nameLocations": - [ + "nameLocations": [ "190:6:1" ], "nodeType": "IdentifierPath", @@ -340,8 +296,7 @@ }, "referencedDeclaration": 20, "src": "190:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_MyUInt_$20", "typeString": "C.MyUInt" } diff --git a/test/libsolidity/ASTJSON/userDefinedValueType.sol b/test/libsolidity/ASTJSON/userDefinedValueType.sol index d5ef2e00b..f1124f8cd 100644 --- a/test/libsolidity/ASTJSON/userDefinedValueType.sol +++ b/test/libsolidity/ASTJSON/userDefinedValueType.sol @@ -9,4 +9,5 @@ contract C { type MyUInt is uint; mapping(MyAddress => MyUInt) public m; } + // ---- diff --git a/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json b/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json index 90e48a982..c3bb96ddd 100644 --- a/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json +++ b/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json @@ -2,16 +2,14 @@ "absolutePath": "a", "id": 28, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "id": 2, "name": "MyAddress", "nameLocation": "5:9:1", "nodeType": "UserDefinedValueTypeDefinition", "src": "0:26:1", - "underlyingType": - { + "underlyingType": { "id": 1, "name": "address", "nodeType": "ElementaryTypeName", @@ -26,8 +24,7 @@ "nameLocation": "32:6:1", "nodeType": "UserDefinedValueTypeDefinition", "src": "27:20:1", - "underlyingType": - { + "underlyingType": { "id": 3, "name": "uint", "nodeType": "ElementaryTypeName", @@ -36,20 +33,16 @@ } }, { - "body": - { + "body": { "id": 15, "nodeType": "Block", "src": "61:34:1", - "statements": - [ + "statements": [ { - "assignments": - [ + "assignments": [ 9 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 9, @@ -61,16 +54,13 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 8, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 7, "name": "MyAddress", - "nameLocations": - [ + "nameLocations": [ "67:9:1" ], "nodeType": "IdentifierPath", @@ -87,12 +77,10 @@ "src": "67:11:1" }, { - "assignments": - [ + "assignments": [ 13 ], - "declarations": - [ + "declarations": [ { "constant": false, "id": 13, @@ -104,16 +92,13 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 12, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 11, "name": "MyUInt", - "nameLocations": - [ + "nameLocations": [ "84:6:1" ], "nodeType": "IdentifierPath", @@ -138,15 +123,13 @@ "name": "f", "nameLocation": "57:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 5, "nodeType": "ParameterList", "parameters": [], "src": "58:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 6, "nodeType": "ParameterList", "parameters": [], @@ -166,16 +149,14 @@ "name": "C", "nameLocation": "105:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "id": 18, "name": "MyAddress", "nameLocation": "118:9:1", "nodeType": "UserDefinedValueTypeDefinition", "src": "113:26:1", - "underlyingType": - { + "underlyingType": { "id": 17, "name": "address", "nodeType": "ElementaryTypeName", @@ -190,8 +171,7 @@ "nameLocation": "149:6:1", "nodeType": "UserDefinedValueTypeDefinition", "src": "144:20:1", - "underlyingType": - { + "underlyingType": { "id": 19, "name": "uint", "nodeType": "ElementaryTypeName", @@ -210,21 +190,17 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 25, "keyName": "", "keyNameLocation": "-1:-1:-1", - "keyType": - { + "keyType": { "id": 22, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 21, "name": "MyAddress", - "nameLocations": - [ + "nameLocations": [ "177:9:1" ], "nodeType": "IdentifierPath", @@ -238,16 +214,13 @@ "typeDescriptions": {}, "valueName": "", "valueNameLocation": "-1:-1:-1", - "valueType": - { + "valueType": { "id": 24, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 23, "name": "MyUInt", - "nameLocations": - [ + "nameLocations": [ "190:6:1" ], "nodeType": "IdentifierPath", diff --git a/test/libsolidity/ASTJSON/user_defined_operator.json b/test/libsolidity/ASTJSON/user_defined_operator.json index ed72de49d..b39d2e07e 100644 --- a/test/libsolidity/ASTJSON/user_defined_operator.json +++ b/test/libsolidity/ASTJSON/user_defined_operator.json @@ -1,28 +1,22 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 49 ], - "I8": - [ + "I8": [ 2 ], - "sub": - [ + "sub": [ 20 ], - "unsub": - [ + "unsub": [ 30 ] }, "id": 50, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "canonicalName": "I8", "id": 2, @@ -30,29 +24,24 @@ "nameLocation": "5:2:1", "nodeType": "UserDefinedValueTypeDefinition", "src": "0:16:1", - "underlyingType": - { + "underlyingType": { "id": 1, "name": "int8", "nodeType": "ElementaryTypeName", "src": "11:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_int8", "typeString": "int8" } } }, { - "functionList": - [ + "functionList": [ { - "definition": - { + "definition": { "id": 3, "name": "sub", - "nameLocations": - [ + "nameLocations": [ "24:3:1" ], "nodeType": "IdentifierPath", @@ -62,12 +51,10 @@ "operator": "-" }, { - "definition": - { + "definition": { "id": 4, "name": "unsub", - "nameLocations": - [ + "nameLocations": [ "34:5:1" ], "nodeType": "IdentifierPath", @@ -81,16 +68,13 @@ "id": 7, "nodeType": "UsingForDirective", "src": "17:43:1", - "typeName": - { + "typeName": { "id": 6, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 5, "name": "I8", - "nameLocations": - [ + "nameLocations": [ "50:2:1" ], "nodeType": "IdentifierPath", @@ -99,16 +83,14 @@ }, "referencedDeclaration": 2, "src": "50:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } } }, { - "body": - { + "body": { "id": 19, "nodeType": "Block", "src": "100:2:1", @@ -121,12 +103,10 @@ "name": "sub", "nameLocation": "70:3:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 14, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 10, @@ -138,21 +118,17 @@ "src": "74:2:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" }, - "typeName": - { + "typeName": { "id": 9, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 8, "name": "I8", - "nameLocations": - [ + "nameLocations": [ "74:2:1" ], "nodeType": "IdentifierPath", @@ -161,8 +137,7 @@ }, "referencedDeclaration": 2, "src": "74:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } @@ -180,21 +155,17 @@ "src": "78:2:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" }, - "typeName": - { + "typeName": { "id": 12, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 11, "name": "I8", - "nameLocations": - [ + "nameLocations": [ "78:2:1" ], "nodeType": "IdentifierPath", @@ -203,8 +174,7 @@ }, "referencedDeclaration": 2, "src": "78:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } @@ -214,12 +184,10 @@ ], "src": "73:8:1" }, - "returnParameters": - { + "returnParameters": { "id": 18, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 17, @@ -231,21 +199,17 @@ "src": "96:2:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" }, - "typeName": - { + "typeName": { "id": 16, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 15, "name": "I8", - "nameLocations": - [ + "nameLocations": [ "96:2:1" ], "nodeType": "IdentifierPath", @@ -254,8 +218,7 @@ }, "referencedDeclaration": 2, "src": "96:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } @@ -272,8 +235,7 @@ "visibility": "internal" }, { - "body": - { + "body": { "id": 29, "nodeType": "Block", "src": "140:2:1", @@ -286,12 +248,10 @@ "name": "unsub", "nameLocation": "112:5:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 24, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 23, @@ -303,21 +263,17 @@ "src": "118:2:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" }, - "typeName": - { + "typeName": { "id": 22, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 21, "name": "I8", - "nameLocations": - [ + "nameLocations": [ "118:2:1" ], "nodeType": "IdentifierPath", @@ -326,8 +282,7 @@ }, "referencedDeclaration": 2, "src": "118:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } @@ -337,12 +292,10 @@ ], "src": "117:4:1" }, - "returnParameters": - { + "returnParameters": { "id": 28, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 27, @@ -354,21 +307,17 @@ "src": "136:2:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" }, - "typeName": - { + "typeName": { "id": 26, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 25, "name": "I8", - "nameLocations": - [ + "nameLocations": [ "136:2:1" ], "nodeType": "IdentifierPath", @@ -377,8 +326,7 @@ }, "referencedDeclaration": 2, "src": "136:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } @@ -402,28 +350,22 @@ "contractKind": "contract", "fullyImplemented": true, "id": 49, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 49 ], "name": "C", "nameLocation": "152:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 47, "nodeType": "Block", "src": "208:30:1", - "statements": - [ + "statements": [ { - "expression": - { - "commonType": - { + "expression": { + "commonType": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" }, @@ -433,8 +375,7 @@ "isLValue": false, "isPure": false, "lValueRequested": false, - "leftExpression": - { + "leftExpression": { "function": 30, "id": 43, "isConstant": false, @@ -445,45 +386,39 @@ "operator": "-", "prefix": true, "src": "225:2:1", - "subExpression": - { + "subExpression": { "id": 42, "name": "a", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 33, "src": "226:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } }, - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } }, "nodeType": "BinaryOperation", "operator": "-", - "rightExpression": - { + "rightExpression": { "id": 44, "name": "b", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 36, "src": "230:1:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } }, "src": "225:6:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } @@ -503,12 +438,10 @@ "name": "f", "nameLocation": "169:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 37, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 33, @@ -520,21 +453,17 @@ "src": "171:4:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" }, - "typeName": - { + "typeName": { "id": 32, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 31, "name": "I8", - "nameLocations": - [ + "nameLocations": [ "171:2:1" ], "nodeType": "IdentifierPath", @@ -543,8 +472,7 @@ }, "referencedDeclaration": 2, "src": "171:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } @@ -562,21 +490,17 @@ "src": "177:4:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" }, - "typeName": - { + "typeName": { "id": 35, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 34, "name": "I8", - "nameLocations": - [ + "nameLocations": [ "177:2:1" ], "nodeType": "IdentifierPath", @@ -585,8 +509,7 @@ }, "referencedDeclaration": 2, "src": "177:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } @@ -596,12 +519,10 @@ ], "src": "170:12:1" }, - "returnParameters": - { + "returnParameters": { "id": 41, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 40, @@ -613,21 +534,17 @@ "src": "204:2:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" }, - "typeName": - { + "typeName": { "id": 39, "nodeType": "UserDefinedTypeName", - "pathNode": - { + "pathNode": { "id": 38, "name": "I8", - "nameLocations": - [ + "nameLocations": [ "204:2:1" ], "nodeType": "IdentifierPath", @@ -636,8 +553,7 @@ }, "referencedDeclaration": 2, "src": "204:2:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_userDefinedValueType$_I8_$2", "typeString": "I8" } diff --git a/test/libsolidity/ASTJSON/user_defined_operator.sol b/test/libsolidity/ASTJSON/user_defined_operator.sol index bfbdf7b9b..df5d0ed32 100644 --- a/test/libsolidity/ASTJSON/user_defined_operator.sol +++ b/test/libsolidity/ASTJSON/user_defined_operator.sol @@ -7,4 +7,5 @@ contract C { return -a - b; } } + // ---- diff --git a/test/libsolidity/ASTJSON/using_for_directive.json b/test/libsolidity/ASTJSON/using_for_directive.json index f3094980f..b62ec8e86 100644 --- a/test/libsolidity/ASTJSON/using_for_directive.json +++ b/test/libsolidity/ASTJSON/using_for_directive.json @@ -1,34 +1,26 @@ { "absolutePath": "a", - "exportedSymbols": - { - "C": - [ + "exportedSymbols": { + "C": [ 13 ], - "L": - [ + "L": [ 4 ], - "f": - [ + "f": [ 10 ] }, "id": 14, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { - "functionList": - [ + "functionList": [ { - "function": - { + "function": { "id": 1, "name": "f", - "nameLocations": - [ + "nameLocations": [ "7:1:1" ], "nodeType": "IdentifierPath", @@ -41,14 +33,12 @@ "id": 3, "nodeType": "UsingForDirective", "src": "0:19:1", - "typeName": - { + "typeName": { "id": 2, "name": "uint", "nodeType": "ElementaryTypeName", "src": "14:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -62,8 +52,7 @@ "contractKind": "library", "fullyImplemented": true, "id": 4, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 4 ], "name": "L", @@ -76,8 +65,7 @@ "usedEvents": [] }, { - "body": - { + "body": { "id": 9, "nodeType": "Block", "src": "50:2:1", @@ -90,12 +78,10 @@ "name": "f", "nameLocation": "42:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 6, @@ -107,19 +93,16 @@ "src": "44:4:1", "stateVariable": false, "storageLocation": "default", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, - "typeName": - { + "typeName": { "id": 5, "name": "uint", "nodeType": "ElementaryTypeName", "src": "44:4:1", - "typeDescriptions": - { + "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } @@ -129,8 +112,7 @@ ], "src": "43:6:1" }, - "returnParameters": - { + "returnParameters": { "id": 8, "nodeType": "ParameterList", "parameters": [], @@ -150,24 +132,20 @@ "contractKind": "contract", "fullyImplemented": true, "id": 13, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 13 ], "name": "C", "nameLocation": "62:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "global": false, "id": 12, - "libraryName": - { + "libraryName": { "id": 11, "name": "L", - "nameLocations": - [ + "nameLocations": [ "72:1:1" ], "nodeType": "IdentifierPath", diff --git a/test/libsolidity/ASTJSON/using_for_directive_parseOnly.json b/test/libsolidity/ASTJSON/using_for_directive_parseOnly.json index 9360227d4..4858081c2 100644 --- a/test/libsolidity/ASTJSON/using_for_directive_parseOnly.json +++ b/test/libsolidity/ASTJSON/using_for_directive_parseOnly.json @@ -2,18 +2,14 @@ "absolutePath": "a", "id": 14, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { - "functionList": - [ + "functionList": [ { - "function": - { + "function": { "id": 1, "name": "f", - "nameLocations": - [ + "nameLocations": [ "7:1:1" ], "nodeType": "IdentifierPath", @@ -25,8 +21,7 @@ "id": 3, "nodeType": "UsingForDirective", "src": "0:19:1", - "typeName": - { + "typeName": { "id": 2, "name": "uint", "nodeType": "ElementaryTypeName", @@ -49,8 +44,7 @@ "usedEvents": [] }, { - "body": - { + "body": { "id": 9, "nodeType": "Block", "src": "50:2:1", @@ -63,12 +57,10 @@ "name": "f", "nameLocation": "42:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 7, "nodeType": "ParameterList", - "parameters": - [ + "parameters": [ { "constant": false, "id": 6, @@ -80,8 +72,7 @@ "stateVariable": false, "storageLocation": "default", "typeDescriptions": {}, - "typeName": - { + "typeName": { "id": 5, "name": "uint", "nodeType": "ElementaryTypeName", @@ -93,8 +84,7 @@ ], "src": "43:6:1" }, - "returnParameters": - { + "returnParameters": { "id": 8, "nodeType": "ParameterList", "parameters": [], @@ -114,17 +104,14 @@ "name": "C", "nameLocation": "62:1:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { "global": false, "id": 12, - "libraryName": - { + "libraryName": { "id": 11, "name": "L", - "nameLocations": - [ + "nameLocations": [ "72:1:1" ], "nodeType": "IdentifierPath", diff --git a/test/libsolidity/ASTJSON/yul_hex_literal.json b/test/libsolidity/ASTJSON/yul_hex_literal.json index 0498289c6..22d8c6d8e 100644 --- a/test/libsolidity/ASTJSON/yul_hex_literal.json +++ b/test/libsolidity/ASTJSON/yul_hex_literal.json @@ -1,16 +1,13 @@ { "absolutePath": "a", - "exportedSymbols": - { - "Sample": - [ + "exportedSymbols": { + "Sample": [ 6 ] }, "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -19,37 +16,30 @@ "contractKind": "contract", "fullyImplemented": true, "id": 6, - "linearizedBaseContracts": - [ + "linearizedBaseContracts": [ 6 ], "name": "Sample", "nameLocation": "9:6:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "47:167:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "66:142:1", "nodeType": "YulBlock", "src": "66:142:1", - "statements": - [ + "statements": [ { "nativeSrc": "80:15:1", "nodeType": "YulVariableDeclaration", "src": "80:15:1", - "value": - { + "value": { "hexValue": "74657374", "kind": "string", "nativeSrc": "89:6:1", @@ -58,8 +48,7 @@ "type": "", "value": "test" }, - "variables": - [ + "variables": [ { "name": "a", "nativeSrc": "84:1:1", @@ -73,8 +62,7 @@ "nativeSrc": "108:54:1", "nodeType": "YulVariableDeclaration", "src": "108:54:1", - "value": - { + "value": { "hexValue": "112233445566778899aabbccddeeff6677889900", "kind": "string", "nativeSrc": "117:45:1", @@ -82,8 +70,7 @@ "src": "117:45:1", "type": "" }, - "variables": - [ + "variables": [ { "name": "b", "nativeSrc": "112:1:1", @@ -97,8 +84,7 @@ "nativeSrc": "175:23:1", "nodeType": "YulVariableDeclaration", "src": "175:23:1", - "value": - { + "value": { "hexValue": "1234abcd", "kind": "string", "nativeSrc": "184:14:1", @@ -106,8 +92,7 @@ "src": "184:14:1", "type": "" }, - "variables": - [ + "variables": [ { "name": "c", "nativeSrc": "179:1:1", @@ -135,15 +120,13 @@ "name": "f", "nameLocation": "31:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "32:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolidity/ASTJSON/yul_hex_literal.sol b/test/libsolidity/ASTJSON/yul_hex_literal.sol index c3b57a8fe..f441866c1 100644 --- a/test/libsolidity/ASTJSON/yul_hex_literal.sol +++ b/test/libsolidity/ASTJSON/yul_hex_literal.sol @@ -7,4 +7,5 @@ contract Sample { } } } + // ---- diff --git a/test/libsolidity/ASTJSON/yul_hex_literal_parseOnly.json b/test/libsolidity/ASTJSON/yul_hex_literal_parseOnly.json index 023c13cc7..d26e2e296 100644 --- a/test/libsolidity/ASTJSON/yul_hex_literal_parseOnly.json +++ b/test/libsolidity/ASTJSON/yul_hex_literal_parseOnly.json @@ -2,8 +2,7 @@ "absolutePath": "a", "id": 7, "nodeType": "SourceUnit", - "nodes": - [ + "nodes": [ { "abstract": false, "baseContracts": [], @@ -13,30 +12,24 @@ "name": "Sample", "nameLocation": "9:6:1", "nodeType": "ContractDefinition", - "nodes": - [ + "nodes": [ { - "body": - { + "body": { "id": 4, "nodeType": "Block", "src": "47:167:1", - "statements": - [ + "statements": [ { - "AST": - { + "AST": { "nativeSrc": "66:142:1", "nodeType": "YulBlock", "src": "66:142:1", - "statements": - [ + "statements": [ { "nativeSrc": "80:15:1", "nodeType": "YulVariableDeclaration", "src": "80:15:1", - "value": - { + "value": { "hexValue": "74657374", "kind": "string", "nativeSrc": "89:6:1", @@ -45,8 +38,7 @@ "type": "", "value": "test" }, - "variables": - [ + "variables": [ { "name": "a", "nativeSrc": "84:1:1", @@ -60,8 +52,7 @@ "nativeSrc": "108:54:1", "nodeType": "YulVariableDeclaration", "src": "108:54:1", - "value": - { + "value": { "hexValue": "112233445566778899aabbccddeeff6677889900", "kind": "string", "nativeSrc": "117:45:1", @@ -69,8 +60,7 @@ "src": "117:45:1", "type": "" }, - "variables": - [ + "variables": [ { "name": "b", "nativeSrc": "112:1:1", @@ -84,8 +74,7 @@ "nativeSrc": "175:23:1", "nodeType": "YulVariableDeclaration", "src": "175:23:1", - "value": - { + "value": { "hexValue": "1234abcd", "kind": "string", "nativeSrc": "184:14:1", @@ -93,8 +82,7 @@ "src": "184:14:1", "type": "" }, - "variables": - [ + "variables": [ { "name": "c", "nativeSrc": "179:1:1", @@ -121,15 +109,13 @@ "name": "f", "nameLocation": "31:1:1", "nodeType": "FunctionDefinition", - "parameters": - { + "parameters": { "id": 1, "nodeType": "ParameterList", "parameters": [], "src": "32:2:1" }, - "returnParameters": - { + "returnParameters": { "id": 2, "nodeType": "ParameterList", "parameters": [], diff --git a/test/libsolutil/JSON.cpp b/test/libsolutil/JSON.cpp index 91e6771ac..7b5528fff 100644 --- a/test/libsolutil/JSON.cpp +++ b/test/libsolutil/JSON.cpp @@ -91,8 +91,7 @@ BOOST_AUTO_TEST_CASE(json_pretty_print) "{\n" " \"1\": 1,\n" " \"2\": \"2\",\n" - " \"3\":\n" - " {\n" + " \"3\": {\n" " \"3.1\": \"3.1\",\n" " \"3.2\": 2\n" " },\n" From 2572e1345ed4cc94e96b15945717c4cfed87c19f Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Tue, 23 Apr 2024 13:20:38 +0200 Subject: [PATCH 0099/1340] SMTChecker: Fix equality of array literals There are two kinds of array literals in Solidity: string literals (arrays of characters/bytes) and proper array literals (e.g., [1,2,3]). While array literals cannot be directly tested for equality in Solidity, it is possible to compute hash of these values and compare hashes. The expectation is that hashes of the same array literals would be the same, but previously SMTChecker returned false positive in this case, saying that they don't have to be equal. The reason for the false positive was the following. We represent Solidity array literal as a tuple `(elements, length)` where `length` is an integer representing the actualy length of the array literal, and `elements` are an SMT-LIB array, where the first `length` elements represent the actual content of the array literal. However, SMT-LIB arrays are infinite objects (more like functions from indices to elements). Previously, we left the part after `length`-th element unspecified. For the solver this meant that two array literals equal at the Solidity level were represented with two different SMT-LIB arrays. The proposed solution is to always start from a constant-zero array, and use store operations to build an SMT-LIB array that matches the Solidity array literal. --- Changelog.md | 1 + libsolidity/formal/SMTEncoder.cpp | 21 ++++++++++++++++- .../model_checker_invariants_all/err | 2 +- .../err | 2 +- .../abi/abi_encode_packed_string_literal.sol | 20 +++++++--------- ...code_packed_string_literal_no_unproved.sol | 20 +++++++--------- .../abi/abi_encode_string_literal.sol | 17 ++++++-------- ...bi_encode_with_selector_string_literal.sol | 21 ++++++++--------- .../abi/abi_encode_with_sig_array_slice.sol | 7 ++---- .../abi/abi_encode_with_sig_array_slice_2.sol | 7 ++---- .../abi_encode_with_sig_string_literal.sol | 20 +++++++--------- .../crypto/crypto_functions_same_array.sol | 23 +++++++++++++++++++ .../crypto_functions_same_string_literal.sol | 23 +++++++++++++++++++ .../external_calls/call_mutex_unsafe.sol | 4 ++-- .../smtCheckerTests/types/array_literal_3.sol | 2 +- 15 files changed, 116 insertions(+), 74 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_array.sol create mode 100644 test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol diff --git a/Changelog.md b/Changelog.md index 59284486b..b924b1ccd 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Compiler Features: Bugfixes: * Commandline Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``--yul-optimizations`` sequence. + * SMTChecker: Fix false positive when comparing hashes of same array or string literals. * SMTChecker: Fix internal error on mapping access caused by too strong requirements on sort compatibility of the index and mapping domain. * SMTChecker: Fix internal error when using an empty tuple in a conditional operator. * SMTChecker: Fix internal error when using bitwise operators with an array element as argument. diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 61aad0e8f..c92c5399a 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -1296,8 +1296,27 @@ void SMTEncoder::addArrayLiteralAssertions( ) { m_context.addAssertion(_symArray.length() == _elementValues.size()); + + // Assert to the solver that _elementValues are exactly the elements at the beginning of the array. + // Since we create new symbolic representation for every array literal in the source file, we want to ensure that + // representations of two equal literals are also equal. For this reason we always start from constant-zero array. + // This ensures SMT-LIB arrays (which are infinite) are also equal beyond the length of the Solidity array literal. + auto type = _symArray.type(); + smtAssert(type); + auto valueType = [&]() { + if (auto const* arrayType = dynamic_cast(type)) + return arrayType->baseType(); + if (smt::isStringLiteral(*type)) + return TypeProvider::stringMemory()->baseType(); + smtAssert(false); + }(); + auto tupleSort = std::dynamic_pointer_cast(smt::smtSort(*type)); + auto sortSort = std::make_shared(tupleSort->components.front()); + smtutil::Expression arrayExpr = smtutil::Expression::const_array(smtutil::Expression(sortSort), smt::zeroValue(valueType)); + smtAssert(arrayExpr.sort->kind == smtutil::Kind::Array); for (size_t i = 0; i < _elementValues.size(); i++) - m_context.addAssertion(smtutil::Expression::select(_symArray.elements(), i) == _elementValues[i]); + arrayExpr = smtutil::Expression::store(arrayExpr, smtutil::Expression(i), _elementValues[i]); + m_context.addAssertion(_symArray.elements() == arrayExpr); } void SMTEncoder::bytesToFixedBytesAssertions( diff --git a/test/cmdlineTests/model_checker_invariants_all/err b/test/cmdlineTests/model_checker_invariants_all/err index 347f40325..7ec97678e 100644 --- a/test/cmdlineTests/model_checker_invariants_all/err +++ b/test/cmdlineTests/model_checker_invariants_all/err @@ -9,6 +9,6 @@ Info: CHC: 1 verification condition(s) proved safe! Enable the model checker opt Info: Contract invariant(s) for model_checker_invariants_all/input.sol:test: (!(x >= 1) || true) Reentrancy property(ies) for model_checker_invariants_all/input.sol:test: -(((!(x <= 0) || !(x' >= 1)) && (!(x <= 0) || !( >= 1))) || true) +(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) = 0 -> no errors = 1 -> Assertion failed at assert(x == 0) diff --git a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err index c6d149f15..11ee3a702 100644 --- a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err +++ b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err @@ -9,6 +9,6 @@ Info: CHC: 1 verification condition(s) proved safe! Enable the model checker opt Info: Contract invariant(s) for model_checker_invariants_contract_reentrancy/input.sol:test: (!(x >= 1) || true) Reentrancy property(ies) for model_checker_invariants_contract_reentrancy/input.sol:test: -(((!(x <= 0) || !(x' >= 1)) && (!(x <= 0) || !( >= 1))) || true) +(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) = 0 -> no errors = 1 -> Assertion failed at assert(x == 0) diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_packed_string_literal.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_packed_string_literal.sol index 08c48cbd9..47b15369c 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_packed_string_literal.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_packed_string_literal.sol @@ -2,18 +2,16 @@ contract C { function abiencodePackedStringLiteral() public pure { bytes memory b1 = abi.encodePacked(""); bytes memory b2 = abi.encodePacked(""); - // should hold, but currently fails due to string literal abstraction - assert(b1.length == b2.length); + assert(b1.length == b2.length); // should hold bytes memory b3 = abi.encodePacked(bytes("")); - assert(b1.length == b3.length); // should fail + assert(b1.length == b3.length); // should hold bytes memory b4 = abi.encodePacked(bytes24("")); - // should hold, but currently fails due to string literal abstraction - assert(b1.length == b4.length); + assert(b1.length == b4.length); // should fail bytes memory b5 = abi.encodePacked(string("")); - assert(b1.length == b5.length); // should fail + assert(b1.length == b5.length); // should hold, but currently fails due to abstraction bytes memory b6 = abi.encode(""); assert(b1.length == b6.length); // should fail @@ -21,10 +19,8 @@ contract C { } // ==== // SMTEngine: all -// SMTIgnoreOS: macos // ---- -// Warning 6328: (226-256): CHC: Assertion violation happens here.\nCounterexample:\n\nb1 = [0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42]\nb3 = []\nb4 = []\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() -// Warning 6328: (310-340): CHC: Assertion violation happens here.\nCounterexample:\n\nb2 = [0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72]\nb4 = []\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() -// Warning 6328: (483-513): CHC: Assertion violation happens here.\nCounterexample:\n\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() -// Warning 6328: (568-598): CHC: Assertion violation happens here.\nCounterexample:\n\nb2 = [0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc]\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() -// Warning 6328: (654-684): CHC: Assertion violation happens here.\nCounterexample:\n\nb3 = [0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a]\nb6 = [0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117]\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() +// Warning 6328: (354-384): CHC: Assertion violation happens here.\nCounterexample:\n\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() +// Warning 6328: (454-484): CHC: Assertion violation happens here.\nCounterexample:\n\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() +// Warning 6328: (580-610): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_packed_string_literal_no_unproved.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_packed_string_literal_no_unproved.sol index f80027626..581e649fc 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_packed_string_literal_no_unproved.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_packed_string_literal_no_unproved.sol @@ -2,18 +2,16 @@ contract C { function abiencodePackedStringLiteral() public pure { bytes memory b1 = abi.encodePacked(""); bytes memory b2 = abi.encodePacked(""); - // should hold, but currently fails due to string literal abstraction - assert(b1.length == b2.length); + assert(b1.length == b2.length); // should hold bytes memory b3 = abi.encodePacked(bytes("")); - assert(b1.length == b3.length); // should fail + assert(b1.length == b3.length); // should hold bytes memory b4 = abi.encodePacked(bytes24("")); - // should hold, but currently fails due to string literal abstraction - assert(b1.length == b4.length); + assert(b1.length == b4.length); // should fail bytes memory b5 = abi.encodePacked(string("")); - assert(b1.length == b5.length); // should fail + assert(b1.length == b5.length); // should hold, but fails due to abstraction bytes memory b6 = abi.encode(""); assert(b1.length == b6.length); // should fail @@ -22,10 +20,8 @@ contract C { // ==== // SMTEngine: all // SMTShowUnproved: no -// SMTIgnoreOS: macos // ---- -// Warning 6328: (226-256): CHC: Assertion violation happens here.\nCounterexample:\n\nb1 = [0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42]\nb3 = []\nb4 = []\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() -// Warning 6328: (310-340): CHC: Assertion violation happens here.\nCounterexample:\n\nb2 = [0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72]\nb4 = []\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() -// Warning 6328: (483-513): CHC: Assertion violation happens here.\nCounterexample:\n\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() -// Warning 6328: (568-598): CHC: Assertion violation happens here.\nCounterexample:\n\nb2 = [0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc]\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() -// Warning 6328: (654-684): CHC: Assertion violation happens here.\nCounterexample:\n\nb3 = [0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a, 0x011a]\nb6 = [0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117]\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() +// Warning 6328: (354-384): CHC: Assertion violation happens here.\nCounterexample:\n\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() +// Warning 6328: (454-484): CHC: Assertion violation happens here.\nCounterexample:\n\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() +// Warning 6328: (570-600): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.abiencodePackedStringLiteral() +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_string_literal.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_string_literal.sol index b55952ee7..77d3cfb83 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_string_literal.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_string_literal.sol @@ -2,25 +2,22 @@ contract C { function abiEncodeStringLiteral() public pure { bytes memory b1 = abi.encode(""); bytes memory b2 = abi.encode(""); - // should hold, but currently fails due to string literal abstraction + // should hold assert(b1.length == b2.length); bytes memory b3 = abi.encode(bytes("")); - assert(b1.length == b3.length); // should fail + assert(b1.length == b3.length); // should hold bytes memory b4 = abi.encode(bytes24("")); - // should hold, but currently fails due to string literal abstraction - assert(b1.length == b4.length); + assert(b1.length == b4.length); // should fail bytes memory b5 = abi.encode(string("")); - assert(b1.length == b5.length); // should fail + assert(b1.length == b5.length); // should hold, but currently fails due to abstraction } } // ==== // SMTEngine: all -// SMTIgnoreOS: macos // ---- -// Warning 6328: (208-238): CHC: Assertion violation happens here.\nCounterexample:\n\nb3 = []\nb4 = []\nb5 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral() -// Warning 6328: (286-316): CHC: Assertion violation happens here.\nCounterexample:\n\nb2 = [0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d]\nb3 = [0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d]\nb4 = []\nb5 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral() -// Warning 6328: (453-483): CHC: Assertion violation happens here.\nCounterexample:\n\nb5 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral() -// Warning 6328: (532-562): CHC: Assertion violation happens here.\nCounterexample:\n\nb3 = [0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca]\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral() +// Warning 6328: (326-356): CHC: Assertion violation happens here.\nCounterexample:\n\nb5 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral() +// Warning 6328: (420-450): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral() +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_string_literal.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_string_literal.sol index 6d1ab3066..dd183263a 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_string_literal.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_string_literal.sol @@ -2,18 +2,17 @@ contract C { function abiEncodeStringLiteral(bytes4 sel) public pure { bytes memory b1 = abi.encodeWithSelector(sel, ""); bytes memory b2 = abi.encodeWithSelector(sel, ""); - // should hold, but currently fails due to string literal abstraction - assert(b1.length == b2.length); + + assert(b1.length == b2.length); // should hold bytes memory b3 = abi.encodeWithSelector(sel, bytes("")); - assert(b1.length == b3.length); // should fail + assert(b1.length == b3.length); // should hold bytes memory b4 = abi.encodeWithSelector(sel, bytes24("")); - // should hold, but currently fails due to string literal abstraction - assert(b1.length == b4.length); + assert(b1.length == b4.length); // should fail bytes memory b5 = abi.encodeWithSelector(sel, string("")); - assert(b1.length == b5.length); // should fail + assert(b1.length == b5.length); // should hold, but currently fails due to abstraction bytes memory b6 = abi.encodeWithSelector(0xcafecafe, bytes24("")); assert(b4.length == b6.length); // should fail @@ -21,10 +20,8 @@ contract C { } // ==== // SMTEngine: all -// SMTIgnoreOS: macos // ---- -// Warning 6328: (252-282): CHC: Assertion violation happens here.\nCounterexample:\n\nsel = 0x0\nb1 = [0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46]\nb3 = []\nb4 = []\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(0x0) -// Warning 6328: (347-377): CHC: Assertion violation happens here.\nCounterexample:\n\nsel = 0x0\nb3 = [0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d]\nb4 = []\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(0x0) -// Warning 6328: (531-561): CHC: Assertion violation happens here.\nCounterexample:\n\nsel = 0x0\nb1 = [0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90]\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(0x0) -// Warning 6328: (627-657): CHC: Assertion violation happens here.\nCounterexample:\n\nsel = 0x0\nb5 = [0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1]\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(0x0) -// Warning 6328: (746-776): CHC: Assertion violation happens here.\nCounterexample:\n\nsel = 0x0\nb2 = []\nb5 = [0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2]\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(0x0) +// Warning 6328: (403-433): CHC: Assertion violation happens here.\nCounterexample:\n\nsel = 0x0\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(0x0) +// Warning 6328: (514-544): CHC: Assertion violation happens here.\nCounterexample:\n\nsel = 0x0\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(0x0) +// Warning 6328: (673-703): CHC: Assertion violation happens here.\nCounterexample:\n\nsel = 0x0\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(0x0) +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol index fad743744..b2d1b4acc 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol @@ -24,10 +24,7 @@ contract C { } // ==== // SMTEngine: all -// SMTIgnoreOS: macos // ---- -// Warning 6328: (334-364): CHC: Assertion violation happens here. +// Warning 6328: (334-364): CHC: Assertion violation happens here.\nCounterexample:\n\ndata = [0x4f]\nb2 = [0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c]\nb3 = []\nb4 = []\nx = 0\ny = 0\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeSlice(sig, [0x4f]) -- counterexample incomplete; parameter name used instead of value // Warning 6328: (588-618): CHC: Assertion violation happens here. -// Warning 6328: (1086-1116): CHC: Assertion violation might happen here. -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 4661: (1086-1116): BMC: Assertion violation happens here. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol index 41e71ee5b..4c21a02a6 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol @@ -24,10 +24,7 @@ contract C { } // ==== // SMTEngine: all -// SMTIgnoreOS: macos // ---- -// Warning 6328: (335-365): CHC: Assertion violation happens here. +// Warning 6328: (335-365): CHC: Assertion violation happens here.\nCounterexample:\n\ndata = [36]\nb3 = []\nb4 = []\nx = 0\ny = 0\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeSlice(sig, [36]) -- counterexample incomplete; parameter name used instead of value // Warning 6328: (589-619): CHC: Assertion violation happens here. -// Warning 6328: (1087-1117): CHC: Assertion violation might happen here. -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 4661: (1087-1117): BMC: Assertion violation happens here. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_string_literal.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_string_literal.sol index de218cfaa..ca782442b 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_string_literal.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_string_literal.sol @@ -2,18 +2,16 @@ contract C { function abiEncodeStringLiteral(string memory sig) public pure { bytes memory b1 = abi.encodeWithSignature(sig, ""); bytes memory b2 = abi.encodeWithSignature(sig, ""); - // should hold, but currently fails due to string literal abstraction - assert(b1.length == b2.length); + assert(b1.length == b2.length); // should hold bytes memory b3 = abi.encodeWithSignature(sig, bytes("")); - assert(b1.length == b3.length); // should fail + assert(b1.length == b3.length); // should hold bytes memory b4 = abi.encodeWithSignature(sig, bytes24("")); - // should hold, but currently fails due to string literal abstraction - assert(b1.length == b4.length); + assert(b1.length == b4.length); // should fail bytes memory b5 = abi.encodeWithSignature(sig, string("")); - assert(b1.length == b5.length); // should fail + assert(b1.length == b5.length); // should hold, but currently fails due to abstraction bytes memory b6 = abi.encodeWithSelector("f()", bytes24("")); assert(b4.length == b6.length); // should fail @@ -21,10 +19,8 @@ contract C { } // ==== // SMTEngine: all -// SMTIgnoreOS: macos // ---- -// Warning 6328: (261-291): CHC: Assertion violation happens here.\nCounterexample:\n\nb2 = [0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a]\nb3 = []\nb4 = []\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(sig) -// Warning 6328: (357-387): CHC: Assertion violation happens here.\nCounterexample:\n\nb3 = [0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90]\nb4 = []\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(sig) -// Warning 6328: (542-572): CHC: Assertion violation happens here.\nCounterexample:\n\nb3 = [0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa]\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(sig) -// Warning 6328: (639-669): CHC: Assertion violation happens here.\nCounterexample:\n\nb4 = [0x22, 0x22, 0x22, 0x22, 0x22, 0x0d, 0x22, 0x22, 0x22, 0x22, 0x09, 0x22, 0x0b, 0x22, 0x22, 0x0e, 0x22, 0x10, 0x22, 0x12, 0x22, 0x14, 0x22, 0x16, 0x22, 0x18, 0x22, 0x1a, 0x22, 0x1c, 0x22, 0x1e, 0x22, 0x20, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22]\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(sig) -// Warning 6328: (753-783): CHC: Assertion violation happens here.\nCounterexample:\n\nb2 = [0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117, 0x0117]\nb4 = []\nb5 = [0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118, 0x0118]\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(sig) +// Warning 6328: (413-443): CHC: Assertion violation happens here.\nCounterexample:\n\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(sig) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (525-555): CHC: Assertion violation happens here.\nCounterexample:\n\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(sig) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (679-709): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.abiEncodeStringLiteral(sig) -- counterexample incomplete; parameter name used instead of value +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_array.sol b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_array.sol new file mode 100644 index 000000000..b0e3b9565 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_array.sol @@ -0,0 +1,23 @@ +contract C { + function c1() public pure { + bytes32 k1 = keccak256(abi.encode([1])); + bytes32 k2 = keccak256(abi.encode([1])); + assert(k1 == k2); + } + + function c2() public pure { + bytes32 s1 = sha256(abi.encode([1,2])); + bytes32 s2 = sha256(abi.encode([1,2])); + assert(s1 == s2); + } + + function c3() public pure { + bytes32 r1 = ripemd160(abi.encode([1,2,3])); + bytes32 r2 = ripemd160(abi.encode([1,2,3])); + assert(r1 == r2); + } +} +// ==== +// SMTEngine: chc +// ---- +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol new file mode 100644 index 000000000..9e5123ab5 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol @@ -0,0 +1,23 @@ +contract C { + function c1() public pure { + bytes32 k1 = keccak256("1"); + bytes32 k2 = keccak256("1"); + assert(k1 == k2); + } + + function c2() public pure { + bytes32 s1 = sha256("10"); + bytes32 s2 = sha256("10"); + assert(s1 == s2); + } + + function c3() public pure { + bytes32 r1 = ripemd160("100"); + bytes32 r2 = ripemd160("100"); + assert(r1 == r2); + } +} +// ==== +// SMTEngine: chc +// ---- +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_mutex_unsafe.sol b/test/libsolidity/smtCheckerTests/external_calls/call_mutex_unsafe.sol index e8c17d3eb..d2fefcd5f 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_mutex_unsafe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_mutex_unsafe.sol @@ -21,7 +21,7 @@ contract C { } // ==== // SMTEngine: all -// SMTIgnoreCex: no +// SMTIgnoreCex: yes // ---- // Warning 9302: (212-228): Return value of low-level calls not used. -// Warning 6328: (232-246): CHC: Assertion violation happens here.\nCounterexample:\nx = 0, lock = false\n_a = 0x0\ny = 1\n\nTransaction trace:\nC.constructor()\nState: x = 0, lock = false\nC.set(1)\nState: x = 1, lock = false\nC.f(0x0)\n _a.call("aaaaa") -- untrusted external call, synthesized as:\n C.set(0) -- reentrant call +// Warning 6328: (232-246): CHC: Assertion violation happens here.\nCounterexample:\nx = 1, lock = false\n_a = 0x0\ny = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0, lock = false\nC.f(0x0)\n _a.call("aaaaa") -- untrusted external call, synthesized as:\n C.set(1) -- reentrant call diff --git a/test/libsolidity/smtCheckerTests/types/array_literal_3.sol b/test/libsolidity/smtCheckerTests/types/array_literal_3.sol index cdaff2bf4..b4655f394 100644 --- a/test/libsolidity/smtCheckerTests/types/array_literal_3.sol +++ b/test/libsolidity/smtCheckerTests/types/array_literal_3.sol @@ -11,5 +11,5 @@ contract C // SMTEngine: all // SMTIgnoreCex: no // ---- -// Warning 6328: (168-188): CHC: Assertion violation happens here. +// Warning 6328: (168-188): CHC: Assertion violation happens here.\nCounterexample:\n\na = [1, 2, 3]\nb = [1, 2, 4]\n\nTransaction trace:\nC.constructor()\nC.f() // Info 1391: CHC: 8 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 9599d85eb042318fbd8d31565f5e5be7b09fc9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 12 Feb 2024 13:24:01 +0100 Subject: [PATCH 0100/1340] Optimizer docs: Style corrections - Add missing backticks. - Use consistent style for step naming (capitalized, without spaces, without backticks). - Correct minor text errors like missing plurals. --- docs/internals/optimizer.rst | 183 ++++++++++++++++++----------------- 1 file changed, 92 insertions(+), 91 deletions(-) diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index c1b959a8a..604560554 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -295,11 +295,11 @@ backtracking. All components of the Yul-based optimizer module are explained below. The following transformation steps are the main components: -- SSA Transform -- Common Subexpression Eliminator -- Expression Simplifier -- Unused Assign Eliminator -- Full Inliner +- SSATransform +- CommonSubexpressionEliminator +- ExpressionSimplifier +- UnusedAssignEliminator +- FullInliner .. _optimizer-steps: @@ -313,7 +313,7 @@ on the individual steps and their sequence below. Abbreviation Full name ============ =============================== ``f`` :ref:`block-flattener` -``l`` :ref:`circular-reference-pruner` +``l`` :ref:`circular-references-pruner` ``c`` :ref:`common-subexpression-eliminator` ``C`` :ref:`conditional-simplifier` ``U`` :ref:`conditional-unsimplifier` @@ -336,8 +336,8 @@ Abbreviation Full name ``L`` :ref:`load-resolver` ``M`` :ref:`loop-invariant-code-motion` ``m`` :ref:`rematerialiser` -``V`` :ref:`SSA-reverser` -``a`` :ref:`SSA-transform` +``V`` :ref:`ssa-reverser` +``a`` :ref:`ssa-transform` ``t`` :ref:`structural-simplifier` ``r`` :ref:`unused-assign-eliminator` ``p`` :ref:`unused-function-parameter-pruner` @@ -416,7 +416,7 @@ and functions can be optimized in isolation without having to traverse the AST c FunctionGrouper ^^^^^^^^^^^^^^^ -The function grouper has to be applied after the disambiguator and the function hoister. +The function grouper has to be applied after the Disambiguator and the FunctionHoister. Its effect is that all topmost elements that are not function definitions are moved into a single block which is the first statement of the root block. @@ -429,14 +429,14 @@ After this step, a program has the following normal form: Where ``I`` is a (potentially empty) block that does not contain any function definitions (not even recursively) and ``F`` is a list of function definitions such that no function contains a function definition. -The benefit of this stage is that we always know where the list of function begins. +The benefit of this stage is that we always know where the list of functions begins. .. _for-loop-condition-into-body: ForLoopConditionIntoBody ^^^^^^^^^^^^^^^^^^^^^^^^ -This transformation moves the loop-iteration condition of a for-loop into loop body. +This transformation moves the loop-iteration condition of a ``for`` loop into loop body. We need this transformation because :ref:`expression-splitter` will not apply to iteration condition expressions (the ``C`` in the following example). @@ -455,7 +455,7 @@ is transformed to Body... } -This transformation can also be useful when paired with ``LoopInvariantCodeMotion``, since +This transformation can also be useful when paired with LoopInvariantCodeMotion, since invariants in the loop-invariant conditions can then be taken outside the loop. .. _for-loop-init-rewriter: @@ -463,7 +463,7 @@ invariants in the loop-invariant conditions can then be taken outside the loop. ForLoopInitRewriter ^^^^^^^^^^^^^^^^^^^ -This transformation moves the initialization part of a for-loop to before +This transformation moves the initialization part of a ``for`` loop to before the loop: .. code-block:: text @@ -482,7 +482,7 @@ is transformed to } This eases the rest of the optimization process because we can ignore -the complicated scoping rules of the for loop initialization block. +the complicated scoping rules of the ``for`` loop initialization block. .. _var-decl-initializer: @@ -600,7 +600,7 @@ and it is also easier to perform function call inlining. Furthermore, it is simp to replace individual parts of expressions or re-organize the "expression tree". The drawback is that such code is much harder to read for humans. -.. _SSA-transform: +.. _ssa-transform: SSATransform ^^^^^^^^^^^^ @@ -645,19 +645,19 @@ are not modified) perform the following transforms: Furthermore, always record the current value of ``i`` used for ``a`` and replace each 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. +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. +``if``/``switch``/``for``/block statement. -After this stage, the Unused Assign Eliminator is recommended to remove the unnecessary +After this stage, the UnusedAssignEliminator is recommended to remove the unnecessary intermediate assignments. -This stage provides best results if the Expression Splitter and the Common Subexpression Eliminator +This stage provides best results if the ExpressionSplitter and the CommonSubexpressionEliminator are run right before it, because then it does not generate excessive amounts of variables. -On the other hand, the Common Subexpression Eliminator could be more efficient if run after the +On the other hand, the CommonSubexpressionEliminator could be more efficient if run after the SSA transform. .. _unused-assign-eliminator: @@ -691,7 +691,7 @@ The SSA transform converts this snippet to the following: sstore(a_3, 1) } -The Unused Assign Eliminator removes all the three assignments to ``a``, because +The UnusedAssignEliminator removes all the three assignments to ``a``, because the value of ``a`` is not used and thus turn this snippet into strict SSA form: @@ -716,7 +716,7 @@ mapping from assignment statements to the three states value will be used later by a reference to the variable. When an assignment is visited, it is added to the mapping in the "undecided" state -(see remark about for loops below) and every other assignment to the same variable +(see remark about ``for`` loops below) and every other assignment to the same variable that is still in the "undecided" state is changed to "unused". When a variable is referenced, the state of any assignment to that variable still in the "undecided" state is changed to "used". @@ -731,7 +731,7 @@ Conflicting values are resolved in the following way: - "unused", "used" -> "used" - "undecided", "used" -> "used" -For for-loops, the condition, body and post-part are visited twice, taking +For ``for`` loops, the condition, body and post-part are visited twice, taking the joining control-flow at the condition into account. In other words, we create three control flow paths: Zero runs of the loop, one run and two runs and then combine them at the end. @@ -757,13 +757,13 @@ and thus .. code-block:: none - max(s, f(s), f(f(s))) = max(s, f(s), f(f(s)), f(f(f(s))), ...). + max(s, f(s), f(f(s))) = max(s, f(s), f(f(s)), f(f(f(s))), ...) In summary, running the loop at most twice is enough because there are only three different states. -For switch statements that have a "default"-case, there is no control-flow -part that skips the switch. +For ``switch`` statements that have a default case, there is no control-flow +part that skips the ``switch``. When a variable goes out of scope, all statements still in the "undecided" state are changed to "unused", unless the variable is the return @@ -793,7 +793,7 @@ The following parts make an expression non-movable: DataflowAnalyzer ^^^^^^^^^^^^^^^^ -The Dataflow Analyzer is not an optimizer step itself but is used as a tool +The DataflowAnalyzer is not an optimizer step itself but is used as a tool by other components. While traversing the AST, it tracks the current value of each variable, as long as that value is a movable expression. It records the variables that are part of the expression @@ -804,7 +804,7 @@ of the currently stored expression for ``b``. At control-flow joins, knowledge about variables is cleared if they have or would be assigned in any of the control-flow paths. For instance, upon entering a -for loop, all variables are cleared that will be assigned during the +``for`` loop, all variables are cleared that will be assigned during the body or the post block. Expression-Scale Simplifications @@ -818,7 +818,7 @@ and hopefully simpler expressions. CommonSubexpressionEliminator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This step uses the Dataflow Analyzer and replaces subexpressions that +This step uses the DataflowAnalyzer and replaces subexpressions that syntactically match the current value of a variable by a reference to that variable. This is an equivalence transform because such subexpressions have to be movable. @@ -828,24 +828,24 @@ current value if the value is an identifier. The combination of the two rules above allow to compute a local value numbering, which means that if two variables have the same -value, one of them will always be unused. The Unused Pruner or the -Unused Assign Eliminator will then be able to fully eliminate such +value, one of them will always be unused. The UnusedPruner or the +UnusedAssignEliminator will then be able to fully eliminate such variables. -This step is especially efficient if the expression splitter is run +This step is especially efficient if the ExpressionSplitter is run before. If the code is in pseudo-SSA form, the values of variables are available for a longer time and thus we have a higher chance of expressions to be replaceable. -The expression simplifier will be able to perform better replacements -if the common subexpression eliminator was run right before it. +The ExpressionSimplifier will be able to perform better replacements +if the CommonSubexpressionEliminator was run right before it. .. _expression-simplifier: ExpressionSimplifier ^^^^^^^^^^^^^^^^^^^^ -The ExpressionSimplifier uses the Dataflow Analyzer and makes use +The ExpressionSimplifier uses the DataflowAnalyzer and makes use of a list of equivalence transforms on expressions like ``X + 0 -> X`` to simplify the code. @@ -857,7 +857,7 @@ even when the code is in pseudo-SSA form. Some of the patterns like ``X - X -> 0`` can only be applied as long as the expression ``X`` is movable, because otherwise it would remove its potential side-effects. Since variable references are always movable, even if their current -value might not be, the Expression Simplifier is again more powerful +value might not be, the ExpressionSimplifier is again more powerful in split or pseudo-SSA form. .. _literal-rematerialiser: @@ -877,12 +877,12 @@ currently stored in storage resp. memory, if known. Works best if the code is in SSA form. -Prerequisite: Disambiguator, ForLoopInitRewriter. +Prerequisites: Disambiguator, ForLoopInitRewriter. Statement-Scale Simplifications ------------------------------- -.. _circular-reference-pruner: +.. _circular-references-pruner: CircularReferencesPruner ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -895,7 +895,7 @@ neither externally referenced nor referenced from the outermost context. ConditionalSimplifier ^^^^^^^^^^^^^^^^^^^^^ -The Conditional Simplifier inserts assignments to condition variables if the value can be determined +The ConditionalSimplifier inserts assignments to condition variables if the value can be determined from the control-flow. Destroys SSA form. @@ -906,12 +906,12 @@ we cannot assign a specific value. Current features: -- switch cases: insert " := " -- after if statement with terminating control-flow, insert " := 0" +- ``switch`` cases: insert `` := `` +- after ``if`` statement with terminating control-flow, insert `` := 0`` Future features: -- allow replacements by "1" +- allow replacements by ``1`` - take termination of user-defined functions into account Works best with SSA form and if dead code removal has run before. @@ -923,7 +923,7 @@ Prerequisite: Disambiguator. ConditionalUnsimplifier ^^^^^^^^^^^^^^^^^^^^^^^ -Reverse of Conditional Simplifier. +Reverse of ConditionalSimplifier. .. _control-flow-simplifier: @@ -932,14 +932,14 @@ ControlFlowSimplifier Simplifies several control-flow structures: -- replace if with empty body with pop(condition) -- remove empty default switch case -- remove empty switch case if no default case exists -- replace switch with no cases with pop(expression) -- turn switch with single case into if -- replace switch with only default case with pop(expression) and body -- replace switch with const expr with matching case body -- replace ``for`` with terminating control flow and without other break/continue by ``if`` +- replace ``if`` with empty body with ``pop(condition)`` +- remove empty default ``switch`` case +- remove empty ``switch`` case if no default case exists +- replace ``switch`` with no cases with ``pop(expression)`` +- turn ``switch`` with single case into ``if`` +- replace ``switch`` with only default case with ``pop(expression)`` and body +- replace ``switch`` with const expr with matching case body +- replace ``for`` with terminating control flow and without other ``break``/``continue`` by ``if`` - remove ``leave`` at the end of a function. None of these operations depend on the data flow. The StructuralSimplifier @@ -949,6 +949,7 @@ The ControlFlowSimplifier does record the presence or absence of ``break`` and ``continue`` statements during its traversal. Prerequisite: Disambiguator, FunctionHoister, ForLoopInitRewriter. + Important: Introduces EVM opcodes and thus can only be used on EVM code for now. .. _dead-code-eliminator: @@ -959,15 +960,16 @@ DeadCodeEliminator This optimization stage removes unreachable code. Unreachable code is any code within a block which is preceded by a -leave, return, invalid, break, continue, selfdestruct, revert or by a call to a user-defined function that recurses infinitely. +``leave``, ``return``, ``invalid``, ``break``, ``continue``, ``selfdestruct``, ``revert`` or by +a call to a user-defined function that recurses infinitely. Function definitions are retained as they might be called by earlier code and thus are considered reachable. -Because variables declared in a for loop's init block have their scope extended to the loop body, +Because variables declared in a ``for`` loop's init block have their scope extended to the loop body, we require ForLoopInitRewriter to run before this step. -Prerequisite: ForLoopInitRewriter, Function Hoister, Function Grouper +Prerequisites: ForLoopInitRewriter, FunctionHoister, FunctionGrouper. .. _equal-store-eliminator: @@ -978,12 +980,12 @@ This steps removes ``mstore(k, v)`` and ``sstore(k, v)`` calls if there was a previous call to ``mstore(k, v)`` / ``sstore(k, v)``, no other store in between and the values of ``k`` and ``v`` did not change. -This simple step is effective if run after the SSA transform and the -Common Subexpression Eliminator, because SSA will make sure that the variables -will not change and the Common Subexpression Eliminator re-uses exactly the same +This simple step is effective if run after the SSATransform and the +CommonSubexpressionEliminator, because SSA will make sure that the variables +will not change and the CommonSubexpressionEliminator re-uses exactly the same variable if the value is known to be the same. -Prerequisites: Disambiguator, ForLoopInitRewriter +Prerequisites: Disambiguator, ForLoopInitRewriter. .. _unused-pruner: @@ -992,8 +994,8 @@ UnusedPruner This step removes the definitions of all functions that are never referenced. -It also removes the declaration of variables that are never referenced. -If the declaration assigns a value that is not movable, the expression is retained, +It also removes declarations of variables that are never referenced. +If a declaration assigns a value that is not movable, the expression is retained, but its value is discarded. All movable expression statements (expressions that are not assigned) are removed. @@ -1006,22 +1008,22 @@ StructuralSimplifier This is a general step that performs various kinds of simplifications on a structural level: -- replace if statement with empty body by ``pop(condition)`` -- replace if statement with true condition by its body -- remove if statement with false condition -- turn switch with single case into if -- replace switch with only default case by ``pop(expression)`` and body -- replace switch with literal expression by matching case body -- replace for loop with false condition by its initialization part +- replace ``if`` statement with empty body by ``pop(condition)`` +- replace ``if`` statement with true condition by its body +- remove ``if`` statement with false condition +- turn ``switch`` with single case into ``if`` +- replace ``switch`` with only default case by ``pop(expression)`` and body +- replace ``switch`` with literal expression by matching case body +- replace ``for`` loop with false condition by its initialization part -This component uses the Dataflow Analyzer. +This component uses the DataflowAnalyzer. .. _block-flattener: BlockFlattener ^^^^^^^^^^^^^^ -This stage eliminates nested blocks by inserting the statement in the +This stage eliminates nested blocks by inserting the statements in the inner block at the appropriate place in the outer block. It depends on the FunctionGrouper and does not flatten the outermost block to keep the form produced by the FunctionGrouper. @@ -1062,10 +1064,9 @@ This optimization moves movable SSA variable declarations outside the loop. Only statements at the top level in a loop's body or post block are considered, i.e variable declarations inside conditional branches will not be moved out of the loop. -Requirements: +ExpressionSplitter and SSATransform should be run upfront to obtain better results. -- The Disambiguator, ForLoopInitRewriter and FunctionHoister must be run upfront. -- Expression splitter and SSA transform should be run upfront to obtain better result. +Prerequisites: Disambiguator, ForLoopInitRewriter, FunctionHoister. Function-Level Optimizations @@ -1092,7 +1093,7 @@ function ``f_1`` that takes only one argument, i.e., Other optimization steps will be able to make more simplifications to the function. The optimization step is mainly useful for functions that would not be inlined. -Prerequisites: Disambiguator, FunctionHoister +Prerequisites: Disambiguator, FunctionHoister. LiteralRematerialiser is recommended as a prerequisite, even though it's not required for correctness. @@ -1122,7 +1123,7 @@ The step LiteralRematerialiser is not required for correctness. It helps deal wi ``function f(x) -> y { revert(y, y} }`` where the literal ``y`` will be replaced by its value ``0``, allowing us to rewrite the function. -.. index:: ! unused store eliminator +.. index:: ! UnusedStoreEliminator .. _unused-store-eliminator: UnusedStoreEliminator @@ -1149,7 +1150,7 @@ For example, the following code sstore(c, 3) } -will be transformed into the code below after the Unused Store Eliminator step is run +will be transformed into the code below after the UnusedStoreEliminator step is run .. code-block:: yul @@ -1159,7 +1160,7 @@ will be transformed into the code below after the Unused Store Eliminator step i sstore(c, 3) } -For memory store operations, things are generally simpler, at least in the outermost yul block as all such +For memory store operations, things are generally simpler, at least in the outermost Yul block as all such statements will be removed if they are never read from in any code path. At function analysis level, however, the approach is similar to ``sstore``, as we do not know whether the memory location will be read once we leave the function's scope, so the statement will be removed only if all code paths lead to a memory overwrite. @@ -1177,8 +1178,8 @@ If two functions are syntactically equivalent, while allowing variable renaming but not any re-ordering, then any reference to one of the functions is replaced by the other. -The actual removal of the function is performed by the Unused Pruner. +The actual removal of the function is performed by the UnusedPruner. Function Inlining ----------------- @@ -1199,7 +1200,7 @@ Furthermore, for all parameters, all of the following need to be true: - The argument is movable. - The parameter is either referenced less than twice in the function body, or the argument is rather cheap - ("cost" of at most 1, like a constant up to 0xff). + ("cost" of at most 1, like a constant up to ``0xff``). Example: The function to be inlined has the form of ``function f(...) -> r { r := E }`` where ``E`` is an expression that does not reference ``r`` and all arguments in the function call are movable expressions. @@ -1255,7 +1256,7 @@ variables as much as possible. ExpressionJoiner ^^^^^^^^^^^^^^^^ -This is the opposite operation of the expression splitter. It turns a sequence of +This is the opposite operation of the ExpressionSplitter. It turns a sequence of variable declarations that have exactly one reference into a complex expression. This stage fully preserves the order of function calls and opcode executions. It does not make use of any information concerning the commutativity of the opcodes; @@ -1275,21 +1276,21 @@ Because of that, the snippet ``let x := add(0, 2) let y := mul(x, 3)`` is transformed to ``let y := mul(add(0, 2), 3)``, even though the ``add`` opcode would be executed after the evaluation of the literal ``3``. -.. _SSA-reverser: +.. _ssa-reverser: SSAReverser ^^^^^^^^^^^ -This is a tiny step that helps in reversing the effects of the SSA transform -if it is combined with the Common Subexpression Eliminator and the -Unused Pruner. +This is a tiny step that helps in reversing the effects of the SSATransform +if it is combined with the CommonSubexpressionEliminator and the +UnusedPruner. The SSA form we generate is detrimental to code generation because it produces many local variables. It would be better to just re-use existing variables with assignments instead of fresh variable declarations. -The SSA transform rewrites +The SSATransform rewrites .. code-block:: yul @@ -1307,7 +1308,7 @@ to a := a_2 The problem is that instead of ``a``, the variable ``a_1`` is used -whenever ``a`` was referenced. The SSA transform changes statements +whenever ``a`` was referenced. The SSATransform changes statements of this form by just swapping out the declaration and the assignment. The above snippet is turned into @@ -1320,10 +1321,10 @@ snippet is turned into let a_2 := a This is a very simple equivalence transform, but when we now run the -Common Subexpression Eliminator, it will replace all occurrences of ``a_1`` -by ``a`` (until ``a`` is re-assigned). The Unused Pruner will then +CommonSubexpressionEliminator, it will replace all occurrences of ``a_1`` +by ``a`` (until ``a`` is re-assigned). The UnusedPruner will then eliminate the variable ``a_1`` altogether and thus fully reverse the -SSA transform. +SSATransform. .. _stack-compressor: @@ -1354,9 +1355,9 @@ is comparatively cheap to evaluate. Furthermore, it is only semantically equival the value of the expression did not change between the point of assignment and the point of use. The main benefit of this stage is that it can save stack slots if it leads to a variable being eliminated completely (see below), but it can also -save a DUP opcode on the EVM if the expression is very cheap. +save a ``DUP`` opcode on the EVM if the expression is very cheap. -The Rematerialiser uses the Dataflow Analyzer to track the current values of variables, +The Rematerialiser uses the DataflowAnalyzer to track the current values of variables, which are always movable. If the value is very cheap or the variable was explicitly requested to be eliminated, the variable reference is replaced by its current value. From e6f48c2d5f8da82e595b691747d2f97a6822acaf Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 9 May 2024 20:46:38 +0200 Subject: [PATCH 0101/1340] Fix python version for Windows builds --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 34e2e3393..38bcaea7b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1728,8 +1728,8 @@ jobs: - run: git config --global core.autocrlf false - checkout - run: - name: Force install python3.12.2 - command: choco install python3 --pre --force --version=3.12.2 + name: Force install python3.12 + command: choco install python312 --pre --force - run: name: Create a symlink for python3 command: ln -s /c/ProgramData/chocolatey/bin/python3.12 /c/ProgramData/chocolatey/bin/python3 From e446713b917d50ea37dc05a280d7c582402d2d3c Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 9 May 2024 20:18:03 +0200 Subject: [PATCH 0102/1340] Fix archlinux build by disabling test --- test/yulPhaser/AlgorithmRunner.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/yulPhaser/AlgorithmRunner.cpp b/test/yulPhaser/AlgorithmRunner.cpp index 56868f1ce..f89a0d70f 100644 --- a/test/yulPhaser/AlgorithmRunner.cpp +++ b/test/yulPhaser/AlgorithmRunner.cpp @@ -434,6 +434,10 @@ BOOST_FIXTURE_TEST_CASE(run_should_overwrite_existing_file_if_autosave_file_spec BOOST_TEST(readLinesFromFile(m_autosavePath) != originalContent); } +// Disabled due to a fairly obscure bug in GCC 13+ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109561 +// The issue is on line 444, and more specifically the Options struct std::optional +/* BOOST_FIXTURE_TEST_CASE(run_should_not_save_population_to_file_if_autosave_file_not_specified, AlgorithmRunnerAutosaveFixture) { m_options.maxRounds = 5; @@ -445,6 +449,7 @@ BOOST_FIXTURE_TEST_CASE(run_should_not_save_population_to_file_if_autosave_file_ BOOST_TEST(!fs::exists(m_autosavePath)); } +*/ BOOST_FIXTURE_TEST_CASE(run_should_randomise_duplicate_chromosomes_if_requested, AlgorithmRunnerFixture) { From c9e2c20932f5635faf5e7715b8a6999f2a8895dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 14 Feb 2024 19:02:36 +0100 Subject: [PATCH 0103/1340] Fix a bug preventing repeated parts of optimizer sequence from ever stopping after the first cycle --- Changelog.md | 1 + libyul/optimiser/Suite.cpp | 4 +- test/cmdlineTests/optimizer_user_yul/output | 13 ++++++- .../copying/array_elements_to_mapping.sol | 2 +- .../array/copying/array_to_mapping.sol | 2 +- .../copying/calldata_array_to_mapping.sol | 2 +- ...d_array_of_structs_calldata_to_storage.sol | 6 +-- ...ted_array_of_structs_memory_to_storage.sol | 6 +-- ...d_array_of_structs_calldata_to_storage.sol | 6 +-- ...ted_array_of_structs_memory_to_storage.sol | 6 +-- .../copying/storage_memory_packed_dyn.sol | 2 +- .../externalContracts/deposit_contract.sol | 12 +++--- .../semanticTests/externalContracts/snark.sol | 4 +- .../functionCall/gas_and_value_basic.sol | 4 +- .../gas_and_value_brace_syntax.sol | 4 +- .../libraries/internal_types_in_library.sol | 2 +- .../copy_substructures_from_mapping.sol | 2 +- .../structs/copy_substructures_to_mapping.sol | 6 +-- .../semanticTests/structs/copy_to_mapping.sol | 8 ++-- .../mapping/copy_from_mapping_to_mapping.sol | 2 +- .../userDefinedValueType/calldata.sol | 4 +- .../skip_dynamic_types_for_structs.sol | 2 +- .../unusedFunctionParameterPruner_loop.yul | 38 ++++++++++++++++--- 23 files changed, 89 insertions(+), 49 deletions(-) diff --git a/Changelog.md b/Changelog.md index b924b1ccd..f34f803e6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Compiler Features: Bugfixes: * Commandline Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``--yul-optimizations`` sequence. + * Optimizer: Fix optimizer executing each repeating part of the step sequence at least twice, even if the code size already became stable after the first iteration. * SMTChecker: Fix false positive when comparing hashes of same array or string literals. * SMTChecker: Fix internal error on mapping access caused by too strong requirements on sort compatibility of the index and mapping domain. * SMTChecker: Fix internal error when using an empty tuple in a conditional operator. diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index d35cdc256..83bc03700 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -462,7 +462,9 @@ void OptimiserSuite::runSequence(std::string_view _stepAbbreviations, Block& _as subsequences.push_back({subsequence, true}); } - size_t codeSize = 0; + // NOTE: If _repeatUntilStable is false, the value will not be used so do not calculate it. + size_t codeSize = (_repeatUntilStable ? CodeSize::codeSizeIncludingFunctions(_ast) : 0); + for (size_t round = 0; round < MaxRounds; ++round) { for (auto const& [subsequence, repeat]: subsequences) diff --git a/test/cmdlineTests/optimizer_user_yul/output b/test/cmdlineTests/optimizer_user_yul/output index 689e82ddb..602a7de95 100644 --- a/test/cmdlineTests/optimizer_user_yul/output +++ b/test/cmdlineTests/optimizer_user_yul/output @@ -42,6 +42,7 @@ tag_5: /* "optimizer_user_yul/input.sol":263:269 a := 2 */ swap1 pop + 0x00 /* "optimizer_user_yul/input.sol":369:370 3 */ 0x03 /* "optimizer_user_yul/input.sol":366:367 2 */ @@ -58,10 +59,18 @@ tag_6: /* "optimizer_user_yul/input.sol":384:392 sload(5) */ dup1 /* "optimizer_user_yul/input.sol":376:509 for { } sload(5) { } {... */ - iszero - tag_6 + tag_8 jumpi + /* "optimizer_user_yul/input.sol":495:504 exp(x, y) */ + 0x01 + /* "optimizer_user_yul/input.sol":490:504 z := exp(x, y) */ + swap2 + pop + /* "optimizer_user_yul/input.sol":376:509 for { } sload(5) { } {... */ + jump(tag_6) +tag_8: /* "optimizer_user_yul/input.sol":380:383 { } */ + pop pop /* "optimizer_user_yul/input.sol":340:513 {... */ pop diff --git a/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol b/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol index b1e8659be..b138e7265 100644 --- a/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol +++ b/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol @@ -52,7 +52,7 @@ contract C { } // ---- // from_storage() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -// gas irOptimized: 150004 +// gas irOptimized: 150022 // gas legacy: 150745 // gas legacyOptimized: 148678 // from_storage_ptr() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 diff --git a/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol b/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol index 50ea19a1e..893610eb1 100644 --- a/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol +++ b/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol @@ -37,7 +37,7 @@ contract C { } // ---- // from_storage() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -// gas irOptimized: 147871 +// gas irOptimized: 147889 // gas legacy: 148896 // gas legacyOptimized: 146901 // from_storage_ptr() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 diff --git a/test/libsolidity/semanticTests/array/copying/calldata_array_to_mapping.sol b/test/libsolidity/semanticTests/array/copying/calldata_array_to_mapping.sol index e6bf7671a..b8bd588d5 100644 --- a/test/libsolidity/semanticTests/array/copying/calldata_array_to_mapping.sol +++ b/test/libsolidity/semanticTests/array/copying/calldata_array_to_mapping.sol @@ -14,4 +14,4 @@ contract C { // compileViaYul: true // ---- // from_calldata(uint8[][]): 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -// gas irOptimized: 139683 +// gas irOptimized: 139637 diff --git a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol index ea5625f21..6c5c0e8fa 100644 --- a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol @@ -31,8 +31,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][][]): 0x20, 1, 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 327874 +// gas irOptimized: 327883 // test2((uint8[],uint8[2])[][1][]): 0x20, 2, 0x40, 0x0160, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13, 0x20, 1, 0x20, 0x60, 31, 37, 2, 23, 29 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 140879 +// gas irOptimized: 140882 // test3((uint8[],uint8[2])[1][][2]): 0x20, 0x40, 0x60, 0, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 188535 +// gas irOptimized: 188541 diff --git a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol index 96f24f77d..a593b1d1d 100644 --- a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol @@ -31,8 +31,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][][]): 0x20, 1, 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 332660 +// gas irOptimized: 332687 // test2((uint8[],uint8[2])[][1][]): 0x20, 2, 0x40, 0x0160, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13, 0x20, 1, 0x20, 0x60, 31, 37, 2, 23, 29 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 145150 +// gas irOptimized: 145159 // test3((uint8[],uint8[2])[1][][2]): 0x20, 0x40, 0x60, 0, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 192598 +// gas irOptimized: 192616 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol index 844a86304..3666443bb 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol @@ -29,8 +29,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 304747 +// gas irOptimized: 304756 // test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 116464 +// gas irOptimized: 116467 // test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 188024 +// gas irOptimized: 188030 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol index 209a6ee69..821d33d4d 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol @@ -29,8 +29,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 309074 +// gas irOptimized: 309101 // test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 118256 +// gas irOptimized: 118265 // test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 190993 +// gas irOptimized: 191011 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol index 3ba5604a7..48d06ab4e 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol @@ -13,6 +13,6 @@ contract C { } // ---- // f() -> 2, 3, 4 -// gas irOptimized: 109108 +// gas irOptimized: 109104 // gas legacy: 122235 // gas legacyOptimized: 118411 diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index ce77683aa..5288d859b 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -176,8 +176,8 @@ contract DepositContract is IDepositContract, ERC165 { } // ---- // constructor() -// gas irOptimized: 809248 -// gas irOptimized code: 558000 +// gas irOptimized: 809628 +// gas irOptimized code: 563200 // gas legacy: 919945 // gas legacy code: 1437600 // gas legacyOptimized: 848464 @@ -187,27 +187,27 @@ contract DepositContract is IDepositContract, ERC165 { // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # // supportsInterface(bytes4): 0x8564090700000000000000000000000000000000000000000000000000000000 -> true # the deposit interface id # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 109009 +// gas irOptimized: 108921 // gas legacy: 142735 // gas legacyOptimized: 117558 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 109009 +// gas irOptimized: 108921 // gas legacy: 142735 // gas legacyOptimized: 117558 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 // get_deposit_root() -> 0x2089653123d9c721215120b6db6738ba273bbc5228ac093b1f983badcdc8a438 -// gas irOptimized: 108994 +// gas irOptimized: 108914 // gas legacy: 142744 // gas legacyOptimized: 117570 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 // get_deposit_root() -> 0x40255975859377d912c53aa853245ebd939bdd2b33a28e084babdcc1ed8238ee -// gas irOptimized: 108994 +// gas irOptimized: 108914 // gas legacy: 142744 // gas legacyOptimized: 117570 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index d3492a5c6..58f5e5804 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -294,11 +294,11 @@ contract Test { // f() -> true // g() -> true // pair() -> true -// gas irOptimized: 269697 +// gas irOptimized: 269701 // gas legacy: 275206 // gas legacyOptimized: 266925 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." -// gas irOptimized: 782210 +// gas irOptimized: 782238 // gas legacy: 801868 // gas legacyOptimized: 770942 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index 806c8eb41..2f8f62586 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -38,8 +38,8 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 120226 -// gas irOptimized code: 132400 +// gas irOptimized: 120912 +// gas irOptimized code: 140000 // gas legacy: 130568 // gas legacy code: 261000 // gas legacyOptimized: 121069 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol index c186fc40b..4821146e7 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol @@ -37,8 +37,8 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 120226 -// gas irOptimized code: 132400 +// gas irOptimized: 120912 +// gas irOptimized code: 140000 // gas legacy: 130568 // gas legacy code: 261000 // gas legacyOptimized: 121069 diff --git a/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol b/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol index 79d53273b..bdf4e4c30 100644 --- a/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol +++ b/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol @@ -22,6 +22,6 @@ contract Test { // ---- // library: Lib // f() -> 4, 0x11 -// gas irOptimized: 111560 +// gas irOptimized: 111629 // gas legacy: 132935 // gas legacyOptimized: 118023 diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol index 9b0fa9207..8091f5a24 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol @@ -44,7 +44,7 @@ contract C { } // ---- // to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121511 +// gas irOptimized: 121499 // gas legacy: 123117 // gas legacyOptimized: 121655 // to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol index a0834ca5b..2083032ff 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol @@ -52,14 +52,14 @@ contract C { } // ---- // from_memory() -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 122952 +// gas irOptimized: 122923 // gas legacy: 130136 // gas legacyOptimized: 128650 // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121622 +// gas irOptimized: 121616 // gas legacy: 123191 // gas legacyOptimized: 121760 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 115043 +// gas irOptimized: 115037 // gas legacy: 122425 // gas legacyOptimized: 120696 diff --git a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol index 033f0f518..c44277e4f 100644 --- a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol @@ -45,18 +45,18 @@ contract C { } // ---- // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121599 +// gas irOptimized: 121593 // gas legacy: 123053 // gas legacyOptimized: 121700 // from_storage() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121644 +// gas irOptimized: 121638 // gas legacy: 123102 // gas legacyOptimized: 121752 // from_memory() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 122860 +// gas irOptimized: 122831 // gas legacy: 129997 // gas legacyOptimized: 128646 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 21, 3, 0x666f6f0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 114958 +// gas irOptimized: 114952 // gas legacy: 118210 // gas legacyOptimized: 115324 diff --git a/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol b/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol index b17ba6d91..e1e1e3b26 100644 --- a/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol +++ b/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol @@ -29,6 +29,6 @@ contract C { } // ---- // f() -> 0x20, 7, 8, 9, 0xa0, 13, 2, 0x40, 0xa0, 2, 3, 4, 2, 3, 4 -// gas irOptimized: 197082 +// gas irOptimized: 197116 // gas legacy: 199891 // gas legacyOptimized: 196817 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol index 9ed64be08..ea1fc99b4 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol @@ -49,11 +49,11 @@ contract C { } // ---- // test_f() -> true -// gas irOptimized: 122078 +// gas irOptimized: 122094 // gas legacy: 125322 // gas legacyOptimized: 122709 // test_g() -> true -// gas irOptimized: 106215 +// gas irOptimized: 106271 // gas legacy: 111120 // gas legacyOptimized: 106964 // addresses(uint256): 0 -> 0x18 diff --git a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol index ef53a4e47..52287a8f3 100644 --- a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol +++ b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol @@ -19,6 +19,6 @@ contract C { } // ---- // g() -> 2, 6 -// gas irOptimized: 178263 +// gas irOptimized: 178277 // gas legacy: 180657 // gas legacyOptimized: 179156 diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_loop.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_loop.yul index f0b7546d0..148f4a1e7 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_loop.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_loop.yul @@ -20,18 +20,46 @@ // { // { // f() -// f() -// f() +// f_72() +// f_73() // sstore(0, 1) // } // function f() // { +// let a := 1 +// let b := 10 +// let a_1 := calldataload(0) +// let _1 := iszero(a_1) +// for { } iszero(b) { b := add(b, not(0)) } +// { +// a := a_1 +// mstore(a_1, 0) +// if _1 { leave } +// } +// } +// function f_72() +// { +// let a := 2 +// let b := 10 +// let a_1 := calldataload(0) +// let _1 := iszero(a_1) +// for { } iszero(b) { b := add(b, not(0)) } +// { +// a := a_1 +// mstore(a_1, 0) +// if _1 { leave } +// } +// } +// function f_73() +// { +// let a := 3 // let b := 10 -// let a := calldataload(0) -// let _1 := iszero(a) +// let a_1 := calldataload(0) +// let _1 := iszero(a_1) // for { } iszero(b) { b := add(b, not(0)) } // { -// mstore(a, 0) +// a := a_1 +// mstore(a_1, 0) // if _1 { leave } // } // } From 10afe0dd544836239dcb1e870a4d2628eb9f0d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 11 May 2024 19:43:45 +0200 Subject: [PATCH 0104/1340] Make fullSuite medium test case less artificial - The structural simplification here is pretty artificial while the main point of the test is resolution of memory loads. - In exchange add a simpler case covering structural simplification for the whole sequence. --- test/libyul/yulOptimizerTests/fullSuite/medium.yul | 4 +--- .../fullSuite/structural_simplification.yul | 11 +++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 test/libyul/yulOptimizerTests/fullSuite/structural_simplification.yul diff --git a/test/libyul/yulOptimizerTests/fullSuite/medium.yul b/test/libyul/yulOptimizerTests/fullSuite/medium.yul index 9a6381d79..911504071 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/medium.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/medium.yul @@ -12,9 +12,7 @@ if 0 { mstore(0x40, 0x20) } - if sub(2,1) { - for { switch mul(1,2) case 2 { mstore(0x40, 0x20) } } sub(1,1) {} { mstore(0x80, 0x40) } - } + mstore(0x40, 0x20) sstore(0, array_index_access(x, 3)) sstore(1, mload(0x40)) } diff --git a/test/libyul/yulOptimizerTests/fullSuite/structural_simplification.yul b/test/libyul/yulOptimizerTests/fullSuite/structural_simplification.yul new file mode 100644 index 000000000..85a975fde --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/structural_simplification.yul @@ -0,0 +1,11 @@ +{ + if sub(2, 1) { + mstore(0x40, 0x20) + for {} sub(1, 1) {} {} + } + sstore(1, mload(0x40)) +} +// ---- +// step: fullSuite +// +// { { sstore(1, 0x20) } } From 54ab398a44143fce6f63502f533c651f4d080bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 6 Mar 2024 12:00:27 +0100 Subject: [PATCH 0105/1340] Change the default optimizer sequence to the `the-good-parts-mk3` candidate - `the-good-parts` variant found using seqbench. - Third refinement: - adjusted to improve results for the erc20.sol contract. - adjustments to address regressions visible in test output of the previous version. --- libsolidity/interface/OptimiserSettings.h | 32 ++++++++++++----------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/libsolidity/interface/OptimiserSettings.h b/libsolidity/interface/OptimiserSettings.h index 46683088a..1ca46ccbc 100644 --- a/libsolidity/interface/OptimiserSettings.h +++ b/libsolidity/interface/OptimiserSettings.h @@ -43,23 +43,25 @@ struct OptimiserSettings { static char constexpr DefaultYulOptimiserSteps[] = "dhfoDgvulfnTUtnIf" // None of these can make stack problems worse - "[" - "xa[r]EscLM" // Turn into SSA and simplify - "cCTUtTOntnfDIul" // Perform structural simplification - "Lcul" // Simplify again - "Vcul [j]" // Reverse SSA - - // should have good "compilability" property here. - - "Tpeul" // Run functional expression inliner - "xa[rul]" // Prune a bit more in SSA - "xa[r]cL" // Turn into SSA again and simplify - "gvif" // Run full inliner - "CTUca[r]LSsTFOtfDnca[r]Iulc" // SSA plus simplify - "]" + + "xa[r]EscLM" // Turn into SSA and simplify + "Vcul [j]" // Reverse SSA + + // should have good "compilability" property here. + + "Trpeul" // Run functional expression inliner + "xa[r]cL" // Turn into SSA again and simplify + "gvifM" // Run full inliner + "CTUca[r]LSsTFOtfDnca[r]Iulc" // SSA plus simplify + + "scCTUt" + "gvifM" // Run full inliner + "x[scCTUt] TOntnfDIul" // Perform structural simplification + "gvifM" // Run full inliner + "jmul[jul] VcTOcul jmul"; // Make source short and pretty - static char constexpr DefaultYulOptimiserCleanupSteps[] = "fDnTOcmu"; + static char constexpr DefaultYulOptimiserCleanupSteps[] = "fDnTOcmuO"; /// No optimisations at all - not recommended. static OptimiserSettings none() From c12fe8a1d00485f10a0d51d05be3ff209795421d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 8 Mar 2024 20:27:38 +0100 Subject: [PATCH 0106/1340] Update gas expectations --- test/libsolidity/gasTests/abiv2_optimised.sol | 6 +++--- .../abiEncoderV1/abi_decode_v2_storage.sol | 4 ++-- .../abi_encode_calldata_slice.sol | 8 ++++---- .../struct/struct_storage_ptr.sol | 2 +- .../abi_encode_calldata_slice.sol | 8 ++++---- .../abiEncoderV2/abi_encode_v2.sol | 4 ++-- ...2_in_function_inherited_in_v1_contract.sol | 8 ++++---- .../abiEncoderV2/calldata_array.sol | 2 +- .../calldata_overlapped_dynamic_arrays.sol | 4 ++-- .../abiEncoderV2/storage_array_encoding.sol | 8 ++++---- .../abi_decode_simple_storage.sol | 4 ++-- .../array/array_memory_index_access.sol | 2 +- .../array/array_storage_index_access.sol | 18 ++++++++--------- .../array_storage_index_boundary_test.sol | 4 ++-- .../array/array_storage_index_zeroed_test.sol | 8 ++++---- .../array/array_storage_length_access.sol | 2 +- .../array/array_storage_push_empty.sol | 4 ++-- ...rray_storage_push_empty_length_address.sol | 4 ++-- .../array/array_storage_push_pop.sol | 4 ++-- .../arrays_complex_from_and_to_storage.sol | 4 ++-- .../array/byte_array_transitional_2.sol | 2 +- .../array/bytes_length_member.sol | 2 +- .../array/constant_var_as_array_length.sol | 4 ++-- .../copying/array_copy_calldata_storage.sol | 4 ++-- .../copying/array_copy_cleanup_uint40.sol | 2 +- .../copying/array_copy_clear_storage.sol | 2 +- .../copying/array_copy_different_packing.sol | 2 +- .../copying/array_copy_including_array.sol | 4 ++-- .../array/copying/array_copy_nested_array.sol | 4 ++-- ...ay_copy_storage_storage_different_base.sol | 2 +- ..._storage_storage_different_base_nested.sol | 2 +- .../array_copy_storage_storage_dyn_dyn.sol | 2 +- ...y_copy_storage_storage_dynamic_dynamic.sol | 2 +- ...ay_copy_storage_storage_static_dynamic.sol | 2 +- ...ray_copy_storage_storage_static_static.sol | 2 +- .../array_copy_storage_storage_struct.sol | 2 +- .../array_copy_storage_to_memory_nested.sol | 4 ++-- .../copying/array_copy_target_leftover.sol | 4 ++-- .../copying/array_copy_target_simple.sol | 2 +- .../copying/array_copy_target_simple_2.sol | 2 +- .../copying/array_elements_to_mapping.sol | 4 ++-- .../array_nested_calldata_to_storage.sol | 8 ++++---- .../array_nested_memory_to_storage.sol | 4 ++-- ...on_external_storage_to_storage_dynamic.sol | 4 ++-- ...o_storage_dynamic_different_mutability.sol | 4 ++-- .../array_of_struct_calldata_to_storage.sol | 2 +- .../array_of_struct_memory_to_storage.sol | 2 +- ..._containing_arrays_calldata_to_storage.sol | 2 +- ...ts_containing_arrays_memory_to_storage.sol | 2 +- .../array_storage_multi_items_per_slot.sol | 2 +- .../array/copying/array_to_mapping.sol | 4 ++-- .../copying/arrays_from_and_to_storage.sol | 2 +- .../array/copying/bytes_inside_mappings.sol | 4 ++-- .../copying/bytes_storage_to_storage.sol | 20 +++++++++---------- .../calldata_array_dynamic_to_storage.sol | 4 ++-- .../copying/calldata_array_to_mapping.sol | 2 +- ...nup_during_multi_element_per_slot_copy.sol | 4 ++-- .../copy_byte_array_in_struct_to_storage.sol | 8 ++++---- .../copying/copy_byte_array_to_storage.sol | 4 ++-- .../copy_function_internal_storage_array.sol | 2 +- .../array/copying/copy_removes_bytes_data.sol | 2 +- ...d_array_of_structs_calldata_to_storage.sol | 6 +++--- ...ted_array_of_structs_memory_to_storage.sol | 6 +++--- .../function_type_array_to_storage.sol | 8 ++++---- .../memory_dyn_2d_bytes_to_storage.sol | 4 ++-- ...ested_array_element_storage_to_storage.sol | 6 +++--- ...d_array_of_structs_calldata_to_storage.sol | 6 +++--- ...ted_array_of_structs_memory_to_storage.sol | 6 +++--- ...ed_array_of_structs_storage_to_storage.sol | 4 ++-- ...amic_array_element_calldata_to_storage.sol | 4 ++-- .../array/copying/storage_memory_nested.sol | 2 +- .../copying/storage_memory_nested_bytes.sol | 4 ++-- .../storage_memory_nested_from_pointer.sol | 2 +- .../copying/storage_memory_nested_struct.sol | 2 +- .../copying/storage_memory_packed_dyn.sol | 2 +- .../array/create_memory_array.sol | 2 +- .../array/delete/bytes_delete_element.sol | 4 ++-- .../array/dynamic_array_cleanup.sol | 2 +- .../array/dynamic_arrays_in_storage.sol | 2 +- .../array/dynamic_multi_array_cleanup.sol | 2 +- .../array/fixed_array_cleanup.sol | 2 +- .../array/fixed_arrays_as_return_type.sol | 6 +++--- .../array/fixed_arrays_in_constructors.sol | 2 +- .../array/function_array_cross_calls.sol | 8 ++++---- ...nvalid_encoding_for_storage_byte_array.sol | 4 ++-- .../array/pop/array_pop_array_transition.sol | 2 +- .../array/pop/array_pop_uint16_transition.sol | 2 +- .../array/pop/array_pop_uint24_transition.sol | 2 +- .../pop/byte_array_pop_long_storage_empty.sol | 2 +- ...ray_pop_long_storage_empty_garbage_ref.sol | 2 +- .../array/pop/byte_array_pop_masking_long.sol | 2 +- .../semanticTests/array/push/array_push.sol | 2 +- .../push/array_push_nested_from_calldata.sol | 4 ++-- .../array/push/array_push_struct.sol | 2 +- .../push/array_push_struct_from_calldata.sol | 4 ++-- .../array/push/byte_array_push_transition.sol | 2 +- .../array/push/nested_bytes_push.sol | 4 ++-- .../array/push/push_no_args_2d.sol | 4 ++-- .../array/push/push_no_args_bytes.sol | 2 +- .../semanticTests/array/reusing_memory.sol | 2 +- .../byte_array_to_storage_cleanup.sol | 8 ++++---- .../copy_from_calldata_removes_bytes_data.sol | 2 +- .../constructor/arrays_in_constructors.sol | 8 ++++---- .../bytes_in_constructors_packer.sol | 8 ++++---- .../bytes_in_constructors_unpacker.sol | 6 +++--- .../constructor_static_array_argument.sol | 4 ++-- .../constructor/no_callvalue_check.sol | 2 +- .../events/event_dynamic_array_storage.sol | 4 ++-- .../events/event_dynamic_array_storage_v2.sol | 4 ++-- .../event_dynamic_nested_array_storage_v2.sol | 4 ++-- .../events/event_indexed_string.sol | 4 ++-- .../externalContracts/FixedFeeRegistrar.sol | 8 ++++---- .../externalContracts/base64.sol | 12 +++++------ .../externalContracts/deposit_contract.sol | 16 +++++++-------- .../externalContracts/prbmath_signed.sol | 4 ++-- .../externalContracts/prbmath_unsigned.sol | 4 ++-- .../externalContracts/ramanujan_pi.sol | 4 ++-- .../semanticTests/externalContracts/snark.sol | 4 ++-- .../externalContracts/strings.sol | 12 +++++------ .../creation_function_call_with_args.sol | 2 +- .../creation_function_call_with_salt.sol | 2 +- .../external_call_to_nonexisting.sol | 8 ++++---- ...ernal_call_to_nonexisting_debugstrings.sol | 8 ++++---- .../functionCall/gas_and_value_basic.sol | 4 ++-- .../gas_and_value_brace_syntax.sol | 4 ++-- .../mapping_array_internal_argument.sol | 2 +- .../immutable/multi_creation.sol | 2 +- .../semanticTests/immutable/use_scratch.sol | 2 +- ...ted_function_calldata_memory_interface.sol | 4 ++-- .../transient_storage_selfdestruct.sol | 4 ++-- .../balance_other_contract.sol | 4 ++-- .../libraries/internal_types_in_library.sol | 2 +- .../using_library_mappings_public.sol | 2 +- .../using_library_mappings_return.sol | 2 +- .../salted_create_with_value.sol | 4 ++-- .../storage/empty_nonempty_empty.sol | 4 ++-- .../storage/packed_storage_structs_bytes.sol | 2 +- ...ta_struct_with_nested_array_to_storage.sol | 4 ++-- .../conversion/recursive_storage_memory.sol | 2 +- .../structs/copy_from_mapping.sol | 4 ++-- .../copy_struct_array_from_storage.sol | 2 +- .../copy_substructures_from_mapping.sol | 4 ++-- .../structs/copy_substructures_to_mapping.sol | 12 +++++------ .../semanticTests/structs/copy_to_mapping.sol | 16 +++++++-------- .../structs/memory_structs_nested_load.sol | 2 +- ...truct_containing_bytes_copy_and_delete.sol | 8 ++++---- .../semanticTests/structs/struct_copy.sol | 4 ++-- .../structs/struct_copy_via_local.sol | 2 +- .../struct_delete_storage_with_array.sol | 4 ++-- .../struct_memory_to_storage_function_ptr.sol | 2 +- .../semanticTests/structs/structs.sol | 2 +- .../mapping/copy_from_mapping_to_mapping.sol | 4 ++-- .../userDefinedValueType/calldata.sol | 8 ++++---- .../userDefinedValueType/erc20.sol | 8 ++++---- .../semanticTests/various/address_code.sol | 6 +++--- .../semanticTests/various/create_calldata.sol | 4 ++-- .../various/destructuring_assignment.sol | 4 ++-- .../semanticTests/various/erc20.sol | 8 ++++---- .../various/many_subassemblies.sol | 2 +- ...uct_post_cancun_multiple_beneficiaries.sol | 6 +++--- .../selfdestruct_post_cancun_redeploy.sol | 6 +++--- ...ruct_pre_cancun_multiple_beneficiaries.sol | 6 +++--- .../selfdestruct_pre_cancun_redeploy.sol | 6 +++--- .../skip_dynamic_types_for_structs.sol | 4 ++-- .../various/staticcall_for_view_and_pure.sol | 2 +- .../semanticTests/various/value_complex.sol | 4 ++-- .../semanticTests/various/value_insane.sol | 4 ++-- .../viaYul/copy_struct_invalid_ir_bug.sol | 2 +- 168 files changed, 358 insertions(+), 358 deletions(-) diff --git a/test/libsolidity/gasTests/abiv2_optimised.sol b/test/libsolidity/gasTests/abiv2_optimised.sol index 8f407e6ed..2989c1acd 100644 --- a/test/libsolidity/gasTests/abiv2_optimised.sol +++ b/test/libsolidity/gasTests/abiv2_optimised.sol @@ -17,9 +17,9 @@ contract C { // optimize-yul: true // ---- // creation: -// codeDepositCost: 634600 -// executionCost: 668 -// totalCost: 635268 +// codeDepositCost: 618200 +// executionCost: 649 +// totalCost: 618849 // external: // a(): 2283 // b(uint256): 4649 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol index b4ef43c44..8d74a34f4 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol @@ -21,6 +21,6 @@ contract C { } // ---- // f() -> 0x20, 0x8, 0x40, 0x3, 0x9, 0xa, 0xb -// gas irOptimized: 203149 +// gas irOptimized: 203173 // gas legacy: 206263 -// gas legacyOptimized: 203156 +// gas legacyOptimized: 203172 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol index 3dd5dd269..a518a3750 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol @@ -59,10 +59,10 @@ contract C { // EVMVersion: >homestead // ---- // test_bytes() -> -// gas irOptimized: 306908 +// gas irOptimized: 314884 // gas legacy: 305827 -// gas legacyOptimized: 255013 +// gas legacyOptimized: 253681 // test_uint256() -> -// gas irOptimized: 435054 +// gas irOptimized: 448346 // gas legacy: 421315 -// gas legacyOptimized: 352838 +// gas legacyOptimized: 351650 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol index efffab86c..c8eb95418 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol @@ -24,6 +24,6 @@ contract C { // ---- // library: L // f() -> 8, 7, 1, 2, 7, 12 -// gas irOptimized: 166475 +// gas irOptimized: 166759 // gas legacy: 169283 // gas legacyOptimized: 167248 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol index 5457e7f67..b80d14d6b 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol @@ -60,10 +60,10 @@ contract C { // EVMVersion: >homestead // ---- // test_bytes() -> -// gas irOptimized: 306908 +// gas irOptimized: 314884 // gas legacy: 305827 -// gas legacyOptimized: 255013 +// gas legacyOptimized: 253681 // test_uint256() -> -// gas irOptimized: 435054 +// gas irOptimized: 448346 // gas legacy: 421315 -// gas legacyOptimized: 352838 +// gas legacyOptimized: 351650 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol index c0d5f5d3f..f07d4039d 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol @@ -50,6 +50,6 @@ contract C { // f2() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f3() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f4() -> 0x20, 0x160, 0x1, 0x80, 0xc0, 0x2, 0x3, "abc", 0x7, 0x40, 0x2, 0x2, 0x3 -// gas irOptimized: 111708 +// gas irOptimized: 111816 // gas legacy: 113892 -// gas legacyOptimized: 111646 +// gas legacyOptimized: 111658 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol index c41905e2a..bb3ad1aad 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol @@ -30,9 +30,9 @@ contract C is B { } // ---- // test() -> 77 -// gas irOptimized: 55148 -// gas irOptimized code: 55200 +// gas irOptimized: 55117 +// gas irOptimized code: 56800 // gas legacy: 57266 // gas legacy code: 94600 -// gas legacyOptimized: 55173 -// gas legacyOptimized code: 55200 +// gas legacyOptimized: 55195 +// gas legacyOptimized code: 55000 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol index f749e403b..cdce1b95a 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol @@ -20,6 +20,6 @@ contract C { // f(uint256[][1]): 32, 32, 0 -> true // f(uint256[][1]): 32, 32, 1, 42 -> true // f(uint256[][1]): 32, 32, 8, 421, 422, 423, 424, 425, 426, 427, 428 -> true -// gas irOptimized: 117157 +// gas irOptimized: 120978 // gas legacy: 101568 // gas legacyOptimized: 119092 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol index 46df31333..81c9c46c6 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol @@ -33,8 +33,8 @@ contract C { // f_which(uint256[],uint256[2],uint256): 0x40, 1, 2, 1, 5, 6 -> 0x20, 0x40, 5, 2 // f_which(uint256[],uint256[2],uint256): 0x40, 1, 2, 1 -> FAILURE // f_storage(uint256[],uint256[2]): 0x20, 1, 2 -> 0x20, 0x60, 0x20, 1, 2 -// gas irOptimized: 111395 +// gas irOptimized: 111415 // gas legacy: 112709 -// gas legacyOptimized: 111852 +// gas legacyOptimized: 111847 // f_storage(uint256[],uint256[2]): 0x40, 1, 2, 5, 6 -> 0x20, 0x80, 0x20, 2, 5, 6 // f_storage(uint256[],uint256[2]): 0x40, 1, 2, 5 -> FAILURE diff --git a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol index 14699df57..7eb93d401 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol @@ -18,10 +18,10 @@ contract C { // EVMVersion: >homestead // ---- // h(uint256[2][]): 0x20, 3, 123, 124, 223, 224, 323, 324 -> 32, 256, 0x20, 3, 123, 124, 223, 224, 323, 324 -// gas irOptimized: 180103 +// gas irOptimized: 180086 // gas legacy: 184235 -// gas legacyOptimized: 180873 +// gas legacyOptimized: 180857 // i(uint256[2][2]): 123, 124, 223, 224 -> 32, 128, 123, 124, 223, 224 -// gas irOptimized: 112104 +// gas irOptimized: 112031 // gas legacy: 115091 -// gas legacyOptimized: 112666 +// gas legacyOptimized: 112657 diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol index 9f59c4315..93e20b475 100644 --- a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol @@ -8,6 +8,6 @@ contract C { } // ---- // f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg" -// gas irOptimized: 135452 +// gas irOptimized: 135505 // gas legacy: 137096 -// gas legacyOptimized: 135834 +// gas legacyOptimized: 135824 diff --git a/test/libsolidity/semanticTests/array/array_memory_index_access.sol b/test/libsolidity/semanticTests/array/array_memory_index_access.sol index d313e7acb..49fc58c45 100644 --- a/test/libsolidity/semanticTests/array/array_memory_index_access.sol +++ b/test/libsolidity/semanticTests/array/array_memory_index_access.sol @@ -26,7 +26,7 @@ contract C { // index(uint256): 10 -> true // index(uint256): 20 -> true // index(uint256): 0xFF -> true -// gas irOptimized: 108291 +// gas irOptimized: 108272 // gas legacy: 181523 // gas legacyOptimized: 117443 // accessIndex(uint256,int256): 10, 1 -> 2 diff --git a/test/libsolidity/semanticTests/array/array_storage_index_access.sol b/test/libsolidity/semanticTests/array/array_storage_index_access.sol index 2589e4709..2957e6d98 100644 --- a/test/libsolidity/semanticTests/array/array_storage_index_access.sol +++ b/test/libsolidity/semanticTests/array/array_storage_index_access.sol @@ -16,38 +16,38 @@ contract C { // ---- // test_indices(uint256): 1 -> // test_indices(uint256): 129 -> -// gas irOptimized: 3003025 +// gas irOptimized: 3017687 // gas legacy: 3038654 // gas legacyOptimized: 2995964 // test_indices(uint256): 5 -> -// gas irOptimized: 576296 +// gas irOptimized: 579670 // gas legacy: 573810 // gas legacyOptimized: 571847 // test_indices(uint256): 10 -> -// gas irOptimized: 157009 +// gas irOptimized: 157953 // gas legacy: 160108 // gas legacyOptimized: 156996 // test_indices(uint256): 15 -> -// gas irOptimized: 171409 +// gas irOptimized: 172733 // gas legacy: 175973 // gas legacyOptimized: 171596 // test_indices(uint256): 0xFF -> -// gas irOptimized: 5645329 +// gas irOptimized: 5673823 // gas legacy: 5715748 // gas legacyOptimized: 5632556 // test_indices(uint256): 1000 -> -// gas irOptimized: 18068701 +// gas irOptimized: 18173005 // gas legacy: 18347810 // gas legacyOptimized: 18037248 // test_indices(uint256): 129 -> -// gas irOptimized: 4136840 +// gas irOptimized: 4166279 // gas legacy: 4140113 // gas legacyOptimized: 4108272 // test_indices(uint256): 128 -> -// gas irOptimized: 395769 +// gas irOptimized: 405522 // gas legacy: 433498 // gas legacyOptimized: 400909 // test_indices(uint256): 1 -> -// gas irOptimized: 580232 +// gas irOptimized: 583437 // gas legacy: 576715 // gas legacyOptimized: 575542 diff --git a/test/libsolidity/semanticTests/array/array_storage_index_boundary_test.sol b/test/libsolidity/semanticTests/array/array_storage_index_boundary_test.sol index c77aad0a4..494c99782 100644 --- a/test/libsolidity/semanticTests/array/array_storage_index_boundary_test.sol +++ b/test/libsolidity/semanticTests/array/array_storage_index_boundary_test.sol @@ -16,11 +16,11 @@ contract C { // test_boundary_check(uint256,uint256): 1, 1 -> FAILURE, hex"4e487b71", 0x32 // test_boundary_check(uint256,uint256): 10, 10 -> FAILURE, hex"4e487b71", 0x32 // test_boundary_check(uint256,uint256): 256, 256 -> FAILURE, hex"4e487b71", 0x32 -// gas irOptimized: 137913 +// gas irOptimized: 147246 // gas legacy: 133633 // gas legacyOptimized: 114354 // test_boundary_check(uint256,uint256): 256, 255 -> 0 -// gas irOptimized: 140048 +// gas irOptimized: 149422 // gas legacy: 135949 // gas legacyOptimized: 116533 // test_boundary_check(uint256,uint256): 256, 0xFFFF -> FAILURE, hex"4e487b71", 0x32 diff --git a/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol b/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol index 593358659..de260b373 100644 --- a/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol +++ b/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol @@ -52,18 +52,18 @@ contract C { // ---- // test_zeroed_indicies(uint256): 1 -> // test_zeroed_indicies(uint256): 5 -> -// gas irOptimized: 131315 +// gas irOptimized: 133763 // gas legacy: 131671 // gas legacyOptimized: 129994 // test_zeroed_indicies(uint256): 10 -> -// gas irOptimized: 224578 +// gas irOptimized: 228556 // gas legacy: 225237 // gas legacyOptimized: 222359 // test_zeroed_indicies(uint256): 15 -> -// gas irOptimized: 321962 +// gas irOptimized: 327360 // gas legacy: 322937 // gas legacyOptimized: 318919 // test_zeroed_indicies(uint256): 0xFF -> -// gas irOptimized: 5080806 +// gas irOptimized: 5180120 // gas legacy: 5093941 // gas legacyOptimized: 5020727 diff --git a/test/libsolidity/semanticTests/array/array_storage_length_access.sol b/test/libsolidity/semanticTests/array/array_storage_length_access.sol index 0669a3209..47fddc554 100644 --- a/test/libsolidity/semanticTests/array/array_storage_length_access.sol +++ b/test/libsolidity/semanticTests/array/array_storage_length_access.sol @@ -16,7 +16,7 @@ contract C { // gas legacy: 128571 // gas legacyOptimized: 110143 // set_get_length(uint256): 0xFFF -> 0xFFF -// gas irOptimized: 1209119 +// gas irOptimized: 1209116 // gas legacy: 1689548 // gas legacyOptimized: 1393535 // set_get_length(uint256): 0xFFFFF -> FAILURE # Out-of-gas # diff --git a/test/libsolidity/semanticTests/array/array_storage_push_empty.sol b/test/libsolidity/semanticTests/array/array_storage_push_empty.sol index 80376b423..b84cdd90a 100644 --- a/test/libsolidity/semanticTests/array/array_storage_push_empty.sol +++ b/test/libsolidity/semanticTests/array/array_storage_push_empty.sol @@ -12,11 +12,11 @@ contract C { // EVMVersion: >=petersburg // ---- // pushEmpty(uint256): 128 -// gas irOptimized: 401024 +// gas irOptimized: 410745 // gas legacy: 400640 // gas legacyOptimized: 388804 // pushEmpty(uint256): 256 -// gas irOptimized: 683700 +// gas irOptimized: 698285 // gas legacy: 685108 // gas legacyOptimized: 671480 // pushEmpty(uint256): 38869 -> FAILURE # out-of-gas # diff --git a/test/libsolidity/semanticTests/array/array_storage_push_empty_length_address.sol b/test/libsolidity/semanticTests/array/array_storage_push_empty_length_address.sol index 4b5b407ea..607e1ecd3 100644 --- a/test/libsolidity/semanticTests/array/array_storage_push_empty_length_address.sol +++ b/test/libsolidity/semanticTests/array/array_storage_push_empty_length_address.sol @@ -21,11 +21,11 @@ contract C { // gas legacy: 77730 // gas legacyOptimized: 77162 // set_get_length(uint256): 0xFF -> 0xFF -// gas irOptimized: 158881 +// gas irOptimized: 168565 // gas legacy: 696850 // gas legacyOptimized: 134488 // set_get_length(uint256): 0xFFF -> 0xFFF -// gas irOptimized: 1762213 +// gas irOptimized: 1908127 // gas legacy: 9857362 // gas legacyOptimized: 1393660 // set_get_length(uint256): 0xFFFFF -> FAILURE # Out-of-gas # diff --git a/test/libsolidity/semanticTests/array/array_storage_push_pop.sol b/test/libsolidity/semanticTests/array/array_storage_push_pop.sol index 5befbe228..78a74ab5d 100644 --- a/test/libsolidity/semanticTests/array/array_storage_push_pop.sol +++ b/test/libsolidity/semanticTests/array/array_storage_push_pop.sol @@ -17,11 +17,11 @@ contract C { // gas legacy: 105722 // gas legacyOptimized: 103508 // set_get_length(uint256): 0xFF -> 0 -// gas irOptimized: 815997 +// gas irOptimized: 833586 // gas legacy: 808020 // gas legacyOptimized: 784467 // set_get_length(uint256): 0xFFF -> 0 -// gas irOptimized: 12746889 +// gas irOptimized: 13029438 // gas legacy: 12612192 // gas legacyOptimized: 12239199 // set_get_length(uint256): 0xFFFF -> FAILURE # Out-of-gas # diff --git a/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol b/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol index 95280054a..918185e9a 100644 --- a/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol +++ b/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol @@ -12,9 +12,9 @@ contract Test { } // ---- // set(uint24[3][]): 0x20, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12 -> 0x06 -// gas irOptimized: 186557 +// gas irOptimized: 185219 // gas legacy: 211054 -// gas legacyOptimized: 206042 +// gas legacyOptimized: 206077 // data(uint256,uint256): 0x02, 0x02 -> 0x09 // data(uint256,uint256): 0x05, 0x01 -> 0x11 // data(uint256,uint256): 0x06, 0x00 -> FAILURE diff --git a/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol b/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol index 3e0f02225..401f97a1c 100644 --- a/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol +++ b/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol @@ -17,6 +17,6 @@ contract c { } // ---- // test() -> 0 -// gas irOptimized: 123560 +// gas irOptimized: 122719 // gas legacy: 147098 // gas legacyOptimized: 144200 diff --git a/test/libsolidity/semanticTests/array/bytes_length_member.sol b/test/libsolidity/semanticTests/array/bytes_length_member.sol index 0a3c58b3a..105bbfba8 100644 --- a/test/libsolidity/semanticTests/array/bytes_length_member.sol +++ b/test/libsolidity/semanticTests/array/bytes_length_member.sol @@ -13,7 +13,7 @@ contract c { // ---- // getLength() -> 0 // set(): 1, 2 -> true -// gas irOptimized: 110393 +// gas irOptimized: 110425 // gas legacy: 110952 // gas legacyOptimized: 110576 // getLength() -> 68 diff --git a/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol b/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol index 19acb7cba..342f3218f 100644 --- a/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol +++ b/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol @@ -8,11 +8,11 @@ contract C { } // ---- // constructor(): 1, 2, 3 -> -// gas irOptimized: 124816 +// gas irOptimized: 124991 // gas irOptimized code: 14800 // gas legacy: 134317 // gas legacy code: 46200 -// gas legacyOptimized: 127062 +// gas legacyOptimized: 127166 // gas legacyOptimized code: 23400 // a(uint256): 0 -> 1 // a(uint256): 1 -> 2 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol index 80ecd3e1c..96580c47d 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol @@ -20,7 +20,7 @@ contract c { } // ---- // store(uint256[9],uint8[3][]): 21, 22, 23, 24, 25, 26, 27, 28, 29, 0x140, 4, 1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33 -> 32 -// gas irOptimized: 648315 +// gas irOptimized: 647725 // gas legacy: 694356 -// gas legacyOptimized: 693864 +// gas legacyOptimized: 693850 // retrieve() -> 9, 28, 9, 28, 4, 3, 32 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol index 600f00a98..9609215a7 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol @@ -46,6 +46,6 @@ contract C { } // ---- // f() -> true -// gas irOptimized: 117264 +// gas irOptimized: 122592 // gas legacy: 124660 // gas legacyOptimized: 122801 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol index 0bdcda1d9..6c0ba7af6 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol @@ -13,6 +13,6 @@ contract C { } // ---- // f() -> 0 -// gas irOptimized: 107453 +// gas irOptimized: 108246 // gas legacy: 108218 // gas legacyOptimized: 107625 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol b/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol index 6e81269d8..2176655fe 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol @@ -18,6 +18,6 @@ contract c { } // ---- // test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x05000000000000000000000000000000000000000000000000 -// gas irOptimized: 207889 +// gas irOptimized: 208459 // gas legacy: 220707 // gas legacyOptimized: 220098 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol index 385f2ecfb..20aee3a29 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol @@ -35,12 +35,12 @@ contract c { } // ---- // test() -> 0x02000202 -// gas irOptimized: 4547793 +// gas irOptimized: 4549703 // gas legacy: 4475396 // gas legacyOptimized: 4447665 // storageEmpty -> 1 // clear() -> 0, 0 -// gas irOptimized: 4474777 +// gas irOptimized: 4478226 // gas legacy: 4407188 // gas legacyOptimized: 4381336 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol b/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol index 737e4b32b..0420f953b 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol @@ -12,6 +12,6 @@ contract c { } // ---- // test(uint256[2][]): 32, 3, 7, 8, 9, 10, 11, 12 -> 10 -// gas irOptimized: 689656 +// gas irOptimized: 689558 // gas legacy: 686178 -// gas legacyOptimized: 685628 +// gas legacyOptimized: 685612 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol index d477dc6cf..e292809b8 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol @@ -17,6 +17,6 @@ contract c { } // ---- // test() -> 5, 4 -// gas irOptimized: 205044 +// gas irOptimized: 205667 // gas legacy: 213863 // gas legacyOptimized: 212902 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol index 057119586..44fede749 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol @@ -21,6 +21,6 @@ contract c { } // ---- // test() -> 3, 4 -// gas irOptimized: 169565 +// gas irOptimized: 169669 // gas legacy: 175424 // gas legacyOptimized: 172535 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol index 99dd1ca93..1f102ea14 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol @@ -15,7 +15,7 @@ contract c { // ---- // setData1(uint256,uint256,uint256): 10, 5, 4 -> // copyStorageStorage() -> -// gas irOptimized: 111348 +// gas irOptimized: 111353 // gas legacy: 109272 // gas legacyOptimized: 109262 // getData2(uint256): 5 -> 10, 4 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol index 30173409e..03c1f4e87 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol @@ -17,6 +17,6 @@ contract c { } // ---- // test() -> 5, 4 -// gas irOptimized: 252929 +// gas irOptimized: 253591 // gas legacy: 250892 // gas legacyOptimized: 250046 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol index 971469dec..f4bf1b2d2 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol @@ -11,6 +11,6 @@ contract c { } // ---- // test() -> 9, 4 -// gas irOptimized: 123135 +// gas irOptimized: 123180 // gas legacy: 123567 // gas legacyOptimized: 123202 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol index 0d613e5e9..145a8060e 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol @@ -14,6 +14,6 @@ contract c { } // ---- // test() -> 8, 0 -// gas irOptimized: 196259 +// gas irOptimized: 196251 // gas legacy: 194843 // gas legacyOptimized: 194281 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol index cfb623393..7fa5ee515 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol @@ -17,7 +17,7 @@ contract c { } // ---- // test() -> 4, 5 -// gas irOptimized: 190694 +// gas irOptimized: 190628 // gas legacy: 190852 // gas legacyOptimized: 189658 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol index 6bd31ca5a..d88ac0674 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol @@ -15,6 +15,6 @@ contract C { } // ---- // f() -> 0x20, 2, 0x40, 0xa0, 2, 0, 1, 2, 2, 3 -// gas irOptimized: 161624 +// gas irOptimized: 161793 // gas legacy: 162203 -// gas legacyOptimized: 159934 +// gas legacyOptimized: 159953 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol b/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol index 10a48a18c..ebfbdeab9 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol @@ -17,6 +17,6 @@ contract c { } // ---- // test() -> 0xffffffff, 0x0000000000000000000000000a00090008000700060005000400030002000100, 0x0000000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 100980 +// gas irOptimized: 100495 // gas legacy: 158142 -// gas legacyOptimized: 141096 +// gas legacyOptimized: 141020 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol index a839e3bb4..309753066 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol @@ -18,6 +18,6 @@ contract c { } // ---- // test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x0 -// gas irOptimized: 273372 +// gas irOptimized: 273545 // gas legacy: 282604 // gas legacyOptimized: 281510 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol index f9e1cbd27..b08487417 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol @@ -18,6 +18,6 @@ contract c { } // ---- // test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x00 -// gas irOptimized: 233118 +// gas irOptimized: 232997 // gas legacy: 235697 // gas legacyOptimized: 235193 diff --git a/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol b/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol index b138e7265..085f72ed9 100644 --- a/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol +++ b/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol @@ -52,9 +52,9 @@ contract C { } // ---- // from_storage() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -// gas irOptimized: 150022 +// gas irOptimized: 149880 // gas legacy: 150745 -// gas legacyOptimized: 148678 +// gas legacyOptimized: 148700 // from_storage_ptr() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 // from_memory() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 // from_calldata(uint8[][]): 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol index 919e83298..ac37f794e 100644 --- a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol @@ -38,10 +38,10 @@ contract c { // compileViaYul: true // ---- // test1(uint256[][]): 0x20, 2, 0x40, 0x40, 2, 23, 42 -> 2, 65 -// gas irOptimized: 180716 +// gas irOptimized: 181041 // test2(uint256[][2]): 0x20, 0x40, 0x40, 2, 23, 42 -> 2, 65 -// gas irOptimized: 157544 +// gas irOptimized: 157604 // test3(uint256[2][]): 0x20, 2, 23, 42, 23, 42 -> 2, 65 -// gas irOptimized: 134634 +// gas irOptimized: 134813 // test4(uint256[2][2]): 23, 42, 23, 42 -> 65 -// gas irOptimized: 111252 +// gas irOptimized: 111177 diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol index eb4b1bbb9..e2228f993 100644 --- a/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol @@ -38,12 +38,12 @@ contract Test { } // ---- // test() -> 24 -// gas irOptimized: 226666 +// gas irOptimized: 226743 // gas legacy: 227084 // gas legacyOptimized: 226529 // test1() -> 3 // test2() -> 6 // test3() -> 24 -// gas irOptimized: 141225 +// gas irOptimized: 141325 // gas legacy: 142238 // gas legacyOptimized: 141365 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol index 01329504d..ab3c172d3 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol @@ -45,7 +45,7 @@ contract C { } // ---- // copyExternalStorageArrayOfFunctionType() -> true -// gas irOptimized: 104592 +// gas irOptimized: 104566 // gas legacy: 108554 -// gas legacyOptimized: 102413 +// gas legacyOptimized: 102405 // copyInternalArrayOfFunctionType() -> true diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol index 50756d0b0..2bb3bcf33 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol @@ -48,8 +48,8 @@ contract C { } // ---- // copyExternalStorageArraysOfFunctionType() -> true -// gas irOptimized: 104265 +// gas irOptimized: 104238 // gas legacy: 108295 -// gas legacyOptimized: 102146 +// gas legacyOptimized: 102162 // copyInternalArrayOfFunctionType() -> true // gas legacy: 104178 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol index 546a6e49e..3147401cf 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol @@ -17,4 +17,4 @@ contract C { // compileViaYul: true // ---- // f((uint128,uint64,uint128)[]): 0x20, 3, 0, 0, 12, 0, 11, 0, 10, 0, 0 -> 10, 11, 12 -// gas irOptimized: 119704 +// gas irOptimized: 120747 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_struct_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_of_struct_memory_to_storage.sol index 38e26e480..5b3fe1f70 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_struct_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_struct_memory_to_storage.sol @@ -19,4 +19,4 @@ contract C { // compileViaYul: true // ---- // f() -> 10, 11, 12 -// gas irOptimized: 118362 +// gas irOptimized: 118796 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol index c6e6c5876..09037719a 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol @@ -23,4 +23,4 @@ contract C { // compileViaYul: true // ---- // f((uint256[])[]): 0x20, 3, 0x60, 0x60, 0x60, 0x20, 3, 1, 2, 3 -> 3, 1 -// gas irOptimized: 326771 +// gas irOptimized: 327456 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol index 510e7c9a4..8b6ad78ea 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol @@ -26,4 +26,4 @@ contract C { // compileViaYul: true // ---- // f() -> 3, 3, 3, 1 -// gas irOptimized: 181890 +// gas irOptimized: 181932 diff --git a/test/libsolidity/semanticTests/array/copying/array_storage_multi_items_per_slot.sol b/test/libsolidity/semanticTests/array/copying/array_storage_multi_items_per_slot.sol index 5c44ef16a..82e65edf1 100644 --- a/test/libsolidity/semanticTests/array/copying/array_storage_multi_items_per_slot.sol +++ b/test/libsolidity/semanticTests/array/copying/array_storage_multi_items_per_slot.sol @@ -12,6 +12,6 @@ contract C { } // ---- // f() -> 1, 2, 3 -// gas irOptimized: 131915 +// gas irOptimized: 131939 // gas legacy: 134606 // gas legacyOptimized: 131938 diff --git a/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol b/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol index 893610eb1..75a68759b 100644 --- a/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol +++ b/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol @@ -37,8 +37,8 @@ contract C { } // ---- // from_storage() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -// gas irOptimized: 147889 +// gas irOptimized: 147761 // gas legacy: 148896 -// gas legacyOptimized: 146901 +// gas legacyOptimized: 146923 // from_storage_ptr() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 // from_memory() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 diff --git a/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol b/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol index 0deb396d3..af2983b06 100644 --- a/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol @@ -12,7 +12,7 @@ contract Test { // set(uint24[]): 0x20, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 -> 18 // gas irOptimized: 99616 // gas legacy: 103509 -// gas legacyOptimized: 101390 +// gas legacyOptimized: 101266 // data(uint256): 7 -> 8 // data(uint256): 15 -> 16 // data(uint256): 18 -> FAILURE diff --git a/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol b/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol index 19e5ddebd..e61b7dff7 100644 --- a/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol +++ b/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol @@ -5,11 +5,11 @@ contract c { } // ---- // set(uint256): 1, 2 -> true -// gas irOptimized: 110558 +// gas irOptimized: 110550 // gas legacy: 111312 // gas legacyOptimized: 110741 // set(uint256): 2, 2, 3, 4, 5 -> true -// gas irOptimized: 177509 +// gas irOptimized: 177501 // gas legacy: 178314 // gas legacyOptimized: 177716 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol index 24565b4c6..ea364d437 100644 --- a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol @@ -17,25 +17,25 @@ contract c { // ---- // f(uint256): 0 -> 0x20, 0x00 // f(uint256): 31 -> 0x20, 0x1f, 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e00 -// gas irOptimized: 103283 +// gas irOptimized: 103269 // gas legacy: 112883 -// gas legacyOptimized: 112629 +// gas legacyOptimized: 112647 // f(uint256): 32 -> 0x20, 0x20, 1780731860627700044960722568376592200742329637303199754547598369979440671 -// gas irOptimized: 117740 +// gas irOptimized: 117928 // gas legacy: 128943 -// gas legacyOptimized: 128864 +// gas legacyOptimized: 128854 // f(uint256): 33 -> 0x20, 33, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x2000000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 124080 +// gas irOptimized: 124200 // gas legacy: 136071 -// gas legacyOptimized: 135479 +// gas legacyOptimized: 135469 // f(uint256): 63 -> 0x20, 0x3f, 1780731860627700044960722568376592200742329637303199754547598369979440671, 14532552714582660066924456880521368950258152170031413196862950297402215316992 -// gas irOptimized: 127140 +// gas irOptimized: 127350 // gas legacy: 148671 -// gas legacyOptimized: 148709 +// gas legacyOptimized: 148699 // f(uint256): 12 -> 0x20, 0x0c, 0x0102030405060708090a0b0000000000000000000000000000000000000000 // gas legacy: 59345 // gas legacyOptimized: 57279 // f(uint256): 129 -> 0x20, 0x81, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f, 29063324697304692433803953038474361308315562010425523193971352996434451193439, 0x606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f, -57896044618658097711785492504343953926634992332820282019728792003956564819968 -// gas irOptimized: 416966 +// gas irOptimized: 417312 // gas legacy: 458976 -// gas legacyOptimized: 460674 +// gas legacyOptimized: 460664 diff --git a/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol b/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol index 706232d58..1da1d0a40 100644 --- a/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol @@ -9,6 +9,6 @@ contract C { } // ---- // f(uint256[]): 0x20, 0x03, 0x1, 0x2, 0x3 -> 0x1 -// gas irOptimized: 110968 +// gas irOptimized: 111096 // gas legacy: 111551 -// gas legacyOptimized: 111339 +// gas legacyOptimized: 111323 diff --git a/test/libsolidity/semanticTests/array/copying/calldata_array_to_mapping.sol b/test/libsolidity/semanticTests/array/copying/calldata_array_to_mapping.sol index b8bd588d5..48460586d 100644 --- a/test/libsolidity/semanticTests/array/copying/calldata_array_to_mapping.sol +++ b/test/libsolidity/semanticTests/array/copying/calldata_array_to_mapping.sol @@ -14,4 +14,4 @@ contract C { // compileViaYul: true // ---- // from_calldata(uint8[][]): 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -// gas irOptimized: 139637 +// gas irOptimized: 139587 diff --git a/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol b/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol index 36b94d7c3..e6284072d 100644 --- a/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol +++ b/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol @@ -16,8 +16,8 @@ contract C { } // ---- // constructor() -// gas irOptimized: 89121 -// gas irOptimized code: 137200 +// gas irOptimized: 90065 +// gas irOptimized code: 149000 // gas legacy: 89553 // gas legacy code: 126200 // gas legacyOptimized: 83556 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol index 33a4c7045..7c0459ef1 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol @@ -35,12 +35,12 @@ contract C { } // ---- // f() -> 0x40, 0x80, 6, 0x6162636465660000000000000000000000000000000000000000000000000000, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000 -// gas irOptimized: 179420 +// gas irOptimized: 179408 // gas legacy: 180675 -// gas legacyOptimized: 179700 +// gas legacyOptimized: 179686 // g() -> 0x40, 0xc0, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000, 0x11, 0x3132333435363738393233343536373839000000000000000000000000000000 -// gas irOptimized: 106349 +// gas irOptimized: 106344 // gas legacy: 109394 -// gas legacyOptimized: 106614 +// gas legacyOptimized: 106600 // h() -> 0x40, 0x60, 0x00, 0x00 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol index d4599cdb7..1fd42ab34 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol @@ -46,6 +46,6 @@ contract C { } // ---- // f() -> 0xff -// gas irOptimized: 143412 +// gas irOptimized: 143867 // gas legacy: 153395 -// gas legacyOptimized: 146720 +// gas legacyOptimized: 146689 diff --git a/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol b/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol index fb2177901..a6a64942d 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol @@ -15,6 +15,6 @@ contract C { } // ---- // test() -> 7 -// gas irOptimized: 122455 +// gas irOptimized: 122461 // gas legacy: 205176 // gas legacyOptimized: 204971 diff --git a/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol b/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol index 85c396fb4..48d02bdc7 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol @@ -7,7 +7,7 @@ contract c { } // ---- // set(): 1, 2, 3, 4, 5 -> true -// gas irOptimized: 177376 +// gas irOptimized: 177344 // gas legacy: 177954 // gas legacyOptimized: 177550 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol index 6c5c0e8fa..672e7435f 100644 --- a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol @@ -31,8 +31,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][][]): 0x20, 1, 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 327883 +// gas irOptimized: 327921 // test2((uint8[],uint8[2])[][1][]): 0x20, 2, 0x40, 0x0160, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13, 0x20, 1, 0x20, 0x60, 31, 37, 2, 23, 29 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 140882 +// gas irOptimized: 141162 // test3((uint8[],uint8[2])[1][][2]): 0x20, 0x40, 0x60, 0, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 188541 +// gas irOptimized: 188442 diff --git a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol index a593b1d1d..f232d8aba 100644 --- a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol @@ -31,8 +31,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][][]): 0x20, 1, 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 332687 +// gas irOptimized: 332567 // test2((uint8[],uint8[2])[][1][]): 0x20, 2, 0x40, 0x0160, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13, 0x20, 1, 0x20, 0x60, 31, 37, 2, 23, 29 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 145159 +// gas irOptimized: 145409 // test3((uint8[],uint8[2])[1][][2]): 0x20, 0x40, 0x60, 0, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 192616 +// gas irOptimized: 192248 diff --git a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol index 56a415079..097c7b4d1 100644 --- a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol @@ -46,11 +46,11 @@ contract C { } // ---- // test() -> 0x20, 0x14, "[a called][b called]" -// gas irOptimized: 116546 +// gas irOptimized: 116530 // gas legacy: 118845 -// gas legacyOptimized: 116887 +// gas legacyOptimized: 116844 // test2() -> 0x20, 0x14, "[b called][a called]" // test3() -> 0x20, 0x14, "[b called][a called]" -// gas irOptimized: 103147 +// gas irOptimized: 103150 // gas legacy: 102654 -// gas legacyOptimized: 101581 +// gas legacyOptimized: 101556 diff --git a/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol b/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol index 79882a74b..c54975479 100644 --- a/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol @@ -18,6 +18,6 @@ contract C { } // ---- // f() -> 3 -// gas irOptimized: 127422 +// gas irOptimized: 128296 // gas legacy: 129050 -// gas legacyOptimized: 128222 +// gas legacyOptimized: 128210 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol index f85b8eb9f..ad00ee8c5 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol @@ -70,15 +70,15 @@ contract C { } // ---- // test1() -> -// gas irOptimized: 150468 +// gas irOptimized: 150488 // gas legacy: 150949 // gas legacyOptimized: 150906 // test2() -> FAILURE -// gas irOptimized: 150378 +// gas irOptimized: 150389 // gas legacy: 150673 // gas legacyOptimized: 150576 // test3() -> -// gas irOptimized: 123762 +// gas irOptimized: 124300 // gas legacy: 125333 // gas legacyOptimized: 125127 // test4() -> FAILURE diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol index 3666443bb..3b774f56e 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol @@ -29,8 +29,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 304756 +// gas irOptimized: 304794 // test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 116467 +// gas irOptimized: 116653 // test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 188030 +// gas irOptimized: 188000 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol index 821d33d4d..35e7943b8 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol @@ -29,8 +29,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 309101 +// gas irOptimized: 309078 // test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 118265 +// gas irOptimized: 118314 // test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 191011 +// gas irOptimized: 191051 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_storage_to_storage.sol index c356e029f..d0d169159 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_storage_to_storage.sol @@ -63,7 +63,7 @@ contract C { // compileViaYul: true // ---- // test1() -// gas irOptimized: 123202 +// gas irOptimized: 123195 // test2() -// gas irOptimized: 123027 +// gas irOptimized: 123018 // test3() diff --git a/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol index dfb7c27ac..a4222be0b 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol @@ -30,7 +30,7 @@ contract C { // compileViaYul: true // ---- // test(uint8[][][]): 0x20, 2, 0x40, 0x60, 0, 2, 0x40, 0x80, 1, 7, 2, 8, 9 -// gas irOptimized: 138040 +// gas irOptimized: 137897 // test2(uint8[][]): 0x20, 2, 0x40, 0x80, 1, 7, 2, 8, 9 -// gas irOptimized: 164246 +// gas irOptimized: 164506 // gas legacyOptimized: 120228 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol index 9a2fbb4d9..ac92189e4 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol @@ -17,6 +17,6 @@ contract C { } // ---- // f() -> 1, 2, 3, 4, 5, 6, 7 -// gas irOptimized: 205783 +// gas irOptimized: 206440 // gas legacy: 211765 // gas legacyOptimized: 211181 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol index 0e8cff97f..b743a5825 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol @@ -11,6 +11,6 @@ contract C { } // ---- // f() -> 0x20, 0x02, 0x40, 0x80, 3, 0x6162630000000000000000000000000000000000000000000000000000000000, 0x99, 44048183304486788312148433451363384677562265908331949128489393215789685032262, 32241931068525137014058842823026578386641954854143559838526554899205067598957, 49951309422467613961193228765530489307475214998374779756599339590522149884499, 0x54555658595a6162636465666768696a6b6c6d6e6f707172737475767778797a, 0x4142434445464748494a4b4c4d4e4f5051525354555658595a00000000000000 -// gas irOptimized: 202162 +// gas irOptimized: 202083 // gas legacy: 204328 -// gas legacyOptimized: 202887 +// gas legacyOptimized: 202900 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol index 3606d7d60..da7187a27 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol @@ -18,6 +18,6 @@ contract C { } // ---- // f() -> 1, 2, 3, 4, 5, 6, 7 -// gas irOptimized: 205783 +// gas irOptimized: 206440 // gas legacy: 211770 // gas legacyOptimized: 211186 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol index cfbf5c874..d4a348ea4 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol @@ -24,6 +24,6 @@ contract C { } // ---- // f() -> 11, 0x0c, 1, 0x15, 22, 4 -// gas irOptimized: 291047 +// gas irOptimized: 291212 // gas legacy: 293407 // gas legacyOptimized: 290218 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol index 48d06ab4e..c5bd7d0b0 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol @@ -13,6 +13,6 @@ contract C { } // ---- // f() -> 2, 3, 4 -// gas irOptimized: 109104 +// gas irOptimized: 114338 // gas legacy: 122235 // gas legacyOptimized: 118411 diff --git a/test/libsolidity/semanticTests/array/create_memory_array.sol b/test/libsolidity/semanticTests/array/create_memory_array.sol index d507f080f..a95499fd8 100644 --- a/test/libsolidity/semanticTests/array/create_memory_array.sol +++ b/test/libsolidity/semanticTests/array/create_memory_array.sol @@ -18,6 +18,6 @@ contract C { } // ---- // f() -> "A", 8, 4, "B" -// gas irOptimized: 125822 +// gas irOptimized: 136664 // gas legacy: 121382 // gas legacyOptimized: 115488 diff --git a/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol b/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol index fffea685a..5deaa7d4e 100644 --- a/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol +++ b/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol @@ -16,6 +16,6 @@ contract c { } // ---- // test1() -> true -// gas irOptimized: 204782 +// gas irOptimized: 218452 // gas legacy: 242256 -// gas legacyOptimized: 241192 +// gas legacyOptimized: 241182 diff --git a/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol b/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol index eb950d183..380e30242 100644 --- a/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol @@ -14,7 +14,7 @@ contract c { // ---- // storageEmpty -> 1 // fill() -> -// gas irOptimized: 519017 +// gas irOptimized: 519494 // gas legacy: 518936 // gas legacyOptimized: 515555 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol index 2f6769a24..62b611a87 100644 --- a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol +++ b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol @@ -41,7 +41,7 @@ contract c { // ---- // getLengths() -> 0, 0 // setLengths(uint256,uint256): 48, 49 -> -// gas irOptimized: 110797 +// gas irOptimized: 112674 // gas legacy: 108273 // gas legacyOptimized: 100269 // getLengths() -> 48, 49 diff --git a/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol b/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol index 7621d05bd..2db14a939 100644 --- a/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/dynamic_multi_array_cleanup.sol @@ -16,7 +16,7 @@ contract c { // ---- // storageEmpty -> 1 // fill() -> 8 -// gas irOptimized: 122742 +// gas irOptimized: 122985 // gas legacy: 121602 // gas legacyOptimized: 120589 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol index b4d9a30ec..cc009b7e9 100644 --- a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol @@ -10,7 +10,7 @@ contract c { // ---- // storageEmpty -> 1 // fill() -> -// gas irOptimized: 464834 +// gas irOptimized: 465013 // gas legacy: 468818 // gas legacyOptimized: 466238 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol b/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol index 0fb513543..e4bf3a719 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_as_return_type.sol @@ -18,9 +18,9 @@ contract B { } // ---- // f() -> 2, 3, 4, 5, 6, 1000, 1001, 1002, 1003, 1004 -// gas irOptimized: 59204 -// gas irOptimized code: 55200 +// gas irOptimized: 59212 +// gas irOptimized code: 56600 // gas legacy: 68001 // gas legacy code: 162000 -// gas legacyOptimized: 60037 +// gas legacyOptimized: 59997 // gas legacyOptimized code: 70600 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol index 0eb0f1e90..817d06c0f 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol @@ -9,7 +9,7 @@ contract Creator { } // ---- // constructor(): 1, 2, 3, 4 -> -// gas irOptimized: 103927 +// gas irOptimized: 104102 // gas irOptimized code: 22400 // gas legacy: 115186 // gas legacy code: 59000 diff --git a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol index e35e24bbf..e9517c0e3 100644 --- a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol +++ b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol @@ -42,9 +42,9 @@ contract C { } // ---- // test() -> 5, 6, 7 -// gas irOptimized: 86128 -// gas irOptimized code: 169600 +// gas irOptimized: 86484 +// gas irOptimized code: 161200 // gas legacy: 97576 // gas legacy code: 342800 -// gas legacyOptimized: 87851 -// gas legacyOptimized code: 190800 +// gas legacyOptimized: 87811 +// gas legacyOptimized code: 193000 diff --git a/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol b/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol index ddf67aa90..5fd53c6d1 100644 --- a/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol +++ b/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol @@ -40,9 +40,9 @@ contract C { // copyFromStorageShort() // x() -> 0x20, 3, 0x6162630000000000000000000000000000000000000000000000000000000000 // copyFromStorageLong() -// gas irOptimized: 121106 +// gas irOptimized: 121104 // gas legacy: 121904 -// gas legacyOptimized: 121398 +// gas legacyOptimized: 121388 // x() -> 0x20, 0x25, 0x3132333435363738393031323334353637383930313233343536373839303132, 0x3334353637000000000000000000000000000000000000000000000000000000 // copyToStorage() // x() -> 0x20, 0x25, 0x3132333435363738393031323334353637383930313233343536373839303132, 0x3334353637000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol b/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol index a08d27ac0..be1916ef1 100644 --- a/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol +++ b/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol @@ -23,7 +23,7 @@ contract c { } // ---- // test() -> 1, 2, 3 -// gas irOptimized: 1827730 +// gas irOptimized: 1828226 // gas legacy: 1822466 // gas legacyOptimized: 1813404 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol b/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol index 1b69ab336..73870d428 100644 --- a/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol +++ b/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol @@ -18,7 +18,7 @@ contract c { } // ---- // test() -> 38, 28, 18 -// gas irOptimized: 148538 +// gas irOptimized: 148380 // gas legacy: 151184 // gas legacyOptimized: 142418 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol b/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol index d2e5995c0..e0fc16581 100644 --- a/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol +++ b/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol @@ -18,7 +18,7 @@ contract c { } // ---- // test() -> 20, 10 -// gas irOptimized: 126068 +// gas irOptimized: 125889 // gas legacy: 127216 // gas legacyOptimized: 122224 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol index a3ba9d4d2..c567c4509 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol @@ -16,7 +16,7 @@ contract c { } // ---- // test() -> true -// gas irOptimized: 140154 +// gas irOptimized: 138848 // gas legacy: 178397 // gas legacyOptimized: 163832 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol index a014e761e..d9d2d9d2d 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol @@ -15,7 +15,7 @@ contract c { } // ---- // test() -> -// gas irOptimized: 113782 +// gas irOptimized: 113679 // gas legacy: 131245 // gas legacyOptimized: 126668 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol index 674b0841e..490de759b 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol @@ -9,6 +9,6 @@ contract c { } // ---- // test() -> 0x20, 33, 0x303030303030303030303030303030303030303030303030303030303030303, 0x0300000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 107183 +// gas irOptimized: 106778 // gas legacy: 121245 // gas legacyOptimized: 120370 diff --git a/test/libsolidity/semanticTests/array/push/array_push.sol b/test/libsolidity/semanticTests/array/push/array_push.sol index 3e7ceb5a8..6198ba163 100644 --- a/test/libsolidity/semanticTests/array/push/array_push.sol +++ b/test/libsolidity/semanticTests/array/push/array_push.sol @@ -16,6 +16,6 @@ contract c { } // ---- // test() -> 5, 4, 3, 3 -// gas irOptimized: 111363 +// gas irOptimized: 111834 // gas legacy: 111807 // gas legacyOptimized: 111122 diff --git a/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol b/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol index a010a9938..4bcac0f13 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol @@ -12,6 +12,6 @@ contract C { } // ---- // f(uint120[]): 0x20, 3, 1, 2, 3 -> 1 -// gas irOptimized: 112812 +// gas irOptimized: 112853 // gas legacy: 113659 -// gas legacyOptimized: 113482 +// gas legacyOptimized: 113466 diff --git a/test/libsolidity/semanticTests/array/push/array_push_struct.sol b/test/libsolidity/semanticTests/array/push/array_push_struct.sol index 06c5db88b..b6db507ea 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_struct.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_struct.sol @@ -20,6 +20,6 @@ contract c { } // ---- // test() -> 2, 3, 4, 5 -// gas irOptimized: 135103 +// gas irOptimized: 135329 // gas legacy: 147443 // gas legacyOptimized: 146434 diff --git a/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol b/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol index 4a33f816d..37de90cb6 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol @@ -16,6 +16,6 @@ contract c { } // ---- // test((uint16,uint16,uint16[3],uint16[])): 0x20, 2, 3, 0, 0, 4, 0xC0, 4, 0, 0, 5, 0, 0 -> 2, 3, 4, 5 -// gas irOptimized: 137061 +// gas irOptimized: 137153 // gas legacy: 142423 -// gas legacyOptimized: 137991 +// gas legacyOptimized: 137981 diff --git a/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol b/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol index 5f1fe0fac..763cb9a04 100644 --- a/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol +++ b/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol @@ -15,6 +15,6 @@ contract c { } // ---- // test() -> 0 -// gas irOptimized: 167700 +// gas irOptimized: 167569 // gas legacy: 206219 // gas legacyOptimized: 197297 diff --git a/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol b/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol index 30ed47920..aeaeb9ee7 100644 --- a/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol +++ b/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol @@ -13,6 +13,6 @@ contract C { } // ---- // f() -> -// gas irOptimized: 179112 +// gas irOptimized: 179534 // gas legacy: 181014 -// gas legacyOptimized: 180422 +// gas legacyOptimized: 180398 diff --git a/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol b/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol index 6901e32b8..00e454516 100644 --- a/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol +++ b/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol @@ -27,14 +27,14 @@ contract C { // ---- // l() -> 0 // f(uint256,uint256): 42, 64 -> -// gas irOptimized: 112266 +// gas irOptimized: 112288 // gas legacy: 107920 // gas legacyOptimized: 101897 // l() -> 1 // ll(uint256): 0 -> 43 // a(uint256,uint256): 0, 42 -> 64 // f(uint256,uint256): 84, 128 -> -// gas irOptimized: 118686 +// gas irOptimized: 118708 // gas legacy: 109972 // gas legacyOptimized: 96331 // l() -> 2 diff --git a/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol b/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol index b19ebcc73..b013a7ebb 100644 --- a/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol +++ b/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol @@ -21,7 +21,7 @@ contract C { // ---- // l() -> 0 // g(uint256): 70 -> -// gas irOptimized: 180849 +// gas irOptimized: 181778 // gas legacy: 175185 // gas legacyOptimized: 175005 // l() -> 70 diff --git a/test/libsolidity/semanticTests/array/reusing_memory.sol b/test/libsolidity/semanticTests/array/reusing_memory.sol index a7608f6e0..621860c07 100644 --- a/test/libsolidity/semanticTests/array/reusing_memory.sol +++ b/test/libsolidity/semanticTests/array/reusing_memory.sol @@ -24,7 +24,7 @@ contract Main { } // ---- // f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1 -// gas irOptimized: 99524 +// gas irOptimized: 99552 // gas irOptimized code: 12400 // gas legacy: 101554 // gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol index 8d0cb0a01..dab01b598 100644 --- a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol +++ b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol @@ -28,12 +28,12 @@ contract C { // compileViaYul: also // ---- // constructor() -> -// gas irOptimized: 81932 -// gas irOptimized code: 355200 +// gas irOptimized: 82100 +// gas irOptimized code: 357600 // gas legacy: 101472 // gas legacy code: 604200 -// gas legacyOptimized: 85004 -// gas legacyOptimized code: 392400 +// gas legacyOptimized: 84956 +// gas legacyOptimized code: 391800 // h() -> 0x20, 0x40, 0x00, 0 // ~ emit ev(uint256[],uint256): 0x40, 0x21, 0x02, 0x00, 0x00 // g() -> 0x20, 0x40, 0, 0x00 diff --git a/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol b/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol index aedf5ada4..09dcd0347 100644 --- a/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol +++ b/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol @@ -9,7 +9,7 @@ contract c { // EVMVersion: >=byzantium // ---- // (): 1, 2, 3, 4, 5 -> -// gas irOptimized: 155130 +// gas irOptimized: 155125 // gas legacy: 155473 // gas legacyOptimized: 155295 // checkIfDataIsEmpty() -> false diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index 3e60ba451..685b1a938 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -24,9 +24,9 @@ contract Creator { } // ---- // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 -// gas irOptimized: 328126 -// gas irOptimized code: 96400 +// gas irOptimized: 327784 +// gas irOptimized code: 94000 // gas legacy: 336626 // gas legacy code: 244800 -// gas legacyOptimized: 329599 -// gas legacyOptimized code: 115000 +// gas legacyOptimized: 329518 +// gas legacyOptimized code: 117000 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index c0b9df16c..0310d58d7 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -24,9 +24,9 @@ contract Creator { } // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" -// gas irOptimized: 169361 -// gas irOptimized code: 99200 +// gas irOptimized: 169292 +// gas irOptimized code: 99600 // gas legacy: 172944 // gas legacy code: 239800 -// gas legacyOptimized: 169858 -// gas legacyOptimized code: 117000 +// gas legacyOptimized: 169818 +// gas legacyOptimized code: 118600 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol index 0918a970e..4194e14a6 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol @@ -8,11 +8,11 @@ contract Test { } // ---- // constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> -// gas irOptimized: 180756 -// gas irOptimized code: 79200 +// gas irOptimized: 181465 +// gas irOptimized code: 78400 // gas legacy: 195165 // gas legacy code: 109400 -// gas legacyOptimized: 181600 +// gas legacyOptimized: 181609 // gas legacyOptimized code: 71400 // m_x() -> 7 // m_s() -> 0x20, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" diff --git a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol index e6ce445ad..327c41d9b 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol @@ -9,11 +9,11 @@ contract C { } // ---- // constructor(): 1, 2, 3, 4 -> -// gas irOptimized: 147975 +// gas irOptimized: 148129 // gas irOptimized code: 23000 // gas legacy: 157978 // gas legacy code: 60400 -// gas legacyOptimized: 150011 +// gas legacyOptimized: 149974 // gas legacyOptimized code: 26200 // a() -> 1 // b(uint256): 0 -> 2 diff --git a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol index b1dc80a40..583f1ca37 100644 --- a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol +++ b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol @@ -17,7 +17,7 @@ contract C { } // ---- // f(), 2000 ether -> true -// gas irOptimized: 117641 +// gas irOptimized: 117623 // gas irOptimized code: 1800 // gas legacy: 117821 // gas legacy code: 4800 diff --git a/test/libsolidity/semanticTests/events/event_dynamic_array_storage.sol b/test/libsolidity/semanticTests/events/event_dynamic_array_storage.sol index fec281c59..76acd4a0b 100644 --- a/test/libsolidity/semanticTests/events/event_dynamic_array_storage.sol +++ b/test/libsolidity/semanticTests/events/event_dynamic_array_storage.sol @@ -13,6 +13,6 @@ contract C { // ---- // createEvent(uint256): 42 -> // ~ emit E(uint256[]): 0x20, 0x03, 0x2a, 0x2b, 0x2c -// gas irOptimized: 113485 +// gas irOptimized: 114231 // gas legacy: 116314 -// gas legacyOptimized: 114407 +// gas legacyOptimized: 114408 diff --git a/test/libsolidity/semanticTests/events/event_dynamic_array_storage_v2.sol b/test/libsolidity/semanticTests/events/event_dynamic_array_storage_v2.sol index 2b5a7114d..bdcda3a09 100644 --- a/test/libsolidity/semanticTests/events/event_dynamic_array_storage_v2.sol +++ b/test/libsolidity/semanticTests/events/event_dynamic_array_storage_v2.sol @@ -14,6 +14,6 @@ contract C { // ---- // createEvent(uint256): 42 -> // ~ emit E(uint256[]): 0x20, 0x03, 0x2a, 0x2b, 0x2c -// gas irOptimized: 113485 +// gas irOptimized: 114231 // gas legacy: 116314 -// gas legacyOptimized: 114407 +// gas legacyOptimized: 114408 diff --git a/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol b/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol index d6cfb68be..324f456f6 100644 --- a/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol +++ b/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol @@ -15,6 +15,6 @@ contract C { // ---- // createEvent(uint256): 42 -> // ~ emit E(uint256[][]): 0x20, 0x02, 0x40, 0xa0, 0x02, 0x2a, 0x2b, 0x02, 0x2c, 0x2d -// gas irOptimized: 185033 +// gas irOptimized: 185148 // gas legacy: 187495 -// gas legacyOptimized: 184525 +// gas legacyOptimized: 184550 diff --git a/test/libsolidity/semanticTests/events/event_indexed_string.sol b/test/libsolidity/semanticTests/events/event_indexed_string.sol index 739619066..0ad2affe3 100644 --- a/test/libsolidity/semanticTests/events/event_indexed_string.sol +++ b/test/libsolidity/semanticTests/events/event_indexed_string.sol @@ -17,6 +17,6 @@ contract C { // ---- // deposit() -> // ~ emit E(string,uint256[4]): #0xa7fb06bb999a5eb9aff9e0779953f4e1e4ce58044936c2f51c7fb879b85c08bd, #0xe755d8cc1a8cde16a2a31160dcd8017ac32d7e2f13215b29a23cdae40a78aa81 -// gas irOptimized: 328856 +// gas irOptimized: 332789 // gas legacy: 365828 -// gas legacyOptimized: 362251 +// gas legacyOptimized: 362250 diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index 925ed54e6..47feaf525 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -74,12 +74,12 @@ contract FixedFeeRegistrar is Registrar { } // ---- // constructor() -// gas irOptimized: 77654 -// gas irOptimized code: 302200 +// gas irOptimized: 78076 +// gas irOptimized code: 307400 // gas legacy: 115395 // gas legacy code: 792400 -// gas legacyOptimized: 84566 -// gas legacyOptimized code: 387600 +// gas legacyOptimized: 84598 +// gas legacyOptimized code: 388000 // reserve(string), 69 ether: 0x20, 3, "abc" -> // ~ emit Changed(string): #0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 // gas irOptimized: 45967 diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol index aed2a11df..a986be149 100644 --- a/test/libsolidity/semanticTests/externalContracts/base64.sol +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -33,11 +33,11 @@ contract test { // EVMVersion: >=constantinople // ---- // constructor() -// gas irOptimized: 78952 -// gas irOptimized code: 320600 +// gas irOptimized: 79076 +// gas irOptimized code: 322000 // gas legacy: 102034 // gas legacy code: 627400 -// gas legacyOptimized: 87950 +// gas legacyOptimized: 87926 // gas legacyOptimized code: 429800 // encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 // encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" @@ -54,10 +54,10 @@ contract test { // encode_no_asm(bytes): 0x20, 5, "fooba" -> 0x20, 8, "Zm9vYmE=" // encode_no_asm(bytes): 0x20, 6, "foobar" -> 0x20, 8, "Zm9vYmFy" // encode_inline_asm_large() -// gas irOptimized: 1322025 +// gas irOptimized: 1406025 // gas legacy: 1554031 // gas legacyOptimized: 1132031 // encode_no_asm_large() -// gas irOptimized: 3206081 +// gas irOptimized: 3512081 // gas legacy: 4587075 -// gas legacyOptimized: 2823075 +// gas legacyOptimized: 2813075 diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index 5288d859b..9bfa3a340 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -176,38 +176,38 @@ contract DepositContract is IDepositContract, ERC165 { } // ---- // constructor() -// gas irOptimized: 809628 -// gas irOptimized code: 563200 +// gas irOptimized: 809602 +// gas irOptimized code: 558000 // gas legacy: 919945 // gas legacy code: 1437600 -// gas legacyOptimized: 848464 -// gas legacyOptimized code: 875200 +// gas legacyOptimized: 848699 +// gas legacyOptimized code: 878200 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # // supportsInterface(bytes4): 0x8564090700000000000000000000000000000000000000000000000000000000 -> true # the deposit interface id # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 108921 +// gas irOptimized: 109178 // gas legacy: 142735 // gas legacyOptimized: 117558 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e -// gas irOptimized: 108921 +// gas irOptimized: 109178 // gas legacy: 142735 // gas legacyOptimized: 117558 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 // get_deposit_root() -> 0x2089653123d9c721215120b6db6738ba273bbc5228ac093b1f983badcdc8a438 -// gas irOptimized: 108914 +// gas irOptimized: 109174 // gas legacy: 142744 // gas legacyOptimized: 117570 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 // get_deposit_root() -> 0x40255975859377d912c53aa853245ebd939bdd2b33a28e084babdcc1ed8238ee -// gas irOptimized: 108914 +// gas irOptimized: 109174 // gas legacy: 142744 // gas legacyOptimized: 117570 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index ddd639718..4990d24e9 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -48,8 +48,8 @@ contract test { } // ---- // constructor() -// gas irOptimized: 177336 -// gas irOptimized code: 1664400 +// gas irOptimized: 177903 +// gas irOptimized code: 1674400 // gas legacy: 209687 // gas legacy code: 2204400 // gas legacyOptimized: 178012 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index deacfd056..5d95c7a75 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -48,8 +48,8 @@ contract test { } // ---- // constructor() -// gas irOptimized: 168523 -// gas irOptimized code: 1547800 +// gas irOptimized: 170626 +// gas irOptimized code: 1577400 // gas legacy: 195146 // gas legacy code: 1998400 // gas legacyOptimized: 168857 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index cdaec8797..1aa72b897 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -33,8 +33,8 @@ contract test { } // ---- // constructor() -// gas irOptimized: 79503 -// gas irOptimized code: 328000 +// gas irOptimized: 77816 +// gas irOptimized code: 307600 // gas legacy: 92086 // gas legacy code: 523000 // gas legacyOptimized: 82667 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index 58f5e5804..97d15183a 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -294,11 +294,11 @@ contract Test { // f() -> true // g() -> true // pair() -> true -// gas irOptimized: 269701 +// gas irOptimized: 270424 // gas legacy: 275206 // gas legacyOptimized: 266925 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." -// gas irOptimized: 782238 +// gas irOptimized: 785783 // gas legacy: 801868 // gas legacyOptimized: 770942 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 102c85ae0..773d7156a 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -49,12 +49,12 @@ contract test { } // ---- // constructor() -// gas irOptimized: 95949 -// gas irOptimized code: 528000 +// gas irOptimized: 95303 +// gas irOptimized code: 520000 // gas legacy: 126106 // gas legacy code: 930200 -// gas legacyOptimized: 102559 -// gas legacyOptimized code: 611400 +// gas legacyOptimized: 102639 +// gas legacyOptimized code: 612400 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22660 // gas legacy: 23190 @@ -72,6 +72,6 @@ contract test { // gas legacy: 31621 // gas legacyOptimized: 27914 // benchmark(string,bytes32): 0x40, 0x0842021, 8, "solidity" -> 0x2020 -// gas irOptimized: 1980944 +// gas irOptimized: 1976778 // gas legacy: 4233999 -// gas legacyOptimized: 2318684 +// gas legacyOptimized: 2318670 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol index 1133dc2be..f7c05c10c 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol @@ -15,7 +15,7 @@ contract D { } // ---- // constructor(): 2 -> -// gas irOptimized: 138863 +// gas irOptimized: 138930 // gas irOptimized code: 53800 // gas legacy: 145570 // gas legacy code: 95600 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol index ba90a8ecd..9742a1d2f 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol @@ -17,7 +17,7 @@ contract D { // EVMVersion: >=constantinople // ---- // constructor(): 2 -> -// gas irOptimized: 139026 +// gas irOptimized: 139112 // gas irOptimized code: 53800 // gas legacy: 145936 // gas legacy code: 95600 diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol index 5b254a9f6..87f7cbebb 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol @@ -22,12 +22,12 @@ contract C { } // ---- // constructor(), 1 ether -> -// gas irOptimized: 89155 -// gas irOptimized code: 167800 +// gas irOptimized: 88853 +// gas irOptimized code: 164400 // gas legacy: 102626 // gas legacy code: 333200 -// gas legacyOptimized: 91471 -// gas legacyOptimized code: 196200 +// gas legacyOptimized: 91599 +// gas legacyOptimized code: 197800 // f(uint256): 0 -> FAILURE // f(uint256): 1 -> FAILURE // f(uint256): 2 -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol index 8bf182a89..9da010e9b 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol @@ -25,12 +25,12 @@ contract C { // revertStrings: debug // ---- // constructor(), 1 ether -> -// gas irOptimized: 98842 -// gas irOptimized code: 286000 +// gas irOptimized: 98698 +// gas irOptimized code: 284200 // gas legacy: 123163 // gas legacy code: 681200 -// gas legacyOptimized: 106957 -// gas legacyOptimized code: 386400 +// gas legacyOptimized: 107069 +// gas legacyOptimized code: 387800 // f(uint256): 0 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 1 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 2 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index 2f8f62586..bf6f2c4ba 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -38,8 +38,8 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 120912 -// gas irOptimized code: 140000 +// gas irOptimized: 120218 +// gas irOptimized code: 132000 // gas legacy: 130568 // gas legacy code: 261000 // gas legacyOptimized: 121069 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol index 4821146e7..ebc78a437 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol @@ -37,8 +37,8 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 120912 -// gas irOptimized code: 140000 +// gas irOptimized: 120218 +// gas irOptimized code: 132000 // gas legacy: 130568 // gas legacy code: 261000 // gas legacyOptimized: 121069 diff --git a/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol b/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol index 28c1822d7..7a9bf6014 100644 --- a/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol +++ b/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol @@ -18,7 +18,7 @@ contract test { } // ---- // set(uint8,uint8,uint8,uint8,uint8): 1, 21, 22, 42, 43 -> 0, 0, 0, 0 -// gas irOptimized: 111628 +// gas irOptimized: 111237 // gas legacy: 113748 // gas legacyOptimized: 111772 // get(uint8): 1 -> 21, 22, 42, 43 diff --git a/test/libsolidity/semanticTests/immutable/multi_creation.sol b/test/libsolidity/semanticTests/immutable/multi_creation.sol index c8806c50d..e1eb0621a 100644 --- a/test/libsolidity/semanticTests/immutable/multi_creation.sol +++ b/test/libsolidity/semanticTests/immutable/multi_creation.sol @@ -27,7 +27,7 @@ contract C { } // ---- // f() -> 3, 7, 5 -// gas irOptimized: 86821 +// gas irOptimized: 86796 // gas irOptimized code: 37200 // gas legacy: 87728 // gas legacy code: 60800 diff --git a/test/libsolidity/semanticTests/immutable/use_scratch.sol b/test/libsolidity/semanticTests/immutable/use_scratch.sol index dc07086c2..2ee05af91 100644 --- a/test/libsolidity/semanticTests/immutable/use_scratch.sol +++ b/test/libsolidity/semanticTests/immutable/use_scratch.sol @@ -15,7 +15,7 @@ contract C { } // ---- // constructor(): 3 -> -// gas irOptimized: 81126 +// gas irOptimized: 81194 // gas irOptimized code: 42400 // gas legacy: 88245 // gas legacy code: 109400 diff --git a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol index d5ff54b68..5234c27ad 100644 --- a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol +++ b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol @@ -25,5 +25,5 @@ contract B { // gas irOptimized: 100282 // gas legacy: 56840 // gas legacy code: 123600 -// gas legacyOptimized: 54996 -// gas legacyOptimized code: 57600 +// gas legacyOptimized: 55002 +// gas legacyOptimized code: 60600 diff --git a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol index f4975cd4c..a37520725 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol @@ -40,8 +40,8 @@ contract D { // EVMVersion: >=cancun // ---- // constructor() -> -// gas irOptimized: 127944 -// gas irOptimized code: 225200 +// gas irOptimized: 127596 +// gas irOptimized code: 221000 // gas legacy: 149357 // gas legacy code: 499800 // gas legacyOptimized: 125830 diff --git a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol index 0ad55b5dd..8ec19fffa 100644 --- a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol +++ b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol @@ -16,8 +16,8 @@ contract ClientReceipt { } // ---- // constructor(), 2000 wei -> -// gas irOptimized: 114107 -// gas irOptimized code: 55800 +// gas irOptimized: 114353 +// gas irOptimized code: 58800 // gas legacy: 118618 // gas legacy code: 111400 // gas legacyOptimized: 114067 diff --git a/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol b/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol index bdf4e4c30..817118473 100644 --- a/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol +++ b/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol @@ -22,6 +22,6 @@ contract Test { // ---- // library: Lib // f() -> 4, 0x11 -// gas irOptimized: 111629 +// gas irOptimized: 111419 // gas legacy: 132935 // gas legacyOptimized: 118023 diff --git a/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol b/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol index b3e06c5bc..bbdc92047 100644 --- a/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol +++ b/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol @@ -19,6 +19,6 @@ contract Test { // ---- // library: Lib // f() -> 1, 0, 0x2a, 0x17, 0, 0x63 -// gas irOptimized: 119635 +// gas irOptimized: 119837 // gas legacy: 124674 // gas legacyOptimized: 119669 diff --git a/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol b/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol index e9d855969..98cdf4fd1 100644 --- a/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol +++ b/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol @@ -17,6 +17,6 @@ contract Test { // ---- // library: Lib // f() -> 1, 0, 0x2a, 0x17, 0, 0x63 -// gas irOptimized: 120194 +// gas irOptimized: 119568 // gas legacy: 125109 // gas legacyOptimized: 120128 diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol index 735731c8a..083c9a5e4 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol @@ -21,8 +21,8 @@ contract A { // EVMVersion: >=constantinople // ---- // f(), 10 ether -> 3007, 3008, 3009 -// gas irOptimized: 187005 -// gas irOptimized code: 66000 +// gas irOptimized: 187022 +// gas irOptimized code: 67200 // gas legacy: 190863 // gas legacy code: 190200 // gas legacyOptimized: 187258 diff --git a/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol b/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol index 5f3242165..0c2f54b9e 100644 --- a/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol +++ b/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol @@ -22,9 +22,9 @@ contract Test { // set(bytes): 0x20, 0 // storageEmpty -> 1 // set(bytes): 0x20, 66, "12345678901234567890123456789012", "12345678901234567890123456789012", "12" -// gas irOptimized: 111886 +// gas irOptimized: 111852 // gas legacy: 112734 -// gas legacyOptimized: 112115 +// gas legacyOptimized: 112084 // storageEmpty -> 0 // set(bytes): 0x20, 3, "abc" // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol b/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol index 2c29abc79..75edb1c9e 100644 --- a/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol +++ b/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol @@ -42,6 +42,6 @@ contract C { } // ---- // test() -> true -// gas irOptimized: 132493 +// gas irOptimized: 132633 // gas legacy: 136009 // gas legacyOptimized: 133478 diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol index add42a8f3..ebf546fe2 100644 --- a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol +++ b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol @@ -16,6 +16,6 @@ contract C { } // ---- // f(uint32,(uint128,uint256[][2],uint32)): 55, 0x40, 77, 0x60, 88, 0x40, 0x40, 2, 1, 2 -> 55, 77, 1, 2, 88 -// gas irOptimized: 202843 +// gas irOptimized: 202902 // gas legacy: 207384 -// gas legacyOptimized: 203584 +// gas legacyOptimized: 203588 diff --git a/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol b/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol index 699836179..4465b1a3e 100644 --- a/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol +++ b/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol @@ -23,6 +23,6 @@ contract CopyTest { } // ---- // run() -> 2, 23, 42 -// gas irOptimized: 193677 +// gas irOptimized: 192828 // gas legacy: 185731 // gas legacyOptimized: 184458 diff --git a/test/libsolidity/semanticTests/structs/copy_from_mapping.sol b/test/libsolidity/semanticTests/structs/copy_from_mapping.sol index 8ee19a278..a072fb057 100644 --- a/test/libsolidity/semanticTests/structs/copy_from_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_from_mapping.sol @@ -36,8 +36,8 @@ contract C { } // ---- // to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121394 +// gas irOptimized: 121282 // gas legacy: 122978 -// gas legacyOptimized: 121648 +// gas legacyOptimized: 121652 // to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 diff --git a/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol b/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol index 937eeeaf4..29e7afca3 100644 --- a/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol +++ b/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol @@ -87,7 +87,7 @@ contract Test { // EVMVersion: >homestead // ---- // test1() -> true -// gas irOptimized: 152882 +// gas irOptimized: 152965 // gas legacy: 153012 // gas legacyOptimized: 152637 // test2() -> true diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol index 8091f5a24..61d2d68aa 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol @@ -44,8 +44,8 @@ contract C { } // ---- // to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121499 +// gas irOptimized: 121454 // gas legacy: 123117 -// gas legacyOptimized: 121655 +// gas legacyOptimized: 121659 // to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol index 2083032ff..7d458ca29 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol @@ -52,14 +52,14 @@ contract C { } // ---- // from_memory() -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 122923 +// gas irOptimized: 122720 // gas legacy: 130136 -// gas legacyOptimized: 128650 +// gas legacyOptimized: 128649 // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121616 +// gas irOptimized: 121424 // gas legacy: 123191 -// gas legacyOptimized: 121760 +// gas legacyOptimized: 121764 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 115037 +// gas irOptimized: 114852 // gas legacy: 122425 -// gas legacyOptimized: 120696 +// gas legacyOptimized: 120700 diff --git a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol index c44277e4f..068dc3d8c 100644 --- a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol @@ -45,18 +45,18 @@ contract C { } // ---- // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121593 +// gas irOptimized: 121515 // gas legacy: 123053 -// gas legacyOptimized: 121700 +// gas legacyOptimized: 121704 // from_storage() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 121638 +// gas irOptimized: 121559 // gas legacy: 123102 -// gas legacyOptimized: 121752 +// gas legacyOptimized: 121756 // from_memory() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 122831 +// gas irOptimized: 122740 // gas legacy: 129997 -// gas legacyOptimized: 128646 +// gas legacyOptimized: 128645 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 21, 3, 0x666f6f0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -// gas irOptimized: 114952 +// gas irOptimized: 114824 // gas legacy: 118210 -// gas legacyOptimized: 115324 +// gas legacyOptimized: 115329 diff --git a/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol b/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol index e5b139d5c..5ba976541 100644 --- a/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol +++ b/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol @@ -66,7 +66,7 @@ contract Test { } // ---- // load() -> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 -// gas irOptimized: 110317 +// gas irOptimized: 110772 // gas legacy: 112964 // gas legacyOptimized: 110876 // store() -> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 diff --git a/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol b/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol index 856edc27b..955e082b7 100644 --- a/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol +++ b/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol @@ -23,17 +23,17 @@ contract c { // ---- // storageEmpty -> 1 // set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true -// gas irOptimized: 133592 +// gas irOptimized: 133560 // gas legacy: 134628 -// gas legacyOptimized: 133871 +// gas legacyOptimized: 133858 // test(uint256): 32 -> "3" // storageEmpty -> 0 // copy() -> true // storageEmpty -> 1 // set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true -// gas irOptimized: 133592 +// gas irOptimized: 133560 // gas legacy: 134628 -// gas legacyOptimized: 133871 +// gas legacyOptimized: 133858 // storageEmpty -> 0 // del() -> true // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/structs/struct_copy.sol b/test/libsolidity/semanticTests/structs/struct_copy.sol index a321f0686..1fb9ef216 100644 --- a/test/libsolidity/semanticTests/structs/struct_copy.sol +++ b/test/libsolidity/semanticTests/structs/struct_copy.sol @@ -35,12 +35,12 @@ contract c { } // ---- // set(uint256): 7 -> true -// gas irOptimized: 109893 +// gas irOptimized: 109932 // gas legacy: 110597 // gas legacyOptimized: 110003 // retrieve(uint256): 7 -> 1, 3, 4, 2 // copy(uint256,uint256): 7, 8 -> true -// gas irOptimized: 118582 +// gas irOptimized: 118581 // gas legacy: 119147 // gas legacyOptimized: 118619 // retrieve(uint256): 7 -> 1, 3, 4, 2 diff --git a/test/libsolidity/semanticTests/structs/struct_copy_via_local.sol b/test/libsolidity/semanticTests/structs/struct_copy_via_local.sol index 71b40acc8..6b8788d2c 100644 --- a/test/libsolidity/semanticTests/structs/struct_copy_via_local.sol +++ b/test/libsolidity/semanticTests/structs/struct_copy_via_local.sol @@ -17,6 +17,6 @@ contract c { } // ---- // test() -> true -// gas irOptimized: 109706 +// gas irOptimized: 109921 // gas legacy: 110615 // gas legacyOptimized: 109705 diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol index d76618bbc..28998df44 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol @@ -42,10 +42,10 @@ contract C { } // ---- // f() -> -// gas irOptimized: 113210 +// gas irOptimized: 113477 // gas legacy: 113591 // gas legacyOptimized: 113103 // g() -> -// gas irOptimized: 118580 +// gas irOptimized: 118843 // gas legacy: 118764 // gas legacyOptimized: 118172 diff --git a/test/libsolidity/semanticTests/structs/struct_memory_to_storage_function_ptr.sol b/test/libsolidity/semanticTests/structs/struct_memory_to_storage_function_ptr.sol index 9af377469..bd9fcf3e2 100644 --- a/test/libsolidity/semanticTests/structs/struct_memory_to_storage_function_ptr.sol +++ b/test/libsolidity/semanticTests/structs/struct_memory_to_storage_function_ptr.sol @@ -28,6 +28,6 @@ contract C { } // ---- // f() -> 42, 23, 34, 42, 42 -// gas irOptimized: 110382 +// gas irOptimized: 110682 // gas legacy: 111993 // gas legacyOptimized: 110546 diff --git a/test/libsolidity/semanticTests/structs/structs.sol b/test/libsolidity/semanticTests/structs/structs.sol index b5e9d10bb..190387051 100644 --- a/test/libsolidity/semanticTests/structs/structs.sol +++ b/test/libsolidity/semanticTests/structs/structs.sol @@ -30,7 +30,7 @@ contract test { // ---- // check() -> false // set() -> -// gas irOptimized: 134417 +// gas irOptimized: 134073 // gas legacy: 135246 // gas legacyOptimized: 134062 // check() -> true diff --git a/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol b/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol index e1e1e3b26..19c31f288 100644 --- a/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol +++ b/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol @@ -29,6 +29,6 @@ contract C { } // ---- // f() -> 0x20, 7, 8, 9, 0xa0, 13, 2, 0x40, 0xa0, 2, 3, 4, 2, 3, 4 -// gas irOptimized: 197116 +// gas irOptimized: 197102 // gas legacy: 199891 -// gas legacyOptimized: 196817 +// gas legacyOptimized: 196845 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol index ea1fc99b4..1433386e5 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol @@ -49,13 +49,13 @@ contract C { } // ---- // test_f() -> true -// gas irOptimized: 122094 +// gas irOptimized: 122212 // gas legacy: 125322 -// gas legacyOptimized: 122709 +// gas legacyOptimized: 122694 // test_g() -> true -// gas irOptimized: 106271 +// gas irOptimized: 106428 // gas legacy: 111120 -// gas legacyOptimized: 106964 +// gas legacyOptimized: 106925 // addresses(uint256): 0 -> 0x18 // addresses(uint256): 1 -> 0x19 // addresses(uint256): 3 -> 0x1b diff --git a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol index 8976cf3c5..30aa590d6 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol @@ -113,12 +113,12 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 121082 -// gas irOptimized code: 231600 +// gas irOptimized: 121322 +// gas irOptimized code: 234600 // gas legacy: 163352 // gas legacy code: 671400 -// gas legacyOptimized: 127448 -// gas legacyOptimized code: 285200 +// gas legacyOptimized: 127464 +// gas legacyOptimized code: 285400 // totalSupply() -> 20 // gas irOptimized: 23415 // gas legacy: 23653 diff --git a/test/libsolidity/semanticTests/various/address_code.sol b/test/libsolidity/semanticTests/various/address_code.sol index f283aaeaa..8b601ca8c 100644 --- a/test/libsolidity/semanticTests/various/address_code.sol +++ b/test/libsolidity/semanticTests/various/address_code.sol @@ -14,11 +14,11 @@ contract C { } // ---- // constructor() -> -// gas irOptimized: 70351 -// gas irOptimized code: 95800 +// gas irOptimized: 70760 +// gas irOptimized code: 94600 // gas legacy: 82380 // gas legacy code: 153800 -// gas legacyOptimized: 69496 +// gas legacyOptimized: 69400 // gas legacyOptimized code: 79200 // initCode() -> 0x20, 0 // f() -> true diff --git a/test/libsolidity/semanticTests/various/create_calldata.sol b/test/libsolidity/semanticTests/various/create_calldata.sol index b8ec25209..3ca50db13 100644 --- a/test/libsolidity/semanticTests/various/create_calldata.sol +++ b/test/libsolidity/semanticTests/various/create_calldata.sol @@ -8,8 +8,8 @@ contract C { } // ---- // constructor(): 42 -> -// gas irOptimized: 67834 -// gas irOptimized code: 70400 +// gas irOptimized: 68239 +// gas irOptimized code: 69000 // gas legacy: 78029 // gas legacy code: 90200 // gas legacyOptimized: 68321 diff --git a/test/libsolidity/semanticTests/various/destructuring_assignment.sol b/test/libsolidity/semanticTests/various/destructuring_assignment.sol index b8236e2cd..82183a112 100644 --- a/test/libsolidity/semanticTests/various/destructuring_assignment.sol +++ b/test/libsolidity/semanticTests/various/destructuring_assignment.sol @@ -33,6 +33,6 @@ contract C { } // ---- // f(bytes): 0x20, 0x5, "abcde" -> 0 -// gas irOptimized: 241837 +// gas irOptimized: 242027 // gas legacy: 243284 -// gas legacyOptimized: 242420 +// gas legacyOptimized: 242395 diff --git a/test/libsolidity/semanticTests/various/erc20.sol b/test/libsolidity/semanticTests/various/erc20.sol index f7956c4c5..1a7718f68 100644 --- a/test/libsolidity/semanticTests/various/erc20.sol +++ b/test/libsolidity/semanticTests/various/erc20.sol @@ -96,12 +96,12 @@ contract ERC20 { // ---- // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 -// gas irOptimized: 121248 -// gas irOptimized code: 232000 +// gas irOptimized: 121632 +// gas irOptimized code: 236800 // gas legacy: 159959 // gas legacy code: 647600 -// gas legacyOptimized: 126918 -// gas legacyOptimized code: 281800 +// gas legacyOptimized: 126934 +// gas legacyOptimized code: 282000 // totalSupply() -> 20 // gas irOptimized: 23415 // gas legacy: 23524 diff --git a/test/libsolidity/semanticTests/various/many_subassemblies.sol b/test/libsolidity/semanticTests/various/many_subassemblies.sol index 67a576da7..b270c7006 100644 --- a/test/libsolidity/semanticTests/various/many_subassemblies.sol +++ b/test/libsolidity/semanticTests/various/many_subassemblies.sol @@ -30,7 +30,7 @@ contract D { } // ---- // run() -> -// gas irOptimized: 375015 +// gas irOptimized: 374934 // gas irOptimized code: 6600 // gas legacy: 375119 // gas legacy code: 17600 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol index 16797ee4c..690bff8d5 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol @@ -35,8 +35,8 @@ contract D { // EVMVersion: >=cancun // ---- // constructor(), 2 ether -> -// gas irOptimized: 107718 -// gas irOptimized code: 116200 +// gas irOptimized: 108104 +// gas irOptimized code: 119200 // gas legacy: 120424 // gas legacy code: 253600 // gas legacyOptimized: 109015 @@ -46,7 +46,7 @@ contract D { // balance -> 2000000000000000000 // exists() -> false // test_deploy_and_terminate_twice() -> -// gas irOptimized: 121350 +// gas irOptimized: 121395 // gas irOptimized code: 14000 // gas legacy: 122384 // gas legacy code: 43200 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol index 1b3022efe..1ae89a558 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol @@ -82,8 +82,8 @@ contract D { // EVMVersion: >=cancun // ---- // constructor(), 1 ether -> -// gas irOptimized: 132874 -// gas irOptimized code: 292400 +// gas irOptimized: 132974 +// gas irOptimized code: 293800 // gas legacy: 151217 // gas legacy code: 533400 // gas legacyOptimized: 131436 @@ -91,7 +91,7 @@ contract D { // exists() -> false // test_deploy_and_terminate() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 96394 +// gas irOptimized: 96528 // gas irOptimized code: 20800 // gas legacy: 97788 // gas legacy code: 20800 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol index a09a7cac6..dbe7109cb 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_multiple_beneficiaries.sol @@ -35,8 +35,8 @@ contract D { // EVMVersion: <=shanghai // ---- // constructor(), 2 ether -> -// gas irOptimized: 107718 -// gas irOptimized code: 116200 +// gas irOptimized: 108104 +// gas irOptimized code: 119200 // gas legacy: 120424 // gas legacy code: 253600 // gas legacyOptimized: 109015 @@ -46,7 +46,7 @@ contract D { // balance -> 2000000000000000000 // exists() -> false // test_deploy_and_terminate_twice() -> -// gas irOptimized: 121350 +// gas irOptimized: 121395 // gas irOptimized code: 14000 // gas legacy: 122384 // gas legacy code: 43200 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol index fc650ebba..0d7f2334e 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_pre_cancun_redeploy.sol @@ -79,8 +79,8 @@ contract D { // EVMVersion: =shanghai // ---- // constructor(), 1 ether -> -// gas irOptimized: 133253 -// gas irOptimized code: 297000 +// gas irOptimized: 133342 +// gas irOptimized code: 298400 // gas legacy: 151644 // gas legacy code: 538600 // gas legacyOptimized: 131799 @@ -88,7 +88,7 @@ contract D { // exists() -> false // test_deploy_and_terminate() -> // ~ emit Deployed(address,bytes32) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: 0x7e6580007e709ac52945fae182c61131d42634e8, 0x1234000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 96689 +// gas irOptimized: 96823 // gas irOptimized code: 20800 // gas legacy: 98095 // gas legacy code: 20800 diff --git a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol index 52287a8f3..9d078cfd6 100644 --- a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol +++ b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol @@ -19,6 +19,6 @@ contract C { } // ---- // g() -> 2, 6 -// gas irOptimized: 178277 +// gas irOptimized: 178195 // gas legacy: 180657 -// gas legacyOptimized: 179156 +// gas legacyOptimized: 179146 diff --git a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol index 77a330f3c..2063fff7a 100644 --- a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol +++ b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol @@ -45,7 +45,7 @@ contract D { // gas legacyOptimized: 98425380 // gas legacyOptimized code: 13200 // fpure() -> FAILURE -// gas irOptimized: 98425389 +// gas irOptimized: 98425388 // gas irOptimized code: 13200 // gas legacy: 98413174 // gas legacy code: 25600 diff --git a/test/libsolidity/semanticTests/various/value_complex.sol b/test/libsolidity/semanticTests/various/value_complex.sol index 427a006dc..dc92e38df 100644 --- a/test/libsolidity/semanticTests/various/value_complex.sol +++ b/test/libsolidity/semanticTests/various/value_complex.sol @@ -19,8 +19,8 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 114399 -// gas irOptimized code: 58000 +// gas irOptimized: 114463 +// gas irOptimized code: 58800 // gas legacy: 120076 // gas legacy code: 132200 // gas legacyOptimized: 114536 diff --git a/test/libsolidity/semanticTests/various/value_insane.sol b/test/libsolidity/semanticTests/various/value_insane.sol index 97fbbab1e..ad0e95701 100644 --- a/test/libsolidity/semanticTests/various/value_insane.sol +++ b/test/libsolidity/semanticTests/various/value_insane.sol @@ -18,8 +18,8 @@ contract test { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 114463 -// gas irOptimized code: 58800 +// gas irOptimized: 114527 +// gas irOptimized code: 59600 // gas legacy: 120200 // gas legacy code: 133600 // gas legacyOptimized: 114568 diff --git a/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol b/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol index 5a85ba075..fbaa7789e 100644 --- a/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol +++ b/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol @@ -21,6 +21,6 @@ contract C { } // ---- // f() -> -// gas irOptimized: 112969 +// gas irOptimized: 113118 // gas legacy: 112890 // gas legacyOptimized: 112580 From e19abe4b622da3ae7ab386e160f631bc8108f6d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 8 Mar 2024 20:33:07 +0100 Subject: [PATCH 0107/1340] Update other test expectations --- .../debug_info_in_yul_snippet_escaping/output | 62 +- test/cmdlineTests/function_debug_info/output | 4 +- .../output | 21 +- .../output | 21 +- test/cmdlineTests/name_simplifier/output | 136 +-- .../cmdlineTests/optimizer_array_sload/output | 15 +- test/cmdlineTests/optimizer_user_yul/output | 13 +- .../output.json | 152 +-- .../output.json | 140 +-- .../output.json | 1021 +++++++++-------- .../viair_subobject_optimization/output | 51 +- .../sizeLimits/combined_too_large_paris.sol | 6 +- .../combined_too_large_shanghai.sol | 8 +- .../initcode_too_large_shanghai.sol | 2 +- .../yulOptimizerTests/fullSuite/abi2.yul | 31 +- .../fullSuite/abi_example1.yul | 58 +- .../fullSuite/ackermann_function.yul | 3 +- .../fullSuite/ackermann_function_if.yul | 3 +- .../yulOptimizerTests/fullSuite/aztec.yul | 79 +- .../call_arguments_without_side_effects.yul | 29 +- .../fullSuite/create2_and_mask.yul | 5 +- .../fullSuite/create_and_mask.yul | 5 +- .../fullSuite/devcon_example.yul | 5 +- .../fullSuite/extcodelength.yul | 8 +- .../fullSuite/loopInvariantCodeMotion.yul | 5 +- ..._dependent_cse_bug_part_1_pre_shanghai.yul | 11 +- ..._dependent_cse_bug_part_2_pre_shanghai.yul | 11 +- .../fullSuite/stack_compressor_msize.yul | 28 +- .../fullSuite/structural_simplification.yul | 9 +- .../unusedFunctionParameterPruner_loop.yul | 38 +- 30 files changed, 965 insertions(+), 1015 deletions(-) diff --git a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output index 0bd6285b7..d5c02fc82 100644 --- a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output +++ b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output @@ -428,8 +428,7 @@ object "D_27" { { /// @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." let _1 := memoryguard(0x80) - let _2 := 64 - mstore(_2, _1) + mstore(64, _1) if iszero(lt(calldatasize(), 4)) { if eq(0x26121ff0, shr(224, calldataload(0))) @@ -437,10 +436,9 @@ object "D_27" { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } /// @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." - let _3 := datasize("C_2") - let _4 := add(_1, _3) - let _5 := 0xffffffffffffffff - if or(gt(_4, _5), lt(_4, _1)) + let _2 := datasize("C_2") + let _3 := add(_1, _2) + if or(gt(_3, 0xffffffffffffffff), lt(_3, _1)) { /// @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." mstore(0, shl(224, 0x4e487b71)) @@ -448,45 +446,53 @@ object "D_27" { revert(0, 0x24) } /// @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." - datacopy(_1, dataoffset("C_2"), _3) - if iszero(create(/** @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." */ 0, /** @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." */ _1, sub(_4, _1))) + datacopy(_1, dataoffset("C_2"), _2) + if iszero(create(/** @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." */ 0, /** @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." */ _1, sub(_3, _1))) { /// @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." - let pos := mload(_2) + let pos := mload(64) returndatacopy(pos, 0, returndatasize()) revert(pos, returndatasize()) } - let memPtr := mload(_2) - let newFreePtr := add(memPtr, _2) - if or(gt(newFreePtr, /** @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." */ _5), /** @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." */ lt(newFreePtr, memPtr)) + let memPtr := 0 + let size := 0 + size := 0 + let memPtr_1 := mload(64) + let newFreePtr := add(memPtr_1, 64) + if or(gt(newFreePtr, /** @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." */ 0xffffffffffffffff), /** @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." */ lt(newFreePtr, memPtr_1)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x41) revert(0, 0x24) } - mstore(_2, newFreePtr) - mstore(memPtr, 2) - mstore(add(memPtr, 32), "/*") - let memPtr_1 := mload(_2) - let newFreePtr_1 := add(memPtr_1, 96) - if or(gt(newFreePtr_1, /** @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." */ _5), /** @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." */ lt(newFreePtr_1, memPtr_1)) + mstore(64, newFreePtr) + memPtr := memPtr_1 + mstore(memPtr_1, 2) + mstore(add(memPtr_1, 32), "/*") + let memPtr_2 := 0 + let size_1 := 0 + size_1 := 0 + let memPtr_3 := mload(64) + let newFreePtr_1 := add(memPtr_3, 96) + if or(gt(newFreePtr_1, /** @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." */ 0xffffffffffffffff), /** @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." */ lt(newFreePtr_1, memPtr_3)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x41) revert(0, 0x24) } - mstore(_2, newFreePtr_1) - mstore(memPtr_1, 39) - let _6 := add(memPtr_1, 32) - mstore(_6, 0x2f2a2a204073726320303a39363a313635202022636f6e74726163742044207b) - mstore(add(memPtr_1, _2), shl(200, 0x2e2e2e22202a2f)) - let memPos := mload(_2) + mstore(64, newFreePtr_1) + memPtr_2 := memPtr_3 + mstore(memPtr_3, 39) + let _4 := add(memPtr_3, 32) + mstore(_4, 0x2f2a2a204073726320303a39363a313635202022636f6e74726163742044207b) + mstore(add(memPtr_3, 64), shl(200, 0x2e2e2e22202a2f)) + let memPos := mload(64) mstore(memPos, 32) - let length := mload(memPtr_1) + let length := mload(memPtr_3) mstore(add(memPos, 32), length) - mcopy(add(memPos, _2), _6, length) - mstore(add(add(memPos, length), _2), 0) - return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), _2)) + mcopy(add(memPos, 64), _4, length) + mstore(add(add(memPos, length), 64), 0) + return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), 64)) } } revert(0, 0) diff --git a/test/cmdlineTests/function_debug_info/output b/test/cmdlineTests/function_debug_info/output index bd7ba1197..c1346e33a 100644 --- a/test/cmdlineTests/function_debug_info/output +++ b/test/cmdlineTests/function_debug_info/output @@ -31,7 +31,7 @@ "returnSlots": 2 }, "abi_decode_tuple_t_uint256": { - "entryPoint": 269, + "entryPoint": 271, "parameterSlots": 2, "returnSlots": 1 }, @@ -40,7 +40,7 @@ "returnSlots": 1 }, "panic_error_0x32": { - "entryPoint": 292, + "entryPoint": 294, "parameterSlots": 0, "returnSlots": 0 } diff --git a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output index 2441357d9..170cdf1a7 100644 --- a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output +++ b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output @@ -22,25 +22,24 @@ object "C_14" { { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let _2 := 64 - let newFreePtr := add(_1, _2) + let newFreePtr := add(_1, 64) if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _1)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x41) revert(0, 36) } - mstore(_2, newFreePtr) + mstore(64, newFreePtr) mstore(_1, 5) - let _3 := add(_1, 0x20) - mstore(_3, "aaaaa") - let memPos := mload(_2) - mstore(memPos, 0x20) + let _2 := add(_1, 32) + mstore(_2, "aaaaa") + let memPos := mload(64) + mstore(memPos, 32) let length := mload(_1) - mstore(add(memPos, 0x20), length) - mcopy(add(memPos, _2), _3, length) - mstore(add(add(memPos, length), _2), 0) - return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), _2)) + mstore(add(memPos, 32), length) + mcopy(add(memPos, 64), _2, length) + mstore(add(add(memPos, length), 64), 0) + return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), 64)) } } revert(0, 0) diff --git a/test/cmdlineTests/mcopy_string_literal_returned_from_function/output b/test/cmdlineTests/mcopy_string_literal_returned_from_function/output index 02740ec0d..548c34de8 100644 --- a/test/cmdlineTests/mcopy_string_literal_returned_from_function/output +++ b/test/cmdlineTests/mcopy_string_literal_returned_from_function/output @@ -22,25 +22,24 @@ object "C_10" { { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let _2 := 64 - let newFreePtr := add(_1, _2) + let newFreePtr := add(_1, 64) if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _1)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x41) revert(0, 0x24) } - mstore(_2, newFreePtr) + mstore(64, newFreePtr) mstore(_1, 25) - let _3 := add(_1, 0x20) - mstore(_3, "MCOPY on Cancun vacation.") - let memPos := mload(_2) - mstore(memPos, 0x20) + let _2 := add(_1, 32) + mstore(_2, "MCOPY on Cancun vacation.") + let memPos := mload(64) + mstore(memPos, 32) let length := mload(_1) - mstore(add(memPos, 0x20), length) - mcopy(add(memPos, _2), _3, length) - mstore(add(add(memPos, length), _2), 0) - return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), _2)) + mstore(add(memPos, 32), length) + mcopy(add(memPos, 64), _2, length) + mstore(add(add(memPos, length), 64), 0) + return(memPos, add(sub(add(memPos, and(add(length, 31), not(31))), memPos), 64)) } } revert(0, 0) diff --git a/test/cmdlineTests/name_simplifier/output b/test/cmdlineTests/name_simplifier/output index 0a461e3e4..04abaf600 100644 --- a/test/cmdlineTests/name_simplifier/output +++ b/test/cmdlineTests/name_simplifier/output @@ -17,100 +17,104 @@ object "C_59" { code { { /// @src 0:346:625 "contract C {..." - let _1 := memoryguard(0x80) - let _2 := 4 - if iszero(lt(calldatasize(), _2)) + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) { if eq(0xf8eddcc6, shr(224, calldataload(0))) { if callvalue() { revert(0, 0) } - let _3 := 32 - if slt(add(calldatasize(), not(3)), _3) { revert(0, 0) } - let offset := calldataload(_2) - let _4 := 0xffffffffffffffff - if gt(offset, _4) { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + let offset := calldataload(4) + if gt(offset, 0xffffffffffffffff) { revert(0, 0) } if iszero(slt(add(offset, 35), calldatasize())) { revert(0, 0) } - let _5 := calldataload(add(_2, offset)) - let _6 := 36 - if gt(_5, _4) + let length := calldataload(add(4, offset)) + if gt(length, 0xffffffffffffffff) { mstore(0, shl(224, 0x4e487b71)) - mstore(_2, 0x41) - revert(0, _6) + mstore(4, 0x41) + revert(0, 36) } - let _7 := shl(5, _5) - let _8 := not(31) - let newFreePtr := add(_1, and(add(_7, 63), _8)) - if or(gt(newFreePtr, _4), lt(newFreePtr, _1)) + let _1 := shl(5, length) + let memPtr := 0 + memPtr := mload(64) + let newFreePtr := add(memPtr, and(add(_1, 63), not(31))) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { mstore(0, shl(224, 0x4e487b71)) - mstore(_2, 0x41) - revert(0, _6) + mstore(4, 0x41) + revert(0, 36) } - let _9 := 64 - mstore(_9, newFreePtr) - let dst := _1 - mstore(_1, _5) - dst := add(_1, _3) + mstore(64, newFreePtr) + let dst := memPtr + mstore(memPtr, length) + dst := add(memPtr, 32) let dst_1 := dst - let srcEnd := add(add(offset, _7), _6) + let srcEnd := add(add(offset, _1), 36) if gt(srcEnd, calldatasize()) { revert(0, 0) } - let src := add(offset, _6) - for { } lt(src, srcEnd) { src := add(src, _3) } + let src := add(offset, 36) + for { } lt(src, srcEnd) { src := add(src, 32) } { - if slt(sub(calldatasize(), src), _3) { revert(0, 0) } - let memPtr := mload(_9) - let newFreePtr_1 := add(memPtr, _3) - if or(gt(newFreePtr_1, _4), lt(newFreePtr_1, memPtr)) + if slt(sub(calldatasize(), src), 32) { revert(0, 0) } + let memPtr_1 := 0 + memPtr_1 := mload(64) + let newFreePtr_1 := add(memPtr_1, 32) + if or(gt(newFreePtr_1, 0xffffffffffffffff), lt(newFreePtr_1, memPtr_1)) { mstore(0, shl(224, 0x4e487b71)) - mstore(_2, 0x41) - revert(0, _6) + mstore(4, 0x41) + revert(0, 36) } - mstore(_9, newFreePtr_1) - mstore(memPtr, calldataload(src)) - mstore(dst, memPtr) - dst := add(dst, _3) + mstore(64, newFreePtr_1) + mstore(memPtr_1, calldataload(src)) + mstore(dst, memPtr_1) + dst := add(dst, 32) } - if iszero(mload(_1)) + /// @src 0:469:474 "_s[0]" + let addr := /** @src 0:346:625 "contract C {..." */ 0 + if iszero(mload(memPtr)) { mstore(0, shl(224, 0x4e487b71)) - mstore(_2, 0x32) - revert(0, _6) + mstore(4, 0x32) + revert(0, 36) } + addr := dst_1 sstore(0, mload(/** @src 0:469:474 "_s[0]" */ mload(dst_1))) - /// @src 0:346:625 "contract C {..." - if iszero(lt(/** @src 0:492:493 "1" */ 0x01, /** @src 0:346:625 "contract C {..." */ mload(_1))) + /// @src 0:489:494 "_s[1]" + let addr_1 := /** @src 0:346:625 "contract C {..." */ 0 + if iszero(lt(/** @src 0:492:493 "1" */ 0x01, /** @src 0:346:625 "contract C {..." */ mload(memPtr))) { mstore(0, shl(224, 0x4e487b71)) - mstore(_2, 0x32) - revert(0, _6) + mstore(4, 0x32) + revert(0, 36) } - let _10 := mload(/** @src 0:489:494 "_s[1]" */ mload(/** @src 0:346:625 "contract C {..." */ add(_1, _9))) - sstore(0x02, _10) - let memPtr_1 := mload(_9) - let newFreePtr_2 := add(memPtr_1, 160) - if or(gt(newFreePtr_2, _4), lt(newFreePtr_2, memPtr_1)) + addr_1 := add(memPtr, 64) + let _2 := mload(/** @src 0:489:494 "_s[1]" */ mload(addr_1)) + /// @src 0:346:625 "contract C {..." + sstore(0x02, _2) + let memPtr_2 := 0 + memPtr_2 := mload(64) + let newFreePtr_2 := add(memPtr_2, 160) + if or(gt(newFreePtr_2, 0xffffffffffffffff), lt(newFreePtr_2, memPtr_2)) { mstore(0, shl(224, 0x4e487b71)) - mstore(_2, 0x41) - revert(0, _6) + mstore(4, 0x41) + revert(0, 36) } - mstore(_9, newFreePtr_2) - mstore(memPtr_1, 100) - let _11 := add(memPtr_1, _3) - mstore(_11, "longstringlongstringlongstringlo") - mstore(add(memPtr_1, _9), "ngstringlongstringlongstringlong") - mstore(add(memPtr_1, 96), "stringlongstringlongstringlongst") - mstore(add(memPtr_1, 128), "ring") - let memPos := mload(_9) - mstore(memPos, _10) - mstore(add(memPos, _3), _9) - let length := mload(memPtr_1) - mstore(add(memPos, _9), length) - mcopy(add(memPos, 96), _11, length) - mstore(add(add(memPos, length), 96), 0) - return(memPos, add(sub(add(memPos, and(add(length, 31), _8)), memPos), 96)) + mstore(64, newFreePtr_2) + mstore(memPtr_2, 100) + let _3 := add(memPtr_2, 32) + mstore(_3, "longstringlongstringlongstringlo") + mstore(add(memPtr_2, 64), "ngstringlongstringlongstringlong") + mstore(add(memPtr_2, 96), "stringlongstringlongstringlongst") + mstore(add(memPtr_2, 128), "ring") + let memPos := mload(64) + mstore(memPos, _2) + mstore(add(memPos, 32), 64) + let length_1 := mload(memPtr_2) + mstore(add(memPos, 64), length_1) + mcopy(add(memPos, 96), _3, length_1) + mstore(add(add(memPos, length_1), 96), 0) + return(memPos, add(sub(add(memPos, and(add(length_1, 0x1f), not(31))), memPos), 96)) } } revert(0, 0) diff --git a/test/cmdlineTests/optimizer_array_sload/output b/test/cmdlineTests/optimizer_array_sload/output index b32d421d0..c1e0796f5 100644 --- a/test/cmdlineTests/optimizer_array_sload/output +++ b/test/cmdlineTests/optimizer_array_sload/output @@ -18,7 +18,6 @@ object "Arraysum_34" { { /// @src 0:80:429 "contract Arraysum {..." mstore(64, memoryguard(0x80)) - let _1 := 4 if iszero(lt(calldatasize(), 4)) { if eq(0x81d73423, shr(224, calldataload(0))) @@ -26,12 +25,14 @@ object "Arraysum_34" { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } let var_sum := 0 + /// @src 0:175:182 "sum = 0" + var_sum := /** @src 0:80:429 "contract Arraysum {..." */ 0 /// @src 0:368:378 "uint i = 0" let var_i := /** @src 0:80:429 "contract Arraysum {..." */ 0 - let _2 := sload(0) + let _1 := sload(0) /// @src 0:364:423 "for(uint i = 0; i < values.length; i++)..." for { } - /** @src 0:380:397 "i < values.length" */ lt(var_i, _2) + /** @src 0:80:429 "contract Arraysum {..." */ 1 /// @src 0:368:378 "uint i = 0" { /// @src 0:399:402 "i++" @@ -39,13 +40,17 @@ object "Arraysum_34" { } /// @src 0:399:402 "i++" { + /// @src 0:380:397 "i < values.length" + let _2 := iszero(lt(var_i, _1)) + if _2 { break } /// @src 0:80:429 "contract Arraysum {..." + _2 := 0 mstore(0, 0) let sum := add(var_sum, sload(add(18569430475105882587588266137607568536673111973893317399460219858819262702947, var_i))) if gt(var_sum, sum) { mstore(0, shl(224, 0x4e487b71)) - mstore(_1, 0x11) + mstore(4, 0x11) revert(0, 0x24) } /// @src 0:407:423 "sum += values[i]" @@ -54,7 +59,7 @@ object "Arraysum_34" { /// @src 0:80:429 "contract Arraysum {..." let memPos := mload(64) mstore(memPos, var_sum) - return(memPos, 32) + return(memPos, 0x20) } } revert(0, 0) diff --git a/test/cmdlineTests/optimizer_user_yul/output b/test/cmdlineTests/optimizer_user_yul/output index 602a7de95..689e82ddb 100644 --- a/test/cmdlineTests/optimizer_user_yul/output +++ b/test/cmdlineTests/optimizer_user_yul/output @@ -42,7 +42,6 @@ tag_5: /* "optimizer_user_yul/input.sol":263:269 a := 2 */ swap1 pop - 0x00 /* "optimizer_user_yul/input.sol":369:370 3 */ 0x03 /* "optimizer_user_yul/input.sol":366:367 2 */ @@ -59,18 +58,10 @@ tag_6: /* "optimizer_user_yul/input.sol":384:392 sload(5) */ dup1 /* "optimizer_user_yul/input.sol":376:509 for { } sload(5) { } {... */ - tag_8 + iszero + tag_6 jumpi - /* "optimizer_user_yul/input.sol":495:504 exp(x, y) */ - 0x01 - /* "optimizer_user_yul/input.sol":490:504 z := exp(x, y) */ - swap2 - pop - /* "optimizer_user_yul/input.sol":376:509 for { } sload(5) { } {... */ - jump(tag_6) -tag_8: /* "optimizer_user_yul/input.sol":380:383 { } */ - pop pop /* "optimizer_user_yul/input.sol":340:513 {... */ pop diff --git a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json index 642d07f49..4ef3c6df1 100644 --- a/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_evm_asm_via_ir_location/output.json @@ -76,25 +76,18 @@ stop sub_0: assembly { /* \"C\":79:503 contract C... */ - 0x80 - 0x40 - swap1 - dup1 - dup3 - mstore + mstore(0x40, 0x80) jumpi(tag_2, iszero(lt(calldatasize, 0x04))) 0x00 dup1 revert tag_2: shr(0xe0, calldataload(0x00)) - swap1 - dup2 + dup1 0x26121ff0 eq tag_4 jumpi - pop dup1 0x793816ec eq @@ -122,19 +115,17 @@ sub_0: assembly { dup2 swap1 sstore - dup2 - mload + mload(0x40) shl(0xe4, 0x026121ff) /* \"C\":475:483 this.f() */ dup2 mstore /* \"C\":79:503 contract C... */ - swap2 swap1 /* \"C\":475:483 this.f() */ 0x20 /* \"C\":79:503 contract C... */ - dup4 + dup3 0x04 dup2 /* \"C\":475:479 this */ @@ -142,50 +133,46 @@ sub_0: assembly { /* \"C\":475:483 this.f() */ gas staticcall - swap3 - dup4 + swap2 + dup3 iszero tag_16 jumpi /* \"C\":79:503 contract C... */ 0x00 /* \"C\":475:483 this.f() */ - swap4 + swap3 tag_18 jumpi /* \"C\":79:503 contract C... */ tag_19: - /* \"C\":464:483 stateVar + this.f() */ - pop - tag_20 /* \"C\":475:483 this.f() */ 0x20 - /* \"C\":464:483 stateVar + this.f() */ - swap4 /* \"C\":464:494 stateVar + this.f() + immutVar */ - tag_21 + tag_20 /* \"C\":464:483 stateVar + this.f() */ - swap3 + tag_21 + dup6 + dup6 tag_1 jump\t// in - tag_20: + tag_21: /* \"C\":486:494 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") /* \"C\":464:494 stateVar + this.f() + immutVar */ swap1 tag_1 jump\t// in - tag_21: + tag_20: /* \"C\":79:503 contract C... */ - swap1 - mload + mload(0x40) swap1 dup2 mstore return /* \"C\":475:483 this.f() */ tag_18: - swap3 + swap2 pop 0x20 jumpi(tag_22, gt(0x20, returndatasize)) @@ -196,12 +183,12 @@ sub_0: assembly { add not(0x1f) and - dup5 + dup4 add 0xffffffffffffffff dup2 gt - dup6 + dup5 dup3 lt or @@ -211,9 +198,9 @@ sub_0: assembly { 0x20 /* \"C\":79:503 contract C... */ swap2 - dup6 + dup5 swap2 - dup6 + 0x40 mstore /* \"C\":475:483 this.f() */ dup2 @@ -223,11 +210,11 @@ sub_0: assembly { slt tag_26 jumpi - swap2 + swap1 mload - swap2 + swap1 /* \"C\":464:483 stateVar + this.f() */ - tag_20 + tag_21 /* \"C\":475:483 this.f() */ jump(tag_19) /* \"C\":79:503 contract C... */ @@ -250,8 +237,7 @@ sub_0: assembly { jump(tag_23) tag_16: /* \"C\":79:503 contract C... */ - dup3 - mload + mload(0x40) returndatasize 0x00 dup3 @@ -278,14 +264,11 @@ sub_0: assembly { revert /* \"C\":79:503 contract C... */ tag_6: - pop jumpi(tag_26, callvalue) jumpi(tag_26, slt(add(not(0x03), calldatasize), 0x00)) 0x20 - swap1 sload(0x00) - swap1 - mload + mload(0x40) swap1 dup2 mstore @@ -296,12 +279,11 @@ sub_0: assembly { /* \"C\":326:334 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") /* \"C\":120:122 41 */ - swap1 - dup2 + dup1 0x29 add - swap2 - dup3 + swap1 + dup2 slt 0x01 and @@ -309,7 +291,9 @@ sub_0: assembly { jumpi /* \"C\":79:503 contract C... */ 0x20 - swap2 + swap1 + mload(0x40) + swap1 dup2 mstore return @@ -438,25 +422,18 @@ stop sub_0: assembly { /* \"D\":91:181 contract D is C(3)... */ - 0x80 - 0x40 - swap1 - dup1 - dup3 - mstore + mstore(0x40, 0x80) jumpi(tag_2, iszero(lt(calldatasize, 0x04))) 0x00 dup1 revert tag_2: shr(0xe0, calldataload(0x00)) - swap1 - dup2 + dup1 0x26121ff0 eq tag_4 jumpi - pop dup1 0x793816ec eq @@ -484,19 +461,17 @@ sub_0: assembly { dup2 swap1 sstore - dup2 - mload + mload(0x40) shl(0xe4, 0x026121ff) /* \"C\":475:483 this.f() */ dup2 mstore /* \"D\":91:181 contract D is C(3)... */ - swap2 swap1 /* \"C\":475:483 this.f() */ 0x20 /* \"D\":91:181 contract D is C(3)... */ - dup4 + dup3 0x04 dup2 /* \"C\":475:479 this */ @@ -504,50 +479,46 @@ sub_0: assembly { /* \"C\":475:483 this.f() */ gas staticcall - swap3 - dup4 + swap2 + dup3 iszero tag_16 jumpi /* \"D\":91:181 contract D is C(3)... */ 0x00 /* \"C\":475:483 this.f() */ - swap4 + swap3 tag_18 jumpi /* \"D\":91:181 contract D is C(3)... */ tag_19: - /* \"C\":464:483 stateVar + this.f() */ - pop - tag_20 /* \"C\":475:483 this.f() */ 0x20 - /* \"C\":464:483 stateVar + this.f() */ - swap4 /* \"C\":464:494 stateVar + this.f() + immutVar */ - tag_21 + tag_20 /* \"C\":464:483 stateVar + this.f() */ - swap3 + tag_21 + dup6 + dup6 tag_1 jump\t// in - tag_20: + tag_21: /* \"C\":486:494 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") /* \"C\":464:494 stateVar + this.f() + immutVar */ swap1 tag_1 jump\t// in - tag_21: + tag_20: /* \"D\":91:181 contract D is C(3)... */ - swap1 - mload + mload(0x40) swap1 dup2 mstore return /* \"C\":475:483 this.f() */ tag_18: - swap3 + swap2 pop 0x20 jumpi(tag_22, gt(0x20, returndatasize)) @@ -558,12 +529,12 @@ sub_0: assembly { add not(0x1f) and - dup5 + dup4 add 0xffffffffffffffff dup2 gt - dup6 + dup5 dup3 lt or @@ -573,9 +544,9 @@ sub_0: assembly { 0x20 /* \"D\":91:181 contract D is C(3)... */ swap2 - dup6 + dup5 swap2 - dup6 + 0x40 mstore /* \"C\":475:483 this.f() */ dup2 @@ -585,11 +556,11 @@ sub_0: assembly { slt tag_26 jumpi - swap2 + swap1 mload - swap2 + swap1 /* \"C\":464:483 stateVar + this.f() */ - tag_20 + tag_21 /* \"C\":475:483 this.f() */ jump(tag_19) /* \"D\":91:181 contract D is C(3)... */ @@ -612,8 +583,7 @@ sub_0: assembly { jump(tag_23) tag_16: /* \"D\":91:181 contract D is C(3)... */ - dup3 - mload + mload(0x40) returndatasize 0x00 dup3 @@ -640,14 +610,11 @@ sub_0: assembly { revert /* \"D\":91:181 contract D is C(3)... */ tag_6: - pop jumpi(tag_26, callvalue) jumpi(tag_26, slt(add(not(0x03), calldatasize), 0x00)) 0x20 - swap1 sload(0x00) - swap1 - mload + mload(0x40) swap1 dup2 mstore @@ -658,12 +625,11 @@ sub_0: assembly { /* \"C\":326:334 immutVar */ immutable(\"0xe4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10\") /* \"C\":120:122 41 */ - swap1 - dup2 + dup1 0x29 add - swap2 - dup3 + swap1 + dup2 slt 0x01 and @@ -671,7 +637,9 @@ sub_0: assembly { jumpi /* \"D\":91:181 contract D is C(3)... */ 0x20 - swap2 + swap1 + mload(0x40) + swap1 dup2 mstore return diff --git a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json index 3e687cc1a..8f0d5b5b5 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json @@ -650,9 +650,7 @@ object \"C_54\" { code { { /// @src 0:79:510 \"contract C...\" - let _1 := memoryguard(0x80) - let _2 := 64 - mstore(_2, _1) + mstore(64, memoryguard(0x80)) if iszero(lt(calldatasize(), 4)) { switch shr(224, calldataload(0)) @@ -660,89 +658,91 @@ object \"C_54\" { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } /// @src 0:333:341 \"immutVar\" - let _3 := loadimmutable(\"8\") - /// @src 0:79:510 \"contract C...\" - let sum := add(/** @src 0:127:129 \"41\" */ 0x29, /** @src 0:79:510 \"contract C...\" */ _3) - if and(1, slt(sum, _3)) + let _1 := loadimmutable(\"8\") + /// @src 0:322:341 \"constVar + immutVar\" + let sum := /** @src 0:79:510 \"contract C...\" */ 0 + sum := add(/** @src 0:127:129 \"41\" */ 0x29, /** @src 0:79:510 \"contract C...\" */ _1) + if and(1, slt(sum, _1)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x11) revert(0, 0x24) } - mstore(_1, sum) - return(_1, 32) + let memPos := mload(64) + mstore(memPos, sum) + return(memPos, 32) } case 0x793816ec { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let _4 := sload(0) - let memPos := mload(_2) - mstore(memPos, _4) - return(memPos, 32) + let _2 := sload(0) + let memPos_1 := mload(64) + mstore(memPos_1, _2) + return(memPos_1, 32) } case 0x9942ec6f { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let _5 := sload(0) - if eq(_5, sub(shl(255, 1), 1)) + let _3 := sload(0) + if eq(_3, sub(shl(255, 1), 1)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x11) revert(0, 0x24) } - let ret := add(_5, 1) + let ret := add(_3, 1) sstore(0, ret) /// @src 0:482:490 \"this.f()\" - let _6 := /** @src 0:79:510 \"contract C...\" */ mload(_2) + let _4 := /** @src 0:79:510 \"contract C...\" */ mload(64) /// @src 0:482:490 \"this.f()\" - mstore(_6, /** @src 0:79:510 \"contract C...\" */ shl(228, 0x026121ff)) + mstore(_4, /** @src 0:79:510 \"contract C...\" */ shl(228, 0x026121ff)) /// @src 0:482:490 \"this.f()\" - let _7 := staticcall(gas(), /** @src 0:482:486 \"this\" */ address(), /** @src 0:482:490 \"this.f()\" */ _6, /** @src 0:79:510 \"contract C...\" */ 4, /** @src 0:482:490 \"this.f()\" */ _6, 32) - if iszero(_7) + let _5 := staticcall(gas(), /** @src 0:482:486 \"this\" */ address(), /** @src 0:482:490 \"this.f()\" */ _4, /** @src 0:79:510 \"contract C...\" */ 4, /** @src 0:482:490 \"this.f()\" */ _4, 32) + if iszero(_5) { /// @src 0:79:510 \"contract C...\" - let pos := mload(_2) + let pos := mload(64) returndatacopy(pos, 0, returndatasize()) revert(pos, returndatasize()) } /// @src 0:482:490 \"this.f()\" let expr := /** @src 0:79:510 \"contract C...\" */ 0 /// @src 0:482:490 \"this.f()\" - if _7 + if _5 { - let _8 := 32 - if gt(32, returndatasize()) { _8 := returndatasize() } + let _6 := 32 + if gt(32, returndatasize()) { _6 := returndatasize() } /// @src 0:79:510 \"contract C...\" - let newFreePtr := add(_6, and(add(_8, 31), not(31))) - if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _6)) + let newFreePtr := add(_4, and(add(_6, 31), not(31))) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _4)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x41) revert(0, 0x24) } - mstore(_2, newFreePtr) - if slt(sub(/** @src 0:482:490 \"this.f()\" */ add(_6, _8), /** @src 0:79:510 \"contract C...\" */ _6), /** @src 0:482:490 \"this.f()\" */ 32) + mstore(64, newFreePtr) + if slt(sub(/** @src 0:482:490 \"this.f()\" */ add(_4, _6), /** @src 0:79:510 \"contract C...\" */ _4), /** @src 0:482:490 \"this.f()\" */ 32) /// @src 0:79:510 \"contract C...\" { revert(0, 0) } /// @src 0:482:490 \"this.f()\" - expr := /** @src 0:79:510 \"contract C...\" */ mload(_6) + expr := /** @src 0:79:510 \"contract C...\" */ mload(_4) } /// @src 0:471:490 \"stateVar + this.f()\" let expr_1 := checked_add_int256(ret, expr) /// @src 0:464:501 \"return stateVar + this.f() + immutVar\" let var := /** @src 0:471:501 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:493:501 \"immutVar\" */ loadimmutable(\"8\")) /// @src 0:79:510 \"contract C...\" - let memPos_1 := mload(_2) - mstore(memPos_1, var) - return(memPos_1, /** @src 0:482:490 \"this.f()\" */ 32) + let memPos_2 := mload(64) + mstore(memPos_2, var) + return(memPos_2, /** @src 0:482:490 \"this.f()\" */ 32) } case /** @src 0:79:510 \"contract C...\" */ 0xa00b982b { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let memPos_2 := mload(_2) - mstore(memPos_2, /** @src 0:127:129 \"41\" */ 0x29) + let memPos_3 := mload(64) + mstore(memPos_3, /** @src 0:127:129 \"41\" */ 0x29) /// @src 0:79:510 \"contract C...\" - return(memPos_2, 32) + return(memPos_3, 32) } } revert(0, 0) @@ -1493,9 +1493,7 @@ object \"D_72\" { code { { /// @src 1:91:181 \"contract D is C(3)...\" - let _1 := memoryguard(0x80) - let _2 := 64 - mstore(_2, _1) + mstore(64, memoryguard(0x80)) if iszero(lt(calldatasize(), 4)) { switch shr(224, calldataload(0)) @@ -1503,89 +1501,91 @@ object \"D_72\" { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } /// @src 0:333:341 \"immutVar\" - let _3 := loadimmutable(\"8\") - /// @src 1:91:181 \"contract D is C(3)...\" - let sum := add(/** @src 0:127:129 \"41\" */ 0x29, /** @src 1:91:181 \"contract D is C(3)...\" */ _3) - if and(1, slt(sum, _3)) + let _1 := loadimmutable(\"8\") + /// @src 0:322:341 \"constVar + immutVar\" + let sum := /** @src 1:91:181 \"contract D is C(3)...\" */ 0 + sum := add(/** @src 0:127:129 \"41\" */ 0x29, /** @src 1:91:181 \"contract D is C(3)...\" */ _1) + if and(1, slt(sum, _1)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x11) revert(0, 0x24) } - mstore(_1, sum) - return(_1, 32) + let memPos := mload(64) + mstore(memPos, sum) + return(memPos, 32) } case 0x793816ec { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let _4 := sload(0) - let memPos := mload(_2) - mstore(memPos, _4) - return(memPos, 32) + let _2 := sload(0) + let memPos_1 := mload(64) + mstore(memPos_1, _2) + return(memPos_1, 32) } case 0x9942ec6f { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let _5 := sload(0) - if eq(_5, sub(shl(255, 1), 1)) + let _3 := sload(0) + if eq(_3, sub(shl(255, 1), 1)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x11) revert(0, 0x24) } - let ret := add(_5, 1) + let ret := add(_3, 1) sstore(0, ret) /// @src 0:482:490 \"this.f()\" - let _6 := /** @src 1:91:181 \"contract D is C(3)...\" */ mload(_2) + let _4 := /** @src 1:91:181 \"contract D is C(3)...\" */ mload(64) /// @src 0:482:490 \"this.f()\" - mstore(_6, /** @src 1:91:181 \"contract D is C(3)...\" */ shl(228, 0x026121ff)) + mstore(_4, /** @src 1:91:181 \"contract D is C(3)...\" */ shl(228, 0x026121ff)) /// @src 0:482:490 \"this.f()\" - let _7 := staticcall(gas(), /** @src 0:482:486 \"this\" */ address(), /** @src 0:482:490 \"this.f()\" */ _6, /** @src 1:91:181 \"contract D is C(3)...\" */ 4, /** @src 0:482:490 \"this.f()\" */ _6, 32) - if iszero(_7) + let _5 := staticcall(gas(), /** @src 0:482:486 \"this\" */ address(), /** @src 0:482:490 \"this.f()\" */ _4, /** @src 1:91:181 \"contract D is C(3)...\" */ 4, /** @src 0:482:490 \"this.f()\" */ _4, 32) + if iszero(_5) { /// @src 1:91:181 \"contract D is C(3)...\" - let pos := mload(_2) + let pos := mload(64) returndatacopy(pos, 0, returndatasize()) revert(pos, returndatasize()) } /// @src 0:482:490 \"this.f()\" let expr := /** @src 1:91:181 \"contract D is C(3)...\" */ 0 /// @src 0:482:490 \"this.f()\" - if _7 + if _5 { - let _8 := 32 - if gt(32, returndatasize()) { _8 := returndatasize() } + let _6 := 32 + if gt(32, returndatasize()) { _6 := returndatasize() } /// @src 1:91:181 \"contract D is C(3)...\" - let newFreePtr := add(_6, and(add(_8, 31), not(31))) - if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _6)) + let newFreePtr := add(_4, and(add(_6, 31), not(31))) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _4)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x41) revert(0, 0x24) } - mstore(_2, newFreePtr) - if slt(sub(/** @src 0:482:490 \"this.f()\" */ add(_6, _8), /** @src 1:91:181 \"contract D is C(3)...\" */ _6), /** @src 0:482:490 \"this.f()\" */ 32) + mstore(64, newFreePtr) + if slt(sub(/** @src 0:482:490 \"this.f()\" */ add(_4, _6), /** @src 1:91:181 \"contract D is C(3)...\" */ _4), /** @src 0:482:490 \"this.f()\" */ 32) /// @src 1:91:181 \"contract D is C(3)...\" { revert(0, 0) } /// @src 0:482:490 \"this.f()\" - expr := /** @src 1:91:181 \"contract D is C(3)...\" */ mload(_6) + expr := /** @src 1:91:181 \"contract D is C(3)...\" */ mload(_4) } /// @src 0:471:490 \"stateVar + this.f()\" let expr_1 := checked_add_int256(ret, expr) /// @src 0:464:501 \"return stateVar + this.f() + immutVar\" let var := /** @src 0:471:501 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:493:501 \"immutVar\" */ loadimmutable(\"8\")) /// @src 1:91:181 \"contract D is C(3)...\" - let memPos_1 := mload(_2) - mstore(memPos_1, var) - return(memPos_1, /** @src 0:482:490 \"this.f()\" */ 32) + let memPos_2 := mload(64) + mstore(memPos_2, var) + return(memPos_2, /** @src 0:482:490 \"this.f()\" */ 32) } case /** @src 1:91:181 \"contract D is C(3)...\" */ 0xa00b982b { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let memPos_2 := mload(_2) - mstore(memPos_2, /** @src 0:127:129 \"41\" */ 0x29) + let memPos_3 := mload(64) + mstore(memPos_3, /** @src 0:127:129 \"41\" */ 0x29) /// @src 1:91:181 \"contract D is C(3)...\" - return(memPos_2, 32) + return(memPos_3, 32) } } revert(0, 0) diff --git a/test/cmdlineTests/standard_optimizer_generatedSources/output.json b/test/cmdlineTests/standard_optimizer_generatedSources/output.json index 0f8c3d4ea..e5b276b1b 100644 --- a/test/cmdlineTests/standard_optimizer_generatedSources/output.json +++ b/test/cmdlineTests/standard_optimizer_generatedSources/output.json @@ -11,9 +11,9 @@ "generatedSources": [ { "ast": { - "nativeSrc": "0:1445:1", + "nativeSrc": "0:1505:1", "nodeType": "YulBlock", - "src": "0:1445:1", + "src": "0:1505:1", "statements": [ { "nativeSrc": "6:3:1", @@ -159,71 +159,49 @@ }, { "body": { - "nativeSrc": "241:1020:1", + "nativeSrc": "241:1080:1", "nodeType": "YulBlock", - "src": "241:1020:1", + "src": "241:1080:1", "statements": [ - { - "nativeSrc": "251:12:1", - "nodeType": "YulVariableDeclaration", - "src": "251:12:1", - "value": { - "kind": "number", - "nativeSrc": "261:2:1", - "nodeType": "YulLiteral", - "src": "261:2:1", - "type": "", - "value": "32" - }, - "variables": [ - { - "name": "_1", - "nativeSrc": "255:2:1", - "nodeType": "YulTypedName", - "src": "255:2:1", - "type": "" - } - ] - }, { "body": { - "nativeSrc": "308:16:1", + "nativeSrc": "287:16:1", "nodeType": "YulBlock", - "src": "308:16:1", + "src": "287:16:1", "statements": [ { "expression": { "arguments": [ { "kind": "number", - "nativeSrc": "317:1:1", + "nativeSrc": "296:1:1", "nodeType": "YulLiteral", - "src": "317:1:1", + "src": "296:1:1", "type": "", "value": "0" }, { "kind": "number", - "nativeSrc": "320:1:1", + "nativeSrc": "299:1:1", "nodeType": "YulLiteral", - "src": "320:1:1", + "src": "299:1:1", "type": "", "value": "0" } ], "functionName": { "name": "revert", - "nativeSrc": "310:6:1", + "nativeSrc": "289:6:1", "nodeType": "YulIdentifier", - "src": "310:6:1" + "src": "289:6:1" }, - "nativeSrc": "310:12:1", + "nativeSrc": "289:12:1", "nodeType": "YulFunctionCall", - "src": "310:12:1" + "src": "289:12:1" }, - "nativeSrc": "310:12:1", + "nativeSrc": "289:12:1", "nodeType": "YulExpressionStatement", - "src": "310:12:1" + "src": "289:12:1" } ] }, @@ -233,142 +211,122 @@ "arguments": [ { "name": "dataEnd", - "nativeSrc": "283:7:1", + "nativeSrc": "262:7:1", "nodeType": "YulIdentifier", - "src": "283:7:1" + "src": "262:7:1" }, { "name": "headStart", - "nativeSrc": "292:9:1", + "nativeSrc": "271:9:1", "nodeType": "YulIdentifier", - "src": "292:9:1" + "src": "271:9:1" } ], "functionName": { "name": "sub", - "nativeSrc": "279:3:1", + "nativeSrc": "258:3:1", "nodeType": "YulIdentifier", - "src": "279:3:1" + "src": "258:3:1" }, - "nativeSrc": "279:23:1", + "nativeSrc": "258:23:1", "nodeType": "YulFunctionCall", - "src": "279:23:1" + "src": "258:23:1" }, { - "name": "_1", - "nativeSrc": "304:2:1", - "nodeType": "YulIdentifier", - "src": "304:2:1" + "kind": "number", + "nativeSrc": "283:2:1", + "nodeType": "YulLiteral", + "src": "283:2:1", + "type": "", + "value": "32" } ], "functionName": { "name": "slt", - "nativeSrc": "275:3:1", + "nativeSrc": "254:3:1", "nodeType": "YulIdentifier", - "src": "275:3:1" + "src": "254:3:1" }, - "nativeSrc": "275:32:1", + "nativeSrc": "254:32:1", "nodeType": "YulFunctionCall", - "src": "275:32:1" + "src": "254:32:1" }, - "nativeSrc": "272:52:1", + "nativeSrc": "251:52:1", "nodeType": "YulIf", - "src": "272:52:1" + "src": "251:52:1" }, { - "nativeSrc": "333:37:1", + "nativeSrc": "312:37:1", "nodeType": "YulVariableDeclaration", - "src": "333:37:1", + "src": "312:37:1", "value": { "arguments": [ { "name": "headStart", - "nativeSrc": "360:9:1", + "nativeSrc": "339:9:1", "nodeType": "YulIdentifier", - "src": "360:9:1" + "src": "339:9:1" } ], "functionName": { "name": "calldataload", - "nativeSrc": "347:12:1", + "nativeSrc": "326:12:1", "nodeType": "YulIdentifier", - "src": "347:12:1" + "src": "326:12:1" }, - "nativeSrc": "347:23:1", + "nativeSrc": "326:23:1", "nodeType": "YulFunctionCall", - "src": "347:23:1" + "src": "326:23:1" }, "variables": [ { "name": "offset", - "nativeSrc": "337:6:1", - "nodeType": "YulTypedName", - "src": "337:6:1", - "type": "" - } - ] - }, - { - "nativeSrc": "379:28:1", - "nodeType": "YulVariableDeclaration", - "src": "379:28:1", - "value": { - "kind": "number", - "nativeSrc": "389:18:1", - "nodeType": "YulLiteral", - "src": "389:18:1", - "type": "", - "value": "0xffffffffffffffff" - }, - "variables": [ - { - "name": "_2", - "nativeSrc": "383:2:1", + "nativeSrc": "316:6:1", "nodeType": "YulTypedName", - "src": "383:2:1", + "src": "316:6:1", "type": "" } ] }, { "body": { - "nativeSrc": "434:16:1", + "nativeSrc": "392:16:1", "nodeType": "YulBlock", - "src": "434:16:1", + "src": "392:16:1", "statements": [ { "expression": { "arguments": [ { "kind": "number", - "nativeSrc": "443:1:1", + "nativeSrc": "401:1:1", "nodeType": "YulLiteral", - "src": "443:1:1", + "src": "401:1:1", "type": "", "value": "0" }, { "kind": "number", - "nativeSrc": "446:1:1", + "nativeSrc": "404:1:1", "nodeType": "YulLiteral", - "src": "446:1:1", + "src": "404:1:1", "type": "", "value": "0" } ], "functionName": { "name": "revert", - "nativeSrc": "436:6:1", + "nativeSrc": "394:6:1", "nodeType": "YulIdentifier", - "src": "436:6:1" + "src": "394:6:1" }, - "nativeSrc": "436:12:1", + "nativeSrc": "394:12:1", "nodeType": "YulFunctionCall", - "src": "436:12:1" + "src": "394:12:1" }, - "nativeSrc": "436:12:1", + "nativeSrc": "394:12:1", "nodeType": "YulExpressionStatement", - "src": "436:12:1" + "src": "394:12:1" } ] }, @@ -376,109 +334,111 @@ "arguments": [ { "name": "offset", - "nativeSrc": "422:6:1", + "nativeSrc": "364:6:1", "nodeType": "YulIdentifier", - "src": "422:6:1" + "src": "364:6:1" }, { - "name": "_2", - "nativeSrc": "430:2:1", - "nodeType": "YulIdentifier", - "src": "430:2:1" + "kind": "number", + "nativeSrc": "372:18:1", + "nodeType": "YulLiteral", + "src": "372:18:1", + "type": "", + "value": "0xffffffffffffffff" } ], "functionName": { "name": "gt", - "nativeSrc": "419:2:1", + "nativeSrc": "361:2:1", "nodeType": "YulIdentifier", - "src": "419:2:1" + "src": "361:2:1" }, - "nativeSrc": "419:14:1", + "nativeSrc": "361:30:1", "nodeType": "YulFunctionCall", - "src": "419:14:1" + "src": "361:30:1" }, - "nativeSrc": "416:34:1", + "nativeSrc": "358:50:1", "nodeType": "YulIf", - "src": "416:34:1" + "src": "358:50:1" }, { - "nativeSrc": "459:32:1", + "nativeSrc": "417:32:1", "nodeType": "YulVariableDeclaration", - "src": "459:32:1", + "src": "417:32:1", "value": { "arguments": [ { "name": "headStart", - "nativeSrc": "473:9:1", + "nativeSrc": "431:9:1", "nodeType": "YulIdentifier", - "src": "473:9:1" + "src": "431:9:1" }, { "name": "offset", - "nativeSrc": "484:6:1", + "nativeSrc": "442:6:1", "nodeType": "YulIdentifier", - "src": "484:6:1" + "src": "442:6:1" } ], "functionName": { "name": "add", - "nativeSrc": "469:3:1", + "nativeSrc": "427:3:1", "nodeType": "YulIdentifier", - "src": "469:3:1" + "src": "427:3:1" }, - "nativeSrc": "469:22:1", + "nativeSrc": "427:22:1", "nodeType": "YulFunctionCall", - "src": "469:22:1" + "src": "427:22:1" }, "variables": [ { - "name": "_3", - "nativeSrc": "463:2:1", + "name": "_1", + "nativeSrc": "421:2:1", "nodeType": "YulTypedName", - "src": "463:2:1", + "src": "421:2:1", "type": "" } ] }, { "body": { - "nativeSrc": "539:16:1", + "nativeSrc": "497:16:1", "nodeType": "YulBlock", - "src": "539:16:1", + "src": "497:16:1", "statements": [ { "expression": { "arguments": [ { "kind": "number", - "nativeSrc": "548:1:1", + "nativeSrc": "506:1:1", "nodeType": "YulLiteral", - "src": "548:1:1", + "src": "506:1:1", "type": "", "value": "0" }, { "kind": "number", - "nativeSrc": "551:1:1", + "nativeSrc": "509:1:1", "nodeType": "YulLiteral", - "src": "551:1:1", + "src": "509:1:1", "type": "", "value": "0" } ], "functionName": { "name": "revert", - "nativeSrc": "541:6:1", + "nativeSrc": "499:6:1", "nodeType": "YulIdentifier", - "src": "541:6:1" + "src": "499:6:1" }, - "nativeSrc": "541:12:1", + "nativeSrc": "499:12:1", "nodeType": "YulFunctionCall", - "src": "541:12:1" + "src": "499:12:1" }, - "nativeSrc": "541:12:1", + "nativeSrc": "499:12:1", "nodeType": "YulExpressionStatement", - "src": "541:12:1" + "src": "499:12:1" } ] }, @@ -489,341 +449,343 @@ { "arguments": [ { - "name": "_3", - "nativeSrc": "518:2:1", + "name": "_1", + "nativeSrc": "476:2:1", "nodeType": "YulIdentifier", - "src": "518:2:1" + "src": "476:2:1" }, { "kind": "number", - "nativeSrc": "522:4:1", + "nativeSrc": "480:4:1", "nodeType": "YulLiteral", - "src": "522:4:1", + "src": "480:4:1", "type": "", "value": "0x1f" } ], "functionName": { "name": "add", - "nativeSrc": "514:3:1", + "nativeSrc": "472:3:1", "nodeType": "YulIdentifier", - "src": "514:3:1" + "src": "472:3:1" }, - "nativeSrc": "514:13:1", + "nativeSrc": "472:13:1", "nodeType": "YulFunctionCall", - "src": "514:13:1" + "src": "472:13:1" }, { "name": "dataEnd", - "nativeSrc": "529:7:1", + "nativeSrc": "487:7:1", "nodeType": "YulIdentifier", - "src": "529:7:1" + "src": "487:7:1" } ], "functionName": { "name": "slt", - "nativeSrc": "510:3:1", + "nativeSrc": "468:3:1", "nodeType": "YulIdentifier", - "src": "510:3:1" + "src": "468:3:1" }, - "nativeSrc": "510:27:1", + "nativeSrc": "468:27:1", "nodeType": "YulFunctionCall", - "src": "510:27:1" + "src": "468:27:1" } ], "functionName": { "name": "iszero", - "nativeSrc": "503:6:1", + "nativeSrc": "461:6:1", "nodeType": "YulIdentifier", - "src": "503:6:1" + "src": "461:6:1" }, - "nativeSrc": "503:35:1", + "nativeSrc": "461:35:1", "nodeType": "YulFunctionCall", - "src": "503:35:1" + "src": "461:35:1" }, - "nativeSrc": "500:55:1", + "nativeSrc": "458:55:1", "nodeType": "YulIf", - "src": "500:55:1" + "src": "458:55:1" }, { - "nativeSrc": "564:26:1", + "nativeSrc": "522:30:1", "nodeType": "YulVariableDeclaration", - "src": "564:26:1", + "src": "522:30:1", "value": { "arguments": [ { - "name": "_3", - "nativeSrc": "587:2:1", + "name": "_1", + "nativeSrc": "549:2:1", "nodeType": "YulIdentifier", - "src": "587:2:1" + "src": "549:2:1" } ], "functionName": { "name": "calldataload", - "nativeSrc": "574:12:1", + "nativeSrc": "536:12:1", "nodeType": "YulIdentifier", - "src": "574:12:1" + "src": "536:12:1" }, - "nativeSrc": "574:16:1", + "nativeSrc": "536:16:1", "nodeType": "YulFunctionCall", - "src": "574:16:1" + "src": "536:16:1" }, "variables": [ { - "name": "_4", - "nativeSrc": "568:2:1", + "name": "length", + "nativeSrc": "526:6:1", "nodeType": "YulTypedName", - "src": "568:2:1", + "src": "526:6:1", "type": "" } ] }, { "body": { - "nativeSrc": "613:22:1", + "nativeSrc": "595:22:1", "nodeType": "YulBlock", - "src": "613:22:1", + "src": "595:22:1", "statements": [ { "expression": { "arguments": [], "functionName": { "name": "panic_error_0x41", - "nativeSrc": "615:16:1", + "nativeSrc": "597:16:1", "nodeType": "YulIdentifier", - "src": "615:16:1" + "src": "597:16:1" }, - "nativeSrc": "615:18:1", + "nativeSrc": "597:18:1", "nodeType": "YulFunctionCall", - "src": "615:18:1" + "src": "597:18:1" }, - "nativeSrc": "615:18:1", + "nativeSrc": "597:18:1", "nodeType": "YulExpressionStatement", - "src": "615:18:1" + "src": "597:18:1" } ] }, "condition": { "arguments": [ { - "name": "_4", - "nativeSrc": "605:2:1", + "name": "length", + "nativeSrc": "567:6:1", "nodeType": "YulIdentifier", - "src": "605:2:1" + "src": "567:6:1" }, { - "name": "_2", - "nativeSrc": "609:2:1", - "nodeType": "YulIdentifier", - "src": "609:2:1" + "kind": "number", + "nativeSrc": "575:18:1", + "nodeType": "YulLiteral", + "src": "575:18:1", + "type": "", + "value": "0xffffffffffffffff" } ], "functionName": { "name": "gt", - "nativeSrc": "602:2:1", + "nativeSrc": "564:2:1", "nodeType": "YulIdentifier", - "src": "602:2:1" + "src": "564:2:1" }, - "nativeSrc": "602:10:1", + "nativeSrc": "564:30:1", "nodeType": "YulFunctionCall", - "src": "602:10:1" + "src": "564:30:1" }, - "nativeSrc": "599:36:1", + "nativeSrc": "561:56:1", "nodeType": "YulIf", - "src": "599:36:1" + "src": "561:56:1" }, { - "nativeSrc": "644:20:1", + "nativeSrc": "626:24:1", "nodeType": "YulVariableDeclaration", - "src": "644:20:1", + "src": "626:24:1", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "658:1:1", + "nativeSrc": "640:1:1", "nodeType": "YulLiteral", - "src": "658:1:1", + "src": "640:1:1", "type": "", "value": "5" }, { - "name": "_4", - "nativeSrc": "661:2:1", + "name": "length", + "nativeSrc": "643:6:1", "nodeType": "YulIdentifier", - "src": "661:2:1" + "src": "643:6:1" } ], "functionName": { "name": "shl", - "nativeSrc": "654:3:1", + "nativeSrc": "636:3:1", "nodeType": "YulIdentifier", - "src": "654:3:1" + "src": "636:3:1" }, - "nativeSrc": "654:10:1", + "nativeSrc": "636:14:1", "nodeType": "YulFunctionCall", - "src": "654:10:1" + "src": "636:14:1" }, "variables": [ { - "name": "_5", - "nativeSrc": "648:2:1", + "name": "_2", + "nativeSrc": "630:2:1", "nodeType": "YulTypedName", - "src": "648:2:1", + "src": "630:2:1", "type": "" } ] }, { - "nativeSrc": "673:23:1", + "nativeSrc": "659:23:1", "nodeType": "YulVariableDeclaration", - "src": "673:23:1", + "src": "659:23:1", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "693:2:1", + "nativeSrc": "679:2:1", "nodeType": "YulLiteral", - "src": "693:2:1", + "src": "679:2:1", "type": "", "value": "64" } ], "functionName": { "name": "mload", - "nativeSrc": "687:5:1", + "nativeSrc": "673:5:1", "nodeType": "YulIdentifier", - "src": "687:5:1" + "src": "673:5:1" }, - "nativeSrc": "687:9:1", + "nativeSrc": "673:9:1", "nodeType": "YulFunctionCall", - "src": "687:9:1" + "src": "673:9:1" }, "variables": [ { "name": "memPtr", - "nativeSrc": "677:6:1", + "nativeSrc": "663:6:1", "nodeType": "YulTypedName", - "src": "677:6:1", + "src": "663:6:1", "type": "" } ] }, { - "nativeSrc": "705:56:1", + "nativeSrc": "691:56:1", "nodeType": "YulVariableDeclaration", - "src": "705:56:1", + "src": "691:56:1", "value": { "arguments": [ { "name": "memPtr", - "nativeSrc": "727:6:1", + "nativeSrc": "713:6:1", "nodeType": "YulIdentifier", - "src": "727:6:1" + "src": "713:6:1" }, { "arguments": [ { "arguments": [ { - "name": "_5", - "nativeSrc": "743:2:1", + "name": "_2", + "nativeSrc": "729:2:1", "nodeType": "YulIdentifier", - "src": "743:2:1" + "src": "729:2:1" }, { "kind": "number", - "nativeSrc": "747:2:1", + "nativeSrc": "733:2:1", "nodeType": "YulLiteral", - "src": "747:2:1", + "src": "733:2:1", "type": "", "value": "63" } ], "functionName": { "name": "add", - "nativeSrc": "739:3:1", + "nativeSrc": "725:3:1", "nodeType": "YulIdentifier", - "src": "739:3:1" + "src": "725:3:1" }, - "nativeSrc": "739:11:1", + "nativeSrc": "725:11:1", "nodeType": "YulFunctionCall", - "src": "739:11:1" + "src": "725:11:1" }, { "arguments": [ { "kind": "number", - "nativeSrc": "756:2:1", + "nativeSrc": "742:2:1", "nodeType": "YulLiteral", - "src": "756:2:1", + "src": "742:2:1", "type": "", "value": "31" } ], "functionName": { "name": "not", - "nativeSrc": "752:3:1", + "nativeSrc": "738:3:1", "nodeType": "YulIdentifier", - "src": "752:3:1" + "src": "738:3:1" }, - "nativeSrc": "752:7:1", + "nativeSrc": "738:7:1", "nodeType": "YulFunctionCall", - "src": "752:7:1" + "src": "738:7:1" } ], "functionName": { "name": "and", - "nativeSrc": "735:3:1", + "nativeSrc": "721:3:1", "nodeType": "YulIdentifier", - "src": "735:3:1" + "src": "721:3:1" }, - "nativeSrc": "735:25:1", + "nativeSrc": "721:25:1", "nodeType": "YulFunctionCall", - "src": "735:25:1" + "src": "721:25:1" } ], "functionName": { "name": "add", - "nativeSrc": "723:3:1", + "nativeSrc": "709:3:1", "nodeType": "YulIdentifier", - "src": "723:3:1" + "src": "709:3:1" }, - "nativeSrc": "723:38:1", + "nativeSrc": "709:38:1", "nodeType": "YulFunctionCall", - "src": "723:38:1" + "src": "709:38:1" }, "variables": [ { "name": "newFreePtr", - "nativeSrc": "709:10:1", + "nativeSrc": "695:10:1", "nodeType": "YulTypedName", - "src": "709:10:1", + "src": "695:10:1", "type": "" } ] }, { "body": { - "nativeSrc": "820:22:1", + "nativeSrc": "822:22:1", "nodeType": "YulBlock", - "src": "820:22:1", + "src": "822:22:1", "statements": [ { "expression": { "arguments": [], "functionName": { "name": "panic_error_0x41", - "nativeSrc": "822:16:1", + "nativeSrc": "824:16:1", "nodeType": "YulIdentifier", - "src": "822:16:1" + "src": "824:16:1" }, - "nativeSrc": "822:18:1", + "nativeSrc": "824:18:1", "nodeType": "YulFunctionCall", - "src": "822:18:1" + "src": "824:18:1" }, - "nativeSrc": "822:18:1", + "nativeSrc": "824:18:1", "nodeType": "YulExpressionStatement", - "src": "822:18:1" + "src": "824:18:1" } ] }, @@ -833,115 +795,117 @@ "arguments": [ { "name": "newFreePtr", - "nativeSrc": "779:10:1", + "nativeSrc": "765:10:1", "nodeType": "YulIdentifier", - "src": "779:10:1" + "src": "765:10:1" }, { - "name": "_2", - "nativeSrc": "791:2:1", - "nodeType": "YulIdentifier", - "src": "791:2:1" + "kind": "number", + "nativeSrc": "777:18:1", + "nodeType": "YulLiteral", + "src": "777:18:1", + "type": "", + "value": "0xffffffffffffffff" } ], "functionName": { "name": "gt", - "nativeSrc": "776:2:1", + "nativeSrc": "762:2:1", "nodeType": "YulIdentifier", - "src": "776:2:1" + "src": "762:2:1" }, - "nativeSrc": "776:18:1", + "nativeSrc": "762:34:1", "nodeType": "YulFunctionCall", - "src": "776:18:1" + "src": "762:34:1" }, { "arguments": [ { "name": "newFreePtr", - "nativeSrc": "799:10:1", + "nativeSrc": "801:10:1", "nodeType": "YulIdentifier", - "src": "799:10:1" + "src": "801:10:1" }, { "name": "memPtr", - "nativeSrc": "811:6:1", + "nativeSrc": "813:6:1", "nodeType": "YulIdentifier", - "src": "811:6:1" + "src": "813:6:1" } ], "functionName": { "name": "lt", - "nativeSrc": "796:2:1", + "nativeSrc": "798:2:1", "nodeType": "YulIdentifier", - "src": "796:2:1" + "src": "798:2:1" }, - "nativeSrc": "796:22:1", + "nativeSrc": "798:22:1", "nodeType": "YulFunctionCall", - "src": "796:22:1" + "src": "798:22:1" } ], "functionName": { "name": "or", - "nativeSrc": "773:2:1", + "nativeSrc": "759:2:1", "nodeType": "YulIdentifier", - "src": "773:2:1" + "src": "759:2:1" }, - "nativeSrc": "773:46:1", + "nativeSrc": "759:62:1", "nodeType": "YulFunctionCall", - "src": "773:46:1" + "src": "759:62:1" }, - "nativeSrc": "770:72:1", + "nativeSrc": "756:88:1", "nodeType": "YulIf", - "src": "770:72:1" + "src": "756:88:1" }, { "expression": { "arguments": [ { "kind": "number", - "nativeSrc": "858:2:1", + "nativeSrc": "860:2:1", "nodeType": "YulLiteral", - "src": "858:2:1", + "src": "860:2:1", "type": "", "value": "64" }, { "name": "newFreePtr", - "nativeSrc": "862:10:1", + "nativeSrc": "864:10:1", "nodeType": "YulIdentifier", - "src": "862:10:1" + "src": "864:10:1" } ], "functionName": { "name": "mstore", - "nativeSrc": "851:6:1", + "nativeSrc": "853:6:1", "nodeType": "YulIdentifier", - "src": "851:6:1" + "src": "853:6:1" }, - "nativeSrc": "851:22:1", + "nativeSrc": "853:22:1", "nodeType": "YulFunctionCall", - "src": "851:22:1" + "src": "853:22:1" }, - "nativeSrc": "851:22:1", + "nativeSrc": "853:22:1", "nodeType": "YulExpressionStatement", - "src": "851:22:1" + "src": "853:22:1" }, { - "nativeSrc": "882:17:1", + "nativeSrc": "884:17:1", "nodeType": "YulVariableDeclaration", - "src": "882:17:1", + "src": "884:17:1", "value": { "name": "memPtr", - "nativeSrc": "893:6:1", + "nativeSrc": "895:6:1", "nodeType": "YulIdentifier", - "src": "893:6:1" + "src": "895:6:1" }, "variables": [ { "name": "dst", - "nativeSrc": "886:3:1", + "nativeSrc": "888:3:1", "nodeType": "YulTypedName", - "src": "886:3:1", + "src": "888:3:1", "type": "" } ] @@ -951,166 +915,170 @@ "arguments": [ { "name": "memPtr", - "nativeSrc": "915:6:1", + "nativeSrc": "917:6:1", "nodeType": "YulIdentifier", - "src": "915:6:1" + "src": "917:6:1" }, { - "name": "_4", - "nativeSrc": "923:2:1", + "name": "length", + "nativeSrc": "925:6:1", "nodeType": "YulIdentifier", - "src": "923:2:1" + "src": "925:6:1" } ], "functionName": { "name": "mstore", - "nativeSrc": "908:6:1", + "nativeSrc": "910:6:1", "nodeType": "YulIdentifier", - "src": "908:6:1" + "src": "910:6:1" }, - "nativeSrc": "908:18:1", + "nativeSrc": "910:22:1", "nodeType": "YulFunctionCall", - "src": "908:18:1" + "src": "910:22:1" }, - "nativeSrc": "908:18:1", + "nativeSrc": "910:22:1", "nodeType": "YulExpressionStatement", - "src": "908:18:1" + "src": "910:22:1" }, { - "nativeSrc": "935:22:1", + "nativeSrc": "941:22:1", "nodeType": "YulAssignment", - "src": "935:22:1", + "src": "941:22:1", "value": { "arguments": [ { "name": "memPtr", - "nativeSrc": "946:6:1", + "nativeSrc": "952:6:1", "nodeType": "YulIdentifier", - "src": "946:6:1" + "src": "952:6:1" }, { - "name": "_1", - "nativeSrc": "954:2:1", - "nodeType": "YulIdentifier", - "src": "954:2:1" + "kind": "number", + "nativeSrc": "960:2:1", + "nodeType": "YulLiteral", + "src": "960:2:1", + "type": "", + "value": "32" } ], "functionName": { "name": "add", - "nativeSrc": "942:3:1", + "nativeSrc": "948:3:1", "nodeType": "YulIdentifier", - "src": "942:3:1" + "src": "948:3:1" }, - "nativeSrc": "942:15:1", + "nativeSrc": "948:15:1", "nodeType": "YulFunctionCall", - "src": "942:15:1" + "src": "948:15:1" }, "variableNames": [ { "name": "dst", - "nativeSrc": "935:3:1", + "nativeSrc": "941:3:1", "nodeType": "YulIdentifier", - "src": "935:3:1" + "src": "941:3:1" } ] }, { - "nativeSrc": "966:34:1", + "nativeSrc": "972:34:1", "nodeType": "YulVariableDeclaration", - "src": "966:34:1", + "src": "972:34:1", "value": { "arguments": [ { "arguments": [ { - "name": "_3", - "nativeSrc": "988:2:1", + "name": "_1", + "nativeSrc": "994:2:1", "nodeType": "YulIdentifier", - "src": "988:2:1" + "src": "994:2:1" }, { - "name": "_5", - "nativeSrc": "992:2:1", + "name": "_2", + "nativeSrc": "998:2:1", "nodeType": "YulIdentifier", - "src": "992:2:1" + "src": "998:2:1" } ], "functionName": { "name": "add", - "nativeSrc": "984:3:1", + "nativeSrc": "990:3:1", "nodeType": "YulIdentifier", - "src": "984:3:1" + "src": "990:3:1" }, - "nativeSrc": "984:11:1", + "nativeSrc": "990:11:1", "nodeType": "YulFunctionCall", - "src": "984:11:1" + "src": "990:11:1" }, { - "name": "_1", - "nativeSrc": "997:2:1", - "nodeType": "YulIdentifier", - "src": "997:2:1" + "kind": "number", + "nativeSrc": "1003:2:1", + "nodeType": "YulLiteral", + "src": "1003:2:1", + "type": "", + "value": "32" } ], "functionName": { "name": "add", - "nativeSrc": "980:3:1", + "nativeSrc": "986:3:1", "nodeType": "YulIdentifier", - "src": "980:3:1" + "src": "986:3:1" }, - "nativeSrc": "980:20:1", + "nativeSrc": "986:20:1", "nodeType": "YulFunctionCall", - "src": "980:20:1" + "src": "986:20:1" }, "variables": [ { "name": "srcEnd", - "nativeSrc": "970:6:1", + "nativeSrc": "976:6:1", "nodeType": "YulTypedName", - "src": "970:6:1", + "src": "976:6:1", "type": "" } ] }, { "body": { - "nativeSrc": "1032:16:1", + "nativeSrc": "1038:16:1", "nodeType": "YulBlock", - "src": "1032:16:1", + "src": "1038:16:1", "statements": [ { "expression": { "arguments": [ { "kind": "number", - "nativeSrc": "1041:1:1", + "nativeSrc": "1047:1:1", "nodeType": "YulLiteral", - "src": "1041:1:1", + "src": "1047:1:1", "type": "", "value": "0" }, { "kind": "number", - "nativeSrc": "1044:1:1", + "nativeSrc": "1050:1:1", "nodeType": "YulLiteral", - "src": "1044:1:1", + "src": "1050:1:1", "type": "", "value": "0" } ], "functionName": { "name": "revert", - "nativeSrc": "1034:6:1", + "nativeSrc": "1040:6:1", "nodeType": "YulIdentifier", - "src": "1034:6:1" + "src": "1040:6:1" }, - "nativeSrc": "1034:12:1", + "nativeSrc": "1040:12:1", "nodeType": "YulFunctionCall", - "src": "1034:12:1" + "src": "1040:12:1" }, - "nativeSrc": "1034:12:1", + "nativeSrc": "1040:12:1", "nodeType": "YulExpressionStatement", - "src": "1034:12:1" + "src": "1040:12:1" } ] }, @@ -1118,154 +1086,199 @@ "arguments": [ { "name": "srcEnd", - "nativeSrc": "1015:6:1", + "nativeSrc": "1021:6:1", "nodeType": "YulIdentifier", - "src": "1015:6:1" + "src": "1021:6:1" }, { "name": "dataEnd", - "nativeSrc": "1023:7:1", + "nativeSrc": "1029:7:1", "nodeType": "YulIdentifier", - "src": "1023:7:1" + "src": "1029:7:1" } ], "functionName": { "name": "gt", - "nativeSrc": "1012:2:1", + "nativeSrc": "1018:2:1", "nodeType": "YulIdentifier", - "src": "1012:2:1" + "src": "1018:2:1" }, - "nativeSrc": "1012:19:1", + "nativeSrc": "1018:19:1", "nodeType": "YulFunctionCall", - "src": "1012:19:1" + "src": "1018:19:1" }, - "nativeSrc": "1009:39:1", + "nativeSrc": "1015:39:1", "nodeType": "YulIf", - "src": "1009:39:1" + "src": "1015:39:1" }, { - "nativeSrc": "1057:22:1", + "nativeSrc": "1063:22:1", "nodeType": "YulVariableDeclaration", - "src": "1057:22:1", + "src": "1063:22:1", "value": { "arguments": [ { - "name": "_3", - "nativeSrc": "1072:2:1", + "name": "_1", + "nativeSrc": "1078:2:1", "nodeType": "YulIdentifier", - "src": "1072:2:1" + "src": "1078:2:1" }, { - "name": "_1", - "nativeSrc": "1076:2:1", - "nodeType": "YulIdentifier", - "src": "1076:2:1" + "kind": "number", + "nativeSrc": "1082:2:1", + "nodeType": "YulLiteral", + "src": "1082:2:1", + "type": "", + "value": "32" } ], "functionName": { "name": "add", - "nativeSrc": "1068:3:1", + "nativeSrc": "1074:3:1", "nodeType": "YulIdentifier", - "src": "1068:3:1" + "src": "1074:3:1" }, - "nativeSrc": "1068:11:1", + "nativeSrc": "1074:11:1", "nodeType": "YulFunctionCall", - "src": "1068:11:1" + "src": "1074:11:1" }, "variables": [ { "name": "src", - "nativeSrc": "1061:3:1", + "nativeSrc": "1067:3:1", "nodeType": "YulTypedName", - "src": "1061:3:1", + "src": "1067:3:1", "type": "" } ] }, { "body": { - "nativeSrc": "1144:86:1", + "nativeSrc": "1150:140:1", "nodeType": "YulBlock", - "src": "1144:86:1", + "src": "1150:140:1", "statements": [ + { + "nativeSrc": "1164:14:1", + "nodeType": "YulVariableDeclaration", + "src": "1164:14:1", + "value": { + "kind": "number", + "nativeSrc": "1177:1:1", + "nodeType": "YulLiteral", + "src": "1177:1:1", + "type": "", + "value": "0" + }, + "variables": [ + { + "name": "value", + "nativeSrc": "1168:5:1", + "nodeType": "YulTypedName", + "src": "1168:5:1", + "type": "" + } + ] + }, + { + "nativeSrc": "1191:26:1", + "nodeType": "YulAssignment", + "src": "1191:26:1", + "value": { + "arguments": [ + { + "name": "src", + "nativeSrc": "1213:3:1", + "nodeType": "YulIdentifier", + "src": "1213:3:1" + } + ], + "functionName": { + "name": "calldataload", + "nativeSrc": "1200:12:1", + "nodeType": "YulIdentifier", + "src": "1200:12:1" + }, + "nativeSrc": "1200:17:1", + "nodeType": "YulFunctionCall", + "src": "1200:17:1" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "1191:5:1", + "nodeType": "YulIdentifier", + "src": "1191:5:1" + } + ] + }, { "expression": { "arguments": [ { "name": "dst", - "nativeSrc": "1165:3:1", + "nativeSrc": "1237:3:1", "nodeType": "YulIdentifier", - "src": "1165:3:1" + "src": "1237:3:1" }, { - "arguments": [ - { - "name": "src", - "nativeSrc": "1183:3:1", - "nodeType": "YulIdentifier", - "src": "1183:3:1" - } - ], - "functionName": { - "name": "calldataload", - "nativeSrc": "1170:12:1", - "nodeType": "YulIdentifier", - "src": "1170:12:1" - }, - "nativeSrc": "1170:17:1", - "nodeType": "YulFunctionCall", - "src": "1170:17:1" + "name": "value", + "nativeSrc": "1242:5:1", + "nodeType": "YulIdentifier", + "src": "1242:5:1" } ], "functionName": { "name": "mstore", - "nativeSrc": "1158:6:1", + "nativeSrc": "1230:6:1", "nodeType": "YulIdentifier", - "src": "1158:6:1" + "src": "1230:6:1" }, - "nativeSrc": "1158:30:1", + "nativeSrc": "1230:18:1", "nodeType": "YulFunctionCall", - "src": "1158:30:1" + "src": "1230:18:1" }, - "nativeSrc": "1158:30:1", + "nativeSrc": "1230:18:1", "nodeType": "YulExpressionStatement", - "src": "1158:30:1" + "src": "1230:18:1" }, { - "nativeSrc": "1201:19:1", + "nativeSrc": "1261:19:1", "nodeType": "YulAssignment", - "src": "1201:19:1", + "src": "1261:19:1", "value": { "arguments": [ { "name": "dst", - "nativeSrc": "1212:3:1", + "nativeSrc": "1272:3:1", "nodeType": "YulIdentifier", - "src": "1212:3:1" + "src": "1272:3:1" }, { - "name": "_1", - "nativeSrc": "1217:2:1", - "nodeType": "YulIdentifier", - "src": "1217:2:1" + "kind": "number", + "nativeSrc": "1277:2:1", + "nodeType": "YulLiteral", + "src": "1277:2:1", + "type": "", + "value": "32" } ], "functionName": { "name": "add", - "nativeSrc": "1208:3:1", + "nativeSrc": "1268:3:1", "nodeType": "YulIdentifier", - "src": "1208:3:1" + "src": "1268:3:1" }, - "nativeSrc": "1208:12:1", + "nativeSrc": "1268:12:1", "nodeType": "YulFunctionCall", - "src": "1208:12:1" + "src": "1268:12:1" }, "variableNames": [ { "name": "dst", - "nativeSrc": "1201:3:1", + "nativeSrc": "1261:3:1", "nodeType": "YulIdentifier", - "src": "1201:3:1" + "src": "1261:3:1" } ] } @@ -1275,105 +1288,107 @@ "arguments": [ { "name": "src", - "nativeSrc": "1099:3:1", + "nativeSrc": "1105:3:1", "nodeType": "YulIdentifier", - "src": "1099:3:1" + "src": "1105:3:1" }, { "name": "srcEnd", - "nativeSrc": "1104:6:1", + "nativeSrc": "1110:6:1", "nodeType": "YulIdentifier", - "src": "1104:6:1" + "src": "1110:6:1" } ], "functionName": { "name": "lt", - "nativeSrc": "1096:2:1", + "nativeSrc": "1102:2:1", "nodeType": "YulIdentifier", - "src": "1096:2:1" + "src": "1102:2:1" }, - "nativeSrc": "1096:15:1", + "nativeSrc": "1102:15:1", "nodeType": "YulFunctionCall", - "src": "1096:15:1" + "src": "1102:15:1" }, - "nativeSrc": "1088:142:1", + "nativeSrc": "1094:196:1", "nodeType": "YulForLoop", "post": { - "nativeSrc": "1112:23:1", + "nativeSrc": "1118:23:1", "nodeType": "YulBlock", - "src": "1112:23:1", + "src": "1118:23:1", "statements": [ { - "nativeSrc": "1114:19:1", + "nativeSrc": "1120:19:1", "nodeType": "YulAssignment", - "src": "1114:19:1", + "src": "1120:19:1", "value": { "arguments": [ { "name": "src", - "nativeSrc": "1125:3:1", + "nativeSrc": "1131:3:1", "nodeType": "YulIdentifier", - "src": "1125:3:1" + "src": "1131:3:1" }, { - "name": "_1", - "nativeSrc": "1130:2:1", - "nodeType": "YulIdentifier", - "src": "1130:2:1" + "kind": "number", + "nativeSrc": "1136:2:1", + "nodeType": "YulLiteral", + "src": "1136:2:1", + "type": "", + "value": "32" } ], "functionName": { "name": "add", - "nativeSrc": "1121:3:1", + "nativeSrc": "1127:3:1", "nodeType": "YulIdentifier", - "src": "1121:3:1" + "src": "1127:3:1" }, - "nativeSrc": "1121:12:1", + "nativeSrc": "1127:12:1", "nodeType": "YulFunctionCall", - "src": "1121:12:1" + "src": "1127:12:1" }, "variableNames": [ { "name": "src", - "nativeSrc": "1114:3:1", + "nativeSrc": "1120:3:1", "nodeType": "YulIdentifier", - "src": "1114:3:1" + "src": "1120:3:1" } ] } ] }, "pre": { - "nativeSrc": "1092:3:1", + "nativeSrc": "1098:3:1", "nodeType": "YulBlock", - "src": "1092:3:1", + "src": "1098:3:1", "statements": [] }, - "src": "1088:142:1" + "src": "1094:196:1" }, { - "nativeSrc": "1239:16:1", + "nativeSrc": "1299:16:1", "nodeType": "YulAssignment", - "src": "1239:16:1", + "src": "1299:16:1", "value": { "name": "memPtr", - "nativeSrc": "1249:6:1", + "nativeSrc": "1309:6:1", "nodeType": "YulIdentifier", - "src": "1249:6:1" + "src": "1309:6:1" }, "variableNames": [ { "name": "value0", - "nativeSrc": "1239:6:1", + "nativeSrc": "1299:6:1", "nodeType": "YulIdentifier", - "src": "1239:6:1" + "src": "1299:6:1" } ] } ] }, "name": "abi_decode_tuple_t_array$_t_uint256_$dyn_memory_ptr", - "nativeSrc": "146:1115:1", + "nativeSrc": "146:1175:1", "nodeType": "YulFunctionDefinition", "parameters": [ { @@ -1400,51 +1415,51 @@ "type": "" } ], - "src": "146:1115:1" + "src": "146:1175:1" }, { "body": { - "nativeSrc": "1367:76:1", + "nativeSrc": "1427:76:1", "nodeType": "YulBlock", - "src": "1367:76:1", + "src": "1427:76:1", "statements": [ { - "nativeSrc": "1377:26:1", + "nativeSrc": "1437:26:1", "nodeType": "YulAssignment", - "src": "1377:26:1", + "src": "1437:26:1", "value": { "arguments": [ { "name": "headStart", - "nativeSrc": "1389:9:1", + "nativeSrc": "1449:9:1", "nodeType": "YulIdentifier", - "src": "1389:9:1" + "src": "1449:9:1" }, { "kind": "number", - "nativeSrc": "1400:2:1", + "nativeSrc": "1460:2:1", "nodeType": "YulLiteral", - "src": "1400:2:1", + "src": "1460:2:1", "type": "", "value": "32" } ], "functionName": { "name": "add", - "nativeSrc": "1385:3:1", + "nativeSrc": "1445:3:1", "nodeType": "YulIdentifier", - "src": "1385:3:1" + "src": "1445:3:1" }, - "nativeSrc": "1385:18:1", + "nativeSrc": "1445:18:1", "nodeType": "YulFunctionCall", - "src": "1385:18:1" + "src": "1445:18:1" }, "variableNames": [ { "name": "tail", - "nativeSrc": "1377:4:1", + "nativeSrc": "1437:4:1", "nodeType": "YulIdentifier", - "src": "1377:4:1" + "src": "1437:4:1" } ] }, @@ -1453,62 +1468,62 @@ "arguments": [ { "name": "headStart", - "nativeSrc": "1419:9:1", + "nativeSrc": "1479:9:1", "nodeType": "YulIdentifier", - "src": "1419:9:1" + "src": "1479:9:1" }, { "name": "value0", - "nativeSrc": "1430:6:1", + "nativeSrc": "1490:6:1", "nodeType": "YulIdentifier", - "src": "1430:6:1" + "src": "1490:6:1" } ], "functionName": { "name": "mstore", - "nativeSrc": "1412:6:1", + "nativeSrc": "1472:6:1", "nodeType": "YulIdentifier", - "src": "1412:6:1" + "src": "1472:6:1" }, - "nativeSrc": "1412:25:1", + "nativeSrc": "1472:25:1", "nodeType": "YulFunctionCall", - "src": "1412:25:1" + "src": "1472:25:1" }, - "nativeSrc": "1412:25:1", + "nativeSrc": "1472:25:1", "nodeType": "YulExpressionStatement", - "src": "1412:25:1" + "src": "1472:25:1" } ] }, "name": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed", - "nativeSrc": "1266:177:1", + "nativeSrc": "1326:177:1", "nodeType": "YulFunctionDefinition", "parameters": [ { "name": "headStart", - "nativeSrc": "1336:9:1", + "nativeSrc": "1396:9:1", "nodeType": "YulTypedName", - "src": "1336:9:1", + "src": "1396:9:1", "type": "" }, { "name": "value0", - "nativeSrc": "1347:6:1", + "nativeSrc": "1407:6:1", "nodeType": "YulTypedName", - "src": "1347:6:1", + "src": "1407:6:1", "type": "" } ], "returnVariables": [ { "name": "tail", - "nativeSrc": "1358:4:1", + "nativeSrc": "1418:4:1", "nodeType": "YulTypedName", - "src": "1358:4:1", + "src": "1418:4:1", "type": "" } ], - "src": "1266:177:1" + "src": "1326:177:1" } ] }, @@ -1522,30 +1537,30 @@ } function abi_decode_tuple_t_array$_t_uint256_$dyn_memory_ptr(headStart, dataEnd) -> value0 { - let _1 := 32 - if slt(sub(dataEnd, headStart), _1) { revert(0, 0) } + if slt(sub(dataEnd, headStart), 32) { revert(0, 0) } let offset := calldataload(headStart) - let _2 := 0xffffffffffffffff - if gt(offset, _2) { revert(0, 0) } - let _3 := add(headStart, offset) - if iszero(slt(add(_3, 0x1f), dataEnd)) { revert(0, 0) } - let _4 := calldataload(_3) - if gt(_4, _2) { panic_error_0x41() } - let _5 := shl(5, _4) + if gt(offset, 0xffffffffffffffff) { revert(0, 0) } + let _1 := add(headStart, offset) + if iszero(slt(add(_1, 0x1f), dataEnd)) { revert(0, 0) } + let length := calldataload(_1) + if gt(length, 0xffffffffffffffff) { panic_error_0x41() } + let _2 := shl(5, length) let memPtr := mload(64) - let newFreePtr := add(memPtr, and(add(_5, 63), not(31))) - if or(gt(newFreePtr, _2), lt(newFreePtr, memPtr)) { panic_error_0x41() } + let newFreePtr := add(memPtr, and(add(_2, 63), not(31))) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() } mstore(64, newFreePtr) let dst := memPtr - mstore(memPtr, _4) - dst := add(memPtr, _1) - let srcEnd := add(add(_3, _5), _1) + mstore(memPtr, length) + dst := add(memPtr, 32) + let srcEnd := add(add(_1, _2), 32) if gt(srcEnd, dataEnd) { revert(0, 0) } - let src := add(_3, _1) - for { } lt(src, srcEnd) { src := add(src, _1) } + let src := add(_1, 32) + for { } lt(src, srcEnd) { src := add(src, 32) } { - mstore(dst, calldataload(src)) - dst := add(dst, _1) + let value := 0 + value := calldataload(src) + mstore(dst, value) + dst := add(dst, 32) } value0 := memPtr } diff --git a/test/cmdlineTests/viair_subobject_optimization/output b/test/cmdlineTests/viair_subobject_optimization/output index 5090c282b..dafba2771 100644 --- a/test/cmdlineTests/viair_subobject_optimization/output +++ b/test/cmdlineTests/viair_subobject_optimization/output @@ -119,53 +119,50 @@ sub_0: assembly { jumpi(tag_7, slt(add(not(0x03), calldatasize), 0x00)) /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ dataSize(sub_0) - /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - swap1 - not(0x1f) swap1 - dup2 + /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ 0x3f - dup5 + dup3 add + not(0x1f) and dup2 add - swap2 + swap1 + 0xffffffffffffffff + dup3 + gt dup2 dup4 lt - 0xffffffffffffffff - dup5 - gt or tag_9 jumpi 0x40 - swap3 - dup4 + swap2 + dup3 mstore /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ - dup4 dup3 + dup2 mstore 0x20 - dup3 + dup2 add - swap4 + swap3 dataOffset(sub_0) - dup6 + dup5 codecopy /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - 0x1f - dup4 + dup2 mload - swap5 - dup6 - swap4 + swap3 + dup4 + swap2 /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ 0x20 /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - dup6 + dup4 mstore mload dup1 @@ -174,21 +171,23 @@ sub_0: assembly { /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ 0x20 /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ - dup8 + dup6 add mstore - dup7 - dup7 + dup5 + dup5 add mcopy 0x00 - dup6 dup3 - dup7 + dup3 add + dup5 add mstore + 0x1f add + not(0x1f) and dup2 add diff --git a/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_paris.sol b/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_paris.sol index 0a97c87df..82a3415d0 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_paris.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_paris.sol @@ -26,6 +26,6 @@ contract test { // ==== // EVMVersion: =paris // ---- -// Warning 5574: (0-27130): Contract code size is 27193 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. -// Warning 5574: (27132-27224): Contract code size is 27219 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. -// Warning 5574: (27226-27319): Contract code size is 27219 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 5574: (0-27130): Contract code size is 27192 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 5574: (27132-27224): Contract code size is 27218 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 5574: (27226-27319): Contract code size is 27218 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. diff --git a/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_shanghai.sol b/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_shanghai.sol index 32e8d9133..dd0122971 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_shanghai.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/combined_too_large_shanghai.sol @@ -26,7 +26,7 @@ contract test { // ==== // EVMVersion: =shanghai // ---- -// Warning 5574: (0-27130): Contract code size is 27187 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. -// Warning 5574: (27132-27224): Contract code size is 27213 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. -// Warning 5574: (27226-27319): Contract code size is 27212 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. -// Warning 3860: (27321-27398): Contract initcode size is 54618 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 5574: (0-27130): Contract code size is 27186 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 5574: (27132-27224): Contract code size is 27212 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 5574: (27226-27319): Contract code size is 27211 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 3860: (27321-27398): Contract initcode size is 54616 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. diff --git a/test/libsolidity/syntaxTests/sizeLimits/initcode_too_large_shanghai.sol b/test/libsolidity/syntaxTests/sizeLimits/initcode_too_large_shanghai.sol index d48693db0..15273c66a 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/initcode_too_large_shanghai.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/initcode_too_large_shanghai.sol @@ -27,4 +27,4 @@ contract test { // ==== // EVMVersion: =shanghai // ---- -// Warning 3860: (20321-20415): Contract initcode size is 60882 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 3860: (20321-20415): Contract initcode size is 60879 bytes and exceeds 49152 bytes (a limit introduced in Shanghai). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi2.yul b/test/libyul/yulOptimizerTests/fullSuite/abi2.yul index d8c8e9055..2f2e060be 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/abi2.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/abi2.yul @@ -1093,25 +1093,21 @@ // value0 := and(calldataload(headStart), sub(shl(160, 1), 1)) // value1 := calldataload(add(headStart, 32)) // let offset := calldataload(add(headStart, 64)) -// let _1 := 0xffffffffffffffff -// if gt(offset, _1) { revert(0, 0) } -// let _2 := add(headStart, offset) -// if iszero(slt(add(_2, 0x1f), dataEnd)) { revert(0, 0) } -// let length := calldataload(_2) -// if gt(length, _1) { revert(0, 0) } -// if gt(add(add(_2, length), 32), dataEnd) { revert(0, 0) } -// value2 := add(_2, 32) +// if gt(offset, 0xffffffffffffffff) { revert(0, 0) } +// let _1 := add(headStart, offset) +// if iszero(slt(add(_1, 0x1f), dataEnd)) { revert(0, 0) } +// let length := calldataload(_1) +// if gt(length, 0xffffffffffffffff) { revert(0, 0) } +// if gt(add(add(_1, length), 32), dataEnd) { revert(0, 0) } +// value2 := add(_1, 32) // value3 := length -// let _3 := calldataload(add(headStart, 96)) -// if iszero(lt(_3, 3)) { revert(0, 0) } -// value4 := _3 +// value4 := cleanup_revert_enum_Operation(calldataload(add(headStart, 96))) // } // function abi_encode_bytes32_address_uint256_bytes32_enum_Operation_uint256_uint256_uint256_address_address_uint256(headStart, value10, value9, value8, value7, value6, value5, value4, value3, value2, value1, value0) -> tail // { // tail := add(headStart, 352) // mstore(headStart, value0) -// let _1 := sub(shl(160, 1), 1) -// mstore(add(headStart, 32), and(value1, _1)) +// mstore(add(headStart, 32), and(value1, sub(shl(160, 1), 1))) // mstore(add(headStart, 64), value2) // mstore(add(headStart, 96), value3) // if iszero(lt(value4, 3)) { invalid() } @@ -1119,8 +1115,13 @@ // mstore(add(headStart, 160), value5) // mstore(add(headStart, 192), value6) // mstore(add(headStart, 224), value7) -// mstore(add(headStart, 256), and(value8, _1)) -// mstore(add(headStart, 288), and(value9, _1)) +// mstore(add(headStart, 256), and(value8, sub(shl(160, 1), 1))) +// mstore(add(headStart, 288), and(value9, sub(shl(160, 1), 1))) // mstore(add(headStart, 320), value10) // } +// function cleanup_revert_enum_Operation(value) -> cleaned +// { +// if iszero(lt(value, 3)) { revert(0, 0) } +// cleaned := value +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul index 2abdf6d9c..dbb87439f 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul @@ -492,68 +492,64 @@ // } // function abi_decode_array_array_uint256_memory_dyn(offset, end) -> array // { -// let _1 := 0x1f // if iszero(slt(add(offset, 0x1f), end)) { revert(0, 0) } // let length := calldataload(offset) // array := allocateMemory(array_allocation_size_array_address_dyn_memory(length)) // let dst := array // mstore(array, length) -// let _2 := 0x20 -// dst := add(array, _2) -// let src := add(offset, _2) -// if gt(add(add(offset, shl(6, length)), _2), end) { revert(0, 0) } +// dst := add(array, 0x20) +// let src := add(offset, 0x20) +// if gt(add(add(offset, shl(6, length)), 0x20), end) { revert(0, 0) } // let i := 0 // for { } lt(i, length) { i := add(i, 1) } // { -// if iszero(slt(add(src, _1), end)) { revert(0, 0) } -// let dst_1 := allocateMemory_967() -// let dst_2 := dst_1 +// if iszero(slt(add(src, 0x1f), end)) { revert(0, 0) } +// let dst_1 := allocateMemory_823() +// let array_1 := dst_1 // let src_1 := src -// let _3 := add(src, 64) -// if gt(_3, end) { revert(0, 0) } +// let _1 := add(src, 64) +// if gt(_1, end) { revert(0, 0) } // let i_1 := 0 // for { } lt(i_1, 0x2) { i_1 := add(i_1, 1) } // { // mstore(dst_1, calldataload(src_1)) -// dst_1 := add(dst_1, _2) -// src_1 := add(src_1, _2) +// dst_1 := add(dst_1, 0x20) +// src_1 := add(src_1, 0x20) // } -// mstore(dst, dst_2) -// dst := add(dst, _2) -// src := _3 +// mstore(dst, array_1) +// dst := add(dst, 0x20) +// src := _1 // } // } // function abi_decode_uint256t_uint256t_array_uint256_dynt_array_array_uint256_memory_dyn(headStart, dataEnd) -> value0, value1, value2, value3 // { // if slt(sub(dataEnd, headStart), 128) { revert(0, 0) } // value0 := calldataload(headStart) -// let _1 := 32 -// value1 := calldataload(add(headStart, _1)) +// value1 := calldataload(add(headStart, 32)) // let offset := calldataload(add(headStart, 64)) -// let _2 := 0xffffffffffffffff -// if gt(offset, _2) { revert(0, 0) } -// let _3 := add(headStart, offset) -// if iszero(slt(add(_3, 0x1f), dataEnd)) { revert(0, 0) } -// let length := calldataload(_3) +// if gt(offset, 0xffffffffffffffff) { revert(0, 0) } +// let _1 := add(headStart, offset) +// if iszero(slt(add(_1, 0x1f), dataEnd)) { revert(0, 0) } +// let length := calldataload(_1) // let dst := allocateMemory(array_allocation_size_array_address_dyn_memory(length)) -// let dst_1 := dst +// let array := dst // mstore(dst, length) -// dst := add(dst, _1) -// let src := add(_3, _1) -// if gt(add(add(_3, shl(5, length)), _1), dataEnd) { revert(0, 0) } +// dst := add(dst, 32) +// let src := add(_1, 32) +// if gt(add(add(_1, shl(5, length)), 32), dataEnd) { revert(0, 0) } // let i := 0 // for { } lt(i, length) { i := add(i, 1) } // { // mstore(dst, calldataload(src)) -// dst := add(dst, _1) -// src := add(src, _1) +// dst := add(dst, 32) +// src := add(src, 32) // } -// value2 := dst_1 +// value2 := array // let offset_1 := calldataload(add(headStart, 96)) -// if gt(offset_1, _2) { revert(0, 0) } +// if gt(offset_1, 0xffffffffffffffff) { revert(0, 0) } // value3 := abi_decode_array_array_uint256_memory_dyn(add(headStart, offset_1), dataEnd) // } -// function allocateMemory_967() -> memPtr +// function allocateMemory_823() -> memPtr // { // memPtr := mload(64) // let newFreePtr := add(memPtr, 64) diff --git a/test/libyul/yulOptimizerTests/fullSuite/ackermann_function.yul b/test/libyul/yulOptimizerTests/fullSuite/ackermann_function.yul index dd5facaf0..bf419017b 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/ackermann_function.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/ackermann_function.yul @@ -36,8 +36,7 @@ // switch n // case 0 { ret := A(add(m, not(0)), 1) } // default { -// let _1 := not(0) -// ret := A(add(m, _1), A(m, add(n, _1))) +// ret := A(add(m, not(0)), A(m, add(n, not(0)))) // } // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/ackermann_function_if.yul b/test/libyul/yulOptimizerTests/fullSuite/ackermann_function_if.yul index 005c58778..edf1a086f 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/ackermann_function_if.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/ackermann_function_if.yul @@ -45,7 +45,6 @@ // ret := A(add(m, not(0)), 1) // leave // } -// let _1 := not(0) -// ret := A(add(m, _1), A(m, add(n, _1))) +// ret := A(add(m, not(0)), A(m, add(n, not(0)))) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul index 2b2205579..8b26a7ba3 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul @@ -237,53 +237,56 @@ // { // mstore(0x80, 7673901602397024137095011250362199966051872585513276903826533215767972925880) // mstore(0xa0, 8489654445897228341090914135473290831551238522473825886865492707826370766375) -// let notes := add(0x04, calldataload(0x04)) +// let _1 := calldataload(0x04) +// let notes := add(0x04, _1) +// let m := calldataload(0x24) // let n := calldataload(notes) -// if gt(calldataload(0x24), n) +// let challenge := mod(calldataload(0x44), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) +// if gt(m, n) // { // mstore(0x00, 404) // revert(0x00, 0x20) // } // let kn := calldataload(add(calldatasize(), not(191))) -// let _1 := 0x2a0 -// mstore(_1, caller()) +// mstore(0x2a0, caller()) // mstore(0x2c0, kn) -// mstore(0x2e0, calldataload(0x24)) -// kn := mulmod(sub(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001, kn), mod(calldataload(0x44), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) +// mstore(0x2e0, m) +// kn := mulmod(sub(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001, kn), challenge, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) // hashCommitments(notes, n) // let b := add(0x300, shl(7, n)) // let i := 0 // for { } lt(i, n) { i := add(i, 0x01) } // { -// let noteIndex := add(add(calldataload(0x04), mul(i, 0xc0)), 0x24) +// let _2 := add(_1, mul(i, 0xc0)) +// let noteIndex := add(_2, 0x24) // let k := 0 -// let a := calldataload(add(add(calldataload(0x04), mul(i, 0xc0)), 0x44)) -// let c := mod(calldataload(0x44), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) -// let _2 := add(i, 0x01) -// switch eq(_2, n) +// let a := calldataload(add(_2, 0x44)) +// let c := challenge +// let _3 := add(i, 0x01) +// switch eq(_3, n) // case 1 { // k := kn -// if eq(calldataload(0x24), n) +// if eq(m, n) // { // k := sub(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001, kn) // } // } // case 0 { k := calldataload(noteIndex) } // validateCommitment(noteIndex, k, a) -// switch gt(_2, calldataload(0x24)) +// switch gt(_3, m) // case 1 { // kn := addmod(kn, sub(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001, k), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) // let x := mod(mload(0), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) // k := mulmod(k, x, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) // a := mulmod(a, x, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) -// c := mulmod(mod(calldataload(0x44), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001), x, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) +// c := mulmod(challenge, x, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) // mstore(0, keccak256(0, 0x20)) // } // case 0 { // kn := addmod(kn, k, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) // } -// calldatacopy(0xe0, add(add(calldataload(0x04), mul(i, 0xc0)), 164), 0x40) -// calldatacopy(0x20, add(add(calldataload(0x04), mul(i, 0xc0)), 100), 0x40) +// calldatacopy(0xe0, add(_2, 164), 0x40) +// calldatacopy(0x20, add(_2, 100), 0x40) // mstore(0x120, sub(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001, c)) // mstore(0x60, k) // mstore(0xc0, a) @@ -292,19 +295,18 @@ // let result_2 := and(result_1, call(gas(), 7, 0, 0x80, 0x60, 0x160, 0x40)) // let result_3 := and(result_2, call(gas(), 6, 0, 0x120, 0x80, 0x160, 0x40)) // result := and(result_3, call(gas(), 6, 0, 0x160, 0x80, b, 0x40)) -// if eq(i, calldataload(0x24)) +// if eq(i, m) // { // mstore(0x260, mload(0x20)) // mstore(0x280, mload(0x40)) // mstore(0x1e0, mload(0xe0)) // mstore(0x200, sub(0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47, mload(0x100))) // } -// if gt(i, calldataload(0x24)) +// if gt(i, m) // { // mstore(0x60, c) -// let _3 := 0x220 -// let result_4 := and(result, call(gas(), 7, 0, 0x20, 0x60, _3, 0x40)) -// let result_5 := and(result_4, call(gas(), 6, 0, _3, 0x80, 0x260, 0x40)) +// let result_4 := and(result, call(gas(), 7, 0, 0x20, 0x60, 0x220, 0x40)) +// let result_5 := and(result_4, call(gas(), 6, 0, 0x220, 0x80, 0x260, 0x40)) // result := and(result_5, call(gas(), 6, 0, 0x1a0, 0x80, 0x1e0, 0x40)) // } // if iszero(result) @@ -314,8 +316,8 @@ // } // b := add(b, 0x40) // } -// if lt(calldataload(0x24), n) { validatePairing() } -// if iszero(eq(mod(keccak256(_1, add(b, not(671))), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001), mod(calldataload(0x44), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001))) +// if lt(m, n) { validatePairing() } +// if iszero(eq(mod(keccak256(0x2a0, add(b, not(671))), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001), challenge)) // { // mstore(0, 404) // revert(0, 0x20) @@ -329,35 +331,28 @@ // let t2_x_1 := calldataload(132) // let t2_y := calldataload(164) // let t2_y_1 := calldataload(196) -// let _1 := 0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b -// let _2 := 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa -// let _3 := 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2 -// let _4 := 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed -// if or(or(or(or(or(or(or(iszero(t2_x), iszero(t2_x_1)), iszero(t2_y)), iszero(t2_y_1)), eq(t2_x, _4)), eq(t2_x_1, _3)), eq(t2_y, _2)), eq(t2_y_1, _1)) +// if or(or(or(or(or(or(or(iszero(t2_x), iszero(t2_x_1)), iszero(t2_y)), iszero(t2_y_1)), eq(t2_x, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed)), eq(t2_x_1, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2)), eq(t2_y, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa)), eq(t2_y_1, 0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b)) // { // mstore(0x00, 400) // revert(0x00, 0x20) // } -// let _5 := mload(0x1e0) -// let _6 := 0x20 -// mstore(_6, _5) +// mstore(0x20, mload(0x1e0)) // mstore(0x40, mload(0x200)) -// mstore(0x80, _4) -// mstore(0x60, _3) -// mstore(0xc0, _2) -// mstore(0xa0, _1) +// mstore(0x80, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) +// mstore(0x60, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) +// mstore(0xc0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) +// mstore(0xa0, 0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) // mstore(0xe0, mload(0x260)) // mstore(0x100, mload(0x280)) // mstore(0x140, t2_x) // mstore(0x120, t2_x_1) -// let _7 := 0x180 -// mstore(_7, t2_y) +// mstore(0x180, t2_y) // mstore(0x160, t2_y_1) -// let success := call(gas(), 8, 0, _6, _7, _6, _6) -// if or(iszero(success), iszero(mload(_6))) +// let success := call(gas(), 8, 0, 0x20, 0x180, 0x20, 0x20) +// if or(iszero(success), iszero(mload(0x20))) // { // mstore(0, 400) -// revert(0, _6) +// revert(0, 0x20) // } // } // function validateCommitment(note, k, a) @@ -366,9 +361,7 @@ // let gammaY := calldataload(add(note, 0x60)) // let sigmaX := calldataload(add(note, 0x80)) // let sigmaY := calldataload(add(note, 0xa0)) -// let _1 := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 -// let _2 := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 -// if iszero(and(and(and(eq(mod(a, _2), a), gt(a, 1)), and(eq(mod(k, _2), k), gt(k, 1))), and(eq(addmod(mulmod(mulmod(sigmaX, sigmaX, _1), sigmaX, _1), 3, _1), mulmod(sigmaY, sigmaY, _1)), eq(addmod(mulmod(mulmod(gammaX, gammaX, _1), gammaX, _1), 3, _1), mulmod(gammaY, gammaY, _1))))) +// if iszero(and(and(and(eq(mod(a, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001), a), gt(a, 1)), and(eq(mod(k, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001), k), gt(k, 1))), and(eq(addmod(mulmod(mulmod(sigmaX, sigmaX, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47), sigmaX, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47), 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47), mulmod(sigmaY, sigmaY, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47)), eq(addmod(mulmod(mulmod(gammaX, gammaX, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47), gammaX, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47), 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47), mulmod(gammaY, gammaY, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47))))) // { // mstore(0x00, 400) // revert(0x00, 0x20) diff --git a/test/libyul/yulOptimizerTests/fullSuite/call_arguments_without_side_effects.yul b/test/libyul/yulOptimizerTests/fullSuite/call_arguments_without_side_effects.yul index fc36bdfa3..5f42470f6 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/call_arguments_without_side_effects.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/call_arguments_without_side_effects.yul @@ -28,21 +28,20 @@ // // { // { -// let _1 := 1 -// mstore(_1, _1) -// mstore(2, _1) -// mstore(3, _1) -// mstore(4, _1) -// mstore(5, _1) -// mstore(6, _1) -// let _2 := sload(8) -// mstore(mload(7), _1) -// mstore(_2, _1) -// mstore(calldataload(9), _1) -// let _3 := mload(13) -// mstore(11, _1) -// mstore(12, _1) -// mstore(_3, _1) +// mstore(1, 1) +// mstore(2, 1) +// mstore(3, 1) +// mstore(4, 1) +// mstore(5, 1) +// mstore(6, 1) +// let _1 := sload(8) +// mstore(mload(7), 1) +// mstore(_1, 1) +// mstore(calldataload(9), 1) +// let _2 := mload(13) +// mstore(11, 1) +// mstore(12, 1) +// mstore(_2, 1) // return(0, 32) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul b/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul index f9d248e2f..6ebca20f5 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul @@ -13,8 +13,7 @@ // // { // { -// let _1 := sub(shl(160, 1), 1) -// let a := and(create2(0, 0, 0x20, 0), _1) -// sstore(a, and(_1, create2(0, 0, 0x20, 0))) +// let a := and(create2(0, 0, 0x20, 0), sub(shl(160, 1), 1)) +// sstore(a, and(sub(shl(160, 1), 1), create2(0, 0, 0x20, 0))) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul b/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul index c89c620bb..078616bb3 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul @@ -13,8 +13,7 @@ // // { // { -// let _1 := sub(shl(160, 1), 1) -// let a := and(create(0, 0, 0x20), _1) -// sstore(a, and(_1, create(0, 0, 0x20))) +// let a := and(create(0, 0, 0x20), sub(shl(160, 1), 1)) +// sstore(a, and(sub(shl(160, 1), 1), create(0, 0, 0x20))) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/devcon_example.yul b/test/libyul/yulOptimizerTests/fullSuite/devcon_example.yul index fe06f1629..fca4a6366 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/devcon_example.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/devcon_example.yul @@ -25,8 +25,11 @@ // let sum := 0 // let length := calldataload(_1) // let i := 0 -// for { } lt(i, length) { i := add(i, 1) } +// for { } true { i := add(i, 1) } // { +// let _2 := iszero(lt(i, length)) +// if _2 { break } +// _2 := 0 // sum := add(sum, calldataload(add(add(_1, shl(5, i)), 0x20))) // } // sstore(0, sum) diff --git a/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul b/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul index 436f5d5fa..dd6cdc0e4 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul @@ -26,12 +26,10 @@ // let value := calldataload(4) // if iszero(eq(value, and(value, sub(shl(160, 1), 1)))) { revert(0, 0) } // let length := extcodesize(value) -// let _1 := 0xffffffffffffffff -// if gt(length, _1) { revert(0, 0) } +// if gt(length, 0xffffffffffffffff) { revert(0, 0) } // let memPtr := mload(64) -// let _2 := not(31) -// let newFreePtr := add(memPtr, and(add(and(add(length, 31), _2), 63), _2)) -// if or(gt(newFreePtr, _1), lt(newFreePtr, memPtr)) { revert(0, 0) } +// let newFreePtr := add(memPtr, and(add(and(add(length, 31), not(31)), 63), not(31))) +// if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { revert(0, 0) } // mstore(64, newFreePtr) // mstore(memPtr, length) // extcodecopy(value, add(memPtr, 32), 0, length) diff --git a/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul b/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul index 86329c327..76d671bfc 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul @@ -29,8 +29,11 @@ // let length := calldataload(_1) // let i := 0 // let _2 := calldataload(7) -// for { } lt(i, length) { i := add(i, 1) } +// for { } true { i := add(i, 1) } // { +// let _3 := iszero(lt(i, length)) +// if _3 { break } +// _3 := 0 // sum := add(sum, add(calldataload(add(add(_1, shl(5, i)), 0x20)), _2)) // } // sstore(0, sum) diff --git a/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_1_pre_shanghai.yul b/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_1_pre_shanghai.yul index d041cff10..4d3ed471b 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_1_pre_shanghai.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_1_pre_shanghai.yul @@ -33,14 +33,13 @@ // { // { // let a := 0 -// let a_1 := 0 -// for { } a_1 { } +// for { } a { } // { -// let _1 := add(a_1, a_1) +// let _1 := add(a, a) // let var := add(_1, _1) -// switch a_1 -// case 0 { a_1 := var } -// default { sstore(a, var) } +// switch a +// case 0 { a := var } +// default { sstore(0, var) } // } // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2_pre_shanghai.yul b/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2_pre_shanghai.yul index 06965e3ca..3161dc2ef 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2_pre_shanghai.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2_pre_shanghai.yul @@ -33,14 +33,13 @@ // { // { // let a := 0 -// let a_1 := 0 -// for { } a_1 { } +// for { } a { } // { -// let _1 := add(a_1, a_1) +// let _1 := add(a, a) // let var := add(_1, _1) -// switch a_1 -// case 0 { a_1 := var } -// default { sstore(a, var) } +// switch a +// case 0 { a := var } +// default { sstore(0, var) } // } // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul b/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul index 75e2ff4c2..5fbe8d22e 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul @@ -40,22 +40,18 @@ // // { // { -// let _1 := 1 -// let _2 := 15 -// let _3 := 10 -// let _4 := gt(not(gcd(_3, _2)), _1) -// let _5 := gcd(_3, _2) -// let _6 := not(0) -// let _7 := lt(or(_1, add(gcd(_3, _2), _6)), _1) -// let _8 := gcd(_3, _2) -// let _9 := gcd(_3, _2) -// pop(keccak256(gcd(_3, _2), or(gt(not(gcd(_3, _2)), _1), _1))) -// mstore(lt(or(gt(_1, or(or(gt(or(or(or(gt(or(gt(_6, _9), _1), _8), _7), _5), _1), _1), _4), _1)), _1), _1), _1) -// sstore(not(gcd(_3, _2)), _1) -// sstore(2, _1) -// extcodecopy(_1, msize(), _1, _1) +// let _1 := gt(not(gcd(10, 15)), 1) +// let _2 := gcd(10, 15) +// let _3 := lt(or(1, add(gcd(10, 15), not(0))), 1) +// let _4 := gcd(10, 15) +// let _5 := gcd(10, 15) +// pop(keccak256(gcd(10, 15), or(gt(not(gcd(10, 15)), 1), 1))) +// mstore(lt(or(gt(1, or(or(gt(or(or(or(gt(or(gt(not(0), _5), 1), _4), _3), _2), 1), 1), _1), 1)), 1), 1), 1) +// sstore(not(gcd(10, 15)), 1) +// sstore(2, 1) +// foo_singlereturn() // sstore(0, 0) -// sstore(3, _1) +// sstore(3, 1) // } // function gcd(_a, _b) -> out // { @@ -63,4 +59,6 @@ // case 0 { out := _a } // default { out := gcd(_b, mod(_a, _b)) } // } +// function foo_singlereturn() +// { extcodecopy(1, msize(), 1, 1) } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/structural_simplification.yul b/test/libyul/yulOptimizerTests/fullSuite/structural_simplification.yul index 85a975fde..aabc14f15 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/structural_simplification.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/structural_simplification.yul @@ -8,4 +8,11 @@ // ---- // step: fullSuite // -// { { sstore(1, 0x20) } } +// { +// { +// mstore(0x40, 0x20) +// for { } iszero(1) { } +// { } +// sstore(1, mload(0x40)) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_loop.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_loop.yul index 148f4a1e7..f0b7546d0 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_loop.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_loop.yul @@ -20,46 +20,18 @@ // { // { // f() -// f_72() -// f_73() +// f() +// f() // sstore(0, 1) // } // function f() // { -// let a := 1 -// let b := 10 -// let a_1 := calldataload(0) -// let _1 := iszero(a_1) -// for { } iszero(b) { b := add(b, not(0)) } -// { -// a := a_1 -// mstore(a_1, 0) -// if _1 { leave } -// } -// } -// function f_72() -// { -// let a := 2 -// let b := 10 -// let a_1 := calldataload(0) -// let _1 := iszero(a_1) -// for { } iszero(b) { b := add(b, not(0)) } -// { -// a := a_1 -// mstore(a_1, 0) -// if _1 { leave } -// } -// } -// function f_73() -// { -// let a := 3 // let b := 10 -// let a_1 := calldataload(0) -// let _1 := iszero(a_1) +// let a := calldataload(0) +// let _1 := iszero(a) // for { } iszero(b) { b := add(b, not(0)) } // { -// a := a_1 -// mstore(a_1, 0) +// mstore(a, 0) // if _1 { leave } // } // } From d5f5742bfc5fff81e5958a5ff230c75d01d222f4 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 8 May 2024 17:25:50 +0200 Subject: [PATCH 0108/1340] CI: Stop installing cvc4 on archlinux This change is in preparation for upgrading to cvc5. Since archlinux is not running SMT tests anyway, we can drop cvc4 from the build immediately. --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 38bcaea7b..6feb033de 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1146,7 +1146,7 @@ jobs: - run: name: Install build dependencies command: | - pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake cvc4 git openssh tar + pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake git openssh tar - checkout - run_build - store_artifacts_solc @@ -1273,7 +1273,7 @@ jobs: - run: name: Install runtime dependencies command: | - pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake z3 cvc4 git openssh tar + pacman --noconfirm -Syu --noprogressbar --needed z3 - soltest t_ubu_clang_soltest: &t_ubu_clang_soltest From 5ffd39a79245be31ffa766e1ed8bba943aac6524 Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 8 May 2024 15:02:07 +0200 Subject: [PATCH 0109/1340] Fix segmentation fault when assigning to a parenthesized non-tuple expression of a tuple type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 3 +- ...d_non_tuple_expressions_of_tuple_types.sol | 40 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/tupleAssignments/assignments_to_tuple_and_non_tuple_expressions_of_tuple_types.sol diff --git a/Changelog.md b/Changelog.md index f34f803e6..252f228c5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ Bugfixes: * SMTChecker: Fix internal error when using bitwise operators with an array element as argument. * Standard JSON Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``optimizerSteps`` sequence. * StaticAnalyzer: Only raise a compile time error for division and modulo by zero when it's between literals. + * TypeChecker: Fix compiler crash when the left-hand side of an assignment was a parenthesized non-tuple expression of a tuple type. * Yul Optimizer: Fix the order of assignments generated by ``SSATransform`` being dependent on AST IDs, sometimes resulting in different (but equivalent) bytecode when unrelated files were added to the compilation pipeline. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index a7402ba40..42c98a8f0 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -116,7 +116,8 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment) TupleType const& lhsType = dynamic_cast(*type(_lhs)); TupleExpression const* lhsResolved = dynamic_cast(resolveOuterUnaryTuples(&_lhs)); - if (lhsType.components().size() != _rhs.components().size() || lhsResolved->components().size() != _rhs.components().size()) + solAssert(!lhsResolved || lhsResolved->components().size() == lhsType.components().size()); + if (lhsType.components().size() != _rhs.components().size()) { solAssert(m_errorReporter.hasErrors(), ""); return; diff --git a/test/libsolidity/syntaxTests/tupleAssignments/assignments_to_tuple_and_non_tuple_expressions_of_tuple_types.sol b/test/libsolidity/syntaxTests/tupleAssignments/assignments_to_tuple_and_non_tuple_expressions_of_tuple_types.sol new file mode 100644 index 000000000..e88d82b85 --- /dev/null +++ b/test/libsolidity/syntaxTests/tupleAssignments/assignments_to_tuple_and_non_tuple_expressions_of_tuple_types.sol @@ -0,0 +1,40 @@ +contract C { + uint[] public array; + + function f() public { + // (f()) is not a tuple expression, but its value is a tuple. + (f()) = (); + } + + function g() public { + // (revert()) is not a tuple expression, but its value is a tuple. + (revert()) = (); + } + + function h() internal returns (uint, uint) {} + + function i() public { + // (h()) is not a tuple expression, but its value is a tuple (uint, uint). + (h()) = (1, 1); + } + + function j() public returns (uint, uint) { + // (j()) is not a tuple expression, but its value is a tuple (uint, uint). + (j()) = (1, 1); + } + + function m() public { + // (uint x, uint y) is a tuple expression, and its value is a tuple (uint, uint). + (uint x, uint y) = (1, 1); + } + + function n() public { + // ((array.push(), array.push())) is not a tuple expression, but contains a tuple expression, and the value of both is a tuple (pointer uint, pointer uint). + ((array.push(), array.push())) = (1, 1); + } +} +// ---- +// TypeError 4247: (126-129): Expression has to be an lvalue. +// TypeError 4247: (236-244): Expression has to be an lvalue. +// TypeError 4247: (407-410): Expression has to be an lvalue. +// TypeError 4247: (550-553): Expression has to be an lvalue. From 9a60c27c3c88a07f7fa69102a5a60f921b1e94b5 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 14 May 2024 12:28:08 +0200 Subject: [PATCH 0110/1340] Update bytecode size test for byzantium. --- .../syntaxTests/sizeLimits/bytecode_too_large_byzantium.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_byzantium.sol b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_byzantium.sol index 67dee4cad..4f3239c22 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_byzantium.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_byzantium.sol @@ -7,4 +7,4 @@ contract test { // ==== // EVMVersion: =byzantium // ---- -// Warning 5574: (0-27133): Contract code size is 27221 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +// Warning 5574: (0-27133): Contract code size is 27220 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. From febe38a27a9aaa0b31a6094d89f97a9c13628f39 Mon Sep 17 00:00:00 2001 From: Pawel Gebal Date: Wed, 8 May 2024 18:10:58 +0200 Subject: [PATCH 0111/1340] SMTChecker: add insufficient funds verification target for CHC engine --- Changelog.md | 2 +- libsolidity/formal/BMC.cpp | 6 +++ libsolidity/formal/CHC.cpp | 18 +++++++ .../model_checker_targets_all_all_engines/err | 14 +----- .../model_checker_targets_all_chc/err | 2 + .../model_checker_targets_balance_chc/err | 1 + .../err | 14 +----- .../model_checker_targets_default_chc/err | 2 + .../output.json | 12 +++++ .../output.json | 49 ++++--------------- .../output.json | 10 ++++ .../blockchain_state/balance_spend.sol | 3 +- .../blockchain_state/balance_spend_2.sol | 6 +-- .../blockchain_state/decreasing_balance.sol | 2 +- .../blockchain_state/free_function_2.sol | 3 +- .../blockchain_state/library_internal_2.sol | 3 +- .../blockchain_state/library_public_2.sol | 2 +- .../{transfer.sol => transfer_1.sol} | 3 +- .../blockchain_state/transfer_2.sol | 14 ++++++ .../blockchain_state/transfer_3.sol | 11 +++++ .../blockchain_state/transfer_4.sol | 12 +++++ .../smtCheckerTests/functions/this_state.sol | 14 +++--- .../types/address_transfer.sol | 2 +- .../types/address_transfer_2.sol | 4 +- .../types/address_transfer_3.sol | 3 +- .../types/address_transfer_insufficient.sol | 4 +- 26 files changed, 125 insertions(+), 91 deletions(-) create mode 100644 test/cmdlineTests/model_checker_targets_balance_chc/err rename test/libsolidity/smtCheckerTests/blockchain_state/{transfer.sol => transfer_1.sol} (66%) create mode 100644 test/libsolidity/smtCheckerTests/blockchain_state/transfer_2.sol create mode 100644 test/libsolidity/smtCheckerTests/blockchain_state/transfer_3.sol create mode 100644 test/libsolidity/smtCheckerTests/blockchain_state/transfer_4.sol diff --git a/Changelog.md b/Changelog.md index 252f228c5..4ed7bd2a3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,7 +5,7 @@ Language Features: Compiler Features: - +* SMTChecker: Create balance check verification target for CHC engine. Bugfixes: * Commandline Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``--yul-optimizations`` sequence. diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 932a315a7..97dd7050f 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -1050,6 +1050,12 @@ void BMC::checkDivByZero(BMCVerificationTarget& _target) void BMC::checkBalance(BMCVerificationTarget& _target) { solAssert(_target.type == VerificationTargetType::Balance, ""); + + if ( + m_solvedTargets.count(_target.expression) && + m_solvedTargets.at(_target.expression).count(VerificationTargetType::Balance) + ) + return; checkCondition( _target, _target.constraints && _target.value, diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 2c9075abc..b6ffd5954 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -607,6 +607,22 @@ void CHC::endVisit(FunctionCall const& _funCall) SMTEncoder::endVisit(_funCall); unknownFunctionCall(_funCall); break; + case FunctionType::Kind::Send: + case FunctionType::Kind::Transfer: + { + auto value = _funCall.arguments().front(); + solAssert(value, ""); + smtutil::Expression thisBalance = state().balance(); + + verificationTargetEncountered( + &_funCall, + VerificationTargetType::Balance, + thisBalance < expr(*value) + ); + + SMTEncoder::endVisit(_funCall); + break; + } case FunctionType::Kind::KECCAK256: case FunctionType::Kind::ECRecover: case FunctionType::Kind::SHA256: @@ -2013,6 +2029,8 @@ std::pair CHC::targetDescription(CHCVerificationTarget con return {"Division by zero", 4281_error}; else if (_target.type == VerificationTargetType::Assert) return {"Assertion violation", 6328_error}; + else if (_target.type == VerificationTargetType::Balance) + return {"Insufficient funds", 8656_error}; else solAssert(false); } diff --git a/test/cmdlineTests/model_checker_targets_all_all_engines/err b/test/cmdlineTests/model_checker_targets_all_all_engines/err index cc8a8ea33..c67d97b61 100644 --- a/test/cmdlineTests/model_checker_targets_all_all_engines/err +++ b/test/cmdlineTests/model_checker_targets_all_all_engines/err @@ -88,21 +88,11 @@ test.f(0x0, 1) 13 | arr[x]; | ^^^^^^ +Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. + Warning: BMC: Condition is always true. --> model_checker_targets_all_all_engines/input.sol:6:11: | 6 | require(x >= 0); | ^^^^^^ Note: Callstack: - -Warning: BMC: Insufficient funds happens here. - --> model_checker_targets_all_all_engines/input.sol:10:3: - | -10 | a.transfer(x); - | ^^^^^^^^^^^^^ -Note: Counterexample: - a = 0 - x = 0 - -Note: Callstack: -Note: diff --git a/test/cmdlineTests/model_checker_targets_all_chc/err b/test/cmdlineTests/model_checker_targets_all_chc/err index d0404ecfb..9c257cefe 100644 --- a/test/cmdlineTests/model_checker_targets_all_chc/err +++ b/test/cmdlineTests/model_checker_targets_all_chc/err @@ -87,3 +87,5 @@ test.f(0x0, 1) | 13 | arr[x]; | ^^^^^^ + +Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/model_checker_targets_balance_chc/err b/test/cmdlineTests/model_checker_targets_balance_chc/err new file mode 100644 index 000000000..57bfe4267 --- /dev/null +++ b/test/cmdlineTests/model_checker_targets_balance_chc/err @@ -0,0 +1 @@ +Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/model_checker_targets_default_all_engines/err b/test/cmdlineTests/model_checker_targets_default_all_engines/err index c1fe2f5b3..62d3b203c 100644 --- a/test/cmdlineTests/model_checker_targets_default_all_engines/err +++ b/test/cmdlineTests/model_checker_targets_default_all_engines/err @@ -58,21 +58,11 @@ test.f(0x0, 1) 13 | arr[x]; | ^^^^^^ +Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. + Warning: BMC: Condition is always true. --> model_checker_targets_default_all_engines/input.sol:6:11: | 6 | require(x >= 0); | ^^^^^^ Note: Callstack: - -Warning: BMC: Insufficient funds happens here. - --> model_checker_targets_default_all_engines/input.sol:10:3: - | -10 | a.transfer(x); - | ^^^^^^^^^^^^^ -Note: Counterexample: - a = 0 - x = 0 - -Note: Callstack: -Note: diff --git a/test/cmdlineTests/model_checker_targets_default_chc/err b/test/cmdlineTests/model_checker_targets_default_chc/err index bd2aa0b4d..70f3c5bc6 100644 --- a/test/cmdlineTests/model_checker_targets_default_chc/err +++ b/test/cmdlineTests/model_checker_targets_default_chc/err @@ -57,3 +57,5 @@ test.f(0x0, 1) | 13 | arr[x]; | ^^^^^^ + +Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json index f047ff70a..9d3e40b70 100644 --- a/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json @@ -1,4 +1,16 @@ { + "errors": [ + { + "component": "general", + "errorCode": "1391", + "formattedMessage": "Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. + +", + "message": "CHC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" + } + ], "sources": { "A": { "id": 0 diff --git a/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json b/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json index 2318e5adf..8f20d854b 100644 --- a/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json @@ -148,6 +148,16 @@ test.f(0x0, 1)", }, "type": "Warning" }, + { + "component": "general", + "errorCode": "1391", + "formattedMessage": "Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. + +", + "message": "CHC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" + }, { "component": "general", "errorCode": "6838", @@ -172,45 +182,6 @@ Note: Callstack: "start": 159 }, "type": "Warning" - }, - { - "component": "general", - "errorCode": "1236", - "formattedMessage": "Warning: BMC: Insufficient funds happens here. - --> A:11:7: - | -11 | \t\t\t\t\t\ta.transfer(x); - | \t\t\t\t\t\t^^^^^^^^^^^^^ -Note: Counterexample: - a = 0 - x = 0 - -Note: Callstack: -Note: - -", - "message": "BMC: Insufficient funds happens here.", - "secondarySourceLocations": [ - { - "message": "Counterexample: - a = 0 - x = 0 -" - }, - { - "message": "Callstack:" - }, - { - "message": "" - } - ], - "severity": "warning", - "sourceLocation": { - "end": 237, - "file": "A", - "start": 224 - }, - "type": "Warning" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json index eb39e0271..e045a8bff 100644 --- a/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json @@ -147,6 +147,16 @@ test.f(0x0, 1)", "start": 283 }, "type": "Warning" + }, + { + "component": "general", + "errorCode": "1391", + "formattedMessage": "Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. + +", + "message": "CHC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol index 387e45bb9..720ab5695 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol @@ -19,5 +19,4 @@ contract C { // SMTIgnoreCex: yes // ---- // Warning 6328: (280-314): CHC: Assertion violation happens here. -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 1236: (175-190): BMC: Insufficient funds happens here. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol index 5df0b9995..3ceac964f 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol @@ -15,9 +15,9 @@ contract C { // ==== // SMTEngine: all // SMTIgnoreCex: yes +// SMTIgnoreOS: macos // ---- -// Warning 6328: (193-226): CHC: Assertion violation might happen here. +// Warning 8656: (141-156): CHC: Insufficient funds happens here. +// Warning 6328: (193-226): CHC: Assertion violation happens here. // Warning 6328: (245-279): CHC: Assertion violation happens here. // Warning 6328: (298-332): CHC: Assertion violation happens here. -// Warning 1236: (141-156): BMC: Insufficient funds happens here. -// Warning 4661: (193-226): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/decreasing_balance.sol b/test/libsolidity/smtCheckerTests/blockchain_state/decreasing_balance.sol index 76455060d..df35a2785 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/decreasing_balance.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/decreasing_balance.sol @@ -18,4 +18,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/free_function_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/free_function_2.sol index e2e187038..3b7c0f9dc 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/free_function_2.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/free_function_2.sol @@ -20,5 +20,4 @@ contract C { // SMTIgnoreCex: yes // ---- // Warning 6328: (258-274): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 1236: (33-46): BMC: Insufficient funds happens here. +// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/library_internal_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/library_internal_2.sol index f16a57acf..826af0bf8 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/library_internal_2.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/library_internal_2.sol @@ -23,5 +23,4 @@ contract C { // SMTIgnoreCex: yes // ---- // Warning 6328: (315-331): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 1236: (87-100): BMC: Insufficient funds happens here. +// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/library_public_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/library_public_2.sol index 4b500581d..02e29be8d 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/library_public_2.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/library_public_2.sol @@ -21,6 +21,6 @@ contract C { // SMTIgnoreCex: yes // ---- // Warning 4588: (238-243): Assertion checker does not yet implement this type of function call. +// Warning 8656: (54-67): CHC: Insufficient funds happens here. // Warning 6328: (282-298): CHC: Assertion violation happens here. // Warning 6328: (317-331): CHC: Assertion violation happens here. -// Warning 1236: (54-67): BMC: Insufficient funds happens here. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/transfer.sol b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_1.sol similarity index 66% rename from test/libsolidity/smtCheckerTests/blockchain_state/transfer.sol rename to test/libsolidity/smtCheckerTests/blockchain_state/transfer_1.sol index c099ffb2e..3118086b9 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/transfer.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_1.sol @@ -12,5 +12,4 @@ contract C { // SMTIgnoreCex: yes // ---- // Warning 6328: (166-201): CHC: Assertion violation happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. \ No newline at end of file diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_2.sol new file mode 100644 index 000000000..ed5b4c90f --- /dev/null +++ b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_2.sol @@ -0,0 +1,14 @@ +contract C { + address payable recipient; + uint amount; + + function shouldHold() public { + uint tempAmount = address(this).balance; + recipient.transfer(tempAmount); + recipient.transfer(amount); + } +} +// ==== +// SMTEngine: chc +// ---- +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_3.sol b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_3.sol new file mode 100644 index 000000000..4b3318b6b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_3.sol @@ -0,0 +1,11 @@ +contract C { + address payable recipient; + + function shouldFail() public { + recipient.transfer(1); + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 8656: (76-97): CHC: Insufficient funds happens here. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_4.sol b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_4.sol new file mode 100644 index 000000000..ab0c4a81e --- /dev/null +++ b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_4.sol @@ -0,0 +1,12 @@ +contract C { + address payable recipient; + + function f() public payable { + require(msg.value > 1); + recipient.transfer(1); + } +} +// ==== +// SMTEngine: all +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/functions/this_state.sol b/test/libsolidity/smtCheckerTests/functions/this_state.sol index dec101060..d069bd90f 100644 --- a/test/libsolidity/smtCheckerTests/functions/this_state.sol +++ b/test/libsolidity/smtCheckerTests/functions/this_state.sol @@ -1,14 +1,14 @@ contract C { - uint public x; - function g() public { + uint public x; + function g() public { x = 0; - this.h(); + this.h(); assert(x == 2); - } - function h() public { - x = 2; - } + } + function h() public { + x = 2; + } } // ==== // SMTEngine: all diff --git a/test/libsolidity/smtCheckerTests/types/address_transfer.sol b/test/libsolidity/smtCheckerTests/types/address_transfer.sol index 89e8ae102..1430e15cb 100644 --- a/test/libsolidity/smtCheckerTests/types/address_transfer.sol +++ b/test/libsolidity/smtCheckerTests/types/address_transfer.sol @@ -11,5 +11,5 @@ contract C // ==== // SMTEngine: all // ---- +// Warning 8656: (98-113): CHC: Insufficient funds happens here. // Warning 6328: (162-186): CHC: Assertion violation happens here. -// Warning 1236: (98-113): BMC: Insufficient funds happens here. diff --git a/test/libsolidity/smtCheckerTests/types/address_transfer_2.sol b/test/libsolidity/smtCheckerTests/types/address_transfer_2.sol index 0a2c08d0c..ce6492d9e 100644 --- a/test/libsolidity/smtCheckerTests/types/address_transfer_2.sol +++ b/test/libsolidity/smtCheckerTests/types/address_transfer_2.sol @@ -15,6 +15,6 @@ contract C // SMTEngine: all // SMTIgnoreCex: yes // ---- +// Warning 8656: (184-199): CHC: Insufficient funds happens here. +// Warning 8656: (203-218): CHC: Insufficient funds happens here. // Warning 6328: (262-291): CHC: Assertion violation happens here. -// Warning 1236: (184-199): BMC: Insufficient funds happens here. -// Warning 1236: (203-218): BMC: Insufficient funds happens here. diff --git a/test/libsolidity/smtCheckerTests/types/address_transfer_3.sol b/test/libsolidity/smtCheckerTests/types/address_transfer_3.sol index 02d20c4f5..3f9cc22c7 100644 --- a/test/libsolidity/smtCheckerTests/types/address_transfer_3.sol +++ b/test/libsolidity/smtCheckerTests/types/address_transfer_3.sol @@ -13,5 +13,4 @@ contract C // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/address_transfer_insufficient.sol b/test/libsolidity/smtCheckerTests/types/address_transfer_insufficient.sol index 59568cb5b..55a96026e 100644 --- a/test/libsolidity/smtCheckerTests/types/address_transfer_insufficient.sol +++ b/test/libsolidity/smtCheckerTests/types/address_transfer_insufficient.sol @@ -12,6 +12,6 @@ contract C // SMTEngine: all // SMTIgnoreCex: yes // ---- +// Warning 8656: (101-116): CHC: Insufficient funds happens here. +// Warning 8656: (120-136): CHC: Insufficient funds happens here. // Warning 6328: (180-204): CHC: Assertion violation happens here. -// Warning 1236: (101-116): BMC: Insufficient funds happens here. -// Warning 1236: (120-136): BMC: Insufficient funds happens here. From c84863f90773523beec4ce871d527655e5d7be9f Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 9 May 2023 17:27:30 +0200 Subject: [PATCH 0112/1340] Do not allocate memory on reverts with small errors. Do not allocate memory on reverts with small errors. Workaround for StringLiteralType Addition require error test coverage --- Changelog.md | 4 +- libsolidity/codegen/YulUtilFunctions.cpp | 42 ++++++++++++++++- .../cmdlineTests/require_with_error_ir/output | 4 ++ .../require_with_string_ir/output | 4 ++ .../errors/errors_by_parameter_type.sol | 45 +++++++++++++++++++ .../errors/small_error_optimization.sol | 22 +++++++++ 6 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol create mode 100644 test/libsolidity/semanticTests/errors/small_error_optimization.sol diff --git a/Changelog.md b/Changelog.md index 4ed7bd2a3..6f129732c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,7 +5,9 @@ Language Features: Compiler Features: -* SMTChecker: Create balance check verification target for CHC engine. + * SMTChecker: Create balance check verification target for CHC engine. + * Yul IR Code Generation: Cheaper code for reverting with errors of a small static encoding size. + Bugfixes: * Commandline Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``--yul-optimizations`` sequence. diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index b71dfd566..9d1929fe1 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -32,11 +32,30 @@ #include #include +#include + using namespace solidity; using namespace solidity::util; using namespace solidity::frontend; using namespace std::string_literals; +namespace +{ + +std::optional staticEncodingSize(std::vector const& _parameterTypes) +{ + size_t encodedSize = 0; + for (auto* type: _parameterTypes) + { + if (type->isDynamicallyEncoded()) + return std::nullopt; + encodedSize += type->calldataHeadSize(); + } + return encodedSize; +} + +} + std::string YulUtilFunctions::identityFunction() { std::string functionName = "identity"; @@ -226,9 +245,26 @@ std::string YulUtilFunctions::revertWithError( { solAssert((!_posVar.empty() && !_endVar.empty()) || (_posVar.empty() && _endVar.empty())); bool const needsNewVariable = !_posVar.empty() && !_endVar.empty(); + bool needsAllocation = true; + + if (std::optional size = staticEncodingSize(_parameterTypes)) + if ( + ranges::all_of(_parameterTypes, [](auto const* type) { + solAssert(!dynamic_cast(type)); + return type && type->isValueType(); + }) + ) + { + constexpr size_t errorSelectorSize = 4; + needsAllocation = *size + errorSelectorSize > CompilerUtils::generalPurposeMemoryStart; + } Whiskers templ(R"({ + let := () + + let := 0 + mstore(, ) let := (add(, 4) ) revert(, sub(, )) @@ -236,7 +272,9 @@ std::string YulUtilFunctions::revertWithError( templ("pos", needsNewVariable ? _posVar : "memPtr"); templ("end", needsNewVariable ? _endVar : "end"); templ("hash", formatNumber(util::selectorFromSignatureU256(_signature))); - templ("allocateUnbounded", allocateUnboundedFunction()); + templ("needsAllocation", needsAllocation); + if (needsAllocation) + templ("allocateUnbounded", allocateUnboundedFunction()); std::vector errorArgumentVars; std::vector errorArgumentTypes; @@ -282,7 +320,7 @@ std::string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* } )") ("functionName", functionName) - ("revertWithError", revertWithError("Error(string)", {_messageType}, {_stringArgumentExpression})) + ("revertWithError", revertWithError("Error(string)", {TypeProvider::stringMemory()}, {_stringArgumentExpression})) ("functionParameterNames", joinHumanReadablePrefixed(functionParameterNames)) .render(); }); diff --git a/test/cmdlineTests/require_with_error_ir/output b/test/cmdlineTests/require_with_error_ir/output index 232f0d76f..09515f3cd 100644 --- a/test/cmdlineTests/require_with_error_ir/output +++ b/test/cmdlineTests/require_with_error_ir/output @@ -186,7 +186,9 @@ object "C_36" { function require_helper_t_error_7_CustomError_t_rational_1_by_1_t_stringliteral_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720(condition , expr_15) { if iszero(condition) { + let memPtr := allocate_unbounded() + mstore(memPtr, 0x97ea5a2f00000000000000000000000000000000000000000000000000000000) let end := abi_encode_tuple_t_rational_1_by_1_t_stringliteral_332c39dcd398ea34a48b871898d589f55fc4c7bce00562fb670c972e7e1b0720__to_t_uint256_t_string_memory_ptr__fromStack(add(memPtr, 4) , expr_15) revert(memPtr, sub(end, memPtr)) @@ -241,7 +243,9 @@ object "C_36" { function require_helper_t_error_7_CustomError_t_rational_2_by_1_t_stringliteral_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5(condition , expr_29) { if iszero(condition) { + let memPtr := allocate_unbounded() + mstore(memPtr, 0x97ea5a2f00000000000000000000000000000000000000000000000000000000) let end := abi_encode_tuple_t_rational_2_by_1_t_stringliteral_89027a4db8d1d3a0787296eb1553fba0dc506f981f9697f1a66994c458d392b5__to_t_uint256_t_string_memory_ptr__fromStack(add(memPtr, 4) , expr_29) revert(memPtr, sub(end, memPtr)) diff --git a/test/cmdlineTests/require_with_string_ir/output b/test/cmdlineTests/require_with_string_ir/output index 21828ac2a..3a19db372 100644 --- a/test/cmdlineTests/require_with_string_ir/output +++ b/test/cmdlineTests/require_with_string_ir/output @@ -228,7 +228,9 @@ object "C_28" { function require_helper_t_string_memory_ptr(condition , expr_12_mpos) { if iszero(condition) { + let memPtr := allocate_unbounded() + mstore(memPtr, 0x08c379a000000000000000000000000000000000000000000000000000000000) let end := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(add(memPtr, 4) , expr_12_mpos) revert(memPtr, sub(end, memPtr)) @@ -266,7 +268,9 @@ object "C_28" { function require_helper_t_stringliteral_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46(condition ) { if iszero(condition) { + let memPtr := allocate_unbounded() + mstore(memPtr, 0x08c379a000000000000000000000000000000000000000000000000000000000) let end := abi_encode_tuple_t_stringliteral_b25d43cff48de8365ad132c5f45b74f4593f9e69e5b749d86685f77282c88e46__to_t_string_memory_ptr__fromStack(add(memPtr, 4) ) revert(memPtr, sub(end, memPtr)) diff --git a/test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol b/test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol new file mode 100644 index 000000000..bc70b5bef --- /dev/null +++ b/test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol @@ -0,0 +1,45 @@ +pragma abicoder v2; + +struct S { + uint256 a; + bool b; + string s; +} + +error E(); +error E1(uint256); +error E2(string); +error E3(S); +error E4(address); +error E5(function() external pure); + +contract C { + function a() external pure { + require(false, E()); + } + function b() external pure { + require(false, E1(1)); + } + function c() external pure { + require(false, E2("string literal")); + } + function d() external pure { + require(false, E3(S(1, true, "string literal"))); + } + function e() external view { + require(false, E4(address(this))); + } + function f() external view { + require(false, E5(this.a)); + } +} + +// ==== +// compileViaYul: true +// ---- +// a() -> FAILURE, hex"92bbf6e8" +// b() -> FAILURE, hex"47e26897", hex"0000000000000000000000000000000000000000000000000000000000000001" +// c() -> FAILURE, hex"8f372c34", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"000000000000000000000000000000000000000000000000000000000000000e", hex"737472696e67206c69746572616c000000000000000000000000000000000000" +// d() -> FAILURE, hex"5717173e", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"000000000000000000000000000000000000000000000000000000000000000e", hex"737472696e67206c69746572616c000000000000000000000000000000000000" +// e() -> FAILURE, hex"7efef9ea", hex"000000000000000000000000c06afe3a8444fc0004668591e8306bfb9968e79e" +// f() -> FAILURE, hex"0c3f12eb", hex"c06afe3a8444fc0004668591e8306bfb9968e79e0dbe671f0000000000000000" diff --git a/test/libsolidity/semanticTests/errors/small_error_optimization.sol b/test/libsolidity/semanticTests/errors/small_error_optimization.sol new file mode 100644 index 000000000..0c9cd750a --- /dev/null +++ b/test/libsolidity/semanticTests/errors/small_error_optimization.sol @@ -0,0 +1,22 @@ +error E(); +contract A { + uint8[] x; + function f() public { + for (uint i = 0; i < 100; ++i) + x.push(uint8(i)); + revert E(); + } +} +contract B { + function f() public { + (new A()).f(); + } +} +// ---- +// f() -> FAILURE, hex"92bbf6e8" +// gas irOptimized: 221918 +// gas irOptimized code: 42800 +// gas legacy: 233746 +// gas legacy code: 37400 +// gas legacyOptimized: 224864 +// gas legacyOptimized code: 34200 From e3e4f665232fbd77d81260a7f8f65f529cef68b3 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 13 May 2024 16:40:17 +0200 Subject: [PATCH 0113/1340] Remove bzzr entries from static binary section in the docs --- docs/installing-solidity.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 8d5b421d3..f079fb024 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -249,7 +249,6 @@ Each one includes a ``list.json`` file listing the available binaries. For examp "keccak256": "0x300330ecd127756b824aa13e843cb1f43c473cb22eaf3750d5fb9c99279af8c3", "sha256": "0x2b55ed5fec4d9625b6c7b3ab1abd2b7fb7dd2a9c68543bf0323db2c7e2d55af2", "urls": [ - "bzzr://16c5f09109c793db99fe35f037c6092b061bd39260ee7a677c8a97f18c955ab1", "dweb:/ipfs/QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS" ] } @@ -264,7 +263,7 @@ This means that: In this case git is not necessary and symlinks are resolved transparently, either by serving a copy of the file or returning a HTTP redirect. - The file is also available on IPFS at `QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS`_. -- The file might in future be available on Swarm at `16c5f09109c793db99fe35f037c6092b061bd39260ee7a677c8a97f18c955ab1`_. + Please, be aware that the order of items in the ``urls`` array is not predetermined or guaranteed and users should not rely on it. - You can verify the integrity of the binary by comparing its keccak256 hash to ``0x300330ecd127756b824aa13e843cb1f43c473cb22eaf3750d5fb9c99279af8c3``. The hash can be computed on the command-line using ``keccak256sum`` utility provided by `sha3sum`_ or `keccak256() function @@ -305,14 +304,12 @@ This means that: in the long-term. .. _IPFS: https://ipfs.io -.. _Swarm: https://swarm-gateways.net/bzz:/swarm.eth .. _solc-bin: https://github.com/ethereum/solc-bin/ .. _Solidity release page on GitHub: https://github.com/ethereum/solidity/releases .. _sha3sum: https://github.com/maandree/sha3sum .. _keccak256() function from ethereumjs-util: https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/modules/_hash_.md#const-keccak256 .. _WebAssembly builds: https://emscripten.org/docs/compiling/WebAssembly.html .. _QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS: https://gateway.ipfs.io/ipfs/QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS -.. _16c5f09109c793db99fe35f037c6092b061bd39260ee7a677c8a97f18c955ab1: https://swarm-gateways.net/bzz:/16c5f09109c793db99fe35f037c6092b061bd39260ee7a677c8a97f18c955ab1/ .. _building-from-source: From 8216a70e5b308da5c0302395f62d89ec281ec99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 May 2024 14:58:05 +0200 Subject: [PATCH 0114/1340] Add the missing changelog entry for the new default optimizer sequence --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 6f129732c..c6ec0a553 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Language Features: Compiler Features: * SMTChecker: Create balance check verification target for CHC engine. * Yul IR Code Generation: Cheaper code for reverting with errors of a small static encoding size. + * Yul Optimizer: New, faster default optimizer step sequence. Bugfixes: From 108d398a7cb9200087b1b0f5baf036414ea8c14c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 May 2024 16:14:33 +0200 Subject: [PATCH 0115/1340] Changelog: Optimizer -> Yul Optimizer in the entry for the superfluous sequence repetition bugfix --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index c6ec0a553..443259806 100644 --- a/Changelog.md +++ b/Changelog.md @@ -12,7 +12,6 @@ Compiler Features: Bugfixes: * Commandline Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``--yul-optimizations`` sequence. - * Optimizer: Fix optimizer executing each repeating part of the step sequence at least twice, even if the code size already became stable after the first iteration. * SMTChecker: Fix false positive when comparing hashes of same array or string literals. * SMTChecker: Fix internal error on mapping access caused by too strong requirements on sort compatibility of the index and mapping domain. * SMTChecker: Fix internal error when using an empty tuple in a conditional operator. @@ -20,6 +19,7 @@ Bugfixes: * Standard JSON Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``optimizerSteps`` sequence. * StaticAnalyzer: Only raise a compile time error for division and modulo by zero when it's between literals. * TypeChecker: Fix compiler crash when the left-hand side of an assignment was a parenthesized non-tuple expression of a tuple type. + * Yul Optimizer: Fix optimizer executing each repeating part of the step sequence at least twice, even if the code size already became stable after the first iteration. * Yul Optimizer: Fix the order of assignments generated by ``SSATransform`` being dependent on AST IDs, sometimes resulting in different (but equivalent) bytecode when unrelated files were added to the compilation pipeline. From bbf5aa2f5b662b1d522e4eb280325ba2a30d5979 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 15 May 2024 18:42:19 +0200 Subject: [PATCH 0116/1340] Remove json-cpp from create source tarball script. --- scripts/create_source_tarball.sh | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/scripts/create_source_tarball.sh b/scripts/create_source_tarball.sh index 1ea8c0b57..4af1cf586 100755 --- a/scripts/create_source_tarball.sh +++ b/scripts/create_source_tarball.sh @@ -29,17 +29,6 @@ REPO_ROOT="$(dirname "$0")"/.. then cp prerelease.txt "$SOLDIR/" fi - # Add dependencies - mkdir -p "$SOLDIR/deps/downloads/" 2>/dev/null || true - jsoncpp_version="1.9.3" - jsoncpp_package_path="$SOLDIR/deps/downloads/jsoncpp-${jsoncpp_version}.tar.gz" - jsoncpp_sha256=8593c1d69e703563d94d8c12244e2e18893eeb9a8a9f8aa3d09a327aa45c8f7d - wget -O "$jsoncpp_package_path" "https://github.com/open-source-parsers/jsoncpp/archive/${jsoncpp_version}.tar.gz" - if ! [ "$(sha256sum "$jsoncpp_package_path")" = "${jsoncpp_sha256} ${jsoncpp_package_path}" ] - then - >&2 echo "ERROR: Downloaded jsoncpp source package has wrong checksum." - exit 1 - fi mkdir -p "$REPO_ROOT/upload" tar --owner 0 --group 0 -czf "$REPO_ROOT/upload/solidity_$versionstring.tar.gz" -C "$TEMPDIR" "solidity_$versionstring" rm -r "$TEMPDIR" From 70e1edcebe3c0e5621ca590afae2744e9a284e92 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 15 May 2024 18:39:25 +0200 Subject: [PATCH 0117/1340] Update PPA release script. --- scripts/deps-ppa/static_z3.sh | 2 +- scripts/release_ppa.sh | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/deps-ppa/static_z3.sh b/scripts/deps-ppa/static_z3.sh index be45f4452..016cd5d21 100755 --- a/scripts/deps-ppa/static_z3.sh +++ b/scripts/deps-ppa/static_z3.sh @@ -41,7 +41,7 @@ sourcePPAConfig # Sanity check checkDputEntries "\[cpp-build-deps\]" -DISTRIBUTIONS="focal jammy mantic" +DISTRIBUTIONS="focal jammy mantic noble" for distribution in $DISTRIBUTIONS do diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 9a94fbcf2..0e4eb7ed4 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -68,7 +68,7 @@ packagename=solc # This needs to be a still active release static_build_distribution=focal -DISTRIBUTIONS="focal jammy mantic" +DISTRIBUTIONS="focal jammy mantic noble" if is_release then @@ -125,7 +125,8 @@ mv solidity solc # Fetch dependencies mkdir -p ./solc/deps/downloads/ 2>/dev/null || true -wget -O ./solc/deps/downloads/jsoncpp-1.9.3.tar.gz https://github.com/open-source-parsers/jsoncpp/archive/1.9.3.tar.gz +mkdir -p ./solc/deps/nlohmann/nlohmann/ 2>/dev/null || true +wget -O ./solc/deps/nlohmann/nlohmann/json.hpp https://github.com/nlohmann/json/releases/download/v3.11.3/json.hpp wget -O ./solc/deps/downloads/range-v3-0.12.0.tar.gz https://github.com/ericniebler/range-v3/archive/0.12.0.tar.gz wget -O ./solc/deps/downloads/fmt-9.1.0.tar.gz https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz From 659d13fcbe97cd89ace325c3493e38253bb9f889 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 15 May 2024 18:00:36 +0200 Subject: [PATCH 0118/1340] Add header include for docker builds. --- liblangutil/Token.h | 1 + 1 file changed, 1 insertion(+) diff --git a/liblangutil/Token.h b/liblangutil/Token.h index d1073a872..d9438271c 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -42,6 +42,7 @@ #pragma once +#include #include #include #include From acec7170bad18b3dce83badec128e3cb75caec53 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 15 May 2024 18:53:04 +0200 Subject: [PATCH 0119/1340] Update license template. --- cmake/templates/license.h.in | 221 ++++++++++++++++++++++++++++------- 1 file changed, 176 insertions(+), 45 deletions(-) diff --git a/cmake/templates/license.h.in b/cmake/templates/license.h.in index 2d7f2691a..7ade6be05 100644 --- a/cmake/templates/license.h.in +++ b/cmake/templates/license.h.in @@ -3,7 +3,7 @@ #include static std::string const otherLicenses{R"(Most of the code is licensed under GPLv3 (see below), the license for individual -parts are as follows: +parts and dependencies are as follows: libkeccak-tiny: The file libsolutil/Keccak256.cpp incorporates libkeccak-tiny. @@ -11,6 +11,26 @@ libkeccak-tiny: A single-file implementation of SHA-3 and SHAKE implemented by David Leon Gil License: CC0, attribution kindly requested. Blame taken too, but not liability. +nlohmann-json: + The source code of nlohmann-json is licensed under the following + conditions: + + The class is licensed under the MIT License: + + Copyright © 2013-2022 Niels Lohmann + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the MIT License (see above). Copyright © 2008-2009 Björn Hoehrmann bjoern@hoehrmann.de + + The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the MIT License (see above). Copyright © 2009 Florian Loitsch + + The class contains a copy of Hedley from Evan Nemerson which is licensed as CC0-1.0. + picosha2: The file libsolutil/picosha2.h is imported. @@ -34,62 +54,160 @@ picosha2: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -jsoncpp: - The JsonCpp library's source code, including accompanying documentation, - tests and demonstration applications, are licensed under the following - conditions... +range-v3: + The range-v3 library is licensed under the following conditions: + + ======================================================== + Boost Software License - Version 1.0 - August 17th, 2003 + ======================================================== - The JsonCpp Authors explicitly disclaim copyright in all - jurisdictions which recognize such a disclaimer. In such jurisdictions, - this software is released into the Public Domain. + Permission is hereby granted, free of charge, to any person or organization + obtaining a copy of the software and accompanying documentation covered by + this license (the "Software") to use, reproduce, display, distribute, + execute, and transmit the Software, and to prepare derivative works of the + Software, and to permit third-parties to whom the Software is furnished to + do so, all subject to the following: - In jurisdictions which do not recognize Public Domain property (e.g. Germany as of - 2010), this software is Copyright (c) 2007-2010 by The JsonCpp Authors, and is - released under the terms of the MIT License (see below). + The copyright notices in the Software and this entire statement, including + the above license grant, this restriction and the following disclaimer, + must be included in all copies of the Software, in whole or in part, and + all derivative works of the Software, unless such copies or derivative + works are solely in the form of machine-executable object code generated by + a source language processor. - In jurisdictions which recognize Public Domain property, the user of this - software may choose to accept it either as 1) Public Domain, 2) under the - conditions of the MIT License (see below), or 3) under the terms of dual - Public Domain/MIT License conditions described here, as they choose. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. - The MIT License is about as close to Public Domain as a license can get, and is - described in clear, concise terms at: + ============================================================================== + libc++ License + ============================================================================== - http://en.wikipedia.org/wiki/MIT_License + The libc++ library is dual licensed under both the University of Illinois + "BSD-Like" license and the MIT license. As a user of this code you may choose + to use it under either license. As a contributor, you agree to allow your code + to be used under both. - The full text of the MIT License follows: + Full text of the relevant licenses is included below. - ======================================================================== - Copyright (c) 2007-2010 The JsonCpp Authors + ============================================================================== - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, copy, - modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: + University of Illinois/NCSA + Open Source License - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. + Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT + http://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. - ======================================================================== - (END LICENSE TEXT) - The MIT license is compatible with both the GPL and commercial - software, affording one all of the rights of Public Domain with the - minor nuisance of being required to keep the above copyright notice - and license text in the source code. Note also that by accepting the - Public Domain "license" you can re-license your copy using whatever - license you like. + ============================================================================== + + Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT + http://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + ============================================================================== + Stepanov and McJones, "Elements of Programming" license + ============================================================================== + + // Copyright (c) 2009 Alexander Stepanov and Paul McJones + // + // Permission to use, copy, modify, distribute and sell this software + // and its documentation for any purpose is hereby granted without + // fee, provided that the above copyright notice appear in all copies + // and that both that copyright notice and this permission notice + // appear in supporting documentation. The authors make no + // representations about the suitability of this software for any + // purpose. It is provided "as is" without express or implied + // warranty. + // + // Algorithms from + // Elements of Programming + // by Alexander Stepanov and Paul McJones + // Addison-Wesley Professional, 2009 + + ============================================================================== + SGI C++ Standard Template Library license + ============================================================================== + + // Copyright (c) 1994 + // Hewlett-Packard Company + // + // Permission to use, copy, modify, distribute and sell this software + // and its documentation for any purpose is hereby granted without fee, + // provided that the above copyright notice appear in all copies and + // that both that copyright notice and this permission notice appear + // in supporting documentation. Hewlett-Packard Company makes no + // representations about the suitability of this software for any + // purpose. It is provided "as is" without express or implied warranty. + // + // Copyright (c) 1996 + // Silicon Graphics Computer Systems, Inc. + // + // Permission to use, copy, modify, distribute and sell this software + // and its documentation for any purpose is hereby granted without fee, + // provided that the above copyright notice appear in all copies and + // that both that copyright notice and this permission notice appear + // in supporting documentation. Silicon Graphics makes no + // representations about the suitability of this software for any + // purpose. It is provided "as is" without express or implied warranty. + // scanner/token: The liblangutil/{CharStream,Scanner,Token}.{h,cpp} files are derived from @@ -167,6 +285,19 @@ base64: Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ +Z3: + The Z3 library is licensed under the following terms: + + Copyright (c) Microsoft Corporation + All rights reserved. + MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + All other code is licensed under GPL version 3: From 24f18e83a6c81935daa150c129b4007d5a41a014 Mon Sep 17 00:00:00 2001 From: hydai Date: Wed, 15 May 2024 23:39:26 +0800 Subject: [PATCH 0120/1340] Remove using namespace std from testing tools, ossfuzz and yulPhaser Signed-off-by: hydai --- scripts/check_style.sh | 4 + test/tools/afl_fuzzer.cpp | 23 +- test/tools/fuzzer_common.cpp | 43 ++- test/tools/isoltest.cpp | 121 ++++--- test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp | 11 +- .../SolidityCustomMutatorInterface.cpp | 7 +- .../tools/ossfuzz/SolidityEvmoneInterface.cpp | 19 +- test/tools/ossfuzz/SolidityGenerator.cpp | 53 ++- .../tools/ossfuzz/StackReuseCodegenFuzzer.cpp | 23 +- test/tools/ossfuzz/abiV2ProtoFuzzer.cpp | 13 +- test/tools/ossfuzz/const_opt_ossfuzz.cpp | 4 +- test/tools/ossfuzz/protoToAbiV2.cpp | 321 +++++++++--------- test/tools/ossfuzz/protoToSol.cpp | 59 ++-- test/tools/ossfuzz/protoToYul.cpp | 151 ++++---- .../ossfuzz/protomutators/YulProtoMutator.cpp | 9 +- test/tools/ossfuzz/solProtoFuzzer.cpp | 15 +- test/tools/ossfuzz/solc_ossfuzz.cpp | 9 +- .../ossfuzz/strictasm_assembly_ossfuzz.cpp | 5 +- test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 9 +- test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp | 5 +- test/tools/ossfuzz/yulFuzzerCommon.cpp | 5 +- test/tools/ossfuzz/yulProtoFuzzer.cpp | 11 +- test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp | 19 +- test/tools/yulopti.cpp | 93 +++-- test/tools/yulrun.cpp | 31 +- tools/yulPhaser/AlgorithmRunner.cpp | 41 ++- tools/yulPhaser/Chromosome.cpp | 25 +- tools/yulPhaser/Common.cpp | 15 +- tools/yulPhaser/FitnessMetrics.cpp | 9 +- tools/yulPhaser/GeneticAlgorithms.cpp | 13 +- tools/yulPhaser/Mutations.cpp | 65 ++-- tools/yulPhaser/PairSelections.cpp | 23 +- tools/yulPhaser/Phaser.cpp | 195 ++++++----- tools/yulPhaser/Population.cpp | 53 ++- tools/yulPhaser/Program.cpp | 63 ++-- tools/yulPhaser/ProgramCache.cpp | 29 +- tools/yulPhaser/Selections.cpp | 27 +- tools/yulPhaser/SimulationRNG.cpp | 5 +- 38 files changed, 796 insertions(+), 830 deletions(-) diff --git a/scripts/check_style.sh b/scripts/check_style.sh index 3c9acf86c..e9d470b76 100755 --- a/scripts/check_style.sh +++ b/scripts/check_style.sh @@ -50,8 +50,12 @@ NAMESPACE_STD_FREE_FILES=( test/libsolidity/util/* test/libyul/* test/solc/* + test/tools/* + test/tools/ossfuzz/* + test/tools/ossfuzz/protomutators/* test/tools/yulInterpreter/* test/yulPhaser/* + tools/yulPhaser/* ) ( diff --git a/test/tools/afl_fuzzer.cpp b/test/tools/afl_fuzzer.cpp index af0939c2b..bac98d76b 100644 --- a/test/tools/afl_fuzzer.cpp +++ b/test/tools/afl_fuzzer.cpp @@ -28,7 +28,6 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::util; @@ -60,11 +59,11 @@ Allowed options)", ) ( "input-file", - po::value(), + po::value(), "input file" )( "input-files", - po::value>()->multitoken(), + po::value>()->multitoken(), "input files" ) ( @@ -86,7 +85,7 @@ Allowed options)", } catch (po::error const& _exception) { - cerr << _exception.what() << endl; + std::cerr << _exception.what() << std::endl; return 1; } @@ -95,26 +94,26 @@ Allowed options)", if (arguments.count("help")) { - cout << options; + std::cout << options; return 0; } - vector inputs; + std::vector inputs; if (arguments.count("input-file")) - inputs.push_back(arguments["input-file"].as()); + inputs.push_back(arguments["input-file"].as()); else if (arguments.count("input-files")) - inputs = arguments["input-files"].as>(); + inputs = arguments["input-files"].as>(); else inputs.emplace_back(""); bool optimize = !arguments.count("without-optimizer"); int retResult = 0; - for (string const& inputFile: inputs) + for (std::string const& inputFile: inputs) { - string input; + std::string input; if (inputFile.size() == 0) - input = readUntilEnd(cin); + input = readUntilEnd(std::cin); else input = readFileAsString(inputFile); @@ -134,7 +133,7 @@ Allowed options)", if (inputFile.size() == 0) throw; - cerr << "Fuzzer " + std::cerr << "Fuzzer " << (optimize ? "" : "(without optimizer) ") << "failed on " << inputFile; diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index c7e94f40b..b05488382 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -33,14 +33,13 @@ #include -using namespace std; using namespace solidity; using namespace solidity::evmasm; using namespace solidity::frontend; using namespace solidity::langutil; using namespace solidity::util; -static vector s_evmVersions = { +static std::vector s_evmVersions = { EVMVersion::homestead(), EVMVersion::tangerineWhistle(), EVMVersion::spuriousDragon(), @@ -53,10 +52,10 @@ static vector s_evmVersions = { EVMVersion::paris() }; -void FuzzerUtil::testCompilerJsonInterface(string const& _input, bool _optimize, bool _quiet) +void FuzzerUtil::testCompilerJsonInterface(std::string const& _input, bool _optimize, bool _quiet) { if (!_quiet) - cout << "Testing compiler " << (_optimize ? "with" : "without") << " optimizer." << endl; + std::cout << "Testing compiler " << (_optimize ? "with" : "without") << " optimizer." << std::endl; Json config; config["language"] = "Solidity"; @@ -82,7 +81,7 @@ void FuzzerUtil::forceSMT(StringMap& _input) // Add SMT checker pragma if not already present in source static auto constexpr smtPragma = "pragma experimental SMTChecker;"; for (auto &sourceUnit: _input) - if (sourceUnit.second.find(smtPragma) == string::npos) + if (sourceUnit.second.find(smtPragma) == std::string::npos) sourceUnit.second += smtPragma; } @@ -144,13 +143,13 @@ void FuzzerUtil::testCompiler( } } -void FuzzerUtil::runCompiler(string const& _input, bool _quiet) +void FuzzerUtil::runCompiler(std::string const& _input, bool _quiet) { if (!_quiet) - cout << "Input JSON: " << _input << endl; - string outputString(solidity_compile(_input.c_str(), nullptr, nullptr)); + std::cout << "Input JSON: " << _input << std::endl; + std::string outputString(solidity_compile(_input.c_str(), nullptr, nullptr)); if (!_quiet) - cout << "Output JSON: " << outputString << endl; + std::cout << "Output JSON: " << outputString << std::endl; // This should be safe given the above copies the output. solidity_reset(); @@ -158,32 +157,32 @@ void FuzzerUtil::runCompiler(string const& _input, bool _quiet) Json output; if (!jsonParseStrict(outputString, output)) { - string msg{"Compiler produced invalid JSON output."}; - cout << msg << endl; + std::string msg{"Compiler produced invalid JSON output."}; + std::cout << msg << std::endl; BOOST_THROW_EXCEPTION(std::runtime_error(std::move(msg))); } if (output.contains("errors")) for (auto const& error: output["errors"]) { - string invalid = findAnyOf(error["type"].get(), vector{ + std::string invalid = findAnyOf(error["type"].get(), std::vector{ "Exception", "InternalCompilerError" }); if (!invalid.empty()) { - string msg = "Invalid error: \"" + error["type"].get() + "\""; - cout << msg << endl; + std::string msg = "Invalid error: \"" + error["type"].get() + "\""; + std::cout << msg << std::endl; BOOST_THROW_EXCEPTION(std::runtime_error(std::move(msg))); } } } -void FuzzerUtil::testConstantOptimizer(string const& _input, bool _quiet) +void FuzzerUtil::testConstantOptimizer(std::string const& _input, bool _quiet) { if (!_quiet) - cout << "Testing constant optimizer" << endl; - vector numbers; - stringstream sin(_input); + std::cout << "Testing constant optimizer" << std::endl; + std::vector numbers; + std::stringstream sin(_input); while (!sin.eof()) { @@ -192,7 +191,7 @@ void FuzzerUtil::testConstantOptimizer(string const& _input, bool _quiet) numbers.push_back(u256(data)); } if (!_quiet) - cout << "Got " << numbers.size() << " inputs:" << endl; + std::cout << "Got " << numbers.size() << " inputs:" << std::endl; for (bool isCreation: {false, true}) { @@ -200,7 +199,7 @@ void FuzzerUtil::testConstantOptimizer(string const& _input, bool _quiet) for (u256 const& n: numbers) { if (!_quiet) - cout << n << endl; + std::cout << n << std::endl; assembly.append(n); } for (unsigned runs: {1u, 2u, 3u, 20u, 40u, 100u, 200u, 400u, 1000u}) @@ -217,10 +216,10 @@ void FuzzerUtil::testConstantOptimizer(string const& _input, bool _quiet) } } -void FuzzerUtil::testStandardCompiler(string const& _input, bool _quiet) +void FuzzerUtil::testStandardCompiler(std::string const& _input, bool _quiet) { if (!_quiet) - cout << "Testing compiler via JSON interface." << endl; + std::cout << "Testing compiler via JSON interface." << std::endl; runCompiler(_input, _quiet); } diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index 9d20f1059..fa56b35d7 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -38,7 +38,6 @@ #include #endif -using namespace std; using namespace solidity; using namespace solidity::util; using namespace solidity::frontend; @@ -69,24 +68,24 @@ struct TestStats class TestFilter { public: - explicit TestFilter(string _filter): m_filter(std::move(_filter)) + explicit TestFilter(std::string _filter): m_filter(std::move(_filter)) { - string filter{m_filter}; + std::string filter{m_filter}; boost::replace_all(filter, "/", "\\/"); boost::replace_all(filter, "*", ".*"); - m_filterExpression = regex{"(" + filter + "(\\.sol|\\.yul|\\.stack))"}; + m_filterExpression = std::regex{"(" + filter + "(\\.sol|\\.yul|\\.stack))"}; } - bool matches(fs::path const& _path, string const& _name) const + bool matches(fs::path const& _path, std::string const& _name) const { - return regex_match(_name, m_filterExpression) && solidity::test::isValidSemanticTestPath(_path); + return std::regex_match(_name, m_filterExpression) && solidity::test::isValidSemanticTestPath(_path); } private: - string m_filter; - regex m_filterExpression; + std::string m_filter; + std::regex m_filterExpression; }; class TestTool @@ -96,7 +95,7 @@ class TestTool TestCreator _testCaseCreator, TestOptions const& _options, fs::path _path, - string _name + std::string _name ): m_testCaseCreator(_testCaseCreator), m_options(_options), @@ -137,9 +136,9 @@ class TestTool TestOptions const& m_options; TestFilter m_filter; fs::path const m_path; - string const m_name; + std::string const m_name; - unique_ptr m_test; + std::unique_ptr m_test; static bool m_exitRequested; }; @@ -154,7 +153,7 @@ TestTool::Result TestTool::process() { if (m_filter.matches(m_path, m_name)) { - (AnsiColorized(cout, formatted, {BOLD}) << m_name << ": ").flush(); + (AnsiColorized(std::cout, formatted, {BOLD}) << m_name << ": ").flush(); m_test = m_testCaseCreator(TestCase::Config{ m_path.string(), @@ -170,22 +169,22 @@ TestTool::Result TestTool::process() switch (TestCase::TestResult result = m_test->run(outputMessages, " ", formatted)) { case TestCase::TestResult::Success: - AnsiColorized(cout, formatted, {BOLD, GREEN}) << "OK" << endl; + AnsiColorized(std::cout, formatted, {BOLD, GREEN}) << "OK" << std::endl; return Result::Success; default: - AnsiColorized(cout, formatted, {BOLD, RED}) << "FAIL" << endl; + AnsiColorized(std::cout, formatted, {BOLD, RED}) << "FAIL" << std::endl; - AnsiColorized(cout, formatted, {BOLD, CYAN}) << " Contract:" << endl; - m_test->printSource(cout, " ", formatted); - m_test->printSettings(cout, " ", formatted); + AnsiColorized(std::cout, formatted, {BOLD, CYAN}) << " Contract:" << std::endl; + m_test->printSource(std::cout, " ", formatted); + m_test->printSettings(std::cout, " ", formatted); - cout << endl << outputMessages.str() << endl; + std::cout << std::endl << outputMessages.str() << std::endl; return result == TestCase::TestResult::FatalError ? Result::Exception : Result::Failure; } } else { - AnsiColorized(cout, formatted, {BOLD, YELLOW}) << "NOT RUN" << endl; + AnsiColorized(std::cout, formatted, {BOLD, YELLOW}) << "NOT RUN" << std::endl; return Result::Skipped; } } @@ -194,30 +193,30 @@ TestTool::Result TestTool::process() } catch (boost::exception const& _e) { - AnsiColorized(cout, formatted, {BOLD, RED}) << - "Exception during test: " << boost::diagnostic_information(_e) << endl; + AnsiColorized(std::cout, formatted, {BOLD, RED}) << + "Exception during test: " << boost::diagnostic_information(_e) << std::endl; return Result::Exception; } catch (std::exception const& _e) { - AnsiColorized(cout, formatted, {BOLD, RED}) << - "Exception during test: " << boost::diagnostic_information(_e) << endl; + AnsiColorized(std::cout, formatted, {BOLD, RED}) << + "Exception during test: " << boost::diagnostic_information(_e) << std::endl; return Result::Exception; } catch (...) { - AnsiColorized(cout, formatted, {BOLD, RED}) << - "Unknown exception during test: " << boost::current_exception_diagnostic_information() << endl; + AnsiColorized(std::cout, formatted, {BOLD, RED}) << + "Unknown exception during test: " << boost::current_exception_diagnostic_information() << std::endl; return Result::Exception; } } void TestTool::updateTestCase() { - ofstream file(m_path.string(), ios::trunc); + std::ofstream file(m_path.string(), std::ios::trunc); m_test->printSource(file); m_test->printUpdatedSettings(file); - file << "// ----" << endl; + file << "// ----" << std::endl; m_test->printUpdatedExpectations(file, "// "); } @@ -230,34 +229,34 @@ TestTool::Request TestTool::handleResponse(bool _exception) } if (_exception) - cout << "(e)dit/(s)kip/(q)uit? "; + std::cout << "(e)dit/(s)kip/(q)uit? "; else - cout << "(e)dit/(u)pdate expectations/(s)kip/(q)uit? "; - cout.flush(); + std::cout << "(e)dit/(u)pdate expectations/(s)kip/(q)uit? "; + std::cout.flush(); while (true) { switch(readStandardInputChar()) { case 's': - cout << endl; + std::cout << std::endl; return Request::Skip; case 'u': if (_exception) break; else { - cout << endl; + std::cout << std::endl; updateTestCase(); return Request::Rerun; } case 'e': - cout << endl << endl; + std::cout << std::endl << std::endl; if (system((m_options.editor + " \"" + m_path.string() + "\"").c_str())) - cerr << "Error running editor command." << endl << endl; + std::cerr << "Error running editor command." << std::endl << std::endl; return Request::Rerun; case 'q': - cout << endl; + std::cout << std::endl; return Request::Quit; default: break; @@ -326,7 +325,7 @@ TestStats TestTool::processPath( m_exitRequested = true; break; case Request::Rerun: - cout << "Re-running test case..." << endl; + std::cout << "Re-running test case..." << std::endl; --testCount; break; case Request::Skip: @@ -379,7 +378,7 @@ std::optional runTestSuite( TestOptions const& _options, fs::path const& _basePath, fs::path const& _subdirectory, - string const& _name, + std::string const& _name, solidity::test::Batcher& _batcher ) { @@ -388,7 +387,7 @@ std::optional runTestSuite( if (!fs::exists(testPath) || !fs::is_directory(testPath)) { - cerr << _name << " tests not found. Use the --testpath argument." << endl; + std::cerr << _name << " tests not found. Use the --testpath argument." << std::endl; return std::nullopt; } @@ -402,19 +401,19 @@ std::optional runTestSuite( if (stats.skippedCount != stats.testCount) { - cout << endl << _name << " Test Summary: "; - AnsiColorized(cout, formatted, {BOLD, stats ? GREEN : RED}) << + std::cout << std::endl << _name << " Test Summary: "; + AnsiColorized(std::cout, formatted, {BOLD, stats ? GREEN : RED}) << stats.successCount << "/" << stats.testCount; - cout << " tests successful"; + std::cout << " tests successful"; if (stats.skippedCount > 0) { - cout << " ("; - AnsiColorized(cout, formatted, {BOLD, YELLOW}) << stats.skippedCount; - cout<< " tests skipped)"; + std::cout << " ("; + AnsiColorized(std::cout, formatted, {BOLD, YELLOW}) << stats.skippedCount; + std::cout<< " tests skipped)"; } - cout << "." << endl << endl; + std::cout << "." << std::endl << std::endl; } return stats; } @@ -446,14 +445,14 @@ int main(int argc, char const *argv[]) return EXIT_FAILURE; if (options.disableSemanticTests) - cout << endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << endl << endl; + std::cout << std::endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << std::endl << std::endl; TestStats global_stats{0, 0}; - cout << "Running tests..." << endl << endl; + std::cout << "Running tests..." << std::endl << std::endl; Batcher batcher(CommonOptions::get().selectedBatch, CommonOptions::get().batches); if (CommonOptions::get().batches > 1) - cout << "Batch " << CommonOptions::get().selectedBatch << " out of " << CommonOptions::get().batches << endl; + std::cout << "Batch " << CommonOptions::get().selectedBatch << " out of " << CommonOptions::get().batches << std::endl; // Actually run the tests. // Interactive tests are added in InteractiveTests.h @@ -479,42 +478,42 @@ int main(int argc, char const *argv[]) return EXIT_FAILURE; } - cout << endl << "Summary: "; - AnsiColorized(cout, !options.noColor, {BOLD, global_stats ? GREEN : RED}) << + std::cout << std::endl << "Summary: "; + AnsiColorized(std::cout, !options.noColor, {BOLD, global_stats ? GREEN : RED}) << global_stats.successCount << "/" << global_stats.testCount; - cout << " tests successful"; + std::cout << " tests successful"; if (global_stats.skippedCount > 0) { - cout << " ("; - AnsiColorized(cout, !options.noColor, {BOLD, YELLOW}) << global_stats.skippedCount; - cout << " tests skipped)"; + std::cout << " ("; + AnsiColorized(std::cout, !options.noColor, {BOLD, YELLOW}) << global_stats.skippedCount; + std::cout << " tests skipped)"; } - cout << "." << endl; + std::cout << "." << std::endl; if (options.disableSemanticTests) - cout << "\nNOTE: Skipped semantics tests.\n" << endl; + std::cout << "\nNOTE: Skipped semantics tests.\n" << std::endl; return global_stats ? EXIT_SUCCESS : EXIT_FAILURE; } catch (boost::program_options::error const& exception) { - cerr << exception.what() << endl; + std::cerr << exception.what() << std::endl; return 2; } catch (std::runtime_error const& exception) { - cerr << exception.what() << endl; + std::cerr << exception.what() << std::endl; return 2; } catch (solidity::test::ConfigException const& exception) { - cerr << exception.what() << endl; + std::cerr << exception.what() << std::endl; return 2; } catch (...) { - cerr << "Unhandled exception caught." << endl; - cerr << boost::current_exception_diagnostic_information() << endl; + std::cerr << "Unhandled exception caught." << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; return 2; } } diff --git a/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp b/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp index 78697a9dd..e10979ee1 100644 --- a/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp +++ b/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp @@ -29,7 +29,6 @@ using namespace solidity::test::abiv2fuzzer; using namespace solidity::test; using namespace solidity::util; using namespace solidity; -using namespace std; static constexpr size_t abiCoderHeapSize = 1024 * 512; static evmc::VM evmone = evmc::VM{evmc_create_evmone()}; @@ -37,18 +36,18 @@ static evmc::VM evmone = evmc::VM{evmc_create_evmone()}; DEFINE_PROTO_FUZZER(Contract const& _contract) { ProtoConverter converter(_contract.seed()); - string contractSource = converter.contractToString(_contract); + std::string contractSource = converter.contractToString(_contract); if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) { // With libFuzzer binary run this to generate the solidity source file x.sol from a proto input: // PROTO_FUZZER_DUMP_PATH=x.sol ./a.out proto-input - ofstream of(dump_path); + std::ofstream of(dump_path); of << contractSource; } - string typeString = converter.isabelleTypeString(); - string valueString = converter.isabelleValueString(); + std::string typeString = converter.isabelleTypeString(); + std::string valueString = converter.isabelleValueString(); abicoder::ABICoder coder(abiCoderHeapSize); if (!typeString.empty() && converter.coderFunction()) { @@ -58,7 +57,7 @@ DEFINE_PROTO_FUZZER(Contract const& _contract) // We target the default EVM which is the latest langutil::EVMVersion version; EVMHost hostContext(version, evmone); - string contractName = "C"; + std::string contractName = "C"; StringMap source({{"test.sol", contractSource}}); CompilerInput cInput(version, source, contractName, OptimiserSettings::minimal(), {}); EvmoneUtility evmoneUtil( diff --git a/test/tools/ossfuzz/SolidityCustomMutatorInterface.cpp b/test/tools/ossfuzz/SolidityCustomMutatorInterface.cpp index ea5fa20ce..738d69b8c 100644 --- a/test/tools/ossfuzz/SolidityCustomMutatorInterface.cpp +++ b/test/tools/ossfuzz/SolidityCustomMutatorInterface.cpp @@ -21,7 +21,6 @@ #include -using namespace std; using namespace solidity::test::fuzzer::mutator; // Prototype as we can't use the FuzzerInterface.h header. @@ -54,17 +53,17 @@ SolidityCustomMutatorInterface::SolidityCustomMutatorInterface( data(_data), size(_size), maxMutantSize(_maxSize), - generator(make_shared(_seed)) + generator(std::make_shared(_seed)) {} size_t SolidityCustomMutatorInterface::generate() { - string testCase = generator->generateTestProgram(); + std::string testCase = generator->generateTestProgram(); solAssert( !testCase.empty() && data, "Solc custom mutator: Invalid mutant or memory pointer" ); - size_t mutantSize = min(testCase.size(), maxMutantSize - 1); + size_t mutantSize = std::min(testCase.size(), maxMutantSize - 1); mempcpy(data, testCase.data(), mutantSize); return mutantSize; } diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp index 9d98190dd..425239808 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp @@ -28,9 +28,8 @@ using namespace solidity::test::fuzzer; using namespace solidity::frontend; using namespace solidity::langutil; using namespace solidity::util; -using namespace std; -optional SolidityCompilationFramework::compileContract() +std::optional SolidityCompilationFramework::compileContract() { m_compiler.setSources(m_compilerInput.sourceCode); m_compiler.setLibraries(m_compilerInput.libraryAddresses); @@ -41,8 +40,8 @@ optional SolidityCompilationFramework::compileContract() { if (m_compilerInput.debugFailure) { - cerr << "Compiling contract failed" << endl; - cerr << SourceReferenceFormatter::formatErrorInformation( + std::cerr << "Compiling contract failed" << std::endl; + std::cerr << SourceReferenceFormatter::formatErrorInformation( m_compiler.errors(), m_compiler ); @@ -51,7 +50,7 @@ optional SolidityCompilationFramework::compileContract() } else { - string contractName; + std::string contractName; if (m_compilerInput.contractName.empty()) contractName = m_compiler.lastContractName(); else @@ -103,7 +102,7 @@ evmc::Result EvmoneUtility::deployContract(bytes const& _code) evmc::Result EvmoneUtility::deployAndExecute( bytes const& _byteCode, - string const& _hexEncodedInput + std::string const& _hexEncodedInput ) { // Deploy contract and signal failure if deploy failed @@ -128,9 +127,9 @@ evmc::Result EvmoneUtility::deployAndExecute( return callResult; } -evmc::Result EvmoneUtility::compileDeployAndExecute(string _fuzzIsabelle) +evmc::Result EvmoneUtility::compileDeployAndExecute(std::string _fuzzIsabelle) { - map libraryAddressMap; + std::map libraryAddressMap; // Stage 1: Compile and deploy library if present. if (!m_libraryName.empty()) { @@ -158,7 +157,7 @@ evmc::Result EvmoneUtility::compileDeployAndExecute(string _fuzzIsabelle) "SolidityEvmoneInterface: Invalid compilation output." ); - string methodName; + std::string methodName; if (!_fuzzIsabelle.empty()) // TODO: Remove this once a cleaner solution is found for querying // isabelle test entry point. At the moment, we are sure that the @@ -175,7 +174,7 @@ evmc::Result EvmoneUtility::compileDeployAndExecute(string _fuzzIsabelle) ); } -optional EvmoneUtility::compileContract() +std::optional EvmoneUtility::compileContract() { try { diff --git a/test/tools/ossfuzz/SolidityGenerator.cpp b/test/tools/ossfuzz/SolidityGenerator.cpp index 1d836a4ae..1897de6f1 100644 --- a/test/tools/ossfuzz/SolidityGenerator.cpp +++ b/test/tools/ossfuzz/SolidityGenerator.cpp @@ -23,7 +23,6 @@ using namespace solidity::test::fuzzer::mutator; using namespace solidity::util; -using namespace std; GeneratorBase::GeneratorBase(std::shared_ptr _mutator) { @@ -32,11 +31,11 @@ GeneratorBase::GeneratorBase(std::shared_ptr _mutator) uRandDist = mutator->uniformRandomDist(); } -string GeneratorBase::visitChildren() +std::string GeneratorBase::visitChildren() { - ostringstream os; + std::ostringstream os; // Randomise visit order - vector randomisedChildren; + std::vector randomisedChildren; for (auto const& child: generators) randomisedChildren.push_back(child); shuffle(randomisedChildren.begin(), randomisedChildren.end(), *uRandDist->randomEngine); @@ -47,7 +46,7 @@ string GeneratorBase::visitChildren() return os.str(); } -string TestState::randomPath(set const& _sourceUnitPaths) const +std::string TestState::randomPath(std::set const& _sourceUnitPaths) const { auto it = _sourceUnitPaths.begin(); /// Advance iterator by n where 0 <= n <= sourceUnitPaths.size() - 1 @@ -60,7 +59,7 @@ string TestState::randomPath(set const& _sourceUnitPaths) const return *it; } -string TestState::randomPath() const +std::string TestState::randomPath() const { solAssert(!empty(), "Solc custom mutator: Null test state"); return randomPath(sourceUnitPaths); @@ -73,20 +72,20 @@ void TestState::print(std::ostream& _os) const _os << "Source path: " << item << std::endl; } -string TestState::randomNonCurrentPath() const +std::string TestState::randomNonCurrentPath() const { /// To obtain a source path that is not the currently visited /// source unit itself, we require at least one other source /// unit to be previously visited. solAssert(size() >= 2, "Solc custom mutator: Invalid test state"); - set filteredSourcePaths; - string currentPath = currentSourceUnitPath; - copy_if( + std::set filteredSourcePaths; + std::string currentPath = currentSourceUnitPath; + std::copy_if( sourceUnitPaths.begin(), sourceUnitPaths.end(), inserter(filteredSourcePaths, filteredSourcePaths.begin()), - [currentPath](string const& _item) { + [currentPath](std::string const& _item) { return _item != currentPath; } ); @@ -100,12 +99,12 @@ void TestCaseGenerator::setup() }); } -string TestCaseGenerator::visit() +std::string TestCaseGenerator::visit() { - ostringstream os; + std::ostringstream os; for (unsigned i = 0; i < uRandDist->distributionOneToN(s_maxSourceUnits); i++) { - string sourcePath = path(); + std::string sourcePath = path(); os << "\n" << "==== Source: " << sourcePath @@ -126,32 +125,32 @@ void SourceUnitGenerator::setup() }); } -string SourceUnitGenerator::visit() +std::string SourceUnitGenerator::visit() { return visitChildren(); } -string PragmaGenerator::visit() +std::string PragmaGenerator::visit() { static constexpr const char* preamble = R"( pragma solidity >= 0.0.0; pragma experimental SMTChecker; )"; // Choose equally at random from coder v1 and v2 - string abiPragma = "pragma abicoder v" + - to_string(uRandDist->distributionOneToN(2)) + + std::string abiPragma = "pragma abicoder v" + + std::to_string(uRandDist->distributionOneToN(2)) + ";\n"; return preamble + abiPragma; } -string ImportGenerator::visit() +std::string ImportGenerator::visit() { /* * Case 1: No source units defined * Case 2: One source unit defined * Case 3: At least two source units defined */ - ostringstream os; + std::ostringstream os; // Self import with a small probability only if // there is one source unit present in test. if (state->size() == 1) @@ -175,19 +174,19 @@ string ImportGenerator::visit() } template -shared_ptr SolidityGenerator::generator() +std::shared_ptr SolidityGenerator::generator() { for (auto& g: m_generators) - if (holds_alternative>(g)) - return get>(g); + if (std::holds_alternative>(g)) + return std::get>(g); solAssert(false, ""); } SolidityGenerator::SolidityGenerator(unsigned _seed) { m_generators = {}; - m_urd = make_shared(make_unique(_seed)); - m_state = make_shared(m_urd); + m_urd = std::make_shared(std::make_unique(_seed)); + m_state = std::make_shared(m_urd); } template @@ -200,14 +199,14 @@ void SolidityGenerator::createGenerators() } } -string SolidityGenerator::generateTestProgram() +std::string SolidityGenerator::generateTestProgram() { createGenerators(); for (auto& g: m_generators) std::visit(GenericVisitor{ [&](auto const& _item) { return _item->setup(); } }, g); - string program = generator()->generate(); + std::string program = generator()->generate(); destroyGenerators(); return program; } diff --git a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp index fb502af52..25559bc66 100644 --- a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp +++ b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp @@ -46,7 +46,6 @@ using namespace solidity::test::fuzzer; using namespace solidity::yul; using namespace solidity::yul::test::yul_fuzzer; using namespace solidity::langutil; -using namespace std; static evmc::VM evmone = evmc::VM{evmc_create_evmone()}; @@ -80,7 +79,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) filterStatefulInstructions, filterUnboundedLoops ); - string yul_source = converter.programToString(_input); + std::string yul_source = converter.programToString(_input); // Do not fuzz the EVM Version field. // See https://github.com/ethereum/solidity/issues/12590 langutil::EVMVersion version; @@ -89,8 +88,8 @@ DEFINE_PROTO_FUZZER(Program const& _input) if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) { - ofstream of(dump_path); - of.write(yul_source.data(), static_cast(yul_source.size())); + std::ofstream of(dump_path); + of.write(yul_source.data(), static_cast(yul_source.size())); } YulStringRepository::reset(); @@ -103,7 +102,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) bool unoptimizedStackTooDeep = false; try { - YulAssembler assembler{version, nullopt, settings, yul_source}; + YulAssembler assembler{version, std::nullopt, settings, yul_source}; unoptimisedByteCode = assembler.assemble(); auto yulObject = assembler.object(); recursiveFunction = recursiveFunctionExists( @@ -116,7 +115,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) unoptimizedStackTooDeep = true; } - ostringstream unoptimizedState; + std::ostringstream unoptimizedState; bool noRevertInSource = true; bool noInvalidInSource = true; if (!unoptimizedStackTooDeep) @@ -128,8 +127,8 @@ DEFINE_PROTO_FUZZER(Program const& _input) evmc::Result callResult = hostContext.call(callMessage); // If the fuzzer synthesized input does not contain the revert opcode which // we lazily check by string find, the EVM call should not revert. - noRevertInSource = yul_source.find("revert") == string::npos; - noInvalidInSource = yul_source.find("invalid") == string::npos; + noRevertInSource = yul_source.find("revert") == std::string::npos; + noInvalidInSource = yul_source.find("invalid") == std::string::npos; if (noInvalidInSource) solAssert( callResult.status_code != EVMC_INVALID_INSTRUCTION, @@ -157,7 +156,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) bytes optimisedByteCode; try { - optimisedByteCode = YulAssembler{version, nullopt, settings, yul_source}.assemble(); + optimisedByteCode = YulAssembler{version, std::nullopt, settings, yul_source}.assemble(); } catch (solidity::yul::StackTooDeepError const&) { @@ -194,13 +193,13 @@ DEFINE_PROTO_FUZZER(Program const& _input) (!noInvalidInSource && callResultOpt.status_code == EVMC_INVALID_INSTRUCTION)), "Optimised call failed." ); - ostringstream optimizedState; + std::ostringstream optimizedState; optimizedState << EVMHostPrinter{hostContext, deployResultOpt.create_address}.state(); if (unoptimizedState.str() != optimizedState.str()) { - cout << unoptimizedState.str() << endl; - cout << optimizedState.str() << endl; + std::cout << unoptimizedState.str() << std::endl; + std::cout << optimizedState.str() << std::endl; solAssert( false, "State of unoptimised and optimised stack reused code do not match." diff --git a/test/tools/ossfuzz/abiV2ProtoFuzzer.cpp b/test/tools/ossfuzz/abiV2ProtoFuzzer.cpp index 6d792a70c..bdfe4e48c 100644 --- a/test/tools/ossfuzz/abiV2ProtoFuzzer.cpp +++ b/test/tools/ossfuzz/abiV2ProtoFuzzer.cpp @@ -29,27 +29,26 @@ using namespace solidity::test::abiv2fuzzer; using namespace solidity::test; using namespace solidity::util; using namespace solidity; -using namespace std; static evmc::VM evmone = evmc::VM{evmc_create_evmone()}; DEFINE_PROTO_FUZZER(Contract const& _input) { - string contract_source = ProtoConverter{_input.seed()}.contractToString(_input); + std::string contract_source = ProtoConverter{_input.seed()}.contractToString(_input); if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) { // With libFuzzer binary run this to generate the solidity source file x.sol from a proto input: // PROTO_FUZZER_DUMP_PATH=x.sol ./a.out proto-input - ofstream of(dump_path); + std::ofstream of(dump_path); of << contract_source; } // We target the default EVM which is the latest langutil::EVMVersion version; EVMHost hostContext(version, evmone); - string contractName = "C"; - string methodName = "test()"; + std::string contractName = "C"; + std::string methodName = "test()"; StringMap source({{"test.sol", contract_source}}); CompilerInput cInput(version, source, contractName, OptimiserSettings::minimal(), {}); EvmoneUtility evmoneUtil( @@ -67,9 +66,9 @@ DEFINE_PROTO_FUZZER(Contract const& _input) if (!EvmoneUtility::zeroWord(result.output_data, result.output_size)) { solidity::bytes res; - for (size_t i = 0; i < result.output_size; i++) + for (std::size_t i = 0; i < result.output_size; i++) res.push_back(result.output_data[i]); - cout << solidity::util::toHex(res) << endl; + std::cout << solidity::util::toHex(res) << std::endl; solAssert( false, "Proto ABIv2 fuzzer: ABIv2 coding failure found" diff --git a/test/tools/ossfuzz/const_opt_ossfuzz.cpp b/test/tools/ossfuzz/const_opt_ossfuzz.cpp index 0b799c956..84ad87e7f 100644 --- a/test/tools/ossfuzz/const_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/const_opt_ossfuzz.cpp @@ -18,8 +18,6 @@ #include -using namespace std; - // Prototype as we can't use the FuzzerInterface.h header. extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size); @@ -27,7 +25,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) { if (_size <= 250) { - string input(reinterpret_cast(_data), _size); + std::string input(reinterpret_cast(_data), _size); FuzzerUtil::testConstantOptimizer(input, /*quiet=*/true); } return 0; diff --git a/test/tools/ossfuzz/protoToAbiV2.cpp b/test/tools/ossfuzz/protoToAbiV2.cpp index af2e5ede1..1511390eb 100644 --- a/test/tools/ossfuzz/protoToAbiV2.cpp +++ b/test/tools/ossfuzz/protoToAbiV2.cpp @@ -50,14 +50,13 @@ BOOST_PP_REPEAT(32, USINGDECL, 0) /// Switch implementation that instantiates case statements for (un)signed /// Solidity integer types. #define SWITCHIMPL(sign) \ - ostringstream stream; \ + std::ostringstream stream; \ switch (_intWidth) \ { \ BOOST_PP_REPEAT(32, CASEIMPL, sign) \ } \ return stream.str(); -using namespace std; using namespace solidity::util; using namespace solidity::test::abiv2fuzzer; @@ -75,17 +74,17 @@ static V integerValue(unsigned _counter) return value; } -static string signedIntegerValue(unsigned _counter, unsigned _intWidth) +static std::string signedIntegerValue(unsigned _counter, unsigned _intWidth) { SWITCHIMPL(1) } -static string unsignedIntegerValue(unsigned _counter, unsigned _intWidth) +static std::string unsignedIntegerValue(unsigned _counter, unsigned _intWidth) { SWITCHIMPL(0) } -static string integerValue(unsigned _counter, unsigned _intWidth, bool _signed) +static std::string integerValue(unsigned _counter, unsigned _intWidth, bool _signed) { if (_signed) return signedIntegerValue(_counter, _intWidth); @@ -94,10 +93,10 @@ static string integerValue(unsigned _counter, unsigned _intWidth, bool _signed) } } -string ProtoConverter::getVarDecl( - string const& _type, - string const& _varName, - string const& _qualifier +std::string ProtoConverter::getVarDecl( + std::string const& _type, + std::string const& _varName, + std::string const& _qualifier ) { // One level of indentation for state variable declarations @@ -114,7 +113,7 @@ string ProtoConverter::getVarDecl( "\n"; } -pair ProtoConverter::visit(Type const& _type) +std::pair ProtoConverter::visit(Type const& _type) { switch (_type.type_oneof_case()) { @@ -123,11 +122,11 @@ pair ProtoConverter::visit(Type const& _type) case Type::kNvtype: return visit(_type.nvtype()); case Type::TYPE_ONEOF_NOT_SET: - return make_pair("", ""); + return std::make_pair("", ""); } } -pair ProtoConverter::visit(ValueType const& _type) +std::pair ProtoConverter::visit(ValueType const& _type) { switch (_type.value_type_oneof_case()) { @@ -140,11 +139,11 @@ pair ProtoConverter::visit(ValueType const& _type) case ValueType::kAdty: return visit(_type.adty()); case ValueType::VALUE_TYPE_ONEOF_NOT_SET: - return make_pair("", ""); + return std::make_pair("", ""); } } -pair ProtoConverter::visit(NonValueType const& _type) +std::pair ProtoConverter::visit(NonValueType const& _type) { switch (_type.nonvalue_type_oneof_case()) { @@ -154,56 +153,56 @@ pair ProtoConverter::visit(NonValueType const& _type) if (ValidityVisitor().visit(_type.arrtype())) return visit(_type.arrtype()); else - return make_pair("", ""); + return std::make_pair("", ""); case NonValueType::kStype: if (ValidityVisitor().visit(_type.stype())) return visit(_type.stype()); else - return make_pair("", ""); + return std::make_pair("", ""); case NonValueType::NONVALUE_TYPE_ONEOF_NOT_SET: - return make_pair("", ""); + return std::make_pair("", ""); } } -pair ProtoConverter::visit(BoolType const& _type) +std::pair ProtoConverter::visit(BoolType const& _type) { return processType(_type, true); } -pair ProtoConverter::visit(IntegerType const& _type) +std::pair ProtoConverter::visit(IntegerType const& _type) { return processType(_type, true); } -pair ProtoConverter::visit(FixedByteType const& _type) +std::pair ProtoConverter::visit(FixedByteType const& _type) { return processType(_type, true); } -pair ProtoConverter::visit(AddressType const& _type) +std::pair ProtoConverter::visit(AddressType const& _type) { return processType(_type, true); } -pair ProtoConverter::visit(DynamicByteArrayType const& _type) +std::pair ProtoConverter::visit(DynamicByteArrayType const& _type) { return processType(_type, false); } -pair ProtoConverter::visit(ArrayType const& _type) +std::pair ProtoConverter::visit(ArrayType const& _type) { return processType(_type, false); } -pair ProtoConverter::visit(StructType const& _type) +std::pair ProtoConverter::visit(StructType const& _type) { return processType(_type, false); } template -pair ProtoConverter::processType(T const& _type, bool _isValueType) +std::pair ProtoConverter::processType(T const& _type, bool _isValueType) { - ostringstream local, global; + std::ostringstream local, global; auto [varName, paramName] = newVarNames(getNextVarCounter(), m_isStateVar); // Add variable name to the argument list of coder function call @@ -212,7 +211,7 @@ pair ProtoConverter::processType(T const& _type, bool _isValueTy else m_argsCoder << ", " << varName; - string location{}; + std::string location{}; if (!m_isStateVar && !_isValueType) location = "memory"; @@ -230,24 +229,24 @@ pair ProtoConverter::processType(T const& _type, bool _isValueTy local << assignCheckBuffers.second; m_structCounter += m_numStructsAdded; - return make_pair(global.str(), local.str()); + return std::make_pair(global.str(), local.str()); } template -pair ProtoConverter::varDecl( - string const& _varName, - string const& _paramName, +std::pair ProtoConverter::varDecl( + std::string const& _varName, + std::string const& _paramName, T _type, bool _isValueType, - string const& _location + std::string const& _location ) { - ostringstream local, global; + std::ostringstream local, global; TypeVisitor tVisitor(m_structCounter); - string typeStr = tVisitor.visit(_type); + std::string typeStr = tVisitor.visit(_type); if (typeStr.empty()) - return make_pair("", ""); + return std::make_pair("", ""); // Append struct defs global << tVisitor.structDef(); @@ -292,17 +291,17 @@ pair ProtoConverter::varDecl( if (tVisitor.isLastDynParamRightPadded()) m_isLastDynParamRightPadded = true; - return make_pair(global.str(), local.str()); + return std::make_pair(global.str(), local.str()); } template -pair ProtoConverter::assignChecker( - string const& _varName, - string const& _paramName, +std::pair ProtoConverter::assignChecker( + std::string const& _varName, + std::string const& _paramName, T _type ) { - ostringstream local; + std::ostringstream local; AssignCheckVisitor acVisitor( _varName, _paramName, @@ -311,7 +310,7 @@ pair ProtoConverter::assignChecker( m_counter, m_structCounter ); - pair assignCheckStrPair = acVisitor.visit(_type); + std::pair assignCheckStrPair = acVisitor.visit(_type); m_returnValue += acVisitor.errorStmts(); m_counter += acVisitor.counted(); @@ -325,10 +324,10 @@ pair ProtoConverter::assignChecker( // Therefore, we buffer their assignments and // render them in function scope later. local << assignCheckStrPair.first; - return make_pair("", local.str()); + return std::make_pair("", local.str()); } -pair ProtoConverter::visit(VarDecl const& _x) +std::pair ProtoConverter::visit(VarDecl const& _x) { return visit(_x.type()); } @@ -375,11 +374,11 @@ void ProtoConverter::appendTypedParams( void ProtoConverter::appendTypes( bool _isValueType, - string const& _typeString, + std::string const& _typeString, Delimiter _delimiter ) { - string qualifiedTypeString = ( + std::string qualifiedTypeString = ( _isValueType ? _typeString : _typeString + " memory" @@ -392,11 +391,11 @@ void ProtoConverter::appendTypes( void ProtoConverter::appendTypedReturn( bool _isValueType, - string const& _typeString, + std::string const& _typeString, Delimiter _delimiter ) { - string qualifiedTypeString = ( + std::string qualifiedTypeString = ( _isValueType ? _typeString : _typeString + " memory" @@ -404,7 +403,7 @@ void ProtoConverter::appendTypedReturn( m_typedReturn << Whiskers(R"( )") ("delimiter", delimiterToString(_delimiter)) ("type", qualifiedTypeString) - ("varName", "lv_" + to_string(m_varCounter - 1)) + ("varName", "lv_" + std::to_string(m_varCounter - 1)) .render(); } @@ -467,16 +466,16 @@ std::string ProtoConverter::typedParametersAsString(CalleeType _calleeType) return m_typedParamsPublic.str(); case CalleeType::EXTERNAL: { - ostringstream typedParamsExternal; + std::ostringstream typedParamsExternal; for (auto const& i: m_externalParamsRep) { - Delimiter del = get<0>(i); - bool valueType = get<1>(i); - string typeString = get<2>(i); - string varName = get<3>(i); + Delimiter del = std::get<0>(i); + bool valueType = std::get<1>(i); + std::string typeString = std::get<2>(i); + std::string varName = std::get<3>(i); bool isCalldata = randomBool(/*probability=*/0.5); - string location = (isCalldata ? "calldata" : "memory"); - string qualifiedTypeString = (valueType ? typeString : typeString + " " + location); + std::string location = (isCalldata ? "calldata" : "memory"); + std::string qualifiedTypeString = (valueType ? typeString : typeString + " " + location); typedParamsExternal << Whiskers(R"( )") ("delimiter", delimiterToString(del)) ("type", qualifiedTypeString) @@ -488,17 +487,17 @@ std::string ProtoConverter::typedParametersAsString(CalleeType _calleeType) } } -string ProtoConverter::visit(TestFunction const& _x, string const& _storageVarDefs) +std::string ProtoConverter::visit(TestFunction const& _x, std::string const& _storageVarDefs) { // TODO: Support more than one but less than N local variables auto localVarBuffers = visit(_x.local_vars()); - string structTypeDecl = localVarBuffers.first; - string localVarDefs = localVarBuffers.second; + std::string structTypeDecl = localVarBuffers.first; + std::string localVarDefs = localVarBuffers.second; - ostringstream testBuffer; + std::ostringstream testBuffer; - string testFunction = Whiskers(R"( + std::string testFunction = Whiskers(R"( function test() public returns (uint) { return test_calldata_coding(); return test_returndata_coding(); @@ -507,8 +506,8 @@ string ProtoConverter::visit(TestFunction const& _x, string const& _storageVarDe ("returndata", m_test == Contract_Test::Contract_Test_RETURNDATA_CODER) .render(); - string functionDeclCalldata = "function test_calldata_coding() internal returns (uint)"; - string functionDeclReturndata = "function test_returndata_coding() internal returns (uint)"; + std::string functionDeclCalldata = "function test_calldata_coding() internal returns (uint)"; + std::string functionDeclReturndata = "function test_returndata_coding() internal returns (uint)"; testBuffer << Whiskers(R"( @@ -551,7 +550,7 @@ string ProtoConverter::visit(TestFunction const& _x, string const& _storageVarDe return testBuffer.str(); } -string ProtoConverter::testCallDataFunction(unsigned _invalidLength) +std::string ProtoConverter::testCallDataFunction(unsigned _invalidLength) { return Whiskers(R"( uint returnVal = this.coder_calldata_public(); @@ -592,7 +591,7 @@ string ProtoConverter::testCallDataFunction(unsigned _invalidLength) .render(); } -string ProtoConverter::testReturnDataFunction() +std::string ProtoConverter::testReturnDataFunction() { return Whiskers(R"( @@ -607,9 +606,9 @@ string ProtoConverter::testReturnDataFunction() .render(); } -string ProtoConverter::calldataHelperFunctions() +std::string ProtoConverter::calldataHelperFunctions() { - stringstream calldataHelperFuncs; + std::stringstream calldataHelperFuncs; calldataHelperFuncs << R"( /// Accepts function selector, correct argument encoding, and length of /// invalid encoding and returns the correct and incorrect abi encoding @@ -676,12 +675,12 @@ string ProtoConverter::calldataHelperFunctions() })"; /// These are indirections to test memory-calldata codings more robustly. - stringstream indirections; + std::stringstream indirections; unsigned numIndirections = randomNumberOneToN(s_maxIndirections); for (unsigned i = 1; i <= numIndirections; i++) { bool finalIndirection = i == numIndirections; - string mutability = (finalIndirection ? "pure" : "view"); + std::string mutability = (finalIndirection ? "pure" : "view"); indirections << Whiskers(R"( function coder_calldata_external_i() external returns (uint) { @@ -692,12 +691,12 @@ string ProtoConverter::calldataHelperFunctions() } )") - ("N", to_string(i)) + ("N", std::to_string(i)) ("parameters", typedParametersAsString(CalleeType::EXTERNAL)) ("mutability", mutability) ("finalIndirection", finalIndirection) ("equality_checks", equalityChecksAsString()) - ("NPlusOne", to_string(i + 1)) + ("NPlusOne", std::to_string(i + 1)) ("untyped_parameters", m_untypedParamsExternal.str()) .render(); } @@ -726,9 +725,9 @@ string ProtoConverter::calldataHelperFunctions() return calldataHelperFuncs.str(); } -string ProtoConverter::commonHelperFunctions() +std::string ProtoConverter::commonHelperFunctions() { - stringstream helperFuncs; + std::stringstream helperFuncs; helperFuncs << R"( /// Compares bytes, returning true if they are equal and false otherwise. function bytesCompare(bytes memory a, bytes memory b) internal pure returns (bool) { @@ -746,7 +745,7 @@ string ProtoConverter::commonHelperFunctions() void ProtoConverter::visit(Contract const& _x) { - string pragmas = R"(pragma solidity >=0.0; + std::string pragmas = R"(pragma solidity >=0.0; pragma experimental ABIEncoderV2;)"; // Record test spec @@ -754,10 +753,10 @@ pragma experimental ABIEncoderV2;)"; // TODO: Support more than one but less than N state variables auto storageBuffers = visit(_x.state_vars()); - string storageVarDecls = storageBuffers.first; - string storageVarDefs = storageBuffers.second; + std::string storageVarDecls = storageBuffers.first; + std::string storageVarDefs = storageBuffers.second; m_isStateVar = false; - string testFunction = visit(_x.testfunction(), storageVarDefs); + std::string testFunction = visit(_x.testfunction(), storageVarDefs); /* Structure of contract body * - Storage variable declarations * - Struct definitions @@ -767,7 +766,7 @@ pragma experimental ABIEncoderV2;)"; * - Test code proper (calls public and external functions) * - Helper functions */ - ostringstream contractBody; + std::ostringstream contractBody; contractBody << storageVarDecls << testFunction << commonHelperFunctions(); @@ -782,32 +781,32 @@ pragma experimental ABIEncoderV2;)"; .render(); } -string ProtoConverter::isabelleTypeString() const +std::string ProtoConverter::isabelleTypeString() const { - string typeString = m_isabelleTypeString.str(); + std::string typeString = m_isabelleTypeString.str(); if (!typeString.empty()) return "(" + typeString + ")"; else return typeString; } -string ProtoConverter::isabelleValueString() const +std::string ProtoConverter::isabelleValueString() const { - string valueString = m_isabelleValueString.str(); + std::string valueString = m_isabelleValueString.str(); if (!valueString.empty()) return "(" + valueString + ")"; else return valueString; } -string ProtoConverter::contractToString(Contract const& _input) +std::string ProtoConverter::contractToString(Contract const& _input) { visit(_input); return m_output.str(); } /// Type visitor -void TypeVisitor::StructTupleString::addTypeStringToTuple(string& _typeString) +void TypeVisitor::StructTupleString::addTypeStringToTuple(std::string& _typeString) { index++; if (index > 1) @@ -815,51 +814,51 @@ void TypeVisitor::StructTupleString::addTypeStringToTuple(string& _typeString) stream << _typeString; } -void TypeVisitor::StructTupleString::addArrayBracketToType(string& _arrayBracket) +void TypeVisitor::StructTupleString::addArrayBracketToType(std::string& _arrayBracket) { stream << _arrayBracket; } -string TypeVisitor::visit(BoolType const&) +std::string TypeVisitor::visit(BoolType const&) { m_baseType = "bool"; m_structTupleString.addTypeStringToTuple(m_baseType); return m_baseType; } -string TypeVisitor::visit(IntegerType const& _type) +std::string TypeVisitor::visit(IntegerType const& _type) { m_baseType = getIntTypeAsString(_type); m_structTupleString.addTypeStringToTuple(m_baseType); return m_baseType; } -string TypeVisitor::visit(FixedByteType const& _type) +std::string TypeVisitor::visit(FixedByteType const& _type) { m_baseType = getFixedByteTypeAsString(_type); m_structTupleString.addTypeStringToTuple(m_baseType); return m_baseType; } -string TypeVisitor::visit(AddressType const&) +std::string TypeVisitor::visit(AddressType const&) { m_baseType = "address"; m_structTupleString.addTypeStringToTuple(m_baseType); return m_baseType; } -string TypeVisitor::visit(ArrayType const& _type) +std::string TypeVisitor::visit(ArrayType const& _type) { if (!ValidityVisitor().visit(_type)) return ""; - string baseType = visit(_type.t()); + std::string baseType = visit(_type.t()); solAssert(!baseType.empty(), ""); - string arrayBracket = _type.is_static() ? - string("[") + - to_string(getStaticArrayLengthFromFuzz(_type.length())) + - string("]") : - string("[]"); + std::string arrayBracket = _type.is_static() ? + std::string("[") + + std::to_string(getStaticArrayLengthFromFuzz(_type.length())) + + std::string("]") : + std::string("[]"); m_baseType += arrayBracket; m_structTupleString.addArrayBracketToType(arrayBracket); @@ -872,7 +871,7 @@ string TypeVisitor::visit(ArrayType const& _type) return baseType + arrayBracket; } -string TypeVisitor::visit(DynamicByteArrayType const&) +std::string TypeVisitor::visit(DynamicByteArrayType const&) { m_isLastDynParamRightPadded = true; m_baseType = "bytes"; @@ -893,10 +892,10 @@ void TypeVisitor::structDefinition(StructType const& _type) m_structFieldCounter = 0; // Commence struct declaration - string structDef = lineString( + std::string structDef = lineString( "struct " + - string(s_structNamePrefix) + - to_string(m_structCounter) + + std::string(s_structNamePrefix) + + std::to_string(m_structCounter) + " {" ); // Start tuple of types with parenthesis @@ -905,7 +904,7 @@ void TypeVisitor::structDefinition(StructType const& _type) m_indentation++; for (auto const& t: _type.t()) { - string type{}; + std::string type{}; if (!ValidityVisitor().visit(t)) continue; @@ -920,10 +919,10 @@ void TypeVisitor::structDefinition(StructType const& _type) structDef += lineString( Whiskers(R"( ;)") ("type", type) - ("member", "m" + to_string(m_structFieldCounter++)) + ("member", "m" + std::to_string(m_structFieldCounter++)) .render() ); - string isabelleTypeStr = tVisitor.isabelleTypeString(); + std::string isabelleTypeStr = tVisitor.isabelleTypeString(); m_structTupleString.addTypeStringToTuple(isabelleTypeStr); } m_indentation--; @@ -936,7 +935,7 @@ void TypeVisitor::structDefinition(StructType const& _type) m_structFieldCounter = wasFieldCounter; } -string TypeVisitor::visit(StructType const& _type) +std::string TypeVisitor::visit(StructType const& _type) { if (ValidityVisitor().visit(_type)) { @@ -945,7 +944,7 @@ string TypeVisitor::visit(StructType const& _type) // Set last dyn param if struct contains a dyn param e.g., bytes, array etc. m_isLastDynParamRightPadded = DynParamVisitor().visit(_type); // If top-level struct is a non-empty struct, assign the name S - m_baseType = s_structTypeName + to_string(m_structStartCounter); + m_baseType = s_structTypeName + std::to_string(m_structStartCounter); } else m_baseType = {}; @@ -954,7 +953,7 @@ string TypeVisitor::visit(StructType const& _type) } /// AssignCheckVisitor implementation -void AssignCheckVisitor::ValueStream::appendValue(string& _value) +void AssignCheckVisitor::ValueStream::appendValue(std::string& _value) { solAssert(!_value.empty(), "Abiv2 fuzzer: Empty value"); index++; @@ -963,77 +962,77 @@ void AssignCheckVisitor::ValueStream::appendValue(string& _value) stream << _value; } -pair AssignCheckVisitor::visit(BoolType const& _type) +std::pair AssignCheckVisitor::visit(BoolType const& _type) { - string value = ValueGetterVisitor(counter()).visit(_type); + std::string value = ValueGetterVisitor(counter()).visit(_type); if (!m_forcedVisit) m_valueStream.appendValue(value); return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } -pair AssignCheckVisitor::visit(IntegerType const& _type) +std::pair AssignCheckVisitor::visit(IntegerType const& _type) { - string value = ValueGetterVisitor(counter()).visit(_type); + std::string value = ValueGetterVisitor(counter()).visit(_type); if (!m_forcedVisit) m_valueStream.appendValue(value); return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } -pair AssignCheckVisitor::visit(FixedByteType const& _type) +std::pair AssignCheckVisitor::visit(FixedByteType const& _type) { - string value = ValueGetterVisitor(counter()).visit(_type); + std::string value = ValueGetterVisitor(counter()).visit(_type); if (!m_forcedVisit) { - string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value); + std::string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value); m_valueStream.appendValue(isabelleValue); } return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } -pair AssignCheckVisitor::visit(AddressType const& _type) +std::pair AssignCheckVisitor::visit(AddressType const& _type) { - string value = ValueGetterVisitor(counter()).visit(_type); + std::string value = ValueGetterVisitor(counter()).visit(_type); if (!m_forcedVisit) { - string isabelleValue = ValueGetterVisitor{}.isabelleAddressValueAsString(value); + std::string isabelleValue = ValueGetterVisitor{}.isabelleAddressValueAsString(value); m_valueStream.appendValue(isabelleValue); } return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } -pair AssignCheckVisitor::visit(DynamicByteArrayType const& _type) +std::pair AssignCheckVisitor::visit(DynamicByteArrayType const& _type) { - string value = ValueGetterVisitor(counter()).visit(_type); + std::string value = ValueGetterVisitor(counter()).visit(_type); if (!m_forcedVisit) { - string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value); + std::string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value); m_valueStream.appendValue(isabelleValue); } DataType dataType = DataType::BYTES; return assignAndCheckStringPair(m_varName, m_paramName, value, value, dataType); } -pair AssignCheckVisitor::visit(ArrayType const& _type) +std::pair AssignCheckVisitor::visit(ArrayType const& _type) { if (!ValidityVisitor().visit(_type)) - return make_pair("", ""); + return std::make_pair("", ""); // Obtain type of array to be resized and initialized - string typeStr{}; + std::string typeStr{}; unsigned wasStructCounter = m_structCounter; TypeVisitor tVisitor(m_structCounter); typeStr = tVisitor.visit(_type); - pair resizeBuffer; - string lengthStr; + std::pair resizeBuffer; + std::string lengthStr; unsigned length; // Resize dynamic arrays if (!_type.is_static()) { length = getDynArrayLengthFromFuzz(_type.length(), counter()); - lengthStr = to_string(length); + lengthStr = std::to_string(length); if (m_stateVar) { // Dynamic storage arrays are resized via the empty push() operation @@ -1048,7 +1047,7 @@ pair AssignCheckVisitor::visit(ArrayType const& _type) else { // Resizing memory arrays via the new operator - string resizeOp = Whiskers(R"(new ())") + std::string resizeOp = Whiskers(R"(new ())") ("fullTypeStr", typeStr) ("length", lengthStr) .render(); @@ -1064,22 +1063,22 @@ pair AssignCheckVisitor::visit(ArrayType const& _type) else { length = getStaticArrayLengthFromFuzz(_type.length()); - lengthStr = to_string(length); + lengthStr = std::to_string(length); // Add check on length resizeBuffer.second = checkString(m_paramName + ".length", lengthStr, DataType::VALUE); } // Add assignCheckBuffer and check statements - pair assignCheckBuffer; - string wasVarName = m_varName; - string wasParamName = m_paramName; + std::pair assignCheckBuffer; + std::string wasVarName = m_varName; + std::string wasParamName = m_paramName; if (!m_forcedVisit) m_valueStream.startArray(); for (unsigned i = 0; i < length; i++) { - m_varName = wasVarName + "[" + to_string(i) + "]"; - m_paramName = wasParamName + "[" + to_string(i) + "]"; - pair assign = visit(_type.t()); + m_varName = wasVarName + "[" + std::to_string(i) + "]"; + m_paramName = wasParamName + "[" + std::to_string(i) + "]"; + std::pair assign = visit(_type.t()); assignCheckBuffer.first += assign.first; assignCheckBuffer.second += assign.second; if (i < length - 1) @@ -1102,33 +1101,33 @@ pair AssignCheckVisitor::visit(ArrayType const& _type) m_paramName = wasParamName; // Compose resize and initialization assignment and check - return make_pair( + return std::make_pair( resizeBuffer.first + assignCheckBuffer.first, resizeBuffer.second + assignCheckBuffer.second ); } -pair AssignCheckVisitor::visit(StructType const& _type) +std::pair AssignCheckVisitor::visit(StructType const& _type) { if (!ValidityVisitor().visit(_type)) - return make_pair("", ""); + return std::make_pair("", ""); - pair assignCheckBuffer; + std::pair assignCheckBuffer; unsigned i = 0; // Increment struct counter m_structCounter++; - string wasVarName = m_varName; - string wasParamName = m_paramName; + std::string wasVarName = m_varName; + std::string wasParamName = m_paramName; if (!m_forcedVisit) m_valueStream.startStruct(); for (auto const& t: _type.t()) { - m_varName = wasVarName + ".m" + to_string(i); - m_paramName = wasParamName + ".m" + to_string(i); - pair assign = visit(t); + m_varName = wasVarName + ".m" + std::to_string(i); + m_paramName = wasParamName + ".m" + std::to_string(i); + std::pair assign = visit(t); // If type is not well formed continue without // updating state. if (assign.first.empty() && assign.second.empty()) @@ -1144,29 +1143,29 @@ pair AssignCheckVisitor::visit(StructType const& _type) return assignCheckBuffer; } -pair AssignCheckVisitor::assignAndCheckStringPair( - string const& _varRef, - string const& _checkRef, - string const& _assignValue, - string const& _checkValue, +std::pair AssignCheckVisitor::assignAndCheckStringPair( + std::string const& _varRef, + std::string const& _checkRef, + std::string const& _assignValue, + std::string const& _checkValue, DataType _type ) { - return make_pair(assignString(_varRef, _assignValue), checkString(_checkRef, _checkValue, _type)); + return std::make_pair(assignString(_varRef, _assignValue), checkString(_checkRef, _checkValue, _type)); } -string AssignCheckVisitor::assignString(string const& _ref, string const& _value) +std::string AssignCheckVisitor::assignString(std::string const& _ref, std::string const& _value) { - string assignStmt = Whiskers(R"( = ;)") + std::string assignStmt = Whiskers(R"( = ;)") ("ref", _ref) ("value", _value) .render(); return indentation() + assignStmt + "\n"; } -string AssignCheckVisitor::checkString(string const& _ref, string const& _value, DataType _type) +std::string AssignCheckVisitor::checkString(std::string const& _ref, std::string const& _value, DataType _type) { - string checkPred; + std::string checkPred; switch (_type) { case DataType::BYTES: @@ -1184,25 +1183,25 @@ string AssignCheckVisitor::checkString(string const& _ref, string const& _value, case DataType::ARRAY: solUnimplemented("Proto ABIv2 fuzzer: Invalid data type."); } - string checkStmt = Whiskers(R"(if () return ;)") + std::string checkStmt = Whiskers(R"(if () return ;)") ("checkPred", checkPred) - ("errCode", to_string(m_errorCode++)) + ("errCode", std::to_string(m_errorCode++)) .render(); return indentation() + checkStmt + "\n"; } /// ValueGetterVisitor -string ValueGetterVisitor::visit(BoolType const&) +std::string ValueGetterVisitor::visit(BoolType const&) { return counter() % 2 ? "true" : "false"; } -string ValueGetterVisitor::visit(IntegerType const& _type) +std::string ValueGetterVisitor::visit(IntegerType const& _type) { return integerValue(counter(), getIntWidth(_type), _type.is_signed()); } -string ValueGetterVisitor::visit(FixedByteType const& _type) +std::string ValueGetterVisitor::visit(FixedByteType const& _type) { return fixedByteValueAsString( getFixedByteWidth(_type), @@ -1210,12 +1209,12 @@ string ValueGetterVisitor::visit(FixedByteType const& _type) ); } -string ValueGetterVisitor::visit(AddressType const&) +std::string ValueGetterVisitor::visit(AddressType const&) { return addressValueAsString(counter()); } -string ValueGetterVisitor::visit(DynamicByteArrayType const&) +std::string ValueGetterVisitor::visit(DynamicByteArrayType const&) { return bytesArrayValueAsString( counter(), @@ -1331,7 +1330,7 @@ std::string ValueGetterVisitor::variableLengthValueAsString( unsigned numBytesRemaining = _numBytes; // Stores the literal - string output{}; + std::string output{}; // If requested value is shorter than or exactly 32 bytes, // the literal is the return value of hexValueAsString. if (numBytesRemaining <= 32) @@ -1350,7 +1349,7 @@ std::string ValueGetterVisitor::variableLengthValueAsString( // update number of bytes to be appended. // Stores the cached literal that saves us // (expensive) calls to keccak256. - string cachedString = hexValueAsString( + std::string cachedString = hexValueAsString( /*numBytes=*/32, _counter, _isHexLiteral, @@ -1398,7 +1397,7 @@ std::string ValueGetterVisitor::variableLengthValueAsString( .render(); } -string ValueGetterVisitor::bytesArrayValueAsString(unsigned _counter, bool _isHexLiteral) +std::string ValueGetterVisitor::bytesArrayValueAsString(unsigned _counter, bool _isHexLiteral) { return variableLengthValueAsString( getVarLength(_counter), diff --git a/test/tools/ossfuzz/protoToSol.cpp b/test/tools/ossfuzz/protoToSol.cpp index 73ed34b0d..f8a60c4a0 100644 --- a/test/tools/ossfuzz/protoToSol.cpp +++ b/test/tools/ossfuzz/protoToSol.cpp @@ -26,30 +26,29 @@ using namespace solidity::test::solprotofuzzer; using namespace solidity::util; -using namespace std; -string ProtoConverter::protoToSolidity(Program const& _p) +std::string ProtoConverter::protoToSolidity(Program const& _p) { // Create random number generator with fuzzer supplied // seed. - m_randomGen = make_shared(_p.seed()); + m_randomGen = std::make_shared(_p.seed()); return visit(_p); } -pair ProtoConverter::generateTestCase(TestContract const& _testContract) +std::pair ProtoConverter::generateTestCase(TestContract const& _testContract) { - ostringstream testCode; - string usingLibDecl; + std::ostringstream testCode; + std::string usingLibDecl; switch (_testContract.type()) { case TestContract::LIBRARY: { m_libraryTest = true; auto testTuple = pseudoRandomLibraryTest(); - m_libraryName = get<0>(testTuple); + m_libraryName = std::get<0>(testTuple); Whiskers u(R"(using for uint;)"); u("ind", "\t"); - u("libraryName", get<0>(testTuple)); + u("libraryName", std::get<0>(testTuple)); usingLibDecl = u.render(); Whiskers test(R"()"); test("endl", "\n"); @@ -57,8 +56,8 @@ pair ProtoConverter::generateTestCase(TestContract const& _testC test("varDecl", "uint x;"); Whiskers ifStmt(R"(if ()return 1;)"); Whiskers ifCond(R"(x.() != )"); - ifCond("testFunction", get<1>(testTuple)); - ifCond("expectedOutput", get<2>(testTuple)); + ifCond("testFunction", std::get<1>(testTuple)); + ifCond("expectedOutput", std::get<2>(testTuple)); ifStmt("cond", ifCond.render()); ifStmt("endl", "\n"); ifStmt("ind", "\t\t\t"); @@ -77,8 +76,8 @@ pair ProtoConverter::generateTestCase(TestContract const& _testC // running into stack too deep errors if (contractVarIndex >= s_maxVars) break; - string contractName = testTuple.first; - string contractVarName = "tc" + to_string(contractVarIndex); + std::string contractName = testTuple.first; + std::string contractVarName = "tc" + std::to_string(contractVarIndex); Whiskers init(R"( = new ();)"); init("endl", "\n"); init("ind", "\t\t"); @@ -98,7 +97,7 @@ pair ProtoConverter::generateTestCase(TestContract const& _testC ifStmt("endl", "\n"); ifStmt("cond", ifCond.render()); ifStmt("ind", "\t\t\t"); - ifStmt("errorCode", to_string(errorCode)); + ifStmt("errorCode", std::to_string(errorCode)); tc("ifStmt", ifStmt.render()); testCode << tc.render(); errorCode++; @@ -113,10 +112,10 @@ pair ProtoConverter::generateTestCase(TestContract const& _testC return {usingLibDecl, testCode.str()}; } -string ProtoConverter::visit(TestContract const& _testContract) +std::string ProtoConverter::visit(TestContract const& _testContract) { - string testCode; - string usingLibDecl; + std::string testCode; + std::string usingLibDecl; m_libraryTest = false; // Simply return valid uint (zero) if there are @@ -143,15 +142,15 @@ bool ProtoConverter::libraryTest() const return m_libraryTest; } -string ProtoConverter::libraryName() const +std::string ProtoConverter::libraryName() const { return m_libraryName; } -string ProtoConverter::visit(Program const& _p) +std::string ProtoConverter::visit(Program const& _p) { - ostringstream program; - ostringstream contracts; + std::ostringstream program; + std::ostringstream contracts; for (auto &contract: _p.contracts()) contracts << visit(contract); @@ -163,7 +162,7 @@ string ProtoConverter::visit(Program const& _p) return p.render(); } -string ProtoConverter::visit(ContractType const& _contractType) +std::string ProtoConverter::visit(ContractType const& _contractType) { switch (_contractType.contract_type_oneof_case()) { @@ -178,25 +177,25 @@ string ProtoConverter::visit(ContractType const& _contractType) } } -string ProtoConverter::visit(Contract const& _contract) +std::string ProtoConverter::visit(Contract const& _contract) { openProgramScope(&_contract); return ""; } -string ProtoConverter::visit(Interface const& _interface) +std::string ProtoConverter::visit(Interface const& _interface) { openProgramScope(&_interface); return ""; } -string ProtoConverter::visit(Library const& _library) +std::string ProtoConverter::visit(Library const& _library) { openProgramScope(&_library); return ""; } -tuple ProtoConverter::pseudoRandomLibraryTest() +std::tuple ProtoConverter::pseudoRandomLibraryTest() { solAssert(m_libraryTests.size() > 0, "Sol proto fuzzer: No library tests found"); unsigned index = randomNumber() % m_libraryTests.size(); @@ -205,18 +204,18 @@ tuple ProtoConverter::pseudoRandomLibraryTest() void ProtoConverter::openProgramScope(CIL _program) { - string programNamePrefix; - if (holds_alternative(_program)) + std::string programNamePrefix; + if (std::holds_alternative(_program)) programNamePrefix = "C"; - else if (holds_alternative(_program)) + else if (std::holds_alternative(_program)) programNamePrefix = "I"; else programNamePrefix = "L"; - string programName = programNamePrefix + to_string(m_programNumericSuffix++); + std::string programName = programNamePrefix + std::to_string(m_programNumericSuffix++); m_programNameMap.emplace(_program, programName); } -string ProtoConverter::programName(CIL _program) +std::string ProtoConverter::programName(CIL _program) { solAssert(m_programNameMap.count(_program), "Sol proto fuzzer: Unregistered program"); return m_programNameMap[_program]; diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 1ba0d599d..8822666c8 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -32,14 +32,13 @@ #include -using namespace std; using namespace solidity::yul::test::yul_fuzzer; using namespace solidity::yul::test; using namespace solidity::langutil; using namespace solidity::util; using namespace solidity; -string ProtoConverter::dictionaryToken(HexPrefix _p) +std::string ProtoConverter::dictionaryToken(HexPrefix _p) { std::string token; // If dictionary constant is requested while converting @@ -57,9 +56,9 @@ string ProtoConverter::dictionaryToken(HexPrefix _p) return _p == HexPrefix::Add ? "0x" + token : token; } -string ProtoConverter::createHex(string const& _hexBytes) +std::string ProtoConverter::createHex(std::string const& _hexBytes) { - string tmp{_hexBytes}; + std::string tmp{_hexBytes}; if (!tmp.empty()) { ranges::actions::remove_if(tmp, [=](char c) -> bool { @@ -79,9 +78,9 @@ string ProtoConverter::createHex(string const& _hexBytes) return tmp; } -string ProtoConverter::createAlphaNum(string const& _strBytes) +std::string ProtoConverter::createAlphaNum(std::string const& _strBytes) { - string tmp{_strBytes}; + std::string tmp{_strBytes}; if (!tmp.empty()) { ranges::actions::remove_if(tmp, [=](char c) -> bool { @@ -123,12 +122,12 @@ EVMVersion ProtoConverter::evmVersionMapping(Program_Version const& _ver) } } -string ProtoConverter::visit(Literal const& _x) +std::string ProtoConverter::visit(Literal const& _x) { switch (_x.literal_oneof_case()) { case Literal::kIntval: - return to_string(_x.intval()); + return std::to_string(_x.intval()); case Literal::kHexval: return "0x" + createHex(_x.hexval()); case Literal::kStrval: @@ -238,7 +237,7 @@ void ProtoConverter::visit(Expression const& _x) case Expression::kFuncExpr: if (auto v = functionExists(NumFunctionReturns::Single); v.has_value()) { - string functionName = v.value(); + std::string functionName = v.value(); visit(_x.func_expr(), functionName, true); } else @@ -359,11 +358,11 @@ void ProtoConverter::visit(BinaryOp const& _x) { m_output << "mod("; visit(_x.left()); - m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxMemory - s_maxSize) << ")"; m_output << ","; m_output << "mod("; visit(_x.right()); - m_output << ", " << to_string(s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxSize) << ")"; } else { @@ -374,7 +373,7 @@ void ProtoConverter::visit(BinaryOp const& _x) m_output << ")"; } -void ProtoConverter::scopeVariables(vector const& _varNames) +void ProtoConverter::scopeVariables(std::vector const& _varNames) { // If we are inside a for-init block, there are two places // where the visited vardecl may have been defined: @@ -443,7 +442,7 @@ void ProtoConverter::scopeVariables(vector const& _varNames) void ProtoConverter::visit(VarDecl const& _x) { - string varName = newVarName(); + std::string varName = newVarName(); m_output << "let " << varName << " := "; visit(_x.expr()); m_output << "\n"; @@ -453,14 +452,14 @@ void ProtoConverter::visit(VarDecl const& _x) void ProtoConverter::visit(MultiVarDecl const& _x) { m_output << "let "; - vector varNames; + std::vector varNames; // We support up to 4 variables in a single // declaration statement. unsigned numVars = _x.num_vars() % 3 + 2; - string delimiter; + std::string delimiter; for (unsigned i = 0; i < numVars; i++) { - string varName = newVarName(); + std::string varName = newVarName(); varNames.push_back(varName); m_output << delimiter << varName; if (i == 0) @@ -472,7 +471,7 @@ void ProtoConverter::visit(MultiVarDecl const& _x) void ProtoConverter::visit(TypedVarDecl const& _x) { - string varName = newVarName(); + std::string varName = newVarName(); m_output << "let " << varName; switch (_x.type()) { @@ -662,7 +661,7 @@ void ProtoConverter::visit(UnaryOp const& _x) { m_output << "mod("; visit(_x.operand()); - m_output << ", " << to_string(s_maxMemory - 32) << ")"; + m_output << ", " << std::to_string(s_maxMemory - 32) << ")"; } else visit(_x.operand()); @@ -844,20 +843,20 @@ void ProtoConverter::visit(CopyFunc const& _x) m_output << "("; m_output << "mod("; visit(_x.target()); - m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; if (type == CopyFunc::MEMORY) { m_output << "mod("; visit(_x.source()); - m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxMemory - s_maxSize) << ")"; } else visit(_x.source()); m_output << ", "; m_output << "mod("; visit(_x.size()); - m_output << ", " << to_string(s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxSize) << ")"; m_output << ")\n"; } @@ -869,13 +868,13 @@ void ProtoConverter::visit(ExtCodeCopy const& _x) m_output << ", "; m_output << "mod("; visit(_x.target()); - m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; visit(_x.source()); m_output << ", "; m_output << "mod("; visit(_x.size()); - m_output << ", " << to_string(s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxSize) << ")"; m_output << ")\n"; } @@ -884,11 +883,11 @@ void ProtoConverter::visit(LogFunc const& _x) auto visitPosAndSize = [&](LogFunc const& _y) { m_output << "mod("; visit(_y.pos()); - m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; m_output << "mod("; visit(_y.size()); - m_output << ", " << to_string(s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxSize) << ")"; }; switch (_x.num_topics()) @@ -984,7 +983,7 @@ void ProtoConverter::visitFunctionInputParams(FunctionCall const& _x, unsigned _ void ProtoConverter::convertFunctionCall( FunctionCall const& _x, - string const& _name, + std::string const& _name, unsigned _numInParams, bool _newLine ) @@ -996,10 +995,10 @@ void ProtoConverter::convertFunctionCall( m_output << "\n"; } -vector ProtoConverter::createVarDecls(unsigned _start, unsigned _end, bool _isAssignment) +std::vector ProtoConverter::createVarDecls(unsigned _start, unsigned _end, bool _isAssignment) { m_output << "let "; - vector varsVec = createVars(_start, _end); + std::vector varsVec = createVars(_start, _end); if (_isAssignment) m_output << " := "; else @@ -1007,7 +1006,7 @@ vector ProtoConverter::createVarDecls(unsigned _start, unsigned _end, bo return varsVec; } -optional ProtoConverter::functionExists(NumFunctionReturns _numReturns) +std::optional ProtoConverter::functionExists(NumFunctionReturns _numReturns) { for (auto const& item: m_functionSigMap) if (_numReturns == NumFunctionReturns::None || _numReturns == NumFunctionReturns::Single) @@ -1020,10 +1019,10 @@ optional ProtoConverter::functionExists(NumFunctionReturns _numReturns) if (item.second.second >= static_cast(_numReturns)) return item.first; } - return nullopt; + return std::nullopt; } -void ProtoConverter::visit(FunctionCall const& _x, string const& _functionName, bool _expression) +void ProtoConverter::visit(FunctionCall const& _x, std::string const& _functionName, bool _expression) { yulAssert(m_functionSigMap.count(_functionName), "Proto fuzzer: Invalid function."); auto ret = m_functionSigMap.at(_functionName); @@ -1038,7 +1037,7 @@ void ProtoConverter::visit(FunctionCall const& _x, string const& _functionName, else { yulAssert(numOutParams > 0, ""); - vector varsVec; + std::vector varsVec; if (!_expression) { // Obtain variable name suffix @@ -1096,19 +1095,19 @@ void ProtoConverter::visit(LowLevelCall const& _x) } m_output << "mod("; visit(_x.in()); - m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; m_output << "mod("; visit(_x.insize()); - m_output << ", " << to_string(s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxSize) << ")"; m_output << ", "; m_output << "mod("; visit(_x.out()); - m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; m_output << "mod("; visit(_x.outsize()); - m_output << ", " << to_string(s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxSize) << ")"; m_output << ")"; } @@ -1137,11 +1136,11 @@ void ProtoConverter::visit(Create const& _x) m_output << ", "; m_output << "mod("; visit(_x.position()); - m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; m_output << "mod("; visit(_x.size()); - m_output << ", " << to_string(s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxSize) << ")"; if (type == Create::CREATE2) { m_output << ", "; @@ -1183,7 +1182,7 @@ void ProtoConverter::visit(StoreFunc const& _x) { m_output << "mod("; visit(_x.loc()); - m_output << ", " << to_string(s_maxMemory) << ")"; + m_output << ", " << std::to_string(s_maxMemory) << ")"; } else if (storeType == StoreFunc::MSTORE) { @@ -1191,7 +1190,7 @@ void ProtoConverter::visit(StoreFunc const& _x) // upper bound on memory. m_output << "mod("; visit(_x.loc()); - m_output << ", " << to_string(s_maxMemory - 32) << ")"; + m_output << ", " << std::to_string(s_maxMemory - 32) << ")"; } m_output << ", "; @@ -1261,7 +1260,7 @@ void ProtoConverter::visit(BoundedForStmt const& _x) void ProtoConverter::visit(CaseStmt const& _x) { - string literal = visit(_x.case_lit()); + std::string literal = visit(_x.case_lit()); // u256 value of literal u256 literalVal; @@ -1278,7 +1277,7 @@ void ProtoConverter::visit(CaseStmt const& _x) // a case statement containing a case literal that has already been used in a // previous case statement. If the hash (u256 value) matches a previous hash, // then we simply don't create a new case statement. - string noDoubleQuoteStr; + std::string noDoubleQuoteStr; if (literal.size() > 2) { // Ensure that all characters in the string literal except the first @@ -1376,11 +1375,11 @@ void ProtoConverter::visit(RetRevStmt const& _x) m_output << "("; m_output << "mod("; visit(_x.pos()); - m_output << ", " << to_string(s_maxMemory - s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxMemory - s_maxSize) << ")"; m_output << ", "; m_output << "mod("; visit(_x.size()); - m_output << ", " << to_string(s_maxSize) << ")"; + m_output << ", " << std::to_string(s_maxSize) << ")"; m_output << ")\n"; } @@ -1527,14 +1526,14 @@ void ProtoConverter::openBlockScope() !m_funcVars.empty(), "Proto fuzzer: Invalid data structure" ); - m_funcVars.back().push_back(vector{}); + m_funcVars.back().push_back(std::vector{}); if (m_inForInitScope && m_forInitScopeExtEnabled) { yulAssert( !m_funcForLoopInitVars.empty(), "Proto fuzzer: Invalid data structure" ); - m_funcForLoopInitVars.back().push_back(vector{}); + m_funcForLoopInitVars.back().push_back(std::vector{}); } } else @@ -1545,13 +1544,13 @@ void ProtoConverter::openBlockScope() } } -void ProtoConverter::openFunctionScope(vector const& _funcParams) +void ProtoConverter::openFunctionScope(std::vector const& _funcParams) { - m_funcVars.push_back(vector>({_funcParams})); - m_funcForLoopInitVars.push_back(vector>({})); + m_funcVars.push_back(std::vector>({_funcParams})); + m_funcForLoopInitVars.push_back(std::vector>({})); } -void ProtoConverter::updateFunctionMaps(string const& _var) +void ProtoConverter::updateFunctionMaps(std::string const& _var) { size_t erased = m_functionSigMap.erase(_var); @@ -1609,7 +1608,7 @@ void ProtoConverter::closeFunctionScope() m_funcForLoopInitVars.pop_back(); } -void ProtoConverter::addVarsToScope(vector const& _vars) +void ProtoConverter::addVarsToScope(std::vector const& _vars) { // If we are in function definition, add the new vars to current function scope if (m_inFunctionDef) @@ -1706,12 +1705,12 @@ void ProtoConverter::visit(Block const& _x) closeBlockScope(); } -vector ProtoConverter::createVars(unsigned _startIdx, unsigned _endIdx) +std::vector ProtoConverter::createVars(unsigned _startIdx, unsigned _endIdx) { yulAssert(_endIdx > _startIdx, "Proto fuzzer: Variable indices not in range"); - string varsStr = suffixedVariableNameList("x_", _startIdx, _endIdx); + std::string varsStr = suffixedVariableNameList("x_", _startIdx, _endIdx); m_output << varsStr; - vector varsVec; + std::vector varsVec; boost::split( varsVec, varsStr, @@ -1740,14 +1739,14 @@ void ProtoConverter::registerFunction(FunctionDef const* _x) numReturns = NumFunctionReturns::Multiple; // Generate function name - string funcName = functionName(numReturns); + std::string funcName = functionName(numReturns); // Register function - auto ret = m_functionSigMap.emplace(make_pair(funcName, make_pair(numInParams, numOutParams))); + auto ret = m_functionSigMap.emplace(std::make_pair(funcName, std::make_pair(numInParams, numOutParams))); yulAssert(ret.second, "Proto fuzzer: Function already exists."); m_functions.push_back(funcName); m_scopeFuncs.back().push_back(funcName); - m_functionDefMap.emplace(make_pair(_x, funcName)); + m_functionDefMap.emplace(std::make_pair(_x, funcName)); } void ProtoConverter::fillFunctionCallInput(unsigned _numInParams) @@ -1760,7 +1759,7 @@ void ProtoConverter::fillFunctionCallInput(unsigned _numInParams) unsigned diceValue = counter() % 4; // Pseudo-randomly choose one of the first ten 32-byte // aligned slots. - string slot = to_string((counter() % 10) * 32); + std::string slot = std::to_string((counter() % 10) * 32); switch (diceValue) { case 0: @@ -1769,7 +1768,7 @@ void ProtoConverter::fillFunctionCallInput(unsigned _numInParams) case 1: { // Access memory within stipulated bounds - slot = "mod(" + dictionaryToken() + ", " + to_string(s_maxMemory - 32) + ")"; + slot = "mod(" + dictionaryToken() + ", " + std::to_string(s_maxMemory - 32) + ")"; m_output << "mload(" << slot << ")"; break; } @@ -1787,19 +1786,19 @@ void ProtoConverter::fillFunctionCallInput(unsigned _numInParams) } } -void ProtoConverter::saveFunctionCallOutput(vector const& _varsVec) +void ProtoConverter::saveFunctionCallOutput(std::vector const& _varsVec) { constexpr auto numSlots = 10; constexpr auto slotSize = 32; - for (string const& var: _varsVec) + for (std::string const& var: _varsVec) { // Flip a dice to choose whether to save output values // in storage or memory. unsigned diceThrow = counter() % (m_evmVersion.supportsTransientStorage() ? 3 : 2); // Pseudo-randomly choose one of the first ten 32-byte // aligned slots. - string slot = std::to_string((counter() % numSlots) * slotSize); + std::string slot = std::to_string((counter() % numSlots) * slotSize); if (diceThrow == 0) m_output << "sstore(" << slot << ", " << var << ")\n"; else if (diceThrow == 1) @@ -1816,12 +1815,12 @@ void ProtoConverter::saveFunctionCallOutput(vector const& _varsVec) } void ProtoConverter::createFunctionCall( - string const& _funcName, + std::string const& _funcName, unsigned _numInParams, unsigned _numOutParams ) { - vector varsVec{}; + std::vector varsVec{}; if (_numOutParams > 0) { unsigned startIdx = counter(); @@ -1864,16 +1863,16 @@ void ProtoConverter::createFunctionDefAndCall( // Obtain function name yulAssert(m_functionDefMap.count(&_x), "Proto fuzzer: Unregistered function"); - string funcName = m_functionDefMap.at(&_x); + std::string funcName = m_functionDefMap.at(&_x); - vector varsVec = {}; + std::vector varsVec = {}; m_output << "function " << funcName << "("; unsigned startIdx = counter(); if (_numInParams > 0) varsVec = createVars(startIdx, startIdx + _numInParams); m_output << ")"; - vector outVarsVec = {}; + std::vector outVarsVec = {}; // This creates -> x_n+1,...,x_r if (_numOutParams > 0) { @@ -1937,15 +1936,15 @@ void ProtoConverter::visit(LeaveStmt const&) m_output << "leave\n"; } -string ProtoConverter::getObjectIdentifier(unsigned _x) +std::string ProtoConverter::getObjectIdentifier(unsigned _x) { unsigned currentId = currentObjectId(); - string currentObjName = "object" + to_string(currentId); + std::string currentObjName = "object" + std::to_string(currentId); yulAssert( m_objectScope.count(currentObjName) && !m_objectScope.at(currentObjName).empty(), "Yul proto fuzzer: Error referencing object" ); - vector objectIdsInScope = m_objectScope.at(currentObjName); + std::vector objectIdsInScope = m_objectScope.at(currentObjName); return objectIdsInScope[_x % objectIdsInScope.size()]; } @@ -1979,8 +1978,8 @@ void ProtoConverter::visit(Object const& _x) void ProtoConverter::buildObjectScopeTree(Object const& _x) { // Identifies object being visited - string objectName = newObjectId(false); - vector node{objectName}; + std::string objectName = newObjectId(false); + std::vector node{objectName}; if (_x.has_data()) node.emplace_back(s_dataIdentifier); for (auto const& subObj: _x.sub_obj()) @@ -1988,12 +1987,12 @@ void ProtoConverter::buildObjectScopeTree(Object const& _x) // Identifies sub object whose numeric suffix is // m_objectId unsigned subObjectId = m_objectId; - string subObjectName = "object" + to_string(subObjectId); + std::string subObjectName = "object" + std::to_string(subObjectId); node.push_back(subObjectName); buildObjectScopeTree(subObj); // Add sub-object to object's ancestors yulAssert(m_objectScope.count(subObjectName), "Yul proto fuzzer: Invalid object hierarchy"); - for (string const& item: m_objectScope.at(subObjectName)) + for (std::string const& item: m_objectScope.at(subObjectName)) if (item != subObjectName) node.emplace_back(subObjectName + "." + item); } @@ -2033,13 +2032,13 @@ void ProtoConverter::visit(Program const& _x) } } -string ProtoConverter::programToString(Program const& _input) +std::string ProtoConverter::programToString(Program const& _input) { visit(_input); return m_output.str(); } -string ProtoConverter::functionTypeToString(NumFunctionReturns _type) +std::string ProtoConverter::functionTypeToString(NumFunctionReturns _type) { switch (_type) { diff --git a/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp b/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp index 9b0c97a22..bf370dd37 100644 --- a/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp +++ b/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp @@ -6,11 +6,10 @@ using namespace solidity::yul::test::yul_fuzzer; using namespace protobuf_mutator; -using namespace std; using YPM = YulProtoMutator; -MutationInfo::MutationInfo(ProtobufMessage const* _message, string const& _info): +MutationInfo::MutationInfo(ProtobufMessage const* _message, std::string const& _info): ScopeGuard([&]{ exitInfo(); }), m_protobufMsg(_message) { @@ -60,7 +59,7 @@ struct addControlFlow /// Unused variable registers callback. LPMPostProcessor callback(function); } - function function; + std::function function; }; } @@ -182,7 +181,7 @@ void YPM::addControlFlow(T* _msg, unsigned _seed) Leave, Termination }; - uniform_int_distribution d( + std::uniform_int_distribution d( static_cast(ControlFlowStmt::For), static_cast(ControlFlowStmt::Termination) ); @@ -229,7 +228,7 @@ Block* YPM::randomBlock(ForStmt* _stmt, unsigned _seed) Post = 1, Body = 2 }; - uniform_int_distribution d( + std::uniform_int_distribution d( static_cast(ForBlocks::Init), static_cast(ForBlocks::Body) ); diff --git a/test/tools/ossfuzz/solProtoFuzzer.cpp b/test/tools/ossfuzz/solProtoFuzzer.cpp index f7acc6c10..06edd3e99 100644 --- a/test/tools/ossfuzz/solProtoFuzzer.cpp +++ b/test/tools/ossfuzz/solProtoFuzzer.cpp @@ -35,19 +35,18 @@ using namespace solidity; using namespace solidity::frontend; using namespace solidity::test; using namespace solidity::util; -using namespace std; DEFINE_PROTO_FUZZER(Program const& _input) { ProtoConverter converter; - string sol_source = converter.protoToSolidity(_input); + std::string sol_source = converter.protoToSolidity(_input); if (char const* dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) { // With libFuzzer binary run this to generate a YUL source file x.yul: // PROTO_FUZZER_DUMP_PATH=x.yul ./a.out proto-input - ofstream of(dump_path); - of.write(sol_source.data(), static_cast(sol_source.size())); + std::ofstream of(dump_path); + of.write(sol_source.data(), static_cast(sol_source.size())); } if (char const* dump_path = getenv("SOL_DEBUG_FILE")) @@ -55,7 +54,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) sol_source.clear(); // With libFuzzer binary run this to generate a YUL source file x.yul: // PROTO_FUZZER_LOAD_PATH=x.yul ./a.out proto-input - ifstream ifstr(dump_path); + std::ifstream ifstr(dump_path); sol_source = { std::istreambuf_iterator(ifstr), std::istreambuf_iterator() @@ -66,9 +65,9 @@ DEFINE_PROTO_FUZZER(Program const& _input) // We target the default EVM which is the latest langutil::EVMVersion version; EVMHost hostContext(version, evmone); - string contractName = "C"; - string libraryName = converter.libraryTest() ? converter.libraryName() : ""; - string methodName = "test()"; + std::string contractName = "C"; + std::string libraryName = converter.libraryTest() ? converter.libraryName() : ""; + std::string methodName = "test()"; StringMap source({{"test.sol", sol_source}}); CompilerInput cInput(version, source, contractName, OptimiserSettings::minimal(), {}); EvmoneUtility evmoneUtil( diff --git a/test/tools/ossfuzz/solc_ossfuzz.cpp b/test/tools/ossfuzz/solc_ossfuzz.cpp index 620ef332b..dc7e26a2a 100644 --- a/test/tools/ossfuzz/solc_ossfuzz.cpp +++ b/test/tools/ossfuzz/solc_ossfuzz.cpp @@ -23,7 +23,6 @@ #include using namespace solidity::frontend::test; -using namespace std; // Prototype as we can't use the FuzzerInterface.h header. extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size); @@ -32,13 +31,13 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) { if (_size <= 600) { - string input(reinterpret_cast(_data), _size); - map sourceCode; + std::string input(reinterpret_cast(_data), _size); + std::map sourceCode; try { TestCaseReader t = TestCaseReader(std::istringstream(input)); sourceCode = t.sources().sources; - map settings = t.settings(); + std::map settings = t.settings(); bool compileViaYul = settings.count("compileViaYul") && (settings.at("compileViaYul") == "also" || settings.at("compileViaYul") == "true"); @@ -51,7 +50,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) compileViaYul ); } - catch (runtime_error const&) + catch (std::runtime_error const&) { return 0; } diff --git a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp index c7ffd3d41..595aecdca 100644 --- a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp @@ -24,7 +24,6 @@ using namespace solidity; using namespace solidity::yul; -using namespace std; // Prototype as we can't use the FuzzerInterface.h header. extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size); @@ -36,10 +35,10 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) YulStringRepository::reset(); - string input(reinterpret_cast(_data), _size); + std::string input(reinterpret_cast(_data), _size); YulStack stack( langutil::EVMVersion(), - nullopt, + std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::minimal(), langutil::DebugInfoSelection::All() diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index 5c923a3ea..e31391b0e 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -36,7 +36,6 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::yul; using namespace solidity::util; @@ -51,7 +50,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) if (_size > 600) return 0; - string input(reinterpret_cast(_data), _size); + std::string input(reinterpret_cast(_data), _size); if (std::any_of(input.begin(), input.end(), [](char c) { return ((static_cast(c) > 127) || !(isPrint(c) || (c == '\n') || (c == '\t'))); @@ -62,7 +61,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) YulStack stack( langutil::EVMVersion(), - nullopt, + std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), DebugInfoSelection::All() @@ -81,8 +80,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) return 0; } - ostringstream os1; - ostringstream os2; + std::ostringstream os1; + std::ostringstream os2; // Disable memory tracing to avoid false positive reports // such as unused write to memory e.g., // { mstore(0, 1) } diff --git a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp index db35cc865..7553c81c0 100644 --- a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp @@ -25,7 +25,6 @@ using namespace solidity; using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; -using namespace std; // Prototype as we can't use the FuzzerInterface.h header. extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size); @@ -37,10 +36,10 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) YulStringRepository::reset(); - string input(reinterpret_cast(_data), _size); + std::string input(reinterpret_cast(_data), _size); YulStack stack( langutil::EVMVersion(), - nullopt, + std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), DebugInfoSelection::All() diff --git a/test/tools/ossfuzz/yulFuzzerCommon.cpp b/test/tools/ossfuzz/yulFuzzerCommon.cpp index 57f930cfe..4f7a871ac 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.cpp +++ b/test/tools/ossfuzz/yulFuzzerCommon.cpp @@ -17,14 +17,13 @@ // SPDX-License-Identifier: GPL-3.0 #include -using namespace std; using namespace solidity; using namespace solidity::yul; using namespace solidity::yul::test::yul_fuzzer; yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( - ostream& _os, - shared_ptr _ast, + std::ostream& _os, + std::shared_ptr _ast, Dialect const& _dialect, bool _disableMemoryTracing, bool _outputStorageOnly, diff --git a/test/tools/ossfuzz/yulProtoFuzzer.cpp b/test/tools/ossfuzz/yulProtoFuzzer.cpp index c2ac68093..b27d879d5 100644 --- a/test/tools/ossfuzz/yulProtoFuzzer.cpp +++ b/test/tools/ossfuzz/yulProtoFuzzer.cpp @@ -40,20 +40,19 @@ using namespace solidity::langutil; using namespace solidity::yul; using namespace solidity::yul::test; using namespace solidity::yul::test::yul_fuzzer; -using namespace std; DEFINE_PROTO_FUZZER(Program const& _input) { ProtoConverter converter; - string yul_source = converter.programToString(_input); + std::string yul_source = converter.programToString(_input); EVMVersion version = converter.version(); if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) { // With libFuzzer binary run this to generate a YUL source file x.yul: // PROTO_FUZZER_DUMP_PATH=x.yul ./a.out proto-input - ofstream of(dump_path); - of.write(yul_source.data(), static_cast(yul_source.size())); + std::ofstream of(dump_path); + of.write(yul_source.data(), static_cast(yul_source.size())); } if (yul_source.size() > 1200) @@ -64,7 +63,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // YulStack entry point YulStack stack( version, - nullopt, + std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), DebugInfoSelection::All() @@ -85,6 +84,6 @@ DEFINE_PROTO_FUZZER(Program const& _input) EVMDialect::strictAssemblyForEVMObjects(version) ); optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); - shared_ptr astBlock = optimizerTest.run(); + std::shared_ptr astBlock = optimizerTest.run(); yulAssert(astBlock != nullptr, "Optimiser error."); } diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index d1717a159..49470f719 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -36,7 +36,6 @@ #include -using namespace std; using namespace solidity; using namespace solidity::util; using namespace solidity::langutil; @@ -47,15 +46,15 @@ using namespace solidity::yul::test::yul_fuzzer; DEFINE_PROTO_FUZZER(Program const& _input) { ProtoConverter converter; - string yul_source = converter.programToString(_input); + std::string yul_source = converter.programToString(_input); EVMVersion version = converter.version(); if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) { // With libFuzzer binary run this to generate a YUL source file x.yul: // PROTO_FUZZER_DUMP_PATH=x.yul ./a.out proto-input - ofstream of(dump_path); - of.write(yul_source.data(), static_cast(yul_source.size())); + std::ofstream of(dump_path); + of.write(yul_source.data(), static_cast(yul_source.size())); } YulStringRepository::reset(); @@ -63,7 +62,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // YulStack entry point YulStack stack( version, - nullopt, + std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), DebugInfoSelection::All() @@ -81,8 +80,8 @@ DEFINE_PROTO_FUZZER(Program const& _input) yulAssert(false, "Proto fuzzer generated malformed program"); } - ostringstream os1; - ostringstream os2; + std::ostringstream os1; + std::ostringstream os2; // Disable memory tracing to avoid false positive reports // such as unused write to memory e.g., // { mstore(0, 1) } @@ -102,7 +101,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) EVMDialect::strictAssemblyForEVMObjects(version) ); optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); - shared_ptr astBlock = optimizerTest.run(); + std::shared_ptr astBlock = optimizerTest.run(); yulAssert(astBlock != nullptr, "Optimiser error."); termReason = yulFuzzerUtil::interpret( os2, @@ -116,8 +115,8 @@ DEFINE_PROTO_FUZZER(Program const& _input) bool isTraceEq = (os1.str() == os2.str()); if (!isTraceEq) { - cout << os1.str() << endl; - cout << os2.str() << endl; + std::cout << os1.str() << std::endl; + std::cout << os2.str() << std::endl; yulAssert(false, "Interpreted traces for optimized and unoptimized code differ."); } return; diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 20491afe1..d16b1da19 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -64,7 +64,6 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::util; using namespace solidity::langutil; @@ -79,14 +78,14 @@ class YulOpti static void printErrors(CharStream const& _charStream, ErrorList const& _errors) { SourceReferenceFormatter{ - cerr, + std::cerr, SingletonCharStreamProvider(_charStream), true, false }.printErrorInformation(_errors); } - void parse(string const& _input) + void parse(std::string const& _input) { ErrorList errors; ErrorReporter errorReporter(errors); @@ -96,11 +95,11 @@ class YulOpti m_ast = yul::Parser(errorReporter, m_dialect).parse(_charStream); if (!m_ast || !errorReporter.errors().empty()) { - cerr << "Error parsing source." << endl; + std::cerr << "Error parsing source." << std::endl; printErrors(_charStream, errors); throw std::runtime_error("Could not parse source."); } - m_analysisInfo = make_unique(); + m_analysisInfo = std::make_unique(); AsmAnalyzer analyzer( *m_analysisInfo, errorReporter, @@ -108,21 +107,21 @@ class YulOpti ); if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty()) { - cerr << "Error analyzing source." << endl; + std::cerr << "Error analyzing source." << std::endl; printErrors(_charStream, errors); throw std::runtime_error("Could not analyze source."); } } catch(...) { - cerr << "Fatal error during parsing: " << endl; + std::cerr << "Fatal error during parsing: " << std::endl; printErrors(_charStream, errors); throw; } } void printUsageBanner( - map const& _extraOptions, + std::map const& _extraOptions, size_t _columns ) { @@ -134,10 +133,10 @@ class YulOpti max_element(_extraOptions.begin(), _extraOptions.end(), hasShorterString)->second.size() ); - vector overlappingAbbreviations = + std::vector overlappingAbbreviations = ranges::views::set_intersection(_extraOptions | ranges::views::keys, optimiserSteps | ranges::views::keys) | - ranges::views::transform([](char _abbreviation){ return string(1, _abbreviation); }) | - ranges::to(); + ranges::views::transform([](char _abbreviation){ return std::string(1, _abbreviation); }) | + ranges::to(); yulAssert( overlappingAbbreviations.empty(), @@ -148,10 +147,10 @@ class YulOpti "Please update the code to use a different character and recompile yulopti." ); - vector> sortedOptions = + std::vector> sortedOptions = ranges::views::concat(optimiserSteps, _extraOptions) | - ranges::to>>() | - ranges::actions::sort([](tuple const& _a, tuple const& _b) { + ranges::to>>() | + ranges::actions::sort([](std::tuple const& _a, std::tuple const& _b) { return ( !boost::algorithm::iequals(get<1>(_a), get<1>(_b)) ? boost::algorithm::lexicographical_compare(get<1>(_a), get<1>(_b), boost::algorithm::is_iless()) : @@ -164,9 +163,9 @@ class YulOpti for (size_t row = 0; row < rows; ++row) { for (auto const& [key, name]: sortedOptions | ranges::views::drop(row) | ranges::views::stride(rows)) - cout << key << ": " << setw(static_cast(longestDescriptionLength)) << setiosflags(ios::left) << name << " "; + std::cout << key << ": " << std::setw(static_cast(longestDescriptionLength)) << std::setiosflags(std::ios::left) << name << " "; - cout << endl; + std::cout << std::endl; } } @@ -177,22 +176,22 @@ class YulOpti m_nameDispenser.reset(*m_ast); } - void runSteps(string _source, string _steps) + void runSteps(std::string _source, std::string _steps) { parse(_source); disambiguate(); OptimiserSuite{m_context}.runSequence(_steps, *m_ast); - cout << AsmPrinter{m_dialect}(*m_ast) << endl; + std::cout << AsmPrinter{m_dialect}(*m_ast) << std::endl; } - void runInteractive(string _source, bool _disambiguated = false) + void runInteractive(std::string _source, bool _disambiguated = false) { bool disambiguated = _disambiguated; while (true) { parse(_source); disambiguated = disambiguated || (disambiguate(), true); - map const& extraOptions = { + std::map const& extraOptions = { // QUIT starts with a non-letter character on purpose to get it to show up on top of the list {'#', ">>> QUIT <<<"}, {',', "VarNameCleaner"}, @@ -200,10 +199,10 @@ class YulOpti }; printUsageBanner(extraOptions, 4); - cout << "? "; - cout.flush(); + std::cout << "? "; + std::cout.flush(); char option = static_cast(readStandardInputChar()); - cout << ' ' << option << endl; + std::cout << ' ' << option << std::endl; try { @@ -234,19 +233,19 @@ class YulOpti } catch (...) { - cerr << endl << "Exception during optimiser step:" << endl; - cerr << boost::current_exception_diagnostic_information() << endl; + std::cerr << std::endl << "Exception during optimiser step:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; } - cout << "----------------------" << endl; - cout << _source << endl; + std::cout << "----------------------" << std::endl; + std::cout << _source << std::endl; } } private: - shared_ptr m_ast; + std::shared_ptr m_ast; Dialect const& m_dialect{EVMDialect::strictAssemblyForEVMObjects(EVMVersion{})}; - unique_ptr m_analysisInfo; - set const m_reservedIdentifiers = {}; + std::unique_ptr m_analysisInfo; + std::set const m_reservedIdentifiers = {}; NameDispenser m_nameDispenser{m_dialect, m_reservedIdentifiers}; OptimiserStepContext m_context{ m_dialect, @@ -275,12 +274,12 @@ int main(int argc, char** argv) options.add_options() ( "input-file", - po::value(), + po::value(), "input file" ) ( "steps", - po::value(), + po::value(), "steps to execute non-interactively" ) ( @@ -302,43 +301,43 @@ int main(int argc, char** argv) if (arguments.count("help")) { - cout << options; + std::cout << options; return 0; } - string input; + std::string input; if (arguments.count("input-file")) { - string filename = arguments["input-file"].as(); + std::string filename = arguments["input-file"].as(); if (filename == "-") { nonInteractive = true; - input = readUntilEnd(cin); + input = readUntilEnd(std::cin); } else - input = readFileAsString(arguments["input-file"].as()); + input = readFileAsString(arguments["input-file"].as()); } else { - cout << options; + std::cout << options; return 1; } if (nonInteractive && !arguments.count("steps")) { - cout << options; + std::cout << options; return 1; } YulOpti yulOpti; bool disambiguated = false; if (!nonInteractive) - cout << input << endl; + std::cout << input << std::endl; if (arguments.count("steps")) { - string sequence = arguments["steps"].as(); + std::string sequence = arguments["steps"].as(); if (!nonInteractive) - cout << "----------------------" << endl; + std::cout << "----------------------" << std::endl; yulOpti.runSteps(input, sequence); disambiguated = true; } @@ -349,23 +348,23 @@ int main(int argc, char** argv) } catch (po::error const& _exception) { - cerr << _exception.what() << endl; + std::cerr << _exception.what() << std::endl; return 1; } catch (FileNotFound const& _exception) { - cerr << "File not found:" << _exception.comment() << endl; + std::cerr << "File not found:" << _exception.comment() << std::endl; return 1; } catch (NotAFile const& _exception) { - cerr << "Not a regular file:" << _exception.comment() << endl; + std::cerr << "Not a regular file:" << _exception.comment() << std::endl; return 1; } catch(...) { - cerr << endl << "Exception:" << endl; - cerr << boost::current_exception_diagnostic_information() << endl; + std::cerr << std::endl << "Exception:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; return 1; } } diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index 2e1bcc013..fb18b4e59 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -43,7 +43,6 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::util; using namespace solidity::langutil; @@ -55,11 +54,11 @@ namespace po = boost::program_options; namespace { -pair, shared_ptr> parse(string const& _source) +std::pair, std::shared_ptr> parse(std::string const& _source) { YulStack stack( langutil::EVMVersion(), - nullopt, + std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::none(), DebugInfoSelection::Default() @@ -71,15 +70,15 @@ pair, shared_ptr> parse(string const& _source } else { - SourceReferenceFormatter(cout, stack, true, false).printErrorInformation(stack.errors()); + SourceReferenceFormatter(std::cout, stack, true, false).printErrorInformation(stack.errors()); return {}; } } -void interpret(string const& _source, bool _inspect, bool _disableExternalCalls) +void interpret(std::string const& _source, bool _inspect, bool _disableExternalCalls) { - shared_ptr ast; - shared_ptr analysisInfo; + std::shared_ptr ast; + std::shared_ptr analysisInfo; tie(ast, analysisInfo) = parse(_source); if (!ast || !analysisInfo) return; @@ -100,7 +99,7 @@ void interpret(string const& _source, bool _inspect, bool _disableExternalCalls) { } - state.dumpTraceAndState(cout, /*disableMemoryTracing=*/false); + state.dumpTraceAndState(std::cout, /*disableMemoryTracing=*/false); } } @@ -119,7 +118,7 @@ Allowed options)", ("help", "Show this help screen.") ("enable-external-calls", "Enable external calls") ("interactive", "Run interactive") - ("input-file", po::value>(), "input file"); + ("input-file", po::value>(), "input file"); po::positional_options_description filesPositions; filesPositions.add("input-file", -1); @@ -132,17 +131,17 @@ Allowed options)", } catch (po::error const& _exception) { - cerr << _exception.what() << endl; + std::cerr << _exception.what() << std::endl; return 1; } if (arguments.count("help")) - cout << options; + std::cout << options; else { - string input; + std::string input; if (arguments.count("input-file")) - for (string path: arguments["input-file"].as>()) + for (std::string path: arguments["input-file"].as>()) { try { @@ -150,17 +149,17 @@ Allowed options)", } catch (FileNotFound const&) { - cerr << "File not found: " << path << endl; + std::cerr << "File not found: " << path << std::endl; return 1; } catch (NotAFile const&) { - cerr << "Not a regular file: " << path << endl; + std::cerr << "Not a regular file: " << path << std::endl; return 1; } } else - input = readUntilEnd(cin); + input = readUntilEnd(std::cin); interpret(input, arguments.count("interactive"), !arguments.count("enable-external-calls")); } diff --git a/tools/yulPhaser/AlgorithmRunner.cpp b/tools/yulPhaser/AlgorithmRunner.cpp index d5ad75575..827261dc0 100644 --- a/tools/yulPhaser/AlgorithmRunner.cpp +++ b/tools/yulPhaser/AlgorithmRunner.cpp @@ -26,7 +26,6 @@ #include #include -using namespace std; using namespace solidity::phaser; void AlgorithmRunner::run(GeneticAlgorithm& _algorithm) @@ -65,12 +64,12 @@ void AlgorithmRunner::printRoundSummary( if (m_options.showRoundInfo) { m_outputStream << "---------- ROUND " << _round + 1; - m_outputStream << " [round: " << fixed << setprecision(1) << roundTime << " s,"; - m_outputStream << " total: " << fixed << setprecision(1) << totalTime << " s]"; - m_outputStream << " ----------" << endl; + m_outputStream << " [round: " << std::fixed << std::setprecision(1) << roundTime << " s,"; + m_outputStream << " total: " << std::fixed << std::setprecision(1) << totalTime << " s]"; + m_outputStream << " ----------" << std::endl; } else if (m_population.individuals().size() > 0) - m_outputStream << endl; + m_outputStream << std::endl; m_outputStream << m_population; } @@ -78,11 +77,11 @@ void AlgorithmRunner::printRoundSummary( { if (m_options.showRoundInfo) { - m_outputStream << setw(5) << _round + 1 << " | "; - m_outputStream << setw(5) << fixed << setprecision(1) << totalTime << " | "; + m_outputStream << std::setw(5) << _round + 1 << " | "; + m_outputStream << std::setw(5) << std::fixed << std::setprecision(1) << totalTime << " | "; } - m_outputStream << m_population.individuals()[0] << endl; + m_outputStream << m_population.individuals()[0] << std::endl; } } @@ -91,7 +90,7 @@ void AlgorithmRunner::printInitialPopulation() const if (!m_options.showInitialPopulation) return; - m_outputStream << "---------- INITIAL POPULATION ----------" << endl; + m_outputStream << "---------- INITIAL POPULATION ----------" << std::endl; m_outputStream << m_population; } @@ -108,23 +107,23 @@ void AlgorithmRunner::printCacheStats() const else ++disabledCacheCount; - m_outputStream << "---------- CACHE STATS ----------" << endl; + m_outputStream << "---------- CACHE STATS ----------" << std::endl; if (disabledCacheCount < m_programCaches.size()) { for (auto& [round, count]: totalStats.roundEntryCounts) - m_outputStream << "Round " << round << ": " << count << " entries" << endl; - m_outputStream << "Total hits: " << totalStats.hits << endl; - m_outputStream << "Total misses: " << totalStats.misses << endl; - m_outputStream << "Size of cached code: " << totalStats.totalCodeSize << endl; + m_outputStream << "Round " << round << ": " << count << " entries" << std::endl; + m_outputStream << "Total hits: " << totalStats.hits << std::endl; + m_outputStream << "Total misses: " << totalStats.misses << std::endl; + m_outputStream << "Size of cached code: " << totalStats.totalCodeSize << std::endl; } if (disabledCacheCount == m_programCaches.size()) - m_outputStream << "Program cache disabled" << endl; + m_outputStream << "Program cache disabled" << std::endl; else if (disabledCacheCount > 0) { m_outputStream << "Program cache disabled for " << disabledCacheCount << " out of "; - m_outputStream << m_programCaches.size() << " programs" << endl; + m_outputStream << m_programCaches.size() << " programs" << std::endl; } } @@ -133,20 +132,20 @@ void AlgorithmRunner::populationAutosave() const if (!m_options.populationAutosaveFile.has_value()) return; - ofstream outputStream(m_options.populationAutosaveFile.value(), ios::out | ios::trunc); + std::ofstream outputStream(m_options.populationAutosaveFile.value(), std::ios::out | std::ios::trunc); assertThrow( outputStream.is_open(), FileOpenError, - "Could not open file '" + m_options.populationAutosaveFile.value() + "': " + strerror(errno) + "Could not open file '" + m_options.populationAutosaveFile.value() + "': " + std::strerror(errno) ); for (auto& individual: m_population.individuals()) - outputStream << individual.chromosome << endl; + outputStream << individual.chromosome << std::endl; assertThrow( !outputStream.bad(), FileWriteError, - "Error while writing to file '" + m_options.populationAutosaveFile.value() + "': " + strerror(errno) + "Error while writing to file '" + m_options.populationAutosaveFile.value() + "': " + std::strerror(errno) ); } @@ -188,7 +187,7 @@ Population AlgorithmRunner::randomiseDuplicates( if (_population.individuals().size() == 0) return _population; - vector individuals{_population.individuals()[0]}; + std::vector individuals{_population.individuals()[0]}; size_t duplicateCount = 0; for (size_t i = 1; i < _population.individuals().size(); ++i) if (_population.individuals()[i].chromosome == _population.individuals()[i - 1].chromosome) diff --git a/tools/yulPhaser/Chromosome.cpp b/tools/yulPhaser/Chromosome.cpp index 6e8d3544e..85a97a781 100644 --- a/tools/yulPhaser/Chromosome.cpp +++ b/tools/yulPhaser/Chromosome.cpp @@ -25,7 +25,6 @@ #include -using namespace std; using namespace solidity; using namespace solidity::yul; using namespace solidity::phaser; @@ -33,36 +32,36 @@ using namespace solidity::phaser; namespace solidity::phaser { -ostream& operator<<(ostream& _stream, Chromosome const& _chromosome); +std::ostream& operator<<(std::ostream& _stream, Chromosome const& _chromosome); } Chromosome Chromosome::makeRandom(size_t _length) { - vector steps; + std::vector steps; for (size_t i = 0; i < _length; ++i) steps.push_back(randomOptimisationStep()); return Chromosome(std::move(steps)); } -ostream& phaser::operator<<(ostream& _stream, Chromosome const& _chromosome) +std::ostream& phaser::operator<<(std::ostream& _stream, Chromosome const& _chromosome) { return _stream << _chromosome.m_genes; } -vector Chromosome::allStepNames() +std::vector Chromosome::allStepNames() { - vector stepNames; + std::vector stepNames; for (auto const& step: OptimiserSuite::allSteps()) stepNames.push_back(step.first); return stepNames; } -string const& Chromosome::randomOptimisationStep() +std::string const& Chromosome::randomOptimisationStep() { - static vector stepNames = allStepNames(); + static std::vector stepNames = allStepNames(); return stepNames[SimulationRNG::uniformInt(0, stepNames.size() - 1)]; } @@ -72,18 +71,18 @@ char Chromosome::randomGene() return OptimiserSuite::stepNameToAbbreviationMap().at(randomOptimisationStep()); } -string Chromosome::stepsToGenes(vector const& _optimisationSteps) +std::string Chromosome::stepsToGenes(std::vector const& _optimisationSteps) { - string genes; - for (string const& stepName: _optimisationSteps) + std::string genes; + for (std::string const& stepName: _optimisationSteps) genes.push_back(OptimiserSuite::stepNameToAbbreviationMap().at(stepName)); return genes; } -vector Chromosome::genesToSteps(string const& _genes) +std::vector Chromosome::genesToSteps(std::string const& _genes) { - vector steps; + std::vector steps; for (char abbreviation: _genes) steps.push_back(OptimiserSuite::stepAbbreviationToNameMap().at(abbreviation)); diff --git a/tools/yulPhaser/Common.cpp b/tools/yulPhaser/Common.cpp index a23210172..ca5197b7d 100644 --- a/tools/yulPhaser/Common.cpp +++ b/tools/yulPhaser/Common.cpp @@ -26,21 +26,20 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::phaser; -vector phaser::readLinesFromFile(string const& _path) +std::vector phaser::readLinesFromFile(std::string const& _path) { - ifstream inputStream(_path); - assertThrow(inputStream.is_open(), FileOpenError, "Could not open file '" + _path + "': " + strerror(errno)); + std::ifstream inputStream(_path); + assertThrow(inputStream.is_open(), FileOpenError, "Could not open file '" + _path + "': " + std::strerror(errno)); - string line; - vector lines; - while (!getline(inputStream, line).fail()) + std::string line; + std::vector lines; + while (!std::getline(inputStream, line).fail()) lines.push_back(line); - assertThrow(!inputStream.bad(), FileReadError, "Error while reading from file '" + _path + "': " + strerror(errno)); + assertThrow(!inputStream.bad(), FileReadError, "Error while reading from file '" + _path + "': " + std::strerror(errno)); return lines; } diff --git a/tools/yulPhaser/FitnessMetrics.cpp b/tools/yulPhaser/FitnessMetrics.cpp index e0b719e25..43ad3aa64 100644 --- a/tools/yulPhaser/FitnessMetrics.cpp +++ b/tools/yulPhaser/FitnessMetrics.cpp @@ -22,7 +22,6 @@ #include -using namespace std; using namespace solidity::util; using namespace solidity::yul; using namespace solidity::phaser; @@ -62,7 +61,7 @@ size_t ProgramSize::evaluate(Chromosome const& _chromosome) size_t RelativeProgramSize::evaluate(Chromosome const& _chromosome) { - double const scalingFactor = pow(10, m_fixedPointPrecision); + double const scalingFactor = std::pow(10, m_fixedPointPrecision); size_t unoptimisedSize = optimisedProgram(Chromosome("")).codeSize(codeWeights()); if (unoptimisedSize == 0) @@ -70,7 +69,7 @@ size_t RelativeProgramSize::evaluate(Chromosome const& _chromosome) size_t optimisedSize = optimisedProgram(_chromosome).codeSize(codeWeights()); - return static_cast(round( + return static_cast(std::round( double(optimisedSize) / double(unoptimisedSize) * scalingFactor )); } @@ -103,7 +102,7 @@ size_t FitnessMetricMaximum::evaluate(Chromosome const& _chromosome) size_t maximum = m_metrics[0]->evaluate(_chromosome); for (size_t i = 1; i < m_metrics.size(); ++i) - maximum = max(maximum, m_metrics[i]->evaluate(_chromosome)); + maximum = std::max(maximum, m_metrics[i]->evaluate(_chromosome)); return maximum; } @@ -114,7 +113,7 @@ size_t FitnessMetricMinimum::evaluate(Chromosome const& _chromosome) size_t minimum = m_metrics[0]->evaluate(_chromosome); for (size_t i = 1; i < m_metrics.size(); ++i) - minimum = min(minimum, m_metrics[i]->evaluate(_chromosome)); + minimum = std::min(minimum, m_metrics[i]->evaluate(_chromosome)); return minimum; } diff --git a/tools/yulPhaser/GeneticAlgorithms.cpp b/tools/yulPhaser/GeneticAlgorithms.cpp index ff40d222a..9345fda4f 100644 --- a/tools/yulPhaser/GeneticAlgorithms.cpp +++ b/tools/yulPhaser/GeneticAlgorithms.cpp @@ -21,13 +21,12 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::phaser; -function phaser::buildCrossoverOperator( +std::function phaser::buildCrossoverOperator( CrossoverChoice _choice, - optional _uniformCrossoverSwapChance + std::optional _uniformCrossoverSwapChance ) { switch (_choice) @@ -44,9 +43,9 @@ function phaser::buildCrossoverOperator( }; } -function phaser::buildSymmetricCrossoverOperator( +std::function phaser::buildSymmetricCrossoverOperator( CrossoverChoice _choice, - optional _uniformCrossoverSwapChance + std::optional _uniformCrossoverSwapChance ) { switch (_choice) @@ -146,14 +145,14 @@ Population ClassicGeneticAlgorithm::select(Population _population, size_t _selec size_t maxFitness = 0; for (auto const& individual: _population.individuals()) - maxFitness = max(maxFitness, individual.fitness); + maxFitness = std::max(maxFitness, individual.fitness); size_t rouletteRange = 0; for (auto const& individual: _population.individuals()) // Add 1 to make sure that every chromosome has non-zero probability of being chosen rouletteRange += maxFitness + 1 - individual.fitness; - vector selectedIndividuals; + std::vector selectedIndividuals; for (size_t i = 0; i < _selectionSize; ++i) { size_t ball = SimulationRNG::uniformInt(0, rouletteRange - 1); diff --git a/tools/yulPhaser/Mutations.cpp b/tools/yulPhaser/Mutations.cpp index 873fbbb9b..ac55ae9d4 100644 --- a/tools/yulPhaser/Mutations.cpp +++ b/tools/yulPhaser/Mutations.cpp @@ -28,15 +28,14 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::phaser; -function phaser::geneRandomisation(double _chance) +std::function phaser::geneRandomisation(double _chance) { return [=](Chromosome const& _chromosome) { - string genes; + std::string genes; for (char gene: _chromosome.genes()) genes.push_back( SimulationRNG::bernoulliTrial(_chance) ? @@ -48,11 +47,11 @@ function phaser::geneRandomisation(double _chance) }; } -function phaser::geneDeletion(double _chance) +std::function phaser::geneDeletion(double _chance) { return [=](Chromosome const& _chromosome) { - string genes; + std::string genes; for (char gene: _chromosome.genes()) if (!SimulationRNG::bernoulliTrial(_chance)) genes.push_back(gene); @@ -61,11 +60,11 @@ function phaser::geneDeletion(double _chance) }; } -function phaser::geneAddition(double _chance) +std::function phaser::geneAddition(double _chance) { return [=](Chromosome const& _chromosome) { - string genes; + std::string genes; if (SimulationRNG::bernoulliTrial(_chance)) genes.push_back(Chromosome::randomGene()); @@ -81,10 +80,10 @@ function phaser::geneAddition(double _chance) }; } -function phaser::alternativeMutations( +std::function phaser::alternativeMutations( double _firstMutationChance, - function _mutation1, - function _mutation2 + std::function _mutation1, + std::function _mutation2 ) { return [=](Chromosome const& _chromosome) @@ -96,7 +95,7 @@ function phaser::alternativeMutations( }; } -function phaser::mutationSequence(vector> _mutations) +std::function phaser::mutationSequence(std::vector> _mutations) { return [=](Chromosome const& _chromosome) { @@ -134,26 +133,26 @@ ChromosomePair fixedPointSwap( } -function phaser::randomPointCrossover() +std::function phaser::randomPointCrossover() { return [=](Chromosome const& _chromosome1, Chromosome const& _chromosome2) { - size_t minLength = min(_chromosome1.length(), _chromosome2.length()); + size_t minLength = std::min(_chromosome1.length(), _chromosome2.length()); // Don't use position 0 (because this just swaps the values) unless it's the only choice. size_t minPoint = (minLength > 0 ? 1 : 0); assert(minPoint <= minLength); size_t randomPoint = SimulationRNG::uniformInt(minPoint, minLength); - return get<0>(fixedPointSwap(_chromosome1, _chromosome2, randomPoint)); + return std::get<0>(fixedPointSwap(_chromosome1, _chromosome2, randomPoint)); }; } -function phaser::symmetricRandomPointCrossover() +std::function phaser::symmetricRandomPointCrossover() { return [=](Chromosome const& _chromosome1, Chromosome const& _chromosome2) { - size_t minLength = min(_chromosome1.length(), _chromosome2.length()); + size_t minLength = std::min(_chromosome1.length(), _chromosome2.length()); // Don't use position 0 (because this just swaps the values) unless it's the only choice. size_t minPoint = (minLength > 0 ? 1 : 0); @@ -164,16 +163,16 @@ function phaser::symmetricRandomPointCrossover() }; } -function phaser::fixedPointCrossover(double _crossoverPoint) +std::function phaser::fixedPointCrossover(double _crossoverPoint) { assert(0.0 <= _crossoverPoint && _crossoverPoint <= 1.0); return [=](Chromosome const& _chromosome1, Chromosome const& _chromosome2) { - size_t minLength = min(_chromosome1.length(), _chromosome2.length()); - size_t concretePoint = static_cast(round(double(minLength) * _crossoverPoint)); + size_t minLength = std::min(_chromosome1.length(), _chromosome2.length()); + size_t concretePoint = static_cast(std::round(double(minLength) * _crossoverPoint)); - return get<0>(fixedPointSwap(_chromosome1, _chromosome2, concretePoint)); + return std::get<0>(fixedPointSwap(_chromosome1, _chromosome2, concretePoint)); }; } @@ -192,8 +191,8 @@ ChromosomePair fixedTwoPointSwap( assert(_crossoverPoint2 <= _chromosome1.length()); assert(_crossoverPoint2 <= _chromosome2.length()); - size_t lowPoint = min(_crossoverPoint1, _crossoverPoint2); - size_t highPoint = max(_crossoverPoint1, _crossoverPoint2); + size_t lowPoint = std::min(_crossoverPoint1, _crossoverPoint2); + size_t highPoint = std::max(_crossoverPoint1, _crossoverPoint2); return { Chromosome( @@ -211,11 +210,11 @@ ChromosomePair fixedTwoPointSwap( } -function phaser::randomTwoPointCrossover() +std::function phaser::randomTwoPointCrossover() { return [=](Chromosome const& _chromosome1, Chromosome const& _chromosome2) { - size_t minLength = min(_chromosome1.length(), _chromosome2.length()); + size_t minLength = std::min(_chromosome1.length(), _chromosome2.length()); // Don't use position 0 (because this just swaps the values) unless it's the only choice. size_t minPoint = (minLength > 0 ? 1 : 0); @@ -223,15 +222,15 @@ function phaser::randomTwoPointCrossover() size_t randomPoint1 = SimulationRNG::uniformInt(minPoint, minLength); size_t randomPoint2 = SimulationRNG::uniformInt(randomPoint1, minLength); - return get<0>(fixedTwoPointSwap(_chromosome1, _chromosome2, randomPoint1, randomPoint2)); + return std::get<0>(fixedTwoPointSwap(_chromosome1, _chromosome2, randomPoint1, randomPoint2)); }; } -function phaser::symmetricRandomTwoPointCrossover() +std::function phaser::symmetricRandomTwoPointCrossover() { return [=](Chromosome const& _chromosome1, Chromosome const& _chromosome2) { - size_t minLength = min(_chromosome1.length(), _chromosome2.length()); + size_t minLength = std::min(_chromosome1.length(), _chromosome2.length()); // Don't use position 0 (because this just swaps the values) unless it's the only choice. size_t minPoint = (minLength > 0 ? 1 : 0); @@ -248,10 +247,10 @@ namespace ChromosomePair uniformSwap(Chromosome const& _chromosome1, Chromosome const& _chromosome2, double _swapChance) { - string steps1; - string steps2; + std::string steps1; + std::string steps2; - size_t minLength = min(_chromosome1.length(), _chromosome2.length()); + size_t minLength = std::min(_chromosome1.length(), _chromosome2.length()); for (size_t i = 0; i < minLength; ++i) if (SimulationRNG::bernoulliTrial(_swapChance)) { @@ -286,15 +285,15 @@ ChromosomePair uniformSwap(Chromosome const& _chromosome1, Chromosome const& _ch } -function phaser::uniformCrossover(double _swapChance) +std::function phaser::uniformCrossover(double _swapChance) { return [=](Chromosome const& _chromosome1, Chromosome const& _chromosome2) { - return get<0>(uniformSwap(_chromosome1, _chromosome2, _swapChance)); + return std::get<0>(uniformSwap(_chromosome1, _chromosome2, _swapChance)); }; } -function phaser::symmetricUniformCrossover(double _swapChance) +std::function phaser::symmetricUniformCrossover(double _swapChance) { return [=](Chromosome const& _chromosome1, Chromosome const& _chromosome2) { diff --git a/tools/yulPhaser/PairSelections.cpp b/tools/yulPhaser/PairSelections.cpp index 4c9d4ee5f..deff94863 100644 --- a/tools/yulPhaser/PairSelections.cpp +++ b/tools/yulPhaser/PairSelections.cpp @@ -23,17 +23,16 @@ #include -using namespace std; using namespace solidity::phaser; -vector> RandomPairSelection::materialise(size_t _poolSize) const +std::vector> RandomPairSelection::materialise(size_t _poolSize) const { if (_poolSize < 2) return {}; - auto count = static_cast(round(double(_poolSize) * m_selectionSize)); + auto count = static_cast(std::round(double(_poolSize) * m_selectionSize)); - vector> selection; + std::vector> selection; for (size_t i = 0; i < count; ++i) { size_t index1 = SimulationRNG::uniformInt(0, _poolSize - 1); @@ -49,9 +48,9 @@ vector> RandomPairSelection::materialise(size_t _poolSize) return selection; } -vector> PairsFromRandomSubset::materialise(size_t _poolSize) const +std::vector> PairsFromRandomSubset::materialise(size_t _poolSize) const { - vector selectedIndices = RandomSubset(m_selectionChance).materialise(_poolSize); + std::vector selectedIndices = RandomSubset(m_selectionChance).materialise(_poolSize); if (selectedIndices.size() % 2 != 0) { @@ -72,7 +71,7 @@ vector> PairsFromRandomSubset::materialise(size_t _poolSiz } assert(selectedIndices.size() % 2 == 0); - vector> selectedPairs; + std::vector> selectedPairs; for (size_t i = selectedIndices.size() / 2; i > 0; --i) { size_t position1 = SimulationRNG::uniformInt(0, selectedIndices.size() - 1); @@ -89,18 +88,18 @@ vector> PairsFromRandomSubset::materialise(size_t _poolSiz return selectedPairs; } -vector> PairMosaicSelection::materialise(size_t _poolSize) const +std::vector> PairMosaicSelection::materialise(size_t _poolSize) const { if (_poolSize < 2) return {}; - size_t count = static_cast(round(double(_poolSize) * m_selectionSize)); + size_t count = static_cast(std::round(double(_poolSize) * m_selectionSize)); - vector> selection; + std::vector> selection; for (size_t i = 0; i < count; ++i) { - tuple pair = m_pattern[i % m_pattern.size()]; - selection.emplace_back(min(get<0>(pair), _poolSize - 1), min(get<1>(pair), _poolSize - 1)); + std::tuple pair = m_pattern[i % m_pattern.size()]; + selection.emplace_back(std::min(std::get<0>(pair), _poolSize - 1), std::min(std::get<1>(pair), _poolSize - 1)); } return selection; diff --git a/tools/yulPhaser/Phaser.cpp b/tools/yulPhaser/Phaser.cpp index db5ec35ce..6bddf39fc 100644 --- a/tools/yulPhaser/Phaser.cpp +++ b/tools/yulPhaser/Phaser.cpp @@ -37,7 +37,6 @@ #include -using namespace std; using namespace solidity; using namespace solidity::langutil; using namespace solidity::util; @@ -49,58 +48,58 @@ namespace po = boost::program_options; namespace { -map const PhaserModeToStringMap = +std::map const PhaserModeToStringMap = { {PhaserMode::RunAlgorithm, "run-algorithm"}, {PhaserMode::PrintOptimisedPrograms, "print-optimised-programs"}, {PhaserMode::PrintOptimisedASTs, "print-optimised-asts"}, }; -map const StringToPhaserModeMap = invertMap(PhaserModeToStringMap); +std::map const StringToPhaserModeMap = invertMap(PhaserModeToStringMap); -map const AlgorithmToStringMap = +std::map const AlgorithmToStringMap = { {Algorithm::Random, "random"}, {Algorithm::GEWEP, "GEWEP"}, {Algorithm::Classic, "classic"}, }; -map const StringToAlgorithmMap = invertMap(AlgorithmToStringMap); +std::map const StringToAlgorithmMap = invertMap(AlgorithmToStringMap); -map MetricChoiceToStringMap = +std::map MetricChoiceToStringMap = { {MetricChoice::CodeSize, "code-size"}, {MetricChoice::RelativeCodeSize, "relative-code-size"}, }; -map const StringToMetricChoiceMap = invertMap(MetricChoiceToStringMap); +std::map const StringToMetricChoiceMap = invertMap(MetricChoiceToStringMap); -map const MetricAggregatorChoiceToStringMap = +std::map const MetricAggregatorChoiceToStringMap = { {MetricAggregatorChoice::Average, "average"}, {MetricAggregatorChoice::Sum, "sum"}, {MetricAggregatorChoice::Maximum, "maximum"}, {MetricAggregatorChoice::Minimum, "minimum"}, }; -map const StringToMetricAggregatorChoiceMap = invertMap(MetricAggregatorChoiceToStringMap); +std::map const StringToMetricAggregatorChoiceMap = invertMap(MetricAggregatorChoiceToStringMap); -map const CrossoverChoiceToStringMap = +std::map const CrossoverChoiceToStringMap = { {CrossoverChoice::SinglePoint, "single-point"}, {CrossoverChoice::TwoPoint, "two-point"}, {CrossoverChoice::Uniform, "uniform"}, }; -map const StringToCrossoverChoiceMap = invertMap(CrossoverChoiceToStringMap); +std::map const StringToCrossoverChoiceMap = invertMap(CrossoverChoiceToStringMap); } -istream& phaser::operator>>(istream& _inputStream, PhaserMode& _phaserMode) { return deserializeChoice(_inputStream, _phaserMode, StringToPhaserModeMap); } -ostream& phaser::operator<<(ostream& _outputStream, PhaserMode _phaserMode) { return serializeChoice(_outputStream, _phaserMode, PhaserModeToStringMap); } -istream& phaser::operator>>(istream& _inputStream, Algorithm& _algorithm) { return deserializeChoice(_inputStream, _algorithm, StringToAlgorithmMap); } -ostream& phaser::operator<<(ostream& _outputStream, Algorithm _algorithm) { return serializeChoice(_outputStream, _algorithm, AlgorithmToStringMap); } -istream& phaser::operator>>(istream& _inputStream, MetricChoice& _metric) { return deserializeChoice(_inputStream, _metric, StringToMetricChoiceMap); } -ostream& phaser::operator<<(ostream& _outputStream, MetricChoice _metric) { return serializeChoice(_outputStream, _metric, MetricChoiceToStringMap); } -istream& phaser::operator>>(istream& _inputStream, MetricAggregatorChoice& _aggregator) { return deserializeChoice(_inputStream, _aggregator, StringToMetricAggregatorChoiceMap); } -ostream& phaser::operator<<(ostream& _outputStream, MetricAggregatorChoice _aggregator) { return serializeChoice(_outputStream, _aggregator, MetricAggregatorChoiceToStringMap); } -istream& phaser::operator>>(istream& _inputStream, CrossoverChoice& _crossover) { return deserializeChoice(_inputStream, _crossover, StringToCrossoverChoiceMap); } -ostream& phaser::operator<<(ostream& _outputStream, CrossoverChoice _crossover) { return serializeChoice(_outputStream, _crossover, CrossoverChoiceToStringMap); } +std::istream& phaser::operator>>(std::istream& _inputStream, PhaserMode& _phaserMode) { return deserializeChoice(_inputStream, _phaserMode, StringToPhaserModeMap); } +std::ostream& phaser::operator<<(std::ostream& _outputStream, PhaserMode _phaserMode) { return serializeChoice(_outputStream, _phaserMode, PhaserModeToStringMap); } +std::istream& phaser::operator>>(std::istream& _inputStream, Algorithm& _algorithm) { return deserializeChoice(_inputStream, _algorithm, StringToAlgorithmMap); } +std::ostream& phaser::operator<<(std::ostream& _outputStream, Algorithm _algorithm) { return serializeChoice(_outputStream, _algorithm, AlgorithmToStringMap); } +std::istream& phaser::operator>>(std::istream& _inputStream, MetricChoice& _metric) { return deserializeChoice(_inputStream, _metric, StringToMetricChoiceMap); } +std::ostream& phaser::operator<<(std::ostream& _outputStream, MetricChoice _metric) { return serializeChoice(_outputStream, _metric, MetricChoiceToStringMap); } +std::istream& phaser::operator>>(std::istream& _inputStream, MetricAggregatorChoice& _aggregator) { return deserializeChoice(_inputStream, _aggregator, StringToMetricAggregatorChoiceMap); } +std::ostream& phaser::operator<<(std::ostream& _outputStream, MetricAggregatorChoice _aggregator) { return serializeChoice(_outputStream, _aggregator, MetricAggregatorChoiceToStringMap); } +std::istream& phaser::operator>>(std::istream& _inputStream, CrossoverChoice& _crossover) { return deserializeChoice(_inputStream, _crossover, StringToCrossoverChoiceMap); } +std::ostream& phaser::operator<<(std::ostream& _outputStream, CrossoverChoice _crossover) { return serializeChoice(_outputStream, _crossover, CrossoverChoiceToStringMap); } GeneticAlgorithmFactory::Options GeneticAlgorithmFactory::Options::fromCommandLine(po::variables_map const& _arguments) { @@ -112,17 +111,17 @@ GeneticAlgorithmFactory::Options GeneticAlgorithmFactory::Options::fromCommandLi _arguments["uniform-crossover-swap-chance"].as(), _arguments.count("random-elite-pool-size") > 0 ? _arguments["random-elite-pool-size"].as() : - optional{}, + std::optional{}, _arguments["gewep-mutation-pool-size"].as(), _arguments["gewep-crossover-pool-size"].as(), _arguments["gewep-randomisation-chance"].as(), _arguments["gewep-deletion-vs-addition-chance"].as(), _arguments.count("gewep-genes-to-randomise") > 0 ? _arguments["gewep-genes-to-randomise"].as() : - optional{}, + std::optional{}, _arguments.count("gewep-genes-to-add-or-delete") > 0 ? _arguments["gewep-genes-to-add-or-delete"].as() : - optional{}, + std::optional{}, _arguments["classic-elite-pool-size"].as(), _arguments["classic-crossover-chance"].as(), _arguments["classic-mutation-chance"].as(), @@ -131,7 +130,7 @@ GeneticAlgorithmFactory::Options GeneticAlgorithmFactory::Options::fromCommandLi }; } -unique_ptr GeneticAlgorithmFactory::build( +std::unique_ptr GeneticAlgorithmFactory::build( Options const& _options, size_t _populationSize ) @@ -147,7 +146,7 @@ unique_ptr GeneticAlgorithmFactory::build( if (_options.randomElitePoolSize.has_value()) elitePoolSize = _options.randomElitePoolSize.value(); - return make_unique(RandomAlgorithm::Options{ + return std::make_unique(RandomAlgorithm::Options{ /* elitePoolSize = */ elitePoolSize, /* minChromosomeLength = */ _options.minChromosomeLength, /* maxChromosomeLength = */ _options.maxChromosomeLength, @@ -163,7 +162,7 @@ unique_ptr GeneticAlgorithmFactory::build( if (_options.gewepGenesToAddOrDelete.has_value()) percentGenesToAddOrDelete = _options.gewepGenesToAddOrDelete.value(); - return make_unique(GenerationalElitistWithExclusivePools::Options{ + return std::make_unique(GenerationalElitistWithExclusivePools::Options{ /* mutationPoolSize = */ _options.gewepMutationPoolSize, /* crossoverPoolSize = */ _options.gewepCrossoverPoolSize, /* randomisationChance = */ _options.gewepRandomisationChance, @@ -176,7 +175,7 @@ unique_ptr GeneticAlgorithmFactory::build( } case Algorithm::Classic: { - return make_unique(ClassicGeneticAlgorithm::Options{ + return std::make_unique(ClassicGeneticAlgorithm::Options{ /* elitePoolSize = */ _options.classicElitePoolSize, /* crossoverChance = */ _options.classicCrossoverChance, /* mutationChance = */ _options.classicMutationChance, @@ -222,24 +221,24 @@ FitnessMetricFactory::Options FitnessMetricFactory::Options::fromCommandLine(po: }; } -unique_ptr FitnessMetricFactory::build( +std::unique_ptr FitnessMetricFactory::build( Options const& _options, - vector _programs, - vector> _programCaches, + std::vector _programs, + std::vector> _programCaches, CodeWeights const& _weights ) { assert(_programCaches.size() == _programs.size()); assert(_programs.size() > 0 && "Validations should prevent this from being executed with zero files."); - vector> metrics; + std::vector> metrics; switch (_options.metric) { case MetricChoice::CodeSize: { for (size_t i = 0; i < _programs.size(); ++i) - metrics.push_back(make_unique( - _programCaches[i] != nullptr ? optional{} : std::move(_programs[i]), + metrics.push_back(std::make_unique( + _programCaches[i] != nullptr ? std::optional{} : std::move(_programs[i]), std::move(_programCaches[i]), _weights, _options.chromosomeRepetitions @@ -250,8 +249,8 @@ unique_ptr FitnessMetricFactory::build( case MetricChoice::RelativeCodeSize: { for (size_t i = 0; i < _programs.size(); ++i) - metrics.push_back(make_unique( - _programCaches[i] != nullptr ? optional{} : std::move(_programs[i]), + metrics.push_back(std::make_unique( + _programCaches[i] != nullptr ? std::optional{} : std::move(_programs[i]), std::move(_programCaches[i]), _options.relativeMetricScale, _weights, @@ -266,13 +265,13 @@ unique_ptr FitnessMetricFactory::build( switch (_options.metricAggregator) { case MetricAggregatorChoice::Average: - return make_unique(std::move(metrics)); + return std::make_unique(std::move(metrics)); case MetricAggregatorChoice::Sum: - return make_unique(std::move(metrics)); + return std::make_unique(std::move(metrics)); case MetricAggregatorChoice::Maximum: - return make_unique(std::move(metrics)); + return std::make_unique(std::move(metrics)); case MetricAggregatorChoice::Minimum: - return make_unique(std::move(metrics)); + return std::make_unique(std::move(metrics)); default: assertThrow(false, solidity::util::Exception, "Invalid MetricAggregatorChoice value."); } @@ -287,20 +286,20 @@ PopulationFactory::Options PopulationFactory::Options::fromCommandLine(po::varia _arguments["min-chromosome-length"].as(), _arguments["max-chromosome-length"].as(), _arguments.count("population") > 0 ? - _arguments["population"].as>() : - vector{}, + _arguments["population"].as>() : + std::vector{}, _arguments.count("random-population") > 0 ? - _arguments["random-population"].as>() : - vector{}, + _arguments["random-population"].as>() : + std::vector{}, _arguments.count("population-from-file") > 0 ? - _arguments["population-from-file"].as>() : - vector{}, + _arguments["population-from-file"].as>() : + std::vector{}, }; } Population PopulationFactory::build( Options const& _options, - shared_ptr _fitnessMetric + std::shared_ptr _fitnessMetric ) { Population population = buildFromStrings(_options.population, _fitnessMetric); @@ -316,19 +315,19 @@ Population PopulationFactory::build( _fitnessMetric ); - for (string const& populationFilePath: _options.populationFromFile) + for (std::string const& populationFilePath: _options.populationFromFile) population = std::move(population) + buildFromFile(populationFilePath, _fitnessMetric); return population; } Population PopulationFactory::buildFromStrings( - vector const& _geneSequences, - shared_ptr _fitnessMetric + std::vector const& _geneSequences, + std::shared_ptr _fitnessMetric ) { - vector chromosomes; - for (string const& geneSequence: _geneSequences) + std::vector chromosomes; + for (std::string const& geneSequence: _geneSequences) chromosomes.emplace_back(geneSequence); return Population(std::move(_fitnessMetric), std::move(chromosomes)); @@ -338,7 +337,7 @@ Population PopulationFactory::buildRandom( size_t _populationSize, size_t _minChromosomeLength, size_t _maxChromosomeLength, - shared_ptr _fitnessMetric + std::shared_ptr _fitnessMetric ) { return Population::makeRandom( @@ -350,8 +349,8 @@ Population PopulationFactory::buildRandom( } Population PopulationFactory::buildFromFile( - string const& _filePath, - shared_ptr _fitnessMetric + std::string const& _filePath, + std::shared_ptr _fitnessMetric ) { return buildFromStrings(readLinesFromFile(_filePath), std::move(_fitnessMetric)); @@ -364,14 +363,14 @@ ProgramCacheFactory::Options ProgramCacheFactory::Options::fromCommandLine(po::v }; } -vector> ProgramCacheFactory::build( +std::vector> ProgramCacheFactory::build( Options const& _options, - vector _programs + std::vector _programs ) { - vector> programCaches; + std::vector> programCaches; for (Program& program: _programs) - programCaches.push_back(_options.programCacheEnabled ? make_shared(std::move(program)) : nullptr); + programCaches.push_back(_options.programCacheEnabled ? std::make_shared(std::move(program)) : nullptr); return programCaches; } @@ -379,28 +378,28 @@ vector> ProgramCacheFactory::build( ProgramFactory::Options ProgramFactory::Options::fromCommandLine(po::variables_map const& _arguments) { return { - _arguments["input-files"].as>(), - _arguments["prefix"].as(), + _arguments["input-files"].as>(), + _arguments["prefix"].as(), }; } -vector ProgramFactory::build(Options const& _options) +std::vector ProgramFactory::build(Options const& _options) { - vector inputPrograms; + std::vector inputPrograms; for (auto& path: _options.inputFiles) { CharStream sourceCode = loadSource(path); - variant programOrErrors = Program::load(sourceCode); - if (holds_alternative(programOrErrors)) + std::variant programOrErrors = Program::load(sourceCode); + if (std::holds_alternative(programOrErrors)) { - SourceReferenceFormatter{cerr, SingletonCharStreamProvider(sourceCode), true, false} - .printErrorInformation(get(programOrErrors)); - cerr << endl; + SourceReferenceFormatter{std::cerr, SingletonCharStreamProvider(sourceCode), true, false} + .printErrorInformation(std::get(programOrErrors)); + std::cerr << std::endl; assertThrow(false, InvalidProgram, "Failed to load program " + path); } - get(programOrErrors).optimise(Chromosome(_options.prefix).optimisationSteps()); - inputPrograms.push_back(std::move(get(programOrErrors))); + std::get(programOrErrors).optimise(Chromosome(_options.prefix).optimisationSteps()); + inputPrograms.push_back(std::move(std::get(programOrErrors))); } return inputPrograms; @@ -410,13 +409,13 @@ CharStream ProgramFactory::loadSource(boost::filesystem::path const& _sourcePath { assertThrow(boost::filesystem::exists(_sourcePath), MissingFile, "Source file does not exist: " + _sourcePath.string()); - string sourceCode = readFileAsString(_sourcePath); + std::string sourceCode = readFileAsString(_sourcePath); return CharStream(sourceCode, _sourcePath.string()); } void Phaser::main(int _argc, char** _argv) { - optional arguments = parseCommandLine(_argc, _argv); + std::optional arguments = parseCommandLine(_argc, _argv); if (!arguments.has_value()) return; @@ -447,10 +446,10 @@ Phaser::CommandLineDescription Phaser::buildCommandLineDescription() po::options_description generalDescription("GENERAL", lineLength, minDescriptionLength); generalDescription.add_options() ("help", "Show help message and exit.") - ("input-files", po::value>()->required()->value_name(""), "Input files.") + ("input-files", po::value>()->required()->value_name(""), "Input files.") ( "prefix", - po::value()->value_name("")->default_value(""), + po::value()->value_name("")->default_value(""), "Initial optimisation steps automatically applied to every input program.\n" "The result is treated as if it was the actual input, i.e. the steps are not considered " "a part of the chromosomes and cannot be mutated. The values of relative metric values " @@ -615,24 +614,24 @@ Phaser::CommandLineDescription Phaser::buildCommandLineDescription() populationDescription.add_options() ( "population", - po::value>()->multitoken()->value_name(""), + po::value>()->multitoken()->value_name(""), "List of chromosomes to be included in the initial population. " "You can specify multiple values separated with spaces or invoke the option multiple times " "and all the values will be included." ) ( "random-population", - po::value>()->value_name(""), + po::value>()->value_name(""), "The number of randomly generated chromosomes to be included in the initial population." ) ( "population-from-file", - po::value>()->value_name(""), + po::value>()->value_name(""), "A text file with a list of chromosomes (one per line) to be included in the initial population." ) ( "population-autosave", - po::value()->value_name(""), + po::value()->value_name(""), "If specified, the population is saved in the specified file after each round. (default=autosave disabled)" ) ; @@ -756,7 +755,7 @@ Phaser::CommandLineDescription Phaser::buildCommandLineDescription() return {keywordDescription, positionalDescription}; } -optional Phaser::parseCommandLine(int _argc, char** _argv) +std::optional Phaser::parseCommandLine(int _argc, char** _argv) { auto [keywordDescription, positionalDescription] = buildCommandLineDescription(); @@ -769,8 +768,8 @@ optional Phaser::parseCommandLine(int _argc, char** _argv) if (arguments.count("help") > 0) { - cout << keywordDescription << endl; - return nullopt; + std::cout << keywordDescription << std::endl; + return std::nullopt; } if (arguments.count("input-files") == 0) @@ -789,14 +788,14 @@ void Phaser::initialiseRNG(po::variables_map const& _arguments) SimulationRNG::reset(seed); if (_arguments["show-seed"].as()) - cout << "Random seed: " << seed << endl; + std::cout << "Random seed: " << seed << std::endl; } AlgorithmRunner::Options Phaser::buildAlgorithmRunnerOptions(po::variables_map const& _arguments) { return { - _arguments.count("rounds") > 0 ? static_cast>(_arguments["rounds"].as()) : nullopt, - _arguments.count("population-autosave") > 0 ? static_cast>(_arguments["population-autosave"].as()) : nullopt, + _arguments.count("rounds") > 0 ? static_cast>(_arguments["rounds"].as()) : std::nullopt, + _arguments.count("population-autosave") > 0 ? static_cast>(_arguments["population-autosave"].as()) : std::nullopt, !_arguments["no-randomise-duplicates"].as(), _arguments["min-chromosome-length"].as(), _arguments["max-chromosome-length"].as(), @@ -814,10 +813,10 @@ void Phaser::runPhaser(po::variables_map const& _arguments) auto metricOptions = FitnessMetricFactory::Options::fromCommandLine(_arguments); auto populationOptions = PopulationFactory::Options::fromCommandLine(_arguments); - vector programs = ProgramFactory::build(programOptions); - vector> programCaches = ProgramCacheFactory::build(cacheOptions, programs); + std::vector programs = ProgramFactory::build(programOptions); + std::vector> programCaches = ProgramCacheFactory::build(cacheOptions, programs); CodeWeights codeWeights = CodeWeightFactory::buildFromCommandLine(_arguments); - unique_ptr fitnessMetric = FitnessMetricFactory::build( + std::unique_ptr fitnessMetric = FitnessMetricFactory::build( metricOptions, programs, programCaches, @@ -834,51 +833,51 @@ void Phaser::runPhaser(po::variables_map const& _arguments) void Phaser::runAlgorithm( po::variables_map const& _arguments, Population _population, - vector> _programCaches + std::vector> _programCaches ) { auto algorithmOptions = GeneticAlgorithmFactory::Options::fromCommandLine(_arguments); - unique_ptr geneticAlgorithm = GeneticAlgorithmFactory::build( + std::unique_ptr geneticAlgorithm = GeneticAlgorithmFactory::build( algorithmOptions, _population.individuals().size() ); - AlgorithmRunner algorithmRunner(std::move(_population), std::move(_programCaches), buildAlgorithmRunnerOptions(_arguments), cout); + AlgorithmRunner algorithmRunner(std::move(_population), std::move(_programCaches), buildAlgorithmRunnerOptions(_arguments), std::cout); algorithmRunner.run(*geneticAlgorithm); } void Phaser::printOptimisedProgramsOrASTs( po::variables_map const& _arguments, Population const& _population, - vector _programs, + std::vector _programs, PhaserMode phaserMode ) { assert(phaserMode == PhaserMode::PrintOptimisedPrograms || phaserMode == PhaserMode::PrintOptimisedASTs); - assert(_programs.size() == _arguments["input-files"].as>().size()); + assert(_programs.size() == _arguments["input-files"].as>().size()); if (_population.individuals().size() == 0) { - cout << "" << endl; + std::cout << "" << std::endl; return; } - vector const& paths = _arguments["input-files"].as>(); + std::vector const& paths = _arguments["input-files"].as>(); for (auto& individual: _population.individuals()) { - cout << "Chromosome: " << individual.chromosome << endl; + std::cout << "Chromosome: " << individual.chromosome << std::endl; for (size_t i = 0; i < _programs.size(); ++i) { for (size_t j = 0; j < _arguments["chromosome-repetitions"].as(); ++j) _programs[i].optimise(individual.chromosome.optimisationSteps()); - cout << "Program: " << paths[i] << endl; + std::cout << "Program: " << paths[i] << std::endl; if (phaserMode == PhaserMode::PrintOptimisedPrograms) - cout << _programs[i] << endl; + std::cout << _programs[i] << std::endl; else - cout << _programs[i].toJson() << endl; + std::cout << _programs[i].toJson() << std::endl; } } } diff --git a/tools/yulPhaser/Population.cpp b/tools/yulPhaser/Population.cpp index d4fe1f0bd..e669dafe5 100644 --- a/tools/yulPhaser/Population.cpp +++ b/tools/yulPhaser/Population.cpp @@ -28,7 +28,6 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::langutil; using namespace solidity::util; @@ -37,12 +36,12 @@ using namespace solidity::phaser; namespace solidity::phaser { -ostream& operator<<(ostream& _stream, Individual const& _individual); -ostream& operator<<(ostream& _stream, Population const& _population); +std::ostream& operator<<(std::ostream& _stream, Individual const& _individual); +std::ostream& operator<<(std::ostream& _stream, Population const& _population); } -ostream& phaser::operator<<(ostream& _stream, Individual const& _individual) +std::ostream& phaser::operator<<(std::ostream& _stream, Individual const& _individual) { _stream << _individual.fitness << " " << _individual.chromosome; @@ -59,12 +58,12 @@ bool phaser::isFitter(Individual const& a, Individual const& b) } Population Population::makeRandom( - shared_ptr _fitnessMetric, + std::shared_ptr _fitnessMetric, size_t _size, - function _chromosomeLengthGenerator + std::function _chromosomeLengthGenerator ) { - vector chromosomes; + std::vector chromosomes; for (size_t i = 0; i < _size; ++i) chromosomes.push_back(Chromosome::makeRandom(_chromosomeLengthGenerator())); @@ -72,7 +71,7 @@ Population Population::makeRandom( } Population Population::makeRandom( - shared_ptr _fitnessMetric, + std::shared_ptr _fitnessMetric, size_t _size, size_t _minChromosomeLength, size_t _maxChromosomeLength @@ -87,25 +86,25 @@ Population Population::makeRandom( Population Population::select(Selection const& _selection) const { - vector selectedIndividuals; + std::vector selectedIndividuals; for (size_t i: _selection.materialise(m_individuals.size())) selectedIndividuals.emplace_back(m_individuals[i]); return Population(m_fitnessMetric, selectedIndividuals); } -Population Population::mutate(Selection const& _selection, function _mutation) const +Population Population::mutate(Selection const& _selection, std::function _mutation) const { - vector mutatedIndividuals; + std::vector mutatedIndividuals; for (size_t i: _selection.materialise(m_individuals.size())) mutatedIndividuals.emplace_back(_mutation(m_individuals[i].chromosome), *m_fitnessMetric); return Population(m_fitnessMetric, mutatedIndividuals); } -Population Population::crossover(PairSelection const& _selection, function _crossover) const +Population Population::crossover(PairSelection const& _selection, std::function _crossover) const { - vector crossedIndividuals; + std::vector crossedIndividuals; for (auto const& [i, j]: _selection.materialise(m_individuals.size())) { auto childChromosome = _crossover( @@ -118,27 +117,27 @@ Population Population::crossover(PairSelection const& _selection, function Population::symmetricCrossoverWithRemainder( +std::tuple Population::symmetricCrossoverWithRemainder( PairSelection const& _selection, - function _symmetricCrossover + std::function _symmetricCrossover ) const { - vector indexSelected(m_individuals.size(), false); + std::vector indexSelected(m_individuals.size(), false); - vector crossedIndividuals; + std::vector crossedIndividuals; for (auto const& [i, j]: _selection.materialise(m_individuals.size())) { auto children = _symmetricCrossover( m_individuals[i].chromosome, m_individuals[j].chromosome ); - crossedIndividuals.emplace_back(std::move(get<0>(children)), *m_fitnessMetric); - crossedIndividuals.emplace_back(std::move(get<1>(children)), *m_fitnessMetric); + crossedIndividuals.emplace_back(std::move(std::get<0>(children)), *m_fitnessMetric); + crossedIndividuals.emplace_back(std::move(std::get<1>(children)), *m_fitnessMetric); indexSelected[i] = true; indexSelected[j] = true; } - vector remainder; + std::vector remainder; for (size_t i = 0; i < indexSelected.size(); ++i) if (!indexSelected[i]) remainder.emplace_back(m_individuals[i]); @@ -166,7 +165,7 @@ Population operator+(Population _a, Population _b) Population Population::combine(std::tuple _populationPair) { - return get<0>(_populationPair) + get<1>(_populationPair); + return std::get<0>(_populationPair) + std::get<1>(_populationPair); } bool Population::operator==(Population const& _other) const @@ -177,28 +176,28 @@ bool Population::operator==(Population const& _other) const return m_individuals == _other.m_individuals && m_fitnessMetric == _other.m_fitnessMetric; } -ostream& phaser::operator<<(ostream& _stream, Population const& _population) +std::ostream& phaser::operator<<(std::ostream& _stream, Population const& _population) { auto individual = _population.m_individuals.begin(); for (; individual != _population.m_individuals.end(); ++individual) - _stream << *individual << endl; + _stream << *individual << std::endl; return _stream; } -vector Population::chromosomesToIndividuals( +std::vector Population::chromosomesToIndividuals( FitnessMetric& _fitnessMetric, - vector _chromosomes + std::vector _chromosomes ) { - vector individuals; + std::vector individuals; for (auto& chromosome: _chromosomes) individuals.emplace_back(std::move(chromosome), _fitnessMetric); return individuals; } -vector Population::sortedIndividuals(vector _individuals) +std::vector Population::sortedIndividuals(std::vector _individuals) { sort(_individuals.begin(), _individuals.end(), isFitter); return _individuals; diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index f24f5e03f..00abcc8e5 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -45,7 +45,6 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::langutil; using namespace solidity::yul; @@ -55,39 +54,39 @@ using namespace solidity::phaser; namespace solidity::phaser { -ostream& operator<<(ostream& _stream, Program const& _program); +std::ostream& operator<<(std::ostream& _stream, Program const& _program); } Program::Program(Program const& program): - m_ast(make_unique(get(ASTCopier{}(*program.m_ast)))), + m_ast(std::make_unique(std::get(ASTCopier{}(*program.m_ast)))), m_dialect{program.m_dialect}, m_nameDispenser(program.m_nameDispenser) { } -variant Program::load(CharStream& _sourceCode) +std::variant Program::load(CharStream& _sourceCode) { // ASSUMPTION: parseSource() rewinds the stream on its own Dialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}); - variant, ErrorList> astOrErrors = parseObject(dialect, _sourceCode); - if (holds_alternative(astOrErrors)) - return get(astOrErrors); + std::variant, ErrorList> astOrErrors = parseObject(dialect, _sourceCode); + if (std::holds_alternative(astOrErrors)) + return std::get(astOrErrors); - variant, ErrorList> analysisInfoOrErrors = analyzeAST( + std::variant, ErrorList> analysisInfoOrErrors = analyzeAST( dialect, - *get>(astOrErrors) + *std::get>(astOrErrors) ); - if (holds_alternative(analysisInfoOrErrors)) - return get(analysisInfoOrErrors); + if (std::holds_alternative(analysisInfoOrErrors)) + return std::get(analysisInfoOrErrors); Program program( dialect, disambiguateAST( dialect, - *get>(astOrErrors), - *get>(analysisInfoOrErrors) + *std::get>(astOrErrors), + *std::get>(analysisInfoOrErrors) ) ); program.optimise({ @@ -99,30 +98,30 @@ variant Program::load(CharStream& _sourceCode) return program; } -void Program::optimise(vector const& _optimisationSteps) +void Program::optimise(std::vector const& _optimisationSteps) { m_ast = applyOptimisationSteps(m_dialect, m_nameDispenser, std::move(m_ast), _optimisationSteps); } -ostream& phaser::operator<<(ostream& _stream, Program const& _program) +std::ostream& phaser::operator<<(std::ostream& _stream, Program const& _program) { return _stream << AsmPrinter()(*_program.m_ast); } -string Program::toJson() const +std::string Program::toJson() const { Json serializedAst = AsmJsonConverter(0)(*m_ast); return jsonPrettyPrint(removeNullMembers(std::move(serializedAst))); } -variant, ErrorList> Program::parseObject(Dialect const& _dialect, CharStream _source) +std::variant, ErrorList> Program::parseObject(Dialect const& _dialect, CharStream _source) { ErrorList errors; ErrorReporter errorReporter(errors); - auto scanner = make_shared(_source); + auto scanner = std::make_shared(_source); ObjectParser parser(errorReporter, _dialect); - shared_ptr object = parser.parse(scanner, false); + std::shared_ptr object = parser.parse(scanner, false); if (object == nullptr || !errorReporter.errors().empty()) // NOTE: It's possible to get errors even if the returned object is non-null. // For example when there are errors in a nested object. @@ -150,16 +149,16 @@ variant, ErrorList> Program::parseObject(Dialect const& _diale // The public API of the class does not provide access to the smart pointer so it won't be hard // to switch to shared_ptr if the copying turns out to be an issue (though it would be better // to refactor ObjectParser and Object to use unique_ptr instead). - auto astCopy = make_unique(get(ASTCopier{}(*selectedObject->code))); + auto astCopy = std::make_unique(std::get(ASTCopier{}(*selectedObject->code))); - return variant, ErrorList>(std::move(astCopy)); + return std::variant, ErrorList>(std::move(astCopy)); } -variant, ErrorList> Program::analyzeAST(Dialect const& _dialect, Block const& _ast) +std::variant, ErrorList> Program::analyzeAST(Dialect const& _dialect, Block const& _ast) { ErrorList errors; ErrorReporter errorReporter(errors); - auto analysisInfo = make_unique(); + auto analysisInfo = std::make_unique(); AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect); bool analysisSuccessful = analyzer.analyze(_ast); @@ -167,31 +166,31 @@ variant, ErrorList> Program::analyzeAST(Dialect cons return errors; assert(errorReporter.errors().empty()); - return variant, ErrorList>(std::move(analysisInfo)); + return std::variant, ErrorList>(std::move(analysisInfo)); } -unique_ptr Program::disambiguateAST( +std::unique_ptr Program::disambiguateAST( Dialect const& _dialect, Block const& _ast, AsmAnalysisInfo const& _analysisInfo ) { - set const externallyUsedIdentifiers = {}; + std::set const externallyUsedIdentifiers = {}; Disambiguator disambiguator(_dialect, _analysisInfo, externallyUsedIdentifiers); - return make_unique(get(disambiguator(_ast))); + return std::make_unique(std::get(disambiguator(_ast))); } -unique_ptr Program::applyOptimisationSteps( +std::unique_ptr Program::applyOptimisationSteps( Dialect const& _dialect, NameDispenser& _nameDispenser, - unique_ptr _ast, - vector const& _optimisationSteps + std::unique_ptr _ast, + std::vector const& _optimisationSteps ) { // An empty set of reserved identifiers. It could be a constructor parameter but I don't // think it would be useful in this tool. Other tools (like yulopti) have it empty too. - set const externallyUsedIdentifiers = {}; + std::set const externallyUsedIdentifiers = {}; OptimiserStepContext context{ _dialect, _nameDispenser, @@ -199,7 +198,7 @@ unique_ptr Program::applyOptimisationSteps( frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment }; - for (string const& step: _optimisationSteps) + for (std::string const& step: _optimisationSteps) OptimiserSuite::allSteps().at(step)->run(context, *_ast); return _ast; diff --git a/tools/yulPhaser/ProgramCache.cpp b/tools/yulPhaser/ProgramCache.cpp index 351532aa7..f8fae50fa 100644 --- a/tools/yulPhaser/ProgramCache.cpp +++ b/tools/yulPhaser/ProgramCache.cpp @@ -22,7 +22,6 @@ #include -using namespace std; using namespace solidity::yul; using namespace solidity::phaser; @@ -51,16 +50,16 @@ bool CacheStats::operator==(CacheStats const& _other) const } Program ProgramCache::optimiseProgram( - string const& _abbreviatedOptimisationSteps, - size_t _repetitionCount + std::string const& _abbreviatedOptimisationSteps, + std::size_t _repetitionCount ) { - string targetOptimisations = _abbreviatedOptimisationSteps; - for (size_t i = 1; i < _repetitionCount; ++i) + std::string targetOptimisations = _abbreviatedOptimisationSteps; + for (std::size_t i = 1; i < _repetitionCount; ++i) targetOptimisations += _abbreviatedOptimisationSteps; - size_t prefixSize = 0; - for (size_t i = 1; i <= targetOptimisations.size(); ++i) + std::size_t prefixSize = 0; + for (std::size_t i = 1; i <= targetOptimisations.size(); ++i) { auto const& pair = m_entries.find(targetOptimisations.substr(0, i)); if (pair != m_entries.end()) @@ -79,9 +78,9 @@ Program ProgramCache::optimiseProgram( m_entries.at(targetOptimisations.substr(0, prefixSize)).program ); - for (size_t i = prefixSize + 1; i <= targetOptimisations.size(); ++i) + for (std::size_t i = prefixSize + 1; i <= targetOptimisations.size(); ++i) { - string stepName = OptimiserSuite::stepAbbreviationToNameMap().at(targetOptimisations[i - 1]); + std::string stepName = OptimiserSuite::stepAbbreviationToNameMap().at(targetOptimisations[i - 1]); intermediateProgram.optimise({stepName}); m_entries.insert({targetOptimisations.substr(0, i), {intermediateProgram, m_currentRound}}); @@ -91,7 +90,7 @@ Program ProgramCache::optimiseProgram( return intermediateProgram; } -void ProgramCache::startRound(size_t _roundNumber) +void ProgramCache::startRound(std::size_t _roundNumber) { assert(_roundNumber > m_currentRound); m_currentRound = _roundNumber; @@ -113,7 +112,7 @@ void ProgramCache::clear() m_currentRound = 0; } -Program const* ProgramCache::find(string const& _abbreviatedOptimisationSteps) const +Program const* ProgramCache::find(std::string const& _abbreviatedOptimisationSteps) const { auto const& pair = m_entries.find(_abbreviatedOptimisationSteps); if (pair == m_entries.end()) @@ -132,18 +131,18 @@ CacheStats ProgramCache::gatherStats() const }; } -size_t ProgramCache::calculateTotalCachedCodeSize() const +std::size_t ProgramCache::calculateTotalCachedCodeSize() const { - size_t size = 0; + std::size_t size = 0; for (auto const& pair: m_entries) size += pair.second.program.codeSize(CacheStats::StorageWeights); return size; } -map ProgramCache::countRoundEntries() const +std::map ProgramCache::countRoundEntries() const { - map counts; + std::map counts; for (auto& pair: m_entries) if (counts.find(pair.second.roundNumber) != counts.end()) ++counts.at(pair.second.roundNumber); diff --git a/tools/yulPhaser/Selections.cpp b/tools/yulPhaser/Selections.cpp index 5c5570645..ca2cefeb4 100644 --- a/tools/yulPhaser/Selections.cpp +++ b/tools/yulPhaser/Selections.cpp @@ -23,14 +23,13 @@ #include #include -using namespace std; using namespace solidity::phaser; -vector RangeSelection::materialise(size_t _poolSize) const +std::vector RangeSelection::materialise(size_t _poolSize) const { - size_t beginIndex = static_cast(round(double(_poolSize) * m_startPercent)); - size_t endIndex = static_cast(round(double(_poolSize) * m_endPercent)); - vector selection; + size_t beginIndex = static_cast(std::round(double(_poolSize) * m_startPercent)); + size_t endIndex = static_cast(std::round(double(_poolSize) * m_endPercent)); + std::vector selection; for (size_t i = beginIndex; i < endIndex; ++i) selection.push_back(i); @@ -38,31 +37,31 @@ vector RangeSelection::materialise(size_t _poolSize) const return selection; } -vector MosaicSelection::materialise(size_t _poolSize) const +std::vector MosaicSelection::materialise(size_t _poolSize) const { - size_t count = static_cast(round(double(_poolSize) * m_selectionSize)); + size_t count = static_cast(std::round(double(_poolSize) * m_selectionSize)); - vector selection; + std::vector selection; for (size_t i = 0; i < count; ++i) - selection.push_back(min(m_pattern[i % m_pattern.size()], _poolSize - 1)); + selection.push_back(std::min(m_pattern[i % m_pattern.size()], _poolSize - 1)); return selection; } -vector RandomSelection::materialise(size_t _poolSize) const +std::vector RandomSelection::materialise(size_t _poolSize) const { - size_t count = static_cast(round(double(_poolSize) * m_selectionSize)); + size_t count = static_cast(std::round(double(_poolSize) * m_selectionSize)); - vector selection; + std::vector selection; for (size_t i = 0; i < count; ++i) selection.push_back(SimulationRNG::uniformInt(0, _poolSize - 1)); return selection; } -vector RandomSubset::materialise(size_t _poolSize) const +std::vector RandomSubset::materialise(size_t _poolSize) const { - vector selection; + std::vector selection; for (size_t index = 0; index < _poolSize; ++index) if (SimulationRNG::bernoulliTrial(m_selectionChance)) selection.push_back(index); diff --git a/tools/yulPhaser/SimulationRNG.cpp b/tools/yulPhaser/SimulationRNG.cpp index 5fca4d99e..2306db63a 100644 --- a/tools/yulPhaser/SimulationRNG.cpp +++ b/tools/yulPhaser/SimulationRNG.cpp @@ -28,7 +28,6 @@ #include #include -using namespace std; using namespace solidity; using namespace solidity::phaser; @@ -51,7 +50,7 @@ size_t SimulationRNG::binomialInt(size_t _numTrials, double _successProbability) { // NOTE: binomial_distribution would not work because it internally tries to use abs() // and fails to compile due to ambiguous conversion. - assert(_numTrials <= static_cast(numeric_limits::max())); + assert(_numTrials <= static_cast(std::numeric_limits::max())); boost::random::binomial_distribution distribution(static_cast(_numTrials), _successProbability); return static_cast(distribution(s_generator)); @@ -62,5 +61,5 @@ uint32_t SimulationRNG::generateSeed() // This is not a secure way to seed the generator but it's good enough for simulation purposes. // The only thing that matters for us is that the sequence is different on each run and that // it fits the expected distribution. It does not have to be 100% unpredictable. - return static_cast(time(nullptr)); + return static_cast(std::time(nullptr)); } From eb4b103ddaf0afe3f3ff82ccf1b4897e6e244ca4 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 17 May 2024 16:41:45 +0200 Subject: [PATCH 0121/1340] Remove included directories check for using std --- scripts/check_style.sh | 42 +----------------------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/scripts/check_style.sh b/scripts/check_style.sh index e9d470b76..dbe470c1a 100755 --- a/scripts/check_style.sh +++ b/scripts/check_style.sh @@ -20,44 +20,6 @@ EXCLUDE_FILES=( EXCLUDE_FILES_JOINED=$(printf "%s\|" "${EXCLUDE_FILES[@]}") EXCLUDE_FILES_JOINED=${EXCLUDE_FILES_JOINED%??} -NAMESPACE_STD_FREE_FILES=( - libevmasm/* - liblangutil/* - libsmtutil/* - libsolc/* - libsolidity/analysis/* - libsolidity/ast/* - libsolidity/codegen/ir/* - libsolidity/codegen/* - libsolidity/experimental/* - libsolidity/formal/* - libsolidity/interface/* - libsolidity/lsp/* - libsolidity/parsing/* - libsolutil/* - libyul/* - libyul/backends/evm/* - libyul/optimiser/* - solc/* - test/* - test/contracts/* - test/libevmasm/* - test/liblangutil/* - test/libsolutil/* - test/libsolidity/* - test/libsolidity/analysis/* - test/libsolidity/interface/* - test/libsolidity/util/* - test/libyul/* - test/solc/* - test/tools/* - test/tools/ossfuzz/* - test/tools/ossfuzz/protomutators/* - test/tools/yulInterpreter/* - test/yulPhaser/* - tools/yulPhaser/* -) - ( REPO_ROOT="$(dirname "$0")"/.. cd "$REPO_ROOT" || exit 1 @@ -104,9 +66,7 @@ FORMATERROR=$( # std namespace usage, test directory must also be covered. FORMATSTDERROR=$( ( - # make sure `using namespace std` is not used in INCLUDE_DIRECTORIES - # shellcheck disable=SC2068,SC2068 - grep -nIE -d skip "using namespace std;" ${NAMESPACE_STD_FREE_FILES[@]} + git grep -nIE "using namespace std;" -- '*.h' '*.cpp' ) || true ) From 3e77bdff88b241f9a88852ff73a70381e396bee8 Mon Sep 17 00:00:00 2001 From: Haoyang Ma Date: Mon, 20 May 2024 09:55:48 +0800 Subject: [PATCH 0122/1340] Update ossfuzz's README.md --- test/tools/ossfuzz/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/test/tools/ossfuzz/README.md b/test/tools/ossfuzz/README.md index dae338648..d00cb3d51 100644 --- a/test/tools/ossfuzz/README.md +++ b/test/tools/ossfuzz/README.md @@ -32,6 +32,7 @@ $ rm -rf fuzzer-build && mkdir fuzzer-build && cd fuzzer-build ## Compile protobuf C++ bindings $ protoc --proto_path=../test/tools/ossfuzz yulProto.proto --cpp_out=../test/tools/ossfuzz $ protoc --proto_path=../test/tools/ossfuzz abiV2Proto.proto --cpp_out=../test/tools/ossfuzz +$ protoc --proto_path=../test/tools/ossfuzz solProto.proto --cpp_out=../test/tools/ossfuzz ## Run cmake $ export CC=clang CXX=clang++ $ cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/libfuzzer.cmake -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:-Release} .. From 2d0783a74f241777ec01385f9ad55791449a17c4 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Sun, 19 May 2024 22:59:35 -0300 Subject: [PATCH 0123/1340] Add stopAfter setting to syntax tests --- test/libsolidity/SyntaxTest.cpp | 12 +++++++++++- test/libsolidity/SyntaxTest.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index f17898c04..f350ea462 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -51,6 +51,16 @@ SyntaxTest::SyntaxTest( if (!util::contains(compileViaYulAllowedValues, m_compileViaYul)) BOOST_THROW_EXCEPTION(std::runtime_error("Invalid compileViaYul value: " + m_compileViaYul + ".")); m_optimiseYul = m_reader.boolSetting("optimize-yul", true); + + static std::map const pipelineStages = { + {"parsing", PipelineStage::Parsing}, + {"analysis", PipelineStage::Analysis}, + {"compilation", PipelineStage::Compilation} + }; + std::string stopAfter = m_reader.stringSetting("stopAfter", "compilation"); + if (!pipelineStages.count(stopAfter)) + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid stopAfter value: " + stopAfter + ".")); + m_stopAfter = pipelineStages.at(stopAfter); } void SyntaxTest::setupCompiler(CompilerStack& _compiler) @@ -72,7 +82,7 @@ void SyntaxTest::parseAndAnalyze() { try { - runFramework(withPreamble(m_sources.sources), PipelineStage::Compilation); + runFramework(withPreamble(m_sources.sources), m_stopAfter); if (!pipelineSuccessful() && stageSuccessful(PipelineStage::Analysis) && !compiler().isExperimentalAnalysis()) { ErrorList const& errors = compiler().errors(); diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index 95df3c6cd..085a32f94 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -55,6 +55,7 @@ class SyntaxTest: public AnalysisFramework, public solidity::test::CommonSyntaxT bool m_optimiseYul{}; std::string m_compileViaYul{}; langutil::Error::Severity m_minSeverity{}; + PipelineStage m_stopAfter; }; } From 50ad425948072d74b743641eff5968e1d703881b Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Sun, 19 May 2024 23:02:57 -0300 Subject: [PATCH 0124/1340] Add tests --- test/libsolidity/syntaxTests/stopAfterAnalysisError.sol | 8 ++++++++ .../stopAfterParsingAnalysisErrorNotShowing.sol | 6 ++++++ test/libsolidity/syntaxTests/stopAfterParsingError.sol | 7 +++++++ 3 files changed, 21 insertions(+) create mode 100644 test/libsolidity/syntaxTests/stopAfterAnalysisError.sol create mode 100644 test/libsolidity/syntaxTests/stopAfterParsingAnalysisErrorNotShowing.sol create mode 100644 test/libsolidity/syntaxTests/stopAfterParsingError.sol diff --git a/test/libsolidity/syntaxTests/stopAfterAnalysisError.sol b/test/libsolidity/syntaxTests/stopAfterAnalysisError.sol new file mode 100644 index 000000000..ac74ecf3a --- /dev/null +++ b/test/libsolidity/syntaxTests/stopAfterAnalysisError.sol @@ -0,0 +1,8 @@ +contract C { + function f(uint[] x) public pure { + } +} +// ==== +// stopAfter: analysis +// ---- +// TypeError 6651: (28-36): Data location must be "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/stopAfterParsingAnalysisErrorNotShowing.sol b/test/libsolidity/syntaxTests/stopAfterParsingAnalysisErrorNotShowing.sol new file mode 100644 index 000000000..58efffea6 --- /dev/null +++ b/test/libsolidity/syntaxTests/stopAfterParsingAnalysisErrorNotShowing.sol @@ -0,0 +1,6 @@ +contract C { + uint x = address(0xabc); +} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/stopAfterParsingError.sol b/test/libsolidity/syntaxTests/stopAfterParsingError.sol new file mode 100644 index 000000000..911a28d77 --- /dev/null +++ b/test/libsolidity/syntaxTests/stopAfterParsingError.sol @@ -0,0 +1,7 @@ +contract C { + uint storage x; +} +// ==== +// stopAfter:parsing +// ---- +// ParserError 2314: (22-29): Expected identifier but got 'storage' From 31aab83b6653160effa363aac87d4669665d11e3 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 20 May 2024 13:31:52 +0200 Subject: [PATCH 0125/1340] Set release date for 0.8.26 --- Changelog.md | 2 +- docs/bugs_by_version.json | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 443259806..0837a7170 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.8.26 (unreleased) +### 0.8.26 (2024-05-21) Language Features: * Introduce a new overload ``require(bool, Error)`` that allows usage of ``require`` functions with custom errors. This feature is available in the ``via-ir`` pipeline only. diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 52b6c9f48..037a36341 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1894,6 +1894,10 @@ "bugs": [], "released": "2024-03-14" }, + "0.8.26": { + "bugs": [], + "released": "2024-05-21" + }, "0.8.3": { "bugs": [ "FullInlinerNonExpressionSplitArgumentEvaluationOrder", From 9da33a63ea9da6fa5dc1f80e5c0a7102c0f96dab Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 20 May 2024 13:35:57 +0200 Subject: [PATCH 0126/1340] Set version to 0.8.27 --- CMakeLists.txt | 2 +- Changelog.md | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91c1056ec..b1a307afb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.26") +set(PROJECT_VERSION "0.8.27") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index 0837a7170..f48fbf080 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,14 @@ +### 0.8.27 (unreleased) + +Language Features: + + +Compiler Features: + + +Bugfixes: + + ### 0.8.26 (2024-05-21) Language Features: From a8406b5692c00ad4ed7e56c9c00a4f131db06c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mati=C4=87?= Date: Tue, 21 May 2024 10:03:22 +0200 Subject: [PATCH 0127/1340] Revert "Set version to 0 8 27" --- CMakeLists.txt | 2 +- Changelog.md | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1a307afb..91c1056ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.27") +set(PROJECT_VERSION "0.8.26") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index f48fbf080..0837a7170 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,14 +1,3 @@ -### 0.8.27 (unreleased) - -Language Features: - - -Compiler Features: - - -Bugfixes: - - ### 0.8.26 (2024-05-21) Language Features: From 194d3c107945348ce9fca2192b5d77f54d12f9de Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 21 May 2024 12:08:55 +0200 Subject: [PATCH 0128/1340] Set version to 0.8.27 --- CMakeLists.txt | 2 +- Changelog.md | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91c1056ec..b1a307afb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.26") +set(PROJECT_VERSION "0.8.27") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index 0837a7170..f48fbf080 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,14 @@ +### 0.8.27 (unreleased) + +Language Features: + + +Compiler Features: + + +Bugfixes: + + ### 0.8.26 (2024-05-21) Language Features: From fe944d34f43ef1aa04fef089b6b9a96133085270 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 22 May 2024 13:01:50 +0200 Subject: [PATCH 0129/1340] Add exclusion for require with errors to chk pragma script --- scripts/docs_version_pragma_check.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/docs_version_pragma_check.sh b/scripts/docs_version_pragma_check.sh index d56bed3a1..c927cfb1e 100755 --- a/scripts/docs_version_pragma_check.sh +++ b/scripts/docs_version_pragma_check.sh @@ -154,7 +154,8 @@ SOLTMPDIR=$(mktemp -d) # We expect errors if explicitly stated, or if imports # are used (in the style guide) if ( ! grep -E "This will not compile after" "$f" >/dev/null && \ - grep -E "This will not compile|import \"" "$f" >/dev/null ) + grep -E "This will not compile|import \"" "$f" >/dev/null || \ + grep -R "This will only compile via IR" "$f" >/dev/null ) then opts=(--expect-errors) fi From 53370849855d997def412564b73ce8d2c77fd7dc Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 22 May 2024 21:10:49 +0200 Subject: [PATCH 0130/1340] formal test smod implementation corresponds to EVM smod --- test/formal/opcodes.py | 10 ++++++- test/formal/smod.py | 65 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 test/formal/smod.py diff --git a/test/formal/opcodes.py b/test/formal/opcodes.py index e091e7847..a70a26fe5 100644 --- a/test/formal/opcodes.py +++ b/test/formal/opcodes.py @@ -25,7 +25,15 @@ def ADDMOD(x, y, m): return If(m == 0, 0, Extract(x.size() - 1, 0, URem(ZeroExt(1, x) + ZeroExt(1, y), ZeroExt(1, m)))) def SMOD(x, y): - return If(y == 0, 0, x % y) + return If( + y == 0, + 0, + If( + x >= 0, + If(y >= 0, x % y, x % (-y)), + If(y >= 0, -((-x) % y), -((-x) % (-y))) + ) + ) def LT(x, y): return If(ULT(x, y), BitVecVal(1, x.size()), BitVecVal(0, x.size())) diff --git a/test/formal/smod.py b/test/formal/smod.py new file mode 100644 index 000000000..d82578d18 --- /dev/null +++ b/test/formal/smod.py @@ -0,0 +1,65 @@ +from z3 import BitVec +from rule import Rule +from opcodes import SMOD + + +n_bits = 256 +X = BitVec('X', n_bits) +Y = BitVec('Y', n_bits) + + +def smod_test(a, b, r, op=SMOD): + r""" + Tests SMOD with predefined parameters a,b against an expected result r. + """ + to_check = Rule() + to_check.require(X == a) + to_check.require(Y == b) + to_check.check(op(X, Y), r) + + +# tests from: +# https://github.com/ethereum/tests/blob/2e37a9f41167534b07e0e8f247ea934a5fe3cac9/src/GeneralStateTestsFiller/VMTests/vmArithmeticTest/smodFiller.yml +smod_test(2, 3, 2) +smod_test(-1, 2, -1) +smod_test(0, -1, 0) +smod_test(3, 0, 0) +smod_test(-2, 3, -2) +smod_test(-2, 3, -2) +smod_test(16, 0, -1, op=lambda x, y: SMOD(x, y) - 1) + +# more tests +rule = Rule() +rule.require(X == 7) +rule.require(Y == 5) +rule.check(SMOD(X, Y), 2) + +rule = Rule() +rule.require(X == 7) +rule.require(Y == 5) +rule.check(SMOD(X, Y), 2) + +rule = Rule() +rule.require(X == -7) +rule.require(Y == 5) +rule.check(SMOD(X, Y), -2) + +rule = Rule() +rule.require(X == 7) +rule.require(Y == -5) +rule.check(SMOD(X, Y), 2) + +rule = Rule() +rule.require(X == -7) +rule.require(Y == -5) +rule.check(SMOD(X, Y), -2) + +for k in [-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7]: + for i in [-13, -12, -11, 10, -7, -2, 1, 0, 1, 2, 7, 10, 11, 12, 13]: + rule = Rule() + rule.require(X == i) + rule.require(Y == k) + if k != 0: + rule.check(SMOD(X, Y) % Y, X % Y) + else: + rule.check(SMOD(X, Y), 0) From 6de168040227fe6b2400736812a38f2b305628dd Mon Sep 17 00:00:00 2001 From: Pawel Gebal Date: Thu, 9 May 2024 13:46:05 +0200 Subject: [PATCH 0131/1340] Remove UnderOverflow verification target for BMC engine --- libsolidity/formal/BMC.cpp | 75 ++++++------------- libsolidity/formal/ModelCheckerSettings.h | 2 +- .../blockchain_state/transfer_1.sol | 2 +- .../constructor_state_variable_init.sol | 2 +- .../constructor_state_variable_init.sol | 1 + ...onstructor_state_variable_init_asserts.sol | 1 + ...tructor_state_variable_init_chain_tree.sol | 1 + .../smtCheckerTests/operators/mod.sol | 1 + .../smtCheckerTests/operators/mod_signed.sol | 2 +- .../user_defined_operations_on_constants.sol | 2 +- ...r_defined_operations_on_constants_fail.sol | 1 + ...rator_matches_equivalent_function_call.sol | 7 +- .../unchecked/flipping_sign_tests.sol | 2 + 13 files changed, 41 insertions(+), 58 deletions(-) diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 97dd7050f..2bb794cde 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -569,11 +569,18 @@ void BMC::endVisit(UnaryOperation const& _op) return; if (_op.getOperator() == Token::Sub && smt::isInteger(*_op.annotation().type)) + { + addVerificationTarget( + VerificationTargetType::Underflow, + expr(_op), + &_op + ); addVerificationTarget( - VerificationTargetType::UnderOverflow, + VerificationTargetType::Overflow, expr(_op), &_op ); + } } void BMC::endVisit(BinaryOperation const& _op) @@ -813,32 +820,29 @@ std::pair BMC::arithmeticOperation( if (_op == Token::Mod) return values; - VerificationTargetType type; // The order matters here: // If _op is Div and intType is signed, we only care about overflow. if (_op == Token::Div) { if (intType->isSigned()) // Signed division can only overflow. - type = VerificationTargetType::Overflow; + addVerificationTarget(VerificationTargetType::Overflow, values.second, &_expression); else // Unsigned division cannot underflow/overflow. return values; } else if (intType->isSigned()) - type = VerificationTargetType::UnderOverflow; + { + addVerificationTarget(VerificationTargetType::Overflow, values.second, &_expression); + addVerificationTarget(VerificationTargetType::Underflow, values.second, &_expression); + } else if (_op == Token::Sub) - type = VerificationTargetType::Underflow; + addVerificationTarget(VerificationTargetType::Underflow, values.second, &_expression); else if (_op == Token::Add || _op == Token::Mul) - type = VerificationTargetType::Overflow; + addVerificationTarget(VerificationTargetType::Overflow, values.second, &_expression); else solAssert(false, ""); - addVerificationTarget( - type, - values.second, - &_expression - ); return values; } @@ -919,6 +923,12 @@ void BMC::checkVerificationTargets() void BMC::checkVerificationTarget(BMCVerificationTarget& _target) { + if ( + m_solvedTargets.count(_target.expression) && + m_solvedTargets.at(_target.expression).count(_target.type) + ) + return; + switch (_target.type) { case VerificationTargetType::ConstantCondition: @@ -930,10 +940,6 @@ void BMC::checkVerificationTarget(BMCVerificationTarget& _target) case VerificationTargetType::Overflow: checkOverflow(_target); break; - case VerificationTargetType::UnderOverflow: - checkUnderflow(_target); - checkOverflow(_target); - break; case VerificationTargetType::DivByZero: checkDivByZero(_target); break; @@ -961,19 +967,10 @@ void BMC::checkConstantCondition(BMCVerificationTarget& _target) void BMC::checkUnderflow(BMCVerificationTarget& _target) { solAssert( - _target.type == VerificationTargetType::Underflow || - _target.type == VerificationTargetType::UnderOverflow, + _target.type == VerificationTargetType::Underflow, "" ); - if ( - m_solvedTargets.count(_target.expression) && ( - m_solvedTargets.at(_target.expression).count(VerificationTargetType::Underflow) || - m_solvedTargets.at(_target.expression).count(VerificationTargetType::UnderOverflow) - ) - ) - return; - auto const* intType = dynamic_cast(_target.expression->annotation().type); if (!intType) intType = TypeProvider::uint256(); @@ -994,19 +991,10 @@ void BMC::checkUnderflow(BMCVerificationTarget& _target) void BMC::checkOverflow(BMCVerificationTarget& _target) { solAssert( - _target.type == VerificationTargetType::Overflow || - _target.type == VerificationTargetType::UnderOverflow, + _target.type == VerificationTargetType::Overflow, "" ); - if ( - m_solvedTargets.count(_target.expression) && ( - m_solvedTargets.at(_target.expression).count(VerificationTargetType::Overflow) || - m_solvedTargets.at(_target.expression).count(VerificationTargetType::UnderOverflow) - ) - ) - return; - auto const* intType = dynamic_cast(_target.expression->annotation().type); if (!intType) intType = TypeProvider::uint256(); @@ -1028,12 +1016,6 @@ void BMC::checkDivByZero(BMCVerificationTarget& _target) { solAssert(_target.type == VerificationTargetType::DivByZero, ""); - if ( - m_solvedTargets.count(_target.expression) && - m_solvedTargets.at(_target.expression).count(VerificationTargetType::DivByZero) - ) - return; - checkCondition( _target, _target.constraints && (_target.value == 0), @@ -1051,11 +1033,6 @@ void BMC::checkBalance(BMCVerificationTarget& _target) { solAssert(_target.type == VerificationTargetType::Balance, ""); - if ( - m_solvedTargets.count(_target.expression) && - m_solvedTargets.at(_target.expression).count(VerificationTargetType::Balance) - ) - return; checkCondition( _target, _target.constraints && _target.value, @@ -1072,12 +1049,6 @@ void BMC::checkAssert(BMCVerificationTarget& _target) { solAssert(_target.type == VerificationTargetType::Assert, ""); - if ( - m_solvedTargets.count(_target.expression) && - m_solvedTargets.at(_target.expression).count(_target.type) - ) - return; - checkCondition( _target, _target.constraints && !_target.value, diff --git a/libsolidity/formal/ModelCheckerSettings.h b/libsolidity/formal/ModelCheckerSettings.h index 0cfa370c4..3dbe472b8 100644 --- a/libsolidity/formal/ModelCheckerSettings.h +++ b/libsolidity/formal/ModelCheckerSettings.h @@ -113,7 +113,7 @@ struct ModelCheckerInvariants std::set invariants; }; -enum class VerificationTargetType { ConstantCondition, Underflow, Overflow, UnderOverflow, DivByZero, Balance, Assert, PopEmptyArray, OutOfBounds }; +enum class VerificationTargetType { ConstantCondition, Underflow, Overflow, DivByZero, Balance, Assert, PopEmptyArray, OutOfBounds }; struct ModelCheckerTargets { diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_1.sol b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_1.sol index 3118086b9..169257edf 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_1.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_1.sol @@ -12,4 +12,4 @@ contract C { // SMTIgnoreCex: yes // ---- // Warning 6328: (166-201): CHC: Assertion violation happens here. -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. \ No newline at end of file +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/bmc_coverage/branches_with_return/constructor_state_variable_init.sol b/test/libsolidity/smtCheckerTests/bmc_coverage/branches_with_return/constructor_state_variable_init.sol index c262e2481..4728a1cb0 100644 --- a/test/libsolidity/smtCheckerTests/bmc_coverage/branches_with_return/constructor_state_variable_init.sol +++ b/test/libsolidity/smtCheckerTests/bmc_coverage/branches_with_return/constructor_state_variable_init.sol @@ -39,4 +39,4 @@ contract C is B { // Warning 4661: (389-412): BMC: Assertion violation happens here. // Warning 4661: (489-513): BMC: Assertion violation happens here. // Warning 4661: (533-546): BMC: Assertion violation happens here. -// Info 6002: BMC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol index d33f9571b..594580f89 100644 --- a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol @@ -40,3 +40,4 @@ contract C is B { // Warning 6328: (489-513): CHC: Assertion violation happens here. // Warning 6328: (533-546): CHC: Assertion violation happens here. // Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol index 03b634ba9..40ae96db4 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol @@ -38,3 +38,4 @@ contract C is B { // Warning 6328: (439-463): CHC: Assertion violation happens here. // Warning 6328: (483-496): CHC: Assertion violation happens here. // Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol index e98ddcb63..638cb640d 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol @@ -42,3 +42,4 @@ contract C is B { // Warning 6328: (403-417): CHC: Assertion violation happens here. // Warning 6328: (450-463): CHC: Assertion violation happens here. // Info 1391: CHC: 6 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/mod.sol b/test/libsolidity/smtCheckerTests/operators/mod.sol index a600ef03f..bd09b8240 100644 --- a/test/libsolidity/smtCheckerTests/operators/mod.sol +++ b/test/libsolidity/smtCheckerTests/operators/mod.sol @@ -11,3 +11,4 @@ contract C { // SMTEngine: all // ---- // Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/mod_signed.sol b/test/libsolidity/smtCheckerTests/operators/mod_signed.sol index 2e640f53f..c995a158a 100644 --- a/test/libsolidity/smtCheckerTests/operators/mod_signed.sol +++ b/test/libsolidity/smtCheckerTests/operators/mod_signed.sol @@ -13,4 +13,4 @@ contract C { // ---- // Warning 6328: (131-148): CHC: Assertion violation might happen here. // Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol index c39360b65..fe12892ea 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol @@ -61,4 +61,4 @@ contract C { // SMTEngine: all // ---- // Info 1391: CHC: 21 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. - +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol index 25674513c..8afd995ea 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol @@ -77,3 +77,4 @@ contract C { // Warning 6328: (2783-2804): CHC: Assertion violation happens here. // Warning 6328: (2829-2850): CHC: Assertion violation happens here. // Info 1391: CHC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol index b734079c7..b3887bfa0 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol @@ -71,7 +71,12 @@ contract C { // Warning 6328: (2209-2235): CHC: Assertion violation might happen here. // Warning 6328: (2245-2271): CHC: Assertion violation might happen here. // Info 1391: CHC: 10 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 2661: (679-708): BMC: Overflow (resulting value larger than 32767) happens here. +// Warning 4144: (679-708): BMC: Underflow (resulting value less than -32768) happens here. +// Warning 2661: (777-806): BMC: Overflow (resulting value larger than 32767) happens here. +// Warning 2661: (953-982): BMC: Overflow (resulting value larger than 32767) happens here. +// Warning 4144: (953-982): BMC: Underflow (resulting value less than -32768) happens here. // Warning 3046: (1051-1080): BMC: Division by zero happens here. // Warning 3046: (1149-1178): BMC: Division by zero happens here. // Warning 7812: (2245-2271): BMC: Assertion violation might happen here. -// Info 6002: BMC: 6 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 10 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol b/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol index 96b415010..59a4b3d26 100644 --- a/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol +++ b/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol @@ -11,3 +11,5 @@ contract test { // ---- // Warning 6328: (110-125): CHC: Assertion violation happens here. // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 2661: (117-119): BMC: Overflow (resulting value larger than 2**255 - 1) happens here. +// Info 6002: BMC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From f87a88aeab6f93cdbc3bef3ba7a3ee74cd4b0695 Mon Sep 17 00:00:00 2001 From: Pawel Gebal Date: Wed, 22 May 2024 17:08:23 +0200 Subject: [PATCH 0132/1340] SMTChecker: Add CHC engine check for underflow and overflow in unary minus operation --- Changelog.md | 1 + libsolidity/formal/CHC.cpp | 17 +++++++++++++++++ .../constructor_state_variable_init.sol | 3 +-- .../constructor_state_variable_init_asserts.sol | 3 +-- ...nstructor_state_variable_init_chain_tree.sol | 3 +-- .../smtCheckerTests/operators/mod.sol | 3 +-- .../smtCheckerTests/operators/mod_signed.sol | 4 ++-- .../operators/unary_minus_bmc.sol | 11 +++++++++++ .../operators/unary_minus_chc.sol | 11 +++++++++++ .../user_defined_operations_on_constants.sol | 3 +-- ...ser_defined_operations_on_constants_fail.sol | 3 +-- ...perator_matches_equivalent_function_call.sol | 16 +++++++--------- .../unchecked/flipping_sign_tests.sol | 7 +++---- 13 files changed, 58 insertions(+), 27 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/operators/unary_minus_bmc.sol create mode 100644 test/libsolidity/smtCheckerTests/operators/unary_minus_chc.sol diff --git a/Changelog.md b/Changelog.md index f48fbf080..eb9d87ea8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * SMTChecker: Add CHC engine check for underflow and overflow in unary minus operation. Bugfixes: diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index b6ffd5954..c520d13f6 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -554,6 +554,23 @@ void CHC::endVisit(UnaryOperation const& _op) internalFunctionCall(funDef, std::nullopt, _op.userDefinedFunctionType(), arguments, state().thisAddress()); createReturnedExpressions(funDef, _op); + return; + } + + if ( + _op.annotation().type->category() == Type::Category::RationalNumber || + _op.annotation().type->category() == Type::Category::FixedPoint + ) + return; + + if (_op.getOperator() == Token::Sub && smt::isInteger(*_op.annotation().type)) + { + auto const* intType = dynamic_cast(_op.annotation().type); + if (!intType) + intType = TypeProvider::uint256(); + + verificationTargetEncountered(&_op, VerificationTargetType::Underflow, expr(_op) < intType->minValue()); + verificationTargetEncountered(&_op, VerificationTargetType::Overflow, expr(_op) > intType->maxValue()); } } diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol index 594580f89..88036eb55 100644 --- a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol @@ -39,5 +39,4 @@ contract C is B { // Warning 6328: (389-412): CHC: Assertion violation happens here. // Warning 6328: (489-513): CHC: Assertion violation happens here. // Warning 6328: (533-546): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol index 40ae96db4..db81b1d0f 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol @@ -37,5 +37,4 @@ contract C is B { // Warning 6328: (339-362): CHC: Assertion violation happens here. // Warning 6328: (439-463): CHC: Assertion violation happens here. // Warning 6328: (483-496): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol index 638cb640d..8fe0cb28e 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol @@ -41,5 +41,4 @@ contract C is B { // ---- // Warning 6328: (403-417): CHC: Assertion violation happens here. // Warning 6328: (450-463): CHC: Assertion violation happens here. -// Info 1391: CHC: 6 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 7 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/mod.sol b/test/libsolidity/smtCheckerTests/operators/mod.sol index bd09b8240..d12e5c49d 100644 --- a/test/libsolidity/smtCheckerTests/operators/mod.sol +++ b/test/libsolidity/smtCheckerTests/operators/mod.sol @@ -10,5 +10,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/mod_signed.sol b/test/libsolidity/smtCheckerTests/operators/mod_signed.sol index c995a158a..c34bd08e3 100644 --- a/test/libsolidity/smtCheckerTests/operators/mod_signed.sol +++ b/test/libsolidity/smtCheckerTests/operators/mod_signed.sol @@ -12,5 +12,5 @@ contract C { // SMTEngine: all // ---- // Warning 6328: (131-148): CHC: Assertion violation might happen here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Info 6002: BMC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/unary_minus_bmc.sol b/test/libsolidity/smtCheckerTests/operators/unary_minus_bmc.sol new file mode 100644 index 000000000..052554d21 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/unary_minus_bmc.sol @@ -0,0 +1,11 @@ +contract C +{ + function f(int x) public pure { + assert(x == -x); + } +} +// ==== +// SMTEngine: bmc +// ---- +// Warning 4661: (48-63): BMC: Assertion violation happens here. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/unary_minus_chc.sol b/test/libsolidity/smtCheckerTests/operators/unary_minus_chc.sol new file mode 100644 index 000000000..0d1bf972b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/unary_minus_chc.sol @@ -0,0 +1,11 @@ +contract C +{ + function f(int x) public pure { + assert(x == -x); + } +} +// ==== +// SMTEngine: chc +// ---- +// Warning 6328: (48-63): CHC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol index fe12892ea..49420440f 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol @@ -60,5 +60,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 21 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 22 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol index 8afd995ea..106a7c5f0 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol @@ -76,5 +76,4 @@ contract C { // Warning 6328: (2741-2758): CHC: Assertion violation happens here. // Warning 6328: (2783-2804): CHC: Assertion violation happens here. // Warning 6328: (2829-2850): CHC: Assertion violation happens here. -// Info 1391: CHC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 6 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol index b3887bfa0..33665ee26 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol @@ -56,27 +56,25 @@ contract C { // SMTIgnoreOS: macos // ---- // Warning 3944: (679-708): CHC: Underflow (resulting value less than -32768) might happen here. -// Warning 4984: (679-708): CHC: Overflow (resulting value larger than 32767) might happen here. -// Warning 3944: (777-806): CHC: Underflow (resulting value less than -32768) happens here. +// Warning 4984: (679-708): CHC: Overflow (resulting value larger than 32767) happens here. +// Warning 3944: (777-806): CHC: Underflow (resulting value less than -32768) might happen here. // Warning 4984: (777-806): CHC: Overflow (resulting value larger than 32767) might happen here. +// Warning 4984: (870-884): CHC: Overflow (resulting value larger than 32767) might happen here. // Warning 3944: (953-982): CHC: Underflow (resulting value less than -32768) might happen here. // Warning 4984: (953-982): CHC: Overflow (resulting value larger than 32767) might happen here. // Warning 4984: (1051-1080): CHC: Overflow (resulting value larger than 32767) might happen here. -// Warning 4281: (1051-1080): CHC: Division by zero might happen here. +// Warning 4281: (1051-1080): CHC: Division by zero happens here. // Warning 4281: (1149-1178): CHC: Division by zero might happen here. // Warning 6328: (2069-2095): CHC: Assertion violation might happen here. -// Warning 6328: (2105-2131): CHC: Assertion violation might happen here. // Warning 6328: (2141-2163): CHC: Assertion violation might happen here. -// Warning 6328: (2173-2199): CHC: Assertion violation might happen here. // Warning 6328: (2209-2235): CHC: Assertion violation might happen here. // Warning 6328: (2245-2271): CHC: Assertion violation might happen here. -// Info 1391: CHC: 10 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 2661: (679-708): BMC: Overflow (resulting value larger than 32767) happens here. +// Info 1391: CHC: 13 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. // Warning 4144: (679-708): BMC: Underflow (resulting value less than -32768) happens here. // Warning 2661: (777-806): BMC: Overflow (resulting value larger than 32767) happens here. +// Warning 4144: (777-806): BMC: Underflow (resulting value less than -32768) happens here. // Warning 2661: (953-982): BMC: Overflow (resulting value larger than 32767) happens here. // Warning 4144: (953-982): BMC: Underflow (resulting value less than -32768) happens here. -// Warning 3046: (1051-1080): BMC: Division by zero happens here. // Warning 3046: (1149-1178): BMC: Division by zero happens here. // Warning 7812: (2245-2271): BMC: Assertion violation might happen here. -// Info 6002: BMC: 10 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 8 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol b/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol index 59a4b3d26..536d2a2b4 100644 --- a/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol +++ b/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol @@ -2,14 +2,13 @@ contract test { function f() public pure returns (bool) { int256 x = -2**255; unchecked { assert(-x == x); } - assert(-x == x); // CHC apparently does not create an underflow target for unary minus + assert(-x == x); return true; } } // ==== // SMTEngine: all // ---- +// Warning 4984: (117-119): CHC: Overflow (resulting value larger than 2**255 - 1) happens here. // Warning 6328: (110-125): CHC: Assertion violation happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 2661: (117-119): BMC: Overflow (resulting value larger than 2**255 - 1) happens here. -// Info 6002: BMC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From f80d45d07f989315f6d540d629368447397a35ab Mon Sep 17 00:00:00 2001 From: Pawel Gebal Date: Fri, 24 May 2024 17:26:03 +0200 Subject: [PATCH 0133/1340] SMTChecker: Add SMTShowProvedSafe option for use in SMT checker tests --- scripts/error_codes.py | 1 - test/libsolidity/SMTCheckerTest.cpp | 8 ++++++++ test/libsolidity/SMTCheckerTest.h | 2 ++ .../smtCheckerTests/operators/compound_add.sol | 5 ++++- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 27e7b1102..8ee5cbbde 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -206,7 +206,6 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "2339", # SMTChecker, covered by CL tests "2961", # SMTChecker, covered by CL tests "6240", # SMTChecker, covered by CL tests - "9576", # SMTChecker, covered by CL tests } assert len(test_ids & white_ids) == 0, "The sets are not supposed to intersect" test_ids |= white_ids diff --git a/test/libsolidity/SMTCheckerTest.cpp b/test/libsolidity/SMTCheckerTest.cpp index 893ccb0f1..e3ec14c97 100644 --- a/test/libsolidity/SMTCheckerTest.cpp +++ b/test/libsolidity/SMTCheckerTest.cpp @@ -38,6 +38,14 @@ SMTCheckerTest::SMTCheckerTest(std::string const& _filename): SyntaxTest(_filena else BOOST_THROW_EXCEPTION(std::runtime_error("Invalid SMT external calls mode.")); + auto const& showProvedSafe = m_reader.stringSetting("SMTShowProvedSafe", "no"); + if (showProvedSafe == "no") + m_modelCheckerSettings.showProvedSafe = false; + else if (showProvedSafe == "yes") + m_modelCheckerSettings.showProvedSafe = true; + else + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid SMT \"show proved safe\" choice.")); + auto const& showUnproved = m_reader.stringSetting("SMTShowUnproved", "yes"); if (showUnproved == "no") m_modelCheckerSettings.showUnproved = false; diff --git a/test/libsolidity/SMTCheckerTest.h b/test/libsolidity/SMTCheckerTest.h index d42572dc5..aa0f92121 100644 --- a/test/libsolidity/SMTCheckerTest.h +++ b/test/libsolidity/SMTCheckerTest.h @@ -52,6 +52,8 @@ class SMTCheckerTest: public SyntaxTest Set in m_ignoreCex. SMTIgnoreInv: `yes`, `no`, where the default is `no`. Set in m_modelCheckerSettings. + SMTShowProvedSafe: `yes`, `no`, where the default is `no`. + Set in m_modelCheckerSettings. SMTShowUnproved: `yes`, `no`, where the default is `yes`. Set in m_modelCheckerSettings. SMTSolvers: `all`, `cvc4`, `z3`, `none`, where the default is `all`. diff --git a/test/libsolidity/smtCheckerTests/operators/compound_add.sol b/test/libsolidity/smtCheckerTests/operators/compound_add.sol index 7a18b1c7e..852956f03 100644 --- a/test/libsolidity/smtCheckerTests/operators/compound_add.sol +++ b/test/libsolidity/smtCheckerTests/operators/compound_add.sol @@ -10,6 +10,9 @@ contract C } // ==== // SMTEngine: all +// SMTShowProvedSafe: yes // ---- // Warning 6328: (118-133): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 9576: (90-95): CHC: Overflow (resulting value larger than 2**256 - 1) check is safe! +// Info 9576: (85-95): CHC: Overflow (resulting value larger than 2**256 - 1) check is safe! +// Info 9576: (99-114): CHC: Assertion violation check is safe! From 5240ef3ecbefc0ec29f42fc96aa4fc7683b9e41b Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 27 May 2024 10:40:08 +0200 Subject: [PATCH 0134/1340] Move type() helper function from TypeChecker to ASTUtils --- libsolidity/analysis/TypeChecker.cpp | 12 ------------ libsolidity/analysis/TypeChecker.h | 6 ------ libsolidity/ast/ASTUtils.cpp | 12 ++++++++++++ libsolidity/ast/ASTUtils.h | 6 ++++++ 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 42c98a8f0..5044414bf 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -80,18 +80,6 @@ bool TypeChecker::checkTypeRequirements(SourceUnit const& _source) return !Error::containsErrors(m_errorReporter.errors()); } -Type const* TypeChecker::type(Expression const& _expression) const -{ - solAssert(!!_expression.annotation().type, "Type requested but not present."); - return _expression.annotation().type; -} - -Type const* TypeChecker::type(VariableDeclaration const& _variable) const -{ - solAssert(!!_variable.annotation().type, "Type requested but not present."); - return _variable.annotation().type; -} - bool TypeChecker::visit(ContractDefinition const& _contract) { m_currentContract = &_contract; diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 2ef6b818b..d7998d178 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -56,12 +56,6 @@ class TypeChecker: private ASTConstVisitor /// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings bool checkTypeRequirements(SourceUnit const& _source); - /// @returns the type of an expression and asserts that it is present. - Type const* type(Expression const& _expression) const; - /// @returns the type of the given variable and throws if the type is not present - /// (this can happen for variables with non-explicit types before their types are resolved) - Type const* type(VariableDeclaration const& _variable) const; - static bool typeSupportedByOldABIEncoder(Type const& _type, bool _isLibraryCall); private: diff --git a/libsolidity/ast/ASTUtils.cpp b/libsolidity/ast/ASTUtils.cpp index 27c0833d2..7d434f896 100644 --- a/libsolidity/ast/ASTUtils.cpp +++ b/libsolidity/ast/ASTUtils.cpp @@ -95,4 +95,16 @@ Expression const* resolveOuterUnaryTuples(Expression const* _expr) return _expr; } +Type const* type(Expression const& _expression) +{ + solAssert(!!_expression.annotation().type, "Type requested but not present."); + return _expression.annotation().type; +} + +Type const* type(VariableDeclaration const& _variable) +{ + solAssert(!!_variable.annotation().type, "Type requested but not present."); + return _variable.annotation().type; +} + } diff --git a/libsolidity/ast/ASTUtils.h b/libsolidity/ast/ASTUtils.h index f6e3f0641..b31bd20d5 100644 --- a/libsolidity/ast/ASTUtils.h +++ b/libsolidity/ast/ASTUtils.h @@ -42,4 +42,10 @@ ASTNode const* locateInnermostASTNode(int _offsetInFile, SourceUnit const& _sour /// into unary tuples and returns the contained expression. Expression const* resolveOuterUnaryTuples(Expression const* _expr); +/// @returns the type of an expression and asserts that it is present. +Type const* type(Expression const& _expression); +/// @returns the type of the given variable and throws if the type is not present +/// (this can happen for variables with non-explicit types before their types are resolved) +Type const* type(VariableDeclaration const& _variable); + } From c285bf3155a522b1c803d4bd811b0b05bd302240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 23 May 2024 19:34:16 +0200 Subject: [PATCH 0135/1340] ReleaseChecklist: Review and approve blog posts before the release starts --- ReleaseChecklist.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 5db731cfc..30dc30a49 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -38,6 +38,7 @@ At least a day before the release: ### Blog Post - [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the ``Releases`` category and explain some of the new features or concepts. - [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the ``Security Alerts`` category in case of important bug(s). + - [ ] Get the posts reviewed and approved **before the release starts**. ### Changelog - [ ] Sort the changelog entries alphabetically and correct any errors you notice. Commit it. From 748d444a232cc4d8a65bd10a2ce333a047390e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 23 May 2024 19:34:30 +0200 Subject: [PATCH 0136/1340] ReleaseChecklist: Fix a misplaced backtick --- ReleaseChecklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 30dc30a49..d5e5abdd1 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -82,7 +82,7 @@ At least a day before the release: ### PPA - [ ] Create ``.release_ppa_auth`` at the root of your local Solidity checkout and set ``LAUNCHPAD_EMAIL`` and ``LAUNCHPAD_KEYID`` to your key's email and key id. - [ ] Double-check that the ``DISTRIBUTIONS`` list in ``scripts/release_ppa.sh`` and ``scripts/deps-ppa/static_z3.sh`` contains the most recent versions of Ubuntu. - - [ ] Make sure the [``~ethereum/cpp-build-deps`` PPA repository](https://launchpad.net/~ethereum/+archive/ubuntu/cpp-build-deps) contains ``libz3-static-dev builds`` for all current versions of Ubuntu. + - [ ] Make sure the [``~ethereum/cpp-build-deps`` PPA repository](https://launchpad.net/~ethereum/+archive/ubuntu/cpp-build-deps) contains ``libz3-static-dev`` builds for all current versions of Ubuntu. Note that it may be included in the ``z3-static`` multipackage (follow the ``View package details`` link to check). If not present, run ``scripts/deps-ppa/static_z3.sh`` and wait for the builds to succeed before continuing. - [ ] Run ``scripts/release_ppa.sh v$VERSION`` to create the PPA release. From 118362f97cdbc899dbdd40bd61b38eadb3adf86a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 23 May 2024 19:34:54 +0200 Subject: [PATCH 0137/1340] ReleaseChecklist: Link to "Learning from Past Releases" --- ReleaseChecklist.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index d5e5abdd1..85d1ff82e 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -24,6 +24,7 @@ At least a day before the release: This is recommended especially when dealing with PPA for the first time, when we add a new Ubuntu version or when the PPA scripts were modified in this release cycle. - [ ] Verify that the release tarball of ``solc-js`` works. Bump version locally, add ``soljson.js`` from CI, build it, compare the file structure with the previous version, install it locally and try to use it. + - [ ] Review [Learning from Past Releases](https://notes.ethereum.org/@solidity/release-mistakes) to make sure you don't repeat the same mistakes. ### Drafts At least a day before the release: @@ -117,4 +118,5 @@ At least a day before the release: - [ ] Share the announcement on [Project Updates](https://discord.com/channels/420394352083337236/798974456704925696) - [ ] Share the announcement on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im) - [ ] Share the announcement on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org) + - [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.ethereum.org/@solidity/release-mistakes). - [ ] Lean back, wait for bug reports and repeat from step 1 :). From dc9874127544ee142a977f1c36e8879a6718a8cd Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 24 May 2024 12:13:58 +0200 Subject: [PATCH 0138/1340] ReleaseChecklist: Mention that docs need to be built before linkcheck --- ReleaseChecklist.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 85d1ff82e..8ca2e7f96 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -15,6 +15,7 @@ At least a day before the release: - [ ] Run ``make linkcheck`` from within ``docs/`` and fix any broken links it finds. Ignore false positives caused by ``href`` anchors and dummy links not meant to work. + **Note**: In order to run the link check, make sure you've built the docs first via ``docs.sh``. - [ ] Double-check that [the most recent docs builds at readthedocs](https://readthedocs.org/projects/solidity/builds/) succeeded. - [ ] Make sure that all merged PRs that should have changelog entries do have them. - [ ] Rerun CI on the top commits of main branches in all repositories that do not have daily activity by creating a test branch or PR: From 75ebcc0147f47c5f55da44ed64697b3d0572ace4 Mon Sep 17 00:00:00 2001 From: Moritz Hoffmann Date: Tue, 28 May 2024 10:42:07 +0200 Subject: [PATCH 0139/1340] test substitution of unlimited string literal in yul - Defines a contract with a name that exceeds 32 characters - programSize is defined as datasize(contractName) - if not correct, programSize can be substituted by optimizations into ctor return value - this is due to u256 words only capturing first 32 chars --- .../long_literals_as_builtin_args.yul | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul new file mode 100644 index 000000000..34b44aad9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul @@ -0,0 +1,28 @@ +object "AccessControlDefaultAdminRules4233_14" { + code { + let programSize := datasize("AccessControlDefaultAdminRules4233_14") + let i := mload(64) + // argument of datasize is a literal of length >32 which shares a common substring + // of length 32 with programSize, this should not be substituted + let j := datasize("AccessControlDefaultAdminRules4233_14_deployed") + codecopy(i, dataoffset("AccessControlDefaultAdminRules4233_14_deployed"), j) + } + object "AccessControlDefaultAdminRules4233_14_deployed" { + code {} + } + +} +// ---- +// step: commonSubexpressionEliminator +// +// object "AccessControlDefaultAdminRules4233_14" { +// code { +// let programSize := datasize("AccessControlDefaultAdminRules4233_14") +// let i := mload(64) +// let j := datasize("AccessControlDefaultAdminRules4233_14_deployed") +// codecopy(i, dataoffset("AccessControlDefaultAdminRules4233_14_deployed"), j) +// } +// object "AccessControlDefaultAdminRules4233_14_deployed" { +// code { } +// } +// } From 85396f448f32e8d649e84b84740b52f7f2a605ed Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 27 May 2024 15:54:16 -0300 Subject: [PATCH 0140/1340] Introduce evm version prague --- .circleci/soltest_all.sh | 2 +- Changelog.md | 1 + docs/using-the-compiler.rst | 3 ++- liblangutil/EVMVersion.h | 34 +++++++++++++++++++++++++++++-- scripts/tests.sh | 2 +- solc/CommandLineParser.cpp | 2 +- test/EVMHost.cpp | 2 ++ test/tools/fuzzer_common.cpp | 3 ++- test/tools/ossfuzz/protoToYul.cpp | 2 ++ test/tools/ossfuzz/yulProto.proto | 1 + 10 files changed, 45 insertions(+), 7 deletions(-) diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 009852710..86c14901b 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -31,7 +31,7 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" -DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shanghai cancun) +DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shanghai cancun prague) # Deserialize the EVM_VALUES array if it was provided as argument or # set EVM_VALUES to the default values. IFS=" " read -ra EVM_VALUES <<< "${1:-${DEFAULT_EVM_VALUES[@]}}" diff --git a/Changelog.md b/Changelog.md index eb9d87ea8..e7a1d865e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * EVM: Support for the EVM version "Prague". * SMTChecker: Add CHC engine check for underflow and overflow in unary minus operation. diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 875c15b09..544f45142 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -181,6 +181,7 @@ at each version. Backward compatibility is not guaranteed between each version. - Introduces ``blobhash()`` in inline assembly and a corresponding global function to retrieve versioned hashes of blobs associated with the transaction (see `EIP-4844 `_). - Opcode ``mcopy`` is available in assembly (see `EIP-5656 `_). - Opcodes ``tstore`` and ``tload`` are available in assembly (see `EIP-1153 `_). +- ``prague`` (**experimental**) .. index:: ! standard JSON, ! --standard-json .. _compiler-api: @@ -344,7 +345,7 @@ Input Description // Version of the EVM to compile for. // Affects type checking and code generation. Can be homestead, // tangerineWhistle, spuriousDragon, byzantium, constantinople, - // petersburg, istanbul, berlin, london, paris, shanghai or cancun (default) + // petersburg, istanbul, berlin, london, paris, shanghai, cancun (default) or prague. "evmVersion": "cancun", // Optional: Change compilation pipeline to go through the Yul intermediate representation. // This is false by default. diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 58b54f3dc..774268917 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -60,10 +60,25 @@ class EVMVersion: static EVMVersion paris() { return {Version::Paris}; } static EVMVersion shanghai() { return {Version::Shanghai}; } static EVMVersion cancun() { return {Version::Cancun}; } + static EVMVersion prague() { return {Version::Prague}; } static std::optional fromString(std::string const& _version) { - for (auto const& v: {homestead(), tangerineWhistle(), spuriousDragon(), byzantium(), constantinople(), petersburg(), istanbul(), berlin(), london(), paris(), shanghai(), cancun()}) + for (auto const& v: { + homestead(), + tangerineWhistle(), + spuriousDragon(), + byzantium(), + constantinople(), + petersburg(), + istanbul(), + berlin(), + london(), + paris(), + shanghai(), + cancun(), + prague() + }) if (_version == v.name()) return v; return std::nullopt; @@ -88,6 +103,7 @@ class EVMVersion: case Version::Paris: return "paris"; case Version::Shanghai: return "shanghai"; case Version::Cancun: return "cancun"; + case Version::Prague: return "prague"; } return "INVALID"; } @@ -115,7 +131,21 @@ class EVMVersion: bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); } private: - enum class Version { Homestead, TangerineWhistle, SpuriousDragon, Byzantium, Constantinople, Petersburg, Istanbul, Berlin, London, Paris, Shanghai, Cancun }; + enum class Version { + Homestead, + TangerineWhistle, + SpuriousDragon, + Byzantium, + Constantinople, + Petersburg, + Istanbul, + Berlin, + London, + Paris, + Shanghai, + Cancun, + Prague + }; EVMVersion(Version _version): m_version(_version) {} diff --git a/scripts/tests.sh b/scripts/tests.sh index 26eaf4b4b..dfbc04773 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -105,7 +105,7 @@ EVM_VERSIONS="homestead byzantium" if [ -z "$CI" ] then - EVM_VERSIONS+=" constantinople petersburg istanbul berlin london paris shanghai cancun" + EVM_VERSIONS+=" constantinople petersburg istanbul berlin london paris shanghai cancun prague" fi # And then run the Solidity unit-tests in the matrix combination of optimizer / no optimizer diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 824c89911..e61c5ce0a 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -605,7 +605,7 @@ General Information)").c_str(), g_strEVMVersion.c_str(), po::value()->value_name("version")->default_value(EVMVersion{}.name()), "Select desired EVM version. Either homestead, tangerineWhistle, spuriousDragon, " - "byzantium, constantinople, petersburg, istanbul, berlin, london, paris, shanghai or cancun." + "byzantium, constantinople, petersburg, istanbul, berlin, london, paris, shanghai, cancun or prague." ) ; if (!_forHelp) // Note: We intentionally keep this undocumented for now. diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 4ab9b2b08..5626f8d43 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -119,6 +119,8 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm): m_evmRevision = EVMC_SHANGHAI; else if (_evmVersion == langutil::EVMVersion::cancun()) m_evmRevision = EVMC_CANCUN; + else if (_evmVersion == langutil::EVMVersion::prague()) + m_evmRevision = EVMC_PRAGUE; else assertThrow(false, Exception, "Unsupported EVM version"); diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index b05488382..8b7dbffa8 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -49,7 +49,8 @@ static std::vector s_evmVersions = { EVMVersion::istanbul(), EVMVersion::berlin(), EVMVersion::london(), - EVMVersion::paris() + EVMVersion::paris(), + EVMVersion::prague() }; void FuzzerUtil::testCompilerJsonInterface(std::string const& _input, bool _optimize, bool _quiet) diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 8822666c8..7913f4d63 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -119,6 +119,8 @@ EVMVersion ProtoConverter::evmVersionMapping(Program_Version const& _ver) return EVMVersion::shanghai(); case Program::CANCUN: return EVMVersion::cancun(); + case Program::PRAGUE: + return EVMVersion::prague(); } } diff --git a/test/tools/ossfuzz/yulProto.proto b/test/tools/ossfuzz/yulProto.proto index cf14b887c..15ac01396 100644 --- a/test/tools/ossfuzz/yulProto.proto +++ b/test/tools/ossfuzz/yulProto.proto @@ -406,6 +406,7 @@ message Program { PARIS = 9; SHANGHAI = 10; CANCUN = 11; + PRAGUE = 12; } oneof program_oneof { Block block = 1; From bbd5e2e130024a4ebb49d078338dc6a90059e779 Mon Sep 17 00:00:00 2001 From: clonker Date: Thu, 23 May 2024 13:24:44 +0200 Subject: [PATCH 0141/1340] yul identifiers with leading or trailing dot are restricted --- Changelog.md | 1 + libyul/optimiser/OptimizerUtilities.cpp | 13 +++++- .../leading_and_trailing_dots.yul | 42 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 test/libyul/objectCompiler/leading_and_trailing_dots.yul diff --git a/Changelog.md b/Changelog.md index eb9d87ea8..7689ede6b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: +Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. ### 0.8.26 (2024-05-21) diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index 17f912762..bfa3d888f 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -36,6 +36,17 @@ using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; +namespace +{ + +bool hasLeadingOrTrailingDot(std::string_view const _s) +{ + yulAssert(!_s.empty()); + return _s.front() == '.' || _s.back() == '.'; +} + +} + void yul::removeEmptyBlocks(Block& _block) { auto isEmptyBlock = [](Statement const& _st) -> bool { @@ -46,7 +57,7 @@ void yul::removeEmptyBlocks(Block& _block) bool yul::isRestrictedIdentifier(Dialect const& _dialect, YulString const& _identifier) { - return _identifier.empty() || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier); + return _identifier.empty() || hasLeadingOrTrailingDot(_identifier.str()) || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier); } std::optional yul::toEVMInstruction(Dialect const& _dialect, YulString const& _name) diff --git a/test/libyul/objectCompiler/leading_and_trailing_dots.yul b/test/libyul/objectCompiler/leading_and_trailing_dots.yul new file mode 100644 index 000000000..ea6a8fcd8 --- /dev/null +++ b/test/libyul/objectCompiler/leading_and_trailing_dots.yul @@ -0,0 +1,42 @@ +{ + function e(_._) { + e(0) + } + e(2) + function f(n._) { + f(0) + } + f(2) + function g(_.n) { + g(0) + } + g(2) +} +// ---- +// Assembly: +// /* "source":49:50 */ +// 0x02 +// /* "source":6:42 */ +// tag_1: +// /* "source":34:35 */ +// 0x00 +// /* "source":32:36 */ +// tag_1 +// jump // in +// /* "source":56:92 */ +// tag_2: +// /* "source":84:85 */ +// 0x00 +// /* "source":82:86 */ +// tag_2 +// jump // in +// /* "source":106:142 */ +// tag_3: +// /* "source":134:135 */ +// 0x00 +// /* "source":132:136 */ +// tag_3 +// jump // in +// Bytecode: 60025b5f6002565b5f6007565b5f600c56 +// Opcodes: PUSH1 0x2 JUMPDEST PUSH0 PUSH1 0x2 JUMP JUMPDEST PUSH0 PUSH1 0x7 JUMP JUMPDEST PUSH0 PUSH1 0xC JUMP +// SourceMappings: 49:1:0:-:0;6:36;34:1;32:4;:::i;56:36::-;84:1;82:4;:::i;106:36::-;134:1;132:4;:::i From 69c646a6077f49b3ed0a7842b564106ffe156751 Mon Sep 17 00:00:00 2001 From: Daniel Zahariev Date: Tue, 28 May 2024 20:53:02 +0300 Subject: [PATCH 0142/1340] Update style-guide.rst Update function modifier order in the example to match with the guide. --- docs/style-guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 0ac890cb3..87e604124 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -662,7 +662,7 @@ Yes: return balanceOf[from]; } - function increment(uint x) public onlyOwner pure returns (uint) { + function increment(uint x) public pure onlyOwner returns (uint) { return x + 1; } From 6e6e5e504eb32b42cd522932ce8d07500a8fd2d3 Mon Sep 17 00:00:00 2001 From: shafu Date: Wed, 29 May 2024 14:25:31 +0200 Subject: [PATCH 0143/1340] Update assembly.rst --- docs/assembly.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/assembly.rst b/docs/assembly.rst index e08ff9f62..224d75208 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -9,7 +9,8 @@ Inline Assembly You can interleave Solidity statements with inline assembly in a language close to the one of the Ethereum Virtual Machine. This gives you more fine-grained control, -which is especially useful when you are enhancing the language by writing libraries. +which is especially useful when you are enhancing the language by writing libraries or +trying to optimize gas usage. The language used for inline assembly in Solidity is called :ref:`Yul ` and it is documented in its own section. This section will only cover From 76e31d9f1af12c2fc80343863589b939b0a0953c Mon Sep 17 00:00:00 2001 From: shafu Date: Wed, 29 May 2024 14:27:27 +0200 Subject: [PATCH 0144/1340] Update assembly.rst --- docs/assembly.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/assembly.rst b/docs/assembly.rst index 224d75208..cf2ce1bf9 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -10,7 +10,7 @@ Inline Assembly You can interleave Solidity statements with inline assembly in a language close to the one of the Ethereum Virtual Machine. This gives you more fine-grained control, which is especially useful when you are enhancing the language by writing libraries or -trying to optimize gas usage. +optimizing gas usage. The language used for inline assembly in Solidity is called :ref:`Yul ` and it is documented in its own section. This section will only cover From e32b3ddc8a06888d9af047e2418a8e1f94bb1913 Mon Sep 17 00:00:00 2001 From: r0qs Date: Thu, 23 May 2024 16:48:34 +0200 Subject: [PATCH 0145/1340] Add authentication header to circleci api --- .circleci/config.yml | 7 ++ scripts/common/rest_api_helpers.py | 13 ++-- scripts/externalTests/download_benchmarks.py | 20 +++++- ...test_externalTests_benchmark_downloader.py | 64 +++++++++++++++---- 4 files changed, 83 insertions(+), 21 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6feb033de..3a246d3a5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1522,6 +1522,13 @@ jobs: c_ext_benchmarks: <<: *base_node_small steps: + - run: + name: Check CircleCI token presence; Skip job if not set. + command: | + if [[ -z "$CIRCLECI_TOKEN" ]]; then + echo "Skipping benchmarks..." + circleci-agent step halt + fi - install_python3: packages: requests - checkout diff --git a/scripts/common/rest_api_helpers.py b/scripts/common/rest_api_helpers.py index 31f973e81..caae2b5db 100644 --- a/scripts/common/rest_api_helpers.py +++ b/scripts/common/rest_api_helpers.py @@ -1,3 +1,4 @@ +from os import environ from pathlib import Path from typing import List, Mapping, Optional import functools @@ -42,13 +43,13 @@ class FileAlreadyExists(APIHelperError): pass -def query_api(url: str, params: Mapping[str, str], debug_requests=False) -> dict: +def query_api(url: str, params: Mapping[str, str], headers: dict, debug_requests=False) -> dict: if debug_requests: print(f'REQUEST URL: {url}') if len(params) > 0: print(f'QUERY: {params}') - response = requests.get(url, params=params, timeout=60) + response = requests.get(url, params=params, headers=headers, timeout=60) response.raise_for_status() if debug_requests: @@ -63,11 +64,11 @@ def query_api(url: str, params: Mapping[str, str], debug_requests=False) -> dict return response.json() -def download_file(url: str, target_path: Path, overwrite=False): +def download_file(url: str, target_path: Path, headers: dict, overwrite=False): if not overwrite and target_path.exists(): raise FileAlreadyExists(f"Refusing to overwrite existing file: '{target_path}'.") - with requests.get(url, stream=True, timeout=60) as request: + with requests.get(url, headers, stream=True, timeout=60) as request: with open(target_path, 'wb') as target_file: shutil.copyfileobj(request.raw, target_file) @@ -86,6 +87,7 @@ def pull_request(self, pr_id: int) -> dict: return query_api( f'{self.BASE_URL}/repos/{self.project_slug}/pulls/{pr_id}', {}, + {}, self.debug_requests ) @@ -108,11 +110,12 @@ def paginated_query_api_iterator(self, url: str, params: Mapping[str, str], max_ page_count = 0 next_page_token = None + headers = {'Circle-Token': str(environ.get('CIRCLECI_TOKEN'))} if 'CIRCLECI_TOKEN' in environ else {} while max_pages is None or page_count < max_pages: if next_page_token is not None: params = {**params, 'page-token': next_page_token} - json_response = query_api(url, params, self.debug_requests) + json_response = query_api(url, params, headers, self.debug_requests) yield json_response['items'] next_page_token = json_response['next_page_token'] diff --git a/scripts/externalTests/download_benchmarks.py b/scripts/externalTests/download_benchmarks.py index 29f5fe4bc..0f8a65036 100755 --- a/scripts/externalTests/download_benchmarks.py +++ b/scripts/externalTests/download_benchmarks.py @@ -2,7 +2,9 @@ from argparse import ArgumentParser, Namespace from enum import Enum, unique +from os import environ from pathlib import Path +from textwrap import dedent from typing import Mapping, Optional import sys @@ -28,8 +30,13 @@ class Status(Enum): def process_commandline() -> Namespace: script_description = ( - "Downloads benchmark results attached as artifacts to the c_ext_benchmarks job on CircleCI. " - "If no options are specified, downloads results for the currently checked out git branch." + """ + Downloads benchmark results attached as artifacts to the c_ext_benchmarks job on CircleCI. + If no options are specified, downloads results for the currently checked out git branch. + + The script requires the CIRCLECI_TOKEN environment variable to be set with a valid CircleCI API token. + You can generate a new token at https://app.circleci.com/settings/user/tokens. + """ ) parser = ArgumentParser(description=script_description) @@ -96,9 +103,11 @@ def download_benchmark_artifact( print(f"Missing artifact: {artifact_path}.") return False + headers = {'Circle-Token': str(environ.get('CIRCLECI_TOKEN'))} if 'CIRCLECI_TOKEN' in environ else {} download_file( artifacts[artifact_path]['url'], Path(f'{benchmark_name}-{branch}-{commit_hash[:8]}.json'), + headers, overwrite, ) @@ -162,6 +171,13 @@ def download_benchmarks( def main(): try: + if 'CIRCLECI_TOKEN' not in environ: + raise RuntimeError( + dedent(""" \ + CIRCLECI_TOKEN environment variable required but not set. + Please generate a new token at https://app.circleci.com/settings/user/tokens and set CIRCLECI_TOKEN. + """) + ) options = process_commandline() return download_benchmarks( options.branch, diff --git a/test/scripts/test_externalTests_benchmark_downloader.py b/test/scripts/test_externalTests_benchmark_downloader.py index aead61847..f9ca9ae72 100644 --- a/test/scripts/test_externalTests_benchmark_downloader.py +++ b/test/scripts/test_externalTests_benchmark_downloader.py @@ -3,6 +3,8 @@ from pathlib import Path from unittest import TestCase from unittest.mock import call, Mock, patch +import os +import requests # NOTE: This test file file only works with scripts/ added to PYTHONPATH so pylint can't find the imports # pragma pylint: disable=import-error @@ -31,7 +33,7 @@ def _git_run_command_mock(command): "If you have updated the code, please remember to add matching command fixtures above." ) -def _requests_get_mock(url, params, timeout): +def _requests_get_mock(url, params, headers, timeout): response_mock = Mock() if url == 'https://api.github.com/repos/ethereum/solidity/pulls/12818': @@ -155,25 +157,37 @@ def _requests_get_mock(url, params, timeout): return response_mock if url == 'https://circleci.com/api/v2/project/gh/ethereum/solidity/1018023/artifacts': - response_mock.json.return_value = { - "next_page_token": None, - "items": [ - { - "path": "reports/externalTests/all-benchmarks.json", - "url": "https://circle-artifacts.com/0/reports/externalTests/all-benchmarks.json" - }, - { - "path": "reports/externalTests/summarized-benchmarks.json", - "url": "https://circle-artifacts.com/0/reports/externalTests/summarized-benchmarks.json" - } - ] - } + if ( + os.environ.get('CIRCLECI_TOKEN') == 'valid_token' and + headers.get('Circle-Token') == os.environ.get('CIRCLECI_TOKEN') + ): + response_mock.json.return_value = { + "next_page_token": None, + "items": [ + { + "path": "reports/externalTests/all-benchmarks.json", + "url": "https://circle-artifacts.com/0/reports/externalTests/all-benchmarks.json" + }, + { + "path": "reports/externalTests/summarized-benchmarks.json", + "url": "https://circle-artifacts.com/0/reports/externalTests/summarized-benchmarks.json" + } + ] + } + else: + response_mock.status_code = 401 + response_mock.json.return_value = { + "message": "Unauthorized" + } + error = requests.exceptions.HTTPError(f"401 Client Error: Unauthorized for url: {url}") + response_mock.raise_for_status.side_effect = error return response_mock raise RuntimeError( "The test tried to perform an unexpected GET request.\n" f"URL: {url}\n" + (f"query: {params}\n" if len(params) > 0 else "") + + (f"headers: {headers}\n" if len(headers) > 0 else "") + f"timeout: {timeout}\n" + "If you have updated the code, please remember to add matching response fixtures above." ) @@ -186,17 +200,20 @@ def setUp(self): @patch('externalTests.download_benchmarks.download_file') @patch('requests.get', _requests_get_mock) @patch('common.git_helpers.run_git_command',_git_run_command_mock) + @patch.dict(os.environ, {'CIRCLECI_TOKEN': 'valid_token'}) def test_download_benchmarks(download_file_mock): download_benchmarks(None, None, None, silent=True) download_file_mock.assert_has_calls([ call( 'https://circle-artifacts.com/0/reports/externalTests/summarized-benchmarks.json', Path('summarized-benchmarks-benchmark-downloader-fa1ddc6f.json'), + {'Circle-Token': 'valid_token'}, False ), call( 'https://circle-artifacts.com/0/reports/externalTests/all-benchmarks.json', Path('all-benchmarks-benchmark-downloader-fa1ddc6f.json'), + {'Circle-Token': 'valid_token'}, False ), ]) @@ -205,17 +222,20 @@ def test_download_benchmarks(download_file_mock): @patch('externalTests.download_benchmarks.download_file') @patch('requests.get', _requests_get_mock) @patch('common.git_helpers.run_git_command',_git_run_command_mock) + @patch.dict(os.environ, {'CIRCLECI_TOKEN': 'valid_token'}) def test_download_benchmarks_branch(download_file_mock): download_benchmarks('develop', None, None, silent=True) download_file_mock.assert_has_calls([ call( 'https://circle-artifacts.com/0/reports/externalTests/summarized-benchmarks.json', Path('summarized-benchmarks-develop-43f29c00.json'), + {'Circle-Token': 'valid_token'}, False ), call( 'https://circle-artifacts.com/0/reports/externalTests/all-benchmarks.json', Path('all-benchmarks-develop-43f29c00.json'), + {'Circle-Token': 'valid_token'}, False ), ]) @@ -224,17 +244,20 @@ def test_download_benchmarks_branch(download_file_mock): @patch('externalTests.download_benchmarks.download_file') @patch('requests.get', _requests_get_mock) @patch('common.git_helpers.run_git_command',_git_run_command_mock) + @patch.dict(os.environ, {'CIRCLECI_TOKEN': 'valid_token'}) def test_download_benchmarks_pr(download_file_mock): download_benchmarks(None, 12818, None, silent=True) download_file_mock.assert_has_calls([ call( 'https://circle-artifacts.com/0/reports/externalTests/summarized-benchmarks.json', Path('summarized-benchmarks-benchmark-downloader-fa1ddc6f.json'), + {'Circle-Token': 'valid_token'}, False ), call( 'https://circle-artifacts.com/0/reports/externalTests/all-benchmarks.json', Path('all-benchmarks-benchmark-downloader-fa1ddc6f.json'), + {'Circle-Token': 'valid_token'}, False ), ]) @@ -243,17 +266,30 @@ def test_download_benchmarks_pr(download_file_mock): @patch('externalTests.download_benchmarks.download_file') @patch('requests.get', _requests_get_mock) @patch('common.git_helpers.run_git_command',_git_run_command_mock) + @patch.dict(os.environ, {'CIRCLECI_TOKEN': 'valid_token'}) def test_download_benchmarks_base_of_pr(download_file_mock): download_benchmarks(None, None, 12818, silent=True) download_file_mock.assert_has_calls([ call( 'https://circle-artifacts.com/0/reports/externalTests/summarized-benchmarks.json', Path('summarized-benchmarks-develop-43f29c00.json'), + {'Circle-Token': 'valid_token'}, False ), call( 'https://circle-artifacts.com/0/reports/externalTests/all-benchmarks.json', Path('all-benchmarks-develop-43f29c00.json'), + {'Circle-Token': 'valid_token'}, False ), ]) + + # NOTE: No circleci token is set in the environment + @patch('externalTests.download_benchmarks.download_file') + @patch('requests.get', _requests_get_mock) + @patch('common.git_helpers.run_git_command',_git_run_command_mock) + def test_download_benchmarks_unauthorized_request(self, _): + with self.assertRaises(requests.exceptions.HTTPError) as manager: + download_benchmarks(None, None, None, silent=True) + + self.assertIn('401 Client Error: Unauthorized', str(manager.exception)) From 6ab7795b41d583d7138e99ae5471ecff64a84b53 Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 28 May 2024 17:27:41 +0200 Subject: [PATCH 0146/1340] Update scripts/externalTests/download_benchmarks.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- scripts/externalTests/download_benchmarks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/externalTests/download_benchmarks.py b/scripts/externalTests/download_benchmarks.py index 0f8a65036..508e801da 100755 --- a/scripts/externalTests/download_benchmarks.py +++ b/scripts/externalTests/download_benchmarks.py @@ -34,8 +34,8 @@ def process_commandline() -> Namespace: Downloads benchmark results attached as artifacts to the c_ext_benchmarks job on CircleCI. If no options are specified, downloads results for the currently checked out git branch. - The script requires the CIRCLECI_TOKEN environment variable to be set with a valid CircleCI API token. - You can generate a new token at https://app.circleci.com/settings/user/tokens. + The script will use the CIRCLECI_TOKEN environment as a CircleCI API token if set. + You can generate a new personal token at https://app.circleci.com/settings/user/tokens. """ ) From fea0c75a6a4b285ae1438ea7ae5e46102deb548d Mon Sep 17 00:00:00 2001 From: r0qs Date: Thu, 23 May 2024 16:48:34 +0200 Subject: [PATCH 0147/1340] Add authentication header to circleci api --- .circleci/config.yml | 24 +++++++++++--------- scripts/externalTests/download_benchmarks.py | 4 ++-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3a246d3a5..c58d01e32 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1522,13 +1522,6 @@ jobs: c_ext_benchmarks: <<: *base_node_small steps: - - run: - name: Check CircleCI token presence; Skip job if not set. - command: | - if [[ -z "$CIRCLECI_TOKEN" ]]; then - echo "Skipping benchmarks..." - circleci-agent step halt - fi - install_python3: packages: requests - checkout @@ -1540,6 +1533,19 @@ jobs: - run: name: Summarize reports command: cat reports/externalTests/all-benchmarks.json | scripts/externalTests/summarize_benchmarks.sh > reports/externalTests/summarized-benchmarks.json + - store_artifacts: + path: reports/externalTests/all-benchmarks.json + - store_artifacts: + path: reports/externalTests/summarized-benchmarks.json + - run: + name: Check CircleCI token presence; Skip remaining steps if the token is not present. + command: | + # NOTE: download_benchmarks.py requires CIRCLECI_TOKEN environment variable to be set to + # a valid CircleCI API token to download the benchmark artifacts. + if [[ -z "$CIRCLECI_TOKEN" ]]; then + echo "Skipping download benchmarks..." + circleci-agent step halt + fi - run: name: Download reports from base branch command: | @@ -1584,10 +1590,6 @@ jobs: base-branch/all-benchmarks-*.json \ all-benchmarks.json > diff/benchmark-diff-all-table-inplace-absolute.md fi - - store_artifacts: - path: reports/externalTests/all-benchmarks.json - - store_artifacts: - path: reports/externalTests/summarized-benchmarks.json - store_artifacts: path: reports/externalTests/diff/ - store_artifacts: diff --git a/scripts/externalTests/download_benchmarks.py b/scripts/externalTests/download_benchmarks.py index 508e801da..0f8a65036 100755 --- a/scripts/externalTests/download_benchmarks.py +++ b/scripts/externalTests/download_benchmarks.py @@ -34,8 +34,8 @@ def process_commandline() -> Namespace: Downloads benchmark results attached as artifacts to the c_ext_benchmarks job on CircleCI. If no options are specified, downloads results for the currently checked out git branch. - The script will use the CIRCLECI_TOKEN environment as a CircleCI API token if set. - You can generate a new personal token at https://app.circleci.com/settings/user/tokens. + The script requires the CIRCLECI_TOKEN environment variable to be set with a valid CircleCI API token. + You can generate a new token at https://app.circleci.com/settings/user/tokens. """ ) From bf4b5e3ce5db68c37e7a512662de400feaac4fae Mon Sep 17 00:00:00 2001 From: Moritz Hoffmann Date: Mon, 3 Jun 2024 10:51:57 +0200 Subject: [PATCH 0148/1340] Fix changelog entry for #15149 missing `*` --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 2dca15562..4361f1fec 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,7 +9,7 @@ Compiler Features: Bugfixes: -Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. + * Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. ### 0.8.26 (2024-05-21) From 52223ff5bd4cd7e21c59705cb6f90bfa98ec4960 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 24 May 2024 11:25:56 +0200 Subject: [PATCH 0149/1340] Fix segfault in nested tuple to tuple assignments --- Changelog.md | 1 + libsolidity/analysis/StaticAnalyzer.cpp | 114 +++++++++++++++++- libsolidity/analysis/StaticAnalyzer.h | 5 + libsolidity/analysis/TypeChecker.cpp | 101 ---------------- libsolidity/analysis/TypeChecker.h | 3 - .../nested_tuple_to_tuple_assignment.sol | 37 ++++++ 6 files changed, 156 insertions(+), 105 deletions(-) create mode 100644 test/libsolidity/syntaxTests/tupleAssignments/nested_tuple_to_tuple_assignment.sol diff --git a/Changelog.md b/Changelog.md index 4361f1fec..2101f1ec9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Compiler Features: Bugfixes: + * TypeChecker: Fix segfault when assigning nested tuple to tuple. * Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp index 563295e23..dfd262c8d 100644 --- a/libsolidity/analysis/StaticAnalyzer.cpp +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -22,10 +22,13 @@ */ #include - #include #include +#include #include + +#include + #include using namespace solidity; @@ -88,6 +91,18 @@ bool StaticAnalyzer::analyze(SourceUnit const& _sourceUnit) return !Error::containsErrors(m_errorReporter.errors()); } +bool StaticAnalyzer::visit(Assignment const& _assignment) +{ + Type const* lhsType = _assignment.leftHandSide().annotation().type; + Type const* rhsType = _assignment.rightHandSide().annotation().type; + solAssert(lhsType && rhsType, "Both left and right hand side expressions in an assignment must have a type."); + + if (dynamic_cast(lhsType) && dynamic_cast(rhsType)) + checkDoubleStorageAssignment(_assignment); + + return true; +} + bool StaticAnalyzer::visit(ContractDefinition const& _contract) { m_library = _contract.isLibrary(); @@ -348,3 +363,100 @@ bool StaticAnalyzer::visit(FunctionCall const& _functionCall) } return true; } + +void StaticAnalyzer::checkDoubleStorageAssignment(Assignment const& _assignment) +{ + size_t storageToStorageCopies = 0; + size_t toStorageCopies = 0; + size_t storageByteArrayPushes = 0; + size_t storageByteAccesses = 0; + auto count = [&](TupleExpression const& _lhs, TupleType const& _rhs, auto _recurse) -> void { + TupleType const& lhsType = dynamic_cast(*type(_lhs)); + TupleExpression const* lhsResolved = dynamic_cast(resolveOuterUnaryTuples(&_lhs)); + + solAssert(lhsResolved && lhsResolved->components().size() == lhsType.components().size()); + if (lhsType.components().size() != _rhs.components().size()) + { + solAssert(m_errorReporter.hasErrors(), ""); + return; + } + + for (auto&& [index, componentType]: lhsType.components() | ranges::views::enumerate) + { + if (ReferenceType const* ref = dynamic_cast(componentType)) + { + if (ref->dataStoredIn(DataLocation::Storage) && !ref->isPointer()) + { + toStorageCopies++; + if (_rhs.components()[index]->dataStoredIn(DataLocation::Storage)) + storageToStorageCopies++; + } + } + else if (FixedBytesType const* bytesType = dynamic_cast(componentType)) + { + if (bytesType->numBytes() == 1) + { + if (FunctionCall const* lhsCall = dynamic_cast(resolveOuterUnaryTuples(lhsResolved->components().at(index).get()))) + { + FunctionType const& callType = dynamic_cast(*type(lhsCall->expression())); + if (callType.kind() == FunctionType::Kind::ArrayPush) + { + ArrayType const& arrayType = dynamic_cast(*callType.selfType()); + if (arrayType.isByteArray() && arrayType.dataStoredIn(DataLocation::Storage)) + { + ++storageByteAccesses; + ++storageByteArrayPushes; + } + } + } + else if (IndexAccess const* indexAccess = dynamic_cast(resolveOuterUnaryTuples(lhsResolved->components().at(index).get()))) + { + if (ArrayType const* arrayType = dynamic_cast(type(indexAccess->baseExpression()))) + if (arrayType->isByteArray() && arrayType->dataStoredIn(DataLocation::Storage)) + ++storageByteAccesses; + } + } + } + else if (dynamic_cast(componentType)) + if (auto const* lhsNested = dynamic_cast(lhsResolved->components().at(index).get())) + if (auto const* rhsNestedType = dynamic_cast(_rhs.components().at(index))) + _recurse( + *lhsNested, + *rhsNestedType, + _recurse + ); + } + }; + + TupleExpression const* lhsTupleExpression = dynamic_cast(&_assignment.leftHandSide()); + if (!lhsTupleExpression) + { + solAssert(m_errorReporter.hasErrors()); + return; + } + count( + *lhsTupleExpression, + dynamic_cast(*type(_assignment.rightHandSide())), + count + ); + + if (storageToStorageCopies >= 1 && toStorageCopies >= 2) + m_errorReporter.warning( + 7238_error, + _assignment.location(), + "This assignment performs two copies to storage. Since storage copies do not first " + "copy to a temporary location, one of them might be overwritten before the second " + "is executed and thus may have unexpected effects. It is safer to perform the copies " + "separately or assign to storage pointers first." + ); + + if (storageByteArrayPushes >= 1 && storageByteAccesses >= 2) + m_errorReporter.warning( + 7239_error, + _assignment.location(), + "This assignment involves multiple accesses to a bytes array in storage while simultaneously enlarging it. " + "When a bytes array is enlarged, it may transition from short storage layout to long storage layout, " + "which invalidates all references to its elements. It is safer to only enlarge byte arrays in a single " + "operation, one element at a time." + ); +} diff --git a/libsolidity/analysis/StaticAnalyzer.h b/libsolidity/analysis/StaticAnalyzer.h index dc6263d7e..909af2b02 100644 --- a/libsolidity/analysis/StaticAnalyzer.h +++ b/libsolidity/analysis/StaticAnalyzer.h @@ -65,6 +65,7 @@ class StaticAnalyzer: private ASTConstVisitor bool visit(FunctionDefinition const& _function) override; void endVisit(FunctionDefinition const& _function) override; + bool visit(Assignment const& _assignment) override; bool visit(ExpressionStatement const& _statement) override; bool visit(VariableDeclaration const& _variable) override; bool visit(Identifier const& _identifier) override; @@ -74,6 +75,10 @@ class StaticAnalyzer: private ASTConstVisitor bool visit(BinaryOperation const& _operation) override; bool visit(FunctionCall const& _functionCall) override; + /// Checks (and warns) if a tuple assignment might cause unexpected overwrites in storage. + /// Should only be called if the left hand side is tuple-typed. + void checkDoubleStorageAssignment(Assignment const& _assignment); + langutil::ErrorReporter& m_errorReporter; /// Flag that indicates whether the current contract definition is a library. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 5044414bf..918e27033 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -94,103 +94,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) return false; } -void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment) -{ - size_t storageToStorageCopies = 0; - size_t toStorageCopies = 0; - size_t storageByteArrayPushes = 0; - size_t storageByteAccesses = 0; - auto count = [&](TupleExpression const& _lhs, TupleType const& _rhs, auto _recurse) -> void { - TupleType const& lhsType = dynamic_cast(*type(_lhs)); - TupleExpression const* lhsResolved = dynamic_cast(resolveOuterUnaryTuples(&_lhs)); - - solAssert(!lhsResolved || lhsResolved->components().size() == lhsType.components().size()); - if (lhsType.components().size() != _rhs.components().size()) - { - solAssert(m_errorReporter.hasErrors(), ""); - return; - } - - for (auto&& [index, componentType]: lhsType.components() | ranges::views::enumerate) - { - if (ReferenceType const* ref = dynamic_cast(componentType)) - { - if (ref && ref->dataStoredIn(DataLocation::Storage) && !ref->isPointer()) - { - toStorageCopies++; - if (_rhs.components()[index]->dataStoredIn(DataLocation::Storage)) - storageToStorageCopies++; - } - } - else if (FixedBytesType const* bytesType = dynamic_cast(componentType)) - { - if (bytesType && bytesType->numBytes() == 1) - { - if (FunctionCall const* lhsCall = dynamic_cast(resolveOuterUnaryTuples(lhsResolved->components().at(index).get()))) - { - FunctionType const& callType = dynamic_cast(*type(lhsCall->expression())); - if (callType.kind() == FunctionType::Kind::ArrayPush) - { - ArrayType const& arrayType = dynamic_cast(*callType.selfType()); - if (arrayType.isByteArray() && arrayType.dataStoredIn(DataLocation::Storage)) - { - ++storageByteAccesses; - ++storageByteArrayPushes; - } - } - } - else if (IndexAccess const* indexAccess = dynamic_cast(resolveOuterUnaryTuples(lhsResolved->components().at(index).get()))) - { - if (ArrayType const* arrayType = dynamic_cast(type(indexAccess->baseExpression()))) - if (arrayType->isByteArray() && arrayType->dataStoredIn(DataLocation::Storage)) - ++storageByteAccesses; - } - } - } - else if (TupleType const* tupleType = dynamic_cast(componentType)) - if (auto const* lhsNested = dynamic_cast(lhsResolved->components().at(index).get())) - if (auto const* rhsNestedType = dynamic_cast(_rhs.components().at(index))) - _recurse( - *lhsNested, - *rhsNestedType, - _recurse - ); - } - }; - - TupleExpression const* lhsTupleExpression = dynamic_cast(&_assignment.leftHandSide()); - if (!lhsTupleExpression) - { - solAssert(m_errorReporter.hasErrors()); - return; - } - count( - *lhsTupleExpression, - dynamic_cast(*type(_assignment.rightHandSide())), - count - ); - - if (storageToStorageCopies >= 1 && toStorageCopies >= 2) - m_errorReporter.warning( - 7238_error, - _assignment.location(), - "This assignment performs two copies to storage. Since storage copies do not first " - "copy to a temporary location, one of them might be overwritten before the second " - "is executed and thus may have unexpected effects. It is safer to perform the copies " - "separately or assign to storage pointers first." - ); - - if (storageByteArrayPushes >= 1 && storageByteAccesses >= 2) - m_errorReporter.warning( - 7239_error, - _assignment.location(), - "This assignment involves multiple accesses to a bytes array in storage while simultaneously enlarging it. " - "When a bytes array is enlarged, it may transition from short storage layout to long storage layout, " - "which invalidates all references to its elements. It is safer to only enlarge byte arrays in a single " - "operation, one element at a time." - ); -} - TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall const& _functionCall, bool _abiEncoderV2) { std::vector> arguments = _functionCall.arguments(); @@ -1575,10 +1478,6 @@ bool TypeChecker::visit(Assignment const& _assignment) _assignment.annotation().type = TypeProvider::emptyTuple(); expectType(_assignment.rightHandSide(), *tupleType); - - // expectType does not cause fatal errors, so we have to check again here. - if (dynamic_cast(type(_assignment.rightHandSide()))) - checkDoubleStorageAssignment(_assignment); } else if (_assignment.assignmentOperator() == Token::Assign) expectType(_assignment.rightHandSide(), *t); diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index d7998d178..b3bd8b91f 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -61,9 +61,6 @@ class TypeChecker: private ASTConstVisitor private: bool visit(ContractDefinition const& _contract) override; - /// Checks (and warns) if a tuple assignment might cause unexpected overwrites in storage. - /// Should only be called if the left hand side is tuple-typed. - void checkDoubleStorageAssignment(Assignment const& _assignment); // Checks whether the expression @arg _expression can be assigned from type @arg _type // and reports an error, if not. void checkExpressionAssignment(Type const& _type, Expression const& _expression); diff --git a/test/libsolidity/syntaxTests/tupleAssignments/nested_tuple_to_tuple_assignment.sol b/test/libsolidity/syntaxTests/tupleAssignments/nested_tuple_to_tuple_assignment.sol new file mode 100644 index 000000000..87ebfbd00 --- /dev/null +++ b/test/libsolidity/syntaxTests/tupleAssignments/nested_tuple_to_tuple_assignment.sol @@ -0,0 +1,37 @@ +contract C { + bool x; + + function foo() external { + (((),x)&x) = ((), true); + (((),x)+x) = ((), true); + (((),x)-x) = ((), true); + (((),x)/x) = ((), true); + (((),x)*x) = ((), true); + (((),x)|x) = ((), true); + } +} +// ---- +// TypeError 6473: (66-68): Tuple component cannot be empty. +// TypeError 2271: (65-73): Built-in binary operator & cannot be applied to types tuple(tuple(),bool) and bool. +// TypeError 4247: (65-73): Expression has to be an lvalue. +// TypeError 6473: (78-80): Tuple component cannot be empty. +// TypeError 6473: (99-101): Tuple component cannot be empty. +// TypeError 2271: (98-106): Built-in binary operator + cannot be applied to types tuple(tuple(),bool) and bool. +// TypeError 4247: (98-106): Expression has to be an lvalue. +// TypeError 6473: (111-113): Tuple component cannot be empty. +// TypeError 6473: (132-134): Tuple component cannot be empty. +// TypeError 2271: (131-139): Built-in binary operator - cannot be applied to types tuple(tuple(),bool) and bool. +// TypeError 4247: (131-139): Expression has to be an lvalue. +// TypeError 6473: (144-146): Tuple component cannot be empty. +// TypeError 6473: (165-167): Tuple component cannot be empty. +// TypeError 2271: (164-172): Built-in binary operator / cannot be applied to types tuple(tuple(),bool) and bool. +// TypeError 4247: (164-172): Expression has to be an lvalue. +// TypeError 6473: (177-179): Tuple component cannot be empty. +// TypeError 6473: (198-200): Tuple component cannot be empty. +// TypeError 2271: (197-205): Built-in binary operator * cannot be applied to types tuple(tuple(),bool) and bool. +// TypeError 4247: (197-205): Expression has to be an lvalue. +// TypeError 6473: (210-212): Tuple component cannot be empty. +// TypeError 6473: (231-233): Tuple component cannot be empty. +// TypeError 2271: (230-238): Built-in binary operator | cannot be applied to types tuple(tuple(),bool) and bool. +// TypeError 4247: (230-238): Expression has to be an lvalue. +// TypeError 6473: (243-245): Tuple component cannot be empty. From 03ecb0f6c0ef20b862b1a1a16e2d144d69c902ab Mon Sep 17 00:00:00 2001 From: Tilak Madichetti Date: Mon, 3 Jun 2024 22:18:13 +0530 Subject: [PATCH 0150/1340] Update 080-breaking-changes.rst --- docs/080-breaking-changes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/080-breaking-changes.rst b/docs/080-breaking-changes.rst index 524d12ac3..9d1f3347b 100644 --- a/docs/080-breaking-changes.rst +++ b/docs/080-breaking-changes.rst @@ -155,7 +155,7 @@ Interface Changes ``storage-layout`` are sub-objects now. Before 0.8.0 they used to be serialised as strings. * The "legacy AST" has been removed (``--ast-json`` on the commandline interface and ``legacyAST`` for standard JSON). - Use the "compact AST" (``--ast-compact--json`` resp. ``AST``) as replacement. + Use the "compact AST" (``--ast-compact-json`` resp. ``AST``) as replacement. * The old error reporter (``--old-reporter``) has been removed. From baddb2193c3716fed09c0edb34a4d289ccd05fb6 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 5 Jun 2024 12:23:40 +0200 Subject: [PATCH 0151/1340] Fix default EVM version in CI. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c58d01e32..5826067dd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,7 +30,7 @@ parameters: default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c57f2bfb8c15d70fe290629358dd1c73dc126e3760f443b54764797556b887d4" evm-version: type: string - default: london + default: cancun orbs: win: circleci/windows@2.2.0 From 9e49b2c5336d93c20d86ade193cdafa6c446db47 Mon Sep 17 00:00:00 2001 From: snoppy Date: Thu, 6 Jun 2024 15:22:13 +0800 Subject: [PATCH 0152/1340] chore: fix typos Signed-off-by: snoppy --- libsolidity/formal/BMC.cpp | 2 +- libsolutil/CommonData.h | 2 +- libyul/AsmParser.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 2bb794cde..e7cf35a7f 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -376,7 +376,7 @@ bool BMC::visit(WhileStatement const& _node) auto indices = copyVariableIndices(); _node.condition().accept(*this); loopCondition = expr(_node.condition()); - // asseert that the loop is complete + // assert that the loop is complete m_context.addAssertion(!loopCondition || broke || !loopConditionOnPreviousIterations); mergeVariables( broke || !loopConditionOnPreviousIterations, diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index de6873845..c52434451 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -575,7 +575,7 @@ void iterateReplacingWindow(std::vector& _vector, F const& _f) detail::iterateReplacingWindow(_vector, _f, std::make_index_sequence{}); } -/// @returns true iff @a _str passess the hex address checksum test. +/// @returns true iff @a _str passes the hex address checksum test. /// @param _strict if false, hex strings with only uppercase or only lowercase letters /// are considered valid. bool passesAddressChecksum(std::string const& _str, bool _strict); diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 3e0af66ac..dd91e436e 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -140,7 +140,7 @@ class Parser: public langutil::ParserBase /// Parses a functional expression that has to push exactly one stack element Expression parseExpression(); /// Parses an elementary operation, i.e. a literal, identifier, instruction or - /// builtin functian call (only the name). + /// builtin function call (only the name). std::variant parseLiteralOrIdentifier(); VariableDeclaration parseVariableDeclaration(); FunctionDefinition parseFunctionDefinition(); From c1edf1983b152807f98f374207f8cbc5b89844fc Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 14 May 2024 18:41:56 +0200 Subject: [PATCH 0153/1340] Split docker run command in Dockerfile.emscripten --- scripts/docker/buildpack-deps/Dockerfile.emscripten | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten index 961901f00..46bf734b6 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -44,8 +44,10 @@ RUN set -ex && \ python3 \ python3-pip \ sudo && \ - pip3 install requests && \ - \ + pip3 install requests; + +# Install Z3 +RUN set -ex && \ cd /usr/src && \ git clone https://github.com/Z3Prover/z3.git -b z3-4.12.1 --depth 1 && \ cd z3 && \ @@ -63,9 +65,11 @@ RUN set -ex && \ .. && \ make && \ make install && \ - rm -r /usr/src/z3 && \ + rm -r /usr/src/z3 + +# Install Boost +RUN set -ex && \ cd /usr/src && \ - \ wget -q 'https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.bz2' -O boost.tar.bz2 && \ test "$(sha256sum boost.tar.bz2)" = "953db31e016db7bb207f11432bef7df100516eeb746843fa0486a222e3fd49cb boost.tar.bz2" && \ tar -xf boost.tar.bz2 && \ From e2da441352b5a28acbb8a531452d9c45ac48d104 Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 14 May 2024 18:42:46 +0200 Subject: [PATCH 0154/1340] Upgrade to cvc5 in buildpack-deps --- .../buildpack-deps/Dockerfile.emscripten | 11 ++++++++++ .../Dockerfile.ubuntu.clang.ossfuzz | 11 ++++++++++ .../buildpack-deps/Dockerfile.ubuntu2004 | 20 ++++++++++++++++--- .../buildpack-deps/Dockerfile.ubuntu2204 | 16 ++++++++++++--- .../Dockerfile.ubuntu2204.clang | 11 ++++++++++ 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten index 46bf734b6..d2726f9a9 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -83,3 +83,14 @@ RUN set -ex && \ cxxflags="-s DISABLE_EXCEPTION_CATCHING=0 -Wno-unused-local-typedef -Wno-variadic-macros -Wno-c99-extensions -Wno-all" \ --prefix=$(em-config CACHE)/sysroot/usr install && \ rm -r /usr/src/boost_1_75_0 + +# CVC5 +RUN set -ex; \ + cvc5_version="1.1.2"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ + unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ + mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ + mv /opt/cvc5-Linux-static/include/* /usr/include; \ + mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ + rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index f8a4c73ce..02cb05be5 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -109,6 +109,17 @@ RUN set -ex; \ unzip /opt/eld_binaries.zip -d /opt; \ rm -f /opt/eld_binaries.zip; +# CVC5 +RUN set -ex; \ + cvc5_version="1.1.2"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ + unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ + mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ + mv /opt/cvc5-Linux-static/include/* /usr/include; \ + mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ + rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + # OSSFUZZ: libprotobuf-mutator RUN set -ex; \ git clone https://github.com/google/libprotobuf-mutator.git \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index 815c93ee8..9f331e1b8 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -39,7 +39,6 @@ RUN set -ex; \ libboost-program-options-dev \ libboost-system-dev \ libboost-test-dev \ - libcvc4-dev \ libz3-static-dev \ lsof \ ninja-build \ @@ -47,6 +46,7 @@ RUN set -ex; \ python3-sphinx \ software-properties-common \ sudo \ + unzip \ z3-static; \ pip3 install \ codecov \ @@ -59,18 +59,32 @@ RUN set -ex; \ tabulate \ z3-solver; +# TODO: we could eliminate duplication by using a Dockerfile extension like: +# https://github.com/edrevo/dockerfile-plus?tab=readme-ov-file#dockerfile +# or mult-stage builds, then we could define a base image which would be included/used by all the other Dockerfiles. +# Or we could move the common parts to a shell script, copying and calling it from the Dockerfiles. # Eldarica RUN set -ex; \ apt-get update; \ apt-get install -qqy \ - openjdk-11-jre \ - unzip; \ + openjdk-11-jre; \ eldarica_version="2.1"; \ wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ unzip /opt/eld_binaries.zip -d /opt; \ rm -f /opt/eld_binaries.zip; +# CVC5 +RUN set -ex; \ + cvc5_version="1.1.2"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ + unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ + mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ + mv /opt/cvc5-Linux-static/include/* /usr/include; \ + mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ + rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + FROM base AS libraries # EVMONE diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index 254e83b4c..6bc1df143 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -40,7 +40,6 @@ RUN set -ex; \ libboost-system-dev \ libboost-test-dev \ libcln-dev \ - libcvc4-dev \ libz3-static-dev \ locales-all \ lsof \ @@ -49,6 +48,7 @@ RUN set -ex; \ python3-sphinx \ software-properties-common \ sudo \ + unzip \ z3-static \ zip; \ pip3 install \ @@ -66,14 +66,24 @@ RUN set -ex; \ RUN set -ex; \ apt-get update; \ apt-get install -qqy \ - openjdk-11-jre \ - unzip; \ + openjdk-11-jre; \ eldarica_version="2.1"; \ wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ unzip /opt/eld_binaries.zip -d /opt; \ rm -f /opt/eld_binaries.zip; +# CVC5 +RUN set -ex; \ + cvc5_version="1.1.2"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ + unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ + mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ + mv /opt/cvc5-Linux-static/include/* /usr/include; \ + mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ + rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + FROM base AS libraries # EVMONE diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang index af6155b6e..de9ce4efb 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang @@ -71,6 +71,17 @@ RUN set -ex; \ unzip /opt/eld_binaries.zip -d /opt; \ rm -f /opt/eld_binaries.zip; +# CVC5 +RUN set -ex; \ + cvc5_version="1.1.2"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ + unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ + mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ + mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ + mv /opt/cvc5-Linux-static/include/* /usr/include; \ + rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + FROM base AS libraries ENV CC clang From 3127bbccd66e701498b3066ff301a957aee0a250 Mon Sep 17 00:00:00 2001 From: r0qs Date: Thu, 16 May 2024 16:44:42 +0200 Subject: [PATCH 0155/1340] Bump docker image versions --- scripts/docker/buildpack-deps/Dockerfile.emscripten | 2 +- scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz | 2 +- scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 | 2 +- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 | 2 +- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten index d2726f9a9..478d8d947 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -33,7 +33,7 @@ # Using $(em-config CACHE)/sysroot/usr seems to work, though, and still has cmake find the # dependencies automatically. FROM emscripten/emsdk:3.1.19 AS base -LABEL version="17" +LABEL version="18" ADD emscripten.jam /usr/src RUN set -ex && \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index 02cb05be5..aae11521e 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-clang:latest as base -LABEL version="6" +LABEL version="7" ARG DEBIAN_FRONTEND=noninteractive diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index 9f331e1b8..8b94fe9dd 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:focal AS base -LABEL version="23" +LABEL version="24" ARG DEBIAN_FRONTEND=noninteractive diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index 6bc1df143..90d5811c3 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="8" +LABEL version="9" ARG DEBIAN_FRONTEND=noninteractive diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang index de9ce4efb..b2f75b0e4 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="7" +LABEL version="8" ARG DEBIAN_FRONTEND=noninteractive From 128b17259c468fbe8a7b1f8219d9d8ab891f43f2 Mon Sep 17 00:00:00 2001 From: r0qs Date: Thu, 16 May 2024 16:46:24 +0200 Subject: [PATCH 0156/1340] Install cvc5 on OSX --- .circleci/osx_install_dependencies.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index 87383ba8f..5436c31fe 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -84,6 +84,16 @@ then sudo mv /tmp/eldarica/{eld,eld-client,target,eldEnv} /usr/local/bin rm -rf /tmp/{eldarica,eld_binaries.zip} + #cvc5 + cvc5_version="1.1.2" + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-macOS-arm64-static.zip" -O /tmp/cvc5.zip + validate_checksum /tmp/cvc5.zip 2017d683d924676cb713865c6d4fcf70115c65b7ec2848f242ab938902f115b5 + unzip /tmp/cvc5.zip -x "cvc5-macOS-arm64-static/lib/cmake/*" -d /tmp + sudo mv /tmp/cvc5-macOS-arm64-static/bin/* /usr/local/bin + sudo mv /tmp/cvc5-macOS-arm64-static/include/* /usr/local/include + sudo mv /tmp/cvc5-macOS-arm64-static/lib/* /usr/local/lib + rm -rf /tmp/{cvc5-macOS-arm64-static,cvc5.zip} + # z3 z3_version="4.12.1" z3_dir="z3-z3-$z3_version" From b8ba5da12f7a6d7622a535b08e6c93bff9384917 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Mon, 6 May 2024 18:58:58 +0200 Subject: [PATCH 0157/1340] SMTChecker: Upgrade CVC4 to cvc5 Instead of compiling `solc` itself with CVC4 support, it is now enough to have `cvc5` executable on PATH when running the compiler. Instead of using API of CVC4, we now use SMT-LIB2 interface. That means we write the queries to temporary SMT-LIB2 files and call the solver process directly to run on the file. --- .circleci/config.yml | 4 +- CMakeLists.txt | 10 +- Changelog.md | 1 + cmake/EthCompilerSettings.cmake | 1 - cmake/FindCVC4.cmake | 33 -- cmake/toolchains/libfuzzer.cmake | 3 +- cmake/toolchains/ossfuzz.cmake | 3 +- docs/installing-solidity.rst | 9 - docs/smtchecker.rst | 6 +- docs/using-the-compiler.rst | 2 +- libsmtutil/CMakeLists.txt | 12 +- libsmtutil/CVC4Interface.cpp | 336 ------------------ libsmtutil/CVC4Interface.h | 74 ---- libsmtutil/SMTLib2Interface.cpp | 6 +- libsmtutil/SMTPortfolio.cpp | 9 +- libsmtutil/SolverInterface.h | 18 +- libsolidity/formal/BMC.cpp | 16 +- libsolidity/formal/ModelChecker.cpp | 14 +- libsolidity/interface/CompilerStack.cpp | 4 + libsolidity/interface/SMTSolverCommand.cpp | 30 +- libsolidity/interface/SMTSolverCommand.h | 1 + solc/CommandLineParser.cpp | 2 +- .../model_checker_print_query_all/err | 2 +- .../model_checker_print_query_bmc/err | 2 +- .../model_checker_solvers_cvc5/args | 1 + .../model_checker_solvers_cvc5/err | 10 + .../model_checker_solvers_cvc5/input.sol | 7 + .../model_checker_solvers_smtlib2/err | 2 +- .../output.json | 4 +- .../output.json | 4 +- .../output.json | 4 +- .../output.json | 4 +- test/libsolidity/SMTCheckerTest.h | 2 +- .../imports/duplicated_errors_1.sol | 4 +- 34 files changed, 99 insertions(+), 541 deletions(-) delete mode 100644 cmake/FindCVC4.cmake delete mode 100644 libsmtutil/CVC4Interface.cpp delete mode 100644 libsmtutil/CVC4Interface.h create mode 100644 test/cmdlineTests/model_checker_solvers_cvc5/args create mode 100644 test/cmdlineTests/model_checker_solvers_cvc5/err create mode 100644 test/cmdlineTests/model_checker_solvers_cvc5/input.sol diff --git a/.circleci/config.yml b/.circleci/config.yml index 5826067dd..3e65f4ac1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1044,7 +1044,7 @@ jobs: <<: *base_ubuntu2004_xlarge environment: <<: *base_ubuntu2204_xlarge_env - CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON + CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DSOLC_STATIC_STDLIBS=ON steps: - checkout - run_build @@ -1104,7 +1104,7 @@ jobs: environment: <<: *base_ubuntu2204_large_env CMAKE_BUILD_TYPE: Debug - CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 -DUSE_CVC4=OFF + CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 MAKEFLAGS: -j 10 steps: - checkout diff --git a/CMakeLists.txt b/CMakeLists.txt index b1a307afb..71f83b80e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,15 +133,11 @@ elseif (${Z3_FOUND}) message("Z3 SMT solver found. This enables optional SMT checking with Z3.") endif() -find_package(CVC4 QUIET) -if (${CVC4_FOUND}) - add_definitions(-DHAVE_CVC4) - message("CVC4 SMT solver found. This enables optional SMT checking with CVC4.") -endif() +find_program(CVC5_PATH cvc5) -if (NOT (${Z3_FOUND} OR ${CVC4_FOUND})) +if (NOT (${Z3_FOUND} OR CVC5_PATH)) message("No SMT solver found (or it has been forcefully disabled). Optional SMT checking will not be available.\ - \nPlease install Z3 or CVC4 or remove the option disabling them (USE_Z3, USE_CVC4).") + \nPlease install Z3 or cvc5 or remove the option disabling them (USE_Z3).") endif() add_subdirectory(libsolutil) diff --git a/Changelog.md b/Changelog.md index 2101f1ec9..1c15478d1 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Language Features: Compiler Features: * EVM: Support for the EVM version "Prague". * SMTChecker: Add CHC engine check for underflow and overflow in unary minus operation. + * SMTChecker: Replace CVC4 as a possible BMC backend with cvc5. Bugfixes: diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 5c2802d1f..eda0e404d 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -266,7 +266,6 @@ option(USE_Z3 "Allow compiling with Z3 SMT solver integration" ON) if(UNIX AND NOT APPLE) option(USE_Z3_DLOPEN "Dynamically load the Z3 SMT solver instead of linking against it." OFF) endif() -option(USE_CVC4 "Allow compiling with CVC4 SMT solver integration" ON) if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) option(USE_LD_GOLD "Use GNU gold linker" ON) diff --git a/cmake/FindCVC4.cmake b/cmake/FindCVC4.cmake deleted file mode 100644 index 887b907b8..000000000 --- a/cmake/FindCVC4.cmake +++ /dev/null @@ -1,33 +0,0 @@ -if (USE_CVC4) - find_path(CVC4_INCLUDE_DIR cvc4/cvc4.h) - find_library(CVC4_LIBRARY NAMES cvc4) - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(CVC4 DEFAULT_MSG CVC4_LIBRARY CVC4_INCLUDE_DIR) - if(CVC4_FOUND) - # CVC4 may depend on either CLN or GMP. - # We can assume that the one it requires is present on the system, - # so we quietly try to find both and link against them, if they are - # present. - find_package(CLN QUIET) - find_package(GMP QUIET) - - set(CVC4_LIBRARIES ${CVC4_LIBRARY}) - - if (CLN_FOUND) - set(CVC4_LIBRARIES ${CVC4_LIBRARIES} CLN::CLN) - endif () - - if (GMP_FOUND) - set(CVC4_LIBRARIES ${CVC4_LIBRARIES} GMP::GMP) - endif () - - if (NOT TARGET CVC4::CVC4) - add_library(CVC4::CVC4 UNKNOWN IMPORTED) - set_property(TARGET CVC4::CVC4 PROPERTY IMPORTED_LOCATION ${CVC4_LIBRARY}) - set_property(TARGET CVC4::CVC4 PROPERTY INTERFACE_LINK_LIBRARIES ${CVC4_LIBRARIES}) - set_property(TARGET CVC4::CVC4 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CVC4_INCLUDE_DIR}) - endif() - endif() -else() - set(CVC4_FOUND FALSE) -endif() diff --git a/cmake/toolchains/libfuzzer.cmake b/cmake/toolchains/libfuzzer.cmake index a734df975..9d83d504f 100644 --- a/cmake/toolchains/libfuzzer.cmake +++ b/cmake/toolchains/libfuzzer.cmake @@ -1,8 +1,7 @@ # Inherit default options include("${CMAKE_CURRENT_LIST_DIR}/default.cmake") -# Enable Z3, disable CVC4 +# Enable Z3 set(USE_Z3 ON CACHE BOOL "Enable Z3" FORCE) -set(USE_CVC4 OFF CACHE BOOL "Disable CVC4" FORCE) # Build fuzzing binaries set(OSSFUZZ ON CACHE BOOL "Enable fuzzer build" FORCE) # Use libfuzzer as the fuzzing back-end diff --git a/cmake/toolchains/ossfuzz.cmake b/cmake/toolchains/ossfuzz.cmake index fb7b8d0b3..88018db93 100644 --- a/cmake/toolchains/ossfuzz.cmake +++ b/cmake/toolchains/ossfuzz.cmake @@ -1,7 +1,6 @@ # Inherit default options include("${CMAKE_CURRENT_LIST_DIR}/default.cmake") -# Disable CVC4 and Z3. -set(USE_CVC4 OFF CACHE BOOL "Disable CVC4" FORCE) +# Disable Z3. set(USE_Z3 OFF CACHE BOOL "Disable Z3" FORCE) # Enable fuzzers set(OSSFUZZ ON CACHE BOOL "Enable fuzzer build" FORCE) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index f079fb024..e37fc1985 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -333,10 +333,7 @@ The following are dependencies for all builds of Solidity: +-----------------------------------+-------------------------------------------------------+ | `z3`_ (version 4.8.16+, Optional) | For use with SMT checker. | +-----------------------------------+-------------------------------------------------------+ -| `cvc4`_ (Optional) | For use with SMT checker. | -+-----------------------------------+-------------------------------------------------------+ -.. _cvc4: https://cvc4.cs.stanford.edu/web/ .. _Git: https://git-scm.com/download .. _Boost: https://www.boost.org .. _CMake: https://cmake.org/download/ @@ -543,12 +540,6 @@ Inside the build folder you can disable them, since they are enabled by default: # disables only Z3 SMT Solver. cmake .. -DUSE_Z3=OFF - # disables only CVC4 SMT Solver. - cmake .. -DUSE_CVC4=OFF - - # disables both Z3 and CVC4 - cmake .. -DUSE_CVC4=OFF -DUSE_Z3=OFF - The Version String in Detail ============================ diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index dfdcf4651..fc7978256 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -822,10 +822,10 @@ which is primarily an SMT solver and makes `Spacer `_ which does both. The user can choose which solvers should be used, if available, via the CLI -option ``--model-checker-solvers {all,cvc4,eld,smtlib2,z3}`` or the JSON option +option ``--model-checker-solvers {all,cvc5,eld,smtlib2,z3}`` or the JSON option ``settings.modelChecker.solvers=[smtlib2,z3]``, where: -- ``cvc4`` is only available if the ``solc`` binary is compiled with it. Only BMC uses ``cvc4``. +- ``cvc5`` is used via its binary which must be installed in the system. Only BMC uses ``cvc5``. - ``eld`` is used via its binary which must be installed in the system. Only CHC uses ``eld``, and only if ``z3`` is not enabled. - ``smtlib2`` outputs SMT/Horn queries in the `smtlib2 `_ format. These can be used together with the compiler's `callback mechanism `_ so that @@ -849,7 +849,7 @@ concerned about this option. More advanced users might apply this option to try alternative solvers on more complex problems. Please note that certain combinations of chosen engine and solver will lead to -the SMTChecker doing nothing, for example choosing CHC and ``cvc4``. +the SMTChecker doing nothing, for example choosing CHC and ``cvc5``. ******************************* Abstraction and False Positives diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 544f45142..1eb6631df 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -486,7 +486,7 @@ Input Description "showUnsupported": true, // Choose which solvers should be used, if available. // See the Formal Verification section for the solvers description. - "solvers": ["cvc4", "smtlib2", "z3"], + "solvers": ["cvc5", "smtlib2", "z3"], // Choose which targets should be checked: constantCondition, // underflow, overflow, divByZero, balance, assert, popEmptyArray, outOfBounds. // If the option is not given all targets are checked by default, diff --git a/libsmtutil/CMakeLists.txt b/libsmtutil/CMakeLists.txt index cb222e22c..005fbeb80 100644 --- a/libsmtutil/CMakeLists.txt +++ b/libsmtutil/CMakeLists.txt @@ -20,12 +20,6 @@ else() set(z3_SRCS) endif() -if (${CVC4_FOUND}) - set(cvc4_SRCS CVC4Interface.cpp CVC4Interface.h) -else() - set(cvc4_SRCS) -endif() - if (${USE_Z3_DLOPEN}) file(GLOB Z3_HEADERS ${Z3_HEADER_PATH}/z3*.h) set(Z3_WRAPPER ${CMAKE_CURRENT_BINARY_DIR}/z3wrapper.cpp) @@ -38,7 +32,7 @@ if (${USE_Z3_DLOPEN}) set(z3_SRCS ${z3_SRCS} ${Z3_WRAPPER} Z3Loader.cpp Z3Loader.h) endif() -add_library(smtutil ${sources} ${z3_SRCS} ${cvc4_SRCS}) +add_library(smtutil ${sources} ${z3_SRCS}) target_link_libraries(smtutil PUBLIC solutil Boost::boost) if (${USE_Z3_DLOPEN}) @@ -47,7 +41,3 @@ if (${USE_Z3_DLOPEN}) elseif (${Z3_FOUND}) target_link_libraries(smtutil PUBLIC z3::libz3) endif() - -if (${CVC4_FOUND}) - target_link_libraries(smtutil PUBLIC CVC4::CVC4) -endif() diff --git a/libsmtutil/CVC4Interface.cpp b/libsmtutil/CVC4Interface.cpp deleted file mode 100644 index f53c92ab5..000000000 --- a/libsmtutil/CVC4Interface.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* - 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 - -#include - -#include -#include - -#include - -using namespace solidity; -using namespace solidity::util; -using namespace solidity::smtutil; - -CVC4Interface::CVC4Interface(std::optional _queryTimeout): - SolverInterface(_queryTimeout), - m_solver(&m_context) -{ - reset(); -} - -void CVC4Interface::reset() -{ - m_variables.clear(); - m_solver.reset(); - m_solver.setOption("produce-models", true); - if (m_queryTimeout) - m_solver.setTimeLimit(*m_queryTimeout); - else - m_solver.setResourceLimit(resourceLimit); -} - -void CVC4Interface::push() -{ - m_solver.push(); -} - -void CVC4Interface::pop() -{ - m_solver.pop(); -} - -void CVC4Interface::declareVariable(std::string const& _name, SortPointer const& _sort) -{ - smtAssert(_sort, ""); - m_variables[_name] = m_context.mkVar(_name.c_str(), cvc4Sort(*_sort)); -} - -void CVC4Interface::addAssertion(Expression const& _expr) -{ - try - { - m_solver.assertFormula(toCVC4Expr(_expr)); - } - catch (CVC4::TypeCheckingException const& _e) - { - smtAssert(false, _e.what()); - } - catch (CVC4::LogicException const& _e) - { - smtAssert(false, _e.what()); - } - catch (CVC4::UnsafeInterruptException const& _e) - { - smtAssert(false, _e.what()); - } - catch (CVC4::Exception const& _e) - { - smtAssert(false, _e.what()); - } -} - -std::pair> CVC4Interface::check(std::vector const& _expressionsToEvaluate) -{ - CheckResult result; - std::vector values; - try - { - switch (m_solver.checkSat().isSat()) - { - case CVC4::Result::SAT: - result = CheckResult::SATISFIABLE; - break; - case CVC4::Result::UNSAT: - result = CheckResult::UNSATISFIABLE; - break; - case CVC4::Result::SAT_UNKNOWN: - result = CheckResult::UNKNOWN; - break; - default: - smtAssert(false, ""); - } - - if (result == CheckResult::SATISFIABLE && !_expressionsToEvaluate.empty()) - { - for (Expression const& e: _expressionsToEvaluate) - values.push_back(toString(m_solver.getValue(toCVC4Expr(e)))); - } - } - catch (CVC4::Exception const&) - { - result = CheckResult::ERROR; - values.clear(); - } - - return std::make_pair(result, values); -} - -CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr) -{ - // Variable - if (_expr.arguments.empty() && m_variables.count(_expr.name)) - return m_variables.at(_expr.name); - - std::vector arguments; - for (auto const& arg: _expr.arguments) - arguments.push_back(toCVC4Expr(arg)); - - try - { - std::string const& n = _expr.name; - // Function application - if (!arguments.empty() && m_variables.count(_expr.name)) - return m_context.mkExpr(CVC4::kind::APPLY_UF, m_variables.at(n), arguments); - // Literal - else if (arguments.empty()) - { - if (n == "true") - return m_context.mkConst(true); - else if (n == "false") - return m_context.mkConst(false); - else if (auto sortSort = std::dynamic_pointer_cast(_expr.sort)) - return m_context.mkVar(n, cvc4Sort(*sortSort->inner)); - else - try - { - return m_context.mkConst(CVC4::Rational(n)); - } - catch (CVC4::TypeCheckingException const& _e) - { - smtAssert(false, _e.what()); - } - catch (CVC4::Exception const& _e) - { - smtAssert(false, _e.what()); - } - } - - smtAssert(_expr.hasCorrectArity(), ""); - if (n == "ite") - return arguments[0].iteExpr(arguments[1], arguments[2]); - else if (n == "not") - return arguments[0].notExpr(); - else if (n == "and") - return arguments[0].andExpr(arguments[1]); - else if (n == "or") - return arguments[0].orExpr(arguments[1]); - else if (n == "=>") - return m_context.mkExpr(CVC4::kind::IMPLIES, arguments[0], arguments[1]); - else if (n == "=") - return m_context.mkExpr(CVC4::kind::EQUAL, arguments[0], arguments[1]); - else if (n == "<") - return m_context.mkExpr(CVC4::kind::LT, arguments[0], arguments[1]); - else if (n == "<=") - return m_context.mkExpr(CVC4::kind::LEQ, arguments[0], arguments[1]); - else if (n == ">") - return m_context.mkExpr(CVC4::kind::GT, arguments[0], arguments[1]); - else if (n == ">=") - return m_context.mkExpr(CVC4::kind::GEQ, arguments[0], arguments[1]); - else if (n == "+") - return m_context.mkExpr(CVC4::kind::PLUS, arguments[0], arguments[1]); - else if (n == "-") - return m_context.mkExpr(CVC4::kind::MINUS, arguments[0], arguments[1]); - else if (n == "*") - return m_context.mkExpr(CVC4::kind::MULT, arguments[0], arguments[1]); - else if (n == "div") - return m_context.mkExpr(CVC4::kind::INTS_DIVISION_TOTAL, arguments[0], arguments[1]); - else if (n == "mod") - return m_context.mkExpr(CVC4::kind::INTS_MODULUS, arguments[0], arguments[1]); - else if (n == "bvnot") - return m_context.mkExpr(CVC4::kind::BITVECTOR_NOT, arguments[0]); - else if (n == "bvand") - return m_context.mkExpr(CVC4::kind::BITVECTOR_AND, arguments[0], arguments[1]); - else if (n == "bvor") - return m_context.mkExpr(CVC4::kind::BITVECTOR_OR, arguments[0], arguments[1]); - else if (n == "bvxor") - return m_context.mkExpr(CVC4::kind::BITVECTOR_XOR, arguments[0], arguments[1]); - else if (n == "bvshl") - return m_context.mkExpr(CVC4::kind::BITVECTOR_SHL, arguments[0], arguments[1]); - else if (n == "bvlshr") - return m_context.mkExpr(CVC4::kind::BITVECTOR_LSHR, arguments[0], arguments[1]); - else if (n == "bvashr") - return m_context.mkExpr(CVC4::kind::BITVECTOR_ASHR, arguments[0], arguments[1]); - else if (n == "int2bv") - { - size_t size = std::stoul(_expr.arguments[1].name); - auto i2bvOp = m_context.mkConst(CVC4::IntToBitVector(static_cast(size))); - // CVC4 treats all BVs as unsigned, so we need to manually apply 2's complement if needed. - return m_context.mkExpr( - CVC4::kind::ITE, - m_context.mkExpr(CVC4::kind::GEQ, arguments[0], m_context.mkConst(CVC4::Rational(0))), - m_context.mkExpr(CVC4::kind::INT_TO_BITVECTOR, i2bvOp, arguments[0]), - m_context.mkExpr( - CVC4::kind::BITVECTOR_NEG, - m_context.mkExpr(CVC4::kind::INT_TO_BITVECTOR, i2bvOp, m_context.mkExpr(CVC4::kind::UMINUS, arguments[0])) - ) - ); - } - else if (n == "bv2int") - { - auto intSort = std::dynamic_pointer_cast(_expr.sort); - smtAssert(intSort, ""); - auto nat = m_context.mkExpr(CVC4::kind::BITVECTOR_TO_NAT, arguments[0]); - if (!intSort->isSigned) - return nat; - - auto type = arguments[0].getType(); - smtAssert(type.isBitVector(), ""); - auto size = CVC4::BitVectorType(type).getSize(); - // CVC4 treats all BVs as unsigned, so we need to manually apply 2's complement if needed. - auto extractOp = m_context.mkConst(CVC4::BitVectorExtract(size - 1, size - 1)); - return m_context.mkExpr(CVC4::kind::ITE, - m_context.mkExpr( - CVC4::kind::EQUAL, - m_context.mkExpr(CVC4::kind::BITVECTOR_EXTRACT, extractOp, arguments[0]), - m_context.mkConst(CVC4::BitVector(1, uint64_t{0})) - ), - nat, - m_context.mkExpr( - CVC4::kind::UMINUS, - m_context.mkExpr(CVC4::kind::BITVECTOR_TO_NAT, m_context.mkExpr(CVC4::kind::BITVECTOR_NEG, arguments[0])) - ) - ); - } - else if (n == "select") - return m_context.mkExpr(CVC4::kind::SELECT, arguments[0], arguments[1]); - else if (n == "store") - return m_context.mkExpr(CVC4::kind::STORE, arguments[0], arguments[1], arguments[2]); - else if (n == "const_array") - { - std::shared_ptr sortSort = std::dynamic_pointer_cast(_expr.arguments[0].sort); - smtAssert(sortSort, ""); - return m_context.mkConst(CVC4::ArrayStoreAll(cvc4Sort(*sortSort->inner), arguments[1])); - } - else if (n == "tuple_get") - { - std::shared_ptr tupleSort = std::dynamic_pointer_cast(_expr.arguments[0].sort); - smtAssert(tupleSort, ""); - CVC4::DatatypeType tt = m_context.mkTupleType(cvc4Sort(tupleSort->components)); - CVC4::Datatype const& dt = tt.getDatatype(); - size_t index = std::stoul(_expr.arguments[1].name); - CVC4::Expr s = dt[0][index].getSelector(); - return m_context.mkExpr(CVC4::kind::APPLY_SELECTOR, s, arguments[0]); - } - else if (n == "tuple_constructor") - { - std::shared_ptr tupleSort = std::dynamic_pointer_cast(_expr.sort); - smtAssert(tupleSort, ""); - CVC4::DatatypeType tt = m_context.mkTupleType(cvc4Sort(tupleSort->components)); - CVC4::Datatype const& dt = tt.getDatatype(); - CVC4::Expr c = dt[0].getConstructor(); - return m_context.mkExpr(CVC4::kind::APPLY_CONSTRUCTOR, c, arguments); - } - - smtAssert(false); - } - catch (CVC4::TypeCheckingException const& _e) - { - smtAssert(false, _e.what()); - } - catch (CVC4::Exception const& _e) - { - smtAssert(false, _e.what()); - } - - smtAssert(false); - - // FIXME: Workaround for spurious GCC 12.1 warning (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105794) - util::unreachable(); -} - -CVC4::Type CVC4Interface::cvc4Sort(Sort const& _sort) -{ - switch (_sort.kind) - { - case Kind::Bool: - return m_context.booleanType(); - case Kind::Int: - return m_context.integerType(); - case Kind::BitVector: - return m_context.mkBitVectorType(dynamic_cast(_sort).size); - case Kind::Function: - { - FunctionSort const& fSort = dynamic_cast(_sort); - return m_context.mkFunctionType(cvc4Sort(fSort.domain), cvc4Sort(*fSort.codomain)); - } - case Kind::Array: - { - auto const& arraySort = dynamic_cast(_sort); - return m_context.mkArrayType(cvc4Sort(*arraySort.domain), cvc4Sort(*arraySort.range)); - } - case Kind::Tuple: - { - auto const& tupleSort = dynamic_cast(_sort); - return m_context.mkTupleType(cvc4Sort(tupleSort.components)); - } - default: - break; - } - smtAssert(false, ""); - // Cannot be reached. - return m_context.integerType(); -} - -std::vector CVC4Interface::cvc4Sort(std::vector const& _sorts) -{ - std::vector cvc4Sorts; - for (auto const& _sort: _sorts) - cvc4Sorts.push_back(cvc4Sort(*_sort)); - return cvc4Sorts; -} diff --git a/libsmtutil/CVC4Interface.h b/libsmtutil/CVC4Interface.h deleted file mode 100644 index cc3c0577c..000000000 --- a/libsmtutil/CVC4Interface.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - 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 - -#pragma once - -#include - -#if defined(__GLIBC__) -// The CVC4 headers includes the deprecated system headers -// and . These headers cause a warning that will break the -// build, unless _GLIBCXX_PERMIT_BACKWARD_HASH is set. -#define _GLIBCXX_PERMIT_BACKWARD_HASH -#endif - -#include - -#if defined(__GLIBC__) -#undef _GLIBCXX_PERMIT_BACKWARD_HASH -#endif - -namespace solidity::smtutil -{ - -class CVC4Interface: public SolverInterface -{ -public: - /// Noncopyable. - CVC4Interface(CVC4Interface const&) = delete; - CVC4Interface& operator=(CVC4Interface const&) = delete; - - CVC4Interface(std::optional _queryTimeout = {}); - - void reset() override; - - void push() override; - void pop() override; - - void declareVariable(std::string const&, SortPointer const&) override; - - void addAssertion(Expression const& _expr) override; - std::pair> check(std::vector const& _expressionsToEvaluate) override; - -private: - CVC4::Expr toCVC4Expr(Expression const& _expr); - CVC4::Type cvc4Sort(Sort const& _sort); - std::vector cvc4Sort(std::vector const& _sorts); - - CVC4::ExprManager m_context; - CVC4::SmtEngine m_solver; - std::map m_variables; - - // CVC4 "basic resources" limit. - // This is used to make the runs more deterministic and platform/machine independent. - // The tests start failing for CVC4 with less than 6000, - // so using double that. - static int const resourceLimit = 12000; -}; - -} diff --git a/libsmtutil/SMTLib2Interface.cpp b/libsmtutil/SMTLib2Interface.cpp index 12469a4ae..cfe1bc0be 100644 --- a/libsmtutil/SMTLib2Interface.cpp +++ b/libsmtutil/SMTLib2Interface.cpp @@ -123,11 +123,11 @@ std::pair> SMTLib2Interface::check(std::ve CheckResult result; // TODO proper parsing - if (boost::starts_with(response, "sat\n")) + if (boost::starts_with(response, "sat")) result = CheckResult::SATISFIABLE; - else if (boost::starts_with(response, "unsat\n")) + else if (boost::starts_with(response, "unsat")) result = CheckResult::UNSATISFIABLE; - else if (boost::starts_with(response, "unknown\n")) + else if (boost::starts_with(response, "unknown")) result = CheckResult::UNKNOWN; else result = CheckResult::ERROR; diff --git a/libsmtutil/SMTPortfolio.cpp b/libsmtutil/SMTPortfolio.cpp index 76c69d018..1435cc9d8 100644 --- a/libsmtutil/SMTPortfolio.cpp +++ b/libsmtutil/SMTPortfolio.cpp @@ -21,9 +21,6 @@ #ifdef HAVE_Z3 #include #endif -#ifdef HAVE_CVC4 -#include -#endif #include using namespace solidity; @@ -41,16 +38,12 @@ SMTPortfolio::SMTPortfolio( SolverInterface(_queryTimeout) { solAssert(!_printQuery || _enabledSolvers == smtutil::SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); - if (_enabledSolvers.smtlib2) + if (_enabledSolvers.smtlib2 || _enabledSolvers.cvc5) m_solvers.emplace_back(std::make_unique(std::move(_smtlib2Responses), std::move(_smtCallback), m_queryTimeout)); #ifdef HAVE_Z3 if (_enabledSolvers.z3 && Z3Interface::available()) m_solvers.emplace_back(std::make_unique(m_queryTimeout)); #endif -#ifdef HAVE_CVC4 - if (_enabledSolvers.cvc4) - m_solvers.emplace_back(std::make_unique(m_queryTimeout)); -#endif } void SMTPortfolio::reset() diff --git a/libsmtutil/SolverInterface.h b/libsmtutil/SolverInterface.h index 13803de6e..92f9c8f75 100644 --- a/libsmtutil/SolverInterface.h +++ b/libsmtutil/SolverInterface.h @@ -41,13 +41,13 @@ namespace solidity::smtutil struct SMTSolverChoice { - bool cvc4 = false; + bool cvc5 = false; bool eld = false; bool smtlib2 = false; bool z3 = false; static constexpr SMTSolverChoice All() noexcept { return {true, true, true, true}; } - static constexpr SMTSolverChoice CVC4() noexcept { return {true, false, false, false}; } + static constexpr SMTSolverChoice CVC5() noexcept { return {true, false, false, false}; } static constexpr SMTSolverChoice ELD() noexcept { return {false, true, false, false}; } static constexpr SMTSolverChoice SMTLIB2() noexcept { return {false, false, true, false}; } static constexpr SMTSolverChoice Z3() noexcept { return {false, false, false, true}; } @@ -65,7 +65,7 @@ struct SMTSolverChoice SMTSolverChoice& operator&=(SMTSolverChoice const& _other) { - cvc4 &= _other.cvc4; + cvc5 &= _other.cvc5; eld &= _other.eld; smtlib2 &= _other.smtlib2; z3 &= _other.z3; @@ -82,7 +82,7 @@ struct SMTSolverChoice bool operator==(SMTSolverChoice const& _other) const noexcept { - return cvc4 == _other.cvc4 && + return cvc5 == _other.cvc5 && eld == _other.eld && smtlib2 == _other.smtlib2 && z3 == _other.z3; @@ -90,11 +90,11 @@ struct SMTSolverChoice bool setSolver(std::string const& _solver) { - static std::set const solvers{"cvc4", "eld", "smtlib2", "z3"}; + static std::set const solvers{"cvc5", "eld", "smtlib2", "z3"}; if (!solvers.count(_solver)) return false; - if (_solver == "cvc4") - cvc4 = true; + if (_solver == "cvc5") + cvc5 = true; if (_solver == "eld") eld = true; else if (_solver == "smtlib2") @@ -105,8 +105,8 @@ struct SMTSolverChoice } bool none() const noexcept { return !some(); } - bool some() const noexcept { return cvc4 || eld || smtlib2 || z3; } - bool all() const noexcept { return cvc4 && eld && smtlib2 && z3; } + bool some() const noexcept { return cvc5 || eld || smtlib2 || z3; } + bool all() const noexcept { return cvc5 && eld && smtlib2 && z3; } }; enum class CheckResult diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index e7cf35a7f..bf6080e7f 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -51,15 +51,15 @@ BMC::BMC( )) { solAssert(!_settings.printQuery || _settings.solvers == smtutil::SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); -#if defined (HAVE_Z3) || defined (HAVE_CVC4) - if (m_settings.solvers.cvc4 || m_settings.solvers.z3) +#if defined (HAVE_Z3) + if (m_settings.solvers.z3) if (!_smtlib2Responses.empty()) m_errorReporter.warning( 5622_error, "SMT-LIB2 query responses were given in the auxiliary input, " - "but this Solidity binary uses an SMT solver (Z3/CVC4) directly." + "but this Solidity binary uses an SMT solver Z3 directly." "These responses will be ignored." - "Consider disabling Z3/CVC4 at compilation time in order to use SMT-LIB2 responses." + "Consider disabling Z3 at compilation time in order to use SMT-LIB2 responses." ); #endif } @@ -67,13 +67,13 @@ BMC::BMC( void BMC::analyze(SourceUnit const& _source, std::map, smt::EncodingContext::IdCompare> _solvedTargets) { // At this point every enabled solver is available. - if (!m_settings.solvers.cvc4 && !m_settings.solvers.smtlib2 && !m_settings.solvers.z3) + if (!m_settings.solvers.cvc5 && !m_settings.solvers.smtlib2 && !m_settings.solvers.z3) { m_errorReporter.warning( 7710_error, SourceLocation(), "BMC analysis was not possible since no SMT solver was found and enabled." - " The accepted solvers for BMC are cvc4 and z3." + " The accepted solvers for BMC are cvc5 and z3." ); return; } @@ -123,7 +123,7 @@ void BMC::analyze(SourceUnit const& _source, std::map #endif -#if defined(__linux) || defined(__APPLE__) #include -#endif #include #include @@ -163,14 +161,10 @@ std::vector ModelChecker::unhandledQueries() SMTSolverChoice ModelChecker::availableSolvers() { smtutil::SMTSolverChoice available = smtutil::SMTSolverChoice::SMTLIB2(); -#if defined(__linux) || defined(__APPLE__) available.eld = !boost::process::search_path("eld").empty(); -#endif + available.cvc5 = !boost::process::search_path("cvc5").empty(); #ifdef HAVE_Z3 available.z3 = solidity::smtutil::Z3Interface::available(); -#endif -#ifdef HAVE_CVC4 - available.cvc4 = true; #endif return available; } @@ -179,13 +173,13 @@ SMTSolverChoice ModelChecker::checkRequestedSolvers(SMTSolverChoice _enabled, Er { SMTSolverChoice availableSolvers{ModelChecker::availableSolvers()}; - if (_enabled.cvc4 && !availableSolvers.cvc4) + if (_enabled.cvc5 && !availableSolvers.cvc5) { - _enabled.cvc4 = false; + _enabled.cvc5 = false; _errorReporter.warning( 4902_error, SourceLocation(), - "Solver CVC4 was selected for SMTChecker but it is not available." + "Solver cvc5 was selected for SMTChecker but it is not available." ); } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 2a9005680..d5fe44ca1 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -656,8 +656,12 @@ bool CompilerStack::analyzeLegacy(bool _noErrorsSoFar) { m_modelCheckerSettings.solvers = ModelChecker::checkRequestedSolvers(m_modelCheckerSettings.solvers, m_errorReporter); if (auto* universalCallback = m_readFile.target()) + { if (m_modelCheckerSettings.solvers.eld) universalCallback->smtCommand().setEldarica(m_modelCheckerSettings.timeout, m_modelCheckerSettings.invariants != ModelCheckerInvariants::None()); + if (m_modelCheckerSettings.solvers.cvc5) + universalCallback->smtCommand().setCvc5(m_modelCheckerSettings.timeout); + } } ModelChecker modelChecker(m_errorReporter, *this, m_smtlib2Responses, m_modelCheckerSettings, m_readFile); diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index 7d814cd9c..b9eb392c6 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -51,6 +51,22 @@ void SMTSolverCommand::setEldarica(std::optional timeoutInMillisec m_arguments.emplace_back("-ssol"); } +void SMTSolverCommand::setCvc5(std::optional timeoutInMilliseconds) +{ + m_arguments.clear(); + m_solverCmd = "cvc5"; + if (timeoutInMilliseconds) + { + m_arguments.push_back("--tlimit-per"); + m_arguments.push_back(std::to_string(timeoutInMilliseconds.value())); + } + else + { + m_arguments.push_back("--rlimit"); + m_arguments.push_back(std::to_string(12000)); + } +} + ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::string const& _query) { try @@ -68,29 +84,29 @@ ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::stri auto queryFile = boost::filesystem::ofstream(queryFileName); queryFile << _query << std::flush; - auto eldBin = boost::process::search_path(m_solverCmd); + auto solverBin = boost::process::search_path(m_solverCmd); - if (eldBin.empty()) + if (solverBin.empty()) return ReadCallback::Result{false, m_solverCmd + " binary not found."}; auto args = m_arguments; args.push_back(queryFileName.string()); boost::process::ipstream pipe; - boost::process::child eld( - eldBin, + boost::process::child solverProcess( + solverBin, args, boost::process::std_out > pipe, - boost::process::std_err >boost::process::null + boost::process::std_err > boost::process::null ); std::vector data; std::string line; - while (eld.running() && std::getline(pipe, line)) + while (solverProcess.running() && std::getline(pipe, line)) if (!line.empty()) data.push_back(line); - eld.wait(); + solverProcess.wait(); return ReadCallback::Result{true, boost::join(data, "\n")}; } diff --git a/libsolidity/interface/SMTSolverCommand.h b/libsolidity/interface/SMTSolverCommand.h index 665c19c1b..3b1022740 100644 --- a/libsolidity/interface/SMTSolverCommand.h +++ b/libsolidity/interface/SMTSolverCommand.h @@ -37,6 +37,7 @@ class SMTSolverCommand } void setEldarica(std::optional timeoutInMilliseconds, bool computeInvariants); + void setCvc5(std::optional timeoutInMilliseconds); private: /// The name of the solver's binary. diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index e61c5ce0a..2697f7ebd 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -877,7 +877,7 @@ General Information)").c_str(), ) ( g_strModelCheckerSolvers.c_str(), - po::value()->value_name("cvc4,eld,z3,smtlib2")->default_value("z3"), + po::value()->value_name("cvc5,eld,z3,smtlib2")->default_value("z3"), "Select model checker solvers." ) ( diff --git a/test/cmdlineTests/model_checker_print_query_all/err b/test/cmdlineTests/model_checker_print_query_all/err index 1a04042cd..fc3bf7c7a 100644 --- a/test/cmdlineTests/model_checker_print_query_all/err +++ b/test/cmdlineTests/model_checker_print_query_all/err @@ -162,4 +162,4 @@ Info: BMC: Requested query: Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. -Warning: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled. +Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. diff --git a/test/cmdlineTests/model_checker_print_query_bmc/err b/test/cmdlineTests/model_checker_print_query_bmc/err index 1a59f87b0..ff8b796f8 100644 --- a/test/cmdlineTests/model_checker_print_query_bmc/err +++ b/test/cmdlineTests/model_checker_print_query_bmc/err @@ -29,4 +29,4 @@ Info: BMC: Requested query: Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. -Warning: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled. +Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. diff --git a/test/cmdlineTests/model_checker_solvers_cvc5/args b/test/cmdlineTests/model_checker_solvers_cvc5/args new file mode 100644 index 000000000..84280d406 --- /dev/null +++ b/test/cmdlineTests/model_checker_solvers_cvc5/args @@ -0,0 +1 @@ +--model-checker-engine bmc --model-checker-solvers cvc5 diff --git a/test/cmdlineTests/model_checker_solvers_cvc5/err b/test/cmdlineTests/model_checker_solvers_cvc5/err new file mode 100644 index 000000000..1c36b103a --- /dev/null +++ b/test/cmdlineTests/model_checker_solvers_cvc5/err @@ -0,0 +1,10 @@ +Warning: BMC: Assertion violation happens here. + --> model_checker_solvers_cvc5/input.sol:5:3: + | +5 | assert(x > 0); + | ^^^^^^^^^^^^^ +Note: Counterexample: + x = 0 + +Note: Callstack: +Note: diff --git a/test/cmdlineTests/model_checker_solvers_cvc5/input.sol b/test/cmdlineTests/model_checker_solvers_cvc5/input.sol new file mode 100644 index 000000000..ef11e87eb --- /dev/null +++ b/test/cmdlineTests/model_checker_solvers_cvc5/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract test { + function f(uint x) public pure { + assert(x > 0); + } +} diff --git a/test/cmdlineTests/model_checker_solvers_smtlib2/err b/test/cmdlineTests/model_checker_solvers_smtlib2/err index 3aa989348..452e2b31d 100644 --- a/test/cmdlineTests/model_checker_solvers_smtlib2/err +++ b/test/cmdlineTests/model_checker_solvers_smtlib2/err @@ -4,4 +4,4 @@ Warning: CHC analysis was not possible. No Horn solver was available. None of th Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. -Warning: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled. +Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. diff --git a/test/cmdlineTests/standard_model_checker_print_query_all/output.json b/test/cmdlineTests/standard_model_checker_print_query_all/output.json index 16ff42e0c..97aa88579 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_all/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_all/output.json @@ -519,10 +519,10 @@ { "component": "general", "errorCode": "8084", - "formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled. + "formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. ", - "message": "BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled.", + "message": "BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.", "severity": "warning", "type": "Warning" } diff --git a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json index 1c9826ad2..9fd5f5929 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json @@ -108,10 +108,10 @@ { "component": "general", "errorCode": "8084", - "formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled. + "formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. ", - "message": "BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled.", + "message": "BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.", "severity": "warning", "type": "Warning" } diff --git a/test/cmdlineTests/standard_model_checker_solvers_none/output.json b/test/cmdlineTests/standard_model_checker_solvers_none/output.json index e8de49d1e..a36195e1c 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_none/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_none/output.json @@ -13,10 +13,10 @@ { "component": "general", "errorCode": "7710", - "formattedMessage": "Warning: BMC analysis was not possible since no SMT solver was found and enabled. The accepted solvers for BMC are cvc4 and z3. + "formattedMessage": "Warning: BMC analysis was not possible since no SMT solver was found and enabled. The accepted solvers for BMC are cvc5 and z3. ", - "message": "BMC analysis was not possible since no SMT solver was found and enabled. The accepted solvers for BMC are cvc4 and z3.", + "message": "BMC analysis was not possible since no SMT solver was found and enabled. The accepted solvers for BMC are cvc5 and z3.", "severity": "warning", "type": "Warning" } diff --git a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json index d3bdc6b7e..e97227076 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json @@ -187,10 +187,10 @@ { "component": "general", "errorCode": "8084", - "formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled. + "formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. ", - "message": "BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled.", + "message": "BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.", "severity": "warning", "type": "Warning" } diff --git a/test/libsolidity/SMTCheckerTest.h b/test/libsolidity/SMTCheckerTest.h index aa0f92121..6a1579152 100644 --- a/test/libsolidity/SMTCheckerTest.h +++ b/test/libsolidity/SMTCheckerTest.h @@ -56,7 +56,7 @@ class SMTCheckerTest: public SyntaxTest Set in m_modelCheckerSettings. SMTShowUnproved: `yes`, `no`, where the default is `yes`. Set in m_modelCheckerSettings. - SMTSolvers: `all`, `cvc4`, `z3`, `none`, where the default is `all`. + SMTSolvers: `all`, `cvc5`, `z3`, `none`, where the default is `all`. Set in m_modelCheckerSettings. BMCLoopIterations: number of loop iterations for BMC engine, the default is 1. Set in m_modelCheckerSettings. diff --git a/test/libsolidity/smtCheckerTests/imports/duplicated_errors_1.sol b/test/libsolidity/smtCheckerTests/imports/duplicated_errors_1.sol index a98ba962a..c225fe0b4 100644 --- a/test/libsolidity/smtCheckerTests/imports/duplicated_errors_1.sol +++ b/test/libsolidity/smtCheckerTests/imports/duplicated_errors_1.sol @@ -19,8 +19,8 @@ contract C is B { // Warning 6328: (b.sol:62-75): CHC: Assertion violation might happen here. // Warning 3996: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled. // Warning 7812: (b.sol:62-75): BMC: Assertion violation might happen here. -// Warning 8084: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled. +// Warning 8084: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. // Warning 6328: (c.sol:68-81): CHC: Assertion violation might happen here. // Warning 3996: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled. // Warning 7812: (c.sol:68-81): BMC: Assertion violation might happen here. -// Warning 8084: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled. +// Warning 8084: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. From 025f9a2cedd54fd77f3b0421887e05fe567527ab Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 15 May 2024 19:08:53 +0200 Subject: [PATCH 0158/1340] Update CI images --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3e65f4ac1..d6c3f33da 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,16 +9,16 @@ version: 2.1 parameters: ubuntu-2004-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-23 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:84a1fb8771236e8d9aa5c615a425b8929e56a6e4f150a60078c8d74a1ceaa6c2" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-24 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:b8b645fa7ab40d55f2d16eac295d16ca01ec51d32be7d668ae6eaecd47dbd763" ubuntu-2204-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-8 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:1c3a4118218640b2bf632242979a63d48f3d9c70d48be9574332f2dbbd04b192" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-9 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:80247de9655b1f39afd4ac22b14266bc9b9a0d64b283ae8fb9cb5b8250e4e77d" ubuntu-2204-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-7 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:0f47e733e100080c4174381c262cfcf974bc8e7c3c41b8dff611b9641c82f714" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-8 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:2662376fe0e1ec2d346495a19a6d64508c1048d5a7325d8600c33c343fa64a0f" ubuntu-clang-ossfuzz-docker-image: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-6 From 20ae0f2e07e1928f04ba212477019329956f66ad Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Sat, 1 Jun 2024 10:04:28 +0200 Subject: [PATCH 0159/1340] SMTChecker: Allow using multiple external solvers in one analysis We are using SMTCommand inside UniversalCallback to call external solvers on queries produced my our engines. Previous mechanism set the external solver once during initialization and it was not possible to change it later. This meant, that it would not be possible to use, e.g., Eldarica and cvc5 at the same time. Here we move the proper setup for SMTCommand just before we call it. This setup is customized by subclasses of (CHC)SmtLib2Interface, which call corresponding external solvers. --- libsmtutil/CHCSmtLib2Interface.cpp | 8 ++-- libsmtutil/CHCSmtLib2Interface.h | 11 ++--- libsmtutil/SMTLib2Interface.cpp | 1 + libsmtutil/SMTLib2Interface.h | 4 +- libsmtutil/SMTPortfolio.cpp | 23 +++-------- libsmtutil/SMTPortfolio.h | 8 +--- libsolidity/CMakeLists.txt | 4 ++ libsolidity/formal/BMC.cpp | 24 ++++++++--- libsolidity/formal/CHC.cpp | 17 ++++++-- libsolidity/formal/Cvc5SMTLib2Interface.cpp | 35 ++++++++++++++++ libsolidity/formal/Cvc5SMTLib2Interface.h | 37 +++++++++++++++++ .../formal/EldaricaCHCSmtLib2Interface.cpp | 37 +++++++++++++++++ .../formal/EldaricaCHCSmtLib2Interface.h | 41 +++++++++++++++++++ libsolidity/interface/CompilerStack.cpp | 9 ---- .../model_checker_solvers_cvc5_eld/args | 1 + .../model_checker_solvers_cvc5_eld/err | 8 ++++ .../model_checker_solvers_cvc5_eld/input.sol | 10 +++++ 17 files changed, 224 insertions(+), 54 deletions(-) create mode 100644 libsolidity/formal/Cvc5SMTLib2Interface.cpp create mode 100644 libsolidity/formal/Cvc5SMTLib2Interface.h create mode 100644 libsolidity/formal/EldaricaCHCSmtLib2Interface.cpp create mode 100644 libsolidity/formal/EldaricaCHCSmtLib2Interface.h create mode 100644 test/cmdlineTests/model_checker_solvers_cvc5_eld/args create mode 100644 test/cmdlineTests/model_checker_solvers_cvc5_eld/err create mode 100644 test/cmdlineTests/model_checker_solvers_cvc5_eld/input.sol diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index 671ec9b51..a267a843b 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -43,16 +43,14 @@ using namespace solidity::frontend; using namespace solidity::smtutil; CHCSmtLib2Interface::CHCSmtLib2Interface( - std::map const& _queryResponses, + std::map _queryResponses, ReadCallback::Callback _smtCallback, - SMTSolverChoice _enabledSolvers, std::optional _queryTimeout ): CHCSolverInterface(_queryTimeout), m_smtlib2(std::make_unique(_queryResponses, _smtCallback, m_queryTimeout)), m_queryResponses(std::move(_queryResponses)), - m_smtCallback(_smtCallback), - m_enabledSolvers(_enabledSolvers) + m_smtCallback(_smtCallback) { reset(); } @@ -186,9 +184,9 @@ std::string CHCSmtLib2Interface::querySolver(std::string const& _input) if (m_queryResponses.count(inputHash)) return m_queryResponses.at(inputHash); - smtAssert(m_enabledSolvers.smtlib2 || m_enabledSolvers.eld); if (m_smtCallback) { + setupSmtCallback(); auto result = m_smtCallback(ReadCallback::kindString(ReadCallback::Kind::SMTQuery), _input); if (result.success) return result.responseOrErrorMessage; diff --git a/libsmtutil/CHCSmtLib2Interface.h b/libsmtutil/CHCSmtLib2Interface.h index f7f656fd0..39131973b 100644 --- a/libsmtutil/CHCSmtLib2Interface.h +++ b/libsmtutil/CHCSmtLib2Interface.h @@ -33,9 +33,8 @@ class CHCSmtLib2Interface: public CHCSolverInterface { public: explicit CHCSmtLib2Interface( - std::map const& _queryResponses = {}, + std::map _queryResponses = {}, frontend::ReadCallback::Callback _smtCallback = {}, - SMTSolverChoice _enabledSolvers = SMTSolverChoice::All(), std::optional _queryTimeout = {} ); @@ -59,7 +58,7 @@ class CHCSmtLib2Interface: public CHCSolverInterface auto const& sortNames() const { return m_smtlib2->sortNames(); } -private: +protected: std::string toSmtLibSort(SortPointer _sort); std::string toSmtLibSort(std::vector const& _sort); @@ -79,17 +78,19 @@ class CHCSmtLib2Interface: public CHCSolverInterface /// Translates CHC solver response with a model to our representation of invariants. Returns None on error. std::optional invariantsFromSolverResponse(std::string const& response) const; + /// Hook to setup external solver call + virtual void setupSmtCallback() {} + /// Used to access toSmtLibSort, SExpr, and handle variables. std::unique_ptr m_smtlib2; std::string m_accumulatedOutput; std::set m_variables; - std::map const& m_queryResponses; + std::map m_queryResponses; std::vector m_unhandledQueries; frontend::ReadCallback::Callback m_smtCallback; - SMTSolverChoice m_enabledSolvers; }; } diff --git a/libsmtutil/SMTLib2Interface.cpp b/libsmtutil/SMTLib2Interface.cpp index cfe1bc0be..06ed26f2b 100644 --- a/libsmtutil/SMTLib2Interface.cpp +++ b/libsmtutil/SMTLib2Interface.cpp @@ -322,6 +322,7 @@ std::string SMTLib2Interface::querySolver(std::string const& _input) return m_queryResponses.at(inputHash); if (m_smtCallback) { + setupSmtCallback(); auto result = m_smtCallback(ReadCallback::kindString(ReadCallback::Kind::SMTQuery), _input); if (result.success) return result.responseOrErrorMessage; diff --git a/libsmtutil/SMTLib2Interface.h b/libsmtutil/SMTLib2Interface.h index fbfde664d..d60a5bd25 100644 --- a/libsmtutil/SMTLib2Interface.h +++ b/libsmtutil/SMTLib2Interface.h @@ -71,7 +71,9 @@ class SMTLib2Interface: public SolverInterface std::string dumpQuery(std::vector const& _expressionsToEvaluate); -private: +protected: + virtual void setupSmtCallback() {} + void declareFunction(std::string const& _name, SortPointer const& _sort); void write(std::string _data); diff --git a/libsmtutil/SMTPortfolio.cpp b/libsmtutil/SMTPortfolio.cpp index 1435cc9d8..196f02fdf 100644 --- a/libsmtutil/SMTPortfolio.cpp +++ b/libsmtutil/SMTPortfolio.cpp @@ -18,9 +18,6 @@ #include -#ifdef HAVE_Z3 -#include -#endif #include using namespace solidity; @@ -29,22 +26,12 @@ using namespace solidity::frontend; using namespace solidity::smtutil; SMTPortfolio::SMTPortfolio( - std::map _smtlib2Responses, - frontend::ReadCallback::Callback _smtCallback, - [[maybe_unused]] SMTSolverChoice _enabledSolvers, - std::optional _queryTimeout, - bool _printQuery + std::vector> _solvers, + std::optional _queryTimeout ): - SolverInterface(_queryTimeout) -{ - solAssert(!_printQuery || _enabledSolvers == smtutil::SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); - if (_enabledSolvers.smtlib2 || _enabledSolvers.cvc5) - m_solvers.emplace_back(std::make_unique(std::move(_smtlib2Responses), std::move(_smtCallback), m_queryTimeout)); -#ifdef HAVE_Z3 - if (_enabledSolvers.z3 && Z3Interface::available()) - m_solvers.emplace_back(std::make_unique(m_queryTimeout)); -#endif -} + SolverInterface(_queryTimeout), m_solvers(std::move(_solvers)) +{} + void SMTPortfolio::reset() { diff --git a/libsmtutil/SMTPortfolio.h b/libsmtutil/SMTPortfolio.h index cdb33368e..5ffb37eb3 100644 --- a/libsmtutil/SMTPortfolio.h +++ b/libsmtutil/SMTPortfolio.h @@ -42,13 +42,7 @@ class SMTPortfolio: public SolverInterface SMTPortfolio(SMTPortfolio const&) = delete; SMTPortfolio& operator=(SMTPortfolio const&) = delete; - SMTPortfolio( - std::map _smtlib2Responses = {}, - frontend::ReadCallback::Callback _smtCallback = {}, - SMTSolverChoice _enabledSolvers = SMTSolverChoice::All(), - std::optional _queryTimeout = {}, - bool _printQuery = false - ); + SMTPortfolio(std::vector> solvers, std::optional _queryTimeout); void reset() override; diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 3db857241..0b796035d 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -109,6 +109,10 @@ set(sources formal/BMC.h formal/CHC.cpp formal/CHC.h + formal/Cvc5SMTLib2Interface.cpp + formal/Cvc5SMTLib2Interface.h + formal/EldaricaCHCSmtLib2Interface.cpp + formal/EldaricaCHCSmtLib2Interface.h formal/EncodingContext.cpp formal/EncodingContext.h formal/ExpressionFormatter.cpp diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index bf6080e7f..916bf5a31 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -18,9 +18,14 @@ #include +#include #include +#include #include +#ifdef HAVE_Z3 +#include +#endif #include #include @@ -35,6 +40,8 @@ using namespace solidity; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::frontend; +using namespace solidity::frontend::smt; +using namespace solidity::smtutil; BMC::BMC( smt::EncodingContext& _context, @@ -45,12 +52,19 @@ BMC::BMC( ModelCheckerSettings _settings, CharStreamProvider const& _charStreamProvider ): - SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _charStreamProvider), - m_interface(std::make_unique( - _smtlib2Responses, _smtCallback, _settings.solvers, _settings.timeout, _settings.printQuery - )) + SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _charStreamProvider) { - solAssert(!_settings.printQuery || _settings.solvers == smtutil::SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); + solAssert(!_settings.printQuery || _settings.solvers == SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); + std::vector> solvers; + if (_settings.solvers.smtlib2) + solvers.emplace_back(std::make_unique(_smtlib2Responses, _smtCallback, _settings.timeout)); + if (_settings.solvers.cvc5) + solvers.emplace_back(std::make_unique(_smtCallback, _settings.timeout)); +#ifdef HAVE_Z3 + if (_settings.solvers.z3 && Z3Interface::available()) + solvers.emplace_back(std::make_unique(_settings.timeout)); +#endif + m_interface = std::make_unique(std::move(solvers), _settings.timeout); #if defined (HAVE_Z3) if (m_settings.solvers.z3) if (!_smtlib2Responses.empty()) diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index c520d13f6..66ebd47ed 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -25,6 +25,7 @@ #endif #include +#include #include #include #include @@ -1289,15 +1290,23 @@ void CHC::resetSourceAnalysis() solAssert(false); #endif } - if (!m_settings.solvers.z3) + else { solAssert(m_settings.solvers.smtlib2 || m_settings.solvers.eld); - if (!m_interface) - m_interface = std::make_unique(m_smtlib2Responses, m_smtCallback, m_settings.solvers, m_settings.timeout); + { + if (m_settings.solvers.eld) + m_interface = std::make_unique( + m_smtCallback, + m_settings.timeout, + m_settings.invariants != ModelCheckerInvariants::None() + ); + else + m_interface = std::make_unique(m_smtlib2Responses, m_smtCallback, m_settings.timeout); + } auto smtlib2Interface = dynamic_cast(m_interface.get()); - solAssert(smtlib2Interface, ""); + solAssert(smtlib2Interface); smtlib2Interface->reset(); m_context.setSolver(smtlib2Interface->smtlib2Interface()); } diff --git a/libsolidity/formal/Cvc5SMTLib2Interface.cpp b/libsolidity/formal/Cvc5SMTLib2Interface.cpp new file mode 100644 index 000000000..8a399c135 --- /dev/null +++ b/libsolidity/formal/Cvc5SMTLib2Interface.cpp @@ -0,0 +1,35 @@ +/* + 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 + +#include + +#include + +using namespace solidity::frontend::smt; + +Cvc5SMTLib2Interface::Cvc5SMTLib2Interface( + frontend::ReadCallback::Callback _smtCallback, + std::optional _queryTimeout +): SMTLib2Interface({}, std::move(_smtCallback), _queryTimeout) +{ +} + +void Cvc5SMTLib2Interface::setupSmtCallback() { + if (auto* universalCallback = m_smtCallback.target()) + universalCallback->smtCommand().setCvc5(m_queryTimeout); +} diff --git a/libsolidity/formal/Cvc5SMTLib2Interface.h b/libsolidity/formal/Cvc5SMTLib2Interface.h new file mode 100644 index 000000000..64bc364da --- /dev/null +++ b/libsolidity/formal/Cvc5SMTLib2Interface.h @@ -0,0 +1,37 @@ +/* + 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 + +#pragma once + +#include + +namespace solidity::frontend::smt +{ + +class Cvc5SMTLib2Interface: public smtutil::SMTLib2Interface +{ +public: + explicit Cvc5SMTLib2Interface( + frontend::ReadCallback::Callback _smtCallback = {}, + std::optional _queryTimeout = {} + ); +private: + void setupSmtCallback() override; +}; + +} diff --git a/libsolidity/formal/EldaricaCHCSmtLib2Interface.cpp b/libsolidity/formal/EldaricaCHCSmtLib2Interface.cpp new file mode 100644 index 000000000..4fa94539d --- /dev/null +++ b/libsolidity/formal/EldaricaCHCSmtLib2Interface.cpp @@ -0,0 +1,37 @@ +/* + 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 + +#include + +#include + +using namespace solidity::frontend::smt; + +EldaricaCHCSmtLib2Interface::EldaricaCHCSmtLib2Interface( + frontend::ReadCallback::Callback _smtCallback, + std::optional _queryTimeout, + bool computeInvariants +): CHCSmtLib2Interface({}, std::move(_smtCallback), _queryTimeout), m_computeInvariants(computeInvariants) +{ +} + +void EldaricaCHCSmtLib2Interface::setupSmtCallback() +{ + if (auto* universalCallback = m_smtCallback.target()) + universalCallback->smtCommand().setEldarica(m_queryTimeout, m_computeInvariants); +} diff --git a/libsolidity/formal/EldaricaCHCSmtLib2Interface.h b/libsolidity/formal/EldaricaCHCSmtLib2Interface.h new file mode 100644 index 000000000..2c83b194c --- /dev/null +++ b/libsolidity/formal/EldaricaCHCSmtLib2Interface.h @@ -0,0 +1,41 @@ +/* + 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 + +#pragma once + +#include + +namespace solidity::frontend::smt +{ + +class EldaricaCHCSmtLib2Interface: public smtutil::CHCSmtLib2Interface +{ +public: + EldaricaCHCSmtLib2Interface( + frontend::ReadCallback::Callback _smtCallback, + std::optional _queryTimeout, + bool computeInvariants + ); + +private: + void setupSmtCallback() override; + + bool m_computeInvariants; +}; + +} diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index d5fe44ca1..f9f1f0e64 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -653,16 +653,7 @@ bool CompilerStack::analyzeLegacy(bool _noErrorsSoFar) // m_modelCheckerSettings is spread to engines and solver interfaces, // so we need to check whether the enabled ones are available before building the classes. if (m_modelCheckerSettings.engine.any()) - { m_modelCheckerSettings.solvers = ModelChecker::checkRequestedSolvers(m_modelCheckerSettings.solvers, m_errorReporter); - if (auto* universalCallback = m_readFile.target()) - { - if (m_modelCheckerSettings.solvers.eld) - universalCallback->smtCommand().setEldarica(m_modelCheckerSettings.timeout, m_modelCheckerSettings.invariants != ModelCheckerInvariants::None()); - if (m_modelCheckerSettings.solvers.cvc5) - universalCallback->smtCommand().setCvc5(m_modelCheckerSettings.timeout); - } - } ModelChecker modelChecker(m_errorReporter, *this, m_smtlib2Responses, m_modelCheckerSettings, m_readFile); modelChecker.checkRequestedSourcesAndContracts(allSources); diff --git a/test/cmdlineTests/model_checker_solvers_cvc5_eld/args b/test/cmdlineTests/model_checker_solvers_cvc5_eld/args new file mode 100644 index 000000000..fb0c074ab --- /dev/null +++ b/test/cmdlineTests/model_checker_solvers_cvc5_eld/args @@ -0,0 +1 @@ +--model-checker-engine all --model-checker-solvers cvc5,eld diff --git a/test/cmdlineTests/model_checker_solvers_cvc5_eld/err b/test/cmdlineTests/model_checker_solvers_cvc5_eld/err new file mode 100644 index 000000000..81a9f3a56 --- /dev/null +++ b/test/cmdlineTests/model_checker_solvers_cvc5_eld/err @@ -0,0 +1,8 @@ +Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. + +Warning: BMC: Condition is always false. + --> model_checker_solvers_cvc5_eld/input.sol:6:7: + | +6 | if (y == 0) + | ^^^^^^ +Note: Callstack: diff --git a/test/cmdlineTests/model_checker_solvers_cvc5_eld/input.sol b/test/cmdlineTests/model_checker_solvers_cvc5_eld/input.sol new file mode 100644 index 000000000..eae2d9b48 --- /dev/null +++ b/test/cmdlineTests/model_checker_solvers_cvc5_eld/input.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract test { + function f() public pure { + uint y = 1; + if (y == 0) + revert(); + assert(y > 0); + } +} From b66df3e36f2660db1ad15e9ddf02042342d9db52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 5 Jun 2024 20:30:36 +0200 Subject: [PATCH 0160/1340] CompilerStack: Remove some misapplied std:: prefixes from comments and messages --- libsolidity/interface/CompilerStack.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index f9f1f0e64..0329aded6 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -279,7 +279,7 @@ void CompilerStack::setOptimiserSettings(OptimiserSettings _settings) void CompilerStack::setRevertStringBehaviour(RevertStrings _revertStrings) { if (m_stackState >= ParsedAndImported) - solThrow(CompilerError, "Must set revert std::string settings before parsing."); + solThrow(CompilerError, "Must set revert string settings before parsing."); solUnimplementedAssert(_revertStrings != RevertStrings::VerboseDebug); m_revertStrings = _revertStrings; } @@ -984,7 +984,7 @@ evmasm::LinkerObject const& CompilerStack::runtimeObject(std::string const& _con return contract(_contractName).runtimeObject; } -/// TODO: cache this std::string +/// TODO: cache this string std::string CompilerStack::assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const { if (m_stackState != CompilationSuccessful) From e2fb57b80b08d6d29af5b67aa53ce7341dbcf807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 5 Jun 2024 20:44:59 +0200 Subject: [PATCH 0161/1340] CompilerStack: Convert overzealous input validations to assertions --- libsolidity/interface/CompilerStack.cpp | 201 +++++++----------------- 1 file changed, 59 insertions(+), 142 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 0329aded6..a07310e2c 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -215,8 +215,7 @@ void CompilerStack::findAndReportCyclicContractDependencies() void CompilerStack::setRemappings(std::vector _remappings) { - if (m_stackState >= ParsedAndImported) - solThrow(CompilerError, "Must set remappings before parsing."); + solAssert(m_stackState < ParsedAndImported, "Must set remappings before parsing."); for (auto const& remapping: _remappings) solAssert(!remapping.prefix.empty(), ""); m_importRemapper.setRemappings(std::move(_remappings)); @@ -224,15 +223,13 @@ void CompilerStack::setRemappings(std::vector _remapp void CompilerStack::setViaIR(bool _viaIR) { - if (m_stackState >= ParsedAndImported) - solThrow(CompilerError, "Must set viaIR before parsing."); + solAssert(m_stackState < ParsedAndImported, "Must set viaIR before parsing."); m_viaIR = _viaIR; } void CompilerStack::setEVMVersion(langutil::EVMVersion _version) { - if (m_stackState >= ParsedAndImported) - solThrow(CompilerError, "Must set EVM version before parsing."); + solAssert(m_stackState < ParsedAndImported, "Must set EVM version before parsing."); m_evmVersion = _version; // GlobalContext depends on evmVersion since the Cancun hardfork. // Therefore, we reset it whenever we set a new EVM version, ensuring that the context is never reused with a mismatched version. @@ -241,24 +238,20 @@ void CompilerStack::setEVMVersion(langutil::EVMVersion _version) void CompilerStack::setEOFVersion(std::optional _version) { - if (m_stackState >= CompilationSuccessful) - solThrow(CompilerError, "Must set EOF version before compiling."); - if (_version && _version != 1) - solThrow(CompilerError, "Invalid EOF version."); + solAssert(m_stackState < CompilationSuccessful, "Must set EOF version before compiling."); + solAssert(!_version || _version == 1, "Invalid EOF version."); m_eofVersion = _version; } void CompilerStack::setModelCheckerSettings(ModelCheckerSettings _settings) { - if (m_stackState >= ParsedAndImported) - solThrow(CompilerError, "Must set model checking settings before parsing."); + solAssert(m_stackState < ParsedAndImported, "Must set model checking settings before parsing."); m_modelCheckerSettings = _settings; } void CompilerStack::setLibraries(std::map const& _libraries) { - if (m_stackState >= ParsedAndImported) - solThrow(CompilerError, "Must set libraries before parsing."); + solAssert(m_stackState < ParsedAndImported, "Must set libraries before parsing."); m_libraries = _libraries; } @@ -271,44 +264,38 @@ void CompilerStack::setOptimiserSettings(bool _optimize, size_t _runs) void CompilerStack::setOptimiserSettings(OptimiserSettings _settings) { - if (m_stackState >= ParsedAndImported) - solThrow(CompilerError, "Must set optimiser settings before parsing."); + solAssert(m_stackState < ParsedAndImported, "Must set optimiser settings before parsing."); m_optimiserSettings = std::move(_settings); } void CompilerStack::setRevertStringBehaviour(RevertStrings _revertStrings) { - if (m_stackState >= ParsedAndImported) - solThrow(CompilerError, "Must set revert string settings before parsing."); + solAssert(m_stackState < ParsedAndImported, "Must set revert string settings before parsing."); solUnimplementedAssert(_revertStrings != RevertStrings::VerboseDebug); m_revertStrings = _revertStrings; } void CompilerStack::useMetadataLiteralSources(bool _metadataLiteralSources) { - if (m_stackState >= ParsedAndImported) - solThrow(CompilerError, "Must set use literal sources before parsing."); + solAssert(m_stackState < ParsedAndImported, "Must set use literal sources before parsing."); m_metadataLiteralSources = _metadataLiteralSources; } void CompilerStack::setMetadataHash(MetadataHash _metadataHash) { - if (m_stackState >= ParsedAndImported) - solThrow(CompilerError, "Must set metadata hash before parsing."); + solAssert(m_stackState < ParsedAndImported, "Must set metadata hash before parsing."); m_metadataHash = _metadataHash; } void CompilerStack::selectDebugInfo(DebugInfoSelection _debugInfoSelection) { - if (m_stackState >= CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << util::errinfo_comment("Must select debug info components before compilation.")); + solAssert(m_stackState < CompilationSuccessful, "Must select debug info components before compilation."); m_debugInfoSelection = _debugInfoSelection; } void CompilerStack::addSMTLib2Response(h256 const& _hash, std::string const& _response) { - if (m_stackState >= ParsedAndImported) - solThrow(CompilerError, "Must add SMTLib2 responses before parsing."); + solAssert(m_stackState < ParsedAndImported, "Must add SMTLib2 responses before parsing."); m_smtlib2Responses[_hash] = _response; } @@ -344,10 +331,8 @@ void CompilerStack::reset(bool _keepSettings) void CompilerStack::setSources(StringMap _sources) { - if (m_stackState == SourcesSet) - solThrow(CompilerError, "Cannot change sources once set."); - if (m_stackState != Empty) - solThrow(CompilerError, "Must set sources before parsing."); + solAssert(m_stackState != SourcesSet, "Cannot change sources once set."); + solAssert(m_stackState == Empty, "Must set sources before parsing."); for (auto source: _sources) m_sources[source.first].charStream = std::make_unique(/*content*/std::move(source.second), /*name*/source.first); m_stackState = SourcesSet; @@ -355,8 +340,7 @@ void CompilerStack::setSources(StringMap _sources) bool CompilerStack::parse() { - if (m_stackState != SourcesSet) - solThrow(CompilerError, "Must call parse only after the SourcesSet state."); + solAssert(m_stackState == SourcesSet, "Must call parse only after the SourcesSet state."); m_errorReporter.clear(); if (SemVerVersion{std::string(VersionString)}.isPrerelease()) @@ -426,8 +410,7 @@ bool CompilerStack::parse() void CompilerStack::importASTs(std::map const& _sources) { - if (m_stackState != Empty) - solThrow(CompilerError, "Must call importASTs only before the SourcesSet state."); + solAssert(m_stackState == Empty, "Must call importASTs only before the SourcesSet state."); std::map> reconstructedSources = ASTJsonImporter(m_evmVersion).jsonToSourceUnit(_sources); for (auto& src: reconstructedSources) { @@ -450,8 +433,7 @@ void CompilerStack::importASTs(std::map const& _sources) bool CompilerStack::analyze() { - if (m_stackState != ParsedAndImported) - solThrow(CompilerError, "Must call analyze only after parsing was successful."); + solAssert(m_stackState == ParsedAndImported, "Must call analyze only after parsing was successful."); if (!resolveImports()) return false; @@ -797,8 +779,7 @@ void CompilerStack::link() std::vector CompilerStack::contractNames() const { - if (m_stackState < Parsed) - solThrow(CompilerError, "Parsing was not successful."); + solAssert(m_stackState >= Parsed, "Parsing was not successful."); std::vector contractNames; for (auto const& contract: m_contracts) contractNames.push_back(contract.first); @@ -807,8 +788,7 @@ std::vector CompilerStack::contractNames() const std::string const CompilerStack::lastContractName(std::optional const& _sourceName) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Parsing was not successful."); + solAssert(m_stackState >= AnalysisSuccessful, "Parsing was not successful."); // try to find some user-supplied contract std::string contractName; for (auto const& it: m_sources) @@ -820,8 +800,7 @@ std::string const CompilerStack::lastContractName(std::optional con evmasm::AssemblyItems const* CompilerStack::assemblyItems(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); Contract const& currentContract = contract(_contractName); return currentContract.evmAssembly ? ¤tContract.evmAssembly->items() : nullptr; @@ -829,8 +808,7 @@ evmasm::AssemblyItems const* CompilerStack::assemblyItems(std::string const& _co evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); Contract const& currentContract = contract(_contractName); return currentContract.evmRuntimeAssembly ? ¤tContract.evmRuntimeAssembly->items() : nullptr; @@ -838,8 +816,7 @@ evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(std::string con Json CompilerStack::generatedSources(std::string const& _contractName, bool _runtime) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); Contract const& c = contract(_contractName); util::LazyInit const& sources = @@ -880,8 +857,7 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run std::string const* CompilerStack::sourceMapping(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); Contract const& c = contract(_contractName); if (!c.sourceMapping) @@ -894,8 +870,7 @@ std::string const* CompilerStack::sourceMapping(std::string const& _contractName std::string const* CompilerStack::runtimeSourceMapping(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); Contract const& c = contract(_contractName); if (!c.runtimeSourceMapping) @@ -910,8 +885,7 @@ std::string const* CompilerStack::runtimeSourceMapping(std::string const& _contr std::string const CompilerStack::filesystemFriendlyName(std::string const& _contractName) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "No compiled contracts found."); + solAssert(m_stackState >= AnalysisSuccessful, "No compiled contracts found."); // Look up the contract (by its fully-qualified name) Contract const& matchContract = m_contracts.at(_contractName); @@ -934,61 +908,46 @@ std::string const CompilerStack::filesystemFriendlyName(std::string const& _cont std::string const& CompilerStack::yulIR(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); - + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); return contract(_contractName).yulIR; } Json const& CompilerStack::yulIRAst(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); - + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); - return contract(_contractName).yulIRAst; } std::string const& CompilerStack::yulIROptimized(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); - + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); return contract(_contractName).yulIROptimized; } Json const& CompilerStack::yulIROptimizedAst(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); - + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); - return contract(_contractName).yulIROptimizedAst; } evmasm::LinkerObject const& CompilerStack::object(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); - + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); return contract(_contractName).object; } evmasm::LinkerObject const& CompilerStack::runtimeObject(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); - + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); return contract(_contractName).runtimeObject; } /// TODO: cache this string std::string CompilerStack::assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); Contract const& currentContract = contract(_contractName); if (currentContract.evmAssembly) @@ -1000,9 +959,7 @@ std::string CompilerStack::assemblyString(std::string const& _contractName, Stri /// TODO: cache the JSON Json CompilerStack::assemblyJSON(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); - + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); Contract const& currentContract = contract(_contractName); @@ -1030,37 +987,28 @@ std::map CompilerStack::sourceIndices() const Json const& CompilerStack::contractABI(std::string const& _contractName) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); - + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); return contractABI(contract(_contractName)); } Json const& CompilerStack::contractABI(Contract const& _contract) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); - - solAssert(_contract.contract, ""); + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + solAssert(_contract.contract); solUnimplementedAssert(!isExperimentalSolidity()); - return _contract.abi.init([&]{ return ABI::generate(*_contract.contract); }); } Json const& CompilerStack::storageLayout(std::string const& _contractName) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); - + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); return storageLayout(contract(_contractName)); } Json const& CompilerStack::storageLayout(Contract const& _contract) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); - - solAssert(_contract.contract, ""); + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + solAssert(_contract.contract); solUnimplementedAssert(!isExperimentalSolidity()); return _contract.storageLayout.init([&]{ return StorageLayout().generate(*_contract.contract); }); @@ -1068,48 +1016,35 @@ Json const& CompilerStack::storageLayout(Contract const& _contract) const Json const& CompilerStack::natspecUser(std::string const& _contractName) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); - + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); return natspecUser(contract(_contractName)); } Json const& CompilerStack::natspecUser(Contract const& _contract) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); - - solAssert(_contract.contract, ""); + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + solAssert(_contract.contract); solUnimplementedAssert(!isExperimentalSolidity()); - return _contract.userDocumentation.init([&]{ return Natspec::userDocumentation(*_contract.contract); }); } Json const& CompilerStack::natspecDev(std::string const& _contractName) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); - + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); return natspecDev(contract(_contractName)); } Json const& CompilerStack::natspecDev(Contract const& _contract) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); - - solAssert(_contract.contract, ""); - + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + solAssert(_contract.contract); solUnimplementedAssert(!isExperimentalSolidity()); - return _contract.devDocumentation.init([&]{ return Natspec::devDocumentation(*_contract.contract); }); } Json CompilerStack::interfaceSymbols(std::string const& _contractName) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); - + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); Json interfaceSymbols; @@ -1139,50 +1074,36 @@ Json CompilerStack::interfaceSymbols(std::string const& _contractName) const bytes CompilerStack::cborMetadata(std::string const& _contractName, bool _forIR) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); - + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); return createCBORMetadata(contract(_contractName), _forIR); } std::string const& CompilerStack::metadata(Contract const& _contract) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); - - solAssert(_contract.contract, ""); - + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + solAssert(_contract.contract); solUnimplementedAssert(!isExperimentalSolidity()); - return _contract.metadata.init([&]{ return createMetadata(_contract, m_viaIR); }); } CharStream const& CompilerStack::charStream(std::string const& _sourceName) const { - if (m_stackState < SourcesSet) - solThrow(CompilerError, "No sources set."); - - solAssert(source(_sourceName).charStream, ""); - + solAssert(m_stackState >= SourcesSet, "No sources set."); + solAssert(source(_sourceName).charStream); return *source(_sourceName).charStream; } SourceUnit const& CompilerStack::ast(std::string const& _sourceName) const { - if (m_stackState < Parsed) - solThrow(CompilerError, "Parsing not yet performed."); - if (!source(_sourceName).ast) - solThrow(CompilerError, "Parsing was not successful."); - + solAssert(m_stackState >= Parsed, "Parsing not yet performed."); + solAssert(source(_sourceName).ast, "Parsing was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); - return *source(_sourceName).ast; } ContractDefinition const& CompilerStack::contractDefinition(std::string const& _contractName) const { - if (m_stackState < AnalysisSuccessful) - solThrow(CompilerError, "Analysis was not successful."); + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); return *contract(_contractName).contract; } @@ -1192,8 +1113,7 @@ size_t CompilerStack::functionEntryPoint( FunctionDefinition const& _function ) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); for (auto&& [name, data]: contract(_contractName).runtimeObject.functionDebugData) if (data.sourceID == _function.id()) @@ -1629,14 +1549,13 @@ CompilerStack::Contract const& CompilerStack::contract(std::string const& _contr } // If we get here, both lookup methods failed. - solThrow(CompilerError, "Contract \"" + _contractName + "\" not found."); + solAssert(false, "Contract \"" + _contractName + "\" not found."); } CompilerStack::Source const& CompilerStack::source(std::string const& _sourceName) const { auto it = m_sources.find(_sourceName); - if (it == m_sources.end()) - solThrow(CompilerError, "Given source file not found: " + _sourceName); + solAssert(it != m_sources.end(), "Given source file not found: " + _sourceName); return it->second; } @@ -1902,9 +1821,7 @@ Json gasToJson(GasEstimator::GasConsumption const& _gas) Json CompilerStack::gasEstimates(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); - + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); if (!assemblyItems(_contractName) && !runtimeAssemblyItems(_contractName)) From 12e8b0cda911ed4661773ee6cd9a2e341d8a77ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 6 Jun 2024 20:00:41 +0200 Subject: [PATCH 0162/1340] Use solAssert() instead of throwing InternalCompilerError directly --- libsolidity/codegen/ExpressionCompiler.cpp | 4 +--- libsolidity/codegen/LValue.cpp | 5 +---- libsolidity/interface/FileReader.cpp | 1 - libsolidity/interface/SMTSolverCommand.cpp | 4 ---- libsolidity/interface/StandardCompiler.cpp | 9 ++------- 5 files changed, 4 insertions(+), 19 deletions(-) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 54090f960..c7bc9a826 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -2952,9 +2952,7 @@ void ExpressionCompiler::setLValueFromDeclaration(Declaration const& _declaratio else if (m_context.isStateVariable(&_declaration)) setLValue(_expression, dynamic_cast(_declaration)); else - BOOST_THROW_EXCEPTION(InternalCompilerError() - << errinfo_sourceLocation(_expression.location()) - << util::errinfo_comment("Identifier type not supported or identifier not found.")); + solAssert(false, "Identifier type not supported or identifier not found."); } void ExpressionCompiler::setLValueToStorageItem(Expression const& _expression) diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 3fbf10383..4847cb093 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -441,10 +441,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc m_context << Instruction::SWAP1 << Instruction::POP; } else - BOOST_THROW_EXCEPTION( - InternalCompilerError() - << errinfo_sourceLocation(_location) - << util::errinfo_comment("Invalid non-value type for assignment.")); + solAssert(false, "Invalid non-value type for assignment."); } } diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index 158d4dd2c..15181acf6 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -31,7 +31,6 @@ #include using solidity::frontend::ReadCallback; -using solidity::langutil::InternalCompilerError; using solidity::util::errinfo_comment; using solidity::util::readFileAsString; using solidity::util::joinHumanReadable; diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index b9eb392c6..75f541692 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -30,10 +30,6 @@ #include #include -using solidity::langutil::InternalCompilerError; -using solidity::util::errinfo_comment; - - namespace solidity::frontend { diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index a54a9aa10..2b36f9032 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1463,13 +1463,8 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu // Note that not completing analysis due to stopAfter does not count as a failure. It's neither failure nor success. bool analysisFailed = !analysisSuccess && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisSuccessful; bool compilationFailed = !compilationSuccess && binariesRequested; - - /// Inconsistent state - stop here to receive error reports from users - if ( - (compilationFailed || analysisFailed || !parsingSuccess) && - errors.empty() - ) - return formatFatalError(Error::Type::InternalCompilerError, "No error reported, but compilation failed."); + if (compilationFailed || analysisFailed || !parsingSuccess) + solAssert(!errors.empty(), "No error reported, but compilation failed."); Json output; From 8d561e36aa1b7c1bb1965c8873657615daf87dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 6 Jun 2024 19:17:28 +0200 Subject: [PATCH 0163/1340] Assert presence of errors in case of FatalError instead of rethrowing --- libsolidity/analysis/NameAndTypeResolver.cpp | 16 +- libsolidity/interface/CompilerStack.cpp | 9 +- libsolidity/parsing/Parser.cpp | 5 +- libyul/AsmAnalysis.cpp | 9 +- libyul/AsmParser.cpp | 5 +- libyul/ObjectParser.cpp | 6 +- .../more_than_256_analysis_errors.yul | 279 ++++++++++++++++++ 7 files changed, 304 insertions(+), 25 deletions(-) create mode 100644 test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 642e87a53..941fbca9b 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -30,6 +30,7 @@ #include #include +using namespace std::string_literals; using namespace solidity::langutil; namespace solidity::frontend @@ -60,10 +61,9 @@ bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit, ASTNode { DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errorReporter, m_globalContext, _currentScope); } - catch (langutil::FatalError const&) + catch (langutil::FatalError const& error) { - if (m_errorReporter.errors().empty()) - throw; // Something is weird here, rather throw again. + solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); return false; } return true; @@ -135,10 +135,9 @@ bool NameAndTypeResolver::resolveNamesAndTypes(SourceUnit& _source) return false; } } - catch (langutil::FatalError const&) + catch (langutil::FatalError const& error) { - if (m_errorReporter.errors().empty()) - throw; // Something is weird here, rather throw again. + solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); return false; } return true; @@ -151,10 +150,9 @@ bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) m_scopes[nullptr]->registerDeclaration(_declaration, false, true); solAssert(_declaration.scope() == nullptr, "Updated declaration outside global scope."); } - catch (langutil::FatalError const&) + catch (langutil::FatalError const& error) { - if (m_errorReporter.errors().empty()) - throw; // Something is weird here, rather throw again. + solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); return false; } return true; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index a07310e2c..89a7a441a 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -489,10 +489,9 @@ bool CompilerStack::analyze() else if (!analyzeLegacy(noErrors)) noErrors = false; } - catch (FatalError const&) + catch (FatalError const& error) { - if (m_errorReporter.errors().empty()) - throw; // Something is weird here, rather throw again. + solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); noErrors = false; } @@ -1174,9 +1173,9 @@ StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast) } } } - catch (FatalError const&) + catch (FatalError const& error) { - solAssert(m_errorReporter.hasErrors(), ""); + solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); } return newSources; } diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index f650e0dbf..15a84c3f4 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -176,10 +176,9 @@ ASTPointer Parser::parse(CharStream& _charStream) solAssert(m_recursionDepth == 0, ""); return nodeFactory.createNode(findLicenseString(nodes), nodes, m_experimentalSolidityEnabledInCurrentSourceUnit); } - catch (FatalError const&) + catch (FatalError const& error) { - if (m_errorReporter.errors().empty()) - throw; // Something is weird here, rather throw again. + solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); return nullptr; } } diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 1972d2674..f85ef9544 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -74,10 +74,13 @@ bool AsmAnalyzer::analyze(Block const& _block) (*this)(_block); } - catch (FatalError const&) + catch (FatalError const& error) { - // This FatalError con occur if the errorReporter has too many errors. - yulAssert(!watcher.ok(), "Fatal error detected, but no error is reported."); + // NOTE: There's a cap on the number of reported errors, but watcher.ok() will work fine even if + // we exceed it because the reporter keeps counting (it just stops adding errors to the list). + // Note also that fact of exceeding the cap triggers a FatalError so one can get thrown even + // if we don't make any of our errors fatal. + yulAssert(!watcher.ok(), "Unreported fatal error: "s + error.what()); } return watcher.ok(); } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 3635b096a..7af648a36 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -37,6 +37,7 @@ #include #include +using namespace std::string_literals; using namespace solidity; using namespace solidity::util; using namespace solidity::langutil; @@ -126,9 +127,9 @@ std::unique_ptr Parser::parseInline(std::shared_ptr const& _scan fetchDebugDataFromComment(); return std::make_unique(parseBlock()); } - catch (FatalError const&) + catch (FatalError const& error) { - yulAssert(!m_errorReporter.errors().empty(), "Fatal error detected, but no error is reported."); + yulAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); } return nullptr; diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 2038959de..d0519be0e 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -32,6 +32,7 @@ #include +using namespace std::string_literals; using namespace solidity; using namespace solidity::yul; using namespace solidity::util; @@ -62,10 +63,9 @@ std::shared_ptr ObjectParser::parse(std::shared_ptr const& _sca expectToken(Token::EOS); return object; } - catch (FatalError const&) + catch (FatalError const& error) { - if (m_errorReporter.errors().empty()) - throw; // Something is weird here, rather throw again. + yulAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); } return nullptr; } diff --git a/test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul b/test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul new file mode 100644 index 000000000..0ae2fb15a --- /dev/null +++ b/test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul @@ -0,0 +1,279 @@ +{ + // There's no type called 'x' so every declaration here should trigger an error. + // It's only detected during analysis and is not fatal. Any other non-fatal analysis error would do. + let $00:x let $10:x let $20:x let $30:x let $40:x let $50:x let $60:x let $70:x let $80:x let $90:x let $a0:x let $b0:x let $c0:x let $d0:x let $e0:x let $f0:x + let $01:x let $11:x let $21:x let $31:x let $41:x let $51:x let $61:x let $71:x let $81:x let $91:x let $a1:x let $b1:x let $c1:x let $d1:x let $e1:x let $f1:x + let $02:x let $12:x let $22:x let $32:x let $42:x let $52:x let $62:x let $72:x let $82:x let $92:x let $a2:x let $b2:x let $c2:x let $d2:x let $e2:x let $f2:x + let $03:x let $13:x let $23:x let $33:x let $43:x let $53:x let $63:x let $73:x let $83:x let $93:x let $a3:x let $b3:x let $c3:x let $d3:x let $e3:x let $f3:x + let $04:x let $14:x let $24:x let $34:x let $44:x let $54:x let $64:x let $74:x let $84:x let $94:x let $a4:x let $b4:x let $c4:x let $d4:x let $e4:x let $f4:x + let $05:x let $15:x let $25:x let $35:x let $45:x let $55:x let $65:x let $75:x let $85:x let $95:x let $a5:x let $b5:x let $c5:x let $d5:x let $e5:x let $f5:x + let $06:x let $16:x let $26:x let $36:x let $46:x let $56:x let $66:x let $76:x let $86:x let $96:x let $a6:x let $b6:x let $c6:x let $d6:x let $e6:x let $f6:x + let $07:x let $17:x let $27:x let $37:x let $47:x let $57:x let $67:x let $77:x let $87:x let $97:x let $a7:x let $b7:x let $c7:x let $d7:x let $e7:x let $f7:x + let $08:x let $18:x let $28:x let $38:x let $48:x let $58:x let $68:x let $78:x let $88:x let $98:x let $a8:x let $b8:x let $c8:x let $d8:x let $e8:x let $f8:x + let $09:x let $19:x let $29:x let $39:x let $49:x let $59:x let $69:x let $79:x let $89:x let $99:x let $a9:x let $b9:x let $c9:x let $d9:x let $e9:x let $f9:x + let $0a:x let $1a:x let $2a:x let $3a:x let $4a:x let $5a:x let $6a:x let $7a:x let $8a:x let $9a:x let $aa:x let $ba:x let $ca:x let $da:x let $ea:x let $fa:x + let $0b:x let $1b:x let $2b:x let $3b:x let $4b:x let $5b:x let $6b:x let $7b:x let $8b:x let $9b:x let $ab:x let $bb:x let $cb:x let $db:x let $eb:x let $fb:x + let $0c:x let $1c:x let $2c:x let $3c:x let $4c:x let $5c:x let $6c:x let $7c:x let $8c:x let $9c:x let $ac:x let $bc:x let $cc:x let $dc:x let $ec:x let $fc:x + let $0d:x let $1d:x let $2d:x let $3d:x let $4d:x let $5d:x let $6d:x let $7d:x let $8d:x let $9d:x let $ad:x let $bd:x let $cd:x let $dd:x let $ed:x let $fd:x + let $0e:x let $1e:x let $2e:x let $3e:x let $4e:x let $5e:x let $6e:x let $7e:x let $8e:x let $9e:x let $ae:x let $be:x let $ce:x let $de:x let $ee:x let $fe:x + let $0f:x let $1f:x let $2f:x let $3f:x let $4f:x let $5f:x let $6f:x let $7f:x let $8f:x let $9f:x let $af:x let $bf:x let $cf:x let $df:x let $ef:x let $ff:x + let $100:x +} +// ---- +// TypeError 5473: (200-205): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (210-215): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (220-225): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (230-235): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (240-245): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (250-255): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (260-265): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (270-275): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (280-285): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (290-295): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (300-305): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (310-315): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (320-325): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (330-335): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (340-345): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (350-355): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (364-369): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (374-379): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (384-389): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (394-399): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (404-409): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (414-419): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (424-429): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (434-439): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (444-449): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (454-459): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (464-469): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (474-479): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (484-489): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (494-499): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (504-509): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (514-519): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (528-533): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (538-543): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (548-553): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (558-563): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (568-573): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (578-583): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (588-593): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (598-603): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (608-613): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (618-623): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (628-633): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (638-643): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (648-653): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (658-663): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (668-673): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (678-683): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (692-697): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (702-707): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (712-717): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (722-727): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (732-737): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (742-747): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (752-757): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (762-767): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (772-777): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (782-787): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (792-797): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (802-807): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (812-817): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (822-827): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (832-837): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (842-847): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (856-861): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (866-871): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (876-881): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (886-891): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (896-901): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (906-911): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (916-921): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (926-931): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (936-941): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (946-951): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (956-961): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (966-971): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (976-981): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (986-991): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (996-1001): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1006-1011): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1020-1025): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1030-1035): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1040-1045): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1050-1055): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1060-1065): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1070-1075): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1080-1085): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1090-1095): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1100-1105): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1110-1115): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1120-1125): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1130-1135): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1140-1145): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1150-1155): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1160-1165): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1170-1175): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1184-1189): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1194-1199): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1204-1209): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1214-1219): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1224-1229): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1234-1239): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1244-1249): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1254-1259): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1264-1269): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1274-1279): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1284-1289): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1294-1299): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1304-1309): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1314-1319): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1324-1329): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1334-1339): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1348-1353): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1358-1363): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1368-1373): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1378-1383): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1388-1393): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1398-1403): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1408-1413): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1418-1423): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1428-1433): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1438-1443): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1448-1453): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1458-1463): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1468-1473): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1478-1483): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1488-1493): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1498-1503): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1512-1517): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1522-1527): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1532-1537): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1542-1547): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1552-1557): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1562-1567): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1572-1577): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1582-1587): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1592-1597): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1602-1607): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1612-1617): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1622-1627): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1632-1637): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1642-1647): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1652-1657): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1662-1667): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1676-1681): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1686-1691): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1696-1701): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1706-1711): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1716-1721): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1726-1731): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1736-1741): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1746-1751): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1756-1761): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1766-1771): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1776-1781): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1786-1791): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1796-1801): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1806-1811): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1816-1821): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1826-1831): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1840-1845): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1850-1855): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1860-1865): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1870-1875): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1880-1885): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1890-1895): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1900-1905): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1910-1915): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1920-1925): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1930-1935): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1940-1945): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1950-1955): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1960-1965): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1970-1975): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1980-1985): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (1990-1995): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2004-2009): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2014-2019): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2024-2029): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2034-2039): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2044-2049): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2054-2059): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2064-2069): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2074-2079): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2084-2089): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2094-2099): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2104-2109): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2114-2119): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2124-2129): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2134-2139): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2144-2149): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2154-2159): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2168-2173): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2178-2183): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2188-2193): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2198-2203): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2208-2213): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2218-2223): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2228-2233): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2238-2243): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2248-2253): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2258-2263): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2268-2273): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2278-2283): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2288-2293): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2298-2303): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2308-2313): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2318-2323): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2332-2337): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2342-2347): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2352-2357): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2362-2367): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2372-2377): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2382-2387): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2392-2397): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2402-2407): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2412-2417): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2422-2427): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2432-2437): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2442-2447): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2452-2457): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2462-2467): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2472-2477): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2482-2487): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2496-2501): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2506-2511): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2516-2521): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2526-2531): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2536-2541): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2546-2551): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2556-2561): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2566-2571): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2576-2581): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2586-2591): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2596-2601): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2606-2611): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2616-2621): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2626-2631): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2636-2641): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2646-2651): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2660-2665): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2670-2675): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2680-2685): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2690-2695): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2700-2705): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2710-2715): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2720-2725): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2730-2735): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2740-2745): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2750-2755): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2760-2765): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2770-2775): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2780-2785): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2790-2795): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2800-2805): "x" is not a valid type (user defined types are not yet supported). +// TypeError 5473: (2810-2815): "x" is not a valid type (user defined types are not yet supported). +// Warning 4013: There are more than 256 errors. Aborting. From 2694190d1dbbc90b001aa76f8d7bd0794923c343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 13 Jun 2024 19:32:29 +0200 Subject: [PATCH 0164/1340] Ignore warnings and infos when checking if FatalError was reported --- libsolidity/analysis/NameAndTypeResolver.cpp | 6 +++--- libsolidity/interface/CompilerStack.cpp | 4 ++-- libsolidity/parsing/Parser.cpp | 2 +- libyul/AsmParser.cpp | 2 +- libyul/ObjectParser.cpp | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 941fbca9b..32ef6d476 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -63,7 +63,7 @@ bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit, ASTNode } catch (langutil::FatalError const& error) { - solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); + solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); return false; } return true; @@ -137,7 +137,7 @@ bool NameAndTypeResolver::resolveNamesAndTypes(SourceUnit& _source) } catch (langutil::FatalError const& error) { - solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); + solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); return false; } return true; @@ -152,7 +152,7 @@ bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) } catch (langutil::FatalError const& error) { - solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); + solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); return false; } return true; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 89a7a441a..229915538 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -491,7 +491,7 @@ bool CompilerStack::analyze() } catch (FatalError const& error) { - solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); + solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); noErrors = false; } @@ -1175,7 +1175,7 @@ StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast) } catch (FatalError const& error) { - solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); + solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); } return newSources; } diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 15a84c3f4..7e2fe030a 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -178,7 +178,7 @@ ASTPointer Parser::parse(CharStream& _charStream) } catch (FatalError const& error) { - solAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); + solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); return nullptr; } } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 7af648a36..a009b005d 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -129,7 +129,7 @@ std::unique_ptr Parser::parseInline(std::shared_ptr const& _scan } catch (FatalError const& error) { - yulAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); + yulAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); } return nullptr; diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index d0519be0e..a02b9660b 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -65,7 +65,7 @@ std::shared_ptr ObjectParser::parse(std::shared_ptr const& _sca } catch (FatalError const& error) { - yulAssert(!m_errorReporter.errors().empty(), "Unreported fatal error: "s + error.what()); + yulAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); } return nullptr; } From 1ca70c8dc089f6a84dea0d13d70934edd7e78789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 6 Jun 2024 15:17:40 +0200 Subject: [PATCH 0165/1340] .gitignore: Mark directories as directories --- .gitignore | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 8ca5f86e7..dc88e1c67 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,7 @@ *.o *.obj *.pyc -__pycache__ +__pycache__/ # Precompiled Headers *.gch @@ -36,12 +36,12 @@ __pycache__ *.app # Build directory -/build* +/build*/ emscripten_build/ -/docs/_build +/docs/_build/ /docs/_static/robots.txt -/deps -/reports +/deps/ +/reports/ # vim stuff [._]*.sw[a-p] From e05c596bd5e931aa4e4c291b76a7765a1437c88f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 5 Jun 2024 14:47:28 +0200 Subject: [PATCH 0166/1340] Setup for benchmarking solc using external projects and foundry --- .gitignore | 3 + test/benchmarks/external-setup.sh | 113 ++++++++++++++++++++++++++++++ test/benchmarks/external.sh | 108 ++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100755 test/benchmarks/external-setup.sh create mode 100755 test/benchmarks/external.sh diff --git a/.gitignore b/.gitignore index dc88e1c67..aafe93f97 100644 --- a/.gitignore +++ b/.gitignore @@ -41,7 +41,10 @@ emscripten_build/ /docs/_build/ /docs/_static/robots.txt /deps/ + +# Reports and benchmarks /reports/ +/benchmarks/ # vim stuff [._]*.sw[a-p] diff --git a/test/benchmarks/external-setup.sh b/test/benchmarks/external-setup.sh new file mode 100755 index 000000000..b995e8e9f --- /dev/null +++ b/test/benchmarks/external-setup.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash + +#------------------------------------------------------------------------------ +# Downloads and configures external projects used for benchmarking by external.sh. +# +# By default the download location is the benchmarks/ dir at the repository root. +# A different directory can be provided via the BENCHMARK_DIR variable. +# +# Dependencies: foundry, git. +# ------------------------------------------------------------------------------ +# 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 +# +# (c) 2024 solidity contributors. +#------------------------------------------------------------------------------ + +set -euo pipefail + +repo_root=$(cd "$(dirname "$0")/../../" && pwd) +BENCHMARK_DIR="${BENCHMARK_DIR:-${repo_root}/benchmarks}" + +function neutralize_version_pragmas { + find . -name '*.sol' -type f -print0 | xargs -0 \ + sed -i -E -e 's/pragma solidity [^;]+;/pragma solidity *;/' +} + +function neutralize_via_ir { + sed -i '/^via_ir\s*=.*$/d' foundry.toml +} + +mkdir -p "$BENCHMARK_DIR" +cd "$BENCHMARK_DIR" + +if [[ ! -e openzeppelin/ ]]; then + git clone --depth=1 https://github.com/OpenZeppelin/openzeppelin-contracts openzeppelin/ --branch v5.0.2 + pushd openzeppelin/ + forge install + neutralize_via_ir + popd +else + echo "Skipped openzeppelin/. Already exists." +fi + +if [[ ! -e uniswap-v4/ ]]; then + git clone --single-branch https://github.com/Uniswap/v4-core uniswap-v4/ + pushd uniswap-v4/ + git checkout d0700ceb251afa48df8cc26d593fe04ee5e6b775 # branch main as of 2024-05-10 + forge install + neutralize_via_ir + popd +else + echo "Skipped uniswap-v4/. Already exists." +fi + +if [[ ! -e seaport/ ]]; then + git clone --single-branch https://github.com/ProjectOpenSea/seaport + pushd seaport/ + # NOTE: Can't select the tag with `git clone` because a branch of the same name exists. + git checkout tags/1.6 + forge install + neutralize_via_ir + neutralize_version_pragmas + popd +else + echo "Skipped seaport/. Already exists." +fi + +if [[ ! -e eigenlayer/ ]]; then + git clone --depth=1 https://github.com/Layr-Labs/eigenlayer-contracts eigenlayer/ --branch v0.3.0-holesky-rewards + pushd eigenlayer/ + neutralize_via_ir + forge install + popd +else + echo "Skipped eigenlayer/. Already exists." +fi + +if [[ ! -e sablier-v2/ ]]; then + git clone --depth=1 https://github.com/sablier-labs/v2-core sablier-v2/ --branch v1.1.2 + pushd sablier-v2/ + # NOTE: To avoid hard-coding dependency versions here we'd have to install them from npm + forge install --no-commit \ + foundry-rs/forge-std@v1.5.6 \ + OpenZeppelin/openzeppelin-contracts@v4.9.2 \ + PaulRBerg/prb-math@v4.0.2 \ + PaulRBerg/prb-test@v0.6.4 \ + evmcheb/solarray@a547630 \ + Vectorized/solady@v0.0.129 + cat < remappings.txt +@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ +forge-std/=lib/forge-std/ +@prb/math/=lib/prb-math/ +@prb/test/=lib/prb-test/ +solarray/=lib/solarray/ +solady/=lib/solady/ +EOF + neutralize_via_ir + popd +else + echo "Skipped sablier-v2/. Already exists." +fi diff --git a/test/benchmarks/external.sh b/test/benchmarks/external.sh new file mode 100755 index 000000000..b37c9105d --- /dev/null +++ b/test/benchmarks/external.sh @@ -0,0 +1,108 @@ +#!/usr/bin/env bash + +#------------------------------------------------------------------------------ +# Benchmarks a solc binary by compiling several external projects, with and without IR. +# +# The script expects each project to be already downloaded and set up by external-setup.sh. +# A different directory can be provided via the BENCHMARK_DIR variable. +# +# The script will by default attempt to use a solc from the default build directory, +# relative to the script directory. To use a different binary you can provide a different +# location of the build directory (via SOLIDITY_BUILD_DIR variable) or simply specify +# the full path to the binary as the script argument. +# +# Dependencies: foundry, time. +# ------------------------------------------------------------------------------ +# 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 +# +# (c) 2024 solidity contributors. +#------------------------------------------------------------------------------ + +set -euo pipefail + +repo_root=$(cd "$(dirname "$0")/../../" && pwd) +SOLIDITY_BUILD_DIR=${SOLIDITY_BUILD_DIR:-${repo_root}/build} +BENCHMARK_DIR="${BENCHMARK_DIR:-${repo_root}/benchmarks}" + +# shellcheck source=scripts/common.sh +source "${repo_root}/scripts/common.sh" +# shellcheck source=scripts/common_cmdline.sh +source "${repo_root}/scripts/common_cmdline.sh" + +(( $# <= 1 )) || fail "Too many arguments. Usage: external.sh []" + +solc="${1:-${SOLIDITY_BUILD_DIR}/solc/solc}" +command_available "$solc" --version + +function benchmark_project { + local pipeline="$1" + local project="$2" + [[ $pipeline == legacy || $pipeline == ir ]] || assertFail + + cd "$project" + local foundry_command=(forge build --use "$solc" --optimize --offline --no-cache) + [[ $pipeline == ir ]] && foundry_command+=(--via-ir) + local time_file="../time-and-status-${project}-${pipeline}.txt" + + # NOTE: The pipeline may fail with "Stack too deep" in some cases. That's fine. + # We note the exit code and will later show full output. + "$time_bin_path" \ + --output "$time_file" \ + --quiet \ + --format '%e s | %x' \ + "${foundry_command[@]}" \ + > /dev/null \ + 2> "../stderr-${project}-${pipeline}.log" || true + + printf '| %-20s | %8s | %21s |\n' \ + "$project" \ + "$pipeline" \ + "$(cat "$time_file")" + cd .. +} + +benchmarks=( + # Fastest ones first so that we get *some* output quickly + openzeppelin + uniswap-v4 + eigenlayer + seaport + sablier-v2 +) +time_bin_path=$(type -P time) + +mkdir -p "$BENCHMARK_DIR" +cd "$BENCHMARK_DIR" + +echo "| Project | Pipeline | Time | Exit code |" +echo "|----------------------|----------|----------:|----------:|" + +for project in "${benchmarks[@]}"; do + benchmark_project legacy "$project" + benchmark_project ir "$project" +done + +for project in "${benchmarks[@]}"; do + for pipeline in legacy ir; do + if [[ -s stderr-${project}-${pipeline}.log ]]; then + echo + echo "==================================" + echo "stderr for ${project} via ${pipeline}" + echo "==================================" + cat "stderr-${project}-${pipeline}.log" + fi + done +done From e1bc6cb95ba8c1786327a7d9e15090378be8160e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 6 Jun 2024 12:42:36 +0200 Subject: [PATCH 0167/1340] benchmarks: Update Uniswap to the latest revision --- test/benchmarks/external-setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/external-setup.sh b/test/benchmarks/external-setup.sh index b995e8e9f..2316d83d5 100755 --- a/test/benchmarks/external-setup.sh +++ b/test/benchmarks/external-setup.sh @@ -56,7 +56,7 @@ fi if [[ ! -e uniswap-v4/ ]]; then git clone --single-branch https://github.com/Uniswap/v4-core uniswap-v4/ pushd uniswap-v4/ - git checkout d0700ceb251afa48df8cc26d593fe04ee5e6b775 # branch main as of 2024-05-10 + git checkout ae86975b058d386c9be24e8994236f662affacdb # branch main as of 2024-06-06 forge install neutralize_via_ir popd From 732658fd59d7263a77b37abb2ba3f60f0ebc8834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 6 Jun 2024 17:51:22 +0200 Subject: [PATCH 0168/1340] Rename benchmarks/run.sh to benchmarks/local.sh --- test/benchmarks/{run.sh => local.sh} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename test/benchmarks/{run.sh => local.sh} (97%) diff --git a/test/benchmarks/run.sh b/test/benchmarks/local.sh similarity index 97% rename from test/benchmarks/run.sh rename to test/benchmarks/local.sh index 1784b3700..9d4f498c1 100755 --- a/test/benchmarks/run.sh +++ b/test/benchmarks/local.sh @@ -31,7 +31,7 @@ source "${REPO_ROOT}/scripts/common.sh" # shellcheck source=scripts/common_cmdline.sh source "${REPO_ROOT}/scripts/common_cmdline.sh" -(( $# <= 1 )) || fail "Too many arguments. Usage: run.sh []" +(( $# <= 1 )) || fail "Too many arguments. Usage: local.sh []" solc="${1:-${SOLIDITY_BUILD_DIR}/solc/solc}" command_available "$solc" --version From 9aceb3a3f716c2eea5bef45724ae5df36d19b2a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 14 Jun 2024 15:25:44 +0200 Subject: [PATCH 0169/1340] Move bytecode_size helper to common.sh --- scripts/common_cmdline.sh | 8 ++++++++ test/benchmarks/local.sh | 6 ------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/common_cmdline.sh b/scripts/common_cmdline.sh index 5e32a76dc..819a4b1c8 100644 --- a/scripts/common_cmdline.sh +++ b/scripts/common_cmdline.sh @@ -169,3 +169,11 @@ function stripEmptyLines { sed -e '/^\s*$/d' } + +# Calculates the total size of bytecode of one or more contracts in bytes. +# Expects the output from `solc --bin` on standard input. +function bytecode_size { + local bytecode_chars + bytecode_chars=$(stripCLIDecorations | stripEmptyLines | wc --chars) + echo $(( bytecode_chars / 2 )) +} diff --git a/test/benchmarks/local.sh b/test/benchmarks/local.sh index 9d4f498c1..16a0c3afe 100755 --- a/test/benchmarks/local.sh +++ b/test/benchmarks/local.sh @@ -45,12 +45,6 @@ function cleanup() { trap cleanup SIGINT SIGTERM -function bytecode_size { - local bytecode_chars - bytecode_chars=$(stripCLIDecorations | stripEmptyLines | wc --chars) - echo $(( bytecode_chars / 2 )) -} - function benchmark_contract { local pipeline="$1" local input_path="$2" From bb168489d270916aeff498963feb407aebeb83d1 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 30 May 2024 23:15:43 -0300 Subject: [PATCH 0170/1340] Catch and report UnimplementedFeatureError --- Changelog.md | 1 + liblangutil/ErrorReporter.cpp | 10 + liblangutil/ErrorReporter.h | 2 + libsolidity/interface/CompilerStack.cpp | 134 ++++++------- libsolidity/interface/CompilerStack.h | 2 + libsolidity/interface/StandardCompiler.cpp | 17 +- libsolutil/Assertions.h | 15 +- libsolutil/CommonData.h | 10 + libsolutil/Exceptions.cpp | 10 + libsolutil/Exceptions.h | 5 + libyul/YulStack.cpp | 189 ++++++++++++------ libyul/YulStack.h | 16 +- scripts/error_codes.py | 2 +- solc/CommandLineInterface.cpp | 6 + solc/main.cpp | 6 - test/libsolidity/SyntaxTest.cpp | 49 ++--- .../operators/shifts/shr_unused.sol | 2 +- .../array/nested_calldata_storage.sol | 2 +- .../array/nested_calldata_storage2.sol | 2 +- .../constants/mod_div_rational.sol | 2 +- .../errors/require_custom_legacy.sol | 2 +- .../builtin/builtin_type_definition.sol | 2 +- .../inline_array_fixed_types.sol | 2 +- .../inline_arrays/inline_array_rationals.sol | 2 +- .../303_fixed_type_int_conversion.sol | 2 +- ...304_fixed_type_rational_int_conversion.sol | 2 +- ...ixed_type_rational_fraction_conversion.sol | 2 +- .../307_rational_unary_minus_operation.sol | 2 +- .../312_leading_zero_rationals_convert.sol | 2 +- .../314_fixed_type_zero_handling.sol | 2 +- ..._fixed_type_valid_explicit_conversions.sol | 2 +- .../323_mapping_with_fixed_literal.sol | 2 +- .../324_fixed_points_inside_structs.sol | 2 +- ...8_rational_to_fixed_literal_expression.sol | 2 +- .../343_integer_and_fixed_interaction.sol | 2 +- .../declaring_fixed_and_ufixed_variables.sol | 2 +- .../lexer_numbers_with_underscores_fixed.sol | 2 +- ...ional_number_literal_to_fixed_implicit.sol | 2 +- 38 files changed, 307 insertions(+), 211 deletions(-) diff --git a/Changelog.md b/Changelog.md index 1c15478d1..29fb86250 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * Error Reporting: Unimplemented features are now properly reported as errors instead of being handled as if they were bugs. * EVM: Support for the EVM version "Prague". * SMTChecker: Add CHC engine check for underflow and overflow in unary minus operation. * SMTChecker: Replace CVC4 as a possible BMC backend with cvc5. diff --git a/liblangutil/ErrorReporter.cpp b/liblangutil/ErrorReporter.cpp index bf10483aa..ddb6b70d1 100644 --- a/liblangutil/ErrorReporter.cpp +++ b/liblangutil/ErrorReporter.cpp @@ -263,6 +263,16 @@ void ErrorReporter::docstringParsingError(ErrorId _error, SourceLocation const& ); } +void ErrorReporter::unimplementedFeatureError(ErrorId _error, SourceLocation const& _location, std::string const& _description) +{ + error( + _error, + Error::Type::UnimplementedFeatureError, + _location, + _description + ); +} + void ErrorReporter::info( ErrorId _error, SourceLocation const& _location, diff --git a/liblangutil/ErrorReporter.h b/liblangutil/ErrorReporter.h index c78b6f498..d7e280ed9 100644 --- a/liblangutil/ErrorReporter.h +++ b/liblangutil/ErrorReporter.h @@ -118,6 +118,8 @@ class ErrorReporter void docstringParsingError(ErrorId _error, SourceLocation const& _location, std::string const& _description); + void unimplementedFeatureError(ErrorId _error, SourceLocation const& _location, std::string const& _description); + ErrorList const& errors() const; void clear(); diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 229915538..0a5fed333 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -346,64 +346,71 @@ bool CompilerStack::parse() if (SemVerVersion{std::string(VersionString)}.isPrerelease()) m_errorReporter.warning(3805_error, "This is a pre-release compiler version, please do not use it in production."); - Parser parser{m_errorReporter, m_evmVersion}; + try + { + Parser parser{m_errorReporter, m_evmVersion}; - std::vector sourcesToParse; - for (auto const& s: m_sources) - sourcesToParse.push_back(s.first); + std::vector sourcesToParse; + for (auto const& s: m_sources) + sourcesToParse.push_back(s.first); - for (size_t i = 0; i < sourcesToParse.size(); ++i) - { - std::string const& path = sourcesToParse[i]; - Source& source = m_sources[path]; - source.ast = parser.parse(*source.charStream); - if (!source.ast) - solAssert(Error::containsErrors(m_errorReporter.errors()), "Parser returned null but did not report error."); - else + for (size_t i = 0; i < sourcesToParse.size(); ++i) { - source.ast->annotation().path = path; - - for (auto const& import: ASTNode::filteredNodes(source.ast->nodes())) + std::string const& path = sourcesToParse[i]; + Source& source = m_sources[path]; + source.ast = parser.parse(*source.charStream); + if (!source.ast) + solAssert(Error::containsErrors(m_errorReporter.errors()), "Parser returned null but did not report error."); + else { - solAssert(!import->path().empty(), "Import path cannot be empty."); - // Check whether the import directive is for the standard library, - // and if yes, add specified file to source units to be parsed. - auto it = stdlib::sources.find(import->path()); - if (it != stdlib::sources.end()) + source.ast->annotation().path = path; + + for (auto const& import: ASTNode::filteredNodes(source.ast->nodes())) { - auto [name, content] = *it; - m_sources[name].charStream = std::make_unique(content, name); - sourcesToParse.push_back(name); + solAssert(!import->path().empty(), "Import path cannot be empty."); + // Check whether the import directive is for the standard library, + // and if yes, add specified file to source units to be parsed. + auto it = stdlib::sources.find(import->path()); + if (it != stdlib::sources.end()) + { + auto [name, content] = *it; + m_sources[name].charStream = std::make_unique(content, name); + sourcesToParse.push_back(name); + } + + // The current value of `path` is the absolute path as seen from this source file. + // We first have to apply remappings before we can store the actual absolute path + // as seen globally. + import->annotation().absolutePath = applyRemapping(util::absolutePath( + import->path(), + path + ), path); } - // The current value of `path` is the absolute path as seen from this source file. - // We first have to apply remappings before we can store the actual absolute path - // as seen globally. - import->annotation().absolutePath = applyRemapping(util::absolutePath( - import->path(), - path - ), path); + if (m_stopAfter >= ParsedAndImported) + for (auto const& newSource: loadMissingSources(*source.ast)) + { + std::string const& newPath = newSource.first; + std::string const& newContents = newSource.second; + m_sources[newPath].charStream = std::make_shared(newContents, newPath); + sourcesToParse.push_back(newPath); + } } - - if (m_stopAfter >= ParsedAndImported) - for (auto const& newSource: loadMissingSources(*source.ast)) - { - std::string const& newPath = newSource.first; - std::string const& newContents = newSource.second; - m_sources[newPath].charStream = std::make_shared(newContents, newPath); - sourcesToParse.push_back(newPath); - } } - } - if (Error::containsErrors(m_errorReporter.errors())) - return false; + if (Error::containsErrors(m_errorReporter.errors())) + return false; - m_stackState = (m_stopAfter <= Parsed ? Parsed : ParsedAndImported); - storeContractDefinitions(); + m_stackState = (m_stopAfter <= Parsed ? Parsed : ParsedAndImported); + storeContractDefinitions(); - solAssert(!m_maxAstId.has_value()); - m_maxAstId = parser.maxID(); + solAssert(!m_maxAstId.has_value()); + m_maxAstId = parser.maxID(); + } + catch (UnimplementedFeatureError const& _error) + { + reportUnimplementedFeatureError(_error); + } return true; } @@ -494,6 +501,11 @@ bool CompilerStack::analyze() solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); noErrors = false; } + catch (UnimplementedFeatureError const& _error) + { + reportUnimplementedFeatureError(_error); + noErrors = false; + } if (!noErrors) return false; @@ -737,28 +749,10 @@ bool CompilerStack::compile(State _stopAfter) m_errorReporter.error(_error.errorId(), _error.type(), SourceLocation(), _error.what()); return false; } - catch (UnimplementedFeatureError const& _unimplementedError) + catch (UnimplementedFeatureError const& _error) { - if ( - SourceLocation const* sourceLocation = - boost::get_error_info(_unimplementedError) - ) - { - std::string const* comment = _unimplementedError.comment(); - m_errorReporter.error( - 1834_error, - Error::Type::CodeGenerationError, - *sourceLocation, - fmt::format( - "Unimplemented feature error {} in {}", - (comment && !comment->empty()) ? ": " + *comment : "", - _unimplementedError.lineInfo() - ) - ); - return false; - } - else - throw; + reportUnimplementedFeatureError(_error); + return false; } } m_stackState = CompilationSuccessful; @@ -1908,3 +1902,9 @@ experimental::Analysis const& CompilerStack::experimentalAnalysis() const solAssert(!!m_experimentalAnalysis); return *m_experimentalAnalysis; } + +void CompilerStack::reportUnimplementedFeatureError(UnimplementedFeatureError const& _error) +{ + solAssert(_error.comment(), "Unimplemented feature errors must include a message for the user"); + m_errorReporter.unimplementedFeatureError(1834_error, _error.sourceLocation(), *_error.comment()); +} diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index ef76764fa..672067d81 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -503,6 +503,8 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac FunctionDefinition const& _function ) const; + void reportUnimplementedFeatureError(langutil::UnimplementedFeatureError const& _error); + ReadCallback::Callback m_readFile; OptimiserSettings m_optimiserSettings; RevertStrings m_revertStrings = RevertStrings::Default; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 2b36f9032..80f788cb6 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -49,6 +49,7 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::frontend; using namespace solidity::langutil; +using namespace solidity::util; using namespace std::string_literals; namespace @@ -1402,13 +1403,8 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu } catch (UnimplementedFeatureError const& _exception) { - errors.emplace_back(formatErrorWithException( - compilerStack, - _exception, - Error::Type::UnimplementedFeatureError, - "general", - "Unimplemented feature (" + _exception.lineInfo() + ")" - )); + // let StandardCompiler::compile handle this + throw _exception; } catch (yul::YulException const& _exception) { @@ -1469,7 +1465,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu Json output; if (errors.size() > 0) - output["errors"] = std::move(errors); + output["errors"] = std::move(errors); if (!compilerStack.unhandledSMTLib2Queries().empty()) for (std::string const& query: compilerStack.unhandledSMTLib2Queries()) @@ -1783,6 +1779,11 @@ Json StandardCompiler::compile(Json const& _input) noexcept { return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON runtime exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); } + catch (UnimplementedFeatureError const& _exception) + { + solAssert(_exception.comment(), "Unimplemented feature errors must include a message for the user"); + return formatFatalError(Error::Type::UnimplementedFeatureError, stringOrDefault(_exception.comment())); + } catch (util::Exception const& _exception) { return formatFatalError(Error::Type::InternalCompilerError, "Internal exception in StandardCompiler::compile: " + boost::diagnostic_information(_exception)); diff --git a/libsolutil/Assertions.h b/libsolutil/Assertions.h index 4879299bf..dcceb1cfc 100644 --- a/libsolutil/Assertions.h +++ b/libsolutil/Assertions.h @@ -26,6 +26,7 @@ #pragma once #include +#include #include #include @@ -63,18 +64,6 @@ namespace solidity::util } #endif -namespace assertions -{ - -inline std::string stringOrDefault(std::string _string, std::string _defaultString) -{ - // NOTE: Putting this in a function rather than directly in a macro prevents the string from - // being evaluated multiple times if it's not just a literal. - return (!_string.empty() ? std::move(_string) : std::move(_defaultString)); -} - -} - /// Base macro that can be used to implement assertion macros. /// Throws an exception containing the given description if the condition is not met. /// Allows you to provide the default description for the case where the user of your macro does @@ -86,7 +75,7 @@ inline std::string stringOrDefault(std::string _string, std::string _defaultStri if (!(_condition)) \ solThrow( \ _exceptionType, \ - ::solidity::util::assertions::stringOrDefault((_description), (_defaultDescription)) \ + ::solidity::util::stringOrDefault((_description), (_defaultDescription)) \ ); \ } \ while (false) diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index c52434451..6e17e674d 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -632,4 +632,14 @@ std::vector make_vector(Args&&... _args) return result; } +inline std::string stringOrDefault(std::string _string, std::string _defaultString = "") +{ + return (!_string.empty() ? std::move(_string) : std::move(_defaultString)); +} + +inline std::string stringOrDefault(std::string const* _string, std::string const& _defaultString = "") +{ + return (_string ? stringOrDefault(*_string, _defaultString) : _defaultString); +} + } diff --git a/libsolutil/Exceptions.cpp b/libsolutil/Exceptions.cpp index 00fe3e26c..ba431a808 100644 --- a/libsolutil/Exceptions.cpp +++ b/libsolutil/Exceptions.cpp @@ -17,8 +17,10 @@ // SPDX-License-Identifier: GPL-3.0 #include +#include using namespace solidity::util; +using namespace solidity::langutil; char const* Exception::what() const noexcept { @@ -49,3 +51,11 @@ std::string const* Exception::comment() const noexcept { return boost::get_error_info(*this); } + +SourceLocation Exception::sourceLocation() const noexcept +{ + if (SourceLocation const* sourceLocation = boost::get_error_info(*this)) + return *sourceLocation; + + return SourceLocation{}; +} diff --git a/libsolutil/Exceptions.h b/libsolutil/Exceptions.h index 7dd9b6769..2ad2713c3 100644 --- a/libsolutil/Exceptions.h +++ b/libsolutil/Exceptions.h @@ -18,6 +18,8 @@ #pragma once +#include + #include #include #include @@ -39,6 +41,9 @@ struct Exception: virtual std::exception, virtual boost::exception /// @returns the errinfo_comment of this exception. std::string const* comment() const noexcept; + + /// @returns the errinfo_sourceLocation of this exception + langutil::SourceLocation sourceLocation() const noexcept; }; /// Throws an exception with a given description and extra information about the location the diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index a4341cba3..94e9ad7a8 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -71,15 +71,35 @@ CharStream const& YulStack::charStream(std::string const& _sourceName) const return *m_charStream; } +bool YulStack::parse(std::string const& _sourceName, std::string const& _source) +{ + yulAssert(m_stackState == Empty); + try + { + m_charStream = std::make_unique(_source, _sourceName); + std::shared_ptr scanner = std::make_shared(*m_charStream); + m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion)).parse(scanner, false); + } + catch (UnimplementedFeatureError const& _error) + { + reportUnimplementedFeatureError(_error); + } + + if (m_errorReporter.errors().empty()) + m_stackState = Parsed; + + return m_stackState == Parsed; +} + bool YulStack::parseAndAnalyze(std::string const& _sourceName, std::string const& _source) { m_errors.clear(); - m_analysisSuccessful = false; - m_charStream = std::make_unique(_source, _sourceName); - std::shared_ptr scanner = std::make_shared(*m_charStream); - m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion)).parse(scanner, false); - if (!m_errorReporter.errors().empty()) + yulAssert(m_stackState == Empty); + + if (!parse(_sourceName, _source)) return false; + + yulAssert(m_stackState == Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); @@ -88,30 +108,37 @@ bool YulStack::parseAndAnalyze(std::string const& _sourceName, std::string const void YulStack::optimize() { - yulAssert(m_analysisSuccessful, "Analysis was not successful."); + yulAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); yulAssert(m_parserResult); - if ( - !m_optimiserSettings.runYulOptimiser && - yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion), *m_parserResult) - ) - return; + try + { + if ( + !m_optimiserSettings.runYulOptimiser && + yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion), *m_parserResult) + ) + return; - m_analysisSuccessful = false; - yulAssert(m_parserResult, ""); - optimize(*m_parserResult, true); - yulAssert(analyzeParsed(), "Invalid source code after optimization."); + m_stackState = Parsed; + optimize(*m_parserResult, true); + yulAssert(analyzeParsed(), "Invalid source code after optimization."); + } + catch (UnimplementedFeatureError const& _error) + { + reportUnimplementedFeatureError(_error); + } } bool YulStack::analyzeParsed() { + yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); - m_analysisSuccessful = analyzeParsed(*m_parserResult); - return m_analysisSuccessful; + return analyzeParsed(*m_parserResult); } bool YulStack::analyzeParsed(Object& _object) { + yulAssert(m_stackState >= Parsed); yulAssert(_object.code, ""); _object.analysisInfo = std::make_shared(); @@ -122,11 +149,25 @@ bool YulStack::analyzeParsed(Object& _object) {}, _object.qualifiedDataNames() ); - bool success = analyzer.analyze(*_object.code); - for (auto& subNode: _object.subObjects) - if (auto subObject = dynamic_cast(subNode.get())) - if (!analyzeParsed(*subObject)) - success = false; + + bool success = false; + try + { + success = analyzer.analyze(*_object.code); + for (auto& subNode: _object.subObjects) + if (auto subObject = dynamic_cast(subNode.get())) + if (!analyzeParsed(*subObject)) + success = false; + } + catch (UnimplementedFeatureError const& _error) + { + reportUnimplementedFeatureError(_error); + success = false; + } + + if (success) + m_stackState = AnalysisSuccessful; + return success; } @@ -204,9 +245,9 @@ void YulStack::optimize(Object& _object, bool _isCreation) ); } -MachineAssemblyObject YulStack::assemble(Machine _machine) const +MachineAssemblyObject YulStack::assemble(Machine _machine) { - yulAssert(m_analysisSuccessful, ""); + yulAssert(m_stackState >= AnalysisSuccessful); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); yulAssert(m_parserResult->analysisInfo, ""); @@ -221,43 +262,50 @@ MachineAssemblyObject YulStack::assemble(Machine _machine) const } std::pair -YulStack::assembleWithDeployed(std::optional _deployName) const +YulStack::assembleWithDeployed(std::optional _deployName) { auto [creationAssembly, deployedAssembly] = assembleEVMWithDeployed(_deployName); yulAssert(creationAssembly, ""); yulAssert(m_charStream, ""); MachineAssemblyObject creationObject; - creationObject.bytecode = std::make_shared(creationAssembly->assemble()); - yulAssert(creationObject.bytecode->immutableReferences.empty(), "Leftover immutables."); - creationObject.assembly = creationAssembly->assemblyString(m_debugInfoSelection); - creationObject.sourceMappings = std::make_unique( - evmasm::AssemblyItem::computeSourceMapping( - creationAssembly->items(), - {{m_charStream->name(), 0}} - ) - ); - MachineAssemblyObject deployedObject; - if (deployedAssembly) + try { - deployedObject.bytecode = std::make_shared(deployedAssembly->assemble()); - deployedObject.assembly = deployedAssembly->assemblyString(m_debugInfoSelection); - deployedObject.sourceMappings = std::make_unique( + creationObject.bytecode = std::make_shared(creationAssembly->assemble()); + yulAssert(creationObject.bytecode->immutableReferences.empty(), "Leftover immutables."); + creationObject.assembly = creationAssembly->assemblyString(m_debugInfoSelection); + creationObject.sourceMappings = std::make_unique( evmasm::AssemblyItem::computeSourceMapping( - deployedAssembly->items(), + creationAssembly->items(), {{m_charStream->name(), 0}} ) ); + + if (deployedAssembly) + { + deployedObject.bytecode = std::make_shared(deployedAssembly->assemble()); + deployedObject.assembly = deployedAssembly->assemblyString(m_debugInfoSelection); + deployedObject.sourceMappings = std::make_unique( + evmasm::AssemblyItem::computeSourceMapping( + deployedAssembly->items(), + {{m_charStream->name(), 0}} + ) + ); + } + } + catch (UnimplementedFeatureError const& _error) + { + reportUnimplementedFeatureError(_error); } return {std::move(creationObject), std::move(deployedObject)}; } std::pair, std::shared_ptr> -YulStack::assembleEVMWithDeployed(std::optional _deployName) const +YulStack::assembleEVMWithDeployed(std::optional _deployName) { - yulAssert(m_analysisSuccessful, ""); + yulAssert(m_stackState >= AnalysisSuccessful); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); yulAssert(m_parserResult->analysisInfo, ""); @@ -272,32 +320,39 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) c !m_optimiserSettings.runYulOptimiser && !yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion), *m_parserResult) ); - compileEVM(adapter, optimize); + try + { + compileEVM(adapter, optimize); - assembly.optimise(evmasm::Assembly::OptimiserSettings::translateSettings(m_optimiserSettings, m_evmVersion)); + assembly.optimise(evmasm::Assembly::OptimiserSettings::translateSettings(m_optimiserSettings, m_evmVersion)); - std::optional subIndex; + std::optional subIndex; - // Pick matching assembly if name was given - if (_deployName.has_value()) - { - for (size_t i = 0; i < assembly.numSubs(); i++) - if (assembly.sub(i).name() == _deployName) - { - subIndex = i; - break; - } + // Pick matching assembly if name was given + if (_deployName.has_value()) + { + for (size_t i = 0; i < assembly.numSubs(); i++) + if (assembly.sub(i).name() == _deployName) + { + subIndex = i; + break; + } + + solAssert(subIndex.has_value(), "Failed to find object to be deployed."); + } + // Otherwise use heuristic: If there is a single sub-assembly, this is likely the object to be deployed. + else if (assembly.numSubs() == 1) + subIndex = 0; - solAssert(subIndex.has_value(), "Failed to find object to be deployed."); + if (subIndex.has_value()) + { + evmasm::Assembly& runtimeAssembly = assembly.sub(*subIndex); + return {std::make_shared(assembly), std::make_shared(runtimeAssembly)}; + } } - // Otherwise use heuristic: If there is a single sub-assembly, this is likely the object to be deployed. - else if (assembly.numSubs() == 1) - subIndex = 0; - - if (subIndex.has_value()) + catch (UnimplementedFeatureError const& _error) { - evmasm::Assembly& runtimeAssembly = assembly.sub(*subIndex); - return {std::make_shared(assembly), std::make_shared(runtimeAssembly)}; + reportUnimplementedFeatureError(_error); } return {std::make_shared(assembly), {}}; @@ -307,6 +362,7 @@ std::string YulStack::print( CharStreamProvider const* _soliditySourceProvider ) const { + yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); return m_parserResult->toString(&languageToDialect(m_language, m_evmVersion), m_debugInfoSelection, _soliditySourceProvider) + "\n"; @@ -314,6 +370,7 @@ std::string YulStack::print( Json YulStack::astJson() const { + yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); return m_parserResult->toJson(); @@ -321,8 +378,14 @@ Json YulStack::astJson() const std::shared_ptr YulStack::parserResult() const { - yulAssert(m_analysisSuccessful, "Analysis was not successful."); + yulAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); return m_parserResult; } + +void YulStack::reportUnimplementedFeatureError(UnimplementedFeatureError const& _error) +{ + solAssert(_error.comment(), "Unimplemented feature errors must include a message for the user"); + m_errorReporter.unimplementedFeatureError(1920_error, _error.sourceLocation(), *_error.comment()); +} diff --git a/libyul/YulStack.h b/libyul/YulStack.h index 27f530b44..d75ff200f 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -67,6 +67,11 @@ class YulStack: public langutil::CharStreamProvider public: enum class Language { Yul, Assembly, StrictAssembly }; enum class Machine { EVM }; + enum State { + Empty, + Parsed, + AnalysisSuccessful + }; YulStack(): YulStack( @@ -105,7 +110,7 @@ class YulStack: public langutil::CharStreamProvider void optimize(); /// Run the assembly step (should only be called after parseAndAnalyze). - MachineAssemblyObject assemble(Machine _machine) const; + MachineAssemblyObject assemble(Machine _machine); /// Run the assembly step (should only be called after parseAndAnalyze). /// In addition to the value returned by @a assemble, returns @@ -114,7 +119,7 @@ class YulStack: public langutil::CharStreamProvider std::pair assembleWithDeployed( std::optional _deployName = {} - ) const; + ); /// Run the assembly step (should only be called after parseAndAnalyze). /// Similar to @a assemblyWithDeployed, but returns EVM assembly objects. @@ -122,7 +127,7 @@ class YulStack: public langutil::CharStreamProvider std::pair, std::shared_ptr> assembleEVMWithDeployed( std::optional _deployName = {} - ) const; + ); /// @returns the errors generated during parsing, analysis (and potentially assembly). langutil::ErrorList const& errors() const { return m_errors; } @@ -136,6 +141,7 @@ class YulStack: public langutil::CharStreamProvider std::shared_ptr parserResult() const; private: + bool parse(std::string const& _sourceName, std::string const& _source); bool analyzeParsed(); bool analyzeParsed(yul::Object& _object); @@ -143,6 +149,8 @@ class YulStack: public langutil::CharStreamProvider void optimize(yul::Object& _object, bool _isCreation); + void reportUnimplementedFeatureError(langutil::UnimplementedFeatureError const& _error); + Language m_language = Language::Assembly; langutil::EVMVersion m_evmVersion; std::optional m_eofVersion; @@ -151,7 +159,7 @@ class YulStack: public langutil::CharStreamProvider std::unique_ptr m_charStream; - bool m_analysisSuccessful = false; + State m_stackState = Empty; std::shared_ptr m_parserResult; langutil::ErrorList m_errors; langutil::ErrorReporter m_errorReporter; diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 8ee5cbbde..24ec2b06d 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -201,7 +201,7 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): # The warning may or may not exist in a compiler build. "4591", # "There are more than 256 warnings. Ignoring the rest." # Due to 3805, the warning lists look different for different compiler builds. - "1834", # Unimplemented feature error, as we do not test it anymore via cmdLineTests + "1920", # Unimplemented feature error from YulStack (currently there are no UnimplementedFeatureErrors thrown by libyul) "1180", # SMTChecker, covered by CL tests "2339", # SMTChecker, covered by CL tests "2961", # SMTChecker, covered by CL tests diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 514f84c20..edfd4d52c 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -691,6 +691,12 @@ bool CommandLineInterface::run(int _argc, char const* const* _argv) return false; } + catch (UnimplementedFeatureError const& _error) + { + solAssert(_error.comment(), "Unimplemented feature errors must include a message for the user"); + report(Error::Severity::Error, stringOrDefault(_error.comment(), "Unimplemented feature")); + return false; + } } bool CommandLineInterface::parseArguments(int _argc, char const* const* _argv) diff --git a/solc/main.cpp b/solc/main.cpp index 4237f9ac6..c6c3df7a2 100644 --- a/solc/main.cpp +++ b/solc/main.cpp @@ -45,12 +45,6 @@ int main(int argc, char** argv) std::cerr << boost::diagnostic_information(_exception); return 2; } - catch (langutil::UnimplementedFeatureError const& _exception) - { - std::cerr << "Unimplemented feature:" << std::endl; - std::cerr << boost::diagnostic_information(_exception); - return 2; - } catch (langutil::InternalCompilerError const& _exception) { std::cerr << "Internal compiler error:" << std::endl; diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index f350ea462..41c1d0568 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -80,34 +81,28 @@ void SyntaxTest::setupCompiler(CompilerStack& _compiler) void SyntaxTest::parseAndAnalyze() { - try + runFramework(withPreamble(m_sources.sources), m_stopAfter); + if (!pipelineSuccessful() && stageSuccessful(PipelineStage::Analysis) && !compiler().isExperimentalAnalysis()) { - runFramework(withPreamble(m_sources.sources), m_stopAfter); - if (!pipelineSuccessful() && stageSuccessful(PipelineStage::Analysis) && !compiler().isExperimentalAnalysis()) - { - ErrorList const& errors = compiler().errors(); - auto codeGeneretionErrorCount = count_if(errors.cbegin(), errors.cend(), [](auto const& error) { - return error->type() == Error::Type::CodeGenerationError; - }); - auto errorCount = count_if(errors.cbegin(), errors.cend(), [](auto const& error) { - return Error::isError(error->type()); - }); - // failing compilation after successful analysis is a rare case, - // it assumes that errors contain exactly one error, and the error is of type Error::Type::CodeGenerationError - if (codeGeneretionErrorCount != 1 || errorCount != 1) - BOOST_THROW_EXCEPTION(std::runtime_error("Compilation failed even though analysis was successful.")); - } - } - catch (UnimplementedFeatureError const& _e) - { - m_errorList.emplace_back(SyntaxTestError{ - Error::Type::UnimplementedFeatureError, - std::nullopt, - errorMessage(_e), - "", - -1, - -1 - }); + ErrorList const& errors = compiler().errors(); + static auto isInternalError = [](std::shared_ptr const& _error) { + return + Error::isError(_error->type()) && + _error->type() != Error::Type::CodeGenerationError && + _error->type() != Error::Type::UnimplementedFeatureError + ; + }; + // Most errors are detected during analysis, and should not happen during code generation. + // There are some exceptions, e.g. unimplemented features or stack too deep, but anything else at this stage + // is an internal error that signals a bug in the compiler (rather than in user's code). + if ( + auto error = ranges::find_if(errors, isInternalError); + error != ranges::end(errors) + ) + BOOST_THROW_EXCEPTION(std::runtime_error( + "Unexpected " + Error::formatErrorType((*error)->type()) + " at compilation stage." + " This error should NOT be encoded as expectation and should be fixed instead." + )); } filterObtainedErrors(); diff --git a/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol b/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol index 8f34b530b..504381758 100644 --- a/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol +++ b/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol @@ -7,5 +7,5 @@ contract C { // ==== // SMTEngine: all // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol b/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol index e9878fc22..18bf550c0 100644 --- a/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol +++ b/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol @@ -6,4 +6,4 @@ contract C { } // ---- -// UnimplementedFeatureError: Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. +// UnimplementedFeatureError 1834: Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. diff --git a/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol b/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol index 2d1c1f586..9f5bb8eab 100644 --- a/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol +++ b/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol @@ -6,4 +6,4 @@ contract C { } // ---- -// UnimplementedFeatureError: Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. +// UnimplementedFeatureError 1834: Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. diff --git a/test/libsolidity/syntaxTests/constants/mod_div_rational.sol b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol index d983fa1ee..5c127eb4a 100644 --- a/test/libsolidity/syntaxTests/constants/mod_div_rational.sol +++ b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol @@ -5,4 +5,4 @@ contract C { fixed a4 = 0 / -0.123; } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/errors/require_custom_legacy.sol b/test/libsolidity/syntaxTests/errors/require_custom_legacy.sol index 334b84739..c1eae591f 100644 --- a/test/libsolidity/syntaxTests/errors/require_custom_legacy.sol +++ b/test/libsolidity/syntaxTests/errors/require_custom_legacy.sol @@ -5,4 +5,4 @@ contract C { } } // ---- -// UnimplementedFeatureError: Require with a custom error is only available using the via-ir pipeline. +// UnimplementedFeatureError 1834: Require with a custom error is only available using the via-ir pipeline. diff --git a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol index 373d76c33..ed7db1ec6 100644 --- a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol +++ b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol @@ -33,7 +33,6 @@ contract C { // EVMVersion: >=constantinople // compileViaYul: true // ---- -// UnimplementedFeatureError: No support for calling functions pointers yet. // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. // Info 4164: (31-61): Inferred type: void // Info 4164: (63-93): Inferred type: bool @@ -90,3 +89,4 @@ contract C { // Info 4164: (563-574): Inferred type: (bool, word) -> word // Info 4164: (563-567): Inferred type: (?bm:type, ?bn:type) // Info 4164: (575-576): Inferred type: (bool, word) +// UnimplementedFeatureError 1834: No support for calling functions pointers yet. diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol index 56a4d0e20..604f9b029 100644 --- a/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol @@ -4,6 +4,6 @@ contract test { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. // Warning 2072: (50-67): Unused local variable. // Warning 2018: (20-119): Function state mutability can be restricted to pure +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol index 78aa35de7..63df5c044 100644 --- a/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol @@ -4,6 +4,6 @@ contract test { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. // Warning 2072: (50-73): Unused local variable. // Warning 2018: (20-118): Function state mutability can be restricted to pure +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol index ba1eb8069..58c74b9ad 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol @@ -8,5 +8,5 @@ contract test { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. // Warning 2018: (20-147): Function state mutability can be restricted to pure +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol index 81ad7dbe8..404cbc4bc 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol @@ -6,5 +6,5 @@ contract test { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. // Warning 2018: (20-104): Function state mutability can be restricted to pure +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol index b7642e16a..b113c6bcc 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol @@ -6,5 +6,5 @@ contract test { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. // Warning 2018: (20-108): Function state mutability can be restricted to pure +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol index b8b2f12b5..e80024a98 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol @@ -6,4 +6,4 @@ contract test { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol index 082514ebc..20be0208c 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol @@ -8,4 +8,4 @@ contract A { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol index 1d1e62cf3..7415ed6e8 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol @@ -5,5 +5,5 @@ contract test { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. // Warning 2018: (20-104): Function state mutability can be restricted to pure +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol index 4899b3d78..fa32ec7dd 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol @@ -6,5 +6,5 @@ contract test { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. // Warning 2018: (20-182): Function state mutability can be restricted to pure +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol index 20ebcb1fe..cb730221d 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol @@ -5,4 +5,4 @@ contract test { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol index 24a090127..9bc624302 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol @@ -6,4 +6,4 @@ contract test { myStruct a = myStruct(3.125, 3); } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol index 4dbcb3f20..8391734ae 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol @@ -11,6 +11,6 @@ contract test { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. // Warning 2519: (238-252): This declaration shadows an existing declaration. // Warning 2018: (20-339): Function state mutability can be restricted to pure +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol index ad7b34fd7..15ca25931 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol @@ -4,6 +4,6 @@ contract test { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. // Warning 2072: (50-58): Unused local variable. // Warning 2018: (20-89): Function state mutability can be restricted to pure +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol b/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol index e34522540..ea41bbf3e 100644 --- a/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol +++ b/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol @@ -6,9 +6,9 @@ contract A { } } // ---- -// UnimplementedFeatureError: Fixed point types not implemented. // Warning 5667: (52-60): Unused function parameter. Remove or comment out the variable name to silence this warning. // Warning 5667: (62-74): Unused function parameter. Remove or comment out the variable name to silence this warning. // Warning 2072: (93-104): Unused local variable. // Warning 2072: (114-121): Unused local variable. // Warning 2018: (41-128): Function state mutability can be restricted to pure +// UnimplementedFeatureError 1834: Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol index 00ed4f654..9932c4c3d 100644 --- a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol index 5bceec609..a93555fd7 100644 --- a/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol +++ b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol @@ -13,4 +13,4 @@ contract C { } } // ---- -// UnimplementedFeatureError: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. From 48f97a377aa92b7a466df826a5a57d6de92accc0 Mon Sep 17 00:00:00 2001 From: Pawel Gebal Date: Mon, 10 Jun 2024 17:33:11 +0200 Subject: [PATCH 0171/1340] SMTChecker: Fix error that reported invalid number of verified checks for BMC and CHC engines --- Changelog.md | 1 + libsolidity/formal/BMC.cpp | 7 ++++++- libsolidity/formal/BMC.h | 5 ++++- .../constructor_state_variable_init.sol | 2 +- .../smtCheckerTests/operators/unary_minus_bmc.sol | 2 +- ...ined_operator_matches_equivalent_function_call.sol | 2 +- .../overflow/overflow_and_underflow_bmc.sol | 11 +++++++++++ 7 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_bmc.sol diff --git a/Changelog.md b/Changelog.md index 29fb86250..de3fc3d6c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,7 @@ Compiler Features: Bugfixes: + * SMTChecker: Fix error that reports invalid number of verified checks for BMC engine. * TypeChecker: Fix segfault when assigning nested tuple to tuple. * Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 916bf5a31..b1a326fc7 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -118,13 +118,18 @@ void BMC::analyze(SourceUnit const& _source, std::mapid() < _b.expression->id(); + if (_a.expression->id() == _b.expression->id()) + return _a.type < _b.type; + else + return _a.expression->id() < _b.expression->id(); } }; diff --git a/test/libsolidity/smtCheckerTests/bmc_coverage/branches_with_return/constructor_state_variable_init.sol b/test/libsolidity/smtCheckerTests/bmc_coverage/branches_with_return/constructor_state_variable_init.sol index 4728a1cb0..a5ec4d87f 100644 --- a/test/libsolidity/smtCheckerTests/bmc_coverage/branches_with_return/constructor_state_variable_init.sol +++ b/test/libsolidity/smtCheckerTests/bmc_coverage/branches_with_return/constructor_state_variable_init.sol @@ -39,4 +39,4 @@ contract C is B { // Warning 4661: (389-412): BMC: Assertion violation happens here. // Warning 4661: (489-513): BMC: Assertion violation happens here. // Warning 4661: (533-546): BMC: Assertion violation happens here. -// Info 6002: BMC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/unary_minus_bmc.sol b/test/libsolidity/smtCheckerTests/operators/unary_minus_bmc.sol index 052554d21..66e80539d 100644 --- a/test/libsolidity/smtCheckerTests/operators/unary_minus_bmc.sol +++ b/test/libsolidity/smtCheckerTests/operators/unary_minus_bmc.sol @@ -8,4 +8,4 @@ contract C // SMTEngine: bmc // ---- // Warning 4661: (48-63): BMC: Assertion violation happens here. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol index 33665ee26..9872a6a92 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol @@ -77,4 +77,4 @@ contract C { // Warning 4144: (953-982): BMC: Underflow (resulting value less than -32768) happens here. // Warning 3046: (1149-1178): BMC: Division by zero happens here. // Warning 7812: (2245-2271): BMC: Assertion violation might happen here. -// Info 6002: BMC: 8 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 10 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_bmc.sol b/test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_bmc.sol new file mode 100644 index 000000000..b788acebf --- /dev/null +++ b/test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_bmc.sol @@ -0,0 +1,11 @@ +contract C { + function f(int x, int y) public pure returns (int) { + require(x == 0); + require(y == 0); + return x + y; + } +} +// ==== +// SMTEngine: bmc +// ---- +// Info 6002: BMC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 6ccb3a340c363558900f59c3773cce11ed4957df Mon Sep 17 00:00:00 2001 From: Pawel Gebal Date: Mon, 10 Jun 2024 17:33:11 +0200 Subject: [PATCH 0172/1340] SMTChecker: Fix internal compiler error on reporting proved targets --- Changelog.md | 3 ++- libsolidity/formal/BMC.cpp | 6 +++--- libsolidity/formal/BMC.h | 1 + libsolidity/formal/CHC.cpp | 12 +++++++++--- libsolidity/formal/CHC.h | 16 ++++++++++++++-- libsolidity/formal/ModelChecker.cpp | 11 +++++++++-- libsolidity/formal/ModelChecker.h | 6 ++++++ libsolidity/formal/SMTEncoder.cpp | 2 ++ libsolidity/formal/SMTEncoder.h | 2 ++ scripts/error_codes.py | 1 - .../push_as_lhs_compound_assignment.sol | 2 +- .../constructor_state_variable_init.sol | 2 +- .../constructor_state_variable_init_asserts.sol | 2 +- ...onstructor_state_variable_init_chain_tree.sol | 2 +- .../inheritance/diamond_super_3.sol | 2 +- .../assignment_contract_member_variable.sol | 2 +- ...ssignment_module_contract_member_variable.sol | 2 +- .../smtCheckerTests/operators/division_4.sol | 2 +- .../operators/division_truncates_correctly_2.sol | 2 +- .../operators/division_truncates_correctly_3.sol | 2 +- .../operators/division_truncates_correctly_4.sol | 2 +- .../operators/division_truncates_correctly_5.sol | 2 +- .../smtCheckerTests/operators/mod.sol | 2 +- .../smtCheckerTests/operators/mod_signed.sol | 2 +- .../operators/unary_add_array_push_2.sol | 2 +- .../operators/unary_minus_chc.sol | 2 +- .../user_defined_operations_on_constants.sol | 2 +- ...user_defined_operations_on_constants_fail.sol | 2 +- .../overflow_and_underflow_bmc_show_proved.sol | 13 +++++++++++++ .../overflow/overflow_and_underflow_chc.sol | 11 +++++++++++ .../overflow/signed_guard_sum_overflow.sol | 2 +- .../smtCheckerTests/try_catch/try_3.sol | 2 +- .../smtCheckerTests/typecast/downcast.sol | 2 +- .../unchecked/flipping_sign_tests.sol | 2 +- 34 files changed, 94 insertions(+), 34 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_bmc_show_proved.sol create mode 100644 test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_chc.sol diff --git a/Changelog.md b/Changelog.md index de3fc3d6c..8343d2f72 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,7 +11,8 @@ Compiler Features: Bugfixes: - * SMTChecker: Fix error that reports invalid number of verified checks for BMC engine. + * SMTChecker: Fix error that reports invalid number of verified checks for BMC and CHC engines. + * SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine. * TypeChecker: Fix segfault when assigning nested tuple to tuple. * Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index b1a326fc7..46812c409 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -47,12 +47,13 @@ BMC::BMC( smt::EncodingContext& _context, UniqueErrorReporter& _errorReporter, UniqueErrorReporter& _unsupportedErrorReporter, + ErrorReporter& _provedSafeReporter, std::map const& _smtlib2Responses, ReadCallback::Callback const& _smtCallback, ModelCheckerSettings _settings, CharStreamProvider const& _charStreamProvider ): - SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _charStreamProvider) + SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _provedSafeReporter, _charStreamProvider) { solAssert(!_settings.printQuery || _settings.solvers == SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); std::vector> solvers; @@ -133,7 +134,7 @@ void BMC::analyze(SourceUnit const& _source, std::maplocation(), "BMC: " + @@ -141,7 +142,6 @@ void BMC::analyze(SourceUnit const& _source, std::map const& _smtlib2Responses, ReadCallback::Callback const& _smtCallback, ModelCheckerSettings _settings, diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 66ebd47ed..357291f27 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -63,12 +63,13 @@ CHC::CHC( EncodingContext& _context, UniqueErrorReporter& _errorReporter, UniqueErrorReporter& _unsupportedErrorReporter, + ErrorReporter& _provedSafeReporter, std::map const& _smtlib2Responses, ReadCallback::Callback const& _smtCallback, ModelCheckerSettings _settings, CharStreamProvider const& _charStreamProvider ): - SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _charStreamProvider), + SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _provedSafeReporter, _charStreamProvider), m_smtlib2Responses(_smtlib2Responses), m_smtCallback(_smtCallback) { @@ -2113,17 +2114,22 @@ void CHC::checkVerificationTargets() ); if (!m_settings.showProvedSafe && !m_safeTargets.empty()) + { + std::size_t provedSafeNum = 0; + for (auto&& [_, targets]: m_safeTargets) + provedSafeNum += targets.size(); m_errorReporter.info( 1391_error, "CHC: " + - std::to_string(m_safeTargets.size()) + + std::to_string(provedSafeNum) + " verification condition(s) proved safe!" + " Enable the model checker option \"show proved safe\" to see all of them." ); + } else if (m_settings.showProvedSafe) for (auto const& [node, targets]: m_safeTargets) for (auto const& target: targets) - m_errorReporter.info( + m_provedSafeReporter.info( 9576_error, node->location(), "CHC: " + diff --git a/libsolidity/formal/CHC.h b/libsolidity/formal/CHC.h index be150baf1..b60e5c3f7 100644 --- a/libsolidity/formal/CHC.h +++ b/libsolidity/formal/CHC.h @@ -58,6 +58,7 @@ class CHC: public SMTEncoder smt::EncodingContext& _context, langutil::UniqueErrorReporter& _errorReporter, langutil::UniqueErrorReporter& _unsupportedErrorReporter, + langutil::ErrorReporter& _provedSafeReporter, std::map const& _smtlib2Responses, ReadCallback::Callback const& _smtCallback, ModelCheckerSettings _settings, @@ -77,6 +78,17 @@ class CHC: public SMTEncoder } }; + struct SafeTargetsCompare + { + bool operator()(CHCVerificationTarget const & _lhs, CHCVerificationTarget const & _rhs) const + { + if (_lhs.errorNode->id() == _rhs.errorNode->id()) + return _lhs.type < _rhs.type; + else + return _lhs.errorNode->id() == _rhs.errorNode->id(); + } + }; + struct ReportTargetInfo { langutil::ErrorId error; @@ -84,7 +96,7 @@ class CHC: public SMTEncoder std::string message; }; - std::map, smt::EncodingContext::IdCompare> const& safeTargets() const { return m_safeTargets; } + std::map, smt::EncodingContext::IdCompare> const& safeTargets() const { return m_safeTargets; } std::map, smt::EncodingContext::IdCompare> const& unsafeTargets() const { return m_unsafeTargets; } /// This is used if the Horn solver is not directly linked into this binary. @@ -423,7 +435,7 @@ class CHC: public SMTEncoder std::map m_verificationTargets; /// Targets proved safe. - std::map, smt::EncodingContext::IdCompare> m_safeTargets; + std::map, smt::EncodingContext::IdCompare> m_safeTargets; /// Targets proved unsafe. std::map, smt::EncodingContext::IdCompare> m_unsafeTargets; /// Targets not proved. diff --git a/libsolidity/formal/ModelChecker.cpp b/libsolidity/formal/ModelChecker.cpp index 94a927d3b..91b88cb9c 100644 --- a/libsolidity/formal/ModelChecker.cpp +++ b/libsolidity/formal/ModelChecker.cpp @@ -43,10 +43,11 @@ ModelChecker::ModelChecker( ReadCallback::Callback const& _smtCallback ): m_errorReporter(_errorReporter), + m_provedSafeReporter(m_provedSafeLogs), m_settings(std::move(_settings)), m_context(), - m_bmc(m_context, m_uniqueErrorReporter, m_unsupportedErrorReporter, _smtlib2Responses, _smtCallback, m_settings, _charStreamProvider), - m_chc(m_context, m_uniqueErrorReporter, m_unsupportedErrorReporter, _smtlib2Responses, _smtCallback, m_settings, _charStreamProvider) + m_bmc(m_context, m_uniqueErrorReporter, m_unsupportedErrorReporter, m_provedSafeReporter, _smtlib2Responses, _smtCallback, m_settings, _charStreamProvider), + m_chc(m_context, m_uniqueErrorReporter, m_unsupportedErrorReporter, m_provedSafeReporter, _smtlib2Responses, _smtCallback, m_settings, _charStreamProvider) { } @@ -151,6 +152,12 @@ void ModelChecker::analyze(SourceUnit const& _source) m_errorReporter.append(m_uniqueErrorReporter.errors()); m_uniqueErrorReporter.clear(); + + if (m_settings.showProvedSafe) + { + m_errorReporter.append(m_provedSafeReporter.errors()); + m_provedSafeReporter.clear(); + } } std::vector ModelChecker::unhandledQueries() diff --git a/libsolidity/formal/ModelChecker.h b/libsolidity/formal/ModelChecker.h index 4c795fa70..2fd4885d5 100644 --- a/libsolidity/formal/ModelChecker.h +++ b/libsolidity/formal/ModelChecker.h @@ -95,6 +95,12 @@ class ModelChecker /// to m_errorReporter at the end of the analysis. langutil::UniqueErrorReporter m_unsupportedErrorReporter; + langutil::ErrorList m_provedSafeLogs; + /// Used by SMTEncoder, BMC and CHC to accumulate info about proved targets. + /// This is local to ModelChecker, so needs to be appended + /// to m_errorReporter at the end of the analysis. + langutil::ErrorReporter m_provedSafeReporter; + ModelCheckerSettings m_settings; /// Stores the context of the encoding. diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index c92c5399a..44282289d 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -51,10 +51,12 @@ SMTEncoder::SMTEncoder( ModelCheckerSettings _settings, UniqueErrorReporter& _errorReporter, UniqueErrorReporter& _unsupportedErrorReporter, + ErrorReporter& _provedSafeReporter, langutil::CharStreamProvider const& _charStreamProvider ): m_errorReporter(_errorReporter), m_unsupportedErrors(_unsupportedErrorReporter), + m_provedSafeReporter(_provedSafeReporter), m_context(_context), m_settings(std::move(_settings)), m_charStreamProvider(_charStreamProvider) diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index bea3a85ef..c017d5c12 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -57,6 +57,7 @@ class SMTEncoder: public ASTConstVisitor ModelCheckerSettings _settings, langutil::UniqueErrorReporter& _errorReporter, langutil::UniqueErrorReporter& _unsupportedErrorReporter, + langutil::ErrorReporter& _provedSafeReporter, langutil::CharStreamProvider const& _charStreamProvider ); @@ -450,6 +451,7 @@ class SMTEncoder: public ASTConstVisitor langutil::UniqueErrorReporter& m_errorReporter; langutil::UniqueErrorReporter& m_unsupportedErrors; + langutil::ErrorReporter& m_provedSafeReporter; /// Stores the current function/modifier call/invocation path. std::vector m_callStack; diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 24ec2b06d..6ca9dd085 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -204,7 +204,6 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "1920", # Unimplemented feature error from YulStack (currently there are no UnimplementedFeatureErrors thrown by libyul) "1180", # SMTChecker, covered by CL tests "2339", # SMTChecker, covered by CL tests - "2961", # SMTChecker, covered by CL tests "6240", # SMTChecker, covered by CL tests } assert len(test_ids & white_ids) == 0, "The sets are not supposed to intersect" diff --git a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_compound_assignment.sol b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_compound_assignment.sol index 4d20c8ae9..b059482ac 100644 --- a/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_compound_assignment.sol +++ b/test/libsolidity/smtCheckerTests/array_members/push_as_lhs_compound_assignment.sol @@ -13,4 +13,4 @@ contract C { // SMTEngine: all // ---- // Warning 6328: (128-145): CHC: Assertion violation happens here. -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol index 88036eb55..69be20b53 100644 --- a/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_with_return/constructor_state_variable_init.sol @@ -39,4 +39,4 @@ contract C is B { // Warning 6328: (389-412): CHC: Assertion violation happens here. // Warning 6328: (489-513): CHC: Assertion violation happens here. // Warning 6328: (533-546): CHC: Assertion violation happens here. -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol index db81b1d0f..23f831d71 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_asserts.sol @@ -37,4 +37,4 @@ contract C is B { // Warning 6328: (339-362): CHC: Assertion violation happens here. // Warning 6328: (439-463): CHC: Assertion violation happens here. // Warning 6328: (483-496): CHC: Assertion violation happens here. -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol index 8fe0cb28e..767d28d52 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_chain_tree.sol @@ -41,4 +41,4 @@ contract C is B { // ---- // Warning 6328: (403-417): CHC: Assertion violation happens here. // Warning 6328: (450-463): CHC: Assertion violation happens here. -// Info 1391: CHC: 7 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 8 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/diamond_super_3.sol b/test/libsolidity/smtCheckerTests/inheritance/diamond_super_3.sol index f6674021e..68bfb883a 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/diamond_super_3.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/diamond_super_3.sol @@ -34,4 +34,4 @@ contract E is C,D { // SMTIgnoreCex: no // ---- // Warning 6328: (379-394): CHC: Assertion violation happens here.\nCounterexample:\nx = 111\n\nTransaction trace:\nE.constructor()\nState: x = 0\nE.f()\n C.f() -- internal call\n B.f() -- internal call\n A.f() -- internal call -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/assignment_contract_member_variable.sol b/test/libsolidity/smtCheckerTests/operators/assignment_contract_member_variable.sol index 40eb48672..2c5fdbf00 100644 --- a/test/libsolidity/smtCheckerTests/operators/assignment_contract_member_variable.sol +++ b/test/libsolidity/smtCheckerTests/operators/assignment_contract_member_variable.sol @@ -30,4 +30,4 @@ contract A { // SMTIgnoreInv: yes // ---- // Warning 6328: (392-408): CHC: Assertion violation happens here. -// Info 1391: CHC: 17 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 26 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol b/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol index baa1c75a4..c943dc800 100644 --- a/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol +++ b/test/libsolidity/smtCheckerTests/operators/assignment_module_contract_member_variable.sol @@ -31,4 +31,4 @@ contract A { // ---- // Warning 6328: (AASource:159-178): CHC: Assertion violation happens here. // Warning 6328: (AASource:370-386): CHC: Assertion violation happens here. -// Info 1391: CHC: 16 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 25 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/division_4.sol b/test/libsolidity/smtCheckerTests/operators/division_4.sol index 54403b1ec..134ddfc52 100644 --- a/test/libsolidity/smtCheckerTests/operators/division_4.sol +++ b/test/libsolidity/smtCheckerTests/operators/division_4.sol @@ -8,4 +8,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_2.sol b/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_2.sol index 29af565a2..a0ce8024c 100644 --- a/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_2.sol +++ b/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_2.sol @@ -8,4 +8,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_3.sol b/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_3.sol index 573f6d246..82aac9d4f 100644 --- a/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_3.sol +++ b/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_3.sol @@ -8,4 +8,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_4.sol b/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_4.sol index 6610bc524..a56594554 100644 --- a/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_4.sol +++ b/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_4.sol @@ -8,4 +8,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_5.sol b/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_5.sol index 97faba60f..2b93bbae1 100644 --- a/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_5.sol +++ b/test/libsolidity/smtCheckerTests/operators/division_truncates_correctly_5.sol @@ -8,4 +8,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/mod.sol b/test/libsolidity/smtCheckerTests/operators/mod.sol index d12e5c49d..b5aae4d40 100644 --- a/test/libsolidity/smtCheckerTests/operators/mod.sol +++ b/test/libsolidity/smtCheckerTests/operators/mod.sol @@ -10,4 +10,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/mod_signed.sol b/test/libsolidity/smtCheckerTests/operators/mod_signed.sol index c34bd08e3..3741b5347 100644 --- a/test/libsolidity/smtCheckerTests/operators/mod_signed.sol +++ b/test/libsolidity/smtCheckerTests/operators/mod_signed.sol @@ -12,5 +12,5 @@ contract C { // SMTEngine: all // ---- // Warning 6328: (131-148): CHC: Assertion violation might happen here. -// Info 1391: CHC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 7 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. // Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/unary_add_array_push_2.sol b/test/libsolidity/smtCheckerTests/operators/unary_add_array_push_2.sol index a6cacac08..a6e078091 100644 --- a/test/libsolidity/smtCheckerTests/operators/unary_add_array_push_2.sol +++ b/test/libsolidity/smtCheckerTests/operators/unary_add_array_push_2.sol @@ -18,4 +18,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 7 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 8 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/unary_minus_chc.sol b/test/libsolidity/smtCheckerTests/operators/unary_minus_chc.sol index 0d1bf972b..d36978c68 100644 --- a/test/libsolidity/smtCheckerTests/operators/unary_minus_chc.sol +++ b/test/libsolidity/smtCheckerTests/operators/unary_minus_chc.sol @@ -8,4 +8,4 @@ contract C // SMTEngine: chc // ---- // Warning 6328: (48-63): CHC: Assertion violation happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol index 49420440f..7f3f9702c 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants.sol @@ -60,4 +60,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 22 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 27 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol index 106a7c5f0..dc624393b 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operations_on_constants_fail.sol @@ -76,4 +76,4 @@ contract C { // Warning 6328: (2741-2758): CHC: Assertion violation happens here. // Warning 6328: (2783-2804): CHC: Assertion violation happens here. // Warning 6328: (2829-2850): CHC: Assertion violation happens here. -// Info 1391: CHC: 6 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 11 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_bmc_show_proved.sol b/test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_bmc_show_proved.sol new file mode 100644 index 000000000..2674890f6 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_bmc_show_proved.sol @@ -0,0 +1,13 @@ +contract C { + function f(int x, int y) public pure returns (int) { + require(x == 0); + require(y == 0); + return x + y; + } +} +// ==== +// SMTEngine: bmc +// SMTShowProvedSafe: yes +// ---- +// Info 2961: (114-119): BMC: Underflow (resulting value less than -2**255) check is safe! +// Info 2961: (114-119): BMC: Overflow (resulting value larger than 2**255 - 1) check is safe! diff --git a/test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_chc.sol b/test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_chc.sol new file mode 100644 index 000000000..783d12b51 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/overflow/overflow_and_underflow_chc.sol @@ -0,0 +1,11 @@ +contract C { + function f(int x, int y) public pure returns (int) { + require(x == 0); + require(y == 0); + return x + y; + } +} +// ==== +// SMTEngine: chc +// ---- +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/overflow/signed_guard_sum_overflow.sol b/test/libsolidity/smtCheckerTests/overflow/signed_guard_sum_overflow.sol index 7704e2d7e..58b582b4b 100644 --- a/test/libsolidity/smtCheckerTests/overflow/signed_guard_sum_overflow.sol +++ b/test/libsolidity/smtCheckerTests/overflow/signed_guard_sum_overflow.sol @@ -10,4 +10,4 @@ contract C { // ---- // Warning 3944: (78-83): CHC: Underflow (resulting value less than -2**255) happens here. // Warning 4984: (78-83): CHC: Overflow (resulting value larger than 2**255 - 1) happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/try_catch/try_3.sol b/test/libsolidity/smtCheckerTests/try_catch/try_3.sol index 7698eed0f..aa4b1eed1 100644 --- a/test/libsolidity/smtCheckerTests/try_catch/try_3.sol +++ b/test/libsolidity/smtCheckerTests/try_catch/try_3.sol @@ -25,4 +25,4 @@ contract C { // ---- // Warning 5667: (259-273): Unused try/catch parameter. Remove or comment out the variable name to silence this warning. // Warning 6328: (280-294): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\ns = []\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.f()\n C.postinc() -- internal call -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/typecast/downcast.sol b/test/libsolidity/smtCheckerTests/typecast/downcast.sol index bba3585f2..d2bb89bae 100644 --- a/test/libsolidity/smtCheckerTests/typecast/downcast.sol +++ b/test/libsolidity/smtCheckerTests/typecast/downcast.sol @@ -46,4 +46,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Info 1391: CHC: 20 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 24 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol b/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol index 536d2a2b4..71cc3754d 100644 --- a/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol +++ b/test/libsolidity/smtCheckerTests/unchecked/flipping_sign_tests.sol @@ -11,4 +11,4 @@ contract test { // ---- // Warning 4984: (117-119): CHC: Overflow (resulting value larger than 2**255 - 1) happens here. // Warning 6328: (110-125): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 050a3a109cc78654bb9c3bbf63101dfc2771b1fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 5 Jun 2024 21:38:49 +0200 Subject: [PATCH 0173/1340] Remove overly specific handlers for internal errors and unexpected exceptions --- libsolidity/interface/FileReader.cpp | 10 +--- libsolidity/interface/SMTSolverCommand.cpp | 2 +- libsolidity/interface/StandardCompiler.cpp | 53 ------------------- libsolidity/lsp/FileRepository.cpp | 6 +-- test/libsolidity/InlineAssembly.cpp | 15 ++---- .../SolidityExpressionCompiler.cpp | 5 -- test/libyul/ObjectParser.cpp | 26 ++++----- test/libyul/Parser.cpp | 41 ++++++-------- test/soltest.cpp | 10 +--- test/tools/fuzzer_common.cpp | 3 -- test/tools/isoltest.cpp | 14 +---- 11 files changed, 34 insertions(+), 151 deletions(-) diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index 15181acf6..913051293 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -164,17 +164,9 @@ ReadCallback::Result FileReader::readFile(std::string const& _kind, std::string m_sourceCodes[_sourceUnitName] = contents; return ReadCallback::Result{true, contents}; } - catch (util::Exception const& _exception) - { - return ReadCallback::Result{false, "Exception in read callback: " + boost::diagnostic_information(_exception)}; - } - catch (std::exception const& _exception) - { - return ReadCallback::Result{false, "Exception in read callback: " + boost::diagnostic_information(_exception)}; - } catch (...) { - return ReadCallback::Result{false, "Unknown exception in read callback: " + boost::current_exception_diagnostic_information()}; + return ReadCallback::Result{false, "Exception in read callback: " + boost::current_exception_diagnostic_information()}; } } diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index 75f541692..7dfb448f8 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -108,7 +108,7 @@ ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::stri } catch (...) { - return ReadCallback::Result{false, "Unknown exception in SMTQuery callback: " + boost::current_exception_diagnostic_information()}; + return ReadCallback::Result{false, "Exception in SMTQuery callback: " + boost::current_exception_diagnostic_information()}; } } diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 80f788cb6..e95dd53bd 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1372,15 +1372,6 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu "Uncaught error: " )); } - /// This should not be leaked from compile(). - catch (FatalError const& _exception) - { - errors.emplace_back(formatError( - Error::Type::FatalError, - "general", - "Uncaught fatal error: " + boost::diagnostic_information(_exception) - )); - } catch (CompilerError const& _exception) { errors.emplace_back(formatErrorWithException( @@ -1426,22 +1417,6 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu "SMT logic exception" )); } - catch (util::Exception const& _exception) - { - errors.emplace_back(formatError( - Error::Type::Exception, - "general", - "Exception during compilation: " + boost::diagnostic_information(_exception) - )); - } - catch (std::exception const& _exception) - { - errors.emplace_back(formatError( - Error::Type::Exception, - "general", - "Unknown exception during compilation: " + boost::diagnostic_information(_exception) - )); - } catch (...) { errors.emplace_back(formatError( @@ -1755,39 +1730,11 @@ Json StandardCompiler::compile(Json const& _input) noexcept else return formatFatalError(Error::Type::JSONError, "Only \"Solidity\", \"Yul\", \"SolidityAST\" or \"EVMAssembly\" is supported as a language."); } - catch (Json::parse_error const& _exception) - { - return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON parse_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); - } - catch (Json::invalid_iterator const& _exception) - { - return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON invalid_iterator exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); - } - catch (Json::type_error const& _exception) - { - return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON type_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); - } - catch (Json::out_of_range const& _exception) - { - return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON out_of_range exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); - } - catch (Json::other_error const& _exception) - { - return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON other_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); - } - catch (Json::exception const& _exception) - { - return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON runtime exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what())); - } catch (UnimplementedFeatureError const& _exception) { solAssert(_exception.comment(), "Unimplemented feature errors must include a message for the user"); return formatFatalError(Error::Type::UnimplementedFeatureError, stringOrDefault(_exception.comment())); } - catch (util::Exception const& _exception) - { - return formatFatalError(Error::Type::InternalCompilerError, "Internal exception in StandardCompiler::compile: " + boost::diagnostic_information(_exception)); - } catch (...) { return formatFatalError(Error::Type::InternalCompilerError, "Internal exception in StandardCompiler::compile: " + boost::current_exception_diagnostic_information()); diff --git a/libsolidity/lsp/FileRepository.cpp b/libsolidity/lsp/FileRepository.cpp index 7138cbd86..7ba37a731 100644 --- a/libsolidity/lsp/FileRepository.cpp +++ b/libsolidity/lsp/FileRepository.cpp @@ -170,13 +170,9 @@ frontend::ReadCallback::Result FileRepository::readFile(std::string const& _kind m_sourceCodes[_sourceUnitName] = contents; return ReadCallback::Result{true, std::move(contents)}; } - catch (std::exception const& _exception) - { - return ReadCallback::Result{false, "Exception in read callback: " + boost::diagnostic_information(_exception)}; - } catch (...) { - return ReadCallback::Result{false, "Unknown exception in read callback: " + boost::current_exception_diagnostic_information()}; + return ReadCallback::Result{false, "Exception in read callback: " + boost::current_exception_diagnostic_information()}; } } diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 1c848d600..a0aa39be4 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -66,18 +66,9 @@ std::optional parseAndReturnFirstError( solidity::frontend::OptimiserSettings::none(), DebugInfoSelection::None() ); - bool success = false; - try - { - success = stack.parseAndAnalyze("", _source); - if (success && _assemble) - stack.assemble(_machine); - } - catch (FatalError const&) - { - BOOST_FAIL("Fatal error leaked."); - success = false; - } + bool success = stack.parseAndAnalyze("", _source); + if (success && _assemble) + stack.assemble(_machine); std::shared_ptr error; for (auto const& e: stack.errors()) { diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 1df1d9430..4810b0143 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -112,11 +112,6 @@ bytes compileFirstExpression( if (!sourceUnit) return bytes(); } - catch (boost::exception const& _e) - { - std::string msg = "Parsing source code failed with:\n" + boost::diagnostic_information(_e); - BOOST_FAIL(msg); - } catch (...) { std::string msg = "Parsing source code failed with:\n" + boost::current_exception_diagnostic_information(); diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index d9623384a..b23e53060 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -55,23 +55,15 @@ namespace std::pair parse(std::string const& _source) { - try - { - YulStack asmStack( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::none(), - DebugInfoSelection::All() - ); - bool success = asmStack.parseAndAnalyze("source", _source); - return {success, asmStack.errors()}; - } - catch (FatalError const&) - { - BOOST_FAIL("Fatal error leaked."); - } - return {false, {}}; + YulStack asmStack( + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion(), + YulStack::Language::StrictAssembly, + solidity::frontend::OptimiserSettings::none(), + DebugInfoSelection::All() + ); + bool success = asmStack.parseAndAnalyze("source", _source); + return {success, asmStack.errors()}; } std::optional parseAndReturnFirstError(std::string const& _source, bool _allowWarningsAndInfos = true) diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 69314abee..46c4f11a8 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -54,32 +54,25 @@ namespace std::shared_ptr parse(std::string const& _source, Dialect const& _dialect, ErrorReporter& errorReporter) { - try + auto stream = CharStream(_source, ""); + std::map> indicesToSourceNames; + indicesToSourceNames[0] = std::make_shared("source0"); + indicesToSourceNames[1] = std::make_shared("source1"); + + auto parserResult = yul::Parser( + errorReporter, + _dialect, + std::move(indicesToSourceNames) + ).parse(stream); + if (parserResult) { - auto stream = CharStream(_source, ""); - std::map> indicesToSourceNames; - indicesToSourceNames[0] = std::make_shared("source0"); - indicesToSourceNames[1] = std::make_shared("source1"); - - auto parserResult = yul::Parser( + yul::AsmAnalysisInfo analysisInfo; + if (yul::AsmAnalyzer( + analysisInfo, errorReporter, - _dialect, - std::move(indicesToSourceNames) - ).parse(stream); - if (parserResult) - { - yul::AsmAnalysisInfo analysisInfo; - if (yul::AsmAnalyzer( - analysisInfo, - errorReporter, - _dialect - ).analyze(*parserResult)) - return parserResult; - } - } - catch (FatalError const&) - { - BOOST_FAIL("Fatal error leaked."); + _dialect + ).analyze(*parserResult)) + return parserResult; } return {}; } diff --git a/test/soltest.cpp b/test/soltest.cpp index 5fde4bda5..8e7a3ddcd 100644 --- a/test/soltest.cpp +++ b/test/soltest.cpp @@ -115,17 +115,9 @@ void runTestCase(TestCase::Config const& _config, TestCase::TestCaseCreator cons break; } } - catch (boost::exception const& _e) - { - BOOST_ERROR("Exception during extracted test: " << boost::diagnostic_information(_e)); - } - catch (std::exception const& _e) - { - BOOST_ERROR("Exception during extracted test: " << boost::diagnostic_information(_e)); - } catch (...) { - BOOST_ERROR("Unknown exception during extracted test: " << boost::current_exception_diagnostic_information()); + BOOST_ERROR("Exception during extracted test: " << boost::current_exception_diagnostic_information()); } } diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index 8b7dbffa8..a469cbeba 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -131,9 +131,6 @@ void FuzzerUtil::testCompiler( catch (Error const&) { } - catch (FatalError const&) - { - } catch (UnimplementedFeatureError const&) { } diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index fa56b35d7..57ab4af16 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -191,22 +191,10 @@ TestTool::Result TestTool::process() else return Result::Skipped; } - catch (boost::exception const& _e) - { - AnsiColorized(std::cout, formatted, {BOLD, RED}) << - "Exception during test: " << boost::diagnostic_information(_e) << std::endl; - return Result::Exception; - } - catch (std::exception const& _e) - { - AnsiColorized(std::cout, formatted, {BOLD, RED}) << - "Exception during test: " << boost::diagnostic_information(_e) << std::endl; - return Result::Exception; - } catch (...) { AnsiColorized(std::cout, formatted, {BOLD, RED}) << - "Unknown exception during test: " << boost::current_exception_diagnostic_information() << std::endl; + "Unhandled exception during test: " << boost::current_exception_diagnostic_information() << std::endl; return Result::Exception; } } From 9b67a390df98195cab0e77dc5723c83431b6a8f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 5 Jun 2024 21:02:26 +0200 Subject: [PATCH 0174/1340] DocumentationParsingError is never thrown and does not need to be caught --- solc/CommandLineInterface.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index edfd4d52c..a51b77e8e 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -923,17 +923,9 @@ void CommandLineInterface::compile() } catch (Error const& _error) { - if (_error.type() == Error::Type::DocstringParsingError) - { - report(Error::Severity::Error, *boost::get_error_info(_error)); - solThrow(CommandLineExecutionError, "Documentation parsing failed."); - } - else - { - m_hasOutput = true; - formatter.printErrorInformation(_error); - solThrow(CommandLineExecutionError, ""); - } + m_hasOutput = true; + formatter.printErrorInformation(_error); + solThrow(CommandLineExecutionError, ""); } } From c2c8c2876822792ba4e1f6d779a13d0359fd3fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 6 Jun 2024 20:19:54 +0200 Subject: [PATCH 0175/1340] Treat util::Error as unexpected outside of codegen - In analysis we use an error reporter and never just throw util::Error. We do it in one case in the codegen (CodeGenerationError) but outside of that case this should not be treated as a proper way to report an error. - Now such errors will be treated as unexpected. They're bugs that should be fixed. --- libsolidity/interface/CompilerStack.cpp | 6 ++++-- libsolidity/interface/StandardCompiler.cpp | 11 ----------- solc/CommandLineInterface.cpp | 6 ------ test/tools/fuzzer_common.cpp | 3 --- 4 files changed, 4 insertions(+), 22 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 0a5fed333..8ee55d87f 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -744,8 +744,10 @@ bool CompilerStack::compile(State _stopAfter) } catch (Error const& _error) { - if (_error.type() != Error::Type::CodeGenerationError) - throw; + // Since codegen has no access to the error reporter, the only way for it to + // report an error is to throw. In most cases it uses dedicated exceptions, + // but CodeGenerationError is one case where someone decided to just throw Error. + solAssert(_error.type() == Error::Type::CodeGenerationError); m_errorReporter.error(_error.errorId(), _error.type(), SourceLocation(), _error.what()); return false; } diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index e95dd53bd..5510b5430 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1361,17 +1361,6 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu )); } } - /// This is only thrown in a very few locations. - catch (Error const& _error) - { - errors.emplace_back(formatErrorWithException( - compilerStack, - _error, - _error.type(), - "general", - "Uncaught error: " - )); - } catch (CompilerError const& _exception) { errors.emplace_back(formatErrorWithException( diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index a51b77e8e..367434c93 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -921,12 +921,6 @@ void CommandLineInterface::compile() ); solThrow(CommandLineExecutionError, ""); } - catch (Error const& _error) - { - m_hasOutput = true; - formatter.printErrorInformation(_error); - solThrow(CommandLineExecutionError, ""); - } } void CommandLineInterface::handleCombinedJSON() diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index a469cbeba..adf5a064b 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -128,9 +128,6 @@ void FuzzerUtil::testCompiler( { compiler.compile(); } - catch (Error const&) - { - } catch (UnimplementedFeatureError const&) { } From ad2644c52b3afbe80801322c5fe44edb59383500 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Sat, 6 Apr 2024 17:17:51 -0300 Subject: [PATCH 0176/1340] Make parser accept transient as location (but not a keyword) --- Changelog.md | 1 + docs/grammar/SolidityLexer.g4 | 1 + docs/grammar/SolidityParser.g4 | 5 ++-- .../analysis/DeclarationTypeChecker.cpp | 27 +++++++++++++++++-- libsolidity/ast/AST.cpp | 4 ++- libsolidity/ast/AST.h | 2 +- libsolidity/ast/ASTJsonExporter.cpp | 2 ++ libsolidity/ast/ASTJsonImporter.cpp | 2 ++ libsolidity/ast/Types.cpp | 17 ++++++++++++ libsolidity/ast/Types.h | 2 +- libsolidity/codegen/ArrayUtils.cpp | 6 +++++ libsolidity/codegen/CompilerUtils.cpp | 9 +++++++ libsolidity/codegen/ContractCompiler.cpp | 1 + libsolidity/codegen/ExpressionCompiler.cpp | 6 +++++ libsolidity/codegen/YulUtilFunctions.cpp | 3 +++ .../codegen/ir/IRGeneratorForStatements.cpp | 13 +++++++++ libsolidity/formal/BMC.cpp | 3 +++ libsolidity/formal/CHC.cpp | 3 +++ libsolidity/formal/SMTEncoder.h | 13 +++++++++ libsolidity/interface/StorageLayout.cpp | 1 + libsolidity/parsing/Parser.cpp | 13 +++++++++ scripts/error_codes.py | 1 + .../in.sol | 10 +++++++ .../input.json | 13 +++++++++ .../output.json | 11 ++++++++ .../transient_data_location.sol | 8 ++++++ .../transient_storage_state_variable.sol | 8 ++++++ ...onstant_state_variable_named_transient.sol | 4 +++ .../constant_transient_state_variable.sol | 5 ++++ .../data_location_in_function_type_fail.sol | 3 +++ ...tion_specifier_test_external_transient.sol | 5 ++++ ...tion_specifier_test_internal_transient.sol | 5 ++++ ..._function_with_data_location_transient.sol | 19 +++++++++++++ ...tion_specifier_test_external_transient.sol | 5 ++++ ...tion_specifier_test_internal_transient.sol | 5 ++++ ...sient_data_location_function_parameter.sol | 6 +++++ ...function_parameters_location_transient.sol | 5 ++++ ...n_return_parameters_location_transient.sol | 5 ++++ ...cation_specifier_test_public_transient.sol | 5 ++++ ...n_return_parameters_location_transient.sol | 5 ++++ ...state_variable_storage_named_transient.sol | 5 ++++ .../state_variable_storage_transient.sol | 5 ++++ .../state_variable_transient_storage.sol | 5 ++++ ...transient_dynamic_array_state_variable.sol | 7 +++++ .../transient_fixed_array_state_variable.sol | 7 +++++ .../dataLocations/transient_function_type.sol | 11 ++++++++ .../transient_function_type_parameter.sol | 5 ++++ .../transient_local_variable.sol | 7 +++++ .../transient_mapping_state_variable.sol | 7 +++++ .../transient_state_variable_visibility.sol | 12 +++++++++ .../transient_struct_state_variable.sol | 12 +++++++++ .../transient_value_type_state_variables.sol | 12 +++++++++ ..._value_type_state_variables_assignment.sol | 10 +++++++ .../errors/invalid_parameter_location.sol | 5 ++++ .../events/invalid_parameter_location.sol | 5 ++++ .../events/transient_indexed_parameter.sol | 5 ++++ .../function_type_with_transient_param.sol | 8 ++++++ ...nction_type_with_param_named_transient.sol | 6 +++++ ...ent_function_type_with_transient_param.sol | 5 ++++ .../immutable_state_var_named_transient.sol | 4 +++ .../state_var_transient_data_location.sol | 5 ++++ .../modifiers/multiple_parameter_location.sol | 7 +++++ .../modifiers/transient_parameter.sol | 5 ++++ .../operators/transient_value_type.sol | 11 ++++++++ .../parsing/contract_named_transient.sol | 1 + .../transient_data_location_member.sol | 5 ++++ ...ate_variable_address_payable_transient.sol | 6 +++++ ...ate_variable_address_transient_payable.sol | 5 ++++ .../transient_as_identifier.sol | 25 +++++++++++++++++ ...nsient_as_identifier_and_data_location.sol | 6 +++++ 70 files changed, 474 insertions(+), 7 deletions(-) create mode 100644 test/cmdlineTests/storage_layout_transient_value_types/in.sol create mode 100644 test/cmdlineTests/storage_layout_transient_value_types/input.json create mode 100644 test/cmdlineTests/storage_layout_transient_value_types/output.json create mode 100644 test/libsolidity/astPropertyTests/transient_data_location.sol create mode 100644 test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol create mode 100644 test/libsolidity/syntaxTests/constants/constant_state_variable_named_transient.sol create mode 100644 test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_transient.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_transient.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_transient.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_transient.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_transient.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/multiple_transient_data_location_function_parameter.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_parameters_location_transient.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_return_parameters_location_transient.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_transient.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_return_parameters_location_transient.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/state_variable_storage_named_transient.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/state_variable_storage_transient.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/state_variable_transient_storage.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_function_type_parameter.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_local_variable.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_struct_state_variable.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol create mode 100644 test/libsolidity/syntaxTests/events/transient_indexed_parameter.sol create mode 100644 test/libsolidity/syntaxTests/functionTypes/function_type_with_transient_param.sol create mode 100644 test/libsolidity/syntaxTests/functionTypes/transient_function_type_with_param_named_transient.sol create mode 100644 test/libsolidity/syntaxTests/functionTypes/transient_function_type_with_transient_param.sol create mode 100644 test/libsolidity/syntaxTests/immutable/immutable_state_var_named_transient.sol create mode 100644 test/libsolidity/syntaxTests/immutable/state_var_transient_data_location.sol create mode 100644 test/libsolidity/syntaxTests/modifiers/transient_parameter.sol create mode 100644 test/libsolidity/syntaxTests/operators/transient_value_type.sol create mode 100644 test/libsolidity/syntaxTests/parsing/contract_named_transient.sol create mode 100644 test/libsolidity/syntaxTests/structs/transient_data_location_member.sol create mode 100644 test/libsolidity/syntaxTests/types/address/state_variable_address_payable_transient.sol create mode 100644 test/libsolidity/syntaxTests/types/address/state_variable_address_transient_payable.sol create mode 100644 test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier.sol create mode 100644 test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier_and_data_location.sol diff --git a/Changelog.md b/Changelog.md index de3fc3d6c..8ac9a7895 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.8.27 (unreleased) Language Features: + * Accept declarations of state variables with ``transient`` data location (parser support only, no code generation yet). Compiler Features: diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index 43648ceb5..f994c331d 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -85,6 +85,7 @@ SignedIntegerType: Storage: 'storage'; String: 'string'; Struct: 'struct'; +Transient: 'transient'; // not a real keyword True: 'true'; Try: 'try'; Type: 'type'; diff --git a/docs/grammar/SolidityParser.g4 b/docs/grammar/SolidityParser.g4 index e6d3ed7cc..a344fad54 100644 --- a/docs/grammar/SolidityParser.g4 +++ b/docs/grammar/SolidityParser.g4 @@ -262,7 +262,7 @@ userDefinedValueTypeDefinition: * The declaration of a state variable. */ stateVariableDeclaration -locals [boolean constantnessSet = false, boolean visibilitySet = false, boolean overrideSpecifierSet = false] +locals [boolean constantnessSet = false, boolean visibilitySet = false, boolean overrideSpecifierSet = false, boolean locationSet = false] : type=typeName ( @@ -272,6 +272,7 @@ locals [boolean constantnessSet = false, boolean visibilitySet = false, boolean | {!$constantnessSet}? Constant {$constantnessSet = true;} | {!$overrideSpecifierSet}? overrideSpecifier {$overrideSpecifierSet = true;} | {!$constantnessSet}? Immutable {$constantnessSet = true;} + | {!$locationSet}? Transient {$locationSet = true;} )* name=identifier (Assign initialValue=expression)? @@ -419,7 +420,7 @@ inlineArrayExpression: LBrack (expression ( Comma expression)* ) RBrack; /** * Besides regular non-keyword Identifiers, some keywords like 'from' and 'error' can also be used as identifiers. */ -identifier: Identifier | From | Error | Revert | Global; +identifier: Identifier | From | Error | Revert | Global | Transient; literal: stringLiteral | numberLiteral | booleanLiteral | hexStringLiteral | unicodeStringLiteral; diff --git a/libsolidity/analysis/DeclarationTypeChecker.cpp b/libsolidity/analysis/DeclarationTypeChecker.cpp index 28c051c0a..7e6ab98e1 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.cpp +++ b/libsolidity/analysis/DeclarationTypeChecker.cpp @@ -407,6 +407,7 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable) { case Location::Memory: return "\"memory\""; case Location::Storage: return "\"storage\""; + case Location::Transient: return "\"transient\""; case Location::CallData: return "\"calldata\""; case Location::Unspecified: return "none"; } @@ -456,8 +457,24 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable) } else if (_variable.isStateVariable()) { - solAssert(varLoc == Location::Unspecified, ""); - typeLoc = (_variable.isConstant() || _variable.immutable()) ? DataLocation::Memory : DataLocation::Storage; + switch (varLoc) + { + case Location::Unspecified: + typeLoc = (_variable.isConstant() || _variable.immutable()) ? DataLocation::Memory : DataLocation::Storage; + break; + case Location::Transient: + if (_variable.isConstant() || _variable.immutable()) + m_errorReporter.declarationError( + 2197_error, + _variable.location(), + "Transient cannot be used as data location for constant or immutable variables." + ); + typeLoc = DataLocation::Transient; + break; + default: + solAssert(false); + break; + } } else if ( dynamic_cast(_variable.scope()) || @@ -477,6 +494,9 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable) case Location::CallData: typeLoc = DataLocation::CallData; break; + case Location::Transient: + solUnimplemented("Transient data location cannot be used in this kind of variable or parameter declaration."); + break; case Location::Unspecified: solAssert(!_variable.hasReferenceOrMappingType(), "Data location not properly set."); } @@ -497,6 +517,9 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable) m_errorReporter.fatalTypeError(9259_error, _variable.location(), "Only constants of value type and byte array type are implemented."); } + if (!type->isValueType()) + solUnimplementedAssert(typeLoc != DataLocation::Transient, "Transient data location is only supported for value types."); + _variable.annotation().type = type; } diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index bae169675..a3aab07fb 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -816,7 +816,9 @@ std::set VariableDeclaration::allowedDataLocation { using Location = VariableDeclaration::Location; - if (!hasReferenceOrMappingType() || isStateVariable() || isEventOrErrorParameter()) + if (isStateVariable()) + return std::set{Location::Unspecified, Location::Transient}; + else if (!hasReferenceOrMappingType() || isEventOrErrorParameter()) return std::set{ Location::Unspecified }; else if (isCallableOrCatchParameter()) { diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index d8b178377..3494ab94b 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1052,7 +1052,7 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen class VariableDeclaration: public Declaration, public StructurallyDocumented { public: - enum Location { Unspecified, Storage, Memory, CallData }; + enum Location { Unspecified, Storage, Transient, Memory, CallData }; enum class Mutability { Mutable, Immutable, Constant }; static std::string mutabilityToString(Mutability _mutability) { diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index f94b91674..69f51618e 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -1058,6 +1058,8 @@ std::string ASTJsonExporter::location(VariableDeclaration::Location _location) return "memory"; case VariableDeclaration::Location::CallData: return "calldata"; + case VariableDeclaration::Location::Transient: + return "transient"; } // To make the compiler happy return {}; diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 5c1d4bdc0..728d77c0d 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -1190,6 +1190,8 @@ VariableDeclaration::Location ASTJsonImporter::location(Json const& _node) return VariableDeclaration::Location::Memory; else if (storageLocStr == "calldata") return VariableDeclaration::Location::CallData; + else if (storageLocStr == "transient") + return VariableDeclaration::Location::Transient; else astAssert(false, "Unknown location declaration"); diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 028b76673..a37cc78a4 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1544,6 +1544,8 @@ TypeResult ReferenceType::unaryOperatorResult(Token _operator) const return TypeProvider::emptyTuple(); case DataLocation::Storage: return isPointer() ? nullptr : TypeProvider::emptyTuple(); + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); } return nullptr; } @@ -1571,6 +1573,9 @@ std::string ReferenceType::stringForReferencePart() const return "calldata"; case DataLocation::Memory: return "memory"; + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; } solAssert(false, ""); return ""; @@ -1584,6 +1589,9 @@ std::string ReferenceType::identifierLocationSuffix() const case DataLocation::Storage: id += "_storage"; break; + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; case DataLocation::Memory: id += "_memory"; break; @@ -1748,6 +1756,9 @@ BoolResult ArrayType::validForLocation(DataLocation _loc) const if (storageSizeUpperBound() >= bigint(1) << 256) return BoolResult::err("Type too large for storage."); break; + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; } return true; } @@ -1828,6 +1839,9 @@ std::vector> ArrayType::makeStackItems() co case DataLocation::Storage: // byte offset inside storage value is omitted return {std::make_tuple("slot", TypeProvider::uint256())}; + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; } solAssert(false, ""); } @@ -2568,6 +2582,9 @@ std::vector> StructType::makeStackItems() c return {std::make_tuple("mpos", TypeProvider::uint256())}; case DataLocation::Storage: return {std::make_tuple("slot", TypeProvider::uint256())}; + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; } solAssert(false, ""); } diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 3ab4a1d97..1817c97af 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -70,7 +70,7 @@ inline rational makeRational(bigint const& _numerator, bigint const& _denominato return rational(_numerator, _denominator); } -enum class DataLocation { Storage, CallData, Memory }; +enum class DataLocation { Storage, Transient, CallData, Memory }; /** diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index e73ddfbae..e653239cf 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -1021,6 +1021,9 @@ void ArrayUtils::retrieveLength(ArrayType const& _arrayType, unsigned _stackDept if (_arrayType.isByteArrayOrString()) m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1); break; + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; } } } @@ -1118,6 +1121,9 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b m_context << endTag; break; } + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; } } diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index bf4f25bf2..822d9d3da 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -1024,6 +1024,9 @@ void CompilerUtils::convertType( "Invalid conversion to storage type." ); break; + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; case DataLocation::Memory: { // Copy the array to a free position in memory, unless it is already in memory. @@ -1168,6 +1171,9 @@ void CompilerUtils::convertType( "Invalid conversion to storage type." ); break; + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; case DataLocation::Memory: // Copy the array to a free position in memory, unless it is already in memory. switch (typeOnStack.location()) @@ -1207,6 +1213,9 @@ void CompilerUtils::convertType( conversionImpl(m_context); break; } + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; case DataLocation::CallData: { if (typeOnStack.isDynamicallyEncoded()) diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 186cebc78..32fb9cae7 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -592,6 +592,7 @@ void ContractCompiler::initializeStateVariables(ContractDefinition const& _contr bool ContractCompiler::visit(VariableDeclaration const& _variableDeclaration) { solAssert(_variableDeclaration.isStateVariable(), "Compiler visit to non-state variable declaration."); + solUnimplementedAssert(_variableDeclaration.referenceLocation() != VariableDeclaration::Location::Transient, "Transient storage variables not supported."); CompilerContext::LocationSetter locationSetter(m_context, _variableDeclaration); m_context.startFunction(_variableDeclaration); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c7bc9a826..6027e0404 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -2047,6 +2047,9 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) ArrayUtils(m_context).retrieveLength(type); m_context << Instruction::SWAP1 << Instruction::POP; break; + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; case DataLocation::Memory: m_context << Instruction::MLOAD; break; @@ -2193,6 +2196,9 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) else setLValueToStorageItem(_indexAccess); break; + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; case DataLocation::Memory: ArrayUtils(m_context).accessIndex(arrayType); setLValue(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArrayOrString()); diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 9d1929fe1..ebf1d384a 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -2563,6 +2563,9 @@ std::string YulUtilFunctions::nextArrayElementFunction(ArrayType const& _type) templ("advance", toCompactHexWithPrefix(size)); break; } + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; case DataLocation::CallData: { u256 size = _type.calldataStride(); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 2464fefc4..2f823fcbf 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -47,6 +47,7 @@ #include #include +#include #include using namespace solidity; @@ -374,6 +375,15 @@ void IRGeneratorForStatements::endVisit(VariableDeclarationStatement const& _var { setLocation(_varDeclStatement); + auto static notTransient = [](std::shared_ptr const& _varDeclaration) { + return (_varDeclaration ? _varDeclaration->referenceLocation() != VariableDeclaration::Location::Transient : true); + }; + + solUnimplementedAssert( + ranges::all_of(_varDeclStatement.declarations(), notTransient), + "Transient storage variables are not supported." + ); + if (Expression const* expression = _varDeclStatement.initialValue()) { if (_varDeclStatement.declarations().size() > 1) @@ -2314,6 +2324,9 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) break; } + case DataLocation::Transient: + solUnimplemented("Transient data location is only supported for value types."); + break; case DataLocation::Memory: { std::string const indexAccessFunction = m_utils.memoryArrayIndexAccessFunction(arrayType); diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index b1a326fc7..2fc24f1f6 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -184,6 +184,9 @@ bool BMC::shouldInlineFunctionCall( bool BMC::visit(ContractDefinition const& _contract) { + // Raises UnimplementedFeatureError in the presence of transient storage variables + TransientDataLocationChecker checker(_contract); + initContract(_contract); SMTEncoder::visit(_contract); diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 66ebd47ed..5e3727712 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -143,6 +143,9 @@ bool CHC::visit(ContractDefinition const& _contract) if (!shouldAnalyze(_contract)) return false; + // Raises UnimplementedFeatureError in the presence of transient storage variables + TransientDataLocationChecker checker(_contract); + resetContractAnalysis(); initContract(_contract); clearIndices(&_contract); diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index bea3a85ef..77e618fed 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -129,6 +129,19 @@ class SMTEncoder: public ASTConstVisitor static std::set sourceDependencies(SourceUnit const& _source); protected: + struct TransientDataLocationChecker: ASTConstVisitor + { + TransientDataLocationChecker(ContractDefinition const& _contract) { _contract.accept(*this); } + + void endVisit(VariableDeclaration const& _var) + { + solUnimplementedAssert( + _var.referenceLocation() != VariableDeclaration::Location::Transient, + "Transient storage variables are not supported." + ); + } + }; + void resetSourceAnalysis(); // TODO: Check that we do not have concurrent reads and writes to a variable, diff --git a/libsolidity/interface/StorageLayout.cpp b/libsolidity/interface/StorageLayout.cpp index 7f344f6ed..0153af1a2 100644 --- a/libsolidity/interface/StorageLayout.cpp +++ b/libsolidity/interface/StorageLayout.cpp @@ -46,6 +46,7 @@ Json StorageLayout::generate(ContractDefinition const& _contractDef) Json StorageLayout::generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset) { + solUnimplementedAssert(_var.referenceLocation() != VariableDeclaration::Location::Transient, "Transient storage layout is not supported yet."); Json varEntry; Type const* varType = _var.type(); diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 7e2fe030a..b51eb9c44 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -885,6 +885,19 @@ ASTPointer Parser::parseVariableDeclaration( } } } + else if ( + _options.kind == VarDeclKind::State && + token == Token::Identifier && + m_scanner->currentLiteral() == "transient" && + m_scanner->peekNextToken() != Token::Assign && + m_scanner->peekNextToken() != Token::Semicolon + ) + { + if (location != VariableDeclaration::Location::Unspecified) + parserError(ErrorId{3548}, "Location already specified."); + else + location = VariableDeclaration::Location::Transient; + } else break; nodeFactory.markEndPosition(); diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 24ec2b06d..54dd00c26 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -202,6 +202,7 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "4591", # "There are more than 256 warnings. Ignoring the rest." # Due to 3805, the warning lists look different for different compiler builds. "1920", # Unimplemented feature error from YulStack (currently there are no UnimplementedFeatureErrors thrown by libyul) + "7053", # Unimplemented feature error (parsing stage), currently has no tests "1180", # SMTChecker, covered by CL tests "2339", # SMTChecker, covered by CL tests "2961", # SMTChecker, covered by CL tests diff --git a/test/cmdlineTests/storage_layout_transient_value_types/in.sol b/test/cmdlineTests/storage_layout_transient_value_types/in.sol new file mode 100644 index 000000000..ba7943c6a --- /dev/null +++ b/test/cmdlineTests/storage_layout_transient_value_types/in.sol @@ -0,0 +1,10 @@ +//SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract A { + uint transient x; + uint y; + bytes32 transient b; + bytes32 c; + address transient a; + address z; +} \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_transient_value_types/input.json b/test/cmdlineTests/storage_layout_transient_value_types/input.json new file mode 100644 index 000000000..96d71ed30 --- /dev/null +++ b/test/cmdlineTests/storage_layout_transient_value_types/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "fileA": {"urls": ["storage_layout_transient_value_types/in.sol"]} + }, + "settings": { + "outputSelection": { + "fileA": { + "A": ["storageLayout"] + } + } + } +} diff --git a/test/cmdlineTests/storage_layout_transient_value_types/output.json b/test/cmdlineTests/storage_layout_transient_value_types/output.json new file mode 100644 index 000000000..a44621048 --- /dev/null +++ b/test/cmdlineTests/storage_layout_transient_value_types/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Transient storage layout is not supported yet.", + "message": "Transient storage layout is not supported yet.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/libsolidity/astPropertyTests/transient_data_location.sol b/test/libsolidity/astPropertyTests/transient_data_location.sol new file mode 100644 index 000000000..6a937414d --- /dev/null +++ b/test/libsolidity/astPropertyTests/transient_data_location.sol @@ -0,0 +1,8 @@ +contract C { + /// TestVarDataLocation: storageLocation + /// TestVarName: name + uint transient transient; +} +// ---- +// TestVarDataLocation: transient +// TestVarName: transient diff --git a/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol b/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol new file mode 100644 index 000000000..b2dbc8efe --- /dev/null +++ b/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol @@ -0,0 +1,8 @@ +contract C { + uint transient x = 42; + function test() public view { assert(x == 42); } +} +// ==== +// SMTEngine: all +// ---- +// UnimplementedFeatureError 1834: Transient storage variables are not supported. diff --git a/test/libsolidity/syntaxTests/constants/constant_state_variable_named_transient.sol b/test/libsolidity/syntaxTests/constants/constant_state_variable_named_transient.sol new file mode 100644 index 000000000..4d9873d36 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/constant_state_variable_named_transient.sol @@ -0,0 +1,4 @@ +contract C { + int constant public transient = 0; +} +// ---- diff --git a/test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol b/test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol new file mode 100644 index 000000000..f9a722a1b --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol @@ -0,0 +1,5 @@ +contract C { + int constant public transient x = 0; +} +// ---- +// DeclarationError 2197: (17-52): Transient cannot be used as data location for constant or immutable variables. diff --git a/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol b/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol index 4e5091e8c..cd46b15b0 100644 --- a/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol +++ b/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol @@ -2,7 +2,10 @@ library L { struct Nested { uint y; } function b(function(Nested calldata) external returns (uint)[] storage) external pure {} function d(function(Nested storage) external returns (uint)[] storage) external pure {} + function f(function(Nested transient) external returns (uint)[] storage) external pure {} } // ---- +// Warning 6162: (251-267): Naming function type parameters is deprecated. // TypeError 6651: (159-173): Data location must be "memory" or "calldata" for parameter in function, but "storage" was given. +// TypeError 6651: (251-267): Data location must be "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_transient.sol b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_transient.sol new file mode 100644 index 000000000..98fbb2d5e --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_transient.sol @@ -0,0 +1,5 @@ +contract test { + function f(bytes transient) external; +} +// ---- +// TypeError 6651: (31-46): Data location must be "memory" or "calldata" for parameter in external function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_transient.sol b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_transient.sol new file mode 100644 index 000000000..4a5b6f999 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_transient.sol @@ -0,0 +1,5 @@ +contract test { + function f(bytes transient) internal {} +} +// ---- +// TypeError 6651: (31-46): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_transient.sol b/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_transient.sol new file mode 100644 index 000000000..75253342c --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_transient.sol @@ -0,0 +1,19 @@ +library L { + function f1(uint[] transient) private pure { } + function f2() private pure returns (uint[] transient) { } + function g1(uint[] transient) internal pure { } + function g2() internal pure returns (uint[] transient) { } + function h1(uint[] transient) public pure { } + function h2() public pure returns (uint[] transient) { } + function i1(uint[] transient) external pure { } + function i2() external pure returns (uint[] transient) { } +} +// ---- +// TypeError 6651: (28-44): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. +// TypeError 6651: (103-119): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given. +// TypeError 6651: (141-157): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. +// TypeError 6651: (218-234): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given. +// TypeError 6651: (256-272): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. +// TypeError 6651: (329-345): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given. +// TypeError 6651: (367-383): Data location must be "storage", "memory" or "calldata" for parameter in external function, but none was given. +// TypeError 6651: (444-460): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_transient.sol b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_transient.sol new file mode 100644 index 000000000..1dcedf49a --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_transient.sol @@ -0,0 +1,5 @@ +library test { + function f(bytes transient) external {} +} +// ---- +// TypeError 6651: (30-45): Data location must be "storage", "memory" or "calldata" for parameter in external function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_transient.sol b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_transient.sol new file mode 100644 index 000000000..d66fa7fad --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_transient.sol @@ -0,0 +1,5 @@ +library test { + function f(bytes transient) internal pure {} +} +// ---- +// TypeError 6651: (30-45): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/multiple_transient_data_location_function_parameter.sol b/test/libsolidity/syntaxTests/dataLocations/multiple_transient_data_location_function_parameter.sol new file mode 100644 index 000000000..193565b2a --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/multiple_transient_data_location_function_parameter.sol @@ -0,0 +1,6 @@ +contract C { + function f(uint[] transient transient x) public pure { } +} + +// ---- +// ParserError 2314: (45-54): Expected ',' but got identifier diff --git a/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_parameters_location_transient.sol b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_parameters_location_transient.sol new file mode 100644 index 000000000..750aa4fee --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_parameters_location_transient.sol @@ -0,0 +1,5 @@ +contract C { + function f(uint[] transient) private pure {} +} +// ---- +// TypeError 6651: (28-44): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_return_parameters_location_transient.sol b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_return_parameters_location_transient.sol new file mode 100644 index 000000000..d1bf87624 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_return_parameters_location_transient.sol @@ -0,0 +1,5 @@ +contract C { + function f() private pure returns (uint[] transient) {} +} +// ---- +// TypeError 6651: (52-68): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_transient.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_transient.sol new file mode 100644 index 000000000..ce4f42f46 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_transient.sol @@ -0,0 +1,5 @@ +contract test { + function f(bytes transient) public; +} +// ---- +// TypeError 6651: (31-46): Data location must be "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_return_parameters_location_transient.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_return_parameters_location_transient.sol new file mode 100644 index 000000000..862b7d236 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_return_parameters_location_transient.sol @@ -0,0 +1,5 @@ +contract C { + function h() public pure returns(uint[] transient) {} +} +// ---- +// TypeError 6651: (50-66): Data location must be "memory" or "calldata" for return parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/state_variable_storage_named_transient.sol b/test/libsolidity/syntaxTests/dataLocations/state_variable_storage_named_transient.sol new file mode 100644 index 000000000..afa6fd250 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/state_variable_storage_named_transient.sol @@ -0,0 +1,5 @@ +contract C { + uint storage transient; +} +// ---- +// ParserError 2314: (22-29): Expected identifier but got 'storage' diff --git a/test/libsolidity/syntaxTests/dataLocations/state_variable_storage_transient.sol b/test/libsolidity/syntaxTests/dataLocations/state_variable_storage_transient.sol new file mode 100644 index 000000000..d3fb023e0 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/state_variable_storage_transient.sol @@ -0,0 +1,5 @@ +contract C { + uint storage transient x; +} +// ---- +// ParserError 2314: (22-29): Expected identifier but got 'storage' diff --git a/test/libsolidity/syntaxTests/dataLocations/state_variable_transient_storage.sol b/test/libsolidity/syntaxTests/dataLocations/state_variable_transient_storage.sol new file mode 100644 index 000000000..53260194d --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/state_variable_transient_storage.sol @@ -0,0 +1,5 @@ +contract C { + uint transient storage x; +} +// ---- +// ParserError 2314: (32-39): Expected identifier but got 'storage' diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol new file mode 100644 index 000000000..b82f40267 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol @@ -0,0 +1,7 @@ +contract C { + uint[] transient x; +} +// ==== +// stopAfter: analysis +// ---- +// UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol new file mode 100644 index 000000000..3f7cec2a7 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol @@ -0,0 +1,7 @@ +contract C { + uint[3] transient x; +} +// ==== +// stopAfter: analysis +// ---- +// UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol b/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol new file mode 100644 index 000000000..9deba463c --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol @@ -0,0 +1,11 @@ +contract C { + function () transient f; + function (uint) external transient y; + function () transient internal fti; + function () internal transient fit; + function () internal transient internal fiti; + function () internal internal transient fiit; +} +// ==== +// stopAfter: analysis +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_function_type_parameter.sol b/test/libsolidity/syntaxTests/dataLocations/transient_function_type_parameter.sol new file mode 100644 index 000000000..04f20e85c --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_function_type_parameter.sol @@ -0,0 +1,5 @@ +contract C { + function (uint transient) external y; +} +// ---- +// Warning 6162: (27-41): Naming function type parameters is deprecated. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_local_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_local_variable.sol new file mode 100644 index 000000000..7602a4cb9 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_local_variable.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + uint transient x = 0; + } +} +// ---- +// ParserError 2314: (67-68): Expected ';' but got identifier diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol new file mode 100644 index 000000000..cd762df30 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol @@ -0,0 +1,7 @@ +contract C { + mapping(uint => uint) transient y; +} +// ==== +// stopAfter: analysis +// ---- +// UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol b/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol new file mode 100644 index 000000000..2579d5532 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol @@ -0,0 +1,12 @@ +contract C { + uint public transient pubt; + uint internal transient it; + uint private transient prvt; + + uint transient public tpub; + uint transient internal ti; + uint transient private tprv; +} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_struct_state_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_struct_state_variable.sol new file mode 100644 index 000000000..19612b9c5 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_struct_state_variable.sol @@ -0,0 +1,12 @@ +struct S { + uint x; + address a; +} + +contract C { + S transient s; +} +// ==== +// stopAfter: analysis +// ---- +// UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol new file mode 100644 index 000000000..55faa1495 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol @@ -0,0 +1,12 @@ +contract D { } + +contract C { + address transient a; + bool transient b; + D transient d; + uint transient x; + bytes32 transient y; +} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol new file mode 100644 index 000000000..10dad9e32 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol @@ -0,0 +1,10 @@ +contract D { } + +contract C { + int transient x = -99; + address transient a = address(0xABC); + bool transient b = x > 0 ? false : true; +} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/errors/invalid_parameter_location.sol b/test/libsolidity/syntaxTests/errors/invalid_parameter_location.sol index a116188d2..38f1bd9af 100644 --- a/test/libsolidity/syntaxTests/errors/invalid_parameter_location.sol +++ b/test/libsolidity/syntaxTests/errors/invalid_parameter_location.sol @@ -10,7 +10,12 @@ contract test { contract test { error e1(string calldata a); } +==== Source: D ==== +contract test { + error e1(string transient a); +} // ---- // ParserError 2314: (A:36-43): Expected ',' but got 'storage' // ParserError 2314: (B:36-42): Expected ',' but got 'memory' // ParserError 2314: (C:36-44): Expected ',' but got 'calldata' +// ParserError 2314: (D:46-47): Expected ',' but got identifier diff --git a/test/libsolidity/syntaxTests/events/invalid_parameter_location.sol b/test/libsolidity/syntaxTests/events/invalid_parameter_location.sol index 04ee9b7bc..1f13bbf90 100644 --- a/test/libsolidity/syntaxTests/events/invalid_parameter_location.sol +++ b/test/libsolidity/syntaxTests/events/invalid_parameter_location.sol @@ -10,7 +10,12 @@ contract test { contract test { event e1(string calldata a); } +==== Source: D ==== +contract test { + event e1(string transient a); +} // ---- // ParserError 2314: (A:36-43): Expected ',' but got 'storage' // ParserError 2314: (B:36-42): Expected ',' but got 'memory' // ParserError 2314: (C:36-44): Expected ',' but got 'calldata' +// ParserError 2314: (D:46-47): Expected ',' but got identifier diff --git a/test/libsolidity/syntaxTests/events/transient_indexed_parameter.sol b/test/libsolidity/syntaxTests/events/transient_indexed_parameter.sol new file mode 100644 index 000000000..718451de2 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/transient_indexed_parameter.sol @@ -0,0 +1,5 @@ +contract C { + event e(string indexed transient a); +} +// ---- +// ParserError 2314: (50-51): Expected ',' but got identifier diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_with_transient_param.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_with_transient_param.sol new file mode 100644 index 000000000..b38e37177 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_with_transient_param.sol @@ -0,0 +1,8 @@ +contract C { + function (uint transient) external y; + function (uint[] transient) external z; +} +// ---- +// Warning 6162: (27-41): Naming function type parameters is deprecated. +// Warning 6162: (69-85): Naming function type parameters is deprecated. +// TypeError 6651: (69-85): Data location must be "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/functionTypes/transient_function_type_with_param_named_transient.sol b/test/libsolidity/syntaxTests/functionTypes/transient_function_type_with_param_named_transient.sol new file mode 100644 index 000000000..fd2884143 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/transient_function_type_with_param_named_transient.sol @@ -0,0 +1,6 @@ +contract C { + function (uint transient) external transient y; +} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/functionTypes/transient_function_type_with_transient_param.sol b/test/libsolidity/syntaxTests/functionTypes/transient_function_type_with_transient_param.sol new file mode 100644 index 000000000..74e5b3413 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/transient_function_type_with_transient_param.sol @@ -0,0 +1,5 @@ +contract C { + function (uint transient x) external transient y; +} +// ---- +// ParserError 2314: (42-43): Expected ',' but got identifier diff --git a/test/libsolidity/syntaxTests/immutable/immutable_state_var_named_transient.sol b/test/libsolidity/syntaxTests/immutable/immutable_state_var_named_transient.sol new file mode 100644 index 000000000..c0ac3a8ab --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/immutable_state_var_named_transient.sol @@ -0,0 +1,4 @@ +contract C { + address public immutable transient; +} +// ---- diff --git a/test/libsolidity/syntaxTests/immutable/state_var_transient_data_location.sol b/test/libsolidity/syntaxTests/immutable/state_var_transient_data_location.sol new file mode 100644 index 000000000..a3d93848d --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/state_var_transient_data_location.sol @@ -0,0 +1,5 @@ +contract C { + uint public immutable transient x; +} +// ---- +// DeclarationError 2197: (17-50): Transient cannot be used as data location for constant or immutable variables. diff --git a/test/libsolidity/syntaxTests/modifiers/multiple_parameter_location.sol b/test/libsolidity/syntaxTests/modifiers/multiple_parameter_location.sol index e264a593f..24bb1cc32 100644 --- a/test/libsolidity/syntaxTests/modifiers/multiple_parameter_location.sol +++ b/test/libsolidity/syntaxTests/modifiers/multiple_parameter_location.sol @@ -8,6 +8,12 @@ contract A { modifier mod7(string calldata storage a) { _; } modifier mod8(string calldata memory a) { _; } modifier mod9(string calldata calldata a) { _; } + modifier modA(string transient storage a) { _; } + modifier modB(string transient memory a) { _; } + modifier modC(string transient calldata a) { _; } + modifier modD(string storage transient a) { _; } + modifier modE(string memory transient a) { _; } + modifier modF(string calldata transient a) { _; } } // ---- // ParserError 3548: (46-53): Location already specified. @@ -19,3 +25,4 @@ contract A { // ParserError 3548: (350-357): Location already specified. // ParserError 3548: (402-408): Location already specified. // ParserError 3548: (453-461): Location already specified. +// ParserError 2314: (507-514): Expected ',' but got 'storage' diff --git a/test/libsolidity/syntaxTests/modifiers/transient_parameter.sol b/test/libsolidity/syntaxTests/modifiers/transient_parameter.sol new file mode 100644 index 000000000..be90ca54d --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/transient_parameter.sol @@ -0,0 +1,5 @@ +contract A { + modifier mod2(uint[] transient) { _; } +} +// ---- +// TypeError 6651: (31-47): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/operators/transient_value_type.sol b/test/libsolidity/syntaxTests/operators/transient_value_type.sol new file mode 100644 index 000000000..3d83fe240 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/transient_value_type.sol @@ -0,0 +1,11 @@ +contract C { + int transient x; + function f() public view returns (int) { + int y = x; + int w = -x; + return (x + w) * (y / x); + } +} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/contract_named_transient.sol b/test/libsolidity/syntaxTests/parsing/contract_named_transient.sol new file mode 100644 index 000000000..853396f21 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/contract_named_transient.sol @@ -0,0 +1 @@ +contract transient {} diff --git a/test/libsolidity/syntaxTests/structs/transient_data_location_member.sol b/test/libsolidity/syntaxTests/structs/transient_data_location_member.sol new file mode 100644 index 000000000..110d4969a --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/transient_data_location_member.sol @@ -0,0 +1,5 @@ +struct S { + int transient x; +} +// ---- +// ParserError 2314: (29-30): Expected ';' but got identifier diff --git a/test/libsolidity/syntaxTests/types/address/state_variable_address_payable_transient.sol b/test/libsolidity/syntaxTests/types/address/state_variable_address_payable_transient.sol new file mode 100644 index 000000000..0cab96722 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/state_variable_address_payable_transient.sol @@ -0,0 +1,6 @@ +contract C { + address payable transient a; +} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/types/address/state_variable_address_transient_payable.sol b/test/libsolidity/syntaxTests/types/address/state_variable_address_transient_payable.sol new file mode 100644 index 000000000..16d8adb49 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/state_variable_address_transient_payable.sol @@ -0,0 +1,5 @@ +contract C { + address transient payable a; +} +// ---- +// ParserError 2314: (35-42): Expected identifier but got 'payable' diff --git a/test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier.sol b/test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier.sol new file mode 100644 index 000000000..ced189faf --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier.sol @@ -0,0 +1,25 @@ +contract C { + function transient() public pure { } +} + +error CustomError(uint transient); +event e1(uint transient); +event e2(uint indexed transient); + +struct S { + int transient; +} + +contract D { + function f() public pure returns (uint) { + uint transient = 1; + return transient; + } + + function g(int transient) public pure { } + + modifier m(address transient) { + _; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier_and_data_location.sol b/test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier_and_data_location.sol new file mode 100644 index 000000000..532df5ba0 --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier_and_data_location.sol @@ -0,0 +1,6 @@ +contract C { + uint transient transient; +} +// ==== +// stopAfter: parsing +// ---- From 06c27a5e06683a23e31413215e6561d33acf32ea Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Sun, 2 Jun 2024 20:45:27 +0200 Subject: [PATCH 0177/1340] Require with custom error for legacy pipeline --- Changelog.md | 1 + libsolidity/codegen/ExpressionCompiler.cpp | 49 +++++++++++++++++-- ...quire_different_errors_same_parameters.sol | 2 - ...re_error_condition_evaluated_only_once.sol | 24 +++++++++ ...l => require_error_evaluation_order_1.sol} | 2 - .../require_error_evaluation_order_2.sol | 16 ++++++ .../require_error_evaluation_order_3.sol | 15 ++++++ ...quire_error_function_join_control_flow.sol | 18 +++++++ ...quire_error_function_pointer_parameter.sol | 2 - .../require_error_multiple_arguments.sol | 2 - .../errors/require_error_stack_check.sol | 19 +++++++ .../errors/require_error_string_literal.sol | 2 - .../errors/require_error_string_memory.sol | 2 - .../errors/require_error_uint256.sol | 6 +-- .../errors/require_inherited_error.sol | 2 - .../syntaxTests/errors/require_custom.sol | 2 - .../errors/require_custom_legacy.sol | 8 --- .../syntaxTests/errors/require_nested.sol | 2 - 18 files changed, 139 insertions(+), 35 deletions(-) create mode 100644 test/libsolidity/semanticTests/errors/require_error_condition_evaluated_only_once.sol rename test/libsolidity/semanticTests/errors/{require_evaluation_order.sol => require_error_evaluation_order_1.sol} (92%) create mode 100644 test/libsolidity/semanticTests/errors/require_error_evaluation_order_2.sol create mode 100644 test/libsolidity/semanticTests/errors/require_error_evaluation_order_3.sol create mode 100644 test/libsolidity/semanticTests/errors/require_error_function_join_control_flow.sol create mode 100644 test/libsolidity/semanticTests/errors/require_error_stack_check.sol delete mode 100644 test/libsolidity/syntaxTests/errors/require_custom_legacy.sol diff --git a/Changelog.md b/Changelog.md index 8ac9a7895..9d1aa77c6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,7 @@ Language Features: * Accept declarations of state variables with ``transient`` data location (parser support only, no code generation yet). + * Make ``require(bool, Error)`` available when using the legacy pipeline. Compiler Features: diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 6027e0404..368ee77a8 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -990,6 +990,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) } case FunctionType::Kind::Error: { + // This case is part of the ``revert `` path of the codegen. + // For ``require(bool, )`` refer to the ``Kind::Require`` case. _functionCall.expression().accept(*this); std::vector argumentTypes; for (ASTPointer const& arg: _functionCall.sortedArguments()) @@ -1249,9 +1251,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) case FunctionType::Kind::Require: { acceptAndConvert(*arguments.front(), *function.parameterTypes().front(), false); - + // stack: bool haveReasonString = arguments.size() > 1 && m_context.revertStrings() != RevertStrings::Strip; - if (arguments.size() > 1) { // Users probably expect the second argument to be evaluated @@ -1259,11 +1260,49 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) // function call. solAssert(arguments.size() == 2, ""); solAssert(function.kind() == FunctionType::Kind::Require, ""); - // Check if the function call matches ``require(bool, error)``, and throw an unimplemented error, - // as require with custom errors is not supported in legacy codegen. auto const* magicType = dynamic_cast(arguments[1]->annotation().type); if (magicType && magicType->kind() == MagicType::Kind::Error) - solUnimplemented("Require with a custom error is only available using the via-ir pipeline."); + { + // Make sure that error constructor arguments are evaluated regardless of the require condition + auto const& errorConstructorCall = dynamic_cast(*arguments[1]); + errorConstructorCall.expression().accept(*this); + std::vector errorConstructorArgumentTypes{}; + for (ASTPointer const& errorConstructorArgument: errorConstructorCall.sortedArguments()) + { + errorConstructorArgument->accept(*this); + errorConstructorArgumentTypes.push_back(errorConstructorArgument->annotation().type); + } + unsigned const sizeOfConditionArgument = arguments.at(0)->annotation().type->sizeOnStack(); + unsigned const sizeOfErrorArguments = CompilerUtils::sizeOnStack(errorConstructorArgumentTypes); + // stack: ... + try + { + // Move condition to the top of the stack + utils().moveToStackTop(sizeOfErrorArguments, sizeOfConditionArgument); + } + catch (StackTooDeepError const& _exception) + { + _exception << errinfo_sourceLocation(errorConstructorCall.location()); + throw _exception; + } + // stack: ... + m_context << Instruction::ISZERO << Instruction::ISZERO; + AssemblyItem successBranchTag = m_context.appendConditionalJump(); + + auto const* errorDefinition = dynamic_cast(ASTNode::referencedDeclaration(errorConstructorCall.expression())); + solAssert(errorDefinition && errorDefinition->functionType(true)); + utils().revertWithError( + errorDefinition->functionType(true)->externalSignature(), + errorDefinition->functionType(true)->parameterTypes(), + errorConstructorArgumentTypes + ); + // Here, the argument is consumed, but in the other branch, it is still there. + m_context.adjustStackOffset(static_cast(sizeOfErrorArguments)); + m_context << successBranchTag; + // In case of the success branch i.e. require(true, ...), pop error constructor arguments + utils().popStackSlots(sizeOfErrorArguments); + break; + } if (m_context.revertStrings() == RevertStrings::Strip) { diff --git a/test/libsolidity/semanticTests/errors/require_different_errors_same_parameters.sol b/test/libsolidity/semanticTests/errors/require_different_errors_same_parameters.sol index 37cbb207d..957cb0bb1 100644 --- a/test/libsolidity/semanticTests/errors/require_different_errors_same_parameters.sol +++ b/test/libsolidity/semanticTests/errors/require_different_errors_same_parameters.sol @@ -14,8 +14,6 @@ contract C } } -// ==== -// compileViaYul: true // ---- // f() -> FAILURE, hex"f55fefe3", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"74776f0000000000000000000000000000000000000000000000000000000000" // g() -> FAILURE, hex"44a06798", hex"0000000000000000000000000000000000000000000000000000000000000004", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000006", hex"0000000000000000000000000000000000000000000000000000000000000004", hex"6669766500000000000000000000000000000000000000000000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_condition_evaluated_only_once.sol b/test/libsolidity/semanticTests/errors/require_error_condition_evaluated_only_once.sol new file mode 100644 index 000000000..e344af43f --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_condition_evaluated_only_once.sol @@ -0,0 +1,24 @@ +contract C { + uint256 counter = 0; + + error CustomError(uint256); + + function getCounter() public view returns (uint256) { + return counter; + } + + function g(bool condition) internal returns (bool) { + counter++; + return condition; + } + + function f(bool condition) external { + require(g(condition), CustomError(counter)); + } +} + +// ---- +// f(bool): false -> FAILURE, hex"110b3655", 1 +// getCounter() -> 0 +// f(bool): true -> +// getCounter() -> 1 diff --git a/test/libsolidity/semanticTests/errors/require_evaluation_order.sol b/test/libsolidity/semanticTests/errors/require_error_evaluation_order_1.sol similarity index 92% rename from test/libsolidity/semanticTests/errors/require_evaluation_order.sol rename to test/libsolidity/semanticTests/errors/require_error_evaluation_order_1.sol index 4733b3aee..019c282c6 100644 --- a/test/libsolidity/semanticTests/errors/require_evaluation_order.sol +++ b/test/libsolidity/semanticTests/errors/require_error_evaluation_order_1.sol @@ -21,8 +21,6 @@ contract C } } -// ==== -// compileViaYul: true // ---- // f() -> 7 // g() -> 7 diff --git a/test/libsolidity/semanticTests/errors/require_error_evaluation_order_2.sol b/test/libsolidity/semanticTests/errors/require_error_evaluation_order_2.sol new file mode 100644 index 000000000..610caeef6 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_evaluation_order_2.sol @@ -0,0 +1,16 @@ +contract C { + uint y; + function g(bool x) internal returns (bool) { + y = 42; + return x; + } + error E(uint256); + function h() internal returns (uint256) { return y; } + function f(bool c) public { + require(g(c), E(h())); + } +} + +// ---- +// f(bool): false -> FAILURE, hex"002ff067", 42 +// f(bool): true -> diff --git a/test/libsolidity/semanticTests/errors/require_error_evaluation_order_3.sol b/test/libsolidity/semanticTests/errors/require_error_evaluation_order_3.sol new file mode 100644 index 000000000..0d70b16b9 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_evaluation_order_3.sol @@ -0,0 +1,15 @@ +contract C { + string failureMessage = "Failure Message"; + function g(bool x) internal returns (bool) { + failureMessage = "Intercepted failure message"; + return x; + } + function h() internal returns (string memory) { return failureMessage; } + function f(bool c) public { + require(g(c), h()); + } +} + +// ---- +// f(bool): false -> FAILURE, hex"08c379a0", 0x20, 0x1b, "Intercepted failure message" +// f(bool): true -> diff --git a/test/libsolidity/semanticTests/errors/require_error_function_join_control_flow.sol b/test/libsolidity/semanticTests/errors/require_error_function_join_control_flow.sol new file mode 100644 index 000000000..e3d7e5fdd --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_function_join_control_flow.sol @@ -0,0 +1,18 @@ +contract C { + uint x = 0; + uint y = 42; + error E(uint); + function f(bool c) public returns (uint256, uint256, uint256) { + uint z = x; + if (y == 42) { + x = 21; + } else { + require(c, E(y)); + } + y /= 2; + return (x,y,z); + } +} +// ---- +// f(bool): true -> 0x15, 0x15, 0 +// f(bool): false -> FAILURE, hex"002ff067", 21 diff --git a/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol b/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol index 2e1dcdd58..3af19ca64 100644 --- a/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol +++ b/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol @@ -14,7 +14,5 @@ contract C } } -// ==== -// compileViaYul: true // ---- // f() -> FAILURE, hex"271b1dfa", hex"c06afe3a8444fc0004668591e8306bfb9968e79ef37cdc8e0000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_multiple_arguments.sol b/test/libsolidity/semanticTests/errors/require_error_multiple_arguments.sol index 6c8521f9d..98254cf08 100644 --- a/test/libsolidity/semanticTests/errors/require_error_multiple_arguments.sol +++ b/test/libsolidity/semanticTests/errors/require_error_multiple_arguments.sol @@ -13,8 +13,6 @@ contract C } } -// ==== -// compileViaYul: true // ---- // f() -> FAILURE, hex"11a1077e", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"74776f0000000000000000000000000000000000000000000000000000000000" // g() -> FAILURE, hex"11a1077e", hex"0000000000000000000000000000000000000000000000000000000000000004", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000006", hex"0000000000000000000000000000000000000000000000000000000000000004", hex"6669766500000000000000000000000000000000000000000000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_stack_check.sol b/test/libsolidity/semanticTests/errors/require_error_stack_check.sol new file mode 100644 index 000000000..0f77e252d --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_stack_check.sol @@ -0,0 +1,19 @@ +// The purpose of this test is to make sure that error constructor call +// stack items are popped from the stack in the success branch, i.e. when +// require condition is true. +contract C { + error E(uint, uint, uint, function(uint256) external pure returns (uint256)); + uint public x; + + function e(uint256 y) external pure returns (uint256) { + return y; + } + + function f(bool condition, uint a, uint b, uint c) public { + require(condition, E(a, b, c, this.e)); + x = b; + } +} +// ---- +// f(bool,uint256,uint256,uint256): true, 42, 4242, 424242 -> +// x() -> 4242 diff --git a/test/libsolidity/semanticTests/errors/require_error_string_literal.sol b/test/libsolidity/semanticTests/errors/require_error_string_literal.sol index 5a3a140d0..6e72253ea 100644 --- a/test/libsolidity/semanticTests/errors/require_error_string_literal.sol +++ b/test/libsolidity/semanticTests/errors/require_error_string_literal.sol @@ -13,8 +13,6 @@ contract C } } -// ==== -// compileViaYul: true // ---- // f() -> FAILURE, hex"8d6ea8be", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"000000000000000000000000000000000000000000000000000000000000000b", hex"6572726f72526561736f6e000000000000000000000000000000000000000000" // g() -> FAILURE, hex"8d6ea8be", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"000000000000000000000000000000000000000000000000000000000000000d", hex"616e6f74686572526561736f6e00000000000000000000000000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_string_memory.sol b/test/libsolidity/semanticTests/errors/require_error_string_memory.sol index 13947d399..15178d859 100644 --- a/test/libsolidity/semanticTests/errors/require_error_string_memory.sol +++ b/test/libsolidity/semanticTests/errors/require_error_string_memory.sol @@ -15,8 +15,6 @@ contract C } } -// ==== -// compileViaYul: true // ---- // f() -> FAILURE, hex"8d6ea8be", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"000000000000000000000000000000000000000000000000000000000000000b", hex"6572726f72526561736f6e000000000000000000000000000000000000000000" // g() -> FAILURE, hex"8d6ea8be", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"000000000000000000000000000000000000000000000000000000000000000d", hex"616e6f74686572526561736f6e00000000000000000000000000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_uint256.sol b/test/libsolidity/semanticTests/errors/require_error_uint256.sol index d400e5fa7..3b8915f8d 100644 --- a/test/libsolidity/semanticTests/errors/require_error_uint256.sol +++ b/test/libsolidity/semanticTests/errors/require_error_uint256.sol @@ -13,8 +13,6 @@ contract C } } -// ==== -// compileViaYul: true // ---- -// f() -> FAILURE, hex"110b3655", hex"0000000000000000000000000000000000000000000000000000000000000001" -// g() -> FAILURE, hex"110b3655", hex"0000000000000000000000000000000000000000000000000000000000000002" +// f() -> FAILURE, hex"110b3655", 1 +// g() -> FAILURE, hex"110b3655", 2 diff --git a/test/libsolidity/semanticTests/errors/require_inherited_error.sol b/test/libsolidity/semanticTests/errors/require_inherited_error.sol index 24b544b73..33cf0e962 100644 --- a/test/libsolidity/semanticTests/errors/require_inherited_error.sol +++ b/test/libsolidity/semanticTests/errors/require_inherited_error.sol @@ -11,7 +11,5 @@ contract C is Base } } -// ==== -// compileViaYul: true // ---- // f() -> FAILURE, hex"11a1077e", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"74776f0000000000000000000000000000000000000000000000000000000000" diff --git a/test/libsolidity/syntaxTests/errors/require_custom.sol b/test/libsolidity/syntaxTests/errors/require_custom.sol index f42839027..0530e8432 100644 --- a/test/libsolidity/syntaxTests/errors/require_custom.sol +++ b/test/libsolidity/syntaxTests/errors/require_custom.sol @@ -4,6 +4,4 @@ contract C { require(c, E(2, 7)); } } -// ==== -// compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/errors/require_custom_legacy.sol b/test/libsolidity/syntaxTests/errors/require_custom_legacy.sol deleted file mode 100644 index c1eae591f..000000000 --- a/test/libsolidity/syntaxTests/errors/require_custom_legacy.sol +++ /dev/null @@ -1,8 +0,0 @@ -error E(uint a, uint b); -contract C { - function f(bool c) public pure { - require(c, E(2, 7)); - } -} -// ---- -// UnimplementedFeatureError 1834: Require with a custom error is only available using the via-ir pipeline. diff --git a/test/libsolidity/syntaxTests/errors/require_nested.sol b/test/libsolidity/syntaxTests/errors/require_nested.sol index c5dc01824..0129959a0 100644 --- a/test/libsolidity/syntaxTests/errors/require_nested.sol +++ b/test/libsolidity/syntaxTests/errors/require_nested.sol @@ -9,7 +9,5 @@ contract C } } -// ==== -// compileViaYul: true // ---- // TypeError 9322: (118-125): No matching declaration found after argument-dependent lookup. From 20213011040ac85e14ced4bedd20f66d480efa2c Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 11 Jun 2024 16:09:32 +0200 Subject: [PATCH 0178/1340] Changelog and docs --- docs/contracts/errors.rst | 3 +-- docs/control-structures.rst | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/contracts/errors.rst b/docs/contracts/errors.rst index 8c57586e9..d345b4eac 100644 --- a/docs/contracts/errors.rst +++ b/docs/contracts/errors.rst @@ -19,7 +19,7 @@ as well as the newer approach with ``require`` in function ``transferWithRequire .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity ^0.8.26; + pragma solidity ^0.8.27; /// Insufficient balance for transfer. Needed `required` but only /// `available` available. @@ -27,7 +27,6 @@ as well as the newer approach with ``require`` in function ``transferWithRequire /// @param required requested amount to transfer. error InsufficientBalance(uint256 available, uint256 required); - // This will only compile via IR contract TestToken { mapping(address => uint) balance; function transferWithRevertError(address to, uint256 amount) public { diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 81e62ec57..238d26115 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -639,10 +639,6 @@ The ``require`` function provides three overloads: For example, in ``require(condition, CustomError(f()));`` and ``require(condition, f());``, function ``f()`` will be called regardless of whether the supplied condition is ``true`` or ``false``. -.. note:: - Using custom errors with ``require`` is only supported by the via IR pipeline, i.e. compilation via Yul. - For the legacy pipeline, please use ``if (!condition) revert CustomError();`` instead. - An ``Error(string)`` exception (or an exception without data) is generated by the compiler in the following situations: From 933598d2eac23bc96521a3cf8febcfe685b48a9f Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Mon, 17 Jun 2024 21:56:19 +0200 Subject: [PATCH 0179/1340] SMTChecker: Methods returning callback can be const --- libsolidity/interface/SMTSolverCommand.cpp | 2 +- libsolidity/interface/SMTSolverCommand.h | 4 ++-- libsolidity/interface/UniversalCallback.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index 7dfb448f8..1eaa3f38c 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -63,7 +63,7 @@ void SMTSolverCommand::setCvc5(std::optional timeoutInMilliseconds } } -ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::string const& _query) +ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::string const& _query) const { try { diff --git a/libsolidity/interface/SMTSolverCommand.h b/libsolidity/interface/SMTSolverCommand.h index 3b1022740..c948ec5d2 100644 --- a/libsolidity/interface/SMTSolverCommand.h +++ b/libsolidity/interface/SMTSolverCommand.h @@ -29,9 +29,9 @@ class SMTSolverCommand { public: /// Calls an SMT solver with the given query. - frontend::ReadCallback::Result solve(std::string const& _kind, std::string const& _query); + frontend::ReadCallback::Result solve(std::string const& _kind, std::string const& _query) const; - frontend::ReadCallback::Callback solver() + frontend::ReadCallback::Callback solver() const { return [this](std::string const& _kind, std::string const& _query) { return solve(_kind, _query); }; } diff --git a/libsolidity/interface/UniversalCallback.h b/libsolidity/interface/UniversalCallback.h index ef5450a1c..943d7e50c 100644 --- a/libsolidity/interface/UniversalCallback.h +++ b/libsolidity/interface/UniversalCallback.h @@ -46,7 +46,7 @@ class UniversalCallback solAssert(false, "Unknown callback kind."); } - frontend::ReadCallback::Callback callback() + frontend::ReadCallback::Callback callback() const { return *this; } From 3e5516cee5903d6940dd42ee97a8dad21a22c6ec Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Mon, 17 Jun 2024 21:57:49 +0200 Subject: [PATCH 0180/1340] SMTChecker: Add SMT callback to SMTChecker tests --- test/libsolidity/SMTCheckerTest.cpp | 9 ++++++++- test/libsolidity/SMTCheckerTest.h | 12 ++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/test/libsolidity/SMTCheckerTest.cpp b/test/libsolidity/SMTCheckerTest.cpp index e3ec14c97..8149f3130 100644 --- a/test/libsolidity/SMTCheckerTest.cpp +++ b/test/libsolidity/SMTCheckerTest.cpp @@ -25,8 +25,11 @@ using namespace solidity; using namespace solidity::langutil; using namespace solidity::frontend; using namespace solidity::frontend::test; +using namespace solidity::test; -SMTCheckerTest::SMTCheckerTest(std::string const& _filename): SyntaxTest(_filename, EVMVersion{}) +SMTCheckerTest::SMTCheckerTest(std::string const& _filename): + SyntaxTest(_filename, EVMVersion{}), + universalCallback(nullptr, smtCommand) { auto contract = m_reader.stringSetting("SMTContract", ""); if (!contract.empty()) @@ -168,3 +171,7 @@ void SMTCheckerTest::printUpdatedExpectations(std::ostream &_stream, const std:: else CommonSyntaxTest::printUpdatedExpectations(_stream, _linePrefix); } + +std::unique_ptr SMTCheckerTest::createStack() const { + return std::make_unique(universalCallback.callback()); +} diff --git a/test/libsolidity/SMTCheckerTest.h b/test/libsolidity/SMTCheckerTest.h index 6a1579152..07ae3728d 100644 --- a/test/libsolidity/SMTCheckerTest.h +++ b/test/libsolidity/SMTCheckerTest.h @@ -24,6 +24,9 @@ #include +#include +#include + #include namespace solidity::frontend::test @@ -36,7 +39,7 @@ class SMTCheckerTest: public SyntaxTest { return std::make_unique(_config.filename); } - SMTCheckerTest(std::string const& _filename); + explicit SMTCheckerTest(std::string const& _filename); void setupCompiler(CompilerStack& _compiler) override; void filterObtainedErrors() override; @@ -44,6 +47,8 @@ class SMTCheckerTest: public SyntaxTest void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override; protected: + std::unique_ptr createStack() const override; + /* Options that can be set in the test: SMTEngine: `all`, `chc`, `bmc`, `none`, where the default is `all`. @@ -56,7 +61,7 @@ class SMTCheckerTest: public SyntaxTest Set in m_modelCheckerSettings. SMTShowUnproved: `yes`, `no`, where the default is `yes`. Set in m_modelCheckerSettings. - SMTSolvers: `all`, `cvc5`, `z3`, `none`, where the default is `all`. + SMTSolvers: `all`, `cvc5`, `z3`, `eld`, `none`, where the default is `z3`. Set in m_modelCheckerSettings. BMCLoopIterations: number of loop iterations for BMC engine, the default is 1. Set in m_modelCheckerSettings. @@ -67,6 +72,9 @@ class SMTCheckerTest: public SyntaxTest bool m_ignoreCex = false; std::vector m_unfilteredErrorList; + + SMTSolverCommand smtCommand; + UniversalCallback universalCallback; }; } From f9be1e3812e426fde2d8ae59c5241cd6969c15cc Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Mon, 17 Jun 2024 22:01:21 +0200 Subject: [PATCH 0181/1340] SMTChecker: Bring back assertions in "external_calls" SMTChecker tests Several assertions were commented out because of nondeterminism we observed in Spacer, which made these tests brittle. Spacer can now solve some of them, others we can now solve with Eldarica. Note that running Eldarica seems to come with significant overhead, because it starts a new Eldarica process (which starts new JVM) for every query. --- .../external_calls/call_with_value_3.sol | 11 ++++++----- .../external_calls/external_call_with_value_1.sol | 10 +++++----- .../external_hash_known_code_state_reentrancy.sol | 7 +++---- .../external_calls/external_reentrancy_3.sol | 8 ++++---- .../external_calls/mutex_f_no_guard.sol | 7 +++---- 5 files changed, 21 insertions(+), 22 deletions(-) diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_3.sol b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_3.sol index 6cbe24136..4b3dcd091 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_3.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_3.sol @@ -3,13 +3,14 @@ contract C { require(address(this).balance > 100); i.call{value: 20}(""); assert(address(this).balance > 0); // should hold - // Disabled due to Spacer nondeterminism - //assert(address(this).balance == 0); // should fail + assert(address(this).balance == 0); // should fail } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTIgnoreCex: yes +// SMTSolvers: eld // ---- // Warning 9302: (95-116): Return value of low-level calls not used. -// Warning 6328: (120-153): CHC: Assertion violation might happen here. -// Warning 4661: (120-153): BMC: Assertion violation happens here. +// Warning 6328: (172-206): CHC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_1.sol index a5ac8ded9..3ecdb00bd 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_1.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_1.sol @@ -7,12 +7,12 @@ contract C { require(address(this).balance == 100); i.f{value: 10}(); assert(address(this).balance == 90); // should hold - // Disabled due to Spacer nondeterminism - //assert(address(this).balance == 100); // should fail + assert(address(this).balance == 100); // should fail } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTSolvers: eld // ---- -// Warning 6328: (151-186): CHC: Assertion violation might happen here. -// Warning 4661: (151-186): BMC: Assertion violation happens here. +// Warning 6328: (205-241): CHC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy.sol index 29d184895..69f76be6b 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy.sol @@ -19,8 +19,7 @@ contract C { address prevOwner = owner; uint z = s.f(); assert(z == y); - // Disabled because of Spacer nondeterminism. - //assert(prevOwner == owner); + assert(prevOwner == owner); } function g() public view returns (uint) { @@ -31,5 +30,5 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 2072: (219-236): Unused local variable. -// Warning 6328: (266-280): CHC: Assertion violation happens here. +// Warning 6328: (266-280): CHC: Assertion violation happens here.\nCounterexample:\nowner = 0x0, y = 0, s = 0\nprevOwner = 0x0\nz = 1\n\nTransaction trace:\nC.constructor(){ msg.sender: 0x0 }\nState: owner = 0x0, y = 0, s = 0\nC.f()\n s.f() -- untrusted external call +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_3.sol index cfe12434c..bdae00667 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_3.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_reentrancy_3.sol @@ -21,15 +21,15 @@ contract C is A { function f() public view override { assert(x == 1); // should hold - //Disabled because of Spacer nondeterminism. - //assert(x == 0); // should fail + assert(x == 0); // should fail } } // ==== -// SMTEngine: all +// SMTEngine: chc // SMTIgnoreCex: yes // SMTIgnoreInv: yes -// SMTIgnoreOS: macos +// SMTSolvers: eld // ---- // Warning 6328: (154-168): CHC: Assertion violation happens here. +// Warning 6328: (352-366): CHC: Assertion violation happens here. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/mutex_f_no_guard.sol b/test/libsolidity/smtCheckerTests/external_calls/mutex_f_no_guard.sol index 76568adf6..7e66c51e1 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/mutex_f_no_guard.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/mutex_f_no_guard.sol @@ -21,12 +21,11 @@ contract C { function f() public { uint y = x; d.d(); - // Disabled because of Spacer nondeterminism. - //assert(y == x); + assert(y == x); } } // ==== -// SMTEngine: all +// SMTEngine: chc // SMTIgnoreCex: yes // ---- -// Warning 2072: (251-257): Unused local variable. +// Warning 6328: (274-288): CHC: Assertion violation happens here.\nCounterexample:\nx = 0, d = 0, lock = false\ny = 1\n\nTransaction trace:\nC.constructor()\nState: x = 0, d = 0, lock = false\nC.set(1)\nState: x = 1, d = 0, lock = false\nC.f()\n d.d() -- untrusted external call, synthesized as:\n C.set(0) -- reentrant call From fbb5eede41433c91ae94e776fdd173435d01e23c Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 19 Jun 2024 17:42:38 +0200 Subject: [PATCH 0182/1340] Docs: Small update regarding the use of Eldarica --- docs/contributing.rst | 8 ++++++-- docs/installing-solidity.rst | 13 +++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 8ce402680..36b858679 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -93,7 +93,8 @@ Prerequisites For running all compiler tests you may want to optionally install a few dependencies (`evmone `_, -`libz3 `_). +`libz3 `_, `Eldarica `_, +`cvc5 `). On macOS systems, some of the testing scripts expect GNU coreutils to be installed. This can be easiest accomplished using Homebrew: ``brew install coreutils``. @@ -133,11 +134,14 @@ extension ``.so`` on Linux, ``.dll`` on Windows systems and ``.dylib`` on macOS. For running SMT tests, the ``libz3`` library must be installed and locatable by ``cmake`` during compiler configure stage. +A few SMT tests use ``Eldarica`` instead of ``Z3``. +``Eldarica`` is a runtime dependency, its executable (``eld``) must be present in ``PATH`` for the tests to pass. +However, if ``Eldarica`` is not found, these tests will be automatically skipped. If the ``libz3`` library is not installed on your system, you should disable the SMT tests by exporting ``SMT_FLAGS=--no-smt`` before running ``./scripts/tests.sh`` or running ``./scripts/soltest.sh --no-smt``. -These tests are ``libsolidity/smtCheckerTests`` and ``libsolidity/smtCheckerTestsJSON``. +These tests are ``libsolidity/smtCheckerTests``. .. note:: diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index e37fc1985..b1b3e1a3f 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -527,19 +527,24 @@ If you are interested what CMake options are available run ``cmake .. -LH``. SMT Solvers ----------- -Solidity can be built against SMT solvers and will do so by default if -they are found in the system. Each solver can be disabled by a ``cmake`` option. +Solidity can be built against Z3 SMT solver and will do so by default if +it is found in the system. Z3 can be disabled by a ``cmake`` option. *Note: In some cases, this can also be a potential workaround for build failures.* -Inside the build folder you can disable them, since they are enabled by default: +Inside the build folder you can disable Z3, since it is enabled by default: .. code-block:: bash - # disables only Z3 SMT Solver. + # disables Z3 SMT Solver. cmake .. -DUSE_Z3=OFF +.. note:: + + Solidity can optionally use other solvers, namely ``cvc5`` and ``Eldarica``, + but their presence is checked only at runtime, they are not needed for the build to succeed. + The Version String in Detail ============================ From d51dbe83a4020b7888b207204576fd9d8b786fbf Mon Sep 17 00:00:00 2001 From: ToonVanHove <9501896+ToonVanHove@users.noreply.github.com> Date: Fri, 21 Jun 2024 09:17:57 +0200 Subject: [PATCH 0183/1340] doc: better specify blobhash() behaviour --- docs/cheatsheet.rst | 1 + docs/units-and-global-variables.rst | 1 + docs/yul.rst | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index 6b69b81be..79aa6e65d 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -66,6 +66,7 @@ Block and Transaction Properties - ``blobhash(uint index) returns (bytes32)``: versioned hash of the ``index``-th blob associated with the current transaction. A versioned hash consists of a single byte representing the version (currently ``0x01``), followed by the last 31 bytes of the SHA256 hash of the KZG commitment (`EIP-4844 `_). + Returns zero if no blob with the given index exists. - ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 `_ and `EIP-1559 `_) - ``block.blobbasefee`` (``uint``): current block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) - ``block.chainid`` (``uint``): current chain id diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index a743441d5..fce4cf96d 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -77,6 +77,7 @@ Block and Transaction Properties - ``blobhash(uint index) returns (bytes32)``: versioned hash of the ``index``-th blob associated with the current transaction. A versioned hash consists of a single byte representing the version (currently ``0x01``), followed by the last 31 bytes of the SHA256 hash of the KZG commitment (`EIP-4844 `_). + Returns zero if no blob with the given index exists. - ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 `_ and `EIP-1559 `_) - ``block.blobbasefee`` (``uint``): current block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) - ``block.chainid`` (``uint``): current chain id diff --git a/docs/yul.rst b/docs/yul.rst index 3cf2785fc..0932c8fa6 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -934,7 +934,8 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a +-------------------------+-----+---+-----------------------------------------------------------------+ | blockhash(b) | | F | hash of block nr b - only for last 256 blocks excluding current | +-------------------------+-----+---+-----------------------------------------------------------------+ -| blobhash(i) | | N | versioned hash of transaction's i-th blob | +| blobhash(i) | | N | versioned hash of transaction's i-th blob, 0 if blob does not | +| | | | exist | +-------------------------+-----+---+-----------------------------------------------------------------+ | coinbase() | | F | current mining beneficiary | +-------------------------+-----+---+-----------------------------------------------------------------+ From dd60886c88ad78dccd2ab78dc8a4ab8cf0d7dfe3 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 24 Jun 2024 16:02:33 +0200 Subject: [PATCH 0184/1340] Error out on transient usage in TypeChecker --- libsolidity/analysis/TypeChecker.cpp | 7 +++ libsolidity/codegen/ContractCompiler.cpp | 3 + libsolidity/codegen/ir/IRGenerator.cpp | 3 + .../output.json | 57 ++++++++++++++++++- .../transient_data_location.sol | 8 --- .../transient_storage_state_variable.sol | 2 +- ...transient_dynamic_array_state_variable.sol | 2 - .../transient_fixed_array_state_variable.sol | 2 - .../dataLocations/transient_function_type.sol | 8 ++- .../transient_mapping_state_variable.sol | 3 +- .../transient_state_variable_visibility.sol | 8 ++- .../transient_struct_state_variable.sol | 2 - .../transient_value_type_state_variables.sol | 7 ++- ..._value_type_state_variables_assignment.sol | 5 +- 14 files changed, 89 insertions(+), 28 deletions(-) delete mode 100644 test/libsolidity/astPropertyTests/transient_data_location.sol diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 918e27033..dfd334295 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -478,6 +478,13 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) Type const* varType = _variable.annotation().type; solAssert(!!varType, "Variable type not provided."); + if (_variable.referenceLocation() == VariableDeclaration::Location::Transient) + m_errorReporter.unimplementedFeatureError( + 6715_error, + _variable.location(), + "Transient storage is not yet implemented." + ); + if (_variable.value()) { if (_variable.isStateVariable() && varType->containsNestedMapping()) diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 32fb9cae7..2326d3336 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -585,8 +585,11 @@ void ContractCompiler::initializeStateVariables(ContractDefinition const& _contr { solAssert(!_contract.isLibrary(), "Tried to initialize state variables of library."); for (VariableDeclaration const* variable: _contract.stateVariables()) + { + solUnimplementedAssert(variable->referenceLocation() != VariableDeclaration::Location::Transient, "Transient storage variables not supported."); if (variable->value() && !variable->isConstant()) ExpressionCompiler(m_context, m_optimiserSettings.runOrderLiterals).appendStateVariableInitialization(*variable); + } } bool ContractCompiler::visit(VariableDeclaration const& _variableDeclaration) diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 59585c762..93136a1a2 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -821,8 +821,11 @@ std::string IRGenerator::initStateVariables(ContractDefinition const& _contract) { IRGeneratorForStatements generator{m_context, m_utils, m_optimiserSettings}; for (VariableDeclaration const* variable: _contract.stateVariables()) + { + solUnimplementedAssert(variable->referenceLocation() != VariableDeclaration::Location::Transient, "Transient storage variables not supported."); if (!variable->isConstant()) generator.initializeStateVar(*variable); + } return generator.code(); } diff --git a/test/cmdlineTests/storage_layout_transient_value_types/output.json b/test/cmdlineTests/storage_layout_transient_value_types/output.json index a44621048..b77de9326 100644 --- a/test/cmdlineTests/storage_layout_transient_value_types/output.json +++ b/test/cmdlineTests/storage_layout_transient_value_types/output.json @@ -2,10 +2,61 @@ "errors": [ { "component": "general", - "formattedMessage": "Transient storage layout is not supported yet.", - "message": "Transient storage layout is not supported yet.", + "errorCode": "6715", + "formattedMessage": "UnimplementedFeatureError: Transient storage is not yet implemented. + --> fileA:4:5: + | +4 | uint transient x; + | ^^^^^^^^^^^^^^^^ + +", + "message": "Transient storage is not yet implemented.", "severity": "error", + "sourceLocation": { + "end": 91, + "file": "fileA", + "start": 75 + }, + "type": "UnimplementedFeatureError" + }, + { + "component": "general", + "errorCode": "6715", + "formattedMessage": "UnimplementedFeatureError: Transient storage is not yet implemented. + --> fileA:6:5: + | +6 | bytes32 transient b; + | ^^^^^^^^^^^^^^^^^^^ + +", + "message": "Transient storage is not yet implemented.", + "severity": "error", + "sourceLocation": { + "end": 128, + "file": "fileA", + "start": 109 + }, + "type": "UnimplementedFeatureError" + }, + { + "component": "general", + "errorCode": "6715", + "formattedMessage": "UnimplementedFeatureError: Transient storage is not yet implemented. + --> fileA:8:5: + | +8 | address transient a; + | ^^^^^^^^^^^^^^^^^^^ + +", + "message": "Transient storage is not yet implemented.", + "severity": "error", + "sourceLocation": { + "end": 168, + "file": "fileA", + "start": 149 + }, "type": "UnimplementedFeatureError" } - ] + ], + "sources": {} } diff --git a/test/libsolidity/astPropertyTests/transient_data_location.sol b/test/libsolidity/astPropertyTests/transient_data_location.sol deleted file mode 100644 index 6a937414d..000000000 --- a/test/libsolidity/astPropertyTests/transient_data_location.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract C { - /// TestVarDataLocation: storageLocation - /// TestVarName: name - uint transient transient; -} -// ---- -// TestVarDataLocation: transient -// TestVarName: transient diff --git a/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol b/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol index b2dbc8efe..cdb446165 100644 --- a/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol +++ b/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol @@ -5,4 +5,4 @@ contract C { // ==== // SMTEngine: all // ---- -// UnimplementedFeatureError 1834: Transient storage variables are not supported. +// UnimplementedFeatureError 6715: (17-38): Transient storage is not yet implemented. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol index b82f40267..7a3caa86e 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol @@ -1,7 +1,5 @@ contract C { uint[] transient x; } -// ==== -// stopAfter: analysis // ---- // UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol index 3f7cec2a7..10b942e23 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol @@ -1,7 +1,5 @@ contract C { uint[3] transient x; } -// ==== -// stopAfter: analysis // ---- // UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol b/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol index 9deba463c..a3d741bbe 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol @@ -6,6 +6,10 @@ contract C { function () internal transient internal fiti; function () internal internal transient fiit; } -// ==== -// stopAfter: analysis // ---- +// UnimplementedFeatureError 6715: (17-40): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (46-82): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (88-122): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (128-162): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (168-212): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (218-262): Transient storage is not yet implemented. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol index cd762df30..2a21b3e00 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol @@ -1,7 +1,6 @@ contract C { mapping(uint => uint) transient y; } -// ==== -// stopAfter: analysis + // ---- // UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol b/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol index 2579d5532..561d9f21d 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol @@ -7,6 +7,10 @@ contract C { uint transient internal ti; uint transient private tprv; } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 6715: (17-43): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (49-75): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (81-108): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (115-141): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (147-173): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (179-206): Transient storage is not yet implemented. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_struct_state_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_struct_state_variable.sol index 19612b9c5..f89608be4 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_struct_state_variable.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_struct_state_variable.sol @@ -6,7 +6,5 @@ struct S { contract C { S transient s; } -// ==== -// stopAfter: analysis // ---- // UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol index 55faa1495..ce2db200b 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol @@ -7,6 +7,9 @@ contract C { uint transient x; bytes32 transient y; } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 6715: (30-49): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (52-68): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (71-84): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (87-103): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (106-125): Transient storage is not yet implemented. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol index 10dad9e32..33b7bb28c 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol @@ -5,6 +5,7 @@ contract C { address transient a = address(0xABC); bool transient b = x > 0 ? false : true; } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 6715: (30-51): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (54-90): Transient storage is not yet implemented. +// UnimplementedFeatureError 6715: (93-132): Transient storage is not yet implemented. From 0d01c93d96c6bed69b81f5fe784842125f9a887b Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Tue, 25 Jun 2024 16:28:45 +0200 Subject: [PATCH 0185/1340] SMTChecker: Fix formatting of unary minus expressions in invariants Previously, unary minus expressions actually ended up formatted as binary expressions in infix format, which meant that the unary minus operator actually disappeared. Additionally, SMTCheckerTest was actually always ignoring the invariant message, and we fix that as well. --- Changelog.md | 1 + libsolidity/formal/ExpressionFormatter.cpp | 4 +++- scripts/error_codes.py | 1 - test/libsolidity/SMTCheckerTest.cpp | 5 +++-- .../invariants/unary_minus_formatting.sol | 13 +++++++++++++ 5 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/invariants/unary_minus_formatting.sol diff --git a/Changelog.md b/Changelog.md index 698c7fb5d..442c4e34f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,6 +14,7 @@ Compiler Features: Bugfixes: * SMTChecker: Fix error that reports invalid number of verified checks for BMC and CHC engines. + * SMTChecker: Fix formatting of unary minus expressions in invariants. * SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine. * TypeChecker: Fix segfault when assigning nested tuple to tuple. * Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. diff --git a/libsolidity/formal/ExpressionFormatter.cpp b/libsolidity/formal/ExpressionFormatter.cpp index cf2f2c3b8..5a3d11dbe 100644 --- a/libsolidity/formal/ExpressionFormatter.cpp +++ b/libsolidity/formal/ExpressionFormatter.cpp @@ -115,6 +115,8 @@ std::string formatUnaryOp(smtutil::Expression const& _expr, std::vector= 2 arguments from z3. - if (infixOps.count(op)) + if (infixOps.count(op) && args.size() >= 2) return formatInfixOp(infixOps.at(op), strArgs); static std::set const arrayOps{"select", "store", "const_array"}; diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 6171714bd..fcb6f0e7f 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -203,7 +203,6 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): # Due to 3805, the warning lists look different for different compiler builds. "1920", # Unimplemented feature error from YulStack (currently there are no UnimplementedFeatureErrors thrown by libyul) "7053", # Unimplemented feature error (parsing stage), currently has no tests - "1180", # SMTChecker, covered by CL tests "2339", # SMTChecker, covered by CL tests "6240", # SMTChecker, covered by CL tests } diff --git a/test/libsolidity/SMTCheckerTest.cpp b/test/libsolidity/SMTCheckerTest.cpp index 8149f3130..c25025ccf 100644 --- a/test/libsolidity/SMTCheckerTest.cpp +++ b/test/libsolidity/SMTCheckerTest.cpp @@ -107,8 +107,6 @@ SMTCheckerTest::SMTCheckerTest(std::string const& _filename): filtered.emplace_back(e); return filtered; }; - if (m_modelCheckerSettings.invariants.invariants.empty()) - m_expectations = removeInv(std::move(m_expectations)); auto const& ignoreInv = m_reader.stringSetting("SMTIgnoreInv", "yes"); if (ignoreInv == "no") @@ -118,6 +116,9 @@ SMTCheckerTest::SMTCheckerTest(std::string const& _filename): else BOOST_THROW_EXCEPTION(std::runtime_error("Invalid SMT invariant choice.")); + if (m_modelCheckerSettings.invariants.invariants.empty()) + m_expectations = removeInv(std::move(m_expectations)); + auto const& ignoreOSSetting = m_reader.stringSetting("SMTIgnoreOS", "none"); for (std::string const& os: ignoreOSSetting | ranges::views::split(',') | ranges::to>()) { diff --git a/test/libsolidity/smtCheckerTests/invariants/unary_minus_formatting.sol b/test/libsolidity/smtCheckerTests/invariants/unary_minus_formatting.sol new file mode 100644 index 000000000..a41329901 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/invariants/unary_minus_formatting.sol @@ -0,0 +1,13 @@ +contract C { + int x = -1; + function i() public view { + assert(x == -1); + } +} +// ==== +// SMTEngine: chc +// SMTIgnoreInv: no +// SMTSolvers: eld +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1180: Contract invariant(s) for :C:\n(x = -1)\n From 477c413bd9a5ddfa21f3c421210e0bd0bdb8a513 Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 15 May 2024 17:29:39 +0200 Subject: [PATCH 0186/1340] yul literal value is struct of u256 + optional formatting hint or 'unlimited' - unlimited is a string literal for which bytes restrictions don't hold; can occur in builtin function arguments --- .../codegen/ir/IRGeneratorForStatements.cpp | 3 +- libsolutil/CommonData.cpp | 4 +- libsolutil/CommonData.h | 4 +- libyul/AST.cpp | 80 +++++++++ libyul/AST.h | 29 +++- libyul/ASTForward.h | 1 + libyul/AsmAnalysis.cpp | 40 +++-- libyul/AsmJsonConverter.cpp | 17 +- libyul/AsmJsonImporter.cpp | 24 +-- libyul/AsmParser.cpp | 20 ++- libyul/AsmParser.h | 4 +- libyul/AsmPrinter.cpp | 14 +- libyul/CMakeLists.txt | 1 + libyul/Dialect.cpp | 10 +- libyul/Dialect.h | 3 +- libyul/Utilities.cpp | 152 ++++++++++++++---- libyul/Utilities.h | 21 ++- libyul/backends/evm/ConstantOptimiser.cpp | 6 +- .../backends/evm/ControlFlowGraphBuilder.cpp | 6 +- libyul/backends/evm/EVMCodeTransform.cpp | 2 +- libyul/backends/evm/EVMDialect.cpp | 16 +- libyul/backends/evm/EVMMetrics.cpp | 2 +- .../evm/OptimizedEVMCodeTransform.cpp | 2 +- libyul/optimiser/BlockHasher.cpp | 28 ++-- libyul/optimiser/BlockHasher.h | 11 +- .../CommonSubexpressionEliminator.cpp | 2 +- libyul/optimiser/ConditionalUnsimplifier.cpp | 4 +- libyul/optimiser/DataFlowAnalyzer.cpp | 2 +- libyul/optimiser/DataFlowAnalyzer.h | 2 +- libyul/optimiser/ExpressionSimplifier.cpp | 4 +- libyul/optimiser/ForLoopConditionIntoBody.cpp | 2 +- .../optimiser/ForLoopConditionOutOfBody.cpp | 2 +- libyul/optimiser/KnowledgeBase.cpp | 4 +- libyul/optimiser/LoadResolver.cpp | 5 +- libyul/optimiser/Metrics.cpp | 8 +- libyul/optimiser/SSAValueTracker.h | 2 +- libyul/optimiser/SimplificationRules.cpp | 6 +- libyul/optimiser/StackLimitEvader.cpp | 4 +- libyul/optimiser/StackToMemoryMover.cpp | 34 ++-- libyul/optimiser/StackToMemoryMover.h | 6 +- libyul/optimiser/StructuralSimplifier.cpp | 6 +- libyul/optimiser/SyntacticalEquality.cpp | 12 +- libyul/optimiser/SyntacticalEquality.h | 3 + libyul/optimiser/UnusedStoreEliminator.cpp | 6 +- .../disambiguator/similar_literals.yul | 23 +++ .../string_as_hex_and_hex_as_string.yul | 13 ++ .../constant_representation.yul | 17 +- .../constant_representation_datasize.yul | 48 ++++++ .../yulSyntaxTests/switch_duplicate_case.yul | 2 +- ...witch_duplicate_case_different_literal.yul | 2 +- .../EVMInstructionInterpreter.cpp | 3 +- test/tools/yulInterpreter/Interpreter.cpp | 18 +-- 52 files changed, 535 insertions(+), 205 deletions(-) create mode 100644 libyul/AST.cpp create mode 100644 test/libyul/yulOptimizerTests/disambiguator/similar_literals.yul create mode 100644 test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul create mode 100644 test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 2f823fcbf..1c212cd82 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -203,7 +204,7 @@ struct CopyTranslate: public yul::ASTCopier solAssert(false); if (isDigit(value.front())) - return yul::Literal{_identifier.debugData, yul::LiteralKind::Number, yul::YulString{value}, {}}; + return yul::Literal{_identifier.debugData, yul::LiteralKind::Number, yul::valueOfNumberLiteral(value), {}}; else return yul::Identifier{_identifier.debugData, yul::YulString{value}}; } diff --git a/libsolutil/CommonData.cpp b/libsolutil/CommonData.cpp index 69f08308c..7b86bae9f 100644 --- a/libsolutil/CommonData.cpp +++ b/libsolutil/CommonData.cpp @@ -161,7 +161,7 @@ std::string solidity::util::getChecksummedAddress(std::string const& _addr) return ret; } -bool solidity::util::isValidHex(std::string const& _string) +bool solidity::util::isValidHex(std::string_view const _string) { if (_string.substr(0, 2) != "0x") return false; @@ -170,7 +170,7 @@ bool solidity::util::isValidHex(std::string const& _string) return true; } -bool solidity::util::isValidDecimal(std::string const& _string) +bool solidity::util::isValidDecimal(std::string_view const _string) { if (_string.empty()) return false; diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index 6e17e674d..c64b3913f 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -584,8 +584,8 @@ bool passesAddressChecksum(std::string const& _str, bool _strict); /// @param hex strings that look like an address std::string getChecksummedAddress(std::string const& _addr); -bool isValidHex(std::string const& _string); -bool isValidDecimal(std::string const& _string); +bool isValidHex(std::string_view _string); +bool isValidDecimal(std::string_view _string); /// @returns a quoted string if all characters are printable ASCII chars, /// or its hex representation otherwise. diff --git a/libyul/AST.cpp b/libyul/AST.cpp new file mode 100644 index 000000000..8c9f37641 --- /dev/null +++ b/libyul/AST.cpp @@ -0,0 +1,80 @@ +/* +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 + +#include +#include + +namespace solidity::yul +{ + +LiteralValue::LiteralValue(std::string _builtinStringLiteralValue): + m_numericValue(std::nullopt), + m_stringValue(std::make_shared(std::move(_builtinStringLiteralValue))) +{ } + +LiteralValue::LiteralValue(solidity::yul::LiteralValue::Data const& _data, std::optional const& _hint): + m_numericValue(_data), + m_stringValue(_hint ? std::make_shared(*_hint) : nullptr) +{ } + +LiteralValue::Data const& LiteralValue::value() const +{ + yulAssert(!unlimited()); + return *m_numericValue; +} + +LiteralValue::BuiltinStringLiteralData const& LiteralValue::builtinStringLiteralValue() const +{ + yulAssert(unlimited()); + return *m_stringValue; +} + +bool LiteralValue::unlimited() const +{ + return !m_numericValue.has_value(); +} + +LiteralValue::RepresentationHint const& LiteralValue::hint() const +{ + yulAssert(!unlimited()); + return m_stringValue; +} + +bool LiteralValue::operator==(LiteralValue const& _rhs) const +{ + if (unlimited() != _rhs.unlimited()) + return false; + + if (unlimited()) + return builtinStringLiteralValue() == _rhs.builtinStringLiteralValue(); + + return value() == _rhs.value(); +} + +bool LiteralValue::operator<(solidity::yul::LiteralValue const& _rhs) const +{ + if (unlimited() != _rhs.unlimited()) + return unlimited() < _rhs.unlimited(); + + if (unlimited()) + return builtinStringLiteralValue() < _rhs.builtinStringLiteralValue(); + + return value() < _rhs.value(); +} + +} diff --git a/libyul/AST.h b/libyul/AST.h index 4e3e92de3..ad60e4685 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -28,6 +28,8 @@ #include +#include + #include #include @@ -41,7 +43,32 @@ using TypedNameList = std::vector; /// Literal number or string (up to 32 bytes) enum class LiteralKind { Number, Boolean, String }; -struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; YulString value; Type type; }; +/// Literal value that holds a u256 word of data, can be of LiteralKind type and - in case of arguments to +/// builtins - exceed the u256 word (32 bytes), in which case the value is stored as string. The former is constructed +/// via u256 word and optional hint and leads to unlimited == false, the latter is +/// constructed via the string constructor and leads to unlimited == true. +class LiteralValue { +public: + using Data = u256; + using BuiltinStringLiteralData = std::string; + using RepresentationHint = std::shared_ptr; + + LiteralValue() = default; + explicit LiteralValue(std::string _builtinStringLiteralValue); + explicit LiteralValue(Data const& _data, std::optional const& _hint = std::nullopt); + + bool operator==(LiteralValue const& _rhs) const; + bool operator<(LiteralValue const& _rhs) const; + Data const& value() const; + BuiltinStringLiteralData const& builtinStringLiteralValue() const; + bool unlimited() const; + RepresentationHint const& hint() const; + +private: + std::optional m_numericValue; + std::shared_ptr m_stringValue; +}; +struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; LiteralValue value; Type type; }; /// External / internal identifier or label reference struct Identifier { langutil::DebugData::ConstPtr debugData; YulString name; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand diff --git a/libyul/ASTForward.h b/libyul/ASTForward.h index a4dc5be3f..12992edf8 100644 --- a/libyul/ASTForward.h +++ b/libyul/ASTForward.h @@ -29,6 +29,7 @@ namespace solidity::yul { enum class LiteralKind; +class LiteralValue; struct Literal; struct Label; struct Identifier; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index f85ef9544..ac97f988d 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -41,7 +41,6 @@ #include -#include #include using namespace std::string_literals; @@ -104,24 +103,32 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, std::vector AsmAnalyzer::operator()(Literal const& _literal) { expectValidType(_literal.type, nativeLocationOf(_literal)); - if (_literal.kind == LiteralKind::String && _literal.value.str().size() > 32) + bool erroneousLiteralValue = false; + if (_literal.kind == LiteralKind::String && !_literal.value.unlimited() && _literal.value.hint() && _literal.value.hint()->size() > 32) + { + erroneousLiteralValue = true; m_errorReporter.typeError( 3069_error, nativeLocationOf(_literal), - "String literal too long (" + std::to_string(_literal.value.str().size()) + " > 32)" + "String literal too long (" + std::to_string(formatLiteral(_literal, false /* _validated */ ).size()) + " > 32)" ); - else if (_literal.kind == LiteralKind::Number && bigint(_literal.value.str()) > u256(-1)) + } + else if (_literal.kind == LiteralKind::Number && _literal.value.hint() && bigint(*_literal.value.hint()) > u256(-1)) + { + erroneousLiteralValue = true; m_errorReporter.typeError(6708_error, nativeLocationOf(_literal), "Number literal too large (> 256 bits)"); - else if (_literal.kind == LiteralKind::Boolean) - yulAssert(_literal.value == "true"_yulstring || _literal.value == "false"_yulstring, ""); + } if (!m_dialect.validTypeForLiteral(_literal.kind, _literal.value, _literal.type)) + { m_errorReporter.typeError( 5170_error, nativeLocationOf(_literal), - "Invalid type \"" + _literal.type.str() + "\" for literal \"" + _literal.value.str() + "\"." + "Invalid type \"" + _literal.type.str() + "\" for literal \"" + formatLiteral(_literal) + "\"." ); + } + yulAssert(erroneousLiteralValue ^ validLiteral(_literal), "Invalid literal after validating it through AsmAnalyzer."); return {_literal.type}; } @@ -420,23 +427,25 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) std::string functionName = _funCall.functionName.name.str(); if (functionName == "datasize" || functionName == "dataoffset") { - if (!m_dataNames.count(std::get(arg).value)) + auto const& argumentAsLiteral = std::get(arg); + if (!m_dataNames.count(YulString(formatLiteral(argumentAsLiteral)))) m_errorReporter.typeError( 3517_error, nativeLocationOf(arg), - "Unknown data object \"" + std::get(arg).value.str() + "\"." + "Unknown data object \"" + formatLiteral(argumentAsLiteral) + "\"." ); } else if (functionName.substr(0, "verbatim_"s.size()) == "verbatim_") { - if (std::get(arg).value.empty()) + auto const& literalValue = std::get(arg).value; + yulAssert(literalValue.unlimited()); // verbatim literals are always unlimited + if (literalValue.builtinStringLiteralValue().empty()) m_errorReporter.typeError( 1844_error, nativeLocationOf(arg), "The \"verbatim_*\" builtins cannot be used with empty bytecode." ); } - argTypes.emplace_back(expectUnlimitedStringLiteral(std::get(arg))); continue; } @@ -495,12 +504,12 @@ void AsmAnalyzer::operator()(Switch const& _switch) (*this)(*_case.value); /// Note: the parser ensures there is only one default case - if (watcher.ok() && !cases.insert(valueOfLiteral(*_case.value)).second) + if (watcher.ok() && !cases.insert(_case.value->value.value()).second) m_errorReporter.declarationError( 6792_error, nativeLocationOf(_case), "Duplicate case \"" + - valueOfLiteral(*_case.value).str() + + formatLiteral(*_case.value) + "\" defined." ); } @@ -560,8 +569,9 @@ YulString AsmAnalyzer::expectExpression(Expression const& _expr) YulString AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal) { - yulAssert(_literal.kind == LiteralKind::String, ""); - yulAssert(m_dialect.validTypeForLiteral(LiteralKind::String, _literal.value, _literal.type), ""); + yulAssert(_literal.kind == LiteralKind::String); + yulAssert(m_dialect.validTypeForLiteral(LiteralKind::String, _literal.value, _literal.type)); + yulAssert(_literal.value.unlimited()); return {_literal.type}; } diff --git a/libyul/AsmJsonConverter.cpp b/libyul/AsmJsonConverter.cpp index a89e4967a..604754975 100644 --- a/libyul/AsmJsonConverter.cpp +++ b/libyul/AsmJsonConverter.cpp @@ -20,9 +20,10 @@ * Converts inline assembly AST to JSON format */ -#include #include +#include #include +#include #include #include @@ -47,14 +48,11 @@ Json AsmJsonConverter::operator()(TypedName const& _node) const Json AsmJsonConverter::operator()(Literal const& _node) const { + yulAssert(validLiteral(_node)); Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulLiteral"); switch (_node.kind) { case LiteralKind::Number: - yulAssert( - util::isValidDecimal(_node.value.str()) || util::isValidHex(_node.value.str()), - "Invalid number literal" - ); ret["kind"] = "number"; break; case LiteralKind::Boolean: @@ -62,12 +60,15 @@ Json AsmJsonConverter::operator()(Literal const& _node) const break; case LiteralKind::String: ret["kind"] = "string"; - ret["hexValue"] = util::toHex(util::asBytes(_node.value.str())); + ret["hexValue"] = util::toHex(util::asBytes(formatLiteral(_node))); break; } ret["type"] = _node.type.str(); - if (util::validateUTF8(_node.value.str())) - ret["value"] = _node.value.str(); + { + auto const formattedLiteral = formatLiteral(_node); + if (util::validateUTF8(formattedLiteral)) + ret["value"] = formattedLiteral; + } return ret; } diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index 41e065853..63b1d65d2 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -165,26 +166,25 @@ Literal AsmJsonImporter::createLiteral(Json const& _node) std::string kind = member(_node, "kind").get(); solAssert(member(_node, "hexValue").is_string() || member(_node, "value").is_string(), ""); + std::string value; if (_node.contains("hexValue")) - lit.value = YulString{util::asString(util::fromHex(member(_node, "hexValue").get()))}; + value = util::asString(util::fromHex(member(_node, "hexValue").get())); else - lit.value = YulString{member(_node, "value").get()}; - - lit.type= YulString{member(_node, "type").get()}; - + value = member(_node, "value").get(); + lit.type = YulString{member(_node, "type").get()}; if (kind == "number") { - langutil::CharStream charStream(lit.value.str(), ""); + langutil::CharStream charStream(value, ""); langutil::Scanner scanner{charStream}; lit.kind = LiteralKind::Number; yulAssert( scanner.currentToken() == Token::Number, - "Expected number but got " + langutil::TokenTraits::friendlyName(scanner.currentToken()) + std::string(" while scanning ") + lit.value.str() + "Expected number but got " + langutil::TokenTraits::friendlyName(scanner.currentToken()) + std::string(" while scanning ") + value ); } else if (kind == "bool") { - langutil::CharStream charStream(lit.value.str(), ""); + langutil::CharStream charStream(value, ""); langutil::Scanner scanner{charStream}; lit.kind = LiteralKind::Boolean; yulAssert( @@ -197,13 +197,17 @@ Literal AsmJsonImporter::createLiteral(Json const& _node) { lit.kind = LiteralKind::String; yulAssert( - lit.value.str().size() <= 32, - "String literal too long (" + std::to_string(lit.value.str().size()) + " > 32)" + value.size() <= 32, + "String literal too long (" + std::to_string(value.size()) + " > 32)" ); } else yulAssert(false, "unknown type of literal"); + // import only for inline assembly, no unlimited string literals there + lit.value = valueOfLiteral(value, lit.kind, false /* _unlimitedLiteralArgument */); + + yulAssert(validLiteral(lit)); return lit; } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index a009b005d..ecf3475a8 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -470,11 +471,11 @@ ForLoop Parser::parseForLoop() return forLoop; } -Expression Parser::parseExpression() +Expression Parser::parseExpression(bool _unlimitedLiteralArgument) { RecursionGuard recursionGuard(*this); - std::variant operation = parseLiteralOrIdentifier(); + std::variant operation = parseLiteralOrIdentifier(_unlimitedLiteralArgument); return visit(GenericVisitor{ [&](Identifier& _identifier) -> Expression { @@ -495,7 +496,7 @@ Expression Parser::parseExpression() }, operation); } -std::variant Parser::parseLiteralOrIdentifier() +std::variant Parser::parseLiteralOrIdentifier(bool _unlimitedLiteralArgument) { RecursionGuard recursionGuard(*this); switch (currentToken()) @@ -535,7 +536,7 @@ std::variant Parser::parseLiteralOrIdentifier() Literal literal{ createDebugData(), kind, - YulString{currentLiteral()}, + valueOfLiteral(currentLiteral(), kind, _unlimitedLiteralArgument && kind == LiteralKind::String), kind == LiteralKind::Boolean ? m_dialect.boolType : m_dialect.defaultType }; advance(); @@ -639,15 +640,20 @@ FunctionCall Parser::parseCall(std::variant&& _initialOp) FunctionCall ret; ret.functionName = std::move(std::get(_initialOp)); ret.debugData = ret.functionName.debugData; - + auto const isUnlimitedLiteralArgument = [f=m_dialect.builtin(ret.functionName.name)](size_t const index) { + if (f && index < f->literalArguments.size()) + return f->literalArgument(index).has_value(); + return false; + }; + size_t argumentIndex {0}; expectToken(Token::LParen); if (currentToken() != Token::RParen) { - ret.arguments.emplace_back(parseExpression()); + ret.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); while (currentToken() != Token::RParen) { expectToken(Token::Comma); - ret.arguments.emplace_back(parseExpression()); + ret.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); } } updateLocationEndFrom(ret.debugData, currentLocation()); diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index dd91e436e..334890409 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -138,10 +138,10 @@ class Parser: public langutil::ParserBase Case parseCase(); ForLoop parseForLoop(); /// Parses a functional expression that has to push exactly one stack element - Expression parseExpression(); + Expression parseExpression(bool _unlimitedLiteralArgument = false); /// Parses an elementary operation, i.e. a literal, identifier, instruction or /// builtin function call (only the name). - std::variant parseLiteralOrIdentifier(); + std::variant parseLiteralOrIdentifier(bool _unlimitedLiteralArgument = false); VariableDeclaration parseVariableDeclaration(); FunctionDefinition parseFunctionDefinition(); FunctionCall parseCall(std::variant&& _initialOp); diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index b27af0371..191fc5d2d 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -34,8 +35,8 @@ #include -#include #include +#include using namespace solidity; using namespace solidity::langutil; @@ -44,21 +45,22 @@ using namespace solidity::yul; std::string AsmPrinter::operator()(Literal const& _literal) { + yulAssert(validLiteral(_literal)); + std::string const locationComment = formatDebugData(_literal); + std::string const formattedValue = formatLiteral(_literal); switch (_literal.kind) { case LiteralKind::Number: - yulAssert(isValidDecimal(_literal.value.str()) || isValidHex(_literal.value.str()), "Invalid number literal"); - return locationComment + _literal.value.str() + appendTypeName(_literal.type); + return locationComment + formattedValue + appendTypeName(_literal.type); case LiteralKind::Boolean: - yulAssert(_literal.value == "true"_yulstring || _literal.value == "false"_yulstring, "Invalid bool literal."); - return locationComment + ((_literal.value == "true"_yulstring) ? "true" : "false") + appendTypeName(_literal.type, true); + return locationComment + formattedValue + appendTypeName(_literal.type, true); case LiteralKind::String: break; } - return locationComment + escapeAndQuoteString(_literal.value.str()) + appendTypeName(_literal.type); + return locationComment + escapeAndQuoteString(formattedValue) + appendTypeName(_literal.type); } std::string AsmPrinter::operator()(Identifier const& _identifier) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 811a6239b..92b03facf 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -5,6 +5,7 @@ add_library(yul AsmAnalysis.h AsmAnalysisInfo.h AST.h + AST.cpp ASTForward.h AsmJsonConverter.h AsmJsonConverter.cpp diff --git a/libyul/Dialect.cpp b/libyul/Dialect.cpp index 8440698f1..69ca1e9dc 100644 --- a/libyul/Dialect.cpp +++ b/libyul/Dialect.cpp @@ -28,20 +28,20 @@ using namespace solidity::langutil; Literal Dialect::zeroLiteralForType(solidity::yul::YulString _type) const { if (_type == boolType && _type != defaultType) - return {DebugData::create(), LiteralKind::Boolean, "false"_yulstring, _type}; - return {DebugData::create(), LiteralKind::Number, "0"_yulstring, _type}; + return {DebugData::create(), LiteralKind::Boolean, LiteralValue(false), _type}; + return {DebugData::create(), LiteralKind::Number, LiteralValue(0, std::nullopt), _type}; } Literal Dialect::trueLiteral() const { if (boolType != defaultType) - return {DebugData::create(), LiteralKind::Boolean, "true"_yulstring, boolType}; + return {DebugData::create(), LiteralKind::Boolean, LiteralValue(true), boolType}; else - return {DebugData::create(), LiteralKind::Number, "1"_yulstring, defaultType}; + return {DebugData::create(), LiteralKind::Number, LiteralValue(1), defaultType}; } -bool Dialect::validTypeForLiteral(LiteralKind _kind, YulString, YulString _type) const +bool Dialect::validTypeForLiteral(LiteralKind _kind, LiteralValue const&, YulString _type) const { if (_kind == LiteralKind::Boolean) return _type == boolType; diff --git a/libyul/Dialect.h b/libyul/Dialect.h index e7a5e4827..e3f270357 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -35,6 +35,7 @@ namespace solidity::yul class YulString; using Type = YulString; enum class LiteralKind; +class LiteralValue; struct Literal; struct BuiltinFunction @@ -85,7 +86,7 @@ struct Dialect /// Check whether the given type is legal for the given literal value. /// Should only be called if the type exists in the dialect at all. - virtual bool validTypeForLiteral(LiteralKind _kind, YulString _value, YulString _type) const; + virtual bool validTypeForLiteral(LiteralKind _kind, LiteralValue const& _value, YulString _type) const; virtual Literal zeroLiteralForType(YulString _type) const; virtual Literal trueLiteral() const; diff --git a/libyul/Utilities.cpp b/libyul/Utilities.cpp index 8242553d3..6a78441cb 100644 --- a/libyul/Utilities.cpp +++ b/libyul/Utilities.cpp @@ -86,56 +86,134 @@ std::string solidity::yul::reindent(std::string const& _code) return out.str(); } -u256 solidity::yul::valueOfNumberLiteral(Literal const& _literal) +LiteralValue solidity::yul::valueOfNumberLiteral(std::string_view const _literal) { - yulAssert(_literal.kind == LiteralKind::Number, "Expected number literal!"); + return LiteralValue{LiteralValue::Data(_literal), std::string(_literal)}; +} + +LiteralValue solidity::yul::valueOfStringLiteral(std::string_view const _literal) +{ + std::string const s(_literal); + return LiteralValue{u256(h256(s, h256::FromBinary, h256::AlignLeft)), s}; +} + +LiteralValue solidity::yul::valueOfBuiltinStringLiteralArgument(std::string_view _literal) +{ + return LiteralValue{std::string(_literal)}; +} - static std::map numberCache; - static YulStringRepository::ResetCallback callback{[&] { numberCache.clear(); }}; +LiteralValue solidity::yul::valueOfBoolLiteral(std::string_view const _literal) +{ + if (_literal == "true") + return LiteralValue{true}; + else if (_literal == "false") + return LiteralValue{false}; + + yulAssert(false, "Unexpected bool literal value!"); +} - auto&& [it, isNew] = numberCache.try_emplace(_literal.value, 0); - if (isNew) +LiteralValue solidity::yul::valueOfLiteral(std::string_view const _literal, LiteralKind const& _kind, bool const _unlimitedLiteralArgument) +{ + switch (_kind) { - std::string const& literalString = _literal.value.str(); - yulAssert(isValidDecimal(literalString) || isValidHex(literalString), "Invalid number literal!"); - it->second = u256(literalString); + case LiteralKind::Number: + return valueOfNumberLiteral(_literal); + case LiteralKind::Boolean: + return valueOfBoolLiteral(_literal); + case LiteralKind::String: + return _unlimitedLiteralArgument ? valueOfBuiltinStringLiteralArgument(_literal) : valueOfStringLiteral(_literal); } - return it->second; + util::unreachable(); } -u256 solidity::yul::valueOfStringLiteral(Literal const& _literal) +std::string solidity::yul::formatLiteral(solidity::yul::Literal const& _literal, bool const _validated) { - yulAssert(_literal.kind == LiteralKind::String, "Expected string literal!"); - yulAssert(_literal.value.str().size() <= 32, "Literal string too long!"); + if (_validated) + yulAssert(validLiteral(_literal), "Encountered invalid literal in formatLiteral."); + + if (_literal.value.unlimited()) + return _literal.value.builtinStringLiteralValue(); + + if (_literal.value.hint()) + return *_literal.value.hint(); + + if (_literal.kind == LiteralKind::Boolean) + return _literal.value.value() == false ? "false" : "true"; - return u256(h256(_literal.value.str(), h256::FromBinary, h256::AlignLeft)); + // if there is no hint and it is not a boolean, just stringify the u256 word + return _literal.value.value().str(); } -u256 yul::valueOfBoolLiteral(Literal const& _literal) +bool solidity::yul::validLiteral(solidity::yul::Literal const& _literal) { - yulAssert(_literal.kind == LiteralKind::Boolean, "Expected bool literal!"); + switch (_literal.kind) + { + case LiteralKind::Number: + return validNumberLiteral(_literal); + case LiteralKind::Boolean: + return validBoolLiteral(_literal); + case LiteralKind::String: + return validStringLiteral(_literal); + } + util::unreachable(); +} - if (_literal.value == "true"_yulstring) - return u256(1); - else if (_literal.value == "false"_yulstring) - return u256(0); +bool solidity::yul::validStringLiteral(solidity::yul::Literal const& _literal) +{ + if (_literal.kind != LiteralKind::String) + return false; - yulAssert(false, "Unexpected bool literal value!"); + if (_literal.value.unlimited()) + return true; + + if (_literal.value.hint()) + return _literal.value.hint()->size() <= 32 && _literal.value.value() == valueOfLiteral(*_literal.value.hint(), _literal.kind).value(); + + return true; } -u256 solidity::yul::valueOfLiteral(Literal const& _literal) +bool solidity::yul::validNumberLiteral(solidity::yul::Literal const& _literal) { - switch (_literal.kind) + if (_literal.kind != LiteralKind::Number || _literal.value.unlimited()) + return false; + + if (!_literal.value.hint()) + return true; + + auto const& repr = *_literal.value.hint(); + + if (!isValidDecimal(repr) && !isValidHex(repr)) + return false; + + if (bigint(repr) > u256(-1)) + return false; + + if (_literal.value.value() != valueOfLiteral(repr, _literal.kind).value()) + return false; + + return true; +} + +bool solidity::yul::validBoolLiteral(solidity::yul::Literal const& _literal) +{ + if (_literal.kind != LiteralKind::Boolean || _literal.value.unlimited()) + return false; + + if (_literal.value.hint() && !(*_literal.value.hint() == "true" || *_literal.value.hint() == "false")) + return false; + + yulAssert(u256(0) == u256(false)); + yulAssert(u256(1) == u256(true)); + + if (_literal.value.hint()) { - case LiteralKind::Number: - return valueOfNumberLiteral(_literal); - case LiteralKind::Boolean: - return valueOfBoolLiteral(_literal); - case LiteralKind::String: - return valueOfStringLiteral(_literal); - default: - yulAssert(false, "Unexpected literal kind!"); + if (*_literal.value.hint() == "false") + return _literal.value.value() == false; + else + return _literal.value.value() == true; } + + return _literal.value.value() == true || _literal.value.value() == false; } template<> @@ -144,10 +222,14 @@ bool Less::operator()(Literal const& _lhs, Literal const& _rhs) const if (std::make_tuple(_lhs.kind, _lhs.type) != std::make_tuple(_rhs.kind, _rhs.type)) return std::make_tuple(_lhs.kind, _lhs.type) < std::make_tuple(_rhs.kind, _rhs.type); - if (_lhs.kind == LiteralKind::Number) - return valueOfNumberLiteral(_lhs) < valueOfNumberLiteral(_rhs); - else - return _lhs.value < _rhs.value; + if (_lhs.value.unlimited() && _rhs.value.unlimited()) + yulAssert( + _lhs.kind == LiteralKind::String && _rhs.kind == LiteralKind::String, + "Cannot have unlimited value that is not of String kind." + ); + + return _lhs.value < _rhs.value; + } bool SwitchCaseCompareByLiteralValue::operator()(Case const* _lhs, Case const* _rhs) const diff --git a/libyul/Utilities.h b/libyul/Utilities.h index e4d496cd4..434c5e9c5 100644 --- a/libyul/Utilities.h +++ b/libyul/Utilities.h @@ -25,15 +25,28 @@ #include #include +#include + namespace solidity::yul { std::string reindent(std::string const& _code); -u256 valueOfNumberLiteral(Literal const& _literal); -u256 valueOfStringLiteral(Literal const& _literal); -u256 valueOfBoolLiteral(Literal const& _literal); -u256 valueOfLiteral(Literal const& _literal); +LiteralValue valueOfNumberLiteral(std::string_view _literal); +LiteralValue valueOfStringLiteral(std::string_view _literal); +LiteralValue valueOfBuiltinStringLiteralArgument(std::string_view _literal); +LiteralValue valueOfBoolLiteral(std::string_view _literal); +LiteralValue valueOfLiteral(std::string_view _literal, LiteralKind const& _kind, bool _unlimitedLiteralArgument = false); +bool validLiteral(Literal const& _literal); +bool validStringLiteral(Literal const& _literal); +bool validNumberLiteral(Literal const& _literal); +bool validBoolLiteral(Literal const& _literal); + +/// Produces a string representation of a Literal instance. +/// @param _literal the Literal to be formatted +/// @param _validated whether the Literal was already validated, i.e., assumptions are asserted in the method +/// @returns the literal's string representation +std::string formatLiteral(Literal const& _literal, bool _validated = true); /** * Linear order on Yul AST nodes. diff --git a/libyul/backends/evm/ConstantOptimiser.cpp b/libyul/backends/evm/ConstantOptimiser.cpp index c5a33e52f..7b17f7d89 100644 --- a/libyul/backends/evm/ConstantOptimiser.cpp +++ b/libyul/backends/evm/ConstantOptimiser.cpp @@ -81,7 +81,7 @@ struct MiniEVMInterpreter } u256 operator()(Literal const& _literal) { - return valueOfLiteral(_literal); + return _literal.value.value(); } u256 operator()(Identifier const&) { yulAssert(false, ""); } @@ -100,7 +100,7 @@ void ConstantOptimiser::visit(Expression& _e) if ( Expression const* repr = RepresentationFinder(m_dialect, m_meter, debugDataOf(_e), m_cache) - .tryFindRepresentation(valueOfLiteral(literal)) + .tryFindRepresentation(literal.value.value()) ) _e = ASTCopier{}.translate(*repr); } @@ -179,7 +179,7 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu Representation RepresentationFinder::represent(u256 const& _value) const { Representation repr; - repr.expression = std::make_unique(Literal{m_debugData, LiteralKind::Number, YulString{formatNumber(_value)}, {}}); + repr.expression = std::make_unique(Literal{m_debugData, LiteralKind::Number, LiteralValue{_value, formatNumber(_value)}, {}}); repr.cost = m_meter.costs(*repr.expression); return repr; } diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index f048e5717..a5e9613b5 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -245,7 +245,7 @@ ControlFlowGraphBuilder::ControlFlowGraphBuilder( StackSlot ControlFlowGraphBuilder::operator()(Literal const& _literal) { - return LiteralSlot{valueOfLiteral(_literal), _literal.debugData}; + return LiteralSlot{_literal.value.value(), _literal.debugData}; } StackSlot ControlFlowGraphBuilder::operator()(Identifier const& _identifier) @@ -361,7 +361,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) {*_case.value, Identifier{{}, ghostVariableName}} }); CFG::Operation& operation = m_currentBlock->operations.emplace_back(CFG::Operation{ - Stack{ghostVarSlot, LiteralSlot{valueOfLiteral(*_case.value), debugDataOf(*_case.value)}}, + Stack{ghostVarSlot, LiteralSlot{_case.value->value.value(), debugDataOf(*_case.value)}}, Stack{TemporarySlot{ghostCall, 0}}, CFG::BuiltinCall{debugDataOf(_case), *equalityBuiltin, ghostCall, 2}, }); @@ -399,7 +399,7 @@ void ControlFlowGraphBuilder::operator()(ForLoop const& _loop) std::optional constantCondition; if (auto const* literalCondition = std::get_if(_loop.condition.get())) - constantCondition = valueOfLiteral(*literalCondition) != 0; + constantCondition = literalCondition->value.value() != 0; CFG::BasicBlock& loopCondition = m_graph.makeBlock(debugDataOf(*_loop.condition)); CFG::BasicBlock& loopBody = m_graph.makeBlock(debugDataOf(_loop.body)); diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 50e48f768..bdce395ef 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -297,7 +297,7 @@ void CodeTransform::operator()(Identifier const& _identifier) void CodeTransform::operator()(Literal const& _literal) { m_assembly.setSourceLocation(originLocationOf(_literal)); - m_assembly.appendConstant(valueOfLiteral(_literal)); + m_assembly.appendConstant(_literal.value.value()); } void CodeTransform::operator()(If const& _if) diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 6a3b34f97..856689c91 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -219,7 +219,7 @@ std::map createBuiltins(langutil::EVMVersion _ ) { yulAssert(_call.arguments.size() == 1, ""); Expression const& arg = _call.arguments.front(); - _assembly.appendLinkerSymbol(std::get(arg).value.str()); + _assembly.appendLinkerSymbol(formatLiteral(std::get(arg))); })); builtins.emplace(createFunction( @@ -236,7 +236,7 @@ std::map createBuiltins(langutil::EVMVersion _ yulAssert(_call.arguments.size() == 1, ""); Literal const* literal = std::get_if(&_call.arguments.front()); yulAssert(literal, ""); - _assembly.appendConstant(valueOfLiteral(*literal)); + _assembly.appendConstant(literal->value.value()); }) ); @@ -248,7 +248,7 @@ std::map createBuiltins(langutil::EVMVersion _ yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); Expression const& arg = _call.arguments.front(); - YulString dataName = std::get(arg).value; + YulString const dataName (formatLiteral(std::get(arg))); if (_context.currentObject->name == dataName) _assembly.appendAssemblySize(); else @@ -269,7 +269,7 @@ std::map createBuiltins(langutil::EVMVersion _ yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); Expression const& arg = _call.arguments.front(); - YulString dataName = std::get(arg).value; + YulString const dataName (formatLiteral(std::get(arg))); if (_context.currentObject->name == dataName) _assembly.appendConstant(0); else @@ -328,8 +328,8 @@ std::map createBuiltins(langutil::EVMVersion _ BuiltinContext& ) { yulAssert(_call.arguments.size() == 3, ""); - YulString identifier = std::get(_call.arguments[1]).value; - _assembly.appendImmutableAssignment(identifier.str()); + auto const identifier = (formatLiteral(std::get(_call.arguments[1]))); + _assembly.appendImmutableAssignment(identifier); } )); builtins.emplace(createFunction( @@ -344,7 +344,7 @@ std::map createBuiltins(langutil::EVMVersion _ BuiltinContext& ) { yulAssert(_call.arguments.size() == 1, ""); - _assembly.appendImmutable(std::get(_call.arguments.front()).value.str()); + _assembly.appendImmutable(formatLiteral(std::get(_call.arguments.front()))); } )); } @@ -450,7 +450,7 @@ BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, siz Expression const& bytecode = _call.arguments.front(); _assembly.appendVerbatim( - asBytes(std::get(bytecode).value.str()), + asBytes(formatLiteral(std::get(bytecode))), _arguments, _returnVariables ); diff --git a/libyul/backends/evm/EVMMetrics.cpp b/libyul/backends/evm/EVMMetrics.cpp index 09c6abdd1..84ebdab1d 100644 --- a/libyul/backends/evm/EVMMetrics.cpp +++ b/libyul/backends/evm/EVMMetrics.cpp @@ -91,7 +91,7 @@ void GasMeterVisitor::operator()(Literal const& _lit) m_dataGas += singleByteDataGas() + evmasm::GasMeter::dataGas( - toCompactBigEndian(valueOfLiteral(_lit), 1), + toCompactBigEndian(_lit.value.value(), 1), m_isCreation, m_dialect.evmVersion() ); diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index a3052a542..047014e3d 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -224,7 +224,7 @@ void OptimizedEVMCodeTransform::validateSlot(StackSlot const& _slot, Expression std::visit(util::GenericVisitor{ [&](yul::Literal const& _literal) { auto* literalSlot = std::get_if(&_slot); - yulAssert(literalSlot && valueOfLiteral(_literal) == literalSlot->value, ""); + yulAssert(literalSlot && _literal.value.value() == literalSlot->value, ""); }, [&](yul::Identifier const& _identifier) { auto* variableSlot = std::get_if(&_slot); diff --git a/libyul/optimiser/BlockHasher.cpp b/libyul/optimiser/BlockHasher.cpp index 380cc15fb..d5febca93 100644 --- a/libyul/optimiser/BlockHasher.cpp +++ b/libyul/optimiser/BlockHasher.cpp @@ -41,6 +41,18 @@ static constexpr uint64_t compileTimeLiteralHash(char const (&_literal)[N]) } } +void ASTHasherBase::hashLiteral(solidity::yul::Literal const& _literal) +{ + hash64(compileTimeLiteralHash("Literal")); + if (!_literal.value.unlimited()) + hash64(std::hash{}(_literal.value.value())); + else + hash64(std::hash{}(_literal.value.builtinStringLiteralValue())); + hash64(_literal.type.hash()); + hash8(static_cast(_literal.kind)); + hash8(_literal.value.unlimited()); +} + std::map BlockHasher::run(Block const& _block) { std::map result; @@ -51,13 +63,7 @@ std::map BlockHasher::run(Block const& _block) void BlockHasher::operator()(Literal const& _literal) { - hash64(compileTimeLiteralHash("Literal")); - if (_literal.kind == LiteralKind::Number) - hash64(std::hash{}(valueOfNumberLiteral(_literal))); - else - hash64(_literal.value.hash()); - hash64(_literal.type.hash()); - hash8(static_cast(_literal.kind)); + hashLiteral(_literal); } void BlockHasher::operator()(Identifier const& _identifier) @@ -203,13 +209,7 @@ uint64_t ExpressionHasher::run(Expression const& _e) void ExpressionHasher::operator()(Literal const& _literal) { - hash64(compileTimeLiteralHash("Literal")); - if (_literal.kind == LiteralKind::Number) - hash64(std::hash{}(valueOfNumberLiteral(_literal))); - else - hash64(_literal.value.hash()); - hash64(_literal.type.hash()); - hash8(static_cast(_literal.kind)); + hashLiteral(_literal); } void ExpressionHasher::operator()(Identifier const& _identifier) diff --git a/libyul/optimiser/BlockHasher.h b/libyul/optimiser/BlockHasher.h index 6dc55371c..2b9a71f10 100644 --- a/libyul/optimiser/BlockHasher.h +++ b/libyul/optimiser/BlockHasher.h @@ -55,10 +55,15 @@ class HasherBase hash32(static_cast(_value >> 32)); } - uint64_t m_hash = fnvEmptyHash; }; +class ASTHasherBase: public HasherBase +{ +protected: + void hashLiteral(solidity::yul::Literal const& _literal); +}; + /** * Optimiser component that calculates hash values for blocks. * Syntactically equal blocks will have identical hashes and @@ -73,7 +78,7 @@ class HasherBase * * Prerequisite: Disambiguator, ForLoopInitRewriter */ -class BlockHasher: public ASTWalker, public HasherBase +class BlockHasher: public ASTWalker, public ASTHasherBase { public: @@ -120,7 +125,7 @@ class BlockHasher: public ASTWalker, public HasherBase * have a different name and the same if the name matches. * This means this hasher should only be used on disambiguated sources. */ -class ExpressionHasher: public ASTWalker, public HasherBase +class ExpressionHasher: public ASTWalker, public ASTHasherBase { public: /// Computes a hash of an expression that (in contrast to the behaviour of the class) diff --git a/libyul/optimiser/CommonSubexpressionEliminator.cpp b/libyul/optimiser/CommonSubexpressionEliminator.cpp index ae55f75e9..1c7879056 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.cpp +++ b/libyul/optimiser/CommonSubexpressionEliminator.cpp @@ -114,7 +114,7 @@ void CommonSubexpressionEliminator::visit(Expression& _e) if ( m_returnVariables.count(variable) && std::holds_alternative(*value->value) && - valueOfLiteral(std::get(*value->value)) == 0 + std::get(*value->value).value.value() == 0 ) continue; // We check for syntactic equality again because the value might have changed. diff --git a/libyul/optimiser/ConditionalUnsimplifier.cpp b/libyul/optimiser/ConditionalUnsimplifier.cpp index 2af09af04..104ec1e4f 100644 --- a/libyul/optimiser/ConditionalUnsimplifier.cpp +++ b/libyul/optimiser/ConditionalUnsimplifier.cpp @@ -59,7 +59,7 @@ void ConditionalUnsimplifier::operator()(Switch& _switch) assignment.variableNames.size() == 1 && assignment.variableNames.front().name == expr && std::holds_alternative(*assignment.value) && - valueOfLiteral(std::get(*assignment.value)) == valueOfLiteral(*_case.value) + std::get(*assignment.value).value == _case.value->value ) _case.body.statements.erase(_case.body.statements.begin()); } @@ -95,7 +95,7 @@ void ConditionalUnsimplifier::operator()(Block& _block) assignment.variableNames.size() == 1 && assignment.variableNames.front().name == condition && std::holds_alternative(*assignment.value) && - valueOfLiteral(std::get(*assignment.value)) == 0 + std::get(*assignment.value).value.value() == 0 ) return {make_vector(std::move(_stmt1))}; } diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 5992c9b98..5ec3cf248 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -414,7 +414,7 @@ std::optional DataFlowAnalyzer::valueOfIdentifier(YulString const& _name) { if (AssignedValue const* value = variableValue(_name)) if (Literal const* literal = std::get_if(value->value)) - return valueOfLiteral(*literal); + return literal->value.value(); return std::nullopt; } diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index b449357e6..e41620b15 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -217,7 +217,7 @@ class DataFlowAnalyzer: public ASTModifier }; /// Special expression whose address will be used in m_value. /// YulString does not need to be reset because DataFlowAnalyzer is short-lived. - Expression const m_zero{Literal{{}, LiteralKind::Number, YulString{"0"}, {}}}; + Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue{0, "0"}, {}}}; /// List of scopes. std::vector m_variableScopes; }; diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index c87c5df23..6d0a8c9d7 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -60,14 +60,14 @@ void ExpressionSimplifier::visit(Expression& _expression) !knownToBeZero(startArgument) && !std::holds_alternative(startArgument) ) - startArgument = Literal{debugDataOf(startArgument), LiteralKind::Number, "0"_yulstring, {}}; + startArgument = Literal{debugDataOf(startArgument), LiteralKind::Number, LiteralValue{0, "0"}, {}}; } } bool ExpressionSimplifier::knownToBeZero(Expression const& _expression) const { if (auto const* literal = std::get_if(&_expression)) - return valueOfLiteral(*literal) == 0; + return literal->value.value() == 0; else if (auto const* identifier = std::get_if(&_expression)) return valueOfIdentifier(identifier->name) == 0; else diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index 33d8496f0..df9847376 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -58,7 +58,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) Literal { debugData, LiteralKind::Boolean, - "true"_yulstring, + LiteralValue{true}, m_dialect.boolType } ); diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.cpp b/libyul/optimiser/ForLoopConditionOutOfBody.cpp index e2451bc6c..83b1e20a8 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.cpp +++ b/libyul/optimiser/ForLoopConditionOutOfBody.cpp @@ -38,7 +38,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) if ( !m_dialect.booleanNegationFunction() || !std::holds_alternative(*_forLoop.condition) || - valueOfLiteral(std::get(*_forLoop.condition)) == u256(0) || + std::get(*_forLoop.condition).value.value() == 0 || _forLoop.body.statements.empty() || !std::holds_alternative(_forLoop.body.statements.front()) ) diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index c280ecf14..79eb2b317 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -78,7 +78,7 @@ std::optional KnowledgeBase::valueIfKnownConstant(Expression const& _expre if (Identifier const* ident = std::get_if(&_expression)) return valueIfKnownConstant(ident->name); else if (Literal const* lit = std::get_if(&_expression)) - return valueOfLiteral(*lit); + return lit->value.value(); else return std::nullopt; } @@ -113,7 +113,7 @@ KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var) std::optional KnowledgeBase::explore(Expression const& _value) { if (Literal const* literal = std::get_if(&_value)) - return VariableOffset{YulString{}, valueOfLiteral(*literal)}; + return VariableOffset{YulString{}, literal->value.value()}; else if (Identifier const* identifier = std::get_if(&_value)) return explore(identifier->name); else if (FunctionCall const* f = std::get_if(&_value)) diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index 84094c33e..170eefc90 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -125,7 +125,7 @@ void LoadResolver::tryEvaluateKeccak( {}, LiteralKind::Number, // a dummy 256-bit number to represent the Keccak256 hash. - YulString{std::numeric_limits::max().str()}, + LiteralValue{std::numeric_limits::max()}, {} } ); @@ -146,10 +146,11 @@ void LoadResolver::tryEvaluateKeccak( { bytes contentAsBytes = toBigEndian(*memoryContent); contentAsBytes.resize(static_cast(*byteLength)); + u256 const contentHash (keccak256(contentAsBytes)); _e = Literal{ debugDataOf(_e), LiteralKind::Number, - YulString{u256(keccak256(contentAsBytes)).str()}, + LiteralValue{contentHash}, m_dialect.defaultType }; } diff --git a/libyul/optimiser/Metrics.cpp b/libyul/optimiser/Metrics.cpp index 42845f3b6..2f1dee93e 100644 --- a/libyul/optimiser/Metrics.cpp +++ b/libyul/optimiser/Metrics.cpp @@ -71,7 +71,7 @@ size_t CodeWeights::costOf(Expression const& _expression) const else if (Literal const* literal = std::get_if(&_expression)) { // Avoid strings because they could be longer than 32 bytes. - if (literal->kind != LiteralKind::String && valueOfLiteral(*literal) == 0) + if (literal->kind != LiteralKind::String && literal->value.value() == 0) return literalZeroCost; else return literalCost; @@ -155,15 +155,15 @@ void CodeCost::operator()(Literal const& _literal) case LiteralKind::Boolean: break; case LiteralKind::Number: - for (u256 n = u256(_literal.value.str()); n >= 0x100; n >>= 8) + for (u256 n = _literal.value.value(); n >= 0x100; n >>= 8) cost++; - if (valueOfLiteral(_literal) == 0) + if (_literal.value.value() == 0) if (auto evmDialect = dynamic_cast(&m_dialect)) if (evmDialect->evmVersion().hasPush0()) --m_cost; break; case LiteralKind::String: - cost = _literal.value.str().size(); + cost = formatLiteral(_literal).size(); break; } diff --git a/libyul/optimiser/SSAValueTracker.h b/libyul/optimiser/SSAValueTracker.h index f1c93ff22..5a7eee512 100644 --- a/libyul/optimiser/SSAValueTracker.h +++ b/libyul/optimiser/SSAValueTracker.h @@ -57,7 +57,7 @@ class SSAValueTracker: public ASTWalker /// Special expression whose address will be used in m_values. /// YulString does not need to be reset because SSAValueTracker is short-lived. - Expression const m_zero{Literal{{}, LiteralKind::Number, YulString{"0"}, {}}}; + Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue(u256{0}), {}}}; std::map m_values; }; diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index 7fe56026a..e2d468329 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -160,7 +160,7 @@ bool Pattern::matches( Literal const& literal = std::get(*expr); if (literal.kind != LiteralKind::Number) return false; - if (m_data && *m_data != u256(literal.value.str())) + if (m_data && *m_data != literal.value.value()) return false; assertThrow(m_arguments.empty(), OptimizerException, ""); } @@ -241,7 +241,7 @@ Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData if (m_kind == PatternKind::Constant) { assertThrow(m_data, OptimizerException, "No match group and no constant value given."); - return Literal{_debugData, LiteralKind::Number, YulString{formatNumber(*m_data)}, {}}; + return Literal{_debugData, LiteralKind::Number, LiteralValue{*m_data, formatNumber(*m_data)}, {}}; } else if (m_kind == PatternKind::Operation) { @@ -261,7 +261,7 @@ Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData u256 Pattern::d() const { - return valueOfNumberLiteral(std::get(matchGroupValue())); + return std::get(matchGroupValue()).value.value(); } Expression const& Pattern::matchGroupValue() const diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 5d7f7fe5d..904ee77e0 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -113,7 +113,7 @@ u256 literalArgumentValue(FunctionCall const& _call) yulAssert(_call.arguments.size() == 1, ""); Literal const* literal = std::get_if(&_call.arguments.front()); yulAssert(literal && literal->kind == LiteralKind::Number, ""); - return valueOfLiteral(*literal); + return literal->value.value(); } } @@ -210,6 +210,6 @@ void StackLimitEvader::run( { Literal* literal = std::get_if(&memoryGuardCall->arguments.front()); yulAssert(literal && literal->kind == LiteralKind::Number, ""); - literal->value = YulString{toCompactHexWithPrefix(reservedMemory)}; + literal->value = LiteralValue{reservedMemory, toCompactHexWithPrefix(reservedMemory)}; } } diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index dedb5cd38..dbf3183fb 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -20,6 +20,7 @@ #include #include +#include #include @@ -37,7 +38,7 @@ namespace std::vector generateMemoryStore( Dialect const& _dialect, langutil::DebugData::ConstPtr const& _debugData, - YulString _mpos, + LiteralValue const& _mpos, Expression _value ) { @@ -55,7 +56,7 @@ std::vector generateMemoryStore( return result; } -FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::ConstPtr const& _debugData, YulString _mpos) +FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::ConstPtr const& _debugData, LiteralValue const& _mpos) { BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(_dialect.defaultType); yulAssert(memoryLoadFunction, ""); @@ -139,7 +140,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) m_context.dialect, returnVariable.debugData, *slot, - Literal{returnVariable.debugData, LiteralKind::Number, "0"_yulstring, {}} + Literal{returnVariable.debugData, LiteralKind::Number, LiteralValue(u256{0}), {}} ); // Special case of a function with a single return argument that needs to move to memory. @@ -208,36 +209,36 @@ void StackToMemoryMover::operator()(Block& _block) auto debugData = _stmt.debugData; if (_lhsVars.size() == 1) { - if (std::optional offset = m_memoryOffsetTracker(_lhsVars.front().name)) + if (auto offset = m_memoryOffsetTracker(_lhsVars.front().name)) return generateMemoryStore( m_context.dialect, debugData, *offset, - _stmt.value ? *std::move(_stmt.value) : Literal{debugData, LiteralKind::Number, "0"_yulstring, {}} + _stmt.value ? *std::move(_stmt.value) : Literal{debugData, LiteralKind::Number, LiteralValue(u256{0}), {}} ); else return {}; } - std::vector> rhsMemorySlots; + std::vector> rhsMemorySlots; if (_stmt.value) { FunctionCall const* functionCall = std::get_if(_stmt.value.get()); yulAssert(functionCall, ""); if (m_context.dialect.builtin(functionCall->functionName.name)) - rhsMemorySlots = std::vector>(_lhsVars.size(), std::nullopt); + rhsMemorySlots = std::vector>(_lhsVars.size(), std::nullopt); else rhsMemorySlots = m_functionReturnVariables.at(functionCall->functionName.name) | ranges::views::transform(m_memoryOffsetTracker) | - ranges::to>>; + ranges::to>>; } else - rhsMemorySlots = std::vector>(_lhsVars.size(), std::nullopt); + rhsMemorySlots = std::vector>(_lhsVars.size(), std::nullopt); // Nothing to do, if the right-hand-side remains entirely on the stack and // none of the variables in the left-hand-side are moved. if ( - ranges::none_of(rhsMemorySlots, [](std::optional const& _slot) { return _slot.has_value(); }) && + ranges::none_of(rhsMemorySlots, [](std::optional const& _slot) { return _slot.has_value(); }) && !util::contains_if(_lhsVars, m_memoryOffsetTracker) ) return {}; @@ -259,7 +260,7 @@ void StackToMemoryMover::operator()(Block& _block) rhs = std::make_unique(Identifier{debugData, tempVarName}); } - if (std::optional offset = m_memoryOffsetTracker(lhsVar.name)) + if (auto offset = m_memoryOffsetTracker(lhsVar.name)) memoryAssignments += generateMemoryStore( m_context.dialect, _stmt.debugData, @@ -304,28 +305,29 @@ void StackToMemoryMover::visit(Expression& _expression) { ASTModifier::visit(_expression); if (Identifier* identifier = std::get_if(&_expression)) - if (std::optional offset = m_memoryOffsetTracker(identifier->name)) + if (auto offset = m_memoryOffsetTracker(identifier->name)) _expression = generateMemoryLoad(m_context.dialect, identifier->debugData, *offset); } -std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString _variable) const +std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString const& _variable) const { if (m_memorySlots.count(_variable)) { uint64_t slot = m_memorySlots.at(_variable); yulAssert(slot < m_numRequiredSlots, ""); - return YulString{toCompactHexWithPrefix(m_reservedMemory + 32 * (m_numRequiredSlots - slot - 1))}; + auto const memoryOffset = m_reservedMemory + 32 * (m_numRequiredSlots - slot - 1); + return valueOfNumberLiteral(toCompactHexWithPrefix(memoryOffset)); } else return std::nullopt; } -std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(TypedName const& _variable) const +std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(TypedName const& _variable) const { return (*this)(_variable.name); } -std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(Identifier const& _variable) const +std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(Identifier const& _variable) const { return (*this)(_variable.name); } diff --git a/libyul/optimiser/StackToMemoryMover.h b/libyul/optimiser/StackToMemoryMover.h index 64c661c0b..79c7276ed 100644 --- a/libyul/optimiser/StackToMemoryMover.h +++ b/libyul/optimiser/StackToMemoryMover.h @@ -165,13 +165,13 @@ class StackToMemoryMover: ASTModifier /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal /// or std::nullopt if the variable should not be moved. - std::optional operator()(YulString _variable) const; + std::optional operator()(YulString const& _variable) const; /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal /// or std::nullopt if the variable should not be moved. - std::optional operator()(TypedName const& _variable) const; + std::optional operator()(TypedName const& _variable) const; /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal /// or std::nullopt if the variable should not be moved. - std::optional operator()(Identifier const& _variable) const; + std::optional operator()(Identifier const& _variable) const; private: u256 m_reservedMemory; diff --git a/libyul/optimiser/StructuralSimplifier.cpp b/libyul/optimiser/StructuralSimplifier.cpp index 2af0f7bac..896c855b0 100644 --- a/libyul/optimiser/StructuralSimplifier.cpp +++ b/libyul/optimiser/StructuralSimplifier.cpp @@ -36,7 +36,7 @@ OptionalStatements replaceConstArgSwitch(Switch& _switchStmt, u256 const& _const for (auto& _case: _switchStmt.cases) { - if (_case.value && valueOfLiteral(*_case.value) == _constExprVal) + if (_case.value && _case.value->value.value() == _constExprVal) { matchingCaseBlock = &_case.body; break; @@ -57,9 +57,9 @@ OptionalStatements replaceConstArgSwitch(Switch& _switchStmt, u256 const& _const std::optional hasLiteralValue(Expression const& _expression) { if (std::holds_alternative(_expression)) - return valueOfLiteral(std::get(_expression)); + return std::get(_expression).value.value(); else - return std::optional(); + return std::nullopt; } bool expressionAlwaysTrue(Expression const& _expression) diff --git a/libyul/optimiser/SyntacticalEquality.cpp b/libyul/optimiser/SyntacticalEquality.cpp index 6f7753827..db562716a 100644 --- a/libyul/optimiser/SyntacticalEquality.cpp +++ b/libyul/optimiser/SyntacticalEquality.cpp @@ -22,6 +22,7 @@ #include #include +#include #include @@ -63,12 +64,13 @@ bool SyntacticallyEqual::expressionEqual(Identifier const& _lhs, Identifier cons } bool SyntacticallyEqual::expressionEqual(Literal const& _lhs, Literal const& _rhs) { - if (_lhs.kind != _rhs.kind || _lhs.type != _rhs.type) + yulAssert(validLiteral(_lhs), "Invalid lhs literal during syntactical equality check"); + yulAssert(validLiteral(_rhs), "Invalid rhs literal during syntactical equality check"); + + if (_lhs.type != _rhs.type) return false; - if (_lhs.kind == LiteralKind::Number) - return valueOfNumberLiteral(_lhs) == valueOfNumberLiteral(_rhs); - else - return _lhs.value == _rhs.value; + + return _lhs.value == _rhs.value; } bool SyntacticallyEqual::statementEqual(ExpressionStatement const& _lhs, ExpressionStatement const& _rhs) diff --git a/libyul/optimiser/SyntacticalEquality.h b/libyul/optimiser/SyntacticalEquality.h index 319da763e..5a8d2b49b 100644 --- a/libyul/optimiser/SyntacticalEquality.h +++ b/libyul/optimiser/SyntacticalEquality.h @@ -34,6 +34,9 @@ namespace solidity::yul /** * Component that can compare ASTs for equality on a syntactic basis. * Ignores source locations and allows for different variable names but requires exact matches otherwise. + * Literals are compared based on their values, e.g., `0x01`, `1`, `"\x01"` and `true` all evaluate as equal. + * Note that this does not apply to unlimited literal strings, which are never considered equal to normal literals, + * even when the values would look like identical strings in the source. * * Prerequisite: Disambiguator (unless only expressions are compared) */ diff --git a/libyul/optimiser/UnusedStoreEliminator.cpp b/libyul/optimiser/UnusedStoreEliminator.cpp index ed3394847..6a0ab1518 100644 --- a/libyul/optimiser/UnusedStoreEliminator.cpp +++ b/libyul/optimiser/UnusedStoreEliminator.cpp @@ -61,9 +61,9 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) std::map values; for (auto const& [name, expression]: ssaValues.values()) values[name] = AssignedValue{expression, {}}; - Expression const zeroLiteral{Literal{{}, LiteralKind::Number, YulString{"0"}, {}}}; - Expression const oneLiteral{Literal{{}, LiteralKind::Number, YulString{"1"}, {}}}; - Expression const thirtyTwoLiteral{Literal{{}, LiteralKind::Number, YulString{"32"}, {}}}; + Expression const zeroLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{0}), {}}}; + Expression const oneLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{1}), {}}}; + Expression const thirtyTwoLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{32}), {}}}; values[YulString{zero}] = AssignedValue{&zeroLiteral, {}}; values[YulString{one}] = AssignedValue{&oneLiteral, {}}; values[YulString{thirtyTwo}] = AssignedValue{&thirtyTwoLiteral, {}}; diff --git a/test/libyul/yulOptimizerTests/disambiguator/similar_literals.yul b/test/libyul/yulOptimizerTests/disambiguator/similar_literals.yul new file mode 100644 index 000000000..87c7d4a19 --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/similar_literals.yul @@ -0,0 +1,23 @@ +{ + let a := 1234 + let a_hex := 0x4d2 + let b := "1234" + let b_hex := "0x4d2" + let c := '1234' + let c_hex := '0x4d2' + let d := hex"1234" + let d_hex := hex"04d2" +} +// ---- +// step: disambiguator +// +// { +// let a := 1234 +// let a_hex := 0x4d2 +// let b := "1234" +// let b_hex := "0x4d2" +// let c := "1234" +// let c_hex := "0x4d2" +// let d := "\x124" +// let d_hex := "\x04\xd2" +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul b/test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul new file mode 100644 index 000000000..f0db2af1b --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul @@ -0,0 +1,13 @@ +object "A" { + code { + pop(datasize(hex'616263')) + } + data 'abc' "1234" +} +// ---- +// step: disambiguator +// +// object "A" { +// code { pop(datasize("abc")) } +// data "abc" hex"31323334" +// } diff --git a/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation.yul b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation.yul index b7a815dd9..77df0ae20 100644 --- a/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation.yul +++ b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation.yul @@ -1,8 +1,10 @@ { f() g() - function f() { mstore(0x01, mload(0x00)) } - function g() { mstore(1, mload(0)) } + h() + function f() { mstore(29400335157912315244266070412362164103369332044010299463143527189509193072640, mload(0x00)) } + function g() { mstore(0x4100000000000000000000000000000000000000000000000000000000000000, mload(0x00)) } + function h() { mstore("A", mload(0)) } } // ---- // step: equivalentFunctionCombiner @@ -10,8 +12,15 @@ // { // f() // f() +// h() // function f() -// { mstore(0x01, mload(0x00)) } +// { +// mstore(29400335157912315244266070412362164103369332044010299463143527189509193072640, mload(0x00)) +// } // function g() -// { mstore(1, mload(0)) } +// { +// mstore(0x4100000000000000000000000000000000000000000000000000000000000000, mload(0x00)) +// } +// function h() +// { mstore("A", mload(0)) } // } diff --git a/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul new file mode 100644 index 000000000..301f50c6e --- /dev/null +++ b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul @@ -0,0 +1,48 @@ +object "test" +{ + code + { + f() + g() + h() + i() + function f() + { + let x := datasize("A") + } + function g() + { + let x := datasize(hex"41") + } + function h() + { + let x := datasize("\x41") + } + function i() + { + let x := datasize("\u0041") + } + } + data 'A' "A" +} + +// ---- +// step: equivalentFunctionCombiner +// +// object "test" { +// code { +// f() +// f() +// f() +// f() +// function f() +// { let x := datasize("A") } +// function g() +// { let x_1 := datasize("A") } +// function h() +// { let x_2 := datasize("A") } +// function i() +// { let x_3 := datasize("A") } +// } +// data "A" hex"41" +// } diff --git a/test/libyul/yulSyntaxTests/switch_duplicate_case.yul b/test/libyul/yulSyntaxTests/switch_duplicate_case.yul index 861f721ac..7417f32d6 100644 --- a/test/libyul/yulSyntaxTests/switch_duplicate_case.yul +++ b/test/libyul/yulSyntaxTests/switch_duplicate_case.yul @@ -6,4 +6,4 @@ // ==== // dialect: evmTyped // ---- -// DeclarationError 6792: (34-50): Duplicate case "0" defined. +// DeclarationError 6792: (34-50): Duplicate case "0x0" defined. diff --git a/test/libyul/yulSyntaxTests/switch_duplicate_case_different_literal.yul b/test/libyul/yulSyntaxTests/switch_duplicate_case_different_literal.yul index e3367b175..91f19efae 100644 --- a/test/libyul/yulSyntaxTests/switch_duplicate_case_different_literal.yul +++ b/test/libyul/yulSyntaxTests/switch_duplicate_case_different_literal.yul @@ -6,4 +6,4 @@ // ==== // dialect: evmTyped // ---- -// DeclarationError 6792: (34-49): Duplicate case "0" defined. +// DeclarationError 6792: (34-49): Duplicate case "" defined. diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index 2fe2b2184..d2cbdb11b 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -508,7 +509,7 @@ u256 EVMInstructionInterpreter::evalBuiltin( // Evaluate datasize/offset/copy instructions if (fun == "datasize" || fun == "dataoffset") { - std::string arg = std::get(_arguments.at(0)).value.str(); + std::string arg = formatLiteral(std::get(_arguments.at(0))); if (arg.length() < 32) arg.resize(32, 0); if (fun == "datasize") diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index a8658e921..6a0f3a999 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -296,10 +296,7 @@ void Interpreter::incrementStep() void ExpressionEvaluator::operator()(Literal const& _literal) { incrementStep(); - static YulString const trueString("true"); - static YulString const falseString("false"); - - setValue(valueOfLiteral(_literal)); + setValue(_literal.value.value()); } void ExpressionEvaluator::operator()(Identifier const& _identifier) @@ -389,16 +386,13 @@ void ExpressionEvaluator::evaluateArgs( visit(expr); else { - std::string literal = std::get(expr).value.str(); - - try - { - m_values = {u256(literal)}; - } - catch (std::exception&) + if (std::get(expr).value.unlimited()) { - m_values = {u256(0)}; + yulAssert(std::get(expr).kind == LiteralKind::String); + m_values = {0xdeadbeef}; } + else + m_values = {std::get(expr).value.value()}; } values.push_back(value()); From 21e3b22c900e951d61b3c2d585bfc1893ca49b6e Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 28 Jun 2024 12:34:22 +0200 Subject: [PATCH 0187/1340] SMTChecker: Do not depend on predicate name containing numbers --- libsolidity/formal/CHC.cpp | 19 +++++++------------ .../operators/slice_access.sol | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/operators/slice_access.sol diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index f0c6ec33a..ff3a6f1da 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -2419,22 +2419,17 @@ std::map> CHC::summaryCalls(CHCSolverInterface:: // nondet_call__ // Those have the extra unique numbers based on the traversal order, and are necessary // to infer the call order so that's shown property in the counterexample trace. - // Predicates that do not have a CALLID have a predicate id at the end of , - // so the assertion below should still hold. + // For other predicates, we do not care. auto beg = _s.data(); while (beg != _s.data() + _s.size() && !isDigit(*beg)) ++beg; - auto end = beg; - while (end != _s.data() + _s.size() && isDigit(*end)) ++end; - - solAssert(beg != end, "Expected to find numerical call or predicate id."); - - int result; - auto [p, ec] = std::from_chars(beg, end, result); - solAssert(ec == std::errc(), "Id should be a number."); - + int result = -1; + static_cast(std::from_chars(beg, _s.data() + _s.size(), result)); return result; }; - return extract(_graph.nodes.at(_a).name) > extract(_graph.nodes.at(_b).name); + auto anum = extract(_graph.nodes.at(_a).name); + auto bnum = extract(_graph.nodes.at(_b).name); + // The second part of the condition is needed to ensure that two different predicates are not considered equal + return (anum > bnum) || (anum == bnum && _graph.nodes.at(_a).name > _graph.nodes.at(_b).name); }; std::queue> q; diff --git a/test/libsolidity/smtCheckerTests/operators/slice_access.sol b/test/libsolidity/smtCheckerTests/operators/slice_access.sol new file mode 100644 index 000000000..6accc54c0 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/slice_access.sol @@ -0,0 +1,16 @@ +contract C { +function f(int[] calldata b) public pure { + require(b.length == 3); + require(b[0] == 0); + require(b[1] == 1); + require(b[2] == 2); + assert(b[1:3][0] == 1); // should hold + assert(b[1:3][1] == 1); // should fail +} +} +// ==== +// SMTEngine: chc +// SMTIgnoreCex: no +// ---- +// Warning 6328: (203-225): CHC: Assertion violation happens here.\nCounterexample:\n\nb = [0, 1, 2]\n\nTransaction trace:\nC.constructor()\nC.f([0, 1, 2]) +// Info 1391: CHC: 6 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 762ebc1ce51c5c016df4e49be06f96d048312cfd Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Mon, 1 Jul 2024 10:02:52 +0200 Subject: [PATCH 0188/1340] Yul fuzzer: Skip tstore generation for older EVM versions. --- test/tools/ossfuzz/protoToYul.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 7913f4d63..5a57b779d 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -1162,6 +1162,11 @@ void ProtoConverter::visit(IfStmt const& _x) void ProtoConverter::visit(StoreFunc const& _x) { auto storeType = _x.st(); + // Skip statement generation if tstore is not + // supported in EVM version + if (storeType == StoreFunc::TSTORE && !m_evmVersion.supportsTransientStorage()) + return; + switch (storeType) { case StoreFunc::MSTORE: From 81966bc5f6b504df18bd5a09f23a13008d1ff378 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 26 Jun 2024 21:38:53 +0200 Subject: [PATCH 0189/1340] SMTChecker: Simplify CHC predicate representation There is no need to represent predicates using the symbolic variables. These are not variables that correspond to expression in the code. It is sufficient to store the name of the predicate and its signature (sort), which we can do with the SMT Expression. --- libsmtutil/Z3CHCInterface.cpp | 2 + libsolidity/formal/CHC.cpp | 5 - libsolidity/formal/CHC.h | 1 - libsolidity/formal/Predicate.cpp | 29 +-- libsolidity/formal/Predicate.h | 20 +- .../model_checker_invariants_reentrancy/err | 2 +- .../model_checker_print_query_all/err | 70 +++--- .../model_checker_print_query_chc/err | 70 +++--- .../output.json | 4 +- .../output.json | 212 +++++++++--------- .../output.json | 212 +++++++++--------- .../output.json | 72 +++--- .../deployment/deploy_trusted_flow.sol | 4 +- ...n_code_state_reentrancy_unsafe_trusted.sol | 2 +- .../underflow_only_in_external_call.sol | 4 +- .../operators/index_access_for_bytesNN.sol | 3 +- .../operators/index_access_side_effect.sol | 5 +- ...rator_matches_equivalent_function_call.sol | 14 +- .../smtCheckerTests/out_of_bounds/array_1.sol | 4 +- .../smtCheckerTests/types/array_branch_3d.sol | 14 +- .../types/array_branches_3d.sol | 1 + .../types/array_branches_3d_show_unproved.sol | 1 + .../types/struct_array_branches_2d.sol | 4 +- 23 files changed, 368 insertions(+), 387 deletions(-) diff --git a/libsmtutil/Z3CHCInterface.cpp b/libsmtutil/Z3CHCInterface.cpp index a25890e8d..787d46d72 100644 --- a/libsmtutil/Z3CHCInterface.cpp +++ b/libsmtutil/Z3CHCInterface.cpp @@ -58,6 +58,8 @@ void Z3CHCInterface::declareVariable(std::string const& _name, SortPointer const void Z3CHCInterface::registerRelation(Expression const& _expr) { + smtAssert(_expr.sort->kind == Kind::Function); + m_z3Interface->declareVariable(_expr.name, _expr.sort); m_solver.register_relation(m_z3Interface->functions().at(_expr.name)); } diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index ff3a6f1da..73b979364 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -1657,11 +1657,6 @@ smtutil::Expression CHC::error() return (*m_errorPredicate)({}); } -smtutil::Expression CHC::error(unsigned _idx) -{ - return m_errorPredicate->functor(_idx)({}); -} - smtutil::Expression CHC::initializer(ContractDefinition const& _contract, ContractDefinition const& _contractContext) { return predicate(*m_contractInitializers.at(&_contractContext).at(&_contract)); diff --git a/libsolidity/formal/CHC.h b/libsolidity/formal/CHC.h index b60e5c3f7..8a40ecb22 100644 --- a/libsolidity/formal/CHC.h +++ b/libsolidity/formal/CHC.h @@ -225,7 +225,6 @@ class CHC: public SMTEncoder smtutil::Expression interface(ContractDefinition const& _contract); /// Error predicate over current variables. smtutil::Expression error(); - smtutil::Expression error(unsigned _idx); /// Creates a block for the given _node. Predicate const* createBlock(ASTNode const* _node, PredicateType _predType, std::string const& _prefix = ""); diff --git a/libsolidity/formal/Predicate.cpp b/libsolidity/formal/Predicate.cpp index 01316d75f..75314d7e9 100644 --- a/libsolidity/formal/Predicate.cpp +++ b/libsolidity/formal/Predicate.cpp @@ -49,26 +49,25 @@ Predicate const* Predicate::create( std::vector _scopeStack ) { - smt::SymbolicFunctionVariable predicate{_sort, std::move(_name), _context}; - std::string functorName = predicate.currentName(); - solAssert(!m_predicates.count(functorName), ""); + solAssert(!m_predicates.count(_name), ""); return &m_predicates.emplace( std::piecewise_construct, - std::forward_as_tuple(functorName), - std::forward_as_tuple(std::move(predicate), _type, _context.state().hasBytesConcatFunction(), + std::forward_as_tuple(_name), + std::forward_as_tuple(_name, std::move(_sort), _type, _context.state().hasBytesConcatFunction(), _node, _contractContext, std::move(_scopeStack)) ).first->second; } Predicate::Predicate( - smt::SymbolicFunctionVariable&& _predicate, + std::string _name, + SortPointer _sort, PredicateType _type, bool _bytesConcatFunctionInContext, ASTNode const* _node, ContractDefinition const* _contractContext, std::vector _scopeStack ): - m_predicate(std::move(_predicate)), + m_functor(std::move(_name), {}, std::move(_sort)), m_type(_type), m_node(_node), m_contractContext(_contractContext), @@ -89,22 +88,12 @@ void Predicate::reset() smtutil::Expression Predicate::operator()(std::vector const& _args) const { - return m_predicate(_args); -} - -smtutil::Expression Predicate::functor() const -{ - return m_predicate.currentFunctionValue(); -} - -smtutil::Expression Predicate::functor(unsigned _idx) const -{ - return m_predicate.functionValueAtIndex(_idx); + return smtutil::Expression(m_functor.name, _args, SortProvider::boolSort); } -void Predicate::newFunctor() +smtutil::Expression const& Predicate::functor() const { - m_predicate.increaseIndex(); + return m_functor; } ASTNode const* Predicate::programNode() const diff --git a/libsolidity/formal/Predicate.h b/libsolidity/formal/Predicate.h index 638354f92..a7df44621 100644 --- a/libsolidity/formal/Predicate.h +++ b/libsolidity/formal/Predicate.h @@ -18,11 +18,10 @@ #pragma once -#include -#include #include +#include #include #include @@ -37,6 +36,11 @@ class CharStreamProvider; namespace solidity::frontend { +namespace smt +{ +class EncodingContext; +} + enum class PredicateType { Interface, @@ -69,7 +73,8 @@ class Predicate ); Predicate( - smt::SymbolicFunctionVariable&& _predicate, + std::string _name, + smtutil::SortPointer _sort, PredicateType _type, bool _bytesConcatFunctionInContext, ASTNode const* _node = nullptr, @@ -91,11 +96,7 @@ class Predicate smtutil::Expression operator()(std::vector const& _args) const; /// @returns the function declaration of the predicate. - smtutil::Expression functor() const; - /// @returns the function declaration of the predicate with index _idx. - smtutil::Expression functor(unsigned _idx) const; - /// Increases the index of the function declaration of the predicate. - void newFunctor(); + smtutil::Expression const& functor() const; /// @returns the program node this predicate represents. ASTNode const* programNode() const; @@ -204,8 +205,7 @@ class Predicate /// @returns index at which state variables values start in args list size_t firstStateVarIndex() const { return m_bytesConcatFunctionInContext ? 8 : 7; } - /// The actual SMT expression. - smt::SymbolicFunctionVariable m_predicate; + smtutil::Expression m_functor; /// The type of this predicate. PredicateType m_type; diff --git a/test/cmdlineTests/model_checker_invariants_reentrancy/err b/test/cmdlineTests/model_checker_invariants_reentrancy/err index bdd19fa18..68ef6404c 100644 --- a/test/cmdlineTests/model_checker_invariants_reentrancy/err +++ b/test/cmdlineTests/model_checker_invariants_reentrancy/err @@ -7,6 +7,6 @@ Warning: Return value of low-level calls not used. Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Info: Reentrancy property(ies) for model_checker_invariants_reentrancy/input.sol:test: -(((!(x <= 0) || !(x' >= 1)) && (!(x <= 0) || !( >= 1))) || true) +(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) = 0 -> no errors = 1 -> Assertion failed at assert(x < 10) diff --git a/test/cmdlineTests/model_checker_print_query_all/err b/test/cmdlineTests/model_checker_print_query_all/err index fc3bf7c7a..7fbaba3eb 100644 --- a/test/cmdlineTests/model_checker_print_query_all/err +++ b/test/cmdlineTests/model_checker_print_query_all/err @@ -7,120 +7,120 @@ Info: CHC: Requested query: (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16_0| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16_0| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) -(declare-fun |summary_3_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16_0 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) -(declare-fun |block_5_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) -(declare-fun |block_7_return_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |block_9_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |contract_initializer_10_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |contract_initializer_after_init_12_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |implicit_constructor_entry_13_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |error_target_3_0| () Bool) +(declare-fun |error_target_3| () Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3_0))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> error_target_3_0 false))) +(=> error_target_3 false))) (check-sat) diff --git a/test/cmdlineTests/model_checker_print_query_chc/err b/test/cmdlineTests/model_checker_print_query_chc/err index 1dd7f0c98..4da0a7cb5 100644 --- a/test/cmdlineTests/model_checker_print_query_chc/err +++ b/test/cmdlineTests/model_checker_print_query_chc/err @@ -7,120 +7,120 @@ Info: CHC: Requested query: (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16_0| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16_0| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) -(declare-fun |summary_3_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16_0 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) -(declare-fun |block_5_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) -(declare-fun |block_7_return_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |block_9_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |contract_initializer_10_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |contract_initializer_after_init_12_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |implicit_constructor_entry_13_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |error_target_3_0| () Bool) +(declare-fun |error_target_3| () Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3_0))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> error_target_3_0 false))) +(=> error_target_3 false))) (check-sat) diff --git a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json index bf6b296cd..760f1d7a7 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json @@ -33,14 +33,14 @@ "component": "general", "errorCode": "1180", "formattedMessage": "Info: Reentrancy property(ies) for A:test: -(((!(x <= 0) || !(x' >= 1)) && (!(x <= 0) || !( >= 1))) || true) +(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) = 0 -> no errors = 1 -> Assertion failed at assert(x < 10) ", "message": "Reentrancy property(ies) for A:test: -(((!(x <= 0) || !(x' >= 1)) && (!(x <= 0) || !( >= 1))) || true) +(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) = 0 -> no errors = 1 -> Assertion failed at assert(x < 10) ", diff --git a/test/cmdlineTests/standard_model_checker_print_query_all/output.json b/test/cmdlineTests/standard_model_checker_print_query_all/output.json index 97aa88579..4b5782de3 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_all/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_all/output.json @@ -1,7 +1,7 @@ { "auxiliaryInputRequested": { "smtlib2queries": { - "0x1880095c52d8681601c6821e4a5c29740649509af99947bce54102546dd3376a": "(set-option :timeout 1000) + "0xcbd85fe3127d1edfce70355ba6da5a3e9573873d8596ee8b1cfc2222af166628": "(set-option :timeout 1000) (set-logic HORN) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) @@ -9,120 +9,120 @@ (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16_0| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16_0| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) -(declare-fun |summary_3_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16_0 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) -(declare-fun |block_5_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) -(declare-fun |block_7_return_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |block_9_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |contract_initializer_10_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |contract_initializer_after_init_12_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |implicit_constructor_entry_13_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |error_target_3_0| () Bool) +(declare-fun |error_target_3| () Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3_0))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> error_target_3_0 false))) +(=> error_target_3 false))) (check-sat) ", "0xcbfcc2413b217c6564ee01f322c9ca1f34fd79d19961dc3e62aa9c2e5dcb6efc": "(set-option :produce-models true) @@ -170,120 +170,120 @@ (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16_0| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16_0| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) -(declare-fun |summary_3_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16_0 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) -(declare-fun |block_5_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) -(declare-fun |block_7_return_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |block_9_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |contract_initializer_10_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |contract_initializer_after_init_12_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |implicit_constructor_entry_13_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |error_target_3_0| () Bool) +(declare-fun |error_target_3| () Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3_0))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> error_target_3_0 false))) +(=> error_target_3 false))) (check-sat) @@ -297,120 +297,120 @@ (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16_0| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16_0| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) -(declare-fun |summary_3_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16_0 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) -(declare-fun |block_5_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) -(declare-fun |block_7_return_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |block_9_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |contract_initializer_10_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |contract_initializer_after_init_12_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |implicit_constructor_entry_13_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |error_target_3_0| () Bool) +(declare-fun |error_target_3| () Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3_0))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> error_target_3_0 false))) +(=> error_target_3 false))) (check-sat) ", "severity": "info", diff --git a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json index a9b0df0fb..a9956d82b 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json @@ -1,7 +1,7 @@ { "auxiliaryInputRequested": { "smtlib2queries": { - "0x1880095c52d8681601c6821e4a5c29740649509af99947bce54102546dd3376a": "(set-option :timeout 1000) + "0xcbd85fe3127d1edfce70355ba6da5a3e9573873d8596ee8b1cfc2222af166628": "(set-option :timeout 1000) (set-logic HORN) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) @@ -9,120 +9,120 @@ (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16_0| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16_0| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) -(declare-fun |summary_3_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16_0 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) -(declare-fun |block_5_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) -(declare-fun |block_7_return_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |block_9_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |contract_initializer_10_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |contract_initializer_after_init_12_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |implicit_constructor_entry_13_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |error_target_3_0| () Bool) +(declare-fun |error_target_3| () Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3_0))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> error_target_3_0 false))) +(=> error_target_3 false))) (check-sat) " } @@ -140,120 +140,120 @@ (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16_0| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16_0| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) -(declare-fun |summary_3_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16_0 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) -(declare-fun |block_5_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) -(declare-fun |block_7_return_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |block_9_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |contract_initializer_10_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |contract_initializer_after_init_12_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |implicit_constructor_entry_13_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |error_target_3_0| () Bool) +(declare-fun |error_target_3| () Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3_0))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> error_target_3_0 false))) +(=> error_target_3 false))) (check-sat) @@ -267,120 +267,120 @@ (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16_0| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16_0| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) -(declare-fun |summary_3_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16_0 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16_0 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) -(declare-fun |block_5_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) -(declare-fun |block_7_return_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |block_9_function_f__15_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |contract_initializer_10_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |contract_initializer_after_init_12_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |implicit_constructor_entry_13_C_16_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |error_target_3_0| () Bool) +(declare-fun |error_target_3| () Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3_0))) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> error_target_3_0 false))) +(=> error_target_3 false))) (check-sat) ", "severity": "info", diff --git a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json index e97227076..9dff9a3bd 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json @@ -28,127 +28,127 @@ (check-sat) (get-value (|EVALEXPR_0| )) ", - "0xe3dc20257e2b1bd9c6eb77b75913ec3a5752be174e0fd56af16d9fc95afa1b15": "(set-logic HORN) + "0xf090d88ff3260790818d140ca909b8f4cb311a0d905e4e0318ad4dd790ff5f19": "(set-logic HORN) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_14_0| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_14_0| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |interface_0_C_14| (Int |abi_type| |crypto_type| |state_type| ) Bool) +(declare-fun |nondet_interface_1_C_14| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) +(declare-fun |summary_constructor_2_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_14_0 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) +(=> (= error_0 0) (nondet_interface_1_C_14 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) -(declare-fun |summary_3_function_f__13_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) -(declare-fun |summary_4_function_f__13_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) +(declare-fun |summary_3_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) +(declare-fun |summary_4_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (and (and (nondet_interface_1_C_14_0 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 x_3_0 state_2 x_3_1))) (nondet_interface_1_C_14_0 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) +(=> (and (and (nondet_interface_1_C_14 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_1 x_3_0 state_2 x_3_1))) (nondet_interface_1_C_14 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) -(declare-fun |block_5_function_f__13_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) -(declare-fun |block_6_f_12_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) +(declare-fun |block_5_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) +(declare-fun |block_6_f_12_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(block_5_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))) +(block_5_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (and (and (block_5_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true)) true) (block_6_f_12_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) +(=> (and (and (block_5_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true)) true) (block_6_f_12_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) -(declare-fun |block_7_return_function_f__13_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) -(declare-fun |block_8_function_f__13_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) +(declare-fun |block_7_return_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) +(declare-fun |block_8_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (and (and (block_6_f_12_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> true true) (and (= expr_8_0 0) (and (=> true (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_1) (and (and (>= x_3_1 0) (<= x_3_1 115792089237316195423570985008687907853269984665640564039457584007913129639935)) true))))))) (and (and true (not expr_9_1)) (= error_1 1))) (block_8_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) +(=> (and (and (block_6_f_12_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> true true) (and (= expr_8_0 0) (and (=> true (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_1) (and (and (>= x_3_1 0) (<= x_3_1 115792089237316195423570985008687907853269984665640564039457584007913129639935)) true))))))) (and (and true (not expr_9_1)) (= error_1 1))) (block_8_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (block_8_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (summary_3_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) +(=> (block_8_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (summary_3_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (and (and (block_6_f_12_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (= error_1 error_0) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> true true) (and (= expr_8_0 0) (and (=> true (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_1) (and (and (>= x_3_1 0) (<= x_3_1 115792089237316195423570985008687907853269984665640564039457584007913129639935)) true)))))))) true) (block_7_return_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) +(=> (and (and (block_6_f_12_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (= error_1 error_0) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> true true) (and (= expr_8_0 0) (and (=> true (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_1) (and (and (>= x_3_1 0) (<= x_3_1 115792089237316195423570985008687907853269984665640564039457584007913129639935)) true)))))))) true) (block_7_return_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (and (and (block_7_return_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) true) true) (summary_3_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) +(=> (and (and (block_7_return_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) true) true) (summary_3_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) -(declare-fun |block_9_function_f__13_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) +(declare-fun |block_9_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(block_9_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))) +(block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (block_9_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (summary_3_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_2 x_3_1 state_3 x_3_2) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true))))))) true) (summary_4_function_f__13_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_3 x_3_2)))) +(=> (and (and (block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (summary_3_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_2 x_3_1 state_3 x_3_2) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true))))))) true) (summary_4_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_3 x_3_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (interface_0_C_14_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (= error_0 0))) (interface_0_C_14_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (interface_0_C_14 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |contract_initializer_10_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_10_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_entry_11_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |contract_initializer_after_init_12_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |contract_initializer_after_init_12_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_entry_11_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (contract_initializer_after_init_12_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) -(declare-fun |implicit_constructor_entry_13_C_14_0| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) +(declare-fun |implicit_constructor_entry_13_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_14_0 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) +(=> (and (and (implicit_constructor_entry_13_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (summary_constructor_2_C_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_14_0 this_0 abi_0 crypto_0 state_1)))) +(=> (and (and (summary_constructor_2_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1)))) -(declare-fun |error_target_3_0| () Bool) +(declare-fun |error_target_3| () Bool) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (interface_0_C_14_0 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__13_14_0 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (= error_0 1))) error_target_3_0))) +(=> (and (and (interface_0_C_14 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (= error_0 1))) error_target_3))) (assert (forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> error_target_3_0 false))) +(=> error_target_3 false))) (check-sat) " } diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol index 09f001719..2148324ad 100644 --- a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol @@ -21,10 +21,10 @@ contract C { // SMTIgnoreOS: macos // ---- // Warning 4984: (47-50): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 6328: (167-185): CHC: Assertion violation might happen here. // Warning 6328: (215-233): CHC: Assertion violation might happen here. +// Warning 6328: (267-285): CHC: Assertion violation might happen here. // Warning 6328: (304-322): CHC: Assertion violation happens here. // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. // Warning 2661: (47-50): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4661: (167-185): BMC: Assertion violation happens here. // Warning 4661: (215-233): BMC: Assertion violation happens here. +// Warning 4661: (267-285): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe_trusted.sol index 4d179ddf8..afd1f111b 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe_trusted.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_unsafe_trusted.sol @@ -40,5 +40,5 @@ contract C { // SMTExtCalls: trusted // SMTIgnoreOS: macos // ---- -// Warning 6328: (396-410): CHC: Assertion violation might happen here. // Warning 6328: (429-455): CHC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/underflow_only_in_external_call.sol b/test/libsolidity/smtCheckerTests/external_calls/underflow_only_in_external_call.sol index 0b5c8fa07..68f5ea049 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/underflow_only_in_external_call.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/underflow_only_in_external_call.sol @@ -4,7 +4,7 @@ contract C { bool guard = true; function dec() public returns (uint) { - if (guard) return 0; + require(!guard); --v; return v; } @@ -21,4 +21,4 @@ contract C { // SMTIgnoreCex: no // SMTTargets: underflow // ---- -// Warning 3944: (109-112): CHC: Underflow (resulting value less than 0) happens here.\nCounterexample:\nv = 0, guard = false\n = 0\n\nTransaction trace:\nC.constructor()\nState: v = 0, guard = true\nC.f()\n C.dec() -- trusted external call +// Warning 3944: (105-108): CHC: Underflow (resulting value less than 0) happens here.\nCounterexample:\nv = 0, guard = false\n = 0\n\nTransaction trace:\nC.constructor()\nState: v = 0, guard = true\nC.f()\n C.dec() -- trusted external call diff --git a/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol b/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol index c516675d6..b18d5426f 100644 --- a/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol +++ b/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol @@ -8,5 +8,4 @@ contract C { // SMTEngine: all // SMTIgnoreOS: macos // ---- -// Warning 6368: (76-90): CHC: Out of bounds access might happen here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol b/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol index 32c9780d1..d3b6f5895 100644 --- a/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol +++ b/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol @@ -21,6 +21,7 @@ contract C { // ==== // SMTEngine: all // SMTIgnoreCex: yes -// SMTIgnoreOS: macos // ---- -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (335-354): CHC: Assertion violation might happen here. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 4661: (335-354): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol index 9872a6a92..206c63042 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol @@ -53,28 +53,32 @@ contract C { } // ==== // SMTEngine: all -// SMTIgnoreOS: macos // ---- // Warning 3944: (679-708): CHC: Underflow (resulting value less than -32768) might happen here. -// Warning 4984: (679-708): CHC: Overflow (resulting value larger than 32767) happens here. +// Warning 4984: (679-708): CHC: Overflow (resulting value larger than 32767) might happen here. // Warning 3944: (777-806): CHC: Underflow (resulting value less than -32768) might happen here. // Warning 4984: (777-806): CHC: Overflow (resulting value larger than 32767) might happen here. +// Warning 3944: (870-884): CHC: Underflow (resulting value less than -32768) might happen here. // Warning 4984: (870-884): CHC: Overflow (resulting value larger than 32767) might happen here. // Warning 3944: (953-982): CHC: Underflow (resulting value less than -32768) might happen here. // Warning 4984: (953-982): CHC: Overflow (resulting value larger than 32767) might happen here. // Warning 4984: (1051-1080): CHC: Overflow (resulting value larger than 32767) might happen here. -// Warning 4281: (1051-1080): CHC: Division by zero happens here. +// Warning 4281: (1051-1080): CHC: Division by zero might happen here. // Warning 4281: (1149-1178): CHC: Division by zero might happen here. // Warning 6328: (2069-2095): CHC: Assertion violation might happen here. +// Warning 6328: (2105-2131): CHC: Assertion violation might happen here. // Warning 6328: (2141-2163): CHC: Assertion violation might happen here. +// Warning 6328: (2173-2199): CHC: Assertion violation might happen here. // Warning 6328: (2209-2235): CHC: Assertion violation might happen here. // Warning 6328: (2245-2271): CHC: Assertion violation might happen here. -// Info 1391: CHC: 13 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 10 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 2661: (679-708): BMC: Overflow (resulting value larger than 32767) happens here. // Warning 4144: (679-708): BMC: Underflow (resulting value less than -32768) happens here. // Warning 2661: (777-806): BMC: Overflow (resulting value larger than 32767) happens here. // Warning 4144: (777-806): BMC: Underflow (resulting value less than -32768) happens here. // Warning 2661: (953-982): BMC: Overflow (resulting value larger than 32767) happens here. // Warning 4144: (953-982): BMC: Underflow (resulting value less than -32768) happens here. +// Warning 3046: (1051-1080): BMC: Division by zero happens here. // Warning 3046: (1149-1178): BMC: Division by zero happens here. // Warning 7812: (2245-2271): BMC: Assertion violation might happen here. -// Info 6002: BMC: 10 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 14 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol b/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol index bc37a3130..65a1dfd39 100644 --- a/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol +++ b/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol @@ -21,8 +21,6 @@ contract C { // SMTIgnoreOS: macos // ---- // Warning 4984: (112-115): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 3944: (181-184): CHC: Underflow (resulting value less than 0) might happen here. // Warning 6368: (259-263): CHC: Out of bounds access happens here. -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. // Warning 2661: (112-115): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4144: (181-184): BMC: Underflow (resulting value less than 0) happens here. diff --git a/test/libsolidity/smtCheckerTests/types/array_branch_3d.sol b/test/libsolidity/smtCheckerTests/types/array_branch_3d.sol index 8ba3f0137..3aced164c 100644 --- a/test/libsolidity/smtCheckerTests/types/array_branch_3d.sol +++ b/test/libsolidity/smtCheckerTests/types/array_branch_3d.sol @@ -7,20 +7,14 @@ contract C c[0][0].push(); } function f(bool b) public { - c[0][0][0] = 0; if (b) c[0][0][0] = 1; assert(c[0][0][0] > 0); } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTSolvers: eld // ---- -// Warning 6368: (124-131): CHC: Out of bounds access might happen here. -// Warning 6368: (124-134): CHC: Out of bounds access might happen here. -// Warning 6368: (152-159): CHC: Out of bounds access might happen here. -// Warning 6368: (152-162): CHC: Out of bounds access might happen here. -// Warning 6368: (177-184): CHC: Out of bounds access might happen here. -// Warning 6368: (177-187): CHC: Out of bounds access might happen here. -// Warning 6328: (170-192): CHC: Assertion violation happens here. -// Info 1391: CHC: 6 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (152-174): CHC: Assertion violation happens here. +// Info 1391: CHC: 9 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/array_branches_3d.sol b/test/libsolidity/smtCheckerTests/types/array_branches_3d.sol index ecd419eea..8e9499183 100644 --- a/test/libsolidity/smtCheckerTests/types/array_branches_3d.sol +++ b/test/libsolidity/smtCheckerTests/types/array_branches_3d.sol @@ -15,6 +15,7 @@ contract C } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- // Warning 6368: (124-131): CHC: Out of bounds access might happen here. // Warning 6368: (124-134): CHC: Out of bounds access might happen here. diff --git a/test/libsolidity/smtCheckerTests/types/array_branches_3d_show_unproved.sol b/test/libsolidity/smtCheckerTests/types/array_branches_3d_show_unproved.sol index acd574472..7e9aad5b0 100644 --- a/test/libsolidity/smtCheckerTests/types/array_branches_3d_show_unproved.sol +++ b/test/libsolidity/smtCheckerTests/types/array_branches_3d_show_unproved.sol @@ -16,6 +16,7 @@ contract C // ==== // SMTEngine: all // SMTShowUnproved: yes +// SMTIgnoreOS: macos // ---- // Warning 6368: (124-131): CHC: Out of bounds access might happen here. // Warning 6368: (124-134): CHC: Out of bounds access might happen here. diff --git a/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol b/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol index 0d45aee14..d5daba699 100644 --- a/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol +++ b/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol @@ -15,7 +15,5 @@ contract C } // ==== // SMTEngine: all -// SMTIgnoreOS: macos // ---- -// Warning 6368: (216-225): CHC: Out of bounds access might happen here. -// Info 1391: CHC: 9 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 10 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From c012b725bb8ce755b93ce0dd05e83c34c499acd6 Mon Sep 17 00:00:00 2001 From: clonker Date: Mon, 1 Jul 2024 18:27:27 +0200 Subject: [PATCH 0190/1340] Scanner: Add SpecialComment mode --- liblangutil/Scanner.cpp | 50 +++++++++++++++++++++++++----------- liblangutil/Scanner.h | 11 ++++---- test/liblangutil/Scanner.cpp | 46 +++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 21 deletions(-) diff --git a/liblangutil/Scanner.cpp b/liblangutil/Scanner.cpp index 806efa311..4a41cb97a 100644 --- a/liblangutil/Scanner.cpp +++ b/liblangutil/Scanner.cpp @@ -826,31 +826,48 @@ Token Scanner::scanString(bool const _isUnicode) char const quote = m_char; advance(); // consume quote LiteralScope literal(this, LITERAL_TYPE_STRING); - while (m_char != quote && !isSourcePastEndOfInput() && !isUnicodeLinebreak()) + // for source location comments we allow multiline string literals + while (m_char != quote && !isSourcePastEndOfInput() && (!isUnicodeLinebreak() || m_kind == ScannerKind::SpecialComment)) { char c = m_char; advance(); - if (c == '\\') + + if (m_kind == ScannerKind::SpecialComment) { - if (isSourcePastEndOfInput() || !scanEscape()) - return setError(ScannerError::IllegalEscapeSequence); + if (c == '\\') + { + if (isSourcePastEndOfInput()) + return setError(ScannerError::IllegalEscapeSequence); + advance(); + } + else + addLiteralChar(c); } else { - // Report error on non-printable characters in string literals, however - // allow anything for unicode string literals, because their validity will - // be verified later (in the syntax checker). - // - // We are using a manual range and not isprint() to avoid - // any potential complications with locale. - if (!_isUnicode && (static_cast(c) <= 0x1f || static_cast(c) >= 0x7f)) + if (c == '\\') { - if (m_kind == ScannerKind::Yul) - return setError(ScannerError::IllegalCharacterInString); - return setError(ScannerError::UnicodeCharacterInNonUnicodeString); + if (isSourcePastEndOfInput() || !scanEscape()) + return setError(ScannerError::IllegalEscapeSequence); + } + else + { + // Report error on non-printable characters in string literals, however + // allow anything for unicode string literals, because their validity will + // be verified later (in the syntax checker). + // + // We are using a manual range and not isprint() to avoid + // any potential complications with locale. + if (!_isUnicode && (static_cast(c) <= 0x1f || static_cast(c) >= 0x7f)) + { + if (m_kind == ScannerKind::Yul) + return setError(ScannerError::IllegalCharacterInString); + return setError(ScannerError::UnicodeCharacterInNonUnicodeString); + } + addLiteralChar(c); } - addLiteralChar(c); } + } if (m_char != quote) return setError(ScannerError::IllegalStringEndQuote); @@ -1023,6 +1040,9 @@ std::tuple Scanner::scanIdentifierOrKeyword() auto const token = TokenTraits::fromIdentifierOrKeyword(m_tokens[NextNext].literal); switch (m_kind) { + case ScannerKind::SpecialComment: + // there are no keywords in special comments + return std::make_tuple(Token::Identifier, 0, 0); case ScannerKind::Solidity: // Turn experimental Solidity keywords that are not keywords in legacy Solidity into identifiers. if (TokenTraits::isExperimentalSolidityOnlyKeyword(std::get<0>(token))) diff --git a/liblangutil/Scanner.h b/liblangutil/Scanner.h index eaa2b3b54..c734a368c 100644 --- a/liblangutil/Scanner.h +++ b/liblangutil/Scanner.h @@ -62,15 +62,12 @@ namespace solidity::langutil { -class AstRawString; -class AstValueFactory; -class ParserRecorder; - enum class ScannerKind { Solidity, Yul, - ExperimentalSolidity + ExperimentalSolidity, + SpecialComment }; enum class ScannerError @@ -102,11 +99,13 @@ class Scanner { friend class LiteralScope; public: - explicit Scanner(CharStream& _source): + explicit Scanner(CharStream& _source, ScannerKind _kind = ScannerKind::Solidity): m_source(_source), m_sourceName{std::make_shared(_source.name())} { reset(); + if (_kind != ScannerKind::Solidity) + setScannerMode(_kind); } /// Resets scanner to the start of input. diff --git a/test/liblangutil/Scanner.cpp b/test/liblangutil/Scanner.cpp index 8c961a3ba..b4043fe86 100644 --- a/test/liblangutil/Scanner.cpp +++ b/test/liblangutil/Scanner.cpp @@ -1026,6 +1026,52 @@ BOOST_AUTO_TEST_CASE(yul_function_with_whitespace) BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } +BOOST_AUTO_TEST_CASE(special_comment_with_invalid_escapes) +{ + std::string input(R"("test\x\f\g\u\g\a\u\g\a12\uö\xyoof")"); + std::string expectedOutput(R"(test12öyoof)"); + CharStream stream(input, ""); + Scanner scanner(stream, ScannerKind::SpecialComment); + BOOST_REQUIRE(scanner.currentToken() == Token::StringLiteral); + BOOST_REQUIRE(scanner.currentLiteral() == expectedOutput); +} + +BOOST_AUTO_TEST_CASE(special_comment_with_valid_and_invalid_escapes) +{ + std::string input(R"("test\n\x61\t\u01A9test\f")"); + std::string expectedOutput(R"(test6101A9test)"); + CharStream stream(input, ""); + Scanner scanner(stream, ScannerKind::SpecialComment); + BOOST_REQUIRE(scanner.currentToken() == Token::StringLiteral); + BOOST_REQUIRE(scanner.currentLiteral() == expectedOutput); +} + +BOOST_AUTO_TEST_CASE(special_comment_with_unterminated_escape_sequence_at_eos) +{ + CharStream stream(R"("test\)", ""); + std::string expectedOutput(R"(test6101A9test)"); + Scanner scanner(stream, ScannerKind::SpecialComment); + BOOST_REQUIRE(scanner.currentToken() == Token::Illegal); + BOOST_REQUIRE(scanner.currentError() == ScannerError::IllegalEscapeSequence); +} + +BOOST_AUTO_TEST_CASE(special_comment_with_escaped_quotes) +{ + CharStream stream(R"("test\\\"")", ""); + std::string expectedOutput(R"(test)"); + Scanner scanner(stream, ScannerKind::SpecialComment); + BOOST_REQUIRE(scanner.currentToken() == Token::StringLiteral); + BOOST_REQUIRE(scanner.currentLiteral() == expectedOutput); +} + +BOOST_AUTO_TEST_CASE(special_comment_with_unterminated_string) +{ + CharStream stream(R"("test)", ""); + Scanner scanner(stream, ScannerKind::SpecialComment); + BOOST_REQUIRE(scanner.currentToken() == Token::Illegal); + BOOST_REQUIRE(scanner.currentError() == ScannerError::IllegalStringEndQuote); +} + BOOST_AUTO_TEST_SUITE_END() } // end namespaces From ef9aa908b6cb8f8cd6d2b287a8778ca162e5cc04 Mon Sep 17 00:00:00 2001 From: clonker Date: Mon, 1 Jul 2024 18:29:07 +0200 Subject: [PATCH 0191/1340] AsmParser: Use scanner instead of regex for source comment parsing --- Changelog.md | 2 + libyul/AsmParser.cpp | 82 ++++++++++++++++++++++++----------- test/libyul/Parser.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 24 deletions(-) diff --git a/Changelog.md b/Changelog.md index 442c4e34f..cba038a56 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,7 @@ Language Features: * Accept declarations of state variables with ``transient`` data location (parser support only, no code generation yet). * Make ``require(bool, Error)`` available when using the legacy pipeline. + * Yul: Parsing rules for source location comments have been relaxed: Whitespace between the location components as well as single-quoted code snippets are now allowed. Compiler Features: @@ -18,6 +19,7 @@ Bugfixes: * SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine. * TypeChecker: Fix segfault when assigning nested tuple to tuple. * Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. + * Yul Parser: Fix segfault when parsing very long location comments. ### 0.8.26 (2024-05-21) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index ecf3475a8..2ae4dd805 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -28,11 +28,10 @@ #include #include #include +#include #include #include -#include - #include #include @@ -53,7 +52,7 @@ std::optional toInt(std::string const& _value) { return stoi(_value); } - catch (...) + catch (std::out_of_range const&) { return std::nullopt; } @@ -193,13 +192,41 @@ std::optional> Parser::parseSrcComme langutil::SourceLocation const& _commentLocation ) { - static std::regex const argsRegex = std::regex( - R"~~(^(-1|\d+):(-1|\d+):(-1|\d+)(?:\s+|$))~~" // index and location, e.g.: 1:234:-1 - R"~~(("(?:[^"\\]|\\.)*"?)?)~~", // optional code snippet, e.g.: "string memory s = \"abc\";..." - std::regex_constants::ECMAScript | std::regex_constants::optimize - ); - std::match_results match; - if (!regex_search(_arguments.cbegin(), _arguments.cend(), match, argsRegex)) + CharStream argumentStream(std::string(_arguments), ""); + Scanner scanner(argumentStream, ScannerKind::SpecialComment); + + std::string_view tail{_arguments.substr(_arguments.size())}; + auto const parseLocationComponent = [](Scanner& _scanner, bool expectTrailingColon) -> std::optional + { + bool negative = false; + if (_scanner.currentToken() == Token::Sub) + { + negative = true; + _scanner.next(); + } + if (_scanner.currentToken() != Token::Number) + return std::nullopt; + if (expectTrailingColon && _scanner.peekNextToken() != Token::Colon) + return std::nullopt; + if (!isValidDecimal(_scanner.currentLiteral())) + return std::nullopt; + std::string decimal = (negative ? "-" : "") + _scanner.currentLiteral(); + _scanner.next(); + if (expectTrailingColon) + _scanner.next(); + return decimal; + }; + std::optional rawSourceIndex = parseLocationComponent(scanner, true); + std::optional rawStart = parseLocationComponent(scanner, true); + std::optional rawEnd = parseLocationComponent(scanner, false); + + size_t const snippetStart = static_cast(scanner.currentLocation().start); + bool const locationScannedSuccessfully = rawSourceIndex && rawStart && rawEnd; + bool const locationIsWhitespaceSeparated = + scanner.peekNextToken() == Token::EOS || + (snippetStart > 0 && langutil::isWhiteSpace(_arguments[snippetStart - 1])); + + if (!locationScannedSuccessfully || !locationIsWhitespaceSeparated) { m_errorReporter.syntaxError( 8387_error, @@ -209,13 +236,16 @@ std::optional> Parser::parseSrcComme return std::nullopt; } - solAssert(match.size() == 5, ""); - std::string_view tail = _arguments.substr(static_cast(match.position() + match.length())); + // captures error cases `"test` (illegal end quote) and `"test\` (illegal escape sequence / dangling backslash) + bool const illegalLiteral = scanner.currentToken() == Token::Illegal && (scanner.currentError() == ScannerError::IllegalStringEndQuote || scanner.currentError() == ScannerError::IllegalEscapeSequence); + if (scanner.currentToken() == Token::StringLiteral || illegalLiteral) + tail = _arguments.substr(static_cast(scanner.currentLocation().end)); + else + tail = _arguments.substr(static_cast(scanner.currentLocation().start)); - if (match[4].matched && ( - !boost::algorithm::ends_with(match[4].str(), "\"") || - boost::algorithm::ends_with(match[4].str(), "\\\"") - )) + // Other scanner errors may occur if there is no string literal which follows + // (f.ex. IllegalHexDigit, IllegalCommentTerminator), but these are ignored + if (illegalLiteral) { m_errorReporter.syntaxError( 1544_error, @@ -225,11 +255,15 @@ std::optional> Parser::parseSrcComme return {{tail, SourceLocation{}}}; } - std::optional const sourceIndex = toInt(match[1].str()); - std::optional const start = toInt(match[2].str()); - std::optional const end = toInt(match[3].str()); + std::optional const sourceIndex = toInt(*rawSourceIndex); + std::optional const start = toInt(*rawStart); + std::optional const end = toInt(*rawEnd); - if (!sourceIndex.has_value() || !start.has_value() || !end.has_value()) + if ( + !sourceIndex.has_value() || *sourceIndex < -1 || + !start.has_value() || *start < -1 || + !end.has_value() || *end < -1 + ) m_errorReporter.syntaxError( 6367_error, _commentLocation, @@ -237,8 +271,8 @@ std::optional> Parser::parseSrcComme "Expected non-negative integer values or -1 for source index and location." ); else if (sourceIndex == -1) - return {{tail, SourceLocation{start.value(), end.value(), nullptr}}}; - else if (!(sourceIndex >= 0 && m_sourceNames->count(static_cast(sourceIndex.value())))) + return {{tail, SourceLocation{*start, *end, nullptr}}}; + else if (!(sourceIndex >= 0 && m_sourceNames->count(static_cast(*sourceIndex)))) m_errorReporter.syntaxError( 2674_error, _commentLocation, @@ -246,9 +280,9 @@ std::optional> Parser::parseSrcComme ); else { - std::shared_ptr sourceName = m_sourceNames->at(static_cast(sourceIndex.value())); + std::shared_ptr sourceName = m_sourceNames->at(static_cast(*sourceIndex)); solAssert(sourceName, ""); - return {{tail, SourceLocation{start.value(), end.value(), std::move(sourceName)}}}; + return {{tail, SourceLocation{*start, *end, std::move(sourceName)}}}; } return {{tail, SourceLocation{}}}; } diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 46c4f11a8..ca8784ddb 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -33,6 +33,8 @@ #include #include +#include +#include #include #include @@ -767,6 +769,102 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_untermina CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); } +BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote) +{ + ErrorList errorList; + ErrorReporter reporter(errorList); + auto const sourceText = R"( + /// @src 0:111:222 " + /// + {} + )"; + EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + std::shared_ptr result = parse(sourceText, dialect, reporter); + BOOST_REQUIRE(!!result); + BOOST_REQUIRE(errorList.size() == 1); + BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); + BOOST_TEST(errorList[0]->errorId() == 1544_error); + CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); +} + +BOOST_AUTO_TEST_CASE(customSourceLocations_two_snippets_with_hex_comment) +{ + ErrorList errorList; + ErrorReporter reporter(errorList); + auto const sourceText = R"( + /// @src 0:111:222 hex"abc"@src 1:333:444 "abc" + {} + )"; + EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + std::shared_ptr result = parse(sourceText, dialect, reporter); + BOOST_REQUIRE(!!result && errorList.size() == 0); + // the second source location is not parsed as such, as the hex string isn't interpreted as snippet but + // as the beginning of the tail in AsmParser + CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); +} + +BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_escapes) +{ + ErrorList errorList; + ErrorReporter reporter(errorList); + auto const sourceText = R"( + /// @src 0:111:222 "\n\\x\x\w\uö\xy\z\y\fq" + {} + )"; + EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + std::shared_ptr result = parse(sourceText, dialect, reporter); + BOOST_REQUIRE(!!result && errorList.size() == 0); + CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); +} + +BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote_snippet_with_whitespaces_and_escapes) +{ + ErrorList errorList; + ErrorReporter reporter(errorList); + auto const sourceText = R"( + /// @src 0:111:222 '\n\\x\x\w\uö\xy\z\y\fq' + /// @src 1 : 222 : 333 '\x33\u1234\t\n' + {} + )"; + EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + std::shared_ptr result = parse(sourceText, dialect, reporter); + BOOST_REQUIRE(!!result && errorList.size() == 0); + CHECK_LOCATION(result->debugData->originLocation, "source1", 222, 333); +} + +BOOST_DATA_TEST_CASE(customSourceLocations_scanner_errors_outside_string_lits_are_ignored, boost::unit_test::data::make({"0x ", "/** unterminated comment", "1_23_4"}), invalid) +{ + ErrorList errorList; + ErrorReporter reporter(errorList); + auto const sourceText = fmt::format(R"( + /// @src 0:111:222 {} + /// @src 1:222:333 + {{}} + )", invalid); + EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + std::shared_ptr result = parse(sourceText, dialect, reporter); + BOOST_REQUIRE(!!result && errorList.empty()); + CHECK_LOCATION(result->debugData->originLocation, "source1", 222, 333); +} + +BOOST_AUTO_TEST_CASE(customSourceLocations_multi_line_source_loc) +{ + ErrorList errorList; + ErrorReporter reporter(errorList); + auto const sourceText = R"( + /// @src 1 : 111: + /// 222 " + /// abc\"def + /// + /// " @src 0:333:444 + {} + )"; + EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + std::shared_ptr result = parse(sourceText, dialect, reporter); + BOOST_REQUIRE(!!result && errorList.empty()); + CHECK_LOCATION(result->debugData->originLocation, "source0", 333, 444); +} + BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locations) { ErrorList errorList; From 8b0bb61a7a9392d07b965e88c267123743869426 Mon Sep 17 00:00:00 2001 From: clonker Date: Mon, 1 Jul 2024 18:30:03 +0200 Subject: [PATCH 0192/1340] CI: Re-enable *_bytecode_too_large_* and *_combined_too_large* tests --- .circleci/parallel_bytecode_report.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/.circleci/parallel_bytecode_report.sh b/.circleci/parallel_bytecode_report.sh index 7fe22c343..ee9dfde9f 100755 --- a/.circleci/parallel_bytecode_report.sh +++ b/.circleci/parallel_bytecode_report.sh @@ -44,9 +44,6 @@ cd test-cases/ echo "Preparing input files" python3 ../scripts/isolate_tests.py ../test/ -# FIXME: These cases crash because of https://github.com/ethereum/solidity/issues/13583 -rm ./*_bytecode_too_large_*.sol ./*_combined_too_large_*.sol - if [[ $binary_type == native || $binary_type == "osx_intel" ]]; then interface=$(echo -e "standard-json\ncli" | circleci tests split) echo "Selected interface: ${interface}" From ce02133054e276106a0cfa3784521cb6bed5fda8 Mon Sep 17 00:00:00 2001 From: clonker Date: Mon, 1 Jul 2024 09:53:22 +0200 Subject: [PATCH 0193/1340] BlockHasher: Do not hash literal kind --- Changelog.md | 1 + libyul/optimiser/BlockHasher.cpp | 1 - .../array/copying/function_type_array_to_storage.sol | 2 +- .../equivalentFunctionCombiner/constant_representation.yul | 2 +- test/libyul/yulOptimizerTests/fullSuite/devcon_example.yul | 2 +- .../yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index 442c4e34f..16920b50b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,7 @@ Compiler Features: * EVM: Support for the EVM version "Prague". * SMTChecker: Add CHC engine check for underflow and overflow in unary minus operation. * SMTChecker: Replace CVC4 as a possible BMC backend with cvc5. + * Yul Optimizer: The optimizer now treats some previously unrecognized identical literals as identical. Bugfixes: diff --git a/libyul/optimiser/BlockHasher.cpp b/libyul/optimiser/BlockHasher.cpp index d5febca93..9d6db2066 100644 --- a/libyul/optimiser/BlockHasher.cpp +++ b/libyul/optimiser/BlockHasher.cpp @@ -49,7 +49,6 @@ void ASTHasherBase::hashLiteral(solidity::yul::Literal const& _literal) else hash64(std::hash{}(_literal.value.builtinStringLiteralValue())); hash64(_literal.type.hash()); - hash8(static_cast(_literal.kind)); hash8(_literal.value.unlimited()); } diff --git a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol index 097c7b4d1..e3490e2db 100644 --- a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol @@ -46,7 +46,7 @@ contract C { } // ---- // test() -> 0x20, 0x14, "[a called][b called]" -// gas irOptimized: 116530 +// gas irOptimized: 116531 // gas legacy: 118845 // gas legacyOptimized: 116844 // test2() -> 0x20, 0x14, "[b called][a called]" diff --git a/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation.yul b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation.yul index 77df0ae20..9d70f75d2 100644 --- a/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation.yul +++ b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation.yul @@ -12,7 +12,7 @@ // { // f() // f() -// h() +// f() // function f() // { // mstore(29400335157912315244266070412362164103369332044010299463143527189509193072640, mload(0x00)) diff --git a/test/libyul/yulOptimizerTests/fullSuite/devcon_example.yul b/test/libyul/yulOptimizerTests/fullSuite/devcon_example.yul index fca4a6366..5efebed09 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/devcon_example.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/devcon_example.yul @@ -25,7 +25,7 @@ // let sum := 0 // let length := calldataload(_1) // let i := 0 -// for { } true { i := add(i, 1) } +// for { } 1 { i := add(i, 1) } // { // let _2 := iszero(lt(i, length)) // if _2 { break } diff --git a/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul b/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul index 76d671bfc..a0be61939 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul @@ -29,7 +29,7 @@ // let length := calldataload(_1) // let i := 0 // let _2 := calldataload(7) -// for { } true { i := add(i, 1) } +// for { } 1 { i := add(i, 1) } // { // let _3 := iszero(lt(i, length)) // if _3 { break } From 2696cff8da228924b7ece37986b124b67c52acb1 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 2 Jul 2024 18:28:09 +0200 Subject: [PATCH 0194/1340] Relax memory safety. Co-authored-by: Moritz Hoffmann --- docs/assembly.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/assembly.rst b/docs/assembly.rst index cf2ce1bf9..04742c504 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -377,3 +377,18 @@ of Solidity, you can use a special comment to annotate an assembly block as memo Note that we will disallow the annotation via comment in a future breaking release; so, if you are not concerned with backward-compatibility with older compiler versions, prefer using the dialect string. + +Advanced Safe Use of Memory +--------------------------- + +Beyond the strict definition of memory-safety given above, there are cases in which you may want to use more than 64 bytes +of scratch space starting at memory offset ``0``. If you are careful, it can be admissible to use memory up to (and not +including) offset ``0x80`` and still safely declare the assembly block as ``memory-safe``. +This is admissible under either of the following conditions: + +- By the end of the assembly block, the free memory pointer at offset ``0x40`` is restored to a sane value (i.e. it is either + restored to its original value or an increment of it due to a manual memory allocation), and the memory word at offset ``0x60`` + is restored to a value of zero. + +- The assembly block terminates, i.e. execution can never return to high-level Solidity code. This is the case, for example, + if your assembly block unconditionally ends in a ``revert`` statement. From 22471ea5ae41a674cd8a8e420780b7841dfda283 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 4 Jul 2024 13:27:12 +0200 Subject: [PATCH 0195/1340] More details about the zero pointer. --- docs/assembly.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/assembly.rst b/docs/assembly.rst index 04742c504..f57b1f0d9 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -392,3 +392,9 @@ This is admissible under either of the following conditions: - The assembly block terminates, i.e. execution can never return to high-level Solidity code. This is the case, for example, if your assembly block unconditionally ends in a ``revert`` statement. + +Furthermore, you need to be aware that the default-value of dynamic arrays in Solidity point to memory offset ``0x60``, so +for the duration of temporarily changing the value at memory offset ``0x60``, you can no longer rely on getting accurate +length values when reading dynamic arrays, until you restore the zero value at ``0x60``. To be more precise, we only guarantee +safety when overwriting the zero pointer, if the remainder of the assembly snippet does not interact with the memory of +high-level Solidity objects (including by reading from offsets previously stored in variables). From 318259c5f883cba10dca3ef2ebd039c93c732e63 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 4 Jul 2024 13:40:03 +0200 Subject: [PATCH 0196/1340] Phrasing. --- docs/assembly.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/assembly.rst b/docs/assembly.rst index f57b1f0d9..34085bccb 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -391,7 +391,7 @@ This is admissible under either of the following conditions: is restored to a value of zero. - The assembly block terminates, i.e. execution can never return to high-level Solidity code. This is the case, for example, - if your assembly block unconditionally ends in a ``revert`` statement. + if your assembly block unconditionally ends in calling the ``revert`` opcode. Furthermore, you need to be aware that the default-value of dynamic arrays in Solidity point to memory offset ``0x60``, so for the duration of temporarily changing the value at memory offset ``0x60``, you can no longer rely on getting accurate From 60eb07376f30cee8dc533b67eedacd3b533c6ac7 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 5 Jul 2024 10:59:55 +0200 Subject: [PATCH 0197/1340] SMTChecker: Move formatting methods out of Predicate Some of the methods related to formatting SMT expressions do not depend on anything from the predicate, so we can make them free and move to more appropriate place. --- libsolidity/formal/ExpressionFormatter.cpp | 176 ++++++++++++++++++++- libsolidity/formal/ExpressionFormatter.h | 11 +- libsolidity/formal/Predicate.cpp | 166 +------------------ libsolidity/formal/Predicate.h | 6 - 4 files changed, 184 insertions(+), 175 deletions(-) diff --git a/libsolidity/formal/ExpressionFormatter.cpp b/libsolidity/formal/ExpressionFormatter.cpp index 5a3d11dbe..6571cf6dd 100644 --- a/libsolidity/formal/ExpressionFormatter.cpp +++ b/libsolidity/formal/ExpressionFormatter.cpp @@ -18,13 +18,13 @@ #include +#include + #include #include #include -#include - #include #include #include @@ -182,4 +182,176 @@ std::string toSolidityStr(smtutil::Expression const& _expr) return op + "(" + boost::algorithm::join(strArgs, ", ") + ")"; } +namespace +{ +bool fillArray(smtutil::Expression const& _expr, std::vector& _array, ArrayType const& _type) +{ + // Base case + if (_expr.name == "const_array") + { + auto length = _array.size(); + std::optional elemStr = expressionToString(_expr.arguments.at(1), _type.baseType()); + if (!elemStr) + return false; + _array.clear(); + _array.resize(length, *elemStr); + return true; + } + + // Recursive case. + if (_expr.name == "store") + { + if (!fillArray(_expr.arguments.at(0), _array, _type)) + return false; + std::optional indexStr = expressionToString(_expr.arguments.at(1), TypeProvider::uint256()); + if (!indexStr) + return false; + // Sometimes the solver assigns huge lengths that are not related, + // we should catch and ignore those. + unsigned long index; + try + { + index = stoul(*indexStr); + } + catch (std::out_of_range const&) + { + return true; + } + catch (std::invalid_argument const&) + { + return true; + } + std::optional elemStr = expressionToString(_expr.arguments.at(2), _type.baseType()); + if (!elemStr) + return false; + if (index < _array.size()) + _array.at(index) = *elemStr; + return true; + } + + // Special base case, not supported yet. + if (_expr.name.rfind("(_ as-array") == 0) + { + // Z3 expression representing reinterpretation of a different term as an array + return false; + } + + solAssert(false); +} +} + +std::optional expressionToString(smtutil::Expression const& _expr, frontend::Type const* _type) +{ + if (smt::isNumber(*_type)) + { + solAssert(_expr.sort->kind == Kind::Int); + solAssert(_expr.arguments.empty()); + + if ( + _type->category() == frontend::Type::Category::Address || + _type->category() == frontend::Type::Category::FixedBytes + ) + { + try + { + if (_expr.name == "0") + return "0x0"; + // For some reason the code below returns "0x" for "0". + return util::toHex(toCompactBigEndian(bigint(_expr.name)), util::HexPrefix::Add, util::HexCase::Lower); + } + catch (std::out_of_range const&) + { + } + catch (std::invalid_argument const&) + { + } + } + + return _expr.name; + } + if (smt::isBool(*_type)) + { + solAssert(_expr.sort->kind == Kind::Bool); + solAssert(_expr.arguments.empty()); + solAssert(_expr.name == "true" || _expr.name == "false"); + return _expr.name; + } + if (smt::isFunction(*_type)) + { + solAssert(_expr.arguments.empty()); + return _expr.name; + } + if (smt::isArray(*_type)) + { + auto const& arrayType = dynamic_cast(*_type); + if (_expr.name != "tuple_constructor") + return {}; + + auto const& tupleSort = dynamic_cast(*_expr.sort); + solAssert(tupleSort.components.size() == 2); + + unsigned long length; + try + { + length = stoul(_expr.arguments.at(1).name); + } + catch(std::out_of_range const&) + { + return {}; + } + catch(std::invalid_argument const&) + { + return {}; + } + + // Limit this counterexample size to 1k. + // Some OSs give you "unlimited" memory through swap and other virtual memory, + // so purely relying on bad_alloc being thrown is not a good idea. + // In that case, the array allocation might cause OOM and the program is killed. + if (length >= 1024) + return {}; + try + { + std::vector array(length); + if (!fillArray(_expr.arguments.at(0), array, arrayType)) + return {}; + return "[" + boost::algorithm::join(array, ", ") + "]"; + } + catch (std::bad_alloc const&) + { + // Solver gave a concrete array but length is too large. + } + } + if (smt::isNonRecursiveStruct(*_type)) + { + auto const& structType = dynamic_cast(*_type); + solAssert(_expr.name == "tuple_constructor"); + auto const& tupleSort = dynamic_cast(*_expr.sort); + auto members = structType.structDefinition().members(); + solAssert(tupleSort.components.size() == members.size()); + solAssert(_expr.arguments.size() == members.size()); + std::vector elements; + for (unsigned i = 0; i < members.size(); ++i) + { + std::optional elementStr = expressionToString(_expr.arguments.at(i), members[i]->type()); + elements.push_back(members[i]->name() + (elementStr.has_value() ? ": " + elementStr.value() : "")); + } + return "{" + boost::algorithm::join(elements, ", ") + "}"; + } + + return {}; +} + +std::vector> formatExpressions( + std::vector const& _exprs, + std::vector const& _types +) +{ + solAssert(_exprs.size() == _types.size()); + std::vector> strExprs; + for (unsigned i = 0; i < _exprs.size(); ++i) + strExprs.push_back(expressionToString(_exprs.at(i), _types.at(i))); + return strExprs; +} + } diff --git a/libsolidity/formal/ExpressionFormatter.h b/libsolidity/formal/ExpressionFormatter.h index 3efbeb781..e42fab26e 100644 --- a/libsolidity/formal/ExpressionFormatter.h +++ b/libsolidity/formal/ExpressionFormatter.h @@ -19,10 +19,12 @@ #pragma once /** - * Formats SMT expressions into Solidity-like strings. + * Helper methods for formatting SMT expressions */ -#include +#include + +#include #include #include @@ -38,4 +40,9 @@ smtutil::Expression substitute(smtutil::Expression _from, std::map expressionToString(smtutil::Expression const& _expr, Type const* _type); + +/// @returns the formatted version of the given SMT expressions. Those expressions must be SMT constants. +std::vector> formatExpressions(std::vector const& _exprs, std::vector const& _types); } diff --git a/libsolidity/formal/Predicate.cpp b/libsolidity/formal/Predicate.cpp index 75314d7e9..5cac3a6a9 100644 --- a/libsolidity/formal/Predicate.cpp +++ b/libsolidity/formal/Predicate.cpp @@ -18,6 +18,7 @@ #include +#include #include #include @@ -485,171 +486,6 @@ std::map Predicate::expressionSubstitution(smtutil::Ex return subst; } -std::vector> Predicate::formatExpressions(std::vector const& _exprs, std::vector const& _types) const -{ - solAssert(_exprs.size() == _types.size(), ""); - std::vector> strExprs; - for (unsigned i = 0; i < _exprs.size(); ++i) - strExprs.push_back(expressionToString(_exprs.at(i), _types.at(i))); - return strExprs; -} - -std::optional Predicate::expressionToString(smtutil::Expression const& _expr, Type const* _type) const -{ - if (smt::isNumber(*_type)) - { - solAssert(_expr.sort->kind == Kind::Int, ""); - solAssert(_expr.arguments.empty(), ""); - - if ( - _type->category() == Type::Category::Address || - _type->category() == Type::Category::FixedBytes - ) - { - try - { - if (_expr.name == "0") - return "0x0"; - // For some reason the code below returns "0x" for "0". - return util::toHex(toCompactBigEndian(bigint(_expr.name)), util::HexPrefix::Add, util::HexCase::Lower); - } - catch (std::out_of_range const&) - { - } - catch (std::invalid_argument const&) - { - } - } - - return _expr.name; - } - if (smt::isBool(*_type)) - { - solAssert(_expr.sort->kind == Kind::Bool, ""); - solAssert(_expr.arguments.empty(), ""); - solAssert(_expr.name == "true" || _expr.name == "false", ""); - return _expr.name; - } - if (smt::isFunction(*_type)) - { - solAssert(_expr.arguments.empty(), ""); - return _expr.name; - } - if (smt::isArray(*_type)) - { - auto const& arrayType = dynamic_cast(*_type); - if (_expr.name != "tuple_constructor") - return {}; - - auto const& tupleSort = dynamic_cast(*_expr.sort); - solAssert(tupleSort.components.size() == 2, ""); - - unsigned long length; - try - { - length = stoul(_expr.arguments.at(1).name); - } - catch(std::out_of_range const&) - { - return {}; - } - catch(std::invalid_argument const&) - { - return {}; - } - - // Limit this counterexample size to 1k. - // Some OSs give you "unlimited" memory through swap and other virtual memory, - // so purely relying on bad_alloc being thrown is not a good idea. - // In that case, the array allocation might cause OOM and the program is killed. - if (length >= 1024) - return {}; - try - { - std::vector array(length); - if (!fillArray(_expr.arguments.at(0), array, arrayType)) - return {}; - return "[" + boost::algorithm::join(array, ", ") + "]"; - } - catch (std::bad_alloc const&) - { - // Solver gave a concrete array but length is too large. - } - } - if (smt::isNonRecursiveStruct(*_type)) - { - auto const& structType = dynamic_cast(*_type); - solAssert(_expr.name == "tuple_constructor", ""); - auto const& tupleSort = dynamic_cast(*_expr.sort); - auto members = structType.structDefinition().members(); - solAssert(tupleSort.components.size() == members.size(), ""); - solAssert(_expr.arguments.size() == members.size(), ""); - std::vector elements; - for (unsigned i = 0; i < members.size(); ++i) - { - std::optional elementStr = expressionToString(_expr.arguments.at(i), members[i]->type()); - elements.push_back(members[i]->name() + (elementStr.has_value() ? ": " + elementStr.value() : "")); - } - return "{" + boost::algorithm::join(elements, ", ") + "}"; - } - - return {}; -} - -bool Predicate::fillArray(smtutil::Expression const& _expr, std::vector& _array, ArrayType const& _type) const -{ - // Base case - if (_expr.name == "const_array") - { - auto length = _array.size(); - std::optional elemStr = expressionToString(_expr.arguments.at(1), _type.baseType()); - if (!elemStr) - return false; - _array.clear(); - _array.resize(length, *elemStr); - return true; - } - - // Recursive case. - if (_expr.name == "store") - { - if (!fillArray(_expr.arguments.at(0), _array, _type)) - return false; - std::optional indexStr = expressionToString(_expr.arguments.at(1), TypeProvider::uint256()); - if (!indexStr) - return false; - // Sometimes the solver assigns huge lengths that are not related, - // we should catch and ignore those. - unsigned long index; - try - { - index = stoul(*indexStr); - } - catch (std::out_of_range const&) - { - return true; - } - catch (std::invalid_argument const&) - { - return true; - } - std::optional elemStr = expressionToString(_expr.arguments.at(2), _type.baseType()); - if (!elemStr) - return false; - if (index < _array.size()) - _array.at(index) = *elemStr; - return true; - } - - // Special base case, not supported yet. - if (_expr.name.rfind("(_ as-array") == 0) - { - // Z3 expression representing reinterpretation of a different term as an array - return false; - } - - solAssert(false, ""); -} std::map> Predicate::readTxVars(smtutil::Expression const& _tx) const { diff --git a/libsolidity/formal/Predicate.h b/libsolidity/formal/Predicate.h index a7df44621..f389ab822 100644 --- a/libsolidity/formal/Predicate.h +++ b/libsolidity/formal/Predicate.h @@ -184,12 +184,6 @@ class Predicate std::map expressionSubstitution(smtutil::Expression const& _predExprs) const; private: - /// @returns the formatted version of the given SMT expressions. Those expressions must be SMT constants. - std::vector> formatExpressions(std::vector const& _exprs, std::vector const& _types) const; - - /// @returns a string representation of the SMT expression based on a Solidity type. - std::optional expressionToString(smtutil::Expression const& _expr, Type const* _type) const; - /// Recursively fills _array from _expr. /// _expr should have the form `store(store(...(const_array(x_0), i_0, e_0), i_m, e_m), i_k, e_k)`. /// @returns true if the construction worked, From 08a98d1914d127dbc755cb20c789ab3a90f9066e Mon Sep 17 00:00:00 2001 From: Meet Mangukiya Date: Sun, 7 Jul 2024 15:19:57 +0530 Subject: [PATCH 0198/1340] OptimizedEVMCodeTransform: tag source location in stack too deep errors in yul --- libyul/backends/evm/OptimizedEVMCodeTransform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 047014e3d..8731f2cc5 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -275,7 +275,7 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr varNameDeep.empty() ? varNameTop : varNameDeep, deficit, msg - )); + ) << langutil::errinfo_sourceLocation(sourceLocation)); m_assembly.markAsInvalid(); } }, From 4c857f50ccd73c86b0d1f0b17cc4be298bd99058 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Tue, 9 Jul 2024 16:45:27 +0200 Subject: [PATCH 0199/1340] SMTChecker: Increase Z3 resource limit Increasing resource limit of z3 results in more SMTChecker tests correctly solved, without increasing the running time significantly. This is in preparation for switching z3 to SMT-LIB interface, so as to not have significant changes in tests for that switch. --- libsmtutil/Z3Interface.h | 2 +- .../abi_encode_with_selector_array_slice.sol | 4 +-- ...abi_encode_with_selector_array_slice_2.sol | 4 +-- .../deployment/deploy_trusted_flow.sol | 10 ++----- .../external_call_indirect_1.sol | 2 +- .../external_call_indirect_3.sol | 3 +- .../external_call_indirect_4.sol | 3 +- .../external_call_indirect_5.sol | 2 +- ..._loop_array_assignment_storage_storage.sol | 10 +++---- .../operators/index_access_side_effect.sol | 4 +-- .../operators/slice_default_start.sol | 7 ++--- ...rator_matches_equivalent_function_call.sol | 28 ++----------------- .../smtCheckerTests/out_of_bounds/array_1.sol | 7 ++--- 13 files changed, 22 insertions(+), 64 deletions(-) diff --git a/libsmtutil/Z3Interface.h b/libsmtutil/Z3Interface.h index ee268ac41..d5dc5792e 100644 --- a/libsmtutil/Z3Interface.h +++ b/libsmtutil/Z3Interface.h @@ -55,7 +55,7 @@ class Z3Interface: public SolverInterface // Z3 "basic resources" limit. // This is used to make the runs more deterministic and platform/machine independent. - static int const resourceLimit = 1000000; + static int const resourceLimit = 2000000; private: void declareFunction(std::string const& _name, Sort const& _sort); diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol index 67c8b92e6..ed6f627b5 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol @@ -28,6 +28,4 @@ contract C { // ---- // Warning 6328: (325-355): CHC: Assertion violation happens here. // Warning 6328: (578-608): CHC: Assertion violation happens here. -// Warning 6328: (1079-1109): CHC: Assertion violation might happen here. -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 4661: (1079-1109): BMC: Assertion violation happens here. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol index 69a3482b1..c13e9ce07 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol @@ -28,6 +28,4 @@ contract C { // ---- // Warning 6328: (326-356): CHC: Assertion violation happens here. // Warning 6328: (579-609): CHC: Assertion violation happens here. -// Warning 6328: (1080-1110): CHC: Assertion violation might happen here. -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 4661: (1080-1110): BMC: Assertion violation happens here. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol index 2148324ad..60f3c9415 100644 --- a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol @@ -18,13 +18,9 @@ contract C { // ==== // SMTEngine: all // SMTExtCalls: trusted -// SMTIgnoreOS: macos // ---- // Warning 4984: (47-50): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 6328: (215-233): CHC: Assertion violation might happen here. -// Warning 6328: (267-285): CHC: Assertion violation might happen here. -// Warning 6328: (304-322): CHC: Assertion violation happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (304-322): CHC: Assertion violation might happen here. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. // Warning 2661: (47-50): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4661: (215-233): BMC: Assertion violation happens here. -// Warning 4661: (267-285): BMC: Assertion violation happens here. +// Warning 4661: (304-322): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol index c6b46b2f8..dd8a529a2 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol @@ -38,5 +38,5 @@ contract C { // SMTIgnoreOS: macos // ---- // Warning 6328: (256-277): CHC: Assertion violation happens here. -// Warning 6328: (533-554): CHC: Assertion violation might happen here. +// Warning 6328: (533-554): CHC: Assertion violation happens here. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol index ff17649dd..d7721037f 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol @@ -40,7 +40,6 @@ contract C { // ==== // SMTEngine: chc // SMTExtCalls: trusted -// SMTIgnoreOS: macos // ---- -// Warning 6328: (561-582): CHC: Assertion violation might happen here. +// Warning 6328: (561-582): CHC: Assertion violation happens here. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_4.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_4.sol index 766f6e133..96adba884 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_4.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_4.sol @@ -43,7 +43,6 @@ contract C { // ==== // SMTEngine: chc // SMTExtCalls: trusted -// SMTIgnoreOS: macos // ---- -// Warning 6328: (641-662): CHC: Assertion violation might happen here. +// Warning 6328: (641-662): CHC: Assertion violation happens here. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol index 9313858ce..26d39838e 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol @@ -47,5 +47,5 @@ contract C { // SMTEngine: chc // SMTExtCalls: trusted // ---- -// Warning 6328: (601-622): CHC: Assertion violation might happen here. +// Warning 6328: (601-622): CHC: Assertion violation happens here. // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_storage_storage.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_storage_storage.sol index ed7ebdfba..4bfd17500 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_storage_storage.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_storage_storage.sol @@ -23,10 +23,8 @@ contract LoopFor2 { } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTTargets: assert // ---- -// Warning 6368: (288-292): CHC: Out of bounds access might happen here. -// Warning 6368: (459-463): CHC: Out of bounds access happens here. -// Warning 6328: (452-471): CHC: Assertion violation happens here. -// Warning 6328: (475-494): CHC: Assertion violation happens here. -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (452-471): CHC: Assertion violation happens here.\nCounterexample:\nb = [1, 0], c = [0, 0]\nn = 1\ni = 1\n\nTransaction trace:\nLoopFor2.constructor()\nState: b = [], c = []\nLoopFor2.p()\nState: b = [0], c = [0]\nLoopFor2.p()\nState: b = [0, 0], c = [0, 0]\nLoopFor2.testUnboundedForLoop(1) +// Warning 6328: (475-494): CHC: Assertion violation happens here.\nCounterexample:\nb = [1, 0], c = [0, 0]\nn = 1\ni = 1\n\nTransaction trace:\nLoopFor2.constructor()\nState: b = [], c = []\nLoopFor2.p()\nState: b = [0], c = [0]\nLoopFor2.p()\nState: b = [0, 0], c = [0, 0]\nLoopFor2.testUnboundedForLoop(1) diff --git a/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol b/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol index d3b6f5895..644ecdb12 100644 --- a/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol +++ b/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol @@ -22,6 +22,4 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 6328: (335-354): CHC: Assertion violation might happen here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 4661: (335-354): BMC: Assertion violation happens here. +// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/slice_default_start.sol b/test/libsolidity/smtCheckerTests/operators/slice_default_start.sol index ef422245d..c4da3b4b6 100644 --- a/test/libsolidity/smtCheckerTests/operators/slice_default_start.sol +++ b/test/libsolidity/smtCheckerTests/operators/slice_default_start.sol @@ -10,8 +10,5 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (150-182): CHC: Assertion violation might happen here. -// Warning 6328: (186-218): CHC: Assertion violation might happen here. -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 4661: (150-182): BMC: Assertion violation happens here. -// Warning 4661: (186-218): BMC: Assertion violation happens here. +// Warning 6328: (186-218): CHC: Assertion violation happens here. +// Info 1391: CHC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol index 206c63042..76ad6db55 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol @@ -53,32 +53,10 @@ contract C { } // ==== // SMTEngine: all +// SMTTargets: assert // ---- -// Warning 3944: (679-708): CHC: Underflow (resulting value less than -32768) might happen here. -// Warning 4984: (679-708): CHC: Overflow (resulting value larger than 32767) might happen here. -// Warning 3944: (777-806): CHC: Underflow (resulting value less than -32768) might happen here. -// Warning 4984: (777-806): CHC: Overflow (resulting value larger than 32767) might happen here. -// Warning 3944: (870-884): CHC: Underflow (resulting value less than -32768) might happen here. -// Warning 4984: (870-884): CHC: Overflow (resulting value larger than 32767) might happen here. -// Warning 3944: (953-982): CHC: Underflow (resulting value less than -32768) might happen here. -// Warning 4984: (953-982): CHC: Overflow (resulting value larger than 32767) might happen here. -// Warning 4984: (1051-1080): CHC: Overflow (resulting value larger than 32767) might happen here. -// Warning 4281: (1051-1080): CHC: Division by zero might happen here. -// Warning 4281: (1149-1178): CHC: Division by zero might happen here. -// Warning 6328: (2069-2095): CHC: Assertion violation might happen here. -// Warning 6328: (2105-2131): CHC: Assertion violation might happen here. -// Warning 6328: (2141-2163): CHC: Assertion violation might happen here. -// Warning 6328: (2173-2199): CHC: Assertion violation might happen here. // Warning 6328: (2209-2235): CHC: Assertion violation might happen here. // Warning 6328: (2245-2271): CHC: Assertion violation might happen here. -// Info 1391: CHC: 10 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 2661: (679-708): BMC: Overflow (resulting value larger than 32767) happens here. -// Warning 4144: (679-708): BMC: Underflow (resulting value less than -32768) happens here. -// Warning 2661: (777-806): BMC: Overflow (resulting value larger than 32767) happens here. -// Warning 4144: (777-806): BMC: Underflow (resulting value less than -32768) happens here. -// Warning 2661: (953-982): BMC: Overflow (resulting value larger than 32767) happens here. -// Warning 4144: (953-982): BMC: Underflow (resulting value less than -32768) happens here. -// Warning 3046: (1051-1080): BMC: Division by zero happens here. -// Warning 3046: (1149-1178): BMC: Division by zero happens here. +// Info 1391: CHC: 14 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. // Warning 7812: (2245-2271): BMC: Assertion violation might happen here. -// Info 6002: BMC: 14 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol b/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol index 65a1dfd39..c52599b03 100644 --- a/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol +++ b/test/libsolidity/smtCheckerTests/out_of_bounds/array_1.sol @@ -18,9 +18,6 @@ contract C { } // ==== // SMTEngine: all -// SMTIgnoreOS: macos +// SMTTargets: outOfBounds // ---- -// Warning 4984: (112-115): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 6368: (259-263): CHC: Out of bounds access happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 2661: (112-115): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. +// Warning 6368: (259-263): CHC: Out of bounds access happens here.\nCounterexample:\na = [0], l = 1\n = 0\n\nTransaction trace:\nC.constructor()\nState: a = [], l = 0\nC.p()\nState: a = [0], l = 1\nC.r() From e0c58e539cebdc9a1de8ae1d27bdb69311b5418c Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 10 Jul 2024 16:37:04 +0200 Subject: [PATCH 0200/1340] SMTChecker: Simplify some of the long running tests --- .../smtCheckerTests/abi/abi_decode_array.sol | 20 +++++++------------ .../smtCheckerTests/types/array_branch_3d.sol | 4 ++-- .../array_struct_array_struct_memory_safe.sol | 3 ++- ...array_struct_array_struct_storage_safe.sol | 3 ++- .../smtCheckerTests/types/type_minmax.sol | 11 +--------- .../types/type_simple_range.sol | 14 +++++++++++++ 6 files changed, 28 insertions(+), 27 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/types/type_simple_range.sol diff --git a/test/libsolidity/smtCheckerTests/abi/abi_decode_array.sol b/test/libsolidity/smtCheckerTests/abi/abi_decode_array.sol index da30d302f..c7db3645a 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_decode_array.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_decode_array.sol @@ -7,9 +7,7 @@ contract C { (uint[] memory c, uint[] memory d) = abi.decode(b1, (uint[], uint[])); assert(a.length == c.length); - assert(a.length == d.length); // should fail assert(b.length == d.length); - assert(b.length == c.length); // should fail (uint[] memory e, uint[] memory f, uint[] memory g) = abi.decode(b1, (uint[], uint[], uint[])); assert(e.length == a.length); // should fail @@ -24,7 +22,6 @@ contract C { (uint[] memory k, uint[] memory l) = abi.decode(b2, (uint[], uint[])); assert(k.length == a.length); // should fail - assert(k.length == l.length); // should fail assert(l.length == b.length); // should fail } } @@ -32,14 +29,11 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 6328: (182-210): CHC: Assertion violation happens here. -// Warning 6328: (335-363): CHC: Assertion violation happens here. -// Warning 6328: (414-442): CHC: Assertion violation happens here. -// Warning 6328: (560-588): CHC: Assertion violation happens here. -// Warning 6328: (607-635): CHC: Assertion violation happens here. -// Warning 6328: (654-682): CHC: Assertion violation happens here. -// Warning 6328: (879-916): CHC: Assertion violation happens here. -// Warning 6328: (1009-1037): CHC: Assertion violation happens here. -// Warning 6328: (1056-1084): CHC: Assertion violation happens here. -// Warning 6328: (1103-1131): CHC: Assertion violation happens here. +// Warning 6328: (182-210): CHC: Assertion violation happens here.\nCounterexample:\n\nc = []\nd = []\ne = []\nf = []\ng = []\nh = []\ni = []\nj = 0\nk = []\nl = []\n\nTransaction trace:\nC.constructor()\nC.abiDecodeArray(b1, b2) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (466-494): CHC: Assertion violation happens here.\nCounterexample:\n\nf = [83, 83, 83, 83, 83, 83, 67, 83, 83, 83, 83, 83, 70, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 72, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 71, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83]\ng = [65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 55, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 60, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65]\nh = []\ni = []\nj = 0\nk = []\nl = []\n\nTransaction trace:\nC.constructor()\nC.abiDecodeArray(b1, b2) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (513-541): CHC: Assertion violation happens here.\nCounterexample:\n\ng = [65, 65, 65, 65, 65, 65, 65, 64, 65, 47, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 48, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65]\nh = []\ni = []\nj = 0\nk = []\nl = []\n\nTransaction trace:\nC.constructor()\nC.abiDecodeArray(b1, b2) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (560-588): CHC: Assertion violation happens here.\nCounterexample:\n\nb = []\nd = []\nh = []\ni = []\nj = 0\nk = []\nl = []\n\nTransaction trace:\nC.constructor()\nC.abiDecodeArray(b1, b2) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (785-822): CHC: Assertion violation happens here.\nCounterexample:\n\nf = [144]\nj = 8365\nk = []\nl = []\n\nTransaction trace:\nC.constructor()\nC.abiDecodeArray(b1, b2) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (915-943): CHC: Assertion violation happens here.\nCounterexample:\n\nj = 8365\nl = [35, 35, 35, 35, 35]\n\nTransaction trace:\nC.constructor()\nC.abiDecodeArray(b1, b2) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (962-990): CHC: Assertion violation happens here.\nCounterexample:\n\nj = 32285\n\nTransaction trace:\nC.constructor()\nC.abiDecodeArray(b1, b2) -- counterexample incomplete; parameter name used instead of value // Info 1391: CHC: 6 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/array_branch_3d.sol b/test/libsolidity/smtCheckerTests/types/array_branch_3d.sol index 3aced164c..6c6404c11 100644 --- a/test/libsolidity/smtCheckerTests/types/array_branch_3d.sol +++ b/test/libsolidity/smtCheckerTests/types/array_branch_3d.sol @@ -15,6 +15,6 @@ contract C // ==== // SMTEngine: chc // SMTSolvers: eld +// SMTTargets: assert // ---- -// Warning 6328: (152-174): CHC: Assertion violation happens here. -// Info 1391: CHC: 9 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (152-174): CHC: Assertion violation happens here.\nCounterexample:\nc = [[[0]]]\nb = false\n\nTransaction trace:\nC.constructor()\nState: c = [[[0]]]\nC.f(false) diff --git a/test/libsolidity/smtCheckerTests/types/struct/array_struct_array_struct_memory_safe.sol b/test/libsolidity/smtCheckerTests/types/struct/array_struct_array_struct_memory_safe.sol index bc5ddf49e..972c77970 100644 --- a/test/libsolidity/smtCheckerTests/types/struct/array_struct_array_struct_memory_safe.sol +++ b/test/libsolidity/smtCheckerTests/types/struct/array_struct_array_struct_memory_safe.sol @@ -32,5 +32,6 @@ contract C { } // ==== // SMTEngine: all +// SMTTargets: assert // ---- -// Info 1391: CHC: 29 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 6 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/struct/array_struct_array_struct_storage_safe.sol b/test/libsolidity/smtCheckerTests/types/struct/array_struct_array_struct_storage_safe.sol index b2f7b9825..ce5f375c4 100644 --- a/test/libsolidity/smtCheckerTests/types/struct/array_struct_array_struct_storage_safe.sol +++ b/test/libsolidity/smtCheckerTests/types/struct/array_struct_array_struct_storage_safe.sol @@ -52,5 +52,6 @@ contract C { } // ==== // SMTEngine: all +// SMTTargets: assert // ---- -// Info 1391: CHC: 51 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 5 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/type_minmax.sol b/test/libsolidity/smtCheckerTests/types/type_minmax.sol index da9bb1b6d..eb739c5e9 100644 --- a/test/libsolidity/smtCheckerTests/types/type_minmax.sol +++ b/test/libsolidity/smtCheckerTests/types/type_minmax.sol @@ -1,12 +1,4 @@ contract C { - function f(uint a) public pure { - assert(a <= type(uint).max); - assert(a >= type(uint).min); - require(a <= type(uint64).max); - assert(a <= type(uint64).max); - assert(a <= type(uint32).max); - } - function int_min() public pure { int8 int8_min = type(int8).min; assert(int8_min == -2**7); @@ -81,5 +73,4 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (178-207): CHC: Assertion violation happens here. -// Info 1391: CHC: 24 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 21 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/type_simple_range.sol b/test/libsolidity/smtCheckerTests/types/type_simple_range.sol new file mode 100644 index 000000000..579b232d7 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/type_simple_range.sol @@ -0,0 +1,14 @@ +contract C { + function f(uint a) public pure { + assert(a <= type(uint).max); + assert(a >= type(uint).min); + require(a <= type(uint64).max); + assert(a <= type(uint64).max); + assert(a <= type(uint32).max); // should fail + } +} +// ==== +// SMTEngine: all +// ---- +// Warning 6328: (178-207): CHC: Assertion violation happens here.\nCounterexample:\n\na = 4294967296\n\nTransaction trace:\nC.constructor()\nC.f(4294967296) +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 54686862ece4f0e3430600849a7a69df57cf68ac Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 10 Jul 2024 14:55:07 +0200 Subject: [PATCH 0201/1340] Yul: Add const version of FunctionCallFinder --- libyul/backends/evm/EVMObjectCompiler.cpp | 4 +-- libyul/optimiser/FullInliner.cpp | 2 +- libyul/optimiser/FunctionCallFinder.cpp | 41 ++++++++++++++++++----- libyul/optimiser/FunctionCallFinder.h | 24 ++++++------- libyul/optimiser/StackLimitEvader.cpp | 4 +-- test/libsolidity/MemoryGuardTest.cpp | 2 +- 6 files changed, 49 insertions(+), 28 deletions(-) diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index 28b72c087..0bd064940 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -90,8 +90,8 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) ); if (!stackErrors.empty()) { - std::vector memoryGuardCalls = FunctionCallFinder::run( - *_object.code, + std::vector memoryGuardCalls = findFunctionCalls( + std::as_const(*_object.code), "memoryguard"_yulstring ); auto stackError = stackErrors.front(); diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index 6e4d84971..3bf00282c 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -83,7 +83,7 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& } // Check for memory guard. - std::vector memoryGuardCalls = FunctionCallFinder::run( + std::vector memoryGuardCalls = findFunctionCalls( _ast, "memoryguard"_yulstring ); diff --git a/libyul/optimiser/FunctionCallFinder.cpp b/libyul/optimiser/FunctionCallFinder.cpp index 9d94dc5f9..99f171026 100644 --- a/libyul/optimiser/FunctionCallFinder.cpp +++ b/libyul/optimiser/FunctionCallFinder.cpp @@ -16,23 +16,46 @@ */ #include + +#include #include using namespace solidity; using namespace solidity::yul; -std::vector FunctionCallFinder::run(Block& _block, YulString _functionName) +namespace +{ +template +class MaybeConstFunctionCallFinder: Base { - FunctionCallFinder functionCallFinder(_functionName); - functionCallFinder(_block); - return functionCallFinder.m_calls; +public: + using MaybeConstBlock = std::conditional_t, Block const, Block>; + static std::vector run(MaybeConstBlock& _block, YulString const _functionName) + { + MaybeConstFunctionCallFinder functionCallFinder(_functionName); + functionCallFinder(_block); + return functionCallFinder.m_calls; + } +private: + explicit MaybeConstFunctionCallFinder(YulString const _functionName): m_functionName(_functionName), m_calls() {} + using Base::operator(); + void operator()(ResultType& _functionCall) override + { + Base::operator()(_functionCall); + if (_functionCall.functionName.name == m_functionName) + m_calls.emplace_back(&_functionCall); + } + YulString m_functionName; + std::vector m_calls; +}; } -FunctionCallFinder::FunctionCallFinder(YulString _functionName): m_functionName(_functionName) {} +std::vector solidity::yul::findFunctionCalls(Block& _block, YulString _functionName) +{ + return MaybeConstFunctionCallFinder::run(_block, _functionName); +} -void FunctionCallFinder::operator()(FunctionCall& _functionCall) +std::vector solidity::yul::findFunctionCalls(Block const& _block, YulString _functionName) { - ASTModifier::operator()(_functionCall); - if (_functionCall.functionName.name == m_functionName) - m_calls.emplace_back(&_functionCall); + return MaybeConstFunctionCallFinder::run(_block, _functionName); } diff --git a/libyul/optimiser/FunctionCallFinder.h b/libyul/optimiser/FunctionCallFinder.h index 365f86688..a5d4da56e 100644 --- a/libyul/optimiser/FunctionCallFinder.h +++ b/libyul/optimiser/FunctionCallFinder.h @@ -20,7 +20,8 @@ #pragma once -#include +#include +#include #include @@ -28,20 +29,17 @@ namespace solidity::yul { /** - * AST walker that finds all calls to a function of a given name. + * Finds all calls to a function of a given name using an ASTModifier. * * Prerequisite: Disambiguator */ -class FunctionCallFinder: ASTModifier -{ -public: - static std::vector run(Block& _block, YulString _functionName); -private: - FunctionCallFinder(YulString _functionName); - using ASTModifier::operator(); - void operator()(FunctionCall& _functionCall) override; - YulString m_functionName; - std::vector m_calls; -}; +std::vector findFunctionCalls(Block& _block, YulString _functionName); + +/** + * Finds all calls to a function of a given name using an ASTWalker. + * + * Prerequisite: Disambiguator + */ +std::vector findFunctionCalls(Block const& _block, YulString _functionName); } diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 904ee77e0..0310858a1 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -174,7 +174,7 @@ void StackLimitEvader::run( "StackLimitEvader can only be run on objects using the EVMDialect with object access." ); - std::vector memoryGuardCalls = FunctionCallFinder::run( + std::vector memoryGuardCalls = findFunctionCalls( *_object.code, "memoryguard"_yulstring ); @@ -206,7 +206,7 @@ void StackLimitEvader::run( StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, *_object.code); reservedMemory += 32 * requiredSlots; - for (FunctionCall* memoryGuardCall: FunctionCallFinder::run(*_object.code, "memoryguard"_yulstring)) + for (FunctionCall* memoryGuardCall: findFunctionCalls(*_object.code, "memoryguard"_yulstring)) { Literal* literal = std::get_if(&memoryGuardCall->arguments.front()); yulAssert(literal && literal->kind == LiteralKind::Number, ""); diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index 7f0914cc4..caa85c6fd 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -73,7 +73,7 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con } auto handleObject = [&](std::string const& _kind, Object const& _object) { - m_obtainedResult += contractName + "(" + _kind + ") " + (FunctionCallFinder::run( + m_obtainedResult += contractName + "(" + _kind + ") " + (findFunctionCalls( *_object.code, "memoryguard"_yulstring ).empty() ? "false" : "true") + "\n"; From f53bb02c52f7c63e59da8299ab9dc72872c2795f Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 10 Jul 2024 21:46:10 +0200 Subject: [PATCH 0202/1340] SMTChecker: Further test simplifications --- .../deployment/deploy_trusted_flow.sol | 8 +++--- ...code_state_reentrancy_indirect_trusted.sol | 24 +++++++---------- .../external_calls/external_inc.sol | 8 +++--- .../external_calls/external_safe.sol | 5 ++-- .../types/array_branches_3d.sol | 10 ++----- .../types/array_branches_3d_show_unproved.sol | 27 ------------------- .../types/array_static_mapping_aliasing_1.sol | 10 +++---- .../types/array_static_mapping_aliasing_2.sol | 12 +++------ 8 files changed, 29 insertions(+), 75 deletions(-) delete mode 100644 test/libsolidity/smtCheckerTests/types/array_branches_3d_show_unproved.sol diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol index 60f3c9415..4a447d631 100644 --- a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_flow.sol @@ -1,6 +1,6 @@ contract D { uint x; - function inc() public { ++x; } + function inc() public { require(x < 5); ++x; } function f() public view returns (uint) { return x; } } @@ -18,9 +18,7 @@ contract C { // ==== // SMTEngine: all // SMTExtCalls: trusted +// SMTTargets: assert // ---- -// Warning 4984: (47-50): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 6328: (304-322): CHC: Assertion violation might happen here. +// Warning 6328: (320-338): CHC: Assertion violation happens here. // Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 2661: (47-50): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4661: (304-322): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_indirect_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_indirect_trusted.sol index 8000b3267..e689c21b4 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_indirect_trusted.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_indirect_trusted.sol @@ -1,9 +1,5 @@ contract Other { - C c; - constructor(C _c) { - c = _c; - } - function h() public { + function h(C c) public { c.setOwner(address(0)); } } @@ -11,13 +7,11 @@ contract Other { contract State { uint x; Other o; - C c; - constructor(C _c) { - c = _c; - o = new Other(_c); + constructor() { + o = new Other(); } - function f() public returns (uint) { - o.h(); + function f(C c) public returns (uint) { + o.h(c); return c.g(); } } @@ -29,7 +23,7 @@ contract C { constructor() { owner = msg.sender; - s = new State(this); + s = new State(); } function setOwner(address _owner) public { @@ -38,7 +32,7 @@ contract C { function f() public { address prevOwner = owner; - uint z = s.f(); + uint z = s.f(this); assert(z == y); // should hold assert(prevOwner == owner); // should not hold because of reentrancy } @@ -52,5 +46,5 @@ contract C { // SMTEngine: chc // SMTExtCalls: trusted // ---- -// Warning 6328: (531-545): CHC: Assertion violation might happen here. -// Warning 6328: (564-590): CHC: Assertion violation happens here. +// Warning 6328: (509-535): CHC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_inc.sol b/test/libsolidity/smtCheckerTests/external_calls/external_inc.sol index 22a4551c8..117d3fa72 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_inc.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_inc.sol @@ -7,18 +7,18 @@ contract C { D d; function inc() public { + require(x < 10); ++x; } function f() public { d.d(); - assert(x < 10); + assert(x < 5); } } // ==== // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 4984: (113-116): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 6328: (156-170): CHC: Assertion violation happens here. -// Warning 2661: (113-116): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. +// Warning 6328: (175-188): CHC: Assertion violation happens here.\nCounterexample:\nx = 5, d = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0, d = 0\nC.inc()\nState: x = 1, d = 0\nC.inc()\nState: x = 2, d = 0\nC.inc()\nState: x = 3, d = 0\nC.inc()\nState: x = 4, d = 0\nC.f()\n d.d() -- untrusted external call, synthesized as:\n C.inc() -- reentrant call +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol index 593aba289..bfc95b35a 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol @@ -6,16 +6,15 @@ contract C { uint x; D d; function f() public { - if (x < 10) + if (x < 5) ++x; } function g() public { d.d(); - assert(x < 11); + assert(x < 6); } } // ==== // SMTEngine: all -// SMTIgnoreOS: macos // ---- // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/array_branches_3d.sol b/test/libsolidity/smtCheckerTests/types/array_branches_3d.sol index 8e9499183..9dbdde90f 100644 --- a/test/libsolidity/smtCheckerTests/types/array_branches_3d.sol +++ b/test/libsolidity/smtCheckerTests/types/array_branches_3d.sol @@ -15,12 +15,6 @@ contract C } // ==== // SMTEngine: all -// SMTIgnoreOS: macos +// SMTTargets: assert // ---- -// Warning 6368: (124-131): CHC: Out of bounds access might happen here. -// Warning 6368: (124-134): CHC: Out of bounds access might happen here. -// Warning 6368: (152-159): CHC: Out of bounds access might happen here. -// Warning 6368: (152-162): CHC: Out of bounds access might happen here. -// Warning 6368: (177-184): CHC: Out of bounds access might happen here. -// Warning 6368: (177-187): CHC: Out of bounds access might happen here. -// Info 1391: CHC: 7 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/array_branches_3d_show_unproved.sol b/test/libsolidity/smtCheckerTests/types/array_branches_3d_show_unproved.sol deleted file mode 100644 index 7e9aad5b0..000000000 --- a/test/libsolidity/smtCheckerTests/types/array_branches_3d_show_unproved.sol +++ /dev/null @@ -1,27 +0,0 @@ -contract C -{ - uint[][][] c; - constructor() { - c.push(); - c[0].push(); - c[0][0].push(); - } - function f(bool b) public { - c[0][0][0] = 0; - if (b) - c[0][0][0] = 1; - assert(c[0][0][0] < 2); - } -} -// ==== -// SMTEngine: all -// SMTShowUnproved: yes -// SMTIgnoreOS: macos -// ---- -// Warning 6368: (124-131): CHC: Out of bounds access might happen here. -// Warning 6368: (124-134): CHC: Out of bounds access might happen here. -// Warning 6368: (152-159): CHC: Out of bounds access might happen here. -// Warning 6368: (152-162): CHC: Out of bounds access might happen here. -// Warning 6368: (177-184): CHC: Out of bounds access might happen here. -// Warning 6368: (177-187): CHC: Out of bounds access might happen here. -// Info 1391: CHC: 7 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/array_static_mapping_aliasing_1.sol b/test/libsolidity/smtCheckerTests/types/array_static_mapping_aliasing_1.sol index 7ee1acf47..8d727f018 100644 --- a/test/libsolidity/smtCheckerTests/types/array_static_mapping_aliasing_1.sol +++ b/test/libsolidity/smtCheckerTests/types/array_static_mapping_aliasing_1.sol @@ -5,7 +5,6 @@ contract C mapping (uint => uint8)[2] severalMaps8; mapping (uint => uint)[2][2] severalMaps3d; function f(mapping (uint => uint) storage map) internal { - // Accesses are safe but oob is reported because of aliasing. severalMaps[0][0] = 42; severalMaps8[0][0] = 42; severalMaps3d[0][0][0] = 42; @@ -15,8 +14,7 @@ contract C // Should not fail since knowledge is erased only for mapping (uint => uint). assert(severalMaps8[0][0] == 42); // Should fail since map == severalMaps3d[0][0] is possible. - // Removed because current Spacer seg faults in cex generation. - //assert(severalMaps3d[0][0][0] == 42); + assert(severalMaps3d[0][0][0] == 42); } function g(uint x) public { require(x < severalMaps.length); @@ -26,6 +24,8 @@ contract C // ==== // SMTEngine: all // SMTIgnoreCex: yes +// SMTTargets: assert // ---- -// Warning 6328: (456-487): CHC: Assertion violation happens here. -// Info 1391: CHC: 8 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (392-423): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\n\nTransaction trace:\nC.constructor()\nC.g(0)\n C.f(map) -- counterexample incomplete; parameter name used instead of value -- internal call +// Warning 6328: (606-642): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\n\nTransaction trace:\nC.constructor()\nC.g(0)\n C.f(map) -- counterexample incomplete; parameter name used instead of value -- internal call +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/array_static_mapping_aliasing_2.sol b/test/libsolidity/smtCheckerTests/types/array_static_mapping_aliasing_2.sol index 1f167b858..f05487dcb 100644 --- a/test/libsolidity/smtCheckerTests/types/array_static_mapping_aliasing_2.sol +++ b/test/libsolidity/smtCheckerTests/types/array_static_mapping_aliasing_2.sol @@ -5,7 +5,6 @@ contract C mapping (uint => uint8)[2] severalMaps8; mapping (uint => uint)[2][2] severalMaps3d; function f(mapping (uint => uint) storage map) internal { - // Accesses are safe but reported as unsafe due to aliasing. map[0] = 42; severalMaps[0][0] = 42; severalMaps8[0][0] = 42; @@ -16,8 +15,7 @@ contract C // Should not fail since knowledge is erased only for mapping (uint => uint). assert(severalMaps8[0][0] == 42); // Should not fail since singleMap == severalMaps3d[0][0] is not possible. - // Removed because of Spacer nondeterminism. - //assert(severalMaps3d[0][0][0] == 42); + assert(severalMaps3d[0][0][0] == 42); // Should fail since singleMap == map is possible. assert(map[0] == 42); } @@ -29,9 +27,7 @@ contract C // ==== // SMTEngine: all // SMTIgnoreCex: yes +// SMTTargets: assert // ---- -// Warning 6368: (340-355): CHC: Out of bounds access might happen here. -// Warning 6368: (612-627): CHC: Out of bounds access might happen here. -// Warning 6328: (860-880): CHC: Assertion violation happens here. -// Warning 6368: (936-952): CHC: Out of bounds access might happen here. -// Info 1391: CHC: 7 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (748-768): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\n\nTransaction trace:\nC.constructor()\nC.g(0)\n C.f(map) -- counterexample incomplete; parameter name used instead of value -- internal call +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 678e352f2093184b5cd1faee54783cfab74978ed Mon Sep 17 00:00:00 2001 From: clonker Date: Mon, 15 Jul 2024 10:55:03 +0200 Subject: [PATCH 0203/1340] Yul: Object node names are std::string instead of YulString --- libsolidity/interface/StandardCompiler.cpp | 2 +- libyul/AsmAnalysis.cpp | 2 +- libyul/AsmAnalysis.h | 4 +-- libyul/Object.cpp | 41 +++++++++++----------- libyul/Object.h | 10 +++--- libyul/ObjectParser.cpp | 18 ++++++---- libyul/ObjectParser.h | 4 +-- libyul/YulStack.cpp | 2 +- libyul/backends/evm/EVMDialect.cpp | 16 ++++----- libyul/backends/evm/EVMDialect.h | 2 +- libyul/backends/evm/EVMObjectCompiler.cpp | 6 ++-- test/libsolidity/MemoryGuardTest.cpp | 2 +- tools/yulPhaser/Program.cpp | 2 +- 13 files changed, 57 insertions(+), 54 deletions(-) diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 5510b5430..b908ab0cc 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1638,7 +1638,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) return output; } - std::string contractName = stack.parserResult()->name.str(); + std::string contractName = stack.parserResult()->name; bool const wildcardMatchesExperimental = true; if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental)) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index ac97f988d..38b9c782e 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -428,7 +428,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) if (functionName == "datasize" || functionName == "dataoffset") { auto const& argumentAsLiteral = std::get(arg); - if (!m_dataNames.count(YulString(formatLiteral(argumentAsLiteral)))) + if (!m_dataNames.count(formatLiteral(argumentAsLiteral))) m_errorReporter.typeError( 3517_error, nativeLocationOf(arg), diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index c49e68559..9dd4b2292 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -61,7 +61,7 @@ class AsmAnalyzer langutil::ErrorReporter& _errorReporter, Dialect const& _dialect, ExternalIdentifierAccess::Resolver _resolver = ExternalIdentifierAccess::Resolver(), - std::set _dataNames = {} + std::set _dataNames = {} ): m_resolver(std::move(_resolver)), m_info(_analysisInfo), @@ -128,7 +128,7 @@ class AsmAnalyzer langutil::EVMVersion m_evmVersion; Dialect const& m_dialect; /// Names of data objects to be referenced by builtin functions with literal arguments. - std::set m_dataNames; + std::set m_dataNames; ForLoop const* m_currentForLoop = nullptr; /// Worst side effects encountered during analysis (including within defined functions). SideEffects m_sideEffects; diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 260cb7330..76d8bdc66 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -40,7 +40,7 @@ using namespace solidity::yul; std::string Data::toString(Dialect const*, DebugInfoSelection const&, CharStreamProvider const*) const { - return "data \"" + name.str() + "\" hex\"" + util::toHex(data) + "\""; + return "data \"" + name + "\" hex\"" + util::toHex(data) + "\""; } std::string Object::toString( @@ -72,7 +72,7 @@ std::string Object::toString( for (auto const& obj: subObjects) inner += "\n" + obj->toString(_dialect, _debugInfoSelection, _soliditySourceProvider); - return useSrcComment + "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}"; + return useSrcComment + "object \"" + name + "\" {\n" + indent(inner) + "\n}"; } Json Data::toJson() const @@ -97,62 +97,61 @@ Json Object::toJson() const Json ret; ret["nodeType"] = "YulObject"; - ret["name"] = name.str(); + ret["name"] = name; ret["code"] = codeJson; ret["subObjects"] = subObjectsJson; return ret; } -std::set Object::qualifiedDataNames() const +std::set Object::qualifiedDataNames() const { - std::set qualifiedNames = - name.empty() || util::contains(name.str(), '.') ? - std::set{} : - std::set{name}; + std::set qualifiedNames = + name.empty() || util::contains(name, '.') ? + std::set{} : + std::set{name}; for (std::shared_ptr const& subObjectNode: subObjects) { yulAssert(qualifiedNames.count(subObjectNode->name) == 0, ""); - if (util::contains(subObjectNode->name.str(), '.')) + if (util::contains(subObjectNode->name, '.')) continue; qualifiedNames.insert(subObjectNode->name); if (auto const* subObject = dynamic_cast(subObjectNode.get())) - for (YulString const& subSubObj: subObject->qualifiedDataNames()) + for (auto const& subSubObj: subObject->qualifiedDataNames()) if (subObject->name != subSubObj) { - yulAssert(qualifiedNames.count(YulString{subObject->name.str() + "." + subSubObj.str()}) == 0, ""); - qualifiedNames.insert(YulString{subObject->name.str() + "." + subSubObj.str()}); + yulAssert(qualifiedNames.count(subObject->name + "." + subSubObj) == 0, ""); + qualifiedNames.insert(subObject->name + "." + subSubObj); } } - yulAssert(qualifiedNames.count(YulString{}) == 0, ""); - qualifiedNames.erase(YulString{}); + yulAssert(qualifiedNames.count("") == 0, ""); return qualifiedNames; } -std::vector Object::pathToSubObject(YulString _qualifiedName) const +std::vector Object::pathToSubObject(std::string_view _qualifiedName) const { yulAssert(_qualifiedName != name, ""); yulAssert(subIndexByName.count(name) == 0, ""); - if (boost::algorithm::starts_with(_qualifiedName.str(), name.str() + ".")) - _qualifiedName = YulString{_qualifiedName.str().substr(name.str().length() + 1)}; + if (boost::algorithm::starts_with(_qualifiedName, name + ".")) + _qualifiedName = _qualifiedName.substr(name.length() + 1); yulAssert(!_qualifiedName.empty(), ""); std::vector subObjectPathComponents; - boost::algorithm::split(subObjectPathComponents, _qualifiedName.str(), boost::is_any_of(".")); + boost::algorithm::split(subObjectPathComponents, _qualifiedName, boost::is_any_of(".")); std::vector path; Object const* object = this; for (std::string const& currentSubObjectName: subObjectPathComponents) { yulAssert(!currentSubObjectName.empty(), ""); - auto subIndexIt = object->subIndexByName.find(YulString{currentSubObjectName}); + auto subIndexIt = object->subIndexByName.find(currentSubObjectName); yulAssert( subIndexIt != object->subIndexByName.end(), - "Assembly object <" + _qualifiedName.str() + "> not found or does not contain code." + "Assembly object <" + std::string(_qualifiedName) + "> not found or does not contain code." ); object = dynamic_cast(object->subObjects[subIndexIt->second].get()); - yulAssert(object, "Assembly object <" + _qualifiedName.str() + "> not found or does not contain code."); + yulAssert(object, "Assembly object <" + std::string(_qualifiedName) + "> not found or does not contain code."); yulAssert(object->subId != std::numeric_limits::max(), ""); path.push_back({object->subId}); } diff --git a/libyul/Object.h b/libyul/Object.h index 54a8080d0..c1ca9244d 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -52,7 +52,7 @@ struct ObjectNode /// Name of the object. /// Can be empty since .yul files can also just contain code, without explicitly placing it in an object. - YulString name; + std::string name; virtual std::string toString( Dialect const* _dialect, langutil::DebugInfoSelection const& _debugInfoSelection, @@ -66,7 +66,7 @@ struct ObjectNode */ struct Data: public ObjectNode { - Data(YulString _name, bytes _data): data(std::move(_data)) { name = _name; } + Data(std::string _name, bytes _data): data(std::move(_data)) { name = _name; } bytes data; @@ -102,7 +102,7 @@ struct Object: public ObjectNode /// @returns the set of names of data objects accessible from within the code of /// this object, including the name of object itself /// Handles all names containing dots as reserved identifiers, not accessible as data. - std::set qualifiedDataNames() const; + std::set qualifiedDataNames() const; /// @returns vector of subIDs if possible to reach subobject with @a _qualifiedName, throws otherwise /// For "B.C" should return vector of two values if success (subId of B and subId of C in B). @@ -114,14 +114,14 @@ struct Object: public ObjectNode /// pathToSubObject("E2.F3.H4") == {1, 0, 2} /// pathToSubObject("A1.E2") == {1} /// The path must not lead to a @a Data object (will throw in that case). - std::vector pathToSubObject(YulString _qualifiedName) const; + std::vector pathToSubObject(std::string_view _qualifiedName) const; /// sub id for object if it is subobject of another object, max value if it is not subobject size_t subId = std::numeric_limits::max(); std::shared_ptr code; std::vector> subObjects; - std::map subIndexByName; + std::map> subIndexByName; std::shared_ptr analysisInfo; std::shared_ptr debugData; diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index a02b9660b..1f5363fd8 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -50,7 +50,7 @@ std::shared_ptr ObjectParser::parse(std::shared_ptr const& _sca { // Special case: Code-only form. object = std::make_shared(); - object->name = "object"_yulstring; + object->name = "object"; auto sourceNameMapping = tryParseSourceNameMapping(); object->debugData = std::make_shared(ObjectDebugData{sourceNameMapping}); object->code = parseBlock(sourceNameMapping); @@ -185,7 +185,7 @@ void ObjectParser::parseData(Object& _containingObject) ); advance(); - YulString name = parseUniqueName(&_containingObject); + auto const name = parseUniqueName(&_containingObject); if (currentToken() == Token::HexStringLiteral) expectToken(Token::HexStringLiteral, false); @@ -195,22 +195,26 @@ void ObjectParser::parseData(Object& _containingObject) advance(); } -YulString ObjectParser::parseUniqueName(Object const* _containingObject) +std::string ObjectParser::parseUniqueName(Object const* _containingObject) { expectToken(Token::StringLiteral, false); - YulString name{currentLiteral()}; + auto const name = currentLiteral(); if (name.empty()) parserError(3287_error, "Object name cannot be empty."); else if (_containingObject && _containingObject->name == name) parserError(8311_error, "Object name cannot be the same as the name of the containing object."); else if (_containingObject && _containingObject->subIndexByName.count(name)) - parserError(8794_error, "Object name \"" + name.str() + "\" already exists inside the containing object."); + parserError(8794_error, "Object name \"" + name + "\" already exists inside the containing object."); advance(); return name; } -void ObjectParser::addNamedSubObject(Object& _container, YulString _name, std::shared_ptr _subObject) +void ObjectParser::addNamedSubObject(Object& _container, std::string_view const _name, std::shared_ptr _subObject) { - _container.subIndexByName[_name] = _container.subObjects.size(); + _container.subIndexByName.emplace( + std::piecewise_construct, + std::forward_as_tuple(_name), + std::forward_as_tuple(_container.subObjects.size()) + ); _container.subObjects.emplace_back(std::move(_subObject)); } diff --git a/libyul/ObjectParser.h b/libyul/ObjectParser.h index 716a191ea..08a852991 100644 --- a/libyul/ObjectParser.h +++ b/libyul/ObjectParser.h @@ -63,8 +63,8 @@ class ObjectParser: public langutil::ParserBase void parseData(Object& _containingObject); /// Tries to parse a name that is non-empty and unique inside the containing object. - YulString parseUniqueName(Object const* _containingObject); - void addNamedSubObject(Object& _container, YulString _name, std::shared_ptr _subObject); + std::string parseUniqueName(Object const* _containingObject); + void addNamedSubObject(Object& _container, std::string_view _name, std::shared_ptr _subObject); Dialect const& m_dialect; }; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 94e9ad7a8..27b4b5526 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -198,7 +198,7 @@ void YulStack::optimize(Object& _object, bool _isCreation) for (auto& subNode: _object.subObjects) if (auto subObject = dynamic_cast(subNode.get())) { - bool isCreation = !boost::ends_with(subObject->name.str(), "_deployed"); + bool isCreation = !boost::ends_with(subObject->name, "_deployed"); optimize(*subObject, isCreation); } diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 856689c91..d3b9c34bc 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -249,14 +249,14 @@ std::map createBuiltins(langutil::EVMVersion _ yulAssert(_call.arguments.size() == 1, ""); Expression const& arg = _call.arguments.front(); YulString const dataName (formatLiteral(std::get(arg))); - if (_context.currentObject->name == dataName) + if (_context.currentObject->name == dataName.str()) _assembly.appendAssemblySize(); else { std::vector subIdPath = - _context.subIDs.count(dataName) == 0 ? - _context.currentObject->pathToSubObject(dataName) : - std::vector{_context.subIDs.at(dataName)}; + _context.subIDs.count(dataName.str()) == 0 ? + _context.currentObject->pathToSubObject(dataName.str()) : + std::vector{_context.subIDs.at(dataName.str())}; yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); _assembly.appendDataSize(subIdPath); } @@ -270,14 +270,14 @@ std::map createBuiltins(langutil::EVMVersion _ yulAssert(_call.arguments.size() == 1, ""); Expression const& arg = _call.arguments.front(); YulString const dataName (formatLiteral(std::get(arg))); - if (_context.currentObject->name == dataName) + if (_context.currentObject->name == dataName.str()) _assembly.appendConstant(0); else { std::vector subIdPath = - _context.subIDs.count(dataName) == 0 ? - _context.currentObject->pathToSubObject(dataName) : - std::vector{_context.subIDs.at(dataName)}; + _context.subIDs.count(dataName.str()) == 0 ? + _context.currentObject->pathToSubObject(dataName.str()) : + std::vector{_context.subIDs.at(dataName.str())}; yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); _assembly.appendDataOffset(subIdPath); } diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 28649f3e5..f0455a8e4 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -45,7 +45,7 @@ struct BuiltinContext { Object const* currentObject = nullptr; /// Mapping from named objects to abstract assembly sub IDs. - std::map subIDs; + std::map subIDs; }; struct BuiltinFunctionForEVM: public BuiltinFunction diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index 0bd064940..81a345f90 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -55,8 +55,8 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) for (auto const& subNode: _object.subObjects) if (auto* subObject = dynamic_cast(subNode.get())) { - bool isCreation = !boost::ends_with(subObject->name.str(), "_deployed"); - auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name.str()); + bool isCreation = !boost::ends_with(subObject->name, "_deployed"); + auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name); context.subIDs[subObject->name] = subAssemblyAndID.second; subObject->subId = subAssemblyAndID.second; compile(*subObject, *subAssemblyAndID.first, m_dialect, _optimize, m_eofVersion); @@ -65,7 +65,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) { Data const& data = dynamic_cast(*subNode); // Special handling of metadata. - if (data.name.str() == Object::metadataName()) + if (data.name == Object::metadataName()) m_assembly.appendToAuxiliaryData(data.data); else context.subIDs[data.name] = m_assembly.appendData(data.data); diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index caa85c6fd..6e44afccf 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -80,7 +80,7 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con }; handleObject("creation", *object); size_t deployedIndex = object->subIndexByName.at( - YulString(IRNames::deployedObject(compiler().contractDefinition(contractName))) + IRNames::deployedObject(compiler().contractDefinition(contractName)) ); handleObject("runtime", dynamic_cast(*object->subObjects[deployedIndex])); } diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 00abcc8e5..1586f6020 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -135,7 +135,7 @@ std::variant, ErrorList> Program::parseObject(Dialect con // The other object references the nested one which makes analysis fail. Below we try to // extract just the nested one for that reason. This is just a heuristic. If there's no // subobject with such a suffix we fall back to accepting the whole object as is. - if (subObject != nullptr && subObject->name.str() == object->name.str() + "_deployed") + if (subObject != nullptr && subObject->name == object->name + "_deployed") { deployedObject = dynamic_cast(subObject.get()); if (deployedObject != nullptr) From d6bf14ae3035df916b1b67667467a08b96cd61f1 Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 7 Jun 2023 12:17:10 +0200 Subject: [PATCH 0204/1340] Implementation of Lengauer-Tarjan algorithm to find dominators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- libsolutil/CMakeLists.txt | 1 + libsolutil/DominatorFinder.h | 412 +++++++++++ test/CMakeLists.txt | 1 + test/libsolutil/DominatorFinderTest.cpp | 920 ++++++++++++++++++++++++ 4 files changed, 1334 insertions(+) create mode 100644 libsolutil/DominatorFinder.h create mode 100644 test/libsolutil/DominatorFinderTest.cpp diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index 0fdb23b04..291c95c0d 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -8,6 +8,7 @@ set(sources CommonIO.cpp CommonIO.h cxx20.h + DominatorFinder.h Exceptions.cpp Exceptions.h ErrorCodes.h diff --git a/libsolutil/DominatorFinder.h b/libsolutil/DominatorFinder.h new file mode 100644 index 000000000..ba86f6f02 --- /dev/null +++ b/libsolutil/DominatorFinder.h @@ -0,0 +1,412 @@ +/* + 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 +/** + * Dominator analysis of a control flow graph. + * The implementation is based on the following paper: + * https://www.cs.princeton.edu/courses/archive/spr03/cs423/download/dominators.pdf + * See appendix B pg. 139. + */ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace +{ + template + struct has_id : std::false_type {}; + + template + struct has_id().id)>> : std::true_type {}; +} + +namespace solidity::util +{ + +/// DominatorFinder computes the dominator tree of a directed graph. +/// V is the type of the vertex and it is assumed to have a unique identifier. +/// ForEachSuccessor is a visitor that visits the successors of a vertex. +/// +/// The graph must contain at least one vertex (the entry point) and is assumed to not be disconnected. +/// Only vertices reachable from the entry vertex are visited. +template +class DominatorFinder +{ +public: + static_assert(has_id::value, "vertex must define id member"); + using VId = typename V::Id; + using DfsIndex = size_t; + + DominatorFinder(V const& _entry): + m_immediateDominators(findDominators(_entry)) + { + buildDominatorTree(); + } + + std::vector const& verticesIdsInDFSOrder() const + { + return m_verticesInDFSOrder; + } + + std::map const& dfsIndexById() const + { + return m_dfsIndexByVertexId; + } + + std::map> const immediateDominators() const + { + return m_immediateDominators + | ranges::views::enumerate + | ranges::views::transform([&](auto const& _v) { + std::optional idomId = (_v.second.has_value()) ? std::optional(m_verticesInDFSOrder[_v.second.value()]) : std::nullopt; + return std::make_pair(m_verticesInDFSOrder[_v.first], idomId); + }) + | ranges::to>>; + } + + std::vector> const& immediateDominatorsByDfsIndex() const + { + return m_immediateDominators; + } + + std::map> const& dominatorTree() const + { + return m_dominatorTree; + } + + bool dominates(VId const& _dominatorId, VId const& _dominatedId) const + { + solAssert(!m_dfsIndexByVertexId.empty()); + solAssert(!m_immediateDominators.empty()); + + solAssert(m_dfsIndexByVertexId.count(_dominatorId) && m_dfsIndexByVertexId.count(_dominatedId)); + DfsIndex dominatorIdx = m_dfsIndexByVertexId.at(_dominatorId); + DfsIndex dominatedIdx = m_dfsIndexByVertexId.at(_dominatedId); + + if (dominatorIdx == dominatedIdx) + return true; + + DfsIndex idomIdx = m_immediateDominators.at(dominatedIdx).value_or(0); + while (idomIdx != 0) + { + solAssert(idomIdx < m_immediateDominators.size()); + if (idomIdx == dominatorIdx) + return true; + // The index of the immediate dominator of a vertex is always less than the index of the vertex itself. + solAssert(m_immediateDominators.at(idomIdx).has_value() && m_immediateDominators.at(idomIdx).value() < idomIdx); + idomIdx = m_immediateDominators[idomIdx].value(); + } + // Now that we reached the entry node (i.e. idomIdx = 0), + // either ``dominatorIdx == 0`` or it does not dominate the other node. + solAssert(idomIdx == 0); + return dominatorIdx == 0; + } + + /// Checks whether vertex ``_dominator`` dominates ``_dominated`` by going + /// through the path from ``_dominated`` to the entry node. + /// If ``_dominator`` is found, then it dominates ``_dominated`` + /// otherwise it doesn't. + bool dominates(V const& _dominator, V const& _dominated) const + { + return dominates(_dominator.id, _dominated.id); + } + + std::vector dominatorsOf(VId const& _vId) const + { + solAssert(!m_verticesInDFSOrder.empty()); + solAssert(!m_dfsIndexByVertexId.empty()); + solAssert(!m_immediateDominators.empty()); + + solAssert(m_dfsIndexByVertexId.count(_vId)); + + // No one dominates the entry vertex and we consider self-dominance implicit + // i.e. every node already dominates itself. + if (m_dfsIndexByVertexId.at(_vId) == 0) + return {}; + + solAssert(m_dfsIndexByVertexId.at(_vId) < m_immediateDominators.size()); + DfsIndex idomIdx = m_immediateDominators.at(m_dfsIndexByVertexId.at(_vId)).value_or(0); + solAssert(idomIdx < m_immediateDominators.size()); + + std::vector dominators; + while (idomIdx != 0) + { + solAssert(m_immediateDominators.at(idomIdx).has_value() && m_immediateDominators.at(idomIdx).value() < idomIdx); + dominators.emplace_back(m_verticesInDFSOrder.at(idomIdx)); + idomIdx = m_immediateDominators[idomIdx].value(); + } + + // The loop above discovers the dominators in the reverse order + // i.e. from the given vertex upwards to the entry node (the root of the dominator tree). + // And the entry vertex always dominates all other vertices. + dominators.emplace_back(m_verticesInDFSOrder[0]); + + return dominators; + } + + /// Find all dominators of a node _v + /// @note for a vertex ``_v``, the _v’s inclusion in the set of dominators of ``_v`` is implicit. + std::vector dominatorsOf(V const& _v) const + { + return dominatorsOf(_v.id); + } + +private: + std::vector> findDominators(V const& _entry) + { + solAssert(m_verticesInDFSOrder.empty()); + solAssert(m_dfsIndexByVertexId.empty()); + + // parent(w): The index of the vertex which is the parent of ``w`` in the spanning + // tree generated by the DFS. + std::vector parent; + + // step 1 + // The vertices are assigned indices in DFS order. + std::set visited; + DfsIndex nextUnusedDFSIndex = 0; + + auto dfs = [&](V const& _v, auto _dfs) -> void { + auto [_, inserted] = visited.insert(_v.id); + if (!inserted) + return; + + m_verticesInDFSOrder.emplace_back(_v.id); + m_dfsIndexByVertexId[_v.id] = nextUnusedDFSIndex; + nextUnusedDFSIndex++; + + ForEachSuccessor{}(_v, [&](V const& _successor) { + if (visited.count(_successor.id) == 0) + { + parent.push_back(m_dfsIndexByVertexId[_v.id]); + m_predecessors.push_back({m_dfsIndexByVertexId[_v.id]}); + _dfs(_successor, _dfs); + } + else + { + solAssert(m_dfsIndexByVertexId[_successor.id] < m_predecessors.size()); + m_predecessors[m_dfsIndexByVertexId[_successor.id]].insert(m_dfsIndexByVertexId[_v.id]); + } + }); + }; + + parent.emplace_back(std::numeric_limits::max()); + m_predecessors.emplace_back(); + dfs(_entry, dfs); + + size_t numVertices = visited.size(); + solAssert(nextUnusedDFSIndex == numVertices); + solAssert(m_verticesInDFSOrder.size() == numVertices); + solAssert(visited.size() == numVertices); + solAssert(m_predecessors.size() == numVertices); + solAssert(parent.size() == numVertices); + + // ancestor(w): Parent of vertex ``w`` in the virtual forest traversed by eval(). + // The forest consists of disjoint subtrees of the spanning tree and the parent of ``w`` is + // always one of its ancestors in that spanning tree. + // Initially each subtree consists of a single vertex. As the algorithm iterates over the + // graph, each processed vertex gets connected to its parent from the spanning tree using + // link(). Later on, the path compression performed by eval() may move it up in the subtree. + std::vector ancestor(numVertices, std::numeric_limits::max()); + // label(w): The index of a vertex with the smallest semidominator, on the path between ``w`` + // and the root of its subtree. The value is not updated immediately by link(), but + // only during path compression performed by eval(). + std::vector label; + // bucket(w): The set of all vertices having ``w`` as their semidominator. + // The index of the array represents the vertex' DFS index. + std::vector> bucket(numVertices); + + // semi(w): The DFS index of the semidominator of ``w``. + std::vector semi; + // idom(w): The DFS index of the immediate dominator of ``w``. + std::vector> idom(numVertices, std::nullopt); + + // ``link(v, w)`` adds an edge from ``w`` to ``v`` in the virtual forest. + // It is meant to initially attach vertex ``w`` to its parent from the spanning tree, + // but path compression can later limit the search path upwards. + // TODO: implement sophisticated link-eval algorithm as shown in pg 132 + // See: https://www.cs.princeton.edu/courses/archive/spr03/cs423/download/dominators.pdf + auto link = [&](DfsIndex _parentIdx, DfsIndex _wIdx) + { + solAssert(ancestor[_wIdx] == std::numeric_limits::max()); + ancestor[_wIdx] = _parentIdx; + }; + + // ``eval(v)`` returns a vertex with the smallest semidominator index on the path between + // vertex ``v`` and the root of its subtree in the virtual forest, i.e. the label of ``v``. + // Performs path compression in the process, updating labels and ancestors on the path to + // the subtree root. + auto eval = [&](DfsIndex _vIdx) -> DfsIndex + { + if (ancestor[_vIdx] == std::numeric_limits::max()) + return _vIdx; + + compressPath(ancestor, label, semi, _vIdx); + return label[_vIdx]; + }; + + auto toDfsIndex = [&](VId const& _vId) { return m_dfsIndexByVertexId[_vId]; }; + + for (DfsIndex wIdx = 0; wIdx < m_verticesInDFSOrder.size(); ++wIdx) + { + semi.push_back(wIdx); + label.push_back(wIdx); + } + + // Process the vertices in decreasing order of the DFS number + for (DfsIndex wIdx: m_verticesInDFSOrder | ranges::views::reverse | ranges::views::transform(toDfsIndex)) + { + // step 3 + // NOTE: this is an optimization, i.e. performing the step 3 before step 2. + // The goal is to process the bucket at the beginning of the loop for the vertex ``w`` + // instead of ``parent[w]`` at the end of the loop as described in the original paper. + // Inverting those steps ensures that a bucket is only processed once and + // it does not need to be erased. + // The optimization proposal is available here: https://jgaa.info/index.php/jgaa/article/view/paper119/2847 pg.77 + for (DfsIndex vIdx: bucket[wIdx]) + { + DfsIndex uIdx = eval(vIdx); + solAssert(uIdx <= vIdx); + idom[vIdx] = (semi[uIdx] < semi[vIdx]) ? uIdx : wIdx; + } + + // step 2 + for (DfsIndex vIdx: m_predecessors[wIdx]) + { + DfsIndex uIdx = eval(vIdx); + solAssert(uIdx <= vIdx); + if (semi[uIdx] < semi[wIdx]) + semi[wIdx] = semi[uIdx]; + } + solAssert(semi[wIdx] < wIdx || wIdx == 0); + bucket[semi[wIdx]].emplace_back(wIdx); + link(parent[wIdx], wIdx); + solAssert(ancestor[wIdx] == parent[wIdx]); + } + + // step 4 + // Compute idom in DFS order + // The entry vertex does not have an immediate dominator. + solAssert(idom[0] == std::nullopt); + for (DfsIndex wIdx: m_verticesInDFSOrder | ranges::views::drop(1) | ranges::views::transform(toDfsIndex)) + { + // All the other vertices must have an immediate dominator. + solAssert(idom[wIdx].has_value()); + if (idom[wIdx].value() != semi[wIdx]) + idom[wIdx] = idom[idom[wIdx].value()]; + } + + return idom; + } + + /// Path compression updates the ancestors of vertices along + /// the path to the ancestor with the minimum label value. + static void compressPath( + std::vector& _ancestor, + std::vector& _label, + std::vector const& _semi, + DfsIndex _vIdx + ) + { + solAssert(_vIdx < _ancestor.size() && _vIdx < _semi.size() && _vIdx < _label.size()); + solAssert(_ancestor[_vIdx] != std::numeric_limits::max()); + solAssert(_ancestor[_vIdx] < _vIdx); + if (_ancestor[_ancestor[_vIdx]] != std::numeric_limits::max()) + { + solAssert(_ancestor[_ancestor[_vIdx]] < _ancestor[_vIdx]); + compressPath(_ancestor, _label, _semi, _ancestor[_vIdx]); + if (_semi[_label[_ancestor[_vIdx]]] < _semi[_label[_vIdx]]) + _label[_vIdx] = _label[_ancestor[_vIdx]]; + _ancestor[_vIdx] = _ancestor[_ancestor[_vIdx]]; + } + solAssert(_label[_ancestor[_vIdx]] <= _label[_vIdx]); + } + + /// Build dominator tree from the immediate dominators set. + /// The function groups all the vertex IDs that are immediately dominated by a vertex. + void buildDominatorTree() + { + // m_immediateDominators is guaranteed to have at least one element after findingDominators() is executed. + solAssert(m_immediateDominators.size() > 0); + solAssert(m_immediateDominators.size() == m_verticesInDFSOrder.size()); + solAssert(m_immediateDominators[0] == std::nullopt); + + // Ignoring the entry node since no one dominates it. + for (DfsIndex dominatedIdx = 1; dominatedIdx < m_verticesInDFSOrder.size(); ++dominatedIdx) + { + VId dominatedId = m_verticesInDFSOrder[dominatedIdx]; + solAssert(m_dfsIndexByVertexId.count(dominatedId)); + solAssert(dominatedIdx == m_dfsIndexByVertexId.at(dominatedId)); + + // If the vertex does not have an immediate dominator, it is the entry vertex (i.e. index 0). + // NOTE: `dominatedIdx` will never be 0 since the loop starts from 1. + solAssert(m_immediateDominators[dominatedIdx].has_value()); + DfsIndex dominatorIdx = m_immediateDominators[dominatedIdx].value(); + + solAssert(dominatorIdx < dominatedIdx); + VId dominatorId = m_verticesInDFSOrder[dominatorIdx]; + m_dominatorTree[dominatorId].emplace_back(dominatedId); + } + } + + // predecessors(w): The set of vertices ``v`` such that (``v``, ``w``) is an edge of the graph. + std::vector> m_predecessors; + + /// Keeps the list of vertex IDs in the DFS order. + /// The entry vertex is the first element of the vector. + /// The indices of the other vertices are assigned in the order they are visited during the DFS. + /// I.e. m_verticesInDFSOrder[i] is the ID of the vertex whose DFS index is i. + /// + /// DFS index -> vertex ID + std::vector m_verticesInDFSOrder; + + /// Maps a vertex ID to its DFS order index. + /// + /// Vertex ID -> DFS index + std::map m_dfsIndexByVertexId; + + /// Maps a vertex to all vertices that it dominates. + /// If the vertex does not dominate any other vertex it has no entry in the map. + /// The value is a set of IDs of vertices dominated by the vertex whose ID is the map key. + /// + /// Vertex id -> dominates set {vertex ID} + std::map> m_dominatorTree; + + /// Immediate dominators by DFS index. + /// Maps a vertex' DFS index (i.e. array index) to its immediate dominator DFS index. + /// As the entry vertex does not have immediate dominator, its idom is always set to `std::nullopt`. + /// However note that the DFS index of the entry vertex is 0, since it is the first element of the vector. + /// + /// E.g. to get the immediate dominator of a Vertex w: + /// idomIdx = m_immediateDominators[m_dfsIndexByVertexId[w.id]] + /// idomVertexId = m_verticesInDFSOrder[domIdx] + /// + /// DFS index -> dominates DFS index + std::vector> m_immediateDominators; +}; +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d5435237e..0d19d7796 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -31,6 +31,7 @@ set(libsolutil_sources libsolutil/Checksum.cpp libsolutil/CommonData.cpp libsolutil/CommonIO.cpp + libsolutil/DominatorFinderTest.cpp libsolutil/FixedHash.cpp libsolutil/FunctionSelector.cpp libsolutil/IpfsHash.cpp diff --git a/test/libsolutil/DominatorFinderTest.cpp b/test/libsolutil/DominatorFinderTest.cpp new file mode 100644 index 000000000..22e8010ca --- /dev/null +++ b/test/libsolutil/DominatorFinderTest.cpp @@ -0,0 +1,920 @@ +/* + 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 . +*/ +/** + * Unit tests for the algorithm to find dominators from a graph. + */ +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include + +using namespace solidity::util; + +namespace solidity::util::test +{ + +typedef size_t TestVertexId; +typedef std::string TestVertexLabel; +typedef std::pair Edge; + +struct TestVertex { + using Id = TestVertexId; + + TestVertexId id; + TestVertexLabel label; + std::vector successors; +}; + +struct ForEachVertexSuccessorMock { + template + void operator()(TestVertex const& _v, Callable&& _callable) const + { + for (auto const& w: _v.successors) + _callable(*w); + } +}; + +typedef DominatorFinder TestDominatorFinder; + +class DominatorFinderTest +{ +public: + DominatorFinderTest( + std::vector const& _vertices, + std::vector const& _edges, + std::map const& _expectedImmediateDominators, + std::map const& _expectedDFSIndices, + std::map> const& _expectedDominatorTree + ) + { + soltestAssert(!_vertices.empty()); + + // NOTE: We use the indices of the vertices in the ``_vertices`` vector as vertex IDs. + TestVertexId id = 0; + vertices = _vertices | ranges::views::transform([&](TestVertexLabel const& label) -> TestVertex { + vertexIdMap[label] = id; + return {id++, label, {}}; + }) | ranges::to>; + soltestAssert(vertices.size() == _vertices.size()); + soltestAssert(vertexIdMap.size() == _vertices.size()); + soltestAssert(id == _vertices.size()); + + // Populate the successors of the vertices. + for (auto const& [from, to]: _edges) + vertices[vertexIdMap[from]].successors.emplace_back(&vertices[vertexIdMap[to]]); + + // Validate that all vertices used in the expected results are part of the graph. + std::set verticesSet = _vertices | ranges::to>; + auto validateVertices = [&](std::set const& labels) { + if (verticesSet.size() != labels.size()) + soltestAssert(std::includes(verticesSet.begin(), verticesSet.end(), labels.begin(), labels.end())); + else + soltestAssert(std::equal(verticesSet.begin(), verticesSet.end(), labels.begin(), labels.end())); + }; + + validateVertices(_edges + | ranges::views::transform([](Edge const& e) { return e.first; }) + | ranges::to> + ); + validateVertices(_edges + | ranges::views::transform([](Edge const& e) { return e.second; }) + | ranges::to> + ); + validateVertices(_expectedImmediateDominators | ranges::views::keys | ranges::to>); + // The entry vertex does not have an immediate dominator. + validateVertices(_expectedImmediateDominators + | ranges::views::values + | ranges::views::filter([](TestVertexLabel const& label) { return !label.empty(); }) + | ranges::to> + ); + validateVertices(_expectedDFSIndices | ranges::views::keys | ranges::to>); + bool allDFSIndexInRange = std::all_of( + _expectedDFSIndices.begin(), + _expectedDFSIndices.end(), + [&](auto const& pair) { + return pair.second < verticesSet.size(); + } + ); + solAssert(allDFSIndexInRange); + validateVertices(_expectedDominatorTree | ranges::views::keys | ranges::to>); + validateVertices(_expectedDominatorTree | ranges::views::values | ranges::views::join | ranges::to>); + + entry = &vertices[0]; + expectedImmediateDominators = labelMapToIdMap(_expectedImmediateDominators); + expectedDFSIndices = toVertexMapById(_expectedDFSIndices); + expectedDominatorTree = vertexMapToVertexId(_expectedDominatorTree); + } + + // Converts a map of vertex labels to map of vertex IDs + std::map> labelMapToIdMap(std::map const& _vertexLabelMap) const + { + return _vertexLabelMap + | ranges::views::transform([&](auto const& pair) -> std::pair> { + return {vertexIdMap.at(pair.first), (pair.second != "") ? std::optional(vertexIdMap.at(pair.second)) : std::nullopt}; + }) + | ranges::to>>; + } + + // Converts a map with vertex labels as keys to a map with vertex IDs as keys. + template + std::map toVertexMapById(std::map const& _verticesByLabel) const + { + return _verticesByLabel + | ranges::views::transform([&](auto const& pair) -> std::pair { + return {vertexIdMap.at(pair.first), pair.second}; + }) + | ranges::to>; + } + + // Converts a map with vertex labels as keys to a map with vertex IDs as keys. + std::map> vertexMapToVertexId(std::map> const& _vertexMapByLabel) const + { + auto labelVectorToIdVector = [&](std::vector const& labels) -> std::vector { + return labels + | ranges::views::transform([&](TestVertexLabel const& label) { + soltestAssert(vertexIdMap.count(label)); + return vertexIdMap.at(label); + }) + | ranges::to>; + }; + + return toVertexMapById(_vertexMapByLabel | ranges::views::transform([&](auto const& pair) -> std::pair> { + return {pair.first, labelVectorToIdVector(pair.second)}; + }) | ranges::to>>); + } + + TestVertex const* entry = nullptr; + std::vector vertices; + // Reverse map from vertices labels to IDs + std::map vertexIdMap; + std::map> expectedImmediateDominators; + std::map expectedDFSIndices; + std::map> expectedDominatorTree; +}; + +BOOST_AUTO_TEST_SUITE(Dominators) + +BOOST_AUTO_TEST_CASE(immediate_dominator_1) +{ + // A + // │ + // ▼ + // ┌───B + // │ │ + // ▼ │ + // C ──┼───┐ + // │ │ │ + // ▼ │ ▼ + // D◄──┘ G + // │ │ + // ▼ ▼ + // E H + // │ │ + // └──►F◄──┘ + DominatorFinderTest test( + {"A", "B", "C", "D", "E", "F", "G", "H"}, // Vertices + { // Edges + Edge("A", "B"), + Edge("B", "C"), + Edge("B", "D"), + Edge("C", "D"), + Edge("C", "G"), + Edge("D", "E"), + Edge("E", "F"), + Edge("G", "H"), + Edge("H", "F") + }, + { // Immediate dominators + {"A", ""}, + {"B", "A"}, + {"C", "B"}, + {"D", "B"}, + {"E", "D"}, + {"F", "B"}, + {"G", "C"}, + {"H", "G"} + }, + { // DFS indices + {"A", 0}, + {"B", 1}, + {"C", 2}, + {"D", 3}, + {"E", 4}, + {"F", 5}, + {"G", 6}, + {"H", 7} + }, + { // Dominator tree + {"A", {"B"}}, + {"B", {"C", "D", "F"}}, + {"C", {"G"}}, + {"D", {"E"}}, + {"G", {"H"}} + } + ); + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(dominatorFinder.immediateDominators() == test.expectedImmediateDominators); + BOOST_TEST(dominatorFinder.dfsIndexById() == test.expectedDFSIndices); + BOOST_TEST(dominatorFinder.dominatorTree() == test.expectedDominatorTree); +} + +BOOST_AUTO_TEST_CASE(immediate_dominator_2) +{ + // ┌────►A──────┐ + // │ │ ▼ + // │ B◄──┘ ┌──D──┐ + // │ │ │ │ + // │ ▼ ▼ ▼ + // └─C◄───┐ E F + // │ │ │ │ + // └───►G◄─┴─────┘ + DominatorFinderTest test( + {"A", "B", "C", "D", "E", "F", "G"}, + { + Edge("A", "B"), + Edge("B", "C"), + Edge("C", "G"), + Edge("C", "A"), + Edge("A", "D"), + Edge("D", "E"), + Edge("D", "F"), + Edge("E", "G"), + Edge("F", "G"), + Edge("G", "C") + }, + { + {"A", ""}, + {"B", "A"}, + {"C", "A"}, + {"D", "A"}, + {"E", "D"}, + {"F", "D"}, + {"G", "A"} + }, + { + {"A", 0}, + {"B", 1}, + {"C", 2}, + {"G", 3}, + {"D", 4}, + {"E", 5}, + {"F", 6} + }, + { + {"A", {"B", "C", "G", "D"}}, + {"D", {"E", "F"}} + } + ); + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(dominatorFinder.immediateDominators() == test.expectedImmediateDominators); + BOOST_TEST(dominatorFinder.dfsIndexById() == test.expectedDFSIndices); + BOOST_TEST(dominatorFinder.dominatorTree() == test.expectedDominatorTree); +} + +BOOST_AUTO_TEST_CASE(immediate_dominator_3) +{ + // ┌─────────┐ + // │ ▼ + // │ ┌───A───┐ + // │ │ │ + // │ ▼ ▼ + // │ ┌──►C◄───── B──┬──────┐ + // │ │ │ ▲ │ │ + // │ │ │ ┌────┘ │ │ + // │ │ ▼ │ ▼ ▼ + // │ │ D──┘ ┌───►E◄─────I + // │ │ ▲ │ │ │ + // │ │ │ │ ├───┐ │ + // │ │ │ │ │ │ │ + // │ │ │ │ ▼ │ ▼ + // │ └───┼─────┼────F └─►H + // │ │ │ │ │ + // │ │ │ │ │ + // │ │ │ │ │ + // │ └─────┴─G◄─┴──────┘ + // │ │ + // └─────────────┘ + DominatorFinderTest test( + {"A", "B", "C", "D", "E", "F", "G", "H", "I"}, + { + Edge("A", "B"), + Edge("A", "C"), + Edge("B", "C"), + Edge("B", "I"), + Edge("B", "E"), + Edge("C", "D"), + Edge("D", "B"), + Edge("E", "H"), + Edge("E", "F"), + Edge("F", "G"), + Edge("F", "C"), + Edge("G", "E"), + Edge("G", "A"), + Edge("G", "D"), + Edge("H", "G"), + Edge("I", "E"), + Edge("I", "H") + }, + { + {"A", ""}, + {"B", "A"}, + {"C", "A"}, + {"D", "A"}, + {"E", "B"}, + {"F", "E"}, + {"G", "B"}, + {"H", "B"}, + {"I", "B"} + }, + { + {"A", 0}, + {"B", 1}, + {"C", 2}, + {"D", 3}, + {"I", 4}, + {"E", 5}, + {"H", 6}, + {"G", 7}, + {"F", 8} + }, + { + {"A", {"B", "C", "D"}}, + {"B", {"I", "E", "H", "G"}}, + {"E", {"F"}} + } + ); + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(dominatorFinder.immediateDominators() == test.expectedImmediateDominators); + BOOST_TEST(dominatorFinder.dfsIndexById() == test.expectedDFSIndices); + BOOST_TEST(dominatorFinder.dominatorTree() == test.expectedDominatorTree); +} + +BOOST_AUTO_TEST_CASE(langauer_tarjan_p122_fig1) +{ + // T. Lengauer and R. E. Tarjan pg. 122 fig. 1 + // ref: https://www.cs.princeton.edu/courses/archive/spr03/cs423/download/dominators.pdf + DominatorFinderTest test( + {"R", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "L", "K"}, + { + Edge("R", "B"), + Edge("R", "A"), + Edge("R", "C"), + Edge("B", "A"), + Edge("B", "D"), + Edge("B", "E"), + Edge("A", "D"), + Edge("D", "L"), + Edge("L", "H"), + Edge("E", "H"), + Edge("H", "E"), + Edge("H", "K"), + Edge("K", "I"), + Edge("K", "R"), + Edge("C", "F"), + Edge("C", "G"), + Edge("F", "I"), + Edge("G", "I"), + Edge("G", "J"), + Edge("J", "I"), + Edge("I", "K") + }, + { + {"R", ""}, + {"A", "R"}, + {"B", "R"}, + {"C", "R"}, + {"D", "R"}, + {"E", "R"}, + {"F", "C"}, + {"G", "C"}, + {"H", "R"}, + {"I", "R"}, + {"J", "G"}, + {"L", "D"}, + {"K", "R"} + }, + { + {"R", 0}, + {"B", 1}, + {"A", 2}, + {"D", 3}, + {"L", 4}, + {"H", 5}, + {"E", 6}, + {"K", 7}, + {"I", 8}, + {"C", 9}, + {"F", 10}, + {"G", 11}, + {"J", 12} + }, + { + {"R", {"B", "A", "D", "H", "E", "K", "I", "C"}}, + {"D", {"L"}}, + {"C", {"F", "G"}}, + {"G", {"J"}} + } + ); + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(dominatorFinder.immediateDominators() == test.expectedImmediateDominators); + BOOST_TEST(dominatorFinder.dfsIndexById() == test.expectedDFSIndices); + BOOST_TEST(dominatorFinder.dominatorTree() == test.expectedDominatorTree); +} + +BOOST_AUTO_TEST_CASE(loukas_georgiadis) +{ + // Extracted from Loukas Georgiadis Dissertation - Linear-Time Algorithms for Dominators and Related Problems + // pg. 12 Fig. 2.2 + // ref: https://www.cs.princeton.edu/techreports/2005/737.pdf + DominatorFinderTest test( + {"R", "W", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "Y"}, + { + Edge("R", "W"), + Edge("R", "Y"), + Edge("W", "X1"), + Edge("Y", "X7"), + Edge("X1", "X2"), + Edge("X2", "X1"), + Edge("X2", "X3"), + Edge("X3", "X2"), + Edge("X3", "X4"), + Edge("X4", "X3"), + Edge("X4", "X5"), + Edge("X5", "X4"), + Edge("X5", "X6"), + Edge("X6", "X5"), + Edge("X6", "X7"), + Edge("X7", "X6") + }, + { + {"R", ""}, + {"W", "R"}, + {"X1", "R"}, + {"X2", "R"}, + {"X3", "R"}, + {"X4", "R"}, + {"X5", "R"}, + {"X6", "R"}, + {"X7", "R"}, + {"Y", "R"} + }, + { + {"R", 0}, + {"W", 1}, + {"X1", 2}, + {"X2", 3}, + {"X3", 4}, + {"X4", 5}, + {"X5", 6}, + {"X6", 7}, + {"X7", 8}, + {"Y", 9} + }, + { + {"R", {"W", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "Y"}}, + } + ); + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(dominatorFinder.immediateDominators() == test.expectedImmediateDominators); + BOOST_TEST(dominatorFinder.dfsIndexById() == test.expectedDFSIndices); + BOOST_TEST(dominatorFinder.dominatorTree() == test.expectedDominatorTree); +} + +BOOST_AUTO_TEST_CASE(itworst) +{ + // Worst-case families for k = 3 + // Example itworst(3) pg. 26 fig. 2.9 + // ref: https://www.cs.princeton.edu/techreports/2005/737.pdf + DominatorFinderTest test( + {"R", "W1", "W2", "W3", "X1", "X2", "X3", "Y1", "Y2", "Y3", "Z1", "Z2", "Z3"}, + { + Edge("R", "W1"), + Edge("R", "X1"), + Edge("R", "Z3"), + Edge("W1", "W2"), + Edge("W2", "W3"), + Edge("X1", "X2"), + Edge("X2", "X3"), + Edge("X3", "Y1"), + Edge("Y1", "W1"), + Edge("Y1", "W2"), + Edge("Y1", "W3"), + Edge("Y1", "Y2"), + Edge("Y2", "W1"), + Edge("Y2", "W2"), + Edge("Y2", "W3"), + Edge("Y2", "Y3"), + Edge("Y3", "W1"), + Edge("Y3", "W2"), + Edge("Y3", "W3"), + Edge("Y3", "Z1"), + Edge("Z1", "Z2"), + Edge("Z2", "Z1"), + Edge("Z2", "Z3"), + Edge("Z3", "Z2") + }, + { + {"R", ""}, + {"W1", "R"}, + {"W2", "R"}, + {"W3", "R"}, + {"X1", "R"}, + {"X2", "X1"}, + {"X3", "X2"}, + {"Y1", "X3"}, + {"Y2", "Y1"}, + {"Y3", "Y2"}, + {"Z1", "R"}, + {"Z2", "R"}, + {"Z3", "R"} + }, + { + {"R", 0}, + {"W1", 1}, + {"W2", 2}, + {"W3", 3}, + {"X1", 4}, + {"X2", 5}, + {"X3", 6}, + {"Y1", 7}, + {"Y2", 8}, + {"Y3", 9}, + {"Z1", 10}, + {"Z2", 11}, + {"Z3", 12} + }, + { + {"R", {"W1", "W2", "W3", "X1", "Z1", "Z2", "Z3"}}, + {"X1", {"X2"}}, + {"X2", {"X3"}}, + {"X3", {"Y1"}}, + {"Y1", {"Y2"}}, + {"Y2", {"Y3"}} + } + ); + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(dominatorFinder.immediateDominators() == test.expectedImmediateDominators); + BOOST_TEST(dominatorFinder.dfsIndexById() == test.expectedDFSIndices); + BOOST_TEST(dominatorFinder.dominatorTree() == test.expectedDominatorTree); +} + +BOOST_AUTO_TEST_CASE(idfsquad) +{ + // Worst-case families for k = 3 + // Example idfsquad(3) pg. 26 fig. 2.9 + // ref: https://www.cs.princeton.edu/techreports/2005/737.pdf + DominatorFinderTest test( + {"R", "X1", "X2", "X3", "Y1", "Y2", "Y3", "Z1", "Z2", "Z3"}, + { + Edge("R", "X1"), + Edge("R", "Z1"), + Edge("X1", "Y1"), + Edge("X1", "X2"), + Edge("X2", "X3"), + Edge("X2", "Y2"), + Edge("X3", "Y3"), + Edge("Y1", "Z1"), + Edge("Y1", "Z2"), + Edge("Z1", "Y1"), + Edge("Y2", "Z2"), + Edge("Y2", "Z3"), + Edge("Z2", "Y2"), + Edge("Y3", "Z3"), + Edge("Z3", "Y3") + }, + { + {"R", ""}, + {"X1", "R"}, + {"X2", "X1"}, + {"X3", "X2"}, + {"Y1", "R"}, + {"Y2", "R"}, + {"Y3", "R"}, + {"Z1", "R"}, + {"Z2", "R"}, + {"Z3", "R"} + }, + { + {"R", 0}, + {"X1", 1}, + {"Y1", 2}, + {"Z1", 3}, + {"Z2", 4}, + {"Y2", 5}, + {"Z3", 6}, + {"Y3", 7}, + {"X2", 8}, + {"X3", 9} + }, + { + {"R", {"X1", "Y1", "Z1", "Z2", "Y2", "Z3", "Y3"}}, + {"X1", {"X2"}}, + {"X2", {"X3"}} + } + ); + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(dominatorFinder.immediateDominators() == test.expectedImmediateDominators); + BOOST_TEST(dominatorFinder.dfsIndexById() == test.expectedDFSIndices); + BOOST_TEST(dominatorFinder.dominatorTree() == test.expectedDominatorTree); +} + +BOOST_AUTO_TEST_CASE(ibsfquad) +{ + // Worst-case families for k = 3 + // Example ibfsquad(3) pg. 26 fig. 2.9 + // ref: https://www.cs.princeton.edu/techreports/2005/737.pdf + DominatorFinderTest test( + {"R", "W", "X1", "X2", "X3", "Y", "Z"}, + { + Edge("R", "W"), + Edge("R", "Y"), + Edge("W", "X1"), + Edge("W", "X2"), + Edge("W", "X3"), + Edge("Y", "Z"), + Edge("Z", "X3"), + Edge("X3", "X2"), + Edge("X2", "X1") + }, + { + {"R", ""}, + {"W", "R"}, + {"X1", "R"}, + {"X2", "R"}, + {"X3", "R"}, + {"Y", "R"}, + {"Z", "Y"} + }, + { + {"R", 0}, + {"W", 1}, + {"X1", 2}, + {"X2", 3}, + {"X3", 4}, + {"Y", 5}, + {"Z", 6} + }, + { + {"R", {"W", "X1", "X2", "X3", "Y"}}, + {"Y", {"Z"}} + } + ); + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(dominatorFinder.immediateDominators() == test.expectedImmediateDominators); + BOOST_TEST(dominatorFinder.dfsIndexById() == test.expectedDFSIndices); + BOOST_TEST(dominatorFinder.dominatorTree() == test.expectedDominatorTree); +} + +BOOST_AUTO_TEST_CASE(sncaworst) +{ + // Worst-case families for k = 3 + // Example sncaworst(3) pg. 26 fig. 2.9 + // ref: https://www.cs.princeton.edu/techreports/2005/737.pdf + DominatorFinderTest test( + {"R", "X1", "X2", "X3", "Y1", "Y2", "Y3"}, + { + Edge("R", "X1"), + Edge("R", "Y1"), + Edge("R", "Y2"), + Edge("R", "Y3"), + Edge("X1", "X2"), + Edge("X2", "X3"), + Edge("X3", "Y1"), + Edge("X3", "Y2"), + Edge("X3", "Y3") + }, + { + {"R", ""}, + {"X1", "R"}, + {"X2", "X1"}, + {"X3", "X2"}, + {"Y1", "R"}, + {"Y2", "R"}, + {"Y3", "R"} + }, + { + {"R", 0}, + {"X1", 1}, + {"X2", 2}, + {"X3", 3}, + {"Y1", 4}, + {"Y2", 5}, + {"Y3", 6} + }, + { + {"R", {"X1", "Y1", "Y2", "Y3"}}, + {"X1", {"X2"}}, + {"X2", {"X3"}} + } + ); + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(dominatorFinder.immediateDominators() == test.expectedImmediateDominators); + BOOST_TEST(dominatorFinder.dfsIndexById() == test.expectedDFSIndices); + BOOST_TEST(dominatorFinder.dominatorTree() == test.expectedDominatorTree); +} + +BOOST_AUTO_TEST_CASE(collect_all_dominators_of_a_vertex) +{ + // A + // │ + // ▼ + // ┌───B + // │ │ + // ▼ │ + // C ──┼───┐ + // │ │ │ + // ▼ │ ▼ + // D◄──┘ G + // │ │ + // ▼ ▼ + // E H + // │ │ + // └──►F◄──┘ + DominatorFinderTest test( + {"A", "B", "C", "D", "E", "F", "G", "H"}, + { + Edge("A", "B"), + Edge("B", "C"), + Edge("B", "D"), + Edge("C", "D"), + Edge("C", "G"), + Edge("D", "E"), + Edge("E", "F"), + Edge("G", "H"), + Edge("H", "F") + }, + {}, + {}, + {} + ); + + // Converts a vector of vertex IDs to a vector of vertex labels. + auto toVertexLabel = [&](std::vector const& _vertices) + { + return _vertices | ranges::views::transform([&](TestVertexId id){ + return test.vertices[id].label; + }) | ranges::to>; + }; + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(toVertexLabel(dominatorFinder.dominatorsOf(test.vertexIdMap["A"])) == std::vector()); + BOOST_TEST(toVertexLabel(dominatorFinder.dominatorsOf(test.vertexIdMap["B"])) == std::vector({"A"})); + BOOST_TEST(toVertexLabel(dominatorFinder.dominatorsOf(test.vertexIdMap["C"])) == std::vector({"B", "A"})); + BOOST_TEST(toVertexLabel(dominatorFinder.dominatorsOf(test.vertexIdMap["D"])) == std::vector({"B", "A"})); + BOOST_TEST(toVertexLabel(dominatorFinder.dominatorsOf(test.vertexIdMap["E"])) == std::vector({"D", "B", "A"})); + BOOST_TEST(toVertexLabel(dominatorFinder.dominatorsOf(test.vertexIdMap["F"])) == std::vector({"B", "A"})); + BOOST_TEST(toVertexLabel(dominatorFinder.dominatorsOf(test.vertexIdMap["G"])) == std::vector({"C", "B", "A"})); + BOOST_TEST(toVertexLabel(dominatorFinder.dominatorsOf(test.vertexIdMap["H"])) == std::vector({"G", "C", "B", "A"})); +} + +BOOST_AUTO_TEST_CASE(check_dominance) +{ + // A + // │ + // ▼ + // ┌───B + // │ │ + // ▼ │ + // C ──┼───┐ + // │ │ │ + // ▼ │ ▼ + // D◄──┘ G + // │ │ + // ▼ ▼ + // E H + // │ │ + // └──►F◄──┘ + DominatorFinderTest test( + {"A", "B", "C", "D", "E", "F", "G", "H"}, + { + Edge("A", "B"), + Edge("B", "C"), + Edge("B", "D"), + Edge("C", "D"), + Edge("C", "G"), + Edge("D", "E"), + Edge("E", "F"), + Edge("G", "H"), + Edge("H", "F") + }, + {}, + { + {"A", 0}, + {"B", 1}, + {"C", 2}, + {"D", 3}, + {"E", 4}, + {"F", 5}, + {"G", 6}, + {"H", 7} + }, + {} + ); + + // Helper function to create a dominance relation for a vertex with all other vertices. + // + // @param _indices: The indices of the vertices that the vertex dominates. + // @return: A vector of booleans where the index represents the vertex and the value + // represents if the vertex dominates the other vertex at that index. + auto makeDominanceVertexRelation = [&](std::vector const& _indices = {}){ + std::vector dominance(test.vertices.size(), false); + for (TestDominatorFinder::DfsIndex i: _indices) + { + soltestAssert(i < test.vertices.size()); + dominance[i] = true; + } + return dominance; + }; + + // Dominance truth table for all vertices. + // Note that it includes self-dominance relation. + std::vector> expectedDominanceTable = { + std::vector(test.vertices.size(), true), // A dominates all vertices, including itself + makeDominanceVertexRelation({1,2,3,4,5,6,7}), // B, C, D, E, F, G, H + makeDominanceVertexRelation({2, 6, 7}), // C, G, H + makeDominanceVertexRelation({3, 4}), // D, E + makeDominanceVertexRelation({4}), // E + makeDominanceVertexRelation({5}), // F + makeDominanceVertexRelation({6, 7}), // G, H + makeDominanceVertexRelation({7}) // H + }; + soltestAssert(expectedDominanceTable.size() == test.vertices.size()); + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(dominatorFinder.dfsIndexById() == test.expectedDFSIndices); + // Check if the dominance table is as expected. + for (TestDominatorFinder::DfsIndex i = 0; i < expectedDominanceTable.size(); ++i) + { + soltestAssert(expectedDominanceTable[i].size() == test.vertices.size()); + for (TestDominatorFinder::DfsIndex j = 0; j < expectedDominanceTable[i].size(); ++j) + { + bool iDominatesJ = dominatorFinder.dominates(i, j); + BOOST_CHECK_MESSAGE( + iDominatesJ == expectedDominanceTable[i][j], + fmt::format( + "Vertex: {} expected to {} dominate vertex {} but returned: {}\n", + i, + (iDominatesJ ? "" : "not"), + j, + iDominatesJ + ) + ); + } + } +} + +BOOST_AUTO_TEST_CASE(no_edges) +{ + DominatorFinderTest test( + {"A"}, + {}, + { + {"A", ""}, + }, + { + {"A", 0}, + }, + {} + ); + + TestDominatorFinder dominatorFinder(*test.entry); + BOOST_TEST(dominatorFinder.immediateDominators() == test.expectedImmediateDominators); + BOOST_TEST(dominatorFinder.dfsIndexById() == test.expectedDFSIndices); + BOOST_TEST(dominatorFinder.dominatorTree() == test.expectedDominatorTree); +} + +BOOST_AUTO_TEST_SUITE_END() + +} // namespace solidity::util::test From 6ad92526990091acce9a242749db795c2282d4c5 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Tue, 16 Jul 2024 09:14:26 +0200 Subject: [PATCH 0205/1340] Add fstream std header to not break build after compiler upgrade. --- test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp b/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp index e10979ee1..aaa8e79c4 100644 --- a/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp +++ b/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp @@ -22,6 +22,7 @@ #include #include +#include using namespace solidity::frontend; using namespace solidity::test::fuzzer; From 630f736cfdbabbfd9015e9180580c32270b7d061 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 16 Jul 2024 17:54:26 +0200 Subject: [PATCH 0206/1340] Add test. --- test/cmdlineTests/ir_subobject_order/args | 1 + .../cmdlineTests/ir_subobject_order/input.sol | 14 +++ test/cmdlineTests/ir_subobject_order/output | 95 +++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 test/cmdlineTests/ir_subobject_order/args create mode 100644 test/cmdlineTests/ir_subobject_order/input.sol create mode 100644 test/cmdlineTests/ir_subobject_order/output diff --git a/test/cmdlineTests/ir_subobject_order/args b/test/cmdlineTests/ir_subobject_order/args new file mode 100644 index 000000000..a536442c5 --- /dev/null +++ b/test/cmdlineTests/ir_subobject_order/args @@ -0,0 +1 @@ +--ir-optimized --optimize --debug-info none diff --git a/test/cmdlineTests/ir_subobject_order/input.sol b/test/cmdlineTests/ir_subobject_order/input.sol new file mode 100644 index 000000000..70326ac06 --- /dev/null +++ b/test/cmdlineTests/ir_subobject_order/input.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >0.0.0; + +contract B { constructor() payable { assembly { revert(0,0) } } } +contract A { constructor() payable { assembly { revert(0,0) } } } +contract C { + // The subobject order should be determined by reference, not AST ID, + // So the subobject for A should precede the subobject for B. + A a = new A(); + B b = new B(); + fallback() external payable { + assembly { revert(0,0) } + } +} diff --git a/test/cmdlineTests/ir_subobject_order/output b/test/cmdlineTests/ir_subobject_order/output new file mode 100644 index 000000000..a364e623d --- /dev/null +++ b/test/cmdlineTests/ir_subobject_order/output @@ -0,0 +1,95 @@ +Optimized IR: +/// @use-src 0:"ir_subobject_order/input.sol" +object "A_13" { + code { { revert(0, 0) } } + /// @use-src 0:"ir_subobject_order/input.sol" + object "A_13_deployed" { + code { { revert(0, 0) } } + data ".metadata" hex"" + } +} + +Optimized IR: +/// @use-src 0:"ir_subobject_order/input.sol" +object "B_7" { + code { { revert(0, 0) } } + /// @use-src 0:"ir_subobject_order/input.sol" + object "B_7_deployed" { + code { { revert(0, 0) } } + data ".metadata" hex"" + } +} + +Optimized IR: +/// @use-src 0:"ir_subobject_order/input.sol" +object "C_33" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("A_13") + let _3 := add(_1, _2) + if or(gt(_3, sub(shl(64, 1), 1)), lt(_3, _1)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x41) + revert(0, 0x24) + } + datacopy(_1, dataoffset("A_13"), _2) + let expr_address := create(0, _1, sub(_3, _1)) + if iszero(expr_address) + { + let pos := mload(64) + returndatacopy(pos, 0, returndatasize()) + revert(pos, returndatasize()) + } + sstore(0, or(and(sload(0), not(sub(shl(160, 1), 1))), and(expr_address, sub(shl(160, 1), 1)))) + let _4 := mload(64) + let _5 := datasize("B_7") + let _6 := add(_4, _5) + if or(gt(_6, sub(shl(64, 1), 1)), lt(_6, _4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x41) + revert(0, 0x24) + } + datacopy(_4, dataoffset("B_7"), _5) + let expr_address_1 := create(0, _4, sub(_6, _4)) + if iszero(expr_address_1) + { + let pos_1 := mload(64) + returndatacopy(pos_1, 0, returndatasize()) + revert(pos_1, returndatasize()) + } + sstore(0x01, or(and(sload(0x01), not(sub(shl(160, 1), 1))), and(expr_address_1, sub(shl(160, 1), 1)))) + let _7 := mload(64) + let _8 := datasize("C_33_deployed") + codecopy(_7, dataoffset("C_33_deployed"), _8) + return(_7, _8) + } + } + /// @use-src 0:"ir_subobject_order/input.sol" + object "C_33_deployed" { + code { { revert(0, 0) } } + data ".metadata" hex"" + } + /// @use-src 0:"ir_subobject_order/input.sol" + object "B_7" { + code { { revert(0, 0) } } + /// @use-src 0:"ir_subobject_order/input.sol" + object "B_7_deployed" { + code { { revert(0, 0) } } + data ".metadata" hex"" + } + } + /// @use-src 0:"ir_subobject_order/input.sol" + object "A_13" { + code { { revert(0, 0) } } + /// @use-src 0:"ir_subobject_order/input.sol" + object "A_13_deployed" { + code { { revert(0, 0) } } + data ".metadata" hex"" + } + } +} From 8840e33746c26cc6398b0498b5a3ba0abc992eef Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 15 Jul 2024 17:15:11 +0200 Subject: [PATCH 0207/1340] Order yul subobjects by order of reference. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- Changelog.md | 1 + libsolidity/codegen/ir/IRGenerationContext.h | 5 +++-- libsolidity/codegen/ir/IRGenerator.cpp | 4 ++-- libsolidity/codegen/ir/IRGeneratorForStatements.cpp | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Changelog.md b/Changelog.md index 7bffd07e1..bfdd45575 100644 --- a/Changelog.md +++ b/Changelog.md @@ -19,6 +19,7 @@ Bugfixes: * SMTChecker: Fix formatting of unary minus expressions in invariants. * SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine. * TypeChecker: Fix segfault when assigning nested tuple to tuple. + * Yul IR Code Generation: Deterministic order of Yul subobjects. * Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. * Yul Parser: Fix segfault when parsing very long location comments. diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index 8e03a378b..2bf837697 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -143,7 +143,8 @@ class IRGenerationContext RevertStrings revertStrings() const { return m_revertStrings; } - std::set& subObjectsCreated() { return m_subObjects; } + util::UniqueVector const& subObjectsCreated() const { return m_subObjects; } + void addSubObject(ContractDefinition const* _contractDefinition) { m_subObjects.pushBack(_contractDefinition); } bool memoryUnsafeInlineAssemblySeen() const { return m_memoryUnsafeInlineAssemblySeen; } void setMemoryUnsafeInlineAssemblySeen() { m_memoryUnsafeInlineAssemblySeen = true; } @@ -195,7 +196,7 @@ class IRGenerationContext /// It will fail at runtime but the code must still compile. InternalDispatchMap m_internalDispatchMap; - std::set m_subObjects; + util::UniqueVector m_subObjects; langutil::DebugInfoSelection m_debugInfoSelection = {}; langutil::CharStreamProvider const* m_soliditySourceProvider = nullptr; diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 93136a1a2..bf0f6d5c0 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -101,10 +101,10 @@ std::string IRGenerator::generate( std::map const& _otherYulSources ) { - auto subObjectSources = [&_otherYulSources](std::set const& subObjects) -> std::string + auto subObjectSources = [&_otherYulSources](UniqueVector const& _subObjects) -> std::string { std::string subObjectsSources; - for (ContractDefinition const* subObject: subObjects) + for (ContractDefinition const* subObject: _subObjects) subObjectsSources += _otherYulSources.at(subObject); return subObjectsSources; }; diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 1c212cd82..0579f50c2 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1559,7 +1559,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) ContractDefinition const* contract = &dynamic_cast(*functionType->returnParameterTypes().front()).contractDefinition(); - m_context.subObjectsCreated().insert(contract); + m_context.addSubObject(contract); Whiskers t(R"(let := () let := add(, datasize("")) @@ -1947,7 +1947,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) auto const& contractType = dynamic_cast(*arg); solAssert(!contractType.isSuper()); ContractDefinition const& contract = contractType.contractDefinition(); - m_context.subObjectsCreated().insert(&contract); + m_context.addSubObject(&contract); appendCode() << Whiskers(R"( let := datasize("") let := (add(, 32)) From c78b7e25c6ccd5344b6d2319a4a992fe2095ee1b Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 16 Jul 2024 17:59:02 +0200 Subject: [PATCH 0208/1340] Update test. --- test/cmdlineTests/ir_subobject_order/output | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/cmdlineTests/ir_subobject_order/output b/test/cmdlineTests/ir_subobject_order/output index a364e623d..da4390fff 100644 --- a/test/cmdlineTests/ir_subobject_order/output +++ b/test/cmdlineTests/ir_subobject_order/output @@ -75,19 +75,19 @@ object "C_33" { data ".metadata" hex"" } /// @use-src 0:"ir_subobject_order/input.sol" - object "B_7" { + object "A_13" { code { { revert(0, 0) } } /// @use-src 0:"ir_subobject_order/input.sol" - object "B_7_deployed" { + object "A_13_deployed" { code { { revert(0, 0) } } data ".metadata" hex"" } } /// @use-src 0:"ir_subobject_order/input.sol" - object "A_13" { + object "B_7" { code { { revert(0, 0) } } /// @use-src 0:"ir_subobject_order/input.sol" - object "A_13_deployed" { + object "B_7_deployed" { code { { revert(0, 0) } } data ".metadata" hex"" } From 3b85fb9ac75f853602779f0541c9f5909640058e Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 17 Jul 2024 11:35:34 +0200 Subject: [PATCH 0209/1340] Remove swap from UniqueVector --- libsolutil/CommonData.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index c64b3913f..1a5451ef5 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -380,12 +380,6 @@ class UniqueVector std::vector m_contents; }; -template -void swap(UniqueVector& _lhs, UniqueVector& _rhs) -{ - std::swap(_lhs.contents(), _rhs.contents()); -} - namespace detail { From 94be070ba099d26587af809a7cc54d5348f2fca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 30 Jun 2024 17:27:36 +0200 Subject: [PATCH 0210/1340] YulStack: Remove unused m_sourceMappings member --- libyul/YulStack.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libyul/YulStack.h b/libyul/YulStack.h index d75ff200f..c6d78a115 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -163,8 +163,6 @@ class YulStack: public langutil::CharStreamProvider std::shared_ptr m_parserResult; langutil::ErrorList m_errors; langutil::ErrorReporter m_errorReporter; - - std::unique_ptr m_sourceMappings; }; } From ee839e9a0eee251f6cba9e440397e5f961635f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 30 Jun 2024 18:43:12 +0200 Subject: [PATCH 0211/1340] YulStack: Use util::unreachable() instead of returning unnecessary values. --- libyul/YulStack.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 27b4b5526..9aaaab2eb 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -44,6 +44,7 @@ using namespace solidity; using namespace solidity::frontend; using namespace solidity::yul; using namespace solidity::langutil; +using namespace solidity::util; namespace { @@ -257,8 +258,7 @@ MachineAssemblyObject YulStack::assemble(Machine _machine) case Machine::EVM: return assembleWithDeployed().first; } - // unreachable - return MachineAssemblyObject(); + unreachable(); } std::pair From 84b89a5cf358f6c103c79d7ff2732180338745f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 18 Jul 2024 14:10:25 +0200 Subject: [PATCH 0212/1340] Fix native source locations in optimized IR AST --- Changelog.md | 1 + libsolidity/interface/CompilerStack.cpp | 47 +++--- test/cmdlineTests/ast_ir/output | 92 ++++++------ .../output.json | 142 +++++++++--------- 4 files changed, 147 insertions(+), 135 deletions(-) diff --git a/Changelog.md b/Changelog.md index bfdd45575..7a5adcc4b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -19,6 +19,7 @@ Bugfixes: * SMTChecker: Fix formatting of unary minus expressions in invariants. * SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine. * TypeChecker: Fix segfault when assigning nested tuple to tuple. + * Yul AST: Fix ``nativeSrc`` attributes in optimized IR AST referring to locations in unoptimized IR. * Yul IR Code Generation: Deterministic order of Yul subobjects. * Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. * Yul Parser: Fix segfault when parsing very long location comments. diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 8ee55d87f..adef81793 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1464,25 +1464,36 @@ void CompilerStack::generateIR(ContractDefinition const& _contract) ); } - yul::YulStack stack( - m_evmVersion, - m_eofVersion, - yul::YulStack::Language::StrictAssembly, - m_optimiserSettings, - m_debugInfoSelection - ); - bool yulAnalysisSuccessful = stack.parseAndAnalyze("", compiledContract.yulIR); - solAssert( - yulAnalysisSuccessful, - compiledContract.yulIR + "\n\n" - "Invalid IR generated:\n" + - langutil::SourceReferenceFormatter::formatErrorInformation(stack.errors(), stack) + "\n" - ); + auto const parseYul = [&](std::string const& _irSource) { + YulStack stack( + m_evmVersion, + m_eofVersion, + YulStack::Language::StrictAssembly, + m_optimiserSettings, + m_debugInfoSelection + ); + bool yulAnalysisSuccessful = stack.parseAndAnalyze("", _irSource); + solAssert( + yulAnalysisSuccessful, + _irSource + "\n\n" + "Invalid IR generated:\n" + + langutil::SourceReferenceFormatter::formatErrorInformation(stack.errors(), stack) + "\n" + ); + return stack; + }; - compiledContract.yulIRAst = stack.astJson(); - stack.optimize(); - compiledContract.yulIROptimized = stack.print(this); - compiledContract.yulIROptimizedAst = stack.astJson(); + { + YulStack stack = parseYul(compiledContract.yulIR); + compiledContract.yulIRAst = stack.astJson(); + stack.optimize(); + compiledContract.yulIROptimized = stack.print(this); + } + { + // Optimizer does not maintain correct native source locations in the AST. + // We can work around it by regenerating the AST from scratch from optimized IR. + YulStack stack = parseYul(compiledContract.yulIROptimized); + compiledContract.yulIROptimizedAst = stack.astJson(); + } } void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) diff --git a/test/cmdlineTests/ast_ir/output b/test/cmdlineTests/ast_ir/output index c68c77872..76f111990 100644 --- a/test/cmdlineTests/ast_ir/output +++ b/test/cmdlineTests/ast_ir/output @@ -637,24 +637,24 @@ Optimized IR AST: { "code": { "block": { - "nativeSrc": "59:790:0", + "nativeSrc": "58:315:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "59:790:0", + "nativeSrc": "68:299:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "122:16:0", + "nativeSrc": "128:27:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "134:3:0", + "nativeSrc": "150:4:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -663,18 +663,18 @@ Optimized IR AST: ], "functionName": { "name": "memoryguard", - "nativeSrc": "122:11:0", + "nativeSrc": "138:11:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "122:16:0", + "nativeSrc": "138:17:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variables": [ { "name": "_1", - "nativeSrc": "122:16:0", + "nativeSrc": "132:2:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -686,7 +686,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "118:2:0", + "nativeSrc": "175:2:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -694,28 +694,28 @@ Optimized IR AST: }, { "name": "_1", - "nativeSrc": "122:16:0", + "nativeSrc": "179:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "111:6:0", + "nativeSrc": "168:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "111:28:0", + "nativeSrc": "168:14:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "111:28:0", + "nativeSrc": "168:14:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, { "body": { - "nativeSrc": "163:83:0", + "nativeSrc": "210:16:0", "nodeType": "YulBlock", "src": "60:13:0", "statements": [ @@ -724,7 +724,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "650:1:0", + "nativeSrc": "219:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -732,7 +732,7 @@ Optimized IR AST: }, { "kind": "number", - "nativeSrc": "650:1:0", + "nativeSrc": "222:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -741,15 +741,15 @@ Optimized IR AST: ], "functionName": { "name": "revert", - "nativeSrc": "640:6:0", + "nativeSrc": "212:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "640:12:0", + "nativeSrc": "212:12:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "640:12:0", + "nativeSrc": "212:12:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } @@ -759,20 +759,20 @@ Optimized IR AST: "arguments": [], "functionName": { "name": "callvalue", - "nativeSrc": "151:9:0", + "nativeSrc": "198:9:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "151:11:0", + "nativeSrc": "198:11:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "148:98:0", + "nativeSrc": "195:31:0", "nodeType": "YulIf", "src": "60:13:0" }, { - "nativeSrc": "363:24:0", + "nativeSrc": "239:34:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", "value": { @@ -780,7 +780,7 @@ Optimized IR AST: { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "372:14:0", + "nativeSrc": "258:14:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -789,18 +789,18 @@ Optimized IR AST: ], "functionName": { "name": "datasize", - "nativeSrc": "363:8:0", + "nativeSrc": "249:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "363:24:0", + "nativeSrc": "249:24:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variables": [ { "name": "_2", - "nativeSrc": "363:24:0", + "nativeSrc": "243:2:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -812,7 +812,7 @@ Optimized IR AST: "arguments": [ { "name": "_1", - "nativeSrc": "331:2:0", + "nativeSrc": "295:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, @@ -821,7 +821,7 @@ Optimized IR AST: { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "346:14:0", + "nativeSrc": "310:14:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -830,32 +830,32 @@ Optimized IR AST: ], "functionName": { "name": "dataoffset", - "nativeSrc": "335:10:0", + "nativeSrc": "299:10:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "335:26:0", + "nativeSrc": "299:26:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, { "name": "_2", - "nativeSrc": "363:24:0", + "nativeSrc": "327:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "codecopy", - "nativeSrc": "322:8:0", + "nativeSrc": "286:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "322:66:0", + "nativeSrc": "286:44:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "322:66:0", + "nativeSrc": "286:44:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, @@ -864,28 +864,28 @@ Optimized IR AST: "arguments": [ { "name": "_1", - "nativeSrc": "405:2:0", + "nativeSrc": "350:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, { "name": "_2", - "nativeSrc": "409:24:0", + "nativeSrc": "354:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "return", - "nativeSrc": "398:6:0", + "nativeSrc": "343:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "398:36:0", + "nativeSrc": "343:14:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "398:36:0", + "nativeSrc": "343:14:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } @@ -901,12 +901,12 @@ Optimized IR AST: { "code": { "block": { - "nativeSrc": "929:588:0", + "nativeSrc": "453:118:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "929:588:0", + "nativeSrc": "467:94:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -915,7 +915,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "1490:1:0", + "nativeSrc": "542:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -923,7 +923,7 @@ Optimized IR AST: }, { "kind": "number", - "nativeSrc": "1490:1:0", + "nativeSrc": "545:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -932,15 +932,15 @@ Optimized IR AST: ], "functionName": { "name": "revert", - "nativeSrc": "1480:6:0", + "nativeSrc": "535:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "1480:12:0", + "nativeSrc": "535:12:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "1480:12:0", + "nativeSrc": "535:12:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } diff --git a/test/cmdlineTests/standard_irOptimized_ast_requested/output.json b/test/cmdlineTests/standard_irOptimized_ast_requested/output.json index 91d0e87f3..5c6762ac9 100644 --- a/test/cmdlineTests/standard_irOptimized_ast_requested/output.json +++ b/test/cmdlineTests/standard_irOptimized_ast_requested/output.json @@ -5,12 +5,12 @@ "irOptimizedAst": { "code": { "block": { - "nativeSrc": "44:790:0", + "nativeSrc": "43:639:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "44:790:0", + "nativeSrc": "53:421:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -19,7 +19,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "103:2:0", + "nativeSrc": "120:2:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -29,7 +29,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "119:3:0", + "nativeSrc": "136:4:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -38,32 +38,32 @@ ], "functionName": { "name": "memoryguard", - "nativeSrc": "107:11:0", + "nativeSrc": "124:11:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "107:16:0", + "nativeSrc": "124:17:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "96:6:0", + "nativeSrc": "113:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "96:28:0", + "nativeSrc": "113:29:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "96:28:0", + "nativeSrc": "113:29:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" }, { "body": { - "nativeSrc": "148:83:0", + "nativeSrc": "182:111:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ @@ -72,15 +72,15 @@ "arguments": [], "functionName": { "name": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "nativeSrc": "150:77:0", + "nativeSrc": "200:77:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "150:79:0", + "nativeSrc": "200:79:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "150:79:0", + "nativeSrc": "200:79:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } @@ -90,38 +90,38 @@ "arguments": [], "functionName": { "name": "callvalue", - "nativeSrc": "136:9:0", + "nativeSrc": "158:9:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "136:11:0", + "nativeSrc": "158:11:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "133:98:0", + "nativeSrc": "155:138:0", "nodeType": "YulIf", "src": "56:13:0" }, { - "nativeSrc": "268:30:0", + "nativeSrc": "306:30:0", "nodeType": "YulVariableDeclaration", "src": "56:13:0", "value": { "arguments": [], "functionName": { "name": "allocate_unbounded", - "nativeSrc": "278:18:0", + "nativeSrc": "316:18:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "278:20:0", + "nativeSrc": "316:20:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, "variables": [ { "name": "_1", - "nativeSrc": "272:2:0", + "nativeSrc": "310:2:0", "nodeType": "YulTypedName", "src": "56:13:0", "type": "" @@ -133,7 +133,7 @@ "arguments": [ { "name": "_1", - "nativeSrc": "316:2:0", + "nativeSrc": "358:2:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, @@ -142,7 +142,7 @@ { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "331:14:0", + "nativeSrc": "373:14:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -151,11 +151,11 @@ ], "functionName": { "name": "dataoffset", - "nativeSrc": "320:10:0", + "nativeSrc": "362:10:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "320:26:0", + "nativeSrc": "362:26:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, @@ -164,7 +164,7 @@ { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "357:14:0", + "nativeSrc": "399:14:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -173,26 +173,26 @@ ], "functionName": { "name": "datasize", - "nativeSrc": "348:8:0", + "nativeSrc": "390:8:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "348:24:0", + "nativeSrc": "390:24:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "codecopy", - "nativeSrc": "307:8:0", + "nativeSrc": "349:8:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "307:66:0", + "nativeSrc": "349:66:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "307:66:0", + "nativeSrc": "349:66:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" }, @@ -201,7 +201,7 @@ "arguments": [ { "name": "_1", - "nativeSrc": "390:2:0", + "nativeSrc": "435:2:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, @@ -210,7 +210,7 @@ { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "403:14:0", + "nativeSrc": "448:14:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -219,26 +219,26 @@ ], "functionName": { "name": "datasize", - "nativeSrc": "394:8:0", + "nativeSrc": "439:8:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "394:24:0", + "nativeSrc": "439:24:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "return", - "nativeSrc": "383:6:0", + "nativeSrc": "428:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "383:36:0", + "nativeSrc": "428:36:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "383:36:0", + "nativeSrc": "428:36:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } @@ -246,19 +246,19 @@ }, { "body": { - "nativeSrc": "469:43:0", + "nativeSrc": "531:23:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ { - "nativeSrc": "483:19:0", + "nativeSrc": "533:19:0", "nodeType": "YulAssignment", "src": "56:13:0", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "499:2:0", + "nativeSrc": "549:2:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -267,18 +267,18 @@ ], "functionName": { "name": "mload", - "nativeSrc": "493:5:0", + "nativeSrc": "543:5:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "493:9:0", + "nativeSrc": "543:9:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, "variableNames": [ { "name": "memPtr", - "nativeSrc": "483:6:0", + "nativeSrc": "533:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" } @@ -287,12 +287,12 @@ ] }, "name": "allocate_unbounded", - "nativeSrc": "429:83:0", + "nativeSrc": "483:71:0", "nodeType": "YulFunctionDefinition", "returnVariables": [ { "name": "memPtr", - "nativeSrc": "462:6:0", + "nativeSrc": "516:6:0", "nodeType": "YulTypedName", "src": "56:13:0", "type": "" @@ -302,7 +302,7 @@ }, { "body": { - "nativeSrc": "611:36:0", + "nativeSrc": "660:16:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ @@ -311,7 +311,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "632:1:0", + "nativeSrc": "669:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -319,7 +319,7 @@ }, { "kind": "number", - "nativeSrc": "635:1:0", + "nativeSrc": "672:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -328,22 +328,22 @@ ], "functionName": { "name": "revert", - "nativeSrc": "625:6:0", + "nativeSrc": "662:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "625:12:0", + "nativeSrc": "662:12:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "625:12:0", + "nativeSrc": "662:12:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } ] }, "name": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "nativeSrc": "522:125:0", + "nativeSrc": "563:113:0", "nodeType": "YulFunctionDefinition", "src": "56:13:0" } @@ -357,12 +357,12 @@ { "code": { "block": { - "nativeSrc": "899:588:0", + "nativeSrc": "747:361:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "899:588:0", + "nativeSrc": "761:207:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -371,7 +371,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "966:2:0", + "nativeSrc": "836:2:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -381,7 +381,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "982:3:0", + "nativeSrc": "852:4:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -390,26 +390,26 @@ ], "functionName": { "name": "memoryguard", - "nativeSrc": "970:11:0", + "nativeSrc": "840:11:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "970:16:0", + "nativeSrc": "840:17:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "959:6:0", + "nativeSrc": "829:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "959:28:0", + "nativeSrc": "829:29:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "959:28:0", + "nativeSrc": "829:29:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" }, @@ -418,15 +418,15 @@ "arguments": [], "functionName": { "name": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", - "nativeSrc": "1001:77:0", + "nativeSrc": "875:77:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "1001:79:0", + "nativeSrc": "875:79:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "1001:79:0", + "nativeSrc": "875:79:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } @@ -434,7 +434,7 @@ }, { "body": { - "nativeSrc": "1432:44:0", + "nativeSrc": "1082:16:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ @@ -443,7 +443,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "1457:1:0", + "nativeSrc": "1091:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -451,7 +451,7 @@ }, { "kind": "number", - "nativeSrc": "1460:1:0", + "nativeSrc": "1094:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -460,22 +460,22 @@ ], "functionName": { "name": "revert", - "nativeSrc": "1450:6:0", + "nativeSrc": "1084:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "1450:12:0", + "nativeSrc": "1084:12:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "1450:12:0", + "nativeSrc": "1084:12:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } ] }, "name": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", - "nativeSrc": "1343:133:0", + "nativeSrc": "981:117:0", "nodeType": "YulFunctionDefinition", "src": "56:13:0" } From 198d2393ce504e108ee0bbb531f8ad3f375a87ca Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 19 Jul 2024 09:56:15 +0200 Subject: [PATCH 0213/1340] Downgrade nodejs in base_node_small image to fix CI --- .circleci/config.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d6c3f33da..20f57b413 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -487,7 +487,8 @@ defaults: - base_node_small: &base_node_small docker: - - image: cimg/node:current + # TODO: Revert to cimg/node:current once https://github.com/npm/cli/issues/7657 is resolved. + - image: cimg/node:22.4 resource_class: small environment: &base_node_small_env TERM: xterm @@ -761,6 +762,7 @@ defaults: # which does not support shanghai EVM. compile_only: 1 resource_class: medium + image: cimg/node:18.16 - job_native_test_ext_yield_liquidator: &job_native_test_ext_yield_liquidator <<: *requires_b_ubu_static From 1a5335a48688bd19dbb95d9279e7e1af5e4044d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 17 Jul 2024 17:01:16 +0200 Subject: [PATCH 0214/1340] Fix isoltest crash when formatting call arguments in a contract whose ABI includes entries without names - functionSignatureFromABI() would attempt to calculate signature for a function even if it had no name (i.e. was a constructor, fallback or receive). This would lead to a crash. - The buggy logic is used only for formatting expectations when an test fails in interactive mode. --- test/libsolidity/util/ContractABIUtils.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/libsolidity/util/ContractABIUtils.cpp b/test/libsolidity/util/ContractABIUtils.cpp index fb2f4eb62..dcbdcbc5d 100644 --- a/test/libsolidity/util/ContractABIUtils.cpp +++ b/test/libsolidity/util/ContractABIUtils.cpp @@ -142,6 +142,8 @@ std::optional isFixedPoint(std::string const& type) std::string functionSignatureFromABI(Json const& _functionABI) { + soltestAssert(_functionABI.contains("name")); + auto inputs = _functionABI["inputs"]; std::string signature = {_functionABI["name"].get() + "("}; size_t parameterCount = 0; @@ -169,7 +171,9 @@ std::optional ContractABIUtils::paramet return std::nullopt; for (auto const& function: _contractABI) - if (_functionSignature == functionSignatureFromABI(function)) + // ABI may contain functions without names (constructor, fallback, receive). Since name is + // necessary to calculate the signature, these cannot possibly match and can be safely ignored. + if (function.contains("name") && _functionSignature == functionSignatureFromABI(function)) { ParameterList inplaceTypeParams; ParameterList dynamicTypeParams; From 96fdcc3d040d05209f561e78a50dee2ebe4252c3 Mon Sep 17 00:00:00 2001 From: clonker Date: Thu, 18 Jul 2024 14:15:22 +0200 Subject: [PATCH 0215/1340] Yul: Prepare removal of YulString by replacing its occurrences by YulName typedef --- libsolc/libsolc.cpp | 2 +- libsolidity/analysis/ReferencesResolver.cpp | 2 +- libsolidity/analysis/ReferencesResolver.h | 2 +- libsolidity/codegen/CompilerContext.cpp | 10 +- libsolidity/codegen/CompilerContext.h | 2 +- libsolidity/codegen/ContractCompiler.cpp | 2 +- .../codegen/ir/IRGeneratorForStatements.cpp | 6 +- .../codegen/IRGeneratorForStatements.cpp | 6 +- libsolidity/interface/CompilerStack.cpp | 2 +- libyul/AST.h | 10 +- libyul/AsmAnalysis.cpp | 52 ++++---- libyul/AsmAnalysis.h | 18 +-- libyul/AsmJsonImporter.cpp | 10 +- libyul/AsmParser.cpp | 6 +- libyul/AsmParser.h | 2 +- libyul/AsmPrinter.cpp | 2 +- libyul/AsmPrinter.h | 4 +- libyul/CMakeLists.txt | 1 + libyul/CompilabilityChecker.h | 4 +- libyul/ControlFlowSideEffectsCollector.cpp | 4 +- libyul/ControlFlowSideEffectsCollector.h | 2 +- libyul/Dialect.cpp | 31 +++-- libyul/Dialect.h | 37 +++--- libyul/Exceptions.h | 10 +- libyul/FunctionReferenceResolver.h | 2 +- libyul/Object.h | 1 - libyul/ObjectParser.h | 1 - libyul/Scope.cpp | 8 +- libyul/Scope.h | 20 +-- libyul/YulName.h | 26 ++++ libyul/YulString.h | 2 +- libyul/backends/evm/ConstantOptimiser.cpp | 16 +-- libyul/backends/evm/ConstantOptimiser.h | 6 +- .../backends/evm/ControlFlowGraphBuilder.cpp | 10 +- libyul/backends/evm/ControlFlowGraphBuilder.h | 4 +- libyul/backends/evm/EVMCodeTransform.cpp | 12 +- libyul/backends/evm/EVMCodeTransform.h | 8 +- libyul/backends/evm/EVMDialect.cpp | 122 +++++++++--------- libyul/backends/evm/EVMDialect.h | 33 +++-- libyul/backends/evm/EVMObjectCompiler.cpp | 2 +- .../evm/OptimizedEVMCodeTransform.cpp | 14 +- libyul/backends/evm/StackLayoutGenerator.cpp | 10 +- libyul/backends/evm/StackLayoutGenerator.h | 6 +- .../backends/evm/VariableReferenceCounter.cpp | 2 +- .../backends/evm/VariableReferenceCounter.h | 2 +- libyul/optimiser/ASTCopier.cpp | 4 +- libyul/optimiser/ASTCopier.h | 10 +- libyul/optimiser/ASTWalker.h | 2 +- libyul/optimiser/BlockHasher.h | 6 +- libyul/optimiser/CallGraphGenerator.cpp | 14 +- libyul/optimiser/CallGraphGenerator.h | 8 +- libyul/optimiser/CircularReferencesPruner.cpp | 12 +- libyul/optimiser/CircularReferencesPruner.h | 7 +- .../CommonSubexpressionEliminator.cpp | 6 +- .../optimiser/CommonSubexpressionEliminator.h | 8 +- libyul/optimiser/ConditionalSimplifier.cpp | 4 +- libyul/optimiser/ConditionalSimplifier.h | 4 +- libyul/optimiser/ConditionalUnsimplifier.cpp | 4 +- libyul/optimiser/ConditionalUnsimplifier.h | 4 +- libyul/optimiser/ControlFlowSimplifier.cpp | 2 +- libyul/optimiser/DataFlowAnalyzer.cpp | 64 ++++----- libyul/optimiser/DataFlowAnalyzer.h | 56 ++++---- libyul/optimiser/DeadCodeEliminator.h | 6 +- libyul/optimiser/Disambiguator.cpp | 2 +- libyul/optimiser/Disambiguator.h | 8 +- libyul/optimiser/EqualStoreEliminator.cpp | 4 +- libyul/optimiser/EqualStoreEliminator.h | 2 +- libyul/optimiser/EquivalentFunctionCombiner.h | 4 +- libyul/optimiser/EquivalentFunctionDetector.h | 4 +- libyul/optimiser/ExpressionInliner.cpp | 4 +- libyul/optimiser/ExpressionInliner.h | 9 +- libyul/optimiser/ExpressionJoiner.h | 2 +- libyul/optimiser/ExpressionSimplifier.cpp | 2 +- libyul/optimiser/ExpressionSplitter.cpp | 4 +- .../optimiser/ForLoopConditionOutOfBody.cpp | 2 +- libyul/optimiser/FullInliner.cpp | 35 +++-- libyul/optimiser/FullInliner.h | 32 ++--- libyul/optimiser/FunctionCallFinder.cpp | 10 +- libyul/optimiser/FunctionCallFinder.h | 6 +- libyul/optimiser/FunctionSpecializer.cpp | 12 +- libyul/optimiser/FunctionSpecializer.h | 8 +- .../InlinableExpressionFunctionFinder.cpp | 4 +- .../InlinableExpressionFunctionFinder.h | 8 +- libyul/optimiser/KnowledgeBase.cpp | 36 +++--- libyul/optimiser/KnowledgeBase.h | 38 +++--- libyul/optimiser/LoadResolver.cpp | 4 +- libyul/optimiser/LoadResolver.h | 2 +- libyul/optimiser/LoopInvariantCodeMotion.cpp | 8 +- libyul/optimiser/LoopInvariantCodeMotion.h | 10 +- libyul/optimiser/Metrics.cpp | 2 +- libyul/optimiser/Metrics.h | 4 +- libyul/optimiser/NameCollector.cpp | 22 ++-- libyul/optimiser/NameCollector.h | 31 ++--- libyul/optimiser/NameDispenser.cpp | 13 +- libyul/optimiser/NameDispenser.h | 18 +-- libyul/optimiser/NameDisplacer.cpp | 4 +- libyul/optimiser/NameDisplacer.h | 14 +- libyul/optimiser/NameSimplifier.cpp | 14 +- libyul/optimiser/NameSimplifier.h | 8 +- libyul/optimiser/OptimiserStep.h | 3 +- libyul/optimiser/OptimizerUtilities.cpp | 4 +- libyul/optimiser/OptimizerUtilities.h | 6 +- libyul/optimiser/Rematerialiser.cpp | 8 +- libyul/optimiser/Rematerialiser.h | 8 +- libyul/optimiser/SSATransform.cpp | 52 ++++---- libyul/optimiser/SSAValueTracker.cpp | 6 +- libyul/optimiser/SSAValueTracker.h | 12 +- libyul/optimiser/Semantics.cpp | 18 +-- libyul/optimiser/Semantics.h | 22 ++-- libyul/optimiser/SimplificationRules.cpp | 8 +- libyul/optimiser/SimplificationRules.h | 6 +- libyul/optimiser/StackCompressor.cpp | 44 +++---- libyul/optimiser/StackLimitEvader.cpp | 33 +++-- libyul/optimiser/StackLimitEvader.h | 4 +- libyul/optimiser/StackToMemoryMover.cpp | 16 +-- libyul/optimiser/StackToMemoryMover.h | 21 +-- libyul/optimiser/Substitution.cpp | 2 +- libyul/optimiser/Substitution.h | 6 +- libyul/optimiser/Suite.cpp | 4 +- libyul/optimiser/Suite.h | 4 +- libyul/optimiser/SyntacticalEquality.h | 6 +- libyul/optimiser/TypeInfo.cpp | 12 +- libyul/optimiser/TypeInfo.h | 16 +-- libyul/optimiser/UnusedAssignEliminator.cpp | 4 +- libyul/optimiser/UnusedAssignEliminator.h | 8 +- .../UnusedFunctionParameterPruner.cpp | 14 +- libyul/optimiser/UnusedFunctionsCommon.cpp | 4 +- libyul/optimiser/UnusedFunctionsCommon.h | 4 +- libyul/optimiser/UnusedPruner.cpp | 20 +-- libyul/optimiser/UnusedPruner.h | 26 ++-- libyul/optimiser/UnusedStoreBase.h | 2 +- libyul/optimiser/UnusedStoreEliminator.cpp | 24 ++-- libyul/optimiser/UnusedStoreEliminator.h | 22 ++-- libyul/optimiser/VarNameCleaner.cpp | 16 +-- libyul/optimiser/VarNameCleaner.h | 16 +-- test/libsolidity/MemoryGuardTest.cpp | 2 +- test/libyul/FunctionSideEffects.cpp | 2 +- test/libyul/KnowledgeBaseTest.cpp | 50 +++---- test/libyul/Parser.cpp | 6 +- test/libyul/StackShufflingTest.cpp | 8 +- test/libyul/StackShufflingTest.h | 4 +- test/libyul/YulOptimizerTestCommon.cpp | 10 +- test/libyul/YulOptimizerTestCommon.h | 4 +- test/tools/yulInterpreter/Inspector.h | 10 +- test/tools/yulInterpreter/Interpreter.cpp | 6 +- test/tools/yulInterpreter/Interpreter.h | 14 +- test/tools/yulopti.cpp | 2 +- tools/yulPhaser/Program.cpp | 6 +- 148 files changed, 879 insertions(+), 871 deletions(-) create mode 100644 libyul/YulName.h diff --git a/libsolc/libsolc.cpp b/libsolc/libsolc.cpp index 105949253..b49905130 100644 --- a/libsolc/libsolc.cpp +++ b/libsolc/libsolc.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index fd7def714..270e1a55a 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -488,7 +488,7 @@ void ReferencesResolver::resolveInheritDoc(StructuredDocumentation const& _docum } } -void ReferencesResolver::validateYulIdentifierName(yul::YulString _name, SourceLocation const& _location) +void ReferencesResolver::validateYulIdentifierName(yul::YulName _name, SourceLocation const& _location) { if (util::contains(_name.str(), '.')) m_errorReporter.declarationError( diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index 13752e9c9..0b7f9d373 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -94,7 +94,7 @@ class ReferencesResolver: private ASTConstVisitor, private yul::ASTWalker void resolveInheritDoc(StructuredDocumentation const& _documentation, StructurallyDocumentedAnnotation& _annotation); /// Checks if the name contains a '.'. - void validateYulIdentifierName(yul::YulString _name, langutil::SourceLocation const& _location); + void validateYulIdentifierName(yul::YulName _name, langutil::SourceLocation const& _location); langutil::ErrorReporter& m_errorReporter; NameAndTypeResolver& m_resolver; diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index d9264c6ac..4d522072a 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include @@ -388,11 +388,11 @@ void CompilerContext::appendInlineAssembly( { unsigned startStackHeight = stackHeight(); - std::set externallyUsedIdentifiers; + std::set externallyUsedIdentifiers; for (auto const& fun: _externallyUsedFunctions) - externallyUsedIdentifiers.insert(yul::YulString(fun)); + externallyUsedIdentifiers.insert(yul::YulName(fun)); for (auto const& var: _localVariables) - externallyUsedIdentifiers.insert(yul::YulString(var)); + externallyUsedIdentifiers.insert(yul::YulName(var)); yul::ExternalIdentifierAccess identifierAccess; identifierAccess.resolve = [&]( @@ -532,7 +532,7 @@ void CompilerContext::appendInlineAssembly( } -void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSettings, std::set const& _externalIdentifiers) +void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSettings, std::set const& _externalIdentifiers) { #ifdef SOL_OUTPUT_ASM cout << yul::AsmPrinter(*dialect)(*_object.code) << endl; diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 8eba084eb..c6972f92b 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -277,7 +277,7 @@ class CompilerContext /// Otherwise returns "revert(0, 0)". std::string revertReasonIfDebug(std::string const& _message = ""); - void optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSetting, std::set const& _externalIdentifiers = {}); + void optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSetting, std::set const& _externalIdentifiers = {}); /// Appends arbitrary data to the end of the bytecode. void appendToAuxiliaryData(bytes const& _data) { m_asm->appendToAuxiliaryData(_data); } diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 2326d3336..0ed17f6d0 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 0579f50c2..5be4d550e 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -78,7 +78,7 @@ struct CopyTranslate: public yul::ASTCopier return ASTCopier::operator()(_identifier); } - yul::YulString translateIdentifier(yul::YulString _name) override + yul::YulName translateIdentifier(yul::YulName _name) override { // Strictly, the dialect used by inline assembly (m_dialect) could be different // from the Yul dialect we are compiling to. So we are assuming here that the builtin @@ -87,7 +87,7 @@ struct CopyTranslate: public yul::ASTCopier if (m_dialect.builtin(_name)) return _name; else - return yul::YulString{"usr$" + _name.str()}; + return yul::YulName{"usr$" + _name.str()}; } yul::Identifier translate(yul::Identifier const& _identifier) override @@ -206,7 +206,7 @@ struct CopyTranslate: public yul::ASTCopier if (isDigit(value.front())) return yul::Literal{_identifier.debugData, yul::LiteralKind::Number, yul::valueOfNumberLiteral(value), {}}; else - return yul::Identifier{_identifier.debugData, yul::YulString{value}}; + return yul::Identifier{_identifier.debugData, yul::YulName{value}}; } diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index cb4705f0d..f9c50cf7a 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -70,12 +70,12 @@ struct CopyTranslate: public yul::ASTCopier return ASTCopier::operator()(_identifier); } - yul::YulString translateIdentifier(yul::YulString _name) override + yul::YulName translateIdentifier(yul::YulName _name) override { if (m_dialect.builtin(_name)) return _name; else - return yul::YulString{"usr$" + _name.str()}; + return yul::YulName{"usr$" + _name.str()}; } yul::Identifier translate(yul::Identifier const& _identifier) override @@ -102,7 +102,7 @@ struct CopyTranslate: public yul::ASTCopier solAssert(type); solAssert(m_context.env->typeEquals(*type, m_context.analysis.typeSystem().type(PrimitiveType::Word, {}))); std::string value = IRNames::localVariable(*varDecl); - return yul::Identifier{_identifier.debugData, yul::YulString{value}}; + return yul::Identifier{_identifier.debugData, yul::YulName{value}}; } IRGenerationContext const& m_context; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index adef81793..566feb21b 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -66,7 +66,7 @@ #include -#include +#include #include #include #include diff --git a/libyul/AST.h b/libyul/AST.h index ad60e4685..72be60a46 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -24,7 +24,7 @@ #pragma once #include -#include +#include #include @@ -36,9 +36,9 @@ namespace solidity::yul { -using Type = YulString; +using Type = YulName; -struct TypedName { langutil::DebugData::ConstPtr debugData; YulString name; Type type; }; +struct TypedName { langutil::DebugData::ConstPtr debugData; YulName name; Type type; }; using TypedNameList = std::vector; /// Literal number or string (up to 32 bytes) @@ -70,7 +70,7 @@ class LiteralValue { }; struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; LiteralValue value; Type type; }; /// External / internal identifier or label reference -struct Identifier { langutil::DebugData::ConstPtr debugData; YulString name; }; +struct Identifier { langutil::DebugData::ConstPtr debugData; YulName name; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand /// side and requires x to occupy exactly one stack slot. /// @@ -86,7 +86,7 @@ struct VariableDeclaration { langutil::DebugData::ConstPtr debugData; TypedNameL /// Block that creates a scope (frees declared stack variables) struct Block { langutil::DebugData::ConstPtr debugData; std::vector statements; }; /// Function definition ("function f(a, b) -> (d, e) { ... }") -struct FunctionDefinition { langutil::DebugData::ConstPtr debugData; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; +struct FunctionDefinition { langutil::DebugData::ConstPtr debugData; YulName name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; /// Conditional execution without "else" part. struct If { langutil::DebugData::ConstPtr debugData; std::unique_ptr condition; Block body; }; /// Switch case or default case diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 38b9c782e..cccb3de42 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -100,7 +100,7 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, return analysisInfo; } -std::vector AsmAnalyzer::operator()(Literal const& _literal) +std::vector AsmAnalyzer::operator()(Literal const& _literal) { expectValidType(_literal.type, nativeLocationOf(_literal)); bool erroneousLiteralValue = false; @@ -132,11 +132,11 @@ std::vector AsmAnalyzer::operator()(Literal const& _literal) return {_literal.type}; } -std::vector AsmAnalyzer::operator()(Identifier const& _identifier) +std::vector AsmAnalyzer::operator()(Identifier const& _identifier) { yulAssert(!_identifier.name.empty(), ""); auto watcher = m_errorReporter.errorWatcher(); - YulString type = m_dialect.defaultType; + YulName type = m_dialect.defaultType; if (m_currentScope->lookup(_identifier.name, GenericVisitor{ [&](Scope::Variable const& _var) @@ -190,7 +190,7 @@ std::vector AsmAnalyzer::operator()(Identifier const& _identifier) void AsmAnalyzer::operator()(ExpressionStatement const& _statement) { auto watcher = m_errorReporter.errorWatcher(); - std::vector types = std::visit(*this, _statement.expression); + std::vector types = std::visit(*this, _statement.expression); if (watcher.ok() && !types.empty()) m_errorReporter.typeError( 3083_error, @@ -209,7 +209,7 @@ void AsmAnalyzer::operator()(Assignment const& _assignment) size_t const numVariables = _assignment.variableNames.size(); yulAssert(numVariables >= 1, ""); - std::set variables; + std::set variables; for (auto const& _variableName: _assignment.variableNames) if (!variables.insert(_variableName.name).second) m_errorReporter.declarationError( @@ -220,7 +220,7 @@ void AsmAnalyzer::operator()(Assignment const& _assignment) " occurs multiple times on the left-hand side of the assignment." ); - std::vector types = std::visit(*this, *_assignment.value); + std::vector types = std::visit(*this, *_assignment.value); if (types.size() != numVariables) m_errorReporter.declarationError( @@ -259,7 +259,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) if (_varDecl.value) { - std::vector types = std::visit(*this, *_varDecl.value); + std::vector types = std::visit(*this, *_varDecl.value); if (types.size() != numVariables) m_errorReporter.declarationError( 3812_error, @@ -275,7 +275,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) for (size_t i = 0; i < _varDecl.variables.size(); ++i) { - YulString givenType = m_dialect.defaultType; + YulName givenType = m_dialect.defaultType; if (i < types.size()) givenType = types[i]; TypedName const& variable = _varDecl.variables[i]; @@ -311,17 +311,17 @@ void AsmAnalyzer::operator()(FunctionDefinition const& _funDef) (*this)(_funDef.body); } -std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) +std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) { yulAssert(!_funCall.functionName.name.empty(), ""); auto watcher = m_errorReporter.errorWatcher(); - std::vector const* parameterTypes = nullptr; - std::vector const* returnTypes = nullptr; + std::vector const* parameterTypes = nullptr; + std::vector const* returnTypes = nullptr; std::vector> const* literalArguments = nullptr; if (BuiltinFunction const* f = m_dialect.builtin(_funCall.functionName.name)) { - if (_funCall.functionName.name == "selfdestruct"_yulstring) + if (_funCall.functionName.name == "selfdestruct"_yulname) m_errorReporter.warning( 1699_error, nativeLocationOf(_funCall.functionName), @@ -334,7 +334,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) ); else if ( m_evmVersion.supportsTransientStorage() && - _funCall.functionName.name == "tstore"_yulstring && + _funCall.functionName.name == "tstore"_yulname && !m_errorReporter.hasError({2394}) ) m_errorReporter.warning( @@ -400,7 +400,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) std::to_string(_funCall.arguments.size()) + "." ); - std::vector argTypes; + std::vector argTypes; for (size_t i = _funCall.arguments.size(); i > 0; i--) { Expression const& arg = _funCall.arguments[i - 1]; @@ -465,7 +465,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) return *returnTypes; } else if (returnTypes) - return std::vector(returnTypes->size(), m_dialect.defaultType); + return std::vector(returnTypes->size(), m_dialect.defaultType); else return {}; } @@ -488,7 +488,7 @@ void AsmAnalyzer::operator()(Switch const& _switch) "\"switch\" statement with only a default case." ); - YulString valueType = expectExpression(*_switch.expression); + YulName valueType = expectExpression(*_switch.expression); std::set cases; for (auto const& _case: _switch.cases) @@ -553,9 +553,9 @@ void AsmAnalyzer::operator()(Block const& _block) m_currentScope = previousScope; } -YulString AsmAnalyzer::expectExpression(Expression const& _expr) +YulName AsmAnalyzer::expectExpression(Expression const& _expr) { - std::vector types = std::visit(*this, _expr); + std::vector types = std::visit(*this, _expr); if (types.size() != 1) m_errorReporter.typeError( 3950_error, @@ -567,7 +567,7 @@ YulString AsmAnalyzer::expectExpression(Expression const& _expr) return types.empty() ? m_dialect.defaultType : types.front(); } -YulString AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal) +YulName AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal) { yulAssert(_literal.kind == LiteralKind::String); yulAssert(m_dialect.validTypeForLiteral(LiteralKind::String, _literal.value, _literal.type)); @@ -578,7 +578,7 @@ YulString AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal) void AsmAnalyzer::expectBoolExpression(Expression const& _expr) { - YulString type = expectExpression(_expr); + YulName type = expectExpression(_expr); if (type != m_dialect.boolType) m_errorReporter.typeError( 1733_error, @@ -591,11 +591,11 @@ void AsmAnalyzer::expectBoolExpression(Expression const& _expr) ); } -void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueType) +void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulName _valueType) { yulAssert(!_variable.name.empty(), ""); auto watcher = m_errorReporter.errorWatcher(); - YulString const* variableType = nullptr; + YulName const* variableType = nullptr; bool found = false; if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name)) { @@ -654,7 +654,7 @@ Scope& AsmAnalyzer::scope(Block const* _block) return *scopePtr; } -void AsmAnalyzer::expectValidIdentifier(YulString _identifier, SourceLocation const& _location) +void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation const& _location) { // NOTE: the leading dot case is handled by the parser not allowing it. if (boost::ends_with(_identifier.str(), ".")) @@ -679,7 +679,7 @@ void AsmAnalyzer::expectValidIdentifier(YulString _identifier, SourceLocation co ); } -void AsmAnalyzer::expectValidType(YulString _type, SourceLocation const& _location) +void AsmAnalyzer::expectValidType(YulName _type, SourceLocation const& _location) { if (!m_dialect.types.count(_type)) m_errorReporter.typeError( @@ -689,7 +689,7 @@ void AsmAnalyzer::expectValidType(YulString _type, SourceLocation const& _locati ); } -void AsmAnalyzer::expectType(YulString _expectedType, YulString _givenType, SourceLocation const& _location) +void AsmAnalyzer::expectType(YulName _expectedType, YulName _givenType, SourceLocation const& _location) { if (_expectedType != _givenType) m_errorReporter.typeError( @@ -702,7 +702,7 @@ void AsmAnalyzer::expectType(YulString _expectedType, YulString _givenType, Sour bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location) { // NOTE: This function uses the default EVM version instead of the currently selected one. - auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}).builtin(YulString(_instructionIdentifier)); + auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}).builtin(YulName(_instructionIdentifier)); if (builtin && builtin->instruction.has_value()) return validateInstructions(builtin->instruction.value(), _location); else diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 9dd4b2292..5aa7fe496 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -79,13 +79,13 @@ class AsmAnalyzer /// Asserts on failure. static AsmAnalysisInfo analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object); - std::vector operator()(Literal const& _literal); - std::vector operator()(Identifier const&); + std::vector operator()(Literal const& _literal); + std::vector operator()(Identifier const&); void operator()(ExpressionStatement const&); void operator()(Assignment const& _assignment); void operator()(VariableDeclaration const& _variableDeclaration); void operator()(FunctionDefinition const& _functionDefinition); - std::vector operator()(FunctionCall const& _functionCall); + std::vector operator()(FunctionCall const& _functionCall); void operator()(If const& _if); void operator()(Switch const& _switch); void operator()(ForLoop const& _forLoop); @@ -99,20 +99,20 @@ class AsmAnalyzer private: /// Visits the expression, expects that it evaluates to exactly one value and /// returns the type. Reports errors on errors and returns the default type. - YulString expectExpression(Expression const& _expr); - YulString expectUnlimitedStringLiteral(Literal const& _literal); + YulName expectExpression(Expression const& _expr); + YulName expectUnlimitedStringLiteral(Literal const& _literal); /// Visits the expression and expects it to return a single boolean value. /// Reports an error otherwise. void expectBoolExpression(Expression const& _expr); /// Verifies that a variable to be assigned to exists, can be assigned to /// and has the same type as the value. - void checkAssignment(Identifier const& _variable, YulString _valueType); + void checkAssignment(Identifier const& _variable, YulName _valueType); Scope& scope(Block const* _block); - void expectValidIdentifier(YulString _identifier, langutil::SourceLocation const& _location); - void expectValidType(YulString _type, langutil::SourceLocation const& _location); - void expectType(YulString _expectedType, YulString _givenType, langutil::SourceLocation const& _location); + void expectValidIdentifier(YulName _identifier, langutil::SourceLocation const& _location); + void expectValidType(YulName _type, langutil::SourceLocation const& _location); + void expectType(YulName _expectedType, YulName _givenType, langutil::SourceLocation const& _location); bool validateInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location); bool validateInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location); diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index 63b1d65d2..8f211f31b 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -72,8 +72,8 @@ Json AsmJsonImporter::member(Json const& _node, std::string const& _name) TypedName AsmJsonImporter::createTypedName(Json const& _node) { auto typedName = createAsmNode(_node); - typedName.type = YulString{member(_node, "type").get()}; - typedName.name = YulString{member(_node, "name").get()}; + typedName.type = YulName{member(_node, "type").get()}; + typedName.name = YulName{member(_node, "name").get()}; return typedName; } @@ -171,7 +171,7 @@ Literal AsmJsonImporter::createLiteral(Json const& _node) value = util::asString(util::fromHex(member(_node, "hexValue").get())); else value = member(_node, "value").get(); - lit.type = YulString{member(_node, "type").get()}; + lit.type = YulName{member(_node, "type").get()}; if (kind == "number") { langutil::CharStream charStream(value, ""); @@ -219,7 +219,7 @@ Leave AsmJsonImporter::createLeave(Json const& _node) Identifier AsmJsonImporter::createIdentifier(Json const& _node) { auto identifier = createAsmNode(_node); - identifier.name = YulString(member(_node, "name").get()); + identifier.name = YulName(member(_node, "name").get()); return identifier; } @@ -269,7 +269,7 @@ VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json const& _node FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json const& _node) { auto funcDef = createAsmNode(_node); - funcDef.name = YulString{member(_node, "name").get()}; + funcDef.name = YulName{member(_node, "name").get()}; if (_node.contains("parameters")) for (auto const& var: member(_node, "parameters")) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 2ae4dd805..41bef57fe 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -537,7 +537,7 @@ std::variant Parser::parseLiteralOrIdentifier(bool _unlimit { case Token::Identifier: { - Identifier identifier{createDebugData(), YulString{currentLiteral()}}; + Identifier identifier{createDebugData(), YulName{currentLiteral()}}; advance(); return identifier; } @@ -712,9 +712,9 @@ TypedName Parser::parseTypedName() return typedName; } -YulString Parser::expectAsmIdentifier() +YulName Parser::expectAsmIdentifier() { - YulString name{currentLiteral()}; + YulName name{currentLiteral()}; if (currentToken() == Token::Identifier && m_dialect.builtin(name)) fatalParserError(5568_error, "Cannot use builtin function name \"" + name.str() + "\" as identifier name."); // NOTE: We keep the expectation here to ensure the correct source location for the error above. diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 334890409..408c8029c 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -146,7 +146,7 @@ class Parser: public langutil::ParserBase FunctionDefinition parseFunctionDefinition(); FunctionCall parseCall(std::variant&& _initialOp); TypedName parseTypedName(); - YulString expectAsmIdentifier(); + YulName expectAsmIdentifier(); /// Reports an error if we are currently not inside the body part of a for loop. void checkBreakContinuePosition(std::string const& _which); diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 191fc5d2d..054f83a91 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -243,7 +243,7 @@ std::string AsmPrinter::formatTypedName(TypedName _variable) return formatDebugData(_variable) + _variable.name.str() + appendTypeName(_variable.type); } -std::string AsmPrinter::appendTypeName(YulString _type, bool _isBoolLiteral) const +std::string AsmPrinter::appendTypeName(YulName _type, bool _isBoolLiteral) const { if (m_dialect && !_type.empty()) { diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index d3f80b9a0..36ea06c76 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -24,7 +24,7 @@ #pragma once #include -#include +#include #include @@ -92,7 +92,7 @@ class AsmPrinter private: std::string formatTypedName(TypedName _variable); - std::string appendTypeName(YulString _type, bool _isBoolLiteral = false) const; + std::string appendTypeName(YulName _type, bool _isBoolLiteral = false) const; std::string formatDebugData(langutil::DebugData::ConstPtr const& _debugData, bool _statement); template std::string formatDebugData(T const& _node) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 92b03facf..ee78d525d 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -37,6 +37,7 @@ add_library(yul ScopeFiller.h Utilities.cpp Utilities.h + YulName.h YulString.h backends/evm/AbstractAssembly.h backends/evm/AsmCodeGen.cpp diff --git a/libyul/CompilabilityChecker.h b/libyul/CompilabilityChecker.h index c046df94f..89bb7aa7c 100644 --- a/libyul/CompilabilityChecker.h +++ b/libyul/CompilabilityChecker.h @@ -45,8 +45,8 @@ namespace solidity::yul struct CompilabilityChecker { CompilabilityChecker(Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation); - std::map> unreachableVariables; - std::map stackDeficit; + std::map> unreachableVariables; + std::map stackDeficit; }; } diff --git a/libyul/ControlFlowSideEffectsCollector.cpp b/libyul/ControlFlowSideEffectsCollector.cpp index c657fa17c..471a164e5 100644 --- a/libyul/ControlFlowSideEffectsCollector.cpp +++ b/libyul/ControlFlowSideEffectsCollector.cpp @@ -229,9 +229,9 @@ ControlFlowSideEffectsCollector::ControlFlowSideEffectsCollector( } } -std::map ControlFlowSideEffectsCollector::functionSideEffectsNamed() const +std::map ControlFlowSideEffectsCollector::functionSideEffectsNamed() const { - std::map result; + std::map result; for (auto&& [function, sideEffects]: m_functionSideEffects) yulAssert(result.insert({function->name, sideEffects}).second); return result; diff --git a/libyul/ControlFlowSideEffectsCollector.h b/libyul/ControlFlowSideEffectsCollector.h index a4ab2bfae..5a1c76297 100644 --- a/libyul/ControlFlowSideEffectsCollector.h +++ b/libyul/ControlFlowSideEffectsCollector.h @@ -101,7 +101,7 @@ class ControlFlowSideEffectsCollector return m_functionSideEffects; } /// Returns the side effects by function name, requires unique function names. - std::map functionSideEffectsNamed() const; + std::map functionSideEffectsNamed() const; private: /// @returns false if nothing could be processed. diff --git a/libyul/Dialect.cpp b/libyul/Dialect.cpp index 69ca1e9dc..f4f59ec26 100644 --- a/libyul/Dialect.cpp +++ b/libyul/Dialect.cpp @@ -25,7 +25,7 @@ using namespace solidity::yul; using namespace solidity::langutil; -Literal Dialect::zeroLiteralForType(solidity::yul::YulString _type) const +Literal Dialect::zeroLiteralForType(solidity::yul::YulName _type) const { if (_type == boolType && _type != defaultType) return {DebugData::create(), LiteralKind::Boolean, LiteralValue(false), _type}; @@ -41,7 +41,7 @@ Literal Dialect::trueLiteral() const return {DebugData::create(), LiteralKind::Number, LiteralValue(1), defaultType}; } -bool Dialect::validTypeForLiteral(LiteralKind _kind, LiteralValue const&, YulString _type) const +bool Dialect::validTypeForLiteral(LiteralKind _kind, LiteralValue const&, YulName _type) const { if (_kind == LiteralKind::Boolean) return _type == boolType; @@ -58,21 +58,20 @@ Dialect const& Dialect::yulDeprecated() { // TODO will probably change, especially the list of types. dialect = std::make_unique(); - dialect->defaultType = "u256"_yulstring; - dialect->boolType = "bool"_yulstring; + dialect->defaultType = "u256"_yulname; + dialect->boolType = "bool"_yulname; dialect->types = { - "bool"_yulstring, - "u8"_yulstring, - "s8"_yulstring, - "u32"_yulstring, - "s32"_yulstring, - "u64"_yulstring, - "s64"_yulstring, - "u128"_yulstring, - "s128"_yulstring, - "u256"_yulstring, - "s256"_yulstring - }; + "bool"_yulname, + "u8"_yulname, + "s8"_yulname, + "u32"_yulname, + "s32"_yulname, + "u64"_yulname, + "s64"_yulname, + "u128"_yulname, + "s128"_yulname, + "u256"_yulname, + "s256"_yulname}; }; return *dialect; diff --git a/libyul/Dialect.h b/libyul/Dialect.h index e3f270357..3362246a0 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include @@ -32,15 +32,14 @@ namespace solidity::yul { -class YulString; -using Type = YulString; +using Type = YulName; enum class LiteralKind; class LiteralValue; struct Literal; struct BuiltinFunction { - YulString name; + YulName name; std::vector parameters; std::vector returns; SideEffects sideEffects; @@ -63,35 +62,35 @@ struct Dialect Dialect& operator=(Dialect const&) = delete; /// Default type, can be omitted. - YulString defaultType; + YulName defaultType; /// Type used for the literals "true" and "false". - YulString boolType; - std::set types = {{}}; + YulName boolType; + std::set types = {{}}; /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. - virtual BuiltinFunction const* builtin(YulString /*_name*/) const { return nullptr; } + virtual BuiltinFunction const* builtin(YulName /*_name*/) const { return nullptr; } /// @returns true if the identifier is reserved. This includes the builtins too. - virtual bool reservedIdentifier(YulString _name) const { return builtin(_name) != nullptr; } + virtual bool reservedIdentifier(YulName _name) const { return builtin(_name) != nullptr; } - virtual BuiltinFunction const* discardFunction(YulString /* _type */) const { return nullptr; } - virtual BuiltinFunction const* equalityFunction(YulString /* _type */) const { return nullptr; } + virtual BuiltinFunction const* discardFunction(YulName /* _type */) const { return nullptr; } + virtual BuiltinFunction const* equalityFunction(YulName /* _type */) const { return nullptr; } virtual BuiltinFunction const* booleanNegationFunction() const { return nullptr; } - virtual BuiltinFunction const* memoryStoreFunction(YulString /* _type */) const { return nullptr; } - virtual BuiltinFunction const* memoryLoadFunction(YulString /* _type */) const { return nullptr; } - virtual BuiltinFunction const* storageStoreFunction(YulString /* _type */) const { return nullptr; } - virtual BuiltinFunction const* storageLoadFunction(YulString /* _type */) const { return nullptr; } - virtual YulString hashFunction(YulString /* _type */ ) const { return YulString{}; } + virtual BuiltinFunction const* memoryStoreFunction(YulName /* _type */) const { return nullptr; } + virtual BuiltinFunction const* memoryLoadFunction(YulName /* _type */) const { return nullptr; } + virtual BuiltinFunction const* storageStoreFunction(YulName /* _type */) const { return nullptr; } + virtual BuiltinFunction const* storageLoadFunction(YulName /* _type */) const { return nullptr; } + virtual YulName hashFunction(YulName /* _type */ ) const { return YulName{}; } /// Check whether the given type is legal for the given literal value. /// Should only be called if the type exists in the dialect at all. - virtual bool validTypeForLiteral(LiteralKind _kind, LiteralValue const& _value, YulString _type) const; + virtual bool validTypeForLiteral(LiteralKind _kind, LiteralValue const& _value, YulName _type) const; - virtual Literal zeroLiteralForType(YulString _type) const; + virtual Literal zeroLiteralForType(YulName _type) const; virtual Literal trueLiteral() const; - virtual std::set fixedFunctionNames() const { return {}; } + virtual std::set fixedFunctionNames() const { return {}; } Dialect() = default; virtual ~Dialect() = default; diff --git a/libyul/Exceptions.h b/libyul/Exceptions.h index 45c681a5d..f92268180 100644 --- a/libyul/Exceptions.h +++ b/libyul/Exceptions.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include @@ -40,18 +40,18 @@ struct YulAssertion: virtual YulException {}; struct StackTooDeepError: virtual YulException { - StackTooDeepError(YulString _variable, int _depth, std::string const& _message): + StackTooDeepError(YulName _variable, int _depth, std::string const& _message): variable(_variable), depth(_depth) { *this << util::errinfo_comment(_message); } - StackTooDeepError(YulString _functionName, YulString _variable, int _depth, std::string const& _message): + StackTooDeepError(YulName _functionName, YulName _variable, int _depth, std::string const& _message): functionName(_functionName), variable(_variable), depth(_depth) { *this << util::errinfo_comment(_message); } - YulString functionName; - YulString variable; + YulName functionName; + YulName variable; int depth; }; diff --git a/libyul/FunctionReferenceResolver.h b/libyul/FunctionReferenceResolver.h index 8c1385adb..dcc5f50e5 100644 --- a/libyul/FunctionReferenceResolver.h +++ b/libyul/FunctionReferenceResolver.h @@ -41,7 +41,7 @@ class FunctionReferenceResolver: private ASTWalker void operator()(Block const& _block) override; std::map m_functionReferences; - std::vector> m_scopes; + std::vector> m_scopes; }; diff --git a/libyul/Object.h b/libyul/Object.h index c1ca9244d..af354005b 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -22,7 +22,6 @@ #pragma once #include -#include #include #include diff --git a/libyul/ObjectParser.h b/libyul/ObjectParser.h index 08a852991..a8f75d373 100644 --- a/libyul/ObjectParser.h +++ b/libyul/ObjectParser.h @@ -21,7 +21,6 @@ #pragma once -#include #include #include diff --git a/libyul/Scope.cpp b/libyul/Scope.cpp index 4471aa531..89bdfc674 100644 --- a/libyul/Scope.cpp +++ b/libyul/Scope.cpp @@ -25,7 +25,7 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::util; -bool Scope::registerVariable(YulString _name, YulType const& _type) +bool Scope::registerVariable(YulName _name, YulType const& _type) { if (exists(_name)) return false; @@ -36,7 +36,7 @@ bool Scope::registerVariable(YulString _name, YulType const& _type) return true; } -bool Scope::registerFunction(YulString _name, std::vector _arguments, std::vector _returns) +bool Scope::registerFunction(YulName _name, std::vector _arguments, std::vector _returns) { if (exists(_name)) return false; @@ -44,7 +44,7 @@ bool Scope::registerFunction(YulString _name, std::vector _arguments, s return true; } -Scope::Identifier* Scope::lookup(YulString _name) +Scope::Identifier* Scope::lookup(YulName _name) { bool crossedFunctionBoundary = false; for (Scope* s = this; s; s = s->superScope) @@ -64,7 +64,7 @@ Scope::Identifier* Scope::lookup(YulString _name) return nullptr; } -bool Scope::exists(YulString _name) const +bool Scope::exists(YulName _name) const { if (identifiers.count(_name)) return true; diff --git a/libyul/Scope.h b/libyul/Scope.h index f9ac3830a..027597290 100644 --- a/libyul/Scope.h +++ b/libyul/Scope.h @@ -23,7 +23,7 @@ #include -#include +#include #include #include @@ -35,25 +35,25 @@ namespace solidity::yul struct Scope { - using YulType = YulString; + using YulType = YulName; struct Variable { YulType type; - YulString name; + YulName name; }; struct Function { std::vector arguments; std::vector returns; - YulString name; + YulName name; }; using Identifier = std::variant; - bool registerVariable(YulString _name, YulType const& _type); + bool registerVariable(YulName _name, YulType const& _type); bool registerFunction( - YulString _name, + YulName _name, std::vector _arguments, std::vector _returns ); @@ -63,12 +63,12 @@ struct Scope /// will any lookups across assembly boundaries. /// The pointer will be invalidated if the scope is modified. /// @param _crossedFunction if true, we already crossed a function boundary during recursive lookup - Identifier* lookup(YulString _name); + Identifier* lookup(YulName _name); /// Looks up the identifier in this and super scopes (will not find variables across function /// boundaries and generally stops at assembly boundaries) and calls the visitor, returns /// false if not found. template - bool lookup(YulString _name, V const& _visitor) + bool lookup(YulName _name, V const& _visitor) { if (Identifier* id = lookup(_name)) { @@ -80,7 +80,7 @@ struct Scope } /// @returns true if the name exists in this scope or in super scopes (also searches /// across function and assembly boundaries). - bool exists(YulString _name) const; + bool exists(YulName _name) const; /// @returns the number of variables directly registered inside the scope. size_t numberOfVariables() const; @@ -91,7 +91,7 @@ struct Scope /// If true, variables from the super scope are not visible here (other identifiers are), /// but they are still taken into account to prevent shadowing. bool functionScope = false; - std::map identifiers; + std::map identifiers; }; } diff --git a/libyul/YulName.h b/libyul/YulName.h new file mode 100644 index 000000000..34fd6a5a2 --- /dev/null +++ b/libyul/YulName.h @@ -0,0 +1,26 @@ +/* + 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 + +#pragma once + +#include + +namespace solidity::yul +{ +using YulName = YulString; +} diff --git a/libyul/YulString.h b/libyul/YulString.h index 7dbaf1b84..89d35b123 100644 --- a/libyul/YulString.h +++ b/libyul/YulString.h @@ -162,7 +162,7 @@ class YulString YulStringRepository::Handle m_handle{ 0, YulStringRepository::emptyHash() }; }; -inline YulString operator "" _yulstring(char const* _string, std::size_t _size) +inline YulString operator "" _yulname(char const* _string, std::size_t _size) { return YulString(std::string(_string, _size)); } diff --git a/libyul/backends/evm/ConstantOptimiser.cpp b/libyul/backends/evm/ConstantOptimiser.cpp index 7b17f7d89..2ab77f84e 100644 --- a/libyul/backends/evm/ConstantOptimiser.cpp +++ b/libyul/backends/evm/ConstantOptimiser.cpp @@ -129,7 +129,7 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu if (numberEncodingSize(~_value) < numberEncodingSize(_value)) // Negated is shorter to represent - routine = min(std::move(routine), represent("not"_yulstring, findRepresentation(~_value))); + routine = min(std::move(routine), represent("not"_yulname, findRepresentation(~_value))); // Decompose value into a * 2**k + b where abs(b) << 2**k for (unsigned bits = 255; bits > 8 && m_maxSteps > 0; --bits) @@ -152,21 +152,21 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu continue; Representation newRoutine; if (m_dialect.evmVersion().hasBitwiseShifting()) - newRoutine = represent("shl"_yulstring, represent(bits), findRepresentation(upperPart)); + newRoutine = represent("shl"_yulname, represent(bits), findRepresentation(upperPart)); else { - newRoutine = represent("exp"_yulstring, represent(2), represent(bits)); + newRoutine = represent("exp"_yulname, represent(2), represent(bits)); if (upperPart != 1) - newRoutine = represent("mul"_yulstring, findRepresentation(upperPart), newRoutine); + newRoutine = represent("mul"_yulname, findRepresentation(upperPart), newRoutine); } if (newRoutine.cost >= routine.cost) continue; if (lowerPart > 0) - newRoutine = represent("add"_yulstring, newRoutine, findRepresentation(u256(abs(lowerPart)))); + newRoutine = represent("add"_yulname, newRoutine, findRepresentation(u256(abs(lowerPart)))); else if (lowerPart < 0) - newRoutine = represent("sub"_yulstring, newRoutine, findRepresentation(u256(abs(lowerPart)))); + newRoutine = represent("sub"_yulname, newRoutine, findRepresentation(u256(abs(lowerPart)))); if (m_maxSteps > 0) m_maxSteps--; @@ -185,7 +185,7 @@ Representation RepresentationFinder::represent(u256 const& _value) const } Representation RepresentationFinder::represent( - YulString _instruction, + YulName _instruction, Representation const& _argument ) const { @@ -200,7 +200,7 @@ Representation RepresentationFinder::represent( } Representation RepresentationFinder::represent( - YulString _instruction, + YulName _instruction, Representation const& _arg1, Representation const& _arg2 ) const diff --git a/libyul/backends/evm/ConstantOptimiser.h b/libyul/backends/evm/ConstantOptimiser.h index 280f50bf9..35d7dfa43 100644 --- a/libyul/backends/evm/ConstantOptimiser.h +++ b/libyul/backends/evm/ConstantOptimiser.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include #include #include @@ -93,8 +93,8 @@ class RepresentationFinder Representation const& findRepresentation(u256 const& _value); Representation represent(u256 const& _value) const; - Representation represent(YulString _instruction, Representation const& _arg) const; - Representation represent(YulString _instruction, Representation const& _arg1, Representation const& _arg2) const; + Representation represent(YulName _instruction, Representation const& _arg) const; + Representation represent(YulName _instruction, Representation const& _arg1, Representation const& _arg2) const; Representation min(Representation _a, Representation _b); diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index a5e9613b5..b4d1cdf15 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -336,8 +336,8 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) langutil::DebugData::ConstPtr preSwitchDebugData = debugDataOf(_switch); auto ghostVariableId = m_graph.ghostVariables.size(); - YulString ghostVariableName("GHOST[" + std::to_string(ghostVariableId) + "]"); - auto& ghostVar = m_graph.ghostVariables.emplace_back(Scope::Variable{""_yulstring, ghostVariableName}); + YulName ghostVariableName("GHOST[" + std::to_string(ghostVariableId) + "]"); + auto& ghostVar = m_graph.ghostVariables.emplace_back(Scope::Variable{""_yulname, ghostVariableName}); // Artificially generate: // let := @@ -357,7 +357,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) auto makeValueCompare = [&](Case const& _case) { yul::FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(yul::FunctionCall{ debugDataOf(_case), - yul::Identifier{{}, "eq"_yulstring}, + yul::Identifier{{}, "eq"_yulname}, {*_case.value, Identifier{{}, ghostVariableName}} }); CFG::Operation& operation = m_currentBlock->operations.emplace_back(CFG::Operation{ @@ -578,7 +578,7 @@ Stack ControlFlowGraphBuilder::visitAssignmentRightHandSide(Expression const& _e }, _expression); } -Scope::Function const& ControlFlowGraphBuilder::lookupFunction(YulString _name) const +Scope::Function const& ControlFlowGraphBuilder::lookupFunction(YulName _name) const { Scope::Function const* function = nullptr; yulAssert(m_scope->lookup(_name, util::GenericVisitor{ @@ -589,7 +589,7 @@ Scope::Function const& ControlFlowGraphBuilder::lookupFunction(YulString _name) return *function; } -Scope::Variable const& ControlFlowGraphBuilder::lookupVariable(YulString _name) const +Scope::Variable const& ControlFlowGraphBuilder::lookupVariable(YulName _name) const { yulAssert(m_scope, ""); Scope::Variable const* var = nullptr; diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.h b/libyul/backends/evm/ControlFlowGraphBuilder.h index 5007d3610..77feaea7b 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.h +++ b/libyul/backends/evm/ControlFlowGraphBuilder.h @@ -63,8 +63,8 @@ class ControlFlowGraphBuilder Stack const& visitFunctionCall(FunctionCall const&); Stack visitAssignmentRightHandSide(Expression const& _expression, size_t _expectedSlotCount); - Scope::Function const& lookupFunction(YulString _name) const; - Scope::Variable const& lookupVariable(YulString _name) const; + Scope::Function const& lookupFunction(YulName _name) const; + Scope::Variable const& lookupVariable(YulName _name) const; /// Resets m_currentBlock to enforce a subsequent explicit reassignment. void makeConditionalJump( langutil::DebugData::ConstPtr _debugData, diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index bdce395ef..211247230 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -79,7 +79,7 @@ CodeTransform::CodeTransform( } } -void CodeTransform::decreaseReference(YulString, Scope::Variable const& _var) +void CodeTransform::decreaseReference(YulName, Scope::Variable const& _var) { if (!m_allowStackOpt) return; @@ -158,7 +158,7 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl) for (size_t varIndex = 0; varIndex < numVariables; ++varIndex) { size_t varIndexReverse = numVariables - 1 - varIndex; - YulString varName = _varDecl.variables[varIndexReverse].name; + YulName varName = _varDecl.variables[varIndexReverse].name; auto& var = std::get(m_scope->identifiers.at(varName)); m_context->variableStackHeights[&var] = heightAtStart + varIndexReverse; if (!m_allowStackOpt) @@ -457,7 +457,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) { StackTooDeepError error( _function.name, - YulString{}, + YulName{}, static_cast(stackLayout.size()) - 17, "The function " + _function.name.str() + @@ -667,7 +667,7 @@ bool statementNeedsReturnVariableSetup(Statement const& _statement, std::vector< std::holds_alternative(_statement) ) { - std::map references = VariableReferencesCounter::countReferences(_statement); + std::map references = VariableReferencesCounter::countReferences(_statement); auto isReferenced = [&references](TypedName const& _returnVariable) { return references.count(_returnVariable.name); }; @@ -771,7 +771,7 @@ void CodeTransform::generateAssignment(Identifier const& _variableName) } } -size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulString _varName, bool _forSwap) +size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulName _varName, bool _forSwap) { yulAssert(m_context->variableStackHeights.count(&_var), ""); size_t heightDiff = static_cast(m_assembly.stackHeight()) - m_context->variableStackHeights[&_var]; @@ -795,7 +795,7 @@ size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulString return heightDiff; } -int CodeTransform::variableStackHeight(YulString _name) const +int CodeTransform::variableStackHeight(YulName _name) const { Scope::Variable const* var = std::get_if(m_scope->lookup(_name)); yulAssert(var, ""); diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h index bad9a357f..0e6a9d8be 100644 --- a/libyul/backends/evm/EVMCodeTransform.h +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -118,7 +118,7 @@ class CodeTransform std::optional _functionExitLabel ); - void decreaseReference(YulString _name, Scope::Variable const& _var); + void decreaseReference(YulName _name, Scope::Variable const& _var); bool unreferenced(Scope::Variable const& _var) const; /// Marks slots of variables that are not used anymore /// and were defined in the current scope for reuse. @@ -165,10 +165,10 @@ class CodeTransform /// the (positive) stack height difference otherwise. /// @param _forSwap if true, produces stack error if the difference is invalid for a swap /// opcode, otherwise checks for validity for a dup opcode. - size_t variableHeightDiff(Scope::Variable const& _var, YulString _name, bool _forSwap); + size_t variableHeightDiff(Scope::Variable const& _var, YulName _name, bool _forSwap); /// Determines the stack height of the given variable. Throws if the variable is not in scope. - int variableStackHeight(YulString _name) const; + int variableStackHeight(YulName _name) const; void expectDeposit(int _deposit, int _oldHeight) const; @@ -198,7 +198,7 @@ class CodeTransform BuiltinContext& m_builtinContext; bool const m_allowStackOpt = true; UseNamedLabels const m_useNamedLabelsForFunctions = UseNamedLabels::Never; - std::set m_assignedNamedLabels; + std::set m_assignedNamedLabels; ExternalIdentifierAccess::CodeGenerator m_identifierAccessCodeGen; std::shared_ptr m_context; diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index d3b9c34bc..50ede8c76 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -46,7 +46,7 @@ using namespace solidity::util; namespace { -std::pair createEVMFunction( +std::pair createEVMFunction( langutil::EVMVersion _evmVersion, std::string const& _name, evmasm::Instruction _instruction @@ -54,7 +54,7 @@ std::pair createEVMFunction( { evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction, _evmVersion); BuiltinFunctionForEVM f; - f.name = YulString{_name}; + f.name = YulName{_name}; f.parameters.resize(static_cast(info.args)); f.returns.resize(static_cast(info.ret)); f.sideEffects = EVMDialect::sideEffectsOfInstruction(_instruction); @@ -83,11 +83,11 @@ std::pair createEVMFunction( _assembly.appendInstruction(_instruction); }; - YulString name = f.name; + YulName name = f.name; return {name, std::move(f)}; } -std::pair createFunction( +std::pair createFunction( std::string _name, size_t _params, size_t _returns, @@ -98,7 +98,7 @@ std::pair createFunction( { yulAssert(_literalArguments.size() == _params || _literalArguments.empty(), ""); - YulString name{std::move(_name)}; + YulName name{std::move(_name)}; BuiltinFunctionForEVM f; f.name = name; f.parameters.resize(_params); @@ -111,7 +111,7 @@ std::pair createFunction( return {name, f}; } -std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) +std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) { // TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name // basefee for VMs before london. @@ -157,7 +157,7 @@ std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) (_instr == evmasm::Instruction::TSTORE || _instr == evmasm::Instruction::TLOAD); }; - std::set reserved; + std::set reserved; for (auto const& instr: evmasm::c_instructions) { std::string name = toLower(instr.first); @@ -171,18 +171,18 @@ std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) ) reserved.emplace(name); } - reserved += std::vector{ - "linkersymbol"_yulstring, - "datasize"_yulstring, - "dataoffset"_yulstring, - "datacopy"_yulstring, - "setimmutable"_yulstring, - "loadimmutable"_yulstring, + reserved += std::vector{ + "linkersymbol"_yulname, + "datasize"_yulname, + "dataoffset"_yulname, + "datacopy"_yulname, + "setimmutable"_yulname, + "loadimmutable"_yulname, }; return reserved; } -std::map createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess) +std::map createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess) { // Exclude prevrandao as builtin for VMs before paris and difficulty for VMs after paris. @@ -191,7 +191,7 @@ std::map createBuiltins(langutil::EVMVersion _ return (_instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris()) || (_instrName == "difficulty" && _evmVersion >= langutil::EVMVersion::paris()); }; - std::map builtins; + std::map builtins; for (auto const& instr: evmasm::c_instructions) { std::string name = toLower(instr.first); @@ -248,7 +248,7 @@ std::map createBuiltins(langutil::EVMVersion _ yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); Expression const& arg = _call.arguments.front(); - YulString const dataName (formatLiteral(std::get(arg))); + YulName const dataName (formatLiteral(std::get(arg))); if (_context.currentObject->name == dataName.str()) _assembly.appendAssemblySize(); else @@ -269,7 +269,7 @@ std::map createBuiltins(langutil::EVMVersion _ yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); Expression const& arg = _call.arguments.front(); - YulString const dataName (formatLiteral(std::get(arg))); + YulName const dataName (formatLiteral(std::get(arg))); if (_context.currentObject->name == dataName.str()) _assembly.appendConstant(0); else @@ -368,7 +368,7 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, bool _objectAccess): { } -BuiltinFunctionForEVM const* EVMDialect::builtin(YulString _name) const +BuiltinFunctionForEVM const* EVMDialect::builtin(YulName _name) const { if (m_objectAccess) { @@ -383,7 +383,7 @@ BuiltinFunctionForEVM const* EVMDialect::builtin(YulString _name) const return nullptr; } -bool EVMDialect::reservedIdentifier(YulString _name) const +bool EVMDialect::reservedIdentifier(YulName _name) const { if (m_objectAccess) if (_name.str().substr(0, "verbatim"s.size()) == "verbatim") @@ -465,8 +465,8 @@ BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, siz EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess): EVMDialect(_evmVersion, _objectAccess) { - defaultType = "u256"_yulstring; - boolType = "bool"_yulstring; + defaultType = "u256"_yulname; + boolType = "bool"_yulname; types = {defaultType, boolType}; // Set all types to ``defaultType`` @@ -478,43 +478,43 @@ EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectA r = defaultType; } - m_functions["lt"_yulstring].returns = {"bool"_yulstring}; - m_functions["gt"_yulstring].returns = {"bool"_yulstring}; - m_functions["slt"_yulstring].returns = {"bool"_yulstring}; - m_functions["sgt"_yulstring].returns = {"bool"_yulstring}; - m_functions["eq"_yulstring].returns = {"bool"_yulstring}; + m_functions["lt"_yulname].returns = {"bool"_yulname}; + m_functions["gt"_yulname].returns = {"bool"_yulname}; + m_functions["slt"_yulname].returns = {"bool"_yulname}; + m_functions["sgt"_yulname].returns = {"bool"_yulname}; + m_functions["eq"_yulname].returns = {"bool"_yulname}; // "not" and "bitnot" replace "iszero" and "not" - m_functions["bitnot"_yulstring] = m_functions["not"_yulstring]; - m_functions["bitnot"_yulstring].name = "bitnot"_yulstring; - m_functions["not"_yulstring] = m_functions["iszero"_yulstring]; - m_functions["not"_yulstring].name = "not"_yulstring; - m_functions["not"_yulstring].returns = {"bool"_yulstring}; - m_functions["not"_yulstring].parameters = {"bool"_yulstring}; - m_functions.erase("iszero"_yulstring); - - m_functions["bitand"_yulstring] = m_functions["and"_yulstring]; - m_functions["bitand"_yulstring].name = "bitand"_yulstring; - m_functions["bitor"_yulstring] = m_functions["or"_yulstring]; - m_functions["bitor"_yulstring].name = "bitor"_yulstring; - m_functions["bitxor"_yulstring] = m_functions["xor"_yulstring]; - m_functions["bitxor"_yulstring].name = "bitxor"_yulstring; - m_functions["and"_yulstring].parameters = {"bool"_yulstring, "bool"_yulstring}; - m_functions["and"_yulstring].returns = {"bool"_yulstring}; - m_functions["or"_yulstring].parameters = {"bool"_yulstring, "bool"_yulstring}; - m_functions["or"_yulstring].returns = {"bool"_yulstring}; - m_functions["xor"_yulstring].parameters = {"bool"_yulstring, "bool"_yulstring}; - m_functions["xor"_yulstring].returns = {"bool"_yulstring}; - m_functions["popbool"_yulstring] = m_functions["pop"_yulstring]; - m_functions["popbool"_yulstring].name = "popbool"_yulstring; - m_functions["popbool"_yulstring].parameters = {"bool"_yulstring}; + m_functions["bitnot"_yulname] = m_functions["not"_yulname]; + m_functions["bitnot"_yulname].name = "bitnot"_yulname; + m_functions["not"_yulname] = m_functions["iszero"_yulname]; + m_functions["not"_yulname].name = "not"_yulname; + m_functions["not"_yulname].returns = {"bool"_yulname}; + m_functions["not"_yulname].parameters = {"bool"_yulname}; + m_functions.erase("iszero"_yulname); + + m_functions["bitand"_yulname] = m_functions["and"_yulname]; + m_functions["bitand"_yulname].name = "bitand"_yulname; + m_functions["bitor"_yulname] = m_functions["or"_yulname]; + m_functions["bitor"_yulname].name = "bitor"_yulname; + m_functions["bitxor"_yulname] = m_functions["xor"_yulname]; + m_functions["bitxor"_yulname].name = "bitxor"_yulname; + m_functions["and"_yulname].parameters = {"bool"_yulname, "bool"_yulname}; + m_functions["and"_yulname].returns = {"bool"_yulname}; + m_functions["or"_yulname].parameters = {"bool"_yulname, "bool"_yulname}; + m_functions["or"_yulname].returns = {"bool"_yulname}; + m_functions["xor"_yulname].parameters = {"bool"_yulname, "bool"_yulname}; + m_functions["xor"_yulname].returns = {"bool"_yulname}; + m_functions["popbool"_yulname] = m_functions["pop"_yulname]; + m_functions["popbool"_yulname].name = "popbool"_yulname; + m_functions["popbool"_yulname].parameters = {"bool"_yulname}; m_functions.insert(createFunction("bool_to_u256", 1, 1, {}, {}, []( FunctionCall const&, AbstractAssembly&, BuiltinContext& ) {})); - m_functions["bool_to_u256"_yulstring].parameters = {"bool"_yulstring}; - m_functions["bool_to_u256"_yulstring].returns = {"u256"_yulstring}; + m_functions["bool_to_u256"_yulname].parameters = {"bool"_yulname}; + m_functions["bool_to_u256"_yulname].returns = {"u256"_yulname}; m_functions.insert(createFunction("u256_to_bool", 1, 1, {}, {}, []( FunctionCall const&, AbstractAssembly& _assembly, @@ -530,29 +530,29 @@ EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectA _assembly.appendInstruction(evmasm::Instruction::INVALID); _assembly.appendLabel(inRange); })); - m_functions["u256_to_bool"_yulstring].parameters = {"u256"_yulstring}; - m_functions["u256_to_bool"_yulstring].returns = {"bool"_yulstring}; + m_functions["u256_to_bool"_yulname].parameters = {"u256"_yulname}; + m_functions["u256_to_bool"_yulname].returns = {"bool"_yulname}; } -BuiltinFunctionForEVM const* EVMDialectTyped::discardFunction(YulString _type) const +BuiltinFunctionForEVM const* EVMDialectTyped::discardFunction(YulName _type) const { - if (_type == "bool"_yulstring) - return builtin("popbool"_yulstring); + if (_type == "bool"_yulname) + return builtin("popbool"_yulname); else { yulAssert(_type == defaultType, ""); - return builtin("pop"_yulstring); + return builtin("pop"_yulname); } } -BuiltinFunctionForEVM const* EVMDialectTyped::equalityFunction(YulString _type) const +BuiltinFunctionForEVM const* EVMDialectTyped::equalityFunction(YulName _type) const { - if (_type == "bool"_yulstring) + if (_type == "bool"_yulname) return nullptr; else { yulAssert(_type == defaultType, ""); - return builtin("eq"_yulstring); + return builtin("eq"_yulname); } } diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index f0455a8e4..7db1ec09d 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -33,8 +33,7 @@ namespace solidity::yul { -class YulString; -using Type = YulString; +using Type = YulName; struct FunctionCall; struct Object; @@ -70,19 +69,19 @@ struct EVMDialect: public Dialect EVMDialect(langutil::EVMVersion _evmVersion, bool _objectAccess); /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. - BuiltinFunctionForEVM const* builtin(YulString _name) const override; + BuiltinFunctionForEVM const* builtin(YulName _name) const override; /// @returns true if the identifier is reserved. This includes the builtins too. - bool reservedIdentifier(YulString _name) const override; + bool reservedIdentifier(YulName _name) const override; - BuiltinFunctionForEVM const* discardFunction(YulString /*_type*/) const override { return builtin("pop"_yulstring); } - BuiltinFunctionForEVM const* equalityFunction(YulString /*_type*/) const override { return builtin("eq"_yulstring); } - BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("iszero"_yulstring); } - BuiltinFunctionForEVM const* memoryStoreFunction(YulString /*_type*/) const override { return builtin("mstore"_yulstring); } - BuiltinFunctionForEVM const* memoryLoadFunction(YulString /*_type*/) const override { return builtin("mload"_yulstring); } - BuiltinFunctionForEVM const* storageStoreFunction(YulString /*_type*/) const override { return builtin("sstore"_yulstring); } - BuiltinFunctionForEVM const* storageLoadFunction(YulString /*_type*/) const override { return builtin("sload"_yulstring); } - YulString hashFunction(YulString /*_type*/) const override { return "keccak256"_yulstring; } + BuiltinFunctionForEVM const* discardFunction(YulName /*_type*/) const override { return builtin("pop"_yulname); } + BuiltinFunctionForEVM const* equalityFunction(YulName /*_type*/) const override { return builtin("eq"_yulname); } + BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("iszero"_yulname); } + BuiltinFunctionForEVM const* memoryStoreFunction(YulName /*_type*/) const override { return builtin("mstore"_yulname); } + BuiltinFunctionForEVM const* memoryLoadFunction(YulName /*_type*/) const override { return builtin("mload"_yulname); } + BuiltinFunctionForEVM const* storageStoreFunction(YulName /*_type*/) const override { return builtin("sstore"_yulname); } + BuiltinFunctionForEVM const* storageLoadFunction(YulName /*_type*/) const override { return builtin("sload"_yulname); } + YulName hashFunction(YulName /*_type*/) const override { return "keccak256"_yulname; } static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version); static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _version); @@ -98,9 +97,9 @@ struct EVMDialect: public Dialect bool const m_objectAccess; langutil::EVMVersion const m_evmVersion; - std::map m_functions; + std::map m_functions; std::map, std::shared_ptr> mutable m_verbatimFunctions; - std::set m_reserved; + std::set m_reserved; }; /** @@ -118,9 +117,9 @@ struct EVMDialectTyped: public EVMDialect /// Constructor, should only be used internally. Use the factory function below. EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess); - BuiltinFunctionForEVM const* discardFunction(YulString _type) const override; - BuiltinFunctionForEVM const* equalityFunction(YulString _type) const override; - BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("not"_yulstring); } + BuiltinFunctionForEVM const* discardFunction(YulName _type) const override; + BuiltinFunctionForEVM const* equalityFunction(YulName _type) const override; + BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("not"_yulname); } static EVMDialectTyped const& instance(langutil::EVMVersion _version); }; diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index 81a345f90..422c08bf9 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -92,7 +92,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) { std::vector memoryGuardCalls = findFunctionCalls( std::as_const(*_object.code), - "memoryguard"_yulstring + "memoryguard"_yulname ); auto stackError = stackErrors.front(); std::string msg = stackError.comment() ? *stackError.comment() : ""; diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 047014e3d..a6b867aba 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -185,7 +185,7 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( m_stackLayout(_stackLayout), m_functionLabels([&](){ std::map functionLabels; - std::set assignedFunctionNames; + std::set assignedFunctionNames; for (Scope::Function const* function: m_dfg.functions) { CFG::FunctionInfo const& functionInfo = m_dfg.functionInfo.at(function); @@ -242,7 +242,7 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr static constexpr auto slotVariableName = [](StackSlot const& _slot) { return std::visit(util::GenericVisitor{ [](VariableSlot const& _var) { return _var.variable.get().name; }, - [](auto const&) { return YulString{}; } + [](auto const&) { return YulName{}; } }, _slot); }; @@ -264,14 +264,14 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr { int deficit = static_cast(_i) - 16; StackSlot const& deepSlot = m_stack.at(m_stack.size() - _i - 1); - YulString varNameDeep = slotVariableName(deepSlot); - YulString varNameTop = slotVariableName(m_stack.back()); + YulName varNameDeep = slotVariableName(deepSlot); + YulName varNameTop = slotVariableName(m_stack.back()); std::string msg = "Cannot swap " + (varNameDeep.empty() ? "Slot " + stackSlotToString(deepSlot) : "Variable " + varNameDeep.str()) + " with " + (varNameTop.empty() ? "Slot " + stackSlotToString(m_stack.back()) : "Variable " + varNameTop.str()) + ": too deep in the stack by " + std::to_string(deficit) + " slots in " + stackToString(m_stack); m_stackErrors.emplace_back(StackTooDeepError( - m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulString{}, + m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulName{}, varNameDeep.empty() ? varNameTop : varNameDeep, deficit, msg @@ -295,12 +295,12 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr else if (!canBeFreelyGenerated(_slot)) { int deficit = static_cast(*depth - 15); - YulString varName = slotVariableName(_slot); + YulName varName = slotVariableName(_slot); std::string msg = (varName.empty() ? "Slot " + stackSlotToString(_slot) : "Variable " + varName.str()) + " is " + std::to_string(*depth - 15) + " too deep in the stack " + stackToString(m_stack); m_stackErrors.emplace_back(StackTooDeepError( - m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulString{}, + m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulName{}, varName, deficit, msg diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 954c9f2af..c781d7c1b 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -58,17 +58,17 @@ StackLayout StackLayoutGenerator::run(CFG const& _cfg) return stackLayout; } -std::map> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg) +std::map> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg) { - std::map> stackTooDeepErrors; - stackTooDeepErrors[YulString{}] = reportStackTooDeep(_cfg, YulString{}); + std::map> stackTooDeepErrors; + stackTooDeepErrors[YulName{}] = reportStackTooDeep(_cfg, YulName{}); for (auto const& function: _cfg.functions) if (auto errors = reportStackTooDeep(_cfg, function->name); !errors.empty()) stackTooDeepErrors[function->name] = std::move(errors); return stackTooDeepErrors; } -std::vector StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulString _functionName) +std::vector StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulName _functionName) { StackLayout stackLayout; CFG::FunctionInfo const* functionInfo = nullptr; @@ -102,7 +102,7 @@ std::vector findStackTooDeep(Stack const& _s Stack currentStack = _source; std::vector stackTooDeepErrors; auto getVariableChoices = [](auto&& _range) { - std::vector result; + std::vector result; for (auto const& slot: _range) if (auto const* variableSlot = std::get_if(&slot)) if (!util::contains(result, variableSlot->variable.get().name)) diff --git a/libyul/backends/evm/StackLayoutGenerator.h b/libyul/backends/evm/StackLayoutGenerator.h index d04b80bdc..fc846a9de 100644 --- a/libyul/backends/evm/StackLayoutGenerator.h +++ b/libyul/backends/evm/StackLayoutGenerator.h @@ -52,18 +52,18 @@ class StackLayoutGenerator /// Number of slots that need to be saved. size_t deficit = 0; /// Set of variables, eliminating which would decrease the stack deficit. - std::vector variableChoices; + std::vector variableChoices; }; static StackLayout run(CFG const& _cfg); /// @returns a map from function names to the stack too deep errors occurring in that function. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// The empty string is mapped to the stack too deep errors of the main entry point. - static std::map> reportStackTooDeep(CFG const& _cfg); + static std::map> reportStackTooDeep(CFG const& _cfg); /// @returns all stack too deep errors in the function named @a _functionName. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// If @a _functionName is empty, the stack too deep errors of the main entry point are reported instead. - static std::vector reportStackTooDeep(CFG const& _cfg, YulString _functionName); + static std::vector reportStackTooDeep(CFG const& _cfg, YulName _functionName); private: StackLayoutGenerator(StackLayout& _context, CFG::FunctionInfo const* _functionInfo); diff --git a/libyul/backends/evm/VariableReferenceCounter.cpp b/libyul/backends/evm/VariableReferenceCounter.cpp index c2afb399d..9f4857887 100644 --- a/libyul/backends/evm/VariableReferenceCounter.cpp +++ b/libyul/backends/evm/VariableReferenceCounter.cpp @@ -71,7 +71,7 @@ void VariableReferenceCounter::operator()(Block const& _block) m_scope = originalScope; } -void VariableReferenceCounter::increaseRefIfFound(YulString _variableName) +void VariableReferenceCounter::increaseRefIfFound(YulName _variableName) { m_scope->lookup(_variableName, util::GenericVisitor{ [&](Scope::Variable const& _var) diff --git a/libyul/backends/evm/VariableReferenceCounter.h b/libyul/backends/evm/VariableReferenceCounter.h index ba6404b17..755522793 100644 --- a/libyul/backends/evm/VariableReferenceCounter.h +++ b/libyul/backends/evm/VariableReferenceCounter.h @@ -58,7 +58,7 @@ struct VariableReferenceCounter: public yul::ASTWalker ): m_info(_assemblyInfo) {} - void increaseRefIfFound(YulString _variableName); + void increaseRefIfFound(YulName _variableName); AsmAnalysisInfo const& m_info; Scope* m_scope = nullptr; diff --git a/libyul/optimiser/ASTCopier.cpp b/libyul/optimiser/ASTCopier.cpp index 9f4107941..8efe29613 100644 --- a/libyul/optimiser/ASTCopier.cpp +++ b/libyul/optimiser/ASTCopier.cpp @@ -83,7 +83,7 @@ Statement ASTCopier::operator()(Switch const& _switch) Statement ASTCopier::operator()(FunctionDefinition const& _function) { - YulString translatedName = translateIdentifier(_function.name); + YulName translatedName = translateIdentifier(_function.name); enterFunction(_function); ScopeGuard g([&]() { this->leaveFunction(_function); }); @@ -168,7 +168,7 @@ TypedName ASTCopier::translate(TypedName const& _typedName) return TypedName{_typedName.debugData, translateIdentifier(_typedName.name), _typedName.type}; } -YulString FunctionCopier::translateIdentifier(YulString _name) +YulName FunctionCopier::translateIdentifier(YulName _name) { if (m_translations.count(_name)) return m_translations.at(_name); diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index db9d72af3..88d2a3451 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -23,7 +23,7 @@ #include -#include +#include #include #include @@ -106,7 +106,7 @@ class ASTCopier: public ExpressionCopier, public StatementCopier virtual void leaveScope(Block const&) { } virtual void enterFunction(FunctionDefinition const&) { } virtual void leaveFunction(FunctionDefinition const&) { } - virtual YulString translateIdentifier(YulString _name) { return _name; } + virtual YulName translateIdentifier(YulName _name) { return _name; } }; template @@ -124,16 +124,16 @@ class FunctionCopier: public ASTCopier { public: FunctionCopier( - std::map const& _translations + std::map const& _translations ): m_translations(_translations) {} using ASTCopier::operator(); - YulString translateIdentifier(YulString _name) override; + YulName translateIdentifier(YulName _name) override; private: /// A mapping between old and new names. We replace the names of variable declarations contained /// in the mapping with their new names. - std::map const& m_translations; + std::map const& m_translations; }; } diff --git a/libyul/optimiser/ASTWalker.h b/libyul/optimiser/ASTWalker.h index b937f7eae..0c23a836e 100644 --- a/libyul/optimiser/ASTWalker.h +++ b/libyul/optimiser/ASTWalker.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include diff --git a/libyul/optimiser/BlockHasher.h b/libyul/optimiser/BlockHasher.h index 2b9a71f10..427161b3c 100644 --- a/libyul/optimiser/BlockHasher.h +++ b/libyul/optimiser/BlockHasher.h @@ -22,7 +22,7 @@ #include #include -#include +#include namespace solidity::yul { @@ -112,8 +112,8 @@ class BlockHasher: public ASTWalker, public ASTHasherBase size_t id = 0; bool isExternal = false; }; - std::map m_variableReferences; - std::vector m_externalReferences; + std::map m_variableReferences; + std::vector m_externalReferences; size_t m_externalIdentifierCount = 0; size_t m_internalIdentifierCount = 0; }; diff --git a/libyul/optimiser/CallGraphGenerator.cpp b/libyul/optimiser/CallGraphGenerator.cpp index 87035e68a..f457f5583 100644 --- a/libyul/optimiser/CallGraphGenerator.cpp +++ b/libyul/optimiser/CallGraphGenerator.cpp @@ -35,11 +35,11 @@ namespace struct CallGraphCycleFinder { CallGraph const& callGraph; - std::set containedInCycle{}; - std::set visited{}; - std::vector currentPath{}; + std::set containedInCycle{}; + std::set visited{}; + std::vector currentPath{}; - void visit(YulString _function) + void visit(YulName _function) { if (visited.count(_function)) return; @@ -61,7 +61,7 @@ struct CallGraphCycleFinder }; } -std::set CallGraph::recursiveFunctions() const +std::set CallGraph::recursiveFunctions() const { CallGraphCycleFinder cycleFinder{*this}; // Visiting the root only is not enough, since there may be disconnected recursive functions. @@ -93,7 +93,7 @@ void CallGraphGenerator::operator()(ForLoop const& _forLoop) void CallGraphGenerator::operator()(FunctionDefinition const& _functionDefinition) { - YulString previousFunction = m_currentFunction; + YulName previousFunction = m_currentFunction; m_currentFunction = _functionDefinition.name; yulAssert(m_callGraph.functionCalls.count(m_currentFunction) == 0, ""); m_callGraph.functionCalls[m_currentFunction] = {}; @@ -103,6 +103,6 @@ void CallGraphGenerator::operator()(FunctionDefinition const& _functionDefinitio CallGraphGenerator::CallGraphGenerator() { - m_callGraph.functionCalls[YulString{}] = {}; + m_callGraph.functionCalls[YulName{}] = {}; } diff --git a/libyul/optimiser/CallGraphGenerator.h b/libyul/optimiser/CallGraphGenerator.h index ad19878b6..23e9a2511 100644 --- a/libyul/optimiser/CallGraphGenerator.h +++ b/libyul/optimiser/CallGraphGenerator.h @@ -32,12 +32,12 @@ namespace solidity::yul struct CallGraph { - std::map> functionCalls; - std::set functionsWithLoops; + std::map> functionCalls; + std::set functionsWithLoops; /// @returns the set of functions contained in cycles in the call graph, i.e. /// functions that are part of a (mutual) recursion. /// Note that this does not include functions that merely call recursive functions. - std::set recursiveFunctions() const; + std::set recursiveFunctions() const; }; /** @@ -62,7 +62,7 @@ class CallGraphGenerator: public ASTWalker CallGraph m_callGraph; /// The name of the function we are currently visiting during traversal. - YulString m_currentFunction; + YulName m_currentFunction; }; } diff --git a/libyul/optimiser/CircularReferencesPruner.cpp b/libyul/optimiser/CircularReferencesPruner.cpp index 824d2be39..a34f3f4e2 100644 --- a/libyul/optimiser/CircularReferencesPruner.cpp +++ b/libyul/optimiser/CircularReferencesPruner.cpp @@ -34,7 +34,7 @@ void CircularReferencesPruner::run(OptimiserStepContext& _context, Block& _ast) void CircularReferencesPruner::operator()(Block& _block) { - std::set functionsToKeep = + std::set functionsToKeep = functionsCalledFromOutermostContext(CallGraphGenerator::callGraph(_block)); for (auto&& statement: _block.statements) @@ -48,13 +48,13 @@ void CircularReferencesPruner::operator()(Block& _block) removeEmptyBlocks(_block); } -std::set CircularReferencesPruner::functionsCalledFromOutermostContext(CallGraph const& _callGraph) +std::set CircularReferencesPruner::functionsCalledFromOutermostContext(CallGraph const& _callGraph) { - std::set verticesToTraverse = m_reservedIdentifiers; - verticesToTraverse.insert(YulString("")); + std::set verticesToTraverse = m_reservedIdentifiers; + verticesToTraverse.insert(YulName("")); - return util::BreadthFirstSearch{{verticesToTraverse.begin(), verticesToTraverse.end()}}.run( - [&_callGraph](YulString _function, auto&& _addChild) { + return util::BreadthFirstSearch{{verticesToTraverse.begin(), verticesToTraverse.end()}}.run( + [&_callGraph](YulName _function, auto&& _addChild) { if (_callGraph.functionCalls.count(_function)) for (auto const& callee: _callGraph.functionCalls.at(_function)) if (_callGraph.functionCalls.count(callee)) diff --git a/libyul/optimiser/CircularReferencesPruner.h b/libyul/optimiser/CircularReferencesPruner.h index 0602445af..090b0617f 100644 --- a/libyul/optimiser/CircularReferencesPruner.h +++ b/libyul/optimiser/CircularReferencesPruner.h @@ -27,6 +27,7 @@ #include #include #include +#include namespace solidity::yul { @@ -44,16 +45,16 @@ class CircularReferencesPruner: public ASTModifier using ASTModifier::operator(); void operator()(Block& _block) override; private: - CircularReferencesPruner(std::set const& _reservedIdentifiers): + CircularReferencesPruner(std::set const& _reservedIdentifiers): m_reservedIdentifiers(_reservedIdentifiers) {} /// Run a breadth-first search starting from the outermost context and /// externally referenced functions to find all the functions that are /// called from there either directly or indirectly. - std::set functionsCalledFromOutermostContext(CallGraph const& _callGraph); + std::set functionsCalledFromOutermostContext(CallGraph const& _callGraph); - std::set const& m_reservedIdentifiers; + std::set const& m_reservedIdentifiers; }; } diff --git a/libyul/optimiser/CommonSubexpressionEliminator.cpp b/libyul/optimiser/CommonSubexpressionEliminator.cpp index 1c7879056..073d621cc 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.cpp +++ b/libyul/optimiser/CommonSubexpressionEliminator.cpp @@ -46,7 +46,7 @@ void CommonSubexpressionEliminator::run(OptimiserStepContext& _context, Block& _ CommonSubexpressionEliminator::CommonSubexpressionEliminator( Dialect const& _dialect, - std::map _functionSideEffects + std::map _functionSideEffects ): DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore, std::move(_functionSideEffects)) { @@ -95,7 +95,7 @@ void CommonSubexpressionEliminator::visit(Expression& _e) if (Identifier const* identifier = std::get_if(&_e)) { - YulString identifierName = identifier->name; + YulName identifierName = identifier->name; if (AssignedValue const* assignedValue = variableValue(identifierName)) { assertThrow(assignedValue->value, OptimizerException, ""); @@ -126,7 +126,7 @@ void CommonSubexpressionEliminator::visit(Expression& _e) } } -void CommonSubexpressionEliminator::assignValue(YulString _variable, Expression const* _value) +void CommonSubexpressionEliminator::assignValue(YulName _variable, Expression const* _value) { if (_value) m_replacementCandidates[*_value].insert(_variable); diff --git a/libyul/optimiser/CommonSubexpressionEliminator.h b/libyul/optimiser/CommonSubexpressionEliminator.h index 163c9df99..d7dc42596 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.h +++ b/libyul/optimiser/CommonSubexpressionEliminator.h @@ -53,19 +53,19 @@ class CommonSubexpressionEliminator: public DataFlowAnalyzer private: CommonSubexpressionEliminator( Dialect const& _dialect, - std::map _functionSideEffects + std::map _functionSideEffects ); protected: using ASTModifier::visit; void visit(Expression& _e) override; - void assignValue(YulString _variable, Expression const* _value) override; + void assignValue(YulName _variable, Expression const* _value) override; private: - std::set m_returnVariables; + std::set m_returnVariables; std::unordered_map< std::reference_wrapper, - std::set, + std::set, ExpressionHash, SyntacticallyEqualExpression > m_replacementCandidates; diff --git a/libyul/optimiser/ConditionalSimplifier.cpp b/libyul/optimiser/ConditionalSimplifier.cpp index 711909125..a2656fed3 100644 --- a/libyul/optimiser/ConditionalSimplifier.cpp +++ b/libyul/optimiser/ConditionalSimplifier.cpp @@ -42,7 +42,7 @@ void ConditionalSimplifier::operator()(Switch& _switch) ASTModifier::operator()(_switch); return; } - YulString expr = std::get(*_switch.expression).name; + YulName expr = std::get(*_switch.expression).name; for (auto& _case: _switch.cases) { if (_case.value) @@ -77,7 +77,7 @@ void ConditionalSimplifier::operator()(Block& _block) TerminationFinder::ControlFlow::FlowOut ) { - YulString condition = std::get(*_if.condition).name; + YulName condition = std::get(*_if.condition).name; langutil::DebugData::ConstPtr debugData = _if.debugData; return make_vector( std::move(_s), diff --git a/libyul/optimiser/ConditionalSimplifier.h b/libyul/optimiser/ConditionalSimplifier.h index e558a1c6c..c78052126 100644 --- a/libyul/optimiser/ConditionalSimplifier.h +++ b/libyul/optimiser/ConditionalSimplifier.h @@ -62,12 +62,12 @@ class ConditionalSimplifier: public ASTModifier private: explicit ConditionalSimplifier( Dialect const& _dialect, - std::map _sideEffects + std::map _sideEffects ): m_dialect(_dialect), m_functionSideEffects(std::move(_sideEffects)) {} Dialect const& m_dialect; - std::map m_functionSideEffects; + std::map m_functionSideEffects; }; } diff --git a/libyul/optimiser/ConditionalUnsimplifier.cpp b/libyul/optimiser/ConditionalUnsimplifier.cpp index 104ec1e4f..06348e997 100644 --- a/libyul/optimiser/ConditionalUnsimplifier.cpp +++ b/libyul/optimiser/ConditionalUnsimplifier.cpp @@ -43,7 +43,7 @@ void ConditionalUnsimplifier::operator()(Switch& _switch) ASTModifier::operator()(_switch); return; } - YulString expr = std::get(*_switch.expression).name; + YulName expr = std::get(*_switch.expression).name; for (auto& _case: _switch.cases) { if (_case.value) @@ -83,7 +83,7 @@ void ConditionalUnsimplifier::operator()(Block& _block) !_if.body.statements.empty() ) { - YulString condition = std::get(*_if.condition).name; + YulName condition = std::get(*_if.condition).name; if ( std::holds_alternative(_stmt2) && TerminationFinder(m_dialect, &m_functionSideEffects).controlFlowKind(_if.body.statements.back()) != diff --git a/libyul/optimiser/ConditionalUnsimplifier.h b/libyul/optimiser/ConditionalUnsimplifier.h index 8025b661b..dc1c6e245 100644 --- a/libyul/optimiser/ConditionalUnsimplifier.h +++ b/libyul/optimiser/ConditionalUnsimplifier.h @@ -42,12 +42,12 @@ class ConditionalUnsimplifier: public ASTModifier private: explicit ConditionalUnsimplifier( Dialect const& _dialect, - std::map const& _sideEffects + std::map const& _sideEffects ): m_dialect(_dialect), m_functionSideEffects(_sideEffects) {} Dialect const& m_dialect; - std::map const& m_functionSideEffects; + std::map const& m_functionSideEffects; }; } diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index 10f479a42..9d56583a0 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -197,7 +197,7 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch auto& switchCase = _switchStmt.cases.front(); langutil::DebugData::ConstPtr debugData = debugDataOf(*_switchStmt.expression); - YulString type = m_typeInfo.typeOf(*_switchStmt.expression); + YulName type = m_typeInfo.typeOf(*_switchStmt.expression); if (switchCase.value) { if (!m_dialect.equalityFunction(type)) diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 5ec3cf248..a51ca9123 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -45,22 +45,22 @@ using namespace solidity::yul; DataFlowAnalyzer::DataFlowAnalyzer( Dialect const& _dialect, MemoryAndStorage _analyzeStores, - std::map _functionSideEffects + std::map _functionSideEffects ): m_dialect(_dialect), m_functionSideEffects(std::move(_functionSideEffects)), - m_knowledgeBase([this](YulString _var) { return variableValue(_var); }), + m_knowledgeBase([this](YulName _var) { return variableValue(_var); }), m_analyzeStores(_analyzeStores == MemoryAndStorage::Analyze) { if (m_analyzeStores) { - if (auto const* builtin = _dialect.memoryStoreFunction(YulString{})) + if (auto const* builtin = _dialect.memoryStoreFunction(YulName{})) m_storeFunctionName[static_cast(StoreLoadLocation::Memory)] = builtin->name; - if (auto const* builtin = _dialect.memoryLoadFunction(YulString{})) + if (auto const* builtin = _dialect.memoryLoadFunction(YulName{})) m_loadFunctionName[static_cast(StoreLoadLocation::Memory)] = builtin->name; - if (auto const* builtin = _dialect.storageStoreFunction(YulString{})) + if (auto const* builtin = _dialect.storageStoreFunction(YulName{})) m_storeFunctionName[static_cast(StoreLoadLocation::Storage)] = builtin->name; - if (auto const* builtin = _dialect.storageLoadFunction(YulString{})) + if (auto const* builtin = _dialect.storageLoadFunction(YulName{})) m_loadFunctionName[static_cast(StoreLoadLocation::Storage)] = builtin->name; } } @@ -98,7 +98,7 @@ void DataFlowAnalyzer::operator()(ExpressionStatement& _statement) void DataFlowAnalyzer::operator()(Assignment& _assignment) { - std::set names; + std::set names; for (auto const& var: _assignment.variableNames) names.emplace(var.name); assertThrow(_assignment.value, OptimizerException, ""); @@ -109,7 +109,7 @@ void DataFlowAnalyzer::operator()(Assignment& _assignment) void DataFlowAnalyzer::operator()(VariableDeclaration& _varDecl) { - std::set names; + std::set names; for (auto const& var: _varDecl.variables) names.emplace(var.name); m_variableScopes.back().variables += names; @@ -138,14 +138,14 @@ void DataFlowAnalyzer::operator()(Switch& _switch) { clearKnowledgeIfInvalidated(*_switch.expression); visit(*_switch.expression); - std::set assignedVariables; + std::set assignedVariables; for (auto& _case: _switch.cases) { Environment preEnvironment = m_state.environment; (*this)(_case.body); joinKnowledge(preEnvironment); - std::set variables = assignedVariableNames(_case.body); + std::set variables = assignedVariableNames(_case.body); assignedVariables += variables; // This is a little too destructive, we could retain the old values. clearValues(variables); @@ -191,7 +191,7 @@ void DataFlowAnalyzer::operator()(ForLoop& _for) AssignmentsSinceContinue assignmentsSinceCont; assignmentsSinceCont(_for.body); - std::set assignedVariables = + std::set assignedVariables = assignedVariableNames(_for.body) + assignedVariableNames(_for.post); clearValues(assignedVariables); @@ -222,31 +222,31 @@ void DataFlowAnalyzer::operator()(Block& _block) assertThrow(numScopes == m_variableScopes.size(), OptimizerException, ""); } -std::optional DataFlowAnalyzer::storageValue(YulString _key) const +std::optional DataFlowAnalyzer::storageValue(YulName _key) const { - if (YulString const* value = valueOrNullptr(m_state.environment.storage, _key)) + if (YulName const* value = valueOrNullptr(m_state.environment.storage, _key)) return *value; else return std::nullopt; } -std::optional DataFlowAnalyzer::memoryValue(YulString _key) const +std::optional DataFlowAnalyzer::memoryValue(YulName _key) const { - if (YulString const* value = valueOrNullptr(m_state.environment.memory, _key)) + if (YulName const* value = valueOrNullptr(m_state.environment.memory, _key)) return *value; else return std::nullopt; } -std::optional DataFlowAnalyzer::keccakValue(YulString _start, YulString _length) const +std::optional DataFlowAnalyzer::keccakValue(YulName _start, YulName _length) const { - if (YulString const* value = valueOrNullptr(m_state.environment.keccak, std::make_pair(_start, _length))) + if (YulName const* value = valueOrNullptr(m_state.environment.keccak, std::make_pair(_start, _length))) return *value; else return std::nullopt; } -void DataFlowAnalyzer::handleAssignment(std::set const& _variables, Expression* _value, bool _isDeclaration) +void DataFlowAnalyzer::handleAssignment(std::set const& _variables, Expression* _value, bool _isDeclaration) { if (!_isDeclaration) clearValues(_variables); @@ -260,7 +260,7 @@ void DataFlowAnalyzer::handleAssignment(std::set const& _variables, E if (_value && _variables.size() == 1) { - YulString name = *_variables.begin(); + YulName name = *_variables.begin(); // Expression has to be movable and cannot contain a reference // to the variable that will be assigned to. if (movableChecker.movable() && !movableChecker.referencedVariables().count(name)) @@ -289,7 +289,7 @@ void DataFlowAnalyzer::handleAssignment(std::set const& _variables, E if (_value && _variables.size() == 1) { - YulString variable = *_variables.begin(); + YulName variable = *_variables.begin(); if (!movableChecker.referencedVariables().count(variable)) { // This might erase additional knowledge about the slot. @@ -320,7 +320,7 @@ void DataFlowAnalyzer::popScope() m_variableScopes.pop_back(); } -void DataFlowAnalyzer::clearValues(std::set _variables) +void DataFlowAnalyzer::clearValues(std::set _variables) { // All variables that reference variables to be cleared also have to be // cleared, but not recursively, since only the value of the original @@ -351,7 +351,7 @@ void DataFlowAnalyzer::clearValues(std::set _variables) }); // Also clear variables that reference variables to be cleared. - std::set referencingVariables; + std::set referencingVariables; for (auto const& variableToClear: _variables) for (auto const& [ref, names]: m_state.references) if (names.count(variableToClear)) @@ -365,7 +365,7 @@ void DataFlowAnalyzer::clearValues(std::set _variables) } } -void DataFlowAnalyzer::assignValue(YulString _variable, Expression const* _value) +void DataFlowAnalyzer::assignValue(YulName _variable, Expression const* _value) { m_state.value[_variable] = {_value, m_loopDepth}; } @@ -398,7 +398,7 @@ void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Expression const& _expr) } } -bool DataFlowAnalyzer::inScope(YulString _variableName) const +bool DataFlowAnalyzer::inScope(YulName _variableName) const { for (auto const& scope: m_variableScopes | ranges::views::reverse) { @@ -410,7 +410,7 @@ bool DataFlowAnalyzer::inScope(YulString _variableName) const return false; } -std::optional DataFlowAnalyzer::valueOfIdentifier(YulString const& _name) const +std::optional DataFlowAnalyzer::valueOfIdentifier(YulName const& _name) const { if (AssignedValue const* value = variableValue(_name)) if (Literal const* literal = std::get_if(value->value)) @@ -418,7 +418,7 @@ std::optional DataFlowAnalyzer::valueOfIdentifier(YulString const& _name) return std::nullopt; } -std::optional> DataFlowAnalyzer::isSimpleStore( +std::optional> DataFlowAnalyzer::isSimpleStore( StoreLoadLocation _location, ExpressionStatement const& _statement ) const @@ -431,7 +431,7 @@ std::optional> DataFlowAnalyzer::isSimpleStore( return {}; } -std::optional DataFlowAnalyzer::isSimpleLoad( +std::optional DataFlowAnalyzer::isSimpleLoad( StoreLoadLocation _location, Expression const& _expression ) const @@ -443,7 +443,7 @@ std::optional DataFlowAnalyzer::isSimpleLoad( return {}; } -std::optional> DataFlowAnalyzer::isKeccak(Expression const& _expression) const +std::optional> DataFlowAnalyzer::isKeccak(Expression const& _expression) const { if (FunctionCall const* funCall = std::get_if(&_expression)) if (funCall->functionName.name == m_dialect.hashFunction({})) @@ -460,14 +460,14 @@ void DataFlowAnalyzer::joinKnowledge(Environment const& _olderEnvironment) joinKnowledgeHelper(m_state.environment.storage, _olderEnvironment.storage); joinKnowledgeHelper(m_state.environment.memory, _olderEnvironment.memory); cxx20::erase_if(m_state.environment.keccak, mapTuple([&_olderEnvironment](auto&& key, auto&& currentValue) { - YulString const* oldValue = valueOrNullptr(_olderEnvironment.keccak, key); + YulName const* oldValue = valueOrNullptr(_olderEnvironment.keccak, key); return !oldValue || *oldValue != currentValue; })); } void DataFlowAnalyzer::joinKnowledgeHelper( - std::unordered_map& _this, - std::unordered_map const& _older + std::unordered_map& _this, + std::unordered_map const& _older ) { // We clear if the key does not exist in the older map or if the value is different. @@ -475,7 +475,7 @@ void DataFlowAnalyzer::joinKnowledgeHelper( // of m_state.environment.memory and thus any overlapping write would have cleared the keys // that are not known to be different inside m_state.environment.memory already. cxx20::erase_if(_this, mapTuple([&_older](auto&& key, auto&& currentValue){ - YulString const* oldValue = valueOrNullptr(_older, key); + YulName const* oldValue = valueOrNullptr(_older, key); return !oldValue || *oldValue != currentValue; })); } diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index e41620b15..6b23a86b9 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include // Needed for m_zero below. #include @@ -89,7 +89,7 @@ class DataFlowAnalyzer: public ASTModifier explicit DataFlowAnalyzer( Dialect const& _dialect, MemoryAndStorage _analyzeStores, - std::map _functionSideEffects = {} + std::map _functionSideEffects = {} ); using ASTModifier::operator(); @@ -103,16 +103,16 @@ class DataFlowAnalyzer: public ASTModifier void operator()(Block& _block) override; /// @returns the current value of the given variable, if known - always movable. - AssignedValue const* variableValue(YulString _variable) const { return util::valueOrNullptr(m_state.value, _variable); } - std::set const* references(YulString _variable) const { return util::valueOrNullptr(m_state.references, _variable); } - std::map const& allValues() const { return m_state.value; } - std::optional storageValue(YulString _key) const; - std::optional memoryValue(YulString _key) const; - std::optional keccakValue(YulString _start, YulString _length) const; + AssignedValue const* variableValue(YulName _variable) const { return util::valueOrNullptr(m_state.value, _variable); } + std::set const* references(YulName _variable) const { return util::valueOrNullptr(m_state.references, _variable); } + std::map const& allValues() const { return m_state.value; } + std::optional storageValue(YulName _key) const; + std::optional memoryValue(YulName _key) const; + std::optional keccakValue(YulName _start, YulName _length) const; protected: /// Registers the assignment. - void handleAssignment(std::set const& _names, Expression* _value, bool _isDeclaration); + void handleAssignment(std::set const& _names, Expression* _value, bool _isDeclaration); /// Creates a new inner scope. void pushScope(bool _functionScope); @@ -122,9 +122,9 @@ class DataFlowAnalyzer: public ASTModifier /// Clears information about the values assigned to the given variables, /// for example at points where control flow is merged. - void clearValues(std::set _names); + void clearValues(std::set _names); - virtual void assignValue(YulString _variable, Expression const* _value); + virtual void assignValue(YulName _variable, Expression const* _value); /// Clears knowledge about storage or memory if they may be modified inside the block. void clearKnowledgeIfInvalidated(Block const& _block); @@ -133,10 +133,10 @@ class DataFlowAnalyzer: public ASTModifier void clearKnowledgeIfInvalidated(Expression const& _expression); /// Returns true iff the variable is in scope. - bool inScope(YulString _variableName) const; + bool inScope(YulName _variableName) const; /// Returns the literal value of the identifier, if it exists. - std::optional valueOfIdentifier(YulString const& _name) const; + std::optional valueOfIdentifier(YulName const& _name) const; enum class StoreLoadLocation { Memory = 0, @@ -146,41 +146,41 @@ class DataFlowAnalyzer: public ASTModifier /// Checks if the statement is sstore(a, b) / mstore(a, b) /// where a and b are variables and returns these variables in that case. - std::optional> isSimpleStore( + std::optional> isSimpleStore( StoreLoadLocation _location, ExpressionStatement const& _statement ) const; /// Checks if the expression is sload(a) / mload(a) /// where a is a variable and returns the variable in that case. - std::optional isSimpleLoad( + std::optional isSimpleLoad( StoreLoadLocation _location, Expression const& _expression ) const; /// Checks if the expression is keccak256(s, l) /// where s and l are variables and returns these variables in that case. - std::optional> isKeccak(Expression const& _expression) const; + std::optional> isKeccak(Expression const& _expression) const; Dialect const& m_dialect; /// Side-effects of user-defined functions. Worst-case side-effects are assumed /// if this is not provided or the function is not found. - std::map m_functionSideEffects; + std::map m_functionSideEffects; private: struct Environment { - std::unordered_map storage; - std::unordered_map memory; + std::unordered_map storage; + std::unordered_map memory; /// If keccak[s, l] = y then y := keccak256(s, l) occurs in the code. - std::map, YulString> keccak; + std::map, YulName> keccak; }; struct State { /// Current values of variables, always movable. - std::map value; + std::map value; /// m_references[a].contains(b) <=> the current expression assigned to a references b - std::unordered_map> references; + std::unordered_map> references; Environment environment; }; @@ -192,8 +192,8 @@ class DataFlowAnalyzer: public ASTModifier void joinKnowledge(Environment const& _olderEnvironment); static void joinKnowledgeHelper( - std::unordered_map& _thisData, - std::unordered_map const& _olderData + std::unordered_map& _thisData, + std::unordered_map const& _olderData ); State m_state; @@ -203,8 +203,8 @@ class DataFlowAnalyzer: public ASTModifier /// If true, analyzes memory and storage content via mload/mstore and sload/sstore. bool m_analyzeStores = true; - YulString m_storeFunctionName[static_cast(StoreLoadLocation::Last) + 1]; - YulString m_loadFunctionName[static_cast(StoreLoadLocation::Last) + 1]; + YulName m_storeFunctionName[static_cast(StoreLoadLocation::Last) + 1]; + YulName m_loadFunctionName[static_cast(StoreLoadLocation::Last) + 1]; /// Current nesting depth of loops. size_t m_loopDepth{0}; @@ -212,11 +212,11 @@ class DataFlowAnalyzer: public ASTModifier struct Scope { explicit Scope(bool _isFunction): isFunction(_isFunction) {} - std::set variables; + std::set variables; bool isFunction; }; /// Special expression whose address will be used in m_value. - /// YulString does not need to be reset because DataFlowAnalyzer is short-lived. + /// YulName does not need to be reset because DataFlowAnalyzer is short-lived. Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue{0, "0"}, {}}}; /// List of scopes. std::vector m_variableScopes; diff --git a/libyul/optimiser/DeadCodeEliminator.h b/libyul/optimiser/DeadCodeEliminator.h index ae8c1b2a6..f252536c5 100644 --- a/libyul/optimiser/DeadCodeEliminator.h +++ b/libyul/optimiser/DeadCodeEliminator.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include #include @@ -62,11 +62,11 @@ class DeadCodeEliminator: public ASTModifier private: DeadCodeEliminator( Dialect const& _dialect, - std::map _sideEffects + std::map _sideEffects ): m_dialect(_dialect), m_functionSideEffects(std::move(_sideEffects)) {} Dialect const& m_dialect; - std::map m_functionSideEffects; + std::map m_functionSideEffects; }; } diff --git a/libyul/optimiser/Disambiguator.cpp b/libyul/optimiser/Disambiguator.cpp index 34e6bc7e6..11325936c 100644 --- a/libyul/optimiser/Disambiguator.cpp +++ b/libyul/optimiser/Disambiguator.cpp @@ -30,7 +30,7 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::util; -YulString Disambiguator::translateIdentifier(YulString _originalName) +YulName Disambiguator::translateIdentifier(YulName _originalName) { if (m_dialect.builtin(_originalName) || m_externallyUsedIdentifiers.count(_originalName)) return _originalName; diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index 062173882..08d8d158f 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -42,7 +42,7 @@ class Disambiguator: public ASTCopier explicit Disambiguator( Dialect const& _dialect, AsmAnalysisInfo const& _analysisInfo, - std::set const& _externallyUsedIdentifiers = {} + std::set const& _externallyUsedIdentifiers = {} ): m_info(_analysisInfo), m_dialect(_dialect), @@ -56,17 +56,17 @@ class Disambiguator: public ASTCopier void leaveScope(Block const& _block) override; void enterFunction(FunctionDefinition const& _function) override; void leaveFunction(FunctionDefinition const& _function) override; - YulString translateIdentifier(YulString _name) override; + YulName translateIdentifier(YulName _name) override; void enterScopeInternal(Scope& _scope); void leaveScopeInternal(Scope& _scope); AsmAnalysisInfo const& m_info; Dialect const& m_dialect; - std::set const& m_externallyUsedIdentifiers; + std::set const& m_externallyUsedIdentifiers; std::vector m_scopes; - std::map m_translations; + std::map m_translations; NameDispenser m_nameDispenser; }; diff --git a/libyul/optimiser/EqualStoreEliminator.cpp b/libyul/optimiser/EqualStoreEliminator.cpp index 1e894608e..0d7ff9e9c 100644 --- a/libyul/optimiser/EqualStoreEliminator.cpp +++ b/libyul/optimiser/EqualStoreEliminator.cpp @@ -53,13 +53,13 @@ void EqualStoreEliminator::visit(Statement& _statement) { if (auto vars = isSimpleStore(StoreLoadLocation::Storage, *expression)) { - if (std::optional currentValue = storageValue(vars->first)) + if (std::optional currentValue = storageValue(vars->first)) if (*currentValue == vars->second) m_pendingRemovals.insert(&_statement); } else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, *expression)) { - if (std::optional currentValue = memoryValue(vars->first)) + if (std::optional currentValue = memoryValue(vars->first)) if (*currentValue == vars->second) m_pendingRemovals.insert(&_statement); } diff --git a/libyul/optimiser/EqualStoreEliminator.h b/libyul/optimiser/EqualStoreEliminator.h index b8572f466..a0b54c590 100644 --- a/libyul/optimiser/EqualStoreEliminator.h +++ b/libyul/optimiser/EqualStoreEliminator.h @@ -45,7 +45,7 @@ class EqualStoreEliminator: public DataFlowAnalyzer private: EqualStoreEliminator( Dialect const& _dialect, - std::map _functionSideEffects + std::map _functionSideEffects ): DataFlowAnalyzer(_dialect, MemoryAndStorage::Analyze, std::move(_functionSideEffects)) {} diff --git a/libyul/optimiser/EquivalentFunctionCombiner.h b/libyul/optimiser/EquivalentFunctionCombiner.h index 5337f7684..627dcb3ff 100644 --- a/libyul/optimiser/EquivalentFunctionCombiner.h +++ b/libyul/optimiser/EquivalentFunctionCombiner.h @@ -46,8 +46,8 @@ class EquivalentFunctionCombiner: public ASTModifier void operator()(FunctionCall& _funCall) override; private: - EquivalentFunctionCombiner(std::map _duplicates): m_duplicates(std::move(_duplicates)) {} - std::map m_duplicates; + EquivalentFunctionCombiner(std::map _duplicates): m_duplicates(std::move(_duplicates)) {} + std::map m_duplicates; }; diff --git a/libyul/optimiser/EquivalentFunctionDetector.h b/libyul/optimiser/EquivalentFunctionDetector.h index d3ddc25f7..7cd161af1 100644 --- a/libyul/optimiser/EquivalentFunctionDetector.h +++ b/libyul/optimiser/EquivalentFunctionDetector.h @@ -35,7 +35,7 @@ namespace solidity::yul class EquivalentFunctionDetector: public ASTWalker { public: - static std::map run(Block& _block) + static std::map run(Block& _block) { EquivalentFunctionDetector detector{BlockHasher::run(_block)}; detector(_block); @@ -50,7 +50,7 @@ class EquivalentFunctionDetector: public ASTWalker std::map m_blockHashes; std::map> m_candidates; - std::map m_duplicates; + std::map m_duplicates; }; diff --git a/libyul/optimiser/ExpressionInliner.cpp b/libyul/optimiser/ExpressionInliner.cpp index cacf5843d..ab4bbcfa4 100644 --- a/libyul/optimiser/ExpressionInliner.cpp +++ b/libyul/optimiser/ExpressionInliner.cpp @@ -56,11 +56,11 @@ void ExpressionInliner::visit(Expression& _expression) return; FunctionDefinition const& fun = *m_inlinableFunctions.at(funCall.functionName.name); - std::map substitutions; + std::map substitutions; for (size_t i = 0; i < funCall.arguments.size(); i++) { Expression const& arg = funCall.arguments[i]; - YulString paraName = fun.parameters[i].name; + YulName paraName = fun.parameters[i].name; if (!SideEffectsCollector(m_dialect, arg).movable()) return; diff --git a/libyul/optimiser/ExpressionInliner.h b/libyul/optimiser/ExpressionInliner.h index ff7da67b8..08ff08648 100644 --- a/libyul/optimiser/ExpressionInliner.h +++ b/libyul/optimiser/ExpressionInliner.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -59,16 +60,16 @@ class ExpressionInliner: public ASTModifier private: ExpressionInliner( Dialect const& _dialect, - std::map const& _inlinableFunctions + std::map const& _inlinableFunctions ): m_dialect(_dialect), m_inlinableFunctions(_inlinableFunctions) {} Dialect const& m_dialect; - std::map const& m_inlinableFunctions; + std::map const& m_inlinableFunctions; - std::map m_varReplacements; + std::map m_varReplacements; /// Set of functions we are currently visiting inside. - std::set m_currentFunctions; + std::set m_currentFunctions; }; } diff --git a/libyul/optimiser/ExpressionJoiner.h b/libyul/optimiser/ExpressionJoiner.h index 3a1fdf743..07f86ddce 100644 --- a/libyul/optimiser/ExpressionJoiner.h +++ b/libyul/optimiser/ExpressionJoiner.h @@ -93,7 +93,7 @@ class ExpressionJoiner: public ASTModifier private: Block* m_currentBlock = nullptr; ///< Pointer to current block holding the statement being visited. size_t m_latestStatementInBlock = 0; ///< Offset to m_currentBlock's statements of the last visited statement. - std::map m_references; ///< Holds reference counts to all variable declarations in current block. + std::map m_references; ///< Holds reference counts to all variable declarations in current block. }; } diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index 6d0a8c9d7..482ade8f8 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -44,7 +44,7 @@ void ExpressionSimplifier::visit(Expression& _expression) while (auto const* match = SimplificationRules::findFirstMatch( _expression, m_dialect, - [this](YulString _var) { return variableValue(_var); } + [this](YulName _var) { return variableValue(_var); } )) _expression = match->action().toExpression(debugDataOf(_expression), evmVersionFromDialect(m_dialect)); diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 6f0834d77..acaa40dbf 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -99,8 +99,8 @@ void ExpressionSplitter::outlineExpression(Expression& _expr) visit(_expr); langutil::DebugData::ConstPtr debugData = debugDataOf(_expr); - YulString var = m_nameDispenser.newName({}); - YulString type = m_typeInfo.typeOf(_expr); + YulName var = m_nameDispenser.newName({}); + YulName type = m_typeInfo.typeOf(_expr); m_statementsToPrefix.emplace_back(VariableDeclaration{ debugData, {{TypedName{debugData, var, type}}}, diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.cpp b/libyul/optimiser/ForLoopConditionOutOfBody.cpp index 83b1e20a8..afd005b71 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.cpp +++ b/libyul/optimiser/ForLoopConditionOutOfBody.cpp @@ -53,7 +53,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) if (!SideEffectsCollector(m_dialect, *firstStatement.condition).movable()) return; - YulString iszero = m_dialect.booleanNegationFunction()->name; + YulName iszero = m_dialect.booleanNegationFunction()->name; langutil::DebugData::ConstPtr debugData = debugDataOf(*firstStatement.condition); if ( diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index 3bf00282c..5cdde8f0f 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -66,8 +66,8 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& m_constants.emplace(ssaValue.first); // Store size of global statements. - m_functionSizes[YulString{}] = CodeSize::codeSize(_ast); - std::map references = ReferencesCounter::countReferences(m_ast); + m_functionSizes[YulName{}] = CodeSize::codeSize(_ast); + std::map references = ReferencesCounter::countReferences(m_ast); for (auto& statement: m_ast.statements) { if (!std::holds_alternative(statement)) @@ -83,10 +83,7 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& } // Check for memory guard. - std::vector memoryGuardCalls = findFunctionCalls( - _ast, - "memoryguard"_yulstring - ); + std::vector memoryGuardCalls = findFunctionCalls(_ast, "memoryguard"_yulname); // We will perform less aggressive inlining, if no ``memoryguard`` call is found. if (!memoryGuardCalls.empty()) m_hasMemoryGuard = true; @@ -104,7 +101,7 @@ void FullInliner::run(Pass _pass) // function name) order. // We use stable_sort below to keep the inlining order of two functions // with the same depth. - std::map depths = callDepths(); + std::map depths = callDepths(); std::vector functions; for (auto& statement: m_ast.statements) if (std::holds_alternative(statement)) @@ -126,10 +123,10 @@ void FullInliner::run(Pass _pass) handleBlock({}, std::get(statement)); } -std::map FullInliner::callDepths() const +std::map FullInliner::callDepths() const { CallGraph cg = CallGraphGenerator::callGraph(m_ast); - cg.functionCalls.erase(""_yulstring); + cg.functionCalls.erase(""_yulname); // Remove calls to builtin functions. for (auto& call: cg.functionCalls) @@ -139,12 +136,12 @@ std::map FullInliner::callDepths() const else ++it; - std::map depths; + std::map depths; size_t currentDepth = 0; while (true) { - std::vector removed; + std::vector removed; for (auto it = cg.functionCalls.begin(); it != cg.functionCalls.end();) { auto const& [fun, callees] = *it; @@ -159,7 +156,7 @@ std::map FullInliner::callDepths() const } for (auto& call: cg.functionCalls) - for (YulString toBeRemoved: removed) + for (YulName toBeRemoved: removed) ranges::actions::remove(call.second, toBeRemoved); currentDepth++; @@ -175,7 +172,7 @@ std::map FullInliner::callDepths() const return depths; } -bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite) +bool FullInliner::shallInline(FunctionCall const& _funCall, YulName _callSite) { // No recursive inlining if (_funCall.functionName.name == _callSite) @@ -237,7 +234,7 @@ bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite) return (size < (aggressiveInlining ? 8u : 6u) || (constantArg && size < (aggressiveInlining ? 16u : 12u))); } -void FullInliner::tentativelyUpdateCodeSize(YulString _function, YulString _callSite) +void FullInliner::tentativelyUpdateCodeSize(YulName _function, YulName _callSite) { m_functionSizes.at(_callSite) += m_functionSizes.at(_function); } @@ -247,14 +244,14 @@ void FullInliner::updateCodeSize(FunctionDefinition const& _fun) m_functionSizes[_fun.name] = CodeSize::codeSize(_fun.body); } -void FullInliner::handleBlock(YulString _currentFunctionName, Block& _block) +void FullInliner::handleBlock(YulName _currentFunctionName, Block& _block) { InlineModifier{*this, m_nameDispenser, _currentFunctionName, m_dialect}(_block); } bool FullInliner::recursive(FunctionDefinition const& _fun) const { - std::map references = ReferencesCounter::countReferences(_fun); + std::map references = ReferencesCounter::countReferences(_fun); return references[_fun.name] > 0; } @@ -292,7 +289,7 @@ std::optional> InlineModifier::tryInlineStatement(Stateme std::vector InlineModifier::performInline(Statement& _statement, FunctionCall& _funCall) { std::vector newStatements; - std::map variableReplacements; + std::map variableReplacements; FunctionDefinition* function = m_driver.function(_funCall.functionName.name); assertThrow(!!function, OptimizerException, "Attempt to inline invalid function."); @@ -302,7 +299,7 @@ std::vector InlineModifier::performInline(Statement& _statement, Func // helper function to create a new variable that is supposed to model // an existing variable. auto newVariable = [&](TypedName const& _existingVariable, Expression* _value) { - YulString newName = m_nameDispenser.newName(_existingVariable.name); + YulName newName = m_nameDispenser.newName(_existingVariable.name); variableReplacements[_existingVariable.name] = newName; VariableDeclaration varDecl{_funCall.debugData, {{_funCall.debugData, newName, _existingVariable.type}}, {}}; if (_value) @@ -364,7 +361,7 @@ Statement BodyCopier::operator()(FunctionDefinition const&) return {}; } -YulString BodyCopier::translateIdentifier(YulString _name) +YulName BodyCopier::translateIdentifier(YulName _name) { if (m_variableReplacements.count(_name)) return m_variableReplacements.at(_name); diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h index 931315305..e93907023 100644 --- a/libyul/optimiser/FullInliner.h +++ b/libyul/optimiser/FullInliner.h @@ -75,9 +75,9 @@ class FullInliner: public ASTModifier /// Inlining heuristic. /// @param _callSite the name of the function in which the function call is located. - bool shallInline(FunctionCall const& _funCall, YulString _callSite); + bool shallInline(FunctionCall const& _funCall, YulName _callSite); - FunctionDefinition* function(YulString _name) + FunctionDefinition* function(YulName _name) { auto it = m_functions.find(_name); if (it != m_functions.end()) @@ -88,7 +88,7 @@ class FullInliner: public ASTModifier /// Adds the size of _funCall to the size of _callSite. This is just /// a rough estimate that is done during inlining. The proper size /// should be determined after inlining is completed. - void tentativelyUpdateCodeSize(YulString _function, YulString _callSite); + void tentativelyUpdateCodeSize(YulName _function, YulName _callSite); private: enum Pass { InlineTiny, InlineRest }; @@ -98,28 +98,28 @@ class FullInliner: public ASTModifier /// @returns a map containing the maximum depths of a call chain starting at each /// function. For recursive functions, the value is one larger than for all others. - std::map callDepths() const; + std::map callDepths() const; void updateCodeSize(FunctionDefinition const& _fun); - void handleBlock(YulString _currentFunctionName, Block& _block); + void handleBlock(YulName _currentFunctionName, Block& _block); bool recursive(FunctionDefinition const& _fun) const; Pass m_pass; /// The AST to be modified. The root block itself will not be modified, because /// we store pointers to functions. Block& m_ast; - std::map m_functions; + std::map m_functions; /// Functions not to be inlined (because they contain the ``leave`` statement). - std::set m_noInlineFunctions; + std::set m_noInlineFunctions; /// True, if the code contains a ``memoryguard`` and we can expect to be able to move variables to memory later. bool m_hasMemoryGuard = false; /// Set of recursive functions. - std::set m_recursiveFunctions; + std::set m_recursiveFunctions; /// Names of functions to always inline. - std::set m_singleUse; + std::set m_singleUse; /// Variables that are constants (used for inlining heuristic) - std::set m_constants; - std::map m_functionSizes; + std::set m_constants; + std::map m_functionSizes; NameDispenser& m_nameDispenser; Dialect const& m_dialect; }; @@ -131,7 +131,7 @@ class FullInliner: public ASTModifier class InlineModifier: public ASTModifier { public: - InlineModifier(FullInliner& _driver, NameDispenser& _nameDispenser, YulString _functionName, Dialect const& _dialect): + InlineModifier(FullInliner& _driver, NameDispenser& _nameDispenser, YulName _functionName, Dialect const& _dialect): m_currentFunction(std::move(_functionName)), m_driver(_driver), m_nameDispenser(_nameDispenser), @@ -144,7 +144,7 @@ class InlineModifier: public ASTModifier std::optional> tryInlineStatement(Statement& _statement); std::vector performInline(Statement& _statement, FunctionCall& _funCall); - YulString m_currentFunction; + YulName m_currentFunction; FullInliner& m_driver; NameDispenser& m_nameDispenser; Dialect const& m_dialect; @@ -160,7 +160,7 @@ class BodyCopier: public ASTCopier public: BodyCopier( NameDispenser& _nameDispenser, - std::map _variableReplacements + std::map _variableReplacements ): m_nameDispenser(_nameDispenser), m_variableReplacements(std::move(_variableReplacements)) @@ -171,10 +171,10 @@ class BodyCopier: public ASTCopier Statement operator()(VariableDeclaration const& _varDecl) override; Statement operator()(FunctionDefinition const& _funDef) override; - YulString translateIdentifier(YulString _name) override; + YulName translateIdentifier(YulName _name) override; NameDispenser& m_nameDispenser; - std::map m_variableReplacements; + std::map m_variableReplacements; }; diff --git a/libyul/optimiser/FunctionCallFinder.cpp b/libyul/optimiser/FunctionCallFinder.cpp index 99f171026..aaf8b9f68 100644 --- a/libyul/optimiser/FunctionCallFinder.cpp +++ b/libyul/optimiser/FunctionCallFinder.cpp @@ -30,14 +30,14 @@ class MaybeConstFunctionCallFinder: Base { public: using MaybeConstBlock = std::conditional_t, Block const, Block>; - static std::vector run(MaybeConstBlock& _block, YulString const _functionName) + static std::vector run(MaybeConstBlock& _block, YulName const _functionName) { MaybeConstFunctionCallFinder functionCallFinder(_functionName); functionCallFinder(_block); return functionCallFinder.m_calls; } private: - explicit MaybeConstFunctionCallFinder(YulString const _functionName): m_functionName(_functionName), m_calls() {} + explicit MaybeConstFunctionCallFinder(YulName const _functionName): m_functionName(_functionName), m_calls() {} using Base::operator(); void operator()(ResultType& _functionCall) override { @@ -45,17 +45,17 @@ class MaybeConstFunctionCallFinder: Base if (_functionCall.functionName.name == m_functionName) m_calls.emplace_back(&_functionCall); } - YulString m_functionName; + YulName m_functionName; std::vector m_calls; }; } -std::vector solidity::yul::findFunctionCalls(Block& _block, YulString _functionName) +std::vector solidity::yul::findFunctionCalls(Block& _block, YulName _functionName) { return MaybeConstFunctionCallFinder::run(_block, _functionName); } -std::vector solidity::yul::findFunctionCalls(Block const& _block, YulString _functionName) +std::vector solidity::yul::findFunctionCalls(Block const& _block, YulName _functionName) { return MaybeConstFunctionCallFinder::run(_block, _functionName); } diff --git a/libyul/optimiser/FunctionCallFinder.h b/libyul/optimiser/FunctionCallFinder.h index a5d4da56e..41a19fe99 100644 --- a/libyul/optimiser/FunctionCallFinder.h +++ b/libyul/optimiser/FunctionCallFinder.h @@ -21,7 +21,7 @@ #pragma once #include -#include +#include #include @@ -33,13 +33,13 @@ namespace solidity::yul * * Prerequisite: Disambiguator */ -std::vector findFunctionCalls(Block& _block, YulString _functionName); +std::vector findFunctionCalls(Block& _block, YulName _functionName); /** * Finds all calls to a function of a given name using an ASTWalker. * * Prerequisite: Disambiguator */ -std::vector findFunctionCalls(Block const& _block, YulString _functionName); +std::vector findFunctionCalls(Block const& _block, YulName _functionName); } diff --git a/libyul/optimiser/FunctionSpecializer.cpp b/libyul/optimiser/FunctionSpecializer.cpp index 7e6d48632..49da50032 100644 --- a/libyul/optimiser/FunctionSpecializer.cpp +++ b/libyul/optimiser/FunctionSpecializer.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include @@ -64,7 +64,7 @@ void FunctionSpecializer::operator()(FunctionCall& _f) if (ranges::any_of(arguments, [](auto& _a) { return _a.has_value(); })) { - YulString oldName = std::move(_f.functionName.name); + YulName oldName = std::move(_f.functionName.name); auto newName = m_nameDispenser.newName(oldName); m_oldToNewMap[oldName].emplace_back(std::make_pair(newName, arguments)); @@ -79,19 +79,19 @@ void FunctionSpecializer::operator()(FunctionCall& _f) FunctionDefinition FunctionSpecializer::specialize( FunctionDefinition const& _f, - YulString _newName, + YulName _newName, FunctionSpecializer::LiteralArguments _arguments ) { yulAssert(_arguments.size() == _f.parameters.size(), ""); - std::map translatedNames = applyMap( + std::map translatedNames = applyMap( NameCollector{_f, NameCollector::OnlyVariables}.names(), - [&](auto& _name) -> std::pair + [&](auto& _name) -> std::pair { return std::make_pair(_name, m_nameDispenser.newName(_name)); }, - std::map{} + std::map{} ); FunctionDefinition newFunction = std::get(FunctionCopier{translatedNames}(_f)); diff --git a/libyul/optimiser/FunctionSpecializer.h b/libyul/optimiser/FunctionSpecializer.h index b922ece8b..784ec4311 100644 --- a/libyul/optimiser/FunctionSpecializer.h +++ b/libyul/optimiser/FunctionSpecializer.h @@ -67,7 +67,7 @@ class FunctionSpecializer: public ASTModifier private: explicit FunctionSpecializer( - std::set _recursiveFunctions, + std::set _recursiveFunctions, NameDispenser& _nameDispenser, Dialect const& _dialect ): @@ -96,15 +96,15 @@ class FunctionSpecializer: public ASTModifier /// FunctionDefinition specialize( FunctionDefinition const& _f, - YulString _newName, + YulName _newName, FunctionSpecializer::LiteralArguments _arguments ); /// A mapping between the old function name and a pair of new function name and its arguments. /// Note that at least one of the argument will have a literal value. - std::map>> m_oldToNewMap; + std::map>> m_oldToNewMap; /// We skip specializing recursive functions. Need backtracking to properly deal with them. - std::set const m_recursiveFunctions; + std::set const m_recursiveFunctions; NameDispenser& m_nameDispenser; Dialect const& m_dialect; diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp index 0bb4d368d..d719302dc 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp @@ -43,7 +43,7 @@ void InlinableExpressionFunctionFinder::operator()(FunctionDefinition const& _fu { if (_function.returnVariables.size() == 1 && _function.body.statements.size() == 1) { - YulString retVariable = _function.returnVariables.front().name; + YulName retVariable = _function.returnVariables.front().name; Statement const& bodyStatement = _function.body.statements.front(); if (std::holds_alternative(bodyStatement)) { @@ -56,7 +56,7 @@ void InlinableExpressionFunctionFinder::operator()(FunctionDefinition const& _fu // would not be valid here if we were searching inside a functionally inlinable // function body. assertThrow(m_disallowedIdentifiers.empty() && !m_foundDisallowedIdentifier, OptimizerException, ""); - m_disallowedIdentifiers = std::set{retVariable, _function.name}; + m_disallowedIdentifiers = std::set{retVariable, _function.name}; std::visit(*this, *assignment.value); if (!m_foundDisallowedIdentifier) m_inlinableFunctions[_function.name] = &_function; diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.h b/libyul/optimiser/InlinableExpressionFunctionFinder.h index 587bdca91..e7210da69 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.h +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.h @@ -42,7 +42,7 @@ class InlinableExpressionFunctionFinder: public ASTWalker { public: - std::map const& inlinableFunctions() const + std::map const& inlinableFunctions() const { return m_inlinableFunctions; } @@ -53,15 +53,15 @@ class InlinableExpressionFunctionFinder: public ASTWalker void operator()(FunctionDefinition const& _function) override; private: - void checkAllowed(YulString _name) + void checkAllowed(YulName _name) { if (m_disallowedIdentifiers.count(_name)) m_foundDisallowedIdentifier = true; } bool m_foundDisallowedIdentifier = false; - std::set m_disallowedIdentifiers; - std::map m_inlinableFunctions; + std::set m_disallowedIdentifiers; + std::map m_inlinableFunctions; }; } diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index 79eb2b317..731f4b3b8 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -32,19 +32,19 @@ using namespace solidity; using namespace solidity::yul; -KnowledgeBase::KnowledgeBase(std::map const& _ssaValues): +KnowledgeBase::KnowledgeBase(std::map const& _ssaValues): m_valuesAreSSA(true), - m_variableValues([_ssaValues](YulString _var) { return util::valueOrNullptr(_ssaValues, _var); }) + m_variableValues([_ssaValues](YulName _var) { return util::valueOrNullptr(_ssaValues, _var); }) {} -bool KnowledgeBase::knownToBeDifferent(YulString _a, YulString _b) +bool KnowledgeBase::knownToBeDifferent(YulName _a, YulName _b) { if (std::optional difference = differenceIfKnownConstant(_a, _b)) return difference != 0; return false; } -std::optional KnowledgeBase::differenceIfKnownConstant(YulString _a, YulString _b) +std::optional KnowledgeBase::differenceIfKnownConstant(YulName _a, YulName _b) { VariableOffset offA = explore(_a); VariableOffset offB = explore(_b); @@ -55,7 +55,7 @@ std::optional KnowledgeBase::differenceIfKnownConstant(YulString _a, YulSt } -bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulString _a, YulString _b) +bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulName _a, YulName _b) { if (std::optional difference = differenceIfKnownConstant(_a, _b)) return difference >= 32 && difference <= u256(0) - 32; @@ -63,12 +63,12 @@ bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulString _a, YulString _b) return false; } -bool KnowledgeBase::knownToBeZero(YulString _a) +bool KnowledgeBase::knownToBeZero(YulName _a) { return valueIfKnownConstant(_a) == 0; } -std::optional KnowledgeBase::valueIfKnownConstant(YulString _a) +std::optional KnowledgeBase::valueIfKnownConstant(YulName _a) { return explore(_a).absoluteValue(); } @@ -83,7 +83,7 @@ std::optional KnowledgeBase::valueIfKnownConstant(Expression const& _expre return std::nullopt; } -KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var) +KnowledgeBase::VariableOffset KnowledgeBase::explore(YulName _var) { Expression const* value = nullptr; if (m_valuesAreSSA) @@ -113,12 +113,12 @@ KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var) std::optional KnowledgeBase::explore(Expression const& _value) { if (Literal const* literal = std::get_if(&_value)) - return VariableOffset{YulString{}, literal->value.value()}; + return VariableOffset{YulName{}, literal->value.value()}; else if (Identifier const* identifier = std::get_if(&_value)) return explore(identifier->name); else if (FunctionCall const* f = std::get_if(&_value)) { - if (f->functionName.name == "add"_yulstring) + if (f->functionName.name == "add"_yulname) { if (std::optional a = explore(f->arguments[0])) if (std::optional b = explore(f->arguments[1])) @@ -132,13 +132,13 @@ std::optional KnowledgeBase::explore(Expression c return VariableOffset{a->reference, offset}; } } - else if (f->functionName.name == "sub"_yulstring) + else if (f->functionName.name == "sub"_yulname) if (std::optional a = explore(f->arguments[0])) if (std::optional b = explore(f->arguments[1])) { u256 offset = a->offset - b->offset; if (a->reference == b->reference) - return VariableOffset{YulString{}, offset}; + return VariableOffset{YulName{}, offset}; else if (b->isAbsolute()) // b is constant return VariableOffset{a->reference, offset}; @@ -148,7 +148,7 @@ std::optional KnowledgeBase::explore(Expression c return std::nullopt; } -Expression const* KnowledgeBase::valueOf(YulString _var) +Expression const* KnowledgeBase::valueOf(YulName _var) { AssignedValue const* assignedValue = m_variableValues(_var); Expression const* currentValue = assignedValue ? assignedValue->value : nullptr; @@ -162,7 +162,7 @@ Expression const* KnowledgeBase::valueOf(YulString _var) return currentValue; } -void KnowledgeBase::reset(YulString _var) +void KnowledgeBase::reset(YulName _var) { yulAssert(!m_valuesAreSSA); @@ -174,16 +174,16 @@ void KnowledgeBase::reset(YulString _var) m_groupMembers[offset->reference].erase(_var); m_offsets.erase(_var); } - if (std::set* group = util::valueOrNullptr(m_groupMembers, _var)) + if (std::set* group = util::valueOrNullptr(m_groupMembers, _var)) { // _var was a representative, we might have to find a new one. if (!group->empty()) { - YulString newRepresentative = *group->begin(); + YulName newRepresentative = *group->begin(); yulAssert(newRepresentative != _var); u256 newOffset = m_offsets[newRepresentative].offset; // newOffset = newRepresentative - _var - for (YulString groupMember: *group) + for (YulName groupMember: *group) { yulAssert(m_offsets[groupMember].reference == _var); m_offsets[groupMember].reference = newRepresentative; @@ -200,7 +200,7 @@ void KnowledgeBase::reset(YulString _var) } } -KnowledgeBase::VariableOffset KnowledgeBase::setOffset(YulString _variable, VariableOffset _value) +KnowledgeBase::VariableOffset KnowledgeBase::setOffset(YulName _variable, VariableOffset _value) { m_offsets[_variable] = _value; // Constants are not tracked in m_groupMembers because diff --git a/libyul/optimiser/KnowledgeBase.h b/libyul/optimiser/KnowledgeBase.h index f83c5ac66..46ea7b96a 100644 --- a/libyul/optimiser/KnowledgeBase.h +++ b/libyul/optimiser/KnowledgeBase.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include #include @@ -55,34 +55,34 @@ struct AssignedValue; * representative variable of the group. * * There is a special group which is the constant values. Those use the - * empty YulString as representative "variable". + * empty YulName as representative "variable". */ class KnowledgeBase { public: /// Constructor for arbitrary value callback that allows for variable values /// to change in between calls to functions of this class. - explicit KnowledgeBase(std::function _variableValues): + explicit KnowledgeBase(std::function _variableValues): m_variableValues(std::move(_variableValues)) {} /// Constructor to use if source code is in SSA form and values are constant. - explicit KnowledgeBase(std::map const& _ssaValues); + explicit KnowledgeBase(std::map const& _ssaValues); - bool knownToBeDifferent(YulString _a, YulString _b); - std::optional differenceIfKnownConstant(YulString _a, YulString _b); - bool knownToBeDifferentByAtLeast32(YulString _a, YulString _b); - bool knownToBeZero(YulString _a); - std::optional valueIfKnownConstant(YulString _a); + bool knownToBeDifferent(YulName _a, YulName _b); + std::optional differenceIfKnownConstant(YulName _a, YulName _b); + bool knownToBeDifferentByAtLeast32(YulName _a, YulName _b); + bool knownToBeZero(YulName _a); + std::optional valueIfKnownConstant(YulName _a); std::optional valueIfKnownConstant(Expression const& _expression); private: /** * Constant offset relative to a reference variable, or absolute constant if the - * reference variable is the empty YulString. + * reference variable is the empty YulName. */ struct VariableOffset { - YulString reference; + YulName reference; u256 offset; bool isAbsolute() const @@ -99,30 +99,30 @@ class KnowledgeBase } }; - VariableOffset explore(YulString _var); + VariableOffset explore(YulName _var); std::optional explore(Expression const& _value); /// Retrieves the current value of a variable and potentially resets the variable if it is not up to date. - Expression const* valueOf(YulString _var); + Expression const* valueOf(YulName _var); /// Resets all information about the variable and removes it from its group, /// potentially finding a new representative. - void reset(YulString _var); + void reset(YulName _var); - VariableOffset setOffset(YulString _variable, VariableOffset _value); + VariableOffset setOffset(YulName _variable, VariableOffset _value); /// If true, we can assume that variable values never change and skip some steps. bool m_valuesAreSSA = false; /// Callback to retrieve the current value of a variable. - std::function m_variableValues; + std::function m_variableValues; /// Offsets for each variable to one representative per group. /// The empty string is the representative of the constant value zero. - std::map m_offsets; + std::map m_offsets; /// Last known value of each variable we queried. - std::map m_lastKnownValue; + std::map m_lastKnownValue; /// For each representative, variables that use it to offset from. - std::map> m_groupMembers; + std::map> m_groupMembers; }; } diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index 170eefc90..a7ee5dd0b 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -87,7 +87,7 @@ void LoadResolver::tryResolve( if (_arguments.empty() || !std::holds_alternative(_arguments.at(0))) return; - YulString key = std::get(_arguments.at(0)).name; + YulName key = std::get(_arguments.at(0)).name; if (_location == StoreLoadLocation::Storage) { if (auto value = storageValue(key)) @@ -137,7 +137,7 @@ void LoadResolver::tryEvaluateKeccak( if (costOfLiteral > costOfKeccak) return; - std::optional value = memoryValue(memoryKey->name); + std::optional value = memoryValue(memoryKey->name); if (value && inScope(*value)) { std::optional memoryContent = valueOfIdentifier(*value); diff --git a/libyul/optimiser/LoadResolver.h b/libyul/optimiser/LoadResolver.h index e56bc6c4a..b4a496303 100644 --- a/libyul/optimiser/LoadResolver.h +++ b/libyul/optimiser/LoadResolver.h @@ -49,7 +49,7 @@ class LoadResolver: public DataFlowAnalyzer private: LoadResolver( Dialect const& _dialect, - std::map _functionSideEffects, + std::map _functionSideEffects, bool _containsMSize, std::optional _expectedExecutionsPerDeployment ): diff --git a/libyul/optimiser/LoopInvariantCodeMotion.cpp b/libyul/optimiser/LoopInvariantCodeMotion.cpp index da3c5e3e0..2a196a68f 100644 --- a/libyul/optimiser/LoopInvariantCodeMotion.cpp +++ b/libyul/optimiser/LoopInvariantCodeMotion.cpp @@ -32,10 +32,10 @@ using namespace solidity::yul; void LoopInvariantCodeMotion::run(OptimiserStepContext& _context, Block& _ast) { - std::map functionSideEffects = + std::map functionSideEffects = SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast)); bool containsMSize = MSizeFinder::containsMSize(_context.dialect, _ast); - std::set ssaVars = SSAValueTracker::ssaVariables(_ast); + std::set ssaVars = SSAValueTracker::ssaVariables(_ast); LoopInvariantCodeMotion{_context.dialect, ssaVars, functionSideEffects, containsMSize}(_ast); } @@ -56,7 +56,7 @@ void LoopInvariantCodeMotion::operator()(Block& _block) bool LoopInvariantCodeMotion::canBePromoted( VariableDeclaration const& _varDecl, - std::set const& _varsDefinedInCurrentScope, + std::set const& _varsDefinedInCurrentScope, SideEffects const& _forLoopSideEffects ) const { @@ -90,7 +90,7 @@ std::optional> LoopInvariantCodeMotion::rewriteLoop(ForLo std::vector replacement; for (Block* block: {&_for.post, &_for.body}) { - std::set varsDefinedInScope; + std::set varsDefinedInScope; util::iterateReplacing( block->statements, [&](Statement& _s) -> std::optional> diff --git a/libyul/optimiser/LoopInvariantCodeMotion.h b/libyul/optimiser/LoopInvariantCodeMotion.h index 1b2647924..c85b87a01 100644 --- a/libyul/optimiser/LoopInvariantCodeMotion.h +++ b/libyul/optimiser/LoopInvariantCodeMotion.h @@ -48,8 +48,8 @@ class LoopInvariantCodeMotion: public ASTModifier private: explicit LoopInvariantCodeMotion( Dialect const& _dialect, - std::set const& _ssaVariables, - std::map const& _functionSideEffects, + std::set const& _ssaVariables, + std::map const& _functionSideEffects, bool _containsMSize ): m_containsMSize(_containsMSize), @@ -61,15 +61,15 @@ class LoopInvariantCodeMotion: public ASTModifier /// @returns true if the given variable declaration can be moved to in front of the loop. bool canBePromoted( VariableDeclaration const& _varDecl, - std::set const& _varsDefinedInCurrentScope, + std::set const& _varsDefinedInCurrentScope, SideEffects const& _forLoopSideEffects ) const; std::optional> rewriteLoop(ForLoop& _for); bool m_containsMSize = true; Dialect const& m_dialect; - std::set const& m_ssaVariables; - std::map const& m_functionSideEffects; + std::set const& m_ssaVariables; + std::map const& m_functionSideEffects; }; } diff --git a/libyul/optimiser/Metrics.cpp b/libyul/optimiser/Metrics.cpp index 2f1dee93e..546c465b5 100644 --- a/libyul/optimiser/Metrics.cpp +++ b/libyul/optimiser/Metrics.cpp @@ -199,7 +199,7 @@ void AssignmentCounter::operator()(Assignment const& _assignment) ++m_assignmentCounters[variable.name]; } -size_t AssignmentCounter::assignmentCount(YulString _name) const +size_t AssignmentCounter::assignmentCount(YulName _name) const { auto it = m_assignmentCounters.find(_name); return (it == m_assignmentCounters.end()) ? 0 : it->second; diff --git a/libyul/optimiser/Metrics.h b/libyul/optimiser/Metrics.h index f86e3b28d..01ab1adbd 100644 --- a/libyul/optimiser/Metrics.h +++ b/libyul/optimiser/Metrics.h @@ -139,9 +139,9 @@ class AssignmentCounter: public ASTWalker public: using ASTWalker::operator(); void operator()(Assignment const& _assignment) override; - std::size_t assignmentCount(YulString _name) const; + std::size_t assignmentCount(YulName _name) const; private: - std::map m_assignmentCounters; + std::map m_assignmentCounters; }; } diff --git a/libyul/optimiser/NameCollector.cpp b/libyul/optimiser/NameCollector.cpp index 7fb0c7ed2..d6db837f8 100644 --- a/libyul/optimiser/NameCollector.cpp +++ b/libyul/optimiser/NameCollector.cpp @@ -59,21 +59,21 @@ void ReferencesCounter::operator()(FunctionCall const& _funCall) ASTWalker::operator()(_funCall); } -std::map ReferencesCounter::countReferences(Block const& _block) +std::map ReferencesCounter::countReferences(Block const& _block) { ReferencesCounter counter; counter(_block); return std::move(counter.m_references); } -std::map ReferencesCounter::countReferences(FunctionDefinition const& _function) +std::map ReferencesCounter::countReferences(FunctionDefinition const& _function) { ReferencesCounter counter; counter(_function); return std::move(counter.m_references); } -std::map ReferencesCounter::countReferences(Expression const& _expression) +std::map ReferencesCounter::countReferences(Expression const& _expression) { ReferencesCounter counter; counter.visit(_expression); @@ -85,28 +85,28 @@ void VariableReferencesCounter::operator()(Identifier const& _identifier) ++m_references[_identifier.name]; } -std::map VariableReferencesCounter::countReferences(Block const& _block) +std::map VariableReferencesCounter::countReferences(Block const& _block) { VariableReferencesCounter counter; counter(_block); return std::move(counter.m_references); } -std::map VariableReferencesCounter::countReferences(FunctionDefinition const& _function) +std::map VariableReferencesCounter::countReferences(FunctionDefinition const& _function) { VariableReferencesCounter counter; counter(_function); return std::move(counter.m_references); } -std::map VariableReferencesCounter::countReferences(Expression const& _expression) +std::map VariableReferencesCounter::countReferences(Expression const& _expression) { VariableReferencesCounter counter; counter.visit(_expression); return std::move(counter.m_references); } -std::map VariableReferencesCounter::countReferences(Statement const& _statement) +std::map VariableReferencesCounter::countReferences(Statement const& _statement) { VariableReferencesCounter counter; counter.visit(_statement); @@ -138,9 +138,9 @@ void AssignmentsSinceContinue::operator()(FunctionDefinition const&) yulAssert(false, ""); } -std::set solidity::yul::assignedVariableNames(Block const& _code) +std::set solidity::yul::assignedVariableNames(Block const& _code) { - std::set names; + std::set names; forEach(_code, [&](Assignment const& _assignment) { for (auto const& var: _assignment.variableNames) names.emplace(var.name); @@ -148,9 +148,9 @@ std::set solidity::yul::assignedVariableNames(Block const& _code) return names; } -std::map solidity::yul::allFunctionDefinitions(Block const& _block) +std::map solidity::yul::allFunctionDefinitions(Block const& _block) { - std::map result; + std::map result; forEach(_block, [&](FunctionDefinition const& _function) { result[_function.name] = &_function; }); diff --git a/libyul/optimiser/NameCollector.h b/libyul/optimiser/NameCollector.h index ad18e1e26..0fc2e311c 100644 --- a/libyul/optimiser/NameCollector.h +++ b/libyul/optimiser/NameCollector.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include #include @@ -59,9 +60,9 @@ class NameCollector: public ASTWalker void operator()(VariableDeclaration const& _varDecl) override; void operator()(FunctionDefinition const& _funDef) override; - std::set names() const { return m_names; } + std::set names() const { return m_names; } private: - std::set m_names; + std::set m_names; CollectWhat m_collectWhat = VariablesAndFunctions; }; @@ -75,12 +76,12 @@ class ReferencesCounter: public ASTWalker void operator()(Identifier const& _identifier) override; void operator()(FunctionCall const& _funCall) override; - static std::map countReferences(Block const& _block); - static std::map countReferences(FunctionDefinition const& _function); - static std::map countReferences(Expression const& _expression); + static std::map countReferences(Block const& _block); + static std::map countReferences(FunctionDefinition const& _function); + static std::map countReferences(Expression const& _expression); private: - std::map m_references; + std::map m_references; }; /** @@ -92,13 +93,13 @@ class VariableReferencesCounter: public ASTWalker using ASTWalker::operator (); void operator()(Identifier const& _identifier) override; - static std::map countReferences(Block const& _block); - static std::map countReferences(FunctionDefinition const& _function); - static std::map countReferences(Expression const& _expression); - static std::map countReferences(Statement const& _statement); + static std::map countReferences(Block const& _block); + static std::map countReferences(FunctionDefinition const& _function); + static std::map countReferences(Expression const& _expression); + static std::map countReferences(Statement const& _statement); private: - std::map m_references; + std::map m_references; }; /** @@ -117,21 +118,21 @@ class AssignmentsSinceContinue: public ASTWalker void operator()(Assignment const& _assignment) override; void operator()(FunctionDefinition const& _funDef) override; - std::set const& names() const { return m_names; } + std::set const& names() const { return m_names; } bool empty() const noexcept { return m_names.empty(); } private: size_t m_forLoopDepth = 0; bool m_continueFound = false; - std::set m_names; + std::set m_names; }; /// @returns the names of all variables that are assigned to inside @a _code. /// (ignores variable declarations) -std::set assignedVariableNames(Block const& _code); +std::set assignedVariableNames(Block const& _code); /// @returns all function definitions anywhere in the AST. /// Requires disambiguated source. -std::map allFunctionDefinitions(Block const& _block); +std::map allFunctionDefinitions(Block const& _block); } diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp index 3a8db5ee4..c2b6b9847 100644 --- a/libyul/optimiser/NameDispenser.cpp +++ b/libyul/optimiser/NameDispenser.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include @@ -33,31 +32,31 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::util; -NameDispenser::NameDispenser(Dialect const& _dialect, Block const& _ast, std::set _reservedNames): +NameDispenser::NameDispenser(Dialect const& _dialect, Block const& _ast, std::set _reservedNames): NameDispenser(_dialect, NameCollector(_ast).names() + _reservedNames) { m_reservedNames = std::move(_reservedNames); } -NameDispenser::NameDispenser(Dialect const& _dialect, std::set _usedNames): +NameDispenser::NameDispenser(Dialect const& _dialect, std::set _usedNames): m_dialect(_dialect), m_usedNames(std::move(_usedNames)) { } -YulString NameDispenser::newName(YulString _nameHint) +YulName NameDispenser::newName(YulName _nameHint) { - YulString name = _nameHint; + YulName name = _nameHint; while (illegalName(name)) { m_counter++; - name = YulString(_nameHint.str() + "_" + std::to_string(m_counter)); + name = YulName(_nameHint.str() + "_" + std::to_string(m_counter)); } m_usedNames.emplace(name); return name; } -bool NameDispenser::illegalName(YulString _name) +bool NameDispenser::illegalName(YulName _name) { return isRestrictedIdentifier(m_dialect, _name) || m_usedNames.count(_name); } diff --git a/libyul/optimiser/NameDispenser.h b/libyul/optimiser/NameDispenser.h index 6e655e416..3da50359a 100644 --- a/libyul/optimiser/NameDispenser.h +++ b/libyul/optimiser/NameDispenser.h @@ -22,7 +22,7 @@ #include -#include +#include #include @@ -40,21 +40,21 @@ class NameDispenser { public: /// Initialize the name dispenser with all the names used in the given AST. - explicit NameDispenser(Dialect const& _dialect, Block const& _ast, std::set _reservedNames = {}); + explicit NameDispenser(Dialect const& _dialect, Block const& _ast, std::set _reservedNames = {}); /// Initialize the name dispenser with the given used names. - explicit NameDispenser(Dialect const& _dialect, std::set _usedNames); + explicit NameDispenser(Dialect const& _dialect, std::set _usedNames); /// @returns a currently unused name that should be similar to _nameHint. - YulString newName(YulString _nameHint); + YulName newName(YulName _nameHint); /// Mark @a _name as used, i.e. the dispenser's newName function will not /// return it. - void markUsed(YulString _name) { m_usedNames.insert(_name); } + void markUsed(YulName _name) { m_usedNames.insert(_name); } - std::set const& usedNames() { return m_usedNames; } + std::set const& usedNames() { return m_usedNames; } /// Returns true if `_name` is either used or is a restricted identifier. - bool illegalName(YulString _name); + bool illegalName(YulName _name); /// Resets `m_usedNames` with *only* the names that are used in the AST. Also resets value of /// `m_counter` to zero. @@ -62,8 +62,8 @@ class NameDispenser private: Dialect const& m_dialect; - std::set m_usedNames; - std::set m_reservedNames; + std::set m_usedNames; + std::set m_reservedNames; size_t m_counter = 0; }; diff --git a/libyul/optimiser/NameDisplacer.cpp b/libyul/optimiser/NameDisplacer.cpp index 4d0d217d8..fd813fbfc 100644 --- a/libyul/optimiser/NameDisplacer.cpp +++ b/libyul/optimiser/NameDisplacer.cpp @@ -69,14 +69,14 @@ void NameDisplacer::operator()(Block& _block) ASTModifier::operator()(_block); } -void NameDisplacer::checkAndReplaceNew(YulString& _name) +void NameDisplacer::checkAndReplaceNew(YulName& _name) { yulAssert(!m_translations.count(_name), ""); if (m_namesToFree.count(_name)) _name = (m_translations[_name] = m_nameDispenser.newName(_name)); } -void NameDisplacer::checkAndReplace(YulString& _name) const +void NameDisplacer::checkAndReplace(YulName& _name) const { if (m_translations.count(_name)) _name = m_translations.at(_name); diff --git a/libyul/optimiser/NameDisplacer.h b/libyul/optimiser/NameDisplacer.h index 336dd04e4..3312e203d 100644 --- a/libyul/optimiser/NameDisplacer.h +++ b/libyul/optimiser/NameDisplacer.h @@ -44,12 +44,12 @@ class NameDisplacer: public ASTModifier public: explicit NameDisplacer( NameDispenser& _dispenser, - std::set const& _namesToFree + std::set const& _namesToFree ): m_nameDispenser(_dispenser), m_namesToFree(_namesToFree) { - for (YulString n: _namesToFree) + for (YulName n: _namesToFree) m_nameDispenser.markUsed(n); } @@ -60,17 +60,17 @@ class NameDisplacer: public ASTModifier void operator()(FunctionCall& _funCall) override; void operator()(Block& _block) override; - std::map const& translations() const { return m_translations; } + std::map const& translations() const { return m_translations; } protected: /// Check if the newly introduced identifier @a _name has to be replaced. - void checkAndReplaceNew(YulString& _name); + void checkAndReplaceNew(YulName& _name); /// Replace the identifier @a _name if it is in the translation map. - void checkAndReplace(YulString& _name) const; + void checkAndReplace(YulName& _name) const; NameDispenser& m_nameDispenser; - std::set const& m_namesToFree; - std::map m_translations; + std::set const& m_namesToFree; + std::map m_translations; }; } diff --git a/libyul/optimiser/NameSimplifier.cpp b/libyul/optimiser/NameSimplifier.cpp index f7d732547..f03a448f0 100644 --- a/libyul/optimiser/NameSimplifier.cpp +++ b/libyul/optimiser/NameSimplifier.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include @@ -32,10 +32,10 @@ using namespace solidity::yul; NameSimplifier::NameSimplifier(OptimiserStepContext& _context, Block const& _ast): m_context(_context) { - for (YulString name: _context.reservedIdentifiers) + for (YulName name: _context.reservedIdentifiers) m_translations[name] = name; - for (YulString const& name: NameCollector(_ast).names()) + for (YulName const& name: NameCollector(_ast).names()) findSimplification(name); } @@ -72,7 +72,7 @@ void NameSimplifier::operator()(FunctionCall& _funCall) ASTModifier::operator()(_funCall); } -void NameSimplifier::findSimplification(YulString const& _name) +void NameSimplifier::findSimplification(YulName const& _name) { if (m_translations.count(_name)) return; @@ -102,19 +102,19 @@ void NameSimplifier::findSimplification(YulString const& _name) for (auto const& [pattern, substitute]: replacements) { std::string candidate = regex_replace(name, pattern, substitute); - if (!candidate.empty() && !m_context.dispenser.illegalName(YulString(candidate))) + if (!candidate.empty() && !m_context.dispenser.illegalName(YulName(candidate))) name = candidate; } if (name != _name.str()) { - YulString newName{name}; + YulName newName{name}; m_context.dispenser.markUsed(newName); m_translations[_name] = std::move(newName); } } -void NameSimplifier::translate(YulString& _name) +void NameSimplifier::translate(YulName& _name) { auto it = m_translations.find(_name); if (it != m_translations.end()) diff --git a/libyul/optimiser/NameSimplifier.h b/libyul/optimiser/NameSimplifier.h index 34cf69451..848e61f56 100644 --- a/libyul/optimiser/NameSimplifier.h +++ b/libyul/optimiser/NameSimplifier.h @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include @@ -62,11 +62,11 @@ class NameSimplifier: public ASTModifier /// Tries to rename a list of variables. void renameVariables(std::vector& _variables); - void findSimplification(YulString const& _name); - void translate(YulString& _name); + void findSimplification(YulName const& _name); + void translate(YulName& _name); OptimiserStepContext& m_context; - std::map m_translations; + std::map m_translations; }; } diff --git a/libyul/optimiser/OptimiserStep.h b/libyul/optimiser/OptimiserStep.h index e3e5fe4c6..89bfcef81 100644 --- a/libyul/optimiser/OptimiserStep.h +++ b/libyul/optimiser/OptimiserStep.h @@ -29,14 +29,13 @@ namespace solidity::yul struct Dialect; struct Block; -class YulString; class NameDispenser; struct OptimiserStepContext { Dialect const& dialect; NameDispenser& dispenser; - std::set const& reservedIdentifiers; + std::set const& reservedIdentifiers; /// The value nullopt represents creation code std::optional expectedExecutionsPerDeployment; }; diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index bfa3d888f..19f262060 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -55,12 +55,12 @@ void yul::removeEmptyBlocks(Block& _block) ranges::actions::remove_if(_block.statements, isEmptyBlock); } -bool yul::isRestrictedIdentifier(Dialect const& _dialect, YulString const& _identifier) +bool yul::isRestrictedIdentifier(Dialect const& _dialect, YulName const& _identifier) { return _identifier.empty() || hasLeadingOrTrailingDot(_identifier.str()) || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier); } -std::optional yul::toEVMInstruction(Dialect const& _dialect, YulString const& _name) +std::optional yul::toEVMInstruction(Dialect const& _dialect, YulName const& _name) { if (auto const* dialect = dynamic_cast(&_dialect)) if (BuiltinFunctionForEVM const* builtin = dialect->builtin(_name)) diff --git a/libyul/optimiser/OptimizerUtilities.h b/libyul/optimiser/OptimizerUtilities.h index cb07f7a53..911a1be0a 100644 --- a/libyul/optimiser/OptimizerUtilities.h +++ b/libyul/optimiser/OptimizerUtilities.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -45,10 +45,10 @@ void removeEmptyBlocks(Block& _block); /// Returns true if a given literal can not be used as an identifier. /// This includes Yul keywords and builtins of the given dialect. -bool isRestrictedIdentifier(Dialect const& _dialect, YulString const& _identifier); +bool isRestrictedIdentifier(Dialect const& _dialect, YulName const& _identifier); /// Helper function that returns the instruction, if the `_name` is a BuiltinFunction -std::optional toEVMInstruction(Dialect const& _dialect, YulString const& _name); +std::optional toEVMInstruction(Dialect const& _dialect, YulName const& _name); /// Helper function that returns the EVM version from a dialect. /// It returns the default EVM version if dialect is not an EVMDialect. diff --git a/libyul/optimiser/Rematerialiser.cpp b/libyul/optimiser/Rematerialiser.cpp index db6920f24..fe33b10a2 100644 --- a/libyul/optimiser/Rematerialiser.cpp +++ b/libyul/optimiser/Rematerialiser.cpp @@ -31,7 +31,7 @@ using namespace solidity; using namespace solidity::yul; -void Rematerialiser::run(Dialect const& _dialect, Block& _ast, std::set _varsToAlwaysRematerialize, bool _onlySelectedVariables) +void Rematerialiser::run(Dialect const& _dialect, Block& _ast, std::set _varsToAlwaysRematerialize, bool _onlySelectedVariables) { Rematerialiser{_dialect, _ast, std::move(_varsToAlwaysRematerialize), _onlySelectedVariables}(_ast); } @@ -39,7 +39,7 @@ void Rematerialiser::run(Dialect const& _dialect, Block& _ast, std::set _varsToAlwaysRematerialize, + std::set _varsToAlwaysRematerialize, bool _onlySelectedVariables ): DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore), @@ -54,7 +54,7 @@ void Rematerialiser::visit(Expression& _e) if (std::holds_alternative(_e)) { Identifier& identifier = std::get(_e); - YulString name = identifier.name; + YulName name = identifier.name; if (AssignedValue const* value = variableValue(name)) { assertThrow(value->value, OptimizerException, ""); @@ -93,7 +93,7 @@ void LiteralRematerialiser::visit(Expression& _e) if (std::holds_alternative(_e)) { Identifier& identifier = std::get(_e); - YulString name = identifier.name; + YulName name = identifier.name; if (AssignedValue const* value = variableValue(name)) { assertThrow(value->value, OptimizerException, ""); diff --git a/libyul/optimiser/Rematerialiser.h b/libyul/optimiser/Rematerialiser.h index 9ee5209fd..a482ef53e 100644 --- a/libyul/optimiser/Rematerialiser.h +++ b/libyul/optimiser/Rematerialiser.h @@ -50,7 +50,7 @@ class Rematerialiser: public DataFlowAnalyzer static void run( Dialect const& _dialect, Block& _ast, - std::set _varsToAlwaysRematerialize = {}, + std::set _varsToAlwaysRematerialize = {}, bool _onlySelectedVariables = false ); @@ -58,7 +58,7 @@ class Rematerialiser: public DataFlowAnalyzer Rematerialiser( Dialect const& _dialect, Block& _ast, - std::set _varsToAlwaysRematerialize = {}, + std::set _varsToAlwaysRematerialize = {}, bool _onlySelectedVariables = false ); @@ -67,8 +67,8 @@ class Rematerialiser: public DataFlowAnalyzer using ASTModifier::visit; void visit(Expression& _e) override; - std::map m_referenceCounts; - std::set m_varsToAlwaysRematerialize; + std::map m_referenceCounts; + std::set m_varsToAlwaysRematerialize; bool m_onlySelectedVariables = false; }; diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index dba2f6f04..80abdf7e6 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -46,7 +46,7 @@ class IntroduceSSA: public ASTModifier public: explicit IntroduceSSA( NameDispenser& _nameDispenser, - std::set const& _variablesToReplace, + std::set const& _variablesToReplace, TypeInfo& _typeInfo ): m_nameDispenser(_nameDispenser), @@ -58,7 +58,7 @@ class IntroduceSSA: public ASTModifier private: NameDispenser& m_nameDispenser; - std::set const& m_variablesToReplace; + std::set const& m_variablesToReplace; TypeInfo const& m_typeInfo; }; @@ -90,8 +90,8 @@ void IntroduceSSA::operator()(Block& _block) TypedNameList newVariables; for (auto const& var: varDecl.variables) { - YulString oldName = var.name; - YulString newName = m_nameDispenser.newName(oldName); + YulName oldName = var.name; + YulName newName = m_nameDispenser.newName(oldName); newVariables.emplace_back(TypedName{debugData, newName, var.type}); statements.emplace_back(VariableDeclaration{ debugData, @@ -117,8 +117,8 @@ void IntroduceSSA::operator()(Block& _block) TypedNameList newVariables; for (auto const& var: assignment.variableNames) { - YulString oldName = var.name; - YulString newName = m_nameDispenser.newName(oldName); + YulName oldName = var.name; + YulName newName = m_nameDispenser.newName(oldName); newVariables.emplace_back(TypedName{debugData, newName, m_typeInfo.typeOfVariable(oldName) @@ -148,7 +148,7 @@ class IntroduceControlFlowSSA: public ASTModifier public: explicit IntroduceControlFlowSSA( NameDispenser& _nameDispenser, - std::set const& _variablesToReplace, + std::set const& _variablesToReplace, TypeInfo const& _typeInfo ): m_nameDispenser(_nameDispenser), @@ -163,19 +163,19 @@ class IntroduceControlFlowSSA: public ASTModifier private: NameDispenser& m_nameDispenser; - std::set const& m_variablesToReplace; + std::set const& m_variablesToReplace; /// Variables (that are to be replaced) currently in scope. - std::set m_variablesInScope; + std::set m_variablesInScope; /// Variables that do not have a specific value. - util::UniqueVector m_variablesToReassign; + util::UniqueVector m_variablesToReassign; TypeInfo const& m_typeInfo; }; void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function) { - std::set varsInScope; + std::set varsInScope; std::swap(varsInScope, m_variablesInScope); - util::UniqueVector toReassign; + util::UniqueVector toReassign; std::swap(toReassign, m_variablesToReassign); for (auto const& param: _function.parameters) @@ -207,7 +207,7 @@ void IntroduceControlFlowSSA::operator()(Switch& _switch) { yulAssert(m_variablesToReassign.empty(), ""); - util::UniqueVector toReassign; + util::UniqueVector toReassign; for (auto& c: _switch.cases) { (*this)(c.body); @@ -219,17 +219,17 @@ void IntroduceControlFlowSSA::operator()(Switch& _switch) void IntroduceControlFlowSSA::operator()(Block& _block) { - util::UniqueVector variablesDeclaredHere; - util::UniqueVector assignedVariables; + util::UniqueVector variablesDeclaredHere; + util::UniqueVector assignedVariables; util::iterateReplacing( _block.statements, [&](Statement& _s) -> std::optional> { std::vector toPrepend; - for (YulString toReassign: m_variablesToReassign) + for (YulName toReassign: m_variablesToReassign) { - YulString newName = m_nameDispenser.newName(toReassign); + YulName newName = m_nameDispenser.newName(toReassign); toPrepend.emplace_back(VariableDeclaration{ debugDataOf(_s), {TypedName{debugDataOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}}, @@ -281,7 +281,7 @@ void IntroduceControlFlowSSA::operator()(Block& _block) class PropagateValues: public ASTModifier { public: - explicit PropagateValues(std::set const& _variablesToReplace): + explicit PropagateValues(std::set const& _variablesToReplace): m_variablesToReplace(_variablesToReplace) { } @@ -294,9 +294,9 @@ class PropagateValues: public ASTModifier private: /// 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. - std::set const& m_variablesToReplace; - std::map m_currentVariableValues; - std::set m_clearAtEndOfBlock; + std::set const& m_variablesToReplace; + std::map m_currentVariableValues; + std::set m_clearAtEndOfBlock; }; void PropagateValues::operator()(Identifier& _identifier) @@ -312,7 +312,7 @@ void PropagateValues::operator()(VariableDeclaration& _varDecl) if (_varDecl.variables.size() != 1) return; - YulString variable = _varDecl.variables.front().name; + YulName variable = _varDecl.variables.front().name; if (m_variablesToReplace.count(variable)) { // `let a := a_1` - regular declaration of non-SSA variable @@ -323,7 +323,7 @@ void PropagateValues::operator()(VariableDeclaration& _varDecl) else if (_varDecl.value && std::holds_alternative(*_varDecl.value)) { // `let a_1 := a` - assignment to SSA variable after a branch. - YulString value = std::get(*_varDecl.value).name; + YulName value = std::get(*_varDecl.value).name; if (m_variablesToReplace.count(value)) { // This is safe because `a_1` is not a "variable to replace" and thus @@ -341,7 +341,7 @@ void PropagateValues::operator()(Assignment& _assignment) if (_assignment.variableNames.size() != 1) return; - YulString name = _assignment.variableNames.front().name; + YulName name = _assignment.variableNames.front().name; if (!m_variablesToReplace.count(name)) return; @@ -364,7 +364,7 @@ void PropagateValues::operator()(ForLoop& _for) void PropagateValues::operator()(Block& _block) { - std::set clearAtParentBlock = std::move(m_clearAtEndOfBlock); + std::set clearAtParentBlock = std::move(m_clearAtEndOfBlock); m_clearAtEndOfBlock.clear(); ASTModifier::operator()(_block); @@ -380,7 +380,7 @@ void PropagateValues::operator()(Block& _block) void SSATransform::run(OptimiserStepContext& _context, Block& _ast) { TypeInfo typeInfo(_context.dialect, _ast); - std::set assignedVariables = assignedVariableNames(_ast); + std::set assignedVariables = assignedVariableNames(_ast); IntroduceSSA{_context.dispenser, assignedVariables, typeInfo}(_ast); IntroduceControlFlowSSA{_context.dispenser, assignedVariables, typeInfo}(_ast); PropagateValues{assignedVariables}(_ast); diff --git a/libyul/optimiser/SSAValueTracker.cpp b/libyul/optimiser/SSAValueTracker.cpp index 1d25cb54b..d39ce4b8d 100644 --- a/libyul/optimiser/SSAValueTracker.cpp +++ b/libyul/optimiser/SSAValueTracker.cpp @@ -49,17 +49,17 @@ void SSAValueTracker::operator()(VariableDeclaration const& _varDecl) setValue(_varDecl.variables.front().name, _varDecl.value.get()); } -std::set SSAValueTracker::ssaVariables(Block const& _ast) +std::set SSAValueTracker::ssaVariables(Block const& _ast) { SSAValueTracker t; t(_ast); - std::set ssaVars; + std::set ssaVars; for (auto const& value: t.values()) ssaVars.insert(value.first); return ssaVars; } -void SSAValueTracker::setValue(YulString _name, Expression const* _value) +void SSAValueTracker::setValue(YulName _name, Expression const* _value) { assertThrow( m_values.count(_name) == 0, diff --git a/libyul/optimiser/SSAValueTracker.h b/libyul/optimiser/SSAValueTracker.h index 5a7eee512..0196ecc40 100644 --- a/libyul/optimiser/SSAValueTracker.h +++ b/libyul/optimiser/SSAValueTracker.h @@ -47,18 +47,18 @@ class SSAValueTracker: public ASTWalker void operator()(VariableDeclaration const& _varDecl) override; void operator()(Assignment const& _assignment) override; - std::map const& values() const { return m_values; } - Expression const* value(YulString _name) const { return m_values.at(_name); } + std::map const& values() const { return m_values; } + Expression const* value(YulName _name) const { return m_values.at(_name); } - static std::set ssaVariables(Block const& _ast); + static std::set ssaVariables(Block const& _ast); private: - void setValue(YulString _name, Expression const* _value); + void setValue(YulName _name, Expression const* _value); /// Special expression whose address will be used in m_values. - /// YulString does not need to be reset because SSAValueTracker is short-lived. + /// YulName does not need to be reset because SSAValueTracker is short-lived. Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue(u256{0}), {}}}; - std::map m_values; + std::map m_values; }; } diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index 5d375b145..7dbbb676b 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -40,7 +40,7 @@ using namespace solidity::yul; SideEffectsCollector::SideEffectsCollector( Dialect const& _dialect, Expression const& _expression, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): SideEffectsCollector(_dialect, _functionSideEffects) { @@ -56,7 +56,7 @@ SideEffectsCollector::SideEffectsCollector(Dialect const& _dialect, Statement co SideEffectsCollector::SideEffectsCollector( Dialect const& _dialect, Block const& _ast, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): SideEffectsCollector(_dialect, _functionSideEffects) { @@ -66,7 +66,7 @@ SideEffectsCollector::SideEffectsCollector( SideEffectsCollector::SideEffectsCollector( Dialect const& _dialect, ForLoop const& _ast, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): SideEffectsCollector(_dialect, _functionSideEffects) { @@ -77,7 +77,7 @@ void SideEffectsCollector::operator()(FunctionCall const& _functionCall) { ASTWalker::operator()(_functionCall); - YulString functionName = _functionCall.functionName.name; + YulName functionName = _functionCall.functionName.name; if (BuiltinFunction const* f = m_dialect.builtin(functionName)) m_sideEffects += f->sideEffects; else if (m_functionSideEffects && m_functionSideEffects->count(functionName)) @@ -115,7 +115,7 @@ void MSizeFinder::operator()(FunctionCall const& _functionCall) m_msizeFound = true; } -std::map SideEffectsPropagator::sideEffects( +std::map SideEffectsPropagator::sideEffects( Dialect const& _dialect, CallGraph const& _directCallGraph ) @@ -126,7 +126,7 @@ std::map SideEffectsPropagator::sideEffects( // In the future, we should refine that, because the property // is actually a bit different from "not movable". - std::map ret; + std::map ret; for (auto const& function: _directCallGraph.functionsWithLoops + _directCallGraph.recursiveFunctions()) { ret[function].movable = false; @@ -137,9 +137,9 @@ std::map SideEffectsPropagator::sideEffects( for (auto const& call: _directCallGraph.functionCalls) { - YulString funName = call.first; + YulName funName = call.first; SideEffects sideEffects; - auto _visit = [&, visited = std::set{}](YulString _function, auto&& _recurse) mutable { + auto _visit = [&, visited = std::set{}](YulName _function, auto&& _recurse) mutable { if (!visited.insert(_function).second) return; if (sideEffects == SideEffects::worst()) @@ -150,7 +150,7 @@ std::map SideEffectsPropagator::sideEffects( { if (ret.count(_function)) sideEffects += ret[_function]; - for (YulString callee: _directCallGraph.functionCalls.at(_function)) + for (YulName callee: _directCallGraph.functionCalls.at(_function)) _recurse(callee, _recurse); } }; diff --git a/libyul/optimiser/Semantics.h b/libyul/optimiser/Semantics.h index df8ae17a5..1d0018897 100644 --- a/libyul/optimiser/Semantics.h +++ b/libyul/optimiser/Semantics.h @@ -42,23 +42,23 @@ class SideEffectsCollector: public ASTWalker public: explicit SideEffectsCollector( Dialect const& _dialect, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ): m_dialect(_dialect), m_functionSideEffects(_functionSideEffects) {} SideEffectsCollector( Dialect const& _dialect, Expression const& _expression, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); SideEffectsCollector(Dialect const& _dialect, Statement const& _statement); SideEffectsCollector( Dialect const& _dialect, Block const& _ast, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); SideEffectsCollector( Dialect const& _dialect, ForLoop const& _ast, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); using ASTWalker::operator(); @@ -117,7 +117,7 @@ class SideEffectsCollector: public ASTWalker private: Dialect const& m_dialect; - std::map const* m_functionSideEffects = nullptr; + std::map const* m_functionSideEffects = nullptr; SideEffects m_sideEffects; }; @@ -130,7 +130,7 @@ class SideEffectsCollector: public ASTWalker class SideEffectsPropagator { public: - static std::map sideEffects( + static std::map sideEffects( Dialect const& _dialect, CallGraph const& _directCallGraph ); @@ -195,7 +195,7 @@ class MovableChecker: public SideEffectsCollector public: explicit MovableChecker( Dialect const& _dialect, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ): SideEffectsCollector(_dialect, _functionSideEffects) {} MovableChecker(Dialect const& _dialect, Expression const& _expression); @@ -205,11 +205,11 @@ class MovableChecker: public SideEffectsCollector void visit(Statement const&) override; using ASTWalker::visit; - std::set const& referencedVariables() const { return m_variableReferences; } + std::set const& referencedVariables() const { return m_variableReferences; } private: /// Which variables the current expression references. - std::set m_variableReferences; + std::set m_variableReferences; }; struct ControlFlowSideEffects; @@ -231,7 +231,7 @@ class TerminationFinder TerminationFinder( Dialect const& _dialect, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ): m_dialect(_dialect), m_functionSideEffects(_functionSideEffects) {} /// @returns the index of the first statement in the provided sequence @@ -256,7 +256,7 @@ class TerminationFinder private: Dialect const& m_dialect; - std::map const* m_functionSideEffects; + std::map const* m_functionSideEffects; }; } diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index e2d468329..03e4ccdd0 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -40,7 +40,7 @@ using namespace solidity::yul; SimplificationRules::Rule const* SimplificationRules::findFirstMatch( Expression const& _expr, Dialect const& _dialect, - std::function const& _ssaValues + std::function const& _ssaValues ) { auto instruction = instructionAndArguments(_dialect, _expr); @@ -137,7 +137,7 @@ void Pattern::setMatchGroup(unsigned _group, std::map const& _ssaValues + std::function const& _ssaValues ) const { Expression const* expr = &_expr; @@ -146,7 +146,7 @@ bool Pattern::matches( // Do not do it for "Any" because we can check identity better for variables. if (m_kind != PatternKind::Any && std::holds_alternative(_expr)) { - YulString varName = std::get(_expr).name; + YulName varName = std::get(_expr).name; if (AssignedValue const* value = _ssaValues(varName)) if (Expression const* new_expr = value->value) expr = new_expr; @@ -252,7 +252,7 @@ Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData std::string name = util::toLower(instructionInfo(m_instruction, _evmVersion).name); return FunctionCall{_debugData, - Identifier{_debugData, YulString{name}}, + Identifier{_debugData, YulName{name}}, std::move(arguments) }; } diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index 5e498bd5c..9362ee855 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include @@ -64,7 +64,7 @@ class SimplificationRules static Rule const* findFirstMatch( Expression const& _expr, Dialect const& _dialect, - std::function const& _ssaValues + std::function const& _ssaValues ); /// Checks whether the rulelist is non-empty. This is usually enforced @@ -121,7 +121,7 @@ class Pattern bool matches( Expression const& _expr, Dialect const& _dialect, - std::function const& _ssaValues + std::function const& _ssaValues ) const; std::vector arguments() const { return m_arguments; } diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 58552147a..23d47b6ee 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -60,9 +60,9 @@ class RematCandidateSelector: public DataFlowAnalyzer /// @returns a map from function name to rematerialisation costs to a vector of variables to rematerialise /// and variables that occur in their expression. /// While the map is sorted by cost, the contained vectors are sorted by the order of occurrence. - std::map>> candidates() + std::map>> candidates() { - std::map>> cand; + std::map>> cand; for (auto const& [functionName, candidate]: m_candidates) { if (size_t const* cost = util::valueOrNullptr(m_expressionCodeCost, candidate)) @@ -88,7 +88,7 @@ class RematCandidateSelector: public DataFlowAnalyzer DataFlowAnalyzer::operator()(_varDecl); if (_varDecl.variables.size() == 1) { - YulString varName = _varDecl.variables.front().name; + YulName varName = _varDecl.variables.front().name; if (AssignedValue const* value = variableValue(varName)) { yulAssert(!m_expressionCodeCost.count(varName), ""); @@ -111,7 +111,7 @@ class RematCandidateSelector: public DataFlowAnalyzer { if (std::holds_alternative(_e)) { - YulString name = std::get(_e).name; + YulName name = std::get(_e).name; if (m_expressionCodeCost.count(name)) { if (!variableValue(name)) @@ -124,29 +124,29 @@ class RematCandidateSelector: public DataFlowAnalyzer } /// Remove the variable from the candidate set. - void rematImpossible(YulString _variable) + void rematImpossible(YulName _variable) { m_numReferences.erase(_variable); m_expressionCodeCost.erase(_variable); } - YulString m_currentFunctionName = {}; + YulName m_currentFunctionName = {}; /// All candidate variables by function name, in order of occurrence. - std::vector> m_candidates; + std::vector> m_candidates; /// Candidate variables and the code cost of their value. - std::map m_expressionCodeCost; + std::map m_expressionCodeCost; /// Number of references to each candidate variable. - std::map m_numReferences; + std::map m_numReferences; }; /// Selects at most @a _numVariables among @a _candidates. -std::set chooseVarsToEliminate( - std::map> const& _candidates, +std::set chooseVarsToEliminate( + std::map> const& _candidates, size_t _numVariables ) { - std::set varsToEliminate; + std::set varsToEliminate; for (auto&& [cost, candidates]: _candidates) for (auto&& candidate: candidates) { @@ -160,15 +160,15 @@ std::set chooseVarsToEliminate( void eliminateVariables( Dialect const& _dialect, Block& _ast, - std::map const& _numVariables, + std::map const& _numVariables, bool _allowMSizeOptimization ) { RematCandidateSelector selector{_dialect}; selector(_ast); - std::map>> candidates = selector.candidates(); + std::map>> candidates = selector.candidates(); - std::set varsToEliminate; + std::set varsToEliminate; for (auto const& [functionName, numVariables]: _numVariables) { yulAssert(numVariables > 0); @@ -177,14 +177,14 @@ void eliminateVariables( Rematerialiser::run(_dialect, _ast, std::move(varsToEliminate)); // Do not remove functions. - std::set allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names(); + std::set allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names(); UnusedPruner::runUntilStabilised(_dialect, _ast, _allowMSizeOptimization, nullptr, allFunctions); } void eliminateVariablesOptimizedCodegen( Dialect const& _dialect, Block& _ast, - std::map> const& _unreachables, + std::map> const& _unreachables, bool _allowMSizeOptimization ) { @@ -194,19 +194,19 @@ void eliminateVariablesOptimizedCodegen( RematCandidateSelector selector{_dialect}; selector(_ast); - std::map candidates; + std::map candidates; for (auto const& [functionName, candidatesInFunction]: selector.candidates()) for (auto [cost, candidatesWithCost]: candidatesInFunction) for (auto candidate: candidatesWithCost) candidates[candidate] = cost; - std::set varsToEliminate; + std::set varsToEliminate; // TODO: this currently ignores the fact that variables may reference other variables we want to eliminate. for (auto const& [functionName, unreachables]: _unreachables) for (auto const& unreachable: unreachables) { - std::map> suitableCandidates; + std::map> suitableCandidates; size_t neededSlots = unreachable.deficit; for (auto varName: unreachable.variableChoices) { @@ -229,7 +229,7 @@ void eliminateVariablesOptimizedCodegen( } Rematerialiser::run(_dialect, _ast, std::move(varsToEliminate), true); // Do not remove functions. - std::set allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names(); + std::set allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names(); UnusedPruner::runUntilStabilised(_dialect, _ast, _allowMSizeOptimization, nullptr, allFunctions); } @@ -268,7 +268,7 @@ bool StackCompressor::run( else for (size_t iterations = 0; iterations < _maxIterations; iterations++) { - std::map stackSurplus = CompilabilityChecker(_dialect, _object, _optimizeStackAllocation).stackDeficit; + std::map stackSurplus = CompilabilityChecker(_dialect, _object, _optimizeStackAllocation).stackDeficit; if (stackSurplus.empty()) return true; eliminateVariables( diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 0310858a1..24712938f 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -56,7 +56,7 @@ namespace */ struct MemoryOffsetAllocator { - uint64_t run(YulString _function = YulString{}) + uint64_t run(YulName _function = YulName{}) { if (slotsRequiredForFunction.count(_function)) return slotsRequiredForFunction[_function]; @@ -66,7 +66,7 @@ struct MemoryOffsetAllocator uint64_t requiredSlots = 0; if (callGraph.count(_function)) - for (YulString child: callGraph.at(_function)) + for (YulName child: callGraph.at(_function)) requiredSlots = std::max(run(child), requiredSlots); if (auto const* unreachables = util::valueOrNullptr(unreachableVariables, _function)) @@ -84,7 +84,7 @@ struct MemoryOffsetAllocator // Assign slots for all variables that become unreachable in the function body, if the above did not // assign a slot for them already. - for (YulString variable: *unreachables) + for (YulName variable: *unreachables) // The empty case is a function with too many arguments or return values, // which was already handled above. if (!variable.empty() && !slotAllocations.count(variable)) @@ -96,16 +96,16 @@ struct MemoryOffsetAllocator /// Maps function names to the set of unreachable variables in that function. /// An empty variable name means that the function has too many arguments or return variables. - std::map> const& unreachableVariables; + std::map> const& unreachableVariables; /// The graph of immediate function calls of all functions. - std::map> const& callGraph; + std::map> const& callGraph; /// Maps the name of each user-defined function to its definition. - std::map const& functionDefinitions; + std::map const& functionDefinitions; /// Maps variable names to the memory slot the respective variable is assigned. - std::map slotAllocations{}; + std::map slotAllocations{}; /// Maps function names to the number of memory slots the respective function requires. - std::map slotsRequiredForFunction{}; + std::map slotsRequiredForFunction{}; }; u256 literalArgumentValue(FunctionCall const& _call) @@ -145,10 +145,10 @@ void StackLimitEvader::run( void StackLimitEvader::run( OptimiserStepContext& _context, Object& _object, - std::map> const& _stackTooDeepErrors + std::map> const& _stackTooDeepErrors ) { - std::map> unreachableVariables; + std::map> unreachableVariables; for (auto&& [function, stackTooDeepErrors]: _stackTooDeepErrors) { auto& unreachables = unreachableVariables[function]; @@ -164,7 +164,7 @@ void StackLimitEvader::run( void StackLimitEvader::run( OptimiserStepContext& _context, Object& _object, - std::map> const& _unreachableVariables + std::map> const& _unreachableVariables ) { yulAssert(_object.code, ""); @@ -174,10 +174,7 @@ void StackLimitEvader::run( "StackLimitEvader can only be run on objects using the EVMDialect with object access." ); - std::vector memoryGuardCalls = findFunctionCalls( - *_object.code, - "memoryguard"_yulstring - ); + std::vector memoryGuardCalls = findFunctionCalls(*_object.code, "memoryguard"_yulname); // Do not optimise, if no ``memoryguard`` call is found. if (memoryGuardCalls.empty()) return; @@ -193,11 +190,11 @@ void StackLimitEvader::run( CallGraph callGraph = CallGraphGenerator::callGraph(*_object.code); // We cannot move variables in recursive functions to fixed memory offsets. - for (YulString function: callGraph.recursiveFunctions()) + for (YulName function: callGraph.recursiveFunctions()) if (_unreachableVariables.count(function)) return; - std::map functionDefinitions = allFunctionDefinitions(*_object.code); + std::map functionDefinitions = allFunctionDefinitions(*_object.code); MemoryOffsetAllocator memoryOffsetAllocator{_unreachableVariables, callGraph.functionCalls, functionDefinitions}; uint64_t requiredSlots = memoryOffsetAllocator.run(); @@ -206,7 +203,7 @@ void StackLimitEvader::run( StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, *_object.code); reservedMemory += 32 * requiredSlots; - for (FunctionCall* memoryGuardCall: findFunctionCalls(*_object.code, "memoryguard"_yulstring)) + for (FunctionCall* memoryGuardCall: findFunctionCalls(*_object.code, "memoryguard"_yulname)) { Literal* literal = std::get_if(&memoryGuardCall->arguments.front()); yulAssert(literal && literal->kind == LiteralKind::Number, ""); diff --git a/libyul/optimiser/StackLimitEvader.h b/libyul/optimiser/StackLimitEvader.h index 025553200..0411f0573 100644 --- a/libyul/optimiser/StackLimitEvader.h +++ b/libyul/optimiser/StackLimitEvader.h @@ -60,7 +60,7 @@ class StackLimitEvader static void run( OptimiserStepContext& _context, Object& _object, - std::map> const& _unreachableVariables + std::map> const& _unreachableVariables ); /// @a _stackTooDeepErrors can be determined by the StackLayoutGenerator. /// Can only be run on the EVM dialect with objects. @@ -70,7 +70,7 @@ class StackLimitEvader static void run( OptimiserStepContext& _context, Object& _object, - std::map> const& _stackTooDeepErrors + std::map> const& _stackTooDeepErrors ); /// Determines stack too deep errors using the appropriate code generation backend. /// Can only be run on the EVM dialect with objects. diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index dbf3183fb..7ec579034 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -77,7 +77,7 @@ FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::Co void StackToMemoryMover::run( OptimiserStepContext& _context, u256 _reservedMemory, - std::map const& _memorySlots, + std::map const& _memorySlots, uint64_t _numRequiredSlots, Block& _block ) @@ -88,10 +88,10 @@ void StackToMemoryMover::run( memoryOffsetTracker, util::applyMap( allFunctionDefinitions(_block), - util::mapTuple([](YulString _name, FunctionDefinition const* _funDef) { + util::mapTuple([](YulName _name, FunctionDefinition const* _funDef) { return make_pair(_name, _funDef->returnVariables); }), - std::map{} + std::map{} ) ); stackToMemoryMover(_block); @@ -101,7 +101,7 @@ void StackToMemoryMover::run( StackToMemoryMover::StackToMemoryMover( OptimiserStepContext& _context, VariableMemoryOffsetTracker const& _memoryOffsetTracker, - std::map _functionReturnVariables + std::map _functionReturnVariables ): m_context(_context), m_memoryOffsetTracker(_memoryOffsetTracker), @@ -150,7 +150,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) std::not_fn(m_memoryOffsetTracker) ) | ranges::to; // Generate new function without return variable and with only the non-moved parameters. - YulString newFunctionName = m_context.dispenser.newName(_functionDefinition.name); + YulName newFunctionName = m_context.dispenser.newName(_functionDefinition.name); m_newFunctionDefinitions.emplace_back(FunctionDefinition{ _functionDefinition.debugData, newFunctionName, @@ -159,7 +159,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) std::move(_functionDefinition.body) }); // Generate new names for the arguments to maintain disambiguation. - std::map newArgumentNames; + std::map newArgumentNames; for (TypedName const& _var: stackParameters) newArgumentNames[_var.name] = m_context.dispenser.newName(_var.name); for (auto& parameter: _functionDefinition.parameters) @@ -255,7 +255,7 @@ void StackToMemoryMover::operator()(Block& _block) rhs = std::make_unique(generateMemoryLoad(m_context.dialect, debugData, *rhsSlot)); else { - YulString tempVarName = m_nameDispenser.newName(lhsVar.name); + YulName tempVarName = m_nameDispenser.newName(lhsVar.name); tempDecl.variables.emplace_back(TypedName{lhsVar.debugData, tempVarName, {}}); rhs = std::make_unique(Identifier{debugData, tempVarName}); } @@ -309,7 +309,7 @@ void StackToMemoryMover::visit(Expression& _expression) _expression = generateMemoryLoad(m_context.dialect, identifier->debugData, *offset); } -std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString const& _variable) const +std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulName const& _variable) const { if (m_memorySlots.count(_variable)) { diff --git a/libyul/optimiser/StackToMemoryMover.h b/libyul/optimiser/StackToMemoryMover.h index 79c7276ed..739266031 100644 --- a/libyul/optimiser/StackToMemoryMover.h +++ b/libyul/optimiser/StackToMemoryMover.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -142,7 +143,7 @@ class StackToMemoryMover: ASTModifier static void run( OptimiserStepContext& _context, u256 _reservedMemory, - std::map const& _memorySlots, + std::map const& _memorySlots, uint64_t _numRequiredSlots, Block& _block ); @@ -158,42 +159,42 @@ class StackToMemoryMover: ASTModifier public: VariableMemoryOffsetTracker( u256 _reservedMemory, - std::map const& _memorySlots, + std::map const& _memorySlots, uint64_t _numRequiredSlots ): m_reservedMemory(_reservedMemory), m_memorySlots(_memorySlots), m_numRequiredSlots(_numRequiredSlots) {} - /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal + /// @returns a YulName containing the memory offset to be assigned to @a _variable as number literal /// or std::nullopt if the variable should not be moved. - std::optional operator()(YulString const& _variable) const; - /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal + std::optional operator()(YulName const& _variable) const; + /// @returns a YulName containing the memory offset to be assigned to @a _variable as number literal /// or std::nullopt if the variable should not be moved. std::optional operator()(TypedName const& _variable) const; - /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal + /// @returns a YulName containing the memory offset to be assigned to @a _variable as number literal /// or std::nullopt if the variable should not be moved. std::optional operator()(Identifier const& _variable) const; private: u256 m_reservedMemory; - std::map const& m_memorySlots; + std::map const& m_memorySlots; uint64_t m_numRequiredSlots = 0; }; struct FunctionMoveInfo { - std::vector> returnVariableSlots; + std::vector> returnVariableSlots; }; StackToMemoryMover( OptimiserStepContext& _context, VariableMemoryOffsetTracker const& _memoryOffsetTracker, - std::map> _functionReturnVariables + std::map> _functionReturnVariables ); OptimiserStepContext& m_context; VariableMemoryOffsetTracker const& m_memoryOffsetTracker; NameDispenser& m_nameDispenser; /// Map from function names to the return variables of the function with that name. - std::map> m_functionReturnVariables; + std::map> m_functionReturnVariables; /// List of functions generated while running this step that are to be appended to the code in the end. std::list m_newFunctionDefinitions; }; diff --git a/libyul/optimiser/Substitution.cpp b/libyul/optimiser/Substitution.cpp index b2d4d469e..5baec51e3 100644 --- a/libyul/optimiser/Substitution.cpp +++ b/libyul/optimiser/Substitution.cpp @@ -30,7 +30,7 @@ Expression Substitution::translate(Expression const& _expression) { if (std::holds_alternative(_expression)) { - YulString name = std::get(_expression).name; + YulName name = std::get(_expression).name; if (m_substitutions.count(name)) // No recursive substitution return ASTCopier().translate(*m_substitutions.at(name)); diff --git a/libyul/optimiser/Substitution.h b/libyul/optimiser/Substitution.h index f76dcc72e..2d4ccffc0 100644 --- a/libyul/optimiser/Substitution.h +++ b/libyul/optimiser/Substitution.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include @@ -35,13 +35,13 @@ namespace solidity::yul class Substitution: public ASTCopier { public: - Substitution(std::map const& _substitutions): + Substitution(std::map const& _substitutions): m_substitutions(_substitutions) {} Expression translate(Expression const& _expression) override; private: - std::map const& m_substitutions; + std::map const& m_substitutions; }; } diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 83bc03700..c4004948c 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -141,7 +141,7 @@ void OptimiserSuite::run( std::string_view _optimisationSequence, std::string_view _optimisationCleanupSequence, std::optional _expectedExecutionsPerDeployment, - std::set const& _externallyUsedIdentifiers + std::set const& _externallyUsedIdentifiers ) { EVMDialect const* evmDialect = dynamic_cast(&_dialect); @@ -150,7 +150,7 @@ void OptimiserSuite::run( evmDialect && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); - std::set reservedIdentifiers = _externallyUsedIdentifiers; + std::set reservedIdentifiers = _externallyUsedIdentifiers; reservedIdentifiers += _dialect.fixedFunctionNames(); *_object.code = std::get(Disambiguator( diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 6e3886da3..15a41cb9f 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include #include #include @@ -70,7 +70,7 @@ class OptimiserSuite std::string_view _optimisationSequence, std::string_view _optimisationCleanupSequence, std::optional _expectedExecutionsPerDeployment, - std::set const& _externallyUsedIdentifiers = {} + std::set const& _externallyUsedIdentifiers = {} ); /// Ensures that specified sequence of step abbreviations is well-formed and can be executed. diff --git a/libyul/optimiser/SyntacticalEquality.h b/libyul/optimiser/SyntacticalEquality.h index 5a8d2b49b..0665a5efb 100644 --- a/libyul/optimiser/SyntacticalEquality.h +++ b/libyul/optimiser/SyntacticalEquality.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include #include @@ -84,8 +84,8 @@ class SyntacticallyEqual } std::size_t m_idsUsed = 0; - std::map m_identifiersLHS; - std::map m_identifiersRHS; + std::map m_identifiersLHS; + std::map m_identifiersRHS; }; /** diff --git a/libyul/optimiser/TypeInfo.cpp b/libyul/optimiser/TypeInfo.cpp index 16ce65496..754c0bad0 100644 --- a/libyul/optimiser/TypeInfo.cpp +++ b/libyul/optimiser/TypeInfo.cpp @@ -62,8 +62,8 @@ class TypeInfo::TypeCollector: public ASTWalker } } - std::map variableTypes; - std::map functionTypes; + std::map variableTypes; + std::map functionTypes; }; @@ -75,12 +75,12 @@ TypeInfo::TypeInfo(Dialect const& _dialect, Block const& _ast): m_variableTypes = std::move(types.variableTypes); } -YulString TypeInfo::typeOf(Expression const& _expression) const +YulName TypeInfo::typeOf(Expression const& _expression) const { return std::visit(GenericVisitor{ [&](FunctionCall const& _funCall) { - YulString name = _funCall.functionName.name; - std::vector const* retTypes = nullptr; + YulName name = _funCall.functionName.name; + std::vector const* retTypes = nullptr; if (BuiltinFunction const* fun = m_dialect.builtin(name)) retTypes = &fun->returns; else @@ -97,7 +97,7 @@ YulString TypeInfo::typeOf(Expression const& _expression) const }, _expression); } -YulString TypeInfo::typeOfVariable(YulString _name) const +YulName TypeInfo::typeOfVariable(YulName _name) const { return m_variableTypes.at(_name); } diff --git a/libyul/optimiser/TypeInfo.h b/libyul/optimiser/TypeInfo.h index 5ed0a0d55..96c43875a 100644 --- a/libyul/optimiser/TypeInfo.h +++ b/libyul/optimiser/TypeInfo.h @@ -21,7 +21,7 @@ #pragma once #include -#include +#include #include #include @@ -40,26 +40,26 @@ class TypeInfo public: TypeInfo(Dialect const& _dialect, Block const& _ast); - void setVariableType(YulString _name, YulString _type) { m_variableTypes[_name] = _type; } + void setVariableType(YulName _name, YulName _type) { m_variableTypes[_name] = _type; } /// @returns the type of an expression that is assumed to return exactly one value. - YulString typeOf(Expression const& _expression) const; + YulName typeOf(Expression const& _expression) const; /// \returns the type of variable - YulString typeOfVariable(YulString _name) const; + YulName typeOfVariable(YulName _name) const; private: class TypeCollector; struct FunctionType { - std::vector parameters; - std::vector returns; + std::vector parameters; + std::vector returns; }; Dialect const& m_dialect; - std::map m_variableTypes; - std::map m_functionTypes; + std::map m_variableTypes; + std::map m_functionTypes; }; } diff --git a/libyul/optimiser/UnusedAssignEliminator.cpp b/libyul/optimiser/UnusedAssignEliminator.cpp index f3d78288f..13a6ba9ee 100644 --- a/libyul/optimiser/UnusedAssignEliminator.cpp +++ b/libyul/optimiser/UnusedAssignEliminator.cpp @@ -92,7 +92,7 @@ void UnusedAssignEliminator::operator()(FunctionCall const& _functionCall) void UnusedAssignEliminator::operator()(Leave const&) { - for (YulString name: m_returnVariables) + for (YulName name: m_returnVariables) markUsed(name); m_activeStores.clear(); } @@ -152,7 +152,7 @@ void UnusedAssignEliminator::finalizeFunctionDefinition(FunctionDefinition const markUsed(retParam.name); } -void UnusedAssignEliminator::markUsed(YulString _variable) +void UnusedAssignEliminator::markUsed(YulName _variable) { for (auto& assignment: m_activeStores[_variable]) m_usedStores.insert(assignment); diff --git a/libyul/optimiser/UnusedAssignEliminator.h b/libyul/optimiser/UnusedAssignEliminator.h index 800d626eb..9c3b1e4bc 100644 --- a/libyul/optimiser/UnusedAssignEliminator.h +++ b/libyul/optimiser/UnusedAssignEliminator.h @@ -121,7 +121,7 @@ class UnusedAssignEliminator: public UnusedStoreBase explicit UnusedAssignEliminator( Dialect const& _dialect, - std::map _controlFlowSideEffects + std::map _controlFlowSideEffects ): UnusedStoreBase(_dialect), m_controlFlowSideEffects(_controlFlowSideEffects) @@ -141,10 +141,10 @@ class UnusedAssignEliminator: public UnusedStoreBase void shortcutNestedLoop(ActiveStores const& _beforeLoop) override; void finalizeFunctionDefinition(FunctionDefinition const& _functionDefinition) override; - void markUsed(YulString _variable); + void markUsed(YulName _variable); - std::set m_returnVariables; - std::map m_controlFlowSideEffects; + std::set m_returnVariables; + std::map m_controlFlowSideEffects; }; } diff --git a/libyul/optimiser/UnusedFunctionParameterPruner.cpp b/libyul/optimiser/UnusedFunctionParameterPruner.cpp index 40c2fe80c..49c0a9c4d 100644 --- a/libyul/optimiser/UnusedFunctionParameterPruner.cpp +++ b/libyul/optimiser/UnusedFunctionParameterPruner.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include @@ -42,7 +42,7 @@ using namespace solidity::yul::unusedFunctionsCommon; void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ast) { - std::map references = VariableReferencesCounter::countReferences(_ast); + std::map references = VariableReferencesCounter::countReferences(_ast); auto used = [&](auto v) -> bool { return references.count(v.name); }; // Function name and a pair of boolean masks, the first corresponds to parameters and the second @@ -54,7 +54,7 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ // Similarly for the second vector in the pair, a value `false` at index `i` indicates that the // return parameter at index `i` in `FunctionDefinition::returnVariables` is unused inside // function body. - std::map, std::vector>> usedParametersAndReturnVariables; + std::map, std::vector>> usedParametersAndReturnVariables; // Step 1 of UnusedFunctionParameterPruner: Find functions whose parameters (both arguments and // return-parameters) are not used in its body. @@ -72,7 +72,7 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ }; } - std::set functionNamesToFree = util::keys(usedParametersAndReturnVariables); + std::set functionNamesToFree = util::keys(usedParametersAndReturnVariables); // Step 2 of UnusedFunctionParameterPruner: Renames the function and replaces all references to // the function, say `f`, by its new name, say `f_1`. @@ -81,7 +81,7 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ // Inverse-Map of the above translations. In the above example, this will store an element with // key `f_1` and value `f`. - std::map newToOriginalNames = invertMap(replace.translations()); + std::map newToOriginalNames = invertMap(replace.translations()); // Step 3 of UnusedFunctionParameterPruner: introduce a new function in the block with body of // the old one. Replace the body of the old one with a function call to the new one with reduced @@ -98,8 +98,8 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ if (newToOriginalNames.count(originalFunction.name)) { - YulString linkingFunctionName = originalFunction.name; - YulString originalFunctionName = newToOriginalNames.at(linkingFunctionName); + YulName linkingFunctionName = originalFunction.name; + YulName originalFunctionName = newToOriginalNames.at(linkingFunctionName); std::pair, std::vector> used = usedParametersAndReturnVariables.at(originalFunctionName); diff --git a/libyul/optimiser/UnusedFunctionsCommon.cpp b/libyul/optimiser/UnusedFunctionsCommon.cpp index ed9d0ba4c..bd38b33ca 100644 --- a/libyul/optimiser/UnusedFunctionsCommon.cpp +++ b/libyul/optimiser/UnusedFunctionsCommon.cpp @@ -30,8 +30,8 @@ using namespace solidity::yul::unusedFunctionsCommon; FunctionDefinition unusedFunctionsCommon::createLinkingFunction( FunctionDefinition const& _original, std::pair, std::vector> const& _usedParametersAndReturns, - YulString const& _originalFunctionName, - YulString const& _linkingFunctionName, + YulName const& _originalFunctionName, + YulName const& _linkingFunctionName, NameDispenser& _nameDispenser ) { diff --git a/libyul/optimiser/UnusedFunctionsCommon.h b/libyul/optimiser/UnusedFunctionsCommon.h index 2b0f3000d..5aa231b1e 100644 --- a/libyul/optimiser/UnusedFunctionsCommon.h +++ b/libyul/optimiser/UnusedFunctionsCommon.h @@ -52,8 +52,8 @@ inline bool tooSimpleToBePruned(FunctionDefinition const& _f) FunctionDefinition createLinkingFunction( FunctionDefinition const& _original, std::pair, std::vector> const& _usedParametersAndReturns, - YulString const& _originalFunctionName, - YulString const& _linkingFunctionName, + YulName const& _originalFunctionName, + YulName const& _linkingFunctionName, NameDispenser& _nameDispenser ); diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index a64f37ebe..9df51cf7f 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -43,8 +43,8 @@ UnusedPruner::UnusedPruner( Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects, - std::set const& _externallyUsedFunctions + std::map const* _functionSideEffects, + std::set const& _externallyUsedFunctions ): m_dialect(_dialect), m_allowMSizeOptimization(_allowMSizeOptimization), @@ -59,7 +59,7 @@ UnusedPruner::UnusedPruner( Dialect const& _dialect, FunctionDefinition& _function, bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions + std::set const& _externallyUsedFunctions ): m_dialect(_dialect), m_allowMSizeOptimization(_allowMSizeOptimization) @@ -135,8 +135,8 @@ void UnusedPruner::runUntilStabilised( Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects, - std::set const& _externallyUsedFunctions + std::map const* _functionSideEffects, + std::set const& _externallyUsedFunctions ) { while (true) @@ -153,10 +153,10 @@ void UnusedPruner::runUntilStabilised( void UnusedPruner::runUntilStabilisedOnFullAST( Dialect const& _dialect, Block& _ast, - std::set const& _externallyUsedFunctions + std::set const& _externallyUsedFunctions ) { - std::map functionSideEffects = + std::map functionSideEffects = SideEffectsPropagator::sideEffects(_dialect, CallGraphGenerator::callGraph(_ast)); bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _ast); runUntilStabilised(_dialect, _ast, allowMSizeOptimization, &functionSideEffects, _externallyUsedFunctions); @@ -166,7 +166,7 @@ void UnusedPruner::runUntilStabilised( Dialect const& _dialect, FunctionDefinition& _function, bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions + std::set const& _externallyUsedFunctions ) { while (true) @@ -178,12 +178,12 @@ void UnusedPruner::runUntilStabilised( } } -bool UnusedPruner::used(YulString _name) const +bool UnusedPruner::used(YulName _name) const { return m_references.count(_name) && m_references.at(_name) > 0; } -void UnusedPruner::subtractReferences(std::map const& _subtrahend) +void UnusedPruner::subtractReferences(std::map const& _subtrahend) { for (auto const& ref: _subtrahend) { diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index e4587d5d7..b0ba53bce 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include @@ -64,14 +64,14 @@ class UnusedPruner: public ASTModifier Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects = nullptr, - std::set const& _externallyUsedFunctions = {} + std::map const* _functionSideEffects = nullptr, + std::set const& _externallyUsedFunctions = {} ); static void run( Dialect const& _dialect, Block& _ast, - std::set const& _externallyUsedFunctions = {} + std::set const& _externallyUsedFunctions = {} ) { runUntilStabilisedOnFullAST(_dialect, _ast, _externallyUsedFunctions); @@ -84,7 +84,7 @@ class UnusedPruner: public ASTModifier static void runUntilStabilisedOnFullAST( Dialect const& _dialect, Block& _ast, - std::set const& _externallyUsedFunctions = {} + std::set const& _externallyUsedFunctions = {} ); // Run the pruner until the code does not change anymore. @@ -96,7 +96,7 @@ class UnusedPruner: public ASTModifier Dialect const& _dialect, FunctionDefinition& _functionDefinition, bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions = {} + std::set const& _externallyUsedFunctions = {} ); private: @@ -104,24 +104,24 @@ class UnusedPruner: public ASTModifier Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects = nullptr, - std::set const& _externallyUsedFunctions = {} + std::map const* _functionSideEffects = nullptr, + std::set const& _externallyUsedFunctions = {} ); UnusedPruner( Dialect const& _dialect, FunctionDefinition& _function, bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions = {} + std::set const& _externallyUsedFunctions = {} ); - bool used(YulString _name) const; - void subtractReferences(std::map const& _subtrahend); + bool used(YulName _name) const; + void subtractReferences(std::map const& _subtrahend); Dialect const& m_dialect; bool m_allowMSizeOptimization = false; - std::map const* m_functionSideEffects = nullptr; + std::map const* m_functionSideEffects = nullptr; bool m_shouldRunAgain = false; - std::map m_references; + std::map m_references; }; } diff --git a/libyul/optimiser/UnusedStoreBase.h b/libyul/optimiser/UnusedStoreBase.h index 0d618d8d2..b6dde8c55 100644 --- a/libyul/optimiser/UnusedStoreBase.h +++ b/libyul/optimiser/UnusedStoreBase.h @@ -60,7 +60,7 @@ class UnusedStoreBase: public ASTWalker void operator()(Continue const&) override; protected: - using ActiveStores = std::map>; + using ActiveStores = std::map>; /// This function is called for a loop that is nested too deep to avoid /// horrible runtime and should just resolve the situation in a pragmatic diff --git a/libyul/optimiser/UnusedStoreEliminator.cpp b/libyul/optimiser/UnusedStoreEliminator.cpp index 6a0ab1518..d049f59a0 100644 --- a/libyul/optimiser/UnusedStoreEliminator.cpp +++ b/libyul/optimiser/UnusedStoreEliminator.cpp @@ -51,22 +51,22 @@ static std::string const thirtyTwo{"@ 32"}; void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) { - std::map functionSideEffects = SideEffectsPropagator::sideEffects( + std::map functionSideEffects = SideEffectsPropagator::sideEffects( _context.dialect, CallGraphGenerator::callGraph(_ast) ); SSAValueTracker ssaValues; ssaValues(_ast); - std::map values; + std::map values; for (auto const& [name, expression]: ssaValues.values()) values[name] = AssignedValue{expression, {}}; Expression const zeroLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{0}), {}}}; Expression const oneLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{1}), {}}}; Expression const thirtyTwoLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{32}), {}}}; - values[YulString{zero}] = AssignedValue{&zeroLiteral, {}}; - values[YulString{one}] = AssignedValue{&oneLiteral, {}}; - values[YulString{thirtyTwo}] = AssignedValue{&thirtyTwoLiteral, {}}; + values[YulName{zero}] = AssignedValue{&zeroLiteral, {}}; + values[YulName{one}] = AssignedValue{&oneLiteral, {}}; + values[YulName{thirtyTwo}] = AssignedValue{&thirtyTwoLiteral, {}}; bool const ignoreMemory = MSizeFinder::containsMSize(_context.dialect, _ast); UnusedStoreEliminator rse{ @@ -93,9 +93,9 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) UnusedStoreEliminator::UnusedStoreEliminator( Dialect const& _dialect, - std::map const& _functionSideEffects, - std::map _controlFlowSideEffects, - std::map const& _ssaValues, + std::map const& _functionSideEffects, + std::map _controlFlowSideEffects, + std::map const& _ssaValues, bool _ignoreMemory ): UnusedStoreBase(_dialect), @@ -228,7 +228,7 @@ std::vector UnusedStoreEliminator::operationsF { using evmasm::Instruction; - YulString functionName = _functionCall.functionName.name; + YulName functionName = _functionCall.functionName.name; SideEffects sideEffects; if (BuiltinFunction const* f = m_dialect.builtin(functionName)) sideEffects = f->sideEffects; @@ -263,8 +263,8 @@ std::vector UnusedStoreEliminator::operationsF if (_op.lengthConstant) switch (*_op.lengthConstant) { - case 1: ourOp.length = YulString(one); break; - case 32: ourOp.length = YulString(thirtyTwo); break; + case 1: ourOp.length = YulName(one); break; + case 32: ourOp.length = YulName(thirtyTwo); break; default: yulAssert(false); } return ourOp; @@ -435,7 +435,7 @@ void UnusedStoreEliminator::clearActive( activeStorageStores() = {}; } -std::optional UnusedStoreEliminator::identifierNameIfSSA(Expression const& _expression) const +std::optional UnusedStoreEliminator::identifierNameIfSSA(Expression const& _expression) const { if (Identifier const* identifier = std::get_if(&_expression)) if (m_ssaValues.count(identifier->name)) diff --git a/libyul/optimiser/UnusedStoreEliminator.h b/libyul/optimiser/UnusedStoreEliminator.h index 89dbabd78..98023b64c 100644 --- a/libyul/optimiser/UnusedStoreEliminator.h +++ b/libyul/optimiser/UnusedStoreEliminator.h @@ -64,9 +64,9 @@ class UnusedStoreEliminator: public UnusedStoreBase explicit UnusedStoreEliminator( Dialect const& _dialect, - std::map const& _functionSideEffects, - std::map _controlFlowSideEffects, - std::map const& _ssaValues, + std::map const& _functionSideEffects, + std::map _controlFlowSideEffects, + std::map const& _ssaValues, bool _ignoreMemory ); @@ -85,15 +85,15 @@ class UnusedStoreEliminator: public UnusedStoreBase Location location; Effect effect; /// Start of affected area. Unknown if not provided. - std::optional start; + std::optional start; /// Length of affected area, unknown if not provided. /// Unused for storage. - std::optional length; + std::optional length; }; private: - std::set& activeMemoryStores() { return m_activeStores["m"_yulstring]; } - std::set& activeStorageStores() { return m_activeStores["s"_yulstring]; } + std::set& activeMemoryStores() { return m_activeStores["m"_yulname]; } + std::set& activeStorageStores() { return m_activeStores["s"_yulname]; } void shortcutNestedLoop(ActiveStores const&) override { @@ -113,12 +113,12 @@ class UnusedStoreEliminator: public UnusedStoreBase void markActiveAsUsed(std::optional _onlyLocation = std::nullopt); void clearActive(std::optional _onlyLocation = std::nullopt); - std::optional identifierNameIfSSA(Expression const& _expression) const; + std::optional identifierNameIfSSA(Expression const& _expression) const; bool const m_ignoreMemory; - std::map const& m_functionSideEffects; - std::map m_controlFlowSideEffects; - std::map const& m_ssaValues; + std::map const& m_functionSideEffects; + std::map m_controlFlowSideEffects; + std::map const& m_ssaValues; std::map m_storeOperations; diff --git a/libyul/optimiser/VarNameCleaner.cpp b/libyul/optimiser/VarNameCleaner.cpp index b13dc8e6b..041ebdeaa 100644 --- a/libyul/optimiser/VarNameCleaner.cpp +++ b/libyul/optimiser/VarNameCleaner.cpp @@ -34,7 +34,7 @@ using namespace solidity::yul; VarNameCleaner::VarNameCleaner( Block const& _ast, Dialect const& _dialect, - std::set _namesToKeep + std::set _namesToKeep ): m_dialect{_dialect}, m_namesToKeep{std::move(_namesToKeep)}, @@ -51,9 +51,9 @@ void VarNameCleaner::operator()(FunctionDefinition& _funDef) yulAssert(!m_insideFunction, ""); m_insideFunction = true; - std::set globalUsedNames = std::move(m_usedNames); + std::set globalUsedNames = std::move(m_usedNames); m_usedNames = m_namesToKeep; - std::map globalTranslatedNames; + std::map globalTranslatedNames; swap(globalTranslatedNames, m_translatedNames); renameVariables(_funDef.parameters); @@ -93,7 +93,7 @@ void VarNameCleaner::operator()(Identifier& _identifier) _identifier.name = name->second; } -YulString VarNameCleaner::findCleanName(YulString const& _name) const +YulName VarNameCleaner::findCleanName(YulName const& _name) const { auto newName = stripSuffix(_name); if (!isUsedName(newName)) @@ -102,24 +102,24 @@ YulString VarNameCleaner::findCleanName(YulString const& _name) const // create new name with suffix (by finding a free identifier) for (size_t i = 1; i < std::numeric_limits::max(); ++i) { - YulString newNameSuffixed = YulString{newName.str() + "_" + std::to_string(i)}; + YulName newNameSuffixed = YulName{newName.str() + "_" + std::to_string(i)}; if (!isUsedName(newNameSuffixed)) return newNameSuffixed; } yulAssert(false, "Exhausted by attempting to find an available suffix."); } -bool VarNameCleaner::isUsedName(YulString const& _name) const +bool VarNameCleaner::isUsedName(YulName const& _name) const { return isRestrictedIdentifier(m_dialect, _name) || m_usedNames.count(_name); } -YulString VarNameCleaner::stripSuffix(YulString const& _name) const +YulName VarNameCleaner::stripSuffix(YulName const& _name) const { static std::regex const suffixRegex("(_+[0-9]+)+$"); std::smatch suffixMatch; if (regex_search(_name.str(), suffixMatch, suffixRegex)) - return {YulString{suffixMatch.prefix().str()}}; + return {YulName{suffixMatch.prefix().str()}}; return _name; } diff --git a/libyul/optimiser/VarNameCleaner.h b/libyul/optimiser/VarNameCleaner.h index 7823e5716..bfb6cfb53 100644 --- a/libyul/optimiser/VarNameCleaner.h +++ b/libyul/optimiser/VarNameCleaner.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -64,33 +64,33 @@ class VarNameCleaner: public ASTModifier VarNameCleaner( Block const& _ast, Dialect const& _dialect, - std::set _namesToKeep = {} + std::set _namesToKeep = {} ); /// Tries to rename a list of variables. void renameVariables(std::vector& _variables); /// @returns suffix-stripped name, if a suffix was detected, none otherwise. - YulString stripSuffix(YulString const& _name) const; + YulName stripSuffix(YulName const& _name) const; /// Looks out for a "clean name" the given @p name could be trimmed down to. /// @returns a trimmed down and "clean name" in case it found one, none otherwise. - YulString findCleanName(YulString const& name) const; + YulName findCleanName(YulName const& name) const; /// Tests whether a given name was already used within this pass /// or was set to be kept. - bool isUsedName(YulString const& _name) const; + bool isUsedName(YulName const& _name) const; Dialect const& m_dialect; /// These names will not be modified. - std::set m_namesToKeep; + std::set m_namesToKeep; /// Set of names that are in use. - std::set m_usedNames; + std::set m_usedNames; /// Maps old to new names. - std::map m_translatedNames; + std::map m_translatedNames; /// Whether the traverse is inside a function definition. /// Used to assert that a function definition cannot be inside another. diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index 6e44afccf..77274200b 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -75,7 +75,7 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con auto handleObject = [&](std::string const& _kind, Object const& _object) { m_obtainedResult += contractName + "(" + _kind + ") " + (findFunctionCalls( *_object.code, - "memoryguard"_yulstring + "memoryguard"_yulname ).empty() ? "false" : "true") + "\n"; }; handleObject("creation", *object); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index a57ec9807..f1bd0ea37 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -87,7 +87,7 @@ TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string if (!obj.code) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); - std::map functionSideEffects = SideEffectsPropagator::sideEffects( + std::map functionSideEffects = SideEffectsPropagator::sideEffects( EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), CallGraphGenerator::callGraph(*obj.code) ); diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index b1dd0e6d1..6a9d3e6da 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -49,7 +49,7 @@ class KnowledgeBaseTest BOOST_REQUIRE(m_object && errorList.empty() && m_object->code); NameDispenser dispenser(m_dialect, *m_object->code); - std::set reserved; + std::set reserved; OptimiserStepContext context{m_dialect, dispenser, reserved, 0}; CommonSubexpressionEliminator::run(context, *m_object->code); @@ -57,13 +57,13 @@ class KnowledgeBaseTest for (auto const& [name, expression]: m_ssaValues.values()) m_values[name].value = expression; - return KnowledgeBase([this](YulString _var) { return util::valueOrNullptr(m_values, _var); }); + return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }); } EVMDialect m_dialect{EVMVersion{}, true}; std::shared_ptr m_object; SSAValueTracker m_ssaValues; - std::map m_values; + std::map m_values; }; BOOST_FIXTURE_TEST_SUITE(KnowledgeBase, KnowledgeBaseTest) @@ -79,14 +79,14 @@ BOOST_AUTO_TEST_CASE(basic) let e := sub(a, b) })"); - BOOST_CHECK(!kb.knownToBeDifferent("a"_yulstring, "b"_yulstring)); + BOOST_CHECK(!kb.knownToBeDifferent("a"_yulname, "b"_yulname)); // This only works if the variable names are the same. // It assumes that SSA+CSE+Simplifier actually replaces the variables. - BOOST_CHECK(!kb.valueIfKnownConstant("a"_yulstring)); - BOOST_CHECK(kb.valueIfKnownConstant("zero"_yulstring) == u256(0)); - BOOST_CHECK(kb.differenceIfKnownConstant("a"_yulstring, "b"_yulstring) == u256(0)); - BOOST_CHECK(kb.differenceIfKnownConstant("a"_yulstring, "c"_yulstring) == u256(0)); - BOOST_CHECK(kb.valueIfKnownConstant("e"_yulstring) == u256(0)); + BOOST_CHECK(!kb.valueIfKnownConstant("a"_yulname)); + BOOST_CHECK(kb.valueIfKnownConstant("zero"_yulname) == u256(0)); + BOOST_CHECK(kb.differenceIfKnownConstant("a"_yulname, "b"_yulname) == u256(0)); + BOOST_CHECK(kb.differenceIfKnownConstant("a"_yulname, "c"_yulname) == u256(0)); + BOOST_CHECK(kb.valueIfKnownConstant("e"_yulname) == u256(0)); } BOOST_AUTO_TEST_CASE(difference) @@ -99,31 +99,21 @@ BOOST_AUTO_TEST_CASE(difference) let e := sub(c, 12) })"); - BOOST_CHECK( - kb.differenceIfKnownConstant("c"_yulstring, "b"_yulstring) == + BOOST_CHECK(kb.differenceIfKnownConstant("c"_yulname, "b"_yulname) == u256(20) ); - BOOST_CHECK( - kb.differenceIfKnownConstant("b"_yulstring, "c"_yulstring) == + BOOST_CHECK(kb.differenceIfKnownConstant("b"_yulname, "c"_yulname) == u256(-20) ); - BOOST_CHECK(!kb.knownToBeDifferentByAtLeast32("b"_yulstring, "c"_yulstring)); - BOOST_CHECK(kb.knownToBeDifferentByAtLeast32("b"_yulstring, "d"_yulstring)); - BOOST_CHECK(kb.knownToBeDifferentByAtLeast32("a"_yulstring, "b"_yulstring)); - BOOST_CHECK(kb.knownToBeDifferentByAtLeast32("b"_yulstring, "a"_yulstring)); - - BOOST_CHECK( - kb.differenceIfKnownConstant("e"_yulstring, "a"_yulstring) == u256(208) - ); - BOOST_CHECK( - kb.differenceIfKnownConstant("e"_yulstring, "b"_yulstring) == u256(8) - ); - BOOST_CHECK( - kb.differenceIfKnownConstant("a"_yulstring, "e"_yulstring) == u256(-208) - ); - BOOST_CHECK( - kb.differenceIfKnownConstant("b"_yulstring, "e"_yulstring) == u256(-8) - ); + BOOST_CHECK(!kb.knownToBeDifferentByAtLeast32("b"_yulname, "c"_yulname)); + BOOST_CHECK(kb.knownToBeDifferentByAtLeast32("b"_yulname, "d"_yulname)); + BOOST_CHECK(kb.knownToBeDifferentByAtLeast32("a"_yulname, "b"_yulname)); + BOOST_CHECK(kb.knownToBeDifferentByAtLeast32("b"_yulname, "a"_yulname)); + + BOOST_CHECK(kb.differenceIfKnownConstant("e"_yulname, "a"_yulname) == u256(208)); + BOOST_CHECK(kb.differenceIfKnownConstant("e"_yulname, "b"_yulname) == u256(8)); + BOOST_CHECK(kb.differenceIfKnownConstant("a"_yulname, "e"_yulname) == u256(-208)); + BOOST_CHECK(kb.differenceIfKnownConstant("b"_yulname, "e"_yulname) == u256(-8)); } diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index ca8784ddb..faa6c6105 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -135,11 +135,11 @@ BOOST_AUTO_TEST_CASE(builtins_analysis) { struct SimpleDialect: public Dialect { - BuiltinFunction const* builtin(YulString _name) const override + BuiltinFunction const* builtin(YulName _name) const override { - return _name == "builtin"_yulstring ? &f : nullptr; + return _name == "builtin"_yulname ? &f : nullptr; } - BuiltinFunction f{"builtin"_yulstring, std::vector(2), std::vector(3), {}, {}, false, {}}; + BuiltinFunction f{"builtin"_yulname, std::vector(2), std::vector(3), {}, {}, false, {}}; }; SimpleDialect dialect; diff --git a/test/libyul/StackShufflingTest.cpp b/test/libyul/StackShufflingTest.cpp index e53eeafbb..2da445dd4 100644 --- a/test/libyul/StackShufflingTest.cpp +++ b/test/libyul/StackShufflingTest.cpp @@ -56,7 +56,7 @@ bool StackShufflingTest::parse(std::string const& _source) scanner.next(); std::string functionName = scanner.currentLiteral(); auto call = yul::FunctionCall{ - {}, yul::Identifier{{}, YulString(functionName)}, {} + {}, yul::Identifier{{}, YulName(functionName)}, {} }; stack.emplace_back(FunctionCallReturnLabelSlot{ m_functions.insert( @@ -78,7 +78,7 @@ bool StackShufflingTest::parse(std::string const& _source) scanner.next(); std::string functionName = scanner.currentLiteral(); auto call = yul::FunctionCall{ - {}, yul::Identifier{{}, YulString(functionName)}, {} + {}, yul::Identifier{{}, YulName(functionName)}, {} }; expectToken(Token::Comma); scanner.next(); @@ -102,7 +102,7 @@ bool StackShufflingTest::parse(std::string const& _source) expectToken(Token::LBrack); scanner.next(); // read number of ghost variables as ghostVariableId std::string ghostVariableId = scanner.currentLiteral(); - Scope::Variable ghostVar = Scope::Variable{""_yulstring, YulString(literal + "[" + ghostVariableId + "]")}; + Scope::Variable ghostVar = Scope::Variable{""_yulname, YulName(literal + "[" + ghostVariableId + "]")}; stack.emplace_back(VariableSlot{ m_variables.insert(std::make_pair(ghostVar.name, ghostVar)).first->second }); @@ -110,7 +110,7 @@ bool StackShufflingTest::parse(std::string const& _source) } else { - Scope::Variable var = Scope::Variable{""_yulstring, YulString(literal)}; + Scope::Variable var = Scope::Variable{""_yulname, YulName(literal)}; stack.emplace_back(VariableSlot{ m_variables.insert( make_pair(literal, var) diff --git a/test/libyul/StackShufflingTest.h b/test/libyul/StackShufflingTest.h index 75715d25b..2e2dd12ad 100644 --- a/test/libyul/StackShufflingTest.h +++ b/test/libyul/StackShufflingTest.h @@ -41,7 +41,7 @@ class StackShufflingTest: public TestCase Stack m_sourceStack; Stack m_targetStack; - std::map m_functions; - std::map m_variables; + std::map m_functions; + std::map m_variables; }; } diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 091a9a0b6..80746c93b 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -89,7 +89,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( disambiguate(); NameDisplacer{ *m_nameDispenser, - {"illegal1"_yulstring, "illegal2"_yulstring, "illegal3"_yulstring, "illegal4"_yulstring, "illegal5"_yulstring} + {"illegal1"_yulname, "illegal2"_yulname, "illegal3"_yulname, "illegal4"_yulname, "illegal5"_yulname} }(*m_ast); }}, {"blockFlattener", [&]() { @@ -348,11 +348,11 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( // Mark all variables with a name starting with "$" for escalation to memory. struct FakeUnreachableGenerator: ASTWalker { - std::map> fakeUnreachables; + std::map> fakeUnreachables; using ASTWalker::operator(); void operator()(FunctionDefinition const& _function) override { - YulString originalFunctionName = m_currentFunction; + YulName originalFunctionName = m_currentFunction; m_currentFunction = _function.name; for (TypedName const& _argument: _function.parameters) visitVariableName(_argument.name); @@ -361,7 +361,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( ASTWalker::operator()(_function); m_currentFunction = originalFunctionName; } - void visitVariableName(YulString _var) + void visitVariableName(YulName _var) { if (!_var.empty() && _var.str().front() == '$') if (!util::contains(fakeUnreachables[m_currentFunction], _var)) @@ -378,7 +378,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( visitVariableName(_identifier.name); ASTWalker::operator()(_identifier); } - YulString m_currentFunction = YulString{}; + YulName m_currentFunction = YulName{}; }; FakeUnreachableGenerator fakeUnreachableGenerator; fakeUnreachableGenerator(*m_ast); diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h index 3dce998c5..0a5d63320 100644 --- a/test/libyul/YulOptimizerTestCommon.h +++ b/test/libyul/YulOptimizerTestCommon.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -63,7 +63,7 @@ class YulOptimizerTestCommon std::string m_optimizerStep; Dialect const* m_dialect = nullptr; - std::set m_reservedIdentifiers; + std::set m_reservedIdentifiers; std::unique_ptr m_nameDispenser; std::unique_ptr m_context; diff --git a/test/tools/yulInterpreter/Inspector.h b/test/tools/yulInterpreter/Inspector.h index f4518c708..903ebc114 100644 --- a/test/tools/yulInterpreter/Inspector.h +++ b/test/tools/yulInterpreter/Inspector.h @@ -53,13 +53,13 @@ class Inspector * @returns NodeAction::RunNode if the current AST node (and all children nodes!) should be * processed without stopping, else NodeAction::StepThroughNode. */ - NodeAction queryUser(langutil::DebugData const& _data, std::map const& _variables); + NodeAction queryUser(langutil::DebugData const& _data, std::map const& _variables); void stepMode(NodeAction _action) { m_stepMode = _action; } std::string const& source() const { return m_source; } - void interactiveVisit(langutil::DebugData const& _debugData, std::map const& _variables, std::function _visitNode) + void interactiveVisit(langutil::DebugData const& _debugData, std::map const& _variables, std::function _visitNode) { Inspector::NodeAction action = queryUser(_debugData, _variables); @@ -116,7 +116,7 @@ class InspectedInterpreter: public Interpreter Scope& _scope, bool _disableExternalCalls, bool _disableMemoryTracing, - std::map _variables = {} + std::map _variables = {} ): Interpreter(_state, _dialect, _scope, _disableExternalCalls, _disableMemoryTracing, _variables), m_inspector(_inspector) @@ -160,7 +160,7 @@ class InspectedExpressionEvaluator: public ExpressionEvaluator InterpreterState& _state, Dialect const& _dialect, Scope& _scope, - std::map const& _variables, + std::map const& _variables, bool _disableExternalCalls, bool _disableMemoryTrace ): @@ -180,7 +180,7 @@ class InspectedExpressionEvaluator: public ExpressionEvaluator void operator()(Identifier const& _node) override { helper(_node); } void operator()(FunctionCall const& _node) override { helper(_node); } protected: - std::unique_ptr makeInterpreterCopy(std::map _variables = {}) const override + std::unique_ptr makeInterpreterCopy(std::map _variables = {}) const override { return std::make_unique( m_inspector, diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index 6a0f3a999..21e97f076 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -131,7 +131,7 @@ void Interpreter::operator()(Assignment const& _assignment) solAssert(values.size() == _assignment.variableNames.size(), ""); for (size_t i = 0; i < values.size(); ++i) { - YulString varName = _assignment.variableNames.at(i).name; + YulName varName = _assignment.variableNames.at(i).name; solAssert(m_variables.count(varName), ""); m_variables[varName] = values.at(i); } @@ -146,7 +146,7 @@ void Interpreter::operator()(VariableDeclaration const& _declaration) solAssert(values.size() == _declaration.variables.size(), ""); for (size_t i = 0; i < values.size(); ++i) { - YulString varName = _declaration.variables.at(i).name; + YulName varName = _declaration.variables.at(i).name; solAssert(!m_variables.count(varName), ""); m_variables[varName] = values.at(i); m_scope->names.emplace(varName, nullptr); @@ -343,7 +343,7 @@ void ExpressionEvaluator::operator()(FunctionCall const& _funCall) FunctionDefinition const* fun = scope->names.at(_funCall.functionName.name); yulAssert(fun, "Function not found."); yulAssert(m_values.size() == fun->parameters.size(), ""); - std::map variables; + std::map variables; for (size_t i = 0; i < fun->parameters.size(); ++i) variables[fun->parameters.at(i).name] = m_values.at(i); for (size_t i = 0; i < fun->returnVariables.size(); ++i) diff --git a/test/tools/yulInterpreter/Interpreter.h b/test/tools/yulInterpreter/Interpreter.h index 23a98ca5c..356a19070 100644 --- a/test/tools/yulInterpreter/Interpreter.h +++ b/test/tools/yulInterpreter/Interpreter.h @@ -145,7 +145,7 @@ struct InterpreterState struct Scope { /// Used for variables and functions. Value is nullptr for variables. - std::map names; + std::map names; std::map> subScopes; Scope* parent = nullptr; }; @@ -174,7 +174,7 @@ class Interpreter: public ASTWalker Scope& _scope, bool _disableExternalCalls, bool _disableMemoryTracing, - std::map _variables = {} + std::map _variables = {} ): m_dialect(_dialect), m_state(_state), @@ -200,7 +200,7 @@ class Interpreter: public ASTWalker bytes returnData() const { return m_state.returndata; } std::vector const& trace() const { return m_state.trace; } - u256 valueOfVariable(YulString _name) const { return m_variables.at(_name); } + u256 valueOfVariable(YulName _name) const { return m_variables.at(_name); } protected: /// Asserts that the expression evaluates to exactly one value and returns it. @@ -218,7 +218,7 @@ class Interpreter: public ASTWalker Dialect const& m_dialect; InterpreterState& m_state; /// Values of variables. - std::map m_variables; + std::map m_variables; Scope* m_scope; /// If not set, external calls (e.g. using `call()`) to the same contract /// are evaluated in a new parser instance. @@ -236,7 +236,7 @@ class ExpressionEvaluator: public ASTWalker InterpreterState& _state, Dialect const& _dialect, Scope& _scope, - std::map const& _variables, + std::map const& _variables, bool _disableExternalCalls, bool _disableMemoryTrace ): @@ -259,7 +259,7 @@ class ExpressionEvaluator: public ASTWalker protected: void runExternalCall(evmasm::Instruction _instruction); - virtual std::unique_ptr makeInterpreterCopy(std::map _variables = {}) const + virtual std::unique_ptr makeInterpreterCopy(std::map _variables = {}) const { return std::make_unique( m_state, @@ -298,7 +298,7 @@ class ExpressionEvaluator: public ASTWalker InterpreterState& m_state; Dialect const& m_dialect; /// Values of variables. - std::map const& m_variables; + std::map const& m_variables; Scope& m_scope; /// Current value of the expression std::vector m_values; diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index d16b1da19..7e81cbf7e 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -245,7 +245,7 @@ class YulOpti std::shared_ptr m_ast; Dialect const& m_dialect{EVMDialect::strictAssemblyForEVMObjects(EVMVersion{})}; std::unique_ptr m_analysisInfo; - std::set const m_reservedIdentifiers = {}; + std::set const m_reservedIdentifiers = {}; NameDispenser m_nameDispenser{m_dialect, m_reservedIdentifiers}; OptimiserStepContext m_context{ m_dialect, diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 1586f6020..0cb22242d 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -175,7 +175,7 @@ std::unique_ptr Program::disambiguateAST( AsmAnalysisInfo const& _analysisInfo ) { - std::set const externallyUsedIdentifiers = {}; + std::set const externallyUsedIdentifiers = {}; Disambiguator disambiguator(_dialect, _analysisInfo, externallyUsedIdentifiers); return std::make_unique(std::get(disambiguator(_ast))); @@ -190,7 +190,7 @@ std::unique_ptr Program::applyOptimisationSteps( { // An empty set of reserved identifiers. It could be a constructor parameter but I don't // think it would be useful in this tool. Other tools (like yulopti) have it empty too. - std::set const externallyUsedIdentifiers = {}; + std::set const externallyUsedIdentifiers = {}; OptimiserStepContext context{ _dialect, _nameDispenser, From b508a63e4a6f10d3f7bb578e9ab7f0fcbb5dd219 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 19 Jul 2024 15:52:20 -0300 Subject: [PATCH 0216/1340] Fix docs on outputSelection --- docs/using-the-compiler.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 1eb6631df..39da067f3 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -404,7 +404,8 @@ Input Description // but to the whole source file like the AST. // A star as contract name refers to all contracts in the file. // Similarly, a star as a file name matches all files. - // To select all outputs the compiler can possibly generate, use + // To select all outputs the compiler can possibly generate, with the exclusion of + // Yul intermediate representation outputs, use // "outputSelection: { "*": { "*": [ "*" ], "": [ "*" ] } }" // but note that this might slow down the compilation process needlessly. // From 535203b58f844335378f0b9567f7abedbd72f904 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 19 Jul 2024 17:27:32 +0200 Subject: [PATCH 0217/1340] Use latest node cimg --- .circleci/config.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 20f57b413..d6c3f33da 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -487,8 +487,7 @@ defaults: - base_node_small: &base_node_small docker: - # TODO: Revert to cimg/node:current once https://github.com/npm/cli/issues/7657 is resolved. - - image: cimg/node:22.4 + - image: cimg/node:current resource_class: small environment: &base_node_small_env TERM: xterm @@ -762,7 +761,6 @@ defaults: # which does not support shanghai EVM. compile_only: 1 resource_class: medium - image: cimg/node:18.16 - job_native_test_ext_yield_liquidator: &job_native_test_ext_yield_liquidator <<: *requires_b_ubu_static From d0cabf490c97906757d8c8263cdd206fdf5f1547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaan=20Uzdo=C4=9Fan?= Date: Mon, 22 Jul 2024 11:56:25 +0200 Subject: [PATCH 0218/1340] Docs: Add note about the library placeholder format change in v0.5.0 The library placeholder string format has changed on v0.5.0. Someone reading the docs would be unaware of this and can assume the format remained the same. This can be important e.g. verifying contracts pre 0.5.0 or working on the bytecode --- docs/contracts/libraries.rst | 2 +- docs/using-the-compiler.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contracts/libraries.rst b/docs/contracts/libraries.rst index 7256ebe03..1c6d837c7 100644 --- a/docs/contracts/libraries.rst +++ b/docs/contracts/libraries.rst @@ -196,7 +196,7 @@ It is possible to obtain the address of a library by converting the library type to the ``address`` type, i.e. using ``address(LibraryName)``. As the compiler does not know the address where the library will be deployed, the compiled hex code -will contain placeholders of the form ``__$30bbc0abd4d6364515865950d3e0d10953$__``. The placeholder +will contain placeholders of the form ``__$30bbc0abd4d6364515865950d3e0d10953$__`` `(format was different `_. The placeholder is a 34 character prefix of the hex encoding of the keccak256 hash of the fully qualified library name, which would be for example ``libraries/bigint.sol:BigInt`` if the library was stored in a file called ``bigint.sol`` in a ``libraries/`` directory. Such bytecode is incomplete and should not be diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 39da067f3..c84d6a838 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -71,7 +71,7 @@ For a detailed explanation with examples and discussion of corner cases please r Library Linking --------------- -If your contracts use :ref:`libraries `, you will notice that the bytecode contains substrings of the form ``__$53aea86b7d70b31448b230b20ae141a537$__``. These are placeholders for the actual library addresses. +If your contracts use :ref:`libraries `, you will notice that the bytecode contains substrings of the form ``__$53aea86b7d70b31448b230b20ae141a537$__`` `(format was different `_. These are placeholders for the actual library addresses. The placeholder is a 34 character prefix of the hex encoding of the keccak256 hash of the fully qualified library name. The bytecode file will also contain lines of the form ``// -> `` at the end to help identify which libraries the placeholders represent. Note that the fully qualified library name From 1cbb3220de39f589885faf9e734e743f3b2f8857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaan=20Uzdo=C4=9Fan?= Date: Mon, 22 Jul 2024 12:03:48 +0200 Subject: [PATCH 0219/1340] Change link to libraries page --- docs/contracts/libraries.rst | 2 +- docs/using-the-compiler.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contracts/libraries.rst b/docs/contracts/libraries.rst index 1c6d837c7..a3c04ba06 100644 --- a/docs/contracts/libraries.rst +++ b/docs/contracts/libraries.rst @@ -196,7 +196,7 @@ It is possible to obtain the address of a library by converting the library type to the ``address`` type, i.e. using ``address(LibraryName)``. As the compiler does not know the address where the library will be deployed, the compiled hex code -will contain placeholders of the form ``__$30bbc0abd4d6364515865950d3e0d10953$__`` `(format was different `_. The placeholder +will contain placeholders of the form ``__$30bbc0abd4d6364515865950d3e0d10953$__`` `(format was different `_. The placeholder is a 34 character prefix of the hex encoding of the keccak256 hash of the fully qualified library name, which would be for example ``libraries/bigint.sol:BigInt`` if the library was stored in a file called ``bigint.sol`` in a ``libraries/`` directory. Such bytecode is incomplete and should not be diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index c84d6a838..a306fa835 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -71,7 +71,7 @@ For a detailed explanation with examples and discussion of corner cases please r Library Linking --------------- -If your contracts use :ref:`libraries `, you will notice that the bytecode contains substrings of the form ``__$53aea86b7d70b31448b230b20ae141a537$__`` `(format was different `_. These are placeholders for the actual library addresses. +If your contracts use :ref:`libraries `, you will notice that the bytecode contains substrings of the form ``__$53aea86b7d70b31448b230b20ae141a537$__`` `(format was different `_. These are placeholders for the actual library addresses. The placeholder is a 34 character prefix of the hex encoding of the keccak256 hash of the fully qualified library name. The bytecode file will also contain lines of the form ``// -> `` at the end to help identify which libraries the placeholders represent. Note that the fully qualified library name From 755201202e3dfb4aca57780b55f8e6ce06663e91 Mon Sep 17 00:00:00 2001 From: dxo Date: Mon, 22 Jul 2024 20:50:00 +0200 Subject: [PATCH 0220/1340] docs/yul: pc is dissalowed in solc yul pc was removed from solc assembly in 0.7.0 (it introduced an unwelcome semantic dependency on code location). --- docs/yul.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/yul.rst b/docs/yul.rst index 3cf2785fc..58cfc992f 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -820,8 +820,6 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a +-------------------------+-----+---+-----------------------------------------------------------------+ | keccak256(p, n) | | F | keccak(mem[p...(p+n))) | +-------------------------+-----+---+-----------------------------------------------------------------+ -| pc() | | F | current position in code | -+-------------------------+-----+---+-----------------------------------------------------------------+ | pop(x) | `-` | F | discard value x | +-------------------------+-----+---+-----------------------------------------------------------------+ | mload(p) | | F | mem[p...(p+32)) | From cccbc122204ed230441ad991fcfd5855caec987f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 28 May 2024 15:06:46 +0200 Subject: [PATCH 0221/1340] Updated some outdated docs and TODOs related to the optimizer outputs --- libsolidity/interface/CompilerStack.h | 9 ++++++--- solc/CommandLineInterface.cpp | 1 - 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 672067d81..6ad868ad0 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -387,8 +387,8 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac std::shared_ptr evmRuntimeAssembly; evmasm::LinkerObject object; ///< Deployment object (includes the runtime sub-object). evmasm::LinkerObject runtimeObject; ///< Runtime object. - std::string yulIR; ///< Yul IR code. - std::string yulIROptimized; ///< Optimized Yul IR code. + std::string yulIR; ///< Yul IR code straight from the code generator. + std::string yulIROptimized; ///< Reparsed and possibly optimized Yul IR code. Json yulIRAst; ///< JSON AST of Yul IR code. Json yulIROptimizedAst; ///< JSON AST of optimized Yul IR code. util::LazyInit metadata; ///< The metadata json that will be hashed into the chain. @@ -449,7 +449,10 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac ); /// Generate Yul IR for a single contract. - /// The IR is stored but otherwise unused. + /// Unoptimized IR is stored but otherwise unused, while optimized IR may be used for code + /// generation if compilation via IR is enabled. Note that whether "optimized IR" is actually + /// optimized depends on the optimizer settings. + /// @param _contract Contract to generate IR for. void generateIR(ContractDefinition const& _contract); /// Generate EVM representation for a single contract. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 367434c93..e2d1e2701 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -849,7 +849,6 @@ void CommandLineInterface::compile() m_compiler->setRevertStringBehaviour(m_options.output.revertStrings); if (m_options.output.debugInfoSelection.has_value()) m_compiler->selectDebugInfo(m_options.output.debugInfoSelection.value()); - // TODO: Perhaps we should not compile unless requested m_compiler->enableIRGeneration( m_options.compiler.outputs.ir || m_options.compiler.outputs.irOptimized || From 1a60d1860d9f75b5d115887548fdec0dfc23a70d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 29 May 2024 21:25:28 +0200 Subject: [PATCH 0222/1340] Do not perform IR optimization if only unoptimized IR is requested --- Changelog.md | 2 + libsolidity/interface/CompilerStack.cpp | 28 ++++++-- libsolidity/interface/CompilerStack.h | 23 ++++-- libsolidity/interface/StandardCompiler.cpp | 27 +++---- solc/CommandLineInterface.cpp | 14 ++-- .../ir_optimized_with_optimize/args | 1 + .../ir_optimized_with_optimize/input.sol | 4 ++ .../ir_optimized_with_optimize/output | 19 +++++ .../ir_unoptimized_with_optimize/args | 1 + .../ir_unoptimized_with_optimize/input.sol | 4 ++ .../ir_unoptimized_with_optimize/output | 58 +++++++++++++++ .../ir_unoptimized_with_optimize_via_ir/args | 1 + .../input.sol | 4 ++ .../output | 58 +++++++++++++++ .../input.json | 11 +++ .../output.json | 72 +++++++++++++++++++ .../input.json | 12 ++++ .../output.json | 72 +++++++++++++++++++ 18 files changed, 381 insertions(+), 30 deletions(-) create mode 100644 test/cmdlineTests/ir_optimized_with_optimize/args create mode 100644 test/cmdlineTests/ir_optimized_with_optimize/input.sol create mode 100644 test/cmdlineTests/ir_optimized_with_optimize/output create mode 100644 test/cmdlineTests/ir_unoptimized_with_optimize/args create mode 100644 test/cmdlineTests/ir_unoptimized_with_optimize/input.sol create mode 100644 test/cmdlineTests/ir_unoptimized_with_optimize/output create mode 100644 test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/args create mode 100644 test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/input.sol create mode 100644 test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/output create mode 100644 test/cmdlineTests/standard_ir_unoptimized_with_optimize/input.json create mode 100644 test/cmdlineTests/standard_ir_unoptimized_with_optimize/output.json create mode 100644 test/cmdlineTests/standard_ir_unoptimized_with_optimize_via_ir/input.json create mode 100644 test/cmdlineTests/standard_ir_unoptimized_with_optimize_via_ir/output.json diff --git a/Changelog.md b/Changelog.md index 7a5adcc4b..e67cf0f07 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,10 +7,12 @@ Language Features: Compiler Features: + * Command Line Interface: Do not perform IR optimization when only unoptimized IR is requested. * Error Reporting: Unimplemented features are now properly reported as errors instead of being handled as if they were bugs. * EVM: Support for the EVM version "Prague". * SMTChecker: Add CHC engine check for underflow and overflow in unary minus operation. * SMTChecker: Replace CVC4 as a possible BMC backend with cvc5. + * Standard JSON Interface: Do not perform IR optimization when only unoptimized IR is requested. * Yul Optimizer: The optimizer now treats some previously unrecognized identical literals as identical. diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 566feb21b..f2c37fa68 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -313,7 +313,7 @@ void CompilerStack::reset(bool _keepSettings) m_viaIR = false; m_evmVersion = langutil::EVMVersion(); m_modelCheckerSettings = ModelCheckerSettings{}; - m_generateIR = false; + m_irOutputSelection = IROutputSelection::None; m_revertStrings = RevertStrings::Default; m_optimiserSettings = OptimiserSettings::minimal(); m_metadataLiteralSources = false; @@ -728,8 +728,17 @@ bool CompilerStack::compile(State _stopAfter) { try { - if ((m_generateEvmBytecode && m_viaIR) || m_generateIR) - generateIR(*contract); + // NOTE: Bytecode generation via IR always uses Contract::yulIROptimized. + // When optimization is not enabled, that member simply contains unoptimized code. + bool needIROutput = + (m_generateEvmBytecode && m_viaIR) || + m_irOutputSelection != IROutputSelection::None; + bool needUnoptimizedIROutputOnly = + !(m_generateEvmBytecode && m_viaIR) && + m_irOutputSelection != IROutputSelection::UnoptimizedAndOptimized; + + if (needIROutput) + generateIR(*contract, needUnoptimizedIROutputOnly); if (m_generateEvmBytecode) { if (m_viaIR) @@ -1402,7 +1411,7 @@ void CompilerStack::compileContract( assembleYul(_contract, compiler->assemblyPtr(), compiler->runtimeAssemblyPtr()); } -void CompilerStack::generateIR(ContractDefinition const& _contract) +void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unoptimizedOnly) { solAssert(m_stackState >= AnalysisSuccessful, ""); @@ -1420,7 +1429,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract) std::string dependenciesSource; for (auto const& [dependency, referencee]: _contract.annotation().contractDependencies) - generateIR(*dependency); + generateIR(*dependency, _unoptimizedOnly); if (!_contract.canBeDeployed()) return; @@ -1485,9 +1494,14 @@ void CompilerStack::generateIR(ContractDefinition const& _contract) { YulStack stack = parseYul(compiledContract.yulIR); compiledContract.yulIRAst = stack.astJson(); - stack.optimize(); - compiledContract.yulIROptimized = stack.print(this); + if (!_unoptimizedOnly) + { + stack.optimize(); + compiledContract.yulIROptimized = stack.print(this); + } } + + if (!_unoptimizedOnly) { // Optimizer does not maintain correct native source locations in the AST. // We can work around it by regenerating the AST from scratch from optimized IR. diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 6ad868ad0..2c5ecb132 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -126,6 +126,12 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac SolidityAST, }; + enum class IROutputSelection { + None, + UnoptimizedOnly, + UnoptimizedAndOptimized, + }; + /// Creates a new compiler stack. /// @param _readFile callback used to read files for import statements. Must return /// and must not emit exceptions. @@ -192,8 +198,14 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// Enable EVM Bytecode generation. This is enabled by default. void enableEvmBytecodeGeneration(bool _enable = true) { m_generateEvmBytecode = _enable; } - /// Enable generation of Yul IR code. - void enableIRGeneration(bool _enable = true) { m_generateIR = _enable; } + /// Enable generation of Yul IR code so that IR output can be safely requested for all contracts. + /// Note that IR may also be implicitly generated when not requested. In particular + /// @a setViaIR(true) requires access to the IR outputs for bytecode generation. + void requestIROutputs(IROutputSelection _selection = IROutputSelection::UnoptimizedAndOptimized) + { + solAssert(m_stackState < ParsedAndImported); + m_irOutputSelection = _selection; + } /// @arg _metadataLiteralSources When true, store sources as literals in the contract metadata. /// Must be set before parsing. @@ -453,7 +465,10 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// generation if compilation via IR is enabled. Note that whether "optimized IR" is actually /// optimized depends on the optimizer settings. /// @param _contract Contract to generate IR for. - void generateIR(ContractDefinition const& _contract); + /// @param _unoptimizedOnly If true, only the IR coming directly from the codegen is stored. + /// Optimizer is not invoked and optimized IR output is not available, which means that + /// optimized IR, its AST or compilation via IR must not be requested. + void generateIR(ContractDefinition const& _contract, bool _unoptimizedOnly); /// Generate EVM representation for a single contract. /// Depends on output generated by generateIR. @@ -518,7 +533,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac ModelCheckerSettings m_modelCheckerSettings; std::map> m_requestedContractNames; bool m_generateEvmBytecode = true; - bool m_generateIR = false; + IROutputSelection m_irOutputSelection = IROutputSelection::None; std::map m_libraries; ImportRemapper m_importRemapper; std::map m_sources; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index b908ab0cc..cb0c81268 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -295,25 +295,26 @@ bool isEvmBytecodeRequested(Json const& _outputSelection) return false; } -/// @returns true if any Yul IR was requested. Note that as an exception, '*' does not -/// yet match "ir", "irAst", "irOptimized" or "irOptimizedAst" -bool isIRRequested(Json const& _outputSelection) +/// @returns The IR output selection for CompilerStack, based on outputs requested in the JSON. +/// Note that as an exception, '*' does not yet match "ir", "irAst", "irOptimized" or "irOptimizedAst". +CompilerStack::IROutputSelection irOutputSelection(Json const& _outputSelection) { if (!_outputSelection.is_object()) - return false; + return CompilerStack::IROutputSelection::None; + CompilerStack::IROutputSelection selection = CompilerStack::IROutputSelection::None; for (auto const& fileRequests: _outputSelection) for (auto const& requests: fileRequests) for (auto const& request: requests) - if ( - request == "ir" || - request == "irAst" || - request == "irOptimized" || - request == "irOptimizedAst" - ) - return true; + { + if (request == "irOptimized" || request == "irOptimizedAst") + return CompilerStack::IROutputSelection::UnoptimizedAndOptimized; - return false; + if (request == "ir" || request == "irAst") + selection = CompilerStack::IROutputSelection::UnoptimizedOnly; + } + + return selection; } Json formatLinkReferences(std::map const& linkReferences) @@ -1320,7 +1321,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu compilerStack.setModelCheckerSettings(_inputsAndSettings.modelCheckerSettings); compilerStack.enableEvmBytecodeGeneration(isEvmBytecodeRequested(_inputsAndSettings.outputSelection)); - compilerStack.enableIRGeneration(isIRRequested(_inputsAndSettings.outputSelection)); + compilerStack.requestIROutputs(irOutputSelection(_inputsAndSettings.outputSelection)); Json errors = std::move(_inputsAndSettings.errors); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index e2d1e2701..5d0272dfa 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -849,12 +849,14 @@ void CommandLineInterface::compile() m_compiler->setRevertStringBehaviour(m_options.output.revertStrings); if (m_options.output.debugInfoSelection.has_value()) m_compiler->selectDebugInfo(m_options.output.debugInfoSelection.value()); - m_compiler->enableIRGeneration( - m_options.compiler.outputs.ir || - m_options.compiler.outputs.irOptimized || - m_options.compiler.outputs.irAstJson || - m_options.compiler.outputs.irOptimizedAstJson - ); + + CompilerStack::IROutputSelection irOutputSelection = CompilerStack::IROutputSelection::None; + if (m_options.compiler.outputs.irOptimized || m_options.compiler.outputs.irOptimizedAstJson) + irOutputSelection = CompilerStack::IROutputSelection::UnoptimizedAndOptimized; + else if (m_options.compiler.outputs.ir || m_options.compiler.outputs.irAstJson) + irOutputSelection = CompilerStack::IROutputSelection::UnoptimizedOnly; + + m_compiler->requestIROutputs(irOutputSelection); m_compiler->enableEvmBytecodeGeneration( m_options.compiler.estimateGas || m_options.compiler.outputs.asm_ || diff --git a/test/cmdlineTests/ir_optimized_with_optimize/args b/test/cmdlineTests/ir_optimized_with_optimize/args new file mode 100644 index 000000000..a536442c5 --- /dev/null +++ b/test/cmdlineTests/ir_optimized_with_optimize/args @@ -0,0 +1 @@ +--ir-optimized --optimize --debug-info none diff --git a/test/cmdlineTests/ir_optimized_with_optimize/input.sol b/test/cmdlineTests/ir_optimized_with_optimize/input.sol new file mode 100644 index 000000000..a3a86cc8d --- /dev/null +++ b/test/cmdlineTests/ir_optimized_with_optimize/input.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +contract C {} diff --git a/test/cmdlineTests/ir_optimized_with_optimize/output b/test/cmdlineTests/ir_optimized_with_optimize/output new file mode 100644 index 000000000..8790e45d3 --- /dev/null +++ b/test/cmdlineTests/ir_optimized_with_optimize/output @@ -0,0 +1,19 @@ +Optimized IR: +/// @use-src 0:"ir_optimized_with_optimize/input.sol" +object "C_2" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_2_deployed") + codecopy(_1, dataoffset("C_2_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"ir_optimized_with_optimize/input.sol" + object "C_2_deployed" { + code { { revert(0, 0) } } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/ir_unoptimized_with_optimize/args b/test/cmdlineTests/ir_unoptimized_with_optimize/args new file mode 100644 index 000000000..cdfef4650 --- /dev/null +++ b/test/cmdlineTests/ir_unoptimized_with_optimize/args @@ -0,0 +1 @@ +--ir --optimize --debug-info none diff --git a/test/cmdlineTests/ir_unoptimized_with_optimize/input.sol b/test/cmdlineTests/ir_unoptimized_with_optimize/input.sol new file mode 100644 index 000000000..a3a86cc8d --- /dev/null +++ b/test/cmdlineTests/ir_unoptimized_with_optimize/input.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +contract C {} diff --git a/test/cmdlineTests/ir_unoptimized_with_optimize/output b/test/cmdlineTests/ir_unoptimized_with_optimize/output new file mode 100644 index 000000000..c5307123f --- /dev/null +++ b/test/cmdlineTests/ir_unoptimized_with_optimize/output @@ -0,0 +1,58 @@ +IR: + +/// @use-src 0:"ir_unoptimized_with_optimize/input.sol" +object "C_2" { + code { + + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_2() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_2_deployed"), datasize("C_2_deployed")) + + return(_1, datasize("C_2_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_2() { + + } + + } + /// @use-src 0:"ir_unoptimized_with_optimize/input.sol" + object "C_2_deployed" { + code { + + mstore(64, memoryguard(128)) + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + } + + data ".metadata" hex"" + } + +} diff --git a/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/args b/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/args new file mode 100644 index 000000000..c8c9fa85e --- /dev/null +++ b/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/args @@ -0,0 +1 @@ +--ir --optimize --via-ir --debug-info none diff --git a/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/input.sol b/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/input.sol new file mode 100644 index 000000000..a3a86cc8d --- /dev/null +++ b/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/input.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +contract C {} diff --git a/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/output b/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/output new file mode 100644 index 000000000..f5ecdd8bf --- /dev/null +++ b/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/output @@ -0,0 +1,58 @@ +IR: + +/// @use-src 0:"ir_unoptimized_with_optimize_via_ir/input.sol" +object "C_2" { + code { + + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_2() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_2_deployed"), datasize("C_2_deployed")) + + return(_1, datasize("C_2_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_2() { + + } + + } + /// @use-src 0:"ir_unoptimized_with_optimize_via_ir/input.sol" + object "C_2_deployed" { + code { + + mstore(64, memoryguard(128)) + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + } + + data ".metadata" hex"" + } + +} diff --git a/test/cmdlineTests/standard_ir_unoptimized_with_optimize/input.json b/test/cmdlineTests/standard_ir_unoptimized_with_optimize/input.json new file mode 100644 index 000000000..d12265a38 --- /dev/null +++ b/test/cmdlineTests/standard_ir_unoptimized_with_optimize/input.json @@ -0,0 +1,11 @@ +{ + "language": "Solidity", + "sources": { + "C.sol": {"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity *; contract C {}"} + }, + "settings": { + "outputSelection": {"*": {"*": ["ir"]}}, + "optimizer": {"enabled": true}, + "debug": {"debugInfo": []} + } +} diff --git a/test/cmdlineTests/standard_ir_unoptimized_with_optimize/output.json b/test/cmdlineTests/standard_ir_unoptimized_with_optimize/output.json new file mode 100644 index 000000000..d19723126 --- /dev/null +++ b/test/cmdlineTests/standard_ir_unoptimized_with_optimize/output.json @@ -0,0 +1,72 @@ +{ + "contracts": { + "C.sol": { + "C": { + "ir": " +/// @use-src 0:\"C.sol\" +object \"C_2\" { + code { + + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_2() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"C_2_deployed\"), datasize(\"C_2_deployed\")) + + return(_1, datasize(\"C_2_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_2() { + + } + + } + /// @use-src 0:\"C.sol\" + object \"C_2_deployed\" { + code { + + mstore(64, memoryguard(128)) + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + } + }, + "sources": { + "C.sol": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_ir_unoptimized_with_optimize_via_ir/input.json b/test/cmdlineTests/standard_ir_unoptimized_with_optimize_via_ir/input.json new file mode 100644 index 000000000..06b89d0e0 --- /dev/null +++ b/test/cmdlineTests/standard_ir_unoptimized_with_optimize_via_ir/input.json @@ -0,0 +1,12 @@ +{ + "language": "Solidity", + "sources": { + "C.sol": {"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity *; contract C {}"} + }, + "settings": { + "outputSelection": {"*": {"*": ["ir"]}}, + "optimizer": {"enabled": true}, + "viaIR": true, + "debug": {"debugInfo": []} + } +} diff --git a/test/cmdlineTests/standard_ir_unoptimized_with_optimize_via_ir/output.json b/test/cmdlineTests/standard_ir_unoptimized_with_optimize_via_ir/output.json new file mode 100644 index 000000000..d19723126 --- /dev/null +++ b/test/cmdlineTests/standard_ir_unoptimized_with_optimize_via_ir/output.json @@ -0,0 +1,72 @@ +{ + "contracts": { + "C.sol": { + "C": { + "ir": " +/// @use-src 0:\"C.sol\" +object \"C_2\" { + code { + + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_2() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"C_2_deployed\"), datasize(\"C_2_deployed\")) + + return(_1, datasize(\"C_2_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_2() { + + } + + } + /// @use-src 0:\"C.sol\" + object \"C_2_deployed\" { + code { + + mstore(64, memoryguard(128)) + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + } + }, + "sources": { + "C.sol": { + "id": 0 + } + } +} From f89e83bbb091be506105f17eb7caf6ec1f63ec51 Mon Sep 17 00:00:00 2001 From: clonker Date: Fri, 12 Jul 2024 10:13:04 +0200 Subject: [PATCH 0223/1340] yul: AsmPrinter has mode enum to determine printing mode instead of dialect pointer --- libsolidity/codegen/CompilerContext.cpp | 4 ++-- .../codegen/ir/IRGeneratorForStatements.cpp | 3 +-- .../codegen/IRGeneratorForStatements.cpp | 2 +- libyul/AsmPrinter.cpp | 10 +++++++--- libyul/AsmPrinter.h | 20 ++++++++++--------- libyul/Object.cpp | 8 +++++--- libyul/Object.h | 10 +++++++--- libyul/YulStack.cpp | 7 ++++++- libyul/optimiser/Suite.cpp | 2 +- test/libyul/Common.cpp | 4 +++- test/libyul/Parser.cpp | 10 ++++------ test/libyul/YulOptimizerTest.cpp | 2 +- test/tools/yulopti.cpp | 4 ++-- tools/yulPhaser/Program.cpp | 2 +- 14 files changed, 52 insertions(+), 36 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 4d522072a..962defdbc 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -491,8 +491,8 @@ void CompilerContext::appendInlineAssembly( { // Store as generated sources, but first re-parse to update the source references. solAssert(m_generatedYulUtilityCode.empty(), ""); - m_generatedYulUtilityCode = yul::AsmPrinter(dialect)(*obj.code); - std::string code = yul::AsmPrinter{dialect}(*obj.code); + m_generatedYulUtilityCode = yul::AsmPrinter(yul::AsmPrinter::TypePrinting::OmitDefault, dialect)(*obj.code); + std::string code = yul::AsmPrinter{yul::AsmPrinter::TypePrinting::OmitDefault, dialect}(*obj.code); langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); obj.code = yul::Parser(errorReporter, dialect).parse(charStream); *obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 5be4d550e..4f4f96329 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2256,8 +2256,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) solAssert(std::holds_alternative(modified)); - // Do not provide dialect so that we get the full type information. - appendCode() << yul::AsmPrinter()(std::get(modified)) << "\n"; + appendCode() << yul::AsmPrinter(yul::AsmPrinter::TypePrinting::Full, _inlineAsm.dialect())(std::get(modified)) << "\n"; return false; } diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index f9c50cf7a..109c3ee6f 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -132,7 +132,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _assembly) CopyTranslate bodyCopier{m_context, _assembly.dialect(), _assembly.annotation().externalReferences}; yul::Statement modified = bodyCopier(_assembly.operations()); solAssert(std::holds_alternative(modified)); - m_code << yul::AsmPrinter()(std::get(modified)) << "\n"; + m_code << yul::AsmPrinter(yul::AsmPrinter::TypePrinting::Full, _assembly.dialect())(std::get(modified)) << "\n"; return false; } diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 054f83a91..6b840fcfe 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -245,11 +245,15 @@ std::string AsmPrinter::formatTypedName(TypedName _variable) std::string AsmPrinter::appendTypeName(YulName _type, bool _isBoolLiteral) const { - if (m_dialect && !_type.empty()) + yulAssert( + m_typePrintingMode == TypePrinting::OmitDefault || m_typePrintingMode == TypePrinting::Full, + "unhandled printing mode" + ); + if (m_typePrintingMode == TypePrinting::OmitDefault && !_type.empty()) { - if (!_isBoolLiteral && _type == m_dialect->defaultType) + if (!_isBoolLiteral && _type == m_dialect.defaultType) _type = {}; - else if (_isBoolLiteral && _type == m_dialect->boolType && !m_dialect->defaultType.empty()) + else if (_isBoolLiteral && _type == m_dialect.boolType && !m_dialect.defaultType.empty()) // Special case: If we have a bool type but empty default type, do not remove the type. _type = {}; } diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 36ea06c76..684ddaacf 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -46,12 +46,20 @@ struct Dialect; class AsmPrinter { public: + enum class TypePrinting + { + OmitDefault, + Full + }; + explicit AsmPrinter( - Dialect const* _dialect = nullptr, + TypePrinting const _typePrintingMode, + Dialect const& _dialect, std::optional>> _sourceIndexToName = {}, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ): + m_typePrintingMode(_typePrintingMode), m_dialect(_dialect), m_debugInfoSelection(_debugInfoSelection), m_soliditySourceProvider(_soliditySourceProvider) @@ -61,13 +69,6 @@ class AsmPrinter m_nameToSourceIndex[*name] = index; } - explicit AsmPrinter( - Dialect const& _dialect, - std::optional>> _sourceIndexToName = {}, - langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), - langutil::CharStreamProvider const* _soliditySourceProvider = nullptr - ): AsmPrinter(&_dialect, _sourceIndexToName, _debugInfoSelection, _soliditySourceProvider) {} - std::string operator()(Literal const& _literal); std::string operator()(Identifier const& _identifier); std::string operator()(ExpressionStatement const& _expr); @@ -101,7 +102,8 @@ class AsmPrinter return formatDebugData(_node.debugData, !isExpression); } - Dialect const* const m_dialect = nullptr; + TypePrinting const m_typePrintingMode{}; + Dialect const& m_dialect; std::map m_nameToSourceIndex; langutil::SourceLocation m_lastLocation = {}; langutil::DebugInfoSelection m_debugInfoSelection = {}; diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 76d8bdc66..736c1bb84 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -38,13 +38,14 @@ using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; -std::string Data::toString(Dialect const*, DebugInfoSelection const&, CharStreamProvider const*) const +std::string Data::toString(Dialect const&, AsmPrinter::TypePrinting, DebugInfoSelection const&, CharStreamProvider const*) const { return "data \"" + name + "\" hex\"" + util::toHex(data) + "\""; } std::string Object::toString( - Dialect const* _dialect, + Dialect const& _dialect, + AsmPrinter::TypePrinting const _printingMode, DebugInfoSelection const& _debugInfoSelection, CharStreamProvider const* _soliditySourceProvider ) const @@ -63,6 +64,7 @@ std::string Object::toString( "\n"; std::string inner = "code " + AsmPrinter( + _printingMode, _dialect, debugData->sourceNames, _debugInfoSelection, @@ -70,7 +72,7 @@ std::string Object::toString( )(*code); for (auto const& obj: subObjects) - inner += "\n" + obj->toString(_dialect, _debugInfoSelection, _soliditySourceProvider); + inner += "\n" + obj->toString(_dialect, _printingMode, _debugInfoSelection, _soliditySourceProvider); return useSrcComment + "object \"" + name + "\" {\n" + indent(inner) + "\n}"; } diff --git a/libyul/Object.h b/libyul/Object.h index af354005b..4e891c264 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -21,6 +21,7 @@ #pragma once +#include #include #include @@ -53,7 +54,8 @@ struct ObjectNode /// Can be empty since .yul files can also just contain code, without explicitly placing it in an object. std::string name; virtual std::string toString( - Dialect const* _dialect, + Dialect const& _dialect, + AsmPrinter::TypePrinting printingMode, langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const = 0; @@ -70,7 +72,8 @@ struct Data: public ObjectNode bytes data; std::string toString( - Dialect const* _dialect, + Dialect const& _dialect, + AsmPrinter::TypePrinting printingMode, langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const override; @@ -92,7 +95,8 @@ struct Object: public ObjectNode public: /// @returns a (parseable) string representation. std::string toString( - Dialect const* _dialect, + Dialect const& _dialect, + AsmPrinter::TypePrinting printingMode = AsmPrinter::TypePrinting::Full, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ) const; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 9aaaab2eb..223d6c04a 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -365,7 +365,12 @@ std::string YulStack::print( yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); - return m_parserResult->toString(&languageToDialect(m_language, m_evmVersion), m_debugInfoSelection, _soliditySourceProvider) + "\n"; + return m_parserResult->toString( + languageToDialect(m_language, m_evmVersion), + AsmPrinter::TypePrinting::OmitDefault, + m_debugInfoSelection, + _soliditySourceProvider + ) + "\n"; } Json YulStack::astJson() const diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index c4004948c..c022fb0d7 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -510,7 +510,7 @@ void OptimiserSuite::runSequence(std::vector const& _steps, Block& else { std::cout << "== Running " << step << " changed the AST." << std::endl; - std::cout << AsmPrinter{}(_ast) << std::endl; + std::cout << AsmPrinter{AsmPrinter::TypePrinting::Full, m_context.dialect}(_ast) << std::endl; copy = std::make_unique(std::get(ASTCopier{}(_ast))); } } diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 10d7d12ad..dece0d82b 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -96,7 +96,9 @@ yul::Block yul::test::disambiguate(std::string const& _source, bool _yul) std::string yul::test::format(std::string const& _source, bool _yul) { - return yul::AsmPrinter()(*parse(_source, _yul).first); + auto const version = solidity::test::CommonOptions::get().evmVersion(); + Dialect const& dialect = _yul ? EVMDialectTyped::instance(version) : EVMDialect::strictAssemblyForEVMObjects(version); + return yul::AsmPrinter(yul::AsmPrinter::TypePrinting::Full, dialect)(*parse(_source, _yul).first); } namespace diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index faa6c6105..7b3cdac8b 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -164,9 +164,8 @@ BOOST_AUTO_TEST_CASE(default_types_set) ); BOOST_REQUIRE(!!result && errorList.size() == 0); - // Use no dialect so that all types are printed. - // This tests that the default types are properly assigned. - BOOST_CHECK_EQUAL(AsmPrinter{}(*result), + // All types are printed. + BOOST_CHECK_EQUAL(AsmPrinter(AsmPrinter::TypePrinting::Full, EVMDialectTyped::instance(EVMVersion()))(*result), "{\n" " let x:bool := true:bool\n" " let z:bool := true:bool\n" @@ -177,9 +176,8 @@ BOOST_AUTO_TEST_CASE(default_types_set) "}" ); - // Now test again with type dialect. Now the default types - // should be omitted. - BOOST_CHECK_EQUAL(AsmPrinter{EVMDialectTyped::instance(EVMVersion{})}(*result), + // Now the default types should be omitted. + BOOST_CHECK_EQUAL(AsmPrinter(AsmPrinter::TypePrinting::OmitDefault, EVMDialectTyped::instance(EVMVersion()))(*result), "{\n" " let x:bool := true\n" " let z:bool := true\n" diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 82e254980..b30fa8251 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -78,7 +78,7 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co return TestResult::FatalError; } - auto const printed = (m_object->subObjects.empty() ? AsmPrinter{ *m_dialect }(*m_object->code) : m_object->toString(m_dialect)); + auto const printed = (m_object->subObjects.empty() ? AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, *m_dialect}(*m_object->code) : m_object->toString(*m_dialect)); // Re-parse new code for compilability if (!std::get<0>(parse(_stream, _linePrefix, _formatted, printed))) diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 7e81cbf7e..2b9e530e0 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -181,7 +181,7 @@ class YulOpti parse(_source); disambiguate(); OptimiserSuite{m_context}.runSequence(_steps, *m_ast); - std::cout << AsmPrinter{m_dialect}(*m_ast) << std::endl; + std::cout << AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, m_dialect}(*m_ast) << std::endl; } void runInteractive(std::string _source, bool _disambiguated = false) @@ -229,7 +229,7 @@ class YulOpti *m_ast ); } - _source = AsmPrinter{m_dialect}(*m_ast); + _source = AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, m_dialect}(*m_ast); } catch (...) { diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 0cb22242d..e0c8ec4fb 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -105,7 +105,7 @@ void Program::optimise(std::vector const& _optimisationSteps) std::ostream& phaser::operator<<(std::ostream& _stream, Program const& _program) { - return _stream << AsmPrinter()(*_program.m_ast); + return _stream << AsmPrinter(AsmPrinter::TypePrinting::Full, _program.m_dialect)(*_program.m_ast); } std::string Program::toJson() const From 5af111584df90e8ff33c62636b419afa4957e50e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaan=20Uzdo=C4=9Fan?= Date: Thu, 25 Jul 2024 17:41:26 +0200 Subject: [PATCH 0224/1340] Add library abi notes in ABI page --- docs/abi-spec.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 0d48b51dd..91da5127c 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -16,7 +16,7 @@ as described in this specification. The encoding is not self describing and thus We assume that the interface functions of a contract are strongly typed, known at compilation time and static. We assume that all contracts will have the interface definitions of any contracts they call available at compile-time. -This specification does not address contracts whose interface is dynamic or otherwise known only at run-time. +This specification does not address contracts whose interface is dynamic or otherwise known only at run-time. Also, the ABI specification for libraries is :ref:`slightly different `. .. _abi_function_selector: .. index:: ! selector; of a function @@ -47,6 +47,8 @@ without the four bytes specifying the function. Types ===== +Note that the library ABIs can take types different than below e.g. for non-storage structs. See :ref:`library selectors ` for details. + The following elementary types exist: - ``uint``: unsigned integer type of ``M`` bits, ``0 < M <= 256``, ``M % 8 == 0``. e.g. ``uint32``, ``uint8``, ``uint256``. From 911ab3c1b65ae65bbb49a07dffce3520fe700028 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 20 Jun 2024 14:24:11 +0200 Subject: [PATCH 0225/1340] SMTChecker: Introduce SMT-LIB context Maintaining SMT-LIB context has two advantages. First, it simplifies parsing back solvers' answer as we keep around all the declarations of datatypes and variables. Second, it clears SMTLibInterface (CHCSmtLibInterface) as we factor out the members and functinality related to SMT-LIB context. --- libsmtutil/BMCSolverInterface.h | 51 ++ libsmtutil/CHCSmtLib2Interface.cpp | 481 ++++++-------- libsmtutil/CHCSmtLib2Interface.h | 52 +- libsmtutil/CHCSolverInterface.h | 6 +- libsmtutil/CMakeLists.txt | 2 + libsmtutil/SMTLib2Context.cpp | 314 ++++++++++ libsmtutil/SMTLib2Context.h | 109 ++++ libsmtutil/SMTLib2Interface.cpp | 268 +++----- libsmtutil/SMTLib2Interface.h | 60 +- libsmtutil/SMTPortfolio.cpp | 4 +- libsmtutil/SMTPortfolio.h | 8 +- libsmtutil/SolverInterface.h | 19 +- libsmtutil/Z3Interface.cpp | 2 +- libsmtutil/Z3Interface.h | 4 +- libsolidity/formal/BMC.cpp | 2 +- libsolidity/formal/BMC.h | 4 +- libsolidity/formal/CHC.cpp | 3 +- .../formal/EldaricaCHCSmtLib2Interface.cpp | 4 +- .../formal/EldaricaCHCSmtLib2Interface.h | 2 +- .../model_checker_print_query_all/err | 191 +++--- .../model_checker_print_query_bmc/err | 1 - .../model_checker_print_query_chc/err | 190 +++--- .../output.json | 593 +++++++----------- .../output.json | 5 +- .../output.json | 572 +++++++---------- .../output.json | 195 +++--- .../invariants/array_access.sol | 20 + .../invariants/struct_access.sol | 15 + 28 files changed, 1599 insertions(+), 1578 deletions(-) create mode 100644 libsmtutil/BMCSolverInterface.h create mode 100644 libsmtutil/SMTLib2Context.cpp create mode 100644 libsmtutil/SMTLib2Context.h create mode 100644 test/libsolidity/smtCheckerTests/invariants/array_access.sol create mode 100644 test/libsolidity/smtCheckerTests/invariants/struct_access.sol diff --git a/libsmtutil/BMCSolverInterface.h b/libsmtutil/BMCSolverInterface.h new file mode 100644 index 000000000..3681b21e4 --- /dev/null +++ b/libsmtutil/BMCSolverInterface.h @@ -0,0 +1,51 @@ +/* + 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 + +#pragma once + +#include + +namespace solidity::smtutil +{ + +class BMCSolverInterface : public SolverInterface +{ +public: + explicit BMCSolverInterface(std::optional _queryTimeout = {}): m_queryTimeout(_queryTimeout) {} + + ~BMCSolverInterface() override = default; + virtual void reset() = 0; + + virtual void push() = 0; + virtual void pop() = 0; + + virtual void addAssertion(Expression const& _expr) = 0; + + /// Checks for satisfiability, evaluates the expressions if a model + /// is available. Throws SMTSolverError on error. + virtual std::pair> + check(std::vector const& _expressionsToEvaluate) = 0; + + /// @returns a list of queries that the system was not able to respond to. + virtual std::vector unhandledQueries() { return {}; } + +protected: + std::optional m_queryTimeout; +}; + +} diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index a267a843b..8b795b9d5 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -48,48 +48,46 @@ CHCSmtLib2Interface::CHCSmtLib2Interface( std::optional _queryTimeout ): CHCSolverInterface(_queryTimeout), - m_smtlib2(std::make_unique(_queryResponses, _smtCallback, m_queryTimeout)), m_queryResponses(std::move(_queryResponses)), - m_smtCallback(_smtCallback) + m_smtCallback(std::move(_smtCallback)) { reset(); } void CHCSmtLib2Interface::reset() { - m_accumulatedOutput.clear(); - m_variables.clear(); m_unhandledQueries.clear(); - m_smtlib2->reset(); + m_commands.clear(); + m_context.clear(); + createHeader(); + m_context.setTupleDeclarationCallback([&](TupleSort const& _tupleSort){ + m_commands.declareTuple( + _tupleSort.name, + _tupleSort.members, + _tupleSort.components + | ranges::views::transform([&](SortPointer const& _sort){ return m_context.toSmtLibSort(_sort); }) + | ranges::to() + ); + }); } void CHCSmtLib2Interface::registerRelation(Expression const& _expr) { smtAssert(_expr.sort); smtAssert(_expr.sort->kind == Kind::Function); - if (!m_variables.count(_expr.name)) - { - auto fSort = std::dynamic_pointer_cast(_expr.sort); - std::string domain = toSmtLibSort(fSort->domain); - // Relations are predicates which have implicit codomain Bool. - m_variables.insert(_expr.name); - write( - "(declare-fun |" + - _expr.name + - "| " + - domain + - " Bool)" - ); - } + if (m_context.isDeclared(_expr.name)) + return; + auto const& fSort = std::dynamic_pointer_cast(_expr.sort); + smtAssert(fSort->codomain); + auto domain = toSmtLibSort(fSort->domain); + std::string codomain = toSmtLibSort(fSort->codomain); + m_commands.declareFunction(_expr.name, domain, codomain); + m_context.declare(_expr.name, _expr.sort); } void CHCSmtLib2Interface::addRule(Expression const& _expr, std::string const& /*_name*/) { - write( - "(assert\n(forall " + forall() + "\n" + - m_smtlib2->toSExpr(_expr) + - "))\n\n" - ); + m_commands.assertion("(forall" + forall(_expr) + '\n' + m_context.toSExpr(_expr) + ")\n"); } std::tuple CHCSmtLib2Interface::query(Expression const& _block) @@ -117,31 +115,45 @@ std::tuple CHCSmtLib2Inte void CHCSmtLib2Interface::declareVariable(std::string const& _name, SortPointer const& _sort) { smtAssert(_sort); - if (_sort->kind == Kind::Function) - declareFunction(_name, _sort); - else if (!m_variables.count(_name)) - { - m_variables.insert(_name); - write("(declare-var |" + _name + "| " + toSmtLibSort(_sort) + ')'); - } + if (!m_context.isDeclared(_name)) + m_context.declare(_name, _sort); } -std::string CHCSmtLib2Interface::toSmtLibSort(SortPointer _sort) +std::string CHCSmtLib2Interface::toSmtLibSort(SortPointer const& _sort) { - return m_smtlib2->toSmtLibSort(_sort); + return m_context.toSmtLibSort(_sort); } -std::string CHCSmtLib2Interface::toSmtLibSort(std::vector const& _sorts) +std::vector CHCSmtLib2Interface::toSmtLibSort(std::vector const& _sorts) { - return m_smtlib2->toSmtLibSort(_sorts); + return applyMap(_sorts, [this](auto const& sort) { return toSmtLibSort(sort); }); } -std::string CHCSmtLib2Interface::forall() +std::set CHCSmtLib2Interface::collectVariableNames(Expression const& _expr) const { + std::set names; + auto dfs = [&](Expression const& _current, auto _recurse) -> void + { + if (_current.arguments.empty()) + { + if (m_context.isDeclared(_current.name)) + names.insert(_current.name); + } + else + for (auto const& arg: _current.arguments) + _recurse(arg, _recurse); + }; + dfs(_expr, dfs); + return names; +} + +std::string CHCSmtLib2Interface::forall(Expression const& _expr) +{ + auto varNames = collectVariableNames(_expr); std::string vars("("); - for (auto const& [name, sort]: m_smtlib2->variables()) + for (auto const& name: varNames) { - solAssert(sort, ""); + auto sort = m_context.getDeclaredSort(name); if (sort->kind != Kind::Function) vars += " (" + name + " " + toSmtLibSort(sort) + ")"; } @@ -149,35 +161,6 @@ std::string CHCSmtLib2Interface::forall() return vars; } -void CHCSmtLib2Interface::declareFunction(std::string const& _name, SortPointer const& _sort) -{ - smtAssert(_sort); - smtAssert(_sort->kind == Kind::Function); - // TODO Use domain and codomain as key as well - if (!m_variables.count(_name)) - { - auto fSort = std::dynamic_pointer_cast(_sort); - smtAssert(fSort->codomain); - std::string domain = toSmtLibSort(fSort->domain); - std::string codomain = toSmtLibSort(fSort->codomain); - m_variables.insert(_name); - write( - "(declare-fun |" + - _name + - "| " + - domain + - " " + - codomain + - ")" - ); - } -} - -void CHCSmtLib2Interface::write(std::string _data) -{ - m_accumulatedOutput += std::move(_data) + "\n"; -} - std::string CHCSmtLib2Interface::querySolver(std::string const& _input) { util::h256 inputHash = util::keccak256(_input); @@ -186,7 +169,6 @@ std::string CHCSmtLib2Interface::querySolver(std::string const& _input) if (m_smtCallback) { - setupSmtCallback(); auto result = m_smtCallback(ReadCallback::kindString(ReadCallback::Kind::SMTQuery), _input); if (result.success) return result.responseOrErrorMessage; @@ -198,242 +180,194 @@ std::string CHCSmtLib2Interface::querySolver(std::string const& _input) std::string CHCSmtLib2Interface::dumpQuery(Expression const& _expr) { - std::stringstream s; - - s - << createHeaderAndDeclarations() - << m_accumulatedOutput << std::endl - << createQueryAssertion(_expr.name) << std::endl - << "(check-sat)" << std::endl; - - return s.str(); + return m_commands.toString() + createQueryAssertion(_expr.name) + '\n' + "(check-sat)" + '\n'; } -std::string CHCSmtLib2Interface::createHeaderAndDeclarations() { - std::stringstream s; +void CHCSmtLib2Interface::createHeader() +{ if (m_queryTimeout) - s << "(set-option :timeout " + std::to_string(*m_queryTimeout) + ")\n"; - s << "(set-logic HORN)" << std::endl; + m_commands.setOption("timeout", std::to_string(*m_queryTimeout)); + m_commands.setLogic("HORN"); +} - for (auto const& decl: m_smtlib2->userSorts() | ranges::views::values) - s << decl << std::endl; +std::string CHCSmtLib2Interface::createQueryAssertion(std::string _name) { + return "(assert\n(forall ((UNUSED Bool))\n(=> " + std::move(_name) + " false)))"; +} - return s.str(); +namespace +{ +bool isNumber(std::string const& _expr) +{ + return ranges::all_of(_expr, [](char c) { return isDigit(c) || c == '.'; }); +} } -std::string CHCSmtLib2Interface::createQueryAssertion(std::string name) { - return "(assert\n(forall " + forall() + "\n" + "(=> " + name + " false)))"; +void CHCSmtLib2Interface::ScopedParser::addVariableDeclaration(std::string _name, solidity::smtutil::SortPointer _sort) +{ + m_localVariables.emplace(std::move(_name), std::move(_sort)); } -class SMTLibTranslationContext +std::optional CHCSmtLib2Interface::ScopedParser::lookupKnownTupleSort(std::string const& _name) const { - CHCSmtLib2Interface const& m_chcInterface; - std::map m_knownVariables; + return m_context.getTupleType(_name); +} - static bool isNumber(std::string const& _expr) +SortPointer CHCSmtLib2Interface::ScopedParser::toSort(SMTLib2Expression const& _expr) +{ + if (isAtom(_expr)) { - return ranges::all_of(_expr, [](char c) { return isDigit(c) || c == '.'; }); + auto const& name = asAtom(_expr); + if (name == "Int") + return SortProvider::sintSort; + if (name == "Bool") + return SortProvider::boolSort; + auto tupleSort = lookupKnownTupleSort(name); + if (tupleSort) + return tupleSort.value(); } - - -public: - explicit SMTLibTranslationContext(CHCSmtLib2Interface const& _chcInterface) : m_chcInterface(_chcInterface) + else { - // fill user defined sorts and constructors - auto const& userSorts = m_chcInterface.smtlib2Interface()->userSorts(); - for (auto const& declaration: userSorts | ranges::views::values) + auto const& args = asSubExpressions(_expr); + if (asAtom(args[0]) == "Array") { - std::stringstream ss(declaration); - SMTLib2Parser parser(ss); - auto expr = parser.parseExpression(); - smtAssert(parser.isEOF()); - smtAssert(!isAtom(expr)); - auto const& args = asSubExpressions(expr); smtAssert(args.size() == 3); - smtAssert(isAtom(args[0]) && asAtom(args[0]) == "declare-datatypes"); - // args[1] is the name of the type - // args[2] is the constructor with the members - smtAssert(!isAtom(args[2]) && asSubExpressions(args[2]).size() == 1 && !isAtom(asSubExpressions(args[2])[0])); - auto const& constructors = asSubExpressions(asSubExpressions(args[2])[0]); - smtAssert(constructors.size() == 1); - auto const& constructor = constructors[0]; - // constructor is a list: name + members - smtAssert(!isAtom(constructor)); - auto const& constructorArgs = asSubExpressions(constructor); - for (unsigned i = 1u; i < constructorArgs.size(); ++i) - { - auto const& carg = constructorArgs[i]; - smtAssert(!isAtom(carg) && asSubExpressions(carg).size() == 2); - auto const& nameSortPair = asSubExpressions(carg); - m_knownVariables.emplace(asAtom(nameSortPair[0]), toSort(nameSortPair[1])); - } + auto domainSort = toSort(args[1]); + auto codomainSort = toSort(args[2]); + return std::make_shared(std::move(domainSort), std::move(codomainSort)); } + if (args.size() == 3 && isAtom(args[0]) && asAtom(args[0]) == "_" && isAtom(args[1]) + && asAtom(args[1]) == "int2bv") + return std::make_shared(std::stoul(asAtom(args[2]))); } + smtAssert(false, "Unknown sort encountered"); +} - void addVariableDeclaration(std::string name, SortPointer sort) +smtutil::Expression CHCSmtLib2Interface::ScopedParser::parseQuantifier( + std::string const& _quantifierName, + std::vector const& _varList, + SMTLib2Expression const& _coreExpression) +{ + std::vector> boundVariables; + for (auto const& sortedVar: _varList) { - smtAssert(m_knownVariables.find(name) == m_knownVariables.end()); - m_knownVariables.emplace(std::move(name), std::move(sort)); - } - - std::optional lookupKnownTupleSort(std::string const& name) { - auto const& userSorts = m_chcInterface.sortNames(); - std::string quotedName = "|" + name + "|"; - auto it = ranges::find_if(userSorts, [&](auto const& entry) { return entry.second == quotedName; }); - if (it != userSorts.end() && it->first->kind == Kind::Tuple) - { - auto tupleSort = std::dynamic_pointer_cast(it->first); - smtAssert(tupleSort); - return tupleSort; - } - return {}; + smtAssert(!isAtom(sortedVar)); + auto varSortPair = asSubExpressions(sortedVar); + smtAssert(varSortPair.size() == 2); + boundVariables.emplace_back(asAtom(varSortPair[0]), toSort(varSortPair[1])); } - - SortPointer toSort(SMTLib2Expression const& expr) + for (auto const& [var, sort]: boundVariables) { - if (isAtom(expr)) - { - auto const& name = asAtom(expr); - if (name == "Int") - return SortProvider::sintSort; - if (name == "Bool") - return SortProvider::boolSort; - auto tupleSort = lookupKnownTupleSort(name); - if (tupleSort) - return tupleSort.value(); - } else { - auto const& args = asSubExpressions(expr); - if (asAtom(args[0]) == "Array") - { - smtAssert(args.size() == 3); - auto domainSort = toSort(args[1]); - auto codomainSort = toSort(args[2]); - return std::make_shared(std::move(domainSort), std::move(codomainSort)); - } - if (args.size() == 3 && isAtom(args[0]) && asAtom(args[0]) == "_" && isAtom(args[1]) && asAtom(args[1]) == "int2bv") - return std::make_shared(std::stoul(asAtom(args[2]))); - } - smtAssert(false, "Unknown sort encountered"); + smtAssert(m_localVariables.count(var) == 0); // TODO: deal with shadowing? + m_localVariables.emplace(var, sort); } - - smtutil::Expression parseQuantifier( - std::string const& quantifierName, - std::vector const& varList, - SMTLib2Expression const& coreExpression - ) + auto core = toSMTUtilExpression(_coreExpression); + for (auto const& [var, sort]: boundVariables) { - std::vector> boundVariables; - for (auto const& sortedVar: varList) - { - smtAssert(!isAtom(sortedVar)); - auto varSortPair = asSubExpressions(sortedVar); - smtAssert(varSortPair.size() == 2); - boundVariables.emplace_back(asAtom(varSortPair[0]), toSort(varSortPair[1])); - } - for (auto const& [var, sort] : boundVariables) - { - smtAssert(m_knownVariables.find(var) == m_knownVariables.end()); // TODO: deal with shadowing? - m_knownVariables.emplace(var, sort); - } - auto core = toSMTUtilExpression(coreExpression); - for (auto const& [var, sort] : boundVariables) - { - smtAssert(m_knownVariables.find(var) != m_knownVariables.end()); - m_knownVariables.erase(var); - } - return Expression(quantifierName, {core}, SortProvider::boolSort); // TODO: what about the bound variables? - + smtAssert(m_localVariables.count(var) != 0); + m_localVariables.erase(var); } + return Expression(_quantifierName, {core}, SortProvider::boolSort); // TODO: what about the bound variables? +} - smtutil::Expression toSMTUtilExpression(SMTLib2Expression const& _expr) - { - return std::visit( - GenericVisitor{ - [&](std::string const& _atom) +smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLib2Expression const& _expr) +{ + return std::visit( + GenericVisitor{ + [&](std::string const& _atom) + { + if (_atom == "true" || _atom == "false") + return smtutil::Expression(_atom == "true"); + else if (isNumber(_atom)) + return smtutil::Expression(_atom, {}, SortProvider::sintSort); + else if (auto it = m_localVariables.find(_atom); it != m_localVariables.end()) + return smtutil::Expression(_atom, {}, it->second); + else if (m_context.isDeclared(_atom)) + return smtutil::Expression(_atom, {}, m_context.getDeclaredSort(_atom)); + else if (auto maybeTupleType = m_context.getTupleType(_atom); maybeTupleType.has_value()) { - if (_atom == "true" || _atom == "false") - return smtutil::Expression(_atom == "true"); - else if (isNumber(_atom)) - return smtutil::Expression(_atom, {}, SortProvider::sintSort); - else if (auto it = m_knownVariables.find(_atom); it != m_knownVariables.end()) - return smtutil::Expression(_atom, {}, it->second); - else // assume this is a predicate with sort bool; TODO: Context should be aware of predicates! - return smtutil::Expression(_atom, {}, SortProvider::boolSort); - }, - [&](std::vector const& _subExpr) + // 0-ary tuple type, can happen + return smtutil::Expression(_atom, {}, std::make_shared(_atom, std::vector{}, std::vector{})); + } + else + smtAssert(false, "Unhandled atomic SMT expression"); + }, + [&](std::vector const& _subExpr) + { + SortPointer sort; + std::vector arguments; + if (isAtom(_subExpr.front())) { - SortPointer sort; - std::vector arguments; - if (isAtom(_subExpr.front())) + std::string const& op = asAtom(_subExpr.front()); + if (op == "!") { - std::string const& op = asAtom(_subExpr.front()); - if (op == "!") - { - // named term, we ignore the name - smtAssert(_subExpr.size() > 2); - return toSMTUtilExpression(_subExpr[1]); - } - if (op == "exists" || op == "forall") - { - smtAssert(_subExpr.size() == 3); - smtAssert(!isAtom(_subExpr[1])); - return parseQuantifier(op, asSubExpressions(_subExpr[1]), _subExpr[2]); - } - for (size_t i = 1; i < _subExpr.size(); i++) - arguments.emplace_back(toSMTUtilExpression(_subExpr[i])); - if (auto tupleSort = lookupKnownTupleSort(op); tupleSort) - { - auto sortSort = std::make_shared(tupleSort.value()); - return Expression::tuple_constructor(Expression(sortSort), arguments); - } - if (auto it = m_knownVariables.find(op); it != m_knownVariables.end()) - return smtutil::Expression(op, std::move(arguments), it->second); - else - { - std::set - boolOperators{"and", "or", "not", "=", "<", ">", "<=", ">=", "=>"}; - sort = contains(boolOperators, op) ? SortProvider::boolSort : arguments.back().sort; - return smtutil::Expression(op, std::move(arguments), std::move(sort)); - } - smtAssert(false, "Unhandled case in expression conversion"); + // named term, we ignore the name + smtAssert(_subExpr.size() > 2); + return toSMTUtilExpression(_subExpr[1]); + } + if (op == "exists" || op == "forall") + { + smtAssert(_subExpr.size() == 3); + smtAssert(!isAtom(_subExpr[1])); + return parseQuantifier(op, asSubExpressions(_subExpr[1]), _subExpr[2]); + } + for (size_t i = 1; i < _subExpr.size(); i++) + arguments.emplace_back(toSMTUtilExpression(_subExpr[i])); + if (auto tupleSort = lookupKnownTupleSort(op); tupleSort) + { + auto sortSort = std::make_shared(tupleSort.value()); + return Expression::tuple_constructor(Expression(sortSort), arguments); + } + if (m_context.isDeclared(op)) + return smtutil::Expression(op, std::move(arguments), m_context.getDeclaredSort(op)); + if (auto maybeTupleAccessor = m_context.getTupleAccessor(op); maybeTupleAccessor.has_value()) + { + auto accessor = maybeTupleAccessor.value(); + return smtutil::Expression("dt_accessor_" + accessor.first, std::move(arguments), accessor.second); } else { - // check for const array - if (_subExpr.size() == 2 and !isAtom(_subExpr[0])) + std::set boolOperators{"and", "or", "not", "=", "<", ">", "<=", ">=", "=>"}; + sort = contains(boolOperators, op) ? SortProvider::boolSort : arguments.back().sort; + return smtutil::Expression(op, std::move(arguments), std::move(sort)); + } + smtAssert(false, "Unhandled case in expression conversion"); + } + else + { + // check for const array + if (_subExpr.size() == 2 and !isAtom(_subExpr[0])) + { + auto const& typeArgs = asSubExpressions(_subExpr.front()); + if (typeArgs.size() == 3 && typeArgs[0].toString() == "as" + && typeArgs[1].toString() == "const") { - auto const& typeArgs = asSubExpressions(_subExpr.front()); - if (typeArgs.size() == 3 && typeArgs[0].toString() == "as" - && typeArgs[1].toString() == "const") - { - auto arraySort = toSort(typeArgs[2]); - auto sortSort = std::make_shared(arraySort); - return smtutil::Expression:: - const_array(Expression(sortSort), toSMTUtilExpression(_subExpr[1])); - } - if (typeArgs.size() == 3 && typeArgs[0].toString() == "_" - && typeArgs[1].toString() == "int2bv") - { - auto bvSort = std::dynamic_pointer_cast(toSort(_subExpr[0])); - smtAssert(bvSort); - return smtutil::Expression::int2bv(toSMTUtilExpression(_subExpr[1]), bvSort->size); - } - if (typeArgs.size() == 4 && typeArgs[0].toString() == "_" - && typeArgs[1].toString() == "extract") - return smtutil::Expression( - "extract", - {toSMTUtilExpression(typeArgs[2]), toSMTUtilExpression(typeArgs[3])}, - SortProvider::bitVectorSort // TODO: Compute bit size properly? - ); + auto arraySort = toSort(typeArgs[2]); + auto sortSort = std::make_shared(arraySort); + return smtutil::Expression:: + const_array(Expression(sortSort), toSMTUtilExpression(_subExpr[1])); } - smtAssert(false, "Unhandled case in expression conversion"); + if (typeArgs.size() == 3 && typeArgs[0].toString() == "_" + && typeArgs[1].toString() == "int2bv") + { + auto bvSort = std::dynamic_pointer_cast(toSort(_subExpr[0])); + smtAssert(bvSort); + return smtutil::Expression::int2bv(toSMTUtilExpression(_subExpr[1]), bvSort->size); + } + if (typeArgs.size() == 4 && typeArgs[0].toString() == "_" + && typeArgs[1].toString() == "extract") + return smtutil::Expression( + "extract", + {toSMTUtilExpression(typeArgs[2]), toSMTUtilExpression(typeArgs[3])}, + SortProvider::bitVectorSort // TODO: Compute bit size properly? + ); } + smtAssert(false, "Unhandled case in expression conversion"); } - }, - _expr.data - ); - } -}; + } + }, + _expr.data + ); +} #define precondition(CONDITION) if (!(CONDITION)) return {} @@ -474,7 +408,7 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp precondition(isAtom(args[3]) && asAtom(args[3]) == "Bool"); auto& interpretation = args[4]; // inlineLetExpressions(interpretation); - SMTLibTranslationContext context(*this); + ScopedParser scopedParser(m_context); auto const& formalArguments = asSubExpressions(args[2]); std::vector predicateArgs; for (auto const& formalArgument: formalArguments) @@ -483,13 +417,14 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp auto const& nameSortPair = asSubExpressions(formalArgument); precondition(nameSortPair.size() == 2); precondition(isAtom(nameSortPair[0])); - SortPointer varSort = context.toSort(nameSortPair[1]); - context.addVariableDeclaration(asAtom(nameSortPair[0]), varSort); - Expression arg = context.toSMTUtilExpression(nameSortPair[0]); + SortPointer varSort = scopedParser.toSort(nameSortPair[1]); + scopedParser.addVariableDeclaration(asAtom(nameSortPair[0]), varSort); + // FIXME: Why Expression here? + Expression arg = scopedParser.toSMTUtilExpression(nameSortPair[0]); predicateArgs.push_back(arg); } - auto parsedInterpretation = context.toSMTUtilExpression(interpretation); + auto parsedInterpretation = scopedParser.toSMTUtilExpression(interpretation); Expression predicate(asAtom(args[1]), predicateArgs, SortProvider::boolSort); definitions.push_back(predicate == parsedInterpretation); diff --git a/libsmtutil/CHCSmtLib2Interface.h b/libsmtutil/CHCSmtLib2Interface.h index 39131973b..0b81b4541 100644 --- a/libsmtutil/CHCSmtLib2Interface.h +++ b/libsmtutil/CHCSmtLib2Interface.h @@ -25,6 +25,7 @@ #include #include +#include namespace solidity::smtutil { @@ -54,38 +55,49 @@ class CHCSmtLib2Interface: public CHCSolverInterface std::vector unhandledQueries() const { return m_unhandledQueries; } - SMTLib2Interface* smtlib2Interface() const { return m_smtlib2.get(); } +protected: + class ScopedParser + { + public: + ScopedParser(SMTLib2Context const& _context): m_context(_context) {} - auto const& sortNames() const { return m_smtlib2->sortNames(); } + smtutil::Expression toSMTUtilExpression(SMTLib2Expression const& _expr); -protected: - std::string toSmtLibSort(SortPointer _sort); - std::string toSmtLibSort(std::vector const& _sort); + SortPointer toSort(SMTLib2Expression const& _expr); + + void addVariableDeclaration(std::string _name, SortPointer _sort); - void writeHeader(); - std::string forall(); + private: + std::optional lookupKnownTupleSort(std::string const& _name) const; - void declareFunction(std::string const& _name, SortPointer const& _sort); + smtutil::Expression parseQuantifier( + std::string const& _quantifierName, + std::vector const& _varList, + SMTLib2Expression const& _coreExpression + ); - void write(std::string _data); + SMTLib2Context const& m_context; + std::unordered_map m_localVariables; + }; - std::string createQueryAssertion(std::string name); - std::string createHeaderAndDeclarations(); + std::string toSmtLibSort(SortPointer const& _sort); + std::vector toSmtLibSort(std::vector const& _sort); + + std::string forall(Expression const& _expr); + + static std::string createQueryAssertion(std::string _name); + void createHeader(); /// Communicates with the solver via the callback. Throws SMTSolverError on error. - std::string querySolver(std::string const& _input); + virtual std::string querySolver(std::string const& _input); /// Translates CHC solver response with a model to our representation of invariants. Returns None on error. - std::optional invariantsFromSolverResponse(std::string const& response) const; - - /// Hook to setup external solver call - virtual void setupSmtCallback() {} + std::optional invariantsFromSolverResponse(std::string const& _response) const; - /// Used to access toSmtLibSort, SExpr, and handle variables. - std::unique_ptr m_smtlib2; + std::set collectVariableNames(Expression const& _expr) const; - std::string m_accumulatedOutput; - std::set m_variables; + SMTLib2Commands m_commands; + SMTLib2Context m_context; std::map m_queryResponses; std::vector m_unhandledQueries; diff --git a/libsmtutil/CHCSolverInterface.h b/libsmtutil/CHCSolverInterface.h index 8385c1c40..a20283b4f 100644 --- a/libsmtutil/CHCSolverInterface.h +++ b/libsmtutil/CHCSolverInterface.h @@ -30,15 +30,11 @@ namespace solidity::smtutil { -class CHCSolverInterface +class CHCSolverInterface : public SolverInterface { public: CHCSolverInterface(std::optional _queryTimeout = {}): m_queryTimeout(_queryTimeout) {} - virtual ~CHCSolverInterface() = default; - - virtual void declareVariable(std::string const& _name, SortPointer const& _sort) = 0; - /// Takes a function declaration as a relation. virtual void registerRelation(Expression const& _expr) = 0; diff --git a/libsmtutil/CMakeLists.txt b/libsmtutil/CMakeLists.txt index 005fbeb80..c89c56f4f 100644 --- a/libsmtutil/CMakeLists.txt +++ b/libsmtutil/CMakeLists.txt @@ -2,6 +2,8 @@ set(sources CHCSmtLib2Interface.cpp CHCSmtLib2Interface.h Exceptions.h + SMTLib2Context.cpp + SMTLib2Context.h SMTLib2Interface.cpp SMTLib2Interface.h SMTLib2Parser.cpp diff --git a/libsmtutil/SMTLib2Context.cpp b/libsmtutil/SMTLib2Context.cpp new file mode 100644 index 000000000..95bc2011b --- /dev/null +++ b/libsmtutil/SMTLib2Context.cpp @@ -0,0 +1,314 @@ +/* + 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 + +#include + +#include + +#include + +namespace solidity::smtutil +{ + +std::size_t SortPairHash::operator()(std::pair const& _pair) const +{ + std::size_t seed = 0; + boost::hash_combine(seed, _pair.first); + boost::hash_combine(seed, _pair.second); + return seed; +} + +SMTLib2Context::SMTLib2Context() +{ + clear(); +} + +bool SMTLib2Context::isDeclared(std::string const& _name) const +{ + return m_functions.count(_name) > 0; +} + +void SMTLib2Context::declare(std::string const& _name, SortPointer const& _sort) +{ + auto [_, inserted] = m_functions.insert({_name, _sort}); + smtAssert(inserted, "Trying to redeclare SMT function!"); +} + +SortPointer SMTLib2Context::getDeclaredSort(std::string const& _name) const +{ + smtAssert(isDeclared(_name)); + return m_functions.at(_name); +} + +void SMTLib2Context::clear() { + m_functions.clear(); + m_knownTypes.clear(); + m_arraySorts.clear(); + m_tupleSorts.clear(); + m_bitVectorSorts.clear(); + m_callback = {}; + m_knownTypes.emplace_back(std::make_unique(Kind::Bool, std::string("Bool"), std::vector{}, SortId{0u})); + m_knownTypes.emplace_back(std::make_unique(Kind::Int, std::string("Int"), std::vector{}, SortId{1u})); + assert(m_boolSort == m_knownTypes[0]->id); + assert(m_intSort == m_knownTypes[1]->id); +} + +SortId SMTLib2Context::resolve(SortPointer const& _sort) +{ + switch (_sort->kind) + { + case Kind::Int: + return m_intSort; + case Kind::Bool: + return m_boolSort; + case Kind::BitVector: + return resolveBitVectorSort(dynamic_cast(*_sort)); + case Kind::Array: + return resolveArraySort(dynamic_cast(*_sort)); + case Kind::Tuple: + return resolveTupleSort(dynamic_cast(*_sort)); + default: + smtAssert(false, "Invalid SMT sort"); + } +} + +SortPointer SMTLib2Context::unresolve(SortId _sortId) const +{ + smtAssert(_sortId < m_knownTypes.size()); + auto const& type = *m_knownTypes[_sortId]; + switch (type.kind) + { + case Kind::Int: + return SortProvider::sintSort; + case Kind::Bool: + return SortProvider::boolSort; + case Kind::BitVector: + { + auto it = ranges::find_if(m_bitVectorSorts, [&](auto const& entry) { return entry.second == _sortId; }); + smtAssert(it != m_bitVectorSorts.end()); + return std::make_shared(it->first); + } + case Kind::Array: + { + auto it = ranges::find_if(m_arraySorts, [&](auto const& entry) { return entry.second == _sortId; }); + smtAssert(it != m_arraySorts.end()); + return std::make_shared(unresolve(it->first.first), unresolve(it->first.second)); + } + case Kind::Tuple: + { + auto const& tupleType = dynamic_cast(type); + std::vector memberNames; + std::vector memberTypes; + for (auto&& [name, sortId] : tupleType.accessors) + { + memberNames.push_back(name); + memberTypes.push_back(unresolve(sortId)); + } + return std::make_shared(tupleType.name, std::move(memberNames), std::move(memberTypes)); + } + default: + smtAssert(false, "Invalid SMT sort"); + } +} + +SortId SMTLib2Context::resolveBitVectorSort(BitVectorSort const& _sort) +{ + auto size = _sort.size; + auto it = m_bitVectorSorts.find(size); + if (it == m_bitVectorSorts.end()) + { + auto newId = static_cast(m_knownTypes.size()); + m_knownTypes.emplace_back(std::make_unique(Kind::BitVector, "(_ BitVec " + std::to_string(size) + ')', std::vector{}, SortId{newId})); + auto&& [newIt, inserted] = m_bitVectorSorts.emplace(size, SortId{newId}); + smtAssert(inserted); + return newIt->second; + } + return it->second; +} + +SortId SMTLib2Context::resolveArraySort(ArraySort const& _sort) +{ + smtAssert(_sort.domain && _sort.range); + auto domainSort = resolve(_sort.domain); + auto rangeSort = resolve(_sort.range); + auto pair = std::make_pair(domainSort, rangeSort); + auto it = m_arraySorts.find(pair); + if (it == m_arraySorts.end()) + { + auto newId = static_cast(m_knownTypes.size()); + m_knownTypes.emplace_back(std::make_unique(Kind::Array, "Array", std::vector{domainSort, rangeSort}, SortId{newId})); + auto&& [newIt, inserted] = m_arraySorts.emplace(pair, SortId{newId}); + smtAssert(inserted); + return newIt->second; + } + return it->second; +} + +SortId SMTLib2Context::resolveTupleSort(TupleSort const& _sort) +{ + auto const& tupleName = _sort.name; + auto it = m_tupleSorts.find(tupleName); + if (it == m_tupleSorts.end()) + { + std::vector> accessors; + smtAssert(_sort.members.size() == _sort.components.size()); + for (std::size_t i = 0u; i < _sort.members.size(); ++i) + accessors.emplace_back(_sort.members[i], resolve(_sort.components[i])); + auto newId = static_cast(m_knownTypes.size()); + m_knownTypes.emplace_back(std::make_unique(tupleName, std::move(accessors), SortId{newId})); + auto&& [newIt, inserted] = m_tupleSorts.emplace(tupleName, SortId{newId}); + smtAssert(inserted); + if (m_callback) + m_callback(_sort); + return newIt->second; + } + return it->second; +} + +std::string SMTLib2Context::toString(SortId _id) +{ + auto const& sort = m_knownTypes.at(_id); + switch (sort->kind) + { + case Kind::Int: + return "Int"; + case Kind::Bool: + return "Bool"; + case Kind::BitVector: + return dynamic_cast(*sort).name; + case Kind::Array: + { + auto const& arraySort = dynamic_cast(*sort); + smtAssert(arraySort.args.size() == 2); + return "(Array " + toString(arraySort.args.at(0)) + ' ' + toString(arraySort.args.at(1)) + ')'; + } + case Kind::Tuple: + { + auto const& tupleType = dynamic_cast(*sort); + return '|' + tupleType.name + '|'; + } + default: + smtAssert(false, "Invalid SMT sort"); + } +} + +std::string SMTLib2Context::toSmtLibSort(solidity::smtutil::SortPointer const& _sort) +{ + return toString(resolve(_sort)); +} + +std::string SMTLib2Context::toSExpr(Expression const& _expr) +{ + if (_expr.arguments.empty()) + return _expr.name; + + std::string sexpr = "("; + if (_expr.name == "int2bv") + { + size_t size = std::stoul(_expr.arguments[1].name); + auto arg = toSExpr(_expr.arguments.front()); + auto int2bv = "(_ int2bv " + std::to_string(size) + ")"; + // Some solvers treat all BVs as unsigned, so we need to manually apply 2's complement if needed. + sexpr += std::string("ite ") + + "(>= " + arg + " 0) " + + "(" + int2bv + " " + arg + ") " + + "(bvneg (" + int2bv + " (- " + arg + ")))"; + } + else if (_expr.name == "bv2int") + { + auto intSort = std::dynamic_pointer_cast(_expr.sort); + smtAssert(intSort, ""); + + auto arg = toSExpr(_expr.arguments.front()); + auto nat = "(bv2nat " + arg + ")"; + + if (!intSort->isSigned) + return nat; + + auto bvSort = std::dynamic_pointer_cast(_expr.arguments.front().sort); + smtAssert(bvSort, ""); + auto size = std::to_string(bvSort->size); + auto pos = std::to_string(bvSort->size - 1); + + // Some solvers treat all BVs as unsigned, so we need to manually apply 2's complement if needed. + sexpr += std::string("ite ") + + "(= ((_ extract " + pos + " " + pos + ")" + arg + ") #b0) " + + nat + " " + + "(- (bv2nat (bvneg " + arg + ")))"; + } + else if (_expr.name == "const_array") + { + smtAssert(_expr.arguments.size() == 2, ""); + auto sortSort = std::dynamic_pointer_cast(_expr.arguments.at(0).sort); + smtAssert(sortSort, ""); + auto arraySort = std::dynamic_pointer_cast(sortSort->inner); + smtAssert(arraySort, ""); + sexpr += "(as const " + toSmtLibSort(arraySort) + ") "; + sexpr += toSExpr(_expr.arguments.at(1)); + } + else if (_expr.name == "tuple_get") + { + smtAssert(_expr.arguments.size() == 2, ""); + auto tupleSort = std::dynamic_pointer_cast(_expr.arguments.at(0).sort); + size_t index = std::stoul(_expr.arguments.at(1).name); + smtAssert(index < tupleSort->members.size(), ""); + sexpr += "|" + tupleSort->members.at(index) + "| " + toSExpr(_expr.arguments.at(0)); + } + else if (_expr.name == "tuple_constructor") + { + auto tupleSort = std::dynamic_pointer_cast(_expr.sort); + smtAssert(tupleSort, ""); + sexpr += "|" + tupleSort->name + "|"; + for (auto const& arg: _expr.arguments) + sexpr += " " + toSExpr(arg); + } + else + { + sexpr += _expr.name; + for (auto const& arg: _expr.arguments) + sexpr += " " + toSExpr(arg); + } + sexpr += ")"; + return sexpr; +} + +std::optional SMTLib2Context::getTupleType(std::string const& _name) const +{ + auto it = m_tupleSorts.find(_name); + return it == m_tupleSorts.end() ? std::nullopt : std::optional(unresolve(it->second)); +} + +std::optional> SMTLib2Context::getTupleAccessor(std::string const& _name) const +{ + for (auto&& [_, sortId] : m_tupleSorts) + { + auto const& type = m_knownTypes.at(sortId); + smtAssert(type->kind == Kind::Tuple); + auto const& tupleType = dynamic_cast(*type); + for (auto&& [memberName, memberSort] : tupleType.accessors) + if (memberName == _name) + return std::make_pair(memberName, unresolve(memberSort)); + } + return std::nullopt; +} + +void SMTLib2Context::setTupleDeclarationCallback(TupleDeclarationCallback _callback) +{ + m_callback = std::move(_callback); +} +} // namespace solidity::smtutil diff --git a/libsmtutil/SMTLib2Context.h b/libsmtutil/SMTLib2Context.h new file mode 100644 index 000000000..30a44605c --- /dev/null +++ b/libsmtutil/SMTLib2Context.h @@ -0,0 +1,109 @@ +/* + 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 + +#pragma once + +#include +#include + +#include +#include +#include + +namespace solidity::smtutil +{ + +using SortId = uint32_t; +struct SortPairHash +{ + std::size_t operator()(std::pair const& _pair) const; +}; + +struct SMTLibType { + Kind const kind; + SortId const id; + SMTLibType(Kind _kind, SortId _id): kind(_kind), id(_id) {} + virtual ~SMTLibType() = default; +}; + +struct SMTLibSort : public SMTLibType +{ + std::string const name; + std::vector const args; + + SMTLibSort( + Kind _kind, + std::string_view _name, + std::vector _args, + SortId _id + ): SMTLibType(_kind, _id), name(_name), args(std::move(_args)) {} +}; + +struct TupleType : public SMTLibType +{ + std::string const name; + std::vector> accessors; + + TupleType(std::string_view _name, std::vector> _accessors, SortId _id) + : SMTLibType(Kind::Tuple, _id), name(_name), accessors(std::move(_accessors)) {} +}; + +class SMTLib2Context +{ +public: + using TupleDeclarationCallback = std::function; + + SMTLib2Context(); + void clear(); + + bool isDeclared(std::string const& _name) const; + void declare(std::string const& _name, SortPointer const& _sort); + SortPointer getDeclaredSort(std::string const& _name) const; + + SortId resolve(SortPointer const& _sort); + SortPointer unresolve(SortId _sortId) const; + + std::string toString(SortId _id); + + std::string toSExpr(Expression const& _expr); + std::string toSmtLibSort(SortPointer const& _sort); + + std::optional getTupleType(std::string const& _name) const; + std::optional> getTupleAccessor(std::string const& _name) const; + + void setTupleDeclarationCallback(TupleDeclarationCallback _callback); +private: + SortId resolveBitVectorSort(BitVectorSort const& _sort); + SortId resolveArraySort(ArraySort const& _sort); + SortId resolveTupleSort(TupleSort const& _sort); + + using functions_t = std::map; + functions_t m_functions; // Variables are uninterpreted constants = nullary functions + + SortId const m_boolSort{0u}; + SortId const m_intSort{1u}; + std::vector> m_knownTypes; + std::unordered_map, SortId, SortPairHash> m_arraySorts; + std::unordered_map m_bitVectorSorts; + std::unordered_map m_tupleSorts; + + TupleDeclarationCallback m_callback; +}; + +} + diff --git a/libsmtutil/SMTLib2Interface.cpp b/libsmtutil/SMTLib2Interface.cpp index 06ed26f2b..81ad5ddd4 100644 --- a/libsmtutil/SMTLib2Interface.cpp +++ b/libsmtutil/SMTLib2Interface.cpp @@ -43,7 +43,7 @@ SMTLib2Interface::SMTLib2Interface( ReadCallback::Callback _smtCallback, std::optional _queryTimeout ): - SolverInterface(_queryTimeout), + BMCSolverInterface(_queryTimeout), m_queryResponses(std::move(_queryResponses)), m_smtCallback(std::move(_smtCallback)) { @@ -52,74 +52,67 @@ SMTLib2Interface::SMTLib2Interface( void SMTLib2Interface::reset() { - m_accumulatedOutput.clear(); - m_accumulatedOutput.emplace_back(); - m_variables.clear(); - m_userSorts.clear(); - m_sortNames.clear(); - write("(set-option :produce-models true)"); + m_commands.clear(); + m_context.clear(); + m_commands.setOption("produce-models", "true"); if (m_queryTimeout) - write("(set-option :timeout " + std::to_string(*m_queryTimeout) + ")"); - write("(set-logic ALL)"); + m_commands.setOption("timeout", std::to_string(*m_queryTimeout)); + m_commands.setLogic("ALL"); + m_context.setTupleDeclarationCallback([&](TupleSort const& tupleSort){ + m_commands.declareTuple( + tupleSort.name, + tupleSort.members, + tupleSort.components + | ranges::views::transform([&](SortPointer const& sort){ return m_context.toSmtLibSort(sort); }) + | ranges::to() + ); + }); } void SMTLib2Interface::push() { - m_accumulatedOutput.emplace_back(); + m_commands.push(); } void SMTLib2Interface::pop() { - smtAssert(!m_accumulatedOutput.empty(), ""); - m_accumulatedOutput.pop_back(); + m_commands.pop(); } void SMTLib2Interface::declareVariable(std::string const& _name, SortPointer const& _sort) { - smtAssert(_sort, ""); + smtAssert(_sort); if (_sort->kind == Kind::Function) declareFunction(_name, _sort); - else if (!m_variables.count(_name)) + else if (!m_context.isDeclared(_name)) { - m_variables.emplace(_name, _sort); - write("(declare-fun |" + _name + "| () " + toSmtLibSort(_sort) + ')'); + m_context.declare(_name, _sort); + m_commands.declareVariable(_name, toSmtLibSort(_sort)); } } void SMTLib2Interface::declareFunction(std::string const& _name, SortPointer const& _sort) { - smtAssert(_sort, ""); - smtAssert(_sort->kind == Kind::Function, ""); - // TODO Use domain and codomain as key as well - if (!m_variables.count(_name)) + smtAssert(_sort); + smtAssert(_sort->kind == Kind::Function); + if (!m_context.isDeclared(_name)) { auto const& fSort = std::dynamic_pointer_cast(_sort); - std::string domain = toSmtLibSort(fSort->domain); + auto domain = toSmtLibSort(fSort->domain); std::string codomain = toSmtLibSort(fSort->codomain); - m_variables.emplace(_name, _sort); - write( - "(declare-fun |" + - _name + - "| " + - domain + - " " + - codomain + - ")" - ); + m_context.declare(_name, _sort); + m_commands.declareFunction(_name, domain, codomain); } } void SMTLib2Interface::addAssertion(Expression const& _expr) { - write("(assert " + toSExpr(_expr) + ")"); + m_commands.assertion(toSExpr(_expr)); } std::pair> SMTLib2Interface::check(std::vector const& _expressionsToEvaluate) { - std::string response = querySolver( - boost::algorithm::join(m_accumulatedOutput, "\n") + - checkSatAndGetValuesCommand(_expressionsToEvaluate) - ); + std::string response = querySolver(dumpQuery(_expressionsToEvaluate)); CheckResult result; // TODO proper parsing @@ -138,140 +131,23 @@ std::pair> SMTLib2Interface::check(std::ve return std::make_pair(result, values); } -std::string SMTLib2Interface::toSExpr(Expression const& _expr) +std::string SMTLib2Interface::toSmtLibSort(SortPointer _sort) { - if (_expr.arguments.empty()) - return _expr.name; - - std::string sexpr = "("; - if (_expr.name == "int2bv") - { - size_t size = std::stoul(_expr.arguments[1].name); - auto arg = toSExpr(_expr.arguments.front()); - auto int2bv = "(_ int2bv " + std::to_string(size) + ")"; - // Some solvers treat all BVs as unsigned, so we need to manually apply 2's complement if needed. - sexpr += std::string("ite ") + - "(>= " + arg + " 0) " + - "(" + int2bv + " " + arg + ") " + - "(bvneg (" + int2bv + " (- " + arg + ")))"; - } - else if (_expr.name == "bv2int") - { - auto intSort = std::dynamic_pointer_cast(_expr.sort); - smtAssert(intSort, ""); - - auto arg = toSExpr(_expr.arguments.front()); - auto nat = "(bv2nat " + arg + ")"; - - if (!intSort->isSigned) - return nat; - - auto bvSort = std::dynamic_pointer_cast(_expr.arguments.front().sort); - smtAssert(bvSort, ""); - auto size = std::to_string(bvSort->size); - auto pos = std::to_string(bvSort->size - 1); - - // Some solvers treat all BVs as unsigned, so we need to manually apply 2's complement if needed. - sexpr += std::string("ite ") + - "(= ((_ extract " + pos + " " + pos + ")" + arg + ") #b0) " + - nat + " " + - "(- (bv2nat (bvneg " + arg + ")))"; - } - else if (_expr.name == "const_array") - { - smtAssert(_expr.arguments.size() == 2, ""); - auto sortSort = std::dynamic_pointer_cast(_expr.arguments.at(0).sort); - smtAssert(sortSort, ""); - auto arraySort = std::dynamic_pointer_cast(sortSort->inner); - smtAssert(arraySort, ""); - sexpr += "(as const " + toSmtLibSort(arraySort) + ") "; - sexpr += toSExpr(_expr.arguments.at(1)); - } - else if (_expr.name == "tuple_get") - { - smtAssert(_expr.arguments.size() == 2, ""); - auto tupleSort = std::dynamic_pointer_cast(_expr.arguments.at(0).sort); - size_t index = std::stoul(_expr.arguments.at(1).name); - smtAssert(index < tupleSort->members.size(), ""); - sexpr += "|" + tupleSort->members.at(index) + "| " + toSExpr(_expr.arguments.at(0)); - } - else if (_expr.name == "tuple_constructor") - { - auto tupleSort = std::dynamic_pointer_cast(_expr.sort); - smtAssert(tupleSort, ""); - sexpr += "|" + tupleSort->name + "|"; - for (auto const& arg: _expr.arguments) - sexpr += " " + toSExpr(arg); - } - else - { - sexpr += _expr.name; - for (auto const& arg: _expr.arguments) - sexpr += " " + toSExpr(arg); - } - sexpr += ")"; - return sexpr; + return m_context.toSmtLibSort(std::move(_sort)); } -std::string SMTLib2Interface::toSmtLibSort(solidity::smtutil::SortPointer _sort) +std::vector SMTLib2Interface::toSmtLibSort(std::vector const& _sorts) { - if (!m_sortNames.count(_sort)) - m_sortNames[_sort] = toSmtLibSortInternal(_sort); - return m_sortNames.at(_sort); -} - -std::string SMTLib2Interface::toSmtLibSortInternal(SortPointer _sort) -{ - switch (_sort->kind) - { - case Kind::Int: - return "Int"; - case Kind::Bool: - return "Bool"; - case Kind::BitVector: - return "(_ BitVec " + std::to_string(dynamic_cast(*_sort).size) + ")"; - case Kind::Array: - { - auto const& arraySort = dynamic_cast(*_sort); - smtAssert(arraySort.domain && arraySort.range, ""); - return "(Array " + toSmtLibSort(arraySort.domain) + ' ' + toSmtLibSort(arraySort.range) + ')'; - } - case Kind::Tuple: - { - auto const& tupleSort = dynamic_cast(*_sort); - std::string tupleName = "|" + tupleSort.name + "|"; - auto isName = [&](auto entry) { return entry.first == tupleName; }; - if (ranges::find_if(m_userSorts, isName) == m_userSorts.end()) - { - std::string decl("(declare-datatypes ((" + tupleName + " 0)) (((" + tupleName); - smtAssert(tupleSort.members.size() == tupleSort.components.size(), ""); - for (unsigned i = 0; i < tupleSort.members.size(); ++i) - decl += " (|" + tupleSort.members.at(i) + "| " + toSmtLibSort(tupleSort.components.at(i)) + ")"; - decl += "))))"; - m_userSorts.emplace_back(tupleName, decl); - write(decl); - } - - return tupleName; - } - default: - smtAssert(false, "Invalid SMT sort"); - } -} - -std::string SMTLib2Interface::toSmtLibSort(std::vector const& _sorts) -{ - std::string ssort("("); + std::vector ssorts; + ssorts.reserve(_sorts.size()); for (auto const& sort: _sorts) - ssort += toSmtLibSort(sort) + " "; - ssort += ")"; - return ssort; + ssorts.push_back(toSmtLibSort(sort)); + return ssorts; } -void SMTLib2Interface::write(std::string _data) +std::string SMTLib2Interface::toSExpr(solidity::smtutil::Expression const& _expr) { - smtAssert(!m_accumulatedOutput.empty(), ""); - m_accumulatedOutput.back() += std::move(_data) + "\n"; + return m_context.toSExpr(_expr); } std::string SMTLib2Interface::checkSatAndGetValuesCommand(std::vector const& _expressionsToEvaluate) @@ -333,6 +209,70 @@ std::string SMTLib2Interface::querySolver(std::string const& _input) std::string SMTLib2Interface::dumpQuery(std::vector const& _expressionsToEvaluate) { - return boost::algorithm::join(m_accumulatedOutput, "\n") + - checkSatAndGetValuesCommand(_expressionsToEvaluate); + return m_commands.toString() + '\n' + checkSatAndGetValuesCommand(_expressionsToEvaluate); +} + + +void SMTLib2Commands::push() { + m_frameLimits.push_back(m_commands.size()); +} + +void SMTLib2Commands::pop() { + smtAssert(!m_commands.empty()); + auto limit = m_frameLimits.back(); + m_frameLimits.pop_back(); + while (m_commands.size() > limit) + m_commands.pop_back(); +} + +std::string SMTLib2Commands::toString() const { + return boost::algorithm::join(m_commands, "\n"); +} + +void SMTLib2Commands::clear() { + m_commands.clear(); + m_frameLimits.clear(); +} + +void SMTLib2Commands::assertion(std::string _expr) { + m_commands.push_back("(assert " + std::move(_expr) + ')'); +} + +void SMTLib2Commands::setOption(std::string _name, std::string _value) +{ + m_commands.push_back("(set-option :" + std::move(_name) + ' ' + std::move(_value) + ')'); +} + +void SMTLib2Commands::setLogic(std::string _logic) +{ + m_commands.push_back("(set-logic " + std::move(_logic) + ')'); +} + +void SMTLib2Commands::declareVariable(std::string _name, std::string _sort) +{ + m_commands.push_back("(declare-fun |" + std::move(_name) + "| () " + std::move(_sort) + ')'); +} + +void SMTLib2Commands::declareFunction(std::string const& _name, std::vector const& _domain, std::string const& _codomain) +{ + std::stringstream ss; + ss << "(declare-fun |" << _name << "| " << '(' << boost::join(_domain, " ") + << ')' << ' ' << _codomain << ')'; + m_commands.push_back(ss.str()); +} + +void SMTLib2Commands::declareTuple( + std::string const& _name, + std::vector const& _memberNames, + std::vector const& _memberSorts +) +{ + auto quotedName = '|' + _name + '|'; + std::stringstream ss; + ss << "(declare-datatypes ((" << quotedName << " 0)) (((" << quotedName; + for (auto && [memberName, memberSort]: ranges::views::zip(_memberNames, _memberSorts)) + ss << " (|" << memberName << "| " << memberSort << ")"; + ss << "))))"; + auto declaration = ss.str(); + m_commands.push_back(ss.str()); } diff --git a/libsmtutil/SMTLib2Interface.h b/libsmtutil/SMTLib2Interface.h index d60a5bd25..11478223c 100644 --- a/libsmtutil/SMTLib2Interface.h +++ b/libsmtutil/SMTLib2Interface.h @@ -18,7 +18,9 @@ #pragma once -#include +#include + +#include #include @@ -34,7 +36,36 @@ namespace solidity::smtutil { -class SMTLib2Interface: public SolverInterface +class SMTLib2Commands +{ +public: + void push(); + void pop(); + + void clear(); + + void assertion(std::string _expr); + + void setOption(std::string _name, std::string _value); + + void setLogic(std::string _logic); + + void declareVariable(std::string _name, std::string _sort); + void declareFunction(std::string const& _name, std::vector const& _domain, std::string const& _codomain); + void declareTuple( + std::string const& _name, + std::vector const& _memberNames, + std::vector const& _memberSorts + ); + + [[nodiscard]] std::string toString() const; +private: + std::vector m_commands; + std::vector m_frameLimits; + +}; + +class SMTLib2Interface: public BMCSolverInterface { public: /// Noncopyable. @@ -62,12 +93,7 @@ class SMTLib2Interface: public SolverInterface // Used by CHCSmtLib2Interface std::string toSExpr(Expression const& _expr); std::string toSmtLibSort(SortPointer _sort); - std::string toSmtLibSort(std::vector const& _sort); - - std::map variables() { return m_variables; } - - std::vector> const& userSorts() const { return m_userSorts; } - std::map const& sortNames() const { return m_sortNames; } + std::vector toSmtLibSort(std::vector const& _sort); std::string dumpQuery(std::vector const& _expressionsToEvaluate); @@ -76,28 +102,14 @@ class SMTLib2Interface: public SolverInterface void declareFunction(std::string const& _name, SortPointer const& _sort); - void write(std::string _data); - std::string checkSatAndGetValuesCommand(std::vector const& _expressionsToEvaluate); std::vector parseValues(std::string::const_iterator _start, std::string::const_iterator _end); /// Communicates with the solver via the callback. Throws SMTSolverError on error. std::string querySolver(std::string const& _input); - std::string toSmtLibSortInternal(SortPointer _sort); - - std::vector m_accumulatedOutput; - std::map m_variables; - - /// Each pair in this vector represents an SMTChecker created - /// sort (a user sort), and the smtlib2 declaration of that sort. - /// It needs to be a vector so that the declaration order is kept, - /// otherwise solvers cannot parse the queries. - std::vector> m_userSorts; - - /// Maps a user sort to SMT-LIB2 sort. - /// Remembers all declared sorts and is used as a cache as well. - std::map m_sortNames; + SMTLib2Commands m_commands; + SMTLib2Context m_context; std::map m_queryResponses; std::vector m_unhandledQueries; diff --git a/libsmtutil/SMTPortfolio.cpp b/libsmtutil/SMTPortfolio.cpp index 196f02fdf..94c92f390 100644 --- a/libsmtutil/SMTPortfolio.cpp +++ b/libsmtutil/SMTPortfolio.cpp @@ -26,10 +26,10 @@ using namespace solidity::frontend; using namespace solidity::smtutil; SMTPortfolio::SMTPortfolio( - std::vector> _solvers, + std::vector> _solvers, std::optional _queryTimeout ): - SolverInterface(_queryTimeout), m_solvers(std::move(_solvers)) + BMCSolverInterface(_queryTimeout), m_solvers(std::move(_solvers)) {} diff --git a/libsmtutil/SMTPortfolio.h b/libsmtutil/SMTPortfolio.h index 5ffb37eb3..b445f40a2 100644 --- a/libsmtutil/SMTPortfolio.h +++ b/libsmtutil/SMTPortfolio.h @@ -19,7 +19,7 @@ #pragma once -#include +#include #include #include @@ -35,14 +35,14 @@ namespace solidity::smtutil * It also checks whether different solvers give conflicting answers * to SMT queries. */ -class SMTPortfolio: public SolverInterface +class SMTPortfolio: public BMCSolverInterface { public: /// Noncopyable. SMTPortfolio(SMTPortfolio const&) = delete; SMTPortfolio& operator=(SMTPortfolio const&) = delete; - SMTPortfolio(std::vector> solvers, std::optional _queryTimeout); + SMTPortfolio(std::vector> solvers, std::optional _queryTimeout); void reset() override; @@ -63,7 +63,7 @@ class SMTPortfolio: public SolverInterface private: static bool solverAnswered(CheckResult result); - std::vector> m_solvers; + std::vector> m_solvers; std::vector m_assertions; }; diff --git a/libsmtutil/SolverInterface.h b/libsmtutil/SolverInterface.h index 92f9c8f75..2639ae024 100644 --- a/libsmtutil/SolverInterface.h +++ b/libsmtutil/SolverInterface.h @@ -512,13 +512,9 @@ DEV_SIMPLE_EXCEPTION(SolverError); class SolverInterface { public: - SolverInterface(std::optional _queryTimeout = {}): m_queryTimeout(_queryTimeout) {} + SolverInterface() = default; virtual ~SolverInterface() = default; - virtual void reset() = 0; - - virtual void push() = 0; - virtual void pop() = 0; virtual void declareVariable(std::string const& _name, SortPointer const& _sort) = 0; Expression newVariable(std::string _name, SortPointer const& _sort) @@ -529,21 +525,8 @@ class SolverInterface return Expression(std::move(_name), {}, _sort); } - virtual void addAssertion(Expression const& _expr) = 0; - - /// Checks for satisfiability, evaluates the expressions if a model - /// is available. Throws SMTSolverError on error. - virtual std::pair> - check(std::vector const& _expressionsToEvaluate) = 0; - - /// @returns a list of queries that the system was not able to respond to. - virtual std::vector unhandledQueries() { return {}; } - /// @returns how many SMT solvers this interface has. virtual size_t solvers() { return 1; } - -protected: - std::optional m_queryTimeout; }; } diff --git a/libsmtutil/Z3Interface.cpp b/libsmtutil/Z3Interface.cpp index 4e1d1cec1..efd656259 100644 --- a/libsmtutil/Z3Interface.cpp +++ b/libsmtutil/Z3Interface.cpp @@ -39,7 +39,7 @@ bool Z3Interface::available() } Z3Interface::Z3Interface(std::optional _queryTimeout): - SolverInterface(_queryTimeout), + BMCSolverInterface(_queryTimeout), m_solver(m_context) { // These need to be set globally. diff --git a/libsmtutil/Z3Interface.h b/libsmtutil/Z3Interface.h index d5dc5792e..ee5270f44 100644 --- a/libsmtutil/Z3Interface.h +++ b/libsmtutil/Z3Interface.h @@ -18,13 +18,13 @@ #pragma once -#include +#include #include namespace solidity::smtutil { -class Z3Interface: public SolverInterface +class Z3Interface: public BMCSolverInterface { public: /// Noncopyable. diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index dbaed2960..fda573d3d 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -56,7 +56,7 @@ BMC::BMC( SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _provedSafeReporter, _charStreamProvider) { solAssert(!_settings.printQuery || _settings.solvers == SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); - std::vector> solvers; + std::vector> solvers; if (_settings.solvers.smtlib2) solvers.emplace_back(std::make_unique(_smtlib2Responses, _smtCallback, _settings.timeout)); if (_settings.solvers.cvc5) diff --git a/libsolidity/formal/BMC.h b/libsolidity/formal/BMC.h index bbd8c1017..a0ee9a374 100644 --- a/libsolidity/formal/BMC.h +++ b/libsolidity/formal/BMC.h @@ -35,7 +35,7 @@ #include -#include +#include #include #include @@ -205,7 +205,7 @@ class BMC: public SMTEncoder smtutil::Expression mergeVariablesFromLoopCheckpoints(); bool isInsideLoop() const; - std::unique_ptr m_interface; + std::unique_ptr m_interface; /// Flags used for better warning messages. bool m_loopExecutionHappened = false; diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 73b979364..2bd019537 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -1312,7 +1312,7 @@ void CHC::resetSourceAnalysis() auto smtlib2Interface = dynamic_cast(m_interface.get()); solAssert(smtlib2Interface); smtlib2Interface->reset(); - m_context.setSolver(smtlib2Interface->smtlib2Interface()); + m_context.setSolver(smtlib2Interface); } m_context.reset(); @@ -1743,7 +1743,6 @@ void CHC::createErrorBlock() "error_target_" + std::to_string(m_context.newUniqueId()), PredicateType::Error ); - m_interface->registerRelation(m_errorPredicate->functor()); } void CHC::connectBlocks(smtutil::Expression const& _from, smtutil::Expression const& _to, smtutil::Expression const& _constraints) diff --git a/libsolidity/formal/EldaricaCHCSmtLib2Interface.cpp b/libsolidity/formal/EldaricaCHCSmtLib2Interface.cpp index 4fa94539d..46416f2d9 100644 --- a/libsolidity/formal/EldaricaCHCSmtLib2Interface.cpp +++ b/libsolidity/formal/EldaricaCHCSmtLib2Interface.cpp @@ -30,8 +30,10 @@ EldaricaCHCSmtLib2Interface::EldaricaCHCSmtLib2Interface( { } -void EldaricaCHCSmtLib2Interface::setupSmtCallback() +std::string EldaricaCHCSmtLib2Interface::querySolver(std::string const& _input) { if (auto* universalCallback = m_smtCallback.target()) universalCallback->smtCommand().setEldarica(m_queryTimeout, m_computeInvariants); + + return CHCSmtLib2Interface::querySolver(_input); } diff --git a/libsolidity/formal/EldaricaCHCSmtLib2Interface.h b/libsolidity/formal/EldaricaCHCSmtLib2Interface.h index 2c83b194c..a0ebdc332 100644 --- a/libsolidity/formal/EldaricaCHCSmtLib2Interface.h +++ b/libsolidity/formal/EldaricaCHCSmtLib2Interface.h @@ -33,7 +33,7 @@ class EldaricaCHCSmtLib2Interface: public smtutil::CHCSmtLib2Interface ); private: - void setupSmtCallback() override; + std::string querySolver(std::string const& _input) override; bool m_computeInvariants; }; diff --git a/test/cmdlineTests/model_checker_print_query_all/err b/test/cmdlineTests/model_checker_print_query_all/err index 7fbaba3eb..76dff6664 100644 --- a/test/cmdlineTests/model_checker_print_query_all/err +++ b/test/cmdlineTests/model_checker_print_query_all/err @@ -1,125 +1,85 @@ Info: CHC: Requested query: (set-option :timeout 1000) (set-logic HORN) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) - - -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) - - -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) - - -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) +) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) +) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) (declare-fun |error_target_3| () Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) - - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) +)(assert +(forall ((UNUSED Bool)) (=> error_target_3 false))) (check-sat) @@ -152,7 +112,6 @@ Info: BMC: Requested query: (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) - (assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) diff --git a/test/cmdlineTests/model_checker_print_query_bmc/err b/test/cmdlineTests/model_checker_print_query_bmc/err index ff8b796f8..6fb8440b7 100644 --- a/test/cmdlineTests/model_checker_print_query_bmc/err +++ b/test/cmdlineTests/model_checker_print_query_bmc/err @@ -19,7 +19,6 @@ Info: BMC: Requested query: (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) - (assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) diff --git a/test/cmdlineTests/model_checker_print_query_chc/err b/test/cmdlineTests/model_checker_print_query_chc/err index 4da0a7cb5..28368f546 100644 --- a/test/cmdlineTests/model_checker_print_query_chc/err +++ b/test/cmdlineTests/model_checker_print_query_chc/err @@ -1,125 +1,85 @@ Info: CHC: Requested query: (set-option :timeout 1000) (set-logic HORN) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) - - -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) - - -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) - - -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) +) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) +) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) (declare-fun |error_target_3| () Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) - - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) +)(assert +(forall ((UNUSED Bool)) (=> error_target_3 false))) (check-sat) diff --git a/test/cmdlineTests/standard_model_checker_print_query_all/output.json b/test/cmdlineTests/standard_model_checker_print_query_all/output.json index 4b5782de3..a800fb34d 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_all/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_all/output.json @@ -1,131 +1,7 @@ { "auxiliaryInputRequested": { "smtlib2queries": { - "0xcbd85fe3127d1edfce70355ba6da5a3e9573873d8596ee8b1cfc2222af166628": "(set-option :timeout 1000) -(set-logic HORN) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) - - -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) - - -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) - - -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - -(declare-fun |error_target_3| () Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) - - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> error_target_3 false))) -(check-sat) -", - "0xcbfcc2413b217c6564ee01f322c9ca1f34fd79d19961dc3e62aa9c2e5dcb6efc": "(set-option :produce-models true) + "0x54683263097e1c4f5e0e75b68e4ebe3e4f7042f899198181df911c8196a1725b": "(set-option :produce-models true) (set-option :timeout 1000) (set-logic ALL) (declare-fun |x_5_3| () Int) @@ -148,12 +24,95 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) - (assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) (get-value (|EVALEXPR_0| )) +", + "0x9cfcd53712a0be144c8e7983b3635498ead1af2624885fb89762eae8c43233e5": "(set-option :timeout 1000) +(set-logic HORN) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) +(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) +(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) +(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) +) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) +) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) +(declare-fun |error_target_3| () Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) +)(assert +(forall ((UNUSED Bool)) +(=> error_target_3 false))) +(check-sat) " } }, @@ -164,125 +123,85 @@ "formattedMessage": "Info: CHC: Requested query: (set-option :timeout 1000) (set-logic HORN) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) - - -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) - - -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) - - -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) +) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) +) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) (declare-fun |error_target_3| () Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) - - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) +)(assert +(forall ((UNUSED Bool)) (=> error_target_3 false))) (check-sat) @@ -291,125 +210,85 @@ "message": "CHC: Requested query: (set-option :timeout 1000) (set-logic HORN) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) - - -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) - - -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) - - -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) +) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) +) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) (declare-fun |error_target_3| () Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) - - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) +)(assert +(forall ((UNUSED Bool)) (=> error_target_3 false))) (check-sat) ", @@ -463,7 +342,6 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) - (assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) @@ -496,7 +374,6 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) - (assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) diff --git a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json index 9fd5f5929..cee9d4b9b 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json @@ -1,7 +1,7 @@ { "auxiliaryInputRequested": { "smtlib2queries": { - "0x8704a7b848b706ef33cbfc06e4f185636f568a29621126b7244355dd0de956bb": "(set-option :produce-models true) + "0x2bd3d35071b94d7536d10aad691cee810d94841cca10218c3be21255e258aeb7": "(set-option :produce-models true) (set-logic ALL) (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) @@ -21,7 +21,6 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) - (assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) @@ -55,7 +54,6 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) - (assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) @@ -85,7 +83,6 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) - (assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) diff --git a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json index a9956d82b..9553a3cfb 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json @@ -1,127 +1,87 @@ { "auxiliaryInputRequested": { "smtlib2queries": { - "0xcbd85fe3127d1edfce70355ba6da5a3e9573873d8596ee8b1cfc2222af166628": "(set-option :timeout 1000) + "0x9cfcd53712a0be144c8e7983b3635498ead1af2624885fb89762eae8c43233e5": "(set-option :timeout 1000) (set-logic HORN) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) - - -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) - - -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) - - -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) +) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) +) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) (declare-fun |error_target_3| () Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) - - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) +)(assert +(forall ((UNUSED Bool)) (=> error_target_3 false))) (check-sat) " @@ -134,125 +94,85 @@ "formattedMessage": "Info: CHC: Requested query: (set-option :timeout 1000) (set-logic HORN) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) - - -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) - - -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) - - -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) +) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) +) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) (declare-fun |error_target_3| () Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) - - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) +)(assert +(forall ((UNUSED Bool)) (=> error_target_3 false))) (check-sat) @@ -261,125 +181,85 @@ "message": "CHC: Requested query: (set-option :timeout 1000) (set-logic HORN) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) - - -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) - - -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)))) - - -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1)))) - - +(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) +(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) +(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) +) +(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) +) +(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) +) +(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) +(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) +(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) +(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +) (declare-fun |error_target_3| () Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3))) - - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_0 Int) (x_5_1 Int) (x_5_2 Int)) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) +)(assert +(forall ((UNUSED Bool)) (=> error_target_3 false))) (check-sat) ", diff --git a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json index 9dff9a3bd..a3f4cc03d 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json @@ -1,7 +1,7 @@ { "auxiliaryInputRequested": { "smtlib2queries": { - "0x75b95497d56c30e254a59358d72ddd4e78f9e90db621cfe677e85d05b2252411": "(set-option :produce-models true) + "0x51b9801f3e8e35f2ff5f4538b0636fae81aa84a482cbb486ae4db63bede5ecb5": "(set-option :produce-models true) (set-logic ALL) (declare-fun |x_3_3| () Int) (declare-fun |error_0| () Int) @@ -21,133 +21,92 @@ (declare-fun |expr_7_0| () Int) (declare-fun |expr_8_0| () Int) (declare-fun |expr_9_1| () Bool) - (assert (and (and (and true true) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> (and true true) true) (and (= expr_8_0 0) (and (=> (and true true) (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_0) (and (and (>= x_3_0 0) (<= x_3_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true)))))))) (not expr_9_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_3_0)) (check-sat) (get-value (|EVALEXPR_0| )) ", - "0xf090d88ff3260790818d140ca909b8f4cb311a0d905e4e0318ad4dd790ff5f19": "(set-logic HORN) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) + "0xdb239809dcdaa42e35abca69790cb7e11b105f839e37faa8841f0dd9736688d7": "(set-logic HORN) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_14| (Int |abi_type| |crypto_type| |state_type| ) Bool) -(declare-fun |nondet_interface_1_C_14| (Int Int |abi_type| |crypto_type| |state_type| |state_type| ) Bool) -(declare-fun |summary_constructor_2_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (= error_0 0) (nondet_interface_1_C_14 error_0 this_0 abi_0 crypto_0 state_0 state_0)))) - - -(declare-fun |summary_3_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) -(declare-fun |summary_4_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (and (and (nondet_interface_1_C_14 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_1 x_3_0 state_2 x_3_1))) (nondet_interface_1_C_14 error_1 this_0 abi_0 crypto_0 state_0 state_2)))) - - -(declare-fun |block_5_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) -(declare-fun |block_6_f_12_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(block_5_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (and (and (block_5_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true)) true) (block_6_f_12_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) - - -(declare-fun |block_7_return_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) -(declare-fun |block_8_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (and (and (block_6_f_12_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> true true) (and (= expr_8_0 0) (and (=> true (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_1) (and (and (>= x_3_1 0) (<= x_3_1 115792089237316195423570985008687907853269984665640564039457584007913129639935)) true))))))) (and (and true (not expr_9_1)) (= error_1 1))) (block_8_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (block_8_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (summary_3_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (and (and (block_6_f_12_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (= error_1 error_0) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> true true) (and (= expr_8_0 0) (and (=> true (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_1) (and (and (>= x_3_1 0) (<= x_3_1 115792089237316195423570985008687907853269984665640564039457584007913129639935)) true)))))))) true) (block_7_return_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(=> (and (and (block_7_return_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) true) true) (summary_3_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)))) - - -(declare-fun |block_9_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) -(block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (summary_3_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_2 x_3_1 state_3 x_3_2) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true))))))) true) (summary_4_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_3 x_3_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (interface_0_C_14 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1)))) - - -(declare-fun |contract_initializer_10_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(declare-fun |contract_initializer_entry_11_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |contract_initializer_after_init_12_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (contract_initializer_entry_11_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (contract_initializer_after_init_12_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(declare-fun |implicit_constructor_entry_13_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| ) Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (implicit_constructor_entry_13_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2)))) - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (summary_constructor_2_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1)))) - - +(declare-fun |interface_0_C_14| (Int |abi_type| |crypto_type| |state_type|) Bool) +(declare-fun |nondet_interface_1_C_14| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |summary_constructor_2_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) +(=> (= error_0 0) (nondet_interface_1_C_14 error_0 this_0 abi_0 crypto_0 state_0 state_0))) +) +(declare-fun |summary_3_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int) Bool) +(declare-fun |summary_4_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) +(=> (and (and (nondet_interface_1_C_14 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_1 x_3_0 state_2 x_3_1))) (nondet_interface_1_C_14 error_1 this_0 abi_0 crypto_0 state_0 state_2))) +) +(declare-fun |block_5_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int) Bool) +(declare-fun |block_6_f_12_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) +(block_5_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) +(=> (and (and (block_5_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true)) true) (block_6_f_12_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))) +) +(declare-fun |block_7_return_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int) Bool) +(declare-fun |block_8_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) +(=> (and (and (block_6_f_12_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> true true) (and (= expr_8_0 0) (and (=> true (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_1) (and (and (>= x_3_1 0) (<= x_3_1 115792089237316195423570985008687907853269984665640564039457584007913129639935)) true))))))) (and (and true (not expr_9_1)) (= error_1 1))) (block_8_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) +(=> (block_8_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (summary_3_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) +(=> (and (and (block_6_f_12_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (= error_1 error_0) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> true true) (and (= expr_8_0 0) (and (=> true (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_1) (and (and (>= x_3_1 0) (<= x_3_1 115792089237316195423570985008687907853269984665640564039457584007913129639935)) true)))))))) true) (block_7_return_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) +(=> (and (and (block_7_return_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) true) true) (summary_3_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1))) +) +(declare-fun |block_9_function_f__13_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| Int |state_type| Int) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) +(block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) +(=> (and (and (block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (summary_3_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_2 x_3_1 state_3 x_3_2) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true))))))) true) (summary_4_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_3 x_3_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) +(=> (and (and (interface_0_C_14 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1))) +) +(declare-fun |contract_initializer_10_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(declare-fun |contract_initializer_entry_11_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |contract_initializer_after_init_12_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_entry_11_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (contract_initializer_after_init_12_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(declare-fun |implicit_constructor_entry_13_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (implicit_constructor_entry_13_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) +) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) +(=> (and (and (summary_constructor_2_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1))) +) (declare-fun |error_target_3| () Bool) -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (interface_0_C_14 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (= error_0 1))) error_target_3))) - - - -(assert -(forall ( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_7_0 Int) (expr_8_0 Int) (expr_9_1 Bool) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) +(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) +(=> (and (and (interface_0_C_14 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (= error_0 1))) error_target_3)) +)(assert +(forall ((UNUSED Bool)) (=> error_target_3 false))) (check-sat) " diff --git a/test/libsolidity/smtCheckerTests/invariants/array_access.sol b/test/libsolidity/smtCheckerTests/invariants/array_access.sol new file mode 100644 index 000000000..be3ad2548 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/invariants/array_access.sol @@ -0,0 +1,20 @@ +contract C { + int[2] a; + + constructor() { + a[0] = 1; + a[1] = 2; + } + + function i() public view { + assert(a[1] > a[0]); + } +} +// ==== +// SMTEngine: chc +// SMTIgnoreInv: no +// SMTSolvers: eld +// SMTTargets: assert +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1180: Contract invariant(s) for :C:\n((a.length = 2) && ((a[1] - a[0]) >= 1))\n diff --git a/test/libsolidity/smtCheckerTests/invariants/struct_access.sol b/test/libsolidity/smtCheckerTests/invariants/struct_access.sol new file mode 100644 index 000000000..afc4eaed7 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/invariants/struct_access.sol @@ -0,0 +1,15 @@ +contract C { + struct S { int x; } + S s = S(1); + + function i() public view { + assert(s.x > 0); + } +} +// ==== +// SMTEngine: chc +// SMTIgnoreInv: no +// SMTSolvers: eld +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1180: Contract invariant(s) for :C:\n(s.x = 1)\n From 9a1d7406bb742f808f1822be8baba5e16924357f Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Thu, 12 Oct 2023 17:46:03 +0200 Subject: [PATCH 0226/1340] Add --asm-json option in assembler mode. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: r0qs Co-authored-by: Kamil Śliwak --- Changelog.md | 1 + libevmasm/Assembly.cpp | 23 +- libsolidity/interface/StandardCompiler.cpp | 2 +- libyul/Object.cpp | 30 ++ libyul/Object.h | 8 + libyul/YulStack.cpp | 9 +- libyul/YulStack.h | 7 +- solc/CommandLineInterface.cpp | 28 +- solc/CommandLineParser.cpp | 1 + .../args | 1 + .../err | 1 + .../exit | 1 + .../stdin | 17 + .../asm_json_yul_export_evm_asm_import/args | 1 + .../asm_json_yul_export_evm_asm_import/output | 39 ++ .../asm_json_yul_export_evm_asm_import/stdin | 36 ++ .../args | 1 + .../err | 1 + .../exit | 1 + .../stdin | 6 + .../args | 1 + .../output | 426 ++++++++++++++++++ .../stdin | 51 +++ .../args | 1 + .../output | 384 ++++++++++++++++ .../stdin | 40 ++ .../args | 1 + .../output | 384 ++++++++++++++++ .../stdin | 34 ++ .../strict_asm_asm_json_yul_verbatim/args | 1 + .../strict_asm_asm_json_yul_verbatim/output | 18 + .../strict_asm_asm_json_yul_verbatim/stdin | 4 + .../strict_asm_output_selection_invalid/err | 2 +- test/libyul/ObjectCompilerTest.cpp | 5 +- .../libyul/objectCompiler/sourceLocations.yul | 14 +- test/solc/CommandLineParser.cpp | 2 + 36 files changed, 1556 insertions(+), 26 deletions(-) create mode 100644 test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/args create mode 100644 test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/err create mode 100644 test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/exit create mode 100644 test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/stdin create mode 100644 test/cmdlineTests/asm_json_yul_export_evm_asm_import/args create mode 100644 test/cmdlineTests/asm_json_yul_export_evm_asm_import/output create mode 100644 test/cmdlineTests/asm_json_yul_export_evm_asm_import/stdin create mode 100644 test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/args create mode 100644 test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/err create mode 100644 test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/exit create mode 100644 test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/stdin create mode 100644 test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/args create mode 100644 test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/output create mode 100644 test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/stdin create mode 100644 test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/args create mode 100644 test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/output create mode 100644 test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/stdin create mode 100644 test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/args create mode 100644 test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/output create mode 100644 test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/stdin create mode 100644 test/cmdlineTests/strict_asm_asm_json_yul_verbatim/args create mode 100644 test/cmdlineTests/strict_asm_asm_json_yul_verbatim/output create mode 100644 test/cmdlineTests/strict_asm_asm_json_yul_verbatim/stdin diff --git a/Changelog.md b/Changelog.md index e67cf0f07..9c9a9e8fd 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,6 +14,7 @@ Compiler Features: * SMTChecker: Replace CVC4 as a possible BMC backend with cvc5. * Standard JSON Interface: Do not perform IR optimization when only unoptimized IR is requested. * Yul Optimizer: The optimizer now treats some previously unrecognized identical literals as identical. + * Commandline Interface: Allow the use of ``--asm-json`` output option in assembler mode to export EVM assembly of the contracts in JSON format. Bugfixes: diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 356a2818a..f9b800c90 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -479,8 +479,18 @@ Json Assembly::assemblyJSON(std::map const& _sourceIndice { root["sourceList"] = Json::array(); Json& jsonSourceList = root["sourceList"]; - for (auto const& [name, index]: _sourceIndices) - jsonSourceList[index] = name; + unsigned maxSourceIndex = 0; + for (auto const& [sourceName, sourceIndex]: _sourceIndices) + { + maxSourceIndex = std::max(sourceIndex, maxSourceIndex); + jsonSourceList[sourceIndex] = sourceName; + } + solAssert(maxSourceIndex + 1 >= _sourceIndices.size()); + solRequire( + _sourceIndices.size() == 0 || _sourceIndices.size() == maxSourceIndex + 1, + AssemblyImportException, + "The 'sourceList' array contains invalid 'null' item." + ); } if (!m_data.empty() || !m_subs.empty()) @@ -522,7 +532,14 @@ std::pair, std::vector> Assembly::fromJSO { solRequire(_json["sourceList"].is_array(), AssemblyImportException, "Optional member 'sourceList' is not an array."); for (Json const& sourceName: _json["sourceList"]) - solRequire(sourceName.is_string(), AssemblyImportException, "The 'sourceList' array contains an item that is not a string."); + { + solRequire(!sourceName.is_null(), AssemblyImportException, "The 'sourceList' array contains invalid 'null' item."); + solRequire( + sourceName.is_string(), + AssemblyImportException, + "The 'sourceList' array contains an item that is not a string." + ); + } } } else diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index cb0c81268..e4b9f9f7a 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1694,7 +1694,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "irOptimized", wildcardMatchesExperimental)) output["contracts"][sourceName][contractName]["irOptimized"] = stack.print(); if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "evm.assembly", wildcardMatchesExperimental)) - output["contracts"][sourceName][contractName]["evm"]["assembly"] = object.assembly; + output["contracts"][sourceName][contractName]["evm"]["assembly"] = object.assembly->assemblyString(stack.debugInfoSelection()); return output; } diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 736c1bb84..989e7ce80 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -160,3 +160,33 @@ std::vector Object::pathToSubObject(std::string_view _qualifiedName) con return path; } + +void Object::collectSourceIndices(std::map& _indices) const +{ + if (debugData && debugData->sourceNames.has_value()) + for (auto const& [sourceIndex, sourceName]: debugData->sourceNames.value()) + { + solAssert(_indices.count(*sourceName) == 0 || _indices[*sourceName] == sourceIndex); + _indices[*sourceName] = sourceIndex; + } + for (std::shared_ptr const& subNode: subObjects) + if (auto subObject = dynamic_cast(subNode.get())) + subObject->collectSourceIndices(_indices); +} + +bool Object::hasContiguousSourceIndices() const +{ + std::map sourceIndices; + collectSourceIndices(sourceIndices); + + unsigned maxSourceIndex = 0; + std::set indices; + for (auto const& [sources, sourceIndex]: sourceIndices) + { + maxSourceIndex = std::max(sourceIndex, maxSourceIndex); + indices.insert(sourceIndex); + } + + solAssert(maxSourceIndex + 1 >= indices.size()); + return indices.size() == 0 || indices.size() == maxSourceIndex + 1; +} diff --git a/libyul/Object.h b/libyul/Object.h index 4e891c264..c419a6d55 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -129,6 +129,14 @@ struct Object: public ObjectNode std::shared_ptr debugData; + /// Collects names of all Solidity source units present in the debug data + /// of the Yul object (including sub-objects) and their assigned indices. + /// @param _indices map that will be filled with source indices of the current Yul object & its sub-objects. + void collectSourceIndices(std::map& _indices) const; + + /// @returns true, if the range of source indices starts at zero and is contiguous, false otherwise. + bool hasContiguousSourceIndices() const; + /// @returns the name of the special metadata data object. static std::string metadataName() { return ".metadata"; } }; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 223d6c04a..b9fc6388c 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -15,10 +15,6 @@ along with solidity. If not, see . */ // SPDX-License-Identifier: GPL-3.0 -/** - * Full assembly stack that can support EVM-assembly and Yul as input and EVM, EVM1.5 - */ - #include @@ -64,7 +60,6 @@ Dialect const& languageToDialect(YulStack::Language _language, EVMVersion _versi } - CharStream const& YulStack::charStream(std::string const& _sourceName) const { yulAssert(m_charStream, ""); @@ -274,7 +269,7 @@ YulStack::assembleWithDeployed(std::optional _deployName) { creationObject.bytecode = std::make_shared(creationAssembly->assemble()); yulAssert(creationObject.bytecode->immutableReferences.empty(), "Leftover immutables."); - creationObject.assembly = creationAssembly->assemblyString(m_debugInfoSelection); + creationObject.assembly = creationAssembly; creationObject.sourceMappings = std::make_unique( evmasm::AssemblyItem::computeSourceMapping( creationAssembly->items(), @@ -285,7 +280,7 @@ YulStack::assembleWithDeployed(std::optional _deployName) if (deployedAssembly) { deployedObject.bytecode = std::make_shared(deployedAssembly->assemble()); - deployedObject.assembly = deployedAssembly->assemblyString(m_debugInfoSelection); + deployedObject.assembly = deployedAssembly; deployedObject.sourceMappings = std::make_unique( evmasm::AssemblyItem::computeSourceMapping( deployedAssembly->items(), diff --git a/libyul/YulStack.h b/libyul/YulStack.h index c6d78a115..f547ef770 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -16,7 +16,7 @@ */ // SPDX-License-Identifier: GPL-3.0 /** - * Full assembly stack that can support EVM-assembly and Yul as input and EVM. + * Full assembly stack that can support Yul as input. */ #pragma once @@ -55,7 +55,7 @@ class AbstractAssembly; struct MachineAssemblyObject { std::shared_ptr bytecode; - std::string assembly; + std::shared_ptr assembly; std::unique_ptr sourceMappings; }; @@ -137,9 +137,12 @@ class YulStack: public langutil::CharStreamProvider langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ) const; Json astJson() const; + /// Return the parsed and analyzed object. std::shared_ptr parserResult() const; + langutil::DebugInfoSelection debugInfoSelection() const { return m_debugInfoSelection; } + private: bool parse(std::string const& _sourceName, std::string const& _source); bool analyzeParsed(); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 5d0272dfa..135185840 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -177,7 +177,7 @@ void CommandLineInterface::handleEVMAssembly(std::string const& _contract) std::string assembly; if (m_options.compiler.outputs.asmJson) - assembly = util::jsonPrint(removeNullMembers(m_assemblyStack->assemblyJSON(_contract)), m_options.formatting.json); + assembly = util::jsonPrint(m_assemblyStack->assemblyJSON(_contract), m_options.formatting.json); else assembly = m_assemblyStack->assemblyString(_contract, m_fileReader.sourceUnits()); @@ -1197,6 +1197,17 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y successful = false; else stack.optimize(); + + if (successful && m_options.compiler.outputs.asmJson) + { + std::shared_ptr result = stack.parserResult(); + if (result && !result->hasContiguousSourceIndices()) + solThrow( + CommandLineExecutionError, + "Generating the assembly JSON output was not possible. " + "Source indices provided in the @use-src annotation in the Yul input do not start at 0 or are not contiguous." + ); + } } for (auto const& sourceAndStack: yulStacks) @@ -1256,11 +1267,22 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y if (m_options.compiler.outputs.asm_) { sout() << std::endl << "Text representation:" << std::endl; - if (!object.assembly.empty()) - sout() << object.assembly << std::endl; + std::string assemblyText{object.assembly->assemblyString(stack.debugInfoSelection())}; + if (!assemblyText.empty()) + sout() << assemblyText << std::endl; else report(Error::Severity::Info, "No text representation found."); } + if (m_options.compiler.outputs.asmJson) + { + sout() << std::endl << "EVM assembly:" << std::endl; + std::map sourceIndices; + stack.parserResult()->collectSourceIndices(sourceIndices); + sout() << util::jsonPrint( + object.assembly->assemblyJSON(sourceIndices), + m_options.formatting.json + ) << std::endl; + } } } diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 2697f7ebd..881c656da 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -472,6 +472,7 @@ void CommandLineParser::parseOutputSelection() CompilerOutputs::componentName(&CompilerOutputs::binary), CompilerOutputs::componentName(&CompilerOutputs::irOptimized), CompilerOutputs::componentName(&CompilerOutputs::astCompactJson), + CompilerOutputs::componentName(&CompilerOutputs::asmJson), }; static std::set const evmAssemblyJsonImportModeOutputs = { CompilerOutputs::componentName(&CompilerOutputs::asm_), diff --git a/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/args b/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/args new file mode 100644 index 000000000..c1bc80dab --- /dev/null +++ b/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 --import-asm-json - diff --git a/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/err b/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/err new file mode 100644 index 000000000..73f36f971 --- /dev/null +++ b/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/err @@ -0,0 +1 @@ +Error: Assembly Import Error: The 'sourceList' array contains invalid 'null' item. diff --git a/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/exit b/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/stdin b/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/stdin new file mode 100644 index 000000000..923376f40 --- /dev/null +++ b/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/stdin @@ -0,0 +1,17 @@ +{ + ".code": + [ + { + "begin": -1, + "end": -1, + "name": "STOP", + "source": -1 + } + ], + "sourceList": + [ + null, + null, + "L0.sol" + ] +} diff --git a/test/cmdlineTests/asm_json_yul_export_evm_asm_import/args b/test/cmdlineTests/asm_json_yul_export_evm_asm_import/args new file mode 100644 index 000000000..15c962831 --- /dev/null +++ b/test/cmdlineTests/asm_json_yul_export_evm_asm_import/args @@ -0,0 +1 @@ +--import-asm-json - --opcodes --asm --bin --asm-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/asm_json_yul_export_evm_asm_import/output b/test/cmdlineTests/asm_json_yul_export_evm_asm_import/output new file mode 100644 index 000000000..9ebef4142 --- /dev/null +++ b/test/cmdlineTests/asm_json_yul_export_evm_asm_import/output @@ -0,0 +1,39 @@ +Opcodes: +PUSH1 0x5 PUSH0 SSTORE STOP +Binary: +60055f5500 +EVM assembly: +{ + ".code": [ + { + "begin": -1, + "end": -1, + "name": "PUSHSIZE", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "0" + }, + { + "begin": -1, + "end": -1, + "name": "SSTORE", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "STOP", + "source": -1 + } + ], + "sourceList": [ + "L0.sol", + "L1.sol", + "L2.sol" + ] +} diff --git a/test/cmdlineTests/asm_json_yul_export_evm_asm_import/stdin b/test/cmdlineTests/asm_json_yul_export_evm_asm_import/stdin new file mode 100644 index 000000000..840660f6b --- /dev/null +++ b/test/cmdlineTests/asm_json_yul_export_evm_asm_import/stdin @@ -0,0 +1,36 @@ +{ + ".code": + [ + { + "begin": -1, + "end": -1, + "name": "PUSHSIZE", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "0" + }, + { + "begin": -1, + "end": -1, + "name": "SSTORE", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "STOP", + "source": -1 + } + ], + "sourceList": + [ + "L0.sol", + "L1.sol", + "L2.sol" + ] +} diff --git a/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/args b/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/args new file mode 100644 index 000000000..bf9bf8851 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/args @@ -0,0 +1 @@ +--strict-assembly - --asm-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/err b/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/err new file mode 100644 index 000000000..129c4a8cc --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/err @@ -0,0 +1 @@ +Error: Generating the assembly JSON output was not possible. Source indices provided in the @use-src annotation in the Yul input do not start at 0 or are not contiguous. diff --git a/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/exit b/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/stdin b/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/stdin new file mode 100644 index 000000000..5b36b4118 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_arbitrary_source_index/stdin @@ -0,0 +1,6 @@ +/// @use-src 2:"L0.sol" +object "L0" { + code { + sstore(0, datasize("L0")) + } +} diff --git a/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/args b/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/args new file mode 100644 index 000000000..bf9bf8851 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/args @@ -0,0 +1 @@ +--strict-assembly - --asm-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/output b/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/output new file mode 100644 index 000000000..dfa765683 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/output @@ -0,0 +1,426 @@ + +======= (EVM) ======= + +EVM assembly: +{ + ".code": [ + { + "begin": 41, + "end": 137, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 41, + "end": 137, + "name": "DUP1", + "source": 0 + }, + { + "begin": 41, + "end": 137, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 41, + "end": 137, + "name": "PUSHSIZE", + "source": 0 + }, + { + "begin": 41, + "end": 137, + "name": "PUSH", + "source": 0, + "value": "1" + }, + { + "begin": 41, + "end": 137, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 41, + "end": 137, + "name": "PUSH [$]", + "source": 0, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": 41, + "end": 137, + "name": "PUSH", + "source": 0, + "value": "2" + }, + { + "begin": 41, + "end": 137, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 41, + "end": 137, + "name": "PUSH #[$]", + "source": 0, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": 41, + "end": 137, + "name": "PUSH", + "source": 0, + "value": "3" + }, + { + "begin": 41, + "end": 137, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 41, + "end": 137, + "name": "PUSH [$]", + "source": 0, + "value": "000000000000000000000000000000000000000000000000ffffffffffffffff" + }, + { + "begin": 41, + "end": 137, + "name": "PUSH", + "source": 0, + "value": "4" + }, + { + "begin": 41, + "end": 137, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 41, + "end": 137, + "name": "PUSH #[$]", + "source": 0, + "value": "000000000000000000000000000000000000000000000000ffffffffffffffff" + }, + { + "begin": 41, + "end": 137, + "name": "PUSH", + "source": 0, + "value": "5" + }, + { + "begin": 41, + "end": 137, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 41, + "end": 137, + "name": "PUSH [$]", + "source": 0, + "value": "000000000000000000000000000000000000000000000000fffffffffffffffe" + }, + { + "begin": 41, + "end": 137, + "name": "PUSH", + "source": 0, + "value": "6" + }, + { + "begin": 41, + "end": 137, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 41, + "end": 137, + "name": "PUSH #[$]", + "source": 0, + "value": "000000000000000000000000000000000000000000000000fffffffffffffffe" + }, + { + "begin": 41, + "end": 137, + "name": "PUSH", + "source": 0, + "value": "7" + }, + { + "begin": 41, + "end": 137, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 41, + "end": 137, + "name": "PUSH [$]", + "source": 0, + "value": "000000000000000000000000000000000000000000000000fffffffffffffffd" + }, + { + "begin": 41, + "end": 137, + "name": "PUSH", + "source": 0, + "value": "8" + }, + { + "begin": 41, + "end": 137, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 41, + "end": 137, + "name": "PUSH #[$]", + "source": 0, + "value": "000000000000000000000000000000000000000000000000fffffffffffffffd" + }, + { + "begin": 41, + "end": 137, + "name": "PUSH", + "source": 0, + "value": "9" + }, + { + "begin": 41, + "end": 137, + "name": "SSTORE", + "source": 0 + }, + { + "begin": -1, + "end": -1, + "name": "STOP", + "source": -1 + } + ], + ".data": { + "0": { + ".code": [ + { + "begin": 57, + "end": 158, + "name": "PUSH [$]", + "source": 1, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": 57, + "end": 158, + "name": "PUSH", + "source": 1, + "value": "A" + }, + { + "begin": 57, + "end": 158, + "name": "SSTORE", + "source": 1 + }, + { + "begin": 57, + "end": 158, + "name": "PUSH #[$]", + "source": 1, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": 57, + "end": 158, + "name": "PUSH", + "source": 1, + "value": "B" + }, + { + "begin": 57, + "end": 158, + "name": "SSTORE", + "source": 1 + }, + { + "begin": 57, + "end": 158, + "name": "PUSH [$]", + "source": 1, + "value": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "begin": 57, + "end": 158, + "name": "PUSH", + "source": 1, + "value": "C" + }, + { + "begin": 57, + "end": 158, + "name": "SSTORE", + "source": 1 + }, + { + "begin": 57, + "end": 158, + "name": "PUSH #[$]", + "source": 1, + "value": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "begin": 57, + "end": 158, + "name": "PUSH", + "source": 1, + "value": "D" + }, + { + "begin": 57, + "end": 158, + "name": "SSTORE", + "source": 1 + }, + { + "begin": 57, + "end": 158, + "name": "PUSH [$]", + "source": 1, + "value": "000000000000000000000000000000000000000000000000ffffffffffffffff" + }, + { + "begin": 57, + "end": 158, + "name": "PUSH", + "source": 1, + "value": "E" + }, + { + "begin": 57, + "end": 158, + "name": "SSTORE", + "source": 1 + }, + { + "begin": 57, + "end": 158, + "name": "PUSH #[$]", + "source": 1, + "value": "000000000000000000000000000000000000000000000000ffffffffffffffff" + }, + { + "begin": 57, + "end": 158, + "name": "PUSH", + "source": 1, + "value": "F" + }, + { + "begin": 57, + "end": 158, + "name": "SSTORE", + "source": 1 + }, + { + "begin": -1, + "end": -1, + "name": "STOP", + "source": -1 + } + ], + ".data": { + "0": { + ".code": [ + { + "begin": 41, + "end": 100, + "name": "PUSH [$]", + "source": 2, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": 41, + "end": 100, + "name": "PUSH", + "source": 2, + "value": "10" + }, + { + "begin": 41, + "end": 100, + "name": "SSTORE", + "source": 2 + }, + { + "begin": 41, + "end": 100, + "name": "PUSH #[$]", + "source": 2, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": 41, + "end": 100, + "name": "PUSH", + "source": 2, + "value": "11" + }, + { + "begin": 41, + "end": 100, + "name": "SSTORE", + "source": 2 + }, + { + "begin": -1, + "end": -1, + "name": "STOP", + "source": -1 + } + ], + ".data": { + "0": { + ".code": [ + { + "begin": -1, + "end": -1, + "name": "INVALID", + "source": -1 + } + ] + } + } + }, + "1": { + ".code": [ + { + "begin": -1, + "end": -1, + "name": "INVALID", + "source": -1 + } + ] + } + } + }, + "ACAF3289D7B601CBD114FB36C4D29C85BBFD5E133F14CB355C3FD8D99367964F": "48656c6c6f2c20576f726c6421" + }, + "sourceList": [ + "a.sol", + "b.sol", + "c.sol", + "d.sol", + "e.sol" + ] +} diff --git a/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/stdin b/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/stdin new file mode 100644 index 000000000..01db34d6f --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/stdin @@ -0,0 +1,51 @@ +/// @use-src 0:"a.sol" +object "A" { + code { + /// @src 0:41:137 "contract A {..." + sstore(0, dataoffset("A")) + sstore(1, datasize("A")) + sstore(2, dataoffset("B")) + sstore(3, datasize("B")) + sstore(4, dataoffset("B.C")) + sstore(5, datasize("B.C")) + sstore(6, dataoffset("B.E")) + sstore(7, datasize("B.E")) + sstore(8, dataoffset("B.C.D")) + sstore(9, datasize("B.C.D")) + } + + data "data1" "Hello, World!" + + /// @use-src 1:"b.sol" + object "B" { + code { + /// @src 1:57:158 "contract B {..." + sstore(10, dataoffset("C")) + sstore(11, datasize("C")) + sstore(12, dataoffset("E")) + sstore(13, datasize("E")) + sstore(14, dataoffset("C.D")) + sstore(15, datasize("C.D")) + } + /// @use-src 2:"c.sol" + object "C" { + code { + /// @src 2:41:100 "contract C {..." + sstore(16, dataoffset("D")) + sstore(17, datasize("D")) + } + /// @use-src 3:"d.sol" + object "D" { + code { + invalid() + } + } + } + /// @use-src 4:"e.sol" + object "E" { + code { + invalid() + } + } + } +} diff --git a/test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/args b/test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/args new file mode 100644 index 000000000..bf9bf8851 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/args @@ -0,0 +1 @@ +--strict-assembly - --asm-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/output b/test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/output new file mode 100644 index 000000000..85642e709 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/output @@ -0,0 +1,384 @@ + +======= (EVM) ======= + +EVM assembly: +{ + ".code": [ + { + "begin": 0, + "end": 125, + "name": "PUSH", + "source": 0, + "value": "80" + }, + { + "begin": 0, + "end": 125, + "name": "DUP1", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH", + "source": 0, + "value": "40" + }, + { + "begin": 0, + "end": 125, + "name": "MSTORE", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "CALLVALUE", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH [tag]", + "source": 0, + "value": "1" + }, + { + "begin": 0, + "end": 125, + "name": "JUMPI", + "source": 0 + }, + { + "begin": 56, + "end": 57, + "name": "PUSH", + "source": 0, + "value": "2" + }, + { + "begin": 33, + "end": 34, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 0, + "end": 125, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 33, + "end": 34, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 33, + "end": 34, + "name": "PUSH", + "source": 0, + "value": "1" + }, + { + "begin": 0, + "end": 125, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH #[$]", + "source": 0, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": 0, + "end": 125, + "name": "SWAP1", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "DUP2", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH [$]", + "source": 0, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": 0, + "end": 125, + "name": "DUP3", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "CODECOPY", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "RETURN", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "tag", + "source": 0, + "value": "1" + }, + { + "begin": 0, + "end": 125, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 0, + "end": 125, + "name": "DUP1", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "REVERT", + "source": 0 + } + ], + ".data": { + "0": { + ".auxdata": "1234abcd", + ".code": [ + { + "begin": 0, + "end": 125, + "name": "PUSH", + "source": 0, + "value": "80" + }, + { + "begin": 0, + "end": 125, + "name": "DUP1", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH", + "source": 0, + "value": "40" + }, + { + "begin": 0, + "end": 125, + "name": "MSTORE", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH", + "source": 0, + "value": "4" + }, + { + "begin": 0, + "end": 125, + "name": "CALLDATASIZE", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "LT", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "ISZERO", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH [tag]", + "source": 0, + "value": "1" + }, + { + "begin": 0, + "end": 125, + "name": "JUMPI", + "source": 0 + }, + { + "begin": -1, + "end": -1, + "name": "tag", + "source": -1, + "value": "2" + }, + { + "begin": -1, + "end": -1, + "name": "JUMPDEST", + "source": -1 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 0, + "end": 125, + "name": "DUP1", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "REVERT", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "tag", + "source": 0, + "value": "1" + }, + { + "begin": 0, + "end": 125, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 0, + "end": 125, + "name": "CALLDATALOAD", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH", + "source": 0, + "value": "E0" + }, + { + "begin": 0, + "end": 125, + "name": "SHR", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH", + "source": 0, + "value": "B4F40C61" + }, + { + "begin": 0, + "end": 125, + "name": "SUB", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH [tag]", + "source": 0, + "value": "2" + }, + { + "begin": 0, + "end": 125, + "name": "JUMPI", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "PUSH", + "source": 0, + "value": "20" + }, + { + "begin": 0, + "end": 125, + "name": "SWAP1", + "source": 0 + }, + { + "begin": 40, + "end": 57, + "name": "PUSH", + "source": 0, + "value": "1" + }, + { + "begin": 0, + "end": 125, + "name": "SLOAD", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "DUP2", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "MSTORE", + "source": 0 + }, + { + "begin": 0, + "end": 125, + "name": "RETURN", + "source": 0 + } + ] + } + }, + "sourceList": [ + "state_var_initialization.sol" + ] +} diff --git a/test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/stdin b/test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/stdin new file mode 100644 index 000000000..d96989ec8 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_with_debug_info_annotations/stdin @@ -0,0 +1,40 @@ +/// @use-src 0:"state_var_initialization.sol" +object "C_23" { + code { + { + /// @src 0:0:125 "contract C {..." + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + sstore(/** @src 0:33:34 "1" */ 0x00, /** @src 0:56:57 "2" */ 0x02) + /// @src 0:0:125 "contract C {..." + sstore(/** @src 0:33:34 "1" */ 0x01, 0x00) + /// @src 0:0:125 "contract C {..." + let _2 := datasize("C_23_deployed") + codecopy(_1, dataoffset("C_23_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"state_var_initialization.sol" + object "C_23_deployed" { + code { + { + /// @src 0:0:125 "contract C {..." + let _1 := memoryguard(0x80) + mstore(64, _1) + if iszero(lt(calldatasize(), 4)) + { + let _2 := 0 + switch shr(224, calldataload(_2)) + case 0xb4f40c61 { + mstore(_1, sload(/** @src 0:40:57 "uint public k = 2" */ 1)) + /// @src 0:0:125 "contract C {..." + return(_1, 32) + } + } + revert(0, 0) + } + } + data ".metadata" hex"1234abcd" + } +} diff --git a/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/args b/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/args new file mode 100644 index 000000000..bf9bf8851 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/args @@ -0,0 +1 @@ +--strict-assembly - --asm-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/output b/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/output new file mode 100644 index 000000000..25fb482d4 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/output @@ -0,0 +1,384 @@ + +======= (EVM) ======= + +EVM assembly: +{ + ".code": [ + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "80" + }, + { + "begin": -1, + "end": -1, + "name": "DUP1", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "40" + }, + { + "begin": -1, + "end": -1, + "name": "MSTORE", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "CALLVALUE", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH [tag]", + "source": -1, + "value": "1" + }, + { + "begin": -1, + "end": -1, + "name": "JUMPI", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "2" + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "0" + }, + { + "begin": -1, + "end": -1, + "name": "SSTORE", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "0" + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "1" + }, + { + "begin": -1, + "end": -1, + "name": "SSTORE", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH #[$]", + "source": -1, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": -1, + "end": -1, + "name": "SWAP1", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "DUP2", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH [$]", + "source": -1, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": -1, + "end": -1, + "name": "DUP3", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "CODECOPY", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "RETURN", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "tag", + "source": -1, + "value": "1" + }, + { + "begin": -1, + "end": -1, + "name": "JUMPDEST", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "0" + }, + { + "begin": -1, + "end": -1, + "name": "DUP1", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "REVERT", + "source": -1 + } + ], + ".data": { + "0": { + ".auxdata": "1234abcd", + ".code": [ + { + "begin": 469, + "end": 486, + "name": "PUSH", + "source": -1, + "value": "80" + }, + { + "begin": 503, + "end": 517, + "name": "DUP1", + "source": -1 + }, + { + "begin": 510, + "end": 512, + "name": "PUSH", + "source": -1, + "value": "40" + }, + { + "begin": 503, + "end": 517, + "name": "MSTORE", + "source": -1 + }, + { + "begin": 563, + "end": 564, + "name": "PUSH", + "source": -1, + "value": "4" + }, + { + "begin": 547, + "end": 561, + "name": "CALLDATASIZE", + "source": -1 + }, + { + "begin": 544, + "end": 565, + "name": "LT", + "source": -1 + }, + { + "begin": 537, + "end": 566, + "name": "ISZERO", + "source": -1 + }, + { + "begin": 534, + "end": 832, + "name": "PUSH [tag]", + "source": -1, + "value": "1" + }, + { + "begin": 534, + "end": 832, + "name": "JUMPI", + "source": -1 + }, + { + "begin": 427, + "end": 885, + "name": "tag", + "source": -1, + "value": "2" + }, + { + "begin": 427, + "end": 885, + "name": "JUMPDEST", + "source": -1 + }, + { + "begin": 859, + "end": 860, + "name": "PUSH", + "source": -1, + "value": "0" + }, + { + "begin": 849, + "end": 861, + "name": "DUP1", + "source": -1 + }, + { + "begin": 849, + "end": 861, + "name": "REVERT", + "source": -1 + }, + { + "begin": 583, + "end": 832, + "name": "tag", + "source": -1, + "value": "1" + }, + { + "begin": 583, + "end": 832, + "name": "JUMPDEST", + "source": -1 + }, + { + "begin": 615, + "end": 616, + "name": "PUSH", + "source": -1, + "value": "0" + }, + { + "begin": 653, + "end": 669, + "name": "CALLDATALOAD", + "source": -1 + }, + { + "begin": 648, + "end": 651, + "name": "PUSH", + "source": -1, + "value": "E0" + }, + { + "begin": 644, + "end": 670, + "name": "SHR", + "source": -1 + }, + { + "begin": 696, + "end": 706, + "name": "PUSH", + "source": -1, + "value": "B4F40C61" + }, + { + "begin": 691, + "end": 814, + "name": "SUB", + "source": -1 + }, + { + "begin": 583, + "end": 832, + "name": "PUSH [tag]", + "source": -1, + "value": "2" + }, + { + "begin": 691, + "end": 814, + "name": "JUMPI", + "source": -1 + }, + { + "begin": 789, + "end": 791, + "name": "PUSH", + "source": -1, + "value": "20" + }, + { + "begin": 744, + "end": 752, + "name": "SWAP1", + "source": -1 + }, + { + "begin": 750, + "end": 751, + "name": "PUSH", + "source": -1, + "value": "1" + }, + { + "begin": 744, + "end": 752, + "name": "SLOAD", + "source": -1 + }, + { + "begin": 733, + "end": 753, + "name": "DUP2", + "source": -1 + }, + { + "begin": 733, + "end": 753, + "name": "MSTORE", + "source": -1 + }, + { + "begin": 778, + "end": 792, + "name": "RETURN", + "source": -1 + } + ] + } + }, + "sourceList": [ + "abc.sol" + ] +} diff --git a/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/stdin b/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/stdin new file mode 100644 index 000000000..72c1b650c --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/stdin @@ -0,0 +1,34 @@ +/// @use-src 0: "abc.sol" +object "C_23" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + sstore(0x00, 0x02) + sstore(0x01, 0x00) + let _2 := datasize("C_23_deployed") + codecopy(_1, dataoffset("C_23_deployed"), _2) + return(_1, _2) + } + } + object "C_23_deployed" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if iszero(lt(calldatasize(), 4)) + { + let _2 := 0 + switch shr(224, calldataload(_2)) + case 0xb4f40c61 { + mstore(_1, sload(1)) + return(_1, 32) + } + } + revert(0, 0) + } + } + data ".metadata" hex"1234abcd" + } +} diff --git a/test/cmdlineTests/strict_asm_asm_json_yul_verbatim/args b/test/cmdlineTests/strict_asm_asm_json_yul_verbatim/args new file mode 100644 index 000000000..bf9bf8851 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_yul_verbatim/args @@ -0,0 +1 @@ +--strict-assembly - --asm-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/strict_asm_asm_json_yul_verbatim/output b/test/cmdlineTests/strict_asm_asm_json_yul_verbatim/output new file mode 100644 index 000000000..454f4a6d2 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_yul_verbatim/output @@ -0,0 +1,18 @@ + +======= (EVM) ======= + +EVM assembly: +{ + ".code": [ + { + "begin": -1, + "end": -1, + "name": "VERBATIM", + "source": -1, + "value": "78797a" + } + ], + "sourceList": [ + "abc.sol" + ] +} diff --git a/test/cmdlineTests/strict_asm_asm_json_yul_verbatim/stdin b/test/cmdlineTests/strict_asm_asm_json_yul_verbatim/stdin new file mode 100644 index 000000000..2dab36854 --- /dev/null +++ b/test/cmdlineTests/strict_asm_asm_json_yul_verbatim/stdin @@ -0,0 +1,4 @@ +/// @use-src 0: "abc.sol" +{ + verbatim_0i_0o("xyz") +} diff --git a/test/cmdlineTests/strict_asm_output_selection_invalid/err b/test/cmdlineTests/strict_asm_output_selection_invalid/err index 81d6eff8a..90fd94704 100644 --- a/test/cmdlineTests/strict_asm_output_selection_invalid/err +++ b/test/cmdlineTests/strict_asm_output_selection_invalid/err @@ -1 +1 @@ -Error: The following outputs are not supported in assembler mode: --abi, --asm-json, --bin-runtime, --devdoc, --hashes, --ir, --metadata, --opcodes, --storage-layout, --userdoc. +Error: The following outputs are not supported in assembler mode: --abi, --bin-runtime, --devdoc, --hashes, --ir, --metadata, --opcodes, --storage-layout, --userdoc. diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp index 65ff18a76..5d6dd1b23 100644 --- a/test/libyul/ObjectCompilerTest.cpp +++ b/test/libyul/ObjectCompilerTest.cpp @@ -26,8 +26,9 @@ #include -#include +#include #include +#include #include #include @@ -83,7 +84,7 @@ TestCase::TestResult ObjectCompilerTest::run(std::ostream& _stream, std::string solAssert(obj.bytecode, ""); solAssert(obj.sourceMappings, ""); - m_obtainedResult = "Assembly:\n" + obj.assembly; + m_obtainedResult = "Assembly:\n" + obj.assembly->assemblyString(stack.debugInfoSelection()); if (obj.bytecode->bytecode.empty()) m_obtainedResult += "-- empty bytecode --\n"; else diff --git a/test/libyul/objectCompiler/sourceLocations.yul b/test/libyul/objectCompiler/sourceLocations.yul index 1c8477324..883e85b04 100644 --- a/test/libyul/objectCompiler/sourceLocations.yul +++ b/test/libyul/objectCompiler/sourceLocations.yul @@ -1,28 +1,28 @@ // something else /*-- another unrelated comment --*/ -/// @use-src 3: "abc.sol" , 2: "def.sol" +/// @use-src 1: "abc.sol" , 0: "def.sol" object "a" { code { - /// @src 3:0:2 + /// @src 1:0:2 datacopy(0, dataoffset("sub"), datasize("sub")) return(0, - /** @src 2:5:6 */ + /** @src 0:5:6 */ datasize("sub") ) } - /// @use-src 3: "abc.sol" , 2: "def.sol" + /// @use-src 1: "abc.sol" , 0: "def.sol" object "sub" { code { - /// @src 2:70:72 + /// @src 0:70:72 sstore(0, dataoffset("sub")) /** * @something else - * @src 3:2:5 + * @src 1:2:5 */ mstore( 0, datasize("data1") - /// @src 3:90:2 + /// @src 1:90:2 ) } data "data1" "Hello, World!" diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 9fe24bcc6..2ba1d43c8 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -310,6 +310,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) "dir1/file1.sol:L=0x1234567890123456789012345678901234567890," "dir2/file2.sol:L=0x1111122222333334444455555666667777788888", "--asm", + "--asm-json", "--bin", "--ir-optimized", "--ast-compact-json", @@ -350,6 +351,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) expectedOptions.formatting.coloredOutput = false; expectedOptions.formatting.withErrorIds = true; expectedOptions.compiler.outputs.asm_ = true; + expectedOptions.compiler.outputs.asmJson = true; expectedOptions.compiler.outputs.binary = true; expectedOptions.compiler.outputs.irOptimized = true; expectedOptions.compiler.outputs.astCompactJson = true; From c458c3ec32d99e95fdbcc5fc7073aed840ad9f70 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 31 Jul 2024 15:05:11 +0200 Subject: [PATCH 0227/1340] SMTChecker: Use pipe instead of temporary file in solver interface Since version 2.1 (released in March 2024) Eldarica supports reading input from standard input. We can therefore update SMTSolverCommand to interact with the solver using pipe instead of creating temporary file on which the solver runs. cvc5 also supports this, and does not require any extra flags to enable this feature. --- libsolidity/interface/SMTSolverCommand.cpp | 30 ++++++++-------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index 1eaa3f38c..0558223d6 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -19,15 +19,7 @@ #include -#include -#include -#include -#include - #include -#include -#include -#include #include namespace solidity::frontend @@ -37,6 +29,8 @@ void SMTSolverCommand::setEldarica(std::optional timeoutInMillisec { m_arguments.clear(); m_solverCmd = "eld"; + m_arguments.emplace_back("-hsmt"); + m_arguments.emplace_back("-in"); if (timeoutInMilliseconds) { unsigned int timeoutInSeconds = timeoutInMilliseconds.value() / 1000u; @@ -73,32 +67,30 @@ ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::stri if (m_solverCmd.empty()) return ReadCallback::Result{false, "No solver set."}; - auto tempDir = solidity::util::TemporaryDirectory("smt"); - util::h256 queryHash = util::keccak256(_query); - auto queryFileName = tempDir.path() / ("query_" + queryHash.hex() + ".smt2"); - - auto queryFile = boost::filesystem::ofstream(queryFileName); - queryFile << _query << std::flush; - auto solverBin = boost::process::search_path(m_solverCmd); if (solverBin.empty()) return ReadCallback::Result{false, m_solverCmd + " binary not found."}; auto args = m_arguments; - args.push_back(queryFileName.string()); - boost::process::ipstream pipe; + boost::process::opstream in; // input to subprocess written to by the main process + boost::process::ipstream out; // output from subprocess read by the main process boost::process::child solverProcess( solverBin, args, - boost::process::std_out > pipe, + boost::process::std_out > out, + boost::process::std_in < in, boost::process::std_err > boost::process::null ); + in << _query << std::flush; + in.pipe().close(); + in.close(); + std::vector data; std::string line; - while (solverProcess.running() && std::getline(pipe, line)) + while (solverProcess.running() && std::getline(out, line)) if (!line.empty()) data.push_back(line); From b4917bbc2d8bf37aa9f07958c04857878cf9dfdb Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Sun, 21 Jul 2024 23:40:16 +0200 Subject: [PATCH 0228/1340] SMTChecker: Do not prematurely end reading solver's response When the main process reads an answer from the solver, it can happen that the solver process has already finished, while the main process is not yet done with reading the output from the pipe. In rare occasions, the caused some test to fail, because SMTChecker could not produced the expected counterexample from partial answer. --- libsolidity/interface/SMTSolverCommand.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index 0558223d6..dd62d2c28 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -90,7 +90,7 @@ ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::stri std::vector data; std::string line; - while (solverProcess.running() && std::getline(out, line)) + while (!(out.fail() || out.eof()) && std::getline(out, line)) if (!line.empty()) data.push_back(line); From ecfe63a08408dcd56bae82fbcaab452dd3cbe1e4 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 31 Jul 2024 22:58:14 +0200 Subject: [PATCH 0229/1340] SMTChecker: Explain command-line arguments of individual solvers --- libsolidity/interface/SMTSolverCommand.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index dd62d2c28..8120e1f11 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -29,8 +29,8 @@ void SMTSolverCommand::setEldarica(std::optional timeoutInMillisec { m_arguments.clear(); m_solverCmd = "eld"; - m_arguments.emplace_back("-hsmt"); - m_arguments.emplace_back("-in"); + m_arguments.emplace_back("-hsmt"); // Tell Eldarica to expect input in SMT2 format + m_arguments.emplace_back("-in"); // Tell Eldarica to read from standard input if (timeoutInMilliseconds) { unsigned int timeoutInSeconds = timeoutInMilliseconds.value() / 1000u; @@ -38,7 +38,7 @@ void SMTSolverCommand::setEldarica(std::optional timeoutInMillisec m_arguments.push_back("-t:" + std::to_string(timeoutInSeconds)); } if (computeInvariants) - m_arguments.emplace_back("-ssol"); + m_arguments.emplace_back("-ssol"); // Tell Eldarica to produce model (invariant) } void SMTSolverCommand::setCvc5(std::optional timeoutInMilliseconds) @@ -47,12 +47,12 @@ void SMTSolverCommand::setCvc5(std::optional timeoutInMilliseconds m_solverCmd = "cvc5"; if (timeoutInMilliseconds) { - m_arguments.push_back("--tlimit-per"); + m_arguments.emplace_back("--tlimit-per"); m_arguments.push_back(std::to_string(timeoutInMilliseconds.value())); } else { - m_arguments.push_back("--rlimit"); + m_arguments.emplace_back("--rlimit"); // Set resource limit cvc5 can spend on a query m_arguments.push_back(std::to_string(12000)); } } From c5685e70544c86f25d87b93048a8bffa963177c6 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 24 Jun 2024 15:53:45 -0300 Subject: [PATCH 0230/1340] generate transient storage layout --- Changelog.md | 2 + docs/internals/layout_in_storage.rst | 14 +- docs/using-the-compiler.rst | 5 +- libsolidity/analysis/TypeChecker.cpp | 7 - libsolidity/ast/Types.cpp | 22 ++- libsolidity/ast/Types.h | 4 +- libsolidity/codegen/Compiler.cpp | 12 ++ libsolidity/codegen/ir/IRGenerator.cpp | 12 ++ libsolidity/interface/CompilerStack.cpp | 17 +- libsolidity/interface/CompilerStack.h | 9 + libsolidity/interface/StandardCompiler.cpp | 2 + libsolidity/interface/StorageLayout.cpp | 7 +- libsolidity/interface/StorageLayout.h | 5 +- solc/CommandLineInterface.cpp | 20 ++- solc/CommandLineInterface.h | 1 + solc/CommandLineParser.cpp | 6 +- solc/CommandLineParser.h | 4 + .../output.json | 4 + .../input.json | 2 +- .../output.json | 159 +++++++++++------- .../transient_storage_layout/args | 1 + .../transient_storage_layout/input.sol | 13 ++ .../transient_storage_layout/output | 67 ++++++++ .../input.json | 15 ++ .../output.json | 17 ++ .../input.json | 21 +++ .../output.json | 51 ++++++ .../in.sol | 23 +++ .../input.json | 13 ++ .../output.json | 123 ++++++++++++++ .../in.sol | 15 ++ .../input.json | 13 ++ .../output.json | 155 +++++++++++++++++ .../in.sol | 24 +++ .../input.json | 13 ++ .../output.json | 131 +++++++++++++++ .../transient_data_location.sol | 14 ++ .../transient_storage_state_variable.sol | 2 +- .../dataLocations/transient_function_type.sol | 7 +- .../transient_state_variable_visibility.sol | 7 +- .../transient_value_type_state_variables.sol | 6 +- ..._value_type_state_variables_assignment.sol | 4 +- test/solc/CommandLineParser.cpp | 9 +- 43 files changed, 948 insertions(+), 110 deletions(-) create mode 100644 test/cmdlineTests/transient_storage_layout/args create mode 100644 test/cmdlineTests/transient_storage_layout/input.sol create mode 100644 test/cmdlineTests/transient_storage_layout/output create mode 100644 test/cmdlineTests/transient_storage_layout_smoke_empty/input.json create mode 100644 test/cmdlineTests/transient_storage_layout_smoke_empty/output.json create mode 100644 test/cmdlineTests/transient_storage_layout_smoke_two_contracts/input.json create mode 100644 test/cmdlineTests/transient_storage_layout_smoke_two_contracts/output.json create mode 100644 test/cmdlineTests/transient_storage_layout_value_types/in.sol create mode 100644 test/cmdlineTests/transient_storage_layout_value_types/input.json create mode 100644 test/cmdlineTests/transient_storage_layout_value_types/output.json create mode 100644 test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/in.sol create mode 100644 test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/input.json create mode 100644 test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/output.json create mode 100644 test/cmdlineTests/transient_storage_layout_value_types_packed/in.sol create mode 100644 test/cmdlineTests/transient_storage_layout_value_types_packed/input.json create mode 100644 test/cmdlineTests/transient_storage_layout_value_types_packed/output.json create mode 100644 test/libsolidity/astPropertyTests/transient_data_location.sol diff --git a/Changelog.md b/Changelog.md index 9c9a9e8fd..8acee7422 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,11 +8,13 @@ Language Features: Compiler Features: * Command Line Interface: Do not perform IR optimization when only unoptimized IR is requested. + * Commandline Interface: Add ``--transient-storage-layout`` output. * Error Reporting: Unimplemented features are now properly reported as errors instead of being handled as if they were bugs. * EVM: Support for the EVM version "Prague". * SMTChecker: Add CHC engine check for underflow and overflow in unary minus operation. * SMTChecker: Replace CVC4 as a possible BMC backend with cvc5. * Standard JSON Interface: Do not perform IR optimization when only unoptimized IR is requested. + * Standard JSON Interface: Add ``transientStorageLayout`` output. * Yul Optimizer: The optimizer now treats some previously unrecognized identical literals as identical. * Commandline Interface: Allow the use of ``--asm-json`` output option in assembler mode to export EVM assembly of the contracts in JSON format. diff --git a/docs/internals/layout_in_storage.rst b/docs/internals/layout_in_storage.rst index 7afcfc2ac..f6b10adee 100644 --- a/docs/internals/layout_in_storage.rst +++ b/docs/internals/layout_in_storage.rst @@ -1,11 +1,17 @@ -.. index:: storage, state variable, mapping +.. index:: storage, state variable, mapping, transient storage -************************************ -Layout of State Variables in Storage -************************************ +********************************************************** +Layout of State Variables in Storage and Transient Storage +********************************************************** .. _storage-inplace-encoding: +.. note:: + The rules described in this section apply for both storage and transient storage data locations. + The layouts are completely independent and don't interfere with each other's variable locations. + Thus storage and transient storage state variables can be safely interleaved without any side effects. + Only value types are supported for transient storage. + State variables of contracts are stored in storage in a compact way such that multiple values sometimes use the same storage slot. Except for dynamically-sized arrays and mappings (see below), data is stored diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index a306fa835..97994e132 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -423,7 +423,8 @@ Input Description // irAst - AST of Yul intermediate representation of the code before optimization // irOptimized - Intermediate representation after optimization // irOptimizedAst - AST of intermediate representation after optimization - // storageLayout - Slots, offsets and types of the contract's state variables. + // storageLayout - Slots, offsets and types of the contract's state variables in storage. + // transientStorageLayout - Slots, offsets and types of the contract's state variables in transient storage. // evm.assembly - New assembly format // evm.legacyAssembly - Old-style assembly format in JSON // evm.bytecode.functionDebugData - Debugging information at function level @@ -578,6 +579,8 @@ Output Description "irOptimizedAst": {/* ... */}, // See the Storage Layout documentation. "storageLayout": {"storage": [/* ... */], "types": {/* ... */} }, + // See the Storage Layout documentation. + "transientStorageLayout": {"storage": [/* ... */], "types": {/* ... */} }, // EVM-related outputs "evm": { // Assembly (string) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index dfd334295..918e27033 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -478,13 +478,6 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) Type const* varType = _variable.annotation().type; solAssert(!!varType, "Variable type not provided."); - if (_variable.referenceLocation() == VariableDeclaration::Location::Transient) - m_errorReporter.unimplementedFeatureError( - 6715_error, - _variable.location(), - "Transient storage is not yet implemented." - ); - if (_variable.value()) { if (_variable.isStateVariable() && varType->containsNestedMapping()) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index a37cc78a4..f6e2a5413 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2140,12 +2140,30 @@ FunctionType const* ContractType::newExpressionType() const return m_constructorType; } -std::vector> ContractType::stateVariables() const +std::vector> ContractType::stateVariables(std::optional _location) const { + std::optional location; + if (_location.has_value()) + { + switch (_location.value()) + { + case DataLocation::Storage: + location = std::make_optional(VariableDeclaration::Location::Unspecified); // By default state variables have unspecified (storage) data location + break; + case DataLocation::Transient: + location = std::make_optional(VariableDeclaration::Location::Transient); + break; + default: solAssert(false); + } + } + std::vector variables; for (ContractDefinition const* contract: m_contract.annotation().linearizedBaseContracts | ranges::views::reverse) for (VariableDeclaration const* variable: contract->stateVariables()) - if (!(variable->isConstant() || variable->immutable())) + if ( + !(variable->isConstant() || variable->immutable()) && + variable->referenceLocation() == location.value_or(variable->referenceLocation()) + ) variables.push_back(variable); TypePointers types; for (auto variable: variables) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 1817c97af..5a5040c40 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1001,8 +1001,8 @@ class ContractType: public Type FunctionType const* newExpressionType() const; /// @returns a list of all state variables (including inherited) of the contract and their - /// offsets in storage. - std::vector> stateVariables() const; + /// offsets in storage/transient storage. + std::vector> stateVariables(std::optional _location = std::nullopt) const; /// @returns a list of all immutable variables (including inherited) of the contract. std::vector immutableVariables() const; protected: diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index 844de8ba8..07b65fcc8 100644 --- a/libsolidity/codegen/Compiler.cpp +++ b/libsolidity/codegen/Compiler.cpp @@ -26,6 +26,8 @@ #include #include +#include + using namespace solidity; using namespace solidity::frontend; @@ -35,6 +37,16 @@ void Compiler::compileContract( bytes const& _metadata ) { + auto static notTransient = [](VariableDeclaration const* _varDeclaration) { + solAssert(_varDeclaration); + return _varDeclaration->referenceLocation() != VariableDeclaration::Location::Transient; + }; + + solUnimplementedAssert( + ranges::all_of(_contract.stateVariables(), notTransient), + "Transient storage variables are not supported." + ); + ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimiserSettings); runtimeCompiler.compileContract(_contract, _otherCompilers); m_runtimeContext.appendToAuxiliaryData(_metadata); diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index bf0f6d5c0..00c9fa196 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -39,6 +39,8 @@ #include #include +#include + #include #include @@ -101,6 +103,16 @@ std::string IRGenerator::generate( std::map const& _otherYulSources ) { + auto notTransient = [](VariableDeclaration const* _varDeclaration) { + solAssert(_varDeclaration); + return _varDeclaration->referenceLocation() != VariableDeclaration::Location::Transient; + }; + + solUnimplementedAssert( + ranges::all_of(_contract.stateVariables(), notTransient), + "Transient storage variables are not supported." + ); + auto subObjectSources = [&_otherYulSources](UniqueVector const& _subObjects) -> std::string { std::string subObjectsSources; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index f2c37fa68..de7b185d2 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1015,7 +1015,22 @@ Json const& CompilerStack::storageLayout(Contract const& _contract) const solAssert(_contract.contract); solUnimplementedAssert(!isExperimentalSolidity()); - return _contract.storageLayout.init([&]{ return StorageLayout().generate(*_contract.contract); }); + return _contract.storageLayout.init([&]{ return StorageLayout().generate(*_contract.contract, DataLocation::Storage); }); +} + +Json const& CompilerStack::transientStorageLayout(std::string const& _contractName) const +{ + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + return transientStorageLayout(contract(_contractName)); +} + +Json const& CompilerStack::transientStorageLayout(Contract const& _contract) const +{ + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + solAssert(_contract.contract); + solUnimplementedAssert(!isExperimentalSolidity()); + + return _contract.transientStorageLayout.init([&]{ return StorageLayout().generate(*_contract.contract, DataLocation::Transient); }); } Json const& CompilerStack::natspecUser(std::string const& _contractName) const diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 2c5ecb132..159a14d8d 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -338,6 +338,10 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// Prerequisite: Successful call to parse or compile. Json const& storageLayout(std::string const& _contractName) const; + /// @returns a JSON representing the transient storage layout of the contract. + /// Prerequisite: Successful call to parse or compile. + Json const& transientStorageLayout(std::string const& _contractName) const; + /// @returns a JSON representing the contract's user documentation. /// Prerequisite: Successful call to parse or compile. Json const& natspecUser(std::string const& _contractName) const; @@ -406,6 +410,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac util::LazyInit metadata; ///< The metadata json that will be hashed into the chain. util::LazyInit abi; util::LazyInit storageLayout; + util::LazyInit transientStorageLayout; util::LazyInit userDocumentation; util::LazyInit devDocumentation; util::LazyInit generatedSources; @@ -502,6 +507,10 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// This will generate the JSON object and store it in the Contract object if it is not present yet. Json const& storageLayout(Contract const&) const; + /// @returns the transient storage layout of the contract as a JSON object. + /// This will generate the JSON object and store it in the Contract object if it is not present yet. + Json const& transientStorageLayout(Contract const&) const; + /// @returns the Natspec User documentation as a JSON object. /// This will generate the JSON object and store it in the Contract object if it is not present yet. Json const& natspecUser(Contract const&) const; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index e4b9f9f7a..b209987dd 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1466,6 +1466,8 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu contractData["abi"] = compilerStack.contractABI(contractName); if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "storageLayout", false)) contractData["storageLayout"] = compilerStack.storageLayout(contractName); + if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "transientStorageLayout", false)) + contractData["transientStorageLayout"] = compilerStack.transientStorageLayout(contractName); if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "metadata", wildcardMatchesExperimental)) contractData["metadata"] = compilerStack.metadata(contractName); if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "userdoc", wildcardMatchesExperimental)) diff --git a/libsolidity/interface/StorageLayout.cpp b/libsolidity/interface/StorageLayout.cpp index 0153af1a2..8565fec68 100644 --- a/libsolidity/interface/StorageLayout.cpp +++ b/libsolidity/interface/StorageLayout.cpp @@ -20,10 +20,11 @@ #include +using namespace std::literals; using namespace solidity; using namespace solidity::frontend; -Json StorageLayout::generate(ContractDefinition const& _contractDef) +Json StorageLayout::generate(ContractDefinition const& _contractDef, DataLocation const _location) { solAssert(!m_contract, ""); m_contract = &_contractDef; @@ -35,18 +36,18 @@ Json StorageLayout::generate(ContractDefinition const& _contractDef) solAssert(contractType, ""); Json variables = Json::array(); - for (auto [var, slot, offset]: contractType->stateVariables()) + for (auto [var, slot, offset]: contractType->stateVariables(_location)) variables.emplace_back(generate(*var, slot, offset)); Json layout; layout["storage"] = std::move(variables); layout["types"] = std::move(m_types); + return layout; } Json StorageLayout::generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset) { - solUnimplementedAssert(_var.referenceLocation() != VariableDeclaration::Location::Transient, "Transient storage layout is not supported yet."); Json varEntry; Type const* varType = _var.type(); diff --git a/libsolidity/interface/StorageLayout.h b/libsolidity/interface/StorageLayout.h index b0b2d70b6..d3c7e2d9f 100644 --- a/libsolidity/interface/StorageLayout.h +++ b/libsolidity/interface/StorageLayout.h @@ -16,7 +16,7 @@ */ // SPDX-License-Identifier: GPL-3.0 /** - * Generates the storage layout of a contract. + * Generates the storage/transient storage layout of a contract. */ #pragma once @@ -33,8 +33,9 @@ class StorageLayout public: /// Generates the storage layout of the contract /// @param _contractDef The contract definition + /// @param _location The location (storage or transient storage) for which to generate the layout /// @return A JSON representation of the contract's storage layout. - Json generate(ContractDefinition const& _contractDef); + Json generate(ContractDefinition const& _contractDef, DataLocation const _location); private: /// Generates the JSON information for a variable and its storage location. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 135185840..02b6dcade 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -135,6 +135,7 @@ static std::string const g_strSources = "sources"; static std::string const g_strSrcMap = "srcmap"; static std::string const g_strSrcMapRuntime = "srcmap-runtime"; static std::string const g_strStorageLayout = "storage-layout"; +static std::string const g_strTransientStorageLayout = "transient-storage-layout"; static std::string const g_strVersion = "version"; static bool needsHumanTargetedStdout(CommandLineOptions const& _options) @@ -154,7 +155,8 @@ static bool needsHumanTargetedStdout(CommandLineOptions const& _options) _options.compiler.outputs.natspecDev || _options.compiler.outputs.opcodes || _options.compiler.outputs.signatureHashes || - _options.compiler.outputs.storageLayout; + _options.compiler.outputs.storageLayout || + _options.compiler.outputs.transientStorageLayout; } static bool coloredOutput(CommandLineOptions const& _options) @@ -420,6 +422,19 @@ void CommandLineInterface::handleStorageLayout(std::string const& _contract) sout() << "Contract Storage Layout:" << std::endl << data << std::endl; } +void CommandLineInterface::handleTransientStorageLayout(std::string const& _contract) +{ + solAssert(CompilerInputModes.count(m_options.input.mode) == 1); + + if (!m_options.compiler.outputs.transientStorageLayout) + return; + std::string data = jsonPrint(removeNullMembers(m_compiler->transientStorageLayout(_contract)), m_options.formatting.json); + if (!m_options.output.dir.empty()) + createFile(m_compiler->filesystemFriendlyName(_contract) + "_transient_storage.json", data); + else + sout() << "Contract Transient Storage Layout:" << std::endl << data << std::endl; +} + void CommandLineInterface::handleNatspec(bool _natspecDev, std::string const& _contract) { solAssert(CompilerInputModes.count(m_options.input.mode) == 1); @@ -956,6 +971,8 @@ void CommandLineInterface::handleCombinedJSON() contractData["metadata"] = m_compiler->metadata(contractName); if (m_options.compiler.combinedJsonRequests->storageLayout) contractData[g_strStorageLayout] = m_compiler->storageLayout(contractName); + if (m_options.compiler.combinedJsonRequests->transientStorageLayout) + contractData[g_strTransientStorageLayout] = m_compiler->transientStorageLayout(contractName); if (m_options.compiler.combinedJsonRequests->generatedSources) contractData[g_strGeneratedSources] = m_compiler->generatedSources(contractName, false); if (m_options.compiler.combinedJsonRequests->generatedSourcesRuntime) @@ -1322,6 +1339,7 @@ void CommandLineInterface::outputCompilationResults() handleMetadata(contract); handleABI(contract); handleStorageLayout(contract); + handleTransientStorageLayout(contract); handleNatspec(true, contract); handleNatspec(false, contract); } // end of contracts iteration diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index bcebcbcfd..c23fd9e17 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -115,6 +115,7 @@ class CommandLineInterface void handleNatspec(bool _natspecDev, std::string const& _contract); void handleGasEstimation(std::string const& _contract); void handleStorageLayout(std::string const& _contract); + void handleTransientStorageLayout(std::string const& _contract); /// Tries to read @ m_sourceCodes as a JSONs holding ASTs /// such that they can be imported into the compiler (importASTs()) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 881c656da..97c690140 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -760,7 +760,8 @@ General Information)").c_str(), (CompilerOutputs::componentName(&CompilerOutputs::natspecUser).c_str(), "Natspec user documentation of all contracts.") (CompilerOutputs::componentName(&CompilerOutputs::natspecDev).c_str(), "Natspec developer documentation of all contracts.") (CompilerOutputs::componentName(&CompilerOutputs::metadata).c_str(), "Combined Metadata JSON whose IPFS hash is stored on-chain.") - (CompilerOutputs::componentName(&CompilerOutputs::storageLayout).c_str(), "Slots, offsets and types of the contract's state variables.") + (CompilerOutputs::componentName(&CompilerOutputs::storageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in storage.") + (CompilerOutputs::componentName(&CompilerOutputs::transientStorageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in transient storage.") ; desc.add(outputComponents); @@ -1469,7 +1470,8 @@ void CommandLineParser::parseCombinedJsonOption() &CombinedJsonRequests::natspecDev, &CombinedJsonRequests::natspecUser, &CombinedJsonRequests::signatureHashes, - &CombinedJsonRequests::storageLayout + &CombinedJsonRequests::storageLayout, + &CombinedJsonRequests::transientStorageLayout }; for (auto const invalidOption: invalidOptions) diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index b95973562..5d941f662 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -86,6 +86,7 @@ struct CompilerOutputs {"devdoc", &CompilerOutputs::natspecDev}, {"metadata", &CompilerOutputs::metadata}, {"storage-layout", &CompilerOutputs::storageLayout}, + {"transient-storage-layout", &CompilerOutputs::transientStorageLayout}, }; return components; } @@ -106,6 +107,7 @@ struct CompilerOutputs bool natspecDev = false; bool metadata = false; bool storageLayout = false; + bool transientStorageLayout = false; }; struct CombinedJsonRequests @@ -125,6 +127,7 @@ struct CombinedJsonRequests {"opcodes", &CombinedJsonRequests::opcodes}, {"asm", &CombinedJsonRequests::asm_}, {"storage-layout", &CombinedJsonRequests::storageLayout}, + {"transient-storage-layout", &CombinedJsonRequests::transientStorageLayout}, {"generated-sources", &CombinedJsonRequests::generatedSources}, {"generated-sources-runtime", &CombinedJsonRequests::generatedSourcesRuntime}, {"srcmap", &CombinedJsonRequests::srcMap}, @@ -146,6 +149,7 @@ struct CombinedJsonRequests bool opcodes = false; bool asm_ = false; bool storageLayout = false; + bool transientStorageLayout = false; bool generatedSources = false; bool generatedSourcesRuntime = false; bool srcMap = false; diff --git a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json index 09f4afc4e..e0f4e37e6 100644 --- a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json +++ b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json @@ -37,6 +37,10 @@ "storage": [], "types": null }, + "transientStorageLayout": { + "storage": [], + "types": null + }, "userdoc": { "kind": "user", "methods": {}, diff --git a/test/cmdlineTests/storage_layout_transient_value_types/input.json b/test/cmdlineTests/storage_layout_transient_value_types/input.json index 96d71ed30..8c90a7dde 100644 --- a/test/cmdlineTests/storage_layout_transient_value_types/input.json +++ b/test/cmdlineTests/storage_layout_transient_value_types/input.json @@ -6,7 +6,7 @@ "settings": { "outputSelection": { "fileA": { - "A": ["storageLayout"] + "A": ["storageLayout", "transientStorageLayout"] } } } diff --git a/test/cmdlineTests/storage_layout_transient_value_types/output.json b/test/cmdlineTests/storage_layout_transient_value_types/output.json index b77de9326..1f688501e 100644 --- a/test/cmdlineTests/storage_layout_transient_value_types/output.json +++ b/test/cmdlineTests/storage_layout_transient_value_types/output.json @@ -1,62 +1,103 @@ { - "errors": [ - { - "component": "general", - "errorCode": "6715", - "formattedMessage": "UnimplementedFeatureError: Transient storage is not yet implemented. - --> fileA:4:5: - | -4 | uint transient x; - | ^^^^^^^^^^^^^^^^ - -", - "message": "Transient storage is not yet implemented.", - "severity": "error", - "sourceLocation": { - "end": 91, - "file": "fileA", - "start": 75 - }, - "type": "UnimplementedFeatureError" - }, - { - "component": "general", - "errorCode": "6715", - "formattedMessage": "UnimplementedFeatureError: Transient storage is not yet implemented. - --> fileA:6:5: - | -6 | bytes32 transient b; - | ^^^^^^^^^^^^^^^^^^^ - -", - "message": "Transient storage is not yet implemented.", - "severity": "error", - "sourceLocation": { - "end": 128, - "file": "fileA", - "start": 109 - }, - "type": "UnimplementedFeatureError" - }, - { - "component": "general", - "errorCode": "6715", - "formattedMessage": "UnimplementedFeatureError: Transient storage is not yet implemented. - --> fileA:8:5: - | -8 | address transient a; - | ^^^^^^^^^^^^^^^^^^^ - -", - "message": "Transient storage is not yet implemented.", - "severity": "error", - "sourceLocation": { - "end": 168, - "file": "fileA", - "start": 149 - }, - "type": "UnimplementedFeatureError" + "contracts": { + "fileA": { + "A": { + "storageLayout": { + "storage": [ + { + "astId": 5, + "contract": "fileA:A", + "label": "y", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 9, + "contract": "fileA:A", + "label": "c", + "offset": 0, + "slot": "1", + "type": "t_bytes32" + }, + { + "astId": 13, + "contract": "fileA:A", + "label": "z", + "offset": 0, + "slot": "2", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + }, + "transientStorageLayout": { + "storage": [ + { + "astId": 3, + "contract": "fileA:A", + "label": "x", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 7, + "contract": "fileA:A", + "label": "b", + "offset": 0, + "slot": "1", + "type": "t_bytes32" + }, + { + "astId": 11, + "contract": "fileA:A", + "label": "a", + "offset": 0, + "slot": "2", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } + } } - ], - "sources": {} + }, + "sources": { + "fileA": { + "id": 0 + } + } } diff --git a/test/cmdlineTests/transient_storage_layout/args b/test/cmdlineTests/transient_storage_layout/args new file mode 100644 index 000000000..fe39ed776 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout/args @@ -0,0 +1 @@ +--transient-storage-layout --pretty-json --json-indent 4 \ No newline at end of file diff --git a/test/cmdlineTests/transient_storage_layout/input.sol b/test/cmdlineTests/transient_storage_layout/input.sol new file mode 100644 index 000000000..e1d028698 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout/input.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity > 0.0; + +contract D { } + +contract C { + uint transient x; + uint y; + address transient w; + int z; + bool transient b; + D transient d; +} \ No newline at end of file diff --git a/test/cmdlineTests/transient_storage_layout/output b/test/cmdlineTests/transient_storage_layout/output new file mode 100644 index 000000000..0736271b4 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout/output @@ -0,0 +1,67 @@ + +======= transient_storage_layout/input.sol:C ======= +Contract Transient Storage Layout: +{ + "storage": [ + { + "astId": 4, + "contract": "transient_storage_layout/input.sol:C", + "label": "x", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 8, + "contract": "transient_storage_layout/input.sol:C", + "label": "w", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 12, + "contract": "transient_storage_layout/input.sol:C", + "label": "b", + "offset": 20, + "slot": "1", + "type": "t_bool" + }, + { + "astId": 15, + "contract": "transient_storage_layout/input.sol:C", + "label": "d", + "offset": 0, + "slot": "2", + "type": "t_contract(D)2" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(D)2": { + "encoding": "inplace", + "label": "contract D", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} + +======= transient_storage_layout/input.sol:D ======= +Contract Transient Storage Layout: +{ + "storage": [] +} diff --git a/test/cmdlineTests/transient_storage_layout_smoke_empty/input.json b/test/cmdlineTests/transient_storage_layout_smoke_empty/input.json new file mode 100644 index 000000000..d167f6663 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_smoke_empty/input.json @@ -0,0 +1,15 @@ +{ + "language": "Solidity", + "sources": { + "fileA": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A { }" + } + }, + "settings": { + "outputSelection": { + "fileA": { + "A": ["transientStorageLayout"] + } + } + } +} diff --git a/test/cmdlineTests/transient_storage_layout_smoke_empty/output.json b/test/cmdlineTests/transient_storage_layout_smoke_empty/output.json new file mode 100644 index 000000000..261442c1d --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_smoke_empty/output.json @@ -0,0 +1,17 @@ +{ + "contracts": { + "fileA": { + "A": { + "transientStorageLayout": { + "storage": [], + "types": null + } + } + } + }, + "sources": { + "fileA": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/transient_storage_layout_smoke_two_contracts/input.json b/test/cmdlineTests/transient_storage_layout_smoke_two_contracts/input.json new file mode 100644 index 000000000..4ca3cc455 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_smoke_two_contracts/input.json @@ -0,0 +1,21 @@ +{ + "language": "Solidity", + "sources": { + "fileA": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A { }" + }, + "fileB": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract B { uint transient x; uint transient y; }" + } + }, + "settings": { + "outputSelection": { + "fileA": { + "A": ["transientStorageLayout"] + }, + "fileB": { + "B": ["transientStorageLayout"] + } + } + } +} diff --git a/test/cmdlineTests/transient_storage_layout_smoke_two_contracts/output.json b/test/cmdlineTests/transient_storage_layout_smoke_two_contracts/output.json new file mode 100644 index 000000000..670ff0125 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_smoke_two_contracts/output.json @@ -0,0 +1,51 @@ +{ + "contracts": { + "fileA": { + "A": { + "transientStorageLayout": { + "storage": [], + "types": null + } + } + }, + "fileB": { + "B": { + "transientStorageLayout": { + "storage": [ + { + "astId": 6, + "contract": "fileB:B", + "label": "x", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 8, + "contract": "fileB:B", + "label": "y", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } + } + } + }, + "sources": { + "fileA": { + "id": 0 + }, + "fileB": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/transient_storage_layout_value_types/in.sol b/test/cmdlineTests/transient_storage_layout_value_types/in.sol new file mode 100644 index 000000000..c2f89a987 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_value_types/in.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +type MyInt is int256; + +enum MyEnum { + None, + Something, + SomethingElse +} + +contract C { } + +contract A { + uint transient x; + int transient y; + address transient addr; + bool transient b; + MyInt transient w; + C transient c; + MyEnum transient e; + function() external transient p; +} diff --git a/test/cmdlineTests/transient_storage_layout_value_types/input.json b/test/cmdlineTests/transient_storage_layout_value_types/input.json new file mode 100644 index 000000000..65d9a2231 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_value_types/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "fileA": {"urls": ["transient_storage_layout_value_types/in.sol"]} + }, + "settings": { + "outputSelection": { + "fileA": { + "A": ["transientStorageLayout"] + } + } + } +} diff --git a/test/cmdlineTests/transient_storage_layout_value_types/output.json b/test/cmdlineTests/transient_storage_layout_value_types/output.json new file mode 100644 index 000000000..298a2588a --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_value_types/output.json @@ -0,0 +1,123 @@ +{ + "contracts": { + "fileA": { + "A": { + "transientStorageLayout": { + "storage": [ + { + "astId": 10, + "contract": "fileA:A", + "label": "x", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 12, + "contract": "fileA:A", + "label": "y", + "offset": 0, + "slot": "1", + "type": "t_int256" + }, + { + "astId": 14, + "contract": "fileA:A", + "label": "addr", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 16, + "contract": "fileA:A", + "label": "b", + "offset": 20, + "slot": "2", + "type": "t_bool" + }, + { + "astId": 19, + "contract": "fileA:A", + "label": "w", + "offset": 0, + "slot": "3", + "type": "t_userDefinedValueType(MyInt)3" + }, + { + "astId": 22, + "contract": "fileA:A", + "label": "c", + "offset": 0, + "slot": "4", + "type": "t_contract(C)8" + }, + { + "astId": 25, + "contract": "fileA:A", + "label": "e", + "offset": 20, + "slot": "4", + "type": "t_enum(MyEnum)7" + }, + { + "astId": 29, + "contract": "fileA:A", + "label": "p", + "offset": 0, + "slot": "5", + "type": "t_function_external_nonpayable()returns()" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(C)8": { + "encoding": "inplace", + "label": "contract C", + "numberOfBytes": "20" + }, + "t_enum(MyEnum)7": { + "encoding": "inplace", + "label": "enum MyEnum", + "numberOfBytes": "1" + }, + "t_function_external_nonpayable()returns()": { + "encoding": "inplace", + "label": "function () external", + "numberOfBytes": "24" + }, + "t_int256": { + "encoding": "inplace", + "label": "int256", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_userDefinedValueType(MyInt)3": { + "encoding": "inplace", + "label": "MyInt", + "numberOfBytes": "32" + } + } + } + } + } + }, + "sources": { + "fileA": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/in.sol b/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/in.sol new file mode 100644 index 000000000..18af07a15 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/in.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +type MyInt is int8; +contract A { + uint public transient x; + uint public y; + int private transient z; + int private w; + address transient addr; + address d; + bool transient b; + bool c; + MyInt i; + MyInt transient j; +} diff --git a/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/input.json b/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/input.json new file mode 100644 index 000000000..e649fc838 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "fileA": {"urls": ["transient_storage_layout_value_types_interleaved_with_storage/in.sol"]} + }, + "settings": { + "outputSelection": { + "fileA": { + "A": ["storageLayout", "transientStorageLayout"] + } + } + } +} diff --git a/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/output.json b/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/output.json new file mode 100644 index 000000000..ab967985d --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/output.json @@ -0,0 +1,155 @@ +{ + "contracts": { + "fileA": { + "A": { + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "fileA:A", + "label": "y", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 11, + "contract": "fileA:A", + "label": "w", + "offset": 0, + "slot": "1", + "type": "t_int256" + }, + { + "astId": 15, + "contract": "fileA:A", + "label": "d", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 19, + "contract": "fileA:A", + "label": "c", + "offset": 20, + "slot": "2", + "type": "t_bool" + }, + { + "astId": 22, + "contract": "fileA:A", + "label": "i", + "offset": 21, + "slot": "2", + "type": "t_userDefinedValueType(MyInt)3" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_int256": { + "encoding": "inplace", + "label": "int256", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_userDefinedValueType(MyInt)3": { + "encoding": "inplace", + "label": "MyInt", + "numberOfBytes": "1" + } + } + }, + "transientStorageLayout": { + "storage": [ + { + "astId": 5, + "contract": "fileA:A", + "label": "x", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 9, + "contract": "fileA:A", + "label": "z", + "offset": 0, + "slot": "1", + "type": "t_int256" + }, + { + "astId": 13, + "contract": "fileA:A", + "label": "addr", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 17, + "contract": "fileA:A", + "label": "b", + "offset": 20, + "slot": "2", + "type": "t_bool" + }, + { + "astId": 25, + "contract": "fileA:A", + "label": "j", + "offset": 21, + "slot": "2", + "type": "t_userDefinedValueType(MyInt)3" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_int256": { + "encoding": "inplace", + "label": "int256", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_userDefinedValueType(MyInt)3": { + "encoding": "inplace", + "label": "MyInt", + "numberOfBytes": "1" + } + } + } + } + } + }, + "sources": { + "fileA": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/transient_storage_layout_value_types_packed/in.sol b/test/cmdlineTests/transient_storage_layout_value_types_packed/in.sol new file mode 100644 index 000000000..9b50fd810 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_value_types_packed/in.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +type MyInt is int128; + +enum MyEnum { + None, + Something, + SomethingElse +} + +contract C { } + +contract A { + uint64 transient x; + uint128 transient y; + uint128 transient z; + address transient addr; + bool transient b; + MyInt transient w; + C transient c; + MyEnum transient e; + function() external transient p; +} diff --git a/test/cmdlineTests/transient_storage_layout_value_types_packed/input.json b/test/cmdlineTests/transient_storage_layout_value_types_packed/input.json new file mode 100644 index 000000000..ee7fb0dec --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_value_types_packed/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "fileA": {"urls": ["transient_storage_layout_value_types_packed/in.sol"]} + }, + "settings": { + "outputSelection": { + "fileA": { + "A": ["transientStorageLayout"] + } + } + } +} diff --git a/test/cmdlineTests/transient_storage_layout_value_types_packed/output.json b/test/cmdlineTests/transient_storage_layout_value_types_packed/output.json new file mode 100644 index 000000000..2be40db84 --- /dev/null +++ b/test/cmdlineTests/transient_storage_layout_value_types_packed/output.json @@ -0,0 +1,131 @@ +{ + "contracts": { + "fileA": { + "A": { + "transientStorageLayout": { + "storage": [ + { + "astId": 10, + "contract": "fileA:A", + "label": "x", + "offset": 0, + "slot": "0", + "type": "t_uint64" + }, + { + "astId": 12, + "contract": "fileA:A", + "label": "y", + "offset": 8, + "slot": "0", + "type": "t_uint128" + }, + { + "astId": 14, + "contract": "fileA:A", + "label": "z", + "offset": 0, + "slot": "1", + "type": "t_uint128" + }, + { + "astId": 16, + "contract": "fileA:A", + "label": "addr", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 18, + "contract": "fileA:A", + "label": "b", + "offset": 20, + "slot": "2", + "type": "t_bool" + }, + { + "astId": 21, + "contract": "fileA:A", + "label": "w", + "offset": 0, + "slot": "3", + "type": "t_userDefinedValueType(MyInt)3" + }, + { + "astId": 24, + "contract": "fileA:A", + "label": "c", + "offset": 0, + "slot": "4", + "type": "t_contract(C)8" + }, + { + "astId": 27, + "contract": "fileA:A", + "label": "e", + "offset": 20, + "slot": "4", + "type": "t_enum(MyEnum)7" + }, + { + "astId": 31, + "contract": "fileA:A", + "label": "p", + "offset": 0, + "slot": "5", + "type": "t_function_external_nonpayable()returns()" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(C)8": { + "encoding": "inplace", + "label": "contract C", + "numberOfBytes": "20" + }, + "t_enum(MyEnum)7": { + "encoding": "inplace", + "label": "enum MyEnum", + "numberOfBytes": "1" + }, + "t_function_external_nonpayable()returns()": { + "encoding": "inplace", + "label": "function () external", + "numberOfBytes": "24" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + }, + "t_userDefinedValueType(MyInt)3": { + "encoding": "inplace", + "label": "MyInt", + "numberOfBytes": "16" + } + } + } + } + } + }, + "sources": { + "fileA": { + "id": 0 + } + } +} diff --git a/test/libsolidity/astPropertyTests/transient_data_location.sol b/test/libsolidity/astPropertyTests/transient_data_location.sol new file mode 100644 index 000000000..be220a366 --- /dev/null +++ b/test/libsolidity/astPropertyTests/transient_data_location.sol @@ -0,0 +1,14 @@ +contract C { + /// TransientDataLocation: storageLocation + /// TransientVarName: name + uint transient x; + /// StorageDataLocation: storageLocation + /// StorageVarName: name + uint y; + +} +// ---- +// TransientDataLocation: transient +// TransientVarName: x +// StorageDataLocation: default +// StorageVarName: y diff --git a/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol b/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol index cdb446165..b2dbc8efe 100644 --- a/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol +++ b/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol @@ -5,4 +5,4 @@ contract C { // ==== // SMTEngine: all // ---- -// UnimplementedFeatureError 6715: (17-38): Transient storage is not yet implemented. +// UnimplementedFeatureError 1834: Transient storage variables are not supported. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol b/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol index a3d741bbe..564562908 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol @@ -7,9 +7,4 @@ contract C { function () internal internal transient fiit; } // ---- -// UnimplementedFeatureError 6715: (17-40): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (46-82): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (88-122): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (128-162): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (168-212): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (218-262): Transient storage is not yet implemented. +// UnimplementedFeatureError 1834: Transient storage variables are not supported. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol b/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol index 561d9f21d..f598fb72c 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol @@ -8,9 +8,4 @@ contract C { uint transient private tprv; } // ---- -// UnimplementedFeatureError 6715: (17-43): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (49-75): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (81-108): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (115-141): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (147-173): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (179-206): Transient storage is not yet implemented. +// UnimplementedFeatureError 1834: Transient storage variables are not supported. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol index ce2db200b..d2eac46f7 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol @@ -8,8 +8,4 @@ contract C { bytes32 transient y; } // ---- -// UnimplementedFeatureError 6715: (30-49): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (52-68): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (71-84): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (87-103): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (106-125): Transient storage is not yet implemented. +// UnimplementedFeatureError 1834: Transient storage variables are not supported. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol index 33b7bb28c..18e6a215d 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol @@ -6,6 +6,4 @@ contract C { bool transient b = x > 0 ? false : true; } // ---- -// UnimplementedFeatureError 6715: (30-51): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (54-90): Transient storage is not yet implemented. -// UnimplementedFeatureError 6715: (93-132): Transient storage is not yet implemented. +// UnimplementedFeatureError 1834: Transient storage variables are not supported. diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 2ba1d43c8..37c638a3b 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -130,10 +130,11 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) "dir1/file1.sol:L=0x1234567890123456789012345678901234567890," "dir2/file2.sol:L=0x1111122222333334444455555666667777788888", "--ast-compact-json", "--asm", "--asm-json", "--opcodes", "--bin", "--bin-runtime", "--abi", - "--ir", "--ir-ast-json", "--ir-optimized", "--ir-optimized-ast-json", "--hashes", "--userdoc", "--devdoc", "--metadata", "--storage-layout", + "--ir", "--ir-ast-json", "--ir-optimized", "--ir-optimized-ast-json", "--hashes", "--userdoc", "--devdoc", "--metadata", + "--storage-layout", "--transient-storage-layout", "--gas", "--combined-json=" - "abi,metadata,bin,bin-runtime,opcodes,asm,storage-layout,generated-sources,generated-sources-runtime," + "abi,metadata,bin,bin-runtime,opcodes,asm,storage-layout,transient-storage-layout,generated-sources,generated-sources-runtime," "srcmap,srcmap-runtime,function-debug,function-debug-runtime,hashes,devdoc,userdoc,ast", "--metadata-hash=swarm", "--metadata-literal", @@ -192,14 +193,14 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, - true, + true, true, }; expectedOptions.compiler.estimateGas = true; expectedOptions.compiler.combinedJsonRequests = { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, + true, true, true, }; expectedOptions.metadata.hash = CompilerStack::MetadataHash::Bzzr1; expectedOptions.metadata.literalSources = true; From 978f9a0cd7e04cea8ad67dc3b5ef130aa9878e72 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 11 Jul 2024 11:30:58 +0200 Subject: [PATCH 0231/1340] Yul: Immutable AST class with top-level block --- libsolidity/analysis/ControlFlowBuilder.cpp | 2 +- libsolidity/analysis/PostTypeChecker.cpp | 2 +- libsolidity/analysis/ReferencesResolver.cpp | 2 +- libsolidity/analysis/SyntaxChecker.cpp | 2 +- libsolidity/analysis/TypeChecker.cpp | 2 +- libsolidity/analysis/ViewPureChecker.cpp | 2 +- libsolidity/ast/AST.h | 8 +- libsolidity/ast/ASTJsonExporter.cpp | 2 +- libsolidity/ast/ASTJsonImporter.cpp | 2 +- libsolidity/codegen/CompilerContext.cpp | 10 +- libsolidity/codegen/ContractCompiler.cpp | 6 +- .../codegen/ir/IRGeneratorForStatements.cpp | 2 +- .../experimental/analysis/TypeInference.cpp | 2 +- .../codegen/IRGeneratorForStatements.cpp | 2 +- libsolidity/formal/SMTEncoder.cpp | 4 +- libsolidity/interface/CompilerStack.cpp | 4 +- libsolidity/parsing/Parser.cpp | 8 +- libyul/AST.h | 12 + libyul/ASTForward.h | 1 + libyul/AsmAnalysis.cpp | 13 +- libyul/AsmAnalysis.h | 5 + libyul/AsmJsonImporter.cpp | 5 + libyul/AsmJsonImporter.h | 3 +- libyul/AsmParser.cpp | 10 +- libyul/AsmParser.h | 4 +- libyul/CompilabilityChecker.cpp | 17 +- libyul/CompilabilityChecker.h | 7 +- libyul/Object.cpp | 4 +- libyul/Object.h | 2 +- libyul/ObjectParser.cpp | 10 +- libyul/ObjectParser.h | 4 +- libyul/YulStack.cpp | 2 +- libyul/backends/evm/EVMObjectCompiler.cpp | 8 +- libyul/optimiser/Semantics.cpp | 2 +- libyul/optimiser/StackCompressor.cpp | 30 +- libyul/optimiser/StackCompressor.h | 13 +- libyul/optimiser/StackLimitEvader.cpp | 31 +- libyul/optimiser/StackLimitEvader.h | 7 +- libyul/optimiser/Suite.cpp | 34 +- test/libsolidity/MemoryGuardTest.cpp | 3 +- test/libyul/Common.cpp | 8 +- test/libyul/Common.h | 3 +- test/libyul/ControlFlowGraphTest.cpp | 2 +- test/libyul/ControlFlowSideEffectsTest.cpp | 4 +- test/libyul/FunctionSideEffects.cpp | 2 +- test/libyul/KnowledgeBaseTest.cpp | 9 +- test/libyul/Metrics.cpp | 4 +- test/libyul/Parser.cpp | 280 +++++------ test/libyul/StackLayoutGeneratorTest.cpp | 2 +- test/libyul/YulInterpreterTest.cpp | 3 +- test/libyul/YulInterpreterTest.h | 4 +- test/libyul/YulOptimizerTest.cpp | 15 +- test/libyul/YulOptimizerTestCommon.cpp | 451 +++++++++++------- test/libyul/YulOptimizerTestCommon.h | 19 +- .../tools/ossfuzz/StackReuseCodegenFuzzer.cpp | 2 +- test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 5 +- test/tools/ossfuzz/yulFuzzerCommon.cpp | 4 +- test/tools/ossfuzz/yulFuzzerCommon.h | 2 +- test/tools/ossfuzz/yulProtoFuzzer.cpp | 4 +- test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp | 9 +- test/tools/yulopti.cpp | 28 +- test/tools/yulrun.cpp | 8 +- tools/yulPhaser/Program.cpp | 37 +- tools/yulPhaser/Program.h | 22 +- 64 files changed, 699 insertions(+), 517 deletions(-) diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index c20968a14..7bc0ebc7b 100644 --- a/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/libsolidity/analysis/ControlFlowBuilder.cpp @@ -451,7 +451,7 @@ bool ControlFlowBuilder::visit(InlineAssembly const& _inlineAssembly) solAssert(!!m_currentNode && !m_inlineAssembly, ""); m_inlineAssembly = &_inlineAssembly; - (*this)(_inlineAssembly.operations()); + (*this)(_inlineAssembly.operations().root()); m_inlineAssembly = nullptr; return false; diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index 9731ef3cc..49c5fa4a4 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -506,7 +506,7 @@ class LValueChecker: public ASTConstVisitor return; YulLValueChecker yulChecker{m_declaration->name()}; - yulChecker(_inlineAssembly.operations()); + yulChecker(_inlineAssembly.operations().root()); m_willBeWrittenTo = yulChecker.willBeWrittenTo(); } private: diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 270e1a55a..bb3b20e93 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -236,7 +236,7 @@ bool ReferencesResolver::visit(UsingForDirective const& _usingFor) bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) { m_yulAnnotation = &_inlineAssembly.annotation(); - (*this)(_inlineAssembly.operations()); + (*this)(_inlineAssembly.operations().root()); m_yulAnnotation = nullptr; return false; diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index b083690cc..1e3f5f1c2 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -354,7 +354,7 @@ bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly) if (!m_useYulOptimizer) return false; - if (yul::MSizeFinder::containsMSize(_inlineAssembly.dialect(), _inlineAssembly.operations())) + if (yul::MSizeFinder::containsMSize(_inlineAssembly.dialect(), _inlineAssembly.operations().root())) m_errorReporter.syntaxError( 6553_error, _inlineAssembly.location(), diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 918e27033..3b7a314fe 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -940,7 +940,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) _inlineAssembly.dialect(), identifierAccess ); - if (!analyzer.analyze(_inlineAssembly.operations())) + if (!analyzer.analyze(_inlineAssembly.operations().root())) solAssert(m_errorReporter.hasErrors()); _inlineAssembly.annotation().hasMemoryEffects = lvalueAccessToMemoryVariable || diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 3f6b954e7..3b16205e7 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -226,7 +226,7 @@ void ViewPureChecker::endVisit(InlineAssembly const& _inlineAssembly) AssemblyViewPureChecker{ _inlineAssembly.dialect(), [&](StateMutability _mutability, SourceLocation const& _location) { reportMutability(_mutability, _location); } - }(_inlineAssembly.operations()); + }(_inlineAssembly.operations().root()); } void ViewPureChecker::reportMutability( diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 3494ab94b..727652f56 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -48,7 +48,7 @@ namespace solidity::yul { // Forward-declaration to -struct Block; +class AST; struct Dialect; } @@ -1569,7 +1569,7 @@ class InlineAssembly: public Statement ASTPointer const& _docString, yul::Dialect const& _dialect, ASTPointer>> _flags, - std::shared_ptr _operations + std::shared_ptr _operations ): Statement(_id, _location, _docString), m_dialect(_dialect), @@ -1580,7 +1580,7 @@ class InlineAssembly: public Statement void accept(ASTConstVisitor& _visitor) const override; yul::Dialect const& dialect() const { return m_dialect; } - yul::Block const& operations() const { return *m_operations; } + yul::AST const& operations() const { return *m_operations; } ASTPointer>> const& flags() const { return m_flags; } InlineAssemblyAnnotation& annotation() const override; @@ -1588,7 +1588,7 @@ class InlineAssembly: public Statement private: yul::Dialect const& m_dialect; ASTPointer>> m_flags; - std::shared_ptr m_operations; + std::shared_ptr m_operations; }; /** diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 69f51618e..910cc257e 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -665,7 +665,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) externalReferencesJson.emplace_back(std::move(it)); std::vector> attributes = { - std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))), + std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations().root()))), std::make_pair("externalReferences", std::move(externalReferencesJson)), std::make_pair("evmVersion", dynamic_cast(_node.dialect()).evmVersion().name()) }; diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 728d77c0d..8d72b41f7 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -733,7 +733,7 @@ ASTPointer ASTJsonImporter::createInlineAssembly(Json const& _no flags->emplace_back(std::make_shared(flag.get())); } } - std::shared_ptr operations = std::make_shared(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST"))); + std::shared_ptr operations = std::make_shared(yul::AsmJsonImporter(m_sourceNames).createAST(member(_node, "AST"))); return createASTNode( _node, nullOrASTString(_node, "documentation"), diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 962defdbc..aa6985503 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -440,7 +440,7 @@ void CompilerContext::appendInlineAssembly( std::optional locationOverride; if (!_system) locationOverride = m_asm->currentSourceLocation(); - std::shared_ptr parserResult = + std::shared_ptr parserResult = yul::Parser(errorReporter, dialect, std::move(locationOverride)) .parse(charStream); #ifdef SOL_OUTPUT_ASM @@ -472,7 +472,7 @@ void CompilerContext::appendInlineAssembly( errorReporter, dialect, identifierAccess.resolve - ).analyze(*parserResult); + ).analyze(parserResult->root()); if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) reportError("Invalid assembly generated by code generator."); @@ -491,8 +491,8 @@ void CompilerContext::appendInlineAssembly( { // Store as generated sources, but first re-parse to update the source references. solAssert(m_generatedYulUtilityCode.empty(), ""); - m_generatedYulUtilityCode = yul::AsmPrinter(yul::AsmPrinter::TypePrinting::OmitDefault, dialect)(*obj.code); - std::string code = yul::AsmPrinter{yul::AsmPrinter::TypePrinting::OmitDefault, dialect}(*obj.code); + m_generatedYulUtilityCode = yul::AsmPrinter(yul::AsmPrinter::TypePrinting::OmitDefault, dialect)(obj.code->root()); + std::string code = yul::AsmPrinter{yul::AsmPrinter::TypePrinting::OmitDefault, dialect}(obj.code->root()); langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); obj.code = yul::Parser(errorReporter, dialect).parse(charStream); *obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj); @@ -518,7 +518,7 @@ void CompilerContext::appendInlineAssembly( solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block."); yul::CodeGenerator::assemble( - *parserResult, + parserResult->root(), analysisInfo, *m_asm, m_evmVersion, diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 0ed17f6d0..21899f72a 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -927,7 +927,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) } }; - yul::Block const* code = &_inlineAssembly.operations(); + yul::AST const* code = &_inlineAssembly.operations(); yul::AsmAnalysisInfo* analysisInfo = _inlineAssembly.annotation().analysisInfo.get(); // Only used in the scope below, but required to live outside to keep the @@ -944,7 +944,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) solAssert(dialect, ""); // Create a modifiable copy of the code and analysis - object.code = std::make_shared(yul::ASTCopier().translate(*code)); + object.code = std::make_shared(yul::ASTCopier().translate(code->root())); object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object)); m_context.optimizeYul(object, *dialect, m_optimiserSettings); @@ -954,7 +954,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) } yul::CodeGenerator::assemble( - *code, + code->root(), *analysisInfo, *m_context.assemblyPtr(), m_context.evmVersion(), diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 4f4f96329..459959604 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2252,7 +2252,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) m_context.setMemoryUnsafeInlineAssemblySeen(); CopyTranslate bodyCopier{_inlineAsm.dialect(), m_context, _inlineAsm.annotation().externalReferences}; - yul::Statement modified = bodyCopier(_inlineAsm.operations()); + yul::Statement modified = bodyCopier(_inlineAsm.operations().root()); solAssert(std::holds_alternative(modified)); diff --git a/libsolidity/experimental/analysis/TypeInference.cpp b/libsolidity/experimental/analysis/TypeInference.cpp index 6913dc0bf..19f019c86 100644 --- a/libsolidity/experimental/analysis/TypeInference.cpp +++ b/libsolidity/experimental/analysis/TypeInference.cpp @@ -302,7 +302,7 @@ bool TypeInference::visit(InlineAssembly const& _inlineAssembly) _inlineAssembly.dialect(), identifierAccess ); - if (!analyzer.analyze(_inlineAssembly.operations())) + if (!analyzer.analyze(_inlineAssembly.operations().root())) solAssert(m_errorReporter.hasErrors()); return false; } diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index 109c3ee6f..3c8bcc9bb 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -130,7 +130,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tupleExpression) bool IRGeneratorForStatements::visit(InlineAssembly const& _assembly) { CopyTranslate bodyCopier{m_context, _assembly.dialect(), _assembly.annotation().externalReferences}; - yul::Statement modified = bodyCopier(_assembly.operations()); + yul::Statement modified = bodyCopier(_assembly.operations().root()); solAssert(std::holds_alternative(modified)); m_code << yul::AsmPrinter(yul::AsmPrinter::TypePrinting::Full, _assembly.dialect())(std::get(modified)) << "\n"; return false; diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 44282289d..7e338d9f8 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -313,7 +313,7 @@ bool SMTEncoder::visit(InlineAssembly const& _inlineAsm) { AssignedExternalsCollector(InlineAssembly const& _inlineAsm): externalReferences(_inlineAsm.annotation().externalReferences) { - this->operator()(_inlineAsm.operations()); + this->operator()(_inlineAsm.operations().root()); } std::map const& externalReferences; @@ -330,7 +330,7 @@ bool SMTEncoder::visit(InlineAssembly const& _inlineAsm) } }; - yul::SideEffectsCollector sideEffectsCollector(_inlineAsm.dialect(), _inlineAsm.operations()); + yul::SideEffectsCollector sideEffectsCollector(_inlineAsm.dialect(), _inlineAsm.operations().root()); if (sideEffectsCollector.invalidatesMemory()) resetMemoryVariables(); if (sideEffectsCollector.invalidatesStorage()) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index de7b185d2..dd5d20126 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -846,9 +846,9 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run ErrorReporter errorReporter(errors); CharStream charStream(source, sourceName); yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); - std::shared_ptr parserResult = yul::Parser{errorReporter, dialect}.parse(charStream); + std::shared_ptr parserResult = yul::Parser{errorReporter, dialect}.parse(charStream); solAssert(parserResult, ""); - sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex}(*parserResult); + sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex}(parserResult->root()); sources[0]["name"] = sourceName; sources[0]["id"] = sourceIndex; sources[0]["language"] = "Yul"; diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index b51eb9c44..5c28c44f2 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1473,12 +1473,12 @@ ASTPointer Parser::parseInlineAssembly(ASTPointer con } yul::Parser asmParser(m_errorReporter, dialect); - std::shared_ptr block = asmParser.parseInline(m_scanner); - if (block == nullptr) + std::shared_ptr ast = asmParser.parseInline(m_scanner); + if (ast == nullptr) BOOST_THROW_EXCEPTION(FatalError()); - location.end = nativeLocationOf(*block).end; - return std::make_shared(nextID(), location, _docString, dialect, std::move(flags), block); + location.end = nativeLocationOf(ast->root()).end; + return std::make_shared(nextID(), location, _docString, dialect, std::move(flags), ast); } ASTPointer Parser::parseIfStatement(ASTPointer const& _docString) diff --git a/libyul/AST.h b/libyul/AST.h index 72be60a46..ca4846907 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -101,6 +101,18 @@ struct Continue { langutil::DebugData::ConstPtr debugData; }; /// Leave statement (valid within function) struct Leave { langutil::DebugData::ConstPtr debugData; }; +/// Immutable AST comprised of its top-level block +class AST +{ +public: + explicit AST(Block _root): m_root(std::move(_root)) {} + + Block const& root() const { return m_root; } +private: + Block m_root; +}; + + /// Extracts the IR source location from a Yul node. template inline langutil::SourceLocation nativeLocationOf(T const& _node) { diff --git a/libyul/ASTForward.h b/libyul/ASTForward.h index 12992edf8..f6fa09387 100644 --- a/libyul/ASTForward.h +++ b/libyul/ASTForward.h @@ -46,6 +46,7 @@ struct Continue; struct Leave; struct ExpressionStatement; struct Block; +class AST; struct TypedName; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index cccb3de42..dae945fe8 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -85,6 +85,15 @@ bool AsmAnalyzer::analyze(Block const& _block) } AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object) +{ + return analyzeStrictAssertCorrect(_dialect, _object.code->root(), _object.qualifiedDataNames()); +} + +AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( + Dialect const& _dialect, + Block const& _astRoot, + std::set const& _qualifiedDataNames +) { ErrorList errorList; langutil::ErrorReporter errors(errorList); @@ -94,8 +103,8 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, errors, _dialect, {}, - _object.qualifiedDataNames() - ).analyze(*_object.code); + _qualifiedDataNames + ).analyze(_astRoot); yulAssert(success && !errors.hasErrors(), "Invalid assembly/yul code."); return analysisInfo; } diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 5aa7fe496..d479a9970 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -78,6 +78,11 @@ class AsmAnalyzer /// Performs analysis on the outermost code of the given object and returns the analysis info. /// Asserts on failure. static AsmAnalysisInfo analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object); + static AsmAnalysisInfo analyzeStrictAssertCorrect( + Dialect const& _dialect, + Block const& _astRoot, + std::set const& _qualifiedDataNames + ); std::vector operator()(Literal const& _literal); std::vector operator()(Identifier const&); diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index 8f211f31b..65ff22999 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -49,6 +49,11 @@ SourceLocation const AsmJsonImporter::createSourceLocation(Json const& _node) return solidity::langutil::parseSourceLocation(_node["src"].get(), m_sourceNames); } +AST AsmJsonImporter::createAST(solidity::Json const& _node) +{ + return AST(createBlock(_node)); +} + template T AsmJsonImporter::createAsmNode(Json const& _node) { diff --git a/libyul/AsmJsonImporter.h b/libyul/AsmJsonImporter.h index 87933761a..d835e99e3 100644 --- a/libyul/AsmJsonImporter.h +++ b/libyul/AsmJsonImporter.h @@ -41,8 +41,8 @@ class AsmJsonImporter explicit AsmJsonImporter(std::vector> const& _sourceNames): m_sourceNames(_sourceNames) {} - yul::Block createBlock(Json const& _node); + yul::AST createAST(Json const& node); private: langutil::SourceLocation const createSourceLocation(Json const& _node); template @@ -51,6 +51,7 @@ class AsmJsonImporter /// and throw an error if it does not exist Json member(Json const& _node, std::string const& _name); + yul::Block createBlock(Json const& _node); yul::Statement createStatement(Json const& _node); yul::Expression createExpression(Json const& _node); std::vector createStatementVector(Json const& _array); diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 41bef57fe..6223a1a8e 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -104,15 +104,15 @@ void Parser::updateLocationEndFrom( } } -std::unique_ptr Parser::parse(CharStream& _charStream) +std::unique_ptr Parser::parse(CharStream& _charStream) { m_scanner = std::make_shared(_charStream); - std::unique_ptr block = parseInline(m_scanner); + std::unique_ptr ast = parseInline(m_scanner); expectToken(Token::EOS); - return block; + return ast; } -std::unique_ptr Parser::parseInline(std::shared_ptr const& _scanner) +std::unique_ptr Parser::parseInline(std::shared_ptr const& _scanner) { m_recursionDepth = 0; @@ -125,7 +125,7 @@ std::unique_ptr Parser::parseInline(std::shared_ptr const& _scan m_scanner = _scanner; if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments) fetchDebugDataFromComment(); - return std::make_unique(parseBlock()); + return std::make_unique(parseBlock()); } catch (FatalError const& error) { diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 408c8029c..dd206b5b1 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -87,12 +87,12 @@ class Parser: public langutil::ParserBase /// Parses an inline assembly block starting with `{` and ending with `}`. /// @returns an empty shared pointer on error. - std::unique_ptr parseInline(std::shared_ptr const& _scanner); + std::unique_ptr parseInline(std::shared_ptr const& _scanner); /// Parses an assembly block starting with `{` and ending with `}` /// and expects end of input after the '}'. /// @returns an empty shared pointer on error. - std::unique_ptr parse(langutil::CharStream& _charStream); + std::unique_ptr parse(langutil::CharStream& _charStream); protected: langutil::SourceLocation currentLocation() const override diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index 9e18f48d8..76affbd64 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -33,15 +33,22 @@ using namespace solidity::util; CompilabilityChecker::CompilabilityChecker( Dialect const& _dialect, Object const& _object, - bool _optimizeStackAllocation + bool _optimizeStackAllocation, + Block const* _block ) { + yulAssert(_object.code || _block); if (auto const* evmDialect = dynamic_cast(&_dialect)) { + if (!_block) + _block = &_object.code->root(); NoOutputEVMDialect noOutputDialect(*evmDialect); - yul::AsmAnalysisInfo analysisInfo = - yul::AsmAnalyzer::analyzeStrictAssertCorrect(noOutputDialect, _object); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( + noOutputDialect, + *_block, + _object.qualifiedDataNames() + ); BuiltinContext builtinContext; builtinContext.currentObject = &_object; @@ -53,12 +60,12 @@ CompilabilityChecker::CompilabilityChecker( CodeTransform transform( assembly, analysisInfo, - *_object.code, + *_block, noOutputDialect, builtinContext, _optimizeStackAllocation ); - transform(*_object.code); + transform(*_block); for (StackTooDeepError const& error: transform.stackErrors()) { diff --git a/libyul/CompilabilityChecker.h b/libyul/CompilabilityChecker.h index 89bb7aa7c..1dd669990 100644 --- a/libyul/CompilabilityChecker.h +++ b/libyul/CompilabilityChecker.h @@ -44,7 +44,12 @@ namespace solidity::yul */ struct CompilabilityChecker { - CompilabilityChecker(Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation); + CompilabilityChecker( + Dialect const& _dialect, + Object const& _object, + bool _optimizeStackAllocation, + Block const* _blockOverride = nullptr + ); std::map> unreachableVariables; std::map stackDeficit; }; diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 989e7ce80..98649b29b 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -69,7 +69,7 @@ std::string Object::toString( debugData->sourceNames, _debugInfoSelection, _soliditySourceProvider - )(*code); + )(code->root()); for (auto const& obj: subObjects) inner += "\n" + obj->toString(_dialect, _printingMode, _debugInfoSelection, _soliditySourceProvider); @@ -91,7 +91,7 @@ Json Object::toJson() const Json codeJson; codeJson["nodeType"] = "YulCode"; - codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */)(*code); + codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */)(code->root()); Json subObjectsJson = Json::array(); for (std::shared_ptr const& subObject: subObjects) diff --git a/libyul/Object.h b/libyul/Object.h index c419a6d55..cab3bc701 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -122,7 +122,7 @@ struct Object: public ObjectNode /// sub id for object if it is subobject of another object, max value if it is not subobject size_t subId = std::numeric_limits::max(); - std::shared_ptr code; + std::shared_ptr code; std::vector> subObjects; std::map> subIndexByName; std::shared_ptr analysisInfo; diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 1f5363fd8..6813e5059 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -106,7 +106,7 @@ std::shared_ptr ObjectParser::parseObject(Object* _containingObject) return ret; } -std::shared_ptr ObjectParser::parseCode(std::optional _sourceNames) +std::shared_ptr ObjectParser::parseCode(std::optional _sourceNames) { if (currentToken() != Token::Identifier || currentLiteral() != "code") fatalParserError(4846_error, "Expected keyword \"code\"."); @@ -169,12 +169,12 @@ std::optional ObjectParser::tryParseSourceNameMapping() const return std::nullopt; } -std::shared_ptr ObjectParser::parseBlock(std::optional _sourceNames) +std::shared_ptr ObjectParser::parseBlock(std::optional _sourceNames) { Parser parser(m_errorReporter, m_dialect, std::move(_sourceNames)); - std::shared_ptr block = parser.parseInline(m_scanner); - yulAssert(block || m_errorReporter.hasErrors(), "Invalid block but no error!"); - return block; + auto ast = parser.parseInline(m_scanner); + yulAssert(ast || m_errorReporter.hasErrors(), "Invalid block but no error!"); + return ast; } void ObjectParser::parseData(Object& _containingObject) diff --git a/libyul/ObjectParser.h b/libyul/ObjectParser.h index a8f75d373..1d7756f5a 100644 --- a/libyul/ObjectParser.h +++ b/libyul/ObjectParser.h @@ -57,8 +57,8 @@ class ObjectParser: public langutil::ParserBase private: std::optional tryParseSourceNameMapping() const; std::shared_ptr parseObject(Object* _containingObject = nullptr); - std::shared_ptr parseCode(std::optional _sourceNames); - std::shared_ptr parseBlock(std::optional _sourceNames); + std::shared_ptr parseCode(std::optional _sourceNames); + std::shared_ptr parseBlock(std::optional _sourceNames); void parseData(Object& _containingObject); /// Tries to parse a name that is non-empty and unique inside the containing object. diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index b9fc6388c..426551152 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -149,7 +149,7 @@ bool YulStack::analyzeParsed(Object& _object) bool success = false; try { - success = analyzer.analyze(*_object.code); + success = analyzer.analyze(_object.code->root()); for (auto& subNode: _object.subObjects) if (auto subObject = dynamic_cast(subNode.get())) if (!analyzeParsed(*subObject)) diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index 422c08bf9..c77bf4e37 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -83,7 +83,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) auto stackErrors = OptimizedEVMCodeTransform::run( m_assembly, *_object.analysisInfo, - *_object.code, + _object.code->root(), m_dialect, context, OptimizedEVMCodeTransform::UseNamedLabels::ForFirstFunctionOfEachName @@ -91,7 +91,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) if (!stackErrors.empty()) { std::vector memoryGuardCalls = findFunctionCalls( - std::as_const(*_object.code), + _object.code->root(), "memoryguard"_yulname ); auto stackError = stackErrors.front(); @@ -113,14 +113,14 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) CodeTransform transform{ m_assembly, *_object.analysisInfo, - *_object.code, + _object.code->root(), m_dialect, context, _optimize, {}, CodeTransform::UseNamedLabels::ForFirstFunctionOfEachName }; - transform(*_object.code); + transform(_object.code->root()); if (!transform.stackErrors().empty()) BOOST_THROW_EXCEPTION(transform.stackErrors().front()); } diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index 7dbbb676b..88f4f7c45 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -95,7 +95,7 @@ bool MSizeFinder::containsMSize(Dialect const& _dialect, Block const& _ast) bool MSizeFinder::containsMSize(Dialect const& _dialect, Object const& _object) { - if (containsMSize(_dialect, *_object.code)) + if (containsMSize(_dialect, _object.code->root())) return true; for (std::shared_ptr const& node: _object.subObjects) diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 23d47b6ee..10360756d 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -241,10 +242,23 @@ bool StackCompressor::run( bool _optimizeStackAllocation, size_t _maxIterations ) +{ + yulAssert(_object.code); + auto block = std::get(ASTCopier{}(_object.code->root())); + auto result = run(_dialect, block, _object, _optimizeStackAllocation, _maxIterations); + _object.code = std::make_shared(std::move(block)); + return result; +} + +bool StackCompressor::run( + Dialect const& _dialect, + Block& _astRoot, + Object const& _object, + bool _optimizeStackAllocation, + size_t _maxIterations) { yulAssert( - _object.code && - _object.code->statements.size() > 0 && std::holds_alternative(_object.code->statements.at(0)), + !_astRoot.statements.empty() && std::holds_alternative(_astRoot.statements.at(0)), "Need to run the function grouper before the stack compressor." ); bool usesOptimizedCodeGenerator = false; @@ -253,14 +267,14 @@ bool StackCompressor::run( _optimizeStackAllocation && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); - bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, *_object.code); + bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _astRoot); if (usesOptimizedCodeGenerator) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, *_object.code); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _astRoot, _object.qualifiedDataNames()); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, _astRoot); eliminateVariablesOptimizedCodegen( _dialect, - *_object.code, + _astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg), allowMSizeOptimization ); @@ -268,12 +282,12 @@ bool StackCompressor::run( else for (size_t iterations = 0; iterations < _maxIterations; iterations++) { - std::map stackSurplus = CompilabilityChecker(_dialect, _object, _optimizeStackAllocation).stackDeficit; + std::map stackSurplus = CompilabilityChecker(_dialect, _object, _optimizeStackAllocation, &_astRoot).stackDeficit; if (stackSurplus.empty()) return true; eliminateVariables( _dialect, - *_object.code, + _astRoot, stackSurplus, allowMSizeOptimization ); diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index d18618667..13b9459a2 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -44,7 +44,7 @@ struct FunctionDefinition; class StackCompressor { public: - /// Try to remove local variables until the AST is compilable. + /// Try to remove local variables until the AST is compilable. Modifies the object's AST. /// @returns true if it was successful. static bool run( Dialect const& _dialect, @@ -52,6 +52,17 @@ class StackCompressor bool _optimizeStackAllocation, size_t _maxIterations ); + + /// Try to remove local variables until the AST is compilable. Operates on provided block, + /// disregards the AST contained in object. + /// @returns true if it was successful. + static bool run( + Dialect const& _dialect, + Block& _astRoot, + Object const& _object, + bool _optimizeStackAllocation, + size_t _maxIterations + ); }; } diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 24712938f..210be1cf3 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -119,7 +119,8 @@ u256 literalArgumentValue(FunctionCall const& _call) void StackLimitEvader::run( OptimiserStepContext& _context, - Object& _object + Block& _astRoot, + Object const& _object ) { auto const* evmDialect = dynamic_cast(&_context.dialect); @@ -129,22 +130,23 @@ void StackLimitEvader::run( ); if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall()) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, _object); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, *_object.code); - run(_context, _object, StackLayoutGenerator::reportStackTooDeep(*cfg)); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, _astRoot, _object.qualifiedDataNames()); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, _astRoot); + run(_context, _astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg)); } else - run(_context, _object, CompilabilityChecker{ + run(_context, _astRoot, CompilabilityChecker{ _context.dialect, _object, - true + true, + &_astRoot }.unreachableVariables); } void StackLimitEvader::run( OptimiserStepContext& _context, - Object& _object, + Block& _astRoot, std::map> const& _stackTooDeepErrors ) { @@ -158,23 +160,22 @@ void StackLimitEvader::run( if (!util::contains(unreachables, variable)) unreachables.emplace_back(variable); } - run(_context, _object, unreachableVariables); + run(_context, _astRoot, unreachableVariables); } void StackLimitEvader::run( OptimiserStepContext& _context, - Object& _object, + Block& _astRoot, std::map> const& _unreachableVariables ) { - yulAssert(_object.code, ""); auto const* evmDialect = dynamic_cast(&_context.dialect); yulAssert( evmDialect && evmDialect->providesObjectAccess(), "StackLimitEvader can only be run on objects using the EVMDialect with object access." ); - std::vector memoryGuardCalls = findFunctionCalls(*_object.code, "memoryguard"_yulname); + std::vector memoryGuardCalls = findFunctionCalls(_astRoot, "memoryguard"_yulname); // Do not optimise, if no ``memoryguard`` call is found. if (memoryGuardCalls.empty()) return; @@ -187,23 +188,23 @@ void StackLimitEvader::run( if (reservedMemory != literalArgumentValue(*memoryGuardCall)) return; - CallGraph callGraph = CallGraphGenerator::callGraph(*_object.code); + CallGraph callGraph = CallGraphGenerator::callGraph(_astRoot); // We cannot move variables in recursive functions to fixed memory offsets. for (YulName function: callGraph.recursiveFunctions()) if (_unreachableVariables.count(function)) return; - std::map functionDefinitions = allFunctionDefinitions(*_object.code); + std::map functionDefinitions = allFunctionDefinitions(_astRoot); MemoryOffsetAllocator memoryOffsetAllocator{_unreachableVariables, callGraph.functionCalls, functionDefinitions}; uint64_t requiredSlots = memoryOffsetAllocator.run(); yulAssert(requiredSlots < (uint64_t(1) << 32) - 1, ""); - StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, *_object.code); + StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, _astRoot); reservedMemory += 32 * requiredSlots; - for (FunctionCall* memoryGuardCall: findFunctionCalls(*_object.code, "memoryguard"_yulname)) + for (FunctionCall* memoryGuardCall: findFunctionCalls(_astRoot, "memoryguard"_yulname)) { Literal* literal = std::get_if(&memoryGuardCall->arguments.front()); yulAssert(literal && literal->kind == LiteralKind::Number, ""); diff --git a/libyul/optimiser/StackLimitEvader.h b/libyul/optimiser/StackLimitEvader.h index 0411f0573..5029f7825 100644 --- a/libyul/optimiser/StackLimitEvader.h +++ b/libyul/optimiser/StackLimitEvader.h @@ -59,7 +59,7 @@ class StackLimitEvader /// are contained in a recursive function. static void run( OptimiserStepContext& _context, - Object& _object, + Block& _astRoot, std::map> const& _unreachableVariables ); /// @a _stackTooDeepErrors can be determined by the StackLayoutGenerator. @@ -69,7 +69,7 @@ class StackLimitEvader /// are contained in a recursive function. static void run( OptimiserStepContext& _context, - Object& _object, + Block& _astRoot, std::map> const& _stackTooDeepErrors ); /// Determines stack too deep errors using the appropriate code generation backend. @@ -79,7 +79,8 @@ class StackLimitEvader /// are contained in a recursive function. static void run( OptimiserStepContext& _context, - Object& _object + Block& _astRoot, + Object const& _object ); }; diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index c022fb0d7..b8826bb8a 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -153,74 +153,76 @@ void OptimiserSuite::run( std::set reservedIdentifiers = _externallyUsedIdentifiers; reservedIdentifiers += _dialect.fixedFunctionNames(); - *_object.code = std::get(Disambiguator( + auto astRoot = std::get(Disambiguator( _dialect, *_object.analysisInfo, reservedIdentifiers - )(*_object.code)); - Block& ast = *_object.code; + )(_object.code->root())); - NameDispenser dispenser{_dialect, ast, reservedIdentifiers}; + NameDispenser dispenser{_dialect, astRoot, reservedIdentifiers}; OptimiserStepContext context{_dialect, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment}; OptimiserSuite suite(context, Debug::None); // Some steps depend on properties ensured by FunctionHoister, BlockFlattener, FunctionGrouper and // ForLoopInitRewriter. Run them first to be able to run arbitrary sequences safely. - suite.runSequence("hgfo", ast); + suite.runSequence("hgfo", astRoot); - NameSimplifier::run(suite.m_context, ast); + NameSimplifier::run(suite.m_context, astRoot); // Now the user-supplied part - suite.runSequence(_optimisationSequence, ast); + suite.runSequence(_optimisationSequence, astRoot); // This is a tuning parameter, but actually just prevents infinite loops. size_t stackCompressorMaxIterations = 16; - suite.runSequence("g", ast); + suite.runSequence("g", astRoot); // We ignore the return value because we will get a much better error // message once we perform code generation. if (!usesOptimizedCodeGenerator) StackCompressor::run( _dialect, + astRoot, _object, _optimizeStackAllocation, stackCompressorMaxIterations ); // Run the user-supplied clean up sequence - suite.runSequence(_optimisationCleanupSequence, ast); + suite.runSequence(_optimisationCleanupSequence, astRoot); // Hard-coded FunctionGrouper step is used to bring the AST into a canonical form required by the StackCompressor // and StackLimitEvader. This is hard-coded as the last step, as some previously executed steps may break the // aforementioned form, thus causing the StackCompressor/StackLimitEvader to throw. - suite.runSequence("g", ast); + suite.runSequence("g", astRoot); if (evmDialect) { yulAssert(_meter, ""); - ConstantOptimiser{*evmDialect, *_meter}(ast); + ConstantOptimiser{*evmDialect, *_meter}(astRoot); if (usesOptimizedCodeGenerator) { StackCompressor::run( _dialect, + astRoot, _object, _optimizeStackAllocation, stackCompressorMaxIterations ); if (evmDialect->providesObjectAccess()) - StackLimitEvader::run(suite.m_context, _object); + StackLimitEvader::run(suite.m_context, astRoot, _object); } else if (evmDialect->providesObjectAccess() && _optimizeStackAllocation) - StackLimitEvader::run(suite.m_context, _object); + StackLimitEvader::run(suite.m_context, astRoot, _object); } - dispenser.reset(ast); - NameSimplifier::run(suite.m_context, ast); - VarNameCleaner::run(suite.m_context, ast); + dispenser.reset(astRoot); + NameSimplifier::run(suite.m_context, astRoot); + VarNameCleaner::run(suite.m_context, astRoot); #ifdef PROFILE_OPTIMIZER_STEPS outputPerformanceMetrics(suite.m_durationPerStepInMicroseconds); #endif + _object.code = std::make_shared(std::move(astRoot)); *_object.analysisInfo = AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object); } diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index 77274200b..c5579d84a 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -74,7 +75,7 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con auto handleObject = [&](std::string const& _kind, Object const& _object) { m_obtainedResult += contractName + "(" + _kind + ") " + (findFunctionCalls( - *_object.code, + _object.code->root(), "memoryguard"_yulname ).empty() ? "false" : "true") + "\n"; }; diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index dece0d82b..26f5e0684 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -50,7 +50,7 @@ Dialect const& defaultDialect(bool _yul) } } -std::pair, std::shared_ptr> yul::test::parse(std::string const& _source, bool _yul) +std::pair, std::shared_ptr> yul::test::parse(std::string const& _source, bool _yul) { YulStack stack( solidity::test::CommonOptions::get().evmVersion(), @@ -83,7 +83,7 @@ std::pair, std::shared_ptr> yul::t std::shared_ptr analysisInfo = std::make_shared(); AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect, {}, parserResult->qualifiedDataNames()); // TODO this should be done recursively. - if (!analyzer.analyze(*parserResult->code) || errorReporter.hasErrors()) + if (!analyzer.analyze(parserResult->code->root()) || errorReporter.hasErrors()) return {}; return {std::move(parserResult), std::move(analysisInfo)}; } @@ -91,14 +91,14 @@ std::pair, std::shared_ptr> yul::t yul::Block yul::test::disambiguate(std::string const& _source, bool _yul) { auto result = parse(_source, _yul); - return std::get(Disambiguator(defaultDialect(_yul), *result.second, {})(*result.first)); + return std::get(Disambiguator(defaultDialect(_yul), *result.second, {})(result.first->root())); } std::string yul::test::format(std::string const& _source, bool _yul) { auto const version = solidity::test::CommonOptions::get().evmVersion(); Dialect const& dialect = _yul ? EVMDialectTyped::instance(version) : EVMDialect::strictAssemblyForEVMObjects(version); - return yul::AsmPrinter(yul::AsmPrinter::TypePrinting::Full, dialect)(*parse(_source, _yul).first); + return yul::AsmPrinter(yul::AsmPrinter::TypePrinting::Full, dialect)(parse(_source, _yul).first->root()); } namespace diff --git a/test/libyul/Common.h b/test/libyul/Common.h index f6c63feb9..4a9696cd9 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -39,12 +39,13 @@ struct AsmAnalysisInfo; struct Block; struct Object; struct Dialect; +class AST; } namespace solidity::yul::test { -std::pair, std::shared_ptr> +std::pair, std::shared_ptr> parse(std::string const& _source, bool _yul = true); std::pair, std::shared_ptr> diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index 9a0e6f092..8e08bf488 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -206,7 +206,7 @@ TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::strin std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, *object->code); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code->root()); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; ControlFlowGraphPrinter printer{output}; diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index 6ac5a7b0a..054c70547 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -63,10 +63,10 @@ TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std: ControlFlowSideEffectsCollector sideEffects( EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), - *obj.code + obj.code->root() ); m_obtainedResult.clear(); - forEach(*obj.code, [&](FunctionDefinition const& _fun) { + forEach(obj.code->root(), [&](FunctionDefinition const& _fun) { std::string effectStr = toString(sideEffects.functionSideEffects().at(&_fun)); m_obtainedResult += _fun.name.str() + (effectStr.empty() ? ":" : ": " + effectStr) + "\n"; }); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index f1bd0ea37..3220a8c6f 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -89,7 +89,7 @@ TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string std::map functionSideEffects = SideEffectsPropagator::sideEffects( EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), - CallGraphGenerator::callGraph(*obj.code) + CallGraphGenerator::callGraph(obj.code->root()) ); std::map functionSideEffectsStr; diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index 6a9d3e6da..a149381ca 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -48,15 +49,17 @@ class KnowledgeBaseTest std::tie(m_object, analysisInfo) = yul::test::parse(_source, m_dialect, errorList); BOOST_REQUIRE(m_object && errorList.empty() && m_object->code); - NameDispenser dispenser(m_dialect, *m_object->code); + auto astRoot = std::get(yul::ASTCopier{}(m_object->code->root())); + NameDispenser dispenser(m_dialect, astRoot); std::set reserved; OptimiserStepContext context{m_dialect, dispenser, reserved, 0}; - CommonSubexpressionEliminator::run(context, *m_object->code); + CommonSubexpressionEliminator::run(context, astRoot); - m_ssaValues(*m_object->code); + m_ssaValues(astRoot); for (auto const& [name, expression]: m_ssaValues.values()) m_values[name].value = expression; + m_object->code = std::make_shared(std::move(astRoot)); return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }); } diff --git a/test/libyul/Metrics.cpp b/test/libyul/Metrics.cpp index ac3153433..ce65cf2c8 100644 --- a/test/libyul/Metrics.cpp +++ b/test/libyul/Metrics.cpp @@ -37,9 +37,9 @@ namespace size_t codeSize(std::string const& _source, CodeWeights const _weights = {}) { - std::shared_ptr ast = parse(_source, false).first; + std::shared_ptr ast = parse(_source, false).first; BOOST_REQUIRE(ast); - return CodeSize::codeSize(*ast, _weights); + return CodeSize::codeSize(ast->root(), _weights); } } diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 7b3cdac8b..0ed09f6a9 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -54,7 +54,7 @@ namespace solidity::yul::test namespace { -std::shared_ptr parse(std::string const& _source, Dialect const& _dialect, ErrorReporter& errorReporter) +std::shared_ptr parse(std::string const& _source, Dialect const& _dialect, ErrorReporter& errorReporter) { auto stream = CharStream(_source, ""); std::map> indicesToSourceNames; @@ -73,7 +73,7 @@ std::shared_ptr parse(std::string const& _source, Dialect const& _dialect analysisInfo, errorReporter, _dialect - ).analyze(*parserResult)) + ).analyze(parserResult->root())) return parserResult; } return {}; @@ -152,7 +152,7 @@ BOOST_AUTO_TEST_CASE(default_types_set) { ErrorList errorList; ErrorReporter reporter(errorList); - std::shared_ptr result = parse( + std::shared_ptr result = parse( "{" "let x:bool := true:bool " "let z:bool := true " @@ -165,7 +165,7 @@ BOOST_AUTO_TEST_CASE(default_types_set) BOOST_REQUIRE(!!result && errorList.size() == 0); // All types are printed. - BOOST_CHECK_EQUAL(AsmPrinter(AsmPrinter::TypePrinting::Full, EVMDialectTyped::instance(EVMVersion()))(*result), + BOOST_CHECK_EQUAL(AsmPrinter(AsmPrinter::TypePrinting::Full, EVMDialectTyped::instance(EVMVersion()))(result->root()), "{\n" " let x:bool := true:bool\n" " let z:bool := true:bool\n" @@ -177,7 +177,7 @@ BOOST_AUTO_TEST_CASE(default_types_set) ); // Now the default types should be omitted. - BOOST_CHECK_EQUAL(AsmPrinter(AsmPrinter::TypePrinting::OmitDefault, EVMDialectTyped::instance(EVMVersion()))(*result), + BOOST_CHECK_EQUAL(AsmPrinter(AsmPrinter::TypePrinting::OmitDefault, EVMDialectTyped::instance(EVMVersion()))(result->root()), "{\n" " let x:bool := true\n" " let z:bool := true\n" @@ -204,9 +204,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_empty_block) "/// @src 0:234:543\n" "{}\n"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); } BOOST_AUTO_TEST_CASE(customSourceLocations_block_with_children) @@ -222,14 +222,14 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_with_children) "let y := add(1, 2)\n" "}\n"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); - CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); - BOOST_REQUIRE_EQUAL(3, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(0)), "source0", 234, 543); - CHECK_LOCATION(originLocationOf(result->statements.at(1)), "source0", 123, 432); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); + BOOST_REQUIRE_EQUAL(3, result->root().statements.size()); + CHECK_LOCATION(originLocationOf(result->root().statements.at(0)), "source0", 234, 543); + CHECK_LOCATION(originLocationOf(result->root().statements.at(1)), "source0", 123, 432); // [2] is inherited source location - CHECK_LOCATION(originLocationOf(result->statements.at(2)), "source0", 123, 432); + CHECK_LOCATION(originLocationOf(result->root().statements.at(2)), "source0", 123, 432); } BOOST_AUTO_TEST_CASE(customSourceLocations_block_different_sources) @@ -245,14 +245,14 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_different_sources) "let y := add(1, 2)\n" "}\n"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); - BOOST_REQUIRE_EQUAL(3, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(0)), "source0", 234, 543); - CHECK_LOCATION(originLocationOf(result->statements.at(1)), "source1", 123, 432); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); + BOOST_REQUIRE_EQUAL(3, result->root().statements.size()); + CHECK_LOCATION(originLocationOf(result->root().statements.at(0)), "source0", 234, 543); + CHECK_LOCATION(originLocationOf(result->root().statements.at(1)), "source1", 123, 432); // [2] is inherited source location - CHECK_LOCATION(originLocationOf(result->statements.at(2)), "source1", 123, 432); + CHECK_LOCATION(originLocationOf(result->root().statements.at(2)), "source1", 123, 432); } BOOST_AUTO_TEST_CASE(customSourceLocations_block_nested) @@ -267,11 +267,11 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_nested) "switch y case 0 {} default {}\n" "}\n"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); - BOOST_REQUIRE_EQUAL(2, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(1)), "source0", 343, 434); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); + BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); + CHECK_LOCATION(originLocationOf(result->root().statements.at(1)), "source0", 343, 434); } BOOST_AUTO_TEST_CASE(customSourceLocations_block_switch_case) @@ -291,13 +291,13 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_switch_case) "}\n" "}\n"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); - BOOST_REQUIRE_EQUAL(2, result->statements.size()); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(1))); - auto const& switchStmt = std::get(result->statements.at(1)); + BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(1))); + auto const& switchStmt = std::get(result->root().statements.at(1)); CHECK_LOCATION(switchStmt.debugData->originLocation, "source0", 343, 434); BOOST_REQUIRE_EQUAL(1, switchStmt.cases.size()); @@ -323,22 +323,22 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_inherit_into_outer_scope) "let y := add(1, 2)\n" "}\n"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 1, 100); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 1, 100); - BOOST_REQUIRE_EQUAL(3, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(0)), "source0", 1, 100); + BOOST_REQUIRE_EQUAL(3, result->root().statements.size()); + CHECK_LOCATION(originLocationOf(result->root().statements.at(0)), "source0", 1, 100); // First child element must be a block itself with one statement. - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - BOOST_REQUIRE_EQUAL(std::get(result->statements.at(0)).statements.size(), 1); - CHECK_LOCATION(originLocationOf(std::get(result->statements.at(0)).statements.at(0)), "source0", 123, 432); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); + BOOST_REQUIRE_EQUAL(std::get(result->root().statements.at(0)).statements.size(), 1); + CHECK_LOCATION(originLocationOf(std::get(result->root().statements.at(0)).statements.at(0)), "source0", 123, 432); // The next two elements have an inherited source location from the prior inner scope. - CHECK_LOCATION(originLocationOf(result->statements.at(1)), "source0", 123, 432); - CHECK_LOCATION(originLocationOf(result->statements.at(2)), "source0", 123, 432); + CHECK_LOCATION(originLocationOf(result->root().statements.at(1)), "source0", 123, 432); + CHECK_LOCATION(originLocationOf(result->root().statements.at(2)), "source0", 123, 432); } BOOST_AUTO_TEST_CASE(customSourceLocations_assign_empty) @@ -354,11 +354,11 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_assign_empty) "a := true:bool\n" "}\n"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // should still parse - BOOST_REQUIRE_EQUAL(2, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(0)), "source0", 123, 432); - CHECK_LOCATION(originLocationOf(result->statements.at(1)), "source1", 1, 10); + BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); + CHECK_LOCATION(originLocationOf(result->root().statements.at(0)), "source0", 123, 432); + CHECK_LOCATION(originLocationOf(result->root().statements.at(1)), "source1", 1, 10); } BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_source_index) @@ -375,7 +375,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_source_index) "\n" "}\n"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); // should still parse BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -395,13 +395,13 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_1) ":= true:bool\n" "}\n"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(1, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(0)), "source0", 123, 432); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varDecl = std::get(result->statements.at(0)); + BOOST_REQUIRE_EQUAL(1, result->root().statements.size()); + CHECK_LOCATION(originLocationOf(result->root().statements.at(0)), "source0", 123, 432); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); + VariableDeclaration const& varDecl = std::get(result->root().statements.at(0)); CHECK_LOCATION(originLocationOf(*varDecl.value), "source0", 234, 2026); } @@ -418,14 +418,14 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_2) } )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(1, result->statements.size()); - CHECK_LOCATION(result->debugData->originLocation, "source0", 0, 5); + BOOST_REQUIRE_EQUAL(1, result->root().statements.size()); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 0, 5); // `let x := add(1, ` - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varDecl = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); + VariableDeclaration const& varDecl = std::get(result->root().statements.at(0)); CHECK_LOCATION(varDecl.debugData->originLocation, "source0", 0, 5); BOOST_REQUIRE(!!varDecl.value); BOOST_REQUIRE(std::holds_alternative(*varDecl.value)); @@ -452,24 +452,24 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_3) } )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(2, result->statements.size()); - CHECK_LOCATION(result->debugData->originLocation, "source1", 23, 45); + BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); + CHECK_LOCATION(result->root().debugData->originLocation, "source1", 23, 45); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - Block const& innerBlock = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); + Block const& innerBlock = std::get(result->root().statements.at(0)); CHECK_LOCATION(innerBlock.debugData->originLocation, "source1", 23, 45); BOOST_REQUIRE_EQUAL(1, innerBlock.statements.size()); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(1))); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(1))); ExpressionStatement const& sstoreStmt = std::get(innerBlock.statements.at(0)); BOOST_REQUIRE(std::holds_alternative(sstoreStmt.expression)); FunctionCall const& sstoreCall = std::get(sstoreStmt.expression); CHECK_LOCATION(sstoreCall.debugData->originLocation, "source1", 23, 45); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(1))); - ExpressionStatement mstoreStmt = std::get(result->statements.at(1)); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(1))); + ExpressionStatement mstoreStmt = std::get(result->root().statements.at(1)); BOOST_REQUIRE(std::holds_alternative(mstoreStmt.expression)); FunctionCall const& mstoreCall = std::get(mstoreStmt.expression); CHECK_LOCATION(mstoreCall.debugData->originLocation, "source0", 420, 680); @@ -488,13 +488,13 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_comments_after_valid) } )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(1, result->statements.size()); - CHECK_LOCATION(result->debugData->originLocation, "source1", 23, 45); + BOOST_REQUIRE_EQUAL(1, result->root().statements.size()); + CHECK_LOCATION(result->root().debugData->originLocation, "source1", 23, 45); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varDecl = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); + VariableDeclaration const& varDecl = std::get(result->root().statements.at(0)); CHECK_LOCATION(varDecl.debugData->originLocation, "source0", 420, 680); } @@ -507,12 +507,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_suffix) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 8387_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_prefix) @@ -524,9 +524,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_prefix) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_unspecified) @@ -538,9 +538,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_unspecified) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_non_integer) @@ -552,12 +552,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_non_integer) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 8387_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_bad_integer) @@ -569,12 +569,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_bad_integer) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 6367_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_ensure_last_match) @@ -590,10 +590,10 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_ensure_last_match) } )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varDecl = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); + VariableDeclaration const& varDecl = std::get(result->root().statements.at(0)); // Ensure the latest @src per documentation-comment is used (0:30:40). CHECK_LOCATION(varDecl.debugData->originLocation, "source0", 30, 40); @@ -608,12 +608,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_no_whitespace) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 8387_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_separated_with_single_space) @@ -625,9 +625,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_separated_with_single_s {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source1", 333, 444); + CHECK_LOCATION(result->root().debugData->originLocation, "source1", 333, 444); } BOOST_AUTO_TEST_CASE(customSourceLocations_leading_trailing_whitespace) @@ -636,9 +636,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_leading_trailing_whitespace) ErrorReporter reporter(errorList); auto const sourceText = "/// @src 0:111:222 \n{}"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); } BOOST_AUTO_TEST_CASE(customSourceLocations_reference_original_sloc) @@ -653,10 +653,10 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_reference_original_sloc) } )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varDecl = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); + VariableDeclaration const& varDecl = std::get(result->root().statements.at(0)); // -1 points to original source code, which in this case is `"source0"` (which is also CHECK_LOCATION(varDecl.debugData->originLocation, "", 10, 20); @@ -675,16 +675,16 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets) } )~~~"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(result->statements.size(), 2); + BOOST_REQUIRE_EQUAL(result->root().statements.size(), 2); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varX = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); + VariableDeclaration const& varX = std::get(result->root().statements.at(0)); CHECK_LOCATION(varX.debugData->originLocation, "source0", 149, 156); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(1))); - VariableDeclaration const& varY = std::get(result->statements.at(1)); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(1))); + VariableDeclaration const& varY = std::get(result->root().statements.at(1)); BOOST_REQUIRE(!!varY.value); BOOST_REQUIRE(std::holds_alternative(*varY.value)); Literal const& literal128 = std::get(*varY.value); @@ -700,9 +700,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_empty_snippet) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); } BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_before_snippet) @@ -714,12 +714,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_befo {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 8387_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_after_snippet) @@ -731,9 +731,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_afte {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); } BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_no_whitespace) @@ -745,9 +745,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_no_whites {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source1", 333, 444); + CHECK_LOCATION(result->root().debugData->originLocation, "source1", 333, 444); } BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_unterminated_quote) @@ -759,12 +759,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_untermina {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 1544_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote) @@ -777,12 +777,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 1544_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_two_snippets_with_hex_comment) @@ -794,11 +794,11 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_snippets_with_hex_comment) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // the second source location is not parsed as such, as the hex string isn't interpreted as snippet but // as the beginning of the tail in AsmParser - CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); } BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_escapes) @@ -810,9 +810,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_escapes) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); } BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote_snippet_with_whitespaces_and_escapes) @@ -825,9 +825,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote_snippet_with_whitespaces {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source1", 222, 333); + CHECK_LOCATION(result->root().debugData->originLocation, "source1", 222, 333); } BOOST_DATA_TEST_CASE(customSourceLocations_scanner_errors_outside_string_lits_are_ignored, boost::unit_test::data::make({"0x ", "/** unterminated comment", "1_23_4"}), invalid) @@ -840,9 +840,9 @@ BOOST_DATA_TEST_CASE(customSourceLocations_scanner_errors_outside_string_lits_ar {{}} )", invalid); EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.empty()); - CHECK_LOCATION(result->debugData->originLocation, "source1", 222, 333); + CHECK_LOCATION(result->root().debugData->originLocation, "source1", 222, 333); } BOOST_AUTO_TEST_CASE(customSourceLocations_multi_line_source_loc) @@ -858,9 +858,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multi_line_source_loc) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.empty()); - CHECK_LOCATION(result->debugData->originLocation, "source0", 333, 444); + CHECK_LOCATION(result->root().debugData->originLocation, "source0", 333, 444); } BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locations) @@ -876,16 +876,16 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locati } )~~~"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(result->statements.size(), 2); + BOOST_REQUIRE_EQUAL(result->root().statements.size(), 2); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varX = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); + VariableDeclaration const& varX = std::get(result->root().statements.at(0)); CHECK_LOCATION(varX.debugData->originLocation, "source0", 149, 156); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(1))); - VariableDeclaration const& varY = std::get(result->statements.at(1)); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(1))); + VariableDeclaration const& varY = std::get(result->root().statements.at(1)); BOOST_REQUIRE(!!varY.value); BOOST_REQUIRE(std::holds_alternative(*varY.value)); Literal const& literal128 = std::get(*varY.value); @@ -905,13 +905,13 @@ BOOST_AUTO_TEST_CASE(astid) } )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); - BOOST_CHECK(result->debugData->astID == int64_t(7)); - auto const& funDef = std::get(result->statements.at(0)); + BOOST_CHECK(result->root().debugData->astID == int64_t(7)); + auto const& funDef = std::get(result->root().statements.at(0)); BOOST_CHECK(funDef.debugData->astID == int64_t(2)); BOOST_CHECK(funDef.parameters.at(0).debugData->astID == std::nullopt); - BOOST_CHECK(debugDataOf(result->statements.at(1))->astID == std::nullopt); + BOOST_CHECK(debugDataOf(result->root().statements.at(1))->astID == std::nullopt); } BOOST_AUTO_TEST_CASE(astid_reset) @@ -927,13 +927,13 @@ BOOST_AUTO_TEST_CASE(astid_reset) } )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); - BOOST_CHECK(result->debugData->astID == int64_t(7)); - auto const& funDef = std::get(result->statements.at(0)); + BOOST_CHECK(result->root().debugData->astID == int64_t(7)); + auto const& funDef = std::get(result->root().statements.at(0)); BOOST_CHECK(funDef.debugData->astID == int64_t(2)); BOOST_CHECK(funDef.parameters.at(0).debugData->astID == std::nullopt); - BOOST_CHECK(debugDataOf(result->statements.at(1))->astID == std::nullopt); + BOOST_CHECK(debugDataOf(result->root().statements.at(1))->astID == std::nullopt); } BOOST_AUTO_TEST_CASE(astid_multi) @@ -945,9 +945,9 @@ BOOST_AUTO_TEST_CASE(astid_multi) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); - BOOST_CHECK(result->debugData->astID == int64_t(8)); + BOOST_CHECK(result->root().debugData->astID == int64_t(8)); } BOOST_AUTO_TEST_CASE(astid_invalid) @@ -959,12 +959,12 @@ BOOST_AUTO_TEST_CASE(astid_invalid) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 1749_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(astid_too_large) @@ -976,7 +976,7 @@ BOOST_AUTO_TEST_CASE(astid_too_large) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -992,7 +992,7 @@ BOOST_AUTO_TEST_CASE(astid_way_too_large) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -1008,7 +1008,7 @@ BOOST_AUTO_TEST_CASE(astid_not_fully_numeric) {} )"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -1030,12 +1030,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multiple_src_tags_on_one_line) " let x := 123\n" "}\n"; EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(result->statements.size(), 1); + BOOST_REQUIRE_EQUAL(result->root().statements.size(), 1); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varX = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); + VariableDeclaration const& varX = std::get(result->root().statements.at(0)); CHECK_LOCATION(varX.debugData->originLocation, "source1", 4, 5); } diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 02b03ccea..2abac60e5 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -224,7 +224,7 @@ TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::s std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, *object->code); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code->root()); StackLayout stackLayout = StackLayoutGenerator::run(*cfg); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index eb6a447d1..d987c519c 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -98,7 +99,7 @@ std::string YulInterpreterTest::interpret() Interpreter::run( state, EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion()), - *m_ast, + m_ast->root(), /*disableExternalCalls=*/ !m_simulateExternalCallsToSelf, /*disableMemoryTracing=*/ false ); diff --git a/test/libyul/YulInterpreterTest.h b/test/libyul/YulInterpreterTest.h index a20b0688a..f53686702 100644 --- a/test/libyul/YulInterpreterTest.h +++ b/test/libyul/YulInterpreterTest.h @@ -23,7 +23,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; -struct Block; +class AST; } namespace solidity::yul::test @@ -45,7 +45,7 @@ class YulInterpreterTest: public solidity::frontend::test::EVMVersionRestrictedT bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); std::string interpret(); - std::shared_ptr m_ast; + std::shared_ptr m_ast; std::shared_ptr m_analysisInfo; bool m_simulateExternalCallsToSelf = false; }; diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index b30fa8251..df28515c3 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -77,19 +78,23 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << std::endl; return TestResult::FatalError; } - - auto const printed = (m_object->subObjects.empty() ? AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, *m_dialect}(*m_object->code) : m_object->toString(*m_dialect)); + auto optimizedObject = tester.optimizedObject(); + std::string printedOptimizedObject; + if (optimizedObject->subObjects.empty()) + printedOptimizedObject = AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, *m_dialect}(optimizedObject->code->root()); + else + printedOptimizedObject = optimizedObject->toString(*m_dialect); // Re-parse new code for compilability - if (!std::get<0>(parse(_stream, _linePrefix, _formatted, printed))) + if (!std::get<0>(parse(_stream, _linePrefix, _formatted, printedOptimizedObject))) { util::AnsiColorized(_stream, _formatted, {util::formatting::BOLD, util::formatting::CYAN}) << _linePrefix << "Result after the optimiser:" << std::endl; - printPrefixed(_stream, printed, _linePrefix + " "); + printPrefixed(_stream, printedOptimizedObject, _linePrefix + " "); return TestResult::FatalError; } - m_obtainedResult = "step: " + m_optimizerStep + "\n\n" + printed + "\n"; + m_obtainedResult = "step: " + m_optimizerStep + "\n\n" + printedOptimizedObject + "\n"; return checkResult(_stream, _linePrefix, _formatted); } diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 80746c93b..357e5b657 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -76,275 +76,361 @@ using namespace solidity::frontend; YulOptimizerTestCommon::YulOptimizerTestCommon( std::shared_ptr _obj, Dialect const& _dialect -) +): m_dialect(&_dialect), m_object(_obj), m_optimizedObject(std::make_shared()), m_analysisInfo(m_object->analysisInfo) { - m_object = _obj; - m_ast = m_object->code; - m_analysisInfo = m_object->analysisInfo; - m_dialect = &_dialect; - + *m_optimizedObject = *m_object; m_namedSteps = { - {"disambiguator", [&]() { disambiguate(); }}, + {"disambiguator", [&]() { return disambiguate(); }}, {"nameDisplacer", [&]() { - disambiguate(); + auto block = disambiguate(); + updateContext(block); NameDisplacer{ *m_nameDispenser, {"illegal1"_yulname, "illegal2"_yulname, "illegal3"_yulname, "illegal4"_yulname, "illegal5"_yulname} - }(*m_ast); + }(block); + return block; }}, {"blockFlattener", [&]() { - disambiguate(); - FunctionGrouper::run(*m_context, *m_ast); - BlockFlattener::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + FunctionGrouper::run(*m_context, block); + BlockFlattener::run(*m_context, block); + return block; }}, {"constantOptimiser", [&]() { + auto block = std::get(ASTCopier{}(m_object->code->root())); + updateContext(block); GasMeter meter(dynamic_cast(*m_dialect), false, 200); - ConstantOptimiser{dynamic_cast(*m_dialect), meter}(*m_ast); + ConstantOptimiser{dynamic_cast(*m_dialect), meter}(block); + return block; + }}, + {"varDeclInitializer", [&]() { + auto block = std::get(ASTCopier{}(m_object->code->root())); + updateContext(block); + VarDeclInitializer::run(*m_context, block); + return block; }}, - {"varDeclInitializer", [&]() { VarDeclInitializer::run(*m_context, *m_ast); }}, {"varNameCleaner", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, *m_ast); - FunctionGrouper::run(*m_context, *m_ast); - VarNameCleaner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + FunctionHoister::run(*m_context, block); + FunctionGrouper::run(*m_context, block); + VarNameCleaner::run(*m_context, block); + return block; }}, {"forLoopConditionIntoBody", [&]() { - disambiguate(); - ForLoopConditionIntoBody::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopConditionIntoBody::run(*m_context, block); + return block; }}, {"forLoopInitRewriter", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + return block; }}, {"commonSubexpressionEliminator", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - CommonSubexpressionEliminator::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + CommonSubexpressionEliminator::run(*m_context, block); + return block; }}, {"conditionalUnsimplifier", [&]() { - disambiguate(); - ConditionalUnsimplifier::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ConditionalUnsimplifier::run(*m_context, block); + return block; }}, {"conditionalSimplifier", [&]() { - disambiguate(); - ConditionalSimplifier::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ConditionalSimplifier::run(*m_context, block); + return block; + }}, + {"expressionSplitter", [&]() { + auto block = std::get(ASTCopier{}(m_object->code->root())); + updateContext(block); + ExpressionSplitter::run(*m_context, block); + return block; }}, - {"expressionSplitter", [&]() { ExpressionSplitter::run(*m_context, *m_ast); }}, {"expressionJoiner", [&]() { - disambiguate(); - ExpressionJoiner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ExpressionJoiner::run(*m_context, block); + return block; }}, {"splitJoin", [&]() { - disambiguate(); - ExpressionSplitter::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ExpressionSplitter::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; }}, {"functionGrouper", [&]() { - disambiguate(); - FunctionGrouper::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + FunctionGrouper::run(*m_context, block); + return block; }}, {"functionHoister", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + FunctionHoister::run(*m_context, block); + return block; }}, {"functionSpecializer", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, *m_object->code); - FunctionSpecializer::run(*m_context, *m_object->code); + auto block = disambiguate(); + updateContext(block); + FunctionHoister::run(*m_context, block); + FunctionSpecializer::run(*m_context, block); + return block; }}, {"expressionInliner", [&]() { - disambiguate(); - ExpressionInliner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ExpressionInliner::run(*m_context, block); + return block; }}, {"fullInliner", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, *m_ast); - FunctionGrouper::run(*m_context, *m_ast); - ExpressionSplitter::run(*m_context, *m_ast); - FullInliner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + FunctionHoister::run(*m_context, block); + FunctionGrouper::run(*m_context, block); + ExpressionSplitter::run(*m_context, block); + FullInliner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; }}, {"fullInlinerWithoutSplitter", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, *m_ast); - FunctionGrouper::run(*m_context, *m_ast); - FullInliner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + FunctionHoister::run(*m_context, block); + FunctionGrouper::run(*m_context, block); + FullInliner::run(*m_context, block); + return block; }}, {"rematerialiser", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - Rematerialiser::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + Rematerialiser::run(*m_context, block); + return block; }}, {"expressionSimplifier", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - ExpressionSplitter::run(*m_context, *m_ast); - CommonSubexpressionEliminator::run(*m_context, *m_ast); - ExpressionSimplifier::run(*m_context, *m_ast); - ExpressionSimplifier::run(*m_context, *m_ast); - ExpressionSimplifier::run(*m_context, *m_ast); - UnusedPruner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + ExpressionSplitter::run(*m_context, block); + CommonSubexpressionEliminator::run(*m_context, block); + ExpressionSimplifier::run(*m_context, block); + ExpressionSimplifier::run(*m_context, block); + ExpressionSimplifier::run(*m_context, block); + UnusedPruner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; }}, {"fullSimplify", [&]() { - disambiguate(); - FunctionGrouper::run(*m_context, *m_ast); - BlockFlattener::run(*m_context, *m_ast); - ExpressionSplitter::run(*m_context, *m_ast); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - CommonSubexpressionEliminator::run(*m_context, *m_ast); - ExpressionSimplifier::run(*m_context, *m_ast); - UnusedPruner::run(*m_context, *m_ast); - CircularReferencesPruner::run(*m_context, *m_ast); - DeadCodeEliminator::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + FunctionGrouper::run(*m_context, block); + BlockFlattener::run(*m_context, block); + ExpressionSplitter::run(*m_context, block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + CommonSubexpressionEliminator::run(*m_context, block); + ExpressionSimplifier::run(*m_context, block); + UnusedPruner::run(*m_context, block); + CircularReferencesPruner::run(*m_context, block); + DeadCodeEliminator::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; }}, {"unusedFunctionParameterPruner", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_object->code); - LiteralRematerialiser::run(*m_context, *m_object->code); - UnusedFunctionParameterPruner::run(*m_context, *m_object->code); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + LiteralRematerialiser::run(*m_context, block); + UnusedFunctionParameterPruner::run(*m_context, block); + return block; }}, {"unusedPruner", [&]() { - disambiguate(); - UnusedPruner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + UnusedPruner::run(*m_context, block); + return block; }}, {"circularReferencesPruner", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, *m_ast); - CircularReferencesPruner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + FunctionHoister::run(*m_context, block); + CircularReferencesPruner::run(*m_context, block); + return block; }}, {"deadCodeEliminator", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - DeadCodeEliminator::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + DeadCodeEliminator::run(*m_context, block); + return block; }}, {"ssaTransform", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - SSATransform::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + SSATransform::run(*m_context, block); + return block; }}, {"unusedAssignEliminator", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - UnusedAssignEliminator::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + UnusedAssignEliminator::run(*m_context, block); + return block; }}, {"unusedStoreEliminator", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - ExpressionSplitter::run(*m_context, *m_ast); - SSATransform::run(*m_context, *m_ast); - UnusedStoreEliminator::run(*m_context, *m_ast); - SSAReverser::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + ExpressionSplitter::run(*m_context, block); + SSATransform::run(*m_context, block); + UnusedStoreEliminator::run(*m_context, block); + SSAReverser::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; }}, {"equalStoreEliminator", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, *m_ast); - ForLoopInitRewriter::run(*m_context, *m_ast); - EqualStoreEliminator::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + FunctionHoister::run(*m_context, block); + ForLoopInitRewriter::run(*m_context, block); + EqualStoreEliminator::run(*m_context, block); + return block; }}, {"ssaPlusCleanup", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - SSATransform::run(*m_context, *m_ast); - UnusedAssignEliminator::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + SSATransform::run(*m_context, block); + UnusedAssignEliminator::run(*m_context, block); + return block; }}, {"loadResolver", [&]() { - disambiguate(); - FunctionGrouper::run(*m_context, *m_ast); - BlockFlattener::run(*m_context, *m_ast); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - ExpressionSplitter::run(*m_context, *m_ast); - CommonSubexpressionEliminator::run(*m_context, *m_ast); - ExpressionSimplifier::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + FunctionGrouper::run(*m_context, block); + BlockFlattener::run(*m_context, block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + ExpressionSplitter::run(*m_context, block); + CommonSubexpressionEliminator::run(*m_context, block); + ExpressionSimplifier::run(*m_context, block); - LoadResolver::run(*m_context, *m_ast); + LoadResolver::run(*m_context, block); - UnusedPruner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); + UnusedPruner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; }}, {"loopInvariantCodeMotion", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - LoopInvariantCodeMotion::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + LoopInvariantCodeMotion::run(*m_context, block); + return block; }}, {"controlFlowSimplifier", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - ControlFlowSimplifier::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + ControlFlowSimplifier::run(*m_context, block); + return block; }}, {"structuralSimplifier", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - LiteralRematerialiser::run(*m_context, *m_ast); - StructuralSimplifier::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + LiteralRematerialiser::run(*m_context, block); + StructuralSimplifier::run(*m_context, block); + return block; }}, {"equivalentFunctionCombiner", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - EquivalentFunctionCombiner::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + EquivalentFunctionCombiner::run(*m_context, block); + return block; }}, {"ssaReverser", [&]() { - disambiguate(); - SSAReverser::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + SSAReverser::run(*m_context, block); + return block; }}, {"ssaAndBack", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); // apply SSA - SSATransform::run(*m_context, *m_ast); - UnusedAssignEliminator::run(*m_context, *m_ast); + SSATransform::run(*m_context, block); + UnusedAssignEliminator::run(*m_context, block); // reverse SSA - SSAReverser::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - CommonSubexpressionEliminator::run(*m_context, *m_ast); - UnusedPruner::run(*m_context, *m_ast); + SSAReverser::run(*m_context, block); + FunctionHoister::run(*m_context, block); + CommonSubexpressionEliminator::run(*m_context, block); + UnusedPruner::run(*m_context, block); + return block; }}, {"stackCompressor", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - FunctionGrouper::run(*m_context, *m_ast); + auto block = disambiguate(); + updateContext(block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + FunctionGrouper::run(*m_context, block); size_t maxIterations = 16; - StackCompressor::run(*m_dialect, *m_object, true, maxIterations); - BlockFlattener::run(*m_context, *m_ast); + StackCompressor::run(*m_dialect, block, *m_object, true, maxIterations); + BlockFlattener::run(*m_context, block); + return block; }}, {"fullSuite", [&]() { GasMeter meter(dynamic_cast(*m_dialect), false, 200); OptimiserSuite::run( *m_dialect, &meter, - *m_object, + *m_optimizedObject, true, frontend::OptimiserSettings::DefaultYulOptimiserSteps, frontend::OptimiserSettings::DefaultYulOptimiserCleanupSteps, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment ); + return std::get(ASTCopier{}(m_optimizedObject->code->root())); }}, {"stackLimitEvader", [&]() { - disambiguate(); - StackLimitEvader::run(*m_context, *m_object, CompilabilityChecker{ + auto block = disambiguate(); + updateContext(block); + StackLimitEvader::run(*m_context, block, CompilabilityChecker{ *m_dialect, *m_object, - true + true, + &block }.unreachableVariables); + return block; }}, {"fakeStackLimitEvader", [&]() { - disambiguate(); + auto block = disambiguate(); + updateContext(block); // Mark all variables with a name starting with "$" for escalation to memory. struct FakeUnreachableGenerator: ASTWalker { @@ -381,8 +467,9 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( YulName m_currentFunction = YulName{}; }; FakeUnreachableGenerator fakeUnreachableGenerator; - fakeUnreachableGenerator(*m_ast); - StackLimitEvader::run(*m_context, *m_object, fakeUnreachableGenerator.fakeUnreachables); + fakeUnreachableGenerator(block); + StackLimitEvader::run(*m_context, block, fakeUnreachableGenerator.fakeUnreachables); + return block; }} }; } @@ -396,10 +483,11 @@ bool YulOptimizerTestCommon::runStep() { yulAssert(m_dialect, "Dialect not set."); - updateContext(); - if (m_namedSteps.count(m_optimizerStep)) - m_namedSteps[m_optimizerStep](); + { + auto block = m_namedSteps[m_optimizerStep](); + m_optimizedObject->code = std::make_shared(std::move(block)); + } else return false; @@ -435,21 +523,21 @@ std::string YulOptimizerTestCommon::randomOptimiserStep(unsigned _seed) yulAssert(false, "Optimiser step selection failed."); } -std::shared_ptr YulOptimizerTestCommon::run() +Block const* YulOptimizerTestCommon::run() { - return runStep() ? m_ast : nullptr; + return runStep() ? &m_optimizedObject->code->root() : nullptr; } -void YulOptimizerTestCommon::disambiguate() +Block YulOptimizerTestCommon::disambiguate() { - *m_object->code = std::get(Disambiguator(*m_dialect, *m_analysisInfo)(*m_object->code)); + auto block = std::get(Disambiguator(*m_dialect, *m_analysisInfo)(m_object->code->root())); m_analysisInfo.reset(); - updateContext(); + return block; } -void YulOptimizerTestCommon::updateContext() +void YulOptimizerTestCommon::updateContext(Block const& _block) { - m_nameDispenser = std::make_unique(*m_dialect, *m_object->code, m_reservedIdentifiers); + m_nameDispenser = std::make_unique(*m_dialect, _block, m_reservedIdentifiers); m_context = std::make_unique(OptimiserStepContext{ *m_dialect, *m_nameDispenser, @@ -457,3 +545,8 @@ void YulOptimizerTestCommon::updateContext() frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment }); } + +std::shared_ptr YulOptimizerTestCommon::optimizedObject() const +{ + return m_optimizedObject; +} diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h index 0a5d63320..8a706c328 100644 --- a/test/libyul/YulOptimizerTestCommon.h +++ b/test/libyul/YulOptimizerTestCommon.h @@ -28,9 +28,10 @@ namespace solidity::yul { - struct AsmAnalysisInfo; - struct Object; - struct Dialect; +struct AsmAnalysisInfo; +struct Object; +struct Dialect; +class AST; } namespace solidity::yul::test @@ -47,7 +48,7 @@ class YulOptimizerTestCommon void setStep(std::string const& _optimizerStep); /// Runs chosen optimiser step returning pointer /// to yul AST Block post optimisation. - std::shared_ptr run(); + Block const* run(); /// Runs chosen optimiser step returning true if /// successful, false otherwise. bool runStep(); @@ -56,9 +57,11 @@ class YulOptimizerTestCommon /// @param _seed is an unsigned integer that /// seeds the random selection. std::string randomOptimiserStep(unsigned _seed); + /// the resulting object after performing optimization steps + std::shared_ptr optimizedObject() const; private: - void disambiguate(); - void updateContext(); + Block disambiguate(); + void updateContext(Block const& _block); std::string m_optimizerStep; @@ -68,9 +71,9 @@ class YulOptimizerTestCommon std::unique_ptr m_context; std::shared_ptr m_object; - std::shared_ptr m_ast; + std::shared_ptr m_optimizedObject; std::shared_ptr m_analysisInfo; - std::map> m_namedSteps; + std::map> m_namedSteps; }; } diff --git a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp index 25559bc66..940fc7374 100644 --- a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp +++ b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp @@ -54,7 +54,7 @@ namespace /// @returns true if there are recursive functions, false otherwise. bool recursiveFunctionExists(Dialect const& _dialect, yul::Object& _object) { - auto recursiveFunctions = CallGraphGenerator::callGraph(*_object.code).recursiveFunctions(); + auto recursiveFunctions = CallGraphGenerator::callGraph(_object.code->root()).recursiveFunctions(); for(auto&& [function, variables]: CompilabilityChecker{ _dialect, _object, diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index e31391b0e..40201bd15 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -88,7 +89,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) // that would be removed by the redundant store eliminator. yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( os1, - stack.parserResult()->code, + stack.parserResult()->code->root(), EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), /*disableMemoryTracing=*/true ); @@ -98,7 +99,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) stack.optimize(); termReason = yulFuzzerUtil::interpret( os2, - stack.parserResult()->code, + stack.parserResult()->code->root(), EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), /*disableMemoryTracing=*/true ); diff --git a/test/tools/ossfuzz/yulFuzzerCommon.cpp b/test/tools/ossfuzz/yulFuzzerCommon.cpp index 4f7a871ac..033dfc044 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.cpp +++ b/test/tools/ossfuzz/yulFuzzerCommon.cpp @@ -23,7 +23,7 @@ using namespace solidity::yul::test::yul_fuzzer; yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( std::ostream& _os, - std::shared_ptr _ast, + yul::Block const& _astRoot, Dialect const& _dialect, bool _disableMemoryTracing, bool _outputStorageOnly, @@ -52,7 +52,7 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( TerminationReason reason = TerminationReason::None; try { - Interpreter::run(state, _dialect, *_ast, true, _disableMemoryTracing); + Interpreter::run(state, _dialect, _astRoot, true, _disableMemoryTracing); } catch (StepLimitReached const&) { diff --git a/test/tools/ossfuzz/yulFuzzerCommon.h b/test/tools/ossfuzz/yulFuzzerCommon.h index 4c8f665f6..6575db11f 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.h +++ b/test/tools/ossfuzz/yulFuzzerCommon.h @@ -40,7 +40,7 @@ struct yulFuzzerUtil /// eliminator. static TerminationReason interpret( std::ostream& _os, - std::shared_ptr _ast, + yul::Block const& _astRoot, Dialect const& _dialect, bool _disableMemoryTracing = false, bool _outputStorageOnly = false, diff --git a/test/tools/ossfuzz/yulProtoFuzzer.cpp b/test/tools/ossfuzz/yulProtoFuzzer.cpp index b27d879d5..092f2dacb 100644 --- a/test/tools/ossfuzz/yulProtoFuzzer.cpp +++ b/test/tools/ossfuzz/yulProtoFuzzer.cpp @@ -84,6 +84,6 @@ DEFINE_PROTO_FUZZER(Program const& _input) EVMDialect::strictAssemblyForEVMObjects(version) ); optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); - std::shared_ptr astBlock = optimizerTest.run(); - yulAssert(astBlock != nullptr, "Optimiser error."); + auto const* astRoot = optimizerTest.run(); + yulAssert(astRoot != nullptr, "Optimiser error."); } diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index 49470f719..4e07eaf64 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -26,6 +26,7 @@ #include +#include #include #include #include @@ -88,7 +89,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // that would be removed by the redundant store eliminator. yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( os1, - stack.parserResult()->code, + stack.parserResult()->code->root(), EVMDialect::strictAssemblyForEVMObjects(version), /*disableMemoryTracing=*/true ); @@ -101,11 +102,11 @@ DEFINE_PROTO_FUZZER(Program const& _input) EVMDialect::strictAssemblyForEVMObjects(version) ); optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); - std::shared_ptr astBlock = optimizerTest.run(); - yulAssert(astBlock != nullptr, "Optimiser error."); + auto const* astRoot = optimizerTest.run(); + yulAssert(astRoot != nullptr, "Optimiser error."); termReason = yulFuzzerUtil::interpret( os2, - astBlock, + *astRoot, EVMDialect::strictAssemblyForEVMObjects(version), true ); diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 2b9e530e0..1655b13d3 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -58,9 +58,7 @@ #include #include -#include #include -#include #include #include @@ -92,20 +90,21 @@ class YulOpti CharStream _charStream(_input, ""); try { - m_ast = yul::Parser(errorReporter, m_dialect).parse(_charStream); - if (!m_ast || !errorReporter.errors().empty()) + auto ast = yul::Parser(errorReporter, m_dialect).parse(_charStream); + if (!m_astRoot || !errorReporter.errors().empty()) { std::cerr << "Error parsing source." << std::endl; printErrors(_charStream, errors); throw std::runtime_error("Could not parse source."); } + m_astRoot = std::make_shared(std::get(ASTCopier{}(ast->root()))); m_analysisInfo = std::make_unique(); AsmAnalyzer analyzer( *m_analysisInfo, errorReporter, m_dialect ); - if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty()) + if (!analyzer.analyze(*m_astRoot) || !errorReporter.errors().empty()) { std::cerr << "Error analyzing source." << std::endl; printErrors(_charStream, errors); @@ -171,17 +170,17 @@ class YulOpti void disambiguate() { - *m_ast = std::get(Disambiguator(m_dialect, *m_analysisInfo)(*m_ast)); + *m_astRoot = std::get(Disambiguator(m_dialect, *m_analysisInfo)(*m_astRoot)); m_analysisInfo.reset(); - m_nameDispenser.reset(*m_ast); + m_nameDispenser.reset(*m_astRoot); } void runSteps(std::string _source, std::string _steps) { parse(_source); disambiguate(); - OptimiserSuite{m_context}.runSequence(_steps, *m_ast); - std::cout << AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, m_dialect}(*m_ast) << std::endl; + OptimiserSuite{m_context}.runSequence(_steps, *m_astRoot); + std::cout << AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, m_dialect}(*m_astRoot) << std::endl; } void runInteractive(std::string _source, bool _disambiguated = false) @@ -212,24 +211,23 @@ class YulOpti case '#': return; case ',': - VarNameCleaner::run(m_context, *m_ast); + VarNameCleaner::run(m_context, *m_astRoot); // VarNameCleaner destroys the unique names guarantee of the disambiguator. disambiguated = false; break; case ';': { Object obj; - obj.code = m_ast; - StackCompressor::run(m_dialect, obj, true, 16); + StackCompressor::run(m_dialect, *m_astRoot, obj, true, 16); break; } default: OptimiserSuite{m_context}.runSequence( std::string_view(&option, 1), - *m_ast + *m_astRoot ); } - _source = AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, m_dialect}(*m_ast); + _source = AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, m_dialect}(*m_astRoot); } catch (...) { @@ -242,7 +240,7 @@ class YulOpti } private: - std::shared_ptr m_ast; + std::shared_ptr m_astRoot; Dialect const& m_dialect{EVMDialect::strictAssemblyForEVMObjects(EVMVersion{})}; std::unique_ptr m_analysisInfo; std::set const m_reservedIdentifiers = {}; diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index fb18b4e59..9aee616e0 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -54,7 +54,7 @@ namespace po = boost::program_options; namespace { -std::pair, std::shared_ptr> parse(std::string const& _source) +std::pair, std::shared_ptr> parse(std::string const& _source) { YulStack stack( langutil::EVMVersion(), @@ -77,7 +77,7 @@ std::pair, std::shared_ptr> parse(std::s void interpret(std::string const& _source, bool _inspect, bool _disableExternalCalls) { - std::shared_ptr ast; + std::shared_ptr ast; std::shared_ptr analysisInfo; tie(ast, analysisInfo) = parse(_source); if (!ast || !analysisInfo) @@ -90,10 +90,10 @@ void interpret(std::string const& _source, bool _inspect, bool _disableExternalC Dialect const& dialect(EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{})); if (_inspect) - InspectedInterpreter::run(std::make_shared(_source, state), state, dialect, *ast, _disableExternalCalls, /*disableMemoryTracing=*/false); + InspectedInterpreter::run(std::make_shared(_source, state), state, dialect, ast->root(), _disableExternalCalls, /*disableMemoryTracing=*/false); else - Interpreter::run(state, dialect, *ast, _disableExternalCalls, /*disableMemoryTracing=*/false); + Interpreter::run(state, dialect, ast->root(), _disableExternalCalls, /*disableMemoryTracing=*/false); } catch (InterpreterTerminatedGeneric const&) { diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index e0c8ec4fb..2d5c31cf1 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -59,7 +59,7 @@ std::ostream& operator<<(std::ostream& _stream, Program const& _program); } Program::Program(Program const& program): - m_ast(std::make_unique(std::get(ASTCopier{}(*program.m_ast)))), + m_ast(std::make_unique(std::get(ASTCopier{}(program.m_ast->root())))), m_dialect{program.m_dialect}, m_nameDispenser(program.m_nameDispenser) { @@ -70,13 +70,13 @@ std::variant Program::load(CharStream& _sourceCode) // ASSUMPTION: parseSource() rewinds the stream on its own Dialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}); - std::variant, ErrorList> astOrErrors = parseObject(dialect, _sourceCode); + std::variant, ErrorList> astOrErrors = parseObject(dialect, _sourceCode); if (std::holds_alternative(astOrErrors)) return std::get(astOrErrors); std::variant, ErrorList> analysisInfoOrErrors = analyzeAST( dialect, - *std::get>(astOrErrors) + *std::get>(astOrErrors) ); if (std::holds_alternative(analysisInfoOrErrors)) return std::get(analysisInfoOrErrors); @@ -85,7 +85,7 @@ std::variant Program::load(CharStream& _sourceCode) dialect, disambiguateAST( dialect, - *std::get>(astOrErrors), + *std::get>(astOrErrors), *std::get>(analysisInfoOrErrors) ) ); @@ -105,16 +105,16 @@ void Program::optimise(std::vector const& _optimisationSteps) std::ostream& phaser::operator<<(std::ostream& _stream, Program const& _program) { - return _stream << AsmPrinter(AsmPrinter::TypePrinting::Full, _program.m_dialect)(*_program.m_ast); + return _stream << AsmPrinter(AsmPrinter::TypePrinting::Full, _program.m_dialect)(_program.m_ast->root()); } std::string Program::toJson() const { - Json serializedAst = AsmJsonConverter(0)(*m_ast); + Json serializedAst = AsmJsonConverter(0)(m_ast->root()); return jsonPrettyPrint(removeNullMembers(std::move(serializedAst))); } -std::variant, ErrorList> Program::parseObject(Dialect const& _dialect, CharStream _source) +std::variant, ErrorList> Program::parseObject(Dialect const& _dialect, CharStream _source) { ErrorList errors; ErrorReporter errorReporter(errors); @@ -149,19 +149,19 @@ std::variant, ErrorList> Program::parseObject(Dialect con // The public API of the class does not provide access to the smart pointer so it won't be hard // to switch to shared_ptr if the copying turns out to be an issue (though it would be better // to refactor ObjectParser and Object to use unique_ptr instead). - auto astCopy = std::make_unique(std::get(ASTCopier{}(*selectedObject->code))); + auto astCopy = std::make_unique(std::get(ASTCopier{}(selectedObject->code->root()))); - return std::variant, ErrorList>(std::move(astCopy)); + return std::variant, ErrorList>(std::move(astCopy)); } -std::variant, ErrorList> Program::analyzeAST(Dialect const& _dialect, Block const& _ast) +std::variant, ErrorList> Program::analyzeAST(Dialect const& _dialect, AST const& _ast) { ErrorList errors; ErrorReporter errorReporter(errors); auto analysisInfo = std::make_unique(); AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect); - bool analysisSuccessful = analyzer.analyze(_ast); + bool analysisSuccessful = analyzer.analyze(_ast.root()); if (!analysisSuccessful) return errors; @@ -169,22 +169,22 @@ std::variant, ErrorList> Program::analyzeAST(Di return std::variant, ErrorList>(std::move(analysisInfo)); } -std::unique_ptr Program::disambiguateAST( +std::unique_ptr Program::disambiguateAST( Dialect const& _dialect, - Block const& _ast, + AST const& _ast, AsmAnalysisInfo const& _analysisInfo ) { std::set const externallyUsedIdentifiers = {}; Disambiguator disambiguator(_dialect, _analysisInfo, externallyUsedIdentifiers); - return std::make_unique(std::get(disambiguator(_ast))); + return std::make_unique(std::get(disambiguator(_ast.root()))); } -std::unique_ptr Program::applyOptimisationSteps( +std::unique_ptr Program::applyOptimisationSteps( Dialect const& _dialect, NameDispenser& _nameDispenser, - std::unique_ptr _ast, + std::unique_ptr _ast, std::vector const& _optimisationSteps ) { @@ -198,10 +198,11 @@ std::unique_ptr Program::applyOptimisationSteps( frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment }; + auto astRoot = std::get(ASTCopier{}(_ast->root())); for (std::string const& step: _optimisationSteps) - OptimiserSuite::allSteps().at(step)->run(context, *_ast); + OptimiserSuite::allSteps().at(step)->run(context, astRoot); - return _ast; + return std::make_unique(std::move(astRoot)); } size_t Program::computeCodeSize(Block const& _ast, CodeWeights const& _weights) diff --git a/tools/yulPhaser/Program.h b/tools/yulPhaser/Program.h index e42471d77..be4bf582d 100644 --- a/tools/yulPhaser/Program.h +++ b/tools/yulPhaser/Program.h @@ -75,8 +75,8 @@ class Program static std::variant load(langutil::CharStream& _sourceCode); void optimise(std::vector const& _optimisationSteps); - size_t codeSize(yul::CodeWeights const& _weights) const { return computeCodeSize(*m_ast, _weights); } - yul::Block const& ast() const { return *m_ast; } + size_t codeSize(yul::CodeWeights const& _weights) const { return computeCodeSize(m_ast->root(), _weights); } + yul::Block const& ast() const { return m_ast->root(); } friend std::ostream& operator<<(std::ostream& _stream, Program const& _program); std::string toJson() const; @@ -84,35 +84,35 @@ class Program private: Program( yul::Dialect const& _dialect, - std::unique_ptr _ast + std::unique_ptr _ast ): m_ast(std::move(_ast)), m_dialect{_dialect}, - m_nameDispenser(_dialect, *m_ast, {}) + m_nameDispenser(_dialect, m_ast->root(), {}) {} - static std::variant, langutil::ErrorList> parseObject( + static std::variant, langutil::ErrorList> parseObject( yul::Dialect const& _dialect, langutil::CharStream _source ); static std::variant, langutil::ErrorList> analyzeAST( yul::Dialect const& _dialect, - yul::Block const& _ast + yul::AST const& _ast ); - static std::unique_ptr disambiguateAST( + static std::unique_ptr disambiguateAST( yul::Dialect const& _dialect, - yul::Block const& _ast, + yul::AST const& _ast, yul::AsmAnalysisInfo const& _analysisInfo ); - static std::unique_ptr applyOptimisationSteps( + static std::unique_ptr applyOptimisationSteps( yul::Dialect const& _dialect, yul::NameDispenser& _nameDispenser, - std::unique_ptr _ast, + std::unique_ptr _ast, std::vector const& _optimisationSteps ); static size_t computeCodeSize(yul::Block const& _ast, yul::CodeWeights const& _weights); - std::unique_ptr m_ast; + std::unique_ptr m_ast; yul::Dialect const& m_dialect; yul::NameDispenser m_nameDispenser; }; From d109d6bf76335f3db6eb8d570e02ecd0f481f180 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 29 Jul 2024 17:43:00 +0200 Subject: [PATCH 0232/1340] Yul: StackCompressor/StackLimitEvader return modified ast and operate on const object input --- libyul/CompilabilityChecker.cpp | 13 ++++---- libyul/CompilabilityChecker.h | 3 +- libyul/optimiser/StackCompressor.cpp | 41 ++++++++++---------------- libyul/optimiser/StackCompressor.h | 17 ++--------- libyul/optimiser/StackLimitEvader.cpp | 19 +++++++----- libyul/optimiser/StackLimitEvader.h | 3 +- libyul/optimiser/Suite.cpp | 24 ++++++++++----- test/libyul/YulOptimizerTestCommon.cpp | 18 +++++++---- test/tools/yulopti.cpp | 3 +- 9 files changed, 67 insertions(+), 74 deletions(-) diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index 76affbd64..af7532c75 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -33,20 +33,17 @@ using namespace solidity::util; CompilabilityChecker::CompilabilityChecker( Dialect const& _dialect, Object const& _object, - bool _optimizeStackAllocation, - Block const* _block + bool _optimizeStackAllocation ) { - yulAssert(_object.code || _block); + yulAssert(_object.code); if (auto const* evmDialect = dynamic_cast(&_dialect)) { - if (!_block) - _block = &_object.code->root(); NoOutputEVMDialect noOutputDialect(*evmDialect); yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( noOutputDialect, - *_block, + _object.code->root(), _object.qualifiedDataNames() ); @@ -60,12 +57,12 @@ CompilabilityChecker::CompilabilityChecker( CodeTransform transform( assembly, analysisInfo, - *_block, + _object.code->root(), noOutputDialect, builtinContext, _optimizeStackAllocation ); - transform(*_block); + transform(_object.code->root()); for (StackTooDeepError const& error: transform.stackErrors()) { diff --git a/libyul/CompilabilityChecker.h b/libyul/CompilabilityChecker.h index 1dd669990..160aeca8c 100644 --- a/libyul/CompilabilityChecker.h +++ b/libyul/CompilabilityChecker.h @@ -47,8 +47,7 @@ struct CompilabilityChecker CompilabilityChecker( Dialect const& _dialect, Object const& _object, - bool _optimizeStackAllocation, - Block const* _blockOverride = nullptr + bool _optimizeStackAllocation ); std::map> unreachableVariables; std::map stackDeficit; diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 10360756d..bdc20a5a8 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -236,29 +236,15 @@ void eliminateVariablesOptimizedCodegen( } -bool StackCompressor::run( +std::tuple StackCompressor::run( Dialect const& _dialect, - Object& _object, - bool _optimizeStackAllocation, - size_t _maxIterations -) -{ - yulAssert(_object.code); - auto block = std::get(ASTCopier{}(_object.code->root())); - auto result = run(_dialect, block, _object, _optimizeStackAllocation, _maxIterations); - _object.code = std::make_shared(std::move(block)); - return result; -} - -bool StackCompressor::run( - Dialect const& _dialect, - Block& _astRoot, Object const& _object, bool _optimizeStackAllocation, size_t _maxIterations) { + yulAssert(_object.code); yulAssert( - !_astRoot.statements.empty() && std::holds_alternative(_astRoot.statements.at(0)), + !_object.code->root().statements.empty() && std::holds_alternative(_object.code->root().statements.at(0)), "Need to run the function grouper before the stack compressor." ); bool usesOptimizedCodeGenerator = false; @@ -267,31 +253,36 @@ bool StackCompressor::run( _optimizeStackAllocation && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); - bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _astRoot); + bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _object.code->root()); + Block astRoot = std::get(ASTCopier{}(_object.code->root())); if (usesOptimizedCodeGenerator) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _astRoot, _object.qualifiedDataNames()); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, _astRoot); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, astRoot, _object.qualifiedDataNames()); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, astRoot); eliminateVariablesOptimizedCodegen( _dialect, - _astRoot, + astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg), allowMSizeOptimization ); } else + { for (size_t iterations = 0; iterations < _maxIterations; iterations++) { - std::map stackSurplus = CompilabilityChecker(_dialect, _object, _optimizeStackAllocation, &_astRoot).stackDeficit; + Object object(_object); + object.code = std::make_shared(std::get(ASTCopier{}(astRoot))); + std::map stackSurplus = CompilabilityChecker(_dialect, object, _optimizeStackAllocation).stackDeficit; if (stackSurplus.empty()) - return true; + return std::make_tuple(true, std::move(astRoot)); eliminateVariables( _dialect, - _astRoot, + astRoot, stackSurplus, allowMSizeOptimization ); } - return false; + } + return std::make_tuple(false, std::move(astRoot)); } diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index 13b9459a2..15d057455 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -44,21 +44,10 @@ struct FunctionDefinition; class StackCompressor { public: - /// Try to remove local variables until the AST is compilable. Modifies the object's AST. - /// @returns true if it was successful. - static bool run( + /// Try to remove local variables until the AST is compilable. + /// @returns tuple with true if it was successful as first element, second element is the modified AST. + static std::tuple run( Dialect const& _dialect, - Object& _object, - bool _optimizeStackAllocation, - size_t _maxIterations - ); - - /// Try to remove local variables until the AST is compilable. Operates on provided block, - /// disregards the AST contained in object. - /// @returns true if it was successful. - static bool run( - Dialect const& _dialect, - Block& _astRoot, Object const& _object, bool _optimizeStackAllocation, size_t _maxIterations diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 210be1cf3..d613ae993 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -15,6 +15,7 @@ along with solidity. If not, see . */ +#include #include #include #include @@ -117,31 +118,33 @@ u256 literalArgumentValue(FunctionCall const& _call) } } -void StackLimitEvader::run( +Block StackLimitEvader::run( OptimiserStepContext& _context, - Block& _astRoot, Object const& _object ) { + yulAssert(_object.code); auto const* evmDialect = dynamic_cast(&_context.dialect); yulAssert( evmDialect && evmDialect->providesObjectAccess(), "StackLimitEvader can only be run on objects using the EVMDialect with object access." ); + auto astRoot = std::get(ASTCopier{}(_object.code->root())); if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall()) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, _astRoot, _object.qualifiedDataNames()); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, _astRoot); - run(_context, _astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg)); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, astRoot, _object.qualifiedDataNames()); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, astRoot); + run(_context, astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg)); } else - run(_context, _astRoot, CompilabilityChecker{ + { + run(_context, astRoot, CompilabilityChecker{ _context.dialect, _object, true, - &_astRoot }.unreachableVariables); - + } + return astRoot; } void StackLimitEvader::run( diff --git a/libyul/optimiser/StackLimitEvader.h b/libyul/optimiser/StackLimitEvader.h index 5029f7825..a5871f7f1 100644 --- a/libyul/optimiser/StackLimitEvader.h +++ b/libyul/optimiser/StackLimitEvader.h @@ -77,9 +77,8 @@ class StackLimitEvader /// Abort and do nothing, if no ``memoryguard`` call or several ``memoryguard`` calls /// with non-matching arguments are found, or if any of the unreachable variables /// are contained in a recursive function. - static void run( + static Block run( OptimiserStepContext& _context, - Block& _astRoot, Object const& _object ); }; diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index b8826bb8a..cc0c1a7f3 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -179,13 +179,15 @@ void OptimiserSuite::run( // We ignore the return value because we will get a much better error // message once we perform code generation. if (!usesOptimizedCodeGenerator) - StackCompressor::run( + { + _object.code = std::make_shared(std::move(astRoot)); + astRoot = std::get<1>(StackCompressor::run( _dialect, - astRoot, _object, _optimizeStackAllocation, stackCompressorMaxIterations - ); + )); + } // Run the user-supplied clean up sequence suite.runSequence(_optimisationCleanupSequence, astRoot); @@ -200,18 +202,24 @@ void OptimiserSuite::run( ConstantOptimiser{*evmDialect, *_meter}(astRoot); if (usesOptimizedCodeGenerator) { - StackCompressor::run( + _object.code = std::make_shared(std::move(astRoot)); + astRoot = std::get<1>(StackCompressor::run( _dialect, - astRoot, _object, _optimizeStackAllocation, stackCompressorMaxIterations - ); + )); if (evmDialect->providesObjectAccess()) - StackLimitEvader::run(suite.m_context, astRoot, _object); + { + _object.code = std::make_shared(std::move(astRoot)); + astRoot = StackLimitEvader::run(suite.m_context, _object); + } } else if (evmDialect->providesObjectAccess() && _optimizeStackAllocation) - StackLimitEvader::run(suite.m_context, astRoot, _object); + { + _object.code = std::make_shared(std::move(astRoot)); + astRoot = StackLimitEvader::run(suite.m_context, _object); + } } dispenser.reset(astRoot); diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 357e5b657..2190c1010 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -400,7 +400,11 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( FunctionHoister::run(*m_context, block); FunctionGrouper::run(*m_context, block); size_t maxIterations = 16; - StackCompressor::run(*m_dialect, block, *m_object, true, maxIterations); + { + Object object(*m_object); + object.code = std::make_shared(std::get(ASTCopier{}(block))); + block = std::get<1>(StackCompressor::run(*m_dialect, object, true, maxIterations)); + } BlockFlattener::run(*m_context, block); return block; }}, @@ -420,12 +424,14 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( {"stackLimitEvader", [&]() { auto block = disambiguate(); updateContext(block); - StackLimitEvader::run(*m_context, block, CompilabilityChecker{ + Object object(*m_object); + object.code = std::make_shared(std::get(ASTCopier{}(block))); + auto const unreachables = CompilabilityChecker{ *m_dialect, - *m_object, - true, - &block - }.unreachableVariables); + object, + true + }.unreachableVariables; + StackLimitEvader::run(*m_context, block, unreachables); return block; }}, {"fakeStackLimitEvader", [&]() { diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 1655b13d3..ad32337bd 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -218,7 +218,8 @@ class YulOpti case ';': { Object obj; - StackCompressor::run(m_dialect, *m_astRoot, obj, true, 16); + obj.code = std::make_shared(std::get(ASTCopier{}(*m_astRoot))); + *m_astRoot = std::get<1>(StackCompressor::run(m_dialect, obj, true, 16)); break; } default: From d067964b29f25985fb71699bc6802e5e06470663 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:00:00 +0200 Subject: [PATCH 0233/1340] Yul: introduce setCode method for yul::Object to properly clean up resources --- libsolidity/codegen/CompilerContext.cpp | 16 ++++++------- libsolidity/codegen/ContractCompiler.cpp | 4 ++-- libyul/AST.h | 2 +- libyul/AsmAnalysis.cpp | 2 +- libyul/CompilabilityChecker.cpp | 8 +++---- libyul/Object.cpp | 24 +++++++++++++++---- libyul/Object.h | 8 ++++++- libyul/ObjectParser.cpp | 6 ++--- libyul/YulStack.cpp | 18 +++++++------- libyul/backends/evm/EVMObjectCompiler.cpp | 10 ++++---- libyul/optimiser/Semantics.cpp | 2 +- libyul/optimiser/StackCompressor.cpp | 10 ++++---- libyul/optimiser/StackLimitEvader.cpp | 4 ++-- libyul/optimiser/Suite.cpp | 14 +++++------ test/libsolidity/MemoryGuardTest.cpp | 2 +- test/libyul/Common.cpp | 8 +++---- test/libyul/Common.h | 2 +- test/libyul/CompilabilityChecker.cpp | 5 ++-- test/libyul/ControlFlowGraphTest.cpp | 2 +- test/libyul/ControlFlowSideEffectsTest.cpp | 9 +++---- test/libyul/FunctionSideEffects.cpp | 7 +++--- test/libyul/KnowledgeBaseTest.cpp | 6 ++--- test/libyul/Metrics.cpp | 3 ++- test/libyul/StackLayoutGeneratorTest.cpp | 2 +- test/libyul/YulInterpreterTest.cpp | 2 +- test/libyul/YulInterpreterTest.h | 4 ++-- test/libyul/YulOptimizerTest.cpp | 2 +- test/libyul/YulOptimizerTestCommon.cpp | 22 ++++++++--------- .../tools/ossfuzz/StackReuseCodegenFuzzer.cpp | 2 +- test/tools/ossfuzz/YulEvmoneInterface.cpp | 2 +- test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 6 ++--- test/tools/ossfuzz/yulProtoFuzzer.cpp | 2 +- test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp | 4 ++-- test/tools/yulopti.cpp | 2 +- test/tools/yulrun.cpp | 6 ++--- tools/yulPhaser/Program.cpp | 2 +- 36 files changed, 128 insertions(+), 102 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index aa6985503..b1b76a97b 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -475,14 +475,14 @@ void CompilerContext::appendInlineAssembly( ).analyze(parserResult->root()); if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) reportError("Invalid assembly generated by code generator."); + std::shared_ptr toBeAssembledAST = parserResult; // Several optimizer steps cannot handle externally supplied stack variables, // so we essentially only optimize the ABI functions. if (_optimiserSettings.runYulOptimiser && _localVariables.empty()) { yul::Object obj; - obj.code = parserResult; - obj.analysisInfo = std::make_shared(analysisInfo); + obj.setCode(parserResult, std::make_shared(analysisInfo)); solAssert(!dialect.providesObjectAccess()); optimizeYul(obj, dialect, _optimiserSettings, externallyUsedIdentifiers); @@ -491,15 +491,15 @@ void CompilerContext::appendInlineAssembly( { // Store as generated sources, but first re-parse to update the source references. solAssert(m_generatedYulUtilityCode.empty(), ""); - m_generatedYulUtilityCode = yul::AsmPrinter(yul::AsmPrinter::TypePrinting::OmitDefault, dialect)(obj.code->root()); - std::string code = yul::AsmPrinter{yul::AsmPrinter::TypePrinting::OmitDefault, dialect}(obj.code->root()); + m_generatedYulUtilityCode = yul::AsmPrinter(yul::AsmPrinter::TypePrinting::OmitDefault, dialect)(obj.code()->root()); + std::string code = yul::AsmPrinter{yul::AsmPrinter::TypePrinting::OmitDefault, dialect}(obj.code()->root()); langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); - obj.code = yul::Parser(errorReporter, dialect).parse(charStream); - *obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj); + obj.setCode(yul::Parser(errorReporter, dialect).parse(charStream)); + obj.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj)); } analysisInfo = std::move(*obj.analysisInfo); - parserResult = std::move(obj.code); + toBeAssembledAST = obj.code(); #ifdef SOL_OUTPUT_ASM cout << "After optimizer:" << endl; @@ -518,7 +518,7 @@ void CompilerContext::appendInlineAssembly( solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block."); yul::CodeGenerator::assemble( - parserResult->root(), + toBeAssembledAST->root(), analysisInfo, *m_asm, m_evmVersion, diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 21899f72a..9e0593cdf 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -944,12 +944,12 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) solAssert(dialect, ""); // Create a modifiable copy of the code and analysis - object.code = std::make_shared(yul::ASTCopier().translate(code->root())); + object.setCode(std::make_shared(yul::ASTCopier().translate(code->root()))); object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object)); m_context.optimizeYul(object, *dialect, m_optimiserSettings); - code = object.code.get(); + code = object.code().get(); analysisInfo = object.analysisInfo.get(); } diff --git a/libyul/AST.h b/libyul/AST.h index ca4846907..6b9682580 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -107,7 +107,7 @@ class AST public: explicit AST(Block _root): m_root(std::move(_root)) {} - Block const& root() const { return m_root; } + [[nodiscard]] Block const& root() const { return m_root; } private: Block m_root; }; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index dae945fe8..09be59742 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -86,7 +86,7 @@ bool AsmAnalyzer::analyze(Block const& _block) AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object) { - return analyzeStrictAssertCorrect(_dialect, _object.code->root(), _object.qualifiedDataNames()); + return analyzeStrictAssertCorrect(_dialect, _object.code()->root(), _object.qualifiedDataNames()); } AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index af7532c75..8ece236bf 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -36,14 +36,14 @@ CompilabilityChecker::CompilabilityChecker( bool _optimizeStackAllocation ) { - yulAssert(_object.code); + yulAssert(_object.hasCode()); if (auto const* evmDialect = dynamic_cast(&_dialect)) { NoOutputEVMDialect noOutputDialect(*evmDialect); yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( noOutputDialect, - _object.code->root(), + _object.code()->root(), _object.qualifiedDataNames() ); @@ -57,12 +57,12 @@ CompilabilityChecker::CompilabilityChecker( CodeTransform transform( assembly, analysisInfo, - _object.code->root(), + _object.code()->root(), noOutputDialect, builtinContext, _optimizeStackAllocation ); - transform(_object.code->root()); + transform(_object.code()->root()); for (StackTooDeepError const& error: transform.stackErrors()) { diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 98649b29b..afd237b5b 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -50,7 +50,7 @@ std::string Object::toString( CharStreamProvider const* _soliditySourceProvider ) const { - yulAssert(code, "No code"); + yulAssert(hasCode(), "No code"); yulAssert(debugData, "No debug data"); std::string useSrcComment; @@ -69,7 +69,7 @@ std::string Object::toString( debugData->sourceNames, _debugInfoSelection, _soliditySourceProvider - )(code->root()); + )(code()->root()); for (auto const& obj: subObjects) inner += "\n" + obj->toString(_dialect, _printingMode, _debugInfoSelection, _soliditySourceProvider); @@ -87,11 +87,11 @@ Json Data::toJson() const Json Object::toJson() const { - yulAssert(code, "No code"); + yulAssert(hasCode(), "No code"); Json codeJson; codeJson["nodeType"] = "YulCode"; - codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */)(code->root()); + codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */)(code()->root()); Json subObjectsJson = Json::array(); for (std::shared_ptr const& subObject: subObjects) @@ -161,6 +161,22 @@ std::vector Object::pathToSubObject(std::string_view _qualifiedName) con return path; } +std::shared_ptr Object::code() const +{ + return m_code; +} + +bool Object::hasCode() const { return code() != nullptr; } + +void Object::setCode(std::shared_ptr const& _ast, std::shared_ptr _analysisInfo) +{ + if (_ast.get() != m_code.get()) + { + m_code = _ast; + analysisInfo = std::move(_analysisInfo); + } +} + void Object::collectSourceIndices(std::map& _indices) const { if (debugData && debugData->sourceNames.has_value()) diff --git a/libyul/Object.h b/libyul/Object.h index cab3bc701..41ca74e9f 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -119,10 +119,13 @@ struct Object: public ObjectNode /// The path must not lead to a @a Data object (will throw in that case). std::vector pathToSubObject(std::string_view _qualifiedName) const; + std::shared_ptr code() const; + void setCode(std::shared_ptr const& _ast, std::shared_ptr = nullptr); + bool hasCode() const; + /// sub id for object if it is subobject of another object, max value if it is not subobject size_t subId = std::numeric_limits::max(); - std::shared_ptr code; std::vector> subObjects; std::map> subIndexByName; std::shared_ptr analysisInfo; @@ -139,6 +142,9 @@ struct Object: public ObjectNode /// @returns the name of the special metadata data object. static std::string metadataName() { return ".metadata"; } + +private: + std::shared_ptr m_code; }; } diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 6813e5059..123dedcb4 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -53,8 +53,8 @@ std::shared_ptr ObjectParser::parse(std::shared_ptr const& _sca object->name = "object"; auto sourceNameMapping = tryParseSourceNameMapping(); object->debugData = std::make_shared(ObjectDebugData{sourceNameMapping}); - object->code = parseBlock(sourceNameMapping); - if (!object->code) + object->setCode(parseBlock(sourceNameMapping)); + if (!object->hasCode()) return nullptr; } else @@ -87,7 +87,7 @@ std::shared_ptr ObjectParser::parseObject(Object* _containingObject) expectToken(Token::LBrace); - ret->code = parseCode(std::move(sourceNameMapping)); + ret->setCode(parseCode(std::move(sourceNameMapping))); while (currentToken() != Token::RBrace) { diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 426551152..dbe30bb13 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -97,7 +97,7 @@ bool YulStack::parseAndAnalyze(std::string const& _sourceName, std::string const yulAssert(m_stackState == Parsed); yulAssert(m_parserResult, ""); - yulAssert(m_parserResult->code, ""); + yulAssert(m_parserResult->hasCode()); return analyzeParsed(); } @@ -135,7 +135,7 @@ bool YulStack::analyzeParsed() bool YulStack::analyzeParsed(Object& _object) { yulAssert(m_stackState >= Parsed); - yulAssert(_object.code, ""); + yulAssert(_object.hasCode()); _object.analysisInfo = std::make_shared(); AsmAnalyzer analyzer( @@ -149,7 +149,7 @@ bool YulStack::analyzeParsed(Object& _object) bool success = false; try { - success = analyzer.analyze(_object.code->root()); + success = analyzer.analyze(_object.code()->root()); for (auto& subNode: _object.subObjects) if (auto subObject = dynamic_cast(subNode.get())) if (!analyzeParsed(*subObject)) @@ -189,7 +189,7 @@ void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) const void YulStack::optimize(Object& _object, bool _isCreation) { - yulAssert(_object.code, ""); + yulAssert(_object.hasCode(), ""); yulAssert(_object.analysisInfo, ""); for (auto& subNode: _object.subObjects) if (auto subObject = dynamic_cast(subNode.get())) @@ -245,7 +245,7 @@ MachineAssemblyObject YulStack::assemble(Machine _machine) { yulAssert(m_stackState >= AnalysisSuccessful); yulAssert(m_parserResult, ""); - yulAssert(m_parserResult->code, ""); + yulAssert(m_parserResult->hasCode(), ""); yulAssert(m_parserResult->analysisInfo, ""); switch (_machine) @@ -302,7 +302,7 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) { yulAssert(m_stackState >= AnalysisSuccessful); yulAssert(m_parserResult, ""); - yulAssert(m_parserResult->code, ""); + yulAssert(m_parserResult->hasCode(), ""); yulAssert(m_parserResult->analysisInfo, ""); evmasm::Assembly assembly(m_evmVersion, true, {}); @@ -359,7 +359,7 @@ std::string YulStack::print( { yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); - yulAssert(m_parserResult->code, ""); + yulAssert(m_parserResult->hasCode(), ""); return m_parserResult->toString( languageToDialect(m_language, m_evmVersion), AsmPrinter::TypePrinting::OmitDefault, @@ -372,7 +372,7 @@ Json YulStack::astJson() const { yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); - yulAssert(m_parserResult->code, ""); + yulAssert(m_parserResult->hasCode(), ""); return m_parserResult->toJson(); } @@ -380,7 +380,7 @@ std::shared_ptr YulStack::parserResult() const { yulAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); yulAssert(m_parserResult, ""); - yulAssert(m_parserResult->code, ""); + yulAssert(m_parserResult->hasCode(), ""); return m_parserResult; } diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index c77bf4e37..ca9f90dfa 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -72,7 +72,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) } yulAssert(_object.analysisInfo, "No analysis info."); - yulAssert(_object.code, "No code."); + yulAssert(_object.hasCode(), "No code."); if (m_eofVersion.has_value()) yulAssert( _optimize && (m_dialect.evmVersion() == langutil::EVMVersion()), @@ -83,7 +83,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) auto stackErrors = OptimizedEVMCodeTransform::run( m_assembly, *_object.analysisInfo, - _object.code->root(), + _object.code()->root(), m_dialect, context, OptimizedEVMCodeTransform::UseNamedLabels::ForFirstFunctionOfEachName @@ -91,7 +91,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) if (!stackErrors.empty()) { std::vector memoryGuardCalls = findFunctionCalls( - _object.code->root(), + _object.code()->root(), "memoryguard"_yulname ); auto stackError = stackErrors.front(); @@ -113,14 +113,14 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) CodeTransform transform{ m_assembly, *_object.analysisInfo, - _object.code->root(), + _object.code()->root(), m_dialect, context, _optimize, {}, CodeTransform::UseNamedLabels::ForFirstFunctionOfEachName }; - transform(_object.code->root()); + transform(_object.code()->root()); if (!transform.stackErrors().empty()) BOOST_THROW_EXCEPTION(transform.stackErrors().front()); } diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index 88f4f7c45..d945dbcac 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -95,7 +95,7 @@ bool MSizeFinder::containsMSize(Dialect const& _dialect, Block const& _ast) bool MSizeFinder::containsMSize(Dialect const& _dialect, Object const& _object) { - if (containsMSize(_dialect, _object.code->root())) + if (containsMSize(_dialect, _object.code()->root())) return true; for (std::shared_ptr const& node: _object.subObjects) diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index bdc20a5a8..2c2ef4272 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -242,9 +242,9 @@ std::tuple StackCompressor::run( bool _optimizeStackAllocation, size_t _maxIterations) { - yulAssert(_object.code); + yulAssert(_object.hasCode()); yulAssert( - !_object.code->root().statements.empty() && std::holds_alternative(_object.code->root().statements.at(0)), + !_object.code()->root().statements.empty() && std::holds_alternative(_object.code()->root().statements.at(0)), "Need to run the function grouper before the stack compressor." ); bool usesOptimizedCodeGenerator = false; @@ -253,8 +253,8 @@ std::tuple StackCompressor::run( _optimizeStackAllocation && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); - bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _object.code->root()); - Block astRoot = std::get(ASTCopier{}(_object.code->root())); + bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _object.code()->root()); + Block astRoot = std::get(ASTCopier{}(_object.code()->root())); if (usesOptimizedCodeGenerator) { yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, astRoot, _object.qualifiedDataNames()); @@ -271,7 +271,7 @@ std::tuple StackCompressor::run( for (size_t iterations = 0; iterations < _maxIterations; iterations++) { Object object(_object); - object.code = std::make_shared(std::get(ASTCopier{}(astRoot))); + object.setCode(std::make_shared(std::get(ASTCopier{}(astRoot)))); std::map stackSurplus = CompilabilityChecker(_dialect, object, _optimizeStackAllocation).stackDeficit; if (stackSurplus.empty()) return std::make_tuple(true, std::move(astRoot)); diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index d613ae993..6e6da63e6 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -123,13 +123,13 @@ Block StackLimitEvader::run( Object const& _object ) { - yulAssert(_object.code); + yulAssert(_object.hasCode()); auto const* evmDialect = dynamic_cast(&_context.dialect); yulAssert( evmDialect && evmDialect->providesObjectAccess(), "StackLimitEvader can only be run on objects using the EVMDialect with object access." ); - auto astRoot = std::get(ASTCopier{}(_object.code->root())); + auto astRoot = std::get(ASTCopier{}(_object.code()->root())); if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall()) { yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, astRoot, _object.qualifiedDataNames()); diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index cc0c1a7f3..a06f48a7f 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -157,7 +157,7 @@ void OptimiserSuite::run( _dialect, *_object.analysisInfo, reservedIdentifiers - )(_object.code->root())); + )(_object.code()->root())); NameDispenser dispenser{_dialect, astRoot, reservedIdentifiers}; OptimiserStepContext context{_dialect, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment}; @@ -180,7 +180,7 @@ void OptimiserSuite::run( // message once we perform code generation. if (!usesOptimizedCodeGenerator) { - _object.code = std::make_shared(std::move(astRoot)); + _object.setCode(std::make_shared(std::move(astRoot))); astRoot = std::get<1>(StackCompressor::run( _dialect, _object, @@ -202,7 +202,7 @@ void OptimiserSuite::run( ConstantOptimiser{*evmDialect, *_meter}(astRoot); if (usesOptimizedCodeGenerator) { - _object.code = std::make_shared(std::move(astRoot)); + _object.setCode(std::make_shared(std::move(astRoot))); astRoot = std::get<1>(StackCompressor::run( _dialect, _object, @@ -211,13 +211,13 @@ void OptimiserSuite::run( )); if (evmDialect->providesObjectAccess()) { - _object.code = std::make_shared(std::move(astRoot)); + _object.setCode(std::make_shared(std::move(astRoot))); astRoot = StackLimitEvader::run(suite.m_context, _object); } } else if (evmDialect->providesObjectAccess() && _optimizeStackAllocation) { - _object.code = std::make_shared(std::move(astRoot)); + _object.setCode(std::make_shared(std::move(astRoot))); astRoot = StackLimitEvader::run(suite.m_context, _object); } } @@ -230,8 +230,8 @@ void OptimiserSuite::run( outputPerformanceMetrics(suite.m_durationPerStepInMicroseconds); #endif - _object.code = std::make_shared(std::move(astRoot)); - *_object.analysisInfo = AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object); + _object.setCode(std::make_shared(std::move(astRoot))); + _object.analysisInfo = std::make_shared(AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object)); } namespace diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index c5579d84a..b2e0b75d3 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -75,7 +75,7 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con auto handleObject = [&](std::string const& _kind, Object const& _object) { m_obtainedResult += contractName + "(" + _kind + ") " + (findFunctionCalls( - _object.code->root(), + _object.code()->root(), "memoryguard"_yulname ).empty() ? "false" : "true") + "\n"; }; diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 26f5e0684..d147e03d0 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -50,7 +50,7 @@ Dialect const& defaultDialect(bool _yul) } } -std::pair, std::shared_ptr> yul::test::parse(std::string const& _source, bool _yul) +std::pair, std::shared_ptr> yul::test::parse(std::string const& _source, bool _yul) { YulStack stack( solidity::test::CommonOptions::get().evmVersion(), @@ -63,7 +63,7 @@ std::pair, std::shared_ptr> yul::test ); if (!stack.parseAndAnalyze("", _source) || !stack.errors().empty()) BOOST_FAIL("Invalid source."); - return make_pair(stack.parserResult()->code, stack.parserResult()->analysisInfo); + return std::make_pair(stack.parserResult()->code(), stack.parserResult()->analysisInfo); } std::pair, std::shared_ptr> yul::test::parse( @@ -78,12 +78,12 @@ std::pair, std::shared_ptr> yul::t std::shared_ptr parserResult = yul::ObjectParser(errorReporter, _dialect).parse(scanner, false); if (!parserResult) return {}; - if (!parserResult->code || errorReporter.hasErrors()) + if (!parserResult->hasCode() || errorReporter.hasErrors()) return {}; std::shared_ptr analysisInfo = std::make_shared(); AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect, {}, parserResult->qualifiedDataNames()); // TODO this should be done recursively. - if (!analyzer.analyze(parserResult->code->root()) || errorReporter.hasErrors()) + if (!analyzer.analyze(parserResult->code()->root()) || errorReporter.hasErrors()) return {}; return {std::move(parserResult), std::move(analysisInfo)}; } diff --git a/test/libyul/Common.h b/test/libyul/Common.h index 4a9696cd9..14d73d77e 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -45,7 +45,7 @@ class AST; namespace solidity::yul::test { -std::pair, std::shared_ptr> +std::pair, std::shared_ptr> parse(std::string const& _source, bool _yul = true); std::pair, std::shared_ptr> diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index 27310cd89..5b64b5e5d 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -35,8 +35,9 @@ namespace std::string check(std::string const& _input) { Object obj; - std::tie(obj.code, obj.analysisInfo) = yul::test::parse(_input, false); - BOOST_REQUIRE(obj.code); + auto parsingResult = yul::test::parse(_input, false); + obj.setCode(parsingResult.first, parsingResult.second); + BOOST_REQUIRE(obj.hasCode()); auto functions = CompilabilityChecker(EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion()), obj, true).stackDeficit; std::string out; for (auto const& function: functions) diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index 8e08bf488..5c9bba8d4 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -206,7 +206,7 @@ TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::strin std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code->root()); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code()->root()); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; ControlFlowGraphPrinter printer{output}; diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index 054c70547..20df176a3 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -57,16 +57,17 @@ ControlFlowSideEffectsTest::ControlFlowSideEffectsTest(std::string const& _filen TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { Object obj; - std::tie(obj.code, obj.analysisInfo) = yul::test::parse(m_source, false); - if (!obj.code) + auto parsingResult = yul::test::parse(m_source, false); + obj.setCode(parsingResult.first, parsingResult.second); + if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); ControlFlowSideEffectsCollector sideEffects( EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), - obj.code->root() + obj.code()->root() ); m_obtainedResult.clear(); - forEach(obj.code->root(), [&](FunctionDefinition const& _fun) { + forEach(obj.code()->root(), [&](FunctionDefinition const& _fun) { std::string effectStr = toString(sideEffects.functionSideEffects().at(&_fun)); m_obtainedResult += _fun.name.str() + (effectStr.empty() ? ":" : ": " + effectStr) + "\n"; }); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index 3220a8c6f..a39024d27 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -83,13 +83,14 @@ FunctionSideEffects::FunctionSideEffects(std::string const& _filename): TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { Object obj; - std::tie(obj.code, obj.analysisInfo) = yul::test::parse(m_source, false); - if (!obj.code) + auto parsingResult = yul::test::parse(m_source, false); + obj.setCode(parsingResult.first, parsingResult.second); + if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); std::map functionSideEffects = SideEffectsPropagator::sideEffects( EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), - CallGraphGenerator::callGraph(obj.code->root()) + CallGraphGenerator::callGraph(obj.code()->root()) ); std::map functionSideEffectsStr; diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index a149381ca..0293f8ee4 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -47,9 +47,9 @@ class KnowledgeBaseTest ErrorList errorList; std::shared_ptr analysisInfo; std::tie(m_object, analysisInfo) = yul::test::parse(_source, m_dialect, errorList); - BOOST_REQUIRE(m_object && errorList.empty() && m_object->code); + BOOST_REQUIRE(m_object && errorList.empty() && m_object->hasCode()); - auto astRoot = std::get(yul::ASTCopier{}(m_object->code->root())); + auto astRoot = std::get(yul::ASTCopier{}(m_object->code()->root())); NameDispenser dispenser(m_dialect, astRoot); std::set reserved; OptimiserStepContext context{m_dialect, dispenser, reserved, 0}; @@ -59,7 +59,7 @@ class KnowledgeBaseTest for (auto const& [name, expression]: m_ssaValues.values()) m_values[name].value = expression; - m_object->code = std::make_shared(std::move(astRoot)); + m_object->setCode(std::make_shared(std::move(astRoot))); return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }); } diff --git a/test/libyul/Metrics.cpp b/test/libyul/Metrics.cpp index ce65cf2c8..bf09a1c2b 100644 --- a/test/libyul/Metrics.cpp +++ b/test/libyul/Metrics.cpp @@ -24,6 +24,7 @@ #include #include +#include #include @@ -37,7 +38,7 @@ namespace size_t codeSize(std::string const& _source, CodeWeights const _weights = {}) { - std::shared_ptr ast = parse(_source, false).first; + std::shared_ptr ast = parse(_source, false).first; BOOST_REQUIRE(ast); return CodeSize::codeSize(ast->root(), _weights); } diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 2abac60e5..9c16eaefc 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -224,7 +224,7 @@ TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::s std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code->root()); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code()->root()); StackLayout stackLayout = StackLayoutGenerator::run(*cfg); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index d987c519c..9d4ccd81b 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -75,7 +75,7 @@ bool YulInterpreterTest::parse(std::ostream& _stream, std::string const& _linePr ); if (stack.parseAndAnalyze("", m_source)) { - m_ast = stack.parserResult()->code; + m_ast = stack.parserResult()->code(); m_analysisInfo = stack.parserResult()->analysisInfo; return true; } diff --git a/test/libyul/YulInterpreterTest.h b/test/libyul/YulInterpreterTest.h index f53686702..d59159133 100644 --- a/test/libyul/YulInterpreterTest.h +++ b/test/libyul/YulInterpreterTest.h @@ -45,8 +45,8 @@ class YulInterpreterTest: public solidity::frontend::test::EVMVersionRestrictedT bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); std::string interpret(); - std::shared_ptr m_ast; - std::shared_ptr m_analysisInfo; + std::shared_ptr m_ast; + std::shared_ptr m_analysisInfo; bool m_simulateExternalCallsToSelf = false; }; diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index df28515c3..048eb7145 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -81,7 +81,7 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co auto optimizedObject = tester.optimizedObject(); std::string printedOptimizedObject; if (optimizedObject->subObjects.empty()) - printedOptimizedObject = AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, *m_dialect}(optimizedObject->code->root()); + printedOptimizedObject = AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, *m_dialect}(optimizedObject->code()->root()); else printedOptimizedObject = optimizedObject->toString(*m_dialect); diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 2190c1010..2898086e8 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -98,14 +98,14 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( return block; }}, {"constantOptimiser", [&]() { - auto block = std::get(ASTCopier{}(m_object->code->root())); + auto block = std::get(ASTCopier{}(m_object->code()->root())); updateContext(block); GasMeter meter(dynamic_cast(*m_dialect), false, 200); ConstantOptimiser{dynamic_cast(*m_dialect), meter}(block); return block; }}, {"varDeclInitializer", [&]() { - auto block = std::get(ASTCopier{}(m_object->code->root())); + auto block = std::get(ASTCopier{}(m_object->code()->root())); updateContext(block); VarDeclInitializer::run(*m_context, block); return block; @@ -151,7 +151,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( return block; }}, {"expressionSplitter", [&]() { - auto block = std::get(ASTCopier{}(m_object->code->root())); + auto block = std::get(ASTCopier{}(m_object->code()->root())); updateContext(block); ExpressionSplitter::run(*m_context, block); return block; @@ -401,8 +401,8 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( FunctionGrouper::run(*m_context, block); size_t maxIterations = 16; { - Object object(*m_object); - object.code = std::make_shared(std::get(ASTCopier{}(block))); + Object object; // (*m_object) ?? + object.setCode(std::make_shared(std::get(ASTCopier{}(block)))); block = std::get<1>(StackCompressor::run(*m_dialect, object, true, maxIterations)); } BlockFlattener::run(*m_context, block); @@ -419,13 +419,13 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( frontend::OptimiserSettings::DefaultYulOptimiserCleanupSteps, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment ); - return std::get(ASTCopier{}(m_optimizedObject->code->root())); + return std::get(ASTCopier{}(m_optimizedObject->code()->root())); }}, {"stackLimitEvader", [&]() { auto block = disambiguate(); updateContext(block); - Object object(*m_object); - object.code = std::make_shared(std::get(ASTCopier{}(block))); + Object object; // (*m_object); + object.setCode(std::make_shared(std::get(ASTCopier{}(block)))); auto const unreachables = CompilabilityChecker{ *m_dialect, object, @@ -492,7 +492,7 @@ bool YulOptimizerTestCommon::runStep() if (m_namedSteps.count(m_optimizerStep)) { auto block = m_namedSteps[m_optimizerStep](); - m_optimizedObject->code = std::make_shared(std::move(block)); + m_optimizedObject->setCode(std::make_shared(std::move(block))); } else return false; @@ -531,12 +531,12 @@ std::string YulOptimizerTestCommon::randomOptimiserStep(unsigned _seed) Block const* YulOptimizerTestCommon::run() { - return runStep() ? &m_optimizedObject->code->root() : nullptr; + return runStep() ? &m_optimizedObject->code()->root() : nullptr; } Block YulOptimizerTestCommon::disambiguate() { - auto block = std::get(Disambiguator(*m_dialect, *m_analysisInfo)(m_object->code->root())); + auto block = std::get(Disambiguator(*m_dialect, *m_analysisInfo)(m_object->code()->root())); m_analysisInfo.reset(); return block; } diff --git a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp index 940fc7374..a064fcdc8 100644 --- a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp +++ b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp @@ -54,7 +54,7 @@ namespace /// @returns true if there are recursive functions, false otherwise. bool recursiveFunctionExists(Dialect const& _dialect, yul::Object& _object) { - auto recursiveFunctions = CallGraphGenerator::callGraph(_object.code->root()).recursiveFunctions(); + auto recursiveFunctions = CallGraphGenerator::callGraph(_object.code()->root()).recursiveFunctions(); for(auto&& [function, variables]: CompilabilityChecker{ _dialect, _object, diff --git a/test/tools/ossfuzz/YulEvmoneInterface.cpp b/test/tools/ossfuzz/YulEvmoneInterface.cpp index b89245443..74da5a1f0 100644 --- a/test/tools/ossfuzz/YulEvmoneInterface.cpp +++ b/test/tools/ossfuzz/YulEvmoneInterface.cpp @@ -27,7 +27,7 @@ bytes YulAssembler::assemble() { if ( !m_stack.parseAndAnalyze("source", m_yulProgram) || - !m_stack.parserResult()->code || + !m_stack.parserResult()->code() || !m_stack.parserResult()->analysisInfo || langutil::Error::containsErrors(m_stack.errors()) ) diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index 40201bd15..f685aa90d 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -71,7 +71,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) { if ( !stack.parseAndAnalyze("source", input) || - !stack.parserResult()->code || + !stack.parserResult()->hasCode() || !stack.parserResult()->analysisInfo ) return 0; @@ -89,7 +89,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) // that would be removed by the redundant store eliminator. yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( os1, - stack.parserResult()->code->root(), + stack.parserResult()->code()->root(), EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), /*disableMemoryTracing=*/true ); @@ -99,7 +99,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) stack.optimize(); termReason = yulFuzzerUtil::interpret( os2, - stack.parserResult()->code->root(), + stack.parserResult()->code()->root(), EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), /*disableMemoryTracing=*/true ); diff --git a/test/tools/ossfuzz/yulProtoFuzzer.cpp b/test/tools/ossfuzz/yulProtoFuzzer.cpp index 092f2dacb..cfdb20813 100644 --- a/test/tools/ossfuzz/yulProtoFuzzer.cpp +++ b/test/tools/ossfuzz/yulProtoFuzzer.cpp @@ -72,7 +72,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // Parse protobuf mutated YUL code if ( !stack.parseAndAnalyze("source", yul_source) || - !stack.parserResult()->code || + !stack.parserResult()->code() || !stack.parserResult()->analysisInfo || Error::containsErrors(stack.errors()) ) diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index 4e07eaf64..13ac4aea8 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -72,7 +72,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // Parse protobuf mutated YUL code if ( !stack.parseAndAnalyze("source", yul_source) || - !stack.parserResult()->code || + !stack.parserResult()->code() || !stack.parserResult()->analysisInfo || Error::containsErrors(stack.errors()) ) @@ -89,7 +89,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // that would be removed by the redundant store eliminator. yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( os1, - stack.parserResult()->code->root(), + stack.parserResult()->code()->root(), EVMDialect::strictAssemblyForEVMObjects(version), /*disableMemoryTracing=*/true ); diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index ad32337bd..faab89e79 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -218,7 +218,7 @@ class YulOpti case ';': { Object obj; - obj.code = std::make_shared(std::get(ASTCopier{}(*m_astRoot))); + obj.setCode(std::make_shared(std::get(ASTCopier{}(*m_astRoot)))); *m_astRoot = std::get<1>(StackCompressor::run(m_dialect, obj, true, 16)); break; } diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index 9aee616e0..c3a7fb19f 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -54,7 +54,7 @@ namespace po = boost::program_options; namespace { -std::pair, std::shared_ptr> parse(std::string const& _source) +std::pair, std::shared_ptr> parse(std::string const& _source) { YulStack stack( langutil::EVMVersion(), @@ -66,7 +66,7 @@ std::pair, std::shared_ptr> parse(std::str if (stack.parseAndAnalyze("--INPUT--", _source)) { yulAssert(stack.errors().empty(), "Parsed successfully but had errors."); - return make_pair(stack.parserResult()->code, stack.parserResult()->analysisInfo); + return make_pair(stack.parserResult()->code(), stack.parserResult()->analysisInfo); } else { @@ -77,7 +77,7 @@ std::pair, std::shared_ptr> parse(std::str void interpret(std::string const& _source, bool _inspect, bool _disableExternalCalls) { - std::shared_ptr ast; + std::shared_ptr ast; std::shared_ptr analysisInfo; tie(ast, analysisInfo) = parse(_source); if (!ast || !analysisInfo) diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 2d5c31cf1..14b640649 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -149,7 +149,7 @@ std::variant, ErrorList> Program::parseObject(Dialect const // The public API of the class does not provide access to the smart pointer so it won't be hard // to switch to shared_ptr if the copying turns out to be an issue (though it would be better // to refactor ObjectParser and Object to use unique_ptr instead). - auto astCopy = std::make_unique(std::get(ASTCopier{}(selectedObject->code->root()))); + auto astCopy = std::make_unique(std::get(ASTCopier{}(selectedObject->code()->root()))); return std::variant, ErrorList>(std::move(astCopy)); } From 44bfa720d0bc6d3ab51154bd44fc66776d453276 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 2 Aug 2024 15:34:20 +0200 Subject: [PATCH 0234/1340] Yul: optimizer tests assert that there are no subobjects but Data --- test/libyul/YulOptimizerTestCommon.cpp | 21 ++++++++++++------- test/libyul/YulOptimizerTestCommon.h | 5 ++--- .../long_literals_as_builtin_args.yul | 8 ++----- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 2898086e8..bf374c21f 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -74,11 +74,19 @@ using namespace solidity::yul::test; using namespace solidity::frontend; YulOptimizerTestCommon::YulOptimizerTestCommon( - std::shared_ptr _obj, + std::shared_ptr _obj, Dialect const& _dialect -): m_dialect(&_dialect), m_object(_obj), m_optimizedObject(std::make_shared()), m_analysisInfo(m_object->analysisInfo) +): m_dialect(&_dialect), m_object(_obj), m_optimizedObject(std::make_shared(*_obj)) { - *m_optimizedObject = *m_object; + if ( + std::any_of( + m_object->subObjects.begin(), + m_object->subObjects.end(), + [](auto const& subObject) { return dynamic_cast(subObject.get()) == nullptr;} + ) + ) + solUnimplementedAssert(false, "The current implementation of YulOptimizerTests ignores subobjects that are not Data."); + m_namedSteps = { {"disambiguator", [&]() { return disambiguate(); }}, {"nameDisplacer", [&]() { @@ -401,7 +409,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( FunctionGrouper::run(*m_context, block); size_t maxIterations = 16; { - Object object; // (*m_object) ?? + Object object(*m_optimizedObject); object.setCode(std::make_shared(std::get(ASTCopier{}(block)))); block = std::get<1>(StackCompressor::run(*m_dialect, object, true, maxIterations)); } @@ -424,7 +432,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( {"stackLimitEvader", [&]() { auto block = disambiguate(); updateContext(block); - Object object; // (*m_object); + Object object(*m_optimizedObject); object.setCode(std::make_shared(std::get(ASTCopier{}(block)))); auto const unreachables = CompilabilityChecker{ *m_dialect, @@ -536,8 +544,7 @@ Block const* YulOptimizerTestCommon::run() Block YulOptimizerTestCommon::disambiguate() { - auto block = std::get(Disambiguator(*m_dialect, *m_analysisInfo)(m_object->code()->root())); - m_analysisInfo.reset(); + auto block = std::get(Disambiguator(*m_dialect, *m_object->analysisInfo)(m_object->code()->root())); return block; } diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h index 8a706c328..41806fcd6 100644 --- a/test/libyul/YulOptimizerTestCommon.h +++ b/test/libyul/YulOptimizerTestCommon.h @@ -40,7 +40,7 @@ class YulOptimizerTestCommon { public: explicit YulOptimizerTestCommon( - std::shared_ptr _obj, + std::shared_ptr _obj, Dialect const& _dialect ); /// Sets optimiser step to be run to @param @@ -70,9 +70,8 @@ class YulOptimizerTestCommon std::unique_ptr m_nameDispenser; std::unique_ptr m_context; - std::shared_ptr m_object; + std::shared_ptr m_object; std::shared_ptr m_optimizedObject; - std::shared_ptr m_analysisInfo; std::map> m_namedSteps; }; diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul index 34b44aad9..f480bec9e 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul @@ -7,9 +7,7 @@ object "AccessControlDefaultAdminRules4233_14" { let j := datasize("AccessControlDefaultAdminRules4233_14_deployed") codecopy(i, dataoffset("AccessControlDefaultAdminRules4233_14_deployed"), j) } - object "AccessControlDefaultAdminRules4233_14_deployed" { - code {} - } + data "AccessControlDefaultAdminRules4233_14_deployed" "AccessControlDefaultAdminRules4233_14_deployed" } // ---- @@ -22,7 +20,5 @@ object "AccessControlDefaultAdminRules4233_14" { // let j := datasize("AccessControlDefaultAdminRules4233_14_deployed") // codecopy(i, dataoffset("AccessControlDefaultAdminRules4233_14_deployed"), j) // } -// object "AccessControlDefaultAdminRules4233_14_deployed" { -// code { } -// } +// data "AccessControlDefaultAdminRules4233_14_deployed" hex"416363657373436f6e74726f6c44656661756c7441646d696e52756c6573343233335f31345f6465706c6f796564" // } From 860f0d4601ee2b2ad200344e7e4a133e71432a57 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 13 Apr 2023 00:10:31 +0200 Subject: [PATCH 0235/1340] Change the constant optimizer to make use of PUSH0 --- libevmasm/Assembly.cpp | 4 +- libevmasm/AssemblyItem.cpp | 6 +- libevmasm/AssemblyItem.h | 7 +- libevmasm/ConstantOptimiser.cpp | 95 ++++++++++++++------ libevmasm/ConstantOptimiser.h | 4 +- libevmasm/GasMeter.cpp | 16 ++-- libevmasm/GasMeter.h | 3 + libevmasm/Inliner.cpp | 16 ++-- libevmasm/PeepholeOptimiser.cpp | 31 ++++--- libevmasm/PeepholeOptimiser.h | 9 +- libyul/backends/evm/EVMMetrics.cpp | 9 +- libyul/backends/evm/StackLayoutGenerator.cpp | 2 +- test/libevmasm/Optimiser.cpp | 77 +++++++++++++--- test/libsolidity/StandardCompiler.cpp | 13 ++- 14 files changed, 206 insertions(+), 86 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index f9b800c90..91773a8e8 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -74,7 +74,7 @@ unsigned Assembly::codeSize(unsigned subTagSize) const ret += i.second.size(); for (AssemblyItem const& i: m_items) - ret += i.bytesRequired(tagSize, Precision::Approximate); + ret += i.bytesRequired(tagSize, m_evmVersion, Precision::Approximate); if (numberEncodingSize(ret) <= tagSize) return static_cast(ret); } @@ -753,7 +753,7 @@ std::map const& Assembly::optimiseInternal( if (_settings.runPeephole) { - PeepholeOptimiser peepOpt{m_items}; + PeepholeOptimiser peepOpt{m_items, m_evmVersion}; while (peepOpt.optimise()) { count++; diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index c88a9663f..837dad8af 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -116,7 +116,7 @@ void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag) setData(data); } -size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision) const +size_t AssemblyItem::bytesRequired(size_t _addressLength, langutil::EVMVersion _evmVersion, Precision _precision) const { switch (m_type) { @@ -124,7 +124,9 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision) case Tag: // 1 byte for the JUMPDEST return 1; case Push: - return 1 + std::max(1, numberEncodingSize(data())); + return + 1 + + std::max((_evmVersion.hasPush0() ? 0 : 1), numberEncodingSize(data())); case PushSubSize: case PushProgramSize: return 1 + 4; // worst case: a 16MB program diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index c2b3603c6..f06c72bac 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -161,10 +161,11 @@ class AssemblyItem /// @returns an upper bound for the number of bytes required by this item, assuming that /// the value of a jump tag takes @a _addressLength bytes. + /// @param _evmVersion the EVM version /// @param _precision Whether to return a precise count (which involves /// counting immutable references which are only set after /// a call to `assemble()`) or an approx. count. - size_t bytesRequired(size_t _addressLength, Precision _precision = Precision::Precise) const; + size_t bytesRequired(size_t _addressLength, langutil::EVMVersion _evmVersion, Precision _precision = Precision::Precise) const; size_t arguments() const; size_t returnValues() const; size_t deposit() const { return returnValues() - arguments(); } @@ -228,11 +229,11 @@ class AssemblyItem mutable std::optional m_immutableOccurrences; }; -inline size_t bytesRequired(AssemblyItems const& _items, size_t _addressLength, Precision _precision = Precision::Precise) +inline size_t bytesRequired(AssemblyItems const& _items, size_t _addressLength, langutil::EVMVersion _evmVersion, Precision _precision = Precision::Precise) { size_t size = 0; for (AssemblyItem const& item: _items) - size += item.bytesRequired(_addressLength, _precision); + size += item.bytesRequired(_addressLength, _evmVersion, _precision); return size; } diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 62dbc803b..360fb781f 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -83,7 +83,7 @@ bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items, lan bigint gas = 0; for (AssemblyItem const& item: _items) if (item.type() == Push) - gas += GasMeter::runGas(Instruction::PUSH1, _evmVersion); + gas += GasMeter::pushGas(item.data(), _evmVersion); else if (item.type() == Operation) { if (item.instruction() == Instruction::EXP) @@ -100,9 +100,9 @@ bigint ConstantOptimisationMethod::dataGas(bytes const& _data) const return bigint(GasMeter::dataGas(_data, m_params.isCreation, m_params.evmVersion)); } -size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items) +size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items, langutil::EVMVersion _evmVersion) { - return evmasm::bytesRequired(_items, 3, Precision::Approximate); // assume 3 byte addresses + return evmasm::bytesRequired(_items, 3, _evmVersion, Precision::Approximate); // assume 3 byte addresses } void ConstantOptimisationMethod::replaceConstants( @@ -143,7 +143,7 @@ bigint CodeCopyMethod::gasNeeded() const // Run gas: we ignore memory increase costs simpleRunGas(copyRoutine(), m_params.evmVersion) + GasCosts::copyGas, // Data gas for copy routines: Some bytes are zero, but we ignore them. - bytesRequired(copyRoutine()) * (m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas), + bytesRequired(copyRoutine(), m_params.evmVersion) * (m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas), // Data gas for data itself dataGas(toBigEndian(m_value)) ); @@ -153,37 +153,74 @@ AssemblyItems CodeCopyMethod::execute(Assembly& _assembly) const { bytes data = toBigEndian(m_value); assertThrow(data.size() == 32, OptimizerException, "Invalid number encoding."); - AssemblyItems actualCopyRoutine = copyRoutine(); - actualCopyRoutine[4] = _assembly.newData(data); - return actualCopyRoutine; + AssemblyItem newPushData = _assembly.newData(data); + return copyRoutine(&newPushData); } -AssemblyItems const& CodeCopyMethod::copyRoutine() +AssemblyItems CodeCopyMethod::copyRoutine(AssemblyItem* _pushData) const { - AssemblyItems static copyRoutine{ - // constant to be reused 3+ times - u256(0), + if (_pushData) + assertThrow(_pushData->type() == PushData, OptimizerException, "Invalid Assembly Item."); - // back up memory - // mload(0) - Instruction::DUP1, - Instruction::MLOAD, + AssemblyItem dataUsed = _pushData ? *_pushData : AssemblyItem(PushData, u256(1) << 16); - // codecopy(0, , 32) - u256(32), - AssemblyItem(PushData, u256(1) << 16), // replaced above in actualCopyRoutine[4] - Instruction::DUP4, - Instruction::CODECOPY, + // PUSH0 is cheaper than PUSHn/DUP/SWAP. + if (m_params.evmVersion.hasPush0()) + { + // This costs ~29 gas. + AssemblyItems copyRoutine{ + // back up memory + // mload(0) + u256(0), + Instruction::MLOAD, + + // codecopy(0, , 32) + u256(32), + dataUsed, + u256(0), + Instruction::CODECOPY, + + // mload(0) + u256(0), + Instruction::MLOAD, + + // restore original memory + // mstore(0, x) + Instruction::SWAP1, + u256(0), + Instruction::MSTORE + }; + return copyRoutine; + } + else + { + // This costs ~33 gas. + AssemblyItems copyRoutine{ + // constant to be reused 3+ times + u256(0), + + // back up memory + // mload(0) + Instruction::DUP1, + Instruction::MLOAD, - // mload(0) - Instruction::DUP2, - Instruction::MLOAD, + // codecopy(0, , 32) + u256(32), + dataUsed, + Instruction::DUP4, + Instruction::CODECOPY, - // restore original memory - Instruction::SWAP2, - Instruction::MSTORE - }; - return copyRoutine; + // mload(0) + Instruction::DUP2, + Instruction::MLOAD, + + // restore original memory + // mstore(0, x) + Instruction::SWAP2, + Instruction::MSTORE + }; + return copyRoutine; + } } AssemblyItems ComputeMethod::findRepresentation(u256 const& _value) @@ -323,7 +360,7 @@ bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine) const return combineGas( simpleRunGas(_routine, m_params.evmVersion) + numExps * (GasCosts::expGas + GasCosts::expByteGas(m_params.evmVersion)), // Data gas for routine: Some bytes are zero, but we ignore them. - bytesRequired(_routine) * (m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas), + bytesRequired(_routine, m_params.evmVersion) * (m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas), 0 ); } diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index 139e263ba..7a929939e 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -79,7 +79,7 @@ class ConstantOptimisationMethod static bigint simpleRunGas(AssemblyItems const& _items, langutil::EVMVersion _evmVersion); /// @returns the gas needed to store the given data literally bigint dataGas(bytes const& _data) const; - static size_t bytesRequired(AssemblyItems const& _items); + static size_t bytesRequired(AssemblyItems const& _items, langutil::EVMVersion _evmVersion); /// @returns the combined estimated gas usage taking @a m_params into account. bigint combineGas( bigint const& _runGas, @@ -123,7 +123,7 @@ class CodeCopyMethod: public ConstantOptimisationMethod AssemblyItems execute(Assembly& _assembly) const override; protected: - static AssemblyItems const& copyRoutine(); + AssemblyItems copyRoutine(AssemblyItem* _pushData = nullptr) const; }; /** diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index b3d160585..a501b487f 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -44,12 +44,8 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _ switch (_item.type()) { case Push: - if (m_evmVersion.hasPush0() && _item.data() == 0) - { - gas = runGas(Instruction::PUSH0, m_evmVersion); - break; - } - [[fallthrough]]; + gas = pushGas(_item.data(), m_evmVersion); + break; case PushTag: case PushData: case PushSub: @@ -290,6 +286,14 @@ unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVer util::unreachable(); } +unsigned GasMeter::pushGas(u256 _value, langutil::EVMVersion _evmVersion) +{ + return runGas( + (_evmVersion.hasPush0() && _value == u256(0)) ? Instruction::PUSH0 : Instruction::PUSH1, + _evmVersion + ); +} + u256 GasMeter::dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersion _evmVersion) { bigint gas = 0; diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index c91e0f097..50a783e1a 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -225,6 +225,9 @@ class GasMeter /// change with EVM versions) static unsigned runGas(Instruction _instruction, langutil::EVMVersion _evmVersion); + /// @returns gas costs for push instructions (may change depending on EVM version) + static unsigned pushGas(u256 _value, langutil::EVMVersion _evmVersion); + /// @returns the gas cost of the supplied data, depending whether it is in creation code, or not. /// In case of @a _inCreation, the data is only sent as a transaction and is not stored, whereas /// otherwise code will be stored and have to pay "createDataGas" cost. diff --git a/libevmasm/Inliner.cpp b/libevmasm/Inliner.cpp index 67918e558..f3358128c 100644 --- a/libevmasm/Inliner.cpp +++ b/libevmasm/Inliner.cpp @@ -59,10 +59,10 @@ u256 executionCost(RangeType const& _itemRange, langutil::EVMVersion _evmVersion } /// @returns an estimation of the code size in bytes needed for the AssemblyItems in @a _itemRange. template -uint64_t codeSize(RangeType const& _itemRange) +uint64_t codeSize(RangeType const& _itemRange, langutil::EVMVersion _evmVersion) { return ranges::accumulate(_itemRange | ranges::views::transform( - [](auto const& _item) { return _item.bytesRequired(2, Precision::Approximate); } + [&](auto const& _item) { return _item.bytesRequired(2, _evmVersion, Precision::Approximate); } ), 0u); } /// @returns the tag id, if @a _item is a PushTag or Tag into the current subassembly, std::nullopt otherwise. @@ -139,7 +139,7 @@ std::map Inliner::determineInlinableBlocks(Asse bool Inliner::shouldInlineFullFunctionBody(size_t _tag, ranges::span _block, uint64_t _pushTagCount) const { // Accumulate size of the inline candidate block in bytes (without the return jump). - uint64_t functionBodySize = codeSize(ranges::views::drop_last(_block, 1)); + uint64_t functionBodySize = codeSize(ranges::views::drop_last(_block, 1), m_evmVersion); // Use the number of push tags as approximation of the average number of calls to the function per run. uint64_t numberOfCalls = _pushTagCount; @@ -167,8 +167,8 @@ bool Inliner::shouldInlineFullFunctionBody(size_t _tag, ranges::span Inliner::shouldInline(size_t _tag, AssemblyItem cons AssemblyItem{Instruction::JUMP}, }; if ( - GasMeter::dataGas(codeSize(_block.items), m_isCreation, m_evmVersion) <= - GasMeter::dataGas(codeSize(jumpPattern), m_isCreation, m_evmVersion) + GasMeter::dataGas(codeSize(_block.items, m_evmVersion), m_isCreation, m_evmVersion) <= + GasMeter::dataGas(codeSize(jumpPattern, m_evmVersion), m_isCreation, m_evmVersion) ) return blockExit; } diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 257a3727c..df33e04e5 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -38,6 +38,7 @@ struct OptimiserState AssemblyItems const& items; size_t i; std::back_insert_iterator out; + langutil::EVMVersion evmVersion = langutil::EVMVersion(); }; template @@ -199,16 +200,26 @@ struct DoubleSwap: SimplePeepholeOptimizerMethod struct DoublePush: SimplePeepholeOptimizerMethod { - static bool applySimple( - AssemblyItem const& _push1, - AssemblyItem const& _push2, - std::back_insert_iterator _out - ) + static bool apply(OptimiserState& _state) { - if (_push1.type() == Push && _push2.type() == Push && _push1.data() == _push2.data()) + size_t windowSize = 2; + if (_state.i + windowSize > _state.items.size()) + return false; + + auto push1 = _state.items.begin() + static_cast(_state.i); + auto push2 = _state.items.begin() + static_cast(_state.i + 1); + assertThrow(push1 != _state.items.end() && push2 != _state.items.end(), OptimizerException, ""); + + if ( + push1->type() == Push && + push2->type() == Push && + push1->data() == push2->data() && + (!_state.evmVersion.hasPush0() || push1->data() != 0) + ) { - *_out = _push1; - *_out = {Instruction::DUP1, _push2.debugData()}; + *_state.out = *push1; + *_state.out = {Instruction::DUP1, push2->debugData()}; + _state.i += windowSize; return true; } else @@ -510,7 +521,7 @@ bool PeepholeOptimiser::optimise() { // Avoid referencing immutables too early by using approx. counting in bytesRequired() auto const approx = evmasm::Precision::Approximate; - OptimiserState state {m_items, 0, back_inserter(m_optimisedItems)}; + OptimiserState state {m_items, 0, back_inserter(m_optimisedItems), m_evmVersion}; while (state.i < m_items.size()) applyMethods( state, @@ -520,7 +531,7 @@ bool PeepholeOptimiser::optimise() ); if (m_optimisedItems.size() < m_items.size() || ( m_optimisedItems.size() == m_items.size() && ( - evmasm::bytesRequired(m_optimisedItems, 3, approx) < evmasm::bytesRequired(m_items, 3, approx) || + evmasm::bytesRequired(m_optimisedItems, 3, m_evmVersion, approx) < evmasm::bytesRequired(m_items, 3, m_evmVersion, approx) || numberOfPops(m_optimisedItems) > numberOfPops(m_items) ) )) diff --git a/libevmasm/PeepholeOptimiser.h b/libevmasm/PeepholeOptimiser.h index 64ad5227f..8e3161b21 100644 --- a/libevmasm/PeepholeOptimiser.h +++ b/libevmasm/PeepholeOptimiser.h @@ -25,6 +25,8 @@ #include #include +#include + namespace solidity::evmasm { class AssemblyItem; @@ -41,7 +43,11 @@ class PeepholeOptimisationMethod class PeepholeOptimiser { public: - explicit PeepholeOptimiser(AssemblyItems& _items): m_items(_items) {} + explicit PeepholeOptimiser(AssemblyItems& _items, langutil::EVMVersion const _evmVersion): + m_items(_items), + m_evmVersion(_evmVersion) + { + } virtual ~PeepholeOptimiser() = default; bool optimise(); @@ -49,6 +55,7 @@ class PeepholeOptimiser private: AssemblyItems& m_items; AssemblyItems m_optimisedItems; + langutil::EVMVersion const m_evmVersion; }; } diff --git a/libyul/backends/evm/EVMMetrics.cpp b/libyul/backends/evm/EVMMetrics.cpp index 84ebdab1d..539279bf2 100644 --- a/libyul/backends/evm/EVMMetrics.cpp +++ b/libyul/backends/evm/EVMMetrics.cpp @@ -87,10 +87,11 @@ void GasMeterVisitor::operator()(FunctionCall const& _funCall) void GasMeterVisitor::operator()(Literal const& _lit) { - m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::PUSH1, m_dialect.evmVersion()); - m_dataGas += - singleByteDataGas() + - evmasm::GasMeter::dataGas( + m_runGas += evmasm::GasMeter::pushGas(_lit.value.value(), m_dialect.evmVersion()); + + m_dataGas += singleByteDataGas(); + if (!m_dialect.evmVersion().hasPush0() || _lit.value.value() != u256(0)) + m_dataGas += evmasm::GasMeter::dataGas( toCompactBigEndian(_lit.value.value(), 1), m_isCreation, m_dialect.evmVersion() diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index c781d7c1b..1a30842ae 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -771,7 +771,7 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi yulAssert(util::contains(m_currentFunctionInfo->returnVariables, std::get(_slot))); // Strictly speaking the cost of the PUSH0 depends on the targeted EVM version, but the difference // will not matter here. - opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(0), langutil::EVMVersion()); + opGas += evmasm::GasMeter::pushGas(u256(0), langutil::EVMVersion()); } } }; diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 04d41fffe..afc3c09fa 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1000,7 +1000,7 @@ BOOST_AUTO_TEST_CASE(clear_unreachable_code) AssemblyItem(PushTag, 1), Instruction::JUMP }; - PeepholeOptimiser peepOpt(items); + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); BOOST_REQUIRE(peepOpt.optimise()); BOOST_CHECK_EQUAL_COLLECTIONS( items.begin(), items.end(), @@ -1026,7 +1026,19 @@ BOOST_AUTO_TEST_CASE(peephole_double_push) u256(4), u256(5) }; - PeepholeOptimiser peepOpt(items); + + // `PUSH0 PUSH0` is cheaper than `DUP1 PUSH0` + if (solidity::test::CommonOptions::get().evmVersion() >= EVMVersion::shanghai()) + expectation = { + u256(0), + u256(0), + u256(5), + Instruction::DUP1, + u256(4), + u256(5) + }; + + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); BOOST_REQUIRE(peepOpt.optimise()); BOOST_CHECK_EQUAL_COLLECTIONS( items.begin(), items.end(), @@ -1042,7 +1054,7 @@ BOOST_AUTO_TEST_CASE(peephole_pop_calldatasize) Instruction::LT, Instruction::POP }; - PeepholeOptimiser peepOpt(items); + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); for (size_t i = 0; i < 3; i++) BOOST_CHECK(peepOpt.optimise()); BOOST_CHECK(items.empty()); @@ -1075,7 +1087,7 @@ BOOST_AUTO_TEST_CASE(peephole_commutative_swap1) u256(4), u256(5) }; - PeepholeOptimiser peepOpt(items); + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); BOOST_REQUIRE(peepOpt.optimise()); BOOST_CHECK_EQUAL_COLLECTIONS( items.begin(), items.end(), @@ -1113,7 +1125,7 @@ BOOST_AUTO_TEST_CASE(peephole_noncommutative_swap1) u256(4), u256(5) }; - PeepholeOptimiser peepOpt(items); + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); BOOST_REQUIRE(!peepOpt.optimise()); BOOST_CHECK_EQUAL_COLLECTIONS( items.begin(), items.end(), @@ -1148,7 +1160,7 @@ BOOST_AUTO_TEST_CASE(peephole_swap_comparison) u256(4), u256(5) }; - PeepholeOptimiser peepOpt(items); + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); BOOST_REQUIRE(peepOpt.optimise()); BOOST_CHECK_EQUAL_COLLECTIONS( items.begin(), items.end(), @@ -1174,7 +1186,7 @@ BOOST_AUTO_TEST_CASE(peephole_truthy_and) AssemblyItem(PushTag, 1), Instruction::JUMPI }; - PeepholeOptimiser peepOpt(items); + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); BOOST_REQUIRE(peepOpt.optimise()); BOOST_CHECK_EQUAL_COLLECTIONS( items.begin(), items.end(), @@ -1207,7 +1219,7 @@ BOOST_AUTO_TEST_CASE(peephole_iszero_iszero_jumpi) u256(0x20), Instruction::RETURN }; - PeepholeOptimiser peepOpt(items); + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); BOOST_REQUIRE(peepOpt.optimise()); BOOST_CHECK_EQUAL_COLLECTIONS( items.begin(), items.end(), @@ -1649,6 +1661,40 @@ BOOST_AUTO_TEST_CASE(cse_replace_too_large_shift) }); } +BOOST_AUTO_TEST_CASE(cse_dup) +{ + AssemblyItems input{ + u256(0), + Instruction::DUP1, + Instruction::REVERT + }; + AssemblyItems output = input; + + checkCSE(input, output); + checkFullCSE(input, output); +} + +BOOST_AUTO_TEST_CASE(cse_push0) +{ + AssemblyItems input{ + u256(0), + u256(0), + Instruction::REVERT + }; + AssemblyItems output{ + u256(0), + Instruction::DUP1, + Instruction::REVERT + }; + // The CSE has a rule to replace with DUP1 PUSH0 + checkCSE(input, output); + + // The full handling by the compiler (Assembly::optimiseInternal) + // will not choose to replace the pattern, because the new size is the same as the old one + output = input; + checkFullCSE(input, output); +} + BOOST_AUTO_TEST_CASE(inliner) { AssemblyItem jumpInto{Instruction::JUMP}; @@ -1873,9 +1919,10 @@ BOOST_AUTO_TEST_CASE(inliner_revert) ); } -BOOST_AUTO_TEST_CASE(inliner_revert_increased_datagas) +BOOST_AUTO_TEST_CASE(inliner_revert_push0) { - // Inlining this would increase data gas (5 bytes v/s 4 bytes), therefore, skipped. + // Inlining this without PUSH0 would increase data gas (5 bytes v/s 4 bytes), therefore, it would be skipped. + // However, with PUSH0 it is inlined (3 bytes vs 4 bytes). AssemblyItems items{ AssemblyItem(PushTag, 1), Instruction::JUMP, @@ -1884,8 +1931,16 @@ BOOST_AUTO_TEST_CASE(inliner_revert_increased_datagas) u256(0), Instruction::REVERT }; + AssemblyItems expectation{ + u256(0), + u256(0), + Instruction::REVERT, + AssemblyItem(Tag, 1), + u256(0), + u256(0), + Instruction::REVERT + }; - AssemblyItems expectation = items; Inliner{items, {}, Assembly::OptimiserSettings{}.expectedExecutionsPerDeployment, false, {}}.optimise(); BOOST_CHECK_EQUAL_COLLECTIONS( items.begin(), items.end(), diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index cdb6c5bd2..4cb0b3c93 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -383,22 +384,20 @@ BOOST_AUTO_TEST_CASE(basic_compilation) BOOST_CHECK(contract["evm"]["bytecode"]["object"].is_string()); BOOST_CHECK_EQUAL( solidity::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].get()), - std::string("6080604052348015600e575f80fd5b5060") + + std::string("6080604052348015600e575f5ffd5b5060") + (VersionIsRelease ? "3e" : util::toHex(bytes{uint8_t(60 + VersionStringStrict.size())})) + - "80601a5f395ff3fe60806040525f80fdfe" + "80601a5f395ff3fe60806040525f5ffdfe" ); BOOST_CHECK(contract["evm"]["assembly"].is_string()); BOOST_CHECK(contract["evm"]["assembly"].get().find( " /* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x80)\n " "callvalue\n dup1\n " "iszero\n tag_1\n jumpi\n " - "0x00\n " - "dup1\n revert\n" + "revert(0x00, 0x00)\n" "tag_1:\n pop\n dataSize(sub_0)\n dup1\n " "dataOffset(sub_0)\n 0x00\n codecopy\n 0x00\n return\nstop\n\nsub_0: assembly {\n " "/* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x80)\n " - "0x00\n " - "dup1\n revert\n\n auxdata: 0xa26469706673582212" + "revert(0x00, 0x00)\n\n auxdata: 0xa26469706673582212" ) == 0); BOOST_CHECK(contract["evm"]["gasEstimates"].is_object()); BOOST_CHECK_EQUAL(contract["evm"]["gasEstimates"].size(), 1); @@ -427,7 +426,7 @@ BOOST_AUTO_TEST_CASE(basic_compilation) "{\"begin\":0,\"end\":14,\"name\":\"PUSH [tag]\",\"source\":0,\"value\":\"1\"}," "{\"begin\":0,\"end\":14,\"name\":\"JUMPI\",\"source\":0}," "{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"source\":0,\"value\":\"0\"}," - "{\"begin\":0,\"end\":14,\"name\":\"DUP1\",\"source\":0}," + "{\"begin\":0,\"end\":14,\"name\":\"PUSH\",\"source\":0,\"value\":\"0\"}," "{\"begin\":0,\"end\":14,\"name\":\"REVERT\",\"source\":0}," "{\"begin\":0,\"end\":14,\"name\":\"tag\",\"source\":0,\"value\":\"1\"}," "{\"begin\":0,\"end\":14,\"name\":\"JUMPDEST\",\"source\":0}," From 6e7d94e886a14e195bc703293e72e2dffe00819b Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Sat, 30 Mar 2024 15:32:16 -0300 Subject: [PATCH 0236/1340] Add new Peephole Optimiser method (deduplicateNextTag) --- Changelog.md | 3 + libevmasm/PeepholeOptimiser.cpp | 99 ++++++++++++++++++++++++++++++- libevmasm/SemanticInformation.cpp | 7 +++ libevmasm/SemanticInformation.h | 1 + test/libevmasm/Optimiser.cpp | 75 +++++++++++++++++++++++ 5 files changed, 182 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index 8acee7422..632ec787e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,8 +9,11 @@ Language Features: Compiler Features: * Command Line Interface: Do not perform IR optimization when only unoptimized IR is requested. * Commandline Interface: Add ``--transient-storage-layout`` output. + * Constant Optimizer: Uses ``PUSH0`` if supported by the selected evm version. * Error Reporting: Unimplemented features are now properly reported as errors instead of being handled as if they were bugs. * EVM: Support for the EVM version "Prague". + * Peephole Optimizer: ``PUSH0``, when supported, is duplicated explicitly instead of using ``DUP1``. + * Peephole optimizer: Remove identical code snippets that terminate the control flow if they occur one after another. * SMTChecker: Add CHC engine check for underflow and overflow in unary minus operation. * SMTChecker: Replace CVC4 as a possible BMC backend with cvc5. * Standard JSON Interface: Do not perform IR optimization when only unoptimized IR is requested. diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index df33e04e5..40937e73f 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -198,7 +198,7 @@ struct DoubleSwap: SimplePeepholeOptimizerMethod } }; -struct DoublePush: SimplePeepholeOptimizerMethod +struct DoublePush { static bool apply(OptimiserState& _state) { @@ -498,6 +498,99 @@ struct UnreachableCode } }; +struct DeduplicateNextTagSize3 : SimplePeepholeOptimizerMethod +{ + static bool applySimple( + AssemblyItem const& _precedingItem, + AssemblyItem const& _itemA, + AssemblyItem const& _itemB, + AssemblyItem const& _breakingItem, + AssemblyItem const& _tag, + AssemblyItem const& _itemC, + AssemblyItem const& _itemD, + AssemblyItem const& _breakingItem2, + std::back_insert_iterator _out + ) + { + if ( + _precedingItem.type() != Tag && + _itemA == _itemC && + _itemB == _itemD && + _breakingItem == _breakingItem2 && + _tag.type() == Tag && + SemanticInformation::terminatesControlFlow(_breakingItem) + ) + { + *_out = _precedingItem; + *_out = _tag; + *_out = _itemC; + *_out = _itemD; + *_out = _breakingItem2; + return true; + } + + return false; + } +}; + +struct DeduplicateNextTagSize2 : SimplePeepholeOptimizerMethod +{ + static bool applySimple( + AssemblyItem const& _precedingItem, + AssemblyItem const& _itemA, + AssemblyItem const& _breakingItem, + AssemblyItem const& _tag, + AssemblyItem const& _itemC, + AssemblyItem const& _breakingItem2, + std::back_insert_iterator _out + ) + { + if ( + _precedingItem.type() != Tag && + _itemA == _itemC && + _breakingItem == _breakingItem2 && + _tag.type() == Tag && + SemanticInformation::terminatesControlFlow(_breakingItem) + ) + { + *_out = _precedingItem; + *_out = _tag; + *_out = _itemC; + *_out = _breakingItem2; + return true; + } + + return false; + } +}; + +struct DeduplicateNextTagSize1 : SimplePeepholeOptimizerMethod +{ + static bool applySimple( + AssemblyItem const& _precedingItem, + AssemblyItem const& _breakingItem, + AssemblyItem const& _tag, + AssemblyItem const& _breakingItem2, + std::back_insert_iterator _out + ) + { + if ( + _precedingItem.type() != Tag && + _breakingItem == _breakingItem2 && + _tag.type() == Tag && + SemanticInformation::terminatesControlFlow(_breakingItem) + ) + { + *_out = _precedingItem; + *_out = _tag; + *_out = _breakingItem2; + return true; + } + + return false; + } +}; + void applyMethods(OptimiserState&) { assertThrow(false, OptimizerException, "Peephole optimizer failed to apply identity."); @@ -526,8 +619,8 @@ bool PeepholeOptimiser::optimise() applyMethods( state, PushPop(), OpPop(), OpStop(), OpReturnRevert(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(), - DupSwap(), IsZeroIsZeroJumpI(), EqIsZeroJumpI(), DoubleJump(), JumpToNext(), UnreachableCode(), - TagConjunctions(), TruthyAnd(), Identity() + DupSwap(), IsZeroIsZeroJumpI(), EqIsZeroJumpI(), DoubleJump(), JumpToNext(), UnreachableCode(), DeduplicateNextTagSize3(), + DeduplicateNextTagSize2(), DeduplicateNextTagSize1(), TagConjunctions(), TruthyAnd(), Identity() ); if (m_optimisedItems.size() < m_items.size() || ( m_optimisedItems.size() == m_items.size() && ( diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index 978fb7ce2..87d41f6c1 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -299,6 +299,13 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) } } +bool SemanticInformation::terminatesControlFlow(AssemblyItem const& _item) +{ + if (_item.type() != evmasm::Operation) + return false; + return terminatesControlFlow(_item.instruction()); +} + bool SemanticInformation::terminatesControlFlow(Instruction _instruction) { switch (_instruction) diff --git a/libevmasm/SemanticInformation.h b/libevmasm/SemanticInformation.h index c3491cda8..b62832f23 100644 --- a/libevmasm/SemanticInformation.h +++ b/libevmasm/SemanticInformation.h @@ -84,6 +84,7 @@ struct SemanticInformation static bool isSwapInstruction(AssemblyItem const& _item); static bool isJumpInstruction(AssemblyItem const& _item); static bool altersControlFlow(AssemblyItem const& _item); + static bool terminatesControlFlow(AssemblyItem const& _item); static bool terminatesControlFlow(Instruction _instruction); static bool reverts(Instruction _instruction); /// @returns false if the value put on the stack by _item depends on anything else than diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index afc3c09fa..13fa58bf4 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1008,6 +1008,81 @@ BOOST_AUTO_TEST_CASE(clear_unreachable_code) ); } +BOOST_AUTO_TEST_CASE(deduplicateNextTagBlockSize3) +{ + AssemblyItems items{ + Instruction::JUMP, + u256(0), + u256(1), + Instruction::REVERT, + AssemblyItem(Tag, 2), + u256(0), + u256(1), + Instruction::REVERT + }; + + AssemblyItems expectation{ + Instruction::JUMP, + AssemblyItem(Tag, 2), + u256(0), + u256(1), + Instruction::REVERT + }; + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + +BOOST_AUTO_TEST_CASE(deduplicateNextTagBlockSize2) +{ + AssemblyItems items{ + Instruction::JUMP, + u256(0), + Instruction::SELFDESTRUCT, + AssemblyItem(Tag, 2), + u256(0), + Instruction::SELFDESTRUCT + }; + + AssemblyItems expectation{ + Instruction::JUMP, + AssemblyItem(Tag, 2), + u256(0), + Instruction::SELFDESTRUCT + }; + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + +BOOST_AUTO_TEST_CASE(deduplicateNextTagBlockSize1) +{ + AssemblyItems items{ + Instruction::JUMP, + Instruction::STOP, + AssemblyItem(Tag, 2), + Instruction::STOP + }; + + AssemblyItems expectation{ + Instruction::JUMP, + AssemblyItem(Tag, 2), + Instruction::STOP + }; + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + BOOST_AUTO_TEST_CASE(peephole_double_push) { AssemblyItems items{ From 7e67811a82d55bb280f5a21e9b623e4c3d99fbca Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Sat, 30 Mar 2024 17:34:55 -0300 Subject: [PATCH 0237/1340] Update tests --- test/cmdlineTests/asm_json/output | 30 +++++++++++-------- .../asm_json_no_pretty_print/output | 2 +- .../output | 12 ++------ .../output | 12 ++------ .../output | 12 ++------ test/cmdlineTests/dup_opt_peephole/output | 8 ++--- .../optimize_full_storage_write/output | 12 ++------ .../optimizer_BlockDeDuplicator/output | 12 ++------ .../cmdlineTests/optimizer_inliner_add/output | 12 ++------ .../output | 12 ++------ .../output | 12 ++------ .../output | 12 ++------ .../cmdlineTests/optimizer_inliner_inc/output | 12 ++------ .../optimizer_inliner_multireturn/output | 12 ++------ test/cmdlineTests/optimizer_user_yul/output | 8 ++--- .../output.json | 12 ++------ .../output.json | 12 ++------ .../output.json | 12 ++------ .../output | 5 ++-- .../strict_asm_msize_without_optimizer/output | 4 +-- .../viair_msize_without_optimizer/output | 21 ++++--------- .../abiEncoderV1/abi_decode_v2_storage.sol | 2 +- .../abi_encode_calldata_slice.sol | 8 ++--- .../struct/struct_storage_ptr.sol | 6 ++-- .../abi_encode_calldata_slice.sol | 8 ++--- .../abiEncoderV2/abi_encode_v2.sol | 2 +- ...ode_v2_in_modifier_used_in_v1_contract.sol | 2 +- .../calldata_overlapped_dynamic_arrays.sol | 6 ++-- .../abiEncoderV2/storage_array_encoding.sol | 6 ++-- .../abi_decode_simple_storage.sol | 6 ++-- .../array/array_memory_index_access.sol | 4 +-- .../array/array_storage_index_access.sol | 18 +++++------ .../array_storage_index_boundary_test.sol | 8 ++--- .../array/array_storage_index_zeroed_test.sol | 16 +++++----- .../array/array_storage_push_empty.sol | 4 +-- .../array/array_storage_push_pop.sol | 4 +-- .../arrays_complex_from_and_to_storage.sol | 2 +- .../array/byte_array_storage_layout.sol | 4 +-- .../array/byte_array_transitional_2.sol | 4 +-- .../array/bytes_length_member.sol | 4 +-- .../copying/array_copy_calldata_storage.sol | 4 +-- .../copying/array_copy_cleanup_uint40.sol | 4 +-- .../copying/array_copy_clear_storage.sol | 4 +-- .../copying/array_copy_different_packing.sol | 6 ++-- .../copying/array_copy_including_array.sol | 10 +++---- .../array/copying/array_copy_nested_array.sol | 6 ++-- ...ay_copy_storage_storage_different_base.sol | 2 +- ..._storage_storage_different_base_nested.sol | 4 +-- .../array_copy_storage_storage_dyn_dyn.sol | 2 +- ...y_copy_storage_storage_dynamic_dynamic.sol | 2 +- ...ay_copy_storage_storage_static_dynamic.sol | 2 +- ...ray_copy_storage_storage_static_static.sol | 2 +- .../array_copy_storage_storage_struct.sol | 4 +-- .../array_copy_storage_to_memory_nested.sol | 2 +- .../copying/array_copy_target_leftover.sol | 6 ++-- .../copying/array_copy_target_simple.sol | 4 +-- .../copying/array_copy_target_simple_2.sol | 4 +-- .../copying/array_elements_to_mapping.sol | 6 ++-- .../array_nested_calldata_to_storage.sol | 4 +-- .../array_nested_memory_to_storage.sol | 6 ++-- ...ts_containing_arrays_memory_to_storage.sol | 2 +- .../array_storage_multi_items_per_slot.sol | 2 +- .../array/copying/array_to_mapping.sol | 6 ++-- .../array/copying/bytes_inside_mappings.sol | 4 +-- .../copying/bytes_storage_to_storage.sol | 20 ++++++------- .../calldata_array_dynamic_to_storage.sol | 6 ++-- .../copy_byte_array_in_struct_to_storage.sol | 6 ++-- .../copying/copy_byte_array_to_storage.sol | 6 ++-- .../copy_function_internal_storage_array.sol | 2 +- .../array/copying/copy_removes_bytes_data.sol | 2 +- .../copying/copying_bytes_multiassign.sol | 2 +- .../function_type_array_to_storage.sol | 8 ++--- .../memory_dyn_2d_bytes_to_storage.sol | 2 +- ...ested_array_element_storage_to_storage.sol | 4 +-- ...d_array_of_structs_calldata_to_storage.sol | 4 +-- ...ted_array_of_structs_memory_to_storage.sol | 4 +-- ...amic_array_element_calldata_to_storage.sol | 2 +- .../array/copying/storage_memory_nested.sol | 4 +-- .../copying/storage_memory_nested_bytes.sol | 4 +-- .../storage_memory_nested_from_pointer.sol | 2 +- .../copying/storage_memory_nested_struct.sol | 2 +- .../copying/storage_memory_packed_dyn.sol | 4 +-- .../array/create_memory_array.sol | 2 +- .../array/delete/bytes_delete_element.sol | 4 +-- .../array/dynamic_array_cleanup.sol | 2 +- .../array/dynamic_arrays_in_storage.sol | 4 +-- .../array/fixed_array_cleanup.sol | 2 +- .../array/fixed_arrays_in_constructors.sol | 4 +-- .../array/function_array_cross_calls.sol | 4 +-- ...nvalid_encoding_for_storage_byte_array.sol | 2 +- .../array/pop/array_pop_array_transition.sol | 2 +- .../array/pop/array_pop_uint16_transition.sol | 2 +- .../array/pop/array_pop_uint24_transition.sol | 2 +- .../pop/byte_array_pop_long_storage_empty.sol | 4 +-- ...ray_pop_long_storage_empty_garbage_ref.sol | 4 +-- .../array/pop/byte_array_pop_masking_long.sol | 4 +-- .../semanticTests/array/push/array_push.sol | 2 +- .../push/array_push_nested_from_calldata.sol | 6 ++-- .../array/push/array_push_struct.sol | 4 +-- .../push/array_push_struct_from_calldata.sol | 4 +-- .../array/push/byte_array_push_transition.sol | 2 +- .../array/push/nested_bytes_push.sol | 4 +-- .../array/push/push_no_args_2d.sol | 6 ++-- .../array/push/push_no_args_bytes.sol | 2 +- .../semanticTests/array/reusing_memory.sol | 2 +- .../byte_array_to_storage_cleanup.sol | 4 +-- .../copy_from_calldata_removes_bytes_data.sol | 2 +- .../constructor/arrays_in_constructors.sol | 4 +-- .../bytes_in_constructors_packer.sol | 4 +-- .../bytes_in_constructors_unpacker.sol | 4 +-- .../constructor_arguments_external.sol | 4 +-- .../constructor_function_complex.sol | 2 +- .../constructor_static_array_argument.sol | 4 +-- .../constructor_inheritance_init_order_2.sol | 2 +- .../semanticTests/constructor_with_params.sol | 2 +- ...ructor_with_params_diamond_inheritance.sol | 4 +-- .../constructor_with_params_inheritance.sol | 4 +-- .../errors/small_error_optimization.sol | 6 ++-- .../events/event_dynamic_array_storage.sol | 4 +-- .../events/event_dynamic_array_storage_v2.sol | 4 +-- .../event_dynamic_nested_array_storage_v2.sol | 4 +-- .../events/event_emit_from_other_contract.sol | 4 +-- .../events/event_indexed_string.sol | 6 ++-- .../externalContracts/base64.sol | 8 ++--- .../externalContracts/deposit_contract.sol | 14 ++++----- .../externalContracts/prbmath_signed.sol | 4 +-- .../externalContracts/prbmath_unsigned.sol | 4 +-- .../externalContracts/ramanujan_pi.sol | 6 ++-- .../semanticTests/externalContracts/snark.sol | 12 ++++---- .../externalContracts/strings.sol | 8 ++--- .../creation_function_call_with_args.sol | 2 +- .../creation_function_call_with_salt.sol | 2 +- .../external_call_to_nonexisting.sol | 8 ++--- ...ernal_call_to_nonexisting_debugstrings.sol | 8 ++--- .../functionCall/failed_create.sol | 4 +-- .../functionCall/gas_and_value_basic.sol | 4 +-- .../gas_and_value_brace_syntax.sol | 4 +-- .../mapping_array_internal_argument.sol | 4 +-- .../functionTypes/store_function.sol | 4 +-- .../immutable/multi_creation.sol | 4 +-- .../semanticTests/immutable/use_scratch.sol | 2 +- ...d_function_calldata_calldata_interface.sol | 2 +- ...ted_function_calldata_memory_interface.sol | 4 +-- .../inheritance/member_notation_ctor.sol | 4 +-- .../inheritance/value_for_constructor.sol | 6 ++-- .../transient_storage_selfdestruct.sol | 12 ++++---- .../tstore_hidden_staticcall.sol | 4 +-- .../balance_other_contract.sol | 2 +- .../libraries/internal_types_in_library.sol | 4 +-- .../using_library_mappings_public.sol | 4 +-- .../using_library_mappings_return.sol | 4 +-- .../libraries/using_library_structs.sol | 2 +- .../operator_making_pure_external_call.sol | 6 ++-- .../operator_making_view_external_call.sol | 6 ++-- .../salted_create/prediction_example.sol | 2 +- .../salted_create_with_value.sol | 4 +-- .../semanticTests/smoke/constructor.sol | 4 +-- .../storage/empty_nonempty_empty.sol | 2 +- .../storage/packed_storage_structs_bytes.sol | 2 +- ...ta_struct_with_nested_array_to_storage.sol | 4 +-- .../conversion/recursive_storage_memory.sol | 4 +-- .../structs/copy_from_mapping.sol | 2 +- .../copy_struct_array_from_storage.sol | 4 +-- .../copy_substructures_from_mapping.sol | 2 +- .../structs/copy_substructures_to_mapping.sol | 12 ++++---- .../semanticTests/structs/copy_to_mapping.sol | 12 ++++---- .../structs/memory_structs_nested_load.sol | 2 +- ...truct_containing_bytes_copy_and_delete.sol | 12 ++++---- .../semanticTests/structs/struct_copy.sol | 6 ++-- .../struct_delete_storage_with_array.sol | 8 ++--- .../struct_memory_to_storage_function_ptr.sol | 2 +- .../semanticTests/structs/structs.sol | 2 +- .../mapping/copy_from_mapping_to_mapping.sol | 2 +- .../userDefinedValueType/calldata.sol | 10 +++---- .../userDefinedValueType/erc20.sol | 2 +- .../using/using_global_invisible.sol | 2 +- .../semanticTests/various/address_code.sol | 2 +- .../various/code_access_content.sol | 4 +-- .../various/code_access_create.sol | 2 +- .../various/code_access_runtime.sol | 2 +- .../semanticTests/various/code_length.sol | 4 +-- .../semanticTests/various/create_calldata.sol | 2 +- .../various/destructuring_assignment.sol | 4 +-- .../semanticTests/various/erc20.sol | 2 +- .../various/external_types_in_calls.sol | 2 +- .../various/selfdestruct_post_cancun.sol | 4 +-- ...uct_post_cancun_multiple_beneficiaries.sol | 6 ++-- .../selfdestruct_post_cancun_redeploy.sol | 10 +++---- .../semanticTests/various/senders_balance.sol | 2 +- .../skip_dynamic_types_for_structs.sol | 4 +-- .../various/staticcall_for_view_and_pure.sol | 8 ++--- .../various/swap_in_storage_overwrite.sol | 2 +- .../semanticTests/various/value_complex.sol | 4 +-- .../semanticTests/various/value_insane.sol | 2 +- .../viaYul/copy_struct_invalid_ir_bug.sol | 4 +-- test/libyul/objectCompiler/datacopy.yul | 6 ++-- .../libyul/objectCompiler/dataoffset_self.yul | 6 ++-- .../libyul/objectCompiler/sourceLocations.yul | 8 ++--- 198 files changed, 472 insertions(+), 566 deletions(-) diff --git a/test/cmdlineTests/asm_json/output b/test/cmdlineTests/asm_json/output index 38d9c9fdf..820eda6ec 100644 --- a/test/cmdlineTests/asm_json/output +++ b/test/cmdlineTests/asm_json/output @@ -64,8 +64,9 @@ EVM assembly: { "begin": 60, "end": 160, - "name": "DUP1", - "source": 0 + "name": "PUSH", + "source": 0, + "value": "0" }, { "begin": 60, @@ -204,8 +205,9 @@ EVM assembly: { "begin": 60, "end": 160, - "name": "DUP1", - "source": 0 + "name": "PUSH", + "source": 0, + "value": "0" }, { "begin": 60, @@ -345,8 +347,9 @@ EVM assembly: { "begin": 60, "end": 160, - "name": "DUP1", - "source": 0 + "name": "PUSH", + "source": 0, + "value": "0" }, { "begin": 60, @@ -622,8 +625,9 @@ EVM assembly: { "begin": 135, "end": 151, - "name": "DUP1", - "source": 0 + "name": "PUSH", + "source": 0, + "value": "0" }, { "begin": 135, @@ -680,8 +684,9 @@ EVM assembly: { "begin": 194, "end": 195, - "name": "DUP1", - "source": 1 + "name": "PUSH", + "source": 1, + "value": "0" }, { "begin": 187, @@ -840,8 +845,9 @@ EVM assembly: { "begin": 526, "end": 527, - "name": "DUP1", - "source": 1 + "name": "PUSH", + "source": 1, + "value": "0" }, { "begin": 519, diff --git a/test/cmdlineTests/asm_json_no_pretty_print/output b/test/cmdlineTests/asm_json_no_pretty_print/output index b713097bb..8fce2f482 100644 --- a/test/cmdlineTests/asm_json_no_pretty_print/output +++ b/test/cmdlineTests/asm_json_no_pretty_print/output @@ -1,4 +1,4 @@ ======= asm_json_no_pretty_print/input.sol:C ======= EVM assembly: -{".code":[{"begin":60,"end":160,"name":"PUSH","source":0,"value":"80"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"40"},{"begin":60,"end":160,"name":"MSTORE","source":0},{"begin":60,"end":160,"name":"CALLVALUE","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"ISZERO","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"POP","source":0},{"begin":60,"end":160,"name":"PUSH #[$]","source":0,"value":"0000000000000000000000000000000000000000000000000000000000000000"},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"PUSH [$]","source":0,"value":"0000000000000000000000000000000000000000000000000000000000000000"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"CODECOPY","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"RETURN","source":0}],".data":{"0":{".auxdata":"",".code":[{"begin":60,"end":160,"name":"PUSH","source":0,"value":"80"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"40"},{"begin":60,"end":160,"name":"MSTORE","source":0},{"begin":60,"end":160,"name":"CALLVALUE","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"ISZERO","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"POP","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"4"},{"begin":60,"end":160,"name":"CALLDATASIZE","source":0},{"begin":60,"end":160,"name":"LT","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"2"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"CALLDATALOAD","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"E0"},{"begin":60,"end":160,"name":"SHR","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"B3DE648B"},{"begin":60,"end":160,"name":"EQ","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"3"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"2"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"3"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"4"},{"begin":77,"end":158,"name":"PUSH","source":0,"value":"4"},{"begin":77,"end":158,"name":"DUP1","source":0},{"begin":77,"end":158,"name":"CALLDATASIZE","source":0},{"begin":77,"end":158,"name":"SUB","source":0},{"begin":77,"end":158,"name":"DUP2","source":0},{"begin":77,"end":158,"name":"ADD","source":0},{"begin":77,"end":158,"name":"SWAP1","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"5"},{"begin":77,"end":158,"name":"SWAP2","source":0},{"begin":77,"end":158,"name":"SWAP1","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"6"},{"begin":77,"end":158,"jumpType":"[in]","name":"JUMP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"5"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"7"},{"begin":77,"end":158,"jumpType":"[in]","name":"JUMP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"4"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"STOP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"7"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":123,"end":125,"name":"PUSH","source":0,"value":"2A"},{"begin":118,"end":125,"name":"DUP2","source":0},{"begin":118,"end":125,"name":"PUSH [tag]","source":0,"value":"9"},{"begin":118,"end":125,"name":"SWAP2","source":0},{"begin":118,"end":125,"name":"SWAP1","source":0},{"begin":118,"end":125,"name":"PUSH [tag]","source":0,"value":"10"},{"begin":118,"end":125,"jumpType":"[in]","name":"JUMP","source":0},{"begin":118,"end":125,"name":"tag","source":0,"value":"9"},{"begin":118,"end":125,"name":"JUMPDEST","source":0},{"begin":118,"end":125,"name":"SWAP1","source":0},{"begin":118,"end":125,"name":"POP","source":0},{"begin":147,"end":150,"name":"PUSH","source":0,"value":"64"},{"begin":143,"end":144,"name":"DUP2","source":0},{"begin":143,"end":150,"name":"GT","source":0},{"begin":135,"end":151,"name":"PUSH [tag]","source":0,"value":"11"},{"begin":135,"end":151,"name":"JUMPI","source":0},{"begin":135,"end":151,"name":"PUSH","source":0,"value":"0"},{"begin":135,"end":151,"name":"DUP1","source":0},{"begin":135,"end":151,"name":"REVERT","source":0},{"begin":135,"end":151,"name":"tag","source":0,"value":"11"},{"begin":135,"end":151,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"POP","source":0},{"begin":77,"end":158,"jumpType":"[out]","name":"JUMP","source":0},{"begin":88,"end":205,"name":"tag","source":1,"value":"13"},{"begin":88,"end":205,"name":"JUMPDEST","source":1},{"begin":197,"end":198,"name":"PUSH","source":1,"value":"0"},{"begin":194,"end":195,"name":"DUP1","source":1},{"begin":187,"end":199,"name":"REVERT","source":1},{"begin":334,"end":411,"name":"tag","source":1,"value":"15"},{"begin":334,"end":411,"name":"JUMPDEST","source":1},{"begin":371,"end":378,"name":"PUSH","source":1,"value":"0"},{"begin":400,"end":405,"name":"DUP2","source":1},{"begin":389,"end":405,"name":"SWAP1","source":1},{"begin":389,"end":405,"name":"POP","source":1},{"begin":334,"end":411,"name":"SWAP2","source":1},{"begin":334,"end":411,"name":"SWAP1","source":1},{"begin":334,"end":411,"name":"POP","source":1},{"begin":334,"end":411,"jumpType":"[out]","name":"JUMP","source":1},{"begin":417,"end":539,"name":"tag","source":1,"value":"16"},{"begin":417,"end":539,"name":"JUMPDEST","source":1},{"begin":490,"end":514,"name":"PUSH [tag]","source":1,"value":"25"},{"begin":508,"end":513,"name":"DUP2","source":1},{"begin":490,"end":514,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":490,"end":514,"jumpType":"[in]","name":"JUMP","source":1},{"begin":490,"end":514,"name":"tag","source":1,"value":"25"},{"begin":490,"end":514,"name":"JUMPDEST","source":1},{"begin":483,"end":488,"name":"DUP2","source":1},{"begin":480,"end":515,"name":"EQ","source":1},{"begin":470,"end":533,"name":"PUSH [tag]","source":1,"value":"26"},{"begin":470,"end":533,"name":"JUMPI","source":1},{"begin":529,"end":530,"name":"PUSH","source":1,"value":"0"},{"begin":526,"end":527,"name":"DUP1","source":1},{"begin":519,"end":531,"name":"REVERT","source":1},{"begin":470,"end":533,"name":"tag","source":1,"value":"26"},{"begin":470,"end":533,"name":"JUMPDEST","source":1},{"begin":417,"end":539,"name":"POP","source":1},{"begin":417,"end":539,"jumpType":"[out]","name":"JUMP","source":1},{"begin":545,"end":684,"name":"tag","source":1,"value":"17"},{"begin":545,"end":684,"name":"JUMPDEST","source":1},{"begin":591,"end":596,"name":"PUSH","source":1,"value":"0"},{"begin":629,"end":635,"name":"DUP2","source":1},{"begin":616,"end":636,"name":"CALLDATALOAD","source":1},{"begin":607,"end":636,"name":"SWAP1","source":1},{"begin":607,"end":636,"name":"POP","source":1},{"begin":645,"end":678,"name":"PUSH [tag]","source":1,"value":"28"},{"begin":672,"end":677,"name":"DUP2","source":1},{"begin":645,"end":678,"name":"PUSH [tag]","source":1,"value":"16"},{"begin":645,"end":678,"jumpType":"[in]","name":"JUMP","source":1},{"begin":645,"end":678,"name":"tag","source":1,"value":"28"},{"begin":645,"end":678,"name":"JUMPDEST","source":1},{"begin":545,"end":684,"name":"SWAP3","source":1},{"begin":545,"end":684,"name":"SWAP2","source":1},{"begin":545,"end":684,"name":"POP","source":1},{"begin":545,"end":684,"name":"POP","source":1},{"begin":545,"end":684,"jumpType":"[out]","name":"JUMP","source":1},{"begin":690,"end":1019,"name":"tag","source":1,"value":"6"},{"begin":690,"end":1019,"name":"JUMPDEST","source":1},{"begin":749,"end":755,"name":"PUSH","source":1,"value":"0"},{"begin":798,"end":800,"name":"PUSH","source":1,"value":"20"},{"begin":786,"end":795,"name":"DUP3","source":1},{"begin":777,"end":784,"name":"DUP5","source":1},{"begin":773,"end":796,"name":"SUB","source":1},{"begin":769,"end":801,"name":"SLT","source":1},{"begin":766,"end":885,"name":"ISZERO","source":1},{"begin":766,"end":885,"name":"PUSH [tag]","source":1,"value":"30"},{"begin":766,"end":885,"name":"JUMPI","source":1},{"begin":804,"end":883,"name":"PUSH [tag]","source":1,"value":"31"},{"begin":804,"end":883,"name":"PUSH [tag]","source":1,"value":"13"},{"begin":804,"end":883,"jumpType":"[in]","name":"JUMP","source":1},{"begin":804,"end":883,"name":"tag","source":1,"value":"31"},{"begin":804,"end":883,"name":"JUMPDEST","source":1},{"begin":766,"end":885,"name":"tag","source":1,"value":"30"},{"begin":766,"end":885,"name":"JUMPDEST","source":1},{"begin":924,"end":925,"name":"PUSH","source":1,"value":"0"},{"begin":949,"end":1002,"name":"PUSH [tag]","source":1,"value":"32"},{"begin":994,"end":1001,"name":"DUP5","source":1},{"begin":985,"end":991,"name":"DUP3","source":1},{"begin":974,"end":983,"name":"DUP6","source":1},{"begin":970,"end":992,"name":"ADD","source":1},{"begin":949,"end":1002,"name":"PUSH [tag]","source":1,"value":"17"},{"begin":949,"end":1002,"jumpType":"[in]","name":"JUMP","source":1},{"begin":949,"end":1002,"name":"tag","source":1,"value":"32"},{"begin":949,"end":1002,"name":"JUMPDEST","source":1},{"begin":939,"end":1002,"name":"SWAP2","source":1},{"begin":939,"end":1002,"name":"POP","source":1},{"begin":895,"end":1012,"name":"POP","source":1},{"begin":690,"end":1019,"name":"SWAP3","source":1},{"begin":690,"end":1019,"name":"SWAP2","source":1},{"begin":690,"end":1019,"name":"POP","source":1},{"begin":690,"end":1019,"name":"POP","source":1},{"begin":690,"end":1019,"jumpType":"[out]","name":"JUMP","source":1},{"begin":1025,"end":1205,"name":"tag","source":1,"value":"18"},{"begin":1025,"end":1205,"name":"JUMPDEST","source":1},{"begin":1073,"end":1150,"name":"PUSH","source":1,"value":"4E487B7100000000000000000000000000000000000000000000000000000000"},{"begin":1070,"end":1071,"name":"PUSH","source":1,"value":"0"},{"begin":1063,"end":1151,"name":"MSTORE","source":1},{"begin":1170,"end":1174,"name":"PUSH","source":1,"value":"11"},{"begin":1167,"end":1168,"name":"PUSH","source":1,"value":"4"},{"begin":1160,"end":1175,"name":"MSTORE","source":1},{"begin":1194,"end":1198,"name":"PUSH","source":1,"value":"24"},{"begin":1191,"end":1192,"name":"PUSH","source":1,"value":"0"},{"begin":1184,"end":1199,"name":"REVERT","source":1},{"begin":1211,"end":1402,"name":"tag","source":1,"value":"10"},{"begin":1211,"end":1402,"name":"JUMPDEST","source":1},{"begin":1251,"end":1254,"name":"PUSH","source":1,"value":"0"},{"begin":1270,"end":1290,"name":"PUSH [tag]","source":1,"value":"35"},{"begin":1288,"end":1289,"name":"DUP3","source":1},{"begin":1270,"end":1290,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":1270,"end":1290,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1270,"end":1290,"name":"tag","source":1,"value":"35"},{"begin":1270,"end":1290,"name":"JUMPDEST","source":1},{"begin":1265,"end":1290,"name":"SWAP2","source":1},{"begin":1265,"end":1290,"name":"POP","source":1},{"begin":1304,"end":1324,"name":"PUSH [tag]","source":1,"value":"36"},{"begin":1322,"end":1323,"name":"DUP4","source":1},{"begin":1304,"end":1324,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":1304,"end":1324,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1304,"end":1324,"name":"tag","source":1,"value":"36"},{"begin":1304,"end":1324,"name":"JUMPDEST","source":1},{"begin":1299,"end":1324,"name":"SWAP3","source":1},{"begin":1299,"end":1324,"name":"POP","source":1},{"begin":1347,"end":1348,"name":"DUP3","source":1},{"begin":1344,"end":1345,"name":"DUP3","source":1},{"begin":1340,"end":1349,"name":"ADD","source":1},{"begin":1333,"end":1349,"name":"SWAP1","source":1},{"begin":1333,"end":1349,"name":"POP","source":1},{"begin":1368,"end":1371,"name":"DUP1","source":1},{"begin":1365,"end":1366,"name":"DUP3","source":1},{"begin":1362,"end":1372,"name":"GT","source":1},{"begin":1359,"end":1395,"name":"ISZERO","source":1},{"begin":1359,"end":1395,"name":"PUSH [tag]","source":1,"value":"37"},{"begin":1359,"end":1395,"name":"JUMPI","source":1},{"begin":1375,"end":1393,"name":"PUSH [tag]","source":1,"value":"38"},{"begin":1375,"end":1393,"name":"PUSH [tag]","source":1,"value":"18"},{"begin":1375,"end":1393,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1375,"end":1393,"name":"tag","source":1,"value":"38"},{"begin":1375,"end":1393,"name":"JUMPDEST","source":1},{"begin":1359,"end":1395,"name":"tag","source":1,"value":"37"},{"begin":1359,"end":1395,"name":"JUMPDEST","source":1},{"begin":1211,"end":1402,"name":"SWAP3","source":1},{"begin":1211,"end":1402,"name":"SWAP2","source":1},{"begin":1211,"end":1402,"name":"POP","source":1},{"begin":1211,"end":1402,"name":"POP","source":1},{"begin":1211,"end":1402,"jumpType":"[out]","name":"JUMP","source":1}]}},"sourceList":["asm_json_no_pretty_print/input.sol","#utility.yul"]} +{".code":[{"begin":60,"end":160,"name":"PUSH","source":0,"value":"80"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"40"},{"begin":60,"end":160,"name":"MSTORE","source":0},{"begin":60,"end":160,"name":"CALLVALUE","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"ISZERO","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"POP","source":0},{"begin":60,"end":160,"name":"PUSH #[$]","source":0,"value":"0000000000000000000000000000000000000000000000000000000000000000"},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"PUSH [$]","source":0,"value":"0000000000000000000000000000000000000000000000000000000000000000"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"CODECOPY","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"RETURN","source":0}],".data":{"0":{".auxdata":"",".code":[{"begin":60,"end":160,"name":"PUSH","source":0,"value":"80"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"40"},{"begin":60,"end":160,"name":"MSTORE","source":0},{"begin":60,"end":160,"name":"CALLVALUE","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"ISZERO","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"POP","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"4"},{"begin":60,"end":160,"name":"CALLDATASIZE","source":0},{"begin":60,"end":160,"name":"LT","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"2"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"CALLDATALOAD","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"E0"},{"begin":60,"end":160,"name":"SHR","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"B3DE648B"},{"begin":60,"end":160,"name":"EQ","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"3"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"2"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"3"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"4"},{"begin":77,"end":158,"name":"PUSH","source":0,"value":"4"},{"begin":77,"end":158,"name":"DUP1","source":0},{"begin":77,"end":158,"name":"CALLDATASIZE","source":0},{"begin":77,"end":158,"name":"SUB","source":0},{"begin":77,"end":158,"name":"DUP2","source":0},{"begin":77,"end":158,"name":"ADD","source":0},{"begin":77,"end":158,"name":"SWAP1","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"5"},{"begin":77,"end":158,"name":"SWAP2","source":0},{"begin":77,"end":158,"name":"SWAP1","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"6"},{"begin":77,"end":158,"jumpType":"[in]","name":"JUMP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"5"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"7"},{"begin":77,"end":158,"jumpType":"[in]","name":"JUMP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"4"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"STOP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"7"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":123,"end":125,"name":"PUSH","source":0,"value":"2A"},{"begin":118,"end":125,"name":"DUP2","source":0},{"begin":118,"end":125,"name":"PUSH [tag]","source":0,"value":"9"},{"begin":118,"end":125,"name":"SWAP2","source":0},{"begin":118,"end":125,"name":"SWAP1","source":0},{"begin":118,"end":125,"name":"PUSH [tag]","source":0,"value":"10"},{"begin":118,"end":125,"jumpType":"[in]","name":"JUMP","source":0},{"begin":118,"end":125,"name":"tag","source":0,"value":"9"},{"begin":118,"end":125,"name":"JUMPDEST","source":0},{"begin":118,"end":125,"name":"SWAP1","source":0},{"begin":118,"end":125,"name":"POP","source":0},{"begin":147,"end":150,"name":"PUSH","source":0,"value":"64"},{"begin":143,"end":144,"name":"DUP2","source":0},{"begin":143,"end":150,"name":"GT","source":0},{"begin":135,"end":151,"name":"PUSH [tag]","source":0,"value":"11"},{"begin":135,"end":151,"name":"JUMPI","source":0},{"begin":135,"end":151,"name":"PUSH","source":0,"value":"0"},{"begin":135,"end":151,"name":"PUSH","source":0,"value":"0"},{"begin":135,"end":151,"name":"REVERT","source":0},{"begin":135,"end":151,"name":"tag","source":0,"value":"11"},{"begin":135,"end":151,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"POP","source":0},{"begin":77,"end":158,"jumpType":"[out]","name":"JUMP","source":0},{"begin":88,"end":205,"name":"tag","source":1,"value":"13"},{"begin":88,"end":205,"name":"JUMPDEST","source":1},{"begin":197,"end":198,"name":"PUSH","source":1,"value":"0"},{"begin":194,"end":195,"name":"PUSH","source":1,"value":"0"},{"begin":187,"end":199,"name":"REVERT","source":1},{"begin":334,"end":411,"name":"tag","source":1,"value":"15"},{"begin":334,"end":411,"name":"JUMPDEST","source":1},{"begin":371,"end":378,"name":"PUSH","source":1,"value":"0"},{"begin":400,"end":405,"name":"DUP2","source":1},{"begin":389,"end":405,"name":"SWAP1","source":1},{"begin":389,"end":405,"name":"POP","source":1},{"begin":334,"end":411,"name":"SWAP2","source":1},{"begin":334,"end":411,"name":"SWAP1","source":1},{"begin":334,"end":411,"name":"POP","source":1},{"begin":334,"end":411,"jumpType":"[out]","name":"JUMP","source":1},{"begin":417,"end":539,"name":"tag","source":1,"value":"16"},{"begin":417,"end":539,"name":"JUMPDEST","source":1},{"begin":490,"end":514,"name":"PUSH [tag]","source":1,"value":"25"},{"begin":508,"end":513,"name":"DUP2","source":1},{"begin":490,"end":514,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":490,"end":514,"jumpType":"[in]","name":"JUMP","source":1},{"begin":490,"end":514,"name":"tag","source":1,"value":"25"},{"begin":490,"end":514,"name":"JUMPDEST","source":1},{"begin":483,"end":488,"name":"DUP2","source":1},{"begin":480,"end":515,"name":"EQ","source":1},{"begin":470,"end":533,"name":"PUSH [tag]","source":1,"value":"26"},{"begin":470,"end":533,"name":"JUMPI","source":1},{"begin":529,"end":530,"name":"PUSH","source":1,"value":"0"},{"begin":526,"end":527,"name":"PUSH","source":1,"value":"0"},{"begin":519,"end":531,"name":"REVERT","source":1},{"begin":470,"end":533,"name":"tag","source":1,"value":"26"},{"begin":470,"end":533,"name":"JUMPDEST","source":1},{"begin":417,"end":539,"name":"POP","source":1},{"begin":417,"end":539,"jumpType":"[out]","name":"JUMP","source":1},{"begin":545,"end":684,"name":"tag","source":1,"value":"17"},{"begin":545,"end":684,"name":"JUMPDEST","source":1},{"begin":591,"end":596,"name":"PUSH","source":1,"value":"0"},{"begin":629,"end":635,"name":"DUP2","source":1},{"begin":616,"end":636,"name":"CALLDATALOAD","source":1},{"begin":607,"end":636,"name":"SWAP1","source":1},{"begin":607,"end":636,"name":"POP","source":1},{"begin":645,"end":678,"name":"PUSH [tag]","source":1,"value":"28"},{"begin":672,"end":677,"name":"DUP2","source":1},{"begin":645,"end":678,"name":"PUSH [tag]","source":1,"value":"16"},{"begin":645,"end":678,"jumpType":"[in]","name":"JUMP","source":1},{"begin":645,"end":678,"name":"tag","source":1,"value":"28"},{"begin":645,"end":678,"name":"JUMPDEST","source":1},{"begin":545,"end":684,"name":"SWAP3","source":1},{"begin":545,"end":684,"name":"SWAP2","source":1},{"begin":545,"end":684,"name":"POP","source":1},{"begin":545,"end":684,"name":"POP","source":1},{"begin":545,"end":684,"jumpType":"[out]","name":"JUMP","source":1},{"begin":690,"end":1019,"name":"tag","source":1,"value":"6"},{"begin":690,"end":1019,"name":"JUMPDEST","source":1},{"begin":749,"end":755,"name":"PUSH","source":1,"value":"0"},{"begin":798,"end":800,"name":"PUSH","source":1,"value":"20"},{"begin":786,"end":795,"name":"DUP3","source":1},{"begin":777,"end":784,"name":"DUP5","source":1},{"begin":773,"end":796,"name":"SUB","source":1},{"begin":769,"end":801,"name":"SLT","source":1},{"begin":766,"end":885,"name":"ISZERO","source":1},{"begin":766,"end":885,"name":"PUSH [tag]","source":1,"value":"30"},{"begin":766,"end":885,"name":"JUMPI","source":1},{"begin":804,"end":883,"name":"PUSH [tag]","source":1,"value":"31"},{"begin":804,"end":883,"name":"PUSH [tag]","source":1,"value":"13"},{"begin":804,"end":883,"jumpType":"[in]","name":"JUMP","source":1},{"begin":804,"end":883,"name":"tag","source":1,"value":"31"},{"begin":804,"end":883,"name":"JUMPDEST","source":1},{"begin":766,"end":885,"name":"tag","source":1,"value":"30"},{"begin":766,"end":885,"name":"JUMPDEST","source":1},{"begin":924,"end":925,"name":"PUSH","source":1,"value":"0"},{"begin":949,"end":1002,"name":"PUSH [tag]","source":1,"value":"32"},{"begin":994,"end":1001,"name":"DUP5","source":1},{"begin":985,"end":991,"name":"DUP3","source":1},{"begin":974,"end":983,"name":"DUP6","source":1},{"begin":970,"end":992,"name":"ADD","source":1},{"begin":949,"end":1002,"name":"PUSH [tag]","source":1,"value":"17"},{"begin":949,"end":1002,"jumpType":"[in]","name":"JUMP","source":1},{"begin":949,"end":1002,"name":"tag","source":1,"value":"32"},{"begin":949,"end":1002,"name":"JUMPDEST","source":1},{"begin":939,"end":1002,"name":"SWAP2","source":1},{"begin":939,"end":1002,"name":"POP","source":1},{"begin":895,"end":1012,"name":"POP","source":1},{"begin":690,"end":1019,"name":"SWAP3","source":1},{"begin":690,"end":1019,"name":"SWAP2","source":1},{"begin":690,"end":1019,"name":"POP","source":1},{"begin":690,"end":1019,"name":"POP","source":1},{"begin":690,"end":1019,"jumpType":"[out]","name":"JUMP","source":1},{"begin":1025,"end":1205,"name":"tag","source":1,"value":"18"},{"begin":1025,"end":1205,"name":"JUMPDEST","source":1},{"begin":1073,"end":1150,"name":"PUSH","source":1,"value":"4E487B7100000000000000000000000000000000000000000000000000000000"},{"begin":1070,"end":1071,"name":"PUSH","source":1,"value":"0"},{"begin":1063,"end":1151,"name":"MSTORE","source":1},{"begin":1170,"end":1174,"name":"PUSH","source":1,"value":"11"},{"begin":1167,"end":1168,"name":"PUSH","source":1,"value":"4"},{"begin":1160,"end":1175,"name":"MSTORE","source":1},{"begin":1194,"end":1198,"name":"PUSH","source":1,"value":"24"},{"begin":1191,"end":1192,"name":"PUSH","source":1,"value":"0"},{"begin":1184,"end":1199,"name":"REVERT","source":1},{"begin":1211,"end":1402,"name":"tag","source":1,"value":"10"},{"begin":1211,"end":1402,"name":"JUMPDEST","source":1},{"begin":1251,"end":1254,"name":"PUSH","source":1,"value":"0"},{"begin":1270,"end":1290,"name":"PUSH [tag]","source":1,"value":"35"},{"begin":1288,"end":1289,"name":"DUP3","source":1},{"begin":1270,"end":1290,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":1270,"end":1290,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1270,"end":1290,"name":"tag","source":1,"value":"35"},{"begin":1270,"end":1290,"name":"JUMPDEST","source":1},{"begin":1265,"end":1290,"name":"SWAP2","source":1},{"begin":1265,"end":1290,"name":"POP","source":1},{"begin":1304,"end":1324,"name":"PUSH [tag]","source":1,"value":"36"},{"begin":1322,"end":1323,"name":"DUP4","source":1},{"begin":1304,"end":1324,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":1304,"end":1324,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1304,"end":1324,"name":"tag","source":1,"value":"36"},{"begin":1304,"end":1324,"name":"JUMPDEST","source":1},{"begin":1299,"end":1324,"name":"SWAP3","source":1},{"begin":1299,"end":1324,"name":"POP","source":1},{"begin":1347,"end":1348,"name":"DUP3","source":1},{"begin":1344,"end":1345,"name":"DUP3","source":1},{"begin":1340,"end":1349,"name":"ADD","source":1},{"begin":1333,"end":1349,"name":"SWAP1","source":1},{"begin":1333,"end":1349,"name":"POP","source":1},{"begin":1368,"end":1371,"name":"DUP1","source":1},{"begin":1365,"end":1366,"name":"DUP3","source":1},{"begin":1362,"end":1372,"name":"GT","source":1},{"begin":1359,"end":1395,"name":"ISZERO","source":1},{"begin":1359,"end":1395,"name":"PUSH [tag]","source":1,"value":"37"},{"begin":1359,"end":1395,"name":"JUMPI","source":1},{"begin":1375,"end":1393,"name":"PUSH [tag]","source":1,"value":"38"},{"begin":1375,"end":1393,"name":"PUSH [tag]","source":1,"value":"18"},{"begin":1375,"end":1393,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1375,"end":1393,"name":"tag","source":1,"value":"38"},{"begin":1375,"end":1393,"name":"JUMPDEST","source":1},{"begin":1359,"end":1395,"name":"tag","source":1,"value":"37"},{"begin":1359,"end":1395,"name":"JUMPDEST","source":1},{"begin":1211,"end":1402,"name":"SWAP3","source":1},{"begin":1211,"end":1402,"name":"SWAP2","source":1},{"begin":1211,"end":1402,"name":"POP","source":1},{"begin":1211,"end":1402,"name":"POP","source":1},{"begin":1211,"end":1402,"jumpType":"[out]","name":"JUMP","source":1}]}},"sourceList":["asm_json_no_pretty_print/input.sol","#utility.yul"]} diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output index a232fed8f..4833a9f62 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output @@ -8,9 +8,7 @@ EVM assembly: iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -30,9 +28,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -43,9 +39,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* "debug_info_in_yul_and_evm_asm_print_all/input.sol":77:99 function f() public {} */ tag_3: stop diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output index 00a6b290f..00b04a01a 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output @@ -8,9 +8,7 @@ EVM assembly: iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -30,9 +28,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -43,9 +39,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* "debug_info_in_yul_and_evm_asm_print_location_only/input.sol":77:99 */ tag_3: stop diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output index c8715df15..9527edf76 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output @@ -7,9 +7,7 @@ EVM assembly: iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -28,9 +26,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -41,9 +37,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_3: stop diff --git a/test/cmdlineTests/dup_opt_peephole/output b/test/cmdlineTests/dup_opt_peephole/output index 2f75f2bdd..a9e0203ed 100644 --- a/test/cmdlineTests/dup_opt_peephole/output +++ b/test/cmdlineTests/dup_opt_peephole/output @@ -8,9 +8,7 @@ EVM assembly: iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -30,9 +28,7 @@ sub_0: assembly { iszero tag_3 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_3: pop /* "dup_opt_peephole/input.sol":134:135 0 */ diff --git a/test/cmdlineTests/optimize_full_storage_write/output b/test/cmdlineTests/optimize_full_storage_write/output index 1a7322030..9ebec71f0 100644 --- a/test/cmdlineTests/optimize_full_storage_write/output +++ b/test/cmdlineTests/optimize_full_storage_write/output @@ -8,9 +8,7 @@ EVM assembly: iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -30,9 +28,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -43,9 +39,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* "optimize_full_storage_write/input.sol":111:211 function f() public {... */ tag_3: tag_4 diff --git a/test/cmdlineTests/optimizer_BlockDeDuplicator/output b/test/cmdlineTests/optimizer_BlockDeDuplicator/output index ddf17bdae..fb72e4bc1 100644 --- a/test/cmdlineTests/optimizer_BlockDeDuplicator/output +++ b/test/cmdlineTests/optimizer_BlockDeDuplicator/output @@ -23,9 +23,7 @@ EVM assembly: iszero tag_5 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_5: pop jump(tag_6) @@ -51,9 +49,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -74,9 +70,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* "optimizer_BlockDeDuplicator/input.sol":138:174 function f() public { true ? 1 : 3;} */ tag_3: stop diff --git a/test/cmdlineTests/optimizer_inliner_add/output b/test/cmdlineTests/optimizer_inliner_add/output index 648d20fe8..9ebc9977d 100644 --- a/test/cmdlineTests/optimizer_inliner_add/output +++ b/test/cmdlineTests/optimizer_inliner_add/output @@ -8,9 +8,7 @@ EVM assembly: iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -30,9 +28,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -43,9 +39,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* "optimizer_inliner_add/input.sol":182:303 function f() public pure {... */ tag_3: tag_4 diff --git a/test/cmdlineTests/optimizer_inliner_call_from_constructor/output b/test/cmdlineTests/optimizer_inliner_call_from_constructor/output index 86c09e27e..f42f9de09 100644 --- a/test/cmdlineTests/optimizer_inliner_call_from_constructor/output +++ b/test/cmdlineTests/optimizer_inliner_call_from_constructor/output @@ -9,9 +9,7 @@ EVM assembly: iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop /* "optimizer_inliner_call_from_constructor/input.sol":257:258 6 */ @@ -38,9 +36,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -51,9 +47,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* "optimizer_inliner_call_from_constructor/input.sol":120:175 function a() public pure returns (uint) { return f(); } */ tag_3: /* "optimizer_inliner_call_from_constructor/input.sol":257:258 6 */ diff --git a/test/cmdlineTests/optimizer_inliner_dynamic_reference/output b/test/cmdlineTests/optimizer_inliner_dynamic_reference/output index 2ddef4d76..b1c5c74d9 100644 --- a/test/cmdlineTests/optimizer_inliner_dynamic_reference/output +++ b/test/cmdlineTests/optimizer_inliner_dynamic_reference/output @@ -8,9 +8,7 @@ EVM assembly: iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -30,9 +28,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -53,9 +49,7 @@ sub_0: assembly { tag_5 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* "optimizer_inliner_dynamic_reference/input.sol":160:215 function a() public pure returns (uint) { return f(); } */ tag_3: /* "optimizer_inliner_dynamic_reference/input.sol":361:362 6 */ diff --git a/test/cmdlineTests/optimizer_inliner_dynamic_reference_constructor/output b/test/cmdlineTests/optimizer_inliner_dynamic_reference_constructor/output index edc93c0be..24ecaede0 100644 --- a/test/cmdlineTests/optimizer_inliner_dynamic_reference_constructor/output +++ b/test/cmdlineTests/optimizer_inliner_dynamic_reference_constructor/output @@ -9,9 +9,7 @@ EVM assembly: iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop /* "optimizer_inliner_dynamic_reference_constructor/input.sol":93:94 x */ @@ -57,9 +55,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -75,9 +71,7 @@ sub_0: assembly { tag_4 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* "optimizer_inliner_dynamic_reference_constructor/input.sol":154:209 function a() public pure returns (uint) { return f(); } */ tag_3: /* "optimizer_inliner_dynamic_reference_constructor/input.sol":355:356 6 */ diff --git a/test/cmdlineTests/optimizer_inliner_inc/output b/test/cmdlineTests/optimizer_inliner_inc/output index 04f5f745a..3a3639e19 100644 --- a/test/cmdlineTests/optimizer_inliner_inc/output +++ b/test/cmdlineTests/optimizer_inliner_inc/output @@ -8,9 +8,7 @@ EVM assembly: iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -30,9 +28,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -43,9 +39,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* "optimizer_inliner_inc/input.sol":174:277 function f() public pure {... */ tag_3: tag_4 diff --git a/test/cmdlineTests/optimizer_inliner_multireturn/output b/test/cmdlineTests/optimizer_inliner_multireturn/output index ca7b0abdf..46d74055a 100644 --- a/test/cmdlineTests/optimizer_inliner_multireturn/output +++ b/test/cmdlineTests/optimizer_inliner_multireturn/output @@ -8,9 +8,7 @@ EVM assembly: iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -30,9 +28,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -43,9 +39,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* "optimizer_inliner_multireturn/input.sol":179:296 function f() public pure {... */ tag_3: tag_4 diff --git a/test/cmdlineTests/optimizer_user_yul/output b/test/cmdlineTests/optimizer_user_yul/output index 689e82ddb..c106c011b 100644 --- a/test/cmdlineTests/optimizer_user_yul/output +++ b/test/cmdlineTests/optimizer_user_yul/output @@ -6,9 +6,9 @@ EVM assembly: /* "optimizer_user_yul/input.sol":101:106 int a */ 0x00 /* "optimizer_user_yul/input.sol":181:190 let x,y,z */ - dup1 0x00 - dup1 + 0x00 + 0x00 /* "optimizer_user_yul/input.sol":205:206 1 */ 0x01 /* "optimizer_user_yul/input.sol":202:203 0 */ @@ -78,9 +78,7 @@ stop sub_0: assembly { /* "optimizer_user_yul/input.sol":60:518 contract C... */ mstore(0x40, 0x80) - 0x00 - dup1 - revert + revert(0x00, 0x00) auxdata: } diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json index 9489a75bf..e004ab742 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json @@ -10,9 +10,7 @@ iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -32,9 +30,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -45,9 +41,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* \"C\":77:99 function f() public {} */ tag_3: stop diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json index f8f2958b0..5c7a93644 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json @@ -10,9 +10,7 @@ iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -32,9 +30,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -45,9 +41,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) /* \"C\":77:99 */ tag_3: stop diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json index 2a5a2bc2a..6f2f9243c 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json @@ -9,9 +9,7 @@ iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop dataSize(sub_0) @@ -30,9 +28,7 @@ sub_0: assembly { iszero tag_1 jumpi - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) @@ -43,9 +39,7 @@ sub_0: assembly { tag_3 jumpi tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_3: stop diff --git a/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/output b/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/output index dfa765683..10a0231f5 100644 --- a/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/output +++ b/test/cmdlineTests/strict_asm_asm_json_subobjects_with_debug/output @@ -14,8 +14,9 @@ EVM assembly: { "begin": 41, "end": 137, - "name": "DUP1", - "source": 0 + "name": "PUSH", + "source": 0, + "value": "0" }, { "begin": 41, diff --git a/test/cmdlineTests/strict_asm_msize_without_optimizer/output b/test/cmdlineTests/strict_asm_msize_without_optimizer/output index fabd2e874..ac19efbcb 100644 --- a/test/cmdlineTests/strict_asm_msize_without_optimizer/output +++ b/test/cmdlineTests/strict_asm_msize_without_optimizer/output @@ -15,13 +15,13 @@ object "object" { Binary representation: -600b565b5f8051905090565b5f8060136003565b5f525050 +600b565b5f5f51905090565b5f8060136003565b5f525050 Text representation: jump(tag_2) tag_1: 0x00 - dup1 + 0x00 mload swap1 pop diff --git a/test/cmdlineTests/viair_msize_without_optimizer/output b/test/cmdlineTests/viair_msize_without_optimizer/output index b54f8a3f5..f94c973bf 100644 --- a/test/cmdlineTests/viair_msize_without_optimizer/output +++ b/test/cmdlineTests/viair_msize_without_optimizer/output @@ -31,9 +31,7 @@ tag_1: swap1 jump // out tag_2: - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_3: jump // out stop @@ -84,13 +82,9 @@ sub_0: assembly { swap1 jump // out tag_3: - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_4: - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_5: 0x00 dup2 @@ -110,7 +104,7 @@ sub_0: assembly { jump // out tag_6: 0x00 - dup1 + 0x00 dup3 add swap1 @@ -151,15 +145,12 @@ sub_0: assembly { dup3 return tag_8: - 0x00 - dup1 - revert + revert(0x00, 0x00) tag_9: jump(tag_35) tag_34: 0x00 - dup1 - mload + mload(0x00) swap1 pop swap1 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol index 8d74a34f4..5c3bcba97 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol @@ -21,6 +21,6 @@ contract C { } // ---- // f() -> 0x20, 0x8, 0x40, 0x3, 0x9, 0xa, 0xb -// gas irOptimized: 203173 +// gas irOptimized: 203167 // gas legacy: 206263 // gas legacyOptimized: 203172 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol index a518a3750..a6a4f8fd8 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol @@ -60,9 +60,9 @@ contract C { // ---- // test_bytes() -> // gas irOptimized: 314884 -// gas legacy: 305827 -// gas legacyOptimized: 253681 +// gas legacy: 305816 +// gas legacyOptimized: 253573 // test_uint256() -> // gas irOptimized: 448346 -// gas legacy: 421315 -// gas legacyOptimized: 351650 +// gas legacy: 421304 +// gas legacyOptimized: 351544 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol index c8eb95418..ed983c77b 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol @@ -24,6 +24,6 @@ contract C { // ---- // library: L // f() -> 8, 7, 1, 2, 7, 12 -// gas irOptimized: 166759 -// gas legacy: 169283 -// gas legacyOptimized: 167248 +// gas irOptimized: 166761 +// gas legacy: 169273 +// gas legacyOptimized: 167243 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol index b80d14d6b..0c59c33c4 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol @@ -61,9 +61,9 @@ contract C { // ---- // test_bytes() -> // gas irOptimized: 314884 -// gas legacy: 305827 -// gas legacyOptimized: 253681 +// gas legacy: 305816 +// gas legacyOptimized: 253573 // test_uint256() -> // gas irOptimized: 448346 -// gas legacy: 421315 -// gas legacyOptimized: 351650 +// gas legacy: 421304 +// gas legacyOptimized: 351544 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol index f07d4039d..edfe075dd 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol @@ -51,5 +51,5 @@ contract C { // f3() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc" // f4() -> 0x20, 0x160, 0x1, 0x80, 0xc0, 0x2, 0x3, "abc", 0x7, 0x40, 0x2, 0x2, 0x3 // gas irOptimized: 111816 -// gas legacy: 113892 +// gas legacy: 113890 // gas legacyOptimized: 111658 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol index 7a2395549..8df4090c3 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol @@ -39,5 +39,5 @@ contract C is B { // ---- // test() -> 5, 10 // gas irOptimized: 87337 -// gas legacy: 66251 +// gas legacy: 66250 // gas legacy code: 36400 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol index 81c9c46c6..aa1e494c2 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol @@ -33,8 +33,8 @@ contract C { // f_which(uint256[],uint256[2],uint256): 0x40, 1, 2, 1, 5, 6 -> 0x20, 0x40, 5, 2 // f_which(uint256[],uint256[2],uint256): 0x40, 1, 2, 1 -> FAILURE // f_storage(uint256[],uint256[2]): 0x20, 1, 2 -> 0x20, 0x60, 0x20, 1, 2 -// gas irOptimized: 111415 -// gas legacy: 112709 -// gas legacyOptimized: 111847 +// gas irOptimized: 111409 +// gas legacy: 112707 +// gas legacyOptimized: 111845 // f_storage(uint256[],uint256[2]): 0x40, 1, 2, 5, 6 -> 0x20, 0x80, 0x20, 2, 5, 6 // f_storage(uint256[],uint256[2]): 0x40, 1, 2, 5 -> FAILURE diff --git a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol index 7eb93d401..9599af6c8 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol @@ -18,9 +18,9 @@ contract C { // EVMVersion: >homestead // ---- // h(uint256[2][]): 0x20, 3, 123, 124, 223, 224, 323, 324 -> 32, 256, 0x20, 3, 123, 124, 223, 224, 323, 324 -// gas irOptimized: 180086 -// gas legacy: 184235 -// gas legacyOptimized: 180857 +// gas irOptimized: 180080 +// gas legacy: 184233 +// gas legacyOptimized: 180856 // i(uint256[2][2]): 123, 124, 223, 224 -> 32, 128, 123, 124, 223, 224 // gas irOptimized: 112031 // gas legacy: 115091 diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol index 93e20b475..54ce693d5 100644 --- a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol @@ -8,6 +8,6 @@ contract C { } // ---- // f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg" -// gas irOptimized: 135505 -// gas legacy: 137096 -// gas legacyOptimized: 135824 +// gas irOptimized: 135499 +// gas legacy: 137095 +// gas legacyOptimized: 135823 diff --git a/test/libsolidity/semanticTests/array/array_memory_index_access.sol b/test/libsolidity/semanticTests/array/array_memory_index_access.sol index 49fc58c45..d992014c4 100644 --- a/test/libsolidity/semanticTests/array/array_memory_index_access.sol +++ b/test/libsolidity/semanticTests/array/array_memory_index_access.sol @@ -27,8 +27,8 @@ contract C { // index(uint256): 20 -> true // index(uint256): 0xFF -> true // gas irOptimized: 108272 -// gas legacy: 181523 -// gas legacyOptimized: 117443 +// gas legacy: 181536 +// gas legacyOptimized: 117442 // accessIndex(uint256,int256): 10, 1 -> 2 // accessIndex(uint256,int256): 10, 0 -> 1 // accessIndex(uint256,int256): 10, 11 -> FAILURE, hex"4e487b71", 0x32 diff --git a/test/libsolidity/semanticTests/array/array_storage_index_access.sol b/test/libsolidity/semanticTests/array/array_storage_index_access.sol index 2957e6d98..325323c5c 100644 --- a/test/libsolidity/semanticTests/array/array_storage_index_access.sol +++ b/test/libsolidity/semanticTests/array/array_storage_index_access.sol @@ -17,37 +17,37 @@ contract C { // test_indices(uint256): 1 -> // test_indices(uint256): 129 -> // gas irOptimized: 3017687 -// gas legacy: 3038654 +// gas legacy: 3038668 // gas legacyOptimized: 2995964 // test_indices(uint256): 5 -> // gas irOptimized: 579670 -// gas legacy: 573810 +// gas legacy: 573821 // gas legacyOptimized: 571847 // test_indices(uint256): 10 -> // gas irOptimized: 157953 -// gas legacy: 160108 +// gas legacy: 160122 // gas legacyOptimized: 156996 // test_indices(uint256): 15 -> // gas irOptimized: 172733 -// gas legacy: 175973 +// gas legacy: 175987 // gas legacyOptimized: 171596 // test_indices(uint256): 0xFF -> // gas irOptimized: 5673823 -// gas legacy: 5715748 +// gas legacy: 5715762 // gas legacyOptimized: 5632556 // test_indices(uint256): 1000 -> // gas irOptimized: 18173005 -// gas legacy: 18347810 +// gas legacy: 18347824 // gas legacyOptimized: 18037248 // test_indices(uint256): 129 -> // gas irOptimized: 4166279 -// gas legacy: 4140113 +// gas legacy: 4140124 // gas legacyOptimized: 4108272 // test_indices(uint256): 128 -> // gas irOptimized: 405522 -// gas legacy: 433498 +// gas legacy: 433512 // gas legacyOptimized: 400909 // test_indices(uint256): 1 -> // gas irOptimized: 583437 -// gas legacy: 576715 +// gas legacy: 576726 // gas legacyOptimized: 575542 diff --git a/test/libsolidity/semanticTests/array/array_storage_index_boundary_test.sol b/test/libsolidity/semanticTests/array/array_storage_index_boundary_test.sol index 494c99782..712a7cdeb 100644 --- a/test/libsolidity/semanticTests/array/array_storage_index_boundary_test.sol +++ b/test/libsolidity/semanticTests/array/array_storage_index_boundary_test.sol @@ -17,11 +17,11 @@ contract C { // test_boundary_check(uint256,uint256): 10, 10 -> FAILURE, hex"4e487b71", 0x32 // test_boundary_check(uint256,uint256): 256, 256 -> FAILURE, hex"4e487b71", 0x32 // gas irOptimized: 147246 -// gas legacy: 133633 -// gas legacyOptimized: 114354 +// gas legacy: 133632 +// gas legacyOptimized: 114353 // test_boundary_check(uint256,uint256): 256, 255 -> 0 // gas irOptimized: 149422 -// gas legacy: 135949 -// gas legacyOptimized: 116533 +// gas legacy: 135948 +// gas legacyOptimized: 116532 // test_boundary_check(uint256,uint256): 256, 0xFFFF -> FAILURE, hex"4e487b71", 0x32 // test_boundary_check(uint256,uint256): 256, 2 -> 0 diff --git a/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol b/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol index de260b373..23feb0da1 100644 --- a/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol +++ b/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol @@ -53,17 +53,17 @@ contract C { // test_zeroed_indicies(uint256): 1 -> // test_zeroed_indicies(uint256): 5 -> // gas irOptimized: 133763 -// gas legacy: 131671 -// gas legacyOptimized: 129994 +// gas legacy: 131664 +// gas legacyOptimized: 129990 // test_zeroed_indicies(uint256): 10 -> // gas irOptimized: 228556 -// gas legacy: 225237 -// gas legacyOptimized: 222359 +// gas legacy: 225215 +// gas legacyOptimized: 222351 // test_zeroed_indicies(uint256): 15 -> // gas irOptimized: 327360 -// gas legacy: 322937 -// gas legacyOptimized: 318919 +// gas legacy: 322899 +// gas legacyOptimized: 318907 // test_zeroed_indicies(uint256): 0xFF -> // gas irOptimized: 5180120 -// gas legacy: 5093941 -// gas legacyOptimized: 5020727 +// gas legacy: 5093135 +// gas legacyOptimized: 5020523 diff --git a/test/libsolidity/semanticTests/array/array_storage_push_empty.sol b/test/libsolidity/semanticTests/array/array_storage_push_empty.sol index b84cdd90a..b6965f62b 100644 --- a/test/libsolidity/semanticTests/array/array_storage_push_empty.sol +++ b/test/libsolidity/semanticTests/array/array_storage_push_empty.sol @@ -13,11 +13,11 @@ contract C { // ---- // pushEmpty(uint256): 128 // gas irOptimized: 410745 -// gas legacy: 400640 +// gas legacy: 400519 // gas legacyOptimized: 388804 // pushEmpty(uint256): 256 // gas irOptimized: 698285 -// gas legacy: 685108 +// gas legacy: 684859 // gas legacyOptimized: 671480 // pushEmpty(uint256): 38869 -> FAILURE # out-of-gas # // gas irOptimized: 100000000 diff --git a/test/libsolidity/semanticTests/array/array_storage_push_pop.sol b/test/libsolidity/semanticTests/array/array_storage_push_pop.sol index 78a74ab5d..a4c7d34d7 100644 --- a/test/libsolidity/semanticTests/array/array_storage_push_pop.sol +++ b/test/libsolidity/semanticTests/array/array_storage_push_pop.sol @@ -18,10 +18,10 @@ contract C { // gas legacyOptimized: 103508 // set_get_length(uint256): 0xFF -> 0 // gas irOptimized: 833586 -// gas legacy: 808020 +// gas legacy: 807764 // gas legacyOptimized: 784467 // set_get_length(uint256): 0xFFF -> 0 // gas irOptimized: 13029438 -// gas legacy: 12612192 +// gas legacy: 12608096 // gas legacyOptimized: 12239199 // set_get_length(uint256): 0xFFFF -> FAILURE # Out-of-gas # diff --git a/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol b/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol index 918185e9a..a9d08ec0c 100644 --- a/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol +++ b/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol @@ -12,7 +12,7 @@ contract Test { } // ---- // set(uint24[3][]): 0x20, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12 -> 0x06 -// gas irOptimized: 185219 +// gas irOptimized: 185216 // gas legacy: 211054 // gas legacyOptimized: 206077 // data(uint256,uint256): 0x02, 0x02 -> 0x09 diff --git a/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol b/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol index 942c7337a..060cafe39 100644 --- a/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol +++ b/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol @@ -46,8 +46,8 @@ contract c { // storageEmpty -> 0 // test_long() -> 67 // gas irOptimized: 89148 -// gas legacy: 101601 -// gas legacyOptimized: 100477 +// gas legacy: 101607 +// gas legacyOptimized: 100479 // storageEmpty -> 0 // test_pop() -> 1780731860627700044960722568376592200742329637303199754547598369979433020 // gas legacy: 61930 diff --git a/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol b/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol index 401f97a1c..e83cc5458 100644 --- a/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol +++ b/test/libsolidity/semanticTests/array/byte_array_transitional_2.sol @@ -17,6 +17,6 @@ contract c { } // ---- // test() -> 0 -// gas irOptimized: 122719 -// gas legacy: 147098 +// gas irOptimized: 122717 +// gas legacy: 147108 // gas legacyOptimized: 144200 diff --git a/test/libsolidity/semanticTests/array/bytes_length_member.sol b/test/libsolidity/semanticTests/array/bytes_length_member.sol index 105bbfba8..5159538bc 100644 --- a/test/libsolidity/semanticTests/array/bytes_length_member.sol +++ b/test/libsolidity/semanticTests/array/bytes_length_member.sol @@ -13,7 +13,7 @@ contract c { // ---- // getLength() -> 0 // set(): 1, 2 -> true -// gas irOptimized: 110425 -// gas legacy: 110952 +// gas irOptimized: 110422 +// gas legacy: 110951 // gas legacyOptimized: 110576 // getLength() -> 68 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol index 96580c47d..ecfe565f1 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol @@ -21,6 +21,6 @@ contract c { // ---- // store(uint256[9],uint8[3][]): 21, 22, 23, 24, 25, 26, 27, 28, 29, 0x140, 4, 1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33 -> 32 // gas irOptimized: 647725 -// gas legacy: 694356 -// gas legacyOptimized: 693850 +// gas legacy: 694354 +// gas legacyOptimized: 693849 // retrieve() -> 9, 28, 9, 28, 4, 3, 32 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol index 9609215a7..d65f4f37c 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol @@ -46,6 +46,6 @@ contract C { } // ---- // f() -> true -// gas irOptimized: 122592 -// gas legacy: 124660 +// gas irOptimized: 122541 +// gas legacy: 124643 // gas legacyOptimized: 122801 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol index 6c0ba7af6..e9f1448a2 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol @@ -13,6 +13,6 @@ contract C { } // ---- // f() -> 0 -// gas irOptimized: 108246 -// gas legacy: 108218 +// gas irOptimized: 108229 +// gas legacy: 108216 // gas legacyOptimized: 107625 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol b/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol index 2176655fe..ee564d01a 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol @@ -18,6 +18,6 @@ contract c { } // ---- // test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x05000000000000000000000000000000000000000000000000 -// gas irOptimized: 208459 -// gas legacy: 220707 -// gas legacyOptimized: 220098 +// gas irOptimized: 208415 +// gas legacy: 220711 +// gas legacyOptimized: 220097 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol index 20aee3a29..bb621fcc8 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol @@ -35,12 +35,12 @@ contract c { } // ---- // test() -> 0x02000202 -// gas irOptimized: 4549703 -// gas legacy: 4475396 +// gas irOptimized: 4549676 +// gas legacy: 4475394 // gas legacyOptimized: 4447665 // storageEmpty -> 1 // clear() -> 0, 0 -// gas irOptimized: 4478226 -// gas legacy: 4407188 -// gas legacyOptimized: 4381336 +// gas irOptimized: 4478184 +// gas legacy: 4407185 +// gas legacyOptimized: 4381337 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol b/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol index 0420f953b..2d325a804 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol @@ -12,6 +12,6 @@ contract c { } // ---- // test(uint256[2][]): 32, 3, 7, 8, 9, 10, 11, 12 -> 10 -// gas irOptimized: 689558 -// gas legacy: 686178 -// gas legacyOptimized: 685612 +// gas irOptimized: 689552 +// gas legacy: 686176 +// gas legacyOptimized: 685611 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol index e292809b8..54639df55 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol @@ -19,4 +19,4 @@ contract c { // test() -> 5, 4 // gas irOptimized: 205667 // gas legacy: 213863 -// gas legacyOptimized: 212902 +// gas legacyOptimized: 212901 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol index 44fede749..ad745ff42 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol @@ -22,5 +22,5 @@ contract c { // ---- // test() -> 3, 4 // gas irOptimized: 169669 -// gas legacy: 175424 -// gas legacyOptimized: 172535 +// gas legacy: 175415 +// gas legacyOptimized: 172533 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol index 1f102ea14..a38685404 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol @@ -15,7 +15,7 @@ contract c { // ---- // setData1(uint256,uint256,uint256): 10, 5, 4 -> // copyStorageStorage() -> -// gas irOptimized: 111353 +// gas irOptimized: 111350 // gas legacy: 109272 // gas legacyOptimized: 109262 // getData2(uint256): 5 -> 10, 4 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol index 03c1f4e87..83df3aef8 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol @@ -19,4 +19,4 @@ contract c { // test() -> 5, 4 // gas irOptimized: 253591 // gas legacy: 250892 -// gas legacyOptimized: 250046 +// gas legacyOptimized: 250045 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol index f4bf1b2d2..94e57c96d 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol @@ -12,5 +12,5 @@ contract c { // ---- // test() -> 9, 4 // gas irOptimized: 123180 -// gas legacy: 123567 +// gas legacy: 123566 // gas legacyOptimized: 123202 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol index 145a8060e..d1f2cbded 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol @@ -15,5 +15,5 @@ contract c { // ---- // test() -> 8, 0 // gas irOptimized: 196251 -// gas legacy: 194843 +// gas legacy: 194842 // gas legacyOptimized: 194281 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol index 7fa5ee515..e638f2dad 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol @@ -18,6 +18,6 @@ contract c { // ---- // test() -> 4, 5 // gas irOptimized: 190628 -// gas legacy: 190852 -// gas legacyOptimized: 189658 +// gas legacy: 190828 +// gas legacyOptimized: 189657 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol index d88ac0674..120e72884 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_to_memory_nested.sol @@ -16,5 +16,5 @@ contract C { // ---- // f() -> 0x20, 2, 0x40, 0xa0, 2, 0, 1, 2, 2, 3 // gas irOptimized: 161793 -// gas legacy: 162203 +// gas legacy: 162200 // gas legacyOptimized: 159953 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol b/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol index ebfbdeab9..22105f642 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol @@ -17,6 +17,6 @@ contract c { } // ---- // test() -> 0xffffffff, 0x0000000000000000000000000a00090008000700060005000400030002000100, 0x0000000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 100495 -// gas legacy: 158142 -// gas legacyOptimized: 141020 +// gas irOptimized: 100496 +// gas legacy: 158109 +// gas legacyOptimized: 141019 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol index 309753066..27fb9f0c5 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol @@ -18,6 +18,6 @@ contract c { } // ---- // test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x0 -// gas irOptimized: 273545 -// gas legacy: 282604 +// gas irOptimized: 273543 +// gas legacy: 282601 // gas legacyOptimized: 281510 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol index b08487417..980e414d1 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol @@ -18,6 +18,6 @@ contract c { } // ---- // test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x00 -// gas irOptimized: 232997 -// gas legacy: 235697 +// gas irOptimized: 232995 +// gas legacy: 235694 // gas legacyOptimized: 235193 diff --git a/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol b/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol index 085f72ed9..becc3d4cd 100644 --- a/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol +++ b/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol @@ -52,9 +52,9 @@ contract C { } // ---- // from_storage() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -// gas irOptimized: 149880 -// gas legacy: 150745 -// gas legacyOptimized: 148700 +// gas irOptimized: 149868 +// gas legacy: 150737 +// gas legacyOptimized: 148690 // from_storage_ptr() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 // from_memory() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 // from_calldata(uint8[][]): 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol index ac37f794e..5d4e5b45e 100644 --- a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol @@ -38,10 +38,10 @@ contract c { // compileViaYul: true // ---- // test1(uint256[][]): 0x20, 2, 0x40, 0x40, 2, 23, 42 -> 2, 65 -// gas irOptimized: 181041 +// gas irOptimized: 181029 // test2(uint256[][2]): 0x20, 0x40, 0x40, 2, 23, 42 -> 2, 65 // gas irOptimized: 157604 // test3(uint256[2][]): 0x20, 2, 23, 42, 23, 42 -> 2, 65 -// gas irOptimized: 134813 +// gas irOptimized: 134801 // test4(uint256[2][2]): 23, 42, 23, 42 -> 65 // gas irOptimized: 111177 diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol index e2228f993..b892ec991 100644 --- a/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol @@ -38,12 +38,12 @@ contract Test { } // ---- // test() -> 24 -// gas irOptimized: 226743 -// gas legacy: 227084 +// gas irOptimized: 226734 +// gas legacy: 227083 // gas legacyOptimized: 226529 // test1() -> 3 // test2() -> 6 // test3() -> 24 -// gas irOptimized: 141325 +// gas irOptimized: 141319 // gas legacy: 142238 // gas legacyOptimized: 141365 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol index 8b6ad78ea..355c268f2 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_memory_to_storage.sol @@ -26,4 +26,4 @@ contract C { // compileViaYul: true // ---- // f() -> 3, 3, 3, 1 -// gas irOptimized: 181932 +// gas irOptimized: 181928 diff --git a/test/libsolidity/semanticTests/array/copying/array_storage_multi_items_per_slot.sol b/test/libsolidity/semanticTests/array/copying/array_storage_multi_items_per_slot.sol index 82e65edf1..3578f0a81 100644 --- a/test/libsolidity/semanticTests/array/copying/array_storage_multi_items_per_slot.sol +++ b/test/libsolidity/semanticTests/array/copying/array_storage_multi_items_per_slot.sol @@ -13,5 +13,5 @@ contract C { // ---- // f() -> 1, 2, 3 // gas irOptimized: 131939 -// gas legacy: 134606 +// gas legacy: 134605 // gas legacyOptimized: 131938 diff --git a/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol b/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol index 75a68759b..c5519e83a 100644 --- a/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol +++ b/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol @@ -37,8 +37,8 @@ contract C { } // ---- // from_storage() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -// gas irOptimized: 147761 -// gas legacy: 148896 -// gas legacyOptimized: 146923 +// gas irOptimized: 147755 +// gas legacy: 148892 +// gas legacyOptimized: 146917 // from_storage_ptr() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 // from_memory() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 diff --git a/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol b/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol index e61b7dff7..90012eed4 100644 --- a/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol +++ b/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol @@ -6,11 +6,11 @@ contract c { // ---- // set(uint256): 1, 2 -> true // gas irOptimized: 110550 -// gas legacy: 111312 +// gas legacy: 111310 // gas legacyOptimized: 110741 // set(uint256): 2, 2, 3, 4, 5 -> true // gas irOptimized: 177501 -// gas legacy: 178314 +// gas legacy: 178312 // gas legacyOptimized: 177716 // storageEmpty -> 0 // copy(uint256,uint256): 1, 2 -> true diff --git a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol index ea364d437..fe758fe8f 100644 --- a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol @@ -17,25 +17,25 @@ contract c { // ---- // f(uint256): 0 -> 0x20, 0x00 // f(uint256): 31 -> 0x20, 0x1f, 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e00 -// gas irOptimized: 103269 -// gas legacy: 112883 +// gas irOptimized: 103268 +// gas legacy: 112904 // gas legacyOptimized: 112647 // f(uint256): 32 -> 0x20, 0x20, 1780731860627700044960722568376592200742329637303199754547598369979440671 -// gas irOptimized: 117928 -// gas legacy: 128943 +// gas irOptimized: 117825 +// gas legacy: 128964 // gas legacyOptimized: 128854 // f(uint256): 33 -> 0x20, 33, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x2000000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 124200 -// gas legacy: 136071 +// gas irOptimized: 124091 +// gas legacy: 136092 // gas legacyOptimized: 135469 // f(uint256): 63 -> 0x20, 0x3f, 1780731860627700044960722568376592200742329637303199754547598369979440671, 14532552714582660066924456880521368950258152170031413196862950297402215316992 -// gas irOptimized: 127350 -// gas legacy: 148671 +// gas irOptimized: 127151 +// gas legacy: 148692 // gas legacyOptimized: 148699 // f(uint256): 12 -> 0x20, 0x0c, 0x0102030405060708090a0b0000000000000000000000000000000000000000 // gas legacy: 59345 // gas legacyOptimized: 57279 // f(uint256): 129 -> 0x20, 0x81, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f, 29063324697304692433803953038474361308315562010425523193971352996434451193439, 0x606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f, -57896044618658097711785492504343953926634992332820282019728792003956564819968 -// gas irOptimized: 417312 -// gas legacy: 458976 +// gas irOptimized: 416918 +// gas legacy: 458997 // gas legacyOptimized: 460664 diff --git a/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol b/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol index 1da1d0a40..3df22c725 100644 --- a/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol @@ -9,6 +9,6 @@ contract C { } // ---- // f(uint256[]): 0x20, 0x03, 0x1, 0x2, 0x3 -> 0x1 -// gas irOptimized: 111096 -// gas legacy: 111551 -// gas legacyOptimized: 111323 +// gas irOptimized: 111084 +// gas legacy: 111548 +// gas legacyOptimized: 111321 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol index 7c0459ef1..787973c5f 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol @@ -35,12 +35,12 @@ contract C { } // ---- // f() -> 0x40, 0x80, 6, 0x6162636465660000000000000000000000000000000000000000000000000000, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000 -// gas irOptimized: 179408 +// gas irOptimized: 179405 // gas legacy: 180675 // gas legacyOptimized: 179686 // g() -> 0x40, 0xc0, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000, 0x11, 0x3132333435363738393233343536373839000000000000000000000000000000 -// gas irOptimized: 106344 -// gas legacy: 109394 +// gas irOptimized: 106338 +// gas legacy: 109415 // gas legacyOptimized: 106600 // h() -> 0x40, 0x60, 0x00, 0x00 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol index 1fd42ab34..fc274bf47 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol @@ -46,6 +46,6 @@ contract C { } // ---- // f() -> 0xff -// gas irOptimized: 143867 -// gas legacy: 153395 -// gas legacyOptimized: 146689 +// gas irOptimized: 143857 +// gas legacy: 153404 +// gas legacyOptimized: 146676 diff --git a/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol b/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol index a6a64942d..7db82f891 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol @@ -15,6 +15,6 @@ contract C { } // ---- // test() -> 7 -// gas irOptimized: 122461 +// gas irOptimized: 122459 // gas legacy: 205176 // gas legacyOptimized: 204971 diff --git a/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol b/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol index 48d02bdc7..46216e912 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol @@ -8,7 +8,7 @@ contract c { // ---- // set(): 1, 2, 3, 4, 5 -> true // gas irOptimized: 177344 -// gas legacy: 177954 +// gas legacy: 177953 // gas legacyOptimized: 177550 // storageEmpty -> 0 // reset() -> true diff --git a/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol b/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol index 58b5dd045..ce4344e87 100644 --- a/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol +++ b/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol @@ -18,7 +18,7 @@ contract sender { } // ---- // (): 7 -> -// gas irOptimized: 110831 +// gas irOptimized: 110822 // gas legacy: 111388 // gas legacyOptimized: 111065 // val() -> 0 diff --git a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol index e3490e2db..640046a11 100644 --- a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol @@ -46,11 +46,11 @@ contract C { } // ---- // test() -> 0x20, 0x14, "[a called][b called]" -// gas irOptimized: 116531 -// gas legacy: 118845 -// gas legacyOptimized: 116844 +// gas irOptimized: 116518 +// gas legacy: 118841 +// gas legacyOptimized: 116843 // test2() -> 0x20, 0x14, "[b called][a called]" // test3() -> 0x20, 0x14, "[b called][a called]" -// gas irOptimized: 103150 +// gas irOptimized: 103144 // gas legacy: 102654 // gas legacyOptimized: 101556 diff --git a/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol b/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol index c54975479..8a4d870b2 100644 --- a/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol @@ -19,5 +19,5 @@ contract C { // ---- // f() -> 3 // gas irOptimized: 128296 -// gas legacy: 129050 +// gas legacy: 129077 // gas legacyOptimized: 128210 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol index ad00ee8c5..f3934fec0 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol @@ -75,8 +75,8 @@ contract C { // gas legacyOptimized: 150906 // test2() -> FAILURE // gas irOptimized: 150389 -// gas legacy: 150673 -// gas legacyOptimized: 150576 +// gas legacy: 150672 +// gas legacyOptimized: 150575 // test3() -> // gas irOptimized: 124300 // gas legacy: 125333 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol index 3b774f56e..7621b2477 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol @@ -29,8 +29,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 304794 +// gas irOptimized: 304788 // test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 // gas irOptimized: 116653 // test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 188000 +// gas irOptimized: 187994 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol index 35e7943b8..8ec3f7769 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol @@ -29,8 +29,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 309078 +// gas irOptimized: 309072 // test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 // gas irOptimized: 118314 // test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 191051 +// gas irOptimized: 191045 diff --git a/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol index a4222be0b..57b3dc521 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol @@ -32,5 +32,5 @@ contract C { // test(uint8[][][]): 0x20, 2, 0x40, 0x60, 0, 2, 0x40, 0x80, 1, 7, 2, 8, 9 // gas irOptimized: 137897 // test2(uint8[][]): 0x20, 2, 0x40, 0x80, 1, 7, 2, 8, 9 -// gas irOptimized: 164506 +// gas irOptimized: 164482 // gas legacyOptimized: 120228 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol index ac92189e4..2a486d256 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested.sol @@ -18,5 +18,5 @@ contract C { // ---- // f() -> 1, 2, 3, 4, 5, 6, 7 // gas irOptimized: 206440 -// gas legacy: 211765 -// gas legacyOptimized: 211181 +// gas legacy: 211758 +// gas legacyOptimized: 211179 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol index b743a5825..e5a6ae53b 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol @@ -12,5 +12,5 @@ contract C { // ---- // f() -> 0x20, 0x02, 0x40, 0x80, 3, 0x6162630000000000000000000000000000000000000000000000000000000000, 0x99, 44048183304486788312148433451363384677562265908331949128489393215789685032262, 32241931068525137014058842823026578386641954854143559838526554899205067598957, 49951309422467613961193228765530489307475214998374779756599339590522149884499, 0x54555658595a6162636465666768696a6b6c6d6e6f707172737475767778797a, 0x4142434445464748494a4b4c4d4e4f5051525354555658595a00000000000000 // gas irOptimized: 202083 -// gas legacy: 204328 -// gas legacyOptimized: 202900 +// gas legacy: 204327 +// gas legacyOptimized: 202899 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol index da7187a27..5ec2cbcf4 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_from_pointer.sol @@ -20,4 +20,4 @@ contract C { // f() -> 1, 2, 3, 4, 5, 6, 7 // gas irOptimized: 206440 // gas legacy: 211770 -// gas legacyOptimized: 211186 +// gas legacyOptimized: 211191 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol index d4a348ea4..b37aa96ea 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_struct.sol @@ -25,5 +25,5 @@ contract C { // ---- // f() -> 11, 0x0c, 1, 0x15, 22, 4 // gas irOptimized: 291212 -// gas legacy: 293407 +// gas legacy: 293398 // gas legacyOptimized: 290218 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol index c5bd7d0b0..a8a1b36e1 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_packed_dyn.sol @@ -14,5 +14,5 @@ contract C { // ---- // f() -> 2, 3, 4 // gas irOptimized: 114338 -// gas legacy: 122235 -// gas legacyOptimized: 118411 +// gas legacy: 122231 +// gas legacyOptimized: 118409 diff --git a/test/libsolidity/semanticTests/array/create_memory_array.sol b/test/libsolidity/semanticTests/array/create_memory_array.sol index a95499fd8..00f32a6e0 100644 --- a/test/libsolidity/semanticTests/array/create_memory_array.sol +++ b/test/libsolidity/semanticTests/array/create_memory_array.sol @@ -19,5 +19,5 @@ contract C { // ---- // f() -> "A", 8, 4, "B" // gas irOptimized: 136664 -// gas legacy: 121382 +// gas legacy: 121380 // gas legacyOptimized: 115488 diff --git a/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol b/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol index 5deaa7d4e..f776626ae 100644 --- a/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol +++ b/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol @@ -16,6 +16,6 @@ contract c { } // ---- // test1() -> true -// gas irOptimized: 218452 -// gas legacy: 242256 +// gas irOptimized: 218449 +// gas legacy: 242263 // gas legacyOptimized: 241182 diff --git a/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol b/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol index 380e30242..b2be566a9 100644 --- a/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol @@ -15,7 +15,7 @@ contract c { // storageEmpty -> 1 // fill() -> // gas irOptimized: 519494 -// gas legacy: 518936 +// gas legacy: 518943 // gas legacyOptimized: 515555 // storageEmpty -> 0 // halfClear() -> diff --git a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol index 62b611a87..f96473739 100644 --- a/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol +++ b/test/libsolidity/semanticTests/array/dynamic_arrays_in_storage.sol @@ -42,8 +42,8 @@ contract c { // getLengths() -> 0, 0 // setLengths(uint256,uint256): 48, 49 -> // gas irOptimized: 112674 -// gas legacy: 108273 -// gas legacyOptimized: 100269 +// gas legacy: 108272 +// gas legacyOptimized: 100268 // getLengths() -> 48, 49 // setIDStatic(uint256): 11 -> // getID(uint256): 2 -> 11 diff --git a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol index cc009b7e9..ebe2186fd 100644 --- a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol @@ -11,7 +11,7 @@ contract c { // storageEmpty -> 1 // fill() -> // gas irOptimized: 465013 -// gas legacy: 468818 +// gas legacy: 468825 // gas legacyOptimized: 466238 // storageEmpty -> 0 // clear() -> diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol index 817d06c0f..8e9780e33 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_in_constructors.sol @@ -11,9 +11,9 @@ contract Creator { // constructor(): 1, 2, 3, 4 -> // gas irOptimized: 104102 // gas irOptimized code: 22400 -// gas legacy: 115186 +// gas legacy: 115185 // gas legacy code: 59000 -// gas legacyOptimized: 104909 +// gas legacyOptimized: 104908 // gas legacyOptimized code: 23800 // r() -> 4 // ch() -> 3 diff --git a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol index e9517c0e3..f3dea83bf 100644 --- a/test/libsolidity/semanticTests/array/function_array_cross_calls.sol +++ b/test/libsolidity/semanticTests/array/function_array_cross_calls.sol @@ -44,7 +44,7 @@ contract C { // test() -> 5, 6, 7 // gas irOptimized: 86484 // gas irOptimized code: 161200 -// gas legacy: 97576 +// gas legacy: 97551 // gas legacy code: 342800 -// gas legacyOptimized: 87811 +// gas legacyOptimized: 87808 // gas legacyOptimized code: 193000 diff --git a/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol b/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol index 5fd53c6d1..95df74b4d 100644 --- a/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol +++ b/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol @@ -40,7 +40,7 @@ contract C { // copyFromStorageShort() // x() -> 0x20, 3, 0x6162630000000000000000000000000000000000000000000000000000000000 // copyFromStorageLong() -// gas irOptimized: 121104 +// gas irOptimized: 121095 // gas legacy: 121904 // gas legacyOptimized: 121388 // x() -> 0x20, 0x25, 0x3132333435363738393031323334353637383930313233343536373839303132, 0x3334353637000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol b/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol index be1916ef1..96fb11a2d 100644 --- a/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol +++ b/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol @@ -24,6 +24,6 @@ contract c { // ---- // test() -> 1, 2, 3 // gas irOptimized: 1828226 -// gas legacy: 1822466 +// gas legacy: 1822464 // gas legacyOptimized: 1813404 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol b/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol index 73870d428..0c68ab70c 100644 --- a/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol +++ b/test/libsolidity/semanticTests/array/pop/array_pop_uint16_transition.sol @@ -19,6 +19,6 @@ contract c { // ---- // test() -> 38, 28, 18 // gas irOptimized: 148380 -// gas legacy: 151184 +// gas legacy: 151182 // gas legacyOptimized: 142418 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol b/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol index e0fc16581..86165dde2 100644 --- a/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol +++ b/test/libsolidity/semanticTests/array/pop/array_pop_uint24_transition.sol @@ -19,6 +19,6 @@ contract c { // ---- // test() -> 20, 10 // gas irOptimized: 125889 -// gas legacy: 127216 +// gas legacy: 127215 // gas legacyOptimized: 122224 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol index c567c4509..18afa649c 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty.sol @@ -16,7 +16,7 @@ contract c { } // ---- // test() -> true -// gas irOptimized: 138848 -// gas legacy: 178397 +// gas irOptimized: 138795 +// gas legacy: 178396 // gas legacyOptimized: 163832 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol index d9d2d9d2d..cbb10a0a1 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_long_storage_empty_garbage_ref.sol @@ -15,7 +15,7 @@ contract c { } // ---- // test() -> -// gas irOptimized: 113679 -// gas legacy: 131245 +// gas irOptimized: 113631 +// gas legacy: 131256 // gas legacyOptimized: 126668 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol index 490de759b..3ef3571f4 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_masking_long.sol @@ -9,6 +9,6 @@ contract c { } // ---- // test() -> 0x20, 33, 0x303030303030303030303030303030303030303030303030303030303030303, 0x0300000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 106778 -// gas legacy: 121245 +// gas irOptimized: 106762 +// gas legacy: 121252 // gas legacyOptimized: 120370 diff --git a/test/libsolidity/semanticTests/array/push/array_push.sol b/test/libsolidity/semanticTests/array/push/array_push.sol index 6198ba163..b8eab8733 100644 --- a/test/libsolidity/semanticTests/array/push/array_push.sol +++ b/test/libsolidity/semanticTests/array/push/array_push.sol @@ -17,5 +17,5 @@ contract c { // ---- // test() -> 5, 4, 3, 3 // gas irOptimized: 111834 -// gas legacy: 111807 +// gas legacy: 111804 // gas legacyOptimized: 111122 diff --git a/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol b/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol index 4bcac0f13..77ae8c4e2 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol @@ -12,6 +12,6 @@ contract C { } // ---- // f(uint120[]): 0x20, 3, 1, 2, 3 -> 1 -// gas irOptimized: 112853 -// gas legacy: 113659 -// gas legacyOptimized: 113466 +// gas irOptimized: 112852 +// gas legacy: 113657 +// gas legacyOptimized: 113465 diff --git a/test/libsolidity/semanticTests/array/push/array_push_struct.sol b/test/libsolidity/semanticTests/array/push/array_push_struct.sol index b6db507ea..92f071e1f 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_struct.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_struct.sol @@ -21,5 +21,5 @@ contract c { // ---- // test() -> 2, 3, 4, 5 // gas irOptimized: 135329 -// gas legacy: 147443 -// gas legacyOptimized: 146434 +// gas legacy: 147437 +// gas legacyOptimized: 146429 diff --git a/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol b/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol index 37de90cb6..254c14b06 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_struct_from_calldata.sol @@ -17,5 +17,5 @@ contract c { // ---- // test((uint16,uint16,uint16[3],uint16[])): 0x20, 2, 3, 0, 0, 4, 0xC0, 4, 0, 0, 5, 0, 0 -> 2, 3, 4, 5 // gas irOptimized: 137153 -// gas legacy: 142423 -// gas legacyOptimized: 137981 +// gas legacy: 142414 +// gas legacyOptimized: 137975 diff --git a/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol b/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol index 763cb9a04..ffc47eaa3 100644 --- a/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol +++ b/test/libsolidity/semanticTests/array/push/byte_array_push_transition.sol @@ -16,5 +16,5 @@ contract c { // ---- // test() -> 0 // gas irOptimized: 167569 -// gas legacy: 206219 +// gas legacy: 206218 // gas legacyOptimized: 197297 diff --git a/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol b/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol index aeaeb9ee7..5633199d4 100644 --- a/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol +++ b/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol @@ -14,5 +14,5 @@ contract C { // ---- // f() -> // gas irOptimized: 179534 -// gas legacy: 181014 -// gas legacyOptimized: 180398 +// gas legacy: 181013 +// gas legacyOptimized: 180397 diff --git a/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol b/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol index 00e454516..3b35719db 100644 --- a/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol +++ b/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol @@ -28,14 +28,14 @@ contract C { // l() -> 0 // f(uint256,uint256): 42, 64 -> // gas irOptimized: 112288 -// gas legacy: 107920 -// gas legacyOptimized: 101897 +// gas legacy: 107925 +// gas legacyOptimized: 101896 // l() -> 1 // ll(uint256): 0 -> 43 // a(uint256,uint256): 0, 42 -> 64 // f(uint256,uint256): 84, 128 -> // gas irOptimized: 118708 -// gas legacy: 109972 +// gas legacy: 109977 // gas legacyOptimized: 96331 // l() -> 2 // ll(uint256): 1 -> 85 diff --git a/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol b/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol index b013a7ebb..de737593c 100644 --- a/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol +++ b/test/libsolidity/semanticTests/array/push/push_no_args_bytes.sol @@ -22,7 +22,7 @@ contract C { // l() -> 0 // g(uint256): 70 -> // gas irOptimized: 181778 -// gas legacy: 175185 +// gas legacy: 175192 // gas legacyOptimized: 175005 // l() -> 70 // a(uint256): 69 -> left(69) diff --git a/test/libsolidity/semanticTests/array/reusing_memory.sol b/test/libsolidity/semanticTests/array/reusing_memory.sol index 621860c07..fd352dd61 100644 --- a/test/libsolidity/semanticTests/array/reusing_memory.sol +++ b/test/libsolidity/semanticTests/array/reusing_memory.sol @@ -26,7 +26,7 @@ contract Main { // f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1 // gas irOptimized: 99552 // gas irOptimized code: 12400 -// gas legacy: 101554 +// gas legacy: 101551 // gas legacy code: 23600 // gas legacyOptimized: 99612 // gas legacyOptimized code: 13400 diff --git a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol index dab01b598..238f96b7e 100644 --- a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol +++ b/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol @@ -30,8 +30,8 @@ contract C { // constructor() -> // gas irOptimized: 82100 // gas irOptimized code: 357600 -// gas legacy: 101472 -// gas legacy code: 604200 +// gas legacy: 101532 +// gas legacy code: 604800 // gas legacyOptimized: 84956 // gas legacyOptimized code: 391800 // h() -> 0x20, 0x40, 0x00, 0 diff --git a/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol b/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol index 09dcd0347..33ab18450 100644 --- a/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol +++ b/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol @@ -9,7 +9,7 @@ contract c { // EVMVersion: >=byzantium // ---- // (): 1, 2, 3, 4, 5 -> -// gas irOptimized: 155125 +// gas irOptimized: 155122 // gas legacy: 155473 // gas legacyOptimized: 155295 // checkIfDataIsEmpty() -> false diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index 685b1a938..8fe8d36f9 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -26,7 +26,7 @@ contract Creator { // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 // gas irOptimized: 327784 // gas irOptimized code: 94000 -// gas legacy: 336626 +// gas legacy: 336623 // gas legacy code: 244800 -// gas legacyOptimized: 329518 +// gas legacyOptimized: 329515 // gas legacyOptimized code: 117000 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index 0310d58d7..69896ebf1 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -26,7 +26,7 @@ contract Creator { // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" // gas irOptimized: 169292 // gas irOptimized code: 99600 -// gas legacy: 172944 +// gas legacy: 172941 // gas legacy code: 239800 -// gas legacyOptimized: 169818 +// gas legacyOptimized: 169815 // gas legacyOptimized code: 118600 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol index 4194e14a6..036d6ca62 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol @@ -10,9 +10,9 @@ contract Test { // constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> // gas irOptimized: 181465 // gas irOptimized code: 78400 -// gas legacy: 195165 +// gas legacy: 195212 // gas legacy code: 109400 -// gas legacyOptimized: 181609 +// gas legacyOptimized: 181608 // gas legacyOptimized code: 71400 // m_x() -> 7 // m_s() -> 0x20, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" diff --git a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol index 8fa725dad..7d068338b 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol @@ -19,9 +19,9 @@ contract Main { // constructor(): "abc", true // gas irOptimized: 80174 // gas irOptimized code: 24200 -// gas legacy: 85100 +// gas legacy: 85098 // gas legacy code: 58200 -// gas legacyOptimized: 80133 +// gas legacyOptimized: 80132 // gas legacyOptimized code: 22800 // getFlag() -> true // getName() -> "abc" diff --git a/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol index 33650aff6..13abe72c5 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol @@ -17,5 +17,5 @@ contract C { } // ---- // f() -> 16 -// gas legacy: 78482 +// gas legacy: 78477 // gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol index 327c41d9b..5947b2573 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol @@ -11,9 +11,9 @@ contract C { // constructor(): 1, 2, 3, 4 -> // gas irOptimized: 148129 // gas irOptimized code: 23000 -// gas legacy: 157978 +// gas legacy: 157977 // gas legacy code: 60400 -// gas legacyOptimized: 149974 +// gas legacyOptimized: 149973 // gas legacyOptimized code: 26200 // a() -> 1 // b(uint256): 0 -> 2 diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol index e19ad39cf..d5cca6420 100644 --- a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol @@ -11,7 +11,7 @@ contract B is A { // constructor() -> // gas irOptimized: 99436 // gas irOptimized code: 20200 -// gas legacy: 100974 +// gas legacy: 100973 // gas legacy code: 32600 // gas legacyOptimized: 99137 // gas legacyOptimized code: 16200 diff --git a/test/libsolidity/semanticTests/constructor_with_params.sol b/test/libsolidity/semanticTests/constructor_with_params.sol index 1c5a17020..c88802029 100644 --- a/test/libsolidity/semanticTests/constructor_with_params.sol +++ b/test/libsolidity/semanticTests/constructor_with_params.sol @@ -11,7 +11,7 @@ contract C { // constructor(): 2, 0 -> // gas irOptimized: 81170 // gas irOptimized code: 20200 -// gas legacy: 83614 +// gas legacy: 83613 // gas legacy code: 32000 // i() -> 2 // k() -> 0 diff --git a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol b/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol index 29f401a77..decb6fc25 100644 --- a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol +++ b/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol @@ -23,9 +23,9 @@ contract D is B, C { // constructor(): 2, 0 -> // gas irOptimized: 124350 // gas irOptimized code: 27600 -// gas legacy: 128223 +// gas legacy: 128222 // gas legacy code: 40400 -// gas legacyOptimized: 123921 +// gas legacyOptimized: 123920 // gas legacyOptimized code: 20600 // i() -> 2 // j() -> 2 diff --git a/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol b/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol index b0373b74f..097e2f808 100644 --- a/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol +++ b/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol @@ -14,9 +14,9 @@ contract D is C { // constructor(): 2, 0 -> // gas irOptimized: 101581 // gas irOptimized code: 20200 -// gas legacy: 105193 +// gas legacy: 105192 // gas legacy code: 32000 -// gas legacyOptimized: 101504 +// gas legacyOptimized: 101503 // gas legacyOptimized code: 17000 // i() -> 2 // k() -> 1 diff --git a/test/libsolidity/semanticTests/errors/small_error_optimization.sol b/test/libsolidity/semanticTests/errors/small_error_optimization.sol index 0c9cd750a..8128193b7 100644 --- a/test/libsolidity/semanticTests/errors/small_error_optimization.sol +++ b/test/libsolidity/semanticTests/errors/small_error_optimization.sol @@ -16,7 +16,7 @@ contract B { // f() -> FAILURE, hex"92bbf6e8" // gas irOptimized: 221918 // gas irOptimized code: 42800 -// gas legacy: 233746 -// gas legacy code: 37400 -// gas legacyOptimized: 224864 +// gas legacy: 233752 +// gas legacy code: 38000 +// gas legacyOptimized: 224863 // gas legacyOptimized code: 34200 diff --git a/test/libsolidity/semanticTests/events/event_dynamic_array_storage.sol b/test/libsolidity/semanticTests/events/event_dynamic_array_storage.sol index 76acd4a0b..bdd355f68 100644 --- a/test/libsolidity/semanticTests/events/event_dynamic_array_storage.sol +++ b/test/libsolidity/semanticTests/events/event_dynamic_array_storage.sol @@ -14,5 +14,5 @@ contract C { // createEvent(uint256): 42 -> // ~ emit E(uint256[]): 0x20, 0x03, 0x2a, 0x2b, 0x2c // gas irOptimized: 114231 -// gas legacy: 116314 -// gas legacyOptimized: 114408 +// gas legacy: 116313 +// gas legacyOptimized: 114407 diff --git a/test/libsolidity/semanticTests/events/event_dynamic_array_storage_v2.sol b/test/libsolidity/semanticTests/events/event_dynamic_array_storage_v2.sol index bdcda3a09..cecf31b42 100644 --- a/test/libsolidity/semanticTests/events/event_dynamic_array_storage_v2.sol +++ b/test/libsolidity/semanticTests/events/event_dynamic_array_storage_v2.sol @@ -15,5 +15,5 @@ contract C { // createEvent(uint256): 42 -> // ~ emit E(uint256[]): 0x20, 0x03, 0x2a, 0x2b, 0x2c // gas irOptimized: 114231 -// gas legacy: 116314 -// gas legacyOptimized: 114408 +// gas legacy: 116313 +// gas legacyOptimized: 114407 diff --git a/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol b/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol index 324f456f6..1ff58d65b 100644 --- a/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol +++ b/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol @@ -16,5 +16,5 @@ contract C { // createEvent(uint256): 42 -> // ~ emit E(uint256[][]): 0x20, 0x02, 0x40, 0xa0, 0x02, 0x2a, 0x2b, 0x02, 0x2c, 0x2d // gas irOptimized: 185148 -// gas legacy: 187495 -// gas legacyOptimized: 184550 +// gas legacy: 187493 +// gas legacyOptimized: 184548 diff --git a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol index 6a01d0019..61e1bbdd6 100644 --- a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol +++ b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol @@ -17,8 +17,8 @@ contract C { // constructor() -> // gas irOptimized: 113970 // gas irOptimized code: 51400 -// gas legacy: 119776 -// gas legacy code: 125000 +// gas legacy: 119791 +// gas legacy code: 125200 // gas legacyOptimized: 114187 // gas legacyOptimized code: 57400 // deposit(bytes32), 18 wei: 0x1234 -> diff --git a/test/libsolidity/semanticTests/events/event_indexed_string.sol b/test/libsolidity/semanticTests/events/event_indexed_string.sol index 0ad2affe3..2e4b11069 100644 --- a/test/libsolidity/semanticTests/events/event_indexed_string.sol +++ b/test/libsolidity/semanticTests/events/event_indexed_string.sol @@ -17,6 +17,6 @@ contract C { // ---- // deposit() -> // ~ emit E(string,uint256[4]): #0xa7fb06bb999a5eb9aff9e0779953f4e1e4ce58044936c2f51c7fb879b85c08bd, #0xe755d8cc1a8cde16a2a31160dcd8017ac32d7e2f13215b29a23cdae40a78aa81 -// gas irOptimized: 332789 -// gas legacy: 365828 -// gas legacyOptimized: 362250 +// gas irOptimized: 332788 +// gas legacy: 366022 +// gas legacyOptimized: 362429 diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol index a986be149..6e23da855 100644 --- a/test/libsolidity/semanticTests/externalContracts/base64.sol +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -35,8 +35,8 @@ contract test { // constructor() // gas irOptimized: 79076 // gas irOptimized code: 322000 -// gas legacy: 102034 -// gas legacy code: 627400 +// gas legacy: 102214 +// gas legacy code: 629800 // gas legacyOptimized: 87926 // gas legacyOptimized code: 429800 // encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 @@ -55,9 +55,9 @@ contract test { // encode_no_asm(bytes): 0x20, 6, "foobar" -> 0x20, 8, "Zm9vYmFy" // encode_inline_asm_large() // gas irOptimized: 1406025 -// gas legacy: 1554031 +// gas legacy: 1554038 // gas legacyOptimized: 1132031 // encode_no_asm_large() // gas irOptimized: 3512081 -// gas legacy: 4587075 +// gas legacy: 4600082 // gas legacyOptimized: 2813075 diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index 9bfa3a340..c53e49f1f 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -176,10 +176,10 @@ contract DepositContract is IDepositContract, ERC165 { } // ---- // constructor() -// gas irOptimized: 809602 +// gas irOptimized: 809570 // gas irOptimized code: 558000 -// gas legacy: 919945 -// gas legacy code: 1437600 +// gas legacy: 920228 +// gas legacy code: 1438800 // gas legacyOptimized: 848699 // gas legacyOptimized code: 878200 // supportsInterface(bytes4): 0x0 -> 0 @@ -188,26 +188,26 @@ contract DepositContract is IDepositContract, ERC165 { // supportsInterface(bytes4): 0x8564090700000000000000000000000000000000000000000000000000000000 -> true # the deposit interface id # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e // gas irOptimized: 109178 -// gas legacy: 142735 +// gas legacy: 142741 // gas legacyOptimized: 117558 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e // gas irOptimized: 109178 -// gas legacy: 142735 +// gas legacy: 142741 // gas legacyOptimized: 117558 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 // get_deposit_root() -> 0x2089653123d9c721215120b6db6738ba273bbc5228ac093b1f983badcdc8a438 // gas irOptimized: 109174 -// gas legacy: 142744 +// gas legacy: 142750 // gas legacyOptimized: 117570 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 // get_deposit_root() -> 0x40255975859377d912c53aa853245ebd939bdd2b33a28e084babdcc1ed8238ee // gas irOptimized: 109174 -// gas legacy: 142744 +// gas legacy: 142750 // gas legacyOptimized: 117570 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index 4990d24e9..cb345757f 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -50,8 +50,8 @@ contract test { // constructor() // gas irOptimized: 177903 // gas irOptimized code: 1674400 -// gas legacy: 209687 -// gas legacy code: 2204400 +// gas legacy: 209723 +// gas legacy code: 2205000 // gas legacyOptimized: 178012 // gas legacyOptimized code: 1669600 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index 5d95c7a75..5902ba490 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -50,8 +50,8 @@ contract test { // constructor() // gas irOptimized: 170626 // gas irOptimized code: 1577400 -// gas legacy: 195146 -// gas legacy code: 1998400 +// gas legacy: 195206 +// gas legacy code: 1999000 // gas legacyOptimized: 168857 // gas legacyOptimized code: 1556200 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index 1aa72b897..70a3004ac 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -35,11 +35,11 @@ contract test { // constructor() // gas irOptimized: 77816 // gas irOptimized code: 307600 -// gas legacy: 92086 -// gas legacy code: 523000 +// gas legacy: 92110 +// gas legacy code: 523600 // gas legacyOptimized: 82667 // gas legacyOptimized code: 369200 // prb_pi() -> 3141592656369545286 // gas irOptimized: 57478 -// gas legacy: 100947 +// gas legacy: 100657 // gas legacyOptimized: 75735 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index 97d15183a..906279d17 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -294,11 +294,11 @@ contract Test { // f() -> true // g() -> true // pair() -> true -// gas irOptimized: 270424 -// gas legacy: 275206 -// gas legacyOptimized: 266925 +// gas irOptimized: 270409 +// gas legacy: 275219 +// gas legacyOptimized: 266862 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." -// gas irOptimized: 785783 -// gas legacy: 801868 -// gas legacyOptimized: 770942 +// gas irOptimized: 785720 +// gas legacy: 801903 +// gas legacyOptimized: 770941 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 773d7156a..cb9616bbe 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -51,8 +51,8 @@ contract test { // constructor() // gas irOptimized: 95303 // gas irOptimized code: 520000 -// gas legacy: 126106 -// gas legacy code: 930200 +// gas legacy: 126346 +// gas legacy code: 932600 // gas legacyOptimized: 102639 // gas legacyOptimized code: 612400 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 @@ -73,5 +73,5 @@ contract test { // gas legacyOptimized: 27914 // benchmark(string,bytes32): 0x40, 0x0842021, 8, "solidity" -> 0x2020 // gas irOptimized: 1976778 -// gas legacy: 4233999 -// gas legacyOptimized: 2318670 +// gas legacy: 4234020 +// gas legacyOptimized: 2318668 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol index f7c05c10c..08e9f36f5 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol @@ -17,7 +17,7 @@ contract D { // constructor(): 2 -> // gas irOptimized: 138930 // gas irOptimized code: 53800 -// gas legacy: 145570 +// gas legacy: 145569 // gas legacy code: 95600 // gas legacyOptimized: 138297 // gas legacyOptimized code: 54600 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol index 9742a1d2f..320b10563 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol @@ -19,7 +19,7 @@ contract D { // constructor(): 2 -> // gas irOptimized: 139112 // gas irOptimized code: 53800 -// gas legacy: 145936 +// gas legacy: 145935 // gas legacy code: 95600 // gas legacyOptimized: 138529 // gas legacyOptimized code: 54600 diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol index 87f7cbebb..472921c1d 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol @@ -24,10 +24,10 @@ contract C { // constructor(), 1 ether -> // gas irOptimized: 88853 // gas irOptimized code: 164400 -// gas legacy: 102626 -// gas legacy code: 333200 -// gas legacyOptimized: 91599 -// gas legacyOptimized code: 197800 +// gas legacy: 102721 +// gas legacy code: 334400 +// gas legacyOptimized: 91499 +// gas legacyOptimized code: 196400 // f(uint256): 0 -> FAILURE // f(uint256): 1 -> FAILURE // f(uint256): 2 -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol index 9da010e9b..d1b6e8e86 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol @@ -27,10 +27,10 @@ contract C { // constructor(), 1 ether -> // gas irOptimized: 98698 // gas irOptimized code: 284200 -// gas legacy: 123163 -// gas legacy code: 681200 -// gas legacyOptimized: 107069 -// gas legacyOptimized code: 387800 +// gas legacy: 123258 +// gas legacy code: 682400 +// gas legacyOptimized: 106969 +// gas legacyOptimized code: 386400 // f(uint256): 0 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 1 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" // f(uint256): 2 -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" diff --git a/test/libsolidity/semanticTests/functionCall/failed_create.sol b/test/libsolidity/semanticTests/functionCall/failed_create.sol index b6c077753..657b4b5cf 100644 --- a/test/libsolidity/semanticTests/functionCall/failed_create.sol +++ b/test/libsolidity/semanticTests/functionCall/failed_create.sol @@ -29,8 +29,8 @@ contract C { // x() -> 1 // stack(uint256): 1023 -> FAILURE // gas irOptimized: 252410 -// gas legacy: 477722 -// gas legacyOptimized: 299567 +// gas legacy: 476845 +// gas legacyOptimized: 299061 // x() -> 1 // stack(uint256): 10 -> 0x87948bd7ebbe13a00bfd930c93e4828ab18e3908 // x() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index bf6f2c4ba..e6187d06e 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -40,8 +40,8 @@ contract test { // constructor(), 20 wei -> // gas irOptimized: 120218 // gas irOptimized code: 132000 -// gas legacy: 130568 -// gas legacy code: 261000 +// gas legacy: 130583 +// gas legacy code: 261200 // gas legacyOptimized: 121069 // gas legacyOptimized code: 147000 // sendAmount(uint256): 5 -> 5 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol index ebc78a437..41079af03 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol @@ -39,8 +39,8 @@ contract test { // constructor(), 20 wei -> // gas irOptimized: 120218 // gas irOptimized code: 132000 -// gas legacy: 130568 -// gas legacy code: 261000 +// gas legacy: 130583 +// gas legacy code: 261200 // gas legacyOptimized: 121069 // gas legacyOptimized code: 147000 // sendAmount(uint256): 5 -> 5 diff --git a/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol b/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol index 7a9bf6014..7505e20cc 100644 --- a/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol +++ b/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol @@ -19,8 +19,8 @@ contract test { // ---- // set(uint8,uint8,uint8,uint8,uint8): 1, 21, 22, 42, 43 -> 0, 0, 0, 0 // gas irOptimized: 111237 -// gas legacy: 113748 -// gas legacyOptimized: 111772 +// gas legacy: 113742 +// gas legacyOptimized: 111768 // get(uint8): 1 -> 21, 22, 42, 43 // set(uint8,uint8,uint8,uint8,uint8): 1, 10, 30, 11, 31 -> 21, 22, 42, 43 // get(uint8): 1 -> 10, 30, 11, 31 diff --git a/test/libsolidity/semanticTests/functionTypes/store_function.sol b/test/libsolidity/semanticTests/functionTypes/store_function.sol index 5397d0b70..eeab740aa 100644 --- a/test/libsolidity/semanticTests/functionTypes/store_function.sol +++ b/test/libsolidity/semanticTests/functionTypes/store_function.sol @@ -26,7 +26,7 @@ contract C { // ---- // t() -> 9 // gas irOptimized: 99064 -// gas legacy: 79495 +// gas legacy: 79492 // gas legacy code: 69600 -// gas legacyOptimized: 77588 +// gas legacyOptimized: 77587 // gas legacyOptimized code: 28600 diff --git a/test/libsolidity/semanticTests/immutable/multi_creation.sol b/test/libsolidity/semanticTests/immutable/multi_creation.sol index e1eb0621a..aa8a1ad8a 100644 --- a/test/libsolidity/semanticTests/immutable/multi_creation.sol +++ b/test/libsolidity/semanticTests/immutable/multi_creation.sol @@ -29,9 +29,9 @@ contract C { // f() -> 3, 7, 5 // gas irOptimized: 86796 // gas irOptimized code: 37200 -// gas legacy: 87728 +// gas legacy: 87727 // gas legacy code: 60800 -// gas legacyOptimized: 86771 +// gas legacyOptimized: 86770 // gas legacyOptimized code: 37200 // x() -> 7 // y() -> 5 diff --git a/test/libsolidity/semanticTests/immutable/use_scratch.sol b/test/libsolidity/semanticTests/immutable/use_scratch.sol index 2ee05af91..432c3c207 100644 --- a/test/libsolidity/semanticTests/immutable/use_scratch.sol +++ b/test/libsolidity/semanticTests/immutable/use_scratch.sol @@ -17,7 +17,7 @@ contract C { // constructor(): 3 -> // gas irOptimized: 81194 // gas irOptimized code: 42400 -// gas legacy: 88245 +// gas legacy: 88244 // gas legacy code: 109400 // gas legacyOptimized: 81858 // gas legacyOptimized code: 55800 diff --git a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol index 0567c2ab1..f64a2e12a 100644 --- a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol +++ b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol @@ -23,5 +23,5 @@ contract B { // ---- // g() -> 42 // gas irOptimized: 80813 -// gas legacy: 55871 +// gas legacy: 55868 // gas legacy code: 66600 diff --git a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol index 5234c27ad..07beb2c53 100644 --- a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol +++ b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol @@ -23,7 +23,7 @@ contract B { // ---- // g() -> 42 // gas irOptimized: 100282 -// gas legacy: 56840 +// gas legacy: 56839 // gas legacy code: 123600 -// gas legacyOptimized: 55002 +// gas legacyOptimized: 55001 // gas legacyOptimized code: 60600 diff --git a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol index e704a297b..b9697c5ae 100644 --- a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol +++ b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol @@ -19,8 +19,8 @@ contract A { } // ---- // g(int256): -1 -> -1 -// gas legacy: 77878 +// gas legacy: 77876 // gas legacy code: 24200 // g(int256): 10 -> 10 -// gas legacy: 77506 +// gas legacy: 77504 // gas legacy code: 24200 diff --git a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol index fdd0bafaa..39b25c005 100644 --- a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol +++ b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol @@ -41,9 +41,9 @@ contract Main { // constructor(), 22 wei -> // gas irOptimized: 143864 // gas irOptimized code: 118000 -// gas legacy: 156586 -// gas legacy code: 236200 -// gas legacyOptimized: 143593 +// gas legacy: 156599 +// gas legacy code: 236400 +// gas legacyOptimized: 143592 // gas legacyOptimized code: 118000 // getFlag() -> true // getName() -> "abc" diff --git a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol index a37520725..c2066ef8b 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol @@ -42,13 +42,13 @@ contract D { // constructor() -> // gas irOptimized: 127596 // gas irOptimized code: 221000 -// gas legacy: 149357 -// gas legacy code: 499800 -// gas legacyOptimized: 125830 -// gas legacyOptimized code: 203200 +// gas legacy: 149480 +// gas legacy code: 501200 +// gas legacyOptimized: 125846 +// gas legacyOptimized code: 203400 // destroy() -> // createAndDestroy() -> -// gas legacy: 67044 +// gas legacy: 67048 // gas legacy code: 92600 -// gas legacyOptimized: 65675 +// gas legacyOptimized: 65677 // gas legacyOptimized code: 39400 diff --git a/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol b/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol index d64c7dfb5..4e4f30a75 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/tstore_hidden_staticcall.sol @@ -19,5 +19,5 @@ contract C { // ---- // test() -> FAILURE // gas irOptimized: 98437877 -// gas legacy: 98437872 -// gas legacyOptimized: 98437873 +// gas legacy: 98437871 +// gas legacyOptimized: 98437872 diff --git a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol index 8ec19fffa..1240a8251 100644 --- a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol +++ b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol @@ -18,7 +18,7 @@ contract ClientReceipt { // constructor(), 2000 wei -> // gas irOptimized: 114353 // gas irOptimized code: 58800 -// gas legacy: 118618 +// gas legacy: 118617 // gas legacy code: 111400 // gas legacyOptimized: 114067 // gas legacyOptimized code: 59800 diff --git a/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol b/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol index 817118473..d59cedfdc 100644 --- a/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol +++ b/test/libsolidity/semanticTests/libraries/internal_types_in_library.sol @@ -23,5 +23,5 @@ contract Test { // library: Lib // f() -> 4, 0x11 // gas irOptimized: 111419 -// gas legacy: 132935 -// gas legacyOptimized: 118023 +// gas legacy: 132930 +// gas legacyOptimized: 118020 diff --git a/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol b/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol index bbdc92047..17406a907 100644 --- a/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol +++ b/test/libsolidity/semanticTests/libraries/using_library_mappings_public.sol @@ -20,5 +20,5 @@ contract Test { // library: Lib // f() -> 1, 0, 0x2a, 0x17, 0, 0x63 // gas irOptimized: 119837 -// gas legacy: 124674 -// gas legacyOptimized: 119669 +// gas legacy: 124661 +// gas legacyOptimized: 119665 diff --git a/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol b/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol index 98cdf4fd1..6e852fdce 100644 --- a/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol +++ b/test/libsolidity/semanticTests/libraries/using_library_mappings_return.sol @@ -18,5 +18,5 @@ contract Test { // library: Lib // f() -> 1, 0, 0x2a, 0x17, 0, 0x63 // gas irOptimized: 119568 -// gas legacy: 125109 -// gas legacyOptimized: 120128 +// gas legacy: 125087 +// gas legacyOptimized: 120120 diff --git a/test/libsolidity/semanticTests/libraries/using_library_structs.sol b/test/libsolidity/semanticTests/libraries/using_library_structs.sol index e709a5b5b..c2ecf1036 100644 --- a/test/libsolidity/semanticTests/libraries/using_library_structs.sol +++ b/test/libsolidity/semanticTests/libraries/using_library_structs.sol @@ -21,4 +21,4 @@ contract Test { // library: Lib // f() -> 7, 8 // gas irOptimized: 101818 -// gas legacy: 101429 +// gas legacy: 101428 diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol index a621b4c12..ec41099ee 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol @@ -53,13 +53,13 @@ contract C { // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 -// gas legacy: 56981 +// gas legacy: 56978 // gas legacy code: 127000 -// gas legacyOptimized: 55163 +// gas legacyOptimized: 55161 // gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 // gas irOptimized: 102386 -// gas legacy: 56239 +// gas legacy: 56238 // gas legacy code: 127000 // gas legacyOptimized: 54851 // gas legacyOptimized code: 68400 diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol index 84f6bf08e..7e70eb091 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol @@ -59,13 +59,13 @@ contract C { // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 -// gas legacy: 56981 +// gas legacy: 56978 // gas legacy code: 127000 -// gas legacyOptimized: 55163 +// gas legacyOptimized: 55161 // gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 // gas irOptimized: 102386 -// gas legacy: 56239 +// gas legacy: 56238 // gas legacy code: 127000 // gas legacyOptimized: 54851 // gas legacyOptimized code: 68400 diff --git a/test/libsolidity/semanticTests/salted_create/prediction_example.sol b/test/libsolidity/semanticTests/salted_create/prediction_example.sol index 751747293..7d0e3c8b0 100644 --- a/test/libsolidity/semanticTests/salted_create/prediction_example.sol +++ b/test/libsolidity/semanticTests/salted_create/prediction_example.sol @@ -26,5 +26,5 @@ contract C { // compileViaYul: also // ---- // createDSalted(bytes32,uint256): 42, 64 -> -// gas legacy: 78574 +// gas legacy: 78573 // gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol index 083c9a5e4..25d193577 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol @@ -23,7 +23,7 @@ contract A { // f(), 10 ether -> 3007, 3008, 3009 // gas irOptimized: 187022 // gas irOptimized code: 67200 -// gas legacy: 190863 +// gas legacy: 190858 // gas legacy code: 190200 -// gas legacyOptimized: 187258 +// gas legacyOptimized: 187256 // gas legacyOptimized code: 92400 diff --git a/test/libsolidity/semanticTests/smoke/constructor.sol b/test/libsolidity/semanticTests/smoke/constructor.sol index 2783fe4a8..d5c5280ae 100644 --- a/test/libsolidity/semanticTests/smoke/constructor.sol +++ b/test/libsolidity/semanticTests/smoke/constructor.sol @@ -14,9 +14,9 @@ contract C { // constructor(), 2 wei: 3 -> // gas irOptimized: 78996 // gas irOptimized code: 25400 -// gas legacy: 83056 +// gas legacy: 83055 // gas legacy code: 65200 -// gas legacyOptimized: 78899 +// gas legacyOptimized: 78898 // gas legacyOptimized code: 27800 // state() -> 3 // balance() -> 2 diff --git a/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol b/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol index 0c2f54b9e..8a795373e 100644 --- a/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol +++ b/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol @@ -22,7 +22,7 @@ contract Test { // set(bytes): 0x20, 0 // storageEmpty -> 1 // set(bytes): 0x20, 66, "12345678901234567890123456789012", "12345678901234567890123456789012", "12" -// gas irOptimized: 111852 +// gas irOptimized: 111849 // gas legacy: 112734 // gas legacyOptimized: 112084 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol b/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol index 75edb1c9e..7d19bc471 100644 --- a/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol +++ b/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol @@ -43,5 +43,5 @@ contract C { // ---- // test() -> true // gas irOptimized: 132633 -// gas legacy: 136009 +// gas legacy: 136010 // gas legacyOptimized: 133478 diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol index ebf546fe2..276748613 100644 --- a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol +++ b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol @@ -17,5 +17,5 @@ contract C { // ---- // f(uint32,(uint128,uint256[][2],uint32)): 55, 0x40, 77, 0x60, 88, 0x40, 0x40, 2, 1, 2 -> 55, 77, 1, 2, 88 // gas irOptimized: 202902 -// gas legacy: 207384 -// gas legacyOptimized: 203588 +// gas legacy: 207376 +// gas legacyOptimized: 203583 diff --git a/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol b/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol index 4465b1a3e..8ec31a5c1 100644 --- a/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol +++ b/test/libsolidity/semanticTests/structs/conversion/recursive_storage_memory.sol @@ -24,5 +24,5 @@ contract CopyTest { // ---- // run() -> 2, 23, 42 // gas irOptimized: 192828 -// gas legacy: 185731 -// gas legacyOptimized: 184458 +// gas legacy: 185730 +// gas legacyOptimized: 184457 diff --git a/test/libsolidity/semanticTests/structs/copy_from_mapping.sol b/test/libsolidity/semanticTests/structs/copy_from_mapping.sol index a072fb057..037ff2067 100644 --- a/test/libsolidity/semanticTests/structs/copy_from_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_from_mapping.sol @@ -37,7 +37,7 @@ contract C { // ---- // to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 121282 -// gas legacy: 122978 +// gas legacy: 122977 // gas legacyOptimized: 121652 // to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 diff --git a/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol b/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol index 29e7afca3..600eb35ab 100644 --- a/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol +++ b/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol @@ -88,8 +88,8 @@ contract Test { // ---- // test1() -> true // gas irOptimized: 152965 -// gas legacy: 153012 -// gas legacyOptimized: 152637 +// gas legacy: 153010 +// gas legacyOptimized: 152636 // test2() -> true // test3() -> true // test4() -> true diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol index 61d2d68aa..7188e1bef 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol @@ -45,7 +45,7 @@ contract C { // ---- // to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 121454 -// gas legacy: 123117 +// gas legacy: 123114 // gas legacyOptimized: 121659 // to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol index 7d458ca29..54b659ba0 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol @@ -53,13 +53,13 @@ contract C { // ---- // from_memory() -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 122720 -// gas legacy: 130136 -// gas legacyOptimized: 128649 +// gas legacy: 130131 +// gas legacyOptimized: 128648 // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 121424 -// gas legacy: 123191 -// gas legacyOptimized: 121764 +// gas legacy: 123190 +// gas legacyOptimized: 121758 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 114852 -// gas legacy: 122425 -// gas legacyOptimized: 120700 +// gas legacy: 122423 +// gas legacyOptimized: 120698 diff --git a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol index 068dc3d8c..d020998b4 100644 --- a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol @@ -46,17 +46,17 @@ contract C { // ---- // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 121515 -// gas legacy: 123053 +// gas legacy: 123051 // gas legacyOptimized: 121704 // from_storage() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 121559 -// gas legacy: 123102 +// gas legacy: 123109 // gas legacyOptimized: 121756 // from_memory() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 122740 -// gas legacy: 129997 -// gas legacyOptimized: 128645 +// gas legacy: 129996 +// gas legacyOptimized: 128644 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 21, 3, 0x666f6f0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 114824 -// gas legacy: 118210 -// gas legacyOptimized: 115329 +// gas legacy: 118207 +// gas legacyOptimized: 115327 diff --git a/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol b/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol index 5ba976541..6785f2108 100644 --- a/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol +++ b/test/libsolidity/semanticTests/structs/memory_structs_nested_load.sol @@ -67,6 +67,6 @@ contract Test { // ---- // load() -> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 // gas irOptimized: 110772 -// gas legacy: 112964 +// gas legacy: 112959 // gas legacyOptimized: 110876 // store() -> 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 diff --git a/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol b/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol index 955e082b7..e50265e51 100644 --- a/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol +++ b/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol @@ -23,17 +23,17 @@ contract c { // ---- // storageEmpty -> 1 // set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true -// gas irOptimized: 133560 -// gas legacy: 134628 -// gas legacyOptimized: 133858 +// gas irOptimized: 133557 +// gas legacy: 134624 +// gas legacyOptimized: 133856 // test(uint256): 32 -> "3" // storageEmpty -> 0 // copy() -> true // storageEmpty -> 1 // set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true -// gas irOptimized: 133560 -// gas legacy: 134628 -// gas legacyOptimized: 133858 +// gas irOptimized: 133557 +// gas legacy: 134624 +// gas legacyOptimized: 133856 // storageEmpty -> 0 // del() -> true // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/structs/struct_copy.sol b/test/libsolidity/semanticTests/structs/struct_copy.sol index 1fb9ef216..e148f81cc 100644 --- a/test/libsolidity/semanticTests/structs/struct_copy.sol +++ b/test/libsolidity/semanticTests/structs/struct_copy.sol @@ -36,13 +36,13 @@ contract c { // ---- // set(uint256): 7 -> true // gas irOptimized: 109932 -// gas legacy: 110597 +// gas legacy: 110593 // gas legacyOptimized: 110003 // retrieve(uint256): 7 -> 1, 3, 4, 2 // copy(uint256,uint256): 7, 8 -> true // gas irOptimized: 118581 -// gas legacy: 119147 -// gas legacyOptimized: 118619 +// gas legacy: 119144 +// gas legacyOptimized: 118618 // retrieve(uint256): 7 -> 1, 3, 4, 2 // retrieve(uint256): 8 -> 1, 3, 4, 2 // copy(uint256,uint256): 0, 7 -> true diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol index 28998df44..cea110566 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol @@ -42,10 +42,10 @@ contract C { } // ---- // f() -> -// gas irOptimized: 113477 +// gas irOptimized: 113465 // gas legacy: 113591 -// gas legacyOptimized: 113103 +// gas legacyOptimized: 113098 // g() -> -// gas irOptimized: 118843 +// gas irOptimized: 118828 // gas legacy: 118764 -// gas legacyOptimized: 118172 +// gas legacyOptimized: 118168 diff --git a/test/libsolidity/semanticTests/structs/struct_memory_to_storage_function_ptr.sol b/test/libsolidity/semanticTests/structs/struct_memory_to_storage_function_ptr.sol index bd9fcf3e2..0de21947a 100644 --- a/test/libsolidity/semanticTests/structs/struct_memory_to_storage_function_ptr.sol +++ b/test/libsolidity/semanticTests/structs/struct_memory_to_storage_function_ptr.sol @@ -29,5 +29,5 @@ contract C { // ---- // f() -> 42, 23, 34, 42, 42 // gas irOptimized: 110682 -// gas legacy: 111993 +// gas legacy: 111990 // gas legacyOptimized: 110546 diff --git a/test/libsolidity/semanticTests/structs/structs.sol b/test/libsolidity/semanticTests/structs/structs.sol index 190387051..96503fa11 100644 --- a/test/libsolidity/semanticTests/structs/structs.sol +++ b/test/libsolidity/semanticTests/structs/structs.sol @@ -31,6 +31,6 @@ contract test { // check() -> false // set() -> // gas irOptimized: 134073 -// gas legacy: 135246 +// gas legacy: 135243 // gas legacyOptimized: 134062 // check() -> true diff --git a/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol b/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol index 19c31f288..26e8294e3 100644 --- a/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol +++ b/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol @@ -30,5 +30,5 @@ contract C { // ---- // f() -> 0x20, 7, 8, 9, 0xa0, 13, 2, 0x40, 0xa0, 2, 3, 4, 2, 3, 4 // gas irOptimized: 197102 -// gas legacy: 199891 +// gas legacy: 199887 // gas legacyOptimized: 196845 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol index 1433386e5..015d51c1f 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol @@ -49,12 +49,12 @@ contract C { } // ---- // test_f() -> true -// gas irOptimized: 122212 -// gas legacy: 125322 -// gas legacyOptimized: 122694 +// gas irOptimized: 122201 +// gas legacy: 125333 +// gas legacyOptimized: 122693 // test_g() -> true -// gas irOptimized: 106428 -// gas legacy: 111120 +// gas irOptimized: 106408 +// gas legacy: 111133 // gas legacyOptimized: 106925 // addresses(uint256): 0 -> 0x18 // addresses(uint256): 1 -> 0x19 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol index 30aa590d6..0e0759d62 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol @@ -115,7 +115,7 @@ contract ERC20 { // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 // gas irOptimized: 121322 // gas irOptimized code: 234600 -// gas legacy: 163352 +// gas legacy: 163350 // gas legacy code: 671400 // gas legacyOptimized: 127464 // gas legacyOptimized code: 285400 diff --git a/test/libsolidity/semanticTests/using/using_global_invisible.sol b/test/libsolidity/semanticTests/using/using_global_invisible.sol index 818707f6f..197198013 100644 --- a/test/libsolidity/semanticTests/using/using_global_invisible.sol +++ b/test/libsolidity/semanticTests/using/using_global_invisible.sol @@ -40,5 +40,5 @@ contract D { // ---- // library: "A":L // test() -> 3 -// gas legacy: 59681 +// gas legacy: 59680 // gas legacy code: 61200 diff --git a/test/libsolidity/semanticTests/various/address_code.sol b/test/libsolidity/semanticTests/various/address_code.sol index 8b601ca8c..549512eb3 100644 --- a/test/libsolidity/semanticTests/various/address_code.sol +++ b/test/libsolidity/semanticTests/various/address_code.sol @@ -16,7 +16,7 @@ contract C { // constructor() -> // gas irOptimized: 70760 // gas irOptimized code: 94600 -// gas legacy: 82380 +// gas legacy: 82428 // gas legacy code: 153800 // gas legacyOptimized: 69400 // gas legacyOptimized code: 79200 diff --git a/test/libsolidity/semanticTests/various/code_access_content.sol b/test/libsolidity/semanticTests/various/code_access_content.sol index dc4e49b2d..22ceff337 100644 --- a/test/libsolidity/semanticTests/various/code_access_content.sol +++ b/test/libsolidity/semanticTests/various/code_access_content.sol @@ -38,8 +38,8 @@ contract C { } // ---- // testRuntime() -> true -// gas legacy: 76577 +// gas legacy: 76575 // gas legacy code: 23600 // testCreation() -> true -// gas legacy: 77000 +// gas legacy: 76999 // gas legacy code: 23600 diff --git a/test/libsolidity/semanticTests/various/code_access_create.sol b/test/libsolidity/semanticTests/various/code_access_create.sol index d2b7f92f4..f5f0b8644 100644 --- a/test/libsolidity/semanticTests/various/code_access_create.sol +++ b/test/libsolidity/semanticTests/various/code_access_create.sol @@ -23,5 +23,5 @@ contract C { } // ---- // test() -> 7 -// gas legacy: 76649 +// gas legacy: 76647 // gas legacy code: 24200 diff --git a/test/libsolidity/semanticTests/various/code_access_runtime.sol b/test/libsolidity/semanticTests/various/code_access_runtime.sol index b62eb0b85..10d7c1852 100644 --- a/test/libsolidity/semanticTests/various/code_access_runtime.sol +++ b/test/libsolidity/semanticTests/various/code_access_runtime.sol @@ -23,5 +23,5 @@ contract C { // EVMVersion: >=constantinople // ---- // test() -> 42 -// gas legacy: 76035 +// gas legacy: 76034 // gas legacy code: 24200 diff --git a/test/libsolidity/semanticTests/various/code_length.sol b/test/libsolidity/semanticTests/various/code_length.sol index c30ac838f..844a0f657 100644 --- a/test/libsolidity/semanticTests/various/code_length.sol +++ b/test/libsolidity/semanticTests/various/code_length.sol @@ -59,6 +59,6 @@ contract C { } // ---- // constructor() -// gas legacy: 66936 -// gas legacy code: 57200 +// gas legacy: 66989 +// gas legacy code: 57800 // f(): true, true -> true, true diff --git a/test/libsolidity/semanticTests/various/create_calldata.sol b/test/libsolidity/semanticTests/various/create_calldata.sol index 3ca50db13..a5f61d2dd 100644 --- a/test/libsolidity/semanticTests/various/create_calldata.sol +++ b/test/libsolidity/semanticTests/various/create_calldata.sol @@ -10,7 +10,7 @@ contract C { // constructor(): 42 -> // gas irOptimized: 68239 // gas irOptimized code: 69000 -// gas legacy: 78029 +// gas legacy: 78076 // gas legacy code: 90200 // gas legacyOptimized: 68321 // gas legacyOptimized code: 64600 diff --git a/test/libsolidity/semanticTests/various/destructuring_assignment.sol b/test/libsolidity/semanticTests/various/destructuring_assignment.sol index 82183a112..a961870ee 100644 --- a/test/libsolidity/semanticTests/various/destructuring_assignment.sol +++ b/test/libsolidity/semanticTests/various/destructuring_assignment.sol @@ -34,5 +34,5 @@ contract C { // ---- // f(bytes): 0x20, 0x5, "abcde" -> 0 // gas irOptimized: 242027 -// gas legacy: 243284 -// gas legacyOptimized: 242395 +// gas legacy: 243281 +// gas legacyOptimized: 242392 diff --git a/test/libsolidity/semanticTests/various/erc20.sol b/test/libsolidity/semanticTests/various/erc20.sol index 1a7718f68..1cc77270f 100644 --- a/test/libsolidity/semanticTests/various/erc20.sol +++ b/test/libsolidity/semanticTests/various/erc20.sol @@ -98,7 +98,7 @@ contract ERC20 { // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 // gas irOptimized: 121632 // gas irOptimized code: 236800 -// gas legacy: 159959 +// gas legacy: 159957 // gas legacy code: 647600 // gas legacyOptimized: 126934 // gas legacyOptimized code: 282000 diff --git a/test/libsolidity/semanticTests/various/external_types_in_calls.sol b/test/libsolidity/semanticTests/various/external_types_in_calls.sol index aff302d26..84e4d36d5 100644 --- a/test/libsolidity/semanticTests/various/external_types_in_calls.sol +++ b/test/libsolidity/semanticTests/various/external_types_in_calls.sol @@ -25,5 +25,5 @@ contract C { // ---- // test() -> 9, 7 // gas legacy: 80314 -// gas legacy code: 47200 +// gas legacy code: 47400 // t2() -> 9 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol index 263da7133..4cb5c8c71 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol @@ -66,8 +66,8 @@ contract D { // constructor(), 1 ether -> // gas irOptimized: 67028 // gas irOptimized code: 175400 -// gas legacy: 76163 -// gas legacy code: 297400 +// gas legacy: 76227 +// gas legacy code: 298200 // gas legacyOptimized: 66516 // gas legacyOptimized code: 168000 // exists() -> false diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol index 690bff8d5..a58264919 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol @@ -37,8 +37,8 @@ contract D { // constructor(), 2 ether -> // gas irOptimized: 108104 // gas irOptimized code: 119200 -// gas legacy: 120424 -// gas legacy code: 253600 +// gas legacy: 120439 +// gas legacy code: 253800 // gas legacyOptimized: 109015 // gas legacyOptimized code: 130800 // balance: 0x1111111111111111111111111111111111111111 -> 0 @@ -48,7 +48,7 @@ contract D { // test_deploy_and_terminate_twice() -> // gas irOptimized: 121395 // gas irOptimized code: 14000 -// gas legacy: 122384 +// gas legacy: 122386 // gas legacy code: 43200 // gas legacyOptimized: 121596 // gas legacyOptimized code: 22800 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol index 1ae89a558..dd550d31a 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol @@ -84,8 +84,8 @@ contract D { // constructor(), 1 ether -> // gas irOptimized: 132974 // gas irOptimized code: 293800 -// gas legacy: 151217 -// gas legacy code: 533400 +// gas legacy: 151236 +// gas legacy code: 533800 // gas legacyOptimized: 131436 // gas legacyOptimized code: 276600 // exists() -> false @@ -95,7 +95,7 @@ contract D { // gas irOptimized code: 20800 // gas legacy: 97788 // gas legacy code: 20800 -// gas legacyOptimized: 96044 +// gas legacyOptimized: 96043 // gas legacyOptimized code: 20800 // exists() -> false // deploy_create2() -> @@ -107,5 +107,5 @@ contract D { // exists() -> true // deploy_create2() -> FAILURE // gas irOptimized: 96903654 -// gas legacy: 96903660 -// gas legacyOptimized: 96903641 +// gas legacy: 96903658 +// gas legacyOptimized: 96903639 diff --git a/test/libsolidity/semanticTests/various/senders_balance.sol b/test/libsolidity/semanticTests/various/senders_balance.sol index 5b4371149..fff16befe 100644 --- a/test/libsolidity/semanticTests/various/senders_balance.sol +++ b/test/libsolidity/semanticTests/various/senders_balance.sol @@ -18,7 +18,7 @@ contract D { // constructor(), 27 wei -> // gas irOptimized: 114057 // gas irOptimized code: 53800 -// gas legacy: 117835 +// gas legacy: 117834 // gas legacy code: 100600 // gas legacyOptimized: 113676 // gas legacyOptimized code: 53600 diff --git a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol index 9d078cfd6..8430da4e8 100644 --- a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol +++ b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol @@ -20,5 +20,5 @@ contract C { // ---- // g() -> 2, 6 // gas irOptimized: 178195 -// gas legacy: 180657 -// gas legacyOptimized: 179146 +// gas legacy: 180653 +// gas legacyOptimized: 179144 diff --git a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol index 2063fff7a..2a9834aab 100644 --- a/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol +++ b/test/libsolidity/semanticTests/various/staticcall_for_view_and_pure.sol @@ -40,14 +40,14 @@ contract D { // fview() -> FAILURE // gas irOptimized: 98425388 // gas irOptimized code: 13200 -// gas legacy: 98413174 +// gas legacy: 98413173 // gas legacy code: 25600 -// gas legacyOptimized: 98425380 +// gas legacyOptimized: 98425379 // gas legacyOptimized code: 13200 // fpure() -> FAILURE // gas irOptimized: 98425388 // gas irOptimized code: 13200 -// gas legacy: 98413174 +// gas legacy: 98413173 // gas legacy code: 25600 -// gas legacyOptimized: 98425380 +// gas legacyOptimized: 98425379 // gas legacyOptimized code: 13200 diff --git a/test/libsolidity/semanticTests/various/swap_in_storage_overwrite.sol b/test/libsolidity/semanticTests/various/swap_in_storage_overwrite.sol index bd5a59519..3422c8121 100644 --- a/test/libsolidity/semanticTests/various/swap_in_storage_overwrite.sol +++ b/test/libsolidity/semanticTests/various/swap_in_storage_overwrite.sol @@ -27,7 +27,7 @@ contract c { // y() -> 0, 0 // set() -> // gas irOptimized: 109684 -// gas legacy: 109728 +// gas legacy: 109727 // gas legacyOptimized: 109680 // x() -> 1, 2 // y() -> 3, 4 diff --git a/test/libsolidity/semanticTests/various/value_complex.sol b/test/libsolidity/semanticTests/various/value_complex.sol index dc92e38df..4639d34c7 100644 --- a/test/libsolidity/semanticTests/various/value_complex.sol +++ b/test/libsolidity/semanticTests/various/value_complex.sol @@ -21,8 +21,8 @@ contract test { // constructor(), 20 wei -> // gas irOptimized: 114463 // gas irOptimized code: 58800 -// gas legacy: 120076 -// gas legacy code: 132200 +// gas legacy: 120091 +// gas legacy code: 132400 // gas legacyOptimized: 114536 // gas legacyOptimized code: 65800 // sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/semanticTests/various/value_insane.sol b/test/libsolidity/semanticTests/various/value_insane.sol index ad0e95701..bc6a803de 100644 --- a/test/libsolidity/semanticTests/various/value_insane.sol +++ b/test/libsolidity/semanticTests/various/value_insane.sol @@ -20,7 +20,7 @@ contract test { // constructor(), 20 wei -> // gas irOptimized: 114527 // gas irOptimized code: 59600 -// gas legacy: 120200 +// gas legacy: 120199 // gas legacy code: 133600 // gas legacyOptimized: 114568 // gas legacyOptimized code: 66200 diff --git a/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol b/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol index fbaa7789e..0db482c04 100644 --- a/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol +++ b/test/libsolidity/semanticTests/viaYul/copy_struct_invalid_ir_bug.sol @@ -21,6 +21,6 @@ contract C { } // ---- // f() -> -// gas irOptimized: 113118 -// gas legacy: 112890 +// gas irOptimized: 113117 +// gas legacy: 112888 // gas legacyOptimized: 112580 diff --git a/test/libyul/objectCompiler/datacopy.yul b/test/libyul/objectCompiler/datacopy.yul index cb9fbcb18..719b109f1 100644 --- a/test/libyul/objectCompiler/datacopy.yul +++ b/test/libyul/objectCompiler/datacopy.yul @@ -33,7 +33,7 @@ object "a" { // /* "source":153:170 */ // 0x00 // /* "source":150:151 */ -// dup1 +// 0x00 // /* "source":143:171 */ // sstore // /* "source":188:205 */ @@ -47,6 +47,6 @@ object "a" { // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // } -// Bytecode: 6009600b5f3960095ff3fe5f8055600d5f5200fe -// Opcodes: PUSH1 0x9 PUSH1 0xB PUSH0 CODECOPY PUSH1 0x9 PUSH0 RETURN INVALID PUSH0 DUP1 SSTORE PUSH1 0xD PUSH0 MSTORE STOP INVALID +// Bytecode: 6009600b5f3960095ff3fe5f5f55600d5f5200fe +// Opcodes: PUSH1 0x9 PUSH1 0xB PUSH0 CODECOPY PUSH1 0x9 PUSH0 RETURN INVALID PUSH0 PUSH0 SSTORE PUSH1 0xD PUSH0 MSTORE STOP INVALID // SourceMappings: 57:15:0:-:0;38:17;35:1;26:47;88:15;85:1;78:26 diff --git a/test/libyul/objectCompiler/dataoffset_self.yul b/test/libyul/objectCompiler/dataoffset_self.yul index 7c38b9502..ae123ba49 100644 --- a/test/libyul/objectCompiler/dataoffset_self.yul +++ b/test/libyul/objectCompiler/dataoffset_self.yul @@ -7,13 +7,13 @@ object "a" { // /* "source":32:47 */ // 0x00 // /* "source":29:30 */ -// dup1 +// 0x00 // /* "source":22:48 */ // sstore // /* "source":20:50 */ // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 -// Bytecode: 5f805500fe -// Opcodes: PUSH0 DUP1 SSTORE STOP INVALID +// Bytecode: 5f5f5500fe +// Opcodes: PUSH0 PUSH0 SSTORE STOP INVALID // SourceMappings: 32:15:0:-:0;29:1;22:26;20:30 diff --git a/test/libyul/objectCompiler/sourceLocations.yul b/test/libyul/objectCompiler/sourceLocations.yul index 883e85b04..d9f1d84fc 100644 --- a/test/libyul/objectCompiler/sourceLocations.yul +++ b/test/libyul/objectCompiler/sourceLocations.yul @@ -41,15 +41,13 @@ object "a" { // // sub_0: assembly { // /* "def.sol":70:72 */ -// 0x00 -// dup1 -// sstore +// sstore(0x00, 0x00) // /* "abc.sol":2:5 */ // mstore(0x00, 0x0d) // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // } -// Bytecode: 6009600b5f3960095ff3fe5f8055600d5f5200fe -// Opcodes: PUSH1 0x9 PUSH1 0xB PUSH0 CODECOPY PUSH1 0x9 PUSH0 RETURN INVALID PUSH0 DUP1 SSTORE PUSH1 0xD PUSH0 MSTORE STOP INVALID +// Bytecode: 6009600b5f3960095ff3fe5f5f55600d5f5200fe +// Opcodes: PUSH1 0x9 PUSH1 0xB PUSH0 CODECOPY PUSH1 0x9 PUSH0 RETURN INVALID PUSH0 PUSH0 SSTORE PUSH1 0xD PUSH0 MSTORE STOP INVALID // SourceMappings: 0:2::-:0;;;;5:1;0:2; From a500a63e7029299928211de433124ae69333b3f2 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Fri, 28 Jun 2024 16:48:11 -0300 Subject: [PATCH 0238/1340] workaround to skip failing hardhat tests --- .circleci/config.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index d6c3f33da..3426db329 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1438,6 +1438,14 @@ jobs: # TODO: temporarily set hardhat stack traces tests to use cancun hardfork # Remove this when hardhat switch to cancun by default: https://github.com/NomicFoundation/hardhat/issues/4851 sed -i 's/hardfork: "shanghai",/hardfork: "cancun",/' test/internal/hardhat-network/stack-traces/execution.ts + # TODO: Remove these tests because they rely on specific stack sequence which has changed since + # Remove when hardhat properly fix a specific version for the tests: https://github.com/NomicFoundation/hardhat/issues/5443 + rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/modifiers/call-message/multiple-modifiers-require/ + rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/modifiers/create-message/multiple-modifiers-require/ + rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/revert-without-message/within-receive/between-statements/ + rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/revert-without-message/within-receive/no-other-statements/ + rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/revert-without-message/within-receive/statement-after/ + rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/revert-without-message/within-receive/statement-before/ pnpm test - matrix_notify_failure_unless_pr From 57ab4dce5a7031d83915f3c43cd331bba940c63e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 5 Aug 2024 10:03:13 +0200 Subject: [PATCH 0239/1340] Parser: Fix spuriously emitted parser error for unary plus operations when used as binary operator in some cases --- Changelog.md | 1 + libsolidity/parsing/Parser.cpp | 2 +- .../declaration_unary_plus_tuple_compound_assign.sol | 9 +++++++++ .../591_access_to_internal_variable.sol | 9 +++++++++ test/libsolidity/syntaxTests/types/binary_add_op.sol | 12 ++++++++++++ 5 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/iceRegressionTests/declarationUnaryTuple/declaration_unary_plus_tuple_compound_assign.sol create mode 100644 test/libsolidity/syntaxTests/nameAndTypeResolution/591_access_to_internal_variable.sol create mode 100644 test/libsolidity/syntaxTests/types/binary_add_op.sol diff --git a/Changelog.md b/Changelog.md index 8acee7422..d6aaf3512 100644 --- a/Changelog.md +++ b/Changelog.md @@ -20,6 +20,7 @@ Compiler Features: Bugfixes: + * Parser: Fix spuriously emitted parser error for unary plus operations when used as binary operator in some cases. * SMTChecker: Fix error that reports invalid number of verified checks for BMC and CHC engines. * SMTChecker: Fix formatting of unary minus expressions in invariants. * SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine. diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index b51eb9c44..a6a4d735a 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -2152,7 +2152,7 @@ ASTPointer Parser::parseUnaryExpression( ASTNodeFactory(*this, _partiallyParsedExpression) : ASTNodeFactory(*this); Token token = m_scanner->currentToken(); - if (token == Token::Add) + if (!_partiallyParsedExpression && token == Token::Add) fatalParserError(9636_error, "Use of unary + is disallowed."); if (!_partiallyParsedExpression && (TokenTraits::isUnaryOp(token) || TokenTraits::isCountOp(token))) diff --git a/test/libsolidity/syntaxTests/iceRegressionTests/declarationUnaryTuple/declaration_unary_plus_tuple_compound_assign.sol b/test/libsolidity/syntaxTests/iceRegressionTests/declarationUnaryTuple/declaration_unary_plus_tuple_compound_assign.sol new file mode 100644 index 000000000..24c795f14 --- /dev/null +++ b/test/libsolidity/syntaxTests/iceRegressionTests/declarationUnaryTuple/declaration_unary_plus_tuple_compound_assign.sol @@ -0,0 +1,9 @@ +contract C +{ + function f(int x) public + { + (x /= 1) + +(1,1); + } +} +// ---- +// ParserError 9636: (67-68): Use of unary + is disallowed. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/591_access_to_internal_variable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/591_access_to_internal_variable.sol new file mode 100644 index 000000000..f8fba4f7d --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/591_access_to_internal_variable.sol @@ -0,0 +1,9 @@ +contract C { + function f(int32 x) external pure returns (int32) + { + this.x + 1; + return x; + } +} +// ---- +// TypeError 9582: (81-87): Member "x" not found or not visible after argument-dependent lookup in contract C. diff --git a/test/libsolidity/syntaxTests/types/binary_add_op.sol b/test/libsolidity/syntaxTests/types/binary_add_op.sol new file mode 100644 index 000000000..1217ed243 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/binary_add_op.sol @@ -0,0 +1,12 @@ +contract C { + function f(int32 x) external pure returns (int32) + { + x = 1 + 1; + (x /= 1) + 1; + (x = ++x) + 1; + (0) + 1; + return x; + } +} +// ---- +// Warning 6133: (145-152): Statement has no effect. From 40aec73c18b4dc7ed684fac1e574c0de6ff2f142 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 6 Aug 2024 16:26:47 +0200 Subject: [PATCH 0240/1340] Update libyul/Object.cpp --- libyul/Object.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libyul/Object.cpp b/libyul/Object.cpp index afd237b5b..c4e7971ab 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -170,11 +170,8 @@ bool Object::hasCode() const { return code() != nullptr; } void Object::setCode(std::shared_ptr const& _ast, std::shared_ptr _analysisInfo) { - if (_ast.get() != m_code.get()) - { - m_code = _ast; - analysisInfo = std::move(_analysisInfo); - } + m_code = _ast; + analysisInfo = std::move(_analysisInfo); } void Object::collectSourceIndices(std::map& _indices) const From 961c99db087108d406206d50f405b9b4f33d940d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 31 Jul 2024 19:21:14 +0200 Subject: [PATCH 0241/1340] Tests for warnings sensitive to optimization --- test/cmdlineTests/strict_asm_warning/args | 1 + test/cmdlineTests/strict_asm_warning/err | 11 +++++++++++ test/cmdlineTests/strict_asm_warning/input.yul | 5 +++++ test/cmdlineTests/strict_asm_warning/output | 7 +++++++ .../strict_asm_warning_and_error_optimize/args | 1 + .../strict_asm_warning_and_error_optimize/err | 11 +++++++++++ .../strict_asm_warning_and_error_optimize/exit | 1 + .../strict_asm_warning_and_error_optimize/input.yul | 5 +++++ test/cmdlineTests/strict_asm_warning_optimize/args | 1 + test/cmdlineTests/strict_asm_warning_optimize/err | 11 +++++++++++ .../strict_asm_warning_optimize/input.yul | 5 +++++ test/cmdlineTests/strict_asm_warning_optimize/output | 7 +++++++ .../strict_asm_warning_optimize_unreachable/args | 1 + .../strict_asm_warning_optimize_unreachable/err | 5 +++++ .../strict_asm_warning_optimize_unreachable/input.yul | 8 ++++++++ .../strict_asm_warning_optimize_unreachable/output | 7 +++++++ 16 files changed, 87 insertions(+) create mode 100644 test/cmdlineTests/strict_asm_warning/args create mode 100644 test/cmdlineTests/strict_asm_warning/err create mode 100644 test/cmdlineTests/strict_asm_warning/input.yul create mode 100644 test/cmdlineTests/strict_asm_warning/output create mode 100644 test/cmdlineTests/strict_asm_warning_and_error_optimize/args create mode 100644 test/cmdlineTests/strict_asm_warning_and_error_optimize/err create mode 100644 test/cmdlineTests/strict_asm_warning_and_error_optimize/exit create mode 100644 test/cmdlineTests/strict_asm_warning_and_error_optimize/input.yul create mode 100644 test/cmdlineTests/strict_asm_warning_optimize/args create mode 100644 test/cmdlineTests/strict_asm_warning_optimize/err create mode 100644 test/cmdlineTests/strict_asm_warning_optimize/input.yul create mode 100644 test/cmdlineTests/strict_asm_warning_optimize/output create mode 100644 test/cmdlineTests/strict_asm_warning_optimize_unreachable/args create mode 100644 test/cmdlineTests/strict_asm_warning_optimize_unreachable/err create mode 100644 test/cmdlineTests/strict_asm_warning_optimize_unreachable/input.yul create mode 100644 test/cmdlineTests/strict_asm_warning_optimize_unreachable/output diff --git a/test/cmdlineTests/strict_asm_warning/args b/test/cmdlineTests/strict_asm_warning/args new file mode 100644 index 000000000..57996b90a --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning/args @@ -0,0 +1 @@ +--strict-assembly --ir-optimized diff --git a/test/cmdlineTests/strict_asm_warning/err b/test/cmdlineTests/strict_asm_warning/err new file mode 100644 index 000000000..1024e870f --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning/err @@ -0,0 +1,11 @@ +Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. + --> strict_asm_warning/input.yul:4:5: + | +4 | selfdestruct(0) + | ^^^^^^^^^^^^ + +Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. + --> strict_asm_warning/input.yul:4:5: + | +4 | selfdestruct(0) + | ^^^^^^^^^^^^ diff --git a/test/cmdlineTests/strict_asm_warning/input.yul b/test/cmdlineTests/strict_asm_warning/input.yul new file mode 100644 index 000000000..cfe85c784 --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning/input.yul @@ -0,0 +1,5 @@ +{ + // The code is valid and will proceed through the whole pipeline, possibly being reparsed multiple times. + // This should produce exactly one warning. + selfdestruct(0) +} diff --git a/test/cmdlineTests/strict_asm_warning/output b/test/cmdlineTests/strict_asm_warning/output new file mode 100644 index 000000000..71cb2ce69 --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning/output @@ -0,0 +1,7 @@ + +======= strict_asm_warning/input.yul (EVM) ======= + +Pretty printed source: +object "object" { + code { { selfdestruct(0) } } +} diff --git a/test/cmdlineTests/strict_asm_warning_and_error_optimize/args b/test/cmdlineTests/strict_asm_warning_and_error_optimize/args new file mode 100644 index 000000000..90b16d1f0 --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_and_error_optimize/args @@ -0,0 +1 @@ +--strict-assembly --optimize --ir-optimized diff --git a/test/cmdlineTests/strict_asm_warning_and_error_optimize/err b/test/cmdlineTests/strict_asm_warning_and_error_optimize/err new file mode 100644 index 000000000..22366e3e7 --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_and_error_optimize/err @@ -0,0 +1,11 @@ +Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. + --> strict_asm_warning_and_error_optimize/input.yul:4:5: + | +4 | selfdestruct() + | ^^^^^^^^^^^^ + +Error: Function "selfdestruct" expects 1 arguments but got 0. + --> strict_asm_warning_and_error_optimize/input.yul:4:5: + | +4 | selfdestruct() + | ^^^^^^^^^^^^ diff --git a/test/cmdlineTests/strict_asm_warning_and_error_optimize/exit b/test/cmdlineTests/strict_asm_warning_and_error_optimize/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_and_error_optimize/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/strict_asm_warning_and_error_optimize/input.yul b/test/cmdlineTests/strict_asm_warning_and_error_optimize/input.yul new file mode 100644 index 000000000..75800c7ff --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_and_error_optimize/input.yul @@ -0,0 +1,5 @@ +{ + // The code does not compile so the optimizer will not run. + // This should generate exactly one warning and one error. + selfdestruct() +} diff --git a/test/cmdlineTests/strict_asm_warning_optimize/args b/test/cmdlineTests/strict_asm_warning_optimize/args new file mode 100644 index 000000000..90b16d1f0 --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_optimize/args @@ -0,0 +1 @@ +--strict-assembly --optimize --ir-optimized diff --git a/test/cmdlineTests/strict_asm_warning_optimize/err b/test/cmdlineTests/strict_asm_warning_optimize/err new file mode 100644 index 000000000..2f3c9bb4a --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_optimize/err @@ -0,0 +1,11 @@ +Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. + --> strict_asm_warning_optimize/input.yul:4:5: + | +4 | selfdestruct(0) + | ^^^^^^^^^^^^ + +Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. + --> strict_asm_warning_optimize/input.yul:4:5: + | +4 | selfdestruct(0) + | ^^^^^^^^^^^^ diff --git a/test/cmdlineTests/strict_asm_warning_optimize/input.yul b/test/cmdlineTests/strict_asm_warning_optimize/input.yul new file mode 100644 index 000000000..cfe85c784 --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_optimize/input.yul @@ -0,0 +1,5 @@ +{ + // The code is valid and will proceed through the whole pipeline, possibly being reparsed multiple times. + // This should produce exactly one warning. + selfdestruct(0) +} diff --git a/test/cmdlineTests/strict_asm_warning_optimize/output b/test/cmdlineTests/strict_asm_warning_optimize/output new file mode 100644 index 000000000..d933dcb05 --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_optimize/output @@ -0,0 +1,7 @@ + +======= strict_asm_warning_optimize/input.yul (EVM) ======= + +Pretty printed source: +object "object" { + code { { selfdestruct(0) } } +} diff --git a/test/cmdlineTests/strict_asm_warning_optimize_unreachable/args b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/args new file mode 100644 index 000000000..90b16d1f0 --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/args @@ -0,0 +1 @@ +--strict-assembly --optimize --ir-optimized diff --git a/test/cmdlineTests/strict_asm_warning_optimize_unreachable/err b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/err new file mode 100644 index 000000000..4535680ba --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/err @@ -0,0 +1,5 @@ +Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. + --> strict_asm_warning_optimize_unreachable/input.yul:7:5: + | +7 | selfdestruct(0) + | ^^^^^^^^^^^^ diff --git a/test/cmdlineTests/strict_asm_warning_optimize_unreachable/input.yul b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/input.yul new file mode 100644 index 000000000..c07ecd43e --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/input.yul @@ -0,0 +1,8 @@ +{ + revert(0, 0) + + // The code is valid and will proceed through the whole pipeline, possibly being reparsed multiple times. + // Note that the code is unreachable, so the warning would not appear in the optimized version. + // This should produce exactly one warning. + selfdestruct(0) +} diff --git a/test/cmdlineTests/strict_asm_warning_optimize_unreachable/output b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/output new file mode 100644 index 000000000..508e9d8ed --- /dev/null +++ b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/output @@ -0,0 +1,7 @@ + +======= strict_asm_warning_optimize_unreachable/input.yul (EVM) ======= + +Pretty printed source: +object "object" { + code { { revert(0, 0) } } +} From ea262ed56c7317f4399262d03fd05f34148c7660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 31 Jul 2024 15:45:34 +0200 Subject: [PATCH 0242/1340] EVMObjectCompiler: Don't require a mutable object --- libyul/backends/evm/EVMObjectCompiler.cpp | 4 ++-- libyul/backends/evm/EVMObjectCompiler.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index ca9f90dfa..ccd8af6d2 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -35,7 +35,7 @@ using namespace solidity::yul; void EVMObjectCompiler::compile( - Object& _object, + Object const& _object, AbstractAssembly& _assembly, EVMDialect const& _dialect, bool _optimize, @@ -46,7 +46,7 @@ void EVMObjectCompiler::compile( compiler.run(_object, _optimize); } -void EVMObjectCompiler::run(Object& _object, bool _optimize) +void EVMObjectCompiler::run(Object const& _object, bool _optimize) { BuiltinContext context; context.currentObject = &_object; diff --git a/libyul/backends/evm/EVMObjectCompiler.h b/libyul/backends/evm/EVMObjectCompiler.h index df8d71c2c..d37ade2cd 100644 --- a/libyul/backends/evm/EVMObjectCompiler.h +++ b/libyul/backends/evm/EVMObjectCompiler.h @@ -34,7 +34,7 @@ class EVMObjectCompiler { public: static void compile( - Object& _object, + Object const& _object, AbstractAssembly& _assembly, EVMDialect const& _dialect, bool _optimize, @@ -45,7 +45,7 @@ class EVMObjectCompiler m_assembly(_assembly), m_dialect(_dialect), m_eofVersion(_eofVersion) {} - void run(Object& _object, bool _optimize); + void run(Object const& _object, bool _optimize); AbstractAssembly& m_assembly; EVMDialect const& m_dialect; From fe4c52e3357ba92da81521c0ad200fa5294ada5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 31 Jul 2024 16:47:28 +0200 Subject: [PATCH 0243/1340] Move optimized IR reparsing from CompilerStack to YulStack - This makes it apply to yul compilation as well. - Also fixes warnings being reported again when optimizing IR. --- Changelog.md | 3 +- libsolidity/interface/CompilerStack.cpp | 47 ++- libyul/YulStack.cpp | 33 ++- libyul/YulStack.h | 7 + test/cmdlineTests/ast_ir/output | 92 +++--- .../linking_strict_assembly/output | 8 +- .../output | 16 +- .../output | 16 +- .../output | 16 +- test/cmdlineTests/object_compiler/output | 32 +- .../output.json | 142 ++++----- test/cmdlineTests/standard_yul/output.json | 10 +- .../standard_yul_object/output.json | 10 +- .../standard_yul_object_name/output.json | 14 +- .../standard_yul_optimiserSteps/output.json | 8 +- .../standard_yul_optimized/output.json | 8 +- .../standard_yul_stack_opt/output.json | 14 +- .../output.json | 12 +- .../output | 128 ++++---- .../strict_asm_ast_compact_json/output | 14 +- .../strict_asm_evm_version_byzantium/output | 2 +- .../output | 2 +- .../strict_asm_optimizer_steps/output | 48 +-- .../output | 8 +- test/cmdlineTests/strict_asm_warning/err | 6 - .../strict_asm_warning_optimize/err | 6 - .../output | 26 +- test/cmdlineTests/yul_optimize_runs/output | 20 +- test/cmdlineTests/yul_verbatim_msize/output | 15 +- test/libyul/objectCompiler/data.yul | 4 +- test/libyul/objectCompiler/datacopy.yul | 30 +- .../libyul/objectCompiler/dataoffset_code.yul | 18 +- .../libyul/objectCompiler/dataoffset_data.yul | 10 +- .../libyul/objectCompiler/dataoffset_self.yul | 10 +- test/libyul/objectCompiler/datasize_code.yul | 18 +- test/libyul/objectCompiler/datasize_data.yul | 10 +- test/libyul/objectCompiler/datasize_self.yul | 10 +- ..._long_name_does_not_end_up_in_bytecode.yul | 10 +- .../leading_and_trailing_dots.yul | 22 +- test/libyul/objectCompiler/linkersymbol.yul | 24 +- .../objectCompiler/long_object_name.yul | 12 +- test/libyul/objectCompiler/manySubObjects.yul | 276 +++++++++--------- test/libyul/objectCompiler/metadata.yul | 26 +- test/libyul/objectCompiler/namedObject.yul | 4 +- .../libyul/objectCompiler/namedObjectCode.yul | 10 +- .../objectCompiler/nested_optimizer.yul | 18 +- test/libyul/objectCompiler/simple.yul | 10 +- .../objectCompiler/simple_optimizer.yul | 10 +- test/libyul/objectCompiler/smoke.yul | 4 +- test/libyul/objectCompiler/subObject.yul | 12 +- .../libyul/objectCompiler/subObjectAccess.yul | 138 ++++----- test/libyul/objectCompiler/subSubObject.yul | 20 +- test/libyul/objectCompiler/verbatim_bug.yul | 82 +++--- 53 files changed, 783 insertions(+), 768 deletions(-) diff --git a/Changelog.md b/Changelog.md index 5e8a7bef8..0395b624b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -28,8 +28,9 @@ Bugfixes: * SMTChecker: Fix formatting of unary minus expressions in invariants. * SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine. * TypeChecker: Fix segfault when assigning nested tuple to tuple. - * Yul AST: Fix ``nativeSrc`` attributes in optimized IR AST referring to locations in unoptimized IR. * Yul IR Code Generation: Deterministic order of Yul subobjects. + * Yul Optimizer: Fix Yul source locations always referring to unoptimized source, even in optimized outputs. + * Yul Optimizer: Fix warnings being generated twice when there are no errors. * Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. * Yul Parser: Fix segfault when parsing very long location comments. diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index dd5d20126..0ea7131db 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1488,39 +1488,26 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti ); } - auto const parseYul = [&](std::string const& _irSource) { - YulStack stack( - m_evmVersion, - m_eofVersion, - YulStack::Language::StrictAssembly, - m_optimiserSettings, - m_debugInfoSelection - ); - bool yulAnalysisSuccessful = stack.parseAndAnalyze("", _irSource); - solAssert( - yulAnalysisSuccessful, - _irSource + "\n\n" - "Invalid IR generated:\n" + - langutil::SourceReferenceFormatter::formatErrorInformation(stack.errors(), stack) + "\n" - ); - return stack; - }; - - { - YulStack stack = parseYul(compiledContract.yulIR); - compiledContract.yulIRAst = stack.astJson(); - if (!_unoptimizedOnly) - { - stack.optimize(); - compiledContract.yulIROptimized = stack.print(this); - } - } + YulStack stack( + m_evmVersion, + m_eofVersion, + YulStack::Language::StrictAssembly, + m_optimiserSettings, + m_debugInfoSelection + ); + bool yulAnalysisSuccessful = stack.parseAndAnalyze("", compiledContract.yulIR); + solAssert( + yulAnalysisSuccessful, + compiledContract.yulIR + "\n\n" + "Invalid IR generated:\n" + + SourceReferenceFormatter::formatErrorInformation(stack.errors(), stack) + "\n" + ); + compiledContract.yulIRAst = stack.astJson(); if (!_unoptimizedOnly) { - // Optimizer does not maintain correct native source locations in the AST. - // We can work around it by regenerating the AST from scratch from optimized IR. - YulStack stack = parseYul(compiledContract.yulIROptimized); + stack.optimize(); + compiledContract.yulIROptimized = stack.print(this); compiledContract.yulIROptimizedAst = stack.astJson(); } } diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index dbe30bb13..a391a6963 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -117,7 +118,10 @@ void YulStack::optimize() m_stackState = Parsed; optimize(*m_parserResult, true); - yulAssert(analyzeParsed(), "Invalid source code after optimization."); + + // Optimizer does not maintain correct native source locations in the AST. + // We can work around it by regenerating the AST from scratch from optimized IR. + reparse(); } catch (UnimplementedFeatureError const& _error) { @@ -241,6 +245,33 @@ void YulStack::optimize(Object& _object, bool _isCreation) ); } +void YulStack::reparse() +{ + yulAssert(m_parserResult); + yulAssert(m_charStream); + + // NOTE: Without passing in _soliditySourceProvider, printed debug info will not include code + // snippets, but it does not matter - we'll still get the same AST after we parse it. Snippets + // are not stored in the AST and the other info that is (location, AST ID, etc) will still be present. + std::string source = print(nullptr /* _soliditySourceProvider */); + + YulStack cleanStack(m_evmVersion, m_eofVersion, m_language, m_optimiserSettings, m_debugInfoSelection); + bool reanalysisSuccessful = cleanStack.parseAndAnalyze(m_charStream->name(), source); + yulAssert( + reanalysisSuccessful, + source + "\n\n" + "Invalid IR generated:\n" + + SourceReferenceFormatter::formatErrorInformation(cleanStack.errors(), cleanStack) + "\n" + ); + + m_stackState = AnalysisSuccessful; + m_parserResult = std::move(cleanStack.m_parserResult); + + // NOTE: We keep the char stream, and errors, even though they no longer match the object, + // because it's the original source that matters to the user. Optimized code may have different + // locations and fewer warnings. +} + MachineAssemblyObject YulStack::assemble(Machine _machine) { yulAssert(m_stackState >= AnalysisSuccessful); diff --git a/libyul/YulStack.h b/libyul/YulStack.h index f547ef770..4dc262a25 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -152,6 +152,13 @@ class YulStack: public langutil::CharStreamProvider void optimize(yul::Object& _object, bool _isCreation); + /// Prints the Yul object stored internally and parses it again. + /// This ensures that the debug info in the AST matches the source that printing would produce + /// rather than the initial source. + /// @warning Does not update the error list or the original source (@a m_charStream) to make + /// it possible to report errors to the user even after the optimization has been performed. + void reparse(); + void reportUnimplementedFeatureError(langutil::UnimplementedFeatureError const& _error); Language m_language = Language::Assembly; diff --git a/test/cmdlineTests/ast_ir/output b/test/cmdlineTests/ast_ir/output index 76f111990..3211ef49b 100644 --- a/test/cmdlineTests/ast_ir/output +++ b/test/cmdlineTests/ast_ir/output @@ -637,24 +637,24 @@ Optimized IR AST: { "code": { "block": { - "nativeSrc": "58:315:0", + "nativeSrc": "58:298:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "68:299:0", + "nativeSrc": "68:282:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "128:27:0", + "nativeSrc": "111:27:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "150:4:0", + "nativeSrc": "133:4:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -663,18 +663,18 @@ Optimized IR AST: ], "functionName": { "name": "memoryguard", - "nativeSrc": "138:11:0", + "nativeSrc": "121:11:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "138:17:0", + "nativeSrc": "121:17:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variables": [ { "name": "_1", - "nativeSrc": "132:2:0", + "nativeSrc": "115:2:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -686,7 +686,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "175:2:0", + "nativeSrc": "158:2:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -694,28 +694,28 @@ Optimized IR AST: }, { "name": "_1", - "nativeSrc": "179:2:0", + "nativeSrc": "162:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "168:6:0", + "nativeSrc": "151:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "168:14:0", + "nativeSrc": "151:14:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "168:14:0", + "nativeSrc": "151:14:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, { "body": { - "nativeSrc": "210:16:0", + "nativeSrc": "193:16:0", "nodeType": "YulBlock", "src": "60:13:0", "statements": [ @@ -724,7 +724,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "219:1:0", + "nativeSrc": "202:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -732,7 +732,7 @@ Optimized IR AST: }, { "kind": "number", - "nativeSrc": "222:1:0", + "nativeSrc": "205:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -741,15 +741,15 @@ Optimized IR AST: ], "functionName": { "name": "revert", - "nativeSrc": "212:6:0", + "nativeSrc": "195:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "212:12:0", + "nativeSrc": "195:12:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "212:12:0", + "nativeSrc": "195:12:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } @@ -759,20 +759,20 @@ Optimized IR AST: "arguments": [], "functionName": { "name": "callvalue", - "nativeSrc": "198:9:0", + "nativeSrc": "181:9:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "198:11:0", + "nativeSrc": "181:11:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "195:31:0", + "nativeSrc": "178:31:0", "nodeType": "YulIf", "src": "60:13:0" }, { - "nativeSrc": "239:34:0", + "nativeSrc": "222:34:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", "value": { @@ -780,7 +780,7 @@ Optimized IR AST: { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "258:14:0", + "nativeSrc": "241:14:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -789,18 +789,18 @@ Optimized IR AST: ], "functionName": { "name": "datasize", - "nativeSrc": "249:8:0", + "nativeSrc": "232:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "249:24:0", + "nativeSrc": "232:24:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variables": [ { "name": "_2", - "nativeSrc": "243:2:0", + "nativeSrc": "226:2:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -812,7 +812,7 @@ Optimized IR AST: "arguments": [ { "name": "_1", - "nativeSrc": "295:2:0", + "nativeSrc": "278:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, @@ -821,7 +821,7 @@ Optimized IR AST: { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "310:14:0", + "nativeSrc": "293:14:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -830,32 +830,32 @@ Optimized IR AST: ], "functionName": { "name": "dataoffset", - "nativeSrc": "299:10:0", + "nativeSrc": "282:10:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "299:26:0", + "nativeSrc": "282:26:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, { "name": "_2", - "nativeSrc": "327:2:0", + "nativeSrc": "310:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "codecopy", - "nativeSrc": "286:8:0", + "nativeSrc": "269:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "286:44:0", + "nativeSrc": "269:44:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "286:44:0", + "nativeSrc": "269:44:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, @@ -864,28 +864,28 @@ Optimized IR AST: "arguments": [ { "name": "_1", - "nativeSrc": "350:2:0", + "nativeSrc": "333:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, { "name": "_2", - "nativeSrc": "354:2:0", + "nativeSrc": "337:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "return", - "nativeSrc": "343:6:0", + "nativeSrc": "326:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "343:14:0", + "nativeSrc": "326:14:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "343:14:0", + "nativeSrc": "326:14:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } @@ -901,12 +901,12 @@ Optimized IR AST: { "code": { "block": { - "nativeSrc": "453:118:0", + "nativeSrc": "436:101:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "467:94:0", + "nativeSrc": "450:77:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -915,7 +915,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "542:1:0", + "nativeSrc": "508:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -923,7 +923,7 @@ Optimized IR AST: }, { "kind": "number", - "nativeSrc": "545:1:0", + "nativeSrc": "511:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -932,15 +932,15 @@ Optimized IR AST: ], "functionName": { "name": "revert", - "nativeSrc": "535:6:0", + "nativeSrc": "501:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "535:12:0", + "nativeSrc": "501:12:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "535:12:0", + "nativeSrc": "501:12:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } diff --git a/test/cmdlineTests/linking_strict_assembly/output b/test/cmdlineTests/linking_strict_assembly/output index 29a8abdfa..4fa6edc0c 100644 --- a/test/cmdlineTests/linking_strict_assembly/output +++ b/test/cmdlineTests/linking_strict_assembly/output @@ -16,11 +16,11 @@ Binary representation: 7312345678901234567890123456789012345678905f5500 Text representation: - /* "linking_strict_assembly/input.yul":44:79 */ + /* "linking_strict_assembly/input.yul":58:93 */ linkerSymbol("f919ba91ac99f96129544b80b9516b27a80e376b9dc693819d0b18b7e0395612") - /* "linking_strict_assembly/input.yul":95:96 */ + /* "linking_strict_assembly/input.yul":113:114 */ 0x00 - /* "linking_strict_assembly/input.yul":88:103 */ + /* "linking_strict_assembly/input.yul":106:121 */ sstore - /* "linking_strict_assembly/input.yul":22:109 */ + /* "linking_strict_assembly/input.yul":22:137 */ stop diff --git a/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files/output b/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files/output index 4aecfc6b2..69c0a21f6 100644 --- a/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files/output +++ b/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files/output @@ -18,19 +18,19 @@ Binary representation: 731111111111111111111111111111111111111111732222222222222222222222222222222222222222905f5560015500 Text representation: - /* "linking_strict_assembly_same_library_name_different_files/input.yul":45:75 */ + /* "linking_strict_assembly_same_library_name_different_files/input.yul":59:89 */ linkerSymbol("f3ffc10c396a7cc41ae954b050792839d20947bf73497d30c49a9fda1ea477ec") - /* "linking_strict_assembly_same_library_name_different_files/input.yul":97:127 */ + /* "linking_strict_assembly_same_library_name_different_files/input.yul":115:145 */ linkerSymbol("c3523432985587641d17c68161d2f700c57aaf4ed21cda4f25d76193c831f97f") - /* "linking_strict_assembly_same_library_name_different_files/input.yul":136:152 */ + /* "linking_strict_assembly_same_library_name_different_files/input.yul":158:174 */ swap1 - /* "linking_strict_assembly_same_library_name_different_files/input.yul":143:144 */ + /* "linking_strict_assembly_same_library_name_different_files/input.yul":165:166 */ 0x00 - /* "linking_strict_assembly_same_library_name_different_files/input.yul":136:152 */ + /* "linking_strict_assembly_same_library_name_different_files/input.yul":158:174 */ sstore - /* "linking_strict_assembly_same_library_name_different_files/input.yul":168:169 */ + /* "linking_strict_assembly_same_library_name_different_files/input.yul":194:195 */ 0x01 - /* "linking_strict_assembly_same_library_name_different_files/input.yul":161:177 */ + /* "linking_strict_assembly_same_library_name_different_files/input.yul":187:203 */ sstore - /* "linking_strict_assembly_same_library_name_different_files/input.yul":22:183 */ + /* "linking_strict_assembly_same_library_name_different_files/input.yul":22:219 */ stop diff --git a/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files_in_link_references/output b/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files_in_link_references/output index 10a7fe7fe..14fafa4e4 100644 --- a/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files_in_link_references/output +++ b/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files_in_link_references/output @@ -18,19 +18,19 @@ Binary representation: 73123456789012345678901234567890123456789073__$c3523432985587641d17c68161d2f700c5$__905f5560015500 Text representation: - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":45:75 */ + /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":59:89 */ linkerSymbol("f3ffc10c396a7cc41ae954b050792839d20947bf73497d30c49a9fda1ea477ec") - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":97:127 */ + /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":115:145 */ linkerSymbol("c3523432985587641d17c68161d2f700c57aaf4ed21cda4f25d76193c831f97f") - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":136:152 */ + /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":158:174 */ swap1 - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":143:144 */ + /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":165:166 */ 0x00 - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":136:152 */ + /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":158:174 */ sstore - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":168:169 */ + /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":194:195 */ 0x01 - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":161:177 */ + /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":187:203 */ sstore - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":22:183 */ + /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":22:219 */ stop diff --git a/test/cmdlineTests/linking_strict_assembly_unresolved_references/output b/test/cmdlineTests/linking_strict_assembly_unresolved_references/output index a110db5a3..3b2d84ab3 100644 --- a/test/cmdlineTests/linking_strict_assembly_unresolved_references/output +++ b/test/cmdlineTests/linking_strict_assembly_unresolved_references/output @@ -18,19 +18,19 @@ Binary representation: 73123456789012345678901234567890123456789073__$fb58009a6b1ecea3b9d99bedd645df4ec3$__905f5560015500 Text representation: - /* "linking_strict_assembly_unresolved_references/input.yul":45:81 */ + /* "linking_strict_assembly_unresolved_references/input.yul":59:95 */ linkerSymbol("05b0326038374a21e0895480a58bda0768cdcc04c8d18f154362d1ca5223d245") - /* "linking_strict_assembly_unresolved_references/input.yul":103:139 */ + /* "linking_strict_assembly_unresolved_references/input.yul":121:157 */ linkerSymbol("fb58009a6b1ecea3b9d99bedd645df4ec308f17bc0087e5f39d078f77f809177") - /* "linking_strict_assembly_unresolved_references/input.yul":148:164 */ + /* "linking_strict_assembly_unresolved_references/input.yul":170:186 */ swap1 - /* "linking_strict_assembly_unresolved_references/input.yul":155:156 */ + /* "linking_strict_assembly_unresolved_references/input.yul":177:178 */ 0x00 - /* "linking_strict_assembly_unresolved_references/input.yul":148:164 */ + /* "linking_strict_assembly_unresolved_references/input.yul":170:186 */ sstore - /* "linking_strict_assembly_unresolved_references/input.yul":180:181 */ + /* "linking_strict_assembly_unresolved_references/input.yul":206:207 */ 0x01 - /* "linking_strict_assembly_unresolved_references/input.yul":173:189 */ + /* "linking_strict_assembly_unresolved_references/input.yul":199:215 */ sstore - /* "linking_strict_assembly_unresolved_references/input.yul":22:195 */ + /* "linking_strict_assembly_unresolved_references/input.yul":22:231 */ stop diff --git a/test/cmdlineTests/object_compiler/output b/test/cmdlineTests/object_compiler/output index 5dd572272..a88851b96 100644 --- a/test/cmdlineTests/object_compiler/output +++ b/test/cmdlineTests/object_compiler/output @@ -26,40 +26,40 @@ Binary representation: 335f55600880600d5f395ff3fe5f545f5260205ff3 Text representation: - /* "object_compiler/input.yul":128:136 */ + /* "object_compiler/input.yul":65:73 */ caller - /* "object_compiler/input.yul":125:126 */ + /* "object_compiler/input.yul":62:63 */ 0x00 - /* "object_compiler/input.yul":118:137 */ + /* "object_compiler/input.yul":55:74 */ sstore - /* "object_compiler/input.yul":240:259 */ + /* "object_compiler/input.yul":97:116 */ dataSize(sub_0) - /* "object_compiler/input.yul":217:238 */ + /* "object_compiler/input.yul":141:162 */ dup1 dataOffset(sub_0) - /* "object_compiler/input.yul":125:126 */ + /* "object_compiler/input.yul":138:139 */ 0x00 - /* "object_compiler/input.yul":205:260 */ + /* "object_compiler/input.yul":129:167 */ codecopy - /* "object_compiler/input.yul":125:126 */ + /* "object_compiler/input.yul":187:188 */ 0x00 - /* "object_compiler/input.yul":265:295 */ + /* "object_compiler/input.yul":180:193 */ return stop sub_0: assembly { - /* "object_compiler/input.yul":397:398 */ + /* "object_compiler/input.yul":294:295 */ 0x00 - /* "object_compiler/input.yul":391:399 */ + /* "object_compiler/input.yul":288:296 */ sload - /* "object_compiler/input.yul":397:398 */ + /* "object_compiler/input.yul":285:286 */ 0x00 - /* "object_compiler/input.yul":381:400 */ + /* "object_compiler/input.yul":278:297 */ mstore - /* "object_compiler/input.yul":417:421 */ + /* "object_compiler/input.yul":324:328 */ 0x20 - /* "object_compiler/input.yul":397:398 */ + /* "object_compiler/input.yul":321:322 */ 0x00 - /* "object_compiler/input.yul":407:422 */ + /* "object_compiler/input.yul":314:329 */ return } diff --git a/test/cmdlineTests/standard_irOptimized_ast_requested/output.json b/test/cmdlineTests/standard_irOptimized_ast_requested/output.json index 5c6762ac9..f80f4466c 100644 --- a/test/cmdlineTests/standard_irOptimized_ast_requested/output.json +++ b/test/cmdlineTests/standard_irOptimized_ast_requested/output.json @@ -5,12 +5,12 @@ "irOptimizedAst": { "code": { "block": { - "nativeSrc": "43:639:0", + "nativeSrc": "43:622:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "53:421:0", + "nativeSrc": "53:404:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -19,7 +19,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "120:2:0", + "nativeSrc": "103:2:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -29,7 +29,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "136:4:0", + "nativeSrc": "119:4:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -38,32 +38,32 @@ ], "functionName": { "name": "memoryguard", - "nativeSrc": "124:11:0", + "nativeSrc": "107:11:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "124:17:0", + "nativeSrc": "107:17:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "113:6:0", + "nativeSrc": "96:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "113:29:0", + "nativeSrc": "96:29:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "113:29:0", + "nativeSrc": "96:29:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" }, { "body": { - "nativeSrc": "182:111:0", + "nativeSrc": "165:111:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ @@ -72,15 +72,15 @@ "arguments": [], "functionName": { "name": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "nativeSrc": "200:77:0", + "nativeSrc": "183:77:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "200:79:0", + "nativeSrc": "183:79:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "200:79:0", + "nativeSrc": "183:79:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } @@ -90,38 +90,38 @@ "arguments": [], "functionName": { "name": "callvalue", - "nativeSrc": "158:9:0", + "nativeSrc": "141:9:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "158:11:0", + "nativeSrc": "141:11:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "155:138:0", + "nativeSrc": "138:138:0", "nodeType": "YulIf", "src": "56:13:0" }, { - "nativeSrc": "306:30:0", + "nativeSrc": "289:30:0", "nodeType": "YulVariableDeclaration", "src": "56:13:0", "value": { "arguments": [], "functionName": { "name": "allocate_unbounded", - "nativeSrc": "316:18:0", + "nativeSrc": "299:18:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "316:20:0", + "nativeSrc": "299:20:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, "variables": [ { "name": "_1", - "nativeSrc": "310:2:0", + "nativeSrc": "293:2:0", "nodeType": "YulTypedName", "src": "56:13:0", "type": "" @@ -133,7 +133,7 @@ "arguments": [ { "name": "_1", - "nativeSrc": "358:2:0", + "nativeSrc": "341:2:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, @@ -142,7 +142,7 @@ { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "373:14:0", + "nativeSrc": "356:14:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -151,11 +151,11 @@ ], "functionName": { "name": "dataoffset", - "nativeSrc": "362:10:0", + "nativeSrc": "345:10:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "362:26:0", + "nativeSrc": "345:26:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, @@ -164,7 +164,7 @@ { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "399:14:0", + "nativeSrc": "382:14:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -173,26 +173,26 @@ ], "functionName": { "name": "datasize", - "nativeSrc": "390:8:0", + "nativeSrc": "373:8:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "390:24:0", + "nativeSrc": "373:24:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "codecopy", - "nativeSrc": "349:8:0", + "nativeSrc": "332:8:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "349:66:0", + "nativeSrc": "332:66:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "349:66:0", + "nativeSrc": "332:66:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" }, @@ -201,7 +201,7 @@ "arguments": [ { "name": "_1", - "nativeSrc": "435:2:0", + "nativeSrc": "418:2:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, @@ -210,7 +210,7 @@ { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "448:14:0", + "nativeSrc": "431:14:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -219,26 +219,26 @@ ], "functionName": { "name": "datasize", - "nativeSrc": "439:8:0", + "nativeSrc": "422:8:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "439:24:0", + "nativeSrc": "422:24:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "return", - "nativeSrc": "428:6:0", + "nativeSrc": "411:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "428:36:0", + "nativeSrc": "411:36:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "428:36:0", + "nativeSrc": "411:36:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } @@ -246,19 +246,19 @@ }, { "body": { - "nativeSrc": "531:23:0", + "nativeSrc": "514:23:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ { - "nativeSrc": "533:19:0", + "nativeSrc": "516:19:0", "nodeType": "YulAssignment", "src": "56:13:0", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "549:2:0", + "nativeSrc": "532:2:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -267,18 +267,18 @@ ], "functionName": { "name": "mload", - "nativeSrc": "543:5:0", + "nativeSrc": "526:5:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "543:9:0", + "nativeSrc": "526:9:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, "variableNames": [ { "name": "memPtr", - "nativeSrc": "533:6:0", + "nativeSrc": "516:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" } @@ -287,12 +287,12 @@ ] }, "name": "allocate_unbounded", - "nativeSrc": "483:71:0", + "nativeSrc": "466:71:0", "nodeType": "YulFunctionDefinition", "returnVariables": [ { "name": "memPtr", - "nativeSrc": "516:6:0", + "nativeSrc": "499:6:0", "nodeType": "YulTypedName", "src": "56:13:0", "type": "" @@ -302,7 +302,7 @@ }, { "body": { - "nativeSrc": "660:16:0", + "nativeSrc": "643:16:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ @@ -311,7 +311,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "669:1:0", + "nativeSrc": "652:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -319,7 +319,7 @@ }, { "kind": "number", - "nativeSrc": "672:1:0", + "nativeSrc": "655:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -328,22 +328,22 @@ ], "functionName": { "name": "revert", - "nativeSrc": "662:6:0", + "nativeSrc": "645:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "662:12:0", + "nativeSrc": "645:12:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "662:12:0", + "nativeSrc": "645:12:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } ] }, "name": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "nativeSrc": "563:113:0", + "nativeSrc": "546:113:0", "nodeType": "YulFunctionDefinition", "src": "56:13:0" } @@ -357,12 +357,12 @@ { "code": { "block": { - "nativeSrc": "747:361:0", + "nativeSrc": "730:344:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "761:207:0", + "nativeSrc": "744:190:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -371,7 +371,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "836:2:0", + "nativeSrc": "802:2:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -381,7 +381,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "852:4:0", + "nativeSrc": "818:4:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -390,26 +390,26 @@ ], "functionName": { "name": "memoryguard", - "nativeSrc": "840:11:0", + "nativeSrc": "806:11:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "840:17:0", + "nativeSrc": "806:17:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "829:6:0", + "nativeSrc": "795:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "829:29:0", + "nativeSrc": "795:29:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "829:29:0", + "nativeSrc": "795:29:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" }, @@ -418,15 +418,15 @@ "arguments": [], "functionName": { "name": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", - "nativeSrc": "875:77:0", + "nativeSrc": "841:77:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "875:79:0", + "nativeSrc": "841:79:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "875:79:0", + "nativeSrc": "841:79:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } @@ -434,7 +434,7 @@ }, { "body": { - "nativeSrc": "1082:16:0", + "nativeSrc": "1048:16:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ @@ -443,7 +443,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "1091:1:0", + "nativeSrc": "1057:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -451,7 +451,7 @@ }, { "kind": "number", - "nativeSrc": "1094:1:0", + "nativeSrc": "1060:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -460,22 +460,22 @@ ], "functionName": { "name": "revert", - "nativeSrc": "1084:6:0", + "nativeSrc": "1050:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "1084:12:0", + "nativeSrc": "1050:12:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "1084:12:0", + "nativeSrc": "1050:12:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } ] }, "name": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", - "nativeSrc": "981:117:0", + "nativeSrc": "947:117:0", "nodeType": "YulFunctionDefinition", "src": "56:13:0" } diff --git a/test/cmdlineTests/standard_yul/output.json b/test/cmdlineTests/standard_yul/output.json index 8d2ab0074..30fe1dd7e 100644 --- a/test/cmdlineTests/standard_yul/output.json +++ b/test/cmdlineTests/standard_yul/output.json @@ -3,17 +3,17 @@ "A": { "object": { "evm": { - "assembly": " /* \"A\":38:39 */ + "assembly": " /* \"A\":99:100 */ 0x00 - /* \"A\":11:19 */ + /* \"A\":60:68 */ dup1 dup1 mload - /* \"A\":27:36 */ + /* \"A\":88:97 */ add - /* \"A\":20:40 */ + /* \"A\":81:101 */ sstore - /* \"A\":0:42 */ + /* \"A\":27:117 */ stop ", "bytecode": { diff --git a/test/cmdlineTests/standard_yul_object/output.json b/test/cmdlineTests/standard_yul_object/output.json index 87d0cab8f..3181da426 100644 --- a/test/cmdlineTests/standard_yul_object/output.json +++ b/test/cmdlineTests/standard_yul_object/output.json @@ -3,16 +3,16 @@ "A": { "NamedObject": { "evm": { - "assembly": " /* \"A\":80:81 */ + "assembly": " /* \"A\":118:119 */ 0x00 - /* \"A\":39:61 */ + /* \"A\":65:87 */ dup1 data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 - /* \"A\":69:78 */ + /* \"A\":107:116 */ add - /* \"A\":62:82 */ + /* \"A\":100:120 */ sstore - /* \"A\":28:84 */ + /* \"A\":32:136 */ stop stop data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 diff --git a/test/cmdlineTests/standard_yul_object_name/output.json b/test/cmdlineTests/standard_yul_object_name/output.json index c6e98130d..1512900e1 100644 --- a/test/cmdlineTests/standard_yul_object_name/output.json +++ b/test/cmdlineTests/standard_yul_object_name/output.json @@ -3,24 +3,24 @@ "A": { "NamedObject": { "evm": { - "assembly": " /* \"A\":80:81 */ + "assembly": " /* \"A\":118:119 */ 0x00 - /* \"A\":39:61 */ + /* \"A\":65:87 */ dup1 data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 - /* \"A\":69:78 */ + /* \"A\":107:116 */ add - /* \"A\":62:82 */ + /* \"A\":100:120 */ sstore - /* \"A\":28:84 */ + /* \"A\":32:136 */ stop stop data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 sub_0: assembly { - /* \"A\":147:148 */ + /* \"A\":223:224 */ 0x00 - /* \"A\":137:149 */ + /* \"A\":213:225 */ dup1 revert } diff --git a/test/cmdlineTests/standard_yul_optimiserSteps/output.json b/test/cmdlineTests/standard_yul_optimiserSteps/output.json index 1c72379c6..2a654d20a 100644 --- a/test/cmdlineTests/standard_yul_optimiserSteps/output.json +++ b/test/cmdlineTests/standard_yul_optimiserSteps/output.json @@ -3,14 +3,14 @@ "A": { "object": { "evm": { - "assembly": " /* \"A\":38:39 */ + "assembly": " /* \"A\":99:100 */ 0x00 - /* \"A\":11:19 */ + /* \"A\":60:68 */ dup1 mload - /* \"A\":20:40 */ + /* \"A\":81:101 */ sstore - /* \"A\":0:42 */ + /* \"A\":27:117 */ stop ", "bytecode": { diff --git a/test/cmdlineTests/standard_yul_optimized/output.json b/test/cmdlineTests/standard_yul_optimized/output.json index c443b2863..513f8148a 100644 --- a/test/cmdlineTests/standard_yul_optimized/output.json +++ b/test/cmdlineTests/standard_yul_optimized/output.json @@ -3,14 +3,14 @@ "A": { "object": { "evm": { - "assembly": " /* \"A\":17:18 */ + "assembly": " /* \"A\":48:49 */ 0x00 - /* \"A\":11:19 */ + /* \"A\":38:46 */ dup1 mload - /* \"A\":20:40 */ + /* \"A\":31:50 */ sstore - /* \"A\":0:42 */ + /* \"A\":27:54 */ stop ", "bytecode": { diff --git a/test/cmdlineTests/standard_yul_stack_opt/output.json b/test/cmdlineTests/standard_yul_stack_opt/output.json index 9d89edfb4..4d7d96b49 100644 --- a/test/cmdlineTests/standard_yul_stack_opt/output.json +++ b/test/cmdlineTests/standard_yul_stack_opt/output.json @@ -3,19 +3,19 @@ "A": { "object": { "evm": { - "assembly": " /* \"A\":16:17 */ + "assembly": " /* \"A\":61:62 */ 0x01 - /* \"A\":27:28 */ + /* \"A\":58:59 */ 0x00 - /* \"A\":20:32 */ + /* \"A\":51:63 */ sstore - /* \"A\":50:51 */ + /* \"A\":87:88 */ 0x02 - /* \"A\":61:63 */ + /* \"A\":83:85 */ 0x20 - /* \"A\":54:67 */ + /* \"A\":76:89 */ sstore - /* \"A\":0:72 */ + /* \"A\":27:105 */ stop " } diff --git a/test/cmdlineTests/standard_yul_stack_opt_disabled/output.json b/test/cmdlineTests/standard_yul_stack_opt_disabled/output.json index f0752b812..ca7e2de19 100644 --- a/test/cmdlineTests/standard_yul_stack_opt_disabled/output.json +++ b/test/cmdlineTests/standard_yul_stack_opt_disabled/output.json @@ -3,17 +3,17 @@ "A": { "object": { "evm": { - "assembly": " /* \"A\":16:17 */ + "assembly": " /* \"A\":61:62 */ 0x01 - /* \"A\":27:28 */ + /* \"A\":58:59 */ 0x00 - /* \"A\":20:32 */ + /* \"A\":51:63 */ sstore - /* \"A\":50:51 */ + /* \"A\":87:88 */ 0x02 - /* \"A\":61:63 */ + /* \"A\":83:85 */ 0x20 - /* \"A\":54:67 */ + /* \"A\":76:89 */ sstore " } diff --git a/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/output b/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/output index 25fb482d4..305185f01 100644 --- a/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/output +++ b/test/cmdlineTests/strict_asm_asm_json_without_debug_info_annotations/output @@ -171,207 +171,207 @@ EVM assembly: ".auxdata": "1234abcd", ".code": [ { - "begin": 469, - "end": 486, + "begin": 468, + "end": 485, "name": "PUSH", "source": -1, "value": "80" }, { - "begin": 503, - "end": 517, + "begin": 502, + "end": 516, "name": "DUP1", "source": -1 }, { - "begin": 510, - "end": 512, + "begin": 509, + "end": 511, "name": "PUSH", "source": -1, "value": "40" }, { - "begin": 503, - "end": 517, + "begin": 502, + "end": 516, "name": "MSTORE", "source": -1 }, { - "begin": 563, - "end": 564, + "begin": 562, + "end": 563, "name": "PUSH", "source": -1, "value": "4" }, { - "begin": 547, - "end": 561, + "begin": 546, + "end": 560, "name": "CALLDATASIZE", "source": -1 }, { - "begin": 544, - "end": 565, + "begin": 543, + "end": 564, "name": "LT", "source": -1 }, { - "begin": 537, - "end": 566, + "begin": 536, + "end": 565, "name": "ISZERO", "source": -1 }, { - "begin": 534, - "end": 832, + "begin": 533, + "end": 831, "name": "PUSH [tag]", "source": -1, "value": "1" }, { - "begin": 534, - "end": 832, + "begin": 533, + "end": 831, "name": "JUMPI", "source": -1 }, { - "begin": 427, - "end": 885, + "begin": 426, + "end": 884, "name": "tag", "source": -1, "value": "2" }, { - "begin": 427, - "end": 885, + "begin": 426, + "end": 884, "name": "JUMPDEST", "source": -1 }, { - "begin": 859, - "end": 860, + "begin": 858, + "end": 859, "name": "PUSH", "source": -1, "value": "0" }, { - "begin": 849, - "end": 861, + "begin": 848, + "end": 860, "name": "DUP1", "source": -1 }, { - "begin": 849, - "end": 861, + "begin": 848, + "end": 860, "name": "REVERT", "source": -1 }, { - "begin": 583, - "end": 832, + "begin": 582, + "end": 831, "name": "tag", "source": -1, "value": "1" }, { - "begin": 583, - "end": 832, + "begin": 582, + "end": 831, "name": "JUMPDEST", "source": -1 }, { - "begin": 615, - "end": 616, + "begin": 614, + "end": 615, "name": "PUSH", "source": -1, "value": "0" }, { - "begin": 653, - "end": 669, + "begin": 652, + "end": 668, "name": "CALLDATALOAD", "source": -1 }, { - "begin": 648, - "end": 651, + "begin": 647, + "end": 650, "name": "PUSH", "source": -1, "value": "E0" }, { - "begin": 644, - "end": 670, + "begin": 643, + "end": 669, "name": "SHR", "source": -1 }, { - "begin": 696, - "end": 706, + "begin": 695, + "end": 705, "name": "PUSH", "source": -1, "value": "B4F40C61" }, { - "begin": 691, - "end": 814, + "begin": 690, + "end": 813, "name": "SUB", "source": -1 }, { - "begin": 583, - "end": 832, + "begin": 582, + "end": 831, "name": "PUSH [tag]", "source": -1, "value": "2" }, { - "begin": 691, - "end": 814, + "begin": 690, + "end": 813, "name": "JUMPI", "source": -1 }, { - "begin": 789, - "end": 791, + "begin": 788, + "end": 790, "name": "PUSH", "source": -1, "value": "20" }, { - "begin": 744, - "end": 752, + "begin": 743, + "end": 751, "name": "SWAP1", "source": -1 }, { - "begin": 750, - "end": 751, + "begin": 749, + "end": 750, "name": "PUSH", "source": -1, "value": "1" }, { - "begin": 744, - "end": 752, + "begin": 743, + "end": 751, "name": "SLOAD", "source": -1 }, { - "begin": 733, - "end": 753, + "begin": 732, + "end": 752, "name": "DUP2", "source": -1 }, { - "begin": 733, - "end": 753, + "begin": 732, + "end": 752, "name": "MSTORE", "source": -1 }, { - "begin": 778, - "end": 792, + "begin": 777, + "end": 791, "name": "RETURN", "source": -1 } diff --git a/test/cmdlineTests/strict_asm_ast_compact_json/output b/test/cmdlineTests/strict_asm_ast_compact_json/output index b4c6dc142..b2271c36c 100644 --- a/test/cmdlineTests/strict_asm_ast_compact_json/output +++ b/test/cmdlineTests/strict_asm_ast_compact_json/output @@ -5,12 +5,12 @@ AST: { "code": { "block": { - "nativeSrc": "60:246:0", + "nativeSrc": "60:85:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "60:246:0", + "nativeSrc": "70:69:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -19,7 +19,7 @@ AST: "arguments": [ { "kind": "number", - "nativeSrc": "122:2:0", + "nativeSrc": "121:2:0", "nodeType": "YulLiteral", "src": "60:41:0", "type": "", @@ -27,7 +27,7 @@ AST: }, { "kind": "number", - "nativeSrc": "126:3:0", + "nativeSrc": "125:3:0", "nodeType": "YulLiteral", "src": "60:41:0", "type": "", @@ -36,15 +36,15 @@ AST: ], "functionName": { "name": "mstore", - "nativeSrc": "115:6:0", + "nativeSrc": "114:6:0", "nodeType": "YulIdentifier", "src": "60:41:0" }, - "nativeSrc": "115:15:0", + "nativeSrc": "114:15:0", "nodeType": "YulFunctionCall", "src": "60:41:0" }, - "nativeSrc": "115:15:0", + "nativeSrc": "114:15:0", "nodeType": "YulExpressionStatement", "src": "60:41:0" } diff --git a/test/cmdlineTests/strict_asm_evm_version_byzantium/output b/test/cmdlineTests/strict_asm_evm_version_byzantium/output index 3a23390a4..2840e1d2b 100644 --- a/test/cmdlineTests/strict_asm_evm_version_byzantium/output +++ b/test/cmdlineTests/strict_asm_evm_version_byzantium/output @@ -11,5 +11,5 @@ Binary representation: 00 Text representation: - /* "strict_asm_evm_version_byzantium/input.yul":0:2 */ + /* "strict_asm_evm_version_byzantium/input.yul":27:34 */ stop diff --git a/test/cmdlineTests/strict_asm_evm_version_constantinople/output b/test/cmdlineTests/strict_asm_evm_version_constantinople/output index c8febd6f1..9362866b4 100644 --- a/test/cmdlineTests/strict_asm_evm_version_constantinople/output +++ b/test/cmdlineTests/strict_asm_evm_version_constantinople/output @@ -11,5 +11,5 @@ Binary representation: 00 Text representation: - /* "strict_asm_evm_version_constantinople/input.yul":0:2 */ + /* "strict_asm_evm_version_constantinople/input.yul":27:34 */ stop diff --git a/test/cmdlineTests/strict_asm_optimizer_steps/output b/test/cmdlineTests/strict_asm_optimizer_steps/output index c10fb02fb..58c919761 100644 --- a/test/cmdlineTests/strict_asm_optimizer_steps/output +++ b/test/cmdlineTests/strict_asm_optimizer_steps/output @@ -27,58 +27,58 @@ Binary representation: 608060405234601357600c60185f39600c5ff35b5f80fdfe608060405236155f555f80fd Text representation: - /* "strict_asm_optimizer_steps/input.yul":45:48 */ + /* "strict_asm_optimizer_steps/input.yul":59:62 */ 0x80 - /* "strict_asm_optimizer_steps/input.yul":41:43 */ + /* "strict_asm_optimizer_steps/input.yul":55:57 */ 0x40 - /* "strict_asm_optimizer_steps/input.yul":34:49 */ + /* "strict_asm_optimizer_steps/input.yul":48:63 */ mstore - /* "strict_asm_optimizer_steps/input.yul":61:72 */ + /* "strict_asm_optimizer_steps/input.yul":79:90 */ callvalue - /* "strict_asm_optimizer_steps/input.yul":58:89 */ + /* "strict_asm_optimizer_steps/input.yul":76:107 */ tag_1 jumpi - /* "strict_asm_optimizer_steps/input.yul":138:162 */ + /* "strict_asm_optimizer_steps/input.yul":160:184 */ dataSize(sub_0) - /* "strict_asm_optimizer_steps/input.yul":110:136 */ + /* "strict_asm_optimizer_steps/input.yul":132:158 */ dataOffset(sub_0) - /* "strict_asm_optimizer_steps/input.yul":107:108 */ + /* "strict_asm_optimizer_steps/input.yul":129:130 */ 0x00 - /* "strict_asm_optimizer_steps/input.yul":98:163 */ + /* "strict_asm_optimizer_steps/input.yul":120:185 */ codecopy - /* "strict_asm_optimizer_steps/input.yul":182:206 */ + /* "strict_asm_optimizer_steps/input.yul":208:232 */ dataSize(sub_0) - /* "strict_asm_optimizer_steps/input.yul":179:180 */ + /* "strict_asm_optimizer_steps/input.yul":205:206 */ 0x00 - /* "strict_asm_optimizer_steps/input.yul":172:207 */ + /* "strict_asm_optimizer_steps/input.yul":198:233 */ return - /* "strict_asm_optimizer_steps/input.yul":73:89 */ + /* "strict_asm_optimizer_steps/input.yul":91:107 */ tag_1: - /* "strict_asm_optimizer_steps/input.yul":85:86 */ + /* "strict_asm_optimizer_steps/input.yul":103:104 */ 0x00 - /* "strict_asm_optimizer_steps/input.yul":75:87 */ + /* "strict_asm_optimizer_steps/input.yul":93:105 */ dup1 revert stop sub_0: assembly { - /* "strict_asm_optimizer_steps/input.yul":298:301 */ + /* "strict_asm_optimizer_steps/input.yul":334:337 */ 0x80 - /* "strict_asm_optimizer_steps/input.yul":294:296 */ + /* "strict_asm_optimizer_steps/input.yul":330:332 */ 0x40 - /* "strict_asm_optimizer_steps/input.yul":287:302 */ + /* "strict_asm_optimizer_steps/input.yul":323:338 */ mstore - /* "strict_asm_optimizer_steps/input.yul":533:547 */ + /* "strict_asm_optimizer_steps/input.yul":372:386 */ calldatasize - /* "strict_asm_optimizer_steps/input.yul":526:548 */ + /* "strict_asm_optimizer_steps/input.yul":365:387 */ iszero - /* "strict_asm_optimizer_steps/input.yul":523:524 */ + /* "strict_asm_optimizer_steps/input.yul":362:363 */ 0x00 - /* "strict_asm_optimizer_steps/input.yul":516:549 */ + /* "strict_asm_optimizer_steps/input.yul":355:388 */ sstore - /* "strict_asm_optimizer_steps/input.yul":576:577 */ + /* "strict_asm_optimizer_steps/input.yul":415:416 */ 0x00 - /* "strict_asm_optimizer_steps/input.yul":566:578 */ + /* "strict_asm_optimizer_steps/input.yul":405:417 */ dup1 revert } diff --git a/test/cmdlineTests/strict_asm_output_selection_asm_only/output b/test/cmdlineTests/strict_asm_output_selection_asm_only/output index abe2143d3..317c9a9ae 100644 --- a/test/cmdlineTests/strict_asm_output_selection_asm_only/output +++ b/test/cmdlineTests/strict_asm_output_selection_asm_only/output @@ -2,11 +2,11 @@ ======= strict_asm_output_selection_asm_only/input.yul (EVM) ======= Text representation: - /* "strict_asm_output_selection_asm_only/input.yul":15:17 */ + /* "strict_asm_output_selection_asm_only/input.yul":41:43 */ 0x2a - /* "strict_asm_output_selection_asm_only/input.yul":29:30 */ + /* "strict_asm_output_selection_asm_only/input.yul":38:39 */ 0x00 - /* "strict_asm_output_selection_asm_only/input.yul":22:34 */ + /* "strict_asm_output_selection_asm_only/input.yul":31:44 */ sstore - /* "strict_asm_output_selection_asm_only/input.yul":0:36 */ + /* "strict_asm_output_selection_asm_only/input.yul":27:48 */ stop diff --git a/test/cmdlineTests/strict_asm_warning/err b/test/cmdlineTests/strict_asm_warning/err index 1024e870f..0661ae1ff 100644 --- a/test/cmdlineTests/strict_asm_warning/err +++ b/test/cmdlineTests/strict_asm_warning/err @@ -3,9 +3,3 @@ Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun | 4 | selfdestruct(0) | ^^^^^^^^^^^^ - -Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. - --> strict_asm_warning/input.yul:4:5: - | -4 | selfdestruct(0) - | ^^^^^^^^^^^^ diff --git a/test/cmdlineTests/strict_asm_warning_optimize/err b/test/cmdlineTests/strict_asm_warning_optimize/err index 2f3c9bb4a..098aa00ba 100644 --- a/test/cmdlineTests/strict_asm_warning_optimize/err +++ b/test/cmdlineTests/strict_asm_warning_optimize/err @@ -3,9 +3,3 @@ Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun | 4 | selfdestruct(0) | ^^^^^^^^^^^^ - -Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. - --> strict_asm_warning_optimize/input.yul:4:5: - | -4 | selfdestruct(0) - | ^^^^^^^^^^^^ diff --git a/test/cmdlineTests/yul_function_name_clashes_different_params/output b/test/cmdlineTests/yul_function_name_clashes_different_params/output index 22cee64c1..85884a6a0 100644 --- a/test/cmdlineTests/yul_function_name_clashes_different_params/output +++ b/test/cmdlineTests/yul_function_name_clashes_different_params/output @@ -23,37 +23,37 @@ Binary representation: 60056011565b600d60706016565b9055005b5f3590565b359056 Text representation: - /* "yul_function_name_clashes_different_params/input.yul":151:154 */ + /* "yul_function_name_clashes_different_params/input.yul":92:95 */ tag_3 tag_1 jump // in tag_3: - /* "yul_function_name_clashes_different_params/input.yul":260:267 */ + /* "yul_function_name_clashes_different_params/input.yul":113:122 */ tag_4 - /* "yul_function_name_clashes_different_params/input.yul":262:266 */ + /* "yul_function_name_clashes_different_params/input.yul":117:121 */ 0x70 - /* "yul_function_name_clashes_different_params/input.yul":260:267 */ + /* "yul_function_name_clashes_different_params/input.yul":113:122 */ tag_2 jump // in tag_4: - /* "yul_function_name_clashes_different_params/input.yul":286:298 */ + /* "yul_function_name_clashes_different_params/input.yul":135:147 */ swap1 sstore - /* "yul_function_name_clashes_different_params/input.yul":27:304 */ + /* "yul_function_name_clashes_different_params/input.yul":27:284 */ stop - /* "yul_function_name_clashes_different_params/input.yul":79:133 */ + /* "yul_function_name_clashes_different_params/input.yul":166:216 */ tag_1: - /* "yul_function_name_clashes_different_params/input.yul":129:130 */ + /* "yul_function_name_clashes_different_params/input.yul":212:213 */ 0x00 - /* "yul_function_name_clashes_different_params/input.yul":116:131 */ + /* "yul_function_name_clashes_different_params/input.yul":199:214 */ calldataload - /* "yul_function_name_clashes_different_params/input.yul":79:133 */ + /* "yul_function_name_clashes_different_params/input.yul":166:216 */ swap1 jump // out - /* "yul_function_name_clashes_different_params/input.yul":187:242 */ + /* "yul_function_name_clashes_different_params/input.yul":225:278 */ tag_2: - /* "yul_function_name_clashes_different_params/input.yul":225:240 */ + /* "yul_function_name_clashes_different_params/input.yul":261:276 */ calldataload - /* "yul_function_name_clashes_different_params/input.yul":187:242 */ + /* "yul_function_name_clashes_different_params/input.yul":225:278 */ swap1 jump // out diff --git a/test/cmdlineTests/yul_optimize_runs/output b/test/cmdlineTests/yul_optimize_runs/output index b7fcabaac..589f8ce1a 100644 --- a/test/cmdlineTests/yul_optimize_runs/output +++ b/test/cmdlineTests/yul_optimize_runs/output @@ -24,28 +24,28 @@ Binary representation: 602480600a5f395ff3fe7fabc12345000000000000000000000000000000000000000000000000000000005f5500 Text representation: - /* "yul_optimize_runs/input.yul":115:143 */ + /* "yul_optimize_runs/input.yul":64:92 */ dataSize(sub_0) - /* "yul_optimize_runs/input.yul":83:113 */ + /* "yul_optimize_runs/input.yul":117:147 */ dup1 dataOffset(sub_0) - /* "yul_optimize_runs/input.yul":80:81 */ + /* "yul_optimize_runs/input.yul":114:115 */ 0x00 - /* "yul_optimize_runs/input.yul":71:144 */ + /* "yul_optimize_runs/input.yul":105:152 */ codecopy - /* "yul_optimize_runs/input.yul":80:81 */ + /* "yul_optimize_runs/input.yul":172:173 */ 0x00 - /* "yul_optimize_runs/input.yul":153:192 */ + /* "yul_optimize_runs/input.yul":165:178 */ return stop sub_0: assembly { - /* "yul_optimize_runs/input.yul":273:293 */ + /* "yul_optimize_runs/input.yul":282:348 */ 0xabc1234500000000000000000000000000000000000000000000000000000000 - /* "yul_optimize_runs/input.yul":313:314 */ + /* "yul_optimize_runs/input.yul":279:280 */ 0x00 - /* "yul_optimize_runs/input.yul":306:324 */ + /* "yul_optimize_runs/input.yul":272:349 */ sstore - /* "yul_optimize_runs/input.yul":244:334 */ + /* "yul_optimize_runs/input.yul":240:373 */ stop } diff --git a/test/cmdlineTests/yul_verbatim_msize/output b/test/cmdlineTests/yul_verbatim_msize/output index 22259fff7..f684bac21 100644 --- a/test/cmdlineTests/yul_verbatim_msize/output +++ b/test/cmdlineTests/yul_verbatim_msize/output @@ -17,18 +17,19 @@ Binary representation: 6120005150616160025f5500 Text representation: - /* "yul_verbatim_msize/input.yul":125:131 */ + /* "yul_verbatim_msize/input.yul":61:67 */ 0x2000 - /* "yul_verbatim_msize/input.yul":119:132 */ + /* "yul_verbatim_msize/input.yul":55:68 */ mload + /* "yul_verbatim_msize/input.yul":51:69 */ pop - /* "yul_verbatim_msize/input.yul":137:157 */ + /* "yul_verbatim_msize/input.yul":82:102 */ verbatimbytecode_6161 - /* "yul_verbatim_msize/input.yul":172:173 */ + /* "yul_verbatim_msize/input.yul":125:126 */ 0x02 - /* "yul_verbatim_msize/input.yul":169:170 */ + /* "yul_verbatim_msize/input.yul":122:123 */ 0x00 - /* "yul_verbatim_msize/input.yul":162:174 */ + /* "yul_verbatim_msize/input.yul":115:127 */ sstore - /* "yul_verbatim_msize/input.yul":0:176 */ + /* "yul_verbatim_msize/input.yul":27:143 */ stop diff --git a/test/libyul/objectCompiler/data.yul b/test/libyul/objectCompiler/data.yul index caa649921..ad8899fb1 100644 --- a/test/libyul/objectCompiler/data.yul +++ b/test/libyul/objectCompiler/data.yul @@ -5,10 +5,10 @@ object "a" { } // ---- // Assembly: -// /* "source":20:22 */ +// /* "source":22:29 */ // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // Bytecode: 00fe // Opcodes: STOP INVALID -// SourceMappings: 20:2:0:-:0 +// SourceMappings: 22:7:0:-:0 diff --git a/test/libyul/objectCompiler/datacopy.yul b/test/libyul/objectCompiler/datacopy.yul index 719b109f1..9f7fca9ad 100644 --- a/test/libyul/objectCompiler/datacopy.yul +++ b/test/libyul/objectCompiler/datacopy.yul @@ -13,40 +13,40 @@ object "a" { } // ---- // Assembly: -// /* "source":57:72 */ +// /* "source":77:92 */ // dataSize(sub_0) -// /* "source":38:55 */ +// /* "source":58:75 */ // dataOffset(sub_0) -// /* "source":35:36 */ +// /* "source":55:56 */ // 0x00 -// /* "source":26:73 */ +// /* "source":46:93 */ // codecopy -// /* "source":88:103 */ +// /* "source":116:131 */ // dataSize(sub_0) -// /* "source":85:86 */ +// /* "source":113:114 */ // 0x00 -// /* "source":78:104 */ +// /* "source":106:132 */ // return // stop // // sub_0: assembly { -// /* "source":153:170 */ +// /* "source":223:240 */ // 0x00 -// /* "source":150:151 */ +// /* "source":220:221 */ // 0x00 -// /* "source":143:171 */ +// /* "source":213:241 */ // sstore -// /* "source":188:205 */ +// /* "source":268:285 */ // 0x0d -// /* "source":185:186 */ +// /* "source":265:266 */ // 0x00 -// /* "source":178:206 */ +// /* "source":258:286 */ // mstore -// /* "source":135:212 */ +// /* "source":181:310 */ // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // } // Bytecode: 6009600b5f3960095ff3fe5f5f55600d5f5200fe // Opcodes: PUSH1 0x9 PUSH1 0xB PUSH0 CODECOPY PUSH1 0x9 PUSH0 RETURN INVALID PUSH0 PUSH0 SSTORE PUSH1 0xD PUSH0 MSTORE STOP INVALID -// SourceMappings: 57:15:0:-:0;38:17;35:1;26:47;88:15;85:1;78:26 +// SourceMappings: 77:15:0:-:0;58:17;55:1;46:47;116:15;113:1;106:26 diff --git a/test/libyul/objectCompiler/dataoffset_code.yul b/test/libyul/objectCompiler/dataoffset_code.yul index 58521c87f..8ca10add2 100644 --- a/test/libyul/objectCompiler/dataoffset_code.yul +++ b/test/libyul/objectCompiler/dataoffset_code.yul @@ -7,28 +7,28 @@ object "a" { } // ---- // Assembly: -// /* "source":32:49 */ +// /* "source":44:61 */ // dataOffset(sub_0) -// /* "source":29:30 */ +// /* "source":41:42 */ // 0x00 -// /* "source":22:50 */ +// /* "source":34:62 */ // sstore -// /* "source":20:52 */ +// /* "source":22:70 */ // stop // stop // // sub_0: assembly { -// /* "source":91:92 */ +// /* "source":117:118 */ // 0x08 -// /* "source":88:89 */ +// /* "source":114:115 */ // 0x00 -// /* "source":81:93 */ +// /* "source":107:119 */ // sstore -// /* "source":79:95 */ +// /* "source":103:123 */ // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // } // Bytecode: 60065f5500fe60085f5500fe // Opcodes: PUSH1 0x6 PUSH0 SSTORE STOP INVALID PUSH1 0x8 PUSH0 SSTORE STOP INVALID -// SourceMappings: 32:17:0:-:0;29:1;22:28;20:32 +// SourceMappings: 44:17:0:-:0;41:1;34:28;22:48 diff --git a/test/libyul/objectCompiler/dataoffset_data.yul b/test/libyul/objectCompiler/dataoffset_data.yul index 61f0c4418..915567489 100644 --- a/test/libyul/objectCompiler/dataoffset_data.yul +++ b/test/libyul/objectCompiler/dataoffset_data.yul @@ -4,16 +4,16 @@ object "a" { } // ---- // Assembly: -// /* "source":32:51 */ +// /* "source":56:75 */ // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f -// /* "source":29:30 */ +// /* "source":53:54 */ // 0x00 -// /* "source":22:52 */ +// /* "source":46:76 */ // sstore -// /* "source":20:54 */ +// /* "source":22:92 */ // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // Bytecode: 60065f5500fe48656c6c6f2c20576f726c6421 // Opcodes: PUSH1 0x6 PUSH0 SSTORE STOP INVALID BASEFEE PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000 -// SourceMappings: 32:19:0:-:0;29:1;22:30;20:34 +// SourceMappings: 56:19:0:-:0;53:1;46:30;22:70 diff --git a/test/libyul/objectCompiler/dataoffset_self.yul b/test/libyul/objectCompiler/dataoffset_self.yul index ae123ba49..681c24c0e 100644 --- a/test/libyul/objectCompiler/dataoffset_self.yul +++ b/test/libyul/objectCompiler/dataoffset_self.yul @@ -4,16 +4,16 @@ object "a" { } // ---- // Assembly: -// /* "source":32:47 */ +// /* "source":44:59 */ // 0x00 -// /* "source":29:30 */ +// /* "source":41:42 */ // 0x00 -// /* "source":22:48 */ +// /* "source":34:60 */ // sstore -// /* "source":20:50 */ +// /* "source":22:68 */ // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // Bytecode: 5f5f5500fe // Opcodes: PUSH0 PUSH0 SSTORE STOP INVALID -// SourceMappings: 32:15:0:-:0;29:1;22:26;20:30 +// SourceMappings: 44:15:0:-:0;41:1;34:26;22:46 diff --git a/test/libyul/objectCompiler/datasize_code.yul b/test/libyul/objectCompiler/datasize_code.yul index 4e559ab89..cab7987ea 100644 --- a/test/libyul/objectCompiler/datasize_code.yul +++ b/test/libyul/objectCompiler/datasize_code.yul @@ -7,28 +7,28 @@ object "a" { } // ---- // Assembly: -// /* "source":32:47 */ +// /* "source":44:59 */ // dataSize(sub_0) -// /* "source":29:30 */ +// /* "source":41:42 */ // 0x00 -// /* "source":22:48 */ +// /* "source":34:60 */ // sstore -// /* "source":20:50 */ +// /* "source":22:68 */ // stop // stop // // sub_0: assembly { -// /* "source":89:90 */ +// /* "source":115:116 */ // 0x08 -// /* "source":86:87 */ +// /* "source":112:113 */ // 0x00 -// /* "source":79:91 */ +// /* "source":105:117 */ // sstore -// /* "source":77:93 */ +// /* "source":101:121 */ // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // } // Bytecode: 60065f5500fe // Opcodes: PUSH1 0x6 PUSH0 SSTORE STOP INVALID -// SourceMappings: 32:15:0:-:0;29:1;22:26;20:30 +// SourceMappings: 44:15:0:-:0;41:1;34:26;22:46 diff --git a/test/libyul/objectCompiler/datasize_data.yul b/test/libyul/objectCompiler/datasize_data.yul index 3281bd9ba..d1261d246 100644 --- a/test/libyul/objectCompiler/datasize_data.yul +++ b/test/libyul/objectCompiler/datasize_data.yul @@ -4,16 +4,16 @@ object "a" { } // ---- // Assembly: -// /* "source":32:49 */ +// /* "source":44:61 */ // 0x0d -// /* "source":29:30 */ +// /* "source":41:42 */ // 0x00 -// /* "source":22:50 */ +// /* "source":34:62 */ // sstore -// /* "source":20:52 */ +// /* "source":22:70 */ // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // Bytecode: 600d5f5500fe // Opcodes: PUSH1 0xD PUSH0 SSTORE STOP INVALID -// SourceMappings: 32:17:0:-:0;29:1;22:28;20:32 +// SourceMappings: 44:17:0:-:0;41:1;34:28;22:48 diff --git a/test/libyul/objectCompiler/datasize_self.yul b/test/libyul/objectCompiler/datasize_self.yul index 6bc520af5..2a19d0a88 100644 --- a/test/libyul/objectCompiler/datasize_self.yul +++ b/test/libyul/objectCompiler/datasize_self.yul @@ -4,16 +4,16 @@ object "a" { } // ---- // Assembly: -// /* "source":32:45 */ +// /* "source":36:49 */ // bytecodeSize -// /* "source":29:30 */ +// /* "source":33:34 */ // 0x00 -// /* "source":22:46 */ +// /* "source":26:50 */ // sstore -// /* "source":20:48 */ +// /* "source":22:54 */ // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // Bytecode: 60065f5500fe // Opcodes: PUSH1 0x6 PUSH0 SSTORE STOP INVALID -// SourceMappings: 32:13:0:-:0;29:1;22:24;20:28 +// SourceMappings: 36:13:0:-:0;33:1;26:24;22:32 diff --git a/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul b/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul index 285a8a8d5..c6fd0ac80 100644 --- a/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul +++ b/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul @@ -9,14 +9,14 @@ object "a" { } // ---- // Assembly: -// /* "source":167:209 */ +// /* "source":143:185 */ // 0x1234567890123456789012345678901234567890 -// /* "source":58:59 */ +// /* "source":59:60 */ // 0x00 -// /* "source":32:219 */ +// /* "source":46:186 */ // assignImmutable("0x85a5b1db611c82c46f5fa18e39ae218397536256c451e5de155a86de843a9ad6") -// /* "source":22:225 */ +// /* "source":22:202 */ // stop // Bytecode: 7312345678901234567890123456789012345678905f505000 // Opcodes: PUSH20 0x1234567890123456789012345678901234567890 PUSH0 POP POP STOP -// SourceMappings: 167:42:0:-:0;58:1;32:187;;22:203 +// SourceMappings: 143:42:0:-:0;59:1;46:140;;22:180 diff --git a/test/libyul/objectCompiler/leading_and_trailing_dots.yul b/test/libyul/objectCompiler/leading_and_trailing_dots.yul index ea6a8fcd8..13c952355 100644 --- a/test/libyul/objectCompiler/leading_and_trailing_dots.yul +++ b/test/libyul/objectCompiler/leading_and_trailing_dots.yul @@ -14,29 +14,29 @@ } // ---- // Assembly: -// /* "source":49:50 */ +// /* "source":53:54 */ // 0x02 -// /* "source":6:42 */ +// /* "source":108:140 */ // tag_1: -// /* "source":34:35 */ +// /* "source":136:137 */ // 0x00 -// /* "source":32:36 */ +// /* "source":134:138 */ // tag_1 // jump // in -// /* "source":56:92 */ +// /* "source":149:181 */ // tag_2: -// /* "source":84:85 */ +// /* "source":177:178 */ // 0x00 -// /* "source":82:86 */ +// /* "source":175:179 */ // tag_2 // jump // in -// /* "source":106:142 */ +// /* "source":190:222 */ // tag_3: -// /* "source":134:135 */ +// /* "source":218:219 */ // 0x00 -// /* "source":132:136 */ +// /* "source":216:220 */ // tag_3 // jump // in // Bytecode: 60025b5f6002565b5f6007565b5f600c56 // Opcodes: PUSH1 0x2 JUMPDEST PUSH0 PUSH1 0x2 JUMP JUMPDEST PUSH0 PUSH1 0x7 JUMP JUMPDEST PUSH0 PUSH1 0xC JUMP -// SourceMappings: 49:1:0:-:0;6:36;34:1;32:4;:::i;56:36::-;84:1;82:4;:::i;106:36::-;134:1;132:4;:::i +// SourceMappings: 53:1:0:-:0;108:32;136:1;134:4;:::i;149:32::-;177:1;175:4;:::i;190:32::-;218:1;216:4;:::i diff --git a/test/libyul/objectCompiler/linkersymbol.yul b/test/libyul/objectCompiler/linkersymbol.yul index c4da288e6..91a456461 100644 --- a/test/libyul/objectCompiler/linkersymbol.yul +++ b/test/libyul/objectCompiler/linkersymbol.yul @@ -7,31 +7,31 @@ object "a" { } // ---- // Assembly: -// /* "source":179:180 */ +// /* "source":190:191 */ // 0x00 -// /* "source":174:177 */ +// /* "source":185:188 */ // 0x80 -// /* "source":171:172 */ +// /* "source":182:183 */ // 0x04 -// /* "source":44:79 */ +// /* "source":58:93 */ // dup2 // dup4 // linkerSymbol("f919ba91ac99f96129544b80b9516b27a80e376b9dc693819d0b18b7e0395612") -// /* "source":109:119 */ +// /* "source":127:137 */ // 0x18530aaf -// /* "source":104:107 */ +// /* "source":122:125 */ // 0xe3 -// /* "source":100:120 */ +// /* "source":118:138 */ // shl -// /* "source":88:121 */ +// /* "source":106:139 */ // dup4 // mstore -// /* "source":150:155 */ +// /* "source":161:166 */ // gas -// /* "source":145:181 */ +// /* "source":156:192 */ // call -// /* "source":130:181 */ +// /* "source":152:193 */ // stop // Bytecode: 5f6080600481837300000000000000000000000000000000000000006318530aaf60e31b83525af100 // Opcodes: PUSH0 PUSH1 0x80 PUSH1 0x4 DUP2 DUP4 PUSH20 0x0 PUSH4 0x18530AAF PUSH1 0xE3 SHL DUP4 MSTORE GAS CALL STOP -// SourceMappings: 179:1:0:-:0;174:3;171:1;44:35;;;109:10;104:3;100:20;88:33;;150:5;145:36;130:51 +// SourceMappings: 190:1:0:-:0;185:3;182:1;58:35;;;127:10;122:3;118:20;106:33;;161:5;156:36;152:41 diff --git a/test/libyul/objectCompiler/long_object_name.yul b/test/libyul/objectCompiler/long_object_name.yul index aa2dd1ac2..f75260224 100644 --- a/test/libyul/objectCompiler/long_object_name.yul +++ b/test/libyul/objectCompiler/long_object_name.yul @@ -10,20 +10,20 @@ object "t" { // optimizationPreset: full // ---- // Assembly: -// /* "source":33:146 */ +// /* "source":56:169 */ // dataSize(sub_0) -// /* "source":30:31 */ +// /* "source":53:54 */ // 0x00 -// /* "source":23:147 */ +// /* "source":46:170 */ // sstore -// /* "source":19:150 */ +// /* "source":22:186 */ // stop // stop // // sub_0: assembly { -// /* "source":272:274 */ +// /* "source":317:324 */ // stop // } // Bytecode: 60015f5500fe // Opcodes: PUSH1 0x1 PUSH0 SSTORE STOP INVALID -// SourceMappings: 33:113:0:-:0;30:1;23:124;19:131 +// SourceMappings: 56:113:0:-:0;53:1;46:124;22:164 diff --git a/test/libyul/objectCompiler/manySubObjects.yul b/test/libyul/objectCompiler/manySubObjects.yul index 2f4b16387..c046b182f 100644 --- a/test/libyul/objectCompiler/manySubObjects.yul +++ b/test/libyul/objectCompiler/manySubObjects.yul @@ -136,340 +136,340 @@ object "root" { } // ---- // Assembly: -// /* "source":45:61 */ +// /* "source":59:75 */ // bytecodeSize -// /* "source":42:43 */ +// /* "source":56:57 */ // 0x00 -// /* "source":35:62 */ +// /* "source":49:76 */ // sstore -// /* "source":81:94 */ +// /* "source":99:112 */ // dataSize(sub_0) -// /* "source":78:79 */ +// /* "source":96:97 */ // 0x01 -// /* "source":71:95 */ +// /* "source":89:113 */ // sstore -// /* "source":114:127 */ +// /* "source":136:149 */ // dataSize(sub_1) -// /* "source":111:112 */ +// /* "source":133:134 */ // 0x02 -// /* "source":104:128 */ +// /* "source":126:150 */ // sstore -// /* "source":147:160 */ +// /* "source":173:186 */ // dataSize(sub_2) -// /* "source":144:145 */ +// /* "source":170:171 */ // 0x03 -// /* "source":137:161 */ +// /* "source":163:187 */ // sstore -// /* "source":180:193 */ +// /* "source":210:223 */ // dataSize(sub_3) -// /* "source":177:178 */ +// /* "source":207:208 */ // 0x04 -// /* "source":170:194 */ +// /* "source":200:224 */ // sstore -// /* "source":213:226 */ +// /* "source":247:260 */ // dataSize(sub_4) -// /* "source":210:211 */ +// /* "source":244:245 */ // 0x05 -// /* "source":203:227 */ +// /* "source":237:261 */ // sstore -// /* "source":246:259 */ +// /* "source":284:297 */ // dataSize(sub_5) -// /* "source":243:244 */ +// /* "source":281:282 */ // 0x06 -// /* "source":236:260 */ +// /* "source":274:298 */ // sstore -// /* "source":279:292 */ +// /* "source":321:334 */ // dataSize(sub_6) -// /* "source":276:277 */ +// /* "source":318:319 */ // 0x07 -// /* "source":269:293 */ +// /* "source":311:335 */ // sstore -// /* "source":312:325 */ +// /* "source":358:371 */ // dataSize(sub_7) -// /* "source":309:310 */ +// /* "source":355:356 */ // 0x08 -// /* "source":302:326 */ +// /* "source":348:372 */ // sstore -// /* "source":345:358 */ +// /* "source":395:408 */ // dataSize(sub_8) -// /* "source":342:343 */ +// /* "source":392:393 */ // 0x09 -// /* "source":335:359 */ +// /* "source":385:409 */ // sstore -// /* "source":379:392 */ +// /* "source":433:446 */ // dataSize(sub_9) -// /* "source":375:377 */ +// /* "source":429:431 */ // 0x0a -// /* "source":368:393 */ +// /* "source":422:447 */ // sstore -// /* "source":413:426 */ +// /* "source":471:484 */ // dataSize(sub_10) -// /* "source":409:411 */ +// /* "source":467:469 */ // 0x0b -// /* "source":402:427 */ +// /* "source":460:485 */ // sstore -// /* "source":447:460 */ +// /* "source":509:522 */ // dataSize(sub_11) -// /* "source":443:445 */ +// /* "source":505:507 */ // 0x0c -// /* "source":436:461 */ +// /* "source":498:523 */ // sstore -// /* "source":481:494 */ +// /* "source":547:560 */ // dataSize(sub_12) -// /* "source":477:479 */ +// /* "source":543:545 */ // 0x0d -// /* "source":470:495 */ +// /* "source":536:561 */ // sstore -// /* "source":515:528 */ +// /* "source":585:598 */ // dataSize(sub_13) -// /* "source":511:513 */ +// /* "source":581:583 */ // 0x0e -// /* "source":504:529 */ +// /* "source":574:599 */ // sstore -// /* "source":549:562 */ +// /* "source":623:636 */ // dataSize(sub_14) -// /* "source":545:547 */ +// /* "source":619:621 */ // 0x0f -// /* "source":538:563 */ +// /* "source":612:637 */ // sstore -// /* "source":583:596 */ +// /* "source":661:674 */ // dataSize(sub_15) -// /* "source":579:581 */ +// /* "source":657:659 */ // 0x10 -// /* "source":572:597 */ +// /* "source":650:675 */ // sstore -// /* "source":617:631 */ +// /* "source":699:713 */ // dataSize(sub_16) -// /* "source":613:615 */ +// /* "source":695:697 */ // 0x11 -// /* "source":606:632 */ +// /* "source":688:714 */ // sstore -// /* "source":25:638 */ +// /* "source":25:730 */ // stop // stop // // sub_0: assembly { -// /* "source":696:697 */ +// /* "source":805:806 */ // 0x00 -// /* "source":691:694 */ +// /* "source":800:803 */ // 0x64 -// /* "source":684:698 */ +// /* "source":793:807 */ // sstore -// /* "source":723:739 */ +// /* "source":836:852 */ // dataSize(sub_0) -// /* "source":718:721 */ +// /* "source":831:834 */ // 0xc8 -// /* "source":711:740 */ +// /* "source":824:853 */ // sstore -// /* "source":670:750 */ +// /* "source":761:877 */ // stop // stop // // sub_0: assembly { -// /* "source":822:823 */ +// /* "source":935:936 */ // 0x00 -// /* "source":817:820 */ +// /* "source":930:933 */ // 0x012c -// /* "source":810:824 */ +// /* "source":923:937 */ // sstore -// /* "source":792:838 */ +// /* "source":919:941 */ // stop // } // } // // sub_1: assembly { -// /* "source":912:913 */ +// /* "source":1004:1005 */ // 0x01 -// /* "source":907:910 */ +// /* "source":999:1002 */ // 0x64 -// /* "source":900:914 */ +// /* "source":992:1006 */ // sstore -// /* "source":886:924 */ +// /* "source":988:1010 */ // stop // } // // sub_2: assembly { -// /* "source":988:989 */ +// /* "source":1063:1064 */ // 0x02 -// /* "source":983:986 */ +// /* "source":1058:1061 */ // 0x65 -// /* "source":976:990 */ +// /* "source":1051:1065 */ // sstore -// /* "source":962:1000 */ +// /* "source":1047:1069 */ // stop // } // // sub_3: assembly { -// /* "source":1064:1065 */ +// /* "source":1122:1123 */ // 0x03 -// /* "source":1059:1062 */ +// /* "source":1117:1120 */ // 0x66 -// /* "source":1052:1066 */ +// /* "source":1110:1124 */ // sstore -// /* "source":1038:1076 */ +// /* "source":1106:1128 */ // stop // } // // sub_4: assembly { -// /* "source":1140:1141 */ +// /* "source":1181:1182 */ // 0x04 -// /* "source":1135:1138 */ +// /* "source":1176:1179 */ // 0x67 -// /* "source":1128:1142 */ +// /* "source":1169:1183 */ // sstore -// /* "source":1114:1152 */ +// /* "source":1165:1187 */ // stop // } // // sub_5: assembly { -// /* "source":1216:1217 */ +// /* "source":1240:1241 */ // 0x05 -// /* "source":1211:1214 */ +// /* "source":1235:1238 */ // 0x68 -// /* "source":1204:1218 */ +// /* "source":1228:1242 */ // sstore -// /* "source":1190:1228 */ +// /* "source":1224:1246 */ // stop // } // // sub_6: assembly { -// /* "source":1292:1293 */ +// /* "source":1299:1300 */ // 0x06 -// /* "source":1287:1290 */ +// /* "source":1294:1297 */ // 0x69 -// /* "source":1280:1294 */ +// /* "source":1287:1301 */ // sstore -// /* "source":1266:1304 */ +// /* "source":1283:1305 */ // stop // } // // sub_7: assembly { -// /* "source":1368:1369 */ +// /* "source":1358:1359 */ // 0x07 -// /* "source":1363:1366 */ +// /* "source":1353:1356 */ // 0x6a -// /* "source":1356:1370 */ +// /* "source":1346:1360 */ // sstore -// /* "source":1342:1380 */ +// /* "source":1342:1364 */ // stop // } // // sub_8: assembly { -// /* "source":1444:1445 */ +// /* "source":1417:1418 */ // 0x08 -// /* "source":1439:1442 */ +// /* "source":1412:1415 */ // 0x6b -// /* "source":1432:1446 */ +// /* "source":1405:1419 */ // sstore -// /* "source":1418:1456 */ +// /* "source":1401:1423 */ // stop // } // // sub_9: assembly { -// /* "source":1520:1521 */ +// /* "source":1476:1477 */ // 0x09 -// /* "source":1515:1518 */ +// /* "source":1471:1474 */ // 0x6c -// /* "source":1508:1522 */ +// /* "source":1464:1478 */ // sstore -// /* "source":1494:1532 */ +// /* "source":1460:1482 */ // stop // } // // sub_10: assembly { -// /* "source":1596:1598 */ +// /* "source":1535:1537 */ // 0x0a -// /* "source":1591:1594 */ +// /* "source":1530:1533 */ // 0x6d -// /* "source":1584:1599 */ +// /* "source":1523:1538 */ // sstore -// /* "source":1570:1609 */ +// /* "source":1519:1542 */ // stop // } // // sub_11: assembly { -// /* "source":1673:1675 */ +// /* "source":1595:1597 */ // 0x0b -// /* "source":1668:1671 */ +// /* "source":1590:1593 */ // 0x6e -// /* "source":1661:1676 */ +// /* "source":1583:1598 */ // sstore -// /* "source":1647:1686 */ +// /* "source":1579:1602 */ // stop // } // // sub_12: assembly { -// /* "source":1750:1752 */ +// /* "source":1655:1657 */ // 0x0c -// /* "source":1745:1748 */ +// /* "source":1650:1653 */ // 0x6f -// /* "source":1738:1753 */ +// /* "source":1643:1658 */ // sstore -// /* "source":1724:1763 */ +// /* "source":1639:1662 */ // stop // } // // sub_13: assembly { -// /* "source":1827:1829 */ +// /* "source":1715:1717 */ // 0x0d -// /* "source":1822:1825 */ +// /* "source":1710:1713 */ // 0x70 -// /* "source":1815:1830 */ +// /* "source":1703:1718 */ // sstore -// /* "source":1801:1840 */ +// /* "source":1699:1722 */ // stop // } // // sub_14: assembly { -// /* "source":1904:1906 */ +// /* "source":1775:1777 */ // 0x0e -// /* "source":1899:1902 */ +// /* "source":1770:1773 */ // 0x71 -// /* "source":1892:1907 */ +// /* "source":1763:1778 */ // sstore -// /* "source":1878:1917 */ +// /* "source":1759:1782 */ // stop // } // // sub_15: assembly { -// /* "source":1981:1983 */ +// /* "source":1835:1837 */ // 0x0f -// /* "source":1976:1979 */ +// /* "source":1830:1833 */ // 0x72 -// /* "source":1969:1984 */ +// /* "source":1823:1838 */ // sstore -// /* "source":1955:1994 */ +// /* "source":1819:1842 */ // stop // } // // sub_16: assembly { -// /* "source":2059:2061 */ +// /* "source":1924:1926 */ // 0x10 -// /* "source":2054:2057 */ +// /* "source":1919:1922 */ // 0x73 -// /* "source":2047:2062 */ +// /* "source":1912:1927 */ // sstore -// /* "source":2087:2104 */ +// /* "source":1956:1973 */ // dataSize(sub_0) -// /* "source":2082:2085 */ +// /* "source":1951:1954 */ // 0xc9 -// /* "source":2075:2105 */ +// /* "source":1944:1974 */ // sstore -// /* "source":2033:2115 */ +// /* "source":1880:1998 */ // stop // stop // // sub_0: assembly { -// /* "source":2188:2190 */ +// /* "source":2057:2059 */ // 0x10 -// /* "source":2183:2186 */ +// /* "source":2052:2055 */ // 0x012c -// /* "source":2176:2191 */ +// /* "source":2045:2060 */ // sstore -// /* "source":2158:2205 */ +// /* "source":2041:2064 */ // stop // } // } // Bytecode: 61005c5f55600b600155600660025560066003556006600455600660055560066006556006600755600660085560066009556006600a556006600b556006600c556006600d556006600e556006600f556006601055600c60115500fe // Opcodes: PUSH2 0x5C PUSH0 SSTORE PUSH1 0xB PUSH1 0x1 SSTORE PUSH1 0x6 PUSH1 0x2 SSTORE PUSH1 0x6 PUSH1 0x3 SSTORE PUSH1 0x6 PUSH1 0x4 SSTORE PUSH1 0x6 PUSH1 0x5 SSTORE PUSH1 0x6 PUSH1 0x6 SSTORE PUSH1 0x6 PUSH1 0x7 SSTORE PUSH1 0x6 PUSH1 0x8 SSTORE PUSH1 0x6 PUSH1 0x9 SSTORE PUSH1 0x6 PUSH1 0xA SSTORE PUSH1 0x6 PUSH1 0xB SSTORE PUSH1 0x6 PUSH1 0xC SSTORE PUSH1 0x6 PUSH1 0xD SSTORE PUSH1 0x6 PUSH1 0xE SSTORE PUSH1 0x6 PUSH1 0xF SSTORE PUSH1 0x6 PUSH1 0x10 SSTORE PUSH1 0xC PUSH1 0x11 SSTORE STOP INVALID -// SourceMappings: 45:16:0:-:0;42:1;35:27;81:13;78:1;71:24;114:13;111:1;104:24;147:13;144:1;137:24;180:13;177:1;170:24;213:13;210:1;203:24;246:13;243:1;236:24;279:13;276:1;269:24;312:13;309:1;302:24;345:13;342:1;335:24;379:13;375:2;368:25;413:13;409:2;402:25;447:13;443:2;436:25;481:13;477:2;470:25;515:13;511:2;504:25;549:13;545:2;538:25;583:13;579:2;572:25;617:14;613:2;606:26;25:613 +// SourceMappings: 59:16:0:-:0;56:1;49:27;99:13;96:1;89:24;136:13;133:1;126:24;173:13;170:1;163:24;210:13;207:1;200:24;247:13;244:1;237:24;284:13;281:1;274:24;321:13;318:1;311:24;358:13;355:1;348:24;395:13;392:1;385:24;433:13;429:2;422:25;471:13;467:2;460:25;509:13;505:2;498:25;547:13;543:2;536:25;585:13;581:2;574:25;623:13;619:2;612:25;661:13;657:2;650:25;699:14;695:2;688:26;25:705 diff --git a/test/libyul/objectCompiler/metadata.yul b/test/libyul/objectCompiler/metadata.yul index 335522d04..4f8cda7a4 100644 --- a/test/libyul/objectCompiler/metadata.yul +++ b/test/libyul/objectCompiler/metadata.yul @@ -21,34 +21,34 @@ object "A" { } // ---- // Assembly: -// /* "source":35:48 */ +// /* "source":55:68 */ // 0x0e -// /* "source":62:75 */ +// /* "source":90:103 */ // 0x03 -// /* "source":80:92 */ +// /* "source":116:128 */ // swap1 -// /* "source":87:88 */ +// /* "source":123:124 */ // 0x00 -// /* "source":80:92 */ +// /* "source":116:128 */ // sstore -// /* "source":104:106 */ +// /* "source":148:150 */ // 0x20 -// /* "source":97:110 */ +// /* "source":141:154 */ // sstore -// /* "source":20:114 */ +// /* "source":22:170 */ // stop // stop // data_211450822d7f8c345093893187e7e1fbebc4ec67af72601920194be14104e336 48656c6c6f2c20576f726c643221 // data_e1629b9dda060bb30c7908346f6af189c16773fa148d3366701fbaa35d54f3c8 414243 // // sub_0: assembly { -// /* "source":157:176 */ +// /* "source":242:261 */ // data_211450822d7f8c345093893187e7e1fbebc4ec67af72601920194be14104e336 -// /* "source":190:191 */ +// /* "source":285:286 */ // 0x00 -// /* "source":183:195 */ +// /* "source":278:290 */ // sstore -// /* "source":140:201 */ +// /* "source":201:314 */ // stop // stop // data_211450822d7f8c345093893187e7e1fbebc4ec67af72601920194be14104e336 48656c6c6f2c20576f726c643221 @@ -59,4 +59,4 @@ object "A" { // auxdata: 0x4d32 // Bytecode: 600e6003905f5560205500fe4d32 // Opcodes: PUSH1 0xE PUSH1 0x3 SWAP1 PUSH0 SSTORE PUSH1 0x20 SSTORE STOP INVALID 0x4D ORIGIN -// SourceMappings: 35:13:0:-:0;62;80:12;87:1;80:12;104:2;97:13;20:94 +// SourceMappings: 55:13:0:-:0;90;116:12;123:1;116:12;148:2;141:13;22:148 diff --git a/test/libyul/objectCompiler/namedObject.yul b/test/libyul/objectCompiler/namedObject.yul index d55c3ca25..06539dd89 100644 --- a/test/libyul/objectCompiler/namedObject.yul +++ b/test/libyul/objectCompiler/namedObject.yul @@ -3,8 +3,8 @@ object "a" { } // ---- // Assembly: -// /* "source":20:22 */ +// /* "source":22:29 */ // stop // Bytecode: 00 // Opcodes: STOP -// SourceMappings: 20:2:0:-:0 +// SourceMappings: 22:7:0:-:0 diff --git a/test/libyul/objectCompiler/namedObjectCode.yul b/test/libyul/objectCompiler/namedObjectCode.yul index 5936aa744..f18535d71 100644 --- a/test/libyul/objectCompiler/namedObjectCode.yul +++ b/test/libyul/objectCompiler/namedObjectCode.yul @@ -3,14 +3,14 @@ object "a" { } // ---- // Assembly: -// /* "source":32:33 */ +// /* "source":36:37 */ // 0x01 -// /* "source":29:30 */ +// /* "source":33:34 */ // 0x00 -// /* "source":22:34 */ +// /* "source":26:38 */ // sstore -// /* "source":20:36 */ +// /* "source":22:42 */ // stop // Bytecode: 60015f5500 // Opcodes: PUSH1 0x1 PUSH0 SSTORE STOP -// SourceMappings: 32:1:0:-:0;29;22:12;20:16 +// SourceMappings: 36:1:0:-:0;33;26:12;22:20 diff --git a/test/libyul/objectCompiler/nested_optimizer.yul b/test/libyul/objectCompiler/nested_optimizer.yul index cde1210ff..ae0650942 100644 --- a/test/libyul/objectCompiler/nested_optimizer.yul +++ b/test/libyul/objectCompiler/nested_optimizer.yul @@ -18,28 +18,28 @@ object "a" { // optimizationPreset: full // ---- // Assembly: -// /* "source":48:49 */ +// /* "source":58:59 */ // 0x00 -// /* "source":35:50 */ +// /* "source":41:56 */ // dup1 // calldataload -// /* "source":107:127 */ +// /* "source":34:60 */ // sstore -// /* "source":20:131 */ +// /* "source":22:68 */ // stop // stop // // sub_0: assembly { -// /* "source":188:189 */ +// /* "source":141:142 */ // 0x00 -// /* "source":175:190 */ +// /* "source":124:139 */ // dup1 // calldataload -// /* "source":253:273 */ +// /* "source":117:143 */ // sstore -// /* "source":158:279 */ +// /* "source":101:155 */ // stop // } // Bytecode: 5f80355500fe // Opcodes: PUSH0 DUP1 CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: 48:1:0:-:0;35:15;;107:20;20:111 +// SourceMappings: 58:1:0:-:0;41:15;;34:26;22:46 diff --git a/test/libyul/objectCompiler/simple.yul b/test/libyul/objectCompiler/simple.yul index b84c49a5a..fb2339ceb 100644 --- a/test/libyul/objectCompiler/simple.yul +++ b/test/libyul/objectCompiler/simple.yul @@ -3,14 +3,14 @@ } // ---- // Assembly: -// /* "source":14:15 */ +// /* "source":41:42 */ // 0x01 -// /* "source":11:12 */ +// /* "source":38:39 */ // 0x00 -// /* "source":4:16 */ +// /* "source":31:43 */ // sstore -// /* "source":0:18 */ +// /* "source":27:47 */ // stop // Bytecode: 60015f5500 // Opcodes: PUSH1 0x1 PUSH0 SSTORE STOP -// SourceMappings: 14:1:0:-:0;11;4:12;0:18 +// SourceMappings: 41:1:0:-:0;38;31:12;27:20 diff --git a/test/libyul/objectCompiler/simple_optimizer.yul b/test/libyul/objectCompiler/simple_optimizer.yul index 3ce4b7a4b..cc6307589 100644 --- a/test/libyul/objectCompiler/simple_optimizer.yul +++ b/test/libyul/objectCompiler/simple_optimizer.yul @@ -8,15 +8,15 @@ // optimizationPreset: full // ---- // Assembly: -// /* "source":26:27 */ +// /* "source":63:64 */ // 0x00 -// /* "source":13:28 */ +// /* "source":46:61 */ // dup1 // calldataload -// /* "source":79:99 */ +// /* "source":39:65 */ // sstore -// /* "source":0:101 */ +// /* "source":27:73 */ // stop // Bytecode: 5f80355500 // Opcodes: PUSH0 DUP1 CALLDATALOAD SSTORE STOP -// SourceMappings: 26:1:0:-:0;13:15;;79:20;0:101 +// SourceMappings: 63:1:0:-:0;46:15;;39:26;27:46 diff --git a/test/libyul/objectCompiler/smoke.yul b/test/libyul/objectCompiler/smoke.yul index 3f1079aa7..82aea42f5 100644 --- a/test/libyul/objectCompiler/smoke.yul +++ b/test/libyul/objectCompiler/smoke.yul @@ -2,8 +2,8 @@ } // ---- // Assembly: -// /* "source":0:3 */ +// /* "source":27:34 */ // stop // Bytecode: 00 // Opcodes: STOP -// SourceMappings: 0:3:0:-:0 +// SourceMappings: 27:7:0:-:0 diff --git a/test/libyul/objectCompiler/subObject.yul b/test/libyul/objectCompiler/subObject.yul index 46fc03f10..a47c4feda 100644 --- a/test/libyul/objectCompiler/subObject.yul +++ b/test/libyul/objectCompiler/subObject.yul @@ -6,21 +6,21 @@ object "a" { } // ---- // Assembly: -// /* "source":20:22 */ +// /* "source":22:29 */ // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // // sub_0: assembly { -// /* "source":149:150 */ +// /* "source":123:124 */ // 0x01 -// /* "source":146:147 */ +// /* "source":120:121 */ // 0x00 -// /* "source":139:151 */ +// /* "source":113:125 */ // sstore -// /* "source":137:153 */ +// /* "source":109:129 */ // stop // } // Bytecode: 00fe // Opcodes: STOP INVALID -// SourceMappings: 20:2:0:-:0 +// SourceMappings: 22:7:0:-:0 diff --git a/test/libyul/objectCompiler/subObjectAccess.yul b/test/libyul/objectCompiler/subObjectAccess.yul index 291749220..b18c902db 100644 --- a/test/libyul/objectCompiler/subObjectAccess.yul +++ b/test/libyul/objectCompiler/subObjectAccess.yul @@ -67,164 +67,164 @@ object "A" { } // ---- // Assembly: -// /* "source":37:52 */ +// /* "source":57:72 */ // 0x00 -// /* "source":68:81 */ +// /* "source":96:109 */ // bytecodeSize -// /* "source":97:112 */ +// /* "source":133:148 */ // dataOffset(sub_0) -// /* "source":128:141 */ +// /* "source":172:185 */ // dataSize(sub_0) -// /* "source":158:175 */ +// /* "source":210:227 */ // dataOffset(sub_0.sub_0) -// /* "source":192:207 */ +// /* "source":252:267 */ // dataSize(sub_0.sub_0) -// /* "source":224:241 */ +// /* "source":292:309 */ // swap1 // dataOffset(sub_0.sub_1) -// /* "source":258:273 */ +// /* "source":334:349 */ // swap3 // dataSize(sub_0.sub_1) -// /* "source":291:310 */ +// /* "source":375:394 */ // swap5 // dataOffset(sub_0.sub_0.sub_0) -// /* "source":328:345 */ +// /* "source":420:437 */ // swap7 // dataSize(sub_0.sub_0.sub_0) -// /* "source":351:365 */ +// /* "source":450:464 */ // swap9 -// /* "source":358:359 */ +// /* "source":457:458 */ // 0x00 -// /* "source":351:365 */ +// /* "source":450:464 */ // sstore -// /* "source":377:379 */ +// /* "source":484:486 */ // 0x20 -// /* "source":370:385 */ +// /* "source":477:492 */ // sstore -// /* "source":397:399 */ +// /* "source":512:514 */ // 0x40 -// /* "source":390:405 */ +// /* "source":505:520 */ // sstore -// /* "source":417:419 */ +// /* "source":540:542 */ // 0x60 -// /* "source":410:425 */ +// /* "source":533:548 */ // sstore -// /* "source":437:440 */ +// /* "source":568:571 */ // 0x80 -// /* "source":430:447 */ +// /* "source":561:578 */ // sstore -// /* "source":459:462 */ +// /* "source":598:601 */ // 0xa0 -// /* "source":452:469 */ +// /* "source":591:608 */ // sstore -// /* "source":481:484 */ +// /* "source":628:631 */ // 0xc0 -// /* "source":474:491 */ +// /* "source":621:638 */ // sstore -// /* "source":503:506 */ +// /* "source":658:661 */ // 0xe0 -// /* "source":496:513 */ +// /* "source":651:668 */ // sstore -// /* "source":525:528 */ +// /* "source":688:691 */ // 0x0100 -// /* "source":518:536 */ +// /* "source":681:699 */ // sstore -// /* "source":548:551 */ +// /* "source":719:722 */ // 0x0120 -// /* "source":541:559 */ +// /* "source":712:730 */ // sstore -// /* "source":574:577 */ +// /* "source":753:756 */ // 0x0140 -// /* "source":571:572 */ +// /* "source":750:751 */ // 0x00 -// /* "source":564:578 */ +// /* "source":743:757 */ // return // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // // sub_0: assembly { -// /* "source":659:674 */ +// /* "source":896:911 */ // dataOffset(sub_0) -// /* "source":692:705 */ +// /* "source":939:952 */ // dataSize(sub_0) -// /* "source":723:738 */ +// /* "source":980:995 */ // dataOffset(sub_1) -// /* "source":756:769 */ +// /* "source":1023:1036 */ // dataSize(sub_1) -// /* "source":788:805 */ +// /* "source":1065:1082 */ // swap1 // dataOffset(sub_0.sub_0) -// /* "source":824:839 */ +// /* "source":1111:1126 */ // swap3 // dataSize(sub_0.sub_0) -// /* "source":847:861 */ +// /* "source":1143:1157 */ // swap5 -// /* "source":854:855 */ +// /* "source":1150:1151 */ // 0x00 -// /* "source":847:861 */ +// /* "source":1143:1157 */ // sstore -// /* "source":875:877 */ +// /* "source":1181:1183 */ // 0x20 -// /* "source":868:883 */ +// /* "source":1174:1189 */ // sstore -// /* "source":897:899 */ +// /* "source":1213:1215 */ // 0x40 -// /* "source":890:905 */ +// /* "source":1206:1221 */ // sstore -// /* "source":919:921 */ +// /* "source":1245:1247 */ // 0x60 -// /* "source":912:927 */ +// /* "source":1238:1253 */ // sstore -// /* "source":941:944 */ +// /* "source":1277:1280 */ // 0x80 -// /* "source":934:951 */ +// /* "source":1270:1287 */ // sstore -// /* "source":965:968 */ +// /* "source":1311:1314 */ // 0xa0 -// /* "source":958:975 */ +// /* "source":1304:1321 */ // sstore -// /* "source":992:995 */ +// /* "source":1348:1351 */ // 0xc0 -// /* "source":989:990 */ +// /* "source":1345:1346 */ // 0x00 -// /* "source":982:996 */ +// /* "source":1338:1352 */ // return // stop // // sub_0: assembly { -// /* "source":1052:1067 */ +// /* "source":1466:1481 */ // dataOffset(sub_0) -// /* "source":1087:1100 */ +// /* "source":1513:1526 */ // dataSize(sub_0) -// /* "source":1110:1124 */ +// /* "source":1547:1561 */ // swap1 -// /* "source":1117:1118 */ +// /* "source":1554:1555 */ // 0x00 -// /* "source":1110:1124 */ +// /* "source":1547:1561 */ // sstore -// /* "source":1140:1142 */ +// /* "source":1589:1591 */ // 0x20 -// /* "source":1133:1148 */ +// /* "source":1582:1597 */ // sstore -// /* "source":1167:1169 */ +// /* "source":1628:1630 */ // 0x40 -// /* "source":1164:1165 */ +// /* "source":1625:1626 */ // 0x00 -// /* "source":1157:1170 */ +// /* "source":1618:1631 */ // return // stop // // sub_0: assembly { -// /* "source":1223:1232 */ +// /* "source":1714:1723 */ // invalid // } // } // // sub_1: assembly { -// /* "source":1295:1304 */ +// /* "source":1794:1803 */ // invalid // } // } // Bytecode: 5f6084603d603660746010906073926001946073966001985f5560205560405560605560805560a05560c05560e05561010055610120556101405ff3fe6025601060356001906035926001945f5560205560405560605560805560a05560c05ff3fe600f6001905f5560205560405ff3fefefefe600f6001905f5560205560405ff3fefe // Opcodes: PUSH0 PUSH1 0x84 PUSH1 0x3D PUSH1 0x36 PUSH1 0x74 PUSH1 0x10 SWAP1 PUSH1 0x73 SWAP3 PUSH1 0x1 SWAP5 PUSH1 0x73 SWAP7 PUSH1 0x1 SWAP9 PUSH0 SSTORE PUSH1 0x20 SSTORE PUSH1 0x40 SSTORE PUSH1 0x60 SSTORE PUSH1 0x80 SSTORE PUSH1 0xA0 SSTORE PUSH1 0xC0 SSTORE PUSH1 0xE0 SSTORE PUSH2 0x100 SSTORE PUSH2 0x120 SSTORE PUSH2 0x140 PUSH0 RETURN INVALID PUSH1 0x25 PUSH1 0x10 PUSH1 0x35 PUSH1 0x1 SWAP1 PUSH1 0x35 SWAP3 PUSH1 0x1 SWAP5 PUSH0 SSTORE PUSH1 0x20 SSTORE PUSH1 0x40 SSTORE PUSH1 0x60 SSTORE PUSH1 0x80 SSTORE PUSH1 0xA0 SSTORE PUSH1 0xC0 PUSH0 RETURN INVALID PUSH1 0xF PUSH1 0x1 SWAP1 PUSH0 SSTORE PUSH1 0x20 SSTORE PUSH1 0x40 PUSH0 RETURN INVALID INVALID INVALID INVALID PUSH1 0xF PUSH1 0x1 SWAP1 PUSH0 SSTORE PUSH1 0x20 SSTORE PUSH1 0x40 PUSH0 RETURN INVALID INVALID -// SourceMappings: 37:15:0:-:0;68:13;97:15;128:13;158:17;192:15;224:17;;258:15;;291:19;;328:17;;351:14;358:1;351:14;377:2;370:15;397:2;390:15;417:2;410:15;437:3;430:17;459:3;452:17;481:3;474:17;503:3;496:17;525:3;518:18;548:3;541:18;574:3;571:1;564:14 +// SourceMappings: 57:15:0:-:0;96:13;133:15;172:13;210:17;252:15;292:17;;334:15;;375:19;;420:17;;450:14;457:1;450:14;484:2;477:15;512:2;505:15;540:2;533:15;568:3;561:17;598:3;591:17;628:3;621:17;658:3;651:17;688:3;681:18;719:3;712:18;753:3;750:1;743:14 diff --git a/test/libyul/objectCompiler/subSubObject.yul b/test/libyul/objectCompiler/subSubObject.yul index a9936d58f..a4511324e 100644 --- a/test/libyul/objectCompiler/subSubObject.yul +++ b/test/libyul/objectCompiler/subSubObject.yul @@ -12,30 +12,30 @@ object "a" { } // ---- // Assembly: -// /* "source":20:22 */ +// /* "source":22:29 */ // stop // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // // sub_0: assembly { -// /* "source":153:154 */ +// /* "source":123:124 */ // 0x01 -// /* "source":150:151 */ +// /* "source":120:121 */ // 0x00 -// /* "source":143:155 */ +// /* "source":113:125 */ // sstore -// /* "source":141:157 */ +// /* "source":109:129 */ // stop // stop // // sub_0: assembly { -// /* "source":203:204 */ +// /* "source":187:188 */ // 0x03 -// /* "source":200:201 */ +// /* "source":184:185 */ // 0x02 -// /* "source":193:205 */ +// /* "source":177:189 */ // sstore -// /* "source":191:207 */ +// /* "source":173:193 */ // stop // stop // data_6adf031833174bbe4c85eafe59ddb54e6584648c2c962c6f94791ab49caa0ad4 123456 @@ -43,4 +43,4 @@ object "a" { // } // Bytecode: 00fe // Opcodes: STOP INVALID -// SourceMappings: 20:2:0:-:0 +// SourceMappings: 22:7:0:-:0 diff --git a/test/libyul/objectCompiler/verbatim_bug.yul b/test/libyul/objectCompiler/verbatim_bug.yul index 778494f0b..14a1c02b1 100644 --- a/test/libyul/objectCompiler/verbatim_bug.yul +++ b/test/libyul/objectCompiler/verbatim_bug.yul @@ -26,99 +26,99 @@ object "a" { // optimizationPreset: full // ---- // Assembly: -// /* "source":87:88 */ +// /* "source":65:66 */ // 0x00 -// /* "source":81:89 */ +// /* "source":59:67 */ // dup1 // sload -// /* "source":139:307 */ +// /* "source":133:225 */ // dup1 // iszero // tag_1 // jumpi -// /* "source":316:361 */ +// /* "source":238:263 */ // dup1 -// /* "source":321:325 */ +// /* "source":243:247 */ // 0x01 -// /* "source":316:361 */ +// /* "source":238:263 */ // eq // tag_3 // jumpi -// /* "source":370:448 */ +// /* "source":276:368 */ // dup1 -// /* "source":375:379 */ +// /* "source":281:285 */ // 0x02 -// /* "source":370:448 */ +// /* "source":276:368 */ // eq // tag_5 // jumpi -// /* "source":462:466 */ +// /* "source":386:390 */ // 0x03 -// /* "source":457:502 */ +// /* "source":381:406 */ // eq // tag_7 // jumpi -// /* "source":87:88 */ +// /* "source":426:427 */ // 0x00 -// /* "source":512:529 */ +// /* "source":419:436 */ // sstore -// /* "source":118:502 */ +// /* "source":108:406 */ // stop -// /* "source":467:502 */ +// /* "source":391:406 */ // tag_7: -// /* "source":481:492 */ +// /* "source":393:404 */ // pop -// /* "source":491:492 */ +// /* "source":403:404 */ // 0x03 -// /* "source":87:88 */ +// /* "source":426:427 */ // 0x00 -// /* "source":512:529 */ +// /* "source":419:436 */ // sstore -// /* "source":118:502 */ +// /* "source":108:406 */ // stop -// /* "source":380:448 */ +// /* "source":286:368 */ // tag_5: -// /* "source":404:438 */ +// /* "source":314:354 */ // pop // pop -// /* "source":45:59 */ +// /* "source":339:353 */ // 0xaabbccddeeff -// /* "source":404:438 */ +// /* "source":314:354 */ // verbatimbytecode_506002 -// /* "source":87:88 */ +// /* "source":426:427 */ // 0x00 -// /* "source":512:529 */ +// /* "source":419:436 */ // sstore -// /* "source":118:502 */ +// /* "source":108:406 */ // stop -// /* "source":326:361 */ +// /* "source":248:263 */ // tag_3: -// /* "source":340:351 */ +// /* "source":250:261 */ // pop // pop -// /* "source":350:351 */ +// /* "source":260:261 */ // 0x01 -// /* "source":87:88 */ +// /* "source":426:427 */ // 0x00 -// /* "source":512:529 */ +// /* "source":419:436 */ // sstore -// /* "source":118:502 */ +// /* "source":108:406 */ // stop -// /* "source":149:307 */ +// /* "source":143:225 */ // tag_1: -// /* "source":263:297 */ +// /* "source":171:211 */ // pop // pop -// /* "source":45:59 */ +// /* "source":196:210 */ // 0xaabbccddeeff -// /* "source":263:297 */ +// /* "source":171:211 */ // verbatimbytecode_506000 -// /* "source":87:88 */ +// /* "source":426:427 */ // 0x00 -// /* "source":512:529 */ +// /* "source":419:436 */ // sstore -// /* "source":118:502 */ +// /* "source":108:406 */ // stop // Bytecode: 5f80548015603e578060011460365780600214602657600314601f575f55005b5060035f55005b505065aabbccddeeff5060025f55005b505060015f55005b505065aabbccddeeff5060005f5500 // Opcodes: PUSH0 DUP1 SLOAD DUP1 ISZERO PUSH1 0x3E JUMPI DUP1 PUSH1 0x1 EQ PUSH1 0x36 JUMPI DUP1 PUSH1 0x2 EQ PUSH1 0x26 JUMPI PUSH1 0x3 EQ PUSH1 0x1F JUMPI PUSH0 SSTORE STOP JUMPDEST POP PUSH1 0x3 PUSH0 SSTORE STOP JUMPDEST POP POP PUSH6 0xAABBCCDDEEFF POP PUSH1 0x2 PUSH0 SSTORE STOP JUMPDEST POP POP PUSH1 0x1 PUSH0 SSTORE STOP JUMPDEST POP POP PUSH6 0xAABBCCDDEEFF POP PUSH1 0x0 PUSH0 SSTORE STOP -// SourceMappings: 87:1:0:-:0;81:8;;139:168;;;;316:45;321:4;316:45;;;370:78;375:4;370:78;;;462:4;457:45;;;87:1;512:17;118:384;467:35;481:11;491:1;87;512:17;118:384;380:68;404:34;;45:14;404:34;87:1;512:17;118:384;326:35;340:11;;350:1;87;512:17;118:384;149:158;263:34;;45:14;263:34;87:1;512:17;118:384 +// SourceMappings: 65:1:0:-:0;59:8;;133:92;;;;238:25;243:4;238:25;;;276:92;281:4;276:92;;;386:4;381:25;;;426:1;419:17;108:298;391:15;393:11;403:1;426;419:17;108:298;286:82;314:40;;339:14;314:40;426:1;419:17;108:298;248:15;250:11;;260:1;426;419:17;108:298;143:82;171:40;;196:14;171:40;426:1;419:17;108:298 From ea85a788255738d36c0d3f886b7f5919f293bc29 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 6 Aug 2024 14:45:02 +0200 Subject: [PATCH 0244/1340] CLI: remove --yul flag --- Changelog.md | 1 + solc/CommandLineParser.cpp | 19 ++++++++----- test/cmdlineTests/yul_optimize_runs/args | 2 +- test/cmdlineTests/~assembler_modes/test.sh | 21 ++++++++------ test/solc/CommandLineInterface.cpp | 9 +++--- test/solc/CommandLineParser.cpp | 32 ++++++++++------------ 6 files changed, 45 insertions(+), 39 deletions(-) diff --git a/Changelog.md b/Changelog.md index 5e8a7bef8..71cff3e1f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -18,6 +18,7 @@ Compiler Features: * SMTChecker: Replace CVC4 as a possible BMC backend with cvc5. * Standard JSON Interface: Do not perform IR optimization when only unoptimized IR is requested. * Standard JSON Interface: Add ``transientStorageLayout`` output. + * Yul: Drop the deprecated typed Yul dialect that was only accessible via ``--yul`` in the CLI. * Yul Optimizer: The optimizer now treats some previously unrecognized identical literals as identical. * Commandline Interface: Allow the use of ``--asm-json`` output option in assembler mode to export EVM assembly of the contracts in JSON format. diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 97c690140..19089d885 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -618,6 +618,9 @@ General Information)").c_str(), "Select desired EOF version. Currently the only valid value is 1. " "If not specified, legacy non-EOF bytecode will be generated." ) + ( + g_strYul.c_str(), "The typed Yul dialect is no longer supported. For regular Yul compilation use --strict-assembly instead." + ) ; outputOptions.add_options() ( @@ -664,10 +667,6 @@ General Information)").c_str(), g_strAssemble.c_str(), "Switch to assembly mode and assume input is assembly." ) - ( - g_strYul.c_str(), - "Switch to Yul mode and assume input is Yul." - ) ( g_strStrictAssembly.c_str(), "Switch to strict assembly mode and assume input is strict assembly." @@ -956,7 +955,6 @@ void CommandLineParser::processArgs() g_strLink, g_strAssemble, g_strStrictAssembly, - g_strYul, g_strImportAst, g_strLSP, g_strImportEvmAssemblerJson, @@ -972,7 +970,7 @@ void CommandLineParser::processArgs() m_options.input.mode = InputMode::StandardJson; else if (m_args.count(g_strLSP)) m_options.input.mode = InputMode::LanguageServer; - else if (m_args.count(g_strAssemble) > 0 || m_args.count(g_strStrictAssembly) > 0 || m_args.count(g_strYul) > 0) + else if (m_args.count(g_strAssemble) > 0 || m_args.count(g_strStrictAssembly) > 0) m_options.input.mode = InputMode::Assembler; else if (m_args.count(g_strLink) > 0) m_options.input.mode = InputMode::Linker; @@ -990,6 +988,13 @@ void CommandLineParser::processArgs() ) return; + if (m_args.count(g_strYul) > 0) + solThrow( + CommandLineValidationError, + "The typed Yul dialect formerly accessible via --yul is no longer supported, " + "please use --strict-assembly instead." + ); + std::map> validOptionInputModeCombinations = { // TODO: This should eventually contain all options. {g_strExperimentalViaIR, {InputMode::Compiler, InputMode::CompilerWithASTImport}}, @@ -1276,7 +1281,7 @@ void CommandLineParser::processArgs() // switch to assembly mode using Input = yul::YulStack::Language; using Machine = yul::YulStack::Machine; - m_options.assembly.inputLanguage = m_args.count(g_strYul) ? Input::Yul : (m_args.count(g_strStrictAssembly) ? Input::StrictAssembly : Input::Assembly); + m_options.assembly.inputLanguage = m_args.count(g_strStrictAssembly) ? Input::StrictAssembly : Input::Assembly; if (m_args.count(g_strMachine)) { diff --git a/test/cmdlineTests/yul_optimize_runs/args b/test/cmdlineTests/yul_optimize_runs/args index 033abe3bb..3a8567e92 100644 --- a/test/cmdlineTests/yul_optimize_runs/args +++ b/test/cmdlineTests/yul_optimize_runs/args @@ -1 +1 @@ ---yul --yul-dialect evm --optimize --optimize-runs 10000 +--strict-assembly --yul-dialect evm --optimize --optimize-runs 10000 diff --git a/test/cmdlineTests/~assembler_modes/test.sh b/test/cmdlineTests/~assembler_modes/test.sh index 5ca1bb40f..708c76395 100755 --- a/test/cmdlineTests/~assembler_modes/test.sh +++ b/test/cmdlineTests/~assembler_modes/test.sh @@ -25,19 +25,24 @@ function test_solc_assembly_output } echo '{}' | msg_on_error --silent "$SOLC" - --assemble -echo '{}' | msg_on_error --silent "$SOLC" - --yul echo '{}' | msg_on_error --silent "$SOLC" - --strict-assembly -# Test options above in conjunction with --optimize. -# Using both, --assemble and --optimize should fail. +# Test in conjunction with --optimize. Using both, --assemble and --optimize should fail. echo '{}' | "$SOLC" - --assemble --optimize &>/dev/null && fail "solc --assemble --optimize did not fail as expected." -echo '{}' | "$SOLC" - --yul --optimize &>/dev/null && fail "solc --yul --optimize did not fail as expected." -# Test yul and strict assembly output +# Test strict assembly output # Non-empty code results in non-empty binary representation with optimizations turned off, # while it results in empty binary representation with optimizations turned on. -test_solc_assembly_output "{ let x:u256 := 0:u256 mstore(0, x) }" "{ { let x := 0 mstore(0, x) } }" "--yul" -test_solc_assembly_output "{ let x:u256 := bitnot(7:u256) mstore(0, x) }" "{ { let x := bitnot(7) mstore(0, x) } }" "--yul" -test_solc_assembly_output "{ let t:bool := not(true) if t { mstore(0, 1) } }" "{ { let t:bool := not(true) if t { mstore(0, 1) } } }" "--yul" test_solc_assembly_output "{ let x := 0 mstore(0, x) }" "{ { let x := 0 mstore(0, x) } }" "--strict-assembly" test_solc_assembly_output "{ let x := 0 mstore(0, x) }" "{ { } }" "--strict-assembly --optimize" + +# Test that --yul triggers an error +set +e +output=$(echo '{}' | "$SOLC" - --yul 2>&1) +failed=$? +expected="Error: The typed Yul dialect formerly accessible via --yul is no longer supported, please use --strict-assembly instead." +set -e +if [[ $output != "${expected}" ]] || (( failed == 0 )) +then + fail "Incorrect error response to --yul flag: $output" +fi diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index b3b93cb3a..6d19df01b 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(version) BOOST_AUTO_TEST_CASE(multiple_input_modes) { - std::array inputModeOptions = { + std::array inputModeOptions { "--help", "--license", "--version", @@ -156,17 +156,16 @@ BOOST_AUTO_TEST_CASE(multiple_input_modes) "--link", "--assemble", "--strict-assembly", - "--yul", "--import-ast", "--import-asm-json", }; std::string expectedMessage = "The following options are mutually exclusive: " - "--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --yul, --import-ast, --lsp, --import-asm-json. " + "--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --import-ast, --lsp, --import-asm-json. " "Select at most one."; - for (std::string const& mode1: inputModeOptions) - for (std::string const& mode2: inputModeOptions) + for (auto const& mode1: inputModeOptions) + for (auto const& mode2: inputModeOptions) if (mode1 != mode2) BOOST_CHECK_EXCEPTION( parseCommandLineAndReadInputFiles({"solc", mode1, mode2}), diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 37c638a3b..e0347a18c 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -250,7 +250,6 @@ BOOST_AUTO_TEST_CASE(no_import_callback) {"solc", "--strict-assembly", "--no-import-callback", "input.yul"}, {"solc", "--import-ast", "--no-import-callback", "ast.json"}, {"solc", "--link", "--no-import-callback", "input.bin"}, - {"solc", "--yul", "--no-import-callback", "input.yul"}, }; for (auto const& commandLine: commandLinePerInputMode) @@ -271,13 +270,10 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) { static std::vector, YulStack::Machine, YulStack::Language>> const allowedCombinations = { {{"--machine=evm", "--yul-dialect=evm", "--assemble"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, - {{"--machine=evm", "--yul-dialect=evm", "--yul"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, {{"--machine=evm", "--yul-dialect=evm", "--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, {{"--machine=evm", "--assemble"}, YulStack::Machine::EVM, YulStack::Language::Assembly}, - {{"--machine=evm", "--yul"}, YulStack::Machine::EVM, YulStack::Language::Yul}, {{"--machine=evm", "--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, {{"--assemble"}, YulStack::Machine::EVM, YulStack::Language::Assembly}, - {{"--yul"}, YulStack::Machine::EVM, YulStack::Language::Yul}, {{"--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, }; @@ -424,20 +420,20 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations) { std::map> invalidOptionInputModeCombinations = { // TODO: This should eventually contain all options. - {"--experimental-via-ir", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--via-ir", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--metadata-literal", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--metadata-hash=swarm", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-show-proved-safe", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-show-unproved", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-show-unsupported", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-div-mod-no-slacks", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-engine=bmc", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-invariants=contract,reentrancy", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-solvers=z3,smtlib2", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-timeout=5", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-contracts=contract1.yul:A,contract2.yul:B", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-targets=underflow,divByZero", {"--assemble", "--yul", "--strict-assembly", "--standard-json", "--link"}} + {"--experimental-via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--metadata-literal", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--metadata-hash=swarm", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--model-checker-show-proved-safe", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--model-checker-show-unproved", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--model-checker-show-unsupported", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--model-checker-div-mod-no-slacks", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--model-checker-engine=bmc", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--model-checker-invariants=contract,reentrancy", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--model-checker-solvers=z3,smtlib2", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--model-checker-timeout=5", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--model-checker-contracts=contract1.yul:A,contract2.yul:B", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--model-checker-targets=underflow,divByZero", {"--assemble", "--strict-assembly", "--standard-json", "--link"}} }; for (auto const& [optionName, inputModes]: invalidOptionInputModeCombinations) From 55a5fd9b8bdd2cdcbc4cafdad2c0e4189aaba607 Mon Sep 17 00:00:00 2001 From: pgebal Date: Fri, 9 Aug 2024 14:47:53 +0200 Subject: [PATCH 0245/1340] Fix SMT logic error when assigning to an array of contracts or functions (#15322) --- Changelog.md | 1 + libsolidity/formal/SymbolicTypes.cpp | 8 ++++++++ .../types/array_of_contracts.sol | 17 +++++++++++++++++ .../types/array_of_functions.sol | 16 ++++++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 test/libsolidity/smtCheckerTests/types/array_of_contracts.sol create mode 100644 test/libsolidity/smtCheckerTests/types/array_of_functions.sol diff --git a/Changelog.md b/Changelog.md index 71cff3e1f..a3dfc541d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -28,6 +28,7 @@ Bugfixes: * SMTChecker: Fix error that reports invalid number of verified checks for BMC and CHC engines. * SMTChecker: Fix formatting of unary minus expressions in invariants. * SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine. + * SMTChecker: Fix SMT logic error when assigning to an array of contracts or functions. * TypeChecker: Fix segfault when assigning nested tuple to tuple. * Yul AST: Fix ``nativeSrc`` attributes in optimized IR AST referring to locations in unoptimized IR. * Yul IR Code Generation: Deterministic order of Yul subobjects. diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 350e18bdc..4a4ac8175 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -110,6 +110,14 @@ SortPointer smtSort(frontend::Type const& _type) // in the tuple's name. if (auto tupleSort = std::dynamic_pointer_cast(array->range)) tupleName = tupleSort->name; + else if (isContract(*baseType)) + // use a common sort for contracts so inheriting contracts do not cause conflicting SMT types + // solc handles types mismtach + tupleName = "contract"; + else if (isFunction(*baseType)) + // use a common sort for functions so pure and view modifier do not cause conflicting SMT types + // solc handles types mismtach + tupleName = "function"; else if ( baseType->category() == frontend::Type::Category::Integer || baseType->category() == frontend::Type::Category::FixedPoint diff --git a/test/libsolidity/smtCheckerTests/types/array_of_contracts.sol b/test/libsolidity/smtCheckerTests/types/array_of_contracts.sol new file mode 100644 index 000000000..89d242032 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/array_of_contracts.sol @@ -0,0 +1,17 @@ +contract A {} + +contract B is A {} + +contract C { + A[10] a; + B[10] b; + + function f() public returns(address) { + a = b; + return address(a[0]); + } +} +// ==== +// SMTEngine: all +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/array_of_functions.sol b/test/libsolidity/smtCheckerTests/types/array_of_functions.sol new file mode 100644 index 000000000..58a73d4ce --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/array_of_functions.sol @@ -0,0 +1,16 @@ +contract C { + function() external returns(uint)[1] a; + + function b() external pure returns(uint) { + return 1; + } + + function test() public returns(uint) { + a = [this.b]; + return a[0](); + } +} +// ==== +// SMTEngine: all +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From da68f49bc3a523f96c1e5aa525f80ee3e104bc4b Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 6 Aug 2024 14:47:28 -0300 Subject: [PATCH 0246/1340] Dont allow initialization of transient storage state variables --- libsolidity/analysis/DeclarationTypeChecker.cpp | 8 ++++++++ .../unsupported/transient_storage_state_variable.sol | 4 ++-- .../constants/constant_transient_state_variable.sol | 1 + ...ransient_value_type_state_variables_assignment.sol | 9 --------- ...ient_value_type_state_variables_initialization.sol | 11 +++++++++++ 5 files changed, 22 insertions(+), 11 deletions(-) delete mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_initialization.sol diff --git a/libsolidity/analysis/DeclarationTypeChecker.cpp b/libsolidity/analysis/DeclarationTypeChecker.cpp index 7e6ab98e1..bdf023c5c 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.cpp +++ b/libsolidity/analysis/DeclarationTypeChecker.cpp @@ -469,6 +469,14 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable) _variable.location(), "Transient cannot be used as data location for constant or immutable variables." ); + + if (_variable.value()) + m_errorReporter.declarationError( + 9825_error, + _variable.location(), + "Initialization of transient storage state variables is not supported." + ); + typeLoc = DataLocation::Transient; break; default: diff --git a/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol b/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol index b2dbc8efe..c74eb24c3 100644 --- a/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol +++ b/test/libsolidity/smtCheckerTests/unsupported/transient_storage_state_variable.sol @@ -1,6 +1,6 @@ contract C { - uint transient x = 42; - function test() public view { assert(x == 42); } + uint transient x; + function test() public view { assert(x == 0); } } // ==== // SMTEngine: all diff --git a/test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol b/test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol index f9a722a1b..15913360c 100644 --- a/test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol +++ b/test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol @@ -3,3 +3,4 @@ contract C { } // ---- // DeclarationError 2197: (17-52): Transient cannot be used as data location for constant or immutable variables. +// DeclarationError 9825: (17-52): Initialization of transient storage state variables is not supported. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol deleted file mode 100644 index 18e6a215d..000000000 --- a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_assignment.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract D { } - -contract C { - int transient x = -99; - address transient a = address(0xABC); - bool transient b = x > 0 ? false : true; -} -// ---- -// UnimplementedFeatureError 1834: Transient storage variables are not supported. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_initialization.sol b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_initialization.sol new file mode 100644 index 000000000..570642485 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_initialization.sol @@ -0,0 +1,11 @@ +contract D { } + +contract C { + int transient x = -99; + address transient a = address(0xABC); + bool transient b = x > 0 ? false : true; +} +// ---- +// DeclarationError 9825: (30-51): Initialization of transient storage state variables is not supported. +// DeclarationError 9825: (54-90): Initialization of transient storage state variables is not supported. +// DeclarationError 9825: (93-132): Initialization of transient storage state variables is not supported. From 44e008bb5dc1599f649121da9eb159cf7050d234 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 7 Aug 2024 11:15:34 +0200 Subject: [PATCH 0247/1340] Yul: remove deprecated dialect --- libyul/Dialect.cpp | 28 ------------------- libyul/Dialect.h | 3 -- libyul/YulStack.cpp | 4 +-- test/libyul/Common.cpp | 11 ++------ test/libyul/Parser.cpp | 4 +-- .../add_correct_type.yul | 2 +- .../disambiguator/for_statement.yul | 10 +++---- .../disambiguator/funtion_call.yul | 2 +- .../disambiguator/if_statement.yul | 2 +- .../disambiguator/long_names.yul | 2 +- .../{smoke_yul.yul => smoke_evmTyped.yul} | 2 +- .../disambiguator/switch_statement.yul | 2 +- .../disambiguator/variables.yul | 2 +- .../disambiguator/variables_clash.yul | 2 +- .../variables_inside_functions.yul | 2 +- .../expressionInliner/simple.yul | 2 +- .../expressionInliner/with_args.yul | 2 +- .../functionGrouper/empty_block.yul | 2 +- .../functionGrouper/multi_fun_mixed.yul | 2 +- .../functionGrouper/nested_fun.yul | 2 +- .../functionGrouper/single_fun.yul | 2 +- .../functionHoister/empty_block.yul | 2 +- .../functionHoister/multi_mixed.yul | 2 +- .../functionHoister/nested.yul | 2 +- .../functionHoister/single.yul | 2 +- test/libyul/yulSyntaxTests/builtin_types.yul | 13 ++------- .../yulSyntaxTests/for_visibility_9.yul | 2 +- .../yulSyntaxTests/for_visibility_A.yul | 2 +- .../yulSyntaxTests/if_statement_invalid_3.yul | 2 +- test/libyul/yulSyntaxTests/instructions.yul | 2 +- test/libyul/yulSyntaxTests/optional_types.yul | 2 +- .../yulSyntaxTests/token_as_identifier.yul | 5 +--- test/libyul/yulSyntaxTests/vardecl.yul | 2 +- .../variable_declaration_complex.yul | 6 ++-- 34 files changed, 43 insertions(+), 91 deletions(-) rename test/libyul/yulOptimizerTests/disambiguator/{smoke_yul.yul => smoke_evmTyped.yul} (71%) diff --git a/libyul/Dialect.cpp b/libyul/Dialect.cpp index f4f59ec26..8afd99a22 100644 --- a/libyul/Dialect.cpp +++ b/libyul/Dialect.cpp @@ -48,31 +48,3 @@ bool Dialect::validTypeForLiteral(LiteralKind _kind, LiteralValue const&, YulNam else return true; } - -Dialect const& Dialect::yulDeprecated() -{ - static std::unique_ptr dialect; - static YulStringRepository::ResetCallback callback{[&] { dialect.reset(); }}; - - if (!dialect) - { - // TODO will probably change, especially the list of types. - dialect = std::make_unique(); - dialect->defaultType = "u256"_yulname; - dialect->boolType = "bool"_yulname; - dialect->types = { - "bool"_yulname, - "u8"_yulname, - "s8"_yulname, - "u32"_yulname, - "s32"_yulname, - "u64"_yulname, - "s64"_yulname, - "u128"_yulname, - "s128"_yulname, - "u256"_yulname, - "s256"_yulname}; - }; - - return *dialect; -} diff --git a/libyul/Dialect.h b/libyul/Dialect.h index 3362246a0..fcec5fe3f 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -94,9 +94,6 @@ struct Dialect Dialect() = default; virtual ~Dialect() = default; - - /// Old "yul" dialect. This is only used for testing. - static Dialect const& yulDeprecated(); }; } diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index dbe30bb13..385c527d2 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -54,8 +54,8 @@ Dialect const& languageToDialect(YulStack::Language _language, EVMVersion _versi case YulStack::Language::Yul: return EVMDialectTyped::instance(_version); } - yulAssert(false, ""); - return Dialect::yulDeprecated(); + yulAssert(false); + util::unreachable(); } } diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index d147e03d0..01956e7f5 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -44,9 +44,9 @@ using namespace solidity::langutil; namespace { -Dialect const& defaultDialect(bool _yul) +Dialect const& defaultDialect() { - return _yul ? yul::Dialect::yulDeprecated() : yul::EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion()); + return yul::EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion()); } } @@ -91,7 +91,7 @@ std::pair, std::shared_ptr> yul::t yul::Block yul::test::disambiguate(std::string const& _source, bool _yul) { auto result = parse(_source, _yul); - return std::get(Disambiguator(defaultDialect(_yul), *result.second, {})(result.first->root())); + return std::get(Disambiguator(defaultDialect(), *result.second, {})(result.first->root())); } std::string yul::test::format(std::string const& _source, bool _yul) @@ -113,11 +113,6 @@ std::map const "evmTyped", [](langutil::EVMVersion _evmVersion) -> yul::Dialect const& { return yul::EVMDialectTyped::instance(_evmVersion); } - }, - { - "yul", - [](langutil::EVMVersion) -> yul::Dialect const& - { return yul::Dialect::yulDeprecated(); } } }; diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 0ed09f6a9..5ce8b449b 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -104,12 +104,12 @@ std::optional parseAndReturnFirstError(std::string const& _source, Dialec return {}; } -bool successParse(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarningsAndInfos = true) +bool successParse(std::string const& _source, Dialect const& _dialect, bool _allowWarningsAndInfos = true) { return !parseAndReturnFirstError(_source, _dialect, _allowWarningsAndInfos); } -Error expectError(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarningsAndInfos = false) +Error expectError(std::string const& _source, Dialect const& _dialect, bool _allowWarningsAndInfos = false) { auto error = parseAndReturnFirstError(_source, _dialect, _allowWarningsAndInfos); diff --git a/test/libyul/yulOptimizerTests/conditionalSimplifier/add_correct_type.yul b/test/libyul/yulOptimizerTests/conditionalSimplifier/add_correct_type.yul index c7cc17fc8..57785f0b3 100644 --- a/test/libyul/yulOptimizerTests/conditionalSimplifier/add_correct_type.yul +++ b/test/libyul/yulOptimizerTests/conditionalSimplifier/add_correct_type.yul @@ -5,7 +5,7 @@ } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: conditionalSimplifier // diff --git a/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul index 30f2e5479..fcfbe3242 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul @@ -1,23 +1,23 @@ { { let a:u256, b:u256 } { - function eq(x: u256, y: u256) -> z: bool {} - for { let a:u256 } eq(a, a) { a := a } { + function eq_function(x: u256, y: u256) -> z: bool {} + for { let a:u256 } eq_function(a, a) { a := a } { let b:u256 := a } } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: disambiguator // // { // { let a, b } // { -// function eq(x, y) -> z:bool +// function eq_function(x, y) -> z:bool // { } -// for { let a_1 } eq(a_1, a_1) { a_1 := a_1 } +// for { let a_1 } eq_function(a_1, a_1) { a_1 := a_1 } // { let b_2 := a_1 } // } // } diff --git a/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul b/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul index f99c4e447..7fc51a5fa 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul @@ -7,7 +7,7 @@ } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul index 6b6da1f18..512d7fc12 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul @@ -6,7 +6,7 @@ } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/long_names.yul b/test/libyul/yulOptimizerTests/disambiguator/long_names.yul index d55afc482..fbd95ef3a 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/long_names.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/long_names.yul @@ -1,6 +1,6 @@ { { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/smoke_yul.yul b/test/libyul/yulOptimizerTests/disambiguator/smoke_evmTyped.yul similarity index 71% rename from test/libyul/yulOptimizerTests/disambiguator/smoke_yul.yul rename to test/libyul/yulOptimizerTests/disambiguator/smoke_evmTyped.yul index 676416437..481cbb588 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/smoke_yul.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/smoke_evmTyped.yul @@ -1,6 +1,6 @@ { } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul index 16ee5353f..86ea9cba2 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul @@ -8,7 +8,7 @@ } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables.yul b/test/libyul/yulOptimizerTests/disambiguator/variables.yul index 65c93bbb9..743eaf0de 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/variables.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/variables.yul @@ -1,6 +1,6 @@ { { let a:u256 } { let a:u256 } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul b/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul index e2cf23756..2a94e4769 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul @@ -1,6 +1,6 @@ { { let a:u256 let a_1:u256 } { let a:u256 } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul b/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul index a78af7dab..f9e134aff 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul @@ -6,7 +6,7 @@ } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/expressionInliner/simple.yul b/test/libyul/yulOptimizerTests/expressionInliner/simple.yul index 2b6dba240..dbc80a859 100644 --- a/test/libyul/yulOptimizerTests/expressionInliner/simple.yul +++ b/test/libyul/yulOptimizerTests/expressionInliner/simple.yul @@ -3,7 +3,7 @@ let y:u256 := f() } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: expressionInliner // diff --git a/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul b/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul index 0456654e3..e142f5978 100644 --- a/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul +++ b/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul @@ -3,7 +3,7 @@ let y:u256 := f(7:u256) } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: expressionInliner // diff --git a/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul b/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul index 7bfbb3401..05fa8d249 100644 --- a/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul +++ b/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul @@ -1,6 +1,6 @@ { let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: functionGrouper // diff --git a/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul b/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul index 1aedecf6a..5d4eaea5e 100644 --- a/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul +++ b/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul @@ -5,7 +5,7 @@ let e:u256 } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: functionGrouper // diff --git a/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul b/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul index 9193da739..5b8436540 100644 --- a/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul +++ b/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul @@ -9,7 +9,7 @@ } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: functionGrouper // diff --git a/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul b/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul index b007f1855..a62b0ddeb 100644 --- a/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul +++ b/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul @@ -2,7 +2,7 @@ let a:u256 function f() {} } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: functionGrouper // diff --git a/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul b/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul index bd66b3a2b..5eed2d2bb 100644 --- a/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul +++ b/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul @@ -8,7 +8,7 @@ } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: functionHoister // diff --git a/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul b/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul index 060fab314..fc6168ce9 100644 --- a/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul +++ b/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul @@ -6,7 +6,7 @@ let e:u256 } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: functionHoister // diff --git a/test/libyul/yulOptimizerTests/functionHoister/nested.yul b/test/libyul/yulOptimizerTests/functionHoister/nested.yul index 05eb4803b..65486dc6c 100644 --- a/test/libyul/yulOptimizerTests/functionHoister/nested.yul +++ b/test/libyul/yulOptimizerTests/functionHoister/nested.yul @@ -7,7 +7,7 @@ } } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: functionHoister // diff --git a/test/libyul/yulOptimizerTests/functionHoister/single.yul b/test/libyul/yulOptimizerTests/functionHoister/single.yul index 205626b57..e939ecb85 100644 --- a/test/libyul/yulOptimizerTests/functionHoister/single.yul +++ b/test/libyul/yulOptimizerTests/functionHoister/single.yul @@ -3,7 +3,7 @@ function f() {} } // ==== -// dialect: yul +// dialect: evmTyped // ---- // step: functionHoister // diff --git a/test/libyul/yulSyntaxTests/builtin_types.yul b/test/libyul/yulSyntaxTests/builtin_types.yul index becf342b8..e4d961c30 100644 --- a/test/libyul/yulSyntaxTests/builtin_types.yul +++ b/test/libyul/yulSyntaxTests/builtin_types.yul @@ -1,16 +1,7 @@ { let x1:bool := true:bool - let x2:u8 := 1:u8 - let x3:s8 := 1:s8 - let x4:u32 := 1:u32 - let x5:s32 := 1:s32 - let x6:u64 := 1:u64 - let x7:s64 := 1:s64 - let x8:u128 := 1:u128 - let x9:s128 := 1:s128 - let x10:u256 := 1:u256 - let x11:s256 := 1:s256 + let x2:u256 := 1:u256 } // ==== -// dialect: yul +// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/for_visibility_9.yul b/test/libyul/yulSyntaxTests/for_visibility_9.yul index 4cda1b165..6922dc961 100644 --- a/test/libyul/yulSyntaxTests/for_visibility_9.yul +++ b/test/libyul/yulSyntaxTests/for_visibility_9.yul @@ -2,6 +2,6 @@ for { let x := 1 } 1 { let x := 1 } {} } // ==== -// dialect: yul +// dialect: evmTyped // ---- // DeclarationError 1395: (26-36): Variable name x already taken in this scope. diff --git a/test/libyul/yulSyntaxTests/for_visibility_A.yul b/test/libyul/yulSyntaxTests/for_visibility_A.yul index a5761f52a..07766159d 100644 --- a/test/libyul/yulSyntaxTests/for_visibility_A.yul +++ b/test/libyul/yulSyntaxTests/for_visibility_A.yul @@ -2,6 +2,6 @@ for { let x := 1 } 1 {} { let x := 1 } } // ==== -// dialect: yul +// dialect: evm // ---- // DeclarationError 1395: (29-39): Variable name x already taken in this scope. diff --git a/test/libyul/yulSyntaxTests/if_statement_invalid_3.yul b/test/libyul/yulSyntaxTests/if_statement_invalid_3.yul index fa396456f..c99bcac14 100644 --- a/test/libyul/yulSyntaxTests/if_statement_invalid_3.yul +++ b/test/libyul/yulSyntaxTests/if_statement_invalid_3.yul @@ -2,6 +2,6 @@ if 32 let x := 3 } // ==== -// dialect: yul +// dialect: evm // ---- // ParserError 2314: (12-15): Expected '{' but got reserved keyword 'let' diff --git a/test/libyul/yulSyntaxTests/instructions.yul b/test/libyul/yulSyntaxTests/instructions.yul index 3d600812f..64268bbb4 100644 --- a/test/libyul/yulSyntaxTests/instructions.yul +++ b/test/libyul/yulSyntaxTests/instructions.yul @@ -1,5 +1,5 @@ { pop } // ==== -// dialect: yul +// dialect: evm // ---- // ParserError 6913: (6-7): Call or assignment expected. diff --git a/test/libyul/yulSyntaxTests/optional_types.yul b/test/libyul/yulSyntaxTests/optional_types.yul index aa77ffca7..151edbf46 100644 --- a/test/libyul/yulSyntaxTests/optional_types.yul +++ b/test/libyul/yulSyntaxTests/optional_types.yul @@ -5,5 +5,5 @@ function g(a:u256) -> b {} } // ==== -// dialect: yul +// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/token_as_identifier.yul b/test/libyul/yulSyntaxTests/token_as_identifier.yul index eaeceb7c4..204b76e55 100644 --- a/test/libyul/yulSyntaxTests/token_as_identifier.yul +++ b/test/libyul/yulSyntaxTests/token_as_identifier.yul @@ -1,9 +1,6 @@ { - let return:u256 := 1:u256 - let byte:u256 := 1:u256 - let address:u256 := 1:u256 let bool:u256 := 1:u256 } // ==== -// dialect: yul +// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/vardecl.yul b/test/libyul/yulSyntaxTests/vardecl.yul index fd7d06bfb..41b58cc2f 100644 --- a/test/libyul/yulSyntaxTests/vardecl.yul +++ b/test/libyul/yulSyntaxTests/vardecl.yul @@ -2,5 +2,5 @@ let x := 7 } // ==== -// dialect: yul +// dialect: evm // ---- diff --git a/test/libyul/yulSyntaxTests/variable_declaration_complex.yul b/test/libyul/yulSyntaxTests/variable_declaration_complex.yul index 4b93cdb04..e7a428fc2 100644 --- a/test/libyul/yulSyntaxTests/variable_declaration_complex.yul +++ b/test/libyul/yulSyntaxTests/variable_declaration_complex.yul @@ -1,8 +1,8 @@ { - function add(a:u256, b:u256) -> c:u256 {} + function add_fn(a:u256, b:u256) -> c:u256 {} let y:u256 := 2:u256 - let x:u256 := add(7:u256, add(6:u256, y)) + let x:u256 := add_fn(7:u256, add_fn(6:u256, y)) } // ==== -// dialect: yul +// dialect: evmTyped // ---- From 61d1d9ddbdda0532068299c651c4e6c102b6c287 Mon Sep 17 00:00:00 2001 From: Alireza Arjmand Date: Mon, 12 Aug 2024 11:28:02 -0400 Subject: [PATCH 0248/1340] fix typo in micropayment.rst --- docs/examples/micropayment.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/micropayment.rst b/docs/examples/micropayment.rst index c3aef0d65..9a3ad845c 100644 --- a/docs/examples/micropayment.rst +++ b/docs/examples/micropayment.rst @@ -482,7 +482,7 @@ The full contract .. note:: The function ``splitSignature`` does not use all security checks. A real implementation should use a more rigorously tested library, - such as openzepplin's `version `_ of this code. + such as openzeppelin's `version `_ of this code. Verifying Payments ------------------ From 1c0b2f5bb760f442c0d71ae37a41ea02f27464f4 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 13 Aug 2024 08:51:05 +0200 Subject: [PATCH 0249/1340] Yul: Remove EVMDialectTyped --- libyul/YulStack.cpp | 5 -- libyul/YulStack.h | 2 +- libyul/backends/evm/EVMDialect.cpp | 108 ----------------------------- libyul/backends/evm/EVMDialect.h | 22 ------ 4 files changed, 1 insertion(+), 136 deletions(-) diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 933c3f75e..8166ed3cf 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -52,8 +52,6 @@ Dialect const& languageToDialect(YulStack::Language _language, EVMVersion _versi case YulStack::Language::Assembly: case YulStack::Language::StrictAssembly: return EVMDialect::strictAssemblyForEVMObjects(_version); - case YulStack::Language::Yul: - return EVMDialectTyped::instance(_version); } yulAssert(false); util::unreachable(); @@ -180,9 +178,6 @@ void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) const case Language::StrictAssembly: dialect = &EVMDialect::strictAssemblyForEVMObjects(m_evmVersion); break; - case Language::Yul: - dialect = &EVMDialectTyped::instance(m_evmVersion); - break; default: yulAssert(false, "Invalid language."); break; diff --git a/libyul/YulStack.h b/libyul/YulStack.h index 4dc262a25..b09fa7975 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -65,7 +65,7 @@ struct MachineAssemblyObject class YulStack: public langutil::CharStreamProvider { public: - enum class Language { Yul, Assembly, StrictAssembly }; + enum class Language { Assembly, StrictAssembly }; enum class Machine { EVM }; enum State { Empty, diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 50ede8c76..aeb825304 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -23,19 +23,14 @@ #include #include -#include #include #include #include -#include #include #include #include #include -#include -#include - #include using namespace std::string_literals; @@ -461,106 +456,3 @@ BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, siz } return function.get(); } - -EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess): - EVMDialect(_evmVersion, _objectAccess) -{ - defaultType = "u256"_yulname; - boolType = "bool"_yulname; - types = {defaultType, boolType}; - - // Set all types to ``defaultType`` - for (auto& fun: m_functions) - { - for (auto& p: fun.second.parameters) - p = defaultType; - for (auto& r: fun.second.returns) - r = defaultType; - } - - m_functions["lt"_yulname].returns = {"bool"_yulname}; - m_functions["gt"_yulname].returns = {"bool"_yulname}; - m_functions["slt"_yulname].returns = {"bool"_yulname}; - m_functions["sgt"_yulname].returns = {"bool"_yulname}; - m_functions["eq"_yulname].returns = {"bool"_yulname}; - - // "not" and "bitnot" replace "iszero" and "not" - m_functions["bitnot"_yulname] = m_functions["not"_yulname]; - m_functions["bitnot"_yulname].name = "bitnot"_yulname; - m_functions["not"_yulname] = m_functions["iszero"_yulname]; - m_functions["not"_yulname].name = "not"_yulname; - m_functions["not"_yulname].returns = {"bool"_yulname}; - m_functions["not"_yulname].parameters = {"bool"_yulname}; - m_functions.erase("iszero"_yulname); - - m_functions["bitand"_yulname] = m_functions["and"_yulname]; - m_functions["bitand"_yulname].name = "bitand"_yulname; - m_functions["bitor"_yulname] = m_functions["or"_yulname]; - m_functions["bitor"_yulname].name = "bitor"_yulname; - m_functions["bitxor"_yulname] = m_functions["xor"_yulname]; - m_functions["bitxor"_yulname].name = "bitxor"_yulname; - m_functions["and"_yulname].parameters = {"bool"_yulname, "bool"_yulname}; - m_functions["and"_yulname].returns = {"bool"_yulname}; - m_functions["or"_yulname].parameters = {"bool"_yulname, "bool"_yulname}; - m_functions["or"_yulname].returns = {"bool"_yulname}; - m_functions["xor"_yulname].parameters = {"bool"_yulname, "bool"_yulname}; - m_functions["xor"_yulname].returns = {"bool"_yulname}; - m_functions["popbool"_yulname] = m_functions["pop"_yulname]; - m_functions["popbool"_yulname].name = "popbool"_yulname; - m_functions["popbool"_yulname].parameters = {"bool"_yulname}; - m_functions.insert(createFunction("bool_to_u256", 1, 1, {}, {}, []( - FunctionCall const&, - AbstractAssembly&, - BuiltinContext& - ) {})); - m_functions["bool_to_u256"_yulname].parameters = {"bool"_yulname}; - m_functions["bool_to_u256"_yulname].returns = {"u256"_yulname}; - m_functions.insert(createFunction("u256_to_bool", 1, 1, {}, {}, []( - FunctionCall const&, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - // TODO this should use a Panic. - // A value larger than 1 causes an invalid instruction. - _assembly.appendConstant(2); - _assembly.appendInstruction(evmasm::Instruction::DUP2); - _assembly.appendInstruction(evmasm::Instruction::LT); - AbstractAssembly::LabelID inRange = _assembly.newLabelId(); - _assembly.appendJumpToIf(inRange); - _assembly.appendInstruction(evmasm::Instruction::INVALID); - _assembly.appendLabel(inRange); - })); - m_functions["u256_to_bool"_yulname].parameters = {"u256"_yulname}; - m_functions["u256_to_bool"_yulname].returns = {"bool"_yulname}; -} - -BuiltinFunctionForEVM const* EVMDialectTyped::discardFunction(YulName _type) const -{ - if (_type == "bool"_yulname) - return builtin("popbool"_yulname); - else - { - yulAssert(_type == defaultType, ""); - return builtin("pop"_yulname); - } -} - -BuiltinFunctionForEVM const* EVMDialectTyped::equalityFunction(YulName _type) const -{ - if (_type == "bool"_yulname) - return nullptr; - else - { - yulAssert(_type == defaultType, ""); - return builtin("eq"_yulname); - } -} - -EVMDialectTyped const& EVMDialectTyped::instance(langutil::EVMVersion _version) -{ - static std::map> dialects; - static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }}; - if (!dialects[_version]) - dialects[_version] = std::make_unique(_version, true); - return *dialects[_version]; -} diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 7db1ec09d..89df94496 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -102,26 +102,4 @@ struct EVMDialect: public Dialect std::set m_reserved; }; -/** - * EVM dialect with types u256 (default) and bool. - * Difference to EVMDialect: - * - All comparison functions return type bool - * - bitwise operations are called bitor, bitand, bitxor and bitnot - * - and, or, xor take bool and return bool - * - iszero is replaced by not, which takes bool and returns bool - * - there are conversion functions bool_to_u256 and u256_to_bool. - * - there is popbool - */ -struct EVMDialectTyped: public EVMDialect -{ - /// Constructor, should only be used internally. Use the factory function below. - EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess); - - BuiltinFunctionForEVM const* discardFunction(YulName _type) const override; - BuiltinFunctionForEVM const* equalityFunction(YulName _type) const override; - BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("not"_yulname); } - - static EVMDialectTyped const& instance(langutil::EVMVersion _version); -}; - } From 65127220bfab7a6b1b185fa07abbc2f912ad8793 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 13 Aug 2024 08:51:59 +0200 Subject: [PATCH 0250/1340] Yul tests: Adapt or remove EVMDialectTyped tests --- test/libyul/Common.cpp | 19 +-- test/libyul/Common.h | 6 +- test/libyul/CompilabilityChecker.cpp | 2 +- test/libyul/ControlFlowSideEffectsTest.cpp | 2 +- test/libyul/FunctionSideEffects.cpp | 2 +- test/libyul/Inliner.cpp | 36 +++-- test/libyul/Metrics.cpp | 2 +- test/libyul/Parser.cpp | 157 ++++++++------------- 8 files changed, 89 insertions(+), 137 deletions(-) diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 01956e7f5..a0c00c90d 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -50,12 +50,12 @@ Dialect const& defaultDialect() } } -std::pair, std::shared_ptr> yul::test::parse(std::string const& _source, bool _yul) +std::pair, std::shared_ptr> yul::test::parse(std::string const& _source) { YulStack stack( solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().eofVersion(), - _yul ? YulStack::Language::Yul : YulStack::Language::StrictAssembly, + YulStack::Language::StrictAssembly, solidity::test::CommonOptions::get().optimize ? solidity::frontend::OptimiserSettings::standard() : solidity::frontend::OptimiserSettings::minimal(), @@ -88,17 +88,17 @@ std::pair, std::shared_ptr> yul::t return {std::move(parserResult), std::move(analysisInfo)}; } -yul::Block yul::test::disambiguate(std::string const& _source, bool _yul) +yul::Block yul::test::disambiguate(std::string const& _source) { - auto result = parse(_source, _yul); + auto result = parse(_source); return std::get(Disambiguator(defaultDialect(), *result.second, {})(result.first->root())); } -std::string yul::test::format(std::string const& _source, bool _yul) +std::string yul::test::format(std::string const& _source) { auto const version = solidity::test::CommonOptions::get().evmVersion(); - Dialect const& dialect = _yul ? EVMDialectTyped::instance(version) : EVMDialect::strictAssemblyForEVMObjects(version); - return yul::AsmPrinter(yul::AsmPrinter::TypePrinting::Full, dialect)(parse(_source, _yul).first->root()); + Dialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(version); + return yul::AsmPrinter(yul::AsmPrinter::TypePrinting::Full, dialect)(parse(_source).first->root()); } namespace @@ -108,11 +108,6 @@ std::map const "evm", [](langutil::EVMVersion _evmVersion) -> yul::Dialect const& { return yul::EVMDialect::strictAssemblyForEVMObjects(_evmVersion); } - }, - { - "evmTyped", - [](langutil::EVMVersion _evmVersion) -> yul::Dialect const& - { return yul::EVMDialectTyped::instance(_evmVersion); } } }; diff --git a/test/libyul/Common.h b/test/libyul/Common.h index 14d73d77e..c87f1c68b 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -46,13 +46,13 @@ namespace solidity::yul::test { std::pair, std::shared_ptr> -parse(std::string const& _source, bool _yul = true); +parse(std::string const& _source); std::pair, std::shared_ptr> parse(std::string const& _source, Dialect const& _dialect, langutil::ErrorList& _errors); -Block disambiguate(std::string const& _source, bool _yul = true); -std::string format(std::string const& _source, bool _yul = true); +Block disambiguate(std::string const& _source); +std::string format(std::string const& _source); solidity::yul::Dialect const& dialect(std::string const& _name, langutil::EVMVersion _evmVersion); diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index 5b64b5e5d..13788b75f 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -35,7 +35,7 @@ namespace std::string check(std::string const& _input) { Object obj; - auto parsingResult = yul::test::parse(_input, false); + auto parsingResult = yul::test::parse(_input); obj.setCode(parsingResult.first, parsingResult.second); BOOST_REQUIRE(obj.hasCode()); auto functions = CompilabilityChecker(EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion()), obj, true).stackDeficit; diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index 20df176a3..3ad70f5a0 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -57,7 +57,7 @@ ControlFlowSideEffectsTest::ControlFlowSideEffectsTest(std::string const& _filen TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { Object obj; - auto parsingResult = yul::test::parse(m_source, false); + auto parsingResult = yul::test::parse(m_source); obj.setCode(parsingResult.first, parsingResult.second); if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index a39024d27..9d6599f42 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -83,7 +83,7 @@ FunctionSideEffects::FunctionSideEffects(std::string const& _filename): TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { Object obj; - auto parsingResult = yul::test::parse(m_source, false); + auto parsingResult = yul::test::parse(m_source); obj.setCode(parsingResult.first, parsingResult.second); if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); diff --git a/test/libyul/Inliner.cpp b/test/libyul/Inliner.cpp index 6f622b41a..f6da0c95c 100644 --- a/test/libyul/Inliner.cpp +++ b/test/libyul/Inliner.cpp @@ -24,8 +24,6 @@ #include #include -#include -#include #include #include @@ -65,44 +63,44 @@ BOOST_AUTO_TEST_CASE(smoke_test) BOOST_AUTO_TEST_CASE(simple) { - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := 2:u256 } }"), "f"); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x { x := 2 } }"), "f"); BOOST_CHECK_EQUAL(inlinableFunctions("{" - "function g(a:u256) -> b:u256 { b := a }" - "function f() -> x:u256 { x := g(2:u256) }" + "function g(a) -> b { b := a }" + "function f() -> x { x := g(2) }" "}"), "g,f"); } BOOST_AUTO_TEST_CASE(simple_inside_structures) { BOOST_CHECK_EQUAL(inlinableFunctions("{" - "switch 2:u256 " - "case 2:u256 {" - "function g(a:u256) -> b:u256 { b := a }" - "function f() -> x:u256 { x := g(2:u256) }" + "switch 2 " + "case 2 {" + "function g(a) -> b { b := a }" + "function f() -> x { x := g(2) }" "}" "}"), "g,f"); BOOST_CHECK_EQUAL(inlinableFunctions("{" - "function g(a:u256) -> b:u256 { b := a }" + "function g(a) -> b { b := a }" "for {" "} true {" - "function f() -> x:u256 { x := g(2:u256) }" + "function f() -> x { x := g(2) }" "}" "{" - "function h() -> y:u256 { y := 2:u256 }" + "function h() -> y { y := 2 }" "}" "}"), "h,g,f"); } BOOST_AUTO_TEST_CASE(negative) { - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { } }"), ""); - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := 2:u256 {} } }"), ""); - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := f() } }"), ""); - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := x } }"), ""); - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256, y:u256 { x := 2:u256 } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x { } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x { x := 2 {} } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x { x := f() } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x { x := x } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x, y { x := 2 } }"), ""); BOOST_CHECK_EQUAL(inlinableFunctions( - "{ function g() -> x:u256, y:u256 {} function f(y:u256) -> x:u256 { x,y := g() } }"), ""); - BOOST_CHECK_EQUAL(inlinableFunctions("{ function f(y:u256) -> x:u256 { y := 2:u256 } }"), ""); + "{ function g() -> x, y {} function f(y) -> x { x,y := g() } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f(y) -> x { y := 2 } }"), ""); } diff --git a/test/libyul/Metrics.cpp b/test/libyul/Metrics.cpp index bf09a1c2b..5c7b5fc34 100644 --- a/test/libyul/Metrics.cpp +++ b/test/libyul/Metrics.cpp @@ -38,7 +38,7 @@ namespace size_t codeSize(std::string const& _source, CodeWeights const _weights = {}) { - std::shared_ptr ast = parse(_source, false).first; + std::shared_ptr ast = parse(_source).first; BOOST_REQUIRE(ast); return CodeSize::codeSize(ast->root(), _weights); } diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 5ce8b449b..2a2f28092 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -148,47 +148,6 @@ BOOST_AUTO_TEST_CASE(builtins_analysis) CHECK_ERROR_DIALECT("{ let a, b := builtin(1, 2) }", DeclarationError, "Variable count mismatch for declaration of \"a, b\": 2 variables and 3 values.", dialect); } -BOOST_AUTO_TEST_CASE(default_types_set) -{ - ErrorList errorList; - ErrorReporter reporter(errorList); - std::shared_ptr result = parse( - "{" - "let x:bool := true:bool " - "let z:bool := true " - "let y := add(1, 2) " - "switch y case 0 {} default {} " - "}", - EVMDialectTyped::instance(EVMVersion{}), - reporter - ); - BOOST_REQUIRE(!!result && errorList.size() == 0); - - // All types are printed. - BOOST_CHECK_EQUAL(AsmPrinter(AsmPrinter::TypePrinting::Full, EVMDialectTyped::instance(EVMVersion()))(result->root()), - "{\n" - " let x:bool := true:bool\n" - " let z:bool := true:bool\n" - " let y:u256 := add(1:u256, 2:u256)\n" - " switch y\n" - " case 0:u256 { }\n" - " default { }\n" - "}" - ); - - // Now the default types should be omitted. - BOOST_CHECK_EQUAL(AsmPrinter(AsmPrinter::TypePrinting::OmitDefault, EVMDialectTyped::instance(EVMVersion()))(result->root()), - "{\n" - " let x:bool := true\n" - " let z:bool := true\n" - " let y := add(1, 2)\n" - " switch y\n" - " case 0 { }\n" - " default { }\n" - "}" - ); -} - #define CHECK_LOCATION(_actual, _sourceName, _start, _end) \ do { \ BOOST_CHECK_EQUAL((_sourceName), ((_actual).sourceName ? *(_actual).sourceName : "")); \ @@ -203,7 +162,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_empty_block) auto const sourceText = "/// @src 0:234:543\n" "{}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -216,12 +175,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_with_children) auto const sourceText = "/// @src 0:234:543\n" "{\n" - "let x:bool := true:bool\n" + "let x := true\n" "/// @src 0:123:432\n" - "let z:bool := true\n" + "let z := true\n" "let y := add(1, 2)\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -239,12 +198,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_different_sources) auto const sourceText = "/// @src 0:234:543\n" "{\n" - "let x:bool := true:bool\n" + "let x := true\n" "/// @src 1:123:432\n" - "let z:bool := true\n" + "let z := true\n" "let y := add(1, 2)\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -266,7 +225,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_nested) "/// @src 0:343:434\n" "switch y case 0 {} default {}\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -290,7 +249,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_switch_case) " let z := add(3, 4)\n" "}\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -317,12 +276,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_inherit_into_outer_scope) "{\n" "{\n" "/// @src 0:123:432\n" - "let x:bool := true:bool\n" + "let x := true\n" "}\n" - "let z:bool := true\n" + "let z := true\n" "let y := add(1, 2)\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); @@ -349,11 +308,11 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_assign_empty) auto const sourceText = "{\n" "/// @src 0:123:432\n" - "let a:bool\n" + "let a\n" "/// @src 1:1:10\n" - "a := true:bool\n" + "a := true\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // should still parse BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); @@ -369,12 +328,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_source_index) auto const sourceText = "{\n" "/// @src 1:123:432\n" - "let a:bool := true:bool\n" + "let a := true\n" "/// @src 2345:0:8\n" - "let b:bool := true:bool\n" + "let b := true\n" "\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); // should still parse BOOST_REQUIRE(errorList.size() == 1); @@ -390,11 +349,11 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_1) auto const sourceText = "{\n" "/// @src 0:123:432\n" - "let x:bool \n" + "let x \n" "/// @src 0:234:2026\n" - ":= true:bool\n" + ":= true\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); @@ -417,7 +376,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_2) 2) } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(1, result->root().statements.size()); @@ -451,7 +410,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_3) mstore(1, 2) // FunctionCall } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); @@ -484,10 +443,10 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_comments_after_valid) { /// @src 0:420:680 /// @invalid - let a:bool := true + let a := true } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(1, result->root().statements.size()); @@ -506,7 +465,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_suffix) /// @src 0:420:680foo {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -523,7 +482,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_prefix) /// abc@src 0:111:222 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); @@ -537,7 +496,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_unspecified) /// @src -1:-1:-1 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); @@ -551,7 +510,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_non_integer) /// @src a:b:c {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -568,7 +527,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_bad_integer) /// @src 111111111111111111111:222222222222222222222:333333333333333333333 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -586,10 +545,10 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_ensure_last_match) { /// @src 1:10:20 /// @src 0:30:40 - let x:bool := true + let x := true } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); @@ -607,7 +566,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_no_whitespace) /// @src 0:111:222@src 1:333:444 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -624,7 +583,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_separated_with_single_s /// @src 0:111:222 @src 1:333:444 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 333, 444); @@ -635,7 +594,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_leading_trailing_whitespace) ErrorList errorList; ErrorReporter reporter(errorList); auto const sourceText = "/// @src 0:111:222 \n{}"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -649,10 +608,10 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_reference_original_sloc) /// @src 1:2:3 { /// @src -1:10:20 - let x:bool := true + let x := true } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); @@ -674,7 +633,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets) let y := /** @src 1:96:165 "contract D {..." */ 128 } )~~~"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 2); @@ -699,7 +658,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_empty_snippet) /// @src 0:111:222 "" {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -713,7 +672,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_befo /// @src 0:111:222"abc" def {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -730,7 +689,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_afte /// @src 0:111:222 "abc"def {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -744,7 +703,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_no_whites /// @src 0:111:222 "abc"@src 1:333:444 "abc" {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 333, 444); @@ -758,7 +717,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_untermina /// @src 0:111:222 " abc @src 1:333:444 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -776,7 +735,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote) /// {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -793,7 +752,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_snippets_with_hex_comment) /// @src 0:111:222 hex"abc"@src 1:333:444 "abc" {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // the second source location is not parsed as such, as the hex string isn't interpreted as snippet but @@ -809,7 +768,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_escapes) /// @src 0:111:222 "\n\\x\x\w\uö\xy\z\y\fq" {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -824,7 +783,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote_snippet_with_whitespaces /// @src 1 : 222 : 333 '\x33\u1234\t\n' {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 222, 333); @@ -839,7 +798,7 @@ BOOST_DATA_TEST_CASE(customSourceLocations_scanner_errors_outside_string_lits_ar /// @src 1:222:333 {{}} )", invalid); - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.empty()); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 222, 333); @@ -857,7 +816,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multi_line_source_loc) /// " @src 0:333:444 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.empty()); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 333, 444); @@ -875,7 +834,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locati let y := /** @src 1:96:165 "function f() internal { \"\/** @src 0:6:7 *\/\"; }" */ 128 } )~~~"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 2); @@ -904,7 +863,7 @@ BOOST_AUTO_TEST_CASE(astid) mstore(1, 2) } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(7)); @@ -926,7 +885,7 @@ BOOST_AUTO_TEST_CASE(astid_reset) mstore(1, 2) } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(7)); @@ -944,7 +903,7 @@ BOOST_AUTO_TEST_CASE(astid_multi) /// @src -1:-1:-1 @ast-id 7 @src 1:1:1 @ast-id 8 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(8)); @@ -958,7 +917,7 @@ BOOST_AUTO_TEST_CASE(astid_invalid) /// @src -1:-1:-1 @ast-id abc @src 1:1:1 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -975,7 +934,7 @@ BOOST_AUTO_TEST_CASE(astid_too_large) /// @ast-id 9223372036854775808 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -991,7 +950,7 @@ BOOST_AUTO_TEST_CASE(astid_way_too_large) /// @ast-id 999999999999999999999999999999999999999 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -1007,7 +966,7 @@ BOOST_AUTO_TEST_CASE(astid_not_fully_numeric) /// @ast-id 9x {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -1029,7 +988,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multiple_src_tags_on_one_line) "\n" " let x := 123\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 1); From 40e05d6e209a6d03afe2085d26a322f6ac8fc56c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 13 Aug 2024 08:54:30 +0200 Subject: [PATCH 0251/1340] Yul optimizer tests: Update test expectations to use evm instead of evmTyped --- .../add_correct_type.yul | 19 -------------- .../disambiguator/for_statement.yul | 12 ++++----- .../disambiguator/funtion_call.yul | 8 +++--- .../disambiguator/if_statement.yul | 12 ++++----- .../disambiguator/long_names.yul | 4 +-- .../disambiguator/smoke_evmTyped.yul | 7 ----- .../disambiguator/switch_statement.yul | 10 +++---- .../disambiguator/variables.yul | 4 +-- .../disambiguator/variables_clash.yul | 4 +-- .../variables_inside_functions.yul | 8 +++--- .../expressionInliner/simple.yul | 6 ++--- .../expressionInliner/with_args.yul | 6 ++--- .../fullInliner/multi_return_typed.yul | 23 ---------------- .../functionGrouper/empty_block.yul | 6 ++--- .../functionGrouper/multi_fun_mixed.yul | 10 +++---- .../functionGrouper/nested_fun.yul | 10 +++---- .../functionGrouper/single_fun.yul | 4 +-- .../functionHoister/empty_block.yul | 10 +++---- .../functionHoister/multi_mixed.yul | 12 ++++----- .../functionHoister/nested.yul | 10 +++---- .../functionHoister/single.yul | 4 +-- .../ssaTransform/for_simpler.yul | 24 +++++++++++++++++ .../ssaTransform/switch_no_default_case.yul | 24 +++++++++++++++++ .../yulOptimizerTests/ssaTransform/typed.yul | 20 +++++++------- .../ssaTransform/typed_for.yul | 26 ------------------- .../ssaTransform/typed_switch.yul | 26 ------------------- .../varDeclInitializer/typed.yul | 24 ----------------- 27 files changed, 109 insertions(+), 224 deletions(-) delete mode 100644 test/libyul/yulOptimizerTests/conditionalSimplifier/add_correct_type.yul delete mode 100644 test/libyul/yulOptimizerTests/disambiguator/smoke_evmTyped.yul delete mode 100644 test/libyul/yulOptimizerTests/fullInliner/multi_return_typed.yul create mode 100644 test/libyul/yulOptimizerTests/ssaTransform/for_simpler.yul create mode 100644 test/libyul/yulOptimizerTests/ssaTransform/switch_no_default_case.yul delete mode 100644 test/libyul/yulOptimizerTests/ssaTransform/typed_for.yul delete mode 100644 test/libyul/yulOptimizerTests/ssaTransform/typed_switch.yul delete mode 100644 test/libyul/yulOptimizerTests/varDeclInitializer/typed.yul diff --git a/test/libyul/yulOptimizerTests/conditionalSimplifier/add_correct_type.yul b/test/libyul/yulOptimizerTests/conditionalSimplifier/add_correct_type.yul deleted file mode 100644 index 57785f0b3..000000000 --- a/test/libyul/yulOptimizerTests/conditionalSimplifier/add_correct_type.yul +++ /dev/null @@ -1,19 +0,0 @@ -{ - let y:bool := false - for {} true { } { - if y { break } - } -} -// ==== -// dialect: evmTyped -// ---- -// step: conditionalSimplifier -// -// { -// let y:bool := false -// for { } true { } -// { -// if y { break } -// y := false -// } -// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul index fcfbe3242..3a01e1ea5 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul @@ -1,21 +1,19 @@ { - { let a:u256, b:u256 } + { let a, b } { - function eq_function(x: u256, y: u256) -> z: bool {} - for { let a:u256 } eq_function(a, a) { a := a } { - let b:u256 := a + function eq_function(x, y) -> z {} + for { let a } eq_function(a, a) { a := a } { + let b := a } } } -// ==== -// dialect: evmTyped // ---- // step: disambiguator // // { // { let a, b } // { -// function eq_function(x, y) -> z:bool +// function eq_function(x, y) -> z // { } // for { let a_1 } eq_function(a_1, a_1) { a_1 := a_1 } // { let b_2 := a_1 } diff --git a/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul b/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul index 7fc51a5fa..0c25f3ee5 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul @@ -1,13 +1,11 @@ { - { let a:u256, b:u256, c:u256, d:u256, f:u256 } + { let a, b, c, d, f } { - function f(a:u256) -> c:u256, d:u256 { - let b:u256, c_1:u256 := f(a) + function f(a) -> c, d { + let b, c_1 := f(a) } } } -// ==== -// dialect: evmTyped // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul index 512d7fc12..e68d9b581 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul @@ -1,19 +1,17 @@ { - { let a:u256, b:u256, c:u256 } + { let a, b, c } { - let a:bool - if a { let b:bool := a } + let a + if a { let b := a } } } -// ==== -// dialect: evmTyped // ---- // step: disambiguator // // { // { let a, b, c } // { -// let a_1:bool -// if a_1 { let b_2:bool := a_1 } +// let a_1 +// if a_1 { let b_2 := a_1 } // } // } diff --git a/test/libyul/yulOptimizerTests/disambiguator/long_names.yul b/test/libyul/yulOptimizerTests/disambiguator/long_names.yul index fbd95ef3a..1d0530f32 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/long_names.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/long_names.yul @@ -1,6 +1,4 @@ -{ { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } } -// ==== -// dialect: evmTyped +{ { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh } { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh } } // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/smoke_evmTyped.yul b/test/libyul/yulOptimizerTests/disambiguator/smoke_evmTyped.yul deleted file mode 100644 index 481cbb588..000000000 --- a/test/libyul/yulOptimizerTests/disambiguator/smoke_evmTyped.yul +++ /dev/null @@ -1,7 +0,0 @@ -{ } -// ==== -// dialect: evmTyped -// ---- -// step: disambiguator -// -// { } diff --git a/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul index 86ea9cba2..d70a805c3 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul @@ -1,14 +1,12 @@ { - { let a:u256, b:u256, c:u256 } + { let a, b, c } { - let a:u256 + let a switch a - case 0:u256 { let b:u256 := a } - default { let c:u256 := a } + case 0 { let b := a } + default { let c := a } } } -// ==== -// dialect: evmTyped // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables.yul b/test/libyul/yulOptimizerTests/disambiguator/variables.yul index 743eaf0de..900090368 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/variables.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/variables.yul @@ -1,6 +1,4 @@ -{ { let a:u256 } { let a:u256 } } -// ==== -// dialect: evmTyped +{ { let a } { let a } } // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul b/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul index 2a94e4769..40ca2b262 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul @@ -1,6 +1,4 @@ -{ { let a:u256 let a_1:u256 } { let a:u256 } } -// ==== -// dialect: evmTyped +{ { let a let a_1 } { let a } } // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul b/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul index f9e134aff..f26aaced2 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul @@ -1,12 +1,10 @@ { - { let c:u256 let b:u256 } - function f(a:u256, c:u256) -> b:u256 { let x:u256 } + { let c let b } + function f(a, c) -> b { let x } { - let a:u256 let x:u256 + let a let x } } -// ==== -// dialect: evmTyped // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/expressionInliner/simple.yul b/test/libyul/yulOptimizerTests/expressionInliner/simple.yul index dbc80a859..24508bb76 100644 --- a/test/libyul/yulOptimizerTests/expressionInliner/simple.yul +++ b/test/libyul/yulOptimizerTests/expressionInliner/simple.yul @@ -1,9 +1,7 @@ { - function f() -> x:u256 { x := 2:u256 } - let y:u256 := f() + function f() -> x { x := 2 } + let y := f() } -// ==== -// dialect: evmTyped // ---- // step: expressionInliner // diff --git a/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul b/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul index e142f5978..caf4cc42e 100644 --- a/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul +++ b/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul @@ -1,9 +1,7 @@ { - function f(a:u256) -> x:u256 { x := a } - let y:u256 := f(7:u256) + function f(a) -> x { x := a } + let y := f(7) } -// ==== -// dialect: evmTyped // ---- // step: expressionInliner // diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_return_typed.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_return_typed.yul deleted file mode 100644 index 143ae35b2..000000000 --- a/test/libyul/yulOptimizerTests/fullInliner/multi_return_typed.yul +++ /dev/null @@ -1,23 +0,0 @@ -{ - function f(a: u256) -> x: bool, y:u256 { - y := mul(a, a) - } - let r: bool, s: u256 := f(mload(3)) -} -// ==== -// dialect: evmTyped -// ---- -// step: fullInliner -// -// { -// { -// let a_3 := mload(3) -// let x_4:bool := false -// let y_5 := 0 -// y_5 := mul(a_3, a_3) -// let r:bool := x_4 -// let s := y_5 -// } -// function f(a) -> x:bool, y -// { y := mul(a, a) } -// } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul b/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul index 05fa8d249..4d2d2c807 100644 --- a/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul +++ b/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul @@ -1,6 +1,4 @@ -{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } } -// ==== -// dialect: evmTyped +{ let a { } function f() -> x { let b := 4 {} for {} f() {} {} } } // ---- // step: functionGrouper // @@ -9,7 +7,7 @@ // let a // { } // } -// function f() -> x:bool +// function f() -> x // { // let b := 4 // { } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul b/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul index 5d4eaea5e..9ac43aebd 100644 --- a/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul +++ b/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul @@ -1,11 +1,9 @@ { - let a:u256 - function f() { let b:u256 } - let c:u256 function g() { let d:u256 } - let e:u256 + let a + function f() { let b } + let c function g() { let d } + let e } -// ==== -// dialect: evmTyped // ---- // step: functionGrouper // diff --git a/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul b/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul index 5b8436540..2c0ac2453 100644 --- a/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul +++ b/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul @@ -1,15 +1,13 @@ { - let a:u256 + let a function f() { - let b:u256 + let b function g() { - let c:u256 + let c } - let d:u256 + let d } } -// ==== -// dialect: evmTyped // ---- // step: functionGrouper // diff --git a/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul b/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul index a62b0ddeb..295ba1e42 100644 --- a/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul +++ b/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul @@ -1,8 +1,6 @@ { - let a:u256 function f() {} + let a function f() {} } -// ==== -// dialect: evmTyped // ---- // step: functionGrouper // diff --git a/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul b/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul index 5eed2d2bb..a97027bfe 100644 --- a/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul +++ b/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul @@ -1,20 +1,18 @@ { - let a:u256 + let a { } - function f() -> x:bool { - let b:u256 := 4:u256 + function f() -> x { + let b := 4 { } for {} f() {} {} } } -// ==== -// dialect: evmTyped // ---- // step: functionHoister // // { // let a -// function f() -> x:bool +// function f() -> x // { // let b := 4 // for { } f() { } diff --git a/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul b/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul index fc6168ce9..22feac222 100644 --- a/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul +++ b/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul @@ -1,12 +1,10 @@ { - let a:u256 - function f() { let b:u256 } - let c:u256 - function g() { let d:u256 } - let e:u256 + let a + function f() { let b } + let c + function g() { let d } + let e } -// ==== -// dialect: evmTyped // ---- // step: functionHoister // diff --git a/test/libyul/yulOptimizerTests/functionHoister/nested.yul b/test/libyul/yulOptimizerTests/functionHoister/nested.yul index 65486dc6c..c7182f607 100644 --- a/test/libyul/yulOptimizerTests/functionHoister/nested.yul +++ b/test/libyul/yulOptimizerTests/functionHoister/nested.yul @@ -1,13 +1,11 @@ { - let a:u256 + let a function f() { - let b:u256 - function g() { let c:u256 } - let d:u256 + let b + function g() { let c } + let d } } -// ==== -// dialect: evmTyped // ---- // step: functionHoister // diff --git a/test/libyul/yulOptimizerTests/functionHoister/single.yul b/test/libyul/yulOptimizerTests/functionHoister/single.yul index e939ecb85..e44b41ee2 100644 --- a/test/libyul/yulOptimizerTests/functionHoister/single.yul +++ b/test/libyul/yulOptimizerTests/functionHoister/single.yul @@ -1,9 +1,7 @@ { - let a:u256 + let a function f() {} } -// ==== -// dialect: evmTyped // ---- // step: functionHoister // diff --git a/test/libyul/yulOptimizerTests/ssaTransform/for_simpler.yul b/test/libyul/yulOptimizerTests/ssaTransform/for_simpler.yul new file mode 100644 index 000000000..82ef5a16b --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/for_simpler.yul @@ -0,0 +1,24 @@ +{ + let b := true + let c := false + for {} b {} { + c := true + } + let d := c +} +// ---- +// step: ssaTransform +// +// { +// let b := true +// let c_1 := false +// let c := c_1 +// for { } b { } +// { +// let c_3 := c +// let c_2 := true +// c := c_2 +// } +// let c_4 := c +// let d := c_4 +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/switch_no_default_case.yul b/test/libyul/yulOptimizerTests/ssaTransform/switch_no_default_case.yul new file mode 100644 index 000000000..18168479b --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/switch_no_default_case.yul @@ -0,0 +1,24 @@ +{ + let b := true + let c := false + switch b + case true { c := true} + case false { } + let d := c +} +// ---- +// step: ssaTransform +// +// { +// let b := true +// let c_1 := false +// let c := c_1 +// switch b +// case true { +// let c_2 := true +// c := c_2 +// } +// case false { } +// let c_3 := c +// let d := c_3 +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/typed.yul b/test/libyul/yulOptimizerTests/ssaTransform/typed.yul index 4b1aa1643..4b722e25c 100644 --- a/test/libyul/yulOptimizerTests/ssaTransform/typed.yul +++ b/test/libyul/yulOptimizerTests/ssaTransform/typed.yul @@ -1,10 +1,10 @@ { - let b:bool := true - let c:bool := false + let b := true + let c := false c := b b := false - let a:u256 := 1 + let a := 1 a := add(a, 1) if c { a := add(a, 1) @@ -12,19 +12,17 @@ a := add(a, 1) mstore(a, 1) } -// ==== -// dialect: evmTyped // ---- // step: ssaTransform // // { -// let b_1:bool := true -// let b:bool := b_1 -// let c_2:bool := false -// let c:bool := c_2 -// let c_3:bool := b_1 +// let b_1 := true +// let b := b_1 +// let c_2 := false +// let c := c_2 +// let c_3 := b_1 // c := c_3 -// let b_4:bool := false +// let b_4 := false // b := b_4 // let a_5 := 1 // let a := a_5 diff --git a/test/libyul/yulOptimizerTests/ssaTransform/typed_for.yul b/test/libyul/yulOptimizerTests/ssaTransform/typed_for.yul deleted file mode 100644 index 596f56cb0..000000000 --- a/test/libyul/yulOptimizerTests/ssaTransform/typed_for.yul +++ /dev/null @@ -1,26 +0,0 @@ -{ - let b:bool := true - let c:bool := false - for {} b {} { - c := true - } - let d: bool := c -} -// ==== -// dialect: evmTyped -// ---- -// step: ssaTransform -// -// { -// let b:bool := true -// let c_1:bool := false -// let c:bool := c_1 -// for { } b { } -// { -// let c_3:bool := c -// let c_2:bool := true -// c := c_2 -// } -// let c_4:bool := c -// let d:bool := c_4 -// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/typed_switch.yul b/test/libyul/yulOptimizerTests/ssaTransform/typed_switch.yul deleted file mode 100644 index b87b5dbbc..000000000 --- a/test/libyul/yulOptimizerTests/ssaTransform/typed_switch.yul +++ /dev/null @@ -1,26 +0,0 @@ -{ - let b:bool := true - let c:bool := false - switch b - case true { c := true} - case false { } - let d: bool := c -} -// ==== -// dialect: evmTyped -// ---- -// step: ssaTransform -// -// { -// let b:bool := true -// let c_1:bool := false -// let c:bool := c_1 -// switch b -// case true { -// let c_2:bool := true -// c := c_2 -// } -// case false { } -// let c_3:bool := c -// let d:bool := c_3 -// } diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/typed.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/typed.yul deleted file mode 100644 index 069c68cab..000000000 --- a/test/libyul/yulOptimizerTests/varDeclInitializer/typed.yul +++ /dev/null @@ -1,24 +0,0 @@ -{ - let a1 - let a2: bool - let b1, b2: bool - function f(a:u256, b:u256, c:bool) -> r:bool, t { - let x1: bool, x2 - } -} -// ==== -// dialect: evmTyped -// ---- -// step: varDeclInitializer -// -// { -// let a1 := 0 -// let a2:bool := false -// let b1 := 0 -// let b2:bool := false -// function f(a, b, c:bool) -> r:bool, t -// { -// let x1:bool := false -// let x2 := 0 -// } -// } From d7bfea0c7c8c08afc4d6b62deeae5a9b8ebf384d Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 13 Aug 2024 09:30:54 +0200 Subject: [PATCH 0252/1340] Yul syntax tests: Update test expectations to use evm instead of evmTyped --- test/libyul/SyntaxTest.cpp | 2 +- test/libyul/yulSyntaxTests/assign_from_stack.yul | 2 +- test/libyul/yulSyntaxTests/assignment.yul | 4 ++-- test/libyul/yulSyntaxTests/assignment_fail.yul | 12 ------------ test/libyul/yulSyntaxTests/blocks.yul | 6 +++--- .../yulSyntaxTests/break_outside_of_for_loop.yul | 6 ++---- test/libyul/yulSyntaxTests/builtin_types.yul | 6 ++---- .../yulSyntaxTests/continue_outside_of_for_loop.yul | 6 ++---- test/libyul/yulSyntaxTests/for_loop_condition.yul | 4 +--- .../yulSyntaxTests/for_loop_condition_fail.yul | 8 -------- test/libyul/yulSyntaxTests/for_statement.yul | 4 +--- test/libyul/yulSyntaxTests/for_statement_break.yul | 4 +--- .../yulSyntaxTests/for_statement_break_init.yul | 6 ++---- .../for_statement_break_nested_body_in_init.yul | 4 +--- .../for_statement_break_nested_body_in_post.yul | 4 +--- .../yulSyntaxTests/for_statement_break_post.yul | 6 ++---- .../libyul/yulSyntaxTests/for_statement_continue.yul | 4 +--- .../for_statement_continue_fail_init.yul | 6 ++---- .../for_statement_continue_fail_post.yul | 6 ++---- .../for_statement_continue_nested_body_in_init.yul | 4 +--- .../for_statement_continue_nested_body_in_post.yul | 4 +--- .../for_statement_continue_nested_init_in_body.yul | 6 ++---- .../yulSyntaxTests/for_statement_nested_break.yul | 6 ++---- .../yulSyntaxTests/for_statement_nested_continue.yul | 2 -- test/libyul/yulSyntaxTests/for_visibility_9.yul | 2 -- test/libyul/yulSyntaxTests/function_calls.yul | 6 +++--- .../function_defined_in_init_block_1.yul | 2 +- .../function_defined_in_init_block_2.yul | 2 +- .../function_defined_in_init_block_3.yul | 2 +- .../function_defined_in_init_nested_1.yul | 4 ++-- .../function_defined_in_init_nested_2.yul | 2 +- .../function_defined_in_init_nested_3.yul | 6 +++--- test/libyul/yulSyntaxTests/function_definitions.yul | 2 +- .../function_shadowing_outside_vars_1.yul | 4 ++-- .../function_shadowing_outside_vars_2.yul | 6 +++--- .../yulSyntaxTests/functions_multiple_args.yul | 4 ++-- test/libyul/yulSyntaxTests/if_statement_1.yul | 4 +--- test/libyul/yulSyntaxTests/if_statement_2.yul | 6 ++---- test/libyul/yulSyntaxTests/if_statement_3.yul | 6 ++---- test/libyul/yulSyntaxTests/if_statement_fail_1.yul | 4 +--- test/libyul/yulSyntaxTests/if_statement_fail_2.yul | 6 ++---- test/libyul/yulSyntaxTests/if_statement_fail_3.yul | 5 ----- test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul | 2 -- test/libyul/yulSyntaxTests/invalid_type.yul | 2 -- test/libyul/yulSyntaxTests/invalid_type2.yul | 4 +--- test/libyul/yulSyntaxTests/invalid_type3.yul | 2 -- test/libyul/yulSyntaxTests/invalid_type4.yul | 4 +--- test/libyul/yulSyntaxTests/linkersymbol_evmtyped.yul | 8 -------- .../linkersymbol_invalid_redefine_builtin.yul | 6 ++++++ test/libyul/yulSyntaxTests/literal_invalid_type.yul | 8 ++++---- test/libyul/yulSyntaxTests/multiple_assignment_1.yul | 10 ++++------ test/libyul/yulSyntaxTests/multiple_assignment_2.yul | 10 ++++------ test/libyul/yulSyntaxTests/multiple_assignment_3.yul | 10 ++++------ test/libyul/yulSyntaxTests/number_literal_1.yul | 2 +- test/libyul/yulSyntaxTests/number_literal_2.yul | 4 ++-- test/libyul/yulSyntaxTests/number_literal_3.yul | 4 ++-- test/libyul/yulSyntaxTests/number_literal_4.yul | 4 ++-- test/libyul/yulSyntaxTests/number_literal_5.yul | 4 ++-- test/libyul/yulSyntaxTests/optional_types.yul | 8 +++----- test/libyul/yulSyntaxTests/period_in_identifier.yul | 2 +- .../yulSyntaxTests/period_in_identifier_spaced_1.yul | 4 ++-- .../yulSyntaxTests/period_in_identifier_spaced_2.yul | 2 +- .../yulSyntaxTests/period_in_identifier_spaced_3.yul | 2 +- .../yulSyntaxTests/period_in_identifier_start.yul | 4 ++-- .../period_in_identifier_start_with_comment.yul | 2 +- .../period_not_as_identifier_start.yul | 2 +- test/libyul/yulSyntaxTests/push.yul | 4 ++-- test/libyul/yulSyntaxTests/recursion_depth.yul | 4 +--- test/libyul/yulSyntaxTests/switch_case.yul | 8 +++----- .../yulSyntaxTests/switch_case_different_literal.yul | 8 +++----- .../switch_case_string_literal_too_long.yul | 8 +++----- .../switch_case_string_literal_very_long.yul | 6 ++---- test/libyul/yulSyntaxTests/switch_duplicate_case.yul | 10 ++++------ .../switch_duplicate_case_different_literal.yul | 10 ++++------ test/libyul/yulSyntaxTests/token_as_identifier.yul | 4 +--- test/libyul/yulSyntaxTests/tuple_assignment.yul | 4 ++-- .../type_check_cases_fail_evmtyped.yul | 10 ---------- .../yulSyntaxTests/user_defined_functions_fail.yul | 11 ++++------- .../yulSyntaxTests/user_defined_functions_fine.yul | 8 +++----- test/libyul/yulSyntaxTests/variable_declaration.yul | 4 +--- .../yulSyntaxTests/variable_declaration_bool.yul | 6 ++---- .../yulSyntaxTests/variable_declaration_complex.yul | 8 +++----- .../yulSyntaxTests/variable_declaration_empty.yul | 2 +- 83 files changed, 145 insertions(+), 275 deletions(-) delete mode 100644 test/libyul/yulSyntaxTests/assignment_fail.yul delete mode 100644 test/libyul/yulSyntaxTests/for_loop_condition_fail.yul delete mode 100644 test/libyul/yulSyntaxTests/if_statement_fail_3.yul delete mode 100644 test/libyul/yulSyntaxTests/linkersymbol_evmtyped.yul create mode 100644 test/libyul/yulSyntaxTests/linkersymbol_invalid_redefine_builtin.yul delete mode 100644 test/libyul/yulSyntaxTests/type_check_cases_fail_evmtyped.yul diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index 0201e047d..7ed87bee4 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -74,6 +74,6 @@ void SyntaxTest::parseAndAnalyze() SyntaxTest::SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVersion): CommonSyntaxTest(_filename, _evmVersion) { - std::string dialectName = m_reader.stringSetting("dialect", "evmTyped"); + std::string dialectName = m_reader.stringSetting("dialect", "evm"); m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); } diff --git a/test/libyul/yulSyntaxTests/assign_from_stack.yul b/test/libyul/yulSyntaxTests/assign_from_stack.yul index 44f50ab5e..ce48abe99 100644 --- a/test/libyul/yulSyntaxTests/assign_from_stack.yul +++ b/test/libyul/yulSyntaxTests/assign_from_stack.yul @@ -1,3 +1,3 @@ -{ =: x:u256 } +{ =: x } // ---- // ParserError 1856: (2-3): Literal or identifier expected. diff --git a/test/libyul/yulSyntaxTests/assignment.yul b/test/libyul/yulSyntaxTests/assignment.yul index 6c2c0f5a4..5ba2e3437 100644 --- a/test/libyul/yulSyntaxTests/assignment.yul +++ b/test/libyul/yulSyntaxTests/assignment.yul @@ -1,5 +1,5 @@ { - let x:u256 := 2:u256 - let y:u256 := x + let x := 2 + let y := x } // ---- diff --git a/test/libyul/yulSyntaxTests/assignment_fail.yul b/test/libyul/yulSyntaxTests/assignment_fail.yul deleted file mode 100644 index 1bcf3fbb3..000000000 --- a/test/libyul/yulSyntaxTests/assignment_fail.yul +++ /dev/null @@ -1,12 +0,0 @@ -{ - let x:u256 - let y := x - let z:bool - z := y - y := z -} -// ==== -// dialect: evmTyped -// ---- -// TypeError 9547: (51-52): Assigning a value of type "u256" to a variable of type "bool". -// TypeError 9547: (62-63): Assigning a value of type "bool" to a variable of type "u256". diff --git a/test/libyul/yulSyntaxTests/blocks.yul b/test/libyul/yulSyntaxTests/blocks.yul index 8c2fdd9a9..16e52fe73 100644 --- a/test/libyul/yulSyntaxTests/blocks.yul +++ b/test/libyul/yulSyntaxTests/blocks.yul @@ -1,10 +1,10 @@ { - let x:u256 := 7:u256 + let x := 7 { - let y:u256 := 3:u256 + let y := 3 } { - let z:u256 := 2:u256 + let z := 2 } } // ---- diff --git a/test/libyul/yulSyntaxTests/break_outside_of_for_loop.yul b/test/libyul/yulSyntaxTests/break_outside_of_for_loop.yul index 1d0f997e6..60329f46f 100644 --- a/test/libyul/yulSyntaxTests/break_outside_of_for_loop.yul +++ b/test/libyul/yulSyntaxTests/break_outside_of_for_loop.yul @@ -1,8 +1,6 @@ { - let x:bool + let x if x { break } } -// ==== -// dialect: evmTyped // ---- -// SyntaxError 2592: (22-27): Keyword "break" needs to be inside a for-loop body. +// SyntaxError 2592: (17-22): Keyword "break" needs to be inside a for-loop body. diff --git a/test/libyul/yulSyntaxTests/builtin_types.yul b/test/libyul/yulSyntaxTests/builtin_types.yul index e4d961c30..275addf39 100644 --- a/test/libyul/yulSyntaxTests/builtin_types.yul +++ b/test/libyul/yulSyntaxTests/builtin_types.yul @@ -1,7 +1,5 @@ { - let x1:bool := true:bool - let x2:u256 := 1:u256 + let x1 := true + let x2 := 1 } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/continue_outside_of_for_loop.yul b/test/libyul/yulSyntaxTests/continue_outside_of_for_loop.yul index c12f7945d..741a4d5b6 100644 --- a/test/libyul/yulSyntaxTests/continue_outside_of_for_loop.yul +++ b/test/libyul/yulSyntaxTests/continue_outside_of_for_loop.yul @@ -1,8 +1,6 @@ { - let x:bool + let x if x { continue } } -// ==== -// dialect: evmTyped // ---- -// SyntaxError 2592: (22-30): Keyword "continue" needs to be inside a for-loop body. +// SyntaxError 2592: (17-25): Keyword "continue" needs to be inside a for-loop body. diff --git a/test/libyul/yulSyntaxTests/for_loop_condition.yul b/test/libyul/yulSyntaxTests/for_loop_condition.yul index 72ed7b71f..22db0ce75 100644 --- a/test/libyul/yulSyntaxTests/for_loop_condition.yul +++ b/test/libyul/yulSyntaxTests/for_loop_condition.yul @@ -1,7 +1,5 @@ { - let x:bool + let x for {} x {} {} } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/for_loop_condition_fail.yul b/test/libyul/yulSyntaxTests/for_loop_condition_fail.yul deleted file mode 100644 index 98a52bf24..000000000 --- a/test/libyul/yulSyntaxTests/for_loop_condition_fail.yul +++ /dev/null @@ -1,8 +0,0 @@ -{ - let x - for {} x {} {} -} -// ==== -// dialect: evmTyped -// ---- -// TypeError 1733: (23-24): Expected a value of boolean type "bool" but got "u256" diff --git a/test/libyul/yulSyntaxTests/for_statement.yul b/test/libyul/yulSyntaxTests/for_statement.yul index 7f180ea8f..6da73b300 100644 --- a/test/libyul/yulSyntaxTests/for_statement.yul +++ b/test/libyul/yulSyntaxTests/for_statement.yul @@ -1,7 +1,5 @@ { - let x:bool + let x for {let i := 0} x {i := add(i, 1)} {} } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/for_statement_break.yul b/test/libyul/yulSyntaxTests/for_statement_break.yul index 4e432557b..258cb4c41 100644 --- a/test/libyul/yulSyntaxTests/for_statement_break.yul +++ b/test/libyul/yulSyntaxTests/for_statement_break.yul @@ -1,10 +1,8 @@ { - let x:bool + let x for {let i := 0} x {i := add(i, 1)} { break } } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/for_statement_break_init.yul b/test/libyul/yulSyntaxTests/for_statement_break_init.yul index 7fb15faf0..bf00d0dfb 100644 --- a/test/libyul/yulSyntaxTests/for_statement_break_init.yul +++ b/test/libyul/yulSyntaxTests/for_statement_break_init.yul @@ -1,8 +1,6 @@ { - let x:bool + let x for {let i := 0 break} x {i := add(i, 1)} {} } -// ==== -// dialect: evmTyped // ---- -// SyntaxError 9615: (31-36): Keyword "break" in for-loop init block is not allowed. +// SyntaxError 9615: (26-31): Keyword "break" in for-loop init block is not allowed. diff --git a/test/libyul/yulSyntaxTests/for_statement_break_nested_body_in_init.yul b/test/libyul/yulSyntaxTests/for_statement_break_nested_body_in_init.yul index 9ffe751cc..cc0fdd341 100644 --- a/test/libyul/yulSyntaxTests/for_statement_break_nested_body_in_init.yul +++ b/test/libyul/yulSyntaxTests/for_statement_break_nested_body_in_init.yul @@ -1,7 +1,5 @@ { - for {let x:bool for {} x {} { break }} 1:bool {} + for {let x for {} x {} { break }} 1 {} {} } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/for_statement_break_nested_body_in_post.yul b/test/libyul/yulSyntaxTests/for_statement_break_nested_body_in_post.yul index ab012a73f..0127e178e 100644 --- a/test/libyul/yulSyntaxTests/for_statement_break_nested_body_in_post.yul +++ b/test/libyul/yulSyntaxTests/for_statement_break_nested_body_in_post.yul @@ -1,7 +1,5 @@ { - for {} 1:bool {let x:bool for {} x {} { break }} + for {} 1 {let x for {} x {} { break }} {} } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/for_statement_break_post.yul b/test/libyul/yulSyntaxTests/for_statement_break_post.yul index 93d1475d0..595ab60d2 100644 --- a/test/libyul/yulSyntaxTests/for_statement_break_post.yul +++ b/test/libyul/yulSyntaxTests/for_statement_break_post.yul @@ -1,8 +1,6 @@ { - let x:bool + let x for {let i := 0 } x {i := add(i, 1) break} {} } -// ==== -// dialect: evmTyped // ---- -// SyntaxError 2461: (51-56): Keyword "break" in for-loop post block is not allowed. +// SyntaxError 2461: (46-51): Keyword "break" in for-loop post block is not allowed. diff --git a/test/libyul/yulSyntaxTests/for_statement_continue.yul b/test/libyul/yulSyntaxTests/for_statement_continue.yul index b7c2b0251..f9badaf55 100644 --- a/test/libyul/yulSyntaxTests/for_statement_continue.yul +++ b/test/libyul/yulSyntaxTests/for_statement_continue.yul @@ -1,10 +1,8 @@ { - let x:bool + let x for {let i := 0} x {i := add(i, 1)} { continue } } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/for_statement_continue_fail_init.yul b/test/libyul/yulSyntaxTests/for_statement_continue_fail_init.yul index eca0d4692..00683f853 100644 --- a/test/libyul/yulSyntaxTests/for_statement_continue_fail_init.yul +++ b/test/libyul/yulSyntaxTests/for_statement_continue_fail_init.yul @@ -1,10 +1,8 @@ { - let x:bool + let x for {let i := 0 continue} x {i := add(i, 1)} { } } -// ==== -// dialect: evmTyped // ---- -// SyntaxError 9615: (31-39): Keyword "continue" in for-loop init block is not allowed. +// SyntaxError 9615: (26-34): Keyword "continue" in for-loop init block is not allowed. diff --git a/test/libyul/yulSyntaxTests/for_statement_continue_fail_post.yul b/test/libyul/yulSyntaxTests/for_statement_continue_fail_post.yul index 7362b38b2..d8c5faaa8 100644 --- a/test/libyul/yulSyntaxTests/for_statement_continue_fail_post.yul +++ b/test/libyul/yulSyntaxTests/for_statement_continue_fail_post.yul @@ -1,8 +1,6 @@ { - let x:bool + let x for {let i := 0} x {i := add(i, 1) continue} {} } -// ==== -// dialect: evmTyped // ---- -// SyntaxError 2461: (50-58): Keyword "continue" in for-loop post block is not allowed. +// SyntaxError 2461: (45-53): Keyword "continue" in for-loop post block is not allowed. diff --git a/test/libyul/yulSyntaxTests/for_statement_continue_nested_body_in_init.yul b/test/libyul/yulSyntaxTests/for_statement_continue_nested_body_in_init.yul index 305cdd36d..565489a37 100644 --- a/test/libyul/yulSyntaxTests/for_statement_continue_nested_body_in_init.yul +++ b/test/libyul/yulSyntaxTests/for_statement_continue_nested_body_in_init.yul @@ -1,8 +1,6 @@ { - for {let x:bool for {} x {} { continue }} 1:bool {} + for {let x for {} x {} { continue }} 1 {} { } } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/for_statement_continue_nested_body_in_post.yul b/test/libyul/yulSyntaxTests/for_statement_continue_nested_body_in_post.yul index e33bd2457..dd7927a8f 100644 --- a/test/libyul/yulSyntaxTests/for_statement_continue_nested_body_in_post.yul +++ b/test/libyul/yulSyntaxTests/for_statement_continue_nested_body_in_post.yul @@ -1,7 +1,5 @@ { - for {} 1:bool {let x:bool for {} x {} { continue }} + for {} 1 {let x for {} x {} { continue }} {} } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/for_statement_continue_nested_init_in_body.yul b/test/libyul/yulSyntaxTests/for_statement_continue_nested_init_in_body.yul index 1ff20943f..c6abf3b53 100644 --- a/test/libyul/yulSyntaxTests/for_statement_continue_nested_init_in_body.yul +++ b/test/libyul/yulSyntaxTests/for_statement_continue_nested_init_in_body.yul @@ -1,11 +1,9 @@ { for {} 1 {} { - let x:bool + let x for { continue } x {} {} } } -// ==== -// dialect: evmTyped // ---- -// SyntaxError 9615: (39-47): Keyword "continue" in for-loop init block is not allowed. +// SyntaxError 9615: (34-42): Keyword "continue" in for-loop init block is not allowed. diff --git a/test/libyul/yulSyntaxTests/for_statement_nested_break.yul b/test/libyul/yulSyntaxTests/for_statement_nested_break.yul index ae3fd9da4..3b29cd754 100644 --- a/test/libyul/yulSyntaxTests/for_statement_nested_break.yul +++ b/test/libyul/yulSyntaxTests/for_statement_nested_break.yul @@ -1,11 +1,9 @@ { - let x:bool + let x for {let i := 0} x {} { function f() { break } } } -// ==== -// dialect: evmTyped // ---- -// SyntaxError 2592: (57-62): Keyword "break" needs to be inside a for-loop body. +// SyntaxError 2592: (52-57): Keyword "break" needs to be inside a for-loop body. diff --git a/test/libyul/yulSyntaxTests/for_statement_nested_continue.yul b/test/libyul/yulSyntaxTests/for_statement_nested_continue.yul index 8e7eca428..6e32d19b7 100644 --- a/test/libyul/yulSyntaxTests/for_statement_nested_continue.yul +++ b/test/libyul/yulSyntaxTests/for_statement_nested_continue.yul @@ -4,7 +4,5 @@ function f() { continue } } } -// ==== -// dialect: evmTyped // ---- // SyntaxError 2592: (61-69): Keyword "continue" needs to be inside a for-loop body. diff --git a/test/libyul/yulSyntaxTests/for_visibility_9.yul b/test/libyul/yulSyntaxTests/for_visibility_9.yul index 6922dc961..d12524e88 100644 --- a/test/libyul/yulSyntaxTests/for_visibility_9.yul +++ b/test/libyul/yulSyntaxTests/for_visibility_9.yul @@ -1,7 +1,5 @@ { for { let x := 1 } 1 { let x := 1 } {} } -// ==== -// dialect: evmTyped // ---- // DeclarationError 1395: (26-36): Variable name x already taken in this scope. diff --git a/test/libyul/yulSyntaxTests/function_calls.yul b/test/libyul/yulSyntaxTests/function_calls.yul index 777382b12..586e778d3 100644 --- a/test/libyul/yulSyntaxTests/function_calls.yul +++ b/test/libyul/yulSyntaxTests/function_calls.yul @@ -1,8 +1,8 @@ { - function f(a:u256) -> b:u256 {} - function g(a:u256, b:u256, c:u256) {} + function f(a) -> b {} + function g(a, b, c) {} function x() { - g(1:u256, 2:u256, f(3:u256)) + g(1, 2, f(3)) x() } } diff --git a/test/libyul/yulSyntaxTests/function_defined_in_init_block_1.yul b/test/libyul/yulSyntaxTests/function_defined_in_init_block_1.yul index 6f921a4ea..165337bcb 100644 --- a/test/libyul/yulSyntaxTests/function_defined_in_init_block_1.yul +++ b/test/libyul/yulSyntaxTests/function_defined_in_init_block_1.yul @@ -1,4 +1,4 @@ { - for { } 1:bool { function f() {} } {} + for { } 1 { function f() {} } {} } // ---- diff --git a/test/libyul/yulSyntaxTests/function_defined_in_init_block_2.yul b/test/libyul/yulSyntaxTests/function_defined_in_init_block_2.yul index f6c92d92a..61a8b1c56 100644 --- a/test/libyul/yulSyntaxTests/function_defined_in_init_block_2.yul +++ b/test/libyul/yulSyntaxTests/function_defined_in_init_block_2.yul @@ -1,4 +1,4 @@ { - for { } 1:bool {} { function f() {} } + for { } 1 {} { function f() {} } } // ---- diff --git a/test/libyul/yulSyntaxTests/function_defined_in_init_block_3.yul b/test/libyul/yulSyntaxTests/function_defined_in_init_block_3.yul index 6e616630a..b9571cbe9 100644 --- a/test/libyul/yulSyntaxTests/function_defined_in_init_block_3.yul +++ b/test/libyul/yulSyntaxTests/function_defined_in_init_block_3.yul @@ -1,5 +1,5 @@ { - for { function f() {} } 1:bool {} {} + for { function f() {} } 1 {} {} } // ---- // SyntaxError 3441: (9-17): Functions cannot be defined inside a for-loop init block. diff --git a/test/libyul/yulSyntaxTests/function_defined_in_init_nested_1.yul b/test/libyul/yulSyntaxTests/function_defined_in_init_nested_1.yul index 766de17a9..e7dca9763 100644 --- a/test/libyul/yulSyntaxTests/function_defined_in_init_nested_1.yul +++ b/test/libyul/yulSyntaxTests/function_defined_in_init_nested_1.yul @@ -1,8 +1,8 @@ { for { - for {} 1:bool { function f() {} } + for {} 1 { function f() {} } {} - } 1:bool {} + } 1 {} {} } // ---- diff --git a/test/libyul/yulSyntaxTests/function_defined_in_init_nested_2.yul b/test/libyul/yulSyntaxTests/function_defined_in_init_nested_2.yul index f5f3accd2..db9445d26 100644 --- a/test/libyul/yulSyntaxTests/function_defined_in_init_nested_2.yul +++ b/test/libyul/yulSyntaxTests/function_defined_in_init_nested_2.yul @@ -1,5 +1,5 @@ { - for { for {function foo() {}} 1:bool {} {} } 1:bool {} {} + for { for {function foo() {}} 1 {} {} } 1 {} {} } // ---- // SyntaxError 3441: (14-22): Functions cannot be defined inside a for-loop init block. diff --git a/test/libyul/yulSyntaxTests/function_defined_in_init_nested_3.yul b/test/libyul/yulSyntaxTests/function_defined_in_init_nested_3.yul index d3a794c0a..ebae8beab 100644 --- a/test/libyul/yulSyntaxTests/function_defined_in_init_nested_3.yul +++ b/test/libyul/yulSyntaxTests/function_defined_in_init_nested_3.yul @@ -1,8 +1,8 @@ { for {} - 1:bool - {for {function foo() {}} 1:bool {} {} } + 1 + {for {function foo() {}} 1 {} {} } {} } // ---- -// SyntaxError 3441: (27-35): Functions cannot be defined inside a for-loop init block. +// SyntaxError 3441: (22-30): Functions cannot be defined inside a for-loop init block. diff --git a/test/libyul/yulSyntaxTests/function_definitions.yul b/test/libyul/yulSyntaxTests/function_definitions.yul index 20dfbb131..ec36b5b80 100644 --- a/test/libyul/yulSyntaxTests/function_definitions.yul +++ b/test/libyul/yulSyntaxTests/function_definitions.yul @@ -1,5 +1,5 @@ { function f() { } - function g(a:u256) -> x:u256 { } + function g(a) -> x { } } // ---- diff --git a/test/libyul/yulSyntaxTests/function_shadowing_outside_vars_1.yul b/test/libyul/yulSyntaxTests/function_shadowing_outside_vars_1.yul index 22c89e2b5..af1273669 100644 --- a/test/libyul/yulSyntaxTests/function_shadowing_outside_vars_1.yul +++ b/test/libyul/yulSyntaxTests/function_shadowing_outside_vars_1.yul @@ -1,5 +1,5 @@ { - { let x:u256 } - function f() -> x:u256 {} + { let x } + function f() -> x {} } // ---- diff --git a/test/libyul/yulSyntaxTests/function_shadowing_outside_vars_2.yul b/test/libyul/yulSyntaxTests/function_shadowing_outside_vars_2.yul index f7fb87278..724f31a3d 100644 --- a/test/libyul/yulSyntaxTests/function_shadowing_outside_vars_2.yul +++ b/test/libyul/yulSyntaxTests/function_shadowing_outside_vars_2.yul @@ -1,6 +1,6 @@ { - let x:u256 - function f() -> x:u256 {} + let x + function f() -> x {} } // ---- -// DeclarationError 1395: (15-40): Variable name x already taken in this scope. +// DeclarationError 1395: (10-30): Variable name x already taken in this scope. diff --git a/test/libyul/yulSyntaxTests/functions_multiple_args.yul b/test/libyul/yulSyntaxTests/functions_multiple_args.yul index aa268dc10..45d481042 100644 --- a/test/libyul/yulSyntaxTests/functions_multiple_args.yul +++ b/test/libyul/yulSyntaxTests/functions_multiple_args.yul @@ -1,5 +1,5 @@ { - function f(a:u256, d:u256) { } - function g(a:u256, d:u256) -> x:u256, y:u256 { } + function f(a, d) { } + function g(a, d) -> x, y { } } // ---- diff --git a/test/libyul/yulSyntaxTests/if_statement_1.yul b/test/libyul/yulSyntaxTests/if_statement_1.yul index b631f8a95..7a5630f25 100644 --- a/test/libyul/yulSyntaxTests/if_statement_1.yul +++ b/test/libyul/yulSyntaxTests/if_statement_1.yul @@ -1,6 +1,4 @@ { - if true:bool {} + if true {} } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/if_statement_2.yul b/test/libyul/yulSyntaxTests/if_statement_2.yul index 20be9b525..7d2ffa225 100644 --- a/test/libyul/yulSyntaxTests/if_statement_2.yul +++ b/test/libyul/yulSyntaxTests/if_statement_2.yul @@ -1,9 +1,7 @@ { - if false:bool + if false { - let x:u256 := 3:u256 + let x := 3 } } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/if_statement_3.yul b/test/libyul/yulSyntaxTests/if_statement_3.yul index 2ba20d39b..c80d8187d 100644 --- a/test/libyul/yulSyntaxTests/if_statement_3.yul +++ b/test/libyul/yulSyntaxTests/if_statement_3.yul @@ -1,11 +1,9 @@ { - function f() -> x:bool {} + function f() -> x {} if f() { - let b:bool := f() + let b := f() } } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/if_statement_fail_1.yul b/test/libyul/yulSyntaxTests/if_statement_fail_1.yul index 6fc409ce3..8bf70df98 100644 --- a/test/libyul/yulSyntaxTests/if_statement_fail_1.yul +++ b/test/libyul/yulSyntaxTests/if_statement_fail_1.yul @@ -1,5 +1,3 @@ -{ if let x:u256 {} } -// ==== -// dialect: evmTyped +{ if let x {} } // ---- // ParserError 1856: (5-8): Literal or identifier expected. diff --git a/test/libyul/yulSyntaxTests/if_statement_fail_2.yul b/test/libyul/yulSyntaxTests/if_statement_fail_2.yul index 97ce0e9f9..8722a7741 100644 --- a/test/libyul/yulSyntaxTests/if_statement_fail_2.yul +++ b/test/libyul/yulSyntaxTests/if_statement_fail_2.yul @@ -1,5 +1,3 @@ -{ if true:bool let x:u256 := 3:u256 } -// ==== -// dialect: evmTyped +{ if true let x := 3 } // ---- -// ParserError 2314: (15-18): Expected '{' but got reserved keyword 'let' +// ParserError 2314: (10-13): Expected '{' but got reserved keyword 'let' diff --git a/test/libyul/yulSyntaxTests/if_statement_fail_3.yul b/test/libyul/yulSyntaxTests/if_statement_fail_3.yul deleted file mode 100644 index 51e36790b..000000000 --- a/test/libyul/yulSyntaxTests/if_statement_fail_3.yul +++ /dev/null @@ -1,5 +0,0 @@ -{ if 42:u256 { } } -// ==== -// dialect: evmTyped -// ---- -// TypeError 1733: (5-12): Expected a value of boolean type "bool" but got "u256" diff --git a/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul b/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul index e43d7a141..d5b3847b1 100644 --- a/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul +++ b/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul @@ -1,7 +1,5 @@ { pop(pc()) } -// ==== -// dialect: evmTyped // ---- // SyntaxError 2450: (10-12): PC instruction is a low-level EVM feature. Because of that PC is disallowed in strict assembly. diff --git a/test/libyul/yulSyntaxTests/invalid_type.yul b/test/libyul/yulSyntaxTests/invalid_type.yul index 99ed4c43b..f86381635 100644 --- a/test/libyul/yulSyntaxTests/invalid_type.yul +++ b/test/libyul/yulSyntaxTests/invalid_type.yul @@ -1,7 +1,5 @@ { let x: invalidType } -// ==== -// dialect: evmTyped // ---- // TypeError 5473: (10-24): "invalidType" is not a valid type (user defined types are not yet supported). diff --git a/test/libyul/yulSyntaxTests/invalid_type2.yul b/test/libyul/yulSyntaxTests/invalid_type2.yul index 2ad035dcf..af30bc2eb 100644 --- a/test/libyul/yulSyntaxTests/invalid_type2.yul +++ b/test/libyul/yulSyntaxTests/invalid_type2.yul @@ -1,8 +1,6 @@ { let x := 1:invalidType } -// ==== -// dialect: evmTyped // ---- // TypeError 5473: (15-28): "invalidType" is not a valid type (user defined types are not yet supported). -// TypeError 3947: (10-11): Assigning value of type "invalidType" to variable of type "u256". +// TypeError 3947: (10-11): Assigning value of type "invalidType" to variable of type "". diff --git a/test/libyul/yulSyntaxTests/invalid_type3.yul b/test/libyul/yulSyntaxTests/invalid_type3.yul index 1ce7092fe..6fc0e35e8 100644 --- a/test/libyul/yulSyntaxTests/invalid_type3.yul +++ b/test/libyul/yulSyntaxTests/invalid_type3.yul @@ -1,8 +1,6 @@ { function f(a: invalidType) -> b: invalidType {} } -// ==== -// dialect: evmTyped // ---- // TypeError 5473: (17-31): "invalidType" is not a valid type (user defined types are not yet supported). // TypeError 5473: (36-50): "invalidType" is not a valid type (user defined types are not yet supported). diff --git a/test/libyul/yulSyntaxTests/invalid_type4.yul b/test/libyul/yulSyntaxTests/invalid_type4.yul index 8195fcf90..90f00ddaa 100644 --- a/test/libyul/yulSyntaxTests/invalid_type4.yul +++ b/test/libyul/yulSyntaxTests/invalid_type4.yul @@ -2,8 +2,6 @@ switch 1 case 8: invalidType {} } -// ==== -// dialect: evmTyped // ---- -// TypeError 3781: (24-38): Expected a value of type "u256" but got "invalidType". +// TypeError 3781: (24-38): Expected a value of type "" but got "invalidType". // TypeError 5473: (24-38): "invalidType" is not a valid type (user defined types are not yet supported). diff --git a/test/libyul/yulSyntaxTests/linkersymbol_evmtyped.yul b/test/libyul/yulSyntaxTests/linkersymbol_evmtyped.yul deleted file mode 100644 index aa9cc3adb..000000000 --- a/test/libyul/yulSyntaxTests/linkersymbol_evmtyped.yul +++ /dev/null @@ -1,8 +0,0 @@ -{ - let addr:u256 := linkersymbol("contract/library.sol:L") - function linkersymbol(x) {} -} -// ==== -// dialect: evmTyped -// ---- -// ParserError 5568: (75-87): Cannot use builtin function name "linkersymbol" as identifier name. diff --git a/test/libyul/yulSyntaxTests/linkersymbol_invalid_redefine_builtin.yul b/test/libyul/yulSyntaxTests/linkersymbol_invalid_redefine_builtin.yul new file mode 100644 index 000000000..462886c87 --- /dev/null +++ b/test/libyul/yulSyntaxTests/linkersymbol_invalid_redefine_builtin.yul @@ -0,0 +1,6 @@ +{ + let addr := linkersymbol("contract/library.sol:L") + function linkersymbol(x) {} +} +// ---- +// ParserError 5568: (70-82): Cannot use builtin function name "linkersymbol" as identifier name. diff --git a/test/libyul/yulSyntaxTests/literal_invalid_type.yul b/test/libyul/yulSyntaxTests/literal_invalid_type.yul index 07a51eb88..fd612a0a5 100644 --- a/test/libyul/yulSyntaxTests/literal_invalid_type.yul +++ b/test/libyul/yulSyntaxTests/literal_invalid_type.yul @@ -1,7 +1,7 @@ { - let x:bool := true:unhappy + let x := true:unhappy } // ---- -// TypeError 5473: (20-32): "unhappy" is not a valid type (user defined types are not yet supported). -// TypeError 5170: (20-32): Invalid type "unhappy" for literal "true". -// TypeError 3947: (10-16): Assigning value of type "unhappy" to variable of type "bool". +// TypeError 5473: (15-27): "unhappy" is not a valid type (user defined types are not yet supported). +// TypeError 5170: (15-27): Invalid type "unhappy" for literal "true". +// TypeError 3947: (10-11): Assigning value of type "unhappy" to variable of type "". diff --git a/test/libyul/yulSyntaxTests/multiple_assignment_1.yul b/test/libyul/yulSyntaxTests/multiple_assignment_1.yul index b619007a5..285374339 100644 --- a/test/libyul/yulSyntaxTests/multiple_assignment_1.yul +++ b/test/libyul/yulSyntaxTests/multiple_assignment_1.yul @@ -1,9 +1,7 @@ { - let x:u256 - function f() -> a:u256, b:u256 {} - 123:u256, x := f() + let x + function f() -> a, b {} + 123, x := f() } -// ==== -// dialect: evmTyped // ---- -// ParserError 2856: (58-59): Variable name must precede "," in multiple assignment. +// ParserError 2856: (38-39): Variable name must precede "," in multiple assignment. diff --git a/test/libyul/yulSyntaxTests/multiple_assignment_2.yul b/test/libyul/yulSyntaxTests/multiple_assignment_2.yul index 852502447..5aae7f668 100644 --- a/test/libyul/yulSyntaxTests/multiple_assignment_2.yul +++ b/test/libyul/yulSyntaxTests/multiple_assignment_2.yul @@ -1,9 +1,7 @@ { - let x:u256 - function f() -> a:u256, b:u256 {} - x, 123:u256 := f() + let x + function f() -> a, b {} + x, 123 := f() } -// ==== -// dialect: evmTyped // ---- -// ParserError 2856: (62-64): Variable name must precede ":=" in assignment. +// ParserError 2856: (42-44): Variable name must precede ":=" in assignment. diff --git a/test/libyul/yulSyntaxTests/multiple_assignment_3.yul b/test/libyul/yulSyntaxTests/multiple_assignment_3.yul index c7ac5eb8e..7a6d8a1ae 100644 --- a/test/libyul/yulSyntaxTests/multiple_assignment_3.yul +++ b/test/libyul/yulSyntaxTests/multiple_assignment_3.yul @@ -1,12 +1,10 @@ { - function f(a:u256) -> r1:u256, r2:u256 { + function f(a) -> r1, r2 { r1 := a - r2 := 7:u256 + r2 := 7 } - let x:u256 := 9:u256 - let y:u256 := 2:u256 + let x := 9 + let y := 2 x, y := f(x) } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/number_literal_1.yul b/test/libyul/yulSyntaxTests/number_literal_1.yul index 5d5bcd150..f261e3157 100644 --- a/test/libyul/yulSyntaxTests/number_literal_1.yul +++ b/test/libyul/yulSyntaxTests/number_literal_1.yul @@ -1,2 +1,2 @@ -{ let x:u256 := 1:u256 } +{ let x := 1 } // ---- diff --git a/test/libyul/yulSyntaxTests/number_literal_2.yul b/test/libyul/yulSyntaxTests/number_literal_2.yul index 94c5929b5..694112146 100644 --- a/test/libyul/yulSyntaxTests/number_literal_2.yul +++ b/test/libyul/yulSyntaxTests/number_literal_2.yul @@ -1,3 +1,3 @@ -{ let x:u256 := .1:u256 } +{ let x := .1 } // ---- -// ParserError 4828: (16-18): Invalid number literal. +// ParserError 4828: (11-13): Invalid number literal. diff --git a/test/libyul/yulSyntaxTests/number_literal_3.yul b/test/libyul/yulSyntaxTests/number_literal_3.yul index 4dbb6879a..b1592adc1 100644 --- a/test/libyul/yulSyntaxTests/number_literal_3.yul +++ b/test/libyul/yulSyntaxTests/number_literal_3.yul @@ -1,3 +1,3 @@ -{ let x:u256 := 1e5:u256 } +{ let x := 1e5 } // ---- -// ParserError 4828: (16-19): Invalid number literal. +// ParserError 4828: (11-14): Invalid number literal. diff --git a/test/libyul/yulSyntaxTests/number_literal_4.yul b/test/libyul/yulSyntaxTests/number_literal_4.yul index 7de784e88..339d7802e 100644 --- a/test/libyul/yulSyntaxTests/number_literal_4.yul +++ b/test/libyul/yulSyntaxTests/number_literal_4.yul @@ -1,3 +1,3 @@ -{ let x:u256 := 67.235:u256 } +{ let x := 67.235 } // ---- -// ParserError 4828: (16-22): Invalid number literal. +// ParserError 4828: (11-17): Invalid number literal. diff --git a/test/libyul/yulSyntaxTests/number_literal_5.yul b/test/libyul/yulSyntaxTests/number_literal_5.yul index df41e69ec..327206e04 100644 --- a/test/libyul/yulSyntaxTests/number_literal_5.yul +++ b/test/libyul/yulSyntaxTests/number_literal_5.yul @@ -1,3 +1,3 @@ -{ let x:u256 := 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:u256 } +{ let x := 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } // ---- -// TypeError 6708: (16-88): Number literal too large (> 256 bits) +// TypeError 6708: (11-78): Number literal too large (> 256 bits) diff --git a/test/libyul/yulSyntaxTests/optional_types.yul b/test/libyul/yulSyntaxTests/optional_types.yul index 151edbf46..121a7d495 100644 --- a/test/libyul/yulSyntaxTests/optional_types.yul +++ b/test/libyul/yulSyntaxTests/optional_types.yul @@ -1,9 +1,7 @@ { - let x := 1:u256 - let y:u256 := 1 + let x := 1 + let y := 1 function f(a) {} - function g(a:u256) -> b {} + function g(a) -> b {} } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/period_in_identifier.yul b/test/libyul/yulSyntaxTests/period_in_identifier.yul index 4ee80a3f4..0fc75185e 100644 --- a/test/libyul/yulSyntaxTests/period_in_identifier.yul +++ b/test/libyul/yulSyntaxTests/period_in_identifier.yul @@ -1,2 +1,2 @@ -{ let x.y:u256 := 2:u256 } +{ let x.y := 2 } // ---- diff --git a/test/libyul/yulSyntaxTests/period_in_identifier_spaced_1.yul b/test/libyul/yulSyntaxTests/period_in_identifier_spaced_1.yul index dc889a2fb..e4ea959d6 100644 --- a/test/libyul/yulSyntaxTests/period_in_identifier_spaced_1.yul +++ b/test/libyul/yulSyntaxTests/period_in_identifier_spaced_1.yul @@ -1,3 +1,3 @@ -{ let x. y:u256 } +{ let x. y } // ---- -// ParserError 6913: (10-11): Call or assignment expected. +// ParserError 6913: (11-12): Call or assignment expected. diff --git a/test/libyul/yulSyntaxTests/period_in_identifier_spaced_2.yul b/test/libyul/yulSyntaxTests/period_in_identifier_spaced_2.yul index 5602cbceb..290eb28a5 100644 --- a/test/libyul/yulSyntaxTests/period_in_identifier_spaced_2.yul +++ b/test/libyul/yulSyntaxTests/period_in_identifier_spaced_2.yul @@ -1,3 +1,3 @@ -{ let x .y:u256 } +{ let x .y } // ---- // ParserError 1856: (8-9): Literal or identifier expected. diff --git a/test/libyul/yulSyntaxTests/period_in_identifier_spaced_3.yul b/test/libyul/yulSyntaxTests/period_in_identifier_spaced_3.yul index 003341b33..3e5ec22a4 100644 --- a/test/libyul/yulSyntaxTests/period_in_identifier_spaced_3.yul +++ b/test/libyul/yulSyntaxTests/period_in_identifier_spaced_3.yul @@ -1,3 +1,3 @@ -{ let x . y:u256 } +{ let x . y } // ---- // ParserError 1856: (8-9): Literal or identifier expected. diff --git a/test/libyul/yulSyntaxTests/period_in_identifier_start.yul b/test/libyul/yulSyntaxTests/period_in_identifier_start.yul index 83da8389f..cb2c66146 100644 --- a/test/libyul/yulSyntaxTests/period_in_identifier_start.yul +++ b/test/libyul/yulSyntaxTests/period_in_identifier_start.yul @@ -1,5 +1,5 @@ { - x.y(2:u256) - function x.y(a:u256) {} + x.y(2) + function x.y(a) {} } // ---- diff --git a/test/libyul/yulSyntaxTests/period_in_identifier_start_with_comment.yul b/test/libyul/yulSyntaxTests/period_in_identifier_start_with_comment.yul index 51623599d..47939019c 100644 --- a/test/libyul/yulSyntaxTests/period_in_identifier_start_with_comment.yul +++ b/test/libyul/yulSyntaxTests/period_in_identifier_start_with_comment.yul @@ -1,3 +1,3 @@ /// comment -{ x.y(2:u256) function x.y(a:u256) {} } +{ x.y(2) function x.y(a) {} } // ---- diff --git a/test/libyul/yulSyntaxTests/period_not_as_identifier_start.yul b/test/libyul/yulSyntaxTests/period_not_as_identifier_start.yul index 0002b76fd..cb47ffb2a 100644 --- a/test/libyul/yulSyntaxTests/period_not_as_identifier_start.yul +++ b/test/libyul/yulSyntaxTests/period_not_as_identifier_start.yul @@ -1,3 +1,3 @@ -{ let .y:u256 } +{ let .y } // ---- // ParserError 2314: (6-7): Expected identifier but got '.' diff --git a/test/libyul/yulSyntaxTests/push.yul b/test/libyul/yulSyntaxTests/push.yul index f3dab144d..beea98be9 100644 --- a/test/libyul/yulSyntaxTests/push.yul +++ b/test/libyul/yulSyntaxTests/push.yul @@ -1,3 +1,3 @@ -{ 0x42:u256 } +{ 0x42 } // ---- -// ParserError 6913: (12-13): Call or assignment expected. +// ParserError 6913: (7-8): Call or assignment expected. diff --git a/test/libyul/yulSyntaxTests/recursion_depth.yul b/test/libyul/yulSyntaxTests/recursion_depth.yul index 9c6501391..97dfd7429 100644 --- a/test/libyul/yulSyntaxTests/recursion_depth.yul +++ b/test/libyul/yulSyntaxTests/recursion_depth.yul @@ -1,7 +1,5 @@ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ -let x:u256 := 0:u256 +let x := 0 }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} -// ==== -// dialect: evmTyped // ---- // ParserError 7319: (600-601): Maximum recursion depth reached during parsing. diff --git a/test/libyul/yulSyntaxTests/switch_case.yul b/test/libyul/yulSyntaxTests/switch_case.yul index 88bda9929..aef17d570 100644 --- a/test/libyul/yulSyntaxTests/switch_case.yul +++ b/test/libyul/yulSyntaxTests/switch_case.yul @@ -1,8 +1,6 @@ { - switch 0:u256 - case 42:u256 {} - case 0x42:u256 {} + switch 0 + case 42 {} + case 0x42 {} } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/switch_case_different_literal.yul b/test/libyul/yulSyntaxTests/switch_case_different_literal.yul index 8514b835d..36f8e0ffc 100644 --- a/test/libyul/yulSyntaxTests/switch_case_different_literal.yul +++ b/test/libyul/yulSyntaxTests/switch_case_different_literal.yul @@ -1,8 +1,6 @@ { - switch 1:u256 - case "1":u256 {} - case "2":u256 {} + switch 1 + case "1" {} + case "2" {} } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/switch_case_string_literal_too_long.yul b/test/libyul/yulSyntaxTests/switch_case_string_literal_too_long.yul index dceb9db16..f8a5c46bc 100644 --- a/test/libyul/yulSyntaxTests/switch_case_string_literal_too_long.yul +++ b/test/libyul/yulSyntaxTests/switch_case_string_literal_too_long.yul @@ -1,9 +1,7 @@ { - let x:u256 + let x switch x - case "012345678901234567890123456789012":u256 {} + case "012345678901234567890123456789012" {} } -// ==== -// dialect: evmTyped // ---- -// TypeError 3069: (30-70): String literal too long (33 > 32) +// TypeError 3069: (25-60): String literal too long (33 > 32) diff --git a/test/libyul/yulSyntaxTests/switch_case_string_literal_very_long.yul b/test/libyul/yulSyntaxTests/switch_case_string_literal_very_long.yul index 55f25124b..94ca50336 100644 --- a/test/libyul/yulSyntaxTests/switch_case_string_literal_very_long.yul +++ b/test/libyul/yulSyntaxTests/switch_case_string_literal_very_long.yul @@ -1,8 +1,6 @@ { - let x:u256 + let x switch x - case "01234567890123456789012345678901":u256 {} + case "01234567890123456789012345678901" {} } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/switch_duplicate_case.yul b/test/libyul/yulSyntaxTests/switch_duplicate_case.yul index 7417f32d6..1dd5f60eb 100644 --- a/test/libyul/yulSyntaxTests/switch_duplicate_case.yul +++ b/test/libyul/yulSyntaxTests/switch_duplicate_case.yul @@ -1,9 +1,7 @@ { - switch 0:u256 - case 0:u256 {} - case 0x0:u256 {} + switch 0 + case 0 {} + case 0x0 {} } -// ==== -// dialect: evmTyped // ---- -// DeclarationError 6792: (34-50): Duplicate case "0x0" defined. +// DeclarationError 6792: (24-35): Duplicate case "0x0" defined. diff --git a/test/libyul/yulSyntaxTests/switch_duplicate_case_different_literal.yul b/test/libyul/yulSyntaxTests/switch_duplicate_case_different_literal.yul index 91f19efae..e28ca3be0 100644 --- a/test/libyul/yulSyntaxTests/switch_duplicate_case_different_literal.yul +++ b/test/libyul/yulSyntaxTests/switch_duplicate_case_different_literal.yul @@ -1,9 +1,7 @@ { - switch 0:u256 - case 0:u256 {} - case "":u256 {} + switch 0 + case 0 {} + case "" {} } -// ==== -// dialect: evmTyped // ---- -// DeclarationError 6792: (34-49): Duplicate case "" defined. +// DeclarationError 6792: (24-34): Duplicate case "" defined. diff --git a/test/libyul/yulSyntaxTests/token_as_identifier.yul b/test/libyul/yulSyntaxTests/token_as_identifier.yul index 204b76e55..ebb85bdb0 100644 --- a/test/libyul/yulSyntaxTests/token_as_identifier.yul +++ b/test/libyul/yulSyntaxTests/token_as_identifier.yul @@ -1,6 +1,4 @@ { - let bool:u256 := 1:u256 + let bool := 1 } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/tuple_assignment.yul b/test/libyul/yulSyntaxTests/tuple_assignment.yul index 4ac961c26..40c4416f0 100644 --- a/test/libyul/yulSyntaxTests/tuple_assignment.yul +++ b/test/libyul/yulSyntaxTests/tuple_assignment.yul @@ -1,5 +1,5 @@ { - function f() -> a:u256, b:u256, c:u256 {} - let x:u256, y:u256, z:u256 := f() + function f() -> a, b, c {} + let x, y, z := f() } // ---- diff --git a/test/libyul/yulSyntaxTests/type_check_cases_fail_evmtyped.yul b/test/libyul/yulSyntaxTests/type_check_cases_fail_evmtyped.yul deleted file mode 100644 index 35926ccb2..000000000 --- a/test/libyul/yulSyntaxTests/type_check_cases_fail_evmtyped.yul +++ /dev/null @@ -1,10 +0,0 @@ -{ - switch 7 - case true:bool {} - case true:bool {} -} -// ==== -// dialect: evmTyped -// ---- -// TypeError 3781: (24-33): Expected a value of type "u256" but got "bool". -// TypeError 3781: (46-55): Expected a value of type "u256" but got "bool". diff --git a/test/libyul/yulSyntaxTests/user_defined_functions_fail.yul b/test/libyul/yulSyntaxTests/user_defined_functions_fail.yul index 7b8d012bb..dc837eb43 100644 --- a/test/libyul/yulSyntaxTests/user_defined_functions_fail.yul +++ b/test/libyul/yulSyntaxTests/user_defined_functions_fail.yul @@ -1,12 +1,9 @@ { - function f(a:u256, b:u256, c:bool) -> r:bool, t { + function f(a, b, c) -> r, t { r := lt(a, b) - t := bool_to_u256(not(c)) + t := not(c) } - let x, y: bool := f(1, 2: u256, true) + let x, y := f(1, 2, true, false) } -// ==== -// dialect: evmTyped // ---- -// TypeError 3947: (126-127): Assigning value of type "bool" to variable of type "u256". -// TypeError 3947: (129-136): Assigning value of type "u256" to variable of type "bool". +// TypeError 7000: (100-101): Function "f" expects 3 arguments but got 4. diff --git a/test/libyul/yulSyntaxTests/user_defined_functions_fine.yul b/test/libyul/yulSyntaxTests/user_defined_functions_fine.yul index e24ea923e..ce79a9b6e 100644 --- a/test/libyul/yulSyntaxTests/user_defined_functions_fine.yul +++ b/test/libyul/yulSyntaxTests/user_defined_functions_fine.yul @@ -1,10 +1,8 @@ { - function f(a:u256, b:u256, c:bool) -> r:bool, t { + function f(a, b, c) -> r, t { r := lt(a, b) - t := bool_to_u256(not(c)) + t := not(c) } - let x: bool, y: u256 := f(1, 2: u256, true) + let x, y := f(1, 2, true) } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/variable_declaration.yul b/test/libyul/yulSyntaxTests/variable_declaration.yul index 3d7c9d595..2bc22446a 100644 --- a/test/libyul/yulSyntaxTests/variable_declaration.yul +++ b/test/libyul/yulSyntaxTests/variable_declaration.yul @@ -1,4 +1,2 @@ -{ let x:u256 := 7:u256 } -// ==== -// dialect: evmTyped +{ let x := 7 } // ---- diff --git a/test/libyul/yulSyntaxTests/variable_declaration_bool.yul b/test/libyul/yulSyntaxTests/variable_declaration_bool.yul index 3e97d5d4d..e49af9b91 100644 --- a/test/libyul/yulSyntaxTests/variable_declaration_bool.yul +++ b/test/libyul/yulSyntaxTests/variable_declaration_bool.yul @@ -1,7 +1,5 @@ { - let x:bool := true:bool - let y:bool := false:bool + let x := true + let y := false } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/variable_declaration_complex.yul b/test/libyul/yulSyntaxTests/variable_declaration_complex.yul index e7a428fc2..6e07849fc 100644 --- a/test/libyul/yulSyntaxTests/variable_declaration_complex.yul +++ b/test/libyul/yulSyntaxTests/variable_declaration_complex.yul @@ -1,8 +1,6 @@ { - function add_fn(a:u256, b:u256) -> c:u256 {} - let y:u256 := 2:u256 - let x:u256 := add_fn(7:u256, add_fn(6:u256, y)) + function add_fn(a, b) -> c {} + let y := 2 + let x := add_fn(7, add_fn(6, y)) } -// ==== -// dialect: evmTyped // ---- diff --git a/test/libyul/yulSyntaxTests/variable_declaration_empty.yul b/test/libyul/yulSyntaxTests/variable_declaration_empty.yul index afbccb293..df81f297a 100644 --- a/test/libyul/yulSyntaxTests/variable_declaration_empty.yul +++ b/test/libyul/yulSyntaxTests/variable_declaration_empty.yul @@ -1,2 +1,2 @@ -{ let x:u256 } +{ let x } // ---- From 83895d0f7d7c5e40f138826f6ce75ec543d0f322 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:10:23 +0200 Subject: [PATCH 0253/1340] Error codes: Whitelist 1733 and 9547 as they rely on Yul types (which have been removed) --- scripts/error_codes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/error_codes.py b/scripts/error_codes.py index fcb6f0e7f..813d08330 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -205,6 +205,8 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "7053", # Unimplemented feature error (parsing stage), currently has no tests "2339", # SMTChecker, covered by CL tests "6240", # SMTChecker, covered by CL tests + "1733", # AsmAnalysis: expecting bool expression (everything is implicitly bool without types in Yul) + "9547", # AsmAnalysis: assigning incompatible types in Yul (whitelisted as there are currently no types) } assert len(test_ids & white_ids) == 0, "The sets are not supposed to intersect" test_ids |= white_ids From 63d87a28684dda2323dbebd3cd62148ab4a548c2 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Wed, 12 Jun 2024 14:36:31 +0200 Subject: [PATCH 0254/1340] Use submodules for some dependencies. --- .circleci/config.yml | 4 +- .gitmodules | 9 +++++ Changelog.md | 2 + cmake/fmtlib.cmake | 23 +++-------- cmake/nlohmann-json.cmake | 24 +++--------- cmake/range-v3.cmake | 41 ++++---------------- cmake/submodules.cmake | 23 +++++++++++ deps/fmtlib | 1 + deps/nlohmann-json | 1 + deps/range-v3 | 1 + libsolutil/CMakeLists.txt | 2 +- scripts/check_style.sh | 1 + scripts/chk_shellscripts/chk_shellscripts.sh | 2 +- scripts/create_source_tarball.sh | 2 + scripts/install_evmone.ps1 | 3 +- scripts/release_ppa.sh | 7 ---- 16 files changed, 64 insertions(+), 82 deletions(-) create mode 100644 .gitmodules create mode 100644 cmake/submodules.cmake create mode 160000 deps/fmtlib create mode 160000 deps/nlohmann-json create mode 160000 deps/range-v3 diff --git a/.circleci/config.yml b/.circleci/config.yml index 3426db329..343bb6d00 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -866,7 +866,7 @@ jobs: name: Check spelling command: | ~/.local/bin/codespell \ - --skip "*.enc,.git,Dockerfile*,LICENSE,codespell_whitelist.txt,codespell_ignored_lines.txt" \ + --skip "*.enc,.git,Dockerfile*,LICENSE,codespell_whitelist.txt,codespell_ignored_lines.txt,deps" \ --ignore-words scripts/codespell_whitelist.txt \ --exclude-file scripts/codespell_ignored_lines.txt - matrix_notify_failure_unless_pr @@ -1273,7 +1273,7 @@ jobs: - run: name: Install runtime dependencies command: | - pacman --noconfirm -Syu --noprogressbar --needed z3 + pacman --noconfirm -Syu --noprogressbar --needed z3 git - soltest t_ubu_clang_soltest: &t_ubu_clang_soltest diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..47bcbb4fd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "deps/nlohmann-json"] + path = deps/nlohmann-json + url = https://github.com/nlohmann/json.git +[submodule "deps/range-v3"] + path = deps/range-v3 + url = https://github.com/ericniebler/range-v3.git +[submodule "deps/fmtlib"] + path = deps/fmtlib + url = https://github.com/fmtlib/fmt.git diff --git a/Changelog.md b/Changelog.md index 1aebcc05a..2a1249c98 100644 --- a/Changelog.md +++ b/Changelog.md @@ -36,6 +36,8 @@ Bugfixes: * Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. * Yul Parser: Fix segfault when parsing very long location comments. +Build System: + * Change build system to use git submodules for some dependencies (nlohmann-json, fmtlib & range-v3). ### 0.8.26 (2024-05-21) diff --git a/cmake/fmtlib.cmake b/cmake/fmtlib.cmake index 032a68cd5..f9522aaec 100644 --- a/cmake/fmtlib.cmake +++ b/cmake/fmtlib.cmake @@ -1,20 +1,9 @@ -include(FetchContent) +include(${CMAKE_SOURCE_DIR}/cmake/submodules.cmake) +initialize_submodule(fmtlib) -FetchContent_Declare( - fmtlib - PREFIX "${PROJECT_BINARY_DIR}/deps" - DOWNLOAD_DIR "${PROJECT_SOURCE_DIR}/deps/downloads" - DOWNLOAD_NAME fmt-9.1.0.tar.gz - URL https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz - URL_HASH SHA256=5dea48d1fcddc3ec571ce2058e13910a0d4a6bab4cc09a809d8b1dd1c88ae6f2 +set(FMT_SYSTEM_HEADERS ON) +add_subdirectory( + ${CMAKE_SOURCE_DIR}/deps/fmtlib + EXCLUDE_FROM_ALL ) -if (CMAKE_VERSION VERSION_LESS "3.14.0") - FetchContent_GetProperties(fmtlib) - if (NOT fmtlib_POPULATED) - FetchContent_Populate(fmtlib) - add_subdirectory(${fmtlib_SOURCE_DIR} ${fmtlib_BINARY_DIR}) - endif() -else() - FetchContent_MakeAvailable(fmtlib) -endif() diff --git a/cmake/nlohmann-json.cmake b/cmake/nlohmann-json.cmake index 02891e6a7..638fcdd65 100644 --- a/cmake/nlohmann-json.cmake +++ b/cmake/nlohmann-json.cmake @@ -1,21 +1,9 @@ -include(ExternalProject) +include(${CMAKE_SOURCE_DIR}/cmake/submodules.cmake) +initialize_submodule(nlohmann-json) -ExternalProject_Add(nlohmann-json-project - DOWNLOAD_DIR "${CMAKE_SOURCE_DIR}/deps/nlohmann/nlohmann" - DOWNLOAD_NAME json.hpp - DOWNLOAD_NO_EXTRACT 1 - URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.hpp - URL_HASH SHA256=9bea4c8066ef4a1c206b2be5a36302f8926f7fdc6087af5d20b417d0cf103ea6 - CMAKE_COMMAND true - BUILD_COMMAND true - INSTALL_COMMAND true +set(JSON_Install OFF CACHE INTERNAL "") +add_subdirectory( + ${CMAKE_SOURCE_DIR}/deps/nlohmann-json + EXCLUDE_FROM_ALL ) -# Create nlohmann-json imported library -add_library(nlohmann-json INTERFACE IMPORTED) -file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/nlohmann) # Must exist. -set_target_properties(nlohmann-json PROPERTIES - INTERFACE_COMPILE_OPTIONS "\$<\$:/permissive->" - INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/nlohmann - INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/nlohmann) -add_dependencies(nlohmann-json nlohmann-json-project) \ No newline at end of file diff --git a/cmake/range-v3.cmake b/cmake/range-v3.cmake index d2f54452b..eaab3b09e 100644 --- a/cmake/range-v3.cmake +++ b/cmake/range-v3.cmake @@ -1,38 +1,11 @@ -include(ExternalProject) +include(${CMAKE_SOURCE_DIR}/cmake/submodules.cmake) +initialize_submodule(range-v3) -if (${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten") - set(RANGE_V3_CMAKE_COMMAND emcmake cmake) -else() - set(RANGE_V3_CMAKE_COMMAND ${CMAKE_COMMAND}) -endif() - -set(prefix "${PROJECT_BINARY_DIR}/deps") -set(RANGE_V3_INCLUDE_DIR "${prefix}/include") - -ExternalProject_Add(range-v3-project - PREFIX "${prefix}" - DOWNLOAD_DIR "${PROJECT_SOURCE_DIR}/deps/downloads" - DOWNLOAD_NAME range-v3-0.12.0.tar.gz - URL https://github.com/ericniebler/range-v3/archive/0.12.0.tar.gz - URL_HASH SHA256=015adb2300a98edfceaf0725beec3337f542af4915cec4d0b89fa0886f4ba9cb - CMAKE_COMMAND ${RANGE_V3_CMAKE_COMMAND} - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} - -DBUILD_TESTING=OFF - -DRANGES_CXX_STD=${CMAKE_CXX_STANDARD} - -DRANGE_V3_DOCS=OFF - -DRANGE_V3_EXAMPLES=OFF - -DRANGE_V3_TESTS=OFF - -DRANGES_BUILD_CALENDAR_EXAMPLE=OFF - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - BUILD_BYPRODUCTS "${RANGE_V3_INCLUDE_DIR}/range/v3/all.hpp" -) - -# Create range-v3 imported library add_library(range-v3 INTERFACE IMPORTED) -file(MAKE_DIRECTORY ${RANGE_V3_INCLUDE_DIR}) # Must exist. set_target_properties(range-v3 PROPERTIES - INTERFACE_COMPILE_OPTIONS "\$<\$:/permissive->" - INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${RANGE_V3_INCLUDE_DIR} - INTERFACE_INCLUDE_DIRECTORIES ${RANGE_V3_INCLUDE_DIR}) + INTERFACE_COMPILE_OPTIONS "\$<\$:/permissive->" + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/range-v3/include + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/range-v3/include +) add_dependencies(range-v3 range-v3-project) + diff --git a/cmake/submodules.cmake b/cmake/submodules.cmake new file mode 100644 index 000000000..099aceaa9 --- /dev/null +++ b/cmake/submodules.cmake @@ -0,0 +1,23 @@ +macro(initialize_submodule SUBMODULE_PATH) + if(NOT USE_SYSTEM_LIBRARIES) + file(GLOB submodule_contents "${CMAKE_SOURCE_DIR}/deps/${SUBMODULE_PATH}/*") + + if(submodule_contents) + message(STATUS "git submodule '${SUBMODULE_PATH}' seem to be already initialized: nothing to do.") + else() + message(STATUS "git submodule '${SUBMODULE_PATH}' seem not to be initialized: implicitly executing 'git submodule update --init '${CMAKE_SOURCE_DIR}/deps/${SUBMODULE_PATH}'.") + find_package(Git) + if(NOT Git_FOUND) + message(FATAL_ERROR "Failed to initialize submodules: 'git' command not found.") + endif() + execute_process( + COMMAND git submodule update --init ${CMAKE_SOURCE_DIR}/deps/${SUBMODULE_PATH} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE result + ) + if(NOT result EQUAL 0) + message(FATAL_ERROR "Failed to initialize submodules: 'git submodule update --init' failed.") + endif() + endif() + endif() +endmacro() diff --git a/deps/fmtlib b/deps/fmtlib new file mode 160000 index 000000000..a33701196 --- /dev/null +++ b/deps/fmtlib @@ -0,0 +1 @@ +Subproject commit a33701196adfad74917046096bf5a2aa0ab0bb50 diff --git a/deps/nlohmann-json b/deps/nlohmann-json new file mode 160000 index 000000000..9cca280a4 --- /dev/null +++ b/deps/nlohmann-json @@ -0,0 +1 @@ +Subproject commit 9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03 diff --git a/deps/range-v3 b/deps/range-v3 new file mode 160000 index 000000000..a81477931 --- /dev/null +++ b/deps/range-v3 @@ -0,0 +1 @@ +Subproject commit a81477931a8aa2ad025c6bda0609f38e09e4d7ec diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index 291c95c0d..a1e9559ed 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -44,7 +44,7 @@ set(sources ) add_library(solutil ${sources}) -target_link_libraries(solutil PUBLIC Boost::boost Boost::filesystem Boost::system range-v3 fmt::fmt-header-only nlohmann-json) +target_link_libraries(solutil PUBLIC Boost::boost Boost::filesystem Boost::system range-v3 fmt::fmt-header-only nlohmann_json::nlohmann_json) target_include_directories(solutil PUBLIC "${PROJECT_SOURCE_DIR}") add_dependencies(solutil solidity_BuildInfo.h) diff --git a/scripts/check_style.sh b/scripts/check_style.sh index dbe470c1a..d67f7b60c 100755 --- a/scripts/check_style.sh +++ b/scripts/check_style.sh @@ -6,6 +6,7 @@ ERROR_LOG="$(mktemp -t check_style_XXXXXX.log)" EXCLUDE_FILES=( # The line below is left unquoted to allow the shell globbing path expansion + deps/* test/cmdlineTests/*/{err,output} "libsolutil/picosha2.h" "test/cmdlineTests/strict_asm_only_cr/input.yul" diff --git a/scripts/chk_shellscripts/chk_shellscripts.sh b/scripts/chk_shellscripts/chk_shellscripts.sh index f94d9f2da..fff9d2662 100755 --- a/scripts/chk_shellscripts/chk_shellscripts.sh +++ b/scripts/chk_shellscripts/chk_shellscripts.sh @@ -13,5 +13,5 @@ if [ ! -f "${SHELLCHECK}" ]; then exit 1 fi -mapfile -t FILES < <(find . -type f -name "*.sh") +mapfile -t FILES < <(find . -type f -name "*.sh" -not -path "./deps/*") "${SHELLCHECK}" "${FILES[@]}" diff --git a/scripts/create_source_tarball.sh b/scripts/create_source_tarball.sh index 4af1cf586..37bee6df1 100755 --- a/scripts/create_source_tarball.sh +++ b/scripts/create_source_tarball.sh @@ -23,6 +23,8 @@ REPO_ROOT="$(dirname "$0")"/.. mkdir "$SOLDIR" # Store the current source git checkout-index -a --prefix="$SOLDIR" + # shellcheck disable=SC2016 + SOLDIR="$SOLDIR" git submodule foreach 'git checkout-index -a --prefix="$SOLDIR/$sm_path/"' # Store the commit hash echo "$commithash" > "$SOLDIR/commit_hash.txt" if [ -e prerelease.txt ] && [ ! -s prerelease.txt ] diff --git a/scripts/install_evmone.ps1 b/scripts/install_evmone.ps1 index acbacdafb..5864f2491 100644 --- a/scripts/install_evmone.ps1 +++ b/scripts/install_evmone.ps1 @@ -5,5 +5,4 @@ $progressPreference = "silentlyContinue" Invoke-WebRequest -URI "https://github.com/ethereum/evmone/releases/download/v0.11.0/evmone-0.11.0-windows-amd64.zip" -OutFile "evmone.zip" tar -xf evmone.zip "bin/evmone.dll" -mkdir deps -mv bin/evmone.dll deps +mv bin/evmone.dll deps/ diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 0e4eb7ed4..3b7c8347c 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -123,13 +123,6 @@ ppafilesurl=https://launchpad.net/~ethereum/+archive/ubuntu/${pparepo}/+files git clone --depth 2 --recursive https://github.com/ethereum/solidity.git -b "$branch" mv solidity solc -# Fetch dependencies -mkdir -p ./solc/deps/downloads/ 2>/dev/null || true -mkdir -p ./solc/deps/nlohmann/nlohmann/ 2>/dev/null || true -wget -O ./solc/deps/nlohmann/nlohmann/json.hpp https://github.com/nlohmann/json/releases/download/v3.11.3/json.hpp -wget -O ./solc/deps/downloads/range-v3-0.12.0.tar.gz https://github.com/ericniebler/range-v3/archive/0.12.0.tar.gz -wget -O ./solc/deps/downloads/fmt-9.1.0.tar.gz https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz - # Determine version cd solc version=$("$(dirname "$0")/get_version.sh") From 3de3c7bd98b9da2ef48eaecb48ff6543fb1b398e Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 9 Aug 2024 10:36:23 +0200 Subject: [PATCH 0255/1340] Bump evmone to v0.12.0 in CI Bump clang to 15 --- .../Dockerfile.ubuntu.clang.ossfuzz | 16 ++++++---------- .../docker/buildpack-deps/Dockerfile.ubuntu2004 | 6 +++--- .../docker/buildpack-deps/Dockerfile.ubuntu2204 | 16 ++++++---------- .../buildpack-deps/Dockerfile.ubuntu2204.clang | 16 ++++++---------- 4 files changed, 21 insertions(+), 33 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index aae11521e..46137b400 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-clang:latest as base -LABEL version="7" +LABEL version="8" ARG DEBIAN_FRONTEND=noninteractive @@ -140,15 +140,11 @@ RUN set -ex; \ # EVMONE RUN set -ex; \ - cd /usr/src; \ - git clone --branch="v0.11.0" --recurse-submodules https://github.com/ethereum/evmone.git; \ - cd evmone; \ - mkdir build; \ - cd build; \ - CXX=clang++ cmake -G Ninja -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX="/usr" ..; \ - ninja; \ - ninja install/strip; \ - rm -rf /usr/src/evmone + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + cd /usr; \ + tar -xf /usr/src/evmone.tar.gz; \ + rm -rf /usr/src/evmone.tar.gz # gmp RUN set -ex; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index 8b94fe9dd..723192e2d 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:focal AS base -LABEL version="24" +LABEL version="25" ARG DEBIAN_FRONTEND=noninteractive @@ -89,8 +89,8 @@ FROM base AS libraries # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.11.0/evmone-0.11.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "051dbe523da165658ced63619ea2c05925516aac3061951da96d3f0962560719 /usr/src/evmone.tar.gz"; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ rm -rf /usr/src/evmone.tar.gz diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index 90d5811c3..add03bb00 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="9" +LABEL version="10" ARG DEBIAN_FRONTEND=noninteractive @@ -88,15 +88,11 @@ FROM base AS libraries # EVMONE RUN set -ex; \ - cd /usr/src; \ - git clone --branch="v0.11.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 + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + cd /usr; \ + tar -xf /usr/src/evmone.tar.gz; \ + rm -rf /usr/src/evmone.tar.gz FROM base COPY --from=libraries /usr/lib /usr/lib diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang index b2f75b0e4..b9c915838 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="8" +LABEL version="9" ARG DEBIAN_FRONTEND=noninteractive @@ -89,15 +89,11 @@ ENV CXX clang++ # EVMONE RUN set -ex; \ - cd /usr/src; \ - git clone --branch="v0.11.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 + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + cd /usr; \ + tar -xf /usr/src/evmone.tar.gz; \ + rm -rf /usr/src/evmone.tar.gz FROM base COPY --from=libraries /usr/lib /usr/lib From 3d3b78e0a39163ef8449defdfa2b4659ded617e7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 14 Aug 2024 13:35:20 +0200 Subject: [PATCH 0256/1340] Fix UB introduced by casting difference of two unsigneds to signed --- liblangutil/SemVerHandler.cpp | 2 +- libsolidity/codegen/ExpressionCompiler.cpp | 6 +++--- libyul/backends/evm/EVMCodeTransform.cpp | 2 +- libyul/backends/evm/NoOutputAssembly.cpp | 2 +- libyul/backends/evm/OptimizedEVMCodeTransform.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/liblangutil/SemVerHandler.cpp b/liblangutil/SemVerHandler.cpp index 2358eec5e..e1a9556ca 100644 --- a/liblangutil/SemVerHandler.cpp +++ b/liblangutil/SemVerHandler.cpp @@ -115,7 +115,7 @@ bool SemVerMatchExpression::MatchComponent::matches(SemVerVersion const& _versio if (version.numbers[i] != std::numeric_limits::max()) { didCompare = true; - cmp = static_cast(_version.numbers[i] - version.numbers[i]); + cmp = static_cast(_version.numbers[i]) - static_cast(version.numbers[i]); } if (cmp == 0 && !_version.prerelease.empty() && didCompare) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 368ee77a8..95b7435ed 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -436,7 +436,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) unsigned returnParametersSize = CompilerUtils::sizeOnStack(functionType->returnParameterTypes()); // callee adds return parameters, but removes arguments and return label - m_context.adjustStackOffset(static_cast(returnParametersSize - parameterSize) - 1); + m_context.adjustStackOffset(static_cast(returnParametersSize) - static_cast(parameterSize) - 1); return false; } @@ -564,7 +564,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation) unsigned returnParametersSize = CompilerUtils::sizeOnStack(functionType->returnParameterTypes()); // callee adds return parameters, but removes arguments and return label - m_context.adjustStackOffset(static_cast(returnParametersSize - parameterSize) - 1); + m_context.adjustStackOffset(static_cast(returnParametersSize) - static_cast(parameterSize) - 1); return false; } @@ -721,7 +721,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) unsigned returnParametersSize = CompilerUtils::sizeOnStack(function.returnParameterTypes()); // callee adds return parameters, but removes arguments and return label - m_context.adjustStackOffset(static_cast(returnParametersSize - parameterSize) - 1); + m_context.adjustStackOffset(static_cast(returnParametersSize) - static_cast(parameterSize) - 1); break; } case FunctionType::Kind::BareCall: diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 211247230..71872a4e8 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -255,7 +255,7 @@ void CodeTransform::operator()(FunctionCall const& _call) m_assembly.setSourceLocation(originLocationOf(_call)); m_assembly.appendJumpTo( functionEntryID(*function), - static_cast(function->returns.size() - function->arguments.size()) - 1, + static_cast(function->returns.size()) - static_cast(function->arguments.size()) - 1, AbstractAssembly::JumpType::IntoFunction ); m_assembly.appendLabel(returnLabel); diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 2a3cca52c..71818d248 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -71,7 +71,7 @@ void NoOutputAssembly::appendLinkerSymbol(std::string const&) void NoOutputAssembly::appendVerbatim(bytes, size_t _arguments, size_t _returnVariables) { - m_stackHeight += static_cast(_returnVariables - _arguments); + m_stackHeight += static_cast(_returnVariables) - static_cast(_arguments); } void NoOutputAssembly::appendJump(int _stackDiffAfter, JumpType) diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index a6b867aba..99f7114e9 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -92,7 +92,7 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call) m_assembly.setSourceLocation(originLocationOf(_call)); m_assembly.appendJumpTo( getFunctionLabel(_call.function), - static_cast(_call.function.get().returns.size() - _call.function.get().arguments.size()) - (_call.canContinue ? 1 : 0), + static_cast(_call.function.get().returns.size()) - static_cast(_call.function.get().arguments.size()) - (_call.canContinue ? 1 : 0), AbstractAssembly::JumpType::IntoFunction ); if (_call.canContinue) From da1bc0bc446d14ae48aca618d878ec3ff6a9d3a3 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 14 Aug 2024 19:53:09 +0200 Subject: [PATCH 0257/1340] SMTChecker: Add setup of z3 to SMTSolverCommand This prepares SMTSolverCommand for invocation of Z3 as an external solver. Command line arguments enusure we match the way we set Z3 in our current code. --- libsolidity/interface/SMTSolverCommand.cpp | 29 ++++++++++++++++++++++ libsolidity/interface/SMTSolverCommand.h | 1 + 2 files changed, 30 insertions(+) diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index 8120e1f11..66adfd0c5 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -57,6 +57,35 @@ void SMTSolverCommand::setCvc5(std::optional timeoutInMilliseconds } } +void SMTSolverCommand::setZ3(std::optional timeoutInMilliseconds, bool _preprocessing, bool _computeInvariants) +{ + constexpr int Z3ResourceLimit = 2000000; + m_arguments.clear(); + m_solverCmd = "z3"; + m_arguments.emplace_back("-in"); // Read from standard input + m_arguments.emplace_back("-smt2"); // Expect input in SMT-LIB2 format + if (_computeInvariants) + m_arguments.emplace_back("-model"); // Output model automatically after check-sat + if (timeoutInMilliseconds) + m_arguments.emplace_back("-t:" + std::to_string(timeoutInMilliseconds.value())); + else + m_arguments.emplace_back("rlimit=" + std::to_string(Z3ResourceLimit)); + + // These options have been empirically established to be helpful + m_arguments.emplace_back("rewriter.pull_cheap_ite=true"); + m_arguments.emplace_back("fp.spacer.q3.use_qgen=true"); + m_arguments.emplace_back("fp.spacer.mbqi=false"); + m_arguments.emplace_back("fp.spacer.ground_pobs=false"); + + // Spacer optimization should be + // - enabled for better solving (default) + // - disable for counterexample generation + std::string preprocessingArg = _preprocessing ? "true" : "false"; + m_arguments.emplace_back("fp.xform.slice=" + preprocessingArg); + m_arguments.emplace_back("fp.xform.inline_linear=" + preprocessingArg); + m_arguments.emplace_back("fp.xform.inline_eager=" + preprocessingArg); +} + ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::string const& _query) const { try diff --git a/libsolidity/interface/SMTSolverCommand.h b/libsolidity/interface/SMTSolverCommand.h index c948ec5d2..13d79fe59 100644 --- a/libsolidity/interface/SMTSolverCommand.h +++ b/libsolidity/interface/SMTSolverCommand.h @@ -38,6 +38,7 @@ class SMTSolverCommand void setEldarica(std::optional timeoutInMilliseconds, bool computeInvariants); void setCvc5(std::optional timeoutInMilliseconds); + void setZ3(std::optional timeoutInMilliseconds, bool _preprocessing, bool _computeInvariants); private: /// The name of the solver's binary. From 363274df8e113aec83f0b56c8bd612efda97ddb1 Mon Sep 17 00:00:00 2001 From: ljmanini <58728166+lmanini@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:26:19 +0200 Subject: [PATCH 0258/1340] Update ContractCompiler.cpp Error msg fix --- libsolidity/codegen/ContractCompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 9e0593cdf..66cfe35c4 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -1396,7 +1396,7 @@ bool ContractCompiler::visit(PlaceholderStatement const& _placeholderStatement) { StackHeightChecker checker(m_context); CompilerContext::LocationSetter locationSetter(m_context, _placeholderStatement); - solAssert(m_context.arithmetic() == Arithmetic::Checked, "Placeholder cannot be used inside checked block."); + solAssert(m_context.arithmetic() == Arithmetic::Checked, "Placeholder cannot be used inside unchecked block."); appendModifierOrFunctionCode(); solAssert(m_context.arithmetic() == Arithmetic::Checked, "Arithmetic not reset to 'checked'."); checker.check(); From fa781b7c4a226340410ddc5a235fd7db7a22fd80 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 13 Aug 2024 13:44:04 +0200 Subject: [PATCH 0259/1340] Remove cmake dependency and bump boost in ossfuzz --- .../Dockerfile.ubuntu.clang.ossfuzz | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index 46137b400..aae11521e 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-clang:latest as base -LABEL version="8" +LABEL version="7" ARG DEBIAN_FRONTEND=noninteractive @@ -140,11 +140,15 @@ RUN set -ex; \ # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ - cd /usr; \ - tar -xf /usr/src/evmone.tar.gz; \ - rm -rf /usr/src/evmone.tar.gz + cd /usr/src; \ + git clone --branch="v0.11.0" --recurse-submodules https://github.com/ethereum/evmone.git; \ + cd evmone; \ + mkdir build; \ + cd build; \ + CXX=clang++ cmake -G Ninja -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX="/usr" ..; \ + ninja; \ + ninja install/strip; \ + rm -rf /usr/src/evmone # gmp RUN set -ex; \ From 1c21f8311a742d47c7621de0c395c441136ac63c Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 14 Aug 2024 11:34:28 +0200 Subject: [PATCH 0260/1340] Add ubuntu2404 docker image --- .github/workflows/buildpack-deps.yml | 3 +- scripts/ci/buildpack-deps_test_ubuntu2404.sh | 1 + .../buildpack-deps/Dockerfile.ubuntu2404 | 106 ++++++++++++++++++ 3 files changed, 109 insertions(+), 1 deletion(-) create mode 120000 scripts/ci/buildpack-deps_test_ubuntu2404.sh create mode 100644 scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index 2cd6e5048..5f66487e0 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -9,6 +9,7 @@ on: - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2004' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2204' + - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404' jobs: buildpack-deps: @@ -23,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2204.clang, ubuntu2204] + image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2204.clang, ubuntu2204, ubuntu2404] steps: - uses: actions/checkout@v4 diff --git a/scripts/ci/buildpack-deps_test_ubuntu2404.sh b/scripts/ci/buildpack-deps_test_ubuntu2404.sh new file mode 120000 index 000000000..c07a74de4 --- /dev/null +++ b/scripts/ci/buildpack-deps_test_ubuntu2404.sh @@ -0,0 +1 @@ +build.sh \ No newline at end of file diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 new file mode 100644 index 000000000..c7ad4594a --- /dev/null +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 @@ -0,0 +1,106 @@ +# vim:syntax=dockerfile +#------------------------------------------------------------------------------ +# Dockerfile for building and testing Solidity Compiler on CI +# Target: Ubuntu 19.04 (Disco Dingo) +# 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 +# +# (c) 2016-2024 solidity contributors. +#------------------------------------------------------------------------------ +FROM buildpack-deps:noble AS base +LABEL version="1" + +ARG DEBIAN_FRONTEND=noninteractive + +# From Python3.11, pip requires a virtual environment, and will thus terminate when installing packages globally. +# Since we're building this image from scratch, it's perfectly fine to use the below flag. +ENV PIP_BREAK_SYSTEM_PACKAGES 1 + +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 \ + cmake \ + jq \ + libboost-filesystem-dev \ + libboost-program-options-dev \ + libboost-system-dev \ + libboost-test-dev \ + libcln-dev \ + libz3-static-dev \ + locales-all \ + lsof \ + ninja-build \ + python3-pip \ + python3-sphinx \ + software-properties-common \ + sudo \ + unzip \ + z3-static \ + zip; \ + pip3 install \ + codecov \ + colorama \ + deepdiff \ + parsec \ + pygments-lexer-solidity \ + pylint \ + requests \ + tabulate \ + z3-solver; + +# Eldarica +RUN set -ex; \ + apt-get update; \ + apt-get install -qqy \ + openjdk-11-jre; \ + eldarica_version="2.1"; \ + wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ + test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ + unzip /opt/eld_binaries.zip -d /opt; \ + rm -f /opt/eld_binaries.zip; + +# CVC5 +RUN set -ex; \ + cvc5_version="1.1.2"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ + unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ + mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ + mv /opt/cvc5-Linux-static/include/* /usr/include; \ + mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ + rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + +FROM base AS libraries + +# EVMONE +RUN set -ex; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + cd /usr; \ + tar -xf /usr/src/evmone.tar.gz; \ + rm -rf /usr/src/evmone.tar.gz + +FROM base +COPY --from=libraries /usr/lib /usr/lib +COPY --from=libraries /usr/bin /usr/bin +COPY --from=libraries /usr/include /usr/include +COPY --from=libraries /opt/eldarica /opt/eldarica +ENV PATH="$PATH:/opt/eldarica" From b9b1d08eedf2716b3237d239c4e99715e668cd11 Mon Sep 17 00:00:00 2001 From: Zuri Obozuwa Date: Wed, 3 Apr 2024 19:36:40 +0000 Subject: [PATCH 0261/1340] Pass vector of SMT expressions to SymbolicFunctionVariable function operator by const ref instead of by value To avoid the cost of copying the vector --- libsolidity/formal/SymbolicVariables.cpp | 2 +- libsolidity/formal/SymbolicVariables.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/formal/SymbolicVariables.cpp b/libsolidity/formal/SymbolicVariables.cpp index 6d6dbee65..f0cebc46c 100644 --- a/libsolidity/formal/SymbolicVariables.cpp +++ b/libsolidity/formal/SymbolicVariables.cpp @@ -203,7 +203,7 @@ smtutil::Expression SymbolicFunctionVariable::increaseIndex() return m_abstract.currentValue(); } -smtutil::Expression SymbolicFunctionVariable::operator()(std::vector _arguments) const +smtutil::Expression SymbolicFunctionVariable::operator()(std::vector const& _arguments) const { return m_declaration(_arguments); } diff --git a/libsolidity/formal/SymbolicVariables.h b/libsolidity/formal/SymbolicVariables.h index 9fd37fe2a..7dbe41d94 100644 --- a/libsolidity/formal/SymbolicVariables.h +++ b/libsolidity/formal/SymbolicVariables.h @@ -62,7 +62,7 @@ class SymbolicVariable virtual smtutil::Expression resetIndex(); virtual smtutil::Expression setIndex(unsigned _index); virtual smtutil::Expression increaseIndex(); - virtual smtutil::Expression operator()(std::vector /*_arguments*/) const + virtual smtutil::Expression operator()(std::vector const& /*_arguments*/) const { solAssert(false, "Function application to non-function."); } @@ -177,7 +177,7 @@ class SymbolicFunctionVariable: public SymbolicVariable smtutil::Expression setIndex(unsigned _index) override; smtutil::Expression increaseIndex() override; - smtutil::Expression operator()(std::vector _arguments) const override; + smtutil::Expression operator()(std::vector const& _arguments) const override; private: /// Creates a new function declaration. From a197cbe3ee6271479382ed6cd77aff024592006d Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Sun, 18 Aug 2024 22:16:47 +0200 Subject: [PATCH 0262/1340] Add back CLion build directories to .gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index aafe93f97..a9430fd98 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ __pycache__/ *.app # Build directory +/cmake-build-*/ /build*/ emscripten_build/ /docs/_build/ From b172de55e9de0f5058fec7e27e8e41c1e57d2174 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 15 Aug 2024 15:29:45 +0200 Subject: [PATCH 0263/1340] SMTChecker: Inline let expressions in solvers' models Models computed by CHC solvers (especially Z3) can contain SMT-LIB's let expressions. These are used to name a subterm and use the name instead of repeating the subterm possibly many times. The easiest (but not necessary the best) way to deal with let terms is to inline (expand) them. In our current experiments inlining did not pose any problem. If, in the future, this would turn out to cause problems, we can devise a way to process let terms without expanding the term to its full tree-like representation. This is part of the preparation to use Z3 as an external solver. It allows us to properly process models returned by Z3. --- libsmtutil/CHCSmtLib2Interface.cpp | 125 ++++++++++++++++++++++++++++- libsmtutil/CHCSmtLib2Interface.h | 3 + 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index 8b795b9d5..e17370562 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -407,7 +407,7 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp precondition(!isAtom(args[2])); precondition(isAtom(args[3]) && asAtom(args[3]) == "Bool"); auto& interpretation = args[4]; -// inlineLetExpressions(interpretation); + inlineLetExpressions(interpretation); ScopedParser scopedParser(m_context); auto const& formalArguments = asSubExpressions(args[2]); std::vector predicateArgs; @@ -432,3 +432,126 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp return Expression::mkAnd(std::move(definitions)); } #undef precondition + +namespace +{ + +struct LetBindings +{ + using BindingRecord = std::vector; + std::unordered_map bindings; + std::vector varNames; + std::vector scopeBounds; + + bool has(std::string const& varName) { return bindings.find(varName) != bindings.end(); } + + SMTLib2Expression& operator[](std::string const& varName) + { + auto it = bindings.find(varName); + smtAssert(it != bindings.end()); + smtAssert(!it->second.empty()); + return it->second.back(); + } + + void pushScope() { scopeBounds.push_back(varNames.size()); } + + void popScope() + { + smtAssert(!scopeBounds.empty()); + auto bound = scopeBounds.back(); + while (varNames.size() > bound) + { + auto const& varName = varNames.back(); + auto it = bindings.find(varName); + smtAssert(it != bindings.end()); + auto& record = it->second; + record.pop_back(); + if (record.empty()) + bindings.erase(it); + varNames.pop_back(); + } + scopeBounds.pop_back(); + } + + void addBinding(std::string name, SMTLib2Expression expression) + { + auto it = bindings.find(name); + if (it == bindings.end()) + bindings.insert({name, {std::move(expression)}}); + else + it->second.push_back(std::move(expression)); + varNames.push_back(std::move(name)); + } +}; + +void inlineLetExpressions(SMTLib2Expression& _expr, LetBindings& _bindings) +{ + if (isAtom(_expr)) + { + auto const& atom = asAtom(_expr); + if (_bindings.has(atom)) + _expr = _bindings[atom]; + return; + } + auto& subexprs = asSubExpressions(_expr); + smtAssert(!subexprs.empty()); + auto const& first = subexprs.at(0); + if (isAtom(first) && asAtom(first) == "let") + { + smtAssert(subexprs.size() == 3); + smtAssert(!isAtom(subexprs[1])); + auto& bindingExpressions = asSubExpressions(subexprs[1]); + // process new bindings + std::vector> newBindings; + for (auto& binding: bindingExpressions) + { + smtAssert(!isAtom(binding)); + auto& bindingPair = asSubExpressions(binding); + smtAssert(bindingPair.size() == 2); + smtAssert(isAtom(bindingPair.at(0))); + inlineLetExpressions(bindingPair.at(1), _bindings); + newBindings.emplace_back(asAtom(bindingPair.at(0)), bindingPair.at(1)); + } + _bindings.pushScope(); + for (auto&& [name, expr]: newBindings) + _bindings.addBinding(std::move(name), std::move(expr)); + + newBindings.clear(); + + // get new subexpression + inlineLetExpressions(subexprs.at(2), _bindings); + // remove the new bindings + _bindings.popScope(); + + // update the expression + auto tmp = std::move(subexprs.at(2)); + _expr = std::move(tmp); + return; + } + else if (isAtom(first) && (asAtom(first) == "forall" || asAtom(first) == "exists")) + { + // A little hack to ensure quantified variables are not substituted because of some outer let definition: + // We define the current binding of the variable to itself, before we recurse in to subterm + smtAssert(subexprs.size() == 3); + _bindings.pushScope(); + for (auto const& sortedVar: asSubExpressions(subexprs.at(1))) + { + auto const& varNameExpr = asSubExpressions(sortedVar).at(0); + _bindings.addBinding(asAtom(varNameExpr), varNameExpr); + } + inlineLetExpressions(subexprs.at(2), _bindings); + _bindings.popScope(); + return; + } + + // not a let expression, just process all arguments recursively + for (auto& subexpr: subexprs) + inlineLetExpressions(subexpr, _bindings); +} +} + +void CHCSmtLib2Interface::inlineLetExpressions(SMTLib2Expression& expr) +{ + LetBindings bindings; + ::inlineLetExpressions(expr, bindings); +} diff --git a/libsmtutil/CHCSmtLib2Interface.h b/libsmtutil/CHCSmtLib2Interface.h index 0b81b4541..b5baba7d6 100644 --- a/libsmtutil/CHCSmtLib2Interface.h +++ b/libsmtutil/CHCSmtLib2Interface.h @@ -80,6 +80,9 @@ class CHCSmtLib2Interface: public CHCSolverInterface std::unordered_map m_localVariables; }; + /* Modifies the passed expression by inlining all let subexpressions */ + static void inlineLetExpressions(SMTLib2Expression& _expr); + std::string toSmtLibSort(SortPointer const& _sort); std::vector toSmtLibSort(std::vector const& _sort); From 3b532e468633e61e6d2660f6c07845dbbe78f31d Mon Sep 17 00:00:00 2001 From: Howe <69898694+DestinyWei@users.noreply.github.com> Date: Sun, 22 Oct 2023 22:03:45 +0800 Subject: [PATCH 0264/1340] docs: add the onlyBuyer modifier in function confirmPurchase() in the function confirmPurchase(), the annotation said 'Confirm the purchase as buyer.' but it doesn't add the `onlyBuyer` modifier --- docs/examples/safe-remote.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/examples/safe-remote.rst b/docs/examples/safe-remote.rst index a2651af23..065aabdd9 100644 --- a/docs/examples/safe-remote.rst +++ b/docs/examples/safe-remote.rst @@ -106,6 +106,7 @@ you can use state machine-like constructs inside a contract. /// is called. function confirmPurchase() external + onlyBuyer inState(State.Created) condition(msg.value == (2 * value)) payable From 91076d648de7829aa236670ac9a58aac47bb9ee8 Mon Sep 17 00:00:00 2001 From: Vishwa Mehta Date: Mon, 19 Aug 2024 18:13:55 +0530 Subject: [PATCH 0265/1340] Update safe-remote.rst Reverts the docs PR #14632. (see: https://github.com/ethereum/solidity/pull/14632#discussion_r1721715090) --- docs/examples/safe-remote.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/examples/safe-remote.rst b/docs/examples/safe-remote.rst index 065aabdd9..a2651af23 100644 --- a/docs/examples/safe-remote.rst +++ b/docs/examples/safe-remote.rst @@ -106,7 +106,6 @@ you can use state machine-like constructs inside a contract. /// is called. function confirmPurchase() external - onlyBuyer inState(State.Created) condition(msg.value == (2 * value)) payable From 020bde963a1b9e4d05d8e89df50e7216729e4b81 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Sat, 20 Jul 2024 10:23:01 +0200 Subject: [PATCH 0266/1340] SMTChecker: Translate bitvector constants properly Bit-vector constants in solvers' output can be represented in binary (starting with #b) or hexadecimal format (starting with #x). Handling of these constants were previously missing in our translation from SMT-LIB expressions. --- libsmtutil/CHCSmtLib2Interface.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index e17370562..6db1c6e87 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -200,6 +200,24 @@ bool isNumber(std::string const& _expr) { return ranges::all_of(_expr, [](char c) { return isDigit(c) || c == '.'; }); } + +bool isBitVectorHexConstant(std::string const& _string) +{ + if (_string.substr(0, 2) != "#x") + return false; + if (_string.find_first_not_of("0123456789abcdefABCDEF", 2) != std::string::npos) + return false; + return true; +} + +bool isBitVectorConstant(std::string const& _string) +{ + if (_string.substr(0, 2) != "#b") + return false; + if (_string.find_first_not_of("01", 2) != std::string::npos) + return false; + return true; +} } void CHCSmtLib2Interface::ScopedParser::addVariableDeclaration(std::string _name, solidity::smtutil::SortPointer _sort) @@ -279,6 +297,10 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi return smtutil::Expression(_atom == "true"); else if (isNumber(_atom)) return smtutil::Expression(_atom, {}, SortProvider::sintSort); + else if (isBitVectorHexConstant(_atom)) + return smtutil::Expression(_atom, {}, std::make_shared((_atom.size() - 2) * 4)); + else if (isBitVectorConstant(_atom)) + return smtutil::Expression(_atom, {}, std::make_shared(_atom.size() - 2)); else if (auto it = m_localVariables.find(_atom); it != m_localVariables.end()) return smtutil::Expression(_atom, {}, it->second); else if (m_context.isDeclared(_atom)) From 06d2bdeb54a6205e7904471dbcd4d9299d2e403e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 22 Jul 2024 13:32:24 +0200 Subject: [PATCH 0267/1340] Object compiler tests for nested identical objects --- ...identical_subobjects_creation_deployed.yul | 107 +++++++++++ .../identical_subobjects_full_debug_info.yul | 114 ++++++++++++ .../identical_subobjects_no_debug_info.yul | 163 +++++++++++++++++ ...dentical_subobjects_partial_debug_info.yul | 151 ++++++++++++++++ ...bobjects_partial_debug_info_no_use_src.yul | 169 ++++++++++++++++++ ...cal_subobjects_with_subject_references.yul | 166 +++++++++++++++++ 6 files changed, 870 insertions(+) create mode 100644 test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul create mode 100644 test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul create mode 100644 test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul create mode 100644 test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul create mode 100644 test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul create mode 100644 test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul diff --git a/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul b/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul new file mode 100644 index 000000000..5eb079db1 --- /dev/null +++ b/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul @@ -0,0 +1,107 @@ +// All objects have identical unoptimized code, but at 200 runs the creation objects will optimized +// differently from deployed objects. + +/// @use-src 0:"A.sol" +object "A" { + code { + function load(i) -> r { r := calldataload(i) } + let x := add(shl(255, 1), shl(127, not(0))) + sstore(load(x), load(1)) + } + + /// @use-src 0:"B.sol" + object "B_deployed" { + code { + function load(i) -> r { r := calldataload(i) } + let x := add(shl(255, 1), shl(127, not(0))) + sstore(load(x), load(1)) + } + + /// @use-src 0:"A.sol" + object "A" { + code { + function load(i) -> r { r := calldataload(i) } + let x := add(shl(255, 1), shl(127, not(0))) + sstore(load(x), load(1)) + } + + /// @use-src 0:"B.sol" + object "B_deployed" { + code { + function load(i) -> r { r := calldataload(i) } + let x := add(shl(255, 1), shl(127, not(0))) + sstore(load(x), load(1)) + } + } + + /// @use-src 0:"C.sol" + object "C" { + code { + function load(i) -> r { r := calldataload(i) } + let x := add(shl(255, 1), shl(127, not(0))) + sstore(load(x), load(1)) + } + } + } + } + + /// @use-src 0:"C.sol" + object "C_deployed" { + code { + function load(i) -> r { r := calldataload(i) } + let x := add(shl(255, 1), shl(127, not(0))) + sstore(load(x), load(1)) + } + } + + /// @use-src 0:"D.sol" + object "D" { + code { + function load(i) -> r { r := calldataload(i) } + let x := add(shl(255, 1), shl(127, not(0))) + sstore(load(x), load(1)) + } + } +} +// ==== +// optimizationPreset: full +// ---- +// Assembly: +// sstore(calldataload(sub(shl(0xff, 0x01), shl(0x7f, 0x01))), calldataload(0x01)) +// stop +// stop +// +// sub_0: assembly { +// sstore(calldataload(shl(0x7f, 0xffffffffffffffffffffffffffffffff)), calldataload(0x01)) +// stop +// stop +// +// sub_0: assembly { +// sstore(calldataload(sub(shl(0xff, 0x01), shl(0x7f, 0x01))), calldataload(0x01)) +// stop +// stop +// +// sub_0: assembly { +// sstore(calldataload(shl(0x7f, 0xffffffffffffffffffffffffffffffff)), calldataload(0x01)) +// stop +// } +// +// sub_1: assembly { +// sstore(calldataload(sub(shl(0xff, 0x01), shl(0x7f, 0x01))), calldataload(0x01)) +// stop +// } +// } +// } +// +// sub_1: assembly { +// sstore(calldataload(shl(0x7f, 0xffffffffffffffffffffffffffffffff)), calldataload(0x01)) +// stop +// } +// +// sub_2: assembly { +// sstore(calldataload(sub(shl(0xff, 0x01), shl(0x7f, 0x01))), calldataload(0x01)) +// stop +// } +// Bytecode: 6001356001607f1b600160ff1b03355500fe +// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH1 0x1 PUSH1 0x7F SHL PUSH1 0x1 PUSH1 0xFF SHL SUB CALLDATALOAD SSTORE STOP INVALID +// SourceMappings: :::-:0;;;;;;;;;;; diff --git a/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul new file mode 100644 index 000000000..74574be13 --- /dev/null +++ b/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul @@ -0,0 +1,114 @@ +// All objects have identical unoptimized code, but with different debug annotations. +// The optimized Yul will be identical only between objects that have identical debug info. + +/// @use-src 0:"A.sol" +object "A" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + + /// @use-src 0:"B.sol" + object "B" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + + /// @use-src 0:"A.sol" + object "A" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + + /// @use-src 0:"B.sol" + object "B" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + } + + /// @use-src 0:"C.sol" + object "C" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + } + } + } + + /// @use-src 0:"C.sol" + object "C" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + } + + /// @use-src 0:"D.sol" + object "D" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + } +} +// ==== +// optimizationPreset: full +// ---- +// Assembly: +// /* "A.sol":10:20 */ +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// stop +// +// sub_0: assembly { +// /* "B.sol":10:20 */ +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// stop +// +// sub_0: assembly { +// /* "A.sol":10:20 */ +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// stop +// +// sub_0: assembly { +// /* "B.sol":10:20 */ +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// } +// +// sub_1: assembly { +// /* "C.sol":10:20 */ +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// } +// } +// } +// +// sub_1: assembly { +// /* "C.sol":10:20 */ +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// } +// +// sub_2: assembly { +// /* "D.sol":10:20 */ +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// } +// Bytecode: 6001355f355500fe +// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID +// SourceMappings: 10:10::-:0;-1:-1;10:10;-1:-1;10:10;-1:-1 diff --git a/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul new file mode 100644 index 000000000..aa20ac679 --- /dev/null +++ b/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul @@ -0,0 +1,163 @@ +// All objects have identical unoptimized code. +// After optimizations we should end up with identical code for all of them. + +object "A" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + + object "B" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + + object "A" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + + object "B" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + } + + object "C" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + } + } + } + + object "C" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + } + + object "D" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + } +} +// ==== +// optimizationPreset: full +// ---- +// Assembly: +// /* "source":83:84 */ +// 0x01 +// /* "source":70:85 */ +// calldataload +// /* "source":66:67 */ +// 0x00 +// /* "source":53:68 */ +// calldataload +// /* "source":46:86 */ +// sstore +// /* "source":22:102 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":202:203 */ +// 0x01 +// /* "source":189:204 */ +// calldataload +// /* "source":185:186 */ +// 0x00 +// /* "source":172:187 */ +// calldataload +// /* "source":165:205 */ +// sstore +// /* "source":133:229 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":345:346 */ +// 0x01 +// /* "source":332:347 */ +// calldataload +// /* "source":328:329 */ +// 0x00 +// /* "source":315:330 */ +// calldataload +// /* "source":308:348 */ +// sstore +// /* "source":268:380 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":512:513 */ +// 0x01 +// /* "source":499:514 */ +// calldataload +// /* "source":495:496 */ +// 0x00 +// /* "source":482:497 */ +// calldataload +// /* "source":475:515 */ +// sstore +// /* "source":427:555 */ +// stop +// } +// +// sub_1: assembly { +// /* "source":701:702 */ +// 0x01 +// /* "source":688:703 */ +// calldataload +// /* "source":684:685 */ +// 0x00 +// /* "source":671:686 */ +// calldataload +// /* "source":664:704 */ +// sstore +// /* "source":616:744 */ +// stop +// } +// } +// } +// +// sub_1: assembly { +// /* "source":874:875 */ +// 0x01 +// /* "source":861:876 */ +// calldataload +// /* "source":857:858 */ +// 0x00 +// /* "source":844:859 */ +// calldataload +// /* "source":837:877 */ +// sstore +// /* "source":805:901 */ +// stop +// } +// +// sub_2: assembly { +// /* "source":1007:1008 */ +// 0x01 +// /* "source":994:1009 */ +// calldataload +// /* "source":990:991 */ +// 0x00 +// /* "source":977:992 */ +// calldataload +// /* "source":970:1010 */ +// sstore +// /* "source":938:1034 */ +// stop +// } +// Bytecode: 6001355f355500fe +// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID +// SourceMappings: 83:1:0:-:0;70:15;66:1;53:15;46:40;22:80 diff --git a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul new file mode 100644 index 000000000..9b63bdc1b --- /dev/null +++ b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul @@ -0,0 +1,151 @@ +// All objects have identical unoptimized code, but don't necessarily contain the same location comments. +// The optimized Yul will be identical only between objects that have identical debug info. +// Note that when @use-src is missing, the parser ignores location comments, so they do not become +// a part of the debug info. + +/// @use-src 0:"A.sol" +object "A" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + + /// @use-src 0:"B.sol" + object "B" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + + object "A" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + + object "B" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + } + + /// @use-src 0:"C.sol" + object "C" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + } + } + } + + /// @use-src 0:"C.sol" + object "C" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + } + + /// @use-src 0:"C.sol" + object "D" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + } + + object "E" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + } +} +// ==== +// optimizationPreset: full +// ---- +// Assembly: +// /* "A.sol":10:20 */ +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// stop +// +// sub_0: assembly { +// /* "B.sol":10:20 */ +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// stop +// +// sub_0: assembly { +// /* "source":621:622 */ +// 0x01 +// /* "source":608:623 */ +// calldataload +// /* "source":604:605 */ +// 0x00 +// /* "source":591:606 */ +// calldataload +// /* "source":584:624 */ +// sstore +// /* "source":544:656 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":788:789 */ +// 0x01 +// /* "source":775:790 */ +// calldataload +// /* "source":771:772 */ +// 0x00 +// /* "source":758:773 */ +// calldataload +// /* "source":751:791 */ +// sstore +// /* "source":703:831 */ +// stop +// } +// +// sub_1: assembly { +// /* "C.sol":10:20 */ +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// } +// } +// } +// +// sub_1: assembly { +// /* "C.sol":10:20 */ +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// } +// +// sub_2: assembly { +// sstore(calldataload(0x00), calldataload(0x01)) +// stop +// } +// +// sub_3: assembly { +// /* "source":1743:1744 */ +// 0x01 +// /* "source":1730:1745 */ +// calldataload +// /* "source":1726:1727 */ +// 0x00 +// /* "source":1713:1728 */ +// calldataload +// /* "source":1706:1746 */ +// sstore +// /* "source":1674:1770 */ +// stop +// } +// Bytecode: 6001355f355500fe +// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID +// SourceMappings: 10:10::-:0;-1:-1;10:10;-1:-1;10:10;-1:-1 diff --git a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul new file mode 100644 index 000000000..d288503ba --- /dev/null +++ b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul @@ -0,0 +1,169 @@ +// All objects have identical unoptimized code, but don't necessarily contain the same location comments. +// After optimizations we should end up with identical code for all of them, because location +// comments will be ignored due to missing @use-src annotations and won't end up in the AST. + +object "A" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + + object "B" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + + object "A" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + + object "B" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(1)) + } + } + + object "C" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + } + } + } + + object "C" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + } + + object "D" { + code { + function load(i) -> r { r := calldataload(i) } + /// @src 0:10:20 + sstore(load(0), load(1)) + } + } +} +// ==== +// optimizationPreset: full +// ---- +// Assembly: +// /* "source":83:84 */ +// 0x01 +// /* "source":70:85 */ +// calldataload +// /* "source":66:67 */ +// 0x00 +// /* "source":53:68 */ +// calldataload +// /* "source":46:86 */ +// sstore +// /* "source":22:102 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":202:203 */ +// 0x01 +// /* "source":189:204 */ +// calldataload +// /* "source":185:186 */ +// 0x00 +// /* "source":172:187 */ +// calldataload +// /* "source":165:205 */ +// sstore +// /* "source":133:229 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":345:346 */ +// 0x01 +// /* "source":332:347 */ +// calldataload +// /* "source":328:329 */ +// 0x00 +// /* "source":315:330 */ +// calldataload +// /* "source":308:348 */ +// sstore +// /* "source":268:380 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":512:513 */ +// 0x01 +// /* "source":499:514 */ +// calldataload +// /* "source":495:496 */ +// 0x00 +// /* "source":482:497 */ +// calldataload +// /* "source":475:515 */ +// sstore +// /* "source":427:555 */ +// stop +// } +// +// sub_1: assembly { +// /* "source":701:702 */ +// 0x01 +// /* "source":688:703 */ +// calldataload +// /* "source":684:685 */ +// 0x00 +// /* "source":671:686 */ +// calldataload +// /* "source":664:704 */ +// sstore +// /* "source":616:744 */ +// stop +// } +// } +// } +// +// sub_1: assembly { +// /* "source":874:875 */ +// 0x01 +// /* "source":861:876 */ +// calldataload +// /* "source":857:858 */ +// 0x00 +// /* "source":844:859 */ +// calldataload +// /* "source":837:877 */ +// sstore +// /* "source":805:901 */ +// stop +// } +// +// sub_2: assembly { +// /* "source":1007:1008 */ +// 0x01 +// /* "source":994:1009 */ +// calldataload +// /* "source":990:991 */ +// 0x00 +// /* "source":977:992 */ +// calldataload +// /* "source":970:1010 */ +// sstore +// /* "source":938:1034 */ +// stop +// } +// Bytecode: 6001355f355500fe +// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID +// SourceMappings: 83:1:0:-:0;70:15;66:1;53:15;46:40;22:80 diff --git a/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul b/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul new file mode 100644 index 000000000..e14b01008 --- /dev/null +++ b/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul @@ -0,0 +1,166 @@ +// All objects have unoptimized code that's identical except for subobject and data object naming. +// The optimized Yul code does not depend on the content of subobjects and data objects, +// only on their names. EVM assembly, on the other hand, is not affected by names - it uses indices +// for subobjects and hashes for data objects. + +/// @use-src 0:"A.sol" +object "A" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(dataoffset("B"))) + } + + /// @use-src 0:"B.sol" + object "B" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(dataoffset("A"))) + } + + /// @use-src 0:"A.sol" + object "A" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(dataoffset("B"))) + } + + /// @use-src 0:"B.sol" + object "B" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(dataoffset("A"))) + } + + /// @use-src 0:"A.sol" + object "A" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(dataoffset("B"))) + } + + data "B" "0xbb" + } + } + + /// @use-src 0:"C.sol" + object "C" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(dataoffset("A"))) + } + + data "A" "0xaa" + } + + /// @use-src 0:"D.sol" + object "D" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(dataoffset("A"))) + } + + data "A" "0xaaaaaa" + } + } + } + + /// @use-src 0:"C.sol" + object "C" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(dataoffset("A"))) + } + + data "A" "0xaaaa" + } + + /// @use-src 0:"D.sol" + object "D" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(dataoffset("B"))) + } + + data "B" "0xbbbb" + } + + /// @use-src 0:"E.sol" + object "E" { + code { + function load(i) -> r { r := calldataload(i) } + sstore(load(0), load(dataoffset("B"))) + } + + data "B" "0xbbbb" + } +} +// ==== +// optimizationPreset: full +// ---- +// Assembly: +// sstore(calldataload(0x00), calldataload(dataOffset(sub_0))) +// stop +// stop +// +// sub_0: assembly { +// sstore(calldataload(0x00), calldataload(dataOffset(sub_0))) +// stop +// stop +// +// sub_0: assembly { +// sstore(calldataload(0x00), calldataload(dataOffset(sub_0))) +// stop +// stop +// +// sub_0: assembly { +// sstore(calldataload(0x00), calldataload(dataOffset(sub_0))) +// stop +// stop +// +// sub_0: assembly { +// sstore(calldataload(0x00), calldataload(data_736ddcdd19b41ff3aa09bd89628fc69562c2e39bdb07c1971217d2e374ce6e27)) +// stop +// stop +// data_736ddcdd19b41ff3aa09bd89628fc69562c2e39bdb07c1971217d2e374ce6e27 30786262 +// } +// } +// +// sub_1: assembly { +// sstore(calldataload(0x00), calldataload(data_89b1fd0f9a40d0a598af5f997daf99fc3d5b98ef4eb429e81755ae0ee49e194e)) +// stop +// stop +// data_89b1fd0f9a40d0a598af5f997daf99fc3d5b98ef4eb429e81755ae0ee49e194e 30786161 +// } +// +// sub_2: assembly { +// sstore(calldataload(0x00), calldataload(data_d8bbdaa6a33092aa88c90c124bdeea5160229ede56dd7d897c2413f9ba7e4f85)) +// stop +// stop +// data_d8bbdaa6a33092aa88c90c124bdeea5160229ede56dd7d897c2413f9ba7e4f85 3078616161616161 +// } +// } +// } +// +// sub_1: assembly { +// sstore(calldataload(0x00), calldataload(data_79f4f313d7d500fd317e5283225bdfe6ea44da3fb73f1fdbf19929f3164bfc1a)) +// stop +// stop +// data_79f4f313d7d500fd317e5283225bdfe6ea44da3fb73f1fdbf19929f3164bfc1a 307861616161 +// } +// +// sub_2: assembly { +// sstore(calldataload(0x00), calldataload(data_257dd53638d790f0311f866044a2856def338f9a4d22fce0bdeed5b2d53851a9)) +// stop +// stop +// data_257dd53638d790f0311f866044a2856def338f9a4d22fce0bdeed5b2d53851a9 307862626262 +// } +// +// sub_3: assembly { +// sstore(calldataload(0x00), calldataload(data_257dd53638d790f0311f866044a2856def338f9a4d22fce0bdeed5b2d53851a9)) +// stop +// stop +// data_257dd53638d790f0311f866044a2856def338f9a4d22fce0bdeed5b2d53851a9 307862626262 +// } +// Bytecode: 6008355f355500fe6008355f355500fe6008355f355500fe6008355f355500fe6008355f355500fe30786262 +// Opcodes: PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID ADDRESS PUSH25 0x62620000000000000000000000000000000000000000000000 +// SourceMappings: :::-:0;;;;; From 8f237deb99b2202672262d374259ce184ef648eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 12 Jun 2024 17:20:57 +0200 Subject: [PATCH 0268/1340] Object: Add missing `override` specifier to overridden methods --- libyul/Object.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libyul/Object.h b/libyul/Object.h index 41ca74e9f..fe946f1bd 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -99,9 +99,9 @@ struct Object: public ObjectNode AsmPrinter::TypePrinting printingMode = AsmPrinter::TypePrinting::Full, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr - ) const; + ) const override; /// @returns a compact JSON representation of the AST. - Json toJson() const; + Json toJson() const override; /// @returns the set of names of data objects accessible from within the code of /// this object, including the name of object itself /// Handles all names containing dots as reserved identifiers, not accessible as data. From 6654e87735d11c265de2e86553a96b865873a239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 12 Jun 2024 17:43:53 +0200 Subject: [PATCH 0269/1340] ObjectDebugData: Expose a helper for formatting the @use-src comment --- libyul/Object.cpp | 31 ++++++++++++++++++++----------- libyul/Object.h | 2 ++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/libyul/Object.cpp b/libyul/Object.cpp index c4e7971ab..57c783b83 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -53,16 +53,6 @@ std::string Object::toString( yulAssert(hasCode(), "No code"); yulAssert(debugData, "No debug data"); - std::string useSrcComment; - - if (debugData->sourceNames) - useSrcComment = - "/// @use-src " + - joinHumanReadable(ranges::views::transform(*debugData->sourceNames, [](auto&& _pair) { - return std::to_string(_pair.first) + ":" + util::escapeAndQuoteString(*_pair.second); - })) + - "\n"; - std::string inner = "code " + AsmPrinter( _printingMode, _dialect, @@ -74,7 +64,11 @@ std::string Object::toString( for (auto const& obj: subObjects) inner += "\n" + obj->toString(_dialect, _printingMode, _debugInfoSelection, _soliditySourceProvider); - return useSrcComment + "object \"" + name + "\" {\n" + indent(inner) + "\n}"; + return + debugData->formatUseSrcComment() + + "object \"" + name + "\" {\n" + + indent(inner) + "\n" + + "}"; } Json Data::toJson() const @@ -85,6 +79,21 @@ Json Data::toJson() const return ret; } +std::string ObjectDebugData::formatUseSrcComment() const +{ + if (!sourceNames) + return ""; + + auto formatIdNamePair = [](auto&& _pair) { + return std::to_string(_pair.first) + ":" + util::escapeAndQuoteString(*_pair.second); + }; + + std::string serializedSourceNames = joinHumanReadable( + ranges::views::transform(*sourceNames, formatIdNamePair) + ); + return "/// @use-src " + serializedSourceNames + "\n"; +} + Json Object::toJson() const { yulAssert(hasCode(), "No code"); diff --git a/libyul/Object.h b/libyul/Object.h index fe946f1bd..fa9ef96ee 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -84,6 +84,8 @@ struct Data: public ObjectNode struct ObjectDebugData { std::optional sourceNames = {}; + + std::string formatUseSrcComment() const; }; From 27daf268e1f680662910957dca3f3a31c88545ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 31 Jul 2024 20:31:29 +0200 Subject: [PATCH 0270/1340] Caching of optimized IR --- Changelog.md | 1 + libsolidity/interface/CompilerStack.cpp | 7 +- libsolidity/interface/CompilerStack.h | 3 + libyul/CMakeLists.txt | 2 + libyul/ObjectOptimizer.cpp | 167 ++++++++++++++++++++++++ libyul/ObjectOptimizer.h | 95 ++++++++++++++ libyul/YulStack.cpp | 112 ++++++---------- libyul/YulStack.h | 13 +- 8 files changed, 319 insertions(+), 81 deletions(-) create mode 100644 libyul/ObjectOptimizer.cpp create mode 100644 libyul/ObjectOptimizer.h diff --git a/Changelog.md b/Changelog.md index 2a1249c98..034be5773 100644 --- a/Changelog.md +++ b/Changelog.md @@ -19,6 +19,7 @@ Compiler Features: * Standard JSON Interface: Do not perform IR optimization when only unoptimized IR is requested. * Standard JSON Interface: Add ``transientStorageLayout`` output. * Yul: Drop the deprecated typed Yul dialect that was only accessible via ``--yul`` in the CLI. + * Yul Optimizer: Caching of optimized IR to speed up optimization of contracts with bytecode dependencies. * Yul Optimizer: The optimizer now treats some previously unrecognized identical literals as identical. * Commandline Interface: Allow the use of ``--asm-json`` output option in assembler mode to export EVM assembly of the contracts in JSON format. diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 0ea7131db..1f432db40 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -111,6 +111,7 @@ static int g_compilerStackCounts = 0; CompilerStack::CompilerStack(ReadCallback::Callback _readFile): m_readFile{std::move(_readFile)}, + m_objectOptimizer(std::make_shared()), m_errorReporter{m_errorList} { // Because TypeProvider is currently a singleton API, we must ensure that @@ -1493,7 +1494,8 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti m_eofVersion, YulStack::Language::StrictAssembly, m_optimiserSettings, - m_debugInfoSelection + m_debugInfoSelection, + m_objectOptimizer ); bool yulAnalysisSuccessful = stack.parseAndAnalyze("", compiledContract.yulIR); solAssert( @@ -1530,7 +1532,8 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) m_eofVersion, yul::YulStack::Language::StrictAssembly, m_optimiserSettings, - m_debugInfoSelection + m_debugInfoSelection, + m_objectOptimizer ); bool analysisSuccessful = stack.parseAndAnalyze("", compiledContract.yulIROptimized); solAssert(analysisSuccessful); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 159a14d8d..6ca792296 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -49,6 +49,8 @@ #include #include +#include + #include #include #include @@ -552,6 +554,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac std::shared_ptr m_globalContext; std::vector m_sourceOrder; std::map m_contracts; + std::shared_ptr m_objectOptimizer; langutil::ErrorList m_errorList; langutil::ErrorReporter m_errorReporter; diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index ee78d525d..dbf3bfdcd 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -29,6 +29,8 @@ add_library(yul FunctionReferenceResolver.h Object.cpp Object.h + ObjectOptimizer.cpp + ObjectOptimizer.h ObjectParser.cpp ObjectParser.h Scope.cpp diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp new file mode 100644 index 000000000..eaaac97d5 --- /dev/null +++ b/libyul/ObjectOptimizer.cpp @@ -0,0 +1,167 @@ +/* + 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +using namespace solidity; +using namespace solidity::langutil; +using namespace solidity::util; +using namespace solidity::yul; + + +Dialect const& yul::languageToDialect(Language _language, EVMVersion _version) +{ + switch (_language) + { + case Language::Assembly: + case Language::StrictAssembly: + return EVMDialect::strictAssemblyForEVMObjects(_version); + } + util::unreachable(); +} + +void ObjectOptimizer::optimize(Object& _object, Settings const& _settings) +{ + yulAssert(_object.subId == std::numeric_limits::max(), "Not a top-level object."); + + optimize(_object, _settings, true /* _isCreation */); +} + +void ObjectOptimizer::optimize(Object& _object, Settings const& _settings, bool _isCreation) +{ + yulAssert(_object.code()); + yulAssert(_object.debugData); + + for (auto& subNode: _object.subObjects) + if (auto subObject = dynamic_cast(subNode.get())) + { + bool isCreation = !boost::ends_with(subObject->name, "_deployed"); + optimize( + *subObject, + _settings, + isCreation + ); + } + + Dialect const& dialect = languageToDialect(_settings.language, _settings.evmVersion); + std::unique_ptr meter; + if (EVMDialect const* evmDialect = dynamic_cast(&dialect)) + meter = std::make_unique(*evmDialect, _isCreation, _settings.expectedExecutionsPerDeployment); + + std::optional cacheKey = calculateCacheKey(_object.code()->root(), *_object.debugData, _settings, _isCreation); + if (cacheKey.has_value() && m_cachedObjects.count(*cacheKey) != 0) + { + overwriteWithOptimizedObject(*cacheKey, _object); + return; + } + + OptimiserSuite::run( + dialect, + meter.get(), + _object, + _settings.optimizeStackAllocation, + _settings.yulOptimiserSteps, + _settings.yulOptimiserCleanupSteps, + _isCreation ? std::nullopt : std::make_optional(_settings.expectedExecutionsPerDeployment), + {} + ); + + if (cacheKey.has_value()) + storeOptimizedObject(*cacheKey, _object, dialect); +} + +void ObjectOptimizer::storeOptimizedObject(util::h256 _cacheKey, Object const& _optimizedObject, Dialect const& _dialect) +{ + m_cachedObjects[_cacheKey] = CachedObject{ + std::make_shared(ASTCopier{}.translate(_optimizedObject.code()->root())), + &_dialect, + }; +} + +void ObjectOptimizer::overwriteWithOptimizedObject(util::h256 _cacheKey, Object& _object) const +{ + yulAssert(m_cachedObjects.count(_cacheKey) != 0); + CachedObject const& cachedObject = m_cachedObjects.at(_cacheKey); + + yulAssert(cachedObject.optimizedAST); + _object.setCode(std::make_shared(ASTCopier{}.translate(*cachedObject.optimizedAST))); + yulAssert(_object.code()); + + // There's no point in caching AnalysisInfo because it references AST nodes. It can't be shared + // by multiple ASTs and it's easier to recalculate it than properly clone it. + yulAssert(cachedObject.dialect); + _object.analysisInfo = std::make_shared( + AsmAnalyzer::analyzeStrictAssertCorrect( + *cachedObject.dialect, + _object + ) + ); + + // NOTE: Source name index is included in the key so it must be identical. No need to store and restore it. +} + +std::optional ObjectOptimizer::calculateCacheKey( + Block const& _ast, + ObjectDebugData const& _debugData, + Settings const& _settings, + bool _isCreation +) +{ + AsmPrinter asmPrinter( + AsmPrinter::TypePrinting::OmitDefault, + languageToDialect(_settings.language, _settings.evmVersion), + _debugData.sourceNames, + DebugInfoSelection::All() + ); + + bytes rawKey; + // NOTE: AsmPrinter never prints nativeLocations included in debug data, so ASTs differing only + // in that regard are considered equal here. This is fine because the optimizer does not keep + // them up to date across AST transformations anyway so in any use where they need to be reliable, + // we just regenerate them by reparsing the object. + rawKey += keccak256(asmPrinter(_ast)).asBytes(); + rawKey += keccak256(_debugData.formatUseSrcComment()).asBytes(); + rawKey += h256(u256(_settings.language)).asBytes(); + rawKey += FixedHash<1>(uint8_t(_settings.optimizeStackAllocation ? 0 : 1)).asBytes(); + rawKey += h256(u256(_settings.expectedExecutionsPerDeployment)).asBytes(); + rawKey += FixedHash<1>(uint8_t(_isCreation ? 0 : 1)).asBytes(); + rawKey += keccak256(_settings.evmVersion.name()).asBytes(); + rawKey += keccak256(_settings.yulOptimiserSteps).asBytes(); + rawKey += keccak256(_settings.yulOptimiserCleanupSteps).asBytes(); + + return h256(keccak256(rawKey)); +} diff --git a/libyul/ObjectOptimizer.h b/libyul/ObjectOptimizer.h new file mode 100644 index 000000000..89e5739be --- /dev/null +++ b/libyul/ObjectOptimizer.h @@ -0,0 +1,95 @@ +/* + 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 + +#pragma once + +#include +#include + +#include + +#include + +#include +#include +#include + +namespace solidity::yul +{ + +enum class Language +{ + Assembly, + StrictAssembly, +}; + +Dialect const& languageToDialect(Language _language, langutil::EVMVersion _version); + +/// Encapsulates logic for applying @a yul::OptimiserSuite to a whole hierarchy of Yul objects. +/// Also, acts as a transparent cache for optimized objects. +/// +/// The cache is designed to allow sharing its instances widely across the compiler, without the +/// need to invalidate entries due to changing settings or context. +/// Caching is performed at the granularity of individual ASTs rather than whole object trees, +/// which means that reuse is possible even within a single hierarchy, e.g. when creation and +/// deployed objects have common dependencies. +class ObjectOptimizer +{ +public: + /// Optimization settings and context information. + /// This information becomes a part of the cache key and, together with the object content, + /// must uniquely determine the result of optimization. + struct Settings + { + Language language; + langutil::EVMVersion evmVersion; + bool optimizeStackAllocation; + std::string yulOptimiserSteps; + std::string yulOptimiserCleanupSteps; + size_t expectedExecutionsPerDeployment; + }; + + /// Recursively optimizes a Yul object with given settings, reusing cached ASTs where possible + /// or caching the result otherwise. The object is modified in-place. + /// Automatically accounts for the difference between creation and deployed objects. + /// @warning Does not ensure that nativeLocations in the resulting AST match the optimized code. + void optimize(Object& _object, Settings const& _settings); + +private: + struct CachedObject + { + std::shared_ptr optimizedAST; + Dialect const* dialect; + }; + + void optimize(Object& _object, Settings const& _settings, bool _isCreation); + + void storeOptimizedObject(util::h256 _cacheKey, Object const& _optimizedObject, Dialect const& _dialect); + void overwriteWithOptimizedObject(util::h256 _cacheKey, Object& _object) const; + + static std::optional calculateCacheKey( + Block const& _ast, + ObjectDebugData const& _debugData, + Settings const& _settings, + bool _isCreation + ); + + std::map m_cachedObjects; +}; + +} diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 8166ed3cf..eac84ae3a 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -24,14 +24,12 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include @@ -43,22 +41,6 @@ using namespace solidity::yul; using namespace solidity::langutil; using namespace solidity::util; -namespace -{ -Dialect const& languageToDialect(YulStack::Language _language, EVMVersion _version) -{ - switch (_language) - { - case YulStack::Language::Assembly: - case YulStack::Language::StrictAssembly: - return EVMDialect::strictAssemblyForEVMObjects(_version); - } - yulAssert(false); - util::unreachable(); -} - -} - CharStream const& YulStack::charStream(std::string const& _sourceName) const { yulAssert(m_charStream, ""); @@ -114,8 +96,44 @@ void YulStack::optimize() ) return; + auto [optimizeStackAllocation, yulOptimiserSteps, yulOptimiserCleanupSteps] = [&]() -> std::tuple + { + if (!m_optimiserSettings.runYulOptimiser) + { + // Yul optimizer disabled, but empty sequence (:) explicitly provided + if (OptimiserSuite::isEmptyOptimizerSequence(m_optimiserSettings.yulOptimiserSteps + ":" + m_optimiserSettings.yulOptimiserCleanupSteps)) + return std::make_tuple(true, "", ""); + // Yul optimizer disabled, and no sequence explicitly provided (assumes default sequence) + else + { + yulAssert( + m_optimiserSettings.yulOptimiserSteps == OptimiserSettings::DefaultYulOptimiserSteps && + m_optimiserSettings.yulOptimiserCleanupSteps == OptimiserSettings::DefaultYulOptimiserCleanupSteps + ); + // Defaults are the minimum necessary to avoid running into "Stack too deep" constantly. + return std::make_tuple(true, "u", ""); + } + } + return std::make_tuple( + m_optimiserSettings.optimizeStackAllocation, + m_optimiserSettings.yulOptimiserSteps, + m_optimiserSettings.yulOptimiserCleanupSteps + ); + }(); + m_stackState = Parsed; - optimize(*m_parserResult, true); + solAssert(m_objectOptimizer); + m_objectOptimizer->optimize( + *m_parserResult, + ObjectOptimizer::Settings{ + m_language, + m_evmVersion, + optimizeStackAllocation, + yulOptimiserSteps, + yulOptimiserCleanupSteps, + m_optimiserSettings.expectedExecutionsPerDeployment + } + ); // Optimizer does not maintain correct native source locations in the AST. // We can work around it by regenerating the AST from scratch from optimized IR. @@ -186,60 +204,6 @@ void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) const EVMObjectCompiler::compile(*m_parserResult, _assembly, *dialect, _optimize, m_eofVersion); } -void YulStack::optimize(Object& _object, bool _isCreation) -{ - yulAssert(_object.hasCode(), ""); - yulAssert(_object.analysisInfo, ""); - for (auto& subNode: _object.subObjects) - if (auto subObject = dynamic_cast(subNode.get())) - { - bool isCreation = !boost::ends_with(subObject->name, "_deployed"); - optimize(*subObject, isCreation); - } - - Dialect const& dialect = languageToDialect(m_language, m_evmVersion); - std::unique_ptr meter; - if (EVMDialect const* evmDialect = dynamic_cast(&dialect)) - meter = std::make_unique(*evmDialect, _isCreation, m_optimiserSettings.expectedExecutionsPerDeployment); - - auto [optimizeStackAllocation, yulOptimiserSteps, yulOptimiserCleanupSteps] = [&]() -> std::tuple - { - if (!m_optimiserSettings.runYulOptimiser) - { - // Yul optimizer disabled, but empty sequence (:) explicitly provided - if (OptimiserSuite::isEmptyOptimizerSequence(m_optimiserSettings.yulOptimiserSteps + ":" + m_optimiserSettings.yulOptimiserCleanupSteps)) - return std::make_tuple(true, "", ""); - // Yul optimizer disabled, and no sequence explicitly provided (assumes default sequence) - else - { - yulAssert( - m_optimiserSettings.yulOptimiserSteps == OptimiserSettings::DefaultYulOptimiserSteps && - m_optimiserSettings.yulOptimiserCleanupSteps == OptimiserSettings::DefaultYulOptimiserCleanupSteps - ); - return std::make_tuple(true, "u", ""); - } - - } - return std::make_tuple( - m_optimiserSettings.optimizeStackAllocation, - m_optimiserSettings.yulOptimiserSteps, - m_optimiserSettings.yulOptimiserCleanupSteps - ); - }(); - - OptimiserSuite::run( - dialect, - meter.get(), - _object, - // Defaults are the minimum necessary to avoid running into "Stack too deep" constantly. - optimizeStackAllocation, - yulOptimiserSteps, - yulOptimiserCleanupSteps, - _isCreation ? std::nullopt : std::make_optional(m_optimiserSettings.expectedExecutionsPerDeployment), - {} - ); -} - void YulStack::reparse() { yulAssert(m_parserResult); @@ -250,7 +214,7 @@ void YulStack::reparse() // are not stored in the AST and the other info that is (location, AST ID, etc) will still be present. std::string source = print(nullptr /* _soliditySourceProvider */); - YulStack cleanStack(m_evmVersion, m_eofVersion, m_language, m_optimiserSettings, m_debugInfoSelection); + YulStack cleanStack(m_evmVersion, m_eofVersion, m_language, m_optimiserSettings, m_debugInfoSelection, m_objectOptimizer); bool reanalysisSuccessful = cleanStack.parseAndAnalyze(m_charStream->name(), source); yulAssert( reanalysisSuccessful, diff --git a/libyul/YulStack.h b/libyul/YulStack.h index b09fa7975..69c0f0165 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -65,7 +66,7 @@ struct MachineAssemblyObject class YulStack: public langutil::CharStreamProvider { public: - enum class Language { Assembly, StrictAssembly }; + using Language = yul::Language; enum class Machine { EVM }; enum State { Empty, @@ -88,14 +89,16 @@ class YulStack: public langutil::CharStreamProvider std::optional _eofVersion, Language _language, solidity::frontend::OptimiserSettings _optimiserSettings, - langutil::DebugInfoSelection const& _debugInfoSelection + langutil::DebugInfoSelection const& _debugInfoSelection, + std::shared_ptr _objectOptimizer = nullptr ): m_language(_language), m_evmVersion(_evmVersion), m_eofVersion(_eofVersion), m_optimiserSettings(std::move(_optimiserSettings)), m_debugInfoSelection(_debugInfoSelection), - m_errorReporter(m_errors) + m_errorReporter(m_errors), + m_objectOptimizer(_objectOptimizer ? std::move(_objectOptimizer) : std::make_shared()) {} /// @returns the char stream used during parsing @@ -150,8 +153,6 @@ class YulStack: public langutil::CharStreamProvider void compileEVM(yul::AbstractAssembly& _assembly, bool _optimize) const; - void optimize(yul::Object& _object, bool _isCreation); - /// Prints the Yul object stored internally and parses it again. /// This ensures that the debug info in the AST matches the source that printing would produce /// rather than the initial source. @@ -173,6 +174,8 @@ class YulStack: public langutil::CharStreamProvider std::shared_ptr m_parserResult; langutil::ErrorList m_errors; langutil::ErrorReporter m_errorReporter; + + std::shared_ptr m_objectOptimizer; }; } From 5c7fc0409d3f7d579571eedc8af18945cd08312b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 30 Jul 2024 15:07:04 +0200 Subject: [PATCH 0271/1340] OptimizedIRCachingTest --- libsolidity/interface/CompilerStack.h | 2 + libyul/ObjectOptimizer.h | 2 + test/CMakeLists.txt | 2 + test/InteractiveTests.h | 2 + test/libsolidity/OptimizedIRCachingTest.cpp | 50 +++++++++++++++++ test/libsolidity/OptimizedIRCachingTest.h | 54 +++++++++++++++++++ .../bytecode_dependency_creation.sol | 7 +++ ...tecode_dependency_creation_and_runtime.sol | 12 +++++ ...dependency_creation_and_runtime_shared.sol | 11 ++++ .../bytecode_dependency_runtime.sol | 9 ++++ ...ependency_shared_by_multiple_contracts.sol | 19 +++++++ .../optimizedIRCaching/multiple_contracts.sol | 5 ++ .../optimizedIRCaching/no_contracts.sol | 2 + .../optimizedIRCaching/single_contract.sol | 3 ++ test/tools/CMakeLists.txt | 2 + 15 files changed, 182 insertions(+) create mode 100644 test/libsolidity/OptimizedIRCachingTest.cpp create mode 100644 test/libsolidity/OptimizedIRCachingTest.h create mode 100644 test/libsolidity/optimizedIRCaching/bytecode_dependency_creation.sol create mode 100644 test/libsolidity/optimizedIRCaching/bytecode_dependency_creation_and_runtime.sol create mode 100644 test/libsolidity/optimizedIRCaching/bytecode_dependency_creation_and_runtime_shared.sol create mode 100644 test/libsolidity/optimizedIRCaching/bytecode_dependency_runtime.sol create mode 100644 test/libsolidity/optimizedIRCaching/bytecode_dependency_shared_by_multiple_contracts.sol create mode 100644 test/libsolidity/optimizedIRCaching/multiple_contracts.sol create mode 100644 test/libsolidity/optimizedIRCaching/no_contracts.sol create mode 100644 test/libsolidity/optimizedIRCaching/single_contract.sol diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 6ca792296..25863b6d0 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -381,6 +381,8 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac return VersionIsRelease ? MetadataFormat::WithReleaseVersionTag : MetadataFormat::WithPrereleaseVersionTag; } + yul::ObjectOptimizer const& objectOptimizer() const { return *m_objectOptimizer; } + private: /// The state per source unit. Filled gradually during parsing. struct Source diff --git a/libyul/ObjectOptimizer.h b/libyul/ObjectOptimizer.h index 89e5739be..e570d69c4 100644 --- a/libyul/ObjectOptimizer.h +++ b/libyul/ObjectOptimizer.h @@ -70,6 +70,8 @@ class ObjectOptimizer /// @warning Does not ensure that nativeLocations in the resulting AST match the optimized code. void optimize(Object& _object, Settings const& _settings); + size_t size() const { return m_cachedObjects.size(); } + private: struct CachedObject { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0d19d7796..5308a55f7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -88,6 +88,8 @@ set(libsolidity_sources libsolidity/MemoryGuardTest.h libsolidity/NatspecJSONTest.cpp libsolidity/NatspecJSONTest.h + libsolidity/OptimizedIRCachingTest.cpp + libsolidity/OptimizedIRCachingTest.h libsolidity/SemanticTest.cpp libsolidity/SemanticTest.h libsolidity/SemVerMatcher.cpp diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index 42e20d7e3..4c2077576 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,7 @@ Testsuite const g_interactiveTestsuites[] = { {"Memory Guard", "libsolidity", "memoryGuardTests", false, false, &MemoryGuardTest::create}, {"AST Properties", "libsolidity", "astPropertyTests", false, false, &ASTPropertyTest::create}, {"Function Dependency Graph", "libsolidity", "functionDependencyGraphTests", false, false, &FunctionDependencyGraphTest::create}, + {"Optimized IR Caching", "libsolidity", "optimizedIRCaching", false, false, &OptimizedIRCachingTest::create}, }; } diff --git a/test/libsolidity/OptimizedIRCachingTest.cpp b/test/libsolidity/OptimizedIRCachingTest.cpp new file mode 100644 index 000000000..d1e735eeb --- /dev/null +++ b/test/libsolidity/OptimizedIRCachingTest.cpp @@ -0,0 +1,50 @@ +/* + 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 + +#include +#include + +#include + +#include + +using namespace solidity::util; +using namespace solidity::langutil; +using namespace solidity::frontend; +using namespace solidity::frontend::test; + +void OptimizedIRCachingTest::setupCompiler(CompilerStack& _compiler) +{ + AnalysisFramework::setupCompiler(_compiler); + _compiler.setOptimiserSettings(true); + _compiler.setViaIR(true); +} + +TestCase::TestResult OptimizedIRCachingTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) +{ + soltestAssert(compiler().objectOptimizer().size() == 0); + + if (!runFramework(m_source, PipelineStage::Compilation)) + { + printPrefixed(_stream, formatErrors(filteredErrors(), _formatted), _linePrefix); + return TestResult::FatalError; + } + + m_obtainedResult = "cachedObjects: " + toString(compiler().objectOptimizer().size()) + "\n"; + return checkResult(_stream, _linePrefix, _formatted); +} diff --git a/test/libsolidity/OptimizedIRCachingTest.h b/test/libsolidity/OptimizedIRCachingTest.h new file mode 100644 index 000000000..8681346ca --- /dev/null +++ b/test/libsolidity/OptimizedIRCachingTest.h @@ -0,0 +1,54 @@ +/* + 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 +/** + * Unit tests for the optimized IR caching in CompilerStack. + */ + +#pragma once + +#include +#include + +#include +#include + +namespace solidity::frontend::test +{ + +class OptimizedIRCachingTest: public AnalysisFramework, public EVMVersionRestrictedTestCase +{ +public: + OptimizedIRCachingTest(std::string const& _filename): + EVMVersionRestrictedTestCase(_filename) + { + m_source = m_reader.source(); + m_expectation = m_reader.simpleExpectations(); + } + + static std::unique_ptr create(Config const& _config) + { + return std::make_unique(_config.filename); + } + + TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool _formatted = false) override; + +protected: + void setupCompiler(CompilerStack& _compiler) override; +}; + +} diff --git a/test/libsolidity/optimizedIRCaching/bytecode_dependency_creation.sol b/test/libsolidity/optimizedIRCaching/bytecode_dependency_creation.sol new file mode 100644 index 000000000..6e603ee73 --- /dev/null +++ b/test/libsolidity/optimizedIRCaching/bytecode_dependency_creation.sol @@ -0,0 +1,7 @@ +contract A {} + +contract C { + A a = new A(); +} +// ---- +// cachedObjects: 4 diff --git a/test/libsolidity/optimizedIRCaching/bytecode_dependency_creation_and_runtime.sol b/test/libsolidity/optimizedIRCaching/bytecode_dependency_creation_and_runtime.sol new file mode 100644 index 000000000..40ab2993c --- /dev/null +++ b/test/libsolidity/optimizedIRCaching/bytecode_dependency_creation_and_runtime.sol @@ -0,0 +1,12 @@ +contract A {} +contract B {} + +contract C { + A a = new A(); + + function f() public returns (B) { + return new B(); + } +} +// ---- +// cachedObjects: 6 diff --git a/test/libsolidity/optimizedIRCaching/bytecode_dependency_creation_and_runtime_shared.sol b/test/libsolidity/optimizedIRCaching/bytecode_dependency_creation_and_runtime_shared.sol new file mode 100644 index 000000000..86df1b37e --- /dev/null +++ b/test/libsolidity/optimizedIRCaching/bytecode_dependency_creation_and_runtime_shared.sol @@ -0,0 +1,11 @@ +contract A {} + +contract C { + A a = new A(); + + function f() public returns (A) { + return new A(); + } +} +// ---- +// cachedObjects: 4 diff --git a/test/libsolidity/optimizedIRCaching/bytecode_dependency_runtime.sol b/test/libsolidity/optimizedIRCaching/bytecode_dependency_runtime.sol new file mode 100644 index 000000000..6cc4d6bde --- /dev/null +++ b/test/libsolidity/optimizedIRCaching/bytecode_dependency_runtime.sol @@ -0,0 +1,9 @@ +contract A {} + +contract C { + function f() public returns (A) { + return new A(); + } +} +// ---- +// cachedObjects: 4 diff --git a/test/libsolidity/optimizedIRCaching/bytecode_dependency_shared_by_multiple_contracts.sol b/test/libsolidity/optimizedIRCaching/bytecode_dependency_shared_by_multiple_contracts.sol new file mode 100644 index 000000000..cd0f97f95 --- /dev/null +++ b/test/libsolidity/optimizedIRCaching/bytecode_dependency_shared_by_multiple_contracts.sol @@ -0,0 +1,19 @@ +contract A {} + +contract C { + A a = new A(); + + function f() public returns (A) { + return new A(); + } +} + +contract D { + A a = new A(); + + function f() public returns (A) { + return new A(); + } +} +// ---- +// cachedObjects: 6 diff --git a/test/libsolidity/optimizedIRCaching/multiple_contracts.sol b/test/libsolidity/optimizedIRCaching/multiple_contracts.sol new file mode 100644 index 000000000..b80c99b65 --- /dev/null +++ b/test/libsolidity/optimizedIRCaching/multiple_contracts.sol @@ -0,0 +1,5 @@ +contract C {} +contract D {} +contract E {} +// ---- +// cachedObjects: 6 diff --git a/test/libsolidity/optimizedIRCaching/no_contracts.sol b/test/libsolidity/optimizedIRCaching/no_contracts.sol new file mode 100644 index 000000000..c080768cd --- /dev/null +++ b/test/libsolidity/optimizedIRCaching/no_contracts.sol @@ -0,0 +1,2 @@ +// ---- +// cachedObjects: 0 diff --git a/test/libsolidity/optimizedIRCaching/single_contract.sol b/test/libsolidity/optimizedIRCaching/single_contract.sol new file mode 100644 index 000000000..6f3ab6df8 --- /dev/null +++ b/test/libsolidity/optimizedIRCaching/single_contract.sol @@ -0,0 +1,3 @@ +contract C {} +// ---- +// cachedObjects: 2 diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 532a08d9f..44a5e2aa7 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -26,6 +26,8 @@ add_executable(isoltest ../libsolidity/GasTest.cpp ../libsolidity/MemoryGuardTest.cpp ../libsolidity/NatspecJSONTest.cpp + ../libsolidity/OptimizedIRCachingTest.cpp + ../libsolidity/OptimizedIRCachingTest.h ../libsolidity/SyntaxTest.cpp ../libsolidity/SemanticTest.cpp ../libsolidity/AnalysisFramework.cpp From f6aee354b3aa379539cd07577d1a61787ad47cd2 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Mon, 19 Aug 2024 17:12:54 +0200 Subject: [PATCH 0272/1340] Fix some submodule related problems. --- .dockerignore | 2 -- scripts/create_source_tarball.sh | 2 ++ scripts/docker_deploy_manual.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.dockerignore b/.dockerignore index ab452ecf2..8d9330854 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,5 +2,3 @@ # the build context to the docker image build server /build -# in-tree builds -/deps diff --git a/scripts/create_source_tarball.sh b/scripts/create_source_tarball.sh index 37bee6df1..f5e2892ac 100755 --- a/scripts/create_source_tarball.sh +++ b/scripts/create_source_tarball.sh @@ -21,6 +21,8 @@ REPO_ROOT="$(dirname "$0")"/.. TEMPDIR=$(mktemp -d) SOLDIR="$TEMPDIR/solidity_$versionstring/" mkdir "$SOLDIR" + # Ensure that submodules are initialized. + git submodule update --init --recursive # Store the current source git checkout-index -a --prefix="$SOLDIR" # shellcheck disable=SC2016 diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index 12d3e5ff4..48d021ff0 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -16,7 +16,7 @@ DIR=$(mktemp -d) ( cd "$DIR" -git clone --depth 2 https://github.com/ethereum/solidity.git -b "$branch" +git clone --recursive --depth 2 https://github.com/ethereum/solidity.git -b "$branch" cd solidity commithash=$(git rev-parse --short=8 HEAD) echo -n "$commithash" > commit_hash.txt From b6ab05419db0742296c0a35b47561cea8652d7a5 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Mon, 29 Jul 2024 13:43:09 +0200 Subject: [PATCH 0273/1340] Update fmtlib to v11.0.2. --- deps/fmtlib | 2 +- libyul/AsmAnalysis.cpp | 4 ++-- libyul/YulString.h | 19 ------------------- 3 files changed, 3 insertions(+), 22 deletions(-) diff --git a/deps/fmtlib b/deps/fmtlib index a33701196..0c9fce2ff 160000 --- a/deps/fmtlib +++ b/deps/fmtlib @@ -1 +1 @@ -Subproject commit a33701196adfad74917046096bf5a2aa0ab0bb50 +Subproject commit 0c9fce2ffefecfdce794e1859584e25877b7b592 diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 09be59742..22ec8c994 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -694,7 +694,7 @@ void AsmAnalyzer::expectValidType(YulName _type, SourceLocation const& _location m_errorReporter.typeError( 5473_error, _location, - fmt::format("\"{}\" is not a valid type (user defined types are not yet supported).", _type) + fmt::format("\"{}\" is not a valid type (user defined types are not yet supported).", _type.str()) ); } @@ -704,7 +704,7 @@ void AsmAnalyzer::expectType(YulName _expectedType, YulName _givenType, SourceLo m_errorReporter.typeError( 3781_error, _location, - fmt::format("Expected a value of type \"{}\" but got \"{}\".", _expectedType, _givenType) + fmt::format("Expected a value of type \"{}\" but got \"{}\".", _expectedType.str(), _givenType.str()) ); } diff --git a/libyul/YulString.h b/libyul/YulString.h index 89d35b123..bd9438e5a 100644 --- a/libyul/YulString.h +++ b/libyul/YulString.h @@ -169,25 +169,6 @@ inline YulString operator "" _yulname(char const* _string, std::size_t _size) } -namespace fmt -{ -template <> -struct formatter -{ - template - constexpr auto parse(ParseContext& _context) - { - return _context.begin(); - } - - template - auto format(solidity::yul::YulString _value, FormatContext& _context) - { - return format_to(_context.out(), "{}", _value.str()); - } -}; -} - namespace std { template<> struct hash From 20fa893f7e6decb502a36fd9e9eee7e4e59b44e0 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 22 Aug 2024 23:32:51 -0300 Subject: [PATCH 0274/1340] More precise calculations when evaluating how many bytes immutables require --- Changelog.md | 1 + libevmasm/Assembly.cpp | 2 +- .../immutable/immutable_tag_too_large_bug.sol | 48 +++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/semanticTests/immutable/immutable_tag_too_large_bug.sol diff --git a/Changelog.md b/Changelog.md index 034be5773..288136dd9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -25,6 +25,7 @@ Compiler Features: Bugfixes: + * Assembler: Fix ICE caused by imprecise calculation of required size of tags in bytecode when code size is above 255. * Parser: Fix spuriously emitted parser error for unary plus operations when used as binary operator in some cases. * SMTChecker: Fix error that reports invalid number of verified checks for BMC and CHC engines. * SMTChecker: Fix formatting of unary minus expressions in invariants. diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 91773a8e8..ab3879da4 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -74,7 +74,7 @@ unsigned Assembly::codeSize(unsigned subTagSize) const ret += i.second.size(); for (AssemblyItem const& i: m_items) - ret += i.bytesRequired(tagSize, m_evmVersion, Precision::Approximate); + ret += i.bytesRequired(tagSize, m_evmVersion, Precision::Precise); if (numberEncodingSize(ret) <= tagSize) return static_cast(ret); } diff --git a/test/libsolidity/semanticTests/immutable/immutable_tag_too_large_bug.sol b/test/libsolidity/semanticTests/immutable/immutable_tag_too_large_bug.sol new file mode 100644 index 000000000..fed424628 --- /dev/null +++ b/test/libsolidity/semanticTests/immutable/immutable_tag_too_large_bug.sol @@ -0,0 +1,48 @@ +contract C { + int immutable x = 1; + int immutable y = 3; + + function f() public payable returns(int, int) { + uint a = uint(y / 1e8); + int256 b = x * y; + int24 c = int24(b * b >> 128); + int24 d = int24((100 * y + 1) >> 128); + int24 e = int24(x >> 128); + int256 f = x * 2; + if (c < 0) { + int256 g = (x * x * y) / x; + require((y >= 0 && g <= x) || (y < 0 && (x - y) > x)); + if (b >= f) { + require(x <= int256(uint256(type(uint168).max)) && x >= 0, ""); + b = (b * b) / f; + for (a = 0; a < a; a++) { + uint8 b; + assembly { + b := and(mload(a), 0xFF) + } + } + b += f; + } + require(d % e != 0); + c = -c; + } + return (x, ((x * (x - y)) / (x + y))); + } + + constructor () { + x--; + --x; + y++; + ++y; + --y; + } +} +// ==== +// compileViaYul: true +// ---- +// constructor() -> +// gas irOptimized: 73171 +// gas irOptimized code: 291200 +// gas legacy: 83499 +// gas legacy code: 408800 +// f() -> -1, 1 From 0e80fbf73b5067affaf22b76588320e649c14f96 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 22 Jul 2024 11:10:20 +0200 Subject: [PATCH 0275/1340] prep: Extend `StandardCompiler` settings with `eofVersion` flag. Fix typo in input parsing Co-authored-by: Daniel Kirchner --- libsolidity/interface/StandardCompiler.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index b209987dd..0c1ccb6b7 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -426,7 +426,7 @@ std::optional checkAuxiliaryInputKeys(Json const& _input) std::optional checkSettingsKeys(Json const& _input) { - static std::set keys{"debug", "evmVersion", "libraries", "metadata", "modelChecker", "optimizer", "outputSelection", "remappings", "stopAfter", "viaIR"}; + static std::set keys{"debug", "evmVersion", "eofVersion", "libraries", "metadata", "modelChecker", "optimizer", "outputSelection", "remappings", "stopAfter", "viaIR"}; return checkKeys(_input, keys, "settings"); } @@ -837,7 +837,7 @@ std::variant StandardCompiler::parseI { if (!settings["eofVersion"].is_number_unsigned()) return formatFatalError(Error::Type::JSONError, "eofVersion must be an unsigned integer."); - auto eofVersion = settings["evmVersion"].get(); + auto eofVersion = settings["eofVersion"].get(); if (eofVersion != 1) return formatFatalError(Error::Type::JSONError, "Invalid EOF version requested."); ret.eofVersion = 1; @@ -1308,6 +1308,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu compilerStack.addSMTLib2Response(smtLib2Response.first, smtLib2Response.second); compilerStack.setViaIR(_inputsAndSettings.viaIR); compilerStack.setEVMVersion(_inputsAndSettings.evmVersion); + compilerStack.setEOFVersion(_inputsAndSettings.eofVersion); compilerStack.setRemappings(std::move(_inputsAndSettings.remappings)); compilerStack.setOptimiserSettings(std::move(_inputsAndSettings.optimiserSettings)); compilerStack.setRevertStringBehaviour(_inputsAndSettings.revertStrings); From 541452036dc5e17c1e1c973bd45ca3596f1106bc Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 22 Jul 2024 15:16:34 +0200 Subject: [PATCH 0276/1340] prep: Change `toBigEndian` interface to support rvalue ref. Co-authored-by: Daniel Kirchner --- libsolutil/Numeric.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libsolutil/Numeric.h b/libsolutil/Numeric.h index be9f0bea2..f4e88de3c 100644 --- a/libsolutil/Numeric.h +++ b/libsolutil/Numeric.h @@ -96,13 +96,13 @@ bool fitsPrecisionBaseX(bigint const& _mantissa, double _log2OfBase, uint32_t _e /// @a Out will typically be either std::string or bytes. /// @a T will typically by unsigned, u160, u256 or bigint. template -inline void toBigEndian(T _val, Out& o_out) +inline void toBigEndian(T _val, Out&& o_out) { static_assert(std::is_same::value || !std::numeric_limits::is_signed, "only unsigned types or bigint supported"); //bigint does not carry sign bit on shift - for (auto i = o_out.size(); i != 0; _val >>= 8, i--) + for (auto i = o_out.size(); i != 0u; _val >>= 8u, i--) { - T v = _val & (T)0xff; - o_out[i - 1] = (typename Out::value_type)(uint8_t)v; + T v = _val & (T)0xffu; + o_out[i - 1u] = (typename std::remove_reference_t::value_type)(uint8_t)v; } } From 9e752f5c1b0ceff75483518f8750eac4dec50392 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Tue, 27 Aug 2024 00:08:37 +0900 Subject: [PATCH 0277/1340] chore: update array_storage_index_zeroed_test.sol test_zeroed_indicies -> test_zeroed_indices --- .../array/array_storage_index_zeroed_test.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol b/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol index 23feb0da1..cdd6b70f5 100644 --- a/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol +++ b/test/libsolidity/semanticTests/array/array_storage_index_zeroed_test.sol @@ -1,6 +1,6 @@ contract C { uint[] storageArray; - function test_zeroed_indicies(uint256 len) public + function test_zeroed_indices(uint256 len) public { while(storageArray.length < len) storageArray.push(); @@ -50,20 +50,20 @@ contract C { } } // ---- -// test_zeroed_indicies(uint256): 1 -> -// test_zeroed_indicies(uint256): 5 -> +// test_zeroed_indices(uint256): 1 -> +// test_zeroed_indices(uint256): 5 -> // gas irOptimized: 133763 // gas legacy: 131664 // gas legacyOptimized: 129990 -// test_zeroed_indicies(uint256): 10 -> +// test_zeroed_indices(uint256): 10 -> // gas irOptimized: 228556 // gas legacy: 225215 // gas legacyOptimized: 222351 -// test_zeroed_indicies(uint256): 15 -> +// test_zeroed_indices(uint256): 15 -> // gas irOptimized: 327360 // gas legacy: 322899 // gas legacyOptimized: 318907 -// test_zeroed_indicies(uint256): 0xFF -> +// test_zeroed_indices(uint256): 0xFF -> // gas irOptimized: 5180120 // gas legacy: 5093135 // gas legacyOptimized: 5020523 From b8373e91297a54e56b4cea31f704a62b97316add Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:16:42 +0200 Subject: [PATCH 0278/1340] CI: explicitly add numpy to LSP test dependencies on windows --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 343bb6d00..b5d0b76d6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1656,7 +1656,7 @@ jobs: shell: powershell.exe - run: name: Install LSP test dependencies - command: python -m pip install --user deepdiff colorama + command: python -m pip install --user numpy deepdiff colorama - run: name: Executing solc LSP test suite command: python test/lsp.py build\solc\Release\solc.exe --non-interactive From 47a715ffa548ac0bcd7532defc76f21c3c68a5ed Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 14 Aug 2024 09:51:15 +0200 Subject: [PATCH 0279/1340] Yul: Remove boolType and defaultType from dialect --- libyul/AsmAnalysis.cpp | 27 +++++++++---------- libyul/AsmParser.cpp | 4 +-- libyul/AsmPrinter.cpp | 13 ++------- libyul/AsmPrinter.h | 2 +- libyul/Dialect.cpp | 23 ++-------------- libyul/Dialect.h | 27 ++++++------------- .../backends/evm/ControlFlowGraphBuilder.cpp | 2 +- libyul/backends/evm/EVMDialect.h | 14 +++++----- libyul/optimiser/ConditionalSimplifier.cpp | 2 +- libyul/optimiser/ControlFlowSimplifier.cpp | 15 +++++------ libyul/optimiser/DataFlowAnalyzer.cpp | 10 +++---- libyul/optimiser/ForLoopConditionIntoBody.cpp | 2 +- libyul/optimiser/FullInliner.cpp | 2 +- libyul/optimiser/LoadResolver.cpp | 4 +-- libyul/optimiser/StackToMemoryMover.cpp | 4 +-- libyul/optimiser/UnusedPruner.cpp | 4 +-- libyul/optimiser/VarDeclInitializer.cpp | 4 +-- 17 files changed, 59 insertions(+), 100 deletions(-) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 22ec8c994..908e30e62 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -128,14 +128,12 @@ std::vector AsmAnalyzer::operator()(Literal const& _literal) m_errorReporter.typeError(6708_error, nativeLocationOf(_literal), "Number literal too large (> 256 bits)"); } - if (!m_dialect.validTypeForLiteral(_literal.kind, _literal.value, _literal.type)) - { + if (_literal.kind == LiteralKind::Boolean && !_literal.type.empty()) m_errorReporter.typeError( 5170_error, nativeLocationOf(_literal), "Invalid type \"" + _literal.type.str() + "\" for literal \"" + formatLiteral(_literal) + "\"." ); - } yulAssert(erroneousLiteralValue ^ validLiteral(_literal), "Invalid literal after validating it through AsmAnalyzer."); return {_literal.type}; @@ -145,7 +143,7 @@ std::vector AsmAnalyzer::operator()(Identifier const& _identifier) { yulAssert(!_identifier.name.empty(), ""); auto watcher = m_errorReporter.errorWatcher(); - YulName type = m_dialect.defaultType; + YulName type{}; if (m_currentScope->lookup(_identifier.name, GenericVisitor{ [&](Scope::Variable const& _var) @@ -284,7 +282,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) for (size_t i = 0; i < _varDecl.variables.size(); ++i) { - YulName givenType = m_dialect.defaultType; + YulName givenType{}; if (i < types.size()) givenType = types[i]; TypedName const& variable = _varDecl.variables[i]; @@ -474,7 +472,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) return *returnTypes; } else if (returnTypes) - return std::vector(returnTypes->size(), m_dialect.defaultType); + return std::vector(returnTypes->size(), YulName{}); else return {}; } @@ -573,13 +571,13 @@ YulName AsmAnalyzer::expectExpression(Expression const& _expr) std::to_string(types.size()) + " values instead." ); - return types.empty() ? m_dialect.defaultType : types.front(); + return types.empty() ? YulName{} : types.front(); } YulName AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal) { yulAssert(_literal.kind == LiteralKind::String); - yulAssert(m_dialect.validTypeForLiteral(LiteralKind::String, _literal.value, _literal.type)); + yulAssert(_literal.type.empty()); yulAssert(_literal.value.unlimited()); return {_literal.type}; @@ -588,12 +586,13 @@ YulName AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal) void AsmAnalyzer::expectBoolExpression(Expression const& _expr) { YulName type = expectExpression(_expr); - if (type != m_dialect.boolType) + static YulName boolType = {}; + if (type != boolType) m_errorReporter.typeError( 1733_error, nativeLocationOf(_expr), "Expected a value of boolean type \"" + - m_dialect.boolType.str() + + boolType.str() + "\" but got \"" + type.str() + "\"" @@ -604,7 +603,7 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulName _valueTyp { yulAssert(!_variable.name.empty(), ""); auto watcher = m_errorReporter.errorWatcher(); - YulName const* variableType = nullptr; + std::optional variableType = std::nullopt; bool found = false; if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name)) { @@ -625,7 +624,7 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulName _valueTyp "Variable " + _variable.name.str() + " used before it was declared." ); else - variableType = &std::get(*var).type; + variableType = std::get(*var).type; found = true; } else if (m_resolver) @@ -634,7 +633,7 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulName _valueTyp if (m_resolver(_variable, yul::IdentifierContext::LValue, insideFunction)) { found = true; - variableType = &m_dialect.defaultType; + variableType = YulName{}; } } @@ -690,7 +689,7 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons void AsmAnalyzer::expectValidType(YulName _type, SourceLocation const& _location) { - if (!m_dialect.types.count(_type)) + if (!_type.empty()) m_errorReporter.typeError( 5473_error, _location, diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 6223a1a8e..a2a4c36dc 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -571,7 +571,7 @@ std::variant Parser::parseLiteralOrIdentifier(bool _unlimit createDebugData(), kind, valueOfLiteral(currentLiteral(), kind, _unlimitedLiteralArgument && kind == LiteralKind::String), - kind == LiteralKind::Boolean ? m_dialect.boolType : m_dialect.defaultType + {} }; advance(); if (currentToken() == Token::Colon) @@ -707,7 +707,7 @@ TypedName Parser::parseTypedName() typedName.type = expectAsmIdentifier(); } else - typedName.type = m_dialect.defaultType; + typedName.type = {}; return typedName; } diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 6b840fcfe..a5ce47d12 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -53,9 +53,8 @@ std::string AsmPrinter::operator()(Literal const& _literal) switch (_literal.kind) { case LiteralKind::Number: - return locationComment + formattedValue + appendTypeName(_literal.type); case LiteralKind::Boolean: - return locationComment + formattedValue + appendTypeName(_literal.type, true); + return locationComment + formattedValue + appendTypeName(_literal.type); case LiteralKind::String: break; } @@ -243,20 +242,12 @@ std::string AsmPrinter::formatTypedName(TypedName _variable) return formatDebugData(_variable) + _variable.name.str() + appendTypeName(_variable.type); } -std::string AsmPrinter::appendTypeName(YulName _type, bool _isBoolLiteral) const +std::string AsmPrinter::appendTypeName(YulName _type) const { yulAssert( m_typePrintingMode == TypePrinting::OmitDefault || m_typePrintingMode == TypePrinting::Full, "unhandled printing mode" ); - if (m_typePrintingMode == TypePrinting::OmitDefault && !_type.empty()) - { - if (!_isBoolLiteral && _type == m_dialect.defaultType) - _type = {}; - else if (_isBoolLiteral && _type == m_dialect.boolType && !m_dialect.defaultType.empty()) - // Special case: If we have a bool type but empty default type, do not remove the type. - _type = {}; - } if (_type.empty()) return {}; else diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 684ddaacf..90fa3a4b5 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -93,7 +93,7 @@ class AsmPrinter private: std::string formatTypedName(TypedName _variable); - std::string appendTypeName(YulName _type, bool _isBoolLiteral = false) const; + std::string appendTypeName(YulName _type) const; std::string formatDebugData(langutil::DebugData::ConstPtr const& _debugData, bool _statement); template std::string formatDebugData(T const& _node) diff --git a/libyul/Dialect.cpp b/libyul/Dialect.cpp index 8afd99a22..be6c6705e 100644 --- a/libyul/Dialect.cpp +++ b/libyul/Dialect.cpp @@ -25,26 +25,7 @@ using namespace solidity::yul; using namespace solidity::langutil; -Literal Dialect::zeroLiteralForType(solidity::yul::YulName _type) const +Literal Dialect::zeroLiteral() const { - if (_type == boolType && _type != defaultType) - return {DebugData::create(), LiteralKind::Boolean, LiteralValue(false), _type}; - return {DebugData::create(), LiteralKind::Number, LiteralValue(0, std::nullopt), _type}; -} - - -Literal Dialect::trueLiteral() const -{ - if (boolType != defaultType) - return {DebugData::create(), LiteralKind::Boolean, LiteralValue(true), boolType}; - else - return {DebugData::create(), LiteralKind::Number, LiteralValue(1), defaultType}; -} - -bool Dialect::validTypeForLiteral(LiteralKind _kind, LiteralValue const&, YulName _type) const -{ - if (_kind == LiteralKind::Boolean) - return _type == boolType; - else - return true; + return {DebugData::create(), LiteralKind::Number, LiteralValue(0, std::nullopt), {}}; } diff --git a/libyul/Dialect.h b/libyul/Dialect.h index fcec5fe3f..f9ce01469 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -61,34 +61,23 @@ struct Dialect Dialect(Dialect const&) = delete; Dialect& operator=(Dialect const&) = delete; - /// Default type, can be omitted. - YulName defaultType; - /// Type used for the literals "true" and "false". - YulName boolType; - std::set types = {{}}; - /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. virtual BuiltinFunction const* builtin(YulName /*_name*/) const { return nullptr; } /// @returns true if the identifier is reserved. This includes the builtins too. virtual bool reservedIdentifier(YulName _name) const { return builtin(_name) != nullptr; } - virtual BuiltinFunction const* discardFunction(YulName /* _type */) const { return nullptr; } - virtual BuiltinFunction const* equalityFunction(YulName /* _type */) const { return nullptr; } + virtual BuiltinFunction const* discardFunction() const { return nullptr; } + virtual BuiltinFunction const* equalityFunction() const { return nullptr; } virtual BuiltinFunction const* booleanNegationFunction() const { return nullptr; } - virtual BuiltinFunction const* memoryStoreFunction(YulName /* _type */) const { return nullptr; } - virtual BuiltinFunction const* memoryLoadFunction(YulName /* _type */) const { return nullptr; } - virtual BuiltinFunction const* storageStoreFunction(YulName /* _type */) const { return nullptr; } - virtual BuiltinFunction const* storageLoadFunction(YulName /* _type */) const { return nullptr; } - virtual YulName hashFunction(YulName /* _type */ ) const { return YulName{}; } - - /// Check whether the given type is legal for the given literal value. - /// Should only be called if the type exists in the dialect at all. - virtual bool validTypeForLiteral(LiteralKind _kind, LiteralValue const& _value, YulName _type) const; + virtual BuiltinFunction const* memoryStoreFunction() const { return nullptr; } + virtual BuiltinFunction const* memoryLoadFunction() const { return nullptr; } + virtual BuiltinFunction const* storageStoreFunction() const { return nullptr; } + virtual BuiltinFunction const* storageLoadFunction() const { return nullptr; } + virtual YulName hashFunction() const { return YulName{}; } - virtual Literal zeroLiteralForType(YulName _type) const; - virtual Literal trueLiteral() const; + Literal zeroLiteral() const; virtual std::set fixedFunctionNames() const { return {}; } diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index b4d1cdf15..3007566dd 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -349,7 +349,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) CFG::Assignment{_switch.debugData, {ghostVarSlot}} }); - BuiltinFunction const* equalityBuiltin = m_dialect.equalityFunction({}); + BuiltinFunction const* equalityBuiltin = m_dialect.equalityFunction(); yulAssert(equalityBuiltin, ""); // Artificially generate: diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 89df94496..3207b8fae 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -74,14 +74,14 @@ struct EVMDialect: public Dialect /// @returns true if the identifier is reserved. This includes the builtins too. bool reservedIdentifier(YulName _name) const override; - BuiltinFunctionForEVM const* discardFunction(YulName /*_type*/) const override { return builtin("pop"_yulname); } - BuiltinFunctionForEVM const* equalityFunction(YulName /*_type*/) const override { return builtin("eq"_yulname); } + BuiltinFunctionForEVM const* discardFunction() const override { return builtin("pop"_yulname); } + BuiltinFunctionForEVM const* equalityFunction() const override { return builtin("eq"_yulname); } BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("iszero"_yulname); } - BuiltinFunctionForEVM const* memoryStoreFunction(YulName /*_type*/) const override { return builtin("mstore"_yulname); } - BuiltinFunctionForEVM const* memoryLoadFunction(YulName /*_type*/) const override { return builtin("mload"_yulname); } - BuiltinFunctionForEVM const* storageStoreFunction(YulName /*_type*/) const override { return builtin("sstore"_yulname); } - BuiltinFunctionForEVM const* storageLoadFunction(YulName /*_type*/) const override { return builtin("sload"_yulname); } - YulName hashFunction(YulName /*_type*/) const override { return "keccak256"_yulname; } + BuiltinFunctionForEVM const* memoryStoreFunction() const override { return builtin("mstore"_yulname); } + BuiltinFunctionForEVM const* memoryLoadFunction() const override { return builtin("mload"_yulname); } + BuiltinFunctionForEVM const* storageStoreFunction() const override { return builtin("sstore"_yulname); } + BuiltinFunctionForEVM const* storageLoadFunction() const override { return builtin("sload"_yulname); } + YulName hashFunction() const override { return "keccak256"_yulname; } static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version); static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _version); diff --git a/libyul/optimiser/ConditionalSimplifier.cpp b/libyul/optimiser/ConditionalSimplifier.cpp index a2656fed3..f81933f41 100644 --- a/libyul/optimiser/ConditionalSimplifier.cpp +++ b/libyul/optimiser/ConditionalSimplifier.cpp @@ -84,7 +84,7 @@ void ConditionalSimplifier::operator()(Block& _block) Assignment{ debugData, {Identifier{debugData, condition}}, - std::make_unique(m_dialect.zeroLiteralForType(m_dialect.boolType)) + std::make_unique(m_dialect.zeroLiteral()) } ); } diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index 9d56583a0..2d0dbb467 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -138,12 +138,12 @@ void ControlFlowSimplifier::simplify(std::vector& _statements) GenericVisitor visitor{ VisitorFallback{}, [&](If& _ifStmt) -> OptionalStatements { - if (_ifStmt.body.statements.empty() && m_dialect.discardFunction(m_dialect.boolType)) + if (_ifStmt.body.statements.empty() && m_dialect.discardFunction()) { OptionalStatements s = std::vector{}; s->emplace_back(makeDiscardCall( _ifStmt.debugData, - *m_dialect.discardFunction(m_dialect.boolType), + *m_dialect.discardFunction(), std::move(*_ifStmt.condition) )); return s; @@ -180,7 +180,7 @@ OptionalStatements ControlFlowSimplifier::reduceNoCaseSwitch(Switch& _switchStmt { yulAssert(_switchStmt.cases.empty(), "Expected no case!"); BuiltinFunction const* discardFunction = - m_dialect.discardFunction(m_typeInfo.typeOf(*_switchStmt.expression)); + m_dialect.discardFunction(); if (!discardFunction) return {}; @@ -197,16 +197,15 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch auto& switchCase = _switchStmt.cases.front(); langutil::DebugData::ConstPtr debugData = debugDataOf(*_switchStmt.expression); - YulName type = m_typeInfo.typeOf(*_switchStmt.expression); if (switchCase.value) { - if (!m_dialect.equalityFunction(type)) + if (!m_dialect.equalityFunction()) return {}; return make_vector(If{ std::move(_switchStmt.debugData), std::make_unique(FunctionCall{ debugData, - Identifier{debugData, m_dialect.equalityFunction(type)->name}, + Identifier{debugData, m_dialect.equalityFunction()->name}, {std::move(*switchCase.value), std::move(*_switchStmt.expression)} }), std::move(switchCase.body) @@ -214,13 +213,13 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch } else { - if (!m_dialect.discardFunction(type)) + if (!m_dialect.discardFunction()) return {}; return make_vector( makeDiscardCall( debugData, - *m_dialect.discardFunction(type), + *m_dialect.discardFunction(), std::move(*_switchStmt.expression) ), std::move(switchCase.body) diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index a51ca9123..bf8952355 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -54,13 +54,13 @@ DataFlowAnalyzer::DataFlowAnalyzer( { if (m_analyzeStores) { - if (auto const* builtin = _dialect.memoryStoreFunction(YulName{})) + if (auto const* builtin = _dialect.memoryStoreFunction()) m_storeFunctionName[static_cast(StoreLoadLocation::Memory)] = builtin->name; - if (auto const* builtin = _dialect.memoryLoadFunction(YulName{})) + if (auto const* builtin = _dialect.memoryLoadFunction()) m_loadFunctionName[static_cast(StoreLoadLocation::Memory)] = builtin->name; - if (auto const* builtin = _dialect.storageStoreFunction(YulName{})) + if (auto const* builtin = _dialect.storageStoreFunction()) m_storeFunctionName[static_cast(StoreLoadLocation::Storage)] = builtin->name; - if (auto const* builtin = _dialect.storageLoadFunction(YulName{})) + if (auto const* builtin = _dialect.storageLoadFunction()) m_loadFunctionName[static_cast(StoreLoadLocation::Storage)] = builtin->name; } } @@ -446,7 +446,7 @@ std::optional DataFlowAnalyzer::isSimpleLoad( std::optional> DataFlowAnalyzer::isKeccak(Expression const& _expression) const { if (FunctionCall const* funCall = std::get_if(&_expression)) - if (funCall->functionName.name == m_dialect.hashFunction({})) + if (funCall->functionName.name == m_dialect.hashFunction()) if (Identifier const* start = std::get_if(&funCall->arguments.at(0))) if (Identifier const* length = std::get_if(&funCall->arguments.at(1))) return std::make_pair(start->name, length->name); diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index df9847376..cc3f936d9 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -59,7 +59,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) debugData, LiteralKind::Boolean, LiteralValue{true}, - m_dialect.boolType + {} } ); } diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index 5cdde8f0f..3daaea658 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -305,7 +305,7 @@ std::vector InlineModifier::performInline(Statement& _statement, Func if (_value) varDecl.value = std::make_unique(std::move(*_value)); else - varDecl.value = std::make_unique(m_dialect.zeroLiteralForType(varDecl.variables.front().type)); + varDecl.value = std::make_unique(m_dialect.zeroLiteral()); newStatements.emplace_back(std::move(varDecl)); }; diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index a7ee5dd0b..943860a0a 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -62,7 +62,7 @@ void LoadResolver::visit(Expression& _e) tryResolve(_e, StoreLoadLocation::Memory, funCall->arguments); else if (funCall->functionName.name == m_loadFunctionName[static_cast(StoreLoadLocation::Storage)]) tryResolve(_e, StoreLoadLocation::Storage, funCall->arguments); - else if (!m_containsMSize && funCall->functionName.name == m_dialect.hashFunction({})) + else if (!m_containsMSize && funCall->functionName.name == m_dialect.hashFunction()) { Identifier const* start = std::get_if(&funCall->arguments.at(0)); Identifier const* length = std::get_if(&funCall->arguments.at(1)); @@ -151,7 +151,7 @@ void LoadResolver::tryEvaluateKeccak( debugDataOf(_e), LiteralKind::Number, LiteralValue{contentHash}, - m_dialect.defaultType + {} }; } } diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index 7ec579034..d5cb539af 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -42,7 +42,7 @@ std::vector generateMemoryStore( Expression _value ) { - BuiltinFunction const* memoryStoreFunction = _dialect.memoryStoreFunction(_dialect.defaultType); + BuiltinFunction const* memoryStoreFunction = _dialect.memoryStoreFunction(); yulAssert(memoryStoreFunction, ""); std::vector result; result.emplace_back(ExpressionStatement{_debugData, FunctionCall{ @@ -58,7 +58,7 @@ std::vector generateMemoryStore( FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::ConstPtr const& _debugData, LiteralValue const& _mpos) { - BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(_dialect.defaultType); + BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(); yulAssert(memoryLoadFunction, ""); return FunctionCall{ _debugData, diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index 9df51cf7f..c71e8077b 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -105,10 +105,10 @@ void UnusedPruner::operator()(Block& _block) subtractReferences(ReferencesCounter::countReferences(*varDecl.value)); statement = Block{std::move(varDecl.debugData), {}}; } - else if (varDecl.variables.size() == 1 && m_dialect.discardFunction(varDecl.variables.front().type)) + else if (varDecl.variables.size() == 1 && m_dialect.discardFunction()) statement = ExpressionStatement{varDecl.debugData, FunctionCall{ varDecl.debugData, - {varDecl.debugData, m_dialect.discardFunction(varDecl.variables.front().type)->name}, + {varDecl.debugData, m_dialect.discardFunction()->name}, {*std::move(varDecl.value)} }}; } diff --git a/libyul/optimiser/VarDeclInitializer.cpp b/libyul/optimiser/VarDeclInitializer.cpp index 845c7cc41..db6d0127e 100644 --- a/libyul/optimiser/VarDeclInitializer.cpp +++ b/libyul/optimiser/VarDeclInitializer.cpp @@ -40,7 +40,7 @@ void VarDeclInitializer::operator()(Block& _block) if (_varDecl.variables.size() == 1) { - _varDecl.value = std::make_unique(m_dialect.zeroLiteralForType(_varDecl.variables.front().type)); + _varDecl.value = std::make_unique(m_dialect.zeroLiteral()); return {}; } else @@ -48,7 +48,7 @@ void VarDeclInitializer::operator()(Block& _block) OptionalStatements ret{std::vector{}}; for (auto& var: _varDecl.variables) { - std::unique_ptr expr = std::make_unique(m_dialect.zeroLiteralForType(var.type)); + std::unique_ptr expr = std::make_unique(m_dialect.zeroLiteral()); ret->emplace_back(VariableDeclaration{std::move(_varDecl.debugData), {std::move(var)}, std::move(expr)}); } return ret; From f5174e767a01316cd56470de334c233b6dc66cda Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 14 Aug 2024 10:28:28 +0200 Subject: [PATCH 0280/1340] Yul: Remove dialect and printing mode from AsmPrinter --- libsolidity/codegen/CompilerContext.cpp | 4 ++-- libsolidity/codegen/ir/IRGeneratorForStatements.cpp | 2 +- .../codegen/IRGeneratorForStatements.cpp | 2 +- libyul/AsmPrinter.cpp | 4 ---- libyul/AsmPrinter.h | 12 ------------ libyul/Object.cpp | 8 ++------ libyul/Object.h | 6 ------ libyul/ObjectOptimizer.cpp | 2 -- libyul/YulStack.cpp | 2 -- libyul/optimiser/ControlFlowSimplifier.cpp | 3 +-- libyul/optimiser/ControlFlowSimplifier.h | 6 ++---- libyul/optimiser/Suite.cpp | 2 +- test/libyul/Common.cpp | 4 +--- test/libyul/YulOptimizerTest.cpp | 4 ++-- test/tools/yulopti.cpp | 4 ++-- tools/yulPhaser/Program.cpp | 2 +- 16 files changed, 16 insertions(+), 51 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index b1b76a97b..2e94e9f0b 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -491,8 +491,8 @@ void CompilerContext::appendInlineAssembly( { // Store as generated sources, but first re-parse to update the source references. solAssert(m_generatedYulUtilityCode.empty(), ""); - m_generatedYulUtilityCode = yul::AsmPrinter(yul::AsmPrinter::TypePrinting::OmitDefault, dialect)(obj.code()->root()); - std::string code = yul::AsmPrinter{yul::AsmPrinter::TypePrinting::OmitDefault, dialect}(obj.code()->root()); + m_generatedYulUtilityCode = yul::AsmPrinter()(obj.code()->root()); + std::string code = yul::AsmPrinter{}(obj.code()->root()); langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); obj.setCode(yul::Parser(errorReporter, dialect).parse(charStream)); obj.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj)); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 459959604..5fed99d21 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2256,7 +2256,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) solAssert(std::holds_alternative(modified)); - appendCode() << yul::AsmPrinter(yul::AsmPrinter::TypePrinting::Full, _inlineAsm.dialect())(std::get(modified)) << "\n"; + appendCode() << yul::AsmPrinter()(std::get(modified)) << "\n"; return false; } diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index 3c8bcc9bb..6925a434d 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -132,7 +132,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _assembly) CopyTranslate bodyCopier{m_context, _assembly.dialect(), _assembly.annotation().externalReferences}; yul::Statement modified = bodyCopier(_assembly.operations().root()); solAssert(std::holds_alternative(modified)); - m_code << yul::AsmPrinter(yul::AsmPrinter::TypePrinting::Full, _assembly.dialect())(std::get(modified)) << "\n"; + m_code << yul::AsmPrinter()(std::get(modified)) << "\n"; return false; } diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index a5ce47d12..612cb8ee0 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -244,10 +244,6 @@ std::string AsmPrinter::formatTypedName(TypedName _variable) std::string AsmPrinter::appendTypeName(YulName _type) const { - yulAssert( - m_typePrintingMode == TypePrinting::OmitDefault || m_typePrintingMode == TypePrinting::Full, - "unhandled printing mode" - ); if (_type.empty()) return {}; else diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 90fa3a4b5..05b6fb9d8 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -46,21 +46,11 @@ struct Dialect; class AsmPrinter { public: - enum class TypePrinting - { - OmitDefault, - Full - }; - explicit AsmPrinter( - TypePrinting const _typePrintingMode, - Dialect const& _dialect, std::optional>> _sourceIndexToName = {}, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ): - m_typePrintingMode(_typePrintingMode), - m_dialect(_dialect), m_debugInfoSelection(_debugInfoSelection), m_soliditySourceProvider(_soliditySourceProvider) { @@ -102,8 +92,6 @@ class AsmPrinter return formatDebugData(_node.debugData, !isExpression); } - TypePrinting const m_typePrintingMode{}; - Dialect const& m_dialect; std::map m_nameToSourceIndex; langutil::SourceLocation m_lastLocation = {}; langutil::DebugInfoSelection m_debugInfoSelection = {}; diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 57c783b83..c6ba5311a 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -38,14 +38,12 @@ using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; -std::string Data::toString(Dialect const&, AsmPrinter::TypePrinting, DebugInfoSelection const&, CharStreamProvider const*) const +std::string Data::toString(DebugInfoSelection const&, CharStreamProvider const*) const { return "data \"" + name + "\" hex\"" + util::toHex(data) + "\""; } std::string Object::toString( - Dialect const& _dialect, - AsmPrinter::TypePrinting const _printingMode, DebugInfoSelection const& _debugInfoSelection, CharStreamProvider const* _soliditySourceProvider ) const @@ -54,15 +52,13 @@ std::string Object::toString( yulAssert(debugData, "No debug data"); std::string inner = "code " + AsmPrinter( - _printingMode, - _dialect, debugData->sourceNames, _debugInfoSelection, _soliditySourceProvider )(code()->root()); for (auto const& obj: subObjects) - inner += "\n" + obj->toString(_dialect, _printingMode, _debugInfoSelection, _soliditySourceProvider); + inner += "\n" + obj->toString(_debugInfoSelection, _soliditySourceProvider); return debugData->formatUseSrcComment() + diff --git a/libyul/Object.h b/libyul/Object.h index fa9ef96ee..230f97866 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -54,8 +54,6 @@ struct ObjectNode /// Can be empty since .yul files can also just contain code, without explicitly placing it in an object. std::string name; virtual std::string toString( - Dialect const& _dialect, - AsmPrinter::TypePrinting printingMode, langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const = 0; @@ -72,8 +70,6 @@ struct Data: public ObjectNode bytes data; std::string toString( - Dialect const& _dialect, - AsmPrinter::TypePrinting printingMode, langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const override; @@ -97,8 +93,6 @@ struct Object: public ObjectNode public: /// @returns a (parseable) string representation. std::string toString( - Dialect const& _dialect, - AsmPrinter::TypePrinting printingMode = AsmPrinter::TypePrinting::Full, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ) const override; diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index eaaac97d5..3694367c5 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -142,8 +142,6 @@ std::optional ObjectOptimizer::calculateCacheKey( ) { AsmPrinter asmPrinter( - AsmPrinter::TypePrinting::OmitDefault, - languageToDialect(_settings.language, _settings.evmVersion), _debugData.sourceNames, DebugInfoSelection::All() ); diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index eac84ae3a..1f57eda48 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -351,8 +351,6 @@ std::string YulStack::print( yulAssert(m_parserResult, ""); yulAssert(m_parserResult->hasCode(), ""); return m_parserResult->toString( - languageToDialect(m_language, m_evmVersion), - AsmPrinter::TypePrinting::OmitDefault, m_debugInfoSelection, _soliditySourceProvider ) + "\n"; diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index 2d0dbb467..2bd505a1c 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -72,8 +72,7 @@ void removeEmptyCasesFromSwitch(Switch& _switchStmt) void ControlFlowSimplifier::run(OptimiserStepContext& _context, Block& _ast) { - TypeInfo typeInfo(_context.dialect, _ast); - ControlFlowSimplifier{_context.dialect, typeInfo}(_ast); + ControlFlowSimplifier{_context.dialect}(_ast); } void ControlFlowSimplifier::operator()(Block& _block) diff --git a/libyul/optimiser/ControlFlowSimplifier.h b/libyul/optimiser/ControlFlowSimplifier.h index 3ebbe7c9a..0f0e725cd 100644 --- a/libyul/optimiser/ControlFlowSimplifier.h +++ b/libyul/optimiser/ControlFlowSimplifier.h @@ -63,9 +63,8 @@ class ControlFlowSimplifier: public ASTModifier void visit(Statement& _st) override; private: - ControlFlowSimplifier(Dialect const& _dialect, TypeInfo const& _typeInfo): - m_dialect(_dialect), - m_typeInfo(_typeInfo) + explicit ControlFlowSimplifier(Dialect const& _dialect): + m_dialect(_dialect) {} void simplify(std::vector& _statements); @@ -74,7 +73,6 @@ class ControlFlowSimplifier: public ASTModifier std::optional> reduceSingleCaseSwitch(Switch& _switchStmt) const; Dialect const& m_dialect; - TypeInfo const& m_typeInfo; size_t m_numBreakStatements = 0; size_t m_numContinueStatements = 0; }; diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index a06f48a7f..d7043e42f 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -520,7 +520,7 @@ void OptimiserSuite::runSequence(std::vector const& _steps, Block& else { std::cout << "== Running " << step << " changed the AST." << std::endl; - std::cout << AsmPrinter{AsmPrinter::TypePrinting::Full, m_context.dialect}(_ast) << std::endl; + std::cout << AsmPrinter{}(_ast) << std::endl; copy = std::make_unique(std::get(ASTCopier{}(_ast))); } } diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index a0c00c90d..8980adcb1 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -96,9 +96,7 @@ yul::Block yul::test::disambiguate(std::string const& _source) std::string yul::test::format(std::string const& _source) { - auto const version = solidity::test::CommonOptions::get().evmVersion(); - Dialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(version); - return yul::AsmPrinter(yul::AsmPrinter::TypePrinting::Full, dialect)(parse(_source).first->root()); + return yul::AsmPrinter()(parse(_source).first->root()); } namespace diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 048eb7145..7f2f5815a 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -81,9 +81,9 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co auto optimizedObject = tester.optimizedObject(); std::string printedOptimizedObject; if (optimizedObject->subObjects.empty()) - printedOptimizedObject = AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, *m_dialect}(optimizedObject->code()->root()); + printedOptimizedObject = AsmPrinter{}(optimizedObject->code()->root()); else - printedOptimizedObject = optimizedObject->toString(*m_dialect); + printedOptimizedObject = optimizedObject->toString(); // Re-parse new code for compilability if (!std::get<0>(parse(_stream, _linePrefix, _formatted, printedOptimizedObject))) diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index faab89e79..891f39c43 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -180,7 +180,7 @@ class YulOpti parse(_source); disambiguate(); OptimiserSuite{m_context}.runSequence(_steps, *m_astRoot); - std::cout << AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, m_dialect}(*m_astRoot) << std::endl; + std::cout << AsmPrinter{}(*m_astRoot) << std::endl; } void runInteractive(std::string _source, bool _disambiguated = false) @@ -228,7 +228,7 @@ class YulOpti *m_astRoot ); } - _source = AsmPrinter{AsmPrinter::TypePrinting::OmitDefault, m_dialect}(*m_astRoot); + _source = AsmPrinter{}(*m_astRoot); } catch (...) { diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 14b640649..bb9eebc4b 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -105,7 +105,7 @@ void Program::optimise(std::vector const& _optimisationSteps) std::ostream& phaser::operator<<(std::ostream& _stream, Program const& _program) { - return _stream << AsmPrinter(AsmPrinter::TypePrinting::Full, _program.m_dialect)(_program.m_ast->root()); + return _stream << AsmPrinter()(_program.m_ast->root()); } std::string Program::toJson() const From 0d0f2771654b14ee0e8d317a5eb22dbff8eab332 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:19:02 +0200 Subject: [PATCH 0281/1340] Yul: Remove types from AST --- Changelog.md | 1 + libsolidity/analysis/ReferencesResolver.cpp | 2 +- .../codegen/ir/IRGeneratorForStatements.cpp | 2 +- libyul/AST.h | 12 +- libyul/ASTForward.h | 2 +- libyul/AsmAnalysis.cpp | 178 ++---- libyul/AsmAnalysis.h | 20 +- libyul/AsmJsonConverter.cpp | 6 +- libyul/AsmJsonConverter.h | 2 +- libyul/AsmJsonImporter.cpp | 20 +- libyul/AsmJsonImporter.h | 2 +- libyul/AsmParser.cpp | 30 +- libyul/AsmParser.h | 3 +- libyul/AsmPrinter.cpp | 23 +- libyul/AsmPrinter.h | 5 +- libyul/CMakeLists.txt | 2 - libyul/Dialect.cpp | 2 +- libyul/Scope.cpp | 7 +- libyul/Scope.h | 13 +- libyul/ScopeFiller.cpp | 12 +- libyul/ScopeFiller.h | 4 +- libyul/Utilities.cpp | 4 +- libyul/backends/evm/ConstantOptimiser.cpp | 2 +- .../backends/evm/ControlFlowGraphBuilder.cpp | 6 +- libyul/backends/evm/EVMCodeTransform.cpp | 14 +- libyul/backends/evm/EVMCodeTransform.h | 4 +- .../evm/OptimizedEVMCodeTransform.cpp | 12 +- libyul/optimiser/ASTCopier.cpp | 4 +- libyul/optimiser/ASTCopier.h | 2 +- libyul/optimiser/BlockHasher.cpp | 1 - libyul/optimiser/ControlFlowSimplifier.cpp | 1 - libyul/optimiser/ControlFlowSimplifier.h | 1 - libyul/optimiser/DataFlowAnalyzer.h | 2 +- libyul/optimiser/ExpressionSimplifier.cpp | 2 +- libyul/optimiser/ExpressionSplitter.cpp | 8 +- libyul/optimiser/ExpressionSplitter.h | 8 +- libyul/optimiser/ForLoopConditionIntoBody.cpp | 3 +- libyul/optimiser/FullInliner.cpp | 4 +- libyul/optimiser/FunctionSpecializer.cpp | 2 +- libyul/optimiser/LoadResolver.cpp | 6 +- libyul/optimiser/NameDisplacer.cpp | 2 +- libyul/optimiser/NameSimplifier.cpp | 4 +- libyul/optimiser/NameSimplifier.h | 2 +- libyul/optimiser/SSATransform.cpp | 36 +- libyul/optimiser/SSAValueTracker.h | 2 +- libyul/optimiser/SimplificationRules.cpp | 2 +- libyul/optimiser/StackLimitEvader.cpp | 2 +- libyul/optimiser/StackToMemoryMover.cpp | 31 +- libyul/optimiser/StackToMemoryMover.h | 6 +- libyul/optimiser/SyntacticalEquality.cpp | 11 +- libyul/optimiser/SyntacticalEquality.h | 2 +- libyul/optimiser/TypeInfo.cpp | 103 ---- libyul/optimiser/TypeInfo.h | 65 --- libyul/optimiser/UnusedFunctionsCommon.cpp | 7 +- libyul/optimiser/UnusedPruner.cpp | 2 +- libyul/optimiser/UnusedStoreEliminator.cpp | 6 +- libyul/optimiser/VarNameCleaner.cpp | 14 +- libyul/optimiser/VarNameCleaner.h | 2 +- test/libyul/StackShufflingTest.cpp | 4 +- test/libyul/YulOptimizerTestCommon.cpp | 4 +- test/libyul/yulSyntaxTests/invalid_type.yul | 2 +- test/libyul/yulSyntaxTests/invalid_type2.yul | 3 +- test/libyul/yulSyntaxTests/invalid_type3.yul | 4 +- test/libyul/yulSyntaxTests/invalid_type4.yul | 3 +- .../yulSyntaxTests/literal_invalid_type.yul | 4 +- .../more_than_256_analysis_errors.yul | 512 +++++++++--------- 66 files changed, 481 insertions(+), 788 deletions(-) delete mode 100644 libyul/optimiser/TypeInfo.cpp delete mode 100644 libyul/optimiser/TypeInfo.h diff --git a/Changelog.md b/Changelog.md index 288136dd9..04bfa9295 100644 --- a/Changelog.md +++ b/Changelog.md @@ -19,6 +19,7 @@ Compiler Features: * Standard JSON Interface: Do not perform IR optimization when only unoptimized IR is requested. * Standard JSON Interface: Add ``transientStorageLayout`` output. * Yul: Drop the deprecated typed Yul dialect that was only accessible via ``--yul`` in the CLI. + * Yul: The presence of types in untyped Yul dialects is now a parser error. * Yul Optimizer: Caching of optimized IR to speed up optimization of contracts with bytecode dependencies. * Yul Optimizer: The optimizer now treats some previously unrecognized identical literals as identical. * Commandline Interface: Allow the use of ``--asm-json`` output option in assembler mode to export EVM assembly of the contracts in JSON format. diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index bb3b20e93..079bbf33c 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -272,7 +272,7 @@ void ReferencesResolver::operator()(yul::FunctionDefinition const& _function) { solAssert(nativeLocationOf(_function) == originLocationOf(_function), ""); validateYulIdentifierName(_function.name, nativeLocationOf(_function)); - for (yul::TypedName const& varName: _function.parameters + _function.returnVariables) + for (yul::NameWithDebugData const& varName: _function.parameters + _function.returnVariables) { solAssert(nativeLocationOf(varName) == originLocationOf(varName), ""); validateYulIdentifierName(varName.name, nativeLocationOf(varName)); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 5fed99d21..c3cd69f43 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -204,7 +204,7 @@ struct CopyTranslate: public yul::ASTCopier solAssert(false); if (isDigit(value.front())) - return yul::Literal{_identifier.debugData, yul::LiteralKind::Number, yul::valueOfNumberLiteral(value), {}}; + return yul::Literal{_identifier.debugData, yul::LiteralKind::Number, yul::valueOfNumberLiteral(value)}; else return yul::Identifier{_identifier.debugData, yul::YulName{value}}; } diff --git a/libyul/AST.h b/libyul/AST.h index 6b9682580..f51846280 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -36,10 +36,8 @@ namespace solidity::yul { -using Type = YulName; - -struct TypedName { langutil::DebugData::ConstPtr debugData; YulName name; Type type; }; -using TypedNameList = std::vector; +struct NameWithDebugData { langutil::DebugData::ConstPtr debugData; YulName name; }; +using NameWithDebugDataList = std::vector; /// Literal number or string (up to 32 bytes) enum class LiteralKind { Number, Boolean, String }; @@ -68,7 +66,7 @@ class LiteralValue { std::optional m_numericValue; std::shared_ptr m_stringValue; }; -struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; LiteralValue value; Type type; }; +struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; LiteralValue value; }; /// External / internal identifier or label reference struct Identifier { langutil::DebugData::ConstPtr debugData; YulName name; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand @@ -82,11 +80,11 @@ struct FunctionCall { langutil::DebugData::ConstPtr debugData; Identifier functi /// Statement that contains only a single expression struct ExpressionStatement { langutil::DebugData::ConstPtr debugData; Expression expression; }; /// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted -struct VariableDeclaration { langutil::DebugData::ConstPtr debugData; TypedNameList variables; std::unique_ptr value; }; +struct VariableDeclaration { langutil::DebugData::ConstPtr debugData; NameWithDebugDataList variables; std::unique_ptr value; }; /// Block that creates a scope (frees declared stack variables) struct Block { langutil::DebugData::ConstPtr debugData; std::vector statements; }; /// Function definition ("function f(a, b) -> (d, e) { ... }") -struct FunctionDefinition { langutil::DebugData::ConstPtr debugData; YulName name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; +struct FunctionDefinition { langutil::DebugData::ConstPtr debugData; YulName name; NameWithDebugDataList parameters; NameWithDebugDataList returnVariables; Block body; }; /// Conditional execution without "else" part. struct If { langutil::DebugData::ConstPtr debugData; std::unique_ptr condition; Block body; }; /// Switch case or default case diff --git a/libyul/ASTForward.h b/libyul/ASTForward.h index f6fa09387..8aba4f248 100644 --- a/libyul/ASTForward.h +++ b/libyul/ASTForward.h @@ -48,7 +48,7 @@ struct ExpressionStatement; struct Block; class AST; -struct TypedName; +struct NameWithDebugData; using Expression = std::variant; using Statement = std::variant; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 908e30e62..d039b3b47 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -109,9 +109,8 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( return analysisInfo; } -std::vector AsmAnalyzer::operator()(Literal const& _literal) +size_t AsmAnalyzer::operator()(Literal const& _literal) { - expectValidType(_literal.type, nativeLocationOf(_literal)); bool erroneousLiteralValue = false; if (_literal.kind == LiteralKind::String && !_literal.value.unlimited() && _literal.value.hint() && _literal.value.hint()->size() > 32) { @@ -128,22 +127,14 @@ std::vector AsmAnalyzer::operator()(Literal const& _literal) m_errorReporter.typeError(6708_error, nativeLocationOf(_literal), "Number literal too large (> 256 bits)"); } - if (_literal.kind == LiteralKind::Boolean && !_literal.type.empty()) - m_errorReporter.typeError( - 5170_error, - nativeLocationOf(_literal), - "Invalid type \"" + _literal.type.str() + "\" for literal \"" + formatLiteral(_literal) + "\"." - ); - yulAssert(erroneousLiteralValue ^ validLiteral(_literal), "Invalid literal after validating it through AsmAnalyzer."); - return {_literal.type}; + return 1; } -std::vector AsmAnalyzer::operator()(Identifier const& _identifier) +size_t AsmAnalyzer::operator()(Identifier const& _identifier) { yulAssert(!_identifier.name.empty(), ""); auto watcher = m_errorReporter.errorWatcher(); - YulName type{}; if (m_currentScope->lookup(_identifier.name, GenericVisitor{ [&](Scope::Variable const& _var) @@ -154,7 +145,6 @@ std::vector AsmAnalyzer::operator()(Identifier const& _identifier) nativeLocationOf(_identifier), "Variable " + _identifier.name.str() + " used before it was declared." ); - type = _var.type; }, [&](Scope::Function const&) { @@ -191,21 +181,21 @@ std::vector AsmAnalyzer::operator()(Identifier const& _identifier) } - return {type}; + return 1; } void AsmAnalyzer::operator()(ExpressionStatement const& _statement) { auto watcher = m_errorReporter.errorWatcher(); - std::vector types = std::visit(*this, _statement.expression); - if (watcher.ok() && !types.empty()) + size_t numReturns = std::visit(*this, _statement.expression); + if (watcher.ok() && numReturns > 0) m_errorReporter.typeError( 3083_error, nativeLocationOf(_statement), "Top-level expressions are not supposed to return values (this expression returns " + - std::to_string(types.size()) + + std::to_string(numReturns) + " value" + - (types.size() == 1 ? "" : "s") + + (numReturns == 1 ? "" : "s") + "). Use ``pop()`` or assign them." ); } @@ -227,9 +217,9 @@ void AsmAnalyzer::operator()(Assignment const& _assignment) " occurs multiple times on the left-hand side of the assignment." ); - std::vector types = std::visit(*this, *_assignment.value); + size_t numRhsValues = std::visit(*this, *_assignment.value); - if (types.size() != numVariables) + if (numRhsValues != numVariables) m_errorReporter.declarationError( 8678_error, nativeLocationOf(_assignment), @@ -238,13 +228,12 @@ void AsmAnalyzer::operator()(Assignment const& _assignment) "\" does not match number of values (" + std::to_string(numVariables) + " vs. " + - std::to_string(types.size()) + + std::to_string(numRhsValues) + ")" ); for (size_t i = 0; i < numVariables; ++i) - if (i < types.size()) - checkAssignment(_assignment.variableNames[i], types[i]); + checkAssignment(_assignment.variableNames[i]); } void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) @@ -261,13 +250,12 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) for (auto const& variable: _varDecl.variables) { expectValidIdentifier(variable.name, nativeLocationOf(variable)); - expectValidType(variable.type, nativeLocationOf(variable)); } if (_varDecl.value) { - std::vector types = std::visit(*this, *_varDecl.value); - if (types.size() != numVariables) + size_t numValues = std::visit(*this, *_varDecl.value); + if (numValues != numVariables) m_errorReporter.declarationError( 3812_error, nativeLocationOf(_varDecl), @@ -276,26 +264,12 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) + "\": " + std::to_string(numVariables) + " variables and " + - std::to_string(types.size()) + + std::to_string(numValues) + " values." ); - - for (size_t i = 0; i < _varDecl.variables.size(); ++i) - { - YulName givenType{}; - if (i < types.size()) - givenType = types[i]; - TypedName const& variable = _varDecl.variables[i]; - if (variable.type != givenType) - m_errorReporter.typeError( - 3947_error, - nativeLocationOf(variable), - "Assigning value of type \"" + givenType.str() + "\" to variable of type \"" + variable.type.str() + "\"." - ); - } } - for (TypedName const& variable: _varDecl.variables) + for (NameWithDebugData const& variable: _varDecl.variables) m_activeVariables.insert(&std::get( m_currentScope->identifiers.at(variable.name)) ); @@ -311,19 +285,18 @@ void AsmAnalyzer::operator()(FunctionDefinition const& _funDef) for (auto const& var: _funDef.parameters + _funDef.returnVariables) { expectValidIdentifier(var.name, nativeLocationOf(var)); - expectValidType(var.type, nativeLocationOf(var)); m_activeVariables.insert(&std::get(varScope.identifiers.at(var.name))); } (*this)(_funDef.body); } -std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) +size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) { yulAssert(!_funCall.functionName.name.empty(), ""); auto watcher = m_errorReporter.errorWatcher(); - std::vector const* parameterTypes = nullptr; - std::vector const* returnTypes = nullptr; + std::optional numParameters; + std::optional numReturns; std::vector> const* literalArguments = nullptr; if (BuiltinFunction const* f = m_dialect.builtin(_funCall.functionName.name)) @@ -354,8 +327,8 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) "The use of transient storage for reentrancy guards that are cleared at the end of the call is safe." ); - parameterTypes = &f->parameters; - returnTypes = &f->returns; + numParameters = f->parameters.size(); + numReturns = f->returns.size(); if (!f->literalArguments.empty()) literalArguments = &f->literalArguments; @@ -373,8 +346,8 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) }, [&](Scope::Function const& _fun) { - parameterTypes = &_fun.arguments; - returnTypes = &_fun.returns; + numParameters = _fun.numArguments; + numReturns = _fun.numReturns; } })) { @@ -397,17 +370,17 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) yulAssert(!watcher.ok(), "Expected a reported error."); } - if (parameterTypes && _funCall.arguments.size() != parameterTypes->size()) + if (numParameters && _funCall.arguments.size() != *numParameters) m_errorReporter.typeError( 7000_error, nativeLocationOf(_funCall.functionName), "Function \"" + _funCall.functionName.name.str() + "\" expects " + - std::to_string(parameterTypes->size()) + + std::to_string(*numParameters) + " arguments but got " + std::to_string(_funCall.arguments.size()) + "." ); - std::vector argTypes; + size_t numArgs{0}; for (size_t i = _funCall.arguments.size(); i > 0; i--) { Expression const& arg = _funCall.arguments[i - 1]; @@ -453,33 +426,30 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) "The \"verbatim_*\" builtins cannot be used with empty bytecode." ); } - argTypes.emplace_back(expectUnlimitedStringLiteral(std::get(arg))); + expectUnlimitedStringLiteral(std::get(arg)); + ++numArgs; continue; } } - argTypes.emplace_back(expectExpression(arg)); + expectExpression(arg); + ++numArgs; } - std::reverse(argTypes.begin(), argTypes.end()); - - if (parameterTypes && parameterTypes->size() == argTypes.size()) - for (size_t i = 0; i < parameterTypes->size(); ++i) - expectType((*parameterTypes)[i], argTypes[i], nativeLocationOf(_funCall.arguments[i])); if (watcher.ok()) { - yulAssert(parameterTypes && parameterTypes->size() == argTypes.size(), ""); - yulAssert(returnTypes, ""); - return *returnTypes; + yulAssert(numParameters && numParameters == numArgs, ""); + yulAssert(numReturns, ""); + return *numReturns; } - else if (returnTypes) - return std::vector(returnTypes->size(), YulName{}); + else if (numReturns) + return *numReturns; else return {}; } void AsmAnalyzer::operator()(If const& _if) { - expectBoolExpression(*_if.condition); + expectExpression(*_if.condition); (*this)(_if.body); } @@ -495,7 +465,7 @@ void AsmAnalyzer::operator()(Switch const& _switch) "\"switch\" statement with only a default case." ); - YulName valueType = expectExpression(*_switch.expression); + expectExpression(*_switch.expression); std::set cases; for (auto const& _case: _switch.cases) @@ -504,8 +474,6 @@ void AsmAnalyzer::operator()(Switch const& _switch) { auto watcher = m_errorReporter.errorWatcher(); - expectType(valueType, _case.value->type, nativeLocationOf(*_case.value)); - // We cannot use "expectExpression" here because *_case.value is not an // Expression and would be converted to an Expression otherwise. (*this)(*_case.value); @@ -537,7 +505,7 @@ void AsmAnalyzer::operator()(ForLoop const& _for) // condition, the body and the post part inside. m_currentScope = &scope(&_for.pre); - expectBoolExpression(*_for.condition); + expectExpression(*_for.condition); // backup outer for-loop & create new state auto outerForLoop = m_currentForLoop; m_currentForLoop = &_for; @@ -560,50 +528,30 @@ void AsmAnalyzer::operator()(Block const& _block) m_currentScope = previousScope; } -YulName AsmAnalyzer::expectExpression(Expression const& _expr) +void AsmAnalyzer::expectExpression(Expression const& _expr) { - std::vector types = std::visit(*this, _expr); - if (types.size() != 1) + size_t numValues = std::visit(*this, _expr); + if (numValues != 1) m_errorReporter.typeError( 3950_error, nativeLocationOf(_expr), "Expected expression to evaluate to one value, but got " + - std::to_string(types.size()) + + std::to_string(numValues) + " values instead." ); - return types.empty() ? YulName{} : types.front(); } -YulName AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal) +void AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal) { yulAssert(_literal.kind == LiteralKind::String); - yulAssert(_literal.type.empty()); yulAssert(_literal.value.unlimited()); - - return {_literal.type}; -} - -void AsmAnalyzer::expectBoolExpression(Expression const& _expr) -{ - YulName type = expectExpression(_expr); - static YulName boolType = {}; - if (type != boolType) - m_errorReporter.typeError( - 1733_error, - nativeLocationOf(_expr), - "Expected a value of boolean type \"" + - boolType.str() + - "\" but got \"" + - type.str() + - "\"" - ); } -void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulName _valueType) +void AsmAnalyzer::checkAssignment(Identifier const& _variable) { yulAssert(!_variable.name.empty(), ""); auto watcher = m_errorReporter.errorWatcher(); - std::optional variableType = std::nullopt; + bool hasVariable = false; bool found = false; if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name)) { @@ -624,7 +572,7 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulName _valueTyp "Variable " + _variable.name.str() + " used before it was declared." ); else - variableType = std::get(*var).type; + hasVariable = true; found = true; } else if (m_resolver) @@ -633,25 +581,15 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulName _valueTyp if (m_resolver(_variable, yul::IdentifierContext::LValue, insideFunction)) { found = true; - variableType = YulName{}; + hasVariable = true; } } if (!found && watcher.ok()) // Only add message if the callback did not. m_errorReporter.declarationError(4634_error, nativeLocationOf(_variable), "Variable not found or variable not lvalue."); - if (variableType && *variableType != _valueType) - m_errorReporter.typeError( - 9547_error, - nativeLocationOf(_variable), - "Assigning a value of type \"" + - _valueType.str() + - "\" to a variable of type \"" + - variableType->str() + - "\"." - ); - yulAssert(!watcher.ok() || variableType, ""); + yulAssert(!watcher.ok() || hasVariable, ""); } Scope& AsmAnalyzer::scope(Block const* _block) @@ -687,26 +625,6 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons ); } -void AsmAnalyzer::expectValidType(YulName _type, SourceLocation const& _location) -{ - if (!_type.empty()) - m_errorReporter.typeError( - 5473_error, - _location, - fmt::format("\"{}\" is not a valid type (user defined types are not yet supported).", _type.str()) - ); -} - -void AsmAnalyzer::expectType(YulName _expectedType, YulName _givenType, SourceLocation const& _location) -{ - if (_expectedType != _givenType) - m_errorReporter.typeError( - 3781_error, - _location, - fmt::format("Expected a value of type \"{}\" but got \"{}\".", _expectedType.str(), _givenType.str()) - ); -} - bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location) { // NOTE: This function uses the default EVM version instead of the currently selected one. diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index d479a9970..d01ecc190 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -84,13 +84,13 @@ class AsmAnalyzer std::set const& _qualifiedDataNames ); - std::vector operator()(Literal const& _literal); - std::vector operator()(Identifier const&); + size_t operator()(Literal const& _literal); + size_t operator()(Identifier const&); void operator()(ExpressionStatement const&); void operator()(Assignment const& _assignment); void operator()(VariableDeclaration const& _variableDeclaration); void operator()(FunctionDefinition const& _functionDefinition); - std::vector operator()(FunctionCall const& _functionCall); + size_t operator()(FunctionCall const& _functionCall); void operator()(If const& _if); void operator()(Switch const& _switch); void operator()(ForLoop const& _forLoop); @@ -104,20 +104,14 @@ class AsmAnalyzer private: /// Visits the expression, expects that it evaluates to exactly one value and /// returns the type. Reports errors on errors and returns the default type. - YulName expectExpression(Expression const& _expr); - YulName expectUnlimitedStringLiteral(Literal const& _literal); - /// Visits the expression and expects it to return a single boolean value. - /// Reports an error otherwise. - void expectBoolExpression(Expression const& _expr); + void expectExpression(Expression const& _expr); + void expectUnlimitedStringLiteral(Literal const& _literal); - /// Verifies that a variable to be assigned to exists, can be assigned to - /// and has the same type as the value. - void checkAssignment(Identifier const& _variable, YulName _valueType); + /// Verifies that a variable to be assigned to exists and can be assigned to. + void checkAssignment(Identifier const& _variable); Scope& scope(Block const* _block); void expectValidIdentifier(YulName _identifier, langutil::SourceLocation const& _location); - void expectValidType(YulName _type, langutil::SourceLocation const& _location); - void expectType(YulName _expectedType, YulName _givenType, langutil::SourceLocation const& _location); bool validateInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location); bool validateInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location); diff --git a/libyul/AsmJsonConverter.cpp b/libyul/AsmJsonConverter.cpp index 604754975..d85b96f8f 100644 --- a/libyul/AsmJsonConverter.cpp +++ b/libyul/AsmJsonConverter.cpp @@ -37,12 +37,12 @@ Json AsmJsonConverter::operator()(Block const& _node) const return ret; } -Json AsmJsonConverter::operator()(TypedName const& _node) const +Json AsmJsonConverter::operator()(NameWithDebugData const& _node) const { yulAssert(!_node.name.empty(), "Invalid variable name."); Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulTypedName"); ret["name"] = _node.name.str(); - ret["type"] = _node.type.str(); + ret["type"] = ""; return ret; } @@ -63,7 +63,7 @@ Json AsmJsonConverter::operator()(Literal const& _node) const ret["hexValue"] = util::toHex(util::asBytes(formatLiteral(_node))); break; } - ret["type"] = _node.type.str(); + ret["type"] = ""; { auto const formattedLiteral = formatLiteral(_node); if (util::validateUTF8(formattedLiteral)) diff --git a/libyul/AsmJsonConverter.h b/libyul/AsmJsonConverter.h index 9c4b5d5e8..523825830 100644 --- a/libyul/AsmJsonConverter.h +++ b/libyul/AsmJsonConverter.h @@ -44,7 +44,7 @@ class AsmJsonConverter: public boost::static_visitor explicit AsmJsonConverter(std::optional _sourceIndex): m_sourceIndex(_sourceIndex) {} Json operator()(Block const& _node) const; - Json operator()(TypedName const& _node) const; + Json operator()(NameWithDebugData const& _node) const; Json operator()(Literal const& _node) const; Json operator()(Identifier const& _node) const; Json operator()(Assignment const& _node) const; diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index 65ff22999..6de7bb6ab 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -74,12 +74,11 @@ Json AsmJsonImporter::member(Json const& _node, std::string const& _name) return _node[_name]; } -TypedName AsmJsonImporter::createTypedName(Json const& _node) +NameWithDebugData AsmJsonImporter::createNameWithDebugData(Json const& _node) { - auto typedName = createAsmNode(_node); - typedName.type = YulName{member(_node, "type").get()}; - typedName.name = YulName{member(_node, "name").get()}; - return typedName; + auto nameWithDebugData = createAsmNode(_node); + nameWithDebugData.name = YulName{member(_node, "name").get()}; + return nameWithDebugData; } Statement AsmJsonImporter::createStatement(Json const& _node) @@ -176,7 +175,10 @@ Literal AsmJsonImporter::createLiteral(Json const& _node) value = util::asString(util::fromHex(member(_node, "hexValue").get())); else value = member(_node, "value").get(); - lit.type = YulName{member(_node, "type").get()}; + { + auto const typeNode = member(_node, "type"); + yulAssert(typeNode.empty() || typeNode.get().empty()); + } if (kind == "number") { langutil::CharStream charStream(value, ""); @@ -263,7 +265,7 @@ VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json const& _node { auto varDec = createAsmNode(_node); for (auto const& var: member(_node, "variables")) - varDec.variables.emplace_back(createTypedName(var)); + varDec.variables.emplace_back(createNameWithDebugData(var)); if (_node.contains("value")) varDec.value = std::make_unique(createExpression(member(_node, "value"))); @@ -278,11 +280,11 @@ FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json const& _node) if (_node.contains("parameters")) for (auto const& var: member(_node, "parameters")) - funcDef.parameters.emplace_back(createTypedName(var)); + funcDef.parameters.emplace_back(createNameWithDebugData(var)); if (_node.contains("returnVariables")) for (auto const& var: member(_node, "returnVariables")) - funcDef.returnVariables.emplace_back(createTypedName(var)); + funcDef.returnVariables.emplace_back(createNameWithDebugData(var)); funcDef.body = createBlock(member(_node, "body")); return funcDef; diff --git a/libyul/AsmJsonImporter.h b/libyul/AsmJsonImporter.h index d835e99e3..f3df8c178 100644 --- a/libyul/AsmJsonImporter.h +++ b/libyul/AsmJsonImporter.h @@ -57,7 +57,7 @@ class AsmJsonImporter std::vector createStatementVector(Json const& _array); std::vector createExpressionVector(Json const& _array); - yul::TypedName createTypedName(Json const& _node); + yul::NameWithDebugData createNameWithDebugData(Json const& _node); yul::Literal createLiteral(Json const& _node); yul::Leave createLeave(Json const& _node); yul::Identifier createIdentifier(Json const& _node); diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index a2a4c36dc..bd890c4aa 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -567,18 +567,20 @@ std::variant Parser::parseLiteralOrIdentifier(bool _unlimit break; } + auto const beginOfLiteralLoc = currentLocation(); Literal literal{ createDebugData(), kind, - valueOfLiteral(currentLiteral(), kind, _unlimitedLiteralArgument && kind == LiteralKind::String), - {} + valueOfLiteral(currentLiteral(), kind, _unlimitedLiteralArgument && kind == LiteralKind::String) }; advance(); if (currentToken() == Token::Colon) { expectToken(Token::Colon); updateLocationEndFrom(literal.debugData, currentLocation()); - literal.type = expectAsmIdentifier(); + auto const loc = SourceLocation::smallestCovering(beginOfLiteralLoc, currentLocation()); + std::ignore = expectAsmIdentifier(); + expectUntyped(loc); } return literal; @@ -599,7 +601,7 @@ VariableDeclaration Parser::parseVariableDeclaration() expectToken(Token::Let); while (true) { - varDecl.variables.emplace_back(parseTypedName()); + varDecl.variables.emplace_back(parseNameWithDebugData()); if (currentToken() == Token::Comma) expectToken(Token::Comma); else @@ -637,7 +639,7 @@ FunctionDefinition Parser::parseFunctionDefinition() expectToken(Token::LParen); while (currentToken() != Token::RParen) { - funDef.parameters.emplace_back(parseTypedName()); + funDef.parameters.emplace_back(parseNameWithDebugData()); if (currentToken() == Token::RParen) break; expectToken(Token::Comma); @@ -648,7 +650,7 @@ FunctionDefinition Parser::parseFunctionDefinition() expectToken(Token::RightArrow); while (true) { - funDef.returnVariables.emplace_back(parseTypedName()); + funDef.returnVariables.emplace_back(parseNameWithDebugData()); if (currentToken() == Token::LBrace) break; expectToken(Token::Comma); @@ -695,19 +697,20 @@ FunctionCall Parser::parseCall(std::variant&& _initialOp) return ret; } -TypedName Parser::parseTypedName() +NameWithDebugData Parser::parseNameWithDebugData() { RecursionGuard recursionGuard(*this); - TypedName typedName = createWithDebugData(); + NameWithDebugData typedName = createWithDebugData(); + auto const locNameStart = currentLocation(); typedName.name = expectAsmIdentifier(); if (currentToken() == Token::Colon) { expectToken(Token::Colon); updateLocationEndFrom(typedName.debugData, currentLocation()); - typedName.type = expectAsmIdentifier(); + auto const loc = SourceLocation::smallestCovering(locNameStart, currentLocation()); + std::ignore = expectAsmIdentifier(); + expectUntyped(loc); } - else - typedName.type = {}; return typedName; } @@ -756,3 +759,8 @@ bool Parser::isValidNumberLiteral(std::string const& _literal) else return _literal.find_first_not_of("0123456789") == std::string::npos; } + +void Parser::expectUntyped(SourceLocation const& loc) +{ + m_errorReporter.parserError(5473_error, loc, "Types are not valid in untyped Yul."); +} diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index dd206b5b1..42ed2ca84 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -145,8 +145,9 @@ class Parser: public langutil::ParserBase VariableDeclaration parseVariableDeclaration(); FunctionDefinition parseFunctionDefinition(); FunctionCall parseCall(std::variant&& _initialOp); - TypedName parseTypedName(); + NameWithDebugData parseNameWithDebugData(); YulName expectAsmIdentifier(); + void expectUntyped(langutil::SourceLocation const& loc); /// Reports an error if we are currently not inside the body part of a for loop. void checkBreakContinuePosition(std::string const& _which); diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 612cb8ee0..5841fdfd3 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -54,12 +53,12 @@ std::string AsmPrinter::operator()(Literal const& _literal) { case LiteralKind::Number: case LiteralKind::Boolean: - return locationComment + formattedValue + appendTypeName(_literal.type); + return locationComment + formattedValue; case LiteralKind::String: break; } - return locationComment + escapeAndQuoteString(formattedValue) + appendTypeName(_literal.type); + return locationComment + escapeAndQuoteString(formattedValue); } std::string AsmPrinter::operator()(Identifier const& _identifier) @@ -94,7 +93,7 @@ std::string AsmPrinter::operator()(VariableDeclaration const& _variableDeclarati out += "let "; out += boost::algorithm::join( _variableDeclaration.variables | ranges::views::transform( - [this](TypedName argument) { return formatTypedName(argument); } + [this](NameWithDebugData argument) { return formatNameWithDebugData(argument); } ), ", " ); @@ -114,7 +113,7 @@ std::string AsmPrinter::operator()(FunctionDefinition const& _functionDefinition out += "function " + _functionDefinition.name.str() + "("; out += boost::algorithm::join( _functionDefinition.parameters | ranges::views::transform( - [this](TypedName argument) { return formatTypedName(argument); } + [this](NameWithDebugData argument) { return formatNameWithDebugData(argument); } ), ", " ); @@ -124,7 +123,7 @@ std::string AsmPrinter::operator()(FunctionDefinition const& _functionDefinition out += " -> "; out += boost::algorithm::join( _functionDefinition.returnVariables | ranges::views::transform( - [this](TypedName argument) { return formatTypedName(argument); } + [this](NameWithDebugData argument) { return formatNameWithDebugData(argument); } ), ", " ); @@ -236,18 +235,10 @@ std::string AsmPrinter::operator()(Block const& _block) } } -std::string AsmPrinter::formatTypedName(TypedName _variable) +std::string AsmPrinter::formatNameWithDebugData(NameWithDebugData _variable) { yulAssert(!_variable.name.empty(), "Invalid variable name."); - return formatDebugData(_variable) + _variable.name.str() + appendTypeName(_variable.type); -} - -std::string AsmPrinter::appendTypeName(YulName _type) const -{ - if (_type.empty()) - return {}; - else - return ":" + _type.str(); + return formatDebugData(_variable) + _variable.name.str(); } std::string AsmPrinter::formatSourceLocation( diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 05b6fb9d8..cc17c6a04 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -36,12 +36,10 @@ namespace solidity::yul { -struct Dialect; /** * Converts a parsed Yul AST into readable string representation. * Ignores source locations. - * If a dialect is provided, the dialect's default type is omitted. */ class AsmPrinter { @@ -82,8 +80,7 @@ class AsmPrinter ); private: - std::string formatTypedName(TypedName _variable); - std::string appendTypeName(YulName _type) const; + std::string formatNameWithDebugData(NameWithDebugData _variable); std::string formatDebugData(langutil::DebugData::ConstPtr const& _debugData, bool _statement); template std::string formatDebugData(T const& _node) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index dbf3bfdcd..d38d5f270 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -177,8 +177,6 @@ add_library(yul optimiser/Suite.h optimiser/SyntacticalEquality.cpp optimiser/SyntacticalEquality.h - optimiser/TypeInfo.cpp - optimiser/TypeInfo.h optimiser/UnusedFunctionParameterPruner.cpp optimiser/UnusedFunctionParameterPruner.h optimiser/UnusedFunctionsCommon.h diff --git a/libyul/Dialect.cpp b/libyul/Dialect.cpp index be6c6705e..06a53ea5f 100644 --- a/libyul/Dialect.cpp +++ b/libyul/Dialect.cpp @@ -27,5 +27,5 @@ using namespace solidity::langutil; Literal Dialect::zeroLiteral() const { - return {DebugData::create(), LiteralKind::Number, LiteralValue(0, std::nullopt), {}}; + return {DebugData::create(), LiteralKind::Number, LiteralValue(0, std::nullopt)}; } diff --git a/libyul/Scope.cpp b/libyul/Scope.cpp index 89bdfc674..a73b2f9fd 100644 --- a/libyul/Scope.cpp +++ b/libyul/Scope.cpp @@ -25,22 +25,21 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::util; -bool Scope::registerVariable(YulName _name, YulType const& _type) +bool Scope::registerVariable(YulName _name) { if (exists(_name)) return false; Variable variable; - variable.type = _type; variable.name = _name; identifiers[_name] = variable; return true; } -bool Scope::registerFunction(YulName _name, std::vector _arguments, std::vector _returns) +bool Scope::registerFunction(YulName _name, size_t _numArguments, size_t _numReturns) { if (exists(_name)) return false; - identifiers[_name] = Function{std::move(_arguments), std::move(_returns), _name}; + identifiers[_name] = Function{_numArguments, _numReturns, _name}; return true; } diff --git a/libyul/Scope.h b/libyul/Scope.h index 027597290..20850cc56 100644 --- a/libyul/Scope.h +++ b/libyul/Scope.h @@ -35,27 +35,24 @@ namespace solidity::yul struct Scope { - using YulType = YulName; - struct Variable { - YulType type; YulName name; }; struct Function { - std::vector arguments; - std::vector returns; + size_t numArguments; + size_t numReturns; YulName name; }; using Identifier = std::variant; - bool registerVariable(YulName _name, YulType const& _type); + bool registerVariable(YulName _name); bool registerFunction( YulName _name, - std::vector _arguments, - std::vector _returns + size_t _numArguments, + size_t _numReturns ); /// Looks up the identifier in this or super scopes and returns a valid pointer if found diff --git a/libyul/ScopeFiller.cpp b/libyul/ScopeFiller.cpp index 22c0d17e3..7d65a2e95 100644 --- a/libyul/ScopeFiller.cpp +++ b/libyul/ScopeFiller.cpp @@ -133,9 +133,9 @@ bool ScopeFiller::operator()(Block const& _block) return success; } -bool ScopeFiller::registerVariable(TypedName const& _name, SourceLocation const& _location, Scope& _scope) +bool ScopeFiller::registerVariable(NameWithDebugData const& _name, SourceLocation const& _location, Scope& _scope) { - if (!_scope.registerVariable(_name.name, _name.type)) + if (!_scope.registerVariable(_name.name)) { //@TODO secondary location m_errorReporter.declarationError( @@ -150,13 +150,7 @@ bool ScopeFiller::registerVariable(TypedName const& _name, SourceLocation const& bool ScopeFiller::registerFunction(FunctionDefinition const& _funDef) { - std::vector parameters; - for (auto const& parameter: _funDef.parameters) - parameters.emplace_back(parameter.type); - std::vector returns; - for (auto const& returnVariable: _funDef.returnVariables) - returns.emplace_back(returnVariable.type); - if (!m_currentScope->registerFunction(_funDef.name, std::move(parameters), std::move(returns))) + if (!m_currentScope->registerFunction(_funDef.name, _funDef.parameters.size(), _funDef.returnVariables.size())) { //@TODO secondary location m_errorReporter.declarationError( diff --git a/libyul/ScopeFiller.h b/libyul/ScopeFiller.h index b43910874..7a4834a48 100644 --- a/libyul/ScopeFiller.h +++ b/libyul/ScopeFiller.h @@ -35,7 +35,7 @@ struct SourceLocation; namespace solidity::yul { -struct TypedName; +struct NameWithDebugData; struct Scope; struct AsmAnalysisInfo; @@ -65,7 +65,7 @@ class ScopeFiller private: bool registerVariable( - TypedName const& _name, + NameWithDebugData const& _name, langutil::SourceLocation const& _location, Scope& _scope ); diff --git a/libyul/Utilities.cpp b/libyul/Utilities.cpp index 6a78441cb..4bbfb4243 100644 --- a/libyul/Utilities.cpp +++ b/libyul/Utilities.cpp @@ -219,8 +219,8 @@ bool solidity::yul::validBoolLiteral(solidity::yul::Literal const& _literal) template<> bool Less::operator()(Literal const& _lhs, Literal const& _rhs) const { - if (std::make_tuple(_lhs.kind, _lhs.type) != std::make_tuple(_rhs.kind, _rhs.type)) - return std::make_tuple(_lhs.kind, _lhs.type) < std::make_tuple(_rhs.kind, _rhs.type); + if (_lhs.kind != _rhs.kind) + return _lhs.kind < _rhs.kind; if (_lhs.value.unlimited() && _rhs.value.unlimited()) yulAssert( diff --git a/libyul/backends/evm/ConstantOptimiser.cpp b/libyul/backends/evm/ConstantOptimiser.cpp index 2ab77f84e..1bb23cbc9 100644 --- a/libyul/backends/evm/ConstantOptimiser.cpp +++ b/libyul/backends/evm/ConstantOptimiser.cpp @@ -179,7 +179,7 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu Representation RepresentationFinder::represent(u256 const& _value) const { Representation repr; - repr.expression = std::make_unique(Literal{m_debugData, LiteralKind::Number, LiteralValue{_value, formatNumber(_value)}, {}}); + repr.expression = std::make_unique(Literal{m_debugData, LiteralKind::Number, LiteralValue{_value, formatNumber(_value)}}); repr.cost = m_meter.costs(*repr.expression); return repr; } diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 3007566dd..596c6c961 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -268,7 +268,7 @@ StackSlot ControlFlowGraphBuilder::operator()(FunctionCall const& _call) void ControlFlowGraphBuilder::operator()(VariableDeclaration const& _varDecl) { yulAssert(m_currentBlock, ""); - auto declaredVariables = _varDecl.variables | ranges::views::transform([&](TypedName const& _var) { + auto declaredVariables = _varDecl.variables | ranges::views::transform([&](NameWithDebugData const& _var) { return VariableSlot{lookupVariable(_var.name), _var.debugData}; }) | ranges::to>; Stack input; @@ -337,7 +337,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) auto ghostVariableId = m_graph.ghostVariables.size(); YulName ghostVariableName("GHOST[" + std::to_string(ghostVariableId) + "]"); - auto& ghostVar = m_graph.ghostVariables.emplace_back(Scope::Variable{""_yulname, ghostVariableName}); + auto& ghostVar = m_graph.ghostVariables.emplace_back(Scope::Variable{ghostVariableName}); // Artificially generate: // let := @@ -548,7 +548,7 @@ Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _cal // input std::move(inputs), // output - ranges::views::iota(0u, function.returns.size()) | ranges::views::transform([&](size_t _i) { + ranges::views::iota(0u, function.numReturns) | ranges::views::transform([&](size_t _i) { return TemporarySlot{_call, _i}; }) | ranges::to, // operation diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 71872a4e8..694639565 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -56,7 +56,7 @@ CodeTransform::CodeTransform( ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen, UseNamedLabels _useNamedLabelsForFunctions, std::shared_ptr _context, - std::vector _delayedReturnVariables, + std::vector _delayedReturnVariables, std::optional _functionExitLabel ): m_assembly(_assembly), @@ -249,13 +249,13 @@ void CodeTransform::operator()(FunctionCall const& _call) [&](Scope::Function& _function) { function = &_function; } }), "Function name not found."); yulAssert(function, ""); - yulAssert(function->arguments.size() == _call.arguments.size(), ""); + yulAssert(function->numArguments == _call.arguments.size(), ""); for (auto const& arg: _call.arguments | ranges::views::reverse) visitExpression(arg); m_assembly.setSourceLocation(originLocationOf(_call)); m_assembly.appendJumpTo( functionEntryID(*function), - static_cast(function->returns.size()) - static_cast(function->arguments.size()) - 1, + static_cast(function->numReturns) - static_cast(function->numArguments) - 1, AbstractAssembly::JumpType::IntoFunction ); m_assembly.appendLabel(returnLabel); @@ -646,10 +646,10 @@ void CodeTransform::setupReturnVariablesAndFunctionExit() } // Allocate slots for return variables as if they were declared as variables in the virtual function scope. - for (TypedName const& var: m_delayedReturnVariables) + for (NameWithDebugData const& var: m_delayedReturnVariables) (*this)(VariableDeclaration{var.debugData, {var}, {}}); - m_functionExitStackHeight = ranges::max(m_delayedReturnVariables | ranges::views::transform([&](TypedName const& _name) { + m_functionExitStackHeight = ranges::max(m_delayedReturnVariables | ranges::views::transform([&](NameWithDebugData const& _name) { return variableStackHeight(_name.name); })) + 1; m_delayedReturnVariables.clear(); @@ -658,7 +658,7 @@ void CodeTransform::setupReturnVariablesAndFunctionExit() namespace { -bool statementNeedsReturnVariableSetup(Statement const& _statement, std::vector const& _returnVariables) +bool statementNeedsReturnVariableSetup(Statement const& _statement, std::vector const& _returnVariables) { if (std::holds_alternative(_statement)) return true; @@ -668,7 +668,7 @@ bool statementNeedsReturnVariableSetup(Statement const& _statement, std::vector< ) { std::map references = VariableReferencesCounter::countReferences(_statement); - auto isReferenced = [&references](TypedName const& _returnVariable) { + auto isReferenced = [&references](NameWithDebugData const& _returnVariable) { return references.count(_returnVariable.name); }; if (ranges::none_of(_returnVariables, isReferenced)) diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h index 0e6a9d8be..c0bbac81b 100644 --- a/libyul/backends/evm/EVMCodeTransform.h +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -114,7 +114,7 @@ class CodeTransform ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen, UseNamedLabels _useNamedLabelsForFunctions, std::shared_ptr _context, - std::vector _delayedReturnVariables, + std::vector _delayedReturnVariables, std::optional _functionExitLabel ); @@ -209,7 +209,7 @@ class CodeTransform std::set m_unusedStackSlots; /// A list of return variables for which no stack slots have been assigned yet. - std::vector m_delayedReturnVariables; + std::vector m_delayedReturnVariables; /// Function exit label. Used as jump target for ``leave``. std::optional m_functionExitLabel; diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 7690cf27c..6395ea64a 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -70,7 +70,7 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call) // Validate stack. { yulAssert(m_assembly.stackHeight() == static_cast(m_stack.size()), ""); - yulAssert(m_stack.size() >= _call.function.get().arguments.size() + (_call.canContinue ? 1 : 0), ""); + yulAssert(m_stack.size() >= _call.function.get().numArguments + (_call.canContinue ? 1 : 0), ""); // Assert that we got the correct arguments on stack for the call. for (auto&& [arg, slot]: ranges::zip_view( _call.functionCall.get().arguments | ranges::views::reverse, @@ -92,7 +92,7 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call) m_assembly.setSourceLocation(originLocationOf(_call)); m_assembly.appendJumpTo( getFunctionLabel(_call.function), - static_cast(_call.function.get().returns.size()) - static_cast(_call.function.get().arguments.size()) - (_call.canContinue ? 1 : 0), + static_cast(_call.function.get().numReturns) - static_cast(_call.function.get().numArguments) - (_call.canContinue ? 1 : 0), AbstractAssembly::JumpType::IntoFunction ); if (_call.canContinue) @@ -102,10 +102,10 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call) // Update stack. { // Remove arguments and return label from m_stack. - for (size_t i = 0; i < _call.function.get().arguments.size() + (_call.canContinue ? 1 : 0); ++i) + for (size_t i = 0; i < _call.function.get().numArguments + (_call.canContinue ? 1 : 0); ++i) m_stack.pop_back(); // Push return values to m_stack. - for (size_t index: ranges::views::iota(0u, _call.function.get().returns.size())) + for (size_t index: ranges::views::iota(0u, _call.function.get().numReturns)) m_stack.emplace_back(TemporarySlot{_call.functionCall, index}); yulAssert(m_assembly.stackHeight() == static_cast(m_stack.size()), ""); } @@ -196,8 +196,8 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( functionLabels[&functionInfo] = useNamedLabel ? m_assembly.namedLabel( function->name.str(), - function->arguments.size(), - function->returns.size(), + function->numArguments, + function->numReturns, functionInfo.debugData ? functionInfo.debugData->astID : std::nullopt ) : m_assembly.newLabelId(); diff --git a/libyul/optimiser/ASTCopier.cpp b/libyul/optimiser/ASTCopier.cpp index 8efe29613..269c7adee 100644 --- a/libyul/optimiser/ASTCopier.cpp +++ b/libyul/optimiser/ASTCopier.cpp @@ -163,9 +163,9 @@ Literal ASTCopier::translate(Literal const& _literal) return _literal; } -TypedName ASTCopier::translate(TypedName const& _typedName) +NameWithDebugData ASTCopier::translate(NameWithDebugData const& _typedName) { - return TypedName{_typedName.debugData, translateIdentifier(_typedName.name), _typedName.type}; + return NameWithDebugData{_typedName.debugData, translateIdentifier(_typedName.name)}; } YulName FunctionCopier::translateIdentifier(YulName _name) diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index 88d2a3451..04b1c96cd 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -100,7 +100,7 @@ class ASTCopier: public ExpressionCopier, public StatementCopier Case translate(Case const& _case); virtual Identifier translate(Identifier const& _identifier); Literal translate(Literal const& _literal); - TypedName translate(TypedName const& _typedName); + NameWithDebugData translate(NameWithDebugData const& _typedName); virtual void enterScope(Block const&) { } virtual void leaveScope(Block const&) { } diff --git a/libyul/optimiser/BlockHasher.cpp b/libyul/optimiser/BlockHasher.cpp index 9d6db2066..5470558ce 100644 --- a/libyul/optimiser/BlockHasher.cpp +++ b/libyul/optimiser/BlockHasher.cpp @@ -48,7 +48,6 @@ void ASTHasherBase::hashLiteral(solidity::yul::Literal const& _literal) hash64(std::hash{}(_literal.value.value())); else hash64(std::hash{}(_literal.value.builtinStringLiteralValue())); - hash64(_literal.type.hash()); hash8(_literal.value.unlimited()); } diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index 2bd505a1c..c078885e8 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/libyul/optimiser/ControlFlowSimplifier.h b/libyul/optimiser/ControlFlowSimplifier.h index 0f0e725cd..86ebf296c 100644 --- a/libyul/optimiser/ControlFlowSimplifier.h +++ b/libyul/optimiser/ControlFlowSimplifier.h @@ -24,7 +24,6 @@ namespace solidity::yul { struct Dialect; struct OptimiserStepContext; -class TypeInfo; /** * Simplifies several control-flow structures: diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index 6b23a86b9..5a4b199ca 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -217,7 +217,7 @@ class DataFlowAnalyzer: public ASTModifier }; /// Special expression whose address will be used in m_value. /// YulName does not need to be reset because DataFlowAnalyzer is short-lived. - Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue{0, "0"}, {}}}; + Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue{0, std::nullopt}}}; /// List of scopes. std::vector m_variableScopes; }; diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index 482ade8f8..598d2e900 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -60,7 +60,7 @@ void ExpressionSimplifier::visit(Expression& _expression) !knownToBeZero(startArgument) && !std::holds_alternative(startArgument) ) - startArgument = Literal{debugDataOf(startArgument), LiteralKind::Number, LiteralValue{0, "0"}, {}}; + startArgument = Literal{debugDataOf(startArgument), LiteralKind::Number, LiteralValue{0, std::nullopt}}; } } diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index acaa40dbf..9f9bf958f 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -37,8 +36,7 @@ using namespace solidity::langutil; void ExpressionSplitter::run(OptimiserStepContext& _context, Block& _ast) { - TypeInfo typeInfo(_context.dialect, _ast); - ExpressionSplitter{_context.dialect, _context.dispenser, typeInfo}(_ast); + ExpressionSplitter{_context.dialect, _context.dispenser}(_ast); } void ExpressionSplitter::operator()(FunctionCall& _funCall) @@ -100,13 +98,11 @@ void ExpressionSplitter::outlineExpression(Expression& _expr) langutil::DebugData::ConstPtr debugData = debugDataOf(_expr); YulName var = m_nameDispenser.newName({}); - YulName type = m_typeInfo.typeOf(_expr); m_statementsToPrefix.emplace_back(VariableDeclaration{ debugData, - {{TypedName{debugData, var, type}}}, + {{NameWithDebugData{debugData, var}}}, std::make_unique(std::move(_expr)) }); _expr = Identifier{debugData, var}; - m_typeInfo.setVariableType(var, type); } diff --git a/libyul/optimiser/ExpressionSplitter.h b/libyul/optimiser/ExpressionSplitter.h index bbde8d6a2..0b223e985 100644 --- a/libyul/optimiser/ExpressionSplitter.h +++ b/libyul/optimiser/ExpressionSplitter.h @@ -33,7 +33,6 @@ namespace solidity::yul struct Dialect; struct OptimiserStepContext; -class TypeInfo; /** * Optimiser component that modifies an AST in place, turning complex @@ -71,12 +70,10 @@ class ExpressionSplitter: public ASTModifier private: explicit ExpressionSplitter( Dialect const& _dialect, - NameDispenser& _nameDispenser, - TypeInfo& _typeInfo + NameDispenser& _nameDispenser ): m_dialect(_dialect), - m_nameDispenser(_nameDispenser), - m_typeInfo(_typeInfo) + m_nameDispenser(_nameDispenser) { } /// Replaces the expression by a variable if it is a function call or functional @@ -89,7 +86,6 @@ class ExpressionSplitter: public ASTModifier std::vector m_statementsToPrefix; Dialect const& m_dialect; NameDispenser& m_nameDispenser; - TypeInfo& m_typeInfo; }; } diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index cc3f936d9..d0839e765 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -58,8 +58,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) Literal { debugData, LiteralKind::Boolean, - LiteralValue{true}, - {} + LiteralValue{true} } ); } diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index 3daaea658..2f138761f 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -298,10 +298,10 @@ std::vector InlineModifier::performInline(Statement& _statement, Func // helper function to create a new variable that is supposed to model // an existing variable. - auto newVariable = [&](TypedName const& _existingVariable, Expression* _value) { + auto newVariable = [&](NameWithDebugData const& _existingVariable, Expression* _value) { YulName newName = m_nameDispenser.newName(_existingVariable.name); variableReplacements[_existingVariable.name] = newName; - VariableDeclaration varDecl{_funCall.debugData, {{_funCall.debugData, newName, _existingVariable.type}}, {}}; + VariableDeclaration varDecl{_funCall.debugData, {{_funCall.debugData, newName}}, {}}; if (_value) varDecl.value = std::make_unique(std::move(*_value)); else diff --git a/libyul/optimiser/FunctionSpecializer.cpp b/libyul/optimiser/FunctionSpecializer.cpp index 49da50032..cb7cd4164 100644 --- a/libyul/optimiser/FunctionSpecializer.cpp +++ b/libyul/optimiser/FunctionSpecializer.cpp @@ -104,7 +104,7 @@ FunctionDefinition FunctionSpecializer::specialize( missingVariableDeclarations.emplace_back( VariableDeclaration{ _f.debugData, - std::vector{newFunction.parameters[index]}, + std::vector{newFunction.parameters[index]}, std::make_unique(std::move(*argument)) } ); diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index 943860a0a..98d938a36 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -125,8 +125,7 @@ void LoadResolver::tryEvaluateKeccak( {}, LiteralKind::Number, // a dummy 256-bit number to represent the Keccak256 hash. - LiteralValue{std::numeric_limits::max()}, - {} + LiteralValue{std::numeric_limits::max()} } ); @@ -150,8 +149,7 @@ void LoadResolver::tryEvaluateKeccak( _e = Literal{ debugDataOf(_e), LiteralKind::Number, - LiteralValue{contentHash}, - {} + LiteralValue{contentHash} }; } } diff --git a/libyul/optimiser/NameDisplacer.cpp b/libyul/optimiser/NameDisplacer.cpp index fd813fbfc..c68d52f9a 100644 --- a/libyul/optimiser/NameDisplacer.cpp +++ b/libyul/optimiser/NameDisplacer.cpp @@ -33,7 +33,7 @@ void NameDisplacer::operator()(Identifier& _identifier) void NameDisplacer::operator()(VariableDeclaration& _varDecl) { - for (TypedName& var: _varDecl.variables) + for (NameWithDebugData& var: _varDecl.variables) checkAndReplaceNew(var.name); ASTModifier::operator()(_varDecl); diff --git a/libyul/optimiser/NameSimplifier.cpp b/libyul/optimiser/NameSimplifier.cpp index f03a448f0..d57a61332 100644 --- a/libyul/optimiser/NameSimplifier.cpp +++ b/libyul/optimiser/NameSimplifier.cpp @@ -53,9 +53,9 @@ void NameSimplifier::operator()(VariableDeclaration& _varDecl) ASTModifier::operator()(_varDecl); } -void NameSimplifier::renameVariables(std::vector& _variables) +void NameSimplifier::renameVariables(std::vector& _variables) { - for (TypedName& typedName: _variables) + for (NameWithDebugData& typedName: _variables) translate(typedName.name); } diff --git a/libyul/optimiser/NameSimplifier.h b/libyul/optimiser/NameSimplifier.h index 848e61f56..0ff5077cc 100644 --- a/libyul/optimiser/NameSimplifier.h +++ b/libyul/optimiser/NameSimplifier.h @@ -60,7 +60,7 @@ class NameSimplifier: public ASTModifier NameSimplifier(OptimiserStepContext& _context, Block const& _ast); /// Tries to rename a list of variables. - void renameVariables(std::vector& _variables); + void renameVariables(std::vector& _variables); void findSimplification(YulName const& _name); void translate(YulName& _name); diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index 80abdf7e6..1d5270f8f 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -28,8 +28,6 @@ #include -#include - using namespace solidity; using namespace solidity::yul; using namespace solidity::langutil; @@ -46,12 +44,10 @@ class IntroduceSSA: public ASTModifier public: explicit IntroduceSSA( NameDispenser& _nameDispenser, - std::set const& _variablesToReplace, - TypeInfo& _typeInfo + std::set const& _variablesToReplace ): m_nameDispenser(_nameDispenser), - m_variablesToReplace(_variablesToReplace), - m_typeInfo(_typeInfo) + m_variablesToReplace(_variablesToReplace) { } void operator()(Block& _block) override; @@ -59,7 +55,6 @@ class IntroduceSSA: public ASTModifier private: NameDispenser& m_nameDispenser; std::set const& m_variablesToReplace; - TypeInfo const& m_typeInfo; }; @@ -87,15 +82,15 @@ void IntroduceSSA::operator()(Block& _block) langutil::DebugData::ConstPtr debugData = varDecl.debugData; std::vector statements; statements.emplace_back(VariableDeclaration{debugData, {}, std::move(varDecl.value)}); - TypedNameList newVariables; + NameWithDebugDataList newVariables; for (auto const& var: varDecl.variables) { YulName oldName = var.name; YulName newName = m_nameDispenser.newName(oldName); - newVariables.emplace_back(TypedName{debugData, newName, var.type}); + newVariables.emplace_back(NameWithDebugData{debugData, newName}); statements.emplace_back(VariableDeclaration{ debugData, - {TypedName{debugData, oldName, var.type}}, + {NameWithDebugData{debugData, oldName}}, std::make_unique(Identifier{debugData, newName}) }); } @@ -114,15 +109,12 @@ void IntroduceSSA::operator()(Block& _block) langutil::DebugData::ConstPtr debugData = assignment.debugData; std::vector statements; statements.emplace_back(VariableDeclaration{debugData, {}, std::move(assignment.value)}); - TypedNameList newVariables; + NameWithDebugDataList newVariables; for (auto const& var: assignment.variableNames) { YulName oldName = var.name; YulName newName = m_nameDispenser.newName(oldName); - newVariables.emplace_back(TypedName{debugData, - newName, - m_typeInfo.typeOfVariable(oldName) - }); + newVariables.emplace_back(NameWithDebugData{debugData, newName}); statements.emplace_back(Assignment{ debugData, {Identifier{debugData, oldName}}, @@ -148,12 +140,10 @@ class IntroduceControlFlowSSA: public ASTModifier public: explicit IntroduceControlFlowSSA( NameDispenser& _nameDispenser, - std::set const& _variablesToReplace, - TypeInfo const& _typeInfo + std::set const& _variablesToReplace ): m_nameDispenser(_nameDispenser), - m_variablesToReplace(_variablesToReplace), - m_typeInfo(_typeInfo) + m_variablesToReplace(_variablesToReplace) { } void operator()(FunctionDefinition& _function) override; @@ -168,7 +158,6 @@ class IntroduceControlFlowSSA: public ASTModifier std::set m_variablesInScope; /// Variables that do not have a specific value. util::UniqueVector m_variablesToReassign; - TypeInfo const& m_typeInfo; }; void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function) @@ -232,7 +221,7 @@ void IntroduceControlFlowSSA::operator()(Block& _block) YulName newName = m_nameDispenser.newName(toReassign); toPrepend.emplace_back(VariableDeclaration{ debugDataOf(_s), - {TypedName{debugDataOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}}, + {NameWithDebugData{debugDataOf(_s), newName}}, std::make_unique(Identifier{debugDataOf(_s), toReassign}) }); assignedVariables.pushBack(toReassign); @@ -379,10 +368,9 @@ void PropagateValues::operator()(Block& _block) void SSATransform::run(OptimiserStepContext& _context, Block& _ast) { - TypeInfo typeInfo(_context.dialect, _ast); std::set assignedVariables = assignedVariableNames(_ast); - IntroduceSSA{_context.dispenser, assignedVariables, typeInfo}(_ast); - IntroduceControlFlowSSA{_context.dispenser, assignedVariables, typeInfo}(_ast); + IntroduceSSA{_context.dispenser, assignedVariables}(_ast); + IntroduceControlFlowSSA{_context.dispenser, assignedVariables}(_ast); PropagateValues{assignedVariables}(_ast); } diff --git a/libyul/optimiser/SSAValueTracker.h b/libyul/optimiser/SSAValueTracker.h index 0196ecc40..2448f99a8 100644 --- a/libyul/optimiser/SSAValueTracker.h +++ b/libyul/optimiser/SSAValueTracker.h @@ -57,7 +57,7 @@ class SSAValueTracker: public ASTWalker /// Special expression whose address will be used in m_values. /// YulName does not need to be reset because SSAValueTracker is short-lived. - Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue(u256{0}), {}}}; + Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue(u256{0})}}; std::map m_values; }; diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index 03e4ccdd0..72c0f70ca 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -241,7 +241,7 @@ Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData if (m_kind == PatternKind::Constant) { assertThrow(m_data, OptimizerException, "No match group and no constant value given."); - return Literal{_debugData, LiteralKind::Number, LiteralValue{*m_data, formatNumber(*m_data)}, {}}; + return Literal{_debugData, LiteralKind::Number, LiteralValue{*m_data, formatNumber(*m_data)}}; } else if (m_kind == PatternKind::Operation) { diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 6e6da63e6..d3cb6418f 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -77,7 +77,7 @@ struct MemoryOffsetAllocator size_t totalArgCount = functionDefinition->returnVariables.size() + functionDefinition->parameters.size(); totalArgCount > 16 ) - for (TypedName const& var: ranges::concat_view( + for (NameWithDebugData const& var: ranges::concat_view( functionDefinition->parameters, functionDefinition->returnVariables ) | ranges::views::take(totalArgCount - 16)) diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index d5cb539af..7e3f93475 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -49,7 +49,7 @@ std::vector generateMemoryStore( _debugData, Identifier{_debugData, memoryStoreFunction->name}, { - Literal{_debugData, LiteralKind::Number, _mpos, {}}, + Literal{_debugData, LiteralKind::Number, _mpos}, std::move(_value) } }}); @@ -66,8 +66,7 @@ FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::Co Literal{ _debugData, LiteralKind::Number, - _mpos, - {} + _mpos } } }; @@ -91,7 +90,7 @@ void StackToMemoryMover::run( util::mapTuple([](YulName _name, FunctionDefinition const* _funDef) { return make_pair(_name, _funDef->returnVariables); }), - std::map{} + std::map{} ) ); stackToMemoryMover(_block); @@ -101,7 +100,7 @@ void StackToMemoryMover::run( StackToMemoryMover::StackToMemoryMover( OptimiserStepContext& _context, VariableMemoryOffsetTracker const& _memoryOffsetTracker, - std::map _functionReturnVariables + std::map _functionReturnVariables ): m_context(_context), m_memoryOffsetTracker(_memoryOffsetTracker), @@ -124,7 +123,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) std::vector memoryVariableInits; // All function parameters with a memory slot are moved at the beginning of the function body. - for (TypedName const& param: _functionDefinition.parameters) + for (NameWithDebugData const& param: _functionDefinition.parameters) if (auto slot = m_memoryOffsetTracker(param.name)) memoryVariableInits += generateMemoryStore( m_context.dialect, @@ -134,21 +133,21 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) ); // All memory return variables have to be initialized to zero in memory. - for (TypedName const& returnVariable: _functionDefinition.returnVariables) + for (NameWithDebugData const& returnVariable: _functionDefinition.returnVariables) if (auto slot = m_memoryOffsetTracker(returnVariable.name)) memoryVariableInits += generateMemoryStore( m_context.dialect, returnVariable.debugData, *slot, - Literal{returnVariable.debugData, LiteralKind::Number, LiteralValue(u256{0}), {}} + Literal{returnVariable.debugData, LiteralKind::Number, LiteralValue(u256{0})} ); // Special case of a function with a single return argument that needs to move to memory. if (_functionDefinition.returnVariables.size() == 1 && m_memoryOffsetTracker(_functionDefinition.returnVariables.front().name)) { - TypedNameList stackParameters = _functionDefinition.parameters | ranges::views::filter( + NameWithDebugDataList stackParameters = _functionDefinition.parameters | ranges::views::filter( std::not_fn(m_memoryOffsetTracker) - ) | ranges::to; + ) | ranges::to; // Generate new function without return variable and with only the non-moved parameters. YulName newFunctionName = m_context.dispenser.newName(_functionDefinition.name); m_newFunctionDefinitions.emplace_back(FunctionDefinition{ @@ -160,7 +159,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) }); // Generate new names for the arguments to maintain disambiguation. std::map newArgumentNames; - for (TypedName const& _var: stackParameters) + for (NameWithDebugData const& _var: stackParameters) newArgumentNames[_var.name] = m_context.dispenser.newName(_var.name); for (auto& parameter: _functionDefinition.parameters) parameter.name = util::valueOrDefault(newArgumentNames, parameter.name, parameter.name); @@ -171,7 +170,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) FunctionCall{ _functionDefinition.debugData, Identifier{_functionDefinition.debugData, newFunctionName}, - stackParameters | ranges::views::transform([&](TypedName const& _arg) { + stackParameters | ranges::views::transform([&](NameWithDebugData const& _arg) { return Expression{Identifier{_arg.debugData, newArgumentNames.at(_arg.name)}}; }) | ranges::to> } @@ -193,7 +192,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) _functionDefinition.returnVariables = _functionDefinition.returnVariables | ranges::views::filter( std::not_fn(m_memoryOffsetTracker) - ) | ranges::to; + ) | ranges::to; } void StackToMemoryMover::operator()(Block& _block) @@ -214,7 +213,7 @@ void StackToMemoryMover::operator()(Block& _block) m_context.dialect, debugData, *offset, - _stmt.value ? *std::move(_stmt.value) : Literal{debugData, LiteralKind::Number, LiteralValue(u256{0}), {}} + _stmt.value ? *std::move(_stmt.value) : Literal{debugData, LiteralKind::Number, LiteralValue(u256{0})} ); else return {}; @@ -256,7 +255,7 @@ void StackToMemoryMover::operator()(Block& _block) else { YulName tempVarName = m_nameDispenser.newName(lhsVar.name); - tempDecl.variables.emplace_back(TypedName{lhsVar.debugData, tempVarName, {}}); + tempDecl.variables.emplace_back(NameWithDebugData{lhsVar.debugData, tempVarName}); rhs = std::make_unique(Identifier{debugData, tempVarName}); } @@ -322,7 +321,7 @@ std::optional StackToMemoryMover::VariableMemoryOffsetTracker::ope return std::nullopt; } -std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(TypedName const& _variable) const +std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(NameWithDebugData const& _variable) const { return (*this)(_variable.name); } diff --git a/libyul/optimiser/StackToMemoryMover.h b/libyul/optimiser/StackToMemoryMover.h index 739266031..89f11c1fe 100644 --- a/libyul/optimiser/StackToMemoryMover.h +++ b/libyul/optimiser/StackToMemoryMover.h @@ -169,7 +169,7 @@ class StackToMemoryMover: ASTModifier std::optional operator()(YulName const& _variable) const; /// @returns a YulName containing the memory offset to be assigned to @a _variable as number literal /// or std::nullopt if the variable should not be moved. - std::optional operator()(TypedName const& _variable) const; + std::optional operator()(NameWithDebugData const& _variable) const; /// @returns a YulName containing the memory offset to be assigned to @a _variable as number literal /// or std::nullopt if the variable should not be moved. std::optional operator()(Identifier const& _variable) const; @@ -187,14 +187,14 @@ class StackToMemoryMover: ASTModifier StackToMemoryMover( OptimiserStepContext& _context, VariableMemoryOffsetTracker const& _memoryOffsetTracker, - std::map> _functionReturnVariables + std::map> _functionReturnVariables ); OptimiserStepContext& m_context; VariableMemoryOffsetTracker const& m_memoryOffsetTracker; NameDispenser& m_nameDispenser; /// Map from function names to the return variables of the function with that name. - std::map> m_functionReturnVariables; + std::map> m_functionReturnVariables; /// List of functions generated while running this step that are to be appended to the code in the end. std::list m_newFunctionDefinitions; }; diff --git a/libyul/optimiser/SyntacticalEquality.cpp b/libyul/optimiser/SyntacticalEquality.cpp index db562716a..0f4aa6e33 100644 --- a/libyul/optimiser/SyntacticalEquality.cpp +++ b/libyul/optimiser/SyntacticalEquality.cpp @@ -67,9 +67,6 @@ bool SyntacticallyEqual::expressionEqual(Literal const& _lhs, Literal const& _rh yulAssert(validLiteral(_lhs), "Invalid lhs literal during syntactical equality check"); yulAssert(validLiteral(_rhs), "Invalid rhs literal during syntactical equality check"); - if (_lhs.type != _rhs.type) - return false; - return _lhs.value == _rhs.value; } @@ -93,14 +90,14 @@ bool SyntacticallyEqual::statementEqual(VariableDeclaration const& _lhs, Variabl // first visit expression, then variable declarations if (!compareUniquePtr(_lhs.value, _rhs.value)) return false; - return util::containerEqual(_lhs.variables, _rhs.variables, [this](TypedName const& _lhsVarName, TypedName const& _rhsVarName) -> bool { + return util::containerEqual(_lhs.variables, _rhs.variables, [this](NameWithDebugData const& _lhsVarName, NameWithDebugData const& _rhsVarName) -> bool { return this->visitDeclaration(_lhsVarName, _rhsVarName); }); } bool SyntacticallyEqual::statementEqual(FunctionDefinition const& _lhs, FunctionDefinition const& _rhs) { - auto compare = [this](TypedName const& _lhsVarName, TypedName const& _rhsVarName) -> bool { + auto compare = [this](NameWithDebugData const& _lhsVarName, NameWithDebugData const& _rhsVarName) -> bool { return this->visitDeclaration(_lhsVarName, _rhsVarName); }; // first visit parameter declarations, then body @@ -157,10 +154,8 @@ bool SyntacticallyEqual::statementEqual(Block const& _lhs, Block const& _rhs) }); } -bool SyntacticallyEqual::visitDeclaration(TypedName const& _lhs, TypedName const& _rhs) +bool SyntacticallyEqual::visitDeclaration(NameWithDebugData const& _lhs, NameWithDebugData const& _rhs) { - if (_lhs.type != _rhs.type) - return false; std::size_t id = m_idsUsed++; m_identifiersLHS[_lhs.name] = id; m_identifiersRHS[_rhs.name] = id; diff --git a/libyul/optimiser/SyntacticalEquality.h b/libyul/optimiser/SyntacticalEquality.h index 0665a5efb..1fd888f7a 100644 --- a/libyul/optimiser/SyntacticalEquality.h +++ b/libyul/optimiser/SyntacticalEquality.h @@ -63,7 +63,7 @@ class SyntacticallyEqual bool statementEqual(Leave const&, Leave const&) { return true; } bool statementEqual(Block const& _lhs, Block const& _rhs); private: - bool visitDeclaration(TypedName const& _lhs, TypedName const& _rhs); + bool visitDeclaration(NameWithDebugData const& _lhs, NameWithDebugData const& _rhs); template bool expressionEqual(U const&, V const&, std::enable_if_t::value>* = nullptr) diff --git a/libyul/optimiser/TypeInfo.cpp b/libyul/optimiser/TypeInfo.cpp deleted file mode 100644 index 754c0bad0..000000000 --- a/libyul/optimiser/TypeInfo.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - 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 -/** - * Helper class that keeps track of the types while performing optimizations. - */ - -#include - -#include - -#include -#include - -#include - -using namespace solidity::yul; -using namespace solidity::util; - -class TypeInfo::TypeCollector: public ASTWalker -{ -public: - explicit TypeCollector(Block const& _block) - { - (*this)(_block); - } - - using ASTWalker::operator(); - void operator()(VariableDeclaration const& _varDecl) override - { - for (auto const& var: _varDecl.variables) - variableTypes[var.name] = var.type; - } - void operator()(FunctionDefinition const& _funDef) override - { - ASTWalker::operator()(_funDef); - - auto& funType = functionTypes[_funDef.name]; - for (auto const& arg: _funDef.parameters) - { - funType.parameters.emplace_back(arg.type); - variableTypes[arg.name] = arg.type; - } - for (auto const& ret: _funDef.returnVariables) - { - funType.returns.emplace_back(ret.type); - variableTypes[ret.name] = ret.type; - } - } - - std::map variableTypes; - std::map functionTypes; -}; - - -TypeInfo::TypeInfo(Dialect const& _dialect, Block const& _ast): - m_dialect(_dialect) -{ - TypeCollector types(_ast); - m_functionTypes = std::move(types.functionTypes); - m_variableTypes = std::move(types.variableTypes); -} - -YulName TypeInfo::typeOf(Expression const& _expression) const -{ - return std::visit(GenericVisitor{ - [&](FunctionCall const& _funCall) { - YulName name = _funCall.functionName.name; - std::vector const* retTypes = nullptr; - if (BuiltinFunction const* fun = m_dialect.builtin(name)) - retTypes = &fun->returns; - else - retTypes = &m_functionTypes.at(name).returns; - yulAssert(retTypes && retTypes->size() == 1, "Call to typeOf for non-single-value expression."); - return retTypes->front(); - }, - [&](Identifier const& _identifier) { - return m_variableTypes.at(_identifier.name); - }, - [&](Literal const& _literal) { - return _literal.type; - } - }, _expression); -} - -YulName TypeInfo::typeOfVariable(YulName _name) const -{ - return m_variableTypes.at(_name); -} diff --git a/libyul/optimiser/TypeInfo.h b/libyul/optimiser/TypeInfo.h deleted file mode 100644 index 96c43875a..000000000 --- a/libyul/optimiser/TypeInfo.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - 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 -/** - * Helper class that keeps track of the types while performing optimizations. - */ -#pragma once - -#include -#include - -#include -#include - -namespace solidity::yul -{ -struct Dialect; - -/** - * Helper class that keeps track of the types while performing optimizations. - * - * Only works on disambiguated sources! - */ -class TypeInfo -{ -public: - TypeInfo(Dialect const& _dialect, Block const& _ast); - - void setVariableType(YulName _name, YulName _type) { m_variableTypes[_name] = _type; } - - /// @returns the type of an expression that is assumed to return exactly one value. - YulName typeOf(Expression const& _expression) const; - - /// \returns the type of variable - YulName typeOfVariable(YulName _name) const; - -private: - class TypeCollector; - - struct FunctionType - { - std::vector parameters; - std::vector returns; - }; - - Dialect const& m_dialect; - std::map m_variableTypes; - std::map m_functionTypes; -}; - -} diff --git a/libyul/optimiser/UnusedFunctionsCommon.cpp b/libyul/optimiser/UnusedFunctionsCommon.cpp index bd38b33ca..a6333a786 100644 --- a/libyul/optimiser/UnusedFunctionsCommon.cpp +++ b/libyul/optimiser/UnusedFunctionsCommon.cpp @@ -35,12 +35,11 @@ FunctionDefinition unusedFunctionsCommon::createLinkingFunction( NameDispenser& _nameDispenser ) { - auto generateTypedName = [&](TypedName t) + auto generateTypedName = [&](NameWithDebugData t) { - return TypedName{ + return NameWithDebugData{ t.debugData, - _nameDispenser.newName(t.name), - t.type + _nameDispenser.newName(t.name) }; }; diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index c71e8077b..a3b6c0708 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -92,7 +92,7 @@ void UnusedPruner::operator()(Block& _block) if (std::none_of( varDecl.variables.begin(), varDecl.variables.end(), - [&](TypedName const& _typedName) { return used(_typedName.name); } + [&](NameWithDebugData const& _typedName) { return used(_typedName.name); } )) { if (!varDecl.value) diff --git a/libyul/optimiser/UnusedStoreEliminator.cpp b/libyul/optimiser/UnusedStoreEliminator.cpp index d049f59a0..c50ddac14 100644 --- a/libyul/optimiser/UnusedStoreEliminator.cpp +++ b/libyul/optimiser/UnusedStoreEliminator.cpp @@ -61,9 +61,9 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) std::map values; for (auto const& [name, expression]: ssaValues.values()) values[name] = AssignedValue{expression, {}}; - Expression const zeroLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{0}), {}}}; - Expression const oneLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{1}), {}}}; - Expression const thirtyTwoLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{32}), {}}}; + Expression const zeroLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{0})}}; + Expression const oneLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{1})}}; + Expression const thirtyTwoLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{32})}}; values[YulName{zero}] = AssignedValue{&zeroLiteral, {}}; values[YulName{one}] = AssignedValue{&oneLiteral, {}}; values[YulName{thirtyTwo}] = AssignedValue{&thirtyTwoLiteral, {}}; diff --git a/libyul/optimiser/VarNameCleaner.cpp b/libyul/optimiser/VarNameCleaner.cpp index 041ebdeaa..b3a34d283 100644 --- a/libyul/optimiser/VarNameCleaner.cpp +++ b/libyul/optimiser/VarNameCleaner.cpp @@ -72,17 +72,17 @@ void VarNameCleaner::operator()(VariableDeclaration& _varDecl) ASTModifier::operator()(_varDecl); } -void VarNameCleaner::renameVariables(std::vector& _variables) +void VarNameCleaner::renameVariables(std::vector& _variables) { - for (TypedName& typedName: _variables) + for (NameWithDebugData& variable: _variables) { - auto newName = findCleanName(typedName.name); - if (newName != typedName.name) + auto newName = findCleanName(variable.name); + if (newName != variable.name) { - m_translatedNames[typedName.name] = newName; - typedName.name = newName; + m_translatedNames[variable.name] = newName; + variable.name = newName; } - m_usedNames.insert(typedName.name); + m_usedNames.insert(variable.name); } } diff --git a/libyul/optimiser/VarNameCleaner.h b/libyul/optimiser/VarNameCleaner.h index bfb6cfb53..7f8bb842e 100644 --- a/libyul/optimiser/VarNameCleaner.h +++ b/libyul/optimiser/VarNameCleaner.h @@ -68,7 +68,7 @@ class VarNameCleaner: public ASTModifier ); /// Tries to rename a list of variables. - void renameVariables(std::vector& _variables); + void renameVariables(std::vector& _variables); /// @returns suffix-stripped name, if a suffix was detected, none otherwise. YulName stripSuffix(YulName const& _name) const; diff --git a/test/libyul/StackShufflingTest.cpp b/test/libyul/StackShufflingTest.cpp index 2da445dd4..40fdcc5b1 100644 --- a/test/libyul/StackShufflingTest.cpp +++ b/test/libyul/StackShufflingTest.cpp @@ -102,7 +102,7 @@ bool StackShufflingTest::parse(std::string const& _source) expectToken(Token::LBrack); scanner.next(); // read number of ghost variables as ghostVariableId std::string ghostVariableId = scanner.currentLiteral(); - Scope::Variable ghostVar = Scope::Variable{""_yulname, YulName(literal + "[" + ghostVariableId + "]")}; + Scope::Variable ghostVar = Scope::Variable{YulName(literal + "[" + ghostVariableId + "]")}; stack.emplace_back(VariableSlot{ m_variables.insert(std::make_pair(ghostVar.name, ghostVar)).first->second }); @@ -110,7 +110,7 @@ bool StackShufflingTest::parse(std::string const& _source) } else { - Scope::Variable var = Scope::Variable{""_yulname, YulName(literal)}; + Scope::Variable var = Scope::Variable{YulName(literal)}; stack.emplace_back(VariableSlot{ m_variables.insert( make_pair(literal, var) diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index bf374c21f..0f94f309d 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -454,9 +454,9 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( { YulName originalFunctionName = m_currentFunction; m_currentFunction = _function.name; - for (TypedName const& _argument: _function.parameters) + for (NameWithDebugData const& _argument: _function.parameters) visitVariableName(_argument.name); - for (TypedName const& _argument: _function.returnVariables) + for (NameWithDebugData const& _argument: _function.returnVariables) visitVariableName(_argument.name); ASTWalker::operator()(_function); m_currentFunction = originalFunctionName; diff --git a/test/libyul/yulSyntaxTests/invalid_type.yul b/test/libyul/yulSyntaxTests/invalid_type.yul index f86381635..e9a4e30c9 100644 --- a/test/libyul/yulSyntaxTests/invalid_type.yul +++ b/test/libyul/yulSyntaxTests/invalid_type.yul @@ -2,4 +2,4 @@ let x: invalidType } // ---- -// TypeError 5473: (10-24): "invalidType" is not a valid type (user defined types are not yet supported). +// ParserError 5473: (10-24): Types are not valid in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/invalid_type2.yul b/test/libyul/yulSyntaxTests/invalid_type2.yul index af30bc2eb..5eb514866 100644 --- a/test/libyul/yulSyntaxTests/invalid_type2.yul +++ b/test/libyul/yulSyntaxTests/invalid_type2.yul @@ -2,5 +2,4 @@ let x := 1:invalidType } // ---- -// TypeError 5473: (15-28): "invalidType" is not a valid type (user defined types are not yet supported). -// TypeError 3947: (10-11): Assigning value of type "invalidType" to variable of type "". +// ParserError 5473: (15-28): Types are not valid in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/invalid_type3.yul b/test/libyul/yulSyntaxTests/invalid_type3.yul index 6fc0e35e8..9814527b0 100644 --- a/test/libyul/yulSyntaxTests/invalid_type3.yul +++ b/test/libyul/yulSyntaxTests/invalid_type3.yul @@ -2,5 +2,5 @@ function f(a: invalidType) -> b: invalidType {} } // ---- -// TypeError 5473: (17-31): "invalidType" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (36-50): "invalidType" is not a valid type (user defined types are not yet supported). +// ParserError 5473: (17-31): Types are not valid in untyped Yul. +// ParserError 5473: (36-50): Types are not valid in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/invalid_type4.yul b/test/libyul/yulSyntaxTests/invalid_type4.yul index 90f00ddaa..4924a592a 100644 --- a/test/libyul/yulSyntaxTests/invalid_type4.yul +++ b/test/libyul/yulSyntaxTests/invalid_type4.yul @@ -3,5 +3,4 @@ case 8: invalidType {} } // ---- -// TypeError 3781: (24-38): Expected a value of type "" but got "invalidType". -// TypeError 5473: (24-38): "invalidType" is not a valid type (user defined types are not yet supported). +// ParserError 5473: (24-38): Types are not valid in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/literal_invalid_type.yul b/test/libyul/yulSyntaxTests/literal_invalid_type.yul index fd612a0a5..10a280120 100644 --- a/test/libyul/yulSyntaxTests/literal_invalid_type.yul +++ b/test/libyul/yulSyntaxTests/literal_invalid_type.yul @@ -2,6 +2,4 @@ let x := true:unhappy } // ---- -// TypeError 5473: (15-27): "unhappy" is not a valid type (user defined types are not yet supported). -// TypeError 5170: (15-27): Invalid type "unhappy" for literal "true". -// TypeError 3947: (10-11): Assigning value of type "unhappy" to variable of type "". +// ParserError 5473: (15-27): Types are not valid in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul b/test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul index 0ae2fb15a..edd7871a7 100644 --- a/test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul +++ b/test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul @@ -20,260 +20,260 @@ let $100:x } // ---- -// TypeError 5473: (200-205): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (210-215): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (220-225): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (230-235): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (240-245): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (250-255): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (260-265): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (270-275): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (280-285): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (290-295): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (300-305): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (310-315): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (320-325): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (330-335): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (340-345): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (350-355): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (364-369): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (374-379): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (384-389): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (394-399): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (404-409): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (414-419): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (424-429): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (434-439): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (444-449): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (454-459): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (464-469): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (474-479): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (484-489): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (494-499): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (504-509): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (514-519): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (528-533): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (538-543): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (548-553): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (558-563): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (568-573): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (578-583): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (588-593): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (598-603): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (608-613): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (618-623): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (628-633): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (638-643): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (648-653): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (658-663): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (668-673): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (678-683): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (692-697): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (702-707): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (712-717): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (722-727): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (732-737): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (742-747): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (752-757): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (762-767): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (772-777): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (782-787): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (792-797): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (802-807): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (812-817): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (822-827): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (832-837): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (842-847): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (856-861): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (866-871): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (876-881): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (886-891): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (896-901): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (906-911): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (916-921): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (926-931): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (936-941): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (946-951): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (956-961): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (966-971): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (976-981): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (986-991): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (996-1001): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1006-1011): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1020-1025): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1030-1035): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1040-1045): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1050-1055): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1060-1065): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1070-1075): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1080-1085): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1090-1095): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1100-1105): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1110-1115): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1120-1125): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1130-1135): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1140-1145): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1150-1155): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1160-1165): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1170-1175): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1184-1189): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1194-1199): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1204-1209): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1214-1219): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1224-1229): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1234-1239): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1244-1249): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1254-1259): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1264-1269): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1274-1279): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1284-1289): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1294-1299): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1304-1309): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1314-1319): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1324-1329): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1334-1339): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1348-1353): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1358-1363): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1368-1373): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1378-1383): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1388-1393): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1398-1403): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1408-1413): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1418-1423): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1428-1433): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1438-1443): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1448-1453): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1458-1463): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1468-1473): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1478-1483): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1488-1493): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1498-1503): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1512-1517): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1522-1527): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1532-1537): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1542-1547): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1552-1557): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1562-1567): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1572-1577): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1582-1587): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1592-1597): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1602-1607): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1612-1617): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1622-1627): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1632-1637): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1642-1647): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1652-1657): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1662-1667): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1676-1681): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1686-1691): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1696-1701): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1706-1711): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1716-1721): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1726-1731): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1736-1741): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1746-1751): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1756-1761): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1766-1771): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1776-1781): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1786-1791): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1796-1801): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1806-1811): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1816-1821): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1826-1831): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1840-1845): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1850-1855): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1860-1865): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1870-1875): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1880-1885): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1890-1895): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1900-1905): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1910-1915): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1920-1925): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1930-1935): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1940-1945): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1950-1955): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1960-1965): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1970-1975): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1980-1985): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (1990-1995): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2004-2009): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2014-2019): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2024-2029): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2034-2039): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2044-2049): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2054-2059): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2064-2069): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2074-2079): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2084-2089): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2094-2099): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2104-2109): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2114-2119): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2124-2129): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2134-2139): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2144-2149): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2154-2159): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2168-2173): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2178-2183): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2188-2193): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2198-2203): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2208-2213): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2218-2223): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2228-2233): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2238-2243): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2248-2253): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2258-2263): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2268-2273): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2278-2283): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2288-2293): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2298-2303): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2308-2313): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2318-2323): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2332-2337): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2342-2347): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2352-2357): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2362-2367): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2372-2377): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2382-2387): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2392-2397): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2402-2407): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2412-2417): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2422-2427): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2432-2437): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2442-2447): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2452-2457): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2462-2467): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2472-2477): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2482-2487): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2496-2501): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2506-2511): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2516-2521): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2526-2531): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2536-2541): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2546-2551): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2556-2561): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2566-2571): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2576-2581): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2586-2591): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2596-2601): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2606-2611): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2616-2621): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2626-2631): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2636-2641): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2646-2651): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2660-2665): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2670-2675): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2680-2685): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2690-2695): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2700-2705): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2710-2715): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2720-2725): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2730-2735): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2740-2745): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2750-2755): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2760-2765): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2770-2775): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2780-2785): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2790-2795): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2800-2805): "x" is not a valid type (user defined types are not yet supported). -// TypeError 5473: (2810-2815): "x" is not a valid type (user defined types are not yet supported). +// ParserError 5473: (200-205): Types are not valid in untyped Yul. +// ParserError 5473: (210-215): Types are not valid in untyped Yul. +// ParserError 5473: (220-225): Types are not valid in untyped Yul. +// ParserError 5473: (230-235): Types are not valid in untyped Yul. +// ParserError 5473: (240-245): Types are not valid in untyped Yul. +// ParserError 5473: (250-255): Types are not valid in untyped Yul. +// ParserError 5473: (260-265): Types are not valid in untyped Yul. +// ParserError 5473: (270-275): Types are not valid in untyped Yul. +// ParserError 5473: (280-285): Types are not valid in untyped Yul. +// ParserError 5473: (290-295): Types are not valid in untyped Yul. +// ParserError 5473: (300-305): Types are not valid in untyped Yul. +// ParserError 5473: (310-315): Types are not valid in untyped Yul. +// ParserError 5473: (320-325): Types are not valid in untyped Yul. +// ParserError 5473: (330-335): Types are not valid in untyped Yul. +// ParserError 5473: (340-345): Types are not valid in untyped Yul. +// ParserError 5473: (350-355): Types are not valid in untyped Yul. +// ParserError 5473: (364-369): Types are not valid in untyped Yul. +// ParserError 5473: (374-379): Types are not valid in untyped Yul. +// ParserError 5473: (384-389): Types are not valid in untyped Yul. +// ParserError 5473: (394-399): Types are not valid in untyped Yul. +// ParserError 5473: (404-409): Types are not valid in untyped Yul. +// ParserError 5473: (414-419): Types are not valid in untyped Yul. +// ParserError 5473: (424-429): Types are not valid in untyped Yul. +// ParserError 5473: (434-439): Types are not valid in untyped Yul. +// ParserError 5473: (444-449): Types are not valid in untyped Yul. +// ParserError 5473: (454-459): Types are not valid in untyped Yul. +// ParserError 5473: (464-469): Types are not valid in untyped Yul. +// ParserError 5473: (474-479): Types are not valid in untyped Yul. +// ParserError 5473: (484-489): Types are not valid in untyped Yul. +// ParserError 5473: (494-499): Types are not valid in untyped Yul. +// ParserError 5473: (504-509): Types are not valid in untyped Yul. +// ParserError 5473: (514-519): Types are not valid in untyped Yul. +// ParserError 5473: (528-533): Types are not valid in untyped Yul. +// ParserError 5473: (538-543): Types are not valid in untyped Yul. +// ParserError 5473: (548-553): Types are not valid in untyped Yul. +// ParserError 5473: (558-563): Types are not valid in untyped Yul. +// ParserError 5473: (568-573): Types are not valid in untyped Yul. +// ParserError 5473: (578-583): Types are not valid in untyped Yul. +// ParserError 5473: (588-593): Types are not valid in untyped Yul. +// ParserError 5473: (598-603): Types are not valid in untyped Yul. +// ParserError 5473: (608-613): Types are not valid in untyped Yul. +// ParserError 5473: (618-623): Types are not valid in untyped Yul. +// ParserError 5473: (628-633): Types are not valid in untyped Yul. +// ParserError 5473: (638-643): Types are not valid in untyped Yul. +// ParserError 5473: (648-653): Types are not valid in untyped Yul. +// ParserError 5473: (658-663): Types are not valid in untyped Yul. +// ParserError 5473: (668-673): Types are not valid in untyped Yul. +// ParserError 5473: (678-683): Types are not valid in untyped Yul. +// ParserError 5473: (692-697): Types are not valid in untyped Yul. +// ParserError 5473: (702-707): Types are not valid in untyped Yul. +// ParserError 5473: (712-717): Types are not valid in untyped Yul. +// ParserError 5473: (722-727): Types are not valid in untyped Yul. +// ParserError 5473: (732-737): Types are not valid in untyped Yul. +// ParserError 5473: (742-747): Types are not valid in untyped Yul. +// ParserError 5473: (752-757): Types are not valid in untyped Yul. +// ParserError 5473: (762-767): Types are not valid in untyped Yul. +// ParserError 5473: (772-777): Types are not valid in untyped Yul. +// ParserError 5473: (782-787): Types are not valid in untyped Yul. +// ParserError 5473: (792-797): Types are not valid in untyped Yul. +// ParserError 5473: (802-807): Types are not valid in untyped Yul. +// ParserError 5473: (812-817): Types are not valid in untyped Yul. +// ParserError 5473: (822-827): Types are not valid in untyped Yul. +// ParserError 5473: (832-837): Types are not valid in untyped Yul. +// ParserError 5473: (842-847): Types are not valid in untyped Yul. +// ParserError 5473: (856-861): Types are not valid in untyped Yul. +// ParserError 5473: (866-871): Types are not valid in untyped Yul. +// ParserError 5473: (876-881): Types are not valid in untyped Yul. +// ParserError 5473: (886-891): Types are not valid in untyped Yul. +// ParserError 5473: (896-901): Types are not valid in untyped Yul. +// ParserError 5473: (906-911): Types are not valid in untyped Yul. +// ParserError 5473: (916-921): Types are not valid in untyped Yul. +// ParserError 5473: (926-931): Types are not valid in untyped Yul. +// ParserError 5473: (936-941): Types are not valid in untyped Yul. +// ParserError 5473: (946-951): Types are not valid in untyped Yul. +// ParserError 5473: (956-961): Types are not valid in untyped Yul. +// ParserError 5473: (966-971): Types are not valid in untyped Yul. +// ParserError 5473: (976-981): Types are not valid in untyped Yul. +// ParserError 5473: (986-991): Types are not valid in untyped Yul. +// ParserError 5473: (996-1001): Types are not valid in untyped Yul. +// ParserError 5473: (1006-1011): Types are not valid in untyped Yul. +// ParserError 5473: (1020-1025): Types are not valid in untyped Yul. +// ParserError 5473: (1030-1035): Types are not valid in untyped Yul. +// ParserError 5473: (1040-1045): Types are not valid in untyped Yul. +// ParserError 5473: (1050-1055): Types are not valid in untyped Yul. +// ParserError 5473: (1060-1065): Types are not valid in untyped Yul. +// ParserError 5473: (1070-1075): Types are not valid in untyped Yul. +// ParserError 5473: (1080-1085): Types are not valid in untyped Yul. +// ParserError 5473: (1090-1095): Types are not valid in untyped Yul. +// ParserError 5473: (1100-1105): Types are not valid in untyped Yul. +// ParserError 5473: (1110-1115): Types are not valid in untyped Yul. +// ParserError 5473: (1120-1125): Types are not valid in untyped Yul. +// ParserError 5473: (1130-1135): Types are not valid in untyped Yul. +// ParserError 5473: (1140-1145): Types are not valid in untyped Yul. +// ParserError 5473: (1150-1155): Types are not valid in untyped Yul. +// ParserError 5473: (1160-1165): Types are not valid in untyped Yul. +// ParserError 5473: (1170-1175): Types are not valid in untyped Yul. +// ParserError 5473: (1184-1189): Types are not valid in untyped Yul. +// ParserError 5473: (1194-1199): Types are not valid in untyped Yul. +// ParserError 5473: (1204-1209): Types are not valid in untyped Yul. +// ParserError 5473: (1214-1219): Types are not valid in untyped Yul. +// ParserError 5473: (1224-1229): Types are not valid in untyped Yul. +// ParserError 5473: (1234-1239): Types are not valid in untyped Yul. +// ParserError 5473: (1244-1249): Types are not valid in untyped Yul. +// ParserError 5473: (1254-1259): Types are not valid in untyped Yul. +// ParserError 5473: (1264-1269): Types are not valid in untyped Yul. +// ParserError 5473: (1274-1279): Types are not valid in untyped Yul. +// ParserError 5473: (1284-1289): Types are not valid in untyped Yul. +// ParserError 5473: (1294-1299): Types are not valid in untyped Yul. +// ParserError 5473: (1304-1309): Types are not valid in untyped Yul. +// ParserError 5473: (1314-1319): Types are not valid in untyped Yul. +// ParserError 5473: (1324-1329): Types are not valid in untyped Yul. +// ParserError 5473: (1334-1339): Types are not valid in untyped Yul. +// ParserError 5473: (1348-1353): Types are not valid in untyped Yul. +// ParserError 5473: (1358-1363): Types are not valid in untyped Yul. +// ParserError 5473: (1368-1373): Types are not valid in untyped Yul. +// ParserError 5473: (1378-1383): Types are not valid in untyped Yul. +// ParserError 5473: (1388-1393): Types are not valid in untyped Yul. +// ParserError 5473: (1398-1403): Types are not valid in untyped Yul. +// ParserError 5473: (1408-1413): Types are not valid in untyped Yul. +// ParserError 5473: (1418-1423): Types are not valid in untyped Yul. +// ParserError 5473: (1428-1433): Types are not valid in untyped Yul. +// ParserError 5473: (1438-1443): Types are not valid in untyped Yul. +// ParserError 5473: (1448-1453): Types are not valid in untyped Yul. +// ParserError 5473: (1458-1463): Types are not valid in untyped Yul. +// ParserError 5473: (1468-1473): Types are not valid in untyped Yul. +// ParserError 5473: (1478-1483): Types are not valid in untyped Yul. +// ParserError 5473: (1488-1493): Types are not valid in untyped Yul. +// ParserError 5473: (1498-1503): Types are not valid in untyped Yul. +// ParserError 5473: (1512-1517): Types are not valid in untyped Yul. +// ParserError 5473: (1522-1527): Types are not valid in untyped Yul. +// ParserError 5473: (1532-1537): Types are not valid in untyped Yul. +// ParserError 5473: (1542-1547): Types are not valid in untyped Yul. +// ParserError 5473: (1552-1557): Types are not valid in untyped Yul. +// ParserError 5473: (1562-1567): Types are not valid in untyped Yul. +// ParserError 5473: (1572-1577): Types are not valid in untyped Yul. +// ParserError 5473: (1582-1587): Types are not valid in untyped Yul. +// ParserError 5473: (1592-1597): Types are not valid in untyped Yul. +// ParserError 5473: (1602-1607): Types are not valid in untyped Yul. +// ParserError 5473: (1612-1617): Types are not valid in untyped Yul. +// ParserError 5473: (1622-1627): Types are not valid in untyped Yul. +// ParserError 5473: (1632-1637): Types are not valid in untyped Yul. +// ParserError 5473: (1642-1647): Types are not valid in untyped Yul. +// ParserError 5473: (1652-1657): Types are not valid in untyped Yul. +// ParserError 5473: (1662-1667): Types are not valid in untyped Yul. +// ParserError 5473: (1676-1681): Types are not valid in untyped Yul. +// ParserError 5473: (1686-1691): Types are not valid in untyped Yul. +// ParserError 5473: (1696-1701): Types are not valid in untyped Yul. +// ParserError 5473: (1706-1711): Types are not valid in untyped Yul. +// ParserError 5473: (1716-1721): Types are not valid in untyped Yul. +// ParserError 5473: (1726-1731): Types are not valid in untyped Yul. +// ParserError 5473: (1736-1741): Types are not valid in untyped Yul. +// ParserError 5473: (1746-1751): Types are not valid in untyped Yul. +// ParserError 5473: (1756-1761): Types are not valid in untyped Yul. +// ParserError 5473: (1766-1771): Types are not valid in untyped Yul. +// ParserError 5473: (1776-1781): Types are not valid in untyped Yul. +// ParserError 5473: (1786-1791): Types are not valid in untyped Yul. +// ParserError 5473: (1796-1801): Types are not valid in untyped Yul. +// ParserError 5473: (1806-1811): Types are not valid in untyped Yul. +// ParserError 5473: (1816-1821): Types are not valid in untyped Yul. +// ParserError 5473: (1826-1831): Types are not valid in untyped Yul. +// ParserError 5473: (1840-1845): Types are not valid in untyped Yul. +// ParserError 5473: (1850-1855): Types are not valid in untyped Yul. +// ParserError 5473: (1860-1865): Types are not valid in untyped Yul. +// ParserError 5473: (1870-1875): Types are not valid in untyped Yul. +// ParserError 5473: (1880-1885): Types are not valid in untyped Yul. +// ParserError 5473: (1890-1895): Types are not valid in untyped Yul. +// ParserError 5473: (1900-1905): Types are not valid in untyped Yul. +// ParserError 5473: (1910-1915): Types are not valid in untyped Yul. +// ParserError 5473: (1920-1925): Types are not valid in untyped Yul. +// ParserError 5473: (1930-1935): Types are not valid in untyped Yul. +// ParserError 5473: (1940-1945): Types are not valid in untyped Yul. +// ParserError 5473: (1950-1955): Types are not valid in untyped Yul. +// ParserError 5473: (1960-1965): Types are not valid in untyped Yul. +// ParserError 5473: (1970-1975): Types are not valid in untyped Yul. +// ParserError 5473: (1980-1985): Types are not valid in untyped Yul. +// ParserError 5473: (1990-1995): Types are not valid in untyped Yul. +// ParserError 5473: (2004-2009): Types are not valid in untyped Yul. +// ParserError 5473: (2014-2019): Types are not valid in untyped Yul. +// ParserError 5473: (2024-2029): Types are not valid in untyped Yul. +// ParserError 5473: (2034-2039): Types are not valid in untyped Yul. +// ParserError 5473: (2044-2049): Types are not valid in untyped Yul. +// ParserError 5473: (2054-2059): Types are not valid in untyped Yul. +// ParserError 5473: (2064-2069): Types are not valid in untyped Yul. +// ParserError 5473: (2074-2079): Types are not valid in untyped Yul. +// ParserError 5473: (2084-2089): Types are not valid in untyped Yul. +// ParserError 5473: (2094-2099): Types are not valid in untyped Yul. +// ParserError 5473: (2104-2109): Types are not valid in untyped Yul. +// ParserError 5473: (2114-2119): Types are not valid in untyped Yul. +// ParserError 5473: (2124-2129): Types are not valid in untyped Yul. +// ParserError 5473: (2134-2139): Types are not valid in untyped Yul. +// ParserError 5473: (2144-2149): Types are not valid in untyped Yul. +// ParserError 5473: (2154-2159): Types are not valid in untyped Yul. +// ParserError 5473: (2168-2173): Types are not valid in untyped Yul. +// ParserError 5473: (2178-2183): Types are not valid in untyped Yul. +// ParserError 5473: (2188-2193): Types are not valid in untyped Yul. +// ParserError 5473: (2198-2203): Types are not valid in untyped Yul. +// ParserError 5473: (2208-2213): Types are not valid in untyped Yul. +// ParserError 5473: (2218-2223): Types are not valid in untyped Yul. +// ParserError 5473: (2228-2233): Types are not valid in untyped Yul. +// ParserError 5473: (2238-2243): Types are not valid in untyped Yul. +// ParserError 5473: (2248-2253): Types are not valid in untyped Yul. +// ParserError 5473: (2258-2263): Types are not valid in untyped Yul. +// ParserError 5473: (2268-2273): Types are not valid in untyped Yul. +// ParserError 5473: (2278-2283): Types are not valid in untyped Yul. +// ParserError 5473: (2288-2293): Types are not valid in untyped Yul. +// ParserError 5473: (2298-2303): Types are not valid in untyped Yul. +// ParserError 5473: (2308-2313): Types are not valid in untyped Yul. +// ParserError 5473: (2318-2323): Types are not valid in untyped Yul. +// ParserError 5473: (2332-2337): Types are not valid in untyped Yul. +// ParserError 5473: (2342-2347): Types are not valid in untyped Yul. +// ParserError 5473: (2352-2357): Types are not valid in untyped Yul. +// ParserError 5473: (2362-2367): Types are not valid in untyped Yul. +// ParserError 5473: (2372-2377): Types are not valid in untyped Yul. +// ParserError 5473: (2382-2387): Types are not valid in untyped Yul. +// ParserError 5473: (2392-2397): Types are not valid in untyped Yul. +// ParserError 5473: (2402-2407): Types are not valid in untyped Yul. +// ParserError 5473: (2412-2417): Types are not valid in untyped Yul. +// ParserError 5473: (2422-2427): Types are not valid in untyped Yul. +// ParserError 5473: (2432-2437): Types are not valid in untyped Yul. +// ParserError 5473: (2442-2447): Types are not valid in untyped Yul. +// ParserError 5473: (2452-2457): Types are not valid in untyped Yul. +// ParserError 5473: (2462-2467): Types are not valid in untyped Yul. +// ParserError 5473: (2472-2477): Types are not valid in untyped Yul. +// ParserError 5473: (2482-2487): Types are not valid in untyped Yul. +// ParserError 5473: (2496-2501): Types are not valid in untyped Yul. +// ParserError 5473: (2506-2511): Types are not valid in untyped Yul. +// ParserError 5473: (2516-2521): Types are not valid in untyped Yul. +// ParserError 5473: (2526-2531): Types are not valid in untyped Yul. +// ParserError 5473: (2536-2541): Types are not valid in untyped Yul. +// ParserError 5473: (2546-2551): Types are not valid in untyped Yul. +// ParserError 5473: (2556-2561): Types are not valid in untyped Yul. +// ParserError 5473: (2566-2571): Types are not valid in untyped Yul. +// ParserError 5473: (2576-2581): Types are not valid in untyped Yul. +// ParserError 5473: (2586-2591): Types are not valid in untyped Yul. +// ParserError 5473: (2596-2601): Types are not valid in untyped Yul. +// ParserError 5473: (2606-2611): Types are not valid in untyped Yul. +// ParserError 5473: (2616-2621): Types are not valid in untyped Yul. +// ParserError 5473: (2626-2631): Types are not valid in untyped Yul. +// ParserError 5473: (2636-2641): Types are not valid in untyped Yul. +// ParserError 5473: (2646-2651): Types are not valid in untyped Yul. +// ParserError 5473: (2660-2665): Types are not valid in untyped Yul. +// ParserError 5473: (2670-2675): Types are not valid in untyped Yul. +// ParserError 5473: (2680-2685): Types are not valid in untyped Yul. +// ParserError 5473: (2690-2695): Types are not valid in untyped Yul. +// ParserError 5473: (2700-2705): Types are not valid in untyped Yul. +// ParserError 5473: (2710-2715): Types are not valid in untyped Yul. +// ParserError 5473: (2720-2725): Types are not valid in untyped Yul. +// ParserError 5473: (2730-2735): Types are not valid in untyped Yul. +// ParserError 5473: (2740-2745): Types are not valid in untyped Yul. +// ParserError 5473: (2750-2755): Types are not valid in untyped Yul. +// ParserError 5473: (2760-2765): Types are not valid in untyped Yul. +// ParserError 5473: (2770-2775): Types are not valid in untyped Yul. +// ParserError 5473: (2780-2785): Types are not valid in untyped Yul. +// ParserError 5473: (2790-2795): Types are not valid in untyped Yul. +// ParserError 5473: (2800-2805): Types are not valid in untyped Yul. +// ParserError 5473: (2810-2815): Types are not valid in untyped Yul. // Warning 4013: There are more than 256 errors. Aborting. From fbaa505de5356aed03979b0bbc3395bbbfcd3a9e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 16 Aug 2024 12:05:56 +0200 Subject: [PATCH 0282/1340] Yul: Builtins now record number of args and rets instead of respective vectors of types --- libyul/AsmAnalysis.cpp | 4 ++-- libyul/Dialect.h | 5 ++--- libyul/backends/evm/ControlFlowGraphBuilder.cpp | 2 +- libyul/backends/evm/EVMDialect.cpp | 8 ++++---- libyul/backends/evm/EVMDialect.h | 1 - libyul/backends/evm/NoOutputAssembly.cpp | 2 +- libyul/backends/evm/OptimizedEVMCodeTransform.cpp | 2 +- test/libyul/Parser.cpp | 2 +- 8 files changed, 12 insertions(+), 14 deletions(-) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index d039b3b47..faa849fe1 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -327,8 +327,8 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) "The use of transient storage for reentrancy guards that are cleared at the end of the call is safe." ); - numParameters = f->parameters.size(); - numReturns = f->returns.size(); + numParameters = f->numParameters; + numReturns = f->numReturns; if (!f->literalArguments.empty()) literalArguments = &f->literalArguments; diff --git a/libyul/Dialect.h b/libyul/Dialect.h index f9ce01469..3589e953f 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -32,7 +32,6 @@ namespace solidity::yul { -using Type = YulName; enum class LiteralKind; class LiteralValue; struct Literal; @@ -40,8 +39,8 @@ struct Literal; struct BuiltinFunction { YulName name; - std::vector parameters; - std::vector returns; + size_t numParameters; + size_t numReturns; SideEffects sideEffects; ControlFlowSideEffects controlFlowSideEffects; /// If true, this is the msize instruction or might contain it. diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 596c6c961..46ef933ba 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -527,7 +527,7 @@ Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _cal // input std::move(inputs), // output - ranges::views::iota(0u, builtin->returns.size()) | ranges::views::transform([&](size_t _i) { + ranges::views::iota(0u, builtin->numReturns) | ranges::views::transform([&](size_t _i) { return TemporarySlot{_call, _i}; }) | ranges::to, // operation diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index aeb825304..dd5cad1dd 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -50,8 +50,8 @@ std::pair createEVMFunction( evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction, _evmVersion); BuiltinFunctionForEVM f; f.name = YulName{_name}; - f.parameters.resize(static_cast(info.args)); - f.returns.resize(static_cast(info.ret)); + f.numParameters = static_cast(info.args); + f.numReturns = static_cast(info.ret); f.sideEffects = EVMDialect::sideEffectsOfInstruction(_instruction); if (evmasm::SemanticInformation::terminatesControlFlow(_instruction)) { @@ -96,8 +96,8 @@ std::pair createFunction( YulName name{std::move(_name)}; BuiltinFunctionForEVM f; f.name = name; - f.parameters.resize(_params); - f.returns.resize(_returns); + f.numParameters = _params; + f.numReturns = _returns; f.sideEffects = std::move(_sideEffects); f.literalArguments = std::move(_literalArguments); f.isMSize = false; diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 3207b8fae..3627a7fea 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -33,7 +33,6 @@ namespace solidity::yul { -using Type = YulName; struct FunctionCall; struct Object; diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 71818d248..04324fa06 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -134,7 +134,7 @@ NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom): { for (auto& fun: m_functions) { - size_t returns = fun.second.returns.size(); + size_t returns = fun.second.numReturns; fun.second.generateCode = [=](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) { for (size_t i: ranges::views::iota(0u, _call.arguments.size())) diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 6395ea64a..8ef01f0b6 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -147,7 +147,7 @@ void OptimizedEVMCodeTransform::operator()(CFG::BuiltinCall const& _call) for (size_t i = 0; i < _call.arguments; ++i) m_stack.pop_back(); // Push return values to m_stack. - for (size_t index: ranges::views::iota(0u, _call.builtin.get().returns.size())) + for (size_t index: ranges::views::iota(0u, _call.builtin.get().numReturns)) m_stack.emplace_back(TemporarySlot{_call.functionCall, index}); yulAssert(m_assembly.stackHeight() == static_cast(m_stack.size()), ""); } diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 2a2f28092..9b8ce4292 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE(builtins_analysis) { return _name == "builtin"_yulname ? &f : nullptr; } - BuiltinFunction f{"builtin"_yulname, std::vector(2), std::vector(3), {}, {}, false, {}}; + BuiltinFunction f{"builtin"_yulname, 2, 3, {}, {}, false, {}}; }; SimpleDialect dialect; From 4938075b94089fd4fedb15177f984512f7efd5c6 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 27 Aug 2024 10:35:59 +0200 Subject: [PATCH 0283/1340] Yul: Improve variable naming and type error message wording, update tests. --- libyul/AsmAnalysis.cpp | 7 +- libyul/AsmAnalysis.h | 4 +- libyul/AsmJsonConverter.cpp | 3 + libyul/AsmJsonImporter.cpp | 8 +- libyul/AsmParser.cpp | 16 +- libyul/AsmParser.h | 2 +- test/libyul/yulSyntaxTests/invalid_type.yul | 2 +- test/libyul/yulSyntaxTests/invalid_type2.yul | 2 +- test/libyul/yulSyntaxTests/invalid_type3.yul | 4 +- test/libyul/yulSyntaxTests/invalid_type4.yul | 2 +- .../yulSyntaxTests/literal_invalid_type.yul | 2 +- .../more_than_256_analysis_errors.yul | 565 +++++++++--------- 12 files changed, 320 insertions(+), 297 deletions(-) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index faa849fe1..64630fa2b 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -380,7 +380,6 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) std::to_string(_funCall.arguments.size()) + "." ); - size_t numArgs{0}; for (size_t i = _funCall.arguments.size(); i > 0; i--) { Expression const& arg = _funCall.arguments[i - 1]; @@ -427,18 +426,16 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) ); } expectUnlimitedStringLiteral(std::get(arg)); - ++numArgs; continue; } } expectExpression(arg); - ++numArgs; } if (watcher.ok()) { - yulAssert(numParameters && numParameters == numArgs, ""); - yulAssert(numReturns, ""); + yulAssert(numParameters && numParameters == _funCall.arguments.size()); + yulAssert(numReturns); return *numReturns; } else if (numReturns) diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index d01ecc190..64cab51f5 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -102,8 +102,8 @@ class AsmAnalyzer /// @returns the worst side effects encountered during analysis (including within defined functions). SideEffects const& sideEffects() const { return m_sideEffects; } private: - /// Visits the expression, expects that it evaluates to exactly one value and - /// returns the type. Reports errors on errors and returns the default type. + /// Visits the expression, expects that it evaluates to exactly one value. + /// Reports errors otherwise. void expectExpression(Expression const& _expr); void expectUnlimitedStringLiteral(Literal const& _literal); diff --git a/libyul/AsmJsonConverter.cpp b/libyul/AsmJsonConverter.cpp index d85b96f8f..226ac52a5 100644 --- a/libyul/AsmJsonConverter.cpp +++ b/libyul/AsmJsonConverter.cpp @@ -42,6 +42,9 @@ Json AsmJsonConverter::operator()(NameWithDebugData const& _node) const yulAssert(!_node.name.empty(), "Invalid variable name."); Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulTypedName"); ret["name"] = _node.name.str(); + // even though types are removed from Yul, we keep this field in the Json interface to not introduce + // a breaking change + // can be removed with the next breaking version ret["type"] = ""; return ret; } diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index 6de7bb6ab..459d9d9be 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -177,7 +177,13 @@ Literal AsmJsonImporter::createLiteral(Json const& _node) value = member(_node, "value").get(); { auto const typeNode = member(_node, "type"); - yulAssert(typeNode.empty() || typeNode.get().empty()); + yulAssert( + typeNode.empty() || typeNode.get().empty(), + fmt::format( + "Expected literal types to be either empty or absent in the JSON. Got \"{}\".", + typeNode.get() + ) + ); } if (kind == "number") { diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index bd890c4aa..d41b41a36 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -567,7 +567,7 @@ std::variant Parser::parseLiteralOrIdentifier(bool _unlimit break; } - auto const beginOfLiteralLoc = currentLocation(); + auto const literalLocation = currentLocation(); Literal literal{ createDebugData(), kind, @@ -578,9 +578,9 @@ std::variant Parser::parseLiteralOrIdentifier(bool _unlimit { expectToken(Token::Colon); updateLocationEndFrom(literal.debugData, currentLocation()); - auto const loc = SourceLocation::smallestCovering(beginOfLiteralLoc, currentLocation()); + auto const typedLiteralLocation = SourceLocation::smallestCovering(literalLocation, currentLocation()); std::ignore = expectAsmIdentifier(); - expectUntyped(loc); + raiseUnsupportedTypesError(typedLiteralLocation); } return literal; @@ -701,15 +701,15 @@ NameWithDebugData Parser::parseNameWithDebugData() { RecursionGuard recursionGuard(*this); NameWithDebugData typedName = createWithDebugData(); - auto const locNameStart = currentLocation(); + auto const nameLocation = currentLocation(); typedName.name = expectAsmIdentifier(); if (currentToken() == Token::Colon) { expectToken(Token::Colon); updateLocationEndFrom(typedName.debugData, currentLocation()); - auto const loc = SourceLocation::smallestCovering(locNameStart, currentLocation()); + auto const typedNameLocation = SourceLocation::smallestCovering(nameLocation, currentLocation()); std::ignore = expectAsmIdentifier(); - expectUntyped(loc); + raiseUnsupportedTypesError(typedNameLocation); } return typedName; @@ -760,7 +760,7 @@ bool Parser::isValidNumberLiteral(std::string const& _literal) return _literal.find_first_not_of("0123456789") == std::string::npos; } -void Parser::expectUntyped(SourceLocation const& loc) +void Parser::raiseUnsupportedTypesError(SourceLocation const& _location) const { - m_errorReporter.parserError(5473_error, loc, "Types are not valid in untyped Yul."); + m_errorReporter.parserError(5473_error, _location, "Types are not supported in untyped Yul."); } diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 42ed2ca84..d4616a2a9 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -147,7 +147,7 @@ class Parser: public langutil::ParserBase FunctionCall parseCall(std::variant&& _initialOp); NameWithDebugData parseNameWithDebugData(); YulName expectAsmIdentifier(); - void expectUntyped(langutil::SourceLocation const& loc); + void raiseUnsupportedTypesError(langutil::SourceLocation const& _location) const; /// Reports an error if we are currently not inside the body part of a for loop. void checkBreakContinuePosition(std::string const& _which); diff --git a/test/libyul/yulSyntaxTests/invalid_type.yul b/test/libyul/yulSyntaxTests/invalid_type.yul index e9a4e30c9..69f20b705 100644 --- a/test/libyul/yulSyntaxTests/invalid_type.yul +++ b/test/libyul/yulSyntaxTests/invalid_type.yul @@ -2,4 +2,4 @@ let x: invalidType } // ---- -// ParserError 5473: (10-24): Types are not valid in untyped Yul. +// ParserError 5473: (10-24): Types are not supported in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/invalid_type2.yul b/test/libyul/yulSyntaxTests/invalid_type2.yul index 5eb514866..ab26f6925 100644 --- a/test/libyul/yulSyntaxTests/invalid_type2.yul +++ b/test/libyul/yulSyntaxTests/invalid_type2.yul @@ -2,4 +2,4 @@ let x := 1:invalidType } // ---- -// ParserError 5473: (15-28): Types are not valid in untyped Yul. +// ParserError 5473: (15-28): Types are not supported in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/invalid_type3.yul b/test/libyul/yulSyntaxTests/invalid_type3.yul index 9814527b0..866d855ad 100644 --- a/test/libyul/yulSyntaxTests/invalid_type3.yul +++ b/test/libyul/yulSyntaxTests/invalid_type3.yul @@ -2,5 +2,5 @@ function f(a: invalidType) -> b: invalidType {} } // ---- -// ParserError 5473: (17-31): Types are not valid in untyped Yul. -// ParserError 5473: (36-50): Types are not valid in untyped Yul. +// ParserError 5473: (17-31): Types are not supported in untyped Yul. +// ParserError 5473: (36-50): Types are not supported in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/invalid_type4.yul b/test/libyul/yulSyntaxTests/invalid_type4.yul index 4924a592a..e6ec73b7a 100644 --- a/test/libyul/yulSyntaxTests/invalid_type4.yul +++ b/test/libyul/yulSyntaxTests/invalid_type4.yul @@ -3,4 +3,4 @@ case 8: invalidType {} } // ---- -// ParserError 5473: (24-38): Types are not valid in untyped Yul. +// ParserError 5473: (24-38): Types are not supported in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/literal_invalid_type.yul b/test/libyul/yulSyntaxTests/literal_invalid_type.yul index 10a280120..c0e6dccdf 100644 --- a/test/libyul/yulSyntaxTests/literal_invalid_type.yul +++ b/test/libyul/yulSyntaxTests/literal_invalid_type.yul @@ -2,4 +2,4 @@ let x := true:unhappy } // ---- -// ParserError 5473: (15-27): Types are not valid in untyped Yul. +// ParserError 5473: (15-27): Types are not supported in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul b/test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul index edd7871a7..031944953 100644 --- a/test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul +++ b/test/libyul/yulSyntaxTests/more_than_256_analysis_errors.yul @@ -1,279 +1,296 @@ { - // There's no type called 'x' so every declaration here should trigger an error. + // Using a variable to initialize itself should trigger a "variable is used before declared" error. // It's only detected during analysis and is not fatal. Any other non-fatal analysis error would do. - let $00:x let $10:x let $20:x let $30:x let $40:x let $50:x let $60:x let $70:x let $80:x let $90:x let $a0:x let $b0:x let $c0:x let $d0:x let $e0:x let $f0:x - let $01:x let $11:x let $21:x let $31:x let $41:x let $51:x let $61:x let $71:x let $81:x let $91:x let $a1:x let $b1:x let $c1:x let $d1:x let $e1:x let $f1:x - let $02:x let $12:x let $22:x let $32:x let $42:x let $52:x let $62:x let $72:x let $82:x let $92:x let $a2:x let $b2:x let $c2:x let $d2:x let $e2:x let $f2:x - let $03:x let $13:x let $23:x let $33:x let $43:x let $53:x let $63:x let $73:x let $83:x let $93:x let $a3:x let $b3:x let $c3:x let $d3:x let $e3:x let $f3:x - let $04:x let $14:x let $24:x let $34:x let $44:x let $54:x let $64:x let $74:x let $84:x let $94:x let $a4:x let $b4:x let $c4:x let $d4:x let $e4:x let $f4:x - let $05:x let $15:x let $25:x let $35:x let $45:x let $55:x let $65:x let $75:x let $85:x let $95:x let $a5:x let $b5:x let $c5:x let $d5:x let $e5:x let $f5:x - let $06:x let $16:x let $26:x let $36:x let $46:x let $56:x let $66:x let $76:x let $86:x let $96:x let $a6:x let $b6:x let $c6:x let $d6:x let $e6:x let $f6:x - let $07:x let $17:x let $27:x let $37:x let $47:x let $57:x let $67:x let $77:x let $87:x let $97:x let $a7:x let $b7:x let $c7:x let $d7:x let $e7:x let $f7:x - let $08:x let $18:x let $28:x let $38:x let $48:x let $58:x let $68:x let $78:x let $88:x let $98:x let $a8:x let $b8:x let $c8:x let $d8:x let $e8:x let $f8:x - let $09:x let $19:x let $29:x let $39:x let $49:x let $59:x let $69:x let $79:x let $89:x let $99:x let $a9:x let $b9:x let $c9:x let $d9:x let $e9:x let $f9:x - let $0a:x let $1a:x let $2a:x let $3a:x let $4a:x let $5a:x let $6a:x let $7a:x let $8a:x let $9a:x let $aa:x let $ba:x let $ca:x let $da:x let $ea:x let $fa:x - let $0b:x let $1b:x let $2b:x let $3b:x let $4b:x let $5b:x let $6b:x let $7b:x let $8b:x let $9b:x let $ab:x let $bb:x let $cb:x let $db:x let $eb:x let $fb:x - let $0c:x let $1c:x let $2c:x let $3c:x let $4c:x let $5c:x let $6c:x let $7c:x let $8c:x let $9c:x let $ac:x let $bc:x let $cc:x let $dc:x let $ec:x let $fc:x - let $0d:x let $1d:x let $2d:x let $3d:x let $4d:x let $5d:x let $6d:x let $7d:x let $8d:x let $9d:x let $ad:x let $bd:x let $cd:x let $dd:x let $ed:x let $fd:x - let $0e:x let $1e:x let $2e:x let $3e:x let $4e:x let $5e:x let $6e:x let $7e:x let $8e:x let $9e:x let $ae:x let $be:x let $ce:x let $de:x let $ee:x let $fe:x - let $0f:x let $1f:x let $2f:x let $3f:x let $4f:x let $5f:x let $6f:x let $7f:x let $8f:x let $9f:x let $af:x let $bf:x let $cf:x let $df:x let $ef:x let $ff:x - let $100:x + let x00:=x00 let x01:=x01 let x02:=x02 let x03:=x03 let x04:=x04 let x05:=x05 let x06:=x06 let x07:=x07 + let x08:=x08 let x09:=x09 let x0a:=x0a let x0b:=x0b let x0c:=x0c let x0d:=x0d let x0e:=x0e let x0f:=x0f + let x10:=x10 let x11:=x11 let x12:=x12 let x13:=x13 let x14:=x14 let x15:=x15 let x16:=x16 let x17:=x17 + let x18:=x18 let x19:=x19 let x1a:=x1a let x1b:=x1b let x1c:=x1c let x1d:=x1d let x1e:=x1e let x1f:=x1f + let x20:=x20 let x21:=x21 let x22:=x22 let x23:=x23 let x24:=x24 let x25:=x25 let x26:=x26 let x27:=x27 + let x28:=x28 let x29:=x29 let x2a:=x2a let x2b:=x2b let x2c:=x2c let x2d:=x2d let x2e:=x2e let x2f:=x2f + let x30:=x30 let x31:=x31 let x32:=x32 let x33:=x33 let x34:=x34 let x35:=x35 let x36:=x36 let x37:=x37 + let x38:=x38 let x39:=x39 let x3a:=x3a let x3b:=x3b let x3c:=x3c let x3d:=x3d let x3e:=x3e let x3f:=x3f + let x40:=x40 let x41:=x41 let x42:=x42 let x43:=x43 let x44:=x44 let x45:=x45 let x46:=x46 let x47:=x47 + let x48:=x48 let x49:=x49 let x4a:=x4a let x4b:=x4b let x4c:=x4c let x4d:=x4d let x4e:=x4e let x4f:=x4f + let x50:=x50 let x51:=x51 let x52:=x52 let x53:=x53 let x54:=x54 let x55:=x55 let x56:=x56 let x57:=x57 + let x58:=x58 let x59:=x59 let x5a:=x5a let x5b:=x5b let x5c:=x5c let x5d:=x5d let x5e:=x5e let x5f:=x5f + let x60:=x60 let x61:=x61 let x62:=x62 let x63:=x63 let x64:=x64 let x65:=x65 let x66:=x66 let x67:=x67 + let x68:=x68 let x69:=x69 let x6a:=x6a let x6b:=x6b let x6c:=x6c let x6d:=x6d let x6e:=x6e let x6f:=x6f + let x70:=x70 let x71:=x71 let x72:=x72 let x73:=x73 let x74:=x74 let x75:=x75 let x76:=x76 let x77:=x77 + let x78:=x78 let x79:=x79 let x7a:=x7a let x7b:=x7b let x7c:=x7c let x7d:=x7d let x7e:=x7e let x7f:=x7f + let x80:=x80 let x81:=x81 let x82:=x82 let x83:=x83 let x84:=x84 let x85:=x85 let x86:=x86 let x87:=x87 + let x88:=x88 let x89:=x89 let x8a:=x8a let x8b:=x8b let x8c:=x8c let x8d:=x8d let x8e:=x8e let x8f:=x8f + let x90:=x90 let x91:=x91 let x92:=x92 let x93:=x93 let x94:=x94 let x95:=x95 let x96:=x96 let x97:=x97 + let x98:=x98 let x99:=x99 let x9a:=x9a let x9b:=x9b let x9c:=x9c let x9d:=x9d let x9e:=x9e let x9f:=x9f + let xa0:=xa0 let xa1:=xa1 let xa2:=xa2 let xa3:=xa3 let xa4:=xa4 let xa5:=xa5 let xa6:=xa6 let xa7:=xa7 + let xa8:=xa8 let xa9:=xa9 let xaa:=xaa let xab:=xab let xac:=xac let xad:=xad let xae:=xae let xaf:=xaf + let xb0:=xb0 let xb1:=xb1 let xb2:=xb2 let xb3:=xb3 let xb4:=xb4 let xb5:=xb5 let xb6:=xb6 let xb7:=xb7 + let xb8:=xb8 let xb9:=xb9 let xba:=xba let xbb:=xbb let xbc:=xbc let xbd:=xbd let xbe:=xbe let xbf:=xbf + let xc0:=xc0 let xc1:=xc1 let xc2:=xc2 let xc3:=xc3 let xc4:=xc4 let xc5:=xc5 let xc6:=xc6 let xc7:=xc7 + let xc8:=xc8 let xc9:=xc9 let xca:=xca let xcb:=xcb let xcc:=xcc let xcd:=xcd let xce:=xce let xcf:=xcf + let xd0:=xd0 let xd1:=xd1 let xd2:=xd2 let xd3:=xd3 let xd4:=xd4 let xd5:=xd5 let xd6:=xd6 let xd7:=xd7 + let xd8:=xd8 let xd9:=xd9 let xda:=xda let xdb:=xdb let xdc:=xdc let xdd:=xdd let xde:=xde let xdf:=xdf + let xe0:=xe0 let xe1:=xe1 let xe2:=xe2 let xe3:=xe3 let xe4:=xe4 let xe5:=xe5 let xe6:=xe6 let xe7:=xe7 + let xe8:=xe8 let xe9:=xe9 let xea:=xea let xeb:=xeb let xec:=xec let xed:=xed let xee:=xee let xef:=xef + let xf0:=xf0 let xf1:=xf1 let xf2:=xf2 let xf3:=xf3 let xf4:=xf4 let xf5:=xf5 let xf6:=xf6 let xf7:=xf7 + let xf8:=xf8 let xf9:=xf9 let xfa:=xfa let xfb:=xfb let xfc:=xfc let xfd:=xfd let xfe:=xfe let xff:=xff + let x100:=x100 + } // ---- -// ParserError 5473: (200-205): Types are not valid in untyped Yul. -// ParserError 5473: (210-215): Types are not valid in untyped Yul. -// ParserError 5473: (220-225): Types are not valid in untyped Yul. -// ParserError 5473: (230-235): Types are not valid in untyped Yul. -// ParserError 5473: (240-245): Types are not valid in untyped Yul. -// ParserError 5473: (250-255): Types are not valid in untyped Yul. -// ParserError 5473: (260-265): Types are not valid in untyped Yul. -// ParserError 5473: (270-275): Types are not valid in untyped Yul. -// ParserError 5473: (280-285): Types are not valid in untyped Yul. -// ParserError 5473: (290-295): Types are not valid in untyped Yul. -// ParserError 5473: (300-305): Types are not valid in untyped Yul. -// ParserError 5473: (310-315): Types are not valid in untyped Yul. -// ParserError 5473: (320-325): Types are not valid in untyped Yul. -// ParserError 5473: (330-335): Types are not valid in untyped Yul. -// ParserError 5473: (340-345): Types are not valid in untyped Yul. -// ParserError 5473: (350-355): Types are not valid in untyped Yul. -// ParserError 5473: (364-369): Types are not valid in untyped Yul. -// ParserError 5473: (374-379): Types are not valid in untyped Yul. -// ParserError 5473: (384-389): Types are not valid in untyped Yul. -// ParserError 5473: (394-399): Types are not valid in untyped Yul. -// ParserError 5473: (404-409): Types are not valid in untyped Yul. -// ParserError 5473: (414-419): Types are not valid in untyped Yul. -// ParserError 5473: (424-429): Types are not valid in untyped Yul. -// ParserError 5473: (434-439): Types are not valid in untyped Yul. -// ParserError 5473: (444-449): Types are not valid in untyped Yul. -// ParserError 5473: (454-459): Types are not valid in untyped Yul. -// ParserError 5473: (464-469): Types are not valid in untyped Yul. -// ParserError 5473: (474-479): Types are not valid in untyped Yul. -// ParserError 5473: (484-489): Types are not valid in untyped Yul. -// ParserError 5473: (494-499): Types are not valid in untyped Yul. -// ParserError 5473: (504-509): Types are not valid in untyped Yul. -// ParserError 5473: (514-519): Types are not valid in untyped Yul. -// ParserError 5473: (528-533): Types are not valid in untyped Yul. -// ParserError 5473: (538-543): Types are not valid in untyped Yul. -// ParserError 5473: (548-553): Types are not valid in untyped Yul. -// ParserError 5473: (558-563): Types are not valid in untyped Yul. -// ParserError 5473: (568-573): Types are not valid in untyped Yul. -// ParserError 5473: (578-583): Types are not valid in untyped Yul. -// ParserError 5473: (588-593): Types are not valid in untyped Yul. -// ParserError 5473: (598-603): Types are not valid in untyped Yul. -// ParserError 5473: (608-613): Types are not valid in untyped Yul. -// ParserError 5473: (618-623): Types are not valid in untyped Yul. -// ParserError 5473: (628-633): Types are not valid in untyped Yul. -// ParserError 5473: (638-643): Types are not valid in untyped Yul. -// ParserError 5473: (648-653): Types are not valid in untyped Yul. -// ParserError 5473: (658-663): Types are not valid in untyped Yul. -// ParserError 5473: (668-673): Types are not valid in untyped Yul. -// ParserError 5473: (678-683): Types are not valid in untyped Yul. -// ParserError 5473: (692-697): Types are not valid in untyped Yul. -// ParserError 5473: (702-707): Types are not valid in untyped Yul. -// ParserError 5473: (712-717): Types are not valid in untyped Yul. -// ParserError 5473: (722-727): Types are not valid in untyped Yul. -// ParserError 5473: (732-737): Types are not valid in untyped Yul. -// ParserError 5473: (742-747): Types are not valid in untyped Yul. -// ParserError 5473: (752-757): Types are not valid in untyped Yul. -// ParserError 5473: (762-767): Types are not valid in untyped Yul. -// ParserError 5473: (772-777): Types are not valid in untyped Yul. -// ParserError 5473: (782-787): Types are not valid in untyped Yul. -// ParserError 5473: (792-797): Types are not valid in untyped Yul. -// ParserError 5473: (802-807): Types are not valid in untyped Yul. -// ParserError 5473: (812-817): Types are not valid in untyped Yul. -// ParserError 5473: (822-827): Types are not valid in untyped Yul. -// ParserError 5473: (832-837): Types are not valid in untyped Yul. -// ParserError 5473: (842-847): Types are not valid in untyped Yul. -// ParserError 5473: (856-861): Types are not valid in untyped Yul. -// ParserError 5473: (866-871): Types are not valid in untyped Yul. -// ParserError 5473: (876-881): Types are not valid in untyped Yul. -// ParserError 5473: (886-891): Types are not valid in untyped Yul. -// ParserError 5473: (896-901): Types are not valid in untyped Yul. -// ParserError 5473: (906-911): Types are not valid in untyped Yul. -// ParserError 5473: (916-921): Types are not valid in untyped Yul. -// ParserError 5473: (926-931): Types are not valid in untyped Yul. -// ParserError 5473: (936-941): Types are not valid in untyped Yul. -// ParserError 5473: (946-951): Types are not valid in untyped Yul. -// ParserError 5473: (956-961): Types are not valid in untyped Yul. -// ParserError 5473: (966-971): Types are not valid in untyped Yul. -// ParserError 5473: (976-981): Types are not valid in untyped Yul. -// ParserError 5473: (986-991): Types are not valid in untyped Yul. -// ParserError 5473: (996-1001): Types are not valid in untyped Yul. -// ParserError 5473: (1006-1011): Types are not valid in untyped Yul. -// ParserError 5473: (1020-1025): Types are not valid in untyped Yul. -// ParserError 5473: (1030-1035): Types are not valid in untyped Yul. -// ParserError 5473: (1040-1045): Types are not valid in untyped Yul. -// ParserError 5473: (1050-1055): Types are not valid in untyped Yul. -// ParserError 5473: (1060-1065): Types are not valid in untyped Yul. -// ParserError 5473: (1070-1075): Types are not valid in untyped Yul. -// ParserError 5473: (1080-1085): Types are not valid in untyped Yul. -// ParserError 5473: (1090-1095): Types are not valid in untyped Yul. -// ParserError 5473: (1100-1105): Types are not valid in untyped Yul. -// ParserError 5473: (1110-1115): Types are not valid in untyped Yul. -// ParserError 5473: (1120-1125): Types are not valid in untyped Yul. -// ParserError 5473: (1130-1135): Types are not valid in untyped Yul. -// ParserError 5473: (1140-1145): Types are not valid in untyped Yul. -// ParserError 5473: (1150-1155): Types are not valid in untyped Yul. -// ParserError 5473: (1160-1165): Types are not valid in untyped Yul. -// ParserError 5473: (1170-1175): Types are not valid in untyped Yul. -// ParserError 5473: (1184-1189): Types are not valid in untyped Yul. -// ParserError 5473: (1194-1199): Types are not valid in untyped Yul. -// ParserError 5473: (1204-1209): Types are not valid in untyped Yul. -// ParserError 5473: (1214-1219): Types are not valid in untyped Yul. -// ParserError 5473: (1224-1229): Types are not valid in untyped Yul. -// ParserError 5473: (1234-1239): Types are not valid in untyped Yul. -// ParserError 5473: (1244-1249): Types are not valid in untyped Yul. -// ParserError 5473: (1254-1259): Types are not valid in untyped Yul. -// ParserError 5473: (1264-1269): Types are not valid in untyped Yul. -// ParserError 5473: (1274-1279): Types are not valid in untyped Yul. -// ParserError 5473: (1284-1289): Types are not valid in untyped Yul. -// ParserError 5473: (1294-1299): Types are not valid in untyped Yul. -// ParserError 5473: (1304-1309): Types are not valid in untyped Yul. -// ParserError 5473: (1314-1319): Types are not valid in untyped Yul. -// ParserError 5473: (1324-1329): Types are not valid in untyped Yul. -// ParserError 5473: (1334-1339): Types are not valid in untyped Yul. -// ParserError 5473: (1348-1353): Types are not valid in untyped Yul. -// ParserError 5473: (1358-1363): Types are not valid in untyped Yul. -// ParserError 5473: (1368-1373): Types are not valid in untyped Yul. -// ParserError 5473: (1378-1383): Types are not valid in untyped Yul. -// ParserError 5473: (1388-1393): Types are not valid in untyped Yul. -// ParserError 5473: (1398-1403): Types are not valid in untyped Yul. -// ParserError 5473: (1408-1413): Types are not valid in untyped Yul. -// ParserError 5473: (1418-1423): Types are not valid in untyped Yul. -// ParserError 5473: (1428-1433): Types are not valid in untyped Yul. -// ParserError 5473: (1438-1443): Types are not valid in untyped Yul. -// ParserError 5473: (1448-1453): Types are not valid in untyped Yul. -// ParserError 5473: (1458-1463): Types are not valid in untyped Yul. -// ParserError 5473: (1468-1473): Types are not valid in untyped Yul. -// ParserError 5473: (1478-1483): Types are not valid in untyped Yul. -// ParserError 5473: (1488-1493): Types are not valid in untyped Yul. -// ParserError 5473: (1498-1503): Types are not valid in untyped Yul. -// ParserError 5473: (1512-1517): Types are not valid in untyped Yul. -// ParserError 5473: (1522-1527): Types are not valid in untyped Yul. -// ParserError 5473: (1532-1537): Types are not valid in untyped Yul. -// ParserError 5473: (1542-1547): Types are not valid in untyped Yul. -// ParserError 5473: (1552-1557): Types are not valid in untyped Yul. -// ParserError 5473: (1562-1567): Types are not valid in untyped Yul. -// ParserError 5473: (1572-1577): Types are not valid in untyped Yul. -// ParserError 5473: (1582-1587): Types are not valid in untyped Yul. -// ParserError 5473: (1592-1597): Types are not valid in untyped Yul. -// ParserError 5473: (1602-1607): Types are not valid in untyped Yul. -// ParserError 5473: (1612-1617): Types are not valid in untyped Yul. -// ParserError 5473: (1622-1627): Types are not valid in untyped Yul. -// ParserError 5473: (1632-1637): Types are not valid in untyped Yul. -// ParserError 5473: (1642-1647): Types are not valid in untyped Yul. -// ParserError 5473: (1652-1657): Types are not valid in untyped Yul. -// ParserError 5473: (1662-1667): Types are not valid in untyped Yul. -// ParserError 5473: (1676-1681): Types are not valid in untyped Yul. -// ParserError 5473: (1686-1691): Types are not valid in untyped Yul. -// ParserError 5473: (1696-1701): Types are not valid in untyped Yul. -// ParserError 5473: (1706-1711): Types are not valid in untyped Yul. -// ParserError 5473: (1716-1721): Types are not valid in untyped Yul. -// ParserError 5473: (1726-1731): Types are not valid in untyped Yul. -// ParserError 5473: (1736-1741): Types are not valid in untyped Yul. -// ParserError 5473: (1746-1751): Types are not valid in untyped Yul. -// ParserError 5473: (1756-1761): Types are not valid in untyped Yul. -// ParserError 5473: (1766-1771): Types are not valid in untyped Yul. -// ParserError 5473: (1776-1781): Types are not valid in untyped Yul. -// ParserError 5473: (1786-1791): Types are not valid in untyped Yul. -// ParserError 5473: (1796-1801): Types are not valid in untyped Yul. -// ParserError 5473: (1806-1811): Types are not valid in untyped Yul. -// ParserError 5473: (1816-1821): Types are not valid in untyped Yul. -// ParserError 5473: (1826-1831): Types are not valid in untyped Yul. -// ParserError 5473: (1840-1845): Types are not valid in untyped Yul. -// ParserError 5473: (1850-1855): Types are not valid in untyped Yul. -// ParserError 5473: (1860-1865): Types are not valid in untyped Yul. -// ParserError 5473: (1870-1875): Types are not valid in untyped Yul. -// ParserError 5473: (1880-1885): Types are not valid in untyped Yul. -// ParserError 5473: (1890-1895): Types are not valid in untyped Yul. -// ParserError 5473: (1900-1905): Types are not valid in untyped Yul. -// ParserError 5473: (1910-1915): Types are not valid in untyped Yul. -// ParserError 5473: (1920-1925): Types are not valid in untyped Yul. -// ParserError 5473: (1930-1935): Types are not valid in untyped Yul. -// ParserError 5473: (1940-1945): Types are not valid in untyped Yul. -// ParserError 5473: (1950-1955): Types are not valid in untyped Yul. -// ParserError 5473: (1960-1965): Types are not valid in untyped Yul. -// ParserError 5473: (1970-1975): Types are not valid in untyped Yul. -// ParserError 5473: (1980-1985): Types are not valid in untyped Yul. -// ParserError 5473: (1990-1995): Types are not valid in untyped Yul. -// ParserError 5473: (2004-2009): Types are not valid in untyped Yul. -// ParserError 5473: (2014-2019): Types are not valid in untyped Yul. -// ParserError 5473: (2024-2029): Types are not valid in untyped Yul. -// ParserError 5473: (2034-2039): Types are not valid in untyped Yul. -// ParserError 5473: (2044-2049): Types are not valid in untyped Yul. -// ParserError 5473: (2054-2059): Types are not valid in untyped Yul. -// ParserError 5473: (2064-2069): Types are not valid in untyped Yul. -// ParserError 5473: (2074-2079): Types are not valid in untyped Yul. -// ParserError 5473: (2084-2089): Types are not valid in untyped Yul. -// ParserError 5473: (2094-2099): Types are not valid in untyped Yul. -// ParserError 5473: (2104-2109): Types are not valid in untyped Yul. -// ParserError 5473: (2114-2119): Types are not valid in untyped Yul. -// ParserError 5473: (2124-2129): Types are not valid in untyped Yul. -// ParserError 5473: (2134-2139): Types are not valid in untyped Yul. -// ParserError 5473: (2144-2149): Types are not valid in untyped Yul. -// ParserError 5473: (2154-2159): Types are not valid in untyped Yul. -// ParserError 5473: (2168-2173): Types are not valid in untyped Yul. -// ParserError 5473: (2178-2183): Types are not valid in untyped Yul. -// ParserError 5473: (2188-2193): Types are not valid in untyped Yul. -// ParserError 5473: (2198-2203): Types are not valid in untyped Yul. -// ParserError 5473: (2208-2213): Types are not valid in untyped Yul. -// ParserError 5473: (2218-2223): Types are not valid in untyped Yul. -// ParserError 5473: (2228-2233): Types are not valid in untyped Yul. -// ParserError 5473: (2238-2243): Types are not valid in untyped Yul. -// ParserError 5473: (2248-2253): Types are not valid in untyped Yul. -// ParserError 5473: (2258-2263): Types are not valid in untyped Yul. -// ParserError 5473: (2268-2273): Types are not valid in untyped Yul. -// ParserError 5473: (2278-2283): Types are not valid in untyped Yul. -// ParserError 5473: (2288-2293): Types are not valid in untyped Yul. -// ParserError 5473: (2298-2303): Types are not valid in untyped Yul. -// ParserError 5473: (2308-2313): Types are not valid in untyped Yul. -// ParserError 5473: (2318-2323): Types are not valid in untyped Yul. -// ParserError 5473: (2332-2337): Types are not valid in untyped Yul. -// ParserError 5473: (2342-2347): Types are not valid in untyped Yul. -// ParserError 5473: (2352-2357): Types are not valid in untyped Yul. -// ParserError 5473: (2362-2367): Types are not valid in untyped Yul. -// ParserError 5473: (2372-2377): Types are not valid in untyped Yul. -// ParserError 5473: (2382-2387): Types are not valid in untyped Yul. -// ParserError 5473: (2392-2397): Types are not valid in untyped Yul. -// ParserError 5473: (2402-2407): Types are not valid in untyped Yul. -// ParserError 5473: (2412-2417): Types are not valid in untyped Yul. -// ParserError 5473: (2422-2427): Types are not valid in untyped Yul. -// ParserError 5473: (2432-2437): Types are not valid in untyped Yul. -// ParserError 5473: (2442-2447): Types are not valid in untyped Yul. -// ParserError 5473: (2452-2457): Types are not valid in untyped Yul. -// ParserError 5473: (2462-2467): Types are not valid in untyped Yul. -// ParserError 5473: (2472-2477): Types are not valid in untyped Yul. -// ParserError 5473: (2482-2487): Types are not valid in untyped Yul. -// ParserError 5473: (2496-2501): Types are not valid in untyped Yul. -// ParserError 5473: (2506-2511): Types are not valid in untyped Yul. -// ParserError 5473: (2516-2521): Types are not valid in untyped Yul. -// ParserError 5473: (2526-2531): Types are not valid in untyped Yul. -// ParserError 5473: (2536-2541): Types are not valid in untyped Yul. -// ParserError 5473: (2546-2551): Types are not valid in untyped Yul. -// ParserError 5473: (2556-2561): Types are not valid in untyped Yul. -// ParserError 5473: (2566-2571): Types are not valid in untyped Yul. -// ParserError 5473: (2576-2581): Types are not valid in untyped Yul. -// ParserError 5473: (2586-2591): Types are not valid in untyped Yul. -// ParserError 5473: (2596-2601): Types are not valid in untyped Yul. -// ParserError 5473: (2606-2611): Types are not valid in untyped Yul. -// ParserError 5473: (2616-2621): Types are not valid in untyped Yul. -// ParserError 5473: (2626-2631): Types are not valid in untyped Yul. -// ParserError 5473: (2636-2641): Types are not valid in untyped Yul. -// ParserError 5473: (2646-2651): Types are not valid in untyped Yul. -// ParserError 5473: (2660-2665): Types are not valid in untyped Yul. -// ParserError 5473: (2670-2675): Types are not valid in untyped Yul. -// ParserError 5473: (2680-2685): Types are not valid in untyped Yul. -// ParserError 5473: (2690-2695): Types are not valid in untyped Yul. -// ParserError 5473: (2700-2705): Types are not valid in untyped Yul. -// ParserError 5473: (2710-2715): Types are not valid in untyped Yul. -// ParserError 5473: (2720-2725): Types are not valid in untyped Yul. -// ParserError 5473: (2730-2735): Types are not valid in untyped Yul. -// ParserError 5473: (2740-2745): Types are not valid in untyped Yul. -// ParserError 5473: (2750-2755): Types are not valid in untyped Yul. -// ParserError 5473: (2760-2765): Types are not valid in untyped Yul. -// ParserError 5473: (2770-2775): Types are not valid in untyped Yul. -// ParserError 5473: (2780-2785): Types are not valid in untyped Yul. -// ParserError 5473: (2790-2795): Types are not valid in untyped Yul. -// ParserError 5473: (2800-2805): Types are not valid in untyped Yul. -// ParserError 5473: (2810-2815): Types are not valid in untyped Yul. +// DeclarationError 4990: (224-227): Variable x00 used before it was declared. +// DeclarationError 4990: (237-240): Variable x01 used before it was declared. +// DeclarationError 4990: (250-253): Variable x02 used before it was declared. +// DeclarationError 4990: (263-266): Variable x03 used before it was declared. +// DeclarationError 4990: (276-279): Variable x04 used before it was declared. +// DeclarationError 4990: (289-292): Variable x05 used before it was declared. +// DeclarationError 4990: (302-305): Variable x06 used before it was declared. +// DeclarationError 4990: (315-318): Variable x07 used before it was declared. +// DeclarationError 4990: (332-335): Variable x08 used before it was declared. +// DeclarationError 4990: (345-348): Variable x09 used before it was declared. +// DeclarationError 4990: (358-361): Variable x0a used before it was declared. +// DeclarationError 4990: (371-374): Variable x0b used before it was declared. +// DeclarationError 4990: (384-387): Variable x0c used before it was declared. +// DeclarationError 4990: (397-400): Variable x0d used before it was declared. +// DeclarationError 4990: (410-413): Variable x0e used before it was declared. +// DeclarationError 4990: (423-426): Variable x0f used before it was declared. +// DeclarationError 4990: (440-443): Variable x10 used before it was declared. +// DeclarationError 4990: (453-456): Variable x11 used before it was declared. +// DeclarationError 4990: (466-469): Variable x12 used before it was declared. +// DeclarationError 4990: (479-482): Variable x13 used before it was declared. +// DeclarationError 4990: (492-495): Variable x14 used before it was declared. +// DeclarationError 4990: (505-508): Variable x15 used before it was declared. +// DeclarationError 4990: (518-521): Variable x16 used before it was declared. +// DeclarationError 4990: (531-534): Variable x17 used before it was declared. +// DeclarationError 4990: (548-551): Variable x18 used before it was declared. +// DeclarationError 4990: (561-564): Variable x19 used before it was declared. +// DeclarationError 4990: (574-577): Variable x1a used before it was declared. +// DeclarationError 4990: (587-590): Variable x1b used before it was declared. +// DeclarationError 4990: (600-603): Variable x1c used before it was declared. +// DeclarationError 4990: (613-616): Variable x1d used before it was declared. +// DeclarationError 4990: (626-629): Variable x1e used before it was declared. +// DeclarationError 4990: (639-642): Variable x1f used before it was declared. +// DeclarationError 4990: (656-659): Variable x20 used before it was declared. +// DeclarationError 4990: (669-672): Variable x21 used before it was declared. +// DeclarationError 4990: (682-685): Variable x22 used before it was declared. +// DeclarationError 4990: (695-698): Variable x23 used before it was declared. +// DeclarationError 4990: (708-711): Variable x24 used before it was declared. +// DeclarationError 4990: (721-724): Variable x25 used before it was declared. +// DeclarationError 4990: (734-737): Variable x26 used before it was declared. +// DeclarationError 4990: (747-750): Variable x27 used before it was declared. +// DeclarationError 4990: (764-767): Variable x28 used before it was declared. +// DeclarationError 4990: (777-780): Variable x29 used before it was declared. +// DeclarationError 4990: (790-793): Variable x2a used before it was declared. +// DeclarationError 4990: (803-806): Variable x2b used before it was declared. +// DeclarationError 4990: (816-819): Variable x2c used before it was declared. +// DeclarationError 4990: (829-832): Variable x2d used before it was declared. +// DeclarationError 4990: (842-845): Variable x2e used before it was declared. +// DeclarationError 4990: (855-858): Variable x2f used before it was declared. +// DeclarationError 4990: (872-875): Variable x30 used before it was declared. +// DeclarationError 4990: (885-888): Variable x31 used before it was declared. +// DeclarationError 4990: (898-901): Variable x32 used before it was declared. +// DeclarationError 4990: (911-914): Variable x33 used before it was declared. +// DeclarationError 4990: (924-927): Variable x34 used before it was declared. +// DeclarationError 4990: (937-940): Variable x35 used before it was declared. +// DeclarationError 4990: (950-953): Variable x36 used before it was declared. +// DeclarationError 4990: (963-966): Variable x37 used before it was declared. +// DeclarationError 4990: (980-983): Variable x38 used before it was declared. +// DeclarationError 4990: (993-996): Variable x39 used before it was declared. +// DeclarationError 4990: (1006-1009): Variable x3a used before it was declared. +// DeclarationError 4990: (1019-1022): Variable x3b used before it was declared. +// DeclarationError 4990: (1032-1035): Variable x3c used before it was declared. +// DeclarationError 4990: (1045-1048): Variable x3d used before it was declared. +// DeclarationError 4990: (1058-1061): Variable x3e used before it was declared. +// DeclarationError 4990: (1071-1074): Variable x3f used before it was declared. +// DeclarationError 4990: (1088-1091): Variable x40 used before it was declared. +// DeclarationError 4990: (1101-1104): Variable x41 used before it was declared. +// DeclarationError 4990: (1114-1117): Variable x42 used before it was declared. +// DeclarationError 4990: (1127-1130): Variable x43 used before it was declared. +// DeclarationError 4990: (1140-1143): Variable x44 used before it was declared. +// DeclarationError 4990: (1153-1156): Variable x45 used before it was declared. +// DeclarationError 4990: (1166-1169): Variable x46 used before it was declared. +// DeclarationError 4990: (1179-1182): Variable x47 used before it was declared. +// DeclarationError 4990: (1196-1199): Variable x48 used before it was declared. +// DeclarationError 4990: (1209-1212): Variable x49 used before it was declared. +// DeclarationError 4990: (1222-1225): Variable x4a used before it was declared. +// DeclarationError 4990: (1235-1238): Variable x4b used before it was declared. +// DeclarationError 4990: (1248-1251): Variable x4c used before it was declared. +// DeclarationError 4990: (1261-1264): Variable x4d used before it was declared. +// DeclarationError 4990: (1274-1277): Variable x4e used before it was declared. +// DeclarationError 4990: (1287-1290): Variable x4f used before it was declared. +// DeclarationError 4990: (1304-1307): Variable x50 used before it was declared. +// DeclarationError 4990: (1317-1320): Variable x51 used before it was declared. +// DeclarationError 4990: (1330-1333): Variable x52 used before it was declared. +// DeclarationError 4990: (1343-1346): Variable x53 used before it was declared. +// DeclarationError 4990: (1356-1359): Variable x54 used before it was declared. +// DeclarationError 4990: (1369-1372): Variable x55 used before it was declared. +// DeclarationError 4990: (1382-1385): Variable x56 used before it was declared. +// DeclarationError 4990: (1395-1398): Variable x57 used before it was declared. +// DeclarationError 4990: (1412-1415): Variable x58 used before it was declared. +// DeclarationError 4990: (1425-1428): Variable x59 used before it was declared. +// DeclarationError 4990: (1438-1441): Variable x5a used before it was declared. +// DeclarationError 4990: (1451-1454): Variable x5b used before it was declared. +// DeclarationError 4990: (1464-1467): Variable x5c used before it was declared. +// DeclarationError 4990: (1477-1480): Variable x5d used before it was declared. +// DeclarationError 4990: (1490-1493): Variable x5e used before it was declared. +// DeclarationError 4990: (1503-1506): Variable x5f used before it was declared. +// DeclarationError 4990: (1520-1523): Variable x60 used before it was declared. +// DeclarationError 4990: (1533-1536): Variable x61 used before it was declared. +// DeclarationError 4990: (1546-1549): Variable x62 used before it was declared. +// DeclarationError 4990: (1559-1562): Variable x63 used before it was declared. +// DeclarationError 4990: (1572-1575): Variable x64 used before it was declared. +// DeclarationError 4990: (1585-1588): Variable x65 used before it was declared. +// DeclarationError 4990: (1598-1601): Variable x66 used before it was declared. +// DeclarationError 4990: (1611-1614): Variable x67 used before it was declared. +// DeclarationError 4990: (1628-1631): Variable x68 used before it was declared. +// DeclarationError 4990: (1641-1644): Variable x69 used before it was declared. +// DeclarationError 4990: (1654-1657): Variable x6a used before it was declared. +// DeclarationError 4990: (1667-1670): Variable x6b used before it was declared. +// DeclarationError 4990: (1680-1683): Variable x6c used before it was declared. +// DeclarationError 4990: (1693-1696): Variable x6d used before it was declared. +// DeclarationError 4990: (1706-1709): Variable x6e used before it was declared. +// DeclarationError 4990: (1719-1722): Variable x6f used before it was declared. +// DeclarationError 4990: (1736-1739): Variable x70 used before it was declared. +// DeclarationError 4990: (1749-1752): Variable x71 used before it was declared. +// DeclarationError 4990: (1762-1765): Variable x72 used before it was declared. +// DeclarationError 4990: (1775-1778): Variable x73 used before it was declared. +// DeclarationError 4990: (1788-1791): Variable x74 used before it was declared. +// DeclarationError 4990: (1801-1804): Variable x75 used before it was declared. +// DeclarationError 4990: (1814-1817): Variable x76 used before it was declared. +// DeclarationError 4990: (1827-1830): Variable x77 used before it was declared. +// DeclarationError 4990: (1844-1847): Variable x78 used before it was declared. +// DeclarationError 4990: (1857-1860): Variable x79 used before it was declared. +// DeclarationError 4990: (1870-1873): Variable x7a used before it was declared. +// DeclarationError 4990: (1883-1886): Variable x7b used before it was declared. +// DeclarationError 4990: (1896-1899): Variable x7c used before it was declared. +// DeclarationError 4990: (1909-1912): Variable x7d used before it was declared. +// DeclarationError 4990: (1922-1925): Variable x7e used before it was declared. +// DeclarationError 4990: (1935-1938): Variable x7f used before it was declared. +// DeclarationError 4990: (1952-1955): Variable x80 used before it was declared. +// DeclarationError 4990: (1965-1968): Variable x81 used before it was declared. +// DeclarationError 4990: (1978-1981): Variable x82 used before it was declared. +// DeclarationError 4990: (1991-1994): Variable x83 used before it was declared. +// DeclarationError 4990: (2004-2007): Variable x84 used before it was declared. +// DeclarationError 4990: (2017-2020): Variable x85 used before it was declared. +// DeclarationError 4990: (2030-2033): Variable x86 used before it was declared. +// DeclarationError 4990: (2043-2046): Variable x87 used before it was declared. +// DeclarationError 4990: (2060-2063): Variable x88 used before it was declared. +// DeclarationError 4990: (2073-2076): Variable x89 used before it was declared. +// DeclarationError 4990: (2086-2089): Variable x8a used before it was declared. +// DeclarationError 4990: (2099-2102): Variable x8b used before it was declared. +// DeclarationError 4990: (2112-2115): Variable x8c used before it was declared. +// DeclarationError 4990: (2125-2128): Variable x8d used before it was declared. +// DeclarationError 4990: (2138-2141): Variable x8e used before it was declared. +// DeclarationError 4990: (2151-2154): Variable x8f used before it was declared. +// DeclarationError 4990: (2168-2171): Variable x90 used before it was declared. +// DeclarationError 4990: (2181-2184): Variable x91 used before it was declared. +// DeclarationError 4990: (2194-2197): Variable x92 used before it was declared. +// DeclarationError 4990: (2207-2210): Variable x93 used before it was declared. +// DeclarationError 4990: (2220-2223): Variable x94 used before it was declared. +// DeclarationError 4990: (2233-2236): Variable x95 used before it was declared. +// DeclarationError 4990: (2246-2249): Variable x96 used before it was declared. +// DeclarationError 4990: (2259-2262): Variable x97 used before it was declared. +// DeclarationError 4990: (2276-2279): Variable x98 used before it was declared. +// DeclarationError 4990: (2289-2292): Variable x99 used before it was declared. +// DeclarationError 4990: (2302-2305): Variable x9a used before it was declared. +// DeclarationError 4990: (2315-2318): Variable x9b used before it was declared. +// DeclarationError 4990: (2328-2331): Variable x9c used before it was declared. +// DeclarationError 4990: (2341-2344): Variable x9d used before it was declared. +// DeclarationError 4990: (2354-2357): Variable x9e used before it was declared. +// DeclarationError 4990: (2367-2370): Variable x9f used before it was declared. +// DeclarationError 4990: (2384-2387): Variable xa0 used before it was declared. +// DeclarationError 4990: (2397-2400): Variable xa1 used before it was declared. +// DeclarationError 4990: (2410-2413): Variable xa2 used before it was declared. +// DeclarationError 4990: (2423-2426): Variable xa3 used before it was declared. +// DeclarationError 4990: (2436-2439): Variable xa4 used before it was declared. +// DeclarationError 4990: (2449-2452): Variable xa5 used before it was declared. +// DeclarationError 4990: (2462-2465): Variable xa6 used before it was declared. +// DeclarationError 4990: (2475-2478): Variable xa7 used before it was declared. +// DeclarationError 4990: (2492-2495): Variable xa8 used before it was declared. +// DeclarationError 4990: (2505-2508): Variable xa9 used before it was declared. +// DeclarationError 4990: (2518-2521): Variable xaa used before it was declared. +// DeclarationError 4990: (2531-2534): Variable xab used before it was declared. +// DeclarationError 4990: (2544-2547): Variable xac used before it was declared. +// DeclarationError 4990: (2557-2560): Variable xad used before it was declared. +// DeclarationError 4990: (2570-2573): Variable xae used before it was declared. +// DeclarationError 4990: (2583-2586): Variable xaf used before it was declared. +// DeclarationError 4990: (2600-2603): Variable xb0 used before it was declared. +// DeclarationError 4990: (2613-2616): Variable xb1 used before it was declared. +// DeclarationError 4990: (2626-2629): Variable xb2 used before it was declared. +// DeclarationError 4990: (2639-2642): Variable xb3 used before it was declared. +// DeclarationError 4990: (2652-2655): Variable xb4 used before it was declared. +// DeclarationError 4990: (2665-2668): Variable xb5 used before it was declared. +// DeclarationError 4990: (2678-2681): Variable xb6 used before it was declared. +// DeclarationError 4990: (2691-2694): Variable xb7 used before it was declared. +// DeclarationError 4990: (2708-2711): Variable xb8 used before it was declared. +// DeclarationError 4990: (2721-2724): Variable xb9 used before it was declared. +// DeclarationError 4990: (2734-2737): Variable xba used before it was declared. +// DeclarationError 4990: (2747-2750): Variable xbb used before it was declared. +// DeclarationError 4990: (2760-2763): Variable xbc used before it was declared. +// DeclarationError 4990: (2773-2776): Variable xbd used before it was declared. +// DeclarationError 4990: (2786-2789): Variable xbe used before it was declared. +// DeclarationError 4990: (2799-2802): Variable xbf used before it was declared. +// DeclarationError 4990: (2816-2819): Variable xc0 used before it was declared. +// DeclarationError 4990: (2829-2832): Variable xc1 used before it was declared. +// DeclarationError 4990: (2842-2845): Variable xc2 used before it was declared. +// DeclarationError 4990: (2855-2858): Variable xc3 used before it was declared. +// DeclarationError 4990: (2868-2871): Variable xc4 used before it was declared. +// DeclarationError 4990: (2881-2884): Variable xc5 used before it was declared. +// DeclarationError 4990: (2894-2897): Variable xc6 used before it was declared. +// DeclarationError 4990: (2907-2910): Variable xc7 used before it was declared. +// DeclarationError 4990: (2924-2927): Variable xc8 used before it was declared. +// DeclarationError 4990: (2937-2940): Variable xc9 used before it was declared. +// DeclarationError 4990: (2950-2953): Variable xca used before it was declared. +// DeclarationError 4990: (2963-2966): Variable xcb used before it was declared. +// DeclarationError 4990: (2976-2979): Variable xcc used before it was declared. +// DeclarationError 4990: (2989-2992): Variable xcd used before it was declared. +// DeclarationError 4990: (3002-3005): Variable xce used before it was declared. +// DeclarationError 4990: (3015-3018): Variable xcf used before it was declared. +// DeclarationError 4990: (3032-3035): Variable xd0 used before it was declared. +// DeclarationError 4990: (3045-3048): Variable xd1 used before it was declared. +// DeclarationError 4990: (3058-3061): Variable xd2 used before it was declared. +// DeclarationError 4990: (3071-3074): Variable xd3 used before it was declared. +// DeclarationError 4990: (3084-3087): Variable xd4 used before it was declared. +// DeclarationError 4990: (3097-3100): Variable xd5 used before it was declared. +// DeclarationError 4990: (3110-3113): Variable xd6 used before it was declared. +// DeclarationError 4990: (3123-3126): Variable xd7 used before it was declared. +// DeclarationError 4990: (3140-3143): Variable xd8 used before it was declared. +// DeclarationError 4990: (3153-3156): Variable xd9 used before it was declared. +// DeclarationError 4990: (3166-3169): Variable xda used before it was declared. +// DeclarationError 4990: (3179-3182): Variable xdb used before it was declared. +// DeclarationError 4990: (3192-3195): Variable xdc used before it was declared. +// DeclarationError 4990: (3205-3208): Variable xdd used before it was declared. +// DeclarationError 4990: (3218-3221): Variable xde used before it was declared. +// DeclarationError 4990: (3231-3234): Variable xdf used before it was declared. +// DeclarationError 4990: (3248-3251): Variable xe0 used before it was declared. +// DeclarationError 4990: (3261-3264): Variable xe1 used before it was declared. +// DeclarationError 4990: (3274-3277): Variable xe2 used before it was declared. +// DeclarationError 4990: (3287-3290): Variable xe3 used before it was declared. +// DeclarationError 4990: (3300-3303): Variable xe4 used before it was declared. +// DeclarationError 4990: (3313-3316): Variable xe5 used before it was declared. +// DeclarationError 4990: (3326-3329): Variable xe6 used before it was declared. +// DeclarationError 4990: (3339-3342): Variable xe7 used before it was declared. +// DeclarationError 4990: (3356-3359): Variable xe8 used before it was declared. +// DeclarationError 4990: (3369-3372): Variable xe9 used before it was declared. +// DeclarationError 4990: (3382-3385): Variable xea used before it was declared. +// DeclarationError 4990: (3395-3398): Variable xeb used before it was declared. +// DeclarationError 4990: (3408-3411): Variable xec used before it was declared. +// DeclarationError 4990: (3421-3424): Variable xed used before it was declared. +// DeclarationError 4990: (3434-3437): Variable xee used before it was declared. +// DeclarationError 4990: (3447-3450): Variable xef used before it was declared. +// DeclarationError 4990: (3464-3467): Variable xf0 used before it was declared. +// DeclarationError 4990: (3477-3480): Variable xf1 used before it was declared. +// DeclarationError 4990: (3490-3493): Variable xf2 used before it was declared. +// DeclarationError 4990: (3503-3506): Variable xf3 used before it was declared. +// DeclarationError 4990: (3516-3519): Variable xf4 used before it was declared. +// DeclarationError 4990: (3529-3532): Variable xf5 used before it was declared. +// DeclarationError 4990: (3542-3545): Variable xf6 used before it was declared. +// DeclarationError 4990: (3555-3558): Variable xf7 used before it was declared. +// DeclarationError 4990: (3572-3575): Variable xf8 used before it was declared. +// DeclarationError 4990: (3585-3588): Variable xf9 used before it was declared. +// DeclarationError 4990: (3598-3601): Variable xfa used before it was declared. +// DeclarationError 4990: (3611-3614): Variable xfb used before it was declared. +// DeclarationError 4990: (3624-3627): Variable xfc used before it was declared. +// DeclarationError 4990: (3637-3640): Variable xfd used before it was declared. +// DeclarationError 4990: (3650-3653): Variable xfe used before it was declared. +// DeclarationError 4990: (3663-3666): Variable xff used before it was declared. // Warning 4013: There are more than 256 errors. Aborting. From c5b1ac3532958eed2288e17860171d5e0eb46ee3 Mon Sep 17 00:00:00 2001 From: Ardis Lu Date: Fri, 26 Jul 2024 20:50:59 -0700 Subject: [PATCH 0284/1340] Fix showProvedSafe flag and JSON key name Extend title underline --- docs/smtchecker.rst | 4 ++-- docs/using-the-compiler.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index fc7978256..92aaa847c 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -488,8 +488,8 @@ Proved Targets If there are any proved targets, the SMTChecker issues one warning per engine stating how many targets were proved. If the user wishes to see all the specific -proved targets, the CLI option ``--model-checker-show-proved`` and -the JSON option ``settings.modelChecker.showProved = true`` can be used. +proved targets, the CLI option ``--model-checker-show-proved-safe`` and +the JSON option ``settings.modelChecker.showProvedSafe = true`` can be used. Unproved Targets ================ diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 97994e132..004bb4a61 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -481,7 +481,7 @@ Input Description // Choose which types of invariants should be reported to the user: contract, reentrancy. "invariants": ["contract", "reentrancy"], // Choose whether to output all proved targets. The default is `false`. - "showProved": true, + "showProvedSafe": true, // Choose whether to output all unproved targets. The default is `false`. "showUnproved": true, // Choose whether to output all unsupported language features. The default is `false`. From 82a3071b854a7051899e2fc09cc7aa29439f4e70 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Mon, 19 Aug 2024 21:59:09 +0200 Subject: [PATCH 0285/1340] SMTChecker: Introduce first draft of Z3CHCSmtlib2Interface This commit introduces the interface class without actually using it. The actual switch will be done later, after all things are set up. --- libsmtutil/CHCSmtLib2Interface.cpp | 4 +- libsolidity/formal/Z3CHCSmtLib2Interface.cpp | 222 +++++++++++++++++++ libsolidity/formal/Z3CHCSmtLib2Interface.h | 50 +++++ 3 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 libsolidity/formal/Z3CHCSmtLib2Interface.cpp create mode 100644 libsolidity/formal/Z3CHCSmtLib2Interface.h diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index 6db1c6e87..6e535f099 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -96,7 +96,9 @@ std::tuple CHCSmtLib2Inte std::string response = querySolver(query); CheckResult result; - // TODO proper parsing + // NOTE: Our internal semantics is UNSAT -> SAFE and SAT -> UNSAFE, which corresponds to usual SMT-based model checking + // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. + // So we have to flip the answer. if (boost::starts_with(response, "sat")) { auto maybeInvariants = invariantsFromSolverResponse(response); diff --git a/libsolidity/formal/Z3CHCSmtLib2Interface.cpp b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp new file mode 100644 index 000000000..cd06a9d33 --- /dev/null +++ b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp @@ -0,0 +1,222 @@ +/* + 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 + +#include + +#include + +#include + +#include + +#include + +using namespace solidity::frontend::smt; +using namespace solidity::smtutil; + +Z3CHCSmtLib2Interface::Z3CHCSmtLib2Interface( + frontend::ReadCallback::Callback _smtCallback, + std::optional _queryTimeout, + bool _computeInvariants +): CHCSmtLib2Interface({}, std::move(_smtCallback), _queryTimeout), m_computeInvariants(_computeInvariants) +{ +} + +void Z3CHCSmtLib2Interface::setupSmtCallback(bool _enablePreprocessing) +{ + if (auto* universalCallback = m_smtCallback.target()) + universalCallback->smtCommand().setZ3(m_queryTimeout, _enablePreprocessing, m_computeInvariants); +} + +std::tuple Z3CHCSmtLib2Interface::query(smtutil::Expression const& _block) +{ + setupSmtCallback(true); + std::string query = dumpQuery(_block); + std::string response = querySolver(query); + // NOTE: Our internal semantics is UNSAT -> SAFE and SAT -> UNSAFE, which corresponds to usual SMT-based model checking + // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. + // So we have to flip the answer. + if (boost::starts_with(response, "unsat")) + { + // Repeat the query with preprocessing disabled, to get the full proof + setupSmtCallback(false); + query = "(set-option :produce-proofs true)" + query + "\n(get-proof)"; + response = querySolver(query); + setupSmtCallback(true); + if (!boost::starts_with(response, "unsat")) + return {CheckResult::SATISFIABLE, Expression(true), {}}; + return {CheckResult::SATISFIABLE, Expression(true), graphFromZ3Answer(response)}; + } + + CheckResult result; + if (boost::starts_with(response, "sat")) + { + auto maybeInvariants = invariantsFromSolverResponse(response); + return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; + } + else if (boost::starts_with(response, "unknown")) + result = CheckResult::UNKNOWN; + else + result = CheckResult::ERROR; + + return {result, Expression(true), {}}; +} + + +CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromZ3Answer(std::string const& _proof) const +{ + std::stringstream ss(_proof); + std::string answer; + ss >> answer; + smtAssert(answer == "unsat"); + + SMTLib2Parser parser(ss); + if (parser.isEOF()) // No proof from Z3 + return {}; + // For some reason Z3 outputs everything as a single s-expression + SMTLib2Expression parsedOutput; + try + { + parsedOutput = parser.parseExpression(); + } + catch (SMTLib2Parser::ParsingException&) + { + return {}; + } + solAssert(parser.isEOF()); + solAssert(!isAtom(parsedOutput)); + auto& commands = asSubExpressions(parsedOutput); + ScopedParser expressionParser(m_context); + for (auto& command: commands) + { + if (isAtom(command)) + continue; + + auto const& args = asSubExpressions(command); + solAssert(args.size() > 0); + auto const& head = args[0]; + if (!isAtom(head)) + continue; + + // Z3 can introduce new helper predicates to be used in the proof + // e.g., "(declare-fun query!0 (Bool Bool Bool Int Int Bool Bool Bool Bool Bool Bool Bool Int) Bool)" + if (asAtom(head) == "declare-fun") + { + solAssert(args.size() == 4); + auto const& name = args[1]; + auto const& domainSorts = args[2]; + auto const& codomainSort = args[3]; + solAssert(isAtom(name)); + solAssert(!isAtom(domainSorts)); + expressionParser.addVariableDeclaration(asAtom(name), expressionParser.toSort(codomainSort)); + } + // The subexpression starting with "proof" contains the whole proof, which we need to transform to our internal + // representation + else if (asAtom(head) == "proof") + { + inlineLetExpressions(command); + return graphFromSMTLib2Expression(command, expressionParser); + } + } + return {}; +} + +CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromSMTLib2Expression( + SMTLib2Expression const& _proof, + ScopedParser& _context +) +{ + auto fact = [](SMTLib2Expression const& _node) -> SMTLib2Expression const& { + if (isAtom(_node)) + return _node; + smtAssert(!asSubExpressions(_node).empty()); + return asSubExpressions(_node).back(); + }; + smtAssert(!isAtom(_proof)); + auto const& proofArgs = asSubExpressions(_proof); + smtAssert(proofArgs.size() == 2); + smtAssert(isAtom(proofArgs.at(0)) && asAtom(proofArgs.at(0)) == "proof"); + auto const& proofNode = proofArgs.at(1); + auto const& derivedFact = fact(proofNode); + if (isAtom(proofNode) || !isAtom(derivedFact) || asAtom(derivedFact) != "false") + return {}; + + CHCSolverInterface::CexGraph graph; + + std::stack proofStack; + proofStack.push(&asSubExpressions(proofNode).at(1)); + + std::map visitedIds; + unsigned nextId = 0; + + auto const* root = proofStack.top(); + auto const& derivedRootFact = fact(*root); + visitedIds.emplace(root, nextId++); + graph.nodes.emplace(visitedIds.at(root), _context.toSMTUtilExpression(derivedRootFact)); + + auto isHyperRes = [](SMTLib2Expression const& expr) { + if (isAtom(expr)) return false; + auto const& subExprs = asSubExpressions(expr); + smtAssert(!subExprs.empty()); + auto const& op = subExprs.at(0); + if (isAtom(op)) return false; + auto const& opExprs = asSubExpressions(op); + if (opExprs.size() < 2) return false; + auto const& ruleName = opExprs.at(1); + return isAtom(ruleName) && asAtom(ruleName) == "hyper-res"; + }; + + while (!proofStack.empty()) + { + auto const* currentNode = proofStack.top(); + smtAssert(visitedIds.find(currentNode) != visitedIds.end()); + auto id = visitedIds.at(currentNode); + smtAssert(graph.nodes.count(id)); + proofStack.pop(); + + if (isHyperRes(*currentNode)) + { + auto const& args = asSubExpressions(*currentNode); + smtAssert(args.size() > 1); + // args[0] is the name of the rule + // args[1] is the clause used + // last argument is the derived fact + // the arguments in the middle are the facts where we need to recurse + for (unsigned i = 2; i < args.size() - 1; ++i) + { + auto const* child = &args[i]; + if (!visitedIds.count(child)) + { + visitedIds.emplace(child, nextId++); + proofStack.push(child); + } + + auto childId = visitedIds.at(child); + if (!graph.nodes.count(childId)) + { + graph.nodes.emplace(childId, _context.toSMTUtilExpression(fact(*child))); + graph.edges[childId] = {}; + } + + graph.edges[id].push_back(childId); + } + } + } + return graph; +} + diff --git a/libsolidity/formal/Z3CHCSmtLib2Interface.h b/libsolidity/formal/Z3CHCSmtLib2Interface.h new file mode 100644 index 000000000..39456cde0 --- /dev/null +++ b/libsolidity/formal/Z3CHCSmtLib2Interface.h @@ -0,0 +1,50 @@ +/* + 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 + +#pragma once + +#include + +namespace solidity::frontend::smt +{ + +class Z3CHCSmtLib2Interface: public smtutil::CHCSmtLib2Interface +{ +public: + Z3CHCSmtLib2Interface( + frontend::ReadCallback::Callback _smtCallback, + std::optional _queryTimeout, + bool _computeInvariants + ); + +private: + void setupSmtCallback(bool _disablePreprocessing); + + std::tuple query(smtutil::Expression const& _expr) override; + + CHCSolverInterface::CexGraph graphFromZ3Answer(std::string const& _proof) const; + + static CHCSolverInterface::CexGraph graphFromSMTLib2Expression( + smtutil::SMTLib2Expression const& _proof, + ScopedParser& _context + ); + + bool m_computeInvariants; +}; + +} From 4aff9978a95f2cb6017c6d6df9b1c4e671abf175 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 20 Aug 2024 13:07:57 +0200 Subject: [PATCH 0286/1340] Implementation of direct SSA CFG generation. --- libyul/CMakeLists.txt | 3 + libyul/backends/evm/SSAControlFlowGraph.h | 226 +++++ .../evm/SSAControlFlowGraphBuilder.cpp | 850 ++++++++++++++++++ .../backends/evm/SSAControlFlowGraphBuilder.h | 137 +++ 4 files changed, 1216 insertions(+) create mode 100644 libyul/backends/evm/SSAControlFlowGraph.h create mode 100644 libyul/backends/evm/SSAControlFlowGraphBuilder.cpp create mode 100644 libyul/backends/evm/SSAControlFlowGraphBuilder.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index d38d5f270..c54513d9a 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -63,6 +63,9 @@ add_library(yul backends/evm/NoOutputAssembly.cpp backends/evm/OptimizedEVMCodeTransform.cpp backends/evm/OptimizedEVMCodeTransform.h + backends/evm/SSAControlFlowGraph.h + backends/evm/SSAControlFlowGraphBuilder.cpp + backends/evm/SSAControlFlowGraphBuilder.h backends/evm/StackHelpers.h backends/evm/StackLayoutGenerator.cpp backends/evm/StackLayoutGenerator.h diff --git a/libyul/backends/evm/SSAControlFlowGraph.h b/libyul/backends/evm/SSAControlFlowGraph.h new file mode 100644 index 000000000..f24b2779f --- /dev/null +++ b/libyul/backends/evm/SSAControlFlowGraph.h @@ -0,0 +1,226 @@ +/* + 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 +/** + * Control flow graph and stack layout structures used during code generation. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace solidity::yul +{ + +class SSACFG +{ +public: + SSACFG() {} + SSACFG(SSACFG const&) = delete; + SSACFG(SSACFG&&) = delete; + SSACFG& operator=(SSACFG const&) = delete; + SSACFG& operator=(SSACFG&&) = delete; + ~SSACFG() = default; + + struct BlockId + { + size_t value = std::numeric_limits::max(); + operator bool() const { return value != std::numeric_limits::max(); } + bool operator<(BlockId const& _rhs) const { return value < _rhs.value; } + bool operator==(BlockId const& _rhs) const { return value == _rhs.value; } + bool operator!=(BlockId const& _rhs) const { return value != _rhs.value; } + }; + struct ValueId + { + size_t value = std::numeric_limits::max(); + operator bool() const { return value != std::numeric_limits::max(); } + bool operator<(ValueId const& _rhs) const { return value < _rhs.value; } + bool operator==(ValueId const& _rhs) const { return value == _rhs.value; } + bool operator!=(ValueId const& _rhs) const { return value != _rhs.value; } + }; + struct BuiltinCall + { + langutil::DebugData::ConstPtr debugData; + std::reference_wrapper builtin; + std::reference_wrapper call; + }; + struct Call + { + langutil::DebugData::ConstPtr debugData; + std::reference_wrapper function; + std::reference_wrapper call; + bool const canContinue = true; + }; + + struct Operation { + std::vector outputs{}; + std::variant kind; + std::vector inputs{}; + }; + struct BasicBlock + { + struct MainExit {}; + struct ConditionalJump + { + langutil::DebugData::ConstPtr debugData; + ValueId condition; + BlockId nonZero; + BlockId zero; + }; + struct Jump + { + langutil::DebugData::ConstPtr debugData; + BlockId target; + }; + struct JumpTable + { + langutil::DebugData::ConstPtr debugData; + ValueId value; + std::map cases; + BlockId defaultCase; + + }; + struct FunctionReturn + { + langutil::DebugData::ConstPtr debugData; + std::vector returnValues; + }; + struct Terminated {}; + langutil::DebugData::ConstPtr debugData; + std::set entries; + std::set phis; + std::list operations; + std::variant exit = MainExit{}; + template + void forEachExit(Callable&& _callable) + { + if (auto* jump = std::get_if(&exit)) + _callable(jump->target); + else if (auto* conditionalJump = std::get_if(&exit)) + { + _callable(conditionalJump->nonZero); + _callable(conditionalJump->zero); + } + else if (auto* jumpTable = std::get_if(&exit)) + { + for (auto _case: jumpTable->cases | ranges::views::values) + _callable(_case); + _callable(jumpTable->defaultCase); + } + } + }; + BlockId makeBlock(langutil::DebugData::ConstPtr _debugData) + { + BlockId blockId { m_blocks.size() }; + m_blocks.emplace_back(BasicBlock{std::move(_debugData), {}, {}, {}, BasicBlock::Terminated{}}); + return blockId; + } + BasicBlock& block(BlockId _id) { return m_blocks.at(_id.value); } + BasicBlock const& block(BlockId _id) const { return m_blocks.at(_id.value); } + size_t numBlocks() const { return m_blocks.size(); } +private: + std::vector m_blocks; +public: + struct LiteralValue { u256 value; }; + struct VariableValue { SSACFG::BlockId definingBlock; }; + struct PhiValue { + BlockId block; + std::vector arguments; + }; + struct UnreachableValue {}; + using ValueInfo = std::variant; + ValueInfo& valueInfo(SSACFG::ValueId _var) + { + yulAssert(_var.value < m_valueInfos.size()); + return m_valueInfos.at(_var.value); + } + ValueInfo const& valueInfo(SSACFG::ValueId _var) const + { + yulAssert(_var.value < m_valueInfos.size()); + return m_valueInfos.at(_var.value); + } + ValueId newPhi(SSACFG::BlockId _definingBlock) + { + SSACFG::ValueId id { m_valueInfos.size() }; + m_valueInfos.emplace_back(PhiValue{_definingBlock, {}}); + return id; + } + ValueId newVariable(SSACFG::BlockId _definingBlock) + { + SSACFG::ValueId id { m_valueInfos.size() }; + m_valueInfos.emplace_back(VariableValue{_definingBlock}); + return id; + } + ValueId unreachableValue() + { + if (!m_unreachableValue) + { + m_unreachableValue = SSACFG::ValueId { m_valueInfos.size() }; + m_valueInfos.emplace_back(UnreachableValue{}); + } + return *m_unreachableValue; + } + ValueId newLiteral(u256 _value) + { + auto [it, inserted] = m_literals.emplace(std::make_pair(_value, SSACFG::ValueId{m_valueInfos.size()})); + if (inserted) + m_valueInfos.emplace_back(LiteralValue{_value}); + else + { + yulAssert(_value == it->first); + yulAssert(std::holds_alternative(m_valueInfos.at(it->second.value))); + yulAssert(std::get(m_valueInfos.at(it->second.value)).value == _value); + } + yulAssert(it->second.value < m_valueInfos.size()); + return it->second; + } +private: + std::deque m_valueInfos; + std::map m_literals; + std::optional m_unreachableValue; +public: + // TODO: the interface for function infos and functions here still sucks. + // Maybe we should split the graphs entirely and just have one SSACFG per function instead. + struct FunctionInfo { + langutil::DebugData::ConstPtr debugData; + std::reference_wrapper function; + BlockId entry; + std::set exits; + bool canContinue = true; + std::vector, ValueId>> arguments; + std::vector> returns; + }; + std::vector> functions; + /// Container for artificial calls generated for switch statements. + /// Ghost calls are used for the equality comparisons of the switch condition ghost variable with + /// the switch case literals when transforming the control flow of a switch to a sequence of conditional jumps. + std::list ghostCalls; +}; + +} diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp new file mode 100644 index 000000000..8648baa17 --- /dev/null +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -0,0 +1,850 @@ +/* + 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 +/** + * Transformation of a Yul AST into a control flow graph. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace solidity; +using namespace solidity::yul; + +namespace +{ +SSACFG::ValueId tryRemoveTrivialPhi(SSACFG& _cfg, SSACFG::ValueId _phi) +{ + // TODO: double-check if this is sane + auto* phiInfo = std::get_if(&_cfg.valueInfo(_phi)); + yulAssert(phiInfo); + + SSACFG::ValueId same; + for (SSACFG::ValueId arg: phiInfo->arguments) + { + if (arg == same || arg == _phi) + continue; + if (same) + return _phi; + same = arg; + } + + struct Use { + std::reference_wrapper operation; + size_t inputIndex = std::numeric_limits::max(); + }; + std::vector uses; + std::vector visited; + std::vector phiUses; + auto isVisited = [&](SSACFG::BlockId _block) -> bool { + if (_block.value < visited.size()) + return visited.at(_block.value); + else + return false; + }; + auto markVisited = [&](SSACFG::BlockId _block) { + if (visited.size() <= _block.value) + visited.resize(_block.value + 1); + visited[_block.value] = true; + }; + // does this even need to be recursive? or can uses only be in the same or neighbouring blocks? + auto findUses = [&](SSACFG::BlockId _blockId, auto _recurse) -> void { + if (isVisited(_blockId)) + return; + markVisited(_blockId); + auto& block = _cfg.block(_blockId); + for (auto blockPhi: block.phis) + { + if (blockPhi == _phi) + continue; + auto const* blockPhiInfo = std::get_if(&_cfg.valueInfo(blockPhi)); + yulAssert(blockPhiInfo); + bool usedInPhi = false; + for (auto input: blockPhiInfo->arguments) + { + if (input == _phi) + usedInPhi = true; + } + if (usedInPhi) + phiUses.emplace_back(blockPhi); + } + for (auto& op: block.operations) + { + // TODO: double check when phiVar occurs in outputs here and what to do about it. + if (op.outputs.size() == 1 && op.outputs.front() == _phi) + continue; + // TODO: check if this always hold - and if so if the assertion is really valuable. + for (auto& output: op.outputs) + yulAssert(output != _phi); + + for (auto&& [n, input]: op.inputs | ranges::views::enumerate) + if (input == _phi) + uses.emplace_back(Use{std::ref(op), n}); + } + block.forEachExit([&](SSACFG::BlockId _block) { + _recurse(_block, _recurse); + }); + }; + auto phiBlock = phiInfo->block; + _cfg.block(phiBlock).phis.erase(_phi); + findUses(phiBlock, findUses); + + if (!same) + { + // This will happen for unreachable paths. + // TODO: check how best to deal with this + same = _cfg.unreachableValue(); + } + + for (auto& use: uses) + use.operation.get().inputs.at(use.inputIndex) = same; + for (auto phiUse: phiUses) + { + auto* blockPhiInfo = std::get_if(&_cfg.valueInfo(phiUse)); + yulAssert(blockPhiInfo); + for (auto& arg: blockPhiInfo->arguments) + if (arg == _phi) + arg = same; + } + + for (auto phiUse: phiUses) + tryRemoveTrivialPhi(_cfg, phiUse); + + return same; +} + +/// Removes edges to blocks that are not reachable. +void cleanUnreachable(SSACFG& _cfg) +{ + // Determine which blocks are reachable from the entry. + util::BreadthFirstSearch reachabilityCheck{{SSACFG::BlockId{0}}}; + for (auto const& functionInfo: _cfg.functionInfos | ranges::views::values) + reachabilityCheck.verticesToTraverse.emplace_back(functionInfo.entry); + + reachabilityCheck.run([&](SSACFG::BlockId _blockId, auto&& _addChild) { + auto const& block = _cfg.block(_blockId); + visit(util::GenericVisitor{ + [&](SSACFG::BasicBlock::Jump const& _jump) { + _addChild(_jump.target); + }, + [&](SSACFG::BasicBlock::ConditionalJump const& _jump) { + _addChild(_jump.zero); + _addChild(_jump.nonZero); + }, + [](SSACFG::BasicBlock::JumpTable const&) { yulAssert(false); }, + [](SSACFG::BasicBlock::FunctionReturn const&) {}, + [](SSACFG::BasicBlock::Terminated const&) {}, + [](SSACFG::BasicBlock::MainExit const&) {} + }, block.exit); + }); + + auto isUnreachableValue = [&](SSACFG::ValueId const& _value) -> bool { + auto* valueInfo = std::get_if(&_cfg.valueInfo(_value)); + return (valueInfo) ? true : false; + }; + + // Remove all entries from unreachable nodes from the graph. + for (SSACFG::BlockId blockId: reachabilityCheck.visited) + { + auto& block = _cfg.block(blockId); + + for (auto phi: block.phis) + { + auto& phiValue = std::get(_cfg.valueInfo(phi)); + yulAssert(block.entries.size() == phiValue.arguments.size()); + for (auto&& [entry, arg]: ranges::zip_view(block.entries, phiValue.arguments)) + yulAssert((reachabilityCheck.visited.count(entry) == 0) == isUnreachableValue(arg)); + } + + std::set maybeTrivialPhi; + for (auto it = block.entries.begin(); it != block.entries.end();) + if (reachabilityCheck.visited.count(*it)) + it++; + else + it = block.entries.erase(it); + for (auto phi: block.phis) + if (auto* phiInfo = std::get_if(&_cfg.valueInfo(phi))) + cxx20::erase_if(phiInfo->arguments, [&](SSACFG::ValueId _arg) { + if (isUnreachableValue(_arg)) + { + maybeTrivialPhi.insert(phi); + return true; + } + return false; + }); + + // After removing a phi argument, we might end up with a trivial phi that can be removed. + for (auto phi: maybeTrivialPhi) + tryRemoveTrivialPhi(_cfg, phi); + } +} + +} + +namespace solidity::yul +{ + +SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder( + SSACFG& _graph, + AsmAnalysisInfo const& _analysisInfo, + std::map const& _functionSideEffects, + Dialect const& _dialect +): + m_graph(_graph), + m_info(_analysisInfo), + m_functionSideEffects(_functionSideEffects), + m_dialect(_dialect) +{ +} + +std::unique_ptr SSAControlFlowGraphBuilder::build( + AsmAnalysisInfo const& _analysisInfo, + Dialect const& _dialect, + Block const& _block +) +{ + auto result = std::make_unique(); + + ControlFlowSideEffectsCollector sideEffects(_dialect, _block); + SSAControlFlowGraphBuilder builder(*result, _analysisInfo, sideEffects.functionSideEffects(), _dialect); + builder.m_currentBlock = result->makeBlock(debugDataOf(_block)); + builder.sealBlock(builder.m_currentBlock); + builder(_block); + if (!builder.blockInfo(builder.m_currentBlock).sealed) + builder.sealBlock(builder.m_currentBlock); + result->block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; + + cleanUnreachable(*result); + return result; +} + +void SSAControlFlowGraphBuilder::operator()(ExpressionStatement const& _expressionStatement) +{ + auto const* functionCall = std::get_if(&_expressionStatement.expression); + yulAssert(functionCall); + auto results = visitFunctionCall(*functionCall); + yulAssert(results.empty()); +} + +void SSAControlFlowGraphBuilder::operator()(Assignment const& _assignment) +{ + assign( + _assignment.variableNames | ranges::views::transform([&](auto& _var) { return std::ref(lookupVariable(_var.name)); }) | ranges::to, + _assignment.value.get() + ); +} + +void SSAControlFlowGraphBuilder::operator()(VariableDeclaration const& _variableDeclaration) +{ + assign( + _variableDeclaration.variables | ranges::views::transform([&](auto& _var) { return std::ref(lookupVariable(_var.name)); }) | ranges::to, + _variableDeclaration.value.get() + ); +} + +void SSAControlFlowGraphBuilder::operator()(FunctionDefinition const& _functionDefinition) +{ + yulAssert(m_scope, ""); + yulAssert(m_scope->identifiers.count(_functionDefinition.name), ""); + Scope::Function& function = std::get(m_scope->identifiers.at(_functionDefinition.name)); + m_graph.functions.emplace_back(function); + + SSACFG::FunctionInfo& functionInfo = m_graph.functionInfos.at(&function); + + SSAControlFlowGraphBuilder builder{m_graph, m_info, m_functionSideEffects, m_dialect}; + builder.m_currentFunction = &functionInfo; + builder.m_currentBlock = functionInfo.entry; + for (auto&& [var, varId]: functionInfo.arguments) + builder.currentDef(var, functionInfo.entry) = varId; + builder.sealBlock(functionInfo.entry); + builder(_functionDefinition.body); + functionInfo.exits.insert(builder.m_currentBlock); + // Artificial explicit function exit (`leave`) at the end of the body. + builder(Leave{debugDataOf(_functionDefinition)}); +} + +void SSAControlFlowGraphBuilder::operator()(If const& _if) +{ + auto condition = std::visit(*this, *_if.condition); + auto ifBranch = m_graph.makeBlock(debugDataOf(_if.body)); + auto afterIf = m_graph.makeBlock(debugDataOf(currentBlock())); + conditionalJump( + debugDataOf(_if), + condition, + ifBranch, + afterIf + ); + sealBlock(ifBranch); + m_currentBlock = ifBranch; + (*this)(_if.body); + jump(debugDataOf(_if.body), afterIf); + sealBlock(afterIf); +} + +void SSAControlFlowGraphBuilder::operator()(Switch const& _switch) +{ + auto expression = std::visit(*this, *_switch.expression); + + auto useJumpTableForSwitch = [](Switch const&) { + // TODO: check for EOF support & tight switch values. + return false; + }; + if (useJumpTableForSwitch(_switch)) + { + // TODO: also generate a subtraction to shift tight, but non-zero switch cases - or, alternative, + // transform to zero-based tight switches on Yul if possible. + std::map cases; + std::optional defaultCase; + std::vector>> children; + for (auto const& _case: _switch.cases) + { + auto blockId = m_graph.makeBlock(debugDataOf(_case.body)); + if (_case.value) + cases[_case.value->value.value()] = blockId; + children.emplace_back(std::make_tuple(blockId, std::ref(_case.body))); + } + auto afterSwitch = m_graph.makeBlock(debugDataOf(currentBlock())); + + tableJump(debugDataOf(_switch), expression, cases, defaultCase ? *defaultCase : afterSwitch); + for (auto [blockId, block]: children) + { + sealBlock(blockId); + m_currentBlock = blockId; + (*this)(block); + jump(debugDataOf(currentBlock()), afterSwitch); + } + sealBlock(afterSwitch); + m_currentBlock = afterSwitch; + } + else + { + auto makeValueCompare = [&](Case const& _case) { + yul::FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(yul::FunctionCall{ + debugDataOf(_case), + yul::Identifier{{}, "eq"_yulname}, + {*_case.value /* skip second argument */ } + }); + auto outputValue = m_graph.newVariable(m_currentBlock); + BuiltinFunction const* builtin = m_dialect.builtin(ghostCall.functionName.name); + currentBlock().operations.emplace_back(SSACFG::Operation{ + {outputValue}, + SSACFG::BuiltinCall{ + debugDataOf(_case), + *builtin, + ghostCall + }, + {m_graph.newLiteral(_case.value->value.value()), expression} + }); + return outputValue; + }; + + auto afterSwitch = m_graph.makeBlock(debugDataOf(currentBlock())); + yulAssert(!_switch.cases.empty(), ""); + for (auto const& switchCase: _switch.cases | ranges::views::drop_last(1)) + { + yulAssert(switchCase.value, ""); + auto caseBranch = m_graph.makeBlock(debugDataOf(switchCase.body)); + auto elseBranch = m_graph.makeBlock(debugDataOf(_switch)); + + conditionalJump(debugDataOf(switchCase), makeValueCompare(switchCase), caseBranch, elseBranch); + sealBlock(caseBranch); + sealBlock(elseBranch); + m_currentBlock = caseBranch; + (*this)(switchCase.body); + jump(debugDataOf(switchCase.body), afterSwitch); + m_currentBlock = elseBranch; + } + Case const& switchCase = _switch.cases.back(); + if (switchCase.value) + { + auto caseBranch = m_graph.makeBlock(debugDataOf(switchCase.body)); + conditionalJump(debugDataOf(switchCase), makeValueCompare(switchCase), caseBranch, afterSwitch); + sealBlock(caseBranch); + m_currentBlock = caseBranch; + } + (*this)(switchCase.body); + jump(debugDataOf(switchCase.body), afterSwitch); + sealBlock(afterSwitch); + } +} +void SSAControlFlowGraphBuilder::operator()(ForLoop const& _loop) +{ + ScopedSaveAndRestore scopeRestore(m_scope, m_info.scopes.at(&_loop.pre).get()); + (*this)(_loop.pre); + auto preLoopDebugData = debugDataOf(currentBlock()); + + std::optional constantCondition; + if (auto const* literalCondition = std::get_if(_loop.condition.get())) + constantCondition = literalCondition->value.value() != 0; + + SSACFG::BlockId loopCondition = m_graph.makeBlock(debugDataOf(*_loop.condition)); + SSACFG::BlockId loopBody = m_graph.makeBlock(debugDataOf(_loop.body)); + SSACFG::BlockId post = m_graph.makeBlock(debugDataOf(_loop.post)); + SSACFG::BlockId afterLoop = m_graph.makeBlock(preLoopDebugData); + + class ForLoopInfoScope { + public: + ForLoopInfoScope(std::stack& _info, SSACFG::BlockId _breakBlock, SSACFG::BlockId _continueBlock): m_info(_info) + { + m_info.push(ForLoopInfo{_breakBlock, _continueBlock}); + } + ~ForLoopInfoScope() { + m_info.pop(); + } + private: + std::stack& m_info; + } forLoopInfoScope(m_forLoopInfo, afterLoop, post); + + if (constantCondition.has_value()) + { + if (*constantCondition) + { + jump(debugDataOf(*_loop.condition), loopBody); + (*this)(_loop.body); + jump(debugDataOf(_loop.body), post); + sealBlock(post); + (*this)(_loop.post); + jump(debugDataOf(_loop.post), loopBody); + sealBlock(loopBody); + } + else + jump(debugDataOf(*_loop.condition), afterLoop); + } + else + { + jump(debugDataOf(_loop.pre), loopCondition); + auto condition = std::visit(*this, *_loop.condition); + conditionalJump(debugDataOf(*_loop.condition), condition, loopBody, afterLoop); + sealBlock(loopBody); + m_currentBlock = loopBody; + (*this)(_loop.body); + jump(debugDataOf(_loop.body), post); + sealBlock(post); + (*this)(_loop.post); + jump(debugDataOf(_loop.post), loopCondition); + sealBlock(loopCondition); + } + + sealBlock(afterLoop); + m_currentBlock = afterLoop; +} + +void SSAControlFlowGraphBuilder::operator()(Break const& _break) +{ + yulAssert(!m_forLoopInfo.empty()); + auto currentBlockDebugData = debugDataOf(currentBlock()); + jump(debugDataOf(_break), m_forLoopInfo.top().breakBlock); + m_currentBlock = m_graph.makeBlock(currentBlockDebugData); + sealBlock(m_currentBlock); +} + +void SSAControlFlowGraphBuilder::operator()(Continue const& _continue) +{ + yulAssert(!m_forLoopInfo.empty()); + auto currentBlockDebugData = debugDataOf(currentBlock()); + jump(debugDataOf(_continue), m_forLoopInfo.top().continueBlock); + m_currentBlock = m_graph.makeBlock(currentBlockDebugData); + sealBlock(m_currentBlock); +} + +void SSAControlFlowGraphBuilder::operator()(Leave const& _leave) +{ + yulAssert(m_currentFunction); + auto currentBlockDebugData = debugDataOf(currentBlock()); + currentBlock().exit = SSACFG::BasicBlock::FunctionReturn{ + debugDataOf(_leave), + m_currentFunction->returns | ranges::views::transform([&](auto _var) { + return readVariable(_var, m_currentBlock); + }) | ranges::to + }; + m_currentBlock = m_graph.makeBlock(currentBlockDebugData); + sealBlock(m_currentBlock); +} + +void SSAControlFlowGraphBuilder::operator()(Block const& _block) +{ + ScopedSaveAndRestore saveScope(m_scope, m_info.scopes.at(&_block).get()); + for (auto const& statement: _block.statements) + if (auto const* function = std::get_if(&statement)) + registerFunction(*function); + for (auto const& statement: _block.statements) + std::visit(*this, statement); +} + +SSACFG::ValueId SSAControlFlowGraphBuilder::operator()(FunctionCall const& _call) +{ + auto results = visitFunctionCall(_call); + yulAssert(results.size() == 1); + return results.front(); +} + +SSACFG::ValueId SSAControlFlowGraphBuilder::operator()(Identifier const& _identifier) +{ + auto const& var = lookupVariable(_identifier.name); + return readVariable(var, m_currentBlock); +} + +SSACFG::ValueId SSAControlFlowGraphBuilder::operator()(Literal const& _literal) +{ + return m_graph.newLiteral(_literal.value.value()); +} + +void SSAControlFlowGraphBuilder::assign(std::vector> _variables, Expression const* _expression) +{ + auto rhs = [&]() -> std::vector { + if (auto const* functionCall = std::get_if(_expression)) + return visitFunctionCall(*functionCall); + else if (_expression) + return {std::visit(*this, *_expression)}; + else + return {_variables.size(), zero()}; + }(); + yulAssert(rhs.size() == _variables.size()); + + for (auto const& [var, value]: ranges::zip_view(_variables, rhs)) + writeVariable(var, m_currentBlock, value); + +} + +void SSAControlFlowGraphBuilder::registerFunction(FunctionDefinition const& _functionDefinition) +{ + yulAssert(m_scope, ""); + yulAssert(m_scope->identifiers.count(_functionDefinition.name), ""); + Scope::Function& function = std::get(m_scope->identifiers.at(_functionDefinition.name)); + + yulAssert(m_info.scopes.at(&_functionDefinition.body), ""); + Scope* virtualFunctionScope = m_info.scopes.at(m_info.virtualBlocks.at(&_functionDefinition).get()).get(); + yulAssert(virtualFunctionScope, ""); + + // TODO: think about using another root node before the function body here (in particular as defining block for the + // arguments below) + SSACFG::BlockId entryBlock = m_graph.makeBlock(debugDataOf(_functionDefinition.body)); + + auto arguments = _functionDefinition.parameters | ranges::views::transform([&](auto const& _param) { + auto const& var = std::get(virtualFunctionScope->identifiers.at(_param.name)); + // Note: cannot use std::make_tuple since it unwraps reference wrappers. + return std::tuple{std::cref(var), m_graph.newVariable(entryBlock)}; + }) | ranges::to; + auto returns = _functionDefinition.returnVariables | ranges::views::transform([&](auto const& _param) { + return std::cref(std::get(virtualFunctionScope->identifiers.at(_param.name))); + }) | ranges::to; + auto [it, inserted] = m_graph.functionInfos.emplace(std::make_pair(&function, SSACFG::FunctionInfo{ + _functionDefinition.debugData, + function, + entryBlock, + {}, + m_functionSideEffects.at(&_functionDefinition).canContinue, + arguments, + returns + })); + yulAssert(inserted); +} + +std::vector SSAControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _call) +{ + bool canContinue = true; + SSACFG::Operation operation = [&](){ + if (BuiltinFunction const* builtin = m_dialect.builtin(_call.functionName.name)) + { + SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData, *builtin, _call}, {}}; + for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) + if (!builtin->literalArgument(idx).has_value()) + result.inputs.emplace_back(std::visit(*this, arg)); + for (size_t i = 0; i < builtin->returns.size(); ++i) + result.outputs.emplace_back(m_graph.newVariable(m_currentBlock)); + canContinue = builtin->controlFlowSideEffects.canContinue; + return result; + } + else + { + Scope::Function const& function = lookupFunction(_call.functionName.name); + canContinue = m_graph.functionInfos.at(&function).canContinue; + SSACFG::Operation result{{}, SSACFG::Call{debugDataOf(_call), function, _call, canContinue}, {}}; + for (auto const& arg: _call.arguments | ranges::views::reverse) + result.inputs.emplace_back(std::visit(*this, arg)); + for (size_t i = 0; i < function.returns.size(); ++i) + result.outputs.emplace_back(m_graph.newVariable(m_currentBlock)); + return result; + } + }(); + auto results = operation.outputs; + currentBlock().operations.emplace_back(std::move(operation)); + if (!canContinue) + { + currentBlock().exit = SSACFG::BasicBlock::Terminated{}; + m_currentBlock = m_graph.makeBlock(debugDataOf(currentBlock())); + sealBlock(m_currentBlock); + } + return results; +} + +SSACFG::ValueId SSAControlFlowGraphBuilder::zero() +{ + return m_graph.newLiteral(0u); +} + +SSACFG::ValueId SSAControlFlowGraphBuilder::readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block) +{ + auto& def = currentDef(_variable, _block); + if (def.has_value()) + return *def; + return readVariableRecursive(_variable, _block); +} + +SSACFG::ValueId SSAControlFlowGraphBuilder::readVariableRecursive(Scope::Variable const& _variable, SSACFG::BlockId _block) +{ + auto& block = m_graph.block(_block); + auto& info = blockInfo(_block); + + if (info.sealed && block.entries.size() == 1) + return readVariable(_variable, *block.entries.begin()); + + SSACFG::ValueId phi = m_graph.newPhi(_block); + block.phis.insert(phi); + if (info.sealed) + { + writeVariable(_variable, _block, phi); + phi = addPhiOperands(_variable, phi); + } + else + { + info.incompletePhis.emplace_back(std::make_tuple(phi, std::ref(_variable))); + } + writeVariable(_variable, _block, phi); + return phi; +} + +SSACFG::ValueId SSAControlFlowGraphBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi) +{ + auto* phi = std::get_if(&m_graph.valueInfo(_phi)); + yulAssert(phi); + for (auto pred: m_graph.block(phi->block).entries) + phi->arguments.emplace_back(readVariable(_variable, pred)); + return tryRemoveTrivialPhi(_phi); +} + +SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) +{ + // TODO: double-check if this is sane + auto* phiInfo = std::get_if(&m_graph.valueInfo(_phi)); + yulAssert(phiInfo); + + SSACFG::ValueId same; + for (SSACFG::ValueId arg: phiInfo->arguments) + { + if (arg == same || arg == _phi) + continue; + if (same) + return _phi; + same = arg; + } + + struct Use { + std::reference_wrapper operation; + size_t inputIndex = std::numeric_limits::max(); + }; + std::vector uses; + std::vector visited; + std::vector phiUses; + auto isVisited = [&](SSACFG::BlockId _block) -> bool { + if (_block.value < visited.size()) + return visited.at(_block.value); + else + return false; + }; + auto markVisited = [&](SSACFG::BlockId _block) { + if (visited.size() <= _block.value) + visited.resize(_block.value + 1); + visited[_block.value] = true; + }; + // does this even need to be recursive? or can uses only be in the same or neighbouring blocks? + auto findUses = [&](SSACFG::BlockId _blockId, auto _recurse) -> void { + if (isVisited(_blockId)) + return; + markVisited(_blockId); + auto& block = m_graph.block(_blockId); + for (auto blockPhi: block.phis) + { + if (blockPhi == _phi) + continue; + auto const* blockPhiInfo = std::get_if(&m_graph.valueInfo(blockPhi)); + yulAssert(blockPhiInfo); + bool usedInPhi = false; + for (auto input: blockPhiInfo->arguments) + { + if (input == _phi) + usedInPhi = true; + } + if (usedInPhi) + phiUses.emplace_back(blockPhi); + } + for (auto& op: block.operations) + { + // TODO: double check when phiVar occurs in outputs here and what to do about it. + if (op.outputs.size() == 1 && op.outputs.front() == _phi) + continue; + // TODO: check if this always hold - and if so if the assertion is really valuable. + for (auto& output: op.outputs) + yulAssert(output != _phi); + + for (auto&& [n, input]: op.inputs | ranges::views::enumerate) + if (input == _phi) + uses.emplace_back(Use{std::ref(op), n}); + } + block.forEachExit([&](SSACFG::BlockId _block) { + _recurse(_block, _recurse); + }); + }; + auto phiBlock = phiInfo->block; + m_graph.block(phiBlock).phis.erase(_phi); + findUses(phiBlock, findUses); + + if (!same) + // This will happen for unreachable paths. + // TODO: check how best to deal with this + same = m_graph.unreachableValue(); + + for (auto& use: uses) + use.operation.get().inputs.at(use.inputIndex) = same; + for (auto phiUse: phiUses) + { + auto* blockPhiInfo = std::get_if(&m_graph.valueInfo(phiUse)); + yulAssert(blockPhiInfo); + for (auto& arg: blockPhiInfo->arguments) + if (arg == _phi) + arg = same; + } + + for (auto phiUse: phiUses) + tryRemoveTrivialPhi(phiUse); + + return same; +} + +void SSAControlFlowGraphBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value) +{ + currentDef(_variable, _block) = _value; +} + +Scope::Function const& SSAControlFlowGraphBuilder::lookupFunction(YulName _name) const +{ + Scope::Function const* function = nullptr; + yulAssert(m_scope->lookup(_name, util::GenericVisitor{ + [](Scope::Variable&) { yulAssert(false, "Expected function name."); }, + [&](Scope::Function& _function) { function = &_function; } + }), "Function name not found."); + yulAssert(function, ""); + return *function; +} + +Scope::Variable const& SSAControlFlowGraphBuilder::lookupVariable(YulName _name) const +{ + yulAssert(m_scope, ""); + Scope::Variable const* var = nullptr; + if (m_scope->lookup(_name, util::GenericVisitor{ + [&](Scope::Variable& _var) { var = &_var; }, + [](Scope::Function&) + { + yulAssert(false, "Function not removed during desugaring."); + } + })) + { + yulAssert(var, ""); + return *var; + }; + yulAssert(false, "External identifier access unimplemented."); +} + +void SSAControlFlowGraphBuilder::sealBlock(SSACFG::BlockId _block) +{ + auto& info = blockInfo(_block); + yulAssert(!info.sealed, "Trying to seal already sealed block."); + for (auto&& [phi, variable] : info.incompletePhis) + addPhiOperands(variable, phi); + info.sealed = true; +} + + +void SSAControlFlowGraphBuilder::conditionalJump( + langutil::DebugData::ConstPtr _debugData, + SSACFG::ValueId _condition, + SSACFG::BlockId _nonZero, + SSACFG::BlockId _zero +) +{ + currentBlock().exit = SSACFG::BasicBlock::ConditionalJump{ + std::move(_debugData), + _condition, + _nonZero, + _zero + }; + m_graph.block(_nonZero).entries.insert(m_currentBlock); + m_graph.block(_zero).entries.insert(m_currentBlock); + m_currentBlock = {}; +} + +void SSAControlFlowGraphBuilder::jump( + langutil::DebugData::ConstPtr _debugData, + SSACFG::BlockId _target +) +{ + currentBlock().exit = SSACFG::BasicBlock::Jump{std::move(_debugData), _target}; + yulAssert(!blockInfo(_target).sealed); + m_graph.block(_target).entries.insert(m_currentBlock); + m_currentBlock = _target; +} + +void SSAControlFlowGraphBuilder::tableJump( + langutil::DebugData::ConstPtr _debugData, + SSACFG::ValueId _value, + std::map _cases, + SSACFG::BlockId _defaultCase +) +{ + for (auto caseBlock: _cases | ranges::views::values) + { + yulAssert(!blockInfo(caseBlock).sealed); + m_graph.block(caseBlock).entries.insert(m_currentBlock); + } + yulAssert(!blockInfo(_defaultCase).sealed); + m_graph.block(_defaultCase).entries.insert(m_currentBlock); + currentBlock().exit = SSACFG::BasicBlock::JumpTable{ + std::move(_debugData), + _value, + std::move(_cases), + _defaultCase + }; + m_currentBlock = {}; +} + +} diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.h b/libyul/backends/evm/SSAControlFlowGraphBuilder.h new file mode 100644 index 000000000..689e5bf88 --- /dev/null +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.h @@ -0,0 +1,137 @@ +/* + 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 +/** +* Transformation of a Yul AST into a control flow graph. +*/ +#pragma once + +#include +#include +#include + +namespace solidity::yul +{ + +class SSAControlFlowGraphBuilder +{ + SSAControlFlowGraphBuilder( + SSACFG& _graph, + AsmAnalysisInfo const& _analysisInfo, + std::map const& _functionSideEffects, + Dialect const& _dialect + ); +public: + SSAControlFlowGraphBuilder(SSAControlFlowGraphBuilder const&) = delete; + SSAControlFlowGraphBuilder& operator=(SSAControlFlowGraphBuilder const&) = delete; + static std::unique_ptr build(AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, Block const& _block); + + void operator()(ExpressionStatement const& _statement); + void operator()(Assignment const& _assignment); + void operator()(VariableDeclaration const& _varDecl); + + void operator()(FunctionDefinition const&); + void operator()(If const& _if); + void operator()(Switch const& _switch); + void operator()(ForLoop const&); + void operator()(Break const&); + void operator()(Continue const&); + void operator()(Leave const&); + + void operator()(Block const& _block); + + SSACFG::ValueId operator()(FunctionCall const& _call); + SSACFG::ValueId operator()(Identifier const& _identifier); + SSACFG::ValueId operator()(Literal const& _literal); + +private: + void assign(std::vector> _variables, Expression const* _expression); + + void registerFunction(FunctionDefinition const& _function); + std::vector visitFunctionCall(FunctionCall const& _call); + + SSACFG::ValueId zero(); + SSACFG::ValueId readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block); + SSACFG::ValueId readVariableRecursive(Scope::Variable const& _variable, SSACFG::BlockId _block); + SSACFG::ValueId addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi); + void writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value); + + SSACFG& m_graph; + AsmAnalysisInfo const& m_info; + std::map const& m_functionSideEffects; + Dialect const& m_dialect; + SSACFG::BlockId m_currentBlock; + SSACFG::BasicBlock& currentBlock() { return m_graph.block(m_currentBlock); } + Scope* m_scope = nullptr; + Scope::Function const& lookupFunction(YulName _name) const; + Scope::Variable const& lookupVariable(YulName _name) const; + + struct BlockInfo { + bool sealed = false; + std::vector>> incompletePhis; + }; + std::vector m_blockInfo; + + BlockInfo& blockInfo(SSACFG::BlockId _block) + { + if (_block.value >= m_blockInfo.size()) + m_blockInfo.resize(_block.value + 1, {}); + return m_blockInfo[_block.value]; + } + void sealBlock(SSACFG::BlockId _block); + + std::map< + Scope::Variable const*, + std::vector> + > m_currentDef; + + struct ForLoopInfo { + SSACFG::BlockId breakBlock; + SSACFG::BlockId continueBlock; + }; + std::stack m_forLoopInfo; + SSACFG::FunctionInfo* m_currentFunction = nullptr; + + std::optional& currentDef(Scope::Variable const& _variable, SSACFG::BlockId _block) + { + auto& varDefs = m_currentDef[&_variable]; + if (varDefs.size() <= _block.value) + varDefs.resize(_block.value + 1); + return varDefs.at(_block.value); + } + + void conditionalJump( + langutil::DebugData::ConstPtr _debugData, + SSACFG::ValueId _condition, + SSACFG::BlockId _nonZero, + SSACFG::BlockId _zero + ); + + void jump( + langutil::DebugData::ConstPtr _debugData, + SSACFG::BlockId _target + ); + + void tableJump( + langutil::DebugData::ConstPtr _debugData, + SSACFG::ValueId _value, + std::map _cases, + SSACFG::BlockId _defaultCase + ); +}; + +} From d9116dc41c8daac9bfa6a2efe0dc3dd2f80f1d2e Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 21 Aug 2024 15:56:32 +0200 Subject: [PATCH 0287/1340] Yul: Split SSA CFG into separate graphs for functions --- libyul/backends/evm/ControlFlow.h | 43 ++++ libyul/backends/evm/SSAControlFlowGraph.h | 72 +++---- .../evm/SSAControlFlowGraphBuilder.cpp | 196 +++++++++--------- .../backends/evm/SSAControlFlowGraphBuilder.h | 25 ++- .../libyul/yulSSAControlFlowGraph/complex.yul | 179 ++++++++++++++++ .../yulSSAControlFlowGraph/complex2.yul | 195 +++++++++++++++++ .../yulSSAControlFlowGraph/function.yul | 68 ++++++ test/libyul/yulSSAControlFlowGraph/if.yul | 40 ++++ test/libyul/yulSSAControlFlowGraph/switch.yul | 68 ++++++ 9 files changed, 750 insertions(+), 136 deletions(-) create mode 100644 libyul/backends/evm/ControlFlow.h create mode 100644 test/libyul/yulSSAControlFlowGraph/complex.yul create mode 100644 test/libyul/yulSSAControlFlowGraph/complex2.yul create mode 100644 test/libyul/yulSSAControlFlowGraph/function.yul create mode 100644 test/libyul/yulSSAControlFlowGraph/if.yul create mode 100644 test/libyul/yulSSAControlFlowGraph/switch.yul diff --git a/libyul/backends/evm/ControlFlow.h b/libyul/backends/evm/ControlFlow.h new file mode 100644 index 000000000..18b43431a --- /dev/null +++ b/libyul/backends/evm/ControlFlow.h @@ -0,0 +1,43 @@ +/* + 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 + +#pragma once + +#include +#include +#include + +namespace solidity::yul +{ + +struct ControlFlow +{ + std::unique_ptr mainGraph{std::make_unique()}; + std::vector> functionGraphs{}; + std::vector> functionGraphMapping{}; + + SSACFG const* functionGraph(Scope::Function const* _function) + { + auto it = std::find_if(functionGraphMapping.begin(), functionGraphMapping.end(), [_function](auto const& tup) { return _function == std::get<0>(tup); }); + if (it != functionGraphMapping.end()) + return std::get<1>(*it); + return nullptr; + } +}; + +} diff --git a/libyul/backends/evm/SSAControlFlowGraph.h b/libyul/backends/evm/SSAControlFlowGraph.h index f24b2779f..311d23e87 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.h +++ b/libyul/backends/evm/SSAControlFlowGraph.h @@ -29,10 +29,10 @@ #include +#include #include #include #include -#include #include namespace solidity::yul @@ -41,7 +41,7 @@ namespace solidity::yul class SSACFG { public: - SSACFG() {} + SSACFG() = default; SSACFG(SSACFG const&) = delete; SSACFG(SSACFG&&) = delete; SSACFG& operator=(SSACFG const&) = delete; @@ -51,7 +51,6 @@ class SSACFG struct BlockId { size_t value = std::numeric_limits::max(); - operator bool() const { return value != std::numeric_limits::max(); } bool operator<(BlockId const& _rhs) const { return value < _rhs.value; } bool operator==(BlockId const& _rhs) const { return value == _rhs.value; } bool operator!=(BlockId const& _rhs) const { return value != _rhs.value; } @@ -59,11 +58,12 @@ class SSACFG struct ValueId { size_t value = std::numeric_limits::max(); - operator bool() const { return value != std::numeric_limits::max(); } + bool hasValue() const { return value != std::numeric_limits::max(); } bool operator<(ValueId const& _rhs) const { return value < _rhs.value; } bool operator==(ValueId const& _rhs) const { return value == _rhs.value; } bool operator!=(ValueId const& _rhs) const { return value != _rhs.value; } }; + struct BuiltinCall { langutil::DebugData::ConstPtr debugData; @@ -104,7 +104,6 @@ class SSACFG ValueId value; std::map cases; BlockId defaultCase; - }; struct FunctionReturn { @@ -115,7 +114,7 @@ class SSACFG langutil::DebugData::ConstPtr debugData; std::set entries; std::set phis; - std::list operations; + std::vector operations; std::variant exit = MainExit{}; template void forEachExit(Callable&& _callable) @@ -147,50 +146,57 @@ class SSACFG private: std::vector m_blocks; public: - struct LiteralValue { u256 value; }; - struct VariableValue { SSACFG::BlockId definingBlock; }; + struct LiteralValue { + langutil::DebugData::ConstPtr debugData; + u256 value; + }; + struct VariableValue { + langutil::DebugData::ConstPtr debugData; + BlockId definingBlock; + }; struct PhiValue { + langutil::DebugData::ConstPtr debugData; BlockId block; std::vector arguments; }; struct UnreachableValue {}; using ValueInfo = std::variant; - ValueInfo& valueInfo(SSACFG::ValueId _var) + ValueInfo& valueInfo(ValueId const _var) { - yulAssert(_var.value < m_valueInfos.size()); return m_valueInfos.at(_var.value); } - ValueInfo const& valueInfo(SSACFG::ValueId _var) const + ValueInfo const& valueInfo(ValueId const _var) const { - yulAssert(_var.value < m_valueInfos.size()); return m_valueInfos.at(_var.value); } - ValueId newPhi(SSACFG::BlockId _definingBlock) + ValueId newPhi(BlockId const _definingBlock) { - SSACFG::ValueId id { m_valueInfos.size() }; - m_valueInfos.emplace_back(PhiValue{_definingBlock, {}}); + ValueId id { m_valueInfos.size() }; + auto block = m_blocks.at(_definingBlock.value); + m_valueInfos.emplace_back(PhiValue{debugDataOf(block), _definingBlock, {}}); return id; } - ValueId newVariable(SSACFG::BlockId _definingBlock) + ValueId newVariable(BlockId const _definingBlock) { - SSACFG::ValueId id { m_valueInfos.size() }; - m_valueInfos.emplace_back(VariableValue{_definingBlock}); + ValueId id { m_valueInfos.size() }; + auto block = m_blocks.at(_definingBlock.value); + m_valueInfos.emplace_back(VariableValue{debugDataOf(block), _definingBlock}); return id; } ValueId unreachableValue() { if (!m_unreachableValue) { - m_unreachableValue = SSACFG::ValueId { m_valueInfos.size() }; + m_unreachableValue = ValueId { m_valueInfos.size() }; m_valueInfos.emplace_back(UnreachableValue{}); } return *m_unreachableValue; } - ValueId newLiteral(u256 _value) + ValueId newLiteral(langutil::DebugData::ConstPtr _debugData, u256 _value) { - auto [it, inserted] = m_literals.emplace(std::make_pair(_value, SSACFG::ValueId{m_valueInfos.size()})); + auto [it, inserted] = m_literals.emplace(_value, ValueId{m_valueInfos.size()}); if (inserted) - m_valueInfos.emplace_back(LiteralValue{_value}); + m_valueInfos.emplace_back(LiteralValue{std::move(_debugData), _value}); else { yulAssert(_value == it->first); @@ -205,21 +211,15 @@ class SSACFG std::map m_literals; std::optional m_unreachableValue; public: - // TODO: the interface for function infos and functions here still sucks. - // Maybe we should split the graphs entirely and just have one SSACFG per function instead. - struct FunctionInfo { - langutil::DebugData::ConstPtr debugData; - std::reference_wrapper function; - BlockId entry; - std::set exits; - bool canContinue = true; - std::vector, ValueId>> arguments; - std::vector> returns; - }; + langutil::DebugData::ConstPtr debugData; + BlockId entry = BlockId{0}; + std::set exits; + Scope::Function const* function = nullptr; + bool canContinue = true; + std::vector, ValueId>> arguments; + std::vector> returns; std::vector> functions; - /// Container for artificial calls generated for switch statements. - /// Ghost calls are used for the equality comparisons of the switch condition ghost variable with - /// the switch case literals when transforming the control flow of a switch to a sequence of conditional jumps. + // Container for artificial calls generated for switch statements. std::list ghostCalls; }; diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 8648baa17..18720e9bc 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,7 @@ SSACFG::ValueId tryRemoveTrivialPhi(SSACFG& _cfg, SSACFG::ValueId _phi) { if (arg == same || arg == _phi) continue; - if (same) + if (same.hasValue()) return _phi; same = arg; } @@ -119,7 +120,7 @@ SSACFG::ValueId tryRemoveTrivialPhi(SSACFG& _cfg, SSACFG::ValueId _phi) _cfg.block(phiBlock).phis.erase(_phi); findUses(phiBlock, findUses); - if (!same) + if (!same.hasValue()) { // This will happen for unreachable paths. // TODO: check how best to deal with this @@ -147,10 +148,7 @@ SSACFG::ValueId tryRemoveTrivialPhi(SSACFG& _cfg, SSACFG::ValueId _phi) void cleanUnreachable(SSACFG& _cfg) { // Determine which blocks are reachable from the entry. - util::BreadthFirstSearch reachabilityCheck{{SSACFG::BlockId{0}}}; - for (auto const& functionInfo: _cfg.functionInfos | ranges::views::values) - reachabilityCheck.verticesToTraverse.emplace_back(functionInfo.entry); - + util::BreadthFirstSearch reachabilityCheck{{_cfg.entry}}; reachabilityCheck.run([&](SSACFG::BlockId _blockId, auto&& _addChild) { auto const& block = _cfg.block(_blockId); visit(util::GenericVisitor{ @@ -217,35 +215,94 @@ namespace solidity::yul SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder( SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, - std::map const& _functionSideEffects, Dialect const& _dialect ): m_graph(_graph), m_info(_analysisInfo), - m_functionSideEffects(_functionSideEffects), m_dialect(_dialect) { } -std::unique_ptr SSAControlFlowGraphBuilder::build( +std::unique_ptr SSAControlFlowGraphBuilder::build( AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, Block const& _block ) { - auto result = std::make_unique(); - ControlFlowSideEffectsCollector sideEffects(_dialect, _block); - SSAControlFlowGraphBuilder builder(*result, _analysisInfo, sideEffects.functionSideEffects(), _dialect); - builder.m_currentBlock = result->makeBlock(debugDataOf(_block)); + + auto result = std::make_unique(); + auto functions = buildMainGraph(*result->mainGraph, _analysisInfo, _dialect, _block); + buildFunctionGraphs(*result, _analysisInfo, sideEffects, _dialect, functions); + + cleanUnreachable(*result->mainGraph); + for (auto& functionGraph: result->functionGraphs) + cleanUnreachable(*functionGraph); + return result; +} + +void SSAControlFlowGraphBuilder::buildFunctionGraphs( + ControlFlow& _controlFlow, + AsmAnalysisInfo const& _info, + ControlFlowSideEffectsCollector const& _sideEffects, + Dialect const& _dialect, + std::vector> const& _functions +) +{ + for (auto const& [function, functionDefinition]: _functions) + { + _controlFlow.functionGraphs.emplace_back(std::make_unique()); + auto& cfg = *_controlFlow.functionGraphs.back(); + _controlFlow.functionGraphMapping.emplace_back(function, &cfg); + + yulAssert(_info.scopes.at(&functionDefinition->body), ""); + Scope* virtualFunctionScope = _info.scopes.at(_info.virtualBlocks.at(functionDefinition).get()).get(); + yulAssert(virtualFunctionScope, ""); + + cfg.entry = cfg.makeBlock(debugDataOf(functionDefinition->body)); + auto arguments = functionDefinition->parameters | ranges::views::transform([&](auto const& _param) { + auto const& var = std::get(virtualFunctionScope->identifiers.at(_param.name)); + // Note: cannot use std::make_tuple since it unwraps reference wrappers. + return std::tuple{std::cref(var), cfg.newVariable(cfg.entry)}; + }) | ranges::to; + auto returns = functionDefinition->returnVariables | ranges::views::transform([&](auto const& _param) { + return std::cref(std::get(virtualFunctionScope->identifiers.at(_param.name))); + }) | ranges::to; + + cfg.debugData = functionDefinition->debugData; + cfg.function = function; + cfg.canContinue = _sideEffects.functionSideEffects().at(functionDefinition).canContinue; + cfg.arguments = arguments; + cfg.returns = returns; + + SSAControlFlowGraphBuilder builder(cfg, _info, _dialect); + builder.m_currentBlock = cfg.entry; + for (auto&& [var, varId]: cfg.arguments) + builder.currentDef(var, cfg.entry) = varId; + builder.sealBlock(cfg.entry); + builder(functionDefinition->body); + cfg.exits.insert(builder.m_currentBlock); + // Artificial explicit function exit (`leave`) at the end of the body. + builder(Leave{debugDataOf(*functionDefinition)}); + } +} + +std::vector> SSAControlFlowGraphBuilder::buildMainGraph( + SSACFG& _cfg, + AsmAnalysisInfo const& _analysisInfo, + Dialect const& _dialect, + Block const& _block +) +{ + SSAControlFlowGraphBuilder builder(_cfg, _analysisInfo, _dialect); + builder.m_currentBlock = _cfg.makeBlock(debugDataOf(_block)); builder.sealBlock(builder.m_currentBlock); builder(_block); if (!builder.blockInfo(builder.m_currentBlock).sealed) builder.sealBlock(builder.m_currentBlock); - result->block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; + _cfg.block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; - cleanUnreachable(*result); - return result; + return builder.m_functionDefinitions; } void SSAControlFlowGraphBuilder::operator()(ExpressionStatement const& _expressionStatement) @@ -276,21 +333,9 @@ void SSAControlFlowGraphBuilder::operator()(FunctionDefinition const& _functionD { yulAssert(m_scope, ""); yulAssert(m_scope->identifiers.count(_functionDefinition.name), ""); - Scope::Function& function = std::get(m_scope->identifiers.at(_functionDefinition.name)); + auto& function = std::get(m_scope->identifiers.at(_functionDefinition.name)); m_graph.functions.emplace_back(function); - - SSACFG::FunctionInfo& functionInfo = m_graph.functionInfos.at(&function); - - SSAControlFlowGraphBuilder builder{m_graph, m_info, m_functionSideEffects, m_dialect}; - builder.m_currentFunction = &functionInfo; - builder.m_currentBlock = functionInfo.entry; - for (auto&& [var, varId]: functionInfo.arguments) - builder.currentDef(var, functionInfo.entry) = varId; - builder.sealBlock(functionInfo.entry); - builder(_functionDefinition.body); - functionInfo.exits.insert(builder.m_currentBlock); - // Artificial explicit function exit (`leave`) at the end of the body. - builder(Leave{debugDataOf(_functionDefinition)}); + m_functionDefinitions.emplace_back(&function, &_functionDefinition); } void SSAControlFlowGraphBuilder::operator()(If const& _if) @@ -331,7 +376,9 @@ void SSAControlFlowGraphBuilder::operator()(Switch const& _switch) auto blockId = m_graph.makeBlock(debugDataOf(_case.body)); if (_case.value) cases[_case.value->value.value()] = blockId; - children.emplace_back(std::make_tuple(blockId, std::ref(_case.body))); + else + defaultCase = blockId; + children.emplace_back(blockId, std::ref(_case.body)); } auto afterSwitch = m_graph.makeBlock(debugDataOf(currentBlock())); @@ -349,9 +396,9 @@ void SSAControlFlowGraphBuilder::operator()(Switch const& _switch) else { auto makeValueCompare = [&](Case const& _case) { - yul::FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(yul::FunctionCall{ + FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(FunctionCall{ debugDataOf(_case), - yul::Identifier{{}, "eq"_yulname}, + Identifier{{}, "eq"_yulname}, {*_case.value /* skip second argument */ } }); auto outputValue = m_graph.newVariable(m_currentBlock); @@ -363,7 +410,7 @@ void SSAControlFlowGraphBuilder::operator()(Switch const& _switch) *builtin, ghostCall }, - {m_graph.newLiteral(_case.value->value.value()), expression} + {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression} }); return outputValue; }; @@ -404,7 +451,7 @@ void SSAControlFlowGraphBuilder::operator()(ForLoop const& _loop) auto preLoopDebugData = debugDataOf(currentBlock()); std::optional constantCondition; - if (auto const* literalCondition = std::get_if(_loop.condition.get())) + if (auto const* literalCondition = std::get_if(_loop.condition.get())) constantCondition = literalCondition->value.value() != 0; SSACFG::BlockId loopCondition = m_graph.makeBlock(debugDataOf(*_loop.condition)); @@ -477,13 +524,12 @@ void SSAControlFlowGraphBuilder::operator()(Continue const& _continue) sealBlock(m_currentBlock); } -void SSAControlFlowGraphBuilder::operator()(Leave const& _leave) +void SSAControlFlowGraphBuilder::operator()(Leave const& _leaveStatement) { - yulAssert(m_currentFunction); auto currentBlockDebugData = debugDataOf(currentBlock()); currentBlock().exit = SSACFG::BasicBlock::FunctionReturn{ - debugDataOf(_leave), - m_currentFunction->returns | ranges::views::transform([&](auto _var) { + debugDataOf(_leaveStatement), + m_graph.returns | ranges::views::transform([&](auto _var) { return readVariable(_var, m_currentBlock); }) | ranges::to }; @@ -494,9 +540,6 @@ void SSAControlFlowGraphBuilder::operator()(Leave const& _leave) void SSAControlFlowGraphBuilder::operator()(Block const& _block) { ScopedSaveAndRestore saveScope(m_scope, m_info.scopes.at(&_block).get()); - for (auto const& statement: _block.statements) - if (auto const* function = std::get_if(&statement)) - registerFunction(*function); for (auto const& statement: _block.statements) std::visit(*this, statement); } @@ -516,7 +559,7 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::operator()(Identifier const& _identi SSACFG::ValueId SSAControlFlowGraphBuilder::operator()(Literal const& _literal) { - return m_graph.newLiteral(_literal.value.value()); + return m_graph.newLiteral(debugDataOf(currentBlock()), _literal.value.value()); } void SSAControlFlowGraphBuilder::assign(std::vector> _variables, Expression const* _expression) @@ -536,40 +579,6 @@ void SSAControlFlowGraphBuilder::assign(std::vectoridentifiers.count(_functionDefinition.name), ""); - Scope::Function& function = std::get(m_scope->identifiers.at(_functionDefinition.name)); - - yulAssert(m_info.scopes.at(&_functionDefinition.body), ""); - Scope* virtualFunctionScope = m_info.scopes.at(m_info.virtualBlocks.at(&_functionDefinition).get()).get(); - yulAssert(virtualFunctionScope, ""); - - // TODO: think about using another root node before the function body here (in particular as defining block for the - // arguments below) - SSACFG::BlockId entryBlock = m_graph.makeBlock(debugDataOf(_functionDefinition.body)); - - auto arguments = _functionDefinition.parameters | ranges::views::transform([&](auto const& _param) { - auto const& var = std::get(virtualFunctionScope->identifiers.at(_param.name)); - // Note: cannot use std::make_tuple since it unwraps reference wrappers. - return std::tuple{std::cref(var), m_graph.newVariable(entryBlock)}; - }) | ranges::to; - auto returns = _functionDefinition.returnVariables | ranges::views::transform([&](auto const& _param) { - return std::cref(std::get(virtualFunctionScope->identifiers.at(_param.name))); - }) | ranges::to; - auto [it, inserted] = m_graph.functionInfos.emplace(std::make_pair(&function, SSACFG::FunctionInfo{ - _functionDefinition.debugData, - function, - entryBlock, - {}, - m_functionSideEffects.at(&_functionDefinition).canContinue, - arguments, - returns - })); - yulAssert(inserted); -} - std::vector SSAControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _call) { bool canContinue = true; @@ -580,7 +589,7 @@ std::vector SSAControlFlowGraphBuilder::visitFunctionCall(Funct for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) if (!builtin->literalArgument(idx).has_value()) result.inputs.emplace_back(std::visit(*this, arg)); - for (size_t i = 0; i < builtin->returns.size(); ++i) + for (size_t i = 0; i < builtin->numReturns; ++i) result.outputs.emplace_back(m_graph.newVariable(m_currentBlock)); canContinue = builtin->controlFlowSideEffects.canContinue; return result; @@ -588,11 +597,11 @@ std::vector SSAControlFlowGraphBuilder::visitFunctionCall(Funct else { Scope::Function const& function = lookupFunction(_call.functionName.name); - canContinue = m_graph.functionInfos.at(&function).canContinue; + canContinue = m_graph.canContinue; SSACFG::Operation result{{}, SSACFG::Call{debugDataOf(_call), function, _call, canContinue}, {}}; for (auto const& arg: _call.arguments | ranges::views::reverse) result.inputs.emplace_back(std::visit(*this, arg)); - for (size_t i = 0; i < function.returns.size(); ++i) + for (size_t i = 0; i < function.numReturns; ++i) result.outputs.emplace_back(m_graph.newVariable(m_currentBlock)); return result; } @@ -610,13 +619,12 @@ std::vector SSAControlFlowGraphBuilder::visitFunctionCall(Funct SSACFG::ValueId SSAControlFlowGraphBuilder::zero() { - return m_graph.newLiteral(0u); + return m_graph.newLiteral(debugDataOf(currentBlock()), 0u); } SSACFG::ValueId SSAControlFlowGraphBuilder::readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block) { - auto& def = currentDef(_variable, _block); - if (def.has_value()) + if (auto const& def = currentDef(_variable, _block)) return *def; return readVariableRecursive(_variable, _block); } @@ -638,7 +646,7 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::readVariableRecursive(Scope::Variabl } else { - info.incompletePhis.emplace_back(std::make_tuple(phi, std::ref(_variable))); + info.incompletePhis.emplace_back(phi, std::ref(_variable)); } writeVariable(_variable, _block, phi); return phi; @@ -646,25 +654,25 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::readVariableRecursive(Scope::Variabl SSACFG::ValueId SSAControlFlowGraphBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi) { - auto* phi = std::get_if(&m_graph.valueInfo(_phi)); - yulAssert(phi); - for (auto pred: m_graph.block(phi->block).entries) - phi->arguments.emplace_back(readVariable(_variable, pred)); + yulAssert(std::holds_alternative(m_graph.valueInfo(_phi))); + auto& phi = std::get(m_graph.valueInfo(_phi)); + for (auto pred: m_graph.block(phi.block).entries) + phi.arguments.emplace_back(readVariable(_variable, pred)); return tryRemoveTrivialPhi(_phi); } SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) { // TODO: double-check if this is sane - auto* phiInfo = std::get_if(&m_graph.valueInfo(_phi)); - yulAssert(phiInfo); + yulAssert(std::holds_alternative(m_graph.valueInfo(_phi))); + auto& phiInfo = std::get(m_graph.valueInfo(_phi)); SSACFG::ValueId same; - for (SSACFG::ValueId arg: phiInfo->arguments) + for (SSACFG::ValueId arg: phiInfo.arguments) { if (arg == same || arg == _phi) continue; - if (same) + if (same.hasValue()) return _phi; same = arg; } @@ -725,11 +733,11 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _recurse(_block, _recurse); }); }; - auto phiBlock = phiInfo->block; + auto phiBlock = phiInfo.block; m_graph.block(phiBlock).phis.erase(_phi); findUses(phiBlock, findUses); - if (!same) + if (!same.hasValue()) // This will happen for unreachable paths. // TODO: check how best to deal with this same = m_graph.unreachableValue(); diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.h b/libyul/backends/evm/SSAControlFlowGraphBuilder.h index 689e5bf88..031016219 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.h +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.h @@ -20,7 +20,9 @@ */ #pragma once +#include #include +#include #include #include @@ -32,13 +34,25 @@ class SSAControlFlowGraphBuilder SSAControlFlowGraphBuilder( SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, - std::map const& _functionSideEffects, Dialect const& _dialect ); public: SSAControlFlowGraphBuilder(SSAControlFlowGraphBuilder const&) = delete; SSAControlFlowGraphBuilder& operator=(SSAControlFlowGraphBuilder const&) = delete; - static std::unique_ptr build(AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, Block const& _block); + static std::unique_ptr build(AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, Block const& _block); + static void buildFunctionGraphs( + ControlFlow& _controlFlow, + AsmAnalysisInfo const& _info, + ControlFlowSideEffectsCollector const& _sideEffects, + Dialect const& _dialect, + std::vector> const& _functions + ); + static std::vector> buildMainGraph( + SSACFG& _cfg, + AsmAnalysisInfo const& _analysisInfo, + Dialect const& _dialect, + Block const& _block + ); void operator()(ExpressionStatement const& _statement); void operator()(Assignment const& _assignment); @@ -60,19 +74,17 @@ class SSAControlFlowGraphBuilder private: void assign(std::vector> _variables, Expression const* _expression); - - void registerFunction(FunctionDefinition const& _function); std::vector visitFunctionCall(FunctionCall const& _call); SSACFG::ValueId zero(); SSACFG::ValueId readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block); SSACFG::ValueId readVariableRecursive(Scope::Variable const& _variable, SSACFG::BlockId _block); SSACFG::ValueId addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi); + SSACFG::ValueId tryRemoveTrivialPhi(SSACFG::ValueId _phi); void writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value); SSACFG& m_graph; AsmAnalysisInfo const& m_info; - std::map const& m_functionSideEffects; Dialect const& m_dialect; SSACFG::BlockId m_currentBlock; SSACFG::BasicBlock& currentBlock() { return m_graph.block(m_currentBlock); } @@ -104,7 +116,6 @@ class SSAControlFlowGraphBuilder SSACFG::BlockId continueBlock; }; std::stack m_forLoopInfo; - SSACFG::FunctionInfo* m_currentFunction = nullptr; std::optional& currentDef(Scope::Variable const& _variable, SSACFG::BlockId _block) { @@ -132,6 +143,8 @@ class SSAControlFlowGraphBuilder std::map _cases, SSACFG::BlockId _defaultCase ); + + std::vector> m_functionDefinitions; }; } diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul new file mode 100644 index 000000000..042b313af --- /dev/null +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -0,0 +1,179 @@ +{ + function f(a, b) -> c { + for { let x := 42 } lt(x, a) { + x := add(x, 1) + if calldataload(x) + { + sstore(0, x) + leave + sstore(0x01, 0x0101) + } + sstore(0xFF, 0xFFFF) + } + { + switch mload(x) + case 0 { + sstore(0x02, 0x0202) + break + sstore(0x03, 0x0303) + } + case 1 { + sstore(0x04, 0x0404) + leave + sstore(0x05, 0x0505) + } + case 2 { + sstore(0x06, 0x0606) + revert(0, 0) + sstore(0x07, 0x0707) + } + case 3 { + sstore(0x08, 0x0808) + } + default { + if mload(b) { + return(0, 0) + sstore(0x09, 0x0909) + } + sstore(0x0A, 0x0A0A) + } + sstore(0x0B, 0x0B0B) + } + sstore(0x0C, 0x0C0C) + } + pop(f(1,2)) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans" ] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry0 [label="Entry"]; +// Entry0 -> Block0_0; +// Block0_0 [label="\ +// Block 0\nv2 := f(2, 1)\l\ +// pop(v2)\l\ +// "]; +// Block0_0Exit [label="MainExit"]; +// Block0_0 -> Block0_0Exit; +// FunctionEntry_f_0 [label="function f: +// c := f(v0, v1)"]; +// FunctionEntry_f_0 -> Block1_0; +// Block1_0 [label="\ +// Block 0\n"]; +// Block1_0 -> Block1_0Exit [arrowhead=none]; +// Block1_0Exit [label="Jump" shape=oval]; +// Block1_0Exit -> Block1_1; +// Block1_1 [label="\ +// Block 1\nv4 := φ(\l\ +// Block 0 => 42,\l\ +// Block 21 => v43\l\ +// )\l\ +// v5 := lt(v0, v4)\l\ +// "]; +// Block1_1 -> Block1_1Exit; +// Block1_1Exit [label="{ If v5| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit:0 -> Block1_4; +// Block1_1Exit:1 -> Block1_2; +// Block1_2 [label="\ +// Block 2\nv6 := mload(v4)\l\ +// v7 := eq(0, v6)\l\ +// "]; +// Block1_2 -> Block1_2Exit; +// Block1_2Exit [label="{ If v7| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit:0 -> Block1_7; +// Block1_2Exit:1 -> Block1_6; +// Block1_4 [label="\ +// Block 4\nsstore(3084, 12)\l\ +// "]; +// Block1_4Exit [label="FunctionReturn[v17]"]; +// Block1_4 -> Block1_4Exit; +// Block1_6 [label="\ +// Block 6\nsstore(514, 2)\l\ +// "]; +// Block1_6 -> Block1_6Exit [arrowhead=none]; +// Block1_6Exit [label="Jump" shape=oval]; +// Block1_6Exit -> Block1_4; +// Block1_7 [label="\ +// Block 7\nv13 := eq(1, v6)\l\ +// "]; +// Block1_7 -> Block1_7Exit; +// Block1_7Exit [label="{ If v13| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit:0 -> Block1_10; +// Block1_7Exit:1 -> Block1_9; +// Block1_9 [label="\ +// Block 9\nsstore(1028, 4)\l\ +// "]; +// Block1_9Exit [label="FunctionReturn[v17]"]; +// Block1_9 -> Block1_9Exit; +// Block1_10 [label="\ +// Block 10\nv20 := eq(2, v6)\l\ +// "]; +// Block1_10 -> Block1_10Exit; +// Block1_10Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit:0 -> Block1_13; +// Block1_10Exit:1 -> Block1_12; +// Block1_12 [label="\ +// Block 12\nsstore(1542, 6)\l\ +// revert(0, 0)\l\ +// "]; +// Block1_12Exit [label="Terminated"]; +// Block1_12 -> Block1_12Exit; +// Block1_13 [label="\ +// Block 13\nv25 := eq(3, v6)\l\ +// "]; +// Block1_13 -> Block1_13Exit; +// Block1_13Exit [label="{ If v25| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit:0 -> Block1_16; +// Block1_13Exit:1 -> Block1_15; +// Block1_15 [label="\ +// Block 15\nsstore(2056, 8)\l\ +// "]; +// Block1_15 -> Block1_15Exit [arrowhead=none]; +// Block1_15Exit [label="Jump" shape=oval]; +// Block1_15Exit -> Block1_5; +// Block1_16 [label="\ +// Block 16\nv29 := mload(v1)\l\ +// "]; +// Block1_16 -> Block1_16Exit; +// Block1_16Exit [label="{ If v29| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit:0 -> Block1_18; +// Block1_16Exit:1 -> Block1_17; +// Block1_5 [label="\ +// Block 5\nsstore(2827, 11)\l\ +// "]; +// Block1_5 -> Block1_5Exit [arrowhead=none]; +// Block1_5Exit [label="Jump" shape=oval]; +// Block1_5Exit -> Block1_3; +// Block1_17 [label="\ +// Block 17\nreturn(0, 0)\l\ +// "]; +// Block1_17Exit [label="Terminated"]; +// Block1_17 -> Block1_17Exit; +// Block1_18 [label="\ +// Block 18\nsstore(2570, 10)\l\ +// "]; +// Block1_18 -> Block1_18Exit [arrowhead=none]; +// Block1_18Exit [label="Jump" shape=oval]; +// Block1_18Exit -> Block1_5; +// Block1_3 [label="\ +// Block 3\nv43 := add(1, v4)\l\ +// v44 := calldataload(v43)\l\ +// "]; +// Block1_3 -> Block1_3Exit; +// Block1_3Exit [label="{ If v44| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit:0 -> Block1_21; +// Block1_3Exit:1 -> Block1_20; +// Block1_20 [label="\ +// Block 20\nsstore(v43, 0)\l\ +// "]; +// Block1_20Exit [label="FunctionReturn[v45]"]; +// Block1_20 -> Block1_20Exit; +// Block1_21 [label="\ +// Block 21\nsstore(65535, 255)\l\ +// "]; +// Block1_21 -> Block1_21Exit [arrowhead=none]; +// Block1_21Exit [label="Jump" shape=oval]; +// Block1_21Exit -> Block1_1; +// } diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul new file mode 100644 index 000000000..e7cba5f91 --- /dev/null +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -0,0 +1,195 @@ +{ + function f(a, b) -> c { + for { let x := 42 } lt(x, a) { + x := add(x, 1) + if calldataload(x) + { + sstore(0, x) + leave + sstore(0x01, 0x0101) + } + sstore(0xFF, 0xFFFF) + } + { + switch mload(x) + case 0 { + sstore(0x02, 0x0202) + break + sstore(0x03, 0x0303) + } + case 1 { + sstore(0x04, 0x0404) + leave + sstore(0x05, 0x0505) + } + case 2 { + sstore(0x06, 0x0606) + revert(0, 0) + sstore(0x07, 0x0707) + } + case 3 { + sstore(0x08, 0x0808) + } + default { + if mload(b) { + return(0, 0) + sstore(0x09, 0x0909) + } + sstore(0x0A, 0x0A0A) + } + sstore(0x0B, 0x0B0B) + } + sstore(0x0C, 0x0C0C) + c:=27 + } + sstore(0x1,0x1) + pop(f(1,2)) + let z:= add(5,sload(0)) + let w := f(z,sload(4)) + sstore(z,w) + let x := f(w,sload(5)) + sstore(0x1,x) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans" ] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry0 [label="Entry"]; +// Entry0 -> Block0_0; +// Block0_0 [label="\ +// Block 0\nsstore(1, 1)\l\ +// v2 := f(2, 1)\l\ +// pop(v2)\l\ +// v4 := sload(0)\l\ +// v6 := add(v4, 5)\l\ +// v8 := sload(4)\l\ +// v9 := f(v8, v6)\l\ +// sstore(v9, v6)\l\ +// v10 := sload(5)\l\ +// v11 := f(v10, v9)\l\ +// sstore(v11, 1)\l\ +// "]; +// Block0_0Exit [label="MainExit"]; +// Block0_0 -> Block0_0Exit; +// FunctionEntry_f_0 [label="function f: +// c := f(v0, v1)"]; +// FunctionEntry_f_0 -> Block1_0; +// Block1_0 [label="\ +// Block 0\n"]; +// Block1_0 -> Block1_0Exit [arrowhead=none]; +// Block1_0Exit [label="Jump" shape=oval]; +// Block1_0Exit -> Block1_1; +// Block1_1 [label="\ +// Block 1\nv4 := φ(\l\ +// Block 0 => 42,\l\ +// Block 21 => v43\l\ +// )\l\ +// v5 := lt(v0, v4)\l\ +// "]; +// Block1_1 -> Block1_1Exit; +// Block1_1Exit [label="{ If v5| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit:0 -> Block1_4; +// Block1_1Exit:1 -> Block1_2; +// Block1_2 [label="\ +// Block 2\nv6 := mload(v4)\l\ +// v7 := eq(0, v6)\l\ +// "]; +// Block1_2 -> Block1_2Exit; +// Block1_2Exit [label="{ If v7| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit:0 -> Block1_7; +// Block1_2Exit:1 -> Block1_6; +// Block1_4 [label="\ +// Block 4\nsstore(3084, 12)\l\ +// "]; +// Block1_4Exit [label="FunctionReturn[27]"]; +// Block1_4 -> Block1_4Exit; +// Block1_6 [label="\ +// Block 6\nsstore(514, 2)\l\ +// "]; +// Block1_6 -> Block1_6Exit [arrowhead=none]; +// Block1_6Exit [label="Jump" shape=oval]; +// Block1_6Exit -> Block1_4; +// Block1_7 [label="\ +// Block 7\nv13 := eq(1, v6)\l\ +// "]; +// Block1_7 -> Block1_7Exit; +// Block1_7Exit [label="{ If v13| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit:0 -> Block1_10; +// Block1_7Exit:1 -> Block1_9; +// Block1_9 [label="\ +// Block 9\nsstore(1028, 4)\l\ +// "]; +// Block1_9Exit [label="FunctionReturn[v17]"]; +// Block1_9 -> Block1_9Exit; +// Block1_10 [label="\ +// Block 10\nv20 := eq(2, v6)\l\ +// "]; +// Block1_10 -> Block1_10Exit; +// Block1_10Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit:0 -> Block1_13; +// Block1_10Exit:1 -> Block1_12; +// Block1_12 [label="\ +// Block 12\nsstore(1542, 6)\l\ +// revert(0, 0)\l\ +// "]; +// Block1_12Exit [label="Terminated"]; +// Block1_12 -> Block1_12Exit; +// Block1_13 [label="\ +// Block 13\nv25 := eq(3, v6)\l\ +// "]; +// Block1_13 -> Block1_13Exit; +// Block1_13Exit [label="{ If v25| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit:0 -> Block1_16; +// Block1_13Exit:1 -> Block1_15; +// Block1_15 [label="\ +// Block 15\nsstore(2056, 8)\l\ +// "]; +// Block1_15 -> Block1_15Exit [arrowhead=none]; +// Block1_15Exit [label="Jump" shape=oval]; +// Block1_15Exit -> Block1_5; +// Block1_16 [label="\ +// Block 16\nv29 := mload(v1)\l\ +// "]; +// Block1_16 -> Block1_16Exit; +// Block1_16Exit [label="{ If v29| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit:0 -> Block1_18; +// Block1_16Exit:1 -> Block1_17; +// Block1_5 [label="\ +// Block 5\nsstore(2827, 11)\l\ +// "]; +// Block1_5 -> Block1_5Exit [arrowhead=none]; +// Block1_5Exit [label="Jump" shape=oval]; +// Block1_5Exit -> Block1_3; +// Block1_17 [label="\ +// Block 17\nreturn(0, 0)\l\ +// "]; +// Block1_17Exit [label="Terminated"]; +// Block1_17 -> Block1_17Exit; +// Block1_18 [label="\ +// Block 18\nsstore(2570, 10)\l\ +// "]; +// Block1_18 -> Block1_18Exit [arrowhead=none]; +// Block1_18Exit [label="Jump" shape=oval]; +// Block1_18Exit -> Block1_5; +// Block1_3 [label="\ +// Block 3\nv43 := add(1, v4)\l\ +// v44 := calldataload(v43)\l\ +// "]; +// Block1_3 -> Block1_3Exit; +// Block1_3Exit [label="{ If v44| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit:0 -> Block1_21; +// Block1_3Exit:1 -> Block1_20; +// Block1_20 [label="\ +// Block 20\nsstore(v43, 0)\l\ +// "]; +// Block1_20Exit [label="FunctionReturn[v45]"]; +// Block1_20 -> Block1_20Exit; +// Block1_21 [label="\ +// Block 21\nsstore(65535, 255)\l\ +// "]; +// Block1_21 -> Block1_21Exit [arrowhead=none]; +// Block1_21Exit [label="Jump" shape=oval]; +// Block1_21Exit -> Block1_1; +// } diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/yulSSAControlFlowGraph/function.yul new file mode 100644 index 000000000..11eb1ac6c --- /dev/null +++ b/test/libyul/yulSSAControlFlowGraph/function.yul @@ -0,0 +1,68 @@ +{ + function f(a, b) -> r { + let x := add(a,b) + r := sub(x,a) + } + function g() { + sstore(0x01, 0x0101) + } + function h(x) { + h(f(x, 0)) + g() + } + function i() -> v, w { + v := 0x0202 + w := 0x0303 + } + let x, y := i() + h(x) + h(y) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans" ] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry0 [label="Entry"]; +// Entry0 -> Block0_0; +// Block0_0 [label="\ +// Block 0\nv0, v1 := i()\l\ +// h(v0)\l\ +// h(v1)\l\ +// "]; +// Block0_0Exit [label="MainExit"]; +// Block0_0 -> Block0_0Exit; +// FunctionEntry_f_0 [label="function f: +// r := f(v0, v1)"]; +// FunctionEntry_f_0 -> Block1_0; +// Block1_0 [label="\ +// Block 0\nv2 := add(v1, v0)\l\ +// v3 := sub(v0, v2)\l\ +// "]; +// Block1_0Exit [label="FunctionReturn[v3]"]; +// Block1_0 -> Block1_0Exit; +// FunctionEntry_g_0 [label="function g: +// g()"]; +// FunctionEntry_g_0 -> Block2_0; +// Block2_0 [label="\ +// Block 0\nsstore(257, 1)\l\ +// "]; +// Block2_0Exit [label="FunctionReturn[]"]; +// Block2_0 -> Block2_0Exit; +// FunctionEntry_h_0 [label="function h: +// h(v0)"]; +// FunctionEntry_h_0 -> Block3_0; +// Block3_0 [label="\ +// Block 0\nv2 := f(0, v0)\l\ +// "]; +// Block3_0Exit [label="Terminated"]; +// Block3_0 -> Block3_0Exit; +// FunctionEntry_i_0 [label="function i: +// v, w := i()"]; +// FunctionEntry_i_0 -> Block4_0; +// Block4_0 [label="\ +// Block 0\n"]; +// Block4_0Exit [label="FunctionReturn[514, 771]"]; +// Block4_0 -> Block4_0Exit; +// } diff --git a/test/libyul/yulSSAControlFlowGraph/if.yul b/test/libyul/yulSSAControlFlowGraph/if.yul new file mode 100644 index 000000000..6a47ec283 --- /dev/null +++ b/test/libyul/yulSSAControlFlowGraph/if.yul @@ -0,0 +1,40 @@ +{ + let x := calldataload(3) + if 0 { + x := calldataload(77) + } + let y := calldataload(x) + sstore(y, 0) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans" ] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry0 [label="Entry"]; +// Entry0 -> Block0_0; +// Block0_0 [label="\ +// Block 0\nv1 := calldataload(3)\l\ +// "]; +// Block0_0 -> Block0_0Exit; +// Block0_0Exit [label="{ If 0| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit:0 -> Block0_2; +// Block0_0Exit:1 -> Block0_1; +// Block0_1 [label="\ +// Block 1\nv4 := calldataload(77)\l\ +// "]; +// Block0_1 -> Block0_1Exit [arrowhead=none]; +// Block0_1Exit [label="Jump" shape=oval]; +// Block0_1Exit -> Block0_2; +// Block0_2 [label="\ +// Block 2\nv5 := φ(\l\ +// Block 0 => v1,\l\ +// Block 1 => v4\l\ +// )\l\ +// v6 := calldataload(v5)\l\ +// sstore(0, v6)\l\ +// "]; +// Block0_2Exit [label="MainExit"]; +// Block0_2 -> Block0_2Exit; +// } diff --git a/test/libyul/yulSSAControlFlowGraph/switch.yul b/test/libyul/yulSSAControlFlowGraph/switch.yul new file mode 100644 index 000000000..e0a24dac1 --- /dev/null +++ b/test/libyul/yulSSAControlFlowGraph/switch.yul @@ -0,0 +1,68 @@ +{ + let x := calldataload(3) + + switch sload(0) + case 0 { + x := calldataload(77) + } + case 1 { + x := calldataload(88) + } + default { + x := calldataload(99) + } + sstore(x, 0) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans" ] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry0 [label="Entry"]; +// Entry0 -> Block0_0; +// Block0_0 [label="\ +// Block 0\nv1 := calldataload(3)\l\ +// v3 := sload(0)\l\ +// v4 := eq(0, v3)\l\ +// "]; +// Block0_0 -> Block0_0Exit; +// Block0_0Exit [label="{ If v4| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit:0 -> Block0_3; +// Block0_0Exit:1 -> Block0_2; +// Block0_2 [label="\ +// Block 2\nv6 := calldataload(77)\l\ +// "]; +// Block0_2 -> Block0_2Exit [arrowhead=none]; +// Block0_2Exit [label="Jump" shape=oval]; +// Block0_2Exit -> Block0_1; +// Block0_3 [label="\ +// Block 3\nv7 := eq(1, v3)\l\ +// "]; +// Block0_3 -> Block0_3Exit; +// Block0_3Exit [label="{ If v7| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_3Exit:0 -> Block0_5; +// Block0_3Exit:1 -> Block0_4; +// Block0_1 [label="\ +// Block 1\nv13 := φ(\l\ +// Block 2 => v6,\l\ +// Block 4 => v10,\l\ +// Block 5 => v12\l\ +// )\l\ +// sstore(0, v13)\l\ +// "]; +// Block0_1Exit [label="MainExit"]; +// Block0_1 -> Block0_1Exit; +// Block0_4 [label="\ +// Block 4\nv10 := calldataload(88)\l\ +// "]; +// Block0_4 -> Block0_4Exit [arrowhead=none]; +// Block0_4Exit [label="Jump" shape=oval]; +// Block0_4Exit -> Block0_1; +// Block0_5 [label="\ +// Block 5\nv12 := calldataload(99)\l\ +// "]; +// Block0_5 -> Block0_5Exit [arrowhead=none]; +// Block0_5Exit [label="Jump" shape=oval]; +// Block0_5Exit -> Block0_1; +// } From 7d87b63991e26dc4a5f2dd78ea8709efd3569506 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:22:30 +0200 Subject: [PATCH 0288/1340] Yul: Dot output of SSA CFG --- libyul/backends/evm/SSAControlFlowGraph.h | 4 +- .../evm/SSAControlFlowGraphBuilder.cpp | 8 - test/CMakeLists.txt | 2 + test/InteractiveTests.h | 2 + test/libyul/ControlFlowGraphTest.cpp | 1 - test/libyul/SSAControlFlowGraphTest.cpp | 318 ++++++++++++++++++ test/libyul/SSAControlFlowGraphTest.h | 42 +++ .../libyul/yulSSAControlFlowGraph/complex.yul | 2 +- .../yulSSAControlFlowGraph/complex2.yul | 2 +- .../yulSSAControlFlowGraph/function.yul | 2 +- test/libyul/yulSSAControlFlowGraph/if.yul | 2 +- test/libyul/yulSSAControlFlowGraph/switch.yul | 2 +- test/tools/CMakeLists.txt | 1 + 13 files changed, 372 insertions(+), 16 deletions(-) create mode 100644 test/libyul/SSAControlFlowGraphTest.cpp create mode 100644 test/libyul/SSAControlFlowGraphTest.h diff --git a/libyul/backends/evm/SSAControlFlowGraph.h b/libyul/backends/evm/SSAControlFlowGraph.h index 311d23e87..f4d0ec242 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.h +++ b/libyul/backends/evm/SSAControlFlowGraph.h @@ -117,7 +117,7 @@ class SSACFG std::vector operations; std::variant exit = MainExit{}; template - void forEachExit(Callable&& _callable) + void forEachExit(Callable&& _callable) const { if (auto* jump = std::get_if(&exit)) _callable(jump->target); @@ -194,7 +194,7 @@ class SSACFG } ValueId newLiteral(langutil::DebugData::ConstPtr _debugData, u256 _value) { - auto [it, inserted] = m_literals.emplace(_value, ValueId{m_valueInfos.size()}); + auto [it, inserted] = m_literals.emplace(_value, SSACFG::ValueId{m_valueInfos.size()}); if (inserted) m_valueInfos.emplace_back(LiteralValue{std::move(_debugData), _value}); else diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 18720e9bc..d9dc7663c 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -176,14 +176,6 @@ void cleanUnreachable(SSACFG& _cfg) { auto& block = _cfg.block(blockId); - for (auto phi: block.phis) - { - auto& phiValue = std::get(_cfg.valueInfo(phi)); - yulAssert(block.entries.size() == phiValue.arguments.size()); - for (auto&& [entry, arg]: ranges::zip_view(block.entries, phiValue.arguments)) - yulAssert((reachabilityCheck.visited.count(entry) == 0) == isUnreachableValue(arg)); - } - std::set maybeTrivialPhi; for (auto it = block.entries.begin(); it != block.entries.end();) if (reachabilityCheck.visited.count(*it)) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5308a55f7..d3498965d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -153,6 +153,8 @@ set(libyul_sources libyul/ObjectCompilerTest.h libyul/ObjectParser.cpp libyul/Parser.cpp + libyul/SSAControlFlowGraphTest.cpp + libyul/SSAControlFlowGraphTest.h libyul/StackLayoutGeneratorTest.cpp libyul/StackLayoutGeneratorTest.h libyul/StackShufflingTest.cpp diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index 4c2077576..e043fcdbe 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,7 @@ Testsuite const g_interactiveTestsuites[] = { {"Yul Interpreter", "libyul", "yulInterpreterTests", false, false, &yul::test::YulInterpreterTest::create}, {"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create}, {"Yul Control Flow Graph", "libyul", "yulControlFlowGraph", false, false, &yul::test::ControlFlowGraphTest::create}, + {"Yul SSA Control Flow Graph", "libyul", "yulSSAControlFlowGraph", false, false, &yul::test::SSAControlFlowGraphTest::create}, {"Yul Stack Layout", "libyul", "yulStackLayout", false, false, &yul::test::StackLayoutGeneratorTest::create}, {"Yul Stack Shuffling", "libyul", "yulStackShuffling", false, false, &yul::test::StackShufflingTest::create}, {"Control Flow Side Effects", "libyul", "controlFlowSideEffects", false, false, &yul::test::ControlFlowSideEffectsTest::create}, diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index 5c9bba8d4..0060b850e 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -130,7 +130,6 @@ class ControlFlowGraphPrinter }, [&](CFG::BuiltinCall const& _call) { m_stream << _call.functionCall.get().functionName.name.str() << ": "; - }, [&](CFG::Assignment const& _assignment) { m_stream << "Assignment("; diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/SSAControlFlowGraphTest.cpp new file mode 100644 index 000000000..e12751411 --- /dev/null +++ b/test/libyul/SSAControlFlowGraphTest.cpp @@ -0,0 +1,318 @@ +/* + 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 + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtautological-compare" +#include +#pragma GCC diagnostic pop + +#ifdef ISOLTEST +#include +#endif + +using namespace solidity; +using namespace solidity::util; +using namespace solidity::langutil; +using namespace solidity::yul; +using namespace solidity::yul::test; +using namespace solidity::frontend; +using namespace solidity::frontend::test; + +std::unique_ptr SSAControlFlowGraphTest::create(TestCase::Config const& _config) { + return std::make_unique(_config.filename); +} + +SSAControlFlowGraphTest::SSAControlFlowGraphTest(std::string const& _filename): TestCase(_filename) +{ + m_source = m_reader.source(); + auto dialectName = m_reader.stringSetting("dialect", "evm"); + m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); + m_expectation = m_reader.simpleExpectations(); +} + +class SSACFGPrinter +{ +public: + SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId) + { + printBlock(_cfg, _blockId, 0); + } + SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function) + { + printFunction(_cfg, _functionIndex, _function); + } + friend std::ostream& operator<<(std::ostream& stream, SSACFGPrinter const& printer) { + stream << printer.m_result.str(); + return stream; + } +private: + std::string varToString(SSACFG const& _cfg, SSACFG::ValueId _var) { + if (_var.value == std::numeric_limits::max()) + return "INVALID"; + auto const& info = _cfg.valueInfo(_var); + return std::visit( + util::GenericVisitor{ + [&](SSACFG::UnreachableValue const&) -> std::string { + return "[unreachable]"; + }, + [&](SSACFG::PhiValue const&) -> std::string { + return fmt::format("v{}", _var.value); + }, + [&](SSACFG::VariableValue const&) -> std::string { + return fmt::format("v{}", _var.value); + }, + [&](SSACFG::LiteralValue const& _literal) -> std::string { + return util::formatNumberReadable(_literal.value); + } + }, + info + ); + } + + std::string formatPhi(SSACFG const& _cfg, SSACFG::PhiValue const& _phiValue) + { + auto const transform = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; + std::vector formattedArgs; + formattedArgs.reserve(_phiValue.arguments.size()); + for(auto const& [arg, entry] : ranges::zip_view(_phiValue.arguments | ranges::views::transform(transform), _cfg.block(_phiValue.block).entries)) + { + formattedArgs.push_back(fmt::format("Block {} => {}", entry.value, arg)); + } + return fmt::format("φ(\\l\\\n\t{}\\l\\\n)", fmt::join(formattedArgs, ",\\l\\\n\t")); + } + + void writeBlock(SSACFG const& _cfg, SSACFG::BlockId const& _id, SSACFG::BasicBlock const& _block, size_t _functionIndex) + { + auto const transform = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; + bool entryBlock = _id.value == 0 && _functionIndex == 0; + if (entryBlock) + { + m_result << fmt::format("Entry{} [label=\"Entry\"];\n", _functionIndex); + m_result << fmt::format("Entry{} -> Block{}_{};\n", _functionIndex, _functionIndex, _id.value); + } + { + m_result << fmt::format("Block{1}_{0} [label=\"\\\nBlock {0}\\n", _id.value, _functionIndex); + for (auto const& phi : _block.phis) + { + auto const* phiValue = std::get_if(&_cfg.valueInfo(phi)); + solAssert(phiValue); + m_result << fmt::format("v{} := {}\\l\\\n", phi.value, formatPhi(_cfg, *phiValue)); + } + for (auto const& operation : _block.operations) + { + std::string const label = std::visit(util::GenericVisitor{ + [&](SSACFG::Call const& _call) { + return _call.function.get().name.str(); + }, + [&](SSACFG::BuiltinCall const& _call) { + return _call.builtin.get().name.str(); + }, + }, operation.kind); + if (operation.outputs.empty()) + m_result << fmt::format( + "{}({})\\l\\\n", + label, + fmt::join(operation.inputs | ranges::views::transform(transform), ", ") + ); + else + m_result << fmt::format( + "{} := {}({})\\l\\\n", + fmt::join(operation.outputs | ranges::views::transform(transform), ", "), + label, + fmt::join(operation.inputs | ranges::views::transform(transform), ", ") + ); + } + m_result << "\"];\n"; + std::visit(util::GenericVisitor{ + [&](SSACFG::BasicBlock::MainExit const&) + { + m_result << fmt::format("Block{}_{}Exit [label=\"MainExit\"];\n", _functionIndex, _id.value); + m_result << fmt::format("Block{1}_{0} -> Block{1}_{0}Exit;\n", _id.value, _functionIndex); + }, + [&](SSACFG::BasicBlock::Jump const& _jump) + { + m_result << fmt::format("Block{1}_{0} -> Block{1}_{0}Exit [arrowhead=none];\n", _id.value, _functionIndex); + m_result << fmt::format("Block{}_{}Exit [label=\"Jump\" shape=oval];\n", _functionIndex, _id.value); + m_result << fmt::format("Block{}_{}Exit -> Block{}_{};\n", _functionIndex, _id.value, _functionIndex, _jump.target.value); + }, + [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) + { + m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"{ If "; + m_result << varToString(_cfg, _conditionalJump.condition); + m_result << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; + m_result << "Block" << _functionIndex << "_" << _id.value; + m_result << "Exit:0 -> Block" << _functionIndex << "_" << _conditionalJump.zero.value << ";\n"; + m_result << "Block" << _functionIndex << "_" << _id.value; + m_result << "Exit:1 -> Block" << _functionIndex << "_" << _conditionalJump.nonZero.value << ";\n"; + }, + [&](SSACFG::BasicBlock::JumpTable const& jt) + { + m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + std::string options; + for(const auto& jumpCase : jt.cases) + { + if (!options.empty()) + options += " | "; + options += fmt::format("<{0}> {0}", formatNumber(jumpCase.first)); + } + if (!options.empty()) + options += " | "; + options += " default"; + m_result << fmt::format("Block{}_{}Exit [label=\"{{ JT | {{ {} }} }}\" shape=Mrecord];\n", _functionIndex, _id.value, options); + for(const auto& jumpCase : jt.cases) + { + m_result << fmt::format("Block{}_{}Exit:{} -> Block{}_{};\n", _functionIndex, _id.value, formatNumber(jumpCase.first), _functionIndex, jumpCase.second.value); + } + m_result << fmt::format("Block{}_{}Exit:default -> Block{}_{};\n", _functionIndex, _id.value, _functionIndex, jt.defaultCase.value); + }, + [&](SSACFG::BasicBlock::FunctionReturn const& fr) + { + m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"FunctionReturn[" + << fmt::format("{}", fmt::join(fr.returnValues | ranges::views::transform(transform), ", ")) + << "]\"];\n"; + m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + }, + [&](SSACFG::BasicBlock::Terminated const&) + { + m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"Terminated\"];\n"; + m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + } + }, _block.exit); + } + + } + + void printBlock(SSACFG const& _cfg, SSACFG::BlockId const& _rootId, size_t _functionIndex) + { + std::set explored{}; + explored.insert(_rootId); + + std::deque toVisit{}; + toVisit.emplace_back(_rootId); + + while(!toVisit.empty()) + { + auto const id = toVisit.front(); + toVisit.pop_front(); + auto const& block = _cfg.block(id); + writeBlock(_cfg, id, block, _functionIndex); + block.forEachExit( + [&](SSACFG::BlockId const& _exitBlock) + { + if (explored.count(_exitBlock) == 0) + { + explored.insert(_exitBlock); + toVisit.emplace_back(_exitBlock); + } + } + ); + } + } + + void printFunction(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _fun) + { + static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return functionReturnValue.get().name.str(); }; + static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", std::get<1>(arg).value); }; + m_result << "FunctionEntry_" << _fun.name.str() << "_" << _cfg.entry.value << " [label=\""; + if (!_cfg.returns.empty()) + m_result << fmt::format("function {0}:\n {1} := {0}({2})", _fun.name.str(), fmt::join(_cfg.returns | ranges::views::transform(returnsTransform), ", "), fmt::join(_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + else + m_result << fmt::format("function {0}:\n {0}({1})", _fun.name.str(), fmt::join(_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + m_result << "\"];\n"; + m_result << "FunctionEntry_" << _fun.name.str() << "_" << _cfg.entry.value << " -> Block" << _functionIndex << "_" << _cfg.entry.value << ";\n"; + printBlock(_cfg, _cfg.entry, _functionIndex); + } + + std::stringstream m_result{}; +}; + +TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) +{ + ErrorList errors; + auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); + if (!object || !analysisInfo || Error::containsErrors(errors)) + { + AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; + return TestResult::FatalError; + } + + std::ostringstream output; + + auto info = AsmAnalyzer::analyzeStrictAssertCorrect(*m_dialect, *object); + std::unique_ptr controlFlow = SSAControlFlowGraphBuilder::build( + info, + *m_dialect, + object->code()->root() + ); + + output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; + output << SSACFGPrinter(*controlFlow->mainGraph, SSACFG::BlockId{0}); + size_t index = 1; + for (auto const& [function, functionGraph]: controlFlow->functionGraphMapping) + output << SSACFGPrinter(*functionGraph, index++, *function); + output << "}\n"; + + m_obtainedResult = output.str(); + + auto result = checkResult(_stream, _linePrefix, _formatted); + +#ifdef ISOLTEST + char* graphDisplayer = nullptr; + // The environment variables specify an optional command that will receive the graph encoded in DOT through stdin. + // Examples for suitable commands are ``dot -Tx11:cairo`` or ``xdot -``. + if (result == TestResult::Failure) + // ISOLTEST_DISPLAY_GRAPHS_ON_FAILURE_COMMAND will run on all failing tests (intended for use during modifications). + graphDisplayer = getenv("ISOLTEST_DISPLAY_GRAPHS_ON_FAILURE_COMMAND"); + else if (result == TestResult::Success) + // ISOLTEST_DISPLAY_GRAPHS_ON_FAILURE_COMMAND will run on all succeeding tests (intended for use during reviews). + graphDisplayer = getenv("ISOLTEST_DISPLAY_GRAPHS_ON_SUCCESS_COMMAND"); + + if (graphDisplayer) + { + if (result == TestResult::Success) + std::cout << std::endl << m_source << std::endl; + boost::process::opstream pipe; + boost::process::child child(graphDisplayer, boost::process::std_in < pipe); + + pipe << output.str(); + pipe.flush(); + pipe.pipe().close(); + if (result == TestResult::Success) + child.wait(); + else + child.detach(); + } +#endif + + return result; + +} diff --git a/test/libyul/SSAControlFlowGraphTest.h b/test/libyul/SSAControlFlowGraphTest.h new file mode 100644 index 000000000..f976be03c --- /dev/null +++ b/test/libyul/SSAControlFlowGraphTest.h @@ -0,0 +1,42 @@ +/* +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 + +#pragma once + +#include + +#include + +namespace solidity::yul +{ +struct Dialect; + +namespace test +{ + +class SSAControlFlowGraphTest: public solidity::frontend::test::TestCase +{ +public: + static std::unique_ptr create(Config const& _config); + explicit SSAControlFlowGraphTest(std::string const& _filename); + TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; +private: + Dialect const* m_dialect = nullptr; +}; +} +} diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index 042b313af..d7e16c9f6 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -46,7 +46,7 @@ // ---- // digraph SSACFG { // nodesep=0.7; -// graph[fontname="DejaVu Sans" ] +// graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // // Entry0 [label="Entry"]; diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index e7cba5f91..863b021d1 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -53,7 +53,7 @@ // ---- // digraph SSACFG { // nodesep=0.7; -// graph[fontname="DejaVu Sans" ] +// graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // // Entry0 [label="Entry"]; diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/yulSSAControlFlowGraph/function.yul index 11eb1ac6c..aa4b6ac97 100644 --- a/test/libyul/yulSSAControlFlowGraph/function.yul +++ b/test/libyul/yulSSAControlFlowGraph/function.yul @@ -21,7 +21,7 @@ // ---- // digraph SSACFG { // nodesep=0.7; -// graph[fontname="DejaVu Sans" ] +// graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // // Entry0 [label="Entry"]; diff --git a/test/libyul/yulSSAControlFlowGraph/if.yul b/test/libyul/yulSSAControlFlowGraph/if.yul index 6a47ec283..9045d8034 100644 --- a/test/libyul/yulSSAControlFlowGraph/if.yul +++ b/test/libyul/yulSSAControlFlowGraph/if.yul @@ -9,7 +9,7 @@ // ---- // digraph SSACFG { // nodesep=0.7; -// graph[fontname="DejaVu Sans" ] +// graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // // Entry0 [label="Entry"]; diff --git a/test/libyul/yulSSAControlFlowGraph/switch.yul b/test/libyul/yulSSAControlFlowGraph/switch.yul index e0a24dac1..f6c084b00 100644 --- a/test/libyul/yulSSAControlFlowGraph/switch.yul +++ b/test/libyul/yulSSAControlFlowGraph/switch.yul @@ -16,7 +16,7 @@ // ---- // digraph SSACFG { // nodesep=0.7; -// graph[fontname="DejaVu Sans" ] +// graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // // Entry0 [label="Entry"]; diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 44a5e2aa7..5c1d41b7f 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -40,6 +40,7 @@ add_executable(isoltest ../libsolidity/SMTCheckerTest.cpp ../libyul/Common.cpp ../libyul/ControlFlowGraphTest.cpp + ../libyul/SSAControlFlowGraphTest.cpp ../libyul/ControlFlowSideEffectsTest.cpp ../libyul/EVMCodeTransformTest.cpp ../libyul/FunctionSideEffects.cpp From 80533d806b0755dd2fa288af73a1bac35d8ec895 Mon Sep 17 00:00:00 2001 From: r0qs Date: Fri, 31 May 2024 13:50:04 +0200 Subject: [PATCH 0289/1340] Convert Yul CFG to Json --- libsolidity/interface/CompilerStack.cpp | 11 ++ libsolidity/interface/CompilerStack.h | 3 + libsolidity/interface/StandardCompiler.cpp | 13 +- libyul/CMakeLists.txt | 2 + libyul/YulControlFlowGraphExporter.cpp | 212 +++++++++++++++++++++ libyul/YulControlFlowGraphExporter.h | 42 ++++ libyul/YulStack.cpp | 41 ++++ libyul/YulStack.h | 3 + solc/CommandLineInterface.cpp | 32 +++- solc/CommandLineInterface.h | 1 + solc/CommandLineParser.cpp | 2 + solc/CommandLineParser.h | 2 + test/solc/CommandLineParser.cpp | 3 +- 13 files changed, 362 insertions(+), 5 deletions(-) create mode 100644 libyul/YulControlFlowGraphExporter.cpp create mode 100644 libyul/YulControlFlowGraphExporter.h diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 1f432db40..ce9525c2b 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -924,6 +924,16 @@ Json const& CompilerStack::yulIRAst(std::string const& _contractName) const return contract(_contractName).yulIRAst; } +Json const& CompilerStack::yulCFGJson(std::string const& _contractName) const +{ + if (m_stackState != CompilationSuccessful) + solThrow(CompilerError, "Compilation was not successful."); + + solUnimplementedAssert(!isExperimentalSolidity()); + + return contract(_contractName).yulCFGJson; +} + std::string const& CompilerStack::yulIROptimized(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); @@ -1506,6 +1516,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti ); compiledContract.yulIRAst = stack.astJson(); + compiledContract.yulCFGJson = stack.cfgJson(); if (!_unoptimizedOnly) { stack.optimize(); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 25863b6d0..0a62cbf7e 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -298,6 +298,8 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// @returns the optimized IR representation of a contract AST in JSON format. Json const& yulIROptimizedAst(std::string const& _contractName) const; + Json const& yulCFGJson(std::string const& _contractName) const; + /// @returns the assembled object for a contract. virtual evmasm::LinkerObject const& object(std::string const& _contractName) const override; @@ -411,6 +413,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac std::string yulIROptimized; ///< Reparsed and possibly optimized Yul IR code. Json yulIRAst; ///< JSON AST of Yul IR code. Json yulIROptimizedAst; ///< JSON AST of optimized Yul IR code. + Json yulCFGJson; ///< JSON CFG of Yul IR code. util::LazyInit metadata; ///< The metadata json that will be hashed into the chain. util::LazyInit abi; util::LazyInit storageLayout; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 0c1ccb6b7..385e48c22 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -180,7 +180,7 @@ bool hashMatchesContent(std::string const& _hash, std::string const& _content) bool isArtifactRequested(Json const& _outputSelection, std::string const& _artifact, bool _wildcardMatchesExperimental) { - static std::set experimental{"ir", "irAst", "irOptimized", "irOptimizedAst"}; + static std::set experimental{"ir", "irAst", "irOptimized", "irOptimizedAst", "yulCFGJson"}; for (auto const& selectedArtifactJson: _outputSelection) { std::string const& selectedArtifact = selectedArtifactJson.get(); @@ -191,6 +191,9 @@ bool isArtifactRequested(Json const& _outputSelection, std::string const& _artif return true; else if (selectedArtifact == "*") { + // TODO: yulCFGJson is only experimental now, so it should not be matched by "*". + if (_artifact == "yulCFGJson") + return false; // "ir", "irOptimized" can only be matched by "*" if activated. if (experimental.count(_artifact) == 0 || _wildcardMatchesExperimental) return true; @@ -264,7 +267,7 @@ bool isBinaryRequested(Json const& _outputSelection) // This does not include "evm.methodIdentifiers" on purpose! static std::vector const outputsThatRequireBinaries = std::vector{ "*", - "ir", "irAst", "irOptimized", "irOptimizedAst", + "ir", "irAst", "irOptimized", "irOptimizedAst", "yulCFGJson", "evm.gasEstimates", "evm.legacyAssembly", "evm.assembly" } + evmObjectComponents("bytecode") + evmObjectComponents("deployedBytecode"); @@ -307,7 +310,7 @@ CompilerStack::IROutputSelection irOutputSelection(Json const& _outputSelection) for (auto const& requests: fileRequests) for (auto const& request: requests) { - if (request == "irOptimized" || request == "irOptimizedAst") + if (request == "irOptimized" || request == "irOptimizedAst" || request == "yulCFGJson") return CompilerStack::IROutputSelection::UnoptimizedAndOptimized; if (request == "ir" || request == "irAst") @@ -1485,6 +1488,8 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu contractData["irOptimized"] = compilerStack.yulIROptimized(contractName); if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "irOptimizedAst", wildcardMatchesExperimental)) contractData["irOptimizedAst"] = compilerStack.yulIROptimizedAst(contractName); + if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "yulCFGJson", wildcardMatchesExperimental)) + contractData["yulCFGJson"] = compilerStack.yulCFGJson(contractName); // EVM Json evmData; @@ -1698,6 +1703,8 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) output["contracts"][sourceName][contractName]["irOptimized"] = stack.print(); if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "evm.assembly", wildcardMatchesExperimental)) output["contracts"][sourceName][contractName]["evm"]["assembly"] = object.assembly->assemblyString(stack.debugInfoSelection()); + if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "yulCFGJson", wildcardMatchesExperimental)) + output["contracts"][sourceName][contractName]["yulCFGJson"] = stack.cfgJson(); return output; } diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index c54513d9a..c0082f5d6 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -39,6 +39,8 @@ add_library(yul ScopeFiller.h Utilities.cpp Utilities.h + YulControlFlowGraphExporter.h + YulControlFlowGraphExporter.cpp YulName.h YulString.h backends/evm/AbstractAssembly.h diff --git a/libyul/YulControlFlowGraphExporter.cpp b/libyul/YulControlFlowGraphExporter.cpp new file mode 100644 index 000000000..3f347fcf4 --- /dev/null +++ b/libyul/YulControlFlowGraphExporter.cpp @@ -0,0 +1,212 @@ +/* + 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 + +#include +#include + +#include +#include + +#include +#include +#include + +using namespace solidity; +using namespace solidity::langutil; +using namespace solidity::util; +using namespace solidity::yul; + +YulControlFlowGraphExporter::YulControlFlowGraphExporter(ControlFlow const& _controlFlow): m_controlFlow(_controlFlow) +{ +} + +std::string YulControlFlowGraphExporter::varToString(SSACFG const& _cfg, SSACFG::ValueId _var) +{ + if (_var.value == std::numeric_limits::max()) + return std::string("INVALID"); + auto const& info = _cfg.valueInfo(_var); + return std::visit( + util::GenericVisitor{ + [&](SSACFG::UnreachableValue const&) -> std::string { + return "[unreachable]"; + }, + [&](SSACFG::LiteralValue const& _literal) { + return toCompactHexWithPrefix(_literal.value); + }, + [&](auto const&) { + return "v" + std::to_string(_var.value); + } + }, + info + ); +} + +Json YulControlFlowGraphExporter::run() +{ + Json yulObjectJson = Json::object(); + yulObjectJson["blocks"] = exportBlock(*m_controlFlow.mainGraph, SSACFG::BlockId{0}); + + Json functionsJson = Json::object(); + for (auto const& [function, functionGraph]: m_controlFlow.functionGraphMapping) + functionsJson[function->name.str()] = exportFunction(*functionGraph); + yulObjectJson["functions"] = functionsJson; + + return yulObjectJson; +} + +Json YulControlFlowGraphExporter::exportFunction(SSACFG const& _cfg) +{ + Json functionJson = Json::object(); + functionJson["type"] = "Function"; + functionJson["entry"] = "Block" + std::to_string(_cfg.entry.value); + functionJson["arguments"] = Json::array(); + for (auto const& [arg, valueId]: _cfg.arguments) + functionJson["arguments"].emplace_back(arg.get().name.str()); + functionJson["returns"] = Json::array(); + for (auto const& ret: _cfg.returns) + functionJson["returns"].emplace_back(ret.get().name.str()); + functionJson["blocks"] = exportBlock(_cfg, _cfg.entry); + return functionJson; +} + +Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId) +{ + Json blocksJson = Json::array(); + util::BreadthFirstSearch bfs{{{_entryId}}}; + bfs.run([&](SSACFG::BlockId _blockId, auto _addChild) { + auto const& block = _cfg.block(_blockId); + // Convert current block to JSON + Json blockJson = toJson(_cfg, _blockId); + + Json exitBlockJson = Json::object(); + std::visit(util::GenericVisitor{ + [&](SSACFG::BasicBlock::MainExit const&) { + exitBlockJson["targets"] = { "Block" + std::to_string(_blockId.value) }; + exitBlockJson["type"] = "MainExit"; + }, + [&](SSACFG::BasicBlock::Jump const& _jump) + { + exitBlockJson["targets"] = { "Block" + std::to_string(_jump.target.value) }; + exitBlockJson["type"] = "Jump"; + _addChild(_jump.target); + }, + [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) + { + exitBlockJson["targets"] = { "Block" + std::to_string(_conditionalJump.zero.value), "Block" + std::to_string(_conditionalJump.nonZero.value) }; + exitBlockJson["cond"] = varToString(_cfg, _conditionalJump.condition); + exitBlockJson["type"] = "ConditionalJump"; + + _addChild(_conditionalJump.zero); + _addChild(_conditionalJump.nonZero); + }, + [&](SSACFG::BasicBlock::FunctionReturn const& _return) { + exitBlockJson["instructions"] = toJson(_cfg, _return.returnValues); + exitBlockJson["targets"] = { "Block" + std::to_string(_blockId.value) }; + exitBlockJson["type"] = "FunctionReturn"; + }, + [&](SSACFG::BasicBlock::Terminated const&) { + exitBlockJson["targets"] = { "Block" + std::to_string(_blockId.value) }; + exitBlockJson["type"] = "Terminated"; + }, + [&](SSACFG::BasicBlock::JumpTable const&) { + yulAssert(false); + } + }, block.exit); + blockJson["exit"] = exitBlockJson; + blocksJson.emplace_back(blockJson); + }); + + return blocksJson; +} + +Json YulControlFlowGraphExporter::toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId) +{ + Json blockJson = Json::object(); + auto const& block = _cfg.block(_blockId); + + blockJson["id"] = "Block" + std::to_string(_blockId.value); + blockJson["instructions"] = Json::array(); + if (!block.phis.empty()) + { + blockJson["entries"] = block.entries + | ranges::views::transform([](auto const& entry) { return "Block" + std::to_string(entry.value); }) + | ranges::to(); + for (auto const& phi: block.phis) + { + auto* phiInfo = std::get_if(&_cfg.valueInfo(phi)); + yulAssert(phiInfo); + Json phiJson = Json::object(); + phiJson["op"] = "PhiFunction"; + phiJson["in"] = toJson(_cfg, phiInfo->arguments); + phiJson["out"] = toJson(_cfg, std::vector{phi}); + blockJson["instructions"].push_back(phiJson); + } + } + for (auto const& operation: block.operations) + blockJson["instructions"].push_back(toJson(blockJson, _cfg, operation)); + + return blockJson; +} + +Json YulControlFlowGraphExporter::toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation) +{ + Json opJson = Json::object(); + std::visit(util::GenericVisitor{ + [&](SSACFG::Call const& _call) { + _ret["type"] = "FunctionCall"; + opJson["op"] = _call.function.get().name.str(); + }, + [&](SSACFG::BuiltinCall const& _call) { + _ret["type"] = "BuiltinCall"; + Json builtinArgsJson = Json::array(); + auto const& builtin = _call.builtin.get(); + if (!builtin.literalArguments.empty()) + { + auto const& functionCallArgs = _call.call.get().arguments; + for (size_t i = 0; i < builtin.literalArguments.size(); ++i) + { + std::optional const& argument = builtin.literalArguments[i]; + if (argument.has_value() && i < functionCallArgs.size()) + { + // The function call argument at index i must be a literal if builtin.literalArguments[i] is not nullopt + yulAssert(std::holds_alternative(functionCallArgs[i])); + builtinArgsJson.push_back(formatLiteral(std::get(functionCallArgs[i]))); + } + } + } + + if (!builtinArgsJson.empty()) + opJson["builtinArgs"] = builtinArgsJson; + + opJson["op"] = _call.builtin.get().name.str(); + }, + }, _operation.kind); + + opJson["in"] = toJson(_cfg, _operation.inputs); + opJson["out"] = toJson(_cfg, _operation.outputs); + + return opJson; +} + +Json YulControlFlowGraphExporter::toJson(SSACFG const& _cfg, std::vector const& _values) +{ + Json ret = Json::array(); + for (auto const& value: _values) + ret.push_back(varToString(_cfg, value)); + return ret; +} diff --git a/libyul/YulControlFlowGraphExporter.h b/libyul/YulControlFlowGraphExporter.h new file mode 100644 index 000000000..37520e194 --- /dev/null +++ b/libyul/YulControlFlowGraphExporter.h @@ -0,0 +1,42 @@ +/* + 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 + +#pragma once + +#include +#include +#include + +using namespace solidity; +using namespace yul; + +class YulControlFlowGraphExporter +{ +public: + YulControlFlowGraphExporter(ControlFlow const& _controlFlow); + Json run(); + Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _blockId); + Json exportFunction(SSACFG const& _cfg); + std::string varToString(SSACFG const& _cfg, SSACFG::ValueId _var); + +private: + ControlFlow const& m_controlFlow; + Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId); + Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation); + Json toJson(SSACFG const& _cfg, std::vector const& _values); +}; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 1f57eda48..373fb304f 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -364,6 +366,45 @@ Json YulStack::astJson() const return m_parserResult->toJson(); } +Json YulStack::cfgJson() const +{ + yulAssert(m_parserResult, ""); + yulAssert(m_parserResult->hasCode(), ""); + yulAssert(m_parserResult->analysisInfo, ""); + // FIXME: we should not regenerate the cfg, but for now this is sufficient for testing purposes + auto exportCFGFromObject = [&](Object const& _object) -> Json { + // NOTE: The block Ids are reset for each object + std::unique_ptr controlFlow = SSAControlFlowGraphBuilder::build( + *_object.analysisInfo.get(), + languageToDialect(m_language, m_evmVersion), + _object.code()->root() + ); + YulControlFlowGraphExporter exporter(*controlFlow); + return exporter.run(); + }; + + std::function>)> exportCFGFromSubObjects; + exportCFGFromSubObjects = [&](std::vector> _subObjects) -> Json { + Json subObjectsJson = Json::object(); + for (std::shared_ptr const& subObjectNode: _subObjects) + if (Object const* subObject = dynamic_cast(subObjectNode.get())) + { + subObjectsJson[subObject->name] = exportCFGFromObject(*subObject); + subObjectsJson["type"] = "subObject"; + if (!subObject->subObjects.empty()) + subObjectsJson["subObjects"] = exportCFGFromSubObjects(subObject->subObjects); + } + return subObjectsJson; + }; + + Object const& object = *m_parserResult.get(); + Json jsonObject = Json::object(); + jsonObject[object.name] = exportCFGFromObject(object); + jsonObject["type"] = "Object"; + jsonObject["subObjects"] = exportCFGFromSubObjects(object.subObjects); + return jsonObject; +} + std::shared_ptr YulStack::parserResult() const { yulAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); diff --git a/libyul/YulStack.h b/libyul/YulStack.h index 69c0f0165..746e0c49f 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -141,6 +141,9 @@ class YulStack: public langutil::CharStreamProvider ) const; Json astJson() const; + // return the JSON representation of the YuL CFG (experimental) + Json cfgJson() const; + /// Return the parsed and analyzed object. std::shared_ptr parserResult() const; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 02b6dcade..f78fdfeb8 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -291,6 +291,30 @@ void CommandLineInterface::handleIRAst(std::string const& _contractName) } } +void CommandLineInterface::handleYulCFGExport(std::string const& _contractName) +{ + solAssert(CompilerInputModes.count(m_options.input.mode) == 1); + + if (!m_options.compiler.outputs.yulCFGJson) + return; + + if (!m_options.output.dir.empty()) + createFile( + m_compiler->filesystemFriendlyName(_contractName) + "_yul_cfg.json", + util::jsonPrint( + m_compiler->yulCFGJson(_contractName), + m_options.formatting.json + ) + ); + else + { + sout() << util::jsonPrint( + m_compiler->yulCFGJson(_contractName), + m_options.formatting.json + ) << std::endl; + } +} + void CommandLineInterface::handleIROptimized(std::string const& _contractName) { solAssert(CompilerInputModes.count(m_options.input.mode) == 1); @@ -866,7 +890,7 @@ void CommandLineInterface::compile() m_compiler->selectDebugInfo(m_options.output.debugInfoSelection.value()); CompilerStack::IROutputSelection irOutputSelection = CompilerStack::IROutputSelection::None; - if (m_options.compiler.outputs.irOptimized || m_options.compiler.outputs.irOptimizedAstJson) + if (m_options.compiler.outputs.irOptimized || m_options.compiler.outputs.irOptimizedAstJson || m_options.compiler.outputs.yulCFGJson) irOutputSelection = CompilerStack::IROutputSelection::UnoptimizedAndOptimized; else if (m_options.compiler.outputs.ir || m_options.compiler.outputs.irAstJson) irOutputSelection = CompilerStack::IROutputSelection::UnoptimizedOnly; @@ -1280,6 +1304,11 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y sout() << "AST:" << std::endl << std::endl; sout() << util::jsonPrint(stack.astJson(), m_options.formatting.json) << std::endl; } + if (m_options.compiler.outputs.yulCFGJson) + { + sout() << "Yul Control Flow Graph:" << std::endl << std::endl; + sout() << util::jsonPrint(stack.cfgJson(), m_options.formatting.json) << std::endl; + } solAssert(_targetMachine == yul::YulStack::Machine::EVM, ""); if (m_options.compiler.outputs.asm_) { @@ -1335,6 +1364,7 @@ void CommandLineInterface::outputCompilationResults() handleIRAst(contract); handleIROptimized(contract); handleIROptimizedAst(contract); + handleYulCFGExport(contract); handleSignatureHashes(contract); handleMetadata(contract); handleABI(contract); diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index c23fd9e17..ce30a4d71 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -108,6 +108,7 @@ class CommandLineInterface void handleIRAst(std::string const& _contract); void handleIROptimized(std::string const& _contract); void handleIROptimizedAst(std::string const& _contract); + void handleYulCFGExport(std::string const& _contract); void handleBytecode(std::string const& _contract); void handleSignatureHashes(std::string const& _contract); void handleMetadata(std::string const& _contract); diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 19089d885..dca68bb1c 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -473,6 +473,7 @@ void CommandLineParser::parseOutputSelection() CompilerOutputs::componentName(&CompilerOutputs::irOptimized), CompilerOutputs::componentName(&CompilerOutputs::astCompactJson), CompilerOutputs::componentName(&CompilerOutputs::asmJson), + CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson), }; static std::set const evmAssemblyJsonImportModeOutputs = { CompilerOutputs::componentName(&CompilerOutputs::asm_), @@ -755,6 +756,7 @@ General Information)").c_str(), (CompilerOutputs::componentName(&CompilerOutputs::irAstJson).c_str(), "AST of Intermediate Representation (IR) of all contracts in a compact JSON format.") (CompilerOutputs::componentName(&CompilerOutputs::irOptimized).c_str(), "Optimized Intermediate Representation (IR) of all contracts.") (CompilerOutputs::componentName(&CompilerOutputs::irOptimizedAstJson).c_str(), "AST of optimized Intermediate Representation (IR) of all contracts in a compact JSON format.") + (CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson).c_str(), "Control Flow Graph (CFG) of Yul code in JSON format.") (CompilerOutputs::componentName(&CompilerOutputs::signatureHashes).c_str(), "Function signature hashes of the contracts.") (CompilerOutputs::componentName(&CompilerOutputs::natspecUser).c_str(), "Natspec user documentation of all contracts.") (CompilerOutputs::componentName(&CompilerOutputs::natspecDev).c_str(), "Natspec developer documentation of all contracts.") diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 5d941f662..3d187694e 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -87,6 +87,7 @@ struct CompilerOutputs {"metadata", &CompilerOutputs::metadata}, {"storage-layout", &CompilerOutputs::storageLayout}, {"transient-storage-layout", &CompilerOutputs::transientStorageLayout}, + {"yul-cfg-json", &CompilerOutputs::yulCFGJson}, }; return components; } @@ -100,6 +101,7 @@ struct CompilerOutputs bool abi = false; bool ir = false; bool irAstJson = false; + bool yulCFGJson = false; bool irOptimized = false; bool irOptimizedAstJson = false; bool signatureHashes = false; diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index e0347a18c..227b1b921 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -131,6 +131,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) "dir2/file2.sol:L=0x1111122222333334444455555666667777788888", "--ast-compact-json", "--asm", "--asm-json", "--opcodes", "--bin", "--bin-runtime", "--abi", "--ir", "--ir-ast-json", "--ir-optimized", "--ir-optimized-ast-json", "--hashes", "--userdoc", "--devdoc", "--metadata", + "--yul-cfg-json", "--storage-layout", "--transient-storage-layout", "--gas", "--combined-json=" @@ -193,7 +194,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, + true, true, true, }; expectedOptions.compiler.estimateGas = true; expectedOptions.compiler.combinedJsonRequests = { From b167c271141715ffca2b28816ede10dd03ba110e Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 26 Aug 2024 11:31:03 +0200 Subject: [PATCH 0290/1340] prep: Pass `_eofVersion` to `libevmasm/Assembly` class Co-authored-by: Daniel Kirchner --- libevmasm/Assembly.cpp | 23 ++++++++++++++++------ libevmasm/Assembly.h | 11 +++++++++-- libsolidity/codegen/CompilerContext.h | 2 +- libsolidity/interface/CompilerStack.cpp | 8 ++++++++ libyul/YulStack.cpp | 2 +- libyul/backends/evm/EVMObjectCompiler.cpp | 2 +- libyul/backends/evm/EthAssemblyAdapter.cpp | 2 +- test/libevmasm/Assembler.cpp | 21 ++++++++++---------- test/libevmasm/Optimiser.cpp | 4 ++-- test/libyul/EVMCodeTransformTest.cpp | 2 +- test/tools/fuzzer_common.cpp | 2 +- 11 files changed, 53 insertions(+), 26 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index ab3879da4..7a28208c1 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -549,7 +549,7 @@ std::pair, std::vector> Assembly::fromJSO "Member 'sourceList' may only be present in the root JSON object." ); - auto result = std::make_shared(EVMVersion{}, _level == 0 /* _creation */, "" /* _name */); + auto result = std::make_shared(EVMVersion{}, _level == 0 /* _creation */, std::nullopt, "" /* _name */); std::vector parsedSourceList; if (_json.contains("sourceList")) { @@ -735,7 +735,7 @@ std::map const& Assembly::optimiseInternal( { count = 0; - if (_settings.runInliner) + if (_settings.runInliner && !m_eofVersion.has_value()) Inliner{ m_items, _tagsReferencedFromOutside, @@ -762,7 +762,7 @@ std::map const& Assembly::optimiseInternal( } // This only modifies PushTags, we have to run again to actually remove code. - if (_settings.runDeduplicate) + if (_settings.runDeduplicate && !m_eofVersion.has_value()) { BlockDeduplicator deduplicator{m_items}; if (deduplicator.deduplicate()) @@ -787,7 +787,8 @@ std::map const& Assembly::optimiseInternal( } } - if (_settings.runCSE) + // TODO: investigate for EOF + if (_settings.runCSE && !m_eofVersion.has_value()) { // Control flow graph optimization has been here before but is disabled because it // assumes we only jump to tags that are pushed. This is not the case anymore with @@ -839,7 +840,8 @@ std::map const& Assembly::optimiseInternal( } } - if (_settings.runConstantOptimiser) + // TODO: investigate for EOF + if (_settings.runConstantOptimiser && !m_eofVersion.has_value()) ConstantOptimisationMethod::optimiseConstants( isCreation(), isCreation() ? 1 : _settings.expectedExecutionsPerDeployment, @@ -862,6 +864,9 @@ LinkerObject const& Assembly::assemble() const LinkerObject& ret = m_assembledObject; + bool const eof = m_eofVersion.has_value(); + solAssert(!eof || m_eofVersion == 1, "Invalid EOF version."); + size_t subTagSize = 1; std::map>> immutableReferencesBySub; for (auto const& sub: m_subs) @@ -957,6 +962,7 @@ LinkerObject const& Assembly::assemble() const } case PushTag: { + assertThrow(!eof, AssemblyException, "PushTag in EOF code"); ret.bytecode.push_back(tagPush); tagRef[ret.bytecode.size()] = i.splitForeignPushTag(); ret.bytecode.resize(ret.bytecode.size() + bytesPerTag); @@ -968,6 +974,7 @@ LinkerObject const& Assembly::assemble() const ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); break; case PushSub: + assertThrow(!eof, AssemblyException, "PushSub in EOF code"); assertThrow(i.data() <= std::numeric_limits::max(), AssemblyException, ""); ret.bytecode.push_back(dataRefPush); subRef.insert(std::make_pair(static_cast(i.data()), ret.bytecode.size())); @@ -975,6 +982,7 @@ LinkerObject const& Assembly::assemble() const break; case PushSubSize: { + assertThrow(!eof, AssemblyException, "PushSubSize in EOF code"); assertThrow(i.data() <= std::numeric_limits::max(), AssemblyException, ""); auto s = subAssemblyById(static_cast(i.data()))->assemble().bytecode.size(); i.setPushedValue(u256(s)); @@ -987,6 +995,7 @@ LinkerObject const& Assembly::assemble() const } case PushProgramSize: { + assertThrow(!eof, AssemblyException, "PushProgramSize in EOF code"); ret.bytecode.push_back(dataRefPush); sizeRef.push_back(static_cast(ret.bytecode.size())); ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); @@ -998,6 +1007,7 @@ LinkerObject const& Assembly::assemble() const ret.bytecode.resize(ret.bytecode.size() + 20); break; case PushImmutable: + assertThrow(!eof, AssemblyException, "PushImmutable in EOF code"); ret.bytecode.push_back(static_cast(Instruction::PUSH32)); // Maps keccak back to the "identifier" std::string of that immutable. ret.immutableReferences[i.data()].first = m_immutables.at(i.data()); @@ -1011,6 +1021,7 @@ LinkerObject const& Assembly::assemble() const break; case AssignImmutable: { + assertThrow(!eof, AssemblyException, "AssignImmutable in EOF code"); // Expect 2 elements on stack (source, dest_base) auto const& offsets = immutableReferencesBySub[i.data()].second; for (size_t i = 0; i < offsets.size(); ++i) @@ -1063,7 +1074,7 @@ LinkerObject const& Assembly::assemble() const "Some immutables were read from but never assigned, possibly because of optimization." ); - if (!m_subs.empty() || !m_data.empty() || !m_auxiliaryData.empty()) + if (!eof && (!m_subs.empty() || !m_data.empty() || !m_auxiliaryData.empty())) // Append an INVALID here to help tests find miscompilation. ret.bytecode.push_back(static_cast(Instruction::INVALID)); diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 123d7f3dd..2b0ef93df 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -48,8 +48,14 @@ using AssemblyPointer = std::shared_ptr; class Assembly { public: - Assembly(langutil::EVMVersion _evmVersion, bool _creation, std::string _name): m_evmVersion(_evmVersion), m_creation(_creation), m_name(std::move(_name)) { } - + Assembly(langutil::EVMVersion _evmVersion, bool _creation, std::optional _eofVersion, std::string _name): + m_evmVersion(_evmVersion), + m_creation(_creation), + m_eofVersion(_eofVersion), + m_name(std::move(_name)) + {} + + std::optional eofVersion() const { return m_eofVersion; } AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); } AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); } /// Returns a tag identified by the given name. Creates it if it does not yet exist. @@ -242,6 +248,7 @@ class Assembly int m_deposit = 0; /// True, if the assembly contains contract creation code. bool const m_creation = false; + std::optional m_eofVersion; /// Internal name of the assembly object, only used with the Yul backend /// currently std::string m_name; diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index c6972f92b..3469ee7d2 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -65,7 +65,7 @@ class CompilerContext RevertStrings _revertStrings, CompilerContext* _runtimeContext = nullptr ): - m_asm(std::make_shared(_evmVersion, _runtimeContext != nullptr, std::string{})), + m_asm(std::make_shared(_evmVersion, _runtimeContext != nullptr, std::nullopt, std::string{})), m_evmVersion(_evmVersion), m_revertStrings(_revertStrings), m_reservedMemory{0}, diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 1f432db40..60f41a7b6 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -864,6 +864,10 @@ std::string const* CompilerStack::sourceMapping(std::string const& _contractName { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); + // TODO + if (m_eofVersion.has_value()) + return nullptr; + Contract const& c = contract(_contractName); if (!c.sourceMapping) { @@ -877,6 +881,10 @@ std::string const* CompilerStack::runtimeSourceMapping(std::string const& _contr { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); + // TODO + if (m_eofVersion.has_value()) + return nullptr; + Contract const& c = contract(_contractName); if (!c.runtimeSourceMapping) { diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 1f57eda48..da9ac35dc 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -295,7 +295,7 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) yulAssert(m_parserResult->hasCode(), ""); yulAssert(m_parserResult->analysisInfo, ""); - evmasm::Assembly assembly(m_evmVersion, true, {}); + evmasm::Assembly assembly(m_evmVersion, true, m_eofVersion, {}); EthAssemblyAdapter adapter(assembly); // NOTE: We always need stack optimization when Yul optimizer is disabled (unless code contains diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index ccd8af6d2..a7ac67c3a 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -75,7 +75,7 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) yulAssert(_object.hasCode(), "No code."); if (m_eofVersion.has_value()) yulAssert( - _optimize && (m_dialect.evmVersion() == langutil::EVMVersion()), + _optimize && (m_dialect.evmVersion() >= langutil::EVMVersion::prague()), "Experimental EOF support is only available for optimized via-IR compilation and the most recent EVM version." ); if (_optimize && m_dialect.evmVersion().canOverchargeGasForCall()) diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index 79146f859..e3a2e01e1 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -123,7 +123,7 @@ void EthAssemblyAdapter::appendAssemblySize() std::pair, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(bool _creation, std::string _name) { - std::shared_ptr assembly{std::make_shared(m_assembly.evmVersion(), _creation, std::move(_name))}; + std::shared_ptr assembly{std::make_shared(m_assembly.evmVersion(), _creation, m_assembly.eofVersion(), std::move(_name))}; auto sub = m_assembly.newSub(assembly); return {std::make_shared(*assembly), static_cast(sub.data())}; } diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index afad9d13d..06c7fb6a9 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -61,15 +62,15 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) { "verbatim.asm", 2 } }; EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); - Assembly _assembly{evmVersion, false, {}}; + Assembly _assembly{evmVersion, false, solidity::test::CommonOptions::get().eofVersion(), {}}; auto root_asm = std::make_shared("root.asm"); _assembly.setSourceLocation({1, 3, root_asm}); - Assembly _subAsm{evmVersion, false, {}}; + Assembly _subAsm{evmVersion, false, solidity::test::CommonOptions::get().eofVersion(), {}}; auto sub_asm = std::make_shared("sub.asm"); _subAsm.setSourceLocation({6, 8, sub_asm}); - Assembly _verbatimAsm(evmVersion, true, ""); + Assembly _verbatimAsm(evmVersion, true, solidity::test::CommonOptions::get().eofVersion(), ""); auto verbatim_asm = std::make_shared("verbatim.asm"); _verbatimAsm.setSourceLocation({8, 18, verbatim_asm}); @@ -246,7 +247,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) { *subName, 1 } }; - auto subAsm = std::make_shared(evmVersion, false, std::string{}); + auto subAsm = std::make_shared(evmVersion, false, solidity::test::CommonOptions::get().eofVersion(), std::string{}); for (char i = 0; i < numImmutables; ++i) { for (int r = 0; r < numActualRefs; ++r) @@ -256,7 +257,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) } } - Assembly assembly{evmVersion, true, {}}; + Assembly assembly{evmVersion, true, solidity::test::CommonOptions::get().eofVersion(), {}}; for (char i = 1; i <= numImmutables; ++i) { assembly.setSourceLocation({10*i, 10*i + 3+i, assemblyName}); @@ -306,11 +307,11 @@ BOOST_AUTO_TEST_CASE(immutable) { "sub.asm", 1 } }; EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); - Assembly _assembly{evmVersion, true, {}}; + Assembly _assembly{evmVersion, true, solidity::test::CommonOptions::get().eofVersion(), {}}; auto root_asm = std::make_shared("root.asm"); _assembly.setSourceLocation({1, 3, root_asm}); - Assembly _subAsm{evmVersion, false, {}}; + Assembly _subAsm{evmVersion, false, solidity::test::CommonOptions::get().eofVersion(), {}}; auto sub_asm = std::make_shared("sub.asm"); _subAsm.setSourceLocation({6, 8, sub_asm}); _subAsm.appendImmutable("someImmutable"); @@ -404,10 +405,10 @@ BOOST_AUTO_TEST_CASE(immutable) BOOST_AUTO_TEST_CASE(subobject_encode_decode) { EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); - Assembly assembly{evmVersion, true, {}}; + Assembly assembly{evmVersion, true, solidity::test::CommonOptions::get().eofVersion(), {}}; - std::shared_ptr subAsmPtr = std::make_shared(evmVersion, false, std::string{}); - std::shared_ptr subSubAsmPtr = std::make_shared(evmVersion, false, std::string{}); + std::shared_ptr subAsmPtr = std::make_shared(evmVersion, false, solidity::test::CommonOptions::get().eofVersion(), std::string{}); + std::shared_ptr subSubAsmPtr = std::make_shared(evmVersion, false, solidity::test::CommonOptions::get().eofVersion(), std::string{}); assembly.appendSubroutine(subAsmPtr); subAsmPtr->appendSubroutine(subSubAsmPtr); diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 13fa58bf4..13d9d6f2b 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1346,8 +1346,8 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) settings.evmVersion = solidity::test::CommonOptions::get().evmVersion(); settings.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment; - Assembly main{settings.evmVersion, false, {}}; - AssemblyPointer sub = std::make_shared(settings.evmVersion, true, std::string{}); + Assembly main{settings.evmVersion, false, solidity::test::CommonOptions::get().eofVersion(), {}}; + AssemblyPointer sub = std::make_shared(settings.evmVersion, true, solidity::test::CommonOptions::get().eofVersion(), std::string{}); sub->append(u256(1)); auto t1 = sub->newTag(); diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 4c2eecab0..e54ab9c8f 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -67,7 +67,7 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin return TestResult::FatalError; } - evmasm::Assembly assembly{solidity::test::CommonOptions::get().evmVersion(), false, {}}; + evmasm::Assembly assembly{solidity::test::CommonOptions::get().evmVersion(), false, std::nullopt, {}}; EthAssemblyAdapter adapter(assembly); EVMObjectCompiler::compile( *stack.parserResult(), diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index adf5a064b..1caa5357e 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -190,7 +190,7 @@ void FuzzerUtil::testConstantOptimizer(std::string const& _input, bool _quiet) for (bool isCreation: {false, true}) { - Assembly assembly{langutil::EVMVersion{}, isCreation, {}}; + Assembly assembly{langutil::EVMVersion{}, isCreation, std::nullopt, {}}; for (u256 const& n: numbers) { if (!_quiet) From 1854186942cc24e94cfed2708ec4d0fc3e668a62 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 28 Aug 2024 15:11:44 +0200 Subject: [PATCH 0291/1340] eof: Remove eof experimental test. It should be reintroduced later. --- test/libsolidity/Metadata.cpp | 39 ----------------------------------- 1 file changed, 39 deletions(-) diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index 94687f990..ed490b9a8 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -225,45 +225,6 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) } } -BOOST_AUTO_TEST_CASE(metadata_eof_experimental) -{ - // Check that setting an EOF version results in the experimental flag being set. - char const* sourceCode = R"( - pragma solidity >=0.0; - contract test { - function g(function(uint) external returns (uint) x) public {} - } - )"; - for (auto metadataFormat: std::set{ - CompilerStack::MetadataFormat::NoMetadata, - CompilerStack::MetadataFormat::WithReleaseVersionTag, - CompilerStack::MetadataFormat::WithPrereleaseVersionTag - }) - { - CompilerStack compilerStack; - compilerStack.setMetadataFormat(metadataFormat); - compilerStack.setSources({{"", sourceCode}}); - compilerStack.setEVMVersion({}); - compilerStack.setViaIR(true); - compilerStack.setEOFVersion(1); - compilerStack.setOptimiserSettings(true); - BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); - bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; - std::string const& metadata = compilerStack.metadata("test"); - BOOST_CHECK(solidity::test::isValidMetadata(metadata)); - - auto const cborMetadata = requireParsedCBORMetadata(bytecode, metadataFormat); - - if (metadataFormat == CompilerStack::MetadataFormat::NoMetadata) - BOOST_CHECK(cborMetadata.count("experimental") == 0); - else - { - BOOST_CHECK(cborMetadata.count("experimental") == 1); - BOOST_CHECK(cborMetadata.at("experimental") == "true"); - } - } -} - BOOST_AUTO_TEST_CASE(metadata_relevant_sources) { CompilerStack compilerStack; From 92a74edfba8ab97eaecad1d97760d2f70b57f77e Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Sat, 20 Jul 2024 11:58:08 +0200 Subject: [PATCH 0292/1340] SMTChecker: Introduce helper struct for query result --- libsmtutil/CHCSmtLib2Interface.cpp | 2 +- libsmtutil/CHCSmtLib2Interface.h | 2 +- libsmtutil/CHCSolverInterface.h | 10 +++++++--- libsmtutil/Z3CHCInterface.cpp | 2 +- libsmtutil/Z3CHCInterface.h | 2 +- libsolidity/formal/CHC.cpp | 21 +++++++------------- libsolidity/formal/CHC.h | 2 +- libsolidity/formal/Z3CHCSmtLib2Interface.cpp | 2 +- libsolidity/formal/Z3CHCSmtLib2Interface.h | 2 +- 9 files changed, 21 insertions(+), 24 deletions(-) diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index 6e535f099..d23249d22 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -90,7 +90,7 @@ void CHCSmtLib2Interface::addRule(Expression const& _expr, std::string const& /* m_commands.assertion("(forall" + forall(_expr) + '\n' + m_context.toSExpr(_expr) + ")\n"); } -std::tuple CHCSmtLib2Interface::query(Expression const& _block) +CHCSolverInterface::QueryResult CHCSmtLib2Interface::query(Expression const& _block) { std::string query = dumpQuery(_block); std::string response = querySolver(query); diff --git a/libsmtutil/CHCSmtLib2Interface.h b/libsmtutil/CHCSmtLib2Interface.h index b5baba7d6..0f8fc061d 100644 --- a/libsmtutil/CHCSmtLib2Interface.h +++ b/libsmtutil/CHCSmtLib2Interface.h @@ -47,7 +47,7 @@ class CHCSmtLib2Interface: public CHCSolverInterface /// Takes a function application _expr and checks for reachability. /// @returns solving result, an invariant, and counterexample graph, if possible. - std::tuple query(Expression const& _expr) override; + QueryResult query(Expression const& _expr) override; void declareVariable(std::string const& _name, SortPointer const& _sort) override; diff --git a/libsmtutil/CHCSolverInterface.h b/libsmtutil/CHCSolverInterface.h index a20283b4f..8feb18aa8 100644 --- a/libsmtutil/CHCSolverInterface.h +++ b/libsmtutil/CHCSolverInterface.h @@ -49,11 +49,15 @@ class CHCSolverInterface : public SolverInterface std::map> edges; }; + struct QueryResult + { + CheckResult answer; + Expression invariant; + CexGraph cex; + }; /// Takes a function application _expr and checks for reachability. /// @returns solving result, an invariant, and counterexample graph, if possible. - virtual std::tuple query( - Expression const& _expr - ) = 0; + virtual QueryResult query(Expression const& _expr) = 0; protected: std::optional m_queryTimeout; diff --git a/libsmtutil/Z3CHCInterface.cpp b/libsmtutil/Z3CHCInterface.cpp index 787d46d72..a79630b6e 100644 --- a/libsmtutil/Z3CHCInterface.cpp +++ b/libsmtutil/Z3CHCInterface.cpp @@ -78,7 +78,7 @@ void Z3CHCInterface::addRule(Expression const& _expr, std::string const& _name) } } -std::tuple Z3CHCInterface::query(Expression const& _expr) +CHCSolverInterface::QueryResult Z3CHCInterface::query(Expression const& _expr) { CheckResult result; try diff --git a/libsmtutil/Z3CHCInterface.h b/libsmtutil/Z3CHCInterface.h index 5a768f65c..98f21246c 100644 --- a/libsmtutil/Z3CHCInterface.h +++ b/libsmtutil/Z3CHCInterface.h @@ -43,7 +43,7 @@ class Z3CHCInterface: public CHCSolverInterface void addRule(Expression const& _expr, std::string const& _name) override; - std::tuple query(Expression const& _expr) override; + QueryResult query(Expression const& _expr) override; Z3Interface* z3Interface() const { return m_z3Interface.get(); } diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 2bd019537..c52a83a26 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -1916,11 +1916,8 @@ void CHC::addRule(smtutil::Expression const& _rule, std::string const& _ruleName m_interface->addRule(_rule, _ruleName); } -std::tuple CHC::query(smtutil::Expression const& _query, langutil::SourceLocation const& _location) +CHCSolverInterface::QueryResult CHC::query(smtutil::Expression const& _query, langutil::SourceLocation const& _location) { - CheckResult result; - smtutil::Expression invariant(true); - CHCSolverInterface::CexGraph cex; if (m_settings.printQuery) { auto smtLibInterface = dynamic_cast(m_interface.get()); @@ -1931,8 +1928,8 @@ std::tuple CHC:: "CHC: Requested query:\n" + smtLibCode ); } - std::tie(result, invariant, cex) = m_interface->query(_query); - switch (result) + auto result = m_interface->query(_query); + switch (result.answer) { case CheckResult::SATISFIABLE: { @@ -1946,13 +1943,10 @@ std::tuple CHC:: solAssert(spacer, ""); spacer->setSpacerOptions(false); - CheckResult resultNoOpt; - smtutil::Expression invariantNoOpt(true); - CHCSolverInterface::CexGraph cexNoOpt; - std::tie(resultNoOpt, invariantNoOpt, cexNoOpt) = m_interface->query(_query); + auto resultNoOpt = m_interface->query(_query); - if (resultNoOpt == CheckResult::SATISFIABLE) - cex = std::move(cexNoOpt); + if (resultNoOpt.answer == CheckResult::SATISFIABLE) + result.cex = std::move(resultNoOpt.cex); spacer->setSpacerOptions(true); #else @@ -1962,7 +1956,6 @@ std::tuple CHC:: break; } case CheckResult::UNSATISFIABLE: - break; case CheckResult::UNKNOWN: break; case CheckResult::CONFLICTING: @@ -1972,7 +1965,7 @@ std::tuple CHC:: m_errorReporter.warning(1218_error, _location, "CHC: Error trying to invoke SMT solver."); break; } - return {result, invariant, cex}; + return result; } void CHC::verificationTargetEncountered( diff --git a/libsolidity/formal/CHC.h b/libsolidity/formal/CHC.h index 8a40ecb22..8ecef3960 100644 --- a/libsolidity/formal/CHC.h +++ b/libsolidity/formal/CHC.h @@ -296,7 +296,7 @@ class CHC: public SMTEncoder void addRule(smtutil::Expression const& _rule, std::string const& _ruleName); /// @returns if query is unsatisfiable (safe). /// @returns otherwise. - std::tuple query(smtutil::Expression const& _query, langutil::SourceLocation const& _location); + smtutil::CHCSolverInterface::QueryResult query(smtutil::Expression const& _query, langutil::SourceLocation const& _location); void verificationTargetEncountered(ASTNode const* const _errorNode, VerificationTargetType _type, smtutil::Expression const& _errorCondition); diff --git a/libsolidity/formal/Z3CHCSmtLib2Interface.cpp b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp index cd06a9d33..d8448fc0b 100644 --- a/libsolidity/formal/Z3CHCSmtLib2Interface.cpp +++ b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp @@ -43,7 +43,7 @@ void Z3CHCSmtLib2Interface::setupSmtCallback(bool _enablePreprocessing) universalCallback->smtCommand().setZ3(m_queryTimeout, _enablePreprocessing, m_computeInvariants); } -std::tuple Z3CHCSmtLib2Interface::query(smtutil::Expression const& _block) +CHCSolverInterface::QueryResult Z3CHCSmtLib2Interface::query(smtutil::Expression const& _block) { setupSmtCallback(true); std::string query = dumpQuery(_block); diff --git a/libsolidity/formal/Z3CHCSmtLib2Interface.h b/libsolidity/formal/Z3CHCSmtLib2Interface.h index 39456cde0..a58e7f857 100644 --- a/libsolidity/formal/Z3CHCSmtLib2Interface.h +++ b/libsolidity/formal/Z3CHCSmtLib2Interface.h @@ -35,7 +35,7 @@ class Z3CHCSmtLib2Interface: public smtutil::CHCSmtLib2Interface private: void setupSmtCallback(bool _disablePreprocessing); - std::tuple query(smtutil::Expression const& _expr) override; + CHCSolverInterface::QueryResult query(smtutil::Expression const& _expr) override; CHCSolverInterface::CexGraph graphFromZ3Answer(std::string const& _proof) const; From 03880e420226de043329b378f0879cd27d073dc4 Mon Sep 17 00:00:00 2001 From: Guilherme Ferreira Date: Tue, 13 Feb 2024 01:01:40 +0100 Subject: [PATCH 0293/1340] Updating copyright year to 2024 --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index ddc3ee81b..9c9e2d5a0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -67,7 +67,7 @@ def setup(sphinx): # General information about the project. project = 'Solidity' -project_copyright = '2016-2023, The Solidity Authors' +project_copyright = '2016-2024, The Solidity Authors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the From d7865f171226cf282d6f9c099b27b14b746935a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 30 Aug 2024 15:42:16 +0200 Subject: [PATCH 0294/1340] Do not suppress the original message from unexpected AssemblyExceptions --- libsolidity/interface/CompilerStack.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index ce9525c2b..385109357 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1348,9 +1348,9 @@ void CompilerStack::assembleYul( // Assemble deployment (incl. runtime) object. compiledContract.object = compiledContract.evmAssembly->assemble(); } - catch (evmasm::AssemblyException const&) + catch (evmasm::AssemblyException const& error) { - solAssert(false, "Assembly exception for bytecode"); + solAssert(false, "Assembly exception for bytecode: "s + error.what()); } solAssert(compiledContract.object.immutableReferences.empty(), "Leftover immutables."); @@ -1361,9 +1361,9 @@ void CompilerStack::assembleYul( // Assemble runtime object. compiledContract.runtimeObject = compiledContract.evmRuntimeAssembly->assemble(); } - catch (evmasm::AssemblyException const&) + catch (evmasm::AssemblyException const& error) { - solAssert(false, "Assembly exception for deployed bytecode"); + solAssert(false, "Assembly exception for deployed bytecode"s + error.what()); } // Throw a warning if EIP-170 limits are exceeded: From 2f46323b171bd3fa086d553430b293e8a3141687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 30 Aug 2024 16:08:40 +0200 Subject: [PATCH 0295/1340] Bump min Boost dependency to 1.67 on Linux and macOS --- cmake/EthDependencies.cmake | 3 ++- docs/installing-solidity.rst | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 16f30a640..87a5e1b5e 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -37,7 +37,8 @@ if (WIN32) find_package(Boost 1.77.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) else() # Boost 1.65 is the first to also provide boost::get for rvalue-references (#5787). - find_package(Boost 1.65.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) + # Boost 1.67 moved container_hash into is own module. + find_package(Boost 1.67.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) endif() # If cmake is older than boost and boost is older than 1.70, diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index b1b3e1a3f..5473dbb52 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -327,7 +327,7 @@ The following are dependencies for all builds of Solidity: | Windows, 3.13+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ | `Boost`_ (version 1.77+ on | C++ libraries. | -| Windows, 1.65+ otherwise) | | +| Windows, 1.67+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ | `Git`_ | Command-line tool for retrieving source code. | +-----------------------------------+-------------------------------------------------------+ From ad969e2b94be91ce54f614c0d5e74ec5ea7686d7 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 2 Sep 2024 12:34:31 +0200 Subject: [PATCH 0296/1340] Hide undocumented yul export cfg option --- solc/CommandLineParser.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index dca68bb1c..4607250a6 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -756,7 +756,6 @@ General Information)").c_str(), (CompilerOutputs::componentName(&CompilerOutputs::irAstJson).c_str(), "AST of Intermediate Representation (IR) of all contracts in a compact JSON format.") (CompilerOutputs::componentName(&CompilerOutputs::irOptimized).c_str(), "Optimized Intermediate Representation (IR) of all contracts.") (CompilerOutputs::componentName(&CompilerOutputs::irOptimizedAstJson).c_str(), "AST of optimized Intermediate Representation (IR) of all contracts in a compact JSON format.") - (CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson).c_str(), "Control Flow Graph (CFG) of Yul code in JSON format.") (CompilerOutputs::componentName(&CompilerOutputs::signatureHashes).c_str(), "Function signature hashes of the contracts.") (CompilerOutputs::componentName(&CompilerOutputs::natspecUser).c_str(), "Natspec user documentation of all contracts.") (CompilerOutputs::componentName(&CompilerOutputs::natspecDev).c_str(), "Natspec developer documentation of all contracts.") @@ -764,6 +763,10 @@ General Information)").c_str(), (CompilerOutputs::componentName(&CompilerOutputs::storageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in storage.") (CompilerOutputs::componentName(&CompilerOutputs::transientStorageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in transient storage.") ; + if (!_forHelp) // Note: We intentionally keep this undocumented for now. + outputComponents.add_options() + (CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson).c_str(), "Control Flow Graph (CFG) of Yul code in JSON format.") + ; desc.add(outputComponents); po::options_description extraOutput("Extra Output"); From b30f1e2af0b9605ae295282188fc4eadc0b10721 Mon Sep 17 00:00:00 2001 From: Vishwa Mehta Date: Mon, 2 Sep 2024 12:39:46 +0200 Subject: [PATCH 0297/1340] Create opRetro.json --- opRetro.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 opRetro.json diff --git a/opRetro.json b/opRetro.json new file mode 100644 index 000000000..6fb1f338b --- /dev/null +++ b/opRetro.json @@ -0,0 +1,5 @@ +{ + "opRetro": { + "projectId": "0xcc8d03e014e121d10602eeff729b755d5dc6a317df0d6302c8a9d3b5424aaba8" + } +} From 1673c5c27ad42a41019a7bafa96e636ef12a0334 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 29 Aug 2024 11:12:22 +0200 Subject: [PATCH 0298/1340] Introduce ubuntu2404 clang docker image wip --- .github/workflows/buildpack-deps.yml | 3 +- .../buildpack-deps_test_ubuntu2404.clang.sh | 1 + .../Dockerfile.ubuntu2404.clang | 107 ++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 120000 scripts/ci/buildpack-deps_test_ubuntu2404.clang.sh create mode 100644 scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index 5f66487e0..1b9555ddc 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -10,6 +10,7 @@ on: - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2204' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404' + - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang' jobs: buildpack-deps: @@ -24,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2204.clang, ubuntu2204, ubuntu2404] + image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2204.clang, ubuntu2204, ubuntu2404, ubuntu2404.clang] steps: - uses: actions/checkout@v4 diff --git a/scripts/ci/buildpack-deps_test_ubuntu2404.clang.sh b/scripts/ci/buildpack-deps_test_ubuntu2404.clang.sh new file mode 120000 index 000000000..c07a74de4 --- /dev/null +++ b/scripts/ci/buildpack-deps_test_ubuntu2404.clang.sh @@ -0,0 +1 @@ +build.sh \ No newline at end of file diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang new file mode 100644 index 000000000..c6b1fd970 --- /dev/null +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang @@ -0,0 +1,107 @@ +# 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 +# +# (c) 2016-2024 solidity contributors. +#------------------------------------------------------------------------------ +FROM buildpack-deps:noble AS base +LABEL version="1" + +ARG DEBIAN_FRONTEND=noninteractive + +# From Python3.11, pip requires a virtual environment, and will thus terminate when installing packages globally. +# Since we're building this image from scratch, it's perfectly fine to use the below flag. +ENV PIP_BREAK_SYSTEM_PACKAGES 1 + +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 \ + clang \ + cmake \ + jq \ + lsof \ + libboost-filesystem-dev \ + libboost-program-options-dev \ + libboost-system-dev \ + libboost-test-dev \ + libcln-dev \ + libz3-static-dev \ + ninja-build \ + python3-pip \ + software-properties-common \ + sudo \ + z3-static; \ + pip3 install \ + codecov \ + colorama \ + deepdiff \ + parsec \ + pygments-lexer-solidity \ + pylint \ + requests \ + tabulate \ + z3-solver; + +# Eldarica +RUN set -ex; \ + apt-get update; \ + apt-get install -qy \ + openjdk-11-jre \ + unzip; \ + eldarica_version="2.1"; \ + wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ + test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ + unzip /opt/eld_binaries.zip -d /opt; \ + rm -f /opt/eld_binaries.zip; + +# CVC5 +RUN set -ex; \ + cvc5_version="1.1.2"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ + unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ + mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ + mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ + mv /opt/cvc5-Linux-static/include/* /usr/include; \ + rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + +FROM base AS libraries + +ENV CC clang +ENV CXX clang++ + +# EVMONE +RUN set -ex; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + cd /usr; \ + tar -xf /usr/src/evmone.tar.gz; \ + rm -rf /usr/src/evmone.tar.gz + +FROM base +COPY --from=libraries /usr/lib /usr/lib +COPY --from=libraries /usr/bin /usr/bin +COPY --from=libraries /usr/include /usr/include +COPY --from=libraries /opt/eldarica /opt/eldarica +ENV PATH="$PATH:/opt/eldarica" From b3ba1b2e373f6ec850733e5ebf12b3808a6f9b74 Mon Sep 17 00:00:00 2001 From: Vishwa Mehta Date: Mon, 2 Sep 2024 14:15:24 +0200 Subject: [PATCH 0299/1340] Rename opRetro.json to funding.json --- opRetro.json => funding.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename opRetro.json => funding.json (100%) diff --git a/opRetro.json b/funding.json similarity index 100% rename from opRetro.json rename to funding.json From 79f05ca5738d927ac7d4f25bbb2d5717017c6736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 30 Aug 2024 16:46:42 +0200 Subject: [PATCH 0300/1340] Mark PROFILE_OPTIMIZER_STEPS CMake option as advanced --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 71f83b80e..02d45d8e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser ste option(USE_SYSTEM_LIBRARIES "Use system libraries" OFF) option(ONLY_BUILD_SOLIDITY_LIBRARIES "Only build solidity libraries" OFF) option(STRICT_NLOHMANN_JSON_VERSION "Strictly check installed nlohmann json version" ON) +mark_as_advanced(PROFILE_OPTIMIZER_STEPS) mark_as_advanced(USE_SYSTEM_LIBRARIES) mark_as_advanced(ONLY_BUILD_SOLIDITY_LIBRARIES) mark_as_advanced(STRICT_NLOHMANN_JSON_VERSION) From b52094bc2832b40c43134990182cc89caabcbf84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 30 Aug 2024 16:49:43 +0200 Subject: [PATCH 0301/1340] Remove nlohmann JSON version check - The git submodule is pinned to that version, which should be enough of a hint that this is the version we expect. If someone builds with a different version and it passes tests, we should not block that. --- CMakeLists.txt | 2 -- libsolutil/JSON.cpp | 6 ------ 2 files changed, 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 02d45d8e6..a08e44da5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,11 +39,9 @@ option(PEDANTIC "Enable extra warnings and pedantic build flags. Treat all warni option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser steps." OFF) option(USE_SYSTEM_LIBRARIES "Use system libraries" OFF) option(ONLY_BUILD_SOLIDITY_LIBRARIES "Only build solidity libraries" OFF) -option(STRICT_NLOHMANN_JSON_VERSION "Strictly check installed nlohmann json version" ON) mark_as_advanced(PROFILE_OPTIMIZER_STEPS) mark_as_advanced(USE_SYSTEM_LIBRARIES) mark_as_advanced(ONLY_BUILD_SOLIDITY_LIBRARIES) -mark_as_advanced(STRICT_NLOHMANN_JSON_VERSION) # Setup cccache. include(EthCcache) diff --git a/libsolutil/JSON.cpp b/libsolutil/JSON.cpp index 055024edb..548fdfe0b 100644 --- a/libsolutil/JSON.cpp +++ b/libsolutil/JSON.cpp @@ -28,12 +28,6 @@ #include -#ifdef STRICT_NLOHMANN_JSON_VERSION_CHECK -static_assert( - (NLOHMANN_JSON_VERSION_MAJOR == 3) && (NLOHMANN_JSON_VERSION_MINOR == 11) && (NLOHMANN_JSON_VERSION_PATCH == 3), - "Unexpected nlohmann-json version. Expecting 3.11.3."); -#endif - namespace solidity::util { From 01a01eb2e0e7fc802d9d35ad89eb50fa2bdc21da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 30 Aug 2024 17:20:49 +0200 Subject: [PATCH 0302/1340] Clearer names and descriptions for advanced CMake options --- CMakeLists.txt | 17 +++++++++++++---- cmake/submodules.cmake | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a08e44da5..8b20f1d10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,10 +37,19 @@ option(SOLC_STATIC_STDLIBS "Link solc against static versions of libgcc and libs option(STRICT_Z3_VERSION "Use the latest version of Z3" ON) option(PEDANTIC "Enable extra warnings and pedantic build flags. Treat all warnings as errors." ON) option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser steps." OFF) -option(USE_SYSTEM_LIBRARIES "Use system libraries" OFF) -option(ONLY_BUILD_SOLIDITY_LIBRARIES "Only build solidity libraries" OFF) +option( + IGNORE_VENDORED_DEPENDENCIES + "Ignore libraries provided as submodules of the repository and allow CMake to look for \ +them in the typical locations, including system-wide dirs." + OFF +) +option( + ONLY_BUILD_SOLIDITY_LIBRARIES + "Only build library targets that can be statically linked against. Do not build executables or tests." + OFF +) mark_as_advanced(PROFILE_OPTIMIZER_STEPS) -mark_as_advanced(USE_SYSTEM_LIBRARIES) +mark_as_advanced(IGNORE_VENDORED_DEPENDENCIES) mark_as_advanced(ONLY_BUILD_SOLIDITY_LIBRARIES) # Setup cccache. @@ -48,7 +57,7 @@ include(EthCcache) # Let's find our dependencies include(EthDependencies) -if (NOT USE_SYSTEM_LIBRARIES) +if (NOT IGNORE_VENDORED_DEPENDENCIES) include(fmtlib) include(nlohmann-json) include(range-v3) diff --git a/cmake/submodules.cmake b/cmake/submodules.cmake index 099aceaa9..1ef55d289 100644 --- a/cmake/submodules.cmake +++ b/cmake/submodules.cmake @@ -1,5 +1,5 @@ macro(initialize_submodule SUBMODULE_PATH) - if(NOT USE_SYSTEM_LIBRARIES) + if(NOT IGNORE_VENDORED_DEPENDENCIES) file(GLOB submodule_contents "${CMAKE_SOURCE_DIR}/deps/${SUBMODULE_PATH}/*") if(submodule_contents) From 3184534fd66579f2fa21bd3896ac0f9b12ae887b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 2 Sep 2024 13:04:03 +0200 Subject: [PATCH 0303/1340] Improve names/descriptions of Z3-related CMake variables --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b20f1d10..656cec348 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,7 @@ endif() option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF) option(SOLC_STATIC_STDLIBS "Link solc against static versions of libgcc and libstdc++ on supported platforms" OFF) -option(STRICT_Z3_VERSION "Use the latest version of Z3" ON) +option(STRICT_Z3_VERSION "Require the exact version of Z3 solver expected by our test suite." ON) option(PEDANTIC "Enable extra warnings and pedantic build flags. Treat all warnings as errors." ON) option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser steps." OFF) option( @@ -94,15 +94,15 @@ configure_file("${PROJECT_SOURCE_DIR}/cmake/templates/license.h.in" include/lice include(EthOptions) configure_project(TESTS) -set(LATEST_Z3_VERSION "4.12.1") +set(TESTED_Z3_VERSION "4.12.1") set(MINIMUM_Z3_VERSION "4.8.16") find_package(Z3) if (${Z3_FOUND}) if (${STRICT_Z3_VERSION}) - if (NOT ("${Z3_VERSION_STRING}" VERSION_EQUAL ${LATEST_Z3_VERSION})) + if (NOT ("${Z3_VERSION_STRING}" VERSION_EQUAL ${TESTED_Z3_VERSION})) message( FATAL_ERROR - "SMTChecker tests require Z3 ${LATEST_Z3_VERSION} for all tests to pass.\n\ + "SMTChecker tests require Z3 ${TESTED_Z3_VERSION} for all tests to pass.\n\ Build with -DSTRICT_Z3_VERSION=OFF if you want to use a different version. \ You can also use -DUSE_Z3=OFF to build without Z3. In both cases use --no-smt when running tests." ) From 3b040385d0926be18eb6b3fdd2f0610d382d4619 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 3 Sep 2024 14:57:30 +0200 Subject: [PATCH 0304/1340] Disable failing import tests introduced by boost upgrade --- test/libsolidity/interface/FileReader.cpp | 14 +++++++++----- .../syntaxTests/imports/boost_filesystem_bug.sol | 5 ----- 2 files changed, 9 insertions(+), 10 deletions(-) delete mode 100644 test/libsolidity/syntaxTests/imports/boost_filesystem_bug.sol diff --git a/test/libsolidity/interface/FileReader.cpp b/test/libsolidity/interface/FileReader.cpp index dbb03c23f..2603c4c60 100644 --- a/test/libsolidity/interface/FileReader.cpp +++ b/test/libsolidity/interface/FileReader.cpp @@ -151,9 +151,11 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_unc_path) { // UNC paths start with // or \\ followed by a name. They are used for network shares on Windows. // On UNIX systems they are not supported but still treated in a special way. - BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/", resolveSymlinks), "//host/"); - BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/a/b", resolveSymlinks), "//host/a/b"); - BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/a/b/", resolveSymlinks), "//host/a/b/"); + + // TODO: Re-enable these once the boost 1.86 change has been addressed + //BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/", resolveSymlinks), "//host/"); + //BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/a/b", resolveSymlinks), "//host/a/b"); + //BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/a/b/", resolveSymlinks), "//host/a/b/"); #if defined(_WIN32) // On Windows an UNC path can also start with \\ instead of // @@ -187,10 +189,12 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_root_name_only) { // UNC paths BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//", resolveSymlinks), "//" / expectedWorkDir); - BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host", resolveSymlinks), "//host" / expectedWorkDir); + // TODO: Re-enable these once the boost 1.86 change has been addressed + //BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host", resolveSymlinks), "//host" / expectedWorkDir); // On UNIX systems root name is empty. - BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("", resolveSymlinks), expectedWorkDir); + // TODO: Re-enable these once the boost 1.86 change has been addressed + //BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("", resolveSymlinks), expectedWorkDir); #if defined(_WIN32) boost::filesystem::path driveLetter = boost::filesystem::current_path().root_name(); diff --git a/test/libsolidity/syntaxTests/imports/boost_filesystem_bug.sol b/test/libsolidity/syntaxTests/imports/boost_filesystem_bug.sol deleted file mode 100644 index 8dc8da068..000000000 --- a/test/libsolidity/syntaxTests/imports/boost_filesystem_bug.sol +++ /dev/null @@ -1,5 +0,0 @@ -==== Source: //// ==== -// This test used to throw due to a bug in boost::filesystem. -// See https://github.com/boostorg/filesystem/issues/176 -import "."; -// ---- From 3f6f2d3f90de9a4f506b196f9fac1d5909693d5f Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 3 Sep 2024 15:33:33 +0200 Subject: [PATCH 0305/1340] Fix Yul stack output using standard json in the presence of warnings. --- Changelog.md | 1 + libsolidity/interface/StandardCompiler.cpp | 26 ++++---- libyul/YulStack.h | 1 + .../standard_yul_output_warning/input.json | 20 ++++++ .../standard_yul_output_warning/output.json | 61 +++++++++++++++++++ 5 files changed, 95 insertions(+), 14 deletions(-) create mode 100644 test/cmdlineTests/standard_yul_output_warning/input.json create mode 100644 test/cmdlineTests/standard_yul_output_warning/output.json diff --git a/Changelog.md b/Changelog.md index 04bfa9295..299a7a5bd 100644 --- a/Changelog.md +++ b/Changelog.md @@ -32,6 +32,7 @@ Bugfixes: * SMTChecker: Fix formatting of unary minus expressions in invariants. * SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine. * SMTChecker: Fix SMT logic error when assigning to an array of contracts or functions. + * Standard JSON Interface: For Yul input, properly produce output artifacts in case of warnings. * TypeChecker: Fix segfault when assigning nested tuple to tuple. * Yul IR Code Generation: Deterministic order of Yul subobjects. * Yul Optimizer: Fix Yul source locations always referring to unoptimized source, even in optimized outputs. diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 385e48c22..0194aa937 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1620,7 +1620,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) std::string const& sourceContents = _inputsAndSettings.sources.begin()->second; // Inconsistent state - stop here to receive error reports from users - if (!stack.parseAndAnalyze(sourceName, sourceContents) && stack.errors().empty()) + if (!stack.parseAndAnalyze(sourceName, sourceContents) && !stack.hasErrors()) { output["errors"].emplace_back(formatError( Error::Type::InternalCompilerError, @@ -1630,22 +1630,20 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) return output; } - if (!stack.errors().empty()) + for (auto const& error: stack.errors()) { - for (auto const& error: stack.errors()) - { - auto err = std::dynamic_pointer_cast(error); + auto err = std::dynamic_pointer_cast(error); - output["errors"].emplace_back(formatErrorWithException( - stack, - *error, - err->type(), - "general", - "" - )); - } - return output; + output["errors"].emplace_back(formatErrorWithException( + stack, + *error, + err->type(), + "general", + "" + )); } + if (stack.hasErrors()) + return output; std::string contractName = stack.parserResult()->name; diff --git a/libyul/YulStack.h b/libyul/YulStack.h index 746e0c49f..0dc90baf8 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -134,6 +134,7 @@ class YulStack: public langutil::CharStreamProvider /// @returns the errors generated during parsing, analysis (and potentially assembly). langutil::ErrorList const& errors() const { return m_errors; } + bool hasErrors() const { return m_errorReporter.hasErrors(); } /// Pretty-print the input after having parsed it. std::string print( diff --git a/test/cmdlineTests/standard_yul_output_warning/input.json b/test/cmdlineTests/standard_yul_output_warning/input.json new file mode 100644 index 000000000..f6f519d82 --- /dev/null +++ b/test/cmdlineTests/standard_yul_output_warning/input.json @@ -0,0 +1,20 @@ +{ + "language": "Yul", + "sources": + { + "C": + { + "content": "{ let x := tload(0) tstore(add(x, 1), 0) }" + } + }, + "settings": + { + "outputSelection": + { + "*": { + "*": ["evm.bytecode", "evm.assembly", "irOptimized"], + "": [ "*" ] + } + } + } +} diff --git a/test/cmdlineTests/standard_yul_output_warning/output.json b/test/cmdlineTests/standard_yul_output_warning/output.json new file mode 100644 index 000000000..3234be181 --- /dev/null +++ b/test/cmdlineTests/standard_yul_output_warning/output.json @@ -0,0 +1,61 @@ +{ + "contracts": { + "C": { + "object": { + "evm": { + "assembly": " /* \"C\":99:100 */ + 0x00 + /* \"C\":95:96 */ + 0x01 + /* \"C\":60:68 */ + dup2 + tload + /* \"C\":88:97 */ + add + /* \"C\":81:101 */ + tstore + /* \"C\":27:117 */ + stop +", + "bytecode": { + "functionDebugData": {}, + "generatedSources": [], + "linkReferences": {}, + "object": "", + "opcodes":"", + "sourceMap":"" + } + }, + "irOptimized": "object \"object\" { + code { + { + let x := tload(0) + tstore(add(x, 1), 0) + } + } +} +" + } + } + }, + "errors": [ + { + "component": "general", + "formattedMessage": "Warning: Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. + --> C:1:21: + | +1 | { let x := tload(0) tstore(add(x, 1), 0) } + | ^^^^^^ + +", + "message": "Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe.", + "severity": "warning", + "sourceLocation": { + "end": 26, + "file": "C", + "start": 20 + }, + "type": "Warning" + } + ] +} From 3e5060c5a45ab92e7bcd3a50e0a481e016449c5d Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 3 Sep 2024 13:46:07 +0200 Subject: [PATCH 0306/1340] Remove mantic from release PPA script (obsolete). --- scripts/deps-ppa/static_z3.sh | 2 +- scripts/release_ppa.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/deps-ppa/static_z3.sh b/scripts/deps-ppa/static_z3.sh index 016cd5d21..9e273188c 100755 --- a/scripts/deps-ppa/static_z3.sh +++ b/scripts/deps-ppa/static_z3.sh @@ -41,7 +41,7 @@ sourcePPAConfig # Sanity check checkDputEntries "\[cpp-build-deps\]" -DISTRIBUTIONS="focal jammy mantic noble" +DISTRIBUTIONS="focal jammy noble oracular" for distribution in $DISTRIBUTIONS do diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 3b7c8347c..64a81f542 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -68,7 +68,7 @@ packagename=solc # This needs to be a still active release static_build_distribution=focal -DISTRIBUTIONS="focal jammy mantic noble" +DISTRIBUTIONS="focal jammy noble oracular" if is_release then From b92cabd44be5f1a0dc3ce8fb79eb0408d214556f Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 3 Sep 2024 15:05:15 +0200 Subject: [PATCH 0307/1340] Sort changelog for the upcoming release --- Changelog.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index 299a7a5bd..8802f7b38 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,22 +7,22 @@ Language Features: Compiler Features: - * Command Line Interface: Do not perform IR optimization when only unoptimized IR is requested. * Commandline Interface: Add ``--transient-storage-layout`` output. + * Commandline Interface: Allow the use of ``--asm-json`` output option in assembler mode to export EVM assembly of the contracts in JSON format. + * Commandline Interface: Do not perform IR optimization when only unoptimized IR is requested. * Constant Optimizer: Uses ``PUSH0`` if supported by the selected evm version. * Error Reporting: Unimplemented features are now properly reported as errors instead of being handled as if they were bugs. * EVM: Support for the EVM version "Prague". * Peephole Optimizer: ``PUSH0``, when supported, is duplicated explicitly instead of using ``DUP1``. - * Peephole optimizer: Remove identical code snippets that terminate the control flow if they occur one after another. + * Peephole Optimizer: Remove identical code snippets that terminate the control flow if they occur one after another. * SMTChecker: Add CHC engine check for underflow and overflow in unary minus operation. * SMTChecker: Replace CVC4 as a possible BMC backend with cvc5. - * Standard JSON Interface: Do not perform IR optimization when only unoptimized IR is requested. * Standard JSON Interface: Add ``transientStorageLayout`` output. + * Standard JSON Interface: Do not perform IR optimization when only unoptimized IR is requested. * Yul: Drop the deprecated typed Yul dialect that was only accessible via ``--yul`` in the CLI. * Yul: The presence of types in untyped Yul dialects is now a parser error. * Yul Optimizer: Caching of optimized IR to speed up optimization of contracts with bytecode dependencies. * Yul Optimizer: The optimizer now treats some previously unrecognized identical literals as identical. - * Commandline Interface: Allow the use of ``--asm-json`` output option in assembler mode to export EVM assembly of the contracts in JSON format. Bugfixes: From 830ec2c4190f6a1ea4960def64edd1911c68ef3b Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 4 Sep 2024 09:03:36 +0200 Subject: [PATCH 0308/1340] Set changelog release date --- Changelog.md | 2 +- docs/bugs_by_version.json | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 8802f7b38..01abe1af6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.8.27 (unreleased) +### 0.8.27 (2024-09-04) Language Features: * Accept declarations of state variables with ``transient`` data location (parser support only, no code generation yet). diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 037a36341..f9913d812 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1898,6 +1898,10 @@ "bugs": [], "released": "2024-05-21" }, + "0.8.27": { + "bugs": [], + "released": "2024-09-04" + }, "0.8.3": { "bugs": [ "FullInlinerNonExpressionSplitArgumentEvaluationOrder", From 7e5836a65ec3354864d5a936e1bc42d78e24186e Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 4 Sep 2024 09:14:49 +0200 Subject: [PATCH 0309/1340] Set version to 0.8.28 --- CMakeLists.txt | 2 +- Changelog.md | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 656cec348..7770d29e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.27") +set(PROJECT_VERSION "0.8.28") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index 01abe1af6..0ecb280c7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,14 @@ +### 0.8.28 (unreleased) + +Language Features: + + +Compiler Features: + + +Bugfixes: + + ### 0.8.27 (2024-09-04) Language Features: From a298438fbb296e4a65aa8e179ac9855ded915a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 2 Sep 2024 18:38:48 +0200 Subject: [PATCH 0310/1340] We no longer use a `release` branch --- scripts/docker_deploy_manual.sh | 2 +- scripts/release_ppa.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index 48d021ff0..11c0b8d3a 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -21,7 +21,7 @@ cd solidity commithash=$(git rev-parse --short=8 HEAD) echo -n "$commithash" > commit_hash.txt version=$("$(dirname "$0")/get_version.sh") -if [ "$branch" = "release" ] || [ "$branch" = v"$version" ] +if [ "$branch" = v"$version" ] then echo -n > prerelease.txt else diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 64a81f542..773c43cc9 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -6,7 +6,7 @@ ## You can pass a branch name as argument to this script (which, if no argument is given, ## will default to "develop"). ## -## If the given branch is "release", the resulting package will be uploaded to +## If the given branch matches a release version tag, the resulting package will be uploaded to ## ethereum/ethereum PPA, or ethereum/ethereum-dev PPA otherwise. ## ## It will clone the Solidity git from github, determine the version, From ee08a758dc7d857704d533413f174e4e565216e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 2 Sep 2024 19:27:02 +0200 Subject: [PATCH 0311/1340] docker_deploy_manual.sh: Make script more configurable to allow testing it in CI --- scripts/docker_deploy_manual.sh | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index 11c0b8d3a..67f5e6b95 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -2,13 +2,25 @@ set -e -if [ -z "$1" ] -then - echo "Usage: $0 " - exit 1 -fi +REPO_ROOT="$(dirname "$0")/.." +# shellcheck source=scripts/common.sh +source "${REPO_ROOT}/scripts/common.sh" + image="ethereum/solc" + +if (( $# < 1 || $# > 3 )); then + fail "Usage: $0 [repo URL] [--no-push]" +fi + branch="$1" +repo_url="${2:-https://github.com/ethereum/solidity.git}" + +if (( $# >= 3 )); then + [[ $3 == --no-push ]] || fail "Invalid flag: $3. Expected --no-push." + publish=false +else + publish=true +fi #docker login @@ -16,7 +28,7 @@ DIR=$(mktemp -d) ( cd "$DIR" -git clone --recursive --depth 2 https://github.com/ethereum/solidity.git -b "$branch" +git clone --recursive --depth 2 "$repo_url" -b "$branch" cd solidity commithash=$(git rev-parse --short=8 HEAD) echo -n "$commithash" > commit_hash.txt @@ -31,7 +43,7 @@ fi function tag_and_push { docker tag "$image:$1" "$image:$2" - docker push "$image:$2" + [[ $publish == false ]] || docker push "$image:$2" } rm -rf .git From 7cca807d218aead77a4c1960d28a5b1dd18e2a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 2 Sep 2024 19:27:11 +0200 Subject: [PATCH 0312/1340] b_alpine_docker nightly job --- .circleci/config.yml | 19 +++++++++++++++++++ scripts/docker_deploy_manual.sh | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b5d0b76d6..710d275d4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1830,6 +1830,22 @@ jobs: - matrix_notify_failure_unless_pr - matrix_notify_release_unless_pr + b_alpine_docker: + <<: *base_cimg_small + steps: + - setup_remote_docker: + # Always build from scratch to use current packages. + # This job is only meant to run nightly so build time is not an issue. + docker_layer_caching: false + - checkout + - run: + name: Build and tag the container + command: scripts/docker_deploy_manual.sh develop "file://$PWD" --no-push + - run: + name: Smoke test + command: docker run --pull=never ethereum/solc:build-alpine --version + - matrix_notify_failure_unless_pr + workflows: version: 2 @@ -2009,6 +2025,9 @@ workflows: - b_ubu: *requires_nothing - t_ubu_soltest_deprecated_evm_versions: *requires_b_ubu + # Build in a Docker container (on Alpine Linux) + - b_alpine_docker: *requires_nothing + nightly-ossfuzz: triggers: diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index 67f5e6b95..232fcbe44 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -28,7 +28,7 @@ DIR=$(mktemp -d) ( cd "$DIR" -git clone --recursive --depth 2 "$repo_url" -b "$branch" +git clone --recursive --depth 2 "$repo_url" -b "$branch" solidity cd solidity commithash=$(git rev-parse --short=8 HEAD) echo -n "$commithash" > commit_hash.txt From 32b8b41351c019bec6ea51c984edc18c5fe4bf4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 2 Sep 2024 20:19:46 +0200 Subject: [PATCH 0313/1340] docker_deploy_manual.sh: Switch to plain docker build output - For some reason it defaults to `tty` on CircleCI which is very spammy and makes logs unreadable. --- scripts/docker_deploy_manual.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index 232fcbe44..8753d59c9 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -47,13 +47,13 @@ function tag_and_push } rm -rf .git -docker build -t "$image":build -f scripts/Dockerfile . +docker build -t "$image":build -f scripts/Dockerfile . --progress plain tmp_container=$(docker create "$image":build sh) # Alpine image mkdir -p upload docker cp "${tmp_container}":/usr/bin/solc upload/solc-static-linux -docker build -t "$image":build-alpine -f scripts/Dockerfile_alpine . +docker build -t "$image":build-alpine -f scripts/Dockerfile_alpine . --progress plain if [ "$branch" = "develop" ] then From 7f582e4265ed2bcad06415eeaf0d5fa20f1c4ab2 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 5 Sep 2024 08:58:18 +0200 Subject: [PATCH 0314/1340] Add ContiguousDisjointSet datastructure --- libsolutil/CMakeLists.txt | 2 + libsolutil/DisjointSet.cpp | 109 ++++++++++++++++++++++++++++++++ libsolutil/DisjointSet.h | 66 +++++++++++++++++++ test/CMakeLists.txt | 1 + test/libsolutil/DisjointSet.cpp | 103 ++++++++++++++++++++++++++++++ 5 files changed, 281 insertions(+) create mode 100644 libsolutil/DisjointSet.cpp create mode 100644 libsolutil/DisjointSet.h create mode 100644 test/libsolutil/DisjointSet.cpp diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index a1e9559ed..6ece23805 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -8,6 +8,8 @@ set(sources CommonIO.cpp CommonIO.h cxx20.h + DisjointSet.cpp + DisjointSet.h DominatorFinder.h Exceptions.cpp Exceptions.h diff --git a/libsolutil/DisjointSet.cpp b/libsolutil/DisjointSet.cpp new file mode 100644 index 000000000..43d3bfa18 --- /dev/null +++ b/libsolutil/DisjointSet.cpp @@ -0,0 +1,109 @@ +/* + 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 + +#include + +#include + +#include + +using namespace solidity::util; + +ContiguousDisjointSet::ContiguousDisjointSet(size_t const _numNodes): + m_parents(_numNodes), + m_neighbors(_numNodes), + m_sizes(_numNodes, static_cast(1)), + m_numSets(_numNodes) +{ + // each is their own neighbor and parent + std::iota(m_parents.begin(), m_parents.end(), 0); + std::iota(m_neighbors.begin(), m_neighbors.end(), 0); +} + +size_t ContiguousDisjointSet::numSets() const { return m_numSets; } + +ContiguousDisjointSet::value_type ContiguousDisjointSet::find(value_type const _element) const +{ + solAssert(_element < m_parents.size()); + // path halving + value_type rootElement = _element; + while (rootElement != m_parents[rootElement]) + { + m_parents[rootElement] = m_parents[m_parents[rootElement]]; + rootElement = m_parents[rootElement]; + } + return rootElement; +} + +void ContiguousDisjointSet::merge(value_type const _x, value_type const _y, bool const _mergeBySize) +{ + auto xRoot = find(_x); + auto yRoot = find(_y); + + if (xRoot == yRoot) + return; // we're done, nothing to merge here + + // if merge by size: merge smaller (yRoot) into larger (xRoot) subset; + // otherwise if _x is the representative of subset(_x), it will stay representative + if (_mergeBySize && m_sizes[xRoot] < m_sizes[yRoot]) + std::swap(xRoot, yRoot); + + m_parents[yRoot] = xRoot; + m_sizes[xRoot] += m_sizes[yRoot]; + std::swap(m_neighbors[xRoot], m_neighbors[yRoot]); + --m_numSets; +} + +bool ContiguousDisjointSet::sameSubset(value_type const _x, value_type const _y) const +{ + return find(_x) == find(_y); +} + +ContiguousDisjointSet::size_type ContiguousDisjointSet::sizeOfSubset(value_type const _x) const +{ + return m_sizes[find(_x)]; +} + +std::set ContiguousDisjointSet::subset(value_type const _x) const +{ + solAssert(_x < m_parents.size()); + std::set result{_x}; + value_type neighbor = m_neighbors[_x]; + while (neighbor != _x) + { + result.insert(neighbor); + neighbor = m_neighbors[neighbor]; + } + return result; +} + +std::vector> ContiguousDisjointSet::subsets() const +{ + std::vector> result; + std::vector visited(m_parents.size(), false); + for (value_type x = 0; x < m_parents.size(); ++x) + { + auto xRoot = find(x); + if (!visited[xRoot]) + { + result.push_back(subset(xRoot)); + visited[xRoot] = true; + } + } + return result; +} diff --git a/libsolutil/DisjointSet.h b/libsolutil/DisjointSet.h new file mode 100644 index 000000000..02792cbe6 --- /dev/null +++ b/libsolutil/DisjointSet.h @@ -0,0 +1,66 @@ +/* + 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 + +#pragma once + +#include +#include +#include + +namespace solidity::util +{ + +/// Implementation of the Disjoint set data structure [1], also called union-set, with path-halving [2]. +/// This implementation assumes that each set element is identified with an element in a iota range (hence contiguous). +/// +/// [1] https://en.wikipedia.org/wiki/Disjoint-set_data_structure +/// [2] Tarjan, Robert E., and Jan Van Leeuwen. "Worst-case analysis of set union algorithms." +/// Journal of the ACM (JACM) 31.2 (1984): 245-281. +class ContiguousDisjointSet +{ +public: + using size_type = size_t; + using value_type = size_t; + + /// Constructs a new disjoint set datastructure with `_numNodes` elements and each element in its own individual set + explicit ContiguousDisjointSet(size_t _numNodes); + + size_type numSets() const; + + /// finds one representative for a set that contains `_element` + value_type find(value_type _element) const; + + /// joins the two sets containing `_x` and `_y`, returns true if the sets were disjoint, otherwise false + void merge(value_type _x, value_type _y, bool _mergeBySize=true); + + bool sameSubset(value_type _x, value_type _y) const; + + size_type sizeOfSubset(value_type _x) const; + + std::set subset(value_type _x) const; + + std::vector> subsets() const; + +private: + std::vector mutable m_parents; // mutable for path compression, doesn't change semantic state + std::vector m_neighbors; + std::vector m_sizes; + size_type m_numSets; +}; + +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d3498965d..da115f0d4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -31,6 +31,7 @@ set(libsolutil_sources libsolutil/Checksum.cpp libsolutil/CommonData.cpp libsolutil/CommonIO.cpp + libsolutil/DisjointSet.cpp libsolutil/DominatorFinderTest.cpp libsolutil/FixedHash.cpp libsolutil/FunctionSelector.cpp diff --git a/test/libsolutil/DisjointSet.cpp b/test/libsolutil/DisjointSet.cpp new file mode 100644 index 000000000..338138b6a --- /dev/null +++ b/test/libsolutil/DisjointSet.cpp @@ -0,0 +1,103 @@ +/* + 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 . +*/ +/** + * Unit tests for DisjointSet. + */ + +#include + +#include + +namespace solidity::util::test +{ + +BOOST_AUTO_TEST_SUITE(DisjointSetTest) + +BOOST_AUTO_TEST_CASE(full_union) +{ + ContiguousDisjointSet ds(10); + for (size_t i = 1; i < 10; ++i) + { + BOOST_CHECK(!ds.sameSubset(0, i)); + ds.merge(0, i); + BOOST_CHECK(ds.sameSubset(0, i)); + } + BOOST_CHECK_EQUAL(ds.numSets(), 1); + auto const& subsets = ds.subsets(); + BOOST_CHECK_EQUAL(subsets.size(), 1); + std::set fullSet{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + BOOST_CHECK_EQUAL_COLLECTIONS(subsets[0].begin(), subsets[0].end(), fullSet.begin(), fullSet.end()); + + for (size_t i = 1; i < 10; ++i) BOOST_CHECK_EQUAL(ds.find(0), ds.find(i)); +} + +BOOST_AUTO_TEST_CASE(pairs) +{ + ContiguousDisjointSet ds(10); + BOOST_CHECK_EQUAL(ds.numSets(), 10); + BOOST_CHECK_EQUAL(ds.subsets().size(), 10); + + auto const checkPair = [&](size_t expectedNumSubsets, size_t x, size_t y) + { + BOOST_CHECK_EQUAL(ds.numSets(), expectedNumSubsets); + BOOST_CHECK_EQUAL(ds.subsets().size(), expectedNumSubsets); + BOOST_CHECK(ds.sameSubset(x, y)); + auto const subset = ds.subset(x); + std::set subsetRef{x, y}; + BOOST_CHECK_EQUAL_COLLECTIONS(subset.begin(), subset.end(), subsetRef.begin(), subsetRef.end()); + }; + + ds.merge(5, 3); + checkPair(9, 5, 3); + + ds.merge(1, 6); + checkPair(8, 1, 6); + + ds.merge(0, 2); + checkPair(7, 0, 2); + + ds.merge(1, 5); + BOOST_CHECK_EQUAL(ds.sizeOfSubset(3), 4); + + ds.merge(1, 0); + + // now we should have a subset with {0, 1, 2, 3, 5, 6} + std::set subsetRef{0, 1, 2, 3, 5, 6}; + BOOST_CHECK_EQUAL(ds.sizeOfSubset(6), subsetRef.size()); + auto const subset = ds.subset(2); + BOOST_CHECK_EQUAL_COLLECTIONS(subset.begin(), subset.end(), subsetRef.begin(), subsetRef.end()); +} + +BOOST_AUTO_TEST_CASE(merge_with_fixed_representative) +{ + ContiguousDisjointSet ds(10); + ds.merge(5, 3, false); + BOOST_CHECK_EQUAL(ds.find(5), 5); + ds.merge(1, 2); + ds.merge(7, 8); + ds.merge(0, 9); + ds.merge(5, 1, false); + BOOST_CHECK_EQUAL(ds.find(5), 5); + ds.merge(5, 0, false); + BOOST_CHECK_EQUAL(ds.find(5), 5); + ds.merge(5, 7, false); + BOOST_CHECK_EQUAL(ds.find(5), 5); +} + +BOOST_AUTO_TEST_SUITE_END() + +} From fc2e90fdda623768d9d41b6a1ccd8a9995e479c6 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 9 Sep 2024 10:13:52 +0200 Subject: [PATCH 0315/1340] Add topological sort implementation for forward SSACFG --- libyul/CMakeLists.txt | 2 + libyul/backends/evm/SSACFGTopologicalSort.cpp | 93 +++++++++++++++++++ libyul/backends/evm/SSACFGTopologicalSort.h | 60 ++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 libyul/backends/evm/SSACFGTopologicalSort.cpp create mode 100644 libyul/backends/evm/SSACFGTopologicalSort.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index c0082f5d6..704e04921 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -65,6 +65,8 @@ add_library(yul backends/evm/NoOutputAssembly.cpp backends/evm/OptimizedEVMCodeTransform.cpp backends/evm/OptimizedEVMCodeTransform.h + backends/evm/SSACFGTopologicalSort.cpp + backends/evm/SSACFGTopologicalSort.h backends/evm/SSAControlFlowGraph.h backends/evm/SSAControlFlowGraphBuilder.cpp backends/evm/SSAControlFlowGraphBuilder.h diff --git a/libyul/backends/evm/SSACFGTopologicalSort.cpp b/libyul/backends/evm/SSACFGTopologicalSort.cpp new file mode 100644 index 000000000..e0370aa27 --- /dev/null +++ b/libyul/backends/evm/SSACFGTopologicalSort.cpp @@ -0,0 +1,93 @@ +/* + 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 + +#include + +using namespace solidity::yul; + +ForwardSSACFGTopologicalSort::ForwardSSACFGTopologicalSort(SSACFG const& _cfg): + m_cfg(_cfg), + m_explored(m_cfg.numBlocks(), false), + m_reversedPostOrder(m_cfg.numBlocks(), std::numeric_limits::max()), + m_preOrder(m_cfg.numBlocks(), std::numeric_limits::max()), + m_maxSubtreePreOrder(m_cfg.numBlocks(), 0), + m_predecessors(m_cfg.numBlocks()) +{ + for (size_t id = 0; id < m_cfg.numBlocks(); ++id) + { + if (!m_explored[id]) + dfs(id); + } + std::reverse(m_reversedPostOrder.begin(), m_reversedPostOrder.end()); + + for (auto const& [v1, v2]: m_potentialBackEdges) + if (ancestor(v2, v1)) + m_backEdgeTargets.insert(v2); +} + +void ForwardSSACFGTopologicalSort::dfs(size_t const _vertex) { + yulAssert(!m_explored[_vertex]); + m_explored[_vertex] = true; + m_preOrder[_vertex] = m_currentNode++; + m_maxSubtreePreOrder[_vertex] = m_preOrder[_vertex]; + + m_cfg.block(SSACFG::BlockId{_vertex}).forEachExit([&](SSACFG::BlockId const& _exitBlock){ + m_predecessors[_exitBlock.value].insert(_vertex); + if (!m_explored[_exitBlock.value]) + { + dfs(_exitBlock.value); + m_maxSubtreePreOrder[_vertex] = std::max(m_maxSubtreePreOrder[_vertex], m_maxSubtreePreOrder[_exitBlock.value]); + } + else + m_potentialBackEdges.emplace_back(_vertex, _exitBlock.value); + }); + + m_reversedPostOrder[m_preOrder[_vertex]] = _vertex; +} + +std::vector const& ForwardSSACFGTopologicalSort::sortedBlocks() const { return m_reversedPostOrder; } +std::vector const& ForwardSSACFGTopologicalSort::preOrder() const { return m_preOrder; } +std::vector const& ForwardSSACFGTopologicalSort::reversedPostOrder() const { return m_reversedPostOrder; } +std::vector const& ForwardSSACFGTopologicalSort::maxSubtreePreOrder() const { return m_maxSubtreePreOrder; } +std::set const& ForwardSSACFGTopologicalSort::backEdgeTargets() const { return m_backEdgeTargets; } +std::vector> const& ForwardSSACFGTopologicalSort::predecessors() const { return m_predecessors; } +SSACFG const& ForwardSSACFGTopologicalSort::cfg() const { return m_cfg; } + +bool ForwardSSACFGTopologicalSort::ancestor(size_t const _block1, size_t const _block2) const { + yulAssert(_block1 < m_preOrder.size()); + yulAssert(_block2 < m_preOrder.size()); + + auto const preOrderIndex1 = m_preOrder[_block1]; + auto const preOrderIndex2 = m_preOrder[_block2]; + + bool const node1VisitedBeforeNode2 = preOrderIndex1 <= preOrderIndex2; + bool const node2InSubtreeOfNode1 = preOrderIndex2 <= m_maxSubtreePreOrder[_block1]; + return node1VisitedBeforeNode2 && node2InSubtreeOfNode1; +} + +bool ForwardSSACFGTopologicalSort::backEdge(SSACFG::BlockId const& _block1, SSACFG::BlockId const& _block2) const +{ + if (ancestor(_block2.value, _block1.value)) + { + // check that block1 -> block2 is indeed an edge in the cfg + bool isEdge = false; + m_cfg.block(_block1).forEachExit([&_block2, &isEdge](SSACFG::BlockId const& _exit) { isEdge |= _block2 == _exit; }); + return isEdge; + } + return false; +} diff --git a/libyul/backends/evm/SSACFGTopologicalSort.h b/libyul/backends/evm/SSACFGTopologicalSort.h new file mode 100644 index 000000000..ec62eb013 --- /dev/null +++ b/libyul/backends/evm/SSACFGTopologicalSort.h @@ -0,0 +1,60 @@ +/* + 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 + +#pragma once + +#include + +#include +#include +#include + +namespace solidity::yul +{ + +/// Performs a topological sort on the forward CFG (no back/cross edges) +class ForwardSSACFGTopologicalSort +{ +public: + explicit ForwardSSACFGTopologicalSort(SSACFG const& _cfg); + + std::vector const& sortedBlocks() const; + std::vector const& preOrder() const; + std::vector const& reversedPostOrder() const; + std::vector const& maxSubtreePreOrder() const; + std::set const& backEdgeTargets() const; + std::vector> const& predecessors() const; + SSACFG const& cfg() const; + bool ancestor(size_t _block1, size_t _block2) const; + bool backEdge(SSACFG::BlockId const& _block1, SSACFG::BlockId const& _block2) const; + +private: + void dfs(size_t _vertex); + + SSACFG const& m_cfg; + + size_t m_currentNode {0}; + std::vector m_explored{}; + std::vector m_reversedPostOrder{}; + std::vector m_preOrder{}; + std::vector m_maxSubtreePreOrder{}; + std::vector> m_potentialBackEdges{}; + std::set m_backEdgeTargets{}; + std::vector> m_predecessors{}; +}; +} From 13fe5ba98c763ea9e6ed6bb747ee101fdedff679 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 17 Jun 2024 22:22:34 -0300 Subject: [PATCH 0316/1340] Replace errors/warning/info empty check with proper errors only check --- liblangutil/ErrorReporter.h | 6 ++++++ liblangutil/Exceptions.h | 5 +++++ libsolidity/analysis/DeclarationTypeChecker.cpp | 2 +- libsolidity/codegen/CompilerContext.cpp | 6 +++--- libsolidity/interface/StandardCompiler.cpp | 9 +-------- libyul/YulStack.cpp | 2 +- test/libsolidity/InlineAssembly.cpp | 4 ++-- test/libyul/Common.cpp | 2 +- test/tools/yulopti.cpp | 4 ++-- test/tools/yulrun.cpp | 2 +- tools/yulPhaser/Program.cpp | 4 ++-- 11 files changed, 25 insertions(+), 21 deletions(-) diff --git a/liblangutil/ErrorReporter.h b/liblangutil/ErrorReporter.h index d7e280ed9..989cc4d5e 100644 --- a/liblangutil/ErrorReporter.h +++ b/liblangutil/ErrorReporter.h @@ -130,6 +130,12 @@ class ErrorReporter return m_errorCount > 0; } + /// @returns true if there is any error, warning or info. + bool hasErrorsWarningsOrInfos() const + { + return m_errorCount + m_warningCount + m_infoCount > 0; + } + /// @returns the number of errors (ignores warnings and infos). unsigned errorCount() const { diff --git a/liblangutil/Exceptions.h b/liblangutil/Exceptions.h index b0701f999..c441a6d2f 100644 --- a/liblangutil/Exceptions.h +++ b/liblangutil/Exceptions.h @@ -256,6 +256,11 @@ class Error: virtual public util::Exception return false; } + static bool hasErrorsWarningsOrInfos(ErrorList const& _list) + { + return !_list.empty(); + } + static std::string formatErrorSeverity(Severity _severity) { switch (_severity) diff --git a/libsolidity/analysis/DeclarationTypeChecker.cpp b/libsolidity/analysis/DeclarationTypeChecker.cpp index bdf023c5c..f5db21100 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.cpp +++ b/libsolidity/analysis/DeclarationTypeChecker.cpp @@ -329,7 +329,7 @@ void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName) Type const* baseType = _typeName.baseType().annotation().type; if (!baseType) { - solAssert(!m_errorReporter.errors().empty(), ""); + solAssert(m_errorReporter.hasErrors(), ""); return; } diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 2e94e9f0b..83b4589fe 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -473,7 +473,7 @@ void CompilerContext::appendInlineAssembly( dialect, identifierAccess.resolve ).analyze(parserResult->root()); - if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) + if (!parserResult || errorReporter.hasErrorsWarningsOrInfos() || !analyzerResult) reportError("Invalid assembly generated by code generator."); std::shared_ptr toBeAssembledAST = parserResult; @@ -513,10 +513,10 @@ void CompilerContext::appendInlineAssembly( m_generatedYulUtilityCode = _assembly; } - if (!errorReporter.errors().empty()) + if (errorReporter.hasErrorsWarningsOrInfos()) reportError("Failed to analyze inline assembly block."); - solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block."); + solAssert(!errorReporter.hasErrorsWarningsOrInfos(), "Failed to analyze inline assembly block."); yul::CodeGenerator::assemble( toBeAssembledAST->root(), analysisInfo, diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 0194aa937..7271cce8b 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1621,14 +1621,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) // Inconsistent state - stop here to receive error reports from users if (!stack.parseAndAnalyze(sourceName, sourceContents) && !stack.hasErrors()) - { - output["errors"].emplace_back(formatError( - Error::Type::InternalCompilerError, - "general", - "No error reported, but compilation failed." - )); - return output; - } + solAssert(false, "No error reported, but parsing/analysis failed."); for (auto const& error: stack.errors()) { diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index bd2c73906..01eb5b738 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -64,7 +64,7 @@ bool YulStack::parse(std::string const& _sourceName, std::string const& _source) reportUnimplementedFeatureError(_error); } - if (m_errorReporter.errors().empty()) + if (!m_errorReporter.hasErrors()) m_stackState = Parsed; return m_stackState == Parsed; diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index a0aa39be4..b3993e39f 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -131,7 +131,7 @@ void parsePrintCompare(std::string const& _source, bool _canWarn = false) if (_canWarn) BOOST_REQUIRE(!Error::containsErrors(stack.errors())); else - BOOST_REQUIRE(stack.errors().empty()); + BOOST_REQUIRE(!Error::hasErrorsWarningsOrInfos(stack.errors())); std::string expectation = "object \"object\" {\n code " + boost::replace_all_copy(_source, "\n", "\n ") + "\n}\n"; BOOST_CHECK_EQUAL(stack.print(), expectation); } @@ -219,7 +219,7 @@ BOOST_AUTO_TEST_CASE(print_string_literal_unicode) DebugInfoSelection::None() ); BOOST_REQUIRE(stack.parseAndAnalyze("", source)); - BOOST_REQUIRE(stack.errors().empty()); + BOOST_REQUIRE(!Error::hasErrorsWarningsOrInfos(stack.errors())); BOOST_CHECK_EQUAL(stack.print(), parsed); std::string parsedInner = "{ let x := \"\\xe1\\xae\\xac\" }"; diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 8980adcb1..7640e4a5d 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -61,7 +61,7 @@ std::pair, std::shared_ptr> yul solidity::frontend::OptimiserSettings::minimal(), DebugInfoSelection::All() ); - if (!stack.parseAndAnalyze("", _source) || !stack.errors().empty()) + if (!stack.parseAndAnalyze("", _source) || Error::hasErrorsWarningsOrInfos(stack.errors())) BOOST_FAIL("Invalid source."); return std::make_pair(stack.parserResult()->code(), stack.parserResult()->analysisInfo); } diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 891f39c43..13375f827 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -91,7 +91,7 @@ class YulOpti try { auto ast = yul::Parser(errorReporter, m_dialect).parse(_charStream); - if (!m_astRoot || !errorReporter.errors().empty()) + if (!m_astRoot || errorReporter.hasErrors()) { std::cerr << "Error parsing source." << std::endl; printErrors(_charStream, errors); @@ -104,7 +104,7 @@ class YulOpti errorReporter, m_dialect ); - if (!analyzer.analyze(*m_astRoot) || !errorReporter.errors().empty()) + if (!analyzer.analyze(*m_astRoot) || errorReporter.hasErrors()) { std::cerr << "Error analyzing source." << std::endl; printErrors(_charStream, errors); diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index c3a7fb19f..e857c2664 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -65,7 +65,7 @@ std::pair, std::shared_ptr> parse(st ); if (stack.parseAndAnalyze("--INPUT--", _source)) { - yulAssert(stack.errors().empty(), "Parsed successfully but had errors."); + yulAssert(!Error::hasErrorsWarningsOrInfos(stack.errors()), "Parsed successfully but had errors."); return make_pair(stack.parserResult()->code(), stack.parserResult()->analysisInfo); } else diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index bb9eebc4b..57e1bf2b9 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -122,7 +122,7 @@ std::variant, ErrorList> Program::parseObject(Dialect const ObjectParser parser(errorReporter, _dialect); std::shared_ptr object = parser.parse(scanner, false); - if (object == nullptr || !errorReporter.errors().empty()) + if (object == nullptr || errorReporter.hasErrors()) // NOTE: It's possible to get errors even if the returned object is non-null. // For example when there are errors in a nested object. return errors; @@ -165,7 +165,7 @@ std::variant, ErrorList> Program::analyzeAST(Di if (!analysisSuccessful) return errors; - assert(errorReporter.errors().empty()); + assert(!errorReporter.hasErrors()); return std::variant, ErrorList>(std::move(analysisInfo)); } From c446d3bb20bf0689926a428cedc0ac65140d9f30 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 22 Aug 2024 16:19:09 +0200 Subject: [PATCH 0317/1340] SMTChecker: Fix parsing of model values in BMC SMT solvers return model values as pairs (enclosed in parentheses) of name and value. Previous way of parsing model values relied on finding the next closing bracket. However, this does not work for negative numbers, which are themselves wrapped in parentheses, e.g. (- 1). --- libsmtutil/SMTLib2Interface.cpp | 55 +++++++++++++++++++++++---------- libsmtutil/SMTLib2Interface.h | 1 - 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/libsmtutil/SMTLib2Interface.cpp b/libsmtutil/SMTLib2Interface.cpp index 81ad5ddd4..0914f8305 100644 --- a/libsmtutil/SMTLib2Interface.cpp +++ b/libsmtutil/SMTLib2Interface.cpp @@ -18,6 +18,8 @@ #include +#include + #include #include @@ -110,6 +112,41 @@ void SMTLib2Interface::addAssertion(Expression const& _expr) m_commands.assertion(toSExpr(_expr)); } +namespace +{ +std::vector parseValuesFromResponse(std::string const& _response) +{ + std::stringstream ss(_response); + std::string answer; + ss >> answer; + smtAssert(answer == "sat"); + + std::vector parsedOutput; + SMTLib2Parser parser(ss); + try + { + while (!parser.isEOF()) + parsedOutput.push_back(parser.parseExpression()); + } + catch(SMTLib2Parser::ParsingException&) + { + return {}; + } + smtAssert(parsedOutput.size() == 1, "SMT: Expected model values as a single s-expression"); + auto const& values = parsedOutput[0]; + smtAssert(!isAtom(values)); + std::vector parsedValues; + for (auto const& nameValuePair: asSubExpressions(values)) + { + smtAssert(!isAtom(nameValuePair)); + smtAssert(asSubExpressions(nameValuePair).size() == 2); + auto const& value = asSubExpressions(nameValuePair)[1]; + parsedValues.push_back(value.toString()); + } + return parsedValues; +} +} // namespace + std::pair> SMTLib2Interface::check(std::vector const& _expressionsToEvaluate) { std::string response = querySolver(dumpQuery(_expressionsToEvaluate)); @@ -127,7 +164,7 @@ std::pair> SMTLib2Interface::check(std::ve std::vector values; if (result == CheckResult::SATISFIABLE && !_expressionsToEvaluate.empty()) - values = parseValues(find(response.cbegin(), response.cend(), '\n'), response.cend()); + values = parseValuesFromResponse(response); return std::make_pair(result, values); } @@ -175,22 +212,6 @@ std::string SMTLib2Interface::checkSatAndGetValuesCommand(std::vector SMTLib2Interface::parseValues(std::string::const_iterator _start, std::string::const_iterator _end) -{ - std::vector values; - while (_start < _end) - { - auto valStart = find(_start, _end, ' '); - if (valStart < _end) - ++valStart; - auto valEnd = find(valStart, _end, ')'); - values.emplace_back(valStart, valEnd); - _start = find(valEnd, _end, '('); - } - - return values; -} - std::string SMTLib2Interface::querySolver(std::string const& _input) { h256 inputHash = keccak256(_input); diff --git a/libsmtutil/SMTLib2Interface.h b/libsmtutil/SMTLib2Interface.h index 11478223c..02b1c85ff 100644 --- a/libsmtutil/SMTLib2Interface.h +++ b/libsmtutil/SMTLib2Interface.h @@ -103,7 +103,6 @@ class SMTLib2Interface: public BMCSolverInterface void declareFunction(std::string const& _name, SortPointer const& _sort); std::string checkSatAndGetValuesCommand(std::vector const& _expressionsToEvaluate); - std::vector parseValues(std::string::const_iterator _start, std::string::const_iterator _end); /// Communicates with the solver via the callback. Throws SMTSolverError on error. std::string querySolver(std::string const& _input); From a204f475fbcadef3cca82f78a2e0665811dafac1 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 29 Aug 2024 13:42:46 +0200 Subject: [PATCH 0318/1340] SMTChecker: Prepare Z3 SMT-LIB interface for BMC engine This is a first draft and will not be used yet. --- libsolidity/formal/Z3SMTLib2Interface.cpp | 35 +++++++++++++++++++++ libsolidity/formal/Z3SMTLib2Interface.h | 37 +++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 libsolidity/formal/Z3SMTLib2Interface.cpp create mode 100644 libsolidity/formal/Z3SMTLib2Interface.h diff --git a/libsolidity/formal/Z3SMTLib2Interface.cpp b/libsolidity/formal/Z3SMTLib2Interface.cpp new file mode 100644 index 000000000..b76cdd252 --- /dev/null +++ b/libsolidity/formal/Z3SMTLib2Interface.cpp @@ -0,0 +1,35 @@ +/* + 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 + +#include + +#include + +using namespace solidity::frontend::smt; + +Z3SMTLib2Interface::Z3SMTLib2Interface( + frontend::ReadCallback::Callback _smtCallback, + std::optional _queryTimeout +): SMTLib2Interface({}, std::move(_smtCallback), _queryTimeout) +{ +} + +void Z3SMTLib2Interface::setupSmtCallback() { + if (auto* universalCallback = m_smtCallback.target()) + universalCallback->smtCommand().setZ3(m_queryTimeout, true, false); +} diff --git a/libsolidity/formal/Z3SMTLib2Interface.h b/libsolidity/formal/Z3SMTLib2Interface.h new file mode 100644 index 000000000..07e138710 --- /dev/null +++ b/libsolidity/formal/Z3SMTLib2Interface.h @@ -0,0 +1,37 @@ +/* + 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 + +#pragma once + +#include + +namespace solidity::frontend::smt +{ + +class Z3SMTLib2Interface: public smtutil::SMTLib2Interface +{ +public: + explicit Z3SMTLib2Interface( + frontend::ReadCallback::Callback _smtCallback = {}, + std::optional _queryTimeout = {} + ); +private: + void setupSmtCallback() override; +}; + +} From 6f548bec194776bef61b8f12172ce41f464c56c8 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 9 Sep 2024 16:20:50 +0200 Subject: [PATCH 0319/1340] Upgrade jobs to run on Ubuntu 2404 --- .circleci/config.yml | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 710d275d4..8384f2eea 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,6 +19,14 @@ parameters: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-8 default: "solbuildpackpusher/solidity-buildpack-deps@sha256:2662376fe0e1ec2d346495a19a6d64508c1048d5a7325d8600c33c343fa64a0f" + ubuntu-2404-docker-image: + type: string + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-1 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:5d6d27551104321a30326d6024bd4e96d9d899a97a78eb9feea364996f1d18b5" + ubuntu-2404-clang-docker-image: + type: string + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-1 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:8df0086907cc1e57068ad48841f2284a87bfbd0a95006286a19a7132d84bb861" ubuntu-clang-ossfuzz-docker-image: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-6 @@ -602,6 +610,56 @@ defaults: MAKEFLAGS: -j 10 CPUs: 10 + - base_ubuntu2404: &base_ubuntu2404 + docker: + - image: << pipeline.parameters.ubuntu-2404-docker-image >> + environment: &base_ubuntu2404_env + TERM: xterm + MAKEFLAGS: -j 3 + CPUs: 3 + + - base_ubuntu2404_clang: &base_ubuntu2404_clang + docker: + - image: << pipeline.parameters.ubuntu-2404-clang-docker-image >> + environment: &base_ubuntu2404_clang_env + TERM: xterm + CC: clang + CXX: clang++ + MAKEFLAGS: -j 3 + CPUs: 3 + + - base_ubuntu2404_clang_large: &base_ubuntu2404_clang_large + <<: *base_ubuntu2404_clang + resource_class: large + environment: &base_ubuntu2404_clang_large_env + <<: *base_ubuntu2404_clang_env + MAKEFLAGS: -j 5 + CPUs: 5 + + - base_ubuntu2404_small: &base_ubuntu2404_small + <<: *base_ubuntu2404 + resource_class: small + environment: &base_ubuntu2404_small_env + <<: *base_ubuntu2404_env + MAKEFLAGS: -j 2 + CPUs: 2 + + - base_ubuntu2404_large: &base_ubuntu2404_large + <<: *base_ubuntu2404 + resource_class: large + environment: &base_ubuntu2404_large_env + <<: *base_ubuntu2404_env + MAKEFLAGS: -j 5 + CPUs: 5 + + - base_ubuntu2404_xlarge: &base_ubuntu2404_xlarge + <<: *base_ubuntu2404 + resource_class: xlarge + environment: &base_ubuntu2404_xlarge_env + <<: *base_ubuntu2404_env + MAKEFLAGS: -j 10 + CPUs: 10 + - base_win: &base_win executor: name: win/default From 6a695274cc65a68c9f050ff410ee85d6031b8dac Mon Sep 17 00:00:00 2001 From: Pawel Gebal Date: Mon, 9 Sep 2024 15:15:07 +0200 Subject: [PATCH 0320/1340] xSMTChecker: Fix SMT logic error when assigning to an array of addresses --- Changelog.md | 2 +- libsolidity/formal/SymbolicTypes.cpp | 4 ++++ .../smtCheckerTests/types/array_of_addresses.sol | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/smtCheckerTests/types/array_of_addresses.sol diff --git a/Changelog.md b/Changelog.md index 0ecb280c7..f001a0efc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,7 +7,7 @@ Compiler Features: Bugfixes: - + * SMTChecker: Fix SMT logic error when assigning to an array of addresses. ### 0.8.27 (2024-09-04) diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 4a4ac8175..f9ec9b011 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -118,6 +118,10 @@ SortPointer smtSort(frontend::Type const& _type) // use a common sort for functions so pure and view modifier do not cause conflicting SMT types // solc handles types mismtach tupleName = "function"; + else if (isAddress(*baseType)) + // use a common sort for address and address payable so it does not cause conflicting SMT types + // solc handles types mismtach + tupleName = "address"; else if ( baseType->category() == frontend::Type::Category::Integer || baseType->category() == frontend::Type::Category::FixedPoint diff --git a/test/libsolidity/smtCheckerTests/types/array_of_addresses.sol b/test/libsolidity/smtCheckerTests/types/array_of_addresses.sol new file mode 100644 index 000000000..74f854846 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/array_of_addresses.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.0.0; +contract C { + address[10] a; + address payable[10] b; + + function f() public { + a = b; + assert(a[0] == b[0]); + } +} +// ==== +// SMTEngine: all +// ---- +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 9d7cc42bc1c12bb43e9dccf8c6c36833fdfcbbca Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 8 Jul 2024 19:27:57 -0300 Subject: [PATCH 0321/1340] legacy codegen transient storage support for state variables --- Changelog.md | 1 + .../analysis/DeclarationTypeChecker.cpp | 7 ++ libsolidity/analysis/ReferencesResolver.cpp | 2 +- libsolidity/analysis/TypeChecker.cpp | 6 +- libsolidity/ast/Types.cpp | 29 +++---- libsolidity/ast/Types.h | 2 +- libsolidity/codegen/Compiler.cpp | 14 +-- libsolidity/codegen/ContractCompiler.cpp | 8 +- libsolidity/codegen/ExpressionCompiler.cpp | 16 +++- libsolidity/codegen/LValue.cpp | 43 ++++++---- libsolidity/codegen/LValue.h | 17 +++- libsolidity/codegen/ir/IRGenerator.cpp | 7 +- .../args | 1 + .../err | 2 +- .../input.sol | 0 .../output | 2 +- .../evmasm_transient_storage_opcodes/args | 1 - .../args | 1 + .../input.sol | 9 ++ .../output | 86 +++++++++++++++++++ .../args | 1 + .../err | 1 + .../exit | 1 + .../input.sol | 9 ++ test/libsolidity/ASTPropertyTest.cpp | 2 +- test/libsolidity/ASTPropertyTest.h | 2 +- .../isSimpleCounterLoop_negative_cases.sol | 11 +++ .../transient_data_location.sol | 2 + .../getters/transient_value_types.sol | 15 ++++ ...transient_value_types_multi_frame_call.sol | 23 +++++ ...ansient_storage_access_inside_function.sol | 23 +++++ .../compound_assign_transient_storage.sol | 23 +++++ ...t_storage_variable_increment_decrement.sol | 16 ++++ .../delete_transient_state_variable.sol | 13 +++ ...transient_function_type_state_variable.sol | 17 ++++ ...ansient_state_address_variable_members.sol | 21 +++++ .../transient_state_enum_variable.sol | 18 ++++ .../variables/transient_state_variable.sol | 22 +++++ ...ient_state_variable_cleanup_assignment.sol | 17 ++++ ...ransient_state_variable_cleanup_tstore.sol | 15 ++++ ...nt_state_variable_slot_inline_assembly.sol | 32 +++++++ ...nsient_state_variable_tuple_assignment.sol | 21 +++++ .../transient_state_variable_udvt.sol | 23 +++++ .../transient_storage_reentrancy_lock.sol | 24 ++++++ .../constant_transient_state_variable.sol | 2 + ...transient_dynamic_array_state_variable.sol | 2 + .../transient_fixed_array_state_variable.sol | 2 + .../dataLocations/transient_function_type.sol | 3 +- .../transient_mapping_state_variable.sol | 3 +- .../transient_state_variable_visibility.sol | 3 +- .../transient_storage_variable_pre_cancun.sol | 7 ++ .../transient_struct_state_variable.sol | 2 + .../transient_value_type_state_variables.sol | 3 +- ...ue_type_state_variables_initialization.sol | 2 + .../state_var_transient_data_location.sol | 2 + .../invalid/constant_variable_via_offset.sol | 2 +- .../invalid/storage_assignment.sol | 2 +- .../storage_assignment_in_modifier.sol | 2 +- .../invalid/transient_storage_assignment.sol | 12 +++ .../invalid/unbalanced_two_stack_load.sol | 2 +- .../storage_reference_assignment_statevar.sol | 4 +- .../inlineAssembly/storage_reference_old.sol | 4 +- ...ient_storage_value_assignment_statevar.sol | 14 +++ ..._both_transient_storage_identical_name.sol | 8 ++ 64 files changed, 614 insertions(+), 73 deletions(-) create mode 100644 test/cmdlineTests/evmasm_transient_storage_inline_assembly/args rename test/cmdlineTests/{evmasm_transient_storage_opcodes => evmasm_transient_storage_inline_assembly}/err (90%) rename test/cmdlineTests/{evmasm_transient_storage_opcodes => evmasm_transient_storage_inline_assembly}/input.sol (100%) rename test/cmdlineTests/{evmasm_transient_storage_opcodes => evmasm_transient_storage_inline_assembly}/output (90%) delete mode 100644 test/cmdlineTests/evmasm_transient_storage_opcodes/args create mode 100644 test/cmdlineTests/evmasm_transient_storage_state_variable/args create mode 100644 test/cmdlineTests/evmasm_transient_storage_state_variable/input.sol create mode 100644 test/cmdlineTests/evmasm_transient_storage_state_variable/output create mode 100644 test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args create mode 100644 test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/err create mode 100644 test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/exit create mode 100644 test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/input.sol create mode 100644 test/libsolidity/semanticTests/getters/transient_value_types.sol create mode 100644 test/libsolidity/semanticTests/getters/transient_value_types_multi_frame_call.sol create mode 100644 test/libsolidity/semanticTests/inlineAssembly/inline_assembly_transient_storage_access_inside_function.sol create mode 100644 test/libsolidity/semanticTests/operators/compound_assign_transient_storage.sol create mode 100644 test/libsolidity/semanticTests/operators/transient_storage_variable_increment_decrement.sol create mode 100644 test/libsolidity/semanticTests/variables/delete_transient_state_variable.sol create mode 100644 test/libsolidity/semanticTests/variables/transient_function_type_state_variable.sol create mode 100644 test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol create mode 100644 test/libsolidity/semanticTests/variables/transient_state_enum_variable.sol create mode 100644 test/libsolidity/semanticTests/variables/transient_state_variable.sol create mode 100644 test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_assignment.sol create mode 100644 test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_tstore.sol create mode 100644 test/libsolidity/semanticTests/variables/transient_state_variable_slot_inline_assembly.sol create mode 100644 test/libsolidity/semanticTests/variables/transient_state_variable_tuple_assignment.sol create mode 100644 test/libsolidity/semanticTests/variables/transient_state_variable_udvt.sol create mode 100644 test/libsolidity/semanticTests/various/transient_storage_reentrancy_lock.sol create mode 100644 test/libsolidity/syntaxTests/dataLocations/transient_storage_variable_pre_cancun.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/invalid/transient_storage_assignment.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/transient_storage_value_assignment_statevar.sol create mode 100644 test/libsolidity/syntaxTests/variableDeclaration/state_variables_both_transient_storage_identical_name.sol diff --git a/Changelog.md b/Changelog.md index f001a0efc..9f531daea 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * Code Generator: Transient storage value type state variables are now supported by the legacy pipeline. Bugfixes: diff --git a/libsolidity/analysis/DeclarationTypeChecker.cpp b/libsolidity/analysis/DeclarationTypeChecker.cpp index f5db21100..e5549f035 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.cpp +++ b/libsolidity/analysis/DeclarationTypeChecker.cpp @@ -398,6 +398,13 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable) Location varLoc = _variable.referenceLocation(); DataLocation typeLoc = DataLocation::Memory; + if (varLoc == VariableDeclaration::Location::Transient && !m_evmVersion.supportsTransientStorage()) + m_errorReporter.declarationError( + 7985_error, + _variable.location(), + "Transient storage is not supported by EVM versions older than cancun." + ); + std::set allowedDataLocations = _variable.allowedDataLocations(); if (!allowedDataLocations.count(varLoc)) { diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 079bbf33c..cfbdec91a 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -370,7 +370,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier) m_errorReporter.declarationError( 9467_error, nativeLocationOf(_identifier), - "Identifier not found. Use \".slot\" and \".offset\" to access storage variables." + "Identifier not found. Use \".slot\" and \".offset\" to access storage or transient storage variables." ); return; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 3b7a314fe..993541472 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -785,7 +785,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) } else if (identifierInfo.suffix == "slot" || identifierInfo.suffix == "offset") { - m_errorReporter.typeError(6617_error, nativeLocationOf(_identifier), "The suffixes .offset and .slot can only be used on non-constant storage variables."); + m_errorReporter.typeError(6617_error, nativeLocationOf(_identifier), "The suffixes .offset and .slot can only be used on non-constant storage or transient storage variables."); return false; } else if (var && var->value() && !var->value()->annotation().type && !dynamic_cast(var->value().get())) @@ -824,7 +824,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) { if (var->isStateVariable()) { - m_errorReporter.typeError(4713_error, nativeLocationOf(_identifier), "State variables cannot be assigned to - you have to use \"sstore()\"."); + m_errorReporter.typeError(4713_error, nativeLocationOf(_identifier), "State variables cannot be assigned to - you have to use \"sstore()\" or \"tstore()\"."); return false; } else if (suffix != "slot") @@ -869,7 +869,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) m_errorReporter.typeError( 1408_error, nativeLocationOf(_identifier), - "Only local variables are supported. To access storage variables, use the \".slot\" and \".offset\" suffixes." + "Only local variables are supported. To access state variables, use the \".slot\" and \".offset\" suffixes." ); return false; } diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index f6e2a5413..95f249516 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2140,30 +2140,25 @@ FunctionType const* ContractType::newExpressionType() const return m_constructorType; } -std::vector> ContractType::stateVariables(std::optional _location) const +std::vector> ContractType::stateVariables(DataLocation _location) const { - std::optional location; - if (_location.has_value()) + VariableDeclaration::Location location; + switch (_location) { - switch (_location.value()) - { - case DataLocation::Storage: - location = std::make_optional(VariableDeclaration::Location::Unspecified); // By default state variables have unspecified (storage) data location - break; - case DataLocation::Transient: - location = std::make_optional(VariableDeclaration::Location::Transient); - break; - default: solAssert(false); - } + case DataLocation::Storage: + location = VariableDeclaration::Location::Unspecified; + break; + case DataLocation::Transient: + location = VariableDeclaration::Location::Transient; + break; + default: + solAssert(false); } std::vector variables; for (ContractDefinition const* contract: m_contract.annotation().linearizedBaseContracts | ranges::views::reverse) for (VariableDeclaration const* variable: contract->stateVariables()) - if ( - !(variable->isConstant() || variable->immutable()) && - variable->referenceLocation() == location.value_or(variable->referenceLocation()) - ) + if (!(variable->isConstant() || variable->immutable()) && variable->referenceLocation() == location) variables.push_back(variable); TypePointers types; for (auto variable: variables) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 5a5040c40..c64236202 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1002,7 +1002,7 @@ class ContractType: public Type /// @returns a list of all state variables (including inherited) of the contract and their /// offsets in storage/transient storage. - std::vector> stateVariables(std::optional _location = std::nullopt) const; + std::vector> stateVariables(DataLocation _location) const; /// @returns a list of all immutable variables (including inherited) of the contract. std::vector immutableVariables() const; protected: diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index 07b65fcc8..3e3f14996 100644 --- a/libsolidity/codegen/Compiler.cpp +++ b/libsolidity/codegen/Compiler.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include using namespace solidity; using namespace solidity::frontend; @@ -37,14 +37,16 @@ void Compiler::compileContract( bytes const& _metadata ) { - auto static notTransient = [](VariableDeclaration const* _varDeclaration) { - solAssert(_varDeclaration); - return _varDeclaration->referenceLocation() != VariableDeclaration::Location::Transient; + auto static isTransientReferenceType = [](VariableDeclaration const* _varDeclaration) { + solAssert(_varDeclaration && _varDeclaration->type()); + return + _varDeclaration->referenceLocation() == VariableDeclaration::Location::Transient && + !_varDeclaration->type()->isValueType(); }; solUnimplementedAssert( - ranges::all_of(_contract.stateVariables(), notTransient), - "Transient storage variables are not supported." + ranges::none_of(_contract.stateVariables(), isTransientReferenceType), + "Transient storage reference type variables are not supported." ); ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimiserSettings); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 66cfe35c4..5ed6e8f96 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -570,8 +570,9 @@ void ContractCompiler::appendReturnValuePacker(TypePointers const& _typeParamete void ContractCompiler::registerStateVariables(ContractDefinition const& _contract) { - for (auto const& var: ContractType(_contract).stateVariables()) - m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var)); + for (auto const location: {DataLocation::Storage, DataLocation::Transient}) + for (auto const& var: ContractType(_contract).stateVariables(location)) + m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var)); } void ContractCompiler::registerImmutableVariables(ContractDefinition const& _contract) @@ -586,7 +587,7 @@ void ContractCompiler::initializeStateVariables(ContractDefinition const& _contr solAssert(!_contract.isLibrary(), "Tried to initialize state variables of library."); for (VariableDeclaration const* variable: _contract.stateVariables()) { - solUnimplementedAssert(variable->referenceLocation() != VariableDeclaration::Location::Transient, "Transient storage variables not supported."); + solAssert(variable->referenceLocation() != VariableDeclaration::Location::Transient || !variable->value()); if (variable->value() && !variable->isConstant()) ExpressionCompiler(m_context, m_optimiserSettings.runOrderLiterals).appendStateVariableInitialization(*variable); } @@ -595,7 +596,6 @@ void ContractCompiler::initializeStateVariables(ContractDefinition const& _contr bool ContractCompiler::visit(VariableDeclaration const& _variableDeclaration) { solAssert(_variableDeclaration.isStateVariable(), "Compiler visit to non-state variable declaration."); - solUnimplementedAssert(_variableDeclaration.referenceLocation() != VariableDeclaration::Location::Transient, "Transient storage variables not supported."); CompilerContext::LocationSetter locationSetter(m_context, _variableDeclaration); m_context.startFunction(_variableDeclaration); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 95b7435ed..85634906e 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -108,7 +108,10 @@ void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration c if (_varDecl.immutable()) ImmutableItem(m_context, _varDecl).storeValue(*type, _varDecl.location(), true); else + { + solAssert(_varDecl.referenceLocation() != VariableDeclaration::Location::Transient); StorageItem(m_context, _varDecl).storeValue(*type, _varDecl.location(), true); + } } void ExpressionCompiler::appendConstStateVariableAccessor(VariableDeclaration const& _varDecl) @@ -147,6 +150,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& if (auto mappingType = dynamic_cast(returnType)) { solAssert(CompilerUtils::freeMemoryPointer >= 0x40, ""); + solAssert(_varDecl.referenceLocation() != VariableDeclaration::Location::Transient); // pop offset m_context << Instruction::POP; @@ -196,6 +200,8 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& } else if (auto arrayType = dynamic_cast(returnType)) { + solAssert(_varDecl.referenceLocation() != VariableDeclaration::Location::Transient); + // pop offset m_context << Instruction::POP; utils().copyToStackTop(static_cast(paramTypes.size() - i + 1), 1); @@ -229,6 +235,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& solAssert(returnTypes.size() >= 1, ""); if (StructType const* structType = dynamic_cast(returnType)) { + solAssert(_varDecl.referenceLocation() != VariableDeclaration::Location::Transient); solAssert(!_varDecl.immutable(), ""); // remove offset m_context << Instruction::POP; @@ -258,6 +265,8 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& solAssert(returnTypes.size() == 1, ""); if (_varDecl.immutable()) ImmutableItem(m_context, _varDecl).retrieveValue(SourceLocation()); + else if (_varDecl.referenceLocation() == VariableDeclaration::Location::Transient) + TransientStorageItem(m_context, *returnType).retrieveValue(SourceLocation(), true); else StorageItem(m_context, *returnType).retrieveValue(SourceLocation(), true); utils().convertType(*returnType, *returnTypes.front()); @@ -2995,7 +3004,12 @@ void ExpressionCompiler::setLValueFromDeclaration(Declaration const& _declaratio if (m_context.isLocalVariable(&_declaration)) setLValue(_expression, dynamic_cast(_declaration)); else if (m_context.isStateVariable(&_declaration)) - setLValue(_expression, dynamic_cast(_declaration)); + { + if (dynamic_cast(_declaration).referenceLocation() == VariableDeclaration::Location::Transient) + setLValue(_expression, dynamic_cast(_declaration)); + else + setLValue(_expression, dynamic_cast(_declaration)); + } else solAssert(false, "Identifier type not supported or identifier not found."); } diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 4847cb093..78efb9f81 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -36,7 +36,6 @@ using namespace solidity::frontend; using namespace solidity::langutil; using namespace solidity::util; - StackVariable::StackVariable(CompilerContext& _compilerContext, VariableDeclaration const& _declaration): LValue(_compilerContext, _declaration.annotation().type), m_baseStackOffset(m_context.baseStackOffsetOfVariable(_declaration)), @@ -198,15 +197,17 @@ void ImmutableItem::setToZero(SourceLocation const&, bool _removeReference) cons m_context << Instruction::POP; } -StorageItem::StorageItem(CompilerContext& _compilerContext, VariableDeclaration const& _declaration): - StorageItem(_compilerContext, *_declaration.annotation().type) +template +GenericStorageItem::GenericStorageItem(CompilerContext& _compilerContext, VariableDeclaration const& _declaration): + GenericStorageItem(_compilerContext, *_declaration.annotation().type) { solAssert(!_declaration.immutable(), ""); auto const& location = m_context.storageLocationOfVariable(_declaration); m_context << location.first << u256(location.second); } -StorageItem::StorageItem(CompilerContext& _compilerContext, Type const& _type): +template +GenericStorageItem::GenericStorageItem(CompilerContext& _compilerContext, Type const& _type): LValue(_compilerContext, &_type) { if (m_dataType->isValueType()) @@ -217,11 +218,13 @@ StorageItem::StorageItem(CompilerContext& _compilerContext, Type const& _type): } } -void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const +template +void GenericStorageItem::retrieveValue(langutil::SourceLocation const&, bool _remove) const { // stack: storage_key storage_offset if (!m_dataType->isValueType()) { + solUnimplementedAssert(!IsTransient, "Transient storage reference types are not supported yet."); solAssert(m_dataType->sizeOnStack() == 1, "Invalid storage ref size."); if (_remove) m_context << Instruction::POP; // remove byte offset @@ -232,7 +235,7 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const if (!_remove) CompilerUtils(m_context).copyToStackTop(sizeOnStack(), sizeOnStack()); if (m_dataType->storageBytes() == 32) - m_context << Instruction::POP << Instruction::SLOAD; + m_context << Instruction::POP << s_loadInstruction; else { Type const* type = m_dataType; @@ -240,12 +243,12 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const type = type->encodingType(); bool cleaned = false; m_context - << Instruction::SWAP1 << Instruction::SLOAD << Instruction::SWAP1 + << Instruction::SWAP1 << s_loadInstruction << Instruction::SWAP1 << u256(0x100) << Instruction::EXP << Instruction::SWAP1 << Instruction::DIV; if (type->category() == Type::Category::FixedPoint) // implementation should be very similar to the integer case. solUnimplemented("Not yet implemented - FixedPointType."); - else if (FunctionType const* fun = dynamic_cast(type)) + else if (auto const* fun = dynamic_cast(type)) { if (fun->kind() == FunctionType::Kind::External) { @@ -281,7 +284,8 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const } } -void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _location, bool _move) const +template +void GenericStorageItem::storeValue(Type const& _sourceType, langutil::SourceLocation const& _location, bool _move) const { CompilerUtils utils(m_context); solAssert(m_dataType, ""); @@ -303,7 +307,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc utils.convertType(_sourceType, *m_dataType, true); m_context << Instruction::SWAP1; - m_context << Instruction::SSTORE; + m_context << s_storeInstruction; } else { @@ -311,7 +315,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc m_context << u256(0x100) << Instruction::EXP; // stack: value storage_ref multiplier // fetch old value - m_context << Instruction::DUP2 << Instruction::SLOAD; + m_context << Instruction::DUP2 << s_loadInstruction; // stack: value storage_ref multiplier old_full_value // clear bytes in old value m_context @@ -358,13 +362,14 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc } m_context << Instruction::MUL << Instruction::OR; // stack: value storage_ref updated_value - m_context << Instruction::SWAP1 << Instruction::SSTORE; + m_context << Instruction::SWAP1 << s_storeInstruction; if (_move) utils.popStackElement(*m_dataType); } } else { + solUnimplementedAssert(!IsTransient, "Transient storage reference types are not supported yet."); solAssert( _sourceType.category() == m_dataType->category(), "Wrong type conversation for assignment." @@ -445,16 +450,19 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc } } -void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const +template +void GenericStorageItem::setToZero(langutil::SourceLocation const&, bool _removeReference) const { if (m_dataType->category() == Type::Category::Array) { + solUnimplementedAssert(!IsTransient, "Transient storage reference types are not supported yet."); if (!_removeReference) CompilerUtils(m_context).copyToStackTop(sizeOnStack(), sizeOnStack()); ArrayUtils(m_context).clearArray(dynamic_cast(*m_dataType)); } else if (m_dataType->category() == Type::Category::Struct) { + solUnimplementedAssert(!IsTransient, "Transient storage reference types are not supported yet."); // stack layout: storage_key storage_offset // @todo this can be improved: use StorageItem for non-value types, and just store 0 in // all slots that contain value types later. @@ -484,14 +492,14 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const // offset should be zero m_context << Instruction::POP << u256(0) - << Instruction::SWAP1 << Instruction::SSTORE; + << Instruction::SWAP1 << s_storeInstruction; } else { m_context << u256(0x100) << Instruction::EXP; // stack: storage_ref multiplier // fetch old value - m_context << Instruction::DUP2 << Instruction::SLOAD; + m_context << Instruction::DUP2 << s_loadInstruction; // stack: storage_ref multiplier old_full_value // clear bytes in old value m_context @@ -499,7 +507,7 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const << Instruction::MUL; m_context << Instruction::NOT << Instruction::AND; // stack: storage_ref cleared_value - m_context << Instruction::SWAP1 << Instruction::SSTORE; + m_context << Instruction::SWAP1 << s_storeInstruction; } } } @@ -610,3 +618,6 @@ void TupleObject::setToZero(SourceLocation const&, bool) const { solAssert(false, "Tried to delete tuple."); } + +template class solidity::frontend::GenericStorageItem; +template class solidity::frontend::GenericStorageItem; diff --git a/libsolidity/codegen/LValue.h b/libsolidity/codegen/LValue.h index 9bf0d1c05..430419727 100644 --- a/libsolidity/codegen/LValue.h +++ b/libsolidity/codegen/LValue.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -149,17 +150,18 @@ class ImmutableItem: public LValue }; /** - * Reference to some item in storage. On the stack this is , + * Reference to some item in storage/transient storage. On the stack this is , * where 0 <= offset_inside_value < 32 and an offset of i means that the value is multiplied * by 2**i before storing it. */ -class StorageItem: public LValue +template +class GenericStorageItem : public LValue { public: /// Constructs the LValue and pushes the location of @a _declaration onto the stack. - StorageItem(CompilerContext& _compilerContext, VariableDeclaration const& _declaration); + GenericStorageItem(CompilerContext& _compilerContext, VariableDeclaration const& _declaration); /// Constructs the LValue and assumes that the storage reference is already on the stack. - StorageItem(CompilerContext& _compilerContext, Type const& _type); + GenericStorageItem(CompilerContext& _compilerContext, Type const& _type); unsigned sizeOnStack() const override { return 2; } void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; void storeValue( @@ -171,7 +173,14 @@ class StorageItem: public LValue langutil::SourceLocation const& _location = {}, bool _removeReference = true ) const override; +private: + static constexpr evmasm::Instruction s_storeInstruction = IsTransient ? evmasm::Instruction::TSTORE : evmasm::Instruction::SSTORE; + static constexpr evmasm::Instruction s_loadInstruction = IsTransient ? evmasm::Instruction::TLOAD : evmasm::Instruction::SLOAD; }; +extern template class GenericStorageItem; +extern template class GenericStorageItem; +using StorageItem = GenericStorageItem; +using TransientStorageItem = GenericStorageItem; /** * Reference to a single byte inside a storage byte array. diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 00c9fa196..f495d97ab 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -110,7 +110,7 @@ std::string IRGenerator::generate( solUnimplementedAssert( ranges::all_of(_contract.stateVariables(), notTransient), - "Transient storage variables are not supported." + "Transient storage variables are not supported when compiling via IR." ); auto subObjectSources = [&_otherYulSources](UniqueVector const& _subObjects) -> std::string @@ -1115,8 +1115,9 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon m_context = std::move(newContext); m_context.setMostDerivedContract(_contract); - for (auto const& var: ContractType(_contract).stateVariables()) - m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var)); + for (auto const location: {DataLocation::Storage, DataLocation::Transient}) + for (auto const& var: ContractType(_contract).stateVariables(location)) + m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var)); } std::string IRGenerator::dispenseLocationComment(ASTNode const& _node) diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/args b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/args new file mode 100644 index 000000000..8430fd558 --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/args @@ -0,0 +1 @@ +--no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none diff --git a/test/cmdlineTests/evmasm_transient_storage_opcodes/err b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/err similarity index 90% rename from test/cmdlineTests/evmasm_transient_storage_opcodes/err rename to test/cmdlineTests/evmasm_transient_storage_inline_assembly/err index a6cd56261..5071bc457 100644 --- a/test/cmdlineTests/evmasm_transient_storage_opcodes/err +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/err @@ -1,5 +1,5 @@ Warning: Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. - --> evmasm_transient_storage_opcodes/input.sol:7:13: + --> evmasm_transient_storage_inline_assembly/input.sol:7:13: | 7 | tstore(0, 0) | ^^^^^^ diff --git a/test/cmdlineTests/evmasm_transient_storage_opcodes/input.sol b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/input.sol similarity index 100% rename from test/cmdlineTests/evmasm_transient_storage_opcodes/input.sol rename to test/cmdlineTests/evmasm_transient_storage_inline_assembly/input.sol diff --git a/test/cmdlineTests/evmasm_transient_storage_opcodes/output b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output similarity index 90% rename from test/cmdlineTests/evmasm_transient_storage_opcodes/output rename to test/cmdlineTests/evmasm_transient_storage_inline_assembly/output index 3d1eddc9a..56dea1afb 100644 --- a/test/cmdlineTests/evmasm_transient_storage_opcodes/output +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output @@ -1,5 +1,5 @@ -======= evmasm_transient_storage_opcodes/input.sol:C ======= +======= evmasm_transient_storage_inline_assembly/input.sol:C ======= EVM assembly: 0x80 dup1 diff --git a/test/cmdlineTests/evmasm_transient_storage_opcodes/args b/test/cmdlineTests/evmasm_transient_storage_opcodes/args deleted file mode 100644 index 552cea1ca..000000000 --- a/test/cmdlineTests/evmasm_transient_storage_opcodes/args +++ /dev/null @@ -1 +0,0 @@ ---evm-version cancun --no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable/args b/test/cmdlineTests/evmasm_transient_storage_state_variable/args new file mode 100644 index 000000000..0df1b673e --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable/args @@ -0,0 +1 @@ +--no-cbor-metadata --optimize --asm --debug-info none diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable/input.sol b/test/cmdlineTests/evmasm_transient_storage_state_variable/input.sol new file mode 100644 index 000000000..7177bdb64 --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable/input.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + uint transient x; + function f() public { + x = x + 1; + } +} diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable/output b/test/cmdlineTests/evmasm_transient_storage_state_variable/output new file mode 100644 index 000000000..e80eb3c57 --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable/output @@ -0,0 +1,86 @@ + +======= evmasm_transient_storage_state_variable/input.sol:C ======= +EVM assembly: + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + tag_2: + revert(0x00, 0x00) + tag_3: + tag_4 + tag_5 + jump // in + tag_4: + stop + tag_5: + tag_7 + tload(0x00) + 0x01 + tag_8 + jump // in + tag_7: + dup1 + 0x00 + tstore + pop + jump // out + tag_8: + dup1 + dup3 + add + dup1 + dup3 + gt + iszero + tag_11 + jumpi + 0x4e487b71 + 0xe0 + shl + 0x00 + mstore + 0x11 + 0x04 + mstore + 0x24 + 0x00 + revert + tag_11: + swap3 + swap2 + pop + pop + jump // out +} diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args new file mode 100644 index 000000000..00dcc3777 --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args @@ -0,0 +1 @@ +--no-cbor-metadata --ir-optimized --debug-info none \ No newline at end of file diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/err b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/err new file mode 100644 index 000000000..2f81d6cd3 --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/err @@ -0,0 +1 @@ +Error: Transient storage variables are not supported when compiling via IR. diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/exit b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/input.sol b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/input.sol new file mode 100644 index 000000000..7177bdb64 --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/input.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + uint transient x; + function f() public { + x = x + 1; + } +} diff --git a/test/libsolidity/ASTPropertyTest.cpp b/test/libsolidity/ASTPropertyTest.cpp index 05c9b8786..3419d51c5 100644 --- a/test/libsolidity/ASTPropertyTest.cpp +++ b/test/libsolidity/ASTPropertyTest.cpp @@ -43,7 +43,7 @@ using namespace solidity; using namespace std::string_literals; ASTPropertyTest::ASTPropertyTest(std::string const& _filename): - TestCase(_filename) + EVMVersionRestrictedTestCase(_filename) { if (!boost::algorithm::ends_with(_filename, ".sol")) BOOST_THROW_EXCEPTION(std::runtime_error("Not a Solidity file: \"" + _filename + "\".")); diff --git a/test/libsolidity/ASTPropertyTest.h b/test/libsolidity/ASTPropertyTest.h index 6130cedb2..9d6414e77 100644 --- a/test/libsolidity/ASTPropertyTest.h +++ b/test/libsolidity/ASTPropertyTest.h @@ -35,7 +35,7 @@ namespace solidity::frontend::test using StringPair = std::pair; -class ASTPropertyTest: public TestCase +class ASTPropertyTest: public EVMVersionRestrictedTestCase { public: static std::unique_ptr create(Config const& _config) diff --git a/test/libsolidity/astPropertyTests/forLoop/isSimpleCounterLoop_negative_cases.sol b/test/libsolidity/astPropertyTests/forLoop/isSimpleCounterLoop_negative_cases.sol index cfdda3813..57e160fcf 100644 --- a/test/libsolidity/astPropertyTests/forLoop/isSimpleCounterLoop_negative_cases.sol +++ b/test/libsolidity/astPropertyTests/forLoop/isSimpleCounterLoop_negative_cases.sol @@ -20,6 +20,7 @@ function h() pure returns (uint) { contract C { uint z = 0; + uint transient t; function modifyStateVarZ() public returns (uint) { z = type(uint).max; @@ -117,6 +118,12 @@ contract C { for (z = 1; z < 2048; ++z) { modifyStateVarZ(); } + /// StorageStateVarCounter: isSimpleCounterLoop + for (z = 1; z < 2048; ++z) { + } + /// TransientStateVarCounter: isSimpleCounterLoop + for (t = 1; t < 2048; ++t) { + } /// NonIntegerCounter: isSimpleCounterLoop for (address i = address(0x123); i < address(this); i = address(0x123 + 1)) { } @@ -135,6 +142,8 @@ contract C { } } } +// ==== +// EVMVersion: >=cancun // ---- // AdditionLoopExpression: false // ShortHandAdditionLoopExpression: false @@ -160,6 +169,8 @@ contract C { // LiteralDifferentCommonTypeConditionRHS: false // StateVarCounterModifiedFunctionConditionRHS: false // StateVarCounterModifiedFunctionLoopBody: false +// StorageStateVarCounter: false +// TransientStateVarCounter: false // NonIntegerCounter: false // AssemblyAfterAssignmentToCounter: false // ExpressionIncrement: false diff --git a/test/libsolidity/astPropertyTests/transient_data_location.sol b/test/libsolidity/astPropertyTests/transient_data_location.sol index be220a366..327564dab 100644 --- a/test/libsolidity/astPropertyTests/transient_data_location.sol +++ b/test/libsolidity/astPropertyTests/transient_data_location.sol @@ -7,6 +7,8 @@ contract C { uint y; } +// ==== +// EVMVersion: >=cancun // ---- // TransientDataLocation: transient // TransientVarName: x diff --git a/test/libsolidity/semanticTests/getters/transient_value_types.sol b/test/libsolidity/semanticTests/getters/transient_value_types.sol new file mode 100644 index 000000000..cc345cb91 --- /dev/null +++ b/test/libsolidity/semanticTests/getters/transient_value_types.sol @@ -0,0 +1,15 @@ +contract C { + int8 public transient x; + + function f() public returns(int8) { + x = -1; + return this.x(); + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// x() -> 0 +// f() -> -1 +// x() -> 0 diff --git a/test/libsolidity/semanticTests/getters/transient_value_types_multi_frame_call.sol b/test/libsolidity/semanticTests/getters/transient_value_types_multi_frame_call.sol new file mode 100644 index 000000000..5e6b3f054 --- /dev/null +++ b/test/libsolidity/semanticTests/getters/transient_value_types_multi_frame_call.sol @@ -0,0 +1,23 @@ +contract C { + int8 public transient x; + + function f() public returns(int8) { + x = -1; + return this.h(); + } + function g() public { + x = x - 1; + } + function h() public returns(int8) { + this.g(); + return this.x(); + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// x() -> 0 +// f() -> -2 +// h() -> -1 +// x() -> 0 diff --git a/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_transient_storage_access_inside_function.sol b/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_transient_storage_access_inside_function.sol new file mode 100644 index 000000000..86463473b --- /dev/null +++ b/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_transient_storage_access_inside_function.sol @@ -0,0 +1,23 @@ +contract C { + uint16 transient x; + uint16 public transient y; + uint256 public transient z; + + function f() public returns (uint256) { + uint256 offset; + assembly { + function f() -> o1 { + tstore(z.slot, 7) + o1 := y.offset + } + offset := f() + } + assert(offset == 2); + return z; + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// f() -> 7 diff --git a/test/libsolidity/semanticTests/operators/compound_assign_transient_storage.sol b/test/libsolidity/semanticTests/operators/compound_assign_transient_storage.sol new file mode 100644 index 000000000..a20c8403e --- /dev/null +++ b/test/libsolidity/semanticTests/operators/compound_assign_transient_storage.sol @@ -0,0 +1,23 @@ +contract test { + uint value1; + uint transient value2; + function f(uint x, uint y) public returns (uint w) { + uint value3 = y; + value1 += x; + value3 *= x; + value2 += value3 + value1; + return value2 += 7; + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// f(uint256,uint256): 0, 6 -> 7 +// f(uint256,uint256): 1, 3 -> 11 +// f(uint256,uint256): 2, 25 -> 0x3c +// f(uint256,uint256): 3, 69 -> 0xdc +// f(uint256,uint256): 4, 84 -> 353 +// f(uint256,uint256): 5, 2 -> 0x20 +// f(uint256,uint256): 6, 51 -> 334 +// f(uint256,uint256): 7, 48 -> 371 diff --git a/test/libsolidity/semanticTests/operators/transient_storage_variable_increment_decrement.sol b/test/libsolidity/semanticTests/operators/transient_storage_variable_increment_decrement.sol new file mode 100644 index 000000000..ac32eee1c --- /dev/null +++ b/test/libsolidity/semanticTests/operators/transient_storage_variable_increment_decrement.sol @@ -0,0 +1,16 @@ +contract C { + int transient x; + function f() public returns (int) { + ++x; + ++x; + --x; + x++; + x--; + return x; + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// f() -> 1 diff --git a/test/libsolidity/semanticTests/variables/delete_transient_state_variable.sol b/test/libsolidity/semanticTests/variables/delete_transient_state_variable.sol new file mode 100644 index 000000000..5f584fc89 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/delete_transient_state_variable.sol @@ -0,0 +1,13 @@ +contract C { + uint transient x; + function f() public returns (uint) { + x = 10; + delete x; + return x; + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// f() -> 0 diff --git a/test/libsolidity/semanticTests/variables/transient_function_type_state_variable.sol b/test/libsolidity/semanticTests/variables/transient_function_type_state_variable.sol new file mode 100644 index 000000000..56a69649e --- /dev/null +++ b/test/libsolidity/semanticTests/variables/transient_function_type_state_variable.sol @@ -0,0 +1,17 @@ +contract C { + function () external transient f; + function g() external { + } + + function test() public returns (bool) { + assert(f != this.g); + f = this.g; + + return f == this.g; + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// test() -> true diff --git a/test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol b/test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol new file mode 100644 index 000000000..6a388b3ee --- /dev/null +++ b/test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol @@ -0,0 +1,21 @@ +contract C { + address transient a; + function f() public returns (uint) { + a = msg.sender; + return a.balance; + } + function g() public returns (uint) { + return a.balance; + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// constructor() -> +// gas legacy: 59027 +// gas legacy code: 70400 +// account: 0 -> 0x1212121212121212121212121212120000000012 +// balance: 0x1212121212121212121212121212120000000012 -> 1267650600228229401496703205376 +// f() -> 1267650600228229401496703205376 +// g() -> 0 \ No newline at end of file diff --git a/test/libsolidity/semanticTests/variables/transient_state_enum_variable.sol b/test/libsolidity/semanticTests/variables/transient_state_enum_variable.sol new file mode 100644 index 000000000..a472212d4 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/transient_state_enum_variable.sol @@ -0,0 +1,18 @@ +contract C { + enum Pets { Dog, Cat, Bird, Fish } + Pets transient myPet; + + function f() public { + myPet = Pets.Bird; + this.g(); + assert(myPet == Pets.Cat); + } + function g() public { + myPet = Pets.Cat; + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// f() -> diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable.sol b/test/libsolidity/semanticTests/variables/transient_state_variable.sol new file mode 100644 index 000000000..71ed212d0 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/transient_state_variable.sol @@ -0,0 +1,22 @@ +contract C { + uint transient public x; + + function f() public { + x = 8; + } + function g() public returns (uint) { + x = 0; + this.f(); + return x; + } + function h() public returns (uint) { + return x; + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// x() -> 0 +// g() -> 8 +// h() -> 0 diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_assignment.sol b/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_assignment.sol new file mode 100644 index 000000000..d1f0cc579 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_assignment.sol @@ -0,0 +1,17 @@ +contract C { + uint8 transient x; + function f() public returns(uint256 r) { + uint8 y; + assembly { y := 0xFFFF } + x = y; + assembly { + r := tload(x.slot) + } + + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// f() -> 0xff diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_tstore.sol b/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_tstore.sol new file mode 100644 index 000000000..425be5500 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_tstore.sol @@ -0,0 +1,15 @@ +contract C { + uint8 transient x; + function f() public returns(uint256 r) { + assembly { + tstore(x.slot, 0xFFFF) + } + return x; + + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// f() -> 0xff diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable_slot_inline_assembly.sol b/test/libsolidity/semanticTests/variables/transient_state_variable_slot_inline_assembly.sol new file mode 100644 index 000000000..6cf05068e --- /dev/null +++ b/test/libsolidity/semanticTests/variables/transient_state_variable_slot_inline_assembly.sol @@ -0,0 +1,32 @@ +contract C { + uint256 y; + uint256 transient x; + int8 transient w; + int z; + address transient a; + function f() public returns(uint256 s, uint256 o) { + assembly { + s := x.slot + o := x.offset + } + } + function g() public returns(uint256 s, uint256 o) { + assembly { + s := w.slot + o := w.offset + } + } + function h() public returns(uint256 s, uint256 o) { + assembly { + s := a.slot + o := a.offset + } + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// f() -> 0, 0 +// g() -> 1, 0 +// h() -> 1, 1 diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable_tuple_assignment.sol b/test/libsolidity/semanticTests/variables/transient_state_variable_tuple_assignment.sol new file mode 100644 index 000000000..1b5180635 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/transient_state_variable_tuple_assignment.sol @@ -0,0 +1,21 @@ +contract C { + uint transient x; + uint y; + uint transient w; + uint z; + + function f() public returns (uint, uint, uint) { + x = 1; + y = 2; + w = 3; + z = 4; + + (x, y, w) = (y, w, z); + return (x, y, w); + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// f() -> 2, 3, 4 diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable_udvt.sol b/test/libsolidity/semanticTests/variables/transient_state_variable_udvt.sol new file mode 100644 index 000000000..2f49a32b0 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/transient_state_variable_udvt.sol @@ -0,0 +1,23 @@ +type MyInt is int256; +contract C { + MyInt transient public x; + + function f() public { + x = MyInt.wrap(2); + } + function g() public returns (MyInt) { + x = MyInt.wrap(0); + this.f(); + return x; + } + function h() public returns (MyInt) { + return x; + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// x() -> 0 +// g() -> 2 +// h() -> 0 diff --git a/test/libsolidity/semanticTests/various/transient_storage_reentrancy_lock.sol b/test/libsolidity/semanticTests/various/transient_storage_reentrancy_lock.sol new file mode 100644 index 000000000..aa3828601 --- /dev/null +++ b/test/libsolidity/semanticTests/various/transient_storage_reentrancy_lock.sol @@ -0,0 +1,24 @@ +contract C { + bool transient locked; + modifier nonReentrant { + require(!locked, "Reentrancy attempt"); + locked = true; + _; + locked = false; + } + + function test(address newAddress, bool reentrancy) nonReentrant public { + if (reentrancy) + reentrantCall(newAddress); + } + + function reentrantCall(address a) public { + this.test(a, false); + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: false +// ---- +// test(address,bool): 0x1234abcd, true -> FAILURE, hex"08c379a0", 0x20, 0x12, "Reentrancy attempt" +// test(address,bool): 0x1234abcd, false -> diff --git a/test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol b/test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol index 15913360c..f30494286 100644 --- a/test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol +++ b/test/libsolidity/syntaxTests/constants/constant_transient_state_variable.sol @@ -1,6 +1,8 @@ contract C { int constant public transient x = 0; } +// ==== +// EVMVersion: >=cancun // ---- // DeclarationError 2197: (17-52): Transient cannot be used as data location for constant or immutable variables. // DeclarationError 9825: (17-52): Initialization of transient storage state variables is not supported. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol index 7a3caa86e..b1b436732 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_dynamic_array_state_variable.sol @@ -1,5 +1,7 @@ contract C { uint[] transient x; } +// ==== +// EVMVersion: >=cancun // ---- // UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol index 10b942e23..ca3898f29 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_fixed_array_state_variable.sol @@ -1,5 +1,7 @@ contract C { uint[3] transient x; } +// ==== +// EVMVersion: >=cancun // ---- // UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol b/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol index 564562908..1d0ccf0c4 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_function_type.sol @@ -6,5 +6,6 @@ contract C { function () internal transient internal fiti; function () internal internal transient fiit; } +// ==== +// EVMVersion: >=cancun // ---- -// UnimplementedFeatureError 1834: Transient storage variables are not supported. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol b/test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol index 2a21b3e00..6c7822bf3 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_mapping_state_variable.sol @@ -1,6 +1,7 @@ contract C { mapping(uint => uint) transient y; } - +// ==== +// EVMVersion: >=cancun // ---- // UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol b/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol index f598fb72c..45ad6e6c5 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_state_variable_visibility.sol @@ -7,5 +7,6 @@ contract C { uint transient internal ti; uint transient private tprv; } +// ==== +// EVMVersion: >=cancun // ---- -// UnimplementedFeatureError 1834: Transient storage variables are not supported. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_storage_variable_pre_cancun.sol b/test/libsolidity/syntaxTests/dataLocations/transient_storage_variable_pre_cancun.sol new file mode 100644 index 000000000..8eb4dd565 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/transient_storage_variable_pre_cancun.sol @@ -0,0 +1,7 @@ +contract C { + uint transient x; +} +// ==== +// EVMVersion: =cancun // ---- // UnimplementedFeatureError 1834: Transient data location is only supported for value types. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol index d2eac46f7..65188a900 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables.sol @@ -7,5 +7,6 @@ contract C { uint transient x; bytes32 transient y; } +// ==== +// EVMVersion: >=cancun // ---- -// UnimplementedFeatureError 1834: Transient storage variables are not supported. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_initialization.sol b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_initialization.sol index 570642485..080ca89cc 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_initialization.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_value_type_state_variables_initialization.sol @@ -5,6 +5,8 @@ contract C { address transient a = address(0xABC); bool transient b = x > 0 ? false : true; } +// ==== +// EVMVersion: >=cancun // ---- // DeclarationError 9825: (30-51): Initialization of transient storage state variables is not supported. // DeclarationError 9825: (54-90): Initialization of transient storage state variables is not supported. diff --git a/test/libsolidity/syntaxTests/immutable/state_var_transient_data_location.sol b/test/libsolidity/syntaxTests/immutable/state_var_transient_data_location.sol index a3d93848d..f4b7e078e 100644 --- a/test/libsolidity/syntaxTests/immutable/state_var_transient_data_location.sol +++ b/test/libsolidity/syntaxTests/immutable/state_var_transient_data_location.sol @@ -1,5 +1,7 @@ contract C { uint public immutable transient x; } +// ==== +// EVMVersion: >=cancun // ---- // DeclarationError 2197: (17-50): Transient cannot be used as data location for constant or immutable variables. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/constant_variable_via_offset.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/constant_variable_via_offset.sol index eab2d2b4e..a6797e05a 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/constant_variable_via_offset.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/constant_variable_via_offset.sol @@ -7,4 +7,4 @@ contract test { } } // ---- -// TypeError 6617: (112-120): The suffixes .offset and .slot can only be used on non-constant storage variables. +// TypeError 6617: (112-120): The suffixes .offset and .slot can only be used on non-constant storage or transient storage variables. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/storage_assignment.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/storage_assignment.sol index b01f1ee21..bcc5eb87c 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/storage_assignment.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/storage_assignment.sol @@ -7,4 +7,4 @@ contract test { } } // ---- -// TypeError 1408: (89-90): Only local variables are supported. To access storage variables, use the ".slot" and ".offset" suffixes. +// TypeError 1408: (89-90): Only local variables are supported. To access state variables, use the ".slot" and ".offset" suffixes. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/storage_assignment_in_modifier.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/storage_assignment_in_modifier.sol index 64cfc8623..7c1265e97 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/storage_assignment_in_modifier.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/storage_assignment_in_modifier.sol @@ -10,4 +10,4 @@ contract test { } } // ---- -// TypeError 1408: (80-81): Only local variables are supported. To access storage variables, use the ".slot" and ".offset" suffixes. +// TypeError 1408: (80-81): Only local variables are supported. To access state variables, use the ".slot" and ".offset" suffixes. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/transient_storage_assignment.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/transient_storage_assignment.sol new file mode 100644 index 000000000..4cab6ffa2 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/transient_storage_assignment.sol @@ -0,0 +1,12 @@ +contract test { + uint transient x; + function f() public { + assembly { + x := 2 + } + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// TypeError 1408: (95-96): Only local variables are supported. To access state variables, use the ".slot" and ".offset" suffixes. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_two_stack_load.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_two_stack_load.sol index b1f8ba435..050716609 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_two_stack_load.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_two_stack_load.sol @@ -5,4 +5,4 @@ contract c { } } // ---- -// TypeError 1408: (75-76): Only local variables are supported. To access storage variables, use the ".slot" and ".offset" suffixes. +// TypeError 1408: (75-76): Only local variables are supported. To access state variables, use the ".slot" and ".offset" suffixes. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_assignment_statevar.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_assignment_statevar.sol index f4ed7c378..5fa0eedbb 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_assignment_statevar.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_assignment_statevar.sol @@ -8,5 +8,5 @@ contract C { } } // ---- -// TypeError 4713: (84-90): State variables cannot be assigned to - you have to use "sstore()". -// TypeError 4713: (108-116): State variables cannot be assigned to - you have to use "sstore()". +// TypeError 4713: (84-90): State variables cannot be assigned to - you have to use "sstore()" or "tstore()". +// TypeError 4713: (108-116): State variables cannot be assigned to - you have to use "sstore()" or "tstore()". diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_old.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_old.sol index d2ca4d7cb..2876ac726 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_old.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_old.sol @@ -9,5 +9,5 @@ contract C { } } // ---- -// DeclarationError 9467: (118-124): Identifier not found. Use ".slot" and ".offset" to access storage variables. -// DeclarationError 9467: (142-150): Identifier not found. Use ".slot" and ".offset" to access storage variables. +// DeclarationError 9467: (118-124): Identifier not found. Use ".slot" and ".offset" to access storage or transient storage variables. +// DeclarationError 9467: (142-150): Identifier not found. Use ".slot" and ".offset" to access storage or transient storage variables. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/transient_storage_value_assignment_statevar.sol b/test/libsolidity/syntaxTests/inlineAssembly/transient_storage_value_assignment_statevar.sol new file mode 100644 index 000000000..704a771f7 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/transient_storage_value_assignment_statevar.sol @@ -0,0 +1,14 @@ +contract C { + uint transient x; + fallback() external { + assembly { + x.slot := 1 + x.offset := 2 + } + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// TypeError 4713: (92-98): State variables cannot be assigned to - you have to use "sstore()" or "tstore()". +// TypeError 4713: (116-124): State variables cannot be assigned to - you have to use "sstore()" or "tstore()". diff --git a/test/libsolidity/syntaxTests/variableDeclaration/state_variables_both_transient_storage_identical_name.sol b/test/libsolidity/syntaxTests/variableDeclaration/state_variables_both_transient_storage_identical_name.sol new file mode 100644 index 000000000..d34c1153a --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/state_variables_both_transient_storage_identical_name.sol @@ -0,0 +1,8 @@ +contract C { + uint public x; + uint public transient x; +} +// ==== +// EVMVersion: >=cancun +// ---- +// DeclarationError 2333: (36-59): Identifier already declared. From 668adbeebd47c8ed581265419a72dceacaf256f0 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Mon, 9 Sep 2024 22:48:17 +0200 Subject: [PATCH 0322/1340] Remove STRICT_NLOHMANN_JSON_VERSION_CHECK leftover. --- CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7770d29e6..7c36ff73b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,10 +73,6 @@ if (PROFILE_OPTIMIZER_STEPS) add_definitions(-DPROFILE_OPTIMIZER_STEPS) endif() -if (STRICT_NLOHMANN_JSON_VERSION) - add_definitions(-DSTRICT_NLOHMANN_JSON_VERSION_CHECK) -endif() - # Figure out what compiler and system are we using include(EthCompilerSettings) From 16b244791392cb0ff9d8da19db0cf0d209cd498d Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 9 Sep 2024 16:20:50 +0200 Subject: [PATCH 0323/1340] Upgrade jobs to run on Ubuntu 2404 --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8384f2eea..68626408f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1293,7 +1293,7 @@ jobs: - matrix_notify_failure_unless_pr t_ubu_soltest_all: &t_ubu_soltest_all - <<: *base_ubuntu2204_large + <<: *base_ubuntu2404_large parallelism: 50 steps: - soltest_all @@ -1335,10 +1335,10 @@ jobs: - soltest t_ubu_clang_soltest: &t_ubu_clang_soltest - <<: *base_ubuntu2204_clang + <<: *base_ubuntu2404_clang parallelism: 20 environment: - <<: *base_ubuntu2204_clang_env + <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> OPTIMIZE: 0 # The high parallelism in this job is causing the SMT tests to run out of memory, @@ -1353,7 +1353,7 @@ jobs: <<: *t_ubu_soltest_all t_ubu_cli: &t_ubu_cli - <<: *base_ubuntu2204_small + <<: *base_ubuntu2404_small parallelism: 8 # Should match number of tests in .circleci/parallel_cli_tests.py steps: - cmdline_tests From 1d58415f1ed8377404d6597621f1e364a3c5be4e Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 13 Sep 2024 10:11:11 +0200 Subject: [PATCH 0324/1340] Update `evmc to` `12.0.0` and `evmone` to `0.12.0` --- .circleci/config.yml | 12 ++-- .circleci/osx_install_dependencies.sh | 28 ++------ scripts/install_evmone.ps1 | 2 +- test/Common.h | 6 +- test/evmc/README.md | 2 +- test/evmc/bytes.hpp | 93 +++++++++++++++++++++++++++ test/evmc/evmc.h | 65 +++++++++++++------ test/evmc/evmc.hpp | 3 - test/evmc/helpers.h | 2 + test/evmc/hex.hpp | 8 +-- test/evmc/mocked_host.hpp | 5 +- 11 files changed, 160 insertions(+), 66 deletions(-) create mode 100644 test/evmc/bytes.hpp diff --git a/.circleci/config.yml b/.circleci/config.yml index 68626408f..931ce476a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,16 +9,16 @@ version: 2.1 parameters: ubuntu-2004-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-24 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:b8b645fa7ab40d55f2d16eac295d16ca01ec51d32be7d668ae6eaecd47dbd763" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-25 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:b3f321fb2d8e7a41ca9328672061c1840e5cd3fb5be503aa158d1c508deacf0a" ubuntu-2204-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-9 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:80247de9655b1f39afd4ac22b14266bc9b9a0d64b283ae8fb9cb5b8250e4e77d" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-10 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:ba2d878c26d681a7d6c1922258b47c2e5dd61d0e46ab4c6a4862b473e61997b6" ubuntu-2204-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-8 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:2662376fe0e1ec2d346495a19a6d64508c1048d5a7325d8600c33c343fa64a0f" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-9 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:703cdad5fa5c8686a3080ebb1aea1485ded2446561bf56e2945a87f2fa20a446" ubuntu-2404-docker-image: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-1 diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index 5436c31fe..dff85b489 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -112,26 +112,10 @@ then rm -rf "$z3_dir" # evmone - evmone_version="0.11.0" - if [[ $(uname -m) == 'arm64' ]] - then - # evmone does not provide any builds for apple silicon yet. so lets just build it locally. - # be aware that we are only building the arm version here, we don't build a universal binary. - git clone https://github.com/ethereum/evmone.git - cd evmone - git checkout "v${evmone_version}" - git submodule update --init - cmake -S . -B build - cmake --build build - cd build - sudo make install - cd ../.. - rm -rf evmone - else - evmone_package="evmone-${evmone_version}-darwin-x86_64.tar.gz" - wget "https://github.com/ethereum/evmone/releases/download/v${evmone_version}/${evmone_package}" - validate_checksum "$evmone_package" 83ed20676681d9a31bd30cac399ab7c615ccab8adb8087cc2c7e9cd22b4d2efc - tar xzpf "$evmone_package" -C /usr/local - rm "$evmone_package" - fi + evmone_version="0.12.0" + evmone_package="evmone-${evmone_version}-darwin-arm64.tar.gz" + wget "https://github.com/ethereum/evmone/releases/download/v${evmone_version}/${evmone_package}" + validate_checksum "$evmone_package" e164e0d2b985cc1cca07b501538b2e804bf872d1d8d531f9241d518a886234a6 + sudo tar xzpf "$evmone_package" -C /usr/local + rm "$evmone_package" fi diff --git a/scripts/install_evmone.ps1 b/scripts/install_evmone.ps1 index 5864f2491..7295afa01 100644 --- a/scripts/install_evmone.ps1 +++ b/scripts/install_evmone.ps1 @@ -3,6 +3,6 @@ $ErrorActionPreference = "Stop" # Needed for Invoke-WebRequest to work via CI. $progressPreference = "silentlyContinue" -Invoke-WebRequest -URI "https://github.com/ethereum/evmone/releases/download/v0.11.0/evmone-0.11.0-windows-amd64.zip" -OutFile "evmone.zip" +Invoke-WebRequest -URI "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-windows-amd64.zip" -OutFile "evmone.zip" tar -xf evmone.zip "bin/evmone.dll" mv bin/evmone.dll deps/ diff --git a/test/Common.h b/test/Common.h index b5963c887..3adb980a0 100644 --- a/test/Common.h +++ b/test/Common.h @@ -34,13 +34,13 @@ namespace solidity::test #ifdef _WIN32 static constexpr auto evmoneFilename = "evmone.dll"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.11.0/evmone-0.11.0-windows-amd64.zip"; +static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-windows-amd64.zip"; #elif defined(__APPLE__) static constexpr auto evmoneFilename = "libevmone.dylib"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.11.0/evmone-0.11.0-darwin-x86_64.tar.gz"; +static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-darwin-x86_64.tar.gz"; #else static constexpr auto evmoneFilename = "libevmone.so"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.11.0/evmone-0.11.0-linux-x86_64.tar.gz"; +static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz"; #endif struct ConfigException: public util::Exception {}; diff --git a/test/evmc/README.md b/test/evmc/README.md index 9381b4f53..35fb11901 100644 --- a/test/evmc/README.md +++ b/test/evmc/README.md @@ -1,6 +1,6 @@ # EVMC -This is an import of [EVMC](https://github.com/ethereum/evmc) version [11.0.0](https://github.com/ethereum/evmc/releases/tag/v11.0.0). +This is an import of [EVMC](https://github.com/ethereum/evmc) version [12.0.0](https://github.com/ethereum/evmc/releases/tag/v12.0.0). Steps when upgrading: - Copy all from [include/evmc](https://github.com/ethereum/evmc/tree/master/include/evmc) to [test/evmc](https://github.com/ethereum/solidity/tree/develop/test/evmc) diff --git a/test/evmc/bytes.hpp b/test/evmc/bytes.hpp new file mode 100644 index 000000000..34ddc2f2c --- /dev/null +++ b/test/evmc/bytes.hpp @@ -0,0 +1,93 @@ +// EVMC: Ethereum Client-VM Connector API. +// Copyright 2024 The EVMC Authors. +// Licensed under the Apache License, Version 2.0. +#pragma once + +#include +#include +#include +#include + +namespace evmc +{ +/// The char traits for byte-like types. +/// +/// See: https://en.cppreference.com/w/cpp/string/char_traits. +template +struct byte_traits : std::char_traits +{ + static_assert(sizeof(T) == 1, "type must be a byte"); + + using char_type = T; ///< The byte type. + + /// Assigns c2 to c1. + static constexpr void assign(char_type& c1, const char_type& c2) { c1 = c2; } + + /// Assigns value to each byte in [ptr, ptr+count). + static constexpr char_type* assign(char_type* ptr, std::size_t count, char_type value) + { + std::fill_n(ptr, count, value); + return ptr; + } + + /// Returns true if bytes are equal. + static constexpr bool eq(char_type a, char_type b) { return a == b; } + + /// Returns true if byte a is less than byte b. + static constexpr bool lt(char_type a, char_type b) { return a < b; } + + /// Copies count bytes from src to dest. Performs correctly even if ranges overlap. + static constexpr char_type* move(char_type* dest, const char_type* src, std::size_t count) + { + if (dest < src) + std::copy_n(src, count, dest); + else if (src < dest) + std::copy_backward(src, src + count, dest + count); + return dest; + } + + /// Copies count bytes from src to dest. The ranges must not overlap. + static constexpr char_type* copy(char_type* dest, const char_type* src, std::size_t count) + { + std::copy_n(src, count, dest); + return dest; + } + + /// Compares lexicographically the bytes in two ranges of equal length. + static constexpr int compare(const char_type* a, const char_type* b, std::size_t count) + { + for (; count != 0; --count, ++a, ++b) + { + if (lt(*a, *b)) + return -1; + if (lt(*b, *a)) + return 1; + } + return 0; + } + + /// Returns the length of a null-terminated byte string. + // TODO: Not constexpr + static std::size_t length(const char_type* s) + { + return std::strlen(reinterpret_cast(s)); + } + + /// Finds the value in the range of bytes and returns the pointer to the first occurrence + /// or nullptr if not found. + static constexpr const char_type* find(const char_type* s, + std::size_t count, + const char_type& value) + { + const auto end = s + count; + const auto p = std::find(s, end, value); + return p != end ? p : nullptr; + } +}; + +/// String of unsigned chars representing bytes. +using bytes = std::basic_string>; + +/// String view of unsigned chars representing bytes. +using bytes_view = std::basic_string_view>; +} // namespace evmc diff --git a/test/evmc/evmc.h b/test/evmc/evmc.h index 571c97f47..bec847597 100644 --- a/test/evmc/evmc.h +++ b/test/evmc/evmc.h @@ -44,7 +44,7 @@ enum * * @see @ref versioning */ - EVMC_ABI_VERSION = 11 + EVMC_ABI_VERSION = 12 }; @@ -79,7 +79,8 @@ enum evmc_call_kind The value param ignored. */ EVMC_CALLCODE = 2, /**< Request CALLCODE. */ EVMC_CREATE = 3, /**< Request CREATE. */ - EVMC_CREATE2 = 4 /**< Request CREATE2. Valid since Constantinople.*/ + EVMC_CREATE2 = 4, /**< Request CREATE2. Valid since Constantinople.*/ + EVMC_EOFCREATE = 5 /**< Request EOFCREATE. Valid since Prague.*/ }; /** The flags for ::evmc_message. */ @@ -168,7 +169,8 @@ struct evmc_message /** * The optional value used in new contract address construction. * - * Needed only for a Host to calculate created address when kind is ::EVMC_CREATE2. + * Needed only for a Host to calculate created address when kind is ::EVMC_CREATE2 or + * ::EVMC_EOFCREATE. * Ignored in evmc_execute_fn(). */ evmc_bytes32 create2_salt; @@ -179,7 +181,7 @@ struct evmc_message * For ::EVMC_CALLCODE or ::EVMC_DELEGATECALL this may be different from * the evmc_message::recipient. * Not required when invoking evmc_execute_fn(), only when invoking evmc_call_fn(). - * Ignored if kind is ::EVMC_CREATE or ::EVMC_CREATE2. + * Ignored if kind is ::EVMC_CREATE, ::EVMC_CREATE2 or ::EVMC_EOFCREATE. * * In case of ::EVMC_CAPABILITY_PRECOMPILES implementation, this fields should be inspected * to identify the requested precompile. @@ -187,24 +189,43 @@ struct evmc_message * Defined as `c` in the Yellow Paper. */ evmc_address code_address; + + /** + * The code to be executed. + */ + const uint8_t* code; + + /** + * The length of the code to be executed. + */ + size_t code_size; }; +/** The hashed initcode used for TXCREATE instruction. */ +typedef struct evmc_tx_initcode +{ + evmc_bytes32 hash; /**< The initcode hash. */ + const uint8_t* code; /**< The code. */ + size_t code_size; /**< The length of the code. */ +} evmc_tx_initcode; /** The transaction and block data for execution. */ struct evmc_tx_context { - evmc_uint256be tx_gas_price; /**< The transaction gas price. */ - evmc_address tx_origin; /**< The transaction origin account. */ - evmc_address block_coinbase; /**< The miner of the block. */ - int64_t block_number; /**< The block number. */ - int64_t block_timestamp; /**< The block timestamp. */ - int64_t block_gas_limit; /**< The block gas limit. */ - evmc_uint256be block_prev_randao; /**< The block previous RANDAO (EIP-4399). */ - evmc_uint256be chain_id; /**< The blockchain's ChainID. */ - evmc_uint256be block_base_fee; /**< The block base fee per gas (EIP-1559, EIP-3198). */ - evmc_uint256be blob_base_fee; /**< The blob base fee (EIP-7516). */ - const evmc_bytes32* blob_hashes; /**< The array of blob hashes (EIP-4844). */ - size_t blob_hashes_count; /**< The number of blob hashes (EIP-4844). */ + evmc_uint256be tx_gas_price; /**< The transaction gas price. */ + evmc_address tx_origin; /**< The transaction origin account. */ + evmc_address block_coinbase; /**< The miner of the block. */ + int64_t block_number; /**< The block number. */ + int64_t block_timestamp; /**< The block timestamp. */ + int64_t block_gas_limit; /**< The block gas limit. */ + evmc_uint256be block_prev_randao; /**< The block previous RANDAO (EIP-4399). */ + evmc_uint256be chain_id; /**< The blockchain's ChainID. */ + evmc_uint256be block_base_fee; /**< The block base fee per gas (EIP-1559, EIP-3198). */ + evmc_uint256be blob_base_fee; /**< The blob base fee (EIP-7516). */ + const evmc_bytes32* blob_hashes; /**< The array of blob hashes (EIP-4844). */ + size_t blob_hashes_count; /**< The number of blob hashes (EIP-4844). */ + const evmc_tx_initcode* initcodes; /**< The array of transaction initcodes (TXCREATE). */ + size_t initcodes_count; /**< The number of transaction initcodes (TXCREATE). */ }; /** @@ -1007,7 +1028,6 @@ enum evmc_revision /** * The Cancun revision. * - * The future next revision after Shanghai. * https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/cancun.md */ EVMC_CANCUN = 12, @@ -1019,15 +1039,22 @@ enum evmc_revision */ EVMC_PRAGUE = 13, + /** + * The Osaka revision. + * + * The future next revision after Prague. + */ + EVMC_OSAKA = 14, + /** The maximum EVM revision supported. */ - EVMC_MAX_REVISION = EVMC_PRAGUE, + EVMC_MAX_REVISION = EVMC_OSAKA, /** * The latest known EVM revision with finalized specification. * * This is handy for EVM tools to always use the latest revision available. */ - EVMC_LATEST_STABLE_REVISION = EVMC_SHANGHAI + EVMC_LATEST_STABLE_REVISION = EVMC_CANCUN }; diff --git a/test/evmc/evmc.hpp b/test/evmc/evmc.hpp index 91386c46f..2dfabf826 100644 --- a/test/evmc/evmc.hpp +++ b/test/evmc/evmc.hpp @@ -20,9 +20,6 @@ static_assert(EVMC_LATEST_STABLE_REVISION <= EVMC_MAX_REVISION, /// @ingroup cpp namespace evmc { -/// String view of uint8_t chars. -using bytes_view = std::basic_string_view; - /// The big-endian 160-bit hash suitable for keeping an Ethereum address. /// /// This type wraps C ::evmc_address to make sure objects of this type are always initialized. diff --git a/test/evmc/helpers.h b/test/evmc/helpers.h index 683567ef1..a5f6c3637 100644 --- a/test/evmc/helpers.h +++ b/test/evmc/helpers.h @@ -301,6 +301,8 @@ static inline const char* evmc_revision_to_string(enum evmc_revision rev) return "Cancun"; case EVMC_PRAGUE: return "Prague"; + case EVMC_OSAKA: + return "Osaka"; } return ""; } diff --git a/test/evmc/hex.hpp b/test/evmc/hex.hpp index 31bbe5195..a2505b71f 100644 --- a/test/evmc/hex.hpp +++ b/test/evmc/hex.hpp @@ -3,6 +3,7 @@ // Licensed under the Apache License, Version 2.0. #pragma once +#include #include #include #include @@ -11,13 +12,6 @@ namespace evmc { -/// String of uint8_t chars. -using bytes = std::basic_string; - -/// String view of uint8_t chars. -using bytes_view = std::basic_string_view; - - /// Encode a byte to a hex string. inline std::string hex(uint8_t b) noexcept { diff --git a/test/evmc/mocked_host.hpp b/test/evmc/mocked_host.hpp index 205a136b3..2b37113ad 100644 --- a/test/evmc/mocked_host.hpp +++ b/test/evmc/mocked_host.hpp @@ -6,16 +6,13 @@ #include #include #include -#include #include +#include #include #include namespace evmc { -/// The string of bytes. -using bytes = std::basic_string; - /// Extended value (with original value and access flag) for account storage. struct StorageValue { From 322d6561360eecf71ce39f6383bc1d95f3083d54 Mon Sep 17 00:00:00 2001 From: Vishwa Mehta Date: Mon, 16 Sep 2024 18:20:44 +0530 Subject: [PATCH 0325/1340] Make it easier for users to discover that copying arrays and structs to storage is unimplemented only in legacy codegen and works via IR (#15432) --- libsolidity/codegen/ArrayUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index e653239cf..5dd94aebc 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -224,7 +224,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons else if (sourceBaseType->isValueType()) CompilerUtils(_context).loadFromMemoryDynamic(*sourceBaseType, fromCalldata, true, false); else - solUnimplemented("Copying of type " + _sourceType.toString(false) + " to storage not yet supported."); + solUnimplemented("Copying of type " + _sourceType.toString(false) + " to storage is not supported in legacy (only supported by the IR pipeline). Hint: try compiling with `--via-ir` (CLI) or the equivalent `viaIR: true` (Standard JSON)"); // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] ... assertThrow( 2 + byteOffsetSize + sourceBaseType->sizeOnStack() <= 16, From 2e6a2d2ba4f0c75c027a949ae57df73b7885c2b7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 9 Sep 2024 10:26:22 +0200 Subject: [PATCH 0326/1340] Add SSACFG loop nesting forest --- libyul/CMakeLists.txt | 2 + .../backends/evm/SSACFGLoopNestingForest.cpp | 90 +++++++ libyul/backends/evm/SSACFGLoopNestingForest.h | 61 +++++ libyul/backends/evm/SSACFGTopologicalSort.cpp | 39 ++- libyul/backends/evm/SSACFGTopologicalSort.h | 22 +- .../yulSSAControlFlowGraph/nested_for.yul | 231 ++++++++++++++++++ 6 files changed, 408 insertions(+), 37 deletions(-) create mode 100644 libyul/backends/evm/SSACFGLoopNestingForest.cpp create mode 100644 libyul/backends/evm/SSACFGLoopNestingForest.h create mode 100644 test/libyul/yulSSAControlFlowGraph/nested_for.yul diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 704e04921..e790f6c17 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -65,6 +65,8 @@ add_library(yul backends/evm/NoOutputAssembly.cpp backends/evm/OptimizedEVMCodeTransform.cpp backends/evm/OptimizedEVMCodeTransform.h + backends/evm/SSACFGLoopNestingForest.cpp + backends/evm/SSACFGLoopNestingForest.h backends/evm/SSACFGTopologicalSort.cpp backends/evm/SSACFGTopologicalSort.h backends/evm/SSAControlFlowGraph.h diff --git a/libyul/backends/evm/SSACFGLoopNestingForest.cpp b/libyul/backends/evm/SSACFGLoopNestingForest.cpp new file mode 100644 index 000000000..b28597813 --- /dev/null +++ b/libyul/backends/evm/SSACFGLoopNestingForest.cpp @@ -0,0 +1,90 @@ +/* + 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 + +#include + +using namespace solidity::yul; + +SSACFGLoopNestingForest::SSACFGLoopNestingForest(ForwardSSACFGTopologicalSort const& _sort): + m_sort(_sort), + m_cfg(_sort.cfg()), + m_vertexPartition(m_cfg.numBlocks()), + m_loopParents(m_cfg.numBlocks(), std::numeric_limits::max()) +{ + auto dfsOrder = m_sort.preOrder(); + // we go from innermost to outermost + std::reverse(dfsOrder.begin(), dfsOrder.end()); + + for (auto const& blockId: dfsOrder) + findLoop(blockId); + + // get the root nodes + for (auto loopHeader: m_loopNodes) + { + while (m_loopParents[loopHeader] != std::numeric_limits::max()) + loopHeader = m_loopParents[loopHeader]; + m_loopRootNodes.insert(loopHeader); + } +} + +void SSACFGLoopNestingForest::findLoop(size_t const _potentialHeader) +{ + if (m_sort.backEdgeTargets().count(_potentialHeader) > 0) + { + std::set loopBody; + std::set workList; + for (auto const pred: m_cfg.block(SSACFG::BlockId{_potentialHeader}).entries) + { + auto const representative = m_vertexPartition.find(pred.value); + if ( + representative != _potentialHeader && + m_sort.backEdge(SSACFG::BlockId{pred}, SSACFG::BlockId{_potentialHeader}) + ) + workList.insert(representative); + } + + while (!workList.empty()) + { + auto const y = workList.extract(workList.begin()).value(); + loopBody.insert(y); + + for (auto const& predecessor: m_cfg.block(SSACFG::BlockId{y}).entries) + { + if (!m_sort.backEdge(SSACFG::BlockId{predecessor}, SSACFG::BlockId{y})) + { + auto const predecessorHeader = m_vertexPartition.find(predecessor.value); + if (predecessorHeader != _potentialHeader && loopBody.count(predecessorHeader) == 0) + workList.insert(predecessorHeader); + } + } + } + + if (!loopBody.empty()) + collapse(loopBody, _potentialHeader); + } +} +void SSACFGLoopNestingForest::collapse(std::set const& _loopBody, size_t _loopHeader) +{ + for (auto const z: _loopBody) + { + m_loopParents[z] = _loopHeader; + m_vertexPartition.merge(_loopHeader, z, false); // don't merge by size, loop header should be representative + } + yulAssert(m_vertexPartition.find(_loopHeader) == _loopHeader); // representative was preserved + m_loopNodes.insert(_loopHeader); +} diff --git a/libyul/backends/evm/SSACFGLoopNestingForest.h b/libyul/backends/evm/SSACFGLoopNestingForest.h new file mode 100644 index 000000000..0aad6ab39 --- /dev/null +++ b/libyul/backends/evm/SSACFGLoopNestingForest.h @@ -0,0 +1,61 @@ +/* + 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 + +#pragma once + +#include +#include + +#include + +#include +#include +#include + +namespace solidity::yul +{ + +/// Constructs a loop nesting forest for an SSACFG using Tarjan's algorithm [1]. +/// +/// [1] Ramalingam, Ganesan. "Identifying loops in almost linear time." +/// ACM Transactions on Programming Languages and Systems (TOPLAS) 21.2 (1999): 175-188. +class SSACFGLoopNestingForest +{ +public: + explicit SSACFGLoopNestingForest(ForwardSSACFGTopologicalSort const& _sort); + + /// blocks which are not contained in a loop get assigned the loop parent numeric_limit::max() + std::vector const& loopParents() const { return m_loopParents; } + /// all loop nodes (entry blocks for loops), also nested ones + std::set const& loopNodes() const { return m_loopNodes; } + /// root loop nodes in the forest for outer-most loops + std::set const& loopRootNodes() const { return m_loopRootNodes; } +private: + void findLoop(size_t _potentialHeader); + void collapse(std::set const& _loopBody, size_t _loopHeader); + + ForwardSSACFGTopologicalSort const& m_sort; + SSACFG const& m_cfg; + + util::ContiguousDisjointSet m_vertexPartition; + std::vector m_loopParents; + std::set m_loopNodes; + std::set m_loopRootNodes; +}; + +} diff --git a/libyul/backends/evm/SSACFGTopologicalSort.cpp b/libyul/backends/evm/SSACFGTopologicalSort.cpp index e0370aa27..5e3e0c0ec 100644 --- a/libyul/backends/evm/SSACFGTopologicalSort.cpp +++ b/libyul/backends/evm/SSACFGTopologicalSort.cpp @@ -22,18 +22,17 @@ using namespace solidity::yul; ForwardSSACFGTopologicalSort::ForwardSSACFGTopologicalSort(SSACFG const& _cfg): m_cfg(_cfg), - m_explored(m_cfg.numBlocks(), false), - m_reversedPostOrder(m_cfg.numBlocks(), std::numeric_limits::max()), - m_preOrder(m_cfg.numBlocks(), std::numeric_limits::max()), - m_maxSubtreePreOrder(m_cfg.numBlocks(), 0), - m_predecessors(m_cfg.numBlocks()) + m_explored(m_cfg.numBlocks(), false), m_blockWisePreOrder(m_cfg.numBlocks(), 0), + m_blockWiseMaxSubtreePreOrder(m_cfg.numBlocks(), 0) { + yulAssert(m_cfg.entry.value == 0); + m_preOrder.reserve(m_cfg.numBlocks()); + m_postOrder.reserve(m_cfg.numBlocks()); for (size_t id = 0; id < m_cfg.numBlocks(); ++id) { if (!m_explored[id]) dfs(id); } - std::reverse(m_reversedPostOrder.begin(), m_reversedPostOrder.end()); for (auto const& [v1, v2]: m_potentialBackEdges) if (ancestor(v2, v1)) @@ -43,40 +42,32 @@ ForwardSSACFGTopologicalSort::ForwardSSACFGTopologicalSort(SSACFG const& _cfg): void ForwardSSACFGTopologicalSort::dfs(size_t const _vertex) { yulAssert(!m_explored[_vertex]); m_explored[_vertex] = true; - m_preOrder[_vertex] = m_currentNode++; - m_maxSubtreePreOrder[_vertex] = m_preOrder[_vertex]; + m_blockWisePreOrder[_vertex] = m_preOrder.size(); + m_blockWiseMaxSubtreePreOrder[_vertex] = m_blockWisePreOrder[_vertex]; + m_preOrder.push_back(_vertex); m_cfg.block(SSACFG::BlockId{_vertex}).forEachExit([&](SSACFG::BlockId const& _exitBlock){ - m_predecessors[_exitBlock.value].insert(_vertex); if (!m_explored[_exitBlock.value]) { dfs(_exitBlock.value); - m_maxSubtreePreOrder[_vertex] = std::max(m_maxSubtreePreOrder[_vertex], m_maxSubtreePreOrder[_exitBlock.value]); + m_blockWiseMaxSubtreePreOrder[_vertex] = std::max(m_blockWiseMaxSubtreePreOrder[_vertex], m_blockWiseMaxSubtreePreOrder[_exitBlock.value]); } else m_potentialBackEdges.emplace_back(_vertex, _exitBlock.value); }); - m_reversedPostOrder[m_preOrder[_vertex]] = _vertex; + m_postOrder.push_back(_vertex); } -std::vector const& ForwardSSACFGTopologicalSort::sortedBlocks() const { return m_reversedPostOrder; } -std::vector const& ForwardSSACFGTopologicalSort::preOrder() const { return m_preOrder; } -std::vector const& ForwardSSACFGTopologicalSort::reversedPostOrder() const { return m_reversedPostOrder; } -std::vector const& ForwardSSACFGTopologicalSort::maxSubtreePreOrder() const { return m_maxSubtreePreOrder; } -std::set const& ForwardSSACFGTopologicalSort::backEdgeTargets() const { return m_backEdgeTargets; } -std::vector> const& ForwardSSACFGTopologicalSort::predecessors() const { return m_predecessors; } -SSACFG const& ForwardSSACFGTopologicalSort::cfg() const { return m_cfg; } - bool ForwardSSACFGTopologicalSort::ancestor(size_t const _block1, size_t const _block2) const { - yulAssert(_block1 < m_preOrder.size()); - yulAssert(_block2 < m_preOrder.size()); + yulAssert(_block1 < m_blockWisePreOrder.size()); + yulAssert(_block2 < m_blockWisePreOrder.size()); - auto const preOrderIndex1 = m_preOrder[_block1]; - auto const preOrderIndex2 = m_preOrder[_block2]; + auto const preOrderIndex1 = m_blockWisePreOrder[_block1]; + auto const preOrderIndex2 = m_blockWisePreOrder[_block2]; bool const node1VisitedBeforeNode2 = preOrderIndex1 <= preOrderIndex2; - bool const node2InSubtreeOfNode1 = preOrderIndex2 <= m_maxSubtreePreOrder[_block1]; + bool const node2InSubtreeOfNode1 = preOrderIndex2 <= m_blockWiseMaxSubtreePreOrder[_block1]; return node1VisitedBeforeNode2 && node2InSubtreeOfNode1; } diff --git a/libyul/backends/evm/SSACFGTopologicalSort.h b/libyul/backends/evm/SSACFGTopologicalSort.h index ec62eb013..973f286f2 100644 --- a/libyul/backends/evm/SSACFGTopologicalSort.h +++ b/libyul/backends/evm/SSACFGTopologicalSort.h @@ -33,28 +33,24 @@ class ForwardSSACFGTopologicalSort public: explicit ForwardSSACFGTopologicalSort(SSACFG const& _cfg); - std::vector const& sortedBlocks() const; - std::vector const& preOrder() const; - std::vector const& reversedPostOrder() const; - std::vector const& maxSubtreePreOrder() const; - std::set const& backEdgeTargets() const; - std::vector> const& predecessors() const; - SSACFG const& cfg() const; - bool ancestor(size_t _block1, size_t _block2) const; + std::vector const& preOrder() const { return m_preOrder; } + std::vector const& postOrder() const { return m_postOrder; } + std::set const& backEdgeTargets() const { return m_backEdgeTargets; } + SSACFG const& cfg() const { return m_cfg; } bool backEdge(SSACFG::BlockId const& _block1, SSACFG::BlockId const& _block2) const; private: void dfs(size_t _vertex); + /// Checks if block1 is an ancestor of block2, ie there's a path from block1 to block2 in the dfs tree + bool ancestor(size_t _block1, size_t _block2) const; SSACFG const& m_cfg; - - size_t m_currentNode {0}; std::vector m_explored{}; - std::vector m_reversedPostOrder{}; + std::vector m_postOrder{}; std::vector m_preOrder{}; - std::vector m_maxSubtreePreOrder{}; + std::vector m_blockWisePreOrder{}; + std::vector m_blockWiseMaxSubtreePreOrder{}; std::vector> m_potentialBackEdges{}; std::set m_backEdgeTargets{}; - std::vector> m_predecessors{}; }; } diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/yulSSAControlFlowGraph/nested_for.yul new file mode 100644 index 000000000..e078630a6 --- /dev/null +++ b/test/libyul/yulSSAControlFlowGraph/nested_for.yul @@ -0,0 +1,231 @@ +{ + for { let i := 0 } lt(i, 3) { i := add(i, 1) } { + for { let j := 0 } lt(j, 3) { j := add(j, 1) } { + for { let k := 0 } lt(k, 3) { k := add(k, 1) } { + if 0 { + for { let l := 0 } lt(l, 3) { l := add(l, 1) } { + sstore(l, add(add(i,j),k)) + } + } + if 1 { + for { let l := 0 } lt(l, 3) { l := add(l, 1) } { + sstore(l, add(add(i,j),k)) + } + } + } + } + } +} + +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans"] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry0 [label="Entry"]; +// Entry0 -> Block0_0; +// Block0_0 [label="\ +// Block 0\n"]; +// Block0_0 -> Block0_0Exit [arrowhead=none]; +// Block0_0Exit [label="Jump" shape=oval]; +// Block0_0Exit -> Block0_1; +// Block0_1 [label="\ +// Block 1\nv2 := φ(\l\ +// Block 0 => 0,\l\ +// Block 3 => v36\l\ +// )\l\ +// v3 := lt(3, v2)\l\ +// "]; +// Block0_1 -> Block0_1Exit; +// Block0_1Exit [label="{ If v3| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_1Exit:0 -> Block0_4; +// Block0_1Exit:1 -> Block0_2; +// Block0_2 [label="\ +// Block 2\n"]; +// Block0_2 -> Block0_2Exit [arrowhead=none]; +// Block0_2Exit [label="Jump" shape=oval]; +// Block0_2Exit -> Block0_5; +// Block0_4 [label="\ +// Block 4\n"]; +// Block0_4Exit [label="MainExit"]; +// Block0_4 -> Block0_4Exit; +// Block0_5 [label="\ +// Block 5\nv4 := φ(\l\ +// Block 2 => 0,\l\ +// Block 7 => v35\l\ +// )\l\ +// v33 := φ(\l\ +// Block 2 => v2,\l\ +// Block 7 => v18\l\ +// )\l\ +// v5 := lt(3, v4)\l\ +// "]; +// Block0_5 -> Block0_5Exit; +// Block0_5Exit [label="{ If v5| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_5Exit:0 -> Block0_8; +// Block0_5Exit:1 -> Block0_6; +// Block0_6 [label="\ +// Block 6\n"]; +// Block0_6 -> Block0_6Exit [arrowhead=none]; +// Block0_6Exit [label="Jump" shape=oval]; +// Block0_6Exit -> Block0_9; +// Block0_8 [label="\ +// Block 8\n"]; +// Block0_8 -> Block0_8Exit [arrowhead=none]; +// Block0_8Exit [label="Jump" shape=oval]; +// Block0_8Exit -> Block0_3; +// Block0_9 [label="\ +// Block 9\nv6 := φ(\l\ +// Block 6 => 0,\l\ +// Block 11 => v31\l\ +// )\l\ +// v17 := φ(\l\ +// Block 6 => v4,\l\ +// Block 11 => v32\l\ +// )\l\ +// v18 := φ(\l\ +// Block 6 => v33,\l\ +// Block 11 => v34\l\ +// )\l\ +// v7 := lt(3, v6)\l\ +// "]; +// Block0_9 -> Block0_9Exit; +// Block0_9Exit [label="{ If v7| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_9Exit:0 -> Block0_12; +// Block0_9Exit:1 -> Block0_10; +// Block0_3 [label="\ +// Block 3\nv36 := add(1, v33)\l\ +// "]; +// Block0_3 -> Block0_3Exit [arrowhead=none]; +// Block0_3Exit [label="Jump" shape=oval]; +// Block0_3Exit -> Block0_1; +// Block0_10 [label="\ +// Block 10\n"]; +// Block0_10 -> Block0_10Exit; +// Block0_10Exit [label="{ If 0| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_10Exit:0 -> Block0_14; +// Block0_10Exit:1 -> Block0_13; +// Block0_12 [label="\ +// Block 12\n"]; +// Block0_12 -> Block0_12Exit [arrowhead=none]; +// Block0_12Exit [label="Jump" shape=oval]; +// Block0_12Exit -> Block0_7; +// Block0_13 [label="\ +// Block 13\n"]; +// Block0_13 -> Block0_13Exit [arrowhead=none]; +// Block0_13Exit [label="Jump" shape=oval]; +// Block0_13Exit -> Block0_15; +// Block0_14 [label="\ +// Block 14\nv27 := φ(\l\ +// Block 10 => v6,\l\ +// Block 18 => v10\l\ +// )\l\ +// v28 := φ(\l\ +// Block 10 => v17,\l\ +// Block 18 => v11\l\ +// )\l\ +// v29 := φ(\l\ +// Block 10 => v18,\l\ +// Block 18 => v12\l\ +// )\l\ +// "]; +// Block0_14 -> Block0_14Exit; +// Block0_14Exit [label="{ If 1| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_14Exit:0 -> Block0_20; +// Block0_14Exit:1 -> Block0_19; +// Block0_7 [label="\ +// Block 7\nv35 := add(1, v17)\l\ +// "]; +// Block0_7 -> Block0_7Exit [arrowhead=none]; +// Block0_7Exit [label="Jump" shape=oval]; +// Block0_7Exit -> Block0_5; +// Block0_15 [label="\ +// Block 15\nv8 := φ(\l\ +// Block 13 => 0,\l\ +// Block 17 => v16\l\ +// )\l\ +// v9 := lt(3, v8)\l\ +// "]; +// Block0_15 -> Block0_15Exit; +// Block0_15Exit [label="{ If v9| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_15Exit:0 -> Block0_18; +// Block0_15Exit:1 -> Block0_16; +// Block0_19 [label="\ +// Block 19\n"]; +// Block0_19 -> Block0_19Exit [arrowhead=none]; +// Block0_19Exit [label="Jump" shape=oval]; +// Block0_19Exit -> Block0_21; +// Block0_20 [label="\ +// Block 20\nv30 := φ(\l\ +// Block 14 => v27,\l\ +// Block 24 => v21\l\ +// )\l\ +// v32 := φ(\l\ +// Block 14 => v28,\l\ +// Block 24 => v22\l\ +// )\l\ +// v34 := φ(\l\ +// Block 14 => v29,\l\ +// Block 24 => v23\l\ +// )\l\ +// "]; +// Block0_20 -> Block0_20Exit [arrowhead=none]; +// Block0_20Exit [label="Jump" shape=oval]; +// Block0_20Exit -> Block0_11; +// Block0_16 [label="\ +// Block 16\nv13 := add(v17, v18)\l\ +// v14 := add(v6, v13)\l\ +// sstore(v14, v8)\l\ +// "]; +// Block0_16 -> Block0_16Exit [arrowhead=none]; +// Block0_16Exit [label="Jump" shape=oval]; +// Block0_16Exit -> Block0_17; +// Block0_18 [label="\ +// Block 18\n"]; +// Block0_18 -> Block0_18Exit [arrowhead=none]; +// Block0_18Exit [label="Jump" shape=oval]; +// Block0_18Exit -> Block0_14; +// Block0_21 [label="\ +// Block 21\nv19 := φ(\l\ +// Block 19 => 0,\l\ +// Block 23 => v26\l\ +// )\l\ +// v20 := lt(3, v19)\l\ +// "]; +// Block0_21 -> Block0_21Exit; +// Block0_21Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_21Exit:0 -> Block0_24; +// Block0_21Exit:1 -> Block0_22; +// Block0_11 [label="\ +// Block 11\nv31 := add(1, v30)\l\ +// "]; +// Block0_11 -> Block0_11Exit [arrowhead=none]; +// Block0_11Exit [label="Jump" shape=oval]; +// Block0_11Exit -> Block0_9; +// Block0_17 [label="\ +// Block 17\nv16 := add(1, v8)\l\ +// "]; +// Block0_17 -> Block0_17Exit [arrowhead=none]; +// Block0_17Exit [label="Jump" shape=oval]; +// Block0_17Exit -> Block0_15; +// Block0_22 [label="\ +// Block 22\nv24 := add(v28, v29)\l\ +// v25 := add(v27, v24)\l\ +// sstore(v25, v19)\l\ +// "]; +// Block0_22 -> Block0_22Exit [arrowhead=none]; +// Block0_22Exit [label="Jump" shape=oval]; +// Block0_22Exit -> Block0_23; +// Block0_24 [label="\ +// Block 24\n"]; +// Block0_24 -> Block0_24Exit [arrowhead=none]; +// Block0_24Exit [label="Jump" shape=oval]; +// Block0_24Exit -> Block0_20; +// Block0_23 [label="\ +// Block 23\nv26 := add(1, v19)\l\ +// "]; +// Block0_23 -> Block0_23Exit [arrowhead=none]; +// Block0_23Exit [label="Jump" shape=oval]; +// Block0_23Exit -> Block0_21; +// } From 2b0d08cb4ef121ee975b76a4af737d4a1ce2c1fa Mon Sep 17 00:00:00 2001 From: Anandu Raveendran <77606647+anandhuRaveendran@users.noreply.github.com> Date: Tue, 17 Sep 2024 14:42:07 +0530 Subject: [PATCH 0327/1340] Apostrophe added in README.md (#15431) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Apostrophe corrected - Update README.md Apostrophe corrected * Update README.md --------- Co-authored-by: Nikola Matić --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e64f8cbfd..197259998 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ The Solidity documentation is hosted using [Read the Docs](https://docs.solidity Solidity is still under development. Contributions are always welcome! Please follow the -[Developers Guide](https://docs.soliditylang.org/en/latest/contributing.html) +[Developer's Guide](https://docs.soliditylang.org/en/latest/contributing.html) if you want to help. You can find our current feature and bug priorities for forthcoming From 963d70ba6c7ca0008147cc533eb7fd5060a30f9f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:12:38 +0200 Subject: [PATCH 0328/1340] Yul: Add toDot to SSACFG --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/SSAControlFlowGraph.cpp | 242 ++++++++++++++++++++ libyul/backends/evm/SSAControlFlowGraph.h | 2 + test/libyul/SSAControlFlowGraphTest.cpp | 208 +---------------- 4 files changed, 247 insertions(+), 206 deletions(-) create mode 100644 libyul/backends/evm/SSAControlFlowGraph.cpp diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index e790f6c17..f621b2089 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -69,6 +69,7 @@ add_library(yul backends/evm/SSACFGLoopNestingForest.h backends/evm/SSACFGTopologicalSort.cpp backends/evm/SSACFGTopologicalSort.h + backends/evm/SSAControlFlowGraph.cpp backends/evm/SSAControlFlowGraph.h backends/evm/SSAControlFlowGraphBuilder.cpp backends/evm/SSAControlFlowGraphBuilder.h diff --git a/libyul/backends/evm/SSAControlFlowGraph.cpp b/libyul/backends/evm/SSAControlFlowGraph.cpp new file mode 100644 index 000000000..e98936aaa --- /dev/null +++ b/libyul/backends/evm/SSAControlFlowGraph.cpp @@ -0,0 +1,242 @@ +/* + 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 + +#include + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtautological-compare" +#include +#pragma GCC diagnostic pop + +#include + +using namespace solidity; +using namespace solidity::util; +using namespace solidity::yul; + +namespace +{ +class SSACFGPrinter +{ +public: + SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId) + { + printBlock(_cfg, _blockId, 0); + } + SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function) + { + printFunction(_cfg, _functionIndex, _function); + } + friend std::ostream& operator<<(std::ostream& stream, SSACFGPrinter const& printer) { + stream << printer.m_result.str(); + return stream; + } +private: + static std::string varToString(SSACFG const& _cfg, SSACFG::ValueId _var) { + if (_var.value == std::numeric_limits::max()) + return "INVALID"; + auto const& info = _cfg.valueInfo(_var); + return std::visit( + GenericVisitor{ + [&](SSACFG::UnreachableValue const&) -> std::string { + return "[unreachable]"; + }, + [&](SSACFG::PhiValue const&) -> std::string { + return fmt::format("v{}", _var.value); + }, + [&](SSACFG::VariableValue const&) -> std::string { + return fmt::format("v{}", _var.value); + }, + [&](SSACFG::LiteralValue const& _literal) -> std::string { + return formatNumberReadable(_literal.value); + } + }, + info + ); + } + + static std::string formatPhi(SSACFG const& _cfg, SSACFG::PhiValue const& _phiValue) + { + auto const transform = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; + std::vector formattedArgs; + formattedArgs.reserve(_phiValue.arguments.size()); + for (auto const& [arg, entry]: ranges::zip_view(_phiValue.arguments | ranges::views::transform(transform), _cfg.block(_phiValue.block).entries)) + formattedArgs.push_back(fmt::format("Block {} => {}", entry.value, arg)); + if (!formattedArgs.empty()) + return fmt::format("φ(\\l\\\n\t{}\\l\\\n)", fmt::join(formattedArgs, ",\\l\\\n\t")); + else + return "φ()"; + } + + void writeBlock(SSACFG const& _cfg, SSACFG::BlockId const& _id, SSACFG::BasicBlock const& _block, size_t const _functionIndex) + { + auto const valueToString = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; + bool entryBlock = _id.value == 0 && _functionIndex == 0; + if (entryBlock) + { + m_result << fmt::format("Entry{} [label=\"Entry\"];\n", _functionIndex); + m_result << fmt::format("Entry{} -> Block{}_{};\n", _functionIndex, _functionIndex, _id.value); + } + { + m_result << fmt::format("Block{1}_{0} [label=\"\\\nBlock {0}\\n", _id.value, _functionIndex); + for (auto const& phi: _block.phis) + { + auto const* phiValue = std::get_if(&_cfg.valueInfo(phi)); + solAssert(phiValue); + m_result << fmt::format("v{} := {}\\l\\\n", phi.value, formatPhi(_cfg, *phiValue)); + } + for (auto const& operation: _block.operations) + { + std::string const label = std::visit(GenericVisitor{ + [&](SSACFG::Call const& _call) { + return _call.function.get().name.str(); + }, + [&](SSACFG::BuiltinCall const& _call) { + return _call.builtin.get().name.str(); + }, + }, operation.kind); + if (!operation.outputs.empty()) + m_result << fmt::format( + "{} := ", + fmt::join(operation.outputs | ranges::views::transform(valueToString), ", ") + ); + m_result << fmt::format( + "{}({})\\l\\\n", + label, + fmt::join(operation.inputs | ranges::views::transform(valueToString), ", ") + ); + } + m_result << "\"];\n"; + std::visit(GenericVisitor{ + [&](SSACFG::BasicBlock::MainExit const&) + { + m_result << fmt::format("Block{}_{}Exit [label=\"MainExit\"];\n", _functionIndex, _id.value); + m_result << fmt::format("Block{1}_{0} -> Block{1}_{0}Exit;\n", _id.value, _functionIndex); + }, + [&](SSACFG::BasicBlock::Jump const& _jump) + { + m_result << fmt::format("Block{1}_{0} -> Block{1}_{0}Exit [arrowhead=none];\n", _id.value, _functionIndex); + m_result << fmt::format("Block{}_{}Exit [label=\"Jump\" shape=oval];\n", _functionIndex, _id.value); + m_result << fmt::format("Block{}_{}Exit -> Block{}_{};\n", _functionIndex, _id.value, _functionIndex, _jump.target.value); + }, + [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) + { + m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"{ If "; + m_result << varToString(_cfg, _conditionalJump.condition); + m_result << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; + m_result << "Block" << _functionIndex << "_" << _id.value; + m_result << "Exit:0 -> Block" << _functionIndex << "_" << _conditionalJump.zero.value << ";\n"; + m_result << "Block" << _functionIndex << "_" << _id.value; + m_result << "Exit:1 -> Block" << _functionIndex << "_" << _conditionalJump.nonZero.value << ";\n"; + }, + [&](SSACFG::BasicBlock::JumpTable const& jt) + { + m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + std::string options; + for (auto const& jumpCase: jt.cases) + { + if (!options.empty()) + options += " | "; + options += fmt::format("<{0}> {0}", formatNumber(jumpCase.first)); + } + if (!options.empty()) + options += " | "; + options += " default"; + m_result << fmt::format("Block{}_{}Exit [label=\"{{ JT | {{ {} }} }}\" shape=Mrecord];\n", _functionIndex, _id.value, options); + for (auto const& jumpCase: jt.cases) + m_result << fmt::format("Block{}_{}Exit:{} -> Block{}_{};\n", _functionIndex, _id.value, formatNumber(jumpCase.first), _functionIndex, jumpCase.second.value); + m_result << fmt::format("Block{}_{}Exit:default -> Block{}_{};\n", _functionIndex, _id.value, _functionIndex, jt.defaultCase.value); + }, + [&](SSACFG::BasicBlock::FunctionReturn const& fr) + { + m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"FunctionReturn[" + << fmt::format("{}", fmt::join(fr.returnValues | ranges::views::transform(valueToString), ", ")) + << "]\"];\n"; + m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + }, + [&](SSACFG::BasicBlock::Terminated const&) + { + m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"Terminated\"];\n"; + m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + } + }, _block.exit); + } + } + + void printBlock(SSACFG const& _cfg, SSACFG::BlockId const& _rootId, size_t const _functionIndex) + { + std::set explored{}; + explored.insert(_rootId); + + std::deque toVisit{}; + toVisit.emplace_back(_rootId); + + while (!toVisit.empty()) + { + auto const id = toVisit.front(); + toVisit.pop_front(); + auto const& block = _cfg.block(id); + writeBlock(_cfg, id, block, _functionIndex); + block.forEachExit( + [&](SSACFG::BlockId const& _exitBlock) + { + if (explored.count(_exitBlock) == 0) + { + explored.insert(_exitBlock); + toVisit.emplace_back(_exitBlock); + } + } + ); + } + } + + void printFunction(SSACFG const& _cfg, size_t const _functionIndex, Scope::Function const& _fun) + { + static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return functionReturnValue.get().name.str(); }; + static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", std::get<1>(arg).value); }; + m_result << "FunctionEntry_" << _fun.name.str() << "_" << _cfg.entry.value << " [label=\""; + if (!_cfg.returns.empty()) + m_result << fmt::format("function {0}:\n {1} := {0}({2})", _fun.name.str(), fmt::join(_cfg.returns | ranges::views::transform(returnsTransform), ", "), fmt::join(_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + else + m_result << fmt::format("function {0}:\n {0}({1})", _fun.name.str(), fmt::join(_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + m_result << "\"];\n"; + m_result << "FunctionEntry_" << _fun.name.str() << "_" << _cfg.entry.value << " -> Block" << _functionIndex << "_" << _cfg.entry.value << ";\n"; + printBlock(_cfg, _cfg.entry, _functionIndex); + } + + std::stringstream m_result{}; +}; +} + +std::string SSACFG::toDot(bool _includeDiGraphDefinition, std::optional _functionIndex) const +{ + std::ostringstream output; + if (_includeDiGraphDefinition) + output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; + if (function) + output << SSACFGPrinter(*this, _functionIndex ? *_functionIndex : static_cast(1), *function); + else + output << SSACFGPrinter(*this, entry); + if (_includeDiGraphDefinition) + output << "}\n"; + return output.str(); +} diff --git a/libyul/backends/evm/SSAControlFlowGraph.h b/libyul/backends/evm/SSAControlFlowGraph.h index f4d0ec242..fd24f06cb 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.h +++ b/libyul/backends/evm/SSAControlFlowGraph.h @@ -206,6 +206,8 @@ class SSACFG yulAssert(it->second.value < m_valueInfos.size()); return it->second; } + + std::string toDot(bool _includeDiGraphDefinition=true, std::optional _functionIndex=std::nullopt) const; private: std::deque m_valueInfos; std::map m_literals; diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/SSAControlFlowGraphTest.cpp index e12751411..1deaaa7f6 100644 --- a/test/libyul/SSAControlFlowGraphTest.cpp +++ b/test/libyul/SSAControlFlowGraphTest.cpp @@ -27,12 +27,6 @@ #include #include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtautological-compare" -#include -#pragma GCC diagnostic pop #ifdef ISOLTEST #include @@ -58,203 +52,6 @@ SSAControlFlowGraphTest::SSAControlFlowGraphTest(std::string const& _filename): m_expectation = m_reader.simpleExpectations(); } -class SSACFGPrinter -{ -public: - SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId) - { - printBlock(_cfg, _blockId, 0); - } - SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function) - { - printFunction(_cfg, _functionIndex, _function); - } - friend std::ostream& operator<<(std::ostream& stream, SSACFGPrinter const& printer) { - stream << printer.m_result.str(); - return stream; - } -private: - std::string varToString(SSACFG const& _cfg, SSACFG::ValueId _var) { - if (_var.value == std::numeric_limits::max()) - return "INVALID"; - auto const& info = _cfg.valueInfo(_var); - return std::visit( - util::GenericVisitor{ - [&](SSACFG::UnreachableValue const&) -> std::string { - return "[unreachable]"; - }, - [&](SSACFG::PhiValue const&) -> std::string { - return fmt::format("v{}", _var.value); - }, - [&](SSACFG::VariableValue const&) -> std::string { - return fmt::format("v{}", _var.value); - }, - [&](SSACFG::LiteralValue const& _literal) -> std::string { - return util::formatNumberReadable(_literal.value); - } - }, - info - ); - } - - std::string formatPhi(SSACFG const& _cfg, SSACFG::PhiValue const& _phiValue) - { - auto const transform = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; - std::vector formattedArgs; - formattedArgs.reserve(_phiValue.arguments.size()); - for(auto const& [arg, entry] : ranges::zip_view(_phiValue.arguments | ranges::views::transform(transform), _cfg.block(_phiValue.block).entries)) - { - formattedArgs.push_back(fmt::format("Block {} => {}", entry.value, arg)); - } - return fmt::format("φ(\\l\\\n\t{}\\l\\\n)", fmt::join(formattedArgs, ",\\l\\\n\t")); - } - - void writeBlock(SSACFG const& _cfg, SSACFG::BlockId const& _id, SSACFG::BasicBlock const& _block, size_t _functionIndex) - { - auto const transform = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; - bool entryBlock = _id.value == 0 && _functionIndex == 0; - if (entryBlock) - { - m_result << fmt::format("Entry{} [label=\"Entry\"];\n", _functionIndex); - m_result << fmt::format("Entry{} -> Block{}_{};\n", _functionIndex, _functionIndex, _id.value); - } - { - m_result << fmt::format("Block{1}_{0} [label=\"\\\nBlock {0}\\n", _id.value, _functionIndex); - for (auto const& phi : _block.phis) - { - auto const* phiValue = std::get_if(&_cfg.valueInfo(phi)); - solAssert(phiValue); - m_result << fmt::format("v{} := {}\\l\\\n", phi.value, formatPhi(_cfg, *phiValue)); - } - for (auto const& operation : _block.operations) - { - std::string const label = std::visit(util::GenericVisitor{ - [&](SSACFG::Call const& _call) { - return _call.function.get().name.str(); - }, - [&](SSACFG::BuiltinCall const& _call) { - return _call.builtin.get().name.str(); - }, - }, operation.kind); - if (operation.outputs.empty()) - m_result << fmt::format( - "{}({})\\l\\\n", - label, - fmt::join(operation.inputs | ranges::views::transform(transform), ", ") - ); - else - m_result << fmt::format( - "{} := {}({})\\l\\\n", - fmt::join(operation.outputs | ranges::views::transform(transform), ", "), - label, - fmt::join(operation.inputs | ranges::views::transform(transform), ", ") - ); - } - m_result << "\"];\n"; - std::visit(util::GenericVisitor{ - [&](SSACFG::BasicBlock::MainExit const&) - { - m_result << fmt::format("Block{}_{}Exit [label=\"MainExit\"];\n", _functionIndex, _id.value); - m_result << fmt::format("Block{1}_{0} -> Block{1}_{0}Exit;\n", _id.value, _functionIndex); - }, - [&](SSACFG::BasicBlock::Jump const& _jump) - { - m_result << fmt::format("Block{1}_{0} -> Block{1}_{0}Exit [arrowhead=none];\n", _id.value, _functionIndex); - m_result << fmt::format("Block{}_{}Exit [label=\"Jump\" shape=oval];\n", _functionIndex, _id.value); - m_result << fmt::format("Block{}_{}Exit -> Block{}_{};\n", _functionIndex, _id.value, _functionIndex, _jump.target.value); - }, - [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) - { - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; - m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"{ If "; - m_result << varToString(_cfg, _conditionalJump.condition); - m_result << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; - m_result << "Block" << _functionIndex << "_" << _id.value; - m_result << "Exit:0 -> Block" << _functionIndex << "_" << _conditionalJump.zero.value << ";\n"; - m_result << "Block" << _functionIndex << "_" << _id.value; - m_result << "Exit:1 -> Block" << _functionIndex << "_" << _conditionalJump.nonZero.value << ";\n"; - }, - [&](SSACFG::BasicBlock::JumpTable const& jt) - { - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; - std::string options; - for(const auto& jumpCase : jt.cases) - { - if (!options.empty()) - options += " | "; - options += fmt::format("<{0}> {0}", formatNumber(jumpCase.first)); - } - if (!options.empty()) - options += " | "; - options += " default"; - m_result << fmt::format("Block{}_{}Exit [label=\"{{ JT | {{ {} }} }}\" shape=Mrecord];\n", _functionIndex, _id.value, options); - for(const auto& jumpCase : jt.cases) - { - m_result << fmt::format("Block{}_{}Exit:{} -> Block{}_{};\n", _functionIndex, _id.value, formatNumber(jumpCase.first), _functionIndex, jumpCase.second.value); - } - m_result << fmt::format("Block{}_{}Exit:default -> Block{}_{};\n", _functionIndex, _id.value, _functionIndex, jt.defaultCase.value); - }, - [&](SSACFG::BasicBlock::FunctionReturn const& fr) - { - m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"FunctionReturn[" - << fmt::format("{}", fmt::join(fr.returnValues | ranges::views::transform(transform), ", ")) - << "]\"];\n"; - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; - }, - [&](SSACFG::BasicBlock::Terminated const&) - { - m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"Terminated\"];\n"; - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; - } - }, _block.exit); - } - - } - - void printBlock(SSACFG const& _cfg, SSACFG::BlockId const& _rootId, size_t _functionIndex) - { - std::set explored{}; - explored.insert(_rootId); - - std::deque toVisit{}; - toVisit.emplace_back(_rootId); - - while(!toVisit.empty()) - { - auto const id = toVisit.front(); - toVisit.pop_front(); - auto const& block = _cfg.block(id); - writeBlock(_cfg, id, block, _functionIndex); - block.forEachExit( - [&](SSACFG::BlockId const& _exitBlock) - { - if (explored.count(_exitBlock) == 0) - { - explored.insert(_exitBlock); - toVisit.emplace_back(_exitBlock); - } - } - ); - } - } - - void printFunction(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _fun) - { - static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return functionReturnValue.get().name.str(); }; - static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", std::get<1>(arg).value); }; - m_result << "FunctionEntry_" << _fun.name.str() << "_" << _cfg.entry.value << " [label=\""; - if (!_cfg.returns.empty()) - m_result << fmt::format("function {0}:\n {1} := {0}({2})", _fun.name.str(), fmt::join(_cfg.returns | ranges::views::transform(returnsTransform), ", "), fmt::join(_cfg.arguments | ranges::views::transform(argsTransform), ", ")); - else - m_result << fmt::format("function {0}:\n {0}({1})", _fun.name.str(), fmt::join(_cfg.arguments | ranges::views::transform(argsTransform), ", ")); - m_result << "\"];\n"; - m_result << "FunctionEntry_" << _fun.name.str() << "_" << _cfg.entry.value << " -> Block" << _functionIndex << "_" << _cfg.entry.value << ";\n"; - printBlock(_cfg, _cfg.entry, _functionIndex); - } - - std::stringstream m_result{}; -}; - TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { ErrorList errors; @@ -275,10 +72,10 @@ TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::st ); output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; - output << SSACFGPrinter(*controlFlow->mainGraph, SSACFG::BlockId{0}); + output << controlFlow->mainGraph->toDot(false); size_t index = 1; for (auto const& [function, functionGraph]: controlFlow->functionGraphMapping) - output << SSACFGPrinter(*functionGraph, index++, *function); + output << functionGraph->toDot(false, index++); output << "}\n"; m_obtainedResult = output.str(); @@ -314,5 +111,4 @@ TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::st #endif return result; - } From 573d7d8f31c59096925e46c01b69348bc124b7ff Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:16:32 +0200 Subject: [PATCH 0329/1340] Yul: Add toDot to ControlFlow --- libyul/backends/evm/ControlFlow.h | 12 ++++++++++++ test/libyul/SSAControlFlowGraphTest.cpp | 13 ++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/libyul/backends/evm/ControlFlow.h b/libyul/backends/evm/ControlFlow.h index 18b43431a..59bc1b677 100644 --- a/libyul/backends/evm/ControlFlow.h +++ b/libyul/backends/evm/ControlFlow.h @@ -38,6 +38,18 @@ struct ControlFlow return std::get<1>(*it); return nullptr; } + + std::string toDot() const + { + std::ostringstream output; + output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; + output << mainGraph->toDot(false); + size_t index = 1; + for (auto const& [function, functionGraph]: functionGraphMapping) + output << functionGraph->toDot(false, index++); + output << "}\n"; + return output.str(); + } }; } diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/SSAControlFlowGraphTest.cpp index 1deaaa7f6..a316356db 100644 --- a/test/libyul/SSAControlFlowGraphTest.cpp +++ b/test/libyul/SSAControlFlowGraphTest.cpp @@ -62,8 +62,6 @@ TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::st return TestResult::FatalError; } - std::ostringstream output; - auto info = AsmAnalyzer::analyzeStrictAssertCorrect(*m_dialect, *object); std::unique_ptr controlFlow = SSAControlFlowGraphBuilder::build( info, @@ -71,14 +69,7 @@ TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::st object->code()->root() ); - output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; - output << controlFlow->mainGraph->toDot(false); - size_t index = 1; - for (auto const& [function, functionGraph]: controlFlow->functionGraphMapping) - output << functionGraph->toDot(false, index++); - output << "}\n"; - - m_obtainedResult = output.str(); + m_obtainedResult = controlFlow->toDot(); auto result = checkResult(_stream, _linePrefix, _formatted); @@ -100,7 +91,7 @@ TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::st boost::process::opstream pipe; boost::process::child child(graphDisplayer, boost::process::std_in < pipe); - pipe << output.str(); + pipe << m_obtainedResult; pipe.flush(); pipe.pipe().close(); if (result == TestResult::Success) From 515f8ab6c5d9c01203e2499ea5c91a5bb0324b9c Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 18 Sep 2024 09:26:19 +0200 Subject: [PATCH 0330/1340] Bump all CI jobs to use Ubuntu 22.04 images --- .circleci/config.yml | 74 ++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 931ce476a..d93fc20c0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -973,7 +973,7 @@ jobs: - matrix_notify_failure_unless_pr chk_pylint: - <<: *base_ubuntu2204_small + <<: *base_ubuntu2404_small steps: - checkout - run: pylint --version @@ -1012,21 +1012,21 @@ jobs: - matrix_notify_failure_unless_pr chk_proofs: - <<: *base_ubuntu2204_small + <<: *base_ubuntu2404_small steps: - checkout - run_proofs - matrix_notify_failure_unless_pr chk_docs_pragma_min_version: - <<: *base_ubuntu2204_small + <<: *base_ubuntu2404_small steps: - checkout - run_docs_pragma_min_version - matrix_notify_failure_unless_pr t_ubu_pyscripts: - <<: *base_ubuntu2204_small + <<: *base_ubuntu2404_small steps: - checkout - run: @@ -1053,25 +1053,25 @@ jobs: b_ubu: &b_ubu # this runs 2x faster on xlarge but takes 4x more resources (compared to medium). # Enough other jobs depend on it that it's worth it though. - <<: *base_ubuntu2204_xlarge + <<: *base_ubuntu2404_xlarge steps: - build # x64 ASAN build, for testing for memory related bugs b_ubu_asan: &b_ubu_asan # Runs slightly faster on large and xlarge but we only run it nightly so efficiency matters more. - <<: *base_ubuntu2204 + <<: *base_ubuntu2404 environment: - <<: *base_ubuntu2204_env + <<: *base_ubuntu2404_env CMAKE_OPTIONS: -DSANITIZE=address CMAKE_BUILD_TYPE: Release steps: - build b_ubu_clang: &b_ubu_clang - <<: *base_ubuntu2204_clang_large + <<: *base_ubuntu2404_clang_large environment: - <<: *base_ubuntu2204_clang_large_env + <<: *base_ubuntu2404_clang_large_env MAKEFLAGS: -j 10 steps: - build @@ -1081,9 +1081,9 @@ jobs: parameters: cmake_options: type: string - <<: *base_ubuntu2204_clang + <<: *base_ubuntu2404_clang environment: - <<: *base_ubuntu2204_clang_env + <<: *base_ubuntu2404_clang_env CMAKE_OPTIONS: << parameters.cmake_options >> steps: - build @@ -1091,7 +1091,7 @@ jobs: b_ubu_force_release: &b_ubu_force_release <<: *b_ubu environment: - <<: *base_ubuntu2204_xlarge_env + <<: *base_ubuntu2404_xlarge_env FORCE_RELEASE: ON b_ubu_static: @@ -1101,7 +1101,7 @@ jobs: # On large runs 2x faster than on medium. 3x on xlarge. <<: *base_ubuntu2004_xlarge environment: - <<: *base_ubuntu2204_xlarge_env + <<: *base_ubuntu2004_xlarge_env CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DSOLC_STATIC_STDLIBS=ON steps: - checkout @@ -1121,9 +1121,9 @@ jobs: b_ubu_codecov: # Runs ~30% faster on large but we only run it nightly so efficiency matters more. - <<: *base_ubuntu2204 + <<: *base_ubuntu2404 environment: - <<: *base_ubuntu2204_env + <<: *base_ubuntu2404_env COVERAGE: ON CMAKE_BUILD_TYPE: Debug steps: @@ -1133,9 +1133,9 @@ jobs: - matrix_notify_failure_unless_pr t_ubu_codecov: - <<: *base_ubuntu2204_large + <<: *base_ubuntu2404_large environment: - <<: *base_ubuntu2204_large_env + <<: *base_ubuntu2404_large_env EVM: << pipeline.parameters.evm-version >> OPTIMIZE: 1 steps: @@ -1158,9 +1158,9 @@ jobs: # Builds in C++20 mode and uses debug build in order to speed up. # Do *NOT* store any artifacts or workspace as we don't run tests on this build. b_ubu_cxx20: - <<: *base_ubuntu2204_large + <<: *base_ubuntu2404_large environment: - <<: *base_ubuntu2204_large_env + <<: *base_ubuntu2404_large_env CMAKE_BUILD_TYPE: Debug CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 MAKEFLAGS: -j 10 @@ -1280,7 +1280,7 @@ jobs: - matrix_notify_failure_unless_pr b_docs: - <<: *base_ubuntu2204_small + <<: *base_ubuntu2404_small steps: - checkout - setup_prerelease_commit_hash @@ -1299,7 +1299,7 @@ jobs: - soltest_all t_ubu_soltest_deprecated_evm_versions: &t_ubu_soltest_deprecated_evm_versions - <<: *base_ubuntu2204_large + <<: *base_ubuntu2404_large parallelism: 50 steps: - checkout @@ -1313,7 +1313,7 @@ jobs: - matrix_notify_failure_unless_pr t_ubu_lsp: &t_ubu_lsp - <<: *base_ubuntu2204_small + <<: *base_ubuntu2404_small steps: - test_lsp @@ -1362,7 +1362,7 @@ jobs: <<: *t_ubu_cli t_ubu_locale: - <<: *base_ubuntu2204_small + <<: *base_ubuntu2404_small steps: - checkout - attach_workspace: @@ -1372,10 +1372,10 @@ jobs: t_ubu_asan_cli: # Runs slightly faster on medium but we only run it nightly so efficiency matters more. - <<: *base_ubuntu2204 + <<: *base_ubuntu2404 parallelism: 8 # Should match number of tests in .circleci/parallel_cli_tests.py environment: - <<: *base_ubuntu2204_env + <<: *base_ubuntu2404_env ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 # Suppress CLN memory leak. # See: https://github.com/ethereum/solidity/issues/13891 for details. @@ -1384,10 +1384,10 @@ jobs: - cmdline_tests t_ubu_asan_soltest: - <<: *base_ubuntu2204 + <<: *base_ubuntu2404 parallelism: 20 environment: - <<: *base_ubuntu2204_env + <<: *base_ubuntu2404_env EVM: << pipeline.parameters.evm-version >> OPTIMIZE: 0 SOLTEST_FLAGS: --no-smt @@ -1399,10 +1399,10 @@ jobs: - soltest t_ubu_asan_clang_soltest: - <<: *base_ubuntu2204_clang + <<: *base_ubuntu2404_clang parallelism: 20 environment: - <<: *base_ubuntu2204_clang_env + <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> OPTIMIZE: 0 SOLTEST_FLAGS: --no-smt @@ -1411,24 +1411,24 @@ jobs: - soltest t_ubu_ubsan_clang_soltest: - <<: *base_ubuntu2204_clang + <<: *base_ubuntu2404_clang parallelism: 20 environment: - <<: *base_ubuntu2204_clang_env + <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> SOLTEST_FLAGS: --no-smt steps: - soltest t_ubu_ubsan_clang_cli: - <<: *base_ubuntu2204_clang + <<: *base_ubuntu2404_clang parallelism: 8 # Should match number of tests in .circleci/parallel_cli_tests.py steps: - cmdline_tests t_ems_solcjs: # Unlike other t_ems jobs this one actually runs 2x faster on medium (compared to small). - <<: *base_ubuntu2204 + <<: *base_ubuntu2404 steps: - checkout - attach_workspace: @@ -1747,7 +1747,7 @@ jobs: parameters: preset: type: string - <<: *base_ubuntu2204_small + <<: *base_ubuntu2404_small parallelism: 2 # For prepare_bytecode_report steps: - checkout @@ -1832,9 +1832,9 @@ jobs: preset: "<< parameters.preset >>" t_bytecode_compare: - <<: *base_ubuntu2204_small + <<: *base_ubuntu2404_small environment: - <<: *base_ubuntu2204_small_env + <<: *base_ubuntu2404_small_env <<: *bytecode_compare_env_presets steps: - checkout @@ -1848,7 +1848,7 @@ jobs: - matrix_notify_failure_unless_pr c_release_binaries: - <<: *base_ubuntu2204 + <<: *base_ubuntu2404 steps: - checkout - attach_workspace: From 38fd087a91340c888f7262f84c3c039facd06679 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 18 Sep 2024 10:06:44 +0200 Subject: [PATCH 0331/1340] Fix pip issues for 24.04 --- docs/docs.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/docs.sh b/docs/docs.sh index f2c566761..abe4921e3 100755 --- a/docs/docs.sh +++ b/docs/docs.sh @@ -31,5 +31,8 @@ set -euo pipefail script_dir="$(dirname "$0")" cd "${script_dir}" -pip3 install -r requirements.txt --upgrade --upgrade-strategy eager +# TODO `--ignore-installed` now fixes an issue where pip tries to uninstall a Debian installed package, but is unable to +# TODO since Debian has decided to not use the RECORD file, which then breaks pip. +# TODO https://github.com/pypa/pip/issues/11631 and https://bugs.launchpad.net/ubuntu/+source/wheel/+bug/2063151 +pip3 install -r requirements.txt --ignore-installed --upgrade --upgrade-strategy eager sphinx-build -nW -b html -d _build/doctrees . _build/html From 10f2e601de02b32dd89033baa315fdc44b849ca5 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:27:52 +0200 Subject: [PATCH 0332/1340] Yul: Fix removal of trivial phi functions in SSA CFG Builder --- .../evm/SSAControlFlowGraphBuilder.cpp | 280 ++++++------------ .../backends/evm/SSAControlFlowGraphBuilder.h | 3 +- .../libyul/yulSSAControlFlowGraph/complex.yul | 6 +- .../yulSSAControlFlowGraph/complex2.yul | 4 +- 4 files changed, 94 insertions(+), 199 deletions(-) diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index d9dc7663c..2579b9064 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -33,30 +33,54 @@ #include #include #include -#include #include #include #include -#include using namespace solidity; using namespace solidity::yul; -namespace +namespace solidity::yul { -SSACFG::ValueId tryRemoveTrivialPhi(SSACFG& _cfg, SSACFG::ValueId _phi) + +SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder( + SSACFG& _graph, + AsmAnalysisInfo const& _analysisInfo, + Dialect const& _dialect +): + m_graph(_graph), + m_info(_analysisInfo), + m_dialect(_dialect) +{ +} + +std::unique_ptr SSAControlFlowGraphBuilder::build( + AsmAnalysisInfo const& _analysisInfo, + Dialect const& _dialect, + Block const& _block +) +{ + ControlFlowSideEffectsCollector sideEffects(_dialect, _block); + + auto result = std::make_unique(); + auto functions = buildMainGraph(*result->mainGraph, _analysisInfo, _dialect, _block); + buildFunctionGraphs(*result, _analysisInfo, sideEffects, _dialect, functions); + return result; +} + +SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) { // TODO: double-check if this is sane - auto* phiInfo = std::get_if(&_cfg.valueInfo(_phi)); + auto const* phiInfo = std::get_if(&m_graph.valueInfo(_phi)); yulAssert(phiInfo); SSACFG::ValueId same; for (SSACFG::ValueId arg: phiInfo->arguments) { if (arg == same || arg == _phi) - continue; + continue; // unique value or self-reference if (same.hasValue()) - return _phi; + return _phi; // phi merges at least two distinct values -> not trivial same = arg; } @@ -65,30 +89,26 @@ SSACFG::ValueId tryRemoveTrivialPhi(SSACFG& _cfg, SSACFG::ValueId _phi) size_t inputIndex = std::numeric_limits::max(); }; std::vector uses; - std::vector visited; std::vector phiUses; - auto isVisited = [&](SSACFG::BlockId _block) -> bool { - if (_block.value < visited.size()) - return visited.at(_block.value); - else - return false; - }; - auto markVisited = [&](SSACFG::BlockId _block) { - if (visited.size() <= _block.value) - visited.resize(_block.value + 1); - visited[_block.value] = true; - }; - // does this even need to be recursive? or can uses only be in the same or neighbouring blocks? - auto findUses = [&](SSACFG::BlockId _blockId, auto _recurse) -> void { - if (isVisited(_blockId)) - return; - markVisited(_blockId); - auto& block = _cfg.block(_blockId); + + if (!same.hasValue()) + { + // This will happen for unreachable paths. + // TODO: check how best to deal with this + same = m_graph.unreachableValue(); + } + + auto phiBlock = phiInfo->block; + m_graph.block(phiBlock).phis.erase(_phi); + + for (size_t blockIdValue = 0; blockIdValue < m_graph.numBlocks(); ++blockIdValue) + { + auto& block = m_graph.block(SSACFG::BlockId{blockIdValue}); for (auto blockPhi: block.phis) { if (blockPhi == _phi) continue; - auto const* blockPhiInfo = std::get_if(&_cfg.valueInfo(blockPhi)); + auto const* blockPhiInfo = std::get_if(&m_graph.valueInfo(blockPhi)); yulAssert(blockPhiInfo); bool usedInPhi = false; for (auto input: blockPhiInfo->arguments) @@ -112,45 +132,45 @@ SSACFG::ValueId tryRemoveTrivialPhi(SSACFG& _cfg, SSACFG::ValueId _phi) if (input == _phi) uses.emplace_back(Use{std::ref(op), n}); } - block.forEachExit([&](SSACFG::BlockId _block) { - _recurse(_block, _recurse); - }); - }; - auto phiBlock = phiInfo->block; - _cfg.block(phiBlock).phis.erase(_phi); - findUses(phiBlock, findUses); - - if (!same.hasValue()) - { - // This will happen for unreachable paths. - // TODO: check how best to deal with this - same = _cfg.unreachableValue(); + // todo check if it is sound to set "unreachable" return values to literal 0 + if (auto* functionReturn = std::get_if(&block.exit)) + std::replace( + functionReturn->returnValues.begin(), + functionReturn->returnValues.end(), + _phi, + same == m_graph.unreachableValue() ? m_graph.newLiteral(block.debugData, 0) : same + ); } - for (auto& use: uses) use.operation.get().inputs.at(use.inputIndex) = same; for (auto phiUse: phiUses) { - auto* blockPhiInfo = std::get_if(&_cfg.valueInfo(phiUse)); + auto* blockPhiInfo = std::get_if(&m_graph.valueInfo(phiUse)); yulAssert(blockPhiInfo); for (auto& arg: blockPhiInfo->arguments) if (arg == _phi) arg = same; } + for (auto& [_, currentVariableDefs]: m_currentDef) + { + for (auto& def: currentVariableDefs) + if (def && *def == _phi) + def = same; + } for (auto phiUse: phiUses) - tryRemoveTrivialPhi(_cfg, phiUse); + tryRemoveTrivialPhi(phiUse); return same; } /// Removes edges to blocks that are not reachable. -void cleanUnreachable(SSACFG& _cfg) +void SSAControlFlowGraphBuilder::cleanUnreachable() { // Determine which blocks are reachable from the entry. - util::BreadthFirstSearch reachabilityCheck{{_cfg.entry}}; + util::BreadthFirstSearch reachabilityCheck{{m_graph.entry}}; reachabilityCheck.run([&](SSACFG::BlockId _blockId, auto&& _addChild) { - auto const& block = _cfg.block(_blockId); + auto const& block = m_graph.block(_blockId); visit(util::GenericVisitor{ [&](SSACFG::BasicBlock::Jump const& _jump) { _addChild(_jump.target); @@ -167,14 +187,14 @@ void cleanUnreachable(SSACFG& _cfg) }); auto isUnreachableValue = [&](SSACFG::ValueId const& _value) -> bool { - auto* valueInfo = std::get_if(&_cfg.valueInfo(_value)); + auto* valueInfo = std::get_if(&m_graph.valueInfo(_value)); return (valueInfo) ? true : false; }; // Remove all entries from unreachable nodes from the graph. for (SSACFG::BlockId blockId: reachabilityCheck.visited) { - auto& block = _cfg.block(blockId); + auto& block = m_graph.block(blockId); std::set maybeTrivialPhi; for (auto it = block.entries.begin(); it != block.entries.end();) @@ -183,7 +203,7 @@ void cleanUnreachable(SSACFG& _cfg) else it = block.entries.erase(it); for (auto phi: block.phis) - if (auto* phiInfo = std::get_if(&_cfg.valueInfo(phi))) + if (auto* phiInfo = std::get_if(&m_graph.valueInfo(phi))) cxx20::erase_if(phiInfo->arguments, [&](SSACFG::ValueId _arg) { if (isUnreachableValue(_arg)) { @@ -195,44 +215,10 @@ void cleanUnreachable(SSACFG& _cfg) // After removing a phi argument, we might end up with a trivial phi that can be removed. for (auto phi: maybeTrivialPhi) - tryRemoveTrivialPhi(_cfg, phi); + tryRemoveTrivialPhi(phi); } } -} - -namespace solidity::yul -{ - -SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder( - SSACFG& _graph, - AsmAnalysisInfo const& _analysisInfo, - Dialect const& _dialect -): - m_graph(_graph), - m_info(_analysisInfo), - m_dialect(_dialect) -{ -} - -std::unique_ptr SSAControlFlowGraphBuilder::build( - AsmAnalysisInfo const& _analysisInfo, - Dialect const& _dialect, - Block const& _block -) -{ - ControlFlowSideEffectsCollector sideEffects(_dialect, _block); - - auto result = std::make_unique(); - auto functions = buildMainGraph(*result->mainGraph, _analysisInfo, _dialect, _block); - buildFunctionGraphs(*result, _analysisInfo, sideEffects, _dialect, functions); - - cleanUnreachable(*result->mainGraph); - for (auto& functionGraph: result->functionGraphs) - cleanUnreachable(*functionGraph); - return result; -} - void SSAControlFlowGraphBuilder::buildFunctionGraphs( ControlFlow& _controlFlow, AsmAnalysisInfo const& _info, @@ -276,6 +262,7 @@ void SSAControlFlowGraphBuilder::buildFunctionGraphs( cfg.exits.insert(builder.m_currentBlock); // Artificial explicit function exit (`leave`) at the end of the body. builder(Leave{debugDataOf(*functionDefinition)}); + builder.cleanUnreachable(); } } @@ -293,7 +280,7 @@ std::vector> SSACo if (!builder.blockInfo(builder.m_currentBlock).sealed) builder.sealBlock(builder.m_currentBlock); _cfg.block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; - + builder.cleanUnreachable(); return builder.m_functionDefinitions; } @@ -626,22 +613,27 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::readVariableRecursive(Scope::Variabl auto& block = m_graph.block(_block); auto& info = blockInfo(_block); - if (info.sealed && block.entries.size() == 1) - return readVariable(_variable, *block.entries.begin()); - - SSACFG::ValueId phi = m_graph.newPhi(_block); - block.phis.insert(phi); - if (info.sealed) + SSACFG::ValueId val; + if (!info.sealed) { - writeVariable(_variable, _block, phi); - phi = addPhiOperands(_variable, phi); + // incomplete block + val = m_graph.newPhi(_block); + block.phis.insert(val); + info.incompletePhis.emplace_back(val, std::ref(_variable)); } + else if (block.entries.size() == 1) + // one predecessor: no phi needed + val = readVariable(_variable, *block.entries.begin()); else { - info.incompletePhis.emplace_back(phi, std::ref(_variable)); + // Break potential cycles with operandless phi + val = m_graph.newPhi(_block); + block.phis.insert(val); + writeVariable(_variable, _block, val); + val = addPhiOperands(_variable, val); } - writeVariable(_variable, _block, phi); - return phi; + writeVariable(_variable, _block, val); + return val; } SSACFG::ValueId SSAControlFlowGraphBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi) @@ -653,104 +645,6 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::addPhiOperands(Scope::Variable const return tryRemoveTrivialPhi(_phi); } -SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) -{ - // TODO: double-check if this is sane - yulAssert(std::holds_alternative(m_graph.valueInfo(_phi))); - auto& phiInfo = std::get(m_graph.valueInfo(_phi)); - - SSACFG::ValueId same; - for (SSACFG::ValueId arg: phiInfo.arguments) - { - if (arg == same || arg == _phi) - continue; - if (same.hasValue()) - return _phi; - same = arg; - } - - struct Use { - std::reference_wrapper operation; - size_t inputIndex = std::numeric_limits::max(); - }; - std::vector uses; - std::vector visited; - std::vector phiUses; - auto isVisited = [&](SSACFG::BlockId _block) -> bool { - if (_block.value < visited.size()) - return visited.at(_block.value); - else - return false; - }; - auto markVisited = [&](SSACFG::BlockId _block) { - if (visited.size() <= _block.value) - visited.resize(_block.value + 1); - visited[_block.value] = true; - }; - // does this even need to be recursive? or can uses only be in the same or neighbouring blocks? - auto findUses = [&](SSACFG::BlockId _blockId, auto _recurse) -> void { - if (isVisited(_blockId)) - return; - markVisited(_blockId); - auto& block = m_graph.block(_blockId); - for (auto blockPhi: block.phis) - { - if (blockPhi == _phi) - continue; - auto const* blockPhiInfo = std::get_if(&m_graph.valueInfo(blockPhi)); - yulAssert(blockPhiInfo); - bool usedInPhi = false; - for (auto input: blockPhiInfo->arguments) - { - if (input == _phi) - usedInPhi = true; - } - if (usedInPhi) - phiUses.emplace_back(blockPhi); - } - for (auto& op: block.operations) - { - // TODO: double check when phiVar occurs in outputs here and what to do about it. - if (op.outputs.size() == 1 && op.outputs.front() == _phi) - continue; - // TODO: check if this always hold - and if so if the assertion is really valuable. - for (auto& output: op.outputs) - yulAssert(output != _phi); - - for (auto&& [n, input]: op.inputs | ranges::views::enumerate) - if (input == _phi) - uses.emplace_back(Use{std::ref(op), n}); - } - block.forEachExit([&](SSACFG::BlockId _block) { - _recurse(_block, _recurse); - }); - }; - auto phiBlock = phiInfo.block; - m_graph.block(phiBlock).phis.erase(_phi); - findUses(phiBlock, findUses); - - if (!same.hasValue()) - // This will happen for unreachable paths. - // TODO: check how best to deal with this - same = m_graph.unreachableValue(); - - for (auto& use: uses) - use.operation.get().inputs.at(use.inputIndex) = same; - for (auto phiUse: phiUses) - { - auto* blockPhiInfo = std::get_if(&m_graph.valueInfo(phiUse)); - yulAssert(blockPhiInfo); - for (auto& arg: blockPhiInfo->arguments) - if (arg == _phi) - arg = same; - } - - for (auto phiUse: phiUses) - tryRemoveTrivialPhi(phiUse); - - return same; -} - void SSAControlFlowGraphBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value) { currentDef(_variable, _block) = _value; diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.h b/libyul/backends/evm/SSAControlFlowGraphBuilder.h index 031016219..0a2ca8064 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.h +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.h @@ -73,6 +73,8 @@ class SSAControlFlowGraphBuilder SSACFG::ValueId operator()(Literal const& _literal); private: + void cleanUnreachable(); + SSACFG::ValueId tryRemoveTrivialPhi(SSACFG::ValueId _phi); void assign(std::vector> _variables, Expression const* _expression); std::vector visitFunctionCall(FunctionCall const& _call); @@ -80,7 +82,6 @@ class SSAControlFlowGraphBuilder SSACFG::ValueId readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block); SSACFG::ValueId readVariableRecursive(Scope::Variable const& _variable, SSACFG::BlockId _block); SSACFG::ValueId addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi); - SSACFG::ValueId tryRemoveTrivialPhi(SSACFG::ValueId _phi); void writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value); SSACFG& m_graph; diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index d7e16c9f6..0d2c958fd 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -87,7 +87,7 @@ // Block1_4 [label="\ // Block 4\nsstore(3084, 12)\l\ // "]; -// Block1_4Exit [label="FunctionReturn[v17]"]; +// Block1_4Exit [label="FunctionReturn[0]"]; // Block1_4 -> Block1_4Exit; // Block1_6 [label="\ // Block 6\nsstore(514, 2)\l\ @@ -105,7 +105,7 @@ // Block1_9 [label="\ // Block 9\nsstore(1028, 4)\l\ // "]; -// Block1_9Exit [label="FunctionReturn[v17]"]; +// Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ // Block 10\nv20 := eq(2, v6)\l\ @@ -168,7 +168,7 @@ // Block1_20 [label="\ // Block 20\nsstore(v43, 0)\l\ // "]; -// Block1_20Exit [label="FunctionReturn[v45]"]; +// Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ // Block 21\nsstore(65535, 255)\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index 863b021d1..8f3b1bd3f 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -121,7 +121,7 @@ // Block1_9 [label="\ // Block 9\nsstore(1028, 4)\l\ // "]; -// Block1_9Exit [label="FunctionReturn[v17]"]; +// Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ // Block 10\nv20 := eq(2, v6)\l\ @@ -184,7 +184,7 @@ // Block1_20 [label="\ // Block 20\nsstore(v43, 0)\l\ // "]; -// Block1_20Exit [label="FunctionReturn[v45]"]; +// Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ // Block 21\nsstore(65535, 255)\l\ From 5fc72695bca7533e1c08981ab7e8bce5f6d58a2b Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 18 Sep 2024 12:54:34 +0200 Subject: [PATCH 0333/1340] Remove 22.04 images and docker buildpack deps --- .circleci/README.md | 10 +- .circleci/config.yml | 58 ---------- .github/workflows/buildpack-deps.yml | 4 +- scripts/ci/buildpack-deps_test_ubuntu1804.sh | 1 - .../buildpack-deps_test_ubuntu2204.clang.sh | 1 - scripts/ci/buildpack-deps_test_ubuntu2204.sh | 1 - .../buildpack-deps/Dockerfile.ubuntu2204 | 102 ----------------- .../Dockerfile.ubuntu2204.clang | 103 ------------------ 8 files changed, 6 insertions(+), 274 deletions(-) delete mode 120000 scripts/ci/buildpack-deps_test_ubuntu1804.sh delete mode 120000 scripts/ci/buildpack-deps_test_ubuntu2204.clang.sh delete mode 120000 scripts/ci/buildpack-deps_test_ubuntu2204.sh delete mode 100644 scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 delete mode 100644 scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang diff --git a/.circleci/README.md b/.circleci/README.md index 6af7fd45c..22b20bc8c 100644 --- a/.circleci/README.md +++ b/.circleci/README.md @@ -7,15 +7,15 @@ The docker images are build locally on the developer machine: ```sh cd .circleci/docker/ -docker build -t ethereum/solidity-buildpack-deps:ubuntu2204- -f Dockerfile.ubuntu2204 . -docker push ethereum/solidity-buildpack-deps:ubuntu2204- +docker build -t ethereum/solidity-buildpack-deps:ubuntu2404- -f Dockerfile.ubuntu2404 . +docker push ethereum/solidity-buildpack-deps:ubuntu2404- ``` -The current revisions per docker image are stored in [circle ci pipeline parameters](https://github.com/CircleCI-Public/api-preview-docs/blob/master/docs/pipeline-parameters.md#pipeline-parameters) called `-docker-image-rev` (e.g., `ubuntu-2204-docker-image-rev`). Please update the value assigned to the parameter(s) corresponding to the docker image(s) being updated at the time of the update. Please verify that the value assigned to the parameter matches the revision part of the docker image tag (`` in the docker build/push snippet shown above). Otherwise, the docker image used by circle ci and the one actually pushed to docker hub will differ. +The current revisions per docker image are stored in [circle ci pipeline parameters](https://github.com/CircleCI-Public/api-preview-docs/blob/master/docs/pipeline-parameters.md#pipeline-parameters) called `-docker-image-rev` (e.g., `ubuntu-2404-docker-image-rev`). Please update the value assigned to the parameter(s) corresponding to the docker image(s) being updated at the time of the update. Please verify that the value assigned to the parameter matches the revision part of the docker image tag (`` in the docker build/push snippet shown above). Otherwise, the docker image used by circle ci and the one actually pushed to docker hub will differ. Once the docker image has been built and pushed to Dockerhub, you can find it at: - https://hub.docker.com/r/ethereum/solidity-buildpack-deps:ubuntu2204- + https://hub.docker.com/r/ethereum/solidity-buildpack-deps:ubuntu2404- where the image tag reflects the target OS and revision to build Solidity and run its tests on. @@ -24,7 +24,7 @@ where the image tag reflects the target OS and revision to build Solidity and ru ```sh cd solidity # Mounts your local solidity directory in docker container for testing -docker run -v `pwd`:/src/solidity -ti ethereum/solidity-buildpack-deps:ubuntu2204- /bin/bash +docker run -v `pwd`:/src/solidity -ti ethereum/solidity-buildpack-deps:ubuntu2404- /bin/bash cd /src/solidity ``` diff --git a/.circleci/config.yml b/.circleci/config.yml index d93fc20c0..18ca18f3c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,14 +11,6 @@ parameters: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-25 default: "solbuildpackpusher/solidity-buildpack-deps@sha256:b3f321fb2d8e7a41ca9328672061c1840e5cd3fb5be503aa158d1c508deacf0a" - ubuntu-2204-docker-image: - type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-10 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:ba2d878c26d681a7d6c1922258b47c2e5dd61d0e46ab4c6a4862b473e61997b6" - ubuntu-2204-clang-docker-image: - type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204.clang-9 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:703cdad5fa5c8686a3080ebb1aea1485ded2446561bf56e2945a87f2fa20a446" ubuntu-2404-docker-image: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-1 @@ -560,56 +552,6 @@ defaults: MAKEFLAGS: -j 10 CPUs: 10 - - base_ubuntu2204: &base_ubuntu2204 - docker: - - image: << pipeline.parameters.ubuntu-2204-docker-image >> - environment: &base_ubuntu2204_env - TERM: xterm - MAKEFLAGS: -j 3 - CPUs: 3 - - - base_ubuntu2204_clang: &base_ubuntu2204_clang - docker: - - image: << pipeline.parameters.ubuntu-2204-clang-docker-image >> - environment: &base_ubuntu2204_clang_env - TERM: xterm - CC: clang - CXX: clang++ - MAKEFLAGS: -j 3 - CPUs: 3 - - - base_ubuntu2204_clang_large: &base_ubuntu2204_clang_large - <<: *base_ubuntu2204_clang - resource_class: large - environment: &base_ubuntu2204_clang_large_env - <<: *base_ubuntu2204_clang_env - MAKEFLAGS: -j 5 - CPUs: 5 - - - base_ubuntu2204_small: &base_ubuntu2204_small - <<: *base_ubuntu2204 - resource_class: small - environment: &base_ubuntu2204_small_env - <<: *base_ubuntu2204_env - MAKEFLAGS: -j 2 - CPUs: 2 - - - base_ubuntu2204_large: &base_ubuntu2204_large - <<: *base_ubuntu2204 - resource_class: large - environment: &base_ubuntu2204_large_env - <<: *base_ubuntu2204_env - MAKEFLAGS: -j 5 - CPUs: 5 - - - base_ubuntu2204_xlarge: &base_ubuntu2204_xlarge - <<: *base_ubuntu2204 - resource_class: xlarge - environment: &base_ubuntu2204_xlarge_env - <<: *base_ubuntu2204_env - MAKEFLAGS: -j 10 - CPUs: 10 - - base_ubuntu2404: &base_ubuntu2404 docker: - image: << pipeline.parameters.ubuntu-2404-docker-image >> diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index 1b9555ddc..fe6da11e1 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -7,8 +7,6 @@ on: - 'scripts/docker/buildpack-deps/Dockerfile.emscripten' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2004' - - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang' - - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2204' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang' @@ -25,7 +23,7 @@ jobs: strategy: fail-fast: false matrix: - image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2204.clang, ubuntu2204, ubuntu2404, ubuntu2404.clang] + image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2404, ubuntu2404.clang] steps: - uses: actions/checkout@v4 diff --git a/scripts/ci/buildpack-deps_test_ubuntu1804.sh b/scripts/ci/buildpack-deps_test_ubuntu1804.sh deleted file mode 120000 index c07a74de4..000000000 --- a/scripts/ci/buildpack-deps_test_ubuntu1804.sh +++ /dev/null @@ -1 +0,0 @@ -build.sh \ No newline at end of file diff --git a/scripts/ci/buildpack-deps_test_ubuntu2204.clang.sh b/scripts/ci/buildpack-deps_test_ubuntu2204.clang.sh deleted file mode 120000 index c07a74de4..000000000 --- a/scripts/ci/buildpack-deps_test_ubuntu2204.clang.sh +++ /dev/null @@ -1 +0,0 @@ -build.sh \ No newline at end of file diff --git a/scripts/ci/buildpack-deps_test_ubuntu2204.sh b/scripts/ci/buildpack-deps_test_ubuntu2204.sh deleted file mode 120000 index c07a74de4..000000000 --- a/scripts/ci/buildpack-deps_test_ubuntu2204.sh +++ /dev/null @@ -1 +0,0 @@ -build.sh \ No newline at end of file diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 deleted file mode 100644 index add03bb00..000000000 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ /dev/null @@ -1,102 +0,0 @@ -# vim:syntax=dockerfile -#------------------------------------------------------------------------------ -# Dockerfile for building and testing Solidity Compiler on CI -# Target: Ubuntu 19.04 (Disco Dingo) -# 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 -# -# (c) 2016-2019 solidity contributors. -#------------------------------------------------------------------------------ -FROM buildpack-deps:jammy AS base -LABEL version="10" - -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 \ - cmake \ - jq \ - libboost-filesystem-dev \ - libboost-program-options-dev \ - libboost-system-dev \ - libboost-test-dev \ - libcln-dev \ - libz3-static-dev \ - locales-all \ - lsof \ - ninja-build \ - python3-pip \ - python3-sphinx \ - software-properties-common \ - sudo \ - unzip \ - z3-static \ - zip; \ - pip3 install \ - codecov \ - colorama \ - deepdiff \ - parsec \ - pygments-lexer-solidity \ - pylint \ - requests \ - tabulate \ - z3-solver; - -# Eldarica -RUN set -ex; \ - apt-get update; \ - apt-get install -qqy \ - openjdk-11-jre; \ - eldarica_version="2.1"; \ - wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ - test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ - unzip /opt/eld_binaries.zip -d /opt; \ - rm -f /opt/eld_binaries.zip; - -# CVC5 -RUN set -ex; \ - cvc5_version="1.1.2"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ - unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ - mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ - mv /opt/cvc5-Linux-static/include/* /usr/include; \ - mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ - rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; - -FROM base AS libraries - -# EVMONE -RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ - cd /usr; \ - tar -xf /usr/src/evmone.tar.gz; \ - rm -rf /usr/src/evmone.tar.gz - -FROM base -COPY --from=libraries /usr/lib /usr/lib -COPY --from=libraries /usr/bin /usr/bin -COPY --from=libraries /usr/include /usr/include -COPY --from=libraries /opt/eldarica /opt/eldarica -ENV PATH="$PATH:/opt/eldarica" diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang deleted file mode 100644 index b9c915838..000000000 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204.clang +++ /dev/null @@ -1,103 +0,0 @@ -# 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 -# -# (c) 2016-2019 solidity contributors. -#------------------------------------------------------------------------------ -FROM buildpack-deps:jammy AS base -LABEL version="9" - -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 \ - clang \ - cmake \ - jq \ - lsof \ - libboost-filesystem-dev \ - libboost-program-options-dev \ - libboost-system-dev \ - libboost-test-dev \ - libcln-dev \ - libz3-static-dev \ - ninja-build \ - python3-pip \ - software-properties-common \ - sudo \ - z3-static; \ - pip3 install \ - codecov \ - colorama \ - deepdiff \ - parsec \ - pygments-lexer-solidity \ - pylint \ - requests \ - tabulate \ - z3-solver; - -# Eldarica -RUN set -ex; \ - apt-get update; \ - apt-get install -qy \ - openjdk-11-jre \ - unzip; \ - eldarica_version="2.1"; \ - wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ - test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ - unzip /opt/eld_binaries.zip -d /opt; \ - rm -f /opt/eld_binaries.zip; - -# CVC5 -RUN set -ex; \ - cvc5_version="1.1.2"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ - unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ - mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ - mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ - mv /opt/cvc5-Linux-static/include/* /usr/include; \ - rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; - -FROM base AS libraries - -ENV CC clang -ENV CXX clang++ - -# EVMONE -RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ - cd /usr; \ - tar -xf /usr/src/evmone.tar.gz; \ - rm -rf /usr/src/evmone.tar.gz - -FROM base -COPY --from=libraries /usr/lib /usr/lib -COPY --from=libraries /usr/bin /usr/bin -COPY --from=libraries /usr/include /usr/include -COPY --from=libraries /opt/eldarica /opt/eldarica -ENV PATH="$PATH:/opt/eldarica" From 7e9ac48c5c227d305a924f11aec11abdb5f0f62d Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 17 Sep 2024 18:21:45 +0200 Subject: [PATCH 0334/1340] SSACFGBuilder: Only eliminate trivial phi of sealed blocks and add return variables to entry definitions --- .../evm/SSAControlFlowGraphBuilder.cpp | 43 +++++++++++---- .../backends/evm/SSAControlFlowGraphBuilder.h | 9 ++++ .../libyul/yulSSAControlFlowGraph/complex.yul | 20 +++---- .../yulSSAControlFlowGraph/complex2.yul | 20 +++---- .../yulSSAControlFlowGraph/function.yul | 6 +-- .../yulSSAControlFlowGraph/nested_for.yul | 52 +++---------------- 6 files changed, 73 insertions(+), 77 deletions(-) diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 2579b9064..26635124e 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -73,6 +73,7 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId // TODO: double-check if this is sane auto const* phiInfo = std::get_if(&m_graph.valueInfo(_phi)); yulAssert(phiInfo); + yulAssert(blockInfo(phiInfo->block).sealed); SSACFG::ValueId same; for (SSACFG::ValueId arg: phiInfo->arguments) @@ -132,14 +133,27 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId if (input == _phi) uses.emplace_back(Use{std::ref(op), n}); } - // todo check if it is sound to set "unreachable" return values to literal 0 - if (auto* functionReturn = std::get_if(&block.exit)) - std::replace( - functionReturn->returnValues.begin(), - functionReturn->returnValues.end(), - _phi, - same == m_graph.unreachableValue() ? m_graph.newLiteral(block.debugData, 0) : same - ); + std::visit(util::GenericVisitor{ + [_phi, same](SSACFG::BasicBlock::FunctionReturn& _functionReturn) { + std::replace( + _functionReturn.returnValues.begin(), + _functionReturn.returnValues.end(), + _phi, + same + ); + }, + [_phi, same](SSACFG::BasicBlock::ConditionalJump& _condJump) { + if (_condJump.condition == _phi) + _condJump.condition = same; + }, + [_phi, same](SSACFG::BasicBlock::JumpTable& _jumpTable) { + if (_jumpTable.value == _phi) + _jumpTable.value = same; + }, + [](SSACFG::BasicBlock::Jump&) {}, + [](SSACFG::BasicBlock::MainExit&) {}, + [](SSACFG::BasicBlock::Terminated&) {} + }, block.exit); } for (auto& use: uses) use.operation.get().inputs.at(use.inputIndex) = same; @@ -257,6 +271,8 @@ void SSAControlFlowGraphBuilder::buildFunctionGraphs( builder.m_currentBlock = cfg.entry; for (auto&& [var, varId]: cfg.arguments) builder.currentDef(var, cfg.entry) = varId; + for (auto const& var: cfg.returns) + builder.currentDef(var.get(), cfg.entry) = builder.zero(); builder.sealBlock(cfg.entry); builder(functionDefinition->body); cfg.exits.insert(builder.m_currentBlock); @@ -630,7 +646,9 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::readVariableRecursive(Scope::Variabl val = m_graph.newPhi(_block); block.phis.insert(val); writeVariable(_variable, _block, val); - val = addPhiOperands(_variable, val); + // we call tryRemoveTrivialPhi explicitly opposed to what is presented in Algorithm 2, as our implementation + // does not call it in addPhiOperands to avoid removing phis in unsealed blocks + val = tryRemoveTrivialPhi(addPhiOperands(_variable, val)); } writeVariable(_variable, _block, val); return val; @@ -642,7 +660,8 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::addPhiOperands(Scope::Variable const auto& phi = std::get(m_graph.valueInfo(_phi)); for (auto pred: m_graph.block(phi.block).entries) phi.arguments.emplace_back(readVariable(_variable, pred)); - return tryRemoveTrivialPhi(_phi); + // we call tryRemoveTrivialPhi explicitly to avoid removing trivial phis in unsealed blocks + return _phi; } void SSAControlFlowGraphBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value) @@ -681,11 +700,15 @@ Scope::Variable const& SSAControlFlowGraphBuilder::lookupVariable(YulName _name) void SSAControlFlowGraphBuilder::sealBlock(SSACFG::BlockId _block) { + // this method deviates from Algorithm 4 in the reference paper, + // as it would lead to tryRemoveTrivialPhi being called on unsealed blocks auto& info = blockInfo(_block); yulAssert(!info.sealed, "Trying to seal already sealed block."); for (auto&& [phi, variable] : info.incompletePhis) addPhiOperands(variable, phi); info.sealed = true; + for (auto& [phi, _]: info.incompletePhis) + phi = tryRemoveTrivialPhi(phi); } diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.h b/libyul/backends/evm/SSAControlFlowGraphBuilder.h index 0a2ca8064..e4d0d6db6 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.h +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.h @@ -17,6 +17,15 @@ // SPDX-License-Identifier: GPL-3.0 /** * Transformation of a Yul AST into a control flow graph. +* +* Based on https://doi.org/10.1007/978-3-642-37051-9_6 +* Braun, Matthias, et al. "Simple and efficient construction of static single assignment form." +* Compiler Construction: 22nd International Conference, CC 2013, +* ETAPS 2013, Rome, Italy, March 16-24, 2013. Proceedings 22. Springer Berlin Heidelberg, 2013. +* +* We have small deviations in Algorithms 2 and 4, as the paper's presentation leads to trivial phis being spuriously +* removed from not yet sealed blocks via a call to addPhiOperands in Algorithm 4. Instead, we perform the deletion +* of trivial phis only after a block has been sealed, i.e., all block's predecessors are present. */ #pragma once diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index 0d2c958fd..eef0b29fa 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -66,22 +66,22 @@ // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1; // Block1_1 [label="\ -// Block 1\nv4 := φ(\l\ +// Block 1\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ // )\l\ -// v5 := lt(v0, v4)\l\ +// v6 := lt(v0, v5)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v5| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit [label="{ If v6| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_1Exit:0 -> Block1_4; // Block1_1Exit:1 -> Block1_2; // Block1_2 [label="\ -// Block 2\nv6 := mload(v4)\l\ -// v7 := eq(0, v6)\l\ +// Block 2\nv7 := mload(v5)\l\ +// v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v7| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit [label="{ If v8| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_2Exit:0 -> Block1_7; // Block1_2Exit:1 -> Block1_6; // Block1_4 [label="\ @@ -96,7 +96,7 @@ // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4; // Block1_7 [label="\ -// Block 7\nv13 := eq(1, v6)\l\ +// Block 7\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; // Block1_7Exit [label="{ If v13| { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -108,7 +108,7 @@ // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10\nv20 := eq(2, v6)\l\ +// Block 10\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; // Block1_10Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -121,7 +121,7 @@ // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13\nv25 := eq(3, v6)\l\ +// Block 13\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; // Block1_13Exit [label="{ If v25| { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -158,7 +158,7 @@ // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5; // Block1_3 [label="\ -// Block 3\nv43 := add(1, v4)\l\ +// Block 3\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index 8f3b1bd3f..743b0513c 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -82,22 +82,22 @@ // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1; // Block1_1 [label="\ -// Block 1\nv4 := φ(\l\ +// Block 1\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ // )\l\ -// v5 := lt(v0, v4)\l\ +// v6 := lt(v0, v5)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v5| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit [label="{ If v6| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_1Exit:0 -> Block1_4; // Block1_1Exit:1 -> Block1_2; // Block1_2 [label="\ -// Block 2\nv6 := mload(v4)\l\ -// v7 := eq(0, v6)\l\ +// Block 2\nv7 := mload(v5)\l\ +// v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v7| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit [label="{ If v8| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_2Exit:0 -> Block1_7; // Block1_2Exit:1 -> Block1_6; // Block1_4 [label="\ @@ -112,7 +112,7 @@ // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4; // Block1_7 [label="\ -// Block 7\nv13 := eq(1, v6)\l\ +// Block 7\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; // Block1_7Exit [label="{ If v13| { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -124,7 +124,7 @@ // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10\nv20 := eq(2, v6)\l\ +// Block 10\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; // Block1_10Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -137,7 +137,7 @@ // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13\nv25 := eq(3, v6)\l\ +// Block 13\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; // Block1_13Exit [label="{ If v25| { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -174,7 +174,7 @@ // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5; // Block1_3 [label="\ -// Block 3\nv43 := add(1, v4)\l\ +// Block 3\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/yulSSAControlFlowGraph/function.yul index aa4b6ac97..436bcd499 100644 --- a/test/libyul/yulSSAControlFlowGraph/function.yul +++ b/test/libyul/yulSSAControlFlowGraph/function.yul @@ -37,10 +37,10 @@ // r := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\nv2 := add(v1, v0)\l\ -// v3 := sub(v0, v2)\l\ +// Block 0\nv3 := add(v1, v0)\l\ +// v4 := sub(v0, v3)\l\ // "]; -// Block1_0Exit [label="FunctionReturn[v3]"]; +// Block1_0Exit [label="FunctionReturn[v4]"]; // Block1_0 -> Block1_0Exit; // FunctionEntry_g_0 [label="function g: // g()"]; diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/yulSSAControlFlowGraph/nested_for.yul index e078630a6..0ed17c870 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_for.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_for.yul @@ -55,10 +55,6 @@ // Block 2 => 0,\l\ // Block 7 => v35\l\ // )\l\ -// v33 := φ(\l\ -// Block 2 => v2,\l\ -// Block 7 => v18\l\ -// )\l\ // v5 := lt(3, v4)\l\ // "]; // Block0_5 -> Block0_5Exit; @@ -80,14 +76,6 @@ // Block 6 => 0,\l\ // Block 11 => v31\l\ // )\l\ -// v17 := φ(\l\ -// Block 6 => v4,\l\ -// Block 11 => v32\l\ -// )\l\ -// v18 := φ(\l\ -// Block 6 => v33,\l\ -// Block 11 => v34\l\ -// )\l\ // v7 := lt(3, v6)\l\ // "]; // Block0_9 -> Block0_9Exit; @@ -95,7 +83,7 @@ // Block0_9Exit:0 -> Block0_12; // Block0_9Exit:1 -> Block0_10; // Block0_3 [label="\ -// Block 3\nv36 := add(1, v33)\l\ +// Block 3\nv36 := add(1, v2)\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; @@ -117,25 +105,13 @@ // Block0_13Exit [label="Jump" shape=oval]; // Block0_13Exit -> Block0_15; // Block0_14 [label="\ -// Block 14\nv27 := φ(\l\ -// Block 10 => v6,\l\ -// Block 18 => v10\l\ -// )\l\ -// v28 := φ(\l\ -// Block 10 => v17,\l\ -// Block 18 => v11\l\ -// )\l\ -// v29 := φ(\l\ -// Block 10 => v18,\l\ -// Block 18 => v12\l\ -// )\l\ -// "]; +// Block 14\n"]; // Block0_14 -> Block0_14Exit; // Block0_14Exit [label="{ If 1| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_14Exit:0 -> Block0_20; // Block0_14Exit:1 -> Block0_19; // Block0_7 [label="\ -// Block 7\nv35 := add(1, v17)\l\ +// Block 7\nv35 := add(1, v4)\l\ // "]; // Block0_7 -> Block0_7Exit [arrowhead=none]; // Block0_7Exit [label="Jump" shape=oval]; @@ -157,24 +133,12 @@ // Block0_19Exit [label="Jump" shape=oval]; // Block0_19Exit -> Block0_21; // Block0_20 [label="\ -// Block 20\nv30 := φ(\l\ -// Block 14 => v27,\l\ -// Block 24 => v21\l\ -// )\l\ -// v32 := φ(\l\ -// Block 14 => v28,\l\ -// Block 24 => v22\l\ -// )\l\ -// v34 := φ(\l\ -// Block 14 => v29,\l\ -// Block 24 => v23\l\ -// )\l\ -// "]; +// Block 20\n"]; // Block0_20 -> Block0_20Exit [arrowhead=none]; // Block0_20Exit [label="Jump" shape=oval]; // Block0_20Exit -> Block0_11; // Block0_16 [label="\ -// Block 16\nv13 := add(v17, v18)\l\ +// Block 16\nv13 := add(v4, v2)\l\ // v14 := add(v6, v13)\l\ // sstore(v14, v8)\l\ // "]; @@ -198,7 +162,7 @@ // Block0_21Exit:0 -> Block0_24; // Block0_21Exit:1 -> Block0_22; // Block0_11 [label="\ -// Block 11\nv31 := add(1, v30)\l\ +// Block 11\nv31 := add(1, v6)\l\ // "]; // Block0_11 -> Block0_11Exit [arrowhead=none]; // Block0_11Exit [label="Jump" shape=oval]; @@ -210,8 +174,8 @@ // Block0_17Exit [label="Jump" shape=oval]; // Block0_17Exit -> Block0_15; // Block0_22 [label="\ -// Block 22\nv24 := add(v28, v29)\l\ -// v25 := add(v27, v24)\l\ +// Block 22\nv24 := add(v4, v2)\l\ +// v25 := add(v6, v24)\l\ // sstore(v25, v19)\l\ // "]; // Block0_22 -> Block0_22Exit [arrowhead=none]; From c4a199a253f958c13ba70dc9f702a37dfbd5f21c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:21:35 +0200 Subject: [PATCH 0335/1340] SSACFGBuilder: clean up tryRemoveTrivialPhi --- .../evm/SSAControlFlowGraphBuilder.cpp | 57 ++++--------------- 1 file changed, 12 insertions(+), 45 deletions(-) diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 26635124e..3735892c3 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -84,14 +84,6 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId return _phi; // phi merges at least two distinct values -> not trivial same = arg; } - - struct Use { - std::reference_wrapper operation; - size_t inputIndex = std::numeric_limits::max(); - }; - std::vector uses; - std::vector phiUses; - if (!same.hasValue()) { // This will happen for unreachable paths. @@ -99,40 +91,29 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId same = m_graph.unreachableValue(); } - auto phiBlock = phiInfo->block; - m_graph.block(phiBlock).phis.erase(_phi); + m_graph.block(phiInfo->block).phis.erase(_phi); + std::set phiUses; for (size_t blockIdValue = 0; blockIdValue < m_graph.numBlocks(); ++blockIdValue) { auto& block = m_graph.block(SSACFG::BlockId{blockIdValue}); for (auto blockPhi: block.phis) { - if (blockPhi == _phi) - continue; - auto const* blockPhiInfo = std::get_if(&m_graph.valueInfo(blockPhi)); + yulAssert(blockPhi != _phi, "Phis should be defined in exactly one block, _phi was erased."); + auto* blockPhiInfo = std::get_if(&m_graph.valueInfo(blockPhi)); yulAssert(blockPhiInfo); bool usedInPhi = false; - for (auto input: blockPhiInfo->arguments) - { - if (input == _phi) + for (auto& arg: blockPhiInfo->arguments) + if (arg == _phi) + { + arg = same; usedInPhi = true; - } + } if (usedInPhi) - phiUses.emplace_back(blockPhi); + phiUses.emplace(blockPhi); } for (auto& op: block.operations) - { - // TODO: double check when phiVar occurs in outputs here and what to do about it. - if (op.outputs.size() == 1 && op.outputs.front() == _phi) - continue; - // TODO: check if this always hold - and if so if the assertion is really valuable. - for (auto& output: op.outputs) - yulAssert(output != _phi); - - for (auto&& [n, input]: op.inputs | ranges::views::enumerate) - if (input == _phi) - uses.emplace_back(Use{std::ref(op), n}); - } + std::replace(op.inputs.begin(), op.inputs.end(), _phi, same); std::visit(util::GenericVisitor{ [_phi, same](SSACFG::BasicBlock::FunctionReturn& _functionReturn) { std::replace( @@ -155,22 +136,8 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId [](SSACFG::BasicBlock::Terminated&) {} }, block.exit); } - for (auto& use: uses) - use.operation.get().inputs.at(use.inputIndex) = same; - for (auto phiUse: phiUses) - { - auto* blockPhiInfo = std::get_if(&m_graph.valueInfo(phiUse)); - yulAssert(blockPhiInfo); - for (auto& arg: blockPhiInfo->arguments) - if (arg == _phi) - arg = same; - } for (auto& [_, currentVariableDefs]: m_currentDef) - { - for (auto& def: currentVariableDefs) - if (def && *def == _phi) - def = same; - } + std::replace(currentVariableDefs.begin(), currentVariableDefs.end(), _phi, same); for (auto phiUse: phiUses) tryRemoveTrivialPhi(phiUse); From 55f746b8c599b76afef97e1b63840b532d43a36c Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 19 Sep 2024 20:23:45 +0200 Subject: [PATCH 0336/1340] eof: Introduce EOF container format support in `Assembly::assemble` (EIP-3540) Co-authored-by: Daniel Kirchner --- libevmasm/Assembly.cpp | 441 +++++++++++++++++++----- libevmasm/Assembly.h | 52 ++- libevmasm/ConstantOptimiser.cpp | 73 ++-- libevmasm/EVMAssemblyStack.cpp | 8 +- libsolidity/interface/CompilerStack.cpp | 13 +- libyul/YulStack.cpp | 10 +- test/libevmasm/Assembler.cpp | 3 +- test/libevmasm/Optimiser.cpp | 6 +- test/libsolidity/Assembly.cpp | 3 +- 9 files changed, 455 insertions(+), 154 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 7a28208c1..df78f43ca 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -58,11 +58,13 @@ AssemblyItem const& Assembly::append(AssemblyItem _i) { assertThrow(m_deposit >= 0, AssemblyException, "Stack underflow."); m_deposit += static_cast(_i.deposit()); - m_items.emplace_back(std::move(_i)); - if (!m_items.back().location().isValid() && m_currentSourceLocation.isValid()) - m_items.back().setLocation(m_currentSourceLocation); - m_items.back().m_modifierDepth = m_currentModifierDepth; - return m_items.back(); + solAssert(m_currentCodeSection < m_codeSections.size()); + auto& currentItems = m_codeSections.at(m_currentCodeSection).items; + currentItems.emplace_back(std::move(_i)); + if (!currentItems.back().location().isValid() && m_currentSourceLocation.isValid()) + currentItems.back().setLocation(m_currentSourceLocation); + currentItems.back().m_modifierDepth = m_currentModifierDepth; + return currentItems.back(); } unsigned Assembly::codeSize(unsigned subTagSize) const @@ -73,8 +75,9 @@ unsigned Assembly::codeSize(unsigned subTagSize) const for (auto const& i: m_data) ret += i.second.size(); - for (AssemblyItem const& i: m_items) - ret += i.bytesRequired(tagSize, m_evmVersion, Precision::Precise); + for (auto const& codeSection: m_codeSections) + for (AssemblyItem const& i: codeSection.items) + ret += i.bytesRequired(tagSize, m_evmVersion, Precision::Precise); if (numberEncodingSize(ret) <= tagSize) return static_cast(ret); } @@ -82,11 +85,15 @@ unsigned Assembly::codeSize(unsigned subTagSize) const void Assembly::importAssemblyItemsFromJSON(Json const& _code, std::vector const& _sourceList) { - solAssert(m_items.empty()); + // Assembly constructor creates first code section with proper type and empty `items` + solAssert(m_codeSections.size() == 1); + solAssert(m_codeSections[0].items.empty()); + // TODO: Add support for EOF and more than one code sections. + solUnimplementedAssert(!m_eofVersion.has_value(), "Assembly output for EOF is not yet implemented."); solRequire(_code.is_array(), AssemblyImportException, "Supplied JSON is not an array."); for (auto jsonItemIter = std::begin(_code); jsonItemIter != std::end(_code); ++jsonItemIter) { - AssemblyItem const& newItem = m_items.emplace_back(createAssemblyItemFromJSON(*jsonItemIter, _sourceList)); + AssemblyItem const& newItem = m_codeSections[0].items.emplace_back(createAssemblyItemFromJSON(*jsonItemIter, _sourceList)); if (newItem == Instruction::JUMPDEST) solThrow(AssemblyImportException, "JUMPDEST instruction without a tag"); else if (newItem.type() == AssemblyItemType::Tag) @@ -396,7 +403,10 @@ void Assembly::assemblyStream( { Functionalizer f(_out, _prefix, _sourceCodes, *this); - for (auto const& i: m_items) + // TODO: support EOF + solUnimplementedAssert(!m_eofVersion.has_value(), "Assembly output for EOF is not yet implemented."); + solAssert(m_codeSections.size() == 1); + for (auto const& i: m_codeSections.front().items) f.feed(i, _debugInfoSelection); f.flush(); @@ -434,7 +444,10 @@ Json Assembly::assemblyJSON(std::map const& _sourceIndice Json root; root[".code"] = Json::array(); Json& code = root[".code"]; - for (AssemblyItem const& item: m_items) + // TODO: support EOF + solUnimplementedAssert(!m_eofVersion.has_value(), "Assembly output for EOF is not yet implemented."); + solAssert(m_codeSections.size() == 1); + for (AssemblyItem const& item: m_codeSections.front().items) { int sourceIndex = -1; if (item.location().sourceName) @@ -518,7 +531,8 @@ Json Assembly::assemblyJSON(std::map const& _sourceIndice std::pair, std::vector> Assembly::fromJSON( Json const& _json, std::vector const& _sourceList, - size_t _level + size_t _level, + std::optional _eofVersion ) { solRequire(_json.is_object(), AssemblyImportException, "Supplied JSON is not an object."); @@ -549,7 +563,7 @@ std::pair, std::vector> Assembly::fromJSO "Member 'sourceList' may only be present in the root JSON object." ); - auto result = std::make_shared(EVMVersion{}, _level == 0 /* _creation */, std::nullopt, "" /* _name */); + auto result = std::make_shared(EVMVersion{}, _level == 0 /* _creation */, _eofVersion, "" /* _name */); std::vector parsedSourceList; if (_json.contains("sourceList")) { @@ -717,16 +731,21 @@ std::map const& Assembly::optimiseInternal( return *m_tagReplacements; // Run optimisation for sub-assemblies. + // TODO: verify and double-check this for EOF. for (size_t subId = 0; subId < m_subs.size(); ++subId) { OptimiserSettings settings = _settings; Assembly& sub = *m_subs[subId]; + std::set referencedTags; + for (auto& codeSection: m_codeSections) + referencedTags += JumpdestRemover::referencedTags(codeSection.items, subId); std::map const& subTagReplacements = sub.optimiseInternal( settings, - JumpdestRemover::referencedTags(m_items, subId) + referencedTags ); // Apply the replacements (can be empty). - BlockDeduplicator::applyTagReplacement(m_items, subTagReplacements, subId); + for (auto& codeSection: m_codeSections) + BlockDeduplicator::applyTagReplacement(codeSection.items, subTagReplacements, subId); } std::map tagReplacements; @@ -735,57 +754,70 @@ std::map const& Assembly::optimiseInternal( { count = 0; + // TODO: verify this for EOF. if (_settings.runInliner && !m_eofVersion.has_value()) + { + solAssert(m_codeSections.size() == 1); Inliner{ - m_items, + m_codeSections.front().items, _tagsReferencedFromOutside, _settings.expectedExecutionsPerDeployment, isCreation(), - _settings.evmVersion - }.optimise(); - - if (_settings.runJumpdestRemover) + _settings.evmVersion} + .optimise(); + } + // TODO: verify this for EOF. + if (_settings.runJumpdestRemover && !m_eofVersion.has_value()) { - JumpdestRemover jumpdestOpt{m_items}; - if (jumpdestOpt.optimise(_tagsReferencedFromOutside)) - count++; + for (auto& codeSection: m_codeSections) + { + JumpdestRemover jumpdestOpt{codeSection.items}; + if (jumpdestOpt.optimise(_tagsReferencedFromOutside)) + count++; + } } - if (_settings.runPeephole) + // TODO: verify this for EOF. + if (_settings.runPeephole && !m_eofVersion.has_value()) { - PeepholeOptimiser peepOpt{m_items, m_evmVersion}; - while (peepOpt.optimise()) + for (auto& codeSection: m_codeSections) { - count++; - assertThrow(count < 64000, OptimizerException, "Peephole optimizer seems to be stuck."); + PeepholeOptimiser peepOpt{codeSection.items, m_evmVersion}; + while (peepOpt.optimise()) + { + count++; + assertThrow(count < 64000, OptimizerException, "Peephole optimizer seems to be stuck."); + } } } // This only modifies PushTags, we have to run again to actually remove code. + // TODO: implement for EOF. if (_settings.runDeduplicate && !m_eofVersion.has_value()) - { - BlockDeduplicator deduplicator{m_items}; - if (deduplicator.deduplicate()) + for (auto& section: m_codeSections) { - for (auto const& replacement: deduplicator.replacedTags()) + BlockDeduplicator deduplicator{section.items}; + if (deduplicator.deduplicate()) { - assertThrow( - replacement.first <= std::numeric_limits::max() && replacement.second <= std::numeric_limits::max(), - OptimizerException, - "Invalid tag replacement." - ); - assertThrow( - !tagReplacements.count(replacement.first), - OptimizerException, - "Replacement already known." - ); - tagReplacements[replacement.first] = replacement.second; - if (_tagsReferencedFromOutside.erase(static_cast(replacement.first))) - _tagsReferencedFromOutside.insert(static_cast(replacement.second)); + for (auto const& replacement: deduplicator.replacedTags()) + { + assertThrow( + replacement.first <= std::numeric_limits::max() && replacement.second <= std::numeric_limits::max(), + OptimizerException, + "Invalid tag replacement." + ); + assertThrow( + !tagReplacements.count(replacement.first), + OptimizerException, + "Replacement already known." + ); + tagReplacements[replacement.first] = replacement.second; + if (_tagsReferencedFromOutside.erase(static_cast(replacement.first))) + _tagsReferencedFromOutside.insert(static_cast(replacement.second)); + } + count++; } - count++; } - } // TODO: investigate for EOF if (_settings.runCSE && !m_eofVersion.has_value()) @@ -795,17 +827,19 @@ std::map const& Assembly::optimiseInternal( // function types that can be stored in storage. AssemblyItems optimisedItems; - bool usesMSize = ranges::any_of(m_items, [](AssemblyItem const& _i) { + solAssert(m_codeSections.size() == 1); + auto& items = m_codeSections.front().items; + bool usesMSize = ranges::any_of(items, [](AssemblyItem const& _i) { return _i == AssemblyItem{Instruction::MSIZE} || _i.type() == VerbatimBytecode; }); - auto iter = m_items.begin(); - while (iter != m_items.end()) + auto iter = items.begin(); + while (iter != items.end()) { KnownState emptyState; CommonSubexpressionEliminator eliminator{emptyState}; auto orig = iter; - iter = eliminator.feedItems(iter, m_items.end(), usesMSize); + iter = eliminator.feedItems(iter, items.end(), usesMSize); bool shouldReplace = false; AssemblyItems optimisedChunk; try @@ -832,9 +866,9 @@ std::map const& Assembly::optimiseInternal( else copy(orig, iter, back_inserter(optimisedItems)); } - if (optimisedItems.size() < m_items.size()) + if (optimisedItems.size() < items.size()) { - m_items = std::move(optimisedItems); + items = std::move(optimisedItems); count++; } } @@ -853,19 +887,115 @@ std::map const& Assembly::optimiseInternal( return *m_tagReplacements; } +namespace +{ +template +void setBigEndian(bytes& _dest, size_t _offset, size_t _size, ValueT _value) +{ + assertThrow(numberEncodingSize(_value) <= _size, AssemblyException, ""); + toBigEndian(_value, bytesRef(_dest.data() + _offset, _size)); +} + +template +void appendBigEndian(bytes& _dest, size_t _size, ValueT _value) +{ + _dest.resize(_dest.size() + _size); + setBigEndian(_dest, _dest.size() - _size, _size, _value); +} + +template +void setBigEndianUint16(bytes& _dest, size_t _offset, ValueT _value) +{ + setBigEndian(_dest, _offset, 2, _value); +} + +template +void appendBigEndianUint16(bytes& _dest, ValueT _value) +{ + static_assert(!std::numeric_limits::is_signed, "only unsigned types or bigint supported"); + assertThrow(_value <= 0xFFFF, AssemblyException, ""); + appendBigEndian(_dest, 2, static_cast(_value)); +} +} + +std::tuple, size_t> Assembly::createEOFHeader(std::set const& _referencedSubIds) const +{ + bytes retBytecode; + std::vector codeSectionSizeOffsets; + size_t dataSectionSizeOffset; + + retBytecode.push_back(0xef); + retBytecode.push_back(0x00); + retBytecode.push_back(0x01); // version 1 + + retBytecode.push_back(0x01); // kind=type + appendBigEndianUint16(retBytecode, m_codeSections.size() * 4u); // length of type section + + retBytecode.push_back(0x02); // kind=code + appendBigEndianUint16(retBytecode, m_codeSections.size()); // placeholder for number of code sections + + for (auto const& codeSection: m_codeSections) + { + (void) codeSection; + codeSectionSizeOffsets.emplace_back(retBytecode.size()); + appendBigEndianUint16(retBytecode, 0u); // placeholder for length of code + } + + if (!_referencedSubIds.empty()) + { + retBytecode.push_back(0x03); + appendBigEndianUint16(retBytecode, _referencedSubIds.size()); + + for (auto subId: _referencedSubIds) + appendBigEndianUint16(retBytecode, m_subs[subId]->assemble().bytecode.size()); + } + + retBytecode.push_back(0x04); // kind=data + dataSectionSizeOffset = retBytecode.size(); + appendBigEndianUint16(retBytecode, 0u); // length of data + + retBytecode.push_back(0x00); // terminator + + for (auto const& codeSection: m_codeSections) + { + retBytecode.push_back(codeSection.inputs); + retBytecode.push_back(codeSection.outputs); + appendBigEndianUint16(retBytecode, 0xFFFFu); // TODO: Add stack height calculation + } + + return {retBytecode, codeSectionSizeOffsets, dataSectionSizeOffset}; +} + LinkerObject const& Assembly::assemble() const { - assertThrow(!m_invalid, AssemblyException, "Attempted to assemble invalid Assembly object."); + solRequire(!m_invalid, AssemblyException, "Attempted to assemble invalid Assembly object."); // Return the already assembled object, if present. if (!m_assembledObject.bytecode.empty()) return m_assembledObject; - // Otherwise ensure the object is actually clear. - assertThrow(m_assembledObject.linkReferences.empty(), AssemblyException, "Unexpected link references."); - LinkerObject& ret = m_assembledObject; + // Otherwise ensure the object is actually clear. + solRequire(m_assembledObject.linkReferences.empty(), AssemblyException, "Unexpected link references."); bool const eof = m_eofVersion.has_value(); - solAssert(!eof || m_eofVersion == 1, "Invalid EOF version."); + solRequire(!eof || m_eofVersion == 1, AssemblyException, "Invalid EOF version."); + + if (!eof) + return assembleLegacy(); + else + return assembleEOF(); +} + +LinkerObject const& Assembly::assembleLegacy() const +{ + solAssert(!m_eofVersion.has_value()); + solAssert(!m_invalid); + // Return the already assembled object, if present. + if (!m_assembledObject.bytecode.empty()) + return m_assembledObject; + // Otherwise ensure the object is actually clear. + solAssert(m_assembledObject.linkReferences.empty()); + + LinkerObject& ret = m_assembledObject; size_t subTagSize = 1; std::map>> immutableReferencesBySub; @@ -889,13 +1019,16 @@ LinkerObject const& Assembly::assemble() const bool setsImmutables = false; bool pushesImmutables = false; - for (auto const& i: m_items) - if (i.type() == AssignImmutable) + assertThrow(m_codeSections.size() == 1, AssemblyException, "Expected exactly one code section in non-EOF code."); + AssemblyItems const& items = m_codeSections.front().items; + + for (auto const& item: items) + if (item.type() == AssignImmutable) { - i.setImmutableOccurrences(immutableReferencesBySub[i.data()].second.size()); + item.setImmutableOccurrences(immutableReferencesBySub[item.data()].second.size()); setsImmutables = true; } - else if (i.type() == PushImmutable) + else if (item.type() == PushImmutable) pushesImmutables = true; if (setsImmutables || pushesImmutables) assertThrow( @@ -912,10 +1045,10 @@ LinkerObject const& Assembly::assemble() const std::vector sizeRef; ///< Pointers to code locations where the size of the program is inserted unsigned bytesPerTag = numberEncodingSize(bytesRequiredForCode); // Adjust bytesPerTag for references to sub assemblies. - for (AssemblyItem const& i: m_items) - if (i.type() == PushTag) + for (AssemblyItem const& item: items) + if (item.type() == PushTag) { - auto [subId, tagId] = i.splitForeignPushTag(); + auto [subId, tagId] = item.splitForeignPushTag(); if (subId == std::numeric_limits::max()) continue; assertThrow(subId < m_subs.size(), AssemblyException, "Invalid sub id"); @@ -933,20 +1066,20 @@ LinkerObject const& Assembly::assemble() const uint8_t dataRefPush = static_cast(pushInstruction(bytesPerDataRef)); ret.bytecode.reserve(bytesRequiredIncludingData); - for (AssemblyItem const& i: m_items) + for (AssemblyItem const& item: items) { // store position of the invalid jump destination - if (i.type() != Tag && m_tagPositionsInBytecode[0] == std::numeric_limits::max()) + if (item.type() != Tag && m_tagPositionsInBytecode[0] == std::numeric_limits::max()) m_tagPositionsInBytecode[0] = ret.bytecode.size(); - switch (i.type()) + switch (item.type()) { case Operation: - ret.bytecode.push_back(static_cast(i.instruction())); + ret.bytecode.push_back(static_cast(item.instruction())); break; case Push: { - unsigned b = numberEncodingSize(i.data()); + unsigned b = numberEncodingSize(item.data()); if (b == 0 && !m_evmVersion.hasPush0()) { b = 1; @@ -956,36 +1089,33 @@ LinkerObject const& Assembly::assemble() const { ret.bytecode.resize(ret.bytecode.size() + b); bytesRef byr(&ret.bytecode.back() + 1 - b, b); - toBigEndian(i.data(), byr); + toBigEndian(item.data(), byr); } break; } case PushTag: { - assertThrow(!eof, AssemblyException, "PushTag in EOF code"); ret.bytecode.push_back(tagPush); - tagRef[ret.bytecode.size()] = i.splitForeignPushTag(); + tagRef[ret.bytecode.size()] = item.splitForeignPushTag(); ret.bytecode.resize(ret.bytecode.size() + bytesPerTag); break; } case PushData: ret.bytecode.push_back(dataRefPush); - dataRef.insert(std::make_pair(h256(i.data()), ret.bytecode.size())); + dataRef.insert(std::make_pair(h256(item.data()), ret.bytecode.size())); ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); break; case PushSub: - assertThrow(!eof, AssemblyException, "PushSub in EOF code"); - assertThrow(i.data() <= std::numeric_limits::max(), AssemblyException, ""); + assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); ret.bytecode.push_back(dataRefPush); - subRef.insert(std::make_pair(static_cast(i.data()), ret.bytecode.size())); + subRef.insert(std::make_pair(static_cast(item.data()), ret.bytecode.size())); ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); break; case PushSubSize: { - assertThrow(!eof, AssemblyException, "PushSubSize in EOF code"); - assertThrow(i.data() <= std::numeric_limits::max(), AssemblyException, ""); - auto s = subAssemblyById(static_cast(i.data()))->assemble().bytecode.size(); - i.setPushedValue(u256(s)); + assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); + auto s = subAssemblyById(static_cast(item.data()))->assemble().bytecode.size(); + item.setPushedValue(u256(s)); unsigned b = std::max(1, numberEncodingSize(s)); ret.bytecode.push_back(static_cast(pushInstruction(b))); ret.bytecode.resize(ret.bytecode.size() + b); @@ -995,7 +1125,6 @@ LinkerObject const& Assembly::assemble() const } case PushProgramSize: { - assertThrow(!eof, AssemblyException, "PushProgramSize in EOF code"); ret.bytecode.push_back(dataRefPush); sizeRef.push_back(static_cast(ret.bytecode.size())); ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); @@ -1003,27 +1132,25 @@ LinkerObject const& Assembly::assemble() const } case PushLibraryAddress: ret.bytecode.push_back(static_cast(Instruction::PUSH20)); - ret.linkReferences[ret.bytecode.size()] = m_libraries.at(i.data()); + ret.linkReferences[ret.bytecode.size()] = m_libraries.at(item.data()); ret.bytecode.resize(ret.bytecode.size() + 20); break; case PushImmutable: - assertThrow(!eof, AssemblyException, "PushImmutable in EOF code"); ret.bytecode.push_back(static_cast(Instruction::PUSH32)); // Maps keccak back to the "identifier" std::string of that immutable. - ret.immutableReferences[i.data()].first = m_immutables.at(i.data()); + ret.immutableReferences[item.data()].first = m_immutables.at(item.data()); // Record the bytecode offset of the PUSH32 argument. - ret.immutableReferences[i.data()].second.emplace_back(ret.bytecode.size()); + ret.immutableReferences[item.data()].second.emplace_back(ret.bytecode.size()); // Advance bytecode by 32 bytes (default initialized). ret.bytecode.resize(ret.bytecode.size() + 32); break; case VerbatimBytecode: - ret.bytecode += i.verbatimData(); + ret.bytecode += item.verbatimData(); break; case AssignImmutable: { - assertThrow(!eof, AssemblyException, "AssignImmutable in EOF code"); // Expect 2 elements on stack (source, dest_base) - auto const& offsets = immutableReferencesBySub[i.data()].second; + auto const& offsets = immutableReferencesBySub[item.data()].second; for (size_t i = 0; i < offsets.size(); ++i) { if (i != offsets.size() - 1) @@ -1043,7 +1170,7 @@ LinkerObject const& Assembly::assemble() const ret.bytecode.push_back(uint8_t(Instruction::POP)); ret.bytecode.push_back(uint8_t(Instruction::POP)); } - immutableReferencesBySub.erase(i.data()); + immutableReferencesBySub.erase(item.data()); break; } case PushDeployTimeAddress: @@ -1052,9 +1179,9 @@ LinkerObject const& Assembly::assemble() const break; case Tag: { - assertThrow(i.data() != 0, AssemblyException, "Invalid tag position."); - assertThrow(i.splitForeignPushTag().first == std::numeric_limits::max(), AssemblyException, "Foreign tag."); - size_t tagId = static_cast(i.data()); + assertThrow(item.data() != 0, AssemblyException, "Invalid tag position."); + assertThrow(item.splitForeignPushTag().first == std::numeric_limits::max(), AssemblyException, "Foreign tag."); + size_t tagId = static_cast(item.data()); assertThrow(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large."); assertThrow(m_tagPositionsInBytecode[tagId] == std::numeric_limits::max(), AssemblyException, "Duplicate tag position."); m_tagPositionsInBytecode[tagId] = ret.bytecode.size(); @@ -1074,7 +1201,7 @@ LinkerObject const& Assembly::assemble() const "Some immutables were read from but never assigned, possibly because of optimization." ); - if (!eof && (!m_subs.empty() || !m_data.empty() || !m_auxiliaryData.empty())) + if (!m_subs.empty() || !m_data.empty() || !m_auxiliaryData.empty()) // Append an INVALID here to help tests find miscompilation. ret.bytecode.push_back(static_cast(Instruction::INVALID)); @@ -1118,7 +1245,7 @@ LinkerObject const& Assembly::assemble() const { size_t position = m_tagPositionsInBytecode.at(tagInfo.id); std::optional tagIndex; - for (auto&& [index, item]: m_items | ranges::views::enumerate) + for (auto&& [index, item]: items | ranges::views::enumerate) if (item.type() == Tag && static_cast(item.data()) == tagInfo.id) { tagIndex = index; @@ -1156,6 +1283,130 @@ LinkerObject const& Assembly::assemble() const return ret; } +std::map Assembly::findReferencedContainers() const +{ + std::set referencedSubcontainersIds; + solAssert(m_subs.size() <= 0x100); // According to EOF spec + + // TODO: Implement properly when opcodes referring sub containers added. + for (uint16_t i = 0; i < m_subs.size(); ++i) + referencedSubcontainersIds.insert(static_cast(i)); + // END TODO + + std::map replacements; + uint8_t nUnreferenced = 0; + for (uint8_t i = 0; i < static_cast(m_subs.size()); ++i) + { + if (referencedSubcontainersIds.count(i) > 0) + replacements[i] = static_cast(i - nUnreferenced); + else + nUnreferenced++; + } + + return replacements; +} + +LinkerObject const& Assembly::assembleEOF() const +{ + solAssert(m_eofVersion.has_value() && m_eofVersion == 1); + LinkerObject& ret = m_assembledObject; + + auto const subIdsReplacements = findReferencedContainers(); + auto const referencedSubIds = keys(subIdsReplacements); + + solRequire(!m_codeSections.empty(), AssemblyException, "Expected at least one code section."); + solRequire( + m_codeSections.front().inputs == 0 && m_codeSections.front().outputs == 0x80, AssemblyException, + "Expected the first code section to have zero inputs and be non-returning." + ); + + // Insert EOF1 header. + auto [bytecode, codeSectionSizeOffsets, dataSectionSizeOffset] = createEOFHeader(referencedSubIds); + ret.bytecode = bytecode; + + m_tagPositionsInBytecode = std::vector(m_usedTags, std::numeric_limits::max()); + + for (auto&& [codeSectionIndex, codeSection]: m_codeSections | ranges::views::enumerate) + { + auto const sectionStart = ret.bytecode.size(); + + for (AssemblyItem const& item: codeSection.items) + { + // store position of the invalid jump destination + if (item.type() != Tag && m_tagPositionsInBytecode[0] == std::numeric_limits::max()) + m_tagPositionsInBytecode[0] = ret.bytecode.size(); + + switch (item.type()) + { + case Operation: + ret.bytecode.push_back(static_cast(item.instruction())); + break; + case Push: + { + unsigned pushValueSize = numberEncodingSize(item.data()); + if (pushValueSize == 0 && !m_evmVersion.hasPush0()) + { + pushValueSize = 1; + } + ret.bytecode.push_back(static_cast(pushInstruction(pushValueSize))); + if (pushValueSize > 0) + { + ret.bytecode.resize(ret.bytecode.size() + pushValueSize); + bytesRef pushValueBytecodeRef(&ret.bytecode.back() + 1 - pushValueSize, pushValueSize); + toBigEndian(item.data(), pushValueBytecodeRef); + } + break; + } + case PushLibraryAddress: + ret.bytecode.push_back(static_cast(Instruction::PUSH20)); + ret.linkReferences[ret.bytecode.size()] = m_libraries.at(item.data()); + ret.bytecode.resize(ret.bytecode.size() + 20); + break; + case VerbatimBytecode: + ret.bytecode += item.verbatimData(); + break; + case PushDeployTimeAddress: + ret.bytecode.push_back(static_cast(Instruction::PUSH20)); + ret.bytecode.resize(ret.bytecode.size() + 20); + break; + case Tag: + { + solRequire(item.data() != 0, AssemblyException, "Invalid tag position."); + solRequire(item.splitForeignPushTag().first == std::numeric_limits::max(), AssemblyException, "Foreign tag."); + size_t tagId = static_cast(item.data()); + solRequire(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large."); + solRequire(m_tagPositionsInBytecode[tagId] == std::numeric_limits::max(), AssemblyException, "Duplicate tag position."); + m_tagPositionsInBytecode[tagId] = ret.bytecode.size(); + break; + } + default: + solRequire(false, InvalidOpcode, "Unexpected opcode while assembling."); + } + } + + auto sectionEnd = ret.bytecode.size(); + setBigEndianUint16(ret.bytecode, codeSectionSizeOffsets[codeSectionIndex], sectionEnd - sectionStart); + } + + for (auto i: referencedSubIds) + ret.bytecode += m_subs[i]->assemble().bytecode; + + // TODO: Fill functionDebugData for EOF. It probably should be handled for new code section in the loop above. + solRequire(m_namedTags.empty(), AssemblyException, "Named tags must be empty in EOF context."); + + auto const dataStart = ret.bytecode.size(); + + for (auto const& dataItem: m_data) + ret.bytecode += dataItem.second; + + ret.bytecode += m_auxiliaryData; + + auto dataLength = ret.bytecode.size() - dataStart; + setBigEndianUint16(ret.bytecode, dataSectionSizeOffset, dataLength); + + return ret; +} + std::vector Assembly::decodeSubPath(size_t _subObjectId) const { if (_subObjectId < m_subs.size()) diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 2b0ef93df..41e735db6 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -49,11 +49,14 @@ class Assembly { public: Assembly(langutil::EVMVersion _evmVersion, bool _creation, std::optional _eofVersion, std::string _name): - m_evmVersion(_evmVersion), - m_creation(_creation), - m_eofVersion(_eofVersion), - m_name(std::move(_name)) - {} + m_evmVersion(_evmVersion), + m_creation(_creation), + m_eofVersion(_eofVersion), + m_name(std::move(_name)) + { + // Code section number 0 has to be non-returning. + m_codeSections.emplace_back(CodeSection{0, 0x80, {}}); + } std::optional eofVersion() const { return m_eofVersion; } AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); } @@ -103,12 +106,6 @@ class Assembly /// Appends @a _data literally to the very end of the bytecode. void appendToAuxiliaryData(bytes const& _data) { m_auxiliaryData += _data; } - /// Returns the assembly items. - AssemblyItems const& items() const { return m_items; } - - /// Returns the mutable assembly items. Use with care! - AssemblyItems& items() { return m_items; } - int deposit() const { return m_deposit; } void adjustDeposit(int _adjustment) { m_deposit += _adjustment; assertThrow(m_deposit >= 0, InvalidDeposit, ""); } void setDeposit(int _deposit) { m_deposit = _deposit; assertThrow(m_deposit >= 0, InvalidDeposit, ""); } @@ -170,7 +167,8 @@ class Assembly static std::pair, std::vector> fromJSON( Json const& _json, std::vector const& _sourceList = {}, - size_t _level = 0 + size_t _level = 0, + std::optional _eofVersion = std::nullopt ); /// Mark this assembly as invalid. Calling ``assemble`` on it will throw. @@ -181,12 +179,30 @@ class Assembly bool isCreation() const { return m_creation; } + struct CodeSection + { + uint8_t inputs = 0; + uint8_t outputs = 0; + AssemblyItems items{}; + }; + + std::vector& codeSections() + { + return m_codeSections; + } + + std::vector const& codeSections() const + { + return m_codeSections; + } + protected: /// Does the same operations as @a optimise, but should only be applied to a sub and /// returns the replaced tags. Also takes an argument containing the tags of this assembly /// that are referenced in a super-assembly. std::map const& optimiseInternal(OptimiserSettings const& _settings, std::set _tagsReferencedFromOutside); + /// For EOF and legacy it calculates approximate size of "pure" code without data. unsigned codeSize(unsigned subTagSize) const; /// Add all assembly items from given JSON array. This function imports the items by iterating through @@ -210,6 +226,15 @@ class Assembly std::shared_ptr sharedSourceName(std::string const& _name) const; + /// Returns EOF header bytecode | code section sizes offsets | data section size offset + std::tuple, size_t> createEOFHeader(std::set const& _referencedSubIds) const; + + LinkerObject const& assembleLegacy() const; + LinkerObject const& assembleEOF() const; + + /// Returns map from m_subs to an index of subcontainer in the final EOF bytecode + std::map findReferencedContainers() const; + protected: /// 0 is reserved for exception unsigned m_usedTags = 1; @@ -223,11 +248,12 @@ class Assembly }; std::map m_namedTags; - AssemblyItems m_items; std::map m_data; /// Data that is appended to the very end of the contract. bytes m_auxiliaryData; std::vector> m_subs; + std::vector m_codeSections; + uint16_t m_currentCodeSection = 0; std::map m_strings; std::map m_libraries; ///< Identifiers of libraries to be linked. std::map m_immutables; ///< Identifiers of immutables. diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 360fb781f..6fdb42bd7 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -35,46 +35,49 @@ unsigned ConstantOptimisationMethod::optimiseConstants( ) { // TODO: design the optimiser in a way this is not needed - AssemblyItems& _items = _assembly.items(); - unsigned optimisations = 0; - std::map pushes; - for (AssemblyItem const& item: _items) - if (item.type() == Push) - pushes[item]++; - std::map pendingReplacements; - for (auto it: pushes) + for (auto& codeSection: _assembly.codeSections()) { - AssemblyItem const& item = it.first; - if (item.data() < 0x100) - continue; - Params params; - params.multiplicity = it.second; - params.isCreation = _isCreation; - params.runs = _runs; - params.evmVersion = _evmVersion; - LiteralMethod lit(params, item.data()); - bigint literalGas = lit.gasNeeded(); - CodeCopyMethod copy(params, item.data()); - bigint copyGas = copy.gasNeeded(); - ComputeMethod compute(params, item.data()); - bigint computeGas = compute.gasNeeded(); - AssemblyItems replacement; - if (copyGas < literalGas && copyGas < computeGas) - { - replacement = copy.execute(_assembly); - optimisations++; - } - else if (computeGas < literalGas && computeGas <= copyGas) + AssemblyItems& _items = codeSection.items; + + std::map pushes; + for (AssemblyItem const& item: _items) + if (item.type() == Push) + pushes[item]++; + std::map pendingReplacements; + for (auto it: pushes) { - replacement = compute.execute(_assembly); - optimisations++; + AssemblyItem const& item = it.first; + if (item.data() < 0x100) + continue; + Params params; + params.multiplicity = it.second; + params.isCreation = _isCreation; + params.runs = _runs; + params.evmVersion = _evmVersion; + LiteralMethod lit(params, item.data()); + bigint literalGas = lit.gasNeeded(); + CodeCopyMethod copy(params, item.data()); + bigint copyGas = copy.gasNeeded(); + ComputeMethod compute(params, item.data()); + bigint computeGas = compute.gasNeeded(); + AssemblyItems replacement; + if (copyGas < literalGas && copyGas < computeGas) + { + replacement = copy.execute(_assembly); + optimisations++; + } + else if (computeGas < literalGas && computeGas <= copyGas) + { + replacement = compute.execute(_assembly); + optimisations++; + } + if (!replacement.empty()) + pendingReplacements[item.data()] = replacement; } - if (!replacement.empty()) - pendingReplacements[item.data()] = replacement; + if (!pendingReplacements.empty()) + replaceConstants(_items, pendingReplacements); } - if (!pendingReplacements.empty()) - replaceConstants(_items, pendingReplacements); return optimisations; } diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index 20605ee35..afe67c5fc 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -56,12 +56,16 @@ void EVMAssemblyStack::assemble() solAssert(!m_evmRuntimeAssembly); m_object = m_evmAssembly->assemble(); - m_sourceMapping = AssemblyItem::computeSourceMapping(m_evmAssembly->items(), sourceIndices()); + // TODO: Check for EOF + solAssert(m_evmAssembly->codeSections().size() == 1); + m_sourceMapping = AssemblyItem::computeSourceMapping(m_evmAssembly->codeSections().front().items, sourceIndices()); if (m_evmAssembly->numSubs() > 0) { m_evmRuntimeAssembly = std::make_shared(m_evmAssembly->sub(0)); solAssert(m_evmRuntimeAssembly && !m_evmRuntimeAssembly->isCreation()); - m_runtimeSourceMapping = AssemblyItem::computeSourceMapping(m_evmRuntimeAssembly->items(), sourceIndices()); + // TODO: Check for EOF + solAssert(m_evmRuntimeAssembly->codeSections().size() == 1); + m_runtimeSourceMapping = AssemblyItem::computeSourceMapping(m_evmRuntimeAssembly->codeSections().front().items, sourceIndices()); m_runtimeObject = m_evmRuntimeAssembly->assemble(); } } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 3389e7eca..e538823f1 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -808,7 +808,11 @@ evmasm::AssemblyItems const* CompilerStack::assemblyItems(std::string const& _co solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); Contract const& currentContract = contract(_contractName); - return currentContract.evmAssembly ? ¤tContract.evmAssembly->items() : nullptr; + if (!currentContract.evmAssembly) + return nullptr; + solUnimplementedAssert(!m_eofVersion.has_value(), "EVM assembly output not implemented for EOF yet."); + solAssert(currentContract.evmAssembly->codeSections().size() == 1, "Expected a single code section in legacy codegen."); + return ¤tContract.evmAssembly->codeSections().front().items; } evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(std::string const& _contractName) const @@ -816,7 +820,12 @@ evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(std::string con solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); Contract const& currentContract = contract(_contractName); - return currentContract.evmRuntimeAssembly ? ¤tContract.evmRuntimeAssembly->items() : nullptr; + + if (!currentContract.evmRuntimeAssembly) + return nullptr; + solUnimplementedAssert(!m_eofVersion.has_value(), "EVM assembly output not implemented for EOF yet."); + solAssert(currentContract.evmRuntimeAssembly->codeSections().size() == 1, "Expected a single code section in legacy codegen."); + return ¤tContract.evmRuntimeAssembly->codeSections().front().items; } Json CompilerStack::generatedSources(std::string const& _contractName, bool _runtime) const diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 01eb5b738..a8e19a69a 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -262,9 +262,12 @@ YulStack::assembleWithDeployed(std::optional _deployName) creationObject.bytecode = std::make_shared(creationAssembly->assemble()); yulAssert(creationObject.bytecode->immutableReferences.empty(), "Leftover immutables."); creationObject.assembly = creationAssembly; + solUnimplementedAssert(!m_eofVersion.has_value(), "EVM assembly output not implemented for EOF yet."); + solAssert(creationAssembly->codeSections().size() == 1); creationObject.sourceMappings = std::make_unique( + // TODO: fix for EOF evmasm::AssemblyItem::computeSourceMapping( - creationAssembly->items(), + creationAssembly->codeSections().front().items, {{m_charStream->name(), 0}} ) ); @@ -273,11 +276,12 @@ YulStack::assembleWithDeployed(std::optional _deployName) { deployedObject.bytecode = std::make_shared(deployedAssembly->assemble()); deployedObject.assembly = deployedAssembly; + solAssert(deployedAssembly->codeSections().size() == 1); deployedObject.sourceMappings = std::make_unique( evmasm::AssemblyItem::computeSourceMapping( - deployedAssembly->items(), + deployedAssembly->codeSections().front().items, {{m_charStream->name(), 0}} - ) + ) ); } } diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 06c7fb6a9..b1222b49d 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -270,7 +270,8 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) checkCompilation(assembly); - std::string const sourceMappings = AssemblyItem::computeSourceMapping(assembly.items(), indices); + BOOST_REQUIRE(assembly.codeSections().size() == 1); + std::string const sourceMappings = AssemblyItem::computeSourceMapping(assembly.codeSections().at(0).items, indices); auto const numberOfMappings = std::count(sourceMappings.begin(), sourceMappings.end(), ';'); LinkerObject const& obj = assembly.assemble(); diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 13d9d6f2b..8ed413cfe 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1381,16 +1381,18 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) t1.toSubAssemblyTag(subId).pushTag(), u256(8) }; + BOOST_REQUIRE(main.codeSections().size() == 1); BOOST_CHECK_EQUAL_COLLECTIONS( - main.items().begin(), main.items().end(), + main.codeSections().at(0).items.begin(),main.codeSections().at(0).items.end(), expectationMain.begin(), expectationMain.end() ); AssemblyItems expectationSub{ u256(1), t1.tag(), u256(2), Instruction::JUMP, t4.tag(), u256(7), t4.pushTag(), Instruction::JUMP }; + BOOST_REQUIRE(sub->codeSections().size() == 1); BOOST_CHECK_EQUAL_COLLECTIONS( - sub->items().begin(), sub->items().end(), + sub->codeSections().at(0).items.begin(), sub->codeSections().at(0).items.end(), expectationSub.begin(), expectationSub.end() ); } diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 7def76e69..03897c454 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -91,7 +91,8 @@ evmasm::AssemblyItems compileContract(std::shared_ptr _sourceCode) ); compiler.compileContract(*contract, std::map>{}, bytes()); - return compiler.runtimeAssembly().items(); + BOOST_REQUIRE(compiler.runtimeAssembly().codeSections().size() == 1); + return compiler.runtimeAssembly().codeSections().at(0).items; } BOOST_FAIL("No contract found in source."); return AssemblyItems(); From 603d9ded7f9e708e67542f0644d65cdba05c681e Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 20 Sep 2024 10:30:56 +0200 Subject: [PATCH 0337/1340] eof: pass EOF flag to `Assembly::fromJSON` --- libevmasm/Assembly.cpp | 2 +- libevmasm/EVMAssemblyStack.cpp | 2 +- libevmasm/EVMAssemblyStack.h | 4 +++- libsolidity/interface/StandardCompiler.cpp | 2 +- solc/CommandLineInterface.cpp | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index df78f43ca..0d5468e26 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -630,7 +630,7 @@ std::pair, std::vector> Assembly::fromJSO solThrow(AssemblyImportException, "The key '" + key + "' inside '.data' is out of the supported integer range."); } - auto [subAssembly, emptySourceList] = Assembly::fromJSON(value, _level == 0 ? parsedSourceList : _sourceList, _level + 1); + auto [subAssembly, emptySourceList] = Assembly::fromJSON(value, _level == 0 ? parsedSourceList : _sourceList, _level + 1, _eofVersion); solAssert(subAssembly); solAssert(emptySourceList.empty()); solAssert(subAssemblies.count(index) == 0); diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index afe67c5fc..df4517fc5 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -45,7 +45,7 @@ void EVMAssemblyStack::analyze(std::string const& _sourceName, Json const& _asse { solAssert(!m_evmAssembly); m_name = _sourceName; - std::tie(m_evmAssembly, m_sourceList) = evmasm::Assembly::fromJSON(_assemblyJson); + std::tie(m_evmAssembly, m_sourceList) = evmasm::Assembly::fromJSON(_assemblyJson, {}, 0, m_eofVersion); solRequire(m_evmAssembly != nullptr, AssemblyImportException, "Could not create evm assembly object."); } diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index f2516c0b8..cf959de79 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -33,7 +33,8 @@ namespace solidity::evmasm class EVMAssemblyStack: public AbstractAssemblyStack { public: - explicit EVMAssemblyStack(langutil::EVMVersion _evmVersion): m_evmVersion(_evmVersion) {} + explicit EVMAssemblyStack(langutil::EVMVersion _evmVersion, std::optional _eofVersion): + m_evmVersion(_evmVersion), m_eofVersion(_eofVersion) {} /// Runs parsing and analysis steps. /// Multiple calls overwrite the previous state. @@ -76,6 +77,7 @@ class EVMAssemblyStack: public AbstractAssemblyStack private: langutil::EVMVersion m_evmVersion; + std::optional m_eofVersion; std::string m_name; std::shared_ptr m_evmAssembly; std::shared_ptr m_evmRuntimeAssembly; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 7271cce8b..cd00caf07 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1204,7 +1204,7 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in if (!isBinaryRequested(_inputsAndSettings.outputSelection)) return Json::object(); - evmasm::EVMAssemblyStack stack(_inputsAndSettings.evmVersion); + evmasm::EVMAssemblyStack stack(_inputsAndSettings.evmVersion, _inputsAndSettings.eofVersion); std::string const& sourceName = _inputsAndSettings.jsonSources.begin()->first; // result of structured binding can only be used within lambda from C++20 on. Json const& sourceJson = _inputsAndSettings.jsonSources.begin()->second; try diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index f78fdfeb8..2d815facc 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -843,7 +843,7 @@ void CommandLineInterface::assembleFromEVMAssemblyJSON() solAssert(m_fileReader.sourceUnits().size() == 1); auto&& [sourceUnitName, source] = *m_fileReader.sourceUnits().begin(); - auto evmAssemblyStack = std::make_unique(m_options.output.evmVersion); + auto evmAssemblyStack = std::make_unique(m_options.output.evmVersion, m_options.output.eofVersion); try { evmAssemblyStack->parseAndAnalyze(sourceUnitName, source); From bc9f3e0c20224f9d3b9c8847b6f3c0f4a6f526d3 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 20 Sep 2024 15:35:49 +0200 Subject: [PATCH 0338/1340] eof: Add container format test --- .../strict_asm_eof_container_prague/args | 1 + .../strict_asm_eof_container_prague/input.yul | 36 +++++++++++++++++++ .../strict_asm_eof_container_prague/output | 5 +++ 3 files changed, 42 insertions(+) create mode 100644 test/cmdlineTests/strict_asm_eof_container_prague/args create mode 100644 test/cmdlineTests/strict_asm_eof_container_prague/input.yul create mode 100644 test/cmdlineTests/strict_asm_eof_container_prague/output diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/args b/test/cmdlineTests/strict_asm_eof_container_prague/args new file mode 100644 index 000000000..b8cc1ab18 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_container_prague/args @@ -0,0 +1 @@ + --strict-assembly --experimental-eof-version 1 --evm-version prague --bin diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/input.yul b/test/cmdlineTests/strict_asm_eof_container_prague/input.yul new file mode 100644 index 000000000..09306772c --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_container_prague/input.yul @@ -0,0 +1,36 @@ +object "object" { + code { + revert(0, 0) + } + + object "sub0" { + code { + mstore(0, 0) + revert(0, 32) + } + } + object "sub1" { + code { + mstore(0, 1) + revert(0, 32) + } + } + object "sub2" { + code { + mstore(0, 2) + revert(0, 32) + } + object "sub20" { + code { + mstore(0, 0x20) + revert(0, 32) + } + } + } + object "sub3" { + code { + mstore(0, 3) + revert(0, 32) + } + } +} \ No newline at end of file diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/output b/test/cmdlineTests/strict_asm_eof_container_prague/output new file mode 100644 index 000000000..caf28d91d --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_container_prague/output @@ -0,0 +1,5 @@ + +======= strict_asm_eof_container_prague/input.yul (EVM) ======= + +Binary representation: +ef00010100040200010003030004001a001b003b001b040000000080ffff5f80fdef00010100040200010007040000000080ffff5f805260205ffdef00010100040200010008040000000080ffff60015f5260205ffdef00010100040200010008030001001b040000000080ffff60025f5260205ffdef00010100040200010008040000000080ffff60205f5260205ffdef00010100040200010008040000000080ffff60035f5260205ffd From 1ba4349f859d53cd9fea7d7a66475b193d3d5538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 23 Sep 2024 12:58:16 +0200 Subject: [PATCH 0339/1340] Rename Standard JSON output selection tests CLI to match the naming convention --- .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 22 files changed, 0 insertions(+), 0 deletions(-) rename test/cmdlineTests/{output_selection_all_blank => standard_output_selection_all_blank}/input.json (100%) rename test/cmdlineTests/{output_selection_all_blank => standard_output_selection_all_blank}/output.json (100%) rename test/cmdlineTests/{output_selection_all_A2 => standard_output_selection_all_sources_single_contract_multiple_matches}/input.json (100%) rename test/cmdlineTests/{output_selection_all_A2 => standard_output_selection_all_sources_single_contract_multiple_matches}/output.json (100%) rename test/cmdlineTests/{output_selection_all_A1 => standard_output_selection_all_sources_single_contract_single_match}/input.json (100%) rename test/cmdlineTests/{output_selection_all_A1 => standard_output_selection_all_sources_single_contract_single_match}/output.json (100%) rename test/cmdlineTests/{output_selection_all_star => standard_output_selection_all_star}/input.json (100%) rename test/cmdlineTests/{output_selection_all_star => standard_output_selection_all_star}/output.json (100%) rename test/cmdlineTests/{output_selection_single_all => standard_output_selection_single_all}/input.json (100%) rename test/cmdlineTests/{output_selection_single_all => standard_output_selection_single_all}/output.json (100%) rename test/cmdlineTests/{output_selection_single_A1 => standard_output_selection_single_source_single_contract_multiple_matches}/input.json (100%) rename test/cmdlineTests/{output_selection_single_A1 => standard_output_selection_single_source_single_contract_multiple_matches}/output.json (100%) rename test/cmdlineTests/{output_selection_single_B1 => standard_output_selection_single_source_single_contract_single_match}/input.json (100%) rename test/cmdlineTests/{output_selection_single_B1 => standard_output_selection_single_source_single_contract_single_match}/output.json (100%) rename test/cmdlineTests/{standard_wrong_type_output_selection => standard_output_selection_wrong_type}/input.json (100%) rename test/cmdlineTests/{standard_wrong_type_output_selection => standard_output_selection_wrong_type}/output.json (100%) rename test/cmdlineTests/{standard_wrong_type_output_selection_contract => standard_output_selection_wrong_type_contract}/input.json (100%) rename test/cmdlineTests/{standard_wrong_type_output_selection_contract => standard_output_selection_wrong_type_contract}/output.json (100%) rename test/cmdlineTests/{standard_wrong_type_output_selection_output => standard_output_selection_wrong_type_output}/input.json (100%) rename test/cmdlineTests/{standard_wrong_type_output_selection_output => standard_output_selection_wrong_type_output}/output.json (100%) rename test/cmdlineTests/{standard_wrong_type_output_selection_file => standard_output_selection_wrong_type_source}/input.json (100%) rename test/cmdlineTests/{standard_wrong_type_output_selection_file => standard_output_selection_wrong_type_source}/output.json (100%) diff --git a/test/cmdlineTests/output_selection_all_blank/input.json b/test/cmdlineTests/standard_output_selection_all_blank/input.json similarity index 100% rename from test/cmdlineTests/output_selection_all_blank/input.json rename to test/cmdlineTests/standard_output_selection_all_blank/input.json diff --git a/test/cmdlineTests/output_selection_all_blank/output.json b/test/cmdlineTests/standard_output_selection_all_blank/output.json similarity index 100% rename from test/cmdlineTests/output_selection_all_blank/output.json rename to test/cmdlineTests/standard_output_selection_all_blank/output.json diff --git a/test/cmdlineTests/output_selection_all_A2/input.json b/test/cmdlineTests/standard_output_selection_all_sources_single_contract_multiple_matches/input.json similarity index 100% rename from test/cmdlineTests/output_selection_all_A2/input.json rename to test/cmdlineTests/standard_output_selection_all_sources_single_contract_multiple_matches/input.json diff --git a/test/cmdlineTests/output_selection_all_A2/output.json b/test/cmdlineTests/standard_output_selection_all_sources_single_contract_multiple_matches/output.json similarity index 100% rename from test/cmdlineTests/output_selection_all_A2/output.json rename to test/cmdlineTests/standard_output_selection_all_sources_single_contract_multiple_matches/output.json diff --git a/test/cmdlineTests/output_selection_all_A1/input.json b/test/cmdlineTests/standard_output_selection_all_sources_single_contract_single_match/input.json similarity index 100% rename from test/cmdlineTests/output_selection_all_A1/input.json rename to test/cmdlineTests/standard_output_selection_all_sources_single_contract_single_match/input.json diff --git a/test/cmdlineTests/output_selection_all_A1/output.json b/test/cmdlineTests/standard_output_selection_all_sources_single_contract_single_match/output.json similarity index 100% rename from test/cmdlineTests/output_selection_all_A1/output.json rename to test/cmdlineTests/standard_output_selection_all_sources_single_contract_single_match/output.json diff --git a/test/cmdlineTests/output_selection_all_star/input.json b/test/cmdlineTests/standard_output_selection_all_star/input.json similarity index 100% rename from test/cmdlineTests/output_selection_all_star/input.json rename to test/cmdlineTests/standard_output_selection_all_star/input.json diff --git a/test/cmdlineTests/output_selection_all_star/output.json b/test/cmdlineTests/standard_output_selection_all_star/output.json similarity index 100% rename from test/cmdlineTests/output_selection_all_star/output.json rename to test/cmdlineTests/standard_output_selection_all_star/output.json diff --git a/test/cmdlineTests/output_selection_single_all/input.json b/test/cmdlineTests/standard_output_selection_single_all/input.json similarity index 100% rename from test/cmdlineTests/output_selection_single_all/input.json rename to test/cmdlineTests/standard_output_selection_single_all/input.json diff --git a/test/cmdlineTests/output_selection_single_all/output.json b/test/cmdlineTests/standard_output_selection_single_all/output.json similarity index 100% rename from test/cmdlineTests/output_selection_single_all/output.json rename to test/cmdlineTests/standard_output_selection_single_all/output.json diff --git a/test/cmdlineTests/output_selection_single_A1/input.json b/test/cmdlineTests/standard_output_selection_single_source_single_contract_multiple_matches/input.json similarity index 100% rename from test/cmdlineTests/output_selection_single_A1/input.json rename to test/cmdlineTests/standard_output_selection_single_source_single_contract_multiple_matches/input.json diff --git a/test/cmdlineTests/output_selection_single_A1/output.json b/test/cmdlineTests/standard_output_selection_single_source_single_contract_multiple_matches/output.json similarity index 100% rename from test/cmdlineTests/output_selection_single_A1/output.json rename to test/cmdlineTests/standard_output_selection_single_source_single_contract_multiple_matches/output.json diff --git a/test/cmdlineTests/output_selection_single_B1/input.json b/test/cmdlineTests/standard_output_selection_single_source_single_contract_single_match/input.json similarity index 100% rename from test/cmdlineTests/output_selection_single_B1/input.json rename to test/cmdlineTests/standard_output_selection_single_source_single_contract_single_match/input.json diff --git a/test/cmdlineTests/output_selection_single_B1/output.json b/test/cmdlineTests/standard_output_selection_single_source_single_contract_single_match/output.json similarity index 100% rename from test/cmdlineTests/output_selection_single_B1/output.json rename to test/cmdlineTests/standard_output_selection_single_source_single_contract_single_match/output.json diff --git a/test/cmdlineTests/standard_wrong_type_output_selection/input.json b/test/cmdlineTests/standard_output_selection_wrong_type/input.json similarity index 100% rename from test/cmdlineTests/standard_wrong_type_output_selection/input.json rename to test/cmdlineTests/standard_output_selection_wrong_type/input.json diff --git a/test/cmdlineTests/standard_wrong_type_output_selection/output.json b/test/cmdlineTests/standard_output_selection_wrong_type/output.json similarity index 100% rename from test/cmdlineTests/standard_wrong_type_output_selection/output.json rename to test/cmdlineTests/standard_output_selection_wrong_type/output.json diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_contract/input.json b/test/cmdlineTests/standard_output_selection_wrong_type_contract/input.json similarity index 100% rename from test/cmdlineTests/standard_wrong_type_output_selection_contract/input.json rename to test/cmdlineTests/standard_output_selection_wrong_type_contract/input.json diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_contract/output.json b/test/cmdlineTests/standard_output_selection_wrong_type_contract/output.json similarity index 100% rename from test/cmdlineTests/standard_wrong_type_output_selection_contract/output.json rename to test/cmdlineTests/standard_output_selection_wrong_type_contract/output.json diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_output/input.json b/test/cmdlineTests/standard_output_selection_wrong_type_output/input.json similarity index 100% rename from test/cmdlineTests/standard_wrong_type_output_selection_output/input.json rename to test/cmdlineTests/standard_output_selection_wrong_type_output/input.json diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_output/output.json b/test/cmdlineTests/standard_output_selection_wrong_type_output/output.json similarity index 100% rename from test/cmdlineTests/standard_wrong_type_output_selection_output/output.json rename to test/cmdlineTests/standard_output_selection_wrong_type_output/output.json diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_file/input.json b/test/cmdlineTests/standard_output_selection_wrong_type_source/input.json similarity index 100% rename from test/cmdlineTests/standard_wrong_type_output_selection_file/input.json rename to test/cmdlineTests/standard_output_selection_wrong_type_source/input.json diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_file/output.json b/test/cmdlineTests/standard_output_selection_wrong_type_source/output.json similarity index 100% rename from test/cmdlineTests/standard_wrong_type_output_selection_file/output.json rename to test/cmdlineTests/standard_output_selection_wrong_type_source/output.json From 3452ba0189f0a086d2a0926a757226bfeb23fb59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 23 Sep 2024 14:04:53 +0200 Subject: [PATCH 0340/1340] More CLI tests for output selection in Standard JSON --- .../input.json | 13 ++ .../output.json | 24 +++ .../input.json | 13 ++ .../output.json | 42 ++++++ .../input.json | 29 ++++ .../output.json | 35 +++++ .../input.json | 9 ++ .../output.json | 7 + .../input.json | 29 ++++ .../output.json | 109 ++++++++++++++ .../input.json | 23 +++ .../output.json | 141 ++++++++++++++++++ .../input.json | 16 ++ .../output.json | 13 ++ .../input.json | 24 +++ .../output.json | 18 +++ .../input.json | 21 +++ .../output.json | 21 +++ 18 files changed, 587 insertions(+) create mode 100644 test/cmdlineTests/standard_output_selection_all_sources_blank_contract_named_blank/input.json create mode 100644 test/cmdlineTests/standard_output_selection_all_sources_blank_contract_named_blank/output.json create mode 100644 test/cmdlineTests/standard_output_selection_all_sources_star_contract_named_star/input.json create mode 100644 test/cmdlineTests/standard_output_selection_all_sources_star_contract_named_star/output.json create mode 100644 test/cmdlineTests/standard_output_selection_duplicate_matching_source_and_contract_selectors/input.json create mode 100644 test/cmdlineTests/standard_output_selection_duplicate_matching_source_and_contract_selectors/output.json create mode 100644 test/cmdlineTests/standard_output_selection_empty/input.json create mode 100644 test/cmdlineTests/standard_output_selection_empty/output.json create mode 100644 test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors/input.json create mode 100644 test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors/output.json create mode 100644 test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors_full_pipeline/input.json create mode 100644 test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors_full_pipeline/output.json create mode 100644 test/cmdlineTests/standard_output_selection_no_output_selected/input.json create mode 100644 test/cmdlineTests/standard_output_selection_no_output_selected/output.json create mode 100644 test/cmdlineTests/standard_output_selection_unrecognized_output/input.json create mode 100644 test/cmdlineTests/standard_output_selection_unrecognized_output/output.json create mode 100644 test/cmdlineTests/standard_output_selection_unrecognized_source_and_contract_selectors/input.json create mode 100644 test/cmdlineTests/standard_output_selection_unrecognized_source_and_contract_selectors/output.json diff --git a/test/cmdlineTests/standard_output_selection_all_sources_blank_contract_named_blank/input.json b/test/cmdlineTests/standard_output_selection_all_sources_blank_contract_named_blank/input.json new file mode 100644 index 000000000..9a2634aa7 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_all_sources_blank_contract_named_blank/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "": {"content": "contract D {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "*": {"content": "contract D {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "C": {"content": "contract D {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"} + }, + "settings": { + "outputSelection": { + "": {"D": ["userdoc"]} + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_all_sources_blank_contract_named_blank/output.json b/test/cmdlineTests/standard_output_selection_all_sources_blank_contract_named_blank/output.json new file mode 100644 index 000000000..ff82564fc --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_all_sources_blank_contract_named_blank/output.json @@ -0,0 +1,24 @@ +{ + "contracts": { + "": { + "D": { + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + } + } + }, + "sources": { + "": { + "id": 0 + }, + "*": { + "id": 1 + }, + "C": { + "id": 2 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_all_sources_star_contract_named_star/input.json b/test/cmdlineTests/standard_output_selection_all_sources_star_contract_named_star/input.json new file mode 100644 index 000000000..950218048 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_all_sources_star_contract_named_star/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "": {"content": "contract D {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "*": {"content": "contract D {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "C": {"content": "contract D {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"} + }, + "settings": { + "outputSelection": { + "*": {"D": ["userdoc"]} + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_all_sources_star_contract_named_star/output.json b/test/cmdlineTests/standard_output_selection_all_sources_star_contract_named_star/output.json new file mode 100644 index 000000000..b5dda3d59 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_all_sources_star_contract_named_star/output.json @@ -0,0 +1,42 @@ +{ + "contracts": { + "": { + "D": { + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + } + }, + "*": { + "D": { + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + } + }, + "C": { + "D": { + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + } + } + }, + "sources": { + "": { + "id": 0 + }, + "*": { + "id": 1 + }, + "C": { + "id": 2 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_duplicate_matching_source_and_contract_selectors/input.json b/test/cmdlineTests/standard_output_selection_duplicate_matching_source_and_contract_selectors/input.json new file mode 100644 index 000000000..70b7b079a --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_duplicate_matching_source_and_contract_selectors/input.json @@ -0,0 +1,29 @@ +{ + "language": "Solidity", + "sources": { + "*": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "C": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "D": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"} + }, + "settings": { + "outputSelection": { + // Outputs from duplicate keys are not combined. Last value wins. + "*": { + "*": ["userdoc"], // Ignored + "*": ["devdoc"] // Ignored + }, + "C": { + "*": ["storageLayout"], // Ignored + "*": ["transientStorageLayout"] // Ignored + }, + "C": { + "A": ["evm.bytecode.linkReferences"], // Ignored + "A": ["evm.bytecode.object"] + }, + "*": { + "A": ["evm.deployedBytecode.immutableReferences"], // Ignored + "A": ["abi"] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_duplicate_matching_source_and_contract_selectors/output.json b/test/cmdlineTests/standard_output_selection_duplicate_matching_source_and_contract_selectors/output.json new file mode 100644 index 000000000..2743eb870 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_duplicate_matching_source_and_contract_selectors/output.json @@ -0,0 +1,35 @@ +{ + "contracts": { + "*": { + "A": { + "abi": [] + } + }, + "C": { + "A": { + "abi": [], + "evm": { + "bytecode": { + "object": "" + } + } + } + }, + "D": { + "A": { + "abi": [] + } + } + }, + "sources": { + "*": { + "id": 0 + }, + "C": { + "id": 1 + }, + "D": { + "id": 2 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_empty/input.json b/test/cmdlineTests/standard_output_selection_empty/input.json new file mode 100644 index 000000000..76cc0fb48 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_empty/input.json @@ -0,0 +1,9 @@ +{ + "language": "Solidity", + "sources": { + "C": {"content": "contract A {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"} + }, + "settings": { + "outputSelection": {} + } +} diff --git a/test/cmdlineTests/standard_output_selection_empty/output.json b/test/cmdlineTests/standard_output_selection_empty/output.json new file mode 100644 index 000000000..264cd37be --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_empty/output.json @@ -0,0 +1,7 @@ +{ + "sources": { + "C": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors/input.json b/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors/input.json new file mode 100644 index 000000000..276869377 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors/input.json @@ -0,0 +1,29 @@ +{ + "language": "Solidity", + "sources": { + "": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "*": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "C": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "D": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"} + }, + "settings": { + "outputSelection": { + // FIXME: Behavior of "" is inconsistent. Sometimes it matches everything, sometimes only empty name. + "": { + "": ["metadata"], // No matches + "*": ["transientStorageLayout"], // All sources, all contracts + "A": ["abi"] // source "", contract A + }, + "*": { + "": ["evm.deployedBytecode.immutableReferences"], // No matches + "*": ["evm.bytecode.object"], // All sources, all contracts + "A": ["evm.bytecode.linkReferences"] // All sources, contract A + }, + "C": { + "": ["userdoc"], // No matches + "*": ["devdoc"], // All contracts in source "C" + "A": ["storageLayout"] // source "C", contract A + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors/output.json b/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors/output.json new file mode 100644 index 000000000..6558a5759 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors/output.json @@ -0,0 +1,109 @@ +{ + "contracts": { + "": { + "A": { + "abi": [], + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "" + } + }, + "transientStorageLayout": { + "storage": [], + "types": null + } + }, + "B": { + "evm": { + "bytecode": { + "object": "" + } + }, + "transientStorageLayout": { + "storage": [], + "types": null + } + } + }, + "*": { + "A": { + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "" + } + } + }, + "B": { + "evm": { + "bytecode": { + "object": "" + } + } + } + }, + "C": { + "A": { + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "" + } + }, + "storageLayout": { + "storage": [], + "types": null + } + }, + "B": { + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "evm": { + "bytecode": { + "object": "" + } + } + } + }, + "D": { + "A": { + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "" + } + } + }, + "B": { + "evm": { + "bytecode": { + "object": "" + } + } + } + } + }, + "sources": { + "": { + "id": 0 + }, + "*": { + "id": 1 + }, + "C": { + "id": 2 + }, + "D": { + "id": 3 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors_full_pipeline/input.json b/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors_full_pipeline/input.json new file mode 100644 index 000000000..22884c9f8 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors_full_pipeline/input.json @@ -0,0 +1,23 @@ +{ + "language": "Solidity", + "sources": { + "C": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "D": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"} + }, + "settings": { + "optimizer": {"enabled": true}, + "debug": {"debugInfo": []}, + "outputSelection": { + // This test uses outputs that require all stages of the pipeline to run, possibly via + // multiple paths, to make sure the later stages handle more complex output selection correctly. + // Currently there are only distinct paths (IR, optimized IR and bytecode generation). + "*": { + "*": ["evm.bytecode.object"], + "A": ["irOptimized"] + }, + "C": { + "A": ["ir"] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors_full_pipeline/output.json b/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors_full_pipeline/output.json new file mode 100644 index 000000000..3ff2b451e --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_multiple_matching_source_and_contract_selectors_full_pipeline/output.json @@ -0,0 +1,141 @@ +{ + "contracts": { + "C": { + "A": { + "evm": { + "bytecode": { + "object": "" + } + }, + "ir": " +/// @use-src 0:\"C\" +object \"A_1\" { + code { + + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A_1() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A_1_deployed\"), datasize(\"A_1_deployed\")) + + return(_1, datasize(\"A_1_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_A_1() { + + } + + } + /// @use-src 0:\"C\" + object \"A_1_deployed\" { + code { + + mstore(64, memoryguard(128)) + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/// @use-src 0:\"C\" +object \"A_1\" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"A_1_deployed\") + codecopy(_1, dataoffset(\"A_1_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 0:\"C\" + object \"A_1_deployed\" { + code { { revert(0, 0) } } + data \".metadata\" hex\"\" + } +} +" + }, + "B": { + "evm": { + "bytecode": { + "object": "" + } + } + } + }, + "D": { + "A": { + "evm": { + "bytecode": { + "object": "" + } + }, + "irOptimized": "/// @use-src 1:\"D\" +object \"A_5\" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"A_5_deployed\") + codecopy(_1, dataoffset(\"A_5_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 1:\"D\" + object \"A_5_deployed\" { + code { { revert(0, 0) } } + data \".metadata\" hex\"\" + } +} +" + }, + "B": { + "evm": { + "bytecode": { + "object": "" + } + } + } + } + }, + "sources": { + "C": { + "id": 0 + }, + "D": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_no_output_selected/input.json b/test/cmdlineTests/standard_output_selection_no_output_selected/input.json new file mode 100644 index 000000000..4e0fd1c0d --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_no_output_selected/input.json @@ -0,0 +1,16 @@ +{ + "language": "Solidity", + "sources": { + "C": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "D": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "E": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"} + }, + "settings": { + "outputSelection": { + "C": {}, + "D": {"A": []}, + "*": {"B": []}, + "": {} + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_no_output_selected/output.json b/test/cmdlineTests/standard_output_selection_no_output_selected/output.json new file mode 100644 index 000000000..2cea05dcf --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_no_output_selected/output.json @@ -0,0 +1,13 @@ +{ + "sources": { + "C": { + "id": 0 + }, + "D": { + "id": 1 + }, + "E": { + "id": 2 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_unrecognized_output/input.json b/test/cmdlineTests/standard_output_selection_unrecognized_output/input.json new file mode 100644 index 000000000..072d9916e --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_unrecognized_output/input.json @@ -0,0 +1,24 @@ +{ + "language": "Solidity", + "sources": { + "C": {"content": "contract A {}\ncontract B {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"} + }, + "settings": { + "outputSelection": { + // Unrecognized outputs are ignored. + "C": { + "A": [ + "X", + "METADATA", + "abi.encode", + "userdoc", // The only valid one here. + ".", + "evm.", + "evm.bytecodeObject", + "evm.bytecode.object.ir", + "evm.bytecode.*" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_unrecognized_output/output.json b/test/cmdlineTests/standard_output_selection_unrecognized_output/output.json new file mode 100644 index 000000000..7fbddd857 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_unrecognized_output/output.json @@ -0,0 +1,18 @@ +{ + "contracts": { + "C": { + "A": { + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + } + } + }, + "sources": { + "C": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_unrecognized_source_and_contract_selectors/input.json b/test/cmdlineTests/standard_output_selection_unrecognized_source_and_contract_selectors/input.json new file mode 100644 index 000000000..b1b4e1bef --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_unrecognized_source_and_contract_selectors/input.json @@ -0,0 +1,21 @@ +{ + "language": "Solidity", + "sources": { + "*": {"content": "contract A {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"}, + "C": {"content": "contract A {}\n//SPDX-License-Identifier: GPL-3.0\npragma solidity *;"} + }, + "settings": { + "outputSelection": { + "*": { + "X": ["userdoc"] // No contract X, but no error, just ignored. + }, + "Y": { + "*": ["devdoc"], // No source "Y", but no error, just ignored. + "Z": ["abi"] // No source "Y", but no error, just ignored. + }, + "C": { + "A": ["evm.bytecode.object"] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_unrecognized_source_and_contract_selectors/output.json b/test/cmdlineTests/standard_output_selection_unrecognized_source_and_contract_selectors/output.json new file mode 100644 index 000000000..20ab65450 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_unrecognized_source_and_contract_selectors/output.json @@ -0,0 +1,21 @@ +{ + "contracts": { + "C": { + "A": { + "evm": { + "bytecode": { + "object": "" + } + } + } + } + }, + "sources": { + "*": { + "id": 0 + }, + "C": { + "id": 1 + } + } +} From 9b4a07bbb46cd4cba23f7dbf406a38dc199a6177 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:51:49 +0200 Subject: [PATCH 0341/1340] SSACFG: Fix canContinue in user-defined function calls --- .../evm/SSAControlFlowGraphBuilder.cpp | 55 ++++++++++++++----- .../backends/evm/SSAControlFlowGraphBuilder.h | 15 +++-- .../yulSSAControlFlowGraph/function.yul | 4 +- 3 files changed, 54 insertions(+), 20 deletions(-) diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 26635124e..dc183a085 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -46,10 +47,12 @@ namespace solidity::yul SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder( SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, + ControlFlowSideEffectsCollector const& _sideEffects, Dialect const& _dialect ): m_graph(_graph), m_info(_analysisInfo), + m_sideEffects(_sideEffects), m_dialect(_dialect) { } @@ -63,7 +66,7 @@ std::unique_ptr SSAControlFlowGraphBuilder::build( ControlFlowSideEffectsCollector sideEffects(_dialect, _block); auto result = std::make_unique(); - auto functions = buildMainGraph(*result->mainGraph, _analysisInfo, _dialect, _block); + auto functions = buildMainGraph(*result->mainGraph, _analysisInfo, sideEffects, _dialect, _block); buildFunctionGraphs(*result, _analysisInfo, sideEffects, _dialect, functions); return result; } @@ -267,8 +270,9 @@ void SSAControlFlowGraphBuilder::buildFunctionGraphs( cfg.arguments = arguments; cfg.returns = returns; - SSAControlFlowGraphBuilder builder(cfg, _info, _dialect); + SSAControlFlowGraphBuilder builder(cfg, _info, _sideEffects, _dialect); builder.m_currentBlock = cfg.entry; + builder.m_functionDefinitions = _functions; for (auto&& [var, varId]: cfg.arguments) builder.currentDef(var, cfg.entry) = varId; for (auto const& var: cfg.returns) @@ -285,11 +289,12 @@ void SSAControlFlowGraphBuilder::buildFunctionGraphs( std::vector> SSAControlFlowGraphBuilder::buildMainGraph( SSACFG& _cfg, AsmAnalysisInfo const& _analysisInfo, + ControlFlowSideEffectsCollector const& _sideEffects, Dialect const& _dialect, Block const& _block ) { - SSAControlFlowGraphBuilder builder(_cfg, _analysisInfo, _dialect); + SSAControlFlowGraphBuilder builder(_cfg, _analysisInfo, _sideEffects, _dialect); builder.m_currentBlock = _cfg.makeBlock(debugDataOf(_block)); builder.sealBlock(builder.m_currentBlock); builder(_block); @@ -535,8 +540,22 @@ void SSAControlFlowGraphBuilder::operator()(Leave const& _leaveStatement) void SSAControlFlowGraphBuilder::operator()(Block const& _block) { ScopedSaveAndRestore saveScope(m_scope, m_info.scopes.at(&_block).get()); - for (auto const& statement: _block.statements) - std::visit(*this, statement); + if (m_currentBlock == m_graph.entry) + { + auto const filterFunctionDefinitions = [](bool _yieldDefinitionsOnly) + { + return [b=_yieldDefinitionsOnly](Statement const& _statement) -> bool { return !b ^ std::holds_alternative(_statement);}; + }; + for (auto const& statement: _block.statements | ranges::views::filter(filterFunctionDefinitions(true))) + std::visit(*this, statement); + for (auto const& statement: _block.statements | ranges::views::filter(filterFunctionDefinitions(false))) + std::visit(*this, statement); + } + else + { + for (auto const& statement: _block.statements) + std::visit(*this, statement); + } } SSACFG::ValueId SSAControlFlowGraphBuilder::operator()(FunctionCall const& _call) @@ -592,7 +611,9 @@ std::vector SSAControlFlowGraphBuilder::visitFunctionCall(Funct else { Scope::Function const& function = lookupFunction(_call.functionName.name); - canContinue = m_graph.canContinue; + auto const* definition = findFunctionDefinition(&function); + yulAssert(definition); + canContinue = m_sideEffects.functionSideEffects().at(definition).canContinue; SSACFG::Operation result{{}, SSACFG::Call{debugDataOf(_call), function, _call, canContinue}, {}}; for (auto const& arg: _call.arguments | ranges::views::reverse) result.inputs.emplace_back(std::visit(*this, arg)); @@ -745,8 +766,7 @@ void SSAControlFlowGraphBuilder::tableJump( langutil::DebugData::ConstPtr _debugData, SSACFG::ValueId _value, std::map _cases, - SSACFG::BlockId _defaultCase -) + SSACFG::BlockId _defaultCase) { for (auto caseBlock: _cases | ranges::views::values) { @@ -755,13 +775,20 @@ void SSAControlFlowGraphBuilder::tableJump( } yulAssert(!blockInfo(_defaultCase).sealed); m_graph.block(_defaultCase).entries.insert(m_currentBlock); - currentBlock().exit = SSACFG::BasicBlock::JumpTable{ - std::move(_debugData), - _value, - std::move(_cases), - _defaultCase - }; + currentBlock().exit = SSACFG::BasicBlock::JumpTable{std::move(_debugData), _value, std::move(_cases), _defaultCase}; m_currentBlock = {}; } +FunctionDefinition const* SSAControlFlowGraphBuilder::findFunctionDefinition(Scope::Function const* _function) const +{ + auto it = std::find_if( + m_functionDefinitions.begin(), + m_functionDefinitions.end(), + [&_function](auto const& _entry) { return std::get<0>(_entry) == _function; } + ); + if (it != m_functionDefinitions.end()) + return std::get<1>(*it); + return nullptr; +} + } diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.h b/libyul/backends/evm/SSAControlFlowGraphBuilder.h index e4d0d6db6..8fc537c14 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.h +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.h @@ -29,9 +29,8 @@ */ #pragma once -#include -#include #include +#include #include #include @@ -43,12 +42,17 @@ class SSAControlFlowGraphBuilder SSAControlFlowGraphBuilder( SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, + ControlFlowSideEffectsCollector const& _sideEffects, Dialect const& _dialect ); public: SSAControlFlowGraphBuilder(SSAControlFlowGraphBuilder const&) = delete; SSAControlFlowGraphBuilder& operator=(SSAControlFlowGraphBuilder const&) = delete; - static std::unique_ptr build(AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, Block const& _block); + static std::unique_ptr build( + AsmAnalysisInfo const& _analysisInfo, + Dialect const& _dialect, + Block const& _block + ); static void buildFunctionGraphs( ControlFlow& _controlFlow, AsmAnalysisInfo const& _info, @@ -59,6 +63,7 @@ class SSAControlFlowGraphBuilder static std::vector> buildMainGraph( SSACFG& _cfg, AsmAnalysisInfo const& _analysisInfo, + ControlFlowSideEffectsCollector const& _sideEffects, Dialect const& _dialect, Block const& _block ); @@ -95,7 +100,9 @@ class SSAControlFlowGraphBuilder SSACFG& m_graph; AsmAnalysisInfo const& m_info; + ControlFlowSideEffectsCollector const& m_sideEffects; Dialect const& m_dialect; + std::vector> m_functionDefinitions; SSACFG::BlockId m_currentBlock; SSACFG::BasicBlock& currentBlock() { return m_graph.block(m_currentBlock); } Scope* m_scope = nullptr; @@ -154,7 +161,7 @@ class SSAControlFlowGraphBuilder SSACFG::BlockId _defaultCase ); - std::vector> m_functionDefinitions; + FunctionDefinition const* findFunctionDefinition(Scope::Function const* _function) const; }; } diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/yulSSAControlFlowGraph/function.yul index 436bcd499..20a536b5e 100644 --- a/test/libyul/yulSSAControlFlowGraph/function.yul +++ b/test/libyul/yulSSAControlFlowGraph/function.yul @@ -29,9 +29,8 @@ // Block0_0 [label="\ // Block 0\nv0, v1 := i()\l\ // h(v0)\l\ -// h(v1)\l\ // "]; -// Block0_0Exit [label="MainExit"]; +// Block0_0Exit [label="Terminated"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_f_0 [label="function f: // r := f(v0, v1)"]; @@ -55,6 +54,7 @@ // FunctionEntry_h_0 -> Block3_0; // Block3_0 [label="\ // Block 0\nv2 := f(0, v0)\l\ +// h(v2)\l\ // "]; // Block3_0Exit [label="Terminated"]; // Block3_0 -> Block3_0Exit; From 4461699a33f7a78df8c28313cd6e76bb9655279c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:35:34 +0200 Subject: [PATCH 0342/1340] SSACFG: Handle nested function definitions --- .../evm/SSAControlFlowGraphBuilder.cpp | 160 ++++++++---------- .../backends/evm/SSAControlFlowGraphBuilder.h | 18 +- .../nested_function.yul | 142 ++++++++++++++++ 3 files changed, 217 insertions(+), 103 deletions(-) create mode 100644 test/libyul/yulSSAControlFlowGraph/nested_function.yul diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index dc183a085..ceaa8acbd 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -45,11 +45,13 @@ namespace solidity::yul { SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder( + ControlFlow& _controlFlow, SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, Dialect const& _dialect ): + m_controlFlow(_controlFlow), m_graph(_graph), m_info(_analysisInfo), m_sideEffects(_sideEffects), @@ -65,10 +67,16 @@ std::unique_ptr SSAControlFlowGraphBuilder::build( { ControlFlowSideEffectsCollector sideEffects(_dialect, _block); - auto result = std::make_unique(); - auto functions = buildMainGraph(*result->mainGraph, _analysisInfo, sideEffects, _dialect, _block); - buildFunctionGraphs(*result, _analysisInfo, sideEffects, _dialect, functions); - return result; + auto controlFlow = std::make_unique(); + SSAControlFlowGraphBuilder builder(*controlFlow, *controlFlow->mainGraph, _analysisInfo, sideEffects, _dialect); + builder.m_currentBlock = controlFlow->mainGraph->makeBlock(debugDataOf(_block)); + builder.sealBlock(builder.m_currentBlock); + builder(_block); + if (!builder.blockInfo(builder.m_currentBlock).sealed) + builder.sealBlock(builder.m_currentBlock); + controlFlow->mainGraph->block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; + builder.cleanUnreachable(); + return controlFlow; } SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) @@ -236,73 +244,48 @@ void SSAControlFlowGraphBuilder::cleanUnreachable() } } -void SSAControlFlowGraphBuilder::buildFunctionGraphs( - ControlFlow& _controlFlow, - AsmAnalysisInfo const& _info, - ControlFlowSideEffectsCollector const& _sideEffects, - Dialect const& _dialect, - std::vector> const& _functions -) -{ - for (auto const& [function, functionDefinition]: _functions) - { - _controlFlow.functionGraphs.emplace_back(std::make_unique()); - auto& cfg = *_controlFlow.functionGraphs.back(); - _controlFlow.functionGraphMapping.emplace_back(function, &cfg); - - yulAssert(_info.scopes.at(&functionDefinition->body), ""); - Scope* virtualFunctionScope = _info.scopes.at(_info.virtualBlocks.at(functionDefinition).get()).get(); - yulAssert(virtualFunctionScope, ""); - - cfg.entry = cfg.makeBlock(debugDataOf(functionDefinition->body)); - auto arguments = functionDefinition->parameters | ranges::views::transform([&](auto const& _param) { - auto const& var = std::get(virtualFunctionScope->identifiers.at(_param.name)); - // Note: cannot use std::make_tuple since it unwraps reference wrappers. - return std::tuple{std::cref(var), cfg.newVariable(cfg.entry)}; - }) | ranges::to; - auto returns = functionDefinition->returnVariables | ranges::views::transform([&](auto const& _param) { - return std::cref(std::get(virtualFunctionScope->identifiers.at(_param.name))); - }) | ranges::to; - - cfg.debugData = functionDefinition->debugData; - cfg.function = function; - cfg.canContinue = _sideEffects.functionSideEffects().at(functionDefinition).canContinue; - cfg.arguments = arguments; - cfg.returns = returns; - - SSAControlFlowGraphBuilder builder(cfg, _info, _sideEffects, _dialect); - builder.m_currentBlock = cfg.entry; - builder.m_functionDefinitions = _functions; - for (auto&& [var, varId]: cfg.arguments) - builder.currentDef(var, cfg.entry) = varId; - for (auto const& var: cfg.returns) - builder.currentDef(var.get(), cfg.entry) = builder.zero(); - builder.sealBlock(cfg.entry); - builder(functionDefinition->body); - cfg.exits.insert(builder.m_currentBlock); - // Artificial explicit function exit (`leave`) at the end of the body. - builder(Leave{debugDataOf(*functionDefinition)}); - builder.cleanUnreachable(); - } -} - -std::vector> SSAControlFlowGraphBuilder::buildMainGraph( - SSACFG& _cfg, - AsmAnalysisInfo const& _analysisInfo, - ControlFlowSideEffectsCollector const& _sideEffects, - Dialect const& _dialect, - Block const& _block +void SSAControlFlowGraphBuilder::buildFunctionGraph( + Scope::Function const* _function, + FunctionDefinition const* _functionDefinition ) { - SSAControlFlowGraphBuilder builder(_cfg, _analysisInfo, _sideEffects, _dialect); - builder.m_currentBlock = _cfg.makeBlock(debugDataOf(_block)); - builder.sealBlock(builder.m_currentBlock); - builder(_block); - if (!builder.blockInfo(builder.m_currentBlock).sealed) - builder.sealBlock(builder.m_currentBlock); - _cfg.block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; + m_controlFlow.functionGraphs.emplace_back(std::make_unique()); + auto& cfg = *m_controlFlow.functionGraphs.back(); + m_controlFlow.functionGraphMapping.emplace_back(_function, &cfg); + + yulAssert(m_info.scopes.at(&_functionDefinition->body), ""); + Scope* virtualFunctionScope = m_info.scopes.at(m_info.virtualBlocks.at(_functionDefinition).get()).get(); + yulAssert(virtualFunctionScope, ""); + + cfg.entry = cfg.makeBlock(debugDataOf(_functionDefinition->body)); + auto arguments = _functionDefinition->parameters | ranges::views::transform([&](auto const& _param) { + auto const& var = std::get(virtualFunctionScope->identifiers.at(_param.name)); + // Note: cannot use std::make_tuple since it unwraps reference wrappers. + return std::tuple{std::cref(var), cfg.newVariable(cfg.entry)}; + }) | ranges::to; + auto returns = _functionDefinition->returnVariables | ranges::views::transform([&](auto const& _param) { + return std::cref(std::get(virtualFunctionScope->identifiers.at(_param.name))); + }) | ranges::to; + + cfg.debugData = _functionDefinition->debugData; + cfg.function = _function; + cfg.canContinue = m_sideEffects.functionSideEffects().at(_functionDefinition).canContinue; + cfg.arguments = arguments; + cfg.returns = returns; + + SSAControlFlowGraphBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect); + builder.m_currentBlock = cfg.entry; + builder.m_functionDefinitions = m_functionDefinitions; + for (auto&& [var, varId]: cfg.arguments) + builder.currentDef(var, cfg.entry) = varId; + for (auto const& var: cfg.returns) + builder.currentDef(var.get(), cfg.entry) = builder.zero(); + builder.sealBlock(cfg.entry); + builder(_functionDefinition->body); + cfg.exits.insert(builder.m_currentBlock); + // Artificial explicit function exit (`leave`) at the end of the body. + builder(Leave{debugDataOf(*_functionDefinition)}); builder.cleanUnreachable(); - return builder.m_functionDefinitions; } void SSAControlFlowGraphBuilder::operator()(ExpressionStatement const& _expressionStatement) @@ -331,11 +314,8 @@ void SSAControlFlowGraphBuilder::operator()(VariableDeclaration const& _variable void SSAControlFlowGraphBuilder::operator()(FunctionDefinition const& _functionDefinition) { - yulAssert(m_scope, ""); - yulAssert(m_scope->identifiers.count(_functionDefinition.name), ""); - auto& function = std::get(m_scope->identifiers.at(_functionDefinition.name)); - m_graph.functions.emplace_back(function); - m_functionDefinitions.emplace_back(&function, &_functionDefinition); + Scope::Function const& function = lookupFunction(_functionDefinition.name); + buildFunctionGraph(&function, &_functionDefinition); } void SSAControlFlowGraphBuilder::operator()(If const& _if) @@ -537,25 +517,27 @@ void SSAControlFlowGraphBuilder::operator()(Leave const& _leaveStatement) sealBlock(m_currentBlock); } +void SSAControlFlowGraphBuilder::registerFunctionDefinition(FunctionDefinition const& _functionDefinition) +{ + yulAssert(m_scope, ""); + yulAssert(m_scope->identifiers.count(_functionDefinition.name), ""); + auto& function = std::get(m_scope->identifiers.at(_functionDefinition.name)); + m_graph.functions.emplace_back(function); + m_functionDefinitions.emplace_back(&function, &_functionDefinition); +} + void SSAControlFlowGraphBuilder::operator()(Block const& _block) { ScopedSaveAndRestore saveScope(m_scope, m_info.scopes.at(&_block).get()); - if (m_currentBlock == m_graph.entry) - { - auto const filterFunctionDefinitions = [](bool _yieldDefinitionsOnly) - { - return [b=_yieldDefinitionsOnly](Statement const& _statement) -> bool { return !b ^ std::holds_alternative(_statement);}; - }; - for (auto const& statement: _block.statements | ranges::views::filter(filterFunctionDefinitions(true))) - std::visit(*this, statement); - for (auto const& statement: _block.statements | ranges::views::filter(filterFunctionDefinitions(false))) - std::visit(*this, statement); - } - else - { - for (auto const& statement: _block.statements) - std::visit(*this, statement); - } + // gather all function definitions so that they are visible to each other's subgraphs + static constexpr auto functionDefinitionFilter = ranges::views::filter( + [](auto const& _statement) { return std::holds_alternative(_statement); } + ); + for (auto const& statement: _block.statements | functionDefinitionFilter) + registerFunctionDefinition(std::get(statement)); + // now visit the rest + for (auto const& statement: _block.statements) + std::visit(*this, statement); } SSACFG::ValueId SSAControlFlowGraphBuilder::operator()(FunctionCall const& _call) diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.h b/libyul/backends/evm/SSAControlFlowGraphBuilder.h index 8fc537c14..a3a723f67 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.h +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.h @@ -40,6 +40,7 @@ namespace solidity::yul class SSAControlFlowGraphBuilder { SSAControlFlowGraphBuilder( + ControlFlow& _controlFlow, SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, @@ -53,20 +54,6 @@ class SSAControlFlowGraphBuilder Dialect const& _dialect, Block const& _block ); - static void buildFunctionGraphs( - ControlFlow& _controlFlow, - AsmAnalysisInfo const& _info, - ControlFlowSideEffectsCollector const& _sideEffects, - Dialect const& _dialect, - std::vector> const& _functions - ); - static std::vector> buildMainGraph( - SSACFG& _cfg, - AsmAnalysisInfo const& _analysisInfo, - ControlFlowSideEffectsCollector const& _sideEffects, - Dialect const& _dialect, - Block const& _block - ); void operator()(ExpressionStatement const& _statement); void operator()(Assignment const& _assignment); @@ -91,6 +78,8 @@ class SSAControlFlowGraphBuilder SSACFG::ValueId tryRemoveTrivialPhi(SSACFG::ValueId _phi); void assign(std::vector> _variables, Expression const* _expression); std::vector visitFunctionCall(FunctionCall const& _call); + void registerFunctionDefinition(FunctionDefinition const& _functionDefinition); + void buildFunctionGraph(Scope::Function const* _function, FunctionDefinition const* _functionDefinition); SSACFG::ValueId zero(); SSACFG::ValueId readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block); @@ -98,6 +87,7 @@ class SSAControlFlowGraphBuilder SSACFG::ValueId addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi); void writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value); + ControlFlow& m_controlFlow; SSACFG& m_graph; AsmAnalysisInfo const& m_info; ControlFlowSideEffectsCollector const& m_sideEffects; diff --git a/test/libyul/yulSSAControlFlowGraph/nested_function.yul b/test/libyul/yulSSAControlFlowGraph/nested_function.yul new file mode 100644 index 000000000..859b24151 --- /dev/null +++ b/test/libyul/yulSSAControlFlowGraph/nested_function.yul @@ -0,0 +1,142 @@ +{ + function f(a, b) -> r { + let x := add(a,b) + r := sub(x,a) + } + function g() { + function z() -> r { + function w() -> rw1 { + rw1 := 0x01 + } + r := w() + } + function v() -> r { + function w() -> rw2 { + rw2 := 0x11 + } + r := w() + } + sstore(z(), f(v(),2)) + } + function cycle1() -> r { + if mload(3) { + r := cycle2() + } + } + function cycle2() -> r { + if mload(4) { + r := cycle1() + } + } +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans"] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry0 [label="Entry"]; +// Entry0 -> Block0_0; +// Block0_0 [label="\ +// Block 0\n"]; +// Block0_0Exit [label="MainExit"]; +// Block0_0 -> Block0_0Exit; +// FunctionEntry_f_0 [label="function f: +// r := f(v0, v1)"]; +// FunctionEntry_f_0 -> Block1_0; +// Block1_0 [label="\ +// Block 0\nv3 := add(v1, v0)\l\ +// v4 := sub(v0, v3)\l\ +// "]; +// Block1_0Exit [label="FunctionReturn[v4]"]; +// Block1_0 -> Block1_0Exit; +// FunctionEntry_g_0 [label="function g: +// g()"]; +// FunctionEntry_g_0 -> Block2_0; +// Block2_0 [label="\ +// Block 0\nv1 := v()\l\ +// v2 := f(2, v1)\l\ +// v3 := z()\l\ +// sstore(v2, v3)\l\ +// "]; +// Block2_0Exit [label="FunctionReturn[]"]; +// Block2_0 -> Block2_0Exit; +// FunctionEntry_z_0 [label="function z: +// r := z()"]; +// FunctionEntry_z_0 -> Block3_0; +// Block3_0 [label="\ +// Block 0\nv1 := w()\l\ +// "]; +// Block3_0Exit [label="FunctionReturn[v1]"]; +// Block3_0 -> Block3_0Exit; +// FunctionEntry_w_0 [label="function w: +// rw1 := w()"]; +// FunctionEntry_w_0 -> Block4_0; +// Block4_0 [label="\ +// Block 0\n"]; +// Block4_0Exit [label="FunctionReturn[1]"]; +// Block4_0 -> Block4_0Exit; +// FunctionEntry_v_0 [label="function v: +// r := v()"]; +// FunctionEntry_v_0 -> Block5_0; +// Block5_0 [label="\ +// Block 0\nv1 := w()\l\ +// "]; +// Block5_0Exit [label="FunctionReturn[v1]"]; +// Block5_0 -> Block5_0Exit; +// FunctionEntry_w_0 [label="function w: +// rw2 := w()"]; +// FunctionEntry_w_0 -> Block6_0; +// Block6_0 [label="\ +// Block 0\n"]; +// Block6_0Exit [label="FunctionReturn[17]"]; +// Block6_0 -> Block6_0Exit; +// FunctionEntry_cycle1_0 [label="function cycle1: +// r := cycle1()"]; +// FunctionEntry_cycle1_0 -> Block7_0; +// Block7_0 [label="\ +// Block 0\nv2 := mload(3)\l\ +// "]; +// Block7_0 -> Block7_0Exit; +// Block7_0Exit [label="{ If v2| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block7_0Exit:0 -> Block7_2; +// Block7_0Exit:1 -> Block7_1; +// Block7_1 [label="\ +// Block 1\nv3 := cycle2()\l\ +// "]; +// Block7_1 -> Block7_1Exit [arrowhead=none]; +// Block7_1Exit [label="Jump" shape=oval]; +// Block7_1Exit -> Block7_2; +// Block7_2 [label="\ +// Block 2\nv4 := φ(\l\ +// Block 0 => 0,\l\ +// Block 1 => v3\l\ +// )\l\ +// "]; +// Block7_2Exit [label="FunctionReturn[v4]"]; +// Block7_2 -> Block7_2Exit; +// FunctionEntry_cycle2_0 [label="function cycle2: +// r := cycle2()"]; +// FunctionEntry_cycle2_0 -> Block8_0; +// Block8_0 [label="\ +// Block 0\nv2 := mload(4)\l\ +// "]; +// Block8_0 -> Block8_0Exit; +// Block8_0Exit [label="{ If v2| { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block8_0Exit:0 -> Block8_2; +// Block8_0Exit:1 -> Block8_1; +// Block8_1 [label="\ +// Block 1\nv3 := cycle1()\l\ +// "]; +// Block8_1 -> Block8_1Exit [arrowhead=none]; +// Block8_1Exit [label="Jump" shape=oval]; +// Block8_1Exit -> Block8_2; +// Block8_2 [label="\ +// Block 2\nv4 := φ(\l\ +// Block 0 => 0,\l\ +// Block 1 => v3\l\ +// )\l\ +// "]; +// Block8_2Exit [label="FunctionReturn[v4]"]; +// Block8_2 -> Block8_2Exit; +// } From 47ba76f14018e1570c9ad47ab15760883e2c2dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 24 Sep 2024 16:07:46 +0200 Subject: [PATCH 0343/1340] benchmarks: Move shared code using /usr/bin/time into a helper with JSON output --- scripts/common.sh | 20 ++++++++++++++++++-- test/benchmarks/external.sh | 18 ++++++++---------- test/benchmarks/local.sh | 12 ++++++------ 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/scripts/common.sh b/scripts/common.sh index 81dd2ec49..2061649f7 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -327,7 +327,7 @@ function gnu_grep function time_to_json_file { - local output_file="$1" + local time_file="$1" local cmd=("${@:2}") (( $# >= 2 )) || assertFail @@ -340,9 +340,25 @@ function time_to_json_file { { time { "${cmd[@]}" 1>&3 2>&4; } - } 2> "$output_file" + } 2> "$time_file" } 3>&1 4>&2 # Restore original format so that it does not spill outside of the function. TIMEFORMAT="$original_timeformat" } + +function gnu_time_to_json_file +{ + local time_file="$1" + local cmd=("${@:2}") + (( $# >= 2 )) || assertFail + + local gnu_time_path + gnu_time_path=$(type -P time) + + "$gnu_time_path" \ + --output "$time_file" \ + --quiet \ + --format '{"real": %e, "user": %U, "sys": %S, "exit": %x}' \ + "${cmd[@]}" +} diff --git a/test/benchmarks/external.sh b/test/benchmarks/external.sh index b37c9105d..cf75a0c9f 100755 --- a/test/benchmarks/external.sh +++ b/test/benchmarks/external.sh @@ -46,6 +46,7 @@ source "${repo_root}/scripts/common_cmdline.sh" solc="${1:-${SOLIDITY_BUILD_DIR}/solc/solc}" command_available "$solc" --version +command_available "$(type -P time)" --version function benchmark_project { local pipeline="$1" @@ -59,18 +60,16 @@ function benchmark_project { # NOTE: The pipeline may fail with "Stack too deep" in some cases. That's fine. # We note the exit code and will later show full output. - "$time_bin_path" \ - --output "$time_file" \ - --quiet \ - --format '%e s | %x' \ - "${foundry_command[@]}" \ - > /dev/null \ - 2> "../stderr-${project}-${pipeline}.log" || true + gnu_time_to_json_file "$time_file" \ + "${foundry_command[@]}" \ + > /dev/null \ + 2> "../stderr-${project}-${pipeline}.log" || true - printf '| %-20s | %8s | %21s |\n' \ + printf '| %-20s | %8s | %7s s | %9d |\n' \ "$project" \ "$pipeline" \ - "$(cat "$time_file")" + "$(jq '.real' "$time_file")" \ + "$(jq '.exit' "$time_file")" cd .. } @@ -82,7 +81,6 @@ benchmarks=( seaport sablier-v2 ) -time_bin_path=$(type -P time) mkdir -p "$BENCHMARK_DIR" cd "$BENCHMARK_DIR" diff --git a/test/benchmarks/local.sh b/test/benchmarks/local.sh index 16a0c3afe..42018e7a1 100755 --- a/test/benchmarks/local.sh +++ b/test/benchmarks/local.sh @@ -35,6 +35,7 @@ source "${REPO_ROOT}/scripts/common_cmdline.sh" solc="${1:-${SOLIDITY_BUILD_DIR}/solc/solc}" command_available "$solc" --version +command_available "$(type -P time)" --version output_dir=$(mktemp -d -t solc-benchmark-XXXXXX) @@ -51,24 +52,23 @@ function benchmark_contract { local solc_command=("${solc}" --optimize --bin --color "${input_path}") [[ $pipeline == via-ir ]] && solc_command+=(--via-ir) - local time_args=(--output "${output_dir}/time-and-status-${pipeline}.txt" --quiet --format '%e s | %x') + local time_file="${output_dir}/time-and-status-${pipeline}.txt" # NOTE: Legacy pipeline may fail with "Stack too deep" in some cases. That's fine. - "$time_bin_path" \ - "${time_args[@]}" \ + gnu_time_to_json_file "$time_file" \ "${solc_command[@]}" \ > "${output_dir}/bytecode-${pipeline}.bin" \ 2>> "${output_dir}/benchmark-warn-err.txt" || [[ $pipeline == legacy ]] - printf '| %-20s | %s | %7d bytes | %20s |\n' \ + printf '| %-20s | %s | %7d bytes | %6s s | %9d |\n' \ '`'"$input_file"'`' \ "$pipeline" \ "$(bytecode_size < "${output_dir}/bytecode-${pipeline}.bin")" \ - "$(< "${output_dir}/time-and-status-${pipeline}.txt")" + "$(jq '.real' "$time_file")" \ + "$(jq '.exit' "$time_file")" } benchmarks=("verifier.sol" "OptimizorClub.sol" "chains.sol") -time_bin_path=$(type -P time) echo "| File | Pipeline | Bytecode size | Time | Exit code |" echo "|----------------------|----------|--------------:|---------:|----------:|" From 8bb279bed90fc7eb494fe2389fc95abe8f4486de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 24 Sep 2024 16:21:51 +0200 Subject: [PATCH 0344/1340] benchmarks: Switch to displaying CPU time rather than wall clock time and round it for external projects --- test/benchmarks/external.sh | 4 ++-- test/benchmarks/local.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/benchmarks/external.sh b/test/benchmarks/external.sh index cf75a0c9f..5188d23d8 100755 --- a/test/benchmarks/external.sh +++ b/test/benchmarks/external.sh @@ -65,10 +65,10 @@ function benchmark_project { > /dev/null \ 2> "../stderr-${project}-${pipeline}.log" || true - printf '| %-20s | %8s | %7s s | %9d |\n' \ + printf '| %-20s | %8s | %7d s | %9d |\n' \ "$project" \ "$pipeline" \ - "$(jq '.real' "$time_file")" \ + "$(jq '(.user + .sys) | round' "$time_file")" \ "$(jq '.exit' "$time_file")" cd .. } diff --git a/test/benchmarks/local.sh b/test/benchmarks/local.sh index 42018e7a1..f250251b1 100755 --- a/test/benchmarks/local.sh +++ b/test/benchmarks/local.sh @@ -60,11 +60,11 @@ function benchmark_contract { > "${output_dir}/bytecode-${pipeline}.bin" \ 2>> "${output_dir}/benchmark-warn-err.txt" || [[ $pipeline == legacy ]] - printf '| %-20s | %s | %7d bytes | %6s s | %9d |\n' \ + printf '| %-20s | %s | %7d bytes | %6.2f s | %9d |\n' \ '`'"$input_file"'`' \ "$pipeline" \ "$(bytecode_size < "${output_dir}/bytecode-${pipeline}.bin")" \ - "$(jq '.real' "$time_file")" \ + "$(jq '(.user + .sys) * 100 | round / 100' "$time_file")" \ "$(jq '.exit' "$time_file")" } From 95534b6b200c49bfa5f7d801a2cc7f8b4b402666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 24 Sep 2024 16:24:00 +0200 Subject: [PATCH 0345/1340] benchmarks: Show peak memory usage --- scripts/common.sh | 2 +- test/benchmarks/external.sh | 7 ++++--- test/benchmarks/local.sh | 7 ++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/scripts/common.sh b/scripts/common.sh index 2061649f7..0ca602ee6 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -359,6 +359,6 @@ function gnu_time_to_json_file "$gnu_time_path" \ --output "$time_file" \ --quiet \ - --format '{"real": %e, "user": %U, "sys": %S, "exit": %x}' \ + --format '{"real": %e, "user": %U, "sys": %S, "mem": %M, "exit": %x}' \ "${cmd[@]}" } diff --git a/test/benchmarks/external.sh b/test/benchmarks/external.sh index 5188d23d8..e93c485fa 100755 --- a/test/benchmarks/external.sh +++ b/test/benchmarks/external.sh @@ -65,10 +65,11 @@ function benchmark_project { > /dev/null \ 2> "../stderr-${project}-${pipeline}.log" || true - printf '| %-20s | %8s | %7d s | %9d |\n' \ + printf '| %-20s | %8s | %7d s | %9d MiB | %9d |\n' \ "$project" \ "$pipeline" \ "$(jq '(.user + .sys) | round' "$time_file")" \ + "$(jq '.mem / 1024 | round' "$time_file")" \ "$(jq '.exit' "$time_file")" cd .. } @@ -85,8 +86,8 @@ benchmarks=( mkdir -p "$BENCHMARK_DIR" cd "$BENCHMARK_DIR" -echo "| Project | Pipeline | Time | Exit code |" -echo "|----------------------|----------|----------:|----------:|" +echo "| Project | Pipeline | Time | Memory (peak) | Exit code |" +echo "|----------------------|----------|----------:|--------------:|----------:|" for project in "${benchmarks[@]}"; do benchmark_project legacy "$project" diff --git a/test/benchmarks/local.sh b/test/benchmarks/local.sh index f250251b1..c86eb4952 100755 --- a/test/benchmarks/local.sh +++ b/test/benchmarks/local.sh @@ -60,18 +60,19 @@ function benchmark_contract { > "${output_dir}/bytecode-${pipeline}.bin" \ 2>> "${output_dir}/benchmark-warn-err.txt" || [[ $pipeline == legacy ]] - printf '| %-20s | %s | %7d bytes | %6.2f s | %9d |\n' \ + printf '| %-20s | %s | %7d bytes | %6.2f s | %9d MiB | %9d |\n' \ '`'"$input_file"'`' \ "$pipeline" \ "$(bytecode_size < "${output_dir}/bytecode-${pipeline}.bin")" \ "$(jq '(.user + .sys) * 100 | round / 100' "$time_file")" \ + "$(jq '.mem / 1024 | round' "$time_file")" \ "$(jq '.exit' "$time_file")" } benchmarks=("verifier.sol" "OptimizorClub.sol" "chains.sol") -echo "| File | Pipeline | Bytecode size | Time | Exit code |" -echo "|----------------------|----------|--------------:|---------:|----------:|" +echo "| File | Pipeline | Bytecode size | Time | Memory (peak) | Exit code |" +echo "|----------------------|----------|--------------:|---------:|--------------:|----------:|" for input_file in "${benchmarks[@]}" do From 9bf850bf8887be2558cf9bf9f6e282658d25cb6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 24 Sep 2024 16:26:26 +0200 Subject: [PATCH 0346/1340] benchmarks: Cosmetic tweaks to how results are displayed - via-ir -> ir - Centered headers --- test/benchmarks/external.sh | 6 +++--- test/benchmarks/local.sh | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/benchmarks/external.sh b/test/benchmarks/external.sh index e93c485fa..9acaccb67 100755 --- a/test/benchmarks/external.sh +++ b/test/benchmarks/external.sh @@ -65,7 +65,7 @@ function benchmark_project { > /dev/null \ 2> "../stderr-${project}-${pipeline}.log" || true - printf '| %-20s | %8s | %7d s | %9d MiB | %9d |\n' \ + printf '| %-20s | %8s | %6d s | %9d MiB | %9d |\n' \ "$project" \ "$pipeline" \ "$(jq '(.user + .sys) | round' "$time_file")" \ @@ -86,8 +86,8 @@ benchmarks=( mkdir -p "$BENCHMARK_DIR" cd "$BENCHMARK_DIR" -echo "| Project | Pipeline | Time | Memory (peak) | Exit code |" -echo "|----------------------|----------|----------:|--------------:|----------:|" +echo "| File | Pipeline | Time | Memory (peak) | Exit code |" +echo "|----------------------|----------|---------:|--------------:|----------:|" for project in "${benchmarks[@]}"; do benchmark_project legacy "$project" diff --git a/test/benchmarks/local.sh b/test/benchmarks/local.sh index c86eb4952..069644301 100755 --- a/test/benchmarks/local.sh +++ b/test/benchmarks/local.sh @@ -51,7 +51,7 @@ function benchmark_contract { local input_path="$2" local solc_command=("${solc}" --optimize --bin --color "${input_path}") - [[ $pipeline == via-ir ]] && solc_command+=(--via-ir) + [[ $pipeline == ir ]] && solc_command+=(--via-ir) local time_file="${output_dir}/time-and-status-${pipeline}.txt" # NOTE: Legacy pipeline may fail with "Stack too deep" in some cases. That's fine. @@ -60,7 +60,7 @@ function benchmark_contract { > "${output_dir}/bytecode-${pipeline}.bin" \ 2>> "${output_dir}/benchmark-warn-err.txt" || [[ $pipeline == legacy ]] - printf '| %-20s | %s | %7d bytes | %6.2f s | %9d MiB | %9d |\n' \ + printf '| %-20s | %8s | %7d bytes | %6.2f s | %9d MiB | %9d |\n' \ '`'"$input_file"'`' \ "$pipeline" \ "$(bytecode_size < "${output_dir}/bytecode-${pipeline}.bin")" \ @@ -71,13 +71,13 @@ function benchmark_contract { benchmarks=("verifier.sol" "OptimizorClub.sol" "chains.sol") -echo "| File | Pipeline | Bytecode size | Time | Memory (peak) | Exit code |" +echo "| File | Pipeline | Bytecode size | Time | Memory (peak) | Exit code |" echo "|----------------------|----------|--------------:|---------:|--------------:|----------:|" for input_file in "${benchmarks[@]}" do benchmark_contract legacy "${REPO_ROOT}/test/benchmarks/${input_file}" - benchmark_contract via-ir "${REPO_ROOT}/test/benchmarks/${input_file}" + benchmark_contract ir "${REPO_ROOT}/test/benchmarks/${input_file}" done echo From 545cab32de0e1c09dcbe489f002bae285e220fd8 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 25 Sep 2024 09:49:16 +0200 Subject: [PATCH 0347/1340] eof: Refactor `assemble` functions in `evmasm::Assembly`` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- libevmasm/Assembly.cpp | 226 +++++++++++---------- libevmasm/Assembly.h | 14 ++ libevmasm/LinkerObject.h | 3 +- libsolidity/interface/StandardCompiler.cpp | 2 +- 4 files changed, 140 insertions(+), 105 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 0d5468e26..f99309554 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -926,19 +926,19 @@ std::tuple, size_t> Assembly::createEOFHeader(std::se retBytecode.push_back(0xef); retBytecode.push_back(0x00); - retBytecode.push_back(0x01); // version 1 + retBytecode.push_back(0x01); // version 1 - retBytecode.push_back(0x01); // kind=type - appendBigEndianUint16(retBytecode, m_codeSections.size() * 4u); // length of type section + retBytecode.push_back(0x01); // kind=type + appendBigEndianUint16(retBytecode, m_codeSections.size() * 4u); // length of type section - retBytecode.push_back(0x02); // kind=code - appendBigEndianUint16(retBytecode, m_codeSections.size()); // placeholder for number of code sections + retBytecode.push_back(0x02); // kind=code + appendBigEndianUint16(retBytecode, m_codeSections.size()); // placeholder for number of code sections for (auto const& codeSection: m_codeSections) { (void) codeSection; codeSectionSizeOffsets.emplace_back(retBytecode.size()); - appendBigEndianUint16(retBytecode, 0u); // placeholder for length of code + appendBigEndianUint16(retBytecode, 0u); // placeholder for length of code } if (!_referencedSubIds.empty()) @@ -950,17 +950,18 @@ std::tuple, size_t> Assembly::createEOFHeader(std::se appendBigEndianUint16(retBytecode, m_subs[subId]->assemble().bytecode.size()); } - retBytecode.push_back(0x04); // kind=data + retBytecode.push_back(0x04); // kind=data dataSectionSizeOffset = retBytecode.size(); - appendBigEndianUint16(retBytecode, 0u); // length of data + appendBigEndianUint16(retBytecode, 0u); // length of data - retBytecode.push_back(0x00); // terminator + retBytecode.push_back(0x00); // terminator for (auto const& codeSection: m_codeSections) { retBytecode.push_back(codeSection.inputs); retBytecode.push_back(codeSection.outputs); - appendBigEndianUint16(retBytecode, 0xFFFFu); // TODO: Add stack height calculation + // TODO: Add stack height calculation + appendBigEndianUint16(retBytecode, 0xFFFFu); } return {retBytecode, codeSectionSizeOffsets, dataSectionSizeOffset}; @@ -985,6 +986,65 @@ LinkerObject const& Assembly::assemble() const return assembleEOF(); } +[[nodiscard]] bytes Assembly::assembleOperation(AssemblyItem const& _item) const +{ + // solidity::evmasm::Instructions underlying type is uint8_t + // TODO: Change to std::to_underlying since C++23 + return {static_cast(_item.instruction())}; +} + +[[nodiscard]] bytes Assembly::assemblePush(AssemblyItem const& _item) const +{ + bytes ret; + unsigned pushValueSize = numberEncodingSize(_item.data()); + if (pushValueSize == 0 && !m_evmVersion.hasPush0()) + pushValueSize = 1; + + // solidity::evmasm::Instructions underlying type is uint8_t + // TODO: Change to std::to_underlying since C++23 + ret.push_back(static_cast(pushInstruction(pushValueSize))); + if (pushValueSize > 0) + appendBigEndian(ret, pushValueSize, _item.data()); + + return ret; +} + +[[nodiscard]] std::pair Assembly::assemblePushLibraryAddress(AssemblyItem const& _item, size_t _pos) const +{ + return { + // solidity::evmasm::Instructions underlying type is uint8_t + // TODO: Change to std::to_underlying since C++23 + bytes(1, static_cast(Instruction::PUSH20)) + bytes(20), + {_pos + 1, m_libraries.at(_item.data())} + }; +} + +[[nodiscard]] bytes Assembly::assembleVerbatimBytecode(AssemblyItem const& item) const +{ + return item.verbatimData(); +} + +[[nodiscard]] bytes Assembly::assemblePushDeployTimeAddress() const +{ + // solidity::evmasm::Instructions underlying type is uint8_t + // TODO: Change to std::to_underlying since C++23 + return bytes(1, static_cast(Instruction::PUSH20)) + bytes(20); +} + +[[nodiscard]] bytes Assembly::assembleTag(AssemblyItem const& _item, size_t _pos, bool _addJumpDest) const +{ + solRequire(_item.data() != 0, AssemblyException, "Invalid tag position."); + solRequire(_item.splitForeignPushTag().first == std::numeric_limits::max(), AssemblyException, "Foreign tag."); + solRequire(_pos < 0xffffffffL, AssemblyException, "Tag too large."); + size_t tagId = static_cast(_item.data()); + solRequire(m_tagPositionsInBytecode[tagId] == std::numeric_limits::max(), AssemblyException, "Duplicate tag position."); + m_tagPositionsInBytecode[tagId] = _pos; + + // solidity::evmasm::Instructions underlying type is uint8_t + // TODO: Change to std::to_underlying since C++23 + return _addJumpDest ? bytes(1, static_cast(Instruction::JUMPDEST)) : bytes(); +} + LinkerObject const& Assembly::assembleLegacy() const { solAssert(!m_eofVersion.has_value()); @@ -998,7 +1058,7 @@ LinkerObject const& Assembly::assembleLegacy() const LinkerObject& ret = m_assembledObject; size_t subTagSize = 1; - std::map>> immutableReferencesBySub; + std::map immutableReferencesBySub; for (auto const& sub: m_subs) { auto const& linkerObject = sub->assemble(); @@ -1039,10 +1099,6 @@ LinkerObject const& Assembly::assembleLegacy() const unsigned bytesRequiredForCode = codeSize(static_cast(subTagSize)); m_tagPositionsInBytecode = std::vector(m_usedTags, std::numeric_limits::max()); - std::map> tagRef; - std::multimap dataRef; - std::multimap subRef; - std::vector sizeRef; ///< Pointers to code locations where the size of the program is inserted unsigned bytesPerTag = numberEncodingSize(bytesRequiredForCode); // Adjust bytesPerTag for references to sub assemblies. for (AssemblyItem const& item: items) @@ -1056,16 +1112,21 @@ LinkerObject const& Assembly::assembleLegacy() const assertThrow(subTagPosition != std::numeric_limits::max(), AssemblyException, "Reference to tag without position."); bytesPerTag = std::max(bytesPerTag, numberEncodingSize(subTagPosition)); } - uint8_t tagPush = static_cast(pushInstruction(bytesPerTag)); unsigned bytesRequiredIncludingData = bytesRequiredForCode + 1 + static_cast(m_auxiliaryData.size()); for (auto const& sub: m_subs) bytesRequiredIncludingData += static_cast(sub->assemble().bytecode.size()); unsigned bytesPerDataRef = numberEncodingSize(bytesRequiredIncludingData); - uint8_t dataRefPush = static_cast(pushInstruction(bytesPerDataRef)); ret.bytecode.reserve(bytesRequiredIncludingData); + TagRefs tagRefs; + DataRefs dataRefs; + SubAssemblyRefs subRefs; + ProgramSizeRefs sizeRefs; + uint8_t tagPush = static_cast(pushInstruction(bytesPerTag)); + uint8_t dataRefPush = static_cast(pushInstruction(bytesPerDataRef)); + for (AssemblyItem const& item: items) { // store position of the invalid jump destination @@ -1075,40 +1136,27 @@ LinkerObject const& Assembly::assembleLegacy() const switch (item.type()) { case Operation: - ret.bytecode.push_back(static_cast(item.instruction())); + ret.bytecode += assembleOperation(item); break; case Push: - { - unsigned b = numberEncodingSize(item.data()); - if (b == 0 && !m_evmVersion.hasPush0()) - { - b = 1; - } - ret.bytecode.push_back(static_cast(pushInstruction(b))); - if (b > 0) - { - ret.bytecode.resize(ret.bytecode.size() + b); - bytesRef byr(&ret.bytecode.back() + 1 - b, b); - toBigEndian(item.data(), byr); - } + ret.bytecode += assemblePush(item); break; - } case PushTag: { ret.bytecode.push_back(tagPush); - tagRef[ret.bytecode.size()] = item.splitForeignPushTag(); + tagRefs[ret.bytecode.size()] = item.splitForeignPushTag(); ret.bytecode.resize(ret.bytecode.size() + bytesPerTag); break; } case PushData: ret.bytecode.push_back(dataRefPush); - dataRef.insert(std::make_pair(h256(item.data()), ret.bytecode.size())); + dataRefs.insert(std::make_pair(h256(item.data()), ret.bytecode.size())); ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); break; case PushSub: assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); ret.bytecode.push_back(dataRefPush); - subRef.insert(std::make_pair(static_cast(item.data()), ret.bytecode.size())); + subRefs.insert(std::make_pair(static_cast(item.data()), ret.bytecode.size())); ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); break; case PushSubSize: @@ -1126,15 +1174,17 @@ LinkerObject const& Assembly::assembleLegacy() const case PushProgramSize: { ret.bytecode.push_back(dataRefPush); - sizeRef.push_back(static_cast(ret.bytecode.size())); + sizeRefs.push_back(static_cast(ret.bytecode.size())); ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); break; } case PushLibraryAddress: - ret.bytecode.push_back(static_cast(Instruction::PUSH20)); - ret.linkReferences[ret.bytecode.size()] = m_libraries.at(item.data()); - ret.bytecode.resize(ret.bytecode.size() + 20); + { + auto const [bytecode, linkRef] = assemblePushLibraryAddress(item, ret.bytecode.size()); + ret.bytecode += bytecode; + ret.linkReferences.insert(linkRef); break; + } case PushImmutable: ret.bytecode.push_back(static_cast(Instruction::PUSH32)); // Maps keccak back to the "identifier" std::string of that immutable. @@ -1145,7 +1195,7 @@ LinkerObject const& Assembly::assembleLegacy() const ret.bytecode.resize(ret.bytecode.size() + 32); break; case VerbatimBytecode: - ret.bytecode += item.verbatimData(); + ret.bytecode += assembleVerbatimBytecode(item); break; case AssignImmutable: { @@ -1174,20 +1224,11 @@ LinkerObject const& Assembly::assembleLegacy() const break; } case PushDeployTimeAddress: - ret.bytecode.push_back(static_cast(Instruction::PUSH20)); - ret.bytecode.resize(ret.bytecode.size() + 20); + ret.bytecode += assemblePushDeployTimeAddress(); break; case Tag: - { - assertThrow(item.data() != 0, AssemblyException, "Invalid tag position."); - assertThrow(item.splitForeignPushTag().first == std::numeric_limits::max(), AssemblyException, "Foreign tag."); - size_t tagId = static_cast(item.data()); - assertThrow(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large."); - assertThrow(m_tagPositionsInBytecode[tagId] == std::numeric_limits::max(), AssemblyException, "Duplicate tag position."); - m_tagPositionsInBytecode[tagId] = ret.bytecode.size(); - ret.bytecode.push_back(static_cast(Instruction::JUMPDEST)); + ret.bytecode += assembleTag(item, ret.bytecode.size(), true); break; - } default: assertThrow(false, InvalidOpcode, "Unexpected opcode while assembling."); } @@ -1206,7 +1247,7 @@ LinkerObject const& Assembly::assembleLegacy() const ret.bytecode.push_back(static_cast(Instruction::INVALID)); std::map subAssemblyOffsets; - for (auto const& [subIdPath, bytecodeOffset]: subRef) + for (auto const& [subIdPath, bytecodeOffset]: subRefs) { LinkerObject subObject = subAssemblyById(subIdPath)->assemble(); bytesRef r(ret.bytecode.data() + bytecodeOffset, bytesPerDataRef); @@ -1224,7 +1265,7 @@ LinkerObject const& Assembly::assembleLegacy() const for (auto const& ref: subObject.linkReferences) ret.linkReferences[ref.first + subAssemblyOffsets[subObject]] = ref.second; } - for (auto const& i: tagRef) + for (auto const& i: tagRefs) { size_t subId; size_t tagId; @@ -1262,7 +1303,7 @@ LinkerObject const& Assembly::assembleLegacy() const for (auto const& dataItem: m_data) { - auto references = dataRef.equal_range(dataItem.first); + auto references = dataRefs.equal_range(dataItem.first); if (references.first == references.second) continue; for (auto ref = references.first; ref != references.second; ++ref) @@ -1275,7 +1316,7 @@ LinkerObject const& Assembly::assembleLegacy() const ret.bytecode += m_auxiliaryData; - for (unsigned pos: sizeRef) + for (unsigned pos: sizeRefs) { bytesRef r(ret.bytecode.data() + pos, bytesPerDataRef); toBigEndian(ret.bytecode.size(), r); @@ -1321,15 +1362,14 @@ LinkerObject const& Assembly::assembleEOF() const ); // Insert EOF1 header. - auto [bytecode, codeSectionSizeOffsets, dataSectionSizeOffset] = createEOFHeader(referencedSubIds); - ret.bytecode = bytecode; + auto [headerBytecode, codeSectionSizeOffsets, dataSectionSizeOffset] = createEOFHeader(referencedSubIds); + ret.bytecode = headerBytecode; m_tagPositionsInBytecode = std::vector(m_usedTags, std::numeric_limits::max()); for (auto&& [codeSectionIndex, codeSection]: m_codeSections | ranges::views::enumerate) { auto const sectionStart = ret.bytecode.size(); - for (AssemblyItem const& item: codeSection.items) { // store position of the invalid jump destination @@ -1338,54 +1378,34 @@ LinkerObject const& Assembly::assembleEOF() const switch (item.type()) { - case Operation: - ret.bytecode.push_back(static_cast(item.instruction())); - break; - case Push: - { - unsigned pushValueSize = numberEncodingSize(item.data()); - if (pushValueSize == 0 && !m_evmVersion.hasPush0()) - { - pushValueSize = 1; - } - ret.bytecode.push_back(static_cast(pushInstruction(pushValueSize))); - if (pushValueSize > 0) - { - ret.bytecode.resize(ret.bytecode.size() + pushValueSize); - bytesRef pushValueBytecodeRef(&ret.bytecode.back() + 1 - pushValueSize, pushValueSize); - toBigEndian(item.data(), pushValueBytecodeRef); - } - break; - } - case PushLibraryAddress: - ret.bytecode.push_back(static_cast(Instruction::PUSH20)); - ret.linkReferences[ret.bytecode.size()] = m_libraries.at(item.data()); - ret.bytecode.resize(ret.bytecode.size() + 20); - break; - case VerbatimBytecode: - ret.bytecode += item.verbatimData(); - break; - case PushDeployTimeAddress: - ret.bytecode.push_back(static_cast(Instruction::PUSH20)); - ret.bytecode.resize(ret.bytecode.size() + 20); - break; - case Tag: - { - solRequire(item.data() != 0, AssemblyException, "Invalid tag position."); - solRequire(item.splitForeignPushTag().first == std::numeric_limits::max(), AssemblyException, "Foreign tag."); - size_t tagId = static_cast(item.data()); - solRequire(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large."); - solRequire(m_tagPositionsInBytecode[tagId] == std::numeric_limits::max(), AssemblyException, "Duplicate tag position."); - m_tagPositionsInBytecode[tagId] = ret.bytecode.size(); - break; - } - default: - solRequire(false, InvalidOpcode, "Unexpected opcode while assembling."); + case Operation: + ret.bytecode += assembleOperation(item); + break; + case Push: + ret.bytecode += assemblePush(item); + break; + case PushLibraryAddress: + { + auto const [pushLibraryAddressBytecode, linkRef] = assemblePushLibraryAddress(item, ret.bytecode.size()); + ret.bytecode += pushLibraryAddressBytecode; + ret.linkReferences.insert(linkRef); + break; + } + case VerbatimBytecode: + ret.bytecode += assembleVerbatimBytecode(item); + break; + case PushDeployTimeAddress: + ret.bytecode += assemblePushDeployTimeAddress(); + break; + case Tag: + ret.bytecode += assembleTag(item, ret.bytecode.size(), false); + break; + default: + solThrow(InvalidOpcode, "Unexpected opcode while assembling."); } } - auto sectionEnd = ret.bytecode.size(); - setBigEndianUint16(ret.bytecode, codeSectionSizeOffsets[codeSectionIndex], sectionEnd - sectionStart); + setBigEndianUint16(ret.bytecode, codeSectionSizeOffsets[codeSectionIndex], ret.bytecode.size() - sectionStart); } for (auto i: referencedSubIds) diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 41e735db6..de1ac20f2 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -47,6 +47,12 @@ using AssemblyPointer = std::shared_ptr; class Assembly { + using TagRefs = std::map>; + using DataRefs = std::multimap; + using SubAssemblyRefs = std::multimap; + using ProgramSizeRefs = std::vector; + using LinkRef = std::pair; + public: Assembly(langutil::EVMVersion _evmVersion, bool _creation, std::optional _eofVersion, std::string _name): m_evmVersion(_evmVersion), @@ -235,6 +241,14 @@ class Assembly /// Returns map from m_subs to an index of subcontainer in the final EOF bytecode std::map findReferencedContainers() const; + /// Assemble bytecode for AssemblyItem type. + [[nodiscard]] bytes assembleOperation(AssemblyItem const& _item) const; + [[nodiscard]] bytes assemblePush(AssemblyItem const& _item) const; + [[nodiscard]] std::pair assemblePushLibraryAddress(AssemblyItem const& _item, size_t _pos) const; + [[nodiscard]] bytes assembleVerbatimBytecode(AssemblyItem const& item) const; + [[nodiscard]] bytes assemblePushDeployTimeAddress() const; + [[nodiscard]] bytes assembleTag(AssemblyItem const& _item, size_t _pos, bool _addJumpDest) const; + protected: /// 0 is reserved for exception unsigned m_usedTags = 1; diff --git a/libevmasm/LinkerObject.h b/libevmasm/LinkerObject.h index 90b519e3a..c103a565a 100644 --- a/libevmasm/LinkerObject.h +++ b/libevmasm/LinkerObject.h @@ -34,6 +34,7 @@ namespace solidity::evmasm */ struct LinkerObject { + using ImmutableRefs = std::pair>; /// The bytecode. bytes bytecode; @@ -43,7 +44,7 @@ struct LinkerObject /// Map from hashes of the identifiers of immutable variables to the full identifier of the immutable and /// to a list of offsets into the bytecode that refer to their values. - std::map>> immutableReferences; + std::map immutableReferences; struct FunctionDebugData { diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index cd00caf07..06df8a940 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -349,7 +349,7 @@ Json formatLinkReferences(std::map const& linkReferences) return ret; } -Json formatImmutableReferences(std::map>> const& _immutableReferences) +Json formatImmutableReferences(std::map const& _immutableReferences) { Json ret = Json::object(); From 09c48f57534d1da162409773954d8e98aeba178d Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 24 Sep 2024 15:22:18 +0200 Subject: [PATCH 0348/1340] eof: Support EOF in `assemblyStream` --- libevmasm/Assembly.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index f99309554..ab26526e1 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -403,13 +403,14 @@ void Assembly::assemblyStream( { Functionalizer f(_out, _prefix, _sourceCodes, *this); - // TODO: support EOF - solUnimplementedAssert(!m_eofVersion.has_value(), "Assembly output for EOF is not yet implemented."); - solAssert(m_codeSections.size() == 1); for (auto const& i: m_codeSections.front().items) f.feed(i, _debugInfoSelection); f.flush(); + // Implementing this requires introduction of CALLF, RETF and JUMPF + if (m_codeSections.size() > 1) + solUnimplemented("Add support for more code sections"); + if (!m_data.empty() || !m_subs.empty()) { _out << _prefix << "stop" << std::endl; From 9e65fffd58b63ee881f38cb955442b0828ed2ceb Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 24 Sep 2024 15:34:34 +0200 Subject: [PATCH 0349/1340] eof: Support EOF in `computeSourceMapping` --- libevmasm/AssemblyItem.cpp | 5 +++-- libyul/YulStack.cpp | 15 +++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 837dad8af..1bc805780 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -450,9 +450,10 @@ std::string AssemblyItem::computeSourceMapping( static_cast(_sourceIndicesMap.at(*location.sourceName)) : -1; char jump = '-'; - if (item.getJumpType() == evmasm::AssemblyItem::JumpType::IntoFunction) + // TODO: Uncomment when EOF functions introduced. + if (item.getJumpType() == evmasm::AssemblyItem::JumpType::IntoFunction /*|| item.type() == CallF || item.type() == JumpF*/) jump = 'i'; - else if (item.getJumpType() == evmasm::AssemblyItem::JumpType::OutOfFunction) + else if (item.getJumpType() == evmasm::AssemblyItem::JumpType::OutOfFunction /*|| item.type() == RetF*/) jump = 'o'; int modifierDepth = static_cast(item.m_modifierDepth); diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index a8e19a69a..59766220c 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -262,15 +262,14 @@ YulStack::assembleWithDeployed(std::optional _deployName) creationObject.bytecode = std::make_shared(creationAssembly->assemble()); yulAssert(creationObject.bytecode->immutableReferences.empty(), "Leftover immutables."); creationObject.assembly = creationAssembly; - solUnimplementedAssert(!m_eofVersion.has_value(), "EVM assembly output not implemented for EOF yet."); - solAssert(creationAssembly->codeSections().size() == 1); - creationObject.sourceMappings = std::make_unique( - // TODO: fix for EOF - evmasm::AssemblyItem::computeSourceMapping( - creationAssembly->codeSections().front().items, + creationObject.sourceMappings = std::make_unique(); + for (auto const& codeSection: creationAssembly->codeSections()) + { + *creationObject.sourceMappings += evmasm::AssemblyItem::computeSourceMapping( + codeSection.items, {{m_charStream->name(), 0}} - ) - ); + ); + } if (deployedAssembly) { From 415d2fca3692d676f007bfdd9f4acd4227de3c57 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 25 Sep 2024 10:27:58 +0200 Subject: [PATCH 0350/1340] eof: strict asm output test update --- .../strict_asm_eof_container_prague/args | 2 +- .../strict_asm_eof_container_prague/output | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/args b/test/cmdlineTests/strict_asm_eof_container_prague/args index b8cc1ab18..0078e6e68 100644 --- a/test/cmdlineTests/strict_asm_eof_container_prague/args +++ b/test/cmdlineTests/strict_asm_eof_container_prague/args @@ -1 +1 @@ - --strict-assembly --experimental-eof-version 1 --evm-version prague --bin + --strict-assembly --experimental-eof-version 1 --evm-version prague --asm --ir-optimized --bin --debug-info none diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/output b/test/cmdlineTests/strict_asm_eof_container_prague/output index caf28d91d..17f6df675 100644 --- a/test/cmdlineTests/strict_asm_eof_container_prague/output +++ b/test/cmdlineTests/strict_asm_eof_container_prague/output @@ -1,5 +1,103 @@ ======= strict_asm_eof_container_prague/input.yul (EVM) ======= +Pretty printed source: +object "object" { + code { { revert(0, 0) } } + object "sub0" { + code { + { + mstore(0, 0) + revert(0, 32) + } + } + } + object "sub1" { + code { + { + mstore(0, 1) + revert(0, 32) + } + } + } + object "sub2" { + code { + { + mstore(0, 2) + revert(0, 32) + } + } + object "sub20" { + code { + { + mstore(0, 0x20) + revert(0, 32) + } + } + } + } + object "sub3" { + code { + { + mstore(0, 3) + revert(0, 32) + } + } + } +} + + Binary representation: ef00010100040200010003030004001a001b003b001b040000000080ffff5f80fdef00010100040200010007040000000080ffff5f805260205ffdef00010100040200010008040000000080ffff60015f5260205ffdef00010100040200010008030001001b040000000080ffff60025f5260205ffdef00010100040200010008040000000080ffff60205f5260205ffdef00010100040200010008040000000080ffff60035f5260205ffd + +Text representation: + 0x00 + dup1 + revert +stop + +sub_0: assembly { + 0x00 + dup1 + mstore + 0x20 + 0x00 + revert +} + +sub_1: assembly { + 0x01 + 0x00 + mstore + 0x20 + 0x00 + revert +} + +sub_2: assembly { + 0x02 + 0x00 + mstore + 0x20 + 0x00 + revert + stop + + sub_0: assembly { + 0x20 + 0x00 + mstore + 0x20 + 0x00 + revert + } +} + +sub_3: assembly { + 0x03 + 0x00 + mstore + 0x20 + 0x00 + revert +} From cffc4f86382de5d611bf81cc50dee1ce2199b93f Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 25 Sep 2024 15:33:22 +0200 Subject: [PATCH 0351/1340] Add missing ASAN runtime libraries --- scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang index c6b1fd970..21092e312 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="1" +LABEL version="2" ARG DEBIAN_FRONTEND=noninteractive @@ -40,13 +40,14 @@ RUN set -ex; \ clang \ cmake \ jq \ - lsof \ libboost-filesystem-dev \ libboost-program-options-dev \ libboost-system-dev \ libboost-test-dev \ + libclang-rt-dev \ libcln-dev \ libz3-static-dev \ + lsof \ ninja-build \ python3-pip \ software-properties-common \ From 4627827a44745406cc67e0a50916f918eadb552a Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 25 Sep 2024 16:40:02 +0200 Subject: [PATCH 0352/1340] Bump ubuntu 24.04 clang image --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 18ca18f3c..9afaa735f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,8 +17,8 @@ parameters: default: "solbuildpackpusher/solidity-buildpack-deps@sha256:5d6d27551104321a30326d6024bd4e96d9d899a97a78eb9feea364996f1d18b5" ubuntu-2404-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-1 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:8df0086907cc1e57068ad48841f2284a87bfbd0a95006286a19a7132d84bb861" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-2 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:bc99a858ba18e088c1cb889ce631e3e707bb3348f0ae452bfe69116dbb931173" ubuntu-clang-ossfuzz-docker-image: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-6 From b7051362eeb816eca7dcf6d633b420663555cf65 Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 25 Sep 2024 14:04:26 +0200 Subject: [PATCH 0353/1340] Do not treat all warnings as errors when building with sanitizers. --- .circleci/config.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 18ca18f3c..a71418833 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1005,7 +1005,11 @@ jobs: <<: *base_ubuntu2404 environment: <<: *base_ubuntu2404_env - CMAKE_OPTIONS: -DSANITIZE=address + # NOTE: Sanitizers may alter the intermediate code, potentially causing false warnings. + # As a result, treating warnings as errors in instrumented builds can lead to build failures due to these false positives. + # Therefore, we disable pedantic builds in such cases. + # See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105562#c27 + CMAKE_OPTIONS: -DSANITIZE=address -DPEDANTIC=OFF CMAKE_BUILD_TYPE: Release steps: - build @@ -1026,7 +1030,8 @@ jobs: <<: *base_ubuntu2404_clang environment: <<: *base_ubuntu2404_clang_env - CMAKE_OPTIONS: << parameters.cmake_options >> + # NOTE: Disabled pedantic builds to avoid false positives, see b_ubu_asan for a more detailed explanation. + CMAKE_OPTIONS: -DPEDANTIC=OFF << parameters.cmake_options >> steps: - build From 5643e8ee1dd14d9f2478c5c3306bfa8c580352b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 25 Sep 2024 18:24:46 +0200 Subject: [PATCH 0354/1340] Remove a few unused YulStack imports --- libsolidity/codegen/ir/IRGenerator.cpp | 2 +- libsolidity/experimental/codegen/IRGenerator.cpp | 1 - libsolidity/experimental/codegen/IRGeneratorForStatements.cpp | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index f495d97ab..a80fb4c27 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/experimental/codegen/IRGenerator.cpp b/libsolidity/experimental/codegen/IRGenerator.cpp index 40deb38c3..60a93bbf0 100644 --- a/libsolidity/experimental/codegen/IRGenerator.cpp +++ b/libsolidity/experimental/codegen/IRGenerator.cpp @@ -27,7 +27,6 @@ #include -#include #include #include #include diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index 6925a434d..772e8575d 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -25,9 +25,9 @@ #include -#include #include #include +#include #include #include From 372dab41c5dcf1087efa767f4b1ecd2ba3f2fb6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 25 Sep 2024 18:26:22 +0200 Subject: [PATCH 0355/1340] Store a reference to a Solidity source provider in YulStack --- libsolidity/interface/CompilerStack.cpp | 4 +++- libyul/YulStack.cpp | 16 +++++++++++----- libyul/YulStack.h | 11 ++++++++--- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index e538823f1..9848b6b59 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1522,6 +1522,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti YulStack::Language::StrictAssembly, m_optimiserSettings, m_debugInfoSelection, + this, // _soliditySourceProvider m_objectOptimizer ); bool yulAnalysisSuccessful = stack.parseAndAnalyze("", compiledContract.yulIR); @@ -1537,7 +1538,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti if (!_unoptimizedOnly) { stack.optimize(); - compiledContract.yulIROptimized = stack.print(this); + compiledContract.yulIROptimized = stack.print(); compiledContract.yulIROptimizedAst = stack.astJson(); } } @@ -1561,6 +1562,7 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) yul::YulStack::Language::StrictAssembly, m_optimiserSettings, m_debugInfoSelection, + this, // _soliditySourceProvider m_objectOptimizer ); bool analysisSuccessful = stack.parseAndAnalyze("", compiledContract.yulIROptimized); diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 59766220c..f060a1e33 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -216,7 +216,15 @@ void YulStack::reparse() // are not stored in the AST and the other info that is (location, AST ID, etc) will still be present. std::string source = print(nullptr /* _soliditySourceProvider */); - YulStack cleanStack(m_evmVersion, m_eofVersion, m_language, m_optimiserSettings, m_debugInfoSelection, m_objectOptimizer); + YulStack cleanStack( + m_evmVersion, + m_eofVersion, + m_language, + m_optimiserSettings, + m_debugInfoSelection, + m_soliditySourceProvider, + m_objectOptimizer + ); bool reanalysisSuccessful = cleanStack.parseAndAnalyze(m_charStream->name(), source); yulAssert( reanalysisSuccessful, @@ -348,16 +356,14 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) return {std::make_shared(assembly), {}}; } -std::string YulStack::print( - CharStreamProvider const* _soliditySourceProvider -) const +std::string YulStack::print() const { yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->hasCode(), ""); return m_parserResult->toString( m_debugInfoSelection, - _soliditySourceProvider + m_soliditySourceProvider ) + "\n"; } diff --git a/libyul/YulStack.h b/libyul/YulStack.h index 0dc90baf8..de391f591 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -90,6 +90,7 @@ class YulStack: public langutil::CharStreamProvider Language _language, solidity::frontend::OptimiserSettings _optimiserSettings, langutil::DebugInfoSelection const& _debugInfoSelection, + langutil::CharStreamProvider const* _soliditySourceProvider = nullptr, std::shared_ptr _objectOptimizer = nullptr ): m_language(_language), @@ -97,6 +98,7 @@ class YulStack: public langutil::CharStreamProvider m_eofVersion(_eofVersion), m_optimiserSettings(std::move(_optimiserSettings)), m_debugInfoSelection(_debugInfoSelection), + m_soliditySourceProvider(_soliditySourceProvider), m_errorReporter(m_errors), m_objectOptimizer(_objectOptimizer ? std::move(_objectOptimizer) : std::make_shared()) {} @@ -137,9 +139,7 @@ class YulStack: public langutil::CharStreamProvider bool hasErrors() const { return m_errorReporter.hasErrors(); } /// Pretty-print the input after having parsed it. - std::string print( - langutil::CharStreamProvider const* _soliditySourceProvider = nullptr - ) const; + std::string print() const; Json astJson() const; // return the JSON representation of the YuL CFG (experimental) @@ -172,6 +172,11 @@ class YulStack: public langutil::CharStreamProvider solidity::frontend::OptimiserSettings m_optimiserSettings; langutil::DebugInfoSelection m_debugInfoSelection{}; + /// Provider of the Solidity sources that the Yul code was generated from. + /// Necessary when code snippets are requested as a part of debug info. When null, code snippets are omitted. + /// NOTE: Not owned by YulStack, the user must ensure that it is not destroyed before the stack is. + langutil::CharStreamProvider const* m_soliditySourceProvider{}; + std::unique_ptr m_charStream; State m_stackState = Empty; From 4216aa72df0ef1a6a1b9a20d72b6dd1b6078e931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 25 Sep 2024 18:40:39 +0200 Subject: [PATCH 0356/1340] Fix shifted native source locations in Yul AST in presence of code snippets --- Changelog.md | 2 + libyul/YulStack.cpp | 8 +- test/cmdlineTests/ast_ir/output | 92 ++++++------ .../output.json | 142 +++++++++--------- 4 files changed, 123 insertions(+), 121 deletions(-) diff --git a/Changelog.md b/Changelog.md index 9f531daea..45ec293a1 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,8 @@ Compiler Features: Bugfixes: * SMTChecker: Fix SMT logic error when assigning to an array of addresses. + * Yul AST: Fix shifted native source locations when debug info selection included code snippets. + ### 0.8.27 (2024-09-04) diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index f060a1e33..67bc6d11a 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -211,10 +211,10 @@ void YulStack::reparse() yulAssert(m_parserResult); yulAssert(m_charStream); - // NOTE: Without passing in _soliditySourceProvider, printed debug info will not include code - // snippets, but it does not matter - we'll still get the same AST after we parse it. Snippets - // are not stored in the AST and the other info that is (location, AST ID, etc) will still be present. - std::string source = print(nullptr /* _soliditySourceProvider */); + // NOTE: it is important for the source printed here to exactly match what the compiler will + // eventually output to the user. In particular, debug info must be exactly the same. + // Otherwise source locations will be off. + std::string source = print(); YulStack cleanStack( m_evmVersion, diff --git a/test/cmdlineTests/ast_ir/output b/test/cmdlineTests/ast_ir/output index 3211ef49b..76f111990 100644 --- a/test/cmdlineTests/ast_ir/output +++ b/test/cmdlineTests/ast_ir/output @@ -637,24 +637,24 @@ Optimized IR AST: { "code": { "block": { - "nativeSrc": "58:298:0", + "nativeSrc": "58:315:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "68:282:0", + "nativeSrc": "68:299:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "111:27:0", + "nativeSrc": "128:27:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "133:4:0", + "nativeSrc": "150:4:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -663,18 +663,18 @@ Optimized IR AST: ], "functionName": { "name": "memoryguard", - "nativeSrc": "121:11:0", + "nativeSrc": "138:11:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "121:17:0", + "nativeSrc": "138:17:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variables": [ { "name": "_1", - "nativeSrc": "115:2:0", + "nativeSrc": "132:2:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -686,7 +686,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "158:2:0", + "nativeSrc": "175:2:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -694,28 +694,28 @@ Optimized IR AST: }, { "name": "_1", - "nativeSrc": "162:2:0", + "nativeSrc": "179:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "151:6:0", + "nativeSrc": "168:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "151:14:0", + "nativeSrc": "168:14:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "151:14:0", + "nativeSrc": "168:14:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, { "body": { - "nativeSrc": "193:16:0", + "nativeSrc": "210:16:0", "nodeType": "YulBlock", "src": "60:13:0", "statements": [ @@ -724,7 +724,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "202:1:0", + "nativeSrc": "219:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -732,7 +732,7 @@ Optimized IR AST: }, { "kind": "number", - "nativeSrc": "205:1:0", + "nativeSrc": "222:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -741,15 +741,15 @@ Optimized IR AST: ], "functionName": { "name": "revert", - "nativeSrc": "195:6:0", + "nativeSrc": "212:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "195:12:0", + "nativeSrc": "212:12:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "195:12:0", + "nativeSrc": "212:12:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } @@ -759,20 +759,20 @@ Optimized IR AST: "arguments": [], "functionName": { "name": "callvalue", - "nativeSrc": "181:9:0", + "nativeSrc": "198:9:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "181:11:0", + "nativeSrc": "198:11:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "178:31:0", + "nativeSrc": "195:31:0", "nodeType": "YulIf", "src": "60:13:0" }, { - "nativeSrc": "222:34:0", + "nativeSrc": "239:34:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", "value": { @@ -780,7 +780,7 @@ Optimized IR AST: { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "241:14:0", + "nativeSrc": "258:14:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -789,18 +789,18 @@ Optimized IR AST: ], "functionName": { "name": "datasize", - "nativeSrc": "232:8:0", + "nativeSrc": "249:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "232:24:0", + "nativeSrc": "249:24:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variables": [ { "name": "_2", - "nativeSrc": "226:2:0", + "nativeSrc": "243:2:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -812,7 +812,7 @@ Optimized IR AST: "arguments": [ { "name": "_1", - "nativeSrc": "278:2:0", + "nativeSrc": "295:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, @@ -821,7 +821,7 @@ Optimized IR AST: { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "293:14:0", + "nativeSrc": "310:14:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -830,32 +830,32 @@ Optimized IR AST: ], "functionName": { "name": "dataoffset", - "nativeSrc": "282:10:0", + "nativeSrc": "299:10:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "282:26:0", + "nativeSrc": "299:26:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, { "name": "_2", - "nativeSrc": "310:2:0", + "nativeSrc": "327:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "codecopy", - "nativeSrc": "269:8:0", + "nativeSrc": "286:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "269:44:0", + "nativeSrc": "286:44:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "269:44:0", + "nativeSrc": "286:44:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, @@ -864,28 +864,28 @@ Optimized IR AST: "arguments": [ { "name": "_1", - "nativeSrc": "333:2:0", + "nativeSrc": "350:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, { "name": "_2", - "nativeSrc": "337:2:0", + "nativeSrc": "354:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "return", - "nativeSrc": "326:6:0", + "nativeSrc": "343:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "326:14:0", + "nativeSrc": "343:14:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "326:14:0", + "nativeSrc": "343:14:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } @@ -901,12 +901,12 @@ Optimized IR AST: { "code": { "block": { - "nativeSrc": "436:101:0", + "nativeSrc": "453:118:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "450:77:0", + "nativeSrc": "467:94:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -915,7 +915,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "508:1:0", + "nativeSrc": "542:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -923,7 +923,7 @@ Optimized IR AST: }, { "kind": "number", - "nativeSrc": "511:1:0", + "nativeSrc": "545:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -932,15 +932,15 @@ Optimized IR AST: ], "functionName": { "name": "revert", - "nativeSrc": "501:6:0", + "nativeSrc": "535:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "501:12:0", + "nativeSrc": "535:12:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "501:12:0", + "nativeSrc": "535:12:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } diff --git a/test/cmdlineTests/standard_irOptimized_ast_requested/output.json b/test/cmdlineTests/standard_irOptimized_ast_requested/output.json index f80f4466c..5c6762ac9 100644 --- a/test/cmdlineTests/standard_irOptimized_ast_requested/output.json +++ b/test/cmdlineTests/standard_irOptimized_ast_requested/output.json @@ -5,12 +5,12 @@ "irOptimizedAst": { "code": { "block": { - "nativeSrc": "43:622:0", + "nativeSrc": "43:639:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "53:404:0", + "nativeSrc": "53:421:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -19,7 +19,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "103:2:0", + "nativeSrc": "120:2:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -29,7 +29,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "119:4:0", + "nativeSrc": "136:4:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -38,32 +38,32 @@ ], "functionName": { "name": "memoryguard", - "nativeSrc": "107:11:0", + "nativeSrc": "124:11:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "107:17:0", + "nativeSrc": "124:17:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "96:6:0", + "nativeSrc": "113:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "96:29:0", + "nativeSrc": "113:29:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "96:29:0", + "nativeSrc": "113:29:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" }, { "body": { - "nativeSrc": "165:111:0", + "nativeSrc": "182:111:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ @@ -72,15 +72,15 @@ "arguments": [], "functionName": { "name": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "nativeSrc": "183:77:0", + "nativeSrc": "200:77:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "183:79:0", + "nativeSrc": "200:79:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "183:79:0", + "nativeSrc": "200:79:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } @@ -90,38 +90,38 @@ "arguments": [], "functionName": { "name": "callvalue", - "nativeSrc": "141:9:0", + "nativeSrc": "158:9:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "141:11:0", + "nativeSrc": "158:11:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "138:138:0", + "nativeSrc": "155:138:0", "nodeType": "YulIf", "src": "56:13:0" }, { - "nativeSrc": "289:30:0", + "nativeSrc": "306:30:0", "nodeType": "YulVariableDeclaration", "src": "56:13:0", "value": { "arguments": [], "functionName": { "name": "allocate_unbounded", - "nativeSrc": "299:18:0", + "nativeSrc": "316:18:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "299:20:0", + "nativeSrc": "316:20:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, "variables": [ { "name": "_1", - "nativeSrc": "293:2:0", + "nativeSrc": "310:2:0", "nodeType": "YulTypedName", "src": "56:13:0", "type": "" @@ -133,7 +133,7 @@ "arguments": [ { "name": "_1", - "nativeSrc": "341:2:0", + "nativeSrc": "358:2:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, @@ -142,7 +142,7 @@ { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "356:14:0", + "nativeSrc": "373:14:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -151,11 +151,11 @@ ], "functionName": { "name": "dataoffset", - "nativeSrc": "345:10:0", + "nativeSrc": "362:10:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "345:26:0", + "nativeSrc": "362:26:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, @@ -164,7 +164,7 @@ { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "382:14:0", + "nativeSrc": "399:14:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -173,26 +173,26 @@ ], "functionName": { "name": "datasize", - "nativeSrc": "373:8:0", + "nativeSrc": "390:8:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "373:24:0", + "nativeSrc": "390:24:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "codecopy", - "nativeSrc": "332:8:0", + "nativeSrc": "349:8:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "332:66:0", + "nativeSrc": "349:66:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "332:66:0", + "nativeSrc": "349:66:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" }, @@ -201,7 +201,7 @@ "arguments": [ { "name": "_1", - "nativeSrc": "418:2:0", + "nativeSrc": "435:2:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, @@ -210,7 +210,7 @@ { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "431:14:0", + "nativeSrc": "448:14:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -219,26 +219,26 @@ ], "functionName": { "name": "datasize", - "nativeSrc": "422:8:0", + "nativeSrc": "439:8:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "422:24:0", + "nativeSrc": "439:24:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "return", - "nativeSrc": "411:6:0", + "nativeSrc": "428:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "411:36:0", + "nativeSrc": "428:36:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "411:36:0", + "nativeSrc": "428:36:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } @@ -246,19 +246,19 @@ }, { "body": { - "nativeSrc": "514:23:0", + "nativeSrc": "531:23:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ { - "nativeSrc": "516:19:0", + "nativeSrc": "533:19:0", "nodeType": "YulAssignment", "src": "56:13:0", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "532:2:0", + "nativeSrc": "549:2:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -267,18 +267,18 @@ ], "functionName": { "name": "mload", - "nativeSrc": "526:5:0", + "nativeSrc": "543:5:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "526:9:0", + "nativeSrc": "543:9:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, "variableNames": [ { "name": "memPtr", - "nativeSrc": "516:6:0", + "nativeSrc": "533:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" } @@ -287,12 +287,12 @@ ] }, "name": "allocate_unbounded", - "nativeSrc": "466:71:0", + "nativeSrc": "483:71:0", "nodeType": "YulFunctionDefinition", "returnVariables": [ { "name": "memPtr", - "nativeSrc": "499:6:0", + "nativeSrc": "516:6:0", "nodeType": "YulTypedName", "src": "56:13:0", "type": "" @@ -302,7 +302,7 @@ }, { "body": { - "nativeSrc": "643:16:0", + "nativeSrc": "660:16:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ @@ -311,7 +311,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "652:1:0", + "nativeSrc": "669:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -319,7 +319,7 @@ }, { "kind": "number", - "nativeSrc": "655:1:0", + "nativeSrc": "672:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -328,22 +328,22 @@ ], "functionName": { "name": "revert", - "nativeSrc": "645:6:0", + "nativeSrc": "662:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "645:12:0", + "nativeSrc": "662:12:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "645:12:0", + "nativeSrc": "662:12:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } ] }, "name": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "nativeSrc": "546:113:0", + "nativeSrc": "563:113:0", "nodeType": "YulFunctionDefinition", "src": "56:13:0" } @@ -357,12 +357,12 @@ { "code": { "block": { - "nativeSrc": "730:344:0", + "nativeSrc": "747:361:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "744:190:0", + "nativeSrc": "761:207:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -371,7 +371,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "802:2:0", + "nativeSrc": "836:2:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -381,7 +381,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "818:4:0", + "nativeSrc": "852:4:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -390,26 +390,26 @@ ], "functionName": { "name": "memoryguard", - "nativeSrc": "806:11:0", + "nativeSrc": "840:11:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "806:17:0", + "nativeSrc": "840:17:0", "nodeType": "YulFunctionCall", "src": "56:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "795:6:0", + "nativeSrc": "829:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "795:29:0", + "nativeSrc": "829:29:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "795:29:0", + "nativeSrc": "829:29:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" }, @@ -418,15 +418,15 @@ "arguments": [], "functionName": { "name": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", - "nativeSrc": "841:77:0", + "nativeSrc": "875:77:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "841:79:0", + "nativeSrc": "875:79:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "841:79:0", + "nativeSrc": "875:79:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } @@ -434,7 +434,7 @@ }, { "body": { - "nativeSrc": "1048:16:0", + "nativeSrc": "1082:16:0", "nodeType": "YulBlock", "src": "56:13:0", "statements": [ @@ -443,7 +443,7 @@ "arguments": [ { "kind": "number", - "nativeSrc": "1057:1:0", + "nativeSrc": "1091:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -451,7 +451,7 @@ }, { "kind": "number", - "nativeSrc": "1060:1:0", + "nativeSrc": "1094:1:0", "nodeType": "YulLiteral", "src": "56:13:0", "type": "", @@ -460,22 +460,22 @@ ], "functionName": { "name": "revert", - "nativeSrc": "1050:6:0", + "nativeSrc": "1084:6:0", "nodeType": "YulIdentifier", "src": "56:13:0" }, - "nativeSrc": "1050:12:0", + "nativeSrc": "1084:12:0", "nodeType": "YulFunctionCall", "src": "56:13:0" }, - "nativeSrc": "1050:12:0", + "nativeSrc": "1084:12:0", "nodeType": "YulExpressionStatement", "src": "56:13:0" } ] }, "name": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", - "nativeSrc": "947:117:0", + "nativeSrc": "981:117:0", "nodeType": "YulFunctionDefinition", "src": "56:13:0" } From 578e1bb850a5a339ab7ada50022b8dd2388204cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 24 Sep 2024 14:53:45 +0200 Subject: [PATCH 0357/1340] CompilerStack: Helper for Yul parsing --- libsolidity/interface/CompilerStack.cpp | 52 ++++++++++++------------- libsolidity/interface/CompilerStack.h | 10 +++++ 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 9848b6b59..deb748fbe 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -782,6 +782,28 @@ void CompilerStack::link() } } +YulStack CompilerStack::loadGeneratedIR(std::string const& _ir) const +{ + YulStack stack( + m_evmVersion, + m_eofVersion, + YulStack::Language::StrictAssembly, + m_optimiserSettings, + m_debugInfoSelection, + this, // _soliditySourceProvider + m_objectOptimizer + ); + bool yulAnalysisSuccessful = stack.parseAndAnalyze("", _ir); + solAssert( + yulAnalysisSuccessful, + _ir + "\n\n" + "Invalid IR generated:\n" + + SourceReferenceFormatter::formatErrorInformation(stack.errors(), stack) + "\n" + ); + + return stack; +} + std::vector CompilerStack::contractNames() const { solAssert(m_stackState >= Parsed, "Parsing was not successful."); @@ -1516,23 +1538,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti ); } - YulStack stack( - m_evmVersion, - m_eofVersion, - YulStack::Language::StrictAssembly, - m_optimiserSettings, - m_debugInfoSelection, - this, // _soliditySourceProvider - m_objectOptimizer - ); - bool yulAnalysisSuccessful = stack.parseAndAnalyze("", compiledContract.yulIR); - solAssert( - yulAnalysisSuccessful, - compiledContract.yulIR + "\n\n" - "Invalid IR generated:\n" + - SourceReferenceFormatter::formatErrorInformation(stack.errors(), stack) + "\n" - ); - + YulStack stack = loadGeneratedIR(compiledContract.yulIR); compiledContract.yulIRAst = stack.astJson(); compiledContract.yulCFGJson = stack.cfgJson(); if (!_unoptimizedOnly) @@ -1556,17 +1562,7 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) return; // Re-parse the Yul IR in EVM dialect - yul::YulStack stack( - m_evmVersion, - m_eofVersion, - yul::YulStack::Language::StrictAssembly, - m_optimiserSettings, - m_debugInfoSelection, - this, // _soliditySourceProvider - m_objectOptimizer - ); - bool analysisSuccessful = stack.parseAndAnalyze("", compiledContract.yulIROptimized); - solAssert(analysisSuccessful); + YulStack stack = loadGeneratedIR(compiledContract.yulIROptimized); //cout << yul::AsmPrinter{}(*stack.parserResult()->code) << endl; diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 0a62cbf7e..885438475 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -71,6 +71,11 @@ class AssemblyItem; using AssemblyItems = std::vector; } +namespace solidity::yul +{ +class YulStack; +} + namespace solidity::frontend { @@ -490,6 +495,11 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// library will still be kept as an unlinked placeholder in the objects. void link(); + /// Parses and analyzes specified Yul source and returns the YulStack that can be used to manipulate it. + /// Assumes that the IR was generated from sources loaded currently into CompilerStack, which + /// means that it is error-free and uses the same settings. + yul::YulStack loadGeneratedIR(std::string const& _ir) const; + /// @returns the contract object for the given @a _contractName. /// Can only be called after state is CompilationSuccessful. Contract const& contract(std::string const& _contractName) const; From 9ccc44a9bac77aa0c75944bd93d57a1ea66d5a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 24 Sep 2024 15:19:02 +0200 Subject: [PATCH 0358/1340] CompilerStack: Yul AST generation only on demand - The JSON artifacts take a lot of memory so always generating them is very wasteful. - Even when requested, they are only relevant while the current contract is being copmiled. We only really want to store the serialized JSON that will be returned to the user. - This actually also speeds up compilation quite a bit. --- Changelog.md | 1 + libsolidity/interface/CompilerStack.cpp | 27 ++++++++++++++----------- libsolidity/interface/CompilerStack.h | 9 +++------ 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Changelog.md b/Changelog.md index 45ec293a1..7d9af1cdb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: * Code Generator: Transient storage value type state variables are now supported by the legacy pipeline. + * General: Generate JSON representations of Yul ASTs only on demand to reduce memory usage. Bugfixes: diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index deb748fbe..bac358a93 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -956,21 +956,24 @@ std::string const& CompilerStack::yulIR(std::string const& _contractName) const return contract(_contractName).yulIR; } -Json const& CompilerStack::yulIRAst(std::string const& _contractName) const +Json CompilerStack::yulIRAst(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); - return contract(_contractName).yulIRAst; + + // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to + // keep it around when compiling a large project containing many contracts. + return loadGeneratedIR(contract(_contractName).yulIR).astJson(); } -Json const& CompilerStack::yulCFGJson(std::string const& _contractName) const +Json CompilerStack::yulCFGJson(std::string const& _contractName) const { - if (m_stackState != CompilationSuccessful) - solThrow(CompilerError, "Compilation was not successful."); - + solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); - return contract(_contractName).yulCFGJson; + // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to + // keep it around when compiling a large project containing many contracts. + return loadGeneratedIR(contract(_contractName).yulIR).cfgJson(); } std::string const& CompilerStack::yulIROptimized(std::string const& _contractName) const @@ -979,11 +982,14 @@ std::string const& CompilerStack::yulIROptimized(std::string const& _contractNam return contract(_contractName).yulIROptimized; } -Json const& CompilerStack::yulIROptimizedAst(std::string const& _contractName) const +Json CompilerStack::yulIROptimizedAst(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); - return contract(_contractName).yulIROptimizedAst; + + // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to + // keep it around when compiling a large project containing many contracts. + return loadGeneratedIR(contract(_contractName).yulIROptimized).astJson(); } evmasm::LinkerObject const& CompilerStack::object(std::string const& _contractName) const @@ -1539,13 +1545,10 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti } YulStack stack = loadGeneratedIR(compiledContract.yulIR); - compiledContract.yulIRAst = stack.astJson(); - compiledContract.yulCFGJson = stack.cfgJson(); if (!_unoptimizedOnly) { stack.optimize(); compiledContract.yulIROptimized = stack.print(); - compiledContract.yulIROptimizedAst = stack.astJson(); } } diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 885438475..c0166af96 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -295,15 +295,15 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac std::string const& yulIR(std::string const& _contractName) const; /// @returns the IR representation of a contract AST in format. - Json const& yulIRAst(std::string const& _contractName) const; + Json yulIRAst(std::string const& _contractName) const; /// @returns the optimized IR representation of a contract. std::string const& yulIROptimized(std::string const& _contractName) const; /// @returns the optimized IR representation of a contract AST in JSON format. - Json const& yulIROptimizedAst(std::string const& _contractName) const; + Json yulIROptimizedAst(std::string const& _contractName) const; - Json const& yulCFGJson(std::string const& _contractName) const; + Json yulCFGJson(std::string const& _contractName) const; /// @returns the assembled object for a contract. virtual evmasm::LinkerObject const& object(std::string const& _contractName) const override; @@ -416,9 +416,6 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac evmasm::LinkerObject runtimeObject; ///< Runtime object. std::string yulIR; ///< Yul IR code straight from the code generator. std::string yulIROptimized; ///< Reparsed and possibly optimized Yul IR code. - Json yulIRAst; ///< JSON AST of Yul IR code. - Json yulIROptimizedAst; ///< JSON AST of optimized Yul IR code. - Json yulCFGJson; ///< JSON CFG of Yul IR code. util::LazyInit metadata; ///< The metadata json that will be hashed into the chain. util::LazyInit abi; util::LazyInit storageLayout; From 5cbfd0d1985aab589c8501998a4459c79e42171d Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 22 Jul 2024 12:43:17 +0200 Subject: [PATCH 0359/1340] Via-IR code-gen for transient state variables Alternative approach Set variable declaration location explicitly --- libsolidity/codegen/ABIFunctions.cpp | 2 +- libsolidity/codegen/LValue.cpp | 2 +- libsolidity/codegen/YulUtilFunctions.cpp | 94 +++++++++++++------ libsolidity/codegen/YulUtilFunctions.h | 26 ++++- libsolidity/codegen/ir/IRGenerator.cpp | 15 +-- .../codegen/ir/IRGeneratorForStatements.cpp | 70 +++++++++++--- .../codegen/ir/IRGeneratorForStatements.h | 1 + libsolidity/codegen/ir/IRLValue.h | 6 +- 8 files changed, 153 insertions(+), 63 deletions(-) diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index bbcdb395b..474848760 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -616,7 +616,7 @@ std::string ABIFunctions::abiEncodingFunctionSimpleArray( break; case DataLocation::Storage: if (_from.baseType()->isValueType()) - templ("arrayElementAccess", m_utils.readFromStorage(*_from.baseType(), 0, false) + "(srcPtr)"); + templ("arrayElementAccess", m_utils.readFromStorage(*_from.baseType(), 0, false, VariableDeclaration::Location::Unspecified) + "(srcPtr)"); else templ("arrayElementAccess", "srcPtr"); break; diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 78efb9f81..a1537f01f 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -401,7 +401,7 @@ void GenericStorageItem::storeValue(Type const& _sourceType, langut solAssert(sourceType.sizeOnStack() == 1, ""); solAssert(structType.sizeOnStack() == 1, ""); m_context << Instruction::DUP2 << Instruction::DUP2; - m_context.callYulFunction(m_context.utilFunctions().updateStorageValueFunction(sourceType, structType, 0), 2, 0); + m_context.callYulFunction(m_context.utilFunctions().updateStorageValueFunction(sourceType, structType, VariableDeclaration::Location::Unspecified, 0), 2, 0); } else { diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index ebf1d384a..fc6de832b 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -1646,7 +1646,7 @@ std::string YulUtilFunctions::storageArrayPopFunction(ArrayType const& _type) ("indexAccess", storageArrayIndexAccessFunction(_type)) ( "setToZero", - _type.baseType()->category() != Type::Category::Mapping ? storageSetToZeroFunction(*_type.baseType()) : "" + _type.baseType()->category() != Type::Category::Mapping ? storageSetToZeroFunction(*_type.baseType(), VariableDeclaration::Location::Unspecified) : "" ) .render(); }); @@ -1691,7 +1691,7 @@ std::string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type ("transitLongToShort", byteArrayTransitLongToShortFunction(_type)) ("encodeUsedSetLen", shortByteArrayEncodeUsedAreaSetLengthFunction()) ("indexAccessNoChecks", longByteArrayStorageIndexAccessNoCheckFunction()) - ("setToZero", storageSetToZeroFunction(*_type.baseType())) + ("setToZero", storageSetToZeroFunction(*_type.baseType(), VariableDeclaration::Location::Unspecified)) .render(); }); } @@ -1760,7 +1760,7 @@ std::string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type, T ("dataAreaFunction", arrayDataAreaFunction(_type)) ("isByteArrayOrString", _type.isByteArrayOrString()) ("indexAccess", storageArrayIndexAccessFunction(_type)) - ("storeValue", updateStorageValueFunction(*_fromType, *_type.baseType())) + ("storeValue", updateStorageValueFunction(*_fromType, *_type.baseType(), VariableDeclaration::Location::Unspecified)) ("maxArrayLength", (u256(1) << 64).str()) ("shl", shiftLeftFunctionDynamic()) .render(); @@ -1834,7 +1834,7 @@ std::string YulUtilFunctions::clearStorageRangeFunction(Type const& _type) } )") ("functionName", functionName) - ("setToZero", storageSetToZeroFunction(_type.storageBytes() < 32 ? *TypeProvider::uint256() : _type)) + ("setToZero", storageSetToZeroFunction(_type.storageBytes() < 32 ? *TypeProvider::uint256() : _type, VariableDeclaration::Location::Unspecified)) ("increment", _type.storageSize().str()) .render(); }); @@ -1912,7 +1912,7 @@ std::string YulUtilFunctions::clearStorageStructFunction(StructType const& _type memberSetValues.emplace_back().emplace("clearMember", Whiskers(R"( (add(slot, ), ) )") - ("setZero", storageSetToZeroFunction(*member.type)) + ("setZero", storageSetToZeroFunction(*member.type, VariableDeclaration::Location::Unspecified)) ("memberSlotDiff", memberSlotDiff.str()) ("memberStorageOffset", std::to_string(memberStorageOffset)) .render() @@ -2015,7 +2015,7 @@ std::string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromT 0, _fromType.baseType()->stackItems().size() )); - templ("updateStorageValue", updateStorageValueFunction(*_fromType.baseType(), *_toType.baseType(), 0)); + templ("updateStorageValue", updateStorageValueFunction(*_fromType.baseType(), *_toType.baseType(), VariableDeclaration::Location::Unspecified, 0)); templ("srcStride", fromCalldata ? std::to_string(_fromType.calldataStride()) : @@ -2746,21 +2746,33 @@ std::string YulUtilFunctions::mappingIndexAccessFunction(MappingType const& _map }); } -std::string YulUtilFunctions::readFromStorage(Type const& _type, size_t _offset, bool _splitFunctionTypes) +std::string YulUtilFunctions::readFromStorage( + Type const& _type, + size_t _offset, + bool _splitFunctionTypes, + VariableDeclaration::Location _location +) { if (_type.isValueType()) - return readFromStorageValueType(_type, _offset, _splitFunctionTypes); + return readFromStorageValueType(_type, _offset, _splitFunctionTypes, _location); else { + solAssert(_location != VariableDeclaration::Location::Transient); solAssert(_offset == 0, ""); return readFromStorageReferenceType(_type); } } -std::string YulUtilFunctions::readFromStorageDynamic(Type const& _type, bool _splitFunctionTypes) +std::string YulUtilFunctions::readFromStorageDynamic( + Type const& _type, + bool _splitFunctionTypes, + VariableDeclaration::Location _location +) { if (_type.isValueType()) - return readFromStorageValueType(_type, {}, _splitFunctionTypes); + return readFromStorageValueType(_type, {}, _splitFunctionTypes, _location); + + solAssert(_location != VariableDeclaration::Location::Transient); std::string functionName = "read_from_storage__dynamic_" + std::string(_splitFunctionTypes ? "split_" : "") + @@ -2780,24 +2792,36 @@ std::string YulUtilFunctions::readFromStorageDynamic(Type const& _type, bool _sp }); } -std::string YulUtilFunctions::readFromStorageValueType(Type const& _type, std::optional _offset, bool _splitFunctionTypes) +std::string YulUtilFunctions::readFromStorageValueType( + Type const& _type, + std::optional _offset, + bool _splitFunctionTypes, + VariableDeclaration::Location _location +) { solAssert(_type.isValueType(), ""); + solAssert( + _location == VariableDeclaration::Location::Transient || + _location == VariableDeclaration::Location::Unspecified, + "Variable location can only be transient or plain storage" + ); std::string functionName = - "read_from_storage_" + - std::string(_splitFunctionTypes ? "split_" : "") + ( - _offset.has_value() ? - "offset_" + std::to_string(*_offset) : - "dynamic" - ) + - "_" + - _type.identifier(); + "read_from_" + + (_location == VariableDeclaration::Location::Transient ? "transient_"s : "") + + "storage_" + + std::string(_splitFunctionTypes ? "split_" : "") + ( + _offset.has_value() ? + "offset_" + std::to_string(*_offset) : + "dynamic" + ) + + "_" + + _type.identifier(); return m_functionCollector.createFunction(functionName, [&] { Whiskers templ(R"( function (slot, offset) -> addr, selectorvalue { - let value := (sload(slot), offset) + let value := ((slot), offset) addr, selector := (value) @@ -2805,6 +2829,7 @@ std::string YulUtilFunctions::readFromStorageValueType(Type const& _type, std::o )"); templ("functionName", functionName); templ("dynamic", !_offset.has_value()); + templ("loadOpcode", _location == VariableDeclaration::Location::Transient ? "tload" : "sload"); if (_offset.has_value()) templ("extract", extractFromStorageValue(_type, *_offset)); else @@ -2850,7 +2875,7 @@ std::string YulUtilFunctions::readFromStorageReferenceType(Type const& _type) ("memberValues", suffixedVariableNameList("memberValue_", 0, structMembers[i].type->stackItems().size())) ("memberMemoryOffset", structType.memoryOffsetOfMember(structMembers[i].name).str()) ("memberSlotDiff", memberSlotDiff.str()) - ("readFromStorage", readFromStorage(*structMembers[i].type, memberStorageOffset, true)) + ("readFromStorage", readFromStorage(*structMembers[i].type, memberStorageOffset, true, VariableDeclaration::Location::Unspecified)) ("writeToMemory", writeToMemoryFunction(*structMembers[i].type)) .render(); } @@ -2884,11 +2909,20 @@ std::string YulUtilFunctions::readFromCalldata(Type const& _type) std::string YulUtilFunctions::updateStorageValueFunction( Type const& _fromType, Type const& _toType, + VariableDeclaration::Location _location, std::optional const& _offset ) { + solAssert( + _location == VariableDeclaration::Location::Transient || + _location == VariableDeclaration::Location::Unspecified, + "Variable location can only be transient or plain storage" + ); + std::string const functionName = - "update_storage_value_" + + "update_" + + (_location == VariableDeclaration::Location::Transient ? "transient_"s : "") + + "storage_value_" + (_offset.has_value() ? ("offset_" + std::to_string(*_offset)) : "") + _fromType.identifier() + "_to_" + @@ -2904,7 +2938,7 @@ std::string YulUtilFunctions::updateStorageValueFunction( return Whiskers(R"( function (slot, ) { let := () - sstore(slot, (sload(slot), ())) + (slot, ((slot), ())) } )") @@ -2918,10 +2952,13 @@ std::string YulUtilFunctions::updateStorageValueFunction( ("convert", conversionFunction(_fromType, _toType)) ("fromValues", suffixedVariableNameList("value_", 0, _fromType.sizeOnStack())) ("toValues", suffixedVariableNameList("convertedValue_", 0, _toType.sizeOnStack())) + ("storeOpcode", _location == VariableDeclaration::Location::Transient ? "tstore" : "sstore") + ("loadOpcode", _location == VariableDeclaration::Location::Transient ? "tload" : "sload") ("prepare", prepareStoreFunction(_toType)) .render(); } + solAssert(_location != VariableDeclaration::Location::Transient); auto const* toReferenceType = dynamic_cast(&_toType); auto const* fromReferenceType = dynamic_cast(&_fromType); solAssert(toReferenceType, ""); @@ -3553,7 +3590,7 @@ std::string YulUtilFunctions::conversionFunction(Type const& _from, Type const& body = Whiskers(R"( converted := (value) )") - ("readFromStorage", readFromStorage(toStructType, 0, true)) + ("readFromStorage", readFromStorage(toStructType, 0, true, VariableDeclaration::Location::Unspecified)) .render(); } } @@ -3683,7 +3720,7 @@ std::string YulUtilFunctions::bytesToFixedBytesConversionFunction(ArrayType cons templ( "extractValue", _from.dataStoredIn(DataLocation::Storage) ? - readFromStorage(_to, 32 - _to.numBytes(), false) : + readFromStorage(_to, 32 - _to.numBytes(), false, VariableDeclaration::Location::Unspecified) : readFromMemory(_to) ); templ("shl", shiftLeftFunctionDynamic()); @@ -3787,7 +3824,7 @@ std::string YulUtilFunctions::copyStructToStorageFunction(StructType const& _fro auto const& [srcSlotOffset, srcOffset] = _from.storageOffsetsOfMember(structMembers[i].name); t("memberOffset", formatNumber(srcSlotOffset)); if (memberType.isValueType()) - t("read", readFromStorageValueType(memberType, srcOffset, true)); + t("read", readFromStorageValueType(memberType, srcOffset, true, VariableDeclaration::Location::Unspecified)); else solAssert(srcOffset == 0, ""); @@ -3795,6 +3832,7 @@ std::string YulUtilFunctions::copyStructToStorageFunction(StructType const& _fro t("updateStorageValue", updateStorageValueFunction( memberType, *toStructMembers[i].type, + VariableDeclaration::Location::Unspecified, std::optional{offset} )); memberParams[i]["updateMemberCall"] = t.render(); @@ -4300,7 +4338,7 @@ std::string YulUtilFunctions::zeroValueFunction(Type const& _type, bool _splitFu }); } -std::string YulUtilFunctions::storageSetToZeroFunction(Type const& _type) +std::string YulUtilFunctions::storageSetToZeroFunction(Type const& _type, VariableDeclaration::Location _location) { std::string const functionName = "storage_set_to_zero_" + _type.identifier(); @@ -4313,7 +4351,7 @@ std::string YulUtilFunctions::storageSetToZeroFunction(Type const& _type) } )") ("functionName", functionName) - ("store", updateStorageValueFunction(_type, _type)) + ("store", updateStorageValueFunction(_type, _type, _location)) ("values", suffixedVariableNameList("zero_", 0, _type.sizeOnStack())) ("zeroValue", zeroValueFunction(_type)) .render(); diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index a1b45b656..6c06cdcc9 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -349,8 +350,17 @@ class YulUtilFunctions /// @returns a function that reads a type from storage. /// @param _splitFunctionTypes if false, returns the address and function signature in a /// single variable. - std::string readFromStorage(Type const& _type, size_t _offset, bool _splitFunctionTypes); - std::string readFromStorageDynamic(Type const& _type, bool _splitFunctionTypes); + std::string readFromStorage( + Type const& _type, + size_t _offset, + bool _splitFunctionTypes, + VariableDeclaration::Location _location + ); + std::string readFromStorageDynamic( + Type const& _type, + bool _splitFunctionTypes, + VariableDeclaration::Location _location + ); /// @returns a function that reads a value type from memory. Performs cleanup. /// signature: (addr) -> value @@ -376,6 +386,7 @@ class YulUtilFunctions std::string updateStorageValueFunction( Type const& _fromType, Type const& _toType, + VariableDeclaration::Location _location, std::optional const& _offset = std::optional() ); @@ -496,7 +507,7 @@ class YulUtilFunctions /// @returns the name of a function that will set the given storage item to /// zero /// signature: (slot, offset) -> - std::string storageSetToZeroFunction(Type const& _type); + std::string storageSetToZeroFunction(Type const& _type, VariableDeclaration::Location _location); /// If revertStrings is debug, @returns the name of a function that /// stores @param _message in memory position 0 and reverts. @@ -573,8 +584,13 @@ class YulUtilFunctions /// @param _splitFunctionTypes if false, returns the address and function signature in a /// single variable. /// @param _offset if provided, read from static offset, otherwise offset is a parameter of the Yul function. - std::string readFromStorageValueType(Type const& _type, std::optional _offset, bool _splitFunctionTypes); - + /// @param _location if provided, indicates whether we're reading from storage our transient storage. + std::string readFromStorageValueType( + Type const& _type, + std::optional _offset, + bool _splitFunctionTypes, + VariableDeclaration::Location _location + ); /// @returns a function that reads a reference type from storage to memory (performing a deep copy). std::string readFromStorageReferenceType(Type const& _type); diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index a80fb4c27..44fc5a935 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -103,16 +103,6 @@ std::string IRGenerator::generate( std::map const& _otherYulSources ) { - auto notTransient = [](VariableDeclaration const* _varDeclaration) { - solAssert(_varDeclaration); - return _varDeclaration->referenceLocation() != VariableDeclaration::Location::Transient; - }; - - solUnimplementedAssert( - ranges::all_of(_contract.stateVariables(), notTransient), - "Transient storage variables are not supported when compiling via IR." - ); - auto subObjectSources = [&_otherYulSources](UniqueVector const& _subObjects) -> std::string { std::string subObjectsSources; @@ -674,7 +664,7 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) := (add(slot, )) )") ("ret", joinHumanReadable(retVars)) - ("readStorage", m_utils.readFromStorage(*returnTypes[i], offsets.second, true)) + ("readStorage", m_utils.readFromStorage(*returnTypes[i], offsets.second, true, _varDecl.referenceLocation())) ("slotOffset", offsets.first.str()) .render(); } @@ -691,7 +681,7 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) := (slot, offset) )") ("ret", joinHumanReadable(retVars)) - ("readStorage", m_utils.readFromStorageDynamic(*returnTypes.front(), true)) + ("readStorage", m_utils.readFromStorageDynamic(*returnTypes.front(), true, _varDecl.referenceLocation())) .render(); } @@ -834,7 +824,6 @@ std::string IRGenerator::initStateVariables(ContractDefinition const& _contract) IRGeneratorForStatements generator{m_context, m_utils, m_optimiserSettings}; for (VariableDeclaration const* variable: _contract.stateVariables()) { - solUnimplementedAssert(variable->referenceLocation() != VariableDeclaration::Location::Transient, "Transient storage variables not supported."); if (!variable->isConstant()) generator.initializeStateVar(*variable); } diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index c3cd69f43..283cc4b6b 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -271,6 +271,7 @@ void IRGeneratorForStatements::initializeStateVar(VariableDeclaration const& _va solAssert(!_varDecl.isConstant()); if (!_varDecl.value()) return; + solAssert(_varDecl.referenceLocation() != VariableDeclaration::Location::Transient, "State variables cannot be initialized in place."); _varDecl.value()->accept(*this); @@ -376,15 +377,6 @@ void IRGeneratorForStatements::endVisit(VariableDeclarationStatement const& _var { setLocation(_varDeclStatement); - auto static notTransient = [](std::shared_ptr const& _varDeclaration) { - return (_varDeclaration ? _varDeclaration->referenceLocation() != VariableDeclaration::Location::Transient : true); - }; - - solUnimplementedAssert( - ranges::all_of(_varDeclStatement.declarations(), notTransient), - "Transient storage variables are not supported." - ); - if (Expression const* expression = _varDeclStatement.initialValue()) { if (_varDeclStatement.declarations().size() > 1) @@ -727,7 +719,7 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation) util::GenericVisitor{ [&](IRLValue::Storage const& _storage) { appendCode() << - m_utils.storageSetToZeroFunction(m_currentLValue->type) << + m_utils.storageSetToZeroFunction(m_currentLValue->type, VariableDeclaration::Location::Unspecified) << "(" << _storage.slot << ", " << @@ -735,6 +727,16 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation) ")\n"; m_currentLValue.reset(); }, + [&](IRLValue::TransientStorage const& _transientStorage) { + appendCode() << + m_utils.storageSetToZeroFunction(m_currentLValue->type, VariableDeclaration::Location::Transient) << + "(" << + _transientStorage.slot << + ", " << + _transientStorage.offsetString() << + ")\n"; + m_currentLValue.reset(); + }, [&](auto const&) { IRVariable zeroValue(m_context.newYulVariable(), m_currentLValue->type); define(zeroValue) << m_utils.zeroValueFunction(m_currentLValue->type) << "()\n"; @@ -2558,6 +2560,14 @@ void IRGeneratorForStatements::handleVariableReference( *_variable.annotation().type, IRLValue::Stack{m_context.localVariable(_variable)} }); + else if (m_context.isStateVariable(_variable) && _variable.referenceLocation() == VariableDeclaration::Location::Transient) + setLValue(_referencingExpression, IRLValue{ + *_variable.annotation().type, + IRLValue::TransientStorage{ + toCompactHexWithPrefix(m_context.storageLocationOfStateVariable(_variable).first), + m_context.storageLocationOfStateVariable(_variable).second + } + }); else if (m_context.isStateVariable(_variable)) setLValue(_referencingExpression, IRLValue{ *_variable.annotation().type, @@ -3073,13 +3083,29 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable }, _storage.offset); appendCode() << - m_utils.updateStorageValueFunction(_value.type(), _lvalue.type, offsetStatic) << + m_utils.updateStorageValueFunction(_value.type(), _lvalue.type, VariableDeclaration::Location::Unspecified, offsetStatic) << "(" << _storage.slot << offsetArgument << _value.commaSeparatedListPrefixed() << ")\n"; + }, + [&](IRLValue::TransientStorage const& _transientStorage) { + std::string offsetArgument; + std::optional offsetStatic; + std::visit(GenericVisitor{ + [&](unsigned _offset) { offsetStatic = _offset; }, + [&](std::string const& _offset) { offsetArgument = ", " + _offset; } + }, _transientStorage.offset); + + appendCode() << + m_utils.updateStorageValueFunction(_value.type(), _lvalue.type, VariableDeclaration::Location::Transient, offsetStatic) << + "(" << + _transientStorage.slot << + offsetArgument << + _value.commaSeparatedListPrefixed() << + ")\n"; }, [&](IRLValue::Memory const& _memory) { if (_lvalue.type.isValueType()) @@ -3158,7 +3184,7 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue) define(result) << _storage.slot << "\n"; else if (std::holds_alternative(_storage.offset)) define(result) << - m_utils.readFromStorageDynamic(_lvalue.type, true) << + m_utils.readFromStorageDynamic(_lvalue.type, true, VariableDeclaration::Location::Unspecified) << "(" << _storage.slot << ", " << @@ -3166,11 +3192,29 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue) ")\n"; else define(result) << - m_utils.readFromStorage(_lvalue.type, std::get(_storage.offset), true) << + m_utils.readFromStorage(_lvalue.type, std::get(_storage.offset), true, VariableDeclaration::Location::Unspecified) << "(" << _storage.slot << ")\n"; }, + [&](IRLValue::TransientStorage const& _transientStorage) { + if (!_lvalue.type.isValueType()) + define(result) << _transientStorage.slot << "\n"; + else if (std::holds_alternative(_transientStorage.offset)) + define(result) << + m_utils.readFromStorageDynamic(_lvalue.type, true, VariableDeclaration::Location::Transient) << + "(" << + _transientStorage.slot << + ", " << + std::get(_transientStorage.offset) << + ")\n"; + else + define(result) << + m_utils.readFromStorage(_lvalue.type, std::get(_transientStorage.offset), true, VariableDeclaration::Location::Transient) << + "(" << + _transientStorage.slot << + ")\n"; + }, [&](IRLValue::Memory const& _memory) { if (_lvalue.type.isValueType()) define(result) << diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index 15ef71f13..9537b1f8f 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -228,6 +228,7 @@ class IRGeneratorForStatements: public IRGeneratorForStatementsBase /// Assigns the value of @a _value to the lvalue @a _lvalue. void writeToLValue(IRLValue const& _lvalue, IRVariable const& _value); + /// @returns a fresh IR variable containing the value of the lvalue @a _lvalue. IRVariable readFromLValue(IRLValue const& _lvalue); diff --git a/libsolidity/codegen/ir/IRLValue.h b/libsolidity/codegen/ir/IRLValue.h index fef390d4c..3f77cdda3 100644 --- a/libsolidity/codegen/ir/IRLValue.h +++ b/libsolidity/codegen/ir/IRLValue.h @@ -40,7 +40,7 @@ struct IRLValue { VariableDeclaration const* variable = nullptr; }; - struct Storage + struct GenericStorage { std::string const slot; /// unsigned: Used when the offset is known at compile time, uses optimized @@ -55,6 +55,8 @@ struct IRLValue return std::get(offset); } }; + struct Storage : public GenericStorage {}; + struct TransientStorage : public GenericStorage {}; struct Memory { std::string const address; @@ -64,7 +66,7 @@ struct IRLValue { std::vector> components; }; - std::variant kind; + std::variant kind; }; } From 0968a33d9c22f8fd673f7539f39ec2c5f925d9c8 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 13 Sep 2024 15:55:49 +0200 Subject: [PATCH 0360/1340] Update old tests --- .../err | 1 - .../exit | 1 - .../output | 131 ++++++++++++++++++ .../getters/transient_value_types.sol | 1 - ...transient_value_types_multi_frame_call.sol | 1 - ...ansient_storage_access_inside_function.sol | 1 - .../compound_assign_transient_storage.sol | 1 - ...t_storage_variable_increment_decrement.sol | 1 - .../delete_transient_state_variable.sol | 1 - ...transient_function_type_state_variable.sol | 1 - ...ansient_state_address_variable_members.sol | 1 - .../transient_state_enum_variable.sol | 1 - .../variables/transient_state_variable.sol | 1 - ...ient_state_variable_cleanup_assignment.sol | 1 - ...ransient_state_variable_cleanup_tstore.sol | 1 - ...nt_state_variable_slot_inline_assembly.sol | 1 - ...nsient_state_variable_tuple_assignment.sol | 1 - .../transient_state_variable_udvt.sol | 1 - .../transient_storage_reentrancy_lock.sol | 1 - 19 files changed, 131 insertions(+), 18 deletions(-) delete mode 100644 test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/err delete mode 100644 test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/exit create mode 100644 test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/err b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/err deleted file mode 100644 index 2f81d6cd3..000000000 --- a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/err +++ /dev/null @@ -1 +0,0 @@ -Error: Transient storage variables are not supported when compiling via IR. diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/exit b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output new file mode 100644 index 000000000..ec427fe37 --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output @@ -0,0 +1,131 @@ +Optimized IR: +/// @use-src 0:"evmasm_transient_storage_state_variable_via_ir/input.sol" +object "C_14" { + code { + { + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_14_deployed"), datasize("C_14_deployed")) + return(_1, datasize("C_14_deployed")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:"evmasm_transient_storage_state_variable_via_ir/input.sol" + object "C_14_deployed" { + code { + { + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0x26121ff0 { external_fun_f() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function abi_decode(headStart, dataEnd) + { + if slt(sub(dataEnd, headStart), 0) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_f() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + abi_decode(4, calldatasize()) + fun_f() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function shift_right_0_unsigned(value) -> newValue + { newValue := shr(0, value) } + function cleanup_from_storage_uint256(value) -> cleaned + { cleaned := value } + function extract_from_storage_value_offsett_uint256(slot_value) -> value + { + value := cleanup_from_storage_uint256(shift_right_0_unsigned(slot_value)) + } + function read_from_transient_storage_split_offset_uint256(slot) -> value + { + value := extract_from_storage_value_offsett_uint256(tload(slot)) + } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x11() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x11) + revert(0, 0x24) + } + function checked_add_uint256(x, y) -> sum + { + x := cleanup_uint256(x) + y := cleanup_uint256(y) + sum := add(x, y) + if gt(x, sum) { panic_error_0x11() } + } + function shift_left(value) -> newValue + { newValue := shl(0, value) } + function update_byte_slice_shift(value, toInsert) -> result + { + let mask := not(0) + toInsert := shift_left(toInsert) + value := and(value, not(mask)) + result := or(value, and(toInsert, mask)) + } + function convert_uint256_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_uint256(value))) + } + function prepare_store_uint256(value) -> ret + { ret := value } + function update_transient_storage_value_offsett_uint256_to_uint256(slot, value) + { + let convertedValue := convert_uint256_to_uint256(value) + tstore(slot, update_byte_slice_shift(tload(slot), prepare_store_uint256(convertedValue))) + } + function fun_f() + { + let _1 := read_from_transient_storage_split_offset_uint256(0x00) + let expr := _1 + let expr_1 := 0x01 + let expr_2 := checked_add_uint256(expr, convert_rational_by_to_uint256(expr_1)) + update_transient_storage_value_offsett_uint256_to_uint256(0x00, expr_2) + } + } + data ".metadata" hex"" + } +} diff --git a/test/libsolidity/semanticTests/getters/transient_value_types.sol b/test/libsolidity/semanticTests/getters/transient_value_types.sol index cc345cb91..852e96baf 100644 --- a/test/libsolidity/semanticTests/getters/transient_value_types.sol +++ b/test/libsolidity/semanticTests/getters/transient_value_types.sol @@ -8,7 +8,6 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // x() -> 0 // f() -> -1 diff --git a/test/libsolidity/semanticTests/getters/transient_value_types_multi_frame_call.sol b/test/libsolidity/semanticTests/getters/transient_value_types_multi_frame_call.sol index 5e6b3f054..912fca4fc 100644 --- a/test/libsolidity/semanticTests/getters/transient_value_types_multi_frame_call.sol +++ b/test/libsolidity/semanticTests/getters/transient_value_types_multi_frame_call.sol @@ -15,7 +15,6 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // x() -> 0 // f() -> -2 diff --git a/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_transient_storage_access_inside_function.sol b/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_transient_storage_access_inside_function.sol index 86463473b..489f1a4ca 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_transient_storage_access_inside_function.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_transient_storage_access_inside_function.sol @@ -18,6 +18,5 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // f() -> 7 diff --git a/test/libsolidity/semanticTests/operators/compound_assign_transient_storage.sol b/test/libsolidity/semanticTests/operators/compound_assign_transient_storage.sol index a20c8403e..c3adf3a1c 100644 --- a/test/libsolidity/semanticTests/operators/compound_assign_transient_storage.sol +++ b/test/libsolidity/semanticTests/operators/compound_assign_transient_storage.sol @@ -11,7 +11,6 @@ contract test { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // f(uint256,uint256): 0, 6 -> 7 // f(uint256,uint256): 1, 3 -> 11 diff --git a/test/libsolidity/semanticTests/operators/transient_storage_variable_increment_decrement.sol b/test/libsolidity/semanticTests/operators/transient_storage_variable_increment_decrement.sol index ac32eee1c..889153014 100644 --- a/test/libsolidity/semanticTests/operators/transient_storage_variable_increment_decrement.sol +++ b/test/libsolidity/semanticTests/operators/transient_storage_variable_increment_decrement.sol @@ -11,6 +11,5 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // f() -> 1 diff --git a/test/libsolidity/semanticTests/variables/delete_transient_state_variable.sol b/test/libsolidity/semanticTests/variables/delete_transient_state_variable.sol index 5f584fc89..868149ebc 100644 --- a/test/libsolidity/semanticTests/variables/delete_transient_state_variable.sol +++ b/test/libsolidity/semanticTests/variables/delete_transient_state_variable.sol @@ -8,6 +8,5 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // f() -> 0 diff --git a/test/libsolidity/semanticTests/variables/transient_function_type_state_variable.sol b/test/libsolidity/semanticTests/variables/transient_function_type_state_variable.sol index 56a69649e..eb9d00fa0 100644 --- a/test/libsolidity/semanticTests/variables/transient_function_type_state_variable.sol +++ b/test/libsolidity/semanticTests/variables/transient_function_type_state_variable.sol @@ -12,6 +12,5 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol b/test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol index 6a388b3ee..22cc5db05 100644 --- a/test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol +++ b/test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol @@ -10,7 +10,6 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // constructor() -> // gas legacy: 59027 diff --git a/test/libsolidity/semanticTests/variables/transient_state_enum_variable.sol b/test/libsolidity/semanticTests/variables/transient_state_enum_variable.sol index a472212d4..e260ebad6 100644 --- a/test/libsolidity/semanticTests/variables/transient_state_enum_variable.sol +++ b/test/libsolidity/semanticTests/variables/transient_state_enum_variable.sol @@ -13,6 +13,5 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // f() -> diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable.sol b/test/libsolidity/semanticTests/variables/transient_state_variable.sol index 71ed212d0..03163982d 100644 --- a/test/libsolidity/semanticTests/variables/transient_state_variable.sol +++ b/test/libsolidity/semanticTests/variables/transient_state_variable.sol @@ -15,7 +15,6 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // x() -> 0 // g() -> 8 diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_assignment.sol b/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_assignment.sol index d1f0cc579..a81572ec1 100644 --- a/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_assignment.sol +++ b/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_assignment.sol @@ -12,6 +12,5 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // f() -> 0xff diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_tstore.sol b/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_tstore.sol index 425be5500..8f3be7ae5 100644 --- a/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_tstore.sol +++ b/test/libsolidity/semanticTests/variables/transient_state_variable_cleanup_tstore.sol @@ -10,6 +10,5 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // f() -> 0xff diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable_slot_inline_assembly.sol b/test/libsolidity/semanticTests/variables/transient_state_variable_slot_inline_assembly.sol index 6cf05068e..0e7f29ed4 100644 --- a/test/libsolidity/semanticTests/variables/transient_state_variable_slot_inline_assembly.sol +++ b/test/libsolidity/semanticTests/variables/transient_state_variable_slot_inline_assembly.sol @@ -25,7 +25,6 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // f() -> 0, 0 // g() -> 1, 0 diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable_tuple_assignment.sol b/test/libsolidity/semanticTests/variables/transient_state_variable_tuple_assignment.sol index 1b5180635..379126621 100644 --- a/test/libsolidity/semanticTests/variables/transient_state_variable_tuple_assignment.sol +++ b/test/libsolidity/semanticTests/variables/transient_state_variable_tuple_assignment.sol @@ -16,6 +16,5 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // f() -> 2, 3, 4 diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable_udvt.sol b/test/libsolidity/semanticTests/variables/transient_state_variable_udvt.sol index 2f49a32b0..1829491f4 100644 --- a/test/libsolidity/semanticTests/variables/transient_state_variable_udvt.sol +++ b/test/libsolidity/semanticTests/variables/transient_state_variable_udvt.sol @@ -16,7 +16,6 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // x() -> 0 // g() -> 2 diff --git a/test/libsolidity/semanticTests/various/transient_storage_reentrancy_lock.sol b/test/libsolidity/semanticTests/various/transient_storage_reentrancy_lock.sol index aa3828601..cc3a9d4a4 100644 --- a/test/libsolidity/semanticTests/various/transient_storage_reentrancy_lock.sol +++ b/test/libsolidity/semanticTests/various/transient_storage_reentrancy_lock.sol @@ -18,7 +18,6 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: false // ---- // test(address,bool): 0x1234abcd, true -> FAILURE, hex"08c379a0", 0x20, 0x12, "Reentrancy attempt" // test(address,bool): 0x1234abcd, false -> From 8dfba6053f2a3d9640cd1452fff74aadf8b1b98b Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 16 Sep 2024 12:03:57 +0200 Subject: [PATCH 0361/1340] New tests --- .../args | 2 +- .../output | 45 +++-- .../args | 1 + .../err | 5 + .../input.sol | 11 ++ .../output | 36 ++++ .../args | 2 +- .../output | 184 +++++------------- .../args | 1 + .../input.sol | 9 + .../output | 41 ++++ ...ransient_state_variable_initialization.sol | 16 ++ .../transient_storage_state_variable.sol | 22 +++ ...orage_state_variable_abstract_contract.sol | 26 +++ .../transient_state_variable_value_type.sol | 17 ++ ...ansient_state_variable_non_zero_offset.sol | 14 ++ ...sient_state_variable_slots_and_offsets.sol | 20 ++ .../various/different_call_type_transient.sol | 51 +++++ .../transient_storage_value_type.sol | 15 ++ 19 files changed, 367 insertions(+), 151 deletions(-) create mode 100644 test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/args create mode 100644 test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err create mode 100644 test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/input.sol create mode 100644 test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output create mode 100644 test/cmdlineTests/ir_optimized_transient_storage_value_type/args create mode 100644 test/cmdlineTests/ir_optimized_transient_storage_value_type/input.sol create mode 100644 test/cmdlineTests/ir_optimized_transient_storage_value_type/output create mode 100644 test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol create mode 100644 test/libsolidity/semanticTests/inheritance/transient_storage_state_variable.sol create mode 100644 test/libsolidity/semanticTests/inheritance/transient_storage_state_variable_abstract_contract.sol create mode 100644 test/libsolidity/semanticTests/modifiers/transient_state_variable_value_type.sol create mode 100644 test/libsolidity/semanticTests/variables/delete_transient_state_variable_non_zero_offset.sol create mode 100644 test/libsolidity/semanticTests/variables/transient_state_variable_slots_and_offsets.sol create mode 100644 test/libsolidity/semanticTests/various/different_call_type_transient.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/transient_storage_value_type.sol diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/args b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/args index 8430fd558..b73ac2146 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/args +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/args @@ -1 +1 @@ ---no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none +--no-cbor-metadata --optimize --opcodes --asm --debug-info none diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output index 56dea1afb..a02eca7d9 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output @@ -1,36 +1,43 @@ ======= evmasm_transient_storage_inline_assembly/input.sol:C ======= EVM assembly: - 0x80 + mstore(0x40, 0x80) + callvalue dup1 - 0x40 - mstore - jumpi(tag_1, callvalue) + iszero + tag_1 + jumpi + revert(0x00, 0x00) +tag_1: + pop dataSize(sub_0) - swap1 - dup2 + dup1 dataOffset(sub_0) - dup3 + 0x00 codecopy - return -tag_1: 0x00 - dup1 - revert + return stop sub_0: assembly { - jumpi(tag_1, callvalue) - 0x00 + mstore(0x40, 0x80) + callvalue dup1 + iszero + tag_3 + jumpi + revert(0x00, 0x00) + tag_3: + pop + 0x00 + 0x00 tstore - sstore(0x00, tload(0x00)) - stop - tag_1: 0x00 - dup1 - revert + tload + 0x00 + sstore + stop } Opcodes: -PUSH1 0x80 DUP1 PUSH1 0x40 MSTORE CALLVALUE PUSH1 0x13 JUMPI PUSH1 0x10 SWAP1 DUP2 PUSH1 0x18 DUP3 CODECOPY RETURN JUMPDEST PUSH0 DUP1 REVERT INVALID CALLVALUE PUSH1 0xC JUMPI PUSH0 DUP1 TSTORE PUSH0 TLOAD PUSH0 SSTORE STOP JUMPDEST PUSH0 DUP1 REVERT +PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xE JUMPI PUSH0 PUSH0 REVERT JUMPDEST POP PUSH1 0x18 DUP1 PUSH1 0x1A PUSH0 CODECOPY PUSH0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xE JUMPI PUSH0 PUSH0 REVERT JUMPDEST POP PUSH0 PUSH0 TSTORE PUSH0 TLOAD PUSH0 SSTORE STOP diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/args b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/args new file mode 100644 index 000000000..8430fd558 --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/args @@ -0,0 +1 @@ +--no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err new file mode 100644 index 000000000..b1ccd751c --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err @@ -0,0 +1,5 @@ +Warning: Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. + --> evmasm_transient_storage_inline_assembly_via_ir/input.sol:7:13: + | +7 | tstore(0, 0) + | ^^^^^^ diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/input.sol b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/input.sol new file mode 100644 index 000000000..94914ac4e --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/input.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + fallback() external { + assembly { + tstore(0, 0) + sstore(0, tload(0)) + } + } +} diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output new file mode 100644 index 000000000..62bf1f456 --- /dev/null +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output @@ -0,0 +1,36 @@ + +======= evmasm_transient_storage_inline_assembly_via_ir/input.sol:C ======= +EVM assembly: + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_1, callvalue) + dataSize(sub_0) + swap1 + dup2 + dataOffset(sub_0) + dup3 + codecopy + return +tag_1: + 0x00 + dup1 + revert +stop + +sub_0: assembly { + jumpi(tag_1, callvalue) + 0x00 + dup1 + tstore + sstore(0x00, tload(0x00)) + stop + tag_1: + 0x00 + dup1 + revert +} + +Opcodes: +PUSH1 0x80 DUP1 PUSH1 0x40 MSTORE CALLVALUE PUSH1 0x13 JUMPI PUSH1 0x10 SWAP1 DUP2 PUSH1 0x18 DUP3 CODECOPY RETURN JUMPDEST PUSH0 DUP1 REVERT INVALID CALLVALUE PUSH1 0xC JUMPI PUSH0 DUP1 TSTORE PUSH0 TLOAD PUSH0 SSTORE STOP JUMPDEST PUSH0 DUP1 REVERT diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args index 00dcc3777..e233e0855 100644 --- a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args @@ -1 +1 @@ ---no-cbor-metadata --ir-optimized --debug-info none \ No newline at end of file +--no-cbor-metadata --via-ir --optimize --asm --debug-info none \ No newline at end of file diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output index ec427fe37..5959fad95 100644 --- a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output @@ -1,131 +1,55 @@ -Optimized IR: -/// @use-src 0:"evmasm_transient_storage_state_variable_via_ir/input.sol" -object "C_14" { - code { - { - mstore(64, memoryguard(0x80)) - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - let _1 := allocate_unbounded() - codecopy(_1, dataoffset("C_14_deployed"), datasize("C_14_deployed")) - return(_1, datasize("C_14_deployed")) - } - function allocate_unbounded() -> memPtr - { memPtr := mload(64) } - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - { revert(0, 0) } - } - /// @use-src 0:"evmasm_transient_storage_state_variable_via_ir/input.sol" - object "C_14_deployed" { - code { - { - mstore(64, memoryguard(0x80)) - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_unsigned(calldataload(0)) - switch selector - case 0x26121ff0 { external_fun_f() } - default { } - } - revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - } - function shift_right_unsigned(value) -> newValue - { newValue := shr(224, value) } - function allocate_unbounded() -> memPtr - { memPtr := mload(64) } - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - { revert(0, 0) } - function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() - { revert(0, 0) } - function abi_decode(headStart, dataEnd) - { - if slt(sub(dataEnd, headStart), 0) - { - revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() - } - } - function abi_encode_tuple(headStart) -> tail - { tail := add(headStart, 0) } - function external_fun_f() - { - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - abi_decode(4, calldatasize()) - fun_f() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple(memPos) - return(memPos, sub(memEnd, memPos)) - } - function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - { revert(0, 0) } - function shift_right_0_unsigned(value) -> newValue - { newValue := shr(0, value) } - function cleanup_from_storage_uint256(value) -> cleaned - { cleaned := value } - function extract_from_storage_value_offsett_uint256(slot_value) -> value - { - value := cleanup_from_storage_uint256(shift_right_0_unsigned(slot_value)) - } - function read_from_transient_storage_split_offset_uint256(slot) -> value - { - value := extract_from_storage_value_offsett_uint256(tload(slot)) - } - function cleanup_rational_by(value) -> cleaned - { cleaned := value } - function cleanup_uint256(value) -> cleaned - { cleaned := value } - function identity(value) -> ret - { ret := value } - function convert_rational_by_to_uint256(value) -> converted - { - converted := cleanup_uint256(identity(cleanup_rational_by(value))) - } - function panic_error_0x11() - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 0x11) - revert(0, 0x24) - } - function checked_add_uint256(x, y) -> sum - { - x := cleanup_uint256(x) - y := cleanup_uint256(y) - sum := add(x, y) - if gt(x, sum) { panic_error_0x11() } - } - function shift_left(value) -> newValue - { newValue := shl(0, value) } - function update_byte_slice_shift(value, toInsert) -> result - { - let mask := not(0) - toInsert := shift_left(toInsert) - value := and(value, not(mask)) - result := or(value, and(toInsert, mask)) - } - function convert_uint256_to_uint256(value) -> converted - { - converted := cleanup_uint256(identity(cleanup_uint256(value))) - } - function prepare_store_uint256(value) -> ret - { ret := value } - function update_transient_storage_value_offsett_uint256_to_uint256(slot, value) - { - let convertedValue := convert_uint256_to_uint256(value) - tstore(slot, update_byte_slice_shift(tload(slot), prepare_store_uint256(convertedValue))) - } - function fun_f() - { - let _1 := read_from_transient_storage_split_offset_uint256(0x00) - let expr := _1 - let expr_1 := 0x01 - let expr_2 := checked_add_uint256(expr, convert_rational_by_to_uint256(expr_1)) - update_transient_storage_value_offsett_uint256_to_uint256(0x00, expr_2) - } - } - data ".metadata" hex"" - } + +======= evmasm_transient_storage_state_variable_via_ir/input.sol:C ======= +EVM assembly: + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_1, callvalue) + dataSize(sub_0) + swap1 + dup2 + dataOffset(sub_0) + dup3 + codecopy + return +tag_1: + 0x00 + dup1 + revert +stop + +sub_0: assembly { + jumpi(tag_1, iszero(lt(calldatasize, 0x04))) + 0x00 + dup1 + revert + tag_1: + jumpi(tag_3, eq(0x26121ff0, shr(0xe0, calldataload(0x00)))) + 0x00 + dup1 + revert + tag_3: + jumpi(tag_7, callvalue) + jumpi(tag_7, slt(add(not(0x03), calldatasize), 0x00)) + tload(0x00) + 0x01 + dup2 + add + dup1 + swap2 + gt + tag_9 + jumpi + 0x00 + tstore + stop + tag_9: + mstore(0x00, shl(0xe0, 0x4e487b71)) + mstore(0x04, 0x11) + revert(0x00, 0x24) + tag_7: + 0x00 + dup1 + revert } diff --git a/test/cmdlineTests/ir_optimized_transient_storage_value_type/args b/test/cmdlineTests/ir_optimized_transient_storage_value_type/args new file mode 100644 index 000000000..20e22da1a --- /dev/null +++ b/test/cmdlineTests/ir_optimized_transient_storage_value_type/args @@ -0,0 +1 @@ +--via-ir --no-cbor-metadata --ir-optimized --optimize --debug-info none diff --git a/test/cmdlineTests/ir_optimized_transient_storage_value_type/input.sol b/test/cmdlineTests/ir_optimized_transient_storage_value_type/input.sol new file mode 100644 index 000000000..7177bdb64 --- /dev/null +++ b/test/cmdlineTests/ir_optimized_transient_storage_value_type/input.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C { + uint transient x; + function f() public { + x = x + 1; + } +} diff --git a/test/cmdlineTests/ir_optimized_transient_storage_value_type/output b/test/cmdlineTests/ir_optimized_transient_storage_value_type/output new file mode 100644 index 000000000..61d289e3f --- /dev/null +++ b/test/cmdlineTests/ir_optimized_transient_storage_value_type/output @@ -0,0 +1,41 @@ +Optimized IR: +/// @use-src 0:"ir_optimized_transient_storage_value_type/input.sol" +object "C_14" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_14_deployed") + codecopy(_1, dataoffset("C_14_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"ir_optimized_transient_storage_value_type/input.sol" + object "C_14_deployed" { + code { + { + if iszero(lt(calldatasize(), 4)) + { + if eq(0x26121ff0, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + let _1 := tload(0) + let sum := add(_1, 0x01) + if gt(_1, sum) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x11) + revert(0, 0x24) + } + tstore(0, sum) + return(0, 0) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol b/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol new file mode 100644 index 000000000..4c69b58f8 --- /dev/null +++ b/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol @@ -0,0 +1,16 @@ +contract C { + uint256 transient x; + + constructor() { + x = 100; + } + + function f() external view returns (uint256 x) { + x; + } +} + +// ==== +// EVMVersion: >=cancun +// ---- +// f() -> 0 diff --git a/test/libsolidity/semanticTests/inheritance/transient_storage_state_variable.sol b/test/libsolidity/semanticTests/inheritance/transient_storage_state_variable.sol new file mode 100644 index 000000000..56c686f82 --- /dev/null +++ b/test/libsolidity/semanticTests/inheritance/transient_storage_state_variable.sol @@ -0,0 +1,22 @@ +contract A { + uint transient x; + int y; +} + +contract C is A { + uint w; + int transient z; + + function f() public returns (uint, int, uint, int) { + x += 1; + y += 2; + w += 3; + z += 4; + + return (x, y, w, z); + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// f() -> 1, 2, 3, 4 diff --git a/test/libsolidity/semanticTests/inheritance/transient_storage_state_variable_abstract_contract.sol b/test/libsolidity/semanticTests/inheritance/transient_storage_state_variable_abstract_contract.sol new file mode 100644 index 000000000..5db209f16 --- /dev/null +++ b/test/libsolidity/semanticTests/inheritance/transient_storage_state_variable_abstract_contract.sol @@ -0,0 +1,26 @@ +abstract contract A { + uint transient x; + int y; + function f() public virtual returns (uint, int, uint, int); +} + +contract C is A { + uint w; + int transient z; + + function g() public { + w += 2; + z += 2; + } + + function f() public override returns (uint, int, uint, int) { + x += 1; + y += 1; + g(); + return (x, y, w, z); + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// f() -> 1, 1, 2, 2 diff --git a/test/libsolidity/semanticTests/modifiers/transient_state_variable_value_type.sol b/test/libsolidity/semanticTests/modifiers/transient_state_variable_value_type.sol new file mode 100644 index 000000000..4c60ee1a8 --- /dev/null +++ b/test/libsolidity/semanticTests/modifiers/transient_state_variable_value_type.sol @@ -0,0 +1,17 @@ +contract C { + uint16 transient x; + + modifier m(uint16) { + x += 10; + _; + } + + function f() public m(x) returns (uint16 x) { + x *= 10; + } +} + +// ==== +// EVMVersion: >=cancun +// ---- +// f() -> 0 diff --git a/test/libsolidity/semanticTests/variables/delete_transient_state_variable_non_zero_offset.sol b/test/libsolidity/semanticTests/variables/delete_transient_state_variable_non_zero_offset.sol new file mode 100644 index 000000000..45860599e --- /dev/null +++ b/test/libsolidity/semanticTests/variables/delete_transient_state_variable_non_zero_offset.sol @@ -0,0 +1,14 @@ +contract C { + uint128 transient x; + uint128 transient y; + + function f() public returns (uint) { + y = 10; + delete y; + return y; + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// f() -> 0 diff --git a/test/libsolidity/semanticTests/variables/transient_state_variable_slots_and_offsets.sol b/test/libsolidity/semanticTests/variables/transient_state_variable_slots_and_offsets.sol new file mode 100644 index 000000000..63f23e185 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/transient_state_variable_slots_and_offsets.sol @@ -0,0 +1,20 @@ +contract C { + uint128 transient x; + uint64 transient y; + uint64 transient w; + uint256 transient z; + + function f() external returns (uint128, uint64, uint64, uint256) { + x = 1; + y = 2; + w = 3; + z = 4; + + return (x, y, w, z); + } +} + +// ==== +// EVMVersion: >=cancun +// ---- +// f() -> 1, 2, 3, 4 diff --git a/test/libsolidity/semanticTests/various/different_call_type_transient.sol b/test/libsolidity/semanticTests/various/different_call_type_transient.sol new file mode 100644 index 000000000..b71e8b252 --- /dev/null +++ b/test/libsolidity/semanticTests/various/different_call_type_transient.sol @@ -0,0 +1,51 @@ +contract B { + uint256 transient public value; + + function setValue(uint256 v) public { + value += v; + } +} + +contract A { + uint256 transient public value; + + function delegateSetValue(address otherContract, uint256 v) public { + (bool success, ) = otherContract.delegatecall(abi.encodeWithSignature("setValue(uint256)", v)); + require(success); + } + function callSetValue(address otherContract, uint256 v) public { + (bool success, ) = otherContract.call(abi.encodeWithSignature("setValue(uint256)", v)); + require(success); + } + function staticSetValue(address otherContract, uint256 v) view public returns (bool) { + (bool success, ) = otherContract.staticcall(abi.encodeWithSignature("setValue(uint256)", v)); + return success; + } +} + +contract Test { + A a = new A(); + B b = new B(); + + function testDelegate() public returns (uint256, uint256) { + a.delegateSetValue(address(b), 7); + return (a.value(), b.value()); + } + function testCall() public returns (uint256, uint256) { + a.callSetValue(address(b), 8); + return (a.value(), b.value()); + } + function testStatic() view public returns (bool) { + return a.staticSetValue(address(b), 0); + } +} + +// ==== +// EVMVersion: >=cancun +// ---- +// testDelegate() -> 7, 0 +// testCall() -> 0, 8 +// testStatic() -> false +// gas irOptimized: 96900694 +// gas legacy: 96901136 +// gas legacyOptimized: 96900725 diff --git a/test/libsolidity/syntaxTests/viewPureChecker/transient_storage_value_type.sol b/test/libsolidity/syntaxTests/viewPureChecker/transient_storage_value_type.sol new file mode 100644 index 000000000..9c48f17f1 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/transient_storage_value_type.sol @@ -0,0 +1,15 @@ +contract C { + uint transient x; + + function f() public view { + x = 1; + } + function g() public pure returns (uint a) { + a = x + 1; + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// TypeError 8961: (75-76): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 2527: (148-149): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". From 6398cb271fe1dfdd8a237bb7cb9625155afa4150 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 16 Sep 2024 14:04:36 +0200 Subject: [PATCH 0362/1340] Changelog --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 7d9af1cdb..b23b5ff9e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,7 +4,7 @@ Language Features: Compiler Features: - * Code Generator: Transient storage value type state variables are now supported by the legacy pipeline. + * Code Generator: Transient storage value type state variables are now supported. * General: Generate JSON representations of Yul ASTs only on demand to reduce memory usage. From 98fdc44b2600b3e7236803b627544ee20eddc6ef Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 25 Sep 2024 19:39:00 +0200 Subject: [PATCH 0363/1340] Fix missing underscore in Yul function names --- libsolidity/codegen/YulUtilFunctions.cpp | 4 +-- .../codegen/ir/IRGeneratorForStatements.cpp | 5 +++- .../err | 2 +- .../input.sol | 2 +- .../output | 4 +-- .../err | 2 +- .../input.sol | 2 +- .../output | 6 ++-- .../args | 2 +- .../output | 2 +- .../output.json | 30 +++++++++---------- ...ransient_state_variable_initialization.sol | 10 ++++--- .../transient_storage_state_variable.sol | 10 +++---- .../transient_state_variable_value_type.sol | 5 ++-- ...ansient_state_variable_non_zero_offset.sol | 15 ++++++---- ...ansient_state_address_variable_members.sol | 2 +- .../various/different_call_type_transient.sol | 2 +- 17 files changed, 56 insertions(+), 49 deletions(-) diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index fc6de832b..c908c7ae0 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -2923,7 +2923,7 @@ std::string YulUtilFunctions::updateStorageValueFunction( "update_" + (_location == VariableDeclaration::Location::Transient ? "transient_"s : "") + "storage_value_" + - (_offset.has_value() ? ("offset_" + std::to_string(*_offset)) : "") + + (_offset.has_value() ? ("offset_" + std::to_string(*_offset)) + "_" : "") + _fromType.identifier() + "_to_" + _toType.identifier(); @@ -3106,7 +3106,7 @@ std::string YulUtilFunctions::extractFromStorageValueDynamic(Type const& _type) std::string YulUtilFunctions::extractFromStorageValue(Type const& _type, size_t _offset) { - std::string functionName = "extract_from_storage_value_offset_" + std::to_string(_offset) + _type.identifier(); + std::string functionName = "extract_from_storage_value_offset_" + std::to_string(_offset) + "_" + _type.identifier(); return m_functionCollector.createFunction(functionName, [&] { return Whiskers(R"( function (slot_value) -> value { diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 283cc4b6b..911230d22 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -271,7 +271,7 @@ void IRGeneratorForStatements::initializeStateVar(VariableDeclaration const& _va solAssert(!_varDecl.isConstant()); if (!_varDecl.value()) return; - solAssert(_varDecl.referenceLocation() != VariableDeclaration::Location::Transient, "State variables cannot be initialized in place."); + solAssert(_varDecl.referenceLocation() != VariableDeclaration::Location::Transient, "Transient storage state variables cannot be initialized in place."); _varDecl.value()->accept(*this); @@ -2569,6 +2569,8 @@ void IRGeneratorForStatements::handleVariableReference( } }); else if (m_context.isStateVariable(_variable)) + { + solAssert(_variable.referenceLocation() == VariableDeclaration::Location::Unspecified, "Must have storage location."); setLValue(_referencingExpression, IRLValue{ *_variable.annotation().type, IRLValue::Storage{ @@ -2576,6 +2578,7 @@ void IRGeneratorForStatements::handleVariableReference( m_context.storageLocationOfStateVariable(_variable).second } }); + } else solAssert(false, "Invalid variable kind."); } diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/err b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/err index 5071bc457..2e52d9ced 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/err +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/err @@ -1,5 +1,5 @@ Warning: Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. --> evmasm_transient_storage_inline_assembly/input.sol:7:13: | -7 | tstore(0, 0) +7 | tstore(0, 123) | ^^^^^^ diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/input.sol b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/input.sol index 94914ac4e..5504944fe 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/input.sol +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/input.sol @@ -4,7 +4,7 @@ pragma solidity >=0.0.0; contract C { fallback() external { assembly { - tstore(0, 0) + tstore(0, 123) sstore(0, tload(0)) } } diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output index a02eca7d9..0b4c516ba 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output @@ -29,7 +29,7 @@ sub_0: assembly { revert(0x00, 0x00) tag_3: pop - 0x00 + 0x7b 0x00 tstore 0x00 @@ -40,4 +40,4 @@ sub_0: assembly { } Opcodes: -PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xE JUMPI PUSH0 PUSH0 REVERT JUMPDEST POP PUSH1 0x18 DUP1 PUSH1 0x1A PUSH0 CODECOPY PUSH0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xE JUMPI PUSH0 PUSH0 REVERT JUMPDEST POP PUSH0 PUSH0 TSTORE PUSH0 TLOAD PUSH0 SSTORE STOP +PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xE JUMPI PUSH0 PUSH0 REVERT JUMPDEST POP PUSH1 0x19 DUP1 PUSH1 0x1A PUSH0 CODECOPY PUSH0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xE JUMPI PUSH0 PUSH0 REVERT JUMPDEST POP PUSH1 0x7B PUSH0 TSTORE PUSH0 TLOAD PUSH0 SSTORE STOP diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err index b1ccd751c..154da21b6 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err @@ -1,5 +1,5 @@ Warning: Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. --> evmasm_transient_storage_inline_assembly_via_ir/input.sol:7:13: | -7 | tstore(0, 0) +7 | tstore(0, 123) | ^^^^^^ diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/input.sol b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/input.sol index 94914ac4e..5504944fe 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/input.sol +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/input.sol @@ -4,7 +4,7 @@ pragma solidity >=0.0.0; contract C { fallback() external { assembly { - tstore(0, 0) + tstore(0, 123) sstore(0, tload(0)) } } diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output index 62bf1f456..673bdd0a0 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output @@ -21,9 +21,7 @@ stop sub_0: assembly { jumpi(tag_1, callvalue) - 0x00 - dup1 - tstore + tstore(0x00, 0x7b) sstore(0x00, tload(0x00)) stop tag_1: @@ -33,4 +31,4 @@ sub_0: assembly { } Opcodes: -PUSH1 0x80 DUP1 PUSH1 0x40 MSTORE CALLVALUE PUSH1 0x13 JUMPI PUSH1 0x10 SWAP1 DUP2 PUSH1 0x18 DUP3 CODECOPY RETURN JUMPDEST PUSH0 DUP1 REVERT INVALID CALLVALUE PUSH1 0xC JUMPI PUSH0 DUP1 TSTORE PUSH0 TLOAD PUSH0 SSTORE STOP JUMPDEST PUSH0 DUP1 REVERT +PUSH1 0x80 DUP1 PUSH1 0x40 MSTORE CALLVALUE PUSH1 0x13 JUMPI PUSH1 0x11 SWAP1 DUP2 PUSH1 0x18 DUP3 CODECOPY RETURN JUMPDEST PUSH0 DUP1 REVERT INVALID CALLVALUE PUSH1 0xD JUMPI PUSH1 0x7B PUSH0 TSTORE PUSH0 TLOAD PUSH0 SSTORE STOP JUMPDEST PUSH0 DUP1 REVERT diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args index e233e0855..163b19ef4 100644 --- a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/args @@ -1 +1 @@ ---no-cbor-metadata --via-ir --optimize --asm --debug-info none \ No newline at end of file +--no-cbor-metadata --via-ir --optimize --asm --debug-info none diff --git a/test/cmdlineTests/inline_assembly_function_name_clash/output b/test/cmdlineTests/inline_assembly_function_name_clash/output index d7c7bf9e0..2fd6ff1f5 100644 --- a/test/cmdlineTests/inline_assembly_function_name_clash/output +++ b/test/cmdlineTests/inline_assembly_function_name_clash/output @@ -128,7 +128,7 @@ "parameterSlots": 2, "returnSlots": 1 }, - "update_storage_value_offsett_uint256_to_uint256": { + "update_storage_value_offset_uint256_to_uint256": { "entryPoint": 307, "parameterSlots": 2, "returnSlots": 0 diff --git a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json index 8f0d5b5b5..5ff4e7a19 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json @@ -127,7 +127,7 @@ object \"C_54\" { ret := value } - function update_storage_value_offset_0t_int256_to_t_int256(slot, value_0) { + function update_storage_value_offset_0_t_int256_to_t_int256(slot, value_0) { let convertedValue_0 := convert_t_int256_to_t_int256(value_0) sstore(slot, update_byte_slice_32_shift_0(sload(slot), prepare_store_t_int256(convertedValue_0))) } @@ -147,7 +147,7 @@ object \"C_54\" { let _4 := var__init_12 let expr_16 := _4 /// @src 0:231:247 \"stateVar = _init\" - update_storage_value_offset_0t_int256_to_t_int256(0x00, expr_16) + update_storage_value_offset_0_t_int256_to_t_int256(0x00, expr_16) let expr_17 := expr_16 } @@ -398,12 +398,12 @@ object \"C_54\" { } - function extract_from_storage_value_offset_0t_int256(slot_value) -> value { + function extract_from_storage_value_offset_0_t_int256(slot_value) -> value { value := cleanup_from_storage_t_int256(shift_right_0_unsigned(slot_value)) } function read_from_storage_split_offset_0_t_int256(slot) -> value { - value := extract_from_storage_value_offset_0t_int256(sload(slot)) + value := extract_from_storage_value_offset_0_t_int256(sload(slot)) } @@ -435,7 +435,7 @@ object \"C_54\" { ret := value } - function update_storage_value_offset_0t_int256_to_t_int256(slot, value_0) { + function update_storage_value_offset_0_t_int256_to_t_int256(slot, value_0) { let convertedValue_0 := convert_t_int256_to_t_int256(value_0) sstore(slot, update_byte_slice_32_shift_0(sload(slot), prepare_store_t_int256(convertedValue_0))) } @@ -448,7 +448,7 @@ object \"C_54\" { /// @src 0:380:390 \"stateVar++\" let _7 := read_from_storage_split_offset_0_t_int256(0x00) let _6 := increment_t_int256(_7) - update_storage_value_offset_0t_int256_to_t_int256(0x00, _6) + update_storage_value_offset_0_t_int256_to_t_int256(0x00, _6) let expr_33 := _7 /// @src 0:400:401 \"_\" _5 := fun_f2_53_inner(var__42) @@ -882,12 +882,12 @@ object \"D_72\" { cleaned := value } - function extract_from_storage_value_offset_0t_int256(slot_value) -> value { + function extract_from_storage_value_offset_0_t_int256(slot_value) -> value { value := cleanup_from_storage_t_int256(shift_right_0_unsigned(slot_value)) } function read_from_storage_split_offset_0_t_int256(slot) -> value { - value := extract_from_storage_value_offset_0t_int256(sload(slot)) + value := extract_from_storage_value_offset_0_t_int256(sload(slot)) } @@ -933,7 +933,7 @@ object \"D_72\" { ret := value } - function update_storage_value_offset_0t_int256_to_t_int256(slot, value_0) { + function update_storage_value_offset_0_t_int256_to_t_int256(slot, value_0) { let convertedValue_0 := convert_t_int256_to_t_int256(value_0) sstore(slot, update_byte_slice_32_shift_0(sload(slot), prepare_store_t_int256(convertedValue_0))) } @@ -955,7 +955,7 @@ object \"D_72\" { let _5 := read_from_storage_split_offset_0_t_int256(0x00) let expr_68 := checked_add_t_int256(_5, expr_67) - update_storage_value_offset_0t_int256_to_t_int256(0x00, expr_68) + update_storage_value_offset_0_t_int256_to_t_int256(0x00, expr_68) } /// @src 1:91:181 \"contract D is C(3)...\" @@ -983,7 +983,7 @@ object \"D_72\" { let _7 := var__init_12 let expr_16 := _7 /// @src 0:231:247 \"stateVar = _init\" - update_storage_value_offset_0t_int256_to_t_int256(0x00, expr_16) + update_storage_value_offset_0_t_int256_to_t_int256(0x00, expr_16) let expr_17 := expr_16 } @@ -1234,12 +1234,12 @@ object \"D_72\" { } - function extract_from_storage_value_offset_0t_int256(slot_value) -> value { + function extract_from_storage_value_offset_0_t_int256(slot_value) -> value { value := cleanup_from_storage_t_int256(shift_right_0_unsigned(slot_value)) } function read_from_storage_split_offset_0_t_int256(slot) -> value { - value := extract_from_storage_value_offset_0t_int256(sload(slot)) + value := extract_from_storage_value_offset_0_t_int256(sload(slot)) } @@ -1271,7 +1271,7 @@ object \"D_72\" { ret := value } - function update_storage_value_offset_0t_int256_to_t_int256(slot, value_0) { + function update_storage_value_offset_0_t_int256_to_t_int256(slot, value_0) { let convertedValue_0 := convert_t_int256_to_t_int256(value_0) sstore(slot, update_byte_slice_32_shift_0(sload(slot), prepare_store_t_int256(convertedValue_0))) } @@ -1284,7 +1284,7 @@ object \"D_72\" { /// @src 0:380:390 \"stateVar++\" let _7 := read_from_storage_split_offset_0_t_int256(0x00) let _6 := increment_t_int256(_7) - update_storage_value_offset_0t_int256_to_t_int256(0x00, _6) + update_storage_value_offset_0_t_int256_to_t_int256(0x00, _6) let expr_33 := _7 /// @src 0:400:401 \"_\" _5 := fun_f2_53_inner(var__42) diff --git a/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol b/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol index 4c69b58f8..3260fa30f 100644 --- a/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol +++ b/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol @@ -1,16 +1,18 @@ contract C { - uint256 transient x; + uint128 transient x; + uint128 y; constructor() { x = 100; + y = x; } - function f() external view returns (uint256 x) { - x; + function f() external view returns (uint128) { + return y; } } // ==== // EVMVersion: >=cancun // ---- -// f() -> 0 +// f() -> 100 diff --git a/test/libsolidity/semanticTests/inheritance/transient_storage_state_variable.sol b/test/libsolidity/semanticTests/inheritance/transient_storage_state_variable.sol index 56c686f82..cef016bc0 100644 --- a/test/libsolidity/semanticTests/inheritance/transient_storage_state_variable.sol +++ b/test/libsolidity/semanticTests/inheritance/transient_storage_state_variable.sol @@ -1,13 +1,13 @@ contract A { - uint transient x; - int y; + uint24 transient x; + int24 y; } contract C is A { - uint w; - int transient z; + uint24 w; + int24 transient z; - function f() public returns (uint, int, uint, int) { + function f() public returns (uint24, int24, uint24, int24) { x += 1; y += 2; w += 3; diff --git a/test/libsolidity/semanticTests/modifiers/transient_state_variable_value_type.sol b/test/libsolidity/semanticTests/modifiers/transient_state_variable_value_type.sol index 4c60ee1a8..2d4157ec9 100644 --- a/test/libsolidity/semanticTests/modifiers/transient_state_variable_value_type.sol +++ b/test/libsolidity/semanticTests/modifiers/transient_state_variable_value_type.sol @@ -6,12 +6,13 @@ contract C { _; } - function f() public m(x) returns (uint16 x) { + function f() public m(x) returns (uint16) { x *= 10; + return x; } } // ==== // EVMVersion: >=cancun // ---- -// f() -> 0 +// f() -> 100 diff --git a/test/libsolidity/semanticTests/variables/delete_transient_state_variable_non_zero_offset.sol b/test/libsolidity/semanticTests/variables/delete_transient_state_variable_non_zero_offset.sol index 45860599e..96dfce602 100644 --- a/test/libsolidity/semanticTests/variables/delete_transient_state_variable_non_zero_offset.sol +++ b/test/libsolidity/semanticTests/variables/delete_transient_state_variable_non_zero_offset.sol @@ -1,14 +1,17 @@ contract C { - uint128 transient x; - uint128 transient y; + bytes14 transient x; + uint32 transient y; + uint112 transient z; - function f() public returns (uint) { - y = 10; + function f() public returns (bytes14, uint32, uint112) { + x = 0xffffffffffffffffffffffffffff; + y = 0xffffffff; + z = 0xffffffffffffffffffffffffffff; delete y; - return y; + return (x, y, z); } } // ==== // EVMVersion: >=cancun // ---- -// f() -> 0 +// f() -> 0xffffffffffffffffffffffffffff000000000000000000000000000000000000, 0, 0xffffffffffffffffffffffffffff diff --git a/test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol b/test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol index 22cc5db05..f609f9d4d 100644 --- a/test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol +++ b/test/libsolidity/semanticTests/variables/transient_state_address_variable_members.sol @@ -17,4 +17,4 @@ contract C { // account: 0 -> 0x1212121212121212121212121212120000000012 // balance: 0x1212121212121212121212121212120000000012 -> 1267650600228229401496703205376 // f() -> 1267650600228229401496703205376 -// g() -> 0 \ No newline at end of file +// g() -> 0 diff --git a/test/libsolidity/semanticTests/various/different_call_type_transient.sol b/test/libsolidity/semanticTests/various/different_call_type_transient.sol index b71e8b252..399cbd02d 100644 --- a/test/libsolidity/semanticTests/various/different_call_type_transient.sol +++ b/test/libsolidity/semanticTests/various/different_call_type_transient.sol @@ -35,7 +35,7 @@ contract Test { a.callSetValue(address(b), 8); return (a.value(), b.value()); } - function testStatic() view public returns (bool) { + function testStatic() view public returns (bool) { return a.staticSetValue(address(b), 0); } } From b54074176a9b751d252650528252a8c8468976ca Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 5 Sep 2024 14:50:04 -0300 Subject: [PATCH 0364/1340] Transient storage docs --- docs/assembly.rst | 9 +- docs/contracts.rst | 2 + docs/contracts/constant-state-variables.rst | 5 +- docs/contracts/functions.rst | 4 +- docs/contracts/transient-storage.rst | 172 ++++++++++++++++++++ docs/internals/layout_in_storage.rst | 79 +++++++-- docs/introduction-to-smart-contracts.rst | 47 +++++- docs/structure-of-a-contract.rst | 6 +- docs/types/reference-types.rst | 3 + docs/types/value-types.rst | 6 + 10 files changed, 305 insertions(+), 28 deletions(-) create mode 100644 docs/contracts/transient-storage.rst diff --git a/docs/assembly.rst b/docs/assembly.rst index 34085bccb..a0a9d06dc 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -163,7 +163,7 @@ their calldata offset (in bytes) and length (number of elements) using ``x.offse Both expressions can also be assigned to, but as for the static case, no validation will be performed to ensure that the resulting data area is within the bounds of ``calldatasize()``. -For local storage variables or state variables, a single Yul identifier +For local storage variables or state variables (including transient storage) a single Yul identifier is not sufficient, since they do not necessarily occupy a single full storage slot. Therefore, their "address" is composed of a slot and a byte-offset inside that slot. To retrieve the slot pointed to by the variable ``x``, you @@ -181,15 +181,18 @@ Local Solidity variables are available for assignments, for example: :force: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.7.0 <0.9.0; + pragma solidity >=0.8.28 <0.9.0; + // This will report a warning contract C { + bool transient a; uint b; - function f(uint x) public view returns (uint r) { + function f(uint x) public returns (uint r) { assembly { // We ignore the storage slot offset, we know it is zero // in this special case. r := mul(x, sload(b.slot)) + tstore(a.slot, true) } } } diff --git a/docs/contracts.rst b/docs/contracts.rst index aee26c95a..588b1da00 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -20,6 +20,8 @@ There is no "cron" concept in Ethereum to call a function at a particular event .. include:: contracts/function-modifiers.rst +.. include:: contracts/transient-storage.rst + .. include:: contracts/constant-state-variables.rst .. include:: contracts/functions.rst diff --git a/docs/contracts/constant-state-variables.rst b/docs/contracts/constant-state-variables.rst index a1bc24f50..4e9698735 100644 --- a/docs/contracts/constant-state-variables.rst +++ b/docs/contracts/constant-state-variables.rst @@ -13,8 +13,9 @@ for ``immutable``, it can still be assigned at construction time. It is also possible to define ``constant`` variables at the file level. -The compiler does not reserve a storage slot for these variables, and every occurrence is -replaced by the respective value. +Every occurrence of such a variable in the source is replaced by its underlying value +and the compiler does not reserve a storage slot for it. +It cannot be assigned a slot in transient storage using the ``transient`` keyword either. Compared to regular state variables, the gas costs of constant and immutable variables are much lower. For a constant variable, the expression assigned to it is copied to diff --git a/docs/contracts/functions.rst b/docs/contracts/functions.rst index 5b82a93bc..e653eb8f0 100644 --- a/docs/contracts/functions.rst +++ b/docs/contracts/functions.rst @@ -174,7 +174,7 @@ Functions can be declared ``view`` in which case they promise not to modify the The following statements are considered modifying the state: -#. Writing to state variables. +#. Writing to state variables (storage and transient storage). #. :ref:`Emitting events `. #. :ref:`Creating other contracts `. #. Using ``selfdestruct``. @@ -226,7 +226,7 @@ This means that reading from ``immutable`` variables can be a non-pure operation In addition to the list of state modifying statements explained above, the following are considered reading from the state: -#. Reading from state variables. +#. Reading from state variables (storage and transient storage). #. Accessing ``address(this).balance`` or ``
.balance``. #. Accessing any of the members of ``block``, ``tx``, ``msg`` (with the exception of ``msg.sig`` and ``msg.data``). #. Calling any function not marked ``pure``. diff --git a/docs/contracts/transient-storage.rst b/docs/contracts/transient-storage.rst new file mode 100644 index 000000000..b2d0be292 --- /dev/null +++ b/docs/contracts/transient-storage.rst @@ -0,0 +1,172 @@ +.. index:: ! transient storage, ! transient, tstore, tload + +.. _transient-storage: + +***************** +Transient Storage +***************** + +Transient storage is another data location besides memory, storage, calldata +(and return-data and code) which was introduced alongside its respective opcodes +``TSTORE`` and ``TLOAD`` by `EIP-1153 `_. +This new data location behaves as a key-value store similar to storage with the main +difference being that data in transient storage is not permanent, but is scoped to +the current transaction only, after which it will be reset to zero. +Since the content of transient storage has very limited lifetime and size, +it does not need to be stored permanently as a part of state +and the associated gas costs are much lower than in case of storage. +EVM version ``cancun`` or newer is required for transient storage to be available. + +Transient storage variables cannot be initialized in place, i.e., they cannot be assigned +to upon declaration, since the value would be cleared at the end of the creation transaction, +rendering the initialization ineffective. +Transient variables will be :ref:`default value` initialized depending on +their underlying type. +``constant`` and ``immutable`` variables conflict with transient storage, since +their values are either inlined or directly stored in code. + +Transient storage variables have completely independent address space from storage, +so that the order of transient state variables does not affect the layout of storage +state variables and vice-versa. +They do need distinct names though because all state variables share the same namespace. +It is also important to note that the values in transient storage are packed in the +same fashion as those in persistent storage. +See :ref:`Storage Layout ` for more information. + +Besides that, transient variables can have visibility as well and ``public`` ones will +have a getter function generated automatically as usual. + +Note that, currently, such use of ``transient`` as a data location is only allowed for +:ref:`value type ` state variable declarations. +Reference types, such as arrays, mappings and structs, as well as local or parameter +variables are not yet supported. + +An expected canonical use case for transient storage is cheaper reentrancy locks, +which can be readily implemented with the opcodes as showcased next. + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.28; + + contract Generosity { + mapping(address => bool) sentGifts; + bool transient locked; + + modifier nonReentrant { + require(!locked, "Reentrancy attempt"); + locked = true; + _; + // Unlocks the guard, making the pattern composable. + // After the function exits, it can be called again, even in the same transaction. + locked = false; + } + + function claimGift() nonReentrant public { + require(address(this).balance >= 1 ether); + require(!sentGifts[msg.sender]); + (bool success, ) = msg.sender.call{value: 1 ether}(""); + require(success); + + // In a reentrant function, doing this last would open up the vulnerability + sentGifts[msg.sender] = true; + } + } + +Transient storage is private to the contract that owns it, in the same way as persistent storage. +Only owning contract frames may access their transient storage, and when they do, all the frames access the same transient store. + +Transient storage is part of the EVM state and is subject to the same mutability enforcements +as persistent storage. As such, any read access to it is not ``pure`` and writing access is not ``view``. + +If the ``TSTORE`` opcode is called within the context of a ``STATICCALL``, +it will result in an exception instead of performing the modification. +``TLOAD`` is allowed within the context of a ``STATICCALL``. + +When transient storage is used in the context of ``DELEGATECALL`` or ``CALLCODE``, +then the owning contract of the transient storage is the contract that issued ``DELEGATECALL`` +or ``CALLCODE`` instruction (the caller) as with persistent storage. +When transient storage is used in the context of ``CALL`` or ``STATICCALL``, +then the owning contract of the transient storage is the contract that is the target +of the ``CALL`` or ``STATICCALL`` instruction (the callee). + +.. note:: + In the case of ``DELEGATECALL``, since references to transient storage variables + are currently not supported, it is not possible to pass those into library calls. + In libraries, access to transient storage is only possible using inline assembly. + +If a frame reverts, all writes to transient storage that took place between entry +to the frame and the return are reverted, including those that took place in inner calls. +The caller of an external call may employ a ``try ... catch`` block to prevent reverts +bubbling up from the inner calls. + +********************************************************************* +Composability of Smart Contracts and the Caveats of Transient Storage +********************************************************************* + +Given the caveats mentioned in the specification of EIP-1153, +in order to preserve the composability of your smart contract, +utmost care is recommended for more advanced use cases of transient storage. + +For smart contracts, composability is a very important design principle to achieve self-contained behaviour, +such that multiple calls into individual smart contracts can be composed to more complex applications. +So far the EVM largely guaranteed composable behaviour, since multiple calls into a smart contract +within a complex transaction are virtually indistinguishable from multiple calls to the contract +stretched over several transactions. However, transient storage allows a violation of this principle, +and incorrect use may lead to complex bugs that only surface when used across several calls. + +Let's illustrate the problem with a simple example: + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.28; + + contract MulService { + uint transient multiplier; + function setMultiplier(uint mul) external { + multiplier = mul; + } + + function multiply(uint value) external view returns (uint) { + return value * multiplier; + } + } + +and a sequence of external calls: + +.. code-block:: solidity + + setMultiplier(42); + multiply(1); + multiply(2); + +If the example used memory or storage to store the multiplier, it would be fully composable. +It would not matter whether you split the sequence into separate transactions or grouped them in some way. +You would always get the same result: after ``multiplier`` is set to ``42``, the subsequent calls +would return ``42`` and ``84`` respectively. +This enables use cases such as batching calls from multiple transactions +together to reduce gas costs. +Transient storage potentially breaks such use cases since composability can no longer be taken for granted. +In the example, if the calls are not executed in the same transaction, then ``multiplier`` +is reset and the next calls to function ``multiply`` would always return ``0``. + +As another example, since transient storage is constructed as a relatively cheap key-value store, +a smart contract author may be tempted to use transient storage as a replacement for in-memory mappings +without keeping track of the modified keys in the mapping and thereby without clearing the mapping +at the end of the call. +This, however, can easily lead to unexpected behaviour in complex transactions, +in which values set by a previous call into the contract within the same transaction remain. + +The use of transient storage for reentrancy locks that are cleared at the end of the call frame +into the contract, is safe. +However, be sure to resist the temptation to save the 100 gas used for resetting the +reentrancy lock, since failing to do so, will restrict your contract to only one call +within a transaction, preventing its use in complex composed transactions, +which have been a cornerstone for complex applications on chain. + +It is recommend to generally always clear transient storage completely at the end of a call +into your smart contract to avoid these kinds of issues and to simplify +the analysis of the behaviour of your contract within complex transactions. +Check the `Security Considerations section of EIP-1153 `_ +for further details. \ No newline at end of file diff --git a/docs/internals/layout_in_storage.rst b/docs/internals/layout_in_storage.rst index f6b10adee..557a0a0e2 100644 --- a/docs/internals/layout_in_storage.rst +++ b/docs/internals/layout_in_storage.rst @@ -153,7 +153,7 @@ JSON Output .. _storage-layout-top-level: -The storage layout of a contract can be requested via +The storage (or transient storage) layout of a contract can be requested via the :ref:`standard JSON interface `. The output is a JSON object containing two keys, ``storage`` and ``types``. The ``storage`` object is an array where each element has the following form: @@ -218,14 +218,14 @@ the same format as the top-level ``storage`` (see :ref:`above The JSON output format of a contract's storage layout is still considered experimental and is subject to change in non-breaking releases of Solidity. -The following example shows a contract and its storage layout, containing -value and reference types, types that are encoded packed, and nested types. +The following example shows a contract and both its storage and transient storage layout, +containing value and reference types, types that are encoded packed, and nested types. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.0 <0.9.0; + pragma solidity ^0.8.28; contract A { struct S { uint128 a; @@ -235,15 +235,22 @@ value and reference types, types that are encoded packed, and nested types. } uint x; - uint y; + uint transient y; + uint w; + uint transient z; + S s; address addr; + address transient taddr; mapping(uint => mapping(address => bool)) map; uint[] array; string s1; bytes b1; } +Storage Layout +-------------- + .. code-block:: json { @@ -257,15 +264,15 @@ value and reference types, types that are encoded packed, and nested types. "type": "t_uint256" }, { - "astId": 17, + "astId": 19, "contract": "fileA:A", - "label": "y", + "label": "w", "offset": 0, "slot": "1", "type": "t_uint256" }, { - "astId": 20, + "astId": 24, "contract": "fileA:A", "label": "s", "offset": 0, @@ -273,7 +280,7 @@ value and reference types, types that are encoded packed, and nested types. "type": "t_struct(S)13_storage" }, { - "astId": 22, + "astId": 26, "contract": "fileA:A", "label": "addr", "offset": 0, @@ -281,7 +288,7 @@ value and reference types, types that are encoded packed, and nested types. "type": "t_address" }, { - "astId": 28, + "astId": 34, "contract": "fileA:A", "label": "map", "offset": 0, @@ -289,7 +296,7 @@ value and reference types, types that are encoded packed, and nested types. "type": "t_mapping(t_uint256,t_mapping(t_address,t_bool))" }, { - "astId": 31, + "astId": 37, "contract": "fileA:A", "label": "array", "offset": 0, @@ -297,7 +304,7 @@ value and reference types, types that are encoded packed, and nested types. "type": "t_array(t_uint256)dyn_storage" }, { - "astId": 33, + "astId": 39, "contract": "fileA:A", "label": "s1", "offset": 0, @@ -305,7 +312,7 @@ value and reference types, types that are encoded packed, and nested types. "type": "t_string_storage" }, { - "astId": 35, + "astId": 41, "contract": "fileA:A", "label": "b1", "offset": 0, @@ -411,3 +418,49 @@ value and reference types, types that are encoded packed, and nested types. } } } + +Transient Storage Layout +------------------------ + +.. code-block:: json + + { + "storage": [ + { + "astId": 17, + "contract": "fileA:A", + "label": "y", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 21, + "contract": "fileA:A", + "label": "z", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 28, + "contract": "fileA:A", + "label": "taddr", + "offset": 0, + "slot": "2", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } \ No newline at end of file diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index c86005794..45857c3f8 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -415,13 +415,15 @@ In case of an exception that reverts changes, already used up gas is not refunde Since EVM executors can choose to include a transaction or not, transaction senders cannot abuse the system by setting a low gas price. -.. index:: ! storage, ! memory, ! stack +.. index:: ! storage, ! memory, ! stack, ! transient storage -Storage, Memory and the Stack -============================= +.. _locations: + +Storage, Transient Storage, Memory and the Stack +================================================ -The Ethereum Virtual Machine has three areas where it can store data: -storage, memory and the stack. +The Ethereum Virtual Machine has different areas where it can store data with the most +prominent being storage, transient storage, memory and the stack. Each account has a data area called **storage**, which is persistent between function calls and transactions. @@ -432,7 +434,15 @@ you should minimize what you store in persistent storage to what the contract ne Store data like derived calculations, caching, and aggregates outside of the contract. A contract can neither read nor write to any storage apart from its own. -The second data area is called **memory**, of which a contract obtains +Similar to storage, there is another data area called **transient storage**, +where the main difference is that it is reset at the end of each transaction. +The values stored in this data location persist only across function calls originating +from the first call of the transaction. +When the transaction ends, the transient storage is reset and the values stored there +become unavailable to calls in subsequent transactions. +Despite this, the cost of reading and writing to transient storage is significantly lower than for storage. + +The third data area is called **memory**, of which a contract obtains a freshly cleared instance for each message call. Memory is linear and can be addressed at byte level, but reads are limited to a width of 256 bits, while writes can be either 8 bits or 256 bits wide. Memory is expanded by a word (256-bit), when @@ -454,6 +464,31 @@ in order to get deeper access to the stack, but it is not possible to just access arbitrary elements deeper in the stack without first removing the top of the stack. +Calldata, Returndata and Code +============================= + +There are also other data areas which are not as apparent as those discussed previously. +However, they are routinely used during the execution of smart contract transactions. + +The calldata region is the data sent to a transaction as part of a smart contract transaction. +For example, when creating a contract, calldata would be the constructor code of the new contract. +The parameters of external functions are always initially stored in calldata in an ABI-encoded form +and only then decoded into the location specified in their declaration. +If declared as ``memory``, the compiler will eagerly decode them into memory at the beginning of the function, +while marking them as ``calldata`` means that this will be done lazily, only when accessed. +Value types and ``storage`` pointers are decoded directly onto the stack. + +The returndata is the way a smart contract can return a value after a call. +In general, external Solidity functions use the ``return`` keyword to ABI-encode values into the returndata area. + +The code is the region where the EVM instructions of a smart contract are stored. +Code is the bytes read, interpreted, and executed by the EVM during smart contract execution. +Instruction data stored in the code is persistent as part of a contract account state field. +Immutable and constant variables are stored in the code region. +All references to immutables are replaced with the values assigned to them. +A similar process is performed for constants which have their expressions inlined +in the places where they are referenced in the smart contract code. + .. index:: ! instruction Instruction Set diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst index 51d99a803..eebef172f 100644 --- a/docs/structure-of-a-contract.rst +++ b/docs/structure-of-a-contract.rst @@ -21,8 +21,10 @@ which serves to provide a quick overview. State Variables =============== -State variables are variables whose values are permanently stored in contract -storage. +State variables are variables whose values are either permanently stored in contract +storage or, alternatively, temporarily stored in transient storage which is cleaned at +the end of each transaction. +See :ref:`data locations ` for more details. .. code-block:: solidity diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index a6c48d241..4a053d51b 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -28,6 +28,9 @@ annotation, the "data location", about where it is stored. There are three data ``memory``, ``storage`` and ``calldata``. Calldata is a non-modifiable, non-persistent area where function arguments are stored, and behaves mostly like memory. +.. note:: + ``transient`` is not yet supported as a data location for reference types. + .. note:: If you can, try to use ``calldata`` as data location because it will avoid copies and also makes sure that the data cannot be modified. Arrays and structs with ``calldata`` diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 12fcb0b17..27baf5485 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -7,6 +7,12 @@ Value Types The following are called value types because their variables will always be passed by value, i.e. they are always copied when they are used as function arguments or in assignments. +Unlike :ref:`reference types `, value type declarations do not +specify a data location since they are small enough to be stored on the stack. +The only exception are :ref:`state variables `. +Those are by default located in storage, but can also be marked as +:ref:`transient `, :ref:`constant or immutable `. + .. index:: ! bool, ! true, ! false Booleans From 146e2bc1916c49cdc36a65c81272a65f2e62f50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 30 Sep 2024 10:37:58 +0200 Subject: [PATCH 0365/1340] outputPerformanceMetrics(): Add missing std:: prefixes --- libyul/optimiser/Suite.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index d7043e42f..0233a1cf0 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -99,13 +99,13 @@ namespace { #ifdef PROFILE_OPTIMIZER_STEPS -void outputPerformanceMetrics(map const& _metrics) +void outputPerformanceMetrics(std::map const& _metrics) { - vector> durations(_metrics.begin(), _metrics.end()); + std::vector> durations(_metrics.begin(), _metrics.end()); sort( durations.begin(), durations.end(), - [](pair const& _lhs, pair const& _rhs) -> bool + [](std::pair const& _lhs, std::pair const& _rhs) -> bool { return _lhs.second < _rhs.second; } @@ -115,18 +115,18 @@ void outputPerformanceMetrics(map const& _metrics) for (auto&& [step, durationInMicroseconds]: durations) totalDurationInMicroseconds += durationInMicroseconds; - cerr << "Performance metrics of optimizer steps" << endl; - cerr << "======================================" << endl; + std::cerr << "Performance metrics of optimizer steps" << std::endl; + std::cerr << "======================================" << std::endl; constexpr double microsecondsInSecond = 1000000; for (auto&& [step, durationInMicroseconds]: durations) { double percentage = 100.0 * static_cast(durationInMicroseconds) / static_cast(totalDurationInMicroseconds); double sec = static_cast(durationInMicroseconds) / microsecondsInSecond; - cerr << fmt::format("{:>7.3f}% ({} s): {}", percentage, sec, step) << endl; + std::cerr << fmt::format("{:>7.3f}% ({} s): {}", percentage, sec, step) << std::endl; } double totalDurationInSeconds = static_cast(totalDurationInMicroseconds) / microsecondsInSecond; - cerr << "--------------------------------------" << endl; - cerr << fmt::format("{:>7}% ({:.3f} s)", 100, totalDurationInSeconds) << endl; + std::cerr << "--------------------------------------" << std::endl; + std::cerr << fmt::format("{:>7}% ({:.3f} s)", 100, totalDurationInSeconds) << std::endl; } #endif From c6df88707f36bf94ffb62858bcabfdba7b80bbe7 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 30 Sep 2024 12:14:29 +0200 Subject: [PATCH 0366/1340] Fix evmone MacOS link --- test/Common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Common.h b/test/Common.h index 3adb980a0..409d6f696 100644 --- a/test/Common.h +++ b/test/Common.h @@ -37,7 +37,7 @@ static constexpr auto evmoneFilename = "evmone.dll"; static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-windows-amd64.zip"; #elif defined(__APPLE__) static constexpr auto evmoneFilename = "libevmone.dylib"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-darwin-x86_64.tar.gz"; +static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-darwin-arm64.tar.gz"; #else static constexpr auto evmoneFilename = "libevmone.so"; static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz"; From 891b7c83d7cbc551c8b3a74cb67bcd6ea26ad96a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 26 Sep 2024 18:38:40 +0200 Subject: [PATCH 0367/1340] Do not cache instances of Compiler in CompilerStack --- libsolidity/interface/CompilerStack.cpp | 14 +++++++++----- libsolidity/interface/CompilerStack.h | 4 +++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index bac358a93..8dd390f5e 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -861,15 +861,18 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run c.generatedSources; return sources.init([&]{ Json sources = Json::array(); - // If there is no compiler, then no bytecode was generated and thus no + + solAssert(c.generatedYulUtilityCode.has_value() == c.runtimeGeneratedYulUtilityCode.has_value()); + + // If there is no generated utility code, then no bytecode was generated and thus no // sources were generated (or we compiled "via IR"). - if (c.compiler) + if (c.runtimeGeneratedYulUtilityCode.has_value()) { solAssert(!m_viaIR, ""); std::string source = _runtime ? - c.compiler->runtimeGeneratedYulUtilityCode() : - c.compiler->generatedYulUtilityCode(); + *c.runtimeGeneratedYulUtilityCode : + *c.generatedYulUtilityCode; if (!source.empty()) { std::string sourceName = CompilerContext::yulUtilityFileName(); @@ -1469,13 +1472,14 @@ void CompilerStack::compileContract( Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName()); std::shared_ptr compiler = std::make_shared(m_evmVersion, m_revertStrings, m_optimiserSettings); - compiledContract.compiler = compiler; solAssert(!m_viaIR, ""); bytes cborEncodedMetadata = createCBORMetadata(compiledContract, /* _forIR */ false); // Run optimiser and compile the contract. compiler->compileContract(_contract, _otherCompilers, cborEncodedMetadata); + compiledContract.generatedYulUtilityCode = compiler->generatedYulUtilityCode(); + compiledContract.runtimeGeneratedYulUtilityCode = compiler->runtimeGeneratedYulUtilityCode(); _otherCompilers[compiledContract.contract] = compiler; diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index c0166af96..f167477fa 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -409,9 +409,11 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac struct Contract { ContractDefinition const* contract = nullptr; - std::shared_ptr compiler; + std::shared_ptr evmAssembly; std::shared_ptr evmRuntimeAssembly; + std::optional generatedYulUtilityCode; ///< Extra Yul utility code that was used when compiling the creation assembly + std::optional runtimeGeneratedYulUtilityCode; ///< Extra Yul utility code that was used when compiling the deployed assembly evmasm::LinkerObject object; ///< Deployment object (includes the runtime sub-object). evmasm::LinkerObject runtimeObject; ///< Runtime object. std::string yulIR; ///< Yul IR code straight from the code generator. From 3c5e46b7d75172114413c7c775c412ffc41d9d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 26 Sep 2024 23:16:19 +0200 Subject: [PATCH 0368/1340] CompilerStack: Do not cache the JSON representation of generated sources --- libsolidity/interface/CompilerStack.cpp | 60 +++++++++++-------------- libsolidity/interface/CompilerStack.h | 2 - 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 8dd390f5e..a9f2708d8 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -855,43 +855,35 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); Contract const& c = contract(_contractName); - util::LazyInit const& sources = - _runtime ? - c.runtimeGeneratedSources : - c.generatedSources; - return sources.init([&]{ - Json sources = Json::array(); - + Json sources = Json::array(); + // If there is no compiler, then no bytecode was generated and thus no + // sources were generated (or we compiled "via IR"). + if (c.runtimeGeneratedYulUtilityCode.has_value()) + { solAssert(c.generatedYulUtilityCode.has_value() == c.runtimeGeneratedYulUtilityCode.has_value()); - - // If there is no generated utility code, then no bytecode was generated and thus no - // sources were generated (or we compiled "via IR"). - if (c.runtimeGeneratedYulUtilityCode.has_value()) + solAssert(!m_viaIR); + std::string source = + _runtime ? + *c.runtimeGeneratedYulUtilityCode : + *c.generatedYulUtilityCode; + if (!source.empty()) { - solAssert(!m_viaIR, ""); - std::string source = - _runtime ? - *c.runtimeGeneratedYulUtilityCode : - *c.generatedYulUtilityCode; - if (!source.empty()) - { - std::string sourceName = CompilerContext::yulUtilityFileName(); - unsigned sourceIndex = sourceIndices()[sourceName]; - ErrorList errors; - ErrorReporter errorReporter(errors); - CharStream charStream(source, sourceName); - yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); - std::shared_ptr parserResult = yul::Parser{errorReporter, dialect}.parse(charStream); - solAssert(parserResult, ""); - sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex}(parserResult->root()); - sources[0]["name"] = sourceName; - sources[0]["id"] = sourceIndex; - sources[0]["language"] = "Yul"; - sources[0]["contents"] = std::move(source); - } + std::string sourceName = CompilerContext::yulUtilityFileName(); + unsigned sourceIndex = sourceIndices()[sourceName]; + ErrorList errors; + ErrorReporter errorReporter(errors); + CharStream charStream(source, sourceName); + yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); + std::shared_ptr parserResult = yul::Parser{errorReporter, dialect}.parse(charStream); + solAssert(parserResult); + sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex}(parserResult->root()); + sources[0]["name"] = sourceName; + sources[0]["id"] = sourceIndex; + sources[0]["language"] = "Yul"; + sources[0]["contents"] = std::move(source); } - return sources; - }); + } + return sources; } std::string const* CompilerStack::sourceMapping(std::string const& _contractName) const diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index f167477fa..2b891293b 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -424,8 +424,6 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac util::LazyInit transientStorageLayout; util::LazyInit userDocumentation; util::LazyInit devDocumentation; - util::LazyInit generatedSources; - util::LazyInit runtimeGeneratedSources; mutable std::optional sourceMapping; mutable std::optional runtimeSourceMapping; }; From 6bee17d21c8d17ade1b459ea9c33141e79011534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 16 Sep 2024 10:35:49 +0200 Subject: [PATCH 0369/1340] CompilerStack: Add missing members to reset() --- libsolidity/interface/CompilerStack.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index a9f2708d8..4d3bacabc 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -313,7 +313,9 @@ void CompilerStack::reset(bool _keepSettings) m_libraries.clear(); m_viaIR = false; m_evmVersion = langutil::EVMVersion(); + m_eofVersion.reset(); m_modelCheckerSettings = ModelCheckerSettings{}; + m_requestedContractNames.clear(); m_irOutputSelection = IROutputSelection::None; m_revertStrings = RevertStrings::Default; m_optimiserSettings = OptimiserSettings::minimal(); @@ -321,6 +323,7 @@ void CompilerStack::reset(bool _keepSettings) m_metadataFormat = defaultMetadataFormat(); m_metadataHash = MetadataHash::IPFS; m_stopAfter = State::CompilationSuccessful; + m_compilationSourceType = CompilationSourceType::Solidity; } m_experimentalAnalysis.reset(); m_globalContext.reset(); From a4fa88646c1ec0a44f2a2b80ee7ae64a1d0de05b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 16 Sep 2024 13:58:39 +0200 Subject: [PATCH 0370/1340] StandardCompiler: Fix bad `if` indent triggering a warning --- libsolidity/interface/StandardCompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 06df8a940..34c9f21a0 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1434,7 +1434,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu Json output; if (errors.size() > 0) - output["errors"] = std::move(errors); + output["errors"] = std::move(errors); if (!compilerStack.unhandledSMTLib2Queries().empty()) for (std::string const& query: compilerStack.unhandledSMTLib2Queries()) From a9d9143007f6a5fb9aa16378b8cfec0a926d70ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 16 Sep 2024 14:36:38 +0200 Subject: [PATCH 0371/1340] Pass selected outputs down to CompilerStack to avoid generating them when not requested --- Changelog.md | 1 + libsolidity/interface/CompilerStack.cpp | 62 ++++++++----- libsolidity/interface/CompilerStack.h | 86 +++++++++++++------ libsolidity/interface/StandardCompiler.cpp | 69 +++++++-------- solc/CommandLineInterface.cpp | 23 ++--- .../SolidityExecutionFramework.cpp | 1 - 6 files changed, 149 insertions(+), 93 deletions(-) diff --git a/Changelog.md b/Changelog.md index b23b5ff9e..b171b6dd0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Language Features: Compiler Features: * Code Generator: Transient storage value type state variables are now supported. * General: Generate JSON representations of Yul ASTs only on demand to reduce memory usage. + * Standard JSON Interface: Bytecode or IR can now be requested for a subset of all contracts without triggering unnecessary code generation for other contracts. Bugfixes: diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 4d3bacabc..39977629d 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -250,6 +250,12 @@ void CompilerStack::setModelCheckerSettings(ModelCheckerSettings _settings) m_modelCheckerSettings = _settings; } +void CompilerStack::selectContracts(ContractSelection const& _selectedContracts) +{ + solAssert(m_stackState < ParsedAndImported, "Must request outputs before parsing."); + m_selectedContracts = _selectedContracts; +} + void CompilerStack::setLibraries(std::map const& _libraries) { solAssert(m_stackState < ParsedAndImported, "Must set libraries before parsing."); @@ -315,8 +321,7 @@ void CompilerStack::reset(bool _keepSettings) m_evmVersion = langutil::EVMVersion(); m_eofVersion.reset(); m_modelCheckerSettings = ModelCheckerSettings{}; - m_requestedContractNames.clear(); - m_irOutputSelection = IROutputSelection::None; + m_selectedContracts.clear(); m_revertStrings = RevertStrings::Default; m_optimiserSettings = OptimiserSettings::minimal(); m_metadataLiteralSources = false; @@ -690,21 +695,21 @@ bool CompilerStack::parseAndAnalyze(State _stopAfter) bool CompilerStack::isRequestedSource(std::string const& _sourceName) const { return - m_requestedContractNames.empty() || - m_requestedContractNames.count("") || - m_requestedContractNames.count(_sourceName); + m_selectedContracts.empty() || + m_selectedContracts.count("") || + m_selectedContracts.count(_sourceName); } bool CompilerStack::isRequestedContract(ContractDefinition const& _contract) const { - /// In case nothing was specified in outputSelection. - if (m_requestedContractNames.empty()) + /// In case nothing was specified in selectedContracts. + if (m_selectedContracts.empty()) return true; for (auto const& key: std::vector{"", _contract.sourceUnitName()}) { - auto const& it = m_requestedContractNames.find(key); - if (it != m_requestedContractNames.end()) + auto const& it = m_selectedContracts.find(key); + if (it != m_selectedContracts.end()) if (it->second.count(_contract.name()) || it->second.count("")) return true; } @@ -712,6 +717,28 @@ bool CompilerStack::isRequestedContract(ContractDefinition const& _contract) con return false; } +CompilerStack::PipelineConfig CompilerStack::requestedPipelineConfig(ContractDefinition const& _contract) const +{ + static PipelineConfig constexpr defaultPipelineConfig = PipelineConfig{ + false, // irCodegen + false, // irOptimization + true, // bytecode + }; + + // If nothing was explicitly selected, all contracts are selected by default. + if (m_selectedContracts.empty()) + return defaultPipelineConfig; + + PipelineConfig combinedConfig; + for (std::string const& sourceUnitName: {""s, _contract.sourceUnitName()}) + if (m_selectedContracts.count(sourceUnitName) != 0) + for (std::string const& contractName: {""s, _contract.name()}) + if (m_selectedContracts.at(sourceUnitName).count(contractName) != 0) + combinedConfig = combinedConfig | m_selectedContracts.at(sourceUnitName).at(contractName); + + return combinedConfig; +} + bool CompilerStack::compile(State _stopAfter) { m_stopAfter = _stopAfter; @@ -730,20 +757,13 @@ bool CompilerStack::compile(State _stopAfter) if (auto contract = dynamic_cast(node.get())) if (isRequestedContract(*contract)) { + PipelineConfig pipelineConfig = requestedPipelineConfig(*contract); + try { - // NOTE: Bytecode generation via IR always uses Contract::yulIROptimized. - // When optimization is not enabled, that member simply contains unoptimized code. - bool needIROutput = - (m_generateEvmBytecode && m_viaIR) || - m_irOutputSelection != IROutputSelection::None; - bool needUnoptimizedIROutputOnly = - !(m_generateEvmBytecode && m_viaIR) && - m_irOutputSelection != IROutputSelection::UnoptimizedAndOptimized; - - if (needIROutput) - generateIR(*contract, needUnoptimizedIROutputOnly); - if (m_generateEvmBytecode) + if (pipelineConfig.needIR(m_viaIR)) + generateIR(*contract, pipelineConfig.needIRCodegenOnly(m_viaIR)); + if (pipelineConfig.needBytecode()) { if (m_viaIR) generateEVMFromIR(*contract); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 2b891293b..8ce2c5d62 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -133,12 +133,54 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac SolidityAST, }; - enum class IROutputSelection { - None, - UnoptimizedOnly, - UnoptimizedAndOptimized, + /// Indicates which stages of the compilation pipeline were explicitly requested and provides + /// logic to determine which ones are effectively needed to accomplish that. + /// Note that parsing and analysis are not selectable, since they cannot be skipped. + struct PipelineConfig + { + bool irCodegen = false; ///< Want IR output straight from code generator. + bool irOptimization = false; ///< Want reparsed IR that went through YulStack. May be optimized or not, depending on settings. + bool bytecode = false; ///< Want EVM-level outputs, especially EVM assembly and bytecode. May be optimized or not, depending on settings. + + bool needIR(bool _viaIR) const + { + return + irCodegen || + irOptimization || + (bytecode && _viaIR); + } + + bool needIRCodegenOnly(bool _viaIR) const + { + return !(bytecode && _viaIR) && !irOptimization; + } + + bool needBytecode() const + { + return bytecode; + } + + PipelineConfig operator|(PipelineConfig const& _other) const + { + return { + irCodegen || _other.irCodegen, + irOptimization || _other.irOptimization, + bytecode || _other.bytecode, + }; + } + + bool operator!=(PipelineConfig const& _other) const { return !(*this == _other); } + bool operator==(PipelineConfig const& _other) const + { + return + irCodegen == _other.irCodegen && + irOptimization == _other.irOptimization && + bytecode == _other.bytecode; + } }; + using ContractSelection = std::map>; + /// Creates a new compiler stack. /// @param _readFile callback used to read files for import statements. Must return /// and must not emit exceptions. @@ -193,26 +235,13 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// Set model checker settings. void setModelCheckerSettings(ModelCheckerSettings _settings); - /// Sets the requested contract names by source. - /// If empty, no filtering is performed and every contract - /// found in the supplied sources is compiled. - /// Names are cleared iff @a _contractNames is missing. - void setRequestedContractNames(std::map> const& _contractNames = std::map>{}) - { - m_requestedContractNames = _contractNames; - } - - /// Enable EVM Bytecode generation. This is enabled by default. - void enableEvmBytecodeGeneration(bool _enable = true) { m_generateEvmBytecode = _enable; } - - /// Enable generation of Yul IR code so that IR output can be safely requested for all contracts. - /// Note that IR may also be implicitly generated when not requested. In particular - /// @a setViaIR(true) requires access to the IR outputs for bytecode generation. - void requestIROutputs(IROutputSelection _selection = IROutputSelection::UnoptimizedAndOptimized) - { - solAssert(m_stackState < ParsedAndImported); - m_irOutputSelection = _selection; - } + /// Sets names of the contracts from each source that should be compiled. + /// If empty, no filtering is performed and every contract found in the supplied sources goes + /// through the default pipeline stages (bytecode-only, no IR). + /// Source/contract names are not validated - ones that do not exist are ignored. + /// The empty source/contract name can be used as a wildcard that matches all sources/contracts. + /// If a contract matches more than one entry, the pipeline selection from all matches is combined. + void selectContracts(ContractSelection const& _selectedContracts); /// @arg _metadataLiteralSources When true, store sources as literals in the contract metadata. /// Must be set before parsing. @@ -450,6 +479,11 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// @returns true if the contract is requested to be compiled. bool isRequestedContract(ContractDefinition const& _contract) const; + /// @returns The effective pipeline configuration for a given contract. + /// Applies defaults for contracts that were not explicitly selected and combines + /// multiple entries if the contact is matched by wildcards. + PipelineConfig requestedPipelineConfig(ContractDefinition const& _contract) const; + /// Perform the analysis steps of legacy language mode. /// @returns false on error. bool analyzeLegacy(bool _noErrorsSoFar); @@ -554,9 +588,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac langutil::EVMVersion m_evmVersion; std::optional m_eofVersion; ModelCheckerSettings m_modelCheckerSettings; - std::map> m_requestedContractNames; - bool m_generateEvmBytecode = true; - IROutputSelection m_irOutputSelection = IROutputSelection::None; + ContractSelection m_selectedContracts; std::map m_libraries; ImportRemapper m_importRemapper; std::map m_sources; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 34c9f21a0..d8ce4f2d0 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -150,21 +150,6 @@ Json formatErrorWithException( return error; } -std::map> requestedContractNames(Json const& _outputSelection) -{ - std::map> contracts; - for (auto const& [sourceName, _]: _outputSelection.items()) - { - std::string key = (sourceName == "*") ? "" : sourceName; - for (auto const& [contractName, _]: _outputSelection[sourceName].items()) - { - std::string value = (contractName == "*") ? "" : contractName; - contracts[key].insert(value); - } - } - return contracts; -} - /// Returns true iff @a _hash (hex with 0x prefix) is the Keccak256 hash of the binary data in @a _content. bool hashMatchesContent(std::string const& _hash, std::string const& _content) { @@ -298,26 +283,45 @@ bool isEvmBytecodeRequested(Json const& _outputSelection) return false; } -/// @returns The IR output selection for CompilerStack, based on outputs requested in the JSON. +/// @returns The set of selected contracts, along with their compiler pipeline configuration, based +/// on outputs requested in the JSON. Translates wildcards to the ones understood by CompilerStack. /// Note that as an exception, '*' does not yet match "ir", "irAst", "irOptimized" or "irOptimizedAst". -CompilerStack::IROutputSelection irOutputSelection(Json const& _outputSelection) +CompilerStack::ContractSelection pipelineConfig( + Json const& _jsonOutputSelection +) { - if (!_outputSelection.is_object()) - return CompilerStack::IROutputSelection::None; + if (!_jsonOutputSelection.is_object()) + return {}; - CompilerStack::IROutputSelection selection = CompilerStack::IROutputSelection::None; - for (auto const& fileRequests: _outputSelection) - for (auto const& requests: fileRequests) - for (auto const& request: requests) + CompilerStack::ContractSelection contractSelection; + for (auto const& [sourceUnitName, jsonOutputSelectionForSource]: _jsonOutputSelection.items()) + { + solAssert(jsonOutputSelectionForSource.is_object()); + for (auto const& [contractName, jsonOutputSelectionForContract]: jsonOutputSelectionForSource.items()) + { + solAssert(jsonOutputSelectionForContract.is_array()); + CompilerStack::PipelineConfig pipelineForContract; + for (Json const& request: jsonOutputSelectionForContract) { - if (request == "irOptimized" || request == "irOptimizedAst" || request == "yulCFGJson") - return CompilerStack::IROutputSelection::UnoptimizedAndOptimized; - - if (request == "ir" || request == "irAst") - selection = CompilerStack::IROutputSelection::UnoptimizedOnly; + solAssert(request.is_string()); + pipelineForContract.irOptimization = + pipelineForContract.irOptimization || + request == "irOptimized" || + request == "irOptimizedAst" || + request == "yulCFGJson"; + pipelineForContract.irCodegen = + pipelineForContract.irCodegen || + pipelineForContract.irOptimization || + request == "ir" || + request == "irAst"; + pipelineForContract.bytecode = isEvmBytecodeRequested(_jsonOutputSelection); } - - return selection; + std::string key = (sourceUnitName == "*") ? "" : sourceUnitName; + std::string value = (contractName == "*") ? "" : contractName; + contractSelection[key][value] = pipelineForContract; + } + } + return contractSelection; } Json formatLinkReferences(std::map const& linkReferences) @@ -1321,12 +1325,9 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu compilerStack.useMetadataLiteralSources(_inputsAndSettings.metadataLiteralSources); compilerStack.setMetadataFormat(_inputsAndSettings.metadataFormat); compilerStack.setMetadataHash(_inputsAndSettings.metadataHash); - compilerStack.setRequestedContractNames(requestedContractNames(_inputsAndSettings.outputSelection)); + compilerStack.selectContracts(pipelineConfig(_inputsAndSettings.outputSelection)); compilerStack.setModelCheckerSettings(_inputsAndSettings.modelCheckerSettings); - compilerStack.enableEvmBytecodeGeneration(isEvmBytecodeRequested(_inputsAndSettings.outputSelection)); - compilerStack.requestIROutputs(irOutputSelection(_inputsAndSettings.outputSelection)); - Json errors = std::move(_inputsAndSettings.errors); bool const binariesRequested = isBinaryRequested(_inputsAndSettings.outputSelection); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 2d815facc..b791de3ef 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -889,14 +889,16 @@ void CommandLineInterface::compile() if (m_options.output.debugInfoSelection.has_value()) m_compiler->selectDebugInfo(m_options.output.debugInfoSelection.value()); - CompilerStack::IROutputSelection irOutputSelection = CompilerStack::IROutputSelection::None; - if (m_options.compiler.outputs.irOptimized || m_options.compiler.outputs.irOptimizedAstJson || m_options.compiler.outputs.yulCFGJson) - irOutputSelection = CompilerStack::IROutputSelection::UnoptimizedAndOptimized; - else if (m_options.compiler.outputs.ir || m_options.compiler.outputs.irAstJson) - irOutputSelection = CompilerStack::IROutputSelection::UnoptimizedOnly; - - m_compiler->requestIROutputs(irOutputSelection); - m_compiler->enableEvmBytecodeGeneration( + CompilerStack::PipelineConfig pipelineConfig; + pipelineConfig.irOptimization = + m_options.compiler.outputs.irOptimized || + m_options.compiler.outputs.irOptimizedAstJson || + m_options.compiler.outputs.yulCFGJson; + pipelineConfig.irCodegen = + pipelineConfig.irOptimization || + m_options.compiler.outputs.ir || + m_options.compiler.outputs.irAstJson; + pipelineConfig.bytecode = m_options.compiler.estimateGas || m_options.compiler.outputs.asm_ || m_options.compiler.outputs.asmJson || @@ -914,8 +916,9 @@ void CommandLineInterface::compile() m_options.compiler.combinedJsonRequests->srcMapRuntime || m_options.compiler.combinedJsonRequests->funDebug || m_options.compiler.combinedJsonRequests->funDebugRuntime - )) - ); + )); + + m_compiler->selectContracts({{"", {{"", pipelineConfig}}}}); m_compiler->setOptimiserSettings(m_options.optimiserSettings()); diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index 27fb39c12..57d4d9d9b 100644 --- a/test/libsolidity/SolidityExecutionFramework.cpp +++ b/test/libsolidity/SolidityExecutionFramework.cpp @@ -60,7 +60,6 @@ bytes SolidityExecutionFramework::multiSourceCompileContract( m_compiler.setEVMVersion(m_evmVersion); m_compiler.setEOFVersion(m_eofVersion); m_compiler.setOptimiserSettings(m_optimiserSettings); - m_compiler.enableEvmBytecodeGeneration(true); m_compiler.setViaIR(m_compileViaYul); m_compiler.setRevertStringBehaviour(m_revertStrings); if (!m_appendCBORMetadata) { From 8d8ac1c376c75ab1f5a9a1b8b6d0a3e18d0f47af Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 1 Oct 2024 22:29:34 +0200 Subject: [PATCH 0372/1340] eof: Pass `eofVersion` flag to `EVMDialect` --- liblangutil/EVMVersion.cpp | 26 +- liblangutil/EVMVersion.h | 2 +- libsolidity/ast/ASTJsonExporter.cpp | 11 +- libsolidity/ast/ASTJsonImporter.cpp | 11 +- libsolidity/ast/ASTJsonImporter.h | 6 +- libsolidity/codegen/CompilerContext.cpp | 3 +- libsolidity/codegen/ContractCompiler.cpp | 1 + libsolidity/interface/CompilerStack.cpp | 7 +- libsolidity/parsing/Parser.cpp | 2 +- libsolidity/parsing/Parser.h | 7 +- libyul/AsmAnalysis.cpp | 3 +- libyul/ObjectOptimizer.cpp | 8 +- libyul/ObjectOptimizer.h | 3 +- libyul/YulStack.cpp | 13 +- libyul/backends/evm/AsmCodeGen.cpp | 3 +- libyul/backends/evm/AsmCodeGen.h | 1 + libyul/backends/evm/EVMDialect.cpp | 232 +++++++++--------- libyul/backends/evm/EVMDialect.h | 8 +- libyul/backends/evm/NoOutputAssembly.cpp | 2 +- test/libsolidity/Assembly.cpp | 6 +- test/libsolidity/MemoryGuardTest.cpp | 2 +- .../SolidityExpressionCompiler.cpp | 6 +- test/libsolidity/SolidityParser.cpp | 3 +- test/libyul/Common.cpp | 15 +- test/libyul/Common.h | 2 +- test/libyul/CompilabilityChecker.cpp | 6 +- test/libyul/ControlFlowGraphTest.cpp | 6 +- test/libyul/ControlFlowSideEffectsTest.cpp | 3 +- test/libyul/EVMCodeTransformTest.cpp | 4 +- test/libyul/FunctionSideEffects.cpp | 3 +- test/libyul/KnowledgeBaseTest.cpp | 3 +- test/libyul/ObjectParser.cpp | 3 +- test/libyul/Parser.cpp | 129 ++++++---- test/libyul/SSAControlFlowGraphTest.cpp | 6 +- test/libyul/StackLayoutGeneratorTest.cpp | 6 +- test/libyul/SyntaxTest.cpp | 6 +- test/libyul/YulInterpreterTest.cpp | 2 +- test/libyul/YulOptimizerTest.cpp | 6 +- .../tools/ossfuzz/StackReuseCodegenFuzzer.cpp | 3 +- test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 5 +- test/tools/ossfuzz/yulProtoFuzzer.cpp | 3 +- test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp | 9 +- test/tools/yulopti.cpp | 2 +- test/tools/yulrun.cpp | 2 +- tools/yulPhaser/Program.cpp | 3 +- 45 files changed, 371 insertions(+), 222 deletions(-) diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index 438932a1c..6435e0f15 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -26,23 +26,26 @@ using namespace solidity; using namespace solidity::evmasm; using namespace solidity::langutil; -bool EVMVersion::hasOpcode(Instruction _opcode) const +bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersion) const { + // EOF version can be only defined since prague + assert(!_eofVersion.has_value() || this->m_version >= prague()); + switch (_opcode) { case Instruction::RETURNDATACOPY: case Instruction::RETURNDATASIZE: return supportsReturndata(); case Instruction::STATICCALL: - return hasStaticCall(); + return !_eofVersion.has_value() && hasStaticCall(); case Instruction::SHL: case Instruction::SHR: case Instruction::SAR: return hasBitwiseShifting(); case Instruction::CREATE2: - return hasCreate2(); + return !_eofVersion.has_value() && hasCreate2(); case Instruction::EXTCODEHASH: - return hasExtCodeHash(); + return !_eofVersion.has_value() && hasExtCodeHash(); case Instruction::CHAINID: return hasChainID(); case Instruction::SELFBALANCE: @@ -58,6 +61,21 @@ bool EVMVersion::hasOpcode(Instruction _opcode) const case Instruction::TSTORE: case Instruction::TLOAD: return supportsTransientStorage(); + // Instructions below are deprecated in EOF + case Instruction::CALL: + case Instruction::CALLCODE: + case Instruction::DELEGATECALL: + case Instruction::SELFDESTRUCT: + case Instruction::JUMP: + case Instruction::JUMPI: + case Instruction::PC: + case Instruction::CREATE: + case Instruction::CODESIZE: + case Instruction::CODECOPY: + case Instruction::EXTCODESIZE: + case Instruction::EXTCODECOPY: + case Instruction::GAS: + return !_eofVersion.has_value(); default: return true; } diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 774268917..3d58fed43 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -124,7 +124,7 @@ class EVMVersion: bool hasMcopy() const { return *this >= cancun(); } bool supportsTransientStorage() const { return *this >= cancun(); } - bool hasOpcode(evmasm::Instruction _opcode) const; + bool hasOpcode(evmasm::Instruction _opcode, std::optional _eofVersion) const; /// Whether we have to retain the costs for the call opcode itself (false), /// or whether we can just forward easily all remaining gas (true). diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 910cc257e..7183c64a3 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -664,12 +664,21 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) for (Json& it: externalReferences | ranges::views::values) externalReferencesJson.emplace_back(std::move(it)); + auto const& evmDialect = dynamic_cast(_node.dialect()); + std::vector> attributes = { std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations().root()))), std::make_pair("externalReferences", std::move(externalReferencesJson)), - std::make_pair("evmVersion", dynamic_cast(_node.dialect()).evmVersion().name()) + std::make_pair("evmVersion", evmDialect.evmVersion().name()) }; + // TODO: Add test in test/linsolidity/ASTJSON/assembly. This requires adding support for eofVersion in ASTJSONTest + if (evmDialect.eofVersion()) + { + solAssert(*evmDialect.eofVersion() > 0); + attributes.push_back(std::make_pair("eofVersion", *evmDialect.eofVersion())); + } + if (_node.flags()) { Json flags = Json::array(); diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 8d72b41f7..ee52bf53c 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -720,7 +720,16 @@ ASTPointer ASTJsonImporter::createInlineAssembly(Json const& _no astAssert(evmVersion.has_value(), "Invalid EVM version!"); astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!"); - yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value()); + // TODO: Add test in test/linsolidity/ASTJSON/assembly. This requires adding support for eofVersion in ASTJSONTest + std::optional eofVersion; + if (auto const it = _node.find("eofVersion"); it != _node.end()) + { + eofVersion = it->get(); + astAssert(eofVersion > 0); + } + astAssert(m_eofVersion == eofVersion, "Imported tree EOF version differs from configured EOF version!"); + + yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value(), eofVersion); ASTPointer>> flags; if (_node.contains("flags")) { diff --git a/libsolidity/ast/ASTJsonImporter.h b/libsolidity/ast/ASTJsonImporter.h index 943415df9..e4a7c2da3 100644 --- a/libsolidity/ast/ASTJsonImporter.h +++ b/libsolidity/ast/ASTJsonImporter.h @@ -40,8 +40,8 @@ namespace solidity::frontend class ASTJsonImporter { public: - ASTJsonImporter(langutil::EVMVersion _evmVersion) - :m_evmVersion(_evmVersion) + ASTJsonImporter(langutil::EVMVersion _evmVersion, std::optional _eofVersion) + :m_evmVersion(_evmVersion), m_eofVersion(_eofVersion) {} /// Converts the AST from JSON-format to ASTPointer @@ -166,6 +166,8 @@ class ASTJsonImporter std::set m_usedIDs; /// Configured EVM version langutil::EVMVersion m_evmVersion; + /// Configured EOF version. Equals std::nullopt if non-EOF + std::optional m_eofVersion; }; } diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 83b4589fe..4a0f636dc 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -436,7 +436,7 @@ void CompilerContext::appendInlineAssembly( ErrorList errors; ErrorReporter errorReporter(errors); langutil::CharStream charStream(_assembly, _sourceName); - yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); + yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion, std::nullopt); std::optional locationOverride; if (!_system) locationOverride = m_asm->currentSourceLocation(); @@ -522,6 +522,7 @@ void CompilerContext::appendInlineAssembly( analysisInfo, *m_asm, m_evmVersion, + std::nullopt, identifierAccess.generateCode, _system, _optimiserSettings.optimizeStackAllocation diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 5ed6e8f96..96b1ea548 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -958,6 +958,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) *analysisInfo, *m_context.assemblyPtr(), m_context.evmVersion(), + std::nullopt, identifierAccessCodeGen, false, m_optimiserSettings.optimizeStackAllocation diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 39977629d..c68df205f 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -357,7 +357,7 @@ bool CompilerStack::parse() try { - Parser parser{m_errorReporter, m_evmVersion}; + Parser parser{m_errorReporter, m_evmVersion, m_eofVersion}; std::vector sourcesToParse; for (auto const& s: m_sources) @@ -427,7 +427,8 @@ bool CompilerStack::parse() void CompilerStack::importASTs(std::map const& _sources) { solAssert(m_stackState == Empty, "Must call importASTs only before the SourcesSet state."); - std::map> reconstructedSources = ASTJsonImporter(m_evmVersion).jsonToSourceUnit(_sources); + std::map> reconstructedSources = + ASTJsonImporter(m_evmVersion, m_eofVersion).jsonToSourceUnit(_sources); for (auto& src: reconstructedSources) { solUnimplementedAssert(!src.second->experimentalSolidity()); @@ -896,7 +897,7 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run ErrorList errors; ErrorReporter errorReporter(errors); CharStream charStream(source, sourceName); - yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); + yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion, m_eofVersion); std::shared_ptr parserResult = yul::Parser{errorReporter, dialect}.parse(charStream); solAssert(parserResult); sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex}(parserResult->root()); diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 208d74463..13303170d 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1448,7 +1448,7 @@ ASTPointer Parser::parseInlineAssembly(ASTPointer con SourceLocation location = currentLocation(); expectToken(Token::Assembly); - yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); + yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion, m_eofVersion); if (m_scanner->currentToken() == Token::StringLiteral) { if (m_scanner->currentLiteral() != "evmasm") diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 8f0868ac1..830df05c2 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -40,10 +40,12 @@ class Parser: public langutil::ParserBase public: explicit Parser( langutil::ErrorReporter& _errorReporter, - langutil::EVMVersion _evmVersion + langutil::EVMVersion _evmVersion, + std::optional _eofVersion ): ParserBase(_errorReporter), - m_evmVersion(_evmVersion) + m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion) {} ASTPointer parse(langutil::CharStream& _charStream); @@ -247,6 +249,7 @@ class Parser: public langutil::ParserBase /// Flag that signifies whether '_' is parsed as a PlaceholderStatement or a regular identifier. bool m_insideModifier = false; langutil::EVMVersion m_evmVersion; + std::optional m_eofVersion; /// Counter for the next AST node ID int64_t m_currentNodeID = 0; /// Flag that indicates whether experimental mode is enabled in the current source unit diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 64630fa2b..cf8c720f6 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -625,7 +625,8 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location) { // NOTE: This function uses the default EVM version instead of the currently selected one. - auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}).builtin(YulName(_instructionIdentifier)); + // TODO: Add EOF support + auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt).builtin(YulName(_instructionIdentifier)); if (builtin && builtin->instruction.has_value()) return validateInstructions(builtin->instruction.value(), _location); else diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index 3694367c5..511fc979d 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -43,13 +43,13 @@ using namespace solidity::util; using namespace solidity::yul; -Dialect const& yul::languageToDialect(Language _language, EVMVersion _version) +Dialect const& yul::languageToDialect(Language _language, EVMVersion _version, std::optional _eofVersion) { switch (_language) { case Language::Assembly: case Language::StrictAssembly: - return EVMDialect::strictAssemblyForEVMObjects(_version); + return EVMDialect::strictAssemblyForEVMObjects(_version, _eofVersion); } util::unreachable(); } @@ -77,7 +77,7 @@ void ObjectOptimizer::optimize(Object& _object, Settings const& _settings, bool ); } - Dialect const& dialect = languageToDialect(_settings.language, _settings.evmVersion); + Dialect const& dialect = languageToDialect(_settings.language, _settings.evmVersion, _settings.eofVersion); std::unique_ptr meter; if (EVMDialect const* evmDialect = dynamic_cast(&dialect)) meter = std::make_unique(*evmDialect, _isCreation, _settings.expectedExecutionsPerDeployment); @@ -158,6 +158,8 @@ std::optional ObjectOptimizer::calculateCacheKey( rawKey += h256(u256(_settings.expectedExecutionsPerDeployment)).asBytes(); rawKey += FixedHash<1>(uint8_t(_isCreation ? 0 : 1)).asBytes(); rawKey += keccak256(_settings.evmVersion.name()).asBytes(); + yulAssert(!_settings.eofVersion.has_value() || *_settings.eofVersion > 0); + rawKey += FixedHash<1>(uint8_t(_settings.eofVersion ? 0 : *_settings.eofVersion)).asBytes(); rawKey += keccak256(_settings.yulOptimiserSteps).asBytes(); rawKey += keccak256(_settings.yulOptimiserCleanupSteps).asBytes(); diff --git a/libyul/ObjectOptimizer.h b/libyul/ObjectOptimizer.h index e570d69c4..b2019d36b 100644 --- a/libyul/ObjectOptimizer.h +++ b/libyul/ObjectOptimizer.h @@ -38,7 +38,7 @@ enum class Language StrictAssembly, }; -Dialect const& languageToDialect(Language _language, langutil::EVMVersion _version); +Dialect const& languageToDialect(Language _language, langutil::EVMVersion _version, std::optional _eofVersion); /// Encapsulates logic for applying @a yul::OptimiserSuite to a whole hierarchy of Yul objects. /// Also, acts as a transparent cache for optimized objects. @@ -58,6 +58,7 @@ class ObjectOptimizer { Language language; langutil::EVMVersion evmVersion; + std::optional eofVersion; bool optimizeStackAllocation; std::string yulOptimiserSteps; std::string yulOptimiserCleanupSteps; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 67bc6d11a..8b559e23f 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -57,7 +57,7 @@ bool YulStack::parse(std::string const& _sourceName, std::string const& _source) { m_charStream = std::make_unique(_source, _sourceName); std::shared_ptr scanner = std::make_shared(*m_charStream); - m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion)).parse(scanner, false); + m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion, m_eofVersion)).parse(scanner, false); } catch (UnimplementedFeatureError const& _error) { @@ -94,7 +94,7 @@ void YulStack::optimize() { if ( !m_optimiserSettings.runYulOptimiser && - yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion), *m_parserResult) + yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion, m_eofVersion), *m_parserResult) ) return; @@ -130,6 +130,7 @@ void YulStack::optimize() ObjectOptimizer::Settings{ m_language, m_evmVersion, + m_eofVersion, optimizeStackAllocation, yulOptimiserSteps, yulOptimiserCleanupSteps, @@ -163,7 +164,7 @@ bool YulStack::analyzeParsed(Object& _object) AsmAnalyzer analyzer( *_object.analysisInfo, m_errorReporter, - languageToDialect(m_language, m_evmVersion), + languageToDialect(m_language, m_evmVersion, m_eofVersion), {}, _object.qualifiedDataNames() ); @@ -196,7 +197,7 @@ void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) const { case Language::Assembly: case Language::StrictAssembly: - dialect = &EVMDialect::strictAssemblyForEVMObjects(m_evmVersion); + dialect = &EVMDialect::strictAssemblyForEVMObjects(m_evmVersion, m_eofVersion); break; default: yulAssert(false, "Invalid language."); @@ -316,7 +317,7 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) // it with the minimal steps required to avoid "stack too deep". bool optimize = m_optimiserSettings.optimizeStackAllocation || ( !m_optimiserSettings.runYulOptimiser && - !yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion), *m_parserResult) + !yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion, m_eofVersion), *m_parserResult) ); try { @@ -385,7 +386,7 @@ Json YulStack::cfgJson() const // NOTE: The block Ids are reset for each object std::unique_ptr controlFlow = SSAControlFlowGraphBuilder::build( *_object.analysisInfo.get(), - languageToDialect(m_language, m_evmVersion), + languageToDialect(m_language, m_evmVersion, m_eofVersion), _object.code()->root() ); YulControlFlowGraphExporter exporter(*controlFlow); diff --git a/libyul/backends/evm/AsmCodeGen.cpp b/libyul/backends/evm/AsmCodeGen.cpp index 645d1fd87..91d06e2f0 100644 --- a/libyul/backends/evm/AsmCodeGen.cpp +++ b/libyul/backends/evm/AsmCodeGen.cpp @@ -38,6 +38,7 @@ void CodeGenerator::assemble( AsmAnalysisInfo& _analysisInfo, evmasm::Assembly& _assembly, langutil::EVMVersion _evmVersion, + std::optional _eofVersion, ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen, bool _useNamedLabelsForFunctions, bool _optimizeStackAllocation @@ -49,7 +50,7 @@ void CodeGenerator::assemble( assemblyAdapter, _analysisInfo, _parsedData, - EVMDialect::strictAssemblyForEVM(_evmVersion), + EVMDialect::strictAssemblyForEVM(_evmVersion, _eofVersion), builtinContext, _optimizeStackAllocation, _identifierAccessCodeGen, diff --git a/libyul/backends/evm/AsmCodeGen.h b/libyul/backends/evm/AsmCodeGen.h index b79338074..d7a6b5c92 100644 --- a/libyul/backends/evm/AsmCodeGen.h +++ b/libyul/backends/evm/AsmCodeGen.h @@ -44,6 +44,7 @@ class CodeGenerator AsmAnalysisInfo& _analysisInfo, evmasm::Assembly& _assembly, langutil::EVMVersion _evmVersion, + std::optional _eofVersion, ExternalIdentifierAccess::CodeGenerator _identifierAccess = {}, bool _useNamedLabelsForFunctions = false, bool _optimizeStackAllocation = false diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index dd5cad1dd..6bfdc9cb9 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -177,7 +177,7 @@ std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) return reserved; } -std::map createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess) +std::map createBuiltins(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess) { // Exclude prevrandao as builtin for VMs before paris and difficulty for VMs after paris. @@ -199,7 +199,7 @@ std::map createBuiltins(langutil::EVMVersion _ev opcode != evmasm::Instruction::JUMP && opcode != evmasm::Instruction::JUMPI && opcode != evmasm::Instruction::JUMPDEST && - _evmVersion.hasOpcode(opcode) && + _evmVersion.hasOpcode(opcode, _eofVersion) && !prevRandaoException(name) ) builtins.emplace(createEVMFunction(_evmVersion, name, opcode)); @@ -235,113 +235,116 @@ std::map createBuiltins(langutil::EVMVersion _ev }) ); - builtins.emplace(createFunction("datasize", 1, 1, SideEffects{}, {LiteralKind::String}, []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& _context - ) { - yulAssert(_context.currentObject, "No object available."); - yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - YulName const dataName (formatLiteral(std::get(arg))); - if (_context.currentObject->name == dataName.str()) - _assembly.appendAssemblySize(); - else - { - std::vector subIdPath = - _context.subIDs.count(dataName.str()) == 0 ? - _context.currentObject->pathToSubObject(dataName.str()) : - std::vector{_context.subIDs.at(dataName.str())}; - yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); - _assembly.appendDataSize(subIdPath); - } - })); - builtins.emplace(createFunction("dataoffset", 1, 1, SideEffects{}, {LiteralKind::String}, []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& _context - ) { - yulAssert(_context.currentObject, "No object available."); - yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - YulName const dataName (formatLiteral(std::get(arg))); - if (_context.currentObject->name == dataName.str()) - _assembly.appendConstant(0); - else - { - std::vector subIdPath = - _context.subIDs.count(dataName.str()) == 0 ? - _context.currentObject->pathToSubObject(dataName.str()) : - std::vector{_context.subIDs.at(dataName.str())}; - yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); - _assembly.appendDataOffset(subIdPath); - } - })); - builtins.emplace(createFunction( - "datacopy", - 3, - 0, - SideEffects{ - false, // movable - true, // movableApartFromEffects - false, // canBeRemoved - false, // canBeRemovedIfNotMSize - true, // cannotLoop - SideEffects::None, // otherState - SideEffects::None, // storage - SideEffects::Write, // memory - SideEffects::None // transientStorage - }, - {}, - []( - FunctionCall const&, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - _assembly.appendInstruction(evmasm::Instruction::CODECOPY); - } - )); - builtins.emplace(createFunction( - "setimmutable", - 3, - 0, - SideEffects{ - false, // movable - false, // movableApartFromEffects - false, // canBeRemoved - false, // canBeRemovedIfNotMSize - true, // cannotLoop - SideEffects::None, // otherState - SideEffects::None, // storage - SideEffects::Write, // memory - SideEffects::None // transientStorage - }, - {std::nullopt, LiteralKind::String, std::nullopt}, - []( + if (!_eofVersion.has_value()) + { + builtins.emplace(createFunction("datasize", 1, 1, SideEffects{}, {LiteralKind::String}, []( FunctionCall const& _call, AbstractAssembly& _assembly, - BuiltinContext& + BuiltinContext& _context ) { - yulAssert(_call.arguments.size() == 3, ""); - auto const identifier = (formatLiteral(std::get(_call.arguments[1]))); - _assembly.appendImmutableAssignment(identifier); - } - )); - builtins.emplace(createFunction( - "loadimmutable", - 1, - 1, - SideEffects{}, - {LiteralKind::String}, - []( + yulAssert(_context.currentObject, "No object available."); + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + YulName const dataName (formatLiteral(std::get(arg))); + if (_context.currentObject->name == dataName.str()) + _assembly.appendAssemblySize(); + else + { + std::vector subIdPath = + _context.subIDs.count(dataName.str()) == 0 ? + _context.currentObject->pathToSubObject(dataName.str()) : + std::vector{_context.subIDs.at(dataName.str())}; + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + _assembly.appendDataSize(subIdPath); + } + })); + builtins.emplace(createFunction("dataoffset", 1, 1, SideEffects{}, {LiteralKind::String}, []( FunctionCall const& _call, AbstractAssembly& _assembly, - BuiltinContext& + BuiltinContext& _context ) { + yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); - _assembly.appendImmutable(formatLiteral(std::get(_call.arguments.front()))); - } - )); + Expression const& arg = _call.arguments.front(); + YulName const dataName (formatLiteral(std::get(arg))); + if (_context.currentObject->name == dataName.str()) + _assembly.appendConstant(0); + else + { + std::vector subIdPath = + _context.subIDs.count(dataName.str()) == 0 ? + _context.currentObject->pathToSubObject(dataName.str()) : + std::vector{_context.subIDs.at(dataName.str())}; + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + _assembly.appendDataOffset(subIdPath); + } + })); + builtins.emplace(createFunction( + "datacopy", + 3, + 0, + SideEffects{ + false, // movable + true, // movableApartFromEffects + false, // canBeRemoved + false, // canBeRemovedIfNotMSize + true, // cannotLoop + SideEffects::None, // otherState + SideEffects::None, // storage + SideEffects::Write, // memory + SideEffects::None // transientStorage + }, + {}, + []( + FunctionCall const&, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + _assembly.appendInstruction(evmasm::Instruction::CODECOPY); + } + )); + builtins.emplace(createFunction( + "setimmutable", + 3, + 0, + SideEffects{ + false, // movable + false, // movableApartFromEffects + false, // canBeRemoved + false, // canBeRemovedIfNotMSize + true, // cannotLoop + SideEffects::None, // otherState + SideEffects::None, // storage + SideEffects::Write, // memory + SideEffects::None // transientStorage + }, + {std::nullopt, LiteralKind::String, std::nullopt}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == 3, ""); + auto const identifier = (formatLiteral(std::get(_call.arguments[1]))); + _assembly.appendImmutableAssignment(identifier); + } + )); + builtins.emplace(createFunction( + "loadimmutable", + 1, + 1, + SideEffects{}, + {LiteralKind::String}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == 1, ""); + _assembly.appendImmutable(formatLiteral(std::get(_call.arguments.front()))); + } + )); + } } return builtins; } @@ -355,10 +358,11 @@ std::regex const& verbatimPattern() } -EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, bool _objectAccess): +EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess): m_objectAccess(_objectAccess), m_evmVersion(_evmVersion), - m_functions(createBuiltins(_evmVersion, _objectAccess)), + m_eofVersion(_eofVersion), + m_functions(createBuiltins(_evmVersion, _eofVersion, _objectAccess)), m_reserved(createReservedIdentifiers(_evmVersion)) { } @@ -386,22 +390,22 @@ bool EVMDialect::reservedIdentifier(YulName _name) const return m_reserved.count(_name) != 0; } -EVMDialect const& EVMDialect::strictAssemblyForEVM(langutil::EVMVersion _version) +EVMDialect const& EVMDialect::strictAssemblyForEVM(langutil::EVMVersion _evmVersion, std::optional _eofVersion) { - static std::map> dialects; + static std::map>, std::unique_ptr> dialects; static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }}; - if (!dialects[_version]) - dialects[_version] = std::make_unique(_version, false); - return *dialects[_version]; + if (!dialects[{_evmVersion, _eofVersion}]) + dialects[{_evmVersion, _eofVersion}] = std::make_unique(_evmVersion, _eofVersion, false); + return *dialects[{_evmVersion, _eofVersion}]; } -EVMDialect const& EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion _version) +EVMDialect const& EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion _evmVersion, std::optional _eofVersion) { - static std::map> dialects; + static std::map>, std::unique_ptr> dialects; static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }}; - if (!dialects[_version]) - dialects[_version] = std::make_unique(_version, true); - return *dialects[_version]; + if (!dialects[{_evmVersion, _eofVersion}]) + dialects[{_evmVersion, _eofVersion}] = std::make_unique(_evmVersion, _eofVersion, true); + return *dialects[{_evmVersion, _eofVersion}]; } SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instruction) diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 3627a7fea..cc064c3a0 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -65,7 +65,7 @@ struct BuiltinFunctionForEVM: public BuiltinFunction struct EVMDialect: public Dialect { /// Constructor, should only be used internally. Use the factory functions below. - EVMDialect(langutil::EVMVersion _evmVersion, bool _objectAccess); + EVMDialect(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess); /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. BuiltinFunctionForEVM const* builtin(YulName _name) const override; @@ -82,10 +82,11 @@ struct EVMDialect: public Dialect BuiltinFunctionForEVM const* storageLoadFunction() const override { return builtin("sload"_yulname); } YulName hashFunction() const override { return "keccak256"_yulname; } - static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version); - static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _version); + static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _evmVersion, std::optional _eofVersion); + static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _evmVersion, std::optional _eofVersion); langutil::EVMVersion evmVersion() const { return m_evmVersion; } + std::optional eofVersion() const { return m_eofVersion; } bool providesObjectAccess() const { return m_objectAccess; } @@ -96,6 +97,7 @@ struct EVMDialect: public Dialect bool const m_objectAccess; langutil::EVMVersion const m_evmVersion; + std::optional m_eofVersion; std::map m_functions; std::map, std::shared_ptr> mutable m_verbatimFunctions; std::set m_reserved; diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 04324fa06..c444a7143 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -130,7 +130,7 @@ void NoOutputAssembly::appendImmutableAssignment(std::string const&) } NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom): - EVMDialect(_copyFrom.evmVersion(), _copyFrom.providesObjectAccess()) + EVMDialect(_copyFrom.evmVersion(), _copyFrom.eofVersion(), _copyFrom.providesObjectAccess()) { for (auto& fun: m_functions) { diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 03897c454..bf1e5caf7 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -56,7 +56,11 @@ evmasm::AssemblyItems compileContract(std::shared_ptr _sourceCode) { ErrorList errors; ErrorReporter errorReporter(errors); - Parser parser(errorReporter, solidity::test::CommonOptions::get().evmVersion()); + Parser parser( + errorReporter, + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); ASTPointer sourceUnit; BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(*_sourceCode)); BOOST_CHECK(!!sourceUnit); diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index b2e0b75d3..08a2814c9 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -62,7 +62,7 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con ErrorList errors; auto [object, analysisInfo] = yul::test::parse( compiler().yulIR(contractName), - EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion()), + EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion(), CommonOptions::get().eofVersion()), errors ); diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 4810b0143..20983b650 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -108,7 +108,11 @@ bytes compileFirstExpression( { ErrorList errors; ErrorReporter errorReporter(errors); - sourceUnit = Parser(errorReporter, solidity::test::CommonOptions::get().evmVersion()).parse(stream); + sourceUnit = Parser( + errorReporter, + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ).parse(stream); if (!sourceUnit) return bytes(); } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index e0f010c49..a0fd1fe94 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -44,7 +44,8 @@ ASTPointer parseText(std::string const& _source, ErrorList& auto charStream = CharStream(_source, ""); ASTPointer sourceUnit = Parser( errorReporter, - solidity::test::CommonOptions::get().evmVersion() + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() ).parse(charStream); if (!sourceUnit) return ASTPointer(); diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 7640e4a5d..6562e1743 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -46,7 +46,10 @@ namespace { Dialect const& defaultDialect() { - return yul::EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion()); + return yul::EVMDialect::strictAssemblyForEVM( + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); } } @@ -101,11 +104,11 @@ std::string yul::test::format(std::string const& _source) namespace { -std::map const validDialects = { +std::map)> const validDialects = { { "evm", - [](langutil::EVMVersion _evmVersion) -> yul::Dialect const& - { return yul::EVMDialect::strictAssemblyForEVMObjects(_evmVersion); } + [](langutil::EVMVersion _evmVersion, std::optional _eofVersion) -> yul::Dialect const& + { return yul::EVMDialect::strictAssemblyForEVMObjects(_evmVersion, _eofVersion); } } }; @@ -118,7 +121,7 @@ std::map const } } -yul::Dialect const& yul::test::dialect(std::string const& _name, langutil::EVMVersion _evmVersion) +yul::Dialect const& yul::test::dialect(std::string const& _name, langutil::EVMVersion _evmVersion, std::optional _eofVersion) { if (!validDialects.count(_name)) BOOST_THROW_EXCEPTION(std::runtime_error{ @@ -129,5 +132,5 @@ yul::Dialect const& yul::test::dialect(std::string const& _name, langutil::EVMVe "." }); - return validDialects.at(_name)(_evmVersion); + return validDialects.at(_name)(_evmVersion, _eofVersion); } diff --git a/test/libyul/Common.h b/test/libyul/Common.h index c87f1c68b..2255272b6 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -54,6 +54,6 @@ parse(std::string const& _source, Dialect const& _dialect, langutil::ErrorList& Block disambiguate(std::string const& _source); std::string format(std::string const& _source); -solidity::yul::Dialect const& dialect(std::string const& _name, langutil::EVMVersion _evmVersion); +solidity::yul::Dialect const& dialect(std::string const& _name, langutil::EVMVersion _evmVersion, std::optional _eofVersion); } diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index 13788b75f..6c86ac21f 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -38,7 +38,11 @@ std::string check(std::string const& _input) auto parsingResult = yul::test::parse(_input); obj.setCode(parsingResult.first, parsingResult.second); BOOST_REQUIRE(obj.hasCode()); - auto functions = CompilabilityChecker(EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion()), obj, true).stackDeficit; + auto functions = CompilabilityChecker( + EVMDialect::strictAssemblyForEVM( + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ), obj, true).stackDeficit; std::string out; for (auto const& function: functions) out += function.first.str() + ": " + std::to_string(function.second) + " "; diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index 0060b850e..b7264bc0e 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -45,7 +45,11 @@ ControlFlowGraphTest::ControlFlowGraphTest(std::string const& _filename): { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); + m_dialect = &dialect( + dialectName, + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); m_expectation = m_reader.simpleExpectations(); } diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index 3ad70f5a0..50c69b179 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -62,8 +62,9 @@ TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std: if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); + // TODO: Add EOF support ControlFlowSideEffectsCollector sideEffects( - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), + EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(), std::nullopt), obj.code()->root() ); m_obtainedResult.clear(); diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index e54ab9c8f..23c24ce30 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -67,12 +67,14 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin return TestResult::FatalError; } + // TODO: Add EOF support evmasm::Assembly assembly{solidity::test::CommonOptions::get().evmVersion(), false, std::nullopt, {}}; EthAssemblyAdapter adapter(assembly); EVMObjectCompiler::compile( *stack.parserResult(), adapter, - EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}), + // TODO: Make sure that why we cannot pass here solidity::test::CommonOptions::get().evmVersion() and assembly.eofVersion() + EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}, std::nullopt), m_stackOpt, std::nullopt ); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index 9d6599f42..7a153de7d 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -88,8 +88,9 @@ TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); + // TODO: Add EOF support std::map functionSideEffects = SideEffectsPropagator::sideEffects( - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), + EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(), std::nullopt), CallGraphGenerator::callGraph(obj.code()->root()) ); diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index 0293f8ee4..badeb21fe 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -63,7 +63,8 @@ class KnowledgeBaseTest return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }); } - EVMDialect m_dialect{EVMVersion{}, true}; + // TODO: Add EOF support + EVMDialect m_dialect{EVMVersion{}, std::nullopt, true}; std::shared_ptr m_object; SSAValueTracker m_ssaValues; std::map m_values; diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index b23e53060..7ed321cd4 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -112,7 +112,8 @@ std::tuple, ErrorList> tryGetSourceLocationMapping( ErrorList errors; ErrorReporter reporter(errors); - Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(EVMVersion::berlin()); + // TODO: Add EOF support + Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); ObjectParser objectParser{reporter, dialect}; CharStream stream(std::move(source), ""); auto object = objectParser.parse(std::make_shared(stream), false); diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 9b8ce4292..930a34cf1 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -162,7 +162,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_empty_block) auto const sourceText = "/// @src 0:234:543\n" "{}\n"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -180,7 +181,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_with_children) "let z := true\n" "let y := add(1, 2)\n" "}\n"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -203,7 +205,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_different_sources) "let z := true\n" "let y := add(1, 2)\n" "}\n"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -225,7 +228,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_nested) "/// @src 0:343:434\n" "switch y case 0 {} default {}\n" "}\n"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -249,7 +253,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_switch_case) " let z := add(3, 4)\n" "}\n" "}\n"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -281,7 +286,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_inherit_into_outer_scope) "let z := true\n" "let y := add(1, 2)\n" "}\n"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); @@ -312,7 +318,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_assign_empty) "/// @src 1:1:10\n" "a := true\n" "}\n"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // should still parse BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); @@ -333,7 +340,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_source_index) "let b := true\n" "\n" "}\n"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); // should still parse BOOST_REQUIRE(errorList.size() == 1); @@ -353,7 +361,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_1) "/// @src 0:234:2026\n" ":= true\n" "}\n"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); @@ -376,7 +385,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_2) 2) } )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(1, result->root().statements.size()); @@ -410,7 +420,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_3) mstore(1, 2) // FunctionCall } )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); @@ -446,7 +457,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_comments_after_valid) let a := true } )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(1, result->root().statements.size()); @@ -465,7 +477,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_suffix) /// @src 0:420:680foo {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -482,7 +495,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_prefix) /// abc@src 0:111:222 {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); @@ -496,7 +510,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_unspecified) /// @src -1:-1:-1 {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); @@ -510,7 +525,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_non_integer) /// @src a:b:c {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -527,7 +543,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_bad_integer) /// @src 111111111111111111111:222222222222222222222:333333333333333333333 {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -548,7 +565,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_ensure_last_match) let x := true } )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); @@ -566,7 +584,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_no_whitespace) /// @src 0:111:222@src 1:333:444 {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -583,7 +602,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_separated_with_single_s /// @src 0:111:222 @src 1:333:444 {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 333, 444); @@ -594,7 +614,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_leading_trailing_whitespace) ErrorList errorList; ErrorReporter reporter(errorList); auto const sourceText = "/// @src 0:111:222 \n{}"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -611,7 +632,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_reference_original_sloc) let x := true } )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); @@ -633,7 +655,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets) let y := /** @src 1:96:165 "contract D {..." */ 128 } )~~~"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 2); @@ -658,7 +681,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_empty_snippet) /// @src 0:111:222 "" {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -672,7 +696,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_befo /// @src 0:111:222"abc" def {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -689,7 +714,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_afte /// @src 0:111:222 "abc"def {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -703,7 +729,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_no_whites /// @src 0:111:222 "abc"@src 1:333:444 "abc" {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 333, 444); @@ -717,7 +744,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_untermina /// @src 0:111:222 " abc @src 1:333:444 {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -735,7 +763,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote) /// {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -752,7 +781,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_snippets_with_hex_comment) /// @src 0:111:222 hex"abc"@src 1:333:444 "abc" {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // the second source location is not parsed as such, as the hex string isn't interpreted as snippet but @@ -768,7 +798,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_escapes) /// @src 0:111:222 "\n\\x\x\w\uö\xy\z\y\fq" {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -783,7 +814,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote_snippet_with_whitespaces /// @src 1 : 222 : 333 '\x33\u1234\t\n' {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 222, 333); @@ -798,7 +830,8 @@ BOOST_DATA_TEST_CASE(customSourceLocations_scanner_errors_outside_string_lits_ar /// @src 1:222:333 {{}} )", invalid); - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.empty()); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 222, 333); @@ -816,7 +849,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multi_line_source_loc) /// " @src 0:333:444 {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.empty()); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 333, 444); @@ -834,7 +868,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locati let y := /** @src 1:96:165 "function f() internal { \"\/** @src 0:6:7 *\/\"; }" */ 128 } )~~~"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 2); @@ -863,7 +898,8 @@ BOOST_AUTO_TEST_CASE(astid) mstore(1, 2) } )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(7)); @@ -885,7 +921,8 @@ BOOST_AUTO_TEST_CASE(astid_reset) mstore(1, 2) } )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(7)); @@ -903,7 +940,8 @@ BOOST_AUTO_TEST_CASE(astid_multi) /// @src -1:-1:-1 @ast-id 7 @src 1:1:1 @ast-id 8 {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(8)); @@ -917,7 +955,8 @@ BOOST_AUTO_TEST_CASE(astid_invalid) /// @src -1:-1:-1 @ast-id abc @src 1:1:1 {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -934,7 +973,8 @@ BOOST_AUTO_TEST_CASE(astid_too_large) /// @ast-id 9223372036854775808 {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -950,7 +990,8 @@ BOOST_AUTO_TEST_CASE(astid_way_too_large) /// @ast-id 999999999999999999999999999999999999999 {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -966,7 +1007,8 @@ BOOST_AUTO_TEST_CASE(astid_not_fully_numeric) /// @ast-id 9x {} )"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -988,7 +1030,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multiple_src_tags_on_one_line) "\n" " let x := 123\n" "}\n"; - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + // TODO: Add EOF support + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 1); diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/SSAControlFlowGraphTest.cpp index a316356db..c0d1e8727 100644 --- a/test/libyul/SSAControlFlowGraphTest.cpp +++ b/test/libyul/SSAControlFlowGraphTest.cpp @@ -48,7 +48,11 @@ SSAControlFlowGraphTest::SSAControlFlowGraphTest(std::string const& _filename): { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); + m_dialect = &dialect( + dialectName, + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); m_expectation = m_reader.simpleExpectations(); } diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 9c16eaefc..f50d2d23b 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -49,7 +49,11 @@ StackLayoutGeneratorTest::StackLayoutGeneratorTest(std::string const& _filename) { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); + m_dialect = &dialect( + dialectName, + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); m_expectation = m_reader.simpleExpectations(); } diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index 7ed87bee4..aa37e85af 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -75,5 +75,9 @@ SyntaxTest::SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVe CommonSyntaxTest(_filename, _evmVersion) { std::string dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); + m_dialect = &dialect( + dialectName, + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); } diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index 9d4ccd81b..343a17b4a 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -98,7 +98,7 @@ std::string YulInterpreterTest::interpret() { Interpreter::run( state, - EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion()), + EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion(), std::nullopt), m_ast->root(), /*disableExternalCalls=*/ !m_simulateExternalCallsToSelf, /*disableMemoryTracing=*/ false diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 7f2f5815a..308afef5f 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -56,7 +56,11 @@ YulOptimizerTest::YulOptimizerTest(std::string const& _filename): m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); + m_dialect = &dialect( + dialectName, + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); m_expectation = m_reader.simpleExpectations(); } diff --git a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp index a064fcdc8..6f603e335 100644 --- a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp +++ b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp @@ -105,8 +105,9 @@ DEFINE_PROTO_FUZZER(Program const& _input) YulAssembler assembler{version, std::nullopt, settings, yul_source}; unoptimisedByteCode = assembler.assemble(); auto yulObject = assembler.object(); + // TODO: Add EOF support recursiveFunction = recursiveFunctionExists( - EVMDialect::strictAssemblyForEVMObjects(version), + EVMDialect::strictAssemblyForEVMObjects(version, std::nullopt), *yulObject ); } diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index f685aa90d..ffeb14702 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -87,10 +87,11 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) // such as unused write to memory e.g., // { mstore(0, 1) } // that would be removed by the redundant store eliminator. + // TODO: Add EOF support yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( os1, stack.parserResult()->code()->root(), - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), + EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(), std::nullopt), /*disableMemoryTracing=*/true ); if (yulFuzzerUtil::resourceLimitsExceeded(termReason)) @@ -100,7 +101,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) termReason = yulFuzzerUtil::interpret( os2, stack.parserResult()->code()->root(), - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), + EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(), std::nullopt), /*disableMemoryTracing=*/true ); diff --git a/test/tools/ossfuzz/yulProtoFuzzer.cpp b/test/tools/ossfuzz/yulProtoFuzzer.cpp index cfdb20813..4e9387f6f 100644 --- a/test/tools/ossfuzz/yulProtoFuzzer.cpp +++ b/test/tools/ossfuzz/yulProtoFuzzer.cpp @@ -78,10 +78,11 @@ DEFINE_PROTO_FUZZER(Program const& _input) ) yulAssert(false, "Proto fuzzer generated malformed program"); + // TODO: Add EOF support // Optimize YulOptimizerTestCommon optimizerTest( stack.parserResult(), - EVMDialect::strictAssemblyForEVMObjects(version) + EVMDialect::strictAssemblyForEVMObjects(version, std::nullopt) ); optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); auto const* astRoot = optimizerTest.run(); diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index 13ac4aea8..eff96f831 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -87,27 +87,30 @@ DEFINE_PROTO_FUZZER(Program const& _input) // such as unused write to memory e.g., // { mstore(0, 1) } // that would be removed by the redundant store eliminator. + // TODO: Add EOF support yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( os1, stack.parserResult()->code()->root(), - EVMDialect::strictAssemblyForEVMObjects(version), + EVMDialect::strictAssemblyForEVMObjects(version, std::nullopt), /*disableMemoryTracing=*/true ); if (yulFuzzerUtil::resourceLimitsExceeded(termReason)) return; + // TODO: Add EOF support YulOptimizerTestCommon optimizerTest( stack.parserResult(), - EVMDialect::strictAssemblyForEVMObjects(version) + EVMDialect::strictAssemblyForEVMObjects(version, std::nullopt) ); optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); auto const* astRoot = optimizerTest.run(); yulAssert(astRoot != nullptr, "Optimiser error."); + // TODO: Add EOF support termReason = yulFuzzerUtil::interpret( os2, *astRoot, - EVMDialect::strictAssemblyForEVMObjects(version), + EVMDialect::strictAssemblyForEVMObjects(version, std::nullopt), true ); if (yulFuzzerUtil::resourceLimitsExceeded(termReason)) diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 13375f827..cbe021967 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -242,7 +242,7 @@ class YulOpti private: std::shared_ptr m_astRoot; - Dialect const& m_dialect{EVMDialect::strictAssemblyForEVMObjects(EVMVersion{})}; + Dialect const& m_dialect{EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}, std::nullopt)}; std::unique_ptr m_analysisInfo; std::set const m_reservedIdentifiers = {}; NameDispenser m_nameDispenser{m_dialect, m_reservedIdentifiers}; diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index e857c2664..36d488586 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -87,7 +87,7 @@ void interpret(std::string const& _source, bool _inspect, bool _disableExternalC state.maxTraceSize = 10000; try { - Dialect const& dialect(EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{})); + Dialect const& dialect(EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}, std::nullopt)); if (_inspect) InspectedInterpreter::run(std::make_shared(_source, state), state, dialect, ast->root(), _disableExternalCalls, /*disableMemoryTracing=*/false); diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 57e1bf2b9..fa7fbe274 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -68,7 +68,8 @@ Program::Program(Program const& program): std::variant Program::load(CharStream& _sourceCode) { // ASSUMPTION: parseSource() rewinds the stream on its own - Dialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}); + // TODO: Add support for EOF + Dialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}, std::nullopt); std::variant, ErrorList> astOrErrors = parseObject(dialect, _sourceCode); if (std::holds_alternative(astOrErrors)) From 62dc5975b83d5448acb70ccdcd54ac39e14d7b75 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Fri, 27 Sep 2024 11:06:43 +0200 Subject: [PATCH 0373/1340] Replace Hardhat with EDR in CI --- .circleci/config.yml | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5e6e65809..58d3803ed 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1394,13 +1394,13 @@ jobs: test/externalTests/solc-js/solc-js.sh /tmp/workspace/soljson.js $(cat /tmp/workspace/version.txt) - matrix_notify_failure_unless_pr - t_ems_ext_hardhat: + t_ems_ext_edr: <<: *base_node_small docker: - - image: cimg/rust:1.74.0-node + - image: cimg/rust:1.79.0-node environment: <<: *base_node_small_env - HARDHAT_TESTS_SOLC_PATH: /tmp/workspace/soljson.js + EDR_TESTS_SOLC_PATH: /tmp/workspace/soljson.js steps: - checkout - attach_workspace: @@ -1409,48 +1409,36 @@ jobs: name: Ensure pnpm is installed if npm is present command: sudo npm install -g pnpm - run: - name: Retrieve Hardhat latest release tag + name: Retrieve EDR latest release tag command: | # Make authenticated requests when the Github token is available if [[ -n "$GITHUB_ACCESS_TOKEN" ]]; then EXTRA_HEADERS=(--header "Authorization: Bearer ${GITHUB_ACCESS_TOKEN}") fi - HARDHAT_LATEST_RELEASE_TAG=$( + EDR_LATEST_RELEASE_TAG=$( curl \ --silent \ --location \ --fail \ --show-error \ "${EXTRA_HEADERS[@]}" \ - https://api.github.com/repos/nomiclabs/hardhat/releases/latest \ + https://api.github.com/repos/nomicfoundation/edr/releases/latest \ | jq --raw-output .tag_name \ ) - echo "export HARDHAT_LATEST_RELEASE_TAG='${HARDHAT_LATEST_RELEASE_TAG}'" >> "$BASH_ENV" - - run: git clone --depth 1 https://github.com/nomiclabs/hardhat.git --branch "$HARDHAT_LATEST_RELEASE_TAG" + echo "export EDR_LATEST_RELEASE_TAG='${EDR_LATEST_RELEASE_TAG}'" >> "$BASH_ENV" + - run: git clone --depth 1 https://github.com/nomicfoundation/edr.git --branch "$EDR_LATEST_RELEASE_TAG" - run: name: Install dependencies command: | - cd hardhat + cd edr pnpm install --no-frozen-lockfile - run: - name: Run hardhat-core test suite + name: Run hardhat-tests in EDR repo command: | - HARDHAT_TESTS_SOLC_VERSION=$(scripts/get_version.sh) - export HARDHAT_TESTS_SOLC_VERSION - - # NOTE: This is expected to work without running `pnpm build` first. - cd hardhat/packages/hardhat-core - # TODO: temporarily set hardhat stack traces tests to use cancun hardfork - # Remove this when hardhat switch to cancun by default: https://github.com/NomicFoundation/hardhat/issues/4851 - sed -i 's/hardfork: "shanghai",/hardfork: "cancun",/' test/internal/hardhat-network/stack-traces/execution.ts - # TODO: Remove these tests because they rely on specific stack sequence which has changed since - # Remove when hardhat properly fix a specific version for the tests: https://github.com/NomicFoundation/hardhat/issues/5443 - rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/modifiers/call-message/multiple-modifiers-require/ - rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/modifiers/create-message/multiple-modifiers-require/ - rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/revert-without-message/within-receive/between-statements/ - rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/revert-without-message/within-receive/no-other-statements/ - rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/revert-without-message/within-receive/statement-after/ - rm -rf test/internal/hardhat-network/stack-traces/test-files/0_8/revert-without-message/revert-without-message/within-receive/statement-before/ + EDR_TESTS_SOLC_VERSION=$(scripts/get_version.sh) + export EDR_TESTS_SOLC_VERSION + + cd edr/hardhat-tests pnpm test - matrix_notify_failure_unless_pr @@ -1904,7 +1892,7 @@ workflows: # Emscripten build and tests that take 15 minutes or less - b_ems: *requires_nothing - t_ems_solcjs: *requires_b_ems - - t_ems_ext_hardhat: *requires_b_ems + - t_ems_ext_edr: *requires_b_ems - t_ext: *job_ems_compile_ext_colony From 2b4184674369e49f5edc1a7cd1cdf77637712221 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:24:11 +0200 Subject: [PATCH 0374/1340] cmake: remove USE_LD_GOLD option --- Changelog.md | 4 ++++ cmake/EthCompilerSettings.cmake | 10 ---------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Changelog.md b/Changelog.md index b171b6dd0..959aff257 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,6 +14,10 @@ Bugfixes: * Yul AST: Fix shifted native source locations when debug info selection included code snippets. +Build system: +* Removed ``USE_LD_GOLD`` option and default to use the compiler default linker. For custom linkers, ``CMAKE_CXX_FLAGS`` can be used. + + ### 0.8.27 (2024-09-04) Language Features: diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index eda0e404d..4cf3927d1 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -266,13 +266,3 @@ option(USE_Z3 "Allow compiling with Z3 SMT solver integration" ON) if(UNIX AND NOT APPLE) option(USE_Z3_DLOPEN "Dynamically load the Z3 SMT solver instead of linking against it." OFF) endif() - -if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) - option(USE_LD_GOLD "Use GNU gold linker" ON) - if (USE_LD_GOLD) - execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) - if ("${LD_VERSION}" MATCHES "GNU gold") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") - endif () - endif () -endif () From badd1154e87a7170467d7855bfc7e17c55748d55 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 2 Oct 2024 19:06:04 +0200 Subject: [PATCH 0375/1340] Avoid unnecessary copy in full inliner. --- libyul/optimiser/FullInliner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index 2f138761f..c6387f808 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -106,7 +106,7 @@ void FullInliner::run(Pass _pass) for (auto& statement: m_ast.statements) if (std::holds_alternative(statement)) functions.emplace_back(&std::get(statement)); - std::stable_sort(functions.begin(), functions.end(), [depths]( + std::stable_sort(functions.begin(), functions.end(), [&depths]( FunctionDefinition const* _a, FunctionDefinition const* _b ) { From 39e5aeff86151c273c5e8c7b040f371536726b9c Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 2 Oct 2024 15:18:40 +0200 Subject: [PATCH 0376/1340] Re-enable cxx20 job --- .circleci/config.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 58d3803ed..82739dffb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1105,9 +1105,9 @@ jobs: # Builds in C++20 mode and uses debug build in order to speed up. # Do *NOT* store any artifacts or workspace as we don't run tests on this build. b_ubu_cxx20: - <<: *base_ubuntu2404_large + <<: *base_ubuntu2404_xlarge environment: - <<: *base_ubuntu2404_large_env + <<: *base_ubuntu2404_xlarge_env CMAKE_BUILD_TYPE: Debug CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 MAKEFLAGS: -j 10 @@ -1859,8 +1859,7 @@ workflows: # build-only - b_docs: *requires_nothing - # DISABLED FOR 0.8.18 - b_ubu_cxx20: *requires_nothing - # Issue: https://github.com/ethereum/solidity/issues/13868 + - b_ubu_cxx20: *requires_nothing - b_ubu_ossfuzz: *requires_nothing # OS/X build and tests From 136fe38f748ee399fd264fc72e641f1d0dcd769f Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 7 Oct 2024 11:56:23 +0200 Subject: [PATCH 0377/1340] Disable legacy presets in zeppelin external test --- test/externalTests/zeppelin.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 64c901f61..b9e65562e 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -52,8 +52,8 @@ function zeppelin_test local settings_presets=( "${compile_only_presets[@]}" ir-optimize-evm+yul - legacy-no-optimize - legacy-optimize-evm-only + #legacy-no-optimize # FIXME: Fails with stack too deep + #legacy-optimize-evm-only # FIXME: Fails with stack too deep legacy-optimize-evm+yul ) From 293bd7fc08d32e3d4871ea745e3cff664d99d48b Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 7 Oct 2024 13:41:52 +0200 Subject: [PATCH 0378/1340] Fix broken flyout layout due to RTD addons upgrade --- docs/_static/js/initialize.js | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/docs/_static/js/initialize.js b/docs/_static/js/initialize.js index a20d4fce7..3cf12e3e1 100644 --- a/docs/_static/js/initialize.js +++ b/docs/_static/js/initialize.js @@ -23,18 +23,24 @@ function rearrangeDom() { document.body.prepend(wrapperDiv); const rstVersions = document.querySelector(".rst-versions"); - rstVersions.remove(); const wyNavSide = document.querySelector("nav.wy-nav-side"); - wyNavSide.appendChild(rstVersions); + // NOTE: Since RTD migration to addons, `.rst-versions` is no longer present in the DOM. + // The following code is kept for compatibility with older versions. + // See: https://github.com/readthedocs/readthedocs.org/issues/11474 + if (rstVersions && wyNavSide) { + rstVersions.remove(); + wyNavSide.appendChild(rstVersions); + } const backdrop = document.createElement("div"); backdrop.classList.add("backdrop"); wrapperDiv.appendChild(backdrop); const content = document.querySelector(".wy-nav-content"); - content.id = "content"; - const oldWrap = document.querySelector("section.wy-nav-content-wrap"); - oldWrap.remove(); - document.querySelector(".wy-grid-for-nav").appendChild(content); + if (content) { + content.id = "content"; + document.querySelector("section.wy-nav-content-wrap")?.remove(); + document.querySelector(".wy-grid-for-nav")?.appendChild(content); + } } function buildHeader() { @@ -146,6 +152,8 @@ document.addEventListener("locationchange", updateActiveNavLink); function updateGitHubEditPath() { // Replaces the version number in the GitHub edit path with "develop" const gitHubEditAnchor = document.querySelector(".wy-breadcrumbs-aside > a"); + if (!gitHubEditAnchor) return; + const url = new URL(gitHubEditAnchor.href); const split = url.pathname.split("/"); const versionIndex = split.indexOf("blob") + 1; @@ -195,10 +203,12 @@ function initialize() { .querySelector(":root") .setAttribute("style", `--color-scheme: ${mode}`); + // NOTE: Since RTD migration to addons, the elements below are no longer present in the DOM. + // The following code is kept for compatibility with older versions. // Remove old input and RTD logo anchor element - document.querySelector("input[name=mode]").remove(); - document.querySelector("label[for=switch]").remove(); - document.querySelector(".wy-side-nav-search > a").remove(); + document.querySelector("input[name=mode]")?.remove(); + document.querySelector("label[for=switch]")?.remove(); + document.querySelector(".wy-side-nav-search > a")?.remove(); // Add footer note addFooterNote(); @@ -239,7 +249,7 @@ document.addEventListener("click", handleClick); const handleKeyDown = (e) => { if (e.metaKey && e.key === "k") { - document.querySelector("#rtd-search-form input").focus(); + document.querySelector("#rtd-search-form input")?.focus(); } else if (e.key === "Escape") { toggleMenu({ force: false }); } From f8477584e7fefd0384dd02223d104554097e3bc2 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 7 Oct 2024 17:17:17 +0200 Subject: [PATCH 0379/1340] Fix "Edit on GitHub" button to always point to develop branch --- docs/_static/js/initialize.js | 7 ++++++- docs/conf.py | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/_static/js/initialize.js b/docs/_static/js/initialize.js index 3cf12e3e1..1c3be8aad 100644 --- a/docs/_static/js/initialize.js +++ b/docs/_static/js/initialize.js @@ -150,7 +150,12 @@ const updateActiveNavLink = () => { document.addEventListener("locationchange", updateActiveNavLink); function updateGitHubEditPath() { - // Replaces the version number in the GitHub edit path with "develop" + // Replaces the version number in the GitHub edit path with "develop" if it exists. + // This is to ensure that the edit path always points to the `develop` branch instead of the specific version branch. + // Note that it will fail silently if the anchor element is not found, i.e. the page is not editable or + // if the sphinx_rtd_theme is updated to a version that changes the anchor element. + // See: https://github.com/readthedocs/sphinx_rtd_theme/blob/a1c2147b17cbf0e57b7d7a6450ad4d9a5ff362cf/sphinx_rtd_theme/breadcrumbs.html#L35 + // TODO: We should consider a more robust way to handle this in the future. const gitHubEditAnchor = document.querySelector(".wy-breadcrumbs-aside > a"); if (!gitHubEditAnchor) return; diff --git a/docs/conf.py b/docs/conf.py index 9c9e2d5a0..354e1feec 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -38,6 +38,13 @@ def setup(sphinx): # -- General configuration ------------------------------------------------ +html_context = { + "display_github": True, + "github_user": "ethereum", + "github_repo": "solidity", + "github_version": os.getenv("READTHEDOCS_VERSION", "develop"), + "conf_py_path": "/docs/", +} # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' From e354f7b098f46d688c5aadf23d28befd6f4e5749 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 7 Oct 2024 12:45:35 -0300 Subject: [PATCH 0380/1340] fix changelog entry --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 959aff257..de1674a15 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,10 +1,10 @@ ### 0.8.28 (unreleased) Language Features: + * Transient storage value type state variables are now fully supported. Compiler Features: - * Code Generator: Transient storage value type state variables are now supported. * General: Generate JSON representations of Yul ASTs only on demand to reduce memory usage. * Standard JSON Interface: Bytecode or IR can now be requested for a subset of all contracts without triggering unnecessary code generation for other contracts. From 8d4dc15588cbe44ff7999d8f73dd251fea04f903 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 7 Oct 2024 18:28:33 +0200 Subject: [PATCH 0381/1340] Fix github user and repo in RTD config for translation projects --- docs/conf.py | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 354e1feec..f57a3b5b9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,15 +36,55 @@ def setup(sphinx): sphinx.add_css_file('css/custom-dark.css') sphinx.add_css_file('css/pygments.css') -# -- General configuration ------------------------------------------------ +# -- RTD GitHub configuration --------------------------------------------- + +# Taken from: +# https://github.com/readthedocs/readthedocs.org/blob/e366e7fc8649fbcf1b6d06ecc12c5f7766144c46/readthedocs/projects/constants.py#L350 +GITHUB_REGEXS = [ + re.compile(r"github.com/(.+)/(.+)(?:\.git){1}$"), + # This must come before the one without a / to make sure we don't capture the / + re.compile(r"github.com/(.+)/(.+)/"), + re.compile(r"github.com/(.+)/(.+)"), + re.compile(r"github.com:(.+)/(.+)\.git$"), +] + +# Taken and adapted from: +# https://github.com/readthedocs/readthedocs.org/blob/e366e7fc8649fbcf1b6d06ecc12c5f7766144c46/readthedocs/builds/utils.py#L24 +def get_github_username_repo(url): + if "github" in url: + for regex in GITHUB_REGEXS: + match = regex.search(url) + if match: + return match.groups() + return (None, None) + +display_github = False +# NOTE: RTD_DISPLAY_GITHUB, RTD_GITHUB_USER and RTD_GITHUB_REPO are set in the RTD project settings +github_user = os.getenv("RTD_GITHUB_USER") +github_repo = os.getenv("RTD_GITHUB_REPO") + +if github_user and github_repo: + display_github = True +else: + git_clone_url = os.getenv("READTHEDOCS_GIT_CLONE_URL") + if git_clone_url: + github_user, github_repo = get_github_username_repo(git_clone_url) + if github_user and github_repo: + display_github = True + +display_github_env = os.getenv("RTD_DISPLAY_GITHUB") +if display_github_env: + display_github = display_github_env.lower() == "true" html_context = { - "display_github": True, - "github_user": "ethereum", - "github_repo": "solidity", + "display_github": display_github, + "github_user": github_user, + "github_repo": github_repo, "github_version": os.getenv("READTHEDOCS_VERSION", "develop"), "conf_py_path": "/docs/", } + +# -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' From 3651f231fd701340927c354c18a598122d7dbf1c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 7 Oct 2024 08:13:55 +0200 Subject: [PATCH 0382/1340] Use gold linker for ossfuzz, codecov, and cxx20 builds --- .circleci/config.yml | 10 ++++++---- cmake/toolchains/libfuzzer.cmake | 3 ++- scripts/ci/build.sh | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 82739dffb..0c8bb02ec 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1073,6 +1073,7 @@ jobs: <<: *base_ubuntu2404_env COVERAGE: ON CMAKE_BUILD_TYPE: Debug + CMAKE_OPTIONS: -DCMAKE_CXX_FLAGS=-fuse-ld=gold steps: - checkout - run_build @@ -1105,12 +1106,13 @@ jobs: # Builds in C++20 mode and uses debug build in order to speed up. # Do *NOT* store any artifacts or workspace as we don't run tests on this build. b_ubu_cxx20: - <<: *base_ubuntu2404_xlarge + <<: *base_ubuntu2404_large environment: - <<: *base_ubuntu2404_xlarge_env + <<: *base_ubuntu2404_large_env CMAKE_BUILD_TYPE: Debug - CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 - MAKEFLAGS: -j 10 + # gold is more memory-efficient than the default, allows us to stay with the "large" resource class without OOM errors + CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS=-fuse-ld=gold + MAKEFLAGS: -j 6 steps: - checkout - run_build diff --git a/cmake/toolchains/libfuzzer.cmake b/cmake/toolchains/libfuzzer.cmake index 9d83d504f..f9ea64860 100644 --- a/cmake/toolchains/libfuzzer.cmake +++ b/cmake/toolchains/libfuzzer.cmake @@ -7,7 +7,8 @@ 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 UBSan instrumentation -set(CMAKE_CXX_FLAGS "-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -I /usr/local/include/c++/v1 -fsanitize=undefined -fsanitize=fuzzer-no-link -stdlib=libc++" CACHE STRING "Custom compilation flags" FORCE) +# uses the more memory-efficient gold, which allows us to stay with the "large" resource class without OOM errors +set(CMAKE_CXX_FLAGS "-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -I /usr/local/include/c++/v1 -fsanitize=undefined -fsanitize=fuzzer-no-link -fuse-ld=gold -stdlib=libc++" CACHE STRING "Custom compilation flags" 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) diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh index d529b03c1..e1d119a06 100755 --- a/scripts/ci/build.sh +++ b/scripts/ci/build.sh @@ -32,6 +32,6 @@ cd build [ -n "$COVERAGE" -a "$CIRCLE_BRANCH" != release -a -z "$CIRCLE_TAG" ] && CMAKE_OPTIONS="$CMAKE_OPTIONS -DCOVERAGE=ON" # shellcheck disable=SC2086 -cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" $CMAKE_OPTIONS -G "Unix Makefiles" +cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" $CMAKE_OPTIONS -make +cmake --build . From c7ff2175a1dae32dbf80be48f5840e04c5465d15 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:00:12 +0200 Subject: [PATCH 0383/1340] Bump ossfuzz to large resource class --- .circleci/config.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0c8bb02ec..ed14c8af4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -528,6 +528,14 @@ defaults: MAKEFLAGS: -j 2 CPUs: 2 + - base_ubuntu_clang_large: &base_ubuntu_clang_large + <<: *base_ubuntu_clang + resource_class: large + environment: &base_ubuntu_clang_small_env + <<: *base_ubuntu_clang_env + MAKEFLAGS: -j 5 + CPUs: 5 + - base_ubuntu2004: &base_ubuntu2004 docker: - image: << pipeline.parameters.ubuntu-2004-docker-image >> @@ -1119,7 +1127,7 @@ jobs: - matrix_notify_failure_unless_pr b_ubu_ossfuzz: &b_ubu_ossfuzz - <<: *base_ubuntu_clang + <<: *base_ubuntu_clang_large steps: - checkout - setup_prerelease_commit_hash From 525381c1b5476e37b5ddb57a9390e2b0a57205aa Mon Sep 17 00:00:00 2001 From: backbonexe <117212528+LMAO798@users.noreply.github.com> Date: Fri, 20 Sep 2024 18:26:56 +0200 Subject: [PATCH 0384/1340] docs: fix broken links and typo --- docs/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 36b858679..28b81626c 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -556,7 +556,7 @@ topics, issues or feature implementations are debated in detail. The invitation We are also sharing feedback surveys and other content that is relevant to language design in the forum. -If you want to know where the team is standing in terms or implementing new features, you can follow the implementation status in the `Solidity GitHub project `_. +If you want to know where the team is standing in terms of implementing new features, you can follow the implementation status in the `Solidity GitHub project `_. Issues in the design backlog need further specification and will either be discussed in a language design call or in a regular team call. You can see the upcoming changes for the next breaking release by changing from the default branch (`develop`) to the `breaking branch `_. From 1a8efbaf79ecd06206c2f0e2dd62ec8c5b5f8145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mati=C4=87?= Date: Tue, 8 Oct 2024 09:33:56 +0200 Subject: [PATCH 0385/1340] Update docs/contributing.rst --- docs/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 28b81626c..bb88d1201 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -556,7 +556,7 @@ topics, issues or feature implementations are debated in detail. The invitation We are also sharing feedback surveys and other content that is relevant to language design in the forum. -If you want to know where the team is standing in terms of implementing new features, you can follow the implementation status in the `Solidity GitHub project `_. +If you want to know where the team is standing in terms of implementing new features, you can follow the implementation status in the `Solidity GitHub project `_. Issues in the design backlog need further specification and will either be discussed in a language design call or in a regular team call. You can see the upcoming changes for the next breaking release by changing from the default branch (`develop`) to the `breaking branch `_. From e8a2c63214457e7e2c4058849d259407964b9a44 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:38:21 +0200 Subject: [PATCH 0386/1340] Yul: Add SSACFG liveness analysis --- libyul/CMakeLists.txt | 2 + libyul/backends/evm/SSACFGLiveness.cpp | 132 +++++++++++++++++++++++++ libyul/backends/evm/SSACFGLiveness.h | 55 +++++++++++ 3 files changed, 189 insertions(+) create mode 100644 libyul/backends/evm/SSACFGLiveness.cpp create mode 100644 libyul/backends/evm/SSACFGLiveness.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index f621b2089..4265b91d3 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -65,6 +65,8 @@ add_library(yul backends/evm/NoOutputAssembly.cpp backends/evm/OptimizedEVMCodeTransform.cpp backends/evm/OptimizedEVMCodeTransform.h + backends/evm/SSACFGLiveness.cpp + backends/evm/SSACFGLiveness.h backends/evm/SSACFGLoopNestingForest.cpp backends/evm/SSACFGLoopNestingForest.h backends/evm/SSACFGTopologicalSort.cpp diff --git a/libyul/backends/evm/SSACFGLiveness.cpp b/libyul/backends/evm/SSACFGLiveness.cpp new file mode 100644 index 000000000..6ed926304 --- /dev/null +++ b/libyul/backends/evm/SSACFGLiveness.cpp @@ -0,0 +1,132 @@ +/* + 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 + +#include + +#include +#include +#include + +using namespace solidity::yul; + +SSACFGLiveness::SSACFGLiveness(SSACFG const& _cfg): + m_cfg(_cfg), + m_topologicalSort(_cfg), + m_loopNestingForest(m_topologicalSort), + m_liveIns(_cfg.numBlocks()), + m_liveOuts(_cfg.numBlocks()) +{ + runDagDfs(); + for (auto const loopRootNode: m_loopNestingForest.loopRootNodes()) + runLoopTreeDfs(loopRootNode); +} +void SSACFGLiveness::runDagDfs() +{ + // SSA Book, Algorithm 9.2 + for(auto const blockIdValue: m_topologicalSort.postOrder()) + { + // post-order traversal + SSACFG::BlockId blockId{blockIdValue}; + auto const filterLiterals = [this](auto const& valueId){ + return !std::holds_alternative(m_cfg.valueInfo(valueId)); + }; + auto const& block = m_cfg.block(blockId); + + // live <- PhiUses(B) + std::set live{}; + block.forEachExit( + [&](SSACFG::BlockId const& _successor) + { + for (auto const& phi: m_cfg.block(_successor).phis) + { + auto const& info = m_cfg.valueInfo(phi); + yulAssert(std::holds_alternative(info), "value info of phi wasn't PhiValue"); + auto const& entries = m_cfg.block(std::get(info).block).entries; + // this is getting the argument index of the phi function corresponding to the path going + // through "blockId", ie, the currently handled block + auto const it = entries.find(blockId); + yulAssert(it != entries.end()); + auto const argIndex = static_cast(std::distance(entries.begin(), it)); + if (argIndex < std::get(info).arguments.size()) + { + // todo not sure why arg index would exceed phi arg length but it does happen + auto const arg = std::get(info).arguments.at(argIndex); + if (!std::holds_alternative(m_cfg.valueInfo(arg))) + live.insert(arg); + } + else + yulAssert(false); + } + }); + + // for each S \in succs(B) s.t. (B, S) not a back edge: live <- live \cup (LiveIn(S) - PhiDefs(S)) + block.forEachExit( + [&](SSACFG::BlockId const& _successor) { + if (!m_topologicalSort.backEdge(blockId, _successor)) + live += m_liveIns[_successor.value] - m_cfg.block(_successor).phis; + }); + if (std::holds_alternative(block.exit)) + live += std::get(block.exit).returnValues + | ranges::views::filter(filterLiterals); + + // clean out unreachables + live = live + | ranges::views::filter( + [&](auto const& valueId) + { return !std::holds_alternative(m_cfg.valueInfo(valueId)); }) + | ranges::to; + + // LiveOut(B) <- live + m_liveOuts[blockId.value] = live; + + // for each program point p in B, backwards, do: + for (auto const& op: block.operations | ranges::views::reverse) + { + // remove variables defined at p from live + live -= op.outputs | ranges::views::filter(filterLiterals) | ranges::to; + // add uses at p to live + live += op.inputs | ranges::views::filter(filterLiterals) | ranges::to; + } + + // livein(b) <- live \cup PhiDefs(B) + m_liveIns[blockId.value] = live + block.phis; + } +} +void SSACFGLiveness::runLoopTreeDfs(size_t const _loopHeader) +{ + // SSA Book, Algorithm 9.3 + if (m_loopNestingForest.loopNodes().count(_loopHeader) > 0) + { + // the loop header block id + auto const& block = m_cfg.block(SSACFG::BlockId{_loopHeader}); + // LiveLoop <- LiveIn(B_N) - PhiDefs(B_N) + auto liveLoop = m_liveIns[_loopHeader] - block.phis; + // must be live out of header if live in of children + m_liveOuts[_loopHeader] += liveLoop; + // for each blockId \in children(loopHeader) + for (size_t blockId = 0; blockId < m_cfg.numBlocks(); ++blockId) + if (m_loopNestingForest.loopParents()[blockId] == _loopHeader) + { + // propagate loop liveness information down to the loop header's children + m_liveIns[blockId] += liveLoop; + m_liveOuts[blockId] += liveLoop; + + runLoopTreeDfs(blockId); + } + } +} diff --git a/libyul/backends/evm/SSACFGLiveness.h b/libyul/backends/evm/SSACFGLiveness.h new file mode 100644 index 000000000..bc254a03a --- /dev/null +++ b/libyul/backends/evm/SSACFGLiveness.h @@ -0,0 +1,55 @@ +/* + 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 + +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace solidity::yul +{ + +/// Performs liveness analysis on an SSA CFG following Algorithm 9.1 in [1]. +/// +/// [1] Rastello, Fabrice, and Florent Bouchez Tichadou, eds. SSA-based Compiler Design. Springer, 2022. +class SSACFGLiveness +{ +public: + explicit SSACFGLiveness(SSACFG const& _cfg); + + std::vector> const& liveIns() const { return m_liveIns; } + std::vector> const& liveOuts() const { return m_liveOuts; } + +private: + + void runDagDfs(); + void runLoopTreeDfs(size_t _loopHeader); + + SSACFG const& m_cfg; + ForwardSSACFGTopologicalSort m_topologicalSort; + SSACFGLoopNestingForest m_loopNestingForest; + std::vector> m_liveIns; + std::vector> m_liveOuts; +}; + +} From eb22cb6fd7b55cf70508cb76d6dda63659898df3 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:03:56 +0200 Subject: [PATCH 0387/1340] Yul: add optional liveness output to toDot of SSACFGs --- libyul/CMakeLists.txt | 2 + libyul/backends/evm/ControlFlow.cpp | 28 +++++++++ libyul/backends/evm/ControlFlow.h | 28 +++++++-- libyul/backends/evm/SSAControlFlowGraph.cpp | 30 ++++++++-- libyul/backends/evm/SSAControlFlowGraph.h | 7 ++- test/libyul/SSAControlFlowGraphTest.cpp | 4 +- test/libyul/SSAControlFlowGraphTest.h | 20 +++---- .../libyul/yulSSAControlFlowGraph/complex.yul | 57 ++++++++++++------- .../yulSSAControlFlowGraph/complex2.yul | 57 ++++++++++++------- .../yulSSAControlFlowGraph/function.yul | 15 +++-- test/libyul/yulSSAControlFlowGraph/if.yul | 9 ++- test/libyul/yulSSAControlFlowGraph/switch.yul | 18 ++++-- 12 files changed, 200 insertions(+), 75 deletions(-) create mode 100644 libyul/backends/evm/ControlFlow.cpp diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 4265b91d3..58c1b17b5 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -48,6 +48,8 @@ add_library(yul backends/evm/AsmCodeGen.h backends/evm/ConstantOptimiser.cpp backends/evm/ConstantOptimiser.h + backends/evm/ControlFlow.cpp + backends/evm/ControlFlow.h backends/evm/ControlFlowGraph.h backends/evm/ControlFlowGraphBuilder.cpp backends/evm/ControlFlowGraphBuilder.h diff --git a/libyul/backends/evm/ControlFlow.cpp b/libyul/backends/evm/ControlFlow.cpp new file mode 100644 index 000000000..3ec123a8e --- /dev/null +++ b/libyul/backends/evm/ControlFlow.cpp @@ -0,0 +1,28 @@ +/* + 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 + +#include +#include + +using namespace solidity::yul; + +ControlFlowLiveness::ControlFlowLiveness(ControlFlow const& _controlFlow): + controlFlow(_controlFlow), + mainLiveness(std::make_unique(*_controlFlow.mainGraph)), + functionLiveness(_controlFlow.functionGraphs | ranges::views::transform([](auto const& _cfg) { return std::make_unique(*_cfg); }) | ranges::to) +{ } diff --git a/libyul/backends/evm/ControlFlow.h b/libyul/backends/evm/ControlFlow.h index 59bc1b677..6438f330c 100644 --- a/libyul/backends/evm/ControlFlow.h +++ b/libyul/backends/evm/ControlFlow.h @@ -20,11 +20,22 @@ #include #include +#include #include namespace solidity::yul { +struct ControlFlow; + +struct ControlFlowLiveness{ + explicit ControlFlowLiveness(ControlFlow const& _controlFlow); + + std::reference_wrapper controlFlow; + std::unique_ptr mainLiveness; + std::vector> functionLiveness; +}; + struct ControlFlow { std::unique_ptr mainGraph{std::make_unique()}; @@ -39,14 +50,21 @@ struct ControlFlow return nullptr; } - std::string toDot() const + std::string toDot(ControlFlowLiveness const* _liveness=nullptr) const { + if (_liveness) + yulAssert(&_liveness->controlFlow.get() == this); std::ostringstream output; output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; - output << mainGraph->toDot(false); - size_t index = 1; - for (auto const& [function, functionGraph]: functionGraphMapping) - output << functionGraph->toDot(false, index++); + output << mainGraph->toDot(false, std::nullopt, _liveness ? _liveness->mainLiveness.get() : nullptr); + + for (size_t index=0; index < functionGraphs.size(); ++index) + output << functionGraphs[index]->toDot( + false, + index+1, + _liveness ? _liveness->functionLiveness[index].get() : nullptr + ); + output << "}\n"; return output.str(); } diff --git a/libyul/backends/evm/SSAControlFlowGraph.cpp b/libyul/backends/evm/SSAControlFlowGraph.cpp index e98936aaa..dcbdcdca3 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.cpp +++ b/libyul/backends/evm/SSAControlFlowGraph.cpp @@ -18,6 +18,8 @@ #include +#include + #include #include @@ -37,11 +39,13 @@ namespace class SSACFGPrinter { public: - SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId) + SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness): + m_liveness(_liveness) { printBlock(_cfg, _blockId, 0); } - SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function) + SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function, SSACFGLiveness const* _liveness): + m_liveness(_liveness) { printFunction(_cfg, _functionIndex, _function); } @@ -97,6 +101,17 @@ class SSACFGPrinter } { m_result << fmt::format("Block{1}_{0} [label=\"\\\nBlock {0}\\n", _id.value, _functionIndex); + if (m_liveness) + { + m_result << fmt::format( + "LiveIn: {}\\l\\\n", + fmt::join(m_liveness->liveIns()[_id.value] | ranges::views::transform(valueToString), ",") + ); + m_result << fmt::format( + "LiveOut: {}\\l\\n", + fmt::join(m_liveness->liveOuts()[_id.value] | ranges::views::transform(valueToString), ",") + ); + } for (auto const& phi: _block.phis) { auto const* phiValue = std::get_if(&_cfg.valueInfo(phi)); @@ -224,18 +239,23 @@ class SSACFGPrinter } std::stringstream m_result{}; + SSACFGLiveness const* m_liveness; }; } -std::string SSACFG::toDot(bool _includeDiGraphDefinition, std::optional _functionIndex) const +std::string SSACFG::toDot( + bool _includeDiGraphDefinition, + std::optional _functionIndex, + SSACFGLiveness const* _liveness +) const { std::ostringstream output; if (_includeDiGraphDefinition) output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; if (function) - output << SSACFGPrinter(*this, _functionIndex ? *_functionIndex : static_cast(1), *function); + output << SSACFGPrinter(*this, _functionIndex ? *_functionIndex : static_cast(1), *function, _liveness); else - output << SSACFGPrinter(*this, entry); + output << SSACFGPrinter(*this, entry, _liveness); if (_includeDiGraphDefinition) output << "}\n"; return output.str(); diff --git a/libyul/backends/evm/SSAControlFlowGraph.h b/libyul/backends/evm/SSAControlFlowGraph.h index fd24f06cb..00f12fc71 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.h +++ b/libyul/backends/evm/SSAControlFlowGraph.h @@ -37,6 +37,7 @@ namespace solidity::yul { +class SSACFGLiveness; class SSACFG { @@ -207,7 +208,11 @@ class SSACFG return it->second; } - std::string toDot(bool _includeDiGraphDefinition=true, std::optional _functionIndex=std::nullopt) const; + std::string toDot( + bool _includeDiGraphDefinition=true, + std::optional _functionIndex=std::nullopt, + SSACFGLiveness const* _liveness=nullptr + ) const; private: std::deque m_valueInfos; std::map m_literals; diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/SSAControlFlowGraphTest.cpp index c0d1e8727..5f0c79da5 100644 --- a/test/libyul/SSAControlFlowGraphTest.cpp +++ b/test/libyul/SSAControlFlowGraphTest.cpp @@ -72,8 +72,8 @@ TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::st *m_dialect, object->code()->root() ); - - m_obtainedResult = controlFlow->toDot(); + ControlFlowLiveness liveness(*controlFlow); + m_obtainedResult = controlFlow->toDot(&liveness); auto result = checkResult(_stream, _linePrefix, _formatted); diff --git a/test/libyul/SSAControlFlowGraphTest.h b/test/libyul/SSAControlFlowGraphTest.h index f976be03c..09c104486 100644 --- a/test/libyul/SSAControlFlowGraphTest.h +++ b/test/libyul/SSAControlFlowGraphTest.h @@ -1,18 +1,18 @@ /* -This file is part of solidity. + This file is part of solidity. -solidity is free software: you can redistribute it and/or modify + 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. + 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. + 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 . + You should have received a copy of the GNU General Public License + along with solidity. If not, see . */ // SPDX-License-Identifier: GPL-3.0 diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index eef0b29fa..799e53d06 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -52,7 +52,8 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nv2 := f(2, 1)\l\ +// Block 0\nLiveIn: \l\ +// LiveOut: \l\nv2 := f(2, 1)\l\ // pop(v2)\l\ // "]; // Block0_0Exit [label="MainExit"]; @@ -61,12 +62,14 @@ // c := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\n"]; +// Block 0\nLiveIn: v0,v1\l\ +// LiveOut: v0,v1\l\n"]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1; // Block1_1 [label="\ -// Block 1\nv5 := φ(\l\ +// Block 1\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ // )\l\ @@ -77,7 +80,8 @@ // Block1_1Exit:0 -> Block1_4; // Block1_1Exit:1 -> Block1_2; // Block1_2 [label="\ -// Block 2\nv7 := mload(v5)\l\ +// Block 2\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ // v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; @@ -85,80 +89,93 @@ // Block1_2Exit:0 -> Block1_7; // Block1_2Exit:1 -> Block1_6; // Block1_4 [label="\ -// Block 4\nsstore(3084, 12)\l\ +// Block 4\nLiveIn: \l\ +// LiveOut: \l\nsstore(3084, 12)\l\ // "]; // Block1_4Exit [label="FunctionReturn[0]"]; // Block1_4 -> Block1_4Exit; // Block1_6 [label="\ -// Block 6\nsstore(514, 2)\l\ +// Block 6\nLiveIn: \l\ +// LiveOut: \l\nsstore(514, 2)\l\ // "]; // Block1_6 -> Block1_6Exit [arrowhead=none]; // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4; // Block1_7 [label="\ -// Block 7\nv13 := eq(1, v7)\l\ +// Block 7\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; // Block1_7Exit [label="{ If v13| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_7Exit:0 -> Block1_10; // Block1_7Exit:1 -> Block1_9; // Block1_9 [label="\ -// Block 9\nsstore(1028, 4)\l\ +// Block 9\nLiveIn: \l\ +// LiveOut: \l\nsstore(1028, 4)\l\ // "]; // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10\nv20 := eq(2, v7)\l\ +// Block 10\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; // Block1_10Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_10Exit:0 -> Block1_13; // Block1_10Exit:1 -> Block1_12; // Block1_12 [label="\ -// Block 12\nsstore(1542, 6)\l\ +// Block 12\nLiveIn: \l\ +// LiveOut: \l\nsstore(1542, 6)\l\ // revert(0, 0)\l\ // "]; // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13\nv25 := eq(3, v7)\l\ +// Block 13\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; // Block1_13Exit [label="{ If v25| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16; // Block1_13Exit:1 -> Block1_15; // Block1_15 [label="\ -// Block 15\nsstore(2056, 8)\l\ +// Block 15\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2056, 8)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; // Block1_15Exit -> Block1_5; // Block1_16 [label="\ -// Block 16\nv29 := mload(v1)\l\ +// Block 16\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; // Block1_16Exit [label="{ If v29| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18; // Block1_16Exit:1 -> Block1_17; // Block1_5 [label="\ -// Block 5\nsstore(2827, 11)\l\ +// Block 5\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2827, 11)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; // Block1_5Exit -> Block1_3; // Block1_17 [label="\ -// Block 17\nreturn(0, 0)\l\ +// Block 17\nLiveIn: \l\ +// LiveOut: \l\nreturn(0, 0)\l\ // "]; // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18\nsstore(2570, 10)\l\ +// Block 18\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2570, 10)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5; // Block1_3 [label="\ -// Block 3\nv43 := add(1, v5)\l\ +// Block 3\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; @@ -166,12 +183,14 @@ // Block1_3Exit:0 -> Block1_21; // Block1_3Exit:1 -> Block1_20; // Block1_20 [label="\ -// Block 20\nsstore(v43, 0)\l\ +// Block 20\nLiveIn: v43\l\ +// LiveOut: \l\nsstore(v43, 0)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21\nsstore(65535, 255)\l\ +// Block 21\nLiveIn: v0,v1,v43\l\ +// LiveOut: v0,v1,v43\l\nsstore(65535, 255)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index 743b0513c..b35f34141 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -59,7 +59,8 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nsstore(1, 1)\l\ +// Block 0\nLiveIn: \l\ +// LiveOut: \l\nsstore(1, 1)\l\ // v2 := f(2, 1)\l\ // pop(v2)\l\ // v4 := sload(0)\l\ @@ -77,12 +78,14 @@ // c := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\n"]; +// Block 0\nLiveIn: v0,v1\l\ +// LiveOut: v0,v1\l\n"]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1; // Block1_1 [label="\ -// Block 1\nv5 := φ(\l\ +// Block 1\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ // )\l\ @@ -93,7 +96,8 @@ // Block1_1Exit:0 -> Block1_4; // Block1_1Exit:1 -> Block1_2; // Block1_2 [label="\ -// Block 2\nv7 := mload(v5)\l\ +// Block 2\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ // v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; @@ -101,80 +105,93 @@ // Block1_2Exit:0 -> Block1_7; // Block1_2Exit:1 -> Block1_6; // Block1_4 [label="\ -// Block 4\nsstore(3084, 12)\l\ +// Block 4\nLiveIn: \l\ +// LiveOut: \l\nsstore(3084, 12)\l\ // "]; // Block1_4Exit [label="FunctionReturn[27]"]; // Block1_4 -> Block1_4Exit; // Block1_6 [label="\ -// Block 6\nsstore(514, 2)\l\ +// Block 6\nLiveIn: \l\ +// LiveOut: \l\nsstore(514, 2)\l\ // "]; // Block1_6 -> Block1_6Exit [arrowhead=none]; // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4; // Block1_7 [label="\ -// Block 7\nv13 := eq(1, v7)\l\ +// Block 7\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; // Block1_7Exit [label="{ If v13| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_7Exit:0 -> Block1_10; // Block1_7Exit:1 -> Block1_9; // Block1_9 [label="\ -// Block 9\nsstore(1028, 4)\l\ +// Block 9\nLiveIn: \l\ +// LiveOut: \l\nsstore(1028, 4)\l\ // "]; // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10\nv20 := eq(2, v7)\l\ +// Block 10\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; // Block1_10Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_10Exit:0 -> Block1_13; // Block1_10Exit:1 -> Block1_12; // Block1_12 [label="\ -// Block 12\nsstore(1542, 6)\l\ +// Block 12\nLiveIn: \l\ +// LiveOut: \l\nsstore(1542, 6)\l\ // revert(0, 0)\l\ // "]; // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13\nv25 := eq(3, v7)\l\ +// Block 13\nLiveIn: v0,v1,v5,v7\l\ +// LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; // Block1_13Exit [label="{ If v25| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16; // Block1_13Exit:1 -> Block1_15; // Block1_15 [label="\ -// Block 15\nsstore(2056, 8)\l\ +// Block 15\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2056, 8)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; // Block1_15Exit -> Block1_5; // Block1_16 [label="\ -// Block 16\nv29 := mload(v1)\l\ +// Block 16\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; // Block1_16Exit [label="{ If v29| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18; // Block1_16Exit:1 -> Block1_17; // Block1_5 [label="\ -// Block 5\nsstore(2827, 11)\l\ +// Block 5\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2827, 11)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; // Block1_5Exit -> Block1_3; // Block1_17 [label="\ -// Block 17\nreturn(0, 0)\l\ +// Block 17\nLiveIn: \l\ +// LiveOut: \l\nreturn(0, 0)\l\ // "]; // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18\nsstore(2570, 10)\l\ +// Block 18\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v5\l\nsstore(2570, 10)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5; // Block1_3 [label="\ -// Block 3\nv43 := add(1, v5)\l\ +// Block 3\nLiveIn: v0,v1,v5\l\ +// LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; @@ -182,12 +199,14 @@ // Block1_3Exit:0 -> Block1_21; // Block1_3Exit:1 -> Block1_20; // Block1_20 [label="\ -// Block 20\nsstore(v43, 0)\l\ +// Block 20\nLiveIn: v43\l\ +// LiveOut: \l\nsstore(v43, 0)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21\nsstore(65535, 255)\l\ +// Block 21\nLiveIn: v0,v1,v43\l\ +// LiveOut: v0,v1,v43\l\nsstore(65535, 255)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/yulSSAControlFlowGraph/function.yul index 20a536b5e..1b759f8b3 100644 --- a/test/libyul/yulSSAControlFlowGraph/function.yul +++ b/test/libyul/yulSSAControlFlowGraph/function.yul @@ -27,7 +27,8 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nv0, v1 := i()\l\ +// Block 0\nLiveIn: \l\ +// LiveOut: \l\nv0, v1 := i()\l\ // h(v0)\l\ // "]; // Block0_0Exit [label="Terminated"]; @@ -36,7 +37,8 @@ // r := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\nv3 := add(v1, v0)\l\ +// Block 0\nLiveIn: v0,v1\l\ +// LiveOut: v4\l\nv3 := add(v1, v0)\l\ // v4 := sub(v0, v3)\l\ // "]; // Block1_0Exit [label="FunctionReturn[v4]"]; @@ -45,7 +47,8 @@ // g()"]; // FunctionEntry_g_0 -> Block2_0; // Block2_0 [label="\ -// Block 0\nsstore(257, 1)\l\ +// Block 0\nLiveIn: \l\ +// LiveOut: \l\nsstore(257, 1)\l\ // "]; // Block2_0Exit [label="FunctionReturn[]"]; // Block2_0 -> Block2_0Exit; @@ -53,7 +56,8 @@ // h(v0)"]; // FunctionEntry_h_0 -> Block3_0; // Block3_0 [label="\ -// Block 0\nv2 := f(0, v0)\l\ +// Block 0\nLiveIn: v0\l\ +// LiveOut: \l\nv2 := f(0, v0)\l\ // h(v2)\l\ // "]; // Block3_0Exit [label="Terminated"]; @@ -62,7 +66,8 @@ // v, w := i()"]; // FunctionEntry_i_0 -> Block4_0; // Block4_0 [label="\ -// Block 0\n"]; +// Block 0\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block4_0Exit [label="FunctionReturn[514, 771]"]; // Block4_0 -> Block4_0Exit; // } diff --git a/test/libyul/yulSSAControlFlowGraph/if.yul b/test/libyul/yulSSAControlFlowGraph/if.yul index 9045d8034..9c4d73a13 100644 --- a/test/libyul/yulSSAControlFlowGraph/if.yul +++ b/test/libyul/yulSSAControlFlowGraph/if.yul @@ -15,20 +15,23 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nv1 := calldataload(3)\l\ +// Block 0\nLiveIn: \l\ +// LiveOut: v1\l\nv1 := calldataload(3)\l\ // "]; // Block0_0 -> Block0_0Exit; // Block0_0Exit [label="{ If 0| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_0Exit:0 -> Block0_2; // Block0_0Exit:1 -> Block0_1; // Block0_1 [label="\ -// Block 1\nv4 := calldataload(77)\l\ +// Block 1\nLiveIn: \l\ +// LiveOut: v4\l\nv4 := calldataload(77)\l\ // "]; // Block0_1 -> Block0_1Exit [arrowhead=none]; // Block0_1Exit [label="Jump" shape=oval]; // Block0_1Exit -> Block0_2; // Block0_2 [label="\ -// Block 2\nv5 := φ(\l\ +// Block 2\nLiveIn: v5\l\ +// LiveOut: \l\nv5 := φ(\l\ // Block 0 => v1,\l\ // Block 1 => v4\l\ // )\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/switch.yul b/test/libyul/yulSSAControlFlowGraph/switch.yul index f6c084b00..d744bd7bd 100644 --- a/test/libyul/yulSSAControlFlowGraph/switch.yul +++ b/test/libyul/yulSSAControlFlowGraph/switch.yul @@ -22,7 +22,8 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nv1 := calldataload(3)\l\ +// Block 0\nLiveIn: \l\ +// LiveOut: v3\l\nv1 := calldataload(3)\l\ // v3 := sload(0)\l\ // v4 := eq(0, v3)\l\ // "]; @@ -31,20 +32,23 @@ // Block0_0Exit:0 -> Block0_3; // Block0_0Exit:1 -> Block0_2; // Block0_2 [label="\ -// Block 2\nv6 := calldataload(77)\l\ +// Block 2\nLiveIn: \l\ +// LiveOut: v6\l\nv6 := calldataload(77)\l\ // "]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; // Block0_2Exit -> Block0_1; // Block0_3 [label="\ -// Block 3\nv7 := eq(1, v3)\l\ +// Block 3\nLiveIn: v3\l\ +// LiveOut: \l\nv7 := eq(1, v3)\l\ // "]; // Block0_3 -> Block0_3Exit; // Block0_3Exit [label="{ If v7| { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_3Exit:0 -> Block0_5; // Block0_3Exit:1 -> Block0_4; // Block0_1 [label="\ -// Block 1\nv13 := φ(\l\ +// Block 1\nLiveIn: v13\l\ +// LiveOut: \l\nv13 := φ(\l\ // Block 2 => v6,\l\ // Block 4 => v10,\l\ // Block 5 => v12\l\ @@ -54,13 +58,15 @@ // Block0_1Exit [label="MainExit"]; // Block0_1 -> Block0_1Exit; // Block0_4 [label="\ -// Block 4\nv10 := calldataload(88)\l\ +// Block 4\nLiveIn: \l\ +// LiveOut: v10\l\nv10 := calldataload(88)\l\ // "]; // Block0_4 -> Block0_4Exit [arrowhead=none]; // Block0_4Exit [label="Jump" shape=oval]; // Block0_4Exit -> Block0_1; // Block0_5 [label="\ -// Block 5\nv12 := calldataload(99)\l\ +// Block 5\nLiveIn: \l\ +// LiveOut: v12\l\nv12 := calldataload(99)\l\ // "]; // Block0_5 -> Block0_5Exit [arrowhead=none]; // Block0_5Exit [label="Jump" shape=oval]; From f35fd1f6df3f0d341ead02d9a83c39f018ba168e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:01:25 +0200 Subject: [PATCH 0388/1340] Yul: display dotted back edges in toDot --- libyul/backends/evm/SSACFGLiveness.cpp | 8 +- libyul/backends/evm/SSACFGLiveness.h | 2 +- libyul/backends/evm/SSACFGTopologicalSort.h | 2 + libyul/backends/evm/SSAControlFlowGraph.cpp | 111 ++++++++----- .../libyul/yulSSAControlFlowGraph/complex.yul | 92 +++++------ .../yulSSAControlFlowGraph/complex2.yul | 92 +++++------ .../yulSSAControlFlowGraph/function.yul | 10 +- test/libyul/yulSSAControlFlowGraph/if.yul | 14 +- .../yulSSAControlFlowGraph/nested_for.yul | 151 ++++++++++-------- .../nested_function.yul | 55 ++++--- test/libyul/yulSSAControlFlowGraph/switch.yul | 30 ++-- 11 files changed, 313 insertions(+), 254 deletions(-) diff --git a/libyul/backends/evm/SSACFGLiveness.cpp b/libyul/backends/evm/SSACFGLiveness.cpp index 6ed926304..b9513f70d 100644 --- a/libyul/backends/evm/SSACFGLiveness.cpp +++ b/libyul/backends/evm/SSACFGLiveness.cpp @@ -38,7 +38,7 @@ SSACFGLiveness::SSACFGLiveness(SSACFG const& _cfg): void SSACFGLiveness::runDagDfs() { // SSA Book, Algorithm 9.2 - for(auto const blockIdValue: m_topologicalSort.postOrder()) + for (auto const blockIdValue: m_topologicalSort.postOrder()) { // post-order traversal SSACFG::BlockId blockId{blockIdValue}; @@ -85,11 +85,7 @@ void SSACFGLiveness::runDagDfs() | ranges::views::filter(filterLiterals); // clean out unreachables - live = live - | ranges::views::filter( - [&](auto const& valueId) - { return !std::holds_alternative(m_cfg.valueInfo(valueId)); }) - | ranges::to; + live = live | ranges::views::filter([&](auto const& valueId) { return !std::holds_alternative(m_cfg.valueInfo(valueId)); }) | ranges::to; // LiveOut(B) <- live m_liveOuts[blockId.value] = live; diff --git a/libyul/backends/evm/SSACFGLiveness.h b/libyul/backends/evm/SSACFGLiveness.h index bc254a03a..6f486b737 100644 --- a/libyul/backends/evm/SSACFGLiveness.h +++ b/libyul/backends/evm/SSACFGLiveness.h @@ -39,7 +39,7 @@ class SSACFGLiveness std::vector> const& liveIns() const { return m_liveIns; } std::vector> const& liveOuts() const { return m_liveOuts; } - + ForwardSSACFGTopologicalSort const& topologicalSort() const { return m_topologicalSort; } private: void runDagDfs(); diff --git a/libyul/backends/evm/SSACFGTopologicalSort.h b/libyul/backends/evm/SSACFGTopologicalSort.h index 973f286f2..025054b95 100644 --- a/libyul/backends/evm/SSACFGTopologicalSort.h +++ b/libyul/backends/evm/SSACFGTopologicalSort.h @@ -38,6 +38,8 @@ class ForwardSSACFGTopologicalSort std::set const& backEdgeTargets() const { return m_backEdgeTargets; } SSACFG const& cfg() const { return m_cfg; } bool backEdge(SSACFG::BlockId const& _block1, SSACFG::BlockId const& _block2) const; + size_t preOrderIndexOf(size_t _block) const { return m_blockWisePreOrder[_block]; } + size_t maxSubtreePreOrderIndexOf(size_t _block) const { return m_blockWiseMaxSubtreePreOrder[_block]; } private: void dfs(size_t _vertex); diff --git a/libyul/backends/evm/SSAControlFlowGraph.cpp b/libyul/backends/evm/SSAControlFlowGraph.cpp index dcbdcdca3..ebd6d84a9 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.cpp +++ b/libyul/backends/evm/SSAControlFlowGraph.cpp @@ -40,14 +40,14 @@ class SSACFGPrinter { public: SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness): - m_liveness(_liveness) + m_cfg(_cfg), m_functionIndex(0), m_liveness(_liveness) { - printBlock(_cfg, _blockId, 0); + printBlock(_blockId); } SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function, SSACFGLiveness const* _liveness): - m_liveness(_liveness) + m_cfg(_cfg), m_functionIndex(_functionIndex), m_liveness(_liveness) { - printFunction(_cfg, _functionIndex, _function); + printFunction(_function); } friend std::ostream& operator<<(std::ostream& stream, SSACFGPrinter const& printer) { stream << printer.m_result.str(); @@ -77,6 +77,20 @@ class SSACFGPrinter ); } + std::string formatBlockHandle(SSACFG::BlockId const& _id) const + { + return fmt::format("Block{}_{}", m_functionIndex, _id.value); + } + + std::string formatEdge(SSACFG::BlockId const& _v, SSACFG::BlockId const& _w, std::optional const& _vPort = std::nullopt) + { + std::string const style = m_liveness && m_liveness->topologicalSort().backEdge(_v, _w) ? "dashed" : "solid"; + if (_vPort) + return fmt::format("{}Exit:{} -> {} [style=\"{}\"];\n", formatBlockHandle(_v), *_vPort, formatBlockHandle(_w), style); + else + return fmt::format("{}Exit -> {} [style=\"{}\"];\n", formatBlockHandle(_v), formatBlockHandle(_w), style); + } + static std::string formatPhi(SSACFG const& _cfg, SSACFG::PhiValue const& _phiValue) { auto const transform = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; @@ -90,19 +104,25 @@ class SSACFGPrinter return "φ()"; } - void writeBlock(SSACFG const& _cfg, SSACFG::BlockId const& _id, SSACFG::BasicBlock const& _block, size_t const _functionIndex) + void writeBlock(SSACFG::BlockId const& _id, SSACFG::BasicBlock const& _block) { - auto const valueToString = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; - bool entryBlock = _id.value == 0 && _functionIndex == 0; + auto const valueToString = [&](SSACFG::ValueId const& valueId) { return varToString(m_cfg, valueId); }; + bool entryBlock = _id.value == 0 && m_functionIndex == 0; if (entryBlock) { - m_result << fmt::format("Entry{} [label=\"Entry\"];\n", _functionIndex); - m_result << fmt::format("Entry{} -> Block{}_{};\n", _functionIndex, _functionIndex, _id.value); + m_result << fmt::format("Entry{} [label=\"Entry\"];\n", m_functionIndex); + m_result << fmt::format("Entry{} -> {};\n", m_functionIndex, formatBlockHandle(_id)); } { - m_result << fmt::format("Block{1}_{0} [label=\"\\\nBlock {0}\\n", _id.value, _functionIndex); if (m_liveness) { + m_result << fmt::format( + "{} [label=\"\\\nBlock {}; ({}, max {})\\n", + formatBlockHandle(_id), + _id.value, + m_liveness->topologicalSort().preOrderIndexOf(_id.value), + m_liveness->topologicalSort().maxSubtreePreOrderIndexOf(_id.value) + ); m_result << fmt::format( "LiveIn: {}\\l\\\n", fmt::join(m_liveness->liveIns()[_id.value] | ranges::views::transform(valueToString), ",") @@ -112,11 +132,13 @@ class SSACFGPrinter fmt::join(m_liveness->liveOuts()[_id.value] | ranges::views::transform(valueToString), ",") ); } + else + m_result << fmt::format("{} [label=\"\\\nBlock {}\\n", formatBlockHandle(_id), _id.value); for (auto const& phi: _block.phis) { - auto const* phiValue = std::get_if(&_cfg.valueInfo(phi)); + auto const* phiValue = std::get_if(&m_cfg.valueInfo(phi)); solAssert(phiValue); - m_result << fmt::format("v{} := {}\\l\\\n", phi.value, formatPhi(_cfg, *phiValue)); + m_result << fmt::format("v{} := {}\\l\\\n", phi.value, formatPhi(m_cfg, *phiValue)); } for (auto const& operation: _block.operations) { @@ -143,29 +165,28 @@ class SSACFGPrinter std::visit(GenericVisitor{ [&](SSACFG::BasicBlock::MainExit const&) { - m_result << fmt::format("Block{}_{}Exit [label=\"MainExit\"];\n", _functionIndex, _id.value); - m_result << fmt::format("Block{1}_{0} -> Block{1}_{0}Exit;\n", _id.value, _functionIndex); + m_result << fmt::format("{}Exit [label=\"MainExit\"];\n", formatBlockHandle(_id)); + m_result << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); }, [&](SSACFG::BasicBlock::Jump const& _jump) { - m_result << fmt::format("Block{1}_{0} -> Block{1}_{0}Exit [arrowhead=none];\n", _id.value, _functionIndex); - m_result << fmt::format("Block{}_{}Exit [label=\"Jump\" shape=oval];\n", _functionIndex, _id.value); - m_result << fmt::format("Block{}_{}Exit -> Block{}_{};\n", _functionIndex, _id.value, _functionIndex, _jump.target.value); + m_result << fmt::format("{} -> {}Exit [arrowhead=none];\n", formatBlockHandle(_id), formatBlockHandle(_id)); + m_result << fmt::format("{}Exit [label=\"Jump\" shape=oval];\n", formatBlockHandle(_id)); + m_result << formatEdge(_id, _jump.target); }, [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; - m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"{ If "; - m_result << varToString(_cfg, _conditionalJump.condition); - m_result << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; - m_result << "Block" << _functionIndex << "_" << _id.value; - m_result << "Exit:0 -> Block" << _functionIndex << "_" << _conditionalJump.zero.value << ";\n"; - m_result << "Block" << _functionIndex << "_" << _id.value; - m_result << "Exit:1 -> Block" << _functionIndex << "_" << _conditionalJump.nonZero.value << ";\n"; + m_result << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); + m_result << fmt::format( + "{}Exit [label=\"{{ If {} | {{ <0> Zero | <1> NonZero }}}}\" shape=Mrecord];\n", + formatBlockHandle(_id), varToString(m_cfg, _conditionalJump.condition) + ); + m_result << formatEdge(_id, _conditionalJump.zero, "0"); + m_result << formatEdge(_id, _conditionalJump.nonZero, "1"); }, [&](SSACFG::BasicBlock::JumpTable const& jt) { - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + m_result << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); std::string options; for (auto const& jumpCase: jt.cases) { @@ -176,28 +197,28 @@ class SSACFGPrinter if (!options.empty()) options += " | "; options += " default"; - m_result << fmt::format("Block{}_{}Exit [label=\"{{ JT | {{ {} }} }}\" shape=Mrecord];\n", _functionIndex, _id.value, options); + m_result << fmt::format("{}Exit [label=\"{{ JT | {{ {} }} }}\" shape=Mrecord];\n", formatBlockHandle(_id), options); for (auto const& jumpCase: jt.cases) - m_result << fmt::format("Block{}_{}Exit:{} -> Block{}_{};\n", _functionIndex, _id.value, formatNumber(jumpCase.first), _functionIndex, jumpCase.second.value); - m_result << fmt::format("Block{}_{}Exit:default -> Block{}_{};\n", _functionIndex, _id.value, _functionIndex, jt.defaultCase.value); + m_result << formatEdge(_id, jumpCase.second, formatNumber(jumpCase.first)); + m_result << formatEdge(_id, jt.defaultCase, "default"); }, [&](SSACFG::BasicBlock::FunctionReturn const& fr) { - m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"FunctionReturn[" + m_result << formatBlockHandle(_id) << "Exit [label=\"FunctionReturn[" << fmt::format("{}", fmt::join(fr.returnValues | ranges::views::transform(valueToString), ", ")) << "]\"];\n"; - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + m_result << formatBlockHandle(_id) << " -> " << formatBlockHandle(_id) << "Exit;\n"; }, [&](SSACFG::BasicBlock::Terminated const&) { - m_result << "Block" << _functionIndex << "_" << _id.value << "Exit [label=\"Terminated\"];\n"; - m_result << "Block" << _functionIndex << "_" << _id.value << " -> Block" << _functionIndex << "_" << _id.value << "Exit;\n"; + m_result << formatBlockHandle(_id) << "Exit [label=\"Terminated\"];\n"; + m_result << formatBlockHandle(_id) << " -> " << formatBlockHandle(_id) << "Exit;\n"; } }, _block.exit); } } - void printBlock(SSACFG const& _cfg, SSACFG::BlockId const& _rootId, size_t const _functionIndex) + void printBlock(SSACFG::BlockId const& _rootId) { std::set explored{}; explored.insert(_rootId); @@ -209,8 +230,8 @@ class SSACFGPrinter { auto const id = toVisit.front(); toVisit.pop_front(); - auto const& block = _cfg.block(id); - writeBlock(_cfg, id, block, _functionIndex); + auto const& block = m_cfg.block(id); + writeBlock(id, block); block.forEachExit( [&](SSACFG::BlockId const& _exitBlock) { @@ -224,22 +245,24 @@ class SSACFGPrinter } } - void printFunction(SSACFG const& _cfg, size_t const _functionIndex, Scope::Function const& _fun) + void printFunction(Scope::Function const& _fun) { static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return functionReturnValue.get().name.str(); }; static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", std::get<1>(arg).value); }; - m_result << "FunctionEntry_" << _fun.name.str() << "_" << _cfg.entry.value << " [label=\""; - if (!_cfg.returns.empty()) - m_result << fmt::format("function {0}:\n {1} := {0}({2})", _fun.name.str(), fmt::join(_cfg.returns | ranges::views::transform(returnsTransform), ", "), fmt::join(_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + m_result << "FunctionEntry_" << _fun.name.str() << "_" << m_cfg.entry.value << " [label=\""; + if (!m_cfg.returns.empty()) + m_result << fmt::format("function {0}:\n {1} := {0}({2})", _fun.name.str(), fmt::join(m_cfg.returns | ranges::views::transform(returnsTransform), ", "), fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); else - m_result << fmt::format("function {0}:\n {0}({1})", _fun.name.str(), fmt::join(_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + m_result << fmt::format("function {0}:\n {0}({1})", _fun.name.str(), fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); m_result << "\"];\n"; - m_result << "FunctionEntry_" << _fun.name.str() << "_" << _cfg.entry.value << " -> Block" << _functionIndex << "_" << _cfg.entry.value << ";\n"; - printBlock(_cfg, _cfg.entry, _functionIndex); + m_result << "FunctionEntry_" << _fun.name.str() << "_" << m_cfg.entry.value << " -> Block" << m_functionIndex << "_" << m_cfg.entry.value << ";\n"; + printBlock(m_cfg.entry); } - std::stringstream m_result{}; + SSACFG const& m_cfg; + size_t m_functionIndex; SSACFGLiveness const* m_liveness; + std::stringstream m_result{}; }; } diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index 799e53d06..6fb0453c1 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -52,7 +52,7 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nLiveIn: \l\ +// Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\nv2 := f(2, 1)\l\ // pop(v2)\l\ // "]; @@ -62,13 +62,13 @@ // c := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\nLiveIn: v0,v1\l\ +// Block 0; (0, max 17)\nLiveIn: v0,v1\l\ // LiveOut: v0,v1\l\n"]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; -// Block1_0Exit -> Block1_1; +// Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1\nLiveIn: v0,v1,v5\l\ +// Block 1; (1, max 17)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5\l\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ @@ -76,123 +76,123 @@ // v6 := lt(v0, v5)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v6| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_1Exit:0 -> Block1_4; -// Block1_1Exit:1 -> Block1_2; +// Block1_1Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit:0 -> Block1_4 [style="solid"]; +// Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2\nLiveIn: v0,v1,v5\l\ +// Block 2; (2, max 17)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ // v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v8| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_2Exit:0 -> Block1_7; -// Block1_2Exit:1 -> Block1_6; +// Block1_2Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit:0 -> Block1_7 [style="solid"]; +// Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ -// Block 4\nLiveIn: \l\ +// Block 4; (4, max 4)\nLiveIn: \l\ // LiveOut: \l\nsstore(3084, 12)\l\ // "]; // Block1_4Exit [label="FunctionReturn[0]"]; // Block1_4 -> Block1_4Exit; // Block1_6 [label="\ -// Block 6\nLiveIn: \l\ +// Block 6; (3, max 4)\nLiveIn: \l\ // LiveOut: \l\nsstore(514, 2)\l\ // "]; // Block1_6 -> Block1_6Exit [arrowhead=none]; // Block1_6Exit [label="Jump" shape=oval]; -// Block1_6Exit -> Block1_4; +// Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7\nLiveIn: v0,v1,v5,v7\l\ +// Block 7; (5, max 17)\nLiveIn: v0,v1,v5,v7\l\ // LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v13| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_7Exit:0 -> Block1_10; -// Block1_7Exit:1 -> Block1_9; +// Block1_7Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit:0 -> Block1_10 [style="solid"]; +// Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ -// Block 9\nLiveIn: \l\ +// Block 9; (6, max 6)\nLiveIn: \l\ // LiveOut: \l\nsstore(1028, 4)\l\ // "]; // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10\nLiveIn: v0,v1,v5,v7\l\ +// Block 10; (7, max 17)\nLiveIn: v0,v1,v5,v7\l\ // LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_10Exit:0 -> Block1_13; -// Block1_10Exit:1 -> Block1_12; +// Block1_10Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit:0 -> Block1_13 [style="solid"]; +// Block1_10Exit:1 -> Block1_12 [style="solid"]; // Block1_12 [label="\ -// Block 12\nLiveIn: \l\ +// Block 12; (8, max 8)\nLiveIn: \l\ // LiveOut: \l\nsstore(1542, 6)\l\ // revert(0, 0)\l\ // "]; // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13\nLiveIn: v0,v1,v5,v7\l\ +// Block 13; (9, max 17)\nLiveIn: v0,v1,v5,v7\l\ // LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v25| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_13Exit:0 -> Block1_16; -// Block1_13Exit:1 -> Block1_15; +// Block1_13Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit:0 -> Block1_16 [style="solid"]; +// Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15\nLiveIn: v0,v1,v5\l\ +// Block 15; (10, max 14)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5\l\nsstore(2056, 8)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; -// Block1_15Exit -> Block1_5; +// Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16\nLiveIn: v0,v1,v5\l\ +// Block 16; (15, max 17)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v29| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_16Exit:0 -> Block1_18; -// Block1_16Exit:1 -> Block1_17; +// Block1_16Exit [label="{ If v29 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit:0 -> Block1_18 [style="solid"]; +// Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5\nLiveIn: v0,v1,v5\l\ +// Block 5; (11, max 14)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5\l\nsstore(2827, 11)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; -// Block1_5Exit -> Block1_3; +// Block1_5Exit -> Block1_3 [style="solid"]; // Block1_17 [label="\ -// Block 17\nLiveIn: \l\ +// Block 17; (16, max 16)\nLiveIn: \l\ // LiveOut: \l\nreturn(0, 0)\l\ // "]; // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18\nLiveIn: v0,v1,v5\l\ +// Block 18; (17, max 17)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5\l\nsstore(2570, 10)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; -// Block1_18Exit -> Block1_5; +// Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3\nLiveIn: v0,v1,v5\l\ +// Block 3; (12, max 14)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v44| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_3Exit:0 -> Block1_21; -// Block1_3Exit:1 -> Block1_20; +// Block1_3Exit [label="{ If v44 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit:0 -> Block1_21 [style="solid"]; +// Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20\nLiveIn: v43\l\ +// Block 20; (13, max 13)\nLiveIn: v43\l\ // LiveOut: \l\nsstore(v43, 0)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21\nLiveIn: v0,v1,v43\l\ +// Block 21; (14, max 14)\nLiveIn: v0,v1,v43\l\ // LiveOut: v0,v1,v43\l\nsstore(65535, 255)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; -// Block1_21Exit -> Block1_1; +// Block1_21Exit -> Block1_1 [style="dashed"]; // } diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index b35f34141..c3ea8b94f 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -59,7 +59,7 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nLiveIn: \l\ +// Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\nsstore(1, 1)\l\ // v2 := f(2, 1)\l\ // pop(v2)\l\ @@ -78,13 +78,13 @@ // c := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\nLiveIn: v0,v1\l\ +// Block 0; (0, max 17)\nLiveIn: v0,v1\l\ // LiveOut: v0,v1\l\n"]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; -// Block1_0Exit -> Block1_1; +// Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1\nLiveIn: v0,v1,v5\l\ +// Block 1; (1, max 17)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5\l\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ @@ -92,123 +92,123 @@ // v6 := lt(v0, v5)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v6| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_1Exit:0 -> Block1_4; -// Block1_1Exit:1 -> Block1_2; +// Block1_1Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit:0 -> Block1_4 [style="solid"]; +// Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2\nLiveIn: v0,v1,v5\l\ +// Block 2; (2, max 17)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ // v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v8| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_2Exit:0 -> Block1_7; -// Block1_2Exit:1 -> Block1_6; +// Block1_2Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit:0 -> Block1_7 [style="solid"]; +// Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ -// Block 4\nLiveIn: \l\ +// Block 4; (4, max 4)\nLiveIn: \l\ // LiveOut: \l\nsstore(3084, 12)\l\ // "]; // Block1_4Exit [label="FunctionReturn[27]"]; // Block1_4 -> Block1_4Exit; // Block1_6 [label="\ -// Block 6\nLiveIn: \l\ +// Block 6; (3, max 4)\nLiveIn: \l\ // LiveOut: \l\nsstore(514, 2)\l\ // "]; // Block1_6 -> Block1_6Exit [arrowhead=none]; // Block1_6Exit [label="Jump" shape=oval]; -// Block1_6Exit -> Block1_4; +// Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7\nLiveIn: v0,v1,v5,v7\l\ +// Block 7; (5, max 17)\nLiveIn: v0,v1,v5,v7\l\ // LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v13| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_7Exit:0 -> Block1_10; -// Block1_7Exit:1 -> Block1_9; +// Block1_7Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit:0 -> Block1_10 [style="solid"]; +// Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ -// Block 9\nLiveIn: \l\ +// Block 9; (6, max 6)\nLiveIn: \l\ // LiveOut: \l\nsstore(1028, 4)\l\ // "]; // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10\nLiveIn: v0,v1,v5,v7\l\ +// Block 10; (7, max 17)\nLiveIn: v0,v1,v5,v7\l\ // LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_10Exit:0 -> Block1_13; -// Block1_10Exit:1 -> Block1_12; +// Block1_10Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit:0 -> Block1_13 [style="solid"]; +// Block1_10Exit:1 -> Block1_12 [style="solid"]; // Block1_12 [label="\ -// Block 12\nLiveIn: \l\ +// Block 12; (8, max 8)\nLiveIn: \l\ // LiveOut: \l\nsstore(1542, 6)\l\ // revert(0, 0)\l\ // "]; // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13\nLiveIn: v0,v1,v5,v7\l\ +// Block 13; (9, max 17)\nLiveIn: v0,v1,v5,v7\l\ // LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v25| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_13Exit:0 -> Block1_16; -// Block1_13Exit:1 -> Block1_15; +// Block1_13Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit:0 -> Block1_16 [style="solid"]; +// Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15\nLiveIn: v0,v1,v5\l\ +// Block 15; (10, max 14)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5\l\nsstore(2056, 8)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; -// Block1_15Exit -> Block1_5; +// Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16\nLiveIn: v0,v1,v5\l\ +// Block 16; (15, max 17)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v29| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_16Exit:0 -> Block1_18; -// Block1_16Exit:1 -> Block1_17; +// Block1_16Exit [label="{ If v29 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit:0 -> Block1_18 [style="solid"]; +// Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5\nLiveIn: v0,v1,v5\l\ +// Block 5; (11, max 14)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5\l\nsstore(2827, 11)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; -// Block1_5Exit -> Block1_3; +// Block1_5Exit -> Block1_3 [style="solid"]; // Block1_17 [label="\ -// Block 17\nLiveIn: \l\ +// Block 17; (16, max 16)\nLiveIn: \l\ // LiveOut: \l\nreturn(0, 0)\l\ // "]; // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18\nLiveIn: v0,v1,v5\l\ +// Block 18; (17, max 17)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v5\l\nsstore(2570, 10)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; -// Block1_18Exit -> Block1_5; +// Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3\nLiveIn: v0,v1,v5\l\ +// Block 3; (12, max 14)\nLiveIn: v0,v1,v5\l\ // LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v44| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block1_3Exit:0 -> Block1_21; -// Block1_3Exit:1 -> Block1_20; +// Block1_3Exit [label="{ If v44 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit:0 -> Block1_21 [style="solid"]; +// Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20\nLiveIn: v43\l\ +// Block 20; (13, max 13)\nLiveIn: v43\l\ // LiveOut: \l\nsstore(v43, 0)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21\nLiveIn: v0,v1,v43\l\ +// Block 21; (14, max 14)\nLiveIn: v0,v1,v43\l\ // LiveOut: v0,v1,v43\l\nsstore(65535, 255)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; -// Block1_21Exit -> Block1_1; +// Block1_21Exit -> Block1_1 [style="dashed"]; // } diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/yulSSAControlFlowGraph/function.yul index 1b759f8b3..acf1a37aa 100644 --- a/test/libyul/yulSSAControlFlowGraph/function.yul +++ b/test/libyul/yulSSAControlFlowGraph/function.yul @@ -27,7 +27,7 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nLiveIn: \l\ +// Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\nv0, v1 := i()\l\ // h(v0)\l\ // "]; @@ -37,7 +37,7 @@ // r := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\nLiveIn: v0,v1\l\ +// Block 0; (0, max 0)\nLiveIn: v0,v1\l\ // LiveOut: v4\l\nv3 := add(v1, v0)\l\ // v4 := sub(v0, v3)\l\ // "]; @@ -47,7 +47,7 @@ // g()"]; // FunctionEntry_g_0 -> Block2_0; // Block2_0 [label="\ -// Block 0\nLiveIn: \l\ +// Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\nsstore(257, 1)\l\ // "]; // Block2_0Exit [label="FunctionReturn[]"]; @@ -56,7 +56,7 @@ // h(v0)"]; // FunctionEntry_h_0 -> Block3_0; // Block3_0 [label="\ -// Block 0\nLiveIn: v0\l\ +// Block 0; (0, max 0)\nLiveIn: v0\l\ // LiveOut: \l\nv2 := f(0, v0)\l\ // h(v2)\l\ // "]; @@ -66,7 +66,7 @@ // v, w := i()"]; // FunctionEntry_i_0 -> Block4_0; // Block4_0 [label="\ -// Block 0\nLiveIn: \l\ +// Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\n"]; // Block4_0Exit [label="FunctionReturn[514, 771]"]; // Block4_0 -> Block4_0Exit; diff --git a/test/libyul/yulSSAControlFlowGraph/if.yul b/test/libyul/yulSSAControlFlowGraph/if.yul index 9c4d73a13..e2a66ab74 100644 --- a/test/libyul/yulSSAControlFlowGraph/if.yul +++ b/test/libyul/yulSSAControlFlowGraph/if.yul @@ -15,22 +15,22 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nLiveIn: \l\ +// Block 0; (0, max 2)\nLiveIn: \l\ // LiveOut: v1\l\nv1 := calldataload(3)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If 0| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_0Exit:0 -> Block0_2; -// Block0_0Exit:1 -> Block0_1; +// Block0_0Exit [label="{ If 0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit:0 -> Block0_2 [style="solid"]; +// Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ -// Block 1\nLiveIn: \l\ +// Block 1; (1, max 2)\nLiveIn: \l\ // LiveOut: v4\l\nv4 := calldataload(77)\l\ // "]; // Block0_1 -> Block0_1Exit [arrowhead=none]; // Block0_1Exit [label="Jump" shape=oval]; -// Block0_1Exit -> Block0_2; +// Block0_1Exit -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2\nLiveIn: v5\l\ +// Block 2; (2, max 2)\nLiveIn: v5\l\ // LiveOut: \l\nv5 := φ(\l\ // Block 0 => v1,\l\ // Block 1 => v4\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/yulSSAControlFlowGraph/nested_for.yul index 0ed17c870..b088e3b55 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_for.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_for.yul @@ -26,170 +26,195 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\n"]; +// Block 0; (0, max 24)\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block0_0 -> Block0_0Exit [arrowhead=none]; // Block0_0Exit [label="Jump" shape=oval]; -// Block0_0Exit -> Block0_1; +// Block0_0Exit -> Block0_1 [style="solid"]; // Block0_1 [label="\ -// Block 1\nv2 := φ(\l\ +// Block 1; (1, max 24)\nLiveIn: v2\l\ +// LiveOut: v2\l\nv2 := φ(\l\ // Block 0 => 0,\l\ // Block 3 => v36\l\ // )\l\ // v3 := lt(3, v2)\l\ // "]; // Block0_1 -> Block0_1Exit; -// Block0_1Exit [label="{ If v3| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_1Exit:0 -> Block0_4; -// Block0_1Exit:1 -> Block0_2; +// Block0_1Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_1Exit:0 -> Block0_4 [style="solid"]; +// Block0_1Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2\n"]; +// Block 2; (2, max 23)\nLiveIn: v2\l\ +// LiveOut: v2\l\n"]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; -// Block0_2Exit -> Block0_5; +// Block0_2Exit -> Block0_5 [style="solid"]; // Block0_4 [label="\ -// Block 4\n"]; +// Block 4; (24, max 24)\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block0_4Exit [label="MainExit"]; // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ -// Block 5\nv4 := φ(\l\ +// Block 5; (3, max 23)\nLiveIn: v2,v4\l\ +// LiveOut: v2,v4\l\nv4 := φ(\l\ // Block 2 => 0,\l\ // Block 7 => v35\l\ // )\l\ // v5 := lt(3, v4)\l\ // "]; // Block0_5 -> Block0_5Exit; -// Block0_5Exit [label="{ If v5| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_5Exit:0 -> Block0_8; -// Block0_5Exit:1 -> Block0_6; +// Block0_5Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_5Exit:0 -> Block0_8 [style="solid"]; +// Block0_5Exit:1 -> Block0_6 [style="solid"]; // Block0_6 [label="\ -// Block 6\n"]; +// Block 6; (4, max 21)\nLiveIn: v2,v4\l\ +// LiveOut: v2,v4\l\n"]; // Block0_6 -> Block0_6Exit [arrowhead=none]; // Block0_6Exit [label="Jump" shape=oval]; -// Block0_6Exit -> Block0_9; +// Block0_6Exit -> Block0_9 [style="solid"]; // Block0_8 [label="\ -// Block 8\n"]; +// Block 8; (22, max 23)\nLiveIn: v2\l\ +// LiveOut: v2\l\n"]; // Block0_8 -> Block0_8Exit [arrowhead=none]; // Block0_8Exit [label="Jump" shape=oval]; -// Block0_8Exit -> Block0_3; +// Block0_8Exit -> Block0_3 [style="solid"]; // Block0_9 [label="\ -// Block 9\nv6 := φ(\l\ +// Block 9; (5, max 21)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\nv6 := φ(\l\ // Block 6 => 0,\l\ // Block 11 => v31\l\ // )\l\ // v7 := lt(3, v6)\l\ // "]; // Block0_9 -> Block0_9Exit; -// Block0_9Exit [label="{ If v7| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_9Exit:0 -> Block0_12; -// Block0_9Exit:1 -> Block0_10; +// Block0_9Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_9Exit:0 -> Block0_12 [style="solid"]; +// Block0_9Exit:1 -> Block0_10 [style="solid"]; // Block0_3 [label="\ -// Block 3\nv36 := add(1, v2)\l\ +// Block 3; (23, max 23)\nLiveIn: v2\l\ +// LiveOut: v36\l\nv36 := add(1, v2)\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; -// Block0_3Exit -> Block0_1; +// Block0_3Exit -> Block0_1 [style="dashed"]; // Block0_10 [label="\ -// Block 10\n"]; +// Block 10; (6, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_10 -> Block0_10Exit; -// Block0_10Exit [label="{ If 0| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_10Exit:0 -> Block0_14; -// Block0_10Exit:1 -> Block0_13; +// Block0_10Exit [label="{ If 0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_10Exit:0 -> Block0_14 [style="solid"]; +// Block0_10Exit:1 -> Block0_13 [style="solid"]; // Block0_12 [label="\ -// Block 12\n"]; +// Block 12; (20, max 21)\nLiveIn: v2,v4\l\ +// LiveOut: v2,v4\l\n"]; // Block0_12 -> Block0_12Exit [arrowhead=none]; // Block0_12Exit [label="Jump" shape=oval]; -// Block0_12Exit -> Block0_7; +// Block0_12Exit -> Block0_7 [style="solid"]; // Block0_13 [label="\ -// Block 13\n"]; +// Block 13; (7, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_13 -> Block0_13Exit [arrowhead=none]; // Block0_13Exit [label="Jump" shape=oval]; -// Block0_13Exit -> Block0_15; +// Block0_13Exit -> Block0_15 [style="solid"]; // Block0_14 [label="\ -// Block 14\n"]; +// Block 14; (12, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_14 -> Block0_14Exit; -// Block0_14Exit [label="{ If 1| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_14Exit:0 -> Block0_20; -// Block0_14Exit:1 -> Block0_19; +// Block0_14Exit [label="{ If 1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_14Exit:0 -> Block0_20 [style="solid"]; +// Block0_14Exit:1 -> Block0_19 [style="solid"]; // Block0_7 [label="\ -// Block 7\nv35 := add(1, v4)\l\ +// Block 7; (21, max 21)\nLiveIn: v2,v4\l\ +// LiveOut: v2,v35\l\nv35 := add(1, v4)\l\ // "]; // Block0_7 -> Block0_7Exit [arrowhead=none]; // Block0_7Exit [label="Jump" shape=oval]; -// Block0_7Exit -> Block0_5; +// Block0_7Exit -> Block0_5 [style="dashed"]; // Block0_15 [label="\ -// Block 15\nv8 := φ(\l\ +// Block 15; (8, max 19)\nLiveIn: v2,v4,v6,v8\l\ +// LiveOut: v2,v4,v6,v8\l\nv8 := φ(\l\ // Block 13 => 0,\l\ // Block 17 => v16\l\ // )\l\ // v9 := lt(3, v8)\l\ // "]; // Block0_15 -> Block0_15Exit; -// Block0_15Exit [label="{ If v9| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_15Exit:0 -> Block0_18; -// Block0_15Exit:1 -> Block0_16; +// Block0_15Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_15Exit:0 -> Block0_18 [style="solid"]; +// Block0_15Exit:1 -> Block0_16 [style="solid"]; // Block0_19 [label="\ -// Block 19\n"]; +// Block 19; (13, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_19 -> Block0_19Exit [arrowhead=none]; // Block0_19Exit [label="Jump" shape=oval]; -// Block0_19Exit -> Block0_21; +// Block0_19Exit -> Block0_21 [style="solid"]; // Block0_20 [label="\ -// Block 20\n"]; +// Block 20; (18, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_20 -> Block0_20Exit [arrowhead=none]; // Block0_20Exit [label="Jump" shape=oval]; -// Block0_20Exit -> Block0_11; +// Block0_20Exit -> Block0_11 [style="solid"]; // Block0_16 [label="\ -// Block 16\nv13 := add(v4, v2)\l\ +// Block 16; (9, max 10)\nLiveIn: v2,v4,v6,v8\l\ +// LiveOut: v2,v4,v6,v8\l\nv13 := add(v4, v2)\l\ // v14 := add(v6, v13)\l\ // sstore(v14, v8)\l\ // "]; // Block0_16 -> Block0_16Exit [arrowhead=none]; // Block0_16Exit [label="Jump" shape=oval]; -// Block0_16Exit -> Block0_17; +// Block0_16Exit -> Block0_17 [style="solid"]; // Block0_18 [label="\ -// Block 18\n"]; +// Block 18; (11, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_18 -> Block0_18Exit [arrowhead=none]; // Block0_18Exit [label="Jump" shape=oval]; -// Block0_18Exit -> Block0_14; +// Block0_18Exit -> Block0_14 [style="solid"]; // Block0_21 [label="\ -// Block 21\nv19 := φ(\l\ +// Block 21; (14, max 19)\nLiveIn: v2,v4,v6,v19\l\ +// LiveOut: v2,v4,v6,v19\l\nv19 := φ(\l\ // Block 19 => 0,\l\ // Block 23 => v26\l\ // )\l\ // v20 := lt(3, v19)\l\ // "]; // Block0_21 -> Block0_21Exit; -// Block0_21Exit [label="{ If v20| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_21Exit:0 -> Block0_24; -// Block0_21Exit:1 -> Block0_22; +// Block0_21Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_21Exit:0 -> Block0_24 [style="solid"]; +// Block0_21Exit:1 -> Block0_22 [style="solid"]; // Block0_11 [label="\ -// Block 11\nv31 := add(1, v6)\l\ +// Block 11; (19, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v31\l\nv31 := add(1, v6)\l\ // "]; // Block0_11 -> Block0_11Exit [arrowhead=none]; // Block0_11Exit [label="Jump" shape=oval]; -// Block0_11Exit -> Block0_9; +// Block0_11Exit -> Block0_9 [style="dashed"]; // Block0_17 [label="\ -// Block 17\nv16 := add(1, v8)\l\ +// Block 17; (10, max 10)\nLiveIn: v2,v4,v6,v8\l\ +// LiveOut: v2,v4,v6,v16\l\nv16 := add(1, v8)\l\ // "]; // Block0_17 -> Block0_17Exit [arrowhead=none]; // Block0_17Exit [label="Jump" shape=oval]; -// Block0_17Exit -> Block0_15; +// Block0_17Exit -> Block0_15 [style="dashed"]; // Block0_22 [label="\ -// Block 22\nv24 := add(v4, v2)\l\ +// Block 22; (15, max 16)\nLiveIn: v2,v4,v6,v19\l\ +// LiveOut: v2,v4,v6,v19\l\nv24 := add(v4, v2)\l\ // v25 := add(v6, v24)\l\ // sstore(v25, v19)\l\ // "]; // Block0_22 -> Block0_22Exit [arrowhead=none]; // Block0_22Exit [label="Jump" shape=oval]; -// Block0_22Exit -> Block0_23; +// Block0_22Exit -> Block0_23 [style="solid"]; // Block0_24 [label="\ -// Block 24\n"]; +// Block 24; (17, max 19)\nLiveIn: v2,v4,v6\l\ +// LiveOut: v2,v4,v6\l\n"]; // Block0_24 -> Block0_24Exit [arrowhead=none]; // Block0_24Exit [label="Jump" shape=oval]; -// Block0_24Exit -> Block0_20; +// Block0_24Exit -> Block0_20 [style="solid"]; // Block0_23 [label="\ -// Block 23\nv26 := add(1, v19)\l\ +// Block 23; (16, max 16)\nLiveIn: v2,v4,v6,v19\l\ +// LiveOut: v2,v4,v6,v26\l\nv26 := add(1, v19)\l\ // "]; // Block0_23 -> Block0_23Exit [arrowhead=none]; // Block0_23Exit [label="Jump" shape=oval]; -// Block0_23Exit -> Block0_21; +// Block0_23Exit -> Block0_21 [style="dashed"]; // } diff --git a/test/libyul/yulSSAControlFlowGraph/nested_function.yul b/test/libyul/yulSSAControlFlowGraph/nested_function.yul index 859b24151..acda15ce8 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_function.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_function.yul @@ -38,14 +38,16 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\n"]; +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_f_0 [label="function f: // r := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0\nv3 := add(v1, v0)\l\ +// Block 0; (0, max 0)\nLiveIn: v0,v1\l\ +// LiveOut: v4\l\nv3 := add(v1, v0)\l\ // v4 := sub(v0, v3)\l\ // "]; // Block1_0Exit [label="FunctionReturn[v4]"]; @@ -54,7 +56,8 @@ // g()"]; // FunctionEntry_g_0 -> Block2_0; // Block2_0 [label="\ -// Block 0\nv1 := v()\l\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nv1 := v()\l\ // v2 := f(2, v1)\l\ // v3 := z()\l\ // sstore(v2, v3)\l\ @@ -65,7 +68,8 @@ // r := z()"]; // FunctionEntry_z_0 -> Block3_0; // Block3_0 [label="\ -// Block 0\nv1 := w()\l\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: v1\l\nv1 := w()\l\ // "]; // Block3_0Exit [label="FunctionReturn[v1]"]; // Block3_0 -> Block3_0Exit; @@ -73,14 +77,16 @@ // rw1 := w()"]; // FunctionEntry_w_0 -> Block4_0; // Block4_0 [label="\ -// Block 0\n"]; +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block4_0Exit [label="FunctionReturn[1]"]; // Block4_0 -> Block4_0Exit; // FunctionEntry_v_0 [label="function v: // r := v()"]; // FunctionEntry_v_0 -> Block5_0; // Block5_0 [label="\ -// Block 0\nv1 := w()\l\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: v1\l\nv1 := w()\l\ // "]; // Block5_0Exit [label="FunctionReturn[v1]"]; // Block5_0 -> Block5_0Exit; @@ -88,27 +94,31 @@ // rw2 := w()"]; // FunctionEntry_w_0 -> Block6_0; // Block6_0 [label="\ -// Block 0\n"]; +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\n"]; // Block6_0Exit [label="FunctionReturn[17]"]; // Block6_0 -> Block6_0Exit; // FunctionEntry_cycle1_0 [label="function cycle1: // r := cycle1()"]; // FunctionEntry_cycle1_0 -> Block7_0; // Block7_0 [label="\ -// Block 0\nv2 := mload(3)\l\ +// Block 0; (0, max 2)\nLiveIn: \l\ +// LiveOut: \l\nv2 := mload(3)\l\ // "]; // Block7_0 -> Block7_0Exit; -// Block7_0Exit [label="{ If v2| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block7_0Exit:0 -> Block7_2; -// Block7_0Exit:1 -> Block7_1; +// Block7_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block7_0Exit:0 -> Block7_2 [style="solid"]; +// Block7_0Exit:1 -> Block7_1 [style="solid"]; // Block7_1 [label="\ -// Block 1\nv3 := cycle2()\l\ +// Block 1; (1, max 2)\nLiveIn: \l\ +// LiveOut: v3\l\nv3 := cycle2()\l\ // "]; // Block7_1 -> Block7_1Exit [arrowhead=none]; // Block7_1Exit [label="Jump" shape=oval]; -// Block7_1Exit -> Block7_2; +// Block7_1Exit -> Block7_2 [style="solid"]; // Block7_2 [label="\ -// Block 2\nv4 := φ(\l\ +// Block 2; (2, max 2)\nLiveIn: v4\l\ +// LiveOut: v4\l\nv4 := φ(\l\ // Block 0 => 0,\l\ // Block 1 => v3\l\ // )\l\ @@ -119,20 +129,23 @@ // r := cycle2()"]; // FunctionEntry_cycle2_0 -> Block8_0; // Block8_0 [label="\ -// Block 0\nv2 := mload(4)\l\ +// Block 0; (0, max 2)\nLiveIn: \l\ +// LiveOut: \l\nv2 := mload(4)\l\ // "]; // Block8_0 -> Block8_0Exit; -// Block8_0Exit [label="{ If v2| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block8_0Exit:0 -> Block8_2; -// Block8_0Exit:1 -> Block8_1; +// Block8_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block8_0Exit:0 -> Block8_2 [style="solid"]; +// Block8_0Exit:1 -> Block8_1 [style="solid"]; // Block8_1 [label="\ -// Block 1\nv3 := cycle1()\l\ +// Block 1; (1, max 2)\nLiveIn: \l\ +// LiveOut: v3\l\nv3 := cycle1()\l\ // "]; // Block8_1 -> Block8_1Exit [arrowhead=none]; // Block8_1Exit [label="Jump" shape=oval]; -// Block8_1Exit -> Block8_2; +// Block8_1Exit -> Block8_2 [style="solid"]; // Block8_2 [label="\ -// Block 2\nv4 := φ(\l\ +// Block 2; (2, max 2)\nLiveIn: v4\l\ +// LiveOut: v4\l\nv4 := φ(\l\ // Block 0 => 0,\l\ // Block 1 => v3\l\ // )\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/switch.yul b/test/libyul/yulSSAControlFlowGraph/switch.yul index d744bd7bd..10573b012 100644 --- a/test/libyul/yulSSAControlFlowGraph/switch.yul +++ b/test/libyul/yulSSAControlFlowGraph/switch.yul @@ -22,32 +22,32 @@ // Entry0 [label="Entry"]; // Entry0 -> Block0_0; // Block0_0 [label="\ -// Block 0\nLiveIn: \l\ +// Block 0; (0, max 5)\nLiveIn: \l\ // LiveOut: v3\l\nv1 := calldataload(3)\l\ // v3 := sload(0)\l\ // v4 := eq(0, v3)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If v4| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_0Exit:0 -> Block0_3; -// Block0_0Exit:1 -> Block0_2; +// Block0_0Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit:0 -> Block0_3 [style="solid"]; +// Block0_0Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2\nLiveIn: \l\ +// Block 2; (1, max 2)\nLiveIn: \l\ // LiveOut: v6\l\nv6 := calldataload(77)\l\ // "]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; -// Block0_2Exit -> Block0_1; +// Block0_2Exit -> Block0_1 [style="solid"]; // Block0_3 [label="\ -// Block 3\nLiveIn: v3\l\ +// Block 3; (3, max 5)\nLiveIn: v3\l\ // LiveOut: \l\nv7 := eq(1, v3)\l\ // "]; // Block0_3 -> Block0_3Exit; -// Block0_3Exit [label="{ If v7| { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block0_3Exit:0 -> Block0_5; -// Block0_3Exit:1 -> Block0_4; +// Block0_3Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_3Exit:0 -> Block0_5 [style="solid"]; +// Block0_3Exit:1 -> Block0_4 [style="solid"]; // Block0_1 [label="\ -// Block 1\nLiveIn: v13\l\ +// Block 1; (2, max 2)\nLiveIn: v13\l\ // LiveOut: \l\nv13 := φ(\l\ // Block 2 => v6,\l\ // Block 4 => v10,\l\ @@ -58,17 +58,17 @@ // Block0_1Exit [label="MainExit"]; // Block0_1 -> Block0_1Exit; // Block0_4 [label="\ -// Block 4\nLiveIn: \l\ +// Block 4; (4, max 4)\nLiveIn: \l\ // LiveOut: v10\l\nv10 := calldataload(88)\l\ // "]; // Block0_4 -> Block0_4Exit [arrowhead=none]; // Block0_4Exit [label="Jump" shape=oval]; -// Block0_4Exit -> Block0_1; +// Block0_4Exit -> Block0_1 [style="solid"]; // Block0_5 [label="\ -// Block 5\nLiveIn: \l\ +// Block 5; (5, max 5)\nLiveIn: \l\ // LiveOut: v12\l\nv12 := calldataload(99)\l\ // "]; // Block0_5 -> Block0_5Exit [arrowhead=none]; // Block0_5Exit [label="Jump" shape=oval]; -// Block0_5Exit -> Block0_1; +// Block0_5Exit -> Block0_1 [style="solid"]; // } From 8a77a26861046a0a2a37cfc908edcc8947ffb91a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:56:20 +0200 Subject: [PATCH 0389/1340] SSACFGLiveness: add operation-wise live out --- libyul/backends/evm/SSACFGLiveness.cpp | 32 ++++++++++++++++++++- libyul/backends/evm/SSACFGLiveness.h | 12 +++++--- libyul/backends/evm/SSAControlFlowGraph.cpp | 4 +-- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/libyul/backends/evm/SSACFGLiveness.cpp b/libyul/backends/evm/SSACFGLiveness.cpp index b9513f70d..85bd41d10 100644 --- a/libyul/backends/evm/SSACFGLiveness.cpp +++ b/libyul/backends/evm/SSACFGLiveness.cpp @@ -29,12 +29,16 @@ SSACFGLiveness::SSACFGLiveness(SSACFG const& _cfg): m_topologicalSort(_cfg), m_loopNestingForest(m_topologicalSort), m_liveIns(_cfg.numBlocks()), - m_liveOuts(_cfg.numBlocks()) + m_liveOuts(_cfg.numBlocks()), + m_operationLiveOuts(_cfg.numBlocks()) { runDagDfs(); for (auto const loopRootNode: m_loopNestingForest.loopRootNodes()) runLoopTreeDfs(loopRootNode); + + fillOperationsLiveOut(); } + void SSACFGLiveness::runDagDfs() { // SSA Book, Algorithm 9.2 @@ -103,6 +107,7 @@ void SSACFGLiveness::runDagDfs() m_liveIns[blockId.value] = live + block.phis; } } + void SSACFGLiveness::runLoopTreeDfs(size_t const _loopHeader) { // SSA Book, Algorithm 9.3 @@ -126,3 +131,28 @@ void SSACFGLiveness::runLoopTreeDfs(size_t const _loopHeader) } } } + +void SSACFGLiveness::fillOperationsLiveOut() +{ + auto const filterLiterals = [this](auto const& valueId){ + return !std::holds_alternative(m_cfg.valueInfo(valueId)); + }; + for (size_t blockIdValue = 0; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) + { + auto const& operations = m_cfg.block(SSACFG::BlockId{blockIdValue}).operations; + auto& liveOuts = m_operationLiveOuts[blockIdValue]; + liveOuts.resize(operations.size()); + if (!operations.empty()) + { + auto live = m_liveOuts[blockIdValue]; + auto rit = liveOuts.rbegin(); + for (auto const& op: operations | ranges::views::reverse) + { + *rit = live; + live -= op.outputs | ranges::views::filter(filterLiterals) | ranges::to; + live += op.inputs | ranges::views::filter(filterLiterals) | ranges::to; + ++rit; + } + } + } +} diff --git a/libyul/backends/evm/SSACFGLiveness.h b/libyul/backends/evm/SSACFGLiveness.h index 6f486b737..72752cfef 100644 --- a/libyul/backends/evm/SSACFGLiveness.h +++ b/libyul/backends/evm/SSACFGLiveness.h @@ -35,21 +35,25 @@ namespace solidity::yul class SSACFGLiveness { public: + using LivenessData = std::set; explicit SSACFGLiveness(SSACFG const& _cfg); - std::vector> const& liveIns() const { return m_liveIns; } - std::vector> const& liveOuts() const { return m_liveOuts; } + LivenessData const& liveIn(SSACFG::BlockId _blockId) const { return m_liveIns[_blockId.value]; } + LivenessData const& liveOut(SSACFG::BlockId _blockId) const { return m_liveOuts[_blockId.value]; } + std::vector const& operationsLiveOut(SSACFG::BlockId _blockId) const { return m_operationLiveOuts[_blockId.value]; } ForwardSSACFGTopologicalSort const& topologicalSort() const { return m_topologicalSort; } private: void runDagDfs(); void runLoopTreeDfs(size_t _loopHeader); + void fillOperationsLiveOut(); SSACFG const& m_cfg; ForwardSSACFGTopologicalSort m_topologicalSort; SSACFGLoopNestingForest m_loopNestingForest; - std::vector> m_liveIns; - std::vector> m_liveOuts; + std::vector m_liveIns; + std::vector m_liveOuts; + std::vector> m_operationLiveOuts; }; } diff --git a/libyul/backends/evm/SSAControlFlowGraph.cpp b/libyul/backends/evm/SSAControlFlowGraph.cpp index ebd6d84a9..35c9db0df 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.cpp +++ b/libyul/backends/evm/SSAControlFlowGraph.cpp @@ -125,11 +125,11 @@ class SSACFGPrinter ); m_result << fmt::format( "LiveIn: {}\\l\\\n", - fmt::join(m_liveness->liveIns()[_id.value] | ranges::views::transform(valueToString), ",") + fmt::join(m_liveness->liveIn(_id) | ranges::views::transform(valueToString), ",") ); m_result << fmt::format( "LiveOut: {}\\l\\n", - fmt::join(m_liveness->liveOuts()[_id.value] | ranges::views::transform(valueToString), ",") + fmt::join(m_liveness->liveOut(_id) | ranges::views::transform(valueToString), ",") ); } else From cdfb93edf08ad36d1399fbb5aa960e29812828ab Mon Sep 17 00:00:00 2001 From: Elias Rad <146735585+nnsW3@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:42:05 +0300 Subject: [PATCH 0390/1340] Update functions.rst --- docs/contracts/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contracts/functions.rst b/docs/contracts/functions.rst index e653eb8f0..a3a275538 100644 --- a/docs/contracts/functions.rst +++ b/docs/contracts/functions.rst @@ -267,7 +267,7 @@ This behavior is also in line with the ``STATICCALL`` opcode. .. note:: Prior to version 0.4.17 the compiler did not enforce that ``pure`` is not reading the state. - It is a compile-time type check, which can be circumvented doing invalid explicit conversions + It is a compile-time type check, which can be circumvented by doing invalid explicit conversions between contract types, because the compiler can verify that the type of the contract does not do state-changing operations, but it cannot check that the contract that will be called at runtime is actually of that type. From 11395ad5b4462de08efa294a5e31c221a4d37bda Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 8 Oct 2024 15:24:26 +0200 Subject: [PATCH 0391/1340] CI: Remove nightly codecov job --- .circleci/config.yml | 46 -------------------------------------------- codecov.yml | 22 --------------------- 2 files changed, 68 deletions(-) delete mode 100644 codecov.yml diff --git a/.circleci/config.yml b/.circleci/config.yml index ed14c8af4..ca1043685 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -670,11 +670,6 @@ defaults: requires: - b_archlinux - - requires_b_ubu_codecov: &requires_b_ubu_codecov - <<: *on_all_tags_and_branches - requires: - - b_ubu_codecov - - requires_b_osx: &requires_b_osx <<: *on_all_tags_and_branches requires: @@ -1074,43 +1069,6 @@ jobs: - solc/solc-static-linux - matrix_notify_failure_unless_pr - b_ubu_codecov: - # Runs ~30% faster on large but we only run it nightly so efficiency matters more. - <<: *base_ubuntu2404 - environment: - <<: *base_ubuntu2404_env - COVERAGE: ON - CMAKE_BUILD_TYPE: Debug - CMAKE_OPTIONS: -DCMAKE_CXX_FLAGS=-fuse-ld=gold - steps: - - checkout - - run_build - - persist_executables_to_workspace - - matrix_notify_failure_unless_pr - - t_ubu_codecov: - <<: *base_ubuntu2404_large - environment: - <<: *base_ubuntu2404_large_env - EVM: << pipeline.parameters.evm-version >> - OPTIMIZE: 1 - steps: - - checkout - - attach_workspace: - at: build - - run: - name: "soltest: Syntax Tests" - command: build/test/soltest -t 'syntaxTest*' -- --testpath test - - run: - name: "Code Coverage: Syntax Tests" - command: codecov --flags syntax --gcov-root build - - run_soltest - - run: - name: "Coverage: All" - command: codecov --flags all --gcov-root build - - store_artifacts_test_results - - matrix_notify_failure_unless_pr - # Builds in C++20 mode and uses debug build in order to speed up. # Do *NOT* store any artifacts or workspace as we don't run tests on this build. b_ubu_cxx20: @@ -2007,10 +1965,6 @@ workflows: <<: *on_develop jobs: - # Code Coverage enabled build and tests - - b_ubu_codecov: *requires_nothing - - t_ubu_codecov: *requires_b_ubu_codecov - # ASan build and tests - b_ubu_asan: *requires_nothing - b_ubu_san_clang: *job_b_ubu_asan_clang diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index c0b72761e..000000000 --- a/codecov.yml +++ /dev/null @@ -1,22 +0,0 @@ -codecov: - branch: develop -coverage: - range: 70...100 - status: - patch: - default: - target: "50%" - paths: "!test/" - project: - default: - target: auto - paths: "!test/" - syntax: - target: auto - paths: "libsolidity/analysis" - flags: syntax - tests: - target: auto - paths: "test/" -comment: - layout: "reach, diff, flags" From 5f2b1bf72d9fc2ea87eeecc66f03f2480f2c135c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:12:54 +0200 Subject: [PATCH 0392/1340] Docs: fix curly bracket language wikipedia anchor --- docs/index.rst | 2 +- docs/language-influences.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 600173d65..f1608890d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,7 +4,7 @@ Solidity Solidity is an object-oriented, high-level language for implementing smart contracts. Smart contracts are programs that govern the behavior of accounts within the Ethereum state. -Solidity is a `curly-bracket language `_ designed to target the Ethereum Virtual Machine (EVM). +Solidity is a `curly-bracket language `_ designed to target the Ethereum Virtual Machine (EVM). It is influenced by C++, Python, and JavaScript. You can find more details about which languages Solidity has been inspired by in the :doc:`language influences ` section. diff --git a/docs/language-influences.rst b/docs/language-influences.rst index e4f0ab690..a3ab1562e 100644 --- a/docs/language-influences.rst +++ b/docs/language-influences.rst @@ -2,7 +2,7 @@ Language Influences ################### -Solidity is a `curly-bracket language `_ +Solidity is a `curly-bracket language `_ that has been influenced and inspired by several well-known programming languages. Solidity is most profoundly influenced by C++, but also borrowed concepts from languages like From 9b97e52d45b4d94df22b3599dc0411317b056668 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 8 Oct 2024 11:58:12 -0300 Subject: [PATCH 0393/1340] sort Changelog --- Changelog.md | 4 ++-- docs/bugs_by_version.json | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index de1674a15..eabd5b9ee 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,7 +1,7 @@ -### 0.8.28 (unreleased) +### 0.8.28 (2024-10-09) Language Features: - * Transient storage value type state variables are now fully supported. + * Transient storage state variables of value types are now fully supported. Compiler Features: diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index f9913d812..2c3b6487a 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1902,6 +1902,10 @@ "bugs": [], "released": "2024-09-04" }, + "0.8.28": { + "bugs": [], + "released": "2024-10-09" + }, "0.8.3": { "bugs": [ "FullInlinerNonExpressionSplitArgumentEvaluationOrder", From fecd1329cd7a2bb0b77428ac8d02bb6b86c72d24 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 9 Oct 2024 13:06:41 +0200 Subject: [PATCH 0394/1340] eof: Support EOF asm analysis --- libyul/AsmAnalysis.cpp | 43 +++++++++++++++++-- libyul/AsmAnalysis.h | 4 ++ test/Common.cpp | 2 + test/TestCase.cpp | 30 ++++++++++++- test/TestCase.h | 4 ++ .../eof/call_intruction_in_eof.yul | 13 ++++++ 6 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 test/libyul/yulSyntaxTests/eof/call_intruction_in_eof.yul diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index cf8c720f6..682931dc4 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -625,12 +625,16 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location) { // NOTE: This function uses the default EVM version instead of the currently selected one. - // TODO: Add EOF support auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt).builtin(YulName(_instructionIdentifier)); if (builtin && builtin->instruction.has_value()) return validateInstructions(builtin->instruction.value(), _location); - else - return false; + + // TODO: Change `prague()` to `EVMVersion{}` once EOF gets deployed + auto const eofBuiltin = EVMDialect::strictAssemblyForEVM(EVMVersion::prague(), 1).builtin(YulName(_instructionIdentifier)); + if (eofBuiltin && eofBuiltin->instruction.has_value()) + return validateInstructions(eofBuiltin->instruction.value(), _location); + + return false; } bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocation const& _location) @@ -702,9 +706,42 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio "PC instruction is a low-level EVM feature. " "Because of that PC is disallowed in strict assembly." ); + else if (m_eofVersion.has_value() && ( + _instr == evmasm::Instruction::CALL || + _instr == evmasm::Instruction::CALLCODE || + _instr == evmasm::Instruction::DELEGATECALL || + _instr == evmasm::Instruction::SELFDESTRUCT || + _instr == evmasm::Instruction::JUMP || + _instr == evmasm::Instruction::JUMPI || + _instr == evmasm::Instruction::PC || + _instr == evmasm::Instruction::CREATE || + _instr == evmasm::Instruction::CODESIZE || + _instr == evmasm::Instruction::CODECOPY || + _instr == evmasm::Instruction::EXTCODESIZE || + _instr == evmasm::Instruction::EXTCODECOPY || + _instr == evmasm::Instruction::GAS + )) + { + m_errorReporter.typeError( + 9132_error, + _location, + fmt::format( + "The \"{instruction}\" instruction is {kind} VMs (you are currently compiling to EOF).", + fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name)), + fmt::arg("kind", "only available in legacy bytecode") + ) + ); + } else + { + // Sanity check + solAssert(m_evmVersion.hasOpcode(_instr, m_eofVersion)); return false; + } + // Sanity check + // PC is not available in strict assembly but it is always valid opcode in legacy evm. + solAssert(_instr == evmasm::Instruction::PC || !m_evmVersion.hasOpcode(_instr, m_eofVersion)); return true; } diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 64cab51f5..d8a2b2b1a 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -70,7 +70,10 @@ class AsmAnalyzer m_dataNames(std::move(_dataNames)) { if (EVMDialect const* evmDialect = dynamic_cast(&m_dialect)) + { m_evmVersion = evmDialect->evmVersion(); + m_eofVersion = evmDialect->eofVersion(); + } } bool analyze(Block const& _block); @@ -125,6 +128,7 @@ class AsmAnalyzer AsmAnalysisInfo& m_info; langutil::ErrorReporter& m_errorReporter; langutil::EVMVersion m_evmVersion; + std::optional m_eofVersion; Dialect const& m_dialect; /// Names of data objects to be referenced by builtin functions with literal arguments. std::set m_dataNames; diff --git a/test/Common.cpp b/test/Common.cpp index ae725774c..bab95c457 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -155,6 +155,8 @@ void CommonOptions::validate() const std::cout << "- ABI coder: v1 (default: v2)" << std::endl; std::cout << std::endl << "DO NOT COMMIT THE UPDATED EXPECTATIONS." << std::endl << std::endl; } + + assertThrow(!eofVersion().has_value() || evmVersion() >= langutil::EVMVersion::prague(), ConfigException, "EOF is unavailable before Prague fork."); } bool CommonOptions::parse(int argc, char const* const* argv) diff --git a/test/TestCase.cpp b/test/TestCase.cpp index ae89bb56f..942153d3c 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -96,8 +96,7 @@ TestCase::TestResult TestCase::checkResult(std::ostream& _stream, const std::str return TestResult::Success; } -EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(std::string const& _filename): - TestCase(_filename) +void EVMVersionRestrictedTestCase::processEVMVersionSetting() { std::string versionString = m_reader.stringSetting("EVMVersion", "any"); if (versionString == "any") @@ -139,3 +138,30 @@ EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(std::string const& _f if (!comparisonResult) m_shouldRun = false; } + +void EVMVersionRestrictedTestCase::processBytecodeFormatSetting() +{ + std::optional eofVersion = solidity::test::CommonOptions::get().eofVersion(); + // TODO: Update if EOF moved to Osaka + // EOF only available since Prague + solAssert(!eofVersion.has_value() ||solidity::test::CommonOptions::get().evmVersion() >= langutil::EVMVersion::prague()); + + std::string bytecodeFormatString = m_reader.stringSetting("bytecodeFormat", "legacy"); + if (bytecodeFormatString == "legacy,>=EOFv1" || bytecodeFormatString == ">=EOFv1,legacy") + return; + + // TODO: This is naive implementation because for now we support only one EOF version. + if (bytecodeFormatString == "legacy" && eofVersion.has_value()) + m_shouldRun = false; + else if (bytecodeFormatString == ">=EOFv1" && !eofVersion.has_value()) + m_shouldRun = false; + else if (bytecodeFormatString != "legacy" && bytecodeFormatString != ">=EOFv1" ) + BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid bytecodeFormat flag: \"" + bytecodeFormatString + "\""}); +} + +EVMVersionRestrictedTestCase::EVMVersionRestrictedTestCase(std::string const& _filename): + TestCase(_filename) +{ + processEVMVersionSetting(); + processBytecodeFormatSetting(); +} diff --git a/test/TestCase.h b/test/TestCase.h index 301dbfb65..bdf51d2a5 100644 --- a/test/TestCase.h +++ b/test/TestCase.h @@ -112,6 +112,10 @@ class TestCase class EVMVersionRestrictedTestCase: public TestCase { +private: + void processEVMVersionSetting(); + void processBytecodeFormatSetting(); + protected: EVMVersionRestrictedTestCase(std::string const& _filename); }; diff --git a/test/libyul/yulSyntaxTests/eof/call_intruction_in_eof.yul b/test/libyul/yulSyntaxTests/eof/call_intruction_in_eof.yul new file mode 100644 index 000000000..d26af22a7 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/call_intruction_in_eof.yul @@ -0,0 +1,13 @@ +object "a" { + code { + let success := call(gas(), 0x1, 0, 128, 4, 128, 0) + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 9132: (47-51): The "call" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 9132: (52-55): The "gas" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (52-57): Expected expression to evaluate to one value, but got 0 values instead. +// DeclarationError 3812: (32-82): Variable count mismatch for declaration of "success": 1 variables and 0 values. From 91a37af31ae42d73aa591fca1e42de2fa37a7007 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 8 Oct 2024 12:19:32 -0300 Subject: [PATCH 0395/1340] Set next version (0.8.29) --- CMakeLists.txt | 2 +- Changelog.md | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c36ff73b..b78269a3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.28") +set(PROJECT_VERSION "0.8.29") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index eabd5b9ee..13af14b75 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,14 @@ +### 0.8.29 (unreleased) + +Language Features: + + +Compiler Features: + + +Bugfixes: + + ### 0.8.28 (2024-10-09) Language Features: From 7210680329061d0a1f0e03a1431a9781fd79708d Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:05:48 +0200 Subject: [PATCH 0396/1340] Yul: SSACFGLiveness simplifications --- libyul/backends/evm/SSACFGLiveness.cpp | 50 +++++++++++++------------- libyul/backends/evm/SSACFGLiveness.h | 2 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/libyul/backends/evm/SSACFGLiveness.cpp b/libyul/backends/evm/SSACFGLiveness.cpp index 85bd41d10..4537c8c5d 100644 --- a/libyul/backends/evm/SSACFGLiveness.cpp +++ b/libyul/backends/evm/SSACFGLiveness.cpp @@ -24,6 +24,17 @@ using namespace solidity::yul; +namespace +{ +constexpr auto literalsFilter(SSACFG const& _cfg) +{ + return [&_cfg](SSACFG::ValueId const& _valueId) -> bool + { + return !std::holds_alternative(_cfg.valueInfo(_valueId));; + }; +} +} + SSACFGLiveness::SSACFGLiveness(SSACFG const& _cfg): m_cfg(_cfg), m_topologicalSort(_cfg), @@ -46,9 +57,6 @@ void SSACFGLiveness::runDagDfs() { // post-order traversal SSACFG::BlockId blockId{blockIdValue}; - auto const filterLiterals = [this](auto const& valueId){ - return !std::holds_alternative(m_cfg.valueInfo(valueId)); - }; auto const& block = m_cfg.block(blockId); // live <- PhiUses(B) @@ -66,15 +74,10 @@ void SSACFGLiveness::runDagDfs() auto const it = entries.find(blockId); yulAssert(it != entries.end()); auto const argIndex = static_cast(std::distance(entries.begin(), it)); - if (argIndex < std::get(info).arguments.size()) - { - // todo not sure why arg index would exceed phi arg length but it does happen - auto const arg = std::get(info).arguments.at(argIndex); - if (!std::holds_alternative(m_cfg.valueInfo(arg))) - live.insert(arg); - } - else - yulAssert(false); + yulAssert(argIndex < std::get(info).arguments.size()); + auto const arg = std::get(info).arguments.at(argIndex); + if (!std::holds_alternative(m_cfg.valueInfo(arg))) + live.insert(arg); } }); @@ -86,7 +89,7 @@ void SSACFGLiveness::runDagDfs() }); if (std::holds_alternative(block.exit)) live += std::get(block.exit).returnValues - | ranges::views::filter(filterLiterals); + | ranges::views::filter(literalsFilter(m_cfg)); // clean out unreachables live = live | ranges::views::filter([&](auto const& valueId) { return !std::holds_alternative(m_cfg.valueInfo(valueId)); }) | ranges::to; @@ -98,9 +101,9 @@ void SSACFGLiveness::runDagDfs() for (auto const& op: block.operations | ranges::views::reverse) { // remove variables defined at p from live - live -= op.outputs | ranges::views::filter(filterLiterals) | ranges::to; + live -= op.outputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; // add uses at p to live - live += op.inputs | ranges::views::filter(filterLiterals) | ranges::to; + live += op.inputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; } // livein(b) <- live \cup PhiDefs(B) @@ -120,23 +123,20 @@ void SSACFGLiveness::runLoopTreeDfs(size_t const _loopHeader) // must be live out of header if live in of children m_liveOuts[_loopHeader] += liveLoop; // for each blockId \in children(loopHeader) - for (size_t blockId = 0; blockId < m_cfg.numBlocks(); ++blockId) - if (m_loopNestingForest.loopParents()[blockId] == _loopHeader) + for (size_t blockIdValue = 0; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) + if (m_loopNestingForest.loopParents()[blockIdValue] == _loopHeader) { // propagate loop liveness information down to the loop header's children - m_liveIns[blockId] += liveLoop; - m_liveOuts[blockId] += liveLoop; + m_liveIns[blockIdValue] += liveLoop; + m_liveOuts[blockIdValue] += liveLoop; - runLoopTreeDfs(blockId); + runLoopTreeDfs(blockIdValue); } } } void SSACFGLiveness::fillOperationsLiveOut() { - auto const filterLiterals = [this](auto const& valueId){ - return !std::holds_alternative(m_cfg.valueInfo(valueId)); - }; for (size_t blockIdValue = 0; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) { auto const& operations = m_cfg.block(SSACFG::BlockId{blockIdValue}).operations; @@ -149,8 +149,8 @@ void SSACFGLiveness::fillOperationsLiveOut() for (auto const& op: operations | ranges::views::reverse) { *rit = live; - live -= op.outputs | ranges::views::filter(filterLiterals) | ranges::to; - live += op.inputs | ranges::views::filter(filterLiterals) | ranges::to; + live -= op.outputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; + live += op.inputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; ++rit; } } diff --git a/libyul/backends/evm/SSACFGLiveness.h b/libyul/backends/evm/SSACFGLiveness.h index 72752cfef..b0b9ccb7a 100644 --- a/libyul/backends/evm/SSACFGLiveness.h +++ b/libyul/backends/evm/SSACFGLiveness.h @@ -29,7 +29,7 @@ namespace solidity::yul { -/// Performs liveness analysis on an SSA CFG following Algorithm 9.1 in [1]. +/// Performs liveness analysis on a reducible SSA CFG following Algorithm 9.1 in [1]. /// /// [1] Rastello, Fabrice, and Florent Bouchez Tichadou, eds. SSA-based Compiler Design. Springer, 2022. class SSACFGLiveness From 3edd2e173828737f6250256380e2d1193e232969 Mon Sep 17 00:00:00 2001 From: Ustas <82833595+ustas-eth@users.noreply.github.com> Date: Sun, 21 Jan 2024 13:48:21 +0000 Subject: [PATCH 0397/1340] [docs] Add warning about `codehash` behavior depending on the account state Co-authored-by: r0qs --- docs/types/value-types.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 27baf5485..5efb08055 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -344,6 +344,13 @@ You can query the deployed code for any smart contract. Use ``.code`` to get the ``bytes memory``, which might be empty. Use ``.codehash`` to get the Keccak-256 hash of that code (as a ``bytes32``). Note that ``addr.codehash`` is cheaper than using ``keccak256(addr.code)``. +.. warning:: + The output of ``addr.codehash`` may be ``0`` if the account associated with ``addr`` is empty or non-existent + (i.e., it has no code, zero balance, and zero nonce as defined by `EIP-161 `_). + If the account has no code but a non-zero balance or nonce, then ``addr.codehash`` will output the Keccak-256 hash of empty data + (i.e., ``keccak256("")`` which is equal to ``c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470``), as defined by + `EIP-1052 `_. + .. note:: All contracts can be converted to ``address`` type, so it is possible to query the balance of the current contract using ``address(this).balance``. From 79ad9610dd2d94f11b204d418db5159d7c95eea8 Mon Sep 17 00:00:00 2001 From: sukey2008 Date: Thu, 10 Oct 2024 21:33:44 +0200 Subject: [PATCH 0398/1340] docs: fix several spelling and grammar issues --- docs/types/value-types.rst | 6 +++--- test/externalTests/README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 5efb08055..9b5ee447e 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -9,7 +9,7 @@ are used as function arguments or in assignments. Unlike :ref:`reference types `, value type declarations do not specify a data location since they are small enough to be stored on the stack. -The only exception are :ref:`state variables `. +The only exception is :ref:`state variables `. Those are by default located in storage, but can also be marked as :ref:`transient `, :ref:`constant or immutable `. @@ -204,7 +204,7 @@ must be explicit via ``payable(
)``. Explicit conversions to and from ``address`` are allowed for ``uint160``, integer literals, ``bytes20`` and contract types. -Only expressions of type ``address`` and contract-type can be converted to the type ``address +Only expressions of type ``address`` and contract type can be converted to the type ``address payable`` via the explicit conversion ``payable(...)``. For contract-type, this conversion is only allowed if the contract can receive Ether, i.e., the contract either has a :ref:`receive ` or a payable fallback function. Note that ``payable(0)`` is valid and is @@ -215,7 +215,7 @@ an exception to this rule. declare its type as ``address payable`` to make this requirement visible. Also, try to make this distinction or conversion as early as possible. - The distinction between ``address`` and ``address payable`` was introduced with version 0.5.0. + The distinction between ``address`` and ``address payable`` was introduced in version 0.5.0. Also starting from that version, contracts are not implicitly convertible to the ``address`` type, but can still be explicitly converted to ``address`` or to ``address payable``, if they have a receive or payable fallback function. diff --git a/test/externalTests/README.md b/test/externalTests/README.md index 8df5b4dfe..91e2ef9af 100644 --- a/test/externalTests/README.md +++ b/test/externalTests/README.md @@ -88,6 +88,6 @@ branches if they exist. If no changes on our part were necessary, it is complete e.g. the `master_060` of an external project in Solidity 0.8.x. Since each project is handled separately, this approach may result in a mix of version-specific branches -between different external projects. For example, in one project we could could have `master_050` on +between different external projects. For example, in one project we could have `master_050` on both `develop` and `breaking` and in another `breaking` could use `master_080` while `develop` still uses `master_060`. From e8b5ca83f37b6a126db6a0a1dcfa00decff63647 Mon Sep 17 00:00:00 2001 From: Jeff Wentworth Date: Fri, 11 Oct 2024 21:25:17 +0900 Subject: [PATCH 0399/1340] Update Natspec format to correct devdoc return parameters (#15187) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update natspec-format.rst for devdoc return values * update changelog * values ==> returns * Fix Solidity and improve doc output * Update Changelog.md Co-authored-by: Nikola Matić * Apply suggestions from code review Co-authored-by: Nikola Matić --------- Co-authored-by: Nikola Matić --- docs/natspec-format.rst | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst index b187ea84c..f19106483 100644 --- a/docs/natspec-format.rst +++ b/docs/natspec-format.rst @@ -73,8 +73,9 @@ The following example shows a contract and a function using all available tags. /// @dev The Alexandr N. Tetearing algorithm could increase precision /// @param rings The number of rings from dendrochronological sample /// @return Age in years, rounded up for partial years - function age(uint256 rings) external virtual pure returns (uint256) { - return rings + 1; + /// @return Name of the tree + function age(uint256 rings) external virtual pure returns (uint256, string memory) { + return (rings + 1, "tree"); } /// @notice Returns the amount of leaves the tree has. @@ -91,8 +92,8 @@ The following example shows a contract and a function using all available tags. } contract KumquatTree is Tree, Plant { - function age(uint256 rings) external override pure returns (uint256) { - return rings + 2; + function age(uint256 rings) external override pure returns (uint256, string memory) { + return (rings + 2, "Kumquat"); } /// Return the amount of leaves that this specific kind of tree has @@ -196,7 +197,7 @@ User Documentation ------------------ The above documentation will produce the following user documentation -JSON file as output: +JSON file as output for the ``Tree`` contract: .. code-block:: json @@ -209,6 +210,10 @@ JSON file as output: { "notice" : "Calculate tree age in years, rounded up, for live trees" } + "leaves()" : + { + "notice" : "Returns the amount of leaves the tree has." + } }, "notice" : "You can use this contract for only the most basic simulation" } @@ -243,7 +248,14 @@ file should also be produced and should look like this: { "rings" : "The number of rings from dendrochronological sample" }, - "return" : "age in years, rounded up for partial years" + "returns" : { + "_0" : "Age in years, rounded up for partial years", + "_1" : "Name of the tree" + } + }, + "leaves()" : + { + "details" : "Returns only a fixed number." } }, "title" : "A simulator for trees" From 520ee5a9c009098a4d94cdc9fbb78896585a8057 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 11 Oct 2024 15:07:47 +0200 Subject: [PATCH 0400/1340] Compiler stack: Protect loadGeneratedIR from contracts that cannot be deployed --- libsolidity/interface/CompilerStack.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index c68df205f..007b6187c 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -982,7 +982,9 @@ Json CompilerStack::yulIRAst(std::string const& _contractName) const // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to // keep it around when compiling a large project containing many contracts. - return loadGeneratedIR(contract(_contractName).yulIR).astJson(); + auto const& currentContract = contract(_contractName); + yulAssert(currentContract.contract); + return currentContract.contract->canBeDeployed() ? loadGeneratedIR(currentContract.yulIR).astJson() : Json{}; } Json CompilerStack::yulCFGJson(std::string const& _contractName) const @@ -992,7 +994,9 @@ Json CompilerStack::yulCFGJson(std::string const& _contractName) const // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to // keep it around when compiling a large project containing many contracts. - return loadGeneratedIR(contract(_contractName).yulIR).cfgJson(); + auto const& currentContract = contract(_contractName); + yulAssert(currentContract.contract); + return currentContract.contract->canBeDeployed() ? loadGeneratedIR(currentContract.yulIR).cfgJson() : Json{}; } std::string const& CompilerStack::yulIROptimized(std::string const& _contractName) const @@ -1008,7 +1012,9 @@ Json CompilerStack::yulIROptimizedAst(std::string const& _contractName) const // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to // keep it around when compiling a large project containing many contracts. - return loadGeneratedIR(contract(_contractName).yulIROptimized).astJson(); + auto const& currentContract = contract(_contractName); + yulAssert(currentContract.contract); + return currentContract.contract->canBeDeployed() ? loadGeneratedIR(currentContract.yulIROptimized).astJson() : Json{}; } evmasm::LinkerObject const& CompilerStack::object(std::string const& _contractName) const From c38e4e66a181ff623a21073a78bdefe61ca80c7d Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 11 Oct 2024 14:57:24 +0200 Subject: [PATCH 0401/1340] Pass `evmVersion` and `eofVersion` to `YulStack` in `ObjectCompilerTest` --- test/libyul/ControlFlowSideEffectsTest.cpp | 4 +- test/libyul/EVMCodeTransformTest.cpp | 5 +- test/libyul/FunctionSideEffects.cpp | 4 +- test/libyul/KnowledgeBaseTest.cpp | 4 +- test/libyul/ObjectCompilerTest.cpp | 6 +- test/libyul/ObjectCompilerTest.h | 2 +- test/libyul/ObjectParser.cpp | 4 +- test/libyul/Parser.cpp | 172 +++++++++--------- test/libyul/YulInterpreterTest.cpp | 3 +- test/libyul/objectCompiler/datacopy.yul | 2 + .../libyul/objectCompiler/dataoffset_code.yul | 2 + .../libyul/objectCompiler/dataoffset_data.yul | 2 + .../libyul/objectCompiler/dataoffset_self.yul | 2 + test/libyul/objectCompiler/datasize_code.yul | 2 + test/libyul/objectCompiler/datasize_data.yul | 2 + test/libyul/objectCompiler/datasize_self.yul | 2 + .../libyul/objectCompiler/function_series.yul | 1 + .../identical_subobjects_full_debug_info.yul | 1 + .../identical_subobjects_no_debug_info.yul | 1 + ...dentical_subobjects_partial_debug_info.yul | 1 + ...bobjects_partial_debug_info_no_use_src.yul | 1 + ...cal_subobjects_with_subject_references.yul | 1 + ..._long_name_does_not_end_up_in_bytecode.yul | 2 + .../leading_and_trailing_dots.yul | 2 + test/libyul/objectCompiler/linkersymbol.yul | 2 + .../objectCompiler/long_object_name.yul | 1 + test/libyul/objectCompiler/manySubObjects.yul | 2 + test/libyul/objectCompiler/metadata.yul | 2 + .../libyul/objectCompiler/namedObjectCode.yul | 2 + .../objectCompiler/nested_optimizer.yul | 1 + test/libyul/objectCompiler/simple.yul | 2 + .../objectCompiler/simple_optimizer.yul | 1 + .../libyul/objectCompiler/sourceLocations.yul | 2 + .../libyul/objectCompiler/subObjectAccess.yul | 2 + test/libyul/objectCompiler/verbatim_bug.yul | 1 + 35 files changed, 144 insertions(+), 102 deletions(-) diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index 50c69b179..b9d883dcd 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -62,9 +62,9 @@ TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std: if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); - // TODO: Add EOF support ControlFlowSideEffectsCollector sideEffects( - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(), std::nullopt), + EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()), obj.code()->root() ); m_obtainedResult.clear(); diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 23c24ce30..75d86136e 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -67,14 +67,13 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin return TestResult::FatalError; } - // TODO: Add EOF support evmasm::Assembly assembly{solidity::test::CommonOptions::get().evmVersion(), false, std::nullopt, {}}; EthAssemblyAdapter adapter(assembly); EVMObjectCompiler::compile( *stack.parserResult(), adapter, - // TODO: Make sure that why we cannot pass here solidity::test::CommonOptions::get().evmVersion() and assembly.eofVersion() - EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}, std::nullopt), + EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()), m_stackOpt, std::nullopt ); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index 7a153de7d..a878d375d 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -88,9 +88,9 @@ TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); - // TODO: Add EOF support std::map functionSideEffects = SideEffectsPropagator::sideEffects( - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(), std::nullopt), + EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()), CallGraphGenerator::callGraph(obj.code()->root()) ); diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index badeb21fe..253e7e0d5 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -63,8 +63,8 @@ class KnowledgeBaseTest return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }); } - // TODO: Add EOF support - EVMDialect m_dialect{EVMVersion{}, std::nullopt, true}; + EVMDialect m_dialect{solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion(), true}; std::shared_ptr m_object; SSAValueTracker m_ssaValues; std::map m_values; diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp index 5d6dd1b23..126c3ad6f 100644 --- a/test/libyul/ObjectCompilerTest.cpp +++ b/test/libyul/ObjectCompilerTest.cpp @@ -46,7 +46,7 @@ using namespace solidity::frontend; using namespace solidity::frontend::test; ObjectCompilerTest::ObjectCompilerTest(std::string const& _filename): - TestCase(_filename) + solidity::frontend::test::EVMVersionRestrictedTestCase(_filename) { m_source = m_reader.source(); m_optimisationPreset = m_reader.enumSetting( @@ -65,8 +65,8 @@ ObjectCompilerTest::ObjectCompilerTest(std::string const& _filename): TestCase::TestResult ObjectCompilerTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { YulStack stack( - EVMVersion(), - std::nullopt, + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, OptimiserSettings::preset(m_optimisationPreset), DebugInfoSelection::All() diff --git a/test/libyul/ObjectCompilerTest.h b/test/libyul/ObjectCompilerTest.h index fe8998700..3310d80b8 100644 --- a/test/libyul/ObjectCompilerTest.h +++ b/test/libyul/ObjectCompilerTest.h @@ -38,7 +38,7 @@ struct Block; namespace solidity::yul::test { -class ObjectCompilerTest: public solidity::frontend::test::TestCase +class ObjectCompilerTest: public solidity::frontend::test::EVMVersionRestrictedTestCase { public: static std::unique_ptr create(Config const& _config) diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index 7ed321cd4..9a891be91 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -112,8 +112,8 @@ std::tuple, ErrorList> tryGetSourceLocationMapping( ErrorList errors; ErrorReporter reporter(errors); - // TODO: Add EOF support - Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); ObjectParser objectParser{reporter, dialect}; CharStream stream(std::move(source), ""); auto object = objectParser.parse(std::make_shared(stream), false); diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 930a34cf1..d0850972b 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -162,8 +162,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_empty_block) auto const sourceText = "/// @src 0:234:543\n" "{}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -181,8 +181,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_with_children) "let z := true\n" "let y := add(1, 2)\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -205,8 +205,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_different_sources) "let z := true\n" "let y := add(1, 2)\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -228,8 +228,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_nested) "/// @src 0:343:434\n" "switch y case 0 {} default {}\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -253,8 +253,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_switch_case) " let z := add(3, 4)\n" "}\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 234, 543); @@ -286,8 +286,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_inherit_into_outer_scope) "let z := true\n" "let y := add(1, 2)\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); @@ -318,8 +318,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_assign_empty) "/// @src 1:1:10\n" "a := true\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // should still parse BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); @@ -340,8 +340,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_source_index) "let b := true\n" "\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); // should still parse BOOST_REQUIRE(errorList.size() == 1); @@ -361,8 +361,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_1) "/// @src 0:234:2026\n" ":= true\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); @@ -385,8 +385,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_2) 2) } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(1, result->root().statements.size()); @@ -420,8 +420,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_3) mstore(1, 2) // FunctionCall } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(2, result->root().statements.size()); @@ -457,8 +457,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_comments_after_valid) let a := true } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(1, result->root().statements.size()); @@ -477,8 +477,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_suffix) /// @src 0:420:680foo {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -495,8 +495,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_prefix) /// abc@src 0:111:222 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); @@ -510,8 +510,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_unspecified) /// @src -1:-1:-1 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "", -1, -1); @@ -525,8 +525,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_non_integer) /// @src a:b:c {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -543,8 +543,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_bad_integer) /// @src 111111111111111111111:222222222222222222222:333333333333333333333 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -565,8 +565,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_ensure_last_match) let x := true } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); @@ -584,8 +584,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_no_whitespace) /// @src 0:111:222@src 1:333:444 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -602,8 +602,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_separated_with_single_s /// @src 0:111:222 @src 1:333:444 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 333, 444); @@ -614,8 +614,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_leading_trailing_whitespace) ErrorList errorList; ErrorReporter reporter(errorList); auto const sourceText = "/// @src 0:111:222 \n{}"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -632,8 +632,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_reference_original_sloc) let x := true } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE(std::holds_alternative(result->root().statements.at(0))); @@ -655,8 +655,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets) let y := /** @src 1:96:165 "contract D {..." */ 128 } )~~~"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 2); @@ -681,8 +681,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_empty_snippet) /// @src 0:111:222 "" {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -696,8 +696,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_befo /// @src 0:111:222"abc" def {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -714,8 +714,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_afte /// @src 0:111:222 "abc"def {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -729,8 +729,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_no_whites /// @src 0:111:222 "abc"@src 1:333:444 "abc" {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 333, 444); @@ -744,8 +744,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_untermina /// @src 0:111:222 " abc @src 1:333:444 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -763,8 +763,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote) /// {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -781,8 +781,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_snippets_with_hex_comment) /// @src 0:111:222 hex"abc"@src 1:333:444 "abc" {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // the second source location is not parsed as such, as the hex string isn't interpreted as snippet but @@ -798,8 +798,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_escapes) /// @src 0:111:222 "\n\\x\x\w\uö\xy\z\y\fq" {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 111, 222); @@ -814,8 +814,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote_snippet_with_whitespaces /// @src 1 : 222 : 333 '\x33\u1234\t\n' {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 222, 333); @@ -830,8 +830,8 @@ BOOST_DATA_TEST_CASE(customSourceLocations_scanner_errors_outside_string_lits_ar /// @src 1:222:333 {{}} )", invalid); - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.empty()); CHECK_LOCATION(result->root().debugData->originLocation, "source1", 222, 333); @@ -849,8 +849,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multi_line_source_loc) /// " @src 0:333:444 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.empty()); CHECK_LOCATION(result->root().debugData->originLocation, "source0", 333, 444); @@ -868,8 +868,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locati let y := /** @src 1:96:165 "function f() internal { \"\/** @src 0:6:7 *\/\"; }" */ 128 } )~~~"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 2); @@ -898,8 +898,8 @@ BOOST_AUTO_TEST_CASE(astid) mstore(1, 2) } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(7)); @@ -921,8 +921,8 @@ BOOST_AUTO_TEST_CASE(astid_reset) mstore(1, 2) } )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(7)); @@ -940,8 +940,8 @@ BOOST_AUTO_TEST_CASE(astid_multi) /// @src -1:-1:-1 @ast-id 7 @src 1:1:1 @ast-id 8 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->root().debugData->astID == int64_t(8)); @@ -955,8 +955,8 @@ BOOST_AUTO_TEST_CASE(astid_invalid) /// @src -1:-1:-1 @ast-id abc @src 1:1:1 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -973,8 +973,8 @@ BOOST_AUTO_TEST_CASE(astid_too_large) /// @ast-id 9223372036854775808 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -990,8 +990,8 @@ BOOST_AUTO_TEST_CASE(astid_way_too_large) /// @ast-id 999999999999999999999999999999999999999 {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -1007,8 +1007,8 @@ BOOST_AUTO_TEST_CASE(astid_not_fully_numeric) /// @ast-id 9x {} )"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); @@ -1030,8 +1030,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multiple_src_tags_on_one_line) "\n" " let x := 123\n" "}\n"; - // TODO: Add EOF support - auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& dialect = EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()); std::shared_ptr result = parse(sourceText, dialect, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->root().statements.size(), 1); diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index 343a17b4a..484a7a241 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -98,7 +98,8 @@ std::string YulInterpreterTest::interpret() { Interpreter::run( state, - EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion(), std::nullopt), + EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion()), m_ast->root(), /*disableExternalCalls=*/ !m_simulateExternalCallsToSelf, /*disableMemoryTracing=*/ false diff --git a/test/libyul/objectCompiler/datacopy.yul b/test/libyul/objectCompiler/datacopy.yul index 9f7fca9ad..46a0ec0f7 100644 --- a/test/libyul/objectCompiler/datacopy.yul +++ b/test/libyul/objectCompiler/datacopy.yul @@ -11,6 +11,8 @@ object "a" { data "data1" "Hello, World!" } } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":77:92 */ diff --git a/test/libyul/objectCompiler/dataoffset_code.yul b/test/libyul/objectCompiler/dataoffset_code.yul index 8ca10add2..1171303af 100644 --- a/test/libyul/objectCompiler/dataoffset_code.yul +++ b/test/libyul/objectCompiler/dataoffset_code.yul @@ -5,6 +5,8 @@ object "a" { data "data1" "Hello, World!" } } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":44:61 */ diff --git a/test/libyul/objectCompiler/dataoffset_data.yul b/test/libyul/objectCompiler/dataoffset_data.yul index 915567489..381cb999f 100644 --- a/test/libyul/objectCompiler/dataoffset_data.yul +++ b/test/libyul/objectCompiler/dataoffset_data.yul @@ -2,6 +2,8 @@ object "a" { code { sstore(0, dataoffset("data1")) } data "data1" "Hello, World!" } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":56:75 */ diff --git a/test/libyul/objectCompiler/dataoffset_self.yul b/test/libyul/objectCompiler/dataoffset_self.yul index 681c24c0e..b6a0552cb 100644 --- a/test/libyul/objectCompiler/dataoffset_self.yul +++ b/test/libyul/objectCompiler/dataoffset_self.yul @@ -2,6 +2,8 @@ object "a" { code { sstore(0, dataoffset("a")) } data "data1" "Hello, World!" } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":44:59 */ diff --git a/test/libyul/objectCompiler/datasize_code.yul b/test/libyul/objectCompiler/datasize_code.yul index cab7987ea..7bf365031 100644 --- a/test/libyul/objectCompiler/datasize_code.yul +++ b/test/libyul/objectCompiler/datasize_code.yul @@ -5,6 +5,8 @@ object "a" { data "data1" "Hello, World!" } } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":44:59 */ diff --git a/test/libyul/objectCompiler/datasize_data.yul b/test/libyul/objectCompiler/datasize_data.yul index d1261d246..f0ae32b1b 100644 --- a/test/libyul/objectCompiler/datasize_data.yul +++ b/test/libyul/objectCompiler/datasize_data.yul @@ -2,6 +2,8 @@ object "a" { code { sstore(0, datasize("data1")) } data "data1" "Hello, World!" } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":44:61 */ diff --git a/test/libyul/objectCompiler/datasize_self.yul b/test/libyul/objectCompiler/datasize_self.yul index 2a19d0a88..fb5b7fb89 100644 --- a/test/libyul/objectCompiler/datasize_self.yul +++ b/test/libyul/objectCompiler/datasize_self.yul @@ -2,6 +2,8 @@ object "a" { code { sstore(0, datasize("a")) } data "data1" "Hello, World!" } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":36:49 */ diff --git a/test/libyul/objectCompiler/function_series.yul b/test/libyul/objectCompiler/function_series.yul index 7be2db96b..8750f1649 100644 --- a/test/libyul/objectCompiler/function_series.yul +++ b/test/libyul/objectCompiler/function_series.yul @@ -11,6 +11,7 @@ object "Contract" { } // ==== +// EVMVersion: >=shanghai // optimizationPreset: none // ---- // Assembly: diff --git a/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul index 74574be13..88ec2c354 100644 --- a/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul +++ b/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul @@ -64,6 +64,7 @@ object "A" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full // ---- // Assembly: diff --git a/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul index aa20ac679..309d99546 100644 --- a/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul +++ b/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul @@ -50,6 +50,7 @@ object "A" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full // ---- // Assembly: diff --git a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul index 9b63bdc1b..82c2fd766 100644 --- a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul +++ b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul @@ -69,6 +69,7 @@ object "A" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full // ---- // Assembly: diff --git a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul index d288503ba..230535525 100644 --- a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul +++ b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul @@ -56,6 +56,7 @@ object "A" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full // ---- // Assembly: diff --git a/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul b/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul index e14b01008..74f613cdf 100644 --- a/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul +++ b/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul @@ -95,6 +95,7 @@ object "A" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full // ---- // Assembly: diff --git a/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul b/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul index c6fd0ac80..18d31087f 100644 --- a/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul +++ b/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul @@ -7,6 +7,8 @@ object "a" { ) } } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":143:185 */ diff --git a/test/libyul/objectCompiler/leading_and_trailing_dots.yul b/test/libyul/objectCompiler/leading_and_trailing_dots.yul index 13c952355..9d32cadc0 100644 --- a/test/libyul/objectCompiler/leading_and_trailing_dots.yul +++ b/test/libyul/objectCompiler/leading_and_trailing_dots.yul @@ -12,6 +12,8 @@ } g(2) } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":53:54 */ diff --git a/test/libyul/objectCompiler/linkersymbol.yul b/test/libyul/objectCompiler/linkersymbol.yul index 91a456461..ba0319108 100644 --- a/test/libyul/objectCompiler/linkersymbol.yul +++ b/test/libyul/objectCompiler/linkersymbol.yul @@ -5,6 +5,8 @@ object "a" { let success := call(gas(), addr, 0, 128, 4, 128, 0) } } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":190:191 */ diff --git a/test/libyul/objectCompiler/long_object_name.yul b/test/libyul/objectCompiler/long_object_name.yul index f75260224..805beb424 100644 --- a/test/libyul/objectCompiler/long_object_name.yul +++ b/test/libyul/objectCompiler/long_object_name.yul @@ -7,6 +7,7 @@ object "t" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full // ---- // Assembly: diff --git a/test/libyul/objectCompiler/manySubObjects.yul b/test/libyul/objectCompiler/manySubObjects.yul index c046b182f..1a087f9c9 100644 --- a/test/libyul/objectCompiler/manySubObjects.yul +++ b/test/libyul/objectCompiler/manySubObjects.yul @@ -134,6 +134,8 @@ object "root" { } } } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":59:75 */ diff --git a/test/libyul/objectCompiler/metadata.yul b/test/libyul/objectCompiler/metadata.yul index 4f8cda7a4..dbd802e33 100644 --- a/test/libyul/objectCompiler/metadata.yul +++ b/test/libyul/objectCompiler/metadata.yul @@ -19,6 +19,8 @@ object "A" { data ".metadata" "M2" data "x" "Hello, World2!" } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":55:68 */ diff --git a/test/libyul/objectCompiler/namedObjectCode.yul b/test/libyul/objectCompiler/namedObjectCode.yul index f18535d71..efb41524b 100644 --- a/test/libyul/objectCompiler/namedObjectCode.yul +++ b/test/libyul/objectCompiler/namedObjectCode.yul @@ -1,6 +1,8 @@ object "a" { code { sstore(0, 1) } } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":36:37 */ diff --git a/test/libyul/objectCompiler/nested_optimizer.yul b/test/libyul/objectCompiler/nested_optimizer.yul index ae0650942..0275e1665 100644 --- a/test/libyul/objectCompiler/nested_optimizer.yul +++ b/test/libyul/objectCompiler/nested_optimizer.yul @@ -15,6 +15,7 @@ object "a" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full // ---- // Assembly: diff --git a/test/libyul/objectCompiler/simple.yul b/test/libyul/objectCompiler/simple.yul index fb2339ceb..f7f945abf 100644 --- a/test/libyul/objectCompiler/simple.yul +++ b/test/libyul/objectCompiler/simple.yul @@ -1,6 +1,8 @@ { sstore(0, 1) } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":41:42 */ diff --git a/test/libyul/objectCompiler/simple_optimizer.yul b/test/libyul/objectCompiler/simple_optimizer.yul index cc6307589..7348b2e20 100644 --- a/test/libyul/objectCompiler/simple_optimizer.yul +++ b/test/libyul/objectCompiler/simple_optimizer.yul @@ -5,6 +5,7 @@ sstore(add(x, 0), z) } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full // ---- // Assembly: diff --git a/test/libyul/objectCompiler/sourceLocations.yul b/test/libyul/objectCompiler/sourceLocations.yul index d9f1d84fc..a1e55ade4 100644 --- a/test/libyul/objectCompiler/sourceLocations.yul +++ b/test/libyul/objectCompiler/sourceLocations.yul @@ -28,6 +28,8 @@ object "a" { data "data1" "Hello, World!" } } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "abc.sol":0:2 */ diff --git a/test/libyul/objectCompiler/subObjectAccess.yul b/test/libyul/objectCompiler/subObjectAccess.yul index b18c902db..047eae408 100644 --- a/test/libyul/objectCompiler/subObjectAccess.yul +++ b/test/libyul/objectCompiler/subObjectAccess.yul @@ -65,6 +65,8 @@ object "A" { } } } +// ==== +// EVMVersion: >=shanghai // ---- // Assembly: // /* "source":57:72 */ diff --git a/test/libyul/objectCompiler/verbatim_bug.yul b/test/libyul/objectCompiler/verbatim_bug.yul index 14a1c02b1..3858b5984 100644 --- a/test/libyul/objectCompiler/verbatim_bug.yul +++ b/test/libyul/objectCompiler/verbatim_bug.yul @@ -23,6 +23,7 @@ object "a" { } } // ==== +// EVMVersion: >=shanghai // optimizationPreset: full // ---- // Assembly: From 69942810512321501c50247b342193e079db53e6 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 3 Oct 2024 12:23:19 -0300 Subject: [PATCH 0402/1340] enable euler ext test --- .circleci/config.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ca1043685..79a149a7e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -760,9 +760,6 @@ defaults: name: t_native_compile_ext_euler project: euler binary_type: native - # NOTE: test suite disabled due to dependence on a specific version of Hardhat - # which does not support shanghai EVM. - compile_only: 1 resource_class: medium - job_native_test_ext_yield_liquidator: &job_native_test_ext_yield_liquidator From e0cf8db3374a4c26d48fc84ac3110b17f694bbf4 Mon Sep 17 00:00:00 2001 From: r0qs Date: Fri, 11 Oct 2024 17:04:09 +0200 Subject: [PATCH 0403/1340] Add tests for irAst and irOptimizedAst --- .../ast_ir_undeployable_contract/args | 1 + .../ast_ir_undeployable_contract/input.sol | 5 +++++ .../ast_ir_undeployable_contract/output | 8 ++++++++ .../in.sol | 5 +++++ .../input.json | 9 +++++++++ .../output.json | 19 +++++++++++++++++++ 6 files changed, 47 insertions(+) create mode 100644 test/cmdlineTests/ast_ir_undeployable_contract/args create mode 100644 test/cmdlineTests/ast_ir_undeployable_contract/input.sol create mode 100644 test/cmdlineTests/ast_ir_undeployable_contract/output create mode 100644 test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/in.sol create mode 100644 test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/input.json create mode 100644 test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/output.json diff --git a/test/cmdlineTests/ast_ir_undeployable_contract/args b/test/cmdlineTests/ast_ir_undeployable_contract/args new file mode 100644 index 000000000..d254bff83 --- /dev/null +++ b/test/cmdlineTests/ast_ir_undeployable_contract/args @@ -0,0 +1 @@ +--ir-ast-json --ir-optimized-ast-json --optimize --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ast_ir_undeployable_contract/input.sol b/test/cmdlineTests/ast_ir_undeployable_contract/input.sol new file mode 100644 index 000000000..06496f4a2 --- /dev/null +++ b/test/cmdlineTests/ast_ir_undeployable_contract/input.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +abstract contract C {} +interface I {} diff --git a/test/cmdlineTests/ast_ir_undeployable_contract/output b/test/cmdlineTests/ast_ir_undeployable_contract/output new file mode 100644 index 000000000..b64e82bd0 --- /dev/null +++ b/test/cmdlineTests/ast_ir_undeployable_contract/output @@ -0,0 +1,8 @@ +IR AST: +null +Optimized IR AST: +null +IR AST: +null +Optimized IR AST: +null diff --git a/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/in.sol b/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/in.sol new file mode 100644 index 000000000..80cc66cd1 --- /dev/null +++ b/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/in.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +abstract contract C {} +interface I {} diff --git a/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/input.json b/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/input.json new file mode 100644 index 000000000..0b40ad072 --- /dev/null +++ b/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/input.json @@ -0,0 +1,9 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["standard_ir_ast_undeployable_contract_requested/in.sol"]} + }, + "settings": { + "outputSelection": {"*": {"*": ["irAst", "irOptimizedAst"]}} + } +} diff --git a/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/output.json b/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/output.json new file mode 100644 index 000000000..dab55ebd1 --- /dev/null +++ b/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/output.json @@ -0,0 +1,19 @@ +{ + "contracts": { + "C": { + "C": { + "irAst": null, + "irOptimizedAst": null + }, + "I": { + "irAst": null, + "irOptimizedAst": null + } + } + }, + "sources": { + "C": { + "id": 0 + } + } +} From 1c0695f664bc123a2cdbf502304c16c9ea2b915f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mati=C4=87?= Date: Mon, 14 Oct 2024 10:44:11 +0200 Subject: [PATCH 0404/1340] Fix ObjectCompiler test (#15511) --- .../objectCompiler/identical_subobjects_creation_deployed.yul | 1 + 1 file changed, 1 insertion(+) diff --git a/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul b/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul index 5eb079db1..01270ef44 100644 --- a/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul +++ b/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul @@ -64,6 +64,7 @@ object "A" { } } // ==== +// EVMVersion: >=constantinople // optimizationPreset: full // ---- // Assembly: From e0ac82d2994e1cb95ad0889d3f1256e3ad8af6ae Mon Sep 17 00:00:00 2001 From: Tran Quang Loc Date: Fri, 11 Oct 2024 22:55:38 +0700 Subject: [PATCH 0405/1340] Use boost's predefined bigint types --- libsolutil/Numeric.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolutil/Numeric.h b/libsolutil/Numeric.h index f4e88de3c..897952452 100644 --- a/libsolutil/Numeric.h +++ b/libsolutil/Numeric.h @@ -45,9 +45,9 @@ namespace solidity { // Numeric types. -using bigint = boost::multiprecision::number>; -using u256 = boost::multiprecision::number>; -using s256 = boost::multiprecision::number>; +using bigint = boost::multiprecision::cpp_int; +using u256 = boost::multiprecision::uint256_t; +using s256 = boost::multiprecision::int256_t; /// Interprets @a _u as a two's complement signed number and returns the resulting s256. inline s256 u2s(u256 _u) From bef29f091ca6b9dd62cae29852bf85edad5941ec Mon Sep 17 00:00:00 2001 From: Tran Quang Loc Date: Fri, 11 Oct 2024 22:57:18 +0700 Subject: [PATCH 0406/1340] Move u512 to Numerics. Use boost:multiprecision::uint512_t. --- libsolutil/Numeric.h | 2 ++ test/tools/yulInterpreter/EVMInstructionInterpreter.cpp | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolutil/Numeric.h b/libsolutil/Numeric.h index 897952452..3ecc813c3 100644 --- a/libsolutil/Numeric.h +++ b/libsolutil/Numeric.h @@ -48,6 +48,8 @@ namespace solidity using bigint = boost::multiprecision::cpp_int; using u256 = boost::multiprecision::uint256_t; using s256 = boost::multiprecision::int256_t; +using u512 = boost::multiprecision::uint512_t; + /// Interprets @a _u as a two's complement signed number and returns the resulting s256. inline s256 u2s(u256 _u) diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index d2cbdb11b..18a87f7bf 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -106,8 +106,6 @@ void copyZeroExtendedWithOverlap( } -using u512 = boost::multiprecision::number>; - u256 EVMInstructionInterpreter::eval( evmasm::Instruction _instruction, std::vector const& _arguments From 9cafc42f1e913856070302cb0e8a156dabda3ed5 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 15 Oct 2024 13:09:45 +0200 Subject: [PATCH 0407/1340] eof: Support `DATALOADN` (EIP-7480) --- libevmasm/Assembly.cpp | 71 ++++++++++++++++--- libevmasm/Assembly.h | 4 ++ libevmasm/AssemblyItem.cpp | 38 +++++++--- libevmasm/AssemblyItem.h | 4 ++ libevmasm/Instruction.cpp | 2 + libevmasm/Instruction.h | 1 + liblangutil/EVMVersion.cpp | 3 + libyul/AsmAnalysis.cpp | 14 ++++ libyul/backends/evm/AbstractAssembly.h | 7 ++ libyul/backends/evm/EVMDialect.cpp | 24 ++++++- libyul/backends/evm/EthAssemblyAdapter.cpp | 5 ++ libyul/backends/evm/EthAssemblyAdapter.h | 2 + libyul/backends/evm/NoOutputAssembly.cpp | 5 ++ libyul/backends/evm/NoOutputAssembly.h | 2 + .../strict_asm_eof_dataloadn_prague/args | 1 + .../strict_asm_eof_dataloadn_prague/input.yul | 9 +++ .../strict_asm_eof_dataloadn_prague/output | 27 +++++++ test/libyul/objectCompiler/dataloadn.yul | 32 +++++++++ .../eof/auxdataloadn_in_eof.yul | 12 ++++ ...xdataloadn_in_eof_invalid_literal_type.yul | 14 ++++ .../eof/auxdataloadn_in_eof_invalid_value.yul | 14 ++++ .../eof/auxdataloadn_in_legacy.yul | 15 ++++ .../EVMInstructionInterpreter.cpp | 12 ++-- 23 files changed, 291 insertions(+), 27 deletions(-) create mode 100644 test/cmdlineTests/strict_asm_eof_dataloadn_prague/args create mode 100644 test/cmdlineTests/strict_asm_eof_dataloadn_prague/input.yul create mode 100644 test/cmdlineTests/strict_asm_eof_dataloadn_prague/output create mode 100644 test/libyul/objectCompiler/dataloadn.yul create mode 100644 test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof.yul create mode 100644 test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_literal_type.yul create mode 100644 test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_value.yul create mode 100644 test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index ab26526e1..8f645f6fd 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -717,6 +717,11 @@ AssemblyItem Assembly::newImmutableAssignment(std::string const& _identifier) return AssemblyItem{AssignImmutable, h}; } +AssemblyItem Assembly::newAuxDataLoadN(size_t _offset) +{ + return AssemblyItem{AuxDataLoadN, _offset}; +} + Assembly& Assembly::optimise(OptimiserSettings const& _settings) { optimiseInternal(_settings, {}); @@ -922,8 +927,8 @@ void appendBigEndianUint16(bytes& _dest, ValueT _value) std::tuple, size_t> Assembly::createEOFHeader(std::set const& _referencedSubIds) const { bytes retBytecode; - std::vector codeSectionSizeOffsets; - size_t dataSectionSizeOffset; + std::vector codeSectionSizePositions; + size_t dataSectionSizePosition; retBytecode.push_back(0xef); retBytecode.push_back(0x00); @@ -938,7 +943,7 @@ std::tuple, size_t> Assembly::createEOFHeader(std::se for (auto const& codeSection: m_codeSections) { (void) codeSection; - codeSectionSizeOffsets.emplace_back(retBytecode.size()); + codeSectionSizePositions.emplace_back(retBytecode.size()); appendBigEndianUint16(retBytecode, 0u); // placeholder for length of code } @@ -952,7 +957,7 @@ std::tuple, size_t> Assembly::createEOFHeader(std::se } retBytecode.push_back(0x04); // kind=data - dataSectionSizeOffset = retBytecode.size(); + dataSectionSizePosition = retBytecode.size(); appendBigEndianUint16(retBytecode, 0u); // length of data retBytecode.push_back(0x00); // terminator @@ -965,7 +970,7 @@ std::tuple, size_t> Assembly::createEOFHeader(std::se appendBigEndianUint16(retBytecode, 0xFFFFu); } - return {retBytecode, codeSectionSizeOffsets, dataSectionSizeOffset}; + return {retBytecode, codeSectionSizePositions, dataSectionSizePosition}; } LinkerObject const& Assembly::assemble() const @@ -1348,6 +1353,23 @@ std::map Assembly::findReferencedContainers() const return replacements; } +std::optional Assembly::findMaxAuxDataLoadNOffset() const +{ + std::optional maxOffset = std::nullopt; + for (auto&& codeSection: m_codeSections) + for (AssemblyItem const& item: codeSection.items) + if (item.type() == AuxDataLoadN) + { + solAssert(item.data() <= std::numeric_limits::max(), "Invalid auxdataloadn index value."); + auto const offset = static_cast(item.data()); + if (!maxOffset.has_value() || offset > maxOffset.value()) + maxOffset = offset; + + } + + return maxOffset; +} + LinkerObject const& Assembly::assembleEOF() const { solAssert(m_eofVersion.has_value() && m_eofVersion == 1); @@ -1362,11 +1384,14 @@ LinkerObject const& Assembly::assembleEOF() const "Expected the first code section to have zero inputs and be non-returning." ); + auto const maxAuxDataLoadNOffset = findMaxAuxDataLoadNOffset(); + // Insert EOF1 header. - auto [headerBytecode, codeSectionSizeOffsets, dataSectionSizeOffset] = createEOFHeader(referencedSubIds); + auto [headerBytecode, codeSectionSizePositions, dataSectionSizePosition] = createEOFHeader(referencedSubIds); ret.bytecode = headerBytecode; m_tagPositionsInBytecode = std::vector(m_usedTags, std::numeric_limits::max()); + std::map dataSectionRef; for (auto&& [codeSectionIndex, codeSection]: m_codeSections | ranges::views::enumerate) { @@ -1380,6 +1405,8 @@ LinkerObject const& Assembly::assembleEOF() const switch (item.type()) { case Operation: + solAssert(item.instruction() != Instruction::DATALOADN); + solAssert(!(item.instruction() >= Instruction::PUSH0 && item.instruction() <= Instruction::PUSH32)); ret.bytecode += assembleOperation(item); break; case Push: @@ -1401,12 +1428,21 @@ LinkerObject const& Assembly::assembleEOF() const case Tag: ret.bytecode += assembleTag(item, ret.bytecode.size(), false); break; + case AuxDataLoadN: + { + // In findMaxAuxDataLoadNOffset we already verified that unsigned data value fits 2 bytes + solAssert(item.data() <= std::numeric_limits::max(), "Invalid auxdataloadn position."); + ret.bytecode.push_back(uint8_t(Instruction::DATALOADN)); + dataSectionRef[ret.bytecode.size()] = static_cast(item.data()); + appendBigEndianUint16(ret.bytecode, item.data()); + break; + } default: solThrow(InvalidOpcode, "Unexpected opcode while assembling."); } } - setBigEndianUint16(ret.bytecode, codeSectionSizeOffsets[codeSectionIndex], ret.bytecode.size() - sectionStart); + setBigEndianUint16(ret.bytecode, codeSectionSizePositions[codeSectionIndex], ret.bytecode.size() - sectionStart); } for (auto i: referencedSubIds) @@ -1422,8 +1458,25 @@ LinkerObject const& Assembly::assembleEOF() const ret.bytecode += m_auxiliaryData; - auto dataLength = ret.bytecode.size() - dataStart; - setBigEndianUint16(ret.bytecode, dataSectionSizeOffset, dataLength); + auto const preDeployDataSectionSize = ret.bytecode.size() - dataStart; + // DATALOADN loads 32 bytes from EOF data section zero padded if reading out of data bounds. + // In our case we do not allow DATALOADN with offsets which reads out of data bounds. + auto const staticAuxDataSize = maxAuxDataLoadNOffset.has_value() ? (*maxAuxDataLoadNOffset + 32u) : 0u; + solRequire(preDeployDataSectionSize + staticAuxDataSize < std::numeric_limits::max(), AssemblyException, + "Invalid DATALOADN offset."); + + // If some data was already added to data section we need to update data section refs accordingly + if (preDeployDataSectionSize > 0) + for (auto [refPosition, staticAuxDataOffset] : dataSectionRef) + { + // staticAuxDataOffset + preDeployDataSectionSize value is already verified to fit 2 bytes because + // staticAuxDataOffset < staticAuxDataSize + setBigEndianUint16(ret.bytecode, refPosition, staticAuxDataOffset + preDeployDataSectionSize); + } + + auto const preDeployAndStaticAuxDataSize = preDeployDataSectionSize + staticAuxDataSize; + + setBigEndianUint16(ret.bytecode, dataSectionSizePosition, preDeployAndStaticAuxDataSize); return ret; } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index de1ac20f2..9b15936d6 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -79,6 +79,7 @@ class Assembly AssemblyItem newPushLibraryAddress(std::string const& _identifier); AssemblyItem newPushImmutable(std::string const& _identifier); AssemblyItem newImmutableAssignment(std::string const& _identifier); + AssemblyItem newAuxDataLoadN(size_t offset); AssemblyItem const& append(AssemblyItem _i); AssemblyItem const& append(bytes const& _data) { return append(newData(_data)); } @@ -91,6 +92,7 @@ class Assembly void appendLibraryAddress(std::string const& _identifier) { append(newPushLibraryAddress(_identifier)); } void appendImmutable(std::string const& _identifier) { append(newPushImmutable(_identifier)); } void appendImmutableAssignment(std::string const& _identifier) { append(newImmutableAssignment(_identifier)); } + void appendAuxDataLoadN(uint16_t _offset) { append(newAuxDataLoadN(_offset));} void appendVerbatim(bytes _data, size_t _arguments, size_t _returnVariables) { @@ -240,6 +242,8 @@ class Assembly /// Returns map from m_subs to an index of subcontainer in the final EOF bytecode std::map findReferencedContainers() const; + /// Returns max AuxDataLoadN offset for the assembly. + std::optional findMaxAuxDataLoadNOffset() const; /// Assemble bytecode for AssemblyItem type. [[nodiscard]] bytes assembleOperation(AssemblyItem const& _item) const; diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 1bc805780..202bb2256 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -102,9 +102,13 @@ std::pair AssemblyItem::nameAndData(langutil::EVMVersi return {"PUSH data", toStringInHex(data())}; case VerbatimBytecode: return {"VERBATIM", util::toHex(verbatimData())}; - default: - assertThrow(false, InvalidOpcode, ""); + case AuxDataLoadN: + return {"AUXDATALOADN", util::toString(data())}; + case UndefinedItem: + solAssert(false); } + + util::unreachable(); } void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag) @@ -161,10 +165,13 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, langutil::EVMVersion _ } case VerbatimBytecode: return std::get<2>(*m_verbatimBytecode).size(); - default: - break; + case AuxDataLoadN: + return 1 + 2; + case UndefinedItem: + solAssert(false); } - assertThrow(false, InvalidOpcode, ""); + + util::unreachable(); } size_t AssemblyItem::arguments() const @@ -203,7 +210,10 @@ size_t AssemblyItem::returnValues() const return 0; case VerbatimBytecode: return std::get<1>(*m_verbatimBytecode); - default: + case AuxDataLoadN: + return 1; + case AssignImmutable: + case UndefinedItem: break; } return 0; @@ -226,10 +236,13 @@ bool AssemblyItem::canBeFunctional() const case PushLibraryAddress: case PushDeployTimeAddress: case PushImmutable: + case AuxDataLoadN: return true; case Tag: return false; - default: + case AssignImmutable: + case VerbatimBytecode: + case UndefinedItem: break; } return false; @@ -327,8 +340,10 @@ std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const case VerbatimBytecode: text = std::string("verbatimbytecode_") + util::toHex(std::get<2>(*m_verbatimBytecode)); break; - default: - assertThrow(false, InvalidOpcode, ""); + case AuxDataLoadN: + assertThrow(data() <= std::numeric_limits::max(), AssemblyException, "Invalid auxdataloadn argument."); + text = "auxdataloadn(" + std::to_string(static_cast(data())) + ")"; + break; } if (m_jumpType == JumpType::IntoFunction || m_jumpType == JumpType::OutOfFunction) { @@ -396,11 +411,12 @@ std::ostream& solidity::evmasm::operator<<(std::ostream& _out, AssemblyItem cons case VerbatimBytecode: _out << " Verbatim " << util::toHex(_item.verbatimData()); break; + case AuxDataLoadN: + _out << " AuxDataLoadN " << util::toString(_item.data()); + break; case UndefinedItem: _out << " ???"; break; - default: - assertThrow(false, InvalidOpcode, ""); } return _out; } diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index f06c72bac..226a126c3 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -51,6 +51,10 @@ enum AssemblyItemType PushDeployTimeAddress, ///< Push an address to be filled at deploy time. Should not be touched by the optimizer. PushImmutable, ///< Push the currently unknown value of an immutable variable. The actual value will be filled in by the constructor. AssignImmutable, ///< Assigns the current value on the stack to an immutable variable. Only valid during creation code. + + /// Loads 32 bytes from static auxiliary data of EOF data section. The offset does *not* have to be always from the beginning + /// of the data EOF section. More details here: https://github.com/ipsilon/eof/blob/main/spec/eof.md#data-section-lifecycle + AuxDataLoadN, VerbatimBytecode ///< Contains data that is inserted into the bytecode code section without modification. }; diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 943f34ee4..b9bb21227 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -168,6 +168,7 @@ std::map const solidity::evmasm::c_instructions = { "LOG2", Instruction::LOG2 }, { "LOG3", Instruction::LOG3 }, { "LOG4", Instruction::LOG4 }, + { "DATALOADN", Instruction::DATALOADN }, { "CREATE", Instruction::CREATE }, { "CALL", Instruction::CALL }, { "CALLCODE", Instruction::CALLCODE }, @@ -252,6 +253,7 @@ static std::map const c_instructionInfo = {Instruction::MSIZE, {"MSIZE", 0, 0, 1, false, Tier::Base}}, {Instruction::GAS, {"GAS", 0, 0, 1, false, Tier::Base}}, {Instruction::JUMPDEST, {"JUMPDEST", 0, 0, 0, true, Tier::Special}}, + {Instruction::DATALOADN, {"DATALOADN", 2, 0, 1, true, Tier::Low}}, {Instruction::PUSH0, {"PUSH0", 0, 0, 1, false, Tier::Base}}, {Instruction::PUSH1, {"PUSH1", 1, 0, 1, false, Tier::VeryLow}}, {Instruction::PUSH2, {"PUSH2", 2, 0, 1, false, Tier::VeryLow}}, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index a3629eec2..2ed773cc9 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -182,6 +182,7 @@ enum class Instruction: uint8_t LOG3, ///< Makes a log entry; 3 topics. LOG4, ///< Makes a log entry; 4 topics. + DATALOADN = 0xd1, ///< load data from EOF data section CREATE = 0xf0, ///< create a new account with associated code CALL, ///< message-call into an account CALLCODE, ///< message-call with another account's code only diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index 6435e0f15..bdd663c41 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -76,6 +76,9 @@ bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersi case Instruction::EXTCODECOPY: case Instruction::GAS: return !_eofVersion.has_value(); + // Instructions below available only in EOF + case Instruction::DATALOADN: + return _eofVersion.has_value(); default: return true; } diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 682931dc4..9eb546547 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -428,6 +428,20 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) expectUnlimitedStringLiteral(std::get(arg)); continue; } + else if (*literalArgumentKind == LiteralKind::Number) + { + std::string functionName = _funCall.functionName.name.str(); + if (functionName == "auxdataloadn") + { + auto const& argumentAsLiteral = std::get(arg); + if (argumentAsLiteral.value.value() > std::numeric_limits::max()) + m_errorReporter.typeError( + 5202_error, + nativeLocationOf(arg), + "Invalid auxdataloadn argument value. Offset must be in range 0...0xFFFF" + ); + } + } } expectExpression(arg); } diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index fe4500896..ed06bebac 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -112,7 +112,14 @@ class AbstractAssembly /// Appends an assignment to an immutable variable. virtual void appendImmutableAssignment(std::string const& _identifier) = 0; + /// Appends an operation that loads 32 bytes of data from a known offset relative to the start of the static_aux_data area of the EOF data section. + /// Note that static_aux_data is only a part or the data section. + /// It is preceded by the pre_deploy_data, whose size is not determined before the bytecode is assembled, and which cannot be accessed using this function. + /// The function is meant to allow indexing into static_aux_data in a way that's independent of the size of pre_deploy_data. + virtual void appendAuxDataLoadN(uint16_t _offset) = 0; + /// Appends data to the very end of the bytecode. Repeated calls concatenate. + /// EOF auxiliary data in data section and the auxiliary data are different things. virtual void appendToAuxiliaryData(bytes const& _data) = 0; /// Mark this assembly as invalid. Any attempt to request bytecode from it should throw. diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 6bfdc9cb9..9e9d5e542 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -199,6 +199,7 @@ std::map createBuiltins(langutil::EVMVersion _ev opcode != evmasm::Instruction::JUMP && opcode != evmasm::Instruction::JUMPI && opcode != evmasm::Instruction::JUMPDEST && + opcode != evmasm::Instruction::DATALOADN && _evmVersion.hasOpcode(opcode, _eofVersion) && !prevRandaoException(name) ) @@ -235,7 +236,7 @@ std::map createBuiltins(langutil::EVMVersion _ev }) ); - if (!_eofVersion.has_value()) + if (!_eofVersion.has_value()) // non-EOF context { builtins.emplace(createFunction("datasize", 1, 1, SideEffects{}, {LiteralKind::String}, []( FunctionCall const& _call, @@ -345,6 +346,27 @@ std::map createBuiltins(langutil::EVMVersion _ev } )); } + else // EOF context + { + builtins.emplace(createFunction( + "auxdataloadn", + 1, + 1, + SideEffects{}, + {LiteralKind::Number}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == 1, ""); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal, ""); + yulAssert(literal->value.value() <= std::numeric_limits::max(), ""); + _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); + } + )); + } } return builtins; } diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index e3a2e01e1..36a437c8c 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -175,6 +175,11 @@ void EthAssemblyAdapter::appendImmutableAssignment(std::string const& _identifie m_assembly.appendImmutableAssignment(_identifier); } +void EthAssemblyAdapter::appendAuxDataLoadN(uint16_t _offset) +{ + m_assembly.appendAuxDataLoadN(_offset); +} + void EthAssemblyAdapter::markAsInvalid() { m_assembly.markAsInvalid(); diff --git a/libyul/backends/evm/EthAssemblyAdapter.h b/libyul/backends/evm/EthAssemblyAdapter.h index 011081ded..7dc89e38e 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.h +++ b/libyul/backends/evm/EthAssemblyAdapter.h @@ -65,6 +65,8 @@ class EthAssemblyAdapter: public AbstractAssembly void appendImmutable(std::string const& _identifier) override; void appendImmutableAssignment(std::string const& _identifier) override; + void appendAuxDataLoadN(uint16_t _offset) override; + void markAsInvalid() override; langutil::EVMVersion evmVersion() const override; diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index c444a7143..9d8bd73a3 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -129,6 +129,11 @@ void NoOutputAssembly::appendImmutableAssignment(std::string const&) yulAssert(false, "setimmutable not implemented."); } +void NoOutputAssembly::appendAuxDataLoadN(uint16_t) +{ + yulAssert(false, "auxdataloadn not implemented."); +} + NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom): EVMDialect(_copyFrom.evmVersion(), _copyFrom.eofVersion(), _copyFrom.providesObjectAccess()) { diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h index 8d7dda0bb..6d3aacb24 100644 --- a/libyul/backends/evm/NoOutputAssembly.h +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -75,6 +75,8 @@ class NoOutputAssembly: public AbstractAssembly void appendImmutable(std::string const& _identifier) override; void appendImmutableAssignment(std::string const& _identifier) override; + void appendAuxDataLoadN(uint16_t) override; + void markAsInvalid() override {} langutil::EVMVersion evmVersion() const override { return m_evmVersion; } diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/args b/test/cmdlineTests/strict_asm_eof_dataloadn_prague/args new file mode 100644 index 000000000..0078e6e68 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_prague/args @@ -0,0 +1 @@ + --strict-assembly --experimental-eof-version 1 --evm-version prague --asm --ir-optimized --bin --debug-info none diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/input.yul b/test/cmdlineTests/strict_asm_eof_dataloadn_prague/input.yul new file mode 100644 index 000000000..bd29cf659 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_prague/input.yul @@ -0,0 +1,9 @@ +object "a" { + code { + mstore(0, auxdataloadn(0)) + return(0, 32) + } + + data "data1" "Hello, World!" +} + diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output b/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output new file mode 100644 index 000000000..5f768feeb --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output @@ -0,0 +1,27 @@ + +======= strict_asm_eof_dataloadn_prague/input.yul (EVM) ======= + +Pretty printed source: +object "a" { + code { + { + mstore(0, auxdataloadn(0)) + return(0, 32) + } + } + data "data1" hex"48656c6c6f2c20576f726c6421" +} + + +Binary representation: +ef0001010004020001000904002d000080ffffd1000d5f5260205ff348656c6c6f2c20576f726c6421 + +Text representation: + auxdataloadn(0) + 0x00 + mstore + 0x20 + 0x00 + return +stop +data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 diff --git a/test/libyul/objectCompiler/dataloadn.yul b/test/libyul/objectCompiler/dataloadn.yul new file mode 100644 index 000000000..8b1c7ab80 --- /dev/null +++ b/test/libyul/objectCompiler/dataloadn.yul @@ -0,0 +1,32 @@ +object "a" { + code { + { + mstore(0, auxdataloadn(0)) + return(0, 32) + } + } + data "data1" hex"48656c6c6f2c20576f726c6421" +} + +// ==== +// bytecodeFormat: >=EOFv1 +// EVMVersion: >=prague +// ---- +// Assembly: +// /* "source":56:71 */ +// auxdataloadn(0) +// /* "source":53:54 */ +// 0x00 +// /* "source":46:72 */ +// mstore +// /* "source":95:97 */ +// 0x20 +// /* "source":92:93 */ +// 0x00 +// /* "source":85:98 */ +// return +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// Bytecode: ef0001010004020001000904002d000080ffffd1000d5f5260205ff348656c6c6f2c20576f726c6421 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP MULMOD DIV STOP 0x2D STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT DATALOADN 0xD PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN BASEFEE PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000 +// SourceMappings: 56:15:0:-:0;53:1;46:26;95:2;92:1;85:13 \ No newline at end of file diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof.yul new file mode 100644 index 000000000..552620a72 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof.yul @@ -0,0 +1,12 @@ +object "a" { + code { + mstore(0, auxdataloadn(0)) + return(0, 32) + } + + data "data1" "Hello, World!" +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 \ No newline at end of file diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_literal_type.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_literal_type.yul new file mode 100644 index 000000000..08de0df18 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_literal_type.yul @@ -0,0 +1,14 @@ +object "a" { + code { + mstore(0, auxdataloadn("0")) + return(0, 32) + } + + data "data1" "Hello, World!" + } + +// ==== +// EVMVersion: >=prague +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 5859: (55-58): Function expects number literal. \ No newline at end of file diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_value.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_value.yul new file mode 100644 index 000000000..08e803784 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_value.yul @@ -0,0 +1,14 @@ +object "a" { + code { + mstore(0, auxdataloadn(0x01FFFF)) + return(0, 32) + } + + data "data1" "Hello, World!" +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 5202: (55-63): Invalid auxdataloadn argument value. Offset must be in range 0...0xFFFF diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul new file mode 100644 index 000000000..0fe3221f1 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul @@ -0,0 +1,15 @@ +object "a" { + code { + mstore(0, auxdataloadn(0)) + return(0, 32) + } + + data "data1" "Hello, World!" +} + +// ==== +// EVMVersion: >=prague +// bytecodeFormat: legacy +// ---- +// DeclarationError 4619: (42-54): Function "auxdataloadn" not found. +// TypeError 3950: (42-57): Expected expression to evaluate to one value, but got 0 values instead. \ No newline at end of file diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index d2cbdb11b..768734458 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -417,7 +418,7 @@ u256 EVMInstructionInterpreter::eval( m_state.trace.clear(); BOOST_THROW_EXCEPTION(ExplicitlyTerminated()); case Instruction::POP: - break; + return 0; // --------------- invalid in strict assembly --------------- case Instruction::JUMP: case Instruction::JUMPI: @@ -487,13 +488,12 @@ u256 EVMInstructionInterpreter::eval( case Instruction::SWAP14: case Instruction::SWAP15: case Instruction::SWAP16: - { - yulAssert(false, ""); - return 0; - } + yulAssert(false, "Impossible in strict assembly."); + case Instruction::DATALOADN: + solUnimplemented("DATALOADN unimplemented in yul interpreter."); } - return 0; + util::unreachable(); } u256 EVMInstructionInterpreter::evalBuiltin( From 77811b06f0505de6551fc85ec8a0603e3f034a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 14 Oct 2024 13:44:53 +0200 Subject: [PATCH 0408/1340] UnusedPruner: Remove dead code --- libyul/optimiser/UnusedPruner.cpp | 38 +++++-------------------------- libyul/optimiser/UnusedPruner.h | 27 ---------------------- 2 files changed, 6 insertions(+), 59 deletions(-) diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index a3b6c0708..75cdd2dd1 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -55,20 +55,6 @@ UnusedPruner::UnusedPruner( ++m_references[f]; } -UnusedPruner::UnusedPruner( - Dialect const& _dialect, - FunctionDefinition& _function, - bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions -): - m_dialect(_dialect), - m_allowMSizeOptimization(_allowMSizeOptimization) -{ - m_references = ReferencesCounter::countReferences(_function); - for (auto const& f: _externallyUsedFunctions) - ++m_references[f]; -} - void UnusedPruner::operator()(Block& _block) { for (auto&& statement: _block.statements) @@ -142,8 +128,12 @@ void UnusedPruner::runUntilStabilised( while (true) { UnusedPruner pruner( - _dialect, _ast, _allowMSizeOptimization, _functionSideEffects, - _externallyUsedFunctions); + _dialect, + _ast, + _allowMSizeOptimization, + _functionSideEffects, + _externallyUsedFunctions + ); pruner(_ast); if (!pruner.shouldRunAgain()) return; @@ -162,22 +152,6 @@ void UnusedPruner::runUntilStabilisedOnFullAST( runUntilStabilised(_dialect, _ast, allowMSizeOptimization, &functionSideEffects, _externallyUsedFunctions); } -void UnusedPruner::runUntilStabilised( - Dialect const& _dialect, - FunctionDefinition& _function, - bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions -) -{ - while (true) - { - UnusedPruner pruner(_dialect, _function, _allowMSizeOptimization, _externallyUsedFunctions); - pruner(_function); - if (!pruner.shouldRunAgain()) - return; - } -} - bool UnusedPruner::used(YulName _name) const { return m_references.count(_name) && m_references.at(_name) > 0; diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index b0ba53bce..040e7ce43 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -68,15 +68,6 @@ class UnusedPruner: public ASTModifier std::set const& _externallyUsedFunctions = {} ); - static void run( - Dialect const& _dialect, - Block& _ast, - std::set const& _externallyUsedFunctions = {} - ) - { - runUntilStabilisedOnFullAST(_dialect, _ast, _externallyUsedFunctions); - } - /// Run the pruner until the code does not change anymore. /// The provided block has to be a full AST. /// The pruner itself determines if msize is used and which user-defined functions @@ -87,18 +78,6 @@ class UnusedPruner: public ASTModifier std::set const& _externallyUsedFunctions = {} ); - // Run the pruner until the code does not change anymore. - // Only run on the given function. - // @param _allowMSizeOptimization if true, allows to remove instructions - // whose only side-effect is a potential change of the return value of - // the msize instruction. - static void runUntilStabilised( - Dialect const& _dialect, - FunctionDefinition& _functionDefinition, - bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions = {} - ); - private: UnusedPruner( Dialect const& _dialect, @@ -107,12 +86,6 @@ class UnusedPruner: public ASTModifier std::map const* _functionSideEffects = nullptr, std::set const& _externallyUsedFunctions = {} ); - UnusedPruner( - Dialect const& _dialect, - FunctionDefinition& _function, - bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions = {} - ); bool used(YulName _name) const; void subtractReferences(std::map const& _subtrahend); From 125d25a21955160ce7c9a0c1a1a94c56a19a0027 Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 15 Oct 2024 16:23:29 +0200 Subject: [PATCH 0409/1340] Restrict object compiler tests to exclude deprecated EVM versions (#15516) --- test/libyul/objectCompiler/data.yul | 2 ++ test/libyul/objectCompiler/namedObject.yul | 2 ++ test/libyul/objectCompiler/smoke.yul | 2 ++ test/libyul/objectCompiler/subObject.yul | 2 ++ test/libyul/objectCompiler/subSubObject.yul | 2 ++ 5 files changed, 10 insertions(+) diff --git a/test/libyul/objectCompiler/data.yul b/test/libyul/objectCompiler/data.yul index ad8899fb1..4447a0b8e 100644 --- a/test/libyul/objectCompiler/data.yul +++ b/test/libyul/objectCompiler/data.yul @@ -3,6 +3,8 @@ object "a" { // Unreferenced data is not added to the assembled bytecode. data "str" "Hello, World!" } +// ==== +// EVMVersion: >=constantinople // ---- // Assembly: // /* "source":22:29 */ diff --git a/test/libyul/objectCompiler/namedObject.yul b/test/libyul/objectCompiler/namedObject.yul index 06539dd89..66727585d 100644 --- a/test/libyul/objectCompiler/namedObject.yul +++ b/test/libyul/objectCompiler/namedObject.yul @@ -1,6 +1,8 @@ object "a" { code {} } +// ==== +// EVMVersion: >=constantinople // ---- // Assembly: // /* "source":22:29 */ diff --git a/test/libyul/objectCompiler/smoke.yul b/test/libyul/objectCompiler/smoke.yul index 82aea42f5..2ca3d62f0 100644 --- a/test/libyul/objectCompiler/smoke.yul +++ b/test/libyul/objectCompiler/smoke.yul @@ -1,5 +1,7 @@ { } +// ==== +// EVMVersion: >=constantinople // ---- // Assembly: // /* "source":27:34 */ diff --git a/test/libyul/objectCompiler/subObject.yul b/test/libyul/objectCompiler/subObject.yul index a47c4feda..f394054d7 100644 --- a/test/libyul/objectCompiler/subObject.yul +++ b/test/libyul/objectCompiler/subObject.yul @@ -4,6 +4,8 @@ object "a" { data "str" "Hello, World!" object "sub" { code { sstore(0, 1) } } } +// ==== +// EVMVersion: >=constantinople // ---- // Assembly: // /* "source":22:29 */ diff --git a/test/libyul/objectCompiler/subSubObject.yul b/test/libyul/objectCompiler/subSubObject.yul index a4511324e..a7274ce63 100644 --- a/test/libyul/objectCompiler/subSubObject.yul +++ b/test/libyul/objectCompiler/subSubObject.yul @@ -10,6 +10,8 @@ object "a" { } } } +// ==== +// EVMVersion: >=constantinople // ---- // Assembly: // /* "source":22:29 */ From 825d69872706a4d0dbdc99744236f71d5746601b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 8 Oct 2024 17:10:24 +0200 Subject: [PATCH 0410/1340] Generalize the profiler used by optimizer suite and make it a singleton --- libsolutil/CMakeLists.txt | 2 + libsolutil/Profiler.cpp | 88 ++++++++++++++++++++++++++++++++++++++ libsolutil/Profiler.h | 75 ++++++++++++++++++++++++++++++++ libyul/optimiser/Suite.cpp | 65 +++------------------------- libyul/optimiser/Suite.h | 3 -- 5 files changed, 172 insertions(+), 61 deletions(-) create mode 100644 libsolutil/Profiler.cpp create mode 100644 libsolutil/Profiler.h diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index 6ece23805..aac943517 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -27,6 +27,8 @@ set(sources Numeric.cpp Numeric.h picosha2.h + Profiler.cpp + Profiler.h Result.h SetOnce.h StackTooDeepString.h diff --git a/libsolutil/Profiler.cpp b/libsolutil/Profiler.cpp new file mode 100644 index 000000000..8cc186b92 --- /dev/null +++ b/libsolutil/Profiler.cpp @@ -0,0 +1,88 @@ +/* + 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 + +#include + +#include + +#include +#include +#include + +using namespace std::chrono; +using namespace solidity; + +#ifdef PROFILE_OPTIMIZER_STEPS + +util::Profiler::Probe::Probe(std::string _scopeName): + m_scopeName(std::move(_scopeName)), + m_startTime(steady_clock::now()) +{ +} + +util::Profiler::Probe::~Probe() +{ + steady_clock::time_point endTime = steady_clock::now(); + int64_t durationInMicroseconds = duration_cast(endTime - m_startTime).count(); + + auto [durationIt, inserted] = Profiler::singleton().m_durations.try_emplace(m_scopeName, 0); + durationIt->second += durationInMicroseconds; +} + +util::Profiler::~Profiler() +{ + outputPerformanceMetrics(); +} + +util::Profiler& util::Profiler::singleton() +{ + static Profiler profiler; + return profiler; +} + +void util::Profiler::outputPerformanceMetrics() +{ + std::vector> durations(m_durations.begin(), m_durations.end()); + std::sort( + durations.begin(), + durations.end(), + [](std::pair const& _lhs, std::pair const& _rhs) -> bool + { + return _lhs.second < _rhs.second; + } + ); + + int64_t totalDurationInMicroseconds = 0; + for (auto&& [scopeName, durationInMicroseconds]: durations) + totalDurationInMicroseconds += durationInMicroseconds; + + std::cerr << "Performance metrics for profiled scopes" << std::endl; + std::cerr << "=======================================" << std::endl; + constexpr double microsecondsInSecond = 1000000; + for (auto&& [scopeName, durationInMicroseconds]: durations) + { + double percentage = 100.0 * static_cast(durationInMicroseconds) / static_cast(totalDurationInMicroseconds); + double durationInSeconds = static_cast(durationInMicroseconds) / microsecondsInSecond; + std::cerr << fmt::format("{:>7.3f}% ({} s): {}", percentage, durationInSeconds, scopeName) << std::endl; + } + double totalDurationInSeconds = static_cast(totalDurationInMicroseconds) / microsecondsInSecond; + std::cerr << "--------------------------------------" << std::endl; + std::cerr << fmt::format("{:>7}% ({:.3f} s)", 100, totalDurationInSeconds) << std::endl; +} + +#endif diff --git a/libsolutil/Profiler.h b/libsolutil/Profiler.h new file mode 100644 index 000000000..e5d519bde --- /dev/null +++ b/libsolutil/Profiler.h @@ -0,0 +1,75 @@ +/* + 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 + +#pragma once + +#include +#include +#include +#include + +#ifdef PROFILE_OPTIMIZER_STEPS +#define PROFILER_PROBE(_scopeName, _variable) solidity::util::Profiler::Probe _variable(_scopeName); +#else +#define PROFILER_PROBE(_scopeName, _variable) void(0); +#endif + +namespace solidity::util +{ + +#ifdef PROFILE_OPTIMIZER_STEPS + +/// Simpler profiler class that gathers metrics during program execution and prints them out on exit. +/// +/// To gather metrics, create a Probe instance and let it live until the end of the scope. +/// The probe will register its creation and destruction time and store the results in the profiler +/// singleton. +/// +/// Use the PROFILER_PROBE macro to create probes conditionally, in a way that will not affect performance +/// unless profiling is enabled at compilation time via PROFILE_OPTIMIZER_STEPS CMake option. +/// +/// Scopes are identified by the name supplied to the probe. Using the same name multiple times +/// will result in metrics for those scopes being aggregated together as if they were the same scope. +class Profiler +{ +public: + class Probe + { + public: + Probe(std::string _scopeName); + ~Probe(); + + private: + std::string m_scopeName; + std::chrono::steady_clock::time_point m_startTime; + }; + + static Profiler& singleton(); + +private: + ~Profiler(); + + /// Summarizes gathered metric and prints a report to standard error output. + void outputPerformanceMetrics(); + + std::map m_durations; +}; + +#endif + +} diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 0233a1cf0..76f0368ab 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -72,6 +72,7 @@ #include #include +#include #include @@ -83,56 +84,10 @@ #include #include -#ifdef PROFILE_OPTIMIZER_STEPS -#include -#include -#endif - using namespace solidity; using namespace solidity::yul; -#ifdef PROFILE_OPTIMIZER_STEPS -using namespace std::chrono; -#endif using namespace std::string_literals; -namespace -{ - -#ifdef PROFILE_OPTIMIZER_STEPS -void outputPerformanceMetrics(std::map const& _metrics) -{ - std::vector> durations(_metrics.begin(), _metrics.end()); - sort( - durations.begin(), - durations.end(), - [](std::pair const& _lhs, std::pair const& _rhs) -> bool - { - return _lhs.second < _rhs.second; - } - ); - - int64_t totalDurationInMicroseconds = 0; - for (auto&& [step, durationInMicroseconds]: durations) - totalDurationInMicroseconds += durationInMicroseconds; - - std::cerr << "Performance metrics of optimizer steps" << std::endl; - std::cerr << "======================================" << std::endl; - constexpr double microsecondsInSecond = 1000000; - for (auto&& [step, durationInMicroseconds]: durations) - { - double percentage = 100.0 * static_cast(durationInMicroseconds) / static_cast(totalDurationInMicroseconds); - double sec = static_cast(durationInMicroseconds) / microsecondsInSecond; - std::cerr << fmt::format("{:>7.3f}% ({} s): {}", percentage, sec, step) << std::endl; - } - double totalDurationInSeconds = static_cast(totalDurationInMicroseconds) / microsecondsInSecond; - std::cerr << "--------------------------------------" << std::endl; - std::cerr << fmt::format("{:>7}% ({:.3f} s)", 100, totalDurationInSeconds) << std::endl; -} -#endif - -} - - void OptimiserSuite::run( Dialect const& _dialect, GasMeter const* _meter, @@ -226,10 +181,6 @@ void OptimiserSuite::run( NameSimplifier::run(suite.m_context, astRoot); VarNameCleaner::run(suite.m_context, astRoot); -#ifdef PROFILE_OPTIMIZER_STEPS - outputPerformanceMetrics(suite.m_durationPerStepInMicroseconds); -#endif - _object.setCode(std::make_shared(std::move(astRoot))); _object.analysisInfo = std::make_shared(AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object)); } @@ -504,14 +455,12 @@ void OptimiserSuite::runSequence(std::vector const& _steps, Block& { if (m_debug == Debug::PrintStep) std::cout << "Running " << step << std::endl; -#ifdef PROFILE_OPTIMIZER_STEPS - steady_clock::time_point startTime = steady_clock::now(); -#endif - allSteps().at(step)->run(m_context, _ast); -#ifdef PROFILE_OPTIMIZER_STEPS - steady_clock::time_point endTime = steady_clock::now(); - m_durationPerStepInMicroseconds[step] += duration_cast(endTime - startTime).count(); -#endif + + { + PROFILER_PROBE(step, probe); + allSteps().at(step)->run(m_context, _ast); + } + if (m_debug == Debug::PrintChanges) { // TODO should add switch to also compare variable names! diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 15a41cb9f..efa82f48c 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -91,9 +91,6 @@ class OptimiserSuite private: OptimiserStepContext& m_context; Debug m_debug; -#ifdef PROFILE_OPTIMIZER_STEPS - std::map m_durationPerStepInMicroseconds; -#endif }; } From c9d2cf2f3cee7aafe906c6a32a45a7b2b7e58edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 11 Oct 2024 16:17:28 +0200 Subject: [PATCH 0411/1340] Profiler: Add call count to metrics --- libsolutil/Profiler.cpp | 39 +++++++++++++++++++++++++-------------- libsolutil/Profiler.h | 8 +++++++- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/libsolutil/Profiler.cpp b/libsolutil/Profiler.cpp index 8cc186b92..88c2f7a99 100644 --- a/libsolutil/Profiler.cpp +++ b/libsolutil/Profiler.cpp @@ -40,8 +40,9 @@ util::Profiler::Probe::~Probe() steady_clock::time_point endTime = steady_clock::now(); int64_t durationInMicroseconds = duration_cast(endTime - m_startTime).count(); - auto [durationIt, inserted] = Profiler::singleton().m_durations.try_emplace(m_scopeName, 0); - durationIt->second += durationInMicroseconds; + auto [metricsIt, inserted] = Profiler::singleton().m_metrics.try_emplace(m_scopeName, Metrics{0, 0}); + metricsIt->second.durationInMicroseconds += durationInMicroseconds; + ++metricsIt->second.callCount; } util::Profiler::~Profiler() @@ -57,32 +58,42 @@ util::Profiler& util::Profiler::singleton() void util::Profiler::outputPerformanceMetrics() { - std::vector> durations(m_durations.begin(), m_durations.end()); + std::vector> sortedMetrics(m_metrics.begin(), m_metrics.end()); std::sort( - durations.begin(), - durations.end(), - [](std::pair const& _lhs, std::pair const& _rhs) -> bool + sortedMetrics.begin(), + sortedMetrics.end(), + [](std::pair const& _lhs, std::pair const& _rhs) -> bool { - return _lhs.second < _rhs.second; + return _lhs.second.durationInMicroseconds < _rhs.second.durationInMicroseconds; } ); int64_t totalDurationInMicroseconds = 0; - for (auto&& [scopeName, durationInMicroseconds]: durations) - totalDurationInMicroseconds += durationInMicroseconds; + size_t totalCallCount = 0; + for (auto&& [scopeName, scopeMetrics]: sortedMetrics) + { + totalDurationInMicroseconds += scopeMetrics.durationInMicroseconds; + totalCallCount += scopeMetrics.callCount; + } std::cerr << "Performance metrics for profiled scopes" << std::endl; std::cerr << "=======================================" << std::endl; constexpr double microsecondsInSecond = 1000000; - for (auto&& [scopeName, durationInMicroseconds]: durations) + for (auto&& [scopeName, scopeMetrics]: sortedMetrics) { - double percentage = 100.0 * static_cast(durationInMicroseconds) / static_cast(totalDurationInMicroseconds); - double durationInSeconds = static_cast(durationInMicroseconds) / microsecondsInSecond; - std::cerr << fmt::format("{:>7.3f}% ({} s): {}", percentage, durationInSeconds, scopeName) << std::endl; + double percentage = 100.0 * static_cast(scopeMetrics.durationInMicroseconds) / static_cast(totalDurationInMicroseconds); + double durationInSeconds = static_cast(scopeMetrics.durationInMicroseconds) / microsecondsInSecond; + std::cerr << fmt::format( + "{:>7.3f}% ({} s, {} calls): {}", + percentage, + durationInSeconds, + scopeMetrics.callCount, + scopeName + ) << std::endl; } double totalDurationInSeconds = static_cast(totalDurationInMicroseconds) / microsecondsInSecond; std::cerr << "--------------------------------------" << std::endl; - std::cerr << fmt::format("{:>7}% ({:.3f} s)", 100, totalDurationInSeconds) << std::endl; + std::cerr << fmt::format("{:>7}% ({:.3f} s, {} calls)", 100, totalDurationInSeconds, totalCallCount) << std::endl; } #endif diff --git a/libsolutil/Profiler.h b/libsolutil/Profiler.h index e5d519bde..c87dce2ad 100644 --- a/libsolutil/Profiler.h +++ b/libsolutil/Profiler.h @@ -64,10 +64,16 @@ class Profiler private: ~Profiler(); + struct Metrics + { + int64_t durationInMicroseconds; + size_t callCount; + }; + /// Summarizes gathered metric and prints a report to standard error output. void outputPerformanceMetrics(); - std::map m_durations; + std::map m_metrics; }; #endif From 3564a75a94ca97e4ae963f7c95a100fe3a2ea9f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 11 Oct 2024 16:00:35 +0200 Subject: [PATCH 0412/1340] Profiler: Adjust report formatting (markdown table, precision) --- libsolutil/Profiler.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libsolutil/Profiler.cpp b/libsolutil/Profiler.cpp index 88c2f7a99..a08636e27 100644 --- a/libsolutil/Profiler.cpp +++ b/libsolutil/Profiler.cpp @@ -76,24 +76,25 @@ void util::Profiler::outputPerformanceMetrics() totalCallCount += scopeMetrics.callCount; } - std::cerr << "Performance metrics for profiled scopes" << std::endl; - std::cerr << "=======================================" << std::endl; + std::cerr << "PERFORMANCE METRICS FOR PROFILED SCOPES\n\n"; + std::cerr << "| Time % | Time | Calls | Scope |\n"; + std::cerr << "|-------:|-----------:|--------:|--------------------------------|\n"; + constexpr double microsecondsInSecond = 1000000; for (auto&& [scopeName, scopeMetrics]: sortedMetrics) { double percentage = 100.0 * static_cast(scopeMetrics.durationInMicroseconds) / static_cast(totalDurationInMicroseconds); double durationInSeconds = static_cast(scopeMetrics.durationInMicroseconds) / microsecondsInSecond; std::cerr << fmt::format( - "{:>7.3f}% ({} s, {} calls): {}", + "| {:5.1f}% | {:8.3f} s | {:7} | {:30} |\n", percentage, durationInSeconds, scopeMetrics.callCount, scopeName - ) << std::endl; + ); } double totalDurationInSeconds = static_cast(totalDurationInMicroseconds) / microsecondsInSecond; - std::cerr << "--------------------------------------" << std::endl; - std::cerr << fmt::format("{:>7}% ({:.3f} s, {} calls)", 100, totalDurationInSeconds, totalCallCount) << std::endl; + std::cerr << fmt::format("| {:5.1f}% | {:8.3f} s | {:7} | {:30} |\n", 100.0, totalDurationInSeconds, totalCallCount, "**TOTAL**"); } #endif From 89444f5290d216ff0aa9427d68113ff2d440d344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 15 Oct 2024 17:46:48 +0200 Subject: [PATCH 0413/1340] Profiler: Refactor to properly use std::chrono types --- libsolutil/Profiler.cpp | 14 ++++++-------- libsolutil/Profiler.h | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/libsolutil/Profiler.cpp b/libsolutil/Profiler.cpp index a08636e27..179296367 100644 --- a/libsolutil/Profiler.cpp +++ b/libsolutil/Profiler.cpp @@ -38,10 +38,9 @@ util::Profiler::Probe::Probe(std::string _scopeName): util::Profiler::Probe::~Probe() { steady_clock::time_point endTime = steady_clock::now(); - int64_t durationInMicroseconds = duration_cast(endTime - m_startTime).count(); - auto [metricsIt, inserted] = Profiler::singleton().m_metrics.try_emplace(m_scopeName, Metrics{0, 0}); - metricsIt->second.durationInMicroseconds += durationInMicroseconds; + auto [metricsIt, inserted] = Profiler::singleton().m_metrics.try_emplace(m_scopeName, Metrics{0us, 0}); + metricsIt->second.durationInMicroseconds += duration_cast(endTime - m_startTime); ++metricsIt->second.callCount; } @@ -68,7 +67,7 @@ void util::Profiler::outputPerformanceMetrics() } ); - int64_t totalDurationInMicroseconds = 0; + std::chrono::microseconds totalDurationInMicroseconds = 0us; size_t totalCallCount = 0; for (auto&& [scopeName, scopeMetrics]: sortedMetrics) { @@ -80,11 +79,11 @@ void util::Profiler::outputPerformanceMetrics() std::cerr << "| Time % | Time | Calls | Scope |\n"; std::cerr << "|-------:|-----------:|--------:|--------------------------------|\n"; - constexpr double microsecondsInSecond = 1000000; + double totalDurationInSeconds = duration_cast>(totalDurationInMicroseconds).count(); for (auto&& [scopeName, scopeMetrics]: sortedMetrics) { - double percentage = 100.0 * static_cast(scopeMetrics.durationInMicroseconds) / static_cast(totalDurationInMicroseconds); - double durationInSeconds = static_cast(scopeMetrics.durationInMicroseconds) / microsecondsInSecond; + double durationInSeconds = duration_cast>(scopeMetrics.durationInMicroseconds).count(); + double percentage = 100.0 * durationInSeconds / totalDurationInSeconds; std::cerr << fmt::format( "| {:5.1f}% | {:8.3f} s | {:7} | {:30} |\n", percentage, @@ -93,7 +92,6 @@ void util::Profiler::outputPerformanceMetrics() scopeName ); } - double totalDurationInSeconds = static_cast(totalDurationInMicroseconds) / microsecondsInSecond; std::cerr << fmt::format("| {:5.1f}% | {:8.3f} s | {:7} | {:30} |\n", 100.0, totalDurationInSeconds, totalCallCount, "**TOTAL**"); } diff --git a/libsolutil/Profiler.h b/libsolutil/Profiler.h index c87dce2ad..79c516d01 100644 --- a/libsolutil/Profiler.h +++ b/libsolutil/Profiler.h @@ -66,7 +66,7 @@ class Profiler struct Metrics { - int64_t durationInMicroseconds; + std::chrono::microseconds durationInMicroseconds; size_t callCount; }; From 9188438b3c846d2eb7302b0a360ae68624b6dcb7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 14 Oct 2024 09:41:22 +0200 Subject: [PATCH 0414/1340] CompilerStack: Changes ir and irOptimized to be optional json / string objects. --- Changelog.md | 1 + libsolidity/interface/CompilerStack.cpp | 48 ++++++---- libsolidity/interface/CompilerStack.h | 14 +-- libsolidity/interface/StandardCompiler.cpp | 10 +- solc/CommandLineInterface.cpp | 27 +++--- .../ast_ir_undeployable_contract/args | 2 +- .../ast_ir_undeployable_contract/output | 36 +++++++ .../input.json | 6 +- .../output.json | 94 ++++++++++++++++++- test/libsolidity/MemoryGuardTest.cpp | 4 +- 10 files changed, 196 insertions(+), 46 deletions(-) diff --git a/Changelog.md b/Changelog.md index 13af14b75..0ebefa659 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: Bugfixes: +* General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. ### 0.8.28 (2024-10-09) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 007b6187c..e3927d4df 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -969,52 +969,61 @@ std::string const CompilerStack::filesystemFriendlyName(std::string const& _cont return matchContract.contract->name(); } -std::string const& CompilerStack::yulIR(std::string const& _contractName) const +std::optional const& CompilerStack::yulIR(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); return contract(_contractName).yulIR; } -Json CompilerStack::yulIRAst(std::string const& _contractName) const +std::optional CompilerStack::yulIRAst(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to // keep it around when compiling a large project containing many contracts. - auto const& currentContract = contract(_contractName); + Contract const& currentContract = contract(_contractName); yulAssert(currentContract.contract); - return currentContract.contract->canBeDeployed() ? loadGeneratedIR(currentContract.yulIR).astJson() : Json{}; + yulAssert(currentContract.yulIR.has_value() == currentContract.contract->canBeDeployed()); + if (!currentContract.yulIR) + return std::nullopt; + return loadGeneratedIR(*currentContract.yulIR).astJson(); } -Json CompilerStack::yulCFGJson(std::string const& _contractName) const +std::optional CompilerStack::yulCFGJson(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to // keep it around when compiling a large project containing many contracts. - auto const& currentContract = contract(_contractName); + Contract const& currentContract = contract(_contractName); yulAssert(currentContract.contract); - return currentContract.contract->canBeDeployed() ? loadGeneratedIR(currentContract.yulIR).cfgJson() : Json{}; + yulAssert(currentContract.yulIR.has_value() == currentContract.contract->canBeDeployed()); + if (!currentContract.yulIR) + return std::nullopt; + return loadGeneratedIR(*currentContract.yulIR).cfgJson(); } -std::string const& CompilerStack::yulIROptimized(std::string const& _contractName) const +std::optional const& CompilerStack::yulIROptimized(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); return contract(_contractName).yulIROptimized; } -Json CompilerStack::yulIROptimizedAst(std::string const& _contractName) const +std::optional CompilerStack::yulIROptimizedAst(std::string const& _contractName) const { solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful."); solUnimplementedAssert(!isExperimentalSolidity()); // NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to // keep it around when compiling a large project containing many contracts. - auto const& currentContract = contract(_contractName); + Contract const& currentContract = contract(_contractName); yulAssert(currentContract.contract); - return currentContract.contract->canBeDeployed() ? loadGeneratedIR(currentContract.yulIROptimized).astJson() : Json{}; + yulAssert(currentContract.yulIROptimized.has_value() == currentContract.contract->canBeDeployed()); + if (!currentContract.yulIROptimized) + return std::nullopt; + return loadGeneratedIR(*currentContract.yulIROptimized).astJson(); } evmasm::LinkerObject const& CompilerStack::object(std::string const& _contractName) const @@ -1513,8 +1522,11 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti solAssert(m_stackState >= AnalysisSuccessful, ""); Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName()); - if (!compiledContract.yulIR.empty()) + if (compiledContract.yulIR) + { + solAssert(!compiledContract.yulIR->empty()); return; + } if (!*_contract.sourceUnit().annotation().useABICoderV2) m_errorReporter.warning( @@ -1533,7 +1545,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti std::map otherYulSources; for (auto const& pair: m_contracts) - otherYulSources.emplace(pair.second.contract, pair.second.yulIR); + otherYulSources.emplace(pair.second.contract, pair.second.yulIR ? *pair.second.yulIR : std::string_view{}); if (m_experimentalAnalysis) { @@ -1570,7 +1582,8 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti ); } - YulStack stack = loadGeneratedIR(compiledContract.yulIR); + yulAssert(compiledContract.yulIR); + YulStack stack = loadGeneratedIR(*compiledContract.yulIR); if (!_unoptimizedOnly) { stack.optimize(); @@ -1586,14 +1599,13 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) return; Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName()); - solAssert(!compiledContract.yulIROptimized.empty(), ""); + solAssert(compiledContract.yulIROptimized); + solAssert(!compiledContract.yulIROptimized->empty()); if (!compiledContract.object.bytecode.empty()) return; // Re-parse the Yul IR in EVM dialect - YulStack stack = loadGeneratedIR(compiledContract.yulIROptimized); - - //cout << yul::AsmPrinter{}(*stack.parserResult()->code) << endl; + YulStack stack = loadGeneratedIR(*compiledContract.yulIROptimized); std::string deployedName = IRNames::deployedObject(_contract); solAssert(!deployedName.empty(), ""); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 8ce2c5d62..009103a49 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -321,18 +321,18 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac virtual std::string const filesystemFriendlyName(std::string const& _contractName) const override; /// @returns the IR representation of a contract. - std::string const& yulIR(std::string const& _contractName) const; + std::optional const& yulIR(std::string const& _contractName) const; /// @returns the IR representation of a contract AST in format. - Json yulIRAst(std::string const& _contractName) const; + std::optional yulIRAst(std::string const& _contractName) const; /// @returns the optimized IR representation of a contract. - std::string const& yulIROptimized(std::string const& _contractName) const; + std::optional const& yulIROptimized(std::string const& _contractName) const; /// @returns the optimized IR representation of a contract AST in JSON format. - Json yulIROptimizedAst(std::string const& _contractName) const; + std::optional yulIROptimizedAst(std::string const& _contractName) const; - Json yulCFGJson(std::string const& _contractName) const; + std::optional yulCFGJson(std::string const& _contractName) const; /// @returns the assembled object for a contract. virtual evmasm::LinkerObject const& object(std::string const& _contractName) const override; @@ -445,8 +445,8 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac std::optional runtimeGeneratedYulUtilityCode; ///< Extra Yul utility code that was used when compiling the deployed assembly evmasm::LinkerObject object; ///< Deployment object (includes the runtime sub-object). evmasm::LinkerObject runtimeObject; ///< Runtime object. - std::string yulIR; ///< Yul IR code straight from the code generator. - std::string yulIROptimized; ///< Reparsed and possibly optimized Yul IR code. + std::optional yulIR; ///< Yul IR code straight from the code generator. + std::optional yulIROptimized; ///< Reparsed and possibly optimized Yul IR code. util::LazyInit metadata; ///< The metadata json that will be hashed into the chain. util::LazyInit abi; util::LazyInit storageLayout; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index d8ce4f2d0..c5248e42e 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1482,15 +1482,15 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu // IR if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "ir", wildcardMatchesExperimental)) - contractData["ir"] = compilerStack.yulIR(contractName); + contractData["ir"] = compilerStack.yulIR(contractName).value_or(""); if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "irAst", wildcardMatchesExperimental)) - contractData["irAst"] = compilerStack.yulIRAst(contractName); + contractData["irAst"] = compilerStack.yulIRAst(contractName).value_or(Json{}); if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "irOptimized", wildcardMatchesExperimental)) - contractData["irOptimized"] = compilerStack.yulIROptimized(contractName); + contractData["irOptimized"] = compilerStack.yulIROptimized(contractName).value_or(""); if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "irOptimizedAst", wildcardMatchesExperimental)) - contractData["irOptimizedAst"] = compilerStack.yulIROptimizedAst(contractName); + contractData["irOptimizedAst"] = compilerStack.yulIROptimizedAst(contractName).value_or(Json{}); if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "yulCFGJson", wildcardMatchesExperimental)) - contractData["yulCFGJson"] = compilerStack.yulCFGJson(contractName); + contractData["yulCFGJson"] = compilerStack.yulCFGJson(contractName).value_or(Json{}); // EVM Json evmData; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index b791de3ef..33aa08b46 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -257,12 +257,13 @@ void CommandLineInterface::handleIR(std::string const& _contractName) if (!m_options.compiler.outputs.ir) return; + std::optional const& ir = m_compiler->yulIR(_contractName); if (!m_options.output.dir.empty()) - createFile(m_compiler->filesystemFriendlyName(_contractName) + ".yul", m_compiler->yulIR(_contractName)); + createFile(m_compiler->filesystemFriendlyName(_contractName) + ".yul", ir.value_or("")); else { - sout() << "IR:" << std::endl; - sout() << m_compiler->yulIR(_contractName) << std::endl; + sout() << "IR:\n"; + sout() << ir.value_or("") << std::endl; } } @@ -273,11 +274,12 @@ void CommandLineInterface::handleIRAst(std::string const& _contractName) if (!m_options.compiler.outputs.irAstJson) return; + std::optional const& yulIRAst = m_compiler->yulIRAst(_contractName); if (!m_options.output.dir.empty()) createFile( m_compiler->filesystemFriendlyName(_contractName) + "_yul_ast.json", util::jsonPrint( - m_compiler->yulIRAst(_contractName), + yulIRAst.value_or(Json{}), m_options.formatting.json ) ); @@ -285,7 +287,7 @@ void CommandLineInterface::handleIRAst(std::string const& _contractName) { sout() << "IR AST:" << std::endl; sout() << util::jsonPrint( - m_compiler->yulIRAst(_contractName), + yulIRAst.value_or(Json{}), m_options.formatting.json ) << std::endl; } @@ -298,18 +300,19 @@ void CommandLineInterface::handleYulCFGExport(std::string const& _contractName) if (!m_options.compiler.outputs.yulCFGJson) return; + std::optional const& yulCFGJson = m_compiler->yulCFGJson(_contractName); if (!m_options.output.dir.empty()) createFile( m_compiler->filesystemFriendlyName(_contractName) + "_yul_cfg.json", util::jsonPrint( - m_compiler->yulCFGJson(_contractName), + yulCFGJson.value_or(Json{}), m_options.formatting.json ) ); else { sout() << util::jsonPrint( - m_compiler->yulCFGJson(_contractName), + yulCFGJson.value_or(Json{}), m_options.formatting.json ) << std::endl; } @@ -322,15 +325,16 @@ void CommandLineInterface::handleIROptimized(std::string const& _contractName) if (!m_options.compiler.outputs.irOptimized) return; + std::optional const& irOptimized = m_compiler->yulIROptimized(_contractName); if (!m_options.output.dir.empty()) createFile( m_compiler->filesystemFriendlyName(_contractName) + "_opt.yul", - m_compiler->yulIROptimized(_contractName) + irOptimized.value_or("") ); else { sout() << "Optimized IR:" << std::endl; - sout() << m_compiler->yulIROptimized(_contractName) << std::endl; + sout() << irOptimized.value_or("") << std::endl; } } @@ -341,11 +345,12 @@ void CommandLineInterface::handleIROptimizedAst(std::string const& _contractName if (!m_options.compiler.outputs.irOptimizedAstJson) return; + std::optional const& yulIROptimizedAst = m_compiler->yulIROptimizedAst(_contractName); if (!m_options.output.dir.empty()) createFile( m_compiler->filesystemFriendlyName(_contractName) + "_opt_yul_ast.json", util::jsonPrint( - m_compiler->yulIROptimizedAst(_contractName), + yulIROptimizedAst.value_or(Json{}), m_options.formatting.json ) ); @@ -353,7 +358,7 @@ void CommandLineInterface::handleIROptimizedAst(std::string const& _contractName { sout() << "Optimized IR AST:" << std::endl; sout() << util::jsonPrint( - m_compiler->yulIROptimizedAst(_contractName), + yulIROptimizedAst.value_or(Json{}), m_options.formatting.json ) << std::endl; } diff --git a/test/cmdlineTests/ast_ir_undeployable_contract/args b/test/cmdlineTests/ast_ir_undeployable_contract/args index d254bff83..74c8e867f 100644 --- a/test/cmdlineTests/ast_ir_undeployable_contract/args +++ b/test/cmdlineTests/ast_ir_undeployable_contract/args @@ -1 +1 @@ ---ir-ast-json --ir-optimized-ast-json --optimize --pretty-json --json-indent 4 +--bin --bin-runtime --opcodes --asm --ir --ir-ast-json --ir-optimized --ir-optimized-ast-json --gas --asm-json --abi --hashes --optimize --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ast_ir_undeployable_contract/output b/test/cmdlineTests/ast_ir_undeployable_contract/output index b64e82bd0..d6089273b 100644 --- a/test/cmdlineTests/ast_ir_undeployable_contract/output +++ b/test/cmdlineTests/ast_ir_undeployable_contract/output @@ -1,8 +1,44 @@ + +======= ast_ir_undeployable_contract/input.sol:C ======= +EVM assembly: +null +Gas estimation: +Opcodes: + +Binary: + +Binary of the runtime part: + +IR: + IR AST: null +Optimized IR: + Optimized IR AST: null +Function signatures: +Contract JSON ABI +[] + +======= ast_ir_undeployable_contract/input.sol:I ======= +EVM assembly: +null +Gas estimation: +Opcodes: + +Binary: + +Binary of the runtime part: + +IR: + IR AST: null +Optimized IR: + Optimized IR AST: null +Function signatures: +Contract JSON ABI +[] diff --git a/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/input.json b/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/input.json index 0b40ad072..cc87ecd49 100644 --- a/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/input.json +++ b/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/input.json @@ -4,6 +4,10 @@ "C": {"urls": ["standard_ir_ast_undeployable_contract_requested/in.sol"]} }, "settings": { - "outputSelection": {"*": {"*": ["irAst", "irOptimizedAst"]}} + "outputSelection": { + "*": { + "*": ["*", "ir", "irAst", "irOptimized", "irOptimizedAst"] + } + } } } diff --git a/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/output.json b/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/output.json index dab55ebd1..3869f7c65 100644 --- a/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/output.json +++ b/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/output.json @@ -2,12 +2,102 @@ "contracts": { "C": { "C": { + "abi": [], + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "evm": { + "assembly": "", + "bytecode": { + "functionDebugData": {}, + "generatedSources": [], + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + }, + "deployedBytecode": { + "functionDebugData": {}, + "generatedSources": [], + "immutableReferences": {}, + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + }, + "gasEstimates": null, + "legacyAssembly": null, + "methodIdentifiers": {} + }, + "ir": "", "irAst": null, - "irOptimizedAst": null + "irOptimized": "", + "irOptimizedAst": null, + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "transientStorageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } }, "I": { + "abi": [], + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "evm": { + "assembly": "", + "bytecode": { + "functionDebugData": {}, + "generatedSources": [], + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + }, + "deployedBytecode": { + "functionDebugData": {}, + "generatedSources": [], + "immutableReferences": {}, + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + }, + "gasEstimates": null, + "legacyAssembly": null, + "methodIdentifiers": {} + }, + "ir": "", "irAst": null, - "irOptimizedAst": null + "irOptimized": "", + "irOptimizedAst": null, + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"I\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "transientStorageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } } } }, diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index 08a2814c9..a98c7a323 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -60,8 +60,10 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con for (std::string contractName: compiler().contractNames()) { ErrorList errors; + std::optional const& ir = compiler().yulIR(contractName); + solAssert(ir); auto [object, analysisInfo] = yul::test::parse( - compiler().yulIR(contractName), + *ir, EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion(), CommonOptions::get().eofVersion()), errors ); From 7972c5118aa8bee603c3e2dbf3413f78689a12f9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 16 Oct 2024 09:04:38 +0200 Subject: [PATCH 0415/1340] Rename undeployable contract tests to reflect they request all outputs --- .../in.sol | 0 .../input.json | 2 +- .../output.json | 0 .../args | 0 .../input.sol | 0 .../output | 4 ++-- 6 files changed, 3 insertions(+), 3 deletions(-) rename test/cmdlineTests/{standard_ir_ast_undeployable_contract_requested => standard_undeployable_contract_all_outputs}/in.sol (100%) rename test/cmdlineTests/{standard_ir_ast_undeployable_contract_requested => standard_undeployable_contract_all_outputs}/input.json (69%) rename test/cmdlineTests/{standard_ir_ast_undeployable_contract_requested => standard_undeployable_contract_all_outputs}/output.json (100%) rename test/cmdlineTests/{ast_ir_undeployable_contract => undeployable_contract_empty_outputs}/args (100%) rename test/cmdlineTests/{ast_ir_undeployable_contract => undeployable_contract_empty_outputs}/input.sol (100%) rename test/cmdlineTests/{ast_ir_undeployable_contract => undeployable_contract_empty_outputs}/output (73%) diff --git a/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/in.sol b/test/cmdlineTests/standard_undeployable_contract_all_outputs/in.sol similarity index 100% rename from test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/in.sol rename to test/cmdlineTests/standard_undeployable_contract_all_outputs/in.sol diff --git a/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/input.json b/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json similarity index 69% rename from test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/input.json rename to test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json index cc87ecd49..4d2aea1f1 100644 --- a/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/input.json +++ b/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_ir_ast_undeployable_contract_requested/in.sol"]} + "C": {"urls": ["standard_undeployable_contract_all_outputs/in.sol"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/output.json b/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json similarity index 100% rename from test/cmdlineTests/standard_ir_ast_undeployable_contract_requested/output.json rename to test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json diff --git a/test/cmdlineTests/ast_ir_undeployable_contract/args b/test/cmdlineTests/undeployable_contract_empty_outputs/args similarity index 100% rename from test/cmdlineTests/ast_ir_undeployable_contract/args rename to test/cmdlineTests/undeployable_contract_empty_outputs/args diff --git a/test/cmdlineTests/ast_ir_undeployable_contract/input.sol b/test/cmdlineTests/undeployable_contract_empty_outputs/input.sol similarity index 100% rename from test/cmdlineTests/ast_ir_undeployable_contract/input.sol rename to test/cmdlineTests/undeployable_contract_empty_outputs/input.sol diff --git a/test/cmdlineTests/ast_ir_undeployable_contract/output b/test/cmdlineTests/undeployable_contract_empty_outputs/output similarity index 73% rename from test/cmdlineTests/ast_ir_undeployable_contract/output rename to test/cmdlineTests/undeployable_contract_empty_outputs/output index d6089273b..123edc75d 100644 --- a/test/cmdlineTests/ast_ir_undeployable_contract/output +++ b/test/cmdlineTests/undeployable_contract_empty_outputs/output @@ -1,5 +1,5 @@ -======= ast_ir_undeployable_contract/input.sol:C ======= +======= undeployable_contract_empty_outputs/input.sol:C ======= EVM assembly: null Gas estimation: @@ -21,7 +21,7 @@ Function signatures: Contract JSON ABI [] -======= ast_ir_undeployable_contract/input.sol:I ======= +======= undeployable_contract_empty_outputs/input.sol:I ======= EVM assembly: null Gas estimation: From 740fe29f453efaf60e1b8fb606e3c3833c065ca4 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 14 Oct 2024 15:04:42 +0200 Subject: [PATCH 0416/1340] Add missing Yul CFG output header to CLI --- scripts/common_cmdline.sh | 1 + solc/CommandLineInterface.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/scripts/common_cmdline.sh b/scripts/common_cmdline.sh index 819a4b1c8..51d30ae5d 100644 --- a/scripts/common_cmdline.sh +++ b/scripts/common_cmdline.sh @@ -152,6 +152,7 @@ function stripCLIDecorations -e '/^IR:$/d' \ -e '/^Optimized IR:$/d' \ -e '/^EVM assembly:$/d' \ + -e '/^Yul Control Flow Graph:$/d' \ -e '/^JSON AST (compact format):$/d' \ -e '/^Function signatures:$/d' \ -e '/^Contract Storage Layout:$/d' \ diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 33aa08b46..4816ee531 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -148,6 +148,7 @@ static bool needsHumanTargetedStdout(CommandLineOptions const& _options) _options.compiler.outputs.abi || _options.compiler.outputs.asm_ || _options.compiler.outputs.asmJson || + _options.compiler.outputs.yulCFGJson || _options.compiler.outputs.binary || _options.compiler.outputs.binaryRuntime || _options.compiler.outputs.metadata || @@ -311,6 +312,7 @@ void CommandLineInterface::handleYulCFGExport(std::string const& _contractName) ); else { + sout() << "Yul Control Flow Graph:" << std::endl; sout() << util::jsonPrint( yulCFGJson.value_or(Json{}), m_options.formatting.json From 78ecc7c851e440305a72e476c485dab49f2f7ef8 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 14 Oct 2024 16:29:38 +0200 Subject: [PATCH 0417/1340] Remove unecessary fields from Yul CFG Json export --- libyul/YulControlFlowGraphExporter.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libyul/YulControlFlowGraphExporter.cpp b/libyul/YulControlFlowGraphExporter.cpp index 3f347fcf4..52593fab7 100644 --- a/libyul/YulControlFlowGraphExporter.cpp +++ b/libyul/YulControlFlowGraphExporter.cpp @@ -96,7 +96,6 @@ Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockI Json exitBlockJson = Json::object(); std::visit(util::GenericVisitor{ [&](SSACFG::BasicBlock::MainExit const&) { - exitBlockJson["targets"] = { "Block" + std::to_string(_blockId.value) }; exitBlockJson["type"] = "MainExit"; }, [&](SSACFG::BasicBlock::Jump const& _jump) @@ -115,12 +114,10 @@ Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockI _addChild(_conditionalJump.nonZero); }, [&](SSACFG::BasicBlock::FunctionReturn const& _return) { - exitBlockJson["instructions"] = toJson(_cfg, _return.returnValues); - exitBlockJson["targets"] = { "Block" + std::to_string(_blockId.value) }; + exitBlockJson["returnValues"] = toJson(_cfg, _return.returnValues); exitBlockJson["type"] = "FunctionReturn"; }, [&](SSACFG::BasicBlock::Terminated const&) { - exitBlockJson["targets"] = { "Block" + std::to_string(_blockId.value) }; exitBlockJson["type"] = "Terminated"; }, [&](SSACFG::BasicBlock::JumpTable const&) { From bddf8013140ce534eea9b9083c8ad3b38301571a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:53:19 +0200 Subject: [PATCH 0418/1340] Yul dialect: Remove fixedFunctionNames --- libyul/Dialect.h | 2 -- libyul/optimiser/Suite.cpp | 1 - 2 files changed, 3 deletions(-) diff --git a/libyul/Dialect.h b/libyul/Dialect.h index 3589e953f..3b0d73597 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -78,8 +78,6 @@ struct Dialect Literal zeroLiteral() const; - virtual std::set fixedFunctionNames() const { return {}; } - Dialect() = default; virtual ~Dialect() = default; }; diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 76f0368ab..21356bffa 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -106,7 +106,6 @@ void OptimiserSuite::run( evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); std::set reservedIdentifiers = _externallyUsedIdentifiers; - reservedIdentifiers += _dialect.fixedFunctionNames(); auto astRoot = std::get(Disambiguator( _dialect, From c38580b8e56949abce4a2b3098db6d27c526dec9 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 14 Oct 2024 17:56:14 +0200 Subject: [PATCH 0419/1340] Add Yul CFG export tests --- .../standard_yul_cfg_json_export/in.sol | 19 + .../standard_yul_cfg_json_export/input.json | 13 + .../standard_yul_cfg_json_export/output.json | 3972 +++++++++++++++++ .../strict_asm_yul_cfg_json_export/args | 1 + .../strict_asm_yul_cfg_json_export/input.yul | 36 + .../strict_asm_yul_cfg_json_export/output | 380 ++ test/cmdlineTests/yul_cfg_json_export/args | 1 + .../yul_cfg_json_export/input.sol | 19 + test/cmdlineTests/yul_cfg_json_export/output | 3964 ++++++++++++++++ 9 files changed, 8405 insertions(+) create mode 100644 test/cmdlineTests/standard_yul_cfg_json_export/in.sol create mode 100644 test/cmdlineTests/standard_yul_cfg_json_export/input.json create mode 100644 test/cmdlineTests/standard_yul_cfg_json_export/output.json create mode 100644 test/cmdlineTests/strict_asm_yul_cfg_json_export/args create mode 100644 test/cmdlineTests/strict_asm_yul_cfg_json_export/input.yul create mode 100644 test/cmdlineTests/strict_asm_yul_cfg_json_export/output create mode 100644 test/cmdlineTests/yul_cfg_json_export/args create mode 100644 test/cmdlineTests/yul_cfg_json_export/input.sol create mode 100644 test/cmdlineTests/yul_cfg_json_export/output diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/in.sol b/test/cmdlineTests/standard_yul_cfg_json_export/in.sol new file mode 100644 index 000000000..85691014f --- /dev/null +++ b/test/cmdlineTests/standard_yul_cfg_json_export/in.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +interface I { + function f() external pure returns (uint); +} + +contract C is I { + function f() public pure override returns (uint) { + return 42; + } +} + +contract D { + function f() public returns (uint) { + C c = new C(); + return c.f(); + } +} diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/input.json b/test/cmdlineTests/standard_yul_cfg_json_export/input.json new file mode 100644 index 000000000..aee56abf8 --- /dev/null +++ b/test/cmdlineTests/standard_yul_cfg_json_export/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["standard_yul_cfg_json_export/in.sol"]} + }, + "settings": { + "optimizer": { + "enabled": true + }, + "viaIR": true, + "outputSelection": {"*": {"*": ["yulCFGJson"]}} + } +} diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json new file mode 100644 index 000000000..d09a6c1a5 --- /dev/null +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -0,0 +1,3972 @@ +{ + "contracts": { + "C": { + "C": { + "yulCFGJson": { + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "constructor_C_19", + "out": [] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v3" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v3" + ], + "op": "codecopy", + "out": [] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v3" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "functions": { + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "constructor_C_19": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "constructor_I_7", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "constructor_I_7": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + } + } + }, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "cond": "v9", + "targets": [ + "Block5", + "Block4" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7" + ], + "op": "shift_right_224_unsigned", + "out": [ + "v8" + ] + }, + { + "in": [ + "0x26121ff0", + "v8" + ], + "op": "eq", + "out": [ + "v9" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block3" + ], + "type": "Jump" + }, + "id": "Block5", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block4", + "instructions": [ + { + "in": [], + "op": "external_fun_f_18", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block3", + "instructions": [] + } + ], + "functions": { + "abi_decode_tuple_": { + "arguments": [ + "headStart", + "dataEnd" + ], + "blocks": [ + { + "exit": { + "cond": "v4", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "v1" + ], + "op": "sub", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x00", + "v3" + ], + "op": "slt", + "out": [ + "v4" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_encode_t_uint256_to_t_uint256_fromStack": { + "arguments": [ + "value", + "pos" + ], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_uint256", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2", + "v1" + ], + "op": "mstore", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { + "arguments": [ + "headStart", + "value0" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x20", + "v0" + ], + "op": "add", + "out": [ + "v4" + ] + }, + { + "in": [ + "0x00", + "v0" + ], + "op": "add", + "out": [ + "v5" + ] + }, + { + "in": [ + "v5", + "v1" + ], + "op": "abi_encode_t_uint256_to_t_uint256_fromStack", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "tail" + ], + "type": "Function" + }, + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "cleanup_t_rational_42_by_1": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "cleanup_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "convert_t_rational_42_by_1_to_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_rational_42_by_1", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2" + ], + "op": "identity", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3" + ], + "op": "cleanup_t_uint256", + "out": [ + "v4" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "converted" + ], + "type": "Function" + }, + "external_fun_f_18": { + "arguments": [], + "blocks": [ + { + "exit": { + "cond": "v0", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v0" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "calldatasize", + "out": [ + "v1" + ] + }, + { + "in": [ + "v1", + "0x04" + ], + "op": "abi_decode_tuple_", + "out": [] + }, + { + "in": [], + "op": "fun_f_18", + "out": [ + "v3" + ] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v4" + ] + }, + { + "in": [ + "v3", + "v4" + ], + "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5" + ], + "op": "sub", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v4" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "fun_f_18": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "zero_value_for_split_t_uint256", + "out": [ + "v1" + ] + }, + { + "in": [ + "0x2a" + ], + "op": "convert_t_rational_42_by_1_to_t_uint256", + "out": [ + "v3" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "var__13" + ], + "type": "Function" + }, + "identity": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + }, + "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "shift_right_224_unsigned": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "0xe0" + ], + "op": "shr", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "newValue" + ], + "type": "Function" + }, + "zero_value_for_split_t_uint256": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "0x00" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + } + } + }, + "subObjects": {}, + "type": "subObject" + }, + "type": "Object" + } + }, + "D": { + "yulCFGJson": { + "D_38": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "constructor_D_38", + "out": [] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v3" + ] + }, + { + "builtinArgs": [ + "D_38_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "D_38_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v3" + ], + "op": "codecopy", + "out": [] + }, + { + "builtinArgs": [ + "D_38_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v3" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "functions": { + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "constructor_D_38": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + } + } + }, + "subObjects": { + "D_38_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "cond": "v9", + "targets": [ + "Block5", + "Block4" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7" + ], + "op": "shift_right_224_unsigned", + "out": [ + "v8" + ] + }, + { + "in": [ + "0x26121ff0", + "v8" + ], + "op": "eq", + "out": [ + "v9" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block3" + ], + "type": "Jump" + }, + "id": "Block5", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block4", + "instructions": [ + { + "in": [], + "op": "external_fun_f_37", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block3", + "instructions": [] + } + ], + "functions": { + "abi_decode_t_uint256_fromMemory": { + "arguments": [ + "offset", + "end" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "mload", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3" + ], + "op": "validator_revert_t_uint256", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "value" + ], + "type": "Function" + }, + "abi_decode_tuple_": { + "arguments": [ + "headStart", + "dataEnd" + ], + "blocks": [ + { + "exit": { + "cond": "v4", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "v1" + ], + "op": "sub", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x00", + "v3" + ], + "op": "slt", + "out": [ + "v4" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_decode_tuple_t_uint256_fromMemory": { + "arguments": [ + "headStart", + "dataEnd" + ], + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "v1" + ], + "op": "sub", + "out": [ + "v4" + ] + }, + { + "in": [ + "0x20", + "v4" + ], + "op": "slt", + "out": [ + "v5" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [ + "v12" + ], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "v0" + ], + "op": "add", + "out": [ + "v11" + ] + }, + { + "in": [ + "v1", + "v11" + ], + "op": "abi_decode_t_uint256_fromMemory", + "out": [ + "v12" + ] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "value0" + ], + "type": "Function" + }, + "abi_encode_t_uint256_to_t_uint256_fromStack": { + "arguments": [ + "value", + "pos" + ], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_uint256", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2", + "v1" + ], + "op": "mstore", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_encode_tuple__to__fromStack": { + "arguments": [ + "headStart" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "v0" + ], + "op": "add", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "tail" + ], + "type": "Function" + }, + "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { + "arguments": [ + "headStart", + "value0" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x20", + "v0" + ], + "op": "add", + "out": [ + "v4" + ] + }, + { + "in": [ + "0x00", + "v0" + ], + "op": "add", + "out": [ + "v5" + ] + }, + { + "in": [ + "v5", + "v1" + ], + "op": "abi_encode_t_uint256_to_t_uint256_fromStack", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "tail" + ], + "type": "Function" + }, + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "cleanup_t_uint160": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0xffffffffffffffffffffffffffffffffffffffff", + "v0" + ], + "op": "and", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "cleanup_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "convert_t_contract$_C_$19_to_t_address": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "convert_t_uint160_to_t_address", + "out": [ + "v2" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "converted" + ], + "type": "Function" + }, + "convert_t_uint160_to_t_address": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "convert_t_uint160_to_t_uint160", + "out": [ + "v2" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "converted" + ], + "type": "Function" + }, + "convert_t_uint160_to_t_uint160": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_uint160", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2" + ], + "op": "identity", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3" + ], + "op": "cleanup_t_uint160", + "out": [ + "v4" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "converted" + ], + "type": "Function" + }, + "external_fun_f_37": { + "arguments": [], + "blocks": [ + { + "exit": { + "cond": "v0", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v0" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "calldatasize", + "out": [ + "v1" + ] + }, + { + "in": [ + "v1", + "0x04" + ], + "op": "abi_decode_tuple_", + "out": [] + }, + { + "in": [], + "op": "fun_f_37", + "out": [ + "v3" + ] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v4" + ] + }, + { + "in": [ + "v3", + "v4" + ], + "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5" + ], + "op": "sub", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v4" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "finalize_allocation": { + "arguments": [ + "memPtr", + "size" + ], + "blocks": [ + { + "exit": { + "cond": "v7", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v1" + ], + "op": "round_up_to_mul_of_32", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2", + "v0" + ], + "op": "add", + "out": [ + "v3" + ] + }, + { + "in": [ + "v0", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v3" + ], + "op": "gt", + "out": [ + "v6" + ] + }, + { + "in": [ + "v4", + "v6" + ], + "op": "or", + "out": [ + "v7" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "v3", + "0x40" + ], + "op": "mstore", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "panic_error_0x41", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "fun_f_37": { + "arguments": [], + "blocks": [ + { + "exit": { + "cond": "v8", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "zero_value_for_split_t_uint256", + "out": [ + "v1" + ] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v2" + ] + }, + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "datasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3", + "v2" + ], + "op": "add", + "out": [ + "v4" + ] + }, + { + "in": [ + "v2", + "v4" + ], + "op": "lt", + "out": [ + "v5" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v4" + ], + "op": "gt", + "out": [ + "v7" + ] + }, + { + "in": [ + "v5", + "v7" + ], + "op": "or", + "out": [ + "v8" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v19", + "targets": [ + "Block5", + "Block4" + ], + "type": "ConditionalJump" + }, + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "datasize", + "out": [ + "v9" + ] + }, + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v10" + ] + }, + { + "in": [ + "v9", + "v10", + "v2" + ], + "op": "datacopy", + "out": [] + }, + { + "in": [ + "v4" + ], + "op": "abi_encode_tuple__to__fromStack", + "out": [ + "v16" + ] + }, + { + "in": [ + "v2", + "v16" + ], + "op": "sub", + "out": [ + "v17" + ] + }, + { + "in": [ + "v17", + "v2", + "0x00" + ], + "op": "create", + "out": [ + "v18" + ] + }, + { + "in": [ + "v18" + ], + "op": "iszero", + "out": [ + "v19" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "panic_error_0x41", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "cond": "v33", + "targets": [ + "Block8", + "Block7" + ], + "type": "ConditionalJump" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "v18" + ], + "op": "convert_t_contract$_C_$19_to_t_address", + "out": [ + "v22" + ] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v24" + ] + }, + { + "in": [ + "0x26121ff0" + ], + "op": "shift_left_224", + "out": [ + "v25" + ] + }, + { + "in": [ + "v25", + "v24" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x04", + "v24" + ], + "op": "add", + "out": [ + "v27" + ] + }, + { + "in": [ + "v27" + ], + "op": "abi_encode_tuple__to__fromStack", + "out": [ + "v28" + ] + }, + { + "in": [ + "v24", + "v28" + ], + "op": "sub", + "out": [ + "v30" + ] + }, + { + "in": [], + "op": "gas", + "out": [ + "v31" + ] + }, + { + "in": [ + "0x20", + "v24", + "v30", + "v24", + "v22", + "v31" + ], + "op": "staticcall", + "out": [ + "v32" + ] + }, + { + "in": [ + "v32" + ], + "op": "iszero", + "out": [ + "v33" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block4", + "instructions": [ + { + "in": [], + "op": "revert_forward_1", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "cond": "v32", + "targets": [ + "Block11", + "Block10" + ], + "type": "ConditionalJump" + }, + "id": "Block8", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block7", + "instructions": [ + { + "in": [], + "op": "revert_forward_1", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "entries": [ + "Block8", + "Block13" + ], + "exit": { + "returnValues": [ + "v45" + ], + "type": "FunctionReturn" + }, + "id": "Block11", + "instructions": [ + { + "in": [ + "0x00", + "v44" + ], + "op": "PhiFunction", + "out": [ + "v45" + ] + } + ] + }, + { + "exit": { + "cond": "v37", + "targets": [ + "Block13", + "Block12" + ], + "type": "ConditionalJump" + }, + "id": "Block10", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v36" + ] + }, + { + "in": [ + "v36", + "0x20" + ], + "op": "gt", + "out": [ + "v37" + ] + } + ], + "type": "BuiltinCall" + }, + { + "entries": [ + "Block10", + "Block12" + ], + "exit": { + "targets": [ + "Block11" + ], + "type": "Jump" + }, + "id": "Block13", + "instructions": [ + { + "in": [ + "0x20", + "v38" + ], + "op": "PhiFunction", + "out": [ + "v39" + ] + }, + { + "in": [ + "v39", + "v24" + ], + "op": "finalize_allocation", + "out": [] + }, + { + "in": [ + "v39", + "v24" + ], + "op": "add", + "out": [ + "v43" + ] + }, + { + "in": [ + "v43", + "v24" + ], + "op": "abi_decode_tuple_t_uint256_fromMemory", + "out": [ + "v44" + ] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "targets": [ + "Block13" + ], + "type": "Jump" + }, + "id": "Block12", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v38" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "var__22" + ], + "type": "Function" + }, + "identity": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + }, + "panic_error_0x41": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x4e487b7100000000000000000000000000000000000000000000000000000000", + "0x00" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x41", + "0x04" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_0cc013b6b3b6beabea4e3a74a6d380f0df81852ca99887912475e1f66b2a2c20": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_forward_1": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v0" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v1" + ] + }, + { + "in": [ + "v1", + "0x00", + "v0" + ], + "op": "returndatacopy", + "out": [] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3", + "v0" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "round_up_to_mul_of_32": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v5" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x1f" + ], + "op": "not", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x1f", + "v0" + ], + "op": "add", + "out": [ + "v4" + ] + }, + { + "in": [ + "v3", + "v4" + ], + "op": "and", + "out": [ + "v5" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "result" + ], + "type": "Function" + }, + "shift_left_224": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "0xe0" + ], + "op": "shl", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "newValue" + ], + "type": "Function" + }, + "shift_right_224_unsigned": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "0xe0" + ], + "op": "shr", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "newValue" + ], + "type": "Function" + }, + "validator_revert_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "cond": "v3", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_uint256", + "out": [ + "v1" + ] + }, + { + "in": [ + "v1", + "v0" + ], + "op": "eq", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2" + ], + "op": "iszero", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "zero_value_for_split_t_uint256": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "0x00" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + } + } + }, + "subObjects": { + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "constructor_C_19", + "out": [] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v3" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v3" + ], + "op": "codecopy", + "out": [] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v3" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "functions": { + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "constructor_C_19": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "constructor_I_7", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "constructor_I_7": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + } + } + }, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "cond": "v9", + "targets": [ + "Block5", + "Block4" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7" + ], + "op": "shift_right_224_unsigned", + "out": [ + "v8" + ] + }, + { + "in": [ + "0x26121ff0", + "v8" + ], + "op": "eq", + "out": [ + "v9" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block3" + ], + "type": "Jump" + }, + "id": "Block5", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block4", + "instructions": [ + { + "in": [], + "op": "external_fun_f_18", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block3", + "instructions": [] + } + ], + "functions": { + "abi_decode_tuple_": { + "arguments": [ + "headStart", + "dataEnd" + ], + "blocks": [ + { + "exit": { + "cond": "v4", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "v1" + ], + "op": "sub", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x00", + "v3" + ], + "op": "slt", + "out": [ + "v4" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_encode_t_uint256_to_t_uint256_fromStack": { + "arguments": [ + "value", + "pos" + ], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_uint256", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2", + "v1" + ], + "op": "mstore", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { + "arguments": [ + "headStart", + "value0" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x20", + "v0" + ], + "op": "add", + "out": [ + "v4" + ] + }, + { + "in": [ + "0x00", + "v0" + ], + "op": "add", + "out": [ + "v5" + ] + }, + { + "in": [ + "v5", + "v1" + ], + "op": "abi_encode_t_uint256_to_t_uint256_fromStack", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "tail" + ], + "type": "Function" + }, + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "cleanup_t_rational_42_by_1": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "cleanup_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "convert_t_rational_42_by_1_to_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_rational_42_by_1", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2" + ], + "op": "identity", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3" + ], + "op": "cleanup_t_uint256", + "out": [ + "v4" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "converted" + ], + "type": "Function" + }, + "external_fun_f_18": { + "arguments": [], + "blocks": [ + { + "exit": { + "cond": "v0", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v0" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "calldatasize", + "out": [ + "v1" + ] + }, + { + "in": [ + "v1", + "0x04" + ], + "op": "abi_decode_tuple_", + "out": [] + }, + { + "in": [], + "op": "fun_f_18", + "out": [ + "v3" + ] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v4" + ] + }, + { + "in": [ + "v3", + "v4" + ], + "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5" + ], + "op": "sub", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v4" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "fun_f_18": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "zero_value_for_split_t_uint256", + "out": [ + "v1" + ] + }, + { + "in": [ + "0x2a" + ], + "op": "convert_t_rational_42_by_1_to_t_uint256", + "out": [ + "v3" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "var__13" + ], + "type": "Function" + }, + "identity": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + }, + "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "shift_right_224_unsigned": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "0xe0" + ], + "op": "shr", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "newValue" + ], + "type": "Function" + }, + "zero_value_for_split_t_uint256": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "0x00" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + } + } + }, + "subObjects": {}, + "type": "subObject" + }, + "type": "subObject" + }, + "type": "subObject" + }, + "type": "Object" + } + }, + "I": { + "yulCFGJson": null + } + } + }, + "sources": { + "C": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/args b/test/cmdlineTests/strict_asm_yul_cfg_json_export/args new file mode 100644 index 000000000..1147466b5 --- /dev/null +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/args @@ -0,0 +1 @@ +--strict-assembly --optimize --yul-cfg-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/input.yul b/test/cmdlineTests/strict_asm_yul_cfg_json_export/input.yul new file mode 100644 index 000000000..4165f70ba --- /dev/null +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/input.yul @@ -0,0 +1,36 @@ +/// @use-src 0:"input.sol" +object "C_19" { + code { + { + /// @src 0:124:223 "contract C is I {..." + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_19_deployed") + codecopy(_1, dataoffset("C_19_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"input.sol" + object "C_19_deployed" { + code { + { + /// @src 0:124:223 "contract C is I {..." + let _1 := memoryguard(0x80) + mstore(64, _1) + if iszero(lt(calldatasize(), 4)) + { + if eq(0x26121ff0, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + mstore(_1, /** @src 0:212:214 "42" */ 0x2a) + /// @src 0:124:223 "contract C is I {..." + return(_1, 32) + } + } + revert(0, 0) + } + } + } +} diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output new file mode 100644 index 000000000..18fa4288c --- /dev/null +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -0,0 +1,380 @@ + +======= strict_asm_yul_cfg_json_export/input.yul (EVM) ======= +Yul Control Flow Graph: + +{ + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v0" + ], + "op": "codecopy", + "out": [] + }, + { + "in": [ + "v4", + "v0" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "functions": {} + }, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [] + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ + { + "in": [ + "0x2a", + "v0" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "functions": {} + }, + "type": "subObject" + }, + "type": "Object" +} diff --git a/test/cmdlineTests/yul_cfg_json_export/args b/test/cmdlineTests/yul_cfg_json_export/args new file mode 100644 index 000000000..4af41df67 --- /dev/null +++ b/test/cmdlineTests/yul_cfg_json_export/args @@ -0,0 +1 @@ +--via-ir --optimize --yul-cfg-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/yul_cfg_json_export/input.sol b/test/cmdlineTests/yul_cfg_json_export/input.sol new file mode 100644 index 000000000..85691014f --- /dev/null +++ b/test/cmdlineTests/yul_cfg_json_export/input.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +interface I { + function f() external pure returns (uint); +} + +contract C is I { + function f() public pure override returns (uint) { + return 42; + } +} + +contract D { + function f() public returns (uint) { + C c = new C(); + return c.f(); + } +} diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output new file mode 100644 index 000000000..3a287ee76 --- /dev/null +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -0,0 +1,3964 @@ + +======= yul_cfg_json_export/input.sol:C ======= +Yul Control Flow Graph: +{ + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "constructor_C_19", + "out": [] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v3" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v3" + ], + "op": "codecopy", + "out": [] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v3" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "functions": { + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "constructor_C_19": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "constructor_I_7", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "constructor_I_7": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + } + } + }, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "cond": "v9", + "targets": [ + "Block5", + "Block4" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7" + ], + "op": "shift_right_224_unsigned", + "out": [ + "v8" + ] + }, + { + "in": [ + "0x26121ff0", + "v8" + ], + "op": "eq", + "out": [ + "v9" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block3" + ], + "type": "Jump" + }, + "id": "Block5", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block4", + "instructions": [ + { + "in": [], + "op": "external_fun_f_18", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block3", + "instructions": [] + } + ], + "functions": { + "abi_decode_tuple_": { + "arguments": [ + "headStart", + "dataEnd" + ], + "blocks": [ + { + "exit": { + "cond": "v4", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "v1" + ], + "op": "sub", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x00", + "v3" + ], + "op": "slt", + "out": [ + "v4" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_encode_t_uint256_to_t_uint256_fromStack": { + "arguments": [ + "value", + "pos" + ], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_uint256", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2", + "v1" + ], + "op": "mstore", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { + "arguments": [ + "headStart", + "value0" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x20", + "v0" + ], + "op": "add", + "out": [ + "v4" + ] + }, + { + "in": [ + "0x00", + "v0" + ], + "op": "add", + "out": [ + "v5" + ] + }, + { + "in": [ + "v5", + "v1" + ], + "op": "abi_encode_t_uint256_to_t_uint256_fromStack", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "tail" + ], + "type": "Function" + }, + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "cleanup_t_rational_42_by_1": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "cleanup_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "convert_t_rational_42_by_1_to_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_rational_42_by_1", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2" + ], + "op": "identity", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3" + ], + "op": "cleanup_t_uint256", + "out": [ + "v4" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "converted" + ], + "type": "Function" + }, + "external_fun_f_18": { + "arguments": [], + "blocks": [ + { + "exit": { + "cond": "v0", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v0" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "calldatasize", + "out": [ + "v1" + ] + }, + { + "in": [ + "v1", + "0x04" + ], + "op": "abi_decode_tuple_", + "out": [] + }, + { + "in": [], + "op": "fun_f_18", + "out": [ + "v3" + ] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v4" + ] + }, + { + "in": [ + "v3", + "v4" + ], + "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5" + ], + "op": "sub", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v4" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "fun_f_18": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "zero_value_for_split_t_uint256", + "out": [ + "v1" + ] + }, + { + "in": [ + "0x2a" + ], + "op": "convert_t_rational_42_by_1_to_t_uint256", + "out": [ + "v3" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "var__13" + ], + "type": "Function" + }, + "identity": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + }, + "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "shift_right_224_unsigned": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "0xe0" + ], + "op": "shr", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "newValue" + ], + "type": "Function" + }, + "zero_value_for_split_t_uint256": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "0x00" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + } + } + }, + "subObjects": {}, + "type": "subObject" + }, + "type": "Object" +} + +======= yul_cfg_json_export/input.sol:D ======= +Yul Control Flow Graph: +{ + "D_38": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "constructor_D_38", + "out": [] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v3" + ] + }, + { + "builtinArgs": [ + "D_38_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "D_38_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v3" + ], + "op": "codecopy", + "out": [] + }, + { + "builtinArgs": [ + "D_38_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v3" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "functions": { + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "constructor_D_38": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + } + } + }, + "subObjects": { + "D_38_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "cond": "v9", + "targets": [ + "Block5", + "Block4" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7" + ], + "op": "shift_right_224_unsigned", + "out": [ + "v8" + ] + }, + { + "in": [ + "0x26121ff0", + "v8" + ], + "op": "eq", + "out": [ + "v9" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block3" + ], + "type": "Jump" + }, + "id": "Block5", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block4", + "instructions": [ + { + "in": [], + "op": "external_fun_f_37", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block3", + "instructions": [] + } + ], + "functions": { + "abi_decode_t_uint256_fromMemory": { + "arguments": [ + "offset", + "end" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "mload", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3" + ], + "op": "validator_revert_t_uint256", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "value" + ], + "type": "Function" + }, + "abi_decode_tuple_": { + "arguments": [ + "headStart", + "dataEnd" + ], + "blocks": [ + { + "exit": { + "cond": "v4", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "v1" + ], + "op": "sub", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x00", + "v3" + ], + "op": "slt", + "out": [ + "v4" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_decode_tuple_t_uint256_fromMemory": { + "arguments": [ + "headStart", + "dataEnd" + ], + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "v1" + ], + "op": "sub", + "out": [ + "v4" + ] + }, + { + "in": [ + "0x20", + "v4" + ], + "op": "slt", + "out": [ + "v5" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [ + "v12" + ], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "v0" + ], + "op": "add", + "out": [ + "v11" + ] + }, + { + "in": [ + "v1", + "v11" + ], + "op": "abi_decode_t_uint256_fromMemory", + "out": [ + "v12" + ] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "value0" + ], + "type": "Function" + }, + "abi_encode_t_uint256_to_t_uint256_fromStack": { + "arguments": [ + "value", + "pos" + ], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_uint256", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2", + "v1" + ], + "op": "mstore", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_encode_tuple__to__fromStack": { + "arguments": [ + "headStart" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "v0" + ], + "op": "add", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "tail" + ], + "type": "Function" + }, + "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { + "arguments": [ + "headStart", + "value0" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x20", + "v0" + ], + "op": "add", + "out": [ + "v4" + ] + }, + { + "in": [ + "0x00", + "v0" + ], + "op": "add", + "out": [ + "v5" + ] + }, + { + "in": [ + "v5", + "v1" + ], + "op": "abi_encode_t_uint256_to_t_uint256_fromStack", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "tail" + ], + "type": "Function" + }, + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "cleanup_t_uint160": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0xffffffffffffffffffffffffffffffffffffffff", + "v0" + ], + "op": "and", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "cleanup_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "convert_t_contract$_C_$19_to_t_address": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "convert_t_uint160_to_t_address", + "out": [ + "v2" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "converted" + ], + "type": "Function" + }, + "convert_t_uint160_to_t_address": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "convert_t_uint160_to_t_uint160", + "out": [ + "v2" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "converted" + ], + "type": "Function" + }, + "convert_t_uint160_to_t_uint160": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_uint160", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2" + ], + "op": "identity", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3" + ], + "op": "cleanup_t_uint160", + "out": [ + "v4" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "converted" + ], + "type": "Function" + }, + "external_fun_f_37": { + "arguments": [], + "blocks": [ + { + "exit": { + "cond": "v0", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v0" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "calldatasize", + "out": [ + "v1" + ] + }, + { + "in": [ + "v1", + "0x04" + ], + "op": "abi_decode_tuple_", + "out": [] + }, + { + "in": [], + "op": "fun_f_37", + "out": [ + "v3" + ] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v4" + ] + }, + { + "in": [ + "v3", + "v4" + ], + "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5" + ], + "op": "sub", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v4" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "finalize_allocation": { + "arguments": [ + "memPtr", + "size" + ], + "blocks": [ + { + "exit": { + "cond": "v7", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v1" + ], + "op": "round_up_to_mul_of_32", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2", + "v0" + ], + "op": "add", + "out": [ + "v3" + ] + }, + { + "in": [ + "v0", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v3" + ], + "op": "gt", + "out": [ + "v6" + ] + }, + { + "in": [ + "v4", + "v6" + ], + "op": "or", + "out": [ + "v7" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "v3", + "0x40" + ], + "op": "mstore", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "panic_error_0x41", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "fun_f_37": { + "arguments": [], + "blocks": [ + { + "exit": { + "cond": "v8", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "zero_value_for_split_t_uint256", + "out": [ + "v1" + ] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v2" + ] + }, + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "datasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3", + "v2" + ], + "op": "add", + "out": [ + "v4" + ] + }, + { + "in": [ + "v2", + "v4" + ], + "op": "lt", + "out": [ + "v5" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v4" + ], + "op": "gt", + "out": [ + "v7" + ] + }, + { + "in": [ + "v5", + "v7" + ], + "op": "or", + "out": [ + "v8" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v19", + "targets": [ + "Block5", + "Block4" + ], + "type": "ConditionalJump" + }, + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "datasize", + "out": [ + "v9" + ] + }, + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v10" + ] + }, + { + "in": [ + "v9", + "v10", + "v2" + ], + "op": "datacopy", + "out": [] + }, + { + "in": [ + "v4" + ], + "op": "abi_encode_tuple__to__fromStack", + "out": [ + "v16" + ] + }, + { + "in": [ + "v2", + "v16" + ], + "op": "sub", + "out": [ + "v17" + ] + }, + { + "in": [ + "v17", + "v2", + "0x00" + ], + "op": "create", + "out": [ + "v18" + ] + }, + { + "in": [ + "v18" + ], + "op": "iszero", + "out": [ + "v19" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "panic_error_0x41", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "cond": "v33", + "targets": [ + "Block8", + "Block7" + ], + "type": "ConditionalJump" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "v18" + ], + "op": "convert_t_contract$_C_$19_to_t_address", + "out": [ + "v22" + ] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v24" + ] + }, + { + "in": [ + "0x26121ff0" + ], + "op": "shift_left_224", + "out": [ + "v25" + ] + }, + { + "in": [ + "v25", + "v24" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x04", + "v24" + ], + "op": "add", + "out": [ + "v27" + ] + }, + { + "in": [ + "v27" + ], + "op": "abi_encode_tuple__to__fromStack", + "out": [ + "v28" + ] + }, + { + "in": [ + "v24", + "v28" + ], + "op": "sub", + "out": [ + "v30" + ] + }, + { + "in": [], + "op": "gas", + "out": [ + "v31" + ] + }, + { + "in": [ + "0x20", + "v24", + "v30", + "v24", + "v22", + "v31" + ], + "op": "staticcall", + "out": [ + "v32" + ] + }, + { + "in": [ + "v32" + ], + "op": "iszero", + "out": [ + "v33" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block4", + "instructions": [ + { + "in": [], + "op": "revert_forward_1", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "cond": "v32", + "targets": [ + "Block11", + "Block10" + ], + "type": "ConditionalJump" + }, + "id": "Block8", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block7", + "instructions": [ + { + "in": [], + "op": "revert_forward_1", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "entries": [ + "Block8", + "Block13" + ], + "exit": { + "returnValues": [ + "v45" + ], + "type": "FunctionReturn" + }, + "id": "Block11", + "instructions": [ + { + "in": [ + "0x00", + "v44" + ], + "op": "PhiFunction", + "out": [ + "v45" + ] + } + ] + }, + { + "exit": { + "cond": "v37", + "targets": [ + "Block13", + "Block12" + ], + "type": "ConditionalJump" + }, + "id": "Block10", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v36" + ] + }, + { + "in": [ + "v36", + "0x20" + ], + "op": "gt", + "out": [ + "v37" + ] + } + ], + "type": "BuiltinCall" + }, + { + "entries": [ + "Block10", + "Block12" + ], + "exit": { + "targets": [ + "Block11" + ], + "type": "Jump" + }, + "id": "Block13", + "instructions": [ + { + "in": [ + "0x20", + "v38" + ], + "op": "PhiFunction", + "out": [ + "v39" + ] + }, + { + "in": [ + "v39", + "v24" + ], + "op": "finalize_allocation", + "out": [] + }, + { + "in": [ + "v39", + "v24" + ], + "op": "add", + "out": [ + "v43" + ] + }, + { + "in": [ + "v43", + "v24" + ], + "op": "abi_decode_tuple_t_uint256_fromMemory", + "out": [ + "v44" + ] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "targets": [ + "Block13" + ], + "type": "Jump" + }, + "id": "Block12", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v38" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "var__22" + ], + "type": "Function" + }, + "identity": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + }, + "panic_error_0x41": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x4e487b7100000000000000000000000000000000000000000000000000000000", + "0x00" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x41", + "0x04" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_0cc013b6b3b6beabea4e3a74a6d380f0df81852ca99887912475e1f66b2a2c20": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_forward_1": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v0" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v1" + ] + }, + { + "in": [ + "v1", + "0x00", + "v0" + ], + "op": "returndatacopy", + "out": [] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3", + "v0" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "round_up_to_mul_of_32": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v5" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x1f" + ], + "op": "not", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x1f", + "v0" + ], + "op": "add", + "out": [ + "v4" + ] + }, + { + "in": [ + "v3", + "v4" + ], + "op": "and", + "out": [ + "v5" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "result" + ], + "type": "Function" + }, + "shift_left_224": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "0xe0" + ], + "op": "shl", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "newValue" + ], + "type": "Function" + }, + "shift_right_224_unsigned": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "0xe0" + ], + "op": "shr", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "newValue" + ], + "type": "Function" + }, + "validator_revert_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "cond": "v3", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_uint256", + "out": [ + "v1" + ] + }, + { + "in": [ + "v1", + "v0" + ], + "op": "eq", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2" + ], + "op": "iszero", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "zero_value_for_split_t_uint256": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "0x00" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + } + } + }, + "subObjects": { + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "constructor_C_19", + "out": [] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v3" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v3" + ], + "op": "codecopy", + "out": [] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v3" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "functions": { + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "constructor_C_19": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "constructor_I_7", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "constructor_I_7": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + } + } + }, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "128" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "cond": "v9", + "targets": [ + "Block5", + "Block4" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7" + ], + "op": "shift_right_224_unsigned", + "out": [ + "v8" + ] + }, + { + "in": [ + "0x26121ff0", + "v8" + ], + "op": "eq", + "out": [ + "v9" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block3" + ], + "type": "Jump" + }, + "id": "Block5", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block4", + "instructions": [ + { + "in": [], + "op": "external_fun_f_18", + "out": [] + } + ], + "type": "FunctionCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block3", + "instructions": [] + } + ], + "functions": { + "abi_decode_tuple_": { + "arguments": [ + "headStart", + "dataEnd" + ], + "blocks": [ + { + "exit": { + "cond": "v4", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "v1" + ], + "op": "sub", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x00", + "v3" + ], + "op": "slt", + "out": [ + "v4" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block2", + "instructions": [] + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_encode_t_uint256_to_t_uint256_fromStack": { + "arguments": [ + "value", + "pos" + ], + "blocks": [ + { + "exit": { + "returnValues": [], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_uint256", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2", + "v1" + ], + "op": "mstore", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { + "arguments": [ + "headStart", + "value0" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x20", + "v0" + ], + "op": "add", + "out": [ + "v4" + ] + }, + { + "in": [ + "0x00", + "v0" + ], + "op": "add", + "out": [ + "v5" + ] + }, + { + "in": [ + "v5", + "v1" + ], + "op": "abi_encode_t_uint256_to_t_uint256_fromStack", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "tail" + ], + "type": "Function" + }, + "allocate_unbounded": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v2" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v2" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "memPtr" + ], + "type": "Function" + }, + "cleanup_t_rational_42_by_1": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "cleanup_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "cleaned" + ], + "type": "Function" + }, + "convert_t_rational_42_by_1_to_t_uint256": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v4" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0" + ], + "op": "cleanup_t_rational_42_by_1", + "out": [ + "v2" + ] + }, + { + "in": [ + "v2" + ], + "op": "identity", + "out": [ + "v3" + ] + }, + { + "in": [ + "v3" + ], + "op": "cleanup_t_uint256", + "out": [ + "v4" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "converted" + ], + "type": "Function" + }, + "external_fun_f_18": { + "arguments": [], + "blocks": [ + { + "exit": { + "cond": "v0", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v0" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [], + "op": "calldatasize", + "out": [ + "v1" + ] + }, + { + "in": [ + "v1", + "0x04" + ], + "op": "abi_decode_tuple_", + "out": [] + }, + { + "in": [], + "op": "fun_f_18", + "out": [ + "v3" + ] + }, + { + "in": [], + "op": "allocate_unbounded", + "out": [ + "v4" + ] + }, + { + "in": [ + "v3", + "v4" + ], + "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5" + ], + "op": "sub", + "out": [ + "v6" + ] + }, + { + "in": [ + "v6", + "v4" + ], + "op": "return", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block1", + "instructions": [ + { + "in": [], + "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "out": [] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "fun_f_18": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [], + "op": "zero_value_for_split_t_uint256", + "out": [ + "v1" + ] + }, + { + "in": [ + "0x2a" + ], + "op": "convert_t_rational_42_by_1_to_t_uint256", + "out": [ + "v3" + ] + } + ], + "type": "FunctionCall" + } + ], + "entry": "Block0", + "returns": [ + "var__13" + ], + "type": "Function" + }, + "identity": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v0" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + }, + "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { + "arguments": [], + "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [], + "type": "Function" + }, + "shift_right_224_unsigned": { + "arguments": [ + "value" + ], + "blocks": [ + { + "exit": { + "returnValues": [ + "v3" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [ + { + "in": [ + "v0", + "0xe0" + ], + "op": "shr", + "out": [ + "v3" + ] + } + ], + "type": "BuiltinCall" + } + ], + "entry": "Block0", + "returns": [ + "newValue" + ], + "type": "Function" + }, + "zero_value_for_split_t_uint256": { + "arguments": [], + "blocks": [ + { + "exit": { + "returnValues": [ + "0x00" + ], + "type": "FunctionReturn" + }, + "id": "Block0", + "instructions": [] + } + ], + "entry": "Block0", + "returns": [ + "ret" + ], + "type": "Function" + } + } + }, + "subObjects": {}, + "type": "subObject" + }, + "type": "subObject" + }, + "type": "subObject" + }, + "type": "Object" +} + +======= yul_cfg_json_export/input.sol:I ======= +Yul Control Flow Graph: +null From 6c1ed9d0ebb7629f29bd581579c5751eb03988b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 16 Oct 2024 17:31:00 +0200 Subject: [PATCH 0420/1340] Add profiler probes for steps outside the sequence --- libyul/optimiser/Suite.cpp | 54 +++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 76f0368ab..9509a4b86 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -108,11 +108,15 @@ void OptimiserSuite::run( std::set reservedIdentifiers = _externallyUsedIdentifiers; reservedIdentifiers += _dialect.fixedFunctionNames(); - auto astRoot = std::get(Disambiguator( - _dialect, - *_object.analysisInfo, - reservedIdentifiers - )(_object.code()->root())); + Block astRoot; + { + PROFILER_PROBE("Disambiguator", probe); + astRoot = std::get(Disambiguator( + _dialect, + *_object.analysisInfo, + reservedIdentifiers + )(_object.code()->root())); + } NameDispenser dispenser{_dialect, astRoot, reservedIdentifiers}; OptimiserStepContext context{_dialect, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment}; @@ -123,7 +127,10 @@ void OptimiserSuite::run( // ForLoopInitRewriter. Run them first to be able to run arbitrary sequences safely. suite.runSequence("hgfo", astRoot); - NameSimplifier::run(suite.m_context, astRoot); + { + PROFILER_PROBE("NameSimplifier", probe); + NameSimplifier::run(suite.m_context, astRoot); + } // Now the user-supplied part suite.runSequence(_optimisationSequence, astRoot); @@ -135,6 +142,7 @@ void OptimiserSuite::run( // message once we perform code generation. if (!usesOptimizedCodeGenerator) { + PROFILER_PROBE("StackCompressor", probe); _object.setCode(std::make_shared(std::move(astRoot))); astRoot = std::get<1>(StackCompressor::run( _dialect, @@ -154,32 +162,46 @@ void OptimiserSuite::run( if (evmDialect) { yulAssert(_meter, ""); - ConstantOptimiser{*evmDialect, *_meter}(astRoot); + { + PROFILER_PROBE("ConstantOptimiser", probe); + ConstantOptimiser{*evmDialect, *_meter}(astRoot); + } if (usesOptimizedCodeGenerator) { - _object.setCode(std::make_shared(std::move(astRoot))); - astRoot = std::get<1>(StackCompressor::run( - _dialect, - _object, - _optimizeStackAllocation, - stackCompressorMaxIterations - )); + { + PROFILER_PROBE("StackCompressor", probe); + _object.setCode(std::make_shared(std::move(astRoot))); + astRoot = std::get<1>(StackCompressor::run( + _dialect, + _object, + _optimizeStackAllocation, + stackCompressorMaxIterations + )); + } if (evmDialect->providesObjectAccess()) { + PROFILER_PROBE("StackLimitEvader", probe); _object.setCode(std::make_shared(std::move(astRoot))); astRoot = StackLimitEvader::run(suite.m_context, _object); } } else if (evmDialect->providesObjectAccess() && _optimizeStackAllocation) { + PROFILER_PROBE("StackLimitEvader", probe); _object.setCode(std::make_shared(std::move(astRoot))); astRoot = StackLimitEvader::run(suite.m_context, _object); } } dispenser.reset(astRoot); - NameSimplifier::run(suite.m_context, astRoot); - VarNameCleaner::run(suite.m_context, astRoot); + { + PROFILER_PROBE("NameSimplifier", probe); + NameSimplifier::run(suite.m_context, astRoot); + } + { + PROFILER_PROBE("VarNameCleaner", probe); + VarNameCleaner::run(suite.m_context, astRoot); + } _object.setCode(std::make_shared(std::move(astRoot))); _object.analysisInfo = std::make_shared(AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object)); From 07dd5475139f2a4d9c97fe509b083785a6ce07f1 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:53:07 +0200 Subject: [PATCH 0421/1340] Yul optimizer suite: Call name simplifier only once --- libyul/optimiser/Suite.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 9509a4b86..1e4c3e21e 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -127,10 +127,6 @@ void OptimiserSuite::run( // ForLoopInitRewriter. Run them first to be able to run arbitrary sequences safely. suite.runSequence("hgfo", astRoot); - { - PROFILER_PROBE("NameSimplifier", probe); - NameSimplifier::run(suite.m_context, astRoot); - } // Now the user-supplied part suite.runSequence(_optimisationSequence, astRoot); From a39a725f31adccfe8f4bf03602d0bc9152fe5400 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 16 Oct 2024 16:53:15 +0200 Subject: [PATCH 0422/1340] Yul: Use builtin handle struct for builtin referencing --- libsolidity/analysis/ControlFlowBuilder.cpp | 9 +- libsolidity/analysis/ViewPureChecker.cpp | 6 +- .../codegen/ir/IRGeneratorForStatements.cpp | 2 +- .../codegen/IRGeneratorForStatements.cpp | 2 +- libyul/AsmAnalysis.cpp | 29 +- libyul/AsmParser.cpp | 15 +- libyul/Builtins.h | 35 ++ libyul/CMakeLists.txt | 1 + libyul/ControlFlowSideEffectsCollector.cpp | 4 +- libyul/Dialect.h | 43 +- libyul/YulControlFlowGraphExporter.cpp | 2 +- libyul/backends/evm/ConstantOptimiser.cpp | 16 +- .../backends/evm/ControlFlowGraphBuilder.cpp | 17 +- libyul/backends/evm/EVMCodeTransform.cpp | 7 +- libyul/backends/evm/EVMDialect.cpp | 471 ++++++++++-------- libyul/backends/evm/EVMDialect.h | 46 +- libyul/backends/evm/EVMMetrics.cpp | 6 +- libyul/backends/evm/NoOutputAssembly.cpp | 25 +- libyul/backends/evm/SSAControlFlowGraph.cpp | 2 +- .../evm/SSAControlFlowGraphBuilder.cpp | 15 +- .../CommonSubexpressionEliminator.cpp | 5 +- libyul/optimiser/ControlFlowSimplifier.cpp | 14 +- libyul/optimiser/DataFlowAnalyzer.cpp | 18 +- libyul/optimiser/Disambiguator.cpp | 2 +- libyul/optimiser/ExpressionSplitter.cpp | 4 +- libyul/optimiser/ForLoopConditionIntoBody.cpp | 2 +- .../optimiser/ForLoopConditionOutOfBody.cpp | 4 +- libyul/optimiser/FullInliner.cpp | 2 +- libyul/optimiser/FunctionSpecializer.cpp | 2 +- libyul/optimiser/LoadResolver.cpp | 2 +- libyul/optimiser/NameSimplifier.cpp | 2 +- libyul/optimiser/OptimizerUtilities.cpp | 6 +- libyul/optimiser/Semantics.cpp | 16 +- libyul/optimiser/SimplificationRules.cpp | 6 +- libyul/optimiser/StackToMemoryMover.cpp | 14 +- libyul/optimiser/UnusedAssignEliminator.cpp | 4 +- libyul/optimiser/UnusedPruner.cpp | 2 +- libyul/optimiser/UnusedStoreEliminator.cpp | 8 +- test/libyul/Parser.cpp | 16 +- .../EVMInstructionInterpreter.cpp | 2 +- test/tools/yulInterpreter/Interpreter.cpp | 20 +- 41 files changed, 535 insertions(+), 369 deletions(-) create mode 100644 libyul/Builtins.h diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index 7bc0ebc7b..a42cec172 100644 --- a/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/libsolidity/analysis/ControlFlowBuilder.cpp @@ -582,13 +582,14 @@ void ControlFlowBuilder::operator()(yul::FunctionCall const& _functionCall) solAssert(m_currentNode && m_inlineAssembly, ""); yul::ASTWalker::operator()(_functionCall); - if (auto const *builtinFunction = m_inlineAssembly->dialect().builtin(_functionCall.functionName.name)) + if (auto const& builtinHandle = m_inlineAssembly->dialect().findBuiltin(_functionCall.functionName.name.str())) { - if (builtinFunction->controlFlowSideEffects.canTerminate) + auto const& builtinFunction = m_inlineAssembly->dialect().builtin(*builtinHandle); + if (builtinFunction.controlFlowSideEffects.canTerminate) connect(m_currentNode, m_transactionReturnNode); - if (builtinFunction->controlFlowSideEffects.canRevert) + if (builtinFunction.controlFlowSideEffects.canRevert) connect(m_currentNode, m_revertNode); - if (!builtinFunction->controlFlowSideEffects.canContinue) + if (!builtinFunction.controlFlowSideEffects.canContinue) m_currentNode = newLabel(); } } diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 3b16205e7..6a3a902ed 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -66,9 +66,9 @@ class AssemblyViewPureChecker void operator()(yul::FunctionCall const& _funCall) { if (yul::EVMDialect const* dialect = dynamic_cast(&m_dialect)) - if (yul::BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name)) - if (fun->instruction) - checkInstruction(nativeLocationOf(_funCall), *fun->instruction); + if (std::optional builtinHandle = dialect->findBuiltin(_funCall.functionName.name.str())) + if (auto const& instruction = dialect->builtin(*builtinHandle).instruction) + checkInstruction(nativeLocationOf(_funCall), *instruction); for (auto const& arg: _funCall.arguments) std::visit(*this, arg); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 911230d22..69d24cf42 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -84,7 +84,7 @@ struct CopyTranslate: public yul::ASTCopier // from the Yul dialect we are compiling to. So we are assuming here that the builtin // functions are identical. This should not be a problem for now since everything // is EVM anyway. - if (m_dialect.builtin(_name)) + if (m_dialect.findBuiltin(_name.str())) return _name; else return yul::YulName{"usr$" + _name.str()}; diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index 772e8575d..a9e4fa931 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -72,7 +72,7 @@ struct CopyTranslate: public yul::ASTCopier yul::YulName translateIdentifier(yul::YulName _name) override { - if (m_dialect.builtin(_name)) + if (m_dialect.findBuiltin(_name.str())) return _name; else return yul::YulName{"usr$" + _name.str()}; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 9eb546547..84eb39daa 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -299,7 +299,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) std::optional numReturns; std::vector> const* literalArguments = nullptr; - if (BuiltinFunction const* f = m_dialect.builtin(_funCall.functionName.name)) + if (std::optional handle = m_dialect.findBuiltin(_funCall.functionName.name.str())) { if (_funCall.functionName.name == "selfdestruct"_yulname) m_errorReporter.warning( @@ -327,13 +327,14 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) "The use of transient storage for reentrancy guards that are cleared at the end of the call is safe." ); - numParameters = f->numParameters; - numReturns = f->numReturns; - if (!f->literalArguments.empty()) - literalArguments = &f->literalArguments; + BuiltinFunction const& f = m_dialect.builtin(*handle); + numParameters = f.numParameters; + numReturns = f.numReturns; + if (!f.literalArguments.empty()) + literalArguments = &f.literalArguments; validateInstructions(_funCall); - m_sideEffects += f->sideEffects; + m_sideEffects += f.sideEffects; } else if (m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{ [&](Scope::Variable const&) @@ -628,7 +629,7 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons "\"" + _identifier.str() + "\" is not a valid identifier (contains consecutive dots)." ); - if (m_dialect.reservedIdentifier(_identifier)) + if (m_dialect.reservedIdentifier(_identifier.str())) m_errorReporter.declarationError( 5017_error, _location, @@ -639,14 +640,16 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location) { // NOTE: This function uses the default EVM version instead of the currently selected one. - auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt).builtin(YulName(_instructionIdentifier)); - if (builtin && builtin->instruction.has_value()) - return validateInstructions(builtin->instruction.value(), _location); + auto const& defaultEVMDialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const builtinHandle = defaultEVMDialect.findBuiltin(_instructionIdentifier); + if (builtinHandle && defaultEVMDialect.builtin(*builtinHandle).instruction.has_value()) + return validateInstructions(*defaultEVMDialect.builtin(*builtinHandle).instruction, _location); // TODO: Change `prague()` to `EVMVersion{}` once EOF gets deployed - auto const eofBuiltin = EVMDialect::strictAssemblyForEVM(EVMVersion::prague(), 1).builtin(YulName(_instructionIdentifier)); - if (eofBuiltin && eofBuiltin->instruction.has_value()) - return validateInstructions(eofBuiltin->instruction.value(), _location); + auto const& eofDialect = EVMDialect::strictAssemblyForEVM(EVMVersion::prague(), 1); + auto const eofBuiltinHandle = eofDialect.findBuiltin(_instructionIdentifier); + if (eofBuiltinHandle && eofDialect.builtin(*eofBuiltinHandle).instruction.has_value()) + return validateInstructions(*eofDialect.builtin(*eofBuiltinHandle).instruction, _location); return false; } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index d41b41a36..f7741dfae 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -432,7 +432,7 @@ Statement Parser::parseStatement() auto const& identifier = std::get(elementary); - if (m_dialect.builtin(identifier.name)) + if (m_dialect.findBuiltin(identifier.name.str())) fatalParserError(6272_error, "Cannot assign to builtin function \"" + identifier.name.str() + "\"."); assignment.variableNames.emplace_back(identifier); @@ -515,7 +515,7 @@ Expression Parser::parseExpression(bool _unlimitedLiteralArgument) { if (currentToken() == Token::LParen) return parseCall(std::move(operation)); - if (m_dialect.builtin(_identifier.name)) + if (m_dialect.findBuiltin(_identifier.name.str())) fatalParserError( 7104_error, nativeLocationOf(_identifier), @@ -676,10 +676,11 @@ FunctionCall Parser::parseCall(std::variant&& _initialOp) FunctionCall ret; ret.functionName = std::move(std::get(_initialOp)); ret.debugData = ret.functionName.debugData; - auto const isUnlimitedLiteralArgument = [f=m_dialect.builtin(ret.functionName.name)](size_t const index) { - if (f && index < f->literalArguments.size()) - return f->literalArgument(index).has_value(); - return false; + auto const isUnlimitedLiteralArgument = [handle=m_dialect.findBuiltin(ret.functionName.name.str()), this](size_t const index) { + if (!handle) + return false; + auto const& function = m_dialect.builtin(*handle); + return index < function.literalArguments.size() && function.literalArgument(index).has_value(); }; size_t argumentIndex {0}; expectToken(Token::LParen); @@ -718,7 +719,7 @@ NameWithDebugData Parser::parseNameWithDebugData() YulName Parser::expectAsmIdentifier() { YulName name{currentLiteral()}; - if (currentToken() == Token::Identifier && m_dialect.builtin(name)) + if (currentToken() == Token::Identifier && m_dialect.findBuiltin(name.str())) fatalParserError(5568_error, "Cannot use builtin function name \"" + name.str() + "\" as identifier name."); // NOTE: We keep the expectation here to ensure the correct source location for the error above. expectToken(Token::Identifier); diff --git a/libyul/Builtins.h b/libyul/Builtins.h new file mode 100644 index 000000000..8ee17de4b --- /dev/null +++ b/libyul/Builtins.h @@ -0,0 +1,35 @@ +/* + 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 + +#pragma once + +#include + +namespace solidity::yul +{ + +/// Handle to reference a builtin function in the AST +struct BuiltinHandle +{ + size_t id; + + bool operator==(BuiltinHandle const& _other) const { return id == _other.id; } + bool operator<(BuiltinHandle const& _other) const { return id < _other.id; } +}; + +} diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 58c1b17b5..cc4c5051c 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -15,6 +15,7 @@ add_library(yul AsmParser.h AsmPrinter.cpp AsmPrinter.h + Builtins.h YulStack.h YulStack.cpp CompilabilityChecker.cpp diff --git a/libyul/ControlFlowSideEffectsCollector.cpp b/libyul/ControlFlowSideEffectsCollector.cpp index 471a164e5..2694eef1c 100644 --- a/libyul/ControlFlowSideEffectsCollector.cpp +++ b/libyul/ControlFlowSideEffectsCollector.cpp @@ -271,8 +271,8 @@ ControlFlowNode const* ControlFlowSideEffectsCollector::nextProcessableNode(Func ControlFlowSideEffects const& ControlFlowSideEffectsCollector::sideEffects(FunctionCall const& _call) const { - if (auto const* builtin = m_dialect.builtin(_call.functionName.name)) - return builtin->controlFlowSideEffects; + if (std::optional builtinHandle = m_dialect.findBuiltin(_call.functionName.name.str())) + return m_dialect.builtin(*builtinHandle).controlFlowSideEffects; else return m_functionSideEffects.at(m_functionReferences.at(&_call)); } diff --git a/libyul/Dialect.h b/libyul/Dialect.h index 3b0d73597..a707771a2 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -21,13 +21,16 @@ #pragma once -#include +#include #include +#include #include +#include -#include -#include #include +#include +#include +#include namespace solidity::yul { @@ -38,7 +41,7 @@ struct Literal; struct BuiltinFunction { - YulName name; + std::string name; size_t numParameters; size_t numReturns; SideEffects sideEffects; @@ -56,25 +59,31 @@ struct BuiltinFunction struct Dialect { + static size_t constexpr verbatimMaxInputSlots = 100; + static size_t constexpr verbatimMaxOutputSlots = 100; + /// Noncopiable. Dialect(Dialect const&) = delete; Dialect& operator=(Dialect const&) = delete; - /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. - virtual BuiltinFunction const* builtin(YulName /*_name*/) const { return nullptr; } + /// @returns the builtin function of the given name or a null if it is not a builtin function. + virtual std::optional findBuiltin(std::string_view /*_name*/) const { return std::nullopt; } - /// @returns true if the identifier is reserved. This includes the builtins too. - virtual bool reservedIdentifier(YulName _name) const { return builtin(_name) != nullptr; } - - virtual BuiltinFunction const* discardFunction() const { return nullptr; } - virtual BuiltinFunction const* equalityFunction() const { return nullptr; } - virtual BuiltinFunction const* booleanNegationFunction() const { return nullptr; } + virtual BuiltinFunction const& builtin(BuiltinHandle const&) const { yulAssert(false); } - virtual BuiltinFunction const* memoryStoreFunction() const { return nullptr; } - virtual BuiltinFunction const* memoryLoadFunction() const { return nullptr; } - virtual BuiltinFunction const* storageStoreFunction() const { return nullptr; } - virtual BuiltinFunction const* storageLoadFunction() const { return nullptr; } - virtual YulName hashFunction() const { return YulName{}; } + /// @returns true if the identifier is reserved. This includes the builtins too. + virtual bool reservedIdentifier(std::string_view _name) const { return findBuiltin(_name).has_value(); } + + // todo these are handles, not functions + virtual std::optional discardFunction() const { return std::nullopt; } + virtual std::optional equalityFunction() const { return std::nullopt; } + virtual std::optional booleanNegationFunction() const { return std::nullopt; } + + virtual std::optional memoryStoreFunction() const { return std::nullopt; } + virtual std::optional memoryLoadFunction() const { return std::nullopt; } + virtual std::optional storageStoreFunction() const { return std::nullopt; } + virtual std::optional storageLoadFunction() const { return std::nullopt; } + virtual std::optional hashFunction() const { return std::nullopt; } Literal zeroLiteral() const; diff --git a/libyul/YulControlFlowGraphExporter.cpp b/libyul/YulControlFlowGraphExporter.cpp index 3f347fcf4..d86ffbc7a 100644 --- a/libyul/YulControlFlowGraphExporter.cpp +++ b/libyul/YulControlFlowGraphExporter.cpp @@ -193,7 +193,7 @@ Json YulControlFlowGraphExporter::toJson(Json& _ret, SSACFG const& _cfg, SSACFG: if (!builtinArgsJson.empty()) opJson["builtinArgs"] = builtinArgsJson; - opJson["op"] = _call.builtin.get().name.str(); + opJson["op"] = _call.builtin.get().name; }, }, _operation.kind); diff --git a/libyul/backends/evm/ConstantOptimiser.cpp b/libyul/backends/evm/ConstantOptimiser.cpp index 1bb23cbc9..0ea8f4e5a 100644 --- a/libyul/backends/evm/ConstantOptimiser.cpp +++ b/libyul/backends/evm/ConstantOptimiser.cpp @@ -74,10 +74,11 @@ struct MiniEVMInterpreter u256 operator()(FunctionCall const& _funCall) { - BuiltinFunctionForEVM const* fun = m_dialect.builtin(_funCall.functionName.name); - yulAssert(fun, "Expected builtin function."); - yulAssert(fun->instruction, "Expected EVM instruction."); - return eval(*fun->instruction, _funCall.arguments); + std::optional funHandle = m_dialect.findBuiltin(_funCall.functionName.name.str()); + yulAssert(funHandle, "Expected builtin function."); + BuiltinFunctionForEVM const& fun = m_dialect.builtin(*funHandle); + yulAssert(fun.instruction, "Expected EVM instruction."); + return eval(*fun.instruction, _funCall.arguments); } u256 operator()(Literal const& _literal) { @@ -195,7 +196,9 @@ Representation RepresentationFinder::represent( Identifier{m_debugData, _instruction}, {ASTCopier{}.translate(*_argument.expression)} }); - repr.cost = _argument.cost + m_meter.instructionCosts(*m_dialect.builtin(_instruction)->instruction); + repr.cost = _argument.cost + m_meter.instructionCosts( + *m_dialect.builtin(*m_dialect.findBuiltin(_instruction.str())).instruction + ); return repr; } @@ -211,7 +214,8 @@ Representation RepresentationFinder::represent( Identifier{m_debugData, _instruction}, {ASTCopier{}.translate(*_arg1.expression), ASTCopier{}.translate(*_arg2.expression)} }); - repr.cost = m_meter.instructionCosts(*m_dialect.builtin(_instruction)->instruction) + _arg1.cost + _arg2.cost; + repr.cost = m_meter.instructionCosts( + *m_dialect.builtin(*m_dialect.findBuiltin(_instruction.str())).instruction) + _arg1.cost + _arg2.cost; return repr; } diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 46ef933ba..1b523c4dd 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -349,8 +349,8 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) CFG::Assignment{_switch.debugData, {ghostVarSlot}} }); - BuiltinFunction const* equalityBuiltin = m_dialect.equalityFunction(); - yulAssert(equalityBuiltin, ""); + std::optional const& equalityBuiltinHandle = m_dialect.equalityFunction(); + yulAssert(equalityBuiltinHandle); // Artificially generate: // eq(, ) @@ -363,7 +363,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) CFG::Operation& operation = m_currentBlock->operations.emplace_back(CFG::Operation{ Stack{ghostVarSlot, LiteralSlot{_case.value->value.value(), debugDataOf(*_case.value)}}, Stack{TemporarySlot{ghostCall, 0}}, - CFG::BuiltinCall{debugDataOf(_case), *equalityBuiltin, ghostCall, 2}, + CFG::BuiltinCall{debugDataOf(_case), m_dialect.builtin(*equalityBuiltinHandle), ghostCall, 2}, }); return operation.output.front(); }; @@ -516,24 +516,25 @@ Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _cal Stack const* output = nullptr; bool canContinue = true; - if (BuiltinFunction const* builtin = m_dialect.builtin(_call.functionName.name)) + if (std::optional const& builtinHandle = m_dialect.findBuiltin(_call.functionName.name.str())) { + auto const& builtin = m_dialect.builtin(*builtinHandle); Stack inputs; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) - if (!builtin->literalArgument(idx).has_value()) + if (!builtin.literalArgument(idx).has_value()) inputs.emplace_back(std::visit(*this, arg)); - CFG::BuiltinCall builtinCall{_call.debugData, *builtin, _call, inputs.size()}; + CFG::BuiltinCall builtinCall{_call.debugData, builtin, _call, inputs.size()}; output = &m_currentBlock->operations.emplace_back(CFG::Operation{ // input std::move(inputs), // output - ranges::views::iota(0u, builtin->numReturns) | ranges::views::transform([&](size_t _i) { + ranges::views::iota(0u, builtin.numReturns) | ranges::views::transform([&](size_t _i) { return TemporarySlot{_call, _i}; }) | ranges::to, // operation std::move(builtinCall) }).output; - canContinue = builtin->controlFlowSideEffects.canContinue; + canContinue = builtin.controlFlowSideEffects.canContinue; } else { diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 694639565..e354649e7 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -230,13 +230,14 @@ void CodeTransform::operator()(FunctionCall const& _call) yulAssert(m_scope, ""); m_assembly.setSourceLocation(originLocationOf(_call)); - if (BuiltinFunctionForEVM const* builtin = m_dialect.builtin(_call.functionName.name)) + if (std::optional builtinHandle = m_dialect.findBuiltin(_call.functionName.name.str())) { + BuiltinFunctionForEVM const& builtin = m_dialect.builtin(*builtinHandle); for (auto&& [i, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) - if (!builtin->literalArgument(i)) + if (!builtin.literalArgument(i)) visitExpression(arg); m_assembly.setSourceLocation(originLocationOf(_call)); - builtin->generateCode(_call, m_assembly, m_builtinContext); + builtin.generateCode(_call, m_assembly, m_builtinContext); } else { diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 9e9d5e542..e50e849d7 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -25,13 +25,17 @@ #include #include #include -#include #include #include #include #include +#include +#include + #include +#include +#include using namespace std::string_literals; using namespace solidity; @@ -41,15 +45,15 @@ using namespace solidity::util; namespace { -std::pair createEVMFunction( +BuiltinFunctionForEVM createEVMFunction( langutil::EVMVersion _evmVersion, std::string const& _name, evmasm::Instruction _instruction ) { - evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction, _evmVersion); BuiltinFunctionForEVM f; - f.name = YulName{_name}; + evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction, _evmVersion); + f.name = _name; f.numParameters = static_cast(info.args); f.numReturns = static_cast(info.ret); f.sideEffects = EVMDialect::sideEffectsOfInstruction(_instruction); @@ -77,13 +81,11 @@ std::pair createEVMFunction( ) { _assembly.appendInstruction(_instruction); }; - - YulName name = f.name; - return {name, std::move(f)}; + return f; } -std::pair createFunction( - std::string _name, +BuiltinFunctionForEVM createFunction( + std::string const& _name, size_t _params, size_t _returns, SideEffects _sideEffects, @@ -93,20 +95,19 @@ std::pair createFunction( { yulAssert(_literalArguments.size() == _params || _literalArguments.empty(), ""); - YulName name{std::move(_name)}; BuiltinFunctionForEVM f; - f.name = name; + f.name = _name; f.numParameters = _params; f.numReturns = _returns; - f.sideEffects = std::move(_sideEffects); + f.sideEffects = _sideEffects; f.literalArguments = std::move(_literalArguments); f.isMSize = false; f.instruction = {}; f.generateCode = std::move(_generateCode); - return {name, f}; + return f; } -std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) +std::set> createReservedIdentifiers(langutil::EVMVersion _evmVersion) { // TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name // basefee for VMs before london. @@ -152,7 +153,7 @@ std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) (_instr == evmasm::Instruction::TSTORE || _instr == evmasm::Instruction::TLOAD); }; - std::set reserved; + std::set> reserved; for (auto const& instr: evmasm::c_instructions) { std::string name = toLower(instr.first); @@ -166,18 +167,18 @@ std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) ) reserved.emplace(name); } - reserved += std::vector{ - "linkersymbol"_yulname, - "datasize"_yulname, - "dataoffset"_yulname, - "datacopy"_yulname, - "setimmutable"_yulname, - "loadimmutable"_yulname, + reserved += std::vector{ + "linkersymbol", + "datasize", + "dataoffset", + "datacopy", + "setimmutable", + "loadimmutable", }; return reserved; } -std::map createBuiltins(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess) +std::vector> createBuiltins(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess) { // Exclude prevrandao as builtin for VMs before paris and difficulty for VMs after paris. @@ -186,7 +187,7 @@ std::map createBuiltins(langutil::EVMVersion _ev return (_instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris()) || (_instrName == "difficulty" && _evmVersion >= langutil::EVMVersion::paris()); }; - std::map builtins; + std::vector> builtins; for (auto const& instr: evmasm::c_instructions) { std::string name = toLower(instr.first); @@ -203,171 +204,188 @@ std::map createBuiltins(langutil::EVMVersion _ev _evmVersion.hasOpcode(opcode, _eofVersion) && !prevRandaoException(name) ) - builtins.emplace(createEVMFunction(_evmVersion, name, opcode)); + builtins.emplace_back(createEVMFunction(_evmVersion, name, opcode)); + else + builtins.emplace_back(std::nullopt); } - if (_objectAccess) + auto const createIfObjectAccess = [_objectAccess]( + std::string const& _name, + size_t _params, + size_t _returns, + SideEffects _sideEffects, + std::vector> _literalArguments, + std::function _generateCode + ) -> std::optional { - builtins.emplace(createFunction("linkersymbol", 1, 1, SideEffects{}, {LiteralKind::String}, []( + if (!_objectAccess) + return std::nullopt; + return createFunction(_name, _params, _returns, _sideEffects, std::move(_literalArguments), std::move(_generateCode)); + }; + + builtins.emplace_back(createIfObjectAccess("linkersymbol", 1, 1, SideEffects{}, {LiteralKind::String}, []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + _assembly.appendLinkerSymbol(formatLiteral(std::get(arg))); + })); + builtins.emplace_back(createIfObjectAccess( + "memoryguard", + 1, + 1, + SideEffects{}, + {LiteralKind::Number}, + []( FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& ) { + yulAssert(_call.arguments.size() == 1, ""); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal, ""); + _assembly.appendConstant(literal->value.value()); + }) + ); + if (!_eofVersion.has_value()) + { + builtins.emplace_back(createIfObjectAccess("datasize", 1, 1, SideEffects{}, {LiteralKind::String}, []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& _context + ) { + yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); Expression const& arg = _call.arguments.front(); - _assembly.appendLinkerSymbol(formatLiteral(std::get(arg))); + YulName const dataName (formatLiteral(std::get(arg))); + if (_context.currentObject->name == dataName.str()) + _assembly.appendAssemblySize(); + else + { + std::vector subIdPath = + _context.subIDs.count(dataName.str()) == 0 ? + _context.currentObject->pathToSubObject(dataName.str()) : + std::vector{_context.subIDs.at(dataName.str())}; + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + _assembly.appendDataSize(subIdPath); + } })); - - builtins.emplace(createFunction( - "memoryguard", - 1, - 1, - SideEffects{}, - {LiteralKind::Number}, + builtins.emplace_back(createIfObjectAccess("dataoffset", 1, 1, SideEffects{}, {LiteralKind::String}, []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& _context + ) { + yulAssert(_context.currentObject, "No object available."); + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + YulName const dataName (formatLiteral(std::get(arg))); + if (_context.currentObject->name == dataName.str()) + _assembly.appendConstant(0); + else + { + std::vector subIdPath = + _context.subIDs.count(dataName.str()) == 0 ? + _context.currentObject->pathToSubObject(dataName.str()) : + std::vector{_context.subIDs.at(dataName.str())}; + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + _assembly.appendDataOffset(subIdPath); + } + })); + builtins.emplace_back(createIfObjectAccess( + "datacopy", + 3, + 0, + SideEffects{ + false, // movable + true, // movableApartFromEffects + false, // canBeRemoved + false, // canBeRemovedIfNotMSize + true, // cannotLoop + SideEffects::None, // otherState + SideEffects::None, // storage + SideEffects::Write, // memory + SideEffects::None // transientStorage + }, + {}, + []( + FunctionCall const&, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + _assembly.appendInstruction(evmasm::Instruction::CODECOPY); + } + )); + builtins.emplace_back(createIfObjectAccess( + "setimmutable", + 3, + 0, + SideEffects{ + false, // movable + false, // movableApartFromEffects + false, // canBeRemoved + false, // canBeRemovedIfNotMSize + true, // cannotLoop + SideEffects::None, // otherState + SideEffects::None, // storage + SideEffects::Write, // memory + SideEffects::None // transientStorage + }, + {std::nullopt, LiteralKind::String, std::nullopt}, []( FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& ) { - yulAssert(_call.arguments.size() == 1, ""); - Literal const* literal = std::get_if(&_call.arguments.front()); - yulAssert(literal, ""); - _assembly.appendConstant(literal->value.value()); - }) - ); - - if (!_eofVersion.has_value()) // non-EOF context - { - builtins.emplace(createFunction("datasize", 1, 1, SideEffects{}, {LiteralKind::String}, []( + yulAssert(_call.arguments.size() == 3, ""); + auto const identifier = (formatLiteral(std::get(_call.arguments[1]))); + _assembly.appendImmutableAssignment(identifier); + } + )); + builtins.emplace_back(createIfObjectAccess( + "loadimmutable", + 1, + 1, + SideEffects{}, + {LiteralKind::String}, + []( FunctionCall const& _call, AbstractAssembly& _assembly, - BuiltinContext& _context + BuiltinContext& ) { - yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - YulName const dataName (formatLiteral(std::get(arg))); - if (_context.currentObject->name == dataName.str()) - _assembly.appendAssemblySize(); - else - { - std::vector subIdPath = - _context.subIDs.count(dataName.str()) == 0 ? - _context.currentObject->pathToSubObject(dataName.str()) : - std::vector{_context.subIDs.at(dataName.str())}; - yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); - _assembly.appendDataSize(subIdPath); - } - })); - builtins.emplace(createFunction("dataoffset", 1, 1, SideEffects{}, {LiteralKind::String}, []( + _assembly.appendImmutable(formatLiteral(std::get(_call.arguments.front()))); + } + )); + } + else + { + builtins.emplace_back(createFunction( + "auxdataloadn", + 1, + 1, + SideEffects{}, + {LiteralKind::Number}, + []( FunctionCall const& _call, AbstractAssembly& _assembly, - BuiltinContext& _context + BuiltinContext& ) { - yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - YulName const dataName (formatLiteral(std::get(arg))); - if (_context.currentObject->name == dataName.str()) - _assembly.appendConstant(0); - else - { - std::vector subIdPath = - _context.subIDs.count(dataName.str()) == 0 ? - _context.currentObject->pathToSubObject(dataName.str()) : - std::vector{_context.subIDs.at(dataName.str())}; - yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); - _assembly.appendDataOffset(subIdPath); - } - })); - builtins.emplace(createFunction( - "datacopy", - 3, - 0, - SideEffects{ - false, // movable - true, // movableApartFromEffects - false, // canBeRemoved - false, // canBeRemovedIfNotMSize - true, // cannotLoop - SideEffects::None, // otherState - SideEffects::None, // storage - SideEffects::Write, // memory - SideEffects::None // transientStorage - }, - {}, - []( - FunctionCall const&, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - _assembly.appendInstruction(evmasm::Instruction::CODECOPY); - } - )); - builtins.emplace(createFunction( - "setimmutable", - 3, - 0, - SideEffects{ - false, // movable - false, // movableApartFromEffects - false, // canBeRemoved - false, // canBeRemovedIfNotMSize - true, // cannotLoop - SideEffects::None, // otherState - SideEffects::None, // storage - SideEffects::Write, // memory - SideEffects::None // transientStorage - }, - {std::nullopt, LiteralKind::String, std::nullopt}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == 3, ""); - auto const identifier = (formatLiteral(std::get(_call.arguments[1]))); - _assembly.appendImmutableAssignment(identifier); - } - )); - builtins.emplace(createFunction( - "loadimmutable", - 1, - 1, - SideEffects{}, - {LiteralKind::String}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == 1, ""); - _assembly.appendImmutable(formatLiteral(std::get(_call.arguments.front()))); - } - )); - } - else // EOF context - { - builtins.emplace(createFunction( - "auxdataloadn", - 1, - 1, - SideEffects{}, - {LiteralKind::Number}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == 1, ""); - Literal const* literal = std::get_if(&_call.arguments.front()); - yulAssert(literal, ""); - yulAssert(literal->value.value() <= std::numeric_limits::max(), ""); - _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); - } - )); - } + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal, ""); + yulAssert(literal->value.value() <= std::numeric_limits::max(), ""); + _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); + } + )); } + yulAssert( + ranges::all_of(builtins, [](std::optional const& _builtinFunction){ + return !_builtinFunction || _builtinFunction->name.substr(0, "verbatim_"s.size()) != "verbatim_"; + }), + "Builtin functions besides verbatim should not start with the verbatim_ prefix." + ); return builtins; } @@ -387,27 +405,58 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, std::optional m_functions(createBuiltins(_evmVersion, _eofVersion, _objectAccess)), m_reserved(createReservedIdentifiers(_evmVersion)) { + for (auto const& [index, maybeBuiltin]: m_functions | ranges::views::enumerate) + if (maybeBuiltin) + // ids are offset by the maximum number of verbatim functions + m_builtinFunctionsByName[maybeBuiltin->name] = BuiltinHandle{index + verbatimIdOffset}; + + m_discardFunction = findBuiltin("pop"); + m_equalityFunction = findBuiltin("eq"); + m_booleanNegationFunction = findBuiltin("iszero"); + m_memoryStoreFunction = findBuiltin("mstore"); + m_memoryLoadFunction = findBuiltin("mload"); + m_storageStoreFunction = findBuiltin("sstore"); + m_storageLoadFunction = findBuiltin("sload"); + m_hashFunction = findBuiltin("keccak256"); } -BuiltinFunctionForEVM const* EVMDialect::builtin(YulName _name) const +std::optional EVMDialect::findBuiltin(std::string_view _name) const { if (m_objectAccess) { std::smatch match; - if (regex_match(_name.str(), match, verbatimPattern())) + std::string name(_name); + if (regex_match(name, match, verbatimPattern())) return verbatimFunction(stoul(match[1]), stoul(match[2])); } - auto it = m_functions.find(_name); - if (it != m_functions.end()) - return &it->second; - else - return nullptr; + auto it = std::find_if(m_functions.begin(), m_functions.end(), [&_name](auto const& builtin) { return builtin && builtin.value().name == _name; }); + if (it != m_functions.end() && *it && it->value().name == _name) + // ids are offset by the maximum number of verbatim functions + return BuiltinHandle{static_cast(std::distance(m_functions.begin(), it)) + verbatimIdOffset}; + return std::nullopt; +} + +BuiltinFunctionForEVM const& EVMDialect::builtin(BuiltinHandle const& handle) const +{ + if (isVerbatimHandle(handle)) + { + yulAssert(handle.id < verbatimIDOffset); + auto const& verbatimFunctionPtr = m_verbatimFunctions[handle.id]; + yulAssert(verbatimFunctionPtr); + return *verbatimFunctionPtr; + } + + yulAssert(handle.id - verbatimIDOffset < m_functions.size()); + auto const& maybeBuiltin = m_functions[handle.id - verbatimIDOffset]; + yulAssert(maybeBuiltin.has_value()); + return *maybeBuiltin; } -bool EVMDialect::reservedIdentifier(YulName _name) const + +bool EVMDialect::reservedIdentifier(std::string_view _name) const { if (m_objectAccess) - if (_name.str().substr(0, "verbatim"s.size()) == "verbatim") + if (_name.substr(0, "verbatim"s.size()) == "verbatim") return true; return m_reserved.count(_name) != 0; } @@ -450,35 +499,49 @@ SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instructio }; } -BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVariables) const +BuiltinHandle EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVariables) const { - std::pair key{_arguments, _returnVariables}; - std::shared_ptr& function = m_verbatimFunctions[key]; - if (!function) - { - BuiltinFunctionForEVM builtinFunction = createFunction( - "verbatim_" + std::to_string(_arguments) + "i_" + std::to_string(_returnVariables) + "o", - 1 + _arguments, - _returnVariables, - SideEffects::worst(), - std::vector>{LiteralKind::String} + std::vector>(_arguments), - [=]( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == (1 + _arguments), ""); - Expression const& bytecode = _call.arguments.front(); - - _assembly.appendVerbatim( - asBytes(formatLiteral(std::get(bytecode))), - _arguments, - _returnVariables - ); - } - ).second; - builtinFunction.isMSize = true; - function = std::make_shared(std::move(builtinFunction)); - } - return function.get(); + auto const it = std::find_if(m_verbatimFunctions.begin(), m_verbatimFunctions.end(), [&](BuiltinFunctionForEVM const& _function) { + return _function.numParameters == 1 + _arguments && _function.numReturns == _returnVariables; + }); + yulAssert(_arguments <= verbatimMaxInputSlots); + yulAssert(_returnVariables <= verbatimMaxOutputSlots); + if (it != m_verbatimFunctions.end()) + return {static_cast(std::distance(m_verbatimFunctions.begin(), it))}; + + BuiltinFunctionForEVM builtinFunction = createFunction( + "verbatim_" + std::to_string(_arguments) + "i_" + std::to_string(_returnVariables) + "o", + 1 + _arguments, + _returnVariables, + SideEffects::worst(), + std::vector>{LiteralKind::String} + std::vector>(_arguments), + [=]( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == (1 + _arguments), ""); + Expression const& bytecode = _call.arguments.front(); + + _assembly.appendVerbatim( + asBytes(formatLiteral(std::get(bytecode))), + _arguments, + _returnVariables + ); + } + ); + builtinFunction.isMSize = true; + m_verbatimFunctions.push_back(std::move(builtinFunction)); + yulAssert(m_verbatimFunctions.size() <= verbatimIdOffset); + return {m_verbatimFunctions.size() - 1}; +} + +BuiltinFunctionForEVM const& EVMDialect::builtin(BuiltinHandle const& handle) const +{ + if (handle.id < verbatimIdOffset) + return m_verbatimFunctions.at(handle.id); + + auto const& maybeBuiltin = m_functions.at(handle.id - verbatimIdOffset); + yulAssert(maybeBuiltin.has_value()); + return *maybeBuiltin; } diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index cc064c3a0..45be636d8 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -62,25 +62,26 @@ struct BuiltinFunctionForEVM: public BuiltinFunction * The main difference is that the builtin functions take an AbstractAssembly for the * code generation. */ -struct EVMDialect: public Dialect +struct EVMDialect: Dialect { /// Constructor, should only be used internally. Use the factory functions below. EVMDialect(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess); - /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. - BuiltinFunctionForEVM const* builtin(YulName _name) const override; + std::optional findBuiltin(std::string_view _name) const override; + + BuiltinFunctionForEVM const& builtin(BuiltinHandle const& handle) const override; /// @returns true if the identifier is reserved. This includes the builtins too. - bool reservedIdentifier(YulName _name) const override; + bool reservedIdentifier(std::string_view _name) const override; - BuiltinFunctionForEVM const* discardFunction() const override { return builtin("pop"_yulname); } - BuiltinFunctionForEVM const* equalityFunction() const override { return builtin("eq"_yulname); } - BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("iszero"_yulname); } - BuiltinFunctionForEVM const* memoryStoreFunction() const override { return builtin("mstore"_yulname); } - BuiltinFunctionForEVM const* memoryLoadFunction() const override { return builtin("mload"_yulname); } - BuiltinFunctionForEVM const* storageStoreFunction() const override { return builtin("sstore"_yulname); } - BuiltinFunctionForEVM const* storageLoadFunction() const override { return builtin("sload"_yulname); } - YulName hashFunction() const override { return "keccak256"_yulname; } + std::optional discardFunction() const override { return m_discardFunction; } + std::optional equalityFunction() const override { return m_equalityFunction; } + std::optional booleanNegationFunction() const override { return m_booleanNegationFunction; } + std::optional memoryStoreFunction() const override { return m_memoryStoreFunction; } + std::optional memoryLoadFunction() const override { return m_memoryLoadFunction; } + std::optional storageStoreFunction() const override { return m_storageStoreFunction; } + std::optional storageLoadFunction() const override { return m_storageLoadFunction; } + std::optional hashFunction() const override { return m_hashFunction; } static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _evmVersion, std::optional _eofVersion); static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _evmVersion, std::optional _eofVersion); @@ -92,15 +93,28 @@ struct EVMDialect: public Dialect static SideEffects sideEffectsOfInstruction(evmasm::Instruction _instruction); + std::vector const& verbatimFunctions() const { return m_verbatimFunctions; } + protected: - BuiltinFunctionForEVM const* verbatimFunction(size_t _arguments, size_t _returnVariables) const; + BuiltinHandle verbatimFunction(size_t _arguments, size_t _returnVariables) const; + + static size_t constexpr verbatimIdOffset = verbatimMaxInputSlots * verbatimMaxOutputSlots; bool const m_objectAccess; langutil::EVMVersion const m_evmVersion; std::optional m_eofVersion; - std::map m_functions; - std::map, std::shared_ptr> mutable m_verbatimFunctions; - std::set m_reserved; + std::vector> m_functions; + std::vector mutable m_verbatimFunctions; + std::set> m_reserved; + + std::optional m_discardFunction; + std::optional m_equalityFunction; + std::optional m_booleanNegationFunction; + std::optional m_memoryStoreFunction; + std::optional m_memoryLoadFunction; + std::optional m_storageStoreFunction; + std::optional m_storageLoadFunction; + std::optional m_hashFunction; }; } diff --git a/libyul/backends/evm/EVMMetrics.cpp b/libyul/backends/evm/EVMMetrics.cpp index 539279bf2..64ff94cf6 100644 --- a/libyul/backends/evm/EVMMetrics.cpp +++ b/libyul/backends/evm/EVMMetrics.cpp @@ -76,10 +76,10 @@ std::pair GasMeterVisitor::instructionCosts( void GasMeterVisitor::operator()(FunctionCall const& _funCall) { ASTWalker::operator()(_funCall); - if (BuiltinFunctionForEVM const* f = m_dialect.builtin(_funCall.functionName.name)) - if (f->instruction) + if (std::optional handle = m_dialect.findBuiltin(_funCall.functionName.name.str())) + if (std::optional const& instruction = m_dialect.builtin(*handle).instruction) { - instructionCostsInternal(*f->instruction); + instructionCostsInternal(*instruction); return; } yulAssert(false, "Functions not implemented."); diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 9d8bd73a3..19d21bccd 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -139,11 +139,30 @@ NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom): { for (auto& fun: m_functions) { - size_t returns = fun.second.numReturns; - fun.second.generateCode = [=](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) + if (fun) + { + size_t returns = fun.value().numReturns; + fun.value().generateCode = [=](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) + { + for (size_t i: ranges::views::iota(0u, _call.arguments.size())) + if (!fun.value().literalArgument(i)) + _assembly.appendInstruction(evmasm::Instruction::POP); + + for (size_t i = 0; i < returns; i++) + _assembly.appendConstant(u256(0)); + }; + } + } + + m_verbatimFunctions = _copyFrom.verbatimFunctions(); + for (auto& entry: m_verbatimFunctions) + { + auto const& fun = entry; + auto returns = fun.numReturns; + entry.generateCode = [returns, fun](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) { for (size_t i: ranges::views::iota(0u, _call.arguments.size())) - if (!fun.second.literalArgument(i)) + if (!fun.literalArgument(i)) _assembly.appendInstruction(evmasm::Instruction::POP); for (size_t i = 0; i < returns; i++) diff --git a/libyul/backends/evm/SSAControlFlowGraph.cpp b/libyul/backends/evm/SSAControlFlowGraph.cpp index 35c9db0df..8e52e78e7 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.cpp +++ b/libyul/backends/evm/SSAControlFlowGraph.cpp @@ -147,7 +147,7 @@ class SSACFGPrinter return _call.function.get().name.str(); }, [&](SSACFG::BuiltinCall const& _call) { - return _call.builtin.get().name.str(); + return _call.builtin.get().name; }, }, operation.kind); if (!operation.outputs.empty()) diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 92b91e8ae..dacd06180 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -349,12 +349,12 @@ void SSAControlFlowGraphBuilder::operator()(Switch const& _switch) {*_case.value /* skip second argument */ } }); auto outputValue = m_graph.newVariable(m_currentBlock); - BuiltinFunction const* builtin = m_dialect.builtin(ghostCall.functionName.name); + std::optional builtinHandle = m_dialect.findBuiltin(ghostCall.functionName.name.str()); currentBlock().operations.emplace_back(SSACFG::Operation{ {outputValue}, SSACFG::BuiltinCall{ debugDataOf(_case), - *builtin, + m_dialect.builtin(*builtinHandle), ghostCall }, {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression} @@ -546,15 +546,16 @@ std::vector SSAControlFlowGraphBuilder::visitFunctionCall(Funct { bool canContinue = true; SSACFG::Operation operation = [&](){ - if (BuiltinFunction const* builtin = m_dialect.builtin(_call.functionName.name)) + if (std::optional const& builtinHandle = m_dialect.findBuiltin(_call.functionName.name.str())) { - SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData, *builtin, _call}, {}}; + auto const& builtinFunction = m_dialect.builtin(*builtinHandle); + SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData, builtinFunction, _call}, {}}; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) - if (!builtin->literalArgument(idx).has_value()) + if (!builtinFunction.literalArgument(idx).has_value()) result.inputs.emplace_back(std::visit(*this, arg)); - for (size_t i = 0; i < builtin->numReturns; ++i) + for (size_t i = 0; i < builtinFunction.numReturns; ++i) result.outputs.emplace_back(m_graph.newVariable(m_currentBlock)); - canContinue = builtin->controlFlowSideEffects.canContinue; + canContinue = builtinFunction.controlFlowSideEffects.canContinue; return result; } else diff --git a/libyul/optimiser/CommonSubexpressionEliminator.cpp b/libyul/optimiser/CommonSubexpressionEliminator.cpp index 073d621cc..f74568421 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.cpp +++ b/libyul/optimiser/CommonSubexpressionEliminator.cpp @@ -72,13 +72,14 @@ void CommonSubexpressionEliminator::visit(Expression& _e) { FunctionCall& funCall = std::get(_e); - if (BuiltinFunction const* builtin = m_dialect.builtin(funCall.functionName.name)) + if (std::optional builtinHandle = m_dialect.findBuiltin(funCall.functionName.name.str())) { + BuiltinFunction const& builtin = m_dialect.builtin(*builtinHandle); for (size_t i = funCall.arguments.size(); i > 0; i--) // We should not modify function arguments that have to be literals // Note that replacing the function call entirely is fine, // if the function call is movable. - if (!builtin->literalArgument(i - 1)) + if (!builtin.literalArgument(i - 1)) visit(funCall.arguments[i - 1]); descend = false; diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index c078885e8..478d7b9d9 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -43,7 +43,7 @@ ExpressionStatement makeDiscardCall( { return {_debugData, FunctionCall{ _debugData, - Identifier{_debugData, _discardFunction.name}, + Identifier{_debugData, YulName{_discardFunction.name}}, {std::move(_expression)} }}; } @@ -141,7 +141,7 @@ void ControlFlowSimplifier::simplify(std::vector& _statements) OptionalStatements s = std::vector{}; s->emplace_back(makeDiscardCall( _ifStmt.debugData, - *m_dialect.discardFunction(), + m_dialect.builtin(*m_dialect.discardFunction()), std::move(*_ifStmt.condition) )); return s; @@ -177,14 +177,14 @@ void ControlFlowSimplifier::simplify(std::vector& _statements) OptionalStatements ControlFlowSimplifier::reduceNoCaseSwitch(Switch& _switchStmt) const { yulAssert(_switchStmt.cases.empty(), "Expected no case!"); - BuiltinFunction const* discardFunction = + std::optional discardFunctionHandle = m_dialect.discardFunction(); - if (!discardFunction) + if (!discardFunctionHandle) return {}; return make_vector(makeDiscardCall( debugDataOf(*_switchStmt.expression), - *discardFunction, + m_dialect.builtin(*discardFunctionHandle), std::move(*_switchStmt.expression) )); } @@ -203,7 +203,7 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch std::move(_switchStmt.debugData), std::make_unique(FunctionCall{ debugData, - Identifier{debugData, m_dialect.equalityFunction()->name}, + Identifier{debugData, YulName{m_dialect.builtin(*m_dialect.equalityFunction()).name}}, {std::move(*switchCase.value), std::move(*_switchStmt.expression)} }), std::move(switchCase.body) @@ -217,7 +217,7 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch return make_vector( makeDiscardCall( debugData, - *m_dialect.discardFunction(), + m_dialect.builtin(*m_dialect.discardFunction()), std::move(*_switchStmt.expression) ), std::move(switchCase.body) diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index bf8952355..022ac199e 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -54,14 +54,14 @@ DataFlowAnalyzer::DataFlowAnalyzer( { if (m_analyzeStores) { - if (auto const* builtin = _dialect.memoryStoreFunction()) - m_storeFunctionName[static_cast(StoreLoadLocation::Memory)] = builtin->name; - if (auto const* builtin = _dialect.memoryLoadFunction()) - m_loadFunctionName[static_cast(StoreLoadLocation::Memory)] = builtin->name; - if (auto const* builtin = _dialect.storageStoreFunction()) - m_storeFunctionName[static_cast(StoreLoadLocation::Storage)] = builtin->name; - if (auto const* builtin = _dialect.storageLoadFunction()) - m_loadFunctionName[static_cast(StoreLoadLocation::Storage)] = builtin->name; + if (auto const& builtinHandle = _dialect.memoryStoreFunction()) + m_storeFunctionName[static_cast(StoreLoadLocation::Memory)] = YulName{_dialect.builtin(*builtinHandle).name}; + if (auto const& builtinHandle = _dialect.memoryLoadFunction()) + m_loadFunctionName[static_cast(StoreLoadLocation::Memory)] = YulName{_dialect.builtin(*builtinHandle).name}; + if (auto const& builtinHandle = _dialect.storageStoreFunction()) + m_storeFunctionName[static_cast(StoreLoadLocation::Storage)] = YulName{_dialect.builtin(*builtinHandle).name}; + if (auto const& builtinHandle = _dialect.storageLoadFunction()) + m_loadFunctionName[static_cast(StoreLoadLocation::Storage)] = YulName{_dialect.builtin(*builtinHandle).name}; } } @@ -446,7 +446,7 @@ std::optional DataFlowAnalyzer::isSimpleLoad( std::optional> DataFlowAnalyzer::isKeccak(Expression const& _expression) const { if (FunctionCall const* funCall = std::get_if(&_expression)) - if (funCall->functionName.name == m_dialect.hashFunction()) + if (funCall->functionName.name.str() == m_dialect.builtin(*m_dialect.hashFunction()).name) if (Identifier const* start = std::get_if(&funCall->arguments.at(0))) if (Identifier const* length = std::get_if(&funCall->arguments.at(1))) return std::make_pair(start->name, length->name); diff --git a/libyul/optimiser/Disambiguator.cpp b/libyul/optimiser/Disambiguator.cpp index 11325936c..55219f6ea 100644 --- a/libyul/optimiser/Disambiguator.cpp +++ b/libyul/optimiser/Disambiguator.cpp @@ -32,7 +32,7 @@ using namespace solidity::util; YulName Disambiguator::translateIdentifier(YulName _originalName) { - if (m_dialect.builtin(_originalName) || m_externallyUsedIdentifiers.count(_originalName)) + if (m_dialect.findBuiltin(_originalName.str()) || m_externallyUsedIdentifiers.count(_originalName)) return _originalName; assertThrow(!m_scopes.empty() && m_scopes.back(), OptimizerException, ""); diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 9f9bf958f..71a0963d5 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -41,10 +41,10 @@ void ExpressionSplitter::run(OptimiserStepContext& _context, Block& _ast) void ExpressionSplitter::operator()(FunctionCall& _funCall) { - BuiltinFunction const* builtin = m_dialect.builtin(_funCall.functionName.name); + std::optional builtinHandle = m_dialect.findBuiltin(_funCall.functionName.name.str()); for (size_t i = _funCall.arguments.size(); i > 0; i--) - if (!builtin || !builtin->literalArgument(i - 1)) + if (!builtinHandle || !m_dialect.builtin(*builtinHandle).literalArgument(i - 1)) outlineExpression(_funCall.arguments[i - 1]); } diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index d0839e765..b1f069e1b 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -47,7 +47,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) std::make_unique( FunctionCall { debugData, - {debugData, m_dialect.booleanNegationFunction()->name}, + {debugData, YulName{m_dialect.builtin(*m_dialect.booleanNegationFunction()).name}}, util::make_vector(std::move(*_forLoop.condition)) } ), diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.cpp b/libyul/optimiser/ForLoopConditionOutOfBody.cpp index afd005b71..0f6583285 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.cpp +++ b/libyul/optimiser/ForLoopConditionOutOfBody.cpp @@ -36,7 +36,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) ASTModifier::operator()(_forLoop); if ( - !m_dialect.booleanNegationFunction() || + !m_dialect.booleanNegationFunctionHandle() || !std::holds_alternative(*_forLoop.condition) || std::get(*_forLoop.condition).value.value() == 0 || _forLoop.body.statements.empty() || @@ -53,7 +53,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) if (!SideEffectsCollector(m_dialect, *firstStatement.condition).movable()) return; - YulName iszero = m_dialect.booleanNegationFunction()->name; + YulName const iszero = YulName{m_dialect.builtin(*m_dialect.booleanNegationFunctionHandle()).name}; langutil::DebugData::ConstPtr debugData = debugDataOf(*firstStatement.condition); if ( diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index c6387f808..df18a687f 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -131,7 +131,7 @@ std::map FullInliner::callDepths() const // Remove calls to builtin functions. for (auto& call: cg.functionCalls) for (auto it = call.second.begin(); it != call.second.end();) - if (m_dialect.builtin(*it)) + if (m_dialect.findBuiltin(it->str())) it = call.second.erase(it); else ++it; diff --git a/libyul/optimiser/FunctionSpecializer.cpp b/libyul/optimiser/FunctionSpecializer.cpp index cb7cd4164..bab02a2e1 100644 --- a/libyul/optimiser/FunctionSpecializer.cpp +++ b/libyul/optimiser/FunctionSpecializer.cpp @@ -55,7 +55,7 @@ void FunctionSpecializer::operator()(FunctionCall& _f) // TODO When backtracking is implemented, the restriction of recursive functions can be lifted. if ( - m_dialect.builtin(_f.functionName.name) || + m_dialect.findBuiltin(_f.functionName.name.str()) || m_recursiveFunctions.count(_f.functionName.name) ) return; diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index 98d938a36..9402bbfb3 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -62,7 +62,7 @@ void LoadResolver::visit(Expression& _e) tryResolve(_e, StoreLoadLocation::Memory, funCall->arguments); else if (funCall->functionName.name == m_loadFunctionName[static_cast(StoreLoadLocation::Storage)]) tryResolve(_e, StoreLoadLocation::Storage, funCall->arguments); - else if (!m_containsMSize && funCall->functionName.name == m_dialect.hashFunction()) + else if (!m_containsMSize && funCall->functionName.name.str() == m_dialect.builtin(*m_dialect.hashFunction()).name) { Identifier const* start = std::get_if(&funCall->arguments.at(0)); Identifier const* length = std::get_if(&funCall->arguments.at(1)); diff --git a/libyul/optimiser/NameSimplifier.cpp b/libyul/optimiser/NameSimplifier.cpp index d57a61332..6f3f1760a 100644 --- a/libyul/optimiser/NameSimplifier.cpp +++ b/libyul/optimiser/NameSimplifier.cpp @@ -67,7 +67,7 @@ void NameSimplifier::operator()(Identifier& _identifier) void NameSimplifier::operator()(FunctionCall& _funCall) { // The visitor on its own does not visit the function name. - if (!m_context.dialect.builtin(_funCall.functionName.name)) + if (!m_context.dialect.findBuiltin(_funCall.functionName.name.str())) (*this)(_funCall.functionName); ASTModifier::operator()(_funCall); } diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index 19f262060..001ff147d 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -57,14 +57,14 @@ void yul::removeEmptyBlocks(Block& _block) bool yul::isRestrictedIdentifier(Dialect const& _dialect, YulName const& _identifier) { - return _identifier.empty() || hasLeadingOrTrailingDot(_identifier.str()) || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier); + return _identifier.empty() || hasLeadingOrTrailingDot(_identifier.str()) || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier.str()); } std::optional yul::toEVMInstruction(Dialect const& _dialect, YulName const& _name) { if (auto const* dialect = dynamic_cast(&_dialect)) - if (BuiltinFunctionForEVM const* builtin = dialect->builtin(_name)) - return builtin->instruction; + if (std::optional const builtinHandle = dialect->findBuiltin(_name.str())) + return dialect->builtin(*builtinHandle).instruction; return std::nullopt; } diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index d945dbcac..5b5ad0eee 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -78,8 +78,8 @@ void SideEffectsCollector::operator()(FunctionCall const& _functionCall) ASTWalker::operator()(_functionCall); YulName functionName = _functionCall.functionName.name; - if (BuiltinFunction const* f = m_dialect.builtin(functionName)) - m_sideEffects += f->sideEffects; + if (std::optional builtinHandle = m_dialect.findBuiltin(functionName.str())) + m_sideEffects += m_dialect.builtin(*builtinHandle).sideEffects; else if (m_functionSideEffects && m_functionSideEffects->count(functionName)) m_sideEffects += m_functionSideEffects->at(functionName); else @@ -110,8 +110,8 @@ void MSizeFinder::operator()(FunctionCall const& _functionCall) { ASTWalker::operator()(_functionCall); - if (BuiltinFunction const* f = m_dialect.builtin(_functionCall.functionName.name)) - if (f->isMSize) + if (std::optional builtinHandle = m_dialect.findBuiltin(_functionCall.functionName.name.str())) + if (m_dialect.builtin(*builtinHandle).isMSize) m_msizeFound = true; } @@ -144,8 +144,8 @@ std::map SideEffectsPropagator::sideEffects( return; if (sideEffects == SideEffects::worst()) return; - if (BuiltinFunction const* f = _dialect.builtin(_function)) - sideEffects += f->sideEffects; + if (std::optional builtinHandle = _dialect.findBuiltin(_function.str())) + sideEffects += _dialect.builtin(*builtinHandle).sideEffects; else { if (ret.count(_function)) @@ -227,8 +227,8 @@ bool TerminationFinder::containsNonContinuingFunctionCall(Expression const& _exp if (containsNonContinuingFunctionCall(arg)) return true; - if (auto builtin = m_dialect.builtin(functionCall->functionName.name)) - return !builtin->controlFlowSideEffects.canContinue; + if (std::optional const builtinHandle = m_dialect.findBuiltin(functionCall->functionName.name.str())) + return !m_dialect.builtin(*builtinHandle).controlFlowSideEffects.canContinue; else if (m_functionSideEffects && m_functionSideEffects->count(functionCall->functionName.name)) return !m_functionSideEffects->at(functionCall->functionName.name).canContinue; } diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index 72c0f70ca..0fcd35bda 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -79,9 +79,9 @@ std::optional const*>> { if (std::holds_alternative(_expr)) if (auto const* dialect = dynamic_cast(&_dialect)) - if (auto const* builtin = dialect->builtin(std::get(_expr).functionName.name)) - if (builtin->instruction) - return std::make_pair(*builtin->instruction, &std::get(_expr).arguments); + if (std::optional const builtinHandle = dialect->findBuiltin(std::get(_expr).functionName.name.str())) + if (auto const& instruction = dialect->builtin(*builtinHandle).instruction) + return std::make_pair(*instruction, &std::get(_expr).arguments); return {}; } diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index 7e3f93475..4b242c82f 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -42,12 +42,12 @@ std::vector generateMemoryStore( Expression _value ) { - BuiltinFunction const* memoryStoreFunction = _dialect.memoryStoreFunction(); - yulAssert(memoryStoreFunction, ""); + std::optional memoryStoreFunctionHandle = _dialect.memoryStoreFunctionHandle(); + yulAssert(memoryStoreFunctionHandle); std::vector result; result.emplace_back(ExpressionStatement{_debugData, FunctionCall{ _debugData, - Identifier{_debugData, memoryStoreFunction->name}, + Identifier{_debugData, YulName{_dialect.builtin(*memoryStoreFunctionHandle).name}}, { Literal{_debugData, LiteralKind::Number, _mpos}, std::move(_value) @@ -58,11 +58,11 @@ std::vector generateMemoryStore( FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::ConstPtr const& _debugData, LiteralValue const& _mpos) { - BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(); - yulAssert(memoryLoadFunction, ""); + std::optional const& memoryLoadHandle = _dialect.memoryStoreFunctionHandle(); + yulAssert(memoryLoadHandle); return FunctionCall{ _debugData, - Identifier{_debugData, memoryLoadFunction->name}, { + Identifier{_debugData, YulName{_dialect.builtin(*memoryLoadHandle).name}}, { Literal{ _debugData, LiteralKind::Number, @@ -223,7 +223,7 @@ void StackToMemoryMover::operator()(Block& _block) { FunctionCall const* functionCall = std::get_if(_stmt.value.get()); yulAssert(functionCall, ""); - if (m_context.dialect.builtin(functionCall->functionName.name)) + if (m_context.dialect.findBuiltin(functionCall->functionName.name.str())) rhsMemorySlots = std::vector>(_lhsVars.size(), std::nullopt); else rhsMemorySlots = diff --git a/libyul/optimiser/UnusedAssignEliminator.cpp b/libyul/optimiser/UnusedAssignEliminator.cpp index 13a6ba9ee..eb639f8a6 100644 --- a/libyul/optimiser/UnusedAssignEliminator.cpp +++ b/libyul/optimiser/UnusedAssignEliminator.cpp @@ -79,8 +79,8 @@ void UnusedAssignEliminator::operator()(FunctionCall const& _functionCall) UnusedStoreBase::operator()(_functionCall); ControlFlowSideEffects sideEffects; - if (auto builtin = m_dialect.builtin(_functionCall.functionName.name)) - sideEffects = builtin->controlFlowSideEffects; + if (std::optional const builtinHandle = m_dialect.findBuiltin(_functionCall.functionName.name.str())) + sideEffects = m_dialect.builtin(*builtinHandle).controlFlowSideEffects; else sideEffects = m_controlFlowSideEffects.at(_functionCall.functionName.name); diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index 75cdd2dd1..a88000f09 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -94,7 +94,7 @@ void UnusedPruner::operator()(Block& _block) else if (varDecl.variables.size() == 1 && m_dialect.discardFunction()) statement = ExpressionStatement{varDecl.debugData, FunctionCall{ varDecl.debugData, - {varDecl.debugData, m_dialect.discardFunction()->name}, + {varDecl.debugData, YulName{m_dialect.builtin(*m_dialect.discardFunction()).name}}, {*std::move(varDecl.value)} }}; } diff --git a/libyul/optimiser/UnusedStoreEliminator.cpp b/libyul/optimiser/UnusedStoreEliminator.cpp index c50ddac14..f4f056697 100644 --- a/libyul/optimiser/UnusedStoreEliminator.cpp +++ b/libyul/optimiser/UnusedStoreEliminator.cpp @@ -114,8 +114,8 @@ void UnusedStoreEliminator::operator()(FunctionCall const& _functionCall) applyOperation(op); ControlFlowSideEffects sideEffects; - if (auto builtin = m_dialect.builtin(_functionCall.functionName.name)) - sideEffects = builtin->controlFlowSideEffects; + if (std::optional const builtinHandle = m_dialect.findBuiltin(_functionCall.functionName.name.str())) + sideEffects = m_dialect.builtin(*builtinHandle).controlFlowSideEffects; else sideEffects = m_controlFlowSideEffects.at(_functionCall.functionName.name); @@ -230,8 +230,8 @@ std::vector UnusedStoreEliminator::operationsF YulName functionName = _functionCall.functionName.name; SideEffects sideEffects; - if (BuiltinFunction const* f = m_dialect.builtin(functionName)) - sideEffects = f->sideEffects; + if (std::optional const builtinHandle = m_dialect.findBuiltin(functionName.str())) + sideEffects = m_dialect.builtin(*builtinHandle).sideEffects; else sideEffects = m_functionSideEffects.at(functionName); diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index d0850972b..d9ea91cbd 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -133,13 +133,21 @@ BOOST_AUTO_TEST_SUITE(YulParser) BOOST_AUTO_TEST_CASE(builtins_analysis) { - struct SimpleDialect: public Dialect + struct SimpleDialect: Dialect { - BuiltinFunction const* builtin(YulName _name) const override + std::optional findBuiltin(std::string_view _name) const override { - return _name == "builtin"_yulname ? &f : nullptr; + if (_name == "builtin") + return BuiltinHandle{std::numeric_limits::max()}; + return std::nullopt; } - BuiltinFunction f{"builtin"_yulname, 2, 3, {}, {}, false, {}}; + + BuiltinFunction const& builtin(BuiltinHandle const& handle) const override + { + BOOST_REQUIRE(handle.id == std::numeric_limits::max()); + return f; + } + BuiltinFunction f{"builtin", 2, 3, {}, {}, false, {}}; }; SimpleDialect dialect; diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index 6ac3cd1bd..b43021ea7 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -503,7 +503,7 @@ u256 EVMInstructionInterpreter::evalBuiltin( if (_fun.instruction) return eval(*_fun.instruction, _evaluatedArguments); - std::string fun = _fun.name.str(); + std::string const& fun = _fun.name; // Evaluate datasize/offset/copy instructions if (fun == "datasize" || fun == "dataoffset") { diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index 21e97f076..433ff3f07 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -309,25 +309,29 @@ void ExpressionEvaluator::operator()(Identifier const& _identifier) void ExpressionEvaluator::operator()(FunctionCall const& _funCall) { std::vector> const* literalArguments = nullptr; - if (BuiltinFunction const* builtin = m_dialect.builtin(_funCall.functionName.name)) - if (!builtin->literalArguments.empty()) - literalArguments = &builtin->literalArguments; + if (std::optional builtinHandle = m_dialect.findBuiltin(_funCall.functionName.name.str())) + if ( + auto const& args = m_dialect.builtin(*builtinHandle).literalArguments; + !args.empty() + ) + literalArguments = &args; evaluateArgs(_funCall.arguments, literalArguments); if (EVMDialect const* dialect = dynamic_cast(&m_dialect)) { - if (BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name)) + if (std::optional builtinHandle = dialect->findBuiltin(_funCall.functionName.name.str())) { + auto const& fun = dialect->builtin(*builtinHandle); EVMInstructionInterpreter interpreter(dialect->evmVersion(), m_state, m_disableMemoryTrace); - u256 const value = interpreter.evalBuiltin(*fun, _funCall.arguments, values()); + u256 const value = interpreter.evalBuiltin(fun, _funCall.arguments, values()); if ( !m_disableExternalCalls && - fun->instruction && - evmasm::isCallInstruction(*fun->instruction) + fun.instruction && + evmasm::isCallInstruction(*fun.instruction) ) - runExternalCall(*fun->instruction); + runExternalCall(*fun.instruction); setValue(value); return; From d8f69b90162ba3a65ad876a57e5449115ffb6d9b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 17 Oct 2024 09:26:14 +0200 Subject: [PATCH 0423/1340] Yul EVM Dialect: Use address table for verbatim functions --- libyul/Dialect.h | 8 +-- .../backends/evm/ControlFlowGraphBuilder.cpp | 3 +- libyul/backends/evm/EVMDialect.cpp | 49 +++++++++------ libyul/backends/evm/EVMDialect.h | 13 ++-- libyul/backends/evm/NoOutputAssembly.cpp | 59 ++++++++++--------- libyul/backends/evm/NoOutputAssembly.h | 5 +- 6 files changed, 81 insertions(+), 56 deletions(-) diff --git a/libyul/Dialect.h b/libyul/Dialect.h index a707771a2..20c2ae3f0 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -59,16 +59,16 @@ struct BuiltinFunction struct Dialect { - static size_t constexpr verbatimMaxInputSlots = 100; - static size_t constexpr verbatimMaxOutputSlots = 100; - /// Noncopiable. Dialect(Dialect const&) = delete; Dialect& operator=(Dialect const&) = delete; - /// @returns the builtin function of the given name or a null if it is not a builtin function. + /// Finds a builtin by name and returns the corresponding handle. + /// @returns Builtin handle or null if the name does not match any builtin in the dialect. virtual std::optional findBuiltin(std::string_view /*_name*/) const { return std::nullopt; } + /// Retrieves the description of a builtin function by its handle. + /// Note that handles are dialect-specific and can be used only with a dialect that created them. virtual BuiltinFunction const& builtin(BuiltinHandle const&) const { yulAssert(false); } /// @returns true if the identifier is reserved. This includes the builtins too. diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 1b523c4dd..4596b2252 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -360,10 +360,11 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) yul::Identifier{{}, "eq"_yulname}, {*_case.value, Identifier{{}, ghostVariableName}} }); + BuiltinFunction const& equalityBuiltin = m_dialect.builtin(*equalityBuiltinHandle); CFG::Operation& operation = m_currentBlock->operations.emplace_back(CFG::Operation{ Stack{ghostVarSlot, LiteralSlot{_case.value->value.value(), debugDataOf(*_case.value)}}, Stack{TemporarySlot{ghostCall, 0}}, - CFG::BuiltinCall{debugDataOf(_case), m_dialect.builtin(*equalityBuiltinHandle), ghostCall, 2}, + CFG::BuiltinCall{debugDataOf(_case), equalityBuiltin, ghostCall, 2}, }); return operation.output.front(); }; diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index e50e849d7..e9beabef6 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -45,6 +45,17 @@ using namespace solidity::util; namespace { +size_t constexpr toContinuousVerbatimIndex(size_t _arguments, size_t _returnVariables) +{ + return _arguments + _returnVariables * EVMDialect::verbatimMaxInputSlots; +} + +std::tuple constexpr verbatimIndexToArgsAndRets(size_t _index) +{ + size_t const numRets = _index / EVMDialect::verbatimMaxInputSlots; + return std::make_tuple(_index - numRets * EVMDialect::verbatimMaxInputSlots, numRets); +} + BuiltinFunctionForEVM createEVMFunction( langutil::EVMVersion _evmVersion, std::string const& _name, @@ -408,7 +419,7 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, std::optional for (auto const& [index, maybeBuiltin]: m_functions | ranges::views::enumerate) if (maybeBuiltin) // ids are offset by the maximum number of verbatim functions - m_builtinFunctionsByName[maybeBuiltin->name] = BuiltinHandle{index + verbatimIdOffset}; + m_builtinFunctionsByName[maybeBuiltin->name] = BuiltinHandle{index + verbatimIDOffset}; m_discardFunction = findBuiltin("pop"); m_equalityFunction = findBuiltin("eq"); @@ -499,16 +510,13 @@ SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instructio }; } -BuiltinHandle EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVariables) const +BuiltinFunctionForEVM EVMDialect::createVerbatimFunctionFromHandle(BuiltinHandle const& _handle) { - auto const it = std::find_if(m_verbatimFunctions.begin(), m_verbatimFunctions.end(), [&](BuiltinFunctionForEVM const& _function) { - return _function.numParameters == 1 + _arguments && _function.numReturns == _returnVariables; - }); - yulAssert(_arguments <= verbatimMaxInputSlots); - yulAssert(_returnVariables <= verbatimMaxOutputSlots); - if (it != m_verbatimFunctions.end()) - return {static_cast(std::distance(m_verbatimFunctions.begin(), it))}; + return std::apply(createVerbatimFunction, verbatimIndexToArgsAndRets(_handle.id)); +} +BuiltinFunctionForEVM EVMDialect::createVerbatimFunction(size_t _arguments, size_t _returnVariables) +{ BuiltinFunctionForEVM builtinFunction = createFunction( "verbatim_" + std::to_string(_arguments) + "i_" + std::to_string(_returnVariables) + "o", 1 + _arguments, @@ -531,17 +539,22 @@ BuiltinHandle EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVari } ); builtinFunction.isMSize = true; - m_verbatimFunctions.push_back(std::move(builtinFunction)); - yulAssert(m_verbatimFunctions.size() <= verbatimIdOffset); - return {m_verbatimFunctions.size() - 1}; + return builtinFunction; } -BuiltinFunctionForEVM const& EVMDialect::builtin(BuiltinHandle const& handle) const +BuiltinHandle EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVariables) const { - if (handle.id < verbatimIdOffset) - return m_verbatimFunctions.at(handle.id); + yulAssert(_arguments <= verbatimMaxInputSlots); + yulAssert(_returnVariables <= verbatimMaxOutputSlots); - auto const& maybeBuiltin = m_functions.at(handle.id - verbatimIdOffset); - yulAssert(maybeBuiltin.has_value()); - return *maybeBuiltin; + auto const verbatimIndex = toContinuousVerbatimIndex(_arguments, _returnVariables); + yulAssert(verbatimIndex < verbatimIDOffset); + + if ( + auto& backingData = m_verbatimFunctions[verbatimIndex]; + !backingData + ) + backingData = std::make_unique(createVerbatimFunction(_arguments, _returnVariables)); + + return {verbatimIndex}; } diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 45be636d8..b78486628 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -62,8 +62,9 @@ struct BuiltinFunctionForEVM: public BuiltinFunction * The main difference is that the builtin functions take an AbstractAssembly for the * code generation. */ -struct EVMDialect: Dialect +class EVMDialect: public Dialect { +public: /// Constructor, should only be used internally. Use the factory functions below. EVMDialect(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess); @@ -93,18 +94,22 @@ struct EVMDialect: Dialect static SideEffects sideEffectsOfInstruction(evmasm::Instruction _instruction); - std::vector const& verbatimFunctions() const { return m_verbatimFunctions; } + static size_t constexpr verbatimMaxInputSlots = 100; + static size_t constexpr verbatimMaxOutputSlots = 100; protected: + static bool constexpr isVerbatimHandle(BuiltinHandle const& _handle) { return _handle.id < verbatimIDOffset; } + static BuiltinFunctionForEVM createVerbatimFunctionFromHandle(BuiltinHandle const& _handle); + static BuiltinFunctionForEVM createVerbatimFunction(size_t _arguments, size_t _returnVariables); BuiltinHandle verbatimFunction(size_t _arguments, size_t _returnVariables) const; - static size_t constexpr verbatimIdOffset = verbatimMaxInputSlots * verbatimMaxOutputSlots; + static size_t constexpr verbatimIDOffset = verbatimMaxInputSlots * verbatimMaxOutputSlots; bool const m_objectAccess; langutil::EVMVersion const m_evmVersion; std::optional m_eofVersion; std::vector> m_functions; - std::vector mutable m_verbatimFunctions; + std::array, verbatimIDOffset> mutable m_verbatimFunctions{}; std::set> m_reserved; std::optional m_discardFunction; diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 19d21bccd..97bf962d0 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -33,6 +33,23 @@ using namespace solidity::yul; using namespace solidity::util; using namespace solidity::langutil; +namespace +{ + +void modifyBuiltinToNoOutput(BuiltinFunctionForEVM& _builtin) +{ + _builtin.generateCode = [fun=_builtin](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) + { + for (size_t i: ranges::views::iota(0u, _call.arguments.size())) + if (!fun.literalArgument(i)) + _assembly.appendInstruction(evmasm::Instruction::POP); + + for (size_t i = 0; i < fun.numReturns; i++) + _assembly.appendConstant(u256(0)); + }; +} + +} void NoOutputAssembly::appendInstruction(evmasm::Instruction _instr) { @@ -138,35 +155,21 @@ NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom): EVMDialect(_copyFrom.evmVersion(), _copyFrom.eofVersion(), _copyFrom.providesObjectAccess()) { for (auto& fun: m_functions) - { if (fun) - { - size_t returns = fun.value().numReturns; - fun.value().generateCode = [=](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) - { - for (size_t i: ranges::views::iota(0u, _call.arguments.size())) - if (!fun.value().literalArgument(i)) - _assembly.appendInstruction(evmasm::Instruction::POP); - - for (size_t i = 0; i < returns; i++) - _assembly.appendConstant(u256(0)); - }; - } - } + modifyBuiltinToNoOutput(*fun); +} - m_verbatimFunctions = _copyFrom.verbatimFunctions(); - for (auto& entry: m_verbatimFunctions) - { - auto const& fun = entry; - auto returns = fun.numReturns; - entry.generateCode = [returns, fun](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) +BuiltinFunctionForEVM const& NoOutputEVMDialect::builtin(BuiltinHandle const& _handle) const +{ + if (isVerbatimHandle(_handle)) + // for verbatims the modification is performed lazily as they are stored in a lookup table fashion + if ( + auto& builtin = m_verbatimFunctions[_handle.id]; + !builtin + ) { - for (size_t i: ranges::views::iota(0u, _call.arguments.size())) - if (!fun.literalArgument(i)) - _assembly.appendInstruction(evmasm::Instruction::POP); - - for (size_t i = 0; i < returns; i++) - _assembly.appendConstant(u256(0)); - }; - } + builtin = std::make_unique(createVerbatimFunctionFromHandle(_handle)); + modifyBuiltinToNoOutput(*builtin); + } + return EVMDialect::builtin(_handle); } diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h index 6d3aacb24..cc70d75af 100644 --- a/libyul/backends/evm/NoOutputAssembly.h +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -90,9 +90,12 @@ class NoOutputAssembly: public AbstractAssembly /** * EVM dialect that does not generate any code. */ -struct NoOutputEVMDialect: public EVMDialect +class NoOutputEVMDialect: public EVMDialect { +public: explicit NoOutputEVMDialect(EVMDialect const& _copyFrom); + + BuiltinFunctionForEVM const& builtin(BuiltinHandle const& _handle) const override; }; From 308827570328959e75c113201d91338f18da4614 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:06:05 +0200 Subject: [PATCH 0424/1340] Yul EVM Dialect: Helper map for builtin function lookup --- libyul/backends/evm/EVMDialect.cpp | 35 ++++++++++++++++-------------- libyul/backends/evm/EVMDialect.h | 3 ++- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index e9beabef6..e95e2246f 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -402,7 +402,7 @@ std::vector> createBuiltins(langutil::EVMVe std::regex const& verbatimPattern() { - std::regex static const pattern{"verbatim_([1-9]?[0-9])i_([1-9]?[0-9])o"}; + std::regex static const pattern{"([1-9]?[0-9])i_([1-9]?[0-9])o"}; return pattern; } @@ -433,32 +433,35 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, std::optional std::optional EVMDialect::findBuiltin(std::string_view _name) const { - if (m_objectAccess) + if (m_objectAccess && _name.substr(0, "verbatim_"s.size()) == "verbatim_") { std::smatch match; - std::string name(_name); + std::string name(_name.substr("verbatim_"s.size())); if (regex_match(name, match, verbatimPattern())) return verbatimFunction(stoul(match[1]), stoul(match[2])); } - auto it = std::find_if(m_functions.begin(), m_functions.end(), [&_name](auto const& builtin) { return builtin && builtin.value().name == _name; }); - if (it != m_functions.end() && *it && it->value().name == _name) - // ids are offset by the maximum number of verbatim functions - return BuiltinHandle{static_cast(std::distance(m_functions.begin(), it)) + verbatimIdOffset}; + + if ( + auto it = m_builtinFunctionsByName.find(_name); + it != m_builtinFunctionsByName.end() + ) + return it->second; + return std::nullopt; } -BuiltinFunctionForEVM const& EVMDialect::builtin(BuiltinHandle const& handle) const +BuiltinFunctionForEVM const& EVMDialect::builtin(BuiltinHandle const& _handle) const { - if (isVerbatimHandle(handle)) + if (isVerbatimHandle(_handle)) { - yulAssert(handle.id < verbatimIDOffset); - auto const& verbatimFunctionPtr = m_verbatimFunctions[handle.id]; + yulAssert(_handle.id < verbatimIDOffset); + auto const& verbatimFunctionPtr = m_verbatimFunctions[_handle.id]; yulAssert(verbatimFunctionPtr); return *verbatimFunctionPtr; } - yulAssert(handle.id - verbatimIDOffset < m_functions.size()); - auto const& maybeBuiltin = m_functions[handle.id - verbatimIDOffset]; + yulAssert(_handle.id - verbatimIDOffset < m_functions.size()); + auto const& maybeBuiltin = m_functions[_handle.id - verbatimIDOffset]; yulAssert(maybeBuiltin.has_value()); return *maybeBuiltin; } @@ -551,10 +554,10 @@ BuiltinHandle EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVari yulAssert(verbatimIndex < verbatimIDOffset); if ( - auto& backingData = m_verbatimFunctions[verbatimIndex]; - !backingData + auto& verbatimFunctionPtr = m_verbatimFunctions[verbatimIndex]; + !verbatimFunctionPtr ) - backingData = std::make_unique(createVerbatimFunction(_arguments, _returnVariables)); + verbatimFunctionPtr = std::make_unique(createVerbatimFunction(_arguments, _returnVariables)); return {verbatimIndex}; } diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index b78486628..f6ebb9340 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -70,7 +70,7 @@ class EVMDialect: public Dialect std::optional findBuiltin(std::string_view _name) const override; - BuiltinFunctionForEVM const& builtin(BuiltinHandle const& handle) const override; + BuiltinFunctionForEVM const& builtin(BuiltinHandle const& _handle) const override; /// @returns true if the identifier is reserved. This includes the builtins too. bool reservedIdentifier(std::string_view _name) const override; @@ -108,6 +108,7 @@ class EVMDialect: public Dialect bool const m_objectAccess; langutil::EVMVersion const m_evmVersion; std::optional m_eofVersion; + std::unordered_map m_builtinFunctionsByName; std::vector> m_functions; std::array, verbatimIDOffset> mutable m_verbatimFunctions{}; std::set> m_reserved; From 6a2631e02574a588eb3bac8305133750be9c568e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:50:33 +0200 Subject: [PATCH 0425/1340] Yul Dialect: Rename functions to function handles --- libyul/Dialect.h | 19 +++++++++---------- .../backends/evm/ControlFlowGraphBuilder.cpp | 2 +- libyul/backends/evm/EVMDialect.h | 17 ++++++++--------- libyul/backends/evm/EVMMetrics.h | 2 +- libyul/backends/evm/EVMObjectCompiler.h | 2 +- libyul/backends/evm/NoOutputAssembly.cpp | 6 +++--- libyul/optimiser/ControlFlowSimplifier.cpp | 14 +++++++------- libyul/optimiser/DataFlowAnalyzer.cpp | 10 +++++----- libyul/optimiser/ForLoopConditionIntoBody.cpp | 4 ++-- .../optimiser/ForLoopConditionOutOfBody.cpp | 2 +- libyul/optimiser/LoadResolver.cpp | 2 +- libyul/optimiser/Metrics.h | 2 +- libyul/optimiser/StackToMemoryMover.cpp | 2 +- libyul/optimiser/UnusedPruner.cpp | 4 ++-- 14 files changed, 43 insertions(+), 45 deletions(-) diff --git a/libyul/Dialect.h b/libyul/Dialect.h index 20c2ae3f0..62d18bdf0 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -74,16 +74,15 @@ struct Dialect /// @returns true if the identifier is reserved. This includes the builtins too. virtual bool reservedIdentifier(std::string_view _name) const { return findBuiltin(_name).has_value(); } - // todo these are handles, not functions - virtual std::optional discardFunction() const { return std::nullopt; } - virtual std::optional equalityFunction() const { return std::nullopt; } - virtual std::optional booleanNegationFunction() const { return std::nullopt; } - - virtual std::optional memoryStoreFunction() const { return std::nullopt; } - virtual std::optional memoryLoadFunction() const { return std::nullopt; } - virtual std::optional storageStoreFunction() const { return std::nullopt; } - virtual std::optional storageLoadFunction() const { return std::nullopt; } - virtual std::optional hashFunction() const { return std::nullopt; } + virtual std::optional discardFunctionHandle() const { return std::nullopt; } + virtual std::optional equalityFunctionHandle() const { return std::nullopt; } + virtual std::optional booleanNegationFunctionHandle() const { return std::nullopt; } + + virtual std::optional memoryStoreFunctionHandle() const { return std::nullopt; } + virtual std::optional memoryLoadFunctionHandle() const { return std::nullopt; } + virtual std::optional storageStoreFunctionHandle() const { return std::nullopt; } + virtual std::optional storageLoadFunctionHandle() const { return std::nullopt; } + virtual std::optional hashFunctionHandle() const { return std::nullopt; } Literal zeroLiteral() const; diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 4596b2252..fe6e0ec8e 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -349,7 +349,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) CFG::Assignment{_switch.debugData, {ghostVarSlot}} }); - std::optional const& equalityBuiltinHandle = m_dialect.equalityFunction(); + std::optional const& equalityBuiltinHandle = m_dialect.equalityFunctionHandle(); yulAssert(equalityBuiltinHandle); // Artificially generate: diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index f6ebb9340..1443b4481 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -72,17 +72,16 @@ class EVMDialect: public Dialect BuiltinFunctionForEVM const& builtin(BuiltinHandle const& _handle) const override; - /// @returns true if the identifier is reserved. This includes the builtins too. bool reservedIdentifier(std::string_view _name) const override; - std::optional discardFunction() const override { return m_discardFunction; } - std::optional equalityFunction() const override { return m_equalityFunction; } - std::optional booleanNegationFunction() const override { return m_booleanNegationFunction; } - std::optional memoryStoreFunction() const override { return m_memoryStoreFunction; } - std::optional memoryLoadFunction() const override { return m_memoryLoadFunction; } - std::optional storageStoreFunction() const override { return m_storageStoreFunction; } - std::optional storageLoadFunction() const override { return m_storageLoadFunction; } - std::optional hashFunction() const override { return m_hashFunction; } + std::optional discardFunctionHandle() const override { return m_discardFunction; } + std::optional equalityFunctionHandle() const override { return m_equalityFunction; } + std::optional booleanNegationFunctionHandle() const override { return m_booleanNegationFunction; } + std::optional memoryStoreFunctionHandle() const override { return m_memoryStoreFunction; } + std::optional memoryLoadFunctionHandle() const override { return m_memoryLoadFunction; } + std::optional storageStoreFunctionHandle() const override { return m_storageStoreFunction; } + std::optional storageLoadFunctionHandle() const override { return m_storageLoadFunction; } + std::optional hashFunctionHandle() const override { return m_hashFunction; } static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _evmVersion, std::optional _eofVersion); static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _evmVersion, std::optional _eofVersion); diff --git a/libyul/backends/evm/EVMMetrics.h b/libyul/backends/evm/EVMMetrics.h index b67cb77cd..1475246f1 100644 --- a/libyul/backends/evm/EVMMetrics.h +++ b/libyul/backends/evm/EVMMetrics.h @@ -29,7 +29,7 @@ namespace solidity::yul { -struct EVMDialect; +class EVMDialect; /** * Gas meter for expressions only involving literals, identifiers and diff --git a/libyul/backends/evm/EVMObjectCompiler.h b/libyul/backends/evm/EVMObjectCompiler.h index d37ade2cd..07ba34a75 100644 --- a/libyul/backends/evm/EVMObjectCompiler.h +++ b/libyul/backends/evm/EVMObjectCompiler.h @@ -28,7 +28,7 @@ namespace solidity::yul { struct Object; class AbstractAssembly; -struct EVMDialect; +class EVMDialect; class EVMObjectCompiler { diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 97bf962d0..5e82cc6fd 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -38,13 +38,13 @@ namespace void modifyBuiltinToNoOutput(BuiltinFunctionForEVM& _builtin) { - _builtin.generateCode = [fun=_builtin](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) + _builtin.generateCode = [_builtin](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) { for (size_t i: ranges::views::iota(0u, _call.arguments.size())) - if (!fun.literalArgument(i)) + if (!_builtin.literalArgument(i)) _assembly.appendInstruction(evmasm::Instruction::POP); - for (size_t i = 0; i < fun.numReturns; i++) + for (size_t i = 0; i < _builtin.numReturns; i++) _assembly.appendConstant(u256(0)); }; } diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index 478d7b9d9..a9a8282a6 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -136,12 +136,12 @@ void ControlFlowSimplifier::simplify(std::vector& _statements) GenericVisitor visitor{ VisitorFallback{}, [&](If& _ifStmt) -> OptionalStatements { - if (_ifStmt.body.statements.empty() && m_dialect.discardFunction()) + if (_ifStmt.body.statements.empty() && m_dialect.discardFunctionHandle()) { OptionalStatements s = std::vector{}; s->emplace_back(makeDiscardCall( _ifStmt.debugData, - m_dialect.builtin(*m_dialect.discardFunction()), + m_dialect.builtin(*m_dialect.discardFunctionHandle()), std::move(*_ifStmt.condition) )); return s; @@ -178,7 +178,7 @@ OptionalStatements ControlFlowSimplifier::reduceNoCaseSwitch(Switch& _switchStmt { yulAssert(_switchStmt.cases.empty(), "Expected no case!"); std::optional discardFunctionHandle = - m_dialect.discardFunction(); + m_dialect.discardFunctionHandle(); if (!discardFunctionHandle) return {}; @@ -197,13 +197,13 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch langutil::DebugData::ConstPtr debugData = debugDataOf(*_switchStmt.expression); if (switchCase.value) { - if (!m_dialect.equalityFunction()) + if (!m_dialect.equalityFunctionHandle()) return {}; return make_vector(If{ std::move(_switchStmt.debugData), std::make_unique(FunctionCall{ debugData, - Identifier{debugData, YulName{m_dialect.builtin(*m_dialect.equalityFunction()).name}}, + Identifier{debugData, YulName{m_dialect.builtin(*m_dialect.equalityFunctionHandle()).name}}, {std::move(*switchCase.value), std::move(*_switchStmt.expression)} }), std::move(switchCase.body) @@ -211,13 +211,13 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch } else { - if (!m_dialect.discardFunction()) + if (!m_dialect.discardFunctionHandle()) return {}; return make_vector( makeDiscardCall( debugData, - m_dialect.builtin(*m_dialect.discardFunction()), + m_dialect.builtin(*m_dialect.discardFunctionHandle()), std::move(*_switchStmt.expression) ), std::move(switchCase.body) diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 022ac199e..8b3282888 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -54,13 +54,13 @@ DataFlowAnalyzer::DataFlowAnalyzer( { if (m_analyzeStores) { - if (auto const& builtinHandle = _dialect.memoryStoreFunction()) + if (auto const& builtinHandle = _dialect.memoryStoreFunctionHandle()) m_storeFunctionName[static_cast(StoreLoadLocation::Memory)] = YulName{_dialect.builtin(*builtinHandle).name}; - if (auto const& builtinHandle = _dialect.memoryLoadFunction()) + if (auto const& builtinHandle = _dialect.memoryLoadFunctionHandle()) m_loadFunctionName[static_cast(StoreLoadLocation::Memory)] = YulName{_dialect.builtin(*builtinHandle).name}; - if (auto const& builtinHandle = _dialect.storageStoreFunction()) + if (auto const& builtinHandle = _dialect.storageStoreFunctionHandle()) m_storeFunctionName[static_cast(StoreLoadLocation::Storage)] = YulName{_dialect.builtin(*builtinHandle).name}; - if (auto const& builtinHandle = _dialect.storageLoadFunction()) + if (auto const& builtinHandle = _dialect.storageLoadFunctionHandle()) m_loadFunctionName[static_cast(StoreLoadLocation::Storage)] = YulName{_dialect.builtin(*builtinHandle).name}; } } @@ -446,7 +446,7 @@ std::optional DataFlowAnalyzer::isSimpleLoad( std::optional> DataFlowAnalyzer::isKeccak(Expression const& _expression) const { if (FunctionCall const* funCall = std::get_if(&_expression)) - if (funCall->functionName.name.str() == m_dialect.builtin(*m_dialect.hashFunction()).name) + if (funCall->functionName.name.str() == m_dialect.builtin(*m_dialect.hashFunctionHandle()).name) if (Identifier const* start = std::get_if(&funCall->arguments.at(0))) if (Identifier const* length = std::get_if(&funCall->arguments.at(1))) return std::make_pair(start->name, length->name); diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index b1f069e1b..7ee9a9b8c 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -33,7 +33,7 @@ void ForLoopConditionIntoBody::run(OptimiserStepContext& _context, Block& _ast) void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) { if ( - m_dialect.booleanNegationFunction() && + m_dialect.booleanNegationFunctionHandle() && !std::holds_alternative(*_forLoop.condition) && !std::holds_alternative(*_forLoop.condition) ) @@ -47,7 +47,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) std::make_unique( FunctionCall { debugData, - {debugData, YulName{m_dialect.builtin(*m_dialect.booleanNegationFunction()).name}}, + {debugData, YulName{m_dialect.builtin(*m_dialect.booleanNegationFunctionHandle()).name}}, util::make_vector(std::move(*_forLoop.condition)) } ), diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.cpp b/libyul/optimiser/ForLoopConditionOutOfBody.cpp index 0f6583285..d082bb78d 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.cpp +++ b/libyul/optimiser/ForLoopConditionOutOfBody.cpp @@ -53,7 +53,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) if (!SideEffectsCollector(m_dialect, *firstStatement.condition).movable()) return; - YulName const iszero = YulName{m_dialect.builtin(*m_dialect.booleanNegationFunctionHandle()).name}; + YulName const iszero{m_dialect.builtin(*m_dialect.booleanNegationFunctionHandle()).name}; langutil::DebugData::ConstPtr debugData = debugDataOf(*firstStatement.condition); if ( diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index 9402bbfb3..d6961b6f8 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -62,7 +62,7 @@ void LoadResolver::visit(Expression& _e) tryResolve(_e, StoreLoadLocation::Memory, funCall->arguments); else if (funCall->functionName.name == m_loadFunctionName[static_cast(StoreLoadLocation::Storage)]) tryResolve(_e, StoreLoadLocation::Storage, funCall->arguments); - else if (!m_containsMSize && funCall->functionName.name.str() == m_dialect.builtin(*m_dialect.hashFunction()).name) + else if (!m_containsMSize && funCall->functionName.name.str() == m_dialect.builtin(*m_dialect.hashFunctionHandle()).name) { Identifier const* start = std::get_if(&funCall->arguments.at(0)); Identifier const* length = std::get_if(&funCall->arguments.at(1)); diff --git a/libyul/optimiser/Metrics.h b/libyul/optimiser/Metrics.h index 01ab1adbd..53ff25325 100644 --- a/libyul/optimiser/Metrics.h +++ b/libyul/optimiser/Metrics.h @@ -28,7 +28,7 @@ namespace solidity::yul { struct Dialect; -struct EVMDialect; +class EVMDialect; /** * Weights to be assigned to specific yul statements and expressions by a metric. diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index 4b242c82f..e75472f06 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -58,7 +58,7 @@ std::vector generateMemoryStore( FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::ConstPtr const& _debugData, LiteralValue const& _mpos) { - std::optional const& memoryLoadHandle = _dialect.memoryStoreFunctionHandle(); + std::optional const& memoryLoadHandle = _dialect.memoryLoadFunctionHandle(); yulAssert(memoryLoadHandle); return FunctionCall{ _debugData, diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index a88000f09..9f6b88412 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -91,10 +91,10 @@ void UnusedPruner::operator()(Block& _block) subtractReferences(ReferencesCounter::countReferences(*varDecl.value)); statement = Block{std::move(varDecl.debugData), {}}; } - else if (varDecl.variables.size() == 1 && m_dialect.discardFunction()) + else if (varDecl.variables.size() == 1 && m_dialect.discardFunctionHandle()) statement = ExpressionStatement{varDecl.debugData, FunctionCall{ varDecl.debugData, - {varDecl.debugData, YulName{m_dialect.builtin(*m_dialect.discardFunction()).name}}, + {varDecl.debugData, YulName{m_dialect.builtin(*m_dialect.discardFunctionHandle()).name}}, {*std::move(varDecl.value)} }}; } From 752c26fbb2f461c311e8aea8381b6efc5091d6c1 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:03:18 +0200 Subject: [PATCH 0426/1340] Correct Yul test file extensions (#15527) Some test files in tests/libyul have a .sol file extension but are invalid Solidity code. Rename them to .yul. Command used: ```bash for f in $(fd -e sol . test/libyul); do mv $f $(basename $f .sol).yul; done ``` --- test/libyul/yulOptimizerTests/fullSuite/mcopy.sol => mcopy.yul | 0 .../mcopy_non_zero_size.sol => mcopy_non_zero_size.yul | 0 ...y_redundant_overwritten.sol => mcopy_redundant_overwritten.yul | 0 ...mcopy_redundant_same_area.sol => mcopy_redundant_same_area.yul | 0 ...mcopy_redundant_zero_size.sol => mcopy_redundant_zero_size.yul | 0 .../mcopy_zero_size.sol => mcopy_zero_size.yul | 0 .../fullInlinerWithoutSplitter/simple.sol => simple.yul | 0 ...rection_override.sol => unicode_comment_direction_override.yul | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename test/libyul/yulOptimizerTests/fullSuite/mcopy.sol => mcopy.yul (100%) rename test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.sol => mcopy_non_zero_size.yul (100%) rename test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_overwritten.sol => mcopy_redundant_overwritten.yul (100%) rename test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_same_area.sol => mcopy_redundant_same_area.yul (100%) rename test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_zero_size.sol => mcopy_redundant_zero_size.yul (100%) rename test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_zero_size.sol => mcopy_zero_size.yul (100%) rename test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.sol => simple.yul (100%) rename test/libyul/yulSyntaxTests/invalid/unicode_comment_direction_override.sol => unicode_comment_direction_override.yul (100%) diff --git a/test/libyul/yulOptimizerTests/fullSuite/mcopy.sol b/mcopy.yul similarity index 100% rename from test/libyul/yulOptimizerTests/fullSuite/mcopy.sol rename to mcopy.yul diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.sol b/mcopy_non_zero_size.yul similarity index 100% rename from test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.sol rename to mcopy_non_zero_size.yul diff --git a/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_overwritten.sol b/mcopy_redundant_overwritten.yul similarity index 100% rename from test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_overwritten.sol rename to mcopy_redundant_overwritten.yul diff --git a/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_same_area.sol b/mcopy_redundant_same_area.yul similarity index 100% rename from test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_same_area.sol rename to mcopy_redundant_same_area.yul diff --git a/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_zero_size.sol b/mcopy_redundant_zero_size.yul similarity index 100% rename from test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_zero_size.sol rename to mcopy_redundant_zero_size.yul diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_zero_size.sol b/mcopy_zero_size.yul similarity index 100% rename from test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_zero_size.sol rename to mcopy_zero_size.yul diff --git a/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.sol b/simple.yul similarity index 100% rename from test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.sol rename to simple.yul diff --git a/test/libyul/yulSyntaxTests/invalid/unicode_comment_direction_override.sol b/unicode_comment_direction_override.yul similarity index 100% rename from test/libyul/yulSyntaxTests/invalid/unicode_comment_direction_override.sol rename to unicode_comment_direction_override.yul From 4cebdc8bf53018d04b470d1f3fbacece761d6027 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 21 Oct 2024 14:52:29 +0200 Subject: [PATCH 0427/1340] Move Yul tests from root to test dir --- .../expressionSimplifier/mcopy_non_zero_size.yul | 0 .../yulOptimizerTests/expressionSimplifier/mcopy_zero_size.yul | 0 .../yulOptimizerTests/fullInlinerWithoutSplitter/simple.yul | 0 mcopy.yul => test/libyul/yulOptimizerTests/fullSuite/mcopy.yul | 0 .../yulOptimizerTests/fullSuite/mcopy_redundant_overwritten.yul | 0 .../yulOptimizerTests/fullSuite/mcopy_redundant_same_area.yul | 0 .../yulOptimizerTests/fullSuite/mcopy_redundant_zero_size.yul | 0 .../yulSyntaxTests/invalid/unicode_comment_direction_override.yul | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename mcopy_non_zero_size.yul => test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.yul (100%) rename mcopy_zero_size.yul => test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_zero_size.yul (100%) rename simple.yul => test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.yul (100%) rename mcopy.yul => test/libyul/yulOptimizerTests/fullSuite/mcopy.yul (100%) rename mcopy_redundant_overwritten.yul => test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_overwritten.yul (100%) rename mcopy_redundant_same_area.yul => test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_same_area.yul (100%) rename mcopy_redundant_zero_size.yul => test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_zero_size.yul (100%) rename unicode_comment_direction_override.yul => test/libyul/yulSyntaxTests/invalid/unicode_comment_direction_override.yul (100%) diff --git a/mcopy_non_zero_size.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.yul similarity index 100% rename from mcopy_non_zero_size.yul rename to test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.yul diff --git a/mcopy_zero_size.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_zero_size.yul similarity index 100% rename from mcopy_zero_size.yul rename to test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_zero_size.yul diff --git a/simple.yul b/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.yul similarity index 100% rename from simple.yul rename to test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.yul diff --git a/mcopy.yul b/test/libyul/yulOptimizerTests/fullSuite/mcopy.yul similarity index 100% rename from mcopy.yul rename to test/libyul/yulOptimizerTests/fullSuite/mcopy.yul diff --git a/mcopy_redundant_overwritten.yul b/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_overwritten.yul similarity index 100% rename from mcopy_redundant_overwritten.yul rename to test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_overwritten.yul diff --git a/mcopy_redundant_same_area.yul b/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_same_area.yul similarity index 100% rename from mcopy_redundant_same_area.yul rename to test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_same_area.yul diff --git a/mcopy_redundant_zero_size.yul b/test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_zero_size.yul similarity index 100% rename from mcopy_redundant_zero_size.yul rename to test/libyul/yulOptimizerTests/fullSuite/mcopy_redundant_zero_size.yul diff --git a/unicode_comment_direction_override.yul b/test/libyul/yulSyntaxTests/invalid/unicode_comment_direction_override.yul similarity index 100% rename from unicode_comment_direction_override.yul rename to test/libyul/yulSyntaxTests/invalid/unicode_comment_direction_override.yul From 5db362cd2190c411a73396746f1754115cf3f3f4 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 22 Oct 2024 09:11:05 +0200 Subject: [PATCH 0428/1340] eof: Add `auxdataloadn` to reserved identifiers. Move test to `eof` dir --- libyul/backends/evm/EVMDialect.cpp | 10 ++++++++-- test/libyul/objectCompiler/{ => eof}/dataloadn.yul | 0 2 files changed, 8 insertions(+), 2 deletions(-) rename test/libyul/objectCompiler/{ => eof}/dataloadn.yul (100%) diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index e95e2246f..1ed422551 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -118,7 +118,7 @@ BuiltinFunctionForEVM createFunction( return f; } -std::set> createReservedIdentifiers(langutil::EVMVersion _evmVersion) +std::set> createReservedIdentifiers(langutil::EVMVersion _evmVersion, std::optional _eofVersion) { // TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name // basefee for VMs before london. @@ -186,6 +186,12 @@ std::set> createReservedIdentifiers(langutil::EVMVersio "setimmutable", "loadimmutable", }; + + if (_eofVersion.has_value()) + reserved += std::vector{ + "auxdataloadn", + }; + return reserved; } @@ -414,7 +420,7 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, std::optional m_evmVersion(_evmVersion), m_eofVersion(_eofVersion), m_functions(createBuiltins(_evmVersion, _eofVersion, _objectAccess)), - m_reserved(createReservedIdentifiers(_evmVersion)) + m_reserved(createReservedIdentifiers(_evmVersion, _eofVersion)) { for (auto const& [index, maybeBuiltin]: m_functions | ranges::views::enumerate) if (maybeBuiltin) diff --git a/test/libyul/objectCompiler/dataloadn.yul b/test/libyul/objectCompiler/eof/dataloadn.yul similarity index 100% rename from test/libyul/objectCompiler/dataloadn.yul rename to test/libyul/objectCompiler/eof/dataloadn.yul From 9b329f4c651a1388919d0abdf6650eeb96cb3262 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 5 Jul 2024 11:09:20 +0200 Subject: [PATCH 0429/1340] SMTChecker: Fix formatting of negative numbers --- libsolidity/formal/ExpressionFormatter.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libsolidity/formal/ExpressionFormatter.cpp b/libsolidity/formal/ExpressionFormatter.cpp index 6571cf6dd..865a568f6 100644 --- a/libsolidity/formal/ExpressionFormatter.cpp +++ b/libsolidity/formal/ExpressionFormatter.cpp @@ -245,7 +245,14 @@ std::optional expressionToString(smtutil::Expression const& _expr, if (smt::isNumber(*_type)) { solAssert(_expr.sort->kind == Kind::Int); - solAssert(_expr.arguments.empty()); + solAssert(_expr.arguments.empty() || _expr.name == "-"); + if (_expr.name == "-") + { + solAssert(_expr.arguments.size() == 1); + smtutil::Expression const& val = _expr.arguments[0]; + solAssert(val.sort->kind == Kind::Int && val.arguments.empty()); + return "(- " + val.name + ")"; + } if ( _type->category() == frontend::Type::Category::Address || From 86b0b4833315c89377d258e9b4fad2a5383f0857 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 19 Jul 2024 10:37:03 +0200 Subject: [PATCH 0430/1340] SMTChecker: Hack to get around a bug in Z3 type printing --- libsolidity/formal/SymbolicTypes.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index f9ec9b011..f8e1ebbdc 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -29,6 +29,20 @@ using namespace solidity::util; using namespace solidity::smtutil; + +namespace +{ + // HACK to get around Z3 bug in printing type names with spaces (https://github.com/Z3Prover/z3/issues/6850) + // Should be fixed in Z3 4.13.0 + // TODO: Remove this afterwards + void sanitizeTypeName(std::string& name) + { + std::replace(name.begin(), name.end(), ' ', '_'); + std::replace(name.begin(), name.end(), '(', '['); + std::replace(name.begin(), name.end(), ')', ']'); + } +} + namespace solidity::frontend::smt { @@ -137,6 +151,7 @@ SortPointer smtSort(frontend::Type const& _type) else tupleName = _type.toString(true); + sanitizeTypeName(tupleName); tupleName += "_tuple"; return std::make_shared( @@ -148,7 +163,8 @@ SortPointer smtSort(frontend::Type const& _type) case Kind::Tuple: { std::vector members; - auto const& tupleName = _type.toString(true); + auto tupleName = _type.toString(true); + sanitizeTypeName(tupleName); std::vector sorts; if (auto const* tupleType = dynamic_cast(&_type)) From 8597223c6868cb387f5dc45227d86caab1d03b2c Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 2 Aug 2024 14:34:11 +0200 Subject: [PATCH 0431/1340] SMTChecker: Hack to make invariants more stable across platforms --- libsmtutil/CHCSmtLib2Interface.cpp | 9 ++- .../model_checker_invariants_all/err | 4 +- .../model_checker_invariants_contract/err | 2 +- .../err | 10 +-- .../input.sol | 7 +- .../model_checker_invariants_reentrancy/err | 2 +- .../output.json | 4 +- .../input.json | 5 +- .../output.json | 66 ++++++------------- .../input.json | 5 +- .../output.json | 24 +++---- 11 files changed, 56 insertions(+), 82 deletions(-) diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index d23249d22..4c6f2a60f 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -27,8 +27,9 @@ #include #include -#include #include +#include +#include #include #include @@ -450,6 +451,12 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp auto parsedInterpretation = scopedParser.toSMTUtilExpression(interpretation); + // Hack to make invariants more stable across operating systems + if (parsedInterpretation.name == "and" || parsedInterpretation.name == "or") + ranges::sort(parsedInterpretation.arguments, [](Expression const& first, Expression const& second) { + return first.name < second.name; + }); + Expression predicate(asAtom(args[1]), predicateArgs, SortProvider::boolSort); definitions.push_back(predicate == parsedInterpretation); } diff --git a/test/cmdlineTests/model_checker_invariants_all/err b/test/cmdlineTests/model_checker_invariants_all/err index 7ec97678e..cd133dab0 100644 --- a/test/cmdlineTests/model_checker_invariants_all/err +++ b/test/cmdlineTests/model_checker_invariants_all/err @@ -7,8 +7,8 @@ Warning: Return value of low-level calls not used. Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Info: Contract invariant(s) for model_checker_invariants_all/input.sol:test: -(!(x >= 1) || true) +(true || !(x >= 1)) Reentrancy property(ies) for model_checker_invariants_all/input.sol:test: -(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors = 1 -> Assertion failed at assert(x == 0) diff --git a/test/cmdlineTests/model_checker_invariants_contract/err b/test/cmdlineTests/model_checker_invariants_contract/err index f6b01e9b2..3ecad6b35 100644 --- a/test/cmdlineTests/model_checker_invariants_contract/err +++ b/test/cmdlineTests/model_checker_invariants_contract/err @@ -1,4 +1,4 @@ Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Info: Contract invariant(s) for model_checker_invariants_contract/input.sol:test: -(!(x >= 1) || true) +(true || !(x >= 1)) diff --git a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err index 11ee3a702..7764e89ab 100644 --- a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err +++ b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err @@ -1,14 +1,8 @@ -Warning: Return value of low-level calls not used. - --> model_checker_invariants_contract_reentrancy/input.sol:6:3: - | -6 | _a.call(""); - | ^^^^^^^^^^^ - Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Info: Contract invariant(s) for model_checker_invariants_contract_reentrancy/input.sol:test: -(!(x >= 1) || true) +(true || !(x >= 1)) Reentrancy property(ies) for model_checker_invariants_contract_reentrancy/input.sol:test: -(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors = 1 -> Assertion failed at assert(x == 0) diff --git a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/input.sol b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/input.sol index 8b90cb3c1..e75a75b5f 100644 --- a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/input.sol +++ b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/input.sol @@ -2,8 +2,7 @@ pragma solidity >=0.0; contract test { uint x; - function f(address _a) public { - _a.call(""); + function f() public view { assert(x == 0); - } -} \ No newline at end of file + } +} diff --git a/test/cmdlineTests/model_checker_invariants_reentrancy/err b/test/cmdlineTests/model_checker_invariants_reentrancy/err index 68ef6404c..78cca4390 100644 --- a/test/cmdlineTests/model_checker_invariants_reentrancy/err +++ b/test/cmdlineTests/model_checker_invariants_reentrancy/err @@ -7,6 +7,6 @@ Warning: Return value of low-level calls not used. Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Info: Reentrancy property(ies) for model_checker_invariants_reentrancy/input.sol:test: -(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors = 1 -> Assertion failed at assert(x < 10) diff --git a/test/cmdlineTests/standard_model_checker_invariants_contract/output.json b/test/cmdlineTests/standard_model_checker_invariants_contract/output.json index f3cd0758c..09d392567 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_contract/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_contract/output.json @@ -14,12 +14,12 @@ "component": "general", "errorCode": "1180", "formattedMessage": "Info: Contract invariant(s) for A:test: -(!(x >= 1) || true) +(true || !(x >= 1)) ", "message": "Contract invariant(s) for A:test: -(!(x >= 1) || true) +(true || !(x >= 1)) ", "severity": "info", "type": "Info" diff --git a/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/input.json b/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/input.json index 38f658653..e4c7c7bd0 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/input.json +++ b/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/input.json @@ -6,9 +6,8 @@ { "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n\ncontract test { uint x; - function f(address _a) public { - _a.call(\"\"); - assert(x == 10); + function f() view public { + assert(x == 0); } }" } diff --git a/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json b/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json index d46fdda8a..b51effdcb 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_contract_reentrancy/output.json @@ -2,59 +2,35 @@ "errors": [ { "component": "general", - "errorCode": "9302", - "formattedMessage": "Warning: Return value of low-level calls not used. - --> A:7:7: - | -7 | \t\t\t\t\t\t_a.call(\"\"); - | \t\t\t\t\t\t^^^^^^^^^^^ + "errorCode": "1391", + "formattedMessage": "Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "Return value of low-level calls not used.", - "severity": "warning", - "sourceLocation": { - "end": 143, - "file": "A", - "start": 132 - }, - "type": "Warning" + "message": "CHC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" }, { "component": "general", - "errorCode": "6328", - "formattedMessage": "Warning: CHC: Assertion violation happens here. -Counterexample: -x = 0 -_a = 0x0 + "errorCode": "1180", + "formattedMessage": "Info: Contract invariant(s) for A:test: +(true || !(x >= 1)) +Reentrancy property(ies) for A:test: +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) + = 0 -> no errors + = 1 -> Assertion failed at assert(x == 0) -Transaction trace: -test.constructor() -State: x = 0 -test.f(0x0) - _a.call(\"\") -- untrusted external call - --> A:8:7: - | -8 | \t\t\t\t\t\tassert(x == 10); - | \t\t\t\t\t\t^^^^^^^^^^^^^^^ ", - "message": "CHC: Assertion violation happens here. -Counterexample: -x = 0 -_a = 0x0 - -Transaction trace: -test.constructor() -State: x = 0 -test.f(0x0) - _a.call(\"\") -- untrusted external call", - "severity": "warning", - "sourceLocation": { - "end": 166, - "file": "A", - "start": 151 - }, - "type": "Warning" + "message": "Contract invariant(s) for A:test: +(true || !(x >= 1)) +Reentrancy property(ies) for A:test: +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) + = 0 -> no errors + = 1 -> Assertion failed at assert(x == 0) +", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/input.json b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/input.json index 1f98000b0..2a3673fad 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/input.json +++ b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/input.json @@ -6,9 +6,8 @@ { "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n\ncontract test { uint x; - function f(address _a) public { - _a.call(\"\"); - assert(x < 10); + function f() public { + assert(x == 0); } }" } diff --git a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json index 760f1d7a7..f1f37340e 100644 --- a/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json +++ b/test/cmdlineTests/standard_model_checker_invariants_reentrancy/output.json @@ -2,20 +2,20 @@ "errors": [ { "component": "general", - "errorCode": "9302", - "formattedMessage": "Warning: Return value of low-level calls not used. - --> A:7:7: + "errorCode": "2018", + "formattedMessage": "Warning: Function state mutability can be restricted to view + --> A:6:6: | -7 | \t\t\t\t\t\t_a.call(\"\"); - | \t\t\t\t\t\t^^^^^^^^^^^ +6 | \t\t\t\t\tfunction f() public { + | \t\t\t\t\t^ (Relevant source part starts here and spans across multiple lines). ", - "message": "Return value of low-level calls not used.", + "message": "Function state mutability can be restricted to view", "severity": "warning", "sourceLocation": { - "end": 143, + "end": 144, "file": "A", - "start": 132 + "start": 94 }, "type": "Warning" }, @@ -33,16 +33,16 @@ "component": "general", "errorCode": "1180", "formattedMessage": "Info: Reentrancy property(ies) for A:test: -(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors - = 1 -> Assertion failed at assert(x < 10) + = 1 -> Assertion failed at assert(x == 0) ", "message": "Reentrancy property(ies) for A:test: -(((!(x <= 0) || !( >= 1)) && (!(x <= 0) || !(x' >= 1))) || true) +((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors - = 1 -> Assertion failed at assert(x < 10) + = 1 -> Assertion failed at assert(x == 0) ", "severity": "info", "type": "Info" From 436f6066d2dabd8da141df1fc04bb8f8ee6af982 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 3 Jul 2024 18:04:59 +0200 Subject: [PATCH 0432/1340] SMTChecker: Switch to Z3 SMTLIB interface Instead of interacting with Z3 via its API, we switch to the interaction using our SMT-LIB interface. An exception is the emscripten build, where we keep including Z3. This is for users' convenience. --- CMakeLists.txt | 8 ++ libsmtutil/CHCSmtLib2Interface.cpp | 1 - libsmtutil/CMakeLists.txt | 2 +- libsmtutil/SMTLib2Interface.h | 2 +- libsolidity/CMakeLists.txt | 4 + libsolidity/formal/BMC.cpp | 10 +-- libsolidity/formal/CHC.cpp | 87 +++++-------------- libsolidity/formal/ModelChecker.cpp | 9 +- libsolidity/formal/Z3CHCSmtLib2Interface.cpp | 29 +++++++ libsolidity/formal/Z3SMTLib2Interface.cpp | 25 ++++++ libsolidity/formal/Z3SMTLib2Interface.h | 1 + .../model_checker_divModSlacks_false_all/err | 12 --- .../model_checker_divModSlacks_false_chc/err | 12 --- .../model_checker_invariants_all/err | 6 -- .../model_checker_invariants_all/input.sol | 7 +- .../input.sol | 8 +- .../model_checker_invariants_reentrancy/err | 8 +- .../input.sol | 9 +- .../output.json | 38 -------- .../output.json | 38 -------- .../abi_encode_with_selector_array_slice.sol | 5 +- ...abi_encode_with_selector_array_slice_2.sol | 7 +- .../abi/abi_encode_with_selector_vs_sig.sol | 2 +- .../abi/abi_encode_with_sig_array_slice.sol | 10 ++- .../abi/abi_encode_with_sig_array_slice_2.sol | 10 ++- .../external_calls/call_with_value_1.sol | 7 +- .../external_calls/call_with_value_2.sol | 6 +- .../external_calls/external.sol | 8 +- .../external_call_indirect_1.sol | 3 +- .../external_call_indirect_2.sol | 3 +- .../external_call_indirect_3.sol | 1 + .../external_call_with_value_2.sol | 6 +- .../external_call_with_value_3.sol | 9 +- ...nal_hash_known_code_state_reentrancy_3.sol | 3 +- ...sh_known_code_state_reentrancy_trusted.sol | 4 +- .../external_calls/external_safe.sol | 4 +- .../operators/index_access_for_bytesNN.sol | 4 +- .../operators/index_access_side_effect.sol | 3 +- ...rator_matches_equivalent_function_call.sol | 4 +- .../out_of_bounds/array_2d_4.sol | 10 +-- .../types/array_mapping_aliasing_2.sol | 13 +-- .../types/struct_array_branches_2d.sol | 5 +- 42 files changed, 178 insertions(+), 265 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b78269a3d..a0a8313b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,6 +144,14 @@ if (NOT (${Z3_FOUND} OR CVC5_PATH)) \nPlease install Z3 or cvc5 or remove the option disabling them (USE_Z3).") endif() +if(EMSCRIPTEN) + if(${Z3_FOUND}) + add_definitions(-DEMSCRIPTEN_BUILD) + else() + message(FATAL_ERROR "Solidity requires Z3 for emscripten build.") + endif() +endif() + add_subdirectory(libsolutil) add_subdirectory(liblangutil) add_subdirectory(libsmtutil) diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index 4c6f2a60f..02257031a 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -28,7 +28,6 @@ #include #include -#include #include #include diff --git a/libsmtutil/CMakeLists.txt b/libsmtutil/CMakeLists.txt index c89c56f4f..2bd870549 100644 --- a/libsmtutil/CMakeLists.txt +++ b/libsmtutil/CMakeLists.txt @@ -17,7 +17,7 @@ set(sources ) if (${Z3_FOUND}) - set(z3_SRCS Z3Interface.cpp Z3Interface.h Z3CHCInterface.cpp Z3CHCInterface.h) + set(z3_SRCS) else() set(z3_SRCS) endif() diff --git a/libsmtutil/SMTLib2Interface.h b/libsmtutil/SMTLib2Interface.h index 02b1c85ff..fe5421acd 100644 --- a/libsmtutil/SMTLib2Interface.h +++ b/libsmtutil/SMTLib2Interface.h @@ -105,7 +105,7 @@ class SMTLib2Interface: public BMCSolverInterface std::string checkSatAndGetValuesCommand(std::vector const& _expressionsToEvaluate); /// Communicates with the solver via the callback. Throws SMTSolverError on error. - std::string querySolver(std::string const& _input); + virtual std::string querySolver(std::string const& _input); SMTLib2Commands m_commands; SMTLib2Context m_context; diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 0b796035d..1c4c48090 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -141,6 +141,10 @@ set(sources formal/SymbolicVariables.h formal/VariableUsage.cpp formal/VariableUsage.h + formal/Z3CHCSmtLib2Interface.cpp + formal/Z3CHCSmtLib2Interface.h + formal/Z3SMTLib2Interface.cpp + formal/Z3SMTLib2Interface.h interface/ABI.cpp interface/ABI.h interface/CompilerStack.cpp diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index fda573d3d..a7f792453 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -20,12 +20,10 @@ #include #include +#include #include #include -#ifdef HAVE_Z3 -#include -#endif #include #include @@ -61,10 +59,8 @@ BMC::BMC( solvers.emplace_back(std::make_unique(_smtlib2Responses, _smtCallback, _settings.timeout)); if (_settings.solvers.cvc5) solvers.emplace_back(std::make_unique(_smtCallback, _settings.timeout)); -#ifdef HAVE_Z3 - if (_settings.solvers.z3 && Z3Interface::available()) - solvers.emplace_back(std::make_unique(_settings.timeout)); -#endif + if (_settings.solvers.z3 ) + solvers.emplace_back(std::make_unique(_smtCallback, _settings.timeout)); m_interface = std::make_unique(std::move(solvers), _settings.timeout); #if defined (HAVE_Z3) if (m_settings.solvers.z3) diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index c52a83a26..7f413f91a 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -18,18 +18,14 @@ #include -#include - -#ifdef HAVE_Z3 -#include -#endif - #include #include #include +#include #include #include #include +#include #include @@ -38,10 +34,6 @@ #include #include -#ifdef HAVE_Z3_DLOPEN -#include -#endif - #include #include @@ -1279,41 +1271,29 @@ void CHC::resetSourceAnalysis() ArraySlicePredicate::reset(); m_blockCounter = 0; - // At this point every enabled solver is available. - // If more than one Horn solver is selected we go with z3. - // We still need the ifdef because of Z3CHCInterface. - if (m_settings.solvers.z3) + solAssert(m_settings.solvers.smtlib2 || m_settings.solvers.eld || m_settings.solvers.z3); + if (!m_interface) { -#ifdef HAVE_Z3 - // z3::fixedpoint does not have a reset mechanism, so we need to create another. - m_interface = std::make_unique(m_settings.timeout); - auto z3Interface = dynamic_cast(m_interface.get()); - solAssert(z3Interface, ""); - m_context.setSolver(z3Interface->z3Interface()); -#else - solAssert(false); -#endif + if (m_settings.solvers.z3) + m_interface = std::make_unique( + m_smtCallback, + m_settings.timeout, + m_settings.invariants != ModelCheckerInvariants::None() + ); + else if (m_settings.solvers.eld) + m_interface = std::make_unique( + m_smtCallback, + m_settings.timeout, + m_settings.invariants != ModelCheckerInvariants::None() + ); + else + m_interface = std::make_unique(m_smtlib2Responses, m_smtCallback, m_settings.timeout); } - else - { - solAssert(m_settings.solvers.smtlib2 || m_settings.solvers.eld); - if (!m_interface) - { - if (m_settings.solvers.eld) - m_interface = std::make_unique( - m_smtCallback, - m_settings.timeout, - m_settings.invariants != ModelCheckerInvariants::None() - ); - else - m_interface = std::make_unique(m_smtlib2Responses, m_smtCallback, m_settings.timeout); - } - auto smtlib2Interface = dynamic_cast(m_interface.get()); - solAssert(smtlib2Interface); - smtlib2Interface->reset(); - m_context.setSolver(smtlib2Interface); - } + auto smtlib2Interface = dynamic_cast(m_interface.get()); + solAssert(smtlib2Interface); + smtlib2Interface->reset(); + m_context.setSolver(smtlib2Interface); m_context.reset(); m_context.resetUniqueId(); @@ -1932,29 +1912,6 @@ CHCSolverInterface::QueryResult CHC::query(smtutil::Expression const& _query, la switch (result.answer) { case CheckResult::SATISFIABLE: - { - // We still need the ifdef because of Z3CHCInterface. - if (m_settings.solvers.z3) - { -#ifdef HAVE_Z3 - // Even though the problem is SAT, Spacer's pre processing makes counterexamples incomplete. - // We now disable those optimizations and check whether we can still solve the problem. - auto* spacer = dynamic_cast(m_interface.get()); - solAssert(spacer, ""); - spacer->setSpacerOptions(false); - - auto resultNoOpt = m_interface->query(_query); - - if (resultNoOpt.answer == CheckResult::SATISFIABLE) - result.cex = std::move(resultNoOpt.cex); - - spacer->setSpacerOptions(true); -#else - solAssert(false); -#endif - } - break; - } case CheckResult::UNSATISFIABLE: case CheckResult::UNKNOWN: break; diff --git a/libsolidity/formal/ModelChecker.cpp b/libsolidity/formal/ModelChecker.cpp index 91b88cb9c..6368dc1ea 100644 --- a/libsolidity/formal/ModelChecker.cpp +++ b/libsolidity/formal/ModelChecker.cpp @@ -17,9 +17,6 @@ // SPDX-License-Identifier: GPL-3.0 #include -#ifdef HAVE_Z3 -#include -#endif #ifdef HAVE_Z3_DLOPEN #include #endif @@ -170,8 +167,10 @@ SMTSolverChoice ModelChecker::availableSolvers() smtutil::SMTSolverChoice available = smtutil::SMTSolverChoice::SMTLIB2(); available.eld = !boost::process::search_path("eld").empty(); available.cvc5 = !boost::process::search_path("cvc5").empty(); -#ifdef HAVE_Z3 - available.z3 = solidity::smtutil::Z3Interface::available(); +#ifdef EMSCRIPTEN_BUILD + available.z3 = true; +#else + available.z3 = !boost::process::search_path("z3").empty(); #endif return available; } diff --git a/libsolidity/formal/Z3CHCSmtLib2Interface.cpp b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp index d8448fc0b..a3aef325b 100644 --- a/libsolidity/formal/Z3CHCSmtLib2Interface.cpp +++ b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp @@ -26,6 +26,10 @@ #include +#ifdef EMSCRIPTEN_BUILD +#include +#endif + using namespace solidity::frontend::smt; using namespace solidity::smtutil; @@ -35,6 +39,17 @@ Z3CHCSmtLib2Interface::Z3CHCSmtLib2Interface( bool _computeInvariants ): CHCSmtLib2Interface({}, std::move(_smtCallback), _queryTimeout), m_computeInvariants(_computeInvariants) { +#ifdef EMSCRIPTEN_BUILD + constexpr int resourceLimit = 2000000; + if (m_queryTimeout) + z3::set_param("timeout", int(*m_queryTimeout)); + else + z3::set_param("rlimit", resourceLimit); + z3::set_param("rewriter.pull_cheap_ite", true); + z3::set_param("fp.spacer.q3.use_qgen", true); + z3::set_param("fp.spacer.mbqi", false); + z3::set_param("fp.spacer.ground_pobs", false); +#endif } void Z3CHCSmtLib2Interface::setupSmtCallback(bool _enablePreprocessing) @@ -47,7 +62,14 @@ CHCSolverInterface::QueryResult Z3CHCSmtLib2Interface::query(smtutil::Expression { setupSmtCallback(true); std::string query = dumpQuery(_block); +#ifdef EMSCRIPTEN_BUILD + z3::set_param("fp.xform.slice", true); + z3::set_param("fp.xform.inline_linear", true); + z3::set_param("fp.xform.inline_eager", true); + std::string response = Z3_eval_smtlib2_string(z3::context{}, query.c_str()); +#else std::string response = querySolver(query); +#endif // NOTE: Our internal semantics is UNSAT -> SAFE and SAT -> UNSAFE, which corresponds to usual SMT-based model checking // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. // So we have to flip the answer. @@ -56,7 +78,14 @@ CHCSolverInterface::QueryResult Z3CHCSmtLib2Interface::query(smtutil::Expression // Repeat the query with preprocessing disabled, to get the full proof setupSmtCallback(false); query = "(set-option :produce-proofs true)" + query + "\n(get-proof)"; +#ifdef EMSCRIPTEN_BUILD + z3::set_param("fp.xform.slice", false); + z3::set_param("fp.xform.inline_linear", false); + z3::set_param("fp.xform.inline_eager", false); + response = Z3_eval_smtlib2_string(z3::context{}, query.c_str()); +#else response = querySolver(query); +#endif setupSmtCallback(true); if (!boost::starts_with(response, "unsat")) return {CheckResult::SATISFIABLE, Expression(true), {}}; diff --git a/libsolidity/formal/Z3SMTLib2Interface.cpp b/libsolidity/formal/Z3SMTLib2Interface.cpp index b76cdd252..2ecb8cbcc 100644 --- a/libsolidity/formal/Z3SMTLib2Interface.cpp +++ b/libsolidity/formal/Z3SMTLib2Interface.cpp @@ -20,6 +20,10 @@ #include +#ifdef EMSCRIPTEN_BUILD +#include +#endif + using namespace solidity::frontend::smt; Z3SMTLib2Interface::Z3SMTLib2Interface( @@ -27,9 +31,30 @@ Z3SMTLib2Interface::Z3SMTLib2Interface( std::optional _queryTimeout ): SMTLib2Interface({}, std::move(_smtCallback), _queryTimeout) { +#ifdef EMSCRIPTEN_BUILD + constexpr int resourceLimit = 2000000; + if (m_queryTimeout) + z3::set_param("timeout", int(*m_queryTimeout)); + else + z3::set_param("rlimit", resourceLimit); + z3::set_param("rewriter.pull_cheap_ite", true); + z3::set_param("fp.spacer.q3.use_qgen", true); + z3::set_param("fp.spacer.mbqi", false); + z3::set_param("fp.spacer.ground_pobs", false); +#endif } void Z3SMTLib2Interface::setupSmtCallback() { if (auto* universalCallback = m_smtCallback.target()) universalCallback->smtCommand().setZ3(m_queryTimeout, true, false); } + +std::string Z3SMTLib2Interface::querySolver(std::string const& _query) +{ +#ifdef EMSCRIPTEN_BUILD + z3::context context; + return Z3_eval_smtlib2_string(context, _query.c_str()); +#else + return SMTLib2Interface::querySolver(_query); +#endif +} diff --git a/libsolidity/formal/Z3SMTLib2Interface.h b/libsolidity/formal/Z3SMTLib2Interface.h index 07e138710..7ab087bbd 100644 --- a/libsolidity/formal/Z3SMTLib2Interface.h +++ b/libsolidity/formal/Z3SMTLib2Interface.h @@ -32,6 +32,7 @@ class Z3SMTLib2Interface: public smtutil::SMTLib2Interface ); private: void setupSmtCallback() override; + std::string querySolver(std::string const& _query) override; }; } diff --git a/test/cmdlineTests/model_checker_divModSlacks_false_all/err b/test/cmdlineTests/model_checker_divModSlacks_false_all/err index 8de36b1ee..bf4337810 100644 --- a/test/cmdlineTests/model_checker_divModSlacks_false_all/err +++ b/test/cmdlineTests/model_checker_divModSlacks_false_all/err @@ -1,15 +1,3 @@ -Warning: CHC: Error trying to invoke SMT solver. - --> model_checker_divModSlacks_false_all/input.sol:6:11: - | -6 | return (a / b, a % b); - | ^^^^^ - -Warning: CHC: Error trying to invoke SMT solver. - --> model_checker_divModSlacks_false_all/input.sol:6:18: - | -6 | return (a / b, a % b); - | ^^^^^ - Warning: CHC: 2 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. Info: BMC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/model_checker_divModSlacks_false_chc/err b/test/cmdlineTests/model_checker_divModSlacks_false_chc/err index 56cca82c0..0d6d7341e 100644 --- a/test/cmdlineTests/model_checker_divModSlacks_false_chc/err +++ b/test/cmdlineTests/model_checker_divModSlacks_false_chc/err @@ -1,13 +1 @@ -Warning: CHC: Error trying to invoke SMT solver. - --> model_checker_divModSlacks_false_chc/input.sol:6:11: - | -6 | return (a / b, a % b); - | ^^^^^ - -Warning: CHC: Error trying to invoke SMT solver. - --> model_checker_divModSlacks_false_chc/input.sol:6:18: - | -6 | return (a / b, a % b); - | ^^^^^ - Warning: CHC: 2 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. diff --git a/test/cmdlineTests/model_checker_invariants_all/err b/test/cmdlineTests/model_checker_invariants_all/err index cd133dab0..dcef00b5f 100644 --- a/test/cmdlineTests/model_checker_invariants_all/err +++ b/test/cmdlineTests/model_checker_invariants_all/err @@ -1,9 +1,3 @@ -Warning: Return value of low-level calls not used. - --> model_checker_invariants_all/input.sol:6:3: - | -6 | _a.call(""); - | ^^^^^^^^^^^ - Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Info: Contract invariant(s) for model_checker_invariants_all/input.sol:test: diff --git a/test/cmdlineTests/model_checker_invariants_all/input.sol b/test/cmdlineTests/model_checker_invariants_all/input.sol index 8b90cb3c1..e75a75b5f 100644 --- a/test/cmdlineTests/model_checker_invariants_all/input.sol +++ b/test/cmdlineTests/model_checker_invariants_all/input.sol @@ -2,8 +2,7 @@ pragma solidity >=0.0; contract test { uint x; - function f(address _a) public { - _a.call(""); + function f() public view { assert(x == 0); - } -} \ No newline at end of file + } +} diff --git a/test/cmdlineTests/model_checker_invariants_contract/input.sol b/test/cmdlineTests/model_checker_invariants_contract/input.sol index 3a857d484..e75a75b5f 100644 --- a/test/cmdlineTests/model_checker_invariants_contract/input.sol +++ b/test/cmdlineTests/model_checker_invariants_contract/input.sol @@ -2,7 +2,7 @@ pragma solidity >=0.0; contract test { uint x; - function f() public view { - assert(x < 10); - } -} \ No newline at end of file + function f() public view { + assert(x == 0); + } +} diff --git a/test/cmdlineTests/model_checker_invariants_reentrancy/err b/test/cmdlineTests/model_checker_invariants_reentrancy/err index 78cca4390..8891b0e18 100644 --- a/test/cmdlineTests/model_checker_invariants_reentrancy/err +++ b/test/cmdlineTests/model_checker_invariants_reentrancy/err @@ -1,12 +1,6 @@ -Warning: Return value of low-level calls not used. - --> model_checker_invariants_reentrancy/input.sol:6:3: - | -6 | _a.call(""); - | ^^^^^^^^^^^ - Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Info: Reentrancy property(ies) for model_checker_invariants_reentrancy/input.sol:test: ((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors - = 1 -> Assertion failed at assert(x < 10) + = 1 -> Assertion failed at assert(x == 0) diff --git a/test/cmdlineTests/model_checker_invariants_reentrancy/input.sol b/test/cmdlineTests/model_checker_invariants_reentrancy/input.sol index f21d4d4c8..e75a75b5f 100644 --- a/test/cmdlineTests/model_checker_invariants_reentrancy/input.sol +++ b/test/cmdlineTests/model_checker_invariants_reentrancy/input.sol @@ -2,8 +2,7 @@ pragma solidity >=0.0; contract test { uint x; - function f(address _a) public { - _a.call(""); - assert(x < 10); - } -} \ No newline at end of file + function f() public view { + assert(x == 0); + } +} diff --git a/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json b/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json index eefa60785..f4137ae42 100644 --- a/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json +++ b/test/cmdlineTests/standard_model_checker_divModSlacks_false_all/output.json @@ -1,43 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "1218", - "formattedMessage": "Warning: CHC: Error trying to invoke SMT solver. - --> A:7:15: - | -7 | \t\t\t\t\t\treturn (a / b, a % b); - | \t\t\t\t\t\t ^^^^^ - -", - "message": "CHC: Error trying to invoke SMT solver.", - "severity": "warning", - "sourceLocation": { - "end": 182, - "file": "A", - "start": 177 - }, - "type": "Warning" - }, - { - "component": "general", - "errorCode": "1218", - "formattedMessage": "Warning: CHC: Error trying to invoke SMT solver. - --> A:7:22: - | -7 | \t\t\t\t\t\treturn (a / b, a % b); - | \t\t\t\t\t\t ^^^^^ - -", - "message": "CHC: Error trying to invoke SMT solver.", - "severity": "warning", - "sourceLocation": { - "end": 189, - "file": "A", - "start": 184 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "5840", diff --git a/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json b/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json index 16fb77513..8690a6e96 100644 --- a/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_divModSlacks_false_chc/output.json @@ -1,43 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "1218", - "formattedMessage": "Warning: CHC: Error trying to invoke SMT solver. - --> A:7:15: - | -7 | \t\t\t\t\t\treturn (a / b, a % b); - | \t\t\t\t\t\t ^^^^^ - -", - "message": "CHC: Error trying to invoke SMT solver.", - "severity": "warning", - "sourceLocation": { - "end": 182, - "file": "A", - "start": 177 - }, - "type": "Warning" - }, - { - "component": "general", - "errorCode": "1218", - "formattedMessage": "Warning: CHC: Error trying to invoke SMT solver. - --> A:7:22: - | -7 | \t\t\t\t\t\treturn (a / b, a % b); - | \t\t\t\t\t\t ^^^^^ - -", - "message": "CHC: Error trying to invoke SMT solver.", - "severity": "warning", - "sourceLocation": { - "end": 189, - "file": "A", - "start": 184 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "5840", diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol index ed6f627b5..25f08dff4 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice.sol @@ -25,7 +25,10 @@ contract C { // ==== // SMTEngine: all // SMTIgnoreCex: yes +// SMTIgnoreOS: macos // ---- // Warning 6328: (325-355): CHC: Assertion violation happens here. // Warning 6328: (578-608): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (691-721): CHC: Assertion violation happens here. +// Warning 6328: (959-989): CHC: Assertion violation happens here. +// Warning 6328: (1079-1109): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol index c13e9ce07..d2446c5f9 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_array_slice_2.sol @@ -23,9 +23,12 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc // SMTIgnoreCex: yes +// SMTIgnoreOS: macos // ---- // Warning 6328: (326-356): CHC: Assertion violation happens here. // Warning 6328: (579-609): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (692-722): CHC: Assertion violation happens here. +// Warning 6328: (960-990): CHC: Assertion violation happens here. +// Warning 6328: (1080-1110): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol index 4b4f7a3ac..e4b42c926 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_selector_vs_sig.sol @@ -12,4 +12,4 @@ contract C { // SMTIgnoreOS: macos // ---- // Warning 6328: (330-360): CHC: Assertion violation might happen here. -// Warning 7812: (330-360): BMC: Assertion violation might happen here. +// Warning 4661: (330-360): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol index b2d1b4acc..3bc9da4d6 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice.sol @@ -23,8 +23,12 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTIgnoreOS: macos +// SMTIgnoreCex: yes // ---- -// Warning 6328: (334-364): CHC: Assertion violation happens here.\nCounterexample:\n\ndata = [0x4f]\nb2 = [0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c]\nb3 = []\nb4 = []\nx = 0\ny = 0\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeSlice(sig, [0x4f]) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (334-364): CHC: Assertion violation happens here. // Warning 6328: (588-618): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (702-732): CHC: Assertion violation happens here. +// Warning 6328: (971-1001): CHC: Assertion violation happens here. +// Warning 6328: (1086-1116): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol index 4c21a02a6..dbf28814d 100644 --- a/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol +++ b/test/libsolidity/smtCheckerTests/abi/abi_encode_with_sig_array_slice_2.sol @@ -23,8 +23,12 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTIgnoreOS: macos +// SMTIgnoreCex: yes // ---- -// Warning 6328: (335-365): CHC: Assertion violation happens here.\nCounterexample:\n\ndata = [36]\nb3 = []\nb4 = []\nx = 0\ny = 0\nb5 = []\nb6 = []\n\nTransaction trace:\nC.constructor()\nC.abiEncodeSlice(sig, [36]) -- counterexample incomplete; parameter name used instead of value +// Warning 6328: (335-365): CHC: Assertion violation happens here. // Warning 6328: (589-619): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (703-733): CHC: Assertion violation happens here. +// Warning 6328: (972-1002): CHC: Assertion violation happens here. +// Warning 6328: (1087-1117): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol index 813185adf..b78589594 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_1.sol @@ -7,10 +7,9 @@ contract C { } } // ==== -// SMTEngine: all -// SMTIgnoreOS: macos +// SMTEngine: chc +// SMTSolvers: eld // ---- // Warning 9302: (96-117): Return value of low-level calls not used. -// Warning 6328: (121-156): CHC: Assertion violation might happen here. // Warning 6328: (175-211): CHC: Assertion violation happens here. -// Warning 4661: (121-156): BMC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_2.sol b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_2.sol index 968095bb2..ef4b19c1d 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/call_with_value_2.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/call_with_value_2.sol @@ -7,9 +7,9 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTSolvers: eld // ---- // Warning 9302: (96-116): Return value of low-level calls not used. -// Warning 6328: (120-156): CHC: Assertion violation might happen here. // Warning 6328: (175-210): CHC: Assertion violation happens here. -// Warning 4661: (120-156): BMC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external.sol b/test/libsolidity/smtCheckerTests/external_calls/external.sol index 5ddb61a22..3e6dbe641 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external.sol @@ -15,7 +15,9 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTTargets: assert +// SMTIgnoreCex: yes +// SMTIgnoreOS: linux // ---- -// Warning 6328: (167-181): CHC: Assertion violation happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (167-181): CHC: Assertion violation happens here.\nCounterexample:\nx = 10, d = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0, d = 0\nC.f()\nState: x = 1, d = 0\nC.f()\nState: x = 2, d = 0\nC.f()\nState: x = 3, d = 0\nC.f()\nState: x = 4, d = 0\nC.f()\nState: x = 5, d = 0\nC.f()\nState: x = 6, d = 0\nC.g()\n d.d() -- untrusted external call, synthesized as:\n C.f() -- reentrant call\n C.f() -- reentrant call\nState: x = 8, d = 0\nC.g()\n d.d() -- untrusted external call, synthesized as:\n C.f() -- reentrant call\n C.f() -- reentrant call diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol index dd8a529a2..65cd7b72c 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_1.sol @@ -35,8 +35,7 @@ contract C { // ==== // SMTEngine: chc // SMTExtCalls: trusted -// SMTIgnoreOS: macos // ---- // Warning 6328: (256-277): CHC: Assertion violation happens here. -// Warning 6328: (533-554): CHC: Assertion violation happens here. +// Warning 6328: (533-554): CHC: Assertion violation might happen here. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol index c1d567cfe..16779bb89 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol @@ -47,7 +47,8 @@ contract C { // ==== // SMTEngine: chc // SMTExtCalls: trusted +// SMTIgnoreOS: macos // ---- // Warning 6328: (434-455): CHC: Assertion violation happens here. -// Warning 6328: (1270-1291): CHC: Assertion violation might happen here. +// Warning 6328: (1270-1291): CHC: Assertion violation happens here. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol index d7721037f..3e8e4f409 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_3.sol @@ -40,6 +40,7 @@ contract C { // ==== // SMTEngine: chc // SMTExtCalls: trusted +// SMTIgnoreOS: macos // ---- // Warning 6328: (561-582): CHC: Assertion violation happens here. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_2.sol index 2b94abc0e..256a8870e 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_2.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_2.sol @@ -11,9 +11,9 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc // SMTIgnoreCex: yes +// SMTSolvers: eld // ---- -// Warning 6328: (150-186): CHC: Assertion violation might happen here. // Warning 6328: (205-240): CHC: Assertion violation happens here. -// Warning 4661: (150-186): BMC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol index 2a535329a..7d87fb07c 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_with_value_3.sol @@ -11,9 +11,8 @@ contract C { } } // ==== -// SMTEngine: all -// SMTIgnoreOS: macos +// SMTEngine: chc +// SMTSolvers: eld // ---- -// Warning 6328: (150-183): CHC: Assertion violation might happen here. -// Warning 6328: (202-236): CHC: Assertion violation happens here.\nCounterexample:\n\ni = 0\n\nTransaction trace:\nC.constructor()\nC.g(0)\n i.f{value: 20}() -- untrusted external call -// Warning 4661: (150-183): BMC: Assertion violation happens here. +// Warning 6328: (202-236): CHC: Assertion violation happens here. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol index 80e27e7e2..182bf15cc 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_3.sol @@ -39,7 +39,8 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTSolvers: eld // SMTIgnoreInv: yes // ---- // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol index 34df5c0e0..3b6630e6d 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_hash_known_code_state_reentrancy_trusted.sol @@ -33,6 +33,6 @@ contract C { // SMTContract: C // SMTEngine: chc // SMTExtCalls: trusted +// SMTSolvers: eld // ---- -// Warning 6328: (314-328): CHC: Assertion violation might happen here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol index bfc95b35a..a28e4852b 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol @@ -16,5 +16,7 @@ contract C { } // ==== // SMTEngine: all +// SMTTargets: assert +// SMTIgnoreOS: linux // ---- -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol b/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol index b18d5426f..ef02b7839 100644 --- a/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol +++ b/test/libsolidity/smtCheckerTests/operators/index_access_for_bytesNN.sol @@ -5,7 +5,7 @@ contract C { } } // ==== -// SMTEngine: all -// SMTIgnoreOS: macos +// SMTEngine: chc +// SMTSolvers: eld // ---- // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol b/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol index 644ecdb12..3057ae0ec 100644 --- a/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol +++ b/test/libsolidity/smtCheckerTests/operators/index_access_side_effect.sol @@ -21,5 +21,6 @@ contract C { // ==== // SMTEngine: all // SMTIgnoreCex: yes +// SMTTargets: assert // ---- -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol index 76ad6db55..30f6a0ba9 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol @@ -53,10 +53,10 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // SMTTargets: assert // ---- // Warning 6328: (2209-2235): CHC: Assertion violation might happen here. // Warning 6328: (2245-2271): CHC: Assertion violation might happen here. // Info 1391: CHC: 14 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 7812: (2245-2271): BMC: Assertion violation might happen here. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/out_of_bounds/array_2d_4.sol b/test/libsolidity/smtCheckerTests/out_of_bounds/array_2d_4.sol index 2a9f39d1a..e4d9bfdff 100644 --- a/test/libsolidity/smtCheckerTests/out_of_bounds/array_2d_4.sol +++ b/test/libsolidity/smtCheckerTests/out_of_bounds/array_2d_4.sol @@ -15,13 +15,11 @@ contract C { // SMTEngine: all // ---- // Warning 4984: (184-197): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 4984: (199-202): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 6368: (228-232): CHC: Out of bounds access happens here. +// Warning 6368: (228-232): CHC: Out of bounds access happens here.\nCounterexample:\na = []\ni = 0\nj = 0\n\nTransaction trace:\nC.constructor()\nState: a = []\nC.r() // Warning 4984: (228-244): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 4984: (246-249): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. -// Warning 6368: (255-259): CHC: Out of bounds access happens here. +// Warning 6368: (255-259): CHC: Out of bounds access happens here.\nCounterexample:\na = []\ni = 0\nj = 0\n\nTransaction trace:\nC.constructor()\nState: a = []\nC.r() // Warning 6368: (255-262): CHC: Out of bounds access happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. // Warning 2661: (184-197): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. // Warning 2661: (228-244): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Info 6002: BMC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 6002: BMC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/array_mapping_aliasing_2.sol b/test/libsolidity/smtCheckerTests/types/array_mapping_aliasing_2.sol index fce586987..bbc3a79cf 100644 --- a/test/libsolidity/smtCheckerTests/types/array_mapping_aliasing_2.sol +++ b/test/libsolidity/smtCheckerTests/types/array_mapping_aliasing_2.sol @@ -34,16 +34,7 @@ contract C // ==== // SMTEngine: all // SMTIgnoreCex: yes -// SMTIgnoreOS: macos +// SMTTargets: assert // ---- -// Warning 6368: (439-453): CHC: Out of bounds access happens here. -// Warning 6368: (465-480): CHC: Out of bounds access might happen here. -// Warning 6368: (492-508): CHC: Out of bounds access happens here. -// Warning 6368: (492-511): CHC: Out of bounds access happens here. -// Warning 6368: (622-636): CHC: Out of bounds access happens here. -// Warning 6368: (737-752): CHC: Out of bounds access might happen here. -// Warning 6368: (850-866): CHC: Out of bounds access happens here. -// Warning 6368: (850-869): CHC: Out of bounds access happens here. -// Warning 6328: (936-956): CHC: Assertion violation happens here. -// Warning 6368: (1029-1043): CHC: Out of bounds access might happen here. +// Warning 6328: (936-956): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\n\nTransaction trace:\nC.constructor()\nC.g(0)\n C.f(map) -- counterexample incomplete; parameter name used instead of value -- internal call // Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol b/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol index d5daba699..5f4fad62a 100644 --- a/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol +++ b/test/libsolidity/smtCheckerTests/types/struct_array_branches_2d.sol @@ -14,6 +14,7 @@ contract C } } // ==== -// SMTEngine: all +// SMTEngine: chc +// SMTTargets: assert // ---- -// Info 1391: CHC: 10 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 9fffec31b651553977f23f66a7c8443a2c2341b7 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 12 Sep 2024 08:33:00 +0200 Subject: [PATCH 0433/1340] Purge Z3 from CMakeLists where possible --- CMakeLists.txt | 75 ++++++++++---------------------------- libsmtutil/CMakeLists.txt | 26 +------------ libsolidity/CMakeLists.txt | 6 +++ 3 files changed, 27 insertions(+), 80 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0a8313b0..836d2cccb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,63 +90,28 @@ configure_file("${PROJECT_SOURCE_DIR}/cmake/templates/license.h.in" include/lice include(EthOptions) configure_project(TESTS) -set(TESTED_Z3_VERSION "4.12.1") -set(MINIMUM_Z3_VERSION "4.8.16") -find_package(Z3) -if (${Z3_FOUND}) - if (${STRICT_Z3_VERSION}) - if (NOT ("${Z3_VERSION_STRING}" VERSION_EQUAL ${TESTED_Z3_VERSION})) - message( - FATAL_ERROR - "SMTChecker tests require Z3 ${TESTED_Z3_VERSION} for all tests to pass.\n\ -Build with -DSTRICT_Z3_VERSION=OFF if you want to use a different version. \ -You can also use -DUSE_Z3=OFF to build without Z3. In both cases use --no-smt when running tests." - ) - endif() - else() - if ("${Z3_VERSION_STRING}" VERSION_LESS ${MINIMUM_Z3_VERSION}) - message( - FATAL_ERROR - "Solidity requires Z3 ${MINIMUM_Z3_VERSION} or newer. You can also use -DUSE_Z3=OFF to build without Z3." - ) - endif() - endif() -endif() - -if(${USE_Z3_DLOPEN}) - add_definitions(-DHAVE_Z3) - add_definitions(-DHAVE_Z3_DLOPEN) - find_package(Python3 COMPONENTS Interpreter) - if(${Z3_FOUND}) - get_target_property(Z3_HEADER_HINTS z3::libz3 INTERFACE_INCLUDE_DIRECTORIES) - endif() - find_path(Z3_HEADER_PATH z3.h HINTS ${Z3_HEADER_HINTS}) - if(Z3_HEADER_PATH) - set(Z3_FOUND TRUE) - else() - message(SEND_ERROR "Dynamic loading of Z3 requires Z3 headers to be present at build time.") - endif() - if(NOT ${Python3_FOUND}) - message(SEND_ERROR "Dynamic loading of Z3 requires Python 3 to be present at build time.") - endif() - if(${SOLC_LINK_STATIC}) - message(SEND_ERROR "solc cannot be linked statically when dynamically loading Z3.") - endif() -elseif (${Z3_FOUND}) - add_definitions(-DHAVE_Z3) - message("Z3 SMT solver found. This enables optional SMT checking with Z3.") -endif() - -find_program(CVC5_PATH cvc5) - -if (NOT (${Z3_FOUND} OR CVC5_PATH)) - message("No SMT solver found (or it has been forcefully disabled). Optional SMT checking will not be available.\ - \nPlease install Z3 or cvc5 or remove the option disabling them (USE_Z3).") -endif() if(EMSCRIPTEN) - if(${Z3_FOUND}) - add_definitions(-DEMSCRIPTEN_BUILD) + set(TESTED_Z3_VERSION "4.12.1") + set(MINIMUM_Z3_VERSION "4.8.16") + find_package(Z3) + if (${Z3_FOUND}) + add_definitions(-DEMSCRIPTEN_BUILD) + if (${STRICT_Z3_VERSION}) + if (NOT ("${Z3_VERSION_STRING}" VERSION_EQUAL ${TESTED_Z3_VERSION})) + message( + FATAL_ERROR + "SMTChecker tests require Z3 ${TESTED_Z3_VERSION} for all tests to pass.\n" + ) + endif() + else() + if ("${Z3_VERSION_STRING}" VERSION_LESS ${MINIMUM_Z3_VERSION}) + message( + FATAL_ERROR + "Solidity requires Z3 ${MINIMUM_Z3_VERSION} or newer." + ) + endif() + endif() else() message(FATAL_ERROR "Solidity requires Z3 for emscripten build.") endif() diff --git a/libsmtutil/CMakeLists.txt b/libsmtutil/CMakeLists.txt index 2bd870549..8b22da7db 100644 --- a/libsmtutil/CMakeLists.txt +++ b/libsmtutil/CMakeLists.txt @@ -16,30 +16,6 @@ set(sources Helpers.h ) -if (${Z3_FOUND}) - set(z3_SRCS) -else() - set(z3_SRCS) -endif() -if (${USE_Z3_DLOPEN}) - file(GLOB Z3_HEADERS ${Z3_HEADER_PATH}/z3*.h) - set(Z3_WRAPPER ${CMAKE_CURRENT_BINARY_DIR}/z3wrapper.cpp) - add_custom_command( - OUTPUT ${Z3_WRAPPER} - COMMAND ${Python3_EXECUTABLE} genz3wrapper.py ${Z3_HEADERS} > ${Z3_WRAPPER} - DEPENDS ${Z3_HEADERS} genz3wrapper.py - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - set(z3_SRCS ${z3_SRCS} ${Z3_WRAPPER} Z3Loader.cpp Z3Loader.h) -endif() - -add_library(smtutil ${sources} ${z3_SRCS}) +add_library(smtutil ${sources}) target_link_libraries(smtutil PUBLIC solutil Boost::boost) - -if (${USE_Z3_DLOPEN}) - target_include_directories(smtutil PUBLIC ${Z3_HEADER_PATH}) - target_link_libraries(smtutil PUBLIC ${CMAKE_DL_LIBS}) -elseif (${Z3_FOUND}) - target_link_libraries(smtutil PUBLIC z3::libz3) -endif() diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 1c4c48090..5925a50ac 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -224,3 +224,9 @@ set(sources add_library(solidity ${sources}) target_link_libraries(solidity PUBLIC yul evmasm langutil smtutil solutil Boost::boost fmt::fmt-header-only Threads::Threads) +if (EMSCRIPTEN) + if(NOT ${Z3_FOUND}) + message(FATAL_ERROR "Z3 library must be present for EMSCRIPTEN build") + endif() + target_link_libraries(solidity PUBLIC z3::libz3) +endif() From 8f4a7e11769661d77e113d41023dc265e7a1afb8 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 12 Sep 2024 09:53:55 +0200 Subject: [PATCH 0434/1340] Docs: Update documentation about usage of Z3 --- docs/contributing.rst | 13 ++++++------- docs/smtchecker.rst | 6 +----- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index bb88d1201..decd51392 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -93,7 +93,7 @@ Prerequisites For running all compiler tests you may want to optionally install a few dependencies (`evmone `_, -`libz3 `_, `Eldarica `_, +`z3 `_, `Eldarica `_, `cvc5 `). On macOS systems, some of the testing scripts expect GNU coreutils to be installed. @@ -132,13 +132,12 @@ flag to ``scripts/soltest.sh``. The ``evmone`` library should end with the file name extension ``.so`` on Linux, ``.dll`` on Windows systems and ``.dylib`` on macOS. -For running SMT tests, the ``libz3`` library must be installed and locatable -by ``cmake`` during compiler configure stage. -A few SMT tests use ``Eldarica`` instead of ``Z3``. -``Eldarica`` is a runtime dependency, its executable (``eld``) must be present in ``PATH`` for the tests to pass. +For running SMT tests, the ``z3`` executable must be present in ``PATH``. +A few SMT tests use ``Eldarica`` instead of ``z3``. +These requry its executable (``eld``) to be present in ``PATH`` for the tests to pass. However, if ``Eldarica`` is not found, these tests will be automatically skipped. -If the ``libz3`` library is not installed on your system, you should disable the +If ``z3`` is not present on your system, you should disable the SMT tests by exporting ``SMT_FLAGS=--no-smt`` before running ``./scripts/tests.sh`` or running ``./scripts/soltest.sh --no-smt``. These tests are ``libsolidity/smtCheckerTests``. @@ -167,7 +166,7 @@ See especially: .. note:: Those working in a Windows environment wanting to run the above basic sets - without libz3. Using Git Bash, you use: ``./build/test/Release/soltest.exe -- --no-smt``. + without z3. Using Git Bash, you use: ``./build/test/Release/soltest.exe -- --no-smt``. If you are running this in plain Command Prompt, use ``.\build\test\Release\soltest.exe -- --no-smt``. If you want to debug using GDB, make sure you build differently than the "usual". diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index 92aaa847c..7db996faf 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -831,11 +831,7 @@ option ``--model-checker-solvers {all,cvc5,eld,smtlib2,z3}`` or the JSON option These can be used together with the compiler's `callback mechanism `_ so that any solver binary from the system can be employed to synchronously return the results of the queries to the compiler. This can be used by both BMC and CHC depending on which solvers are called. -- ``z3`` is available - - - if ``solc`` is compiled with it; - - if a dynamic ``z3`` library of version >=4.8.x is installed in a Linux system (from Solidity 0.7.6); - - statically in ``soljson.js`` (from Solidity 0.6.9), that is, the JavaScript binary of the compiler. +- ``z3`` is available statically in ``soljson.js`` (from Solidity 0.6.9), that is, the JavaScript binary of the compiler. Otherwise it is used via its binary which must be installed in the system. .. note:: z3 version 4.8.16 broke ABI compatibility with previous versions and cannot From 2c75667266fd129694120780553d603def7a880d Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 12 Sep 2024 09:56:11 +0200 Subject: [PATCH 0435/1340] Add changelog entry about Z3 switch --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 0ebefa659..4c2885c9a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * SMTChecker: Z3 is now a runtime dependency, not a build dependency (except for emscripten build). Bugfixes: From 2ad9723df2b92d7bfc30a957f0bd8cb0cf936aeb Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Mon, 16 Sep 2024 16:58:02 +0200 Subject: [PATCH 0436/1340] SMTChecker: Validate interaction with SMT and CHC solvers We introduce new tyoe of check to validate our assumptions when interacting with the solvers. If our assumption is violated, we can gracefully handle that and not crash the whole compiler. --- libsmtutil/CHCSmtLib2Interface.cpp | 114 ++++++++++--------- libsmtutil/Exceptions.h | 12 ++ libsmtutil/SMTLib2Interface.cpp | 12 +- libsolidity/formal/BMC.cpp | 2 +- libsolidity/formal/CHC.cpp | 2 +- libsolidity/formal/Z3CHCSmtLib2Interface.cpp | 105 +++++++++-------- 6 files changed, 136 insertions(+), 111 deletions(-) diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index 02257031a..0bd74a410 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -93,25 +93,32 @@ void CHCSmtLib2Interface::addRule(Expression const& _expr, std::string const& /* CHCSolverInterface::QueryResult CHCSmtLib2Interface::query(Expression const& _block) { std::string query = dumpQuery(_block); - std::string response = querySolver(query); + try + { + std::string response = querySolver(query); - CheckResult result; - // NOTE: Our internal semantics is UNSAT -> SAFE and SAT -> UNSAFE, which corresponds to usual SMT-based model checking - // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. - // So we have to flip the answer. - if (boost::starts_with(response, "sat")) + CheckResult result; + // NOTE: Our internal semantics is UNSAT -> SAFE and SAT -> UNSAFE, which corresponds to usual SMT-based model checking + // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. + // So we have to flip the answer. + if (boost::starts_with(response, "sat")) + { + auto maybeInvariants = invariantsFromSolverResponse(response); + return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; + } + else if (boost::starts_with(response, "unsat")) + result = CheckResult::SATISFIABLE; + else if (boost::starts_with(response, "unknown")) + result = CheckResult::UNKNOWN; + else + result = CheckResult::ERROR; + return {result, Expression(true), {}}; + } + catch(smtutil::SMTSolverInteractionError const&) { - auto maybeInvariants = invariantsFromSolverResponse(response); - return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; + return {CheckResult::ERROR, Expression(true), {}}; } - else if (boost::starts_with(response, "unsat")) - result = CheckResult::SATISFIABLE; - else if (boost::starts_with(response, "unknown")) - result = CheckResult::UNKNOWN; - else - result = CheckResult::ERROR; - return {result, Expression(true), {}}; } void CHCSmtLib2Interface::declareVariable(std::string const& _name, SortPointer const& _sort) @@ -250,7 +257,7 @@ SortPointer CHCSmtLib2Interface::ScopedParser::toSort(SMTLib2Expression const& _ auto const& args = asSubExpressions(_expr); if (asAtom(args[0]) == "Array") { - smtAssert(args.size() == 3); + smtSolverInteractionRequire(args.size() == 3, "Wrong format of Array sort in solver's response"); auto domainSort = toSort(args[1]); auto codomainSort = toSort(args[2]); return std::make_shared(std::move(domainSort), std::move(codomainSort)); @@ -259,7 +266,7 @@ SortPointer CHCSmtLib2Interface::ScopedParser::toSort(SMTLib2Expression const& _ && asAtom(args[1]) == "int2bv") return std::make_shared(std::stoul(asAtom(args[2]))); } - smtAssert(false, "Unknown sort encountered"); + smtSolverInteractionRequire(false, "Unknown sort encountered"); } smtutil::Expression CHCSmtLib2Interface::ScopedParser::parseQuantifier( @@ -270,20 +277,20 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::parseQuantifier( std::vector> boundVariables; for (auto const& sortedVar: _varList) { - smtAssert(!isAtom(sortedVar)); + smtSolverInteractionRequire(!isAtom(sortedVar), "Wrong format of quantified expression in solver's response"); auto varSortPair = asSubExpressions(sortedVar); - smtAssert(varSortPair.size() == 2); + smtSolverInteractionRequire(varSortPair.size() == 2, "Wrong format of quantified expression in solver's response"); boundVariables.emplace_back(asAtom(varSortPair[0]), toSort(varSortPair[1])); } for (auto const& [var, sort]: boundVariables) { - smtAssert(m_localVariables.count(var) == 0); // TODO: deal with shadowing? + smtSolverInteractionRequire(m_localVariables.count(var) == 0, "Quantifying over previously encountered variable"); // TODO: deal with shadowing? m_localVariables.emplace(var, sort); } auto core = toSMTUtilExpression(_coreExpression); for (auto const& [var, sort]: boundVariables) { - smtAssert(m_localVariables.count(var) != 0); + smtSolverInteractionRequire(m_localVariables.count(var) != 0, "Error in processing quantified expression"); m_localVariables.erase(var); } return Expression(_quantifierName, {core}, SortProvider::boolSort); // TODO: what about the bound variables? @@ -313,7 +320,7 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi return smtutil::Expression(_atom, {}, std::make_shared(_atom, std::vector{}, std::vector{})); } else - smtAssert(false, "Unhandled atomic SMT expression"); + smtSolverInteractionRequire(false, "Unhandled atomic SMT expression"); }, [&](std::vector const& _subExpr) { @@ -325,13 +332,13 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi if (op == "!") { // named term, we ignore the name - smtAssert(_subExpr.size() > 2); + smtSolverInteractionRequire(_subExpr.size() > 2, "Wrong format of named SMT-LIB term"); return toSMTUtilExpression(_subExpr[1]); } if (op == "exists" || op == "forall") { - smtAssert(_subExpr.size() == 3); - smtAssert(!isAtom(_subExpr[1])); + smtSolverInteractionRequire(_subExpr.size() == 3, "Wrong format of quantified expression"); + smtSolverInteractionRequire(!isAtom(_subExpr[1]), "Wrong format of quantified expression"); return parseQuantifier(op, asSubExpressions(_subExpr[1]), _subExpr[2]); } for (size_t i = 1; i < _subExpr.size(); i++) @@ -354,7 +361,7 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi sort = contains(boolOperators, op) ? SortProvider::boolSort : arguments.back().sort; return smtutil::Expression(op, std::move(arguments), std::move(sort)); } - smtAssert(false, "Unhandled case in expression conversion"); + smtSolverInteractionRequire(false, "Unhandled case in expression conversion"); } else { @@ -374,7 +381,7 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi && typeArgs[1].toString() == "int2bv") { auto bvSort = std::dynamic_pointer_cast(toSort(_subExpr[0])); - smtAssert(bvSort); + smtSolverInteractionRequire(bvSort, "Invalid format of bitvector sort"); return smtutil::Expression::int2bv(toSMTUtilExpression(_subExpr[1]), bvSort->size); } if (typeArgs.size() == 4 && typeArgs[0].toString() == "_" @@ -385,7 +392,7 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi SortProvider::bitVectorSort // TODO: Compute bit size properly? ); } - smtAssert(false, "Unhandled case in expression conversion"); + smtSolverInteractionRequire(false, "Unhandled case in expression conversion"); } } }, @@ -394,15 +401,15 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi } -#define precondition(CONDITION) if (!(CONDITION)) return {} std::optional CHCSmtLib2Interface::invariantsFromSolverResponse(std::string const& _response) const { std::stringstream ss(_response); std::string answer; ss >> answer; - precondition(answer == "sat"); + smtSolverInteractionRequire(answer == "sat", "CHC model can only be extracted from sat answer"); SMTLib2Parser parser(ss); - precondition(!parser.isEOF()); // There has to be a model + if (parser.isEOF()) + return {}; std::vector parsedOutput; try { @@ -411,25 +418,25 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp } catch(SMTLib2Parser::ParsingException&) { - return {}; + smtSolverInteractionRequire(false, "Error during parsing CHC model"); } - smtAssert(parser.isEOF()); - precondition(!parsedOutput.empty()); + smtSolverInteractionRequire(parser.isEOF(), "Error during parsing CHC model"); + smtSolverInteractionRequire(!parsedOutput.empty(), "Error during parsing CHC model"); auto& commands = parsedOutput.size() == 1 ? asSubExpressions(parsedOutput[0]) : parsedOutput; std::vector definitions; for (auto& command: commands) { auto& args = asSubExpressions(command); - precondition(args.size() == 5); + smtSolverInteractionRequire(args.size() == 5, "Invalid format of CHC model"); // args[0] = "define-fun" // args[1] = predicate name // args[2] = formal arguments of the predicate // args[3] = return sort // args[4] = body of the predicate's interpretation - precondition(isAtom(args[0]) && asAtom(args[0]) == "define-fun"); - precondition(isAtom(args[1])); - precondition(!isAtom(args[2])); - precondition(isAtom(args[3]) && asAtom(args[3]) == "Bool"); + smtSolverInteractionRequire(isAtom(args[0]) && asAtom(args[0]) == "define-fun", "Invalid format of CHC model"); + smtSolverInteractionRequire(isAtom(args[1]), "Invalid format of CHC model"); + smtSolverInteractionRequire(!isAtom(args[2]), "Invalid format of CHC model"); + smtSolverInteractionRequire(isAtom(args[3]) && asAtom(args[3]) == "Bool", "Invalid format of CHC model"); auto& interpretation = args[4]; inlineLetExpressions(interpretation); ScopedParser scopedParser(m_context); @@ -437,10 +444,10 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp std::vector predicateArgs; for (auto const& formalArgument: formalArguments) { - precondition(!isAtom(formalArgument)); + smtSolverInteractionRequire(!isAtom(formalArgument), "Invalid format of CHC model"); auto const& nameSortPair = asSubExpressions(formalArgument); - precondition(nameSortPair.size() == 2); - precondition(isAtom(nameSortPair[0])); + smtSolverInteractionRequire(nameSortPair.size() == 2, "Invalid format of CHC model"); + smtSolverInteractionRequire(isAtom(nameSortPair[0]), "Invalid format of CHC model"); SortPointer varSort = scopedParser.toSort(nameSortPair[1]); scopedParser.addVariableDeclaration(asAtom(nameSortPair[0]), varSort); // FIXME: Why Expression here? @@ -461,7 +468,6 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp } return Expression::mkAnd(std::move(definitions)); } -#undef precondition namespace { @@ -478,8 +484,8 @@ struct LetBindings SMTLib2Expression& operator[](std::string const& varName) { auto it = bindings.find(varName); - smtAssert(it != bindings.end()); - smtAssert(!it->second.empty()); + smtSolverInteractionRequire(it != bindings.end(), "Error in processing let bindings"); + smtSolverInteractionRequire(!it->second.empty(), "Error in processing let bindings"); return it->second.back(); } @@ -487,13 +493,13 @@ struct LetBindings void popScope() { - smtAssert(!scopeBounds.empty()); + smtSolverInteractionRequire(!scopeBounds.empty(), "Error in processing let bindings"); auto bound = scopeBounds.back(); while (varNames.size() > bound) { auto const& varName = varNames.back(); auto it = bindings.find(varName); - smtAssert(it != bindings.end()); + smtSolverInteractionRequire(it != bindings.end(), "Error in processing let bindings"); auto& record = it->second; record.pop_back(); if (record.empty()) @@ -524,21 +530,21 @@ void inlineLetExpressions(SMTLib2Expression& _expr, LetBindings& _bindings) return; } auto& subexprs = asSubExpressions(_expr); - smtAssert(!subexprs.empty()); + smtSolverInteractionRequire(!subexprs.empty(), "Invalid let expression"); auto const& first = subexprs.at(0); if (isAtom(first) && asAtom(first) == "let") { - smtAssert(subexprs.size() == 3); - smtAssert(!isAtom(subexprs[1])); + smtSolverInteractionRequire(subexprs.size() == 3, "Invalid let expression"); + smtSolverInteractionRequire(!isAtom(subexprs[1]), "Invalid let expression"); auto& bindingExpressions = asSubExpressions(subexprs[1]); // process new bindings std::vector> newBindings; for (auto& binding: bindingExpressions) { - smtAssert(!isAtom(binding)); + smtSolverInteractionRequire(!isAtom(binding), "Invalid let expression"); auto& bindingPair = asSubExpressions(binding); - smtAssert(bindingPair.size() == 2); - smtAssert(isAtom(bindingPair.at(0))); + smtSolverInteractionRequire(bindingPair.size() == 2, "Invalid let expression"); + smtSolverInteractionRequire(isAtom(bindingPair.at(0)), "Invalid let expression"); inlineLetExpressions(bindingPair.at(1), _bindings); newBindings.emplace_back(asAtom(bindingPair.at(0)), bindingPair.at(1)); } @@ -562,7 +568,7 @@ void inlineLetExpressions(SMTLib2Expression& _expr, LetBindings& _bindings) { // A little hack to ensure quantified variables are not substituted because of some outer let definition: // We define the current binding of the variable to itself, before we recurse in to subterm - smtAssert(subexprs.size() == 3); + smtSolverInteractionRequire(subexprs.size() == 3, "Invalid let expression"); _bindings.pushScope(); for (auto const& sortedVar: asSubExpressions(subexprs.at(1))) { diff --git a/libsmtutil/Exceptions.h b/libsmtutil/Exceptions.h index 2a32c4fcd..5c642b0e2 100644 --- a/libsmtutil/Exceptions.h +++ b/libsmtutil/Exceptions.h @@ -48,4 +48,16 @@ struct SMTLogicError: virtual util::Exception {}; "SMT assertion failed" \ ) + +// Error to indicate that some problem occurred during an interaction with external solver. +// This could be a problem with calling the solver or unexpected situation during the processing of solver's response. +struct SMTSolverInteractionError: virtual util::Exception {}; + +#define smtSolverInteractionRequire(CONDITION, DESCRIPTION) \ + assertThrowWithDefaultDescription( \ + (CONDITION), \ + ::solidity::smtutil::SMTSolverInteractionError, \ + (DESCRIPTION), \ + "Encountered problem during interaction with a solver" \ + ) } diff --git a/libsmtutil/SMTLib2Interface.cpp b/libsmtutil/SMTLib2Interface.cpp index 0914f8305..0430f0d21 100644 --- a/libsmtutil/SMTLib2Interface.cpp +++ b/libsmtutil/SMTLib2Interface.cpp @@ -119,7 +119,7 @@ std::vector parseValuesFromResponse(std::string const& _response) std::stringstream ss(_response); std::string answer; ss >> answer; - smtAssert(answer == "sat"); + smtSolverInteractionRequire(answer == "sat", "SMT: Parsing model values only possible after sat answer"); std::vector parsedOutput; SMTLib2Parser parser(ss); @@ -130,16 +130,16 @@ std::vector parseValuesFromResponse(std::string const& _response) } catch(SMTLib2Parser::ParsingException&) { - return {}; + smtSolverInteractionRequire(false, "Error during parsing SMT answer"); } - smtAssert(parsedOutput.size() == 1, "SMT: Expected model values as a single s-expression"); + smtSolverInteractionRequire(parsedOutput.size() == 1, "SMT: Expected model values as a single s-expression"); auto const& values = parsedOutput[0]; - smtAssert(!isAtom(values)); + smtSolverInteractionRequire(!isAtom(values), "Invalid format of values in SMT answer"); std::vector parsedValues; for (auto const& nameValuePair: asSubExpressions(values)) { - smtAssert(!isAtom(nameValuePair)); - smtAssert(asSubExpressions(nameValuePair).size() == 2); + smtSolverInteractionRequire(!isAtom(nameValuePair), "Invalid format of values in SMT answer"); + smtSolverInteractionRequire(asSubExpressions(nameValuePair).size() == 2, "Invalid format of values in SMT answer"); auto const& value = asSubExpressions(nameValuePair)[1]; parsedValues.push_back(value.toString()); } diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index a7f792453..6f3eb6c4c 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -1197,7 +1197,7 @@ void BMC::checkCondition( m_errorReporter.warning(1584_error, _location, "BMC: At least two SMT solvers provided conflicting answers. Results might not be sound."); break; case smtutil::CheckResult::ERROR: - m_errorReporter.warning(1823_error, _location, "BMC: Error trying to invoke SMT solver."); + m_errorReporter.warning(1823_error, _location, "BMC: Error during interaction with the SMT solver."); break; } diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 7f413f91a..9f23aff6f 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -1919,7 +1919,7 @@ CHCSolverInterface::QueryResult CHC::query(smtutil::Expression const& _query, la m_errorReporter.warning(1988_error, _location, "CHC: At least two SMT solvers provided conflicting answers. Results might not be sound."); break; case CheckResult::ERROR: - m_errorReporter.warning(1218_error, _location, "CHC: Error trying to invoke SMT solver."); + m_errorReporter.warning(1218_error, _location, "CHC: Error during interaction with the solver."); break; } return result; diff --git a/libsolidity/formal/Z3CHCSmtLib2Interface.cpp b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp index a3aef325b..2ceecfcf9 100644 --- a/libsolidity/formal/Z3CHCSmtLib2Interface.cpp +++ b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp @@ -62,48 +62,55 @@ CHCSolverInterface::QueryResult Z3CHCSmtLib2Interface::query(smtutil::Expression { setupSmtCallback(true); std::string query = dumpQuery(_block); + try + { #ifdef EMSCRIPTEN_BUILD - z3::set_param("fp.xform.slice", true); - z3::set_param("fp.xform.inline_linear", true); - z3::set_param("fp.xform.inline_eager", true); - std::string response = Z3_eval_smtlib2_string(z3::context{}, query.c_str()); + z3::set_param("fp.xform.slice", true); + z3::set_param("fp.xform.inline_linear", true); + z3::set_param("fp.xform.inline_eager", true); + std::string response = Z3_eval_smtlib2_string(z3::context{}, query.c_str()); #else - std::string response = querySolver(query); + std::string response = querySolver(query); #endif - // NOTE: Our internal semantics is UNSAT -> SAFE and SAT -> UNSAFE, which corresponds to usual SMT-based model checking - // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. - // So we have to flip the answer. - if (boost::starts_with(response, "unsat")) - { - // Repeat the query with preprocessing disabled, to get the full proof - setupSmtCallback(false); - query = "(set-option :produce-proofs true)" + query + "\n(get-proof)"; + // NOTE: Our internal semantics is UNSAT -> SAFE and SAT -> UNSAFE, which corresponds to usual SMT-based model checking + // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. + // So we have to flip the answer. + if (boost::starts_with(response, "unsat")) + { + // Repeat the query with preprocessing disabled, to get the full proof + setupSmtCallback(false); + query = "(set-option :produce-proofs true)" + query + "\n(get-proof)"; #ifdef EMSCRIPTEN_BUILD - z3::set_param("fp.xform.slice", false); - z3::set_param("fp.xform.inline_linear", false); - z3::set_param("fp.xform.inline_eager", false); - response = Z3_eval_smtlib2_string(z3::context{}, query.c_str()); + z3::set_param("fp.xform.slice", false); + z3::set_param("fp.xform.inline_linear", false); + z3::set_param("fp.xform.inline_eager", false); + response = Z3_eval_smtlib2_string(z3::context{}, query.c_str()); #else - response = querySolver(query); + response = querySolver(query); #endif - setupSmtCallback(true); - if (!boost::starts_with(response, "unsat")) - return {CheckResult::SATISFIABLE, Expression(true), {}}; - return {CheckResult::SATISFIABLE, Expression(true), graphFromZ3Answer(response)}; - } + setupSmtCallback(true); + if (!boost::starts_with(response, "unsat")) + return {CheckResult::SATISFIABLE, Expression(true), {}}; + return {CheckResult::SATISFIABLE, Expression(true), graphFromZ3Answer(response)}; + } - CheckResult result; - if (boost::starts_with(response, "sat")) + CheckResult result; + if (boost::starts_with(response, "sat")) + { + auto maybeInvariants = invariantsFromSolverResponse(response); + return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; + } + else if (boost::starts_with(response, "unknown")) + result = CheckResult::UNKNOWN; + else + result = CheckResult::ERROR; + + return {result, Expression(true), {}}; + } + catch(smtutil::SMTSolverInteractionError const&) { - auto maybeInvariants = invariantsFromSolverResponse(response); - return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; + return {CheckResult::ERROR, Expression(true), {}}; } - else if (boost::starts_with(response, "unknown")) - result = CheckResult::UNKNOWN; - else - result = CheckResult::ERROR; - - return {result, Expression(true), {}}; } @@ -112,7 +119,7 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromZ3Answer(std::strin std::stringstream ss(_proof); std::string answer; ss >> answer; - smtAssert(answer == "unsat"); + smtSolverInteractionRequire(answer == "unsat", "Proof must follow an unsat answer"); SMTLib2Parser parser(ss); if (parser.isEOF()) // No proof from Z3 @@ -125,10 +132,10 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromZ3Answer(std::strin } catch (SMTLib2Parser::ParsingException&) { - return {}; + smtSolverInteractionRequire(false, "Error during parsing Z3's proof"); } - solAssert(parser.isEOF()); - solAssert(!isAtom(parsedOutput)); + smtSolverInteractionRequire(parser.isEOF(), "Error during parsing Z3's proof"); + smtSolverInteractionRequire(!isAtom(parsedOutput), "Encountered unexpected format of Z3's proof"); auto& commands = asSubExpressions(parsedOutput); ScopedParser expressionParser(m_context); for (auto& command: commands) @@ -137,7 +144,7 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromZ3Answer(std::strin continue; auto const& args = asSubExpressions(command); - solAssert(args.size() > 0); + smtSolverInteractionRequire(args.size() > 0, "Encountered unexpected format of Z3's proof"); auto const& head = args[0]; if (!isAtom(head)) continue; @@ -146,12 +153,12 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromZ3Answer(std::strin // e.g., "(declare-fun query!0 (Bool Bool Bool Int Int Bool Bool Bool Bool Bool Bool Bool Int) Bool)" if (asAtom(head) == "declare-fun") { - solAssert(args.size() == 4); + smtSolverInteractionRequire(args.size() == 4, "Encountered unexpected format of Z3's proof"); auto const& name = args[1]; auto const& domainSorts = args[2]; auto const& codomainSort = args[3]; - solAssert(isAtom(name)); - solAssert(!isAtom(domainSorts)); + smtSolverInteractionRequire(isAtom(name), "Encountered unexpected format of Z3's proof"); + smtSolverInteractionRequire(!isAtom(domainSorts), "Encountered unexpected format of Z3's proof"); expressionParser.addVariableDeclaration(asAtom(name), expressionParser.toSort(codomainSort)); } // The subexpression starting with "proof" contains the whole proof, which we need to transform to our internal @@ -173,13 +180,13 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromSMTLib2Expression( auto fact = [](SMTLib2Expression const& _node) -> SMTLib2Expression const& { if (isAtom(_node)) return _node; - smtAssert(!asSubExpressions(_node).empty()); + smtSolverInteractionRequire(!asSubExpressions(_node).empty(), "Encountered unexpected format of Z3's proof"); return asSubExpressions(_node).back(); }; - smtAssert(!isAtom(_proof)); + smtSolverInteractionRequire(!isAtom(_proof), "Encountered unexpected format of Z3's proof"); auto const& proofArgs = asSubExpressions(_proof); - smtAssert(proofArgs.size() == 2); - smtAssert(isAtom(proofArgs.at(0)) && asAtom(proofArgs.at(0)) == "proof"); + smtSolverInteractionRequire(proofArgs.size() == 2, "Encountered unexpected format of Z3's proof"); + smtSolverInteractionRequire(isAtom(proofArgs.at(0)) && asAtom(proofArgs.at(0)) == "proof", "Encountered unexpected format of Z3's proof"); auto const& proofNode = proofArgs.at(1); auto const& derivedFact = fact(proofNode); if (isAtom(proofNode) || !isAtom(derivedFact) || asAtom(derivedFact) != "false") @@ -201,7 +208,7 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromSMTLib2Expression( auto isHyperRes = [](SMTLib2Expression const& expr) { if (isAtom(expr)) return false; auto const& subExprs = asSubExpressions(expr); - smtAssert(!subExprs.empty()); + smtSolverInteractionRequire(!subExprs.empty(), "Encountered unexpected format of Z3's proof"); auto const& op = subExprs.at(0); if (isAtom(op)) return false; auto const& opExprs = asSubExpressions(op); @@ -213,15 +220,15 @@ CHCSolverInterface::CexGraph Z3CHCSmtLib2Interface::graphFromSMTLib2Expression( while (!proofStack.empty()) { auto const* currentNode = proofStack.top(); - smtAssert(visitedIds.find(currentNode) != visitedIds.end()); + smtSolverInteractionRequire(visitedIds.find(currentNode) != visitedIds.end(), "Error in processing Z3's proof"); auto id = visitedIds.at(currentNode); - smtAssert(graph.nodes.count(id)); + smtSolverInteractionRequire(graph.nodes.count(id), "Error in processing Z3's proof"); proofStack.pop(); if (isHyperRes(*currentNode)) { auto const& args = asSubExpressions(*currentNode); - smtAssert(args.size() > 1); + smtSolverInteractionRequire(args.size() > 1, "Unexpected format of hyper-resolution rule in Z3's proof"); // args[0] is the name of the rule // args[1] is the clause used // last argument is the derived fact From c8d9fc3fb41ae6cec35c8d140d11110d1ffd8805 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 22 Oct 2024 15:56:12 +0200 Subject: [PATCH 0437/1340] Remove remaining artifacts of dynamically loading Z3. --- .circleci/config.yml | 2 +- cmake/EthCompilerSettings.cmake | 3 - libsmtutil/Z3CHCInterface.cpp | 244 -------------- libsmtutil/Z3CHCInterface.h | 72 ---- libsmtutil/Z3Interface.cpp | 487 ---------------------------- libsmtutil/Z3Interface.h | 75 ----- libsmtutil/Z3Loader.cpp | 69 ---- libsmtutil/Z3Loader.h | 38 --- libsmtutil/genz3wrapper.py | 99 ------ libsolidity/formal/BMC.cpp | 7 - libsolidity/formal/ModelChecker.cpp | 6 - 11 files changed, 1 insertion(+), 1101 deletions(-) delete mode 100644 libsmtutil/Z3CHCInterface.cpp delete mode 100644 libsmtutil/Z3CHCInterface.h delete mode 100644 libsmtutil/Z3Interface.cpp delete mode 100644 libsmtutil/Z3Interface.h delete mode 100644 libsmtutil/Z3Loader.cpp delete mode 100644 libsmtutil/Z3Loader.h delete mode 100755 libsmtutil/genz3wrapper.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 79a149a7e..a8f6d7552 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1049,7 +1049,7 @@ jobs: <<: *base_ubuntu2004_xlarge environment: <<: *base_ubuntu2004_xlarge_env - CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DSOLC_STATIC_STDLIBS=ON + CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DSOLC_STATIC_STDLIBS=ON steps: - checkout - run_build diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 4cf3927d1..8b40bb2c5 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -263,6 +263,3 @@ endif() # SMT Solvers integration option(USE_Z3 "Allow compiling with Z3 SMT solver integration" ON) -if(UNIX AND NOT APPLE) - option(USE_Z3_DLOPEN "Dynamically load the Z3 SMT solver instead of linking against it." OFF) -endif() diff --git a/libsmtutil/Z3CHCInterface.cpp b/libsmtutil/Z3CHCInterface.cpp deleted file mode 100644 index a79630b6e..000000000 --- a/libsmtutil/Z3CHCInterface.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* - 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 - -#include - -#include - -#include -#include - -using namespace solidity; -using namespace solidity::smtutil; - -Z3CHCInterface::Z3CHCInterface(std::optional _queryTimeout): - CHCSolverInterface(_queryTimeout), - m_z3Interface(std::make_unique(m_queryTimeout)), - m_context(m_z3Interface->context()), - m_solver(*m_context) -{ - Z3_get_version( - &std::get<0>(m_version), - &std::get<1>(m_version), - &std::get<2>(m_version), - &std::get<3>(m_version) - ); - - // These need to be set globally. - z3::set_param("rewriter.pull_cheap_ite", true); - - if (m_queryTimeout) - m_context->set("timeout", int(*m_queryTimeout)); - else - z3::set_param("rlimit", Z3Interface::resourceLimit); - - setSpacerOptions(); -} - -void Z3CHCInterface::declareVariable(std::string const& _name, SortPointer const& _sort) -{ - smtAssert(_sort, ""); - m_z3Interface->declareVariable(_name, _sort); -} - -void Z3CHCInterface::registerRelation(Expression const& _expr) -{ - smtAssert(_expr.sort->kind == Kind::Function); - m_z3Interface->declareVariable(_expr.name, _expr.sort); - m_solver.register_relation(m_z3Interface->functions().at(_expr.name)); -} - -void Z3CHCInterface::addRule(Expression const& _expr, std::string const& _name) -{ - z3::expr rule = m_z3Interface->toZ3Expr(_expr); - if (m_z3Interface->constants().empty()) - m_solver.add_rule(rule, m_context->str_symbol(_name.c_str())); - else - { - z3::expr_vector variables(*m_context); - for (auto const& var: m_z3Interface->constants()) - variables.push_back(var.second); - z3::expr boundRule = z3::forall(variables, rule); - m_solver.add_rule(boundRule, m_context->str_symbol(_name.c_str())); - } -} - -CHCSolverInterface::QueryResult Z3CHCInterface::query(Expression const& _expr) -{ - CheckResult result; - try - { - z3::expr z3Expr = m_z3Interface->toZ3Expr(_expr); - switch (m_solver.query(z3Expr)) - { - case z3::check_result::sat: - { - result = CheckResult::SATISFIABLE; - // z3 version 4.8.8 modified Spacer to also return - // proofs containing nonlinear clauses. - if (m_version >= std::tuple(4, 8, 8, 0)) - { - auto proof = m_solver.get_answer(); - return {result, Expression(true), cexGraph(proof)}; - } - break; - } - case z3::check_result::unsat: - { - result = CheckResult::UNSATISFIABLE; - auto invariants = m_z3Interface->fromZ3Expr(m_solver.get_answer()); - return {result, std::move(invariants), {}}; - } - case z3::check_result::unknown: - { - result = CheckResult::UNKNOWN; - break; - } - } - // TODO retrieve model / invariants - } - catch (z3::exception const& _err) - { - std::set msgs{ - /// Resource limit (rlimit) exhausted. - "max. resource limit exceeded", - /// User given timeout exhausted. - "canceled" - }; - if (msgs.count(_err.msg())) - result = CheckResult::UNKNOWN; - else - result = CheckResult::ERROR; - } - - return {result, Expression(true), {}}; -} - -void Z3CHCInterface::setSpacerOptions(bool _preProcessing) -{ - // Spacer options. - // These needs to be set in the solver. - // https://github.com/Z3Prover/z3/blob/master/src/muz/base/fp_params.pyg - z3::params p(*m_context); - // These are useful for solving problems with arrays and loops. - // Use quantified lemma generalizer. - p.set("fp.spacer.q3.use_qgen", true); - p.set("fp.spacer.mbqi", false); - // Ground pobs by using values from a model. - p.set("fp.spacer.ground_pobs", false); - - // Spacer optimization should be - // - enabled for better solving (default) - // - disable for counterexample generation - p.set("fp.xform.slice", _preProcessing); - p.set("fp.xform.inline_linear", _preProcessing); - p.set("fp.xform.inline_eager", _preProcessing); - - m_solver.set(p); -} - -/** -Convert a ground refutation into a linear or nonlinear counterexample. -The counterexample is given as an implication graph of the form -`premises => conclusion` where `premises` are the predicates -from the body of nonlinear clauses, representing the proof graph. - -This function is based on and similar to -https://github.com/Z3Prover/z3/blob/z3-4.8.8/src/muz/spacer/spacer_context.cpp#L2919 -(spacer::context::get_ground_sat_answer) -which generates linear counterexamples. -It is modified here to accept nonlinear CHCs as well, generating a DAG -instead of a path. -*/ -CHCSolverInterface::CexGraph Z3CHCInterface::cexGraph(z3::expr const& _proof) -{ - /// The root fact of the refutation proof is `false`. - /// The node itself is not a hyper resolution, so we need to - /// extract the `query` hyper resolution node from the - /// `false` node (the first child). - /// The proof has the shape above for z3 >=4.8.8. - /// If an older version is used, this check will fail and no - /// counterexample will be generated. - if (!_proof.is_app() || fact(_proof).decl().decl_kind() != Z3_OP_FALSE) - return {}; - - CexGraph graph; - - std::stack proofStack; - proofStack.push(_proof.arg(0)); - - auto const& root = proofStack.top(); - graph.nodes.emplace(root.id(), m_z3Interface->fromZ3Expr(fact(root))); - - std::set visited; - visited.insert(root.id()); - - while (!proofStack.empty()) - { - z3::expr proofNode = proofStack.top(); - smtAssert(graph.nodes.count(proofNode.id()), ""); - proofStack.pop(); - - if (proofNode.is_app() && proofNode.decl().decl_kind() == Z3_OP_PR_HYPER_RESOLVE) - { - smtAssert(proofNode.num_args() > 0, ""); - for (unsigned i = 1; i < proofNode.num_args() - 1; ++i) - { - z3::expr child = proofNode.arg(i); - if (!visited.count(child.id())) - { - visited.insert(child.id()); - proofStack.push(child); - } - - if (!graph.nodes.count(child.id())) - { - graph.nodes.emplace(child.id(), m_z3Interface->fromZ3Expr(fact(child))); - graph.edges[child.id()] = {}; - } - - graph.edges[proofNode.id()].push_back(child.id()); - } - } - } - - return graph; -} - -z3::expr Z3CHCInterface::fact(z3::expr const& _node) -{ - smtAssert(_node.is_app(), ""); - if (_node.num_args() == 0) - return _node; - return _node.arg(_node.num_args() - 1); -} - -std::string Z3CHCInterface::name(z3::expr const& _predicate) -{ - smtAssert(_predicate.is_app(), ""); - return _predicate.decl().name().str(); -} - -std::vector Z3CHCInterface::arguments(z3::expr const& _predicate) -{ - smtAssert(_predicate.is_app(), ""); - std::vector args; - for (unsigned i = 0; i < _predicate.num_args(); ++i) - args.emplace_back(_predicate.arg(i).to_string()); - return args; -} diff --git a/libsmtutil/Z3CHCInterface.h b/libsmtutil/Z3CHCInterface.h deleted file mode 100644 index 98f21246c..000000000 --- a/libsmtutil/Z3CHCInterface.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - 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 - -/** - * Z3 specific Horn solver interface. - */ - -#pragma once - -#include -#include - -#include -#include - -namespace solidity::smtutil -{ - -class Z3CHCInterface: public CHCSolverInterface -{ -public: - Z3CHCInterface(std::optional _queryTimeout = {}); - - /// Forwards variable declaration to Z3Interface. - void declareVariable(std::string const& _name, SortPointer const& _sort) override; - - void registerRelation(Expression const& _expr) override; - - void addRule(Expression const& _expr, std::string const& _name) override; - - QueryResult query(Expression const& _expr) override; - - Z3Interface* z3Interface() const { return m_z3Interface.get(); } - - void setSpacerOptions(bool _preProcessing = true); - -private: - /// Constructs a nonlinear counterexample graph from the refutation. - CHCSolverInterface::CexGraph cexGraph(z3::expr const& _proof); - /// @returns the fact from a proof node. - z3::expr fact(z3::expr const& _node); - /// @returns @a _predicate's name. - std::string name(z3::expr const& _predicate); - /// @returns the arguments of @a _predicate. - std::vector arguments(z3::expr const& _predicate); - - // Used to handle variables. - std::unique_ptr m_z3Interface; - - z3::context* m_context; - // Horn solver. - z3::fixedpoint m_solver; - - std::tuple m_version = std::tuple(0, 0, 0, 0); -}; - -} diff --git a/libsmtutil/Z3Interface.cpp b/libsmtutil/Z3Interface.cpp deleted file mode 100644 index efd656259..000000000 --- a/libsmtutil/Z3Interface.cpp +++ /dev/null @@ -1,487 +0,0 @@ -/* - 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 - -#include - -#include -#include -#include - -#ifdef HAVE_Z3_DLOPEN -#include -#endif - -using namespace solidity::smtutil; -using namespace solidity::util; - -bool Z3Interface::available() -{ -#ifdef HAVE_Z3_DLOPEN - return Z3Loader::get().available(); -#else - return true; -#endif -} - -Z3Interface::Z3Interface(std::optional _queryTimeout): - BMCSolverInterface(_queryTimeout), - m_solver(m_context) -{ - // These need to be set globally. - z3::set_param("rewriter.pull_cheap_ite", true); - - if (m_queryTimeout) - m_context.set("timeout", int(*m_queryTimeout)); - else - z3::set_param("rlimit", resourceLimit); -} - -void Z3Interface::reset() -{ - m_constants.clear(); - m_functions.clear(); - m_solver.reset(); -} - -void Z3Interface::push() -{ - m_solver.push(); -} - -void Z3Interface::pop() -{ - m_solver.pop(); -} - -void Z3Interface::declareVariable(std::string const& _name, SortPointer const& _sort) -{ - smtAssert(_sort, ""); - if (_sort->kind == Kind::Function) - declareFunction(_name, *_sort); - else if (m_constants.count(_name)) - m_constants.at(_name) = m_context.constant(_name.c_str(), z3Sort(*_sort)); - else - m_constants.emplace(_name, m_context.constant(_name.c_str(), z3Sort(*_sort))); -} - -void Z3Interface::declareFunction(std::string const& _name, Sort const& _sort) -{ - smtAssert(_sort.kind == Kind::Function, ""); - FunctionSort fSort = dynamic_cast(_sort); - if (m_functions.count(_name)) - m_functions.at(_name) = m_context.function(_name.c_str(), z3Sort(fSort.domain), z3Sort(*fSort.codomain)); - else - m_functions.emplace(_name, m_context.function(_name.c_str(), z3Sort(fSort.domain), z3Sort(*fSort.codomain))); -} - -void Z3Interface::addAssertion(Expression const& _expr) -{ - m_solver.add(toZ3Expr(_expr)); -} - -std::pair> Z3Interface::check(std::vector const& _expressionsToEvaluate) -{ - CheckResult result; - std::vector values; - try - { - switch (m_solver.check()) - { - case z3::check_result::sat: - result = CheckResult::SATISFIABLE; - break; - case z3::check_result::unsat: - result = CheckResult::UNSATISFIABLE; - break; - case z3::check_result::unknown: - result = CheckResult::UNKNOWN; - break; - } - - if (result == CheckResult::SATISFIABLE && !_expressionsToEvaluate.empty()) - { - z3::model m = m_solver.get_model(); - for (Expression const& e: _expressionsToEvaluate) - values.push_back(util::toString(m.eval(toZ3Expr(e)))); - } - } - catch (z3::exception const& _err) - { - std::set msgs{ - /// Resource limit (rlimit) exhausted. - "max. resource limit exceeded", - /// User given timeout exhausted. - "canceled" - }; - - if (msgs.count(_err.msg())) - result = CheckResult::UNKNOWN; - else - result = CheckResult::ERROR; - values.clear(); - } - - return std::make_pair(result, values); -} - -z3::expr Z3Interface::toZ3Expr(Expression const& _expr) -{ - if (_expr.arguments.empty() && m_constants.count(_expr.name)) - return m_constants.at(_expr.name); - z3::expr_vector arguments(m_context); - for (auto const& arg: _expr.arguments) - arguments.push_back(toZ3Expr(arg)); - - try - { - std::string const& n = _expr.name; - if (m_functions.count(n)) - return m_functions.at(n)(arguments); - else if (m_constants.count(n)) - { - smtAssert(arguments.empty(), ""); - return m_constants.at(n); - } - else if (arguments.empty()) - { - if (n == "true") - return m_context.bool_val(true); - else if (n == "false") - return m_context.bool_val(false); - else if (_expr.sort->kind == Kind::Sort) - { - auto sortSort = std::dynamic_pointer_cast(_expr.sort); - smtAssert(sortSort, ""); - return m_context.constant(n.c_str(), z3Sort(*sortSort->inner)); - } - else if (n == "tuple_constructor") - { - auto constructor = z3::func_decl(m_context, Z3_get_tuple_sort_mk_decl(m_context, z3Sort(*_expr.sort))); - smtAssert(constructor.arity() == arguments.size()); - return constructor(); - } - else - try - { - return m_context.int_val(n.c_str()); - } - catch (z3::exception const& _e) - { - smtAssert(false, _e.msg()); - } - } - - smtAssert(_expr.hasCorrectArity(), ""); - if (n == "ite") - return z3::ite(arguments[0], arguments[1], arguments[2]); - else if (n == "not") - return !arguments[0]; - else if (n == "and") - return arguments[0] && arguments[1]; - else if (n == "or") - return arguments[0] || arguments[1]; - else if (n == "=>") - return z3::implies(arguments[0], arguments[1]); - else if (n == "=") - return arguments[0] == arguments[1]; - else if (n == "<") - return arguments[0] < arguments[1]; - else if (n == "<=") - return arguments[0] <= arguments[1]; - else if (n == ">") - return arguments[0] > arguments[1]; - else if (n == ">=") - return arguments[0] >= arguments[1]; - else if (n == "+") - return arguments[0] + arguments[1]; - else if (n == "-") - return arguments[0] - arguments[1]; - else if (n == "*") - return arguments[0] * arguments[1]; - else if (n == "div") - return arguments[0] / arguments[1]; - else if (n == "mod") - return z3::mod(arguments[0], arguments[1]); - else if (n == "bvnot") - return ~arguments[0]; - else if (n == "bvand") - return arguments[0] & arguments[1]; - else if (n == "bvor") - return arguments[0] | arguments[1]; - else if (n == "bvxor") - return arguments[0] ^ arguments[1]; - else if (n == "bvshl") - return z3::shl(arguments[0], arguments[1]); - else if (n == "bvlshr") - return z3::lshr(arguments[0], arguments[1]); - else if (n == "bvashr") - return z3::ashr(arguments[0], arguments[1]); - else if (n == "int2bv") - { - size_t size = std::stoul(_expr.arguments[1].name); - return z3::int2bv(static_cast(size), arguments[0]); - } - else if (n == "bv2int") - { - auto intSort = std::dynamic_pointer_cast(_expr.sort); - smtAssert(intSort, ""); - return z3::bv2int(arguments[0], intSort->isSigned); - } - else if (n == "select") - return z3::select(arguments[0], arguments[1]); - else if (n == "store") - return z3::store(arguments[0], arguments[1], arguments[2]); - else if (n == "const_array") - { - std::shared_ptr sortSort = std::dynamic_pointer_cast(_expr.arguments[0].sort); - smtAssert(sortSort, ""); - auto arraySort = std::dynamic_pointer_cast(sortSort->inner); - smtAssert(arraySort && arraySort->domain, ""); - return z3::const_array(z3Sort(*arraySort->domain), arguments[1]); - } - else if (n == "tuple_get") - { - size_t index = stoul(_expr.arguments[1].name); - return z3::func_decl(m_context, Z3_get_tuple_sort_field_decl(m_context, z3Sort(*_expr.arguments[0].sort), static_cast(index)))(arguments[0]); - } - else if (n == "tuple_constructor") - { - auto constructor = z3::func_decl(m_context, Z3_get_tuple_sort_mk_decl(m_context, z3Sort(*_expr.sort))); - smtAssert(constructor.arity() == arguments.size(), ""); - z3::expr_vector args(m_context); - for (auto const& arg: arguments) - args.push_back(arg); - return constructor(args); - } - - smtAssert(false); - } - catch (z3::exception const& _e) - { - smtAssert(false, _e.msg()); - } - - smtAssert(false); - - // FIXME: Workaround for spurious GCC 12.1 warning (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105794) - util::unreachable(); -} - -Expression Z3Interface::fromZ3Expr(z3::expr const& _expr) -{ - auto sort = fromZ3Sort(_expr.get_sort()); - if (_expr.is_const() || _expr.is_var()) - return Expression(_expr.to_string(), {}, sort); - - if (_expr.is_quantifier()) - { - std::string quantifierName; - if (_expr.is_exists()) - quantifierName = "exists"; - else if (_expr.is_forall()) - quantifierName = "forall"; - else if (_expr.is_lambda()) - quantifierName = "lambda"; - else - smtAssert(false, ""); - return Expression(quantifierName, {fromZ3Expr(_expr.body())}, sort); - } - smtAssert(_expr.is_app(), ""); - std::vector arguments; - for (unsigned i = 0; i < _expr.num_args(); ++i) - arguments.push_back(fromZ3Expr(_expr.arg(i))); - - auto kind = _expr.decl().decl_kind(); - - if (_expr.is_ite()) - return Expression::ite(arguments[0], arguments[1], arguments[2]); - else if (_expr.is_not()) - return !arguments[0]; - else if (_expr.is_and()) - return Expression::mkAnd(arguments); - else if (_expr.is_or()) - return Expression::mkOr(arguments); - else if (_expr.is_implies()) - return Expression::implies(arguments[0], arguments[1]); - else if (_expr.is_eq()) - { - smtAssert(arguments.size() == 2, ""); - return arguments[0] == arguments[1]; - } - else if (kind == Z3_OP_ULT || kind == Z3_OP_SLT) - return arguments[0] < arguments[1]; - else if (kind == Z3_OP_LE || kind == Z3_OP_ULEQ || kind == Z3_OP_SLEQ) - return arguments[0] <= arguments[1]; - else if (kind == Z3_OP_GT || kind == Z3_OP_SGT) - return arguments[0] > arguments[1]; - else if (kind == Z3_OP_GE || kind == Z3_OP_UGEQ || kind == Z3_OP_SGEQ) - return arguments[0] >= arguments[1]; - else if (kind == Z3_OP_ADD) - return Expression::mkPlus(arguments); - else if (kind == Z3_OP_SUB) - { - smtAssert(arguments.size() == 2, ""); - return arguments[0] - arguments[1]; - } - else if (kind == Z3_OP_MUL) - return Expression::mkMul(arguments); - else if (kind == Z3_OP_DIV) - { - smtAssert(arguments.size() == 2, ""); - return arguments[0] / arguments[1]; - } - else if (kind == Z3_OP_MOD) - return arguments[0] % arguments[1]; - else if (kind == Z3_OP_XOR) - return arguments[0] ^ arguments[1]; - else if (kind == Z3_OP_BOR) - return arguments[0] | arguments[1]; - else if (kind == Z3_OP_BAND) - return arguments[0] & arguments[1]; - else if (kind == Z3_OP_BXOR) - return arguments[0] ^ arguments[1]; - else if (kind == Z3_OP_BNOT) - return !arguments[0]; - else if (kind == Z3_OP_BSHL) - return arguments[0] << arguments[1]; - else if (kind == Z3_OP_BLSHR) - return arguments[0] >> arguments[1]; - else if (kind == Z3_OP_BASHR) - return Expression::ashr(arguments[0], arguments[1]); - else if (kind == Z3_OP_INT2BV) - return Expression::int2bv(arguments[0], _expr.get_sort().bv_size()); - else if (kind == Z3_OP_BV2INT) - return Expression::bv2int(arguments[0]); - else if (kind == Z3_OP_EXTRACT) - return Expression("extract", arguments, sort); - else if (kind == Z3_OP_SELECT) - return Expression::select(arguments[0], arguments[1]); - else if (kind == Z3_OP_STORE) - return Expression::store(arguments[0], arguments[1], arguments[2]); - else if (kind == Z3_OP_CONST_ARRAY) - { - auto sortSort = std::make_shared(fromZ3Sort(_expr.get_sort())); - return Expression::const_array(Expression(sortSort), arguments[0]); - } - else if (kind == Z3_OP_DT_CONSTRUCTOR) - { - auto sortSort = std::make_shared(fromZ3Sort(_expr.get_sort())); - return Expression::tuple_constructor(Expression(sortSort), arguments); - } - else if (kind == Z3_OP_DT_ACCESSOR) - return Expression("dt_accessor_" + _expr.decl().name().str(), arguments, sort); - else if (kind == Z3_OP_DT_IS) - return Expression("dt_is", {arguments.at(0)}, sort); - else if ( - kind == Z3_OP_UNINTERPRETED || - kind == Z3_OP_RECURSIVE - ) - return Expression(_expr.decl().name().str(), arguments, fromZ3Sort(_expr.get_sort())); - else if (kind == Z3_OP_CONCAT) - return Expression("concat", arguments, sort); - - smtAssert(false); - - // FIXME: Workaround for spurious GCC 12.1 warning (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105794) - util::unreachable(); -} - -z3::sort Z3Interface::z3Sort(Sort const& _sort) -{ - switch (_sort.kind) - { - case Kind::Bool: - return m_context.bool_sort(); - case Kind::Int: - return m_context.int_sort(); - case Kind::BitVector: - return m_context.bv_sort(dynamic_cast(_sort).size); - case Kind::Array: - { - auto const& arraySort = dynamic_cast(_sort); - return m_context.array_sort(z3Sort(*arraySort.domain), z3Sort(*arraySort.range)); - } - case Kind::Tuple: - { - auto const& tupleSort = dynamic_cast(_sort); - std::vector cMembers; - for (auto const& member: tupleSort.members) - cMembers.emplace_back(member.c_str()); - /// Using this instead of the function below because with that one - /// we can't use `&sorts[0]` here. - std::vector sorts; - for (auto const& sort: tupleSort.components) - sorts.push_back(z3Sort(*sort)); - z3::func_decl_vector projs(m_context); - z3::func_decl tupleConstructor = m_context.tuple_sort( - tupleSort.name.c_str(), - static_cast(tupleSort.members.size()), - cMembers.data(), - sorts.data(), - projs - ); - return tupleConstructor.range(); - } - - default: - break; - } - smtAssert(false, ""); - // Cannot be reached. - return m_context.int_sort(); -} - -z3::sort_vector Z3Interface::z3Sort(std::vector const& _sorts) -{ - z3::sort_vector z3Sorts(m_context); - for (auto const& _sort: _sorts) - z3Sorts.push_back(z3Sort(*_sort)); - return z3Sorts; -} - -SortPointer Z3Interface::fromZ3Sort(z3::sort const& _sort) -{ - if (_sort.is_bool()) - return SortProvider::boolSort; - if (_sort.is_int()) - return SortProvider::sintSort; - if (_sort.is_bv()) - return std::make_shared(_sort.bv_size()); - if (_sort.is_array()) - return std::make_shared(fromZ3Sort(_sort.array_domain()), fromZ3Sort(_sort.array_range())); - if (_sort.is_datatype()) - { - auto name = _sort.name().str(); - auto constructor = z3::func_decl(m_context, Z3_get_tuple_sort_mk_decl(m_context, _sort)); - std::vector memberNames; - std::vector memberSorts; - for (unsigned i = 0; i < constructor.arity(); ++i) - { - auto accessor = z3::func_decl(m_context, Z3_get_tuple_sort_field_decl(m_context, _sort, i)); - memberNames.push_back(accessor.name().str()); - memberSorts.push_back(fromZ3Sort(accessor.range())); - } - return std::make_shared(name, memberNames, memberSorts); - } - smtAssert(false, ""); -} - -std::vector Z3Interface::fromZ3Sort(z3::sort_vector const& _sorts) -{ - return applyMap(_sorts, [this](auto const& sort) { return fromZ3Sort(sort); }); -} diff --git a/libsmtutil/Z3Interface.h b/libsmtutil/Z3Interface.h deleted file mode 100644 index ee5270f44..000000000 --- a/libsmtutil/Z3Interface.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - 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 - -#pragma once - -#include -#include - -namespace solidity::smtutil -{ - -class Z3Interface: public BMCSolverInterface -{ -public: - /// Noncopyable. - Z3Interface(Z3Interface const&) = delete; - Z3Interface& operator=(Z3Interface const&) = delete; - - Z3Interface(std::optional _queryTimeout = {}); - - static bool available(); - - void reset() override; - - void push() override; - void pop() override; - - void declareVariable(std::string const& _name, SortPointer const& _sort) override; - - void addAssertion(Expression const& _expr) override; - std::pair> check(std::vector const& _expressionsToEvaluate) override; - - z3::expr toZ3Expr(Expression const& _expr); - smtutil::Expression fromZ3Expr(z3::expr const& _expr); - - std::map constants() const { return m_constants; } - std::map functions() const { return m_functions; } - - z3::context* context() { return &m_context; } - - // Z3 "basic resources" limit. - // This is used to make the runs more deterministic and platform/machine independent. - static int const resourceLimit = 2000000; - -private: - void declareFunction(std::string const& _name, Sort const& _sort); - - z3::sort z3Sort(Sort const& _sort); - z3::sort_vector z3Sort(std::vector const& _sorts); - smtutil::SortPointer fromZ3Sort(z3::sort const& _sort); - std::vector fromZ3Sort(z3::sort_vector const& _sorts); - - z3::context m_context; - z3::solver m_solver; - - std::map m_constants; - std::map m_functions; -}; - -} diff --git a/libsmtutil/Z3Loader.cpp b/libsmtutil/Z3Loader.cpp deleted file mode 100644 index 0211f600d..000000000 --- a/libsmtutil/Z3Loader.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - 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 - -#include -#include -#include -#include -#include - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include - -using namespace solidity; -using namespace solidity::smtutil; - -Z3Loader const& Z3Loader::get() -{ - static Z3Loader z3; - return z3; -} - -void* Z3Loader::loadSymbol(char const* _name) const -{ - smtAssert(m_handle, "Attempted to use dynamically loaded Z3, even though it is not available."); - void* sym = dlsym(m_handle, _name); - smtAssert(sym, std::string("Symbol \"") + _name + "\" not found in libz3.so"); - return sym; -} - -bool Z3Loader::available() const -{ - if (m_handle == nullptr) - return false; - unsigned major = 0; - unsigned minor = 0; - unsigned build = 0; - unsigned rev = 0; - Z3_get_version(&major, &minor, &build, &rev); - return major == Z3_MAJOR_VERSION && minor == Z3_MINOR_VERSION; -} - -Z3Loader::Z3Loader() -{ - std::string libname{"libz3.so." + std::to_string(Z3_MAJOR_VERSION) + "." + std::to_string(Z3_MINOR_VERSION)}; - m_handle = dlmopen(LM_ID_NEWLM, libname.c_str(), RTLD_NOW); -} - -Z3Loader::~Z3Loader() -{ - if (m_handle) - dlclose(m_handle); -} diff --git a/libsmtutil/Z3Loader.h b/libsmtutil/Z3Loader.h deleted file mode 100644 index 5e755cb24..000000000 --- a/libsmtutil/Z3Loader.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - 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 - -#pragma once - -namespace solidity::smtutil -{ - -class Z3Loader -{ -public: - Z3Loader(Z3Loader const&) = delete; - Z3Loader& operator=(Z3Loader const&) = delete; - static Z3Loader const& get(); - void* loadSymbol(char const* _name) const; - bool available() const; -private: - Z3Loader(); - ~Z3Loader(); - void* m_handle = nullptr; -}; - -} \ No newline at end of file diff --git a/libsmtutil/genz3wrapper.py b/libsmtutil/genz3wrapper.py deleted file mode 100755 index 9b24b32db..000000000 --- a/libsmtutil/genz3wrapper.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python3 -# ------------------------------------------------------------------------------ -# 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 -#------------------------------------------------------------------------------ -# -# Script that generates a dlsym-wrapper for Z3 from the header files. -# Expects all Z3 headers as arguments and outputs the wrapper code to stdout. - -import sys -import re - -# Patterns to match Z3 API entry point definitions. -def_pat = re.compile(" *def_API(.*)") -extradef_pat = re.compile(" *extra_API(.*)") -# Pattern to extract name and arguments from the above. -def_args_pat = re.compile("\('([^']*)'[^\(\)]*\((.*)\)\s*\)") -# Pattern to extract a list of arguments from the above. -arg_list_pat = re.compile("[^\(]*\([^\)]*\)[, ]*") - -def generateEntryPoint(line, args): - m = def_args_pat.match(args) - if not m: - raise Exception('Could not parse entry point definition: ' + line) - name = m.group(1) - num_args = len(arg_list_pat.findall(m.group(2))) - arglist = ', '.join(f"_{i}" for i in range(num_args)) - paramlist = ', '.join(f"ArgType<&{name}, {i}> _{i}" for i in range(num_args)) - print(f'ResultType<&{name}> Z3_API {name}({paramlist})') - print('{') - print(f'\tstatic auto sym = reinterpret_cast(Z3Loader::get().loadSymbol(\"{name}\"));') - print(f'\treturn sym({arglist});') - print('}') - - -print(r"""// This file is auto-generated from genz3wrapper.py -#include -#include -#include - -namespace -{ - -template -struct FunctionTrait; - -template -struct FunctionTrait -{ - using ResultType = R; - template - using ArgType = std::tuple_element_t>; -}; - -template -using ResultType = typename FunctionTrait::ResultType; - -template -using ArgType = typename FunctionTrait::template ArgType; - -} - -using namespace solidity; -using namespace solidity::smtutil; - -extern "C" -{ - -void Z3_API Z3_set_error_handler(Z3_context c, Z3_error_handler h) -{ - static auto sym = reinterpret_cast(Z3Loader::get().loadSymbol("Z3_set_error_handler")); - sym(c, h); -} -""") - -for header in sys.argv[1:]: - with open(header, 'r') as f: - for line in f: - line = line.strip('\r\n\t ') - m = def_pat.match(line) - if m: - generateEntryPoint(line, m.group(1).strip('\r\n\t ')) - m = extradef_pat.match(line) - if m: - generateEntryPoint(line, m.group(1).strip('\r\n\t ')) - -print('}') diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 6f3eb6c4c..679309766 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -30,10 +30,6 @@ #include -#ifdef HAVE_Z3_DLOPEN -#include -#endif - using namespace solidity; using namespace solidity::util; using namespace solidity::langutil; @@ -151,9 +147,6 @@ void BMC::analyze(SourceUnit const& _source, std::map -#ifdef HAVE_Z3_DLOPEN -#include -#endif #include @@ -210,9 +207,6 @@ SMTSolverChoice ModelChecker::checkRequestedSolvers(SMTSolverChoice _enabled, Er 8158_error, SourceLocation(), "Solver z3 was selected for SMTChecker but it is not available." -#ifdef HAVE_Z3_DLOPEN - " libz3.so." + std::to_string(Z3_MAJOR_VERSION) + "." + std::to_string(Z3_MINOR_VERSION) + " was not found." -#endif ); } From 66dc47f1f1e57670c237804be274259d461f460f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 22 Oct 2024 16:05:01 +0200 Subject: [PATCH 0438/1340] EVMVersion::name(): Use util::unreachable() to mark unreachable paths --- liblangutil/EVMVersion.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 3d58fed43..4fdb85aea 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -21,6 +21,8 @@ #pragma once +#include + #include #include #include @@ -105,7 +107,7 @@ class EVMVersion: case Version::Cancun: return "cancun"; case Version::Prague: return "prague"; } - return "INVALID"; + util::unreachable(); } /// Has the RETURNDATACOPY and RETURNDATASIZE opcodes. From a610a5f0acf32ce8bb31588d88deb71c90bf7ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 22 Oct 2024 15:34:58 +0200 Subject: [PATCH 0439/1340] Make it possible to enumerate EVM versions to avoid repetition --- liblangutil/EVMVersion.h | 15 ++++++++++----- solc/CommandLineParser.cpp | 3 +-- test/tools/fuzzer_common.cpp | 14 +------------- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 4fdb85aea..8b41105f1 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -64,9 +65,8 @@ class EVMVersion: static EVMVersion cancun() { return {Version::Cancun}; } static EVMVersion prague() { return {Version::Prague}; } - static std::optional fromString(std::string const& _version) - { - for (auto const& v: { + static std::vector allVersions() { + return { homestead(), tangerineWhistle(), spuriousDragon(), @@ -79,8 +79,13 @@ class EVMVersion: paris(), shanghai(), cancun(), - prague() - }) + prague(), + }; + } + + static std::optional fromString(std::string const& _version) + { + for (auto const& v: allVersions()) if (_version == v.name()) return v; return std::nullopt; diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 4607250a6..aa38e6c7a 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -606,8 +606,7 @@ General Information)").c_str(), ( g_strEVMVersion.c_str(), po::value()->value_name("version")->default_value(EVMVersion{}.name()), - "Select desired EVM version. Either homestead, tangerineWhistle, spuriousDragon, " - "byzantium, constantinople, petersburg, istanbul, berlin, london, paris, shanghai, cancun or prague." + ("Select desired EVM version. Either " + util::joinHumanReadable(EVMVersion::allVersions(), ", ", " or ") + ".").c_str() ) ; if (!_forHelp) // Note: We intentionally keep this undocumented for now. diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index 1caa5357e..6a70c1cc8 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -39,19 +39,7 @@ using namespace solidity::frontend; using namespace solidity::langutil; using namespace solidity::util; -static std::vector s_evmVersions = { - EVMVersion::homestead(), - EVMVersion::tangerineWhistle(), - EVMVersion::spuriousDragon(), - EVMVersion::byzantium(), - EVMVersion::constantinople(), - EVMVersion::petersburg(), - EVMVersion::istanbul(), - EVMVersion::berlin(), - EVMVersion::london(), - EVMVersion::paris(), - EVMVersion::prague() -}; +static std::vector s_evmVersions = EVMVersion::allVersions(); void FuzzerUtil::testCompilerJsonInterface(std::string const& _input, bool _optimize, bool _quiet) { From 167f5547da0e8b14adbd126c5cceb6f27531a3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 22 Oct 2024 16:04:27 +0200 Subject: [PATCH 0440/1340] Mark prague as experimental in places where it was not so (docs, --help) --- docs/using-the-compiler.rst | 2 +- liblangutil/EVMVersion.h | 4 ++++ solc/CommandLineParser.cpp | 12 +++++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 004bb4a61..b2fe490cc 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -345,7 +345,7 @@ Input Description // Version of the EVM to compile for. // Affects type checking and code generation. Can be homestead, // tangerineWhistle, spuriousDragon, byzantium, constantinople, - // petersburg, istanbul, berlin, london, paris, shanghai, cancun (default) or prague. + // petersburg, istanbul, berlin, london, paris, shanghai, cancun (default) or prague (experimental). "evmVersion": "cancun", // Optional: Change compilation pipeline to go through the Yul intermediate representation. // This is false by default. diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 8b41105f1..2201f3c9d 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -91,6 +91,10 @@ class EVMVersion: return std::nullopt; } + bool isExperimental() const { + return m_version == Version::Prague; + } + bool operator==(EVMVersion const& _other) const { return m_version == _other.m_version; } bool operator<(EVMVersion const& _other) const { return m_version < _other.m_version; } diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index aa38e6c7a..592914404 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -592,6 +592,16 @@ General Information)").c_str(), ; desc.add(inputOptions); + auto const annotateEVMVersion = [](EVMVersion const& _version) { + return _version.name() + (_version.isExperimental() ? " (experimental)" : ""); + }; + std::vector allEVMVersions = EVMVersion::allVersions(); + std::string annotatedEVMVersions = util::joinHumanReadable( + allEVMVersions | ranges::views::transform(annotateEVMVersion), + ", ", + " or " + ); + po::options_description outputOptions("Output Options"); outputOptions.add_options() ( @@ -606,7 +616,7 @@ General Information)").c_str(), ( g_strEVMVersion.c_str(), po::value()->value_name("version")->default_value(EVMVersion{}.name()), - ("Select desired EVM version. Either " + util::joinHumanReadable(EVMVersion::allVersions(), ", ", " or ") + ".").c_str() + ("Select desired EVM version: " + annotatedEVMVersions + ".").c_str() ) ; if (!_forHelp) // Note: We intentionally keep this undocumented for now. From 457bed6c3a003a0946665c9322e8c56db615ce2e Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 22 Oct 2024 16:16:02 +0200 Subject: [PATCH 0441/1340] Also eliminate USE_Z3. --- .circleci/build_win.ps1 | 2 +- .circleci/config.yml | 2 - cmake/EthCompilerSettings.cmake | 3 -- cmake/FindZ3.cmake | 80 +++++++++++++++----------------- cmake/toolchains/libfuzzer.cmake | 2 - docs/installing-solidity.rst | 17 ++----- 6 files changed, 42 insertions(+), 64 deletions(-) diff --git a/.circleci/build_win.ps1 b/.circleci/build_win.ps1 index 730bb6319..e95caa7c1 100644 --- a/.circleci/build_win.ps1 +++ b/.circleci/build_win.ps1 @@ -18,7 +18,7 @@ else { mkdir build cd build $boost_dir=(Resolve-Path $PSScriptRoot\..\deps\boost\lib\cmake\Boost-*) -..\deps\cmake\bin\cmake -G "Visual Studio 16 2019" -DBoost_DIR="$boost_dir\" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_INSTALL_PREFIX="$PSScriptRoot\..\upload" -DUSE_Z3=OFF .. +..\deps\cmake\bin\cmake -G "Visual Studio 16 2019" -DBoost_DIR="$boost_dir\" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_INSTALL_PREFIX="$PSScriptRoot\..\upload" .. if ( -not $? ) { throw "CMake configure failed." } msbuild solidity.sln /p:Configuration=Release /m:10 /v:minimal if ( -not $? ) { throw "Build failed." } diff --git a/.circleci/config.yml b/.circleci/config.yml index a8f6d7552..eb5161406 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1110,8 +1110,6 @@ jobs: <<: *base_archlinux_large environment: <<: *base_archlinux_large_env - # This can be switched off if we run out of sync with Arch. - USE_Z3: ON steps: - run: name: Install build dependencies diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 8b40bb2c5..ccbd8a6c4 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -260,6 +260,3 @@ if(COVERAGE) endif() add_compile_options(-g --coverage) endif() - -# SMT Solvers integration -option(USE_Z3 "Allow compiling with Z3 SMT solver integration" ON) diff --git a/cmake/FindZ3.cmake b/cmake/FindZ3.cmake index 092b8636b..0a00fb152 100644 --- a/cmake/FindZ3.cmake +++ b/cmake/FindZ3.cmake @@ -1,51 +1,47 @@ -if (USE_Z3) - # Save and clear Z3_FIND_VERSION, since the - # Z3 config module cannot handle version requirements. - set(Z3_FIND_VERSION_ORIG ${Z3_FIND_VERSION}) - set(Z3_FIND_VERSION) - # Try to find Z3 using its stock cmake files. - find_package(Z3 QUIET CONFIG) - # Restore Z3_FIND_VERSION for find_package_handle_standard_args. - set(Z3_FIND_VERSION ${Z3_FIND_VERSION_ORIG}) - set(Z3_FIND_VERSION_ORIG) +# Save and clear Z3_FIND_VERSION, since the +# Z3 config module cannot handle version requirements. +set(Z3_FIND_VERSION_ORIG ${Z3_FIND_VERSION}) +set(Z3_FIND_VERSION) +# Try to find Z3 using its stock cmake files. +find_package(Z3 QUIET CONFIG) +# Restore Z3_FIND_VERSION for find_package_handle_standard_args. +set(Z3_FIND_VERSION ${Z3_FIND_VERSION_ORIG}) +set(Z3_FIND_VERSION_ORIG) - include(FindPackageHandleStandardArgs) +include(FindPackageHandleStandardArgs) - if (Z3_FOUND) - set(Z3_VERSION ${Z3_VERSION_STRING}) - find_package_handle_standard_args(Z3 CONFIG_MODE) - else() - find_path(Z3_INCLUDE_DIR NAMES z3++.h PATH_SUFFIXES z3) - find_library(Z3_LIBRARY NAMES z3) - find_program(Z3_EXECUTABLE z3 PATH_SUFFIXES bin) +if (Z3_FOUND) + set(Z3_VERSION ${Z3_VERSION_STRING}) + find_package_handle_standard_args(Z3 CONFIG_MODE) +else() + find_path(Z3_INCLUDE_DIR NAMES z3++.h PATH_SUFFIXES z3) + find_library(Z3_LIBRARY NAMES z3) + find_program(Z3_EXECUTABLE z3 PATH_SUFFIXES bin) - if(Z3_INCLUDE_DIR AND Z3_LIBRARY) - if(Z3_EXECUTABLE) - execute_process (COMMAND ${Z3_EXECUTABLE} -version - OUTPUT_VARIABLE libz3_version_str - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) + if(Z3_INCLUDE_DIR AND Z3_LIBRARY) + if(Z3_EXECUTABLE) + execute_process (COMMAND ${Z3_EXECUTABLE} -version + OUTPUT_VARIABLE libz3_version_str + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REGEX REPLACE "^Z3 version ([0-9.]+).*" "\\1" - Z3_VERSION_STRING "${libz3_version_str}") - unset(libz3_version_str) - else() - message(WARNING "Could not determine the version of z3, since the z3 executable was not found.") - set(Z3_VERSION_STRING "0.0.0") - endif() + string(REGEX REPLACE "^Z3 version ([0-9.]+).*" "\\1" + Z3_VERSION_STRING "${libz3_version_str}") + unset(libz3_version_str) + else() + message(WARNING "Could not determine the version of z3, since the z3 executable was not found.") + set(Z3_VERSION_STRING "0.0.0") endif() - mark_as_advanced(Z3_VERSION_STRING z3_DIR) + endif() + mark_as_advanced(Z3_VERSION_STRING z3_DIR) - find_package_handle_standard_args(Z3 - REQUIRED_VARS Z3_LIBRARY Z3_INCLUDE_DIR - VERSION_VAR Z3_VERSION_STRING) + find_package_handle_standard_args(Z3 + REQUIRED_VARS Z3_LIBRARY Z3_INCLUDE_DIR + VERSION_VAR Z3_VERSION_STRING) - if (NOT TARGET z3::libz3) - add_library(z3::libz3 UNKNOWN IMPORTED) - set_property(TARGET z3::libz3 PROPERTY IMPORTED_LOCATION ${Z3_LIBRARY}) - set_property(TARGET z3::libz3 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Z3_INCLUDE_DIR}) - endif() + if (NOT TARGET z3::libz3) + add_library(z3::libz3 UNKNOWN IMPORTED) + set_property(TARGET z3::libz3 PROPERTY IMPORTED_LOCATION ${Z3_LIBRARY}) + set_property(TARGET z3::libz3 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Z3_INCLUDE_DIR}) endif() -else() - set(Z3_FOUND FALSE) endif() diff --git a/cmake/toolchains/libfuzzer.cmake b/cmake/toolchains/libfuzzer.cmake index f9ea64860..272d0bc4d 100644 --- a/cmake/toolchains/libfuzzer.cmake +++ b/cmake/toolchains/libfuzzer.cmake @@ -1,7 +1,5 @@ # Inherit default options include("${CMAKE_CURRENT_LIST_DIR}/default.cmake") -# Enable Z3 -set(USE_Z3 ON CACHE BOOL "Enable Z3" FORCE) # Build fuzzing binaries set(OSSFUZZ ON CACHE BOOL "Enable fuzzer build" FORCE) # Use libfuzzer as the fuzzing back-end diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 5473dbb52..0d63d4821 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -527,23 +527,12 @@ If you are interested what CMake options are available run ``cmake .. -LH``. SMT Solvers ----------- -Solidity can be built against Z3 SMT solver and will do so by default if -it is found in the system. Z3 can be disabled by a ``cmake`` option. - -*Note: In some cases, this can also be a potential workaround for build failures.* - - -Inside the build folder you can disable Z3, since it is enabled by default: - -.. code-block:: bash - - # disables Z3 SMT Solver. - cmake .. -DUSE_Z3=OFF +Solidity can optionally use SMT solvers, namely ``z3``, ``cvc5`` and ``Eldarica``, +but their presence is checked only at runtime, they are not needed for the build to succeed. .. note:: - Solidity can optionally use other solvers, namely ``cvc5`` and ``Eldarica``, - but their presence is checked only at runtime, they are not needed for the build to succeed. + The emscripten builds require Z3 and will statically link against it instead. The Version String in Detail ============================ From 017d24bcc3ec0cc18510e0ce1defee80ce8cd92b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:03:03 +0200 Subject: [PATCH 0442/1340] SSACFGBuilder: Descent into constant condition for loops' conditions --- libyul/backends/evm/SSAControlFlowGraphBuilder.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index dacd06180..e7b3c9e6d 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -421,6 +421,7 @@ void SSAControlFlowGraphBuilder::operator()(ForLoop const& _loop) if (constantCondition.has_value()) { + std::visit(*this, *_loop.condition); if (*constantCondition) { jump(debugDataOf(*_loop.condition), loopBody); From cbb604ead6d0c00f0eddb46126d0f08cc0f2db7e Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 23 Oct 2024 11:51:18 +0200 Subject: [PATCH 0443/1340] Add `ControlFlowSideEffects` parameter to `createFunction` in EVMDialect --- libyul/ControlFlowSideEffects.h | 24 +++++++++++++++++++++ libyul/backends/evm/EVMDialect.cpp | 34 +++++++++++++----------------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/libyul/ControlFlowSideEffects.h b/libyul/ControlFlowSideEffects.h index d4debab93..554019135 100644 --- a/libyul/ControlFlowSideEffects.h +++ b/libyul/ControlFlowSideEffects.h @@ -18,6 +18,9 @@ #pragma once +#include +#include + namespace solidity::yul { @@ -44,6 +47,27 @@ struct ControlFlowSideEffects { return (canTerminate || canRevert) && !canContinue; } + + static ControlFlowSideEffects fromInstruction(evmasm::Instruction _instruction) + { + ControlFlowSideEffects controlFlowSideEffects; + if (evmasm::SemanticInformation::terminatesControlFlow(_instruction)) + { + controlFlowSideEffects.canContinue = false; + if (evmasm::SemanticInformation::reverts(_instruction)) + { + controlFlowSideEffects.canTerminate = false; + controlFlowSideEffects.canRevert = true; + } + else + { + controlFlowSideEffects.canTerminate = true; + controlFlowSideEffects.canRevert = false; + } + } + + return controlFlowSideEffects; + } }; } diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 1ed422551..27a1f1426 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -68,20 +68,7 @@ BuiltinFunctionForEVM createEVMFunction( f.numParameters = static_cast(info.args); f.numReturns = static_cast(info.ret); f.sideEffects = EVMDialect::sideEffectsOfInstruction(_instruction); - if (evmasm::SemanticInformation::terminatesControlFlow(_instruction)) - { - f.controlFlowSideEffects.canContinue = false; - if (evmasm::SemanticInformation::reverts(_instruction)) - { - f.controlFlowSideEffects.canTerminate = false; - f.controlFlowSideEffects.canRevert = true; - } - else - { - f.controlFlowSideEffects.canTerminate = true; - f.controlFlowSideEffects.canRevert = false; - } - } + f.controlFlowSideEffects = ControlFlowSideEffects::fromInstruction(_instruction); f.isMSize = _instruction == evmasm::Instruction::MSIZE; f.literalArguments.clear(); f.instruction = _instruction; @@ -100,6 +87,7 @@ BuiltinFunctionForEVM createFunction( size_t _params, size_t _returns, SideEffects _sideEffects, + ControlFlowSideEffects _controlFlowSideEffects, std::vector> _literalArguments, std::function _generateCode ) @@ -111,6 +99,7 @@ BuiltinFunctionForEVM createFunction( f.numParameters = _params; f.numReturns = _returns; f.sideEffects = _sideEffects; + f.controlFlowSideEffects = _controlFlowSideEffects; f.literalArguments = std::move(_literalArguments); f.isMSize = false; f.instruction = {}; @@ -231,16 +220,17 @@ std::vector> createBuiltins(langutil::EVMVe size_t _params, size_t _returns, SideEffects _sideEffects, + ControlFlowSideEffects _controlFlowSideEffects, std::vector> _literalArguments, std::function _generateCode ) -> std::optional { if (!_objectAccess) return std::nullopt; - return createFunction(_name, _params, _returns, _sideEffects, std::move(_literalArguments), std::move(_generateCode)); + return createFunction(_name, _params, _returns, _sideEffects, _controlFlowSideEffects, std::move(_literalArguments), std::move(_generateCode)); }; - builtins.emplace_back(createIfObjectAccess("linkersymbol", 1, 1, SideEffects{}, {LiteralKind::String}, []( + builtins.emplace_back(createIfObjectAccess("linkersymbol", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& @@ -254,6 +244,7 @@ std::vector> createBuiltins(langutil::EVMVe 1, 1, SideEffects{}, + ControlFlowSideEffects{}, {LiteralKind::Number}, []( FunctionCall const& _call, @@ -268,7 +259,7 @@ std::vector> createBuiltins(langutil::EVMVe ); if (!_eofVersion.has_value()) { - builtins.emplace_back(createIfObjectAccess("datasize", 1, 1, SideEffects{}, {LiteralKind::String}, []( + builtins.emplace_back(createIfObjectAccess("datasize", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& _context @@ -289,7 +280,7 @@ std::vector> createBuiltins(langutil::EVMVe _assembly.appendDataSize(subIdPath); } })); - builtins.emplace_back(createIfObjectAccess("dataoffset", 1, 1, SideEffects{}, {LiteralKind::String}, []( + builtins.emplace_back(createIfObjectAccess("dataoffset", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& _context @@ -325,6 +316,7 @@ std::vector> createBuiltins(langutil::EVMVe SideEffects::Write, // memory SideEffects::None // transientStorage }, + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::CODECOPY), {}, []( FunctionCall const&, @@ -349,6 +341,7 @@ std::vector> createBuiltins(langutil::EVMVe SideEffects::Write, // memory SideEffects::None // transientStorage }, + ControlFlowSideEffects{}, {std::nullopt, LiteralKind::String, std::nullopt}, []( FunctionCall const& _call, @@ -365,6 +358,7 @@ std::vector> createBuiltins(langutil::EVMVe 1, 1, SideEffects{}, + ControlFlowSideEffects{}, {LiteralKind::String}, []( FunctionCall const& _call, @@ -382,7 +376,8 @@ std::vector> createBuiltins(langutil::EVMVe "auxdataloadn", 1, 1, - SideEffects{}, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::DATALOADN), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::DATALOADN), {LiteralKind::Number}, []( FunctionCall const& _call, @@ -531,6 +526,7 @@ BuiltinFunctionForEVM EVMDialect::createVerbatimFunction(size_t _arguments, size 1 + _arguments, _returnVariables, SideEffects::worst(), + ControlFlowSideEffects{}, std::vector>{LiteralKind::String} + std::vector>(_arguments), [=]( FunctionCall const& _call, From edc352b03d28aa87f0311cc08f38533bfc5764be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 25 Oct 2024 03:17:42 +0200 Subject: [PATCH 0444/1340] cmdlineTests.sh: Compare stderr first and exit code last - Comparing exit code first looks confusing in CI, because we see that there is an error but not what it is. - Similarly, we wnat to see the errors before we see the difference in output (which is usually just the stdout becoming empty) --- test/cmdlineTests.sh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 4f7b88fe9..3c781ea78 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -275,12 +275,18 @@ EOF sed -i.bak -e 's/^\(Dynamic exception type:\).*/\1/' "$stderr_path" rm "$stderr_path.bak" - if [[ $exitCode -ne "$exit_code_expected" ]] + if [[ "$(cat "$stderr_path")" != "${stderr_expected}" ]] then - printError "Incorrect exit code. Expected $exit_code_expected but got $exitCode." + printError "Incorrect output on stderr received. Expected:" + echo -e "${stderr_expected}" - [[ $exit_code_expectation_file != "" ]] && ask_expectation_update "$exitCode" "$exit_code_expectation_file" - [[ $exit_code_expectation_file == "" ]] && fail + printError "But got:" + echo -e "$(cat "$stderr_path")" + + printError "When running $solc_command" + + [[ $stderr_expectation_file != "" ]] && ask_expectation_update "$(cat "$stderr_path")" "$stderr_expectation_file" + [[ $stderr_expectation_file == "" ]] && fail fi if [[ "$(cat "$stdout_path")" != "${stdout_expected}" ]] @@ -297,18 +303,12 @@ EOF [[ $stdout_expectation_file == "" ]] && fail fi - if [[ "$(cat "$stderr_path")" != "${stderr_expected}" ]] + if [[ $exitCode -ne "$exit_code_expected" ]] then - printError "Incorrect output on stderr received. Expected:" - echo -e "${stderr_expected}" - - printError "But got:" - echo -e "$(cat "$stderr_path")" - - printError "When running $solc_command" + printError "Incorrect exit code. Expected $exit_code_expected but got $exitCode." - [[ $stderr_expectation_file != "" ]] && ask_expectation_update "$(cat "$stderr_path")" "$stderr_expectation_file" - [[ $stderr_expectation_file == "" ]] && fail + [[ $exit_code_expectation_file != "" ]] && ask_expectation_update "$exitCode" "$exit_code_expectation_file" + [[ $exit_code_expectation_file == "" ]] && fail fi rm "$stdout_path" "$stderr_path" From 21df0544c1423da72ec37b5fea121826f56bb9b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 25 Oct 2024 03:32:32 +0200 Subject: [PATCH 0445/1340] parallel_cli_tests.py: Handle test runner failures gracefully, by printing the error - No need to let the exception escape and print the whole stack trace. This is an expected situation. --- .circleci/parallel_cli_tests.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.circleci/parallel_cli_tests.py b/.circleci/parallel_cli_tests.py index 45cc83aec..42dabbf05 100755 --- a/.circleci/parallel_cli_tests.py +++ b/.circleci/parallel_cli_tests.py @@ -37,10 +37,13 @@ else: filters = list(selected_tests) -subprocess.run( - ['test/cmdlineTests.sh'] + filters, - stdin=sys.stdin, - stdout=sys.stdout, - stderr=sys.stderr, - check=True, -) +try: + subprocess.run( + ['test/cmdlineTests.sh'] + filters, + stdin=sys.stdin, + stdout=sys.stdout, + stderr=sys.stderr, + check=True, + ) +except subprocess.CalledProcessError as exception: + sys.exit(exception) From f5914232d335df35fe40acecbac6099310ce517d Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 25 Oct 2024 11:59:09 +0200 Subject: [PATCH 0446/1340] eof: Fix `AuxDataLoadN` immediate argument printing --- libevmasm/AssemblyItem.cpp | 2 +- test/cmdlineTests/strict_asm_eof_dataloadn_prague/output | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 202bb2256..3ce6238bc 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -342,7 +342,7 @@ std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const break; case AuxDataLoadN: assertThrow(data() <= std::numeric_limits::max(), AssemblyException, "Invalid auxdataloadn argument."); - text = "auxdataloadn(" + std::to_string(static_cast(data())) + ")"; + text = "auxdataloadn{" + std::to_string(static_cast(data())) + "}"; break; } if (m_jumpType == JumpType::IntoFunction || m_jumpType == JumpType::OutOfFunction) diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output b/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output index 5f768feeb..1c06caa5e 100644 --- a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output @@ -17,7 +17,7 @@ Binary representation: ef0001010004020001000904002d000080ffffd1000d5f5260205ff348656c6c6f2c20576f726c6421 Text representation: - auxdataloadn(0) + auxdataloadn{0} 0x00 mstore 0x20 From 42d94f5ee100303113058e18573c4ed2fc854322 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 25 Oct 2024 12:14:35 +0200 Subject: [PATCH 0447/1340] Yulopti: Fix parsing error --- test/tools/yulopti.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index cbe021967..e3ea50d09 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -91,7 +91,7 @@ class YulOpti try { auto ast = yul::Parser(errorReporter, m_dialect).parse(_charStream); - if (!m_astRoot || errorReporter.hasErrors()) + if (!ast || errorReporter.hasErrors()) { std::cerr << "Error parsing source." << std::endl; printErrors(_charStream, errors); From e5bfa54f580a0a96943de44afdfb54b0f57660c6 Mon Sep 17 00:00:00 2001 From: monem <119044801+pucedoteth@users.noreply.github.com> Date: Tue, 29 Oct 2024 01:33:55 +0200 Subject: [PATCH 0448/1340] Update ReleaseChecklist.md --- ReleaseChecklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 8ca2e7f96..a70afe0cb 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -76,7 +76,7 @@ At least a day before the release: - [ ] Create a pull request in solc-bin and merge. ### Homebrew and MacOS - - [ ] Update the version and the hash (``sha256sum solidity_$VERSION.tar.gz``) in the [``solidity`` formula in Homebrew core repository](https://github.com/Homebrew/homebrew-core/blob/master/Formula/solidity.rb). + - [ ] Update the version and the hash (``sha256sum solidity_$VERSION.tar.gz``) in the [``solidity`` formula in Homebrew core repository](https://github.com/Homebrew/homebrew-core/blob/master/Formula/s/solidity.rb). ### Docker - [ ] Run ``./scripts/docker_deploy_manual.sh v$VERSION``. From d4078ee5abed5dbb4ecd20c3990f541666e5fa02 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 29 Oct 2024 09:38:33 +0100 Subject: [PATCH 0449/1340] eof: Update `dataloadn` test with new immediate arguments notation --- test/libyul/objectCompiler/eof/dataloadn.yul | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/libyul/objectCompiler/eof/dataloadn.yul b/test/libyul/objectCompiler/eof/dataloadn.yul index 8b1c7ab80..b38222917 100644 --- a/test/libyul/objectCompiler/eof/dataloadn.yul +++ b/test/libyul/objectCompiler/eof/dataloadn.yul @@ -9,12 +9,12 @@ object "a" { } // ==== -// bytecodeFormat: >=EOFv1 // EVMVersion: >=prague +// bytecodeFormat: >=EOFv1 // ---- // Assembly: // /* "source":56:71 */ -// auxdataloadn(0) +// auxdataloadn{0} // /* "source":53:54 */ // 0x00 // /* "source":46:72 */ @@ -29,4 +29,4 @@ object "a" { // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 // Bytecode: ef0001010004020001000904002d000080ffffd1000d5f5260205ff348656c6c6f2c20576f726c6421 // Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP MULMOD DIV STOP 0x2D STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT DATALOADN 0xD PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN BASEFEE PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000 -// SourceMappings: 56:15:0:-:0;53:1;46:26;95:2;92:1;85:13 \ No newline at end of file +// SourceMappings: 56:15:0:-:0;53:1;46:26;95:2;92:1;85:13 From 41edff7100b58780111662043df59ec364ef99f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 29 Oct 2024 14:22:27 +0100 Subject: [PATCH 0450/1340] via_ir_equivalence test: Fix syntqax used to check for a list match --- test/cmdlineTests/~via_ir_equivalence/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cmdlineTests/~via_ir_equivalence/test.sh b/test/cmdlineTests/~via_ir_equivalence/test.sh index d663bef85..0dcfba471 100755 --- a/test/cmdlineTests/~via_ir_equivalence/test.sh +++ b/test/cmdlineTests/~via_ir_equivalence/test.sh @@ -86,7 +86,7 @@ requiresOptimizer=( for contractFile in "${externalContracts[@]}" do - if ! [[ "${requiresOptimizer[*]}" =~ $contractFile ]] + if ! [[ " ${requiresOptimizer[*]} " == *" $contractFile "* ]] then printTask " - ${contractFile}" test_via_ir_equivalence "${REPO_ROOT}/test/${contractFile}" From 1f2c5319507e13126fd626ae9c46977196c58b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 29 Oct 2024 14:21:44 +0100 Subject: [PATCH 0451/1340] Add an EOF pass to soltest --- .circleci/config.yml | 6 ++++++ .circleci/soltest.sh | 35 +++++++++++++++++++++++++++++++++++ .circleci/soltest_all.sh | 35 +++++++++++++++++++++++------------ 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index eb5161406..0bd7932ce 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1141,6 +1141,7 @@ jobs: environment: <<: *base_osx_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 OPTIMIZE: 0 steps: - checkout @@ -1233,6 +1234,7 @@ jobs: environment: <<: *base_archlinux_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 OPTIMIZE: 0 # For Archlinux we do not have prebuilt docker images and we would need to build evmone from source, # thus we forgo semantics tests to speed things up. @@ -1250,6 +1252,7 @@ jobs: environment: <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 OPTIMIZE: 0 # The high parallelism in this job is causing the SMT tests to run out of memory, # so disabling for now. @@ -1299,6 +1302,7 @@ jobs: environment: <<: *base_ubuntu2404_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 OPTIMIZE: 0 SOLTEST_FLAGS: --no-smt ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 @@ -1314,6 +1318,7 @@ jobs: environment: <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 OPTIMIZE: 0 SOLTEST_FLAGS: --no-smt ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 @@ -1326,6 +1331,7 @@ jobs: environment: <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 SOLTEST_FLAGS: --no-smt steps: - soltest diff --git a/.circleci/soltest.sh b/.circleci/soltest.sh index 488201bae..9631a7256 100755 --- a/.circleci/soltest.sh +++ b/.circleci/soltest.sh @@ -36,12 +36,44 @@ set -e OPTIMIZE=${OPTIMIZE:-"0"} EVM=${EVM:-"invalid"} +EOF_VERSION=${EOF_VERSION:-0} CPUs=${CPUs:-3} REPODIR="$(realpath "$(dirname "$0")/..")" IFS=" " read -r -a BOOST_TEST_ARGS <<< "$BOOST_TEST_ARGS" IFS=" " read -r -a SOLTEST_FLAGS <<< "$SOLTEST_FLAGS" +# TODO: [EOF] These won't pass on EOF yet. Reenable them when the implementation is complete. +EOF_EXCLUDES=( + --run_test='!Assembler/all_assembly_items' + --run_test='!Assembler/immutable' + --run_test='!Assembler/immutables_and_its_source_maps' + --run_test='!Optimiser/jumpdest_removal_subassemblies' + --run_test='!Optimiser/jumpdest_removal_subassemblies/*' + --run_test='!SolidityCompiler/does_not_include_creation_time_only_internal_functions' + --run_test='!SolidityInlineAssembly/Analysis/create2' + --run_test='!SolidityInlineAssembly/Analysis/inline_assembly_shadowed_instruction_declaration' + --run_test='!SolidityInlineAssembly/Analysis/large_constant' + --run_test='!SolidityInlineAssembly/Analysis/staticcall' + --run_test='!ViewPureChecker/assembly_staticcall' + --run_test='!functionSideEffects/otherImmovables' + --run_test='!functionSideEffects/state' + --run_test='!functionSideEffects/storage' + --run_test='!gasTests/abiv2' + --run_test='!gasTests/abiv2_optimised' + --run_test='!gasTests/data_storage' + --run_test='!gasTests/dispatch_large' + --run_test='!gasTests/dispatch_large_optimised' + --run_test='!gasTests/dispatch_medium' + --run_test='!gasTests/dispatch_medium_optimised' + --run_test='!gasTests/dispatch_small' + --run_test='!gasTests/dispatch_small_optimised' + --run_test='!gasTests/exp' + --run_test='!gasTests/exp_optimized' + --run_test='!gasTests/storage_costs' + --run_test='!yulStackLayout/literal_loop' +) + # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" # Test result output directory (CircleCI is reading test results from here) @@ -55,6 +87,7 @@ get_logfile_basename() { local filename="${EVM}" test "${OPTIMIZE}" = "1" && filename="${filename}_opt" test "${ABI_ENCODER_V1}" = "1" && filename="${filename}_abiv1" + (( EOF_VERSION != 0 )) && filename="${filename}_eofv${EOF_VERSION}" filename="${filename}_${run}" echo -ne "${filename}" @@ -78,10 +111,12 @@ do "--logger=HRF,error,stdout" "${BOOST_TEST_ARGS[@]}" ) + (( EOF_VERSION != 0 )) && BOOST_TEST_ARGS_RUN+=("${EOF_EXCLUDES[@]}") SOLTEST_ARGS=("--evm-version=$EVM" "${SOLTEST_FLAGS[@]}") test "${OPTIMIZE}" = "1" && SOLTEST_ARGS+=(--optimize) test "${ABI_ENCODER_V1}" = "1" && SOLTEST_ARGS+=(--abiencoderv1) + (( EOF_VERSION != 0 )) && SOLTEST_ARGS+=(--eof-version "$EOF_VERSION") BATCH_ARGS=("--batches" "$((CPUs * CIRCLE_NODE_TOTAL))" "--selected-batch" "$((CPUs * CIRCLE_NODE_INDEX + run))") diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 86c14901b..1c7882448 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -32,12 +32,15 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" source "${REPODIR}/scripts/common.sh" DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shanghai cancun prague) +EVMS_WITH_EOF=(prague) + # Deserialize the EVM_VALUES array if it was provided as argument or # set EVM_VALUES to the default values. IFS=" " read -ra EVM_VALUES <<< "${1:-${DEFAULT_EVM_VALUES[@]}}" DEFAULT_EVM=cancun OPTIMIZE_VALUES=(0 1) +EOF_VERSIONS=(0 1) # Run for ABI encoder v1, without SMTChecker tests. EVM="${DEFAULT_EVM}" \ @@ -53,19 +56,27 @@ for OPTIMIZE in "${OPTIMIZE_VALUES[@]}" do for EVM in "${EVM_VALUES[@]}" do - ENFORCE_GAS_ARGS="" - [ "${EVM}" = "${DEFAULT_EVM}" ] && ENFORCE_GAS_ARGS="--enforce-gas-cost" - # Run SMTChecker tests only when OPTIMIZE == 0 - DISABLE_SMTCHECKER="" - [ "${OPTIMIZE}" != "0" ] && DISABLE_SMTCHECKER="-t !smtCheckerTests" + for EOF_VERSION in "${EOF_VERSIONS[@]}" + do + if (( EOF_VERSION > 0 )) && [[ ! " ${EVMS_WITH_EOF[*]} " == *" $EVM "* ]]; then + continue + fi + + ENFORCE_GAS_ARGS="" + [ "${EVM}" = "${DEFAULT_EVM}" ] && ENFORCE_GAS_ARGS="--enforce-gas-cost" + # Run SMTChecker tests only when OPTIMIZE == 0 + DISABLE_SMTCHECKER="" + [ "${OPTIMIZE}" != "0" ] && DISABLE_SMTCHECKER="-t !smtCheckerTests" - EVM="$EVM" \ - OPTIMIZE="$OPTIMIZE" \ - SOLTEST_FLAGS="$SOLTEST_FLAGS $ENFORCE_GAS_ARGS" \ - BOOST_TEST_ARGS="-t !@nooptions $DISABLE_SMTCHECKER" \ - INDEX_SHIFT="$INDEX_SHIFT" \ - "${REPODIR}/.circleci/soltest.sh" + EVM="$EVM" \ + EOF_VERSION="$EOF_VERSION" \ + OPTIMIZE="$OPTIMIZE" \ + SOLTEST_FLAGS="$SOLTEST_FLAGS $ENFORCE_GAS_ARGS" \ + BOOST_TEST_ARGS="-t !@nooptions $DISABLE_SMTCHECKER" \ + INDEX_SHIFT="$INDEX_SHIFT" \ + "${REPODIR}/.circleci/soltest.sh" - INDEX_SHIFT=$((INDEX_SHIFT + 1)) + INDEX_SHIFT=$((INDEX_SHIFT + 1)) + done done done From e6b0856e1ce910c6477db76e0c3cdd2cae820c63 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 30 Oct 2024 10:20:56 +0100 Subject: [PATCH 0452/1340] Pass object name to `AsmAnalyzer` --- libyul/AsmAnalysis.cpp | 23 +++++++-- libyul/AsmAnalysis.h | 11 +++-- libyul/CompilabilityChecker.cpp | 2 +- libyul/Object.cpp | 49 +++++++++++++++---- libyul/Object.h | 24 ++++++++- libyul/YulStack.cpp | 2 +- libyul/optimiser/StackCompressor.cpp | 6 ++- libyul/optimiser/StackLimitEvader.cpp | 6 ++- test/libyul/Common.cpp | 2 +- .../yulSyntaxTests/eof/object_name_in_eof.yul | 9 ++++ 10 files changed, 111 insertions(+), 23 deletions(-) create mode 100644 test/libyul/yulSyntaxTests/eof/object_name_in_eof.yul diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 84eb39daa..a234fdb81 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -68,6 +68,8 @@ bool AsmAnalyzer::analyze(Block const& _block) auto watcher = m_errorReporter.errorWatcher(); try { + // FIXME: Pass location of the object name. Now it's a location of first code section in yul + validateObjectStructure(nativeLocationOf(_block)); if (!(ScopeFiller(m_info, m_errorReporter))(_block)) return false; @@ -86,13 +88,13 @@ bool AsmAnalyzer::analyze(Block const& _block) AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object) { - return analyzeStrictAssertCorrect(_dialect, _object.code()->root(), _object.qualifiedDataNames()); + return analyzeStrictAssertCorrect(_dialect, _object.code()->root(), _object.summarizeStructure()); } AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( Dialect const& _dialect, Block const& _astRoot, - std::set const& _qualifiedDataNames + Object::Structure const _objectStructure ) { ErrorList errorList; @@ -103,7 +105,7 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( errors, _dialect, {}, - _qualifiedDataNames + std::move(_objectStructure) ).analyze(_astRoot); yulAssert(success && !errors.hasErrors(), "Invalid assembly/yul code."); return analysisInfo; @@ -408,7 +410,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) if (functionName == "datasize" || functionName == "dataoffset") { auto const& argumentAsLiteral = std::get(arg); - if (!m_dataNames.count(formatLiteral(argumentAsLiteral))) + if (!m_objectStructure.contains(formatLiteral(argumentAsLiteral))) m_errorReporter.typeError( 3517_error, nativeLocationOf(arg), @@ -766,3 +768,16 @@ bool AsmAnalyzer::validateInstructions(FunctionCall const& _functionCall) { return validateInstructions(_functionCall.functionName.name.str(), nativeLocationOf(_functionCall.functionName)); } + +void AsmAnalyzer::validateObjectStructure(langutil::SourceLocation _astRootLocation) +{ + if (m_eofVersion.has_value() && util::contains(m_objectStructure.objectName, '.')) // No dots in object name for EOF + m_errorReporter.syntaxError( + 9822_error, + _astRootLocation, + fmt::format( + "The object name \"{objectName}\" is invalid in EOF context. Object names must not contain 'dot' character.", + fmt::arg("objectName", m_objectStructure.objectName) + ) + ); +} diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index d8a2b2b1a..7673e375a 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -61,13 +62,13 @@ class AsmAnalyzer langutil::ErrorReporter& _errorReporter, Dialect const& _dialect, ExternalIdentifierAccess::Resolver _resolver = ExternalIdentifierAccess::Resolver(), - std::set _dataNames = {} + Object::Structure const _objectStructure = {} ): m_resolver(std::move(_resolver)), m_info(_analysisInfo), m_errorReporter(_errorReporter), m_dialect(_dialect), - m_dataNames(std::move(_dataNames)) + m_objectStructure(std::move(_objectStructure)) { if (EVMDialect const* evmDialect = dynamic_cast(&m_dialect)) { @@ -84,7 +85,7 @@ class AsmAnalyzer static AsmAnalysisInfo analyzeStrictAssertCorrect( Dialect const& _dialect, Block const& _astRoot, - std::set const& _qualifiedDataNames + Object::Structure const _objectStructure ); size_t operator()(Literal const& _literal); @@ -120,6 +121,8 @@ class AsmAnalyzer bool validateInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location); bool validateInstructions(FunctionCall const& _functionCall); + void validateObjectStructure(langutil::SourceLocation _astRootLocation); + yul::ExternalIdentifierAccess::Resolver m_resolver; Scope* m_currentScope = nullptr; /// Variables that are active at the current point in assembly (as opposed to @@ -131,7 +134,7 @@ class AsmAnalyzer std::optional m_eofVersion; Dialect const& m_dialect; /// Names of data objects to be referenced by builtin functions with literal arguments. - std::set m_dataNames; + Object::Structure m_objectStructure; ForLoop const* m_currentForLoop = nullptr; /// Worst side effects encountered during analysis (including within defined functions). SideEffects m_sideEffects; diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index 8ece236bf..9cc6bd864 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -44,7 +44,7 @@ CompilabilityChecker::CompilabilityChecker( yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( noOutputDialect, _object.code()->root(), - _object.qualifiedDataNames() + _object.summarizeStructure() ); BuiltinContext builtinContext; diff --git a/libyul/Object.cpp b/libyul/Object.cpp index c6ba5311a..4b8119ffa 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -110,29 +110,60 @@ Json Object::toJson() const return ret; } -std::set Object::qualifiedDataNames() const + +std::set Object::Structure::topLevelSubObjectNames() const +{ + std::set topLevelObjectNames; + + for (auto const& path: objectPaths) + if (!util::contains(path, '.') && path != objectName) + topLevelObjectNames.insert(path); + + return topLevelObjectNames; +} + +Object::Structure Object::summarizeStructure() const { - std::set qualifiedNames = + Structure structure; + + structure.objectPaths = name.empty() || util::contains(name, '.') ? std::set{} : std::set{name}; + + structure.objectName = name; + for (std::shared_ptr const& subObjectNode: subObjects) { - yulAssert(qualifiedNames.count(subObjectNode->name) == 0, ""); + yulAssert(!structure.contains(subObjectNode->name)); if (util::contains(subObjectNode->name, '.')) continue; - qualifiedNames.insert(subObjectNode->name); + if (auto const* subObject = dynamic_cast(subObjectNode.get())) - for (auto const& subSubObj: subObject->qualifiedDataNames()) + { + structure.objectPaths.insert(subObjectNode->name); + + auto const subObjectStructure = subObject->summarizeStructure(); + + for (auto const& subSubObj: subObjectStructure.objectPaths) if (subObject->name != subSubObj) { - yulAssert(qualifiedNames.count(subObject->name + "." + subSubObj) == 0, ""); - qualifiedNames.insert(subObject->name + "." + subSubObj); + yulAssert(!structure.contains(subObject->name + "." + subSubObj)); + structure.objectPaths.insert(subObject->name + "." + subSubObj); + } + for (auto const& subSubObjData: subObjectStructure.dataPaths) + if (subObject->name != subSubObjData) + { + yulAssert(!structure.contains(subObject->name + "." + subSubObjData)); + structure.dataPaths.insert(subObject->name + "." + subSubObjData); } + } + else + structure.dataPaths.insert(subObjectNode->name); } - yulAssert(qualifiedNames.count("") == 0, ""); - return qualifiedNames; + yulAssert(!structure.contains("")); + return structure; } std::vector Object::pathToSubObject(std::string_view _qualifiedName) const diff --git a/libyul/Object.h b/libyul/Object.h index 230f97866..3a89db4bc 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -98,10 +98,32 @@ struct Object: public ObjectNode ) const override; /// @returns a compact JSON representation of the AST. Json toJson() const override; + + /// Summarizes the structure of the subtree rooted at a given object, + /// in particular the paths that can be used from within to refer to nested nodes (objects and data). + struct Structure + { + /// The name of the object + std::string objectName; + /// Available dot-separated paths to nested objects (relative to current object). + std::set objectPaths; + /// Available dot-separated paths to nested data entries (relative to current object). + std::set dataPaths; + + /// Checks if a path is available. + bool contains(std::string const& _path) const { return containsObject(_path) || containsData(_path); } + /// Checks if a path is available and leads to an object. + bool containsObject(std::string const& _path) const { return objectPaths.count(_path) > 0; } + /// Checks if a path is available and leads to a data entry. + bool containsData(std::string const& _path) const { return dataPaths.count(_path) > 0; } + + std::set topLevelSubObjectNames() const; + }; + /// @returns the set of names of data objects accessible from within the code of /// this object, including the name of object itself /// Handles all names containing dots as reserved identifiers, not accessible as data. - std::set qualifiedDataNames() const; + Structure summarizeStructure() const; /// @returns vector of subIDs if possible to reach subobject with @a _qualifiedName, throws otherwise /// For "B.C" should return vector of two values if success (subId of B and subId of C in B). diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 8b559e23f..877e447c7 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -166,7 +166,7 @@ bool YulStack::analyzeParsed(Object& _object) m_errorReporter, languageToDialect(m_language, m_evmVersion, m_eofVersion), {}, - _object.qualifiedDataNames() + _object.summarizeStructure() ); bool success = false; diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 2c2ef4272..6ad3899e9 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -257,7 +257,11 @@ std::tuple StackCompressor::run( Block astRoot = std::get(ASTCopier{}(_object.code()->root())); if (usesOptimizedCodeGenerator) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, astRoot, _object.qualifiedDataNames()); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( + _dialect, + astRoot, + _object.summarizeStructure() + ); std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, astRoot); eliminateVariablesOptimizedCodegen( _dialect, diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index d3cb6418f..6ef4b267b 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -132,7 +132,11 @@ Block StackLimitEvader::run( auto astRoot = std::get(ASTCopier{}(_object.code()->root())); if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall()) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, astRoot, _object.qualifiedDataNames()); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( + *evmDialect, + astRoot, + _object.summarizeStructure() + ); std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, astRoot); run(_context, astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg)); } diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 6562e1743..41b856edd 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -84,7 +84,7 @@ std::pair, std::shared_ptr> yul::t if (!parserResult->hasCode() || errorReporter.hasErrors()) return {}; std::shared_ptr analysisInfo = std::make_shared(); - AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect, {}, parserResult->qualifiedDataNames()); + AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect, {}, parserResult->summarizeStructure()); // TODO this should be done recursively. if (!analyzer.analyze(parserResult->code()->root()) || errorReporter.hasErrors()) return {}; diff --git a/test/libyul/yulSyntaxTests/eof/object_name_in_eof.yul b/test/libyul/yulSyntaxTests/eof/object_name_in_eof.yul new file mode 100644 index 000000000..bcbbca624 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/object_name_in_eof.yul @@ -0,0 +1,9 @@ +object "a.b" { + code {} +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// SyntaxError 9822: (24-26): The object name "a.b" is invalid in EOF context. Object names must not contain 'dot' character. From 974c11229c14edea3d94f1d7ef7af27cc8d6a2a1 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 30 Oct 2024 11:13:17 +0100 Subject: [PATCH 0453/1340] eof: Support EOF contract creation. --- libevmasm/Assembly.cpp | 30 ++++- libevmasm/Assembly.h | 11 ++ libevmasm/AssemblyItem.cpp | 20 +++- libevmasm/AssemblyItem.h | 33 +++++- libevmasm/Instruction.cpp | 4 + libevmasm/Instruction.h | 2 + libevmasm/SemanticInformation.cpp | 50 +++++++- liblangutil/EVMVersion.cpp | 2 + .../codegen/ir/IRGenerationContext.cpp | 47 ++++++++ libsolidity/codegen/ir/IRGenerationContext.h | 10 ++ libsolidity/codegen/ir/IRGenerator.cpp | 109 +++++++++++++----- libsolidity/codegen/ir/IRGenerator.h | 1 + .../codegen/ir/IRGeneratorForStatements.cpp | 37 ++++-- .../experimental/codegen/IRGenerator.cpp | 1 + libyul/AsmAnalysis.cpp | 29 +++++ libyul/backends/evm/AbstractAssembly.h | 5 + libyul/backends/evm/EVMDialect.cpp | 56 ++++++++- libyul/backends/evm/EthAssemblyAdapter.cpp | 10 ++ libyul/backends/evm/EthAssemblyAdapter.h | 2 + libyul/backends/evm/NoOutputAssembly.cpp | 10 ++ libyul/backends/evm/NoOutputAssembly.h | 2 + .../debug_info_in_yul_snippet_escaping/output | 1 + .../standard_viair_requested/output.json | 1 + .../strict_asm_eof_container_prague/input.yul | 27 ++--- .../strict_asm_eof_container_prague/output | 87 +++++++------- .../eof/creation_with_immutables.yul | 100 ++++++++++++++++ test/libyul/yulSyntaxTests/eof/eofcreate.yul | 13 +++ .../eof/eofcreate_invalid_object.yul | 11 ++ .../eofcreate_invalid_object_name_data.yul | 13 +++ .../eofcreate_invalid_object_name_path.yul | 18 +++ .../yulSyntaxTests/eof/returncontract.yul | 12 ++ .../eof/returncontract_invalid_object.yul | 10 ++ .../EVMInstructionInterpreter.cpp | 4 +- 33 files changed, 661 insertions(+), 107 deletions(-) create mode 100644 test/libyul/objectCompiler/eof/creation_with_immutables.yul create mode 100644 test/libyul/yulSyntaxTests/eof/eofcreate.yul create mode 100644 test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object.yul create mode 100644 test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul create mode 100644 test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_path.yul create mode 100644 test/libyul/yulSyntaxTests/eof/returncontract.yul create mode 100644 test/libyul/yulSyntaxTests/eof/returncontract_invalid_object.yul diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 8f645f6fd..153ab547e 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1335,10 +1335,14 @@ std::map Assembly::findReferencedContainers() const std::set referencedSubcontainersIds; solAssert(m_subs.size() <= 0x100); // According to EOF spec - // TODO: Implement properly when opcodes referring sub containers added. - for (uint16_t i = 0; i < m_subs.size(); ++i) - referencedSubcontainersIds.insert(static_cast(i)); - // END TODO + for (auto&& codeSection: m_codeSections) + for (AssemblyItem const& item: codeSection.items) + if (item.type() == EOFCreate || item.type() == ReturnContract) + { + solAssert(item.data() <= m_subs.size(), "Invalid subcontainer index."); + auto const containerId = static_cast(item.data()); + referencedSubcontainersIds.insert(containerId); + } std::map replacements; uint8_t nUnreferenced = 0; @@ -1405,7 +1409,11 @@ LinkerObject const& Assembly::assembleEOF() const switch (item.type()) { case Operation: - solAssert(item.instruction() != Instruction::DATALOADN); + solAssert( + item.instruction() != Instruction::DATALOADN && + item.instruction() != Instruction::RETURNCONTRACT && + item.instruction() != Instruction::EOFCREATE + ); solAssert(!(item.instruction() >= Instruction::PUSH0 && item.instruction() <= Instruction::PUSH32)); ret.bytecode += assembleOperation(item); break; @@ -1419,6 +1427,18 @@ LinkerObject const& Assembly::assembleEOF() const ret.linkReferences.insert(linkRef); break; } + case EOFCreate: + { + ret.bytecode.push_back(static_cast(Instruction::EOFCREATE)); + ret.bytecode.push_back(static_cast(item.data())); + break; + } + case ReturnContract: + { + ret.bytecode.push_back(static_cast(Instruction::RETURNCONTRACT)); + ret.bytecode.push_back(static_cast(item.data())); + break; + } case VerbatimBytecode: ret.bytecode += assembleVerbatimBytecode(item); break; diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 9b15936d6..daeea6e8c 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -99,6 +99,17 @@ class Assembly append(AssemblyItem(std::move(_data), _arguments, _returnVariables)); } + AssemblyItem appendEOFCreate(ContainerID _containerId) + { + solAssert(_containerId < m_subs.size(), "EOF Create of undefined container."); + return append(AssemblyItem::eofCreate(_containerId)); + } + AssemblyItem appendReturnContract(ContainerID _containerId) + { + solAssert(_containerId < m_subs.size(), "Return undefined container ID."); + return append(AssemblyItem::returnContract(_containerId)); + } + AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; } AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; } AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; } diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 3ce6238bc..d26e01f8a 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -74,6 +74,8 @@ std::pair AssemblyItem::nameAndData(langutil::EVMVersi switch (type()) { case Operation: + case EOFCreate: + case ReturnContract: return {instructionInfo(instruction(), _evmVersion).name, m_data != nullptr ? toStringInHex(*m_data) : ""}; case Push: return {"PUSH", toStringInHex(data())}; @@ -167,6 +169,10 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, langutil::EVMVersion _ return std::get<2>(*m_verbatimBytecode).size(); case AuxDataLoadN: return 1 + 2; + case EOFCreate: + return 2; + case ReturnContract: + return 2; case UndefinedItem: solAssert(false); } @@ -176,7 +182,7 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, langutil::EVMVersion _ size_t AssemblyItem::arguments() const { - if (type() == Operation) + if (hasInstruction()) // The latest EVMVersion is used here, since the InstructionInfo is assumed to be // the same across all EVM versions except for the instruction name. return static_cast(instructionInfo(instruction(), EVMVersion()).args); @@ -193,6 +199,8 @@ size_t AssemblyItem::returnValues() const switch (m_type) { case Operation: + case EOFCreate: + case ReturnContract: // The latest EVMVersion is used here, since the InstructionInfo is assumed to be // the same across all EVM versions except for the instruction name. return static_cast(instructionInfo(instruction(), EVMVersion()).ret); @@ -226,6 +234,8 @@ bool AssemblyItem::canBeFunctional() const switch (m_type) { case Operation: + case EOFCreate: + case ReturnContract: return !isDupInstruction(instruction()) && !isSwapInstruction(instruction()); case Push: case PushTag: @@ -344,6 +354,12 @@ std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const assertThrow(data() <= std::numeric_limits::max(), AssemblyException, "Invalid auxdataloadn argument."); text = "auxdataloadn{" + std::to_string(static_cast(data())) + "}"; break; + case EOFCreate: + text = "eofcreate{" + std::to_string(static_cast(data())) + "}"; + break; + case ReturnContract: + text = "returcontract{" + std::to_string(static_cast(data())) + "}"; + break; } if (m_jumpType == JumpType::IntoFunction || m_jumpType == JumpType::OutOfFunction) { @@ -362,6 +378,8 @@ std::ostream& solidity::evmasm::operator<<(std::ostream& _out, AssemblyItem cons switch (_item.type()) { case Operation: + case EOFCreate: + case ReturnContract: _out << " " << instructionInfo(_item.instruction(), EVMVersion()).name; if (_item.instruction() == Instruction::JUMP || _item.instruction() == Instruction::JUMPI) _out << "\t" << _item.getJumpTypeAsString(); diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 226a126c3..e51d07b16 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -55,6 +55,8 @@ enum AssemblyItemType /// Loads 32 bytes from static auxiliary data of EOF data section. The offset does *not* have to be always from the beginning /// of the data EOF section. More details here: https://github.com/ipsilon/eof/blob/main/spec/eof.md#data-section-lifecycle AuxDataLoadN, + EOFCreate, ///< Creates new contract using subcontainer as initcode + ReturnContract, ///< Returns new container (with auxiliary data filled in) to be deployed VerbatimBytecode ///< Contains data that is inserted into the bytecode code section without modification. }; @@ -63,6 +65,7 @@ enum class Precision { Precise , Approximate }; class Assembly; class AssemblyItem; using AssemblyItems = std::vector; +using ContainerID = uint8_t; class AssemblyItem { @@ -85,6 +88,14 @@ class AssemblyItem else m_data = std::make_shared(std::move(_data)); } + + explicit AssemblyItem(AssemblyItemType _type, Instruction _instruction, u256 _data = 0, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()): + m_type(_type), + m_instruction(_instruction), + m_data(std::make_shared(std::move(_data))), + m_debugData(std::move(_debugData)) + {} + explicit AssemblyItem(bytes _verbatimData, size_t _arguments, size_t _returnVariables): m_type(VerbatimBytecode), m_instruction{}, @@ -92,6 +103,15 @@ class AssemblyItem m_debugData{langutil::DebugData::create()} {} + static AssemblyItem eofCreate(ContainerID _containerID, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + return AssemblyItem(EOFCreate, Instruction::EOFCREATE, _containerID, std::move(_debugData)); + } + static AssemblyItem returnContract(ContainerID _containerID, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + return AssemblyItem(ReturnContract, Instruction::RETURNCONTRACT, _containerID, std::move(_debugData)); + } + AssemblyItem(AssemblyItem const&) = default; AssemblyItem(AssemblyItem&&) = default; AssemblyItem& operator=(AssemblyItem const&) = default; @@ -122,8 +142,17 @@ class AssemblyItem bytes const& verbatimData() const { assertThrow(m_type == VerbatimBytecode, util::Exception, ""); return std::get<2>(*m_verbatimBytecode); } - /// @returns the instruction of this item (only valid if type() == Operation) - Instruction instruction() const { assertThrow(m_type == Operation, util::Exception, ""); return m_instruction; } + /// @returns true if the item has m_instruction properly set. + bool hasInstruction() const + { + return m_type == Operation || m_type == EOFCreate || m_type == ReturnContract; + } + /// @returns the instruction of this item (only valid if type() == Operation || EOFCreate || ReturnContract) + Instruction instruction() const + { + solAssert(hasInstruction()); + return m_instruction; + } /// @returns true if the type and data of the items are equal. bool operator==(AssemblyItem const& _other) const diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index b9bb21227..5122fb01f 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -169,6 +169,8 @@ std::map const solidity::evmasm::c_instructions = { "LOG3", Instruction::LOG3 }, { "LOG4", Instruction::LOG4 }, { "DATALOADN", Instruction::DATALOADN }, + { "EOFCREATE", Instruction::EOFCREATE }, + { "RETURNCONTRACT", Instruction::RETURNCONTRACT }, { "CREATE", Instruction::CREATE }, { "CALL", Instruction::CALL }, { "CALLCODE", Instruction::CALLCODE }, @@ -324,6 +326,8 @@ static std::map const c_instructionInfo = {Instruction::LOG2, {"LOG2", 0, 4, 0, true, Tier::Special}}, {Instruction::LOG3, {"LOG3", 0, 5, 0, true, Tier::Special}}, {Instruction::LOG4, {"LOG4", 0, 6, 0, true, Tier::Special}}, + {Instruction::EOFCREATE, {"EOFCREATE", 1, 4, 1, true, Tier::Special}}, + {Instruction::RETURNCONTRACT, {"RETURNCONTRACT", 1, 2, 0, true, Tier::Special}}, {Instruction::CREATE, {"CREATE", 0, 3, 1, true, Tier::Special}}, {Instruction::CALL, {"CALL", 0, 7, 1, true, Tier::Special}}, {Instruction::CALLCODE, {"CALLCODE", 0, 7, 1, true, Tier::Special}}, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 2ed773cc9..d9e96c49a 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -183,6 +183,8 @@ enum class Instruction: uint8_t LOG4, ///< Makes a log entry; 4 topics. DATALOADN = 0xd1, ///< load data from EOF data section + EOFCREATE = 0xec, ///< create a new account with associated container code. + RETURNCONTRACT = 0xee, ///< return container to be deployed with axiliary data filled in. CREATE = 0xf0, ///< create a new account with associated code CALL, ///< message-call into an account CALLCODE, ///< message-call with another account's code only diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index 87d41f6c1..e909a7074 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -184,6 +184,34 @@ std::vector SemanticInformation::readWriteOperat Operation{Location::TransientStorage, Effect::Read, {}, {}, {}}, Operation{Location::TransientStorage, Effect::Write, {}, {}, {}} }; + case Instruction::EOFCREATE: + return std::vector{ + Operation{ + Location::Memory, + Effect::Read, + 2, + 3, + {} + }, + Operation{Location::Storage, Effect::Read, {}, {}, {}}, + Operation{Location::Storage, Effect::Write, {}, {}, {}}, + Operation{Location::TransientStorage, Effect::Read, {}, {}, {}}, + Operation{Location::TransientStorage, Effect::Write, {}, {}, {}} + }; + case Instruction::RETURNCONTRACT: + return std::vector{ + Operation{ + Location::Memory, + Effect::Read, + 0, + 1, + {} + }, + Operation{Location::Storage, Effect::Read, {}, {}, {}}, + Operation{Location::Storage, Effect::Write, {}, {}, {}}, + Operation{Location::TransientStorage, Effect::Read, {}, {}, {}}, + Operation{Location::TransientStorage, Effect::Write, {}, {}, {}} + }; case Instruction::MSIZE: // This is just to satisfy the assert below. return std::vector{}; @@ -280,8 +308,9 @@ bool SemanticInformation::isJumpInstruction(AssemblyItem const& _item) bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) { - if (_item.type() != evmasm::Operation) + if (!_item.hasInstruction()) return false; + switch (_item.instruction()) { // note that CALL, CALLCODE and CREATE do not really alter the control flow, because we @@ -293,6 +322,7 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) case Instruction::STOP: case Instruction::INVALID: case Instruction::REVERT: + case Instruction::RETURNCONTRACT: return true; default: return false; @@ -301,7 +331,7 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) bool SemanticInformation::terminatesControlFlow(AssemblyItem const& _item) { - if (_item.type() != evmasm::Operation) + if (!_item.hasInstruction()) return false; return terminatesControlFlow(_item.instruction()); } @@ -315,6 +345,7 @@ bool SemanticInformation::terminatesControlFlow(Instruction _instruction) case Instruction::STOP: case Instruction::INVALID: case Instruction::REVERT: + case Instruction::RETURNCONTRACT: return true; default: return false; @@ -337,7 +368,7 @@ bool SemanticInformation::isDeterministic(AssemblyItem const& _item) { assertThrow(_item.type() != VerbatimBytecode, AssemblyException, ""); - if (_item.type() != evmasm::Operation) + if (!_item.hasInstruction()) return true; switch (_item.instruction()) @@ -357,6 +388,7 @@ bool SemanticInformation::isDeterministic(AssemblyItem const& _item) case Instruction::EXTCODEHASH: case Instruction::RETURNDATACOPY: // depends on previous calls case Instruction::RETURNDATASIZE: + case Instruction::EOFCREATE: return false; default: return true; @@ -436,6 +468,8 @@ SemanticInformation::Effect SemanticInformation::memory(Instruction _instruction case Instruction::LOG2: case Instruction::LOG3: case Instruction::LOG4: + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: return SemanticInformation::Read; default: @@ -473,6 +507,8 @@ SemanticInformation::Effect SemanticInformation::storage(Instruction _instructio case Instruction::CREATE: case Instruction::CREATE2: case Instruction::SSTORE: + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: return SemanticInformation::Write; case Instruction::SLOAD: @@ -494,6 +530,8 @@ SemanticInformation::Effect SemanticInformation::transientStorage(Instruction _i case Instruction::CREATE: case Instruction::CREATE2: case Instruction::TSTORE: + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: return SemanticInformation::Write; case Instruction::TLOAD: @@ -514,6 +552,8 @@ SemanticInformation::Effect SemanticInformation::otherState(Instruction _instruc case Instruction::DELEGATECALL: case Instruction::CREATE: case Instruction::CREATE2: + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: case Instruction::SELFDESTRUCT: case Instruction::STATICCALL: // because it can affect returndatasize // Strictly speaking, log0, .., log4 writes to the state, but the EVM cannot read it, so they @@ -588,6 +628,10 @@ bool SemanticInformation::invalidInViewFunctions(Instruction _instruction) case Instruction::CALL: case Instruction::CALLCODE: case Instruction::DELEGATECALL: + // According to EOF spec https://eips.ethereum.org/EIPS/eip-7620#eofcreate + case Instruction::EOFCREATE: + // According to EOF spec https://eips.ethereum.org/EIPS/eip-7620#returncontract + case Instruction::RETURNCONTRACT: case Instruction::CREATE2: case Instruction::SELFDESTRUCT: return true; diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index bdd663c41..9041ae793 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -77,6 +77,8 @@ bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersi case Instruction::GAS: return !_eofVersion.has_value(); // Instructions below available only in EOF + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: case Instruction::DATALOADN: return _eofVersion.has_value(); default: diff --git a/libsolidity/codegen/ir/IRGenerationContext.cpp b/libsolidity/codegen/ir/IRGenerationContext.cpp index e087dc69a..fd47fec10 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.cpp +++ b/libsolidity/codegen/ir/IRGenerationContext.cpp @@ -107,10 +107,57 @@ size_t IRGenerationContext::immutableMemoryOffset(VariableDeclaration const& _va return m_immutableVariables.at(&_variable); } +size_t IRGenerationContext::immutableMemoryOffsetRelative(VariableDeclaration const& _variable) const +{ + auto const absoluteOffset = immutableMemoryOffset(_variable); + solAssert(absoluteOffset >= CompilerUtils::generalPurposeMemoryStart); + return absoluteOffset - CompilerUtils::generalPurposeMemoryStart; +} + +size_t IRGenerationContext::reservedMemorySize() const +{ + solAssert(m_reservedMemory.has_value()); + return *m_reservedMemory; +} + +void IRGenerationContext::registerLibraryAddressImmutable() +{ + solAssert(m_reservedMemory.has_value(), "Reserved memory has already been reset."); + solAssert(!m_libraryAddressImmutableOffset.has_value()); + m_libraryAddressImmutableOffset = CompilerUtils::generalPurposeMemoryStart + *m_reservedMemory; + *m_reservedMemory += 32; +} + +size_t IRGenerationContext::libraryAddressImmutableOffset() const +{ + solAssert(m_libraryAddressImmutableOffset.has_value()); + return *m_libraryAddressImmutableOffset; +} + +size_t IRGenerationContext::libraryAddressImmutableOffsetRelative() const +{ + solAssert(m_libraryAddressImmutableOffset.has_value()); + solAssert(m_libraryAddressImmutableOffset >= CompilerUtils::generalPurposeMemoryStart); + return *m_libraryAddressImmutableOffset - CompilerUtils::generalPurposeMemoryStart; +} + size_t IRGenerationContext::reservedMemory() { solAssert(m_reservedMemory.has_value(), "Reserved memory was used before."); size_t reservedMemory = *m_reservedMemory; + + // We assume reserved memory contains only immutable variables. + // This memory is used i.e. by RETURNCONTRACT to create new EOF container with aux data. + size_t immutableVariablesSize = 0; + for (auto const* var: keys(m_immutableVariables)) + { + solUnimplementedAssert(var->type()->isValueType()); + solUnimplementedAssert(var->type()->sizeOnStack() == 1); + immutableVariablesSize += var->type()->sizeOnStack() * 32; + } + + solAssert(immutableVariablesSize == reservedMemory); + m_reservedMemory = std::nullopt; return reservedMemory; } diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index 2bf837697..01220e87b 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -58,6 +58,7 @@ class IRGenerationContext IRGenerationContext( langutil::EVMVersion _evmVersion, + std::optional _eofVersion, ExecutionContext _executionContext, RevertStrings _revertStrings, std::map _sourceIndices, @@ -65,6 +66,7 @@ class IRGenerationContext langutil::CharStreamProvider const* _soliditySourceProvider ): m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion), m_executionContext(_executionContext), m_revertStrings(_revertStrings), m_sourceIndices(std::move(_sourceIndices)), @@ -99,13 +101,18 @@ class IRGenerationContext /// Registers an immutable variable of the contract. /// Should only be called at construction time. void registerImmutableVariable(VariableDeclaration const& _varDecl); + void registerLibraryAddressImmutable(); + size_t libraryAddressImmutableOffset() const; + size_t libraryAddressImmutableOffsetRelative() const; /// @returns the reserved memory for storing the value of the /// immutable @a _variable during contract creation. size_t immutableMemoryOffset(VariableDeclaration const& _variable) const; + size_t immutableMemoryOffsetRelative(VariableDeclaration const& _variable) const; /// @returns the reserved memory and resets it to mark it as used. /// Intended to be used only once for initializing the free memory pointer /// to after the area used for immutables. size_t reservedMemory(); + size_t reservedMemorySize() const; void addStateVariable(VariableDeclaration const& _varDecl, u256 _storageOffset, unsigned _byteOffset); bool isStateVariable(VariableDeclaration const& _varDecl) const { return m_stateVariables.count(&_varDecl); } @@ -134,6 +141,7 @@ class IRGenerationContext YulUtilFunctions utils(); langutil::EVMVersion evmVersion() const { return m_evmVersion; } + std::optional eofVersion() const { return m_eofVersion; } ExecutionContext executionContext() const { return m_executionContext; } void setArithmetic(Arithmetic _value) { m_arithmetic = _value; } @@ -160,6 +168,7 @@ class IRGenerationContext private: langutil::EVMVersion m_evmVersion; + std::optional m_eofVersion; ExecutionContext m_executionContext; RevertStrings m_revertStrings; std::map m_sourceIndices; @@ -169,6 +178,7 @@ class IRGenerationContext /// Memory offsets reserved for the values of immutable variables during contract creation. /// This map is empty in the runtime context. std::map m_immutableVariables; + std::optional m_libraryAddressImmutableOffset; /// Total amount of reserved memory. Reserved memory is used to store /// immutable variables during contract creation. std::optional m_reservedMemory = {0}; diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 44fc5a935..48b646d35 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -141,7 +141,11 @@ std::string IRGenerator::generate( - let called_via_delegatecall := iszero(eq(loadimmutable(""), address())) + + let called_via_delegatecall := iszero(eq(auxdataloadn(), address())) + + let called_via_delegatecall := iszero(eq(loadimmutable(""), address())) + @@ -154,6 +158,9 @@ std::string IRGenerator::generate( )"); resetContext(_contract, ExecutionContext::Creation); + auto const eof = m_context.eofVersion().has_value(); + if (eof && _contract.isLibrary()) + m_context.registerLibraryAddressImmutable(); for (VariableDeclaration const* var: ContractType(_contract).immutableVariables()) m_context.registerImmutableVariable(*var); @@ -200,7 +207,15 @@ std::string IRGenerator::generate( // Do not register immutables to avoid assignment. t("DeployedObject", IRNames::deployedObject(_contract)); t("sourceLocationCommentDeployed", dispenseLocationComment(_contract)); - t("library_address", IRNames::libraryAddressImmutable()); + t("eof", eof); + if (_contract.isLibrary()) + { + if (!eof) + t("library_address", IRNames::libraryAddressImmutable()); + else + t("library_address_immutable_offset", std::to_string(m_context.libraryAddressImmutableOffsetRelative())); + } + t("dispatch", dispatchRoutine(_contract)); std::set deployedFunctionList = generateQueuedFunctions(); generateInternalDispatchFunctions(_contract); @@ -532,27 +547,39 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) { solAssert(paramTypes.empty(), ""); solUnimplementedAssert(type->sizeOnStack() == 1); - return Whiskers(R"( + + auto t = Whiskers(R"( function () -> rval { - rval := loadimmutable("") + + rval := auxdataloadn() + + rval := loadimmutable("") + } - )") - ( + )"); + t( "astIDComment", m_context.debugInfoSelection().astID ? "/// @ast-id " + std::to_string(_varDecl.id()) + "\n" : "" - ) - ("sourceLocationComment", dispenseLocationComment(_varDecl)) - ( + ); + t("sourceLocationComment", dispenseLocationComment(_varDecl)); + t( "contractSourceLocationComment", dispenseLocationComment(m_context.mostDerivedContract()) - ) - ("functionName", functionName) - ("id", std::to_string(_varDecl.id())) - .render(); + ); + t("functionName", functionName); + + auto const eof = m_context.eofVersion().has_value(); + t("eof", eof); + if (!eof) + t("id", std::to_string(_varDecl.id())); + else + t("immutableOffset", std::to_string(m_context.immutableMemoryOffsetRelative(_varDecl))); + + return t.render(); } else if (_varDecl.isConstant()) { @@ -940,13 +967,22 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract) std::string IRGenerator::deployCode(ContractDefinition const& _contract) { Whiskers t(R"X( - let := () - codecopy(, dataoffset(""), datasize("")) - <#immutables> - setimmutable(, "", ) - - return(, datasize("")) + + + mstore(, address()) + + returncontract("", , ) + + let := () + codecopy(, dataoffset(""), datasize("")) + <#immutables> + setimmutable(, "", ) + + return(, datasize("")) + )X"); + auto const eof = m_context.eofVersion().has_value(); + t("eof", eof); t("allocateUnbounded", m_utils.allocateUnboundedFunction()); t("codeOffset", m_context.newYulVariable()); t("object", IRNames::deployedObject(_contract)); @@ -955,23 +991,37 @@ std::string IRGenerator::deployCode(ContractDefinition const& _contract) if (_contract.isLibrary()) { solAssert(ContractType(_contract).immutableVariables().empty(), ""); - immutables.emplace_back(std::map{ - {"immutableName"s, IRNames::libraryAddressImmutable()}, - {"value"s, "address()"} - }); - + if (!eof) + immutables.emplace_back(std::map{ + {"immutableName"s, IRNames::libraryAddressImmutable()}, + {"value"s, "address()"} + }); + else + t("libraryAddressImmutableOffset", std::to_string(m_context.libraryAddressImmutableOffset())); } else + { for (VariableDeclaration const* immutable: ContractType(_contract).immutableVariables()) { solUnimplementedAssert(immutable->type()->isValueType()); solUnimplementedAssert(immutable->type()->sizeOnStack() == 1); - immutables.emplace_back(std::map{ - {"immutableName"s, std::to_string(immutable->id())}, - {"value"s, "mload(" + std::to_string(m_context.immutableMemoryOffset(*immutable)) + ")"} - }); + if (!eof) + immutables.emplace_back(std::map{ + {"immutableName"s, std::to_string(immutable->id())}, + {"value"s, "mload(" + std::to_string(m_context.immutableMemoryOffset(*immutable)) + ")"} + }); } - t("immutables", std::move(immutables)); + } + + if (eof) + { + t("auxDataStart", std::to_string(CompilerUtils::generalPurposeMemoryStart)); + solAssert(m_context.reservedMemorySize() <= 0xFFFF, "Reserved memory size exceeded maximum allowed EOF data section size."); + t("auxDataSize", std::to_string(m_context.reservedMemorySize())); + } + else + t("immutables", std::move(immutables)); + return t.render(); } @@ -1095,6 +1145,7 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon ); IRGenerationContext newContext( m_evmVersion, + m_eofVersion, _context, m_context.revertStrings(), m_context.sourceIndices(), diff --git a/libsolidity/codegen/ir/IRGenerator.h b/libsolidity/codegen/ir/IRGenerator.h index 9f01b74fc..ed29a8bb3 100644 --- a/libsolidity/codegen/ir/IRGenerator.h +++ b/libsolidity/codegen/ir/IRGenerator.h @@ -59,6 +59,7 @@ class IRGenerator m_eofVersion(_eofVersion), m_context( _evmVersion, + _eofVersion, ExecutionContext::Creation, _revertStrings, std::move(_sourceIndices), diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 69d24cf42..1304eca9a 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1563,22 +1563,30 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) &dynamic_cast(*functionType->returnParameterTypes().front()).contractDefinition(); m_context.addSubObject(contract); - Whiskers t(R"(let := () - let := add(, datasize("")) - if or(gt(, 0xffffffffffffffff), lt(, )) { () } - datacopy(, dataoffset(""), datasize("")) - := () - - let
:= create2(, , sub(, ), ) - - let
:= create(, , sub(, )) - + Whiskers t(R"( + + let := () + let := () + let
:= eofcreate("", , , , sub(, )) + + let := () + let := add(, datasize("")) + if or(gt(, 0xffffffffffffffff), lt(, )) { () } + datacopy(, dataoffset(""), datasize("")) + := () + + let
:= create2(, , sub(, ), ) + + let
:= create(, , sub(, )) + + let := iszero(iszero(
)) if iszero(
) { () } )"); + t("eof", m_context.eofVersion().has_value()); t("memPos", m_context.newYulVariable()); t("memEnd", m_context.newYulVariable()); t("allocateUnbounded", m_utils.allocateUnboundedFunction()); @@ -1592,6 +1600,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) t("saltSet", functionType->saltSet()); if (functionType->saltSet()) t("salt", IRVariable(_functionCall.expression()).part("salt").name()); + else if (m_context.eofVersion().has_value()) // Set salt to 0 if not defined. + t("salt", "0"); // TODO: We should reject non-salted creation during analysis and not set here solAssert(IRVariable(_functionCall).stackSlots().size() == 1); t("address", IRVariable(_functionCall).commaSeparatedList()); t("isTryCall", _functionCall.annotation().tryCall); @@ -3245,7 +3255,12 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue) ")\n"; } else - define(result) << "loadimmutable(\"" << std::to_string(_immutable.variable->id()) << "\")\n"; + { + if (!m_context.eofVersion().has_value()) + define(result) << "loadimmutable(\"" << std::to_string(_immutable.variable->id()) << "\")\n"; + else + define(result) << "auxdataloadn(" << std::to_string(m_context.immutableMemoryOffsetRelative(*_immutable.variable)) << ")\n"; + } }, [&](IRLValue::Tuple const&) { solAssert(false, "Attempted to read from tuple lvalue."); diff --git a/libsolidity/experimental/codegen/IRGenerator.cpp b/libsolidity/experimental/codegen/IRGenerator.cpp index 60a93bbf0..457b28e37 100644 --- a/libsolidity/experimental/codegen/IRGenerator.cpp +++ b/libsolidity/experimental/codegen/IRGenerator.cpp @@ -67,6 +67,7 @@ std::string IRGenerator::run( std::map const& /*_otherYulSources*/ ) { + solUnimplementedAssert(!m_eofVersion.has_value(), "Experimental IRGenerator not implemented for EOF"); Whiskers t(R"( object "" { diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index a234fdb81..8ed0b4142 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -428,6 +428,35 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) "The \"verbatim_*\" builtins cannot be used with empty bytecode." ); } + else if (functionName == "eofcreate" || functionName == "returncontract") + { + auto const& argumentAsLiteral = std::get(arg); + auto const formattedLiteral = formatLiteral(argumentAsLiteral); + + if (util::contains(formattedLiteral, '.')) + m_errorReporter.typeError( + 2186_error, + nativeLocationOf(arg), + "Name required but path given as \"" + functionName + "\" argument." + ); + + if (!m_objectStructure.topLevelSubObjectNames().count(formattedLiteral)) + { + if (m_objectStructure.containsData(formattedLiteral)) + m_errorReporter.typeError( + 7575_error, + nativeLocationOf(arg), + "Data name \"" + formattedLiteral + "\" cannot be used as an argument of eofcreate/returncontract. " + + "An object name is only acceptable." + ); + else + m_errorReporter.typeError( + 8970_error, + nativeLocationOf(arg), + "Unknown object \"" + formattedLiteral + "\"." + ); + } + } expectUnlimitedStringLiteral(std::get(arg)); continue; } diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index ed06bebac..7c44dfa78 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -56,6 +56,7 @@ class AbstractAssembly public: using LabelID = size_t; using SubID = size_t; + using ContainerID = uint8_t; enum class JumpType { Ordinary, IntoFunction, OutOfFunction }; virtual ~AbstractAssembly() = default; @@ -118,6 +119,10 @@ class AbstractAssembly /// The function is meant to allow indexing into static_aux_data in a way that's independent of the size of pre_deploy_data. virtual void appendAuxDataLoadN(uint16_t _offset) = 0; + /// Appends EOF contract creation instruction which takes creation code from subcontainer with _containerID. + virtual void appendEOFCreate(ContainerID _containerID) = 0; + /// Appends EOF contract return instruction which returns a subcontainer ID (_containerID) with auxiliary data filled in. + virtual void appendReturnContract(ContainerID _containerID) = 0; /// Appends data to the very end of the bytecode. Repeated calls concatenate. /// EOF auxiliary data in data section and the auxiliary data are different things. virtual void appendToAuxiliaryData(bytes const& _data) = 0; diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 27a1f1426..9de3e40fc 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -207,6 +207,8 @@ std::vector> createBuiltins(langutil::EVMVe opcode != evmasm::Instruction::JUMPI && opcode != evmasm::Instruction::JUMPDEST && opcode != evmasm::Instruction::DATALOADN && + opcode != evmasm::Instruction::EOFCREATE && + opcode != evmasm::Instruction::RETURNCONTRACT && _evmVersion.hasOpcode(opcode, _eofVersion) && !prevRandaoException(name) ) @@ -370,7 +372,7 @@ std::vector> createBuiltins(langutil::EVMVe } )); } - else + else // EOF context { builtins.emplace_back(createFunction( "auxdataloadn", @@ -384,13 +386,61 @@ std::vector> createBuiltins(langutil::EVMVe AbstractAssembly& _assembly, BuiltinContext& ) { - yulAssert(_call.arguments.size() == 1, ""); + yulAssert(_call.arguments.size() == 1); Literal const* literal = std::get_if(&_call.arguments.front()); yulAssert(literal, ""); - yulAssert(literal->value.value() <= std::numeric_limits::max(), ""); + yulAssert(literal->value.value() <= std::numeric_limits::max()); _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); } )); + + builtins.emplace_back(createFunction( + "eofcreate", + 5, + 1, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE), + {LiteralKind::String, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& context + ) { + yulAssert(_call.arguments.size() == 5); + Literal const* literal = std::get_if(&_call.arguments.front()); + auto const formattedLiteral = formatLiteral(*literal); + yulAssert(!util::contains(formattedLiteral, '.')); + auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); + yulAssert(containerID != nullptr); + yulAssert(*containerID <= std::numeric_limits::max()); + _assembly.appendEOFCreate(static_cast(*containerID)); + } + )); + + if (_objectAccess) + builtins.emplace_back(createFunction( + "returncontract", + 3, + 0, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::RETURNCONTRACT), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::RETURNCONTRACT), + {LiteralKind::String, std::nullopt, std::nullopt}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& context + ) { + yulAssert(_call.arguments.size() == 3); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal); + auto const formattedLiteral = formatLiteral(*literal); + yulAssert(!util::contains(formattedLiteral, '.')); + auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); + yulAssert(containerID != nullptr); + yulAssert(*containerID <= std::numeric_limits::max()); + _assembly.appendReturnContract(static_cast(*containerID)); + } + )); } yulAssert( ranges::all_of(builtins, [](std::optional const& _builtinFunction){ diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index 36a437c8c..604177c4f 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -128,6 +128,16 @@ std::pair, AbstractAssembly::SubID> EthAssembl return {std::make_shared(*assembly), static_cast(sub.data())}; } +void EthAssemblyAdapter::appendEOFCreate(ContainerID _containerID) +{ + m_assembly.appendEOFCreate(_containerID); +} + +void EthAssemblyAdapter::appendReturnContract(ContainerID _containerID) +{ + m_assembly.appendReturnContract(_containerID); +} + void EthAssemblyAdapter::appendDataOffset(std::vector const& _subPath) { if (auto it = m_dataHashBySubId.find(_subPath[0]); it != m_dataHashBySubId.end()) diff --git a/libyul/backends/evm/EthAssemblyAdapter.h b/libyul/backends/evm/EthAssemblyAdapter.h index 7dc89e38e..d0bd3e14a 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.h +++ b/libyul/backends/evm/EthAssemblyAdapter.h @@ -56,6 +56,8 @@ class EthAssemblyAdapter: public AbstractAssembly void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override; void appendAssemblySize() override; std::pair, SubID> createSubAssembly(bool _creation, std::string _name = {}) override; + void appendEOFCreate(ContainerID _containerID) override; + void appendReturnContract(ContainerID _containerID) override; void appendDataOffset(std::vector const& _subPath) override; void appendDataSize(std::vector const& _subPath) override; SubID appendData(bytes const& _data) override; diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 5e82cc6fd..0497b11b6 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -151,6 +151,16 @@ void NoOutputAssembly::appendAuxDataLoadN(uint16_t) yulAssert(false, "auxdataloadn not implemented."); } +void NoOutputAssembly::appendEOFCreate(ContainerID) +{ + yulAssert(false, "eofcreate not implemented."); + +} +void NoOutputAssembly::appendReturnContract(ContainerID) +{ + yulAssert(false, "returncontract not implemented."); +} + NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom): EVMDialect(_copyFrom.evmVersion(), _copyFrom.eofVersion(), _copyFrom.providesObjectAccess()) { diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h index cc70d75af..5af1bd418 100644 --- a/libyul/backends/evm/NoOutputAssembly.h +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -76,6 +76,8 @@ class NoOutputAssembly: public AbstractAssembly void appendImmutableAssignment(std::string const& _identifier) override; void appendAuxDataLoadN(uint16_t) override; + void appendEOFCreate(ContainerID) override; + void appendReturnContract(ContainerID) override; void markAsInvalid() override {} diff --git a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output index d5c02fc82..975582f66 100644 --- a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output +++ b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output @@ -312,6 +312,7 @@ object "D_27" { var__5_mpos := zero_t_string_memory_ptr_1_mpos /// @src 0:446:491 "new /// @src 0:149:156 \"new C()\"..." + let _2 := allocate_unbounded() let _3 := add(_2, datasize("C_2")) if or(gt(_3, 0xffffffffffffffff), lt(_3, _2)) { panic_error_0x41() } diff --git a/test/cmdlineTests/standard_viair_requested/output.json b/test/cmdlineTests/standard_viair_requested/output.json index 0105ea972..133815b97 100644 --- a/test/cmdlineTests/standard_viair_requested/output.json +++ b/test/cmdlineTests/standard_viair_requested/output.json @@ -201,6 +201,7 @@ object \"D_16\" { function fun_f_15() { /// @src 0:134:141 \"new C()\" + let _1 := allocate_unbounded() let _2 := add(_1, datasize(\"C_3\")) if or(gt(_2, 0xffffffffffffffff), lt(_2, _1)) { panic_error_0x41() } diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/input.yul b/test/cmdlineTests/strict_asm_eof_container_prague/input.yul index 09306772c..d4d9190ff 100644 --- a/test/cmdlineTests/strict_asm_eof_container_prague/input.yul +++ b/test/cmdlineTests/strict_asm_eof_container_prague/input.yul @@ -1,33 +1,34 @@ object "object" { code { - revert(0, 0) + mstore(0, eofcreate("sub0", 0, 0, 0, 0)) + mstore(32, eofcreate("sub1", 0, 0, 0, 0)) + return(0, 64) } object "sub0" { code { - mstore(0, 0) - revert(0, 32) + returncontract("sub00", 0, 0) } - } - object "sub1" { - code { - mstore(0, 1) - revert(0, 32) + object "sub00" { + code { + mstore(0, 1) + revert(0, 32) + } } } - object "sub2" { + + object "sub1" { code { - mstore(0, 2) - revert(0, 32) + returncontract("sub10", 0, 0) } - object "sub20" { + object "sub10" { code { mstore(0, 0x20) revert(0, 32) } } } - object "sub3" { + object "sub2" { code { mstore(0, 3) revert(0, 32) diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/output b/test/cmdlineTests/strict_asm_eof_container_prague/output index 17f6df675..26d37caf4 100644 --- a/test/cmdlineTests/strict_asm_eof_container_prague/output +++ b/test/cmdlineTests/strict_asm_eof_container_prague/output @@ -3,31 +3,31 @@ Pretty printed source: object "object" { - code { { revert(0, 0) } } - object "sub0" { - code { - { - mstore(0, 0) - revert(0, 32) - } + code { + { + mstore(0, eofcreate("sub0", 0, 0, 0, 0)) + mstore(32, eofcreate("sub1", 0, 0, 0, 0)) + return(0, 64) } } - object "sub1" { + object "sub0" { code { - { - mstore(0, 1) - revert(0, 32) + { returncontract("sub00", 0, 0) } + } + object "sub00" { + code { + { + mstore(0, 1) + revert(0, 32) + } } } } - object "sub2" { + object "sub1" { code { - { - mstore(0, 2) - revert(0, 32) - } + { returncontract("sub10", 0, 0) } } - object "sub20" { + object "sub10" { code { { mstore(0, 0x20) @@ -36,7 +36,7 @@ object "object" { } } } - object "sub3" { + object "sub2" { code { { mstore(0, 3) @@ -48,39 +48,48 @@ object "object" { Binary representation: -ef00010100040200010003030004001a001b003b001b040000000080ffff5f80fdef00010100040200010007040000000080ffff5f805260205ffdef00010100040200010008040000000080ffff60015f5260205ffdef00010100040200010008030001001b040000000080ffff60025f5260205ffdef00010100040200010008040000000080ffff60205f5260205ffdef00010100040200010008040000000080ffff60035f5260205ffd +ef0001010004020001001503000200370037040000000080ffff5f808080ec005f525f808080ec0160205260405ff3ef00010100040200010004030001001b040000000080ffff5f80ee00ef00010100040200010008040000000080ffff60015f5260205ffdef00010100040200010004030001001b040000000080ffff5f80ee00ef00010100040200010008040000000080ffff60205f5260205ffd Text representation: 0x00 dup1 - revert + dup1 + dup1 + eofcreate{0} + 0x00 + mstore + 0x00 + dup1 + dup1 + dup1 + eofcreate{1} + 0x20 + mstore + 0x40 + 0x00 + return stop sub_0: assembly { 0x00 dup1 - mstore - 0x20 - 0x00 - revert -} + returcontract{0} + stop -sub_1: assembly { - 0x01 - 0x00 - mstore - 0x20 - 0x00 - revert + sub_0: assembly { + 0x01 + 0x00 + mstore + 0x20 + 0x00 + revert + } } -sub_2: assembly { - 0x02 - 0x00 - mstore - 0x20 +sub_1: assembly { 0x00 - revert + dup1 + returcontract{0} stop sub_0: assembly { @@ -93,7 +102,7 @@ sub_2: assembly { } } -sub_3: assembly { +sub_2: assembly { 0x03 0x00 mstore diff --git a/test/libyul/objectCompiler/eof/creation_with_immutables.yul b/test/libyul/objectCompiler/eof/creation_with_immutables.yul new file mode 100644 index 000000000..63558294f --- /dev/null +++ b/test/libyul/objectCompiler/eof/creation_with_immutables.yul @@ -0,0 +1,100 @@ +object "a" { + code { + mstore(0, eofcreate("b", 0, 0, 0, 0)) + return(0, 32) + } + + object "b" { + code { + mstore(0, 0x1122334455667788990011223344556677889900112233445566778899001122) + mstore(32, 0x1122334455667788990011223344556677889900112233445566778899001122) + returncontract("c", 0, 64) + } + object "c" { + code { + let d0 := auxdataloadn(0) + let d1 := auxdataloadn(32) + + mstore(0, d0) + mstore(32, d1) + + return(0, 64) + } + } + } + + data "data1" hex"48656c6c6f2c20576f726c6421" +} + +// ==== +// EVMVersion: >=prague +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":80:81 */ +// 0x00 +// /* "source":56:82 */ +// dup1 +// dup1 +// dup1 +// eofcreate{0} +// /* "source":53:54 */ +// 0x00 +// /* "source":46:83 */ +// mstore +// /* "source":106:108 */ +// 0x20 +// /* "source":103:104 */ +// 0x00 +// /* "source":96:109 */ +// return +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// +// sub_0: assembly { +// /* "source":198:264 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":195:196 */ +// 0x00 +// /* "source":188:265 */ +// mstore +// /* "source":293:359 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":289:291 */ +// 0x20 +// /* "source":282:360 */ +// mstore +// /* "source":400:402 */ +// 0x40 +// /* "source":397:398 */ +// 0x00 +// /* "source":377:403 */ +// returcontract{0} +// stop +// +// sub_0: assembly { +// /* "source":516:531 */ +// auxdataloadn{0} +// /* "source":562:578 */ +// auxdataloadn{32} +// /* "source":599:612 */ +// swap1 +// /* "source":606:607 */ +// 0x00 +// /* "source":599:612 */ +// mstore +// /* "source":640:642 */ +// 0x20 +// /* "source":633:647 */ +// mstore +// /* "source":678:680 */ +// 0x40 +// /* "source":675:676 */ +// 0x00 +// /* "source":668:681 */ +// return +// } +// } +// Bytecode: ef0001010004020001000c030001008704000d000080ffff5f808080ec005f5260205ff3ef0001010004020001004c0300010023040000000080ffff7f11223344556677889900112233445566778899001122334455667788990011225f527f112233445566778899001122334455667788990011223344556677889900112260205260405fee00ef00010100040200010010040040000080ffffd10000d10020905f5260205260405ff348656c6c6f2c20576f726c6421 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0xC SUB STOP ADD STOP DUP8 DIV STOP 0xD STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0x4C SUB STOP ADD STOP 0x23 DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH0 MSTORE PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH1 0x20 MSTORE PUSH1 0x40 PUSH0 RETURNCONTRACT 0x0 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP LT DIV STOP BLOCKHASH STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT DATALOADN 0x0 DATALOADN 0x20 SWAP1 PUSH0 MSTORE PUSH1 0x20 MSTORE PUSH1 0x40 PUSH0 RETURN BASEFEE PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000 +// SourceMappings: 80:1:0:-:0;56:26;;;;53:1;46:37;106:2;103:1;96:13 diff --git a/test/libyul/yulSyntaxTests/eof/eofcreate.yul b/test/libyul/yulSyntaxTests/eof/eofcreate.yul new file mode 100644 index 000000000..4169d52ab --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eofcreate.yul @@ -0,0 +1,13 @@ +object "a" { + code { + let addr := eofcreate("b", 0, 0, 0, 0) + return(0, 0) + } + + object "b" { + code {} + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 diff --git a/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object.yul b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object.yul new file mode 100644 index 000000000..f3acc8277 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object.yul @@ -0,0 +1,11 @@ +object "a" { + code { + mstore(0, eofcreate("b", 0, 0, 0, 0)) + return(0, 32) + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 8970: (52-55): Unknown object "b". diff --git a/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul new file mode 100644 index 000000000..1e9fad7d0 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul @@ -0,0 +1,13 @@ +object "a" { + code { + mstore(0, eofcreate("data1", 0, 0, 0, 0)) + return(0, 32) + } + + data "data1" "Hello, World!" +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 7575: (52-59): Data name "data1" cannot be used as an argument of eofcreate/returncontract. An object name is only acceptable. diff --git a/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_path.yul b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_path.yul new file mode 100644 index 000000000..7efaada8b --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_path.yul @@ -0,0 +1,18 @@ +object "a" { + code { + mstore(0, eofcreate("a.b", 0, 0, 0, 0)) + mstore(0, eofcreate("a", 0, 0, 0, 0)) + return(0, 32) + } + + object "b" { + code {} + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 2186: (52-57): Name required but path given as "eofcreate" argument. +// TypeError 8970: (52-57): Unknown object "a.b". +// TypeError 8970: (100-103): Unknown object "a". diff --git a/test/libyul/yulSyntaxTests/eof/returncontract.yul b/test/libyul/yulSyntaxTests/eof/returncontract.yul new file mode 100644 index 000000000..2d193a800 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/returncontract.yul @@ -0,0 +1,12 @@ +object "b" { + code { + returncontract("c", 0, 0) + } + + object "c" { + code {} + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 diff --git a/test/libyul/yulSyntaxTests/eof/returncontract_invalid_object.yul b/test/libyul/yulSyntaxTests/eof/returncontract_invalid_object.yul new file mode 100644 index 000000000..be345ff0a --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/returncontract_invalid_object.yul @@ -0,0 +1,10 @@ +object "a" { + code { + returncontract("b", 0, 0) + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 8970: (47-50): Unknown object "b". diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index b43021ea7..0f1f37451 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -488,7 +488,9 @@ u256 EVMInstructionInterpreter::eval( case Instruction::SWAP16: yulAssert(false, "Impossible in strict assembly."); case Instruction::DATALOADN: - solUnimplemented("DATALOADN unimplemented in yul interpreter."); + case Instruction::EOFCREATE: + case Instruction::RETURNCONTRACT: + solUnimplemented("EOF not yet supported by Yul interpreter."); } util::unreachable(); From c66905a18999b5c4be2678a7829b6703f902e341 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 8 Oct 2024 18:20:28 +0200 Subject: [PATCH 0454/1340] Avoid multiple lookups during body-copying while inlining. --- libyul/optimiser/FullInliner.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index df18a687f..328ef83b8 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -363,8 +363,5 @@ Statement BodyCopier::operator()(FunctionDefinition const&) YulName BodyCopier::translateIdentifier(YulName _name) { - if (m_variableReplacements.count(_name)) - return m_variableReplacements.at(_name); - else - return _name; + return util::valueOrDefault(m_variableReplacements, _name, _name); } From fff9260306fe66e81ecd75c195181590db0bcb83 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 15 Aug 2024 17:22:25 +0200 Subject: [PATCH 0455/1340] Remove special "m" and "s" strings from UnusedStoreEliminator. --- libyul/optimiser/UnusedAssignEliminator.h | 2 +- libyul/optimiser/UnusedStoreBase.cpp | 27 ++++++++++++++++------- libyul/optimiser/UnusedStoreBase.h | 6 ++++- libyul/optimiser/UnusedStoreEliminator.h | 8 +++---- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/libyul/optimiser/UnusedAssignEliminator.h b/libyul/optimiser/UnusedAssignEliminator.h index 9c3b1e4bc..ea2116f03 100644 --- a/libyul/optimiser/UnusedAssignEliminator.h +++ b/libyul/optimiser/UnusedAssignEliminator.h @@ -113,7 +113,7 @@ struct Dialect; * * Prerequisite: Disambiguator, ForLoopInitRewriter. */ -class UnusedAssignEliminator: public UnusedStoreBase +class UnusedAssignEliminator: public UnusedStoreBase { public: static constexpr char const* name{"UnusedAssignEliminator"}; diff --git a/libyul/optimiser/UnusedStoreBase.cpp b/libyul/optimiser/UnusedStoreBase.cpp index 977db11c4..4159b875f 100644 --- a/libyul/optimiser/UnusedStoreBase.cpp +++ b/libyul/optimiser/UnusedStoreBase.cpp @@ -32,7 +32,8 @@ using namespace solidity; using namespace solidity::yul; -void UnusedStoreBase::operator()(If const& _if) +template +void UnusedStoreBase::operator()(If const& _if) { visit(*_if.condition); @@ -42,7 +43,8 @@ void UnusedStoreBase::operator()(If const& _if) merge(m_activeStores, std::move(skipBranch)); } -void UnusedStoreBase::operator()(Switch const& _switch) +template +void UnusedStoreBase::operator()(Switch const& _switch) { visit(*_switch.expression); @@ -68,7 +70,8 @@ void UnusedStoreBase::operator()(Switch const& _switch) merge(m_activeStores, std::move(branch)); } -void UnusedStoreBase::operator()(FunctionDefinition const& _functionDefinition) +template +void UnusedStoreBase::operator()(FunctionDefinition const& _functionDefinition) { ScopedSaveAndRestore allStores(m_allStores, {}); ScopedSaveAndRestore usedStores(m_usedStores, {}); @@ -82,7 +85,8 @@ void UnusedStoreBase::operator()(FunctionDefinition const& _functionDefinition) m_storesToRemove += m_allStores - m_usedStores; } -void UnusedStoreBase::operator()(ForLoop const& _forLoop) +template +void UnusedStoreBase::operator()(ForLoop const& _forLoop) { ScopedSaveAndRestore outerForLoopInfo(m_forLoopInfo, {}); ScopedSaveAndRestore forLoopNestingDepth(m_forLoopNestingDepth, m_forLoopNestingDepth + 1); @@ -130,19 +134,22 @@ void UnusedStoreBase::operator()(ForLoop const& _forLoop) m_forLoopInfo.pendingBreakStmts.clear(); } -void UnusedStoreBase::operator()(Break const&) +template +void UnusedStoreBase::operator()(Break const&) { m_forLoopInfo.pendingBreakStmts.emplace_back(std::move(m_activeStores)); m_activeStores.clear(); } -void UnusedStoreBase::operator()(Continue const&) +template +void UnusedStoreBase::operator()(Continue const&) { m_forLoopInfo.pendingContinueStmts.emplace_back(std::move(m_activeStores)); m_activeStores.clear(); } -void UnusedStoreBase::merge(ActiveStores& _target, ActiveStores&& _other) +template +void UnusedStoreBase::merge(ActiveStores& _target, ActiveStores&& _other) { util::joinMap(_target, std::move(_other), []( std::set& _storesHere, @@ -153,9 +160,13 @@ void UnusedStoreBase::merge(ActiveStores& _target, ActiveStores&& _other) }); } -void UnusedStoreBase::merge(ActiveStores& _target, std::vector&& _source) +template +void UnusedStoreBase::merge(ActiveStores& _target, std::vector&& _source) { for (ActiveStores& ts: _source) merge(_target, std::move(ts)); _source.clear(); } + +template class solidity::yul::UnusedStoreBase; +template class solidity::yul::UnusedStoreBase; diff --git a/libyul/optimiser/UnusedStoreBase.h b/libyul/optimiser/UnusedStoreBase.h index b6dde8c55..e5c11c491 100644 --- a/libyul/optimiser/UnusedStoreBase.h +++ b/libyul/optimiser/UnusedStoreBase.h @@ -46,6 +46,7 @@ struct Dialect; * * Prerequisite: Disambiguator, ForLoopInitRewriter. */ +template class UnusedStoreBase: public ASTWalker { public: @@ -60,7 +61,7 @@ class UnusedStoreBase: public ASTWalker void operator()(Continue const&) override; protected: - using ActiveStores = std::map>; + using ActiveStores = std::map>; /// This function is called for a loop that is nested too deep to avoid /// horrible runtime and should just resolve the situation in a pragmatic @@ -98,4 +99,7 @@ class UnusedStoreBase: public ASTWalker size_t m_forLoopNestingDepth = 0; }; +enum class UnusedStoreEliminatorKey { Memory, Storage }; +extern template class UnusedStoreBase; +extern template class UnusedStoreBase; } diff --git a/libyul/optimiser/UnusedStoreEliminator.h b/libyul/optimiser/UnusedStoreEliminator.h index 98023b64c..6f50636a7 100644 --- a/libyul/optimiser/UnusedStoreEliminator.h +++ b/libyul/optimiser/UnusedStoreEliminator.h @@ -50,13 +50,11 @@ struct AssignedValue; * to sstore, as we don't know whether the memory location will be read once we leave the function's scope, * so the statement will be removed only if all code code paths lead to a memory overwrite. * - * The m_store member of UnusedStoreBase uses the key "m" for memory and "s" for storage stores. - * * Best run in SSA form. * * Prerequisite: Disambiguator, ForLoopInitRewriter. */ -class UnusedStoreEliminator: public UnusedStoreBase +class UnusedStoreEliminator: public UnusedStoreBase { public: static constexpr char const* name{"UnusedStoreEliminator"}; @@ -92,8 +90,8 @@ class UnusedStoreEliminator: public UnusedStoreBase }; private: - std::set& activeMemoryStores() { return m_activeStores["m"_yulname]; } - std::set& activeStorageStores() { return m_activeStores["s"_yulname]; } + std::set& activeMemoryStores() { return m_activeStores[UnusedStoreEliminatorKey::Memory]; } + std::set& activeStorageStores() { return m_activeStores[UnusedStoreEliminatorKey::Storage]; } void shortcutNestedLoop(ActiveStores const&) override { From cbfe4a1f77fdf6301c53b205f7eac802fd0126c4 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 15 Aug 2024 17:41:13 +0200 Subject: [PATCH 0456/1340] Replace special names for literals in UnusedStoreEliminator. --- libyul/optimiser/UnusedStoreEliminator.cpp | 38 ++++++++-------------- libyul/optimiser/UnusedStoreEliminator.h | 10 +++++- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/libyul/optimiser/UnusedStoreEliminator.cpp b/libyul/optimiser/UnusedStoreEliminator.cpp index f4f056697..7c68d577b 100644 --- a/libyul/optimiser/UnusedStoreEliminator.cpp +++ b/libyul/optimiser/UnusedStoreEliminator.cpp @@ -43,12 +43,6 @@ using namespace solidity; using namespace solidity::yul; -/// Variable names for special constants that can never appear in actual Yul code. -static std::string const zero{"@ 0"}; -static std::string const one{"@ 1"}; -static std::string const thirtyTwo{"@ 32"}; - - void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) { std::map functionSideEffects = SideEffectsPropagator::sideEffects( @@ -61,12 +55,6 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) std::map values; for (auto const& [name, expression]: ssaValues.values()) values[name] = AssignedValue{expression, {}}; - Expression const zeroLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{0})}}; - Expression const oneLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{1})}}; - Expression const thirtyTwoLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{32})}}; - values[YulName{zero}] = AssignedValue{&zeroLiteral, {}}; - values[YulName{one}] = AssignedValue{&oneLiteral, {}}; - values[YulName{thirtyTwo}] = AssignedValue{&thirtyTwoLiteral, {}}; bool const ignoreMemory = MSizeFinder::containsMSize(_context.dialect, _ast); UnusedStoreEliminator rse{ @@ -263,8 +251,8 @@ std::vector UnusedStoreEliminator::operationsF if (_op.lengthConstant) switch (*_op.lengthConstant) { - case 1: ourOp.length = YulName(one); break; - case 32: ourOp.length = YulName(thirtyTwo); break; + case 1: ourOp.length = u256(1); break; + case 32: ourOp.length = u256(32); break; default: yulAssert(false); } return ourOp; @@ -312,8 +300,8 @@ bool UnusedStoreEliminator::knownUnrelated( yulAssert( _op1.length && _op2.length && - m_knowledgeBase.valueIfKnownConstant(*_op1.length) == 1 && - m_knowledgeBase.valueIfKnownConstant(*_op2.length) == 1 + lengthValue(*_op1.length) == 1 && + lengthValue(*_op2.length) == 1 ); return m_knowledgeBase.knownToBeDifferent(*_op1.start, *_op2.start); } @@ -322,14 +310,14 @@ bool UnusedStoreEliminator::knownUnrelated( { yulAssert(_op1.location == Location::Memory, ""); if ( - (_op1.length && m_knowledgeBase.knownToBeZero(*_op1.length)) || - (_op2.length && m_knowledgeBase.knownToBeZero(*_op2.length)) + (_op1.length && lengthValue(*_op1.length) == 0) || + (_op2.length && lengthValue(*_op2.length) == 0) ) return true; if (_op1.start && _op1.length && _op2.start) { - std::optional length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length); + std::optional length1 = lengthValue(*_op1.length); std::optional start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start); std::optional start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start); if ( @@ -341,7 +329,7 @@ bool UnusedStoreEliminator::knownUnrelated( } if (_op2.start && _op2.length && _op1.start) { - std::optional length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length); + std::optional length2 = lengthValue(*_op2.length); std::optional start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start); std::optional start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start); if ( @@ -354,8 +342,8 @@ bool UnusedStoreEliminator::knownUnrelated( if (_op1.start && _op1.length && _op2.start && _op2.length) { - std::optional length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length); - std::optional length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length); + std::optional length1 = lengthValue(*_op1.length); + std::optional length2 = lengthValue(*_op2.length); if ( (length1 && *length1 <= 32) && (length2 && *length2 <= 32) && @@ -382,15 +370,15 @@ bool UnusedStoreEliminator::knownCovered( return true; if (_covered.location == Location::Memory) { - if (_covered.length && m_knowledgeBase.knownToBeZero(*_covered.length)) + if (_covered.length && lengthValue(*_covered.length) == 0) return true; // Condition (i = cover_i_ng, e = cover_e_d): // i.start <= e.start && e.start + e.length <= i.start + i.length if (!_covered.start || !_covering.start || !_covered.length || !_covering.length) return false; - std::optional coveredLength = m_knowledgeBase.valueIfKnownConstant(*_covered.length); - std::optional coveringLength = m_knowledgeBase.valueIfKnownConstant(*_covering.length); + std::optional coveredLength = lengthValue(*_covered.length); + std::optional coveringLength = lengthValue(*_covering.length); if (*_covered.start == *_covering.start) if (coveredLength && coveringLength && *coveredLength <= *coveringLength) return true; diff --git a/libyul/optimiser/UnusedStoreEliminator.h b/libyul/optimiser/UnusedStoreEliminator.h index 6f50636a7..f749a229c 100644 --- a/libyul/optimiser/UnusedStoreEliminator.h +++ b/libyul/optimiser/UnusedStoreEliminator.h @@ -78,6 +78,7 @@ class UnusedStoreEliminator: public UnusedStoreBase using Location = evmasm::SemanticInformation::Location; using Effect = evmasm::SemanticInformation::Effect; + using OperationLength = std::variant; struct Operation { Location location; @@ -86,12 +87,19 @@ class UnusedStoreEliminator: public UnusedStoreBase std::optional start; /// Length of affected area, unknown if not provided. /// Unused for storage. - std::optional length; + std::optional length; }; private: std::set& activeMemoryStores() { return m_activeStores[UnusedStoreEliminatorKey::Memory]; } std::set& activeStorageStores() { return m_activeStores[UnusedStoreEliminatorKey::Storage]; } + std::optional lengthValue(OperationLength const& _length) const + { + if (YulName const* length = std::get_if(&_length)) + return m_knowledgeBase.valueIfKnownConstant(*length); + else + return std::get(_length); + } void shortcutNestedLoop(ActiveStores const&) override { From 371647ca13f960e32c72971cee8bdc50608c7251 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:32:49 +0200 Subject: [PATCH 0457/1340] Yul: Object contains dialect --- libsolidity/ast/ASTJsonExporter.cpp | 2 +- libsolidity/codegen/CompilerContext.cpp | 6 +++--- libsolidity/codegen/ContractCompiler.cpp | 2 +- libsolidity/codegen/ir/IRGeneratorForStatements.cpp | 2 +- .../codegen/IRGeneratorForStatements.cpp | 2 +- libsolidity/interface/CompilerStack.cpp | 2 +- libyul/AsmJsonConverter.h | 4 +++- libyul/AsmPrinter.h | 3 +++ libyul/Object.cpp | 3 ++- libyul/Object.h | 8 ++++++-- libyul/ObjectOptimizer.cpp | 1 + libyul/ObjectParser.cpp | 4 ++-- libyul/backends/evm/EVMDialect.h | 2 +- libyul/backends/evm/EVMObjectCompiler.h | 2 +- libyul/optimiser/StackCompressor.h | 2 +- libyul/optimiser/StackLimitEvader.h | 2 +- libyul/optimiser/Suite.cpp | 2 +- libyul/optimiser/Suite.h | 2 +- test/libyul/Common.cpp | 7 ++++++- test/libyul/Common.h | 2 +- test/libyul/CompilabilityChecker.cpp | 12 ++++++------ test/libyul/ControlFlowSideEffectsTest.cpp | 9 ++++++--- test/libyul/FunctionSideEffects.cpp | 9 ++++++--- test/libyul/YulOptimizerTest.cpp | 2 +- test/libyul/YulOptimizerTest.h | 2 +- test/libyul/YulOptimizerTestCommon.h | 2 +- test/tools/yulopti.cpp | 6 +++--- tools/yulPhaser/Program.cpp | 4 ++-- 28 files changed, 64 insertions(+), 42 deletions(-) diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 7183c64a3..4e7a5cd50 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -667,7 +667,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) auto const& evmDialect = dynamic_cast(_node.dialect()); std::vector> attributes = { - std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations().root()))), + std::make_pair("AST", Json(yul::AsmJsonConverter(evmDialect, sourceIndexFromLocation(_node.location()))(_node.operations().root()))), std::make_pair("externalReferences", std::move(externalReferencesJson)), std::make_pair("evmVersion", evmDialect.evmVersion().name()) }; diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 4a0f636dc..84de00656 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -481,7 +481,7 @@ void CompilerContext::appendInlineAssembly( // so we essentially only optimize the ABI functions. if (_optimiserSettings.runYulOptimiser && _localVariables.empty()) { - yul::Object obj; + yul::Object obj{dialect}; obj.setCode(parserResult, std::make_shared(analysisInfo)); solAssert(!dialect.providesObjectAccess()); @@ -491,8 +491,8 @@ void CompilerContext::appendInlineAssembly( { // Store as generated sources, but first re-parse to update the source references. solAssert(m_generatedYulUtilityCode.empty(), ""); - m_generatedYulUtilityCode = yul::AsmPrinter()(obj.code()->root()); - std::string code = yul::AsmPrinter{}(obj.code()->root()); + m_generatedYulUtilityCode = yul::AsmPrinter(obj.dialect())(obj.code()->root()); + std::string code = yul::AsmPrinter{obj.dialect()}(obj.code()->root()); langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); obj.setCode(yul::Parser(errorReporter, dialect).parse(charStream)); obj.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj)); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 96b1ea548..97ffb17e9 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -932,7 +932,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) // Only used in the scope below, but required to live outside to keep the // std::shared_ptr's alive - yul::Object object = {}; + yul::Object object{_inlineAssembly.dialect()}; // The optimiser cannot handle external references if ( diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 69d24cf42..5054e1aa1 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2258,7 +2258,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) solAssert(std::holds_alternative(modified)); - appendCode() << yul::AsmPrinter()(std::get(modified)) << "\n"; + appendCode() << yul::AsmPrinter(_inlineAsm.dialect())(std::get(modified)) << "\n"; return false; } diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index a9e4fa931..80c442b88 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -132,7 +132,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _assembly) CopyTranslate bodyCopier{m_context, _assembly.dialect(), _assembly.annotation().externalReferences}; yul::Statement modified = bodyCopier(_assembly.operations().root()); solAssert(std::holds_alternative(modified)); - m_code << yul::AsmPrinter()(std::get(modified)) << "\n"; + m_code << yul::AsmPrinter(_assembly.dialect())(std::get(modified)) << "\n"; return false; } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index e3927d4df..f24fae3cd 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -900,7 +900,7 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion, m_eofVersion); std::shared_ptr parserResult = yul::Parser{errorReporter, dialect}.parse(charStream); solAssert(parserResult); - sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex}(parserResult->root()); + sources[0]["ast"] = yul::AsmJsonConverter{dialect, sourceIndex}(parserResult->root()); sources[0]["name"] = sourceName; sources[0]["id"] = sourceIndex; sources[0]["language"] = "Yul"; diff --git a/libyul/AsmJsonConverter.h b/libyul/AsmJsonConverter.h index 523825830..75e3400b7 100644 --- a/libyul/AsmJsonConverter.h +++ b/libyul/AsmJsonConverter.h @@ -33,6 +33,8 @@ namespace solidity::yul { +struct Dialect; + /** * Converter of the yul AST into JSON format */ @@ -41,7 +43,7 @@ class AsmJsonConverter: public boost::static_visitor public: /// Create a converter to JSON for any block of inline assembly /// @a _sourceIndex to be used to abbreviate source name in the source locations - explicit AsmJsonConverter(std::optional _sourceIndex): m_sourceIndex(_sourceIndex) {} + explicit AsmJsonConverter(Dialect const&, std::optional _sourceIndex): m_sourceIndex(_sourceIndex) {} Json operator()(Block const& _node) const; Json operator()(NameWithDebugData const& _node) const; diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index cc17c6a04..6eda13fcd 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -37,6 +37,8 @@ namespace solidity::yul { +struct Dialect; + /** * Converts a parsed Yul AST into readable string representation. * Ignores source locations. @@ -45,6 +47,7 @@ class AsmPrinter { public: explicit AsmPrinter( + Dialect const&, std::optional>> _sourceIndexToName = {}, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr diff --git a/libyul/Object.cpp b/libyul/Object.cpp index c6ba5311a..0d5e120a8 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -52,6 +52,7 @@ std::string Object::toString( yulAssert(debugData, "No debug data"); std::string inner = "code " + AsmPrinter( + m_dialect, debugData->sourceNames, _debugInfoSelection, _soliditySourceProvider @@ -96,7 +97,7 @@ Json Object::toJson() const Json codeJson; codeJson["nodeType"] = "YulCode"; - codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */)(code()->root()); + codeJson["block"] = AsmJsonConverter(m_dialect, 0 /* sourceIndex */)(code()->root()); Json subObjectsJson = Json::array(); for (std::shared_ptr const& subObject: subObjects) diff --git a/libyul/Object.h b/libyul/Object.h index 230f97866..15b94044b 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -41,7 +41,7 @@ struct AsmAnalysisInfo; using SourceNameMap = std::map>; -struct Object; +class Object; /** * Generic base class for both Yul objects and Yul data. @@ -88,9 +88,10 @@ struct ObjectDebugData /** * Yul code and data object container. */ -struct Object: public ObjectNode +class Object: public ObjectNode { public: + explicit Object(Dialect const& _dialect): m_dialect(_dialect) {} /// @returns a (parseable) string representation. std::string toString( langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), @@ -139,7 +140,10 @@ struct Object: public ObjectNode /// @returns the name of the special metadata data object. static std::string metadataName() { return ".metadata"; } + Dialect const& dialect() const { return m_dialect; } + private: + Dialect const& m_dialect; std::shared_ptr m_code; }; diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index 511fc979d..6a6354f94 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -142,6 +142,7 @@ std::optional ObjectOptimizer::calculateCacheKey( ) { AsmPrinter asmPrinter( + languageToDialect(_settings.language, _settings.evmVersion, _settings.eofVersion), _debugData.sourceNames, DebugInfoSelection::All() ); diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 123dedcb4..67f5b70dd 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -49,7 +49,7 @@ std::shared_ptr ObjectParser::parse(std::shared_ptr const& _sca if (currentToken() == Token::LBrace) { // Special case: Code-only form. - object = std::make_shared(); + object = std::make_shared(m_dialect); object->name = "object"; auto sourceNameMapping = tryParseSourceNameMapping(); object->debugData = std::make_shared(ObjectDebugData{sourceNameMapping}); @@ -74,7 +74,7 @@ std::shared_ptr ObjectParser::parseObject(Object* _containingObject) { RecursionGuard guard(*this); - std::shared_ptr ret = std::make_shared(); + std::shared_ptr ret = std::make_shared(m_dialect); auto sourceNameMapping = tryParseSourceNameMapping(); ret->debugData = std::make_shared(ObjectDebugData{sourceNameMapping}); diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 1443b4481..65cc70f16 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -34,7 +34,7 @@ namespace solidity::yul { struct FunctionCall; -struct Object; +class Object; /** * Context used during code generation. diff --git a/libyul/backends/evm/EVMObjectCompiler.h b/libyul/backends/evm/EVMObjectCompiler.h index 07ba34a75..5154bd37f 100644 --- a/libyul/backends/evm/EVMObjectCompiler.h +++ b/libyul/backends/evm/EVMObjectCompiler.h @@ -26,7 +26,7 @@ namespace solidity::yul { -struct Object; +class Object; class AbstractAssembly; class EVMDialect; diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index 15d057455..70c020b9c 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -30,7 +30,7 @@ namespace solidity::yul { struct Dialect; -struct Object; +class Object; struct FunctionDefinition; /** diff --git a/libyul/optimiser/StackLimitEvader.h b/libyul/optimiser/StackLimitEvader.h index a5871f7f1..d63c3287d 100644 --- a/libyul/optimiser/StackLimitEvader.h +++ b/libyul/optimiser/StackLimitEvader.h @@ -27,7 +27,7 @@ namespace solidity::yul { -struct Object; +class Object; /** * Optimisation stage that assigns memory offsets to variables that would become unreachable if diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index ff8c2b7cf..c6b5f8cfc 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -486,7 +486,7 @@ void OptimiserSuite::runSequence(std::vector const& _steps, Block& else { std::cout << "== Running " << step << " changed the AST." << std::endl; - std::cout << AsmPrinter{}(_ast) << std::endl; + std::cout << AsmPrinter{m_context.dialect}(_ast) << std::endl; copy = std::make_unique(std::get(ASTCopier{}(_ast))); } } diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index efa82f48c..e4eac31df 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -38,7 +38,7 @@ namespace solidity::yul struct AsmAnalysisInfo; struct Dialect; class GasMeter; -struct Object; +class Object; /** * Optimiser suite that combines all steps and also provides the settings for the heuristics. diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 6562e1743..9b72fdc29 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -99,7 +99,12 @@ yul::Block yul::test::disambiguate(std::string const& _source) std::string yul::test::format(std::string const& _source) { - return yul::AsmPrinter()(parse(_source).first->root()); + Dialect const& dialect = languageToDialect( + YulStack::Language::StrictAssembly, + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); + return AsmPrinter(dialect)(parse(_source).first->root()); } namespace diff --git a/test/libyul/Common.h b/test/libyul/Common.h index 2255272b6..54c61f875 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -37,7 +37,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; struct Block; -struct Object; +class Object; struct Dialect; class AST; } diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index 6c86ac21f..9691efa21 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -34,15 +34,15 @@ namespace { std::string check(std::string const& _input) { - Object obj; + auto const& dialect = EVMDialect::strictAssemblyForEVM( + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); + Object obj{dialect}; auto parsingResult = yul::test::parse(_input); obj.setCode(parsingResult.first, parsingResult.second); BOOST_REQUIRE(obj.hasCode()); - auto functions = CompilabilityChecker( - EVMDialect::strictAssemblyForEVM( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ), obj, true).stackDeficit; + auto functions = CompilabilityChecker(dialect, obj, true).stackDeficit; std::string out; for (auto const& function: functions) out += function.first.str() + ": " + std::to_string(function.second) + " "; diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index b9d883dcd..799f64ce7 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -56,15 +56,18 @@ ControlFlowSideEffectsTest::ControlFlowSideEffectsTest(std::string const& _filen TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - Object obj; + auto const& dialect = EVMDialect::strictAssemblyForEVMObjects( + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); + Object obj{dialect}; auto parsingResult = yul::test::parse(m_source); obj.setCode(parsingResult.first, parsingResult.second); if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); ControlFlowSideEffectsCollector sideEffects( - EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion()), + dialect, obj.code()->root() ); m_obtainedResult.clear(); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index a878d375d..bd9a9da07 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -82,15 +82,18 @@ FunctionSideEffects::FunctionSideEffects(std::string const& _filename): TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - Object obj; + auto const& dialect = EVMDialect::strictAssemblyForEVMObjects( + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); + Object obj{dialect}; auto parsingResult = yul::test::parse(m_source); obj.setCode(parsingResult.first, parsingResult.second); if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); std::map functionSideEffects = SideEffectsPropagator::sideEffects( - EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion()), + dialect, CallGraphGenerator::callGraph(obj.code()->root()) ); diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 308afef5f..c17beb84d 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -85,7 +85,7 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co auto optimizedObject = tester.optimizedObject(); std::string printedOptimizedObject; if (optimizedObject->subObjects.empty()) - printedOptimizedObject = AsmPrinter{}(optimizedObject->code()->root()); + printedOptimizedObject = AsmPrinter{optimizedObject->dialect()}(optimizedObject->code()->root()); else printedOptimizedObject = optimizedObject->toString(); diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 832b5dfb8..241281288 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -29,7 +29,7 @@ using ErrorList = std::vector>; namespace solidity::yul { struct AsmAnalysisInfo; -struct Object; +class Object; struct Dialect; } diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h index 41806fcd6..b214b80c0 100644 --- a/test/libyul/YulOptimizerTestCommon.h +++ b/test/libyul/YulOptimizerTestCommon.h @@ -29,7 +29,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; -struct Object; +class Object; struct Dialect; class AST; } diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index cbe021967..a1a5e8c58 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -180,7 +180,7 @@ class YulOpti parse(_source); disambiguate(); OptimiserSuite{m_context}.runSequence(_steps, *m_astRoot); - std::cout << AsmPrinter{}(*m_astRoot) << std::endl; + std::cout << AsmPrinter{m_dialect}(*m_astRoot) << std::endl; } void runInteractive(std::string _source, bool _disambiguated = false) @@ -217,7 +217,7 @@ class YulOpti break; case ';': { - Object obj; + Object obj{m_dialect}; obj.setCode(std::make_shared(std::get(ASTCopier{}(*m_astRoot)))); *m_astRoot = std::get<1>(StackCompressor::run(m_dialect, obj, true, 16)); break; @@ -228,7 +228,7 @@ class YulOpti *m_astRoot ); } - _source = AsmPrinter{}(*m_astRoot); + _source = AsmPrinter{m_dialect}(*m_astRoot); } catch (...) { diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index fa7fbe274..25cc8c550 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -106,12 +106,12 @@ void Program::optimise(std::vector const& _optimisationSteps) std::ostream& phaser::operator<<(std::ostream& _stream, Program const& _program) { - return _stream << AsmPrinter()(_program.m_ast->root()); + return _stream << AsmPrinter(_program.m_dialect)(_program.m_ast->root()); } std::string Program::toJson() const { - Json serializedAst = AsmJsonConverter(0)(m_ast->root()); + Json serializedAst = AsmJsonConverter(m_dialect, 0)(m_ast->root()); return jsonPrettyPrint(removeNullMembers(std::move(serializedAst))); } From 2162dec0c92e1b68bd2e10c9f8732354fa8cf6d6 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:38:43 +0100 Subject: [PATCH 0458/1340] Yul SSACFG JSON export fix: Function arguments are referenced by their value ids --- libyul/YulControlFlowGraphExporter.cpp | 5 +- .../standard_yul_cfg_json_export/output.json | 90 +++++++++---------- test/cmdlineTests/yul_cfg_json_export/output | 90 +++++++++---------- 3 files changed, 92 insertions(+), 93 deletions(-) diff --git a/libyul/YulControlFlowGraphExporter.cpp b/libyul/YulControlFlowGraphExporter.cpp index 13770989b..6219d51b8 100644 --- a/libyul/YulControlFlowGraphExporter.cpp +++ b/libyul/YulControlFlowGraphExporter.cpp @@ -74,9 +74,8 @@ Json YulControlFlowGraphExporter::exportFunction(SSACFG const& _cfg) Json functionJson = Json::object(); functionJson["type"] = "Function"; functionJson["entry"] = "Block" + std::to_string(_cfg.entry.value); - functionJson["arguments"] = Json::array(); - for (auto const& [arg, valueId]: _cfg.arguments) - functionJson["arguments"].emplace_back(arg.get().name.str()); + static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", std::get<1>(_arg).value); }; + functionJson["arguments"] = _cfg.arguments | ranges::views::transform(argsTransform) | ranges::to; functionJson["returns"] = Json::array(); for (auto const& ret: _cfg.returns) functionJson["returns"].emplace_back(ret.get().name.str()); diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index d09a6c1a5..a43c553c4 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -380,8 +380,8 @@ "functions": { "abi_decode_tuple_": { "arguments": [ - "headStart", - "dataEnd" + "v0", + "v1" ], "blocks": [ { @@ -447,8 +447,8 @@ }, "abi_encode_t_uint256_to_t_uint256_fromStack": { "arguments": [ - "value", - "pos" + "v0", + "v1" ], "blocks": [ { @@ -485,8 +485,8 @@ }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { "arguments": [ - "headStart", - "value0" + "v0", + "v1" ], "blocks": [ { @@ -569,7 +569,7 @@ }, "cleanup_t_rational_42_by_1": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -591,7 +591,7 @@ }, "cleanup_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -613,7 +613,7 @@ }, "convert_t_rational_42_by_1_to_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -811,7 +811,7 @@ }, "identity": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -908,7 +908,7 @@ }, "shift_right_224_unsigned": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1324,8 +1324,8 @@ "functions": { "abi_decode_t_uint256_fromMemory": { "arguments": [ - "offset", - "end" + "v0", + "v1" ], "blocks": [ { @@ -1365,8 +1365,8 @@ }, "abi_decode_tuple_": { "arguments": [ - "headStart", - "dataEnd" + "v0", + "v1" ], "blocks": [ { @@ -1432,8 +1432,8 @@ }, "abi_decode_tuple_t_uint256_fromMemory": { "arguments": [ - "headStart", - "dataEnd" + "v0", + "v1" ], "blocks": [ { @@ -1525,8 +1525,8 @@ }, "abi_encode_t_uint256_to_t_uint256_fromStack": { "arguments": [ - "value", - "pos" + "v0", + "v1" ], "blocks": [ { @@ -1563,7 +1563,7 @@ }, "abi_encode_tuple__to__fromStack": { "arguments": [ - "headStart" + "v0" ], "blocks": [ { @@ -1597,8 +1597,8 @@ }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { "arguments": [ - "headStart", - "value0" + "v0", + "v1" ], "blocks": [ { @@ -1681,7 +1681,7 @@ }, "cleanup_t_uint160": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1715,7 +1715,7 @@ }, "cleanup_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1737,7 +1737,7 @@ }, "convert_t_contract$_C_$19_to_t_address": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1770,7 +1770,7 @@ }, "convert_t_uint160_to_t_address": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1803,7 +1803,7 @@ }, "convert_t_uint160_to_t_uint160": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1963,8 +1963,8 @@ }, "finalize_allocation": { "arguments": [ - "memPtr", - "size" + "v0", + "v1" ], "blocks": [ { @@ -2528,7 +2528,7 @@ }, "identity": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -2771,7 +2771,7 @@ }, "round_up_to_mul_of_32": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -2824,7 +2824,7 @@ }, "shift_left_224": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -2858,7 +2858,7 @@ }, "shift_right_224_unsigned": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -2892,7 +2892,7 @@ }, "validator_revert_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -3367,8 +3367,8 @@ "functions": { "abi_decode_tuple_": { "arguments": [ - "headStart", - "dataEnd" + "v0", + "v1" ], "blocks": [ { @@ -3434,8 +3434,8 @@ }, "abi_encode_t_uint256_to_t_uint256_fromStack": { "arguments": [ - "value", - "pos" + "v0", + "v1" ], "blocks": [ { @@ -3472,8 +3472,8 @@ }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { "arguments": [ - "headStart", - "value0" + "v0", + "v1" ], "blocks": [ { @@ -3556,7 +3556,7 @@ }, "cleanup_t_rational_42_by_1": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -3578,7 +3578,7 @@ }, "cleanup_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -3600,7 +3600,7 @@ }, "convert_t_rational_42_by_1_to_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -3798,7 +3798,7 @@ }, "identity": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -3895,7 +3895,7 @@ }, "shift_right_224_unsigned": { "arguments": [ - "value" + "v0" ], "blocks": [ { diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index 3a287ee76..d68997bff 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -379,8 +379,8 @@ Yul Control Flow Graph: "functions": { "abi_decode_tuple_": { "arguments": [ - "headStart", - "dataEnd" + "v0", + "v1" ], "blocks": [ { @@ -446,8 +446,8 @@ Yul Control Flow Graph: }, "abi_encode_t_uint256_to_t_uint256_fromStack": { "arguments": [ - "value", - "pos" + "v0", + "v1" ], "blocks": [ { @@ -484,8 +484,8 @@ Yul Control Flow Graph: }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { "arguments": [ - "headStart", - "value0" + "v0", + "v1" ], "blocks": [ { @@ -568,7 +568,7 @@ Yul Control Flow Graph: }, "cleanup_t_rational_42_by_1": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -590,7 +590,7 @@ Yul Control Flow Graph: }, "cleanup_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -612,7 +612,7 @@ Yul Control Flow Graph: }, "convert_t_rational_42_by_1_to_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -810,7 +810,7 @@ Yul Control Flow Graph: }, "identity": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -907,7 +907,7 @@ Yul Control Flow Graph: }, "shift_right_224_unsigned": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1324,8 +1324,8 @@ Yul Control Flow Graph: "functions": { "abi_decode_t_uint256_fromMemory": { "arguments": [ - "offset", - "end" + "v0", + "v1" ], "blocks": [ { @@ -1365,8 +1365,8 @@ Yul Control Flow Graph: }, "abi_decode_tuple_": { "arguments": [ - "headStart", - "dataEnd" + "v0", + "v1" ], "blocks": [ { @@ -1432,8 +1432,8 @@ Yul Control Flow Graph: }, "abi_decode_tuple_t_uint256_fromMemory": { "arguments": [ - "headStart", - "dataEnd" + "v0", + "v1" ], "blocks": [ { @@ -1525,8 +1525,8 @@ Yul Control Flow Graph: }, "abi_encode_t_uint256_to_t_uint256_fromStack": { "arguments": [ - "value", - "pos" + "v0", + "v1" ], "blocks": [ { @@ -1563,7 +1563,7 @@ Yul Control Flow Graph: }, "abi_encode_tuple__to__fromStack": { "arguments": [ - "headStart" + "v0" ], "blocks": [ { @@ -1597,8 +1597,8 @@ Yul Control Flow Graph: }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { "arguments": [ - "headStart", - "value0" + "v0", + "v1" ], "blocks": [ { @@ -1681,7 +1681,7 @@ Yul Control Flow Graph: }, "cleanup_t_uint160": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1715,7 +1715,7 @@ Yul Control Flow Graph: }, "cleanup_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1737,7 +1737,7 @@ Yul Control Flow Graph: }, "convert_t_contract$_C_$19_to_t_address": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1770,7 +1770,7 @@ Yul Control Flow Graph: }, "convert_t_uint160_to_t_address": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1803,7 +1803,7 @@ Yul Control Flow Graph: }, "convert_t_uint160_to_t_uint160": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -1963,8 +1963,8 @@ Yul Control Flow Graph: }, "finalize_allocation": { "arguments": [ - "memPtr", - "size" + "v0", + "v1" ], "blocks": [ { @@ -2528,7 +2528,7 @@ Yul Control Flow Graph: }, "identity": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -2771,7 +2771,7 @@ Yul Control Flow Graph: }, "round_up_to_mul_of_32": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -2824,7 +2824,7 @@ Yul Control Flow Graph: }, "shift_left_224": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -2858,7 +2858,7 @@ Yul Control Flow Graph: }, "shift_right_224_unsigned": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -2892,7 +2892,7 @@ Yul Control Flow Graph: }, "validator_revert_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -3367,8 +3367,8 @@ Yul Control Flow Graph: "functions": { "abi_decode_tuple_": { "arguments": [ - "headStart", - "dataEnd" + "v0", + "v1" ], "blocks": [ { @@ -3434,8 +3434,8 @@ Yul Control Flow Graph: }, "abi_encode_t_uint256_to_t_uint256_fromStack": { "arguments": [ - "value", - "pos" + "v0", + "v1" ], "blocks": [ { @@ -3472,8 +3472,8 @@ Yul Control Flow Graph: }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { "arguments": [ - "headStart", - "value0" + "v0", + "v1" ], "blocks": [ { @@ -3556,7 +3556,7 @@ Yul Control Flow Graph: }, "cleanup_t_rational_42_by_1": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -3578,7 +3578,7 @@ Yul Control Flow Graph: }, "cleanup_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -3600,7 +3600,7 @@ Yul Control Flow Graph: }, "convert_t_rational_42_by_1_to_t_uint256": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -3798,7 +3798,7 @@ Yul Control Flow Graph: }, "identity": { "arguments": [ - "value" + "v0" ], "blocks": [ { @@ -3895,7 +3895,7 @@ Yul Control Flow Graph: }, "shift_right_224_unsigned": { "arguments": [ - "value" + "v0" ], "blocks": [ { From 85318c927695fdfa5443b16108a9f681c6eabc89 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 31 Oct 2024 13:33:22 +0100 Subject: [PATCH 0459/1340] Yul SSACFG JSON export: Change returns field to numReturns --- libyul/YulControlFlowGraphExporter.cpp | 4 +- .../standard_yul_cfg_json_export/output.json | 212 ++++++------------ test/cmdlineTests/yul_cfg_json_export/output | 212 ++++++------------ 3 files changed, 139 insertions(+), 289 deletions(-) diff --git a/libyul/YulControlFlowGraphExporter.cpp b/libyul/YulControlFlowGraphExporter.cpp index 6219d51b8..17737533f 100644 --- a/libyul/YulControlFlowGraphExporter.cpp +++ b/libyul/YulControlFlowGraphExporter.cpp @@ -76,9 +76,7 @@ Json YulControlFlowGraphExporter::exportFunction(SSACFG const& _cfg) functionJson["entry"] = "Block" + std::to_string(_cfg.entry.value); static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", std::get<1>(_arg).value); }; functionJson["arguments"] = _cfg.arguments | ranges::views::transform(argsTransform) | ranges::to; - functionJson["returns"] = Json::array(); - for (auto const& ret: _cfg.returns) - functionJson["returns"].emplace_back(ret.get().name.str()); + functionJson["numReturns"] = _cfg.returns.size(); functionJson["blocks"] = exportBlock(_cfg, _cfg.entry); return functionJson; } diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index a43c553c4..8d3fc5b7e 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -154,9 +154,7 @@ } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "constructor_C_19": { @@ -179,7 +177,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "constructor_I_7": { @@ -195,7 +193,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -220,7 +218,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" } } @@ -442,7 +440,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_encode_t_uint256_to_t_uint256_fromStack": { @@ -480,7 +478,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { @@ -531,9 +529,7 @@ } ], "entry": "Block0", - "returns": [ - "tail" - ], + "numReturns": 1, "type": "Function" }, "allocate_unbounded": { @@ -562,9 +558,7 @@ } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_rational_42_by_1": { @@ -584,9 +578,7 @@ } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_uint256": { @@ -606,9 +598,7 @@ } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "convert_t_rational_42_by_1_to_t_uint256": { @@ -657,9 +647,7 @@ } ], "entry": "Block0", - "returns": [ - "converted" - ], + "numReturns": 1, "type": "Function" }, "external_fun_f_18": { @@ -768,7 +756,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "fun_f_18": { @@ -804,9 +792,7 @@ } ], "entry": "Block0", - "returns": [ - "var__13" - ], + "numReturns": 1, "type": "Function" }, "identity": { @@ -826,9 +812,7 @@ } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" }, "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { @@ -853,7 +837,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -878,7 +862,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { @@ -903,7 +887,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "shift_right_224_unsigned": { @@ -935,9 +919,7 @@ } ], "entry": "Block0", - "returns": [ - "newValue" - ], + "numReturns": 1, "type": "Function" }, "zero_value_for_split_t_uint256": { @@ -955,9 +937,7 @@ } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" } } @@ -1121,9 +1101,7 @@ } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "constructor_D_38": { @@ -1139,7 +1117,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -1164,7 +1142,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" } } @@ -1358,9 +1336,7 @@ } ], "entry": "Block0", - "returns": [ - "value" - ], + "numReturns": 1, "type": "Function" }, "abi_decode_tuple_": { @@ -1427,7 +1403,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_decode_tuple_t_uint256_fromMemory": { @@ -1518,9 +1494,7 @@ } ], "entry": "Block0", - "returns": [ - "value0" - ], + "numReturns": 1, "type": "Function" }, "abi_encode_t_uint256_to_t_uint256_fromStack": { @@ -1558,7 +1532,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_encode_tuple__to__fromStack": { @@ -1590,9 +1564,7 @@ } ], "entry": "Block0", - "returns": [ - "tail" - ], + "numReturns": 1, "type": "Function" }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { @@ -1643,9 +1615,7 @@ } ], "entry": "Block0", - "returns": [ - "tail" - ], + "numReturns": 1, "type": "Function" }, "allocate_unbounded": { @@ -1674,9 +1644,7 @@ } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_uint160": { @@ -1708,9 +1676,7 @@ } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_uint256": { @@ -1730,9 +1696,7 @@ } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "convert_t_contract$_C_$19_to_t_address": { @@ -1763,9 +1727,7 @@ } ], "entry": "Block0", - "returns": [ - "converted" - ], + "numReturns": 1, "type": "Function" }, "convert_t_uint160_to_t_address": { @@ -1796,9 +1758,7 @@ } ], "entry": "Block0", - "returns": [ - "converted" - ], + "numReturns": 1, "type": "Function" }, "convert_t_uint160_to_t_uint160": { @@ -1847,9 +1807,7 @@ } ], "entry": "Block0", - "returns": [ - "converted" - ], + "numReturns": 1, "type": "Function" }, "external_fun_f_37": { @@ -1958,7 +1916,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "finalize_allocation": { @@ -2064,7 +2022,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "fun_f_37": { @@ -2521,9 +2479,7 @@ } ], "entry": "Block0", - "returns": [ - "var__22" - ], + "numReturns": 1, "type": "Function" }, "identity": { @@ -2543,9 +2499,7 @@ } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" }, "panic_error_0x41": { @@ -2586,7 +2540,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_0cc013b6b3b6beabea4e3a74a6d380f0df81852ca99887912475e1f66b2a2c20": { @@ -2611,7 +2565,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { @@ -2636,7 +2590,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db": { @@ -2661,7 +2615,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -2686,7 +2640,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { @@ -2711,7 +2665,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_forward_1": { @@ -2766,7 +2720,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "round_up_to_mul_of_32": { @@ -2817,9 +2771,7 @@ } ], "entry": "Block0", - "returns": [ - "result" - ], + "numReturns": 1, "type": "Function" }, "shift_left_224": { @@ -2851,9 +2803,7 @@ } ], "entry": "Block0", - "returns": [ - "newValue" - ], + "numReturns": 1, "type": "Function" }, "shift_right_224_unsigned": { @@ -2885,9 +2835,7 @@ } ], "entry": "Block0", - "returns": [ - "newValue" - ], + "numReturns": 1, "type": "Function" }, "validator_revert_t_uint256": { @@ -2964,7 +2912,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "zero_value_for_split_t_uint256": { @@ -2982,9 +2930,7 @@ } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" } } @@ -3141,9 +3087,7 @@ } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "constructor_C_19": { @@ -3166,7 +3110,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "constructor_I_7": { @@ -3182,7 +3126,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -3207,7 +3151,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" } } @@ -3429,7 +3373,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_encode_t_uint256_to_t_uint256_fromStack": { @@ -3467,7 +3411,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { @@ -3518,9 +3462,7 @@ } ], "entry": "Block0", - "returns": [ - "tail" - ], + "numReturns": 1, "type": "Function" }, "allocate_unbounded": { @@ -3549,9 +3491,7 @@ } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_rational_42_by_1": { @@ -3571,9 +3511,7 @@ } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_uint256": { @@ -3593,9 +3531,7 @@ } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "convert_t_rational_42_by_1_to_t_uint256": { @@ -3644,9 +3580,7 @@ } ], "entry": "Block0", - "returns": [ - "converted" - ], + "numReturns": 1, "type": "Function" }, "external_fun_f_18": { @@ -3755,7 +3689,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "fun_f_18": { @@ -3791,9 +3725,7 @@ } ], "entry": "Block0", - "returns": [ - "var__13" - ], + "numReturns": 1, "type": "Function" }, "identity": { @@ -3813,9 +3745,7 @@ } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" }, "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { @@ -3840,7 +3770,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -3865,7 +3795,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { @@ -3890,7 +3820,7 @@ } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "shift_right_224_unsigned": { @@ -3922,9 +3852,7 @@ } ], "entry": "Block0", - "returns": [ - "newValue" - ], + "numReturns": 1, "type": "Function" }, "zero_value_for_split_t_uint256": { @@ -3942,9 +3870,7 @@ } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" } } diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index d68997bff..d8f2025b3 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -153,9 +153,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "constructor_C_19": { @@ -178,7 +176,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "constructor_I_7": { @@ -194,7 +192,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -219,7 +217,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" } } @@ -441,7 +439,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_encode_t_uint256_to_t_uint256_fromStack": { @@ -479,7 +477,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { @@ -530,9 +528,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "tail" - ], + "numReturns": 1, "type": "Function" }, "allocate_unbounded": { @@ -561,9 +557,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_rational_42_by_1": { @@ -583,9 +577,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_uint256": { @@ -605,9 +597,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "convert_t_rational_42_by_1_to_t_uint256": { @@ -656,9 +646,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "converted" - ], + "numReturns": 1, "type": "Function" }, "external_fun_f_18": { @@ -767,7 +755,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "fun_f_18": { @@ -803,9 +791,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "var__13" - ], + "numReturns": 1, "type": "Function" }, "identity": { @@ -825,9 +811,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" }, "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { @@ -852,7 +836,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -877,7 +861,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { @@ -902,7 +886,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "shift_right_224_unsigned": { @@ -934,9 +918,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "newValue" - ], + "numReturns": 1, "type": "Function" }, "zero_value_for_split_t_uint256": { @@ -954,9 +936,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" } } @@ -1121,9 +1101,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "constructor_D_38": { @@ -1139,7 +1117,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -1164,7 +1142,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" } } @@ -1358,9 +1336,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "value" - ], + "numReturns": 1, "type": "Function" }, "abi_decode_tuple_": { @@ -1427,7 +1403,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_decode_tuple_t_uint256_fromMemory": { @@ -1518,9 +1494,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "value0" - ], + "numReturns": 1, "type": "Function" }, "abi_encode_t_uint256_to_t_uint256_fromStack": { @@ -1558,7 +1532,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_encode_tuple__to__fromStack": { @@ -1590,9 +1564,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "tail" - ], + "numReturns": 1, "type": "Function" }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { @@ -1643,9 +1615,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "tail" - ], + "numReturns": 1, "type": "Function" }, "allocate_unbounded": { @@ -1674,9 +1644,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_uint160": { @@ -1708,9 +1676,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_uint256": { @@ -1730,9 +1696,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "convert_t_contract$_C_$19_to_t_address": { @@ -1763,9 +1727,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "converted" - ], + "numReturns": 1, "type": "Function" }, "convert_t_uint160_to_t_address": { @@ -1796,9 +1758,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "converted" - ], + "numReturns": 1, "type": "Function" }, "convert_t_uint160_to_t_uint160": { @@ -1847,9 +1807,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "converted" - ], + "numReturns": 1, "type": "Function" }, "external_fun_f_37": { @@ -1958,7 +1916,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "finalize_allocation": { @@ -2064,7 +2022,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "fun_f_37": { @@ -2521,9 +2479,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "var__22" - ], + "numReturns": 1, "type": "Function" }, "identity": { @@ -2543,9 +2499,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" }, "panic_error_0x41": { @@ -2586,7 +2540,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_0cc013b6b3b6beabea4e3a74a6d380f0df81852ca99887912475e1f66b2a2c20": { @@ -2611,7 +2565,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { @@ -2636,7 +2590,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db": { @@ -2661,7 +2615,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -2686,7 +2640,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { @@ -2711,7 +2665,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_forward_1": { @@ -2766,7 +2720,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "round_up_to_mul_of_32": { @@ -2817,9 +2771,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "result" - ], + "numReturns": 1, "type": "Function" }, "shift_left_224": { @@ -2851,9 +2803,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "newValue" - ], + "numReturns": 1, "type": "Function" }, "shift_right_224_unsigned": { @@ -2885,9 +2835,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "newValue" - ], + "numReturns": 1, "type": "Function" }, "validator_revert_t_uint256": { @@ -2964,7 +2912,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "zero_value_for_split_t_uint256": { @@ -2982,9 +2930,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" } } @@ -3141,9 +3087,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "constructor_C_19": { @@ -3166,7 +3110,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "constructor_I_7": { @@ -3182,7 +3126,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -3207,7 +3151,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" } } @@ -3429,7 +3373,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_encode_t_uint256_to_t_uint256_fromStack": { @@ -3467,7 +3411,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { @@ -3518,9 +3462,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "tail" - ], + "numReturns": 1, "type": "Function" }, "allocate_unbounded": { @@ -3549,9 +3491,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "memPtr" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_rational_42_by_1": { @@ -3571,9 +3511,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "cleanup_t_uint256": { @@ -3593,9 +3531,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "cleaned" - ], + "numReturns": 1, "type": "Function" }, "convert_t_rational_42_by_1_to_t_uint256": { @@ -3644,9 +3580,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "converted" - ], + "numReturns": 1, "type": "Function" }, "external_fun_f_18": { @@ -3755,7 +3689,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "fun_f_18": { @@ -3791,9 +3725,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "var__13" - ], + "numReturns": 1, "type": "Function" }, "identity": { @@ -3813,9 +3745,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" }, "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { @@ -3840,7 +3770,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { @@ -3865,7 +3795,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { @@ -3890,7 +3820,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [], + "numReturns": 0, "type": "Function" }, "shift_right_224_unsigned": { @@ -3922,9 +3852,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "newValue" - ], + "numReturns": 1, "type": "Function" }, "zero_value_for_split_t_uint256": { @@ -3942,9 +3870,7 @@ Yul Control Flow Graph: } ], "entry": "Block0", - "returns": [ - "ret" - ], + "numReturns": 1, "type": "Function" } } From c7621f9ceeef8879456d34df1216c0cba4f05d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 1 Nov 2024 01:19:18 +0100 Subject: [PATCH 0460/1340] Refactor external benchmark downloader to reduce duplication --- test/benchmarks/external-setup.sh | 87 ++++++++++++++----------------- 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/test/benchmarks/external-setup.sh b/test/benchmarks/external-setup.sh index 2316d83d5..451e766dd 100755 --- a/test/benchmarks/external-setup.sh +++ b/test/benchmarks/external-setup.sh @@ -40,56 +40,41 @@ function neutralize_via_ir { sed -i '/^via_ir\s*=.*$/d' foundry.toml } -mkdir -p "$BENCHMARK_DIR" -cd "$BENCHMARK_DIR" +function setup_foundry_project { + local subdir="$1" + local ref_type="$2" + local ref="$3" + local repo_url="$4" + local install_function="${5:-}" -if [[ ! -e openzeppelin/ ]]; then - git clone --depth=1 https://github.com/OpenZeppelin/openzeppelin-contracts openzeppelin/ --branch v5.0.2 - pushd openzeppelin/ - forge install - neutralize_via_ir - popd -else - echo "Skipped openzeppelin/. Already exists." -fi + printf ">>> %-22s | " "$subdir" -if [[ ! -e uniswap-v4/ ]]; then - git clone --single-branch https://github.com/Uniswap/v4-core uniswap-v4/ - pushd uniswap-v4/ - git checkout ae86975b058d386c9be24e8994236f662affacdb # branch main as of 2024-06-06 - forge install - neutralize_via_ir - popd -else - echo "Skipped uniswap-v4/. Already exists." -fi + [[ $ref_type == commit || $ref_type == tag ]] || assertFail -if [[ ! -e seaport/ ]]; then - git clone --single-branch https://github.com/ProjectOpenSea/seaport - pushd seaport/ - # NOTE: Can't select the tag with `git clone` because a branch of the same name exists. - git checkout tags/1.6 - forge install - neutralize_via_ir - neutralize_version_pragmas - popd -else - echo "Skipped seaport/. Already exists." -fi + [[ ! -e "$subdir" ]] || { printf "already exists\n"; return; } + printf "downloading...\n\n" + + if [[ $ref_type == tag ]]; then + git clone --depth=1 "$repo_url" "$subdir" --branch "$ref" + pushd "$subdir" + else + git clone "$repo_url" "$subdir" + pushd "$subdir" + git checkout "$ref" + fi + if [[ -z $install_function ]]; then + forge install + else + "$install_function" + fi -if [[ ! -e eigenlayer/ ]]; then - git clone --depth=1 https://github.com/Layr-Labs/eigenlayer-contracts eigenlayer/ --branch v0.3.0-holesky-rewards - pushd eigenlayer/ neutralize_via_ir - forge install + neutralize_version_pragmas popd -else - echo "Skipped eigenlayer/. Already exists." -fi + echo +} -if [[ ! -e sablier-v2/ ]]; then - git clone --depth=1 https://github.com/sablier-labs/v2-core sablier-v2/ --branch v1.1.2 - pushd sablier-v2/ +function install_sablier { # NOTE: To avoid hard-coding dependency versions here we'd have to install them from npm forge install --no-commit \ foundry-rs/forge-std@v1.5.6 \ @@ -106,8 +91,14 @@ forge-std/=lib/forge-std/ solarray/=lib/solarray/ solady/=lib/solady/ EOF - neutralize_via_ir - popd -else - echo "Skipped sablier-v2/. Already exists." -fi +} + +mkdir -p "$BENCHMARK_DIR" +cd "$BENCHMARK_DIR" + +setup_foundry_project openzeppelin/ tag v5.0.2 https://github.com/OpenZeppelin/openzeppelin-contracts +setup_foundry_project uniswap-v4/ commit ae86975b058d386c9be24e8994236f662affacdb https://github.com/Uniswap/v4-core +# NOTE: Can't select the tag with `git clone` because a branch of the same name exists. +setup_foundry_project seaport/ commit tags/1.6 https://github.com/ProjectOpenSea/seaport +setup_foundry_project eigenlayer/ tag v0.3.0-holesky-rewards https://github.com/Layr-Labs/eigenlayer-contracts +setup_foundry_project sablier-v2/ tag v1.1.2 https://github.com/sablier-labs/v2-core install_sablier From 897dbcce2d82e0e568a8d860c43a4ac3ba499ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 1 Nov 2024 01:19:18 +0100 Subject: [PATCH 0461/1340] Add liquity and farcaster as external benchmarks --- test/benchmarks/external-setup.sh | 7 +++++++ test/benchmarks/external.sh | 2 ++ 2 files changed, 9 insertions(+) diff --git a/test/benchmarks/external-setup.sh b/test/benchmarks/external-setup.sh index 451e766dd..30235c478 100755 --- a/test/benchmarks/external-setup.sh +++ b/test/benchmarks/external-setup.sh @@ -74,6 +74,11 @@ function setup_foundry_project { echo } +function install_liquity { + sed -i -e 's|git@github.com:|https://github.com/|g' .gitmodules + forge install +} + function install_sablier { # NOTE: To avoid hard-coding dependency versions here we'd have to install them from npm forge install --no-commit \ @@ -97,8 +102,10 @@ mkdir -p "$BENCHMARK_DIR" cd "$BENCHMARK_DIR" setup_foundry_project openzeppelin/ tag v5.0.2 https://github.com/OpenZeppelin/openzeppelin-contracts +setup_foundry_project liquity/ commit 7f93a3f1781dfce2c4e0b6a7262deddd8a10e45b https://github.com/liquity/V2-gov install_liquity setup_foundry_project uniswap-v4/ commit ae86975b058d386c9be24e8994236f662affacdb https://github.com/Uniswap/v4-core # NOTE: Can't select the tag with `git clone` because a branch of the same name exists. setup_foundry_project seaport/ commit tags/1.6 https://github.com/ProjectOpenSea/seaport setup_foundry_project eigenlayer/ tag v0.3.0-holesky-rewards https://github.com/Layr-Labs/eigenlayer-contracts +setup_foundry_project farcaster/ tag v3.1.0 https://github.com/farcasterxyz/contracts setup_foundry_project sablier-v2/ tag v1.1.2 https://github.com/sablier-labs/v2-core install_sablier diff --git a/test/benchmarks/external.sh b/test/benchmarks/external.sh index 9acaccb67..3f5fe0bbf 100755 --- a/test/benchmarks/external.sh +++ b/test/benchmarks/external.sh @@ -77,9 +77,11 @@ function benchmark_project { benchmarks=( # Fastest ones first so that we get *some* output quickly openzeppelin + liquity uniswap-v4 eigenlayer seaport + farcaster sablier-v2 ) From 14f0c6edc294775a5f12e41851f8b0bfae254ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 1 Nov 2024 01:19:18 +0100 Subject: [PATCH 0462/1340] Add older OpenZeppelin and Uniswap versions to external benchmarks - Also use explicit versions for all projects --- test/benchmarks/external-setup.sh | 33 +++++++++++++++++++++++-------- test/benchmarks/external.sh | 24 ++++++++++++---------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/test/benchmarks/external-setup.sh b/test/benchmarks/external-setup.sh index 30235c478..bbba60bad 100755 --- a/test/benchmarks/external-setup.sh +++ b/test/benchmarks/external-setup.sh @@ -68,7 +68,7 @@ function setup_foundry_project { "$install_function" fi - neutralize_via_ir + [[ ! -e foundry.toml ]] || neutralize_via_ir neutralize_version_pragmas popd echo @@ -79,6 +79,13 @@ function install_liquity { forge install } +function install_old_uniswap { + openzeppelin_version=$(sed -n 's|\s\+"@openzeppelin/contracts": "\([0-9.]\+\)"|\1|p' package.json) + rm package.json + rm yarn.lock + npm install "@openzeppelin/contracts@${openzeppelin_version}" +} + function install_sablier { # NOTE: To avoid hard-coding dependency versions here we'd have to install them from npm forge install --no-commit \ @@ -101,11 +108,21 @@ EOF mkdir -p "$BENCHMARK_DIR" cd "$BENCHMARK_DIR" -setup_foundry_project openzeppelin/ tag v5.0.2 https://github.com/OpenZeppelin/openzeppelin-contracts -setup_foundry_project liquity/ commit 7f93a3f1781dfce2c4e0b6a7262deddd8a10e45b https://github.com/liquity/V2-gov install_liquity -setup_foundry_project uniswap-v4/ commit ae86975b058d386c9be24e8994236f662affacdb https://github.com/Uniswap/v4-core +setup_foundry_project openzeppelin-5.0.2/ tag v5.0.2 https://github.com/OpenZeppelin/openzeppelin-contracts +setup_foundry_project openzeppelin-4.9.0/ tag v4.9.0 https://github.com/OpenZeppelin/openzeppelin-contracts +setup_foundry_project openzeppelin-4.8.0/ tag v4.8.0 https://github.com/OpenZeppelin/openzeppelin-contracts +setup_foundry_project openzeppelin-4.7.0/ tag v4.7.0 https://github.com/OpenZeppelin/openzeppelin-contracts + +setup_foundry_project liquity-2024-10-30/ commit 7f93a3f1781dfce2c4e0b6a7262deddd8a10e45b https://github.com/liquity/V2-gov install_liquity + +setup_foundry_project uniswap-v4-2024-06-06/ commit ae86975b058d386c9be24e8994236f662affacdb https://github.com/Uniswap/v4-core +setup_foundry_project uniswap-v4-2022-06-16/ commit 9aeddf76e1b8646908fbcc7519c882bf458b794d https://github.com/Uniswap/v4-core install_old_uniswap + +setup_foundry_project farcaster-3.1.0/ tag v3.1.0 https://github.com/farcasterxyz/contracts + # NOTE: Can't select the tag with `git clone` because a branch of the same name exists. -setup_foundry_project seaport/ commit tags/1.6 https://github.com/ProjectOpenSea/seaport -setup_foundry_project eigenlayer/ tag v0.3.0-holesky-rewards https://github.com/Layr-Labs/eigenlayer-contracts -setup_foundry_project farcaster/ tag v3.1.0 https://github.com/farcasterxyz/contracts -setup_foundry_project sablier-v2/ tag v1.1.2 https://github.com/sablier-labs/v2-core install_sablier +setup_foundry_project seaport-1.6/ commit tags/1.6 https://github.com/ProjectOpenSea/seaport + +setup_foundry_project eigenlayer-0.3.0/ tag v0.3.0-holesky-rewards https://github.com/Layr-Labs/eigenlayer-contracts + +setup_foundry_project sablier-v2-1.1.2/ tag v1.1.2 https://github.com/sablier-labs/v2-core install_sablier diff --git a/test/benchmarks/external.sh b/test/benchmarks/external.sh index 3f5fe0bbf..16e47ee4f 100755 --- a/test/benchmarks/external.sh +++ b/test/benchmarks/external.sh @@ -65,7 +65,7 @@ function benchmark_project { > /dev/null \ 2> "../stderr-${project}-${pipeline}.log" || true - printf '| %-20s | %8s | %6d s | %9d MiB | %9d |\n' \ + printf '| %-21s | %8s | %6d s | %9d MiB | %9d |\n' \ "$project" \ "$pipeline" \ "$(jq '(.user + .sys) | round' "$time_file")" \ @@ -76,20 +76,24 @@ function benchmark_project { benchmarks=( # Fastest ones first so that we get *some* output quickly - openzeppelin - liquity - uniswap-v4 - eigenlayer - seaport - farcaster - sablier-v2 + uniswap-v4-2022-06-16 # compiles via IR with solc >=0.8.12 + openzeppelin-5.0.2 # compiles via IR with solc >=0.8.26 + openzeppelin-4.9.0 # compiles via IR with solc 0.8.10-0.8.14 and >=0.8.26 + liquity-2024-10-30 # compiles via IR with solc >=0.8.24 + openzeppelin-4.7.0 # compiles via IR with solc >=0.8.10 + openzeppelin-4.8.0 # compiles via IR with solc >=0.8.10 + uniswap-v4-2024-06-06 # compiles via IR with solc >=0.8.24 + eigenlayer-0.3.0 # compiles via IR with solc >=0.8.18 + seaport-1.6 # StackTooDeep via IR + farcaster-3.1.0 # StackTooDeep via IR + sablier-v2-1.1.2 # StackTooDeep via IR ) mkdir -p "$BENCHMARK_DIR" cd "$BENCHMARK_DIR" -echo "| File | Pipeline | Time | Memory (peak) | Exit code |" -echo "|----------------------|----------|---------:|--------------:|----------:|" +echo "| File | Pipeline | Time | Memory (peak) | Exit code |" +echo "|-----------------------|----------|---------:|--------------:|----------:|" for project in "${benchmarks[@]}"; do benchmark_project legacy "$project" From 249c3357f2b51de7d4468858dd575985ad510962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 1 Nov 2024 04:41:29 +0100 Subject: [PATCH 0463/1340] Switch to a more recent Sablier version that does compile in external benchmarks --- test/benchmarks/external-setup.sh | 12 +++++------- test/benchmarks/external.sh | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/test/benchmarks/external-setup.sh b/test/benchmarks/external-setup.sh index bbba60bad..9b82c5767 100755 --- a/test/benchmarks/external-setup.sh +++ b/test/benchmarks/external-setup.sh @@ -89,17 +89,15 @@ function install_old_uniswap { function install_sablier { # NOTE: To avoid hard-coding dependency versions here we'd have to install them from npm forge install --no-commit \ - foundry-rs/forge-std@v1.5.6 \ - OpenZeppelin/openzeppelin-contracts@v4.9.2 \ - PaulRBerg/prb-math@v4.0.2 \ - PaulRBerg/prb-test@v0.6.4 \ + foundry-rs/forge-std@v1.8.2 \ + OpenZeppelin/openzeppelin-contracts@v5.0.2 \ + PaulRBerg/prb-math@v4.0.3 \ evmcheb/solarray@a547630 \ - Vectorized/solady@v0.0.129 + Vectorized/solady@v0.0.208 cat < remappings.txt @openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ forge-std/=lib/forge-std/ @prb/math/=lib/prb-math/ -@prb/test/=lib/prb-test/ solarray/=lib/solarray/ solady/=lib/solady/ EOF @@ -125,4 +123,4 @@ setup_foundry_project seaport-1.6/ commit tags/1.6 https://github.com/ProjectOpe setup_foundry_project eigenlayer-0.3.0/ tag v0.3.0-holesky-rewards https://github.com/Layr-Labs/eigenlayer-contracts -setup_foundry_project sablier-v2-1.1.2/ tag v1.1.2 https://github.com/sablier-labs/v2-core install_sablier +setup_foundry_project sablier-v2-1.2.0/ tag v1.2.0 https://github.com/sablier-labs/v2-core install_sablier diff --git a/test/benchmarks/external.sh b/test/benchmarks/external.sh index 16e47ee4f..b003f0ba1 100755 --- a/test/benchmarks/external.sh +++ b/test/benchmarks/external.sh @@ -84,9 +84,9 @@ benchmarks=( openzeppelin-4.8.0 # compiles via IR with solc >=0.8.10 uniswap-v4-2024-06-06 # compiles via IR with solc >=0.8.24 eigenlayer-0.3.0 # compiles via IR with solc >=0.8.18 + sablier-v2-1.2.0 # compiles via IR with solc >=0.8.28 (maybe >=0.8.26) seaport-1.6 # StackTooDeep via IR farcaster-3.1.0 # StackTooDeep via IR - sablier-v2-1.1.2 # StackTooDeep via IR ) mkdir -p "$BENCHMARK_DIR" From eb7dc2169b58a59a0d57ea6ca61d2fa0b548c324 Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Fri, 18 Oct 2024 22:20:54 +0100 Subject: [PATCH 0464/1340] refine the doc about calldata --- docs/types/reference-types.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 4a053d51b..23119484d 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -37,6 +37,14 @@ non-persistent area where function arguments are stored, and behaves mostly like data location can also be returned from functions, but it is not possible to allocate such types. +.. note:: + Arrays and structs with ``calldata`` location declared in a function body + or as its return parameters must be assigned before being used or returned. + There are certain cases in which non-trivial control flow is used and the compiler + can't properly detect the initialization. + A common workaround in such cases is to assign the affected variable to itself before + the correct initialization takes place. + .. note:: Prior to version 0.6.9 data location for reference-type arguments was limited to ``calldata`` in external functions, ``memory`` in public functions and either From 40e92c9d7dd526aa12a43e8a350344f81bf9bb9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 30 Oct 2024 20:45:21 +0100 Subject: [PATCH 0465/1340] Fix movableApartFromEffects flag for datacopy() builtin in Yul - Side effects should have been identical to those of `CODECOPY`, but movableApartFromEffects was different. --- libyul/backends/evm/EVMDialect.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 9de3e40fc..d7167fc77 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -307,17 +307,7 @@ std::vector> createBuiltins(langutil::EVMVe "datacopy", 3, 0, - SideEffects{ - false, // movable - true, // movableApartFromEffects - false, // canBeRemoved - false, // canBeRemovedIfNotMSize - true, // cannotLoop - SideEffects::None, // otherState - SideEffects::None, // storage - SideEffects::Write, // memory - SideEffects::None // transientStorage - }, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::CODECOPY), ControlFlowSideEffects::fromInstruction(evmasm::Instruction::CODECOPY), {}, []( From d9a231cb109a49043b0eca40ba01aa4a5735fa1d Mon Sep 17 00:00:00 2001 From: Hopium <135053852+Hopium21@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:54:53 +0100 Subject: [PATCH 0466/1340] Fix minor text errors in READMEs and checklists (#15577) * Update README.md * Update ReviewChecklist.md * Update README.md --- .circleci/README.md | 2 +- README.md | 2 +- ReviewChecklist.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/README.md b/.circleci/README.md index 22b20bc8c..cd1a88ab7 100644 --- a/.circleci/README.md +++ b/.circleci/README.md @@ -2,7 +2,7 @@ ### Docker images -The docker images are build locally on the developer machine: +The docker images are built locally on the developer machine: ```sh cd .circleci/docker/ diff --git a/README.md b/README.md index 197259998..2d8e02322 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ You can talk to us on Gitter and Matrix, tweet at us on X (previously Twitter) or create a new topic in the Solidity forum. Questions, feedback, and suggestions are welcome! -Solidity is a statically typed, contract-oriented, high-level language for implementing smart contracts on the Ethereum platform. +Solidity is a statically-typed, contract-oriented, high-level language for implementing smart contracts on the Ethereum platform. For a good overview and starting point, please check out the official [Solidity Language Portal](https://soliditylang.org). diff --git a/ReviewChecklist.md b/ReviewChecklist.md index 3f0af6f98..35563d890 100644 --- a/ReviewChecklist.md +++ b/ReviewChecklist.md @@ -123,7 +123,7 @@ The following points are all covered by the coding style but come up so often th - If it is a bugfix: - [ ] **The PR must include tests that reproduce the bug.** - [ ] **Are there gaps in test coverage of the buggy feature?** Fill them by adding more tests. - - [ ] **Try to break it.** Can you of any similar features that could also be buggy? + - [ ] **Try to break it.** Can you think of any similar features that could also be buggy? Play with the repro and include prominent variants as separate test cases, even if they don't trigger a bug. - [ ] **Positive cases (code that compiles) should have a semantic test.** - [ ] **Negative cases (code with compilation errors) should have a syntax test.** From 8548a93197e83773847ad5d1c67853ef4667b3ef Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 14 Nov 2024 16:56:00 +0100 Subject: [PATCH 0467/1340] Yul: Avoid expensive check in frequently called function The equality comparison is called very often in CommonSubexpressionEliminator, presumably because it is the comparison operator used for the map `CommonSubexpressionEliminator::m_replacementCandidates`. The method `validLiteral` is nontrivial and should not be called (twice!) on every call to the equality comparison. --- libyul/optimiser/SyntacticalEquality.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libyul/optimiser/SyntacticalEquality.cpp b/libyul/optimiser/SyntacticalEquality.cpp index 0f4aa6e33..73b4d5083 100644 --- a/libyul/optimiser/SyntacticalEquality.cpp +++ b/libyul/optimiser/SyntacticalEquality.cpp @@ -64,9 +64,8 @@ bool SyntacticallyEqual::expressionEqual(Identifier const& _lhs, Identifier cons } bool SyntacticallyEqual::expressionEqual(Literal const& _lhs, Literal const& _rhs) { - yulAssert(validLiteral(_lhs), "Invalid lhs literal during syntactical equality check"); - yulAssert(validLiteral(_rhs), "Invalid rhs literal during syntactical equality check"); - + assert(validLiteral(_lhs)); + assert(validLiteral(_rhs)); return _lhs.value == _rhs.value; } From 515001595266add692de272d433c0021767acd56 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 14 Nov 2024 18:19:03 +0100 Subject: [PATCH 0468/1340] Yul: Avoid expensive check against std::regex when possible --- libyul/AsmParser.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index f7741dfae..26a4d386d 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -147,12 +147,17 @@ void Parser::fetchDebugDataFromComment() { solAssert(m_sourceNames.has_value(), ""); + std::string_view commentLiteral = m_scanner->currentCommentLiteral(); + if (commentLiteral.empty()) + { + m_astIDFromComment = std::nullopt; + return; + } static std::regex const tagRegex = std::regex( R"~~((?:^|\s+)(@[a-zA-Z0-9\-_]+)(?:\s+|$))~~", // tag, e.g: @src std::regex_constants::ECMAScript | std::regex_constants::optimize ); - std::string_view commentLiteral = m_scanner->currentCommentLiteral(); std::match_results match; langutil::SourceLocation originLocation = m_locationFromComment; From d282afcddf4deab86ef212046c4eab237429d463 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 21 Nov 2024 08:30:30 +0100 Subject: [PATCH 0469/1340] Update package list before installing Python 2 --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0bd7932ce..a39fad80b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1458,6 +1458,7 @@ jobs: - run: name: Install Python 2 and make it the default command: | + sudo apt update # python is used by node-gyp to build native modules (needed for Colony). # In the 14.x image node-gyp still requires Python 2. sudo apt install python2 --assume-yes --no-install-recommends From 48d40d5eaf97c835cf55896a7a161eedc57c57f9 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Sun, 17 Nov 2024 04:24:06 +0100 Subject: [PATCH 0470/1340] AST: More efficient way to collect referenced source units Previous implementation of the method SourceUnit::referencedSourceUnits contained a subtle performance bug. Because the skip list was passed by value into the recursive call, the dependency graph of the imports were effectively traversed as if expanded into a full tree, instead of as a DAG (directed acyclic graph). An example to illustrate that previously the same source was visited more than once: Suppose `A.sol` imports `B.sol` and `C.sol` and both of these import `D.sol`. Previosuly, the method would process `A` by first recursing into `B` and then `C`. When processing `B`, the source `D` is processed and then added to the skip list. When the recursion returns from processing `B`, any changes made to the skip list there were discarded, so that during processing `C`, the source `D` is not find in the skip list and processed again. Now, in most cases the import/dependency graph is probably shallow or does not contain such diamond-like subgraphs, and the performance is not affected. However, for a deeper dependency graph with multiple layers of diamond-like subgraphs this quickly leads to very bad performance, because every source unit is visited a number of times equal to the number of paths by which the source unit is reachable from the root source unit. This change seems to shave off *tens* of seconds on **both** legacy and ir pipeline for `sablier-v2-1.2.0` project. --- libsolidity/ast/AST.cpp | 15 ++++++++++----- libsolidity/ast/AST.h | 6 ++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index a3aab07fb..b62ea3e2d 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -130,18 +130,23 @@ SourceUnitAnnotation& SourceUnit::annotation() const std::set SourceUnit::referencedSourceUnits(bool _recurse, std::set _skipList) const { std::set sourceUnits; + referencedSourceUnits(sourceUnits, _recurse, _skipList); + return sourceUnits; +} + +void SourceUnit::referencedSourceUnits(std::set& _referencedSourceUnits, bool _recurse, std::set& _skipList) const +{ for (ImportDirective const* importDirective: filteredNodes(nodes())) { auto const& sourceUnit = importDirective->annotation().sourceUnit; - if (!_skipList.count(sourceUnit)) + auto [skipListIt, notOnSkipListYet] = _skipList.insert(sourceUnit); + if (notOnSkipListYet) { - _skipList.insert(sourceUnit); - sourceUnits.insert(sourceUnit); + _referencedSourceUnits.insert(sourceUnit); if (_recurse) - sourceUnits += sourceUnit->referencedSourceUnits(true, _skipList); + sourceUnit->referencedSourceUnits(_referencedSourceUnits, true, _skipList); } } - return sourceUnits; } ImportAnnotation& ImportDirective::annotation() const diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 727652f56..0e2df8a90 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -193,6 +193,12 @@ class SourceUnit: public ASTNode, public ScopeOpener bool experimentalSolidity() const { return m_experimentalSolidity; } private: + void referencedSourceUnits( + std::set& _referencedSourceUnits, + bool _recurse, + std::set& _skipList + ) const; + std::optional m_licenseString; std::vector> m_nodes; bool m_experimentalSolidity = false; From 1d595b28df80d335afacbabe29e6036a887c1d08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 20 Nov 2024 17:15:02 +0100 Subject: [PATCH 0471/1340] OptimiserSettings: fix mismatched docstrings on several settings --- libsolidity/interface/OptimiserSettings.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/interface/OptimiserSettings.h b/libsolidity/interface/OptimiserSettings.h index 1ca46ccbc..1f702851c 100644 --- a/libsolidity/interface/OptimiserSettings.h +++ b/libsolidity/interface/OptimiserSettings.h @@ -149,11 +149,11 @@ struct OptimiserSettings /// Constant optimizer, which tries to find better representations that satisfy the given /// size/cost-trade-off. bool runConstantOptimiser = false; - /// Perform more efficient stack allocation for variables during code generation from Yul to bytecode. + /// Allow unchecked arithmetic when incrementing the counter of certain kinds of 'for' loop bool simpleCounterForLoopUncheckedIncrement = false; - /// Yul optimiser with default settings. Will only run on certain parts of the code for now. + /// Perform more efficient stack allocation for variables during code generation from Yul to bytecode. bool optimizeStackAllocation = false; - /// Allow unchecked arithmetic when incrementing the counter of certain kinds of 'for' loop + /// Yul optimiser with default settings. Will only run on certain parts of the code for now. bool runYulOptimiser = false; /// Sequence of optimisation steps to be performed by Yul optimiser. /// Note that there are some hard-coded steps in the optimiser and you cannot disable From 8a8b543dfdc247ed37ad688a557d649455e49f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 20 Nov 2024 18:33:43 +0100 Subject: [PATCH 0472/1340] More precise description of optimizer settings and their defaults in the docs --- docs/using-the-compiler.rst | 84 +++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index b2fe490cc..48151a637 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -281,63 +281,67 @@ Input Description "remappings": [ ":g=/dir" ], // Optional: Optimizer settings "optimizer": { - // Disabled by default. - // NOTE: enabled=false still leaves some optimizations on. See comments below. - // WARNING: Before version 0.8.6 omitting the 'enabled' key was not equivalent to setting - // it to false and would actually disable all the optimizations. + // Turn on the optimizer. Optional. Default: false. + // NOTE: The state of the optimizer is fully determined by the 'details' dict and this setting + // only affects its defaults - when enabled, all components default to being enabled. + // The opposite is not true - there are several components that always default to being + // enabled an can only be explicitly disabled via 'details'. + // WARNING: Before version 0.8.6 omitting this setting was not equivalent to setting + // it to false and would result in all components being disabled instead. "enabled": true, - // Optimize for how many times you intend to run the code. + // Optimize for how many times you intend to run the code. Optional. Default: 200. // Lower values will optimize more for initial deployment cost, higher // values will optimize more for high-frequency usage. "runs": 200, - // Switch optimizer components on or off in detail. - // The "enabled" switch above provides two defaults which can be - // tweaked here. If "details" is given, "enabled" can be omitted. + // State of all optimizer components. Optional. + // Default values are determined by whether the optimizer is enabled or not. + // Note that the 'enabled' setting only affects the defaults here and has no effect when + // all values are provided explicitly. "details": { - // The peephole optimizer is always on if no details are given, - // use details to switch it off. + // Peephole optimizer (opcode-based). Optional. Default: true. + // NOTE: Always runs (even with optimization disabled) unless explicitly turned off here. "peephole": true, - // The inliner is always off if no details are given, - // use details to switch it on. + // Inliner (opcode-based). Optional. Default: true when optimization is enabled. "inliner": false, - // The unused jumpdest remover is always on if no details are given, - // use details to switch it off. + // Unused JUMPDEST remover (opcode-based). Optional. Default: true. + // NOTE: Always runs (even with optimization disabled) unless explicitly turned off here. "jumpdestRemover": true, - // Sometimes re-orders literals in commutative operations. + // Literal reordering (codegen-based). Optional. Default: true when optimization is enabled. + // Moves literals to the right of commutative binary operators during code generation, helping exploit associativity. "orderLiterals": false, - // Removes duplicate code blocks + // Block deduplicator (opcode-based). Optional. Default: true when optimization is enabled. + // Unifies assembly code blocks that share content. "deduplicate": false, - // Common subexpression elimination, this is the most complicated step but - // can also provide the largest gain. + // Common subexpression elimination (opcode-based). Optional. Default: true when optimization is enabled. + // This is the most complicated step but can also provide the largest gain. "cse": false, - // Optimize representation of literal numbers and strings in code. + // Constant optimizer (opcode-based). Optional. Default: true when optimization is enabled. + // Tries to find better representations of literal numbers and strings, that satisfy the + // size/cost trade-off determined by the 'runs' setting. "constantOptimizer": false, - // Use unchecked arithmetic when incrementing the counter of for loops - // under certain circumstances. It is always on if no details are given. + // Unchecked loop increment (codegen-based). Optional. Default: true. + // Use unchecked arithmetic when incrementing the counter of 'for' loops under certain circumstances. + // NOTE: Always runs (even with optimization disabled) unless explicitly turned off here. "simpleCounterForLoopUncheckedIncrement": true, - // The new Yul optimizer. Mostly operates on the code of ABI coder v2 - // and inline assembly. - // It is activated together with the global optimizer setting - // and can be deactivated here. - // Before Solidity 0.6.0 it had to be activated through this switch. + // Yul optimizer. Optional. Default: true when optimization is enabled. + // Used to optimize the IR produced by the Yul IR-based pipeline as well as inline assembly + // and utility Yul code generated by the compiler. + // NOTE: Before Solidity 0.6.0 the default was false. "yul": false, - // Tuning options for the Yul optimizer. + // Tuning options for the Yul optimizer. Optional. "yulDetails": { // Improve allocation of stack slots for variables, can free up stack slots early. - // Activated by default if the Yul optimizer is activated. + // Optional. Default: true if Yul optimizer is enabled. "stackAllocation": true, - // Select optimization steps to be applied. It is also possible to modify both the - // optimization sequence and the clean-up sequence. Instructions for each sequence - // are separated with the ":" delimiter and the values are provided in the form of - // optimization-sequence:clean-up-sequence. For more information see - // "The Optimizer > Selecting Optimizations". - // This field is optional, and if not provided, the default sequences for both - // optimization and clean-up are used. If only one of the sequences is provided - // the other will not be run. - // If only the delimiter ":" is provided then neither the optimization nor the clean-up - // sequence will be run. - // If set to an empty value, only the default clean-up sequence is used and - // no optimization steps are applied. + // Optimization step sequence. + // The general form of the value is "
:". + // The setting is optional and when omitted, default values are used for both sequences. + // If the value does not contain the ':' delimiter, it is interpreted as the main + // sequence and the default is used for the cleanup sequence. + // To make one of the sequences empty, the delimiter must be present at the first or last position. + // In particular if the whole value consists only of the delimiter, both sequences are empty. + // Note that there are several hard-coded steps that always run, even when both sequences are empty. + // For more information see "The Optimizer > Selecting Optimizations". "optimizerSteps": "dhfoDgvulfnTUtnIf..." } } From 379b7248b8c057eb6ca63ef6ed2fddd3543fdf4a Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 22 Nov 2024 13:26:01 +0100 Subject: [PATCH 0473/1340] eof: Implement relative jumps support --- libevmasm/Assembly.cpp | 25 +++- libevmasm/Assembly.h | 1 + libevmasm/AssemblyItem.cpp | 29 +++- libevmasm/AssemblyItem.h | 27 +++- libevmasm/BlockDeduplicator.cpp | 4 +- libevmasm/GasMeter.cpp | 2 + libevmasm/GasMeter.h | 1 + libevmasm/Instruction.cpp | 4 + libevmasm/Instruction.h | 5 + libevmasm/JumpdestRemover.cpp | 2 +- libevmasm/PeepholeOptimiser.cpp | 126 +++++++++++++++++- libevmasm/SemanticInformation.cpp | 12 +- liblangutil/EVMVersion.cpp | 2 + libyul/backends/evm/EthAssemblyAdapter.cpp | 25 +++- test/libyul/objectCompiler/eof/rjumps.yul | 40 ++++++ .../EVMInstructionInterpreter.cpp | 2 + 16 files changed, 289 insertions(+), 18 deletions(-) create mode 100644 test/libyul/objectCompiler/eof/rjumps.yul diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 153ab547e..fdc272415 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1396,6 +1396,7 @@ LinkerObject const& Assembly::assembleEOF() const m_tagPositionsInBytecode = std::vector(m_usedTags, std::numeric_limits::max()); std::map dataSectionRef; + std::map tagRef; for (auto&& [codeSectionIndex, codeSection]: m_codeSections | ranges::views::enumerate) { @@ -1412,7 +1413,9 @@ LinkerObject const& Assembly::assembleEOF() const solAssert( item.instruction() != Instruction::DATALOADN && item.instruction() != Instruction::RETURNCONTRACT && - item.instruction() != Instruction::EOFCREATE + item.instruction() != Instruction::EOFCREATE && + item.instruction() != Instruction::RJUMP && + item.instruction() != Instruction::RJUMPI ); solAssert(!(item.instruction() >= Instruction::PUSH0 && item.instruction() <= Instruction::PUSH32)); ret.bytecode += assembleOperation(item); @@ -1427,6 +1430,14 @@ LinkerObject const& Assembly::assembleEOF() const ret.linkReferences.insert(linkRef); break; } + case RelativeJump: + case ConditionalRelativeJump: + { + ret.bytecode.push_back(static_cast(item.instruction())); + tagRef[ret.bytecode.size()] = item.relativeJumpTagID(); + appendBigEndianUint16(ret.bytecode, 0u); + break; + } case EOFCreate: { ret.bytecode.push_back(static_cast(Instruction::EOFCREATE)); @@ -1465,6 +1476,18 @@ LinkerObject const& Assembly::assembleEOF() const setBigEndianUint16(ret.bytecode, codeSectionSizePositions[codeSectionIndex], ret.bytecode.size() - sectionStart); } + for (auto const& [refPos, tagId]: tagRef) + { + solAssert(tagId < m_tagPositionsInBytecode.size(), "Reference to non-existing tag."); + size_t tagPos = m_tagPositionsInBytecode[tagId]; + solAssert(tagPos != std::numeric_limits::max(), "Reference to tag without position."); + + ptrdiff_t const relativeJumpOffset = static_cast(tagPos) - (static_cast(refPos) + 2); + solRequire(-0x8000 <= relativeJumpOffset && relativeJumpOffset <= 0x7FFF, AssemblyException, "Relative jump too far"); + solAssert(relativeJumpOffset < -2 || 0 <= relativeJumpOffset, "Relative jump offset into immediate argument."); + setBigEndianUint16(ret.bytecode, refPos, static_cast(static_cast(relativeJumpOffset))); + } + for (auto i: referencedSubIds) ret.bytecode += m_subs[i]->assemble().bytecode; diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index daeea6e8c..4b52ca3d7 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -65,6 +65,7 @@ class Assembly } std::optional eofVersion() const { return m_eofVersion; } + bool supportsRelativeJumps() const { return m_eofVersion.has_value(); } AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); } AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); } /// Returns a tag identified by the given name. Creates it if it does not yet exist. diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index d26e01f8a..96c007ea5 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -62,13 +62,21 @@ AssemblyItem AssemblyItem::toSubAssemblyTag(size_t _subId) const std::pair AssemblyItem::splitForeignPushTag() const { - assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); + solAssert(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump); u256 combined = u256(data()); size_t subId = static_cast((combined >> 64) - 1); size_t tag = static_cast(combined & 0xffffffffffffffffULL); return std::make_pair(subId, tag); } +size_t AssemblyItem::relativeJumpTagID() const +{ + solAssert(m_type == RelativeJump || m_type == ConditionalRelativeJump); + auto const [subId, tagId] = splitForeignPushTag(); + solAssert(subId == std::numeric_limits::max(), "Relative jump to sub"); + return tagId; +} + std::pair AssemblyItem::nameAndData(langutil::EVMVersion _evmVersion) const { switch (type()) @@ -76,6 +84,8 @@ std::pair AssemblyItem::nameAndData(langutil::EVMVersi case Operation: case EOFCreate: case ReturnContract: + case RelativeJump: + case ConditionalRelativeJump: return {instructionInfo(instruction(), _evmVersion).name, m_data != nullptr ? toStringInHex(*m_data) : ""}; case Push: return {"PUSH", toStringInHex(data())}; @@ -115,7 +125,8 @@ std::pair AssemblyItem::nameAndData(langutil::EVMVersi void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag) { - assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); + solAssert(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump); + solAssert(!(m_type == RelativeJump || m_type == ConditionalRelativeJump) || _subId == std::numeric_limits::max()); u256 data = _tag; if (_subId != std::numeric_limits::max()) data |= (u256(_subId) + 1) << 64; @@ -167,6 +178,8 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, langutil::EVMVersion _ } case VerbatimBytecode: return std::get<2>(*m_verbatimBytecode).size(); + case RelativeJump: + case ConditionalRelativeJump: case AuxDataLoadN: return 1 + 2; case EOFCreate: @@ -201,6 +214,8 @@ size_t AssemblyItem::returnValues() const case Operation: case EOFCreate: case ReturnContract: + case RelativeJump: + case ConditionalRelativeJump: // The latest EVMVersion is used here, since the InstructionInfo is assumed to be // the same across all EVM versions except for the instruction name. return static_cast(instructionInfo(instruction(), EVMVersion()).ret); @@ -236,6 +251,8 @@ bool AssemblyItem::canBeFunctional() const case Operation: case EOFCreate: case ReturnContract: + case RelativeJump: + case ConditionalRelativeJump: return !isDupInstruction(instruction()) && !isSwapInstruction(instruction()); case Push: case PushTag: @@ -360,6 +377,12 @@ std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const case ReturnContract: text = "returcontract{" + std::to_string(static_cast(data())) + "}"; break; + case RelativeJump: + text = "rjump{" + std::string("tag_") + std::to_string(relativeJumpTagID()) + "}"; + break; + case ConditionalRelativeJump: + text = "rjumpi{" + std::string("tag_") + std::to_string(relativeJumpTagID()) + "}"; + break; } if (m_jumpType == JumpType::IntoFunction || m_jumpType == JumpType::OutOfFunction) { @@ -380,6 +403,8 @@ std::ostream& solidity::evmasm::operator<<(std::ostream& _out, AssemblyItem cons case Operation: case EOFCreate: case ReturnContract: + case RelativeJump: + case ConditionalRelativeJump: _out << " " << instructionInfo(_item.instruction(), EVMVersion()).name; if (_item.instruction() == Instruction::JUMP || _item.instruction() == Instruction::JUMPI) _out << "\t" << _item.getJumpTypeAsString(); diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index e51d07b16..a9c46bb14 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -57,6 +57,8 @@ enum AssemblyItemType AuxDataLoadN, EOFCreate, ///< Creates new contract using subcontainer as initcode ReturnContract, ///< Returns new container (with auxiliary data filled in) to be deployed + RelativeJump, ///< Jumps to relative position accordingly to its argument + ConditionalRelativeJump, ///< Same as RelativeJump but takes condition from the stack VerbatimBytecode ///< Contains data that is inserted into the bytecode code section without modification. }; @@ -111,20 +113,32 @@ class AssemblyItem { return AssemblyItem(ReturnContract, Instruction::RETURNCONTRACT, _containerID, std::move(_debugData)); } + static AssemblyItem relativeJumpTo(AssemblyItem _tag, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + solAssert(_tag.type() == Tag); + return AssemblyItem(RelativeJump, Instruction::RJUMP, _tag.data(), _debugData); + } + static AssemblyItem conditionalRelativeJumpTo(AssemblyItem _tag, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + solAssert(_tag.type() == Tag); + return AssemblyItem(ConditionalRelativeJump, Instruction::RJUMPI, _tag.data(), _debugData); + } AssemblyItem(AssemblyItem const&) = default; AssemblyItem(AssemblyItem&&) = default; AssemblyItem& operator=(AssemblyItem const&) = default; AssemblyItem& operator=(AssemblyItem&&) = default; - AssemblyItem tag() const { assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); return AssemblyItem(Tag, data()); } - AssemblyItem pushTag() const { assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); return AssemblyItem(PushTag, data()); } + AssemblyItem tag() const { solAssert(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump); return AssemblyItem(Tag, data()); } + AssemblyItem pushTag() const { solAssert(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump); return AssemblyItem(PushTag, data()); } /// Converts the tag to a subassembly tag. This has to be called in order to move a tag across assemblies. /// @param _subId the identifier of the subassembly the tag is taken from. AssemblyItem toSubAssemblyTag(size_t _subId) const; /// @returns splits the data of the push tag into sub assembly id and actual tag id. /// The sub assembly id of non-foreign push tags is -1. std::pair splitForeignPushTag() const; + /// @returns relative jump target tag ID. Asserts that it is not foreign tag. + size_t relativeJumpTagID() const; /// Sets sub-assembly part and tag for a push tag. void setPushTagSubIdAndTag(size_t _subId, size_t _tag); @@ -145,9 +159,14 @@ class AssemblyItem /// @returns true if the item has m_instruction properly set. bool hasInstruction() const { - return m_type == Operation || m_type == EOFCreate || m_type == ReturnContract; + return + m_type == Operation || + m_type == EOFCreate || + m_type == ReturnContract || + m_type == RelativeJump || + m_type == ConditionalRelativeJump; } - /// @returns the instruction of this item (only valid if type() == Operation || EOFCreate || ReturnContract) + /// @returns the instruction of this item (only valid if hasInstruction returns true) Instruction instruction() const { solAssert(hasInstruction()); diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp index c978bae2b..3ba8cfcd3 100644 --- a/libevmasm/BlockDeduplicator.cpp +++ b/libevmasm/BlockDeduplicator.cpp @@ -106,7 +106,7 @@ bool BlockDeduplicator::applyTagReplacement( { bool changed = false; for (AssemblyItem& item: _items) - if (item.type() == PushTag) + if (item.type() == PushTag || item.type() == RelativeJump || item.type() == ConditionalRelativeJump) { size_t subId; size_t tagId; @@ -131,7 +131,7 @@ BlockDeduplicator::BlockIterator& BlockDeduplicator::BlockIterator::operator++() { if (it == end) return *this; - if (SemanticInformation::altersControlFlow(*it) && *it != AssemblyItem{Instruction::JUMPI}) + if (SemanticInformation::altersControlFlow(*it) && *it != AssemblyItem{Instruction::JUMPI} && it->type() != ConditionalRelativeJump) it = end; else { diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index a501b487f..3ee3a39cb 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -272,6 +272,8 @@ unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVer { case Tier::Zero: return GasCosts::tier0Gas; case Tier::Base: return GasCosts::tier1Gas; + case Tier::RJump: return GasCosts::tier1Gas; + case Tier::RJumpI: return GasCosts::rjumpiGas; case Tier::VeryLow: return GasCosts::tier2Gas; case Tier::Low: return GasCosts::tier3Gas; case Tier::Mid: return GasCosts::tier4Gas; diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index 50a783e1a..f202b358e 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -177,6 +177,7 @@ namespace GasCosts return _evmVersion >= langutil::EVMVersion::istanbul() ? 16 : 68; } static unsigned const copyGas = 3; + static unsigned const rjumpiGas = 4; } /** diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 5122fb01f..60ec75f92 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -169,6 +169,8 @@ std::map const solidity::evmasm::c_instructions = { "LOG3", Instruction::LOG3 }, { "LOG4", Instruction::LOG4 }, { "DATALOADN", Instruction::DATALOADN }, + { "RJUMP", Instruction::RJUMP }, + { "RJUMPI", Instruction::RJUMPI }, { "EOFCREATE", Instruction::EOFCREATE }, { "RETURNCONTRACT", Instruction::RETURNCONTRACT }, { "CREATE", Instruction::CREATE }, @@ -256,6 +258,8 @@ static std::map const c_instructionInfo = {Instruction::GAS, {"GAS", 0, 0, 1, false, Tier::Base}}, {Instruction::JUMPDEST, {"JUMPDEST", 0, 0, 0, true, Tier::Special}}, {Instruction::DATALOADN, {"DATALOADN", 2, 0, 1, true, Tier::Low}}, + {Instruction::RJUMP, {"RJUMP", 2, 0, 0, true, Tier::RJump}}, + {Instruction::RJUMPI, {"RJUMPI", 2, 1, 0, true, Tier::RJumpI}}, {Instruction::PUSH0, {"PUSH0", 0, 0, 1, false, Tier::Base}}, {Instruction::PUSH1, {"PUSH1", 1, 0, 1, false, Tier::VeryLow}}, {Instruction::PUSH2, {"PUSH2", 2, 0, 1, false, Tier::VeryLow}}, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index d9e96c49a..76998c538 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -183,6 +183,9 @@ enum class Instruction: uint8_t LOG4, ///< Makes a log entry; 4 topics. DATALOADN = 0xd1, ///< load data from EOF data section + + RJUMP = 0xe0, ///< relative jump + RJUMPI = 0xe1, ///< conditional relative jump EOFCREATE = 0xec, ///< create a new account with associated container code. RETURNCONTRACT = 0xee, ///< return container to be deployed with axiliary data filled in. CREATE = 0xf0, ///< create a new account with associated code @@ -298,7 +301,9 @@ enum class Tier // NOTE: Tiers should be ordered by cost, since we sometimes perform comparisons between them. Zero = 0, // 0, Zero Base, // 2, Quick + RJump, // 2, RJump VeryLow, // 3, Fastest + RJumpI, // 4, Low, // 5, Fast Mid, // 8, Mid High, // 10, Slow diff --git a/libevmasm/JumpdestRemover.cpp b/libevmasm/JumpdestRemover.cpp index 7afa715a8..7ded5ae90 100644 --- a/libevmasm/JumpdestRemover.cpp +++ b/libevmasm/JumpdestRemover.cpp @@ -58,7 +58,7 @@ std::set JumpdestRemover::referencedTags(AssemblyItems const& _items, si { std::set ret; for (auto const& item: _items) - if (item.type() == PushTag) + if (item.type() == PushTag || item.type() == RelativeJump || item.type() == ConditionalRelativeJump) { auto subAndTag = item.splitForeignPushTag(); if (subAndTag.first == _subId) diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 40937e73f..64650eaee 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -328,6 +328,29 @@ struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod } }; +struct IsZeroIsZeroRJumpI: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _iszero1, + AssemblyItem const& _iszero2, + AssemblyItem const& _rjumpi, + std::back_insert_iterator _out + ) + { + if ( + _iszero1 == Instruction::ISZERO && + _iszero2 == Instruction::ISZERO && + _rjumpi.type() == ConditionalRelativeJump + ) + { + *_out = _rjumpi; + return true; + } + else + return false; + } +}; + struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod { static size_t applySimple( @@ -355,6 +378,30 @@ struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod } }; +struct EqIsZeroRJumpI: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _eq, + AssemblyItem const& _iszero, + AssemblyItem const& _rjumpi, + std::back_insert_iterator _out + ) + { + if ( + _eq == Instruction::EQ && + _iszero == Instruction::ISZERO && + _rjumpi.type() == ConditionalRelativeJump + ) + { + *_out = AssemblyItem(Instruction::SUB, _eq.debugData()); + *_out = _rjumpi; + return true; + } + else + return false; + } +}; + // push_tag_1 jumpi push_tag_2 jump tag_1: -> iszero push_tag_2 jumpi tag_1: struct DoubleJump: SimplePeepholeOptimizerMethod { @@ -387,6 +434,33 @@ struct DoubleJump: SimplePeepholeOptimizerMethod } }; +// rjumpi(tag_1) rjump(tag_2) tag_1: -> iszero rjumpi(tag_2) tag_1: +struct DoubleRJump: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _rjumpi, + AssemblyItem const& _rjump, + AssemblyItem const& _tag1, + std::back_insert_iterator _out + ) + { + if ( + _rjumpi.type() == ConditionalRelativeJump && + _rjump.type() == RelativeJump && + _tag1.type() == Tag && + _rjumpi.data() == _tag1.data() + ) + { + *_out = AssemblyItem(Instruction::ISZERO, _rjumpi.debugData()); + *_out = AssemblyItem::conditionalRelativeJumpTo(_rjump.tag(), _rjump.debugData()); + *_out = _tag1; + return true; + } + else + return false; + } +}; + struct JumpToNext: SimplePeepholeOptimizerMethod { static size_t applySimple( @@ -413,6 +487,30 @@ struct JumpToNext: SimplePeepholeOptimizerMethod } }; +struct RJumpToNext: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _rjump, + AssemblyItem const& _tag, + std::back_insert_iterator _out + ) + { + if ( + (_rjump.type() == ConditionalRelativeJump || _rjump.type() == RelativeJump) && + _tag.type() == Tag && + _rjump.data() == _tag.data() + ) + { + if (_rjump.type() == ConditionalRelativeJump) + *_out = AssemblyItem(Instruction::POP, _rjump.debugData()); + *_out = _tag; + return true; + } + else + return false; + } +}; + struct TagConjunctions: SimplePeepholeOptimizerMethod { static bool applySimple( @@ -476,6 +574,7 @@ struct UnreachableCode return false; if ( it[0] != Instruction::JUMP && + it[0] != Instruction::RJUMP && it[0] != Instruction::RETURN && it[0] != Instruction::STOP && it[0] != Instruction::INVALID && @@ -618,9 +717,30 @@ bool PeepholeOptimiser::optimise() while (state.i < m_items.size()) applyMethods( state, - PushPop(), OpPop(), OpStop(), OpReturnRevert(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(), - DupSwap(), IsZeroIsZeroJumpI(), EqIsZeroJumpI(), DoubleJump(), JumpToNext(), UnreachableCode(), DeduplicateNextTagSize3(), - DeduplicateNextTagSize2(), DeduplicateNextTagSize1(), TagConjunctions(), TruthyAnd(), Identity() + PushPop(), + OpPop(), + OpStop(), + OpReturnRevert(), + DoublePush(), + DoubleSwap(), + CommutativeSwap(), + SwapComparison(), + DupSwap(), + IsZeroIsZeroJumpI(), + IsZeroIsZeroRJumpI(), // EOF specific + EqIsZeroJumpI(), + EqIsZeroRJumpI(), // EOF specific + DoubleJump(), + DoubleRJump(), // EOF specific + JumpToNext(), + RJumpToNext(), // EOF specific + UnreachableCode(), + DeduplicateNextTagSize3(), + DeduplicateNextTagSize2(), + DeduplicateNextTagSize1(), + TagConjunctions(), + TruthyAnd(), + Identity() ); if (m_optimisedItems.size() < m_items.size() || ( m_optimisedItems.size() == m_items.size() && ( diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index e909a7074..99a5a0f43 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -303,7 +303,13 @@ bool SemanticInformation::isSwapInstruction(AssemblyItem const& _item) bool SemanticInformation::isJumpInstruction(AssemblyItem const& _item) { - return _item == Instruction::JUMP || _item == Instruction::JUMPI; + return + _item == Instruction::JUMP || + _item == Instruction::JUMPI || + _item == Instruction::RJUMP || + _item == Instruction::RJUMPI || + _item.type() == RelativeJump || + _item.type() == ConditionalRelativeJump; } bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) @@ -317,6 +323,8 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) // continue on the next instruction case Instruction::JUMP: case Instruction::JUMPI: + case Instruction::RJUMP: + case Instruction::RJUMPI: case Instruction::RETURN: case Instruction::SELFDESTRUCT: case Instruction::STOP: @@ -613,6 +621,8 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction) bool SemanticInformation::invalidInViewFunctions(Instruction _instruction) { + // Relative jumps cannot jump out of the current code section of EOF so they are valid in view functions + // (under the assumption that every Solidity function actually gets its own code section). switch (_instruction) { case Instruction::SSTORE: diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index 9041ae793..f469f337d 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -80,6 +80,8 @@ bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersi case Instruction::EOFCREATE: case Instruction::RETURNCONTRACT: case Instruction::DATALOADN: + case Instruction::RJUMP: + case Instruction::RJUMPI: return _eofVersion.has_value(); default: return true; diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index 604177c4f..d8810b261 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -106,14 +106,31 @@ void EthAssemblyAdapter::appendJump(int _stackDiffAfter, JumpType _jumpType) void EthAssemblyAdapter::appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType) { - appendLabelReference(_labelId); - appendJump(_stackDiffAfter, _jumpType); + if (m_assembly.supportsRelativeJumps()) + { + m_assembly.append(evmasm::AssemblyItem::relativeJumpTo(evmasm::AssemblyItem(evmasm::Tag, _labelId))); + yulAssert(_jumpType == JumpType::Ordinary); + m_assembly.adjustDeposit(_stackDiffAfter); + } + else + { + appendLabelReference(_labelId); + appendJump(_stackDiffAfter, _jumpType); + } } void EthAssemblyAdapter::appendJumpToIf(LabelID _labelId, JumpType _jumpType) { - appendLabelReference(_labelId); - appendJumpInstruction(evmasm::Instruction::JUMPI, _jumpType); + if (m_assembly.supportsRelativeJumps()) + { + m_assembly.append(evmasm::AssemblyItem::conditionalRelativeJumpTo(evmasm::AssemblyItem(evmasm::Tag, _labelId))); + yulAssert(_jumpType == JumpType::Ordinary); + } + else + { + appendLabelReference(_labelId); + appendJumpInstruction(evmasm::Instruction::JUMPI, _jumpType); + } } void EthAssemblyAdapter::appendAssemblySize() diff --git a/test/libyul/objectCompiler/eof/rjumps.yul b/test/libyul/objectCompiler/eof/rjumps.yul new file mode 100644 index 000000000..b13f3c362 --- /dev/null +++ b/test/libyul/objectCompiler/eof/rjumps.yul @@ -0,0 +1,40 @@ +object "a" { + code { + if true { + mstore(0, 1) + } + + return(0, 32) + } +} + +// ==== +// EVMVersion: >=prague +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":49:53 */ +// 0x01 +// /* "source":46:70 */ +// rjumpi{tag_1} +// /* "source":22:112 */ +// tag_2: +// /* "source":93:95 */ +// 0x20 +// /* "source":90:91 */ +// 0x00 +// /* "source":83:96 */ +// return +// /* "source":54:70 */ +// tag_1: +// /* "source":66:67 */ +// 0x01 +// /* "source":63:64 */ +// 0x00 +// /* "source":56:68 */ +// mstore +// /* "source":54:70 */ +// rjump{tag_2} +// Bytecode: ef00010100040200010010040000000080ffff6001e1000460205ff360015f52e0fff5 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP LT DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH1 0x1 RJUMPI 0x4 PUSH1 0x20 PUSH0 RETURN PUSH1 0x1 PUSH0 MSTORE RJUMP 0xFFF5 +// SourceMappings: 49:4:0:-:0;46:24;22:90;93:2;90:1;83:13;54:16;66:1;63;56:12;54:16 diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index 0f1f37451..044fff8ce 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -490,6 +490,8 @@ u256 EVMInstructionInterpreter::eval( case Instruction::DATALOADN: case Instruction::EOFCREATE: case Instruction::RETURNCONTRACT: + case Instruction::RJUMP: + case Instruction::RJUMPI: solUnimplemented("EOF not yet supported by Yul interpreter."); } From 1b3d549df61f0d7fbd9207679e8fc6df0a2e529b Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 22 Nov 2024 13:28:51 +0100 Subject: [PATCH 0474/1340] Fix verbatim control flow size effects. --- docs/yul.rst | 3 ++- libyul/ControlFlowSideEffects.h | 6 ++++++ libyul/backends/evm/EVMDialect.cpp | 2 +- ...ore_before_terminating_verbatim_revert.yul | 20 +++++++++++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 test/libyul/yulOptimizerTests/unusedStoreEliminator/store_before_terminating_verbatim_revert.yul diff --git a/docs/yul.rst b/docs/yul.rst index dd29d9a49..2642c0f5c 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -1094,7 +1094,8 @@ the compiler. Violations of these restrictions can result in undefined behavior. - Control-flow should not jump into or out of verbatim blocks, - but it can jump within the same verbatim block. + but it can jump within the same verbatim block. In particular, + reverting or returning from the block is *not* allowed. - Stack contents apart from the input and output parameters should not be accessed. - The stack height difference should be exactly ``m - n`` diff --git a/libyul/ControlFlowSideEffects.h b/libyul/ControlFlowSideEffects.h index 554019135..8de6b53d4 100644 --- a/libyul/ControlFlowSideEffects.h +++ b/libyul/ControlFlowSideEffects.h @@ -68,6 +68,12 @@ struct ControlFlowSideEffects return controlFlowSideEffects; } + + /// @returns the worst-case control flow side effects. + static ControlFlowSideEffects worst() + { + return ControlFlowSideEffects{true, true, true}; + } }; } diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index d7167fc77..f998b7abb 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -566,7 +566,7 @@ BuiltinFunctionForEVM EVMDialect::createVerbatimFunction(size_t _arguments, size 1 + _arguments, _returnVariables, SideEffects::worst(), - ControlFlowSideEffects{}, + ControlFlowSideEffects::worst(), // Worst control flow side effects because verbatim can do anything. std::vector>{LiteralKind::String} + std::vector>(_arguments), [=]( FunctionCall const& _call, diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/store_before_terminating_verbatim_revert.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/store_before_terminating_verbatim_revert.yul new file mode 100644 index 000000000..cbc76b1de --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/store_before_terminating_verbatim_revert.yul @@ -0,0 +1,20 @@ +{ + let x := 0 + let y := 1 + sstore(x, y) + // opcodes: PUSH1 0x00 DUP1 RETURN + // SSTORE is not redundant due to the RETURN hidden in the verbatim block. It must not be removed. + verbatim_0i_0o(hex"600080F3") + revert(0,0) +} +// ---- +// step: unusedStoreEliminator +// +// { +// { +// let x := 0 +// sstore(x, 1) +// verbatim_0i_0o("`\x00\x80\xf3") +// revert(0, 0) +// } +// } From d74c1c72bda0e0c9b51eb78608f1612aadebb932 Mon Sep 17 00:00:00 2001 From: Cypher Pepe <125112044+cypherpepe@users.noreply.github.com> Date: Mon, 25 Nov 2024 23:01:06 +0300 Subject: [PATCH 0475/1340] Fix box-shadow value in .wy-side-nav-search custom.css The box-shadow property in .wy-side-nav-search was incorrectly specified with four values, omitting the necessary units. --- docs/_static/css/custom.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index 25ab26544..d2c9c86e7 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -229,7 +229,7 @@ small * { .wy-side-nav-search { background-color: transparent !important; color: var(--color-a) !important; - box-shadow: 0 4 4 0 var(--color-a); + box-shadow: 0 4px 4px 0 var(--color-a); border-bottom: 1px solid var(--color-d) !important; } @@ -823,4 +823,4 @@ a.skip-to-content:focus { #content { scroll-margin-top: 6rem; scroll-behavior: smooth; -} \ No newline at end of file +} From 6fc4c033500ce68543d087ee6c4ab1cd1677efaa Mon Sep 17 00:00:00 2001 From: Cypher Pepe <125112044+cypherpepe@users.noreply.github.com> Date: Tue, 26 Nov 2024 00:42:49 +0300 Subject: [PATCH 0476/1340] typo contributing.rst --- docs/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index decd51392..3cdadef95 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -134,7 +134,7 @@ extension ``.so`` on Linux, ``.dll`` on Windows systems and ``.dylib`` on macOS. For running SMT tests, the ``z3`` executable must be present in ``PATH``. A few SMT tests use ``Eldarica`` instead of ``z3``. -These requry its executable (``eld``) to be present in ``PATH`` for the tests to pass. +These require its executable (``eld``) to be present in ``PATH`` for the tests to pass. However, if ``Eldarica`` is not found, these tests will be automatically skipped. If ``z3`` is not present on your system, you should disable the From 0462db28b0f2c15d40eb8849efc16b33697a5bb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 26 Nov 2024 20:30:10 +0100 Subject: [PATCH 0477/1340] CI: Replace base_python_small with Ubuntu to keep python up to date - I could just bump the current image to 3.13 but this would require manual bumping in the future again. --- .circleci/config.yml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a39fad80b..994a20032 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -503,15 +503,6 @@ defaults: MAKEFLAGS: -j5 CPUs: 5 - - base_python_small: &base_python_small - docker: - - image: cimg/python:3.6 - resource_class: small - environment: &base_python_small_env - TERM: xterm - MAKEFLAGS: -j 2 - CPUs: 2 - - base_ubuntu_clang: &base_ubuntu_clang docker: - image: << pipeline.parameters.ubuntu-clang-ossfuzz-docker-image >> @@ -853,7 +844,7 @@ defaults: jobs: chk_spelling: - <<: *base_python_small + <<: *base_ubuntu2404_small steps: - checkout - attach_workspace: @@ -906,7 +897,7 @@ jobs: - matrix_notify_failure_unless_pr chk_errorcodes: - <<: *base_python_small + <<: *base_ubuntu2404_small steps: - checkout - run: From 297230ad32a4ba0ac2505fc1a0d391d1cd1c25a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 26 Nov 2024 20:41:48 +0100 Subject: [PATCH 0478/1340] Fix (or whitelist) new typos found by codespell --- CODE_OF_CONDUCT.md | 2 +- docs/bugs.json | 4 ++-- docs/internals/optimizer.rst | 4 ++-- docs/yul.rst | 2 +- scripts/codespell_ignored_lines.txt | 1 + scripts/codespell_whitelist.txt | 1 + .../abiencodedecode/abi_encode_with_signature.sol | 2 +- .../abi_encode_with_signaturev2.sol | 2 +- .../stackReuse/function_params_and_retparams.yul | 14 +++++++------- .../unassigned_return.yul | 4 ++-- 10 files changed, 19 insertions(+), 17 deletions(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 4c75649ae..273eac602 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -6,7 +6,7 @@ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal +level of experience, education, socioeconomic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards diff --git a/docs/bugs.json b/docs/bugs.json index c853f95ed..800524669 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -151,7 +151,7 @@ { "uid": "SOL-2021-1", "name": "KeccakCaching", - "summary": "The bytecode optimizer incorrectly re-used previously evaluated Keccak-256 hashes. You are unlikely to be affected if you do not compute Keccak-256 hashes in inline assembly.", + "summary": "The bytecode optimizer incorrectly reused previously evaluated Keccak-256 hashes. You are unlikely to be affected if you do not compute Keccak-256 hashes in inline assembly.", "description": "Solidity's bytecode optimizer has a step that can compute Keccak-256 hashes, if the contents of the memory are known during compilation time. This step also has a mechanism to determine that two Keccak-256 hashes are equal even if the values in memory are not known during compile time. This mechanism had a bug where Keccak-256 of the same memory content, but different sizes were considered equal. More specifically, ``keccak256(mpos1, length1)`` and ``keccak256(mpos2, length2)`` in some cases were considered equal if ``length1`` and ``length2``, when rounded up to nearest multiple of 32 were the same, and when the memory contents at ``mpos1`` and ``mpos2`` can be deduced to be equal. You maybe affected if you compute multiple Keccak-256 hashes of the same content, but with different lengths inside inline assembly. You are unaffected if your code uses ``keccak256`` with a length that is not a compile-time constant or if it is always a multiple of 32.", "link": "https://blog.soliditylang.org/2021/03/23/keccak-optimizer-bug/", "fixed": "0.8.3", @@ -200,7 +200,7 @@ "uid": "SOL-2020-7", "name": "MissingEscapingInFormatting", "summary": "String literals containing double backslash characters passed directly to external or encoding function calls can lead to a different string being used when ABIEncoderV2 is enabled.", - "description": "When ABIEncoderV2 is enabled, string literals passed directly to encoding functions or external function calls are stored as strings in the intemediate code. Characters outside the printable range are handled correctly, but backslashes are not escaped in this procedure. This leads to double backslashes being reduced to single backslashes and consequently re-interpreted as escapes potentially resulting in a different string being encoded.", + "description": "When ABIEncoderV2 is enabled, string literals passed directly to encoding functions or external function calls are stored as strings in the intermediate code. Characters outside the printable range are handled correctly, but backslashes are not escaped in this procedure. This leads to double backslashes being reduced to single backslashes and consequently re-interpreted as escapes potentially resulting in a different string being encoded.", "introduced": "0.5.14", "fixed": "0.6.8", "severity": "very low", diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index 604560554..4d02d3e18 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -982,7 +982,7 @@ no other store in between and the values of ``k`` and ``v`` did not change. This simple step is effective if run after the SSATransform and the CommonSubexpressionEliminator, because SSA will make sure that the variables -will not change and the CommonSubexpressionEliminator re-uses exactly the same +will not change and the CommonSubexpressionEliminator reuses exactly the same variable if the value is known to be the same. Prerequisites: Disambiguator, ForLoopInitRewriter. @@ -1287,7 +1287,7 @@ UnusedPruner. The SSA form we generate is detrimental to code generation because it produces many local variables. It would -be better to just re-use existing variables with assignments instead of +be better to just reuse existing variables with assignments instead of fresh variable declarations. The SSATransform rewrites diff --git a/docs/yul.rst b/docs/yul.rst index 2642c0f5c..c81c9562a 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -1069,7 +1069,7 @@ by two, without the optimizer touching the constant two, you can use let double := verbatim_1i_1o(hex"600202", x) This code will result in a ``dup1`` opcode to retrieve ``x`` -(the optimizer might directly re-use result of the +(the optimizer might directly reuse result of the ``calldataload`` opcode, though) directly followed by ``600202``. The code is assumed to consume the copied value of ``x`` and produce the result diff --git a/scripts/codespell_ignored_lines.txt b/scripts/codespell_ignored_lines.txt index b7987cc00..7ad83795c 100644 --- a/scripts/codespell_ignored_lines.txt +++ b/scripts/codespell_ignored_lines.txt @@ -18,3 +18,4 @@ docker run --rm -v "${OUTPUTDIR}":/tmp/output -v "${SCRIPTDIR}":/tmp/scripts:ro templ("assignEnd", "end := pos"); templ("assignEnd", "end := tail"); templ("assignEnd", ""); + self.assertIn('401 Client Error: Unauthorized', str(manager.exception)) diff --git a/scripts/codespell_whitelist.txt b/scripts/codespell_whitelist.txt index 7de8a42fe..7bcbf6ad1 100644 --- a/scripts/codespell_whitelist.txt +++ b/scripts/codespell_whitelist.txt @@ -1,3 +1,4 @@ nd compilability keypair +wast diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signature.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signature.sol index 61a8d0b43..97d7273e9 100644 --- a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signature.sol +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signature.sol @@ -20,7 +20,7 @@ contract C { y[2] = type(uint).max - 2; y[3] = type(uint).max - 3; r = abi.encodeWithSignature(x, y); - // The hash uses temporary memory. This allocation re-uses the memory + // The hash uses temporary memory. This allocation reuses the memory // and should initialize it properly. ar = new uint[](2); } diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol index 402053086..b44d39c34 100644 --- a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol +++ b/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol @@ -20,7 +20,7 @@ contract C { y[2] = type(uint).max - 2; y[3] = type(uint).max - 3; r = abi.encodeWithSignature(x, y); - // The hash uses temporary memory. This allocation re-uses the memory + // The hash uses temporary memory. This allocation reuses the memory // and should initialize it properly. ar = new uint[](2); } diff --git a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul index 529203400..1d157663a 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul @@ -1,25 +1,25 @@ -// This does not re-use the parameters for the return parameters +// This does not reuse the parameters for the return parameters // We do not expect parameters to be fully unused, so the stack // layout for a function is still fixed, even though parameters -// can be re-used. +// can be reused. { function f(a, b, c, d) -> x, y { } } // ==== // stackOptimization: true // ---- -// /* "":212:254 */ +// /* "":210:252 */ // stop -// /* "":218:252 */ +// /* "":216:250 */ // tag_1: // pop // pop // pop // pop -// /* "":247:248 */ +// /* "":245:246 */ // 0x00 -// /* "":244:245 */ +// /* "":242:243 */ // 0x00 -// /* "":218:252 */ +// /* "":216:250 */ // swap2 // jump // out diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul index 35891b459..d26901c23 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul @@ -1,11 +1,11 @@ { function f() -> x { - // can re-use x + // can reuse x let y := 0 mstore(y, 7) } let a - // can re-use a + // can reuse a let b := 0 sstore(a, b) } From 7039ab618c14e110d0e71b4441a9bb4499560031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 26 Nov 2024 20:53:52 +0100 Subject: [PATCH 0479/1340] Move codespell options to a config file - This makes it move convenient to use on the CLI --- .circleci/config.yml | 6 +----- .codespellrc | 4 ++++ 2 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 .codespellrc diff --git a/.circleci/config.yml b/.circleci/config.yml index 994a20032..15d3b4fc5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -855,11 +855,7 @@ jobs: pip install --user codespell - run: name: Check spelling - command: | - ~/.local/bin/codespell \ - --skip "*.enc,.git,Dockerfile*,LICENSE,codespell_whitelist.txt,codespell_ignored_lines.txt,deps" \ - --ignore-words scripts/codespell_whitelist.txt \ - --exclude-file scripts/codespell_ignored_lines.txt + command: ~/.local/bin/codespell - matrix_notify_failure_unless_pr chk_docs_examples: diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 000000000..df31cd316 --- /dev/null +++ b/.codespellrc @@ -0,0 +1,4 @@ +[codespell] +skip = .git,deps,LICENSE,*.enc,Dockerfile*,codespell_whitelist.txt,codespell_ignored_lines.txt +ignore-words = scripts/codespell_whitelist.txt +exclude-file = scripts/codespell_ignored_lines.txt From b887be9eafea1d1e7465e9ca09975d3508dda5c0 Mon Sep 17 00:00:00 2001 From: Noisy <125606576+donatik27@users.noreply.github.com> Date: Wed, 27 Nov 2024 20:54:17 +0100 Subject: [PATCH 0480/1340] Update README.md --- .circleci/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/README.md b/.circleci/README.md index cd1a88ab7..b3e879574 100644 --- a/.circleci/README.md +++ b/.circleci/README.md @@ -13,7 +13,7 @@ docker push ethereum/solidity-buildpack-deps:ubuntu2404- The current revisions per docker image are stored in [circle ci pipeline parameters](https://github.com/CircleCI-Public/api-preview-docs/blob/master/docs/pipeline-parameters.md#pipeline-parameters) called `-docker-image-rev` (e.g., `ubuntu-2404-docker-image-rev`). Please update the value assigned to the parameter(s) corresponding to the docker image(s) being updated at the time of the update. Please verify that the value assigned to the parameter matches the revision part of the docker image tag (`` in the docker build/push snippet shown above). Otherwise, the docker image used by circle ci and the one actually pushed to docker hub will differ. -Once the docker image has been built and pushed to Dockerhub, you can find it at: +Once the docker image has been built and pushed to Docker Hub, you can find it at: https://hub.docker.com/r/ethereum/solidity-buildpack-deps:ubuntu2404- From 9404c86f9d64437484c3105d53503915285434b0 Mon Sep 17 00:00:00 2001 From: Noisy <125606576+donatik27@users.noreply.github.com> Date: Wed, 27 Nov 2024 20:57:40 +0100 Subject: [PATCH 0481/1340] Update README.md --- test/externalTests/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/README.md b/test/externalTests/README.md index 91e2ef9af..327920e21 100644 --- a/test/externalTests/README.md +++ b/test/externalTests/README.md @@ -15,7 +15,7 @@ these projects *can* be upgraded at all. #### Adding a new external project 1. If the upstream code cannot be compiled without modifications, create a fork of the repository in https://github.com/solidity-external-tests/. -2. In our fork, remove all the branches except for main one (`master`, `develop`, `main`, etc). +2. In our fork, remove all the branches except for the main one (`master`, `develop`, `main`, etc). This branch is going to be always kept up to date with the upstream repository and should not contain any extra commits. - If the project is not up to date with the latest compiler version but has a branch that is, From dd4b6d3c4f23ee73e6daefd030374d5f0a79abdf Mon Sep 17 00:00:00 2001 From: Noisy <125606576+donatik27@users.noreply.github.com> Date: Wed, 27 Nov 2024 21:01:08 +0100 Subject: [PATCH 0482/1340] Update README.md --- scripts/docker/buildpack-deps/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docker/buildpack-deps/README.md b/scripts/docker/buildpack-deps/README.md index 15cb71f5b..9cfcafd4b 100644 --- a/scripts/docker/buildpack-deps/README.md +++ b/scripts/docker/buildpack-deps/README.md @@ -4,7 +4,7 @@ The `buildpack-deps` docker images are used to compile and test solidity within ## GitHub Workflow -The creation of the images are triggered by a single workflow, defined in `.github/workflows/buildpack-deps.yml`. +The creation of the images is triggered by a single workflow, defined in `.github/workflows/buildpack-deps.yml`. For each resulting `buildpack-deps` docker image a strategy is defined in the workflow file - the image variant. The workflow gets triggered, if any Dockerfile defined in `scripts/docker/buildpack-deps/Dockerfile.*` were changed within the PR. From 1cce974400d80e4002d4fd37ab432c79260cca8b Mon Sep 17 00:00:00 2001 From: Vishwa Mehta Date: Thu, 28 Nov 2024 23:40:51 +0530 Subject: [PATCH 0483/1340] Update the "Resources" section in the docs (#15076) --- docs/resources.rst | 54 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/docs/resources.rst b/docs/resources.rst index 1773859d4..e8e8fed58 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -5,37 +5,46 @@ Resources General Resources ================= -* `Ethereum.org Developer Portal `_ +* `Ethereum.org Developers page `_ * `Ethereum StackExchange `_ -* `Solidity Portal `_ -* `Solidity Changelog `_ -* `Solidity Source Code on GitHub `_ -* `Solidity Language Users Chat `_ -* `Solidity Compiler Developers Chat `_ -* `Awesome Solidity `_ +* `Solidity website `_ +* `Solidity changelog `_ +* `Solidity codebase on GitHub `_ +* `Solidity language users chat `_ +* `Solidity compiler developers chat `_ +* `awesome-solidity `_ * `Solidity by Example `_ -* `Solidity Documentation Community Translations `_ +* `Solidity documentation community translations `_ Integrated (Ethereum) Development Environments ============================================== - * `Brownie `_ - Python-based development and testing framework for smart contracts targeting the Ethereum Virtual Machine. +* `Ape `_ + A Python-based web3 development tool for compiling, testing, and interacting with smart contracts. - * `Dapp `_ +* `Brownie `_ + A Python-based development and testing framework for smart contracts targeting the Ethereum Virtual Machine. + 💡 Note: As per the official docs, Brownie is no longer actively maintained. + Future releases may come sporadically - or never at all. + Check out Ape Framework (first in list) for all your python Ethereum development needs. + +* `Dapp `_ Tool for building, testing and deploying smart contracts from the command-line. - * `Foundry `_ +* `Foundry `_ Fast, portable and modular toolkit for Ethereum application development written in Rust. - * `Hardhat `_ +* `Hardhat `_ Ethereum development environment with local Ethereum network, debugging features and plugin ecosystem. - * `Remix `_ +* `Remix `_ Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. - * `Truffle `_ +* `Truffle `_ Ethereum development framework. + 💡 Note: Consensys announced the sunset of Truffle on September 21, 2023. + Current users may check out the migration path and available product support `here. + `_ Editor Integrations =================== @@ -70,6 +79,7 @@ Editor Integrations * `Ethereum Remix Visual Studio Code extension `_ Ethereum Remix extension pack for VS Code + 💡 Note: As per the official repository, this extension has been removed from the VSCODE marketplace and will be replaced by a dedicated stand-alone desktop application. * `Solidity Visual Studio Code extension, by Juan Blanco `_ Solidity plugin for Microsoft Visual Studio Code that includes syntax highlighting and the Solidity compiler. @@ -82,6 +92,9 @@ Editor Integrations * `Truffle for VS Code `_ Build, debug and deploy smart contracts on Ethereum and EVM-compatible blockchains. + 💡 Note: This extension has built-in support for the Truffle Suite which is being sunset. + For information on ongoing support, migration options and FAQs, visit the `Consensys blog. + `_ Solidity Tools ============== @@ -92,9 +105,15 @@ Solidity Tools * `abi-to-sol `_ Tool to generate Solidity interface source from a given ABI JSON. +* `Aderyn `_ + Rust-based solidity smart contract static analyzer designed to help find vulnerabilities in Solidity code bases. + * `Doxity `_ Documentation Generator for Solidity. +* `ethdebug `_ + A standard debugging data format for smart contracts on Ethereum-compatible networks. + * `Ethlint `_ Linter to identify and fix style and security issues in Solidity. @@ -102,7 +121,7 @@ Solidity Tools EVM Disassembler that performs static analysis on the bytecode to provide a higher level of abstraction than raw EVM operations. * `EVM Lab `_ - Rich tool package to interact with the EVM. Includes a VM, Etherchain API, and a trace-viewer with gas cost display. + A collection of tools to interact with the EVM. The package includes a VM, Etherchain API, and a trace-viewer with gas cost display. * `hevm `_ EVM debugger and symbolic execution engine. @@ -140,6 +159,9 @@ Solidity Tools * `Universal Mutator `_ A tool for mutation generation, with configurable rules and support for Solidity and Vyper. +* `Wake `_ + A Python-based Solidity development and testing framework with built-in vulnerability detectors. + Third-Party Solidity Parsers and Grammars ========================================= From 6634b9ee9e558789d5673df6ba2f712eb1f10412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 28 Nov 2024 23:35:58 +0100 Subject: [PATCH 0484/1340] Replace InvalidDeposit exception with assertions - We never actually catch it so it's already de facto handled like a failed assert, just with worse diagnostics. --- libevmasm/Assembly.h | 4 ++-- libevmasm/Exceptions.h | 1 - libevmasm/KnownState.cpp | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 4b52ca3d7..f2da01e22 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -127,8 +127,8 @@ class Assembly void appendToAuxiliaryData(bytes const& _data) { m_auxiliaryData += _data; } int deposit() const { return m_deposit; } - void adjustDeposit(int _adjustment) { m_deposit += _adjustment; assertThrow(m_deposit >= 0, InvalidDeposit, ""); } - void setDeposit(int _deposit) { m_deposit = _deposit; assertThrow(m_deposit >= 0, InvalidDeposit, ""); } + void adjustDeposit(int _adjustment) { m_deposit += _adjustment; solAssert(m_deposit >= 0); } + void setDeposit(int _deposit) { m_deposit = _deposit; solAssert(m_deposit >= 0); } std::string const& name() const { return m_name; } /// Changes the source location used for each appended item. diff --git a/libevmasm/Exceptions.h b/libevmasm/Exceptions.h index ae6d1bf9c..032ed4411 100644 --- a/libevmasm/Exceptions.h +++ b/libevmasm/Exceptions.h @@ -33,7 +33,6 @@ struct OptimizerException: virtual AssemblyException {}; struct StackTooDeepException: virtual OptimizerException {}; struct ItemNotAvailableException: virtual OptimizerException {}; -DEV_SIMPLE_EXCEPTION(InvalidDeposit); DEV_SIMPLE_EXCEPTION(InvalidOpcode); } diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 3878ae0fd..66553bc06 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -120,7 +120,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool } else if (_item.type() != Operation) { - assertThrow(_item.deposit() == 1, InvalidDeposit, ""); + solAssert(_item.deposit() == 1); if (_item.pushedValue()) // only available after assembly stage, should not be used for optimisation setStackElement(++m_stackHeight, m_expressionClasses->find(*_item.pushedValue())); @@ -194,7 +194,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool resetStorage(); if (invMem || invStor) m_sequenceNumber += 2; // Increment by two because it can read and write - assertThrow(info.ret <= 1, InvalidDeposit, ""); + solAssert(info.ret <= 1); if (info.ret == 1) setStackElement( m_stackHeight + static_cast(_item.deposit()), From c127395fabcf87605693829132de30501aa8e21e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 29 Nov 2024 02:17:14 +0100 Subject: [PATCH 0485/1340] Replace InvalidOpcode exception with AssemblyImportException and asserts - The only case where it needs to be an exception is assembly import. In other situations we don't catch it so it's effectively an assert. --- libevmasm/Assembly.cpp | 6 +++--- libevmasm/Exceptions.h | 2 -- libevmasm/Instruction.h | 9 +++++---- libsolidity/interface/StandardCompiler.cpp | 4 ---- .../standard_import_asm_json_invalid_opcode/output.json | 4 ++-- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index fdc272415..5bf8e2508 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -281,7 +281,7 @@ AssemblyItem Assembly::createAssemblyItemFromJSON(Json const& _json, std::vector result = item; } else - solThrow(InvalidOpcode, "Invalid opcode: " + name); + solThrow(AssemblyImportException, "Invalid opcode (" + name + ")"); } result.setLocation(location); result.m_modifierDepth = modifierDepth; @@ -1236,7 +1236,7 @@ LinkerObject const& Assembly::assembleLegacy() const ret.bytecode += assembleTag(item, ret.bytecode.size(), true); break; default: - assertThrow(false, InvalidOpcode, "Unexpected opcode while assembling."); + solAssert(false, "Unexpected opcode while assembling."); } } @@ -1469,7 +1469,7 @@ LinkerObject const& Assembly::assembleEOF() const break; } default: - solThrow(InvalidOpcode, "Unexpected opcode while assembling."); + solAssert(false, "Unexpected opcode while assembling."); } } diff --git a/libevmasm/Exceptions.h b/libevmasm/Exceptions.h index 032ed4411..c9d0633e4 100644 --- a/libevmasm/Exceptions.h +++ b/libevmasm/Exceptions.h @@ -33,6 +33,4 @@ struct OptimizerException: virtual AssemblyException {}; struct StackTooDeepException: virtual OptimizerException {}; struct ItemNotAvailableException: virtual OptimizerException {}; -DEV_SIMPLE_EXCEPTION(InvalidOpcode); - } diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 76998c538..84c6e34e6 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace solidity::evmasm { @@ -267,28 +268,28 @@ inline unsigned getLogNumber(Instruction _inst) /// @returns the PUSH<_number> instruction inline Instruction pushInstruction(unsigned _number) { - assertThrow(_number <= 32, InvalidOpcode, std::string("Invalid PUSH instruction requested (") + std::to_string(_number) + ")."); + solAssert(_number <= 32); return Instruction(unsigned(Instruction::PUSH0) + _number); } /// @returns the DUP<_number> instruction inline Instruction dupInstruction(unsigned _number) { - assertThrow(1 <= _number && _number <= 16, InvalidOpcode, std::string("Invalid DUP instruction requested (") + std::to_string(_number) + ")."); + solAssert(1 <= _number && _number <= 16); return Instruction(unsigned(Instruction::DUP1) + _number - 1); } /// @returns the SWAP<_number> instruction inline Instruction swapInstruction(unsigned _number) { - assertThrow(1 <= _number && _number <= 16, InvalidOpcode, std::string("Invalid SWAP instruction requested (") + std::to_string(_number) + ")."); + solAssert(1 <= _number && _number <= 16); return Instruction(unsigned(Instruction::SWAP1) + _number - 1); } /// @returns the LOG<_number> instruction inline Instruction logInstruction(unsigned _number) { - assertThrow(_number <= 4, InvalidOpcode, std::string("Invalid LOG instruction requested (") + std::to_string(_number) + ")."); + solAssert(_number <= 4); return Instruction(unsigned(Instruction::LOG0) + _number); } diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index c5248e42e..351a17b89 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1220,10 +1220,6 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in { return formatFatalError(Error::Type::Exception, "Assembly import error: " + std::string(e.what())); } - catch (evmasm::InvalidOpcode const& e) - { - return formatFatalError(Error::Type::Exception, "Assembly import error: " + std::string(e.what())); - } catch (...) { return formatError( diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json index cccd241d9..14e502301 100644 --- a/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json +++ b/test/cmdlineTests/standard_import_asm_json_invalid_opcode/output.json @@ -2,8 +2,8 @@ "errors": [ { "component": "general", - "formattedMessage": "Assembly import error: InvalidOpcode", - "message": "Assembly import error: InvalidOpcode", + "formattedMessage": "Assembly import error: Invalid opcode (INVALID_OPCODE)", + "message": "Assembly import error: Invalid opcode (INVALID_OPCODE)", "severity": "error", "type": "Exception" } From 8fdbee88055542adfebca6d74f8701d7d7b08e5b Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 31 Oct 2024 20:33:56 +0100 Subject: [PATCH 0486/1340] CI: Limit parallelism when building Z3 on MacOS Unlimited parallelism led to overwhelmed worker and unsuccessful builds. --- .circleci/osx_install_dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index dff85b489..4c359c411 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -106,7 +106,7 @@ then mkdir build cd build cmake -DCMAKE_OSX_ARCHITECTURES:STRING="x86_64;arm64" -DZ3_BUILD_LIBZ3_SHARED=false .. - make -j + make -j "$(nproc)" sudo make install cd ../.. rm -rf "$z3_dir" From ff62b340523d98d63d3d006474d14a3e92afa70b Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 1 Nov 2024 10:53:55 +0100 Subject: [PATCH 0487/1340] Pylint: Disable check for too many positional arguments --- scripts/pylintrc | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/pylintrc b/scripts/pylintrc index 5ef5a6eff..191e80386 100644 --- a/scripts/pylintrc +++ b/scripts/pylintrc @@ -29,6 +29,7 @@ disable= too-many-branches, too-many-instance-attributes, too-many-locals, + too-many-positional-arguments, too-many-public-methods, too-many-statements, ungrouped-imports From 973b403f30e91cdcbb4fe0c335e38700b161617d Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 31 Oct 2024 15:09:00 +0100 Subject: [PATCH 0488/1340] SMTChecker: Update solvers' versions in CI and update test expectations This includes using new version of docker images, and updating the MacOS environment --- .circleci/config.yml | 16 ++++++++-------- .circleci/osx_install_dependencies.sh | 18 ++++++++---------- CMakeLists.txt | 2 +- scripts/build_emscripten.sh | 4 ++-- .../types/fixed_bytes_access_3.sol | 4 ++-- .../types/tuple_assignment_array_empty.sol | 5 +++-- 6 files changed, 24 insertions(+), 25 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 15d3b4fc5..542118f6d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,16 +9,16 @@ version: 2.1 parameters: ubuntu-2004-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-25 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:b3f321fb2d8e7a41ca9328672061c1840e5cd3fb5be503aa158d1c508deacf0a" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-26 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:1f387a77be889f65a2a25986a5c5eccc88cec23fabe6aeaf351790751145c81e" ubuntu-2404-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-1 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:5d6d27551104321a30326d6024bd4e96d9d899a97a78eb9feea364996f1d18b5" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-2 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:92efa8581887e5389b29d3a150112a8433a04ebf5fddf2c65ed6794b4cdf1fe3" ubuntu-2404-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-2 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:bc99a858ba18e088c1cb889ce631e3e707bb3348f0ae452bfe69116dbb931173" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-3 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:534c4eea1ba370a85cf3c106b4a30b43152ba4f695fab5e18577009a5e272146" ubuntu-clang-ossfuzz-docker-image: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-6 @@ -26,8 +26,8 @@ parameters: emscripten-docker-image: type: string # NOTE: Please remember to update the `scripts/build_emscripten.sh` whenever the hash of this image changes. - # solbuildpackpusher/solidity-buildpack-deps:emscripten-17 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c57f2bfb8c15d70fe290629358dd1c73dc126e3760f443b54764797556b887d4" + # solbuildpackpusher/solidity-buildpack-deps:emscripten-19 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:170b159c82ce70e639500551394460f01798c18a5e17b45ea91277b0cf8eae37" evm-version: type: string default: cancun diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index 4c359c411..c606913e4 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -85,21 +85,19 @@ then rm -rf /tmp/{eldarica,eld_binaries.zip} #cvc5 - cvc5_version="1.1.2" - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-macOS-arm64-static.zip" -O /tmp/cvc5.zip - validate_checksum /tmp/cvc5.zip 2017d683d924676cb713865c6d4fcf70115c65b7ec2848f242ab938902f115b5 - unzip /tmp/cvc5.zip -x "cvc5-macOS-arm64-static/lib/cmake/*" -d /tmp - sudo mv /tmp/cvc5-macOS-arm64-static/bin/* /usr/local/bin - sudo mv /tmp/cvc5-macOS-arm64-static/include/* /usr/local/include - sudo mv /tmp/cvc5-macOS-arm64-static/lib/* /usr/local/lib - rm -rf /tmp/{cvc5-macOS-arm64-static,cvc5.zip} + cvc5_version="1.2.0" + cvc5_archive_name="cvc5-macOS-arm64-static" + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /tmp/cvc5.zip + validate_checksum /tmp/cvc5.zip 57d2d4855af3f3865110a254e415098b4e150a655f297010e27eb292f48f7da7 + sudo unzip -j /tmp/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/local/bin + rm -f /tmp/cvc5.zip # z3 - z3_version="4.12.1" + z3_version="4.13.3" z3_dir="z3-z3-$z3_version" z3_package="z3-$z3_version.tar.gz" wget "https://github.com/Z3Prover/z3/archive/refs/tags/$z3_package" - validate_checksum "$z3_package" a3735fabf00e1341adcc70394993c05fd3e2ae167a3e9bb46045e33084eb64a3 + validate_checksum "$z3_package" f59c9cf600ea57fb64ffeffbffd0f2d2b896854f339e846f48f069d23bc14ba0 tar xf "$z3_package" rm "$z3_package" cd "$z3_dir" diff --git a/CMakeLists.txt b/CMakeLists.txt index 836d2cccb..729da0d72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,7 +92,7 @@ include(EthOptions) configure_project(TESTS) if(EMSCRIPTEN) - set(TESTED_Z3_VERSION "4.12.1") + set(TESTED_Z3_VERSION "4.13.3") set(MINIMUM_Z3_VERSION "4.8.16") find_package(Z3) if (${Z3_FOUND}) diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index dc862b1f7..a53393f1d 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -33,9 +33,9 @@ if (( $# != 0 )); then params="$(printf "%q " "${@}")" fi -# solbuildpackpusher/solidity-buildpack-deps:emscripten-17 +# solbuildpackpusher/solidity-buildpack-deps:emscripten-19 # NOTE: Without `safe.directory` git would assume it's not safe to operate on /root/project since it's owned by a different user. # See https://github.blog/2022-04-12-git-security-vulnerability-announced/ docker run -v "$(pwd):/root/project" -w /root/project \ - solbuildpackpusher/solidity-buildpack-deps@sha256:c57f2bfb8c15d70fe290629358dd1c73dc126e3760f443b54764797556b887d4 \ + solbuildpackpusher/solidity-buildpack-deps@sha256:170b159c82ce70e639500551394460f01798c18a5e17b45ea91277b0cf8eae37 \ /bin/bash -c "git config --global --add safe.directory /root/project && ./scripts/ci/build_emscripten.sh ${params}" diff --git a/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol b/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol index bb4ef0342..54f323353 100644 --- a/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol +++ b/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol @@ -30,7 +30,7 @@ contract C { } // ==== // SMTEngine: all -// SMTIgnoreOS: macos // ---- +// Warning 6368: (374-381): CHC: Out of bounds access might happen here. // Warning 6368: (456-462): CHC: Out of bounds access happens here. -// Info 1391: CHC: 13 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 12 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/tuple_assignment_array_empty.sol b/test/libsolidity/smtCheckerTests/types/tuple_assignment_array_empty.sol index 79be48b3a..3b9a47986 100644 --- a/test/libsolidity/smtCheckerTests/types/tuple_assignment_array_empty.sol +++ b/test/libsolidity/smtCheckerTests/types/tuple_assignment_array_empty.sol @@ -16,6 +16,7 @@ contract C // ==== // SMTEngine: all // SMTIgnoreCex: yes +// SMTTargets: assert // ---- -// Warning 6328: (198-215): CHC: Assertion violation happens here. -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (198-215): CHC: Assertion violation happens here.\nCounterexample:\na = [3212, 4]\nx = 0\ny = 1\n\nTransaction trace:\nC.constructor()\nState: a = []\nC.f(3212)\nState: a = [3212]\nC.f(1573)\nState: a = [3212, 1573]\nC.g(0, 1) +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 311e8dba3abbb5aede0741f7e8761673a490257e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20=C5=BBuk?= Date: Fri, 29 Nov 2024 15:35:33 +0100 Subject: [PATCH 0489/1340] Document memory alignment (#15586) --- docs/assembly.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/assembly.rst b/docs/assembly.rst index a0a9d06dc..09e158e48 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -257,6 +257,8 @@ starting from where this pointer points at and update it. There is no guarantee that the memory has not been used before and thus you cannot assume that its contents are zero bytes. There is no built-in mechanism to release or free allocated memory. +Solidity does not guarantee and does not require that the values in memory +are placed at positions aligned to a multiple of any value. Here is an assembly snippet you can use for allocating memory that follows the process outlined above: .. code-block:: yul From 7a5e5a6e82e9630449736f080935527692521fa0 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 29 Nov 2024 11:20:24 +0100 Subject: [PATCH 0490/1340] eof: Refactor of`findReferencedContainers` and `createEOFHeader`. --- libevmasm/Assembly.cpp | 13 +- libevmasm/Assembly.h | 4 +- .../objectCompiler/eof/256_subcontainers.yul | 4113 +++++++++++++++++ 3 files changed, 4122 insertions(+), 8 deletions(-) create mode 100644 test/libyul/objectCompiler/eof/256_subcontainers.yul diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 5bf8e2508..584c46455 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -924,7 +924,7 @@ void appendBigEndianUint16(bytes& _dest, ValueT _value) } } -std::tuple, size_t> Assembly::createEOFHeader(std::set const& _referencedSubIds) const +std::tuple, size_t> Assembly::createEOFHeader(std::set const& _referencedSubIds) const { bytes retBytecode; std::vector codeSectionSizePositions; @@ -1330,9 +1330,9 @@ LinkerObject const& Assembly::assembleLegacy() const return ret; } -std::map Assembly::findReferencedContainers() const +std::map Assembly::findReferencedContainers() const { - std::set referencedSubcontainersIds; + std::set referencedSubcontainersIds; solAssert(m_subs.size() <= 0x100); // According to EOF spec for (auto&& codeSection: m_codeSections) @@ -1344,12 +1344,13 @@ std::map Assembly::findReferencedContainers() const referencedSubcontainersIds.insert(containerId); } - std::map replacements; + std::map replacements; uint8_t nUnreferenced = 0; for (uint8_t i = 0; i < static_cast(m_subs.size()); ++i) { - if (referencedSubcontainersIds.count(i) > 0) - replacements[i] = static_cast(i - nUnreferenced); + solAssert(i <= std::numeric_limits::max()); + if (referencedSubcontainersIds.count(static_cast(i)) > 0) + replacements[static_cast(i)] = static_cast(i - nUnreferenced); else nUnreferenced++; } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index f2da01e22..7ef03460c 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -247,13 +247,13 @@ class Assembly std::shared_ptr sharedSourceName(std::string const& _name) const; /// Returns EOF header bytecode | code section sizes offsets | data section size offset - std::tuple, size_t> createEOFHeader(std::set const& _referencedSubIds) const; + std::tuple, size_t> createEOFHeader(std::set const& _referencedSubIds) const; LinkerObject const& assembleLegacy() const; LinkerObject const& assembleEOF() const; /// Returns map from m_subs to an index of subcontainer in the final EOF bytecode - std::map findReferencedContainers() const; + std::map findReferencedContainers() const; /// Returns max AuxDataLoadN offset for the assembly. std::optional findMaxAuxDataLoadNOffset() const; diff --git a/test/libyul/objectCompiler/eof/256_subcontainers.yul b/test/libyul/objectCompiler/eof/256_subcontainers.yul new file mode 100644 index 000000000..06aebd674 --- /dev/null +++ b/test/libyul/objectCompiler/eof/256_subcontainers.yul @@ -0,0 +1,4113 @@ +object "a" { + code { + pop(eofcreate("s0000", 0, 0, 0, 0)) + pop(eofcreate("s0001", 0, 0, 0, 0)) + pop(eofcreate("s0002", 0, 0, 0, 0)) + pop(eofcreate("s0003", 0, 0, 0, 0)) + pop(eofcreate("s0004", 0, 0, 0, 0)) + pop(eofcreate("s0005", 0, 0, 0, 0)) + pop(eofcreate("s0006", 0, 0, 0, 0)) + pop(eofcreate("s0007", 0, 0, 0, 0)) + pop(eofcreate("s0008", 0, 0, 0, 0)) + pop(eofcreate("s0009", 0, 0, 0, 0)) + pop(eofcreate("s0010", 0, 0, 0, 0)) + pop(eofcreate("s0011", 0, 0, 0, 0)) + pop(eofcreate("s0012", 0, 0, 0, 0)) + pop(eofcreate("s0013", 0, 0, 0, 0)) + pop(eofcreate("s0014", 0, 0, 0, 0)) + pop(eofcreate("s0015", 0, 0, 0, 0)) + pop(eofcreate("s0016", 0, 0, 0, 0)) + pop(eofcreate("s0017", 0, 0, 0, 0)) + pop(eofcreate("s0018", 0, 0, 0, 0)) + pop(eofcreate("s0019", 0, 0, 0, 0)) + pop(eofcreate("s0020", 0, 0, 0, 0)) + pop(eofcreate("s0021", 0, 0, 0, 0)) + pop(eofcreate("s0022", 0, 0, 0, 0)) + pop(eofcreate("s0023", 0, 0, 0, 0)) + pop(eofcreate("s0024", 0, 0, 0, 0)) + pop(eofcreate("s0025", 0, 0, 0, 0)) + pop(eofcreate("s0026", 0, 0, 0, 0)) + pop(eofcreate("s0027", 0, 0, 0, 0)) + pop(eofcreate("s0028", 0, 0, 0, 0)) + pop(eofcreate("s0029", 0, 0, 0, 0)) + pop(eofcreate("s0030", 0, 0, 0, 0)) + pop(eofcreate("s0031", 0, 0, 0, 0)) + pop(eofcreate("s0032", 0, 0, 0, 0)) + pop(eofcreate("s0033", 0, 0, 0, 0)) + pop(eofcreate("s0034", 0, 0, 0, 0)) + pop(eofcreate("s0035", 0, 0, 0, 0)) + pop(eofcreate("s0036", 0, 0, 0, 0)) + pop(eofcreate("s0037", 0, 0, 0, 0)) + pop(eofcreate("s0038", 0, 0, 0, 0)) + pop(eofcreate("s0039", 0, 0, 0, 0)) + pop(eofcreate("s0040", 0, 0, 0, 0)) + pop(eofcreate("s0041", 0, 0, 0, 0)) + pop(eofcreate("s0042", 0, 0, 0, 0)) + pop(eofcreate("s0043", 0, 0, 0, 0)) + pop(eofcreate("s0044", 0, 0, 0, 0)) + pop(eofcreate("s0045", 0, 0, 0, 0)) + pop(eofcreate("s0046", 0, 0, 0, 0)) + pop(eofcreate("s0047", 0, 0, 0, 0)) + pop(eofcreate("s0048", 0, 0, 0, 0)) + pop(eofcreate("s0049", 0, 0, 0, 0)) + pop(eofcreate("s0050", 0, 0, 0, 0)) + pop(eofcreate("s0051", 0, 0, 0, 0)) + pop(eofcreate("s0052", 0, 0, 0, 0)) + pop(eofcreate("s0053", 0, 0, 0, 0)) + pop(eofcreate("s0054", 0, 0, 0, 0)) + pop(eofcreate("s0055", 0, 0, 0, 0)) + pop(eofcreate("s0056", 0, 0, 0, 0)) + pop(eofcreate("s0057", 0, 0, 0, 0)) + pop(eofcreate("s0058", 0, 0, 0, 0)) + pop(eofcreate("s0059", 0, 0, 0, 0)) + pop(eofcreate("s0060", 0, 0, 0, 0)) + pop(eofcreate("s0061", 0, 0, 0, 0)) + pop(eofcreate("s0062", 0, 0, 0, 0)) + pop(eofcreate("s0063", 0, 0, 0, 0)) + pop(eofcreate("s0064", 0, 0, 0, 0)) + pop(eofcreate("s0065", 0, 0, 0, 0)) + pop(eofcreate("s0066", 0, 0, 0, 0)) + pop(eofcreate("s0067", 0, 0, 0, 0)) + pop(eofcreate("s0068", 0, 0, 0, 0)) + pop(eofcreate("s0069", 0, 0, 0, 0)) + pop(eofcreate("s0070", 0, 0, 0, 0)) + pop(eofcreate("s0071", 0, 0, 0, 0)) + pop(eofcreate("s0072", 0, 0, 0, 0)) + pop(eofcreate("s0073", 0, 0, 0, 0)) + pop(eofcreate("s0074", 0, 0, 0, 0)) + pop(eofcreate("s0075", 0, 0, 0, 0)) + pop(eofcreate("s0076", 0, 0, 0, 0)) + pop(eofcreate("s0077", 0, 0, 0, 0)) + pop(eofcreate("s0078", 0, 0, 0, 0)) + pop(eofcreate("s0079", 0, 0, 0, 0)) + pop(eofcreate("s0080", 0, 0, 0, 0)) + pop(eofcreate("s0081", 0, 0, 0, 0)) + pop(eofcreate("s0082", 0, 0, 0, 0)) + pop(eofcreate("s0083", 0, 0, 0, 0)) + pop(eofcreate("s0084", 0, 0, 0, 0)) + pop(eofcreate("s0085", 0, 0, 0, 0)) + pop(eofcreate("s0086", 0, 0, 0, 0)) + pop(eofcreate("s0087", 0, 0, 0, 0)) + pop(eofcreate("s0088", 0, 0, 0, 0)) + pop(eofcreate("s0089", 0, 0, 0, 0)) + pop(eofcreate("s0090", 0, 0, 0, 0)) + pop(eofcreate("s0091", 0, 0, 0, 0)) + pop(eofcreate("s0092", 0, 0, 0, 0)) + pop(eofcreate("s0093", 0, 0, 0, 0)) + pop(eofcreate("s0094", 0, 0, 0, 0)) + pop(eofcreate("s0095", 0, 0, 0, 0)) + pop(eofcreate("s0096", 0, 0, 0, 0)) + pop(eofcreate("s0097", 0, 0, 0, 0)) + pop(eofcreate("s0098", 0, 0, 0, 0)) + pop(eofcreate("s0099", 0, 0, 0, 0)) + pop(eofcreate("s0100", 0, 0, 0, 0)) + pop(eofcreate("s0101", 0, 0, 0, 0)) + pop(eofcreate("s0102", 0, 0, 0, 0)) + pop(eofcreate("s0103", 0, 0, 0, 0)) + pop(eofcreate("s0104", 0, 0, 0, 0)) + pop(eofcreate("s0105", 0, 0, 0, 0)) + pop(eofcreate("s0106", 0, 0, 0, 0)) + pop(eofcreate("s0107", 0, 0, 0, 0)) + pop(eofcreate("s0108", 0, 0, 0, 0)) + pop(eofcreate("s0109", 0, 0, 0, 0)) + pop(eofcreate("s0110", 0, 0, 0, 0)) + pop(eofcreate("s0111", 0, 0, 0, 0)) + pop(eofcreate("s0112", 0, 0, 0, 0)) + pop(eofcreate("s0113", 0, 0, 0, 0)) + pop(eofcreate("s0114", 0, 0, 0, 0)) + pop(eofcreate("s0115", 0, 0, 0, 0)) + pop(eofcreate("s0116", 0, 0, 0, 0)) + pop(eofcreate("s0117", 0, 0, 0, 0)) + pop(eofcreate("s0118", 0, 0, 0, 0)) + pop(eofcreate("s0119", 0, 0, 0, 0)) + pop(eofcreate("s0120", 0, 0, 0, 0)) + pop(eofcreate("s0121", 0, 0, 0, 0)) + pop(eofcreate("s0122", 0, 0, 0, 0)) + pop(eofcreate("s0123", 0, 0, 0, 0)) + pop(eofcreate("s0124", 0, 0, 0, 0)) + pop(eofcreate("s0125", 0, 0, 0, 0)) + pop(eofcreate("s0126", 0, 0, 0, 0)) + pop(eofcreate("s0127", 0, 0, 0, 0)) + pop(eofcreate("s0128", 0, 0, 0, 0)) + pop(eofcreate("s0129", 0, 0, 0, 0)) + pop(eofcreate("s0130", 0, 0, 0, 0)) + pop(eofcreate("s0131", 0, 0, 0, 0)) + pop(eofcreate("s0132", 0, 0, 0, 0)) + pop(eofcreate("s0133", 0, 0, 0, 0)) + pop(eofcreate("s0134", 0, 0, 0, 0)) + pop(eofcreate("s0135", 0, 0, 0, 0)) + pop(eofcreate("s0136", 0, 0, 0, 0)) + pop(eofcreate("s0137", 0, 0, 0, 0)) + pop(eofcreate("s0138", 0, 0, 0, 0)) + pop(eofcreate("s0139", 0, 0, 0, 0)) + pop(eofcreate("s0140", 0, 0, 0, 0)) + pop(eofcreate("s0141", 0, 0, 0, 0)) + pop(eofcreate("s0142", 0, 0, 0, 0)) + pop(eofcreate("s0143", 0, 0, 0, 0)) + pop(eofcreate("s0144", 0, 0, 0, 0)) + pop(eofcreate("s0145", 0, 0, 0, 0)) + pop(eofcreate("s0146", 0, 0, 0, 0)) + pop(eofcreate("s0147", 0, 0, 0, 0)) + pop(eofcreate("s0148", 0, 0, 0, 0)) + pop(eofcreate("s0149", 0, 0, 0, 0)) + pop(eofcreate("s0150", 0, 0, 0, 0)) + pop(eofcreate("s0151", 0, 0, 0, 0)) + pop(eofcreate("s0152", 0, 0, 0, 0)) + pop(eofcreate("s0153", 0, 0, 0, 0)) + pop(eofcreate("s0154", 0, 0, 0, 0)) + pop(eofcreate("s0155", 0, 0, 0, 0)) + pop(eofcreate("s0156", 0, 0, 0, 0)) + pop(eofcreate("s0157", 0, 0, 0, 0)) + pop(eofcreate("s0158", 0, 0, 0, 0)) + pop(eofcreate("s0159", 0, 0, 0, 0)) + pop(eofcreate("s0160", 0, 0, 0, 0)) + pop(eofcreate("s0161", 0, 0, 0, 0)) + pop(eofcreate("s0162", 0, 0, 0, 0)) + pop(eofcreate("s0163", 0, 0, 0, 0)) + pop(eofcreate("s0164", 0, 0, 0, 0)) + pop(eofcreate("s0165", 0, 0, 0, 0)) + pop(eofcreate("s0166", 0, 0, 0, 0)) + pop(eofcreate("s0167", 0, 0, 0, 0)) + pop(eofcreate("s0168", 0, 0, 0, 0)) + pop(eofcreate("s0169", 0, 0, 0, 0)) + pop(eofcreate("s0170", 0, 0, 0, 0)) + pop(eofcreate("s0171", 0, 0, 0, 0)) + pop(eofcreate("s0172", 0, 0, 0, 0)) + pop(eofcreate("s0173", 0, 0, 0, 0)) + pop(eofcreate("s0174", 0, 0, 0, 0)) + pop(eofcreate("s0175", 0, 0, 0, 0)) + pop(eofcreate("s0176", 0, 0, 0, 0)) + pop(eofcreate("s0177", 0, 0, 0, 0)) + pop(eofcreate("s0178", 0, 0, 0, 0)) + pop(eofcreate("s0179", 0, 0, 0, 0)) + pop(eofcreate("s0180", 0, 0, 0, 0)) + pop(eofcreate("s0181", 0, 0, 0, 0)) + pop(eofcreate("s0182", 0, 0, 0, 0)) + pop(eofcreate("s0183", 0, 0, 0, 0)) + pop(eofcreate("s0184", 0, 0, 0, 0)) + pop(eofcreate("s0185", 0, 0, 0, 0)) + pop(eofcreate("s0186", 0, 0, 0, 0)) + pop(eofcreate("s0187", 0, 0, 0, 0)) + pop(eofcreate("s0188", 0, 0, 0, 0)) + pop(eofcreate("s0189", 0, 0, 0, 0)) + pop(eofcreate("s0190", 0, 0, 0, 0)) + pop(eofcreate("s0191", 0, 0, 0, 0)) + pop(eofcreate("s0192", 0, 0, 0, 0)) + pop(eofcreate("s0193", 0, 0, 0, 0)) + pop(eofcreate("s0194", 0, 0, 0, 0)) + pop(eofcreate("s0195", 0, 0, 0, 0)) + pop(eofcreate("s0196", 0, 0, 0, 0)) + pop(eofcreate("s0197", 0, 0, 0, 0)) + pop(eofcreate("s0198", 0, 0, 0, 0)) + pop(eofcreate("s0199", 0, 0, 0, 0)) + pop(eofcreate("s0200", 0, 0, 0, 0)) + pop(eofcreate("s0201", 0, 0, 0, 0)) + pop(eofcreate("s0202", 0, 0, 0, 0)) + pop(eofcreate("s0203", 0, 0, 0, 0)) + pop(eofcreate("s0204", 0, 0, 0, 0)) + pop(eofcreate("s0205", 0, 0, 0, 0)) + pop(eofcreate("s0206", 0, 0, 0, 0)) + pop(eofcreate("s0207", 0, 0, 0, 0)) + pop(eofcreate("s0208", 0, 0, 0, 0)) + pop(eofcreate("s0209", 0, 0, 0, 0)) + pop(eofcreate("s0210", 0, 0, 0, 0)) + pop(eofcreate("s0211", 0, 0, 0, 0)) + pop(eofcreate("s0212", 0, 0, 0, 0)) + pop(eofcreate("s0213", 0, 0, 0, 0)) + pop(eofcreate("s0214", 0, 0, 0, 0)) + pop(eofcreate("s0215", 0, 0, 0, 0)) + pop(eofcreate("s0216", 0, 0, 0, 0)) + pop(eofcreate("s0217", 0, 0, 0, 0)) + pop(eofcreate("s0218", 0, 0, 0, 0)) + pop(eofcreate("s0219", 0, 0, 0, 0)) + pop(eofcreate("s0220", 0, 0, 0, 0)) + pop(eofcreate("s0221", 0, 0, 0, 0)) + pop(eofcreate("s0222", 0, 0, 0, 0)) + pop(eofcreate("s0223", 0, 0, 0, 0)) + pop(eofcreate("s0224", 0, 0, 0, 0)) + pop(eofcreate("s0225", 0, 0, 0, 0)) + pop(eofcreate("s0226", 0, 0, 0, 0)) + pop(eofcreate("s0227", 0, 0, 0, 0)) + pop(eofcreate("s0228", 0, 0, 0, 0)) + pop(eofcreate("s0229", 0, 0, 0, 0)) + pop(eofcreate("s0230", 0, 0, 0, 0)) + pop(eofcreate("s0231", 0, 0, 0, 0)) + pop(eofcreate("s0232", 0, 0, 0, 0)) + pop(eofcreate("s0233", 0, 0, 0, 0)) + pop(eofcreate("s0234", 0, 0, 0, 0)) + pop(eofcreate("s0235", 0, 0, 0, 0)) + pop(eofcreate("s0236", 0, 0, 0, 0)) + pop(eofcreate("s0237", 0, 0, 0, 0)) + pop(eofcreate("s0238", 0, 0, 0, 0)) + pop(eofcreate("s0239", 0, 0, 0, 0)) + pop(eofcreate("s0240", 0, 0, 0, 0)) + pop(eofcreate("s0241", 0, 0, 0, 0)) + pop(eofcreate("s0242", 0, 0, 0, 0)) + pop(eofcreate("s0243", 0, 0, 0, 0)) + pop(eofcreate("s0244", 0, 0, 0, 0)) + pop(eofcreate("s0245", 0, 0, 0, 0)) + pop(eofcreate("s0246", 0, 0, 0, 0)) + pop(eofcreate("s0247", 0, 0, 0, 0)) + pop(eofcreate("s0248", 0, 0, 0, 0)) + pop(eofcreate("s0249", 0, 0, 0, 0)) + pop(eofcreate("s0250", 0, 0, 0, 0)) + pop(eofcreate("s0251", 0, 0, 0, 0)) + pop(eofcreate("s0252", 0, 0, 0, 0)) + pop(eofcreate("s0253", 0, 0, 0, 0)) + pop(eofcreate("s0254", 0, 0, 0, 0)) + pop(eofcreate("s0255", 0, 0, 0, 0)) + } + + object "s0000" {code{}} + object "s0001" {code{}} + object "s0002" {code{}} + object "s0003" {code{}} + object "s0004" {code{}} + object "s0005" {code{}} + object "s0006" {code{}} + object "s0007" {code{}} + object "s0008" {code{}} + object "s0009" {code{}} + object "s0010" {code{}} + object "s0011" {code{}} + object "s0012" {code{}} + object "s0013" {code{}} + object "s0014" {code{}} + object "s0015" {code{}} + object "s0016" {code{}} + object "s0017" {code{}} + object "s0018" {code{}} + object "s0019" {code{}} + object "s0020" {code{}} + object "s0021" {code{}} + object "s0022" {code{}} + object "s0023" {code{}} + object "s0024" {code{}} + object "s0025" {code{}} + object "s0026" {code{}} + object "s0027" {code{}} + object "s0028" {code{}} + object "s0029" {code{}} + object "s0030" {code{}} + object "s0031" {code{}} + object "s0032" {code{}} + object "s0033" {code{}} + object "s0034" {code{}} + object "s0035" {code{}} + object "s0036" {code{}} + object "s0037" {code{}} + object "s0038" {code{}} + object "s0039" {code{}} + object "s0040" {code{}} + object "s0041" {code{}} + object "s0042" {code{}} + object "s0043" {code{}} + object "s0044" {code{}} + object "s0045" {code{}} + object "s0046" {code{}} + object "s0047" {code{}} + object "s0048" {code{}} + object "s0049" {code{}} + object "s0050" {code{}} + object "s0051" {code{}} + object "s0052" {code{}} + object "s0053" {code{}} + object "s0054" {code{}} + object "s0055" {code{}} + object "s0056" {code{}} + object "s0057" {code{}} + object "s0058" {code{}} + object "s0059" {code{}} + object "s0060" {code{}} + object "s0061" {code{}} + object "s0062" {code{}} + object "s0063" {code{}} + object "s0064" {code{}} + object "s0065" {code{}} + object "s0066" {code{}} + object "s0067" {code{}} + object "s0068" {code{}} + object "s0069" {code{}} + object "s0070" {code{}} + object "s0071" {code{}} + object "s0072" {code{}} + object "s0073" {code{}} + object "s0074" {code{}} + object "s0075" {code{}} + object "s0076" {code{}} + object "s0077" {code{}} + object "s0078" {code{}} + object "s0079" {code{}} + object "s0080" {code{}} + object "s0081" {code{}} + object "s0082" {code{}} + object "s0083" {code{}} + object "s0084" {code{}} + object "s0085" {code{}} + object "s0086" {code{}} + object "s0087" {code{}} + object "s0088" {code{}} + object "s0089" {code{}} + object "s0090" {code{}} + object "s0091" {code{}} + object "s0092" {code{}} + object "s0093" {code{}} + object "s0094" {code{}} + object "s0095" {code{}} + object "s0096" {code{}} + object "s0097" {code{}} + object "s0098" {code{}} + object "s0099" {code{}} + object "s0100" {code{}} + object "s0101" {code{}} + object "s0102" {code{}} + object "s0103" {code{}} + object "s0104" {code{}} + object "s0105" {code{}} + object "s0106" {code{}} + object "s0107" {code{}} + object "s0108" {code{}} + object "s0109" {code{}} + object "s0110" {code{}} + object "s0111" {code{}} + object "s0112" {code{}} + object "s0113" {code{}} + object "s0114" {code{}} + object "s0115" {code{}} + object "s0116" {code{}} + object "s0117" {code{}} + object "s0118" {code{}} + object "s0119" {code{}} + object "s0120" {code{}} + object "s0121" {code{}} + object "s0122" {code{}} + object "s0123" {code{}} + object "s0124" {code{}} + object "s0125" {code{}} + object "s0126" {code{}} + object "s0127" {code{}} + object "s0128" {code{}} + object "s0129" {code{}} + object "s0130" {code{}} + object "s0131" {code{}} + object "s0132" {code{}} + object "s0133" {code{}} + object "s0134" {code{}} + object "s0135" {code{}} + object "s0136" {code{}} + object "s0137" {code{}} + object "s0138" {code{}} + object "s0139" {code{}} + object "s0140" {code{}} + object "s0141" {code{}} + object "s0142" {code{}} + object "s0143" {code{}} + object "s0144" {code{}} + object "s0145" {code{}} + object "s0146" {code{}} + object "s0147" {code{}} + object "s0148" {code{}} + object "s0149" {code{}} + object "s0150" {code{}} + object "s0151" {code{}} + object "s0152" {code{}} + object "s0153" {code{}} + object "s0154" {code{}} + object "s0155" {code{}} + object "s0156" {code{}} + object "s0157" {code{}} + object "s0158" {code{}} + object "s0159" {code{}} + object "s0160" {code{}} + object "s0161" {code{}} + object "s0162" {code{}} + object "s0163" {code{}} + object "s0164" {code{}} + object "s0165" {code{}} + object "s0166" {code{}} + object "s0167" {code{}} + object "s0168" {code{}} + object "s0169" {code{}} + object "s0170" {code{}} + object "s0171" {code{}} + object "s0172" {code{}} + object "s0173" {code{}} + object "s0174" {code{}} + object "s0175" {code{}} + object "s0176" {code{}} + object "s0177" {code{}} + object "s0178" {code{}} + object "s0179" {code{}} + object "s0180" {code{}} + object "s0181" {code{}} + object "s0182" {code{}} + object "s0183" {code{}} + object "s0184" {code{}} + object "s0185" {code{}} + object "s0186" {code{}} + object "s0187" {code{}} + object "s0188" {code{}} + object "s0189" {code{}} + object "s0190" {code{}} + object "s0191" {code{}} + object "s0192" {code{}} + object "s0193" {code{}} + object "s0194" {code{}} + object "s0195" {code{}} + object "s0196" {code{}} + object "s0197" {code{}} + object "s0198" {code{}} + object "s0199" {code{}} + object "s0200" {code{}} + object "s0201" {code{}} + object "s0202" {code{}} + object "s0203" {code{}} + object "s0204" {code{}} + object "s0205" {code{}} + object "s0206" {code{}} + object "s0207" {code{}} + object "s0208" {code{}} + object "s0209" {code{}} + object "s0210" {code{}} + object "s0211" {code{}} + object "s0212" {code{}} + object "s0213" {code{}} + object "s0214" {code{}} + object "s0215" {code{}} + object "s0216" {code{}} + object "s0217" {code{}} + object "s0218" {code{}} + object "s0219" {code{}} + object "s0220" {code{}} + object "s0221" {code{}} + object "s0222" {code{}} + object "s0223" {code{}} + object "s0224" {code{}} + object "s0225" {code{}} + object "s0226" {code{}} + object "s0227" {code{}} + object "s0228" {code{}} + object "s0229" {code{}} + object "s0230" {code{}} + object "s0231" {code{}} + object "s0232" {code{}} + object "s0233" {code{}} + object "s0234" {code{}} + object "s0235" {code{}} + object "s0236" {code{}} + object "s0237" {code{}} + object "s0238" {code{}} + object "s0239" {code{}} + object "s0240" {code{}} + object "s0241" {code{}} + object "s0242" {code{}} + object "s0243" {code{}} + object "s0244" {code{}} + object "s0245" {code{}} + object "s0246" {code{}} + object "s0247" {code{}} + object "s0248" {code{}} + object "s0249" {code{}} + object "s0250" {code{}} + object "s0251" {code{}} + object "s0252" {code{}} + object "s0253" {code{}} + object "s0254" {code{}} + object "s0255" {code{}} +} + +// ==== +// EVMVersion: >=prague +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":78:79 */ +// 0x00 +// /* "source":50:80 */ +// dup1 +// dup1 +// dup1 +// eofcreate{0} +// /* "source":46:81 */ +// pop +// /* "source":126:127 */ +// 0x00 +// /* "source":98:128 */ +// dup1 +// dup1 +// dup1 +// eofcreate{1} +// /* "source":94:129 */ +// pop +// /* "source":174:175 */ +// 0x00 +// /* "source":146:176 */ +// dup1 +// dup1 +// dup1 +// eofcreate{2} +// /* "source":142:177 */ +// pop +// /* "source":222:223 */ +// 0x00 +// /* "source":194:224 */ +// dup1 +// dup1 +// dup1 +// eofcreate{3} +// /* "source":190:225 */ +// pop +// /* "source":270:271 */ +// 0x00 +// /* "source":242:272 */ +// dup1 +// dup1 +// dup1 +// eofcreate{4} +// /* "source":238:273 */ +// pop +// /* "source":318:319 */ +// 0x00 +// /* "source":290:320 */ +// dup1 +// dup1 +// dup1 +// eofcreate{5} +// /* "source":286:321 */ +// pop +// /* "source":366:367 */ +// 0x00 +// /* "source":338:368 */ +// dup1 +// dup1 +// dup1 +// eofcreate{6} +// /* "source":334:369 */ +// pop +// /* "source":414:415 */ +// 0x00 +// /* "source":386:416 */ +// dup1 +// dup1 +// dup1 +// eofcreate{7} +// /* "source":382:417 */ +// pop +// /* "source":462:463 */ +// 0x00 +// /* "source":434:464 */ +// dup1 +// dup1 +// dup1 +// eofcreate{8} +// /* "source":430:465 */ +// pop +// /* "source":510:511 */ +// 0x00 +// /* "source":482:512 */ +// dup1 +// dup1 +// dup1 +// eofcreate{9} +// /* "source":478:513 */ +// pop +// /* "source":558:559 */ +// 0x00 +// /* "source":530:560 */ +// dup1 +// dup1 +// dup1 +// eofcreate{10} +// /* "source":526:561 */ +// pop +// /* "source":606:607 */ +// 0x00 +// /* "source":578:608 */ +// dup1 +// dup1 +// dup1 +// eofcreate{11} +// /* "source":574:609 */ +// pop +// /* "source":654:655 */ +// 0x00 +// /* "source":626:656 */ +// dup1 +// dup1 +// dup1 +// eofcreate{12} +// /* "source":622:657 */ +// pop +// /* "source":702:703 */ +// 0x00 +// /* "source":674:704 */ +// dup1 +// dup1 +// dup1 +// eofcreate{13} +// /* "source":670:705 */ +// pop +// /* "source":750:751 */ +// 0x00 +// /* "source":722:752 */ +// dup1 +// dup1 +// dup1 +// eofcreate{14} +// /* "source":718:753 */ +// pop +// /* "source":798:799 */ +// 0x00 +// /* "source":770:800 */ +// dup1 +// dup1 +// dup1 +// eofcreate{15} +// /* "source":766:801 */ +// pop +// /* "source":846:847 */ +// 0x00 +// /* "source":818:848 */ +// dup1 +// dup1 +// dup1 +// eofcreate{16} +// /* "source":814:849 */ +// pop +// /* "source":894:895 */ +// 0x00 +// /* "source":866:896 */ +// dup1 +// dup1 +// dup1 +// eofcreate{17} +// /* "source":862:897 */ +// pop +// /* "source":942:943 */ +// 0x00 +// /* "source":914:944 */ +// dup1 +// dup1 +// dup1 +// eofcreate{18} +// /* "source":910:945 */ +// pop +// /* "source":990:991 */ +// 0x00 +// /* "source":962:992 */ +// dup1 +// dup1 +// dup1 +// eofcreate{19} +// /* "source":958:993 */ +// pop +// /* "source":1038:1039 */ +// 0x00 +// /* "source":1010:1040 */ +// dup1 +// dup1 +// dup1 +// eofcreate{20} +// /* "source":1006:1041 */ +// pop +// /* "source":1086:1087 */ +// 0x00 +// /* "source":1058:1088 */ +// dup1 +// dup1 +// dup1 +// eofcreate{21} +// /* "source":1054:1089 */ +// pop +// /* "source":1134:1135 */ +// 0x00 +// /* "source":1106:1136 */ +// dup1 +// dup1 +// dup1 +// eofcreate{22} +// /* "source":1102:1137 */ +// pop +// /* "source":1182:1183 */ +// 0x00 +// /* "source":1154:1184 */ +// dup1 +// dup1 +// dup1 +// eofcreate{23} +// /* "source":1150:1185 */ +// pop +// /* "source":1230:1231 */ +// 0x00 +// /* "source":1202:1232 */ +// dup1 +// dup1 +// dup1 +// eofcreate{24} +// /* "source":1198:1233 */ +// pop +// /* "source":1278:1279 */ +// 0x00 +// /* "source":1250:1280 */ +// dup1 +// dup1 +// dup1 +// eofcreate{25} +// /* "source":1246:1281 */ +// pop +// /* "source":1326:1327 */ +// 0x00 +// /* "source":1298:1328 */ +// dup1 +// dup1 +// dup1 +// eofcreate{26} +// /* "source":1294:1329 */ +// pop +// /* "source":1374:1375 */ +// 0x00 +// /* "source":1346:1376 */ +// dup1 +// dup1 +// dup1 +// eofcreate{27} +// /* "source":1342:1377 */ +// pop +// /* "source":1422:1423 */ +// 0x00 +// /* "source":1394:1424 */ +// dup1 +// dup1 +// dup1 +// eofcreate{28} +// /* "source":1390:1425 */ +// pop +// /* "source":1470:1471 */ +// 0x00 +// /* "source":1442:1472 */ +// dup1 +// dup1 +// dup1 +// eofcreate{29} +// /* "source":1438:1473 */ +// pop +// /* "source":1518:1519 */ +// 0x00 +// /* "source":1490:1520 */ +// dup1 +// dup1 +// dup1 +// eofcreate{30} +// /* "source":1486:1521 */ +// pop +// /* "source":1566:1567 */ +// 0x00 +// /* "source":1538:1568 */ +// dup1 +// dup1 +// dup1 +// eofcreate{31} +// /* "source":1534:1569 */ +// pop +// /* "source":1614:1615 */ +// 0x00 +// /* "source":1586:1616 */ +// dup1 +// dup1 +// dup1 +// eofcreate{32} +// /* "source":1582:1617 */ +// pop +// /* "source":1662:1663 */ +// 0x00 +// /* "source":1634:1664 */ +// dup1 +// dup1 +// dup1 +// eofcreate{33} +// /* "source":1630:1665 */ +// pop +// /* "source":1710:1711 */ +// 0x00 +// /* "source":1682:1712 */ +// dup1 +// dup1 +// dup1 +// eofcreate{34} +// /* "source":1678:1713 */ +// pop +// /* "source":1758:1759 */ +// 0x00 +// /* "source":1730:1760 */ +// dup1 +// dup1 +// dup1 +// eofcreate{35} +// /* "source":1726:1761 */ +// pop +// /* "source":1806:1807 */ +// 0x00 +// /* "source":1778:1808 */ +// dup1 +// dup1 +// dup1 +// eofcreate{36} +// /* "source":1774:1809 */ +// pop +// /* "source":1854:1855 */ +// 0x00 +// /* "source":1826:1856 */ +// dup1 +// dup1 +// dup1 +// eofcreate{37} +// /* "source":1822:1857 */ +// pop +// /* "source":1902:1903 */ +// 0x00 +// /* "source":1874:1904 */ +// dup1 +// dup1 +// dup1 +// eofcreate{38} +// /* "source":1870:1905 */ +// pop +// /* "source":1950:1951 */ +// 0x00 +// /* "source":1922:1952 */ +// dup1 +// dup1 +// dup1 +// eofcreate{39} +// /* "source":1918:1953 */ +// pop +// /* "source":1998:1999 */ +// 0x00 +// /* "source":1970:2000 */ +// dup1 +// dup1 +// dup1 +// eofcreate{40} +// /* "source":1966:2001 */ +// pop +// /* "source":2046:2047 */ +// 0x00 +// /* "source":2018:2048 */ +// dup1 +// dup1 +// dup1 +// eofcreate{41} +// /* "source":2014:2049 */ +// pop +// /* "source":2094:2095 */ +// 0x00 +// /* "source":2066:2096 */ +// dup1 +// dup1 +// dup1 +// eofcreate{42} +// /* "source":2062:2097 */ +// pop +// /* "source":2142:2143 */ +// 0x00 +// /* "source":2114:2144 */ +// dup1 +// dup1 +// dup1 +// eofcreate{43} +// /* "source":2110:2145 */ +// pop +// /* "source":2190:2191 */ +// 0x00 +// /* "source":2162:2192 */ +// dup1 +// dup1 +// dup1 +// eofcreate{44} +// /* "source":2158:2193 */ +// pop +// /* "source":2238:2239 */ +// 0x00 +// /* "source":2210:2240 */ +// dup1 +// dup1 +// dup1 +// eofcreate{45} +// /* "source":2206:2241 */ +// pop +// /* "source":2286:2287 */ +// 0x00 +// /* "source":2258:2288 */ +// dup1 +// dup1 +// dup1 +// eofcreate{46} +// /* "source":2254:2289 */ +// pop +// /* "source":2334:2335 */ +// 0x00 +// /* "source":2306:2336 */ +// dup1 +// dup1 +// dup1 +// eofcreate{47} +// /* "source":2302:2337 */ +// pop +// /* "source":2382:2383 */ +// 0x00 +// /* "source":2354:2384 */ +// dup1 +// dup1 +// dup1 +// eofcreate{48} +// /* "source":2350:2385 */ +// pop +// /* "source":2430:2431 */ +// 0x00 +// /* "source":2402:2432 */ +// dup1 +// dup1 +// dup1 +// eofcreate{49} +// /* "source":2398:2433 */ +// pop +// /* "source":2478:2479 */ +// 0x00 +// /* "source":2450:2480 */ +// dup1 +// dup1 +// dup1 +// eofcreate{50} +// /* "source":2446:2481 */ +// pop +// /* "source":2526:2527 */ +// 0x00 +// /* "source":2498:2528 */ +// dup1 +// dup1 +// dup1 +// eofcreate{51} +// /* "source":2494:2529 */ +// pop +// /* "source":2574:2575 */ +// 0x00 +// /* "source":2546:2576 */ +// dup1 +// dup1 +// dup1 +// eofcreate{52} +// /* "source":2542:2577 */ +// pop +// /* "source":2622:2623 */ +// 0x00 +// /* "source":2594:2624 */ +// dup1 +// dup1 +// dup1 +// eofcreate{53} +// /* "source":2590:2625 */ +// pop +// /* "source":2670:2671 */ +// 0x00 +// /* "source":2642:2672 */ +// dup1 +// dup1 +// dup1 +// eofcreate{54} +// /* "source":2638:2673 */ +// pop +// /* "source":2718:2719 */ +// 0x00 +// /* "source":2690:2720 */ +// dup1 +// dup1 +// dup1 +// eofcreate{55} +// /* "source":2686:2721 */ +// pop +// /* "source":2766:2767 */ +// 0x00 +// /* "source":2738:2768 */ +// dup1 +// dup1 +// dup1 +// eofcreate{56} +// /* "source":2734:2769 */ +// pop +// /* "source":2814:2815 */ +// 0x00 +// /* "source":2786:2816 */ +// dup1 +// dup1 +// dup1 +// eofcreate{57} +// /* "source":2782:2817 */ +// pop +// /* "source":2862:2863 */ +// 0x00 +// /* "source":2834:2864 */ +// dup1 +// dup1 +// dup1 +// eofcreate{58} +// /* "source":2830:2865 */ +// pop +// /* "source":2910:2911 */ +// 0x00 +// /* "source":2882:2912 */ +// dup1 +// dup1 +// dup1 +// eofcreate{59} +// /* "source":2878:2913 */ +// pop +// /* "source":2958:2959 */ +// 0x00 +// /* "source":2930:2960 */ +// dup1 +// dup1 +// dup1 +// eofcreate{60} +// /* "source":2926:2961 */ +// pop +// /* "source":3006:3007 */ +// 0x00 +// /* "source":2978:3008 */ +// dup1 +// dup1 +// dup1 +// eofcreate{61} +// /* "source":2974:3009 */ +// pop +// /* "source":3054:3055 */ +// 0x00 +// /* "source":3026:3056 */ +// dup1 +// dup1 +// dup1 +// eofcreate{62} +// /* "source":3022:3057 */ +// pop +// /* "source":3102:3103 */ +// 0x00 +// /* "source":3074:3104 */ +// dup1 +// dup1 +// dup1 +// eofcreate{63} +// /* "source":3070:3105 */ +// pop +// /* "source":3150:3151 */ +// 0x00 +// /* "source":3122:3152 */ +// dup1 +// dup1 +// dup1 +// eofcreate{64} +// /* "source":3118:3153 */ +// pop +// /* "source":3198:3199 */ +// 0x00 +// /* "source":3170:3200 */ +// dup1 +// dup1 +// dup1 +// eofcreate{65} +// /* "source":3166:3201 */ +// pop +// /* "source":3246:3247 */ +// 0x00 +// /* "source":3218:3248 */ +// dup1 +// dup1 +// dup1 +// eofcreate{66} +// /* "source":3214:3249 */ +// pop +// /* "source":3294:3295 */ +// 0x00 +// /* "source":3266:3296 */ +// dup1 +// dup1 +// dup1 +// eofcreate{67} +// /* "source":3262:3297 */ +// pop +// /* "source":3342:3343 */ +// 0x00 +// /* "source":3314:3344 */ +// dup1 +// dup1 +// dup1 +// eofcreate{68} +// /* "source":3310:3345 */ +// pop +// /* "source":3390:3391 */ +// 0x00 +// /* "source":3362:3392 */ +// dup1 +// dup1 +// dup1 +// eofcreate{69} +// /* "source":3358:3393 */ +// pop +// /* "source":3438:3439 */ +// 0x00 +// /* "source":3410:3440 */ +// dup1 +// dup1 +// dup1 +// eofcreate{70} +// /* "source":3406:3441 */ +// pop +// /* "source":3486:3487 */ +// 0x00 +// /* "source":3458:3488 */ +// dup1 +// dup1 +// dup1 +// eofcreate{71} +// /* "source":3454:3489 */ +// pop +// /* "source":3534:3535 */ +// 0x00 +// /* "source":3506:3536 */ +// dup1 +// dup1 +// dup1 +// eofcreate{72} +// /* "source":3502:3537 */ +// pop +// /* "source":3582:3583 */ +// 0x00 +// /* "source":3554:3584 */ +// dup1 +// dup1 +// dup1 +// eofcreate{73} +// /* "source":3550:3585 */ +// pop +// /* "source":3630:3631 */ +// 0x00 +// /* "source":3602:3632 */ +// dup1 +// dup1 +// dup1 +// eofcreate{74} +// /* "source":3598:3633 */ +// pop +// /* "source":3678:3679 */ +// 0x00 +// /* "source":3650:3680 */ +// dup1 +// dup1 +// dup1 +// eofcreate{75} +// /* "source":3646:3681 */ +// pop +// /* "source":3726:3727 */ +// 0x00 +// /* "source":3698:3728 */ +// dup1 +// dup1 +// dup1 +// eofcreate{76} +// /* "source":3694:3729 */ +// pop +// /* "source":3774:3775 */ +// 0x00 +// /* "source":3746:3776 */ +// dup1 +// dup1 +// dup1 +// eofcreate{77} +// /* "source":3742:3777 */ +// pop +// /* "source":3822:3823 */ +// 0x00 +// /* "source":3794:3824 */ +// dup1 +// dup1 +// dup1 +// eofcreate{78} +// /* "source":3790:3825 */ +// pop +// /* "source":3870:3871 */ +// 0x00 +// /* "source":3842:3872 */ +// dup1 +// dup1 +// dup1 +// eofcreate{79} +// /* "source":3838:3873 */ +// pop +// /* "source":3918:3919 */ +// 0x00 +// /* "source":3890:3920 */ +// dup1 +// dup1 +// dup1 +// eofcreate{80} +// /* "source":3886:3921 */ +// pop +// /* "source":3966:3967 */ +// 0x00 +// /* "source":3938:3968 */ +// dup1 +// dup1 +// dup1 +// eofcreate{81} +// /* "source":3934:3969 */ +// pop +// /* "source":4014:4015 */ +// 0x00 +// /* "source":3986:4016 */ +// dup1 +// dup1 +// dup1 +// eofcreate{82} +// /* "source":3982:4017 */ +// pop +// /* "source":4062:4063 */ +// 0x00 +// /* "source":4034:4064 */ +// dup1 +// dup1 +// dup1 +// eofcreate{83} +// /* "source":4030:4065 */ +// pop +// /* "source":4110:4111 */ +// 0x00 +// /* "source":4082:4112 */ +// dup1 +// dup1 +// dup1 +// eofcreate{84} +// /* "source":4078:4113 */ +// pop +// /* "source":4158:4159 */ +// 0x00 +// /* "source":4130:4160 */ +// dup1 +// dup1 +// dup1 +// eofcreate{85} +// /* "source":4126:4161 */ +// pop +// /* "source":4206:4207 */ +// 0x00 +// /* "source":4178:4208 */ +// dup1 +// dup1 +// dup1 +// eofcreate{86} +// /* "source":4174:4209 */ +// pop +// /* "source":4254:4255 */ +// 0x00 +// /* "source":4226:4256 */ +// dup1 +// dup1 +// dup1 +// eofcreate{87} +// /* "source":4222:4257 */ +// pop +// /* "source":4302:4303 */ +// 0x00 +// /* "source":4274:4304 */ +// dup1 +// dup1 +// dup1 +// eofcreate{88} +// /* "source":4270:4305 */ +// pop +// /* "source":4350:4351 */ +// 0x00 +// /* "source":4322:4352 */ +// dup1 +// dup1 +// dup1 +// eofcreate{89} +// /* "source":4318:4353 */ +// pop +// /* "source":4398:4399 */ +// 0x00 +// /* "source":4370:4400 */ +// dup1 +// dup1 +// dup1 +// eofcreate{90} +// /* "source":4366:4401 */ +// pop +// /* "source":4446:4447 */ +// 0x00 +// /* "source":4418:4448 */ +// dup1 +// dup1 +// dup1 +// eofcreate{91} +// /* "source":4414:4449 */ +// pop +// /* "source":4494:4495 */ +// 0x00 +// /* "source":4466:4496 */ +// dup1 +// dup1 +// dup1 +// eofcreate{92} +// /* "source":4462:4497 */ +// pop +// /* "source":4542:4543 */ +// 0x00 +// /* "source":4514:4544 */ +// dup1 +// dup1 +// dup1 +// eofcreate{93} +// /* "source":4510:4545 */ +// pop +// /* "source":4590:4591 */ +// 0x00 +// /* "source":4562:4592 */ +// dup1 +// dup1 +// dup1 +// eofcreate{94} +// /* "source":4558:4593 */ +// pop +// /* "source":4638:4639 */ +// 0x00 +// /* "source":4610:4640 */ +// dup1 +// dup1 +// dup1 +// eofcreate{95} +// /* "source":4606:4641 */ +// pop +// /* "source":4686:4687 */ +// 0x00 +// /* "source":4658:4688 */ +// dup1 +// dup1 +// dup1 +// eofcreate{96} +// /* "source":4654:4689 */ +// pop +// /* "source":4734:4735 */ +// 0x00 +// /* "source":4706:4736 */ +// dup1 +// dup1 +// dup1 +// eofcreate{97} +// /* "source":4702:4737 */ +// pop +// /* "source":4782:4783 */ +// 0x00 +// /* "source":4754:4784 */ +// dup1 +// dup1 +// dup1 +// eofcreate{98} +// /* "source":4750:4785 */ +// pop +// /* "source":4830:4831 */ +// 0x00 +// /* "source":4802:4832 */ +// dup1 +// dup1 +// dup1 +// eofcreate{99} +// /* "source":4798:4833 */ +// pop +// /* "source":4878:4879 */ +// 0x00 +// /* "source":4850:4880 */ +// dup1 +// dup1 +// dup1 +// eofcreate{100} +// /* "source":4846:4881 */ +// pop +// /* "source":4926:4927 */ +// 0x00 +// /* "source":4898:4928 */ +// dup1 +// dup1 +// dup1 +// eofcreate{101} +// /* "source":4894:4929 */ +// pop +// /* "source":4974:4975 */ +// 0x00 +// /* "source":4946:4976 */ +// dup1 +// dup1 +// dup1 +// eofcreate{102} +// /* "source":4942:4977 */ +// pop +// /* "source":5022:5023 */ +// 0x00 +// /* "source":4994:5024 */ +// dup1 +// dup1 +// dup1 +// eofcreate{103} +// /* "source":4990:5025 */ +// pop +// /* "source":5070:5071 */ +// 0x00 +// /* "source":5042:5072 */ +// dup1 +// dup1 +// dup1 +// eofcreate{104} +// /* "source":5038:5073 */ +// pop +// /* "source":5118:5119 */ +// 0x00 +// /* "source":5090:5120 */ +// dup1 +// dup1 +// dup1 +// eofcreate{105} +// /* "source":5086:5121 */ +// pop +// /* "source":5166:5167 */ +// 0x00 +// /* "source":5138:5168 */ +// dup1 +// dup1 +// dup1 +// eofcreate{106} +// /* "source":5134:5169 */ +// pop +// /* "source":5214:5215 */ +// 0x00 +// /* "source":5186:5216 */ +// dup1 +// dup1 +// dup1 +// eofcreate{107} +// /* "source":5182:5217 */ +// pop +// /* "source":5262:5263 */ +// 0x00 +// /* "source":5234:5264 */ +// dup1 +// dup1 +// dup1 +// eofcreate{108} +// /* "source":5230:5265 */ +// pop +// /* "source":5310:5311 */ +// 0x00 +// /* "source":5282:5312 */ +// dup1 +// dup1 +// dup1 +// eofcreate{109} +// /* "source":5278:5313 */ +// pop +// /* "source":5358:5359 */ +// 0x00 +// /* "source":5330:5360 */ +// dup1 +// dup1 +// dup1 +// eofcreate{110} +// /* "source":5326:5361 */ +// pop +// /* "source":5406:5407 */ +// 0x00 +// /* "source":5378:5408 */ +// dup1 +// dup1 +// dup1 +// eofcreate{111} +// /* "source":5374:5409 */ +// pop +// /* "source":5454:5455 */ +// 0x00 +// /* "source":5426:5456 */ +// dup1 +// dup1 +// dup1 +// eofcreate{112} +// /* "source":5422:5457 */ +// pop +// /* "source":5502:5503 */ +// 0x00 +// /* "source":5474:5504 */ +// dup1 +// dup1 +// dup1 +// eofcreate{113} +// /* "source":5470:5505 */ +// pop +// /* "source":5550:5551 */ +// 0x00 +// /* "source":5522:5552 */ +// dup1 +// dup1 +// dup1 +// eofcreate{114} +// /* "source":5518:5553 */ +// pop +// /* "source":5598:5599 */ +// 0x00 +// /* "source":5570:5600 */ +// dup1 +// dup1 +// dup1 +// eofcreate{115} +// /* "source":5566:5601 */ +// pop +// /* "source":5646:5647 */ +// 0x00 +// /* "source":5618:5648 */ +// dup1 +// dup1 +// dup1 +// eofcreate{116} +// /* "source":5614:5649 */ +// pop +// /* "source":5694:5695 */ +// 0x00 +// /* "source":5666:5696 */ +// dup1 +// dup1 +// dup1 +// eofcreate{117} +// /* "source":5662:5697 */ +// pop +// /* "source":5742:5743 */ +// 0x00 +// /* "source":5714:5744 */ +// dup1 +// dup1 +// dup1 +// eofcreate{118} +// /* "source":5710:5745 */ +// pop +// /* "source":5790:5791 */ +// 0x00 +// /* "source":5762:5792 */ +// dup1 +// dup1 +// dup1 +// eofcreate{119} +// /* "source":5758:5793 */ +// pop +// /* "source":5838:5839 */ +// 0x00 +// /* "source":5810:5840 */ +// dup1 +// dup1 +// dup1 +// eofcreate{120} +// /* "source":5806:5841 */ +// pop +// /* "source":5886:5887 */ +// 0x00 +// /* "source":5858:5888 */ +// dup1 +// dup1 +// dup1 +// eofcreate{121} +// /* "source":5854:5889 */ +// pop +// /* "source":5934:5935 */ +// 0x00 +// /* "source":5906:5936 */ +// dup1 +// dup1 +// dup1 +// eofcreate{122} +// /* "source":5902:5937 */ +// pop +// /* "source":5982:5983 */ +// 0x00 +// /* "source":5954:5984 */ +// dup1 +// dup1 +// dup1 +// eofcreate{123} +// /* "source":5950:5985 */ +// pop +// /* "source":6030:6031 */ +// 0x00 +// /* "source":6002:6032 */ +// dup1 +// dup1 +// dup1 +// eofcreate{124} +// /* "source":5998:6033 */ +// pop +// /* "source":6078:6079 */ +// 0x00 +// /* "source":6050:6080 */ +// dup1 +// dup1 +// dup1 +// eofcreate{125} +// /* "source":6046:6081 */ +// pop +// /* "source":6126:6127 */ +// 0x00 +// /* "source":6098:6128 */ +// dup1 +// dup1 +// dup1 +// eofcreate{126} +// /* "source":6094:6129 */ +// pop +// /* "source":6174:6175 */ +// 0x00 +// /* "source":6146:6176 */ +// dup1 +// dup1 +// dup1 +// eofcreate{127} +// /* "source":6142:6177 */ +// pop +// /* "source":6222:6223 */ +// 0x00 +// /* "source":6194:6224 */ +// dup1 +// dup1 +// dup1 +// eofcreate{128} +// /* "source":6190:6225 */ +// pop +// /* "source":6270:6271 */ +// 0x00 +// /* "source":6242:6272 */ +// dup1 +// dup1 +// dup1 +// eofcreate{129} +// /* "source":6238:6273 */ +// pop +// /* "source":6318:6319 */ +// 0x00 +// /* "source":6290:6320 */ +// dup1 +// dup1 +// dup1 +// eofcreate{130} +// /* "source":6286:6321 */ +// pop +// /* "source":6366:6367 */ +// 0x00 +// /* "source":6338:6368 */ +// dup1 +// dup1 +// dup1 +// eofcreate{131} +// /* "source":6334:6369 */ +// pop +// /* "source":6414:6415 */ +// 0x00 +// /* "source":6386:6416 */ +// dup1 +// dup1 +// dup1 +// eofcreate{132} +// /* "source":6382:6417 */ +// pop +// /* "source":6462:6463 */ +// 0x00 +// /* "source":6434:6464 */ +// dup1 +// dup1 +// dup1 +// eofcreate{133} +// /* "source":6430:6465 */ +// pop +// /* "source":6510:6511 */ +// 0x00 +// /* "source":6482:6512 */ +// dup1 +// dup1 +// dup1 +// eofcreate{134} +// /* "source":6478:6513 */ +// pop +// /* "source":6558:6559 */ +// 0x00 +// /* "source":6530:6560 */ +// dup1 +// dup1 +// dup1 +// eofcreate{135} +// /* "source":6526:6561 */ +// pop +// /* "source":6606:6607 */ +// 0x00 +// /* "source":6578:6608 */ +// dup1 +// dup1 +// dup1 +// eofcreate{136} +// /* "source":6574:6609 */ +// pop +// /* "source":6654:6655 */ +// 0x00 +// /* "source":6626:6656 */ +// dup1 +// dup1 +// dup1 +// eofcreate{137} +// /* "source":6622:6657 */ +// pop +// /* "source":6702:6703 */ +// 0x00 +// /* "source":6674:6704 */ +// dup1 +// dup1 +// dup1 +// eofcreate{138} +// /* "source":6670:6705 */ +// pop +// /* "source":6750:6751 */ +// 0x00 +// /* "source":6722:6752 */ +// dup1 +// dup1 +// dup1 +// eofcreate{139} +// /* "source":6718:6753 */ +// pop +// /* "source":6798:6799 */ +// 0x00 +// /* "source":6770:6800 */ +// dup1 +// dup1 +// dup1 +// eofcreate{140} +// /* "source":6766:6801 */ +// pop +// /* "source":6846:6847 */ +// 0x00 +// /* "source":6818:6848 */ +// dup1 +// dup1 +// dup1 +// eofcreate{141} +// /* "source":6814:6849 */ +// pop +// /* "source":6894:6895 */ +// 0x00 +// /* "source":6866:6896 */ +// dup1 +// dup1 +// dup1 +// eofcreate{142} +// /* "source":6862:6897 */ +// pop +// /* "source":6942:6943 */ +// 0x00 +// /* "source":6914:6944 */ +// dup1 +// dup1 +// dup1 +// eofcreate{143} +// /* "source":6910:6945 */ +// pop +// /* "source":6990:6991 */ +// 0x00 +// /* "source":6962:6992 */ +// dup1 +// dup1 +// dup1 +// eofcreate{144} +// /* "source":6958:6993 */ +// pop +// /* "source":7038:7039 */ +// 0x00 +// /* "source":7010:7040 */ +// dup1 +// dup1 +// dup1 +// eofcreate{145} +// /* "source":7006:7041 */ +// pop +// /* "source":7086:7087 */ +// 0x00 +// /* "source":7058:7088 */ +// dup1 +// dup1 +// dup1 +// eofcreate{146} +// /* "source":7054:7089 */ +// pop +// /* "source":7134:7135 */ +// 0x00 +// /* "source":7106:7136 */ +// dup1 +// dup1 +// dup1 +// eofcreate{147} +// /* "source":7102:7137 */ +// pop +// /* "source":7182:7183 */ +// 0x00 +// /* "source":7154:7184 */ +// dup1 +// dup1 +// dup1 +// eofcreate{148} +// /* "source":7150:7185 */ +// pop +// /* "source":7230:7231 */ +// 0x00 +// /* "source":7202:7232 */ +// dup1 +// dup1 +// dup1 +// eofcreate{149} +// /* "source":7198:7233 */ +// pop +// /* "source":7278:7279 */ +// 0x00 +// /* "source":7250:7280 */ +// dup1 +// dup1 +// dup1 +// eofcreate{150} +// /* "source":7246:7281 */ +// pop +// /* "source":7326:7327 */ +// 0x00 +// /* "source":7298:7328 */ +// dup1 +// dup1 +// dup1 +// eofcreate{151} +// /* "source":7294:7329 */ +// pop +// /* "source":7374:7375 */ +// 0x00 +// /* "source":7346:7376 */ +// dup1 +// dup1 +// dup1 +// eofcreate{152} +// /* "source":7342:7377 */ +// pop +// /* "source":7422:7423 */ +// 0x00 +// /* "source":7394:7424 */ +// dup1 +// dup1 +// dup1 +// eofcreate{153} +// /* "source":7390:7425 */ +// pop +// /* "source":7470:7471 */ +// 0x00 +// /* "source":7442:7472 */ +// dup1 +// dup1 +// dup1 +// eofcreate{154} +// /* "source":7438:7473 */ +// pop +// /* "source":7518:7519 */ +// 0x00 +// /* "source":7490:7520 */ +// dup1 +// dup1 +// dup1 +// eofcreate{155} +// /* "source":7486:7521 */ +// pop +// /* "source":7566:7567 */ +// 0x00 +// /* "source":7538:7568 */ +// dup1 +// dup1 +// dup1 +// eofcreate{156} +// /* "source":7534:7569 */ +// pop +// /* "source":7614:7615 */ +// 0x00 +// /* "source":7586:7616 */ +// dup1 +// dup1 +// dup1 +// eofcreate{157} +// /* "source":7582:7617 */ +// pop +// /* "source":7662:7663 */ +// 0x00 +// /* "source":7634:7664 */ +// dup1 +// dup1 +// dup1 +// eofcreate{158} +// /* "source":7630:7665 */ +// pop +// /* "source":7710:7711 */ +// 0x00 +// /* "source":7682:7712 */ +// dup1 +// dup1 +// dup1 +// eofcreate{159} +// /* "source":7678:7713 */ +// pop +// /* "source":7758:7759 */ +// 0x00 +// /* "source":7730:7760 */ +// dup1 +// dup1 +// dup1 +// eofcreate{160} +// /* "source":7726:7761 */ +// pop +// /* "source":7806:7807 */ +// 0x00 +// /* "source":7778:7808 */ +// dup1 +// dup1 +// dup1 +// eofcreate{161} +// /* "source":7774:7809 */ +// pop +// /* "source":7854:7855 */ +// 0x00 +// /* "source":7826:7856 */ +// dup1 +// dup1 +// dup1 +// eofcreate{162} +// /* "source":7822:7857 */ +// pop +// /* "source":7902:7903 */ +// 0x00 +// /* "source":7874:7904 */ +// dup1 +// dup1 +// dup1 +// eofcreate{163} +// /* "source":7870:7905 */ +// pop +// /* "source":7950:7951 */ +// 0x00 +// /* "source":7922:7952 */ +// dup1 +// dup1 +// dup1 +// eofcreate{164} +// /* "source":7918:7953 */ +// pop +// /* "source":7998:7999 */ +// 0x00 +// /* "source":7970:8000 */ +// dup1 +// dup1 +// dup1 +// eofcreate{165} +// /* "source":7966:8001 */ +// pop +// /* "source":8046:8047 */ +// 0x00 +// /* "source":8018:8048 */ +// dup1 +// dup1 +// dup1 +// eofcreate{166} +// /* "source":8014:8049 */ +// pop +// /* "source":8094:8095 */ +// 0x00 +// /* "source":8066:8096 */ +// dup1 +// dup1 +// dup1 +// eofcreate{167} +// /* "source":8062:8097 */ +// pop +// /* "source":8142:8143 */ +// 0x00 +// /* "source":8114:8144 */ +// dup1 +// dup1 +// dup1 +// eofcreate{168} +// /* "source":8110:8145 */ +// pop +// /* "source":8190:8191 */ +// 0x00 +// /* "source":8162:8192 */ +// dup1 +// dup1 +// dup1 +// eofcreate{169} +// /* "source":8158:8193 */ +// pop +// /* "source":8238:8239 */ +// 0x00 +// /* "source":8210:8240 */ +// dup1 +// dup1 +// dup1 +// eofcreate{170} +// /* "source":8206:8241 */ +// pop +// /* "source":8286:8287 */ +// 0x00 +// /* "source":8258:8288 */ +// dup1 +// dup1 +// dup1 +// eofcreate{171} +// /* "source":8254:8289 */ +// pop +// /* "source":8334:8335 */ +// 0x00 +// /* "source":8306:8336 */ +// dup1 +// dup1 +// dup1 +// eofcreate{172} +// /* "source":8302:8337 */ +// pop +// /* "source":8382:8383 */ +// 0x00 +// /* "source":8354:8384 */ +// dup1 +// dup1 +// dup1 +// eofcreate{173} +// /* "source":8350:8385 */ +// pop +// /* "source":8430:8431 */ +// 0x00 +// /* "source":8402:8432 */ +// dup1 +// dup1 +// dup1 +// eofcreate{174} +// /* "source":8398:8433 */ +// pop +// /* "source":8478:8479 */ +// 0x00 +// /* "source":8450:8480 */ +// dup1 +// dup1 +// dup1 +// eofcreate{175} +// /* "source":8446:8481 */ +// pop +// /* "source":8526:8527 */ +// 0x00 +// /* "source":8498:8528 */ +// dup1 +// dup1 +// dup1 +// eofcreate{176} +// /* "source":8494:8529 */ +// pop +// /* "source":8574:8575 */ +// 0x00 +// /* "source":8546:8576 */ +// dup1 +// dup1 +// dup1 +// eofcreate{177} +// /* "source":8542:8577 */ +// pop +// /* "source":8622:8623 */ +// 0x00 +// /* "source":8594:8624 */ +// dup1 +// dup1 +// dup1 +// eofcreate{178} +// /* "source":8590:8625 */ +// pop +// /* "source":8670:8671 */ +// 0x00 +// /* "source":8642:8672 */ +// dup1 +// dup1 +// dup1 +// eofcreate{179} +// /* "source":8638:8673 */ +// pop +// /* "source":8718:8719 */ +// 0x00 +// /* "source":8690:8720 */ +// dup1 +// dup1 +// dup1 +// eofcreate{180} +// /* "source":8686:8721 */ +// pop +// /* "source":8766:8767 */ +// 0x00 +// /* "source":8738:8768 */ +// dup1 +// dup1 +// dup1 +// eofcreate{181} +// /* "source":8734:8769 */ +// pop +// /* "source":8814:8815 */ +// 0x00 +// /* "source":8786:8816 */ +// dup1 +// dup1 +// dup1 +// eofcreate{182} +// /* "source":8782:8817 */ +// pop +// /* "source":8862:8863 */ +// 0x00 +// /* "source":8834:8864 */ +// dup1 +// dup1 +// dup1 +// eofcreate{183} +// /* "source":8830:8865 */ +// pop +// /* "source":8910:8911 */ +// 0x00 +// /* "source":8882:8912 */ +// dup1 +// dup1 +// dup1 +// eofcreate{184} +// /* "source":8878:8913 */ +// pop +// /* "source":8958:8959 */ +// 0x00 +// /* "source":8930:8960 */ +// dup1 +// dup1 +// dup1 +// eofcreate{185} +// /* "source":8926:8961 */ +// pop +// /* "source":9006:9007 */ +// 0x00 +// /* "source":8978:9008 */ +// dup1 +// dup1 +// dup1 +// eofcreate{186} +// /* "source":8974:9009 */ +// pop +// /* "source":9054:9055 */ +// 0x00 +// /* "source":9026:9056 */ +// dup1 +// dup1 +// dup1 +// eofcreate{187} +// /* "source":9022:9057 */ +// pop +// /* "source":9102:9103 */ +// 0x00 +// /* "source":9074:9104 */ +// dup1 +// dup1 +// dup1 +// eofcreate{188} +// /* "source":9070:9105 */ +// pop +// /* "source":9150:9151 */ +// 0x00 +// /* "source":9122:9152 */ +// dup1 +// dup1 +// dup1 +// eofcreate{189} +// /* "source":9118:9153 */ +// pop +// /* "source":9198:9199 */ +// 0x00 +// /* "source":9170:9200 */ +// dup1 +// dup1 +// dup1 +// eofcreate{190} +// /* "source":9166:9201 */ +// pop +// /* "source":9246:9247 */ +// 0x00 +// /* "source":9218:9248 */ +// dup1 +// dup1 +// dup1 +// eofcreate{191} +// /* "source":9214:9249 */ +// pop +// /* "source":9294:9295 */ +// 0x00 +// /* "source":9266:9296 */ +// dup1 +// dup1 +// dup1 +// eofcreate{192} +// /* "source":9262:9297 */ +// pop +// /* "source":9342:9343 */ +// 0x00 +// /* "source":9314:9344 */ +// dup1 +// dup1 +// dup1 +// eofcreate{193} +// /* "source":9310:9345 */ +// pop +// /* "source":9390:9391 */ +// 0x00 +// /* "source":9362:9392 */ +// dup1 +// dup1 +// dup1 +// eofcreate{194} +// /* "source":9358:9393 */ +// pop +// /* "source":9438:9439 */ +// 0x00 +// /* "source":9410:9440 */ +// dup1 +// dup1 +// dup1 +// eofcreate{195} +// /* "source":9406:9441 */ +// pop +// /* "source":9486:9487 */ +// 0x00 +// /* "source":9458:9488 */ +// dup1 +// dup1 +// dup1 +// eofcreate{196} +// /* "source":9454:9489 */ +// pop +// /* "source":9534:9535 */ +// 0x00 +// /* "source":9506:9536 */ +// dup1 +// dup1 +// dup1 +// eofcreate{197} +// /* "source":9502:9537 */ +// pop +// /* "source":9582:9583 */ +// 0x00 +// /* "source":9554:9584 */ +// dup1 +// dup1 +// dup1 +// eofcreate{198} +// /* "source":9550:9585 */ +// pop +// /* "source":9630:9631 */ +// 0x00 +// /* "source":9602:9632 */ +// dup1 +// dup1 +// dup1 +// eofcreate{199} +// /* "source":9598:9633 */ +// pop +// /* "source":9678:9679 */ +// 0x00 +// /* "source":9650:9680 */ +// dup1 +// dup1 +// dup1 +// eofcreate{200} +// /* "source":9646:9681 */ +// pop +// /* "source":9726:9727 */ +// 0x00 +// /* "source":9698:9728 */ +// dup1 +// dup1 +// dup1 +// eofcreate{201} +// /* "source":9694:9729 */ +// pop +// /* "source":9774:9775 */ +// 0x00 +// /* "source":9746:9776 */ +// dup1 +// dup1 +// dup1 +// eofcreate{202} +// /* "source":9742:9777 */ +// pop +// /* "source":9822:9823 */ +// 0x00 +// /* "source":9794:9824 */ +// dup1 +// dup1 +// dup1 +// eofcreate{203} +// /* "source":9790:9825 */ +// pop +// /* "source":9870:9871 */ +// 0x00 +// /* "source":9842:9872 */ +// dup1 +// dup1 +// dup1 +// eofcreate{204} +// /* "source":9838:9873 */ +// pop +// /* "source":9918:9919 */ +// 0x00 +// /* "source":9890:9920 */ +// dup1 +// dup1 +// dup1 +// eofcreate{205} +// /* "source":9886:9921 */ +// pop +// /* "source":9966:9967 */ +// 0x00 +// /* "source":9938:9968 */ +// dup1 +// dup1 +// dup1 +// eofcreate{206} +// /* "source":9934:9969 */ +// pop +// /* "source":10014:10015 */ +// 0x00 +// /* "source":9986:10016 */ +// dup1 +// dup1 +// dup1 +// eofcreate{207} +// /* "source":9982:10017 */ +// pop +// /* "source":10062:10063 */ +// 0x00 +// /* "source":10034:10064 */ +// dup1 +// dup1 +// dup1 +// eofcreate{208} +// /* "source":10030:10065 */ +// pop +// /* "source":10110:10111 */ +// 0x00 +// /* "source":10082:10112 */ +// dup1 +// dup1 +// dup1 +// eofcreate{209} +// /* "source":10078:10113 */ +// pop +// /* "source":10158:10159 */ +// 0x00 +// /* "source":10130:10160 */ +// dup1 +// dup1 +// dup1 +// eofcreate{210} +// /* "source":10126:10161 */ +// pop +// /* "source":10206:10207 */ +// 0x00 +// /* "source":10178:10208 */ +// dup1 +// dup1 +// dup1 +// eofcreate{211} +// /* "source":10174:10209 */ +// pop +// /* "source":10254:10255 */ +// 0x00 +// /* "source":10226:10256 */ +// dup1 +// dup1 +// dup1 +// eofcreate{212} +// /* "source":10222:10257 */ +// pop +// /* "source":10302:10303 */ +// 0x00 +// /* "source":10274:10304 */ +// dup1 +// dup1 +// dup1 +// eofcreate{213} +// /* "source":10270:10305 */ +// pop +// /* "source":10350:10351 */ +// 0x00 +// /* "source":10322:10352 */ +// dup1 +// dup1 +// dup1 +// eofcreate{214} +// /* "source":10318:10353 */ +// pop +// /* "source":10398:10399 */ +// 0x00 +// /* "source":10370:10400 */ +// dup1 +// dup1 +// dup1 +// eofcreate{215} +// /* "source":10366:10401 */ +// pop +// /* "source":10446:10447 */ +// 0x00 +// /* "source":10418:10448 */ +// dup1 +// dup1 +// dup1 +// eofcreate{216} +// /* "source":10414:10449 */ +// pop +// /* "source":10494:10495 */ +// 0x00 +// /* "source":10466:10496 */ +// dup1 +// dup1 +// dup1 +// eofcreate{217} +// /* "source":10462:10497 */ +// pop +// /* "source":10542:10543 */ +// 0x00 +// /* "source":10514:10544 */ +// dup1 +// dup1 +// dup1 +// eofcreate{218} +// /* "source":10510:10545 */ +// pop +// /* "source":10590:10591 */ +// 0x00 +// /* "source":10562:10592 */ +// dup1 +// dup1 +// dup1 +// eofcreate{219} +// /* "source":10558:10593 */ +// pop +// /* "source":10638:10639 */ +// 0x00 +// /* "source":10610:10640 */ +// dup1 +// dup1 +// dup1 +// eofcreate{220} +// /* "source":10606:10641 */ +// pop +// /* "source":10686:10687 */ +// 0x00 +// /* "source":10658:10688 */ +// dup1 +// dup1 +// dup1 +// eofcreate{221} +// /* "source":10654:10689 */ +// pop +// /* "source":10734:10735 */ +// 0x00 +// /* "source":10706:10736 */ +// dup1 +// dup1 +// dup1 +// eofcreate{222} +// /* "source":10702:10737 */ +// pop +// /* "source":10782:10783 */ +// 0x00 +// /* "source":10754:10784 */ +// dup1 +// dup1 +// dup1 +// eofcreate{223} +// /* "source":10750:10785 */ +// pop +// /* "source":10830:10831 */ +// 0x00 +// /* "source":10802:10832 */ +// dup1 +// dup1 +// dup1 +// eofcreate{224} +// /* "source":10798:10833 */ +// pop +// /* "source":10878:10879 */ +// 0x00 +// /* "source":10850:10880 */ +// dup1 +// dup1 +// dup1 +// eofcreate{225} +// /* "source":10846:10881 */ +// pop +// /* "source":10926:10927 */ +// 0x00 +// /* "source":10898:10928 */ +// dup1 +// dup1 +// dup1 +// eofcreate{226} +// /* "source":10894:10929 */ +// pop +// /* "source":10974:10975 */ +// 0x00 +// /* "source":10946:10976 */ +// dup1 +// dup1 +// dup1 +// eofcreate{227} +// /* "source":10942:10977 */ +// pop +// /* "source":11022:11023 */ +// 0x00 +// /* "source":10994:11024 */ +// dup1 +// dup1 +// dup1 +// eofcreate{228} +// /* "source":10990:11025 */ +// pop +// /* "source":11070:11071 */ +// 0x00 +// /* "source":11042:11072 */ +// dup1 +// dup1 +// dup1 +// eofcreate{229} +// /* "source":11038:11073 */ +// pop +// /* "source":11118:11119 */ +// 0x00 +// /* "source":11090:11120 */ +// dup1 +// dup1 +// dup1 +// eofcreate{230} +// /* "source":11086:11121 */ +// pop +// /* "source":11166:11167 */ +// 0x00 +// /* "source":11138:11168 */ +// dup1 +// dup1 +// dup1 +// eofcreate{231} +// /* "source":11134:11169 */ +// pop +// /* "source":11214:11215 */ +// 0x00 +// /* "source":11186:11216 */ +// dup1 +// dup1 +// dup1 +// eofcreate{232} +// /* "source":11182:11217 */ +// pop +// /* "source":11262:11263 */ +// 0x00 +// /* "source":11234:11264 */ +// dup1 +// dup1 +// dup1 +// eofcreate{233} +// /* "source":11230:11265 */ +// pop +// /* "source":11310:11311 */ +// 0x00 +// /* "source":11282:11312 */ +// dup1 +// dup1 +// dup1 +// eofcreate{234} +// /* "source":11278:11313 */ +// pop +// /* "source":11358:11359 */ +// 0x00 +// /* "source":11330:11360 */ +// dup1 +// dup1 +// dup1 +// eofcreate{235} +// /* "source":11326:11361 */ +// pop +// /* "source":11406:11407 */ +// 0x00 +// /* "source":11378:11408 */ +// dup1 +// dup1 +// dup1 +// eofcreate{236} +// /* "source":11374:11409 */ +// pop +// /* "source":11454:11455 */ +// 0x00 +// /* "source":11426:11456 */ +// dup1 +// dup1 +// dup1 +// eofcreate{237} +// /* "source":11422:11457 */ +// pop +// /* "source":11502:11503 */ +// 0x00 +// /* "source":11474:11504 */ +// dup1 +// dup1 +// dup1 +// eofcreate{238} +// /* "source":11470:11505 */ +// pop +// /* "source":11550:11551 */ +// 0x00 +// /* "source":11522:11552 */ +// dup1 +// dup1 +// dup1 +// eofcreate{239} +// /* "source":11518:11553 */ +// pop +// /* "source":11598:11599 */ +// 0x00 +// /* "source":11570:11600 */ +// dup1 +// dup1 +// dup1 +// eofcreate{240} +// /* "source":11566:11601 */ +// pop +// /* "source":11646:11647 */ +// 0x00 +// /* "source":11618:11648 */ +// dup1 +// dup1 +// dup1 +// eofcreate{241} +// /* "source":11614:11649 */ +// pop +// /* "source":11694:11695 */ +// 0x00 +// /* "source":11666:11696 */ +// dup1 +// dup1 +// dup1 +// eofcreate{242} +// /* "source":11662:11697 */ +// pop +// /* "source":11742:11743 */ +// 0x00 +// /* "source":11714:11744 */ +// dup1 +// dup1 +// dup1 +// eofcreate{243} +// /* "source":11710:11745 */ +// pop +// /* "source":11790:11791 */ +// 0x00 +// /* "source":11762:11792 */ +// dup1 +// dup1 +// dup1 +// eofcreate{244} +// /* "source":11758:11793 */ +// pop +// /* "source":11838:11839 */ +// 0x00 +// /* "source":11810:11840 */ +// dup1 +// dup1 +// dup1 +// eofcreate{245} +// /* "source":11806:11841 */ +// pop +// /* "source":11886:11887 */ +// 0x00 +// /* "source":11858:11888 */ +// dup1 +// dup1 +// dup1 +// eofcreate{246} +// /* "source":11854:11889 */ +// pop +// /* "source":11934:11935 */ +// 0x00 +// /* "source":11906:11936 */ +// dup1 +// dup1 +// dup1 +// eofcreate{247} +// /* "source":11902:11937 */ +// pop +// /* "source":11982:11983 */ +// 0x00 +// /* "source":11954:11984 */ +// dup1 +// dup1 +// dup1 +// eofcreate{248} +// /* "source":11950:11985 */ +// pop +// /* "source":12030:12031 */ +// 0x00 +// /* "source":12002:12032 */ +// dup1 +// dup1 +// dup1 +// eofcreate{249} +// /* "source":11998:12033 */ +// pop +// /* "source":12078:12079 */ +// 0x00 +// /* "source":12050:12080 */ +// dup1 +// dup1 +// dup1 +// eofcreate{250} +// /* "source":12046:12081 */ +// pop +// /* "source":12126:12127 */ +// 0x00 +// /* "source":12098:12128 */ +// dup1 +// dup1 +// dup1 +// eofcreate{251} +// /* "source":12094:12129 */ +// pop +// /* "source":12174:12175 */ +// 0x00 +// /* "source":12146:12176 */ +// dup1 +// dup1 +// dup1 +// eofcreate{252} +// /* "source":12142:12177 */ +// pop +// /* "source":12222:12223 */ +// 0x00 +// /* "source":12194:12224 */ +// dup1 +// dup1 +// dup1 +// eofcreate{253} +// /* "source":12190:12225 */ +// pop +// /* "source":12270:12271 */ +// 0x00 +// /* "source":12242:12272 */ +// dup1 +// dup1 +// dup1 +// eofcreate{254} +// /* "source":12238:12273 */ +// pop +// /* "source":12318:12319 */ +// 0x00 +// /* "source":12290:12320 */ +// dup1 +// dup1 +// dup1 +// eofcreate{255} +// /* "source":12286:12321 */ +// pop +// /* "source":22:12337 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":12372:12379 */ +// stop +// } +// +// sub_1: assembly { +// /* "source":12420:12427 */ +// stop +// } +// +// sub_2: assembly { +// /* "source":12468:12475 */ +// stop +// } +// +// sub_3: assembly { +// /* "source":12516:12523 */ +// stop +// } +// +// sub_4: assembly { +// /* "source":12564:12571 */ +// stop +// } +// +// sub_5: assembly { +// /* "source":12612:12619 */ +// stop +// } +// +// sub_6: assembly { +// /* "source":12660:12667 */ +// stop +// } +// +// sub_7: assembly { +// /* "source":12708:12715 */ +// stop +// } +// +// sub_8: assembly { +// /* "source":12756:12763 */ +// stop +// } +// +// sub_9: assembly { +// /* "source":12804:12811 */ +// stop +// } +// +// sub_10: assembly { +// /* "source":12852:12859 */ +// stop +// } +// +// sub_11: assembly { +// /* "source":12900:12907 */ +// stop +// } +// +// sub_12: assembly { +// /* "source":12948:12955 */ +// stop +// } +// +// sub_13: assembly { +// /* "source":12996:13003 */ +// stop +// } +// +// sub_14: assembly { +// /* "source":13044:13051 */ +// stop +// } +// +// sub_15: assembly { +// /* "source":13092:13099 */ +// stop +// } +// +// sub_16: assembly { +// /* "source":13140:13147 */ +// stop +// } +// +// sub_17: assembly { +// /* "source":13188:13195 */ +// stop +// } +// +// sub_18: assembly { +// /* "source":13236:13243 */ +// stop +// } +// +// sub_19: assembly { +// /* "source":13284:13291 */ +// stop +// } +// +// sub_20: assembly { +// /* "source":13332:13339 */ +// stop +// } +// +// sub_21: assembly { +// /* "source":13380:13387 */ +// stop +// } +// +// sub_22: assembly { +// /* "source":13428:13435 */ +// stop +// } +// +// sub_23: assembly { +// /* "source":13476:13483 */ +// stop +// } +// +// sub_24: assembly { +// /* "source":13524:13531 */ +// stop +// } +// +// sub_25: assembly { +// /* "source":13572:13579 */ +// stop +// } +// +// sub_26: assembly { +// /* "source":13620:13627 */ +// stop +// } +// +// sub_27: assembly { +// /* "source":13668:13675 */ +// stop +// } +// +// sub_28: assembly { +// /* "source":13716:13723 */ +// stop +// } +// +// sub_29: assembly { +// /* "source":13764:13771 */ +// stop +// } +// +// sub_30: assembly { +// /* "source":13812:13819 */ +// stop +// } +// +// sub_31: assembly { +// /* "source":13860:13867 */ +// stop +// } +// +// sub_32: assembly { +// /* "source":13908:13915 */ +// stop +// } +// +// sub_33: assembly { +// /* "source":13956:13963 */ +// stop +// } +// +// sub_34: assembly { +// /* "source":14004:14011 */ +// stop +// } +// +// sub_35: assembly { +// /* "source":14052:14059 */ +// stop +// } +// +// sub_36: assembly { +// /* "source":14100:14107 */ +// stop +// } +// +// sub_37: assembly { +// /* "source":14148:14155 */ +// stop +// } +// +// sub_38: assembly { +// /* "source":14196:14203 */ +// stop +// } +// +// sub_39: assembly { +// /* "source":14244:14251 */ +// stop +// } +// +// sub_40: assembly { +// /* "source":14292:14299 */ +// stop +// } +// +// sub_41: assembly { +// /* "source":14340:14347 */ +// stop +// } +// +// sub_42: assembly { +// /* "source":14388:14395 */ +// stop +// } +// +// sub_43: assembly { +// /* "source":14436:14443 */ +// stop +// } +// +// sub_44: assembly { +// /* "source":14484:14491 */ +// stop +// } +// +// sub_45: assembly { +// /* "source":14532:14539 */ +// stop +// } +// +// sub_46: assembly { +// /* "source":14580:14587 */ +// stop +// } +// +// sub_47: assembly { +// /* "source":14628:14635 */ +// stop +// } +// +// sub_48: assembly { +// /* "source":14676:14683 */ +// stop +// } +// +// sub_49: assembly { +// /* "source":14724:14731 */ +// stop +// } +// +// sub_50: assembly { +// /* "source":14772:14779 */ +// stop +// } +// +// sub_51: assembly { +// /* "source":14820:14827 */ +// stop +// } +// +// sub_52: assembly { +// /* "source":14868:14875 */ +// stop +// } +// +// sub_53: assembly { +// /* "source":14916:14923 */ +// stop +// } +// +// sub_54: assembly { +// /* "source":14964:14971 */ +// stop +// } +// +// sub_55: assembly { +// /* "source":15012:15019 */ +// stop +// } +// +// sub_56: assembly { +// /* "source":15060:15067 */ +// stop +// } +// +// sub_57: assembly { +// /* "source":15108:15115 */ +// stop +// } +// +// sub_58: assembly { +// /* "source":15156:15163 */ +// stop +// } +// +// sub_59: assembly { +// /* "source":15204:15211 */ +// stop +// } +// +// sub_60: assembly { +// /* "source":15252:15259 */ +// stop +// } +// +// sub_61: assembly { +// /* "source":15300:15307 */ +// stop +// } +// +// sub_62: assembly { +// /* "source":15348:15355 */ +// stop +// } +// +// sub_63: assembly { +// /* "source":15396:15403 */ +// stop +// } +// +// sub_64: assembly { +// /* "source":15444:15451 */ +// stop +// } +// +// sub_65: assembly { +// /* "source":15492:15499 */ +// stop +// } +// +// sub_66: assembly { +// /* "source":15540:15547 */ +// stop +// } +// +// sub_67: assembly { +// /* "source":15588:15595 */ +// stop +// } +// +// sub_68: assembly { +// /* "source":15636:15643 */ +// stop +// } +// +// sub_69: assembly { +// /* "source":15684:15691 */ +// stop +// } +// +// sub_70: assembly { +// /* "source":15732:15739 */ +// stop +// } +// +// sub_71: assembly { +// /* "source":15780:15787 */ +// stop +// } +// +// sub_72: assembly { +// /* "source":15828:15835 */ +// stop +// } +// +// sub_73: assembly { +// /* "source":15876:15883 */ +// stop +// } +// +// sub_74: assembly { +// /* "source":15924:15931 */ +// stop +// } +// +// sub_75: assembly { +// /* "source":15972:15979 */ +// stop +// } +// +// sub_76: assembly { +// /* "source":16020:16027 */ +// stop +// } +// +// sub_77: assembly { +// /* "source":16068:16075 */ +// stop +// } +// +// sub_78: assembly { +// /* "source":16116:16123 */ +// stop +// } +// +// sub_79: assembly { +// /* "source":16164:16171 */ +// stop +// } +// +// sub_80: assembly { +// /* "source":16212:16219 */ +// stop +// } +// +// sub_81: assembly { +// /* "source":16260:16267 */ +// stop +// } +// +// sub_82: assembly { +// /* "source":16308:16315 */ +// stop +// } +// +// sub_83: assembly { +// /* "source":16356:16363 */ +// stop +// } +// +// sub_84: assembly { +// /* "source":16404:16411 */ +// stop +// } +// +// sub_85: assembly { +// /* "source":16452:16459 */ +// stop +// } +// +// sub_86: assembly { +// /* "source":16500:16507 */ +// stop +// } +// +// sub_87: assembly { +// /* "source":16548:16555 */ +// stop +// } +// +// sub_88: assembly { +// /* "source":16596:16603 */ +// stop +// } +// +// sub_89: assembly { +// /* "source":16644:16651 */ +// stop +// } +// +// sub_90: assembly { +// /* "source":16692:16699 */ +// stop +// } +// +// sub_91: assembly { +// /* "source":16740:16747 */ +// stop +// } +// +// sub_92: assembly { +// /* "source":16788:16795 */ +// stop +// } +// +// sub_93: assembly { +// /* "source":16836:16843 */ +// stop +// } +// +// sub_94: assembly { +// /* "source":16884:16891 */ +// stop +// } +// +// sub_95: assembly { +// /* "source":16932:16939 */ +// stop +// } +// +// sub_96: assembly { +// /* "source":16980:16987 */ +// stop +// } +// +// sub_97: assembly { +// /* "source":17028:17035 */ +// stop +// } +// +// sub_98: assembly { +// /* "source":17076:17083 */ +// stop +// } +// +// sub_99: assembly { +// /* "source":17124:17131 */ +// stop +// } +// +// sub_100: assembly { +// /* "source":17172:17179 */ +// stop +// } +// +// sub_101: assembly { +// /* "source":17220:17227 */ +// stop +// } +// +// sub_102: assembly { +// /* "source":17268:17275 */ +// stop +// } +// +// sub_103: assembly { +// /* "source":17316:17323 */ +// stop +// } +// +// sub_104: assembly { +// /* "source":17364:17371 */ +// stop +// } +// +// sub_105: assembly { +// /* "source":17412:17419 */ +// stop +// } +// +// sub_106: assembly { +// /* "source":17460:17467 */ +// stop +// } +// +// sub_107: assembly { +// /* "source":17508:17515 */ +// stop +// } +// +// sub_108: assembly { +// /* "source":17556:17563 */ +// stop +// } +// +// sub_109: assembly { +// /* "source":17604:17611 */ +// stop +// } +// +// sub_110: assembly { +// /* "source":17652:17659 */ +// stop +// } +// +// sub_111: assembly { +// /* "source":17700:17707 */ +// stop +// } +// +// sub_112: assembly { +// /* "source":17748:17755 */ +// stop +// } +// +// sub_113: assembly { +// /* "source":17796:17803 */ +// stop +// } +// +// sub_114: assembly { +// /* "source":17844:17851 */ +// stop +// } +// +// sub_115: assembly { +// /* "source":17892:17899 */ +// stop +// } +// +// sub_116: assembly { +// /* "source":17940:17947 */ +// stop +// } +// +// sub_117: assembly { +// /* "source":17988:17995 */ +// stop +// } +// +// sub_118: assembly { +// /* "source":18036:18043 */ +// stop +// } +// +// sub_119: assembly { +// /* "source":18084:18091 */ +// stop +// } +// +// sub_120: assembly { +// /* "source":18132:18139 */ +// stop +// } +// +// sub_121: assembly { +// /* "source":18180:18187 */ +// stop +// } +// +// sub_122: assembly { +// /* "source":18228:18235 */ +// stop +// } +// +// sub_123: assembly { +// /* "source":18276:18283 */ +// stop +// } +// +// sub_124: assembly { +// /* "source":18324:18331 */ +// stop +// } +// +// sub_125: assembly { +// /* "source":18372:18379 */ +// stop +// } +// +// sub_126: assembly { +// /* "source":18420:18427 */ +// stop +// } +// +// sub_127: assembly { +// /* "source":18468:18475 */ +// stop +// } +// +// sub_128: assembly { +// /* "source":18516:18523 */ +// stop +// } +// +// sub_129: assembly { +// /* "source":18564:18571 */ +// stop +// } +// +// sub_130: assembly { +// /* "source":18612:18619 */ +// stop +// } +// +// sub_131: assembly { +// /* "source":18660:18667 */ +// stop +// } +// +// sub_132: assembly { +// /* "source":18708:18715 */ +// stop +// } +// +// sub_133: assembly { +// /* "source":18756:18763 */ +// stop +// } +// +// sub_134: assembly { +// /* "source":18804:18811 */ +// stop +// } +// +// sub_135: assembly { +// /* "source":18852:18859 */ +// stop +// } +// +// sub_136: assembly { +// /* "source":18900:18907 */ +// stop +// } +// +// sub_137: assembly { +// /* "source":18948:18955 */ +// stop +// } +// +// sub_138: assembly { +// /* "source":18996:19003 */ +// stop +// } +// +// sub_139: assembly { +// /* "source":19044:19051 */ +// stop +// } +// +// sub_140: assembly { +// /* "source":19092:19099 */ +// stop +// } +// +// sub_141: assembly { +// /* "source":19140:19147 */ +// stop +// } +// +// sub_142: assembly { +// /* "source":19188:19195 */ +// stop +// } +// +// sub_143: assembly { +// /* "source":19236:19243 */ +// stop +// } +// +// sub_144: assembly { +// /* "source":19284:19291 */ +// stop +// } +// +// sub_145: assembly { +// /* "source":19332:19339 */ +// stop +// } +// +// sub_146: assembly { +// /* "source":19380:19387 */ +// stop +// } +// +// sub_147: assembly { +// /* "source":19428:19435 */ +// stop +// } +// +// sub_148: assembly { +// /* "source":19476:19483 */ +// stop +// } +// +// sub_149: assembly { +// /* "source":19524:19531 */ +// stop +// } +// +// sub_150: assembly { +// /* "source":19572:19579 */ +// stop +// } +// +// sub_151: assembly { +// /* "source":19620:19627 */ +// stop +// } +// +// sub_152: assembly { +// /* "source":19668:19675 */ +// stop +// } +// +// sub_153: assembly { +// /* "source":19716:19723 */ +// stop +// } +// +// sub_154: assembly { +// /* "source":19764:19771 */ +// stop +// } +// +// sub_155: assembly { +// /* "source":19812:19819 */ +// stop +// } +// +// sub_156: assembly { +// /* "source":19860:19867 */ +// stop +// } +// +// sub_157: assembly { +// /* "source":19908:19915 */ +// stop +// } +// +// sub_158: assembly { +// /* "source":19956:19963 */ +// stop +// } +// +// sub_159: assembly { +// /* "source":20004:20011 */ +// stop +// } +// +// sub_160: assembly { +// /* "source":20052:20059 */ +// stop +// } +// +// sub_161: assembly { +// /* "source":20100:20107 */ +// stop +// } +// +// sub_162: assembly { +// /* "source":20148:20155 */ +// stop +// } +// +// sub_163: assembly { +// /* "source":20196:20203 */ +// stop +// } +// +// sub_164: assembly { +// /* "source":20244:20251 */ +// stop +// } +// +// sub_165: assembly { +// /* "source":20292:20299 */ +// stop +// } +// +// sub_166: assembly { +// /* "source":20340:20347 */ +// stop +// } +// +// sub_167: assembly { +// /* "source":20388:20395 */ +// stop +// } +// +// sub_168: assembly { +// /* "source":20436:20443 */ +// stop +// } +// +// sub_169: assembly { +// /* "source":20484:20491 */ +// stop +// } +// +// sub_170: assembly { +// /* "source":20532:20539 */ +// stop +// } +// +// sub_171: assembly { +// /* "source":20580:20587 */ +// stop +// } +// +// sub_172: assembly { +// /* "source":20628:20635 */ +// stop +// } +// +// sub_173: assembly { +// /* "source":20676:20683 */ +// stop +// } +// +// sub_174: assembly { +// /* "source":20724:20731 */ +// stop +// } +// +// sub_175: assembly { +// /* "source":20772:20779 */ +// stop +// } +// +// sub_176: assembly { +// /* "source":20820:20827 */ +// stop +// } +// +// sub_177: assembly { +// /* "source":20868:20875 */ +// stop +// } +// +// sub_178: assembly { +// /* "source":20916:20923 */ +// stop +// } +// +// sub_179: assembly { +// /* "source":20964:20971 */ +// stop +// } +// +// sub_180: assembly { +// /* "source":21012:21019 */ +// stop +// } +// +// sub_181: assembly { +// /* "source":21060:21067 */ +// stop +// } +// +// sub_182: assembly { +// /* "source":21108:21115 */ +// stop +// } +// +// sub_183: assembly { +// /* "source":21156:21163 */ +// stop +// } +// +// sub_184: assembly { +// /* "source":21204:21211 */ +// stop +// } +// +// sub_185: assembly { +// /* "source":21252:21259 */ +// stop +// } +// +// sub_186: assembly { +// /* "source":21300:21307 */ +// stop +// } +// +// sub_187: assembly { +// /* "source":21348:21355 */ +// stop +// } +// +// sub_188: assembly { +// /* "source":21396:21403 */ +// stop +// } +// +// sub_189: assembly { +// /* "source":21444:21451 */ +// stop +// } +// +// sub_190: assembly { +// /* "source":21492:21499 */ +// stop +// } +// +// sub_191: assembly { +// /* "source":21540:21547 */ +// stop +// } +// +// sub_192: assembly { +// /* "source":21588:21595 */ +// stop +// } +// +// sub_193: assembly { +// /* "source":21636:21643 */ +// stop +// } +// +// sub_194: assembly { +// /* "source":21684:21691 */ +// stop +// } +// +// sub_195: assembly { +// /* "source":21732:21739 */ +// stop +// } +// +// sub_196: assembly { +// /* "source":21780:21787 */ +// stop +// } +// +// sub_197: assembly { +// /* "source":21828:21835 */ +// stop +// } +// +// sub_198: assembly { +// /* "source":21876:21883 */ +// stop +// } +// +// sub_199: assembly { +// /* "source":21924:21931 */ +// stop +// } +// +// sub_200: assembly { +// /* "source":21972:21979 */ +// stop +// } +// +// sub_201: assembly { +// /* "source":22020:22027 */ +// stop +// } +// +// sub_202: assembly { +// /* "source":22068:22075 */ +// stop +// } +// +// sub_203: assembly { +// /* "source":22116:22123 */ +// stop +// } +// +// sub_204: assembly { +// /* "source":22164:22171 */ +// stop +// } +// +// sub_205: assembly { +// /* "source":22212:22219 */ +// stop +// } +// +// sub_206: assembly { +// /* "source":22260:22267 */ +// stop +// } +// +// sub_207: assembly { +// /* "source":22308:22315 */ +// stop +// } +// +// sub_208: assembly { +// /* "source":22356:22363 */ +// stop +// } +// +// sub_209: assembly { +// /* "source":22404:22411 */ +// stop +// } +// +// sub_210: assembly { +// /* "source":22452:22459 */ +// stop +// } +// +// sub_211: assembly { +// /* "source":22500:22507 */ +// stop +// } +// +// sub_212: assembly { +// /* "source":22548:22555 */ +// stop +// } +// +// sub_213: assembly { +// /* "source":22596:22603 */ +// stop +// } +// +// sub_214: assembly { +// /* "source":22644:22651 */ +// stop +// } +// +// sub_215: assembly { +// /* "source":22692:22699 */ +// stop +// } +// +// sub_216: assembly { +// /* "source":22740:22747 */ +// stop +// } +// +// sub_217: assembly { +// /* "source":22788:22795 */ +// stop +// } +// +// sub_218: assembly { +// /* "source":22836:22843 */ +// stop +// } +// +// sub_219: assembly { +// /* "source":22884:22891 */ +// stop +// } +// +// sub_220: assembly { +// /* "source":22932:22939 */ +// stop +// } +// +// sub_221: assembly { +// /* "source":22980:22987 */ +// stop +// } +// +// sub_222: assembly { +// /* "source":23028:23035 */ +// stop +// } +// +// sub_223: assembly { +// /* "source":23076:23083 */ +// stop +// } +// +// sub_224: assembly { +// /* "source":23124:23131 */ +// stop +// } +// +// sub_225: assembly { +// /* "source":23172:23179 */ +// stop +// } +// +// sub_226: assembly { +// /* "source":23220:23227 */ +// stop +// } +// +// sub_227: assembly { +// /* "source":23268:23275 */ +// stop +// } +// +// sub_228: assembly { +// /* "source":23316:23323 */ +// stop +// } +// +// sub_229: assembly { +// /* "source":23364:23371 */ +// stop +// } +// +// sub_230: assembly { +// /* "source":23412:23419 */ +// stop +// } +// +// sub_231: assembly { +// /* "source":23460:23467 */ +// stop +// } +// +// sub_232: assembly { +// /* "source":23508:23515 */ +// stop +// } +// +// sub_233: assembly { +// /* "source":23556:23563 */ +// stop +// } +// +// sub_234: assembly { +// /* "source":23604:23611 */ +// stop +// } +// +// sub_235: assembly { +// /* "source":23652:23659 */ +// stop +// } +// +// sub_236: assembly { +// /* "source":23700:23707 */ +// stop +// } +// +// sub_237: assembly { +// /* "source":23748:23755 */ +// stop +// } +// +// sub_238: assembly { +// /* "source":23796:23803 */ +// stop +// } +// +// sub_239: assembly { +// /* "source":23844:23851 */ +// stop +// } +// +// sub_240: assembly { +// /* "source":23892:23899 */ +// stop +// } +// +// sub_241: assembly { +// /* "source":23940:23947 */ +// stop +// } +// +// sub_242: assembly { +// /* "source":23988:23995 */ +// stop +// } +// +// sub_243: assembly { +// /* "source":24036:24043 */ +// stop +// } +// +// sub_244: assembly { +// /* "source":24084:24091 */ +// stop +// } +// +// sub_245: assembly { +// /* "source":24132:24139 */ +// stop +// } +// +// sub_246: assembly { +// /* "source":24180:24187 */ +// stop +// } +// +// sub_247: assembly { +// /* "source":24228:24235 */ +// stop +// } +// +// sub_248: assembly { +// /* "source":24276:24283 */ +// stop +// } +// +// sub_249: assembly { +// /* "source":24324:24331 */ +// stop +// } +// +// sub_250: assembly { +// /* "source":24372:24379 */ +// stop +// } +// +// sub_251: assembly { +// /* "source":24420:24427 */ +// stop +// } +// +// sub_252: assembly { +// /* "source":24468:24475 */ +// stop +// } +// +// sub_253: assembly { +// /* "source":24516:24523 */ +// stop +// } +// +// sub_254: assembly { +// /* "source":24564:24571 */ +// stop +// } +// +// sub_255: assembly { +// /* "source":24612:24619 */ +// stop +// } +// Bytecode: ef000101000402000107010301000014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014040000000080ffff5f808080ec00505f808080ec01505f808080ec02505f808080ec03505f808080ec04505f808080ec05505f808080ec06505f808080ec07505f808080ec08505f808080ec09505f808080ec0a505f808080ec0b505f808080ec0c505f808080ec0d505f808080ec0e505f808080ec0f505f808080ec10505f808080ec11505f808080ec12505f808080ec13505f808080ec14505f808080ec15505f808080ec16505f808080ec17505f808080ec18505f808080ec19505f808080ec1a505f808080ec1b505f808080ec1c505f808080ec1d505f808080ec1e505f808080ec1f505f808080ec20505f808080ec21505f808080ec22505f808080ec23505f808080ec24505f808080ec25505f808080ec26505f808080ec27505f808080ec28505f808080ec29505f808080ec2a505f808080ec2b505f808080ec2c505f808080ec2d505f808080ec2e505f808080ec2f505f808080ec30505f808080ec31505f808080ec32505f808080ec33505f808080ec34505f808080ec35505f808080ec36505f808080ec37505f808080ec38505f808080ec39505f808080ec3a505f808080ec3b505f808080ec3c505f808080ec3d505f808080ec3e505f808080ec3f505f808080ec40505f808080ec41505f808080ec42505f808080ec43505f808080ec44505f808080ec45505f808080ec46505f808080ec47505f808080ec48505f808080ec49505f808080ec4a505f808080ec4b505f808080ec4c505f808080ec4d505f808080ec4e505f808080ec4f505f808080ec50505f808080ec51505f808080ec52505f808080ec53505f808080ec54505f808080ec55505f808080ec56505f808080ec57505f808080ec58505f808080ec59505f808080ec5a505f808080ec5b505f808080ec5c505f808080ec5d505f808080ec5e505f808080ec5f505f808080ec60505f808080ec61505f808080ec62505f808080ec63505f808080ec64505f808080ec65505f808080ec66505f808080ec67505f808080ec68505f808080ec69505f808080ec6a505f808080ec6b505f808080ec6c505f808080ec6d505f808080ec6e505f808080ec6f505f808080ec70505f808080ec71505f808080ec72505f808080ec73505f808080ec74505f808080ec75505f808080ec76505f808080ec77505f808080ec78505f808080ec79505f808080ec7a505f808080ec7b505f808080ec7c505f808080ec7d505f808080ec7e505f808080ec7f505f808080ec80505f808080ec81505f808080ec82505f808080ec83505f808080ec84505f808080ec85505f808080ec86505f808080ec87505f808080ec88505f808080ec89505f808080ec8a505f808080ec8b505f808080ec8c505f808080ec8d505f808080ec8e505f808080ec8f505f808080ec90505f808080ec91505f808080ec92505f808080ec93505f808080ec94505f808080ec95505f808080ec96505f808080ec97505f808080ec98505f808080ec99505f808080ec9a505f808080ec9b505f808080ec9c505f808080ec9d505f808080ec9e505f808080ec9f505f808080eca0505f808080eca1505f808080eca2505f808080eca3505f808080eca4505f808080eca5505f808080eca6505f808080eca7505f808080eca8505f808080eca9505f808080ecaa505f808080ecab505f808080ecac505f808080ecad505f808080ecae505f808080ecaf505f808080ecb0505f808080ecb1505f808080ecb2505f808080ecb3505f808080ecb4505f808080ecb5505f808080ecb6505f808080ecb7505f808080ecb8505f808080ecb9505f808080ecba505f808080ecbb505f808080ecbc505f808080ecbd505f808080ecbe505f808080ecbf505f808080ecc0505f808080ecc1505f808080ecc2505f808080ecc3505f808080ecc4505f808080ecc5505f808080ecc6505f808080ecc7505f808080ecc8505f808080ecc9505f808080ecca505f808080eccb505f808080eccc505f808080eccd505f808080ecce505f808080eccf505f808080ecd0505f808080ecd1505f808080ecd2505f808080ecd3505f808080ecd4505f808080ecd5505f808080ecd6505f808080ecd7505f808080ecd8505f808080ecd9505f808080ecda505f808080ecdb505f808080ecdc505f808080ecdd505f808080ecde505f808080ecdf505f808080ece0505f808080ece1505f808080ece2505f808080ece3505f808080ece4505f808080ece5505f808080ece6505f808080ece7505f808080ece8505f808080ece9505f808080ecea505f808080eceb505f808080ecec505f808080eced505f808080ecee505f808080ecef505f808080ecf0505f808080ecf1505f808080ecf2505f808080ecf3505f808080ecf4505f808080ecf5505f808080ecf6505f808080ecf7505f808080ecf8505f808080ecf9505f808080ecfa505f808080ecfb505f808080ecfc505f808080ecfd505f808080ecfe505f808080ecff5000ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD SMOD ADD SUB ADD STOP STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x10 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x11 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x12 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x13 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x14 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x15 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x16 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x17 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x18 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x19 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x20 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x21 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x22 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x23 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x24 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x25 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x26 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x27 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x28 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x29 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x30 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x31 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x32 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x33 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x34 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x35 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x36 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x37 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x38 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x39 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x40 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x41 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x42 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x43 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x44 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x45 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x46 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x47 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x48 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x49 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x50 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x51 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x52 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x53 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x54 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x55 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x56 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x57 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x58 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x59 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x60 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x61 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x62 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x63 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x64 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x65 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x66 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x67 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x68 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x69 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x70 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x71 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x72 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x73 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x74 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x75 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x76 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x77 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x78 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x79 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x80 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x81 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x82 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x83 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x84 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x85 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x86 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x87 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x88 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x89 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x90 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x91 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x92 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x93 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x94 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x95 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x96 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x97 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x98 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x99 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xED POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFF POP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP +// SourceMappings: 78:1:0:-:0;50:30;;;;46:35;126:1;98:30;;;;94:35;174:1;146:30;;;;142:35;222:1;194:30;;;;190:35;270:1;242:30;;;;238:35;318:1;290:30;;;;286:35;366:1;338:30;;;;334:35;414:1;386:30;;;;382:35;462:1;434:30;;;;430:35;510:1;482:30;;;;478:35;558:1;530:30;;;;526:35;606:1;578:30;;;;574:35;654:1;626:30;;;;622:35;702:1;674:30;;;;670:35;750:1;722:30;;;;718:35;798:1;770:30;;;;766:35;846:1;818:30;;;;814:35;894:1;866:30;;;;862:35;942:1;914:30;;;;910:35;990:1;962:30;;;;958:35;1038:1;1010:30;;;;1006:35;1086:1;1058:30;;;;1054:35;1134:1;1106:30;;;;1102:35;1182:1;1154:30;;;;1150:35;1230:1;1202:30;;;;1198:35;1278:1;1250:30;;;;1246:35;1326:1;1298:30;;;;1294:35;1374:1;1346:30;;;;1342:35;1422:1;1394:30;;;;1390:35;1470:1;1442:30;;;;1438:35;1518:1;1490:30;;;;1486:35;1566:1;1538:30;;;;1534:35;1614:1;1586:30;;;;1582:35;1662:1;1634:30;;;;1630:35;1710:1;1682:30;;;;1678:35;1758:1;1730:30;;;;1726:35;1806:1;1778:30;;;;1774:35;1854:1;1826:30;;;;1822:35;1902:1;1874:30;;;;1870:35;1950:1;1922:30;;;;1918:35;1998:1;1970:30;;;;1966:35;2046:1;2018:30;;;;2014:35;2094:1;2066:30;;;;2062:35;2142:1;2114:30;;;;2110:35;2190:1;2162:30;;;;2158:35;2238:1;2210:30;;;;2206:35;2286:1;2258:30;;;;2254:35;2334:1;2306:30;;;;2302:35;2382:1;2354:30;;;;2350:35;2430:1;2402:30;;;;2398:35;2478:1;2450:30;;;;2446:35;2526:1;2498:30;;;;2494:35;2574:1;2546:30;;;;2542:35;2622:1;2594:30;;;;2590:35;2670:1;2642:30;;;;2638:35;2718:1;2690:30;;;;2686:35;2766:1;2738:30;;;;2734:35;2814:1;2786:30;;;;2782:35;2862:1;2834:30;;;;2830:35;2910:1;2882:30;;;;2878:35;2958:1;2930:30;;;;2926:35;3006:1;2978:30;;;;2974:35;3054:1;3026:30;;;;3022:35;3102:1;3074:30;;;;3070:35;3150:1;3122:30;;;;3118:35;3198:1;3170:30;;;;3166:35;3246:1;3218:30;;;;3214:35;3294:1;3266:30;;;;3262:35;3342:1;3314:30;;;;3310:35;3390:1;3362:30;;;;3358:35;3438:1;3410:30;;;;3406:35;3486:1;3458:30;;;;3454:35;3534:1;3506:30;;;;3502:35;3582:1;3554:30;;;;3550:35;3630:1;3602:30;;;;3598:35;3678:1;3650:30;;;;3646:35;3726:1;3698:30;;;;3694:35;3774:1;3746:30;;;;3742:35;3822:1;3794:30;;;;3790:35;3870:1;3842:30;;;;3838:35;3918:1;3890:30;;;;3886:35;3966:1;3938:30;;;;3934:35;4014:1;3986:30;;;;3982:35;4062:1;4034:30;;;;4030:35;4110:1;4082:30;;;;4078:35;4158:1;4130:30;;;;4126:35;4206:1;4178:30;;;;4174:35;4254:1;4226:30;;;;4222:35;4302:1;4274:30;;;;4270:35;4350:1;4322:30;;;;4318:35;4398:1;4370:30;;;;4366:35;4446:1;4418:30;;;;4414:35;4494:1;4466:30;;;;4462:35;4542:1;4514:30;;;;4510:35;4590:1;4562:30;;;;4558:35;4638:1;4610:30;;;;4606:35;4686:1;4658:30;;;;4654:35;4734:1;4706:30;;;;4702:35;4782:1;4754:30;;;;4750:35;4830:1;4802:30;;;;4798:35;4878:1;4850:30;;;;4846:35;4926:1;4898:30;;;;4894:35;4974:1;4946:30;;;;4942:35;5022:1;4994:30;;;;4990:35;5070:1;5042:30;;;;5038:35;5118:1;5090:30;;;;5086:35;5166:1;5138:30;;;;5134:35;5214:1;5186:30;;;;5182:35;5262:1;5234:30;;;;5230:35;5310:1;5282:30;;;;5278:35;5358:1;5330:30;;;;5326:35;5406:1;5378:30;;;;5374:35;5454:1;5426:30;;;;5422:35;5502:1;5474:30;;;;5470:35;5550:1;5522:30;;;;5518:35;5598:1;5570:30;;;;5566:35;5646:1;5618:30;;;;5614:35;5694:1;5666:30;;;;5662:35;5742:1;5714:30;;;;5710:35;5790:1;5762:30;;;;5758:35;5838:1;5810:30;;;;5806:35;5886:1;5858:30;;;;5854:35;5934:1;5906:30;;;;5902:35;5982:1;5954:30;;;;5950:35;6030:1;6002:30;;;;5998:35;6078:1;6050:30;;;;6046:35;6126:1;6098:30;;;;6094:35;6174:1;6146:30;;;;6142:35;6222:1;6194:30;;;;6190:35;6270:1;6242:30;;;;6238:35;6318:1;6290:30;;;;6286:35;6366:1;6338:30;;;;6334:35;6414:1;6386:30;;;;6382:35;6462:1;6434:30;;;;6430:35;6510:1;6482:30;;;;6478:35;6558:1;6530:30;;;;6526:35;6606:1;6578:30;;;;6574:35;6654:1;6626:30;;;;6622:35;6702:1;6674:30;;;;6670:35;6750:1;6722:30;;;;6718:35;6798:1;6770:30;;;;6766:35;6846:1;6818:30;;;;6814:35;6894:1;6866:30;;;;6862:35;6942:1;6914:30;;;;6910:35;6990:1;6962:30;;;;6958:35;7038:1;7010:30;;;;7006:35;7086:1;7058:30;;;;7054:35;7134:1;7106:30;;;;7102:35;7182:1;7154:30;;;;7150:35;7230:1;7202:30;;;;7198:35;7278:1;7250:30;;;;7246:35;7326:1;7298:30;;;;7294:35;7374:1;7346:30;;;;7342:35;7422:1;7394:30;;;;7390:35;7470:1;7442:30;;;;7438:35;7518:1;7490:30;;;;7486:35;7566:1;7538:30;;;;7534:35;7614:1;7586:30;;;;7582:35;7662:1;7634:30;;;;7630:35;7710:1;7682:30;;;;7678:35;7758:1;7730:30;;;;7726:35;7806:1;7778:30;;;;7774:35;7854:1;7826:30;;;;7822:35;7902:1;7874:30;;;;7870:35;7950:1;7922:30;;;;7918:35;7998:1;7970:30;;;;7966:35;8046:1;8018:30;;;;8014:35;8094:1;8066:30;;;;8062:35;8142:1;8114:30;;;;8110:35;8190:1;8162:30;;;;8158:35;8238:1;8210:30;;;;8206:35;8286:1;8258:30;;;;8254:35;8334:1;8306:30;;;;8302:35;8382:1;8354:30;;;;8350:35;8430:1;8402:30;;;;8398:35;8478:1;8450:30;;;;8446:35;8526:1;8498:30;;;;8494:35;8574:1;8546:30;;;;8542:35;8622:1;8594:30;;;;8590:35;8670:1;8642:30;;;;8638:35;8718:1;8690:30;;;;8686:35;8766:1;8738:30;;;;8734:35;8814:1;8786:30;;;;8782:35;8862:1;8834:30;;;;8830:35;8910:1;8882:30;;;;8878:35;8958:1;8930:30;;;;8926:35;9006:1;8978:30;;;;8974:35;9054:1;9026:30;;;;9022:35;9102:1;9074:30;;;;9070:35;9150:1;9122:30;;;;9118:35;9198:1;9170:30;;;;9166:35;9246:1;9218:30;;;;9214:35;9294:1;9266:30;;;;9262:35;9342:1;9314:30;;;;9310:35;9390:1;9362:30;;;;9358:35;9438:1;9410:30;;;;9406:35;9486:1;9458:30;;;;9454:35;9534:1;9506:30;;;;9502:35;9582:1;9554:30;;;;9550:35;9630:1;9602:30;;;;9598:35;9678:1;9650:30;;;;9646:35;9726:1;9698:30;;;;9694:35;9774:1;9746:30;;;;9742:35;9822:1;9794:30;;;;9790:35;9870:1;9842:30;;;;9838:35;9918:1;9890:30;;;;9886:35;9966:1;9938:30;;;;9934:35;10014:1;9986:30;;;;9982:35;10062:1;10034:30;;;;10030:35;10110:1;10082:30;;;;10078:35;10158:1;10130:30;;;;10126:35;10206:1;10178:30;;;;10174:35;10254:1;10226:30;;;;10222:35;10302:1;10274:30;;;;10270:35;10350:1;10322:30;;;;10318:35;10398:1;10370:30;;;;10366:35;10446:1;10418:30;;;;10414:35;10494:1;10466:30;;;;10462:35;10542:1;10514:30;;;;10510:35;10590:1;10562:30;;;;10558:35;10638:1;10610:30;;;;10606:35;10686:1;10658:30;;;;10654:35;10734:1;10706:30;;;;10702:35;10782:1;10754:30;;;;10750:35;10830:1;10802:30;;;;10798:35;10878:1;10850:30;;;;10846:35;10926:1;10898:30;;;;10894:35;10974:1;10946:30;;;;10942:35;11022:1;10994:30;;;;10990:35;11070:1;11042:30;;;;11038:35;11118:1;11090:30;;;;11086:35;11166:1;11138:30;;;;11134:35;11214:1;11186:30;;;;11182:35;11262:1;11234:30;;;;11230:35;11310:1;11282:30;;;;11278:35;11358:1;11330:30;;;;11326:35;11406:1;11378:30;;;;11374:35;11454:1;11426:30;;;;11422:35;11502:1;11474:30;;;;11470:35;11550:1;11522:30;;;;11518:35;11598:1;11570:30;;;;11566:35;11646:1;11618:30;;;;11614:35;11694:1;11666:30;;;;11662:35;11742:1;11714:30;;;;11710:35;11790:1;11762:30;;;;11758:35;11838:1;11810:30;;;;11806:35;11886:1;11858:30;;;;11854:35;11934:1;11906:30;;;;11902:35;11982:1;11954:30;;;;11950:35;12030:1;12002:30;;;;11998:35;12078:1;12050:30;;;;12046:35;12126:1;12098:30;;;;12094:35;12174:1;12146:30;;;;12142:35;12222:1;12194:30;;;;12190:35;12270:1;12242:30;;;;12238:35;12318:1;12290:30;;;;12286:35;22:12315 From c73c4d2871fd510fbb7e560587ab07ba8f4837ba Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 29 Nov 2024 11:20:24 +0100 Subject: [PATCH 0491/1340] eof: Fix wrong int type for subcontainers iteration --- libevmasm/Assembly.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 584c46455..f8734b5fc 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1346,7 +1346,7 @@ std::map Assembly::findReferencedContainers() const std::map replacements; uint8_t nUnreferenced = 0; - for (uint8_t i = 0; i < static_cast(m_subs.size()); ++i) + for (size_t i = 0; i < m_subs.size(); ++i) { solAssert(i <= std::numeric_limits::max()); if (referencedSubcontainersIds.count(static_cast(i)) > 0) From a87c49d104cae74bab502cc40771befcf04204e0 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 29 Nov 2024 11:21:02 +0100 Subject: [PATCH 0492/1340] eof: Fix container id bug --- libevmasm/Assembly.cpp | 10 ++- .../eof/prune_unreferenced_container.yul | 81 +++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 test/libyul/objectCompiler/eof/prune_unreferenced_container.yul diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index f8734b5fc..4719d357f 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1442,13 +1442,19 @@ LinkerObject const& Assembly::assembleEOF() const case EOFCreate: { ret.bytecode.push_back(static_cast(Instruction::EOFCREATE)); - ret.bytecode.push_back(static_cast(item.data())); + solAssert(item.data() <= std::numeric_limits::max()); + auto const containerID = static_cast(item.data()); + solAssert(subIdsReplacements.count(containerID) == 1); + ret.bytecode.push_back(subIdsReplacements.at(containerID)); break; } case ReturnContract: { ret.bytecode.push_back(static_cast(Instruction::RETURNCONTRACT)); - ret.bytecode.push_back(static_cast(item.data())); + solAssert(item.data() <= std::numeric_limits::max()); + auto const containerID = static_cast(item.data()); + solAssert(subIdsReplacements.count(containerID) == 1); + ret.bytecode.push_back(subIdsReplacements.at(containerID)); break; } case VerbatimBytecode: diff --git a/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul b/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul new file mode 100644 index 000000000..2225fe6eb --- /dev/null +++ b/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul @@ -0,0 +1,81 @@ +object "a" { + code { + mstore(0, eofcreate("c", 0, 0, 0, 0)) + return(0, 32) + } + + object "b" { + code { + mstore(0, 0x1122334455667788990011223344556677889900112233445566778899001122) + mstore(32, 0x1122334455667788990011223344556677889900112233445566778899001122) + } + } + + object "c" { + code { + mstore(0, 0x1122334455667788990011223344556677889900112233445566778899001122) + mstore(32, 0x1122334455667788990011223344556677889900112233445566778899001122) + } + } +} + +// ==== +// EVMVersion: >=prague +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":80:81 */ +// 0x00 +// /* "source":56:82 */ +// dup1 +// dup1 +// dup1 +// eofcreate{1} +// /* "source":53:54 */ +// 0x00 +// /* "source":46:83 */ +// mstore +// /* "source":106:108 */ +// 0x20 +// /* "source":103:104 */ +// 0x00 +// /* "source":96:109 */ +// return +// stop +// +// sub_0: assembly { +// /* "source":198:264 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":195:196 */ +// 0x00 +// /* "source":188:265 */ +// mstore +// /* "source":293:359 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":289:291 */ +// 0x20 +// /* "source":282:360 */ +// mstore +// /* "source":156:384 */ +// stop +// } +// +// sub_1: assembly { +// /* "source":463:529 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":460:461 */ +// 0x00 +// /* "source":453:530 */ +// mstore +// /* "source":558:624 */ +// 0x1122334455667788990011223344556677889900112233445566778899001122 +// /* "source":554:556 */ +// 0x20 +// /* "source":547:625 */ +// mstore +// /* "source":421:649 */ +// stop +// } +// Bytecode: ef0001010004020001000c030001005b040000000080ffff5f808080ec005f5260205ff3ef00010100040200010048040000000080ffff7f11223344556677889900112233445566778899001122334455667788990011225f527f112233445566778899001122334455667788990011223344556677889900112260205200 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0xC SUB STOP ADD STOP JUMPDEST DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP BASEFEE DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH0 MSTORE PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH1 0x20 MSTORE STOP +// SourceMappings: 80:1:0:-:0;56:26;;;;53:1;46:37;106:2;103:1;96:13 From 6b347a13d0092de83041b08b5904a6ee50ca44ce Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 29 Nov 2024 11:23:18 +0100 Subject: [PATCH 0493/1340] eof: Add yul syntax test and proper error for too many subcontainers --- libyul/AsmAnalysis.cpp | 32 ++- .../eof/too_many_subcontainers.yul | 270 ++++++++++++++++++ 2 files changed, 293 insertions(+), 9 deletions(-) create mode 100644 test/libyul/yulSyntaxTests/eof/too_many_subcontainers.yul diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 8ed0b4142..aedf4fd07 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -800,13 +800,27 @@ bool AsmAnalyzer::validateInstructions(FunctionCall const& _functionCall) void AsmAnalyzer::validateObjectStructure(langutil::SourceLocation _astRootLocation) { - if (m_eofVersion.has_value() && util::contains(m_objectStructure.objectName, '.')) // No dots in object name for EOF - m_errorReporter.syntaxError( - 9822_error, - _astRootLocation, - fmt::format( - "The object name \"{objectName}\" is invalid in EOF context. Object names must not contain 'dot' character.", - fmt::arg("objectName", m_objectStructure.objectName) - ) - ); + if (m_eofVersion.has_value()) + { + if (util::contains(m_objectStructure.objectName, '.')) // No dots in object name for EOF + m_errorReporter.syntaxError( + 9822_error, + _astRootLocation, + fmt::format( + "The object name \"{objectName}\" is invalid in EOF context. Object names must not contain 'dot' character.", + fmt::arg("objectName", m_objectStructure.objectName) + ) + ); + else if (m_objectStructure.topLevelSubObjectNames().size() > 256) + { + m_errorReporter.syntaxError( + 1305_error, + _astRootLocation, + fmt::format( + "Too many subobjects in \"{objectName}\". At most 256 subobjects allowed when compiling to EOF", + fmt::arg("objectName", m_objectStructure.objectName) + ) + ); + } + } } diff --git a/test/libyul/yulSyntaxTests/eof/too_many_subcontainers.yul b/test/libyul/yulSyntaxTests/eof/too_many_subcontainers.yul new file mode 100644 index 000000000..f39d6f2d8 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/too_many_subcontainers.yul @@ -0,0 +1,270 @@ +object "a" { + code { + mstore(0, eofcreate("s0000", 0, 0, 0, 0)) + return(0, 32) + } + + object "s0000" {code{}} + object "s0001" {code{}} + object "s0002" {code{}} + object "s0003" {code{}} + object "s0004" {code{}} + object "s0005" {code{}} + object "s0006" {code{}} + object "s0007" {code{}} + object "s0008" {code{}} + object "s0009" {code{}} + object "s0010" {code{}} + object "s0011" {code{}} + object "s0012" {code{}} + object "s0013" {code{}} + object "s0014" {code{}} + object "s0015" {code{}} + object "s0016" {code{}} + object "s0017" {code{}} + object "s0018" {code{}} + object "s0019" {code{}} + object "s0020" {code{}} + object "s0021" {code{}} + object "s0022" {code{}} + object "s0023" {code{}} + object "s0024" {code{}} + object "s0025" {code{}} + object "s0026" {code{}} + object "s0027" {code{}} + object "s0028" {code{}} + object "s0029" {code{}} + object "s0030" {code{}} + object "s0031" {code{}} + object "s0032" {code{}} + object "s0033" {code{}} + object "s0034" {code{}} + object "s0035" {code{}} + object "s0036" {code{}} + object "s0037" {code{}} + object "s0038" {code{}} + object "s0039" {code{}} + object "s0040" {code{}} + object "s0041" {code{}} + object "s0042" {code{}} + object "s0043" {code{}} + object "s0044" {code{}} + object "s0045" {code{}} + object "s0046" {code{}} + object "s0047" {code{}} + object "s0048" {code{}} + object "s0049" {code{}} + object "s0050" {code{}} + object "s0051" {code{}} + object "s0052" {code{}} + object "s0053" {code{}} + object "s0054" {code{}} + object "s0055" {code{}} + object "s0056" {code{}} + object "s0057" {code{}} + object "s0058" {code{}} + object "s0059" {code{}} + object "s0060" {code{}} + object "s0061" {code{}} + object "s0062" {code{}} + object "s0063" {code{}} + object "s0064" {code{}} + object "s0065" {code{}} + object "s0066" {code{}} + object "s0067" {code{}} + object "s0068" {code{}} + object "s0069" {code{}} + object "s0070" {code{}} + object "s0071" {code{}} + object "s0072" {code{}} + object "s0073" {code{}} + object "s0074" {code{}} + object "s0075" {code{}} + object "s0076" {code{}} + object "s0077" {code{}} + object "s0078" {code{}} + object "s0079" {code{}} + object "s0080" {code{}} + object "s0081" {code{}} + object "s0082" {code{}} + object "s0083" {code{}} + object "s0084" {code{}} + object "s0085" {code{}} + object "s0086" {code{}} + object "s0087" {code{}} + object "s0088" {code{}} + object "s0089" {code{}} + object "s0090" {code{}} + object "s0091" {code{}} + object "s0092" {code{}} + object "s0093" {code{}} + object "s0094" {code{}} + object "s0095" {code{}} + object "s0096" {code{}} + object "s0097" {code{}} + object "s0098" {code{}} + object "s0099" {code{}} + object "s0100" {code{}} + object "s0101" {code{}} + object "s0102" {code{}} + object "s0103" {code{}} + object "s0104" {code{}} + object "s0105" {code{}} + object "s0106" {code{}} + object "s0107" {code{}} + object "s0108" {code{}} + object "s0109" {code{}} + object "s0110" {code{}} + object "s0111" {code{}} + object "s0112" {code{}} + object "s0113" {code{}} + object "s0114" {code{}} + object "s0115" {code{}} + object "s0116" {code{}} + object "s0117" {code{}} + object "s0118" {code{}} + object "s0119" {code{}} + object "s0120" {code{}} + object "s0121" {code{}} + object "s0122" {code{}} + object "s0123" {code{}} + object "s0124" {code{}} + object "s0125" {code{}} + object "s0126" {code{}} + object "s0127" {code{}} + object "s0128" {code{}} + object "s0129" {code{}} + object "s0130" {code{}} + object "s0131" {code{}} + object "s0132" {code{}} + object "s0133" {code{}} + object "s0134" {code{}} + object "s0135" {code{}} + object "s0136" {code{}} + object "s0137" {code{}} + object "s0138" {code{}} + object "s0139" {code{}} + object "s0140" {code{}} + object "s0141" {code{}} + object "s0142" {code{}} + object "s0143" {code{}} + object "s0144" {code{}} + object "s0145" {code{}} + object "s0146" {code{}} + object "s0147" {code{}} + object "s0148" {code{}} + object "s0149" {code{}} + object "s0150" {code{}} + object "s0151" {code{}} + object "s0152" {code{}} + object "s0153" {code{}} + object "s0154" {code{}} + object "s0155" {code{}} + object "s0156" {code{}} + object "s0157" {code{}} + object "s0158" {code{}} + object "s0159" {code{}} + object "s0160" {code{}} + object "s0161" {code{}} + object "s0162" {code{}} + object "s0163" {code{}} + object "s0164" {code{}} + object "s0165" {code{}} + object "s0166" {code{}} + object "s0167" {code{}} + object "s0168" {code{}} + object "s0169" {code{}} + object "s0170" {code{}} + object "s0171" {code{}} + object "s0172" {code{}} + object "s0173" {code{}} + object "s0174" {code{}} + object "s0175" {code{}} + object "s0176" {code{}} + object "s0177" {code{}} + object "s0178" {code{}} + object "s0179" {code{}} + object "s0180" {code{}} + object "s0181" {code{}} + object "s0182" {code{}} + object "s0183" {code{}} + object "s0184" {code{}} + object "s0185" {code{}} + object "s0186" {code{}} + object "s0187" {code{}} + object "s0188" {code{}} + object "s0189" {code{}} + object "s0190" {code{}} + object "s0191" {code{}} + object "s0192" {code{}} + object "s0193" {code{}} + object "s0194" {code{}} + object "s0195" {code{}} + object "s0196" {code{}} + object "s0197" {code{}} + object "s0198" {code{}} + object "s0199" {code{}} + object "s0200" {code{}} + object "s0201" {code{}} + object "s0202" {code{}} + object "s0203" {code{}} + object "s0204" {code{}} + object "s0205" {code{}} + object "s0206" {code{}} + object "s0207" {code{}} + object "s0208" {code{}} + object "s0209" {code{}} + object "s0210" {code{}} + object "s0211" {code{}} + object "s0212" {code{}} + object "s0213" {code{}} + object "s0214" {code{}} + object "s0215" {code{}} + object "s0216" {code{}} + object "s0217" {code{}} + object "s0218" {code{}} + object "s0219" {code{}} + object "s0220" {code{}} + object "s0221" {code{}} + object "s0222" {code{}} + object "s0223" {code{}} + object "s0224" {code{}} + object "s0225" {code{}} + object "s0226" {code{}} + object "s0227" {code{}} + object "s0228" {code{}} + object "s0229" {code{}} + object "s0230" {code{}} + object "s0231" {code{}} + object "s0232" {code{}} + object "s0233" {code{}} + object "s0234" {code{}} + object "s0235" {code{}} + object "s0236" {code{}} + object "s0237" {code{}} + object "s0238" {code{}} + object "s0239" {code{}} + object "s0240" {code{}} + object "s0241" {code{}} + object "s0242" {code{}} + object "s0243" {code{}} + object "s0244" {code{}} + object "s0245" {code{}} + object "s0246" {code{}} + object "s0247" {code{}} + object "s0248" {code{}} + object "s0249" {code{}} + object "s0250" {code{}} + object "s0251" {code{}} + object "s0252" {code{}} + object "s0253" {code{}} + object "s0254" {code{}} + object "s0255" {code{}} + object "s0256" {code{}} +} + +// ==== +// EVMVersion: >=prague +// bytecodeFormat: >=EOFv1 +// ---- +// SyntaxError 1305: (22-101): Too many subobjects in "a". At most 256 subobjects allowed when compiling to EOF From 515ad3654075f2fea16b2ae90e3b2e8793870770 Mon Sep 17 00:00:00 2001 From: Haoyang Ma Date: Mon, 4 Nov 2024 17:24:51 +0000 Subject: [PATCH 0494/1340] refine specification to add rules about calldata in constructor --- docs/types/reference-types.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 23119484d..79ba8da6e 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -51,6 +51,9 @@ non-persistent area where function arguments are stored, and behaves mostly like ``memory`` or ``storage`` in internal and private ones. Now ``memory`` and ``calldata`` are allowed in all functions regardless of their visibility. +.. note:: + Constructor parameters cannot use ``calldata`` as their data location. + .. note:: Prior to version 0.5.0 the data location could be omitted, and would default to different locations depending on the kind of variable, function type, etc., but all complex types must now give an explicit From 68ff34b094483bb8dc263f42ad39e1c45548e7cb Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 29 Nov 2024 20:21:58 +0100 Subject: [PATCH 0495/1340] eof: Introduce new instructions set. --- libevmasm/GasMeter.cpp | 3 +++ libevmasm/Instruction.cpp | 6 ++++++ libevmasm/Instruction.h | 6 ++++++ libevmasm/SemanticInformation.cpp | 2 ++ liblangutil/EVMVersion.cpp | 3 +++ libyul/backends/evm/EVMDialect.cpp | 3 +++ test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul | 11 +++++++++++ .../yulInterpreter/EVMInstructionInterpreter.cpp | 3 +++ 8 files changed, 37 insertions(+) create mode 100644 test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index 3ee3a39cb..1eff35fb2 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -275,7 +275,10 @@ unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVer case Tier::RJump: return GasCosts::tier1Gas; case Tier::RJumpI: return GasCosts::rjumpiGas; case Tier::VeryLow: return GasCosts::tier2Gas; + case Tier::RetF: return GasCosts::tier2Gas; case Tier::Low: return GasCosts::tier3Gas; + case Tier::CallF: return GasCosts::tier3Gas; + case Tier::JumpF: return GasCosts::tier3Gas; case Tier::Mid: return GasCosts::tier4Gas; case Tier::High: return GasCosts::tier5Gas; case Tier::BlockHash: return GasCosts::tier6Gas; diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 60ec75f92..82ed73cc9 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -169,6 +169,9 @@ std::map const solidity::evmasm::c_instructions = { "LOG3", Instruction::LOG3 }, { "LOG4", Instruction::LOG4 }, { "DATALOADN", Instruction::DATALOADN }, + { "CALLF", Instruction::CALLF }, + { "RETF", Instruction::RETF }, + { "JUMPF", Instruction::JUMPF }, { "RJUMP", Instruction::RJUMP }, { "RJUMPI", Instruction::RJUMPI }, { "EOFCREATE", Instruction::EOFCREATE }, @@ -330,6 +333,9 @@ static std::map const c_instructionInfo = {Instruction::LOG2, {"LOG2", 0, 4, 0, true, Tier::Special}}, {Instruction::LOG3, {"LOG3", 0, 5, 0, true, Tier::Special}}, {Instruction::LOG4, {"LOG4", 0, 6, 0, true, Tier::Special}}, + {Instruction::RETF, {"RETF", 0, 0, 0, true, Tier::RetF}}, + {Instruction::CALLF, {"CALLF", 2, 0, 0, true, Tier::CallF}}, + {Instruction::JUMPF, {"JUMPF", 2, 0, 0, true, Tier::JumpF}}, {Instruction::EOFCREATE, {"EOFCREATE", 1, 4, 1, true, Tier::Special}}, {Instruction::RETURNCONTRACT, {"RETURNCONTRACT", 1, 2, 0, true, Tier::Special}}, {Instruction::CREATE, {"CREATE", 0, 3, 1, true, Tier::Special}}, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 84c6e34e6..351a6981c 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -187,6 +187,9 @@ enum class Instruction: uint8_t RJUMP = 0xe0, ///< relative jump RJUMPI = 0xe1, ///< conditional relative jump + CALLF = 0xe3, ///< call function in a EOF code section + RETF = 0xe4, ///< return to caller from the code section of EOF container + JUMPF = 0xe5, ///< jump to a code section of EOF container without adding a new return stack frame. EOFCREATE = 0xec, ///< create a new account with associated container code. RETURNCONTRACT = 0xee, ///< return container to be deployed with axiliary data filled in. CREATE = 0xf0, ///< create a new account with associated code @@ -304,8 +307,11 @@ enum class Tier Base, // 2, Quick RJump, // 2, RJump VeryLow, // 3, Fastest + RetF, // 3, RJumpI, // 4, Low, // 5, Fast + CallF, // 5, + JumpF, // 5, Mid, // 8, Mid High, // 10, Slow BlockHash, // 20 diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index 99a5a0f43..4d61240fb 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -397,6 +397,8 @@ bool SemanticInformation::isDeterministic(AssemblyItem const& _item) case Instruction::RETURNDATACOPY: // depends on previous calls case Instruction::RETURNDATASIZE: case Instruction::EOFCREATE: + case Instruction::CALLF: + case Instruction::JUMPF: return false; default: return true; diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index f469f337d..26364f2af 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -82,6 +82,9 @@ bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersi case Instruction::DATALOADN: case Instruction::RJUMP: case Instruction::RJUMPI: + case Instruction::CALLF: + case Instruction::JUMPF: + case Instruction::RETF: return _eofVersion.has_value(); default: return true; diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index f998b7abb..de1201481 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -209,6 +209,9 @@ std::vector> createBuiltins(langutil::EVMVe opcode != evmasm::Instruction::DATALOADN && opcode != evmasm::Instruction::EOFCREATE && opcode != evmasm::Instruction::RETURNCONTRACT && + opcode != evmasm::Instruction::CALLF && + opcode != evmasm::Instruction::JUMPF && + opcode != evmasm::Instruction::RETF && _evmVersion.hasOpcode(opcode, _eofVersion) && !prevRandaoException(name) ) diff --git a/test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul b/test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul new file mode 100644 index 000000000..2dcd04ca6 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul @@ -0,0 +1,11 @@ +object "a" { + code { + callf() + jumpf() + retf() + } +} +// ---- +// DeclarationError 4619: (32-37): Function "callf" not found. +// DeclarationError 4619: (48-53): Function "jumpf" not found. +// DeclarationError 4619: (64-68): Function "retf" not found. diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index 044fff8ce..92ac56d69 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -488,6 +488,9 @@ u256 EVMInstructionInterpreter::eval( case Instruction::SWAP16: yulAssert(false, "Impossible in strict assembly."); case Instruction::DATALOADN: + case Instruction::CALLF: + case Instruction::RETF: + case Instruction::JUMPF: case Instruction::EOFCREATE: case Instruction::RETURNCONTRACT: case Instruction::RJUMP: From 6f29e6a29e4b5ec6e0b893d8e92947ebef83d296 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 29 Nov 2024 20:21:58 +0100 Subject: [PATCH 0496/1340] eof: Introduce new AssemblyItem types --- libevmasm/AssemblyItem.cpp | 39 +++++++++++++++++++++++++++---- libevmasm/AssemblyItem.h | 8 ++++++- libevmasm/SemanticInformation.cpp | 17 +++++--------- libevmasm/SemanticInformation.h | 1 - 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 96c007ea5..ea670eb0a 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -86,7 +86,10 @@ std::pair AssemblyItem::nameAndData(langutil::EVMVersi case ReturnContract: case RelativeJump: case ConditionalRelativeJump: - return {instructionInfo(instruction(), _evmVersion).name, m_data != nullptr ? toStringInHex(*m_data) : ""}; + case CallF: + case JumpF: + case RetF: + return {instructionInfo(instruction(), _evmVersion).name, ""}; case Push: return {"PUSH", toStringInHex(data())}; case PushTag: @@ -139,6 +142,7 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, langutil::EVMVersion _ { case Operation: case Tag: // 1 byte for the JUMPDEST + case RetF: return 1; case Push: return @@ -181,6 +185,8 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, langutil::EVMVersion _ case RelativeJump: case ConditionalRelativeJump: case AuxDataLoadN: + case JumpF: + case CallF: return 1 + 2; case EOFCreate: return 2; @@ -195,10 +201,15 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, langutil::EVMVersion _ size_t AssemblyItem::arguments() const { - if (hasInstruction()) + if (type() == CallF || type() == JumpF) + return functionSignature().argsNum; + else if (hasInstruction()) + { + solAssert(instruction() != Instruction::CALLF && instruction() != Instruction::JUMPF); // The latest EVMVersion is used here, since the InstructionInfo is assumed to be // the same across all EVM versions except for the instruction name. return static_cast(instructionInfo(instruction(), EVMVersion()).args); + } else if (type() == VerbatimBytecode) return std::get<0>(*m_verbatimBytecode); else if (type() == AssignImmutable) @@ -216,6 +227,7 @@ size_t AssemblyItem::returnValues() const case ReturnContract: case RelativeJump: case ConditionalRelativeJump: + case RetF: // The latest EVMVersion is used here, since the InstructionInfo is assumed to be // the same across all EVM versions except for the instruction name. return static_cast(instructionInfo(instruction(), EVMVersion()).ret); @@ -235,6 +247,9 @@ size_t AssemblyItem::returnValues() const return std::get<1>(*m_verbatimBytecode); case AuxDataLoadN: return 1; + case JumpF: + case CallF: + return functionSignature().canContinue() ? functionSignature().retsNum : 0; case AssignImmutable: case UndefinedItem: break; @@ -253,6 +268,9 @@ bool AssemblyItem::canBeFunctional() const case ReturnContract: case RelativeJump: case ConditionalRelativeJump: + case CallF: + case JumpF: + case RetF: return !isDupInstruction(instruction()) && !isSwapInstruction(instruction()); case Push: case PushTag: @@ -383,6 +401,15 @@ std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const case ConditionalRelativeJump: text = "rjumpi{" + std::string("tag_") + std::to_string(relativeJumpTagID()) + "}"; break; + case CallF: + text = "callf{" + std::string("code_section_") + std::to_string(static_cast(data())) + "}"; + break; + case JumpF: + text = "jumpf{" + std::string("code_section_") + std::to_string(static_cast(data())) + "}"; + break; + case RetF: + text = "retf"; + break; } if (m_jumpType == JumpType::IntoFunction || m_jumpType == JumpType::OutOfFunction) { @@ -405,6 +432,9 @@ std::ostream& solidity::evmasm::operator<<(std::ostream& _out, AssemblyItem cons case ReturnContract: case RelativeJump: case ConditionalRelativeJump: + case CallF: + case JumpF: + case RetF: _out << " " << instructionInfo(_item.instruction(), EVMVersion()).name; if (_item.instruction() == Instruction::JUMP || _item.instruction() == Instruction::JUMPI) _out << "\t" << _item.getJumpTypeAsString(); @@ -509,10 +539,9 @@ std::string AssemblyItem::computeSourceMapping( static_cast(_sourceIndicesMap.at(*location.sourceName)) : -1; char jump = '-'; - // TODO: Uncomment when EOF functions introduced. - if (item.getJumpType() == evmasm::AssemblyItem::JumpType::IntoFunction /*|| item.type() == CallF || item.type() == JumpF*/) + if (item.getJumpType() == evmasm::AssemblyItem::JumpType::IntoFunction || item.type() == CallF || item.type() == JumpF) jump = 'i'; - else if (item.getJumpType() == evmasm::AssemblyItem::JumpType::OutOfFunction /*|| item.type() == RetF*/) + else if (item.getJumpType() == evmasm::AssemblyItem::JumpType::OutOfFunction || item.type() == RetF) jump = 'o'; int modifierDepth = static_cast(item.m_modifierDepth); diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index a9c46bb14..62e21008b 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -59,6 +59,9 @@ enum AssemblyItemType ReturnContract, ///< Returns new container (with auxiliary data filled in) to be deployed RelativeJump, ///< Jumps to relative position accordingly to its argument ConditionalRelativeJump, ///< Same as RelativeJump but takes condition from the stack + CallF, ///< Jumps to a returning EOF function, adding a new frame to the return stack. + JumpF, ///< Jumps to a returning or non-returning EOF function without changing the return stack. + RetF, ///< Returns from an EOF function, removing a frame from the return stack. VerbatimBytecode ///< Contains data that is inserted into the bytecode code section without modification. }; @@ -164,7 +167,10 @@ class AssemblyItem m_type == EOFCreate || m_type == ReturnContract || m_type == RelativeJump || - m_type == ConditionalRelativeJump; + m_type == ConditionalRelativeJump || + m_type == CallF || + m_type == JumpF || + m_type == RetF; } /// @returns the instruction of this item (only valid if hasInstruction returns true) Instruction instruction() const diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index 4d61240fb..c27945b82 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -231,6 +231,9 @@ bool SemanticInformation::breaksCSEAnalysisBlock(AssemblyItem const& _item, bool case PushDeployTimeAddress: case AssignImmutable: case VerbatimBytecode: + case CallF: + case JumpF: + case RetF: return true; case Push: case PushTag: @@ -301,17 +304,6 @@ bool SemanticInformation::isSwapInstruction(AssemblyItem const& _item) return evmasm::isSwapInstruction(_item.instruction()); } -bool SemanticInformation::isJumpInstruction(AssemblyItem const& _item) -{ - return - _item == Instruction::JUMP || - _item == Instruction::JUMPI || - _item == Instruction::RJUMP || - _item == Instruction::RJUMPI || - _item.type() == RelativeJump || - _item.type() == ConditionalRelativeJump; -} - bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) { if (!_item.hasInstruction()) @@ -331,6 +323,9 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) case Instruction::INVALID: case Instruction::REVERT: case Instruction::RETURNCONTRACT: + case Instruction::CALLF: + case Instruction::JUMPF: + case Instruction::RETF: return true; default: return false; diff --git a/libevmasm/SemanticInformation.h b/libevmasm/SemanticInformation.h index b62832f23..457f60052 100644 --- a/libevmasm/SemanticInformation.h +++ b/libevmasm/SemanticInformation.h @@ -82,7 +82,6 @@ struct SemanticInformation static bool isCommutativeOperation(AssemblyItem const& _item); static bool isDupInstruction(AssemblyItem const& _item); static bool isSwapInstruction(AssemblyItem const& _item); - static bool isJumpInstruction(AssemblyItem const& _item); static bool altersControlFlow(AssemblyItem const& _item); static bool terminatesControlFlow(AssemblyItem const& _item); static bool terminatesControlFlow(Instruction _instruction); From 15ebc748a77bac100f62ee3d2133a69d382212c9 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 29 Nov 2024 20:21:58 +0100 Subject: [PATCH 0497/1340] eof: Implement new instructions assembly interface and logic --- libevmasm/Assembly.cpp | 81 ++++++++++++++++++++-- libevmasm/Assembly.h | 19 +++++ libevmasm/AssemblyItem.h | 41 ++++++++++- libyul/backends/evm/AbstractAssembly.h | 21 ++++++ libyul/backends/evm/EthAssemblyAdapter.cpp | 25 +++++++ libyul/backends/evm/EthAssemblyAdapter.h | 5 ++ libyul/backends/evm/NoOutputAssembly.cpp | 37 ++++++++++ libyul/backends/evm/NoOutputAssembly.h | 14 ++++ 8 files changed, 238 insertions(+), 5 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 4719d357f..29b8c8a40 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -407,9 +407,15 @@ void Assembly::assemblyStream( f.feed(i, _debugInfoSelection); f.flush(); - // Implementing this requires introduction of CALLF, RETF and JUMPF - if (m_codeSections.size() > 1) - solUnimplemented("Add support for more code sections"); + for (size_t i = 1; i < m_codeSections.size(); ++i) + { + _out << std::endl << _prefix << "code_section_" << i << ": assembly {\n"; + Functionalizer codeSectionF(_out, _prefix + " ", _sourceCodes, *this); + for (auto const& item: m_codeSections[i].items) + codeSectionF.feed(item, _debugInfoSelection); + codeSectionF.flush(); + _out << _prefix << "}" << std::endl; + } if (!m_data.empty() || !m_subs.empty()) { @@ -696,6 +702,49 @@ AssemblyItem Assembly::namedTag(std::string const& _name, size_t _params, size_t return AssemblyItem{Tag, m_namedTags.at(_name).id}; } +AssemblyItem Assembly::newFunctionCall(uint16_t _functionID) const +{ + solAssert(_functionID < m_codeSections.size(), "Call to undeclared function."); + solAssert(_functionID > 0, "Cannot call section 0"); + auto const& section = m_codeSections.at(_functionID); + if (section.outputs != 0x80) + return AssemblyItem::functionCall(_functionID, section.inputs, section.outputs); + else + return AssemblyItem::jumpToFunction(_functionID, section.inputs, section.outputs); +} + +AssemblyItem Assembly::newFunctionReturn() const +{ + solAssert(m_currentCodeSection != 0, "Appending function return without begin function."); + return AssemblyItem::functionReturn(); +} + +uint16_t Assembly::createFunction(uint8_t _args, uint8_t _rets) +{ + size_t functionID = m_codeSections.size(); + solRequire(functionID < 1024, AssemblyException, "Too many functions for EOF"); + solAssert(m_currentCodeSection == 0, "Functions need to be declared from the main block."); + solAssert(_rets <= 0x80, "Too many function returns."); + solAssert(_args <= 127, "Too many function inputs."); + m_codeSections.emplace_back(CodeSection{_args, _rets, {}}); + return static_cast(functionID); +} + +void Assembly::beginFunction(uint16_t _functionID) +{ + solAssert(m_currentCodeSection == 0, "Attempted to begin a function before ending the last one."); + solAssert(_functionID != 0, "Attempt to begin a function with id 0"); + solAssert(_functionID < m_codeSections.size(), "Attempt to begin an undeclared function."); + auto& section = m_codeSections.at(_functionID); + solAssert(section.items.empty(), "Function already defined."); + m_currentCodeSection = _functionID; +} +void Assembly::endFunction() +{ + solAssert(m_currentCodeSection != 0, "End function without begin function."); + m_currentCodeSection = 0; +} + AssemblyItem Assembly::newPushLibraryAddress(std::string const& _identifier) { h256 h(util::keccak256(_identifier)); @@ -1402,6 +1451,7 @@ LinkerObject const& Assembly::assembleEOF() const for (auto&& [codeSectionIndex, codeSection]: m_codeSections | ranges::views::enumerate) { auto const sectionStart = ret.bytecode.size(); + solAssert(!codeSection.items.empty(), "Empty code section."); for (AssemblyItem const& item: codeSection.items) { // store position of the invalid jump destination @@ -1416,7 +1466,10 @@ LinkerObject const& Assembly::assembleEOF() const item.instruction() != Instruction::RETURNCONTRACT && item.instruction() != Instruction::EOFCREATE && item.instruction() != Instruction::RJUMP && - item.instruction() != Instruction::RJUMPI + item.instruction() != Instruction::RJUMPI && + item.instruction() != Instruction::CALLF && + item.instruction() != Instruction::JUMPF && + item.instruction() != Instruction::RETF ); solAssert(!(item.instruction() >= Instruction::PUSH0 && item.instruction() <= Instruction::PUSH32)); ret.bytecode += assembleOperation(item); @@ -1475,6 +1528,26 @@ LinkerObject const& Assembly::assembleEOF() const appendBigEndianUint16(ret.bytecode, item.data()); break; } + case CallF: + case JumpF: + { + ret.bytecode.push_back(static_cast(item.instruction())); + solAssert(item.data() <= std::numeric_limits::max(), "Invalid callf/jumpf index value."); + size_t const index = static_cast(item.data()); + solAssert(index < m_codeSections.size()); + solAssert(item.functionSignature().argsNum <= 127); + solAssert(item.type() == JumpF || item.functionSignature().retsNum <= 127); + solAssert(item.type() == CallF || item.functionSignature().retsNum <= 128); + solAssert(m_codeSections[index].inputs == item.functionSignature().argsNum); + solAssert(m_codeSections[index].outputs == item.functionSignature().retsNum); + // If CallF the function can continue. + solAssert(item.type() == JumpF || item.functionSignature().canContinue()); + appendBigEndianUint16(ret.bytecode, item.data()); + break; + } + case RetF: + ret.bytecode.push_back(static_cast(Instruction::RETF)); + break; default: solAssert(false, "Unexpected opcode while assembling."); } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 7ef03460c..db567a917 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -65,9 +65,17 @@ class Assembly } std::optional eofVersion() const { return m_eofVersion; } + bool supportsFunctions() const { return m_eofVersion.has_value(); } bool supportsRelativeJumps() const { return m_eofVersion.has_value(); } AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); } AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); } + + AssemblyItem newFunctionCall(uint16_t _functionID) const; + AssemblyItem newFunctionReturn() const; + uint16_t createFunction(uint8_t _args, uint8_t _rets); + void beginFunction(uint16_t _functionID); + void endFunction(); + /// Returns a tag identified by the given name. Creates it if it does not yet exist. AssemblyItem namedTag(std::string const& _name, size_t _params, size_t _returns, std::optional _sourceID); AssemblyItem newData(bytes const& _data) { util::h256 h(util::keccak256(util::asString(_data))); m_data[h] = _data; return AssemblyItem(PushData, h); } @@ -111,6 +119,17 @@ class Assembly return append(AssemblyItem::returnContract(_containerId)); } + AssemblyItem appendFunctionCall(uint16_t _functionID) + { + return append(newFunctionCall(_functionID)); + } + + AssemblyItem appendFunctionReturn() + { + solAssert(m_currentCodeSection != 0, "Appending function return without begin function."); + return append(newFunctionReturn()); + } + AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; } AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; } AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; } diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 62e21008b..28b2fb537 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -108,6 +108,27 @@ class AssemblyItem m_debugData{langutil::DebugData::create()} {} + static AssemblyItem functionCall(uint16_t _functionID, uint8_t _args, uint8_t _rets, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + // TODO: Make this constructor this way that it's impossible to create it without setting functions signature. + // It can be done by template constructor with Instruction as template parameter i.e. Same for JumpF below. + AssemblyItem result(CallF, Instruction::CALLF, _functionID, _debugData); + solAssert(_args <= 127 && _rets <= 127); + result.m_functionSignature = {_args, _rets}; + return result; + } + static AssemblyItem jumpToFunction(uint16_t _functionID, uint8_t _args, uint8_t _rets, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + AssemblyItem result(JumpF, Instruction::JUMPF, _functionID, _debugData); + solAssert(_args <= 127 && _rets <= 128); + result.m_functionSignature = {_args, _rets}; + return result; + } + static AssemblyItem functionReturn(langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + return AssemblyItem(RetF, Instruction::RETF, 0, std::move(_debugData)); + } + static AssemblyItem eofCreate(ContainerID _containerID, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) { return AssemblyItem(EOFCreate, Instruction::EOFCREATE, _containerID, std::move(_debugData)); @@ -146,7 +167,7 @@ class AssemblyItem void setPushTagSubIdAndTag(size_t _subId, size_t _tag); AssemblyItemType type() const { return m_type; } - u256 const& data() const { assertThrow(m_type != Operation, util::Exception, ""); return *m_data; } + u256 const& data() const { solAssert(m_type != Operation && m_data != nullptr); return *m_data; } void setData(u256 const& _data) { assertThrow(m_type != Operation, util::Exception, ""); m_data = std::make_shared(_data); } /// This function is used in `Assembly::assemblyJSON`. @@ -269,12 +290,30 @@ class AssemblyItem void setImmutableOccurrences(size_t _n) const { m_immutableOccurrences = _n; } + struct FunctionSignature + { + /// Number of EOF function arguments. must be less than 127 + uint8_t argsNum; + /// Number of EOF function return values. Must be less than 128. 128(0x80) means that it's non-returning. + uint8_t retsNum; + + bool canContinue() const { return retsNum != 0x80;} + }; + + FunctionSignature const& functionSignature() const + { + solAssert(m_type == CallF || m_type == JumpF); + solAssert(m_functionSignature.has_value()); + return *m_functionSignature; + } + private: size_t opcodeCount() const noexcept; AssemblyItemType m_type; Instruction m_instruction; ///< Only valid if m_type == Operation std::shared_ptr m_data; ///< Only valid if m_type != Operation + std::optional m_functionSignature; ///< Only valid if m_type == CallF or JumpF /// If m_type == VerbatimBytecode, this holds number of arguments, number of /// return variables and verbatim bytecode. std::optional> m_verbatimBytecode; diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index 7c44dfa78..6fe234782 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -57,6 +57,7 @@ class AbstractAssembly using LabelID = size_t; using SubID = size_t; using ContainerID = uint8_t; + using FunctionID = uint16_t; enum class JumpType { Ordinary, IntoFunction, OutOfFunction }; virtual ~AbstractAssembly() = default; @@ -101,6 +102,26 @@ class AbstractAssembly virtual void appendAssemblySize() = 0; /// Creates a new sub-assembly, which can be referenced using dataSize and dataOffset. virtual std::pair, SubID> createSubAssembly(bool _creation, std::string _name = "") = 0; + + /// Registers a new function with given signature and returns its ID. + /// The function is initially empty and its body must be filled with instructions. + virtual FunctionID registerFunction(uint8_t _args, uint8_t _rets) = 0; + /// Selects a function as a target for newly appended instructions. + /// May only be called after the main code section is already filled and + /// must not be called when another function is already selected. + /// Filling the same function more than once is not allowed. + /// @a endFunction() must be called at the end to finalize the function. + virtual void beginFunction(FunctionID _functionID) = 0; + /// Finalizes the process of filling a function body and switches back to the main code section. + /// Must not be called if no function is selected. + /// Must be called after filling the main yul section + virtual void endFunction() = 0; + /// Appends function call to a function under given ID + virtual void appendFunctionCall(FunctionID _functionID) = 0; + /// Appends an instruction that returns values from the current function. + /// Only allowed inside a function body. + virtual void appendFunctionReturn() = 0; + /// Appends the offset of the given sub-assembly or data. virtual void appendDataOffset(std::vector const& _subPath) = 0; /// Appends the size of the given sub-assembly or data. diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index d8810b261..d9cf47f4d 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -145,6 +145,31 @@ std::pair, AbstractAssembly::SubID> EthAssembl return {std::make_shared(*assembly), static_cast(sub.data())}; } +AbstractAssembly::FunctionID EthAssemblyAdapter::registerFunction(uint8_t _args, uint8_t _rets) +{ + return m_assembly.createFunction(_args, _rets); +} + +void EthAssemblyAdapter::beginFunction(AbstractAssembly::FunctionID _functionID) +{ + m_assembly.beginFunction(_functionID); +} + +void EthAssemblyAdapter::endFunction() +{ + m_assembly.endFunction(); +} + +void EthAssemblyAdapter::appendFunctionReturn() +{ + m_assembly.appendFunctionReturn(); +} + +void EthAssemblyAdapter::appendFunctionCall(FunctionID _functionID) +{ + m_assembly.appendFunctionCall(_functionID); +} + void EthAssemblyAdapter::appendEOFCreate(ContainerID _containerID) { m_assembly.appendEOFCreate(_containerID); diff --git a/libyul/backends/evm/EthAssemblyAdapter.h b/libyul/backends/evm/EthAssemblyAdapter.h index d0bd3e14a..29a6fba7b 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.h +++ b/libyul/backends/evm/EthAssemblyAdapter.h @@ -56,6 +56,11 @@ class EthAssemblyAdapter: public AbstractAssembly void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override; void appendAssemblySize() override; std::pair, SubID> createSubAssembly(bool _creation, std::string _name = {}) override; + AbstractAssembly::FunctionID registerFunction(uint8_t _args, uint8_t _rets) override; + void beginFunction(AbstractAssembly::FunctionID _functionID) override; + void endFunction() override; + void appendFunctionCall(FunctionID _functionID) override; + void appendFunctionReturn() override; void appendEOFCreate(ContainerID _containerID) override; void appendReturnContract(ContainerID _containerID) override; void appendDataOffset(std::vector const& _subPath) override; diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 0497b11b6..c9d6c6292 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -120,6 +120,43 @@ std::pair, AbstractAssembly::SubID> NoOutputAs return {}; } +AbstractAssembly::FunctionID NoOutputAssembly::registerFunction(uint8_t _args, uint8_t _rets) +{ + yulAssert(m_context.numFunctions <= std::numeric_limits::max()); + AbstractAssembly::FunctionID id = static_cast(m_context.numFunctions++); + m_context.functionSignatures[id] = std::make_pair(_args, _rets); + return id; +} + +void NoOutputAssembly::beginFunction(FunctionID _functionID) +{ + yulAssert(m_currentFunctionID == 0, "Attempted to begin a function before ending the last one."); + yulAssert(m_context.functionSignatures.count(_functionID) == 1, "Filling unregistered function."); + yulAssert(m_stackHeight == 0, "Non-empty stack on beginFunction call."); + m_currentFunctionID = _functionID; +} + +void NoOutputAssembly::endFunction() +{ + yulAssert(m_currentFunctionID != 0, "End function without begin function."); + auto const rets = m_context.functionSignatures.at(m_currentFunctionID).second; + yulAssert(rets == 0x80 || m_stackHeight == rets, "Stack height mismatch at function end."); + m_currentFunctionID = 0; +} + +void NoOutputAssembly::appendFunctionCall(FunctionID _functionID) +{ + auto [args, rets] = m_context.functionSignatures.at(_functionID); + m_stackHeight += static_cast(rets) - static_cast(args); +} + +void NoOutputAssembly::appendFunctionReturn() +{ + yulAssert(m_currentFunctionID != 0, "End function without begin function."); + auto const rets = m_context.functionSignatures.at(m_currentFunctionID).second; + yulAssert(rets == 0x80 || m_stackHeight == rets, "Stack height mismatch at function end."); +} + void NoOutputAssembly::appendDataOffset(std::vector const&) { appendInstruction(evmasm::Instruction::PUSH1); diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h index 5af1bd418..2669a277c 100644 --- a/libyul/backends/evm/NoOutputAssembly.h +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -37,6 +37,13 @@ struct SourceLocation; namespace solidity::yul { +class NoOutputAssembly; + +struct NoOutputAssemblyContext +{ + size_t numFunctions = 0; + std::map> functionSignatures; +}; /** * Assembly class that just ignores everything and only performs stack counting. @@ -66,6 +73,11 @@ class NoOutputAssembly: public AbstractAssembly void appendAssemblySize() override; std::pair, SubID> createSubAssembly(bool _creation, std::string _name = "") override; + FunctionID registerFunction(uint8_t _args, uint8_t _rets) override; + void beginFunction(FunctionID) override; + void endFunction() override; + void appendFunctionCall(FunctionID _functionID) override; + void appendFunctionReturn() override; void appendDataOffset(std::vector const& _subPath) override; void appendDataSize(std::vector const& _subPath) override; SubID appendData(bytes const& _data) override; @@ -84,7 +96,9 @@ class NoOutputAssembly: public AbstractAssembly langutil::EVMVersion evmVersion() const override { return m_evmVersion; } private: + NoOutputAssemblyContext m_context = {}; int m_stackHeight = 0; + FunctionID m_currentFunctionID = 0; langutil::EVMVersion m_evmVersion; }; From a00ceb90b1c463747c7f8995b03a9dc74173eebc Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 29 Nov 2024 20:21:58 +0100 Subject: [PATCH 0498/1340] eof: Adjust EVM code transform and graph builder for EOF functions --- .../backends/evm/ControlFlowGraphBuilder.cpp | 10 ++- libyul/backends/evm/ControlFlowGraphBuilder.h | 2 + libyul/backends/evm/EVMDialect.h | 3 + .../evm/OptimizedEVMCodeTransform.cpp | 73 ++++++++++++++----- .../backends/evm/OptimizedEVMCodeTransform.h | 6 +- libyul/backends/evm/StackLayoutGenerator.cpp | 31 ++++---- libyul/backends/evm/StackLayoutGenerator.h | 10 ++- libyul/optimiser/StackCompressor.cpp | 6 +- libyul/optimiser/StackLimitEvader.cpp | 2 +- 9 files changed, 103 insertions(+), 40 deletions(-) diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index fe6e0ec8e..e92515e98 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -211,6 +212,10 @@ std::unique_ptr ControlFlowGraphBuilder::build( Block const& _block ) { + std::optional eofVersion; + if (EVMDialect const* evmDialect = dynamic_cast(&_dialect)) + eofVersion = evmDialect->eofVersion(); + auto result = std::make_unique(); result->entry = &result->makeBlock(debugDataOf(_block)); @@ -241,6 +246,8 @@ ControlFlowGraphBuilder::ControlFlowGraphBuilder( m_functionSideEffects(_functionSideEffects), m_dialect(_dialect) { + if (EVMDialect const* evmDialect = dynamic_cast(&m_dialect)) + m_simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); } StackSlot ControlFlowGraphBuilder::operator()(Literal const& _literal) @@ -542,7 +549,8 @@ Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _cal Scope::Function const& function = lookupFunction(_call.functionName.name); canContinue = m_graph.functionInfo.at(&function).canContinue; Stack inputs; - if (canContinue) + // For EOF (m_simulateFunctionsWithJumps == false) we do not have to put return label on stack. + if (m_simulateFunctionsWithJumps && canContinue) inputs.emplace_back(FunctionCallReturnLabelSlot{_call}); for (auto const& arg: _call.arguments | ranges::views::reverse) inputs.emplace_back(std::visit(*this, arg)); diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.h b/libyul/backends/evm/ControlFlowGraphBuilder.h index 77feaea7b..1d0227a56 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.h +++ b/libyul/backends/evm/ControlFlowGraphBuilder.h @@ -90,6 +90,8 @@ class ControlFlowGraphBuilder }; std::optional m_forLoopInfo; std::optional m_currentFunction; + /// True if control flow graph simulates functions with jumps. False otherwise. True for legacy bytecode + bool m_simulateFunctionsWithJumps = true; }; } diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 65cc70f16..58944bdc7 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include #include @@ -44,6 +45,8 @@ struct BuiltinContext Object const* currentObject = nullptr; /// Mapping from named objects to abstract assembly sub IDs. std::map subIDs; + + std::map functionIDs; }; struct BuiltinFunctionForEVM: public BuiltinFunction diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 8ef01f0b6..89a75019e 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -49,13 +49,31 @@ std::vector OptimizedEVMCodeTransform::run( ) { std::unique_ptr dfg = ControlFlowGraphBuilder::build(_analysisInfo, _dialect, _block); - StackLayout stackLayout = StackLayoutGenerator::run(*dfg); + StackLayout stackLayout = StackLayoutGenerator::run(*dfg, !_dialect.eofVersion().has_value()); + + if (_dialect.eofVersion().has_value()) + { + for (Scope::Function const* function: dfg->functions) + { + auto const& info = dfg->functionInfo.at(function); + yulAssert(info.parameters.size() <= 0x7f); + yulAssert(info.returnVariables.size() <= 0x7f); + // According to EOF spec function output num equals 0x80 means non-returning function + auto functionID = _assembly.registerFunction( + static_cast(info.parameters.size()), + static_cast(info.canContinue ? info.returnVariables.size() : 0x80) + ); + _builtinContext.functionIDs[function] = functionID; + } + } + OptimizedEVMCodeTransform optimizedCodeTransform( _assembly, _builtinContext, _useNamedLabelsForFunctions, *dfg, - stackLayout + stackLayout, + !_dialect.eofVersion().has_value() ); // Create initial entry layout. optimizedCodeTransform.createStackLayout(debugDataOf(*dfg->entry), stackLayout.blockInfos.at(dfg->entry).entryLayout); @@ -67,10 +85,11 @@ std::vector OptimizedEVMCodeTransform::run( void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call) { + bool useReturnLabel = m_simulateFunctionsWithJumps && _call.canContinue; // Validate stack. { yulAssert(m_assembly.stackHeight() == static_cast(m_stack.size()), ""); - yulAssert(m_stack.size() >= _call.function.get().numArguments + (_call.canContinue ? 1 : 0), ""); + yulAssert(m_stack.size() >= _call.function.get().numArguments + (useReturnLabel ? 1 : 0), ""); // Assert that we got the correct arguments on stack for the call. for (auto&& [arg, slot]: ranges::zip_view( _call.functionCall.get().arguments | ranges::views::reverse, @@ -78,7 +97,7 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call) )) validateSlot(slot, arg); // Assert that we got the correct return label on stack. - if (_call.canContinue) + if (useReturnLabel) { auto const* returnLabelSlot = std::get_if( &m_stack.at(m_stack.size() - _call.functionCall.get().arguments.size() - 1) @@ -90,21 +109,26 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call) // Emit code. { m_assembly.setSourceLocation(originLocationOf(_call)); - m_assembly.appendJumpTo( - getFunctionLabel(_call.function), - static_cast(_call.function.get().numReturns) - static_cast(_call.function.get().numArguments) - (_call.canContinue ? 1 : 0), - AbstractAssembly::JumpType::IntoFunction - ); - if (_call.canContinue) + if (!m_simulateFunctionsWithJumps) + m_assembly.appendFunctionCall(m_builtinContext.functionIDs.at(&_call.function.get())); + else + m_assembly.appendJumpTo( + getFunctionLabel(_call.function), + static_cast(_call.function.get().numReturns) - static_cast(_call.function.get().numArguments) - (_call.canContinue ? 1 : 0), + AbstractAssembly::JumpType::IntoFunction + ); + if (useReturnLabel) m_assembly.appendLabel(m_returnLabels.at(&_call.functionCall.get())); } // Update stack. { // Remove arguments and return label from m_stack. - for (size_t i = 0; i < _call.function.get().numArguments + (_call.canContinue ? 1 : 0); ++i) + for (size_t i = 0; i < _call.function.get().numArguments + (useReturnLabel ? 1 : 0); ++i) m_stack.pop_back(); // Push return values to m_stack. + if (!m_simulateFunctionsWithJumps) + yulAssert(_call.function.get().numReturns < 0x80, "Num of function output >= 128"); for (size_t index: ranges::views::iota(0u, _call.function.get().numReturns)) m_stack.emplace_back(TemporarySlot{_call.functionCall, index}); yulAssert(m_assembly.stackHeight() == static_cast(m_stack.size()), ""); @@ -177,13 +201,14 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( BuiltinContext& _builtinContext, UseNamedLabels _useNamedLabelsForFunctions, CFG const& _dfg, - StackLayout const& _stackLayout + StackLayout const& _stackLayout, + bool _simulateFunctionsWithJumps ): m_assembly(_assembly), m_builtinContext(_builtinContext), m_dfg(_dfg), m_stackLayout(_stackLayout), - m_functionLabels([&](){ + m_functionLabels(!_simulateFunctionsWithJumps ? decltype(m_functionLabels)() : [&](){ std::map functionLabels; std::set assignedFunctionNames; for (Scope::Function const* function: m_dfg.functions) @@ -203,7 +228,8 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( m_assembly.newLabelId(); } return functionLabels; - }()) + }()), + m_simulateFunctionsWithJumps(_simulateFunctionsWithJumps) { } @@ -216,6 +242,7 @@ void OptimizedEVMCodeTransform::assertLayoutCompatibility(Stack const& _currentS AbstractAssembly::LabelID OptimizedEVMCodeTransform::getFunctionLabel(Scope::Function const& _function) { + yulAssert(m_simulateFunctionsWithJumps); return m_functionLabels.at(&m_dfg.functionInfo.at(&_function)); } @@ -493,11 +520,15 @@ void OptimizedEVMCodeTransform::operator()(CFG::BasicBlock const& _block) Stack exitStack = m_currentFunctionInfo->returnVariables | ranges::views::transform([](auto const& _varSlot){ return StackSlot{_varSlot}; }) | ranges::to; - exitStack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function}); + if (m_simulateFunctionsWithJumps) + exitStack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function}); // Create the function return layout and jump. createStackLayout(debugDataOf(_functionReturn), exitStack); - m_assembly.appendJump(0, AbstractAssembly::JumpType::OutOfFunction); + if (!m_simulateFunctionsWithJumps) + m_assembly.appendFunctionReturn(); + else + m_assembly.appendJump(0, AbstractAssembly::JumpType::OutOfFunction); }, [&](CFG::BasicBlock::Terminated const&) { @@ -518,25 +549,31 @@ void OptimizedEVMCodeTransform::operator()(CFG::BasicBlock const& _block) void OptimizedEVMCodeTransform::operator()(CFG::FunctionInfo const& _functionInfo) { + bool useReturnLabel = m_simulateFunctionsWithJumps && _functionInfo.canContinue; yulAssert(!m_currentFunctionInfo, ""); ScopedSaveAndRestore currentFunctionInfoRestore(m_currentFunctionInfo, &_functionInfo); yulAssert(m_stack.empty() && m_assembly.stackHeight() == 0, ""); // Create function entry layout in m_stack. - if (_functionInfo.canContinue) + if (useReturnLabel) m_stack.emplace_back(FunctionReturnLabelSlot{_functionInfo.function}); for (auto const& param: _functionInfo.parameters | ranges::views::reverse) m_stack.emplace_back(param); + if (!m_simulateFunctionsWithJumps) + m_assembly.beginFunction(m_builtinContext.functionIDs[&_functionInfo.function]); m_assembly.setStackHeight(static_cast(m_stack.size())); m_assembly.setSourceLocation(originLocationOf(_functionInfo)); - m_assembly.appendLabel(getFunctionLabel(_functionInfo.function)); + if (m_simulateFunctionsWithJumps) + m_assembly.appendLabel(getFunctionLabel(_functionInfo.function)); // Create the entry layout of the function body block and visit. createStackLayout(debugDataOf(_functionInfo), m_stackLayout.blockInfos.at(_functionInfo.entry).entryLayout); (*this)(*_functionInfo.entry); m_stack.clear(); + if (!m_simulateFunctionsWithJumps) + m_assembly.endFunction(); m_assembly.setStackHeight(0); } diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.h b/libyul/backends/evm/OptimizedEVMCodeTransform.h index 7e648ca96..2c072bcca 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.h +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.h @@ -68,7 +68,8 @@ class OptimizedEVMCodeTransform BuiltinContext& _builtinContext, UseNamedLabels _useNamedLabelsForFunctions, CFG const& _dfg, - StackLayout const& _stackLayout + StackLayout const& _stackLayout, + bool _simulateFunctionsWithJumps ); /// Assert that it is valid to transition from @a _currentStack to @a _desiredStack. @@ -104,12 +105,15 @@ class OptimizedEVMCodeTransform Stack m_stack; std::map m_returnLabels; std::map m_blockLabels; + /// Non-empty only if m_dfg.simulateFunctionsWithJumps == true std::map const m_functionLabels; /// Set of blocks already generated. If any of the contained blocks is ever jumped to, m_blockLabels should /// contain a jump label for it. std::set m_generated; CFG::FunctionInfo const* m_currentFunctionInfo = nullptr; std::vector m_stackErrors; + /// True if it simulates functions with jumps. False otherwise. True for legacy bytecode + bool m_simulateFunctionsWithJumps = true; }; } diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 1a30842ae..3d1d5f7b0 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -47,30 +47,30 @@ using namespace solidity; using namespace solidity::yul; -StackLayout StackLayoutGenerator::run(CFG const& _cfg) +StackLayout StackLayoutGenerator::run(CFG const& _cfg, bool _simulateFunctionsWithJumps) { - StackLayout stackLayout; - StackLayoutGenerator{stackLayout, nullptr}.processEntryPoint(*_cfg.entry); + StackLayout stackLayout{{}, {}}; + StackLayoutGenerator{stackLayout, nullptr, _simulateFunctionsWithJumps}.processEntryPoint(*_cfg.entry); for (auto& functionInfo: _cfg.functionInfo | ranges::views::values) - StackLayoutGenerator{stackLayout, &functionInfo}.processEntryPoint(*functionInfo.entry, &functionInfo); + StackLayoutGenerator{stackLayout, &functionInfo, _simulateFunctionsWithJumps}.processEntryPoint(*functionInfo.entry, &functionInfo); return stackLayout; } -std::map> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg) +std::map> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, bool _simulateFunctionsWithJumps) { std::map> stackTooDeepErrors; - stackTooDeepErrors[YulName{}] = reportStackTooDeep(_cfg, YulName{}); + stackTooDeepErrors[YulName{}] = reportStackTooDeep(_cfg, YulName{}, _simulateFunctionsWithJumps); for (auto const& function: _cfg.functions) - if (auto errors = reportStackTooDeep(_cfg, function->name); !errors.empty()) + if (auto errors = reportStackTooDeep(_cfg, function->name, _simulateFunctionsWithJumps); !errors.empty()) stackTooDeepErrors[function->name] = std::move(errors); return stackTooDeepErrors; } -std::vector StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulName _functionName) +std::vector StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulName _functionName, bool _simulateFunctionsWithJumps) { - StackLayout stackLayout; + StackLayout stackLayout{{}, {}}; CFG::FunctionInfo const* functionInfo = nullptr; if (!_functionName.empty()) { @@ -82,15 +82,16 @@ std::vector StackLayoutGenerator::reportStac yulAssert(functionInfo, "Function not found."); } - StackLayoutGenerator generator{stackLayout, functionInfo}; + StackLayoutGenerator generator{stackLayout, functionInfo, _simulateFunctionsWithJumps}; CFG::BasicBlock const* entry = functionInfo ? functionInfo->entry : _cfg.entry; generator.processEntryPoint(*entry); return generator.reportStackTooDeep(*entry); } -StackLayoutGenerator::StackLayoutGenerator(StackLayout& _layout, CFG::FunctionInfo const* _functionInfo): +StackLayoutGenerator::StackLayoutGenerator(StackLayout& _layout, CFG::FunctionInfo const* _functionInfo, bool _simulateFunctionsWithJumps): m_layout(_layout), - m_currentFunctionInfo(_functionInfo) + m_currentFunctionInfo(_functionInfo), + m_simulateFunctionsWithJumps(_simulateFunctionsWithJumps) { } @@ -464,7 +465,9 @@ std::optional StackLayoutGenerator::getExitLayoutOrStageDependencies( Stack stack = _functionReturn.info->returnVariables | ranges::views::transform([](auto const& _varSlot){ return StackSlot{_varSlot}; }) | ranges::to; - stack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function}); + + if (m_simulateFunctionsWithJumps) + stack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function}); return stack; }, [&](CFG::BasicBlock::Terminated const&) -> std::optional @@ -735,7 +738,7 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi _addChild(_conditionalJump.zero); _addChild(_conditionalJump.nonZero); }, - [&](CFG::BasicBlock::FunctionReturn const&) { yulAssert(false); }, + [&](CFG::BasicBlock::FunctionReturn const&) { yulAssert(!m_simulateFunctionsWithJumps); }, [&](CFG::BasicBlock::Terminated const&) {}, }, _block->exit); }); diff --git a/libyul/backends/evm/StackLayoutGenerator.h b/libyul/backends/evm/StackLayoutGenerator.h index fc846a9de..44cbbd43a 100644 --- a/libyul/backends/evm/StackLayoutGenerator.h +++ b/libyul/backends/evm/StackLayoutGenerator.h @@ -55,18 +55,18 @@ class StackLayoutGenerator std::vector variableChoices; }; - static StackLayout run(CFG const& _cfg); + static StackLayout run(CFG const& _cfg, bool _simulateFunctionsWithJumps); /// @returns a map from function names to the stack too deep errors occurring in that function. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// The empty string is mapped to the stack too deep errors of the main entry point. - static std::map> reportStackTooDeep(CFG const& _cfg); + static std::map> reportStackTooDeep(CFG const& _cfg, bool _simulateFunctionsWithJumps); /// @returns all stack too deep errors in the function named @a _functionName. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// If @a _functionName is empty, the stack too deep errors of the main entry point are reported instead. - static std::vector reportStackTooDeep(CFG const& _cfg, YulName _functionName); + static std::vector reportStackTooDeep(CFG const& _cfg, YulName _functionName, bool _simulateFunctionsWithJumps); private: - StackLayoutGenerator(StackLayout& _context, CFG::FunctionInfo const* _functionInfo); + StackLayoutGenerator(StackLayout& _context, CFG::FunctionInfo const* _functionInfo, bool _simulateFunctionsWithJumps); /// @returns the optimal entry stack layout, s.t. @a _operation can be applied to it and /// the result can be transformed to @a _exitStack with minimal stack shuffling. @@ -116,6 +116,8 @@ class StackLayoutGenerator StackLayout& m_layout; CFG::FunctionInfo const* m_currentFunctionInfo = nullptr; + /// True if it simulates functions with jumps. False otherwise. True for legacy bytecode + bool m_simulateFunctionsWithJumps = true; }; } diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 6ad3899e9..71a0463c9 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -248,11 +248,15 @@ std::tuple StackCompressor::run( "Need to run the function grouper before the stack compressor." ); bool usesOptimizedCodeGenerator = false; + bool simulateFunctionsWithJumps = true; if (auto evmDialect = dynamic_cast(&_dialect)) + { usesOptimizedCodeGenerator = _optimizeStackAllocation && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); + simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); + } bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _object.code()->root()); Block astRoot = std::get(ASTCopier{}(_object.code()->root())); if (usesOptimizedCodeGenerator) @@ -266,7 +270,7 @@ std::tuple StackCompressor::run( eliminateVariablesOptimizedCodegen( _dialect, astRoot, - StackLayoutGenerator::reportStackTooDeep(*cfg), + StackLayoutGenerator::reportStackTooDeep(*cfg, simulateFunctionsWithJumps), allowMSizeOptimization ); } diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 6ef4b267b..02c6de159 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -138,7 +138,7 @@ Block StackLimitEvader::run( _object.summarizeStructure() ); std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, astRoot); - run(_context, astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg)); + run(_context, astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg, !evmDialect->eofVersion().has_value())); } else { From 2bae7e16d9de49c3bccbbe5ac9a84893052767c9 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 29 Nov 2024 20:21:58 +0100 Subject: [PATCH 0499/1340] eof: Add proper errors on arguments and return values count limit exceeded. --- libyul/AsmAnalysis.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index aedf4fd07..491effe8e 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -290,6 +290,23 @@ void AsmAnalyzer::operator()(FunctionDefinition const& _funDef) m_activeVariables.insert(&std::get(varScope.identifiers.at(var.name))); } + if (m_eofVersion.has_value()) + { + if (_funDef.parameters.size() >= 0x80) + m_errorReporter.typeError( + 8534_error, + nativeLocationOf(_funDef), + "Too many function parameters. At most 127 parameters allowed for EOF" + ); + + if (_funDef.returnVariables.size() >= 0x80) + m_errorReporter.typeError( + 2101_error, + nativeLocationOf(_funDef), + "Too many function return variables. At most 127 return variables allowed for EOF" + ); + } + (*this)(_funDef.body); } From 363f3ddee21019336f4d777457781e4627f72acf Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 29 Nov 2024 20:21:58 +0100 Subject: [PATCH 0500/1340] eof: Add test, make needed test support bytecodeFormat flag, adjust subcontainers tests --- test/libyul/ControlFlowGraphTest.cpp | 2 +- test/libyul/ControlFlowGraphTest.h | 2 +- test/libyul/StackLayoutGeneratorTest.cpp | 10 ++- test/libyul/StackLayoutGeneratorTest.h | 2 +- .../objectCompiler/eof/256_subcontainers.yul | 1 - test/libyul/objectCompiler/eof/functions.yul | 84 +++++++++++++++++++ ...oo_many_functions_arguments_or_returns.yul | 26 ++++++ .../eof/too_many_subcontainers.yul | 1 - 8 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 test/libyul/objectCompiler/eof/functions.yul create mode 100644 test/libyul/yulSyntaxTests/eof/too_many_functions_arguments_or_returns.yul diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index b7264bc0e..0aaaea581 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -41,7 +41,7 @@ using namespace solidity::frontend; using namespace solidity::frontend::test; ControlFlowGraphTest::ControlFlowGraphTest(std::string const& _filename): - TestCase(_filename) + EVMVersionRestrictedTestCase(_filename) { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); diff --git a/test/libyul/ControlFlowGraphTest.h b/test/libyul/ControlFlowGraphTest.h index 44cea06d3..e9de50a61 100644 --- a/test/libyul/ControlFlowGraphTest.h +++ b/test/libyul/ControlFlowGraphTest.h @@ -27,7 +27,7 @@ struct Dialect; namespace test { -class ControlFlowGraphTest: public solidity::frontend::test::TestCase +class ControlFlowGraphTest: public frontend::test::EVMVersionRestrictedTestCase { public: static std::unique_ptr create(Config const& _config) diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index f50d2d23b..49af089ef 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -45,7 +46,7 @@ using namespace solidity::frontend; using namespace solidity::frontend::test; StackLayoutGeneratorTest::StackLayoutGeneratorTest(std::string const& _filename): - TestCase(_filename) + EVMVersionRestrictedTestCase(_filename) { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); @@ -229,7 +230,12 @@ TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::s std::ostringstream output; std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code()->root()); - StackLayout stackLayout = StackLayoutGenerator::run(*cfg); + + bool simulateFunctionsWithJumps = true; + if (auto const* evmDialect = dynamic_cast(m_dialect)) + simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); + + StackLayout stackLayout = StackLayoutGenerator::run(*cfg, simulateFunctionsWithJumps); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; StackLayoutPrinter printer{output, stackLayout}; diff --git a/test/libyul/StackLayoutGeneratorTest.h b/test/libyul/StackLayoutGeneratorTest.h index 9f570045f..6116b1df7 100644 --- a/test/libyul/StackLayoutGeneratorTest.h +++ b/test/libyul/StackLayoutGeneratorTest.h @@ -27,7 +27,7 @@ struct Dialect; namespace test { -class StackLayoutGeneratorTest: public solidity::frontend::test::TestCase +class StackLayoutGeneratorTest: public frontend::test::EVMVersionRestrictedTestCase { public: static std::unique_ptr create(Config const& _config) diff --git a/test/libyul/objectCompiler/eof/256_subcontainers.yul b/test/libyul/objectCompiler/eof/256_subcontainers.yul index 06aebd674..46df86355 100644 --- a/test/libyul/objectCompiler/eof/256_subcontainers.yul +++ b/test/libyul/objectCompiler/eof/256_subcontainers.yul @@ -517,7 +517,6 @@ object "a" { } // ==== -// EVMVersion: >=prague // bytecodeFormat: >=EOFv1 // ---- // Assembly: diff --git a/test/libyul/objectCompiler/eof/functions.yul b/test/libyul/objectCompiler/eof/functions.yul new file mode 100644 index 000000000..72167f72a --- /dev/null +++ b/test/libyul/objectCompiler/eof/functions.yul @@ -0,0 +1,84 @@ +object "a" { + code { + mstore(0, fun1(calldataload(0))) + + if calldataload(32) { + non_ret_fun() + } + + return(0, 32) + + function fun1(i) -> r { + if i { + r := 5 + leave + } + r := 99 + } + + function non_ret_fun() { + revert(0, 0) + } + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":74:75 */ +// 0x00 +// /* "source":61:76 */ +// calldataload +// /* "source":56:77 */ +// callf{code_section_1} +// /* "source":53:54 */ +// 0x00 +// /* "source":46:78 */ +// mstore +// /* "source":107:109 */ +// 0x20 +// /* "source":94:110 */ +// calldataload +// /* "source":91:128 */ +// rjumpi{tag_1} +// /* "source":22:386 */ +// tag_2: +// /* "source":151:153 */ +// 0x20 +// /* "source":148:149 */ +// 0x00 +// /* "source":141:154 */ +// return +// /* "source":111:128 */ +// tag_1: +// /* "source":113:126 */ +// jumpf{code_section_2} +// +// code_section_1: assembly { +// /* "source":217:294 */ +// rjumpi{tag_3} +// /* "source":203:324 */ +// tag_4: +// /* "source":312:314 */ +// 0x63 +// /* "source":173:324 */ +// retf +// /* "source":234:294 */ +// tag_3: +// /* "source":257:258 */ +// 0x05 +// /* "source":275:280 */ +// retf +// } +// +// code_section_2: assembly { +// /* "source":376:377 */ +// 0x00 +// /* "source":366:378 */ +// dup1 +// revert +// } +// Bytecode: ef000101000c020003001400090003040000000080ffff0101ffff0080ffff5f35e300015f52602035e1000460205ff3e50002e100036063e46005e45f80fd +// Opcodes: 0xEF STOP ADD ADD STOP 0xC MUL STOP SUB STOP EQ STOP MULMOD STOP SUB DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT ADD ADD SELFDESTRUCT SELFDESTRUCT STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH0 CALLDATALOAD CALLF 0x1 PUSH0 MSTORE PUSH1 0x20 CALLDATALOAD RJUMPI 0x4 PUSH1 0x20 PUSH0 RETURN JUMPF 0x2 RJUMPI 0x3 PUSH1 0x63 RETF PUSH1 0x5 RETF PUSH0 DUP1 REVERT +// SourceMappings: 74:1:0:-:0;61:15;56:21::i;53:1::-;46:32;107:2;94:16;91:37;22:364;151:2;148:1;141:13;111:17;113:13::i217:77:0:-:0;203:121;312:2;173:151::o;234:60::-;257:1;275:5::o376:1:0:-:0;366:12; diff --git a/test/libyul/yulSyntaxTests/eof/too_many_functions_arguments_or_returns.yul b/test/libyul/yulSyntaxTests/eof/too_many_functions_arguments_or_returns.yul new file mode 100644 index 000000000..623bf6ded --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/too_many_functions_arguments_or_returns.yul @@ -0,0 +1,26 @@ +object "a" { + code { + function too_many_arguments( + i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, + i31, i32, i33, i34, i35, i36, i37, i38, i39, i40, i41, i42, i43, i44, i45, i46, i47, i48, i49, i50, i51, i52, i53, i54, i55, i56, i57, i58, i59, i60, + i61, i62, i63, i64, i65, i66, i67, i68, i69, i70, i71, i72, i73, i74, i75, i76, i77, i78, i79, i80, i81, i82, i83, i84, i85, i86, i87, i88, i89, i90, + i91, i92, i93, i94, i95, i96, i97, i98, i99, i100, i101, i102, i103, i104, i105, i106, i107, i108, i109, i110, i111, i112, i113, i114, i115, i116, i117, i118, i119, i120, + i121, i122, i123, i124, i125, i126, i127, i128 + ) + {} + + function too_many_returns()-> + i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, + i31, i32, i33, i34, i35, i36, i37, i38, i39, i40, i41, i42, i43, i44, i45, i46, i47, i48, i49, i50, i51, i52, i53, i54, i55, i56, i57, i58, i59, i60, + i61, i62, i63, i64, i65, i66, i67, i68, i69, i70, i71, i72, i73, i74, i75, i76, i77, i78, i79, i80, i81, i82, i83, i84, i85, i86, i87, i88, i89, i90, + i91, i92, i93, i94, i95, i96, i97, i98, i99, i100, i101, i102, i103, i104, i105, i106, i107, i108, i109, i110, i111, i112, i113, i114, i115, i116, i117, i118, i119, i120, + i121, i122, i123, i124, i125, i126, i127, i128 + {} + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 8534: (32-800): Too many function parameters. At most 127 parameters allowed for EOF +// TypeError 2101: (810-1569): Too many function return variables. At most 127 return variables allowed for EOF diff --git a/test/libyul/yulSyntaxTests/eof/too_many_subcontainers.yul b/test/libyul/yulSyntaxTests/eof/too_many_subcontainers.yul index f39d6f2d8..314d4fa3d 100644 --- a/test/libyul/yulSyntaxTests/eof/too_many_subcontainers.yul +++ b/test/libyul/yulSyntaxTests/eof/too_many_subcontainers.yul @@ -264,7 +264,6 @@ object "a" { } // ==== -// EVMVersion: >=prague // bytecodeFormat: >=EOFv1 // ---- // SyntaxError 1305: (22-101): Too many subobjects in "a". At most 256 subobjects allowed when compiling to EOF From 120e344b4eca4c42a405fe2da84b02468f921ada Mon Sep 17 00:00:00 2001 From: rodiazet Date: Sat, 30 Nov 2024 12:10:16 +0100 Subject: [PATCH 0501/1340] eof: Hide rjumps in yul --- libyul/backends/evm/EVMDialect.cpp | 2 ++ test/libyul/yulSyntaxTests/eof/rjump_rjumpi.yul | 11 +++++++++++ 2 files changed, 13 insertions(+) create mode 100644 test/libyul/yulSyntaxTests/eof/rjump_rjumpi.yul diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index de1201481..4d160b030 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -209,6 +209,8 @@ std::vector> createBuiltins(langutil::EVMVe opcode != evmasm::Instruction::DATALOADN && opcode != evmasm::Instruction::EOFCREATE && opcode != evmasm::Instruction::RETURNCONTRACT && + opcode != evmasm::Instruction::RJUMP && + opcode != evmasm::Instruction::RJUMPI && opcode != evmasm::Instruction::CALLF && opcode != evmasm::Instruction::JUMPF && opcode != evmasm::Instruction::RETF && diff --git a/test/libyul/yulSyntaxTests/eof/rjump_rjumpi.yul b/test/libyul/yulSyntaxTests/eof/rjump_rjumpi.yul new file mode 100644 index 000000000..00042ae65 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/rjump_rjumpi.yul @@ -0,0 +1,11 @@ +object "a" { + code { + rjump() + rjumpi() + } +} +// ==== +// bytecodeFormat: legacy,>=EOFv1 +// ---- +// DeclarationError 4619: (32-37): Function "rjump" not found. +// DeclarationError 4619: (48-54): Function "rjumpi" not found. From a0ec6a49955867775dbfe3d2afdce6d19e45c9fa Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 31 Oct 2024 11:27:10 +0100 Subject: [PATCH 0502/1340] Yul: Store dialect in the AST --- libsolidity/ast/ASTJsonImporter.cpp | 2 +- libsolidity/codegen/CompilerContext.cpp | 7 ++++--- libsolidity/codegen/ContractCompiler.cpp | 4 ++-- libyul/AST.h | 8 ++++++-- libyul/AsmJsonImporter.cpp | 2 +- libyul/AsmJsonImporter.h | 6 +++++- libyul/AsmParser.cpp | 2 +- libyul/Object.cpp | 13 +++++++++++-- libyul/Object.h | 6 ++---- libyul/ObjectOptimizer.cpp | 4 ++-- libyul/ObjectParser.cpp | 4 ++-- libyul/optimiser/StackCompressor.cpp | 3 ++- libyul/optimiser/Suite.cpp | 10 +++++----- test/libyul/CompilabilityChecker.cpp | 3 ++- test/libyul/ControlFlowSideEffectsTest.cpp | 2 +- test/libyul/FunctionSideEffects.cpp | 2 +- test/libyul/KnowledgeBaseTest.cpp | 2 +- test/libyul/YulOptimizerTest.cpp | 3 ++- test/libyul/YulOptimizerTestCommon.cpp | 6 +++--- test/tools/yulopti.cpp | 4 ++-- tools/yulPhaser/Program.cpp | 8 ++++---- 21 files changed, 60 insertions(+), 41 deletions(-) diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index ee52bf53c..5d59308ae 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -742,7 +742,7 @@ ASTPointer ASTJsonImporter::createInlineAssembly(Json const& _no flags->emplace_back(std::make_shared(flag.get())); } } - std::shared_ptr operations = std::make_shared(yul::AsmJsonImporter(m_sourceNames).createAST(member(_node, "AST"))); + std::shared_ptr operations = std::make_shared(yul::AsmJsonImporter(dialect, m_sourceNames).createAST(member(_node, "AST"))); return createASTNode( _node, nullOrASTString(_node, "documentation"), diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 84de00656..c09b33a00 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -481,7 +481,7 @@ void CompilerContext::appendInlineAssembly( // so we essentially only optimize the ABI functions. if (_optimiserSettings.runYulOptimiser && _localVariables.empty()) { - yul::Object obj{dialect}; + yul::Object obj; obj.setCode(parserResult, std::make_shared(analysisInfo)); solAssert(!dialect.providesObjectAccess()); @@ -491,8 +491,9 @@ void CompilerContext::appendInlineAssembly( { // Store as generated sources, but first re-parse to update the source references. solAssert(m_generatedYulUtilityCode.empty(), ""); - m_generatedYulUtilityCode = yul::AsmPrinter(obj.dialect())(obj.code()->root()); - std::string code = yul::AsmPrinter{obj.dialect()}(obj.code()->root()); + solAssert(obj.dialect()); + m_generatedYulUtilityCode = yul::AsmPrinter(*obj.dialect())(obj.code()->root()); + std::string code = yul::AsmPrinter{*obj.dialect()}(obj.code()->root()); langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); obj.setCode(yul::Parser(errorReporter, dialect).parse(charStream)); obj.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj)); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 97ffb17e9..3548d0ae7 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -932,7 +932,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) // Only used in the scope below, but required to live outside to keep the // std::shared_ptr's alive - yul::Object object{_inlineAssembly.dialect()}; + yul::Object object; // The optimiser cannot handle external references if ( @@ -944,7 +944,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) solAssert(dialect, ""); // Create a modifiable copy of the code and analysis - object.setCode(std::make_shared(yul::ASTCopier().translate(code->root()))); + object.setCode(std::make_shared(_inlineAssembly.dialect(), yul::ASTCopier().translate(code->root()))); object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object)); m_context.optimizeYul(object, *dialect, m_optimiserSettings); diff --git a/libyul/AST.h b/libyul/AST.h index f51846280..be734fa6b 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -36,6 +36,8 @@ namespace solidity::yul { +struct Dialect; + struct NameWithDebugData { langutil::DebugData::ConstPtr debugData; YulName name; }; using NameWithDebugDataList = std::vector; @@ -103,10 +105,12 @@ struct Leave { langutil::DebugData::ConstPtr debugData; }; class AST { public: - explicit AST(Block _root): m_root(std::move(_root)) {} + AST(Dialect const& _dialect, Block _root): m_dialect(_dialect), m_root(std::move(_root)) {} - [[nodiscard]] Block const& root() const { return m_root; } + Dialect const& dialect() const { return m_dialect; } + Block const& root() const { return m_root; } private: + Dialect const& m_dialect; Block m_root; }; diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index 459d9d9be..692169fd2 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -51,7 +51,7 @@ SourceLocation const AsmJsonImporter::createSourceLocation(Json const& _node) AST AsmJsonImporter::createAST(solidity::Json const& _node) { - return AST(createBlock(_node)); + return {m_dialect, createBlock(_node)}; } template diff --git a/libyul/AsmJsonImporter.h b/libyul/AsmJsonImporter.h index f3df8c178..2d7ff472c 100644 --- a/libyul/AsmJsonImporter.h +++ b/libyul/AsmJsonImporter.h @@ -32,13 +32,16 @@ namespace solidity::yul { +struct Dialect; + /** * Component that imports an AST from json format to the internal format */ class AsmJsonImporter { public: - explicit AsmJsonImporter(std::vector> const& _sourceNames): + explicit AsmJsonImporter(Dialect const& _dialect, std::vector> const& _sourceNames): + m_dialect(_dialect), m_sourceNames(_sourceNames) {} @@ -73,6 +76,7 @@ class AsmJsonImporter yul::Break createBreak(Json const& _node); yul::Continue createContinue(Json const& _node); + Dialect const& m_dialect; std::vector> const& m_sourceNames; }; diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 26a4d386d..baef6a3c5 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -125,7 +125,7 @@ std::unique_ptr Parser::parseInline(std::shared_ptr const& _scanne m_scanner = _scanner; if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments) fetchDebugDataFromComment(); - return std::make_unique(parseBlock()); + return std::make_unique(m_dialect, parseBlock()); } catch (FatalError const& error) { diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 3bd0531f4..0dfa610d0 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -49,10 +49,11 @@ std::string Object::toString( ) const { yulAssert(hasCode(), "No code"); + yulAssert(dialect(), "No dialect"); yulAssert(debugData, "No debug data"); std::string inner = "code " + AsmPrinter( - m_dialect, + *dialect(), debugData->sourceNames, _debugInfoSelection, _soliditySourceProvider @@ -94,10 +95,11 @@ std::string ObjectDebugData::formatUseSrcComment() const Json Object::toJson() const { yulAssert(hasCode(), "No code"); + yulAssert(dialect(), "No dialect"); Json codeJson; codeJson["nodeType"] = "YulCode"; - codeJson["block"] = AsmJsonConverter(m_dialect, 0 /* sourceIndex */)(code()->root()); + codeJson["block"] = AsmJsonConverter(*dialect(), 0 /* sourceIndex */)(code()->root()); Json subObjectsJson = Json::array(); for (std::shared_ptr const& subObject: subObjects) @@ -240,3 +242,10 @@ bool Object::hasContiguousSourceIndices() const solAssert(maxSourceIndex + 1 >= indices.size()); return indices.size() == 0 || indices.size() == maxSourceIndex + 1; } + +Dialect const* Object::dialect() const +{ + if (!m_code) + return nullptr; + return &m_code->dialect(); +} diff --git a/libyul/Object.h b/libyul/Object.h index 2109b69ae..295c4a87c 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -21,8 +21,8 @@ #pragma once -#include #include +#include #include #include @@ -91,7 +91,6 @@ struct ObjectDebugData class Object: public ObjectNode { public: - explicit Object(Dialect const& _dialect): m_dialect(_dialect) {} /// @returns a (parseable) string representation. std::string toString( langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), @@ -162,10 +161,9 @@ class Object: public ObjectNode /// @returns the name of the special metadata data object. static std::string metadataName() { return ".metadata"; } - Dialect const& dialect() const { return m_dialect; } + Dialect const* dialect() const; private: - Dialect const& m_dialect; std::shared_ptr m_code; }; diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index 6a6354f94..d7c1526cb 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -118,12 +118,12 @@ void ObjectOptimizer::overwriteWithOptimizedObject(util::h256 _cacheKey, Object& CachedObject const& cachedObject = m_cachedObjects.at(_cacheKey); yulAssert(cachedObject.optimizedAST); - _object.setCode(std::make_shared(ASTCopier{}.translate(*cachedObject.optimizedAST))); + yulAssert(cachedObject.dialect); + _object.setCode(std::make_shared(*cachedObject.dialect, ASTCopier{}.translate(*cachedObject.optimizedAST))); yulAssert(_object.code()); // There's no point in caching AnalysisInfo because it references AST nodes. It can't be shared // by multiple ASTs and it's easier to recalculate it than properly clone it. - yulAssert(cachedObject.dialect); _object.analysisInfo = std::make_shared( AsmAnalyzer::analyzeStrictAssertCorrect( *cachedObject.dialect, diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 67f5b70dd..123dedcb4 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -49,7 +49,7 @@ std::shared_ptr ObjectParser::parse(std::shared_ptr const& _sca if (currentToken() == Token::LBrace) { // Special case: Code-only form. - object = std::make_shared(m_dialect); + object = std::make_shared(); object->name = "object"; auto sourceNameMapping = tryParseSourceNameMapping(); object->debugData = std::make_shared(ObjectDebugData{sourceNameMapping}); @@ -74,7 +74,7 @@ std::shared_ptr ObjectParser::parseObject(Object* _containingObject) { RecursionGuard guard(*this); - std::shared_ptr ret = std::make_shared(m_dialect); + std::shared_ptr ret = std::make_shared(); auto sourceNameMapping = tryParseSourceNameMapping(); ret->debugData = std::make_shared(ObjectDebugData{sourceNameMapping}); diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 71a0463c9..686fb6695 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -243,6 +243,7 @@ std::tuple StackCompressor::run( size_t _maxIterations) { yulAssert(_object.hasCode()); + yulAssert(_object.dialect(), "No dialect"); yulAssert( !_object.code()->root().statements.empty() && std::holds_alternative(_object.code()->root().statements.at(0)), "Need to run the function grouper before the stack compressor." @@ -279,7 +280,7 @@ std::tuple StackCompressor::run( for (size_t iterations = 0; iterations < _maxIterations; iterations++) { Object object(_object); - object.setCode(std::make_shared(std::get(ASTCopier{}(astRoot)))); + object.setCode(std::make_shared(*_object.dialect(), std::get(ASTCopier{}(astRoot)))); std::map stackSurplus = CompilabilityChecker(_dialect, object, _optimizeStackAllocation).stackDeficit; if (stackSurplus.empty()) return std::make_tuple(true, std::move(astRoot)); diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index c6b5f8cfc..0bef31472 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -138,7 +138,7 @@ void OptimiserSuite::run( if (!usesOptimizedCodeGenerator) { PROFILER_PROBE("StackCompressor", probe); - _object.setCode(std::make_shared(std::move(astRoot))); + _object.setCode(std::make_shared(_dialect, std::move(astRoot))); astRoot = std::get<1>(StackCompressor::run( _dialect, _object, @@ -165,7 +165,7 @@ void OptimiserSuite::run( { { PROFILER_PROBE("StackCompressor", probe); - _object.setCode(std::make_shared(std::move(astRoot))); + _object.setCode(std::make_shared(_dialect, std::move(astRoot))); astRoot = std::get<1>(StackCompressor::run( _dialect, _object, @@ -176,14 +176,14 @@ void OptimiserSuite::run( if (evmDialect->providesObjectAccess()) { PROFILER_PROBE("StackLimitEvader", probe); - _object.setCode(std::make_shared(std::move(astRoot))); + _object.setCode(std::make_shared(_dialect, std::move(astRoot))); astRoot = StackLimitEvader::run(suite.m_context, _object); } } else if (evmDialect->providesObjectAccess() && _optimizeStackAllocation) { PROFILER_PROBE("StackLimitEvader", probe); - _object.setCode(std::make_shared(std::move(astRoot))); + _object.setCode(std::make_shared(_dialect, std::move(astRoot))); astRoot = StackLimitEvader::run(suite.m_context, _object); } } @@ -198,7 +198,7 @@ void OptimiserSuite::run( VarNameCleaner::run(suite.m_context, astRoot); } - _object.setCode(std::make_shared(std::move(astRoot))); + _object.setCode(std::make_shared(_dialect, std::move(astRoot))); _object.analysisInfo = std::make_shared(AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object)); } diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index 9691efa21..daa8f61aa 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -38,10 +38,11 @@ std::string check(std::string const& _input) solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().eofVersion() ); - Object obj{dialect}; + Object obj; auto parsingResult = yul::test::parse(_input); obj.setCode(parsingResult.first, parsingResult.second); BOOST_REQUIRE(obj.hasCode()); + BOOST_REQUIRE(obj.dialect()); auto functions = CompilabilityChecker(dialect, obj, true).stackDeficit; std::string out; for (auto const& function: functions) diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index 799f64ce7..3dc576c8e 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -60,7 +60,7 @@ TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std: solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().eofVersion() ); - Object obj{dialect}; + Object obj; auto parsingResult = yul::test::parse(m_source); obj.setCode(parsingResult.first, parsingResult.second); if (!obj.hasCode()) diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index bd9a9da07..46a7c99fe 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -86,7 +86,7 @@ TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().eofVersion() ); - Object obj{dialect}; + Object obj; auto parsingResult = yul::test::parse(m_source); obj.setCode(parsingResult.first, parsingResult.second); if (!obj.hasCode()) diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index 253e7e0d5..0e7d411a3 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -59,7 +59,7 @@ class KnowledgeBaseTest for (auto const& [name, expression]: m_ssaValues.values()) m_values[name].value = expression; - m_object->setCode(std::make_shared(std::move(astRoot))); + m_object->setCode(std::make_shared(m_dialect, std::move(astRoot))); return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }); } diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index c17beb84d..ad7485aea 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -84,8 +84,9 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co } auto optimizedObject = tester.optimizedObject(); std::string printedOptimizedObject; + soltestAssert(optimizedObject->dialect()); if (optimizedObject->subObjects.empty()) - printedOptimizedObject = AsmPrinter{optimizedObject->dialect()}(optimizedObject->code()->root()); + printedOptimizedObject = AsmPrinter{*optimizedObject->dialect()}(optimizedObject->code()->root()); else printedOptimizedObject = optimizedObject->toString(); diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 0f94f309d..9b8d2073c 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -410,7 +410,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( size_t maxIterations = 16; { Object object(*m_optimizedObject); - object.setCode(std::make_shared(std::get(ASTCopier{}(block)))); + object.setCode(std::make_shared(*m_dialect, std::get(ASTCopier{}(block)))); block = std::get<1>(StackCompressor::run(*m_dialect, object, true, maxIterations)); } BlockFlattener::run(*m_context, block); @@ -433,7 +433,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( auto block = disambiguate(); updateContext(block); Object object(*m_optimizedObject); - object.setCode(std::make_shared(std::get(ASTCopier{}(block)))); + object.setCode(std::make_shared(*m_dialect, std::get(ASTCopier{}(block)))); auto const unreachables = CompilabilityChecker{ *m_dialect, object, @@ -500,7 +500,7 @@ bool YulOptimizerTestCommon::runStep() if (m_namedSteps.count(m_optimizerStep)) { auto block = m_namedSteps[m_optimizerStep](); - m_optimizedObject->setCode(std::make_shared(std::move(block))); + m_optimizedObject->setCode(std::make_shared(*m_dialect, std::move(block))); } else return false; diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 3221dce8c..5b634de36 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -217,8 +217,8 @@ class YulOpti break; case ';': { - Object obj{m_dialect}; - obj.setCode(std::make_shared(std::get(ASTCopier{}(*m_astRoot)))); + Object obj; + obj.setCode(std::make_shared(m_dialect, std::get(ASTCopier{}(*m_astRoot)))); *m_astRoot = std::get<1>(StackCompressor::run(m_dialect, obj, true, 16)); break; } diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 25cc8c550..9e16826d9 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -59,7 +59,7 @@ std::ostream& operator<<(std::ostream& _stream, Program const& _program); } Program::Program(Program const& program): - m_ast(std::make_unique(std::get(ASTCopier{}(program.m_ast->root())))), + m_ast(std::make_unique(program.m_dialect, std::get(ASTCopier{}(program.m_ast->root())))), m_dialect{program.m_dialect}, m_nameDispenser(program.m_nameDispenser) { @@ -150,7 +150,7 @@ std::variant, ErrorList> Program::parseObject(Dialect const // The public API of the class does not provide access to the smart pointer so it won't be hard // to switch to shared_ptr if the copying turns out to be an issue (though it would be better // to refactor ObjectParser and Object to use unique_ptr instead). - auto astCopy = std::make_unique(std::get(ASTCopier{}(selectedObject->code()->root()))); + auto astCopy = std::make_unique(_dialect, std::get(ASTCopier{}(selectedObject->code()->root()))); return std::variant, ErrorList>(std::move(astCopy)); } @@ -179,7 +179,7 @@ std::unique_ptr Program::disambiguateAST( std::set const externallyUsedIdentifiers = {}; Disambiguator disambiguator(_dialect, _analysisInfo, externallyUsedIdentifiers); - return std::make_unique(std::get(disambiguator(_ast.root()))); + return std::make_unique(_dialect, std::get(disambiguator(_ast.root()))); } std::unique_ptr Program::applyOptimisationSteps( @@ -203,7 +203,7 @@ std::unique_ptr Program::applyOptimisationSteps( for (std::string const& step: _optimisationSteps) OptimiserSuite::allSteps().at(step)->run(context, astRoot); - return std::make_unique(std::move(astRoot)); + return std::make_unique(_dialect, std::move(astRoot)); } size_t Program::computeCodeSize(Block const& _ast, CodeWeights const& _weights) From aee13b208afcd18cf39eb09bb6b5bd63fc956747 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 31 Oct 2024 16:26:13 +0100 Subject: [PATCH 0503/1340] Yul: add static format method to AsmPrinter --- libsolidity/codegen/CompilerContext.cpp | 16 +++++++--------- libyul/AsmPrinter.cpp | 10 ++++++++++ libyul/AsmPrinter.h | 9 ++++++++- libyul/Object.cpp | 6 +++--- test/libyul/Common.cpp | 7 +------ test/libyul/YulOptimizerTest.cpp | 2 +- tools/yulPhaser/Program.cpp | 2 +- 7 files changed, 31 insertions(+), 21 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index c09b33a00..5c859f54f 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -444,7 +444,7 @@ void CompilerContext::appendInlineAssembly( yul::Parser(errorReporter, dialect, std::move(locationOverride)) .parse(charStream); #ifdef SOL_OUTPUT_ASM - cout << yul::AsmPrinter(&dialect)(*parserResult) << endl; + std::cout << yul::AsmPrinter::format(*parserResult) << std::endl; #endif auto reportError = [&](std::string const& _context) @@ -491,9 +491,7 @@ void CompilerContext::appendInlineAssembly( { // Store as generated sources, but first re-parse to update the source references. solAssert(m_generatedYulUtilityCode.empty(), ""); - solAssert(obj.dialect()); - m_generatedYulUtilityCode = yul::AsmPrinter(*obj.dialect())(obj.code()->root()); - std::string code = yul::AsmPrinter{*obj.dialect()}(obj.code()->root()); + m_generatedYulUtilityCode = yul::AsmPrinter::format(*obj.code()); langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); obj.setCode(yul::Parser(errorReporter, dialect).parse(charStream)); obj.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj)); @@ -503,8 +501,8 @@ void CompilerContext::appendInlineAssembly( toBeAssembledAST = obj.code(); #ifdef SOL_OUTPUT_ASM - cout << "After optimizer:" << endl; - cout << yul::AsmPrinter(&dialect)(*parserResult) << endl; + std::cout << "After optimizer:" << std::endl; + std::cout << yul::AsmPrinter::format(*parserResult) << std::endl; #endif } else if (_system) @@ -537,7 +535,7 @@ void CompilerContext::appendInlineAssembly( void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSettings, std::set const& _externalIdentifiers) { #ifdef SOL_OUTPUT_ASM - cout << yul::AsmPrinter(*dialect)(*_object.code) << endl; + std::cout << yul::AsmPrinter::format(*_object.code()) << std::endl; #endif bool const isCreation = runtimeContext() != nullptr; @@ -554,8 +552,8 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _ ); #ifdef SOL_OUTPUT_ASM - cout << "After optimizer:" << endl; - cout << yul::AsmPrinter(*dialect)(*object.code) << endl; + std::cout << "After optimizer:" << std::endl; + std::cout << yul::AsmPrinter::format(*_object.code()) << std::endl; #endif } diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 5841fdfd3..5ba190149 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -42,6 +42,16 @@ using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; +std::string AsmPrinter::format( + AST const& _ast, + std::optional>> const& _sourceIndexToName, + DebugInfoSelection const& _debugInfoSelection, + CharStreamProvider const* _soliditySourceProvider) +{ + return AsmPrinter{_ast.dialect(), _sourceIndexToName, _debugInfoSelection, _soliditySourceProvider}(_ast.root()); +} + + std::string AsmPrinter::operator()(Literal const& _literal) { yulAssert(validLiteral(_literal)); diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 6eda13fcd..6b63c8638 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -46,9 +46,16 @@ struct Dialect; class AsmPrinter { public: + static std::string format( + AST const& _ast, + std::optional>> const& _sourceIndexToName = {}, + langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), + langutil::CharStreamProvider const* _soliditySourceProvider = nullptr + ); + explicit AsmPrinter( Dialect const&, - std::optional>> _sourceIndexToName = {}, + std::optional>> const& _sourceIndexToName = {}, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ): diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 0dfa610d0..54ec6a3cf 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -52,12 +52,12 @@ std::string Object::toString( yulAssert(dialect(), "No dialect"); yulAssert(debugData, "No debug data"); - std::string inner = "code " + AsmPrinter( - *dialect(), + std::string inner = "code " + AsmPrinter::format( + *code(), debugData->sourceNames, _debugInfoSelection, _soliditySourceProvider - )(code()->root()); + ); for (auto const& obj: subObjects) inner += "\n" + obj->toString(_debugInfoSelection, _soliditySourceProvider); diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 10a55217c..32f60c8eb 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -99,12 +99,7 @@ yul::Block yul::test::disambiguate(std::string const& _source) std::string yul::test::format(std::string const& _source) { - Dialect const& dialect = languageToDialect( - YulStack::Language::StrictAssembly, - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); - return AsmPrinter(dialect)(parse(_source).first->root()); + return AsmPrinter::format(*parse(_source).first); } namespace diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index ad7485aea..dc05810bc 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -86,7 +86,7 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co std::string printedOptimizedObject; soltestAssert(optimizedObject->dialect()); if (optimizedObject->subObjects.empty()) - printedOptimizedObject = AsmPrinter{*optimizedObject->dialect()}(optimizedObject->code()->root()); + printedOptimizedObject = AsmPrinter::format(*optimizedObject->code()); else printedOptimizedObject = optimizedObject->toString(); diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 9e16826d9..6d1827827 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -106,7 +106,7 @@ void Program::optimise(std::vector const& _optimisationSteps) std::ostream& phaser::operator<<(std::ostream& _stream, Program const& _program) { - return _stream << AsmPrinter(_program.m_dialect)(_program.m_ast->root()); + return _stream << AsmPrinter::format(*_program.m_ast); } std::string Program::toJson() const From b7f676a98b1db778aacf1599f5571819bf523bbf Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:01:33 +0100 Subject: [PATCH 0504/1340] Yul compiler context runs optimizeYul on dialect contained in object --- libsolidity/codegen/CompilerContext.cpp | 11 +++++++---- libsolidity/codegen/CompilerContext.h | 2 +- libsolidity/codegen/ContractCompiler.cpp | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 5c859f54f..25829d96a 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -485,7 +485,7 @@ void CompilerContext::appendInlineAssembly( obj.setCode(parserResult, std::make_shared(analysisInfo)); solAssert(!dialect.providesObjectAccess()); - optimizeYul(obj, dialect, _optimiserSettings, externallyUsedIdentifiers); + optimizeYul(obj, _optimiserSettings, externallyUsedIdentifiers); if (_system) { @@ -532,16 +532,19 @@ void CompilerContext::appendInlineAssembly( } -void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSettings, std::set const& _externalIdentifiers) +void CompilerContext::optimizeYul(yul::Object& _object, OptimiserSettings const& _optimiserSettings, std::set const& _externalIdentifiers) { + yulAssert(_object.dialect()); + auto const* evmDialect = dynamic_cast(_object.dialect()); + yulAssert(evmDialect); #ifdef SOL_OUTPUT_ASM std::cout << yul::AsmPrinter::format(*_object.code()) << std::endl; #endif bool const isCreation = runtimeContext() != nullptr; - yul::GasMeter meter(_dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment); + yul::GasMeter meter(*evmDialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment); yul::OptimiserSuite::run( - _dialect, + *evmDialect, &meter, _object, _optimiserSettings.optimizeStackAllocation, diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 3469ee7d2..2805b8daf 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -277,7 +277,7 @@ class CompilerContext /// Otherwise returns "revert(0, 0)". std::string revertReasonIfDebug(std::string const& _message = ""); - void optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSetting, std::set const& _externalIdentifiers = {}); + void optimizeYul(yul::Object& _object, OptimiserSettings const& _optimiserSetting, std::set const& _externalIdentifiers = {}); /// Appends arbitrary data to the end of the bytecode. void appendToAuxiliaryData(bytes const& _data) { m_asm->appendToAuxiliaryData(_data); } diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 3548d0ae7..d7db52e76 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -947,7 +947,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) object.setCode(std::make_shared(_inlineAssembly.dialect(), yul::ASTCopier().translate(code->root()))); object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object)); - m_context.optimizeYul(object, *dialect, m_optimiserSettings); + m_context.optimizeYul(object, m_optimiserSettings); code = object.code().get(); analysisInfo = object.analysisInfo.get(); From 34919223e25d51a4b4639d566e9b68276b7551e9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:09:30 +0100 Subject: [PATCH 0505/1340] AsmAnalysis: analyzeStrictAssertCorrect only on object --- libsolidity/codegen/CompilerContext.cpp | 2 +- libsolidity/codegen/ContractCompiler.cpp | 2 +- libyul/AsmAnalysis.cpp | 5 +++-- libyul/AsmAnalysis.h | 2 +- libyul/ObjectOptimizer.cpp | 2 +- libyul/optimiser/Suite.cpp | 2 +- test/libyul/SSAControlFlowGraphTest.cpp | 2 +- 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 25829d96a..3cf713a94 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -494,7 +494,7 @@ void CompilerContext::appendInlineAssembly( m_generatedYulUtilityCode = yul::AsmPrinter::format(*obj.code()); langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); obj.setCode(yul::Parser(errorReporter, dialect).parse(charStream)); - obj.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj)); + obj.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(obj)); } analysisInfo = std::move(*obj.analysisInfo); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index d7db52e76..57a23fb80 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -945,7 +945,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) // Create a modifiable copy of the code and analysis object.setCode(std::make_shared(_inlineAssembly.dialect(), yul::ASTCopier().translate(code->root()))); - object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object)); + object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(object)); m_context.optimizeYul(object, m_optimiserSettings); diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 491effe8e..b00982faf 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -86,9 +86,10 @@ bool AsmAnalyzer::analyze(Block const& _block) return watcher.ok(); } -AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object) +AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Object const& _object) { - return analyzeStrictAssertCorrect(_dialect, _object.code()->root(), _object.summarizeStructure()); + yulAssert(_object.dialect()); + return analyzeStrictAssertCorrect(*_object.dialect(), _object.code()->root(), _object.summarizeStructure()); } AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 7673e375a..6235b530d 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -81,7 +81,7 @@ class AsmAnalyzer /// Performs analysis on the outermost code of the given object and returns the analysis info. /// Asserts on failure. - static AsmAnalysisInfo analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object); + static AsmAnalysisInfo analyzeStrictAssertCorrect(Object const& _object); static AsmAnalysisInfo analyzeStrictAssertCorrect( Dialect const& _dialect, Block const& _astRoot, diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index d7c1526cb..992c41b4d 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -121,12 +121,12 @@ void ObjectOptimizer::overwriteWithOptimizedObject(util::h256 _cacheKey, Object& yulAssert(cachedObject.dialect); _object.setCode(std::make_shared(*cachedObject.dialect, ASTCopier{}.translate(*cachedObject.optimizedAST))); yulAssert(_object.code()); + yulAssert(_object.dialect()); // There's no point in caching AnalysisInfo because it references AST nodes. It can't be shared // by multiple ASTs and it's easier to recalculate it than properly clone it. _object.analysisInfo = std::make_shared( AsmAnalyzer::analyzeStrictAssertCorrect( - *cachedObject.dialect, _object ) ); diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 0bef31472..a9c5b0f2a 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -199,7 +199,7 @@ void OptimiserSuite::run( } _object.setCode(std::make_shared(_dialect, std::move(astRoot))); - _object.analysisInfo = std::make_shared(AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object)); + _object.analysisInfo = std::make_shared(AsmAnalyzer::analyzeStrictAssertCorrect(_object)); } namespace diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/SSAControlFlowGraphTest.cpp index 5f0c79da5..ad825cdf5 100644 --- a/test/libyul/SSAControlFlowGraphTest.cpp +++ b/test/libyul/SSAControlFlowGraphTest.cpp @@ -66,7 +66,7 @@ TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::st return TestResult::FatalError; } - auto info = AsmAnalyzer::analyzeStrictAssertCorrect(*m_dialect, *object); + auto info = AsmAnalyzer::analyzeStrictAssertCorrect(*object); std::unique_ptr controlFlow = SSAControlFlowGraphBuilder::build( info, *m_dialect, From c8fa1cd8a2ff1d01b8f9121571f87a722df953bd Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:18:29 +0100 Subject: [PATCH 0506/1340] Yul Semantics: containsMSize only on object --- libyul/YulStack.cpp | 4 ++-- libyul/optimiser/Semantics.cpp | 7 ++++--- libyul/optimiser/Semantics.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 877e447c7..a7bf415a5 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -94,7 +94,7 @@ void YulStack::optimize() { if ( !m_optimiserSettings.runYulOptimiser && - yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion, m_eofVersion), *m_parserResult) + yul::MSizeFinder::containsMSize(*m_parserResult) ) return; @@ -317,7 +317,7 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) // it with the minimal steps required to avoid "stack too deep". bool optimize = m_optimiserSettings.optimizeStackAllocation || ( !m_optimiserSettings.runYulOptimiser && - !yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion, m_eofVersion), *m_parserResult) + !yul::MSizeFinder::containsMSize(*m_parserResult) ); try { diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index 5b5ad0eee..1698ac5ee 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -93,14 +93,15 @@ bool MSizeFinder::containsMSize(Dialect const& _dialect, Block const& _ast) return finder.m_msizeFound; } -bool MSizeFinder::containsMSize(Dialect const& _dialect, Object const& _object) +bool MSizeFinder::containsMSize(Object const& _object) { - if (containsMSize(_dialect, _object.code()->root())) + yulAssert(_object.dialect()); + if (containsMSize(*_object.dialect(), _object.code()->root())) return true; for (std::shared_ptr const& node: _object.subObjects) if (auto const* object = dynamic_cast(node.get())) - if (containsMSize(_dialect, *object)) + if (containsMSize(*object)) return true; return false; diff --git a/libyul/optimiser/Semantics.h b/libyul/optimiser/Semantics.h index 1d0018897..e97fbd0c3 100644 --- a/libyul/optimiser/Semantics.h +++ b/libyul/optimiser/Semantics.h @@ -149,7 +149,7 @@ class MSizeFinder: public ASTWalker { public: static bool containsMSize(Dialect const& _dialect, Block const& _ast); - static bool containsMSize(Dialect const& _dialect, Object const& _object); + static bool containsMSize(Object const& _object); using ASTWalker::operator(); void operator()(FunctionCall const& _funCall) override; From 5168861695fab4986f9a1450e61c50897e6baf0f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:25:55 +0100 Subject: [PATCH 0507/1340] Run Yul stack compressor only on object --- libyul/optimiser/StackCompressor.cpp | 15 +++++++-------- libyul/optimiser/StackCompressor.h | 1 - libyul/optimiser/Suite.cpp | 2 -- test/libyul/YulOptimizerTestCommon.cpp | 2 +- test/tools/yulopti.cpp | 2 +- 5 files changed, 9 insertions(+), 13 deletions(-) diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 686fb6695..a421a2d02 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -237,7 +237,6 @@ void eliminateVariablesOptimizedCodegen( } std::tuple StackCompressor::run( - Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation, size_t _maxIterations) @@ -250,7 +249,7 @@ std::tuple StackCompressor::run( ); bool usesOptimizedCodeGenerator = false; bool simulateFunctionsWithJumps = true; - if (auto evmDialect = dynamic_cast(&_dialect)) + if (auto evmDialect = dynamic_cast(_object.dialect())) { usesOptimizedCodeGenerator = _optimizeStackAllocation && @@ -258,18 +257,18 @@ std::tuple StackCompressor::run( evmDialect->providesObjectAccess(); simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); } - bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _object.code()->root()); + bool allowMSizeOptimization = !MSizeFinder::containsMSize(*_object.dialect(), _object.code()->root()); Block astRoot = std::get(ASTCopier{}(_object.code()->root())); if (usesOptimizedCodeGenerator) { yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( - _dialect, + *_object.dialect(), astRoot, _object.summarizeStructure() ); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, astRoot); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *_object.dialect(), astRoot); eliminateVariablesOptimizedCodegen( - _dialect, + *_object.dialect(), astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg, simulateFunctionsWithJumps), allowMSizeOptimization @@ -281,11 +280,11 @@ std::tuple StackCompressor::run( { Object object(_object); object.setCode(std::make_shared(*_object.dialect(), std::get(ASTCopier{}(astRoot)))); - std::map stackSurplus = CompilabilityChecker(_dialect, object, _optimizeStackAllocation).stackDeficit; + std::map stackSurplus = CompilabilityChecker(*object.dialect(), object, _optimizeStackAllocation).stackDeficit; if (stackSurplus.empty()) return std::make_tuple(true, std::move(astRoot)); eliminateVariables( - _dialect, + *object.dialect(), astRoot, stackSurplus, allowMSizeOptimization diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index 70c020b9c..b0b086a7e 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -47,7 +47,6 @@ class StackCompressor /// Try to remove local variables until the AST is compilable. /// @returns tuple with true if it was successful as first element, second element is the modified AST. static std::tuple run( - Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation, size_t _maxIterations diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index a9c5b0f2a..805dd9291 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -140,7 +140,6 @@ void OptimiserSuite::run( PROFILER_PROBE("StackCompressor", probe); _object.setCode(std::make_shared(_dialect, std::move(astRoot))); astRoot = std::get<1>(StackCompressor::run( - _dialect, _object, _optimizeStackAllocation, stackCompressorMaxIterations @@ -167,7 +166,6 @@ void OptimiserSuite::run( PROFILER_PROBE("StackCompressor", probe); _object.setCode(std::make_shared(_dialect, std::move(astRoot))); astRoot = std::get<1>(StackCompressor::run( - _dialect, _object, _optimizeStackAllocation, stackCompressorMaxIterations diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 9b8d2073c..d75fbbe15 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -411,7 +411,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( { Object object(*m_optimizedObject); object.setCode(std::make_shared(*m_dialect, std::get(ASTCopier{}(block)))); - block = std::get<1>(StackCompressor::run(*m_dialect, object, true, maxIterations)); + block = std::get<1>(StackCompressor::run(object, true, maxIterations)); } BlockFlattener::run(*m_context, block); return block; diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 5b634de36..b164bfb4f 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -219,7 +219,7 @@ class YulOpti { Object obj; obj.setCode(std::make_shared(m_dialect, std::get(ASTCopier{}(*m_astRoot)))); - *m_astRoot = std::get<1>(StackCompressor::run(m_dialect, obj, true, 16)); + *m_astRoot = std::get<1>(StackCompressor::run(obj, true, 16)); break; } default: From a16833718d920354985ba621d1e95470071acccc Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:29:16 +0100 Subject: [PATCH 0508/1340] Remove dialect from yul optimization suite run arguments --- libsolidity/codegen/CompilerContext.cpp | 1 - libyul/ObjectOptimizer.cpp | 1 - libyul/optimiser/Suite.cpp | 21 +++++++++++---------- libyul/optimiser/Suite.h | 1 - test/libyul/YulOptimizerTestCommon.cpp | 1 - 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 3cf713a94..4d53b9c23 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -544,7 +544,6 @@ void CompilerContext::optimizeYul(yul::Object& _object, OptimiserSettings const& bool const isCreation = runtimeContext() != nullptr; yul::GasMeter meter(*evmDialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment); yul::OptimiserSuite::run( - *evmDialect, &meter, _object, _optimiserSettings.optimizeStackAllocation, diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index 992c41b4d..181cbaa8f 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -90,7 +90,6 @@ void ObjectOptimizer::optimize(Object& _object, Settings const& _settings, bool } OptimiserSuite::run( - dialect, meter.get(), _object, _settings.optimizeStackAllocation, diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 805dd9291..766f96821 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -89,7 +89,6 @@ using namespace solidity::yul; using namespace std::string_literals; void OptimiserSuite::run( - Dialect const& _dialect, GasMeter const* _meter, Object& _object, bool _optimizeStackAllocation, @@ -99,7 +98,9 @@ void OptimiserSuite::run( std::set const& _externallyUsedIdentifiers ) { - EVMDialect const* evmDialect = dynamic_cast(&_dialect); + yulAssert(_object.dialect()); + auto const& dialect = *_object.dialect(); + EVMDialect const* evmDialect = dynamic_cast(_object.dialect()); bool usesOptimizedCodeGenerator = _optimizeStackAllocation && evmDialect && @@ -111,14 +112,14 @@ void OptimiserSuite::run( { PROFILER_PROBE("Disambiguator", probe); astRoot = std::get(Disambiguator( - _dialect, + dialect, *_object.analysisInfo, reservedIdentifiers )(_object.code()->root())); } - NameDispenser dispenser{_dialect, astRoot, reservedIdentifiers}; - OptimiserStepContext context{_dialect, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment}; + NameDispenser dispenser{dialect, astRoot, reservedIdentifiers}; + OptimiserStepContext context{dialect, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment}; OptimiserSuite suite(context, Debug::None); @@ -138,7 +139,7 @@ void OptimiserSuite::run( if (!usesOptimizedCodeGenerator) { PROFILER_PROBE("StackCompressor", probe); - _object.setCode(std::make_shared(_dialect, std::move(astRoot))); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); astRoot = std::get<1>(StackCompressor::run( _object, _optimizeStackAllocation, @@ -164,7 +165,7 @@ void OptimiserSuite::run( { { PROFILER_PROBE("StackCompressor", probe); - _object.setCode(std::make_shared(_dialect, std::move(astRoot))); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); astRoot = std::get<1>(StackCompressor::run( _object, _optimizeStackAllocation, @@ -174,14 +175,14 @@ void OptimiserSuite::run( if (evmDialect->providesObjectAccess()) { PROFILER_PROBE("StackLimitEvader", probe); - _object.setCode(std::make_shared(_dialect, std::move(astRoot))); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); astRoot = StackLimitEvader::run(suite.m_context, _object); } } else if (evmDialect->providesObjectAccess() && _optimizeStackAllocation) { PROFILER_PROBE("StackLimitEvader", probe); - _object.setCode(std::make_shared(_dialect, std::move(astRoot))); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); astRoot = StackLimitEvader::run(suite.m_context, _object); } } @@ -196,7 +197,7 @@ void OptimiserSuite::run( VarNameCleaner::run(suite.m_context, astRoot); } - _object.setCode(std::make_shared(_dialect, std::move(astRoot))); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); _object.analysisInfo = std::make_shared(AsmAnalyzer::analyzeStrictAssertCorrect(_object)); } diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index e4eac31df..bd3e1aa05 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -63,7 +63,6 @@ class OptimiserSuite /// The value nullopt for `_expectedExecutionsPerDeployment` represents creation code. static void run( - Dialect const& _dialect, GasMeter const* _meter, Object& _object, bool _optimizeStackAllocation, diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index d75fbbe15..a7452d053 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -419,7 +419,6 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( {"fullSuite", [&]() { GasMeter meter(dynamic_cast(*m_dialect), false, 200); OptimiserSuite::run( - *m_dialect, &meter, *m_optimizedObject, true, From 96e63ab08f6744aba273d590a5245d8e6979827a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:32:12 +0100 Subject: [PATCH 0509/1340] Remove dialect from yul compilability checker run arguments --- libyul/CompilabilityChecker.cpp | 3 +-- libyul/CompilabilityChecker.h | 1 - libyul/optimiser/StackCompressor.cpp | 2 +- libyul/optimiser/StackLimitEvader.cpp | 1 - test/libyul/CompilabilityChecker.cpp | 6 +----- test/libyul/YulOptimizerTestCommon.cpp | 1 - test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp | 1 - 7 files changed, 3 insertions(+), 12 deletions(-) diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index 9cc6bd864..cc46ecb77 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -31,13 +31,12 @@ using namespace solidity::yul; using namespace solidity::util; CompilabilityChecker::CompilabilityChecker( - Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation ) { yulAssert(_object.hasCode()); - if (auto const* evmDialect = dynamic_cast(&_dialect)) + if (auto const* evmDialect = dynamic_cast(_object.dialect())) { NoOutputEVMDialect noOutputDialect(*evmDialect); diff --git a/libyul/CompilabilityChecker.h b/libyul/CompilabilityChecker.h index 160aeca8c..1b7bf65a5 100644 --- a/libyul/CompilabilityChecker.h +++ b/libyul/CompilabilityChecker.h @@ -45,7 +45,6 @@ namespace solidity::yul struct CompilabilityChecker { CompilabilityChecker( - Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation ); diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index a421a2d02..04b931a24 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -280,7 +280,7 @@ std::tuple StackCompressor::run( { Object object(_object); object.setCode(std::make_shared(*_object.dialect(), std::get(ASTCopier{}(astRoot)))); - std::map stackSurplus = CompilabilityChecker(*object.dialect(), object, _optimizeStackAllocation).stackDeficit; + std::map stackSurplus = CompilabilityChecker(object, _optimizeStackAllocation).stackDeficit; if (stackSurplus.empty()) return std::make_tuple(true, std::move(astRoot)); eliminateVariables( diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 02c6de159..2dc32d787 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -143,7 +143,6 @@ Block StackLimitEvader::run( else { run(_context, astRoot, CompilabilityChecker{ - _context.dialect, _object, true, }.unreachableVariables); diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index daa8f61aa..1956db84c 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -34,16 +34,12 @@ namespace { std::string check(std::string const& _input) { - auto const& dialect = EVMDialect::strictAssemblyForEVM( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); Object obj; auto parsingResult = yul::test::parse(_input); obj.setCode(parsingResult.first, parsingResult.second); BOOST_REQUIRE(obj.hasCode()); BOOST_REQUIRE(obj.dialect()); - auto functions = CompilabilityChecker(dialect, obj, true).stackDeficit; + auto functions = CompilabilityChecker(obj, true).stackDeficit; std::string out; for (auto const& function: functions) out += function.first.str() + ": " + std::to_string(function.second) + " "; diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index a7452d053..351d705cc 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -434,7 +434,6 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( Object object(*m_optimizedObject); object.setCode(std::make_shared(*m_dialect, std::get(ASTCopier{}(block)))); auto const unreachables = CompilabilityChecker{ - *m_dialect, object, true }.unreachableVariables; diff --git a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp index 6f603e335..de2fdd286 100644 --- a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp +++ b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp @@ -56,7 +56,6 @@ bool recursiveFunctionExists(Dialect const& _dialect, yul::Object& _object) { auto recursiveFunctions = CallGraphGenerator::callGraph(_object.code()->root()).recursiveFunctions(); for(auto&& [function, variables]: CompilabilityChecker{ - _dialect, _object, true }.unreachableVariables From 6cec259deea1686e704a707386911e6920685d36 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 30 Oct 2024 17:41:36 +0100 Subject: [PATCH 0510/1340] Run docker container as current user, not as root --- scripts/ci/build_emscripten.sh | 3 ++- scripts/ci/build_ossfuzz.sh | 2 +- scripts/ci/docker_upgrade.sh | 11 +++-------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/scripts/ci/build_emscripten.sh b/scripts/ci/build_emscripten.sh index 04e16293f..e4d25f195 100755 --- a/scripts/ci/build_emscripten.sh +++ b/scripts/ci/build_emscripten.sh @@ -37,12 +37,13 @@ set -ev SCRIPT_DIR="$(realpath "$(dirname "$0")/..")" # shellcheck source=scripts/common.sh source "${SCRIPT_DIR}/common.sh" +ROOT_DIR="${SCRIPT_DIR}/.." function build() { local build_dir="$1" local prerelease_source="${2:-ci}" - cd /root/project + cd "${ROOT_DIR}" # shellcheck disable=SC2166 if [[ "$CIRCLE_BRANCH" = release || -n "$CIRCLE_TAG" || -n "$FORCE_RELEASE" || "$(git tag --points-at HEAD 2>/dev/null)" == v* ]] diff --git a/scripts/ci/build_ossfuzz.sh b/scripts/ci/build_ossfuzz.sh index 1240b6877..c44f9baba 100755 --- a/scripts/ci/build_ossfuzz.sh +++ b/scripts/ci/build_ossfuzz.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -ex -ROOTDIR="/root/project" +ROOTDIR="$(realpath "$(dirname "$0")/../..")" BUILDDIR="${ROOTDIR}/build" mkdir -p "${BUILDDIR}" && mkdir -p "$BUILDDIR/deps" diff --git a/scripts/ci/docker_upgrade.sh b/scripts/ci/docker_upgrade.sh index a6b59e157..c2077239a 100755 --- a/scripts/ci/docker_upgrade.sh +++ b/scripts/ci/docker_upgrade.sh @@ -51,17 +51,12 @@ docker build "scripts/docker/${IMAGE_NAME}" --file "scripts/docker/${IMAGE_NAME} echo "-- test_docker @ '${PWD}'" -# NOTE: Since /root/project/ is a dir from outside the container and the owner of the files is different, -# git show in the script refuses to work. It must be marked as safe to use first. -# See https://github.blog/2022-04-12-git-security-vulnerability-announced/ docker run \ --rm \ - --volume "${PWD}:/root/project" \ + --volume "${PWD}:/project" \ + -u "$(id -u "${USER}"):$(id -g "${USER}")" \ "${IMAGE_NAME}" \ - bash -c " - git config --global --add safe.directory /root/project && - /root/project/scripts/ci/${IMAGE_NAME}_test_${IMAGE_VARIANT}.sh - " + bash -c "/project/scripts/ci/${IMAGE_NAME}_test_${IMAGE_VARIANT}.sh" echo "-- push_docker" From 75ad2ea34db5582263ad0453dc233db21c462a9f Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 24 Oct 2024 15:03:03 +0200 Subject: [PATCH 0511/1340] Docker: Update Z3 and cvc5 versions --- .../buildpack-deps/Dockerfile.emscripten | 18 +++++------- .../buildpack-deps/Dockerfile.ubuntu2004 | 29 +++++++++++-------- .../buildpack-deps/Dockerfile.ubuntu2404 | 27 ++++++++++------- .../Dockerfile.ubuntu2404.clang | 29 +++++++++++-------- 4 files changed, 58 insertions(+), 45 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten index 478d8d947..8bfb9c51a 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -33,7 +33,7 @@ # Using $(em-config CACHE)/sysroot/usr seems to work, though, and still has cmake find the # dependencies automatically. FROM emscripten/emsdk:3.1.19 AS base -LABEL version="18" +LABEL version="19" ADD emscripten.jam /usr/src RUN set -ex && \ @@ -49,7 +49,7 @@ RUN set -ex && \ # Install Z3 RUN set -ex && \ cd /usr/src && \ - git clone https://github.com/Z3Prover/z3.git -b z3-4.12.1 --depth 1 && \ + git clone https://github.com/Z3Prover/z3.git -b z3-4.13.3 --depth 1 && \ cd z3 && \ mkdir build && \ cd build && \ @@ -86,11 +86,9 @@ RUN set -ex && \ # CVC5 RUN set -ex; \ - cvc5_version="1.1.2"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ - unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ - mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ - mv /opt/cvc5-Linux-static/include/* /usr/include; \ - mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ - rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + cvc5_version="1.2.0"; \ + cvc5_archive_name="cvc5-Linux-x86_64-static"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ + rm -f /opt/cvc5.zip; diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index 723192e2d..7592f55ec 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:focal AS base -LABEL version="25" +LABEL version="26" ARG DEBIAN_FRONTEND=noninteractive @@ -39,15 +39,13 @@ RUN set -ex; \ libboost-program-options-dev \ libboost-system-dev \ libboost-test-dev \ - libz3-static-dev \ lsof \ ninja-build \ python3-pip \ python3-sphinx \ software-properties-common \ sudo \ - unzip \ - z3-static; \ + unzip; \ pip3 install \ codecov \ colorama \ @@ -76,14 +74,21 @@ RUN set -ex; \ # CVC5 RUN set -ex; \ - cvc5_version="1.1.2"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ - unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ - mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ - mv /opt/cvc5-Linux-static/include/* /usr/include; \ - mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ - rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + cvc5_version="1.2.0"; \ + cvc5_archive_name="cvc5-Linux-x86_64-static"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ + rm -f /opt/cvc5.zip; + +# Z3 +RUN set -ex; \ + z3_version="4.13.3"; \ + z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ + wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ + test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ + unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ + rm -f /opt/z3.zip; FROM base AS libraries diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 index c7ad4594a..eb5439f59 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="1" +LABEL version="2" ARG DEBIAN_FRONTEND=noninteractive @@ -44,7 +44,6 @@ RUN set -ex; \ libboost-system-dev \ libboost-test-dev \ libcln-dev \ - libz3-static-dev \ locales-all \ lsof \ ninja-build \ @@ -53,7 +52,6 @@ RUN set -ex; \ software-properties-common \ sudo \ unzip \ - z3-static \ zip; \ pip3 install \ codecov \ @@ -79,14 +77,21 @@ RUN set -ex; \ # CVC5 RUN set -ex; \ - cvc5_version="1.1.2"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ - unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ - mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ - mv /opt/cvc5-Linux-static/include/* /usr/include; \ - mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ - rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + cvc5_version="1.2.0"; \ + cvc5_archive_name="cvc5-Linux-x86_64-static"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ + rm -f /opt/cvc5.zip; + +# Z3 +RUN set -ex; \ + z3_version="4.13.3"; \ + z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ + wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ + test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ + unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ + rm -f /opt/z3.zip; FROM base AS libraries diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang index 21092e312..3b1e3e614 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="2" +LABEL version="3" ARG DEBIAN_FRONTEND=noninteractive @@ -46,13 +46,11 @@ RUN set -ex; \ libboost-test-dev \ libclang-rt-dev \ libcln-dev \ - libz3-static-dev \ lsof \ ninja-build \ python3-pip \ software-properties-common \ - sudo \ - z3-static; \ + sudo; \ pip3 install \ codecov \ colorama \ @@ -78,14 +76,21 @@ RUN set -ex; \ # CVC5 RUN set -ex; \ - cvc5_version="1.1.2"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ - unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ - mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ - mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ - mv /opt/cvc5-Linux-static/include/* /usr/include; \ - rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + cvc5_version="1.2.0"; \ + cvc5_archive_name="cvc5-Linux-x86_64-static"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ + rm -f /opt/cvc5.zip; + +# Z3 +RUN set -ex; \ + z3_version="4.13.3"; \ + z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ + wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ + test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ + unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ + rm -f /opt/z3.zip; FROM base AS libraries From 966fba572d57107d9a4eda263eeecad81168699a Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 3 Dec 2024 14:35:41 +0700 Subject: [PATCH 0512/1340] Yul SSACFG JSON export fix: Export Yul SSA CFG of optimized IR --- libsolidity/interface/CompilerStack.cpp | 6 +- .../standard_yul_cfg_json_export/output.json | 4146 +++++------------ test/cmdlineTests/yul_cfg_json_export/output | 4146 +++++------------ 3 files changed, 2083 insertions(+), 6215 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index f24fae3cd..b90a30242 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -999,10 +999,10 @@ std::optional CompilerStack::yulCFGJson(std::string const& _contractName) // keep it around when compiling a large project containing many contracts. Contract const& currentContract = contract(_contractName); yulAssert(currentContract.contract); - yulAssert(currentContract.yulIR.has_value() == currentContract.contract->canBeDeployed()); - if (!currentContract.yulIR) + yulAssert(currentContract.yulIROptimized.has_value() == currentContract.contract->canBeDeployed()); + if (!currentContract.yulIROptimized) return std::nullopt; - return loadGeneratedIR(*currentContract.yulIR).cfgJson(); + return loadGeneratedIR(*currentContract.yulIROptimized).cfgJson(); } std::optional const& CompilerStack::yulIROptimized(std::string const& _contractName) const diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index 8d3fc5b7e..c224164c5 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -18,7 +18,7 @@ "instructions": [ { "builtinArgs": [ - "128" + "0x80" ], "in": [], "op": "memoryguard", @@ -50,18 +50,6 @@ }, "id": "Block2", "instructions": [ - { - "in": [], - "op": "constructor_C_19", - "out": [] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v3" - ] - }, { "builtinArgs": [ "C_19_deployed" @@ -86,25 +74,15 @@ "in": [ "v4", "v5", - "v3" + "v0" ], "op": "codecopy", "out": [] }, - { - "builtinArgs": [ - "C_19_deployed" - ], - "in": [], - "op": "datasize", - "out": [ - "v6" - ] - }, { "in": [ - "v6", - "v3" + "v4", + "v0" ], "op": "return", "out": [] @@ -119,109 +97,18 @@ "id": "Block1", "instructions": [ { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "in": [ + "0x00", + "0x00" + ], + "op": "revert", "out": [] } ], - "type": "FunctionCall" + "type": "BuiltinCall" } ], - "functions": { - "allocate_unbounded": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "constructor_C_19": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "constructor_I_7", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "constructor_I_7": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - } - } + "functions": {} }, "subObjects": { "C_19_deployed": { @@ -239,7 +126,7 @@ "instructions": [ { "builtinArgs": [ - "128" + "0x80" ], "in": [], "op": "memoryguard", @@ -291,19 +178,22 @@ "id": "Block2", "instructions": [ { - "in": [], - "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", + "in": [ + "0x00", + "0x00" + ], + "op": "revert", "out": [] } ], - "type": "FunctionCall" + "type": "BuiltinCall" }, { "exit": { - "cond": "v9", + "cond": "v11", "targets": [ - "Block5", - "Block4" + "Block4", + "Block3" ], "type": "ConditionalJump" }, @@ -320,21 +210,22 @@ }, { "in": [ - "v7" + "v7", + "0xe0" ], - "op": "shift_right_224_unsigned", + "op": "shr", "out": [ - "v8" + "v9" ] }, { "in": [ - "0x26121ff0", - "v8" + "v9", + "0x26121ff0" ], "op": "eq", "out": [ - "v9" + "v11" ] } ], @@ -343,604 +234,145 @@ { "exit": { "targets": [ - "Block3" + "Block2" ], "type": "Jump" }, - "id": "Block5", + "id": "Block4", "instructions": [] }, { "exit": { - "type": "Terminated" + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" }, - "id": "Block4", + "id": "Block3", "instructions": [ { "in": [], - "op": "external_fun_f_18", - "out": [] + "op": "callvalue", + "out": [ + "v12" + ] } ], - "type": "FunctionCall" + "type": "BuiltinCall" }, { "exit": { + "cond": "v17", "targets": [ - "Block2" + "Block9", + "Block8" ], - "type": "Jump" + "type": "ConditionalJump" }, - "id": "Block3", - "instructions": [] - } - ], - "functions": { - "abi_decode_tuple_": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + "id": "Block6", + "instructions": [ { - "exit": { - "cond": "v4", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "v1" - ], - "op": "sub", - "out": [ - "v3" - ] - }, - { - "in": [ - "0x00", - "v3" - ], - "op": "slt", - "out": [ - "v4" - ] - } + "in": [ + "0x03" ], - "type": "BuiltinCall" + "op": "not", + "out": [ + "v14" + ] }, { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [] + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", - "out": [] - } + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" ], - "type": "FunctionCall" + "op": "slt", + "out": [ + "v17" + ] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "abi_encode_t_uint256_to_t_uint256_fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_uint256", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2", - "v1" - ], - "op": "mstore", - "out": [] - } + "in": [ + "0x00", + "0x00" ], - "type": "BuiltinCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x20", - "v0" - ], - "op": "add", - "out": [ - "v4" - ] - }, - { - "in": [ - "0x00", - "v0" - ], - "op": "add", - "out": [ - "v5" - ] - }, - { - "in": [ - "v5", - "v1" - ], - "op": "abi_encode_t_uint256_to_t_uint256_fromStack", - "out": [] - } + "in": [ + "0x2a", + "v0" ], - "type": "FunctionCall" + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "allocate_unbounded": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "cleanup_t_rational_42_by_1": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "cleanup_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "convert_t_rational_42_by_1_to_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_rational_42_by_1", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2" - ], - "op": "identity", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3" - ], - "op": "cleanup_t_uint256", - "out": [ - "v4" - ] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "external_fun_f_18": { - "arguments": [], - "blocks": [ - { - "exit": { - "cond": "v0", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "callvalue", - "out": [ - "v0" - ] - } - ], - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block2", - "instructions": [ - { - "in": [], - "op": "calldatasize", - "out": [ - "v1" - ] - }, - { - "in": [ - "v1", - "0x04" - ], - "op": "abi_decode_tuple_", - "out": [] - }, - { - "in": [], - "op": "fun_f_18", - "out": [ - "v3" - ] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v4" - ] - }, - { - "in": [ - "v3", - "v4" - ], - "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", - "out": [ - "v5" - ] - }, - { - "in": [ - "v4", - "v5" - ], - "op": "sub", - "out": [ - "v6" - ] - }, - { - "in": [ - "v6", - "v4" - ], - "op": "return", - "out": [] - } - ], - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "fun_f_18": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "zero_value_for_split_t_uint256", - "out": [ - "v1" - ] - }, - { - "in": [ - "0x2a" - ], - "op": "convert_t_rational_42_by_1_to_t_uint256", - "out": [ - "v3" - ] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "identity": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "shift_right_224_unsigned": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "0xe0" - ], - "op": "shr", - "out": [ - "v3" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "zero_value_for_split_t_uint256": { - "arguments": [], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ { - "exit": { - "returnValues": [ - "0x00" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" } - } + ], + "functions": {} }, "subObjects": {}, "type": "subObject" @@ -965,7 +397,7 @@ "instructions": [ { "builtinArgs": [ - "128" + "0x80" ], "in": [], "op": "memoryguard", @@ -997,18 +429,6 @@ }, "id": "Block2", "instructions": [ - { - "in": [], - "op": "constructor_D_38", - "out": [] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v3" - ] - }, { "builtinArgs": [ "D_38_deployed" @@ -1033,25 +453,15 @@ "in": [ "v4", "v5", - "v3" + "v0" ], "op": "codecopy", "out": [] }, - { - "builtinArgs": [ - "D_38_deployed" - ], - "in": [], - "op": "datasize", - "out": [ - "v6" - ] - }, { "in": [ - "v6", - "v3" + "v4", + "v0" ], "op": "return", "out": [] @@ -1066,86 +476,18 @@ "id": "Block1", "instructions": [ { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "in": [ + "0x00", + "0x00" + ], + "op": "revert", "out": [] } ], - "type": "FunctionCall" + "type": "BuiltinCall" } ], - "functions": { - "allocate_unbounded": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "constructor_D_38": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - } - } + "functions": {} }, "subObjects": { "D_38_deployed": { @@ -1153,1787 +495,947 @@ { "exit": { "cond": "v5", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "builtinArgs": [ - "128" - ], - "in": [], - "op": "memoryguard", - "out": [ - "v0" - ] - }, - { - "in": [ - "v0", - "0x40" - ], - "op": "mstore", - "out": [] - }, - { - "in": [], - "op": "calldatasize", - "out": [ - "v3" - ] - }, - { - "in": [ - "0x04", - "v3" - ], - "op": "lt", - "out": [ - "v4" - ] - }, - { - "in": [ - "v4" - ], - "op": "iszero", - "out": [ - "v5" - ] - } - ], - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block2", - "instructions": [ - { - "in": [], - "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", - "out": [] - } - ], - "type": "FunctionCall" - }, - { - "exit": { - "cond": "v9", - "targets": [ - "Block5", - "Block4" - ], - "type": "ConditionalJump" - }, - "id": "Block1", - "instructions": [ - { - "in": [ - "0x00" - ], - "op": "calldataload", - "out": [ - "v7" - ] - }, - { - "in": [ - "v7" - ], - "op": "shift_right_224_unsigned", - "out": [ - "v8" - ] - }, - { - "in": [ - "0x26121ff0", - "v8" - ], - "op": "eq", - "out": [ - "v9" - ] - } - ], - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block3" - ], - "type": "Jump" - }, - "id": "Block5", - "instructions": [] - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block4", - "instructions": [ - { - "in": [], - "op": "external_fun_f_37", - "out": [] - } - ], - "type": "FunctionCall" - }, - { - "exit": { - "targets": [ - "Block2" - ], - "type": "Jump" - }, - "id": "Block3", - "instructions": [] - } - ], - "functions": { - "abi_decode_t_uint256_fromMemory": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "mload", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3" - ], - "op": "validator_revert_t_uint256", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "abi_decode_tuple_": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ { - "exit": { - "cond": "v4", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "v1" - ], - "op": "sub", - "out": [ - "v3" - ] - }, - { - "in": [ - "0x00", - "v3" - ], - "op": "slt", - "out": [ - "v4" - ] - } + "builtinArgs": [ + "0x80" ], - "type": "BuiltinCall" - }, - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [] + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", - "out": [] - } + "in": [ + "v0", + "0x40" ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "abi_decode_tuple_t_uint256_fromMemory": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + "op": "mstore", + "out": [] + }, { - "exit": { - "cond": "v5", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "v1" - ], - "op": "sub", - "out": [ - "v4" - ] - }, - { - "in": [ - "0x20", - "v4" - ], - "op": "slt", - "out": [ - "v5" - ] - } - ], - "type": "BuiltinCall" + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] }, { - "exit": { - "returnValues": [ - "v12" - ], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [ - { - "in": [ - "0x00", - "v0" - ], - "op": "add", - "out": [ - "v11" - ] - }, - { - "in": [ - "v1", - "v11" - ], - "op": "abi_decode_t_uint256_fromMemory", - "out": [ - "v12" - ] - } + "in": [ + "0x04", + "v3" ], - "type": "FunctionCall" + "op": "lt", + "out": [ + "v4" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", - "out": [] - } + "in": [ + "v4" ], - "type": "FunctionCall" + "op": "iszero", + "out": [ + "v5" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "abi_encode_t_uint256_to_t_uint256_fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_uint256", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2", - "v1" - ], - "op": "mstore", - "out": [] - } + "in": [ + "0x00", + "0x00" ], - "type": "BuiltinCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "abi_encode_tuple__to__fromStack": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "v0" - ], - "op": "add", - "out": [ - "v2" - ] - } + "in": [ + "0x00" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + "op": "calldataload", + "out": [ + "v7" + ] + }, { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x20", - "v0" - ], - "op": "add", - "out": [ - "v4" - ] - }, - { - "in": [ - "0x00", - "v0" - ], - "op": "add", - "out": [ - "v5" - ] - }, - { - "in": [ - "v5", - "v1" - ], - "op": "abi_encode_t_uint256_to_t_uint256_fromStack", - "out": [] - } + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" ], - "type": "FunctionCall" + "op": "eq", + "out": [ + "v11" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "allocate_unbounded": { - "arguments": [], - "blocks": [ + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [] + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "cleanup_t_uint160": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0xffffffffffffffffffffffffffffffffffffffff", - "v0" - ], - "op": "and", - "out": [ - "v3" - ] - } + "in": [ + "0x03" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "cleanup_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ + "op": "not", + "out": [ + "v14" + ] + }, { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "convert_t_contract$_C_$19_to_t_address": { - "arguments": [ - "v0" - ], - "blocks": [ + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "convert_t_uint160_to_t_address", - "out": [ - "v2" - ] - } + "in": [ + "v14", + "v15" ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "convert_t_uint160_to_t_address": { - "arguments": [ - "v0" - ], - "blocks": [ + "op": "add", + "out": [ + "v16" + ] + }, { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "convert_t_uint160_to_t_uint160", - "out": [ - "v2" - ] - } + "in": [ + "0x00", + "v16" ], - "type": "FunctionCall" + "op": "slt", + "out": [ + "v17" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "convert_t_uint160_to_t_uint160": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_uint160", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2" - ], - "op": "identity", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3" - ], - "op": "cleanup_t_uint160", - "out": [ - "v4" - ] - } + "in": [ + "0x00", + "0x00" ], - "type": "FunctionCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "external_fun_f_37": { - "arguments": [], - "blocks": [ + { + "exit": { + "cond": "v28", + "targets": [ + "Block12", + "Block11" + ], + "type": "ConditionalJump" + }, + "id": "Block9", + "instructions": [ { - "exit": { - "cond": "v0", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "callvalue", - "out": [ - "v0" - ] - } + "builtinArgs": [ + "C_19" ], - "type": "BuiltinCall" + "in": [], + "op": "datasize", + "out": [ + "v18" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block2", - "instructions": [ - { - "in": [], - "op": "calldatasize", - "out": [ - "v1" - ] - }, - { - "in": [ - "v1", - "0x04" - ], - "op": "abi_decode_tuple_", - "out": [] - }, - { - "in": [], - "op": "fun_f_37", - "out": [ - "v3" - ] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v4" - ] - }, - { - "in": [ - "v3", - "v4" - ], - "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", - "out": [ - "v5" - ] - }, - { - "in": [ - "v4", - "v5" - ], - "op": "sub", - "out": [ - "v6" - ] - }, - { - "in": [ - "v6", - "v4" - ], - "op": "return", - "out": [] - } + "in": [ + "v18", + "v0" + ], + "op": "add", + "out": [ + "v24" + ] + }, + { + "in": [ + "v0", + "v24" ], - "type": "BuiltinCall" + "op": "lt", + "out": [ + "v25" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "out": [] - } + "in": [ + "0xffffffffffffffff", + "v24" ], - "type": "FunctionCall" + "op": "gt", + "out": [ + "v27" + ] + }, + { + "in": [ + "v25", + "v27" + ], + "op": "or", + "out": [ + "v28" + ] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "finalize_allocation": { - "arguments": [ - "v0", - "v1" + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "blocks": [ + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v42", + "targets": [ + "Block15", + "Block14" + ], + "type": "ConditionalJump" + }, + "id": "Block12", + "instructions": [ { - "exit": { - "cond": "v7", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v1" - ], - "op": "round_up_to_mul_of_32", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2", - "v0" - ], - "op": "add", - "out": [ - "v3" - ] - }, - { - "in": [ - "v0", - "v3" - ], - "op": "lt", - "out": [ - "v4" - ] - }, - { - "in": [ - "0xffffffffffffffff", - "v3" - ], - "op": "gt", - "out": [ - "v6" - ] - }, - { - "in": [ - "v4", - "v6" - ], - "op": "or", - "out": [ - "v7" - ] - } + "builtinArgs": [ + "C_19" ], - "type": "BuiltinCall" + "in": [], + "op": "dataoffset", + "out": [ + "v35" + ] }, { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [ - { - "in": [ - "v3", - "0x40" - ], - "op": "mstore", - "out": [] - } + "in": [ + "v18", + "v35", + "v0" ], - "type": "BuiltinCall" + "op": "datacopy", + "out": [] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "panic_error_0x41", - "out": [] - } + "in": [ + "v0", + "v24" ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "fun_f_37": { - "arguments": [], - "blocks": [ + "op": "sub", + "out": [ + "v40" + ] + }, { - "exit": { - "cond": "v8", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "zero_value_for_split_t_uint256", - "out": [ - "v1" - ] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v2" - ] - }, - { - "builtinArgs": [ - "C_19" - ], - "in": [], - "op": "datasize", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3", - "v2" - ], - "op": "add", - "out": [ - "v4" - ] - }, - { - "in": [ - "v2", - "v4" - ], - "op": "lt", - "out": [ - "v5" - ] - }, - { - "in": [ - "0xffffffffffffffff", - "v4" - ], - "op": "gt", - "out": [ - "v7" - ] - }, - { - "in": [ - "v5", - "v7" - ], - "op": "or", - "out": [ - "v8" - ] - } + "in": [ + "v40", + "v0", + "0x00" ], - "type": "BuiltinCall" + "op": "create", + "out": [ + "v41" + ] }, { - "exit": { - "cond": "v19", - "targets": [ - "Block5", - "Block4" - ], - "type": "ConditionalJump" - }, - "id": "Block2", - "instructions": [ - { - "builtinArgs": [ - "C_19" - ], - "in": [], - "op": "datasize", - "out": [ - "v9" - ] - }, - { - "builtinArgs": [ - "C_19" - ], - "in": [], - "op": "dataoffset", - "out": [ - "v10" - ] - }, - { - "in": [ - "v9", - "v10", - "v2" - ], - "op": "datacopy", - "out": [] - }, - { - "in": [ - "v4" - ], - "op": "abi_encode_tuple__to__fromStack", - "out": [ - "v16" - ] - }, - { - "in": [ - "v2", - "v16" - ], - "op": "sub", - "out": [ - "v17" - ] - }, - { - "in": [ - "v17", - "v2", - "0x00" - ], - "op": "create", - "out": [ - "v18" - ] - }, - { - "in": [ - "v18" - ], - "op": "iszero", - "out": [ - "v19" - ] - } + "in": [ + "v41" ], - "type": "BuiltinCall" + "op": "iszero", + "out": [ + "v42" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block11", + "instructions": [ + { + "in": [ + "0x4e487b71", + "0xe0" + ], + "op": "shl", + "out": [ + "v30" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "panic_error_0x41", - "out": [] - } + "in": [ + "v30", + "0x00" ], - "type": "FunctionCall" + "op": "mstore", + "out": [] }, { - "exit": { - "cond": "v33", - "targets": [ - "Block8", - "Block7" - ], - "type": "ConditionalJump" - }, - "id": "Block5", - "instructions": [ - { - "in": [ - "v18" - ], - "op": "convert_t_contract$_C_$19_to_t_address", - "out": [ - "v22" - ] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v24" - ] - }, - { - "in": [ - "0x26121ff0" - ], - "op": "shift_left_224", - "out": [ - "v25" - ] - }, - { - "in": [ - "v25", - "v24" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x04", - "v24" - ], - "op": "add", - "out": [ - "v27" - ] - }, - { - "in": [ - "v27" - ], - "op": "abi_encode_tuple__to__fromStack", - "out": [ - "v28" - ] - }, - { - "in": [ - "v24", - "v28" - ], - "op": "sub", - "out": [ - "v30" - ] - }, - { - "in": [], - "op": "gas", - "out": [ - "v31" - ] - }, - { - "in": [ - "0x20", - "v24", - "v30", - "v24", - "v22", - "v31" - ], - "op": "staticcall", - "out": [ - "v32" - ] - }, - { - "in": [ - "v32" - ], - "op": "iszero", - "out": [ - "v33" - ] - } + "in": [ + "0x41", + "0x04" ], - "type": "BuiltinCall" + "op": "mstore", + "out": [] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block4", - "instructions": [ - { - "in": [], - "op": "revert_forward_1", - "out": [] - } + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v60", + "targets": [ + "Block18", + "Block17" + ], + "type": "ConditionalJump" + }, + "id": "Block15", + "instructions": [ + { + "in": [ + "0x40" ], - "type": "FunctionCall" + "op": "mload", + "out": [ + "v46" + ] }, { - "exit": { - "cond": "v32", - "targets": [ - "Block11", - "Block10" - ], - "type": "ConditionalJump" - }, - "id": "Block8", - "instructions": [] + "in": [ + "0x026121ff", + "0xe4" + ], + "op": "shl", + "out": [ + "v49" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block7", - "instructions": [ - { - "in": [], - "op": "revert_forward_1", - "out": [] - } + "in": [ + "v49", + "v46" ], - "type": "FunctionCall" + "op": "mstore", + "out": [] }, { - "entries": [ - "Block8", - "Block13" + "in": [ + "0x01", + "0xa0" ], - "exit": { - "returnValues": [ - "v45" - ], - "type": "FunctionReturn" - }, - "id": "Block11", - "instructions": [ - { - "in": [ - "0x00", - "v44" - ], - "op": "PhiFunction", - "out": [ - "v45" - ] - } + "op": "shl", + "out": [ + "v53" ] }, { - "exit": { - "cond": "v37", - "targets": [ - "Block13", - "Block12" - ], - "type": "ConditionalJump" - }, - "id": "Block10", - "instructions": [ - { - "in": [], - "op": "returndatasize", - "out": [ - "v36" - ] - }, - { - "in": [ - "v36", - "0x20" - ], - "op": "gt", - "out": [ - "v37" - ] - } + "in": [ + "0x01", + "v53" ], - "type": "BuiltinCall" + "op": "sub", + "out": [ + "v54" + ] }, { - "entries": [ - "Block10", - "Block12" + "in": [ + "v54", + "v41" ], - "exit": { - "targets": [ - "Block11" - ], - "type": "Jump" - }, - "id": "Block13", - "instructions": [ - { - "in": [ - "0x20", - "v38" - ], - "op": "PhiFunction", - "out": [ - "v39" - ] - }, - { - "in": [ - "v39", - "v24" - ], - "op": "finalize_allocation", - "out": [] - }, - { - "in": [ - "v39", - "v24" - ], - "op": "add", - "out": [ - "v43" - ] - }, - { - "in": [ - "v43", - "v24" - ], - "op": "abi_decode_tuple_t_uint256_fromMemory", - "out": [ - "v44" - ] - } + "op": "and", + "out": [ + "v57" + ] + }, + { + "in": [], + "op": "gas", + "out": [ + "v58" + ] + }, + { + "in": [ + "0x20", + "v46", + "0x04", + "v46", + "v57", + "v58" + ], + "op": "staticcall", + "out": [ + "v59" + ] + }, + { + "in": [ + "v59" + ], + "op": "iszero", + "out": [ + "v60" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block14", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v43" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v44" + ] + }, + { + "in": [ + "v44", + "0x00", + "v43" ], - "type": "FunctionCall" + "op": "returndatacopy", + "out": [] }, { - "exit": { - "targets": [ - "Block13" - ], - "type": "Jump" - }, - "id": "Block12", - "instructions": [ - { - "in": [], - "op": "returndatasize", - "out": [ - "v38" - ] - } + "in": [], + "op": "returndatasize", + "out": [ + "v45" + ] + }, + { + "in": [ + "v45", + "v43" ], - "type": "BuiltinCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "identity": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + { + "exit": { + "cond": "v59", + "targets": [ + "Block21", + "Block20" + ], + "type": "ConditionalJump" + }, + "id": "Block18", + "instructions": [] }, - "panic_error_0x41": { - "arguments": [], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block17", + "instructions": [ { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x4e487b7100000000000000000000000000000000000000000000000000000000", - "0x00" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x41", - "0x04" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x24", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x40" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_0cc013b6b3b6beabea4e3a74a6d380f0df81852ca99887912475e1f66b2a2c20": { - "arguments": [], - "blocks": [ + "op": "mload", + "out": [ + "v61" + ] + }, { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [], + "op": "returndatasize", + "out": [ + "v62" + ] + }, + { + "in": [ + "v62", + "0x00", + "v61" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { - "arguments": [], - "blocks": [ + "op": "returndatacopy", + "out": [] + }, { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [], + "op": "returndatasize", + "out": [ + "v63" + ] + }, + { + "in": [ + "v63", + "v61" ], - "type": "BuiltinCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db": { - "arguments": [], - "blocks": [ + { + "entries": [ + "Block18", + "Block28" + ], + "exit": { + "type": "Terminated" + }, + "id": "Block21", + "instructions": [ { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x00", + "v93" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ + "op": "PhiFunction", + "out": [ + "v95" + ] + }, { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x40" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { - "arguments": [], - "blocks": [ + "op": "mload", + "out": [ + "v94" + ] + }, { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "v95", + "v94" ], - "type": "BuiltinCall" + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v94" + ], + "op": "return", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "revert_forward_1": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v0" - ] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v1" - ] - }, - { - "in": [ - "v1", - "0x00", - "v0" - ], - "op": "returndatacopy", - "out": [] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3", - "v0" - ], - "op": "revert", - "out": [] - } + { + "exit": { + "cond": "v67", + "targets": [ + "Block23", + "Block22" + ], + "type": "ConditionalJump" + }, + "id": "Block20", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v66" + ] + }, + { + "in": [ + "v66", + "0x20" ], - "type": "BuiltinCall" + "op": "gt", + "out": [ + "v67" + ] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "round_up_to_mul_of_32": { - "arguments": [ - "v0" + { + "entries": [ + "Block20", + "Block22" ], - "blocks": [ + "exit": { + "cond": "v80", + "targets": [ + "Block25", + "Block24" + ], + "type": "ConditionalJump" + }, + "id": "Block23", + "instructions": [ { - "exit": { - "returnValues": [ - "v5" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x1f" - ], - "op": "not", - "out": [ - "v3" - ] - }, - { - "in": [ - "0x1f", - "v0" - ], - "op": "add", - "out": [ - "v4" - ] - }, - { - "in": [ - "v3", - "v4" - ], - "op": "and", - "out": [ - "v5" - ] - } + "in": [ + "0x20", + "v68" ], - "type": "BuiltinCall" + "op": "PhiFunction", + "out": [ + "v71" + ] + }, + { + "in": [ + "0x1f" + ], + "op": "not", + "out": [ + "v70" + ] + }, + { + "in": [ + "0x1f", + "v71" + ], + "op": "add", + "out": [ + "v72" + ] + }, + { + "in": [ + "v70", + "v72" + ], + "op": "and", + "out": [ + "v73" + ] + }, + { + "in": [ + "v73", + "v46" + ], + "op": "add", + "out": [ + "v77" + ] + }, + { + "in": [ + "v46", + "v77" + ], + "op": "lt", + "out": [ + "v78" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v77" + ], + "op": "gt", + "out": [ + "v79" + ] + }, + { + "in": [ + "v78", + "v79" + ], + "op": "or", + "out": [ + "v80" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "shift_left_224": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "targets": [ + "Block23" + ], + "type": "Jump" + }, + "id": "Block22", + "instructions": [ { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "0xe0" - ], - "op": "shl", - "out": [ - "v3" - ] - } - ], - "type": "BuiltinCall" + "in": [], + "op": "returndatasize", + "out": [ + "v68" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "shift_right_224_unsigned": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "cond": "v90", + "targets": [ + "Block28", + "Block27" + ], + "type": "ConditionalJump" + }, + "id": "Block25", + "instructions": [ { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "0xe0" - ], - "op": "shr", - "out": [ - "v3" - ] - } + "in": [ + "v77", + "0x40" ], - "type": "BuiltinCall" + "op": "mstore", + "out": [] + }, + { + "in": [ + "v71", + "v46" + ], + "op": "add", + "out": [ + "v88" + ] + }, + { + "in": [ + "v46", + "v88" + ], + "op": "sub", + "out": [ + "v89" + ] + }, + { + "in": [ + "0x20", + "v89" + ], + "op": "slt", + "out": [ + "v90" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "validator_revert_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block24", + "instructions": [ { - "exit": { - "cond": "v3", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_uint256", - "out": [ - "v1" - ] - }, - { - "in": [ - "v1", - "v0" - ], - "op": "eq", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2" - ], - "op": "iszero", - "out": [ - "v3" - ] - } + "in": [ + "0x4e487b71", + "0xe0" ], - "type": "BuiltinCall" + "op": "shl", + "out": [ + "v81" + ] }, { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [] + "in": [ + "v81", + "0x00" + ], + "op": "mstore", + "out": [] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x41", + "0x04" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block21" + ], + "type": "Jump" + }, + "id": "Block28", + "instructions": [ + { + "in": [ + "v46" ], - "type": "BuiltinCall" + "op": "mload", + "out": [ + "v93" + ] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "zero_value_for_split_t_uint256": { - "arguments": [], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block27", + "instructions": [ { - "exit": { - "returnValues": [ - "0x00" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" } - } + ], + "functions": {} }, "subObjects": { "C_19": { @@ -2951,7 +1453,7 @@ "instructions": [ { "builtinArgs": [ - "128" + "0x80" ], "in": [], "op": "memoryguard", @@ -2983,18 +1485,6 @@ }, "id": "Block2", "instructions": [ - { - "in": [], - "op": "constructor_C_19", - "out": [] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v3" - ] - }, { "builtinArgs": [ "C_19_deployed" @@ -3019,25 +1509,15 @@ "in": [ "v4", "v5", - "v3" + "v0" ], "op": "codecopy", "out": [] }, - { - "builtinArgs": [ - "C_19_deployed" - ], - "in": [], - "op": "datasize", - "out": [ - "v6" - ] - }, { "in": [ - "v6", - "v3" + "v4", + "v0" ], "op": "return", "out": [] @@ -3052,109 +1532,18 @@ "id": "Block1", "instructions": [ { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "in": [ + "0x00", + "0x00" + ], + "op": "revert", "out": [] } ], - "type": "FunctionCall" + "type": "BuiltinCall" } ], - "functions": { - "allocate_unbounded": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "constructor_C_19": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "constructor_I_7", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "constructor_I_7": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - } - } + "functions": {} }, "subObjects": { "C_19_deployed": { @@ -3172,7 +1561,7 @@ "instructions": [ { "builtinArgs": [ - "128" + "0x80" ], "in": [], "op": "memoryguard", @@ -3224,19 +1613,22 @@ "id": "Block2", "instructions": [ { - "in": [], - "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", + "in": [ + "0x00", + "0x00" + ], + "op": "revert", "out": [] } ], - "type": "FunctionCall" + "type": "BuiltinCall" }, { "exit": { - "cond": "v9", + "cond": "v11", "targets": [ - "Block5", - "Block4" + "Block4", + "Block3" ], "type": "ConditionalJump" }, @@ -3253,21 +1645,22 @@ }, { "in": [ - "v7" + "v7", + "0xe0" ], - "op": "shift_right_224_unsigned", + "op": "shr", "out": [ - "v8" + "v9" ] }, { "in": [ - "0x26121ff0", - "v8" + "v9", + "0x26121ff0" ], "op": "eq", "out": [ - "v9" + "v11" ] } ], @@ -3276,604 +1669,145 @@ { "exit": { "targets": [ - "Block3" + "Block2" ], "type": "Jump" }, - "id": "Block5", + "id": "Block4", "instructions": [] }, { "exit": { - "type": "Terminated" + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" }, - "id": "Block4", + "id": "Block3", "instructions": [ { "in": [], - "op": "external_fun_f_18", - "out": [] + "op": "callvalue", + "out": [ + "v12" + ] } ], - "type": "FunctionCall" + "type": "BuiltinCall" }, { "exit": { + "cond": "v17", "targets": [ - "Block2" + "Block9", + "Block8" ], - "type": "Jump" + "type": "ConditionalJump" }, - "id": "Block3", - "instructions": [] - } - ], - "functions": { - "abi_decode_tuple_": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + "id": "Block6", + "instructions": [ { - "exit": { - "cond": "v4", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "v1" - ], - "op": "sub", - "out": [ - "v3" - ] - }, - { - "in": [ - "0x00", - "v3" - ], - "op": "slt", - "out": [ - "v4" - ] - } + "in": [ + "0x03" ], - "type": "BuiltinCall" - }, - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [] + "op": "not", + "out": [ + "v14" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "abi_encode_t_uint256_to_t_uint256_fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_uint256", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2", - "v1" - ], - "op": "mstore", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x20", - "v0" - ], - "op": "add", - "out": [ - "v4" - ] - }, - { - "in": [ - "0x00", - "v0" - ], - "op": "add", - "out": [ - "v5" - ] - }, - { - "in": [ - "v5", - "v1" - ], - "op": "abi_encode_t_uint256_to_t_uint256_fromStack", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "allocate_unbounded": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "cleanup_t_rational_42_by_1": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "cleanup_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "convert_t_rational_42_by_1_to_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_rational_42_by_1", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2" - ], - "op": "identity", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3" - ], - "op": "cleanup_t_uint256", - "out": [ - "v4" - ] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "external_fun_f_18": { - "arguments": [], - "blocks": [ - { - "exit": { - "cond": "v0", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "callvalue", - "out": [ - "v0" - ] - } - ], - "type": "BuiltinCall" + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block2", - "instructions": [ - { - "in": [], - "op": "calldatasize", - "out": [ - "v1" - ] - }, - { - "in": [ - "v1", - "0x04" - ], - "op": "abi_decode_tuple_", - "out": [] - }, - { - "in": [], - "op": "fun_f_18", - "out": [ - "v3" - ] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v4" - ] - }, - { - "in": [ - "v3", - "v4" - ], - "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", - "out": [ - "v5" - ] - }, - { - "in": [ - "v4", - "v5" - ], - "op": "sub", - "out": [ - "v6" - ] - }, - { - "in": [ - "v6", - "v4" - ], - "op": "return", - "out": [] - } + "in": [ + "v14", + "v15" ], - "type": "BuiltinCall" + "op": "add", + "out": [ + "v16" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "fun_f_18": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "zero_value_for_split_t_uint256", - "out": [ - "v1" - ] - }, - { - "in": [ - "0x2a" - ], - "op": "convert_t_rational_42_by_1_to_t_uint256", - "out": [ - "v3" - ] - } + "in": [ + "0x00", + "v16" ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "identity": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] + "op": "slt", + "out": [ + "v17" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { - "arguments": [], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x00", + "0x00" ], - "type": "BuiltinCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x2a", + "v0" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { - "arguments": [], - "blocks": [ + "op": "mstore", + "out": [] + }, { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x20", + "v0" ], - "type": "BuiltinCall" + "op": "return", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "shift_right_224_unsigned": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "0xe0" - ], - "op": "shr", - "out": [ - "v3" - ] - } + "in": [ + "0x00", + "0x00" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "zero_value_for_split_t_uint256": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "0x00" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" } - } + ], + "functions": {} }, "subObjects": {}, "type": "subObject" diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index d8f2025b3..8339d02c7 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -17,7 +17,7 @@ Yul Control Flow Graph: "instructions": [ { "builtinArgs": [ - "128" + "0x80" ], "in": [], "op": "memoryguard", @@ -49,18 +49,6 @@ Yul Control Flow Graph: }, "id": "Block2", "instructions": [ - { - "in": [], - "op": "constructor_C_19", - "out": [] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v3" - ] - }, { "builtinArgs": [ "C_19_deployed" @@ -85,25 +73,15 @@ Yul Control Flow Graph: "in": [ "v4", "v5", - "v3" + "v0" ], "op": "codecopy", "out": [] }, - { - "builtinArgs": [ - "C_19_deployed" - ], - "in": [], - "op": "datasize", - "out": [ - "v6" - ] - }, { "in": [ - "v6", - "v3" + "v4", + "v0" ], "op": "return", "out": [] @@ -118,109 +96,18 @@ Yul Control Flow Graph: "id": "Block1", "instructions": [ { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "in": [ + "0x00", + "0x00" + ], + "op": "revert", "out": [] } ], - "type": "FunctionCall" + "type": "BuiltinCall" } ], - "functions": { - "allocate_unbounded": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "constructor_C_19": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "constructor_I_7", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "constructor_I_7": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - } - } + "functions": {} }, "subObjects": { "C_19_deployed": { @@ -238,7 +125,7 @@ Yul Control Flow Graph: "instructions": [ { "builtinArgs": [ - "128" + "0x80" ], "in": [], "op": "memoryguard", @@ -290,19 +177,22 @@ Yul Control Flow Graph: "id": "Block2", "instructions": [ { - "in": [], - "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", + "in": [ + "0x00", + "0x00" + ], + "op": "revert", "out": [] } ], - "type": "FunctionCall" + "type": "BuiltinCall" }, { "exit": { - "cond": "v9", + "cond": "v11", "targets": [ - "Block5", - "Block4" + "Block4", + "Block3" ], "type": "ConditionalJump" }, @@ -319,21 +209,22 @@ Yul Control Flow Graph: }, { "in": [ - "v7" + "v7", + "0xe0" ], - "op": "shift_right_224_unsigned", + "op": "shr", "out": [ - "v8" + "v9" ] }, { "in": [ - "0x26121ff0", - "v8" + "v9", + "0x26121ff0" ], "op": "eq", "out": [ - "v9" + "v11" ] } ], @@ -342,604 +233,145 @@ Yul Control Flow Graph: { "exit": { "targets": [ - "Block3" + "Block2" ], "type": "Jump" }, - "id": "Block5", + "id": "Block4", "instructions": [] }, { "exit": { - "type": "Terminated" + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" }, - "id": "Block4", + "id": "Block3", "instructions": [ { "in": [], - "op": "external_fun_f_18", - "out": [] + "op": "callvalue", + "out": [ + "v12" + ] } ], - "type": "FunctionCall" + "type": "BuiltinCall" }, { "exit": { + "cond": "v17", "targets": [ - "Block2" + "Block9", + "Block8" ], - "type": "Jump" + "type": "ConditionalJump" }, - "id": "Block3", - "instructions": [] - } - ], - "functions": { - "abi_decode_tuple_": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + "id": "Block6", + "instructions": [ { - "exit": { - "cond": "v4", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "v1" - ], - "op": "sub", - "out": [ - "v3" - ] - }, - { - "in": [ - "0x00", - "v3" - ], - "op": "slt", - "out": [ - "v4" - ] - } + "in": [ + "0x03" ], - "type": "BuiltinCall" + "op": "not", + "out": [ + "v14" + ] }, { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [] + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", - "out": [] - } + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" ], - "type": "FunctionCall" + "op": "slt", + "out": [ + "v17" + ] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "abi_encode_t_uint256_to_t_uint256_fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_uint256", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2", - "v1" - ], - "op": "mstore", - "out": [] - } + "in": [ + "0x00", + "0x00" ], - "type": "BuiltinCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x20", - "v0" - ], - "op": "add", - "out": [ - "v4" - ] - }, - { - "in": [ - "0x00", - "v0" - ], - "op": "add", - "out": [ - "v5" - ] - }, - { - "in": [ - "v5", - "v1" - ], - "op": "abi_encode_t_uint256_to_t_uint256_fromStack", - "out": [] - } + "in": [ + "0x2a", + "v0" ], - "type": "FunctionCall" + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "allocate_unbounded": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "cleanup_t_rational_42_by_1": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "cleanup_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "convert_t_rational_42_by_1_to_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_rational_42_by_1", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2" - ], - "op": "identity", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3" - ], - "op": "cleanup_t_uint256", - "out": [ - "v4" - ] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "external_fun_f_18": { - "arguments": [], - "blocks": [ - { - "exit": { - "cond": "v0", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "callvalue", - "out": [ - "v0" - ] - } - ], - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block2", - "instructions": [ - { - "in": [], - "op": "calldatasize", - "out": [ - "v1" - ] - }, - { - "in": [ - "v1", - "0x04" - ], - "op": "abi_decode_tuple_", - "out": [] - }, - { - "in": [], - "op": "fun_f_18", - "out": [ - "v3" - ] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v4" - ] - }, - { - "in": [ - "v3", - "v4" - ], - "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", - "out": [ - "v5" - ] - }, - { - "in": [ - "v4", - "v5" - ], - "op": "sub", - "out": [ - "v6" - ] - }, - { - "in": [ - "v6", - "v4" - ], - "op": "return", - "out": [] - } - ], - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "fun_f_18": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "zero_value_for_split_t_uint256", - "out": [ - "v1" - ] - }, - { - "in": [ - "0x2a" - ], - "op": "convert_t_rational_42_by_1_to_t_uint256", - "out": [ - "v3" - ] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "identity": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "shift_right_224_unsigned": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "0xe0" - ], - "op": "shr", - "out": [ - "v3" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "zero_value_for_split_t_uint256": { - "arguments": [], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ { - "exit": { - "returnValues": [ - "0x00" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" } - } + ], + "functions": {} }, "subObjects": {}, "type": "subObject" @@ -965,7 +397,7 @@ Yul Control Flow Graph: "instructions": [ { "builtinArgs": [ - "128" + "0x80" ], "in": [], "op": "memoryguard", @@ -997,18 +429,6 @@ Yul Control Flow Graph: }, "id": "Block2", "instructions": [ - { - "in": [], - "op": "constructor_D_38", - "out": [] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v3" - ] - }, { "builtinArgs": [ "D_38_deployed" @@ -1033,25 +453,15 @@ Yul Control Flow Graph: "in": [ "v4", "v5", - "v3" + "v0" ], "op": "codecopy", "out": [] }, - { - "builtinArgs": [ - "D_38_deployed" - ], - "in": [], - "op": "datasize", - "out": [ - "v6" - ] - }, { "in": [ - "v6", - "v3" + "v4", + "v0" ], "op": "return", "out": [] @@ -1066,86 +476,18 @@ Yul Control Flow Graph: "id": "Block1", "instructions": [ { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "in": [ + "0x00", + "0x00" + ], + "op": "revert", "out": [] } ], - "type": "FunctionCall" + "type": "BuiltinCall" } ], - "functions": { - "allocate_unbounded": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "constructor_D_38": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - } - } + "functions": {} }, "subObjects": { "D_38_deployed": { @@ -1153,1787 +495,947 @@ Yul Control Flow Graph: { "exit": { "cond": "v5", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "builtinArgs": [ - "128" - ], - "in": [], - "op": "memoryguard", - "out": [ - "v0" - ] - }, - { - "in": [ - "v0", - "0x40" - ], - "op": "mstore", - "out": [] - }, - { - "in": [], - "op": "calldatasize", - "out": [ - "v3" - ] - }, - { - "in": [ - "0x04", - "v3" - ], - "op": "lt", - "out": [ - "v4" - ] - }, - { - "in": [ - "v4" - ], - "op": "iszero", - "out": [ - "v5" - ] - } - ], - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block2", - "instructions": [ - { - "in": [], - "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", - "out": [] - } - ], - "type": "FunctionCall" - }, - { - "exit": { - "cond": "v9", - "targets": [ - "Block5", - "Block4" - ], - "type": "ConditionalJump" - }, - "id": "Block1", - "instructions": [ - { - "in": [ - "0x00" - ], - "op": "calldataload", - "out": [ - "v7" - ] - }, - { - "in": [ - "v7" - ], - "op": "shift_right_224_unsigned", - "out": [ - "v8" - ] - }, - { - "in": [ - "0x26121ff0", - "v8" - ], - "op": "eq", - "out": [ - "v9" - ] - } - ], - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block3" - ], - "type": "Jump" - }, - "id": "Block5", - "instructions": [] - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block4", - "instructions": [ - { - "in": [], - "op": "external_fun_f_37", - "out": [] - } - ], - "type": "FunctionCall" - }, - { - "exit": { - "targets": [ - "Block2" - ], - "type": "Jump" - }, - "id": "Block3", - "instructions": [] - } - ], - "functions": { - "abi_decode_t_uint256_fromMemory": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "mload", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3" - ], - "op": "validator_revert_t_uint256", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "abi_decode_tuple_": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ { - "exit": { - "cond": "v4", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "v1" - ], - "op": "sub", - "out": [ - "v3" - ] - }, - { - "in": [ - "0x00", - "v3" - ], - "op": "slt", - "out": [ - "v4" - ] - } + "builtinArgs": [ + "0x80" ], - "type": "BuiltinCall" - }, - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [] + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", - "out": [] - } + "in": [ + "v0", + "0x40" ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "abi_decode_tuple_t_uint256_fromMemory": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + "op": "mstore", + "out": [] + }, { - "exit": { - "cond": "v5", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "v1" - ], - "op": "sub", - "out": [ - "v4" - ] - }, - { - "in": [ - "0x20", - "v4" - ], - "op": "slt", - "out": [ - "v5" - ] - } - ], - "type": "BuiltinCall" + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] }, { - "exit": { - "returnValues": [ - "v12" - ], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [ - { - "in": [ - "0x00", - "v0" - ], - "op": "add", - "out": [ - "v11" - ] - }, - { - "in": [ - "v1", - "v11" - ], - "op": "abi_decode_t_uint256_fromMemory", - "out": [ - "v12" - ] - } + "in": [ + "0x04", + "v3" ], - "type": "FunctionCall" + "op": "lt", + "out": [ + "v4" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", - "out": [] - } + "in": [ + "v4" ], - "type": "FunctionCall" + "op": "iszero", + "out": [ + "v5" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "abi_encode_t_uint256_to_t_uint256_fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_uint256", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2", - "v1" - ], - "op": "mstore", - "out": [] - } + "in": [ + "0x00", + "0x00" ], - "type": "BuiltinCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "abi_encode_tuple__to__fromStack": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "v0" - ], - "op": "add", - "out": [ - "v2" - ] - } + "in": [ + "0x00" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + "op": "calldataload", + "out": [ + "v7" + ] + }, { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x20", - "v0" - ], - "op": "add", - "out": [ - "v4" - ] - }, - { - "in": [ - "0x00", - "v0" - ], - "op": "add", - "out": [ - "v5" - ] - }, - { - "in": [ - "v5", - "v1" - ], - "op": "abi_encode_t_uint256_to_t_uint256_fromStack", - "out": [] - } + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" ], - "type": "FunctionCall" + "op": "eq", + "out": [ + "v11" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "allocate_unbounded": { - "arguments": [], - "blocks": [ + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [] + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "cleanup_t_uint160": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0xffffffffffffffffffffffffffffffffffffffff", - "v0" - ], - "op": "and", - "out": [ - "v3" - ] - } + "in": [ + "0x03" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "cleanup_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ + "op": "not", + "out": [ + "v14" + ] + }, { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "convert_t_contract$_C_$19_to_t_address": { - "arguments": [ - "v0" - ], - "blocks": [ + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "convert_t_uint160_to_t_address", - "out": [ - "v2" - ] - } + "in": [ + "v14", + "v15" ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "convert_t_uint160_to_t_address": { - "arguments": [ - "v0" - ], - "blocks": [ + "op": "add", + "out": [ + "v16" + ] + }, { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "convert_t_uint160_to_t_uint160", - "out": [ - "v2" - ] - } + "in": [ + "0x00", + "v16" ], - "type": "FunctionCall" + "op": "slt", + "out": [ + "v17" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "convert_t_uint160_to_t_uint160": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_uint160", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2" - ], - "op": "identity", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3" - ], - "op": "cleanup_t_uint160", - "out": [ - "v4" - ] - } + "in": [ + "0x00", + "0x00" ], - "type": "FunctionCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "external_fun_f_37": { - "arguments": [], - "blocks": [ + { + "exit": { + "cond": "v28", + "targets": [ + "Block12", + "Block11" + ], + "type": "ConditionalJump" + }, + "id": "Block9", + "instructions": [ { - "exit": { - "cond": "v0", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "callvalue", - "out": [ - "v0" - ] - } + "builtinArgs": [ + "C_19" ], - "type": "BuiltinCall" + "in": [], + "op": "datasize", + "out": [ + "v18" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block2", - "instructions": [ - { - "in": [], - "op": "calldatasize", - "out": [ - "v1" - ] - }, - { - "in": [ - "v1", - "0x04" - ], - "op": "abi_decode_tuple_", - "out": [] - }, - { - "in": [], - "op": "fun_f_37", - "out": [ - "v3" - ] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v4" - ] - }, - { - "in": [ - "v3", - "v4" - ], - "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", - "out": [ - "v5" - ] - }, - { - "in": [ - "v4", - "v5" - ], - "op": "sub", - "out": [ - "v6" - ] - }, - { - "in": [ - "v6", - "v4" - ], - "op": "return", - "out": [] - } + "in": [ + "v18", + "v0" + ], + "op": "add", + "out": [ + "v24" + ] + }, + { + "in": [ + "v0", + "v24" ], - "type": "BuiltinCall" + "op": "lt", + "out": [ + "v25" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "out": [] - } + "in": [ + "0xffffffffffffffff", + "v24" ], - "type": "FunctionCall" + "op": "gt", + "out": [ + "v27" + ] + }, + { + "in": [ + "v25", + "v27" + ], + "op": "or", + "out": [ + "v28" + ] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "finalize_allocation": { - "arguments": [ - "v0", - "v1" + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "blocks": [ + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v42", + "targets": [ + "Block15", + "Block14" + ], + "type": "ConditionalJump" + }, + "id": "Block12", + "instructions": [ { - "exit": { - "cond": "v7", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v1" - ], - "op": "round_up_to_mul_of_32", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2", - "v0" - ], - "op": "add", - "out": [ - "v3" - ] - }, - { - "in": [ - "v0", - "v3" - ], - "op": "lt", - "out": [ - "v4" - ] - }, - { - "in": [ - "0xffffffffffffffff", - "v3" - ], - "op": "gt", - "out": [ - "v6" - ] - }, - { - "in": [ - "v4", - "v6" - ], - "op": "or", - "out": [ - "v7" - ] - } + "builtinArgs": [ + "C_19" ], - "type": "BuiltinCall" + "in": [], + "op": "dataoffset", + "out": [ + "v35" + ] }, { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [ - { - "in": [ - "v3", - "0x40" - ], - "op": "mstore", - "out": [] - } + "in": [ + "v18", + "v35", + "v0" ], - "type": "BuiltinCall" + "op": "datacopy", + "out": [] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "panic_error_0x41", - "out": [] - } + "in": [ + "v0", + "v24" ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "fun_f_37": { - "arguments": [], - "blocks": [ + "op": "sub", + "out": [ + "v40" + ] + }, { - "exit": { - "cond": "v8", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "zero_value_for_split_t_uint256", - "out": [ - "v1" - ] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v2" - ] - }, - { - "builtinArgs": [ - "C_19" - ], - "in": [], - "op": "datasize", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3", - "v2" - ], - "op": "add", - "out": [ - "v4" - ] - }, - { - "in": [ - "v2", - "v4" - ], - "op": "lt", - "out": [ - "v5" - ] - }, - { - "in": [ - "0xffffffffffffffff", - "v4" - ], - "op": "gt", - "out": [ - "v7" - ] - }, - { - "in": [ - "v5", - "v7" - ], - "op": "or", - "out": [ - "v8" - ] - } + "in": [ + "v40", + "v0", + "0x00" ], - "type": "BuiltinCall" + "op": "create", + "out": [ + "v41" + ] }, { - "exit": { - "cond": "v19", - "targets": [ - "Block5", - "Block4" - ], - "type": "ConditionalJump" - }, - "id": "Block2", - "instructions": [ - { - "builtinArgs": [ - "C_19" - ], - "in": [], - "op": "datasize", - "out": [ - "v9" - ] - }, - { - "builtinArgs": [ - "C_19" - ], - "in": [], - "op": "dataoffset", - "out": [ - "v10" - ] - }, - { - "in": [ - "v9", - "v10", - "v2" - ], - "op": "datacopy", - "out": [] - }, - { - "in": [ - "v4" - ], - "op": "abi_encode_tuple__to__fromStack", - "out": [ - "v16" - ] - }, - { - "in": [ - "v2", - "v16" - ], - "op": "sub", - "out": [ - "v17" - ] - }, - { - "in": [ - "v17", - "v2", - "0x00" - ], - "op": "create", - "out": [ - "v18" - ] - }, - { - "in": [ - "v18" - ], - "op": "iszero", - "out": [ - "v19" - ] - } + "in": [ + "v41" ], - "type": "BuiltinCall" + "op": "iszero", + "out": [ + "v42" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block11", + "instructions": [ + { + "in": [ + "0x4e487b71", + "0xe0" + ], + "op": "shl", + "out": [ + "v30" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "panic_error_0x41", - "out": [] - } + "in": [ + "v30", + "0x00" ], - "type": "FunctionCall" + "op": "mstore", + "out": [] }, { - "exit": { - "cond": "v33", - "targets": [ - "Block8", - "Block7" - ], - "type": "ConditionalJump" - }, - "id": "Block5", - "instructions": [ - { - "in": [ - "v18" - ], - "op": "convert_t_contract$_C_$19_to_t_address", - "out": [ - "v22" - ] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v24" - ] - }, - { - "in": [ - "0x26121ff0" - ], - "op": "shift_left_224", - "out": [ - "v25" - ] - }, - { - "in": [ - "v25", - "v24" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x04", - "v24" - ], - "op": "add", - "out": [ - "v27" - ] - }, - { - "in": [ - "v27" - ], - "op": "abi_encode_tuple__to__fromStack", - "out": [ - "v28" - ] - }, - { - "in": [ - "v24", - "v28" - ], - "op": "sub", - "out": [ - "v30" - ] - }, - { - "in": [], - "op": "gas", - "out": [ - "v31" - ] - }, - { - "in": [ - "0x20", - "v24", - "v30", - "v24", - "v22", - "v31" - ], - "op": "staticcall", - "out": [ - "v32" - ] - }, - { - "in": [ - "v32" - ], - "op": "iszero", - "out": [ - "v33" - ] - } + "in": [ + "0x41", + "0x04" ], - "type": "BuiltinCall" + "op": "mstore", + "out": [] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block4", - "instructions": [ - { - "in": [], - "op": "revert_forward_1", - "out": [] - } + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v60", + "targets": [ + "Block18", + "Block17" + ], + "type": "ConditionalJump" + }, + "id": "Block15", + "instructions": [ + { + "in": [ + "0x40" ], - "type": "FunctionCall" + "op": "mload", + "out": [ + "v46" + ] }, { - "exit": { - "cond": "v32", - "targets": [ - "Block11", - "Block10" - ], - "type": "ConditionalJump" - }, - "id": "Block8", - "instructions": [] + "in": [ + "0x026121ff", + "0xe4" + ], + "op": "shl", + "out": [ + "v49" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block7", - "instructions": [ - { - "in": [], - "op": "revert_forward_1", - "out": [] - } + "in": [ + "v49", + "v46" ], - "type": "FunctionCall" + "op": "mstore", + "out": [] }, { - "entries": [ - "Block8", - "Block13" + "in": [ + "0x01", + "0xa0" ], - "exit": { - "returnValues": [ - "v45" - ], - "type": "FunctionReturn" - }, - "id": "Block11", - "instructions": [ - { - "in": [ - "0x00", - "v44" - ], - "op": "PhiFunction", - "out": [ - "v45" - ] - } + "op": "shl", + "out": [ + "v53" ] }, { - "exit": { - "cond": "v37", - "targets": [ - "Block13", - "Block12" - ], - "type": "ConditionalJump" - }, - "id": "Block10", - "instructions": [ - { - "in": [], - "op": "returndatasize", - "out": [ - "v36" - ] - }, - { - "in": [ - "v36", - "0x20" - ], - "op": "gt", - "out": [ - "v37" - ] - } + "in": [ + "0x01", + "v53" ], - "type": "BuiltinCall" + "op": "sub", + "out": [ + "v54" + ] }, { - "entries": [ - "Block10", - "Block12" + "in": [ + "v54", + "v41" ], - "exit": { - "targets": [ - "Block11" - ], - "type": "Jump" - }, - "id": "Block13", - "instructions": [ - { - "in": [ - "0x20", - "v38" - ], - "op": "PhiFunction", - "out": [ - "v39" - ] - }, - { - "in": [ - "v39", - "v24" - ], - "op": "finalize_allocation", - "out": [] - }, - { - "in": [ - "v39", - "v24" - ], - "op": "add", - "out": [ - "v43" - ] - }, - { - "in": [ - "v43", - "v24" - ], - "op": "abi_decode_tuple_t_uint256_fromMemory", - "out": [ - "v44" - ] - } + "op": "and", + "out": [ + "v57" + ] + }, + { + "in": [], + "op": "gas", + "out": [ + "v58" + ] + }, + { + "in": [ + "0x20", + "v46", + "0x04", + "v46", + "v57", + "v58" + ], + "op": "staticcall", + "out": [ + "v59" + ] + }, + { + "in": [ + "v59" + ], + "op": "iszero", + "out": [ + "v60" + ] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block14", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v43" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v44" + ] + }, + { + "in": [ + "v44", + "0x00", + "v43" ], - "type": "FunctionCall" + "op": "returndatacopy", + "out": [] }, { - "exit": { - "targets": [ - "Block13" - ], - "type": "Jump" - }, - "id": "Block12", - "instructions": [ - { - "in": [], - "op": "returndatasize", - "out": [ - "v38" - ] - } + "in": [], + "op": "returndatasize", + "out": [ + "v45" + ] + }, + { + "in": [ + "v45", + "v43" ], - "type": "BuiltinCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "identity": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + { + "exit": { + "cond": "v59", + "targets": [ + "Block21", + "Block20" + ], + "type": "ConditionalJump" + }, + "id": "Block18", + "instructions": [] }, - "panic_error_0x41": { - "arguments": [], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block17", + "instructions": [ { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x4e487b7100000000000000000000000000000000000000000000000000000000", - "0x00" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x41", - "0x04" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x24", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x40" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_0cc013b6b3b6beabea4e3a74a6d380f0df81852ca99887912475e1f66b2a2c20": { - "arguments": [], - "blocks": [ + "op": "mload", + "out": [ + "v61" + ] + }, { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [], + "op": "returndatasize", + "out": [ + "v62" + ] + }, + { + "in": [ + "v62", + "0x00", + "v61" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { - "arguments": [], - "blocks": [ + "op": "returndatacopy", + "out": [] + }, { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [], + "op": "returndatasize", + "out": [ + "v63" + ] + }, + { + "in": [ + "v63", + "v61" ], - "type": "BuiltinCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db": { - "arguments": [], - "blocks": [ + { + "entries": [ + "Block18", + "Block28" + ], + "exit": { + "type": "Terminated" + }, + "id": "Block21", + "instructions": [ { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x00", + "v93" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ + "op": "PhiFunction", + "out": [ + "v95" + ] + }, { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x40" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { - "arguments": [], - "blocks": [ + "op": "mload", + "out": [ + "v94" + ] + }, { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "v95", + "v94" ], - "type": "BuiltinCall" + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v94" + ], + "op": "return", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "revert_forward_1": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v0" - ] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v1" - ] - }, - { - "in": [ - "v1", - "0x00", - "v0" - ], - "op": "returndatacopy", - "out": [] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3", - "v0" - ], - "op": "revert", - "out": [] - } + { + "exit": { + "cond": "v67", + "targets": [ + "Block23", + "Block22" + ], + "type": "ConditionalJump" + }, + "id": "Block20", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v66" + ] + }, + { + "in": [ + "v66", + "0x20" ], - "type": "BuiltinCall" + "op": "gt", + "out": [ + "v67" + ] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "round_up_to_mul_of_32": { - "arguments": [ - "v0" + { + "entries": [ + "Block20", + "Block22" ], - "blocks": [ + "exit": { + "cond": "v80", + "targets": [ + "Block25", + "Block24" + ], + "type": "ConditionalJump" + }, + "id": "Block23", + "instructions": [ { - "exit": { - "returnValues": [ - "v5" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x1f" - ], - "op": "not", - "out": [ - "v3" - ] - }, - { - "in": [ - "0x1f", - "v0" - ], - "op": "add", - "out": [ - "v4" - ] - }, - { - "in": [ - "v3", - "v4" - ], - "op": "and", - "out": [ - "v5" - ] - } + "in": [ + "0x20", + "v68" ], - "type": "BuiltinCall" + "op": "PhiFunction", + "out": [ + "v71" + ] + }, + { + "in": [ + "0x1f" + ], + "op": "not", + "out": [ + "v70" + ] + }, + { + "in": [ + "0x1f", + "v71" + ], + "op": "add", + "out": [ + "v72" + ] + }, + { + "in": [ + "v70", + "v72" + ], + "op": "and", + "out": [ + "v73" + ] + }, + { + "in": [ + "v73", + "v46" + ], + "op": "add", + "out": [ + "v77" + ] + }, + { + "in": [ + "v46", + "v77" + ], + "op": "lt", + "out": [ + "v78" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v77" + ], + "op": "gt", + "out": [ + "v79" + ] + }, + { + "in": [ + "v78", + "v79" + ], + "op": "or", + "out": [ + "v80" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "shift_left_224": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "targets": [ + "Block23" + ], + "type": "Jump" + }, + "id": "Block22", + "instructions": [ { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "0xe0" - ], - "op": "shl", - "out": [ - "v3" - ] - } - ], - "type": "BuiltinCall" + "in": [], + "op": "returndatasize", + "out": [ + "v68" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "shift_right_224_unsigned": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "cond": "v90", + "targets": [ + "Block28", + "Block27" + ], + "type": "ConditionalJump" + }, + "id": "Block25", + "instructions": [ { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "0xe0" - ], - "op": "shr", - "out": [ - "v3" - ] - } + "in": [ + "v77", + "0x40" ], - "type": "BuiltinCall" + "op": "mstore", + "out": [] + }, + { + "in": [ + "v71", + "v46" + ], + "op": "add", + "out": [ + "v88" + ] + }, + { + "in": [ + "v46", + "v88" + ], + "op": "sub", + "out": [ + "v89" + ] + }, + { + "in": [ + "0x20", + "v89" + ], + "op": "slt", + "out": [ + "v90" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "validator_revert_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block24", + "instructions": [ { - "exit": { - "cond": "v3", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_uint256", - "out": [ - "v1" - ] - }, - { - "in": [ - "v1", - "v0" - ], - "op": "eq", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2" - ], - "op": "iszero", - "out": [ - "v3" - ] - } + "in": [ + "0x4e487b71", + "0xe0" ], - "type": "BuiltinCall" + "op": "shl", + "out": [ + "v81" + ] }, { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [] + "in": [ + "v81", + "0x00" + ], + "op": "mstore", + "out": [] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x41", + "0x04" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block21" + ], + "type": "Jump" + }, + "id": "Block28", + "instructions": [ + { + "in": [ + "v46" ], - "type": "BuiltinCall" + "op": "mload", + "out": [ + "v93" + ] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "zero_value_for_split_t_uint256": { - "arguments": [], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block27", + "instructions": [ { - "exit": { - "returnValues": [ - "0x00" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" } - } + ], + "functions": {} }, "subObjects": { "C_19": { @@ -2951,7 +1453,7 @@ Yul Control Flow Graph: "instructions": [ { "builtinArgs": [ - "128" + "0x80" ], "in": [], "op": "memoryguard", @@ -2983,18 +1485,6 @@ Yul Control Flow Graph: }, "id": "Block2", "instructions": [ - { - "in": [], - "op": "constructor_C_19", - "out": [] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v3" - ] - }, { "builtinArgs": [ "C_19_deployed" @@ -3019,25 +1509,15 @@ Yul Control Flow Graph: "in": [ "v4", "v5", - "v3" + "v0" ], "op": "codecopy", "out": [] }, - { - "builtinArgs": [ - "C_19_deployed" - ], - "in": [], - "op": "datasize", - "out": [ - "v6" - ] - }, { "in": [ - "v6", - "v3" + "v4", + "v0" ], "op": "return", "out": [] @@ -3052,109 +1532,18 @@ Yul Control Flow Graph: "id": "Block1", "instructions": [ { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", + "in": [ + "0x00", + "0x00" + ], + "op": "revert", "out": [] } ], - "type": "FunctionCall" + "type": "BuiltinCall" } ], - "functions": { - "allocate_unbounded": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "constructor_C_19": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "constructor_I_7", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "constructor_I_7": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ - { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - } - } + "functions": {} }, "subObjects": { "C_19_deployed": { @@ -3172,7 +1561,7 @@ Yul Control Flow Graph: "instructions": [ { "builtinArgs": [ - "128" + "0x80" ], "in": [], "op": "memoryguard", @@ -3224,19 +1613,22 @@ Yul Control Flow Graph: "id": "Block2", "instructions": [ { - "in": [], - "op": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", + "in": [ + "0x00", + "0x00" + ], + "op": "revert", "out": [] } ], - "type": "FunctionCall" + "type": "BuiltinCall" }, { "exit": { - "cond": "v9", + "cond": "v11", "targets": [ - "Block5", - "Block4" + "Block4", + "Block3" ], "type": "ConditionalJump" }, @@ -3253,21 +1645,22 @@ Yul Control Flow Graph: }, { "in": [ - "v7" + "v7", + "0xe0" ], - "op": "shift_right_224_unsigned", + "op": "shr", "out": [ - "v8" + "v9" ] }, { "in": [ - "0x26121ff0", - "v8" + "v9", + "0x26121ff0" ], "op": "eq", "out": [ - "v9" + "v11" ] } ], @@ -3276,604 +1669,145 @@ Yul Control Flow Graph: { "exit": { "targets": [ - "Block3" + "Block2" ], "type": "Jump" }, - "id": "Block5", + "id": "Block4", "instructions": [] }, { "exit": { - "type": "Terminated" + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" }, - "id": "Block4", + "id": "Block3", "instructions": [ { "in": [], - "op": "external_fun_f_18", - "out": [] + "op": "callvalue", + "out": [ + "v12" + ] } ], - "type": "FunctionCall" + "type": "BuiltinCall" }, { "exit": { + "cond": "v17", "targets": [ - "Block2" + "Block9", + "Block8" ], - "type": "Jump" + "type": "ConditionalJump" }, - "id": "Block3", - "instructions": [] - } - ], - "functions": { - "abi_decode_tuple_": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ + "id": "Block6", + "instructions": [ { - "exit": { - "cond": "v4", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "v1" - ], - "op": "sub", - "out": [ - "v3" - ] - }, - { - "in": [ - "0x00", - "v3" - ], - "op": "slt", - "out": [ - "v4" - ] - } + "in": [ + "0x03" ], - "type": "BuiltinCall" - }, - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block2", - "instructions": [] + "op": "not", + "out": [ + "v14" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "abi_encode_t_uint256_to_t_uint256_fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ - { - "exit": { - "returnValues": [], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_uint256", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2", - "v1" - ], - "op": "mstore", - "out": [] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { - "arguments": [ - "v0", - "v1" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x20", - "v0" - ], - "op": "add", - "out": [ - "v4" - ] - }, - { - "in": [ - "0x00", - "v0" - ], - "op": "add", - "out": [ - "v5" - ] - }, - { - "in": [ - "v5", - "v1" - ], - "op": "abi_encode_t_uint256_to_t_uint256_fromStack", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "allocate_unbounded": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v2" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v2" - ] - } - ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "cleanup_t_rational_42_by_1": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "cleanup_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "convert_t_rational_42_by_1_to_t_uint256": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v4" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0" - ], - "op": "cleanup_t_rational_42_by_1", - "out": [ - "v2" - ] - }, - { - "in": [ - "v2" - ], - "op": "identity", - "out": [ - "v3" - ] - }, - { - "in": [ - "v3" - ], - "op": "cleanup_t_uint256", - "out": [ - "v4" - ] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "external_fun_f_18": { - "arguments": [], - "blocks": [ - { - "exit": { - "cond": "v0", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "callvalue", - "out": [ - "v0" - ] - } - ], - "type": "BuiltinCall" + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block2", - "instructions": [ - { - "in": [], - "op": "calldatasize", - "out": [ - "v1" - ] - }, - { - "in": [ - "v1", - "0x04" - ], - "op": "abi_decode_tuple_", - "out": [] - }, - { - "in": [], - "op": "fun_f_18", - "out": [ - "v3" - ] - }, - { - "in": [], - "op": "allocate_unbounded", - "out": [ - "v4" - ] - }, - { - "in": [ - "v3", - "v4" - ], - "op": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack", - "out": [ - "v5" - ] - }, - { - "in": [ - "v4", - "v5" - ], - "op": "sub", - "out": [ - "v6" - ] - }, - { - "in": [ - "v6", - "v4" - ], - "op": "return", - "out": [] - } + "in": [ + "v14", + "v15" ], - "type": "BuiltinCall" + "op": "add", + "out": [ + "v16" + ] }, { - "exit": { - "type": "Terminated" - }, - "id": "Block1", - "instructions": [ - { - "in": [], - "op": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "out": [] - } - ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "fun_f_18": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [], - "op": "zero_value_for_split_t_uint256", - "out": [ - "v1" - ] - }, - { - "in": [ - "0x2a" - ], - "op": "convert_t_rational_42_by_1_to_t_uint256", - "out": [ - "v3" - ] - } + "in": [ + "0x00", + "v16" ], - "type": "FunctionCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "identity": { - "arguments": [ - "v0" - ], - "blocks": [ - { - "exit": { - "returnValues": [ - "v0" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] + "op": "slt", + "out": [ + "v17" + ] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" }, - "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74": { - "arguments": [], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x00", + "0x00" ], - "type": "BuiltinCall" + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb": { - "arguments": [], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x2a", + "v0" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" - }, - "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b": { - "arguments": [], - "blocks": [ + "op": "mstore", + "out": [] + }, { - "exit": { - "type": "Terminated" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } + "in": [ + "0x20", + "v0" ], - "type": "BuiltinCall" + "op": "return", + "out": [] } ], - "entry": "Block0", - "numReturns": 0, - "type": "Function" + "type": "BuiltinCall" }, - "shift_right_224_unsigned": { - "arguments": [ - "v0" - ], - "blocks": [ + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ { - "exit": { - "returnValues": [ - "v3" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [ - { - "in": [ - "v0", - "0xe0" - ], - "op": "shr", - "out": [ - "v3" - ] - } + "in": [ + "0x00", + "0x00" ], - "type": "BuiltinCall" - } - ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" - }, - "zero_value_for_split_t_uint256": { - "arguments": [], - "blocks": [ - { - "exit": { - "returnValues": [ - "0x00" - ], - "type": "FunctionReturn" - }, - "id": "Block0", - "instructions": [] + "op": "revert", + "out": [] } ], - "entry": "Block0", - "numReturns": 1, - "type": "Function" + "type": "BuiltinCall" } - } + ], + "functions": {} }, "subObjects": {}, "type": "subObject" From 8da621c41d67d8ee5a74157f28efa670a7370746 Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 4 Dec 2024 12:26:00 +0700 Subject: [PATCH 0513/1340] Export liveness information of Yul SSA CFG (#15608) Export SSA CFG liveness data --- libyul/YulControlFlowGraphExporter.cpp | 33 +- libyul/YulControlFlowGraphExporter.h | 9 +- libyul/YulStack.cpp | 3 +- .../standard_yul_cfg_json_export/output.json | 314 +++++++++++++++++- .../strict_asm_yul_cfg_json_export/output | 70 +++- test/cmdlineTests/yul_cfg_json_export/output | 314 +++++++++++++++++- 6 files changed, 721 insertions(+), 22 deletions(-) diff --git a/libyul/YulControlFlowGraphExporter.cpp b/libyul/YulControlFlowGraphExporter.cpp index 17737533f..65c0805f9 100644 --- a/libyul/YulControlFlowGraphExporter.cpp +++ b/libyul/YulControlFlowGraphExporter.cpp @@ -31,7 +31,7 @@ using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; -YulControlFlowGraphExporter::YulControlFlowGraphExporter(ControlFlow const& _controlFlow): m_controlFlow(_controlFlow) +YulControlFlowGraphExporter::YulControlFlowGraphExporter(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness): m_controlFlow(_controlFlow), m_liveness(_liveness) { } @@ -58,18 +58,22 @@ std::string YulControlFlowGraphExporter::varToString(SSACFG const& _cfg, SSACFG: Json YulControlFlowGraphExporter::run() { + if (m_liveness) + yulAssert(&m_liveness->controlFlow.get() == &m_controlFlow); + Json yulObjectJson = Json::object(); - yulObjectJson["blocks"] = exportBlock(*m_controlFlow.mainGraph, SSACFG::BlockId{0}); + yulObjectJson["blocks"] = exportBlock(*m_controlFlow.mainGraph, SSACFG::BlockId{0}, m_liveness ? m_liveness->mainLiveness.get() : nullptr); Json functionsJson = Json::object(); + size_t index = 0; for (auto const& [function, functionGraph]: m_controlFlow.functionGraphMapping) - functionsJson[function->name.str()] = exportFunction(*functionGraph); + functionsJson[function->name.str()] = exportFunction(*functionGraph, m_liveness ? m_liveness->functionLiveness[index++].get() : nullptr); yulObjectJson["functions"] = functionsJson; return yulObjectJson; } -Json YulControlFlowGraphExporter::exportFunction(SSACFG const& _cfg) +Json YulControlFlowGraphExporter::exportFunction(SSACFG const& _cfg, SSACFGLiveness const* _liveness) { Json functionJson = Json::object(); functionJson["type"] = "Function"; @@ -77,18 +81,18 @@ Json YulControlFlowGraphExporter::exportFunction(SSACFG const& _cfg) static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", std::get<1>(_arg).value); }; functionJson["arguments"] = _cfg.arguments | ranges::views::transform(argsTransform) | ranges::to; functionJson["numReturns"] = _cfg.returns.size(); - functionJson["blocks"] = exportBlock(_cfg, _cfg.entry); + functionJson["blocks"] = exportBlock(_cfg, _cfg.entry, _liveness); return functionJson; } -Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId) +Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, SSACFGLiveness const* _liveness) { Json blocksJson = Json::array(); util::BreadthFirstSearch bfs{{{_entryId}}}; bfs.run([&](SSACFG::BlockId _blockId, auto _addChild) { auto const& block = _cfg.block(_blockId); // Convert current block to JSON - Json blockJson = toJson(_cfg, _blockId); + Json blockJson = toJson(_cfg, _blockId, _liveness); Json exitBlockJson = Json::object(); std::visit(util::GenericVisitor{ @@ -128,12 +132,25 @@ Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockI return blocksJson; } -Json YulControlFlowGraphExporter::toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId) +Json YulControlFlowGraphExporter::toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness) { + auto const valueToString = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; + Json blockJson = Json::object(); auto const& block = _cfg.block(_blockId); blockJson["id"] = "Block" + std::to_string(_blockId.value); + if (_liveness) + { + Json livenessJson = Json::object(); + livenessJson["in"] = _liveness->liveIn(_blockId) + | ranges::views::transform(valueToString) + | ranges::to(); + livenessJson["out"] = _liveness->liveOut(_blockId) + | ranges::views::transform(valueToString) + | ranges::to(); + blockJson["liveness"] = livenessJson; + } blockJson["instructions"] = Json::array(); if (!block.phis.empty()) { diff --git a/libyul/YulControlFlowGraphExporter.h b/libyul/YulControlFlowGraphExporter.h index 37520e194..91f9d040e 100644 --- a/libyul/YulControlFlowGraphExporter.h +++ b/libyul/YulControlFlowGraphExporter.h @@ -28,15 +28,16 @@ using namespace yul; class YulControlFlowGraphExporter { public: - YulControlFlowGraphExporter(ControlFlow const& _controlFlow); + YulControlFlowGraphExporter(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness=nullptr); Json run(); - Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _blockId); - Json exportFunction(SSACFG const& _cfg); + Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness); + Json exportFunction(SSACFG const& _cfg, SSACFGLiveness const* _liveness); std::string varToString(SSACFG const& _cfg, SSACFG::ValueId _var); private: ControlFlow const& m_controlFlow; - Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId); + ControlFlowLiveness const* m_liveness; + Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness); Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation); Json toJson(SSACFG const& _cfg, std::vector const& _values); }; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index a7bf415a5..22c1fcb7d 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -389,7 +389,8 @@ Json YulStack::cfgJson() const languageToDialect(m_language, m_evmVersion, m_eofVersion), _object.code()->root() ); - YulControlFlowGraphExporter exporter(*controlFlow); + std::unique_ptr liveness = std::make_unique(*controlFlow); + YulControlFlowGraphExporter exporter(*controlFlow, liveness.get()); return exporter.run(); }; diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index c224164c5..fc47f4f7b 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -42,6 +42,12 @@ ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -88,6 +94,12 @@ "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -105,6 +117,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], @@ -169,6 +185,12 @@ ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -186,6 +208,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -229,6 +255,14 @@ ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -239,7 +273,11 @@ "type": "Jump" }, "id": "Block4", - "instructions": [] + "instructions": [], + "liveness": { + "in": [], + "out": [] + } }, { "exit": { @@ -260,6 +298,14 @@ ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -310,6 +356,14 @@ ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -327,6 +381,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -352,6 +410,12 @@ "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -369,6 +433,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], @@ -421,6 +489,12 @@ ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -467,6 +541,12 @@ "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -484,6 +564,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], @@ -548,6 +632,12 @@ ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -565,6 +655,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -608,6 +702,14 @@ ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -618,7 +720,11 @@ "type": "Jump" }, "id": "Block4", - "instructions": [] + "instructions": [], + "liveness": { + "in": [], + "out": [] + } }, { "exit": { @@ -639,6 +745,14 @@ ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -689,6 +803,14 @@ ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -706,6 +828,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -770,6 +896,16 @@ ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0", + "v18", + "v24" + ] + }, "type": "BuiltinCall" }, { @@ -787,6 +923,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -850,6 +990,16 @@ ] } ], + "liveness": { + "in": [ + "v0", + "v18", + "v24" + ], + "out": [ + "v41" + ] + }, "type": "BuiltinCall" }, { @@ -893,6 +1043,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -994,6 +1148,14 @@ ] } ], + "liveness": { + "in": [ + "v41" + ], + "out": [ + "v46" + ] + }, "type": "BuiltinCall" }, { @@ -1043,6 +1205,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1055,7 +1221,15 @@ "type": "ConditionalJump" }, "id": "Block18", - "instructions": [] + "instructions": [], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v46" + ] + } }, { "exit": { @@ -1104,6 +1278,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1152,6 +1330,12 @@ "out": [] } ], + "liveness": { + "in": [ + "v95" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1183,6 +1367,14 @@ ] } ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v46" + ] + }, "type": "BuiltinCall" }, { @@ -1280,6 +1472,17 @@ ] } ], + "liveness": { + "in": [ + "v46", + "v71" + ], + "out": [ + "v46", + "v71", + "v77" + ] + }, "type": "BuiltinCall" }, { @@ -1299,6 +1502,15 @@ ] } ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v46", + "v68" + ] + }, "type": "BuiltinCall" }, { @@ -1351,6 +1563,16 @@ ] } ], + "liveness": { + "in": [ + "v46", + "v71", + "v77" + ], + "out": [ + "v46" + ] + }, "type": "BuiltinCall" }, { @@ -1394,6 +1616,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1415,6 +1641,14 @@ ] } ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v93" + ] + }, "type": "BuiltinCall" }, { @@ -1432,6 +1666,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], @@ -1477,6 +1715,12 @@ ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -1523,6 +1767,12 @@ "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1540,6 +1790,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], @@ -1604,6 +1858,12 @@ ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -1621,6 +1881,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1664,6 +1928,14 @@ ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -1674,7 +1946,11 @@ "type": "Jump" }, "id": "Block4", - "instructions": [] + "instructions": [], + "liveness": { + "in": [], + "out": [] + } }, { "exit": { @@ -1695,6 +1971,14 @@ ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -1745,6 +2029,14 @@ ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -1762,6 +2054,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1787,6 +2083,12 @@ "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1804,6 +2106,10 @@ "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output index 18fa4288c..ac154fc16 100644 --- a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -42,6 +42,12 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -88,6 +94,12 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -105,6 +117,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], @@ -169,6 +185,12 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -186,6 +208,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -229,6 +255,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -239,7 +273,11 @@ Yul Control Flow Graph: "type": "Jump" }, "id": "Block4", - "instructions": [] + "instructions": [], + "liveness": { + "in": [], + "out": [] + } }, { "exit": { @@ -260,6 +298,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -310,6 +356,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -327,6 +381,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -352,6 +410,12 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -369,6 +433,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index 8339d02c7..6848d7db9 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -41,6 +41,12 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -87,6 +93,12 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -104,6 +116,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], @@ -168,6 +184,12 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -185,6 +207,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -228,6 +254,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -238,7 +272,11 @@ Yul Control Flow Graph: "type": "Jump" }, "id": "Block4", - "instructions": [] + "instructions": [], + "liveness": { + "in": [], + "out": [] + } }, { "exit": { @@ -259,6 +297,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -309,6 +355,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -326,6 +380,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -351,6 +409,12 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -368,6 +432,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], @@ -421,6 +489,12 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -467,6 +541,12 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -484,6 +564,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], @@ -548,6 +632,12 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -565,6 +655,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -608,6 +702,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -618,7 +720,11 @@ Yul Control Flow Graph: "type": "Jump" }, "id": "Block4", - "instructions": [] + "instructions": [], + "liveness": { + "in": [], + "out": [] + } }, { "exit": { @@ -639,6 +745,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -689,6 +803,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -706,6 +828,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -770,6 +896,16 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0", + "v18", + "v24" + ] + }, "type": "BuiltinCall" }, { @@ -787,6 +923,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -850,6 +990,16 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0", + "v18", + "v24" + ], + "out": [ + "v41" + ] + }, "type": "BuiltinCall" }, { @@ -893,6 +1043,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -994,6 +1148,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v41" + ], + "out": [ + "v46" + ] + }, "type": "BuiltinCall" }, { @@ -1043,6 +1205,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1055,7 +1221,15 @@ Yul Control Flow Graph: "type": "ConditionalJump" }, "id": "Block18", - "instructions": [] + "instructions": [], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v46" + ] + } }, { "exit": { @@ -1104,6 +1278,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1152,6 +1330,12 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [ + "v95" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1183,6 +1367,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v46" + ] + }, "type": "BuiltinCall" }, { @@ -1280,6 +1472,17 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v46", + "v71" + ], + "out": [ + "v46", + "v71", + "v77" + ] + }, "type": "BuiltinCall" }, { @@ -1299,6 +1502,15 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v46", + "v68" + ] + }, "type": "BuiltinCall" }, { @@ -1351,6 +1563,16 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v46", + "v71", + "v77" + ], + "out": [ + "v46" + ] + }, "type": "BuiltinCall" }, { @@ -1394,6 +1616,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1415,6 +1641,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v46" + ], + "out": [ + "v93" + ] + }, "type": "BuiltinCall" }, { @@ -1432,6 +1666,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], @@ -1477,6 +1715,12 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -1523,6 +1767,12 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1540,6 +1790,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], @@ -1604,6 +1858,12 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -1621,6 +1881,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1664,6 +1928,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -1674,7 +1946,11 @@ Yul Control Flow Graph: "type": "Jump" }, "id": "Block4", - "instructions": [] + "instructions": [], + "liveness": { + "in": [], + "out": [] + } }, { "exit": { @@ -1695,6 +1971,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -1745,6 +2029,14 @@ Yul Control Flow Graph: ] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, "type": "BuiltinCall" }, { @@ -1762,6 +2054,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1787,6 +2083,12 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, "type": "BuiltinCall" }, { @@ -1804,6 +2106,10 @@ Yul Control Flow Graph: "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, "type": "BuiltinCall" } ], From ca54a7695da56b973dcf7198393a44fe4712a0c2 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:39:29 +0200 Subject: [PATCH 0514/1340] Yul: Add utilities to resolve function name strings and builtin functions from an AST FunctionName --- libyul/Utilities.cpp | 32 ++++++++++++++++++++++++++++++++ libyul/Utilities.h | 10 ++++++++++ 2 files changed, 42 insertions(+) diff --git a/libyul/Utilities.cpp b/libyul/Utilities.cpp index 4bbfb4243..dd32d6a60 100644 --- a/libyul/Utilities.cpp +++ b/libyul/Utilities.cpp @@ -21,11 +21,15 @@ #include +#include + #include +#include #include #include #include +#include #include @@ -237,3 +241,31 @@ bool SwitchCaseCompareByLiteralValue::operator()(Case const* _lhs, Case const* _ yulAssert(_lhs && _rhs, ""); return Less{}(_lhs->value.get(), _rhs->value.get()); } + +std::string_view yul::resolveFunctionName(FunctionName const& _functionName, Dialect const& _dialect) +{ + GenericVisitor visitor{ + [&](Identifier const& _identifier) -> std::string const& { return _identifier.name.str(); }, + [&](BuiltinName const& _builtin) -> std::string const& { return _dialect.builtin(_builtin.handle).name; } + }; + return std::visit(visitor, _functionName); +} + +BuiltinFunction const* yul::resolveBuiltinFunction(FunctionName const& _functionName, Dialect const& _dialect) +{ + GenericVisitor visitor{ + [&](Identifier const&) -> BuiltinFunction const* { return nullptr; }, + [&](BuiltinName const& _builtin) -> BuiltinFunction const* { return &_dialect.builtin(_builtin.handle); } + }; + return std::visit(visitor, _functionName); +} + +BuiltinFunctionForEVM const* yul::resolveBuiltinFunctionForEVM(FunctionName const& _functionName, EVMDialect const& _dialect) +{ + GenericVisitor visitor{ + [&](Identifier const&) -> BuiltinFunctionForEVM const* { return nullptr; }, + [&](BuiltinName const& _builtin) -> BuiltinFunctionForEVM const* { return &_dialect.builtin(_builtin.handle); } + }; + return std::visit(visitor, _functionName); +} + diff --git a/libyul/Utilities.h b/libyul/Utilities.h index 434c5e9c5..2341ee62a 100644 --- a/libyul/Utilities.h +++ b/libyul/Utilities.h @@ -30,6 +30,11 @@ namespace solidity::yul { +struct Dialect; +class EVMDialect; +struct BuiltinFunction; +struct BuiltinFunctionForEVM; + std::string reindent(std::string const& _code); LiteralValue valueOfNumberLiteral(std::string_view _literal); @@ -83,4 +88,9 @@ struct SwitchCaseCompareByLiteralValue bool operator()(Case const* _lhsCase, Case const* _rhsCase) const; }; +std::string_view resolveFunctionName(FunctionName const& _functionName, Dialect const& _dialect); + +BuiltinFunction const* resolveBuiltinFunction(FunctionName const& _functionName, Dialect const& _dialect); +BuiltinFunctionForEVM const* resolveBuiltinFunctionForEVM(FunctionName const& _functionName, EVMDialect const& _dialect); + } From 144a3a9a15335282f35ede74c563f1a182f1dcdc Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:10:10 +0200 Subject: [PATCH 0515/1340] Yul EVM dialect: Add auxiliary builtin handles --- libyul/backends/evm/EVMDialect.cpp | 9 +++++++++ libyul/backends/evm/EVMDialect.h | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 4d160b030..161f92336 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -475,6 +475,15 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, std::optional m_storageStoreFunction = findBuiltin("sstore"); m_storageLoadFunction = findBuiltin("sload"); m_hashFunction = findBuiltin("keccak256"); + + m_discardFunction = findBuiltin("pop"); + m_equalityFunction = findBuiltin("eq"); + m_booleanNegationFunction = findBuiltin("iszero"); + m_memoryStoreFunction = findBuiltin("mstore"); + m_memoryLoadFunction = findBuiltin("mload"); + m_storageStoreFunction = findBuiltin("sstore"); + m_storageLoadFunction = findBuiltin("sload"); + m_hashFunction = findBuiltin("keccak256"); } std::optional EVMDialect::findBuiltin(std::string_view _name) const diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 58944bdc7..5d5ea90a9 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -68,6 +68,18 @@ struct BuiltinFunctionForEVM: public BuiltinFunction class EVMDialect: public Dialect { public: + /// Handles to (depending on dialect, potentially existing) builtins, which are not accessible via the + /// `...FunctionHandle` functions of `Dialect` and of which it is statically known, that they are needed in, + /// e.g., certain optimization steps. + struct AuxiliaryBuiltinHandles + { + std::optional add; + std::optional exp; + std::optional mul; + std::optional not_; + std::optional shl; + std::optional sub; + }; /// Constructor, should only be used internally. Use the factory functions below. EVMDialect(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess); @@ -85,6 +97,7 @@ class EVMDialect: public Dialect std::optional storageStoreFunctionHandle() const override { return m_storageStoreFunction; } std::optional storageLoadFunctionHandle() const override { return m_storageLoadFunction; } std::optional hashFunctionHandle() const override { return m_hashFunction; } + AuxiliaryBuiltinHandles const& auxiliaryBuiltinHandles() const { return m_auxiliaryBuiltinHandles; } static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _evmVersion, std::optional _eofVersion); static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _evmVersion, std::optional _eofVersion); @@ -123,6 +136,7 @@ class EVMDialect: public Dialect std::optional m_storageStoreFunction; std::optional m_storageLoadFunction; std::optional m_hashFunction; + AuxiliaryBuiltinHandles m_auxiliaryBuiltinHandles; }; } From 7c3ed2b65f88d972014816884ccfa4ba9f4bac04 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 5 Dec 2024 19:24:35 +0100 Subject: [PATCH 0516/1340] Remove request about deleting issue template notes These notes are already commented out so there is no reason to request deleting it. --- .github/ISSUE_TEMPLATE/bug_report.md | 2 -- .github/ISSUE_TEMPLATE/feature_request.md | 2 -- 2 files changed, 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 30c09039e..ef411e08a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -16,8 +16,6 @@ assignees: '' - [Stack Overflow](https://ethereum.stackexchange.com/) - Ensure the issue isn't already reported. - The issue should be reproducible with the latest solidity version; however, this isn't a hard requirement and being reproducible with an older version is sufficient. - -*Delete the above section and the instructions in the sections below before submitting* --> ## Description diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 7ec729b1c..328ff76e2 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -18,8 +18,6 @@ assignees: '' - Ensure the issue isn't already reported (check `feature` and `language design` labels). - If you feel uncertain about your feature request, perhaps it's better to open a language design or feedback forum thread via the issue selector, or by going to the forum directly. - [Solidity forum](https://forum.soliditylang.org/) - -*Delete the above section and the instructions in the sections below before submitting* --> ## Abstract From 4edb59d322daabecb6e1b07214ff0c2bb879eacb Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 6 Dec 2024 14:51:32 +0100 Subject: [PATCH 0517/1340] eof: Implement stack height calculation --- libevmasm/Assembly.cpp | 91 ++++++++++++++++++- .../strict_asm_eof_container_prague/output | 2 +- .../strict_asm_eof_dataloadn_prague/output | 2 +- .../objectCompiler/eof/256_subcontainers.yul | 4 +- .../eof/creation_with_immutables.yul | 4 +- test/libyul/objectCompiler/eof/dataloadn.yul | 4 +- test/libyul/objectCompiler/eof/functions.yul | 4 +- .../eof/prune_unreferenced_container.yul | 4 +- test/libyul/objectCompiler/eof/rjumps.yul | 4 +- 9 files changed, 103 insertions(+), 16 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 29b8c8a40..e5c62958f 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -46,6 +46,7 @@ #include #include #include +#include using namespace solidity; using namespace solidity::evmasm; @@ -971,6 +972,93 @@ void appendBigEndianUint16(bytes& _dest, ValueT _value) assertThrow(_value <= 0xFFFF, AssemblyException, ""); appendBigEndian(_dest, 2, static_cast(_value)); } + +// Calculates maximum stack height for given code section. According to EIP5450 https://eips.ethereum.org/EIPS/eip-5450 +uint16_t calculateMaxStackHeight(Assembly::CodeSection const& _section) +{ + static auto constexpr UNVISITED = std::numeric_limits::max(); + + AssemblyItems const& items = _section.items; + solAssert(!items.empty()); + uint16_t overallMaxHeight = _section.inputs; + std::stack worklist; + std::vector maxStackHeights(items.size(), UNVISITED); + + // Init first item stack height to number of inputs to the code section + // maxStackHeights stores stack height for an item before the item execution + maxStackHeights[0] = _section.inputs; + // Push first item index to the worklist + worklist.push(0u); + while (!worklist.empty()) + { + size_t idx = worklist.top(); + worklist.pop(); + AssemblyItem const& item = items[idx]; + size_t stackHeightChange = item.deposit(); + size_t currentMaxHeight = maxStackHeights[idx]; + solAssert(currentMaxHeight != UNVISITED); + + std::vector successors; + + // Add next instruction to successors for non-control-flow-changing instructions + if ( + !(item.hasInstruction() && SemanticInformation::terminatesControlFlow(item.instruction())) && + item.type() != RelativeJump && + item.type() != RetF && + item.type() != JumpF + ) + { + solAssert(idx < items.size() - 1, "No terminating instruction."); + successors.emplace_back(idx + 1); + } + + // Add jumps destinations to successors + // TODO: Remember to add RJUMPV when it is supported. + if (item.type() == RelativeJump || item.type() == ConditionalRelativeJump) + { + auto const tagIt = std::find(items.begin(), items.end(), item.tag()); + solAssert(tagIt != items.end(), "Tag not found."); + successors.emplace_back(static_cast(std::distance(items.begin(), tagIt))); + // If backward jump the successor must be already visited. + solAssert(idx <= successors.back() || maxStackHeights[successors.back()] != UNVISITED); + } + + solRequire( + currentMaxHeight + stackHeightChange <= std::numeric_limits::max(), + AssemblyException, + "Stack overflow in EOF function." + ); + overallMaxHeight = std::max(overallMaxHeight, static_cast(currentMaxHeight + stackHeightChange)); + currentMaxHeight += stackHeightChange; + + // Set stack height for all instruction successors + for (size_t successor: successors) + { + solAssert(successor < maxStackHeights.size()); + // Set stack height for newly visited + if (maxStackHeights[successor] == UNVISITED) + { + maxStackHeights[successor] = currentMaxHeight; + worklist.push(successor); + } + else + { + solAssert(successor < maxStackHeights.size()); + // For backward jump successor stack height must be equal + if (successor < idx) + solAssert(maxStackHeights[successor] == currentMaxHeight, "Stack height mismatch."); + + // If successor stack height is smaller update it and recalculate + if (currentMaxHeight > maxStackHeights[successor]) + { + maxStackHeights[successor] = currentMaxHeight; + worklist.push(successor); + } + } + } + } + return overallMaxHeight; +} } std::tuple, size_t> Assembly::createEOFHeader(std::set const& _referencedSubIds) const @@ -1015,8 +1103,7 @@ std::tuple, size_t> Assembly::createEOFHeader(std::se { retBytecode.push_back(codeSection.inputs); retBytecode.push_back(codeSection.outputs); - // TODO: Add stack height calculation - appendBigEndianUint16(retBytecode, 0xFFFFu); + appendBigEndianUint16(retBytecode, calculateMaxStackHeight(codeSection)); } return {retBytecode, codeSectionSizePositions, dataSectionSizePosition}; diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/output b/test/cmdlineTests/strict_asm_eof_container_prague/output index 26d37caf4..5d134f277 100644 --- a/test/cmdlineTests/strict_asm_eof_container_prague/output +++ b/test/cmdlineTests/strict_asm_eof_container_prague/output @@ -48,7 +48,7 @@ object "object" { Binary representation: -ef0001010004020001001503000200370037040000000080ffff5f808080ec005f525f808080ec0160205260405ff3ef00010100040200010004030001001b040000000080ffff5f80ee00ef00010100040200010008040000000080ffff60015f5260205ffdef00010100040200010004030001001b040000000080ffff5f80ee00ef00010100040200010008040000000080ffff60205f5260205ffd +ef000101000402000100150300020037003704000000008000045f808080ec005f525f808080ec0160205260405ff3ef00010100040200010004030001001b04000000008000025f80ee00ef00010100040200010008040000000080000260015f5260205ffdef00010100040200010004030001001b04000000008000025f80ee00ef00010100040200010008040000000080000260205f5260205ffd Text representation: 0x00 diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output b/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output index 1c06caa5e..5d2115f95 100644 --- a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output @@ -14,7 +14,7 @@ object "a" { Binary representation: -ef0001010004020001000904002d000080ffffd1000d5f5260205ff348656c6c6f2c20576f726c6421 +ef0001010004020001000904002d0000800002d1000d5f5260205ff348656c6c6f2c20576f726c6421 Text representation: auxdataloadn{0} diff --git a/test/libyul/objectCompiler/eof/256_subcontainers.yul b/test/libyul/objectCompiler/eof/256_subcontainers.yul index 46df86355..fac0f7b5d 100644 --- a/test/libyul/objectCompiler/eof/256_subcontainers.yul +++ b/test/libyul/objectCompiler/eof/256_subcontainers.yul @@ -4107,6 +4107,6 @@ object "a" { // /* "source":24612:24619 */ // stop // } -// Bytecode: ef000101000402000107010301000014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014040000000080ffff5f808080ec00505f808080ec01505f808080ec02505f808080ec03505f808080ec04505f808080ec05505f808080ec06505f808080ec07505f808080ec08505f808080ec09505f808080ec0a505f808080ec0b505f808080ec0c505f808080ec0d505f808080ec0e505f808080ec0f505f808080ec10505f808080ec11505f808080ec12505f808080ec13505f808080ec14505f808080ec15505f808080ec16505f808080ec17505f808080ec18505f808080ec19505f808080ec1a505f808080ec1b505f808080ec1c505f808080ec1d505f808080ec1e505f808080ec1f505f808080ec20505f808080ec21505f808080ec22505f808080ec23505f808080ec24505f808080ec25505f808080ec26505f808080ec27505f808080ec28505f808080ec29505f808080ec2a505f808080ec2b505f808080ec2c505f808080ec2d505f808080ec2e505f808080ec2f505f808080ec30505f808080ec31505f808080ec32505f808080ec33505f808080ec34505f808080ec35505f808080ec36505f808080ec37505f808080ec38505f808080ec39505f808080ec3a505f808080ec3b505f808080ec3c505f808080ec3d505f808080ec3e505f808080ec3f505f808080ec40505f808080ec41505f808080ec42505f808080ec43505f808080ec44505f808080ec45505f808080ec46505f808080ec47505f808080ec48505f808080ec49505f808080ec4a505f808080ec4b505f808080ec4c505f808080ec4d505f808080ec4e505f808080ec4f505f808080ec50505f808080ec51505f808080ec52505f808080ec53505f808080ec54505f808080ec55505f808080ec56505f808080ec57505f808080ec58505f808080ec59505f808080ec5a505f808080ec5b505f808080ec5c505f808080ec5d505f808080ec5e505f808080ec5f505f808080ec60505f808080ec61505f808080ec62505f808080ec63505f808080ec64505f808080ec65505f808080ec66505f808080ec67505f808080ec68505f808080ec69505f808080ec6a505f808080ec6b505f808080ec6c505f808080ec6d505f808080ec6e505f808080ec6f505f808080ec70505f808080ec71505f808080ec72505f808080ec73505f808080ec74505f808080ec75505f808080ec76505f808080ec77505f808080ec78505f808080ec79505f808080ec7a505f808080ec7b505f808080ec7c505f808080ec7d505f808080ec7e505f808080ec7f505f808080ec80505f808080ec81505f808080ec82505f808080ec83505f808080ec84505f808080ec85505f808080ec86505f808080ec87505f808080ec88505f808080ec89505f808080ec8a505f808080ec8b505f808080ec8c505f808080ec8d505f808080ec8e505f808080ec8f505f808080ec90505f808080ec91505f808080ec92505f808080ec93505f808080ec94505f808080ec95505f808080ec96505f808080ec97505f808080ec98505f808080ec99505f808080ec9a505f808080ec9b505f808080ec9c505f808080ec9d505f808080ec9e505f808080ec9f505f808080eca0505f808080eca1505f808080eca2505f808080eca3505f808080eca4505f808080eca5505f808080eca6505f808080eca7505f808080eca8505f808080eca9505f808080ecaa505f808080ecab505f808080ecac505f808080ecad505f808080ecae505f808080ecaf505f808080ecb0505f808080ecb1505f808080ecb2505f808080ecb3505f808080ecb4505f808080ecb5505f808080ecb6505f808080ecb7505f808080ecb8505f808080ecb9505f808080ecba505f808080ecbb505f808080ecbc505f808080ecbd505f808080ecbe505f808080ecbf505f808080ecc0505f808080ecc1505f808080ecc2505f808080ecc3505f808080ecc4505f808080ecc5505f808080ecc6505f808080ecc7505f808080ecc8505f808080ecc9505f808080ecca505f808080eccb505f808080eccc505f808080eccd505f808080ecce505f808080eccf505f808080ecd0505f808080ecd1505f808080ecd2505f808080ecd3505f808080ecd4505f808080ecd5505f808080ecd6505f808080ecd7505f808080ecd8505f808080ecd9505f808080ecda505f808080ecdb505f808080ecdc505f808080ecdd505f808080ecde505f808080ecdf505f808080ece0505f808080ece1505f808080ece2505f808080ece3505f808080ece4505f808080ece5505f808080ece6505f808080ece7505f808080ece8505f808080ece9505f808080ecea505f808080eceb505f808080ecec505f808080eced505f808080ecee505f808080ecef505f808080ecf0505f808080ecf1505f808080ecf2505f808080ecf3505f808080ecf4505f808080ecf5505f808080ecf6505f808080ecf7505f808080ecf8505f808080ecf9505f808080ecfa505f808080ecfb505f808080ecfc505f808080ecfd505f808080ecfe505f808080ecff5000ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00ef00010100040200010001040000000080ffff00 -// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD SMOD ADD SUB ADD STOP STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x10 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x11 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x12 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x13 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x14 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x15 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x16 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x17 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x18 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x19 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x20 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x21 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x22 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x23 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x24 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x25 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x26 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x27 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x28 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x29 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x30 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x31 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x32 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x33 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x34 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x35 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x36 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x37 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x38 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x39 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x40 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x41 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x42 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x43 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x44 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x45 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x46 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x47 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x48 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x49 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x50 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x51 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x52 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x53 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x54 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x55 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x56 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x57 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x58 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x59 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x60 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x61 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x62 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x63 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x64 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x65 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x66 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x67 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x68 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x69 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x70 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x71 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x72 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x73 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x74 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x75 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x76 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x77 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x78 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x79 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x80 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x81 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x82 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x83 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x84 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x85 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x86 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x87 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x88 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x89 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x90 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x91 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x92 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x93 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x94 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x95 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x96 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x97 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x98 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x99 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xED POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFF POP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP +// Bytecode: ef00010100040200010701030100001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001404000000008000045f808080ec00505f808080ec01505f808080ec02505f808080ec03505f808080ec04505f808080ec05505f808080ec06505f808080ec07505f808080ec08505f808080ec09505f808080ec0a505f808080ec0b505f808080ec0c505f808080ec0d505f808080ec0e505f808080ec0f505f808080ec10505f808080ec11505f808080ec12505f808080ec13505f808080ec14505f808080ec15505f808080ec16505f808080ec17505f808080ec18505f808080ec19505f808080ec1a505f808080ec1b505f808080ec1c505f808080ec1d505f808080ec1e505f808080ec1f505f808080ec20505f808080ec21505f808080ec22505f808080ec23505f808080ec24505f808080ec25505f808080ec26505f808080ec27505f808080ec28505f808080ec29505f808080ec2a505f808080ec2b505f808080ec2c505f808080ec2d505f808080ec2e505f808080ec2f505f808080ec30505f808080ec31505f808080ec32505f808080ec33505f808080ec34505f808080ec35505f808080ec36505f808080ec37505f808080ec38505f808080ec39505f808080ec3a505f808080ec3b505f808080ec3c505f808080ec3d505f808080ec3e505f808080ec3f505f808080ec40505f808080ec41505f808080ec42505f808080ec43505f808080ec44505f808080ec45505f808080ec46505f808080ec47505f808080ec48505f808080ec49505f808080ec4a505f808080ec4b505f808080ec4c505f808080ec4d505f808080ec4e505f808080ec4f505f808080ec50505f808080ec51505f808080ec52505f808080ec53505f808080ec54505f808080ec55505f808080ec56505f808080ec57505f808080ec58505f808080ec59505f808080ec5a505f808080ec5b505f808080ec5c505f808080ec5d505f808080ec5e505f808080ec5f505f808080ec60505f808080ec61505f808080ec62505f808080ec63505f808080ec64505f808080ec65505f808080ec66505f808080ec67505f808080ec68505f808080ec69505f808080ec6a505f808080ec6b505f808080ec6c505f808080ec6d505f808080ec6e505f808080ec6f505f808080ec70505f808080ec71505f808080ec72505f808080ec73505f808080ec74505f808080ec75505f808080ec76505f808080ec77505f808080ec78505f808080ec79505f808080ec7a505f808080ec7b505f808080ec7c505f808080ec7d505f808080ec7e505f808080ec7f505f808080ec80505f808080ec81505f808080ec82505f808080ec83505f808080ec84505f808080ec85505f808080ec86505f808080ec87505f808080ec88505f808080ec89505f808080ec8a505f808080ec8b505f808080ec8c505f808080ec8d505f808080ec8e505f808080ec8f505f808080ec90505f808080ec91505f808080ec92505f808080ec93505f808080ec94505f808080ec95505f808080ec96505f808080ec97505f808080ec98505f808080ec99505f808080ec9a505f808080ec9b505f808080ec9c505f808080ec9d505f808080ec9e505f808080ec9f505f808080eca0505f808080eca1505f808080eca2505f808080eca3505f808080eca4505f808080eca5505f808080eca6505f808080eca7505f808080eca8505f808080eca9505f808080ecaa505f808080ecab505f808080ecac505f808080ecad505f808080ecae505f808080ecaf505f808080ecb0505f808080ecb1505f808080ecb2505f808080ecb3505f808080ecb4505f808080ecb5505f808080ecb6505f808080ecb7505f808080ecb8505f808080ecb9505f808080ecba505f808080ecbb505f808080ecbc505f808080ecbd505f808080ecbe505f808080ecbf505f808080ecc0505f808080ecc1505f808080ecc2505f808080ecc3505f808080ecc4505f808080ecc5505f808080ecc6505f808080ecc7505f808080ecc8505f808080ecc9505f808080ecca505f808080eccb505f808080eccc505f808080eccd505f808080ecce505f808080eccf505f808080ecd0505f808080ecd1505f808080ecd2505f808080ecd3505f808080ecd4505f808080ecd5505f808080ecd6505f808080ecd7505f808080ecd8505f808080ecd9505f808080ecda505f808080ecdb505f808080ecdc505f808080ecdd505f808080ecde505f808080ecdf505f808080ece0505f808080ece1505f808080ece2505f808080ece3505f808080ece4505f808080ece5505f808080ece6505f808080ece7505f808080ece8505f808080ece9505f808080ecea505f808080eceb505f808080ecec505f808080eced505f808080ecee505f808080ecef505f808080ecf0505f808080ecf1505f808080ecf2505f808080ecf3505f808080ecf4505f808080ecf5505f808080ecf6505f808080ecf7505f808080ecf8505f808080ecf9505f808080ecfa505f808080ecfb505f808080ecfc505f808080ecfd505f808080ecfe505f808080ecff5000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD SMOD ADD SUB ADD STOP STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ DIV STOP STOP STOP STOP DUP1 STOP DIV PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x10 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x11 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x12 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x13 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x14 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x15 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x16 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x17 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x18 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x19 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x20 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x21 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x22 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x23 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x24 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x25 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x26 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x27 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x28 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x29 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x30 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x31 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x32 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x33 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x34 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x35 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x36 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x37 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x38 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x39 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x40 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x41 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x42 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x43 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x44 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x45 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x46 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x47 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x48 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x49 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x50 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x51 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x52 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x53 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x54 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x55 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x56 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x57 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x58 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x59 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x60 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x61 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x62 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x63 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x64 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x65 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x66 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x67 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x68 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x69 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x70 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x71 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x72 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x73 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x74 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x75 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x76 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x77 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x78 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x79 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x80 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x81 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x82 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x83 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x84 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x85 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x86 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x87 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x88 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x89 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x90 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x91 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x92 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x93 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x94 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x95 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x96 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x97 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x98 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x99 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xED POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFF POP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP // SourceMappings: 78:1:0:-:0;50:30;;;;46:35;126:1;98:30;;;;94:35;174:1;146:30;;;;142:35;222:1;194:30;;;;190:35;270:1;242:30;;;;238:35;318:1;290:30;;;;286:35;366:1;338:30;;;;334:35;414:1;386:30;;;;382:35;462:1;434:30;;;;430:35;510:1;482:30;;;;478:35;558:1;530:30;;;;526:35;606:1;578:30;;;;574:35;654:1;626:30;;;;622:35;702:1;674:30;;;;670:35;750:1;722:30;;;;718:35;798:1;770:30;;;;766:35;846:1;818:30;;;;814:35;894:1;866:30;;;;862:35;942:1;914:30;;;;910:35;990:1;962:30;;;;958:35;1038:1;1010:30;;;;1006:35;1086:1;1058:30;;;;1054:35;1134:1;1106:30;;;;1102:35;1182:1;1154:30;;;;1150:35;1230:1;1202:30;;;;1198:35;1278:1;1250:30;;;;1246:35;1326:1;1298:30;;;;1294:35;1374:1;1346:30;;;;1342:35;1422:1;1394:30;;;;1390:35;1470:1;1442:30;;;;1438:35;1518:1;1490:30;;;;1486:35;1566:1;1538:30;;;;1534:35;1614:1;1586:30;;;;1582:35;1662:1;1634:30;;;;1630:35;1710:1;1682:30;;;;1678:35;1758:1;1730:30;;;;1726:35;1806:1;1778:30;;;;1774:35;1854:1;1826:30;;;;1822:35;1902:1;1874:30;;;;1870:35;1950:1;1922:30;;;;1918:35;1998:1;1970:30;;;;1966:35;2046:1;2018:30;;;;2014:35;2094:1;2066:30;;;;2062:35;2142:1;2114:30;;;;2110:35;2190:1;2162:30;;;;2158:35;2238:1;2210:30;;;;2206:35;2286:1;2258:30;;;;2254:35;2334:1;2306:30;;;;2302:35;2382:1;2354:30;;;;2350:35;2430:1;2402:30;;;;2398:35;2478:1;2450:30;;;;2446:35;2526:1;2498:30;;;;2494:35;2574:1;2546:30;;;;2542:35;2622:1;2594:30;;;;2590:35;2670:1;2642:30;;;;2638:35;2718:1;2690:30;;;;2686:35;2766:1;2738:30;;;;2734:35;2814:1;2786:30;;;;2782:35;2862:1;2834:30;;;;2830:35;2910:1;2882:30;;;;2878:35;2958:1;2930:30;;;;2926:35;3006:1;2978:30;;;;2974:35;3054:1;3026:30;;;;3022:35;3102:1;3074:30;;;;3070:35;3150:1;3122:30;;;;3118:35;3198:1;3170:30;;;;3166:35;3246:1;3218:30;;;;3214:35;3294:1;3266:30;;;;3262:35;3342:1;3314:30;;;;3310:35;3390:1;3362:30;;;;3358:35;3438:1;3410:30;;;;3406:35;3486:1;3458:30;;;;3454:35;3534:1;3506:30;;;;3502:35;3582:1;3554:30;;;;3550:35;3630:1;3602:30;;;;3598:35;3678:1;3650:30;;;;3646:35;3726:1;3698:30;;;;3694:35;3774:1;3746:30;;;;3742:35;3822:1;3794:30;;;;3790:35;3870:1;3842:30;;;;3838:35;3918:1;3890:30;;;;3886:35;3966:1;3938:30;;;;3934:35;4014:1;3986:30;;;;3982:35;4062:1;4034:30;;;;4030:35;4110:1;4082:30;;;;4078:35;4158:1;4130:30;;;;4126:35;4206:1;4178:30;;;;4174:35;4254:1;4226:30;;;;4222:35;4302:1;4274:30;;;;4270:35;4350:1;4322:30;;;;4318:35;4398:1;4370:30;;;;4366:35;4446:1;4418:30;;;;4414:35;4494:1;4466:30;;;;4462:35;4542:1;4514:30;;;;4510:35;4590:1;4562:30;;;;4558:35;4638:1;4610:30;;;;4606:35;4686:1;4658:30;;;;4654:35;4734:1;4706:30;;;;4702:35;4782:1;4754:30;;;;4750:35;4830:1;4802:30;;;;4798:35;4878:1;4850:30;;;;4846:35;4926:1;4898:30;;;;4894:35;4974:1;4946:30;;;;4942:35;5022:1;4994:30;;;;4990:35;5070:1;5042:30;;;;5038:35;5118:1;5090:30;;;;5086:35;5166:1;5138:30;;;;5134:35;5214:1;5186:30;;;;5182:35;5262:1;5234:30;;;;5230:35;5310:1;5282:30;;;;5278:35;5358:1;5330:30;;;;5326:35;5406:1;5378:30;;;;5374:35;5454:1;5426:30;;;;5422:35;5502:1;5474:30;;;;5470:35;5550:1;5522:30;;;;5518:35;5598:1;5570:30;;;;5566:35;5646:1;5618:30;;;;5614:35;5694:1;5666:30;;;;5662:35;5742:1;5714:30;;;;5710:35;5790:1;5762:30;;;;5758:35;5838:1;5810:30;;;;5806:35;5886:1;5858:30;;;;5854:35;5934:1;5906:30;;;;5902:35;5982:1;5954:30;;;;5950:35;6030:1;6002:30;;;;5998:35;6078:1;6050:30;;;;6046:35;6126:1;6098:30;;;;6094:35;6174:1;6146:30;;;;6142:35;6222:1;6194:30;;;;6190:35;6270:1;6242:30;;;;6238:35;6318:1;6290:30;;;;6286:35;6366:1;6338:30;;;;6334:35;6414:1;6386:30;;;;6382:35;6462:1;6434:30;;;;6430:35;6510:1;6482:30;;;;6478:35;6558:1;6530:30;;;;6526:35;6606:1;6578:30;;;;6574:35;6654:1;6626:30;;;;6622:35;6702:1;6674:30;;;;6670:35;6750:1;6722:30;;;;6718:35;6798:1;6770:30;;;;6766:35;6846:1;6818:30;;;;6814:35;6894:1;6866:30;;;;6862:35;6942:1;6914:30;;;;6910:35;6990:1;6962:30;;;;6958:35;7038:1;7010:30;;;;7006:35;7086:1;7058:30;;;;7054:35;7134:1;7106:30;;;;7102:35;7182:1;7154:30;;;;7150:35;7230:1;7202:30;;;;7198:35;7278:1;7250:30;;;;7246:35;7326:1;7298:30;;;;7294:35;7374:1;7346:30;;;;7342:35;7422:1;7394:30;;;;7390:35;7470:1;7442:30;;;;7438:35;7518:1;7490:30;;;;7486:35;7566:1;7538:30;;;;7534:35;7614:1;7586:30;;;;7582:35;7662:1;7634:30;;;;7630:35;7710:1;7682:30;;;;7678:35;7758:1;7730:30;;;;7726:35;7806:1;7778:30;;;;7774:35;7854:1;7826:30;;;;7822:35;7902:1;7874:30;;;;7870:35;7950:1;7922:30;;;;7918:35;7998:1;7970:30;;;;7966:35;8046:1;8018:30;;;;8014:35;8094:1;8066:30;;;;8062:35;8142:1;8114:30;;;;8110:35;8190:1;8162:30;;;;8158:35;8238:1;8210:30;;;;8206:35;8286:1;8258:30;;;;8254:35;8334:1;8306:30;;;;8302:35;8382:1;8354:30;;;;8350:35;8430:1;8402:30;;;;8398:35;8478:1;8450:30;;;;8446:35;8526:1;8498:30;;;;8494:35;8574:1;8546:30;;;;8542:35;8622:1;8594:30;;;;8590:35;8670:1;8642:30;;;;8638:35;8718:1;8690:30;;;;8686:35;8766:1;8738:30;;;;8734:35;8814:1;8786:30;;;;8782:35;8862:1;8834:30;;;;8830:35;8910:1;8882:30;;;;8878:35;8958:1;8930:30;;;;8926:35;9006:1;8978:30;;;;8974:35;9054:1;9026:30;;;;9022:35;9102:1;9074:30;;;;9070:35;9150:1;9122:30;;;;9118:35;9198:1;9170:30;;;;9166:35;9246:1;9218:30;;;;9214:35;9294:1;9266:30;;;;9262:35;9342:1;9314:30;;;;9310:35;9390:1;9362:30;;;;9358:35;9438:1;9410:30;;;;9406:35;9486:1;9458:30;;;;9454:35;9534:1;9506:30;;;;9502:35;9582:1;9554:30;;;;9550:35;9630:1;9602:30;;;;9598:35;9678:1;9650:30;;;;9646:35;9726:1;9698:30;;;;9694:35;9774:1;9746:30;;;;9742:35;9822:1;9794:30;;;;9790:35;9870:1;9842:30;;;;9838:35;9918:1;9890:30;;;;9886:35;9966:1;9938:30;;;;9934:35;10014:1;9986:30;;;;9982:35;10062:1;10034:30;;;;10030:35;10110:1;10082:30;;;;10078:35;10158:1;10130:30;;;;10126:35;10206:1;10178:30;;;;10174:35;10254:1;10226:30;;;;10222:35;10302:1;10274:30;;;;10270:35;10350:1;10322:30;;;;10318:35;10398:1;10370:30;;;;10366:35;10446:1;10418:30;;;;10414:35;10494:1;10466:30;;;;10462:35;10542:1;10514:30;;;;10510:35;10590:1;10562:30;;;;10558:35;10638:1;10610:30;;;;10606:35;10686:1;10658:30;;;;10654:35;10734:1;10706:30;;;;10702:35;10782:1;10754:30;;;;10750:35;10830:1;10802:30;;;;10798:35;10878:1;10850:30;;;;10846:35;10926:1;10898:30;;;;10894:35;10974:1;10946:30;;;;10942:35;11022:1;10994:30;;;;10990:35;11070:1;11042:30;;;;11038:35;11118:1;11090:30;;;;11086:35;11166:1;11138:30;;;;11134:35;11214:1;11186:30;;;;11182:35;11262:1;11234:30;;;;11230:35;11310:1;11282:30;;;;11278:35;11358:1;11330:30;;;;11326:35;11406:1;11378:30;;;;11374:35;11454:1;11426:30;;;;11422:35;11502:1;11474:30;;;;11470:35;11550:1;11522:30;;;;11518:35;11598:1;11570:30;;;;11566:35;11646:1;11618:30;;;;11614:35;11694:1;11666:30;;;;11662:35;11742:1;11714:30;;;;11710:35;11790:1;11762:30;;;;11758:35;11838:1;11810:30;;;;11806:35;11886:1;11858:30;;;;11854:35;11934:1;11906:30;;;;11902:35;11982:1;11954:30;;;;11950:35;12030:1;12002:30;;;;11998:35;12078:1;12050:30;;;;12046:35;12126:1;12098:30;;;;12094:35;12174:1;12146:30;;;;12142:35;12222:1;12194:30;;;;12190:35;12270:1;12242:30;;;;12238:35;12318:1;12290:30;;;;12286:35;22:12315 diff --git a/test/libyul/objectCompiler/eof/creation_with_immutables.yul b/test/libyul/objectCompiler/eof/creation_with_immutables.yul index 63558294f..aaffee722 100644 --- a/test/libyul/objectCompiler/eof/creation_with_immutables.yul +++ b/test/libyul/objectCompiler/eof/creation_with_immutables.yul @@ -95,6 +95,6 @@ object "a" { // return // } // } -// Bytecode: ef0001010004020001000c030001008704000d000080ffff5f808080ec005f5260205ff3ef0001010004020001004c0300010023040000000080ffff7f11223344556677889900112233445566778899001122334455667788990011225f527f112233445566778899001122334455667788990011223344556677889900112260205260405fee00ef00010100040200010010040040000080ffffd10000d10020905f5260205260405ff348656c6c6f2c20576f726c6421 -// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0xC SUB STOP ADD STOP DUP8 DIV STOP 0xD STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0x4C SUB STOP ADD STOP 0x23 DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH0 MSTORE PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH1 0x20 MSTORE PUSH1 0x40 PUSH0 RETURNCONTRACT 0x0 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP LT DIV STOP BLOCKHASH STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT DATALOADN 0x0 DATALOADN 0x20 SWAP1 PUSH0 MSTORE PUSH1 0x20 MSTORE PUSH1 0x40 PUSH0 RETURN BASEFEE PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000 +// Bytecode: ef0001010004020001000c030001008704000d00008000045f808080ec005f5260205ff3ef0001010004020001004c030001002304000000008000027f11223344556677889900112233445566778899001122334455667788990011225f527f112233445566778899001122334455667788990011223344556677889900112260205260405fee00ef000101000402000100100400400000800003d10000d10020905f5260205260405ff348656c6c6f2c20576f726c6421 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0xC SUB STOP ADD STOP DUP8 DIV STOP 0xD STOP STOP DUP1 STOP DIV PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0x4C SUB STOP ADD STOP 0x23 DIV STOP STOP STOP STOP DUP1 STOP MUL PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH0 MSTORE PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH1 0x20 MSTORE PUSH1 0x40 PUSH0 RETURNCONTRACT 0x0 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP LT DIV STOP BLOCKHASH STOP STOP DUP1 STOP SUB DATALOADN 0x0 DATALOADN 0x20 SWAP1 PUSH0 MSTORE PUSH1 0x20 MSTORE PUSH1 0x40 PUSH0 RETURN BASEFEE PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000 // SourceMappings: 80:1:0:-:0;56:26;;;;53:1;46:37;106:2;103:1;96:13 diff --git a/test/libyul/objectCompiler/eof/dataloadn.yul b/test/libyul/objectCompiler/eof/dataloadn.yul index b38222917..06ebdaa3c 100644 --- a/test/libyul/objectCompiler/eof/dataloadn.yul +++ b/test/libyul/objectCompiler/eof/dataloadn.yul @@ -27,6 +27,6 @@ object "a" { // return // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 -// Bytecode: ef0001010004020001000904002d000080ffffd1000d5f5260205ff348656c6c6f2c20576f726c6421 -// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP MULMOD DIV STOP 0x2D STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT DATALOADN 0xD PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN BASEFEE PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000 +// Bytecode: ef0001010004020001000904002d0000800002d1000d5f5260205ff348656c6c6f2c20576f726c6421 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP MULMOD DIV STOP 0x2D STOP STOP DUP1 STOP MUL DATALOADN 0xD PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN BASEFEE PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000 // SourceMappings: 56:15:0:-:0;53:1;46:26;95:2;92:1;85:13 diff --git a/test/libyul/objectCompiler/eof/functions.yul b/test/libyul/objectCompiler/eof/functions.yul index 72167f72a..65361efa3 100644 --- a/test/libyul/objectCompiler/eof/functions.yul +++ b/test/libyul/objectCompiler/eof/functions.yul @@ -79,6 +79,6 @@ object "a" { // dup1 // revert // } -// Bytecode: ef000101000c020003001400090003040000000080ffff0101ffff0080ffff5f35e300015f52602035e1000460205ff3e50002e100036063e46005e45f80fd -// Opcodes: 0xEF STOP ADD ADD STOP 0xC MUL STOP SUB STOP EQ STOP MULMOD STOP SUB DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT ADD ADD SELFDESTRUCT SELFDESTRUCT STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH0 CALLDATALOAD CALLF 0x1 PUSH0 MSTORE PUSH1 0x20 CALLDATALOAD RJUMPI 0x4 PUSH1 0x20 PUSH0 RETURN JUMPF 0x2 RJUMPI 0x3 PUSH1 0x63 RETF PUSH1 0x5 RETF PUSH0 DUP1 REVERT +// Bytecode: ef000101000c020003001400090003040000000080000201010001008000025f35e300015f52602035e1000460205ff3e50002e100036063e46005e45f80fd +// Opcodes: 0xEF STOP ADD ADD STOP 0xC MUL STOP SUB STOP EQ STOP MULMOD STOP SUB DIV STOP STOP STOP STOP DUP1 STOP MUL ADD ADD STOP ADD STOP DUP1 STOP MUL PUSH0 CALLDATALOAD CALLF 0x1 PUSH0 MSTORE PUSH1 0x20 CALLDATALOAD RJUMPI 0x4 PUSH1 0x20 PUSH0 RETURN JUMPF 0x2 RJUMPI 0x3 PUSH1 0x63 RETF PUSH1 0x5 RETF PUSH0 DUP1 REVERT // SourceMappings: 74:1:0:-:0;61:15;56:21::i;53:1::-;46:32;107:2;94:16;91:37;22:364;151:2;148:1;141:13;111:17;113:13::i217:77:0:-:0;203:121;312:2;173:151::o;234:60::-;257:1;275:5::o376:1:0:-:0;366:12; diff --git a/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul b/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul index 2225fe6eb..0c9f9a382 100644 --- a/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul +++ b/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul @@ -76,6 +76,6 @@ object "a" { // /* "source":421:649 */ // stop // } -// Bytecode: ef0001010004020001000c030001005b040000000080ffff5f808080ec005f5260205ff3ef00010100040200010048040000000080ffff7f11223344556677889900112233445566778899001122334455667788990011225f527f112233445566778899001122334455667788990011223344556677889900112260205200 -// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0xC SUB STOP ADD STOP JUMPDEST DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP BASEFEE DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH0 MSTORE PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH1 0x20 MSTORE STOP +// Bytecode: ef0001010004020001000c030001005b04000000008000045f808080ec005f5260205ff3ef0001010004020001004804000000008000027f11223344556677889900112233445566778899001122334455667788990011225f527f112233445566778899001122334455667788990011223344556677889900112260205200 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP 0xC SUB STOP ADD STOP JUMPDEST DIV STOP STOP STOP STOP DUP1 STOP DIV PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 PUSH0 MSTORE PUSH1 0x20 PUSH0 RETURN 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP BASEFEE DIV STOP STOP STOP STOP DUP1 STOP MUL PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH0 MSTORE PUSH32 0x1122334455667788990011223344556677889900112233445566778899001122 PUSH1 0x20 MSTORE STOP // SourceMappings: 80:1:0:-:0;56:26;;;;53:1;46:37;106:2;103:1;96:13 diff --git a/test/libyul/objectCompiler/eof/rjumps.yul b/test/libyul/objectCompiler/eof/rjumps.yul index b13f3c362..d5f2f6c21 100644 --- a/test/libyul/objectCompiler/eof/rjumps.yul +++ b/test/libyul/objectCompiler/eof/rjumps.yul @@ -35,6 +35,6 @@ object "a" { // mstore // /* "source":54:70 */ // rjump{tag_2} -// Bytecode: ef00010100040200010010040000000080ffff6001e1000460205ff360015f52e0fff5 -// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP LT DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT PUSH1 0x1 RJUMPI 0x4 PUSH1 0x20 PUSH0 RETURN PUSH1 0x1 PUSH0 MSTORE RJUMP 0xFFF5 +// Bytecode: ef0001010004020001001004000000008000026001e1000460205ff360015f52e0fff5 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP LT DIV STOP STOP STOP STOP DUP1 STOP MUL PUSH1 0x1 RJUMPI 0x4 PUSH1 0x20 PUSH0 RETURN PUSH1 0x1 PUSH0 MSTORE RJUMP 0xFFF5 // SourceMappings: 49:4:0:-:0;46:24;22:90;93:2;90:1;83:13;54:16;66:1;63;56:12;54:16 From b292de4f13ceaa100eeed6824d91c053842314dc Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 6 Dec 2024 15:36:22 +0100 Subject: [PATCH 0518/1340] eof: Fix legacy `staticcall` error for EOF. Add test. --- libyul/AsmAnalysis.cpp | 1 + .../yulSyntaxTests/eof/legacy_calls_in_eof.yul | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 test/libyul/yulSyntaxTests/eof/legacy_calls_in_eof.yul diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index b00982faf..f1664ad68 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -776,6 +776,7 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio _instr == evmasm::Instruction::CALL || _instr == evmasm::Instruction::CALLCODE || _instr == evmasm::Instruction::DELEGATECALL || + _instr == evmasm::Instruction::STATICCALL || _instr == evmasm::Instruction::SELFDESTRUCT || _instr == evmasm::Instruction::JUMP || _instr == evmasm::Instruction::JUMPI || diff --git a/test/libyul/yulSyntaxTests/eof/legacy_calls_in_eof.yul b/test/libyul/yulSyntaxTests/eof/legacy_calls_in_eof.yul new file mode 100644 index 000000000..4ed95e6c3 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/legacy_calls_in_eof.yul @@ -0,0 +1,17 @@ +object "a" { + code { + pop(call(address(), 0, 0, 10)) + pop(staticcall(address(), 0, 0)) + pop(delegatecall(address(), 0, 0)) + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 9132: (36-40): The "call" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (36-61): Expected expression to evaluate to one value, but got 0 values instead. +// TypeError 9132: (75-85): The "staticcall" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (75-102): Expected expression to evaluate to one value, but got 0 values instead. +// TypeError 9132: (116-128): The "delegatecall" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (116-145): Expected expression to evaluate to one value, but got 0 values instead. From c5ab3b81400573c25f47402d515de52db9b26963 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:16:30 +0200 Subject: [PATCH 0519/1340] Yul: Add builtin AST element --- libsolidity/analysis/ControlFlowBuilder.cpp | 10 +- libsolidity/analysis/ViewPureChecker.cpp | 9 +- libsolidity/ast/ASTJsonImporter.cpp | 4 +- libyul/AST.h | 11 +- libyul/ASTForward.h | 9 ++ libyul/AsmAnalysis.cpp | 48 +++--- libyul/AsmAnalysis.h | 2 +- libyul/AsmJsonConverter.cpp | 14 +- libyul/AsmJsonConverter.h | 5 +- libyul/AsmJsonImporter.cpp | 13 +- libyul/AsmParser.cpp | 144 +++++++++++------- libyul/AsmParser.h | 4 +- libyul/AsmPrinter.cpp | 8 +- libyul/AsmPrinter.h | 5 +- libyul/ControlFlowSideEffectsCollector.cpp | 5 +- libyul/FunctionReferenceResolver.cpp | 14 +- libyul/Utilities.cpp | 9 ++ libyul/Utilities.h | 1 + libyul/backends/evm/ConstantOptimiser.cpp | 45 +++--- libyul/backends/evm/ConstantOptimiser.h | 4 +- .../backends/evm/ControlFlowGraphBuilder.cpp | 14 +- libyul/backends/evm/EVMCodeTransform.cpp | 10 +- libyul/backends/evm/EVMDialect.cpp | 14 +- libyul/backends/evm/EVMMetrics.cpp | 6 +- libyul/backends/evm/EVMObjectCompiler.cpp | 4 +- .../evm/OptimizedEVMCodeTransform.cpp | 17 ++- .../backends/evm/OptimizedEVMCodeTransform.h | 4 +- .../evm/SSAControlFlowGraphBuilder.cpp | 23 +-- libyul/backends/evm/StackHelpers.h | 11 +- libyul/optimiser/ASTCopier.cpp | 10 ++ libyul/optimiser/ASTCopier.h | 1 + libyul/optimiser/BlockHasher.cpp | 29 +++- libyul/optimiser/BlockHasher.h | 1 + libyul/optimiser/CallGraphGenerator.cpp | 20 ++- libyul/optimiser/CallGraphGenerator.h | 7 +- libyul/optimiser/CircularReferencesPruner.cpp | 4 +- .../CommonSubexpressionEliminator.cpp | 7 +- .../optimiser/CommonSubexpressionEliminator.h | 2 +- libyul/optimiser/ControlFlowSimplifier.cpp | 13 +- libyul/optimiser/DataFlowAnalyzer.cpp | 31 ++-- libyul/optimiser/DataFlowAnalyzer.h | 8 +- libyul/optimiser/EqualStoreEliminator.h | 2 +- .../optimiser/EquivalentFunctionCombiner.cpp | 11 +- libyul/optimiser/ExpressionInliner.cpp | 6 +- libyul/optimiser/ExpressionSimplifier.cpp | 9 +- libyul/optimiser/ExpressionSplitter.cpp | 5 +- libyul/optimiser/ForLoopConditionIntoBody.cpp | 2 +- .../optimiser/ForLoopConditionOutOfBody.cpp | 9 +- libyul/optimiser/FullInliner.cpp | 31 ++-- libyul/optimiser/FullInliner.h | 4 +- libyul/optimiser/FunctionCallFinder.cpp | 23 +-- libyul/optimiser/FunctionCallFinder.h | 8 +- libyul/optimiser/FunctionSpecializer.cpp | 13 +- libyul/optimiser/FunctionSpecializer.h | 14 +- .../InlinableExpressionFunctionFinder.cpp | 10 +- .../InlinableExpressionFunctionFinder.h | 6 +- libyul/optimiser/KnowledgeBase.cpp | 15 +- libyul/optimiser/KnowledgeBase.h | 11 +- libyul/optimiser/LoadResolver.cpp | 12 +- libyul/optimiser/LoadResolver.h | 2 +- libyul/optimiser/LoopInvariantCodeMotion.cpp | 2 +- libyul/optimiser/LoopInvariantCodeMotion.h | 4 +- libyul/optimiser/Metrics.cpp | 2 +- libyul/optimiser/NameCollector.cpp | 9 +- libyul/optimiser/NameCollector.h | 8 +- libyul/optimiser/NameDisplacer.cpp | 3 +- libyul/optimiser/NameSimplifier.cpp | 7 +- libyul/optimiser/OptimizerUtilities.cpp | 9 +- libyul/optimiser/OptimizerUtilities.h | 2 +- libyul/optimiser/Semantics.cpp | 54 ++++--- libyul/optimiser/Semantics.h | 14 +- libyul/optimiser/SimplificationRules.cpp | 20 ++- libyul/optimiser/SimplificationRules.h | 7 +- libyul/optimiser/StackLimitEvader.cpp | 28 ++-- libyul/optimiser/StackToMemoryMover.cpp | 11 +- libyul/optimiser/SyntacticalEquality.cpp | 9 ++ libyul/optimiser/SyntacticalEquality.h | 1 + libyul/optimiser/UnusedAssignEliminator.cpp | 10 +- libyul/optimiser/UnusedPruner.cpp | 10 +- libyul/optimiser/UnusedPruner.h | 11 +- libyul/optimiser/UnusedStoreEliminator.cpp | 34 +++-- libyul/optimiser/UnusedStoreEliminator.h | 4 +- test/libsolidity/MemoryGuardTest.cpp | 6 +- test/libyul/ControlFlowGraphTest.cpp | 14 +- test/libyul/FunctionSideEffects.cpp | 11 +- test/libyul/KnowledgeBaseTest.cpp | 2 +- test/libyul/StackLayoutGeneratorTest.cpp | 21 +-- test/libyul/StackShufflingTest.cpp | 20 ++- test/tools/yulInterpreter/Interpreter.cpp | 25 ++- 89 files changed, 710 insertions(+), 441 deletions(-) diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index a42cec172..11d8e84c6 100644 --- a/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/libsolidity/analysis/ControlFlowBuilder.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include using namespace solidity::langutil; @@ -582,14 +583,13 @@ void ControlFlowBuilder::operator()(yul::FunctionCall const& _functionCall) solAssert(m_currentNode && m_inlineAssembly, ""); yul::ASTWalker::operator()(_functionCall); - if (auto const& builtinHandle = m_inlineAssembly->dialect().findBuiltin(_functionCall.functionName.name.str())) + if (auto const* builtinFunction = resolveBuiltinFunction(_functionCall.functionName, m_inlineAssembly->dialect())) { - auto const& builtinFunction = m_inlineAssembly->dialect().builtin(*builtinHandle); - if (builtinFunction.controlFlowSideEffects.canTerminate) + if (builtinFunction->controlFlowSideEffects.canTerminate) connect(m_currentNode, m_transactionReturnNode); - if (builtinFunction.controlFlowSideEffects.canRevert) + if (builtinFunction->controlFlowSideEffects.canRevert) connect(m_currentNode, m_revertNode); - if (!builtinFunction.controlFlowSideEffects.canContinue) + if (!builtinFunction->controlFlowSideEffects.canContinue) m_currentNode = newLabel(); } } diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 6a3a902ed..cbd538551 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -18,8 +18,9 @@ #include #include -#include #include +#include +#include #include #include @@ -66,9 +67,9 @@ class AssemblyViewPureChecker void operator()(yul::FunctionCall const& _funCall) { if (yul::EVMDialect const* dialect = dynamic_cast(&m_dialect)) - if (std::optional builtinHandle = dialect->findBuiltin(_funCall.functionName.name.str())) - if (auto const& instruction = dialect->builtin(*builtinHandle).instruction) - checkInstruction(nativeLocationOf(_funCall), *instruction); + if (yul::BuiltinFunctionForEVM const* builtin = resolveBuiltinFunctionForEVM(_funCall.functionName, *dialect)) + if (builtin->instruction) + checkInstruction(nativeLocationOf(_funCall), *builtin->instruction); for (auto const& arg: _funCall.arguments) std::visit(*this, arg); diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 5d59308ae..344bfb39d 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -742,7 +742,9 @@ ASTPointer ASTJsonImporter::createInlineAssembly(Json const& _no flags->emplace_back(std::make_shared(flag.get())); } } - std::shared_ptr operations = std::make_shared(yul::AsmJsonImporter(dialect, m_sourceNames).createAST(member(_node, "AST"))); + std::shared_ptr operations = std::make_shared( + yul::AsmJsonImporter(dialect, m_sourceNames).createAST(member(_node, "AST")) + ); return createASTNode( _node, nullOrASTString(_node, "documentation"), diff --git a/libyul/AST.h b/libyul/AST.h index be734fa6b..b19499b9a 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -24,6 +24,7 @@ #pragma once #include +#include #include #include @@ -71,6 +72,9 @@ class LiteralValue { struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; LiteralValue value; }; /// External / internal identifier or label reference struct Identifier { langutil::DebugData::ConstPtr debugData; YulName name; }; +/// AST Node representing a reference to one of the built-in functions (as defined by the dialect). +/// In the source it's an actual name, while in the AST we only store a handle that can be used to find the the function in the Dialect +struct BuiltinName { langutil::DebugData::ConstPtr debugData; BuiltinHandle handle; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand /// side and requires x to occupy exactly one stack slot. /// @@ -78,7 +82,7 @@ struct Identifier { langutil::DebugData::ConstPtr debugData; YulName name; }; /// a single stack slot and expects a single expression on the right hand returning /// the same amount of items as the number of variables. struct Assignment { langutil::DebugData::ConstPtr debugData; std::vector variableNames; std::unique_ptr value; }; -struct FunctionCall { langutil::DebugData::ConstPtr debugData; Identifier functionName; std::vector arguments; }; +struct FunctionCall { langutil::DebugData::ConstPtr debugData; FunctionName functionName; std::vector arguments; }; /// Statement that contains only a single expression struct ExpressionStatement { langutil::DebugData::ConstPtr debugData; Expression expression; }; /// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted @@ -114,6 +118,11 @@ class AST Block m_root; }; +bool constexpr isBuiltinFunctionCall(FunctionCall const& _functionCall) noexcept +{ + return std::holds_alternative(_functionCall.functionName); +} + /// Extracts the IR source location from a Yul node. template inline langutil::SourceLocation nativeLocationOf(T const& _node) diff --git a/libyul/ASTForward.h b/libyul/ASTForward.h index 8aba4f248..868fc84b2 100644 --- a/libyul/ASTForward.h +++ b/libyul/ASTForward.h @@ -28,6 +28,9 @@ namespace solidity::yul { +class YulString; +using YulName = YulString; + enum class LiteralKind; class LiteralValue; struct Literal; @@ -46,11 +49,17 @@ struct Continue; struct Leave; struct ExpressionStatement; struct Block; +struct BuiltinName; +struct BuiltinHandle; class AST; struct NameWithDebugData; using Expression = std::variant; +using FunctionName = std::variant; +/// Type that can refer to both user-defined functions and built-ins. +/// Technically the AST allows these names to overlap, but this is not possible to represent in the source. +using FunctionHandle = std::variant; using Statement = std::variant; } diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index b00982faf..7d395a208 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -313,15 +313,14 @@ void AsmAnalyzer::operator()(FunctionDefinition const& _funDef) size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) { - yulAssert(!_funCall.functionName.name.empty(), ""); auto watcher = m_errorReporter.errorWatcher(); std::optional numParameters; std::optional numReturns; std::vector> const* literalArguments = nullptr; - if (std::optional handle = m_dialect.findBuiltin(_funCall.functionName.name.str())) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_funCall.functionName, m_dialect)) { - if (_funCall.functionName.name == "selfdestruct"_yulname) + if (builtin->name == "selfdestruct") m_errorReporter.warning( 1699_error, nativeLocationOf(_funCall.functionName), @@ -334,7 +333,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) ); else if ( m_evmVersion.supportsTransientStorage() && - _funCall.functionName.name == "tstore"_yulname && + builtin->name == "tstore" && !m_errorReporter.hasError({2394}) ) m_errorReporter.warning( @@ -347,16 +346,15 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) "The use of transient storage for reentrancy guards that are cleared at the end of the call is safe." ); - BuiltinFunction const& f = m_dialect.builtin(*handle); - numParameters = f.numParameters; - numReturns = f.numReturns; - if (!f.literalArguments.empty()) - literalArguments = &f.literalArguments; + numParameters = builtin->numParameters; + numReturns = builtin->numReturns; + if (!builtin->literalArguments.empty()) + literalArguments = &builtin->literalArguments; validateInstructions(_funCall); - m_sideEffects += f.sideEffects; + m_sideEffects += builtin->sideEffects; } - else if (m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{ + else if (m_currentScope->lookup(YulName{std::string(resolveFunctionName(_funCall.functionName, m_dialect))}, GenericVisitor{ [&](Scope::Variable const&) { m_errorReporter.typeError( @@ -372,10 +370,11 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) } })) { + yulAssert(std::holds_alternative(_funCall.functionName)); if (m_resolver) // We found a local reference, make sure there is no external reference. m_resolver( - _funCall.functionName, + std::get(_funCall.functionName), yul::IdentifierContext::NonExternal, m_currentScope->insideFunction() ); @@ -386,7 +385,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) m_errorReporter.declarationError( 4619_error, nativeLocationOf(_funCall.functionName), - "Function \"" + _funCall.functionName.name.str() + "\" not found." + fmt::format("Function \"{}\" not found.", resolveFunctionName(_funCall.functionName, m_dialect)) ); yulAssert(!watcher.ok(), "Expected a reported error."); } @@ -395,10 +394,12 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) m_errorReporter.typeError( 7000_error, nativeLocationOf(_funCall.functionName), - "Function \"" + _funCall.functionName.name.str() + "\" expects " + - std::to_string(*numParameters) + - " arguments but got " + - std::to_string(_funCall.arguments.size()) + "." + fmt::format( + "Function \"{}\" expects {} arguments but got {}.", + resolveFunctionName(_funCall.functionName, m_dialect), + *numParameters, + _funCall.arguments.size() + ) ); for (size_t i = _funCall.arguments.size(); i > 0; i--) @@ -424,7 +425,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) ); else if (*literalArgumentKind == LiteralKind::String) { - std::string functionName = _funCall.functionName.name.str(); + std::string_view functionName = resolveFunctionName(_funCall.functionName, m_dialect); if (functionName == "datasize" || functionName == "dataoffset") { auto const& argumentAsLiteral = std::get(arg); @@ -455,7 +456,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) m_errorReporter.typeError( 2186_error, nativeLocationOf(arg), - "Name required but path given as \"" + functionName + "\" argument." + fmt::format("Name required but path given as \"{}\" argument.", functionName) ); if (!m_objectStructure.topLevelSubObjectNames().count(formattedLiteral)) @@ -480,7 +481,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) } else if (*literalArgumentKind == LiteralKind::Number) { - std::string functionName = _funCall.functionName.name.str(); + std::string_view functionName = resolveFunctionName(_funCall.functionName, m_dialect); if (functionName == "auxdataloadn") { auto const& argumentAsLiteral = std::get(arg); @@ -686,7 +687,7 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons ); } -bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location) +bool AsmAnalyzer::validateInstructions(std::string_view _instructionIdentifier, langutil::SourceLocation const& _location) { // NOTE: This function uses the default EVM version instead of the currently selected one. auto const& defaultEVMDialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); @@ -813,7 +814,10 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio bool AsmAnalyzer::validateInstructions(FunctionCall const& _functionCall) { - return validateInstructions(_functionCall.functionName.name.str(), nativeLocationOf(_functionCall.functionName)); + return validateInstructions( + resolveFunctionName(_functionCall.functionName, m_dialect), + nativeLocationOf(_functionCall.functionName) + ); } void AsmAnalyzer::validateObjectStructure(langutil::SourceLocation _astRootLocation) diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 6235b530d..e8c02fbec 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -118,7 +118,7 @@ class AsmAnalyzer void expectValidIdentifier(YulName _identifier, langutil::SourceLocation const& _location); bool validateInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location); - bool validateInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location); + bool validateInstructions(std::string_view _instrIdentifier, langutil::SourceLocation const& _location); bool validateInstructions(FunctionCall const& _functionCall); void validateObjectStructure(langutil::SourceLocation _astRootLocation); diff --git a/libyul/AsmJsonConverter.cpp b/libyul/AsmJsonConverter.cpp index 226ac52a5..fd36dd260 100644 --- a/libyul/AsmJsonConverter.cpp +++ b/libyul/AsmJsonConverter.cpp @@ -20,8 +20,10 @@ * Converts inline assembly AST to JSON format */ -#include #include + +#include +#include #include #include #include @@ -83,6 +85,14 @@ Json AsmJsonConverter::operator()(Identifier const& _node) const return ret; } +Json AsmJsonConverter::operator()(BuiltinName const& _node) const +{ + // represents BuiltinName also with YulIdentifier node type to avoid a breaking change in the JSON interface + Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIdentifier"); + ret["name"] = m_dialect.builtin(_node.handle).name; + return ret; +} + Json AsmJsonConverter::operator()(Assignment const& _node) const { yulAssert(_node.variableNames.size() >= 1, "Invalid assignment syntax"); @@ -96,7 +106,7 @@ Json AsmJsonConverter::operator()(Assignment const& _node) const Json AsmJsonConverter::operator()(FunctionCall const& _node) const { Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionCall"); - ret["functionName"] = (*this)(_node.functionName); + ret["functionName"] = std::visit(*this, _node.functionName); ret["arguments"] = vectorOfVariantsToJson(_node.arguments); return ret; } diff --git a/libyul/AsmJsonConverter.h b/libyul/AsmJsonConverter.h index 75e3400b7..458142e29 100644 --- a/libyul/AsmJsonConverter.h +++ b/libyul/AsmJsonConverter.h @@ -43,12 +43,14 @@ class AsmJsonConverter: public boost::static_visitor public: /// Create a converter to JSON for any block of inline assembly /// @a _sourceIndex to be used to abbreviate source name in the source locations - explicit AsmJsonConverter(Dialect const&, std::optional _sourceIndex): m_sourceIndex(_sourceIndex) {} + AsmJsonConverter(Dialect const& _dialect, std::optional _sourceIndex): + m_dialect(_dialect), m_sourceIndex(_sourceIndex) {} Json operator()(Block const& _node) const; Json operator()(NameWithDebugData const& _node) const; Json operator()(Literal const& _node) const; Json operator()(Identifier const& _node) const; + Json operator()(BuiltinName const& _node) const; Json operator()(Assignment const& _node) const; Json operator()(VariableDeclaration const& _node) const; Json operator()(FunctionDefinition const& _node) const; @@ -68,6 +70,7 @@ class AsmJsonConverter: public boost::static_visitor template Json vectorOfVariantsToJson(std::vector const& vec) const; + Dialect const& m_dialect; std::optional const m_sourceIndex; }; diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index 692169fd2..a937be62f 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -23,7 +23,9 @@ */ #include + #include +#include #include #include @@ -255,7 +257,16 @@ FunctionCall AsmJsonImporter::createFunctionCall(Json const& _node) for (auto const& var: member(_node, "arguments")) functionCall.arguments.emplace_back(createExpression(var)); - functionCall.functionName = createIdentifier(member(_node, "functionName")); + auto const functionNameNode = member(_node, "functionName"); + auto const name = member(functionNameNode, "name").get(); + if (std::optional builtinHandle = m_dialect.findBuiltin(name)) + { + auto builtin = createAsmNode(functionNameNode); + builtin.handle = *builtinHandle; + functionCall.functionName = builtin; + } + else + functionCall.functionName = createIdentifier(functionNameNode); return functionCall; } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index baef6a3c5..66ac22a08 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -405,7 +405,7 @@ Statement Parser::parseStatement() // Options left: // Expression/FunctionCall // Assignment - std::variant elementary(parseLiteralOrIdentifier()); + std::variant elementary(parseLiteralOrIdentifier()); switch (currentToken()) { @@ -420,35 +420,47 @@ Statement Parser::parseStatement() Assignment assignment; assignment.debugData = debugDataOf(elementary); - while (true) + bool foundListEnd = false; + do { - if (!std::holds_alternative(elementary)) - { - auto const token = currentToken() == Token::Comma ? "," : ":="; - - fatalParserError( - 2856_error, - std::string("Variable name must precede \"") + - token + - "\"" + - (currentToken() == Token::Comma ? " in multiple assignment." : " in assignment.") - ); - } - - auto const& identifier = std::get(elementary); - - if (m_dialect.findBuiltin(identifier.name.str())) - fatalParserError(6272_error, "Cannot assign to builtin function \"" + identifier.name.str() + "\"."); - - assignment.variableNames.emplace_back(identifier); - - if (currentToken() != Token::Comma) - break; - - expectToken(Token::Comma); - - elementary = parseLiteralOrIdentifier(); - } + std::visit(GenericVisitor{ + [&](Literal const&) + { + auto const token = currentToken() == Token::Comma ? "," : ":="; + + fatalParserError( + 2856_error, + std::string("Variable name must precede \"") + + token + + "\"" + + (currentToken() == Token::Comma ? " in multiple assignment." : " in assignment.") + ); + }, + [&](BuiltinName const& _builtin) + { + fatalParserError( + 6272_error, + fmt::format( + "Cannot assign to builtin function \"{}\".", + m_dialect.builtin(_builtin.handle).name + ) + ); + }, + [&](Identifier const& _identifier) + { + assignment.variableNames.emplace_back(_identifier); + + if (currentToken() != Token::Comma) + foundListEnd = true; + else + { + expectToken(Token::Comma); + elementary = parseLiteralOrIdentifier(); + } + } + }, elementary); + + } while (!foundListEnd); expectToken(Token::AssemblyAssign); @@ -475,7 +487,7 @@ Case Parser::parseCase() else if (currentToken() == Token::Case) { advance(); - std::variant literal = parseLiteralOrIdentifier(); + std::variant literal = parseLiteralOrIdentifier(); if (!std::holds_alternative(literal)) fatalParserError(4805_error, "Literal expected."); _case.value = std::make_unique(std::get(std::move(literal))); @@ -514,20 +526,25 @@ Expression Parser::parseExpression(bool _unlimitedLiteralArgument) { RecursionGuard recursionGuard(*this); - std::variant operation = parseLiteralOrIdentifier(_unlimitedLiteralArgument); + std::variant operation = parseLiteralOrIdentifier(_unlimitedLiteralArgument); return visit(GenericVisitor{ [&](Identifier& _identifier) -> Expression { if (currentToken() == Token::LParen) return parseCall(std::move(operation)); - if (m_dialect.findBuiltin(_identifier.name.str())) - fatalParserError( - 7104_error, - nativeLocationOf(_identifier), - "Builtin function \"" + _identifier.name.str() + "\" must be called." - ); return std::move(_identifier); }, + [&](BuiltinName& _builtin) -> Expression + { + if (currentToken() == Token::LParen) + return parseCall(std::move(operation)); + fatalParserError( + 7104_error, + nativeLocationOf(_builtin), + "Builtin function \"" + m_dialect.builtin(_builtin.handle).name + "\" must be called." + ); + unreachable(); + }, [&](Literal& _literal) -> Expression { return std::move(_literal); @@ -535,16 +552,20 @@ Expression Parser::parseExpression(bool _unlimitedLiteralArgument) }, operation); } -std::variant Parser::parseLiteralOrIdentifier(bool _unlimitedLiteralArgument) +std::variant Parser::parseLiteralOrIdentifier(bool _unlimitedLiteralArgument) { RecursionGuard recursionGuard(*this); switch (currentToken()) { case Token::Identifier: { - Identifier identifier{createDebugData(), YulName{currentLiteral()}}; + std::variant literalOrIdentifier; + if (std::optional const builtinHandle = m_dialect.findBuiltin(currentLiteral())) + literalOrIdentifier = BuiltinName{createDebugData(), *builtinHandle}; + else + literalOrIdentifier = Identifier{createDebugData(), YulName{currentLiteral()}}; advance(); - return identifier; + return literalOrIdentifier; } case Token::StringLiteral: case Token::HexStringLiteral: @@ -671,36 +692,45 @@ FunctionDefinition Parser::parseFunctionDefinition() return funDef; } -FunctionCall Parser::parseCall(std::variant&& _initialOp) +FunctionCall Parser::parseCall(std::variant&& _initialOp) { RecursionGuard recursionGuard(*this); - if (!std::holds_alternative(_initialOp)) - fatalParserError(9980_error, "Function name expected."); - - FunctionCall ret; - ret.functionName = std::move(std::get(_initialOp)); - ret.debugData = ret.functionName.debugData; - auto const isUnlimitedLiteralArgument = [handle=m_dialect.findBuiltin(ret.functionName.name.str()), this](size_t const index) { - if (!handle) - return false; - auto const& function = m_dialect.builtin(*handle); - return index < function.literalArguments.size() && function.literalArgument(index).has_value(); - }; + std::function isUnlimitedLiteralArgument = [](size_t) -> bool { return false; }; + FunctionCall functionCall; + std::visit(GenericVisitor{ + [&](Literal const&) { fatalParserError(9980_error, "Function name expected."); }, + [&](Identifier const& _identifier) + { + functionCall.debugData = _identifier.debugData; + functionCall.functionName = _identifier; + }, + [&](BuiltinName const& _builtin) + { + isUnlimitedLiteralArgument = [builtinFunction=m_dialect.builtin(_builtin.handle)](size_t _index) { + if (_index < builtinFunction.literalArguments.size()) + return builtinFunction.literalArgument(_index).has_value(); + return false; + }; + functionCall.debugData = _builtin.debugData; + functionCall.functionName = _builtin; + } + }, _initialOp); + size_t argumentIndex {0}; expectToken(Token::LParen); if (currentToken() != Token::RParen) { - ret.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); + functionCall.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); while (currentToken() != Token::RParen) { expectToken(Token::Comma); - ret.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); + functionCall.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); } } - updateLocationEndFrom(ret.debugData, currentLocation()); + updateLocationEndFrom(functionCall.debugData, currentLocation()); expectToken(Token::RParen); - return ret; + return functionCall; } NameWithDebugData Parser::parseNameWithDebugData() diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index d4616a2a9..b546e179f 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -141,10 +141,10 @@ class Parser: public langutil::ParserBase Expression parseExpression(bool _unlimitedLiteralArgument = false); /// Parses an elementary operation, i.e. a literal, identifier, instruction or /// builtin function call (only the name). - std::variant parseLiteralOrIdentifier(bool _unlimitedLiteralArgument = false); + std::variant parseLiteralOrIdentifier(bool _unlimitedLiteralArgument = false); VariableDeclaration parseVariableDeclaration(); FunctionDefinition parseFunctionDefinition(); - FunctionCall parseCall(std::variant&& _initialOp); + FunctionCall parseCall(std::variant&& _index); NameWithDebugData parseNameWithDebugData(); YulName expectAsmIdentifier(); void raiseUnsupportedTypesError(langutil::SourceLocation const& _location) const; diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 5ba190149..a3f7b4ca2 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -77,6 +78,11 @@ std::string AsmPrinter::operator()(Identifier const& _identifier) return formatDebugData(_identifier) + _identifier.name.str(); } +std::string AsmPrinter::operator()(BuiltinName const& _builtin) +{ + return formatDebugData(_builtin) + m_dialect.builtin(_builtin.handle).name; +} + std::string AsmPrinter::operator()(ExpressionStatement const& _statement) { std::string const locationComment = formatDebugData(_statement); @@ -145,7 +151,7 @@ std::string AsmPrinter::operator()(FunctionDefinition const& _functionDefinition std::string AsmPrinter::operator()(FunctionCall const& _functionCall) { std::string const locationComment = formatDebugData(_functionCall); - std::string const functionName = (*this)(_functionCall.functionName); + std::string const functionName = std::visit(*this, _functionCall.functionName); return locationComment + functionName + "(" + diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 6b63c8638..d889d83f8 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -54,11 +54,12 @@ class AsmPrinter ); explicit AsmPrinter( - Dialect const&, + Dialect const& _dialect, std::optional>> const& _sourceIndexToName = {}, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ): + m_dialect(_dialect), m_debugInfoSelection(_debugInfoSelection), m_soliditySourceProvider(_soliditySourceProvider) { @@ -69,6 +70,7 @@ class AsmPrinter std::string operator()(Literal const& _literal); std::string operator()(Identifier const& _identifier); + std::string operator()(BuiltinName const& _builtin); std::string operator()(ExpressionStatement const& _expr); std::string operator()(Assignment const& _assignment); std::string operator()(VariableDeclaration const& _variableDeclaration); @@ -99,6 +101,7 @@ class AsmPrinter return formatDebugData(_node.debugData, !isExpression); } + Dialect const& m_dialect; std::map m_nameToSourceIndex; langutil::SourceLocation m_lastLocation = {}; langutil::DebugInfoSelection m_debugInfoSelection = {}; diff --git a/libyul/ControlFlowSideEffectsCollector.cpp b/libyul/ControlFlowSideEffectsCollector.cpp index 2694eef1c..28089b029 100644 --- a/libyul/ControlFlowSideEffectsCollector.cpp +++ b/libyul/ControlFlowSideEffectsCollector.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -271,8 +272,8 @@ ControlFlowNode const* ControlFlowSideEffectsCollector::nextProcessableNode(Func ControlFlowSideEffects const& ControlFlowSideEffectsCollector::sideEffects(FunctionCall const& _call) const { - if (std::optional builtinHandle = m_dialect.findBuiltin(_call.functionName.name.str())) - return m_dialect.builtin(*builtinHandle).controlFlowSideEffects; + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_call.functionName, m_dialect)) + return builtin->controlFlowSideEffects; else return m_functionSideEffects.at(m_functionReferences.at(&_call)); } diff --git a/libyul/FunctionReferenceResolver.cpp b/libyul/FunctionReferenceResolver.cpp index 99e83c213..bf3f536a4 100644 --- a/libyul/FunctionReferenceResolver.cpp +++ b/libyul/FunctionReferenceResolver.cpp @@ -34,15 +34,17 @@ FunctionReferenceResolver::FunctionReferenceResolver(Block const& _ast) void FunctionReferenceResolver::operator()(FunctionCall const& _functionCall) { - for (auto&& scope: m_scopes | ranges::views::reverse) - if (FunctionDefinition const** function = util::valueOrNullptr(scope, _functionCall.functionName.name)) + if (!isBuiltinFunctionCall(_functionCall)) + for (auto&& scope: m_scopes | ranges::views::reverse) { - m_functionReferences[&_functionCall] = *function; - break; + yulAssert(std::holds_alternative(_functionCall.functionName)); + if (FunctionDefinition const** function = util::valueOrNullptr(scope, std::get(_functionCall.functionName).name)) + { + m_functionReferences[&_functionCall] = *function; + break; + } } - // If we did not find anything, it was a builtin call. - ASTWalker::operator()(_functionCall); } diff --git a/libyul/Utilities.cpp b/libyul/Utilities.cpp index dd32d6a60..e7caf1b2d 100644 --- a/libyul/Utilities.cpp +++ b/libyul/Utilities.cpp @@ -269,3 +269,12 @@ BuiltinFunctionForEVM const* yul::resolveBuiltinFunctionForEVM(FunctionName cons return std::visit(visitor, _functionName); } +FunctionHandle yul::functionNameToHandle(FunctionName const& _functionName) +{ + GenericVisitor visitor{ + [&](Identifier const& _identifier) -> FunctionHandle { return _identifier.name; }, + [&](BuiltinName const& _builtin) -> FunctionHandle { return _builtin.handle; } + }; + return std::visit(visitor, _functionName); +} + diff --git a/libyul/Utilities.h b/libyul/Utilities.h index 2341ee62a..a4a558a85 100644 --- a/libyul/Utilities.h +++ b/libyul/Utilities.h @@ -92,5 +92,6 @@ std::string_view resolveFunctionName(FunctionName const& _functionName, Dialect BuiltinFunction const* resolveBuiltinFunction(FunctionName const& _functionName, Dialect const& _dialect); BuiltinFunctionForEVM const* resolveBuiltinFunctionForEVM(FunctionName const& _functionName, EVMDialect const& _dialect); +FunctionHandle functionNameToHandle(FunctionName const& _functionName); } diff --git a/libyul/backends/evm/ConstantOptimiser.cpp b/libyul/backends/evm/ConstantOptimiser.cpp index 0ea8f4e5a..d7aed27c3 100644 --- a/libyul/backends/evm/ConstantOptimiser.cpp +++ b/libyul/backends/evm/ConstantOptimiser.cpp @@ -74,11 +74,10 @@ struct MiniEVMInterpreter u256 operator()(FunctionCall const& _funCall) { - std::optional funHandle = m_dialect.findBuiltin(_funCall.functionName.name.str()); - yulAssert(funHandle, "Expected builtin function."); - BuiltinFunctionForEVM const& fun = m_dialect.builtin(*funHandle); - yulAssert(fun.instruction, "Expected EVM instruction."); - return eval(*fun.instruction, _funCall.arguments); + BuiltinFunctionForEVM const* builtin = resolveBuiltinFunctionForEVM(_funCall.functionName, m_dialect); + yulAssert(builtin, "Expected builtin function."); + yulAssert(builtin->instruction, "Expected EVM instruction."); + return eval(*builtin->instruction, _funCall.arguments); } u256 operator()(Literal const& _literal) { @@ -126,11 +125,20 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu if (m_cache.count(_value)) return m_cache.at(_value); + yulAssert(m_dialect.auxiliaryBuiltinHandles().not_); + yulAssert(m_dialect.auxiliaryBuiltinHandles().shl); + yulAssert(m_dialect.auxiliaryBuiltinHandles().exp); + yulAssert(m_dialect.auxiliaryBuiltinHandles().mul); + yulAssert(m_dialect.auxiliaryBuiltinHandles().add); + yulAssert(m_dialect.auxiliaryBuiltinHandles().sub); + + auto const& auxHandles = m_dialect.auxiliaryBuiltinHandles(); + Representation routine = represent(_value); if (numberEncodingSize(~_value) < numberEncodingSize(_value)) // Negated is shorter to represent - routine = min(std::move(routine), represent("not"_yulname, findRepresentation(~_value))); + routine = min(std::move(routine), represent(*auxHandles.not_, findRepresentation(~_value))); // Decompose value into a * 2**k + b where abs(b) << 2**k for (unsigned bits = 255; bits > 8 && m_maxSteps > 0; --bits) @@ -153,21 +161,21 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu continue; Representation newRoutine; if (m_dialect.evmVersion().hasBitwiseShifting()) - newRoutine = represent("shl"_yulname, represent(bits), findRepresentation(upperPart)); + newRoutine = represent(*auxHandles.shl, represent(bits), findRepresentation(upperPart)); else { - newRoutine = represent("exp"_yulname, represent(2), represent(bits)); + newRoutine = represent(*auxHandles.exp, represent(2), represent(bits)); if (upperPart != 1) - newRoutine = represent("mul"_yulname, findRepresentation(upperPart), newRoutine); + newRoutine = represent(*auxHandles.mul, findRepresentation(upperPart), newRoutine); } if (newRoutine.cost >= routine.cost) continue; if (lowerPart > 0) - newRoutine = represent("add"_yulname, newRoutine, findRepresentation(u256(abs(lowerPart)))); + newRoutine = represent(*auxHandles.add, newRoutine, findRepresentation(u256(abs(lowerPart)))); else if (lowerPart < 0) - newRoutine = represent("sub"_yulname, newRoutine, findRepresentation(u256(abs(lowerPart)))); + newRoutine = represent(*auxHandles.sub, newRoutine, findRepresentation(u256(abs(lowerPart)))); if (m_maxSteps > 0) m_maxSteps--; @@ -186,24 +194,22 @@ Representation RepresentationFinder::represent(u256 const& _value) const } Representation RepresentationFinder::represent( - YulName _instruction, + BuiltinHandle const& _instruction, Representation const& _argument ) const { Representation repr; repr.expression = std::make_unique(FunctionCall{ m_debugData, - Identifier{m_debugData, _instruction}, + BuiltinName{m_debugData, _instruction}, {ASTCopier{}.translate(*_argument.expression)} }); - repr.cost = _argument.cost + m_meter.instructionCosts( - *m_dialect.builtin(*m_dialect.findBuiltin(_instruction.str())).instruction - ); + repr.cost = _argument.cost + m_meter.instructionCosts(*m_dialect.builtin(_instruction).instruction); return repr; } Representation RepresentationFinder::represent( - YulName _instruction, + BuiltinHandle const& _instruction, Representation const& _arg1, Representation const& _arg2 ) const @@ -211,11 +217,10 @@ Representation RepresentationFinder::represent( Representation repr; repr.expression = std::make_unique(FunctionCall{ m_debugData, - Identifier{m_debugData, _instruction}, + BuiltinName{m_debugData, _instruction}, {ASTCopier{}.translate(*_arg1.expression), ASTCopier{}.translate(*_arg2.expression)} }); - repr.cost = m_meter.instructionCosts( - *m_dialect.builtin(*m_dialect.findBuiltin(_instruction.str())).instruction) + _arg1.cost + _arg2.cost; + repr.cost = m_meter.instructionCosts(*m_dialect.builtin(_instruction).instruction) + _arg1.cost + _arg2.cost; return repr; } diff --git a/libyul/backends/evm/ConstantOptimiser.h b/libyul/backends/evm/ConstantOptimiser.h index 35d7dfa43..5e4b2002b 100644 --- a/libyul/backends/evm/ConstantOptimiser.h +++ b/libyul/backends/evm/ConstantOptimiser.h @@ -93,8 +93,8 @@ class RepresentationFinder Representation const& findRepresentation(u256 const& _value); Representation represent(u256 const& _value) const; - Representation represent(YulName _instruction, Representation const& _arg) const; - Representation represent(YulName _instruction, Representation const& _arg1, Representation const& _arg2) const; + Representation represent(BuiltinHandle const& _instruction, Representation const& _arg) const; + Representation represent(BuiltinHandle const& _instruction, Representation const& _arg1, Representation const& _arg2) const; Representation min(Representation _a, Representation _b); diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index e92515e98..990456732 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -524,29 +524,29 @@ Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _cal Stack const* output = nullptr; bool canContinue = true; - if (std::optional const& builtinHandle = m_dialect.findBuiltin(_call.functionName.name.str())) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_call.functionName, m_dialect)) { - auto const& builtin = m_dialect.builtin(*builtinHandle); Stack inputs; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) - if (!builtin.literalArgument(idx).has_value()) + if (!builtin->literalArgument(idx).has_value()) inputs.emplace_back(std::visit(*this, arg)); - CFG::BuiltinCall builtinCall{_call.debugData, builtin, _call, inputs.size()}; + CFG::BuiltinCall builtinCall{_call.debugData, *builtin, _call, inputs.size()}; output = &m_currentBlock->operations.emplace_back(CFG::Operation{ // input std::move(inputs), // output - ranges::views::iota(0u, builtin.numReturns) | ranges::views::transform([&](size_t _i) { + ranges::views::iota(0u, builtin->numReturns) | ranges::views::transform([&](size_t _i) { return TemporarySlot{_call, _i}; }) | ranges::to, // operation std::move(builtinCall) }).output; - canContinue = builtin.controlFlowSideEffects.canContinue; + canContinue = builtin->controlFlowSideEffects.canContinue; } else { - Scope::Function const& function = lookupFunction(_call.functionName.name); + yulAssert(std::holds_alternative(_call.functionName)); + Scope::Function const& function = lookupFunction(std::get(_call.functionName).name); canContinue = m_graph.functionInfo.at(&function).canContinue; Stack inputs; // For EOF (m_simulateFunctionsWithJumps == false) we do not have to put return label on stack. diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index e354649e7..f77e4e047 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -230,22 +230,22 @@ void CodeTransform::operator()(FunctionCall const& _call) yulAssert(m_scope, ""); m_assembly.setSourceLocation(originLocationOf(_call)); - if (std::optional builtinHandle = m_dialect.findBuiltin(_call.functionName.name.str())) + if (BuiltinFunctionForEVM const* builtin = resolveBuiltinFunctionForEVM(_call.functionName, m_dialect)) { - BuiltinFunctionForEVM const& builtin = m_dialect.builtin(*builtinHandle); for (auto&& [i, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) - if (!builtin.literalArgument(i)) + if (!builtin->literalArgument(i)) visitExpression(arg); m_assembly.setSourceLocation(originLocationOf(_call)); - builtin.generateCode(_call, m_assembly, m_builtinContext); + builtin->generateCode(_call, m_assembly, m_builtinContext); } else { + yulAssert(std::holds_alternative(_call.functionName)); AbstractAssembly::LabelID returnLabel = m_assembly.newLabelId(); m_assembly.appendLabelReference(returnLabel); Scope::Function* function = nullptr; - yulAssert(m_scope->lookup(_call.functionName.name, GenericVisitor{ + yulAssert(m_scope->lookup(std::get(_call.functionName).name, GenericVisitor{ [](Scope::Variable&) { yulAssert(false, "Expected function name."); }, [&](Scope::Function& _function) { function = &_function; } }), "Function name not found."); diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 161f92336..c73a9a794 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -476,14 +476,12 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, std::optional m_storageLoadFunction = findBuiltin("sload"); m_hashFunction = findBuiltin("keccak256"); - m_discardFunction = findBuiltin("pop"); - m_equalityFunction = findBuiltin("eq"); - m_booleanNegationFunction = findBuiltin("iszero"); - m_memoryStoreFunction = findBuiltin("mstore"); - m_memoryLoadFunction = findBuiltin("mload"); - m_storageStoreFunction = findBuiltin("sstore"); - m_storageLoadFunction = findBuiltin("sload"); - m_hashFunction = findBuiltin("keccak256"); + m_auxiliaryBuiltinHandles.add = EVMDialect::findBuiltin("add"); + m_auxiliaryBuiltinHandles.exp = EVMDialect::findBuiltin("exp"); + m_auxiliaryBuiltinHandles.mul = EVMDialect::findBuiltin("mul"); + m_auxiliaryBuiltinHandles.not_ = EVMDialect::findBuiltin("not"); + m_auxiliaryBuiltinHandles.shl = EVMDialect::findBuiltin("shl"); + m_auxiliaryBuiltinHandles.sub = EVMDialect::findBuiltin("sub"); } std::optional EVMDialect::findBuiltin(std::string_view _name) const diff --git a/libyul/backends/evm/EVMMetrics.cpp b/libyul/backends/evm/EVMMetrics.cpp index 64ff94cf6..57593fdc2 100644 --- a/libyul/backends/evm/EVMMetrics.cpp +++ b/libyul/backends/evm/EVMMetrics.cpp @@ -76,10 +76,10 @@ std::pair GasMeterVisitor::instructionCosts( void GasMeterVisitor::operator()(FunctionCall const& _funCall) { ASTWalker::operator()(_funCall); - if (std::optional handle = m_dialect.findBuiltin(_funCall.functionName.name.str())) - if (std::optional const& instruction = m_dialect.builtin(*handle).instruction) + if (BuiltinFunctionForEVM const* builtin = resolveBuiltinFunctionForEVM(_funCall.functionName, m_dialect)) + if (builtin->instruction) { - instructionCostsInternal(*instruction); + instructionCostsInternal(*builtin->instruction); return; } yulAssert(false, "Functions not implemented."); diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index a7ac67c3a..de1174ace 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -90,9 +90,11 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) ); if (!stackErrors.empty()) { + yulAssert(_object.dialect()); std::vector memoryGuardCalls = findFunctionCalls( _object.code()->root(), - "memoryguard"_yulname + "memoryguard", + *_object.dialect() ); auto stackError = stackErrors.front(); std::string msg = stackError.comment() ? *stackError.comment() : ""; diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 89a75019e..3a1b78e1e 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -73,7 +73,8 @@ std::vector OptimizedEVMCodeTransform::run( _useNamedLabelsForFunctions, *dfg, stackLayout, - !_dialect.eofVersion().has_value() + !_dialect.eofVersion().has_value(), + _dialect ); // Create initial entry layout. optimizedCodeTransform.createStackLayout(debugDataOf(*dfg->entry), stackLayout.blockInfos.at(dfg->entry).entryLayout); @@ -202,12 +203,14 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( UseNamedLabels _useNamedLabelsForFunctions, CFG const& _dfg, StackLayout const& _stackLayout, - bool _simulateFunctionsWithJumps + bool _simulateFunctionsWithJumps, + EVMDialect const& _dialect ): m_assembly(_assembly), m_builtinContext(_builtinContext), m_dfg(_dfg), m_stackLayout(_stackLayout), + m_dialect(_dialect), m_functionLabels(!_simulateFunctionsWithJumps ? decltype(m_functionLabels)() : [&](){ std::map functionLabels; std::set assignedFunctionNames; @@ -294,9 +297,9 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr YulName varNameDeep = slotVariableName(deepSlot); YulName varNameTop = slotVariableName(m_stack.back()); std::string msg = - "Cannot swap " + (varNameDeep.empty() ? "Slot " + stackSlotToString(deepSlot) : "Variable " + varNameDeep.str()) + - " with " + (varNameTop.empty() ? "Slot " + stackSlotToString(m_stack.back()) : "Variable " + varNameTop.str()) + - ": too deep in the stack by " + std::to_string(deficit) + " slots in " + stackToString(m_stack); + "Cannot swap " + (varNameDeep.empty() ? "Slot " + stackSlotToString(deepSlot, m_dialect) : "Variable " + varNameDeep.str()) + + " with " + (varNameTop.empty() ? "Slot " + stackSlotToString(m_stack.back(), m_dialect) : "Variable " + varNameTop.str()) + + ": too deep in the stack by " + std::to_string(deficit) + " slots in " + stackToString(m_stack, m_dialect); m_stackErrors.emplace_back(StackTooDeepError( m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulName{}, varNameDeep.empty() ? varNameTop : varNameDeep, @@ -324,8 +327,8 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr int deficit = static_cast(*depth - 15); YulName varName = slotVariableName(_slot); std::string msg = - (varName.empty() ? "Slot " + stackSlotToString(_slot) : "Variable " + varName.str()) - + " is " + std::to_string(*depth - 15) + " too deep in the stack " + stackToString(m_stack); + (varName.empty() ? "Slot " + stackSlotToString(_slot, m_dialect) : "Variable " + varName.str()) + + " is " + std::to_string(*depth - 15) + " too deep in the stack " + stackToString(m_stack, m_dialect); m_stackErrors.emplace_back(StackTooDeepError( m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulName{}, varName, diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.h b/libyul/backends/evm/OptimizedEVMCodeTransform.h index 2c072bcca..88ecc2967 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.h +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.h @@ -69,7 +69,8 @@ class OptimizedEVMCodeTransform UseNamedLabels _useNamedLabelsForFunctions, CFG const& _dfg, StackLayout const& _stackLayout, - bool _simulateFunctionsWithJumps + bool _simulateFunctionsWithJumps, + EVMDialect const& _dialect ); /// Assert that it is valid to transition from @a _currentStack to @a _desiredStack. @@ -102,6 +103,7 @@ class OptimizedEVMCodeTransform BuiltinContext& m_builtinContext; CFG const& m_dfg; StackLayout const& m_stackLayout; + EVMDialect const& m_dialect; Stack m_stack; std::map m_returnLabels; std::map m_blockLabels; diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index e7b3c9e6d..b47248dd5 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -342,19 +343,21 @@ void SSAControlFlowGraphBuilder::operator()(Switch const& _switch) } else { + std::optional equalityBuiltinHandle = m_dialect.equalityFunctionHandle(); + yulAssert(equalityBuiltinHandle); + auto makeValueCompare = [&](Case const& _case) { FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(FunctionCall{ debugDataOf(_case), - Identifier{{}, "eq"_yulname}, + BuiltinName{{}, *equalityBuiltinHandle}, {*_case.value /* skip second argument */ } }); auto outputValue = m_graph.newVariable(m_currentBlock); - std::optional builtinHandle = m_dialect.findBuiltin(ghostCall.functionName.name.str()); currentBlock().operations.emplace_back(SSACFG::Operation{ {outputValue}, SSACFG::BuiltinCall{ debugDataOf(_case), - m_dialect.builtin(*builtinHandle), + m_dialect.builtin(*equalityBuiltinHandle), ghostCall }, {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression} @@ -547,21 +550,21 @@ std::vector SSAControlFlowGraphBuilder::visitFunctionCall(Funct { bool canContinue = true; SSACFG::Operation operation = [&](){ - if (std::optional const& builtinHandle = m_dialect.findBuiltin(_call.functionName.name.str())) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_call.functionName, m_dialect)) { - auto const& builtinFunction = m_dialect.builtin(*builtinHandle); - SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData, builtinFunction, _call}, {}}; + SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData, *builtin, _call}, {}}; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) - if (!builtinFunction.literalArgument(idx).has_value()) + if (!builtin->literalArgument(idx).has_value()) result.inputs.emplace_back(std::visit(*this, arg)); - for (size_t i = 0; i < builtinFunction.numReturns; ++i) + for (size_t i = 0; i < builtin->numReturns; ++i) result.outputs.emplace_back(m_graph.newVariable(m_currentBlock)); - canContinue = builtinFunction.controlFlowSideEffects.canContinue; + canContinue = builtin->controlFlowSideEffects.canContinue; return result; } else { - Scope::Function const& function = lookupFunction(_call.functionName.name); + YulName const functionName{std::string(resolveFunctionName(_call.functionName, m_dialect))}; + Scope::Function const& function = lookupFunction(functionName); auto const* definition = findFunctionDefinition(&function); yulAssert(definition); canContinue = m_sideEffects.functionSideEffects().at(definition).canContinue; diff --git a/libyul/backends/evm/StackHelpers.h b/libyul/backends/evm/StackHelpers.h index dae4352a0..0fd238c40 100644 --- a/libyul/backends/evm/StackHelpers.h +++ b/libyul/backends/evm/StackHelpers.h @@ -20,6 +20,7 @@ #include #include +#include #include @@ -33,23 +34,23 @@ namespace solidity::yul { -inline std::string stackSlotToString(StackSlot const& _slot) +inline std::string stackSlotToString(StackSlot const& _slot, Dialect const& _dialect) { return std::visit(util::GenericVisitor{ - [](FunctionCallReturnLabelSlot const& _ret) -> std::string { return "RET[" + _ret.call.get().functionName.name.str() + "]"; }, + [&](FunctionCallReturnLabelSlot const& _ret) -> std::string { return "RET[" + std::string(resolveFunctionName(_ret.call.get().functionName, _dialect)) + "]"; }, [](FunctionReturnLabelSlot const&) -> std::string { return "RET"; }, [](VariableSlot const& _var) { return _var.variable.get().name.str(); }, [](LiteralSlot const& _lit) { return toCompactHexWithPrefix(_lit.value); }, - [](TemporarySlot const& _tmp) -> std::string { return "TMP[" + _tmp.call.get().functionName.name.str() + ", " + std::to_string(_tmp.index) + "]"; }, + [&](TemporarySlot const& _tmp) -> std::string { return "TMP[" + std::string(resolveFunctionName(_tmp.call.get().functionName, _dialect)) + ", " + std::to_string(_tmp.index) + "]"; }, [](JunkSlot const&) -> std::string { return "JUNK"; } }, _slot); } -inline std::string stackToString(Stack const& _stack) +inline std::string stackToString(Stack const& _stack, Dialect const& _dialect) { std::string result("[ "); for (auto const& slot: _stack) - result += stackSlotToString(slot) + ' '; + result += stackSlotToString(slot, _dialect) + ' '; result += ']'; return result; } diff --git a/libyul/optimiser/ASTCopier.cpp b/libyul/optimiser/ASTCopier.cpp index 269c7adee..9e85651ad 100644 --- a/libyul/optimiser/ASTCopier.cpp +++ b/libyul/optimiser/ASTCopier.cpp @@ -24,6 +24,7 @@ #include #include +#include using namespace solidity; using namespace solidity::yul; @@ -153,6 +154,15 @@ Case ASTCopier::translate(Case const& _case) return Case{_case.debugData, translate(_case.value), translate(_case.body)}; } +FunctionName ASTCopier::translate(FunctionName const& _functionName) +{ + GenericVisitor visitor{ + [&](Identifier const& _identifier) -> FunctionName { return translate(_identifier); }, + [](BuiltinName const& _builtin) -> FunctionName { return _builtin; } + }; + return std::visit(visitor, _functionName); +} + Identifier ASTCopier::translate(Identifier const& _identifier) { return Identifier{_identifier.debugData, translateIdentifier(_identifier.name)}; diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index 04b1c96cd..e1c3a16aa 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -100,6 +100,7 @@ class ASTCopier: public ExpressionCopier, public StatementCopier Case translate(Case const& _case); virtual Identifier translate(Identifier const& _identifier); Literal translate(Literal const& _literal); + FunctionName translate(FunctionName const& _functionName); NameWithDebugData translate(NameWithDebugData const& _typedName); virtual void enterScope(Block const&) { } diff --git a/libyul/optimiser/BlockHasher.cpp b/libyul/optimiser/BlockHasher.cpp index 5470558ce..2cc7a6648 100644 --- a/libyul/optimiser/BlockHasher.cpp +++ b/libyul/optimiser/BlockHasher.cpp @@ -23,6 +23,8 @@ #include #include +#include + using namespace solidity; using namespace solidity::yul; using namespace solidity::util; @@ -51,6 +53,25 @@ void ASTHasherBase::hashLiteral(solidity::yul::Literal const& _literal) hash8(_literal.value.unlimited()); } +void ASTHasherBase::hashFunctionCall(FunctionCall const& _funCall) +{ + hash64(compileTimeLiteralHash("FunctionCall")); + GenericVisitor visitor{ + [&](BuiltinName const& _builtin) + { + hash64(compileTimeLiteralHash("Builtin")); + hash64(_builtin.handle.id); + }, + [&](Identifier const& _identifier) + { + hash64(compileTimeLiteralHash("UserDefined")); + hash64(_identifier.name.hash()); + hash64(_funCall.arguments.size()); + } + }; + std::visit(visitor, _funCall.functionName); +} + std::map BlockHasher::run(Block const& _block) { std::map result; @@ -85,9 +106,7 @@ void BlockHasher::operator()(Identifier const& _identifier) void BlockHasher::operator()(FunctionCall const& _funCall) { - hash64(compileTimeLiteralHash("FunctionCall")); - hash64(_funCall.functionName.name.hash()); - hash64(_funCall.arguments.size()); + hashFunctionCall(_funCall); ASTWalker::operator()(_funCall); } @@ -218,8 +237,6 @@ void ExpressionHasher::operator()(Identifier const& _identifier) void ExpressionHasher::operator()(FunctionCall const& _funCall) { - hash64(compileTimeLiteralHash("FunctionCall")); - hash64(_funCall.functionName.name.hash()); - hash64(_funCall.arguments.size()); + hashFunctionCall(_funCall); ASTWalker::operator()(_funCall); } diff --git a/libyul/optimiser/BlockHasher.h b/libyul/optimiser/BlockHasher.h index 427161b3c..12c1c5e72 100644 --- a/libyul/optimiser/BlockHasher.h +++ b/libyul/optimiser/BlockHasher.h @@ -62,6 +62,7 @@ class ASTHasherBase: public HasherBase { protected: void hashLiteral(solidity::yul::Literal const& _literal); + void hashFunctionCall(FunctionCall const& _functionCall); }; /** diff --git a/libyul/optimiser/CallGraphGenerator.cpp b/libyul/optimiser/CallGraphGenerator.cpp index f457f5583..9b69835dc 100644 --- a/libyul/optimiser/CallGraphGenerator.cpp +++ b/libyul/optimiser/CallGraphGenerator.cpp @@ -23,6 +23,8 @@ #include #include +#include + #include using namespace solidity; @@ -35,11 +37,11 @@ namespace struct CallGraphCycleFinder { CallGraph const& callGraph; - std::set containedInCycle{}; - std::set visited{}; - std::vector currentPath{}; + std::set containedInCycle{}; + std::set visited{}; + std::vector currentPath{}; - void visit(YulName _function) + void visit(FunctionHandle const& _function) { if (visited.count(_function)) return; @@ -61,7 +63,7 @@ struct CallGraphCycleFinder }; } -std::set CallGraph::recursiveFunctions() const +std::set CallGraph::recursiveFunctions() const { CallGraphCycleFinder cycleFinder{*this}; // Visiting the root only is not enough, since there may be disconnected recursive functions. @@ -80,8 +82,12 @@ CallGraph CallGraphGenerator::callGraph(Block const& _ast) void CallGraphGenerator::operator()(FunctionCall const& _functionCall) { auto& functionCalls = m_callGraph.functionCalls[m_currentFunction]; - if (!util::contains(functionCalls, _functionCall.functionName.name)) - functionCalls.emplace_back(_functionCall.functionName.name); + FunctionHandle identifier = std::visit(GenericVisitor{ + [](BuiltinName const& _builtin) -> FunctionHandle { return _builtin.handle; }, + [](Identifier const& _identifier) -> FunctionHandle { return _identifier.name; }, + }, _functionCall.functionName); + if (!util::contains(functionCalls, identifier)) + functionCalls.emplace_back(identifier); ASTWalker::operator()(_functionCall); } diff --git a/libyul/optimiser/CallGraphGenerator.h b/libyul/optimiser/CallGraphGenerator.h index 23e9a2511..722cbba4a 100644 --- a/libyul/optimiser/CallGraphGenerator.h +++ b/libyul/optimiser/CallGraphGenerator.h @@ -22,9 +22,9 @@ #pragma once #include +#include #include -#include #include namespace solidity::yul @@ -32,12 +32,13 @@ namespace solidity::yul struct CallGraph { - std::map> functionCalls; + /// Map function definition name -> function name + std::map> functionCalls; std::set functionsWithLoops; /// @returns the set of functions contained in cycles in the call graph, i.e. /// functions that are part of a (mutual) recursion. /// Note that this does not include functions that merely call recursive functions. - std::set recursiveFunctions() const; + std::set recursiveFunctions() const; }; /** diff --git a/libyul/optimiser/CircularReferencesPruner.cpp b/libyul/optimiser/CircularReferencesPruner.cpp index a34f3f4e2..d238f8da2 100644 --- a/libyul/optimiser/CircularReferencesPruner.cpp +++ b/libyul/optimiser/CircularReferencesPruner.cpp @@ -57,7 +57,7 @@ std::set CircularReferencesPruner::functionsCalledFromOutermostContext( [&_callGraph](YulName _function, auto&& _addChild) { if (_callGraph.functionCalls.count(_function)) for (auto const& callee: _callGraph.functionCalls.at(_function)) - if (_callGraph.functionCalls.count(callee)) - _addChild(callee); + if (std::holds_alternative(callee) && _callGraph.functionCalls.count(std::get(callee))) + _addChild(std::get(callee)); }).visited; } diff --git a/libyul/optimiser/CommonSubexpressionEliminator.cpp b/libyul/optimiser/CommonSubexpressionEliminator.cpp index f74568421..87a14d259 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.cpp +++ b/libyul/optimiser/CommonSubexpressionEliminator.cpp @@ -46,7 +46,7 @@ void CommonSubexpressionEliminator::run(OptimiserStepContext& _context, Block& _ CommonSubexpressionEliminator::CommonSubexpressionEliminator( Dialect const& _dialect, - std::map _functionSideEffects + std::map _functionSideEffects ): DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore, std::move(_functionSideEffects)) { @@ -72,14 +72,13 @@ void CommonSubexpressionEliminator::visit(Expression& _e) { FunctionCall& funCall = std::get(_e); - if (std::optional builtinHandle = m_dialect.findBuiltin(funCall.functionName.name.str())) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(funCall.functionName, m_dialect)) { - BuiltinFunction const& builtin = m_dialect.builtin(*builtinHandle); for (size_t i = funCall.arguments.size(); i > 0; i--) // We should not modify function arguments that have to be literals // Note that replacing the function call entirely is fine, // if the function call is movable. - if (!builtin.literalArgument(i - 1)) + if (!builtin->literalArgument(i - 1)) visit(funCall.arguments[i - 1]); descend = false; diff --git a/libyul/optimiser/CommonSubexpressionEliminator.h b/libyul/optimiser/CommonSubexpressionEliminator.h index d7dc42596..35f8168eb 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.h +++ b/libyul/optimiser/CommonSubexpressionEliminator.h @@ -53,7 +53,7 @@ class CommonSubexpressionEliminator: public DataFlowAnalyzer private: CommonSubexpressionEliminator( Dialect const& _dialect, - std::map _functionSideEffects + std::map _functionSideEffects ); protected: diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index a9a8282a6..53afb5e77 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -37,13 +37,13 @@ namespace ExpressionStatement makeDiscardCall( langutil::DebugData::ConstPtr const& _debugData, - BuiltinFunction const& _discardFunction, + BuiltinHandle const& _discardFunction, Expression&& _expression ) { return {_debugData, FunctionCall{ _debugData, - Identifier{_debugData, YulName{_discardFunction.name}}, + BuiltinName{_debugData, _discardFunction}, {std::move(_expression)} }}; } @@ -141,7 +141,7 @@ void ControlFlowSimplifier::simplify(std::vector& _statements) OptionalStatements s = std::vector{}; s->emplace_back(makeDiscardCall( _ifStmt.debugData, - m_dialect.builtin(*m_dialect.discardFunctionHandle()), + *m_dialect.discardFunctionHandle(), std::move(*_ifStmt.condition) )); return s; @@ -184,7 +184,7 @@ OptionalStatements ControlFlowSimplifier::reduceNoCaseSwitch(Switch& _switchStmt return make_vector(makeDiscardCall( debugDataOf(*_switchStmt.expression), - m_dialect.builtin(*discardFunctionHandle), + *discardFunctionHandle, std::move(*_switchStmt.expression) )); } @@ -199,11 +199,12 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch { if (!m_dialect.equalityFunctionHandle()) return {}; + BuiltinName const builtinName{debugData, *m_dialect.equalityFunctionHandle()}; return make_vector(If{ std::move(_switchStmt.debugData), std::make_unique(FunctionCall{ debugData, - Identifier{debugData, YulName{m_dialect.builtin(*m_dialect.equalityFunctionHandle()).name}}, + builtinName, {std::move(*switchCase.value), std::move(*_switchStmt.expression)} }), std::move(switchCase.body) @@ -217,7 +218,7 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch return make_vector( makeDiscardCall( debugData, - m_dialect.builtin(*m_dialect.discardFunctionHandle()), + *m_dialect.discardFunctionHandle(), std::move(*_switchStmt.expression) ), std::move(switchCase.body) diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 8b3282888..ac08fb0be 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -45,23 +45,19 @@ using namespace solidity::yul; DataFlowAnalyzer::DataFlowAnalyzer( Dialect const& _dialect, MemoryAndStorage _analyzeStores, - std::map _functionSideEffects + std::map _functionSideEffects ): m_dialect(_dialect), m_functionSideEffects(std::move(_functionSideEffects)), - m_knowledgeBase([this](YulName _var) { return variableValue(_var); }), + m_knowledgeBase([this](YulName _var) { return variableValue(_var); }, _dialect), m_analyzeStores(_analyzeStores == MemoryAndStorage::Analyze) { if (m_analyzeStores) { - if (auto const& builtinHandle = _dialect.memoryStoreFunctionHandle()) - m_storeFunctionName[static_cast(StoreLoadLocation::Memory)] = YulName{_dialect.builtin(*builtinHandle).name}; - if (auto const& builtinHandle = _dialect.memoryLoadFunctionHandle()) - m_loadFunctionName[static_cast(StoreLoadLocation::Memory)] = YulName{_dialect.builtin(*builtinHandle).name}; - if (auto const& builtinHandle = _dialect.storageStoreFunctionHandle()) - m_storeFunctionName[static_cast(StoreLoadLocation::Storage)] = YulName{_dialect.builtin(*builtinHandle).name}; - if (auto const& builtinHandle = _dialect.storageLoadFunctionHandle()) - m_loadFunctionName[static_cast(StoreLoadLocation::Storage)] = YulName{_dialect.builtin(*builtinHandle).name}; + m_storeFunctionName[static_cast(StoreLoadLocation::Memory)] = _dialect.memoryStoreFunctionHandle(); + m_loadFunctionName[static_cast(StoreLoadLocation::Memory)] = _dialect.memoryLoadFunctionHandle(); + m_storeFunctionName[static_cast(StoreLoadLocation::Storage)] = _dialect.storageStoreFunctionHandle(); + m_loadFunctionName[static_cast(StoreLoadLocation::Storage)] = _dialect.storageLoadFunctionHandle(); } } @@ -424,7 +420,10 @@ std::optional> DataFlowAnalyzer::isSimpleStore( ) const { if (FunctionCall const* funCall = std::get_if(&_statement.expression)) - if (funCall->functionName.name == m_storeFunctionName[static_cast(_location)]) + if ( + std::holds_alternative(funCall->functionName) && + std::get(funCall->functionName).handle == m_storeFunctionName[static_cast(_location)] + ) if (Identifier const* key = std::get_if(&funCall->arguments.front())) if (Identifier const* value = std::get_if(&funCall->arguments.back())) return std::make_pair(key->name, value->name); @@ -437,7 +436,10 @@ std::optional DataFlowAnalyzer::isSimpleLoad( ) const { if (FunctionCall const* funCall = std::get_if(&_expression)) - if (funCall->functionName.name == m_loadFunctionName[static_cast(_location)]) + if ( + std::holds_alternative(funCall->functionName) && + std::get(funCall->functionName).handle == m_loadFunctionName[static_cast(_location)] + ) if (Identifier const* key = std::get_if(&funCall->arguments.front())) return key->name; return {}; @@ -446,7 +448,10 @@ std::optional DataFlowAnalyzer::isSimpleLoad( std::optional> DataFlowAnalyzer::isKeccak(Expression const& _expression) const { if (FunctionCall const* funCall = std::get_if(&_expression)) - if (funCall->functionName.name.str() == m_dialect.builtin(*m_dialect.hashFunctionHandle()).name) + if ( + std::holds_alternative(funCall->functionName) && + std::get(funCall->functionName).handle == m_dialect.hashFunctionHandle() + ) if (Identifier const* start = std::get_if(&funCall->arguments.at(0))) if (Identifier const* length = std::get_if(&funCall->arguments.at(1))) return std::make_pair(start->name, length->name); diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index 5a4b199ca..7d0f78b53 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -89,7 +89,7 @@ class DataFlowAnalyzer: public ASTModifier explicit DataFlowAnalyzer( Dialect const& _dialect, MemoryAndStorage _analyzeStores, - std::map _functionSideEffects = {} + std::map _functionSideEffects = {} ); using ASTModifier::operator(); @@ -165,7 +165,7 @@ class DataFlowAnalyzer: public ASTModifier Dialect const& m_dialect; /// Side-effects of user-defined functions. Worst-case side-effects are assumed /// if this is not provided or the function is not found. - std::map m_functionSideEffects; + std::map m_functionSideEffects; private: struct Environment @@ -203,8 +203,8 @@ class DataFlowAnalyzer: public ASTModifier /// If true, analyzes memory and storage content via mload/mstore and sload/sstore. bool m_analyzeStores = true; - YulName m_storeFunctionName[static_cast(StoreLoadLocation::Last) + 1]; - YulName m_loadFunctionName[static_cast(StoreLoadLocation::Last) + 1]; + std::optional m_storeFunctionName[static_cast(StoreLoadLocation::Last) + 1]; + std::optional m_loadFunctionName[static_cast(StoreLoadLocation::Last) + 1]; /// Current nesting depth of loops. size_t m_loopDepth{0}; diff --git a/libyul/optimiser/EqualStoreEliminator.h b/libyul/optimiser/EqualStoreEliminator.h index a0b54c590..87f8cae16 100644 --- a/libyul/optimiser/EqualStoreEliminator.h +++ b/libyul/optimiser/EqualStoreEliminator.h @@ -45,7 +45,7 @@ class EqualStoreEliminator: public DataFlowAnalyzer private: EqualStoreEliminator( Dialect const& _dialect, - std::map _functionSideEffects + std::map _functionSideEffects ): DataFlowAnalyzer(_dialect, MemoryAndStorage::Analyze, std::move(_functionSideEffects)) {} diff --git a/libyul/optimiser/EquivalentFunctionCombiner.cpp b/libyul/optimiser/EquivalentFunctionCombiner.cpp index 10d15126e..bbbf039d5 100644 --- a/libyul/optimiser/EquivalentFunctionCombiner.cpp +++ b/libyul/optimiser/EquivalentFunctionCombiner.cpp @@ -33,8 +33,13 @@ void EquivalentFunctionCombiner::run(OptimiserStepContext&, Block& _ast) void EquivalentFunctionCombiner::operator()(FunctionCall& _funCall) { - auto it = m_duplicates.find(_funCall.functionName.name); - if (it != m_duplicates.end()) - _funCall.functionName.name = it->second->name; + if (!isBuiltinFunctionCall(_funCall)) + { + auto* identifier = std::get_if(&_funCall.functionName); + yulAssert(identifier); + auto it = m_duplicates.find(identifier->name); + if (it != m_duplicates.end()) + identifier->name = it->second->name; + } ASTModifier::operator()(_funCall); } diff --git a/libyul/optimiser/ExpressionInliner.cpp b/libyul/optimiser/ExpressionInliner.cpp index ab4bbcfa4..1dbd5ca98 100644 --- a/libyul/optimiser/ExpressionInliner.cpp +++ b/libyul/optimiser/ExpressionInliner.cpp @@ -29,6 +29,7 @@ #include #include +#include using namespace solidity; using namespace solidity::yul; @@ -52,9 +53,10 @@ void ExpressionInliner::visit(Expression& _expression) if (std::holds_alternative(_expression)) { FunctionCall& funCall = std::get(_expression); - if (!m_inlinableFunctions.count(funCall.functionName.name)) + YulString const functionName{std::string(resolveFunctionName(funCall.functionName, m_dialect))}; + if (!m_inlinableFunctions.count(functionName)) return; - FunctionDefinition const& fun = *m_inlinableFunctions.at(funCall.functionName.name); + FunctionDefinition const& fun = *m_inlinableFunctions.at(functionName); std::map substitutions; for (size_t i = 0; i < funCall.arguments.size(); i++) diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index 598d2e900..4aa7be1bb 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -46,10 +47,14 @@ void ExpressionSimplifier::visit(Expression& _expression) m_dialect, [this](YulName _var) { return variableValue(_var); } )) - _expression = match->action().toExpression(debugDataOf(_expression), evmVersionFromDialect(m_dialect)); + { + auto const* evmDialect = dynamic_cast(&m_dialect); + yulAssert(evmDialect); + _expression = match->action().toExpression(debugDataOf(_expression), *evmDialect); + } if (auto* functionCall = std::get_if(&_expression)) - if (std::optional instruction = toEVMInstruction(m_dialect, functionCall->functionName.name)) + if (std::optional instruction = toEVMInstruction(m_dialect, functionCall->functionName)) for (auto op: evmasm::SemanticInformation::readWriteOperations(*instruction)) if (op.startParameter && op.lengthParameter) { diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 71a0963d5..1bdaa552b 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -26,6 +26,7 @@ #include #include +#include #include @@ -41,10 +42,10 @@ void ExpressionSplitter::run(OptimiserStepContext& _context, Block& _ast) void ExpressionSplitter::operator()(FunctionCall& _funCall) { - std::optional builtinHandle = m_dialect.findBuiltin(_funCall.functionName.name.str()); + BuiltinFunction const* builtin = resolveBuiltinFunction(_funCall.functionName, m_dialect); for (size_t i = _funCall.arguments.size(); i > 0; i--) - if (!builtinHandle || !m_dialect.builtin(*builtinHandle).literalArgument(i - 1)) + if (!builtin || !builtin->literalArgument(i - 1)) outlineExpression(_funCall.arguments[i - 1]); } diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index 7ee9a9b8c..6324085e6 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -47,7 +47,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) std::make_unique( FunctionCall { debugData, - {debugData, YulName{m_dialect.builtin(*m_dialect.booleanNegationFunctionHandle()).name}}, + BuiltinName{debugData, *m_dialect.booleanNegationFunctionHandle()}, util::make_vector(std::move(*_forLoop.condition)) } ), diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.cpp b/libyul/optimiser/ForLoopConditionOutOfBody.cpp index d082bb78d..111f26fec 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.cpp +++ b/libyul/optimiser/ForLoopConditionOutOfBody.cpp @@ -53,18 +53,21 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) if (!SideEffectsCollector(m_dialect, *firstStatement.condition).movable()) return; - YulName const iszero{m_dialect.builtin(*m_dialect.booleanNegationFunctionHandle()).name}; + std::optional iszero = m_dialect.booleanNegationFunctionHandle(); + yulAssert(iszero.has_value()); + auto const& isZeroHandle = *iszero; langutil::DebugData::ConstPtr debugData = debugDataOf(*firstStatement.condition); if ( std::holds_alternative(*firstStatement.condition) && - std::get(*firstStatement.condition).functionName.name == iszero + std::holds_alternative(std::get(*firstStatement.condition).functionName) && + std::get(std::get(*firstStatement.condition).functionName).handle == isZeroHandle ) _forLoop.condition = std::make_unique(std::move(std::get(*firstStatement.condition).arguments.front())); else _forLoop.condition = std::make_unique(FunctionCall{ debugData, - Identifier{debugData, iszero}, + BuiltinName{debugData, isZeroHandle}, util::make_vector( std::move(*firstStatement.condition) ) diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index 328ef83b8..4b390f4f2 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -67,7 +67,7 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& // Store size of global statements. m_functionSizes[YulName{}] = CodeSize::codeSize(_ast); - std::map references = ReferencesCounter::countReferences(m_ast); + std::map references = ReferencesCounter::countReferences(m_ast); for (auto& statement: m_ast.statements) { if (!std::holds_alternative(statement)) @@ -83,7 +83,7 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& } // Check for memory guard. - std::vector memoryGuardCalls = findFunctionCalls(_ast, "memoryguard"_yulname); + std::vector memoryGuardCalls = findFunctionCalls(_ast, "memoryguard", m_dialect); // We will perform less aggressive inlining, if no ``memoryguard`` call is found. if (!memoryGuardCalls.empty()) m_hasMemoryGuard = true; @@ -101,7 +101,7 @@ void FullInliner::run(Pass _pass) // function name) order. // We use stable_sort below to keep the inlining order of two functions // with the same depth. - std::map depths = callDepths(); + std::map depths = callDepths(); std::vector functions; for (auto& statement: m_ast.statements) if (std::holds_alternative(statement)) @@ -123,7 +123,7 @@ void FullInliner::run(Pass _pass) handleBlock({}, std::get(statement)); } -std::map FullInliner::callDepths() const +std::map FullInliner::callDepths() const { CallGraph cg = CallGraphGenerator::callGraph(m_ast); cg.functionCalls.erase(""_yulname); @@ -131,17 +131,17 @@ std::map FullInliner::callDepths() const // Remove calls to builtin functions. for (auto& call: cg.functionCalls) for (auto it = call.second.begin(); it != call.second.end();) - if (m_dialect.findBuiltin(it->str())) + if (std::holds_alternative(*it)) it = call.second.erase(it); else ++it; - std::map depths; + std::map depths; size_t currentDepth = 0; while (true) { - std::vector removed; + std::vector removed; for (auto it = cg.functionCalls.begin(); it != cg.functionCalls.end();) { auto const& [fun, callees] = *it; @@ -156,7 +156,7 @@ std::map FullInliner::callDepths() const } for (auto& call: cg.functionCalls) - for (YulName toBeRemoved: removed) + for (FunctionHandle toBeRemoved: removed) ranges::actions::remove(call.second, toBeRemoved); currentDepth++; @@ -174,15 +174,19 @@ std::map FullInliner::callDepths() const bool FullInliner::shallInline(FunctionCall const& _funCall, YulName _callSite) { + if (isBuiltinFunctionCall(_funCall)) + return false; + yulAssert(std::holds_alternative(_funCall.functionName)); + auto const& functionName = std::get(_funCall.functionName).name; // No recursive inlining - if (_funCall.functionName.name == _callSite) + if (functionName == _callSite) return false; - FunctionDefinition* calledFunction = function(_funCall.functionName.name); + FunctionDefinition* calledFunction = function(functionName); if (!calledFunction) return false; - if (m_noInlineFunctions.count(_funCall.functionName.name) || recursive(*calledFunction)) + if (m_noInlineFunctions.count(functionName) || recursive(*calledFunction)) return false; // No inlining of calls where argument expressions may have side-effects. @@ -251,7 +255,7 @@ void FullInliner::handleBlock(YulName _currentFunctionName, Block& _block) bool FullInliner::recursive(FunctionDefinition const& _fun) const { - std::map references = ReferencesCounter::countReferences(_fun); + std::map references = ReferencesCounter::countReferences(_fun); return references[_fun.name] > 0; } @@ -291,7 +295,8 @@ std::vector InlineModifier::performInline(Statement& _statement, Func std::vector newStatements; std::map variableReplacements; - FunctionDefinition* function = m_driver.function(_funCall.functionName.name); + yulAssert(std::holds_alternative(_funCall.functionName)); + FunctionDefinition* function = m_driver.function(std::get(_funCall.functionName).name); assertThrow(!!function, OptimizerException, "Attempt to inline invalid function."); m_driver.tentativelyUpdateCodeSize(function->name, m_currentFunction); diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h index e93907023..4620194a4 100644 --- a/libyul/optimiser/FullInliner.h +++ b/libyul/optimiser/FullInliner.h @@ -98,7 +98,7 @@ class FullInliner: public ASTModifier /// @returns a map containing the maximum depths of a call chain starting at each /// function. For recursive functions, the value is one larger than for all others. - std::map callDepths() const; + std::map callDepths() const; void updateCodeSize(FunctionDefinition const& _fun); void handleBlock(YulName _currentFunctionName, Block& _block); @@ -114,7 +114,7 @@ class FullInliner: public ASTModifier /// True, if the code contains a ``memoryguard`` and we can expect to be able to move variables to memory later. bool m_hasMemoryGuard = false; /// Set of recursive functions. - std::set m_recursiveFunctions; + std::set m_recursiveFunctions; /// Names of functions to always inline. std::set m_singleUse; /// Variables that are constants (used for inlining heuristic) diff --git a/libyul/optimiser/FunctionCallFinder.cpp b/libyul/optimiser/FunctionCallFinder.cpp index aaf8b9f68..4c85d77f5 100644 --- a/libyul/optimiser/FunctionCallFinder.cpp +++ b/libyul/optimiser/FunctionCallFinder.cpp @@ -19,6 +19,8 @@ #include #include +#include +#include using namespace solidity; using namespace solidity::yul; @@ -30,32 +32,35 @@ class MaybeConstFunctionCallFinder: Base { public: using MaybeConstBlock = std::conditional_t, Block const, Block>; - static std::vector run(MaybeConstBlock& _block, YulName const _functionName) + static std::vector run(MaybeConstBlock& _block, std::string_view const _functionName, Dialect const& _dialect) { - MaybeConstFunctionCallFinder functionCallFinder(_functionName); + MaybeConstFunctionCallFinder functionCallFinder(_functionName, _dialect); functionCallFinder(_block); return functionCallFinder.m_calls; } private: - explicit MaybeConstFunctionCallFinder(YulName const _functionName): m_functionName(_functionName), m_calls() {} + explicit MaybeConstFunctionCallFinder(std::string_view const _functionName, Dialect const& _dialect): + m_dialect(_dialect), m_functionName(_functionName), m_calls() {} + using Base::operator(); void operator()(ResultType& _functionCall) override { Base::operator()(_functionCall); - if (_functionCall.functionName.name == m_functionName) + if (resolveFunctionName(_functionCall.functionName, m_dialect) == m_functionName) m_calls.emplace_back(&_functionCall); } - YulName m_functionName; + Dialect const& m_dialect; + std::string_view m_functionName; std::vector m_calls; }; } -std::vector solidity::yul::findFunctionCalls(Block& _block, YulName _functionName) +std::vector solidity::yul::findFunctionCalls(Block& _block, std::string_view const _functionName, Dialect const& _dialect) { - return MaybeConstFunctionCallFinder::run(_block, _functionName); + return MaybeConstFunctionCallFinder::run(_block, _functionName, _dialect); } -std::vector solidity::yul::findFunctionCalls(Block const& _block, YulName _functionName) +std::vector solidity::yul::findFunctionCalls(Block const& _block, std::string_view const _functionName, Dialect const& _dialect) { - return MaybeConstFunctionCallFinder::run(_block, _functionName); + return MaybeConstFunctionCallFinder::run(_block, _functionName, _dialect); } diff --git a/libyul/optimiser/FunctionCallFinder.h b/libyul/optimiser/FunctionCallFinder.h index 41a19fe99..067aee2a3 100644 --- a/libyul/optimiser/FunctionCallFinder.h +++ b/libyul/optimiser/FunctionCallFinder.h @@ -21,25 +21,27 @@ #pragma once #include -#include +#include #include namespace solidity::yul { +struct Dialect; + /** * Finds all calls to a function of a given name using an ASTModifier. * * Prerequisite: Disambiguator */ -std::vector findFunctionCalls(Block& _block, YulName _functionName); +std::vector findFunctionCalls(Block& _block, std::string_view _functionName, Dialect const& _dialect); /** * Finds all calls to a function of a given name using an ASTWalker. * * Prerequisite: Disambiguator */ -std::vector findFunctionCalls(Block const& _block, YulName _functionName); +std::vector findFunctionCalls(Block const& _block, std::string_view _functionName, Dialect const& _dialect); } diff --git a/libyul/optimiser/FunctionSpecializer.cpp b/libyul/optimiser/FunctionSpecializer.cpp index bab02a2e1..cbbf14e8f 100644 --- a/libyul/optimiser/FunctionSpecializer.cpp +++ b/libyul/optimiser/FunctionSpecializer.cpp @@ -55,21 +55,23 @@ void FunctionSpecializer::operator()(FunctionCall& _f) // TODO When backtracking is implemented, the restriction of recursive functions can be lifted. if ( - m_dialect.findBuiltin(_f.functionName.name.str()) || - m_recursiveFunctions.count(_f.functionName.name) + isBuiltinFunctionCall(_f) || + (std::holds_alternative(_f.functionName) && m_recursiveFunctions.count(std::get(_f.functionName).name)) ) return; + yulAssert(std::holds_alternative(_f.functionName)); + auto& identifier = std::get(_f.functionName); LiteralArguments arguments = specializableArguments(_f); if (ranges::any_of(arguments, [](auto& _a) { return _a.has_value(); })) { - YulName oldName = std::move(_f.functionName.name); + YulName oldName = std::move(identifier.name); auto newName = m_nameDispenser.newName(oldName); m_oldToNewMap[oldName].emplace_back(std::make_pair(newName, arguments)); - _f.functionName.name = newName; + identifier.name = newName; _f.arguments = util::filter( _f.arguments, applyMap(arguments, [](auto& _a) { return !_a; }) @@ -128,8 +130,7 @@ void FunctionSpecializer::run(OptimiserStepContext& _context, Block& _ast) { FunctionSpecializer f{ CallGraphGenerator::callGraph(_ast).recursiveFunctions(), - _context.dispenser, - _context.dialect + _context.dispenser }; f(_ast); diff --git a/libyul/optimiser/FunctionSpecializer.h b/libyul/optimiser/FunctionSpecializer.h index 784ec4311..4df59b354 100644 --- a/libyul/optimiser/FunctionSpecializer.h +++ b/libyul/optimiser/FunctionSpecializer.h @@ -22,8 +22,7 @@ #include #include -#include -#include +#include #include #include @@ -67,13 +66,11 @@ class FunctionSpecializer: public ASTModifier private: explicit FunctionSpecializer( - std::set _recursiveFunctions, - NameDispenser& _nameDispenser, - Dialect const& _dialect + std::set _recursiveFunctions, + NameDispenser& _nameDispenser ): m_recursiveFunctions(std::move(_recursiveFunctions)), - m_nameDispenser(_nameDispenser), - m_dialect(_dialect) + m_nameDispenser(_nameDispenser) {} /// Returns a vector of Expressions, where the index `i` is an expression if the function's /// `i`-th argument can be specialized, nullopt otherwise. @@ -104,10 +101,9 @@ class FunctionSpecializer: public ASTModifier /// Note that at least one of the argument will have a literal value. std::map>> m_oldToNewMap; /// We skip specializing recursive functions. Need backtracking to properly deal with them. - std::set const m_recursiveFunctions; + std::set const m_recursiveFunctions; NameDispenser& m_nameDispenser; - Dialect const& m_dialect; }; } diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp index d719302dc..6061fa3e9 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp @@ -29,13 +29,13 @@ using namespace solidity::yul; void InlinableExpressionFunctionFinder::operator()(Identifier const& _identifier) { - checkAllowed(_identifier.name); + checkAllowed(_identifier); ASTWalker::operator()(_identifier); } void InlinableExpressionFunctionFinder::operator()(FunctionCall const& _funCall) { - checkAllowed(_funCall.functionName.name); + checkAllowed(_funCall.functionName); ASTWalker::operator()(_funCall); } @@ -67,3 +67,9 @@ void InlinableExpressionFunctionFinder::operator()(FunctionDefinition const& _fu } ASTWalker::operator()(_function.body); } +void InlinableExpressionFunctionFinder::checkAllowed(FunctionName const& _name) +{ + // disallowed function names can only ever be user-defined `yul::Identifier`s, not builtins + if (std::holds_alternative(_name) && m_disallowedIdentifiers.count(std::get(_name).name) != 0) + m_foundDisallowedIdentifier = true; +} diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.h b/libyul/optimiser/InlinableExpressionFunctionFinder.h index e7210da69..c6897c173 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.h +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.h @@ -53,11 +53,7 @@ class InlinableExpressionFunctionFinder: public ASTWalker void operator()(FunctionDefinition const& _function) override; private: - void checkAllowed(YulName _name) - { - if (m_disallowedIdentifiers.count(_name)) - m_foundDisallowedIdentifier = true; - } + void checkAllowed(FunctionName const& _name); bool m_foundDisallowedIdentifier = false; std::set m_disallowedIdentifiers; diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index 731f4b3b8..ceaa8f06b 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -32,9 +32,11 @@ using namespace solidity; using namespace solidity::yul; -KnowledgeBase::KnowledgeBase(std::map const& _ssaValues): +KnowledgeBase::KnowledgeBase(std::map const& _ssaValues, Dialect const& _dialect): m_valuesAreSSA(true), - m_variableValues([_ssaValues](YulName _var) { return util::valueOrNullptr(_ssaValues, _var); }) + m_variableValues([_ssaValues](YulName _var) { return util::valueOrNullptr(_ssaValues, _var); }), + m_addBuiltinHandle(_dialect.findBuiltin("add")), + m_subBuiltinHandle(_dialect.findBuiltin("sub")) {} bool KnowledgeBase::knownToBeDifferent(YulName _a, YulName _b) @@ -116,9 +118,12 @@ std::optional KnowledgeBase::explore(Expression c return VariableOffset{YulName{}, literal->value.value()}; else if (Identifier const* identifier = std::get_if(&_value)) return explore(identifier->name); - else if (FunctionCall const* f = std::get_if(&_value)) + else if ( + FunctionCall const* f = std::get_if(&_value); + f && isBuiltinFunctionCall(*f) + ) { - if (f->functionName.name == "add"_yulname) + if (std::get(f->functionName).handle == m_addBuiltinHandle) { if (std::optional a = explore(f->arguments[0])) if (std::optional b = explore(f->arguments[1])) @@ -132,7 +137,7 @@ std::optional KnowledgeBase::explore(Expression c return VariableOffset{a->reference, offset}; } } - else if (f->functionName.name == "sub"_yulname) + else if (std::get(f->functionName).handle == m_subBuiltinHandle) if (std::optional a = explore(f->arguments[0])) if (std::optional b = explore(f->arguments[1])) { diff --git a/libyul/optimiser/KnowledgeBase.h b/libyul/optimiser/KnowledgeBase.h index 46ea7b96a..78daadbc4 100644 --- a/libyul/optimiser/KnowledgeBase.h +++ b/libyul/optimiser/KnowledgeBase.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include #include @@ -62,11 +63,13 @@ class KnowledgeBase public: /// Constructor for arbitrary value callback that allows for variable values /// to change in between calls to functions of this class. - explicit KnowledgeBase(std::function _variableValues): - m_variableValues(std::move(_variableValues)) + explicit KnowledgeBase(std::function _variableValues, Dialect const& _dialect): + m_variableValues(std::move(_variableValues)), + m_addBuiltinHandle(_dialect.findBuiltin("add")), + m_subBuiltinHandle(_dialect.findBuiltin("sub")) {} /// Constructor to use if source code is in SSA form and values are constant. - explicit KnowledgeBase(std::map const& _ssaValues); + explicit KnowledgeBase(std::map const& _ssaValues, Dialect const& _dialect); bool knownToBeDifferent(YulName _a, YulName _b); std::optional differenceIfKnownConstant(YulName _a, YulName _b); @@ -115,6 +118,8 @@ class KnowledgeBase bool m_valuesAreSSA = false; /// Callback to retrieve the current value of a variable. std::function m_variableValues; + std::optional m_addBuiltinHandle; + std::optional m_subBuiltinHandle; /// Offsets for each variable to one representative per group. /// The empty string is the representative of the constant value zero. diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index d6961b6f8..36163c6c5 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -56,13 +56,17 @@ void LoadResolver::visit(Expression& _e) { DataFlowAnalyzer::visit(_e); - if (FunctionCall const* funCall = std::get_if(&_e)) + if ( + FunctionCall const* funCall = std::get_if(&_e); + funCall && std::holds_alternative(funCall->functionName) + ) { - if (funCall->functionName.name == m_loadFunctionName[static_cast(StoreLoadLocation::Memory)]) + auto const& builtinHandle = std::get(funCall->functionName).handle; + if (builtinHandle == m_loadFunctionName[static_cast(StoreLoadLocation::Memory)]) tryResolve(_e, StoreLoadLocation::Memory, funCall->arguments); - else if (funCall->functionName.name == m_loadFunctionName[static_cast(StoreLoadLocation::Storage)]) + else if (builtinHandle == m_loadFunctionName[static_cast(StoreLoadLocation::Storage)]) tryResolve(_e, StoreLoadLocation::Storage, funCall->arguments); - else if (!m_containsMSize && funCall->functionName.name.str() == m_dialect.builtin(*m_dialect.hashFunctionHandle()).name) + else if (!m_containsMSize && builtinHandle == m_dialect.hashFunctionHandle()) { Identifier const* start = std::get_if(&funCall->arguments.at(0)); Identifier const* length = std::get_if(&funCall->arguments.at(1)); diff --git a/libyul/optimiser/LoadResolver.h b/libyul/optimiser/LoadResolver.h index b4a496303..d87807692 100644 --- a/libyul/optimiser/LoadResolver.h +++ b/libyul/optimiser/LoadResolver.h @@ -49,7 +49,7 @@ class LoadResolver: public DataFlowAnalyzer private: LoadResolver( Dialect const& _dialect, - std::map _functionSideEffects, + std::map _functionSideEffects, bool _containsMSize, std::optional _expectedExecutionsPerDeployment ): diff --git a/libyul/optimiser/LoopInvariantCodeMotion.cpp b/libyul/optimiser/LoopInvariantCodeMotion.cpp index 2a196a68f..f2e7d0408 100644 --- a/libyul/optimiser/LoopInvariantCodeMotion.cpp +++ b/libyul/optimiser/LoopInvariantCodeMotion.cpp @@ -32,7 +32,7 @@ using namespace solidity::yul; void LoopInvariantCodeMotion::run(OptimiserStepContext& _context, Block& _ast) { - std::map functionSideEffects = + std::map functionSideEffects = SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast)); bool containsMSize = MSizeFinder::containsMSize(_context.dialect, _ast); std::set ssaVars = SSAValueTracker::ssaVariables(_ast); diff --git a/libyul/optimiser/LoopInvariantCodeMotion.h b/libyul/optimiser/LoopInvariantCodeMotion.h index c85b87a01..d03a91eee 100644 --- a/libyul/optimiser/LoopInvariantCodeMotion.h +++ b/libyul/optimiser/LoopInvariantCodeMotion.h @@ -49,7 +49,7 @@ class LoopInvariantCodeMotion: public ASTModifier explicit LoopInvariantCodeMotion( Dialect const& _dialect, std::set const& _ssaVariables, - std::map const& _functionSideEffects, + std::map const& _functionSideEffects, bool _containsMSize ): m_containsMSize(_containsMSize), @@ -69,7 +69,7 @@ class LoopInvariantCodeMotion: public ASTModifier bool m_containsMSize = true; Dialect const& m_dialect; std::set const& m_ssaVariables; - std::map const& m_functionSideEffects; + std::map const& m_functionSideEffects; }; } diff --git a/libyul/optimiser/Metrics.cpp b/libyul/optimiser/Metrics.cpp index 546c465b5..04bfe9a7a 100644 --- a/libyul/optimiser/Metrics.cpp +++ b/libyul/optimiser/Metrics.cpp @@ -137,7 +137,7 @@ void CodeCost::operator()(FunctionCall const& _funCall) { ASTWalker::operator()(_funCall); - if (auto instruction = toEVMInstruction(m_dialect, _funCall.functionName.name)) + if (auto instruction = toEVMInstruction(m_dialect, _funCall.functionName)) { addInstructionCost(*instruction); return; diff --git a/libyul/optimiser/NameCollector.cpp b/libyul/optimiser/NameCollector.cpp index d6db837f8..cde9b64f6 100644 --- a/libyul/optimiser/NameCollector.cpp +++ b/libyul/optimiser/NameCollector.cpp @@ -22,6 +22,7 @@ #include #include +#include using namespace solidity; using namespace solidity::yul; @@ -55,25 +56,25 @@ void ReferencesCounter::operator()(Identifier const& _identifier) void ReferencesCounter::operator()(FunctionCall const& _funCall) { - ++m_references[_funCall.functionName.name]; + ++m_references[functionNameToHandle(_funCall.functionName)]; ASTWalker::operator()(_funCall); } -std::map ReferencesCounter::countReferences(Block const& _block) +std::map ReferencesCounter::countReferences(Block const& _block) { ReferencesCounter counter; counter(_block); return std::move(counter.m_references); } -std::map ReferencesCounter::countReferences(FunctionDefinition const& _function) +std::map ReferencesCounter::countReferences(FunctionDefinition const& _function) { ReferencesCounter counter; counter(_function); return std::move(counter.m_references); } -std::map ReferencesCounter::countReferences(Expression const& _expression) +std::map ReferencesCounter::countReferences(Expression const& _expression) { ReferencesCounter counter; counter.visit(_expression); diff --git a/libyul/optimiser/NameCollector.h b/libyul/optimiser/NameCollector.h index 0fc2e311c..2adc73ced 100644 --- a/libyul/optimiser/NameCollector.h +++ b/libyul/optimiser/NameCollector.h @@ -76,12 +76,12 @@ class ReferencesCounter: public ASTWalker void operator()(Identifier const& _identifier) override; void operator()(FunctionCall const& _funCall) override; - static std::map countReferences(Block const& _block); - static std::map countReferences(FunctionDefinition const& _function); - static std::map countReferences(Expression const& _expression); + static std::map countReferences(Block const& _block); + static std::map countReferences(FunctionDefinition const& _function); + static std::map countReferences(Expression const& _expression); private: - std::map m_references; + std::map m_references; }; /** diff --git a/libyul/optimiser/NameDisplacer.cpp b/libyul/optimiser/NameDisplacer.cpp index c68d52f9a..7430c26c3 100644 --- a/libyul/optimiser/NameDisplacer.cpp +++ b/libyul/optimiser/NameDisplacer.cpp @@ -54,7 +54,8 @@ void NameDisplacer::operator()(FunctionDefinition& _function) void NameDisplacer::operator()(FunctionCall& _funCall) { - checkAndReplace(_funCall.functionName.name); + if (std::holds_alternative(_funCall.functionName)) + checkAndReplace(std::get(_funCall.functionName).name); ASTModifier::operator()(_funCall); } diff --git a/libyul/optimiser/NameSimplifier.cpp b/libyul/optimiser/NameSimplifier.cpp index 6f3f1760a..0572a9003 100644 --- a/libyul/optimiser/NameSimplifier.cpp +++ b/libyul/optimiser/NameSimplifier.cpp @@ -67,8 +67,11 @@ void NameSimplifier::operator()(Identifier& _identifier) void NameSimplifier::operator()(FunctionCall& _funCall) { // The visitor on its own does not visit the function name. - if (!m_context.dialect.findBuiltin(_funCall.functionName.name.str())) - (*this)(_funCall.functionName); + if (!isBuiltinFunctionCall(_funCall)) + { + yulAssert(std::holds_alternative(_funCall.functionName)); + (*this)(std::get(_funCall.functionName)); + } ASTModifier::operator()(_funCall); } diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index 001ff147d..8fc225bee 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -23,8 +23,9 @@ #include -#include #include +#include +#include #include #include @@ -60,11 +61,11 @@ bool yul::isRestrictedIdentifier(Dialect const& _dialect, YulName const& _identi return _identifier.empty() || hasLeadingOrTrailingDot(_identifier.str()) || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier.str()); } -std::optional yul::toEVMInstruction(Dialect const& _dialect, YulName const& _name) +std::optional yul::toEVMInstruction(Dialect const& _dialect, FunctionName const& _name) { if (auto const* dialect = dynamic_cast(&_dialect)) - if (std::optional const builtinHandle = dialect->findBuiltin(_name.str())) - return dialect->builtin(*builtinHandle).instruction; + if (BuiltinFunctionForEVM const* builtin = resolveBuiltinFunctionForEVM(_name, *dialect)) + return builtin->instruction; return std::nullopt; } diff --git a/libyul/optimiser/OptimizerUtilities.h b/libyul/optimiser/OptimizerUtilities.h index 911a1be0a..430834d83 100644 --- a/libyul/optimiser/OptimizerUtilities.h +++ b/libyul/optimiser/OptimizerUtilities.h @@ -48,7 +48,7 @@ void removeEmptyBlocks(Block& _block); bool isRestrictedIdentifier(Dialect const& _dialect, YulName const& _identifier); /// Helper function that returns the instruction, if the `_name` is a BuiltinFunction -std::optional toEVMInstruction(Dialect const& _dialect, YulName const& _name); +std::optional toEVMInstruction(Dialect const& _dialect, FunctionName const& _name); /// Helper function that returns the EVM version from a dialect. /// It returns the default EVM version if dialect is not an EVMDialect. diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index 1698ac5ee..a505126ae 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -40,7 +41,7 @@ using namespace solidity::yul; SideEffectsCollector::SideEffectsCollector( Dialect const& _dialect, Expression const& _expression, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): SideEffectsCollector(_dialect, _functionSideEffects) { @@ -56,7 +57,7 @@ SideEffectsCollector::SideEffectsCollector(Dialect const& _dialect, Statement co SideEffectsCollector::SideEffectsCollector( Dialect const& _dialect, Block const& _ast, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): SideEffectsCollector(_dialect, _functionSideEffects) { @@ -66,7 +67,7 @@ SideEffectsCollector::SideEffectsCollector( SideEffectsCollector::SideEffectsCollector( Dialect const& _dialect, ForLoop const& _ast, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): SideEffectsCollector(_dialect, _functionSideEffects) { @@ -77,11 +78,11 @@ void SideEffectsCollector::operator()(FunctionCall const& _functionCall) { ASTWalker::operator()(_functionCall); - YulName functionName = _functionCall.functionName.name; - if (std::optional builtinHandle = m_dialect.findBuiltin(functionName.str())) - m_sideEffects += m_dialect.builtin(*builtinHandle).sideEffects; - else if (m_functionSideEffects && m_functionSideEffects->count(functionName)) - m_sideEffects += m_functionSideEffects->at(functionName); + FunctionHandle functionHandle = functionNameToHandle(_functionCall.functionName); + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_functionCall.functionName, m_dialect)) + m_sideEffects += builtin->sideEffects; + else if (m_functionSideEffects && m_functionSideEffects->count(functionHandle)) + m_sideEffects += m_functionSideEffects->at(functionHandle); else m_sideEffects += SideEffects::worst(); } @@ -111,12 +112,12 @@ void MSizeFinder::operator()(FunctionCall const& _functionCall) { ASTWalker::operator()(_functionCall); - if (std::optional builtinHandle = m_dialect.findBuiltin(_functionCall.functionName.name.str())) - if (m_dialect.builtin(*builtinHandle).isMSize) + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_functionCall.functionName, m_dialect)) + if (builtin->isMSize) m_msizeFound = true; } -std::map SideEffectsPropagator::sideEffects( +std::map SideEffectsPropagator::sideEffects( Dialect const& _dialect, CallGraph const& _directCallGraph ) @@ -127,8 +128,16 @@ std::map SideEffectsPropagator::sideEffects( // In the future, we should refine that, because the property // is actually a bit different from "not movable". - std::map ret; - for (auto const& function: _directCallGraph.functionsWithLoops + _directCallGraph.recursiveFunctions()) + std::map ret; + for (auto const& function: _directCallGraph.functionsWithLoops) + { + ret[function].movable = false; + ret[function].canBeRemoved = false; + ret[function].canBeRemovedIfNoMSize = false; + ret[function].cannotLoop = false; + } + + for (auto const& function: _directCallGraph.recursiveFunctions()) { ret[function].movable = false; ret[function].canBeRemoved = false; @@ -138,20 +147,20 @@ std::map SideEffectsPropagator::sideEffects( for (auto const& call: _directCallGraph.functionCalls) { - YulName funName = call.first; + FunctionHandle funName = call.first; SideEffects sideEffects; - auto _visit = [&, visited = std::set{}](YulName _function, auto&& _recurse) mutable { + auto _visit = [&, visited = std::set{}](FunctionHandle _function, auto&& _recurse) mutable { if (!visited.insert(_function).second) return; if (sideEffects == SideEffects::worst()) return; - if (std::optional builtinHandle = _dialect.findBuiltin(_function.str())) + if (BuiltinHandle const* builtinHandle = std::get_if(&_function)) sideEffects += _dialect.builtin(*builtinHandle).sideEffects; else { if (ret.count(_function)) sideEffects += ret[_function]; - for (YulName callee: _directCallGraph.functionCalls.at(_function)) + for (FunctionHandle const& callee: _directCallGraph.functionCalls.at(_function)) _recurse(callee, _recurse); } }; @@ -228,10 +237,13 @@ bool TerminationFinder::containsNonContinuingFunctionCall(Expression const& _exp if (containsNonContinuingFunctionCall(arg)) return true; - if (std::optional const builtinHandle = m_dialect.findBuiltin(functionCall->functionName.name.str())) - return !m_dialect.builtin(*builtinHandle).controlFlowSideEffects.canContinue; - else if (m_functionSideEffects && m_functionSideEffects->count(functionCall->functionName.name)) - return !m_functionSideEffects->at(functionCall->functionName.name).canContinue; + if (BuiltinFunction const* builtin = resolveBuiltinFunction(functionCall->functionName, m_dialect)) + return !builtin->controlFlowSideEffects.canContinue; + + yulAssert(std::holds_alternative(functionCall->functionName)); + auto const& name = std::get(functionCall->functionName).name; + if (m_functionSideEffects && m_functionSideEffects->count(name)) + return !m_functionSideEffects->at(name).canContinue; } return false; } diff --git a/libyul/optimiser/Semantics.h b/libyul/optimiser/Semantics.h index e97fbd0c3..9fdeb78d0 100644 --- a/libyul/optimiser/Semantics.h +++ b/libyul/optimiser/Semantics.h @@ -42,23 +42,23 @@ class SideEffectsCollector: public ASTWalker public: explicit SideEffectsCollector( Dialect const& _dialect, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ): m_dialect(_dialect), m_functionSideEffects(_functionSideEffects) {} SideEffectsCollector( Dialect const& _dialect, Expression const& _expression, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); SideEffectsCollector(Dialect const& _dialect, Statement const& _statement); SideEffectsCollector( Dialect const& _dialect, Block const& _ast, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); SideEffectsCollector( Dialect const& _dialect, ForLoop const& _ast, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); using ASTWalker::operator(); @@ -117,7 +117,7 @@ class SideEffectsCollector: public ASTWalker private: Dialect const& m_dialect; - std::map const* m_functionSideEffects = nullptr; + std::map const* m_functionSideEffects = nullptr; SideEffects m_sideEffects; }; @@ -130,7 +130,7 @@ class SideEffectsCollector: public ASTWalker class SideEffectsPropagator { public: - static std::map sideEffects( + static std::map sideEffects( Dialect const& _dialect, CallGraph const& _directCallGraph ); @@ -195,7 +195,7 @@ class MovableChecker: public SideEffectsCollector public: explicit MovableChecker( Dialect const& _dialect, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ): SideEffectsCollector(_dialect, _functionSideEffects) {} MovableChecker(Dialect const& _dialect, Expression const& _expression); diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index 0fcd35bda..8a7549cc1 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -79,9 +79,9 @@ std::optional const*>> { if (std::holds_alternative(_expr)) if (auto const* dialect = dynamic_cast(&_dialect)) - if (std::optional const builtinHandle = dialect->findBuiltin(std::get(_expr).functionName.name.str())) - if (auto const& instruction = dialect->builtin(*builtinHandle).instruction) - return std::make_pair(*instruction, &std::get(_expr).arguments); + if (auto const* builtin = resolveBuiltinFunctionForEVM(std::get(_expr).functionName, *dialect)) + if (builtin->instruction) + return std::make_pair(*builtin->instruction, &std::get(_expr).arguments); return {}; } @@ -234,7 +234,7 @@ evmasm::Instruction Pattern::instruction() const return m_instruction; } -Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion) const +Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData, EVMDialect const& _dialect) const { if (matchGroup()) return ASTCopier().translate(matchGroupValue()); @@ -247,12 +247,18 @@ Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData { std::vector arguments; for (auto const& arg: m_arguments) - arguments.emplace_back(arg.toExpression(_debugData, _evmVersion)); + arguments.emplace_back(arg.toExpression(_debugData, _dialect)); - std::string name = util::toLower(instructionInfo(m_instruction, _evmVersion).name); + if (!m_instructionBuiltinHandle) + { + std::string name = util::toLower(instructionInfo(m_instruction, _dialect.evmVersion()).name); + std::optional handle = _dialect.findBuiltin(name); + yulAssert(handle); + m_instructionBuiltinHandle = *handle; + } return FunctionCall{_debugData, - Identifier{_debugData, YulName{name}}, + BuiltinName{_debugData, *m_instructionBuiltinHandle}, std::move(arguments) }; } diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index 9362ee855..2d48464ca 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -38,8 +39,9 @@ namespace solidity::yul { -struct Dialect; struct AssignedValue; +struct Dialect; +class EVMDialect; class Pattern; using DebugData = langutil::DebugData; @@ -133,13 +135,14 @@ class Pattern /// Turns this pattern into an actual expression. Should only be called /// for patterns resulting from an action, i.e. with match groups assigned. - Expression toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion) const; + Expression toExpression(langutil::DebugData::ConstPtr const& _debugData, EVMDialect const& _dialect) const; private: Expression const& matchGroupValue() const; PatternKind m_kind = PatternKind::Any; evmasm::Instruction m_instruction; ///< Only valid if m_kind is Operation + std::optional mutable m_instructionBuiltinHandle; ///< Builtin handle cache for instructions std::shared_ptr m_data; ///< Only valid if m_kind is Constant std::vector m_arguments; unsigned m_matchGroup = 0; diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 2dc32d787..766cd4928 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -57,7 +57,7 @@ namespace */ struct MemoryOffsetAllocator { - uint64_t run(YulName _function = YulName{}) + uint64_t run(FunctionHandle _function = YulName{}) { if (slotsRequiredForFunction.count(_function)) return slotsRequiredForFunction[_function]; @@ -65,14 +65,17 @@ struct MemoryOffsetAllocator // Assign to zero early to guard against recursive calls. slotsRequiredForFunction[_function] = 0; + if (!std::holds_alternative(_function)) + return 0; + uint64_t requiredSlots = 0; - if (callGraph.count(_function)) - for (YulName child: callGraph.at(_function)) + if (callGraph.count(std::get(_function))) + for (FunctionHandle const& child: callGraph.at(std::get(_function))) requiredSlots = std::max(run(child), requiredSlots); - if (auto const* unreachables = util::valueOrNullptr(unreachableVariables, _function)) + if (auto const* unreachables = util::valueOrNullptr(unreachableVariables, std::get(_function))) { - if (FunctionDefinition const* functionDefinition = util::valueOrDefault(functionDefinitions, _function, nullptr, util::allow_copy)) + if (FunctionDefinition const* functionDefinition = util::valueOrDefault(functionDefinitions, std::get(_function), nullptr, util::allow_copy)) if ( size_t totalArgCount = functionDefinition->returnVariables.size() + functionDefinition->parameters.size(); totalArgCount > 16 @@ -99,14 +102,14 @@ struct MemoryOffsetAllocator /// An empty variable name means that the function has too many arguments or return variables. std::map> const& unreachableVariables; /// The graph of immediate function calls of all functions. - std::map> const& callGraph; + std::map> const& callGraph; /// Maps the name of each user-defined function to its definition. std::map const& functionDefinitions; /// Maps variable names to the memory slot the respective variable is assigned. std::map slotAllocations{}; /// Maps function names to the number of memory slots the respective function requires. - std::map slotsRequiredForFunction{}; + std::map slotsRequiredForFunction{}; }; u256 literalArgumentValue(FunctionCall const& _call) @@ -181,7 +184,7 @@ void StackLimitEvader::run( "StackLimitEvader can only be run on objects using the EVMDialect with object access." ); - std::vector memoryGuardCalls = findFunctionCalls(_astRoot, "memoryguard"_yulname); + std::vector memoryGuardCalls = findFunctionCalls(_astRoot, "memoryguard", *evmDialect); // Do not optimise, if no ``memoryguard`` call is found. if (memoryGuardCalls.empty()) return; @@ -197,9 +200,12 @@ void StackLimitEvader::run( CallGraph callGraph = CallGraphGenerator::callGraph(_astRoot); // We cannot move variables in recursive functions to fixed memory offsets. - for (YulName function: callGraph.recursiveFunctions()) - if (_unreachableVariables.count(function)) + for (FunctionHandle function: callGraph.recursiveFunctions()) + { + yulAssert(std::holds_alternative(function), "Builtins are not recursive."); + if (_unreachableVariables.count(std::get(function))) return; + } std::map functionDefinitions = allFunctionDefinitions(_astRoot); @@ -210,7 +216,7 @@ void StackLimitEvader::run( StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, _astRoot); reservedMemory += 32 * requiredSlots; - for (FunctionCall* memoryGuardCall: findFunctionCalls(_astRoot, "memoryguard"_yulname)) + for (FunctionCall* memoryGuardCall: findFunctionCalls(_astRoot, "memoryguard", *evmDialect)) { Literal* literal = std::get_if(&memoryGuardCall->arguments.front()); yulAssert(literal && literal->kind == LiteralKind::Number, ""); diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index e75472f06..15df64b3f 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -47,7 +47,7 @@ std::vector generateMemoryStore( std::vector result; result.emplace_back(ExpressionStatement{_debugData, FunctionCall{ _debugData, - Identifier{_debugData, YulName{_dialect.builtin(*memoryStoreFunctionHandle).name}}, + BuiltinName{_debugData, *memoryStoreFunctionHandle}, { Literal{_debugData, LiteralKind::Number, _mpos}, std::move(_value) @@ -62,7 +62,7 @@ FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::Co yulAssert(memoryLoadHandle); return FunctionCall{ _debugData, - Identifier{_debugData, YulName{_dialect.builtin(*memoryLoadHandle).name}}, { + BuiltinName{_debugData, *memoryLoadHandle}, { Literal{ _debugData, LiteralKind::Number, @@ -223,13 +223,16 @@ void StackToMemoryMover::operator()(Block& _block) { FunctionCall const* functionCall = std::get_if(_stmt.value.get()); yulAssert(functionCall, ""); - if (m_context.dialect.findBuiltin(functionCall->functionName.name.str())) + if (isBuiltinFunctionCall(*functionCall)) rhsMemorySlots = std::vector>(_lhsVars.size(), std::nullopt); else + { + yulAssert(std::holds_alternative(functionCall->functionName)); rhsMemorySlots = - m_functionReturnVariables.at(functionCall->functionName.name) | + m_functionReturnVariables.at(std::get(functionCall->functionName).name) | ranges::views::transform(m_memoryOffsetTracker) | ranges::to>>; + } } else rhsMemorySlots = std::vector>(_lhsVars.size(), std::nullopt); diff --git a/libyul/optimiser/SyntacticalEquality.cpp b/libyul/optimiser/SyntacticalEquality.cpp index 73b4d5083..e233b57e9 100644 --- a/libyul/optimiser/SyntacticalEquality.cpp +++ b/libyul/optimiser/SyntacticalEquality.cpp @@ -25,6 +25,7 @@ #include #include +#include using namespace solidity; using namespace solidity::yul; @@ -54,6 +55,14 @@ bool SyntacticallyEqual::expressionEqual(FunctionCall const& _lhs, FunctionCall }); } +bool SyntacticallyEqual::expressionEqual(FunctionName const& _lhs, FunctionName const& _rhs) +{ + return std::visit(util::GenericVisitor{ + [&](BuiltinName const& _builtin) { return std::holds_alternative(_rhs) && _builtin.handle == std::get(_rhs).handle; }, + [&](Identifier const& _identifier) { return std::holds_alternative(_rhs) && expressionEqual(_identifier, std::get(_rhs)); }, + }, _lhs); +} + bool SyntacticallyEqual::expressionEqual(Identifier const& _lhs, Identifier const& _rhs) { auto lhsIt = m_identifiersLHS.find(_lhs.name); diff --git a/libyul/optimiser/SyntacticalEquality.h b/libyul/optimiser/SyntacticalEquality.h index 1fd888f7a..0db52c969 100644 --- a/libyul/optimiser/SyntacticalEquality.h +++ b/libyul/optimiser/SyntacticalEquality.h @@ -48,6 +48,7 @@ class SyntacticallyEqual bool expressionEqual(FunctionCall const& _lhs, FunctionCall const& _rhs); bool expressionEqual(Identifier const& _lhs, Identifier const& _rhs); + bool expressionEqual(FunctionName const& _lhs, FunctionName const& _rhs); bool expressionEqual(Literal const& _lhs, Literal const& _rhs); bool statementEqual(ExpressionStatement const& _lhs, ExpressionStatement const& _rhs); diff --git a/libyul/optimiser/UnusedAssignEliminator.cpp b/libyul/optimiser/UnusedAssignEliminator.cpp index eb639f8a6..6de2ebf4c 100644 --- a/libyul/optimiser/UnusedAssignEliminator.cpp +++ b/libyul/optimiser/UnusedAssignEliminator.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -79,10 +80,13 @@ void UnusedAssignEliminator::operator()(FunctionCall const& _functionCall) UnusedStoreBase::operator()(_functionCall); ControlFlowSideEffects sideEffects; - if (std::optional const builtinHandle = m_dialect.findBuiltin(_functionCall.functionName.name.str())) - sideEffects = m_dialect.builtin(*builtinHandle).controlFlowSideEffects; + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_functionCall.functionName, m_dialect)) + sideEffects = builtin->controlFlowSideEffects; else - sideEffects = m_controlFlowSideEffects.at(_functionCall.functionName.name); + { + yulAssert(std::holds_alternative(_functionCall.functionName)); + sideEffects = m_controlFlowSideEffects.at(std::get(_functionCall.functionName).name); + } if (!sideEffects.canContinue) // We do not return from the current function, so it is OK to also diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index 9f6b88412..91568f4d6 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -43,7 +43,7 @@ UnusedPruner::UnusedPruner( Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects, + std::map const* _functionSideEffects, std::set const& _externallyUsedFunctions ): m_dialect(_dialect), @@ -94,7 +94,7 @@ void UnusedPruner::operator()(Block& _block) else if (varDecl.variables.size() == 1 && m_dialect.discardFunctionHandle()) statement = ExpressionStatement{varDecl.debugData, FunctionCall{ varDecl.debugData, - {varDecl.debugData, YulName{m_dialect.builtin(*m_dialect.discardFunctionHandle()).name}}, + BuiltinName{varDecl.debugData, *m_dialect.discardFunctionHandle()}, {*std::move(varDecl.value)} }}; } @@ -121,7 +121,7 @@ void UnusedPruner::runUntilStabilised( Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects, + std::map const* _functionSideEffects, std::set const& _externallyUsedFunctions ) { @@ -146,7 +146,7 @@ void UnusedPruner::runUntilStabilisedOnFullAST( std::set const& _externallyUsedFunctions ) { - std::map functionSideEffects = + std::map functionSideEffects = SideEffectsPropagator::sideEffects(_dialect, CallGraphGenerator::callGraph(_ast)); bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _ast); runUntilStabilised(_dialect, _ast, allowMSizeOptimization, &functionSideEffects, _externallyUsedFunctions); @@ -157,7 +157,7 @@ bool UnusedPruner::used(YulName _name) const return m_references.count(_name) && m_references.at(_name) > 0; } -void UnusedPruner::subtractReferences(std::map const& _subtrahend) +void UnusedPruner::subtractReferences(std::map const& _subtrahend) { for (auto const& ref: _subtrahend) { diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index 040e7ce43..37d26bbb0 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -52,7 +52,6 @@ class UnusedPruner: public ASTModifier static constexpr char const* name{"UnusedPruner"}; static void run(OptimiserStepContext& _context, Block& _ast); - using ASTModifier::operator(); void operator()(Block& _block) override; @@ -64,7 +63,7 @@ class UnusedPruner: public ASTModifier Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects = nullptr, + std::map const* _functionSideEffects = nullptr, std::set const& _externallyUsedFunctions = {} ); @@ -83,18 +82,18 @@ class UnusedPruner: public ASTModifier Dialect const& _dialect, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects = nullptr, + std::map const* _functionSideEffects = nullptr, std::set const& _externallyUsedFunctions = {} ); bool used(YulName _name) const; - void subtractReferences(std::map const& _subtrahend); + void subtractReferences(std::map const& _subtrahend); Dialect const& m_dialect; bool m_allowMSizeOptimization = false; - std::map const* m_functionSideEffects = nullptr; + std::map const* m_functionSideEffects = nullptr; bool m_shouldRunAgain = false; - std::map m_references; + std::map m_references; }; } diff --git a/libyul/optimiser/UnusedStoreEliminator.cpp b/libyul/optimiser/UnusedStoreEliminator.cpp index 7c68d577b..6f2f1ee93 100644 --- a/libyul/optimiser/UnusedStoreEliminator.cpp +++ b/libyul/optimiser/UnusedStoreEliminator.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -45,7 +46,7 @@ using namespace solidity::yul; void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) { - std::map functionSideEffects = SideEffectsPropagator::sideEffects( + std::map functionSideEffects = SideEffectsPropagator::sideEffects( _context.dialect, CallGraphGenerator::callGraph(_ast) ); @@ -81,7 +82,7 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) UnusedStoreEliminator::UnusedStoreEliminator( Dialect const& _dialect, - std::map const& _functionSideEffects, + std::map const& _functionSideEffects, std::map _controlFlowSideEffects, std::map const& _ssaValues, bool _ignoreMemory @@ -89,9 +90,9 @@ UnusedStoreEliminator::UnusedStoreEliminator( UnusedStoreBase(_dialect), m_ignoreMemory(_ignoreMemory), m_functionSideEffects(_functionSideEffects), - m_controlFlowSideEffects(_controlFlowSideEffects), + m_controlFlowSideEffects(std::move(_controlFlowSideEffects)), m_ssaValues(_ssaValues), - m_knowledgeBase(_ssaValues) + m_knowledgeBase(_ssaValues, _dialect) {} void UnusedStoreEliminator::operator()(FunctionCall const& _functionCall) @@ -102,10 +103,13 @@ void UnusedStoreEliminator::operator()(FunctionCall const& _functionCall) applyOperation(op); ControlFlowSideEffects sideEffects; - if (std::optional const builtinHandle = m_dialect.findBuiltin(_functionCall.functionName.name.str())) - sideEffects = m_dialect.builtin(*builtinHandle).controlFlowSideEffects; + if (auto builtin = resolveBuiltinFunction(_functionCall.functionName, m_dialect)) + sideEffects = builtin->controlFlowSideEffects; else - sideEffects = m_controlFlowSideEffects.at(_functionCall.functionName.name); + { + yulAssert(std::holds_alternative(_functionCall.functionName)); + sideEffects = m_controlFlowSideEffects.at(std::get(_functionCall.functionName).name); + } if (sideEffects.canTerminate) markActiveAsUsed(Location::Storage); @@ -141,7 +145,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement) FunctionCall const* funCall = std::get_if(&exprStatement->expression); yulAssert(funCall); - std::optional instruction = toEVMInstruction(m_dialect, funCall->functionName.name); + std::optional instruction = toEVMInstruction(m_dialect, funCall->functionName); if (!instruction) return; @@ -189,7 +193,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement) if ( m_knowledgeBase.knownToBeZero(*startOffset) && lengthCall && - toEVMInstruction(m_dialect, lengthCall->functionName.name) == Instruction::RETURNDATASIZE + toEVMInstruction(m_dialect, lengthCall->functionName) == Instruction::RETURNDATASIZE ) allowReturndatacopyToBeRemoved = true; } @@ -216,14 +220,16 @@ std::vector UnusedStoreEliminator::operationsF { using evmasm::Instruction; - YulName functionName = _functionCall.functionName.name; SideEffects sideEffects; - if (std::optional const builtinHandle = m_dialect.findBuiltin(functionName.str())) - sideEffects = m_dialect.builtin(*builtinHandle).sideEffects; + if (BuiltinFunction const* f = resolveBuiltinFunction(_functionCall.functionName, m_dialect)) + sideEffects = f->sideEffects; else - sideEffects = m_functionSideEffects.at(functionName); + { + yulAssert(std::holds_alternative(_functionCall.functionName)); + sideEffects = m_functionSideEffects.at(std::get(_functionCall.functionName).name); + } - std::optional instruction = toEVMInstruction(m_dialect, functionName); + std::optional instruction = toEVMInstruction(m_dialect, _functionCall.functionName); if (!instruction) { std::vector result; diff --git a/libyul/optimiser/UnusedStoreEliminator.h b/libyul/optimiser/UnusedStoreEliminator.h index f749a229c..6da33a986 100644 --- a/libyul/optimiser/UnusedStoreEliminator.h +++ b/libyul/optimiser/UnusedStoreEliminator.h @@ -62,7 +62,7 @@ class UnusedStoreEliminator: public UnusedStoreBase explicit UnusedStoreEliminator( Dialect const& _dialect, - std::map const& _functionSideEffects, + std::map const& _functionSideEffects, std::map _controlFlowSideEffects, std::map const& _ssaValues, bool _ignoreMemory @@ -122,7 +122,7 @@ class UnusedStoreEliminator: public UnusedStoreBase std::optional identifierNameIfSSA(Expression const& _expression) const; bool const m_ignoreMemory; - std::map const& m_functionSideEffects; + std::map const& m_functionSideEffects; std::map m_controlFlowSideEffects; std::map const& m_ssaValues; diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index a98c7a323..b797564b7 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -59,12 +59,13 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con m_obtainedResult.clear(); for (std::string contractName: compiler().contractNames()) { + auto const& dialect = EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion(), CommonOptions::get().eofVersion()); ErrorList errors; std::optional const& ir = compiler().yulIR(contractName); solAssert(ir); auto [object, analysisInfo] = yul::test::parse( *ir, - EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion(), CommonOptions::get().eofVersion()), + dialect, errors ); @@ -78,7 +79,8 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con auto handleObject = [&](std::string const& _kind, Object const& _object) { m_obtainedResult += contractName + "(" + _kind + ") " + (findFunctionCalls( _object.code()->root(), - "memoryguard"_yulname + "memoryguard", + dialect ).empty() ? "false" : "true") + "\n"; }; handleObject("creation", *object); diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index 0aaaea581..bd0bf0a80 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -64,8 +64,9 @@ static std::string variableSlotToString(VariableSlot const& _slot) class ControlFlowGraphPrinter { public: - ControlFlowGraphPrinter(std::ostream& _stream): - m_stream(_stream) + ControlFlowGraphPrinter(std::ostream& _stream, Dialect const& _dialect): + m_stream(_stream), + m_dialect(_dialect) { } void operator()(CFG::BasicBlock const& _block, bool _isMainEntry = true) @@ -133,7 +134,7 @@ class ControlFlowGraphPrinter m_stream << _call.function.get().name.str() << ": "; }, [&](CFG::BuiltinCall const& _call) { - m_stream << _call.functionCall.get().functionName.name.str() << ": "; + m_stream << _call.builtin.get().name << ": "; }, [&](CFG::Assignment const& _assignment) { m_stream << "Assignment("; @@ -141,7 +142,7 @@ class ControlFlowGraphPrinter m_stream << "): "; } }, operation.operation); - m_stream << stackToString(operation.input) << " => " << stackToString(operation.output) << "\\l\\\n"; + m_stream << stackToString(operation.input, m_dialect) << " => " << stackToString(operation.output, m_dialect) << "\\l\\\n"; } m_stream << "\"];\n"; std::visit(util::GenericVisitor{ @@ -163,7 +164,7 @@ class ControlFlowGraphPrinter { m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; m_stream << "Block" << getBlockId(_block) << "Exit [label=\"{ "; - m_stream << stackSlotToString(_conditionalJump.condition); + m_stream << stackSlotToString(_conditionalJump.condition, m_dialect); m_stream << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; m_stream << "Block" << getBlockId(_block); m_stream << "Exit:0 -> Block" << getBlockId(*_conditionalJump.zero) << ";\n"; @@ -192,6 +193,7 @@ class ControlFlowGraphPrinter return id; } std::ostream& m_stream; + Dialect const& m_dialect; std::map m_blockIds; size_t m_blockCount = 0; std::list m_blocksToPrint; @@ -212,7 +214,7 @@ TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::strin std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code()->root()); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - ControlFlowGraphPrinter printer{output}; + ControlFlowGraphPrinter printer{output, *m_dialect}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index 46a7c99fe..204150ad8 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -29,6 +29,7 @@ #include #include +#include #include @@ -92,14 +93,20 @@ TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); - std::map functionSideEffects = SideEffectsPropagator::sideEffects( + std::map functionSideEffects = SideEffectsPropagator::sideEffects( dialect, CallGraphGenerator::callGraph(obj.code()->root()) ); std::map functionSideEffectsStr; for (auto const& fun: functionSideEffects) - functionSideEffectsStr[fun.first.str()] = toString(fun.second); + { + auto const& functionNameStr = std::visit(GenericVisitor{ + [](YulName const& _name) { return _name.str(); }, + [&](BuiltinHandle const& _builtin) { return dialect.builtin(_builtin).name; } + }, fun.first); + functionSideEffectsStr[functionNameStr] = toString(fun.second); + } m_obtainedResult.clear(); for (auto const& fun: functionSideEffectsStr) diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index 0e7d411a3..eefeb9010 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -60,7 +60,7 @@ class KnowledgeBaseTest m_values[name].value = expression; m_object->setCode(std::make_shared(m_dialect, std::move(astRoot))); - return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }); + return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }, m_dialect); } EVMDialect m_dialect{solidity::test::CommonOptions::get().evmVersion(), diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 49af089ef..b41f7f21e 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -69,8 +69,8 @@ static std::string variableSlotToString(VariableSlot const& _slot) class StackLayoutPrinter { public: - StackLayoutPrinter(std::ostream& _stream, StackLayout const& _stackLayout): - m_stream(_stream), m_stackLayout(_stackLayout) + StackLayoutPrinter(std::ostream& _stream, StackLayout const& _stackLayout, Dialect const& _dialect): + m_stream(_stream), m_stackLayout(_stackLayout), m_dialect(_dialect) { } void operator()(CFG::BasicBlock const& _block, bool _isMainEntry = true) @@ -104,7 +104,7 @@ class StackLayoutPrinter m_stream << "\\l\\\n"; Stack functionEntryStack = {FunctionReturnLabelSlot{_info.function}}; functionEntryStack += _info.parameters | ranges::views::reverse; - m_stream << stackToString(functionEntryStack) << "\"];\n"; + m_stream << stackToString(functionEntryStack, m_dialect) << "\"];\n"; m_stream << "FunctionEntry_" << _info.function.name.str() << " -> Block" << getBlockId(*_info.entry) << ";\n"; (*this)(*_info.entry, false); } @@ -135,17 +135,17 @@ class StackLayoutPrinter }, entry->exit); auto const& blockInfo = m_stackLayout.blockInfos.at(&_block); - m_stream << stackToString(blockInfo.entryLayout) << "\\l\\\n"; + m_stream << stackToString(blockInfo.entryLayout, m_dialect) << "\\l\\\n"; for (auto const& operation: _block.operations) { auto entryLayout = m_stackLayout.operationEntryLayout.at(&operation); - m_stream << stackToString(m_stackLayout.operationEntryLayout.at(&operation)) << "\\l\\\n"; + m_stream << stackToString(m_stackLayout.operationEntryLayout.at(&operation), m_dialect) << "\\l\\\n"; std::visit(util::GenericVisitor{ [&](CFG::FunctionCall const& _call) { m_stream << _call.function.get().name.str(); }, [&](CFG::BuiltinCall const& _call) { - m_stream << _call.functionCall.get().functionName.name.str(); + m_stream << _call.builtin.get().name; }, [&](CFG::Assignment const& _assignment) { @@ -159,9 +159,9 @@ class StackLayoutPrinter for (size_t i = 0; i < operation.input.size(); ++i) entryLayout.pop_back(); entryLayout += operation.output; - m_stream << stackToString(entryLayout) << "\\l\\\n"; + m_stream << stackToString(entryLayout, m_dialect) << "\\l\\\n"; } - m_stream << stackToString(blockInfo.exitLayout) << "\\l\\\n"; + m_stream << stackToString(blockInfo.exitLayout, m_dialect) << "\\l\\\n"; m_stream << "\"];\n"; std::visit(util::GenericVisitor{ [&](CFG::BasicBlock::MainExit const&) @@ -182,7 +182,7 @@ class StackLayoutPrinter { m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; m_stream << "Block" << getBlockId(_block) << "Exit [label=\"{ "; - m_stream << stackSlotToString(_conditionalJump.condition); + m_stream << stackSlotToString(_conditionalJump.condition, m_dialect); m_stream << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; m_stream << "Block" << getBlockId(_block); m_stream << "Exit:0 -> Block" << getBlockId(*_conditionalJump.zero) << ";\n"; @@ -212,6 +212,7 @@ class StackLayoutPrinter } std::ostream& m_stream; StackLayout const& m_stackLayout; + Dialect const& m_dialect; std::map m_blockIds; size_t m_blockCount = 0; std::list m_blocksToPrint; @@ -238,7 +239,7 @@ TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::s StackLayout stackLayout = StackLayoutGenerator::run(*cfg, simulateFunctionsWithJumps); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - StackLayoutPrinter printer{output, stackLayout}; + StackLayoutPrinter printer{output, stackLayout, *m_dialect}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/StackShufflingTest.cpp b/test/libyul/StackShufflingTest.cpp index 40fdcc5b1..baf8e0c8e 100644 --- a/test/libyul/StackShufflingTest.cpp +++ b/test/libyul/StackShufflingTest.cpp @@ -17,9 +17,13 @@ #include +#include + +#include +#include + #include #include -#include using namespace solidity::util; using namespace solidity::langutil; @@ -137,6 +141,10 @@ StackShufflingTest::StackShufflingTest(std::string const& _filename): TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { + auto const& dialect = EVMDialect::strictAssemblyForEVMObjects( + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion() + ); if (!parse(m_source)) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; @@ -149,14 +157,14 @@ TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string m_targetStack, [&](unsigned _swapDepth) // swap { - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, dialect) << std::endl; output << "SWAP" << _swapDepth << std::endl; }, [&](StackSlot const& _slot) // dupOrPush { - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, dialect) << std::endl; if (canBeFreelyGenerated(_slot)) - output << "PUSH " << stackSlotToString(_slot) << std::endl; + output << "PUSH " << stackSlotToString(_slot, dialect) << std::endl; else { if (auto depth = util::findOffset(m_sourceStack | ranges::views::reverse, _slot)) @@ -166,12 +174,12 @@ TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string } }, [&](){ // pop - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, dialect) << std::endl; output << "POP" << std::endl; } ); - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, dialect) << std::endl; m_obtainedResult = output.str(); return checkResult(_stream, _linePrefix, _formatted); diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index 433ff3f07..2709d1b46 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -309,42 +309,39 @@ void ExpressionEvaluator::operator()(Identifier const& _identifier) void ExpressionEvaluator::operator()(FunctionCall const& _funCall) { std::vector> const* literalArguments = nullptr; - if (std::optional builtinHandle = m_dialect.findBuiltin(_funCall.functionName.name.str())) - if ( - auto const& args = m_dialect.builtin(*builtinHandle).literalArguments; - !args.empty() - ) - literalArguments = &args; + if (BuiltinFunction const* builtin = resolveBuiltinFunction(_funCall.functionName, m_dialect)) + if (!builtin->literalArguments.empty()) + literalArguments = &builtin->literalArguments; evaluateArgs(_funCall.arguments, literalArguments); if (EVMDialect const* dialect = dynamic_cast(&m_dialect)) { - if (std::optional builtinHandle = dialect->findBuiltin(_funCall.functionName.name.str())) + if (BuiltinFunctionForEVM const* fun = resolveBuiltinFunctionForEVM(_funCall.functionName, *dialect)) { - auto const& fun = dialect->builtin(*builtinHandle); EVMInstructionInterpreter interpreter(dialect->evmVersion(), m_state, m_disableMemoryTrace); - u256 const value = interpreter.evalBuiltin(fun, _funCall.arguments, values()); + u256 const value = interpreter.evalBuiltin(*fun, _funCall.arguments, values()); if ( !m_disableExternalCalls && - fun.instruction && - evmasm::isCallInstruction(*fun.instruction) + fun->instruction && + evmasm::isCallInstruction(*fun->instruction) ) - runExternalCall(*fun.instruction); + runExternalCall(*fun->instruction); setValue(value); return; } } + yulAssert(!isBuiltinFunctionCall(_funCall)); Scope* scope = &m_scope; for (; scope; scope = scope->parent) - if (scope->names.count(_funCall.functionName.name)) + if (scope->names.count(std::get(_funCall.functionName).name)) break; yulAssert(scope, ""); - FunctionDefinition const* fun = scope->names.at(_funCall.functionName.name); + FunctionDefinition const* fun = scope->names.at(std::get(_funCall.functionName).name); yulAssert(fun, "Function not found."); yulAssert(m_values.size() == fun->parameters.size(), ""); std::map variables; From 1380016cc3e20797b2e663e34e7aa2dcb980572c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:34:46 +0200 Subject: [PATCH 0520/1340] Add Yul tests to test erroneous assignment to builtins and numbers --- test/libyul/yulSyntaxTests/assignment_to_builtin.yul | 6 ++++++ test/libyul/yulSyntaxTests/assignment_to_number.yul | 6 ++++++ 2 files changed, 12 insertions(+) create mode 100644 test/libyul/yulSyntaxTests/assignment_to_builtin.yul create mode 100644 test/libyul/yulSyntaxTests/assignment_to_number.yul diff --git a/test/libyul/yulSyntaxTests/assignment_to_builtin.yul b/test/libyul/yulSyntaxTests/assignment_to_builtin.yul new file mode 100644 index 000000000..80f84c134 --- /dev/null +++ b/test/libyul/yulSyntaxTests/assignment_to_builtin.yul @@ -0,0 +1,6 @@ +{ + function f() -> x {} + add := f() +} +// ---- +// ParserError 6272: (35-37): Cannot assign to builtin function "add". diff --git a/test/libyul/yulSyntaxTests/assignment_to_number.yul b/test/libyul/yulSyntaxTests/assignment_to_number.yul new file mode 100644 index 000000000..3c4517fdd --- /dev/null +++ b/test/libyul/yulSyntaxTests/assignment_to_number.yul @@ -0,0 +1,6 @@ +{ + function f() -> x {} + let 123 := f() +} +// ---- +// ParserError 2314: (35-38): Expected identifier but got 'Number' From 804c4848657b0cacbb20afb8610d2e0a62b403eb Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 6 Dec 2024 07:04:09 +0100 Subject: [PATCH 0521/1340] Yul BlockHasher: Do not hash number of arguments for function calls. --- libyul/optimiser/BlockHasher.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libyul/optimiser/BlockHasher.cpp b/libyul/optimiser/BlockHasher.cpp index 2cc7a6648..6e8e8ed62 100644 --- a/libyul/optimiser/BlockHasher.cpp +++ b/libyul/optimiser/BlockHasher.cpp @@ -66,7 +66,6 @@ void ASTHasherBase::hashFunctionCall(FunctionCall const& _funCall) { hash64(compileTimeLiteralHash("UserDefined")); hash64(_identifier.name.hash()); - hash64(_funCall.arguments.size()); } }; std::visit(visitor, _funCall.functionName); From 8994d85fb7f86804436c81a64f6ee998a6f01fac Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 6 Dec 2024 08:13:57 +0100 Subject: [PATCH 0522/1340] YulString accepts string_view --- libyul/AsmAnalysis.cpp | 2 +- libyul/YulString.h | 7 ++++--- libyul/backends/evm/SSAControlFlowGraphBuilder.cpp | 2 +- libyul/optimiser/ExpressionInliner.cpp | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 7d395a208..ddd7ad153 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -354,7 +354,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) validateInstructions(_funCall); m_sideEffects += builtin->sideEffects; } - else if (m_currentScope->lookup(YulName{std::string(resolveFunctionName(_funCall.functionName, m_dialect))}, GenericVisitor{ + else if (m_currentScope->lookup(YulName{resolveFunctionName(_funCall.functionName, m_dialect)}, GenericVisitor{ [&](Scope::Variable const&) { m_errorReporter.typeError( diff --git a/libyul/YulString.h b/libyul/YulString.h index bd9438e5a..d6c13f0d3 100644 --- a/libyul/YulString.h +++ b/libyul/YulString.h @@ -27,6 +27,7 @@ #include #include #include +#include #include namespace solidity::yul @@ -51,7 +52,7 @@ class YulStringRepository return inst; } - Handle stringToHandle(std::string const& _string) + Handle stringToHandle(std::string_view const _string) { if (_string.empty()) return { 0, emptyHash() }; @@ -68,7 +69,7 @@ class YulStringRepository } std::string const& idToString(size_t _id) const { return *m_strings.at(_id); } - static std::uint64_t hash(std::string const& v) + static std::uint64_t hash(std::string_view const v) { // FNV hash - can be replaced by a better one, e.g. xxhash64 std::uint64_t hash = emptyHash(); @@ -126,7 +127,7 @@ class YulString { public: YulString() = default; - explicit YulString(std::string const& _s): m_handle(YulStringRepository::instance().stringToHandle(_s)) {} + explicit YulString(std::string_view const _s): m_handle(YulStringRepository::instance().stringToHandle(_s)) {} YulString(YulString const&) = default; YulString(YulString&&) = default; YulString& operator=(YulString const&) = default; diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index b47248dd5..4597c56a5 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -563,7 +563,7 @@ std::vector SSAControlFlowGraphBuilder::visitFunctionCall(Funct } else { - YulName const functionName{std::string(resolveFunctionName(_call.functionName, m_dialect))}; + YulName const functionName{resolveFunctionName(_call.functionName, m_dialect)}; Scope::Function const& function = lookupFunction(functionName); auto const* definition = findFunctionDefinition(&function); yulAssert(definition); diff --git a/libyul/optimiser/ExpressionInliner.cpp b/libyul/optimiser/ExpressionInliner.cpp index 1dbd5ca98..0d59dab2d 100644 --- a/libyul/optimiser/ExpressionInliner.cpp +++ b/libyul/optimiser/ExpressionInliner.cpp @@ -53,7 +53,7 @@ void ExpressionInliner::visit(Expression& _expression) if (std::holds_alternative(_expression)) { FunctionCall& funCall = std::get(_expression); - YulString const functionName{std::string(resolveFunctionName(funCall.functionName, m_dialect))}; + YulString const functionName{resolveFunctionName(funCall.functionName, m_dialect)}; if (!m_inlinableFunctions.count(functionName)) return; FunctionDefinition const& fun = *m_inlinableFunctions.at(functionName); From a9f0b3d2aec443c95294fc6c8640e77bc77b377b Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 9 Dec 2024 15:04:16 +0100 Subject: [PATCH 0523/1340] eof: eof: Fix legacy `create2` and `extcodehash` error for EOF --- libyul/AsmAnalysis.cpp | 2 ++ test/libyul/yulSyntaxTests/eof/create2_in_eof.yul | 11 +++++++++++ test/libyul/yulSyntaxTests/eof/extcodehash_in_eof.yul | 11 +++++++++++ 3 files changed, 24 insertions(+) create mode 100644 test/libyul/yulSyntaxTests/eof/create2_in_eof.yul create mode 100644 test/libyul/yulSyntaxTests/eof/extcodehash_in_eof.yul diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 9d816061c..55f5af4cf 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -783,10 +783,12 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio _instr == evmasm::Instruction::JUMPI || _instr == evmasm::Instruction::PC || _instr == evmasm::Instruction::CREATE || + _instr == evmasm::Instruction::CREATE2 || _instr == evmasm::Instruction::CODESIZE || _instr == evmasm::Instruction::CODECOPY || _instr == evmasm::Instruction::EXTCODESIZE || _instr == evmasm::Instruction::EXTCODECOPY || + _instr == evmasm::Instruction::EXTCODEHASH || _instr == evmasm::Instruction::GAS )) { diff --git a/test/libyul/yulSyntaxTests/eof/create2_in_eof.yul b/test/libyul/yulSyntaxTests/eof/create2_in_eof.yul new file mode 100644 index 000000000..77c106947 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/create2_in_eof.yul @@ -0,0 +1,11 @@ +object "a" { + code { + pop(create2(0, 0, 0, 0)) + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 9132: (36-43): The "create2" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (36-55): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libyul/yulSyntaxTests/eof/extcodehash_in_eof.yul b/test/libyul/yulSyntaxTests/eof/extcodehash_in_eof.yul new file mode 100644 index 000000000..79bfb4499 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extcodehash_in_eof.yul @@ -0,0 +1,11 @@ +object "a" { + code { + pop(extcodehash(0)) + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 9132: (36-47): The "extcodehash" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). +// TypeError 3950: (36-50): Expected expression to evaluate to one value, but got 0 values instead. From becce9242634da8d909a123586ecad1d4f9042be Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 9 Dec 2024 17:32:17 +0100 Subject: [PATCH 0524/1340] Disable the stale action for issues. --- .github/workflows/stale.yml | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d982c43f2..0b3447282 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,4 +1,4 @@ -name: Check stale issues and pull requests +name: Check stale pull requests on: workflow_dispatch: @@ -6,12 +6,12 @@ on: - cron: '0 12 * * *' permissions: - issues: write pull-requests: write env: - BEFORE_ISSUE_STALE: 90 - BEFORE_ISSUE_CLOSE: 7 + # NOTE: We set the parameters below to -1, so issues will never be marked as stale or closed automatically. + BEFORE_ISSUE_STALE: -1 + BEFORE_ISSUE_CLOSE: -1 BEFORE_PR_STALE: 14 BEFORE_PR_CLOSE: 7 @@ -24,17 +24,7 @@ jobs: debug-only: false days-before-issue-stale: ${{ env.BEFORE_ISSUE_STALE }} days-before-issue-close: ${{ env.BEFORE_ISSUE_CLOSE }} - stale-issue-message: | - This issue has been marked as stale due to inactivity for the last ${{ env.BEFORE_ISSUE_STALE }} days. - It will be automatically closed in ${{ env.BEFORE_ISSUE_CLOSE }} days. - close-issue-message: | - Hi everyone! This issue has been automatically closed due to inactivity. - If you think this issue is still relevant in the latest Solidity version and you have something to [contribute](https://docs.soliditylang.org/en/latest/contributing.html), feel free to reopen. - However, unless the issue is a concrete proposal that can be implemented, we recommend starting a language discussion on the [forum](https://forum.soliditylang.org) instead. ascending: true - stale-issue-label: stale - close-issue-label: 'closed due inactivity' - exempt-issue-labels: 'bug :bug:,epic,roadmap,selected for development,must have,must have eventually,smt' stale-pr-message: | This pull request is stale because it has been open for ${{ env.BEFORE_PR_STALE }} days with no activity. It will be closed in ${{ env.BEFORE_PR_CLOSE }} days unless the `stale` label is removed. From 5efaa669208d26d847e2ac5f57a5195a3c487891 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 6 Dec 2024 07:42:31 +0100 Subject: [PATCH 0525/1340] Yul: Make Dialect into a class. --- libsolidity/ast/AST.h | 2 +- libsolidity/ast/ASTAnnotations.h | 2 +- libyul/AST.h | 2 +- libyul/AsmJsonConverter.h | 2 +- libyul/AsmJsonImporter.h | 2 +- libyul/AsmPrinter.h | 2 +- libyul/ControlFlowSideEffectsCollector.h | 2 +- libyul/Dialect.h | 3 ++- libyul/Object.h | 2 +- libyul/Utilities.h | 2 +- libyul/backends/evm/ConstantOptimiser.h | 2 +- libyul/optimiser/CommonSubexpressionEliminator.h | 2 +- libyul/optimiser/ControlFlowSimplifier.h | 2 +- libyul/optimiser/DataFlowAnalyzer.h | 2 +- libyul/optimiser/DeadCodeEliminator.h | 2 +- libyul/optimiser/Disambiguator.h | 2 +- libyul/optimiser/ExpressionInliner.h | 2 +- libyul/optimiser/ExpressionSimplifier.h | 2 +- libyul/optimiser/ExpressionSplitter.h | 2 +- libyul/optimiser/FunctionCallFinder.h | 2 +- libyul/optimiser/KnowledgeBase.h | 2 +- libyul/optimiser/Metrics.h | 2 +- libyul/optimiser/NameDispenser.h | 2 +- libyul/optimiser/NameDisplacer.h | 2 +- libyul/optimiser/NameSimplifier.h | 2 +- libyul/optimiser/OptimiserStep.h | 2 +- libyul/optimiser/Semantics.h | 2 +- libyul/optimiser/SimplificationRules.h | 2 +- libyul/optimiser/StackCompressor.h | 2 +- libyul/optimiser/Suite.h | 2 +- libyul/optimiser/UnusedAssignEliminator.h | 2 +- libyul/optimiser/UnusedPruner.h | 2 +- libyul/optimiser/UnusedStoreBase.h | 2 +- libyul/optimiser/UnusedStoreEliminator.h | 2 +- libyul/optimiser/VarNameCleaner.h | 2 +- test/libyul/Common.h | 2 +- test/libyul/ControlFlowGraphTest.h | 2 +- test/libyul/SSAControlFlowGraphTest.h | 2 +- test/libyul/StackLayoutGeneratorTest.h | 2 +- test/libyul/YulOptimizerTest.h | 2 +- test/libyul/YulOptimizerTestCommon.h | 2 +- test/tools/yulInterpreter/Interpreter.h | 2 +- tools/yulPhaser/Program.h | 2 +- 43 files changed, 44 insertions(+), 43 deletions(-) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 0e2df8a90..fa2ce2094 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -49,7 +49,7 @@ namespace solidity::yul { // Forward-declaration to class AST; -struct Dialect; +class Dialect; } namespace solidity::frontend diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 81b3b8374..f017481be 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -39,7 +39,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; struct Identifier; -struct Dialect; +class Dialect; } namespace solidity::frontend diff --git a/libyul/AST.h b/libyul/AST.h index b19499b9a..6a49db68e 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -37,7 +37,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct NameWithDebugData { langutil::DebugData::ConstPtr debugData; YulName name; }; using NameWithDebugDataList = std::vector; diff --git a/libyul/AsmJsonConverter.h b/libyul/AsmJsonConverter.h index 458142e29..6705197f9 100644 --- a/libyul/AsmJsonConverter.h +++ b/libyul/AsmJsonConverter.h @@ -33,7 +33,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Converter of the yul AST into JSON format diff --git a/libyul/AsmJsonImporter.h b/libyul/AsmJsonImporter.h index 2d7ff472c..830e44b3a 100644 --- a/libyul/AsmJsonImporter.h +++ b/libyul/AsmJsonImporter.h @@ -32,7 +32,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Component that imports an AST from json format to the internal format diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index d889d83f8..60a7f9a0f 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -37,7 +37,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Converts a parsed Yul AST into readable string representation. diff --git a/libyul/ControlFlowSideEffectsCollector.h b/libyul/ControlFlowSideEffectsCollector.h index 5a1c76297..2ef7a4bfa 100644 --- a/libyul/ControlFlowSideEffectsCollector.h +++ b/libyul/ControlFlowSideEffectsCollector.h @@ -29,7 +29,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct ControlFlowNode { diff --git a/libyul/Dialect.h b/libyul/Dialect.h index 62d18bdf0..2afd4a579 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -57,8 +57,9 @@ struct BuiltinFunction } }; -struct Dialect +class Dialect { +public: /// Noncopiable. Dialect(Dialect const&) = delete; Dialect& operator=(Dialect const&) = delete; diff --git a/libyul/Object.h b/libyul/Object.h index 295c4a87c..c865b906e 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -36,7 +36,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct AsmAnalysisInfo; using SourceNameMap = std::map>; diff --git a/libyul/Utilities.h b/libyul/Utilities.h index a4a558a85..64b5f456a 100644 --- a/libyul/Utilities.h +++ b/libyul/Utilities.h @@ -30,7 +30,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; class EVMDialect; struct BuiltinFunction; struct BuiltinFunctionForEVM; diff --git a/libyul/backends/evm/ConstantOptimiser.h b/libyul/backends/evm/ConstantOptimiser.h index 5e4b2002b..9c25450bf 100644 --- a/libyul/backends/evm/ConstantOptimiser.h +++ b/libyul/backends/evm/ConstantOptimiser.h @@ -37,7 +37,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; class GasMeter; /** diff --git a/libyul/optimiser/CommonSubexpressionEliminator.h b/libyul/optimiser/CommonSubexpressionEliminator.h index 35f8168eb..713c35f02 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.h +++ b/libyul/optimiser/CommonSubexpressionEliminator.h @@ -32,7 +32,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct SideEffects; /** diff --git a/libyul/optimiser/ControlFlowSimplifier.h b/libyul/optimiser/ControlFlowSimplifier.h index 86ebf296c..829138471 100644 --- a/libyul/optimiser/ControlFlowSimplifier.h +++ b/libyul/optimiser/ControlFlowSimplifier.h @@ -22,7 +22,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct OptimiserStepContext; /** diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index 7d0f78b53..5b1cf25ff 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -37,7 +37,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct SideEffects; class KnowledgeBase; diff --git a/libyul/optimiser/DeadCodeEliminator.h b/libyul/optimiser/DeadCodeEliminator.h index f252536c5..701af3ad1 100644 --- a/libyul/optimiser/DeadCodeEliminator.h +++ b/libyul/optimiser/DeadCodeEliminator.h @@ -30,7 +30,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct OptimiserStepContext; /** diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index 08d8d158f..36d178b08 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -31,7 +31,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Creates a copy of a Yul AST replacing all identifiers by unique names. diff --git a/libyul/optimiser/ExpressionInliner.h b/libyul/optimiser/ExpressionInliner.h index 08ff08648..f8cf70d56 100644 --- a/libyul/optimiser/ExpressionInliner.h +++ b/libyul/optimiser/ExpressionInliner.h @@ -29,7 +29,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct OptimiserStepContext; /** diff --git a/libyul/optimiser/ExpressionSimplifier.h b/libyul/optimiser/ExpressionSimplifier.h index 662c8c389..b004c9b52 100644 --- a/libyul/optimiser/ExpressionSimplifier.h +++ b/libyul/optimiser/ExpressionSimplifier.h @@ -27,7 +27,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct OptimiserStepContext; /** diff --git a/libyul/optimiser/ExpressionSplitter.h b/libyul/optimiser/ExpressionSplitter.h index 0b223e985..2581b23de 100644 --- a/libyul/optimiser/ExpressionSplitter.h +++ b/libyul/optimiser/ExpressionSplitter.h @@ -31,7 +31,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct OptimiserStepContext; /** diff --git a/libyul/optimiser/FunctionCallFinder.h b/libyul/optimiser/FunctionCallFinder.h index 067aee2a3..1c21a0115 100644 --- a/libyul/optimiser/FunctionCallFinder.h +++ b/libyul/optimiser/FunctionCallFinder.h @@ -28,7 +28,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Finds all calls to a function of a given name using an ASTModifier. diff --git a/libyul/optimiser/KnowledgeBase.h b/libyul/optimiser/KnowledgeBase.h index 78daadbc4..0852f8902 100644 --- a/libyul/optimiser/KnowledgeBase.h +++ b/libyul/optimiser/KnowledgeBase.h @@ -34,7 +34,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct AssignedValue; /** diff --git a/libyul/optimiser/Metrics.h b/libyul/optimiser/Metrics.h index 53ff25325..cdcc28822 100644 --- a/libyul/optimiser/Metrics.h +++ b/libyul/optimiser/Metrics.h @@ -27,7 +27,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; class EVMDialect; /** diff --git a/libyul/optimiser/NameDispenser.h b/libyul/optimiser/NameDispenser.h index 3da50359a..ec936d39a 100644 --- a/libyul/optimiser/NameDispenser.h +++ b/libyul/optimiser/NameDispenser.h @@ -28,7 +28,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Optimizer component that can be used to generate new names that diff --git a/libyul/optimiser/NameDisplacer.h b/libyul/optimiser/NameDisplacer.h index 3312e203d..cfe297d4d 100644 --- a/libyul/optimiser/NameDisplacer.h +++ b/libyul/optimiser/NameDisplacer.h @@ -29,7 +29,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Optimiser component that renames identifiers to free up certain names. diff --git a/libyul/optimiser/NameSimplifier.h b/libyul/optimiser/NameSimplifier.h index 0ff5077cc..f3426d60f 100644 --- a/libyul/optimiser/NameSimplifier.h +++ b/libyul/optimiser/NameSimplifier.h @@ -30,7 +30,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Pass to "simplify" all identifier names. diff --git a/libyul/optimiser/OptimiserStep.h b/libyul/optimiser/OptimiserStep.h index 89bfcef81..7425a1906 100644 --- a/libyul/optimiser/OptimiserStep.h +++ b/libyul/optimiser/OptimiserStep.h @@ -27,7 +27,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct Block; class NameDispenser; diff --git a/libyul/optimiser/Semantics.h b/libyul/optimiser/Semantics.h index 9fdeb78d0..9d3c724af 100644 --- a/libyul/optimiser/Semantics.h +++ b/libyul/optimiser/Semantics.h @@ -31,7 +31,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Specific AST walker that determines side-effect free-ness and movability of code. diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index 2d48464ca..f4b584b99 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -40,7 +40,7 @@ namespace solidity::yul { struct AssignedValue; -struct Dialect; +class Dialect; class EVMDialect; class Pattern; diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index b0b086a7e..d5590006c 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -29,7 +29,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; class Object; struct FunctionDefinition; diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index bd3e1aa05..b0c331408 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -36,7 +36,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; -struct Dialect; +class Dialect; class GasMeter; class Object; diff --git a/libyul/optimiser/UnusedAssignEliminator.h b/libyul/optimiser/UnusedAssignEliminator.h index ea2116f03..73628c929 100644 --- a/libyul/optimiser/UnusedAssignEliminator.h +++ b/libyul/optimiser/UnusedAssignEliminator.h @@ -33,7 +33,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Optimiser component that removes assignments to variables that are not used diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index 37d26bbb0..cd9a7e341 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -30,7 +30,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct SideEffects; /** diff --git a/libyul/optimiser/UnusedStoreBase.h b/libyul/optimiser/UnusedStoreBase.h index e5c11c491..2c51224c0 100644 --- a/libyul/optimiser/UnusedStoreBase.h +++ b/libyul/optimiser/UnusedStoreBase.h @@ -31,7 +31,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Base class for both UnusedAssignEliminator and UnusedStoreEliminator. diff --git a/libyul/optimiser/UnusedStoreEliminator.h b/libyul/optimiser/UnusedStoreEliminator.h index 6da33a986..45d363dfc 100644 --- a/libyul/optimiser/UnusedStoreEliminator.h +++ b/libyul/optimiser/UnusedStoreEliminator.h @@ -36,7 +36,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; struct AssignedValue; /** diff --git a/libyul/optimiser/VarNameCleaner.h b/libyul/optimiser/VarNameCleaner.h index 7f8bb842e..47f3aca48 100644 --- a/libyul/optimiser/VarNameCleaner.h +++ b/libyul/optimiser/VarNameCleaner.h @@ -31,7 +31,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; /** * Pass to normalize identifier suffixes. diff --git a/test/libyul/Common.h b/test/libyul/Common.h index 54c61f875..e36e81052 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -38,7 +38,7 @@ namespace solidity::yul struct AsmAnalysisInfo; struct Block; class Object; -struct Dialect; +class Dialect; class AST; } diff --git a/test/libyul/ControlFlowGraphTest.h b/test/libyul/ControlFlowGraphTest.h index e9de50a61..953a27b22 100644 --- a/test/libyul/ControlFlowGraphTest.h +++ b/test/libyul/ControlFlowGraphTest.h @@ -22,7 +22,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; namespace test { diff --git a/test/libyul/SSAControlFlowGraphTest.h b/test/libyul/SSAControlFlowGraphTest.h index 09c104486..13ca2027a 100644 --- a/test/libyul/SSAControlFlowGraphTest.h +++ b/test/libyul/SSAControlFlowGraphTest.h @@ -24,7 +24,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; namespace test { diff --git a/test/libyul/StackLayoutGeneratorTest.h b/test/libyul/StackLayoutGeneratorTest.h index 6116b1df7..e1c6dc7f9 100644 --- a/test/libyul/StackLayoutGeneratorTest.h +++ b/test/libyul/StackLayoutGeneratorTest.h @@ -22,7 +22,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; namespace test { diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 241281288..207a4b8ce 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -30,7 +30,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; class Object; -struct Dialect; +class Dialect; } namespace solidity::yul::test diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h index b214b80c0..bc513e748 100644 --- a/test/libyul/YulOptimizerTestCommon.h +++ b/test/libyul/YulOptimizerTestCommon.h @@ -30,7 +30,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; class Object; -struct Dialect; +class Dialect; class AST; } diff --git a/test/tools/yulInterpreter/Interpreter.h b/test/tools/yulInterpreter/Interpreter.h index 356a19070..427a30d9e 100644 --- a/test/tools/yulInterpreter/Interpreter.h +++ b/test/tools/yulInterpreter/Interpreter.h @@ -35,7 +35,7 @@ namespace solidity::yul { -struct Dialect; +class Dialect; } namespace solidity::yul::test diff --git a/tools/yulPhaser/Program.h b/tools/yulPhaser/Program.h index be4bf582d..7ac7f3aad 100644 --- a/tools/yulPhaser/Program.h +++ b/tools/yulPhaser/Program.h @@ -43,7 +43,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; -struct Dialect; +class Dialect; struct CodeWeights; } From b1ce8a26fee9af9c4396d8531b238f5bcba98d40 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 9 Dec 2024 11:53:09 +0100 Subject: [PATCH 0526/1340] eof: Fix `library` argument setting in `deployCode` --- libsolidity/codegen/ir/IRGenerator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 48b646d35..688ab258a 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -1015,6 +1015,7 @@ std::string IRGenerator::deployCode(ContractDefinition const& _contract) if (eof) { + t("library", _contract.isLibrary()); t("auxDataStart", std::to_string(CompilerUtils::generalPurposeMemoryStart)); solAssert(m_context.reservedMemorySize() <= 0xFFFF, "Reserved memory size exceeded maximum allowed EOF data section size."); t("auxDataSize", std::to_string(m_context.reservedMemorySize())); From a26b2812aa231e63be1573b07d2a38f64c8878e1 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 6 Dec 2024 08:36:50 +0100 Subject: [PATCH 0527/1340] Add test::CommonOptions::evmDialect method --- test/Common.cpp | 16 ++++++++++++++-- test/Common.h | 6 ++++++ test/libsolidity/MemoryGuardTest.cpp | 2 +- test/libyul/ControlFlowSideEffectsTest.cpp | 8 +++----- test/libyul/EVMCodeTransformTest.cpp | 6 +++--- test/libyul/FunctionSideEffects.cpp | 8 +++----- test/libyul/StackShufflingTest.cpp | 6 ++---- test/libyul/YulInterpreterTest.cpp | 10 +++++----- 8 files changed, 37 insertions(+), 25 deletions(-) diff --git a/test/Common.cpp b/test/Common.cpp index bab95c457..43f73d4d7 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -16,19 +16,25 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include -#include #include + #include #include +#include + #include #include + #include #include #include + #include +#include +#include + namespace fs = boost::filesystem; namespace po = boost::program_options; @@ -260,6 +266,12 @@ langutil::EVMVersion CommonOptions::evmVersion() const return langutil::EVMVersion(); } +yul::EVMDialect const& CommonOptions::evmDialect() const +{ + return yul::EVMDialect::strictAssemblyForEVMObjects(evmVersion(), eofVersion()); +} + + CommonOptions const& CommonOptions::get() { if (!m_singleton) diff --git a/test/Common.h b/test/Common.h index 409d6f696..c3d21d258 100644 --- a/test/Common.h +++ b/test/Common.h @@ -29,6 +29,11 @@ #include #include +namespace solidity::yul +{ +class EVMDialect; +} + namespace solidity::test { @@ -66,6 +71,7 @@ struct CommonOptions langutil::EVMVersion evmVersion() const; std::optional eofVersion() const { return m_eofVersion; } + yul::EVMDialect const& evmDialect() const; virtual void addOptions(); // @returns true if the program should continue, false if it should exit immediately without diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index b797564b7..9826f4b19 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -59,7 +59,7 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con m_obtainedResult.clear(); for (std::string contractName: compiler().contractNames()) { - auto const& dialect = EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion(), CommonOptions::get().eofVersion()); + auto const& dialect = CommonOptions::get().evmDialect(); ErrorList errors; std::optional const& ir = compiler().yulIR(contractName); solAssert(ir); diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index 3dc576c8e..50c546e36 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -28,6 +28,7 @@ #include using namespace solidity; +using namespace solidity::test; using namespace solidity::yul; using namespace solidity::yul::test; using namespace solidity::frontend::test; @@ -56,12 +57,9 @@ ControlFlowSideEffectsTest::ControlFlowSideEffectsTest(std::string const& _filen TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - auto const& dialect = EVMDialect::strictAssemblyForEVMObjects( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + auto const& dialect = CommonOptions::get().evmDialect(); Object obj; - auto parsingResult = yul::test::parse(m_source); + auto parsingResult = parse(m_source); obj.setCode(parsingResult.first, parsingResult.second); if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 75d86136e..da2eaad0e 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -32,6 +32,7 @@ #include using namespace solidity; +using namespace solidity::test; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul; @@ -67,13 +68,12 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin return TestResult::FatalError; } - evmasm::Assembly assembly{solidity::test::CommonOptions::get().evmVersion(), false, std::nullopt, {}}; + evmasm::Assembly assembly{CommonOptions::get().evmVersion(), false, std::nullopt, {}}; EthAssemblyAdapter adapter(assembly); EVMObjectCompiler::compile( *stack.parserResult(), adapter, - EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion()), + CommonOptions::get().evmDialect(), m_stackOpt, std::nullopt ); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index 204150ad8..d19d87844 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -35,6 +35,7 @@ using namespace solidity; +using namespace solidity::test; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul; @@ -83,12 +84,9 @@ FunctionSideEffects::FunctionSideEffects(std::string const& _filename): TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - auto const& dialect = EVMDialect::strictAssemblyForEVMObjects( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + auto const& dialect = CommonOptions::get().evmDialect(); Object obj; - auto parsingResult = yul::test::parse(m_source); + auto parsingResult = parse(m_source); obj.setCode(parsingResult.first, parsingResult.second); if (!obj.hasCode()) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); diff --git a/test/libyul/StackShufflingTest.cpp b/test/libyul/StackShufflingTest.cpp index baf8e0c8e..258bc9204 100644 --- a/test/libyul/StackShufflingTest.cpp +++ b/test/libyul/StackShufflingTest.cpp @@ -25,6 +25,7 @@ #include #include +using namespace solidity::test; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul; @@ -141,10 +142,7 @@ StackShufflingTest::StackShufflingTest(std::string const& _filename): TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - auto const& dialect = EVMDialect::strictAssemblyForEVMObjects( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + auto const& dialect = CommonOptions::get().evmDialect(); if (!parse(m_source)) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index 484a7a241..25b348dfb 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -39,6 +39,7 @@ #include using namespace solidity; +using namespace solidity::test; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul; @@ -67,10 +68,10 @@ TestCase::TestResult YulInterpreterTest::run(std::ostream& _stream, std::string bool YulInterpreterTest::parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { YulStack stack( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion(), + CommonOptions::get().evmVersion(), + CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::none(), + OptimiserSettings::none(), DebugInfoSelection::All() ); if (stack.parseAndAnalyze("", m_source)) @@ -98,8 +99,7 @@ std::string YulInterpreterTest::interpret() { Interpreter::run( state, - EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion()), + CommonOptions::get().evmDialect(), m_ast->root(), /*disableExternalCalls=*/ !m_simulateExternalCallsToSelf, /*disableMemoryTracing=*/ false From 2ae6807f49d180d2493637d59ca8e723eca2b3d8 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 9 Dec 2024 11:23:43 +0100 Subject: [PATCH 0528/1340] eof: Introduce new instruction set for `ext*call` --- libevmasm/Instruction.cpp | 6 +++ libevmasm/Instruction.h | 6 +++ libevmasm/SemanticInformation.cpp | 38 +++++++++++++++++++ liblangutil/EVMVersion.cpp | 3 ++ libyul/AsmAnalysis.cpp | 15 ++++++++ libyul/backends/evm/EVMDialect.cpp | 15 +++++++- .../EVMInstructionInterpreter.cpp | 3 ++ 7 files changed, 85 insertions(+), 1 deletion(-) diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 82ed73cc9..649a6c863 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -182,6 +182,9 @@ std::map const solidity::evmasm::c_instructions = { "STATICCALL", Instruction::STATICCALL }, { "RETURN", Instruction::RETURN }, { "DELEGATECALL", Instruction::DELEGATECALL }, + { "EXTCALL", Instruction::EXTCALL }, + { "EXTSTATICCALL", Instruction::EXTSTATICCALL }, + { "EXTDELEGATECALL", Instruction::EXTDELEGATECALL }, { "CREATE2", Instruction::CREATE2 }, { "REVERT", Instruction::REVERT }, { "INVALID", Instruction::INVALID }, @@ -344,6 +347,9 @@ static std::map const c_instructionInfo = {Instruction::RETURN, {"RETURN", 0, 2, 0, true, Tier::Zero}}, {Instruction::DELEGATECALL, {"DELEGATECALL", 0, 6, 1, true, Tier::Special}}, {Instruction::STATICCALL, {"STATICCALL", 0, 6, 1, true, Tier::Special}}, + {Instruction::EXTCALL, {"EXTCALL", 0, 4, 1, true, Tier::Special}}, + {Instruction::EXTDELEGATECALL,{"EXTDELEGATECALL", 0, 3, 1, true, Tier::Special}}, + {Instruction::EXTSTATICCALL, {"EXTSTATICCALL", 0, 3, 1, true, Tier::Special}}, {Instruction::CREATE2, {"CREATE2", 0, 4, 1, true, Tier::Special}}, {Instruction::REVERT, {"REVERT", 0, 2, 0, true, Tier::Zero}}, {Instruction::INVALID, {"INVALID", 0, 0, 0, true, Tier::Zero}}, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 351a6981c..a1b9af364 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -198,7 +198,10 @@ enum class Instruction: uint8_t RETURN, ///< halt execution returning output data DELEGATECALL, ///< like CALLCODE but keeps caller's value and sender CREATE2 = 0xf5, ///< create new account with associated code at address `sha3(0xff + sender + salt + init code) % 2**160` + EXTCALL = 0xf8, ///< EOF message-call into an account + EXTDELEGATECALL = 0xf9, ///< EOF delegate call STATICCALL = 0xfa, ///< like CALL but disallow state modifications + EXTSTATICCALL = 0xfb, ///< like EXTCALL but disallow state modifications REVERT = 0xfd, ///< halt execution, revert state and return output data INVALID = 0xfe, ///< invalid instruction for expressing runtime errors (e.g., division-by-zero) @@ -214,6 +217,9 @@ constexpr bool isCallInstruction(Instruction _inst) noexcept case Instruction::CALLCODE: case Instruction::DELEGATECALL: case Instruction::STATICCALL: + case Instruction::EXTCALL: + case Instruction::EXTSTATICCALL: + case Instruction::EXTDELEGATECALL: return true; default: return false; diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index c27945b82..a9672efa5 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -169,6 +169,26 @@ std::vector SemanticInformation::readWriteOperat }); return operations; } + case Instruction::EXTCALL: + case Instruction::EXTSTATICCALL: + case Instruction::EXTDELEGATECALL: + { + size_t paramCount = static_cast(instructionInfo(_instruction, langutil::EVMVersion()).args); + size_t const memoryStartParam = _instruction == Instruction::EXTCALL ? paramCount - 3 : paramCount - 2; + size_t const memoryLengthParam = _instruction == Instruction::EXTCALL ? paramCount - 2 : paramCount - 1; + std::vector operations{ + Operation{Location::Memory, Effect::Read, memoryStartParam, memoryLengthParam, {}}, + Operation{Location::Storage, Effect::Read, {}, {}, {}}, + Operation{Location::TransientStorage, Effect::Read, {}, {}, {}} + }; + if (_instruction == Instruction::EXTDELEGATECALL) + { + operations.emplace_back(Operation{Location::Storage, Effect::Write, {}, {}, {}}); + operations.emplace_back(Operation{Location::TransientStorage, Effect::Write, {}, {}, {}}); + } + + return operations; + } case Instruction::CREATE: case Instruction::CREATE2: return std::vector{ @@ -380,6 +400,9 @@ bool SemanticInformation::isDeterministic(AssemblyItem const& _item) case Instruction::CALLCODE: case Instruction::DELEGATECALL: case Instruction::STATICCALL: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: + case Instruction::EXTSTATICCALL: case Instruction::CREATE: case Instruction::CREATE2: case Instruction::GAS: @@ -475,6 +498,9 @@ SemanticInformation::Effect SemanticInformation::memory(Instruction _instruction case Instruction::LOG4: case Instruction::EOFCREATE: case Instruction::RETURNCONTRACT: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: + case Instruction::EXTSTATICCALL: return SemanticInformation::Read; default: @@ -514,10 +540,13 @@ SemanticInformation::Effect SemanticInformation::storage(Instruction _instructio case Instruction::SSTORE: case Instruction::EOFCREATE: case Instruction::RETURNCONTRACT: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: return SemanticInformation::Write; case Instruction::SLOAD: case Instruction::STATICCALL: + case Instruction::EXTSTATICCALL: return SemanticInformation::Read; default: @@ -537,10 +566,13 @@ SemanticInformation::Effect SemanticInformation::transientStorage(Instruction _i case Instruction::TSTORE: case Instruction::EOFCREATE: case Instruction::RETURNCONTRACT: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: return SemanticInformation::Write; case Instruction::TLOAD: case Instruction::STATICCALL: + case Instruction::EXTSTATICCALL: return SemanticInformation::Read; default: @@ -559,7 +591,10 @@ SemanticInformation::Effect SemanticInformation::otherState(Instruction _instruc case Instruction::CREATE2: case Instruction::EOFCREATE: case Instruction::RETURNCONTRACT: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: case Instruction::SELFDESTRUCT: + case Instruction::EXTSTATICCALL: case Instruction::STATICCALL: // because it can affect returndatasize // Strictly speaking, log0, .., log4 writes to the state, but the EVM cannot read it, so they // are just marked as having 'other side effects.' @@ -606,6 +641,7 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction) case Instruction::NUMBER: case Instruction::PREVRANDAO: case Instruction::GASLIMIT: + case Instruction::EXTSTATICCALL: case Instruction::STATICCALL: case Instruction::SLOAD: case Instruction::TLOAD: @@ -635,6 +671,8 @@ bool SemanticInformation::invalidInViewFunctions(Instruction _instruction) case Instruction::CALL: case Instruction::CALLCODE: case Instruction::DELEGATECALL: + case Instruction::EXTCALL: + case Instruction::EXTDELEGATECALL: // According to EOF spec https://eips.ethereum.org/EIPS/eip-7620#eofcreate case Instruction::EOFCREATE: // According to EOF spec https://eips.ethereum.org/EIPS/eip-7620#returncontract diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index 26364f2af..6f7ac9139 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -85,6 +85,9 @@ bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersi case Instruction::CALLF: case Instruction::JUMPF: case Instruction::RETF: + case Instruction::EXTCALL: + case Instruction::EXTSTATICCALL: + case Instruction::EXTDELEGATECALL: return _eofVersion.has_value(); default: return true; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 55f5af4cf..fd826eaec 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -773,6 +773,21 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio "PC instruction is a low-level EVM feature. " "Because of that PC is disallowed in strict assembly." ); + else if (!m_eofVersion.has_value() && ( + _instr == evmasm::Instruction::EXTCALL || + _instr == evmasm::Instruction::EXTDELEGATECALL || + _instr == evmasm::Instruction::EXTSTATICCALL + )) + { + m_errorReporter.typeError( + 4328_error, + _location, + fmt::format( + "The \"{}\" instruction is only available on EOF.", + fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name)) + ) + ); + } else if (m_eofVersion.has_value() && ( _instr == evmasm::Instruction::CALL || _instr == evmasm::Instruction::CALLCODE || diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index c73a9a794..bb7a96953 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -153,6 +153,18 @@ std::set> createReservedIdentifiers(langutil::EVMVersio (_instr == evmasm::Instruction::TSTORE || _instr == evmasm::Instruction::TLOAD); }; + auto eofIdentifiersException = [&](evmasm::Instruction _instr) -> bool + { + solAssert(!_eofVersion.has_value() || _evmVersion >= langutil::EVMVersion::prague()); + return + !_eofVersion.has_value() && + ( + _instr == evmasm::Instruction::EXTCALL || + _instr == evmasm::Instruction::EXTSTATICCALL || + _instr == evmasm::Instruction::EXTDELEGATECALL + ); + }; + std::set> reserved; for (auto const& instr: evmasm::c_instructions) { @@ -163,7 +175,8 @@ std::set> createReservedIdentifiers(langutil::EVMVersio !blobHashException(instr.second) && !blobBaseFeeException(instr.second) && !mcopyException(instr.second) && - !transientStorageException(instr.second) + !transientStorageException(instr.second) && + !eofIdentifiersException(instr.second) ) reserved.emplace(name); } diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index 92ac56d69..94a6c3b1e 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -495,6 +495,9 @@ u256 EVMInstructionInterpreter::eval( case Instruction::RETURNCONTRACT: case Instruction::RJUMP: case Instruction::RJUMPI: + case Instruction::EXTCALL: + case Instruction::EXTSTATICCALL: + case Instruction::EXTDELEGATECALL: solUnimplemented("EOF not yet supported by Yul interpreter."); } From f495f676ac6749e219f40eca594f1c2f6f63a799 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 9 Dec 2024 11:23:43 +0100 Subject: [PATCH 0529/1340] eof: Use EOF `ext*call` in yul generator for statements. --- .../codegen/ir/IRGeneratorForStatements.cpp | 72 ++++++++++++++----- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 9b2e0ea77..babe43357 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1622,11 +1622,16 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) Whiskers templ(R"( let := 0 if iszero() { := } - let := call(,
, , 0, 0, 0, 0) + + let := iszero(extcall(
, 0, 0, )) + + let := call(,
, , 0, 0, 0, 0) + if iszero() { () } )"); + templ("eof", m_context.eofVersion().has_value()); templ("gas", m_context.newYulVariable()); templ("callStipend", toString(evmasm::GasCosts::callStipend)); templ("address", address); @@ -1669,17 +1674,30 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) mstore(0, 0) - let := (,
, 0, , sub(, ), 0, 32) + + // EOF always uses extstaticcall + let := iszero(extstaticcall(
, , sub(, ))) + + let := (,
, 0, , sub(, ), 0, 32) + if iszero() { () } + + if eq(returndatasize(), 32) { returndatacopy(0, 0, 32) } + let := (mload(0)) )"); - templ("call", m_context.evmVersion().hasStaticCall() ? "staticcall" : "call"); - templ("isCall", !m_context.evmVersion().hasStaticCall()); + auto const eof = m_context.eofVersion().has_value(); + if (!eof) + { + templ("call", m_context.evmVersion().hasStaticCall() ? "staticcall" : "call"); + templ("isCall", !m_context.evmVersion().hasStaticCall()); + } templ("shl", m_utils.shiftLeftFunction(offset * 8)); templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); templ("pos", m_context.newYulVariable()); templ("end", m_context.newYulVariable()); templ("isECRecover", FunctionType::Kind::ECRecover == functionType->kind()); + templ("eof", eof); if (FunctionType::Kind::ECRecover == functionType->kind()) templ("encodeArgs", m_context.abiFunctions().tupleEncoder(argumentTypes, parameterTypes)); else @@ -2630,7 +2648,6 @@ void IRGeneratorForStatements::appendExternalFunctionCall( argumentStrings += IRVariable(*arg).stackSlots(); } - if (!m_context.evmVersion().canOverchargeGasForCall()) { // Touch the end of the output area so that we do not pay for memory resize during the call @@ -2642,7 +2659,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall( } // NOTE: When the expected size of returndata is static, we pass that in to the call opcode and it gets copied automatically. - // When it's dynamic, we get zero from estimatedReturnSize() instead and then we need an explicit returndatacopy(). + // When it's dynamic, we get zero from estimatedReturnSize() instead and then we need an explicit returndatacopy(). Whiskers templ(R"( if iszero(extcodesize(
)) { () } @@ -2652,7 +2669,11 @@ void IRGeneratorForStatements::appendExternalFunctionCall( mstore(, ()) let := (add(, 4) ) - let := (,
, , , sub(, ), , ) + + let := iszero((
, , sub(, ) , )) + + let := (,
, , , sub(, ), , ) + if iszero() { () } @@ -2667,6 +2688,9 @@ void IRGeneratorForStatements::appendExternalFunctionCall( if gt(, returndatasize()) { := returndatasize() } + + returndatacopy(, 0, ) + @@ -2678,6 +2702,9 @@ void IRGeneratorForStatements::appendExternalFunctionCall( } )"); templ("revertNoCode", m_utils.revertReasonIfDebugFunction("Target contract does not contain code")); + auto const eof = m_context.eofVersion().has_value(); + solAssert(!eof || !funType.gasSet()); + templ("eof", eof); // We do not need to check extcodesize if we expect return data: If there is no // code, the call will return empty data and the ABI decoder will revert. @@ -2685,9 +2712,12 @@ void IRGeneratorForStatements::appendExternalFunctionCall( for (auto const& t: returnInfo.returnTypes) encodedHeadSize += t->decodingType()->calldataHeadSize(); bool const checkExtcodesize = - encodedHeadSize == 0 || - !m_context.evmVersion().supportsReturndata() || - m_context.revertStrings() >= RevertStrings::Debug; + !eof && + ( + encodedHeadSize == 0 || + !m_context.evmVersion().supportsReturndata() || + m_context.revertStrings() >= RevertStrings::Debug + ); templ("checkExtcodesize", checkExtcodesize); templ("pos", m_context.newYulVariable()); @@ -2748,11 +2778,11 @@ void IRGeneratorForStatements::appendExternalFunctionCall( } // Order is important here, STATICCALL might overlap with DELEGATECALL. if (isDelegateCall) - templ("call", "delegatecall"); + templ("call", eof ? "extdelegatecall" : "delegatecall"); else if (useStaticCall) - templ("call", "staticcall"); + templ("call", eof ? "extstaticcall" : "staticcall"); else - templ("call", "call"); + templ("call", eof ? "extcall" : "call"); templ("forwardingRevert", m_utils.forwardingRevertFunction()); @@ -2791,13 +2821,20 @@ void IRGeneratorForStatements::appendBareCall( let := mload() - let := (,
, , , , 0, 0) + + let := iszero((
, , , )) + + let := (,
, , , , 0, 0) + + let := () )"); templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); templ("pos", m_context.newYulVariable()); templ("length", m_context.newYulVariable()); + auto const eof = m_context.eofVersion().has_value(); + templ("eof", eof); templ("arg", IRVariable(*_arguments.front()).commaSeparatedList()); Type const& argType = type(*_arguments.front()); @@ -2819,18 +2856,19 @@ void IRGeneratorForStatements::appendBareCall( if (funKind == FunctionType::Kind::BareCall) { templ("value", funType.valueSet() ? IRVariable(_functionCall.expression()).part("value").name() : "0"); - templ("call", "call"); + templ("call", eof ? "extcall" : "call"); } else { solAssert(!funType.valueSet(), "Value set for delegatecall or staticcall."); templ("value", ""); if (funKind == FunctionType::Kind::BareStaticCall) - templ("call", "staticcall"); + templ("call", eof ? "extstaticcall" : "staticcall"); else - templ("call", "delegatecall"); + templ("call", eof ? "extdelegatecall" : "delegatecall"); } + solAssert(!eof || !funType.gasSet()); if (funType.gasSet()) templ("gas", IRVariable(_functionCall.expression()).part("gas").name()); else if (m_context.evmVersion().canOverchargeGasForCall()) From 6520bfd55639c2ab76e922aa1d51813fa0f0f552 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 9 Dec 2024 11:23:43 +0100 Subject: [PATCH 0530/1340] eof: Add unit tests in `yulSyntaxTests` and `objectCompiler` --- test/libyul/objectCompiler/eof/extcall.yul | 52 +++++++++++++++++++ .../eof/eof_identifiers_in_legacy.yul | 10 ++++ .../eof/extcall_function_in_eof.yul | 11 ++++ test/libyul/yulSyntaxTests/eof/extcalls.yul | 11 ++++ .../eof/extcalls_invalid_in_legacy.yul | 17 ++++++ .../eof/extdelegatecall_function_in_eof.yul | 11 ++++ .../eof/extstaticcall_function_in_eof.yul | 11 ++++ 7 files changed, 123 insertions(+) create mode 100644 test/libyul/objectCompiler/eof/extcall.yul create mode 100644 test/libyul/yulSyntaxTests/eof/eof_identifiers_in_legacy.yul create mode 100644 test/libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul create mode 100644 test/libyul/yulSyntaxTests/eof/extcalls.yul create mode 100644 test/libyul/yulSyntaxTests/eof/extcalls_invalid_in_legacy.yul create mode 100644 test/libyul/yulSyntaxTests/eof/extdelegatecall_function_in_eof.yul create mode 100644 test/libyul/yulSyntaxTests/eof/extstaticcall_function_in_eof.yul diff --git a/test/libyul/objectCompiler/eof/extcall.yul b/test/libyul/objectCompiler/eof/extcall.yul new file mode 100644 index 000000000..d0322b1a9 --- /dev/null +++ b/test/libyul/objectCompiler/eof/extcall.yul @@ -0,0 +1,52 @@ +object "a" { + code { + sstore(0, extcall(address(), 0, 0, 10)) + sstore(1, extdelegatecall(address(), 0, 0)) + sstore(2, extstaticcall(address(), 0, 0)) + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":81:83 */ +// 0x0a +// /* "source":78:79 */ +// 0x00 +// /* "source":64:73 */ +// dup1 +// address +// /* "source":56:84 */ +// extcall +// /* "source":53:54 */ +// 0x00 +// /* "source":46:85 */ +// sstore +// /* "source":138:139 */ +// 0x00 +// /* "source":124:133 */ +// dup1 +// address +// /* "source":108:140 */ +// extdelegatecall +// /* "source":105:106 */ +// 0x01 +// /* "source":98:141 */ +// sstore +// /* "source":192:193 */ +// 0x00 +// /* "source":178:187 */ +// dup1 +// address +// /* "source":164:194 */ +// extstaticcall +// /* "source":161:162 */ +// 0x02 +// /* "source":154:195 */ +// sstore +// /* "source":22:211 */ +// stop +// Bytecode: ef000101000402000100170400000000800004600a5f8030f85f555f8030f96001555f8030fb60025500 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP OR DIV STOP STOP STOP STOP DUP1 STOP DIV PUSH1 0xA PUSH0 DUP1 ADDRESS EXTCALL PUSH0 SSTORE PUSH0 DUP1 ADDRESS EXTDELEGATECALL PUSH1 0x1 SSTORE PUSH0 DUP1 ADDRESS EXTSTATICCALL PUSH1 0x2 SSTORE STOP +// SourceMappings: 81:2:0:-:0;78:1;64:9;;56:28;53:1;46:39;138:1;124:9;;108:32;105:1;98:43;192:1;178:9;;164:30;161:1;154:41;22:189 diff --git a/test/libyul/yulSyntaxTests/eof/eof_identifiers_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/eof_identifiers_in_legacy.yul new file mode 100644 index 000000000..d9d7fde15 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eof_identifiers_in_legacy.yul @@ -0,0 +1,10 @@ +object "a" { + code { + function extcall() {} + function extstaticcall() {} + function extdelegatecall() {} + } +} + +// ==== +// bytecodeFormat: legacy \ No newline at end of file diff --git a/test/libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul b/test/libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul new file mode 100644 index 000000000..1e503ca94 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul @@ -0,0 +1,11 @@ +object "a" { + code { + function extcall() {} + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// ParserError 5568: (41-48): Cannot use builtin function name "extcall" as identifier name. +// ParserError 8143: (41-48): Expected keyword "data" or "object" or "}". diff --git a/test/libyul/yulSyntaxTests/eof/extcalls.yul b/test/libyul/yulSyntaxTests/eof/extcalls.yul new file mode 100644 index 000000000..a8352c254 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extcalls.yul @@ -0,0 +1,11 @@ +object "a" { + code { + pop(extcall(address(), 0, 0, 0)) + pop(extdelegatecall(address(), 0, 0)) + pop(extstaticcall(address(), 0, 0)) + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- diff --git a/test/libyul/yulSyntaxTests/eof/extcalls_invalid_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/extcalls_invalid_in_legacy.yul new file mode 100644 index 000000000..6aec96aa2 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extcalls_invalid_in_legacy.yul @@ -0,0 +1,17 @@ +object "a" { + code { + pop(extcall(address(), 0, 0, 0)) + pop(extdelegatecall(address(), 0, 0)) + pop(extstaticcall(address(), 0, 0)) + } +} + +// ==== +// bytecodeFormat: legacy +// ---- +// TypeError 4328: (36-43): The "extcall" instruction is only available on EOF. +// TypeError 3950: (36-63): Expected expression to evaluate to one value, but got 0 values instead. +// TypeError 4328: (77-92): The "extdelegatecall" instruction is only available on EOF. +// TypeError 3950: (77-109): Expected expression to evaluate to one value, but got 0 values instead. +// TypeError 4328: (123-136): The "extstaticcall" instruction is only available on EOF. +// TypeError 3950: (123-153): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libyul/yulSyntaxTests/eof/extdelegatecall_function_in_eof.yul b/test/libyul/yulSyntaxTests/eof/extdelegatecall_function_in_eof.yul new file mode 100644 index 000000000..0515c8d26 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extdelegatecall_function_in_eof.yul @@ -0,0 +1,11 @@ +object "a" { + code { + function extdelegatecall() {} + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// ParserError 5568: (41-56): Cannot use builtin function name "extdelegatecall" as identifier name. +// ParserError 8143: (41-56): Expected keyword "data" or "object" or "}". diff --git a/test/libyul/yulSyntaxTests/eof/extstaticcall_function_in_eof.yul b/test/libyul/yulSyntaxTests/eof/extstaticcall_function_in_eof.yul new file mode 100644 index 000000000..fbfb5074b --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/extstaticcall_function_in_eof.yul @@ -0,0 +1,11 @@ +object "a" { + code { + function extstaticcall() {} + } +} + +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// ParserError 5568: (41-54): Cannot use builtin function name "extstaticcall" as identifier name. +// ParserError 8143: (41-54): Expected keyword "data" or "object" or "}". From 6263f56071e16d2edce233e7ff349d6ae7303e32 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 9 Dec 2024 11:50:59 +0100 Subject: [PATCH 0531/1340] eof: Enable one semantic test to sanity check. --- test/libsolidity/semanticTests/ecrecover/ecrecover.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/libsolidity/semanticTests/ecrecover/ecrecover.sol b/test/libsolidity/semanticTests/ecrecover/ecrecover.sol index 1beb451de..41b0bf865 100644 --- a/test/libsolidity/semanticTests/ecrecover/ecrecover.sol +++ b/test/libsolidity/semanticTests/ecrecover/ecrecover.sol @@ -3,6 +3,8 @@ contract test { return ecrecover(h, v, r, s); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // a(bytes32,uint8,bytes32,bytes32): // 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c, From 4f6ebd2605ea12489ef395df7805c2b8e3ff0856 Mon Sep 17 00:00:00 2001 From: RiceChuan Date: Tue, 10 Dec 2024 16:58:37 +0800 Subject: [PATCH 0532/1340] =?UTF-8?q?style=EF=BC=9A=20SETTINGS=5FPRESETS?= =?UTF-8?q?=20is=20not=20declared=20using=20const.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RiceChuan --- scripts/bytecodecompare/prepare_report.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bytecodecompare/prepare_report.js b/scripts/bytecodecompare/prepare_report.js index 821b5cb75..96bd3c1ee 100755 --- a/scripts/bytecodecompare/prepare_report.js +++ b/scripts/bytecodecompare/prepare_report.js @@ -4,7 +4,7 @@ const fs = require('fs') const compiler = require('solc') -SETTINGS_PRESETS = { +const SETTINGS_PRESETS = { 'legacy-optimize': {optimize: true, viaIR: false}, 'legacy-no-optimize': {optimize: false, viaIR: false}, 'via-ir-optimize': {optimize: true, viaIR: true}, From 34657855cab27408ac6ee7f283a7ac175510ebc6 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 10 Dec 2024 12:35:56 +0100 Subject: [PATCH 0533/1340] eof: Comment unnecessary `solAssert` --- libevmasm/Assembly.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index e5c62958f..12bb3cccc 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1019,8 +1019,9 @@ uint16_t calculateMaxStackHeight(Assembly::CodeSection const& _section) auto const tagIt = std::find(items.begin(), items.end(), item.tag()); solAssert(tagIt != items.end(), "Tag not found."); successors.emplace_back(static_cast(std::distance(items.begin(), tagIt))); + // TODO: This assert fails until the code is not topologically sorted. Uncomment when sorting introduced. // If backward jump the successor must be already visited. - solAssert(idx <= successors.back() || maxStackHeights[successors.back()] != UNVISITED); + // solAssert(idx <= successors.back() || maxStackHeights[successors.back()] != UNVISITED); } solRequire( From 3a290debd12f8d385abaa1e7affb86aa1cc26dc9 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 10 Dec 2024 16:44:58 +0100 Subject: [PATCH 0534/1340] eof: Disallow `gas` option for external function call. --- libsolidity/analysis/TypeChecker.cpp | 6 ++++++ libsolidity/analysis/TypeChecker.h | 4 +++- libsolidity/interface/CompilerStack.cpp | 2 +- test/libsolidity/Assembly.cpp | 6 +++++- test/libsolidity/SolidityExpressionCompiler.cpp | 6 +++++- .../eof/external_call_with_gas_option.sol | 12 ++++++++++++ 6 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 test/libsolidity/syntaxTests/functionCalls/eof/external_call_with_gas_option.sol diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 993541472..4264bf71d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2967,6 +2967,12 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions) _functionCallOptions.location(), "Function call option \"gas\" cannot be used with \"new\"." ); + else if (m_eofVersion.has_value()) + m_errorReporter.typeError( + 3765_error, + _functionCallOptions.location(), + "Function call option \"gas\" cannot be used when compiling to EOF." + ); else { expectType(*_functionCallOptions.options()[i], *TypeProvider::uint256()); diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index b3bd8b91f..a517a750c 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -47,8 +47,9 @@ class TypeChecker: private ASTConstVisitor { public: /// @param _errorReporter provides the error logging functionality. - TypeChecker(langutil::EVMVersion _evmVersion, langutil::ErrorReporter& _errorReporter): + TypeChecker(langutil::EVMVersion _evmVersion, std::optional _eofVersion, langutil::ErrorReporter& _errorReporter): m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion), m_errorReporter(_errorReporter) {} @@ -192,6 +193,7 @@ class TypeChecker: private ASTConstVisitor ContractDefinition const* m_currentContract = nullptr; langutil::EVMVersion m_evmVersion; + std::optional m_eofVersion; langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index b90a30242..fa8436468 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -557,7 +557,7 @@ bool CompilerStack::analyzeLegacy(bool _noErrorsSoFar) // // Note: this does not resolve overloaded functions. In order to do that, types of arguments are needed, // which is only done one step later. - TypeChecker typeChecker(m_evmVersion, m_errorReporter); + TypeChecker typeChecker(m_evmVersion, m_eofVersion, m_errorReporter); for (Source const* source: m_sourceOrder) if (source->ast && !typeChecker.checkTypeRequirements(*source->ast)) noErrors = false; diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index bf1e5caf7..0999e30ed 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -81,7 +81,11 @@ evmasm::AssemblyItems compileContract(std::shared_ptr _sourceCode) if (Error::containsErrors(errorReporter.errors())) return AssemblyItems(); } - TypeChecker checker(solidity::test::CommonOptions::get().evmVersion(), errorReporter); + TypeChecker checker( + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion(), + errorReporter + ); BOOST_REQUIRE_NO_THROW(checker.checkTypeRequirements(*sourceUnit)); if (Error::containsErrors(errorReporter.errors())) return AssemblyItems(); diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 20983b650..3df712a43 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -133,7 +133,11 @@ bytes compileFirstExpression( DeclarationTypeChecker declarationTypeChecker(errorReporter, solidity::test::CommonOptions::get().evmVersion()); for (ASTPointer const& node: sourceUnit->nodes()) BOOST_REQUIRE(declarationTypeChecker.check(*node)); - TypeChecker typeChecker(solidity::test::CommonOptions::get().evmVersion(), errorReporter); + TypeChecker typeChecker( + solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion(), + errorReporter + ); BOOST_REQUIRE(typeChecker.checkTypeRequirements(*sourceUnit)); for (ASTPointer const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) diff --git a/test/libsolidity/syntaxTests/functionCalls/eof/external_call_with_gas_option.sol b/test/libsolidity/syntaxTests/functionCalls/eof/external_call_with_gas_option.sol new file mode 100644 index 000000000..9443bac06 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/eof/external_call_with_gas_option.sol @@ -0,0 +1,12 @@ +contract C { + function g(bool x) public pure { + require(x); + } + function f(bool x) public returns (uint) { + this.g{gas: 8000}(x); + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 3765: (131-148): Function call option "gas" cannot be used when compiling to EOF. From e8cfe0b304872291d63da69c20d73540a2a18739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 6 Dec 2024 21:57:57 +0100 Subject: [PATCH 0535/1340] StandardCompiler: Fix evm.* outputs being evaluated even when not requested in Standard JSON --- Changelog.md | 1 + libsolidity/interface/StandardCompiler.cpp | 218 +++++++++++---------- 2 files changed, 115 insertions(+), 104 deletions(-) diff --git a/Changelog.md b/Changelog.md index 4c2885c9a..29b5870bc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ Compiler Features: Bugfixes: * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. +* Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested. ### 0.8.28 (2024-10-09) diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 351a17b89..56f955f40 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -374,33 +374,6 @@ Json formatImmutableReferences(std::map const& _artifactRequested -) -{ - Json output; - if (_artifactRequested("object")) - output["object"] = _object.toHex(); - if (_artifactRequested("opcodes")) - output["opcodes"] = evmasm::disassemble(_object.bytecode, _evmVersion); - if (_artifactRequested("sourceMap")) - output["sourceMap"] = _sourceMap ? *_sourceMap : ""; - if (_artifactRequested("functionDebugData")) - output["functionDebugData"] = StandardCompiler::formatFunctionDebugData(_object.functionDebugData); - if (_artifactRequested("linkReferences")) - output["linkReferences"] = formatLinkReferences(_object.linkReferences); - if (_runtimeObject && _artifactRequested("immutableReferences")) - output["immutableReferences"] = formatImmutableReferences(_object.immutableReferences); - if (_artifactRequested("generatedSources")) - output["generatedSources"] = std::move(_generatedSources); - return output; -} - std::optional checkKeys(Json const& _input, std::set const& _keys, std::string const& _name) { if (!_input.empty() && !_input.is_object()) @@ -1246,22 +1219,26 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in evmObjectComponents("bytecode"), wildcardMatchesExperimental )) - evmData["bytecode"] = collectEVMObject( - _inputsAndSettings.evmVersion, - stack.object(sourceName), - stack.sourceMapping(sourceName), - {}, - false, // _runtimeObject - [&](std::string const& _element) { - return isArtifactRequested( - _inputsAndSettings.outputSelection, - sourceName, - "", - "evm.bytecode." + _element, - wildcardMatchesExperimental - ); - } - ); + { + auto const evmCreationArtifactRequested = [&](std::string const& _element) { + return isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "evm.bytecode." + _element, wildcardMatchesExperimental); + }; + + Json creationJSON; + if (evmCreationArtifactRequested("object")) + creationJSON["object"] = stack.object(sourceName).toHex(); + if (evmCreationArtifactRequested("opcodes")) + creationJSON["opcodes"] = evmasm::disassemble(stack.object(sourceName).bytecode, _inputsAndSettings.evmVersion); + if (evmCreationArtifactRequested("sourceMap")) + creationJSON["sourceMap"] = stack.sourceMapping(sourceName) ? *stack.sourceMapping(sourceName) : ""; + if (evmCreationArtifactRequested("functionDebugData")) + creationJSON["functionDebugData"] = formatFunctionDebugData(stack.object(sourceName).functionDebugData); + if (evmCreationArtifactRequested("linkReferences")) + creationJSON["linkReferences"] = formatLinkReferences(stack.object(sourceName).linkReferences); + if (evmCreationArtifactRequested("generatedSources")) + creationJSON["generatedSources"] = {}; + evmData["bytecode"] = creationJSON; + } if (isArtifactRequested( _inputsAndSettings.outputSelection, @@ -1270,22 +1247,28 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in evmObjectComponents("deployedBytecode"), wildcardMatchesExperimental )) - evmData["deployedBytecode"] = collectEVMObject( - _inputsAndSettings.evmVersion, - stack.runtimeObject(sourceName), - stack.runtimeSourceMapping(sourceName), - {}, - true, // _runtimeObject - [&](std::string const& _element) { - return isArtifactRequested( - _inputsAndSettings.outputSelection, - sourceName, - "", - "evm.deployedBytecode." + _element, - wildcardMatchesExperimental - ); - } - ); + { + auto const evmDeployedArtifactRequested = [&](std::string const& _element) { + return isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "evm.deployedBytecode." + _element, wildcardMatchesExperimental); + }; + + Json deployedJSON; + if (evmDeployedArtifactRequested("object")) + deployedJSON["object"] = stack.runtimeObject(sourceName).toHex(); + if (evmDeployedArtifactRequested("opcodes")) + deployedJSON["opcodes"] = evmasm::disassemble(stack.runtimeObject(sourceName).bytecode, _inputsAndSettings.evmVersion); + if (evmDeployedArtifactRequested("sourceMap")) + deployedJSON["sourceMap"] = stack.runtimeSourceMapping(sourceName) ? *stack.runtimeSourceMapping(sourceName) : ""; + if (evmDeployedArtifactRequested("functionDebugData")) + deployedJSON["functionDebugData"] = formatFunctionDebugData(stack.runtimeObject(sourceName).functionDebugData); + if (evmDeployedArtifactRequested("linkReferences")) + deployedJSON["linkReferences"] = formatLinkReferences(stack.runtimeObject(sourceName).linkReferences); + if (evmDeployedArtifactRequested("immutableReferences")) + deployedJSON["immutableReferences"] = formatImmutableReferences(stack.runtimeObject(sourceName).immutableReferences); + if (evmDeployedArtifactRequested("generatedSources")) + deployedJSON["generatedSources"] = {}; + evmData["deployedBytecode"] = deployedJSON; + } Json contractData; if (!evmData.empty()) @@ -1506,20 +1489,26 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu evmObjectComponents("bytecode"), wildcardMatchesExperimental )) - evmData["bytecode"] = collectEVMObject( - _inputsAndSettings.evmVersion, - compilerStack.object(contractName), - compilerStack.sourceMapping(contractName), - compilerStack.generatedSources(contractName), - false, - [&](std::string const& _element) { return isArtifactRequested( - _inputsAndSettings.outputSelection, - file, - name, - "evm.bytecode." + _element, - wildcardMatchesExperimental - ); } - ); + { + auto const evmCreationArtifactRequested = [&](std::string const& _element) { + return isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.bytecode." + _element, wildcardMatchesExperimental); + }; + + Json creationJSON; + if (evmCreationArtifactRequested("object")) + creationJSON["object"] = compilerStack.object(contractName).toHex(); + if (evmCreationArtifactRequested("opcodes")) + creationJSON["opcodes"] = evmasm::disassemble(compilerStack.object(contractName).bytecode, _inputsAndSettings.evmVersion); + if (evmCreationArtifactRequested("sourceMap")) + creationJSON["sourceMap"] = compilerStack.sourceMapping(contractName) ? *compilerStack.sourceMapping(contractName) : ""; + if (evmCreationArtifactRequested("functionDebugData")) + creationJSON["functionDebugData"] = formatFunctionDebugData(compilerStack.object(contractName).functionDebugData); + if (evmCreationArtifactRequested("linkReferences")) + creationJSON["linkReferences"] = formatLinkReferences(compilerStack.object(contractName).linkReferences); + if (evmCreationArtifactRequested("generatedSources")) + creationJSON["generatedSources"] = compilerStack.generatedSources(contractName, /* _runtime */ false); + evmData["bytecode"] = creationJSON; + } if (compilationSuccess && isArtifactRequested( _inputsAndSettings.outputSelection, @@ -1528,20 +1517,28 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu evmObjectComponents("deployedBytecode"), wildcardMatchesExperimental )) - evmData["deployedBytecode"] = collectEVMObject( - _inputsAndSettings.evmVersion, - compilerStack.runtimeObject(contractName), - compilerStack.runtimeSourceMapping(contractName), - compilerStack.generatedSources(contractName, true), - true, - [&](std::string const& _element) { return isArtifactRequested( - _inputsAndSettings.outputSelection, - file, - name, - "evm.deployedBytecode." + _element, - wildcardMatchesExperimental - ); } - ); + { + auto const evmDeployedArtifactRequested = [&](std::string const& _element) { + return isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.deployedBytecode." + _element, wildcardMatchesExperimental); + }; + + Json deployedJSON; + if (evmDeployedArtifactRequested("object")) + deployedJSON["object"] = compilerStack.runtimeObject(contractName).toHex(); + if (evmDeployedArtifactRequested("opcodes")) + deployedJSON["opcodes"] = evmasm::disassemble(compilerStack.runtimeObject(contractName).bytecode, _inputsAndSettings.evmVersion); + if (evmDeployedArtifactRequested("sourceMap")) + deployedJSON["sourceMap"] = compilerStack.runtimeSourceMapping(contractName) ? *compilerStack.runtimeSourceMapping(contractName) : ""; + if (evmDeployedArtifactRequested("functionDebugData")) + deployedJSON["functionDebugData"] = formatFunctionDebugData(compilerStack.runtimeObject(contractName).functionDebugData); + if (evmDeployedArtifactRequested("linkReferences")) + deployedJSON["linkReferences"] = formatLinkReferences(compilerStack.runtimeObject(contractName).linkReferences); + if (evmDeployedArtifactRequested("immutableReferences")) + deployedJSON["immutableReferences"] = formatImmutableReferences(compilerStack.runtimeObject(contractName).immutableReferences); + if (evmDeployedArtifactRequested("generatedSources")) + deployedJSON["generatedSources"] = compilerStack.generatedSources(contractName, /* _runtime */ true); + evmData["deployedBytecode"] = deployedJSON; + } if (!evmData.empty()) contractData["evm"] = evmData; @@ -1668,23 +1665,36 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) wildcardMatchesExperimental )) { - MachineAssemblyObject const& o = isDeployed ? deployedObject : object; - if (o.bytecode) - output["contracts"][sourceName][contractName]["evm"][kind] = - collectEVMObject( - _inputsAndSettings.evmVersion, - *o.bytecode, - o.sourceMappings.get(), - Json::array(), - isDeployed, - [&, kind = kind](std::string const& _element) { return isArtifactRequested( - _inputsAndSettings.outputSelection, - sourceName, - contractName, - "evm." + kind + "." + _element, - wildcardMatchesExperimental - ); } - ); + auto const evmArtifactRequested = [&](std::string const& _kind, std::string const& _element) { + return isArtifactRequested( + _inputsAndSettings.outputSelection, + sourceName, + contractName, + "evm." + _kind + "." + _element, + wildcardMatchesExperimental + ); + }; + + MachineAssemblyObject const& selectedObject = isDeployed ? deployedObject : object; + if (selectedObject.bytecode) + { + Json bytecodeJSON; + if (evmArtifactRequested(kind, "object")) + bytecodeJSON["object"] = selectedObject.bytecode->toHex(); + if (evmArtifactRequested(kind, "opcodes")) + bytecodeJSON["opcodes"] = evmasm::disassemble(selectedObject.bytecode->bytecode, _inputsAndSettings.evmVersion); + if (evmArtifactRequested(kind, "sourceMap")) + bytecodeJSON["sourceMap"] = selectedObject.sourceMappings ? *selectedObject.sourceMappings : ""; + if (evmArtifactRequested(kind, "functionDebugData")) + bytecodeJSON["functionDebugData"] = formatFunctionDebugData(selectedObject.bytecode->functionDebugData); + if (evmArtifactRequested(kind, "linkReferences")) + bytecodeJSON["linkReferences"] = formatLinkReferences(selectedObject.bytecode->linkReferences); + if (isDeployed && evmArtifactRequested(kind, "immutableReferences")) + bytecodeJSON["immutableReferences"] = formatImmutableReferences(selectedObject.bytecode->immutableReferences); + if (evmArtifactRequested(kind, "generatedSources")) + bytecodeJSON["generatedSources"] = Json::array(); + output["contracts"][sourceName][contractName]["evm"][kind] = bytecodeJSON; + } } if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "irOptimized", wildcardMatchesExperimental)) From 11d8fddeeff896d5d13eb873b8dac90c3c659988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 6 Dec 2024 22:27:47 +0100 Subject: [PATCH 0536/1340] StandardCompiler: Don't include empty generatedSources key for Yul compilation and assembly import --- libsolidity/interface/StandardCompiler.cpp | 6 ------ test/cmdlineTests/standard_yul/output.json | 1 - .../standard_yul_immutable_references/output.json | 2 -- test/cmdlineTests/standard_yul_object/output.json | 1 - test/cmdlineTests/standard_yul_object_name/output.json | 2 -- test/cmdlineTests/standard_yul_optimiserSteps/output.json | 1 - test/cmdlineTests/standard_yul_optimized/output.json | 1 - test/cmdlineTests/standard_yul_output_warning/output.json | 1 - 8 files changed, 15 deletions(-) diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 56f955f40..b5279c624 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1235,8 +1235,6 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in creationJSON["functionDebugData"] = formatFunctionDebugData(stack.object(sourceName).functionDebugData); if (evmCreationArtifactRequested("linkReferences")) creationJSON["linkReferences"] = formatLinkReferences(stack.object(sourceName).linkReferences); - if (evmCreationArtifactRequested("generatedSources")) - creationJSON["generatedSources"] = {}; evmData["bytecode"] = creationJSON; } @@ -1265,8 +1263,6 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in deployedJSON["linkReferences"] = formatLinkReferences(stack.runtimeObject(sourceName).linkReferences); if (evmDeployedArtifactRequested("immutableReferences")) deployedJSON["immutableReferences"] = formatImmutableReferences(stack.runtimeObject(sourceName).immutableReferences); - if (evmDeployedArtifactRequested("generatedSources")) - deployedJSON["generatedSources"] = {}; evmData["deployedBytecode"] = deployedJSON; } @@ -1691,8 +1687,6 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) bytecodeJSON["linkReferences"] = formatLinkReferences(selectedObject.bytecode->linkReferences); if (isDeployed && evmArtifactRequested(kind, "immutableReferences")) bytecodeJSON["immutableReferences"] = formatImmutableReferences(selectedObject.bytecode->immutableReferences); - if (evmArtifactRequested(kind, "generatedSources")) - bytecodeJSON["generatedSources"] = Json::array(); output["contracts"][sourceName][contractName]["evm"][kind] = bytecodeJSON; } } diff --git a/test/cmdlineTests/standard_yul/output.json b/test/cmdlineTests/standard_yul/output.json index 30fe1dd7e..a72904ee6 100644 --- a/test/cmdlineTests/standard_yul/output.json +++ b/test/cmdlineTests/standard_yul/output.json @@ -18,7 +18,6 @@ ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", diff --git a/test/cmdlineTests/standard_yul_immutable_references/output.json b/test/cmdlineTests/standard_yul_immutable_references/output.json index 7bfbb076a..3f82bcbaa 100644 --- a/test/cmdlineTests/standard_yul_immutable_references/output.json +++ b/test/cmdlineTests/standard_yul_immutable_references/output.json @@ -5,7 +5,6 @@ "evm": { "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", @@ -13,7 +12,6 @@ }, "deployedBytecode": { "functionDebugData": {}, - "generatedSources": [], "immutableReferences": { "test": [ { diff --git a/test/cmdlineTests/standard_yul_object/output.json b/test/cmdlineTests/standard_yul_object/output.json index 3181da426..c1bb2eb3e 100644 --- a/test/cmdlineTests/standard_yul_object/output.json +++ b/test/cmdlineTests/standard_yul_object/output.json @@ -19,7 +19,6 @@ data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263 ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", diff --git a/test/cmdlineTests/standard_yul_object_name/output.json b/test/cmdlineTests/standard_yul_object_name/output.json index 1512900e1..2b6dc1f73 100644 --- a/test/cmdlineTests/standard_yul_object_name/output.json +++ b/test/cmdlineTests/standard_yul_object_name/output.json @@ -27,7 +27,6 @@ sub_0: assembly { ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", @@ -35,7 +34,6 @@ sub_0: assembly { }, "deployedBytecode": { "functionDebugData": {}, - "generatedSources": [], "immutableReferences": {}, "linkReferences": {}, "object": "", diff --git a/test/cmdlineTests/standard_yul_optimiserSteps/output.json b/test/cmdlineTests/standard_yul_optimiserSteps/output.json index 2a654d20a..621a02907 100644 --- a/test/cmdlineTests/standard_yul_optimiserSteps/output.json +++ b/test/cmdlineTests/standard_yul_optimiserSteps/output.json @@ -15,7 +15,6 @@ ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", diff --git a/test/cmdlineTests/standard_yul_optimized/output.json b/test/cmdlineTests/standard_yul_optimized/output.json index 513f8148a..ad0e9f40a 100644 --- a/test/cmdlineTests/standard_yul_optimized/output.json +++ b/test/cmdlineTests/standard_yul_optimized/output.json @@ -15,7 +15,6 @@ ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", diff --git a/test/cmdlineTests/standard_yul_output_warning/output.json b/test/cmdlineTests/standard_yul_output_warning/output.json index 3234be181..514280afc 100644 --- a/test/cmdlineTests/standard_yul_output_warning/output.json +++ b/test/cmdlineTests/standard_yul_output_warning/output.json @@ -19,7 +19,6 @@ ", "bytecode": { "functionDebugData": {}, - "generatedSources": [], "linkReferences": {}, "object": "", "opcodes":"", From 8616387d5c999b088e654d49cfe20420f6c89cf0 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 10 Dec 2024 14:41:54 +0100 Subject: [PATCH 0537/1340] eof: Add new (EOF) message kind to EVMHost. Separate arguments in sendMessage --- test/EVMHost.cpp | 18 +++++++++++++----- test/ExecutionFramework.cpp | 18 +++++++++++++----- test/ExecutionFramework.h | 8 ++++---- test/contracts/AuctionRegistrar.cpp | 2 +- test/contracts/Wallet.cpp | 2 +- test/libsolidity/GasMeter.cpp | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 4 ++-- test/libsolidity/SolidityExecutionFramework.h | 2 +- 8 files changed, 36 insertions(+), 20 deletions(-) diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 5626f8d43..7d0125eec 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -332,13 +332,17 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept code = evmc::bytes(message.input_data, message.input_data + message.input_size); } - else if (message.kind == EVMC_CREATE2) + else if (message.kind == EVMC_CREATE2 || message.kind == EVMC_EOFCREATE) { h160 createAddress(keccak256( bytes{0xff} + bytes(std::begin(message.sender.bytes), std::end(message.sender.bytes)) + bytes(std::begin(message.create2_salt.bytes), std::end(message.create2_salt.bytes)) + - keccak256(bytes(message.input_data, message.input_data + message.input_size)).asBytes() + keccak256( + message.kind == EVMC_CREATE2 ? + bytes(message.input_data, message.input_data + message.input_size) : + bytes(message.code, message.code + message.code_size) + ).asBytes() ), h160::AlignRight); message.recipient = convertToEVMC(createAddress); @@ -353,13 +357,16 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept return result; } - code = evmc::bytes(message.input_data, message.input_data + message.input_size); + if (message.kind == EVMC_CREATE2) + code = evmc::bytes(message.input_data, message.input_data + message.input_size); + else // EOFCREATE + code = evmc::bytes(message.code, message.code + message.code_size); } else code = accounts[message.code_address].code; auto& destination = accounts[message.recipient]; - if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2) + if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2 || message.kind == EVMC_EOFCREATE) // Mark account as created if it is a CREATE or CREATE2 call // TODO: Should we roll changes back on failure like we do for `accounts`? m_newlyCreatedAccounts.emplace(message.recipient); @@ -396,7 +403,7 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept } evmc::Result result = m_vm.execute(*this, m_evmRevision, message, code.data(), code.size()); - if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2) + if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2 || message.kind == EVMC_EOFCREATE) { int64_t codeDepositGas = static_cast(evmasm::GasCosts::createDataGas * result.output_size); result.gas_left -= codeDepositGas; @@ -409,6 +416,7 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept } else { + // TODO: Add proper codehash calculation for EOF. m_totalCodeDepositGas += codeDepositGas; result.create_address = message.recipient; destination.code = evmc::bytes(result.output_data, result.output_data + result.output_size); diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index 0081ba4a9..582cf1eda 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -145,10 +145,13 @@ u256 ExecutionFramework::blockNumber() const return m_evmcHost->tx_context.block_number; } -void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value) +void ExecutionFramework::sendMessage(bytes const& _bytecode, bytes const& _arguments, bool _isCreation, u256 const& _value) { + auto const eof = _bytecode.size() > 1 && _bytecode[0] == 0xef && _bytecode[1] == 0x00; m_evmcHost->newBlock(); + auto const data = _bytecode + _arguments; + if (m_showMessages) { if (_isCreation) @@ -157,17 +160,22 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 std::cout << "CALL " << m_sender.hex() << " -> " << m_contractAddress.hex() << ":" << std::endl; if (_value > 0) std::cout << " value: " << _value << std::endl; - std::cout << " in: " << util::toHex(_data) << std::endl; + std::cout << " in: " << util::toHex(data) << std::endl; } evmc_message message{}; - message.input_data = _data.data(); - message.input_size = _data.size(); + message.input_data = eof ? _arguments.data() : data.data(); + message.input_size = eof ? _arguments.size() : data.size(); + if (eof) + { + message.code = _bytecode.data(); + message.code_size = _bytecode.size(); + } message.sender = EVMHost::convertToEVMC(m_sender); message.value = EVMHost::convertToEVMC(_value); if (_isCreation) { - message.kind = EVMC_CREATE; + message.kind = eof ? EVMC_EOFCREATE : EVMC_CREATE; message.recipient = {}; message.code_address = {}; } diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index 5d66ea10d..44812e230 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -90,7 +90,7 @@ class ExecutionFramework bytes const& callFallbackWithValue(u256 const& _value) { - sendMessage(bytes(), false, _value); + sendMessage(bytes(), bytes(), false, _value); return m_output; } @@ -101,13 +101,13 @@ class ExecutionFramework bytes const& callLowLevel(bytes const& _data, u256 const& _value) { - sendMessage(_data, false, _value); + sendMessage(_data, bytes(), false, _value); return m_output; } bytes const& callContractFunctionWithValueNoEncoding(std::string _sig, u256 const& _value, bytes const& _arguments) { - sendMessage(util::selectorFromSignatureH32(_sig).asBytes() + _arguments, false, _value); + sendMessage(util::selectorFromSignatureH32(_sig).asBytes(), _arguments, false, _value); return m_output; } @@ -277,7 +277,7 @@ class ExecutionFramework void selectVM(evmc_capabilities _cap = evmc_capabilities::EVMC_CAPABILITY_EVM1); void reset(); - void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0); + void sendMessage(bytes const& _bytecode, bytes const& _argument, bool _isCreation, u256 const& _value = 0); void sendEther(util::h160 const& _to, u256 const& _value); size_t currentTimestamp(); size_t blockTimestamp(u256 _number); diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index 8d0b1ccb6..c686963df 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -225,7 +225,7 @@ class AuctionRegistrarTestFramework: public SolidityExecutionFramework return compileContract(registrarCode, "GlobalRegistrar"); }); - sendMessage(compiled, true); + sendMessage(compiled, bytes(), true); BOOST_REQUIRE(m_transactionSuccessful); BOOST_REQUIRE(!m_output.empty()); } diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index db9119dee..6e8670e14 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -454,7 +454,7 @@ class WalletTestFramework: public SolidityExecutionFramework }); bytes args = encodeArgs(u256(0x60), _required, _dailyLimit, u256(_owners.size()), _owners); - sendMessage(compiled + args, true, _value); + sendMessage(compiled, args, true, _value); BOOST_REQUIRE(m_transactionSuccessful); BOOST_REQUIRE(!m_output.empty()); } diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index 1afebac5c..9012ad083 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -76,7 +76,7 @@ class GasMeterTestFramework: public SolidityExecutionFramework util::FixedHash<4> hash = util::selectorFromSignatureH32(_sig); for (bytes const& arguments: _argumentVariants) { - sendMessage(hash.asBytes() + arguments, false, 0); + sendMessage(hash.asBytes(), arguments, false, 0); BOOST_CHECK(m_transactionSuccessful); gasUsed = std::max(gasUsed, m_gasUsed); gas = std::max(gas, gasForTransaction(hash.asBytes() + arguments, false)); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e321a5298..76699c2e3 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1374,7 +1374,7 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) ALSO_VIA_YUL( compileAndRun(sourceCode); bytes calldata1 = util::selectorFromSignatureH32("f()").asBytes() + bytes(61, 0x22) + bytes(12, 0x12); - sendMessage(calldata1, false); + sendMessage(calldata1, bytes(), false); BOOST_CHECK(m_transactionSuccessful); BOOST_CHECK(m_output == encodeArgs(util::keccak256(bytes{'a', 'b', 'c'} + calldata1))); ); @@ -1474,7 +1474,7 @@ BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data) compileAndRun(sourceCode); ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); - sendMessage(bytes(), false); + sendMessage(bytes(), bytes(), false); BOOST_CHECK(m_transactionSuccessful); BOOST_CHECK(m_output.empty()); BOOST_CHECK(storageEmpty(m_contractAddress)); diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index f91ba758f..4caa4aa1e 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -62,7 +62,7 @@ class SolidityExecutionFramework: public solidity::test::ExecutionFramework ) override { bytes bytecode = multiSourceCompileContract(_sourceCode, _sourceName, _contractName, _libraryAddresses); - sendMessage(bytecode + _arguments, true, _value); + sendMessage(bytecode, _arguments, true, _value); return m_output; } From 0f7729df486a9c51eb51db507b9fbf0431fae4e6 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 10 Dec 2024 14:41:54 +0100 Subject: [PATCH 0538/1340] eof: Enable EOF validation in `EVMHost` --- test/EVMHost.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 7d0125eec..fdaf3f35b 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -58,6 +58,7 @@ evmc::VM& EVMHost::getVM(std::string const& _path) std::cerr << ":" << std::endl << errorMsg; std::cerr << std::endl; } + vms[_path]->set_option("validate_eof", "1"); } if (vms.count(_path) > 0) From db7dacf3ddb4f786f66368b1db64d1ce14b5a710 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 10 Dec 2024 08:46:01 +0100 Subject: [PATCH 0539/1340] Constant Optimizer: Do not assert for shl builtin It is guarded by dialect.evmVersion().hasBitwiseShifting(). --- libyul/backends/evm/ConstantOptimiser.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libyul/backends/evm/ConstantOptimiser.cpp b/libyul/backends/evm/ConstantOptimiser.cpp index d7aed27c3..aa744415b 100644 --- a/libyul/backends/evm/ConstantOptimiser.cpp +++ b/libyul/backends/evm/ConstantOptimiser.cpp @@ -126,7 +126,6 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu return m_cache.at(_value); yulAssert(m_dialect.auxiliaryBuiltinHandles().not_); - yulAssert(m_dialect.auxiliaryBuiltinHandles().shl); yulAssert(m_dialect.auxiliaryBuiltinHandles().exp); yulAssert(m_dialect.auxiliaryBuiltinHandles().mul); yulAssert(m_dialect.auxiliaryBuiltinHandles().add); From b976807ea9b2300d0d4ee261c88a23e3efdc949e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 10 Dec 2024 09:59:18 +0100 Subject: [PATCH 0540/1340] EVMCodeTransformTest: use defaulted evm dialect --- test/libyul/EVMCodeTransformTest.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index da2eaad0e..3b3432f8e 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -53,6 +53,8 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin solidity::frontend::OptimiserSettings settings = solidity::frontend::OptimiserSettings::none(); settings.runYulOptimiser = false; settings.optimizeStackAllocation = m_stackOpt; + // Restrict to a single EVM/EOF version combination (the default one) as code generation + // can be different from version to version. YulStack stack( EVMVersion{}, std::nullopt, @@ -73,7 +75,7 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin EVMObjectCompiler::compile( *stack.parserResult(), adapter, - CommonOptions::get().evmDialect(), + *dynamic_cast(stack.parserResult()->dialect()), m_stackOpt, std::nullopt ); From 58e71b274ca64b443df57815ed1b4bb60466a98e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 11 Dec 2024 08:37:09 +0100 Subject: [PATCH 0541/1340] EVMObjectCompiler: Take dialect from object --- libyul/YulStack.cpp | 14 +------------- libyul/backends/evm/EVMObjectCompiler.cpp | 22 ++++++++++++---------- libyul/backends/evm/EVMObjectCompiler.h | 10 ++-------- test/libyul/EVMCodeTransformTest.cpp | 4 +--- 4 files changed, 16 insertions(+), 34 deletions(-) diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 22c1fcb7d..4517853a3 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -192,19 +192,7 @@ bool YulStack::analyzeParsed(Object& _object) void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) const { - EVMDialect const* dialect = nullptr; - switch (m_language) - { - case Language::Assembly: - case Language::StrictAssembly: - dialect = &EVMDialect::strictAssemblyForEVMObjects(m_evmVersion, m_eofVersion); - break; - default: - yulAssert(false, "Invalid language."); - break; - } - - EVMObjectCompiler::compile(*m_parserResult, _assembly, *dialect, _optimize, m_eofVersion); + EVMObjectCompiler::compile(*m_parserResult, _assembly, _optimize); } void YulStack::reparse() diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index de1174ace..fb61e70f6 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -37,17 +37,19 @@ using namespace solidity::yul; void EVMObjectCompiler::compile( Object const& _object, AbstractAssembly& _assembly, - EVMDialect const& _dialect, - bool _optimize, - std::optional _eofVersion + bool _optimize ) { - EVMObjectCompiler compiler(_assembly, _dialect, _eofVersion); + EVMObjectCompiler compiler(_assembly); compiler.run(_object, _optimize); } void EVMObjectCompiler::run(Object const& _object, bool _optimize) { + yulAssert(_object.dialect()); + auto const* evmDialect = dynamic_cast(_object.dialect()); + yulAssert(evmDialect); + BuiltinContext context; context.currentObject = &_object; @@ -59,7 +61,7 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name); context.subIDs[subObject->name] = subAssemblyAndID.second; subObject->subId = subAssemblyAndID.second; - compile(*subObject, *subAssemblyAndID.first, m_dialect, _optimize, m_eofVersion); + compile(*subObject, *subAssemblyAndID.first, _optimize); } else { @@ -73,18 +75,18 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) yulAssert(_object.analysisInfo, "No analysis info."); yulAssert(_object.hasCode(), "No code."); - if (m_eofVersion.has_value()) + if (evmDialect->eofVersion().has_value()) yulAssert( - _optimize && (m_dialect.evmVersion() >= langutil::EVMVersion::prague()), + _optimize && (evmDialect->evmVersion() >= langutil::EVMVersion::prague()), "Experimental EOF support is only available for optimized via-IR compilation and the most recent EVM version." ); - if (_optimize && m_dialect.evmVersion().canOverchargeGasForCall()) + if (_optimize && evmDialect->evmVersion().canOverchargeGasForCall()) { auto stackErrors = OptimizedEVMCodeTransform::run( m_assembly, *_object.analysisInfo, _object.code()->root(), - m_dialect, + *evmDialect, context, OptimizedEVMCodeTransform::UseNamedLabels::ForFirstFunctionOfEachName ); @@ -116,7 +118,7 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) m_assembly, *_object.analysisInfo, _object.code()->root(), - m_dialect, + *evmDialect, context, _optimize, {}, diff --git a/libyul/backends/evm/EVMObjectCompiler.h b/libyul/backends/evm/EVMObjectCompiler.h index 5154bd37f..cca346ae7 100644 --- a/libyul/backends/evm/EVMObjectCompiler.h +++ b/libyul/backends/evm/EVMObjectCompiler.h @@ -36,20 +36,14 @@ class EVMObjectCompiler static void compile( Object const& _object, AbstractAssembly& _assembly, - EVMDialect const& _dialect, - bool _optimize, - std::optional _eofVersion + bool _optimize ); private: - EVMObjectCompiler(AbstractAssembly& _assembly, EVMDialect const& _dialect, std::optional _eofVersion): - m_assembly(_assembly), m_dialect(_dialect), m_eofVersion(_eofVersion) - {} + EVMObjectCompiler(AbstractAssembly& _assembly): m_assembly(_assembly) {} void run(Object const& _object, bool _optimize); AbstractAssembly& m_assembly; - EVMDialect const& m_dialect; - std::optional m_eofVersion; }; } diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 3b3432f8e..1ba74a6e2 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -75,9 +75,7 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin EVMObjectCompiler::compile( *stack.parserResult(), adapter, - *dynamic_cast(stack.parserResult()->dialect()), - m_stackOpt, - std::nullopt + m_stackOpt ); std::ostringstream output; From 394dd929f3bc6208c73cef98af918d696d418679 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 11 Dec 2024 09:07:30 +0100 Subject: [PATCH 0542/1340] EVMCodeTransformTest: Only run for the current EVM version --- test/libyul/EVMCodeTransformTest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 1ba74a6e2..288c35570 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -46,6 +46,7 @@ EVMCodeTransformTest::EVMCodeTransformTest(std::string const& _filename): m_source = m_reader.source(); m_stackOpt = m_reader.boolSetting("stackOptimization", false); m_expectation = m_reader.simpleExpectations(); + m_shouldRun = CommonOptions::get().evmDialect().evmVersion() == EVMVersion{}; } TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) From 7e1486dba24929451fefe6ee5152fd2bd7e61b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 6 Dec 2024 23:17:23 +0100 Subject: [PATCH 0543/1340] Fix unimplemented errors during Solidity and Yul parsing being treated as success --- libsolidity/interface/CompilerStack.cpp | 1 + libyul/YulStack.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index fa8436468..dbfa4febe 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -419,6 +419,7 @@ bool CompilerStack::parse() catch (UnimplementedFeatureError const& _error) { reportUnimplementedFeatureError(_error); + return false; } return true; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 4517853a3..97c67d3b5 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -62,6 +62,7 @@ bool YulStack::parse(std::string const& _sourceName, std::string const& _source) catch (UnimplementedFeatureError const& _error) { reportUnimplementedFeatureError(_error); + return false; } if (!m_errorReporter.hasErrors()) From 95c6e84f0ffc498b62009b3999881b75f37efd77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 29 Nov 2024 20:37:54 +0100 Subject: [PATCH 0544/1340] Don't ignore errors reported at optimization and assembling steps in Yul compilation --- libsolidity/interface/CompilerStack.cpp | 38 +++++++++++++-- libsolidity/interface/CompilerStack.h | 1 + libsolidity/interface/StandardCompiler.cpp | 56 +++++++++++----------- libyul/YulStack.cpp | 15 ++++-- solc/CommandLineInterface.cpp | 38 ++++++++------- test/libyul/ObjectCompilerTest.cpp | 16 ++++--- 6 files changed, 108 insertions(+), 56 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index dbfa4febe..6a50b04c5 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -784,14 +784,17 @@ bool CompilerStack::compile(State _stopAfter) // but CodeGenerationError is one case where someone decided to just throw Error. solAssert(_error.type() == Error::Type::CodeGenerationError); m_errorReporter.error(_error.errorId(), _error.type(), SourceLocation(), _error.what()); - return false; } catch (UnimplementedFeatureError const& _error) { reportUnimplementedFeatureError(_error); - return false; } + + if (m_errorReporter.hasErrors()) + return false; } + + solAssert(!m_errorReporter.hasErrors()); m_stackState = CompilationSuccessful; this->link(); return true; @@ -1611,6 +1614,14 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) std::string deployedName = IRNames::deployedObject(_contract); solAssert(!deployedName.empty(), ""); tie(compiledContract.evmAssembly, compiledContract.evmRuntimeAssembly) = stack.assembleEVMWithDeployed(deployedName); + + if (stack.hasErrors()) + { + for (std::shared_ptr const& error: stack.errors()) + reportIRPostAnalysisError(error.get()); + return; + } + assembleYul(_contract, compiledContract.evmAssembly, compiledContract.evmRuntimeAssembly); } @@ -2005,6 +2016,27 @@ experimental::Analysis const& CompilerStack::experimentalAnalysis() const void CompilerStack::reportUnimplementedFeatureError(UnimplementedFeatureError const& _error) { - solAssert(_error.comment(), "Unimplemented feature errors must include a message for the user"); + solAssert(_error.comment(), "Errors must include a message for the user."); + m_errorReporter.unimplementedFeatureError(1834_error, _error.sourceLocation(), *_error.comment()); } + +void CompilerStack::reportIRPostAnalysisError(Error const* _error) +{ + solAssert(_error); + solAssert(_error->comment(), "Errors must include a message for the user."); + solAssert(!_error->secondarySourceLocation()); + + // Do not report Yul warnings and infos. These are only reported in pure Yul compilation. + if (!Error::isError(_error->severity())) + return; + + m_errorReporter.error( + _error->errorId(), + _error->type(), + // Ignore the original location. It's likely missing, but even if not, it points at Yul source. + // CompilerStack can only point at locations in Solidity sources. + SourceLocation{}, + *_error->comment() + ); +} diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 009103a49..81a039403 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -579,6 +579,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac ) const; void reportUnimplementedFeatureError(langutil::UnimplementedFeatureError const& _error); + void reportIRPostAnalysisError(langutil::Error const* _error); ReadCallback::Callback m_readFile; OptimiserSettings m_optimiserSettings; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index b5279c624..9357310c0 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1609,9 +1609,35 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) std::string const& sourceName = _inputsAndSettings.sources.begin()->first; std::string const& sourceContents = _inputsAndSettings.sources.begin()->second; - // Inconsistent state - stop here to receive error reports from users - if (!stack.parseAndAnalyze(sourceName, sourceContents) && !stack.hasErrors()) - solAssert(false, "No error reported, but parsing/analysis failed."); + std::string contractName; + bool const wildcardMatchesExperimental = true; + MachineAssemblyObject object; + MachineAssemblyObject deployedObject; + + bool successful = stack.parseAndAnalyze(sourceName, sourceContents); + if (!successful) + // Inconsistent state - stop here to receive error reports from users + solAssert(stack.hasErrors(), "No error reported, but parsing/analysis failed."); + else + { + contractName = stack.parserResult()->name; + if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental)) + output["contracts"][sourceName][contractName]["ir"] = stack.print(); + + if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ast", wildcardMatchesExperimental)) + { + Json sourceResult; + sourceResult["id"] = 0; + sourceResult["ast"] = stack.astJson(); + output["sources"][sourceName] = sourceResult; + } + stack.optimize(); + std::tie(object, deployedObject) = stack.assembleWithDeployed(); + if (object.bytecode) + object.bytecode->link(_inputsAndSettings.libraries); + if (deployedObject.bytecode) + deployedObject.bytecode->link(_inputsAndSettings.libraries); + } for (auto const& error: stack.errors()) { @@ -1628,30 +1654,6 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) if (stack.hasErrors()) return output; - std::string contractName = stack.parserResult()->name; - - bool const wildcardMatchesExperimental = true; - if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental)) - output["contracts"][sourceName][contractName]["ir"] = stack.print(); - - if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ast", wildcardMatchesExperimental)) - { - Json sourceResult; - sourceResult["id"] = 0; - sourceResult["ast"] = stack.astJson(); - output["sources"][sourceName] = sourceResult; - } - stack.optimize(); - - MachineAssemblyObject object; - MachineAssemblyObject deployedObject; - std::tie(object, deployedObject) = stack.assembleWithDeployed(); - - if (object.bytecode) - object.bytecode->link(_inputsAndSettings.libraries); - if (deployedObject.bytecode) - deployedObject.bytecode->link(_inputsAndSettings.libraries); - for (auto&& [kind, isDeployed]: {make_pair("bytecode"s, false), make_pair("deployedBytecode"s, true)}) if (isArtifactRequested( _inputsAndSettings.outputSelection, diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 97c67d3b5..caa1bef87 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -249,9 +249,14 @@ MachineAssemblyObject YulStack::assemble(Machine _machine) std::pair YulStack::assembleWithDeployed(std::optional _deployName) { + yulAssert(m_charStream); + auto [creationAssembly, deployedAssembly] = assembleEVMWithDeployed(_deployName); - yulAssert(creationAssembly, ""); - yulAssert(m_charStream, ""); + if (!creationAssembly) + { + yulAssert(!deployedAssembly); + return {MachineAssemblyObject{}, MachineAssemblyObject{}}; + } MachineAssemblyObject creationObject; MachineAssemblyObject deployedObject; @@ -285,6 +290,7 @@ YulStack::assembleWithDeployed(std::optional _deployName) catch (UnimplementedFeatureError const& _error) { reportUnimplementedFeatureError(_error); + return {MachineAssemblyObject{}, MachineAssemblyObject{}}; } return {std::move(creationObject), std::move(deployedObject)}; @@ -341,9 +347,10 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) catch (UnimplementedFeatureError const& _error) { reportUnimplementedFeatureError(_error); + return {nullptr, nullptr}; } - return {std::make_shared(assembly), {}}; + return {std::make_shared(assembly), nullptr}; } std::string YulStack::print() const @@ -415,6 +422,6 @@ std::shared_ptr YulStack::parserResult() const void YulStack::reportUnimplementedFeatureError(UnimplementedFeatureError const& _error) { - solAssert(_error.comment(), "Unimplemented feature errors must include a message for the user"); + yulAssert(_error.comment(), "Errors must include a message for the user."); m_errorReporter.unimplementedFeatureError(1920_error, _error.sourceLocation(), *_error.comment()); } diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 4816ee531..f2bb4af10 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -1232,9 +1232,10 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y bool successful = true; std::map yulStacks; - for (auto const& src: m_fileReader.sourceUnits()) + std::map objects; + for (auto const& [sourceUnitName, yulSource]: m_fileReader.sourceUnits()) { - auto& stack = yulStacks[src.first] = yul::YulStack( + auto& stack = yulStacks[sourceUnitName] = yul::YulStack( m_options.output.evmVersion, m_options.output.eofVersion, _language, @@ -1244,20 +1245,28 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y DebugInfoSelection::Default() ); - if (!stack.parseAndAnalyze(src.first, src.second)) - successful = false; + successful = successful && stack.parseAndAnalyze(sourceUnitName, yulSource); + if (!successful) + solAssert(stack.hasErrors(), "No error reported, but parsing/analysis failed."); else - stack.optimize(); - - if (successful && m_options.compiler.outputs.asmJson) { - std::shared_ptr result = stack.parserResult(); - if (result && !result->hasContiguousSourceIndices()) + if ( + m_options.compiler.outputs.asmJson && + stack.parserResult() && + !stack.parserResult()->hasContiguousSourceIndices() + ) solThrow( CommandLineExecutionError, "Generating the assembly JSON output was not possible. " "Source indices provided in the @use-src annotation in the Yul input do not start at 0 or are not contiguous." ); + + stack.optimize(); + + yul::MachineAssemblyObject object = stack.assemble(_targetMachine); + if (object.bytecode) + object.bytecode->link(m_options.linker.libraries); + objects.insert({sourceUnitName, std::move(object)}); } } @@ -1281,13 +1290,14 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y solThrow(CommandLineExecutionError, ""); } - for (auto const& src: m_fileReader.sourceUnits()) + for (auto const& [sourceUnitName, yulSource]: m_fileReader.sourceUnits()) { solAssert(_targetMachine == yul::YulStack::Machine::EVM); std::string machine = "EVM"; - sout() << std::endl << "======= " << src.first << " (" << machine << ") =======" << std::endl; + sout() << std::endl << "======= " << sourceUnitName << " (" << machine << ") =======" << std::endl; - yul::YulStack& stack = yulStacks[src.first]; + yul::YulStack const& stack = yulStacks[sourceUnitName]; + yul::MachineAssemblyObject const& object = objects[sourceUnitName]; if (m_options.compiler.outputs.irOptimized) { @@ -1297,10 +1307,6 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y sout() << stack.print() << std::endl; } - yul::MachineAssemblyObject object; - object = stack.assemble(_targetMachine); - object.bytecode->link(m_options.linker.libraries); - if (m_options.compiler.outputs.binary) { sout() << std::endl << "Binary representation:" << std::endl; diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp index 126c3ad6f..d507aa333 100644 --- a/test/libyul/ObjectCompilerTest.cpp +++ b/test/libyul/ObjectCompilerTest.cpp @@ -71,18 +71,22 @@ TestCase::TestResult ObjectCompilerTest::run(std::ostream& _stream, std::string OptimiserSettings::preset(m_optimisationPreset), DebugInfoSelection::All() ); - if (!stack.parseAndAnalyze("source", m_source)) + bool successful = stack.parseAndAnalyze("source", m_source); + MachineAssemblyObject obj; + if (successful) + { + stack.optimize(); + obj = stack.assemble(YulStack::Machine::EVM); + } + if (stack.hasErrors()) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; SourceReferenceFormatter{_stream, stack, true, false} .printErrorInformation(stack.errors()); return TestResult::FatalError; } - stack.optimize(); - - MachineAssemblyObject obj = stack.assemble(YulStack::Machine::EVM); - solAssert(obj.bytecode, ""); - solAssert(obj.sourceMappings, ""); + solAssert(obj.bytecode); + solAssert(obj.sourceMappings); m_obtainedResult = "Assembly:\n" + obj.assembly->assemblyString(stack.debugInfoSelection()); if (obj.bytecode->bytecode.empty()) From 65130cdee2e2a68285c75a7910e5a0cb573f2eb2 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 10 Dec 2024 12:21:54 +0100 Subject: [PATCH 0545/1340] eof: Fix immutables for EOF. Pass `m_immutablesVariables` and `m_libraryAddressOffset` to `Deployed` context of IRGenerationContext for EOF --- libsolidity/codegen/ir/IRGenerationContext.cpp | 10 +++++++++- libsolidity/codegen/ir/IRGenerationContext.h | 15 ++++++++++++++- libsolidity/codegen/ir/IRGenerator.cpp | 14 ++++++++++++++ test/libsolidity/semanticTests/immutable/stub.sol | 2 ++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/libsolidity/codegen/ir/IRGenerationContext.cpp b/libsolidity/codegen/ir/IRGenerationContext.cpp index fd47fec10..89ce99949 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.cpp +++ b/libsolidity/codegen/ir/IRGenerationContext.cpp @@ -87,6 +87,7 @@ void IRGenerationContext::resetLocalVariables() void IRGenerationContext::registerImmutableVariable(VariableDeclaration const& _variable) { + solAssert(m_executionContext != ExecutionContext::Deployed); solAssert(_variable.immutable(), "Attempted to register a non-immutable variable as immutable."); solUnimplementedAssert( _variable.annotation().type->isValueType(), @@ -122,6 +123,7 @@ size_t IRGenerationContext::reservedMemorySize() const void IRGenerationContext::registerLibraryAddressImmutable() { + solAssert(m_executionContext != ExecutionContext::Deployed); solAssert(m_reservedMemory.has_value(), "Reserved memory has already been reset."); solAssert(!m_libraryAddressImmutableOffset.has_value()); m_libraryAddressImmutableOffset = CompilerUtils::generalPurposeMemoryStart + *m_reservedMemory; @@ -156,7 +158,13 @@ size_t IRGenerationContext::reservedMemory() immutableVariablesSize += var->type()->sizeOnStack() * 32; } - solAssert(immutableVariablesSize == reservedMemory); + // In Creation context check that only immutable variables or library address are stored in the reserved memory. + // In Deployed context (for EOF) m_immutableVariables contains offsets in EOF data section. + solAssert( + (m_executionContext == ExecutionContext::Creation && + reservedMemory == immutableVariablesSize + (m_libraryAddressImmutableOffset.has_value() ? 32 : 0)) || + (m_executionContext == ExecutionContext::Deployed && reservedMemory == 0) + ); m_reservedMemory = std::nullopt; return reservedMemory; diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index 01220e87b..1a995734d 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -165,6 +165,19 @@ class IRGenerationContext langutil::DebugInfoSelection debugInfoSelection() const { return m_debugInfoSelection; } langutil::CharStreamProvider const* soliditySourceProvider() const { return m_soliditySourceProvider; } + std::map const& immutableVariables() const { return m_immutableVariables; } + void setImmutableVariables(std::map _immutableVariables) + { + solAssert(m_eofVersion.has_value()); + solAssert(m_executionContext == ExecutionContext::Deployed); + m_immutableVariables = std::move(_immutableVariables); + } + void setLibraryAddressImmutableOffset(size_t _libraryAddressImmutableOffset) + { + solAssert(m_eofVersion.has_value()); + solAssert(m_executionContext == ExecutionContext::Deployed); + m_libraryAddressImmutableOffset = _libraryAddressImmutableOffset; + } private: langutil::EVMVersion m_evmVersion; @@ -176,7 +189,7 @@ class IRGenerationContext ContractDefinition const* m_mostDerivedContract = nullptr; std::map m_localVariables; /// Memory offsets reserved for the values of immutable variables during contract creation. - /// This map is empty in the runtime context. + /// This map is empty in the legacy runtime context and may be not empty in EOF runtime context. std::map m_immutableVariables; std::optional m_libraryAddressImmutableOffset; /// Total amount of reserved memory. Reserved memory is used to store diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 688ab258a..e8bb7a874 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -197,8 +197,21 @@ std::string IRGenerator::generate( t("memoryInitCreation", memoryInit(!creationInvolvesMemoryUnsafeAssembly)); t("useSrcMapCreation", formatUseSrcMap(m_context)); + auto const immutableVariables = m_context.immutableVariables(); + auto const libraryAddressImmutableOffset = (_contract.isLibrary() && eof) ? + m_context.libraryAddressImmutableOffset() : 0; + resetContext(_contract, ExecutionContext::Deployed); + // When generating to EOF we have to initialize these two members, because they store offsets in EOF data section + // which is used during deployed container generation + if (m_eofVersion.has_value()) + { + m_context.setImmutableVariables(std::move(immutableVariables)); + if (_contract.isLibrary()) + m_context.setLibraryAddressImmutableOffset(libraryAddressImmutableOffset); + } + // NOTE: Function pointers can be passed from creation code via storage variables. We need to // get all the functions they could point to into the dispatch functions even if they're never // referenced by name in the deployed code. @@ -1153,6 +1166,7 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon m_context.debugInfoSelection(), m_context.soliditySourceProvider() ); + m_context = std::move(newContext); m_context.setMostDerivedContract(_contract); diff --git a/test/libsolidity/semanticTests/immutable/stub.sol b/test/libsolidity/semanticTests/immutable/stub.sol index 092edfab4..c528b1aa7 100644 --- a/test/libsolidity/semanticTests/immutable/stub.sol +++ b/test/libsolidity/semanticTests/immutable/stub.sol @@ -9,5 +9,7 @@ contract C { return (x+x,y); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // f() -> 84, 23 From b3bf85e44799440018c174787e71e6be56dc4994 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 11 Dec 2024 15:33:27 +0100 Subject: [PATCH 0546/1340] eof: Enable `ext*call`s unavailability test for EOF and legacy bytecode format. --- test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul b/test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul index 2dcd04ca6..1d8ae6ddc 100644 --- a/test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul +++ b/test/libyul/yulSyntaxTests/eof/callf_jumpf_retf.yul @@ -5,6 +5,8 @@ object "a" { retf() } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // DeclarationError 4619: (32-37): Function "callf" not found. // DeclarationError 4619: (48-53): Function "jumpf" not found. From 72715f1b2cc7de8f30b012df5ae1a3a5f38ea0e0 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 10 Dec 2024 12:15:03 +0100 Subject: [PATCH 0547/1340] eof: Fix subassembly references in parent object --- libevmasm/Assembly.cpp | 11 ++++++++++- .../semanticTests/libraries/library_address.sol | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 12bb3cccc..1fe4fa7d9 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1657,7 +1657,16 @@ LinkerObject const& Assembly::assembleEOF() const } for (auto i: referencedSubIds) - ret.bytecode += m_subs[i]->assemble().bytecode; + { + size_t const subAssemblyPostionInParentObject = ret.bytecode.size(); + auto const& subAssemblyLinkerObject = m_subs[i]->assemble(); + // Append subassembly bytecode to the parent assembly result bytecode + ret.bytecode += subAssemblyLinkerObject.bytecode; + // Add subassembly link references to parent linker object. + // Offset accordingly to subassembly position in parent object bytecode + for (auto const& [subAssemblyLinkRefPosition, linkRef]: subAssemblyLinkerObject.linkReferences) + ret.linkReferences[subAssemblyPostionInParentObject + subAssemblyLinkRefPosition] = linkRef; + } // TODO: Fill functionDebugData for EOF. It probably should be handled for new code section in the loop above. solRequire(m_namedTags.empty(), AssemblyException, "Named tags must be empty in EOF context."); diff --git a/test/libsolidity/semanticTests/libraries/library_address.sol b/test/libsolidity/semanticTests/libraries/library_address.sol index 6ca064445..af3a45a97 100644 --- a/test/libsolidity/semanticTests/libraries/library_address.sol +++ b/test/libsolidity/semanticTests/libraries/library_address.sol @@ -36,6 +36,7 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy,>=EOFv1 // ---- // library: L // addr() -> false From e6bca7308b3ec86abbcf1e837aca2b5d2b169a90 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 12 Dec 2024 10:54:36 +0100 Subject: [PATCH 0548/1340] Yul CFG Builder: Fix ghost call function name --- libyul/backends/evm/ControlFlowGraphBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 990456732..cce5c9855 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -364,7 +364,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) auto makeValueCompare = [&](Case const& _case) { yul::FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(yul::FunctionCall{ debugDataOf(_case), - yul::Identifier{{}, "eq"_yulname}, + BuiltinName{{}, *equalityBuiltinHandle}, {*_case.value, Identifier{{}, ghostVariableName}} }); BuiltinFunction const& equalityBuiltin = m_dialect.builtin(*equalityBuiltinHandle); From 834e9ada0bc80d8ea3f8e07cba294c3622c360d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 4 Dec 2024 04:04:55 +0100 Subject: [PATCH 0549/1340] Failing tests testing proper handling of CodeGenerationError in Yul --- .../standard_yul_code_generation_error/args | 1 + .../standard_yul_code_generation_error/in.yul | 9 +++++++++ .../standard_yul_code_generation_error/input.json | 6 ++++++ .../standard_yul_code_generation_error/output.json | 13 +++++++++++++ .../strict_asm_code_generation_error/args | 1 + .../strict_asm_code_generation_error/err | 1 + .../strict_asm_code_generation_error/exit | 1 + .../strict_asm_code_generation_error/input.yul | 9 +++++++++ 8 files changed, 41 insertions(+) create mode 100644 test/cmdlineTests/standard_yul_code_generation_error/args create mode 100644 test/cmdlineTests/standard_yul_code_generation_error/in.yul create mode 100644 test/cmdlineTests/standard_yul_code_generation_error/input.json create mode 100644 test/cmdlineTests/standard_yul_code_generation_error/output.json create mode 100644 test/cmdlineTests/strict_asm_code_generation_error/args create mode 100644 test/cmdlineTests/strict_asm_code_generation_error/err create mode 100644 test/cmdlineTests/strict_asm_code_generation_error/exit create mode 100644 test/cmdlineTests/strict_asm_code_generation_error/input.yul diff --git a/test/cmdlineTests/standard_yul_code_generation_error/args b/test/cmdlineTests/standard_yul_code_generation_error/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_code_generation_error/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_code_generation_error/in.yul b/test/cmdlineTests/standard_yul_code_generation_error/in.yul new file mode 100644 index 000000000..2bf18f0c6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_code_generation_error/in.yul @@ -0,0 +1,9 @@ +object "C" { + code {} + + object "C_deployed" { + code { + sstore(0, loadimmutable("1")) + } + } +} diff --git a/test/cmdlineTests/standard_yul_code_generation_error/input.json b/test/cmdlineTests/standard_yul_code_generation_error/input.json new file mode 100644 index 000000000..905eef6c7 --- /dev/null +++ b/test/cmdlineTests/standard_yul_code_generation_error/input.json @@ -0,0 +1,6 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_code_generation_error/in.yul"]} + } +} diff --git a/test/cmdlineTests/standard_yul_code_generation_error/output.json b/test/cmdlineTests/standard_yul_code_generation_error/output.json new file mode 100644 index 000000000..9bd38bbac --- /dev/null +++ b/test/cmdlineTests/standard_yul_code_generation_error/output.json @@ -0,0 +1,13 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "CodeGenerationError: Some immutables were read from but never assigned, possibly because of optimization. + +", + "message": "Some immutables were read from but never assigned, possibly because of optimization.", + "severity": "error", + "type": "CodeGenerationError" + } + ] +} diff --git a/test/cmdlineTests/strict_asm_code_generation_error/args b/test/cmdlineTests/strict_asm_code_generation_error/args new file mode 100644 index 000000000..47be2b30e --- /dev/null +++ b/test/cmdlineTests/strict_asm_code_generation_error/args @@ -0,0 +1 @@ +--strict-assembly --bin diff --git a/test/cmdlineTests/strict_asm_code_generation_error/err b/test/cmdlineTests/strict_asm_code_generation_error/err new file mode 100644 index 000000000..31af508c7 --- /dev/null +++ b/test/cmdlineTests/strict_asm_code_generation_error/err @@ -0,0 +1 @@ +Error: Some immutables were read from but never assigned, possibly because of optimization. diff --git a/test/cmdlineTests/strict_asm_code_generation_error/exit b/test/cmdlineTests/strict_asm_code_generation_error/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/strict_asm_code_generation_error/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/strict_asm_code_generation_error/input.yul b/test/cmdlineTests/strict_asm_code_generation_error/input.yul new file mode 100644 index 000000000..2bf18f0c6 --- /dev/null +++ b/test/cmdlineTests/strict_asm_code_generation_error/input.yul @@ -0,0 +1,9 @@ +object "C" { + code {} + + object "C_deployed" { + code { + sstore(0, loadimmutable("1")) + } + } +} From 47545d3c3ac66547e279fdff0b08e4abdf92b65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 29 Nov 2024 20:07:26 +0100 Subject: [PATCH 0550/1340] Accept throwing as the standard mechanism for reporting errors during code generation --- Changelog.md | 1 + liblangutil/ErrorReporter.cpp | 17 +++++++++++++++++ liblangutil/ErrorReporter.h | 3 +++ libsolidity/interface/CompilerStack.cpp | 6 +----- libyul/YulStack.cpp | 10 ++++++++++ libyul/YulStack.h | 2 ++ 6 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index 29b5870bc..9aaa1ca8b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,7 @@ Compiler Features: Bugfixes: * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. * Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested. +* Yul: Fix internal compiler error when a code generation error should be reported instead. ### 0.8.28 (2024-10-09) diff --git a/liblangutil/ErrorReporter.cpp b/liblangutil/ErrorReporter.cpp index ddb6b70d1..8c8bb7ab0 100644 --- a/liblangutil/ErrorReporter.cpp +++ b/liblangutil/ErrorReporter.cpp @@ -273,6 +273,23 @@ void ErrorReporter::unimplementedFeatureError(ErrorId _error, SourceLocation con ); } +void ErrorReporter::codeGenerationError(ErrorId _error, SourceLocation const& _location, std::string const& _description) +{ + error(_error, Error::Type::CodeGenerationError, _location, _description); +} + +void ErrorReporter::codeGenerationError(Error const& _error) +{ + solAssert(_error.type() == Error::Type::CodeGenerationError); + solAssert(_error.comment(), "Errors must include a message for the user."); + solUnimplementedAssert(!_error.secondarySourceLocation(), "Secondary locations not supported yet."); + codeGenerationError( + _error.errorId(), + _error.sourceLocation() ? *_error.sourceLocation() : SourceLocation{}, + *_error.comment() + ); +} + void ErrorReporter::info( ErrorId _error, SourceLocation const& _location, diff --git a/liblangutil/ErrorReporter.h b/liblangutil/ErrorReporter.h index 989cc4d5e..55e4d5621 100644 --- a/liblangutil/ErrorReporter.h +++ b/liblangutil/ErrorReporter.h @@ -120,6 +120,9 @@ class ErrorReporter void unimplementedFeatureError(ErrorId _error, SourceLocation const& _location, std::string const& _description); + void codeGenerationError(ErrorId _error, SourceLocation const& _location, std::string const& _description); + void codeGenerationError(Error const& _error); + ErrorList const& errors() const; void clear(); diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 6a50b04c5..9649b79c8 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -779,11 +779,7 @@ bool CompilerStack::compile(State _stopAfter) } catch (Error const& _error) { - // Since codegen has no access to the error reporter, the only way for it to - // report an error is to throw. In most cases it uses dedicated exceptions, - // but CodeGenerationError is one case where someone decided to just throw Error. - solAssert(_error.type() == Error::Type::CodeGenerationError); - m_errorReporter.error(_error.errorId(), _error.type(), SourceLocation(), _error.what()); + m_errorReporter.codeGenerationError(_error); } catch (UnimplementedFeatureError const& _error) { diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index caa1bef87..dfab4b687 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -287,6 +287,11 @@ YulStack::assembleWithDeployed(std::optional _deployName) ); } } + catch (Error const& _error) + { + m_errorReporter.codeGenerationError(_error); + return {MachineAssemblyObject{}, MachineAssemblyObject{}}; + } catch (UnimplementedFeatureError const& _error) { reportUnimplementedFeatureError(_error); @@ -344,6 +349,11 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) return {std::make_shared(assembly), std::make_shared(runtimeAssembly)}; } } + catch (Error const& _error) + { + m_errorReporter.codeGenerationError(_error); + return {nullptr, nullptr}; + } catch (UnimplementedFeatureError const& _error) { reportUnimplementedFeatureError(_error); diff --git a/libyul/YulStack.h b/libyul/YulStack.h index de391f591..f9837e553 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -25,6 +25,8 @@ #include #include #include +#include + #include #include From 287c05cd1b697114b7696ed7d4cda3a29d39d649 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:22:11 +0100 Subject: [PATCH 0551/1340] Testing: Add "current" evm version setting to tests --- test/TestCase.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/TestCase.cpp b/test/TestCase.cpp index 942153d3c..9505a2caa 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -114,7 +114,11 @@ void EVMVersionRestrictedTestCase::processEVMVersionSetting() break; versionString = versionString.substr(versionBegin); - std::optional version = langutil::EVMVersion::fromString(versionString); + std::optional version; + if (versionString == "current") + version = std::make_optional(); + else + version = langutil::EVMVersion::fromString(versionString); if (!version) BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid EVM version: \"" + versionString + "\""}); From 20644423ed80d8dc35aafd7182eae24b10283860 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 12 Dec 2024 08:58:25 +0100 Subject: [PATCH 0552/1340] EVMCodeTransformTest: Restrict to current version --- test/libyul/EVMCodeTransformTest.cpp | 5 ++--- test/libyul/evmCodeTransform/after_terminating_function.yul | 1 + test/libyul/evmCodeTransform/early_push_on_deep_swap.yul | 1 + test/libyul/evmCodeTransform/literal_loop.yul | 1 + test/libyul/evmCodeTransform/nonempty_initial_layout.yul | 1 + test/libyul/evmCodeTransform/pops_in_reverting_branch.yul | 1 + test/libyul/evmCodeTransform/stackReuse/for_1.yul | 1 + test/libyul/evmCodeTransform/stackReuse/for_2.yul | 1 + .../evmCodeTransform/stackReuse/function_argument_reuse.yul | 1 + test/libyul/evmCodeTransform/stackReuse/function_call.yul | 1 + .../evmCodeTransform/stackReuse/function_many_arguments.yul | 1 + test/libyul/evmCodeTransform/stackReuse/function_params.yul | 1 + .../stackReuse/function_params_and_retparams.yul | 1 + .../stackReuse/function_params_and_retparams_partly_used.yul | 1 + .../libyul/evmCodeTransform/stackReuse/function_retparam.yul | 1 + .../evmCodeTransform/stackReuse/function_retparam_block.yul | 1 + .../stackReuse/function_retparam_declaration.yul | 1 + .../evmCodeTransform/stackReuse/function_retparam_for.yul | 1 + .../evmCodeTransform/stackReuse/function_retparam_if.yul | 1 + .../evmCodeTransform/stackReuse/function_retparam_leave.yul | 1 + .../evmCodeTransform/stackReuse/function_retparam_read.yul | 1 + .../stackReuse/function_retparam_unassigned.yul | 1 + .../stackReuse/function_retparam_unassigned_multiple.yul | 1 + test/libyul/evmCodeTransform/stackReuse/function_trivial.yul | 1 + .../stackReuse/function_with_body_embedded.yul | 1 + .../evmCodeTransform/stackReuse/functions_multi_return.yul | 1 + test/libyul/evmCodeTransform/stackReuse/if.yul | 1 + .../evmCodeTransform/stackReuse/last_use_in_nested_block.yul | 1 + .../stackReuse/multi_reuse_same_variable_name.yul | 1 + .../evmCodeTransform/stackReuse/multi_reuse_single_slot.yul | 1 + .../stackReuse/multi_reuse_single_slot_nested.yul | 1 + .../stackReuse/reuse_on_decl_assign_not_same_scope.yul | 1 + .../stackReuse/reuse_on_decl_assign_to_last_used.yul | 1 + .../stackReuse/reuse_on_decl_assign_to_last_used_expr.yul | 1 + .../stackReuse/reuse_on_decl_assign_to_not_last_used.yul | 1 + test/libyul/evmCodeTransform/stackReuse/reuse_slots.yul | 1 + .../evmCodeTransform/stackReuse/reuse_slots_function.yul | 1 + .../stackReuse/reuse_slots_function_with_gaps.yul | 1 + .../evmCodeTransform/stackReuse/reuse_too_deep_slot.yul | 1 + test/libyul/evmCodeTransform/stackReuse/single_var.yul | 1 + .../evmCodeTransform/stackReuse/single_var_assigned.yul | 1 + .../stackReuse/single_var_assigned_plus_code.yul | 1 + .../stackReuse/single_var_assigned_plus_code_and_reused.yul | 1 + test/libyul/evmCodeTransform/stackReuse/smoke.yul | 1 + test/libyul/evmCodeTransform/stackReuse/switch.yul | 1 + test/libyul/evmCodeTransform/stub.yul | 1 + test/libyul/evmCodeTransform/unassigned_return_variable.yul | 1 + 47 files changed, 48 insertions(+), 3 deletions(-) diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 288c35570..3d80281c7 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -46,7 +46,6 @@ EVMCodeTransformTest::EVMCodeTransformTest(std::string const& _filename): m_source = m_reader.source(); m_stackOpt = m_reader.boolSetting("stackOptimization", false); m_expectation = m_reader.simpleExpectations(); - m_shouldRun = CommonOptions::get().evmDialect().evmVersion() == EVMVersion{}; } TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) @@ -57,8 +56,8 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin // Restrict to a single EVM/EOF version combination (the default one) as code generation // can be different from version to version. YulStack stack( - EVMVersion{}, - std::nullopt, + CommonOptions::get().evmVersion(), + CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, settings, DebugInfoSelection::All() diff --git a/test/libyul/evmCodeTransform/after_terminating_function.yul b/test/libyul/evmCodeTransform/after_terminating_function.yul index ee32b4431..7baa751c3 100644 --- a/test/libyul/evmCodeTransform/after_terminating_function.yul +++ b/test/libyul/evmCodeTransform/after_terminating_function.yul @@ -5,6 +5,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":17:18 */ // 0x02 diff --git a/test/libyul/evmCodeTransform/early_push_on_deep_swap.yul b/test/libyul/evmCodeTransform/early_push_on_deep_swap.yul index 5e119cc73..3d9d55e78 100644 --- a/test/libyul/evmCodeTransform/early_push_on_deep_swap.yul +++ b/test/libyul/evmCodeTransform/early_push_on_deep_swap.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":1027:1092 */ // 0x0100000000000000000000000000000000000000000000000000000000000001 diff --git a/test/libyul/evmCodeTransform/literal_loop.yul b/test/libyul/evmCodeTransform/literal_loop.yul index d743836cb..060d0f428 100644 --- a/test/libyul/evmCodeTransform/literal_loop.yul +++ b/test/libyul/evmCodeTransform/literal_loop.yul @@ -14,6 +14,7 @@ object "main" { } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":62:82 */ // dataSize(sub_0) diff --git a/test/libyul/evmCodeTransform/nonempty_initial_layout.yul b/test/libyul/evmCodeTransform/nonempty_initial_layout.yul index eb1a787c0..df2277724 100644 --- a/test/libyul/evmCodeTransform/nonempty_initial_layout.yul +++ b/test/libyul/evmCodeTransform/nonempty_initial_layout.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":9:69 */ // 0x2000000000000000000000000000000000000000000000000000000000 diff --git a/test/libyul/evmCodeTransform/pops_in_reverting_branch.yul b/test/libyul/evmCodeTransform/pops_in_reverting_branch.yul index 78bf0a168..5c1f027a4 100644 --- a/test/libyul/evmCodeTransform/pops_in_reverting_branch.yul +++ b/test/libyul/evmCodeTransform/pops_in_reverting_branch.yul @@ -10,6 +10,7 @@ object "main" { } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":51:52 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/for_1.yul b/test/libyul/evmCodeTransform/stackReuse/for_1.yul index b02710598..92ecf2314 100644 --- a/test/libyul/evmCodeTransform/stackReuse/for_1.yul +++ b/test/libyul/evmCodeTransform/stackReuse/for_1.yul @@ -1,6 +1,7 @@ { for { let z := 0 } 1 { } { let x := 3 } let t := 2 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":17:18 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/for_2.yul b/test/libyul/evmCodeTransform/stackReuse/for_2.yul index 37d372fb9..20403c512 100644 --- a/test/libyul/evmCodeTransform/stackReuse/for_2.yul +++ b/test/libyul/evmCodeTransform/stackReuse/for_2.yul @@ -1,6 +1,7 @@ { for { let z := 0 } 1 { } { z := 8 let x := 3 } let t := 2 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":17:18 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul index 96637da89..c5fea43e8 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:88 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_call.yul b/test/libyul/evmCodeTransform/stackReuse/function_call.yul index 507b35441..669d62bb8 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_call.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_call.yul @@ -5,6 +5,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:22 */ // tag_2 diff --git a/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul b/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul index 17ccdd3ca..f92aa2954 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul @@ -24,6 +24,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:662 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_params.yul b/test/libyul/evmCodeTransform/stackReuse/function_params.yul index e8d9bb30c..4f667cf17 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_params.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_params.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:28 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul index 1d157663a..78e788808 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul @@ -7,6 +7,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":210:252 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul index d0fc0506f..401b6927f 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:80 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul index bee0d3f63..6dc0cacff 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:32 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul index 5a9e7704e..2fad31cc7 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:65 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul index 97bffac38..868316393 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:65 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul index c18fb7c37..698f50830 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:78 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul index 08dda5a3b..e7c752a15 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:70 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul index 9ac0c00bf..b043977f7 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:67 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul index fcc8278e6..4266f1499 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:74 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul index 1cc19a464..e83d68dd0 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:46 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul index e44e3b437..bef253867 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:52 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul b/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul index 3d6286efd..e9f44f11d 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul @@ -3,6 +3,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:22 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul b/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul index f8480bc91..077a2e428 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul @@ -8,6 +8,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:16 */ // 0x03 diff --git a/test/libyul/evmCodeTransform/stackReuse/functions_multi_return.yul b/test/libyul/evmCodeTransform/stackReuse/functions_multi_return.yul index 1ce02483d..e834b7aa8 100644 --- a/test/libyul/evmCodeTransform/stackReuse/functions_multi_return.yul +++ b/test/libyul/evmCodeTransform/stackReuse/functions_multi_return.yul @@ -9,6 +9,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":74:81 */ // tag_3 diff --git a/test/libyul/evmCodeTransform/stackReuse/if.yul b/test/libyul/evmCodeTransform/stackReuse/if.yul index cee19ab93..23ab75b59 100644 --- a/test/libyul/evmCodeTransform/stackReuse/if.yul +++ b/test/libyul/evmCodeTransform/stackReuse/if.yul @@ -2,6 +2,7 @@ { let z := mload(0) if z { let x := z } let t := 3 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":72:73 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/last_use_in_nested_block.yul b/test/libyul/evmCodeTransform/stackReuse/last_use_in_nested_block.yul index 49ffb3971..ed0a297bb 100644 --- a/test/libyul/evmCodeTransform/stackReuse/last_use_in_nested_block.yul +++ b/test/libyul/evmCodeTransform/stackReuse/last_use_in_nested_block.yul @@ -1,6 +1,7 @@ { let z := 0 { pop(z) } let x := 1 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_same_variable_name.yul b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_same_variable_name.yul index 3404dc536..eee735565 100644 --- a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_same_variable_name.yul +++ b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_same_variable_name.yul @@ -1,6 +1,7 @@ { let z := mload(0) { let x := 1 x := 6 z := x } { let x := 2 z := x x := 4 } } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":17:18 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot.yul b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot.yul index a80e66c10..dde7e1269 100644 --- a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot.yul +++ b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot.yul @@ -1,6 +1,7 @@ { let x := 1 x := 6 let y := 2 y := 4 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x01 diff --git a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot_nested.yul b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot_nested.yul index db8783502..fdf2f695b 100644 --- a/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot_nested.yul +++ b/test/libyul/evmCodeTransform/stackReuse/multi_reuse_single_slot_nested.yul @@ -1,6 +1,7 @@ { let x := 1 x := 6 { let y := 2 y := 4 } } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x01 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_not_same_scope.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_not_same_scope.yul index 9be91989d..4d0531a4d 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_not_same_scope.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_not_same_scope.yul @@ -7,6 +7,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:16 */ // 0x05 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used.yul index 11e77c626..a7ef081e2 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used.yul @@ -5,6 +5,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:16 */ // 0x05 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used_expr.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used_expr.yul index 214020ccd..adaa15461 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used_expr.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_last_used_expr.yul @@ -5,6 +5,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":37:38 */ // 0x02 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_not_last_used.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_not_last_used.yul index e3002f34d..3d10ecd42 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_not_last_used.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_on_decl_assign_to_not_last_used.yul @@ -5,6 +5,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:16 */ // 0x05 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_slots.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_slots.yul index 13decd323..b9bbeeb38 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_slots.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_slots.yul @@ -1,6 +1,7 @@ { let a, b, c, d let x := 2 let y := 3 mstore(x, a) mstore(y, c) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":2:16 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function.yul index 13e3065cc..1af5c6454 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function.yul @@ -4,6 +4,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":58:61 */ // tag_2 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function_with_gaps.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function_with_gaps.yul index f1cde362a..329d354ce 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function_with_gaps.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_slots_function_with_gaps.yul @@ -8,6 +8,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":106:107 */ // 0x05 diff --git a/test/libyul/evmCodeTransform/stackReuse/reuse_too_deep_slot.yul b/test/libyul/evmCodeTransform/stackReuse/reuse_too_deep_slot.yul index 2adfe7892..a2f2a1b47 100644 --- a/test/libyul/evmCodeTransform/stackReuse/reuse_too_deep_slot.yul +++ b/test/libyul/evmCodeTransform/stackReuse/reuse_too_deep_slot.yul @@ -32,6 +32,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":15:16 */ // 0x07 diff --git a/test/libyul/evmCodeTransform/stackReuse/single_var.yul b/test/libyul/evmCodeTransform/stackReuse/single_var.yul index 09a0d6fee..d42e5928a 100644 --- a/test/libyul/evmCodeTransform/stackReuse/single_var.yul +++ b/test/libyul/evmCodeTransform/stackReuse/single_var.yul @@ -1,6 +1,7 @@ { let x } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":2:7 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned.yul b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned.yul index ed497467d..3d6b68000 100644 --- a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned.yul +++ b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned.yul @@ -1,6 +1,7 @@ { let x := 1 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x01 diff --git a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code.yul b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code.yul index bec4c834f..707c8a306 100644 --- a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code.yul +++ b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code.yul @@ -1,6 +1,7 @@ { let x := 1 mstore(3, 4) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x01 diff --git a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code_and_reused.yul b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code_and_reused.yul index b9a814700..8f3e28390 100644 --- a/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code_and_reused.yul +++ b/test/libyul/evmCodeTransform/stackReuse/single_var_assigned_plus_code_and_reused.yul @@ -1,6 +1,7 @@ { let x := 1 mstore(3, 4) pop(mload(x)) } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x01 diff --git a/test/libyul/evmCodeTransform/stackReuse/smoke.yul b/test/libyul/evmCodeTransform/stackReuse/smoke.yul index aa46f7a4a..32b3704fd 100644 --- a/test/libyul/evmCodeTransform/stackReuse/smoke.yul +++ b/test/libyul/evmCodeTransform/stackReuse/smoke.yul @@ -1,6 +1,7 @@ {} // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:2 */ // stop diff --git a/test/libyul/evmCodeTransform/stackReuse/switch.yul b/test/libyul/evmCodeTransform/stackReuse/switch.yul index f72d80fad..a7fb935a4 100644 --- a/test/libyul/evmCodeTransform/stackReuse/switch.yul +++ b/test/libyul/evmCodeTransform/stackReuse/switch.yul @@ -1,6 +1,7 @@ { let z := 0 switch z case 0 { let x := 2 let y := 3 } default { z := 3 } let t := 9 } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":11:12 */ // 0x00 diff --git a/test/libyul/evmCodeTransform/stub.yul b/test/libyul/evmCodeTransform/stub.yul index ef7cd668c..f8541dd3f 100644 --- a/test/libyul/evmCodeTransform/stub.yul +++ b/test/libyul/evmCodeTransform/stub.yul @@ -19,6 +19,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":14:21 */ // tag_2 diff --git a/test/libyul/evmCodeTransform/unassigned_return_variable.yul b/test/libyul/evmCodeTransform/unassigned_return_variable.yul index 666fefe1a..2c28d52a3 100644 --- a/test/libyul/evmCodeTransform/unassigned_return_variable.yul +++ b/test/libyul/evmCodeTransform/unassigned_return_variable.yul @@ -6,6 +6,7 @@ } // ==== // stackOptimization: true +// EVMVersion: =current // ---- // /* "":0:111 */ // stop From 3c0545cfbb0bbb65a4408641cd6cfa8d541a15d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 4 Dec 2024 00:41:11 +0100 Subject: [PATCH 0553/1340] YulOptimizerTestCommon: Get Dialect from Object --- test/libyul/YulOptimizerTest.cpp | 2 +- test/libyul/YulOptimizerTestCommon.cpp | 33 ++++++++++---------- test/libyul/YulOptimizerTestCommon.h | 7 +---- test/tools/ossfuzz/yulProtoFuzzer.cpp | 5 +-- test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp | 5 +-- 5 files changed, 21 insertions(+), 31 deletions(-) diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index dc05810bc..03f05ffa2 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -74,7 +74,7 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co soltestAssert(m_dialect, "Dialect not set."); m_object->analysisInfo = m_analysisInfo; - YulOptimizerTestCommon tester(m_object, *m_dialect); + YulOptimizerTestCommon tester(m_object); tester.setStep(m_optimizerStep); if (!tester.runStep()) diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 351d705cc..19b2176c1 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -18,6 +18,8 @@ #include +#include + #include #include #include @@ -73,11 +75,12 @@ using namespace solidity::yul; using namespace solidity::yul::test; using namespace solidity::frontend; -YulOptimizerTestCommon::YulOptimizerTestCommon( - std::shared_ptr _obj, - Dialect const& _dialect -): m_dialect(&_dialect), m_object(_obj), m_optimizedObject(std::make_shared(*_obj)) +YulOptimizerTestCommon::YulOptimizerTestCommon(std::shared_ptr _obj): + m_object(_obj), + m_optimizedObject(std::make_shared(*_obj)) { + soltestAssert(m_object && m_optimizedObject); + if ( std::any_of( m_object->subObjects.begin(), @@ -85,7 +88,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( [](auto const& subObject) { return dynamic_cast(subObject.get()) == nullptr;} ) ) - solUnimplementedAssert(false, "The current implementation of YulOptimizerTests ignores subobjects that are not Data."); + solUnimplemented("The current implementation of YulOptimizerTests ignores subobjects that are not Data."); m_namedSteps = { {"disambiguator", [&]() { return disambiguate(); }}, @@ -108,8 +111,8 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( {"constantOptimiser", [&]() { auto block = std::get(ASTCopier{}(m_object->code()->root())); updateContext(block); - GasMeter meter(dynamic_cast(*m_dialect), false, 200); - ConstantOptimiser{dynamic_cast(*m_dialect), meter}(block); + GasMeter meter(dynamic_cast(*m_object->dialect()), false, 200); + ConstantOptimiser{dynamic_cast(*m_object->dialect()), meter}(block); return block; }}, {"varDeclInitializer", [&]() { @@ -410,14 +413,14 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( size_t maxIterations = 16; { Object object(*m_optimizedObject); - object.setCode(std::make_shared(*m_dialect, std::get(ASTCopier{}(block)))); + object.setCode(std::make_shared(*m_object->dialect(), std::get(ASTCopier{}(block)))); block = std::get<1>(StackCompressor::run(object, true, maxIterations)); } BlockFlattener::run(*m_context, block); return block; }}, {"fullSuite", [&]() { - GasMeter meter(dynamic_cast(*m_dialect), false, 200); + GasMeter meter(dynamic_cast(*m_object->dialect()), false, 200); OptimiserSuite::run( &meter, *m_optimizedObject, @@ -432,7 +435,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( auto block = disambiguate(); updateContext(block); Object object(*m_optimizedObject); - object.setCode(std::make_shared(*m_dialect, std::get(ASTCopier{}(block)))); + object.setCode(std::make_shared(*m_object->dialect(), std::get(ASTCopier{}(block)))); auto const unreachables = CompilabilityChecker{ object, true @@ -493,12 +496,10 @@ void YulOptimizerTestCommon::setStep(std::string const& _optimizerStep) bool YulOptimizerTestCommon::runStep() { - yulAssert(m_dialect, "Dialect not set."); - if (m_namedSteps.count(m_optimizerStep)) { auto block = m_namedSteps[m_optimizerStep](); - m_optimizedObject->setCode(std::make_shared(*m_dialect, std::move(block))); + m_optimizedObject->setCode(std::make_shared(*m_object->dialect(), std::move(block))); } else return false; @@ -542,15 +543,15 @@ Block const* YulOptimizerTestCommon::run() Block YulOptimizerTestCommon::disambiguate() { - auto block = std::get(Disambiguator(*m_dialect, *m_object->analysisInfo)(m_object->code()->root())); + auto block = std::get(Disambiguator(*m_object->dialect(), *m_object->analysisInfo)(m_object->code()->root())); return block; } void YulOptimizerTestCommon::updateContext(Block const& _block) { - m_nameDispenser = std::make_unique(*m_dialect, _block, m_reservedIdentifiers); + m_nameDispenser = std::make_unique(*m_object->dialect(), _block, m_reservedIdentifiers); m_context = std::make_unique(OptimiserStepContext{ - *m_dialect, + *m_object->dialect(), *m_nameDispenser, m_reservedIdentifiers, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h index bc513e748..df5c84039 100644 --- a/test/libyul/YulOptimizerTestCommon.h +++ b/test/libyul/YulOptimizerTestCommon.h @@ -30,7 +30,6 @@ namespace solidity::yul { struct AsmAnalysisInfo; class Object; -class Dialect; class AST; } @@ -39,10 +38,7 @@ namespace solidity::yul::test class YulOptimizerTestCommon { public: - explicit YulOptimizerTestCommon( - std::shared_ptr _obj, - Dialect const& _dialect - ); + explicit YulOptimizerTestCommon(std::shared_ptr _obj); /// Sets optimiser step to be run to @param /// _optimiserStep. void setStep(std::string const& _optimizerStep); @@ -65,7 +61,6 @@ class YulOptimizerTestCommon std::string m_optimizerStep; - Dialect const* m_dialect = nullptr; std::set m_reservedIdentifiers; std::unique_ptr m_nameDispenser; std::unique_ptr m_context; diff --git a/test/tools/ossfuzz/yulProtoFuzzer.cpp b/test/tools/ossfuzz/yulProtoFuzzer.cpp index 4e9387f6f..2f372c325 100644 --- a/test/tools/ossfuzz/yulProtoFuzzer.cpp +++ b/test/tools/ossfuzz/yulProtoFuzzer.cpp @@ -80,10 +80,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // TODO: Add EOF support // Optimize - YulOptimizerTestCommon optimizerTest( - stack.parserResult(), - EVMDialect::strictAssemblyForEVMObjects(version, std::nullopt) - ); + YulOptimizerTestCommon optimizerTest(stack.parserResult()); optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); auto const* astRoot = optimizerTest.run(); yulAssert(astRoot != nullptr, "Optimiser error."); diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index eff96f831..d15043972 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -99,10 +99,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) return; // TODO: Add EOF support - YulOptimizerTestCommon optimizerTest( - stack.parserResult(), - EVMDialect::strictAssemblyForEVMObjects(version, std::nullopt) - ); + YulOptimizerTestCommon optimizerTest(stack.parserResult()); optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); auto const* astRoot = optimizerTest.run(); yulAssert(astRoot != nullptr, "Optimiser error."); From 46b0616aaed98fa7ddef3c396d7d5fa81d075f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 4 Dec 2024 01:13:29 +0100 Subject: [PATCH 0554/1340] Unify Yul code parsing across different test suites --- libyul/YulStack.cpp | 7 ++ libyul/YulStack.h | 3 + test/libsolidity/MemoryGuardTest.cpp | 29 +++--- test/libyul/Common.cpp | 102 +++++++++++---------- test/libyul/Common.h | 21 ++++- test/libyul/CompilabilityChecker.cpp | 15 +-- test/libyul/ControlFlowGraphTest.cpp | 24 ++--- test/libyul/ControlFlowGraphTest.h | 10 +- test/libyul/ControlFlowSideEffectsTest.cpp | 24 +++-- test/libyul/EVMCodeTransformTest.cpp | 19 ++-- test/libyul/FunctionSideEffects.cpp | 23 ++--- test/libyul/FunctionSideEffects.h | 1 - test/libyul/KnowledgeBaseTest.cpp | 26 +++--- test/libyul/Metrics.cpp | 10 +- test/libyul/ObjectCompilerTest.cpp | 30 ++---- test/libyul/ObjectCompilerTest.h | 1 - test/libyul/ObjectParser.cpp | 41 ++------- test/libyul/SSAControlFlowGraphTest.cpp | 25 ++--- test/libyul/SSAControlFlowGraphTest.h | 10 +- test/libyul/StackLayoutGeneratorTest.cpp | 28 +++--- test/libyul/StackLayoutGeneratorTest.h | 10 +- test/libyul/SyntaxTest.cpp | 34 +++---- test/libyul/SyntaxTest.h | 4 - test/libyul/YulInterpreterTest.cpp | 45 +++------ test/libyul/YulInterpreterTest.h | 8 +- test/libyul/YulOptimizerTest.cpp | 34 +++---- test/libyul/YulOptimizerTest.h | 10 +- 27 files changed, 259 insertions(+), 335 deletions(-) diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index dfab4b687..791b7103d 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -430,6 +430,13 @@ std::shared_ptr YulStack::parserResult() const return m_parserResult; } +Dialect const& YulStack::dialect() const +{ + yulAssert(m_stackState >= AnalysisSuccessful); + yulAssert(m_parserResult && m_parserResult->dialect()); + return *m_parserResult->dialect(); +} + void YulStack::reportUnimplementedFeatureError(UnimplementedFeatureError const& _error) { yulAssert(_error.comment(), "Errors must include a message for the user."); diff --git a/libyul/YulStack.h b/libyul/YulStack.h index f9837e553..94688fddc 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -139,6 +139,7 @@ class YulStack: public langutil::CharStreamProvider /// @returns the errors generated during parsing, analysis (and potentially assembly). langutil::ErrorList const& errors() const { return m_errors; } bool hasErrors() const { return m_errorReporter.hasErrors(); } + bool hasErrorsWarningsOrInfos() const { return m_errorReporter.hasErrorsWarningsOrInfos(); } /// Pretty-print the input after having parsed it. std::string print() const; @@ -150,6 +151,8 @@ class YulStack: public langutil::CharStreamProvider /// Return the parsed and analyzed object. std::shared_ptr parserResult() const; + Dialect const& dialect() const; + langutil::DebugInfoSelection debugInfoSelection() const { return m_debugInfoSelection; } private: diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index 9826f4b19..0f4230d5a 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -20,13 +20,17 @@ #include #include + #include + #include #include + #include -#include #include #include +#include + #include #include #include @@ -38,6 +42,7 @@ using namespace solidity::langutil; using namespace solidity::frontend; using namespace solidity::frontend::test; using namespace solidity::test; +using namespace solidity::yul::test; using namespace yul; void MemoryGuardTest::setupCompiler(CompilerStack& _compiler) @@ -59,20 +64,14 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con m_obtainedResult.clear(); for (std::string contractName: compiler().contractNames()) { - auto const& dialect = CommonOptions::get().evmDialect(); ErrorList errors; std::optional const& ir = compiler().yulIR(contractName); - solAssert(ir); - auto [object, analysisInfo] = yul::test::parse( - *ir, - dialect, - errors - ); + soltestAssert(ir); - if (!object || !analysisInfo || Error::containsErrors(errors)) + YulStack yulStack = parseYul(*ir); + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing IR:" << std::endl; - printPrefixed(_stream, formatErrors(filterErrors(errors), _formatted), _linePrefix); + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } @@ -80,14 +79,14 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con m_obtainedResult += contractName + "(" + _kind + ") " + (findFunctionCalls( _object.code()->root(), "memoryguard", - dialect + yulStack.dialect() ).empty() ? "false" : "true") + "\n"; }; - handleObject("creation", *object); - size_t deployedIndex = object->subIndexByName.at( + handleObject("creation", *yulStack.parserResult()); + size_t deployedIndex = yulStack.parserResult()->subIndexByName.at( IRNames::deployedObject(compiler().contractDefinition(contractName)) ); - handleObject("runtime", dynamic_cast(*object->subObjects[deployedIndex])); + handleObject("runtime", dynamic_cast(*yulStack.parserResult()->subObjects[deployedIndex])); } return checkResult(_stream, _linePrefix, _formatted); } diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 32f60c8eb..e64558bd4 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -21,6 +21,8 @@ #include +#include + #include #include @@ -30,76 +32,69 @@ #include #include +#include + #include #include #include +#include #include #include using namespace solidity; +using namespace solidity::frontend; using namespace solidity::yul; using namespace solidity::langutil; +using namespace solidity::util; +using namespace solidity::test; -namespace -{ -Dialect const& defaultDialect() -{ - return yul::EVMDialect::strictAssemblyForEVM( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); -} -} - -std::pair, std::shared_ptr> yul::test::parse(std::string const& _source) +YulStack yul::test::parseYul( + std::string const& _source, + std::string _sourceUnitName, + std::optional _optimiserSettings +) { - YulStack stack( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion(), + YulStack yulStack( + CommonOptions::get().evmVersion(), + CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, - solidity::test::CommonOptions::get().optimize ? - solidity::frontend::OptimiserSettings::standard() : - solidity::frontend::OptimiserSettings::minimal(), + _optimiserSettings.has_value() ? + *_optimiserSettings : + (CommonOptions::get().optimize ? OptimiserSettings::standard() : OptimiserSettings::minimal()), DebugInfoSelection::All() ); - if (!stack.parseAndAnalyze("", _source) || Error::hasErrorsWarningsOrInfos(stack.errors())) - BOOST_FAIL("Invalid source."); - return std::make_pair(stack.parserResult()->code(), stack.parserResult()->analysisInfo); -} - -std::pair, std::shared_ptr> yul::test::parse( - std::string const& _source, - Dialect const& _dialect, - ErrorList& _errors -) -{ - ErrorReporter errorReporter(_errors); - CharStream stream(_source, ""); - std::shared_ptr scanner = std::make_shared(stream); - std::shared_ptr parserResult = yul::ObjectParser(errorReporter, _dialect).parse(scanner, false); - if (!parserResult) - return {}; - if (!parserResult->hasCode() || errorReporter.hasErrors()) - return {}; - std::shared_ptr analysisInfo = std::make_shared(); - AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect, {}, parserResult->summarizeStructure()); - // TODO this should be done recursively. - if (!analyzer.analyze(parserResult->code()->root()) || errorReporter.hasErrors()) - return {}; - return {std::move(parserResult), std::move(analysisInfo)}; + bool successful = yulStack.parseAndAnalyze(_sourceUnitName, _source); + if (!successful) + soltestAssert(yulStack.hasErrors()); + else + { + soltestAssert(!yulStack.hasErrors()); + soltestAssert(yulStack.parserResult()); + soltestAssert(yulStack.parserResult()->code()); + soltestAssert(yulStack.parserResult()->analysisInfo); + } + return yulStack; } yul::Block yul::test::disambiguate(std::string const& _source) { - auto result = parse(_source); - return std::get(Disambiguator(defaultDialect(), *result.second, {})(result.first->root())); + YulStack yulStack = parseYul(_source); + soltestAssert(!yulStack.hasErrorsWarningsOrInfos()); + return std::get(Disambiguator( + yulStack.dialect(), + *yulStack.parserResult()->analysisInfo, + {} + )(yulStack.parserResult()->code()->root())); } std::string yul::test::format(std::string const& _source) { - return AsmPrinter::format(*parse(_source).first); + YulStack yulStack = parseYul(_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Subobjects not supported."); + soltestAssert(!yulStack.hasErrorsWarningsOrInfos()); + return AsmPrinter::format(*yulStack.parserResult()->code()); } namespace @@ -134,3 +129,18 @@ yul::Dialect const& yul::test::dialect(std::string const& _name, langutil::EVMVe return validDialects.at(_name)(_evmVersion, _eofVersion); } + +void yul::test::printYulErrors( + YulStack const& _yulStack, + std::ostream& _stream, + std::string const& _linePrefix, + bool const _formatted +) +{ + AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) + << _linePrefix + << "Error parsing source." + << std::endl; + SourceReferenceFormatter formatter{_stream, _yulStack, true, false}; + formatter.printErrorInformation(_yulStack.errors()); +} diff --git a/test/libyul/Common.h b/test/libyul/Common.h index e36e81052..de402c29a 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -21,11 +21,14 @@ #pragma once +#include + #include #include #include #include +#include namespace solidity::langutil { @@ -40,20 +43,28 @@ struct Block; class Object; class Dialect; class AST; +class YulStack; } namespace solidity::yul::test { -std::pair, std::shared_ptr> -parse(std::string const& _source); - -std::pair, std::shared_ptr> -parse(std::string const& _source, Dialect const& _dialect, langutil::ErrorList& _errors); +yul::YulStack parseYul( + std::string const& _source, + std::string _sourceUnitName = "", + std::optional _optimiserSettings = std::nullopt +); Block disambiguate(std::string const& _source); std::string format(std::string const& _source); solidity::yul::Dialect const& dialect(std::string const& _name, langutil::EVMVersion _evmVersion, std::optional _eofVersion); +void printYulErrors( + yul::YulStack const& _yulStack, + std::ostream& _stream, + std::string const& _linePrefix, + bool const _formatted +); + } diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index 1956db84c..a030af487 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -20,10 +20,12 @@ #include +#include + #include -#include #include +#include #include @@ -34,12 +36,11 @@ namespace { std::string check(std::string const& _input) { - Object obj; - auto parsingResult = yul::test::parse(_input); - obj.setCode(parsingResult.first, parsingResult.second); - BOOST_REQUIRE(obj.hasCode()); - BOOST_REQUIRE(obj.dialect()); - auto functions = CompilabilityChecker(obj, true).stackDeficit; + YulStack yulStack = parseYul(_input); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + soltestAssert(!yulStack.hasErrorsWarningsOrInfos()); + + auto functions = CompilabilityChecker(*yulStack.parserResult(), true).stackDeficit; std::string out; for (auto const& function: functions) out += function.first.str() + ": " + std::to_string(function.second) + " "; diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index bd0bf0a80..c0ab37956 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -24,8 +24,8 @@ #include #include #include +#include -#include #include #ifdef ISOLTEST @@ -45,11 +45,7 @@ ControlFlowGraphTest::ControlFlowGraphTest(std::string const& _filename): { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect( - dialectName, - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + soltestAssert(dialectName == "evm"); // We only have one dialect now m_expectation = m_reader.simpleExpectations(); } @@ -201,20 +197,24 @@ class ControlFlowGraphPrinter TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - ErrorList errors; - auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); - if (!object || !analysisInfo || Error::containsErrors(errors)) + YulStack yulStack = parseYul(m_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code()->root()); + std::unique_ptr cfg = ControlFlowGraphBuilder::build( + *yulStack.parserResult()->analysisInfo, + yulStack.dialect(), + yulStack.parserResult()->code()->root() + ); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - ControlFlowGraphPrinter printer{output, *m_dialect}; + ControlFlowGraphPrinter printer{output, yulStack.dialect()}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/ControlFlowGraphTest.h b/test/libyul/ControlFlowGraphTest.h index 953a27b22..f6c8ddfce 100644 --- a/test/libyul/ControlFlowGraphTest.h +++ b/test/libyul/ControlFlowGraphTest.h @@ -20,11 +20,7 @@ #include -namespace solidity::yul -{ -class Dialect; - -namespace test +namespace solidity::yul::test { class ControlFlowGraphTest: public frontend::test::EVMVersionRestrictedTestCase @@ -36,8 +32,6 @@ class ControlFlowGraphTest: public frontend::test::EVMVersionRestrictedTestCase } explicit ControlFlowGraphTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; -private: - Dialect const* m_dialect = nullptr; }; -} + } diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index 50c546e36..2249ba110 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -25,13 +25,15 @@ #include #include #include -#include +#include using namespace solidity; using namespace solidity::test; using namespace solidity::yul; using namespace solidity::yul::test; using namespace solidity::frontend::test; +using namespace solidity::util; +using namespace solidity::langutil; namespace { @@ -57,19 +59,21 @@ ControlFlowSideEffectsTest::ControlFlowSideEffectsTest(std::string const& _filen TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - auto const& dialect = CommonOptions::get().evmDialect(); - Object obj; - auto parsingResult = parse(m_source); - obj.setCode(parsingResult.first, parsingResult.second); - if (!obj.hasCode()) - BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); + YulStack yulStack = parseYul(m_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + + if (yulStack.hasErrors()) + { + printYulErrors(yulStack, _stream, _linePrefix, _formatted); + return TestResult::FatalError; + } ControlFlowSideEffectsCollector sideEffects( - dialect, - obj.code()->root() + yulStack.dialect(), + yulStack.parserResult()->code()->root() ); m_obtainedResult.clear(); - forEach(obj.code()->root(), [&](FunctionDefinition const& _fun) { + forEach(yulStack.parserResult()->code()->root(), [&](FunctionDefinition const& _fun) { std::string effectStr = toString(sideEffects.functionSideEffects().at(&_fun)); m_obtainedResult += _fun.name.str() + (effectStr.empty() ? ":" : ": " + effectStr) + "\n"; }); diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 3d80281c7..624a44c3e 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -27,9 +27,7 @@ #include -#include - -#include +#include using namespace solidity; using namespace solidity::test; @@ -55,32 +53,29 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin settings.optimizeStackAllocation = m_stackOpt; // Restrict to a single EVM/EOF version combination (the default one) as code generation // can be different from version to version. - YulStack stack( + YulStack yulStack( CommonOptions::get().evmVersion(), CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, settings, DebugInfoSelection::All() ); - if (!stack.parseAndAnalyze("", m_source)) + yulStack.parseAndAnalyze("", m_source); + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; - SourceReferenceFormatter{_stream, stack, true, false} - .printErrorInformation(stack.errors()); + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } evmasm::Assembly assembly{CommonOptions::get().evmVersion(), false, std::nullopt, {}}; EthAssemblyAdapter adapter(assembly); EVMObjectCompiler::compile( - *stack.parserResult(), + *yulStack.parserResult(), adapter, m_stackOpt ); - std::ostringstream output; - output << assembly; - m_obtainedResult = output.str(); + m_obtainedResult = toString(assembly); return checkResult(_stream, _linePrefix, _formatted); } diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index d19d87844..4dab4ace2 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -20,12 +20,11 @@ #include #include -#include - #include #include #include #include +#include #include #include @@ -84,16 +83,18 @@ FunctionSideEffects::FunctionSideEffects(std::string const& _filename): TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - auto const& dialect = CommonOptions::get().evmDialect(); - Object obj; - auto parsingResult = parse(m_source); - obj.setCode(parsingResult.first, parsingResult.second); - if (!obj.hasCode()) - BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); + YulStack yulStack = parseYul(m_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + + if (yulStack.hasErrors()) + { + printYulErrors(yulStack, _stream, _linePrefix, _formatted); + return TestResult::FatalError; + } std::map functionSideEffects = SideEffectsPropagator::sideEffects( - dialect, - CallGraphGenerator::callGraph(obj.code()->root()) + yulStack.dialect(), + CallGraphGenerator::callGraph(yulStack.parserResult()->code()->root()) ); std::map functionSideEffectsStr; @@ -101,7 +102,7 @@ TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string { auto const& functionNameStr = std::visit(GenericVisitor{ [](YulName const& _name) { return _name.str(); }, - [&](BuiltinHandle const& _builtin) { return dialect.builtin(_builtin).name; } + [&](BuiltinHandle const& _builtin) { return yulStack.dialect().builtin(_builtin).name; } }, fun.first); functionSideEffectsStr[functionNameStr] = toString(fun.second); } diff --git a/test/libyul/FunctionSideEffects.h b/test/libyul/FunctionSideEffects.h index ac0653733..3490c854a 100644 --- a/test/libyul/FunctionSideEffects.h +++ b/test/libyul/FunctionSideEffects.h @@ -18,7 +18,6 @@ #pragma once -#include #include #include diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index eefeb9010..6e75442f0 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -20,9 +20,12 @@ #include +#include + #include #include +#include #include #include #include @@ -30,8 +33,6 @@ #include #include -#include - #include using namespace solidity::langutil; @@ -44,27 +45,28 @@ class KnowledgeBaseTest protected: KnowledgeBase constructKnowledgeBase(std::string const& _source) { - ErrorList errorList; - std::shared_ptr analysisInfo; - std::tie(m_object, analysisInfo) = yul::test::parse(_source, m_dialect, errorList); - BOOST_REQUIRE(m_object && errorList.empty() && m_object->hasCode()); + YulStack yulStack = parseYul(_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + soltestAssert(!yulStack.hasErrors()); + m_object = yulStack.parserResult(); auto astRoot = std::get(yul::ASTCopier{}(m_object->code()->root())); - NameDispenser dispenser(m_dialect, astRoot); + NameDispenser dispenser(*m_object->dialect(), astRoot); std::set reserved; - OptimiserStepContext context{m_dialect, dispenser, reserved, 0}; + OptimiserStepContext context{*m_object->dialect(), dispenser, reserved, 0}; CommonSubexpressionEliminator::run(context, astRoot); m_ssaValues(astRoot); for (auto const& [name, expression]: m_ssaValues.values()) m_values[name].value = expression; - m_object->setCode(std::make_shared(m_dialect, std::move(astRoot))); - return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }, m_dialect); + m_object->setCode(std::make_shared(*m_object->dialect(), std::move(astRoot))); + return KnowledgeBase( + [this](YulName _var) { return util::valueOrNullptr(m_values, _var); }, + *m_object->dialect() + ); } - EVMDialect m_dialect{solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion(), true}; std::shared_ptr m_object; SSAValueTracker m_ssaValues; std::map m_values; diff --git a/test/libyul/Metrics.cpp b/test/libyul/Metrics.cpp index 5c7b5fc34..9e74cd150 100644 --- a/test/libyul/Metrics.cpp +++ b/test/libyul/Metrics.cpp @@ -20,11 +20,14 @@ #include +#include + #include #include #include #include +#include #include @@ -38,9 +41,10 @@ namespace size_t codeSize(std::string const& _source, CodeWeights const _weights = {}) { - std::shared_ptr ast = parse(_source).first; - BOOST_REQUIRE(ast); - return CodeSize::codeSize(ast->root(), _weights); + YulStack yulStack = parseYul(_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + soltestAssert(!yulStack.hasErrors()); + return CodeSize::codeSize(yulStack.parserResult()->code()->root(), _weights); } } diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp index d507aa333..f7d331d94 100644 --- a/test/libyul/ObjectCompilerTest.cpp +++ b/test/libyul/ObjectCompilerTest.cpp @@ -21,8 +21,7 @@ #include #include - -#include +#include #include @@ -31,11 +30,10 @@ #include #include -#include #include -#include +#include using namespace solidity; using namespace solidity::util; @@ -64,31 +62,23 @@ ObjectCompilerTest::ObjectCompilerTest(std::string const& _filename): TestCase::TestResult ObjectCompilerTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - YulStack stack( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, - OptimiserSettings::preset(m_optimisationPreset), - DebugInfoSelection::All() - ); - bool successful = stack.parseAndAnalyze("source", m_source); + YulStack yulStack = parseYul(m_source, "source", OptimiserSettings::preset(m_optimisationPreset)); MachineAssemblyObject obj; - if (successful) + if (!yulStack.hasErrors()) { - stack.optimize(); - obj = stack.assemble(YulStack::Machine::EVM); + yulStack.optimize(); + obj = yulStack.assemble(YulStack::Machine::EVM); } - if (stack.hasErrors()) + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; - SourceReferenceFormatter{_stream, stack, true, false} - .printErrorInformation(stack.errors()); + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } + solAssert(obj.bytecode); solAssert(obj.sourceMappings); - m_obtainedResult = "Assembly:\n" + obj.assembly->assemblyString(stack.debugInfoSelection()); + m_obtainedResult = "Assembly:\n" + obj.assembly->assemblyString(yulStack.debugInfoSelection()); if (obj.bytecode->bytecode.empty()) m_obtainedResult += "-- empty bytecode --\n"; else diff --git a/test/libyul/ObjectCompilerTest.h b/test/libyul/ObjectCompilerTest.h index 3310d80b8..604ad0346 100644 --- a/test/libyul/ObjectCompilerTest.h +++ b/test/libyul/ObjectCompilerTest.h @@ -51,7 +51,6 @@ class ObjectCompilerTest: public solidity::frontend::test::EVMVersionRestrictedT TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: - bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); void disambiguate(); frontend::OptimisationPreset m_optimisationPreset; diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index 9a891be91..23d8aaa57 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -53,42 +54,14 @@ namespace solidity::yul::test namespace { -std::pair parse(std::string const& _source) -{ - YulStack asmStack( - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::none(), - DebugInfoSelection::All() - ); - bool success = asmStack.parseAndAnalyze("source", _source); - return {success, asmStack.errors()}; -} - std::optional parseAndReturnFirstError(std::string const& _source, bool _allowWarningsAndInfos = true) { - bool success; - ErrorList errors; - tie(success, errors) = parse(_source); - if (!success) - { - BOOST_REQUIRE_EQUAL(errors.size(), 1); - return *errors.front(); - } - else - { - // If success is true, there might still be an error in the assembly stage. - if (_allowWarningsAndInfos && !Error::containsErrors(errors)) - return {}; - else if (!errors.empty()) - { - if (!_allowWarningsAndInfos) - BOOST_CHECK_EQUAL(errors.size(), 1); - return *errors.front(); - } - } - return {}; + YulStack yulStack = parseYul(_source, "source", OptimiserSettings::none()); + if (!yulStack.hasErrorsWarningsOrInfos() || (!yulStack.hasErrors() && _allowWarningsAndInfos)) + return {}; + + BOOST_REQUIRE_EQUAL(yulStack.errors().size(), 1); + return *yulStack.errors().front(); } bool successParse(std::string const& _source, bool _allowWarningsAndInfos = true) diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/SSAControlFlowGraphTest.cpp index ad825cdf5..c23a2ca5f 100644 --- a/test/libyul/SSAControlFlowGraphTest.cpp +++ b/test/libyul/SSAControlFlowGraphTest.cpp @@ -25,8 +25,7 @@ #include #include - -#include +#include #ifdef ISOLTEST #include @@ -48,29 +47,25 @@ SSAControlFlowGraphTest::SSAControlFlowGraphTest(std::string const& _filename): { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect( - dialectName, - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + soltestAssert(dialectName == "evm"); // We only have one dialect now m_expectation = m_reader.simpleExpectations(); } TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - ErrorList errors; - auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); - if (!object || !analysisInfo || Error::containsErrors(errors)) + YulStack yulStack = parseYul(m_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } - auto info = AsmAnalyzer::analyzeStrictAssertCorrect(*object); std::unique_ptr controlFlow = SSAControlFlowGraphBuilder::build( - info, - *m_dialect, - object->code()->root() + *yulStack.parserResult()->analysisInfo, + yulStack.dialect(), + yulStack.parserResult()->code()->root() ); ControlFlowLiveness liveness(*controlFlow); m_obtainedResult = controlFlow->toDot(&liveness); diff --git a/test/libyul/SSAControlFlowGraphTest.h b/test/libyul/SSAControlFlowGraphTest.h index 13ca2027a..51dd3c86d 100644 --- a/test/libyul/SSAControlFlowGraphTest.h +++ b/test/libyul/SSAControlFlowGraphTest.h @@ -22,11 +22,7 @@ #include -namespace solidity::yul -{ -class Dialect; - -namespace test +namespace solidity::yul::test { class SSAControlFlowGraphTest: public solidity::frontend::test::TestCase @@ -35,8 +31,6 @@ class SSAControlFlowGraphTest: public solidity::frontend::test::TestCase static std::unique_ptr create(Config const& _config); explicit SSAControlFlowGraphTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; -private: - Dialect const* m_dialect = nullptr; }; -} + } diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index b41f7f21e..0db063740 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -26,9 +26,8 @@ #include #include #include -#include +#include -#include #include #include @@ -50,11 +49,7 @@ StackLayoutGeneratorTest::StackLayoutGeneratorTest(std::string const& _filename) { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect( - dialectName, - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + soltestAssert(dialectName == "evm"); // We only have one dialect now m_expectation = m_reader.simpleExpectations(); } @@ -220,26 +215,31 @@ class StackLayoutPrinter TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - ErrorList errors; - auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); - if (!object || !analysisInfo || Error::containsErrors(errors)) + YulStack yulStack = parseYul(m_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; } std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, object->code()->root()); + std::unique_ptr cfg = ControlFlowGraphBuilder::build( + *yulStack.parserResult()->analysisInfo, + yulStack.dialect(), + yulStack.parserResult()->code()->root() + ); bool simulateFunctionsWithJumps = true; - if (auto const* evmDialect = dynamic_cast(m_dialect)) + if (auto const* evmDialect = dynamic_cast(&yulStack.dialect())) simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); StackLayout stackLayout = StackLayoutGenerator::run(*cfg, simulateFunctionsWithJumps); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - StackLayoutPrinter printer{output, stackLayout, *m_dialect}; + StackLayoutPrinter printer{output, stackLayout, yulStack.dialect()}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/StackLayoutGeneratorTest.h b/test/libyul/StackLayoutGeneratorTest.h index e1c6dc7f9..c7259a02a 100644 --- a/test/libyul/StackLayoutGeneratorTest.h +++ b/test/libyul/StackLayoutGeneratorTest.h @@ -20,11 +20,7 @@ #include -namespace solidity::yul -{ -class Dialect; - -namespace test +namespace solidity::yul::test { class StackLayoutGeneratorTest: public frontend::test::EVMVersionRestrictedTestCase @@ -36,8 +32,6 @@ class StackLayoutGeneratorTest: public frontend::test::EVMVersionRestrictedTestC } explicit StackLayoutGeneratorTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; -private: - Dialect const* m_dialect = nullptr; }; -} + } diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index aa37e85af..70f54b86a 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -16,39 +16,32 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include -#include - -#include -#include +#include #include -#include #include #include #include +#include + using namespace solidity; using namespace solidity::util; using namespace solidity::langutil; +using namespace solidity::test; using namespace solidity::yul::test; +using namespace solidity::frontend; using namespace solidity::frontend::test; void SyntaxTest::parseAndAnalyze() { - if (m_sources.sources.size() != 1) - BOOST_THROW_EXCEPTION(std::runtime_error{"Expected only one source for yul test."}); - - std::string const& name = m_sources.sources.begin()->first; - std::string const& source = m_sources.sources.begin()->second; + solUnimplementedAssert(m_sources.sources.size() == 1, "Multi-source Yul tests are not supported."); + auto const& [sourceUnitName, source] = *m_sources.sources.begin(); - ErrorList errorList{}; - soltestAssert(m_dialect, ""); - // Silently ignoring the results. - yul::test::parse(source, *m_dialect, errorList); - for (auto const& error: errorList) + YulStack yulStack = parseYul(source); + for (auto const& error: yulStack.errors()) { int locationStart = -1; int locationEnd = -1; @@ -63,21 +56,16 @@ void SyntaxTest::parseAndAnalyze() error->type(), error->errorId(), errorMessage(*error), - name, + sourceUnitName, locationStart, locationEnd }); } - } SyntaxTest::SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVersion): CommonSyntaxTest(_filename, _evmVersion) { std::string dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect( - dialectName, - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + soltestAssert(dialectName == "evm"); // We only have one dialect now } diff --git a/test/libyul/SyntaxTest.h b/test/libyul/SyntaxTest.h index 27e59ee61..9aab3298e 100644 --- a/test/libyul/SyntaxTest.h +++ b/test/libyul/SyntaxTest.h @@ -19,7 +19,6 @@ #pragma once #include -#include namespace solidity::yul::test { @@ -37,9 +36,6 @@ class SyntaxTest: public solidity::test::CommonSyntaxTest ~SyntaxTest() override {} protected: void parseAndAnalyze() override; - -private: - Dialect const* m_dialect = nullptr; }; } diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index 25b348dfb..d97211b97 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -18,20 +18,18 @@ #include +#include + #include #include -#include #include #include #include #include #include -#include - -#include #include #include @@ -57,40 +55,23 @@ YulInterpreterTest::YulInterpreterTest(std::string const& _filename): TestCase::TestResult YulInterpreterTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - if (!parse(_stream, _linePrefix, _formatted)) + YulStack yulStack = parseYul(m_source, "", solidity::frontend::OptimiserSettings::none()); + + if (yulStack.hasErrors()) + { + printYulErrors(yulStack, _stream, _linePrefix, _formatted); return TestResult::FatalError; + } - m_obtainedResult = interpret(); + m_obtainedResult = interpret(yulStack.parserResult()); return checkResult(_stream, _linePrefix, _formatted); } -bool YulInterpreterTest::parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) +std::string YulInterpreterTest::interpret(std::shared_ptr const& _object) { - YulStack stack( - CommonOptions::get().evmVersion(), - CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, - OptimiserSettings::none(), - DebugInfoSelection::All() - ); - if (stack.parseAndAnalyze("", m_source)) - { - m_ast = stack.parserResult()->code(); - m_analysisInfo = stack.parserResult()->analysisInfo; - return true; - } - else - { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; - SourceReferenceFormatter{_stream, stack, true, false} - .printErrorInformation(stack.errors()); - return false; - } -} + solAssert(_object && _object->hasCode()); -std::string YulInterpreterTest::interpret() -{ InterpreterState state; state.maxTraceSize = 32; state.maxSteps = 512; @@ -99,8 +80,8 @@ std::string YulInterpreterTest::interpret() { Interpreter::run( state, - CommonOptions::get().evmDialect(), - m_ast->root(), + *_object->dialect(), + _object->code()->root(), /*disableExternalCalls=*/ !m_simulateExternalCallsToSelf, /*disableMemoryTracing=*/ false ); diff --git a/test/libyul/YulInterpreterTest.h b/test/libyul/YulInterpreterTest.h index d59159133..b4a21b69a 100644 --- a/test/libyul/YulInterpreterTest.h +++ b/test/libyul/YulInterpreterTest.h @@ -22,8 +22,7 @@ namespace solidity::yul { -struct AsmAnalysisInfo; -class AST; +class Object; } namespace solidity::yul::test @@ -42,11 +41,8 @@ class YulInterpreterTest: public solidity::frontend::test::EVMVersionRestrictedT TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: - bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); - std::string interpret(); + std::string interpret(std::shared_ptr const& _object); - std::shared_ptr m_ast; - std::shared_ptr m_analysisInfo; bool m_simulateExternalCallsToSelf = false; }; diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 03f05ffa2..1048fb468 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -56,24 +57,17 @@ YulOptimizerTest::YulOptimizerTest(std::string const& _filename): m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect( - dialectName, - solidity::test::CommonOptions::get().evmVersion(), - solidity::test::CommonOptions::get().eofVersion() - ); + soltestAssert(dialectName == "evm"); // We only have one dialect now m_expectation = m_reader.simpleExpectations(); } TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - std::tie(m_object, m_analysisInfo) = parse(_stream, _linePrefix, _formatted, m_source); + m_object = parse(_stream, _linePrefix, _formatted, m_source); if (!m_object) return TestResult::FatalError; - soltestAssert(m_dialect, "Dialect not set."); - - m_object->analysisInfo = m_analysisInfo; YulOptimizerTestCommon tester(m_object); tester.setStep(m_optimizerStep); @@ -91,7 +85,7 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co printedOptimizedObject = optimizedObject->toString(); // Re-parse new code for compilability - if (!std::get<0>(parse(_stream, _linePrefix, _formatted, printedOptimizedObject))) + if (!parse(_stream, _linePrefix, _formatted, printedOptimizedObject)) { util::AnsiColorized(_stream, _formatted, {util::formatting::BOLD, util::formatting::CYAN}) << _linePrefix << "Result after the optimiser:" << std::endl; @@ -104,25 +98,19 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co return checkResult(_stream, _linePrefix, _formatted); } -std::pair, std::shared_ptr> YulOptimizerTest::parse( +std::shared_ptr YulOptimizerTest::parse( std::ostream& _stream, std::string const& _linePrefix, bool const _formatted, std::string const& _source ) { - ErrorList errors; - soltestAssert(m_dialect, ""); - std::shared_ptr object; - std::shared_ptr analysisInfo; - std::tie(object, analysisInfo) = yul::test::parse(_source, *m_dialect, errors); - if (!object || !analysisInfo || Error::containsErrors(errors)) + YulStack yulStack = parseYul(_source); + if (yulStack.hasErrors()) { - AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; - CharStream charStream(_source, ""); - SourceReferenceFormatter{_stream, SingletonCharStreamProvider(charStream), true, false} - .printErrorInformation(errors); - return {}; + printYulErrors(yulStack, _stream, _linePrefix, _formatted); + return nullptr; } - return {std::move(object), std::move(analysisInfo)}; + + return yulStack.parserResult(); } diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 207a4b8ce..02fd6a0b2 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -48,16 +48,16 @@ class YulOptimizerTest: public solidity::frontend::test::EVMVersionRestrictedTes TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: - std::pair, std::shared_ptr> parse( - std::ostream& _stream, std::string const& _linePrefix, bool const _formatted, std::string const& _source + std::shared_ptr parse( + std::ostream& _stream, + std::string const& _linePrefix, + bool const _formatted, + std::string const& _source ); std::string m_optimizerStep; - Dialect const* m_dialect = nullptr; - std::shared_ptr m_object; - std::shared_ptr m_analysisInfo; }; } From 2ccf0df6162224f2910fde333ecb8f9ecb2bcaf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 7 Dec 2024 02:38:29 +0100 Subject: [PATCH 0555/1340] CompilerStack: Use location of the current contract as default location in post-analysis errors --- Changelog.md | 1 + libsolidity/interface/CompilerStack.cpp | 43 ++++++++++++++++--- libsolidity/interface/CompilerStack.h | 8 +++- libyul/YulStack.cpp | 3 ++ .../output.json | 9 ++++ .../operators/shifts/shr_unused.sol | 2 +- .../array/nested_calldata_storage.sol | 2 +- .../array/nested_calldata_storage2.sol | 2 +- .../constants/mod_div_rational.sol | 2 +- .../builtin/builtin_type_definition.sol | 2 +- .../syntaxTests/immutable/no_assignments.sol | 2 +- .../inline_array_fixed_types.sol | 2 +- .../inline_arrays/inline_array_rationals.sol | 2 +- .../303_fixed_type_int_conversion.sol | 2 +- ...304_fixed_type_rational_int_conversion.sol | 2 +- ...ixed_type_rational_fraction_conversion.sol | 2 +- .../307_rational_unary_minus_operation.sol | 2 +- .../312_leading_zero_rationals_convert.sol | 2 +- .../314_fixed_type_zero_handling.sol | 2 +- ..._fixed_type_valid_explicit_conversions.sol | 2 +- .../323_mapping_with_fixed_literal.sol | 2 +- .../324_fixed_points_inside_structs.sol | 2 +- ...8_rational_to_fixed_literal_expression.sol | 2 +- .../343_integer_and_fixed_interaction.sol | 2 +- .../declaring_fixed_and_ufixed_variables.sol | 2 +- .../lexer_numbers_with_underscores_fixed.sol | 2 +- ...ional_number_literal_to_fixed_implicit.sol | 2 +- 27 files changed, 77 insertions(+), 31 deletions(-) diff --git a/Changelog.md b/Changelog.md index 9aaa1ca8b..731640653 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * Error Reporting: Errors reported during code generation now point at the location of the contract when more fine-grained location is not available. * SMTChecker: Z3 is now a runtime dependency, not a build dependency (except for emscripten build). diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 9649b79c8..9d76ced02 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -779,11 +779,11 @@ bool CompilerStack::compile(State _stopAfter) } catch (Error const& _error) { - m_errorReporter.codeGenerationError(_error); + reportCodeGenerationError(_error, contract); } catch (UnimplementedFeatureError const& _error) { - reportUnimplementedFeatureError(_error); + reportUnimplementedFeatureError(_error, contract); } if (m_errorReporter.hasErrors()) @@ -1614,7 +1614,7 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) if (stack.hasErrors()) { for (std::shared_ptr const& error: stack.errors()) - reportIRPostAnalysisError(error.get()); + reportIRPostAnalysisError(error.get(), compiledContract.contract); return; } @@ -2010,18 +2010,47 @@ experimental::Analysis const& CompilerStack::experimentalAnalysis() const return *m_experimentalAnalysis; } -void CompilerStack::reportUnimplementedFeatureError(UnimplementedFeatureError const& _error) +void CompilerStack::reportUnimplementedFeatureError( + UnimplementedFeatureError const& _error, + ContractDefinition const* _contractDefinition +) { solAssert(_error.comment(), "Errors must include a message for the user."); + if (_error.sourceLocation().sourceName) + solAssert(m_sources.count(*_error.sourceLocation().sourceName) != 0); + + m_errorReporter.unimplementedFeatureError( + 1834_error, + (_error.sourceLocation().sourceName || !_contractDefinition) ? + _error.sourceLocation() : + _contractDefinition->location(), + *_error.comment() + ); +} - m_errorReporter.unimplementedFeatureError(1834_error, _error.sourceLocation(), *_error.comment()); +void CompilerStack::reportCodeGenerationError(Error const& _error, ContractDefinition const* _contractDefinition) +{ + solAssert(_error.type() == Error::Type::CodeGenerationError); + solAssert(_error.comment(), "Errors must include a message for the user."); + if (_error.sourceLocation() && _error.sourceLocation()->sourceName) + solAssert(m_sources.count(*_error.sourceLocation()->sourceName) != 0); + solAssert(_contractDefinition); + + m_errorReporter.codeGenerationError( + _error.errorId(), + (_error.sourceLocation() && _error.sourceLocation()->sourceName) ? + *_error.sourceLocation() : + _contractDefinition->location(), + *_error.comment() + ); } -void CompilerStack::reportIRPostAnalysisError(Error const* _error) +void CompilerStack::reportIRPostAnalysisError(Error const* _error, ContractDefinition const* _contractDefinition) { solAssert(_error); solAssert(_error->comment(), "Errors must include a message for the user."); solAssert(!_error->secondarySourceLocation()); + solAssert(_contractDefinition); // Do not report Yul warnings and infos. These are only reported in pure Yul compilation. if (!Error::isError(_error->severity())) @@ -2032,7 +2061,7 @@ void CompilerStack::reportIRPostAnalysisError(Error const* _error) _error->type(), // Ignore the original location. It's likely missing, but even if not, it points at Yul source. // CompilerStack can only point at locations in Solidity sources. - SourceLocation{}, + _contractDefinition->location(), *_error->comment() ); } diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 81a039403..f36eedde0 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -578,8 +578,12 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac FunctionDefinition const& _function ) const; - void reportUnimplementedFeatureError(langutil::UnimplementedFeatureError const& _error); - void reportIRPostAnalysisError(langutil::Error const* _error); + void reportUnimplementedFeatureError( + langutil::UnimplementedFeatureError const& _error, + ContractDefinition const* _contractDefinition = nullptr + ); + void reportCodeGenerationError(langutil::Error const& _error, ContractDefinition const* _contractDefinition); + void reportIRPostAnalysisError(langutil::Error const* _error, ContractDefinition const* _contractDefinition); ReadCallback::Callback m_readFile; OptimiserSettings m_optimiserSettings; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 791b7103d..03e22c8d1 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -439,6 +439,9 @@ Dialect const& YulStack::dialect() const void YulStack::reportUnimplementedFeatureError(UnimplementedFeatureError const& _error) { + yulAssert(m_charStream); yulAssert(_error.comment(), "Errors must include a message for the user."); + if (_error.sourceLocation().sourceName) + yulAssert(*_error.sourceLocation().sourceName == m_charStream->name()); m_errorReporter.unimplementedFeatureError(1920_error, _error.sourceLocation(), *_error.comment()); } diff --git a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json index e0f4e37e6..0fa7fcff3 100644 --- a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json +++ b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json @@ -54,10 +54,19 @@ "component": "general", "errorCode": "1284", "formattedMessage": "CodeGenerationError: Some immutables were read from but never assigned, possibly because of optimization. + --> C:4:1: + | +4 | contract C { + | ^ (Relevant source part starts here and spans across multiple lines). ", "message": "Some immutables were read from but never assigned, possibly because of optimization.", "severity": "error", + "sourceLocation": { + "end": 320, + "file": "C", + "start": 56 + }, "type": "CodeGenerationError" } ], diff --git a/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol b/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol index 504381758..2134068db 100644 --- a/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol +++ b/test/libsolidity/smtCheckerTests/operators/shifts/shr_unused.sol @@ -8,4 +8,4 @@ contract C { // SMTEngine: all // ---- // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-80): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol b/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol index 18bf550c0..9aa5fce12 100644 --- a/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol +++ b/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol @@ -6,4 +6,4 @@ contract C { } // ---- -// UnimplementedFeatureError 1834: Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. +// UnimplementedFeatureError 1834: (35-127): Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. diff --git a/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol b/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol index 9f5bb8eab..f1125b4d2 100644 --- a/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol +++ b/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol @@ -6,4 +6,4 @@ contract C { } // ---- -// UnimplementedFeatureError 1834: Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. +// UnimplementedFeatureError 1834: (35-125): Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. diff --git a/test/libsolidity/syntaxTests/constants/mod_div_rational.sol b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol index 5c127eb4a..68d3bfc7a 100644 --- a/test/libsolidity/syntaxTests/constants/mod_div_rational.sol +++ b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol @@ -5,4 +5,4 @@ contract C { fixed a4 = 0 / -0.123; } // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-150): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol index ed7db1ec6..858b9132d 100644 --- a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol +++ b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol @@ -89,4 +89,4 @@ contract C { // Info 4164: (563-574): Inferred type: (bool, word) -> word // Info 4164: (563-567): Inferred type: (?bm:type, ?bn:type) // Info 4164: (575-576): Inferred type: (bool, word) -// UnimplementedFeatureError 1834: No support for calling functions pointers yet. +// UnimplementedFeatureError 1834: (267-586): No support for calling functions pointers yet. diff --git a/test/libsolidity/syntaxTests/immutable/no_assignments.sol b/test/libsolidity/syntaxTests/immutable/no_assignments.sol index 7357d174a..7d7948671 100644 --- a/test/libsolidity/syntaxTests/immutable/no_assignments.sol +++ b/test/libsolidity/syntaxTests/immutable/no_assignments.sol @@ -10,4 +10,4 @@ contract C { // ==== // optimize-yul: true // ---- -// CodeGenerationError 1284: Some immutables were read from but never assigned, possibly because of optimization. +// CodeGenerationError 1284: (0-168): Some immutables were read from but never assigned, possibly because of optimization. diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol index 604f9b029..8e51bd188 100644 --- a/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol @@ -6,4 +6,4 @@ contract test { // ---- // Warning 2072: (50-67): Unused local variable. // Warning 2018: (20-119): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-121): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol index 63df5c044..0382672fe 100644 --- a/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol @@ -6,4 +6,4 @@ contract test { // ---- // Warning 2072: (50-73): Unused local variable. // Warning 2018: (20-118): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-120): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol index 58c74b9ad..88a407fef 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol @@ -9,4 +9,4 @@ contract test { } // ---- // Warning 2018: (20-147): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-149): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol index 404cbc4bc..0e3cb3b6c 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol @@ -7,4 +7,4 @@ contract test { } // ---- // Warning 2018: (20-104): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-106): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol index b113c6bcc..ada627037 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol @@ -7,4 +7,4 @@ contract test { } // ---- // Warning 2018: (20-108): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-110): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol index e80024a98..adb9fbe69 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol @@ -6,4 +6,4 @@ contract test { } } // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-126): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol index 20be0208c..e763fa18b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol @@ -8,4 +8,4 @@ contract A { } } // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-289): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol index 7415ed6e8..b9205f01b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol @@ -6,4 +6,4 @@ contract test { } // ---- // Warning 2018: (20-104): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-106): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol index fa32ec7dd..1282c24da 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol @@ -7,4 +7,4 @@ contract test { } // ---- // Warning 2018: (20-182): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-184): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol index cb730221d..3ee670cd5 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol @@ -5,4 +5,4 @@ contract test { } } // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-130): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol index 9bc624302..ba467a67b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol @@ -6,4 +6,4 @@ contract test { myStruct a = myStruct(3.125, 3); } // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-115): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol index 8391734ae..b5162bcd9 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol @@ -13,4 +13,4 @@ contract test { // ---- // Warning 2519: (238-252): This declaration shadows an existing declaration. // Warning 2018: (20-339): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-341): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol index 15ca25931..3ebd54d45 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol @@ -6,4 +6,4 @@ contract test { // ---- // Warning 2072: (50-58): Unused local variable. // Warning 2018: (20-89): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-91): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol b/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol index ea41bbf3e..2518a4b57 100644 --- a/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol +++ b/test/libsolidity/syntaxTests/parsing/declaring_fixed_and_ufixed_variables.sol @@ -11,4 +11,4 @@ contract A { // Warning 2072: (93-104): Unused local variable. // Warning 2072: (114-121): Unused local variable. // Warning 2018: (41-128): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: Fixed point types not implemented. +// UnimplementedFeatureError 1834: (0-130): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol index 9932c4c3d..9346264ed 100644 --- a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-109): Not yet implemented - FixedPointType. diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol index a93555fd7..e62728770 100644 --- a/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol +++ b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol @@ -13,4 +13,4 @@ contract C { } } // ---- -// UnimplementedFeatureError 1834: Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (0-317): Not yet implemented - FixedPointType. From 682d2c617177fe082544b5a93f6520ee6aa2b537 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 2 Dec 2024 11:37:23 +0100 Subject: [PATCH 0556/1340] Prune unreferenced functions from CFG --- .../backends/evm/ControlFlowGraphBuilder.cpp | 27 ++++++++++++-- ...une_unreachable_function_non_returning.yul | 29 +++++++++++++++ .../prune_unreachable_function_recursion.yul | 26 ++++++++++++++ .../eof/prune_unreferenced_function.yul | 33 +++++++++++++++++ ...une_unreachable_function_non_returning.yul | 29 +++++++++++++++ .../prune_unreachable_function_recursion.yul | 27 ++++++++++++++ .../prune_unreferenced_function.yul | 35 +++++++++++++++++++ 7 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 test/libyul/objectCompiler/eof/prune_unreachable_function_non_returning.yul create mode 100644 test/libyul/objectCompiler/eof/prune_unreachable_function_recursion.yul create mode 100644 test/libyul/objectCompiler/eof/prune_unreferenced_function.yul create mode 100644 test/libyul/objectCompiler/prune_unreachable_function_non_returning.yul create mode 100644 test/libyul/objectCompiler/prune_unreachable_function_recursion.yul create mode 100644 test/libyul/objectCompiler/prune_unreferenced_function.yul diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index cce5c9855..3986d54a0 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -52,12 +52,23 @@ namespace /// Removes edges to blocks that are not reachable. void cleanUnreachable(CFG& _cfg) { + // If operation is a function call it adds the callee entry as child + auto const addFunctionsEntries = [&_cfg](CFG::BasicBlock* _node, auto&& _addChild) + { + for (auto const& operation: _node->operations) + { + if (auto const* functionCall = std::get_if(&operation.operation)) + { + auto const functionInfo = _cfg.functionInfo.at(&(functionCall->function.get())); + _addChild(functionInfo.entry); + } + } + }; + // Determine which blocks are reachable from the entry. util::BreadthFirstSearch reachabilityCheck{{_cfg.entry}}; - for (auto const& functionInfo: _cfg.functionInfo | ranges::views::values) - reachabilityCheck.verticesToTraverse.emplace_back(functionInfo.entry); - reachabilityCheck.run([&](CFG::BasicBlock* _node, auto&& _addChild) { + addFunctionsEntries(_node, _addChild); visit(util::GenericVisitor{ [&](CFG::BasicBlock::Jump const& _jump) { _addChild(_jump.target); @@ -77,6 +88,16 @@ void cleanUnreachable(CFG& _cfg) cxx20::erase_if(node->entries, [&](CFG::BasicBlock* entry) -> bool { return !reachabilityCheck.visited.count(entry); }); + + // Remove functions which are never referenced. + _cfg.functions.erase(std::remove_if(_cfg.functions.begin(), _cfg.functions.end(), [&](auto const& item) { + return !reachabilityCheck.visited.count(_cfg.functionInfo.at(item).entry); + }), _cfg.functions.end()); + + // Remove functionInfos which are never referenced. + cxx20::erase_if(_cfg.functionInfo, [&](auto const& entry) -> bool { + return !reachabilityCheck.visited.count(entry.second.entry); + }); } /// Sets the ``recursive`` member to ``true`` for all recursive function calls. diff --git a/test/libyul/objectCompiler/eof/prune_unreachable_function_non_returning.yul b/test/libyul/objectCompiler/eof/prune_unreachable_function_non_returning.yul new file mode 100644 index 000000000..c1ed84ca4 --- /dev/null +++ b/test/libyul/objectCompiler/eof/prune_unreachable_function_non_returning.yul @@ -0,0 +1,29 @@ +object "Contract" { + code { + f() + g() + + function f() { revert(0, 0) } + function g() { mstore(0, 2) } + } +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":53:56 */ +// jumpf{code_section_1} +// +// code_section_1: assembly { +// /* "source":124:125 */ +// 0x00 +// /* "source":114:126 */ +// dup1 +// revert +// } +// Bytecode: ef000101000802000200030003040000000080ffff0080ffffe500015f80fd +// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP SUB STOP SUB DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP DUP1 SELFDESTRUCT SELFDESTRUCT JUMPF 0x1 PUSH0 DUP1 REVERT +// SourceMappings: 53:3:0:i:0124:1:0:-:0;114:12; diff --git a/test/libyul/objectCompiler/eof/prune_unreachable_function_recursion.yul b/test/libyul/objectCompiler/eof/prune_unreachable_function_recursion.yul new file mode 100644 index 000000000..f3869c9ad --- /dev/null +++ b/test/libyul/objectCompiler/eof/prune_unreachable_function_recursion.yul @@ -0,0 +1,26 @@ +object "Contract" { + code { + f() + g() + + function f() { f() } + function g() { mstore(0, 2) } + } +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":53:56 */ +// jumpf{code_section_1} +// +// code_section_1: assembly { +// /* "source":114:117 */ +// jumpf{code_section_1} +// } +// Bytecode: ef000101000802000200030003040000000080ffff0080ffffe50001e50001 +// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP SUB STOP SUB DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP DUP1 SELFDESTRUCT SELFDESTRUCT JUMPF 0x1 JUMPF 0x1 +// SourceMappings: 53:3:0:i:0114:3:0:i:0 diff --git a/test/libyul/objectCompiler/eof/prune_unreferenced_function.yul b/test/libyul/objectCompiler/eof/prune_unreferenced_function.yul new file mode 100644 index 000000000..610c9a458 --- /dev/null +++ b/test/libyul/objectCompiler/eof/prune_unreferenced_function.yul @@ -0,0 +1,33 @@ +object "Contract" { + code { + g() + + function f() { mstore(0, 3) } + function g() { mstore(0, 2) } + } +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":41:44 */ +// callf{code_section_1} +// /* "source":29:98 */ +// stop +// +// code_section_1: assembly { +// /* "source":88:89 */ +// 0x02 +// /* "source":85:86 */ +// 0x00 +// /* "source":78:90 */ +// mstore +// /* "source":55:92 */ +// retf +// } +// Bytecode: ef000101000802000200040005040000000080ffff0000ffffe300010060025f52e4 +// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP DIV STOP SDIV DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP STOP SELFDESTRUCT SELFDESTRUCT CALLF 0x1 STOP PUSH1 0x2 PUSH0 MSTORE RETF +// SourceMappings: 41:3:0:i:0;29:69::-88:1:0:-:0;85;78:12;55:37::o diff --git a/test/libyul/objectCompiler/prune_unreachable_function_non_returning.yul b/test/libyul/objectCompiler/prune_unreachable_function_non_returning.yul new file mode 100644 index 000000000..9c0a0acdc --- /dev/null +++ b/test/libyul/objectCompiler/prune_unreachable_function_non_returning.yul @@ -0,0 +1,29 @@ +object "Contract" { + code { + f() + g() + + function f() { revert(0, 0) } + function g() { mstore(0, 2) } + } +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":53:56 */ +// tag_1 +// jump // in +// /* "source":91:128 */ +// tag_1: +// /* "source":124:125 */ +// 0x00 +// /* "source":114:126 */ +// dup1 +// revert +// Bytecode: 6003565b5f80fd +// Opcodes: PUSH1 0x3 JUMP JUMPDEST PUSH0 DUP1 REVERT +// SourceMappings: 53:3:0:-:0;:::i;91:37::-;124:1;114:12; diff --git a/test/libyul/objectCompiler/prune_unreachable_function_recursion.yul b/test/libyul/objectCompiler/prune_unreachable_function_recursion.yul new file mode 100644 index 000000000..1000cfd31 --- /dev/null +++ b/test/libyul/objectCompiler/prune_unreachable_function_recursion.yul @@ -0,0 +1,27 @@ +object "Contract" { + code { + f() + g() + + function f() { f() } + function g() { mstore(0, 2) } + } +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":53:56 */ +// tag_1 +// jump // in +// /* "source":91:119 */ +// tag_1: +// /* "source":114:117 */ +// tag_1 +// jump // in +// Bytecode: 6003565b600356 +// Opcodes: PUSH1 0x3 JUMP JUMPDEST PUSH1 0x3 JUMP +// SourceMappings: 53:3:0:-:0;:::i;91:28::-;114:3;:::i diff --git a/test/libyul/objectCompiler/prune_unreferenced_function.yul b/test/libyul/objectCompiler/prune_unreferenced_function.yul new file mode 100644 index 000000000..88010bd72 --- /dev/null +++ b/test/libyul/objectCompiler/prune_unreferenced_function.yul @@ -0,0 +1,35 @@ +object "Contract" { + code { + g() + + function f() { mstore(0, 3) } + function g() { mstore(0, 2) } + } +} + +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: legacy +// optimizationPreset: none +// ---- +// Assembly: +// /* "source":41:44 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "source":29:98 */ +// stop +// /* "source":55:92 */ +// tag_1: +// /* "source":88:89 */ +// 0x02 +// /* "source":85:86 */ +// 0x00 +// /* "source":78:90 */ +// mstore +// /* "source":55:92 */ +// jump // out +// Bytecode: 60056007565b005b60025f5256 +// Opcodes: PUSH1 0x5 PUSH1 0x7 JUMP JUMPDEST STOP JUMPDEST PUSH1 0x2 PUSH0 MSTORE JUMP +// SourceMappings: 41:3:0:-:0;;:::i;:::-;29:69;55:37;88:1;85;78:12;55:37::o From bbb6a116e3c2732c7e5201d02387928a9fa983aa Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 16 Dec 2024 12:20:48 +0100 Subject: [PATCH 0557/1340] Update tests expectations --- .../stackReuse/function_argument_reuse.yul | 15 ++++++++- ...ction_argument_reuse_without_retparams.yul | 23 +++++++++---- .../stackReuse/function_many_arguments.yul | 33 ++++++++++++++++++- .../stackReuse/function_params.yul | 13 +++++++- .../function_params_and_retparams.yul | 15 ++++++++- ...ction_params_and_retparams_partly_used.yul | 15 ++++++++- .../stackReuse/function_retparam.yul | 9 ++++- .../stackReuse/function_retparam_block.yul | 11 ++++++- .../function_retparam_declaration.yul | 11 ++++++- .../stackReuse/function_retparam_for.yul | 11 ++++++- .../stackReuse/function_retparam_if.yul | 19 ++++++++--- .../stackReuse/function_retparam_leave.yul | 11 ++++++- .../stackReuse/function_retparam_read.yul | 11 ++++++- .../function_retparam_unassigned.yul | 11 ++++++- .../function_retparam_unassigned_multiple.yul | 9 ++++- .../stackReuse/function_trivial.yul | 13 ++++++-- .../function_with_body_embedded.yul | 16 ++++++++- .../unassigned_return_variable.yul | 10 ++++-- ...une_unreachable_function_non_returning.yul | 4 +-- .../prune_unreachable_function_recursion.yul | 5 ++- .../eof/prune_unreferenced_function.yul | 4 +-- .../leading_and_trailing_dots.yul | 20 ++--------- test/libyul/yulControlFlowGraph/function.yul | 26 +++++---------- test/libyul/yulStackLayout/function.yul | 31 ++++++----------- 24 files changed, 254 insertions(+), 92 deletions(-) diff --git a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul index 96637da89..515765ad2 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse.yul @@ -1,10 +1,23 @@ { function f(a, b, c) -> x { pop(address()) sstore(a, c) pop(callvalue()) x := b } + pop(f(0, 0, 0)) } // ==== // stackOptimization: true // ---- -// /* "":0:88 */ +// /* "":95:105 */ +// tag_2 +// /* "":103:104 */ +// 0x00 +// /* "":95:105 */ +// dup1 +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":91:106 */ +// pop +// /* "":0:108 */ // stop // /* "":6:86 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul index b5cc61187..09ce0b84a 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul @@ -3,12 +3,23 @@ mstore(0x80, x) if calldataload(0) { sstore(y, y) } } + + f(0, 0) } // ==== -// stackOptimization: true // EVMVersion: >=shanghai +// stackOptimization: true // ---- -// /* "":0:88 */ +// /* "":90:97 */ +// tag_2 +// /* "":95:96 */ +// 0x00 +// /* "":90:97 */ +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":0:99 */ // stop // /* "":4:86 */ // tag_1: @@ -21,18 +32,18 @@ // /* "":50:65 */ // calldataload // /* "":47:82 */ -// tag_2 +// tag_3 // jumpi // /* "":21:86 */ -// tag_3: +// tag_4: // /* "":4:86 */ // pop // jump // out // /* "":66:82 */ -// tag_2: +// tag_3: // /* "":68:80 */ // dup1 // sstore // /* "":66:82 */ // 0x00 -// jump(tag_3) +// jump(tag_4) diff --git a/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul b/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul index 17ccdd3ca..e78cda9cb 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_many_arguments.yul @@ -21,11 +21,42 @@ mstore(0x0340, a19) x := a20 } + + pop(f(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) } // ==== // stackOptimization: true // ---- -// /* "":0:662 */ +// /* "":670:731 */ +// tag_2 +// /* "":729:730 */ +// 0x00 +// /* "":670:731 */ +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":666:732 */ +// pop +// /* "":0:734 */ // stop // /* "":6:660 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_params.yul b/test/libyul/evmCodeTransform/stackReuse/function_params.yul index e8d9bb30c..dda389524 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_params.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_params.yul @@ -1,10 +1,21 @@ { function f(a, b) { } + + f(0, 0) } // ==== // stackOptimization: true // ---- -// /* "":0:28 */ +// /* "":32:39 */ +// tag_2 +// /* "":37:38 */ +// 0x00 +// /* "":32:39 */ +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":0:41 */ // stop // /* "":6:26 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul index 1d157663a..bf6ed9f14 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams.yul @@ -4,11 +4,24 @@ // can be reused. { function f(a, b, c, d) -> x, y { } + + let x, y := f(0, 0, 0, 0) } // ==== // stackOptimization: true // ---- -// /* "":210:252 */ +// /* "":268:281 */ +// tag_2 +// /* "":279:280 */ +// 0x00 +// /* "":268:281 */ +// dup1 +// dup1 +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":210:283 */ // stop // /* "":216:250 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul index d0fc0506f..cf38dc0b4 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_params_and_retparams_partly_used.yul @@ -1,10 +1,23 @@ { function f(a, b, c, d) -> x, y { b := 3 let s := 9 y := 2 mstore(s, y) } + + let x, y := f(0, 0, 0, 0) } // ==== // stackOptimization: true // ---- -// /* "":0:80 */ +// /* "":97:110 */ +// tag_2 +// /* "":108:109 */ +// 0x00 +// /* "":97:110 */ +// dup1 +// dup1 +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":0:112 */ // stop // /* "":6:78 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul index bee0d3f63..eb912cbe2 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam.yul @@ -1,10 +1,17 @@ { function f() -> x, y { } + + let x, y := f() } // ==== // stackOptimization: true // ---- -// /* "":0:32 */ +// /* "":49:52 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":0:54 */ // stop // /* "":6:30 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul index 5a9e7704e..42186ca69 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_block.yul @@ -1,10 +1,19 @@ { function f() -> x { pop(address()) { pop(callvalue()) } } + + pop(f()) } // ==== // stackOptimization: true // ---- -// /* "":0:65 */ +// /* "":74:77 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":70:78 */ +// pop +// /* "":0:80 */ // stop // /* "":6:63 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul index 97bffac38..402555e2d 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_declaration.yul @@ -1,10 +1,19 @@ { function f() -> x { pop(address()) let y := callvalue() } + + pop(f()) } // ==== // stackOptimization: true // ---- -// /* "":0:65 */ +// /* "":74:77 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":70:78 */ +// pop +// /* "":0:80 */ // stop // /* "":6:63 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul index c18fb7c37..583173222 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_for.yul @@ -1,10 +1,19 @@ { function f() -> x { pop(address()) for { pop(callvalue()) } 0 {} { } } + + pop(f()) } // ==== // stackOptimization: true // ---- -// /* "":0:78 */ +// /* "":86:89 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":82:90 */ +// pop +// /* "":0:92 */ // stop // /* "":6:76 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul index 08dda5a3b..6a53eab99 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_if.yul @@ -1,10 +1,19 @@ { function f() -> x { pop(address()) if 1 { pop(callvalue()) } } + + pop(f()) } // ==== // stackOptimization: true // ---- -// /* "":0:70 */ +// /* "":78:81 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":74:82 */ +// pop +// /* "":0:84 */ // stop // /* "":6:68 */ // tag_1: @@ -19,17 +28,17 @@ // /* "":26:40 */ // pop // /* "":41:66 */ -// tag_2 +// tag_3 // jumpi // /* "":24:68 */ -// tag_3: +// tag_4: // /* "":6:68 */ // jump // out // /* "":46:66 */ -// tag_2: +// tag_3: // /* "":52:63 */ // callvalue // /* "":48:64 */ // pop // /* "":46:66 */ -// jump(tag_3) +// jump(tag_4) diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul index 9ac0c00bf..ecaf79f76 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_leave.yul @@ -1,10 +1,19 @@ { function f() -> x { pop(address()) leave pop(callvalue()) } + + pop(f()) } // ==== // stackOptimization: true // ---- -// /* "":0:67 */ +// /* "":75:78 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":71:79 */ +// pop +// /* "":0:81 */ // stop // /* "":6:65 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul index fcc8278e6..4fe4dcd4e 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_read.yul @@ -1,10 +1,19 @@ { function f() -> x { pop(address()) sstore(0, x) pop(callvalue()) } + + pop(f()) } // ==== // stackOptimization: true // ---- -// /* "":0:74 */ +// /* "":82:85 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":78:86 */ +// pop +// /* "":0:88 */ // stop // /* "":6:72 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul index 1cc19a464..977f8c9d6 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned.yul @@ -1,10 +1,19 @@ { function f() -> x { pop(callvalue()) } + + pop(f()) } // ==== // stackOptimization: true // ---- -// /* "":0:46 */ +// /* "":54:57 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":50:58 */ +// pop +// /* "":0:60 */ // stop // /* "":6:44 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul index e44e3b437..7d3d96057 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_retparam_unassigned_multiple.yul @@ -1,10 +1,17 @@ { function f() -> x, y, z { pop(callvalue()) } + + let x, y, z := f() } // ==== // stackOptimization: true // ---- -// /* "":0:52 */ +// /* "":71:74 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":0:76 */ // stop // /* "":6:50 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul b/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul index 3d6286efd..ad5098af7 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_trivial.yul @@ -1,11 +1,18 @@ { - function f() { } + function f() { } + + f() } // ==== // stackOptimization: true // ---- -// /* "":0:22 */ +// /* "":28:31 */ +// tag_2 +// tag_1 +// jump // in +// tag_2: +// /* "":0:33 */ // stop -// /* "":4:20 */ +// /* "":6:22 */ // tag_1: // jump // out diff --git a/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul b/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul index f8480bc91..20651dd49 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_with_body_embedded.yul @@ -5,6 +5,8 @@ let x := a a := 3 t := a } b := 7 + + pop(f(0, 0)) } // ==== // stackOptimization: true @@ -15,7 +17,19 @@ // pop // /* "":182:183 */ // 0x07 -// /* "":0:185 */ +// /* "":193:200 */ +// pop +// tag_2 +// /* "":198:199 */ +// 0x00 +// /* "":193:200 */ +// dup1 +// tag_1 +// jump // in +// tag_2: +// /* "":189:201 */ +// pop +// /* "":0:203 */ // stop // /* "":21:172 */ // tag_1: diff --git a/test/libyul/evmCodeTransform/unassigned_return_variable.yul b/test/libyul/evmCodeTransform/unassigned_return_variable.yul index 666fefe1a..e0ff7eddf 100644 --- a/test/libyul/evmCodeTransform/unassigned_return_variable.yul +++ b/test/libyul/evmCodeTransform/unassigned_return_variable.yul @@ -3,12 +3,18 @@ function g(b,s) -> y { y := g(b, g(y, s)) } + + pop(g(0,0)) } // ==== // stackOptimization: true // ---- -// /* "":0:111 */ -// stop +// /* "":121:122 */ +// 0x00 +// /* "":117:123 */ +// dup1 +// tag_1 +// jump // in // /* "":60:109 */ // tag_1: // pop diff --git a/test/libyul/objectCompiler/eof/prune_unreachable_function_non_returning.yul b/test/libyul/objectCompiler/eof/prune_unreachable_function_non_returning.yul index c1ed84ca4..f4792619f 100644 --- a/test/libyul/objectCompiler/eof/prune_unreachable_function_non_returning.yul +++ b/test/libyul/objectCompiler/eof/prune_unreachable_function_non_returning.yul @@ -24,6 +24,6 @@ object "Contract" { // dup1 // revert // } -// Bytecode: ef000101000802000200030003040000000080ffff0080ffffe500015f80fd -// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP SUB STOP SUB DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP DUP1 SELFDESTRUCT SELFDESTRUCT JUMPF 0x1 PUSH0 DUP1 REVERT +// Bytecode: ef000101000802000200030003040000000080000000800002e500015f80fd +// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP SUB STOP SUB DIV STOP STOP STOP STOP DUP1 STOP STOP STOP DUP1 STOP MUL JUMPF 0x1 PUSH0 DUP1 REVERT // SourceMappings: 53:3:0:i:0124:1:0:-:0;114:12; diff --git a/test/libyul/objectCompiler/eof/prune_unreachable_function_recursion.yul b/test/libyul/objectCompiler/eof/prune_unreachable_function_recursion.yul index f3869c9ad..0276b4cad 100644 --- a/test/libyul/objectCompiler/eof/prune_unreachable_function_recursion.yul +++ b/test/libyul/objectCompiler/eof/prune_unreachable_function_recursion.yul @@ -9,7 +9,6 @@ object "Contract" { } // ==== -// EVMVersion: >=shanghai // bytecodeFormat: >=EOFv1 // optimizationPreset: none // ---- @@ -21,6 +20,6 @@ object "Contract" { // /* "source":114:117 */ // jumpf{code_section_1} // } -// Bytecode: ef000101000802000200030003040000000080ffff0080ffffe50001e50001 -// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP SUB STOP SUB DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP DUP1 SELFDESTRUCT SELFDESTRUCT JUMPF 0x1 JUMPF 0x1 +// Bytecode: ef000101000802000200030003040000000080000000800000e50001e50001 +// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP SUB STOP SUB DIV STOP STOP STOP STOP DUP1 STOP STOP STOP DUP1 STOP STOP JUMPF 0x1 JUMPF 0x1 // SourceMappings: 53:3:0:i:0114:3:0:i:0 diff --git a/test/libyul/objectCompiler/eof/prune_unreferenced_function.yul b/test/libyul/objectCompiler/eof/prune_unreferenced_function.yul index 610c9a458..8cbb294cd 100644 --- a/test/libyul/objectCompiler/eof/prune_unreferenced_function.yul +++ b/test/libyul/objectCompiler/eof/prune_unreferenced_function.yul @@ -28,6 +28,6 @@ object "Contract" { // /* "source":55:92 */ // retf // } -// Bytecode: ef000101000802000200040005040000000080ffff0000ffffe300010060025f52e4 -// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP DIV STOP SDIV DIV STOP STOP STOP STOP DUP1 SELFDESTRUCT SELFDESTRUCT STOP STOP SELFDESTRUCT SELFDESTRUCT CALLF 0x1 STOP PUSH1 0x2 PUSH0 MSTORE RETF +// Bytecode: ef000101000802000200040005040000000080000000000002e300010060025f52e4 +// Opcodes: 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP DIV STOP SDIV DIV STOP STOP STOP STOP DUP1 STOP STOP STOP STOP STOP MUL CALLF 0x1 STOP PUSH1 0x2 PUSH0 MSTORE RETF // SourceMappings: 41:3:0:i:0;29:69::-88:1:0:-:0;85;78:12;55:37::o diff --git a/test/libyul/objectCompiler/leading_and_trailing_dots.yul b/test/libyul/objectCompiler/leading_and_trailing_dots.yul index 9d32cadc0..ddacd8b45 100644 --- a/test/libyul/objectCompiler/leading_and_trailing_dots.yul +++ b/test/libyul/objectCompiler/leading_and_trailing_dots.yul @@ -25,20 +25,6 @@ // /* "source":134:138 */ // tag_1 // jump // in -// /* "source":149:181 */ -// tag_2: -// /* "source":177:178 */ -// 0x00 -// /* "source":175:179 */ -// tag_2 -// jump // in -// /* "source":190:222 */ -// tag_3: -// /* "source":218:219 */ -// 0x00 -// /* "source":216:220 */ -// tag_3 -// jump // in -// Bytecode: 60025b5f6002565b5f6007565b5f600c56 -// Opcodes: PUSH1 0x2 JUMPDEST PUSH0 PUSH1 0x2 JUMP JUMPDEST PUSH0 PUSH1 0x7 JUMP JUMPDEST PUSH0 PUSH1 0xC JUMP -// SourceMappings: 53:1:0:-:0;108:32;136:1;134:4;:::i;149:32::-;177:1;175:4;:::i;190:32::-;218:1;216:4;:::i +// Bytecode: 60025b5f600256 +// Opcodes: PUSH1 0x2 JUMPDEST PUSH0 PUSH1 0x2 JUMP +// SourceMappings: 53:1:0:-:0;108:32;136:1;134:4;:::i diff --git a/test/libyul/yulControlFlowGraph/function.yul b/test/libyul/yulControlFlowGraph/function.yul index 90c4b380e..f65c7505c 100644 --- a/test/libyul/yulControlFlowGraph/function.yul +++ b/test/libyul/yulControlFlowGraph/function.yul @@ -44,30 +44,22 @@ // Block1Exit [label="FunctionReturn[f]"]; // Block1 -> Block1Exit; // -// FunctionEntry_g_2 [label="function g()"]; -// FunctionEntry_g_2 -> Block2; +// FunctionEntry_h_2 [label="function h(x)"]; +// FunctionEntry_h_2 -> Block2; // Block2 [label="\ -// sstore: [ 0x0101 0x01 ] => [ ]\l\ -// "]; -// Block2Exit [label="FunctionReturn[g]"]; -// Block2 -> Block2Exit; -// -// FunctionEntry_h_3 [label="function h(x)"]; -// FunctionEntry_h_3 -> Block3; -// Block3 [label="\ // f: [ RET[f] 0x00 x ] => [ TMP[f, 0] ]\l\ // h: [ TMP[f, 0] ] => [ ]\l\ // "]; -// Block3Exit [label="Terminated"]; -// Block3 -> Block3Exit; +// Block2Exit [label="Terminated"]; +// Block2 -> Block2Exit; // -// FunctionEntry_i_4 [label="function i() -> v, w"]; -// FunctionEntry_i_4 -> Block4; -// Block4 [label="\ +// FunctionEntry_i_3 [label="function i() -> v, w"]; +// FunctionEntry_i_3 -> Block3; +// Block3 [label="\ // Assignment(v): [ 0x0202 ] => [ v ]\l\ // Assignment(w): [ 0x0303 ] => [ w ]\l\ // "]; -// Block4Exit [label="FunctionReturn[i]"]; -// Block4 -> Block4Exit; +// Block3Exit [label="FunctionReturn[i]"]; +// Block3 -> Block3Exit; // // } diff --git a/test/libyul/yulStackLayout/function.yul b/test/libyul/yulStackLayout/function.yul index ccf97422f..e01a8dcb3 100644 --- a/test/libyul/yulStackLayout/function.yul +++ b/test/libyul/yulStackLayout/function.yul @@ -17,6 +17,8 @@ let x, y := i() h(x) h(y) + // This calla of g() is unreachable too as the one in h() but we wanna cover both cases. + g() } // ---- // digraph CFG { @@ -63,23 +65,10 @@ // Block1Exit [label="FunctionReturn[f]"]; // Block1 -> Block1Exit; // -// FunctionEntry_g [label="function g()\l\ -// [ RET ]"]; -// FunctionEntry_g -> Block2; -// Block2 [label="\ -// [ RET ]\l\ -// [ RET 0x0101 0x01 ]\l\ -// sstore\l\ -// [ RET ]\l\ -// [ RET ]\l\ -// "]; -// Block2Exit [label="FunctionReturn[g]"]; -// Block2 -> Block2Exit; -// // FunctionEntry_h [label="function h(x)\l\ // [ RET x ]"]; -// FunctionEntry_h -> Block3; -// Block3 [label="\ +// FunctionEntry_h -> Block2; +// Block2 [label="\ // [ RET[f] 0x00 x ]\l\ // [ RET[f] 0x00 x ]\l\ // f\l\ @@ -89,13 +78,13 @@ // [ ]\l\ // [ ]\l\ // "]; -// Block3Exit [label="Terminated"]; -// Block3 -> Block3Exit; +// Block2Exit [label="Terminated"]; +// Block2 -> Block2Exit; // // FunctionEntry_i [label="function i() -> v, w\l\ // [ RET ]"]; -// FunctionEntry_i -> Block4; -// Block4 [label="\ +// FunctionEntry_i -> Block3; +// Block3 [label="\ // [ RET ]\l\ // [ RET 0x0202 ]\l\ // Assignment(v)\l\ @@ -105,7 +94,7 @@ // [ v RET w ]\l\ // [ v w RET ]\l\ // "]; -// Block4Exit [label="FunctionReturn[i]"]; -// Block4 -> Block4Exit; +// Block3Exit [label="FunctionReturn[i]"]; +// Block3 -> Block3Exit; // // } From 8d98c6d8ad440a932b8e299ee6bebb028f9f2693 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 18 Dec 2024 17:05:12 +0100 Subject: [PATCH 0558/1340] eof: Support `bytecodeFormat` flag by `FunctionSideEffects` tests --- test/libyul/FunctionSideEffects.cpp | 2 +- test/libyul/FunctionSideEffects.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index 4dab4ace2..cb24ed764 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -75,7 +75,7 @@ std::string toString(SideEffects const& _sideEffects) } FunctionSideEffects::FunctionSideEffects(std::string const& _filename): - TestCase(_filename) + EVMVersionRestrictedTestCase(_filename) { m_source = m_reader.source(); m_expectation = m_reader.simpleExpectations(); diff --git a/test/libyul/FunctionSideEffects.h b/test/libyul/FunctionSideEffects.h index 3490c854a..9a7b77c14 100644 --- a/test/libyul/FunctionSideEffects.h +++ b/test/libyul/FunctionSideEffects.h @@ -28,7 +28,7 @@ namespace solidity::yul::test { -class FunctionSideEffects: public solidity::frontend::test::TestCase +class FunctionSideEffects: public solidity::frontend::test::EVMVersionRestrictedTestCase { public: static std::unique_ptr create(Config const& _config) From 535e2a97053d420bd3f62dc0938b2de26593e3d9 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 18 Dec 2024 17:05:12 +0100 Subject: [PATCH 0559/1340] eof: Update `functionSideEffects` tests --- test/libyul/functionSideEffects/otherImmovables.yul | 2 ++ test/libyul/functionSideEffects/state.yul | 2 ++ test/libyul/functionSideEffects/storage.yul | 2 ++ 3 files changed, 6 insertions(+) diff --git a/test/libyul/functionSideEffects/otherImmovables.yul b/test/libyul/functionSideEffects/otherImmovables.yul index bb02dba1d..01dfd877c 100644 --- a/test/libyul/functionSideEffects/otherImmovables.yul +++ b/test/libyul/functionSideEffects/otherImmovables.yul @@ -4,6 +4,8 @@ function g() { stop() } function h() { invalid() } } +// ==== +// bytecodeFormat: legacy // ---- // : movable, movable apart from effects, can be removed, can be removed if no msize // a: can be removed, can be removed if no msize diff --git a/test/libyul/functionSideEffects/state.yul b/test/libyul/functionSideEffects/state.yul index e605ff1e5..c8b467094 100644 --- a/test/libyul/functionSideEffects/state.yul +++ b/test/libyul/functionSideEffects/state.yul @@ -3,6 +3,8 @@ function f() { a() } function g() { sstore(0, 1) } } +// ==== +// bytecodeFormat: legacy // ---- // : movable, movable apart from effects, can be removed, can be removed if no msize // a: writes other state, writes storage, writes memory diff --git a/test/libyul/functionSideEffects/storage.yul b/test/libyul/functionSideEffects/storage.yul index 038c368a2..3d1e2d836 100644 --- a/test/libyul/functionSideEffects/storage.yul +++ b/test/libyul/functionSideEffects/storage.yul @@ -4,6 +4,8 @@ function g() { pop(callcode(100, 0x010, 10, 0x00, 32, 0x0100, 32))} function h() { pop(sload(0))} } +// ==== +// bytecodeFormat: legacy // ---- // : movable, movable apart from effects, can be removed, can be removed if no msize // a: writes storage From 8b31ce84a60979767aadd36ba9a5a6d5cc5891f2 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 18 Dec 2024 17:05:12 +0100 Subject: [PATCH 0560/1340] eof: Re-enable excluded earlier tests. --- .circleci/soltest.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/.circleci/soltest.sh b/.circleci/soltest.sh index 9631a7256..940ff1122 100755 --- a/.circleci/soltest.sh +++ b/.circleci/soltest.sh @@ -56,9 +56,6 @@ EOF_EXCLUDES=( --run_test='!SolidityInlineAssembly/Analysis/large_constant' --run_test='!SolidityInlineAssembly/Analysis/staticcall' --run_test='!ViewPureChecker/assembly_staticcall' - --run_test='!functionSideEffects/otherImmovables' - --run_test='!functionSideEffects/state' - --run_test='!functionSideEffects/storage' --run_test='!gasTests/abiv2' --run_test='!gasTests/abiv2_optimised' --run_test='!gasTests/data_storage' From f2d41d39ac504731448f618c1a3a892cbc41d478 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 13 Dec 2024 12:15:32 +0100 Subject: [PATCH 0561/1340] Adjust `copyConstructorArgumentsToMemoryFunction` function to make it supports EOF --- libsolidity/codegen/ABIFunctions.h | 3 +- libsolidity/codegen/Compiler.h | 11 +++++-- libsolidity/codegen/CompilerContext.h | 5 +-- libsolidity/codegen/YulUtilFunctions.cpp | 33 ++++++++++++------- libsolidity/codegen/YulUtilFunctions.h | 3 ++ .../codegen/ir/IRGenerationContext.cpp | 4 +-- libsolidity/codegen/ir/IRGenerator.cpp | 7 ++-- libsolidity/codegen/ir/IRGenerator.h | 2 +- .../codegen/ir/IRGeneratorForStatements.cpp | 4 +-- libsolidity/interface/CompilerStack.cpp | 7 +++- .../output.json | 2 ++ test/libsolidity/Assembly.cpp | 1 + .../SolidityExpressionCompiler.cpp | 1 + .../base_constructor_arguments.sol | 2 ++ 14 files changed, 60 insertions(+), 25 deletions(-) diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index b7f7f8ae5..d357447ac 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -56,13 +56,14 @@ class ABIFunctions public: explicit ABIFunctions( langutil::EVMVersion _evmVersion, + std::optional _eofVersion, RevertStrings _revertStrings, MultiUseYulFunctionCollector& _functionCollector ): m_evmVersion(_evmVersion), m_revertStrings(_revertStrings), m_functionCollector(_functionCollector), - m_utils(_evmVersion, m_revertStrings, m_functionCollector) + m_utils(_evmVersion, _eofVersion, m_revertStrings, m_functionCollector) {} /// @returns name of an assembly function to ABI-encode values of @a _givenTypes diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index 1267c1a2d..bc801ff57 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -37,10 +37,15 @@ namespace solidity::frontend class Compiler { public: - Compiler(langutil::EVMVersion _evmVersion, RevertStrings _revertStrings, OptimiserSettings _optimiserSettings): + Compiler( + langutil::EVMVersion _evmVersion, + std::optional _eofVersion, + RevertStrings _revertStrings, + OptimiserSettings _optimiserSettings + ): m_optimiserSettings(std::move(_optimiserSettings)), - m_runtimeContext(_evmVersion, _revertStrings), - m_context(_evmVersion, _revertStrings, &m_runtimeContext) + m_runtimeContext(_evmVersion, _eofVersion, _revertStrings), + m_context(_evmVersion, _eofVersion, _revertStrings, &m_runtimeContext) { } /// Compiles a contract. diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 2805b8daf..17559fbf4 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -62,6 +62,7 @@ class CompilerContext public: explicit CompilerContext( langutil::EVMVersion _evmVersion, + std::optional _eofVersion, RevertStrings _revertStrings, CompilerContext* _runtimeContext = nullptr ): @@ -70,8 +71,8 @@ class CompilerContext m_revertStrings(_revertStrings), m_reservedMemory{0}, m_runtimeContext(_runtimeContext), - m_abiFunctions(m_evmVersion, m_revertStrings, m_yulFunctionCollector), - m_yulUtilFunctions(m_evmVersion, m_revertStrings, m_yulFunctionCollector) + m_abiFunctions(m_evmVersion, _eofVersion, m_revertStrings, m_yulFunctionCollector), + m_yulUtilFunctions(m_evmVersion, _eofVersion, m_revertStrings, m_yulFunctionCollector) { if (m_runtimeContext) m_runtimeSub = size_t(m_asm->newSub(m_runtimeContext->m_asm).data()); diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index c908c7ae0..ffeaa790e 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -285,7 +285,7 @@ std::string YulUtilFunctions::revertWithError( errorArgumentTypes.push_back(arg->annotation().type); } templ("argumentVars", joinHumanReadablePrefixed(errorArgumentVars)); - templ("encode", ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector).tupleEncoder(errorArgumentTypes, _parameterTypes)); + templ("encode", ABIFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector).tupleEncoder(errorArgumentTypes, _parameterTypes)); return templ.render(); } @@ -2592,7 +2592,7 @@ std::string YulUtilFunctions::copyArrayFromStorageToMemoryFunction(ArrayType con if (_from.baseType()->isValueType()) { solAssert(*_from.baseType() == *_to.baseType(), ""); - ABIFunctions abi(m_evmVersion, m_revertStrings, m_functionCollector); + ABIFunctions abi(m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector); return Whiskers(R"( function (slot) -> memPtr { memPtr := () @@ -2697,7 +2697,7 @@ std::string YulUtilFunctions::bytesOrStringConcatFunction( templ("finalizeAllocation", finalizeAllocationFunction()); templ( "encodePacked", - ABIFunctions{m_evmVersion, m_revertStrings, m_functionCollector}.tupleEncoderPacked( + ABIFunctions{m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector}.tupleEncoderPacked( _argumentTypes, targetTypes ) @@ -3578,7 +3578,7 @@ std::string YulUtilFunctions::conversionFunction(Type const& _from, Type const& )") ( "abiDecode", - ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector).abiDecodingFunctionStruct( + ABIFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector).abiDecodingFunctionStruct( toStructType, false ) @@ -3907,6 +3907,7 @@ std::string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, Ar _from.dataStoredIn(DataLocation::CallData) ? ABIFunctions( m_evmVersion, + m_eofVersion, m_revertStrings, m_functionCollector ).abiDecodingFunctionArrayAvailableLength(_to, false) : @@ -4105,7 +4106,10 @@ std::string YulUtilFunctions::packedHashFunction( templ("variables", suffixedVariableNameList("var_", 1, 1 + sizeOnStack)); templ("comma", sizeOnStack > 0 ? "," : ""); templ("allocateUnbounded", allocateUnboundedFunction()); - templ("packedEncode", ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector).tupleEncoderPacked(_givenTypes, _targetTypes)); + templ( + "packedEncode", + ABIFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector).tupleEncoderPacked(_givenTypes, _targetTypes) + ); return templ.render(); }); } @@ -4726,15 +4730,21 @@ std::string YulUtilFunctions::copyConstructorArgumentsToMemoryFunction( return m_functionCollector.createFunction(functionName, [&]() { std::string returnParams = suffixedVariableNameList("ret_param_",0, CompilerUtils::sizeOnStack(_contract.constructor()->parameters())); - ABIFunctions abiFunctions(m_evmVersion, m_revertStrings, m_functionCollector); + ABIFunctions abiFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector); return util::Whiskers(R"( function () -> { - let programSize := datasize("") - let argSize := sub(codesize(), programSize) - - let memoryDataOffset := (argSize) - codecopy(memoryDataOffset, programSize, argSize) + + let argSize := calldatasize() + let memoryDataOffset := (argSize) + calldatacopy(memoryDataOffset, 0, argSize) + + let programSize := datasize("") + let argSize := sub(codesize(), programSize) + + let memoryDataOffset := (argSize) + codecopy(memoryDataOffset, programSize, argSize) + := (memoryDataOffset, add(memoryDataOffset, argSize)) } @@ -4744,6 +4754,7 @@ std::string YulUtilFunctions::copyConstructorArgumentsToMemoryFunction( ("object", _creationObjectName) ("allocate", allocationFunction()) ("abiDecode", abiFunctions.tupleDecoder(FunctionType(*_contract.constructor()).parameterTypes(), true)) + ("eof", m_eofVersion.has_value()) .render(); }); } diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index 6c06cdcc9..5ea99d603 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -52,10 +52,12 @@ class YulUtilFunctions public: explicit YulUtilFunctions( langutil::EVMVersion _evmVersion, + std::optional _eofVersion, RevertStrings _revertStrings, MultiUseYulFunctionCollector& _functionCollector ): m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion), m_revertStrings(_revertStrings), m_functionCollector(_functionCollector) {} @@ -640,6 +642,7 @@ class YulUtilFunctions std::string longByteArrayStorageIndexAccessNoCheckFunction(); langutil::EVMVersion m_evmVersion; + std::optional m_eofVersion; RevertStrings m_revertStrings; MultiUseYulFunctionCollector& m_functionCollector; }; diff --git a/libsolidity/codegen/ir/IRGenerationContext.cpp b/libsolidity/codegen/ir/IRGenerationContext.cpp index 89ce99949..f33461b63 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.cpp +++ b/libsolidity/codegen/ir/IRGenerationContext.cpp @@ -224,10 +224,10 @@ void IRGenerationContext::internalFunctionCalledThroughDispatch(YulArity const& YulUtilFunctions IRGenerationContext::utils() { - return YulUtilFunctions(m_evmVersion, m_revertStrings, m_functions); + return YulUtilFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functions); } ABIFunctions IRGenerationContext::abiFunctions() { - return ABIFunctions(m_evmVersion, m_revertStrings, m_functions); + return ABIFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functions); } diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index e8bb7a874..ae2a12c71 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -177,7 +177,10 @@ std::string IRGenerator::generate( constructorParams.emplace_back(m_context.newYulVariable()); t( "copyConstructorArguments", - m_utils.copyConstructorArgumentsToMemoryFunction(_contract, IRNames::creationObject(_contract)) + m_utils.copyConstructorArgumentsToMemoryFunction( + _contract, + IRNames::creationObject(_contract) + ) ); } t("constructorParams", joinHumanReadable(constructorParams)); @@ -768,7 +771,7 @@ std::string IRGenerator::generateExternalFunction(ContractDefinition const& _con unsigned paramVars = std::make_shared(_functionType.parameterTypes())->sizeOnStack(); unsigned retVars = std::make_shared(_functionType.returnParameterTypes())->sizeOnStack(); - ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector()); + ABIFunctions abiFunctions(m_evmVersion, m_eofVersion, m_context.revertStrings(), m_context.functionCollector()); t("abiDecode", abiFunctions.tupleDecoder(_functionType.parameterTypes())); t("params", suffixedVariableNameList("param_", 0, paramVars)); t("retParams", suffixedVariableNameList("ret_", 0, retVars)); diff --git a/libsolidity/codegen/ir/IRGenerator.h b/libsolidity/codegen/ir/IRGenerator.h index ed29a8bb3..60d5d25cd 100644 --- a/libsolidity/codegen/ir/IRGenerator.h +++ b/libsolidity/codegen/ir/IRGenerator.h @@ -66,7 +66,7 @@ class IRGenerator _debugInfoSelection, _soliditySourceProvider ), - m_utils(_evmVersion, m_context.revertStrings(), m_context.functionCollector()), + m_utils(_evmVersion, _eofVersion, m_context.revertStrings(), m_context.functionCollector()), m_optimiserSettings(_optimiserSettings) {} diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index babe43357..3ae151593 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1072,7 +1072,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) { auto const& event = dynamic_cast(functionType->declaration()); TypePointers paramTypes = functionType->parameterTypes(); - ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector()); + ABIFunctions abi(m_context.evmVersion(), m_context.eofVersion(), m_context.revertStrings(), m_context.functionCollector()); std::vector indexedArgs; std::vector nonIndexedArgs; @@ -2843,7 +2843,7 @@ void IRGeneratorForStatements::appendBareCall( else { templ("needsEncoding", true); - ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector()); + ABIFunctions abi(m_context.evmVersion(), m_context.eofVersion(), m_context.revertStrings(), m_context.functionCollector()); templ("encode", abi.tupleEncoderPacked({&argType}, {TypeProvider::bytesMemory()})); } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 9d76ced02..2a859ea24 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1502,7 +1502,12 @@ void CompilerStack::compileContract( Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName()); - std::shared_ptr compiler = std::make_shared(m_evmVersion, m_revertStrings, m_optimiserSettings); + std::shared_ptr compiler = std::make_shared( + m_evmVersion, + m_eofVersion, + m_revertStrings, + m_optimiserSettings + ); solAssert(!m_viaIR, ""); bytes cborEncodedMetadata = createCBORMetadata(compiledContract, /* _forIR */ false); diff --git a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json index 5ff4e7a19..16220fd61 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json @@ -84,6 +84,7 @@ object \"C_54\" { } function copy_arguments_for_constructor_20_object_C_54() -> ret_param_0 { + let programSize := datasize(\"C_54\") let argSize := sub(codesize(), programSize) @@ -850,6 +851,7 @@ object \"D_72\" { } function copy_arguments_for_constructor_71_object_D_72() -> ret_param_0 { + let programSize := datasize(\"D_72\") let argSize := sub(codesize(), programSize) diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 0999e30ed..bf9c6b16a 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -94,6 +94,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr _sourceCode) { Compiler compiler( solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion(), RevertStrings::Default, solidity::test::CommonOptions::get().optimize ? OptimiserSettings::standard() : OptimiserSettings::minimal() ); diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 3df712a43..b6d40eed0 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -147,6 +147,7 @@ bytes compileFirstExpression( CompilerContext context( solidity::test::CommonOptions::get().evmVersion(), + solidity::test::CommonOptions::get().eofVersion(), RevertStrings::Default ); context.resetVisitedNodes(contract); diff --git a/test/libsolidity/semanticTests/constructor/base_constructor_arguments.sol b/test/libsolidity/semanticTests/constructor/base_constructor_arguments.sol index 55daf6d3d..ee1ed3019 100644 --- a/test/libsolidity/semanticTests/constructor/base_constructor_arguments.sol +++ b/test/libsolidity/semanticTests/constructor/base_constructor_arguments.sol @@ -19,5 +19,7 @@ contract Derived is Base { return m_a; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getA() -> 49 From b1d31432cc57a0d1ee67ccd8b525690c0967cb8e Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 13 Dec 2024 12:15:53 +0100 Subject: [PATCH 0562/1340] eof: Enable semantic tests. --- .../semanticTests/constructor/arrays_in_constructors.sol | 2 ++ .../semanticTests/constructor/bytes_in_constructors_packer.sol | 2 ++ .../constructor/bytes_in_constructors_unpacker.sol | 2 ++ .../constructor/constructor_arguments_external.sol | 2 ++ .../constructor/constructor_arguments_internal.sol | 2 ++ .../semanticTests/constructor/constructor_function_argument.sol | 2 ++ .../semanticTests/constructor/constructor_function_complex.sol | 2 ++ .../constructor/constructor_static_array_argument.sol | 2 ++ .../constructor/evm_exceptions_in_constructor_call_fail.sol | 2 ++ .../constructor/function_usage_in_constructor_arguments.sol | 2 ++ .../constructor/functions_called_by_constructor.sol | 2 ++ .../functions_called_by_constructor_through_dispatch.sol | 2 ++ .../inline_member_init_inheritence_without_constructor.sol | 2 ++ .../semanticTests/constructor/order_of_evaluation.sol | 2 ++ .../semanticTests/constructor/payable_constructor.sol | 2 ++ .../semanticTests/constructor/store_function_in_constructor.sol | 2 ++ .../constructor/store_function_in_constructor_packed.sol | 2 ++ .../store_internal_unused_function_in_constructor.sol | 2 ++ .../store_internal_unused_library_function_in_constructor.sol | 2 ++ .../constructor/transient_state_variable_initialization.sol | 1 + 20 files changed, 39 insertions(+) diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index 8fe8d36f9..aeeb1a0c1 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -22,6 +22,8 @@ contract Creator { ch = c.part(x); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 // gas irOptimized: 327784 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index 69896ebf1..55abe4804 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -22,6 +22,8 @@ contract Creator { ch = c.part(x); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" // gas irOptimized: 169292 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol index 036d6ca62..13db633b9 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol @@ -6,6 +6,8 @@ contract Test { m_s = s; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> // gas irOptimized: 181465 diff --git a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol index 7d068338b..e59cb4214 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_arguments_external.sol @@ -15,6 +15,8 @@ contract Main { return flag; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // constructor(): "abc", true // gas irOptimized: 80174 diff --git a/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol b/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol index bf3f0c0c9..a811d12c8 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_arguments_internal.sol @@ -32,6 +32,8 @@ contract Main { return h.getName(); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getFlag() -> true // getName() -> "abc" diff --git a/test/libsolidity/semanticTests/constructor/constructor_function_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_function_argument.sol index 159f2943d..76e5193d9 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_function_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_function_argument.sol @@ -3,5 +3,7 @@ contract D { constructor(function() external returns (uint)) { } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // constructor(): 0xfdd67305928fcac8d213d1e47bfa6165cd0b87b946644cd0000000000000000 -> diff --git a/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol index 13abe72c5..10a4ee06d 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol @@ -15,6 +15,8 @@ contract C { return 16; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // f() -> 16 // gas legacy: 78477 diff --git a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol index 5947b2573..ed4eb6e4d 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol @@ -7,6 +7,8 @@ contract C { b = _b; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // constructor(): 1, 2, 3, 4 -> // gas irOptimized: 148129 diff --git a/test/libsolidity/semanticTests/constructor/evm_exceptions_in_constructor_call_fail.sol b/test/libsolidity/semanticTests/constructor/evm_exceptions_in_constructor_call_fail.sol index 43d1fdab8..d45c65524 100644 --- a/test/libsolidity/semanticTests/constructor/evm_exceptions_in_constructor_call_fail.sol +++ b/test/libsolidity/semanticTests/constructor/evm_exceptions_in_constructor_call_fail.sol @@ -13,6 +13,8 @@ contract B { ++test; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // testIt() -> // test() -> 2 diff --git a/test/libsolidity/semanticTests/constructor/function_usage_in_constructor_arguments.sol b/test/libsolidity/semanticTests/constructor/function_usage_in_constructor_arguments.sol index c04f03918..a736cab91 100644 --- a/test/libsolidity/semanticTests/constructor/function_usage_in_constructor_arguments.sol +++ b/test/libsolidity/semanticTests/constructor/function_usage_in_constructor_arguments.sol @@ -19,5 +19,7 @@ contract Derived is Base { return m_a; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getA() -> 2 diff --git a/test/libsolidity/semanticTests/constructor/functions_called_by_constructor.sol b/test/libsolidity/semanticTests/constructor/functions_called_by_constructor.sol index b968a07a1..d70508b76 100644 --- a/test/libsolidity/semanticTests/constructor/functions_called_by_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/functions_called_by_constructor.sol @@ -14,5 +14,7 @@ contract Test { name = _name; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getName() -> "abc" diff --git a/test/libsolidity/semanticTests/constructor/functions_called_by_constructor_through_dispatch.sol b/test/libsolidity/semanticTests/constructor/functions_called_by_constructor_through_dispatch.sol index 0a1250a8b..ef7b5dcf8 100644 --- a/test/libsolidity/semanticTests/constructor/functions_called_by_constructor_through_dispatch.sol +++ b/test/libsolidity/semanticTests/constructor/functions_called_by_constructor_through_dispatch.sol @@ -24,5 +24,7 @@ contract Test { name = _shiftOperator(name, _bytes); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getName() -> "def\x00\x00\x00" diff --git a/test/libsolidity/semanticTests/constructor/inline_member_init_inheritence_without_constructor.sol b/test/libsolidity/semanticTests/constructor/inline_member_init_inheritence_without_constructor.sol index 320349cda..13c80b7b6 100644 --- a/test/libsolidity/semanticTests/constructor/inline_member_init_inheritence_without_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/inline_member_init_inheritence_without_constructor.sol @@ -14,6 +14,8 @@ contract Derived is Base { return m_derived; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // getBMember() -> 5 // getDMember() -> 6 diff --git a/test/libsolidity/semanticTests/constructor/order_of_evaluation.sol b/test/libsolidity/semanticTests/constructor/order_of_evaluation.sol index 2416f124e..14bb7cf07 100644 --- a/test/libsolidity/semanticTests/constructor/order_of_evaluation.sol +++ b/test/libsolidity/semanticTests/constructor/order_of_evaluation.sol @@ -18,5 +18,7 @@ contract X is D, C, B, A { function g() public view returns (uint[] memory) { return x; } constructor() A(f(1)) C(f(2)) B(f(3)) D(f(4)) {} } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // g() -> 0x20, 4, 1, 3, 2, 4 diff --git a/test/libsolidity/semanticTests/constructor/payable_constructor.sol b/test/libsolidity/semanticTests/constructor/payable_constructor.sol index 09fe0a1cc..1020f697d 100644 --- a/test/libsolidity/semanticTests/constructor/payable_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/payable_constructor.sol @@ -1,5 +1,7 @@ contract C { constructor() payable {} } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // constructor(), 27 wei -> diff --git a/test/libsolidity/semanticTests/constructor/store_function_in_constructor.sol b/test/libsolidity/semanticTests/constructor/store_function_in_constructor.sol index dee3af354..7bc2982b7 100644 --- a/test/libsolidity/semanticTests/constructor/store_function_in_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/store_function_in_constructor.sol @@ -15,6 +15,8 @@ contract C { return x(_arg); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // use(uint256): 3 -> 6 // result_in_constructor() -> 4 diff --git a/test/libsolidity/semanticTests/constructor/store_function_in_constructor_packed.sol b/test/libsolidity/semanticTests/constructor/store_function_in_constructor_packed.sol index 07b12ad96..b0a20f143 100644 --- a/test/libsolidity/semanticTests/constructor/store_function_in_constructor_packed.sol +++ b/test/libsolidity/semanticTests/constructor/store_function_in_constructor_packed.sol @@ -16,6 +16,8 @@ contract C { return x(_arg); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // use(uint16): 3 -> 0xfff9 // result_in_constructor() -> 0xfffb diff --git a/test/libsolidity/semanticTests/constructor/store_internal_unused_function_in_constructor.sol b/test/libsolidity/semanticTests/constructor/store_internal_unused_function_in_constructor.sol index cc9d8ca6a..905e1d349 100644 --- a/test/libsolidity/semanticTests/constructor/store_internal_unused_function_in_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/store_internal_unused_function_in_constructor.sol @@ -13,5 +13,7 @@ contract C { return x(); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // t() -> 7 diff --git a/test/libsolidity/semanticTests/constructor/store_internal_unused_library_function_in_constructor.sol b/test/libsolidity/semanticTests/constructor/store_internal_unused_library_function_in_constructor.sol index 5845e9b56..b7d9bb5f4 100644 --- a/test/libsolidity/semanticTests/constructor/store_internal_unused_library_function_in_constructor.sol +++ b/test/libsolidity/semanticTests/constructor/store_internal_unused_library_function_in_constructor.sol @@ -16,5 +16,7 @@ contract C { return x(); } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // t() -> 7 diff --git a/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol b/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol index 3260fa30f..46a9090c2 100644 --- a/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol +++ b/test/libsolidity/semanticTests/constructor/transient_state_variable_initialization.sol @@ -14,5 +14,6 @@ contract C { // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy,>=EOFv1 // ---- // f() -> 100 From be16078d747b14b67616e4a64fe2df54949b97f7 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 18 Dec 2024 16:15:29 +0100 Subject: [PATCH 0563/1340] eof: Make `GasTest` inherits from `EVMVersionRestricted` --- test/libsolidity/GasTest.cpp | 6 +----- test/libsolidity/GasTest.h | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/test/libsolidity/GasTest.cpp b/test/libsolidity/GasTest.cpp index 14722535e..39b0e6681 100644 --- a/test/libsolidity/GasTest.cpp +++ b/test/libsolidity/GasTest.cpp @@ -37,7 +37,7 @@ using namespace solidity; using namespace boost::unit_test; GasTest::GasTest(std::string const& _filename): - TestCase(_filename) + EVMVersionRestrictedTestCase(_filename) { m_source = m_reader.source(); m_optimise = m_reader.boolSetting("optimize", false); @@ -114,10 +114,6 @@ void GasTest::setupCompiler(CompilerStack& _compiler) } settings.expectedExecutionsPerDeployment = m_optimiseRuns; _compiler.setOptimiserSettings(settings); - - // Intentionally ignoring EVM version specified on the command line. - // Gas expectations are only valid for the default version. - _compiler.setEVMVersion(EVMVersion{}); } TestCase::TestResult GasTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) diff --git a/test/libsolidity/GasTest.h b/test/libsolidity/GasTest.h index 1337ae3f6..998411abf 100644 --- a/test/libsolidity/GasTest.h +++ b/test/libsolidity/GasTest.h @@ -32,7 +32,7 @@ namespace solidity::frontend::test { -class GasTest: AnalysisFramework, public TestCase +class GasTest: AnalysisFramework, public EVMVersionRestrictedTestCase { public: static std::unique_ptr create(Config const& _config) From da7e1bc2f7125d1c9b03e3ff5894374aeac22a9e Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 18 Dec 2024 16:50:16 +0100 Subject: [PATCH 0564/1340] eof: Enable disabled earlier `gasTests` in `soltest.sh` --- .circleci/soltest.sh | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.circleci/soltest.sh b/.circleci/soltest.sh index 940ff1122..71c2a952a 100755 --- a/.circleci/soltest.sh +++ b/.circleci/soltest.sh @@ -56,18 +56,6 @@ EOF_EXCLUDES=( --run_test='!SolidityInlineAssembly/Analysis/large_constant' --run_test='!SolidityInlineAssembly/Analysis/staticcall' --run_test='!ViewPureChecker/assembly_staticcall' - --run_test='!gasTests/abiv2' - --run_test='!gasTests/abiv2_optimised' - --run_test='!gasTests/data_storage' - --run_test='!gasTests/dispatch_large' - --run_test='!gasTests/dispatch_large_optimised' - --run_test='!gasTests/dispatch_medium' - --run_test='!gasTests/dispatch_medium_optimised' - --run_test='!gasTests/dispatch_small' - --run_test='!gasTests/dispatch_small_optimised' - --run_test='!gasTests/exp' - --run_test='!gasTests/exp_optimized' - --run_test='!gasTests/storage_costs' --run_test='!yulStackLayout/literal_loop' ) From 586d31473d8d4fdbf41392f345a5ffd80ffff738 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 18 Dec 2024 21:32:16 +0100 Subject: [PATCH 0565/1340] eof: Update `gasTests` tests --- test/libsolidity/gasTests/abiv2.sol | 3 +++ test/libsolidity/gasTests/abiv2_optimised.sol | 2 ++ test/libsolidity/gasTests/data_storage.sol | 3 +++ test/libsolidity/gasTests/dispatch_large.sol | 3 +++ test/libsolidity/gasTests/dispatch_large_optimised.sol | 2 ++ test/libsolidity/gasTests/dispatch_medium.sol | 3 +++ test/libsolidity/gasTests/dispatch_medium_optimised.sol | 3 +++ test/libsolidity/gasTests/dispatch_small.sol | 3 +++ test/libsolidity/gasTests/dispatch_small_optimised.sol | 2 ++ test/libsolidity/gasTests/exp.sol | 2 ++ test/libsolidity/gasTests/exp_optimized.sol | 2 ++ test/libsolidity/gasTests/storage_costs.sol | 2 ++ 12 files changed, 30 insertions(+) diff --git a/test/libsolidity/gasTests/abiv2.sol b/test/libsolidity/gasTests/abiv2.sol index 6fa822fad..95c30ac64 100644 --- a/test/libsolidity/gasTests/abiv2.sol +++ b/test/libsolidity/gasTests/abiv2.sol @@ -12,6 +12,9 @@ contract C { function f7(uint[31] memory, string[20] memory, C, address) public returns (bytes[] memory, uint16[] memory) {} function f8(uint[32] memory, string[] memory, uint32, address) public returns (uint[] memory, uint16[] memory) {} } +// ==== +// EVMVersion: =current +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 1208000 diff --git a/test/libsolidity/gasTests/abiv2_optimised.sol b/test/libsolidity/gasTests/abiv2_optimised.sol index 2989c1acd..e23a7bff2 100644 --- a/test/libsolidity/gasTests/abiv2_optimised.sol +++ b/test/libsolidity/gasTests/abiv2_optimised.sol @@ -13,6 +13,8 @@ contract C { function f8(uint[32] memory, string[] memory, uint32, address) public returns (uint[] memory, uint16[] memory) {} } // ==== +// EVMVersion: =current +// bytecodeFormat: legacy // optimize: true // optimize-yul: true // ---- diff --git a/test/libsolidity/gasTests/data_storage.sol b/test/libsolidity/gasTests/data_storage.sol index 0d24ef505..d9cacf5ca 100644 --- a/test/libsolidity/gasTests/data_storage.sol +++ b/test/libsolidity/gasTests/data_storage.sol @@ -11,6 +11,9 @@ contract C { require(false, "12345678901234567890123456789012123456789012345678901234567890123"); } } +// ==== +// EVMVersion: =current +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 377800 diff --git a/test/libsolidity/gasTests/dispatch_large.sol b/test/libsolidity/gasTests/dispatch_large.sol index e1cce4acd..2b7822f5f 100644 --- a/test/libsolidity/gasTests/dispatch_large.sol +++ b/test/libsolidity/gasTests/dispatch_large.sol @@ -22,6 +22,9 @@ contract Large { function g9(uint x) public payable returns (uint) { b[uint8(msg.data[8])] = x; } function g0(uint x) public payable returns (uint) { require(x > 10); } } +// ==== +// EVMVersion: =current +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 618400 diff --git a/test/libsolidity/gasTests/dispatch_large_optimised.sol b/test/libsolidity/gasTests/dispatch_large_optimised.sol index 83e55c1a9..5ab62e892 100644 --- a/test/libsolidity/gasTests/dispatch_large_optimised.sol +++ b/test/libsolidity/gasTests/dispatch_large_optimised.sol @@ -23,6 +23,8 @@ contract Large { function g0(uint x) public payable returns (uint) { require(x > 10); } } // ==== +// EVMVersion: =current +// bytecodeFormat: legacy // optimize: true // optimize-runs: 2 // ---- diff --git a/test/libsolidity/gasTests/dispatch_medium.sol b/test/libsolidity/gasTests/dispatch_medium.sol index 6bf8f8939..aedbec0b0 100644 --- a/test/libsolidity/gasTests/dispatch_medium.sol +++ b/test/libsolidity/gasTests/dispatch_medium.sol @@ -9,6 +9,9 @@ contract Medium { function g9(uint x) public payable returns (uint) { b[uint8(msg.data[8])] = x; } function g0(uint x) public payable returns (uint) { require(x > 10); } } +// ==== +// EVMVersion: =current +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 259600 diff --git a/test/libsolidity/gasTests/dispatch_medium_optimised.sol b/test/libsolidity/gasTests/dispatch_medium_optimised.sol index e921fcf12..2ea33955e 100644 --- a/test/libsolidity/gasTests/dispatch_medium_optimised.sol +++ b/test/libsolidity/gasTests/dispatch_medium_optimised.sol @@ -10,6 +10,9 @@ contract Medium { function g0(uint x) public payable returns (uint) { require(x > 10); } } // ==== +// EVMVersion: =current +// bytecodeFormat: legacy +// ==== // optimize: true // optimize-runs: 2 // ---- diff --git a/test/libsolidity/gasTests/dispatch_small.sol b/test/libsolidity/gasTests/dispatch_small.sol index d2c391582..d198fd992 100644 --- a/test/libsolidity/gasTests/dispatch_small.sol +++ b/test/libsolidity/gasTests/dispatch_small.sol @@ -4,6 +4,9 @@ contract Small { function f1(uint x) public returns (uint) { a = x; b[uint8(msg.data[0])] = x; } fallback () external payable {} } +// ==== +// EVMVersion: =current +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 103800 diff --git a/test/libsolidity/gasTests/dispatch_small_optimised.sol b/test/libsolidity/gasTests/dispatch_small_optimised.sol index e20e1d982..b59bdafc2 100644 --- a/test/libsolidity/gasTests/dispatch_small_optimised.sol +++ b/test/libsolidity/gasTests/dispatch_small_optimised.sol @@ -5,8 +5,10 @@ contract Small { fallback () external payable {} } // ==== +// EVMVersion: =current // optimize: true // optimize-runs: 2 +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 58200 diff --git a/test/libsolidity/gasTests/exp.sol b/test/libsolidity/gasTests/exp.sol index 6ad4dd3be..40ef13813 100644 --- a/test/libsolidity/gasTests/exp.sol +++ b/test/libsolidity/gasTests/exp.sol @@ -15,6 +15,8 @@ contract C { } } // ==== +// EVMVersion: =current +// bytecodeFormat: legacy // optimize: false // optimize-yul: false // ---- diff --git a/test/libsolidity/gasTests/exp_optimized.sol b/test/libsolidity/gasTests/exp_optimized.sol index 982fcd28f..fae9a24fd 100644 --- a/test/libsolidity/gasTests/exp_optimized.sol +++ b/test/libsolidity/gasTests/exp_optimized.sol @@ -15,6 +15,8 @@ contract C { } } // ==== +// EVMVersion: =current +// bytecodeFormat: legacy // optimize: true // optimize-yul: true // ---- diff --git a/test/libsolidity/gasTests/storage_costs.sol b/test/libsolidity/gasTests/storage_costs.sol index afb442ed7..871c15eab 100644 --- a/test/libsolidity/gasTests/storage_costs.sol +++ b/test/libsolidity/gasTests/storage_costs.sol @@ -11,8 +11,10 @@ contract C { } } // ==== +// EVMVersion: =current // optimize: true // optimize-yul: true +// bytecodeFormat: legacy // ---- // creation: // codeDepositCost: 25600 From 969950c637752cac0dffa50f781334a5d14a343d Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 13 Dec 2024 14:22:23 +0100 Subject: [PATCH 0566/1340] eof: Fix assembly stack height for non-returning function --- libevmasm/Assembly.cpp | 27 ++++++++++--------- libevmasm/Assembly.h | 7 +++-- libevmasm/AssemblyItem.cpp | 2 +- libevmasm/AssemblyItem.h | 8 +++--- libyul/backends/evm/AbstractAssembly.h | 3 ++- libyul/backends/evm/EthAssemblyAdapter.cpp | 4 +-- libyul/backends/evm/EthAssemblyAdapter.h | 2 +- libyul/backends/evm/NoOutputAssembly.cpp | 12 ++++----- libyul/backends/evm/NoOutputAssembly.h | 2 +- .../evm/OptimizedEVMCodeTransform.cpp | 10 +++---- .../inline_assembly_in_modifiers.sol | 2 ++ 11 files changed, 41 insertions(+), 38 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 1fe4fa7d9..001865b2c 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -708,10 +708,10 @@ AssemblyItem Assembly::newFunctionCall(uint16_t _functionID) const solAssert(_functionID < m_codeSections.size(), "Call to undeclared function."); solAssert(_functionID > 0, "Cannot call section 0"); auto const& section = m_codeSections.at(_functionID); - if (section.outputs != 0x80) - return AssemblyItem::functionCall(_functionID, section.inputs, section.outputs); - else + if (section.nonReturning) return AssemblyItem::jumpToFunction(_functionID, section.inputs, section.outputs); + else + return AssemblyItem::functionCall(_functionID, section.inputs, section.outputs); } AssemblyItem Assembly::newFunctionReturn() const @@ -720,14 +720,14 @@ AssemblyItem Assembly::newFunctionReturn() const return AssemblyItem::functionReturn(); } -uint16_t Assembly::createFunction(uint8_t _args, uint8_t _rets) +uint16_t Assembly::createFunction(uint8_t _args, uint8_t _rets, bool _nonReturning) { size_t functionID = m_codeSections.size(); solRequire(functionID < 1024, AssemblyException, "Too many functions for EOF"); solAssert(m_currentCodeSection == 0, "Functions need to be declared from the main block."); - solAssert(_rets <= 0x80, "Too many function returns."); - solAssert(_args <= 127, "Too many function inputs."); - m_codeSections.emplace_back(CodeSection{_args, _rets, {}}); + solRequire(_rets <= 127, AssemblyException, "Too many function returns."); + solRequire(_args <= 127, AssemblyException, "Too many function inputs."); + m_codeSections.emplace_back(CodeSection{_args, _rets, _nonReturning, {}}); return static_cast(functionID); } @@ -1103,7 +1103,8 @@ std::tuple, size_t> Assembly::createEOFHeader(std::se for (auto const& codeSection: m_codeSections) { retBytecode.push_back(codeSection.inputs); - retBytecode.push_back(codeSection.outputs); + // According to EOF spec function output num equals 0x80 means non-returning function + retBytecode.push_back(codeSection.nonReturning ? 0x80 : codeSection.outputs); appendBigEndianUint16(retBytecode, calculateMaxStackHeight(codeSection)); } @@ -1522,7 +1523,8 @@ LinkerObject const& Assembly::assembleEOF() const solRequire(!m_codeSections.empty(), AssemblyException, "Expected at least one code section."); solRequire( - m_codeSections.front().inputs == 0 && m_codeSections.front().outputs == 0x80, AssemblyException, + m_codeSections.front().inputs == 0 && m_codeSections.front().outputs == 0 && m_codeSections.front().nonReturning, + AssemblyException, "Expected the first code section to have zero inputs and be non-returning." ); @@ -1624,12 +1626,11 @@ LinkerObject const& Assembly::assembleEOF() const size_t const index = static_cast(item.data()); solAssert(index < m_codeSections.size()); solAssert(item.functionSignature().argsNum <= 127); - solAssert(item.type() == JumpF || item.functionSignature().retsNum <= 127); - solAssert(item.type() == CallF || item.functionSignature().retsNum <= 128); + solAssert(item.functionSignature().retsNum <= 127); solAssert(m_codeSections[index].inputs == item.functionSignature().argsNum); solAssert(m_codeSections[index].outputs == item.functionSignature().retsNum); - // If CallF the function can continue. - solAssert(item.type() == JumpF || item.functionSignature().canContinue()); + // If CallF the function cannot be non-returning. + solAssert(item.type() == JumpF || !m_codeSections[index].nonReturning); appendBigEndianUint16(ret.bytecode, item.data()); break; } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index db567a917..92dfb0a44 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -61,7 +61,7 @@ class Assembly m_name(std::move(_name)) { // Code section number 0 has to be non-returning. - m_codeSections.emplace_back(CodeSection{0, 0x80, {}}); + m_codeSections.emplace_back(CodeSection{0, 0, true, {}}); } std::optional eofVersion() const { return m_eofVersion; } @@ -72,7 +72,7 @@ class Assembly AssemblyItem newFunctionCall(uint16_t _functionID) const; AssemblyItem newFunctionReturn() const; - uint16_t createFunction(uint8_t _args, uint8_t _rets); + uint16_t createFunction(uint8_t _args, uint8_t _rets, bool _nonReturning); void beginFunction(uint16_t _functionID); void endFunction(); @@ -221,7 +221,10 @@ class Assembly struct CodeSection { uint8_t inputs = 0; + // Number of outputs needs to be set properly even for non-returning function. + // It matters in case of stack height calculation of the function call instruction. uint8_t outputs = 0; + bool nonReturning = false; AssemblyItems items{}; }; diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index ea670eb0a..424b9eeda 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -249,7 +249,7 @@ size_t AssemblyItem::returnValues() const return 1; case JumpF: case CallF: - return functionSignature().canContinue() ? functionSignature().retsNum : 0; + return functionSignature().retsNum; case AssignImmutable: case UndefinedItem: break; diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 28b2fb537..babf2b7b7 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -120,7 +120,7 @@ class AssemblyItem static AssemblyItem jumpToFunction(uint16_t _functionID, uint8_t _args, uint8_t _rets, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) { AssemblyItem result(JumpF, Instruction::JUMPF, _functionID, _debugData); - solAssert(_args <= 127 && _rets <= 128); + solAssert(_args <= 127 && _rets <= 127); result.m_functionSignature = {_args, _rets}; return result; } @@ -292,12 +292,10 @@ class AssemblyItem struct FunctionSignature { - /// Number of EOF function arguments. must be less than 127 + /// Number of EOF function arguments. must be less than 128 uint8_t argsNum; - /// Number of EOF function return values. Must be less than 128. 128(0x80) means that it's non-returning. + /// Number of EOF function return values. Must be less than 128. uint8_t retsNum; - - bool canContinue() const { return retsNum != 0x80;} }; FunctionSignature const& functionSignature() const diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index 6fe234782..7a3e6b742 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -105,7 +105,8 @@ class AbstractAssembly /// Registers a new function with given signature and returns its ID. /// The function is initially empty and its body must be filled with instructions. - virtual FunctionID registerFunction(uint8_t _args, uint8_t _rets) = 0; + /// `_rets` even for non-returning function matters in case of stack height calculation. + virtual FunctionID registerFunction(uint8_t _args, uint8_t _rets, bool _nonReturning) = 0; /// Selects a function as a target for newly appended instructions. /// May only be called after the main code section is already filled and /// must not be called when another function is already selected. diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index d9cf47f4d..b608859e2 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -145,9 +145,9 @@ std::pair, AbstractAssembly::SubID> EthAssembl return {std::make_shared(*assembly), static_cast(sub.data())}; } -AbstractAssembly::FunctionID EthAssemblyAdapter::registerFunction(uint8_t _args, uint8_t _rets) +AbstractAssembly::FunctionID EthAssemblyAdapter::registerFunction(uint8_t _args, uint8_t _rets, bool _nonReturning) { - return m_assembly.createFunction(_args, _rets); + return m_assembly.createFunction(_args, _rets, _nonReturning); } void EthAssemblyAdapter::beginFunction(AbstractAssembly::FunctionID _functionID) diff --git a/libyul/backends/evm/EthAssemblyAdapter.h b/libyul/backends/evm/EthAssemblyAdapter.h index 29a6fba7b..93e7c816a 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.h +++ b/libyul/backends/evm/EthAssemblyAdapter.h @@ -56,7 +56,7 @@ class EthAssemblyAdapter: public AbstractAssembly void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override; void appendAssemblySize() override; std::pair, SubID> createSubAssembly(bool _creation, std::string _name = {}) override; - AbstractAssembly::FunctionID registerFunction(uint8_t _args, uint8_t _rets) override; + AbstractAssembly::FunctionID registerFunction(uint8_t _args, uint8_t _rets, bool _nonReturning) override; void beginFunction(AbstractAssembly::FunctionID _functionID) override; void endFunction() override; void appendFunctionCall(FunctionID _functionID) override; diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index c9d6c6292..840372fca 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -120,11 +120,11 @@ std::pair, AbstractAssembly::SubID> NoOutputAs return {}; } -AbstractAssembly::FunctionID NoOutputAssembly::registerFunction(uint8_t _args, uint8_t _rets) +AbstractAssembly::FunctionID NoOutputAssembly::registerFunction(uint8_t _args, uint8_t _rets, bool) { yulAssert(m_context.numFunctions <= std::numeric_limits::max()); AbstractAssembly::FunctionID id = static_cast(m_context.numFunctions++); - m_context.functionSignatures[id] = std::make_pair(_args, _rets); + m_context.functionSignatures[id] = {_args, _rets}; return id; } @@ -139,8 +139,8 @@ void NoOutputAssembly::beginFunction(FunctionID _functionID) void NoOutputAssembly::endFunction() { yulAssert(m_currentFunctionID != 0, "End function without begin function."); - auto const rets = m_context.functionSignatures.at(m_currentFunctionID).second; - yulAssert(rets == 0x80 || m_stackHeight == rets, "Stack height mismatch at function end."); + auto const [_, rets] = m_context.functionSignatures.at(m_currentFunctionID); + yulAssert(m_stackHeight == rets, "Stack height mismatch at function end."); m_currentFunctionID = 0; } @@ -153,8 +153,8 @@ void NoOutputAssembly::appendFunctionCall(FunctionID _functionID) void NoOutputAssembly::appendFunctionReturn() { yulAssert(m_currentFunctionID != 0, "End function without begin function."); - auto const rets = m_context.functionSignatures.at(m_currentFunctionID).second; - yulAssert(rets == 0x80 || m_stackHeight == rets, "Stack height mismatch at function end."); + auto const [_, rets] = m_context.functionSignatures.at(m_currentFunctionID); + yulAssert(m_stackHeight == rets, "Stack height mismatch at function end."); } void NoOutputAssembly::appendDataOffset(std::vector const&) diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h index 2669a277c..64832b083 100644 --- a/libyul/backends/evm/NoOutputAssembly.h +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -73,7 +73,7 @@ class NoOutputAssembly: public AbstractAssembly void appendAssemblySize() override; std::pair, SubID> createSubAssembly(bool _creation, std::string _name = "") override; - FunctionID registerFunction(uint8_t _args, uint8_t _rets) override; + FunctionID registerFunction(uint8_t _args, uint8_t _rets, bool _nonReturning) override; void beginFunction(FunctionID) override; void endFunction() override; void appendFunctionCall(FunctionID _functionID) override; diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 3a1b78e1e..139df8af6 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -56,12 +56,12 @@ std::vector OptimizedEVMCodeTransform::run( for (Scope::Function const* function: dfg->functions) { auto const& info = dfg->functionInfo.at(function); - yulAssert(info.parameters.size() <= 0x7f); - yulAssert(info.returnVariables.size() <= 0x7f); - // According to EOF spec function output num equals 0x80 means non-returning function + yulAssert(info.parameters.size() <= std::numeric_limits::max()); + yulAssert(info.returnVariables.size() <= std::numeric_limits::max()); auto functionID = _assembly.registerFunction( static_cast(info.parameters.size()), - static_cast(info.canContinue ? info.returnVariables.size() : 0x80) + static_cast(info.returnVariables.size()), + !info.canContinue ); _builtinContext.functionIDs[function] = functionID; } @@ -128,8 +128,6 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call) for (size_t i = 0; i < _call.function.get().numArguments + (useReturnLabel ? 1 : 0); ++i) m_stack.pop_back(); // Push return values to m_stack. - if (!m_simulateFunctionsWithJumps) - yulAssert(_call.function.get().numReturns < 0x80, "Num of function output >= 128"); for (size_t index: ranges::views::iota(0u, _call.function.get().numReturns)) m_stack.emplace_back(TemporarySlot{_call.functionCall, index}); yulAssert(m_assembly.stackHeight() == static_cast(m_stack.size()), ""); diff --git a/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_in_modifiers.sol b/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_in_modifiers.sol index e050d2b52..bed3add8a 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_in_modifiers.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/inline_assembly_in_modifiers.sol @@ -27,6 +27,8 @@ contract C { return true; } } +// ==== +// bytecodeFormat: legacy,>=EOFv1 // ---- // f() -> true // g() -> FAILURE From e45133c77a6706e9aee829d56e17096d03ddaba6 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 13 Dec 2024 14:23:08 +0100 Subject: [PATCH 0567/1340] eof: Add `solAssert` checking that stack height does not go negative. --- libyul/backends/evm/NoOutputAssembly.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 840372fca..322191984 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -148,6 +148,7 @@ void NoOutputAssembly::appendFunctionCall(FunctionID _functionID) { auto [args, rets] = m_context.functionSignatures.at(_functionID); m_stackHeight += static_cast(rets) - static_cast(args); + solAssert(m_stackHeight >= 0); } void NoOutputAssembly::appendFunctionReturn() From 81f410fae40f1874539c73e91456df8e516e315a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 19 Dec 2024 10:13:00 +0100 Subject: [PATCH 0568/1340] SSACFG liveness: add conditional jump values to live set --- libyul/backends/evm/SSACFGLiveness.cpp | 22 +++++- .../standard_yul_cfg_json_export/output.json | 70 +++++++++++++------ .../strict_asm_yul_cfg_json_export/output | 15 ++-- test/cmdlineTests/yul_cfg_json_export/output | 70 +++++++++++++------ .../libyul/yulSSAControlFlowGraph/complex.yul | 14 ++-- .../yulSSAControlFlowGraph/complex2.yul | 14 ++-- .../yulSSAControlFlowGraph/nested_for.yul | 10 +-- .../nested_function.yul | 4 +- test/libyul/yulSSAControlFlowGraph/switch.yul | 4 +- 9 files changed, 146 insertions(+), 77 deletions(-) diff --git a/libyul/backends/evm/SSACFGLiveness.cpp b/libyul/backends/evm/SSACFGLiveness.cpp index 4537c8c5d..6ecd559ca 100644 --- a/libyul/backends/evm/SSACFGLiveness.cpp +++ b/libyul/backends/evm/SSACFGLiveness.cpp @@ -18,6 +18,8 @@ #include +#include + #include #include #include @@ -87,9 +89,23 @@ void SSACFGLiveness::runDagDfs() if (!m_topologicalSort.backEdge(blockId, _successor)) live += m_liveIns[_successor.value] - m_cfg.block(_successor).phis; }); - if (std::holds_alternative(block.exit)) - live += std::get(block.exit).returnValues - | ranges::views::filter(literalsFilter(m_cfg)); + util::GenericVisitor exitVisitor { + [](SSACFG::BasicBlock::MainExit const&) {}, + [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { + live += _functionReturn.returnValues | ranges::views::filter(literalsFilter(m_cfg)); + }, + [&](SSACFG::BasicBlock::JumpTable const& _jt) { + if (literalsFilter(m_cfg)(_jt.value)) + live.emplace(_jt.value); + }, + [](SSACFG::BasicBlock::Jump const&) {}, + [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { + if (literalsFilter(m_cfg)(_conditionalJump.condition)) + live.emplace(_conditionalJump.condition); + }, + [](SSACFG::BasicBlock::Terminated const&) {} + }; + std::visit(exitVisitor, block.exit); // clean out unreachables live = live | ranges::views::filter([&](auto const& valueId) { return !std::holds_alternative(m_cfg.valueInfo(valueId)); }) | ranges::to; diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index fc47f4f7b..bb13b3e91 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -45,7 +45,8 @@ "liveness": { "in": [], "out": [ - "v0" + "v0", + "v2" ] }, "type": "BuiltinCall" @@ -188,7 +189,8 @@ "liveness": { "in": [], "out": [ - "v0" + "v0", + "v5" ] }, "type": "BuiltinCall" @@ -260,7 +262,8 @@ "v0" ], "out": [ - "v0" + "v0", + "v11" ] }, "type": "BuiltinCall" @@ -303,7 +306,8 @@ "v0" ], "out": [ - "v0" + "v0", + "v12" ] }, "type": "BuiltinCall" @@ -361,7 +365,8 @@ "v0" ], "out": [ - "v0" + "v0", + "v17" ] }, "type": "BuiltinCall" @@ -492,7 +497,8 @@ "liveness": { "in": [], "out": [ - "v0" + "v0", + "v2" ] }, "type": "BuiltinCall" @@ -635,7 +641,8 @@ "liveness": { "in": [], "out": [ - "v0" + "v0", + "v5" ] }, "type": "BuiltinCall" @@ -707,7 +714,8 @@ "v0" ], "out": [ - "v0" + "v0", + "v11" ] }, "type": "BuiltinCall" @@ -750,7 +758,8 @@ "v0" ], "out": [ - "v0" + "v0", + "v12" ] }, "type": "BuiltinCall" @@ -808,7 +817,8 @@ "v0" ], "out": [ - "v0" + "v0", + "v17" ] }, "type": "BuiltinCall" @@ -903,7 +913,8 @@ "out": [ "v0", "v18", - "v24" + "v24", + "v28" ] }, "type": "BuiltinCall" @@ -997,7 +1008,8 @@ "v24" ], "out": [ - "v41" + "v41", + "v42" ] }, "type": "BuiltinCall" @@ -1153,7 +1165,9 @@ "v41" ], "out": [ - "v46" + "v46", + "v59", + "v60" ] }, "type": "BuiltinCall" @@ -1224,10 +1238,12 @@ "instructions": [], "liveness": { "in": [ - "v46" + "v46", + "v59" ], "out": [ - "v46" + "v46", + "v59" ] } }, @@ -1372,7 +1388,8 @@ "v46" ], "out": [ - "v46" + "v46", + "v67" ] }, "type": "BuiltinCall" @@ -1480,7 +1497,8 @@ "out": [ "v46", "v71", - "v77" + "v77", + "v80" ] }, "type": "BuiltinCall" @@ -1570,7 +1588,8 @@ "v77" ], "out": [ - "v46" + "v46", + "v90" ] }, "type": "BuiltinCall" @@ -1718,7 +1737,8 @@ "liveness": { "in": [], "out": [ - "v0" + "v0", + "v2" ] }, "type": "BuiltinCall" @@ -1861,7 +1881,8 @@ "liveness": { "in": [], "out": [ - "v0" + "v0", + "v5" ] }, "type": "BuiltinCall" @@ -1933,7 +1954,8 @@ "v0" ], "out": [ - "v0" + "v0", + "v11" ] }, "type": "BuiltinCall" @@ -1976,7 +1998,8 @@ "v0" ], "out": [ - "v0" + "v0", + "v12" ] }, "type": "BuiltinCall" @@ -2034,7 +2057,8 @@ "v0" ], "out": [ - "v0" + "v0", + "v17" ] }, "type": "BuiltinCall" diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output index ac154fc16..a65c164d6 100644 --- a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -45,7 +45,8 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0" + "v0", + "v2" ] }, "type": "BuiltinCall" @@ -188,7 +189,8 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0" + "v0", + "v5" ] }, "type": "BuiltinCall" @@ -260,7 +262,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v11" ] }, "type": "BuiltinCall" @@ -303,7 +306,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v12" ] }, "type": "BuiltinCall" @@ -361,7 +365,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v17" ] }, "type": "BuiltinCall" diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index 6848d7db9..f6f2ec6d8 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -44,7 +44,8 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0" + "v0", + "v2" ] }, "type": "BuiltinCall" @@ -187,7 +188,8 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0" + "v0", + "v5" ] }, "type": "BuiltinCall" @@ -259,7 +261,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v11" ] }, "type": "BuiltinCall" @@ -302,7 +305,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v12" ] }, "type": "BuiltinCall" @@ -360,7 +364,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v17" ] }, "type": "BuiltinCall" @@ -492,7 +497,8 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0" + "v0", + "v2" ] }, "type": "BuiltinCall" @@ -635,7 +641,8 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0" + "v0", + "v5" ] }, "type": "BuiltinCall" @@ -707,7 +714,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v11" ] }, "type": "BuiltinCall" @@ -750,7 +758,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v12" ] }, "type": "BuiltinCall" @@ -808,7 +817,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v17" ] }, "type": "BuiltinCall" @@ -903,7 +913,8 @@ Yul Control Flow Graph: "out": [ "v0", "v18", - "v24" + "v24", + "v28" ] }, "type": "BuiltinCall" @@ -997,7 +1008,8 @@ Yul Control Flow Graph: "v24" ], "out": [ - "v41" + "v41", + "v42" ] }, "type": "BuiltinCall" @@ -1153,7 +1165,9 @@ Yul Control Flow Graph: "v41" ], "out": [ - "v46" + "v46", + "v59", + "v60" ] }, "type": "BuiltinCall" @@ -1224,10 +1238,12 @@ Yul Control Flow Graph: "instructions": [], "liveness": { "in": [ - "v46" + "v46", + "v59" ], "out": [ - "v46" + "v46", + "v59" ] } }, @@ -1372,7 +1388,8 @@ Yul Control Flow Graph: "v46" ], "out": [ - "v46" + "v46", + "v67" ] }, "type": "BuiltinCall" @@ -1480,7 +1497,8 @@ Yul Control Flow Graph: "out": [ "v46", "v71", - "v77" + "v77", + "v80" ] }, "type": "BuiltinCall" @@ -1570,7 +1588,8 @@ Yul Control Flow Graph: "v77" ], "out": [ - "v46" + "v46", + "v90" ] }, "type": "BuiltinCall" @@ -1718,7 +1737,8 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0" + "v0", + "v2" ] }, "type": "BuiltinCall" @@ -1861,7 +1881,8 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0" + "v0", + "v5" ] }, "type": "BuiltinCall" @@ -1933,7 +1954,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v11" ] }, "type": "BuiltinCall" @@ -1976,7 +1998,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v12" ] }, "type": "BuiltinCall" @@ -2034,7 +2057,8 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0" + "v0", + "v17" ] }, "type": "BuiltinCall" diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index 6fb0453c1..3f7f329a4 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -69,7 +69,7 @@ // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ // Block 1; (1, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nv5 := φ(\l\ +// LiveOut: v0,v1,v5,v6\l\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ // )\l\ @@ -81,7 +81,7 @@ // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ // Block 2; (2, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ +// LiveOut: v0,v1,v5,v7,v8\l\nv7 := mload(v5)\l\ // v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; @@ -103,7 +103,7 @@ // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ // Block 7; (5, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ +// LiveOut: v0,v1,v5,v7,v13\l\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; // Block1_7Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -117,7 +117,7 @@ // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ // Block 10; (7, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ +// LiveOut: v0,v1,v5,v7,v20\l\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; // Block1_10Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -132,7 +132,7 @@ // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ // Block 13; (9, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ +// LiveOut: v0,v1,v5,v25\l\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; // Block1_13Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -147,7 +147,7 @@ // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ // Block 16; (15, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ +// LiveOut: v0,v1,v5,v29\l\nv29 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; // Block1_16Exit [label="{ If v29 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -175,7 +175,7 @@ // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ // Block 3; (12, max 14)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ +// LiveOut: v0,v1,v43,v44\l\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index c3ea8b94f..6d801124c 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -85,7 +85,7 @@ // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ // Block 1; (1, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nv5 := φ(\l\ +// LiveOut: v0,v1,v5,v6\l\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ // )\l\ @@ -97,7 +97,7 @@ // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ // Block 2; (2, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ +// LiveOut: v0,v1,v5,v7,v8\l\nv7 := mload(v5)\l\ // v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; @@ -119,7 +119,7 @@ // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ // Block 7; (5, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ +// LiveOut: v0,v1,v5,v7,v13\l\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; // Block1_7Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -133,7 +133,7 @@ // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ // Block 10; (7, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ +// LiveOut: v0,v1,v5,v7,v20\l\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; // Block1_10Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -148,7 +148,7 @@ // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ // Block 13; (9, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ +// LiveOut: v0,v1,v5,v25\l\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; // Block1_13Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -163,7 +163,7 @@ // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ // Block 16; (15, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ +// LiveOut: v0,v1,v5,v29\l\nv29 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; // Block1_16Exit [label="{ If v29 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -191,7 +191,7 @@ // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ // Block 3; (12, max 14)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ +// LiveOut: v0,v1,v43,v44\l\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/yulSSAControlFlowGraph/nested_for.yul index b088e3b55..f816df462 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_for.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_for.yul @@ -33,7 +33,7 @@ // Block0_0Exit -> Block0_1 [style="solid"]; // Block0_1 [label="\ // Block 1; (1, max 24)\nLiveIn: v2\l\ -// LiveOut: v2\l\nv2 := φ(\l\ +// LiveOut: v2,v3\l\nv2 := φ(\l\ // Block 0 => 0,\l\ // Block 3 => v36\l\ // )\l\ @@ -56,7 +56,7 @@ // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ // Block 5; (3, max 23)\nLiveIn: v2,v4\l\ -// LiveOut: v2,v4\l\nv4 := φ(\l\ +// LiveOut: v2,v4,v5\l\nv4 := φ(\l\ // Block 2 => 0,\l\ // Block 7 => v35\l\ // )\l\ @@ -80,7 +80,7 @@ // Block0_8Exit -> Block0_3 [style="solid"]; // Block0_9 [label="\ // Block 9; (5, max 21)\nLiveIn: v2,v4,v6\l\ -// LiveOut: v2,v4,v6\l\nv6 := φ(\l\ +// LiveOut: v2,v4,v6,v7\l\nv6 := φ(\l\ // Block 6 => 0,\l\ // Block 11 => v31\l\ // )\l\ @@ -132,7 +132,7 @@ // Block0_7Exit -> Block0_5 [style="dashed"]; // Block0_15 [label="\ // Block 15; (8, max 19)\nLiveIn: v2,v4,v6,v8\l\ -// LiveOut: v2,v4,v6,v8\l\nv8 := φ(\l\ +// LiveOut: v2,v4,v6,v8,v9\l\nv8 := φ(\l\ // Block 13 => 0,\l\ // Block 17 => v16\l\ // )\l\ @@ -171,7 +171,7 @@ // Block0_18Exit -> Block0_14 [style="solid"]; // Block0_21 [label="\ // Block 21; (14, max 19)\nLiveIn: v2,v4,v6,v19\l\ -// LiveOut: v2,v4,v6,v19\l\nv19 := φ(\l\ +// LiveOut: v2,v4,v6,v19,v20\l\nv19 := φ(\l\ // Block 19 => 0,\l\ // Block 23 => v26\l\ // )\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/nested_function.yul b/test/libyul/yulSSAControlFlowGraph/nested_function.yul index acda15ce8..1263d4782 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_function.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_function.yul @@ -103,7 +103,7 @@ // FunctionEntry_cycle1_0 -> Block7_0; // Block7_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: \l\nv2 := mload(3)\l\ +// LiveOut: v2\l\nv2 := mload(3)\l\ // "]; // Block7_0 -> Block7_0Exit; // Block7_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -130,7 +130,7 @@ // FunctionEntry_cycle2_0 -> Block8_0; // Block8_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: \l\nv2 := mload(4)\l\ +// LiveOut: v2\l\nv2 := mload(4)\l\ // "]; // Block8_0 -> Block8_0Exit; // Block8_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; diff --git a/test/libyul/yulSSAControlFlowGraph/switch.yul b/test/libyul/yulSSAControlFlowGraph/switch.yul index 10573b012..91b3daeee 100644 --- a/test/libyul/yulSSAControlFlowGraph/switch.yul +++ b/test/libyul/yulSSAControlFlowGraph/switch.yul @@ -23,7 +23,7 @@ // Entry0 -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 5)\nLiveIn: \l\ -// LiveOut: v3\l\nv1 := calldataload(3)\l\ +// LiveOut: v3,v4\l\nv1 := calldataload(3)\l\ // v3 := sload(0)\l\ // v4 := eq(0, v3)\l\ // "]; @@ -40,7 +40,7 @@ // Block0_2Exit -> Block0_1 [style="solid"]; // Block0_3 [label="\ // Block 3; (3, max 5)\nLiveIn: v3\l\ -// LiveOut: \l\nv7 := eq(1, v3)\l\ +// LiveOut: v7\l\nv7 := eq(1, v3)\l\ // "]; // Block0_3 -> Block0_3Exit; // Block0_3Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; From d2e468cb735f1c35f1a28d4cf6e560028892479e Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 19 Dec 2024 16:51:50 +0200 Subject: [PATCH 0569/1340] Remove unused expression annotation Remove the unused lValueOfOrdinaryAssignment expression annotation. --- libsolidity/analysis/TypeChecker.cpp | 15 ++++----------- libsolidity/analysis/TypeChecker.h | 2 +- libsolidity/ast/ASTAnnotations.h | 4 ---- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 4264bf71d..b461fa283 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1454,10 +1454,7 @@ void TypeChecker::checkExpressionAssignment(Type const& _type, Expression const& bool TypeChecker::visit(Assignment const& _assignment) { - requireLValue( - _assignment.leftHandSide(), - _assignment.assignmentOperator() == Token::Assign - ); + requireLValue(_assignment.leftHandSide()); Type const* t = type(_assignment.leftHandSide()); _assignment.annotation().type = t; _assignment.annotation().isPure = false; @@ -1518,10 +1515,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple) for (auto const& component: components) if (component) { - requireLValue( - *component, - _tuple.annotation().lValueOfOrdinaryAssignment - ); + requireLValue(*component); types.push_back(type(*component)); } else @@ -1614,7 +1608,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation) Token op = _operation.getOperator(); bool const modifying = (op == Token::Inc || op == Token::Dec || op == Token::Delete); if (modifying) - requireLValue(_operation.subExpression(), false); + requireLValue(_operation.subExpression()); else _operation.subExpression().accept(*this); Type const* operandType = type(_operation.subExpression()); @@ -4137,10 +4131,9 @@ bool TypeChecker::expectType(Expression const& _expression, Type const& _expecte return true; } -void TypeChecker::requireLValue(Expression const& _expression, bool _ordinaryAssignment) +void TypeChecker::requireLValue(Expression const& _expression) { _expression.annotation().willBeWrittenTo = true; - _expression.annotation().lValueOfOrdinaryAssignment = _ordinaryAssignment; _expression.accept(*this); if (*_expression.annotation().isLValue) diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index a517a750c..e4bc12705 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -175,7 +175,7 @@ class TypeChecker: private ASTConstVisitor /// convertible to @a _expectedType. bool expectType(Expression const& _expression, Type const& _expectedType); /// Runs type checks on @a _expression to infer its type and then checks that it is an LValue. - void requireLValue(Expression const& _expression, bool _ordinaryAssignment); + void requireLValue(Expression const& _expression); bool useABICoderV2() const; diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index f017481be..3f817b180 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -279,10 +279,6 @@ struct ExpressionAnnotation: ASTAnnotation util::SetOnce isLValue; /// Whether the expression is used in a context where the LValue is actually required. bool willBeWrittenTo = false; - /// Whether the expression is an lvalue that is only assigned. - /// Would be false for --, ++, delete, +=, -=, .... - /// Only relevant if isLvalue == true - bool lValueOfOrdinaryAssignment = false; /// Types and - if given - names of arguments if the expr. is a function /// that is called, used for overload resolution From 749f64c807af480b6d4e6859493381cabd1b2077 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 16 Dec 2024 19:59:01 +0100 Subject: [PATCH 0570/1340] eof: Add EOF enabled predicate to BOOST tests. --- test/Common.cpp | 7 +++++++ test/Common.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/test/Common.cpp b/test/Common.cpp index 43f73d4d7..30738dcfc 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -302,6 +302,13 @@ bool isValidSemanticTestPath(boost::filesystem::path const& _testPath) return true; } +boost::unit_test::precondition::predicate_t nonEOF() +{ + return [](boost::unit_test::test_unit_id) { + return !solidity::test::CommonOptions::get().eofVersion().has_value(); + }; +} + boost::unit_test::precondition::predicate_t minEVMVersionCheck(langutil::EVMVersion _minEVMVersion) { return [_minEVMVersion](boost::unit_test::test_unit_id) { diff --git a/test/Common.h b/test/Common.h index c3d21d258..866f6945a 100644 --- a/test/Common.h +++ b/test/Common.h @@ -112,6 +112,10 @@ bool isValidSemanticTestPath(boost::filesystem::path const& _testPath); /// @return A predicate (function) that can be passed into @a boost::unit_test::precondition(). boost::unit_test::precondition::predicate_t minEVMVersionCheck(langutil::EVMVersion _minEVMVersion); +/// Helper that can be used to skip tests when the EOF is not supported by the test case. +/// @return A predicate (function) that can be passed into @a boost::unit_test::precondition(). +boost::unit_test::precondition::predicate_t nonEOF(); + bool loadVMs(CommonOptions const& _options); /** From 53c6abc7fcf2b0cef8a75baace1369d375eca3bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 4 Dec 2024 01:31:06 +0100 Subject: [PATCH 0571/1340] Fix typos in a couple of Yul test names --- .../{long_obect_name.yul => long_object_name.yul} | 0 .../{call_intruction_in_eof.yul => call_instruction_in_eof.yul} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/libyul/yulInterpreterTests/{long_obect_name.yul => long_object_name.yul} (100%) rename test/libyul/yulSyntaxTests/eof/{call_intruction_in_eof.yul => call_instruction_in_eof.yul} (100%) diff --git a/test/libyul/yulInterpreterTests/long_obect_name.yul b/test/libyul/yulInterpreterTests/long_object_name.yul similarity index 100% rename from test/libyul/yulInterpreterTests/long_obect_name.yul rename to test/libyul/yulInterpreterTests/long_object_name.yul diff --git a/test/libyul/yulSyntaxTests/eof/call_intruction_in_eof.yul b/test/libyul/yulSyntaxTests/eof/call_instruction_in_eof.yul similarity index 100% rename from test/libyul/yulSyntaxTests/eof/call_intruction_in_eof.yul rename to test/libyul/yulSyntaxTests/eof/call_instruction_in_eof.yul From 715573aa379ab1a268fc8fedbc7861d15fccd095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 4 Dec 2024 03:42:34 +0100 Subject: [PATCH 0572/1340] More accurate unimplemented message for assembly import on EOF --- libevmasm/Assembly.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 001865b2c..17c4ee10e 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -90,7 +90,7 @@ void Assembly::importAssemblyItemsFromJSON(Json const& _code, std::vector const& _sourceIndice Json root; root[".code"] = Json::array(); Json& code = root[".code"]; - // TODO: support EOF + // TODO: support EOF solUnimplementedAssert(!m_eofVersion.has_value(), "Assembly output for EOF is not yet implemented."); solAssert(m_codeSections.size() == 1); for (AssemblyItem const& item: m_codeSections.front().items) From bb9d694a6a6ef18947d17bd914af800b60c7e652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 19 Dec 2024 16:33:40 +0100 Subject: [PATCH 0573/1340] Assembly: Fix check for the maximum size of the EOF data section --- libevmasm/Assembly.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 17c4ee10e..430124e2a 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1683,8 +1683,12 @@ LinkerObject const& Assembly::assembleEOF() const // DATALOADN loads 32 bytes from EOF data section zero padded if reading out of data bounds. // In our case we do not allow DATALOADN with offsets which reads out of data bounds. auto const staticAuxDataSize = maxAuxDataLoadNOffset.has_value() ? (*maxAuxDataLoadNOffset + 32u) : 0u; - solRequire(preDeployDataSectionSize + staticAuxDataSize < std::numeric_limits::max(), AssemblyException, - "Invalid DATALOADN offset."); + auto const preDeployAndStaticAuxDataSize = preDeployDataSectionSize + staticAuxDataSize; + solRequire( + preDeployAndStaticAuxDataSize <= std::numeric_limits::max(), + AssemblyException, + "Invalid DATALOADN offset." + ); // If some data was already added to data section we need to update data section refs accordingly if (preDeployDataSectionSize > 0) @@ -1695,8 +1699,6 @@ LinkerObject const& Assembly::assembleEOF() const setBigEndianUint16(ret.bytecode, refPosition, staticAuxDataOffset + preDeployDataSectionSize); } - auto const preDeployAndStaticAuxDataSize = preDeployDataSectionSize + staticAuxDataSize; - setBigEndianUint16(ret.bytecode, dataSectionSizePosition, preDeployAndStaticAuxDataSize); return ret; From b639134f3a87e2b3701889cae7ead1ff48ca41a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 30 Nov 2024 04:00:48 +0100 Subject: [PATCH 0574/1340] Assemble Yul in syntax tests so that CodeGenerationErrors can be tested --- test/libyul/SyntaxTest.cpp | 6 ++++++ .../loadimmutable_without_setimmutable.yul | 11 +++++++++++ 2 files changed, 17 insertions(+) create mode 100644 test/libyul/yulSyntaxTests/loadimmutable_without_setimmutable.yul diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index 70f54b86a..88046c02f 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -41,6 +41,12 @@ void SyntaxTest::parseAndAnalyze() auto const& [sourceUnitName, source] = *m_sources.sources.begin(); YulStack yulStack = parseYul(source); + if (!yulStack.hasErrors()) + { + // Assemble the object so that we can test CodeGenerationErrors too. + yulStack.optimize(); + yulStack.assemble(YulStack::Machine::EVM); + } for (auto const& error: yulStack.errors()) { int locationStart = -1; diff --git a/test/libyul/yulSyntaxTests/loadimmutable_without_setimmutable.yul b/test/libyul/yulSyntaxTests/loadimmutable_without_setimmutable.yul new file mode 100644 index 000000000..8695e938d --- /dev/null +++ b/test/libyul/yulSyntaxTests/loadimmutable_without_setimmutable.yul @@ -0,0 +1,11 @@ +object "C" { + code {} + + object "C_deployed" { + code { + sstore(0, loadimmutable("1")) + } + } +} +// ---- +// CodeGenerationError 1284: Some immutables were read from but never assigned, possibly because of optimization. From ba19d3ff3309ff4e1af740758438169a9eb92076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 30 Nov 2024 03:21:24 +0100 Subject: [PATCH 0575/1340] Throw CodeGenerationError in two cases where we can't generate bytecode due to EOF limits --- libevmasm/Assembly.cpp | 20 +- .../auxdataloadn_in_eof_offset_too_high.yul | 13 + .../eof/too_large_code_section.yul | 1880 +++++++++++++++++ 3 files changed, 1908 insertions(+), 5 deletions(-) create mode 100644 test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_offset_too_high.yul create mode 100644 test/libyul/yulSyntaxTests/eof/too_large_code_section.yul diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 430124e2a..1cd3e11fa 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1642,6 +1642,14 @@ LinkerObject const& Assembly::assembleEOF() const } } + if (ret.bytecode.size() - sectionStart > std::numeric_limits::max()) + // TODO: Include source location. Note that origin locations we have in debug data are + // not usable for error reporting when compiling pure Yul because they point at the optimized source. + throw Error( + 2202_error, + Error::Type::CodeGenerationError, + "Code section too large for EOF." + ); setBigEndianUint16(ret.bytecode, codeSectionSizePositions[codeSectionIndex], ret.bytecode.size() - sectionStart); } @@ -1684,11 +1692,13 @@ LinkerObject const& Assembly::assembleEOF() const // In our case we do not allow DATALOADN with offsets which reads out of data bounds. auto const staticAuxDataSize = maxAuxDataLoadNOffset.has_value() ? (*maxAuxDataLoadNOffset + 32u) : 0u; auto const preDeployAndStaticAuxDataSize = preDeployDataSectionSize + staticAuxDataSize; - solRequire( - preDeployAndStaticAuxDataSize <= std::numeric_limits::max(), - AssemblyException, - "Invalid DATALOADN offset." - ); + + if (preDeployAndStaticAuxDataSize > std::numeric_limits::max()) + throw Error( + 3965_error, + Error::Type::CodeGenerationError, + "The highest accessed data offset exceeds the maximum possible size of the static auxdata section." + ); // If some data was already added to data section we need to update data section refs accordingly if (preDeployDataSectionSize > 0) diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_offset_too_high.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_offset_too_high.yul new file mode 100644 index 000000000..1d163c232 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_offset_too_high.yul @@ -0,0 +1,13 @@ +object "a" { + code { + { + mstore(0, auxdataloadn(0xffe0)) + return(0, 32) + } + } + data "data1" hex"48656c6c6f2c20576f726c6421" +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// CodeGenerationError 3965: The highest accessed data offset exceeds the maximum possible size of the static auxdata section. diff --git a/test/libyul/yulSyntaxTests/eof/too_large_code_section.yul b/test/libyul/yulSyntaxTests/eof/too_large_code_section.yul new file mode 100644 index 000000000..ce69a69a5 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/too_large_code_section.yul @@ -0,0 +1,1880 @@ +{ + sstore("112233445566778899aabbccddee0000", "112233445566778899aabbccddee0000") + sstore("112233445566778899aabbccddee0001", "112233445566778899aabbccddee0001") + sstore("112233445566778899aabbccddee0002", "112233445566778899aabbccddee0002") + sstore("112233445566778899aabbccddee0003", "112233445566778899aabbccddee0003") + sstore("112233445566778899aabbccddee0004", "112233445566778899aabbccddee0004") + sstore("112233445566778899aabbccddee0005", "112233445566778899aabbccddee0005") + sstore("112233445566778899aabbccddee0006", "112233445566778899aabbccddee0006") + sstore("112233445566778899aabbccddee0007", "112233445566778899aabbccddee0007") + sstore("112233445566778899aabbccddee0008", "112233445566778899aabbccddee0008") + sstore("112233445566778899aabbccddee0009", "112233445566778899aabbccddee0009") + sstore("112233445566778899aabbccddee000a", "112233445566778899aabbccddee000a") + sstore("112233445566778899aabbccddee000b", "112233445566778899aabbccddee000b") + sstore("112233445566778899aabbccddee000c", "112233445566778899aabbccddee000c") + sstore("112233445566778899aabbccddee000d", "112233445566778899aabbccddee000d") + sstore("112233445566778899aabbccddee000e", "112233445566778899aabbccddee000e") + sstore("112233445566778899aabbccddee000f", "112233445566778899aabbccddee000f") + sstore("112233445566778899aabbccddee0010", "112233445566778899aabbccddee0010") + sstore("112233445566778899aabbccddee0011", "112233445566778899aabbccddee0011") + sstore("112233445566778899aabbccddee0012", "112233445566778899aabbccddee0012") + sstore("112233445566778899aabbccddee0013", "112233445566778899aabbccddee0013") + sstore("112233445566778899aabbccddee0014", "112233445566778899aabbccddee0014") + sstore("112233445566778899aabbccddee0015", "112233445566778899aabbccddee0015") + sstore("112233445566778899aabbccddee0016", "112233445566778899aabbccddee0016") + sstore("112233445566778899aabbccddee0017", "112233445566778899aabbccddee0017") + sstore("112233445566778899aabbccddee0018", "112233445566778899aabbccddee0018") + sstore("112233445566778899aabbccddee0019", "112233445566778899aabbccddee0019") + sstore("112233445566778899aabbccddee001a", "112233445566778899aabbccddee001a") + sstore("112233445566778899aabbccddee001b", "112233445566778899aabbccddee001b") + sstore("112233445566778899aabbccddee001c", "112233445566778899aabbccddee001c") + sstore("112233445566778899aabbccddee001d", "112233445566778899aabbccddee001d") + sstore("112233445566778899aabbccddee001e", "112233445566778899aabbccddee001e") + sstore("112233445566778899aabbccddee001f", "112233445566778899aabbccddee001f") + sstore("112233445566778899aabbccddee0020", "112233445566778899aabbccddee0020") + sstore("112233445566778899aabbccddee0021", "112233445566778899aabbccddee0021") + sstore("112233445566778899aabbccddee0022", "112233445566778899aabbccddee0022") + sstore("112233445566778899aabbccddee0023", "112233445566778899aabbccddee0023") + sstore("112233445566778899aabbccddee0024", "112233445566778899aabbccddee0024") + sstore("112233445566778899aabbccddee0025", "112233445566778899aabbccddee0025") + sstore("112233445566778899aabbccddee0026", "112233445566778899aabbccddee0026") + sstore("112233445566778899aabbccddee0027", "112233445566778899aabbccddee0027") + sstore("112233445566778899aabbccddee0028", "112233445566778899aabbccddee0028") + sstore("112233445566778899aabbccddee0029", "112233445566778899aabbccddee0029") + sstore("112233445566778899aabbccddee002a", "112233445566778899aabbccddee002a") + sstore("112233445566778899aabbccddee002b", "112233445566778899aabbccddee002b") + sstore("112233445566778899aabbccddee002c", "112233445566778899aabbccddee002c") + sstore("112233445566778899aabbccddee002d", "112233445566778899aabbccddee002d") + sstore("112233445566778899aabbccddee002e", "112233445566778899aabbccddee002e") + sstore("112233445566778899aabbccddee002f", "112233445566778899aabbccddee002f") + sstore("112233445566778899aabbccddee0030", "112233445566778899aabbccddee0030") + sstore("112233445566778899aabbccddee0031", "112233445566778899aabbccddee0031") + sstore("112233445566778899aabbccddee0032", "112233445566778899aabbccddee0032") + sstore("112233445566778899aabbccddee0033", "112233445566778899aabbccddee0033") + sstore("112233445566778899aabbccddee0034", "112233445566778899aabbccddee0034") + sstore("112233445566778899aabbccddee0035", "112233445566778899aabbccddee0035") + sstore("112233445566778899aabbccddee0036", "112233445566778899aabbccddee0036") + sstore("112233445566778899aabbccddee0037", "112233445566778899aabbccddee0037") + sstore("112233445566778899aabbccddee0038", "112233445566778899aabbccddee0038") + sstore("112233445566778899aabbccddee0039", "112233445566778899aabbccddee0039") + sstore("112233445566778899aabbccddee003a", "112233445566778899aabbccddee003a") + sstore("112233445566778899aabbccddee003b", "112233445566778899aabbccddee003b") + sstore("112233445566778899aabbccddee003c", "112233445566778899aabbccddee003c") + sstore("112233445566778899aabbccddee003d", "112233445566778899aabbccddee003d") + sstore("112233445566778899aabbccddee003e", "112233445566778899aabbccddee003e") + sstore("112233445566778899aabbccddee003f", "112233445566778899aabbccddee003f") + sstore("112233445566778899aabbccddee0040", "112233445566778899aabbccddee0040") + sstore("112233445566778899aabbccddee0041", "112233445566778899aabbccddee0041") + sstore("112233445566778899aabbccddee0042", "112233445566778899aabbccddee0042") + sstore("112233445566778899aabbccddee0043", "112233445566778899aabbccddee0043") + sstore("112233445566778899aabbccddee0044", "112233445566778899aabbccddee0044") + sstore("112233445566778899aabbccddee0045", "112233445566778899aabbccddee0045") + sstore("112233445566778899aabbccddee0046", "112233445566778899aabbccddee0046") + sstore("112233445566778899aabbccddee0047", "112233445566778899aabbccddee0047") + sstore("112233445566778899aabbccddee0048", "112233445566778899aabbccddee0048") + sstore("112233445566778899aabbccddee0049", "112233445566778899aabbccddee0049") + sstore("112233445566778899aabbccddee004a", "112233445566778899aabbccddee004a") + sstore("112233445566778899aabbccddee004b", "112233445566778899aabbccddee004b") + sstore("112233445566778899aabbccddee004c", "112233445566778899aabbccddee004c") + sstore("112233445566778899aabbccddee004d", "112233445566778899aabbccddee004d") + sstore("112233445566778899aabbccddee004e", "112233445566778899aabbccddee004e") + sstore("112233445566778899aabbccddee004f", "112233445566778899aabbccddee004f") + sstore("112233445566778899aabbccddee0050", "112233445566778899aabbccddee0050") + sstore("112233445566778899aabbccddee0051", "112233445566778899aabbccddee0051") + sstore("112233445566778899aabbccddee0052", "112233445566778899aabbccddee0052") + sstore("112233445566778899aabbccddee0053", "112233445566778899aabbccddee0053") + sstore("112233445566778899aabbccddee0054", "112233445566778899aabbccddee0054") + sstore("112233445566778899aabbccddee0055", "112233445566778899aabbccddee0055") + sstore("112233445566778899aabbccddee0056", "112233445566778899aabbccddee0056") + sstore("112233445566778899aabbccddee0057", "112233445566778899aabbccddee0057") + sstore("112233445566778899aabbccddee0058", "112233445566778899aabbccddee0058") + sstore("112233445566778899aabbccddee0059", "112233445566778899aabbccddee0059") + sstore("112233445566778899aabbccddee005a", "112233445566778899aabbccddee005a") + sstore("112233445566778899aabbccddee005b", "112233445566778899aabbccddee005b") + sstore("112233445566778899aabbccddee005c", "112233445566778899aabbccddee005c") + sstore("112233445566778899aabbccddee005d", "112233445566778899aabbccddee005d") + sstore("112233445566778899aabbccddee005e", "112233445566778899aabbccddee005e") + sstore("112233445566778899aabbccddee005f", "112233445566778899aabbccddee005f") + sstore("112233445566778899aabbccddee0060", "112233445566778899aabbccddee0060") + sstore("112233445566778899aabbccddee0061", "112233445566778899aabbccddee0061") + sstore("112233445566778899aabbccddee0062", "112233445566778899aabbccddee0062") + sstore("112233445566778899aabbccddee0063", "112233445566778899aabbccddee0063") + sstore("112233445566778899aabbccddee0064", "112233445566778899aabbccddee0064") + sstore("112233445566778899aabbccddee0065", "112233445566778899aabbccddee0065") + sstore("112233445566778899aabbccddee0066", "112233445566778899aabbccddee0066") + sstore("112233445566778899aabbccddee0067", "112233445566778899aabbccddee0067") + sstore("112233445566778899aabbccddee0068", "112233445566778899aabbccddee0068") + sstore("112233445566778899aabbccddee0069", "112233445566778899aabbccddee0069") + sstore("112233445566778899aabbccddee006a", "112233445566778899aabbccddee006a") + sstore("112233445566778899aabbccddee006b", "112233445566778899aabbccddee006b") + sstore("112233445566778899aabbccddee006c", "112233445566778899aabbccddee006c") + sstore("112233445566778899aabbccddee006d", "112233445566778899aabbccddee006d") + sstore("112233445566778899aabbccddee006e", "112233445566778899aabbccddee006e") + sstore("112233445566778899aabbccddee006f", "112233445566778899aabbccddee006f") + sstore("112233445566778899aabbccddee0070", "112233445566778899aabbccddee0070") + sstore("112233445566778899aabbccddee0071", "112233445566778899aabbccddee0071") + sstore("112233445566778899aabbccddee0072", "112233445566778899aabbccddee0072") + sstore("112233445566778899aabbccddee0073", "112233445566778899aabbccddee0073") + sstore("112233445566778899aabbccddee0074", "112233445566778899aabbccddee0074") + sstore("112233445566778899aabbccddee0075", "112233445566778899aabbccddee0075") + sstore("112233445566778899aabbccddee0076", "112233445566778899aabbccddee0076") + sstore("112233445566778899aabbccddee0077", "112233445566778899aabbccddee0077") + sstore("112233445566778899aabbccddee0078", "112233445566778899aabbccddee0078") + sstore("112233445566778899aabbccddee0079", "112233445566778899aabbccddee0079") + sstore("112233445566778899aabbccddee007a", "112233445566778899aabbccddee007a") + sstore("112233445566778899aabbccddee007b", "112233445566778899aabbccddee007b") + sstore("112233445566778899aabbccddee007c", "112233445566778899aabbccddee007c") + sstore("112233445566778899aabbccddee007d", "112233445566778899aabbccddee007d") + sstore("112233445566778899aabbccddee007e", "112233445566778899aabbccddee007e") + sstore("112233445566778899aabbccddee007f", "112233445566778899aabbccddee007f") + sstore("112233445566778899aabbccddee0080", "112233445566778899aabbccddee0080") + sstore("112233445566778899aabbccddee0081", "112233445566778899aabbccddee0081") + sstore("112233445566778899aabbccddee0082", "112233445566778899aabbccddee0082") + sstore("112233445566778899aabbccddee0083", "112233445566778899aabbccddee0083") + sstore("112233445566778899aabbccddee0084", "112233445566778899aabbccddee0084") + sstore("112233445566778899aabbccddee0085", "112233445566778899aabbccddee0085") + sstore("112233445566778899aabbccddee0086", "112233445566778899aabbccddee0086") + sstore("112233445566778899aabbccddee0087", "112233445566778899aabbccddee0087") + sstore("112233445566778899aabbccddee0088", "112233445566778899aabbccddee0088") + sstore("112233445566778899aabbccddee0089", "112233445566778899aabbccddee0089") + sstore("112233445566778899aabbccddee008a", "112233445566778899aabbccddee008a") + sstore("112233445566778899aabbccddee008b", "112233445566778899aabbccddee008b") + sstore("112233445566778899aabbccddee008c", "112233445566778899aabbccddee008c") + sstore("112233445566778899aabbccddee008d", "112233445566778899aabbccddee008d") + sstore("112233445566778899aabbccddee008e", "112233445566778899aabbccddee008e") + sstore("112233445566778899aabbccddee008f", "112233445566778899aabbccddee008f") + sstore("112233445566778899aabbccddee0090", "112233445566778899aabbccddee0090") + sstore("112233445566778899aabbccddee0091", "112233445566778899aabbccddee0091") + sstore("112233445566778899aabbccddee0092", "112233445566778899aabbccddee0092") + sstore("112233445566778899aabbccddee0093", "112233445566778899aabbccddee0093") + sstore("112233445566778899aabbccddee0094", "112233445566778899aabbccddee0094") + sstore("112233445566778899aabbccddee0095", "112233445566778899aabbccddee0095") + sstore("112233445566778899aabbccddee0096", "112233445566778899aabbccddee0096") + sstore("112233445566778899aabbccddee0097", "112233445566778899aabbccddee0097") + sstore("112233445566778899aabbccddee0098", "112233445566778899aabbccddee0098") + sstore("112233445566778899aabbccddee0099", "112233445566778899aabbccddee0099") + sstore("112233445566778899aabbccddee009a", "112233445566778899aabbccddee009a") + sstore("112233445566778899aabbccddee009b", "112233445566778899aabbccddee009b") + sstore("112233445566778899aabbccddee009c", "112233445566778899aabbccddee009c") + sstore("112233445566778899aabbccddee009d", "112233445566778899aabbccddee009d") + sstore("112233445566778899aabbccddee009e", "112233445566778899aabbccddee009e") + sstore("112233445566778899aabbccddee009f", "112233445566778899aabbccddee009f") + sstore("112233445566778899aabbccddee00a0", "112233445566778899aabbccddee00a0") + sstore("112233445566778899aabbccddee00a1", "112233445566778899aabbccddee00a1") + sstore("112233445566778899aabbccddee00a2", "112233445566778899aabbccddee00a2") + sstore("112233445566778899aabbccddee00a3", "112233445566778899aabbccddee00a3") + sstore("112233445566778899aabbccddee00a4", "112233445566778899aabbccddee00a4") + sstore("112233445566778899aabbccddee00a5", "112233445566778899aabbccddee00a5") + sstore("112233445566778899aabbccddee00a6", "112233445566778899aabbccddee00a6") + sstore("112233445566778899aabbccddee00a7", "112233445566778899aabbccddee00a7") + sstore("112233445566778899aabbccddee00a8", "112233445566778899aabbccddee00a8") + sstore("112233445566778899aabbccddee00a9", "112233445566778899aabbccddee00a9") + sstore("112233445566778899aabbccddee00aa", "112233445566778899aabbccddee00aa") + sstore("112233445566778899aabbccddee00ab", "112233445566778899aabbccddee00ab") + sstore("112233445566778899aabbccddee00ac", "112233445566778899aabbccddee00ac") + sstore("112233445566778899aabbccddee00ad", "112233445566778899aabbccddee00ad") + sstore("112233445566778899aabbccddee00ae", "112233445566778899aabbccddee00ae") + sstore("112233445566778899aabbccddee00af", "112233445566778899aabbccddee00af") + sstore("112233445566778899aabbccddee00b0", "112233445566778899aabbccddee00b0") + sstore("112233445566778899aabbccddee00b1", "112233445566778899aabbccddee00b1") + sstore("112233445566778899aabbccddee00b2", "112233445566778899aabbccddee00b2") + sstore("112233445566778899aabbccddee00b3", "112233445566778899aabbccddee00b3") + sstore("112233445566778899aabbccddee00b4", "112233445566778899aabbccddee00b4") + sstore("112233445566778899aabbccddee00b5", "112233445566778899aabbccddee00b5") + sstore("112233445566778899aabbccddee00b6", "112233445566778899aabbccddee00b6") + sstore("112233445566778899aabbccddee00b7", "112233445566778899aabbccddee00b7") + sstore("112233445566778899aabbccddee00b8", "112233445566778899aabbccddee00b8") + sstore("112233445566778899aabbccddee00b9", "112233445566778899aabbccddee00b9") + sstore("112233445566778899aabbccddee00ba", "112233445566778899aabbccddee00ba") + sstore("112233445566778899aabbccddee00bb", "112233445566778899aabbccddee00bb") + sstore("112233445566778899aabbccddee00bc", "112233445566778899aabbccddee00bc") + sstore("112233445566778899aabbccddee00bd", "112233445566778899aabbccddee00bd") + sstore("112233445566778899aabbccddee00be", "112233445566778899aabbccddee00be") + sstore("112233445566778899aabbccddee00bf", "112233445566778899aabbccddee00bf") + sstore("112233445566778899aabbccddee00c0", "112233445566778899aabbccddee00c0") + sstore("112233445566778899aabbccddee00c1", "112233445566778899aabbccddee00c1") + sstore("112233445566778899aabbccddee00c2", "112233445566778899aabbccddee00c2") + sstore("112233445566778899aabbccddee00c3", "112233445566778899aabbccddee00c3") + sstore("112233445566778899aabbccddee00c4", "112233445566778899aabbccddee00c4") + sstore("112233445566778899aabbccddee00c5", "112233445566778899aabbccddee00c5") + sstore("112233445566778899aabbccddee00c6", "112233445566778899aabbccddee00c6") + sstore("112233445566778899aabbccddee00c7", "112233445566778899aabbccddee00c7") + sstore("112233445566778899aabbccddee00c8", "112233445566778899aabbccddee00c8") + sstore("112233445566778899aabbccddee00c9", "112233445566778899aabbccddee00c9") + sstore("112233445566778899aabbccddee00ca", "112233445566778899aabbccddee00ca") + sstore("112233445566778899aabbccddee00cb", "112233445566778899aabbccddee00cb") + sstore("112233445566778899aabbccddee00cc", "112233445566778899aabbccddee00cc") + sstore("112233445566778899aabbccddee00cd", "112233445566778899aabbccddee00cd") + sstore("112233445566778899aabbccddee00ce", "112233445566778899aabbccddee00ce") + sstore("112233445566778899aabbccddee00cf", "112233445566778899aabbccddee00cf") + sstore("112233445566778899aabbccddee00d0", "112233445566778899aabbccddee00d0") + sstore("112233445566778899aabbccddee00d1", "112233445566778899aabbccddee00d1") + sstore("112233445566778899aabbccddee00d2", "112233445566778899aabbccddee00d2") + sstore("112233445566778899aabbccddee00d3", "112233445566778899aabbccddee00d3") + sstore("112233445566778899aabbccddee00d4", "112233445566778899aabbccddee00d4") + sstore("112233445566778899aabbccddee00d5", "112233445566778899aabbccddee00d5") + sstore("112233445566778899aabbccddee00d6", "112233445566778899aabbccddee00d6") + sstore("112233445566778899aabbccddee00d7", "112233445566778899aabbccddee00d7") + sstore("112233445566778899aabbccddee00d8", "112233445566778899aabbccddee00d8") + sstore("112233445566778899aabbccddee00d9", "112233445566778899aabbccddee00d9") + sstore("112233445566778899aabbccddee00da", "112233445566778899aabbccddee00da") + sstore("112233445566778899aabbccddee00db", "112233445566778899aabbccddee00db") + sstore("112233445566778899aabbccddee00dc", "112233445566778899aabbccddee00dc") + sstore("112233445566778899aabbccddee00dd", "112233445566778899aabbccddee00dd") + sstore("112233445566778899aabbccddee00de", "112233445566778899aabbccddee00de") + sstore("112233445566778899aabbccddee00df", "112233445566778899aabbccddee00df") + sstore("112233445566778899aabbccddee00e0", "112233445566778899aabbccddee00e0") + sstore("112233445566778899aabbccddee00e1", "112233445566778899aabbccddee00e1") + sstore("112233445566778899aabbccddee00e2", "112233445566778899aabbccddee00e2") + sstore("112233445566778899aabbccddee00e3", "112233445566778899aabbccddee00e3") + sstore("112233445566778899aabbccddee00e4", "112233445566778899aabbccddee00e4") + sstore("112233445566778899aabbccddee00e5", "112233445566778899aabbccddee00e5") + sstore("112233445566778899aabbccddee00e6", "112233445566778899aabbccddee00e6") + sstore("112233445566778899aabbccddee00e7", "112233445566778899aabbccddee00e7") + sstore("112233445566778899aabbccddee00e8", "112233445566778899aabbccddee00e8") + sstore("112233445566778899aabbccddee00e9", "112233445566778899aabbccddee00e9") + sstore("112233445566778899aabbccddee00ea", "112233445566778899aabbccddee00ea") + sstore("112233445566778899aabbccddee00eb", "112233445566778899aabbccddee00eb") + sstore("112233445566778899aabbccddee00ec", "112233445566778899aabbccddee00ec") + sstore("112233445566778899aabbccddee00ed", "112233445566778899aabbccddee00ed") + sstore("112233445566778899aabbccddee00ee", "112233445566778899aabbccddee00ee") + sstore("112233445566778899aabbccddee00ef", "112233445566778899aabbccddee00ef") + sstore("112233445566778899aabbccddee00f0", "112233445566778899aabbccddee00f0") + sstore("112233445566778899aabbccddee00f1", "112233445566778899aabbccddee00f1") + sstore("112233445566778899aabbccddee00f2", "112233445566778899aabbccddee00f2") + sstore("112233445566778899aabbccddee00f3", "112233445566778899aabbccddee00f3") + sstore("112233445566778899aabbccddee00f4", "112233445566778899aabbccddee00f4") + sstore("112233445566778899aabbccddee00f5", "112233445566778899aabbccddee00f5") + sstore("112233445566778899aabbccddee00f6", "112233445566778899aabbccddee00f6") + sstore("112233445566778899aabbccddee00f7", "112233445566778899aabbccddee00f7") + sstore("112233445566778899aabbccddee00f8", "112233445566778899aabbccddee00f8") + sstore("112233445566778899aabbccddee00f9", "112233445566778899aabbccddee00f9") + sstore("112233445566778899aabbccddee00fa", "112233445566778899aabbccddee00fa") + sstore("112233445566778899aabbccddee00fb", "112233445566778899aabbccddee00fb") + sstore("112233445566778899aabbccddee00fc", "112233445566778899aabbccddee00fc") + sstore("112233445566778899aabbccddee00fd", "112233445566778899aabbccddee00fd") + sstore("112233445566778899aabbccddee00fe", "112233445566778899aabbccddee00fe") + sstore("112233445566778899aabbccddee00ff", "112233445566778899aabbccddee00ff") + sstore("112233445566778899aabbccddee0100", "112233445566778899aabbccddee0100") + sstore("112233445566778899aabbccddee0101", "112233445566778899aabbccddee0101") + sstore("112233445566778899aabbccddee0102", "112233445566778899aabbccddee0102") + sstore("112233445566778899aabbccddee0103", "112233445566778899aabbccddee0103") + sstore("112233445566778899aabbccddee0104", "112233445566778899aabbccddee0104") + sstore("112233445566778899aabbccddee0105", "112233445566778899aabbccddee0105") + sstore("112233445566778899aabbccddee0106", "112233445566778899aabbccddee0106") + sstore("112233445566778899aabbccddee0107", "112233445566778899aabbccddee0107") + sstore("112233445566778899aabbccddee0108", "112233445566778899aabbccddee0108") + sstore("112233445566778899aabbccddee0109", "112233445566778899aabbccddee0109") + sstore("112233445566778899aabbccddee010a", "112233445566778899aabbccddee010a") + sstore("112233445566778899aabbccddee010b", "112233445566778899aabbccddee010b") + sstore("112233445566778899aabbccddee010c", "112233445566778899aabbccddee010c") + sstore("112233445566778899aabbccddee010d", "112233445566778899aabbccddee010d") + sstore("112233445566778899aabbccddee010e", "112233445566778899aabbccddee010e") + sstore("112233445566778899aabbccddee010f", "112233445566778899aabbccddee010f") + sstore("112233445566778899aabbccddee0110", "112233445566778899aabbccddee0110") + sstore("112233445566778899aabbccddee0111", "112233445566778899aabbccddee0111") + sstore("112233445566778899aabbccddee0112", "112233445566778899aabbccddee0112") + sstore("112233445566778899aabbccddee0113", "112233445566778899aabbccddee0113") + sstore("112233445566778899aabbccddee0114", "112233445566778899aabbccddee0114") + sstore("112233445566778899aabbccddee0115", "112233445566778899aabbccddee0115") + sstore("112233445566778899aabbccddee0116", "112233445566778899aabbccddee0116") + sstore("112233445566778899aabbccddee0117", "112233445566778899aabbccddee0117") + sstore("112233445566778899aabbccddee0118", "112233445566778899aabbccddee0118") + sstore("112233445566778899aabbccddee0119", "112233445566778899aabbccddee0119") + sstore("112233445566778899aabbccddee011a", "112233445566778899aabbccddee011a") + sstore("112233445566778899aabbccddee011b", "112233445566778899aabbccddee011b") + sstore("112233445566778899aabbccddee011c", "112233445566778899aabbccddee011c") + sstore("112233445566778899aabbccddee011d", "112233445566778899aabbccddee011d") + sstore("112233445566778899aabbccddee011e", "112233445566778899aabbccddee011e") + sstore("112233445566778899aabbccddee011f", "112233445566778899aabbccddee011f") + sstore("112233445566778899aabbccddee0120", "112233445566778899aabbccddee0120") + sstore("112233445566778899aabbccddee0121", "112233445566778899aabbccddee0121") + sstore("112233445566778899aabbccddee0122", "112233445566778899aabbccddee0122") + sstore("112233445566778899aabbccddee0123", "112233445566778899aabbccddee0123") + sstore("112233445566778899aabbccddee0124", "112233445566778899aabbccddee0124") + sstore("112233445566778899aabbccddee0125", "112233445566778899aabbccddee0125") + sstore("112233445566778899aabbccddee0126", "112233445566778899aabbccddee0126") + sstore("112233445566778899aabbccddee0127", "112233445566778899aabbccddee0127") + sstore("112233445566778899aabbccddee0128", "112233445566778899aabbccddee0128") + sstore("112233445566778899aabbccddee0129", "112233445566778899aabbccddee0129") + sstore("112233445566778899aabbccddee012a", "112233445566778899aabbccddee012a") + sstore("112233445566778899aabbccddee012b", "112233445566778899aabbccddee012b") + sstore("112233445566778899aabbccddee012c", "112233445566778899aabbccddee012c") + sstore("112233445566778899aabbccddee012d", "112233445566778899aabbccddee012d") + sstore("112233445566778899aabbccddee012e", "112233445566778899aabbccddee012e") + sstore("112233445566778899aabbccddee012f", "112233445566778899aabbccddee012f") + sstore("112233445566778899aabbccddee0130", "112233445566778899aabbccddee0130") + sstore("112233445566778899aabbccddee0131", "112233445566778899aabbccddee0131") + sstore("112233445566778899aabbccddee0132", "112233445566778899aabbccddee0132") + sstore("112233445566778899aabbccddee0133", "112233445566778899aabbccddee0133") + sstore("112233445566778899aabbccddee0134", "112233445566778899aabbccddee0134") + sstore("112233445566778899aabbccddee0135", "112233445566778899aabbccddee0135") + sstore("112233445566778899aabbccddee0136", "112233445566778899aabbccddee0136") + sstore("112233445566778899aabbccddee0137", "112233445566778899aabbccddee0137") + sstore("112233445566778899aabbccddee0138", "112233445566778899aabbccddee0138") + sstore("112233445566778899aabbccddee0139", "112233445566778899aabbccddee0139") + sstore("112233445566778899aabbccddee013a", "112233445566778899aabbccddee013a") + sstore("112233445566778899aabbccddee013b", "112233445566778899aabbccddee013b") + sstore("112233445566778899aabbccddee013c", "112233445566778899aabbccddee013c") + sstore("112233445566778899aabbccddee013d", "112233445566778899aabbccddee013d") + sstore("112233445566778899aabbccddee013e", "112233445566778899aabbccddee013e") + sstore("112233445566778899aabbccddee013f", "112233445566778899aabbccddee013f") + sstore("112233445566778899aabbccddee0140", "112233445566778899aabbccddee0140") + sstore("112233445566778899aabbccddee0141", "112233445566778899aabbccddee0141") + sstore("112233445566778899aabbccddee0142", "112233445566778899aabbccddee0142") + sstore("112233445566778899aabbccddee0143", "112233445566778899aabbccddee0143") + sstore("112233445566778899aabbccddee0144", "112233445566778899aabbccddee0144") + sstore("112233445566778899aabbccddee0145", "112233445566778899aabbccddee0145") + sstore("112233445566778899aabbccddee0146", "112233445566778899aabbccddee0146") + sstore("112233445566778899aabbccddee0147", "112233445566778899aabbccddee0147") + sstore("112233445566778899aabbccddee0148", "112233445566778899aabbccddee0148") + sstore("112233445566778899aabbccddee0149", "112233445566778899aabbccddee0149") + sstore("112233445566778899aabbccddee014a", "112233445566778899aabbccddee014a") + sstore("112233445566778899aabbccddee014b", "112233445566778899aabbccddee014b") + sstore("112233445566778899aabbccddee014c", "112233445566778899aabbccddee014c") + sstore("112233445566778899aabbccddee014d", "112233445566778899aabbccddee014d") + sstore("112233445566778899aabbccddee014e", "112233445566778899aabbccddee014e") + sstore("112233445566778899aabbccddee014f", "112233445566778899aabbccddee014f") + sstore("112233445566778899aabbccddee0150", "112233445566778899aabbccddee0150") + sstore("112233445566778899aabbccddee0151", "112233445566778899aabbccddee0151") + sstore("112233445566778899aabbccddee0152", "112233445566778899aabbccddee0152") + sstore("112233445566778899aabbccddee0153", "112233445566778899aabbccddee0153") + sstore("112233445566778899aabbccddee0154", "112233445566778899aabbccddee0154") + sstore("112233445566778899aabbccddee0155", "112233445566778899aabbccddee0155") + sstore("112233445566778899aabbccddee0156", "112233445566778899aabbccddee0156") + sstore("112233445566778899aabbccddee0157", "112233445566778899aabbccddee0157") + sstore("112233445566778899aabbccddee0158", "112233445566778899aabbccddee0158") + sstore("112233445566778899aabbccddee0159", "112233445566778899aabbccddee0159") + sstore("112233445566778899aabbccddee015a", "112233445566778899aabbccddee015a") + sstore("112233445566778899aabbccddee015b", "112233445566778899aabbccddee015b") + sstore("112233445566778899aabbccddee015c", "112233445566778899aabbccddee015c") + sstore("112233445566778899aabbccddee015d", "112233445566778899aabbccddee015d") + sstore("112233445566778899aabbccddee015e", "112233445566778899aabbccddee015e") + sstore("112233445566778899aabbccddee015f", "112233445566778899aabbccddee015f") + sstore("112233445566778899aabbccddee0160", "112233445566778899aabbccddee0160") + sstore("112233445566778899aabbccddee0161", "112233445566778899aabbccddee0161") + sstore("112233445566778899aabbccddee0162", "112233445566778899aabbccddee0162") + sstore("112233445566778899aabbccddee0163", "112233445566778899aabbccddee0163") + sstore("112233445566778899aabbccddee0164", "112233445566778899aabbccddee0164") + sstore("112233445566778899aabbccddee0165", "112233445566778899aabbccddee0165") + sstore("112233445566778899aabbccddee0166", "112233445566778899aabbccddee0166") + sstore("112233445566778899aabbccddee0167", "112233445566778899aabbccddee0167") + sstore("112233445566778899aabbccddee0168", "112233445566778899aabbccddee0168") + sstore("112233445566778899aabbccddee0169", "112233445566778899aabbccddee0169") + sstore("112233445566778899aabbccddee016a", "112233445566778899aabbccddee016a") + sstore("112233445566778899aabbccddee016b", "112233445566778899aabbccddee016b") + sstore("112233445566778899aabbccddee016c", "112233445566778899aabbccddee016c") + sstore("112233445566778899aabbccddee016d", "112233445566778899aabbccddee016d") + sstore("112233445566778899aabbccddee016e", "112233445566778899aabbccddee016e") + sstore("112233445566778899aabbccddee016f", "112233445566778899aabbccddee016f") + sstore("112233445566778899aabbccddee0170", "112233445566778899aabbccddee0170") + sstore("112233445566778899aabbccddee0171", "112233445566778899aabbccddee0171") + sstore("112233445566778899aabbccddee0172", "112233445566778899aabbccddee0172") + sstore("112233445566778899aabbccddee0173", "112233445566778899aabbccddee0173") + sstore("112233445566778899aabbccddee0174", "112233445566778899aabbccddee0174") + sstore("112233445566778899aabbccddee0175", "112233445566778899aabbccddee0175") + sstore("112233445566778899aabbccddee0176", "112233445566778899aabbccddee0176") + sstore("112233445566778899aabbccddee0177", "112233445566778899aabbccddee0177") + sstore("112233445566778899aabbccddee0178", "112233445566778899aabbccddee0178") + sstore("112233445566778899aabbccddee0179", "112233445566778899aabbccddee0179") + sstore("112233445566778899aabbccddee017a", "112233445566778899aabbccddee017a") + sstore("112233445566778899aabbccddee017b", "112233445566778899aabbccddee017b") + sstore("112233445566778899aabbccddee017c", "112233445566778899aabbccddee017c") + sstore("112233445566778899aabbccddee017d", "112233445566778899aabbccddee017d") + sstore("112233445566778899aabbccddee017e", "112233445566778899aabbccddee017e") + sstore("112233445566778899aabbccddee017f", "112233445566778899aabbccddee017f") + sstore("112233445566778899aabbccddee0180", "112233445566778899aabbccddee0180") + sstore("112233445566778899aabbccddee0181", "112233445566778899aabbccddee0181") + sstore("112233445566778899aabbccddee0182", "112233445566778899aabbccddee0182") + sstore("112233445566778899aabbccddee0183", "112233445566778899aabbccddee0183") + sstore("112233445566778899aabbccddee0184", "112233445566778899aabbccddee0184") + sstore("112233445566778899aabbccddee0185", "112233445566778899aabbccddee0185") + sstore("112233445566778899aabbccddee0186", "112233445566778899aabbccddee0186") + sstore("112233445566778899aabbccddee0187", "112233445566778899aabbccddee0187") + sstore("112233445566778899aabbccddee0188", "112233445566778899aabbccddee0188") + sstore("112233445566778899aabbccddee0189", "112233445566778899aabbccddee0189") + sstore("112233445566778899aabbccddee018a", "112233445566778899aabbccddee018a") + sstore("112233445566778899aabbccddee018b", "112233445566778899aabbccddee018b") + sstore("112233445566778899aabbccddee018c", "112233445566778899aabbccddee018c") + sstore("112233445566778899aabbccddee018d", "112233445566778899aabbccddee018d") + sstore("112233445566778899aabbccddee018e", "112233445566778899aabbccddee018e") + sstore("112233445566778899aabbccddee018f", "112233445566778899aabbccddee018f") + sstore("112233445566778899aabbccddee0190", "112233445566778899aabbccddee0190") + sstore("112233445566778899aabbccddee0191", "112233445566778899aabbccddee0191") + sstore("112233445566778899aabbccddee0192", "112233445566778899aabbccddee0192") + sstore("112233445566778899aabbccddee0193", "112233445566778899aabbccddee0193") + sstore("112233445566778899aabbccddee0194", "112233445566778899aabbccddee0194") + sstore("112233445566778899aabbccddee0195", "112233445566778899aabbccddee0195") + sstore("112233445566778899aabbccddee0196", "112233445566778899aabbccddee0196") + sstore("112233445566778899aabbccddee0197", "112233445566778899aabbccddee0197") + sstore("112233445566778899aabbccddee0198", "112233445566778899aabbccddee0198") + sstore("112233445566778899aabbccddee0199", "112233445566778899aabbccddee0199") + sstore("112233445566778899aabbccddee019a", "112233445566778899aabbccddee019a") + sstore("112233445566778899aabbccddee019b", "112233445566778899aabbccddee019b") + sstore("112233445566778899aabbccddee019c", "112233445566778899aabbccddee019c") + sstore("112233445566778899aabbccddee019d", "112233445566778899aabbccddee019d") + sstore("112233445566778899aabbccddee019e", "112233445566778899aabbccddee019e") + sstore("112233445566778899aabbccddee019f", "112233445566778899aabbccddee019f") + sstore("112233445566778899aabbccddee01a0", "112233445566778899aabbccddee01a0") + sstore("112233445566778899aabbccddee01a1", "112233445566778899aabbccddee01a1") + sstore("112233445566778899aabbccddee01a2", "112233445566778899aabbccddee01a2") + sstore("112233445566778899aabbccddee01a3", "112233445566778899aabbccddee01a3") + sstore("112233445566778899aabbccddee01a4", "112233445566778899aabbccddee01a4") + sstore("112233445566778899aabbccddee01a5", "112233445566778899aabbccddee01a5") + sstore("112233445566778899aabbccddee01a6", "112233445566778899aabbccddee01a6") + sstore("112233445566778899aabbccddee01a7", "112233445566778899aabbccddee01a7") + sstore("112233445566778899aabbccddee01a8", "112233445566778899aabbccddee01a8") + sstore("112233445566778899aabbccddee01a9", "112233445566778899aabbccddee01a9") + sstore("112233445566778899aabbccddee01aa", "112233445566778899aabbccddee01aa") + sstore("112233445566778899aabbccddee01ab", "112233445566778899aabbccddee01ab") + sstore("112233445566778899aabbccddee01ac", "112233445566778899aabbccddee01ac") + sstore("112233445566778899aabbccddee01ad", "112233445566778899aabbccddee01ad") + sstore("112233445566778899aabbccddee01ae", "112233445566778899aabbccddee01ae") + sstore("112233445566778899aabbccddee01af", "112233445566778899aabbccddee01af") + sstore("112233445566778899aabbccddee01b0", "112233445566778899aabbccddee01b0") + sstore("112233445566778899aabbccddee01b1", "112233445566778899aabbccddee01b1") + sstore("112233445566778899aabbccddee01b2", "112233445566778899aabbccddee01b2") + sstore("112233445566778899aabbccddee01b3", "112233445566778899aabbccddee01b3") + sstore("112233445566778899aabbccddee01b4", "112233445566778899aabbccddee01b4") + sstore("112233445566778899aabbccddee01b5", "112233445566778899aabbccddee01b5") + sstore("112233445566778899aabbccddee01b6", "112233445566778899aabbccddee01b6") + sstore("112233445566778899aabbccddee01b7", "112233445566778899aabbccddee01b7") + sstore("112233445566778899aabbccddee01b8", "112233445566778899aabbccddee01b8") + sstore("112233445566778899aabbccddee01b9", "112233445566778899aabbccddee01b9") + sstore("112233445566778899aabbccddee01ba", "112233445566778899aabbccddee01ba") + sstore("112233445566778899aabbccddee01bb", "112233445566778899aabbccddee01bb") + sstore("112233445566778899aabbccddee01bc", "112233445566778899aabbccddee01bc") + sstore("112233445566778899aabbccddee01bd", "112233445566778899aabbccddee01bd") + sstore("112233445566778899aabbccddee01be", "112233445566778899aabbccddee01be") + sstore("112233445566778899aabbccddee01bf", "112233445566778899aabbccddee01bf") + sstore("112233445566778899aabbccddee01c0", "112233445566778899aabbccddee01c0") + sstore("112233445566778899aabbccddee01c1", "112233445566778899aabbccddee01c1") + sstore("112233445566778899aabbccddee01c2", "112233445566778899aabbccddee01c2") + sstore("112233445566778899aabbccddee01c3", "112233445566778899aabbccddee01c3") + sstore("112233445566778899aabbccddee01c4", "112233445566778899aabbccddee01c4") + sstore("112233445566778899aabbccddee01c5", "112233445566778899aabbccddee01c5") + sstore("112233445566778899aabbccddee01c6", "112233445566778899aabbccddee01c6") + sstore("112233445566778899aabbccddee01c7", "112233445566778899aabbccddee01c7") + sstore("112233445566778899aabbccddee01c8", "112233445566778899aabbccddee01c8") + sstore("112233445566778899aabbccddee01c9", "112233445566778899aabbccddee01c9") + sstore("112233445566778899aabbccddee01ca", "112233445566778899aabbccddee01ca") + sstore("112233445566778899aabbccddee01cb", "112233445566778899aabbccddee01cb") + sstore("112233445566778899aabbccddee01cc", "112233445566778899aabbccddee01cc") + sstore("112233445566778899aabbccddee01cd", "112233445566778899aabbccddee01cd") + sstore("112233445566778899aabbccddee01ce", "112233445566778899aabbccddee01ce") + sstore("112233445566778899aabbccddee01cf", "112233445566778899aabbccddee01cf") + sstore("112233445566778899aabbccddee01d0", "112233445566778899aabbccddee01d0") + sstore("112233445566778899aabbccddee01d1", "112233445566778899aabbccddee01d1") + sstore("112233445566778899aabbccddee01d2", "112233445566778899aabbccddee01d2") + sstore("112233445566778899aabbccddee01d3", "112233445566778899aabbccddee01d3") + sstore("112233445566778899aabbccddee01d4", "112233445566778899aabbccddee01d4") + sstore("112233445566778899aabbccddee01d5", "112233445566778899aabbccddee01d5") + sstore("112233445566778899aabbccddee01d6", "112233445566778899aabbccddee01d6") + sstore("112233445566778899aabbccddee01d7", "112233445566778899aabbccddee01d7") + sstore("112233445566778899aabbccddee01d8", "112233445566778899aabbccddee01d8") + sstore("112233445566778899aabbccddee01d9", "112233445566778899aabbccddee01d9") + sstore("112233445566778899aabbccddee01da", "112233445566778899aabbccddee01da") + sstore("112233445566778899aabbccddee01db", "112233445566778899aabbccddee01db") + sstore("112233445566778899aabbccddee01dc", "112233445566778899aabbccddee01dc") + sstore("112233445566778899aabbccddee01dd", "112233445566778899aabbccddee01dd") + sstore("112233445566778899aabbccddee01de", "112233445566778899aabbccddee01de") + sstore("112233445566778899aabbccddee01df", "112233445566778899aabbccddee01df") + sstore("112233445566778899aabbccddee01e0", "112233445566778899aabbccddee01e0") + sstore("112233445566778899aabbccddee01e1", "112233445566778899aabbccddee01e1") + sstore("112233445566778899aabbccddee01e2", "112233445566778899aabbccddee01e2") + sstore("112233445566778899aabbccddee01e3", "112233445566778899aabbccddee01e3") + sstore("112233445566778899aabbccddee01e4", "112233445566778899aabbccddee01e4") + sstore("112233445566778899aabbccddee01e5", "112233445566778899aabbccddee01e5") + sstore("112233445566778899aabbccddee01e6", "112233445566778899aabbccddee01e6") + sstore("112233445566778899aabbccddee01e7", "112233445566778899aabbccddee01e7") + sstore("112233445566778899aabbccddee01e8", "112233445566778899aabbccddee01e8") + sstore("112233445566778899aabbccddee01e9", "112233445566778899aabbccddee01e9") + sstore("112233445566778899aabbccddee01ea", "112233445566778899aabbccddee01ea") + sstore("112233445566778899aabbccddee01eb", "112233445566778899aabbccddee01eb") + sstore("112233445566778899aabbccddee01ec", "112233445566778899aabbccddee01ec") + sstore("112233445566778899aabbccddee01ed", "112233445566778899aabbccddee01ed") + sstore("112233445566778899aabbccddee01ee", "112233445566778899aabbccddee01ee") + sstore("112233445566778899aabbccddee01ef", "112233445566778899aabbccddee01ef") + sstore("112233445566778899aabbccddee01f0", "112233445566778899aabbccddee01f0") + sstore("112233445566778899aabbccddee01f1", "112233445566778899aabbccddee01f1") + sstore("112233445566778899aabbccddee01f2", "112233445566778899aabbccddee01f2") + sstore("112233445566778899aabbccddee01f3", "112233445566778899aabbccddee01f3") + sstore("112233445566778899aabbccddee01f4", "112233445566778899aabbccddee01f4") + sstore("112233445566778899aabbccddee01f5", "112233445566778899aabbccddee01f5") + sstore("112233445566778899aabbccddee01f6", "112233445566778899aabbccddee01f6") + sstore("112233445566778899aabbccddee01f7", "112233445566778899aabbccddee01f7") + sstore("112233445566778899aabbccddee01f8", "112233445566778899aabbccddee01f8") + sstore("112233445566778899aabbccddee01f9", "112233445566778899aabbccddee01f9") + sstore("112233445566778899aabbccddee01fa", "112233445566778899aabbccddee01fa") + sstore("112233445566778899aabbccddee01fb", "112233445566778899aabbccddee01fb") + sstore("112233445566778899aabbccddee01fc", "112233445566778899aabbccddee01fc") + sstore("112233445566778899aabbccddee01fd", "112233445566778899aabbccddee01fd") + sstore("112233445566778899aabbccddee01fe", "112233445566778899aabbccddee01fe") + sstore("112233445566778899aabbccddee01ff", "112233445566778899aabbccddee01ff") + sstore("112233445566778899aabbccddee0200", "112233445566778899aabbccddee0200") + sstore("112233445566778899aabbccddee0201", "112233445566778899aabbccddee0201") + sstore("112233445566778899aabbccddee0202", "112233445566778899aabbccddee0202") + sstore("112233445566778899aabbccddee0203", "112233445566778899aabbccddee0203") + sstore("112233445566778899aabbccddee0204", "112233445566778899aabbccddee0204") + sstore("112233445566778899aabbccddee0205", "112233445566778899aabbccddee0205") + sstore("112233445566778899aabbccddee0206", "112233445566778899aabbccddee0206") + sstore("112233445566778899aabbccddee0207", "112233445566778899aabbccddee0207") + sstore("112233445566778899aabbccddee0208", "112233445566778899aabbccddee0208") + sstore("112233445566778899aabbccddee0209", "112233445566778899aabbccddee0209") + sstore("112233445566778899aabbccddee020a", "112233445566778899aabbccddee020a") + sstore("112233445566778899aabbccddee020b", "112233445566778899aabbccddee020b") + sstore("112233445566778899aabbccddee020c", "112233445566778899aabbccddee020c") + sstore("112233445566778899aabbccddee020d", "112233445566778899aabbccddee020d") + sstore("112233445566778899aabbccddee020e", "112233445566778899aabbccddee020e") + sstore("112233445566778899aabbccddee020f", "112233445566778899aabbccddee020f") + sstore("112233445566778899aabbccddee0210", "112233445566778899aabbccddee0210") + sstore("112233445566778899aabbccddee0211", "112233445566778899aabbccddee0211") + sstore("112233445566778899aabbccddee0212", "112233445566778899aabbccddee0212") + sstore("112233445566778899aabbccddee0213", "112233445566778899aabbccddee0213") + sstore("112233445566778899aabbccddee0214", "112233445566778899aabbccddee0214") + sstore("112233445566778899aabbccddee0215", "112233445566778899aabbccddee0215") + sstore("112233445566778899aabbccddee0216", "112233445566778899aabbccddee0216") + sstore("112233445566778899aabbccddee0217", "112233445566778899aabbccddee0217") + sstore("112233445566778899aabbccddee0218", "112233445566778899aabbccddee0218") + sstore("112233445566778899aabbccddee0219", "112233445566778899aabbccddee0219") + sstore("112233445566778899aabbccddee021a", "112233445566778899aabbccddee021a") + sstore("112233445566778899aabbccddee021b", "112233445566778899aabbccddee021b") + sstore("112233445566778899aabbccddee021c", "112233445566778899aabbccddee021c") + sstore("112233445566778899aabbccddee021d", "112233445566778899aabbccddee021d") + sstore("112233445566778899aabbccddee021e", "112233445566778899aabbccddee021e") + sstore("112233445566778899aabbccddee021f", "112233445566778899aabbccddee021f") + sstore("112233445566778899aabbccddee0220", "112233445566778899aabbccddee0220") + sstore("112233445566778899aabbccddee0221", "112233445566778899aabbccddee0221") + sstore("112233445566778899aabbccddee0222", "112233445566778899aabbccddee0222") + sstore("112233445566778899aabbccddee0223", "112233445566778899aabbccddee0223") + sstore("112233445566778899aabbccddee0224", "112233445566778899aabbccddee0224") + sstore("112233445566778899aabbccddee0225", "112233445566778899aabbccddee0225") + sstore("112233445566778899aabbccddee0226", "112233445566778899aabbccddee0226") + sstore("112233445566778899aabbccddee0227", "112233445566778899aabbccddee0227") + sstore("112233445566778899aabbccddee0228", "112233445566778899aabbccddee0228") + sstore("112233445566778899aabbccddee0229", "112233445566778899aabbccddee0229") + sstore("112233445566778899aabbccddee022a", "112233445566778899aabbccddee022a") + sstore("112233445566778899aabbccddee022b", "112233445566778899aabbccddee022b") + sstore("112233445566778899aabbccddee022c", "112233445566778899aabbccddee022c") + sstore("112233445566778899aabbccddee022d", "112233445566778899aabbccddee022d") + sstore("112233445566778899aabbccddee022e", "112233445566778899aabbccddee022e") + sstore("112233445566778899aabbccddee022f", "112233445566778899aabbccddee022f") + sstore("112233445566778899aabbccddee0230", "112233445566778899aabbccddee0230") + sstore("112233445566778899aabbccddee0231", "112233445566778899aabbccddee0231") + sstore("112233445566778899aabbccddee0232", "112233445566778899aabbccddee0232") + sstore("112233445566778899aabbccddee0233", "112233445566778899aabbccddee0233") + sstore("112233445566778899aabbccddee0234", "112233445566778899aabbccddee0234") + sstore("112233445566778899aabbccddee0235", "112233445566778899aabbccddee0235") + sstore("112233445566778899aabbccddee0236", "112233445566778899aabbccddee0236") + sstore("112233445566778899aabbccddee0237", "112233445566778899aabbccddee0237") + sstore("112233445566778899aabbccddee0238", "112233445566778899aabbccddee0238") + sstore("112233445566778899aabbccddee0239", "112233445566778899aabbccddee0239") + sstore("112233445566778899aabbccddee023a", "112233445566778899aabbccddee023a") + sstore("112233445566778899aabbccddee023b", "112233445566778899aabbccddee023b") + sstore("112233445566778899aabbccddee023c", "112233445566778899aabbccddee023c") + sstore("112233445566778899aabbccddee023d", "112233445566778899aabbccddee023d") + sstore("112233445566778899aabbccddee023e", "112233445566778899aabbccddee023e") + sstore("112233445566778899aabbccddee023f", "112233445566778899aabbccddee023f") + sstore("112233445566778899aabbccddee0240", "112233445566778899aabbccddee0240") + sstore("112233445566778899aabbccddee0241", "112233445566778899aabbccddee0241") + sstore("112233445566778899aabbccddee0242", "112233445566778899aabbccddee0242") + sstore("112233445566778899aabbccddee0243", "112233445566778899aabbccddee0243") + sstore("112233445566778899aabbccddee0244", "112233445566778899aabbccddee0244") + sstore("112233445566778899aabbccddee0245", "112233445566778899aabbccddee0245") + sstore("112233445566778899aabbccddee0246", "112233445566778899aabbccddee0246") + sstore("112233445566778899aabbccddee0247", "112233445566778899aabbccddee0247") + sstore("112233445566778899aabbccddee0248", "112233445566778899aabbccddee0248") + sstore("112233445566778899aabbccddee0249", "112233445566778899aabbccddee0249") + sstore("112233445566778899aabbccddee024a", "112233445566778899aabbccddee024a") + sstore("112233445566778899aabbccddee024b", "112233445566778899aabbccddee024b") + sstore("112233445566778899aabbccddee024c", "112233445566778899aabbccddee024c") + sstore("112233445566778899aabbccddee024d", "112233445566778899aabbccddee024d") + sstore("112233445566778899aabbccddee024e", "112233445566778899aabbccddee024e") + sstore("112233445566778899aabbccddee024f", "112233445566778899aabbccddee024f") + sstore("112233445566778899aabbccddee0250", "112233445566778899aabbccddee0250") + sstore("112233445566778899aabbccddee0251", "112233445566778899aabbccddee0251") + sstore("112233445566778899aabbccddee0252", "112233445566778899aabbccddee0252") + sstore("112233445566778899aabbccddee0253", "112233445566778899aabbccddee0253") + sstore("112233445566778899aabbccddee0254", "112233445566778899aabbccddee0254") + sstore("112233445566778899aabbccddee0255", "112233445566778899aabbccddee0255") + sstore("112233445566778899aabbccddee0256", "112233445566778899aabbccddee0256") + sstore("112233445566778899aabbccddee0257", "112233445566778899aabbccddee0257") + sstore("112233445566778899aabbccddee0258", "112233445566778899aabbccddee0258") + sstore("112233445566778899aabbccddee0259", "112233445566778899aabbccddee0259") + sstore("112233445566778899aabbccddee025a", "112233445566778899aabbccddee025a") + sstore("112233445566778899aabbccddee025b", "112233445566778899aabbccddee025b") + sstore("112233445566778899aabbccddee025c", "112233445566778899aabbccddee025c") + sstore("112233445566778899aabbccddee025d", "112233445566778899aabbccddee025d") + sstore("112233445566778899aabbccddee025e", "112233445566778899aabbccddee025e") + sstore("112233445566778899aabbccddee025f", "112233445566778899aabbccddee025f") + sstore("112233445566778899aabbccddee0260", "112233445566778899aabbccddee0260") + sstore("112233445566778899aabbccddee0261", "112233445566778899aabbccddee0261") + sstore("112233445566778899aabbccddee0262", "112233445566778899aabbccddee0262") + sstore("112233445566778899aabbccddee0263", "112233445566778899aabbccddee0263") + sstore("112233445566778899aabbccddee0264", "112233445566778899aabbccddee0264") + sstore("112233445566778899aabbccddee0265", "112233445566778899aabbccddee0265") + sstore("112233445566778899aabbccddee0266", "112233445566778899aabbccddee0266") + sstore("112233445566778899aabbccddee0267", "112233445566778899aabbccddee0267") + sstore("112233445566778899aabbccddee0268", "112233445566778899aabbccddee0268") + sstore("112233445566778899aabbccddee0269", "112233445566778899aabbccddee0269") + sstore("112233445566778899aabbccddee026a", "112233445566778899aabbccddee026a") + sstore("112233445566778899aabbccddee026b", "112233445566778899aabbccddee026b") + sstore("112233445566778899aabbccddee026c", "112233445566778899aabbccddee026c") + sstore("112233445566778899aabbccddee026d", "112233445566778899aabbccddee026d") + sstore("112233445566778899aabbccddee026e", "112233445566778899aabbccddee026e") + sstore("112233445566778899aabbccddee026f", "112233445566778899aabbccddee026f") + sstore("112233445566778899aabbccddee0270", "112233445566778899aabbccddee0270") + sstore("112233445566778899aabbccddee0271", "112233445566778899aabbccddee0271") + sstore("112233445566778899aabbccddee0272", "112233445566778899aabbccddee0272") + sstore("112233445566778899aabbccddee0273", "112233445566778899aabbccddee0273") + sstore("112233445566778899aabbccddee0274", "112233445566778899aabbccddee0274") + sstore("112233445566778899aabbccddee0275", "112233445566778899aabbccddee0275") + sstore("112233445566778899aabbccddee0276", "112233445566778899aabbccddee0276") + sstore("112233445566778899aabbccddee0277", "112233445566778899aabbccddee0277") + sstore("112233445566778899aabbccddee0278", "112233445566778899aabbccddee0278") + sstore("112233445566778899aabbccddee0279", "112233445566778899aabbccddee0279") + sstore("112233445566778899aabbccddee027a", "112233445566778899aabbccddee027a") + sstore("112233445566778899aabbccddee027b", "112233445566778899aabbccddee027b") + sstore("112233445566778899aabbccddee027c", "112233445566778899aabbccddee027c") + sstore("112233445566778899aabbccddee027d", "112233445566778899aabbccddee027d") + sstore("112233445566778899aabbccddee027e", "112233445566778899aabbccddee027e") + sstore("112233445566778899aabbccddee027f", "112233445566778899aabbccddee027f") + sstore("112233445566778899aabbccddee0280", "112233445566778899aabbccddee0280") + sstore("112233445566778899aabbccddee0281", "112233445566778899aabbccddee0281") + sstore("112233445566778899aabbccddee0282", "112233445566778899aabbccddee0282") + sstore("112233445566778899aabbccddee0283", "112233445566778899aabbccddee0283") + sstore("112233445566778899aabbccddee0284", "112233445566778899aabbccddee0284") + sstore("112233445566778899aabbccddee0285", "112233445566778899aabbccddee0285") + sstore("112233445566778899aabbccddee0286", "112233445566778899aabbccddee0286") + sstore("112233445566778899aabbccddee0287", "112233445566778899aabbccddee0287") + sstore("112233445566778899aabbccddee0288", "112233445566778899aabbccddee0288") + sstore("112233445566778899aabbccddee0289", "112233445566778899aabbccddee0289") + sstore("112233445566778899aabbccddee028a", "112233445566778899aabbccddee028a") + sstore("112233445566778899aabbccddee028b", "112233445566778899aabbccddee028b") + sstore("112233445566778899aabbccddee028c", "112233445566778899aabbccddee028c") + sstore("112233445566778899aabbccddee028d", "112233445566778899aabbccddee028d") + sstore("112233445566778899aabbccddee028e", "112233445566778899aabbccddee028e") + sstore("112233445566778899aabbccddee028f", "112233445566778899aabbccddee028f") + sstore("112233445566778899aabbccddee0290", "112233445566778899aabbccddee0290") + sstore("112233445566778899aabbccddee0291", "112233445566778899aabbccddee0291") + sstore("112233445566778899aabbccddee0292", "112233445566778899aabbccddee0292") + sstore("112233445566778899aabbccddee0293", "112233445566778899aabbccddee0293") + sstore("112233445566778899aabbccddee0294", "112233445566778899aabbccddee0294") + sstore("112233445566778899aabbccddee0295", "112233445566778899aabbccddee0295") + sstore("112233445566778899aabbccddee0296", "112233445566778899aabbccddee0296") + sstore("112233445566778899aabbccddee0297", "112233445566778899aabbccddee0297") + sstore("112233445566778899aabbccddee0298", "112233445566778899aabbccddee0298") + sstore("112233445566778899aabbccddee0299", "112233445566778899aabbccddee0299") + sstore("112233445566778899aabbccddee029a", "112233445566778899aabbccddee029a") + sstore("112233445566778899aabbccddee029b", "112233445566778899aabbccddee029b") + sstore("112233445566778899aabbccddee029c", "112233445566778899aabbccddee029c") + sstore("112233445566778899aabbccddee029d", "112233445566778899aabbccddee029d") + sstore("112233445566778899aabbccddee029e", "112233445566778899aabbccddee029e") + sstore("112233445566778899aabbccddee029f", "112233445566778899aabbccddee029f") + sstore("112233445566778899aabbccddee02a0", "112233445566778899aabbccddee02a0") + sstore("112233445566778899aabbccddee02a1", "112233445566778899aabbccddee02a1") + sstore("112233445566778899aabbccddee02a2", "112233445566778899aabbccddee02a2") + sstore("112233445566778899aabbccddee02a3", "112233445566778899aabbccddee02a3") + sstore("112233445566778899aabbccddee02a4", "112233445566778899aabbccddee02a4") + sstore("112233445566778899aabbccddee02a5", "112233445566778899aabbccddee02a5") + sstore("112233445566778899aabbccddee02a6", "112233445566778899aabbccddee02a6") + sstore("112233445566778899aabbccddee02a7", "112233445566778899aabbccddee02a7") + sstore("112233445566778899aabbccddee02a8", "112233445566778899aabbccddee02a8") + sstore("112233445566778899aabbccddee02a9", "112233445566778899aabbccddee02a9") + sstore("112233445566778899aabbccddee02aa", "112233445566778899aabbccddee02aa") + sstore("112233445566778899aabbccddee02ab", "112233445566778899aabbccddee02ab") + sstore("112233445566778899aabbccddee02ac", "112233445566778899aabbccddee02ac") + sstore("112233445566778899aabbccddee02ad", "112233445566778899aabbccddee02ad") + sstore("112233445566778899aabbccddee02ae", "112233445566778899aabbccddee02ae") + sstore("112233445566778899aabbccddee02af", "112233445566778899aabbccddee02af") + sstore("112233445566778899aabbccddee02b0", "112233445566778899aabbccddee02b0") + sstore("112233445566778899aabbccddee02b1", "112233445566778899aabbccddee02b1") + sstore("112233445566778899aabbccddee02b2", "112233445566778899aabbccddee02b2") + sstore("112233445566778899aabbccddee02b3", "112233445566778899aabbccddee02b3") + sstore("112233445566778899aabbccddee02b4", "112233445566778899aabbccddee02b4") + sstore("112233445566778899aabbccddee02b5", "112233445566778899aabbccddee02b5") + sstore("112233445566778899aabbccddee02b6", "112233445566778899aabbccddee02b6") + sstore("112233445566778899aabbccddee02b7", "112233445566778899aabbccddee02b7") + sstore("112233445566778899aabbccddee02b8", "112233445566778899aabbccddee02b8") + sstore("112233445566778899aabbccddee02b9", "112233445566778899aabbccddee02b9") + sstore("112233445566778899aabbccddee02ba", "112233445566778899aabbccddee02ba") + sstore("112233445566778899aabbccddee02bb", "112233445566778899aabbccddee02bb") + sstore("112233445566778899aabbccddee02bc", "112233445566778899aabbccddee02bc") + sstore("112233445566778899aabbccddee02bd", "112233445566778899aabbccddee02bd") + sstore("112233445566778899aabbccddee02be", "112233445566778899aabbccddee02be") + sstore("112233445566778899aabbccddee02bf", "112233445566778899aabbccddee02bf") + sstore("112233445566778899aabbccddee02c0", "112233445566778899aabbccddee02c0") + sstore("112233445566778899aabbccddee02c1", "112233445566778899aabbccddee02c1") + sstore("112233445566778899aabbccddee02c2", "112233445566778899aabbccddee02c2") + sstore("112233445566778899aabbccddee02c3", "112233445566778899aabbccddee02c3") + sstore("112233445566778899aabbccddee02c4", "112233445566778899aabbccddee02c4") + sstore("112233445566778899aabbccddee02c5", "112233445566778899aabbccddee02c5") + sstore("112233445566778899aabbccddee02c6", "112233445566778899aabbccddee02c6") + sstore("112233445566778899aabbccddee02c7", "112233445566778899aabbccddee02c7") + sstore("112233445566778899aabbccddee02c8", "112233445566778899aabbccddee02c8") + sstore("112233445566778899aabbccddee02c9", "112233445566778899aabbccddee02c9") + sstore("112233445566778899aabbccddee02ca", "112233445566778899aabbccddee02ca") + sstore("112233445566778899aabbccddee02cb", "112233445566778899aabbccddee02cb") + sstore("112233445566778899aabbccddee02cc", "112233445566778899aabbccddee02cc") + sstore("112233445566778899aabbccddee02cd", "112233445566778899aabbccddee02cd") + sstore("112233445566778899aabbccddee02ce", "112233445566778899aabbccddee02ce") + sstore("112233445566778899aabbccddee02cf", "112233445566778899aabbccddee02cf") + sstore("112233445566778899aabbccddee02d0", "112233445566778899aabbccddee02d0") + sstore("112233445566778899aabbccddee02d1", "112233445566778899aabbccddee02d1") + sstore("112233445566778899aabbccddee02d2", "112233445566778899aabbccddee02d2") + sstore("112233445566778899aabbccddee02d3", "112233445566778899aabbccddee02d3") + sstore("112233445566778899aabbccddee02d4", "112233445566778899aabbccddee02d4") + sstore("112233445566778899aabbccddee02d5", "112233445566778899aabbccddee02d5") + sstore("112233445566778899aabbccddee02d6", "112233445566778899aabbccddee02d6") + sstore("112233445566778899aabbccddee02d7", "112233445566778899aabbccddee02d7") + sstore("112233445566778899aabbccddee02d8", "112233445566778899aabbccddee02d8") + sstore("112233445566778899aabbccddee02d9", "112233445566778899aabbccddee02d9") + sstore("112233445566778899aabbccddee02da", "112233445566778899aabbccddee02da") + sstore("112233445566778899aabbccddee02db", "112233445566778899aabbccddee02db") + sstore("112233445566778899aabbccddee02dc", "112233445566778899aabbccddee02dc") + sstore("112233445566778899aabbccddee02dd", "112233445566778899aabbccddee02dd") + sstore("112233445566778899aabbccddee02de", "112233445566778899aabbccddee02de") + sstore("112233445566778899aabbccddee02df", "112233445566778899aabbccddee02df") + sstore("112233445566778899aabbccddee02e0", "112233445566778899aabbccddee02e0") + sstore("112233445566778899aabbccddee02e1", "112233445566778899aabbccddee02e1") + sstore("112233445566778899aabbccddee02e2", "112233445566778899aabbccddee02e2") + sstore("112233445566778899aabbccddee02e3", "112233445566778899aabbccddee02e3") + sstore("112233445566778899aabbccddee02e4", "112233445566778899aabbccddee02e4") + sstore("112233445566778899aabbccddee02e5", "112233445566778899aabbccddee02e5") + sstore("112233445566778899aabbccddee02e6", "112233445566778899aabbccddee02e6") + sstore("112233445566778899aabbccddee02e7", "112233445566778899aabbccddee02e7") + sstore("112233445566778899aabbccddee02e8", "112233445566778899aabbccddee02e8") + sstore("112233445566778899aabbccddee02e9", "112233445566778899aabbccddee02e9") + sstore("112233445566778899aabbccddee02ea", "112233445566778899aabbccddee02ea") + sstore("112233445566778899aabbccddee02eb", "112233445566778899aabbccddee02eb") + sstore("112233445566778899aabbccddee02ec", "112233445566778899aabbccddee02ec") + sstore("112233445566778899aabbccddee02ed", "112233445566778899aabbccddee02ed") + sstore("112233445566778899aabbccddee02ee", "112233445566778899aabbccddee02ee") + sstore("112233445566778899aabbccddee02ef", "112233445566778899aabbccddee02ef") + sstore("112233445566778899aabbccddee02f0", "112233445566778899aabbccddee02f0") + sstore("112233445566778899aabbccddee02f1", "112233445566778899aabbccddee02f1") + sstore("112233445566778899aabbccddee02f2", "112233445566778899aabbccddee02f2") + sstore("112233445566778899aabbccddee02f3", "112233445566778899aabbccddee02f3") + sstore("112233445566778899aabbccddee02f4", "112233445566778899aabbccddee02f4") + sstore("112233445566778899aabbccddee02f5", "112233445566778899aabbccddee02f5") + sstore("112233445566778899aabbccddee02f6", "112233445566778899aabbccddee02f6") + sstore("112233445566778899aabbccddee02f7", "112233445566778899aabbccddee02f7") + sstore("112233445566778899aabbccddee02f8", "112233445566778899aabbccddee02f8") + sstore("112233445566778899aabbccddee02f9", "112233445566778899aabbccddee02f9") + sstore("112233445566778899aabbccddee02fa", "112233445566778899aabbccddee02fa") + sstore("112233445566778899aabbccddee02fb", "112233445566778899aabbccddee02fb") + sstore("112233445566778899aabbccddee02fc", "112233445566778899aabbccddee02fc") + sstore("112233445566778899aabbccddee02fd", "112233445566778899aabbccddee02fd") + sstore("112233445566778899aabbccddee02fe", "112233445566778899aabbccddee02fe") + sstore("112233445566778899aabbccddee02ff", "112233445566778899aabbccddee02ff") + sstore("112233445566778899aabbccddee0300", "112233445566778899aabbccddee0300") + sstore("112233445566778899aabbccddee0301", "112233445566778899aabbccddee0301") + sstore("112233445566778899aabbccddee0302", "112233445566778899aabbccddee0302") + sstore("112233445566778899aabbccddee0303", "112233445566778899aabbccddee0303") + sstore("112233445566778899aabbccddee0304", "112233445566778899aabbccddee0304") + sstore("112233445566778899aabbccddee0305", "112233445566778899aabbccddee0305") + sstore("112233445566778899aabbccddee0306", "112233445566778899aabbccddee0306") + sstore("112233445566778899aabbccddee0307", "112233445566778899aabbccddee0307") + sstore("112233445566778899aabbccddee0308", "112233445566778899aabbccddee0308") + sstore("112233445566778899aabbccddee0309", "112233445566778899aabbccddee0309") + sstore("112233445566778899aabbccddee030a", "112233445566778899aabbccddee030a") + sstore("112233445566778899aabbccddee030b", "112233445566778899aabbccddee030b") + sstore("112233445566778899aabbccddee030c", "112233445566778899aabbccddee030c") + sstore("112233445566778899aabbccddee030d", "112233445566778899aabbccddee030d") + sstore("112233445566778899aabbccddee030e", "112233445566778899aabbccddee030e") + sstore("112233445566778899aabbccddee030f", "112233445566778899aabbccddee030f") + sstore("112233445566778899aabbccddee0310", "112233445566778899aabbccddee0310") + sstore("112233445566778899aabbccddee0311", "112233445566778899aabbccddee0311") + sstore("112233445566778899aabbccddee0312", "112233445566778899aabbccddee0312") + sstore("112233445566778899aabbccddee0313", "112233445566778899aabbccddee0313") + sstore("112233445566778899aabbccddee0314", "112233445566778899aabbccddee0314") + sstore("112233445566778899aabbccddee0315", "112233445566778899aabbccddee0315") + sstore("112233445566778899aabbccddee0316", "112233445566778899aabbccddee0316") + sstore("112233445566778899aabbccddee0317", "112233445566778899aabbccddee0317") + sstore("112233445566778899aabbccddee0318", "112233445566778899aabbccddee0318") + sstore("112233445566778899aabbccddee0319", "112233445566778899aabbccddee0319") + sstore("112233445566778899aabbccddee031a", "112233445566778899aabbccddee031a") + sstore("112233445566778899aabbccddee031b", "112233445566778899aabbccddee031b") + sstore("112233445566778899aabbccddee031c", "112233445566778899aabbccddee031c") + sstore("112233445566778899aabbccddee031d", "112233445566778899aabbccddee031d") + sstore("112233445566778899aabbccddee031e", "112233445566778899aabbccddee031e") + sstore("112233445566778899aabbccddee031f", "112233445566778899aabbccddee031f") + sstore("112233445566778899aabbccddee0320", "112233445566778899aabbccddee0320") + sstore("112233445566778899aabbccddee0321", "112233445566778899aabbccddee0321") + sstore("112233445566778899aabbccddee0322", "112233445566778899aabbccddee0322") + sstore("112233445566778899aabbccddee0323", "112233445566778899aabbccddee0323") + sstore("112233445566778899aabbccddee0324", "112233445566778899aabbccddee0324") + sstore("112233445566778899aabbccddee0325", "112233445566778899aabbccddee0325") + sstore("112233445566778899aabbccddee0326", "112233445566778899aabbccddee0326") + sstore("112233445566778899aabbccddee0327", "112233445566778899aabbccddee0327") + sstore("112233445566778899aabbccddee0328", "112233445566778899aabbccddee0328") + sstore("112233445566778899aabbccddee0329", "112233445566778899aabbccddee0329") + sstore("112233445566778899aabbccddee032a", "112233445566778899aabbccddee032a") + sstore("112233445566778899aabbccddee032b", "112233445566778899aabbccddee032b") + sstore("112233445566778899aabbccddee032c", "112233445566778899aabbccddee032c") + sstore("112233445566778899aabbccddee032d", "112233445566778899aabbccddee032d") + sstore("112233445566778899aabbccddee032e", "112233445566778899aabbccddee032e") + sstore("112233445566778899aabbccddee032f", "112233445566778899aabbccddee032f") + sstore("112233445566778899aabbccddee0330", "112233445566778899aabbccddee0330") + sstore("112233445566778899aabbccddee0331", "112233445566778899aabbccddee0331") + sstore("112233445566778899aabbccddee0332", "112233445566778899aabbccddee0332") + sstore("112233445566778899aabbccddee0333", "112233445566778899aabbccddee0333") + sstore("112233445566778899aabbccddee0334", "112233445566778899aabbccddee0334") + sstore("112233445566778899aabbccddee0335", "112233445566778899aabbccddee0335") + sstore("112233445566778899aabbccddee0336", "112233445566778899aabbccddee0336") + sstore("112233445566778899aabbccddee0337", "112233445566778899aabbccddee0337") + sstore("112233445566778899aabbccddee0338", "112233445566778899aabbccddee0338") + sstore("112233445566778899aabbccddee0339", "112233445566778899aabbccddee0339") + sstore("112233445566778899aabbccddee033a", "112233445566778899aabbccddee033a") + sstore("112233445566778899aabbccddee033b", "112233445566778899aabbccddee033b") + sstore("112233445566778899aabbccddee033c", "112233445566778899aabbccddee033c") + sstore("112233445566778899aabbccddee033d", "112233445566778899aabbccddee033d") + sstore("112233445566778899aabbccddee033e", "112233445566778899aabbccddee033e") + sstore("112233445566778899aabbccddee033f", "112233445566778899aabbccddee033f") + sstore("112233445566778899aabbccddee0340", "112233445566778899aabbccddee0340") + sstore("112233445566778899aabbccddee0341", "112233445566778899aabbccddee0341") + sstore("112233445566778899aabbccddee0342", "112233445566778899aabbccddee0342") + sstore("112233445566778899aabbccddee0343", "112233445566778899aabbccddee0343") + sstore("112233445566778899aabbccddee0344", "112233445566778899aabbccddee0344") + sstore("112233445566778899aabbccddee0345", "112233445566778899aabbccddee0345") + sstore("112233445566778899aabbccddee0346", "112233445566778899aabbccddee0346") + sstore("112233445566778899aabbccddee0347", "112233445566778899aabbccddee0347") + sstore("112233445566778899aabbccddee0348", "112233445566778899aabbccddee0348") + sstore("112233445566778899aabbccddee0349", "112233445566778899aabbccddee0349") + sstore("112233445566778899aabbccddee034a", "112233445566778899aabbccddee034a") + sstore("112233445566778899aabbccddee034b", "112233445566778899aabbccddee034b") + sstore("112233445566778899aabbccddee034c", "112233445566778899aabbccddee034c") + sstore("112233445566778899aabbccddee034d", "112233445566778899aabbccddee034d") + sstore("112233445566778899aabbccddee034e", "112233445566778899aabbccddee034e") + sstore("112233445566778899aabbccddee034f", "112233445566778899aabbccddee034f") + sstore("112233445566778899aabbccddee0350", "112233445566778899aabbccddee0350") + sstore("112233445566778899aabbccddee0351", "112233445566778899aabbccddee0351") + sstore("112233445566778899aabbccddee0352", "112233445566778899aabbccddee0352") + sstore("112233445566778899aabbccddee0353", "112233445566778899aabbccddee0353") + sstore("112233445566778899aabbccddee0354", "112233445566778899aabbccddee0354") + sstore("112233445566778899aabbccddee0355", "112233445566778899aabbccddee0355") + sstore("112233445566778899aabbccddee0356", "112233445566778899aabbccddee0356") + sstore("112233445566778899aabbccddee0357", "112233445566778899aabbccddee0357") + sstore("112233445566778899aabbccddee0358", "112233445566778899aabbccddee0358") + sstore("112233445566778899aabbccddee0359", "112233445566778899aabbccddee0359") + sstore("112233445566778899aabbccddee035a", "112233445566778899aabbccddee035a") + sstore("112233445566778899aabbccddee035b", "112233445566778899aabbccddee035b") + sstore("112233445566778899aabbccddee035c", "112233445566778899aabbccddee035c") + sstore("112233445566778899aabbccddee035d", "112233445566778899aabbccddee035d") + sstore("112233445566778899aabbccddee035e", "112233445566778899aabbccddee035e") + sstore("112233445566778899aabbccddee035f", "112233445566778899aabbccddee035f") + sstore("112233445566778899aabbccddee0360", "112233445566778899aabbccddee0360") + sstore("112233445566778899aabbccddee0361", "112233445566778899aabbccddee0361") + sstore("112233445566778899aabbccddee0362", "112233445566778899aabbccddee0362") + sstore("112233445566778899aabbccddee0363", "112233445566778899aabbccddee0363") + sstore("112233445566778899aabbccddee0364", "112233445566778899aabbccddee0364") + sstore("112233445566778899aabbccddee0365", "112233445566778899aabbccddee0365") + sstore("112233445566778899aabbccddee0366", "112233445566778899aabbccddee0366") + sstore("112233445566778899aabbccddee0367", "112233445566778899aabbccddee0367") + sstore("112233445566778899aabbccddee0368", "112233445566778899aabbccddee0368") + sstore("112233445566778899aabbccddee0369", "112233445566778899aabbccddee0369") + sstore("112233445566778899aabbccddee036a", "112233445566778899aabbccddee036a") + sstore("112233445566778899aabbccddee036b", "112233445566778899aabbccddee036b") + sstore("112233445566778899aabbccddee036c", "112233445566778899aabbccddee036c") + sstore("112233445566778899aabbccddee036d", "112233445566778899aabbccddee036d") + sstore("112233445566778899aabbccddee036e", "112233445566778899aabbccddee036e") + sstore("112233445566778899aabbccddee036f", "112233445566778899aabbccddee036f") + sstore("112233445566778899aabbccddee0370", "112233445566778899aabbccddee0370") + sstore("112233445566778899aabbccddee0371", "112233445566778899aabbccddee0371") + sstore("112233445566778899aabbccddee0372", "112233445566778899aabbccddee0372") + sstore("112233445566778899aabbccddee0373", "112233445566778899aabbccddee0373") + sstore("112233445566778899aabbccddee0374", "112233445566778899aabbccddee0374") + sstore("112233445566778899aabbccddee0375", "112233445566778899aabbccddee0375") + sstore("112233445566778899aabbccddee0376", "112233445566778899aabbccddee0376") + sstore("112233445566778899aabbccddee0377", "112233445566778899aabbccddee0377") + sstore("112233445566778899aabbccddee0378", "112233445566778899aabbccddee0378") + sstore("112233445566778899aabbccddee0379", "112233445566778899aabbccddee0379") + sstore("112233445566778899aabbccddee037a", "112233445566778899aabbccddee037a") + sstore("112233445566778899aabbccddee037b", "112233445566778899aabbccddee037b") + sstore("112233445566778899aabbccddee037c", "112233445566778899aabbccddee037c") + sstore("112233445566778899aabbccddee037d", "112233445566778899aabbccddee037d") + sstore("112233445566778899aabbccddee037e", "112233445566778899aabbccddee037e") + sstore("112233445566778899aabbccddee037f", "112233445566778899aabbccddee037f") + sstore("112233445566778899aabbccddee0380", "112233445566778899aabbccddee0380") + sstore("112233445566778899aabbccddee0381", "112233445566778899aabbccddee0381") + sstore("112233445566778899aabbccddee0382", "112233445566778899aabbccddee0382") + sstore("112233445566778899aabbccddee0383", "112233445566778899aabbccddee0383") + sstore("112233445566778899aabbccddee0384", "112233445566778899aabbccddee0384") + sstore("112233445566778899aabbccddee0385", "112233445566778899aabbccddee0385") + sstore("112233445566778899aabbccddee0386", "112233445566778899aabbccddee0386") + sstore("112233445566778899aabbccddee0387", "112233445566778899aabbccddee0387") + sstore("112233445566778899aabbccddee0388", "112233445566778899aabbccddee0388") + sstore("112233445566778899aabbccddee0389", "112233445566778899aabbccddee0389") + sstore("112233445566778899aabbccddee038a", "112233445566778899aabbccddee038a") + sstore("112233445566778899aabbccddee038b", "112233445566778899aabbccddee038b") + sstore("112233445566778899aabbccddee038c", "112233445566778899aabbccddee038c") + sstore("112233445566778899aabbccddee038d", "112233445566778899aabbccddee038d") + sstore("112233445566778899aabbccddee038e", "112233445566778899aabbccddee038e") + sstore("112233445566778899aabbccddee038f", "112233445566778899aabbccddee038f") + sstore("112233445566778899aabbccddee0390", "112233445566778899aabbccddee0390") + sstore("112233445566778899aabbccddee0391", "112233445566778899aabbccddee0391") + sstore("112233445566778899aabbccddee0392", "112233445566778899aabbccddee0392") + sstore("112233445566778899aabbccddee0393", "112233445566778899aabbccddee0393") + sstore("112233445566778899aabbccddee0394", "112233445566778899aabbccddee0394") + sstore("112233445566778899aabbccddee0395", "112233445566778899aabbccddee0395") + sstore("112233445566778899aabbccddee0396", "112233445566778899aabbccddee0396") + sstore("112233445566778899aabbccddee0397", "112233445566778899aabbccddee0397") + sstore("112233445566778899aabbccddee0398", "112233445566778899aabbccddee0398") + sstore("112233445566778899aabbccddee0399", "112233445566778899aabbccddee0399") + sstore("112233445566778899aabbccddee039a", "112233445566778899aabbccddee039a") + sstore("112233445566778899aabbccddee039b", "112233445566778899aabbccddee039b") + sstore("112233445566778899aabbccddee039c", "112233445566778899aabbccddee039c") + sstore("112233445566778899aabbccddee039d", "112233445566778899aabbccddee039d") + sstore("112233445566778899aabbccddee039e", "112233445566778899aabbccddee039e") + sstore("112233445566778899aabbccddee039f", "112233445566778899aabbccddee039f") + sstore("112233445566778899aabbccddee03a0", "112233445566778899aabbccddee03a0") + sstore("112233445566778899aabbccddee03a1", "112233445566778899aabbccddee03a1") + sstore("112233445566778899aabbccddee03a2", "112233445566778899aabbccddee03a2") + sstore("112233445566778899aabbccddee03a3", "112233445566778899aabbccddee03a3") + sstore("112233445566778899aabbccddee03a4", "112233445566778899aabbccddee03a4") + sstore("112233445566778899aabbccddee03a5", "112233445566778899aabbccddee03a5") + sstore("112233445566778899aabbccddee03a6", "112233445566778899aabbccddee03a6") + sstore("112233445566778899aabbccddee03a7", "112233445566778899aabbccddee03a7") + sstore("112233445566778899aabbccddee03a8", "112233445566778899aabbccddee03a8") + sstore("112233445566778899aabbccddee03a9", "112233445566778899aabbccddee03a9") + sstore("112233445566778899aabbccddee03aa", "112233445566778899aabbccddee03aa") + sstore("112233445566778899aabbccddee03ab", "112233445566778899aabbccddee03ab") + sstore("112233445566778899aabbccddee03ac", "112233445566778899aabbccddee03ac") + sstore("112233445566778899aabbccddee03ad", "112233445566778899aabbccddee03ad") + sstore("112233445566778899aabbccddee03ae", "112233445566778899aabbccddee03ae") + sstore("112233445566778899aabbccddee03af", "112233445566778899aabbccddee03af") + sstore("112233445566778899aabbccddee03b0", "112233445566778899aabbccddee03b0") + sstore("112233445566778899aabbccddee03b1", "112233445566778899aabbccddee03b1") + sstore("112233445566778899aabbccddee03b2", "112233445566778899aabbccddee03b2") + sstore("112233445566778899aabbccddee03b3", "112233445566778899aabbccddee03b3") + sstore("112233445566778899aabbccddee03b4", "112233445566778899aabbccddee03b4") + sstore("112233445566778899aabbccddee03b5", "112233445566778899aabbccddee03b5") + sstore("112233445566778899aabbccddee03b6", "112233445566778899aabbccddee03b6") + sstore("112233445566778899aabbccddee03b7", "112233445566778899aabbccddee03b7") + sstore("112233445566778899aabbccddee03b8", "112233445566778899aabbccddee03b8") + sstore("112233445566778899aabbccddee03b9", "112233445566778899aabbccddee03b9") + sstore("112233445566778899aabbccddee03ba", "112233445566778899aabbccddee03ba") + sstore("112233445566778899aabbccddee03bb", "112233445566778899aabbccddee03bb") + sstore("112233445566778899aabbccddee03bc", "112233445566778899aabbccddee03bc") + sstore("112233445566778899aabbccddee03bd", "112233445566778899aabbccddee03bd") + sstore("112233445566778899aabbccddee03be", "112233445566778899aabbccddee03be") + sstore("112233445566778899aabbccddee03bf", "112233445566778899aabbccddee03bf") + sstore("112233445566778899aabbccddee03c0", "112233445566778899aabbccddee03c0") + sstore("112233445566778899aabbccddee03c1", "112233445566778899aabbccddee03c1") + sstore("112233445566778899aabbccddee03c2", "112233445566778899aabbccddee03c2") + sstore("112233445566778899aabbccddee03c3", "112233445566778899aabbccddee03c3") + sstore("112233445566778899aabbccddee03c4", "112233445566778899aabbccddee03c4") + sstore("112233445566778899aabbccddee03c5", "112233445566778899aabbccddee03c5") + sstore("112233445566778899aabbccddee03c6", "112233445566778899aabbccddee03c6") + sstore("112233445566778899aabbccddee03c7", "112233445566778899aabbccddee03c7") + sstore("112233445566778899aabbccddee03c8", "112233445566778899aabbccddee03c8") + sstore("112233445566778899aabbccddee03c9", "112233445566778899aabbccddee03c9") + sstore("112233445566778899aabbccddee03ca", "112233445566778899aabbccddee03ca") + sstore("112233445566778899aabbccddee03cb", "112233445566778899aabbccddee03cb") + sstore("112233445566778899aabbccddee03cc", "112233445566778899aabbccddee03cc") + sstore("112233445566778899aabbccddee03cd", "112233445566778899aabbccddee03cd") + sstore("112233445566778899aabbccddee03ce", "112233445566778899aabbccddee03ce") + sstore("112233445566778899aabbccddee03cf", "112233445566778899aabbccddee03cf") + sstore("112233445566778899aabbccddee03d0", "112233445566778899aabbccddee03d0") + sstore("112233445566778899aabbccddee03d1", "112233445566778899aabbccddee03d1") + sstore("112233445566778899aabbccddee03d2", "112233445566778899aabbccddee03d2") + sstore("112233445566778899aabbccddee03d3", "112233445566778899aabbccddee03d3") + sstore("112233445566778899aabbccddee03d4", "112233445566778899aabbccddee03d4") + sstore("112233445566778899aabbccddee03d5", "112233445566778899aabbccddee03d5") + sstore("112233445566778899aabbccddee03d6", "112233445566778899aabbccddee03d6") + sstore("112233445566778899aabbccddee03d7", "112233445566778899aabbccddee03d7") + sstore("112233445566778899aabbccddee03d8", "112233445566778899aabbccddee03d8") + sstore("112233445566778899aabbccddee03d9", "112233445566778899aabbccddee03d9") + sstore("112233445566778899aabbccddee03da", "112233445566778899aabbccddee03da") + sstore("112233445566778899aabbccddee03db", "112233445566778899aabbccddee03db") + sstore("112233445566778899aabbccddee03dc", "112233445566778899aabbccddee03dc") + sstore("112233445566778899aabbccddee03dd", "112233445566778899aabbccddee03dd") + sstore("112233445566778899aabbccddee03de", "112233445566778899aabbccddee03de") + sstore("112233445566778899aabbccddee03df", "112233445566778899aabbccddee03df") + sstore("112233445566778899aabbccddee03e0", "112233445566778899aabbccddee03e0") + sstore("112233445566778899aabbccddee03e1", "112233445566778899aabbccddee03e1") + sstore("112233445566778899aabbccddee03e2", "112233445566778899aabbccddee03e2") + sstore("112233445566778899aabbccddee03e3", "112233445566778899aabbccddee03e3") + sstore("112233445566778899aabbccddee03e4", "112233445566778899aabbccddee03e4") + sstore("112233445566778899aabbccddee03e5", "112233445566778899aabbccddee03e5") + sstore("112233445566778899aabbccddee03e6", "112233445566778899aabbccddee03e6") + sstore("112233445566778899aabbccddee03e7", "112233445566778899aabbccddee03e7") + sstore("112233445566778899aabbccddee03e8", "112233445566778899aabbccddee03e8") + sstore("112233445566778899aabbccddee03e9", "112233445566778899aabbccddee03e9") + sstore("112233445566778899aabbccddee03ea", "112233445566778899aabbccddee03ea") + sstore("112233445566778899aabbccddee03eb", "112233445566778899aabbccddee03eb") + sstore("112233445566778899aabbccddee03ec", "112233445566778899aabbccddee03ec") + sstore("112233445566778899aabbccddee03ed", "112233445566778899aabbccddee03ed") + sstore("112233445566778899aabbccddee03ee", "112233445566778899aabbccddee03ee") + sstore("112233445566778899aabbccddee03ef", "112233445566778899aabbccddee03ef") + sstore("112233445566778899aabbccddee03f0", "112233445566778899aabbccddee03f0") + sstore("112233445566778899aabbccddee03f1", "112233445566778899aabbccddee03f1") + sstore("112233445566778899aabbccddee03f2", "112233445566778899aabbccddee03f2") + sstore("112233445566778899aabbccddee03f3", "112233445566778899aabbccddee03f3") + sstore("112233445566778899aabbccddee03f4", "112233445566778899aabbccddee03f4") + sstore("112233445566778899aabbccddee03f5", "112233445566778899aabbccddee03f5") + sstore("112233445566778899aabbccddee03f6", "112233445566778899aabbccddee03f6") + sstore("112233445566778899aabbccddee03f7", "112233445566778899aabbccddee03f7") + sstore("112233445566778899aabbccddee03f8", "112233445566778899aabbccddee03f8") + sstore("112233445566778899aabbccddee03f9", "112233445566778899aabbccddee03f9") + sstore("112233445566778899aabbccddee03fa", "112233445566778899aabbccddee03fa") + sstore("112233445566778899aabbccddee03fb", "112233445566778899aabbccddee03fb") + sstore("112233445566778899aabbccddee03fc", "112233445566778899aabbccddee03fc") + sstore("112233445566778899aabbccddee03fd", "112233445566778899aabbccddee03fd") + sstore("112233445566778899aabbccddee03fe", "112233445566778899aabbccddee03fe") + sstore("112233445566778899aabbccddee03ff", "112233445566778899aabbccddee03ff") + sstore("112233445566778899aabbccddee0400", "112233445566778899aabbccddee0400") + sstore("112233445566778899aabbccddee0401", "112233445566778899aabbccddee0401") + sstore("112233445566778899aabbccddee0402", "112233445566778899aabbccddee0402") + sstore("112233445566778899aabbccddee0403", "112233445566778899aabbccddee0403") + sstore("112233445566778899aabbccddee0404", "112233445566778899aabbccddee0404") + sstore("112233445566778899aabbccddee0405", "112233445566778899aabbccddee0405") + sstore("112233445566778899aabbccddee0406", "112233445566778899aabbccddee0406") + sstore("112233445566778899aabbccddee0407", "112233445566778899aabbccddee0407") + sstore("112233445566778899aabbccddee0408", "112233445566778899aabbccddee0408") + sstore("112233445566778899aabbccddee0409", "112233445566778899aabbccddee0409") + sstore("112233445566778899aabbccddee040a", "112233445566778899aabbccddee040a") + sstore("112233445566778899aabbccddee040b", "112233445566778899aabbccddee040b") + sstore("112233445566778899aabbccddee040c", "112233445566778899aabbccddee040c") + sstore("112233445566778899aabbccddee040d", "112233445566778899aabbccddee040d") + sstore("112233445566778899aabbccddee040e", "112233445566778899aabbccddee040e") + sstore("112233445566778899aabbccddee040f", "112233445566778899aabbccddee040f") + sstore("112233445566778899aabbccddee0410", "112233445566778899aabbccddee0410") + sstore("112233445566778899aabbccddee0411", "112233445566778899aabbccddee0411") + sstore("112233445566778899aabbccddee0412", "112233445566778899aabbccddee0412") + sstore("112233445566778899aabbccddee0413", "112233445566778899aabbccddee0413") + sstore("112233445566778899aabbccddee0414", "112233445566778899aabbccddee0414") + sstore("112233445566778899aabbccddee0415", "112233445566778899aabbccddee0415") + sstore("112233445566778899aabbccddee0416", "112233445566778899aabbccddee0416") + sstore("112233445566778899aabbccddee0417", "112233445566778899aabbccddee0417") + sstore("112233445566778899aabbccddee0418", "112233445566778899aabbccddee0418") + sstore("112233445566778899aabbccddee0419", "112233445566778899aabbccddee0419") + sstore("112233445566778899aabbccddee041a", "112233445566778899aabbccddee041a") + sstore("112233445566778899aabbccddee041b", "112233445566778899aabbccddee041b") + sstore("112233445566778899aabbccddee041c", "112233445566778899aabbccddee041c") + sstore("112233445566778899aabbccddee041d", "112233445566778899aabbccddee041d") + sstore("112233445566778899aabbccddee041e", "112233445566778899aabbccddee041e") + sstore("112233445566778899aabbccddee041f", "112233445566778899aabbccddee041f") + sstore("112233445566778899aabbccddee0420", "112233445566778899aabbccddee0420") + sstore("112233445566778899aabbccddee0421", "112233445566778899aabbccddee0421") + sstore("112233445566778899aabbccddee0422", "112233445566778899aabbccddee0422") + sstore("112233445566778899aabbccddee0423", "112233445566778899aabbccddee0423") + sstore("112233445566778899aabbccddee0424", "112233445566778899aabbccddee0424") + sstore("112233445566778899aabbccddee0425", "112233445566778899aabbccddee0425") + sstore("112233445566778899aabbccddee0426", "112233445566778899aabbccddee0426") + sstore("112233445566778899aabbccddee0427", "112233445566778899aabbccddee0427") + sstore("112233445566778899aabbccddee0428", "112233445566778899aabbccddee0428") + sstore("112233445566778899aabbccddee0429", "112233445566778899aabbccddee0429") + sstore("112233445566778899aabbccddee042a", "112233445566778899aabbccddee042a") + sstore("112233445566778899aabbccddee042b", "112233445566778899aabbccddee042b") + sstore("112233445566778899aabbccddee042c", "112233445566778899aabbccddee042c") + sstore("112233445566778899aabbccddee042d", "112233445566778899aabbccddee042d") + sstore("112233445566778899aabbccddee042e", "112233445566778899aabbccddee042e") + sstore("112233445566778899aabbccddee042f", "112233445566778899aabbccddee042f") + sstore("112233445566778899aabbccddee0430", "112233445566778899aabbccddee0430") + sstore("112233445566778899aabbccddee0431", "112233445566778899aabbccddee0431") + sstore("112233445566778899aabbccddee0432", "112233445566778899aabbccddee0432") + sstore("112233445566778899aabbccddee0433", "112233445566778899aabbccddee0433") + sstore("112233445566778899aabbccddee0434", "112233445566778899aabbccddee0434") + sstore("112233445566778899aabbccddee0435", "112233445566778899aabbccddee0435") + sstore("112233445566778899aabbccddee0436", "112233445566778899aabbccddee0436") + sstore("112233445566778899aabbccddee0437", "112233445566778899aabbccddee0437") + sstore("112233445566778899aabbccddee0438", "112233445566778899aabbccddee0438") + sstore("112233445566778899aabbccddee0439", "112233445566778899aabbccddee0439") + sstore("112233445566778899aabbccddee043a", "112233445566778899aabbccddee043a") + sstore("112233445566778899aabbccddee043b", "112233445566778899aabbccddee043b") + sstore("112233445566778899aabbccddee043c", "112233445566778899aabbccddee043c") + sstore("112233445566778899aabbccddee043d", "112233445566778899aabbccddee043d") + sstore("112233445566778899aabbccddee043e", "112233445566778899aabbccddee043e") + sstore("112233445566778899aabbccddee043f", "112233445566778899aabbccddee043f") + sstore("112233445566778899aabbccddee0440", "112233445566778899aabbccddee0440") + sstore("112233445566778899aabbccddee0441", "112233445566778899aabbccddee0441") + sstore("112233445566778899aabbccddee0442", "112233445566778899aabbccddee0442") + sstore("112233445566778899aabbccddee0443", "112233445566778899aabbccddee0443") + sstore("112233445566778899aabbccddee0444", "112233445566778899aabbccddee0444") + sstore("112233445566778899aabbccddee0445", "112233445566778899aabbccddee0445") + sstore("112233445566778899aabbccddee0446", "112233445566778899aabbccddee0446") + sstore("112233445566778899aabbccddee0447", "112233445566778899aabbccddee0447") + sstore("112233445566778899aabbccddee0448", "112233445566778899aabbccddee0448") + sstore("112233445566778899aabbccddee0449", "112233445566778899aabbccddee0449") + sstore("112233445566778899aabbccddee044a", "112233445566778899aabbccddee044a") + sstore("112233445566778899aabbccddee044b", "112233445566778899aabbccddee044b") + sstore("112233445566778899aabbccddee044c", "112233445566778899aabbccddee044c") + sstore("112233445566778899aabbccddee044d", "112233445566778899aabbccddee044d") + sstore("112233445566778899aabbccddee044e", "112233445566778899aabbccddee044e") + sstore("112233445566778899aabbccddee044f", "112233445566778899aabbccddee044f") + sstore("112233445566778899aabbccddee0450", "112233445566778899aabbccddee0450") + sstore("112233445566778899aabbccddee0451", "112233445566778899aabbccddee0451") + sstore("112233445566778899aabbccddee0452", "112233445566778899aabbccddee0452") + sstore("112233445566778899aabbccddee0453", "112233445566778899aabbccddee0453") + sstore("112233445566778899aabbccddee0454", "112233445566778899aabbccddee0454") + sstore("112233445566778899aabbccddee0455", "112233445566778899aabbccddee0455") + sstore("112233445566778899aabbccddee0456", "112233445566778899aabbccddee0456") + sstore("112233445566778899aabbccddee0457", "112233445566778899aabbccddee0457") + sstore("112233445566778899aabbccddee0458", "112233445566778899aabbccddee0458") + sstore("112233445566778899aabbccddee0459", "112233445566778899aabbccddee0459") + sstore("112233445566778899aabbccddee045a", "112233445566778899aabbccddee045a") + sstore("112233445566778899aabbccddee045b", "112233445566778899aabbccddee045b") + sstore("112233445566778899aabbccddee045c", "112233445566778899aabbccddee045c") + sstore("112233445566778899aabbccddee045d", "112233445566778899aabbccddee045d") + sstore("112233445566778899aabbccddee045e", "112233445566778899aabbccddee045e") + sstore("112233445566778899aabbccddee045f", "112233445566778899aabbccddee045f") + sstore("112233445566778899aabbccddee0460", "112233445566778899aabbccddee0460") + sstore("112233445566778899aabbccddee0461", "112233445566778899aabbccddee0461") + sstore("112233445566778899aabbccddee0462", "112233445566778899aabbccddee0462") + sstore("112233445566778899aabbccddee0463", "112233445566778899aabbccddee0463") + sstore("112233445566778899aabbccddee0464", "112233445566778899aabbccddee0464") + sstore("112233445566778899aabbccddee0465", "112233445566778899aabbccddee0465") + sstore("112233445566778899aabbccddee0466", "112233445566778899aabbccddee0466") + sstore("112233445566778899aabbccddee0467", "112233445566778899aabbccddee0467") + sstore("112233445566778899aabbccddee0468", "112233445566778899aabbccddee0468") + sstore("112233445566778899aabbccddee0469", "112233445566778899aabbccddee0469") + sstore("112233445566778899aabbccddee046a", "112233445566778899aabbccddee046a") + sstore("112233445566778899aabbccddee046b", "112233445566778899aabbccddee046b") + sstore("112233445566778899aabbccddee046c", "112233445566778899aabbccddee046c") + sstore("112233445566778899aabbccddee046d", "112233445566778899aabbccddee046d") + sstore("112233445566778899aabbccddee046e", "112233445566778899aabbccddee046e") + sstore("112233445566778899aabbccddee046f", "112233445566778899aabbccddee046f") + sstore("112233445566778899aabbccddee0470", "112233445566778899aabbccddee0470") + sstore("112233445566778899aabbccddee0471", "112233445566778899aabbccddee0471") + sstore("112233445566778899aabbccddee0472", "112233445566778899aabbccddee0472") + sstore("112233445566778899aabbccddee0473", "112233445566778899aabbccddee0473") + sstore("112233445566778899aabbccddee0474", "112233445566778899aabbccddee0474") + sstore("112233445566778899aabbccddee0475", "112233445566778899aabbccddee0475") + sstore("112233445566778899aabbccddee0476", "112233445566778899aabbccddee0476") + sstore("112233445566778899aabbccddee0477", "112233445566778899aabbccddee0477") + sstore("112233445566778899aabbccddee0478", "112233445566778899aabbccddee0478") + sstore("112233445566778899aabbccddee0479", "112233445566778899aabbccddee0479") + sstore("112233445566778899aabbccddee047a", "112233445566778899aabbccddee047a") + sstore("112233445566778899aabbccddee047b", "112233445566778899aabbccddee047b") + sstore("112233445566778899aabbccddee047c", "112233445566778899aabbccddee047c") + sstore("112233445566778899aabbccddee047d", "112233445566778899aabbccddee047d") + sstore("112233445566778899aabbccddee047e", "112233445566778899aabbccddee047e") + sstore("112233445566778899aabbccddee047f", "112233445566778899aabbccddee047f") + sstore("112233445566778899aabbccddee0480", "112233445566778899aabbccddee0480") + sstore("112233445566778899aabbccddee0481", "112233445566778899aabbccddee0481") + sstore("112233445566778899aabbccddee0482", "112233445566778899aabbccddee0482") + sstore("112233445566778899aabbccddee0483", "112233445566778899aabbccddee0483") + sstore("112233445566778899aabbccddee0484", "112233445566778899aabbccddee0484") + sstore("112233445566778899aabbccddee0485", "112233445566778899aabbccddee0485") + sstore("112233445566778899aabbccddee0486", "112233445566778899aabbccddee0486") + sstore("112233445566778899aabbccddee0487", "112233445566778899aabbccddee0487") + sstore("112233445566778899aabbccddee0488", "112233445566778899aabbccddee0488") + sstore("112233445566778899aabbccddee0489", "112233445566778899aabbccddee0489") + sstore("112233445566778899aabbccddee048a", "112233445566778899aabbccddee048a") + sstore("112233445566778899aabbccddee048b", "112233445566778899aabbccddee048b") + sstore("112233445566778899aabbccddee048c", "112233445566778899aabbccddee048c") + sstore("112233445566778899aabbccddee048d", "112233445566778899aabbccddee048d") + sstore("112233445566778899aabbccddee048e", "112233445566778899aabbccddee048e") + sstore("112233445566778899aabbccddee048f", "112233445566778899aabbccddee048f") + sstore("112233445566778899aabbccddee0490", "112233445566778899aabbccddee0490") + sstore("112233445566778899aabbccddee0491", "112233445566778899aabbccddee0491") + sstore("112233445566778899aabbccddee0492", "112233445566778899aabbccddee0492") + sstore("112233445566778899aabbccddee0493", "112233445566778899aabbccddee0493") + sstore("112233445566778899aabbccddee0494", "112233445566778899aabbccddee0494") + sstore("112233445566778899aabbccddee0495", "112233445566778899aabbccddee0495") + sstore("112233445566778899aabbccddee0496", "112233445566778899aabbccddee0496") + sstore("112233445566778899aabbccddee0497", "112233445566778899aabbccddee0497") + sstore("112233445566778899aabbccddee0498", "112233445566778899aabbccddee0498") + sstore("112233445566778899aabbccddee0499", "112233445566778899aabbccddee0499") + sstore("112233445566778899aabbccddee049a", "112233445566778899aabbccddee049a") + sstore("112233445566778899aabbccddee049b", "112233445566778899aabbccddee049b") + sstore("112233445566778899aabbccddee049c", "112233445566778899aabbccddee049c") + sstore("112233445566778899aabbccddee049d", "112233445566778899aabbccddee049d") + sstore("112233445566778899aabbccddee049e", "112233445566778899aabbccddee049e") + sstore("112233445566778899aabbccddee049f", "112233445566778899aabbccddee049f") + sstore("112233445566778899aabbccddee04a0", "112233445566778899aabbccddee04a0") + sstore("112233445566778899aabbccddee04a1", "112233445566778899aabbccddee04a1") + sstore("112233445566778899aabbccddee04a2", "112233445566778899aabbccddee04a2") + sstore("112233445566778899aabbccddee04a3", "112233445566778899aabbccddee04a3") + sstore("112233445566778899aabbccddee04a4", "112233445566778899aabbccddee04a4") + sstore("112233445566778899aabbccddee04a5", "112233445566778899aabbccddee04a5") + sstore("112233445566778899aabbccddee04a6", "112233445566778899aabbccddee04a6") + sstore("112233445566778899aabbccddee04a7", "112233445566778899aabbccddee04a7") + sstore("112233445566778899aabbccddee04a8", "112233445566778899aabbccddee04a8") + sstore("112233445566778899aabbccddee04a9", "112233445566778899aabbccddee04a9") + sstore("112233445566778899aabbccddee04aa", "112233445566778899aabbccddee04aa") + sstore("112233445566778899aabbccddee04ab", "112233445566778899aabbccddee04ab") + sstore("112233445566778899aabbccddee04ac", "112233445566778899aabbccddee04ac") + sstore("112233445566778899aabbccddee04ad", "112233445566778899aabbccddee04ad") + sstore("112233445566778899aabbccddee04ae", "112233445566778899aabbccddee04ae") + sstore("112233445566778899aabbccddee04af", "112233445566778899aabbccddee04af") + sstore("112233445566778899aabbccddee04b0", "112233445566778899aabbccddee04b0") + sstore("112233445566778899aabbccddee04b1", "112233445566778899aabbccddee04b1") + sstore("112233445566778899aabbccddee04b2", "112233445566778899aabbccddee04b2") + sstore("112233445566778899aabbccddee04b3", "112233445566778899aabbccddee04b3") + sstore("112233445566778899aabbccddee04b4", "112233445566778899aabbccddee04b4") + sstore("112233445566778899aabbccddee04b5", "112233445566778899aabbccddee04b5") + sstore("112233445566778899aabbccddee04b6", "112233445566778899aabbccddee04b6") + sstore("112233445566778899aabbccddee04b7", "112233445566778899aabbccddee04b7") + sstore("112233445566778899aabbccddee04b8", "112233445566778899aabbccddee04b8") + sstore("112233445566778899aabbccddee04b9", "112233445566778899aabbccddee04b9") + sstore("112233445566778899aabbccddee04ba", "112233445566778899aabbccddee04ba") + sstore("112233445566778899aabbccddee04bb", "112233445566778899aabbccddee04bb") + sstore("112233445566778899aabbccddee04bc", "112233445566778899aabbccddee04bc") + sstore("112233445566778899aabbccddee04bd", "112233445566778899aabbccddee04bd") + sstore("112233445566778899aabbccddee04be", "112233445566778899aabbccddee04be") + sstore("112233445566778899aabbccddee04bf", "112233445566778899aabbccddee04bf") + sstore("112233445566778899aabbccddee04c0", "112233445566778899aabbccddee04c0") + sstore("112233445566778899aabbccddee04c1", "112233445566778899aabbccddee04c1") + sstore("112233445566778899aabbccddee04c2", "112233445566778899aabbccddee04c2") + sstore("112233445566778899aabbccddee04c3", "112233445566778899aabbccddee04c3") + sstore("112233445566778899aabbccddee04c4", "112233445566778899aabbccddee04c4") + sstore("112233445566778899aabbccddee04c5", "112233445566778899aabbccddee04c5") + sstore("112233445566778899aabbccddee04c6", "112233445566778899aabbccddee04c6") + sstore("112233445566778899aabbccddee04c7", "112233445566778899aabbccddee04c7") + sstore("112233445566778899aabbccddee04c8", "112233445566778899aabbccddee04c8") + sstore("112233445566778899aabbccddee04c9", "112233445566778899aabbccddee04c9") + sstore("112233445566778899aabbccddee04ca", "112233445566778899aabbccddee04ca") + sstore("112233445566778899aabbccddee04cb", "112233445566778899aabbccddee04cb") + sstore("112233445566778899aabbccddee04cc", "112233445566778899aabbccddee04cc") + sstore("112233445566778899aabbccddee04cd", "112233445566778899aabbccddee04cd") + sstore("112233445566778899aabbccddee04ce", "112233445566778899aabbccddee04ce") + sstore("112233445566778899aabbccddee04cf", "112233445566778899aabbccddee04cf") + sstore("112233445566778899aabbccddee04d0", "112233445566778899aabbccddee04d0") + sstore("112233445566778899aabbccddee04d1", "112233445566778899aabbccddee04d1") + sstore("112233445566778899aabbccddee04d2", "112233445566778899aabbccddee04d2") + sstore("112233445566778899aabbccddee04d3", "112233445566778899aabbccddee04d3") + sstore("112233445566778899aabbccddee04d4", "112233445566778899aabbccddee04d4") + sstore("112233445566778899aabbccddee04d5", "112233445566778899aabbccddee04d5") + sstore("112233445566778899aabbccddee04d6", "112233445566778899aabbccddee04d6") + sstore("112233445566778899aabbccddee04d7", "112233445566778899aabbccddee04d7") + sstore("112233445566778899aabbccddee04d8", "112233445566778899aabbccddee04d8") + sstore("112233445566778899aabbccddee04d9", "112233445566778899aabbccddee04d9") + sstore("112233445566778899aabbccddee04da", "112233445566778899aabbccddee04da") + sstore("112233445566778899aabbccddee04db", "112233445566778899aabbccddee04db") + sstore("112233445566778899aabbccddee04dc", "112233445566778899aabbccddee04dc") + sstore("112233445566778899aabbccddee04dd", "112233445566778899aabbccddee04dd") + sstore("112233445566778899aabbccddee04de", "112233445566778899aabbccddee04de") + sstore("112233445566778899aabbccddee04df", "112233445566778899aabbccddee04df") + sstore("112233445566778899aabbccddee04e0", "112233445566778899aabbccddee04e0") + sstore("112233445566778899aabbccddee04e1", "112233445566778899aabbccddee04e1") + sstore("112233445566778899aabbccddee04e2", "112233445566778899aabbccddee04e2") + sstore("112233445566778899aabbccddee04e3", "112233445566778899aabbccddee04e3") + sstore("112233445566778899aabbccddee04e4", "112233445566778899aabbccddee04e4") + sstore("112233445566778899aabbccddee04e5", "112233445566778899aabbccddee04e5") + sstore("112233445566778899aabbccddee04e6", "112233445566778899aabbccddee04e6") + sstore("112233445566778899aabbccddee04e7", "112233445566778899aabbccddee04e7") + sstore("112233445566778899aabbccddee04e8", "112233445566778899aabbccddee04e8") + sstore("112233445566778899aabbccddee04e9", "112233445566778899aabbccddee04e9") + sstore("112233445566778899aabbccddee04ea", "112233445566778899aabbccddee04ea") + sstore("112233445566778899aabbccddee04eb", "112233445566778899aabbccddee04eb") + sstore("112233445566778899aabbccddee04ec", "112233445566778899aabbccddee04ec") + sstore("112233445566778899aabbccddee04ed", "112233445566778899aabbccddee04ed") + sstore("112233445566778899aabbccddee04ee", "112233445566778899aabbccddee04ee") + sstore("112233445566778899aabbccddee04ef", "112233445566778899aabbccddee04ef") + sstore("112233445566778899aabbccddee04f0", "112233445566778899aabbccddee04f0") + sstore("112233445566778899aabbccddee04f1", "112233445566778899aabbccddee04f1") + sstore("112233445566778899aabbccddee04f2", "112233445566778899aabbccddee04f2") + sstore("112233445566778899aabbccddee04f3", "112233445566778899aabbccddee04f3") + sstore("112233445566778899aabbccddee04f4", "112233445566778899aabbccddee04f4") + sstore("112233445566778899aabbccddee04f5", "112233445566778899aabbccddee04f5") + sstore("112233445566778899aabbccddee04f6", "112233445566778899aabbccddee04f6") + sstore("112233445566778899aabbccddee04f7", "112233445566778899aabbccddee04f7") + sstore("112233445566778899aabbccddee04f8", "112233445566778899aabbccddee04f8") + sstore("112233445566778899aabbccddee04f9", "112233445566778899aabbccddee04f9") + sstore("112233445566778899aabbccddee04fa", "112233445566778899aabbccddee04fa") + sstore("112233445566778899aabbccddee04fb", "112233445566778899aabbccddee04fb") + sstore("112233445566778899aabbccddee04fc", "112233445566778899aabbccddee04fc") + sstore("112233445566778899aabbccddee04fd", "112233445566778899aabbccddee04fd") + sstore("112233445566778899aabbccddee04fe", "112233445566778899aabbccddee04fe") + sstore("112233445566778899aabbccddee04ff", "112233445566778899aabbccddee04ff") + sstore("112233445566778899aabbccddee0500", "112233445566778899aabbccddee0500") + sstore("112233445566778899aabbccddee0501", "112233445566778899aabbccddee0501") + sstore("112233445566778899aabbccddee0502", "112233445566778899aabbccddee0502") + sstore("112233445566778899aabbccddee0503", "112233445566778899aabbccddee0503") + sstore("112233445566778899aabbccddee0504", "112233445566778899aabbccddee0504") + sstore("112233445566778899aabbccddee0505", "112233445566778899aabbccddee0505") + sstore("112233445566778899aabbccddee0506", "112233445566778899aabbccddee0506") + sstore("112233445566778899aabbccddee0507", "112233445566778899aabbccddee0507") + sstore("112233445566778899aabbccddee0508", "112233445566778899aabbccddee0508") + sstore("112233445566778899aabbccddee0509", "112233445566778899aabbccddee0509") + sstore("112233445566778899aabbccddee050a", "112233445566778899aabbccddee050a") + sstore("112233445566778899aabbccddee050b", "112233445566778899aabbccddee050b") + sstore("112233445566778899aabbccddee050c", "112233445566778899aabbccddee050c") + sstore("112233445566778899aabbccddee050d", "112233445566778899aabbccddee050d") + sstore("112233445566778899aabbccddee050e", "112233445566778899aabbccddee050e") + sstore("112233445566778899aabbccddee050f", "112233445566778899aabbccddee050f") + sstore("112233445566778899aabbccddee0510", "112233445566778899aabbccddee0510") + sstore("112233445566778899aabbccddee0511", "112233445566778899aabbccddee0511") + sstore("112233445566778899aabbccddee0512", "112233445566778899aabbccddee0512") + sstore("112233445566778899aabbccddee0513", "112233445566778899aabbccddee0513") + sstore("112233445566778899aabbccddee0514", "112233445566778899aabbccddee0514") + sstore("112233445566778899aabbccddee0515", "112233445566778899aabbccddee0515") + sstore("112233445566778899aabbccddee0516", "112233445566778899aabbccddee0516") + sstore("112233445566778899aabbccddee0517", "112233445566778899aabbccddee0517") + sstore("112233445566778899aabbccddee0518", "112233445566778899aabbccddee0518") + sstore("112233445566778899aabbccddee0519", "112233445566778899aabbccddee0519") + sstore("112233445566778899aabbccddee051a", "112233445566778899aabbccddee051a") + sstore("112233445566778899aabbccddee051b", "112233445566778899aabbccddee051b") + sstore("112233445566778899aabbccddee051c", "112233445566778899aabbccddee051c") + sstore("112233445566778899aabbccddee051d", "112233445566778899aabbccddee051d") + sstore("112233445566778899aabbccddee051e", "112233445566778899aabbccddee051e") + sstore("112233445566778899aabbccddee051f", "112233445566778899aabbccddee051f") + sstore("112233445566778899aabbccddee0520", "112233445566778899aabbccddee0520") + sstore("112233445566778899aabbccddee0521", "112233445566778899aabbccddee0521") + sstore("112233445566778899aabbccddee0522", "112233445566778899aabbccddee0522") + sstore("112233445566778899aabbccddee0523", "112233445566778899aabbccddee0523") + sstore("112233445566778899aabbccddee0524", "112233445566778899aabbccddee0524") + sstore("112233445566778899aabbccddee0525", "112233445566778899aabbccddee0525") + sstore("112233445566778899aabbccddee0526", "112233445566778899aabbccddee0526") + sstore("112233445566778899aabbccddee0527", "112233445566778899aabbccddee0527") + sstore("112233445566778899aabbccddee0528", "112233445566778899aabbccddee0528") + sstore("112233445566778899aabbccddee0529", "112233445566778899aabbccddee0529") + sstore("112233445566778899aabbccddee052a", "112233445566778899aabbccddee052a") + sstore("112233445566778899aabbccddee052b", "112233445566778899aabbccddee052b") + sstore("112233445566778899aabbccddee052c", "112233445566778899aabbccddee052c") + sstore("112233445566778899aabbccddee052d", "112233445566778899aabbccddee052d") + sstore("112233445566778899aabbccddee052e", "112233445566778899aabbccddee052e") + sstore("112233445566778899aabbccddee052f", "112233445566778899aabbccddee052f") + sstore("112233445566778899aabbccddee0530", "112233445566778899aabbccddee0530") + sstore("112233445566778899aabbccddee0531", "112233445566778899aabbccddee0531") + sstore("112233445566778899aabbccddee0532", "112233445566778899aabbccddee0532") + sstore("112233445566778899aabbccddee0533", "112233445566778899aabbccddee0533") + sstore("112233445566778899aabbccddee0534", "112233445566778899aabbccddee0534") + sstore("112233445566778899aabbccddee0535", "112233445566778899aabbccddee0535") + sstore("112233445566778899aabbccddee0536", "112233445566778899aabbccddee0536") + sstore("112233445566778899aabbccddee0537", "112233445566778899aabbccddee0537") + sstore("112233445566778899aabbccddee0538", "112233445566778899aabbccddee0538") + sstore("112233445566778899aabbccddee0539", "112233445566778899aabbccddee0539") + sstore("112233445566778899aabbccddee053a", "112233445566778899aabbccddee053a") + sstore("112233445566778899aabbccddee053b", "112233445566778899aabbccddee053b") + sstore("112233445566778899aabbccddee053c", "112233445566778899aabbccddee053c") + sstore("112233445566778899aabbccddee053d", "112233445566778899aabbccddee053d") + sstore("112233445566778899aabbccddee053e", "112233445566778899aabbccddee053e") + sstore("112233445566778899aabbccddee053f", "112233445566778899aabbccddee053f") + sstore("112233445566778899aabbccddee0540", "112233445566778899aabbccddee0540") + sstore("112233445566778899aabbccddee0541", "112233445566778899aabbccddee0541") + sstore("112233445566778899aabbccddee0542", "112233445566778899aabbccddee0542") + sstore("112233445566778899aabbccddee0543", "112233445566778899aabbccddee0543") + sstore("112233445566778899aabbccddee0544", "112233445566778899aabbccddee0544") + sstore("112233445566778899aabbccddee0545", "112233445566778899aabbccddee0545") + sstore("112233445566778899aabbccddee0546", "112233445566778899aabbccddee0546") + sstore("112233445566778899aabbccddee0547", "112233445566778899aabbccddee0547") + sstore("112233445566778899aabbccddee0548", "112233445566778899aabbccddee0548") + sstore("112233445566778899aabbccddee0549", "112233445566778899aabbccddee0549") + sstore("112233445566778899aabbccddee054a", "112233445566778899aabbccddee054a") + sstore("112233445566778899aabbccddee054b", "112233445566778899aabbccddee054b") + sstore("112233445566778899aabbccddee054c", "112233445566778899aabbccddee054c") + sstore("112233445566778899aabbccddee054d", "112233445566778899aabbccddee054d") + sstore("112233445566778899aabbccddee054e", "112233445566778899aabbccddee054e") + sstore("112233445566778899aabbccddee054f", "112233445566778899aabbccddee054f") + sstore("112233445566778899aabbccddee0550", "112233445566778899aabbccddee0550") + sstore("112233445566778899aabbccddee0551", "112233445566778899aabbccddee0551") + sstore("112233445566778899aabbccddee0552", "112233445566778899aabbccddee0552") + sstore("112233445566778899aabbccddee0553", "112233445566778899aabbccddee0553") + sstore("112233445566778899aabbccddee0554", "112233445566778899aabbccddee0554") + sstore("112233445566778899aabbccddee0555", "112233445566778899aabbccddee0555") + sstore("112233445566778899aabbccddee0556", "112233445566778899aabbccddee0556") + sstore("112233445566778899aabbccddee0557", "112233445566778899aabbccddee0557") + sstore("112233445566778899aabbccddee0558", "112233445566778899aabbccddee0558") + sstore("112233445566778899aabbccddee0559", "112233445566778899aabbccddee0559") + sstore("112233445566778899aabbccddee055a", "112233445566778899aabbccddee055a") + sstore("112233445566778899aabbccddee055b", "112233445566778899aabbccddee055b") + sstore("112233445566778899aabbccddee055c", "112233445566778899aabbccddee055c") + sstore("112233445566778899aabbccddee055d", "112233445566778899aabbccddee055d") + sstore("112233445566778899aabbccddee055e", "112233445566778899aabbccddee055e") + sstore("112233445566778899aabbccddee055f", "112233445566778899aabbccddee055f") + sstore("112233445566778899aabbccddee0560", "112233445566778899aabbccddee0560") + sstore("112233445566778899aabbccddee0561", "112233445566778899aabbccddee0561") + sstore("112233445566778899aabbccddee0562", "112233445566778899aabbccddee0562") + sstore("112233445566778899aabbccddee0563", "112233445566778899aabbccddee0563") + sstore("112233445566778899aabbccddee0564", "112233445566778899aabbccddee0564") + sstore("112233445566778899aabbccddee0565", "112233445566778899aabbccddee0565") + sstore("112233445566778899aabbccddee0566", "112233445566778899aabbccddee0566") + sstore("112233445566778899aabbccddee0567", "112233445566778899aabbccddee0567") + sstore("112233445566778899aabbccddee0568", "112233445566778899aabbccddee0568") + sstore("112233445566778899aabbccddee0569", "112233445566778899aabbccddee0569") + sstore("112233445566778899aabbccddee056a", "112233445566778899aabbccddee056a") + sstore("112233445566778899aabbccddee056b", "112233445566778899aabbccddee056b") + sstore("112233445566778899aabbccddee056c", "112233445566778899aabbccddee056c") + sstore("112233445566778899aabbccddee056d", "112233445566778899aabbccddee056d") + sstore("112233445566778899aabbccddee056e", "112233445566778899aabbccddee056e") + sstore("112233445566778899aabbccddee056f", "112233445566778899aabbccddee056f") + sstore("112233445566778899aabbccddee0570", "112233445566778899aabbccddee0570") + sstore("112233445566778899aabbccddee0571", "112233445566778899aabbccddee0571") + sstore("112233445566778899aabbccddee0572", "112233445566778899aabbccddee0572") + sstore("112233445566778899aabbccddee0573", "112233445566778899aabbccddee0573") + sstore("112233445566778899aabbccddee0574", "112233445566778899aabbccddee0574") + sstore("112233445566778899aabbccddee0575", "112233445566778899aabbccddee0575") + sstore("112233445566778899aabbccddee0576", "112233445566778899aabbccddee0576") + sstore("112233445566778899aabbccddee0577", "112233445566778899aabbccddee0577") + sstore("112233445566778899aabbccddee0578", "112233445566778899aabbccddee0578") + sstore("112233445566778899aabbccddee0579", "112233445566778899aabbccddee0579") + sstore("112233445566778899aabbccddee057a", "112233445566778899aabbccddee057a") + sstore("112233445566778899aabbccddee057b", "112233445566778899aabbccddee057b") + sstore("112233445566778899aabbccddee057c", "112233445566778899aabbccddee057c") + sstore("112233445566778899aabbccddee057d", "112233445566778899aabbccddee057d") + sstore("112233445566778899aabbccddee057e", "112233445566778899aabbccddee057e") + sstore("112233445566778899aabbccddee057f", "112233445566778899aabbccddee057f") + sstore("112233445566778899aabbccddee0580", "112233445566778899aabbccddee0580") + sstore("112233445566778899aabbccddee0581", "112233445566778899aabbccddee0581") + sstore("112233445566778899aabbccddee0582", "112233445566778899aabbccddee0582") + sstore("112233445566778899aabbccddee0583", "112233445566778899aabbccddee0583") + sstore("112233445566778899aabbccddee0584", "112233445566778899aabbccddee0584") + sstore("112233445566778899aabbccddee0585", "112233445566778899aabbccddee0585") + sstore("112233445566778899aabbccddee0586", "112233445566778899aabbccddee0586") + sstore("112233445566778899aabbccddee0587", "112233445566778899aabbccddee0587") + sstore("112233445566778899aabbccddee0588", "112233445566778899aabbccddee0588") + sstore("112233445566778899aabbccddee0589", "112233445566778899aabbccddee0589") + sstore("112233445566778899aabbccddee058a", "112233445566778899aabbccddee058a") + sstore("112233445566778899aabbccddee058b", "112233445566778899aabbccddee058b") + sstore("112233445566778899aabbccddee058c", "112233445566778899aabbccddee058c") + sstore("112233445566778899aabbccddee058d", "112233445566778899aabbccddee058d") + sstore("112233445566778899aabbccddee058e", "112233445566778899aabbccddee058e") + sstore("112233445566778899aabbccddee058f", "112233445566778899aabbccddee058f") + sstore("112233445566778899aabbccddee0590", "112233445566778899aabbccddee0590") + sstore("112233445566778899aabbccddee0591", "112233445566778899aabbccddee0591") + sstore("112233445566778899aabbccddee0592", "112233445566778899aabbccddee0592") + sstore("112233445566778899aabbccddee0593", "112233445566778899aabbccddee0593") + sstore("112233445566778899aabbccddee0594", "112233445566778899aabbccddee0594") + sstore("112233445566778899aabbccddee0595", "112233445566778899aabbccddee0595") + sstore("112233445566778899aabbccddee0596", "112233445566778899aabbccddee0596") + sstore("112233445566778899aabbccddee0597", "112233445566778899aabbccddee0597") + sstore("112233445566778899aabbccddee0598", "112233445566778899aabbccddee0598") + sstore("112233445566778899aabbccddee0599", "112233445566778899aabbccddee0599") + sstore("112233445566778899aabbccddee059a", "112233445566778899aabbccddee059a") + sstore("112233445566778899aabbccddee059b", "112233445566778899aabbccddee059b") + sstore("112233445566778899aabbccddee059c", "112233445566778899aabbccddee059c") + sstore("112233445566778899aabbccddee059d", "112233445566778899aabbccddee059d") + sstore("112233445566778899aabbccddee059e", "112233445566778899aabbccddee059e") + sstore("112233445566778899aabbccddee059f", "112233445566778899aabbccddee059f") + sstore("112233445566778899aabbccddee05a0", "112233445566778899aabbccddee05a0") + sstore("112233445566778899aabbccddee05a1", "112233445566778899aabbccddee05a1") + sstore("112233445566778899aabbccddee05a2", "112233445566778899aabbccddee05a2") + sstore("112233445566778899aabbccddee05a3", "112233445566778899aabbccddee05a3") + sstore("112233445566778899aabbccddee05a4", "112233445566778899aabbccddee05a4") + sstore("112233445566778899aabbccddee05a5", "112233445566778899aabbccddee05a5") + sstore("112233445566778899aabbccddee05a6", "112233445566778899aabbccddee05a6") + sstore("112233445566778899aabbccddee05a7", "112233445566778899aabbccddee05a7") + sstore("112233445566778899aabbccddee05a8", "112233445566778899aabbccddee05a8") + sstore("112233445566778899aabbccddee05a9", "112233445566778899aabbccddee05a9") + sstore("112233445566778899aabbccddee05aa", "112233445566778899aabbccddee05aa") + sstore("112233445566778899aabbccddee05ab", "112233445566778899aabbccddee05ab") + sstore("112233445566778899aabbccddee05ac", "112233445566778899aabbccddee05ac") + sstore("112233445566778899aabbccddee05ad", "112233445566778899aabbccddee05ad") + sstore("112233445566778899aabbccddee05ae", "112233445566778899aabbccddee05ae") + sstore("112233445566778899aabbccddee05af", "112233445566778899aabbccddee05af") + sstore("112233445566778899aabbccddee05b0", "112233445566778899aabbccddee05b0") + sstore("112233445566778899aabbccddee05b1", "112233445566778899aabbccddee05b1") + sstore("112233445566778899aabbccddee05b2", "112233445566778899aabbccddee05b2") + sstore("112233445566778899aabbccddee05b3", "112233445566778899aabbccddee05b3") + sstore("112233445566778899aabbccddee05b4", "112233445566778899aabbccddee05b4") + sstore("112233445566778899aabbccddee05b5", "112233445566778899aabbccddee05b5") + sstore("112233445566778899aabbccddee05b6", "112233445566778899aabbccddee05b6") + sstore("112233445566778899aabbccddee05b7", "112233445566778899aabbccddee05b7") + sstore("112233445566778899aabbccddee05b8", "112233445566778899aabbccddee05b8") + sstore("112233445566778899aabbccddee05b9", "112233445566778899aabbccddee05b9") + sstore("112233445566778899aabbccddee05ba", "112233445566778899aabbccddee05ba") + sstore("112233445566778899aabbccddee05bb", "112233445566778899aabbccddee05bb") + sstore("112233445566778899aabbccddee05bc", "112233445566778899aabbccddee05bc") + sstore("112233445566778899aabbccddee05bd", "112233445566778899aabbccddee05bd") + sstore("112233445566778899aabbccddee05be", "112233445566778899aabbccddee05be") + sstore("112233445566778899aabbccddee05bf", "112233445566778899aabbccddee05bf") + sstore("112233445566778899aabbccddee05c0", "112233445566778899aabbccddee05c0") + sstore("112233445566778899aabbccddee05c1", "112233445566778899aabbccddee05c1") + sstore("112233445566778899aabbccddee05c2", "112233445566778899aabbccddee05c2") + sstore("112233445566778899aabbccddee05c3", "112233445566778899aabbccddee05c3") + sstore("112233445566778899aabbccddee05c4", "112233445566778899aabbccddee05c4") + sstore("112233445566778899aabbccddee05c5", "112233445566778899aabbccddee05c5") + sstore("112233445566778899aabbccddee05c6", "112233445566778899aabbccddee05c6") + sstore("112233445566778899aabbccddee05c7", "112233445566778899aabbccddee05c7") + sstore("112233445566778899aabbccddee05c8", "112233445566778899aabbccddee05c8") + sstore("112233445566778899aabbccddee05c9", "112233445566778899aabbccddee05c9") + sstore("112233445566778899aabbccddee05ca", "112233445566778899aabbccddee05ca") + sstore("112233445566778899aabbccddee05cb", "112233445566778899aabbccddee05cb") + sstore("112233445566778899aabbccddee05cc", "112233445566778899aabbccddee05cc") + sstore("112233445566778899aabbccddee05cd", "112233445566778899aabbccddee05cd") + sstore("112233445566778899aabbccddee05ce", "112233445566778899aabbccddee05ce") + sstore("112233445566778899aabbccddee05cf", "112233445566778899aabbccddee05cf") + sstore("112233445566778899aabbccddee05d0", "112233445566778899aabbccddee05d0") + sstore("112233445566778899aabbccddee05d1", "112233445566778899aabbccddee05d1") + sstore("112233445566778899aabbccddee05d2", "112233445566778899aabbccddee05d2") + sstore("112233445566778899aabbccddee05d3", "112233445566778899aabbccddee05d3") + sstore("112233445566778899aabbccddee05d4", "112233445566778899aabbccddee05d4") + sstore("112233445566778899aabbccddee05d5", "112233445566778899aabbccddee05d5") + sstore("112233445566778899aabbccddee05d6", "112233445566778899aabbccddee05d6") + sstore("112233445566778899aabbccddee05d7", "112233445566778899aabbccddee05d7") + sstore("112233445566778899aabbccddee05d8", "112233445566778899aabbccddee05d8") + sstore("112233445566778899aabbccddee05d9", "112233445566778899aabbccddee05d9") + sstore("112233445566778899aabbccddee05da", "112233445566778899aabbccddee05da") + sstore("112233445566778899aabbccddee05db", "112233445566778899aabbccddee05db") + sstore("112233445566778899aabbccddee05dc", "112233445566778899aabbccddee05dc") + sstore("112233445566778899aabbccddee05dd", "112233445566778899aabbccddee05dd") + sstore("112233445566778899aabbccddee05de", "112233445566778899aabbccddee05de") + sstore("112233445566778899aabbccddee05df", "112233445566778899aabbccddee05df") + sstore("112233445566778899aabbccddee05e0", "112233445566778899aabbccddee05e0") + sstore("112233445566778899aabbccddee05e1", "112233445566778899aabbccddee05e1") + sstore("112233445566778899aabbccddee05e2", "112233445566778899aabbccddee05e2") + sstore("112233445566778899aabbccddee05e3", "112233445566778899aabbccddee05e3") + sstore("112233445566778899aabbccddee05e4", "112233445566778899aabbccddee05e4") + sstore("112233445566778899aabbccddee05e5", "112233445566778899aabbccddee05e5") + sstore("112233445566778899aabbccddee05e6", "112233445566778899aabbccddee05e6") + sstore("112233445566778899aabbccddee05e7", "112233445566778899aabbccddee05e7") + sstore("112233445566778899aabbccddee05e8", "112233445566778899aabbccddee05e8") + sstore("112233445566778899aabbccddee05e9", "112233445566778899aabbccddee05e9") + sstore("112233445566778899aabbccddee05ea", "112233445566778899aabbccddee05ea") + sstore("112233445566778899aabbccddee05eb", "112233445566778899aabbccddee05eb") + sstore("112233445566778899aabbccddee05ec", "112233445566778899aabbccddee05ec") + sstore("112233445566778899aabbccddee05ed", "112233445566778899aabbccddee05ed") + sstore("112233445566778899aabbccddee05ee", "112233445566778899aabbccddee05ee") + sstore("112233445566778899aabbccddee05ef", "112233445566778899aabbccddee05ef") + sstore("112233445566778899aabbccddee05f0", "112233445566778899aabbccddee05f0") + sstore("112233445566778899aabbccddee05f1", "112233445566778899aabbccddee05f1") + sstore("112233445566778899aabbccddee05f2", "112233445566778899aabbccddee05f2") + sstore("112233445566778899aabbccddee05f3", "112233445566778899aabbccddee05f3") + sstore("112233445566778899aabbccddee05f4", "112233445566778899aabbccddee05f4") + sstore("112233445566778899aabbccddee05f5", "112233445566778899aabbccddee05f5") + sstore("112233445566778899aabbccddee05f6", "112233445566778899aabbccddee05f6") + sstore("112233445566778899aabbccddee05f7", "112233445566778899aabbccddee05f7") + sstore("112233445566778899aabbccddee05f8", "112233445566778899aabbccddee05f8") + sstore("112233445566778899aabbccddee05f9", "112233445566778899aabbccddee05f9") + sstore("112233445566778899aabbccddee05fa", "112233445566778899aabbccddee05fa") + sstore("112233445566778899aabbccddee05fb", "112233445566778899aabbccddee05fb") + sstore("112233445566778899aabbccddee05fc", "112233445566778899aabbccddee05fc") + sstore("112233445566778899aabbccddee05fd", "112233445566778899aabbccddee05fd") + sstore("112233445566778899aabbccddee05fe", "112233445566778899aabbccddee05fe") + sstore("112233445566778899aabbccddee05ff", "112233445566778899aabbccddee05ff") + sstore("112233445566778899aabbccddee0600", "112233445566778899aabbccddee0600") + sstore("112233445566778899aabbccddee0601", "112233445566778899aabbccddee0601") + sstore("112233445566778899aabbccddee0602", "112233445566778899aabbccddee0602") + sstore("112233445566778899aabbccddee0603", "112233445566778899aabbccddee0603") + sstore("112233445566778899aabbccddee0604", "112233445566778899aabbccddee0604") + sstore("112233445566778899aabbccddee0605", "112233445566778899aabbccddee0605") + sstore("112233445566778899aabbccddee0606", "112233445566778899aabbccddee0606") + sstore("112233445566778899aabbccddee0607", "112233445566778899aabbccddee0607") + sstore("112233445566778899aabbccddee0608", "112233445566778899aabbccddee0608") + sstore("112233445566778899aabbccddee0609", "112233445566778899aabbccddee0609") + sstore("112233445566778899aabbccddee060a", "112233445566778899aabbccddee060a") + sstore("112233445566778899aabbccddee060b", "112233445566778899aabbccddee060b") + sstore("112233445566778899aabbccddee060c", "112233445566778899aabbccddee060c") + sstore("112233445566778899aabbccddee060d", "112233445566778899aabbccddee060d") + sstore("112233445566778899aabbccddee060e", "112233445566778899aabbccddee060e") + sstore("112233445566778899aabbccddee060f", "112233445566778899aabbccddee060f") + sstore("112233445566778899aabbccddee0610", "112233445566778899aabbccddee0610") + sstore("112233445566778899aabbccddee0611", "112233445566778899aabbccddee0611") + sstore("112233445566778899aabbccddee0612", "112233445566778899aabbccddee0612") + sstore("112233445566778899aabbccddee0613", "112233445566778899aabbccddee0613") + sstore("112233445566778899aabbccddee0614", "112233445566778899aabbccddee0614") + sstore("112233445566778899aabbccddee0615", "112233445566778899aabbccddee0615") + sstore("112233445566778899aabbccddee0616", "112233445566778899aabbccddee0616") + sstore("112233445566778899aabbccddee0617", "112233445566778899aabbccddee0617") + sstore("112233445566778899aabbccddee0618", "112233445566778899aabbccddee0618") + sstore("112233445566778899aabbccddee0619", "112233445566778899aabbccddee0619") + sstore("112233445566778899aabbccddee061a", "112233445566778899aabbccddee061a") + sstore("112233445566778899aabbccddee061b", "112233445566778899aabbccddee061b") + sstore("112233445566778899aabbccddee061c", "112233445566778899aabbccddee061c") + sstore("112233445566778899aabbccddee061d", "112233445566778899aabbccddee061d") + sstore("112233445566778899aabbccddee061e", "112233445566778899aabbccddee061e") + sstore("112233445566778899aabbccddee061f", "112233445566778899aabbccddee061f") + sstore("112233445566778899aabbccddee0620", "112233445566778899aabbccddee0620") + sstore("112233445566778899aabbccddee0621", "112233445566778899aabbccddee0621") + sstore("112233445566778899aabbccddee0622", "112233445566778899aabbccddee0622") + sstore("112233445566778899aabbccddee0623", "112233445566778899aabbccddee0623") + sstore("112233445566778899aabbccddee0624", "112233445566778899aabbccddee0624") + sstore("112233445566778899aabbccddee0625", "112233445566778899aabbccddee0625") + sstore("112233445566778899aabbccddee0626", "112233445566778899aabbccddee0626") + sstore("112233445566778899aabbccddee0627", "112233445566778899aabbccddee0627") + sstore("112233445566778899aabbccddee0628", "112233445566778899aabbccddee0628") + sstore("112233445566778899aabbccddee0629", "112233445566778899aabbccddee0629") + sstore("112233445566778899aabbccddee062a", "112233445566778899aabbccddee062a") + sstore("112233445566778899aabbccddee062b", "112233445566778899aabbccddee062b") + sstore("112233445566778899aabbccddee062c", "112233445566778899aabbccddee062c") + sstore("112233445566778899aabbccddee062d", "112233445566778899aabbccddee062d") + sstore("112233445566778899aabbccddee062e", "112233445566778899aabbccddee062e") + sstore("112233445566778899aabbccddee062f", "112233445566778899aabbccddee062f") + sstore("112233445566778899aabbccddee0630", "112233445566778899aabbccddee0630") + sstore("112233445566778899aabbccddee0631", "112233445566778899aabbccddee0631") + sstore("112233445566778899aabbccddee0632", "112233445566778899aabbccddee0632") + sstore("112233445566778899aabbccddee0633", "112233445566778899aabbccddee0633") + sstore("112233445566778899aabbccddee0634", "112233445566778899aabbccddee0634") + sstore("112233445566778899aabbccddee0635", "112233445566778899aabbccddee0635") + sstore("112233445566778899aabbccddee0636", "112233445566778899aabbccddee0636") + sstore("112233445566778899aabbccddee0637", "112233445566778899aabbccddee0637") + sstore("112233445566778899aabbccddee0638", "112233445566778899aabbccddee0638") + sstore("112233445566778899aabbccddee0639", "112233445566778899aabbccddee0639") + sstore("112233445566778899aabbccddee063a", "112233445566778899aabbccddee063a") + sstore("112233445566778899aabbccddee063b", "112233445566778899aabbccddee063b") + sstore("112233445566778899aabbccddee063c", "112233445566778899aabbccddee063c") + sstore("112233445566778899aabbccddee063d", "112233445566778899aabbccddee063d") + sstore("112233445566778899aabbccddee063e", "112233445566778899aabbccddee063e") + sstore("112233445566778899aabbccddee063f", "112233445566778899aabbccddee063f") + sstore("112233445566778899aabbccddee0640", "112233445566778899aabbccddee0640") + sstore("112233445566778899aabbccddee0641", "112233445566778899aabbccddee0641") + sstore("112233445566778899aabbccddee0642", "112233445566778899aabbccddee0642") + sstore("112233445566778899aabbccddee0643", "112233445566778899aabbccddee0643") + sstore("112233445566778899aabbccddee0644", "112233445566778899aabbccddee0644") + sstore("112233445566778899aabbccddee0645", "112233445566778899aabbccddee0645") + sstore("112233445566778899aabbccddee0646", "112233445566778899aabbccddee0646") + sstore("112233445566778899aabbccddee0647", "112233445566778899aabbccddee0647") + sstore("112233445566778899aabbccddee0648", "112233445566778899aabbccddee0648") + sstore("112233445566778899aabbccddee0649", "112233445566778899aabbccddee0649") + sstore("112233445566778899aabbccddee064a", "112233445566778899aabbccddee064a") + sstore("112233445566778899aabbccddee064b", "112233445566778899aabbccddee064b") + sstore("112233445566778899aabbccddee064c", "112233445566778899aabbccddee064c") + sstore("112233445566778899aabbccddee064d", "112233445566778899aabbccddee064d") + sstore("112233445566778899aabbccddee064e", "112233445566778899aabbccddee064e") + sstore("112233445566778899aabbccddee064f", "112233445566778899aabbccddee064f") + sstore("112233445566778899aabbccddee0650", "112233445566778899aabbccddee0650") + sstore("112233445566778899aabbccddee0651", "112233445566778899aabbccddee0651") + sstore("112233445566778899aabbccddee0652", "112233445566778899aabbccddee0652") + sstore("112233445566778899aabbccddee0653", "112233445566778899aabbccddee0653") + sstore("112233445566778899aabbccddee0654", "112233445566778899aabbccddee0654") + sstore("112233445566778899aabbccddee0655", "112233445566778899aabbccddee0655") + sstore("112233445566778899aabbccddee0656", "112233445566778899aabbccddee0656") + sstore("112233445566778899aabbccddee0657", "112233445566778899aabbccddee0657") + sstore("112233445566778899aabbccddee0658", "112233445566778899aabbccddee0658") + sstore("112233445566778899aabbccddee0659", "112233445566778899aabbccddee0659") + sstore("112233445566778899aabbccddee065a", "112233445566778899aabbccddee065a") + sstore("112233445566778899aabbccddee065b", "112233445566778899aabbccddee065b") + sstore("112233445566778899aabbccddee065c", "112233445566778899aabbccddee065c") + sstore("112233445566778899aabbccddee065d", "112233445566778899aabbccddee065d") + sstore("112233445566778899aabbccddee065e", "112233445566778899aabbccddee065e") + sstore("112233445566778899aabbccddee065f", "112233445566778899aabbccddee065f") + sstore("112233445566778899aabbccddee0660", "112233445566778899aabbccddee0660") + sstore("112233445566778899aabbccddee0661", "112233445566778899aabbccddee0661") + sstore("112233445566778899aabbccddee0662", "112233445566778899aabbccddee0662") + sstore("112233445566778899aabbccddee0663", "112233445566778899aabbccddee0663") + sstore("112233445566778899aabbccddee0664", "112233445566778899aabbccddee0664") + sstore("112233445566778899aabbccddee0665", "112233445566778899aabbccddee0665") + sstore("112233445566778899aabbccddee0666", "112233445566778899aabbccddee0666") + sstore("112233445566778899aabbccddee0667", "112233445566778899aabbccddee0667") + sstore("112233445566778899aabbccddee0668", "112233445566778899aabbccddee0668") + sstore("112233445566778899aabbccddee0669", "112233445566778899aabbccddee0669") + sstore("112233445566778899aabbccddee066a", "112233445566778899aabbccddee066a") + sstore("112233445566778899aabbccddee066b", "112233445566778899aabbccddee066b") + sstore("112233445566778899aabbccddee066c", "112233445566778899aabbccddee066c") + sstore("112233445566778899aabbccddee066d", "112233445566778899aabbccddee066d") + sstore("112233445566778899aabbccddee066e", "112233445566778899aabbccddee066e") + sstore("112233445566778899aabbccddee066f", "112233445566778899aabbccddee066f") + sstore("112233445566778899aabbccddee0670", "112233445566778899aabbccddee0670") + sstore("112233445566778899aabbccddee0671", "112233445566778899aabbccddee0671") + sstore("112233445566778899aabbccddee0672", "112233445566778899aabbccddee0672") + sstore("112233445566778899aabbccddee0673", "112233445566778899aabbccddee0673") + sstore("112233445566778899aabbccddee0674", "112233445566778899aabbccddee0674") + sstore("112233445566778899aabbccddee0675", "112233445566778899aabbccddee0675") + sstore("112233445566778899aabbccddee0676", "112233445566778899aabbccddee0676") + sstore("112233445566778899aabbccddee0677", "112233445566778899aabbccddee0677") + sstore("112233445566778899aabbccddee0678", "112233445566778899aabbccddee0678") + sstore("112233445566778899aabbccddee0679", "112233445566778899aabbccddee0679") + sstore("112233445566778899aabbccddee067a", "112233445566778899aabbccddee067a") + sstore("112233445566778899aabbccddee067b", "112233445566778899aabbccddee067b") + sstore("112233445566778899aabbccddee067c", "112233445566778899aabbccddee067c") + sstore("112233445566778899aabbccddee067d", "112233445566778899aabbccddee067d") + sstore("112233445566778899aabbccddee067e", "112233445566778899aabbccddee067e") + sstore("112233445566778899aabbccddee067f", "112233445566778899aabbccddee067f") + sstore("112233445566778899aabbccddee0680", "112233445566778899aabbccddee0680") + sstore("112233445566778899aabbccddee0681", "112233445566778899aabbccddee0681") + sstore("112233445566778899aabbccddee0682", "112233445566778899aabbccddee0682") + sstore("112233445566778899aabbccddee0683", "112233445566778899aabbccddee0683") + sstore("112233445566778899aabbccddee0684", "112233445566778899aabbccddee0684") + sstore("112233445566778899aabbccddee0685", "112233445566778899aabbccddee0685") + sstore("112233445566778899aabbccddee0686", "112233445566778899aabbccddee0686") + sstore("112233445566778899aabbccddee0687", "112233445566778899aabbccddee0687") + sstore("112233445566778899aabbccddee0688", "112233445566778899aabbccddee0688") + sstore("112233445566778899aabbccddee0689", "112233445566778899aabbccddee0689") + sstore("112233445566778899aabbccddee068a", "112233445566778899aabbccddee068a") + sstore("112233445566778899aabbccddee068b", "112233445566778899aabbccddee068b") + sstore("112233445566778899aabbccddee068c", "112233445566778899aabbccddee068c") + sstore("112233445566778899aabbccddee068d", "112233445566778899aabbccddee068d") + sstore("112233445566778899aabbccddee068e", "112233445566778899aabbccddee068e") + sstore("112233445566778899aabbccddee068f", "112233445566778899aabbccddee068f") + sstore("112233445566778899aabbccddee0690", "112233445566778899aabbccddee0690") + sstore("112233445566778899aabbccddee0691", "112233445566778899aabbccddee0691") + sstore("112233445566778899aabbccddee0692", "112233445566778899aabbccddee0692") + sstore("112233445566778899aabbccddee0693", "112233445566778899aabbccddee0693") + sstore("112233445566778899aabbccddee0694", "112233445566778899aabbccddee0694") + sstore("112233445566778899aabbccddee0695", "112233445566778899aabbccddee0695") + sstore("112233445566778899aabbccddee0696", "112233445566778899aabbccddee0696") + sstore("112233445566778899aabbccddee0697", "112233445566778899aabbccddee0697") + sstore("112233445566778899aabbccddee0698", "112233445566778899aabbccddee0698") + sstore("112233445566778899aabbccddee0699", "112233445566778899aabbccddee0699") + sstore("112233445566778899aabbccddee069a", "112233445566778899aabbccddee069a") + sstore("112233445566778899aabbccddee069b", "112233445566778899aabbccddee069b") + sstore("112233445566778899aabbccddee069c", "112233445566778899aabbccddee069c") + sstore("112233445566778899aabbccddee069d", "112233445566778899aabbccddee069d") + sstore("112233445566778899aabbccddee069e", "112233445566778899aabbccddee069e") + sstore("112233445566778899aabbccddee069f", "112233445566778899aabbccddee069f") + sstore("112233445566778899aabbccddee06a0", "112233445566778899aabbccddee06a0") + sstore("112233445566778899aabbccddee06a1", "112233445566778899aabbccddee06a1") + sstore("112233445566778899aabbccddee06a2", "112233445566778899aabbccddee06a2") + sstore("112233445566778899aabbccddee06a3", "112233445566778899aabbccddee06a3") + sstore("112233445566778899aabbccddee06a4", "112233445566778899aabbccddee06a4") + sstore("112233445566778899aabbccddee06a5", "112233445566778899aabbccddee06a5") + sstore("112233445566778899aabbccddee06a6", "112233445566778899aabbccddee06a6") + sstore("112233445566778899aabbccddee06a7", "112233445566778899aabbccddee06a7") + sstore("112233445566778899aabbccddee06a8", "112233445566778899aabbccddee06a8") + sstore("112233445566778899aabbccddee06a9", "112233445566778899aabbccddee06a9") + sstore("112233445566778899aabbccddee06aa", "112233445566778899aabbccddee06aa") + sstore("112233445566778899aabbccddee06ab", "112233445566778899aabbccddee06ab") + sstore("112233445566778899aabbccddee06ac", "112233445566778899aabbccddee06ac") + sstore("112233445566778899aabbccddee06ad", "112233445566778899aabbccddee06ad") + sstore("112233445566778899aabbccddee06ae", "112233445566778899aabbccddee06ae") + sstore("112233445566778899aabbccddee06af", "112233445566778899aabbccddee06af") + sstore("112233445566778899aabbccddee06b0", "112233445566778899aabbccddee06b0") + sstore("112233445566778899aabbccddee06b1", "112233445566778899aabbccddee06b1") + sstore("112233445566778899aabbccddee06b2", "112233445566778899aabbccddee06b2") + sstore("112233445566778899aabbccddee06b3", "112233445566778899aabbccddee06b3") + sstore("112233445566778899aabbccddee06b4", "112233445566778899aabbccddee06b4") + sstore("112233445566778899aabbccddee06b5", "112233445566778899aabbccddee06b5") + sstore("112233445566778899aabbccddee06b6", "112233445566778899aabbccddee06b6") + sstore("112233445566778899aabbccddee06b7", "112233445566778899aabbccddee06b7") + sstore("112233445566778899aabbccddee06b8", "112233445566778899aabbccddee06b8") + sstore("112233445566778899aabbccddee06b9", "112233445566778899aabbccddee06b9") + sstore("112233445566778899aabbccddee06ba", "112233445566778899aabbccddee06ba") + sstore("112233445566778899aabbccddee06bb", "112233445566778899aabbccddee06bb") + sstore("112233445566778899aabbccddee06bc", "112233445566778899aabbccddee06bc") + sstore("112233445566778899aabbccddee06bd", "112233445566778899aabbccddee06bd") + sstore("112233445566778899aabbccddee06be", "112233445566778899aabbccddee06be") + sstore("112233445566778899aabbccddee06bf", "112233445566778899aabbccddee06bf") + sstore("112233445566778899aabbccddee06c0", "112233445566778899aabbccddee06c0") + sstore("112233445566778899aabbccddee06c1", "112233445566778899aabbccddee06c1") + sstore("112233445566778899aabbccddee06c2", "112233445566778899aabbccddee06c2") + sstore("112233445566778899aabbccddee06c3", "112233445566778899aabbccddee06c3") + sstore("112233445566778899aabbccddee06c4", "112233445566778899aabbccddee06c4") + sstore("112233445566778899aabbccddee06c5", "112233445566778899aabbccddee06c5") + sstore("112233445566778899aabbccddee06c6", "112233445566778899aabbccddee06c6") + sstore("112233445566778899aabbccddee06c7", "112233445566778899aabbccddee06c7") + sstore("112233445566778899aabbccddee06c8", "112233445566778899aabbccddee06c8") + sstore("112233445566778899aabbccddee06c9", "112233445566778899aabbccddee06c9") + sstore("112233445566778899aabbccddee06ca", "112233445566778899aabbccddee06ca") + sstore("112233445566778899aabbccddee06cb", "112233445566778899aabbccddee06cb") + sstore("112233445566778899aabbccddee06cc", "112233445566778899aabbccddee06cc") + sstore("112233445566778899aabbccddee06cd", "112233445566778899aabbccddee06cd") + sstore("112233445566778899aabbccddee06ce", "112233445566778899aabbccddee06ce") + sstore("112233445566778899aabbccddee06cf", "112233445566778899aabbccddee06cf") + sstore("112233445566778899aabbccddee06d0", "112233445566778899aabbccddee06d0") + sstore("112233445566778899aabbccddee06d1", "112233445566778899aabbccddee06d1") + sstore("112233445566778899aabbccddee06d2", "112233445566778899aabbccddee06d2") + sstore("112233445566778899aabbccddee06d3", "112233445566778899aabbccddee06d3") + sstore("112233445566778899aabbccddee06d4", "112233445566778899aabbccddee06d4") + sstore("112233445566778899aabbccddee06d5", "112233445566778899aabbccddee06d5") + sstore("112233445566778899aabbccddee06d6", "112233445566778899aabbccddee06d6") + sstore("112233445566778899aabbccddee06d7", "112233445566778899aabbccddee06d7") + sstore("112233445566778899aabbccddee06d8", "112233445566778899aabbccddee06d8") + sstore("112233445566778899aabbccddee06d9", "112233445566778899aabbccddee06d9") + sstore("112233445566778899aabbccddee06da", "112233445566778899aabbccddee06da") + sstore("112233445566778899aabbccddee06db", "112233445566778899aabbccddee06db") + sstore("112233445566778899aabbccddee06dc", "112233445566778899aabbccddee06dc") + sstore("112233445566778899aabbccddee06dd", "112233445566778899aabbccddee06dd") + sstore("112233445566778899aabbccddee06de", "112233445566778899aabbccddee06de") + sstore("112233445566778899aabbccddee06df", "112233445566778899aabbccddee06df") + sstore("112233445566778899aabbccddee06e0", "112233445566778899aabbccddee06e0") + sstore("112233445566778899aabbccddee06e1", "112233445566778899aabbccddee06e1") + sstore("112233445566778899aabbccddee06e2", "112233445566778899aabbccddee06e2") + sstore("112233445566778899aabbccddee06e3", "112233445566778899aabbccddee06e3") + sstore("112233445566778899aabbccddee06e4", "112233445566778899aabbccddee06e4") + sstore("112233445566778899aabbccddee06e5", "112233445566778899aabbccddee06e5") + sstore("112233445566778899aabbccddee06e6", "112233445566778899aabbccddee06e6") + sstore("112233445566778899aabbccddee06e7", "112233445566778899aabbccddee06e7") + sstore("112233445566778899aabbccddee06e8", "112233445566778899aabbccddee06e8") + sstore("112233445566778899aabbccddee06e9", "112233445566778899aabbccddee06e9") + sstore("112233445566778899aabbccddee06ea", "112233445566778899aabbccddee06ea") + sstore("112233445566778899aabbccddee06eb", "112233445566778899aabbccddee06eb") + sstore("112233445566778899aabbccddee06ec", "112233445566778899aabbccddee06ec") + sstore("112233445566778899aabbccddee06ed", "112233445566778899aabbccddee06ed") + sstore("112233445566778899aabbccddee06ee", "112233445566778899aabbccddee06ee") + sstore("112233445566778899aabbccddee06ef", "112233445566778899aabbccddee06ef") + sstore("112233445566778899aabbccddee06f0", "112233445566778899aabbccddee06f0") + sstore("112233445566778899aabbccddee06f1", "112233445566778899aabbccddee06f1") + sstore("112233445566778899aabbccddee06f2", "112233445566778899aabbccddee06f2") + sstore("112233445566778899aabbccddee06f3", "112233445566778899aabbccddee06f3") + sstore("112233445566778899aabbccddee06f4", "112233445566778899aabbccddee06f4") + sstore("112233445566778899aabbccddee06f5", "112233445566778899aabbccddee06f5") + sstore("112233445566778899aabbccddee06f6", "112233445566778899aabbccddee06f6") + sstore("112233445566778899aabbccddee06f7", "112233445566778899aabbccddee06f7") + sstore("112233445566778899aabbccddee06f8", "112233445566778899aabbccddee06f8") + sstore("112233445566778899aabbccddee06f9", "112233445566778899aabbccddee06f9") + sstore("112233445566778899aabbccddee06fa", "112233445566778899aabbccddee06fa") + sstore("112233445566778899aabbccddee06fb", "112233445566778899aabbccddee06fb") + sstore("112233445566778899aabbccddee06fc", "112233445566778899aabbccddee06fc") + sstore("112233445566778899aabbccddee06fd", "112233445566778899aabbccddee06fd") + sstore("112233445566778899aabbccddee06fe", "112233445566778899aabbccddee06fe") + sstore("112233445566778899aabbccddee06ff", "112233445566778899aabbccddee06ff") + sstore("112233445566778899aabbccddee0700", "112233445566778899aabbccddee0700") + sstore("112233445566778899aabbccddee0701", "112233445566778899aabbccddee0701") + sstore("112233445566778899aabbccddee0702", "112233445566778899aabbccddee0702") + sstore("112233445566778899aabbccddee0703", "112233445566778899aabbccddee0703") + sstore("112233445566778899aabbccddee0704", "112233445566778899aabbccddee0704") + sstore("112233445566778899aabbccddee0705", "112233445566778899aabbccddee0705") + sstore("112233445566778899aabbccddee0706", "112233445566778899aabbccddee0706") + sstore("112233445566778899aabbccddee0707", "112233445566778899aabbccddee0707") + sstore("112233445566778899aabbccddee0708", "112233445566778899aabbccddee0708") + sstore("112233445566778899aabbccddee0709", "112233445566778899aabbccddee0709") + sstore("112233445566778899aabbccddee070a", "112233445566778899aabbccddee070a") + sstore("112233445566778899aabbccddee070b", "112233445566778899aabbccddee070b") + sstore("112233445566778899aabbccddee070c", "112233445566778899aabbccddee070c") + sstore("112233445566778899aabbccddee070d", "112233445566778899aabbccddee070d") + sstore("112233445566778899aabbccddee070e", "112233445566778899aabbccddee070e") + sstore("112233445566778899aabbccddee070f", "112233445566778899aabbccddee070f") + sstore("112233445566778899aabbccddee0710", "112233445566778899aabbccddee0710") + sstore("112233445566778899aabbccddee0711", "112233445566778899aabbccddee0711") + sstore("112233445566778899aabbccddee0712", "112233445566778899aabbccddee0712") + sstore("112233445566778899aabbccddee0713", "112233445566778899aabbccddee0713") + sstore("112233445566778899aabbccddee0714", "112233445566778899aabbccddee0714") + sstore("112233445566778899aabbccddee0715", "112233445566778899aabbccddee0715") + sstore("112233445566778899aabbccddee0716", "112233445566778899aabbccddee0716") + sstore("112233445566778899aabbccddee0717", "112233445566778899aabbccddee0717") + sstore("112233445566778899aabbccddee0718", "112233445566778899aabbccddee0718") + sstore("112233445566778899aabbccddee0719", "112233445566778899aabbccddee0719") + sstore("112233445566778899aabbccddee071a", "112233445566778899aabbccddee071a") + sstore("112233445566778899aabbccddee071b", "112233445566778899aabbccddee071b") + sstore("112233445566778899aabbccddee071c", "112233445566778899aabbccddee071c") + sstore("112233445566778899aabbccddee071d", "112233445566778899aabbccddee071d") + sstore("112233445566778899aabbccddee071e", "112233445566778899aabbccddee071e") + sstore("112233445566778899aabbccddee071f", "112233445566778899aabbccddee071f") + sstore("112233445566778899aabbccddee0720", "112233445566778899aabbccddee0720") + sstore("112233445566778899aabbccddee0721", "112233445566778899aabbccddee0721") + sstore("112233445566778899aabbccddee0722", "112233445566778899aabbccddee0722") + sstore("112233445566778899aabbccddee0723", "112233445566778899aabbccddee0723") + sstore("112233445566778899aabbccddee0724", "112233445566778899aabbccddee0724") + sstore("112233445566778899aabbccddee0725", "112233445566778899aabbccddee0725") + sstore("112233445566778899aabbccddee0726", "112233445566778899aabbccddee0726") + sstore("112233445566778899aabbccddee0727", "112233445566778899aabbccddee0727") + sstore("112233445566778899aabbccddee0728", "112233445566778899aabbccddee0728") + sstore("112233445566778899aabbccddee0729", "112233445566778899aabbccddee0729") + sstore("112233445566778899aabbccddee072a", "112233445566778899aabbccddee072a") + sstore("112233445566778899aabbccddee072b", "112233445566778899aabbccddee072b") + sstore("112233445566778899aabbccddee072c", "112233445566778899aabbccddee072c") + sstore("112233445566778899aabbccddee072d", "112233445566778899aabbccddee072d") + sstore("112233445566778899aabbccddee072e", "112233445566778899aabbccddee072e") + sstore("112233445566778899aabbccddee072f", "112233445566778899aabbccddee072f") + sstore("112233445566778899aabbccddee0730", "112233445566778899aabbccddee0730") + sstore("112233445566778899aabbccddee0731", "112233445566778899aabbccddee0731") + sstore("112233445566778899aabbccddee0732", "112233445566778899aabbccddee0732") + sstore("112233445566778899aabbccddee0733", "112233445566778899aabbccddee0733") + sstore("112233445566778899aabbccddee0734", "112233445566778899aabbccddee0734") + sstore("112233445566778899aabbccddee0735", "112233445566778899aabbccddee0735") + sstore("112233445566778899aabbccddee0736", "112233445566778899aabbccddee0736") + sstore("112233445566778899aabbccddee0737", "112233445566778899aabbccddee0737") + sstore("112233445566778899aabbccddee0738", "112233445566778899aabbccddee0738") + sstore("112233445566778899aabbccddee0739", "112233445566778899aabbccddee0739") + sstore("112233445566778899aabbccddee073a", "112233445566778899aabbccddee073a") + sstore("112233445566778899aabbccddee073b", "112233445566778899aabbccddee073b") + sstore("112233445566778899aabbccddee073c", "112233445566778899aabbccddee073c") + sstore("112233445566778899aabbccddee073d", "112233445566778899aabbccddee073d") + sstore("112233445566778899aabbccddee073e", "112233445566778899aabbccddee073e") + sstore("112233445566778899aabbccddee073f", "112233445566778899aabbccddee073f") + sstore("112233445566778899aabbccddee0740", "112233445566778899aabbccddee0740") + sstore("112233445566778899aabbccddee0741", "112233445566778899aabbccddee0741") + sstore("112233445566778899aabbccddee0742", "112233445566778899aabbccddee0742") + sstore("112233445566778899aabbccddee0743", "112233445566778899aabbccddee0743") + sstore("112233445566778899aabbccddee0744", "112233445566778899aabbccddee0744") + sstore("112233445566778899aabbccddee0745", "112233445566778899aabbccddee0745") + sstore("112233445566778899aabbccddee0746", "112233445566778899aabbccddee0746") + sstore("112233445566778899aabbccddee0747", "112233445566778899aabbccddee0747") + sstore("112233445566778899aabbccddee0748", "112233445566778899aabbccddee0748") + sstore("112233445566778899aabbccddee0749", "112233445566778899aabbccddee0749") + sstore("112233445566778899aabbccddee074a", "112233445566778899aabbccddee074a") + sstore("112233445566778899aabbccddee074b", "112233445566778899aabbccddee074b") + sstore("112233445566778899aabbccddee074c", "112233445566778899aabbccddee074c") + sstore("112233445566778899aabbccddee074d", "112233445566778899aabbccddee074d") + sstore("112233445566778899aabbccddee074e", "112233445566778899aabbccddee074e") + sstore("112233445566778899aabbccddee074f", "112233445566778899aabbccddee074f") + sstore("112233445566778899aabbccddee0750", "112233445566778899aabbccddee0750") + return(0, 32) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// CodeGenerationError 2202: Code section too large for EOF. From 43b84f0f11012454f609242a89d342c8ea7b9b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 4 Dec 2024 03:25:52 +0100 Subject: [PATCH 0576/1340] Replace several unnecessary EOF validations with assertions --- libevmasm/Assembly.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 1cd3e11fa..19201545e 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1521,10 +1521,9 @@ LinkerObject const& Assembly::assembleEOF() const auto const subIdsReplacements = findReferencedContainers(); auto const referencedSubIds = keys(subIdsReplacements); - solRequire(!m_codeSections.empty(), AssemblyException, "Expected at least one code section."); - solRequire( + solAssert(!m_codeSections.empty(), "Expected at least one code section."); + solAssert( m_codeSections.front().inputs == 0 && m_codeSections.front().outputs == 0 && m_codeSections.front().nonReturning, - AssemblyException, "Expected the first code section to have zero inputs and be non-returning." ); @@ -1660,7 +1659,8 @@ LinkerObject const& Assembly::assembleEOF() const solAssert(tagPos != std::numeric_limits::max(), "Reference to tag without position."); ptrdiff_t const relativeJumpOffset = static_cast(tagPos) - (static_cast(refPos) + 2); - solRequire(-0x8000 <= relativeJumpOffset && relativeJumpOffset <= 0x7FFF, AssemblyException, "Relative jump too far"); + // This cannot happen in practice because we'll run into section size limit first. + solAssert(-0x8000 <= relativeJumpOffset && relativeJumpOffset <= 0x7FFF, "Relative jump too far"); solAssert(relativeJumpOffset < -2 || 0 <= relativeJumpOffset, "Relative jump offset into immediate argument."); setBigEndianUint16(ret.bytecode, refPos, static_cast(static_cast(relativeJumpOffset))); } From b5fed832739adbd12cdaacd915f340b461238427 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 16 Dec 2024 19:59:01 +0100 Subject: [PATCH 0577/1340] eof: Disable C++ tests which won't work for EOF. --- test/libevmasm/Assembler.cpp | 9 ++++++--- test/libevmasm/Optimiser.cpp | 8 +++++--- test/libsolidity/InlineAssembly.cpp | 8 +++++--- test/libsolidity/SolidityCompiler.cpp | 4 +++- test/libsolidity/ViewPureChecker.cpp | 3 ++- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index b1222b49d..3a6383002 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -37,6 +37,7 @@ using namespace solidity::langutil; using namespace solidity::evmasm; +using namespace solidity::test; using namespace std::string_literals; namespace solidity::frontend::test @@ -54,7 +55,7 @@ namespace BOOST_AUTO_TEST_SUITE(Assembler) -BOOST_AUTO_TEST_CASE(all_assembly_items) +BOOST_AUTO_TEST_CASE(all_assembly_items, *boost::unit_test::precondition(nonEOF())) { std::map indices = { { "root.asm", 0 }, @@ -216,7 +217,8 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) BOOST_CHECK_EQUAL(util::jsonCompactPrint(_assembly.assemblyJSON(indices)), util::jsonCompactPrint(jsonValue)); } -BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) +// TODO: Implement EOF counterpart +BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps, *boost::unit_test::precondition(nonEOF())) { EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); // Tests for 1, 2, 3 number of immutables. @@ -301,7 +303,8 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) } } -BOOST_AUTO_TEST_CASE(immutable) +// TODO: Implement EOF counterpart +BOOST_AUTO_TEST_CASE(immutable, *boost::unit_test::precondition(nonEOF())) { std::map indices = { { "root.asm", 0 }, diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 8ed413cfe..a8e9afeaf 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -41,6 +41,7 @@ using namespace solidity::langutil; using namespace solidity::evmasm; +using namespace solidity::test; namespace solidity::frontend::test { @@ -1329,13 +1330,14 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal) ); } -BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) +BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies, *boost::unit_test::precondition(nonEOF())) { // This tests that tags from subassemblies are not removed // if they are referenced by a super-assembly. Furthermore, // tag unifications (due to block deduplication) is also // visible at the super-assembly. + solAssert(!solidity::test::CommonOptions::get().eofVersion().has_value()); Assembly::OptimiserSettings settings; settings.runInliner = false; settings.runJumpdestRemover = true; @@ -1346,8 +1348,8 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) settings.evmVersion = solidity::test::CommonOptions::get().evmVersion(); settings.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment; - Assembly main{settings.evmVersion, false, solidity::test::CommonOptions::get().eofVersion(), {}}; - AssemblyPointer sub = std::make_shared(settings.evmVersion, true, solidity::test::CommonOptions::get().eofVersion(), std::string{}); + Assembly main{settings.evmVersion, false, std::nullopt, {}}; + AssemblyPointer sub = std::make_shared(settings.evmVersion, true, std::nullopt, std::string{}); sub->append(u256(1)); auto t1 = sub->newTag(); diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index b3993e39f..fb08c667c 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -44,6 +44,7 @@ using namespace solidity::langutil; using namespace solidity::yul; +using namespace solidity::test; namespace solidity::frontend::test { @@ -294,7 +295,8 @@ BOOST_AUTO_TEST_CASE(designated_invalid_instruction) BOOST_CHECK(successAssemble("{ invalid() }")); } -BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_declaration) +// TODO: Implement EOF counterpart +BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_declaration, *boost::unit_test::precondition(nonEOF())) { CHECK_ASSEMBLE_ERROR("{ let gas := 1 }", ParserError, "Cannot use builtin"); } @@ -333,14 +335,14 @@ BOOST_AUTO_TEST_CASE(returndatacopy) BOOST_CHECK(successAssemble("{ returndatacopy(0, 32, 64) }")); } -BOOST_AUTO_TEST_CASE(staticcall) +BOOST_AUTO_TEST_CASE(staticcall, *boost::unit_test::precondition(nonEOF())) { if (!solidity::test::CommonOptions::get().evmVersion().hasStaticCall()) return; BOOST_CHECK(successAssemble("{ pop(staticcall(10000, 0x123, 64, 0x10, 128, 0x10)) }")); } -BOOST_AUTO_TEST_CASE(create2) +BOOST_AUTO_TEST_CASE(create2, *boost::unit_test::precondition(nonEOF())) { if (!solidity::test::CommonOptions::get().evmVersion().hasCreate2()) return; diff --git a/test/libsolidity/SolidityCompiler.cpp b/test/libsolidity/SolidityCompiler.cpp index 7cb95a99d..79d838349 100644 --- a/test/libsolidity/SolidityCompiler.cpp +++ b/test/libsolidity/SolidityCompiler.cpp @@ -24,6 +24,7 @@ #include +using namespace solidity::test; namespace solidity::frontend::test { @@ -42,7 +43,8 @@ class SolidityCompilerFixture: protected AnalysisFramework BOOST_FIXTURE_TEST_SUITE(SolidityCompiler, SolidityCompilerFixture) -BOOST_AUTO_TEST_CASE(does_not_include_creation_time_only_internal_functions) +// TODO: Implement EOF counterpart +BOOST_AUTO_TEST_CASE(does_not_include_creation_time_only_internal_functions, *boost::unit_test::precondition(nonEOF())) { char const* sourceCode = R"( contract C { diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index 3d0e024da..ac220283a 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -28,6 +28,7 @@ #include using namespace solidity::langutil; +using namespace solidity::test; namespace solidity::frontend::test { @@ -133,7 +134,7 @@ BOOST_AUTO_TEST_CASE(address_staticcall) } -BOOST_AUTO_TEST_CASE(assembly_staticcall) +BOOST_AUTO_TEST_CASE(assembly_staticcall, *boost::unit_test::precondition(nonEOF())) { std::string text = R"( contract C { From 10a1d516f8cd3a3c4d659a0a98f33cd6e2bc6797 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 19 Dec 2024 10:10:21 +0100 Subject: [PATCH 0578/1340] eof: Re-enable test disabled in `soltest.sh` --- .circleci/soltest.sh | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.circleci/soltest.sh b/.circleci/soltest.sh index 71c2a952a..318192de4 100755 --- a/.circleci/soltest.sh +++ b/.circleci/soltest.sh @@ -45,17 +45,6 @@ IFS=" " read -r -a SOLTEST_FLAGS <<< "$SOLTEST_FLAGS" # TODO: [EOF] These won't pass on EOF yet. Reenable them when the implementation is complete. EOF_EXCLUDES=( - --run_test='!Assembler/all_assembly_items' - --run_test='!Assembler/immutable' - --run_test='!Assembler/immutables_and_its_source_maps' - --run_test='!Optimiser/jumpdest_removal_subassemblies' - --run_test='!Optimiser/jumpdest_removal_subassemblies/*' - --run_test='!SolidityCompiler/does_not_include_creation_time_only_internal_functions' - --run_test='!SolidityInlineAssembly/Analysis/create2' - --run_test='!SolidityInlineAssembly/Analysis/inline_assembly_shadowed_instruction_declaration' - --run_test='!SolidityInlineAssembly/Analysis/large_constant' - --run_test='!SolidityInlineAssembly/Analysis/staticcall' - --run_test='!ViewPureChecker/assembly_staticcall' --run_test='!yulStackLayout/literal_loop' ) From cb4899a0def8b135b5056a1f7b48f8ea926103af Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 19 Dec 2024 21:46:41 +0100 Subject: [PATCH 0579/1340] eof: Disable `smtCheckeTests` when compiling to EOF. --- test/libsolidity/SMTCheckerTest.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/libsolidity/SMTCheckerTest.cpp b/test/libsolidity/SMTCheckerTest.cpp index c25025ccf..96a9538f1 100644 --- a/test/libsolidity/SMTCheckerTest.cpp +++ b/test/libsolidity/SMTCheckerTest.cpp @@ -136,6 +136,10 @@ SMTCheckerTest::SMTCheckerTest(std::string const& _filename): auto const& bmcLoopIterations = m_reader.sizetSetting("BMCLoopIterations", 1); m_modelCheckerSettings.bmcLoopIterations = std::optional{bmcLoopIterations}; + + // TODO: Enable EOF testing when EOF gets stable and smtCheckerTest starts using IR. + if (CommonOptions::get().eofVersion().has_value()) + m_shouldRun = false; } void SMTCheckerTest::setupCompiler(CompilerStack& _compiler) From f7b86bb4c550eff9bb6309c06bc5eaf0f0fc2b1d Mon Sep 17 00:00:00 2001 From: Gaetan Lepage Date: Tue, 31 Dec 2024 13:50:00 +0100 Subject: [PATCH 0580/1340] Fix build with GCC 14 --- test/yulPhaser/Chromosome.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/yulPhaser/Chromosome.cpp b/test/yulPhaser/Chromosome.cpp index da109086a..881f70007 100644 --- a/test/yulPhaser/Chromosome.cpp +++ b/test/yulPhaser/Chromosome.cpp @@ -85,8 +85,8 @@ BOOST_AUTO_TEST_CASE(makeRandom_should_use_every_possible_step_with_the_same_pro const double expectedValue = double(stepIndices.size() - 1) / 2.0; const double variance = double(stepIndices.size() * stepIndices.size() - 1) / 12.0; - BOOST_TEST(abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(fabs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(fabs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(constructor_should_store_genes) @@ -159,8 +159,8 @@ BOOST_AUTO_TEST_CASE(randomOptimisationStep_should_return_each_step_with_same_pr const double expectedValue = double(stepIndices.size() - 1) / 2.0; const double variance = double(stepIndices.size() * stepIndices.size() - 1) / 12.0; - BOOST_TEST(abs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); - BOOST_TEST(abs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); + BOOST_TEST(fabs(mean(samples) - expectedValue) < expectedValue * relativeTolerance); + BOOST_TEST(fabs(meanSquaredError(samples, expectedValue) - variance) < variance * relativeTolerance); } BOOST_AUTO_TEST_CASE(stepsToGenes_should_translate_optimisation_step_names_to_abbreviations) From ac4d267f8154677f66af4d33f98f233699db1fb7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 6 Jan 2025 10:38:14 +0100 Subject: [PATCH 0581/1340] Adapts to new Boost download location --- .circleci/osx_install_dependencies.sh | 2 +- scripts/docker/buildpack-deps/Dockerfile.emscripten | 4 ++-- scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz | 4 ++-- scripts/install_deps.ps1 | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index c606913e4..f618bd9d3 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -66,7 +66,7 @@ then boost_version="1.84.0" boost_package="boost_${boost_version//./_}.tar.bz2" boost_dir="boost_${boost_version//./_}" - wget "https://boostorg.jfrog.io/artifactory/main/release/$boost_version/source/$boost_package" + wget "https://archives.boost.io/release/$boost_version/source/$boost_package" tar xf "$boost_package" rm "$boost_package" cd "$boost_dir" diff --git a/scripts/docker/buildpack-deps/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten index 8bfb9c51a..d8eb9a903 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -33,7 +33,7 @@ # Using $(em-config CACHE)/sysroot/usr seems to work, though, and still has cmake find the # dependencies automatically. FROM emscripten/emsdk:3.1.19 AS base -LABEL version="19" +LABEL version="20" ADD emscripten.jam /usr/src RUN set -ex && \ @@ -70,7 +70,7 @@ RUN set -ex && \ # Install Boost RUN set -ex && \ cd /usr/src && \ - wget -q 'https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.bz2' -O boost.tar.bz2 && \ + wget -q 'https://archives.boost.io/release/1.75.0/source/boost_1_75_0.tar.bz2' -O boost.tar.bz2 && \ test "$(sha256sum boost.tar.bz2)" = "953db31e016db7bb207f11432bef7df100516eeb746843fa0486a222e3fd49cb boost.tar.bz2" && \ tar -xf boost.tar.bz2 && \ rm boost.tar.bz2 && \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index aae11521e..743d924d7 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-clang:latest as base -LABEL version="7" +LABEL version="8" ARG DEBIAN_FRONTEND=noninteractive @@ -73,7 +73,7 @@ FROM base AS libraries # Boost RUN set -ex; \ cd /usr/src; \ - wget -q 'https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2' -O boost.tar.bz2; \ + wget -q 'https://archives.boost.io/release/1.74.0/source/boost_1_74_0.tar.bz2' -O boost.tar.bz2; \ test "$(sha256sum boost.tar.bz2)" = "83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1 boost.tar.bz2" && \ tar -xf boost.tar.bz2; \ rm boost.tar.bz2; \ diff --git a/scripts/install_deps.ps1 b/scripts/install_deps.ps1 index 26a9e116f..ad4f5bdad 100644 --- a/scripts/install_deps.ps1 +++ b/scripts/install_deps.ps1 @@ -16,7 +16,7 @@ if ( -not (Test-Path "$PSScriptRoot\..\deps\boost") ) { # FIXME: The default user agent results in Artifactory treating Invoke-WebRequest as a browser # and serving it a page that requires JavaScript. - Invoke-WebRequest -URI "https://boostorg.jfrog.io/artifactory/main/release/1.83.0/source/boost_1_83_0.zip" -OutFile boost.zip -UserAgent "" + Invoke-WebRequest -URI "https://archives.boost.io/release/1.83.0/source/boost_1_83_0.zip" -OutFile boost.zip -UserAgent "" if ((Get-FileHash boost.zip).Hash -ne "c86bd9d9eef795b4b0d3802279419fde5221922805b073b9bd822edecb1ca28e") { throw 'Downloaded Boost source package has wrong checksum.' } From 6af8becb47b131ae894fb66502fbe02922b0af35 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 6 Jan 2025 13:55:51 +0100 Subject: [PATCH 0582/1340] Update emscripten docker image version --- .circleci/config.yml | 4 ++-- scripts/build_emscripten.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 542118f6d..18dc57ebd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -26,8 +26,8 @@ parameters: emscripten-docker-image: type: string # NOTE: Please remember to update the `scripts/build_emscripten.sh` whenever the hash of this image changes. - # solbuildpackpusher/solidity-buildpack-deps:emscripten-19 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:170b159c82ce70e639500551394460f01798c18a5e17b45ea91277b0cf8eae37" + # solbuildpackpusher/solidity-buildpack-deps:emscripten-20 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:98f963ed799a0d206ef8e7b5475f847e0dea53b7fdea9618bbc6106a62730bd2" evm-version: type: string default: cancun diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index a53393f1d..93556a557 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -33,9 +33,9 @@ if (( $# != 0 )); then params="$(printf "%q " "${@}")" fi -# solbuildpackpusher/solidity-buildpack-deps:emscripten-19 +# solbuildpackpusher/solidity-buildpack-deps:emscripten-20` # NOTE: Without `safe.directory` git would assume it's not safe to operate on /root/project since it's owned by a different user. # See https://github.blog/2022-04-12-git-security-vulnerability-announced/ docker run -v "$(pwd):/root/project" -w /root/project \ - solbuildpackpusher/solidity-buildpack-deps@sha256:170b159c82ce70e639500551394460f01798c18a5e17b45ea91277b0cf8eae37 \ + solbuildpackpusher/solidity-buildpack-deps@sha256:98f963ed799a0d206ef8e7b5475f847e0dea53b7fdea9618bbc6106a62730bd2 \ /bin/bash -c "git config --global --add safe.directory /root/project && ./scripts/ci/build_emscripten.sh ${params}" From 969c9ca39de8049988b1441ec35b09be48269668 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 6 Jan 2025 11:21:28 +0100 Subject: [PATCH 0583/1340] SSACFG liveness: Adds exit liveness info to livein --- libyul/backends/evm/SSACFGLiveness.cpp | 52 ++++++++------- .../standard_yul_cfg_json_export/output.json | 66 +++++++------------ .../strict_asm_yul_cfg_json_export/output | 15 ++--- test/cmdlineTests/yul_cfg_json_export/output | 66 +++++++------------ .../libyul/yulSSAControlFlowGraph/complex.yul | 14 ++-- .../yulSSAControlFlowGraph/complex2.yul | 14 ++-- .../yulSSAControlFlowGraph/nested_for.yul | 10 +-- .../nested_function.yul | 4 +- test/libyul/yulSSAControlFlowGraph/switch.yul | 4 +- 9 files changed, 102 insertions(+), 143 deletions(-) diff --git a/libyul/backends/evm/SSACFGLiveness.cpp b/libyul/backends/evm/SSACFGLiveness.cpp index 6ecd559ca..aecaed6ff 100644 --- a/libyul/backends/evm/SSACFGLiveness.cpp +++ b/libyul/backends/evm/SSACFGLiveness.cpp @@ -89,23 +89,10 @@ void SSACFGLiveness::runDagDfs() if (!m_topologicalSort.backEdge(blockId, _successor)) live += m_liveIns[_successor.value] - m_cfg.block(_successor).phis; }); - util::GenericVisitor exitVisitor { - [](SSACFG::BasicBlock::MainExit const&) {}, - [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { - live += _functionReturn.returnValues | ranges::views::filter(literalsFilter(m_cfg)); - }, - [&](SSACFG::BasicBlock::JumpTable const& _jt) { - if (literalsFilter(m_cfg)(_jt.value)) - live.emplace(_jt.value); - }, - [](SSACFG::BasicBlock::Jump const&) {}, - [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { - if (literalsFilter(m_cfg)(_conditionalJump.condition)) - live.emplace(_conditionalJump.condition); - }, - [](SSACFG::BasicBlock::Terminated const&) {} - }; - std::visit(exitVisitor, block.exit); + + if (std::holds_alternative(block.exit)) + live += std::get(block.exit).returnValues + | ranges::views::filter(literalsFilter(m_cfg)); // clean out unreachables live = live | ranges::views::filter([&](auto const& valueId) { return !std::holds_alternative(m_cfg.valueInfo(valueId)); }) | ranges::to; @@ -114,12 +101,33 @@ void SSACFGLiveness::runDagDfs() m_liveOuts[blockId.value] = live; // for each program point p in B, backwards, do: - for (auto const& op: block.operations | ranges::views::reverse) { - // remove variables defined at p from live - live -= op.outputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; - // add uses at p to live - live += op.inputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; + // add value ids to the live set that are used in exit blocks + util::GenericVisitor exitVisitor { + [](SSACFG::BasicBlock::MainExit const&) {}, + [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { + live += _functionReturn.returnValues | ranges::views::filter(literalsFilter(m_cfg)); + }, + [&](SSACFG::BasicBlock::JumpTable const& _jt) { + if (literalsFilter(m_cfg)(_jt.value)) + live.emplace(_jt.value); + }, + [](SSACFG::BasicBlock::Jump const&) {}, + [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { + if (literalsFilter(m_cfg)(_conditionalJump.condition)) + live.emplace(_conditionalJump.condition); + }, + [](SSACFG::BasicBlock::Terminated const&) {} + }; + std::visit(exitVisitor, block.exit); + + for (auto const& op: block.operations | ranges::views::reverse) + { + // remove variables defined at p from live + live -= op.outputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; + // add uses at p to live + live += op.inputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; + } } // livein(b) <- live \cup PhiDefs(B) diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index bb13b3e91..81c0e49e5 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -45,8 +45,7 @@ "liveness": { "in": [], "out": [ - "v0", - "v2" + "v0" ] }, "type": "BuiltinCall" @@ -189,8 +188,7 @@ "liveness": { "in": [], "out": [ - "v0", - "v5" + "v0" ] }, "type": "BuiltinCall" @@ -262,8 +260,7 @@ "v0" ], "out": [ - "v0", - "v11" + "v0" ] }, "type": "BuiltinCall" @@ -306,8 +303,7 @@ "v0" ], "out": [ - "v0", - "v12" + "v0" ] }, "type": "BuiltinCall" @@ -365,8 +361,7 @@ "v0" ], "out": [ - "v0", - "v17" + "v0" ] }, "type": "BuiltinCall" @@ -497,8 +492,7 @@ "liveness": { "in": [], "out": [ - "v0", - "v2" + "v0" ] }, "type": "BuiltinCall" @@ -641,8 +635,7 @@ "liveness": { "in": [], "out": [ - "v0", - "v5" + "v0" ] }, "type": "BuiltinCall" @@ -714,8 +707,7 @@ "v0" ], "out": [ - "v0", - "v11" + "v0" ] }, "type": "BuiltinCall" @@ -758,8 +750,7 @@ "v0" ], "out": [ - "v0", - "v12" + "v0" ] }, "type": "BuiltinCall" @@ -817,8 +808,7 @@ "v0" ], "out": [ - "v0", - "v17" + "v0" ] }, "type": "BuiltinCall" @@ -913,8 +903,7 @@ "out": [ "v0", "v18", - "v24", - "v28" + "v24" ] }, "type": "BuiltinCall" @@ -1008,8 +997,7 @@ "v24" ], "out": [ - "v41", - "v42" + "v41" ] }, "type": "BuiltinCall" @@ -1166,8 +1154,7 @@ ], "out": [ "v46", - "v59", - "v60" + "v59" ] }, "type": "BuiltinCall" @@ -1242,8 +1229,7 @@ "v59" ], "out": [ - "v46", - "v59" + "v46" ] } }, @@ -1388,8 +1374,7 @@ "v46" ], "out": [ - "v46", - "v67" + "v46" ] }, "type": "BuiltinCall" @@ -1497,8 +1482,7 @@ "out": [ "v46", "v71", - "v77", - "v80" + "v77" ] }, "type": "BuiltinCall" @@ -1588,8 +1572,7 @@ "v77" ], "out": [ - "v46", - "v90" + "v46" ] }, "type": "BuiltinCall" @@ -1737,8 +1720,7 @@ "liveness": { "in": [], "out": [ - "v0", - "v2" + "v0" ] }, "type": "BuiltinCall" @@ -1881,8 +1863,7 @@ "liveness": { "in": [], "out": [ - "v0", - "v5" + "v0" ] }, "type": "BuiltinCall" @@ -1954,8 +1935,7 @@ "v0" ], "out": [ - "v0", - "v11" + "v0" ] }, "type": "BuiltinCall" @@ -1998,8 +1978,7 @@ "v0" ], "out": [ - "v0", - "v12" + "v0" ] }, "type": "BuiltinCall" @@ -2057,8 +2036,7 @@ "v0" ], "out": [ - "v0", - "v17" + "v0" ] }, "type": "BuiltinCall" diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output index a65c164d6..ac154fc16 100644 --- a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -45,8 +45,7 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0", - "v2" + "v0" ] }, "type": "BuiltinCall" @@ -189,8 +188,7 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0", - "v5" + "v0" ] }, "type": "BuiltinCall" @@ -262,8 +260,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v11" + "v0" ] }, "type": "BuiltinCall" @@ -306,8 +303,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v12" + "v0" ] }, "type": "BuiltinCall" @@ -365,8 +361,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v17" + "v0" ] }, "type": "BuiltinCall" diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index f6f2ec6d8..dd4dece74 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -44,8 +44,7 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0", - "v2" + "v0" ] }, "type": "BuiltinCall" @@ -188,8 +187,7 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0", - "v5" + "v0" ] }, "type": "BuiltinCall" @@ -261,8 +259,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v11" + "v0" ] }, "type": "BuiltinCall" @@ -305,8 +302,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v12" + "v0" ] }, "type": "BuiltinCall" @@ -364,8 +360,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v17" + "v0" ] }, "type": "BuiltinCall" @@ -497,8 +492,7 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0", - "v2" + "v0" ] }, "type": "BuiltinCall" @@ -641,8 +635,7 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0", - "v5" + "v0" ] }, "type": "BuiltinCall" @@ -714,8 +707,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v11" + "v0" ] }, "type": "BuiltinCall" @@ -758,8 +750,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v12" + "v0" ] }, "type": "BuiltinCall" @@ -817,8 +808,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v17" + "v0" ] }, "type": "BuiltinCall" @@ -913,8 +903,7 @@ Yul Control Flow Graph: "out": [ "v0", "v18", - "v24", - "v28" + "v24" ] }, "type": "BuiltinCall" @@ -1008,8 +997,7 @@ Yul Control Flow Graph: "v24" ], "out": [ - "v41", - "v42" + "v41" ] }, "type": "BuiltinCall" @@ -1166,8 +1154,7 @@ Yul Control Flow Graph: ], "out": [ "v46", - "v59", - "v60" + "v59" ] }, "type": "BuiltinCall" @@ -1242,8 +1229,7 @@ Yul Control Flow Graph: "v59" ], "out": [ - "v46", - "v59" + "v46" ] } }, @@ -1388,8 +1374,7 @@ Yul Control Flow Graph: "v46" ], "out": [ - "v46", - "v67" + "v46" ] }, "type": "BuiltinCall" @@ -1497,8 +1482,7 @@ Yul Control Flow Graph: "out": [ "v46", "v71", - "v77", - "v80" + "v77" ] }, "type": "BuiltinCall" @@ -1588,8 +1572,7 @@ Yul Control Flow Graph: "v77" ], "out": [ - "v46", - "v90" + "v46" ] }, "type": "BuiltinCall" @@ -1737,8 +1720,7 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0", - "v2" + "v0" ] }, "type": "BuiltinCall" @@ -1881,8 +1863,7 @@ Yul Control Flow Graph: "liveness": { "in": [], "out": [ - "v0", - "v5" + "v0" ] }, "type": "BuiltinCall" @@ -1954,8 +1935,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v11" + "v0" ] }, "type": "BuiltinCall" @@ -1998,8 +1978,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v12" + "v0" ] }, "type": "BuiltinCall" @@ -2057,8 +2036,7 @@ Yul Control Flow Graph: "v0" ], "out": [ - "v0", - "v17" + "v0" ] }, "type": "BuiltinCall" diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index 3f7f329a4..6fb0453c1 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -69,7 +69,7 @@ // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ // Block 1; (1, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5,v6\l\nv5 := φ(\l\ +// LiveOut: v0,v1,v5\l\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ // )\l\ @@ -81,7 +81,7 @@ // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ // Block 2; (2, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5,v7,v8\l\nv7 := mload(v5)\l\ +// LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ // v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; @@ -103,7 +103,7 @@ // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ // Block 7; (5, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7,v13\l\nv13 := eq(1, v7)\l\ +// LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; // Block1_7Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -117,7 +117,7 @@ // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ // Block 10; (7, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7,v20\l\nv20 := eq(2, v7)\l\ +// LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; // Block1_10Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -132,7 +132,7 @@ // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ // Block 13; (9, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v25\l\nv25 := eq(3, v7)\l\ +// LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; // Block1_13Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -147,7 +147,7 @@ // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ // Block 16; (15, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5,v29\l\nv29 := mload(v1)\l\ +// LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; // Block1_16Exit [label="{ If v29 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -175,7 +175,7 @@ // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ // Block 3; (12, max 14)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v43,v44\l\nv43 := add(1, v5)\l\ +// LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index 6d801124c..c3ea8b94f 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -85,7 +85,7 @@ // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ // Block 1; (1, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5,v6\l\nv5 := φ(\l\ +// LiveOut: v0,v1,v5\l\nv5 := φ(\l\ // Block 0 => 42,\l\ // Block 21 => v43\l\ // )\l\ @@ -97,7 +97,7 @@ // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ // Block 2; (2, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5,v7,v8\l\nv7 := mload(v5)\l\ +// LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ // v8 := eq(0, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; @@ -119,7 +119,7 @@ // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ // Block 7; (5, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7,v13\l\nv13 := eq(1, v7)\l\ +// LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; // Block1_7Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -133,7 +133,7 @@ // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ // Block 10; (7, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7,v20\l\nv20 := eq(2, v7)\l\ +// LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; // Block1_10Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -148,7 +148,7 @@ // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ // Block 13; (9, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v25\l\nv25 := eq(3, v7)\l\ +// LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; // Block1_13Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -163,7 +163,7 @@ // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ // Block 16; (15, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5,v29\l\nv29 := mload(v1)\l\ +// LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; // Block1_16Exit [label="{ If v29 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -191,7 +191,7 @@ // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ // Block 3; (12, max 14)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v43,v44\l\nv43 := add(1, v5)\l\ +// LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ // v44 := calldataload(v43)\l\ // "]; // Block1_3 -> Block1_3Exit; diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/yulSSAControlFlowGraph/nested_for.yul index f816df462..b088e3b55 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_for.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_for.yul @@ -33,7 +33,7 @@ // Block0_0Exit -> Block0_1 [style="solid"]; // Block0_1 [label="\ // Block 1; (1, max 24)\nLiveIn: v2\l\ -// LiveOut: v2,v3\l\nv2 := φ(\l\ +// LiveOut: v2\l\nv2 := φ(\l\ // Block 0 => 0,\l\ // Block 3 => v36\l\ // )\l\ @@ -56,7 +56,7 @@ // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ // Block 5; (3, max 23)\nLiveIn: v2,v4\l\ -// LiveOut: v2,v4,v5\l\nv4 := φ(\l\ +// LiveOut: v2,v4\l\nv4 := φ(\l\ // Block 2 => 0,\l\ // Block 7 => v35\l\ // )\l\ @@ -80,7 +80,7 @@ // Block0_8Exit -> Block0_3 [style="solid"]; // Block0_9 [label="\ // Block 9; (5, max 21)\nLiveIn: v2,v4,v6\l\ -// LiveOut: v2,v4,v6,v7\l\nv6 := φ(\l\ +// LiveOut: v2,v4,v6\l\nv6 := φ(\l\ // Block 6 => 0,\l\ // Block 11 => v31\l\ // )\l\ @@ -132,7 +132,7 @@ // Block0_7Exit -> Block0_5 [style="dashed"]; // Block0_15 [label="\ // Block 15; (8, max 19)\nLiveIn: v2,v4,v6,v8\l\ -// LiveOut: v2,v4,v6,v8,v9\l\nv8 := φ(\l\ +// LiveOut: v2,v4,v6,v8\l\nv8 := φ(\l\ // Block 13 => 0,\l\ // Block 17 => v16\l\ // )\l\ @@ -171,7 +171,7 @@ // Block0_18Exit -> Block0_14 [style="solid"]; // Block0_21 [label="\ // Block 21; (14, max 19)\nLiveIn: v2,v4,v6,v19\l\ -// LiveOut: v2,v4,v6,v19,v20\l\nv19 := φ(\l\ +// LiveOut: v2,v4,v6,v19\l\nv19 := φ(\l\ // Block 19 => 0,\l\ // Block 23 => v26\l\ // )\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/nested_function.yul b/test/libyul/yulSSAControlFlowGraph/nested_function.yul index 1263d4782..acda15ce8 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_function.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_function.yul @@ -103,7 +103,7 @@ // FunctionEntry_cycle1_0 -> Block7_0; // Block7_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: v2\l\nv2 := mload(3)\l\ +// LiveOut: \l\nv2 := mload(3)\l\ // "]; // Block7_0 -> Block7_0Exit; // Block7_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -130,7 +130,7 @@ // FunctionEntry_cycle2_0 -> Block8_0; // Block8_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: v2\l\nv2 := mload(4)\l\ +// LiveOut: \l\nv2 := mload(4)\l\ // "]; // Block8_0 -> Block8_0Exit; // Block8_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; diff --git a/test/libyul/yulSSAControlFlowGraph/switch.yul b/test/libyul/yulSSAControlFlowGraph/switch.yul index 91b3daeee..10573b012 100644 --- a/test/libyul/yulSSAControlFlowGraph/switch.yul +++ b/test/libyul/yulSSAControlFlowGraph/switch.yul @@ -23,7 +23,7 @@ // Entry0 -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 5)\nLiveIn: \l\ -// LiveOut: v3,v4\l\nv1 := calldataload(3)\l\ +// LiveOut: v3\l\nv1 := calldataload(3)\l\ // v3 := sload(0)\l\ // v4 := eq(0, v3)\l\ // "]; @@ -40,7 +40,7 @@ // Block0_2Exit -> Block0_1 [style="solid"]; // Block0_3 [label="\ // Block 3; (3, max 5)\nLiveIn: v3\l\ -// LiveOut: v7\l\nv7 := eq(1, v3)\l\ +// LiveOut: \l\nv7 := eq(1, v3)\l\ // "]; // Block0_3 -> Block0_3Exit; // Block0_3Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; From 9e9c29a1e920f956814132fd608861bf589aa75e Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 8 Jan 2025 14:58:22 +0100 Subject: [PATCH 0584/1340] SSA CFG Exporter: fix subobjects placement in json exporter --- libyul/YulStack.cpp | 5 +- .../standard_yul_cfg_json_export/output.json | 3220 ++++++++--------- .../strict_asm_yul_cfg_json_export/output | 548 +-- test/cmdlineTests/yul_cfg_json_export/output | 3220 ++++++++--------- 4 files changed, 3497 insertions(+), 3496 deletions(-) diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 03e22c8d1..aa8a32820 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -409,7 +409,7 @@ Json YulStack::cfgJson() const subObjectsJson[subObject->name] = exportCFGFromObject(*subObject); subObjectsJson["type"] = "subObject"; if (!subObject->subObjects.empty()) - subObjectsJson["subObjects"] = exportCFGFromSubObjects(subObject->subObjects); + subObjectsJson[subObject->name]["subObjects"] = exportCFGFromSubObjects(subObject->subObjects); } return subObjectsJson; }; @@ -418,7 +418,8 @@ Json YulStack::cfgJson() const Json jsonObject = Json::object(); jsonObject[object.name] = exportCFGFromObject(object); jsonObject["type"] = "Object"; - jsonObject["subObjects"] = exportCFGFromSubObjects(object.subObjects); + if (!object.subObjects.empty()) + jsonObject[object.name]["subObjects"] = exportCFGFromSubObjects(object.subObjects); return jsonObject; } diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index 81c0e49e5..303d51bbb 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -124,326 +124,326 @@ "type": "BuiltinCall" } ], - "functions": {} - }, - "subObjects": { - "C_19_deployed": { - "blocks": [ - { - "exit": { - "cond": "v5", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "builtinArgs": [ - "0x80" + "functions": {}, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { "in": [], - "op": "memoryguard", "out": [ "v0" ] }, - { - "in": [ - "v0", - "0x40" - ], - "op": "mstore", - "out": [] + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" }, - { + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { "in": [], - "op": "calldatasize", - "out": [ - "v3" - ] + "out": [] }, - { - "in": [ - "0x04", - "v3" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" ], - "op": "lt", - "out": [ - "v4" - ] + "type": "ConditionalJump" }, - { + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { "in": [ - "v4" + "v0" ], - "op": "iszero", "out": [ - "v5" + "v0" ] - } - ], - "liveness": { - "in": [], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" + }, + "type": "BuiltinCall" }, - "id": "Block2", - "instructions": [ - { - "in": [ - "0x00", - "0x00" + { + "exit": { + "targets": [ + "Block2" ], - "op": "revert", + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], "out": [] } - ], - "liveness": { - "in": [], - "out": [] }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v11", - "targets": [ - "Block4", - "Block3" + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } ], - "type": "ConditionalJump" - }, - "id": "Block1", - "instructions": [ - { + "liveness": { "in": [ - "0x00" + "v0" ], - "op": "calldataload", "out": [ - "v7" + "v0" ] }, - { - "in": [ - "v7", - "0xe0" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" ], - "op": "shr", - "out": [ - "v9" - ] + "type": "ConditionalJump" }, - { + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { "in": [ - "v9", - "0x26121ff0" + "v0" ], - "op": "eq", "out": [ - "v11" + "v0" ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block2" - ], - "type": "Jump" + }, + "type": "BuiltinCall" }, - "id": "Block4", - "instructions": [], - "liveness": { - "in": [], - "out": [] - } - }, - { - "exit": { - "cond": "v12", - "targets": [ - "Block6", - "Block5" + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "type": "ConditionalJump" - }, - "id": "Block3", - "instructions": [ - { + "liveness": { "in": [], - "op": "callvalue", - "out": [ - "v12" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] + "out": [] + }, + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v17", - "targets": [ - "Block9", - "Block8" + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ + { + "in": [ + "0x2a", + "v0" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] + } ], - "type": "ConditionalJump" - }, - "id": "Block6", - "instructions": [ - { + "liveness": { "in": [ - "0x03" + "v0" ], - "op": "not", - "out": [ - "v14" - ] - }, - { - "in": [], - "op": "calldatasize", - "out": [ - "v15" - ] - }, - { - "in": [ - "v14", - "v15" - ], - "op": "add", - "out": [ - "v16" - ] - }, - { - "in": [ - "0x00", - "v16" - ], - "op": "slt", - "out": [ - "v17" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block5", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" + }, + "type": "BuiltinCall" }, - "id": "Block9", - "instructions": [ - { - "in": [ - "0x2a", - "v0" - ], - "op": "mstore", - "out": [] + { + "exit": { + "type": "Terminated" }, - { - "in": [ - "0x20", - "v0" - ], - "op": "return", - "out": [] - } - ], - "liveness": { - "in": [ - "v0" + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block8", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", + "liveness": { + "in": [], "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - } - ], - "functions": {} - }, - "subObjects": {}, - "type": "subObject" + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": {} + }, + "type": "subObject" + } }, "type": "Object" } @@ -571,1156 +571,1007 @@ "type": "BuiltinCall" } ], - "functions": {} - }, - "subObjects": { - "D_38_deployed": { - "blocks": [ - { - "exit": { - "cond": "v5", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "builtinArgs": [ - "0x80" + "functions": {}, + "subObjects": { + "D_38_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { "in": [], - "op": "memoryguard", "out": [ "v0" ] }, - { - "in": [ - "v0", - "0x40" - ], - "op": "mstore", - "out": [] + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" }, - { + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { "in": [], - "op": "calldatasize", - "out": [ - "v3" - ] + "out": [] }, - { - "in": [ - "0x04", - "v3" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" ], - "op": "lt", - "out": [ - "v4" - ] + "type": "ConditionalJump" }, - { + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { "in": [ - "v4" + "v0" ], - "op": "iszero", "out": [ - "v5" + "v0" ] - } - ], - "liveness": { - "in": [], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" + }, + "type": "BuiltinCall" }, - "id": "Block2", - "instructions": [ - { - "in": [ - "0x00", - "0x00" + { + "exit": { + "targets": [ + "Block2" ], - "op": "revert", + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], "out": [] } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v11", - "targets": [ - "Block4", - "Block3" - ], - "type": "ConditionalJump" }, - "id": "Block1", - "instructions": [ - { - "in": [ - "0x00" + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" ], - "op": "calldataload", - "out": [ - "v7" - ] + "type": "ConditionalJump" }, - { + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { "in": [ - "v7", - "0xe0" + "v0" ], - "op": "shr", "out": [ - "v9" + "v0" ] }, - { - "in": [ - "v9", - "0x26121ff0" - ], - "op": "eq", - "out": [ - "v11" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block2" - ], - "type": "Jump" - }, - "id": "Block4", - "instructions": [], - "liveness": { - "in": [], - "out": [] - } - }, - { - "exit": { - "cond": "v12", - "targets": [ - "Block6", - "Block5" - ], - "type": "ConditionalJump" + "type": "BuiltinCall" }, - "id": "Block3", - "instructions": [ - { - "in": [], - "op": "callvalue", - "out": [ - "v12" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v17", - "targets": [ - "Block9", - "Block8" - ], - "type": "ConditionalJump" - }, - "id": "Block6", - "instructions": [ - { - "in": [ - "0x03" + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" ], - "op": "not", - "out": [ - "v14" - ] - }, - { - "in": [], - "op": "calldatasize", - "out": [ - "v15" - ] + "type": "ConditionalJump" }, - { + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { "in": [ - "v14", - "v15" + "v0" ], - "op": "add", "out": [ - "v16" + "v0" ] }, - { - "in": [ - "0x00", - "v16" - ], - "op": "slt", - "out": [ - "v17" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block5", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v28", - "targets": [ - "Block12", - "Block11" + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "type": "ConditionalJump" + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" }, - "id": "Block9", - "instructions": [ - { - "builtinArgs": [ - "C_19" + { + "exit": { + "cond": "v28", + "targets": [ + "Block12", + "Block11" ], - "in": [], - "op": "datasize", - "out": [ - "v18" - ] + "type": "ConditionalJump" }, - { + "id": "Block9", + "instructions": [ + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "datasize", + "out": [ + "v18" + ] + }, + { + "in": [ + "v18", + "v0" + ], + "op": "add", + "out": [ + "v24" + ] + }, + { + "in": [ + "v0", + "v24" + ], + "op": "lt", + "out": [ + "v25" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v24" + ], + "op": "gt", + "out": [ + "v27" + ] + }, + { + "in": [ + "v25", + "v27" + ], + "op": "or", + "out": [ + "v28" + ] + } + ], + "liveness": { "in": [ - "v18", "v0" ], - "op": "add", "out": [ - "v24" - ] - }, - { - "in": [ "v0", + "v18", "v24" - ], - "op": "lt", - "out": [ - "v25" - ] - }, - { - "in": [ - "0xffffffffffffffff", - "v24" - ], - "op": "gt", - "out": [ - "v27" ] }, - { - "in": [ - "v25", - "v27" - ], - "op": "or", - "out": [ - "v28" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0", - "v18", - "v24" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block8", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v42", - "targets": [ - "Block15", - "Block14" + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "type": "ConditionalJump" - }, - "id": "Block12", - "instructions": [ - { - "builtinArgs": [ - "C_19" - ], + "liveness": { "in": [], - "op": "dataoffset", - "out": [ - "v35" - ] - }, - { - "in": [ - "v18", - "v35", - "v0" - ], - "op": "datacopy", "out": [] }, - { - "in": [ - "v0", - "v24" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v42", + "targets": [ + "Block15", + "Block14" ], - "op": "sub", - "out": [ - "v40" - ] + "type": "ConditionalJump" }, - { + "id": "Block12", + "instructions": [ + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v35" + ] + }, + { + "in": [ + "v18", + "v35", + "v0" + ], + "op": "datacopy", + "out": [] + }, + { + "in": [ + "v0", + "v24" + ], + "op": "sub", + "out": [ + "v40" + ] + }, + { + "in": [ + "v40", + "v0", + "0x00" + ], + "op": "create", + "out": [ + "v41" + ] + }, + { + "in": [ + "v41" + ], + "op": "iszero", + "out": [ + "v42" + ] + } + ], + "liveness": { "in": [ - "v40", "v0", - "0x00" + "v18", + "v24" ], - "op": "create", "out": [ "v41" ] }, - { - "in": [ - "v41" - ], - "op": "iszero", - "out": [ - "v42" - ] - } - ], - "liveness": { - "in": [ - "v0", - "v18", - "v24" - ], - "out": [ - "v41" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" + "type": "BuiltinCall" }, - "id": "Block11", - "instructions": [ - { - "in": [ - "0x4e487b71", - "0xe0" - ], - "op": "shl", - "out": [ - "v30" - ] - }, - { - "in": [ - "v30", - "0x00" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x41", - "0x04" - ], - "op": "mstore", - "out": [] + { + "exit": { + "type": "Terminated" }, - { - "in": [ - "0x24", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v60", - "targets": [ - "Block18", - "Block17" + "id": "Block11", + "instructions": [ + { + "in": [ + "0x4e487b71", + "0xe0" + ], + "op": "shl", + "out": [ + "v30" + ] + }, + { + "in": [ + "v30", + "0x00" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x41", + "0x04" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "type": "ConditionalJump" - }, - "id": "Block15", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v46" - ] - }, - { - "in": [ - "0x026121ff", - "0xe4" - ], - "op": "shl", - "out": [ - "v49" - ] - }, - { - "in": [ - "v49", - "v46" - ], - "op": "mstore", + "liveness": { + "in": [], "out": [] }, - { - "in": [ - "0x01", - "0xa0" - ], - "op": "shl", - "out": [ - "v53" - ] - }, - { - "in": [ - "0x01", - "v53" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v60", + "targets": [ + "Block18", + "Block17" ], - "op": "sub", - "out": [ - "v54" - ] + "type": "ConditionalJump" }, - { + "id": "Block15", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v46" + ] + }, + { + "in": [ + "0x026121ff", + "0xe4" + ], + "op": "shl", + "out": [ + "v49" + ] + }, + { + "in": [ + "v49", + "v46" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x01", + "0xa0" + ], + "op": "shl", + "out": [ + "v53" + ] + }, + { + "in": [ + "0x01", + "v53" + ], + "op": "sub", + "out": [ + "v54" + ] + }, + { + "in": [ + "v54", + "v41" + ], + "op": "and", + "out": [ + "v57" + ] + }, + { + "in": [], + "op": "gas", + "out": [ + "v58" + ] + }, + { + "in": [ + "0x20", + "v46", + "0x04", + "v46", + "v57", + "v58" + ], + "op": "staticcall", + "out": [ + "v59" + ] + }, + { + "in": [ + "v59" + ], + "op": "iszero", + "out": [ + "v60" + ] + } + ], + "liveness": { "in": [ - "v54", "v41" ], - "op": "and", - "out": [ - "v57" - ] - }, - { - "in": [], - "op": "gas", "out": [ - "v58" - ] - }, - { - "in": [ - "0x20", "v46", - "0x04", - "v46", - "v57", - "v58" - ], - "op": "staticcall", - "out": [ - "v59" - ] - }, - { - "in": [ "v59" - ], - "op": "iszero", - "out": [ - "v60" - ] - } - ], - "liveness": { - "in": [ - "v41" - ], - "out": [ - "v46", - "v59" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block14", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v43" - ] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v44" - ] - }, - { - "in": [ - "v44", - "0x00", - "v43" - ], - "op": "returndatacopy", - "out": [] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v45" - ] - }, - { - "in": [ - "v45", - "v43" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v59", - "targets": [ - "Block21", - "Block20" - ], - "type": "ConditionalJump" - }, - "id": "Block18", - "instructions": [], - "liveness": { - "in": [ - "v46", - "v59" - ], - "out": [ - "v46" - ] - } - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block17", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v61" - ] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v62" - ] - }, - { - "in": [ - "v62", - "0x00", - "v61" - ], - "op": "returndatacopy", - "out": [] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v63" - ] - }, - { - "in": [ - "v63", - "v61" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "entries": [ - "Block18", - "Block28" - ], - "exit": { - "type": "Terminated" - }, - "id": "Block21", - "instructions": [ - { - "in": [ - "0x00", - "v93" - ], - "op": "PhiFunction", - "out": [ - "v95" ] }, - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v94" - ] - }, - { - "in": [ - "v95", - "v94" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x20", - "v94" - ], - "op": "return", - "out": [] - } - ], - "liveness": { - "in": [ - "v95" - ], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v67", - "targets": [ - "Block23", - "Block22" - ], - "type": "ConditionalJump" - }, - "id": "Block20", - "instructions": [ - { - "in": [], - "op": "returndatasize", - "out": [ - "v66" - ] - }, - { - "in": [ - "v66", - "0x20" - ], - "op": "gt", - "out": [ - "v67" - ] - } - ], - "liveness": { - "in": [ - "v46" - ], - "out": [ - "v46" - ] - }, - "type": "BuiltinCall" - }, - { - "entries": [ - "Block20", - "Block22" - ], - "exit": { - "cond": "v80", - "targets": [ - "Block25", - "Block24" - ], - "type": "ConditionalJump" + "type": "BuiltinCall" }, - "id": "Block23", - "instructions": [ - { - "in": [ - "0x20", - "v68" - ], - "op": "PhiFunction", - "out": [ - "v71" - ] - }, - { - "in": [ - "0x1f" - ], - "op": "not", - "out": [ - "v70" - ] - }, - { - "in": [ - "0x1f", - "v71" - ], - "op": "add", - "out": [ - "v72" - ] + { + "exit": { + "type": "Terminated" }, - { - "in": [ - "v70", - "v72" - ], - "op": "and", - "out": [ - "v73" - ] + "id": "Block14", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v43" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v44" + ] + }, + { + "in": [ + "v44", + "0x00", + "v43" + ], + "op": "returndatacopy", + "out": [] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v45" + ] + }, + { + "in": [ + "v45", + "v43" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] }, - { - "in": [ - "v73", - "v46" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v59", + "targets": [ + "Block21", + "Block20" ], - "op": "add", - "out": [ - "v77" - ] + "type": "ConditionalJump" }, - { + "id": "Block18", + "instructions": [], + "liveness": { "in": [ "v46", - "v77" - ], - "op": "lt", - "out": [ - "v78" - ] - }, - { - "in": [ - "0xffffffffffffffff", - "v77" - ], - "op": "gt", - "out": [ - "v79" - ] - }, - { - "in": [ - "v78", - "v79" + "v59" ], - "op": "or", "out": [ - "v80" + "v46" ] } - ], - "liveness": { - "in": [ - "v46", - "v71" - ], - "out": [ - "v46", - "v71", - "v77" - ] }, - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block23" + { + "exit": { + "type": "Terminated" + }, + "id": "Block17", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v61" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v62" + ] + }, + { + "in": [ + "v62", + "0x00", + "v61" + ], + "op": "returndatacopy", + "out": [] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v63" + ] + }, + { + "in": [ + "v63", + "v61" + ], + "op": "revert", + "out": [] + } ], - "type": "Jump" - }, - "id": "Block22", - "instructions": [ - { + "liveness": { "in": [], - "op": "returndatasize", - "out": [ - "v68" - ] - } - ], - "liveness": { - "in": [ - "v46" - ], - "out": [ - "v46", - "v68" - ] + "out": [] + }, + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v90", - "targets": [ - "Block28", - "Block27" + { + "entries": [ + "Block18", + "Block28" ], - "type": "ConditionalJump" - }, - "id": "Block25", - "instructions": [ - { + "exit": { + "type": "Terminated" + }, + "id": "Block21", + "instructions": [ + { + "in": [ + "0x00", + "v93" + ], + "op": "PhiFunction", + "out": [ + "v95" + ] + }, + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v94" + ] + }, + { + "in": [ + "v95", + "v94" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v94" + ], + "op": "return", + "out": [] + } + ], + "liveness": { "in": [ - "v77", - "0x40" + "v95" ], - "op": "mstore", "out": [] }, - { - "in": [ - "v71", - "v46" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v67", + "targets": [ + "Block23", + "Block22" ], - "op": "add", - "out": [ - "v88" - ] + "type": "ConditionalJump" }, - { + "id": "Block20", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v66" + ] + }, + { + "in": [ + "v66", + "0x20" + ], + "op": "gt", + "out": [ + "v67" + ] + } + ], + "liveness": { "in": [ - "v46", - "v88" + "v46" ], - "op": "sub", "out": [ - "v89" + "v46" ] }, - { - "in": [ - "0x20", - "v89" + "type": "BuiltinCall" + }, + { + "entries": [ + "Block20", + "Block22" + ], + "exit": { + "cond": "v80", + "targets": [ + "Block25", + "Block24" ], - "op": "slt", - "out": [ - "v90" - ] - } - ], - "liveness": { - "in": [ - "v46", - "v71", - "v77" + "type": "ConditionalJump" + }, + "id": "Block23", + "instructions": [ + { + "in": [ + "0x20", + "v68" + ], + "op": "PhiFunction", + "out": [ + "v71" + ] + }, + { + "in": [ + "0x1f" + ], + "op": "not", + "out": [ + "v70" + ] + }, + { + "in": [ + "0x1f", + "v71" + ], + "op": "add", + "out": [ + "v72" + ] + }, + { + "in": [ + "v70", + "v72" + ], + "op": "and", + "out": [ + "v73" + ] + }, + { + "in": [ + "v73", + "v46" + ], + "op": "add", + "out": [ + "v77" + ] + }, + { + "in": [ + "v46", + "v77" + ], + "op": "lt", + "out": [ + "v78" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v77" + ], + "op": "gt", + "out": [ + "v79" + ] + }, + { + "in": [ + "v78", + "v79" + ], + "op": "or", + "out": [ + "v80" + ] + } ], - "out": [ - "v46" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block24", - "instructions": [ - { + "liveness": { "in": [ - "0x4e487b71", - "0xe0" + "v46", + "v71" ], - "op": "shl", "out": [ - "v81" + "v46", + "v71", + "v77" ] }, - { - "in": [ - "v81", - "0x00" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x41", - "0x04" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x24", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block21" + { + "exit": { + "targets": [ + "Block23" + ], + "type": "Jump" + }, + "id": "Block22", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v68" + ] + } ], - "type": "Jump" - }, - "id": "Block28", - "instructions": [ - { + "liveness": { "in": [ "v46" ], - "op": "mload", "out": [ - "v93" + "v46", + "v68" ] - } - ], - "liveness": { - "in": [ - "v46" - ], - "out": [ - "v93" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block27", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + }, + "type": "BuiltinCall" }, - "type": "BuiltinCall" - } - ], - "functions": {} - }, - "subObjects": { - "C_19": { - "blocks": [ { "exit": { - "cond": "v2", + "cond": "v90", "targets": [ - "Block2", - "Block1" + "Block28", + "Block27" ], "type": "ConditionalJump" }, - "id": "Block0", + "id": "Block25", "instructions": [ { - "builtinArgs": [ - "0x80" + "in": [ + "v77", + "0x40" ], - "in": [], - "op": "memoryguard", + "op": "mstore", + "out": [] + }, + { + "in": [ + "v71", + "v46" + ], + "op": "add", "out": [ - "v0" + "v88" ] }, { "in": [ - "v0", - "0x40" + "v46", + "v88" ], - "op": "mstore", - "out": [] + "op": "sub", + "out": [ + "v89" + ] }, { - "in": [], - "op": "callvalue", + "in": [ + "0x20", + "v89" + ], + "op": "slt", "out": [ - "v2" + "v90" ] } ], "liveness": { - "in": [], + "in": [ + "v46", + "v71", + "v77" + ], "out": [ - "v0" + "v46" ] }, "type": "BuiltinCall" @@ -1729,51 +1580,75 @@ "exit": { "type": "Terminated" }, - "id": "Block2", + "id": "Block24", "instructions": [ { - "builtinArgs": [ - "C_19_deployed" + "in": [ + "0x4e487b71", + "0xe0" ], - "in": [], - "op": "datasize", + "op": "shl", "out": [ - "v4" + "v81" ] }, { - "builtinArgs": [ - "C_19_deployed" + "in": [ + "v81", + "0x00" ], - "in": [], - "op": "dataoffset", - "out": [ - "v5" - ] + "op": "mstore", + "out": [] }, { "in": [ - "v4", - "v5", - "v0" + "0x41", + "0x04" ], - "op": "codecopy", + "op": "mstore", "out": [] }, { "in": [ - "v4", - "v0" + "0x24", + "0x00" ], - "op": "return", + "op": "revert", "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block21" + ], + "type": "Jump" + }, + "id": "Block28", + "instructions": [ + { + "in": [ + "v46" + ], + "op": "mload", + "out": [ + "v93" + ] + } + ], "liveness": { "in": [ - "v0" + "v46" ], - "out": [] + "out": [ + "v93" + ] }, "type": "BuiltinCall" }, @@ -1781,7 +1656,7 @@ "exit": { "type": "Terminated" }, - "id": "Block1", + "id": "Block27", "instructions": [ { "in": [ @@ -1799,330 +1674,455 @@ "type": "BuiltinCall" } ], - "functions": {} - }, - "subObjects": { - "C_19_deployed": { - "blocks": [ - { - "exit": { - "cond": "v5", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "builtinArgs": [ - "0x80" - ], - "in": [], - "op": "memoryguard", - "out": [ - "v0" - ] - }, - { - "in": [ - "v0", - "0x40" + "functions": {}, + "subObjects": { + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" ], - "op": "mstore", - "out": [] + "type": "ConditionalJump" }, - { + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "liveness": { "in": [], - "op": "calldatasize", "out": [ - "v3" - ] - }, - { - "in": [ - "0x04", - "v3" - ], - "op": "lt", - "out": [ - "v4" + "v0" ] }, - { - "in": [ - "v4" - ], - "op": "iszero", - "out": [ - "v5" - ] - } - ], - "liveness": { - "in": [], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block2", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v11", - "targets": [ - "Block4", - "Block3" - ], - "type": "ConditionalJump" - }, - "id": "Block1", - "instructions": [ - { - "in": [ - "0x00" - ], - "op": "calldataload", - "out": [ - "v7" - ] - }, - { - "in": [ - "v7", - "0xe0" - ], - "op": "shr", - "out": [ - "v9" - ] + { + "exit": { + "type": "Terminated" }, - { - "in": [ - "v9", - "0x26121ff0" - ], - "op": "eq", - "out": [ - "v11" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block2" + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v0" + ], + "op": "codecopy", + "out": [] + }, + { + "in": [ + "v4", + "v0" + ], + "op": "return", + "out": [] + } ], - "type": "Jump" - }, - "id": "Block4", - "instructions": [], - "liveness": { - "in": [], - "out": [] - } - }, - { - "exit": { - "cond": "v12", - "targets": [ - "Block6", - "Block5" - ], - "type": "ConditionalJump" - }, - "id": "Block3", - "instructions": [ - { - "in": [], - "op": "callvalue", - "out": [ - "v12" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v17", - "targets": [ - "Block9", - "Block8" - ], - "type": "ConditionalJump" - }, - "id": "Block6", - "instructions": [ - { + "liveness": { "in": [ - "0x03" + "v0" ], - "op": "not", - "out": [ - "v14" - ] - }, - { - "in": [], - "op": "calldatasize", - "out": [ - "v15" - ] + "out": [] }, - { - "in": [ - "v14", - "v15" - ], - "op": "add", - "out": [ - "v16" - ] + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" }, - { - "in": [ - "0x00", - "v16" - ], - "op": "slt", - "out": [ - "v17" - ] - } - ], - "liveness": { - "in": [ - "v0" + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block5", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block9", - "instructions": [ - { - "in": [ - "0x2a", - "v0" - ], - "op": "mstore", + "liveness": { + "in": [], "out": [] }, - { - "in": [ - "0x20", - "v0" - ], - "op": "return", - "out": [] - } - ], - "liveness": { - "in": [ - "v0" + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], + "out": [] + } + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ + { + "in": [ + "0x2a", + "v0" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } ], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block8", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + "functions": {}, + "subObjects": {} }, - "type": "BuiltinCall" + "type": "subObject" } - ], - "functions": {} - }, - "subObjects": {}, - "type": "subObject" + }, + "type": "subObject" + } }, "type": "subObject" - }, - "type": "subObject" + } }, "type": "Object" } diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output index ac154fc16..c79692c3c 100644 --- a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -124,325 +124,325 @@ Yul Control Flow Graph: "type": "BuiltinCall" } ], - "functions": {} - }, - "subObjects": { - "C_19_deployed": { - "blocks": [ - { - "exit": { - "cond": "v5", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "builtinArgs": [ - "0x80" + "functions": {}, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { "in": [], - "op": "memoryguard", "out": [ "v0" ] }, - { - "in": [ - "v0", - "0x40" - ], - "op": "mstore", - "out": [] + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" }, - { + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { "in": [], - "op": "calldatasize", - "out": [ - "v3" - ] + "out": [] }, - { - "in": [ - "0x04", - "v3" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" ], - "op": "lt", - "out": [ - "v4" - ] + "type": "ConditionalJump" }, - { + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { "in": [ - "v4" + "v0" ], - "op": "iszero", "out": [ - "v5" + "v0" ] - } - ], - "liveness": { - "in": [], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" + }, + "type": "BuiltinCall" }, - "id": "Block2", - "instructions": [ - { - "in": [ - "0x00", - "0x00" + { + "exit": { + "targets": [ + "Block2" ], - "op": "revert", + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], "out": [] } - ], - "liveness": { - "in": [], - "out": [] }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v11", - "targets": [ - "Block4", - "Block3" - ], - "type": "ConditionalJump" - }, - "id": "Block1", - "instructions": [ - { - "in": [ - "0x00" + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" ], - "op": "calldataload", - "out": [ - "v7" - ] + "type": "ConditionalJump" }, - { + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { "in": [ - "v7", - "0xe0" + "v0" ], - "op": "shr", "out": [ - "v9" + "v0" ] }, - { - "in": [ - "v9", - "0x26121ff0" - ], - "op": "eq", - "out": [ - "v11" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block2" - ], - "type": "Jump" + "type": "BuiltinCall" }, - "id": "Block4", - "instructions": [], - "liveness": { - "in": [], - "out": [] - } - }, - { - "exit": { - "cond": "v12", - "targets": [ - "Block6", - "Block5" - ], - "type": "ConditionalJump" - }, - "id": "Block3", - "instructions": [ - { - "in": [], - "op": "callvalue", - "out": [ - "v12" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v17", - "targets": [ - "Block9", - "Block8" - ], - "type": "ConditionalJump" - }, - "id": "Block6", - "instructions": [ - { - "in": [ - "0x03" + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" ], - "op": "not", - "out": [ - "v14" - ] + "type": "ConditionalJump" }, - { - "in": [], - "op": "calldatasize", - "out": [ - "v15" - ] - }, - { + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { "in": [ - "v14", - "v15" + "v0" ], - "op": "add", "out": [ - "v16" + "v0" ] }, - { - "in": [ - "0x00", - "v16" - ], - "op": "slt", - "out": [ - "v17" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block5", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" + }, + "type": "BuiltinCall" }, - "id": "Block9", - "instructions": [ - { - "in": [ - "0x2a", - "v0" - ], - "op": "mstore", - "out": [] + { + "exit": { + "type": "Terminated" }, - { + "id": "Block9", + "instructions": [ + { + "in": [ + "0x2a", + "v0" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { "in": [ - "0x20", "v0" ], - "op": "return", "out": [] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" + }, + "type": "BuiltinCall" }, - "id": "Block8", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - } - ], - "functions": {} - }, - "type": "subObject" + }, + "type": "BuiltinCall" + } + ], + "functions": {} + }, + "type": "subObject" + } }, "type": "Object" } diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index dd4dece74..0508769d7 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -123,326 +123,326 @@ Yul Control Flow Graph: "type": "BuiltinCall" } ], - "functions": {} - }, - "subObjects": { - "C_19_deployed": { - "blocks": [ - { - "exit": { - "cond": "v5", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "builtinArgs": [ - "0x80" + "functions": {}, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { "in": [], - "op": "memoryguard", "out": [ "v0" ] }, - { - "in": [ - "v0", - "0x40" - ], - "op": "mstore", - "out": [] + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" }, - { + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { "in": [], - "op": "calldatasize", - "out": [ - "v3" - ] + "out": [] }, - { - "in": [ - "0x04", - "v3" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" ], - "op": "lt", - "out": [ - "v4" - ] + "type": "ConditionalJump" }, - { + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { "in": [ - "v4" + "v0" ], - "op": "iszero", "out": [ - "v5" + "v0" ] - } - ], - "liveness": { - "in": [], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" + }, + "type": "BuiltinCall" }, - "id": "Block2", - "instructions": [ - { - "in": [ - "0x00", - "0x00" + { + "exit": { + "targets": [ + "Block2" ], - "op": "revert", + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], "out": [] } - ], - "liveness": { - "in": [], - "out": [] }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v11", - "targets": [ - "Block4", - "Block3" + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } ], - "type": "ConditionalJump" - }, - "id": "Block1", - "instructions": [ - { + "liveness": { "in": [ - "0x00" + "v0" ], - "op": "calldataload", "out": [ - "v7" + "v0" ] }, - { - "in": [ - "v7", - "0xe0" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" ], - "op": "shr", - "out": [ - "v9" - ] + "type": "ConditionalJump" }, - { + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { "in": [ - "v9", - "0x26121ff0" + "v0" ], - "op": "eq", "out": [ - "v11" + "v0" ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block2" - ], - "type": "Jump" + }, + "type": "BuiltinCall" }, - "id": "Block4", - "instructions": [], - "liveness": { - "in": [], - "out": [] - } - }, - { - "exit": { - "cond": "v12", - "targets": [ - "Block6", - "Block5" + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "type": "ConditionalJump" - }, - "id": "Block3", - "instructions": [ - { + "liveness": { "in": [], - "op": "callvalue", - "out": [ - "v12" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] + "out": [] + }, + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v17", - "targets": [ - "Block9", - "Block8" + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ + { + "in": [ + "0x2a", + "v0" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] + } ], - "type": "ConditionalJump" - }, - "id": "Block6", - "instructions": [ - { + "liveness": { "in": [ - "0x03" + "v0" ], - "op": "not", - "out": [ - "v14" - ] - }, - { - "in": [], - "op": "calldatasize", - "out": [ - "v15" - ] - }, - { - "in": [ - "v14", - "v15" - ], - "op": "add", - "out": [ - "v16" - ] - }, - { - "in": [ - "0x00", - "v16" - ], - "op": "slt", - "out": [ - "v17" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block5", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" + }, + "type": "BuiltinCall" }, - "id": "Block9", - "instructions": [ - { - "in": [ - "0x2a", - "v0" - ], - "op": "mstore", - "out": [] + { + "exit": { + "type": "Terminated" }, - { - "in": [ - "0x20", - "v0" - ], - "op": "return", - "out": [] - } - ], - "liveness": { - "in": [ - "v0" + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block8", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", + "liveness": { + "in": [], "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - } - ], - "functions": {} - }, - "subObjects": {}, - "type": "subObject" + }, + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": {} + }, + "type": "subObject" + } }, "type": "Object" } @@ -571,1156 +571,1007 @@ Yul Control Flow Graph: "type": "BuiltinCall" } ], - "functions": {} - }, - "subObjects": { - "D_38_deployed": { - "blocks": [ - { - "exit": { - "cond": "v5", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "builtinArgs": [ - "0x80" + "functions": {}, + "subObjects": { + "D_38_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { "in": [], - "op": "memoryguard", "out": [ "v0" ] }, - { - "in": [ - "v0", - "0x40" - ], - "op": "mstore", - "out": [] + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" }, - { + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { "in": [], - "op": "calldatasize", - "out": [ - "v3" - ] + "out": [] }, - { - "in": [ - "0x04", - "v3" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" ], - "op": "lt", - "out": [ - "v4" - ] + "type": "ConditionalJump" }, - { + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { "in": [ - "v4" + "v0" ], - "op": "iszero", "out": [ - "v5" + "v0" ] - } - ], - "liveness": { - "in": [], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" + }, + "type": "BuiltinCall" }, - "id": "Block2", - "instructions": [ - { - "in": [ - "0x00", - "0x00" + { + "exit": { + "targets": [ + "Block2" ], - "op": "revert", + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], "out": [] } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v11", - "targets": [ - "Block4", - "Block3" - ], - "type": "ConditionalJump" }, - "id": "Block1", - "instructions": [ - { - "in": [ - "0x00" + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" ], - "op": "calldataload", - "out": [ - "v7" - ] + "type": "ConditionalJump" }, - { + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { "in": [ - "v7", - "0xe0" + "v0" ], - "op": "shr", "out": [ - "v9" + "v0" ] }, - { - "in": [ - "v9", - "0x26121ff0" - ], - "op": "eq", - "out": [ - "v11" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block2" - ], - "type": "Jump" - }, - "id": "Block4", - "instructions": [], - "liveness": { - "in": [], - "out": [] - } - }, - { - "exit": { - "cond": "v12", - "targets": [ - "Block6", - "Block5" - ], - "type": "ConditionalJump" + "type": "BuiltinCall" }, - "id": "Block3", - "instructions": [ - { - "in": [], - "op": "callvalue", - "out": [ - "v12" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v17", - "targets": [ - "Block9", - "Block8" - ], - "type": "ConditionalJump" - }, - "id": "Block6", - "instructions": [ - { - "in": [ - "0x03" + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" ], - "op": "not", - "out": [ - "v14" - ] - }, - { - "in": [], - "op": "calldatasize", - "out": [ - "v15" - ] + "type": "ConditionalJump" }, - { + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { "in": [ - "v14", - "v15" + "v0" ], - "op": "add", "out": [ - "v16" + "v0" ] }, - { - "in": [ - "0x00", - "v16" - ], - "op": "slt", - "out": [ - "v17" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block5", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v28", - "targets": [ - "Block12", - "Block11" + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "type": "ConditionalJump" + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" }, - "id": "Block9", - "instructions": [ - { - "builtinArgs": [ - "C_19" + { + "exit": { + "cond": "v28", + "targets": [ + "Block12", + "Block11" ], - "in": [], - "op": "datasize", - "out": [ - "v18" - ] + "type": "ConditionalJump" }, - { + "id": "Block9", + "instructions": [ + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "datasize", + "out": [ + "v18" + ] + }, + { + "in": [ + "v18", + "v0" + ], + "op": "add", + "out": [ + "v24" + ] + }, + { + "in": [ + "v0", + "v24" + ], + "op": "lt", + "out": [ + "v25" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v24" + ], + "op": "gt", + "out": [ + "v27" + ] + }, + { + "in": [ + "v25", + "v27" + ], + "op": "or", + "out": [ + "v28" + ] + } + ], + "liveness": { "in": [ - "v18", "v0" ], - "op": "add", "out": [ - "v24" - ] - }, - { - "in": [ "v0", + "v18", "v24" - ], - "op": "lt", - "out": [ - "v25" - ] - }, - { - "in": [ - "0xffffffffffffffff", - "v24" - ], - "op": "gt", - "out": [ - "v27" ] }, - { - "in": [ - "v25", - "v27" - ], - "op": "or", - "out": [ - "v28" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0", - "v18", - "v24" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block8", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v42", - "targets": [ - "Block15", - "Block14" + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "type": "ConditionalJump" - }, - "id": "Block12", - "instructions": [ - { - "builtinArgs": [ - "C_19" - ], + "liveness": { "in": [], - "op": "dataoffset", - "out": [ - "v35" - ] - }, - { - "in": [ - "v18", - "v35", - "v0" - ], - "op": "datacopy", "out": [] }, - { - "in": [ - "v0", - "v24" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v42", + "targets": [ + "Block15", + "Block14" ], - "op": "sub", - "out": [ - "v40" - ] + "type": "ConditionalJump" }, - { + "id": "Block12", + "instructions": [ + { + "builtinArgs": [ + "C_19" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v35" + ] + }, + { + "in": [ + "v18", + "v35", + "v0" + ], + "op": "datacopy", + "out": [] + }, + { + "in": [ + "v0", + "v24" + ], + "op": "sub", + "out": [ + "v40" + ] + }, + { + "in": [ + "v40", + "v0", + "0x00" + ], + "op": "create", + "out": [ + "v41" + ] + }, + { + "in": [ + "v41" + ], + "op": "iszero", + "out": [ + "v42" + ] + } + ], + "liveness": { "in": [ - "v40", "v0", - "0x00" + "v18", + "v24" ], - "op": "create", "out": [ "v41" ] }, - { - "in": [ - "v41" - ], - "op": "iszero", - "out": [ - "v42" - ] - } - ], - "liveness": { - "in": [ - "v0", - "v18", - "v24" - ], - "out": [ - "v41" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" + "type": "BuiltinCall" }, - "id": "Block11", - "instructions": [ - { - "in": [ - "0x4e487b71", - "0xe0" - ], - "op": "shl", - "out": [ - "v30" - ] - }, - { - "in": [ - "v30", - "0x00" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x41", - "0x04" - ], - "op": "mstore", - "out": [] + { + "exit": { + "type": "Terminated" }, - { - "in": [ - "0x24", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v60", - "targets": [ - "Block18", - "Block17" + "id": "Block11", + "instructions": [ + { + "in": [ + "0x4e487b71", + "0xe0" + ], + "op": "shl", + "out": [ + "v30" + ] + }, + { + "in": [ + "v30", + "0x00" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x41", + "0x04" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x24", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "type": "ConditionalJump" - }, - "id": "Block15", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v46" - ] - }, - { - "in": [ - "0x026121ff", - "0xe4" - ], - "op": "shl", - "out": [ - "v49" - ] - }, - { - "in": [ - "v49", - "v46" - ], - "op": "mstore", + "liveness": { + "in": [], "out": [] }, - { - "in": [ - "0x01", - "0xa0" - ], - "op": "shl", - "out": [ - "v53" - ] - }, - { - "in": [ - "0x01", - "v53" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v60", + "targets": [ + "Block18", + "Block17" ], - "op": "sub", - "out": [ - "v54" - ] + "type": "ConditionalJump" }, - { + "id": "Block15", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v46" + ] + }, + { + "in": [ + "0x026121ff", + "0xe4" + ], + "op": "shl", + "out": [ + "v49" + ] + }, + { + "in": [ + "v49", + "v46" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x01", + "0xa0" + ], + "op": "shl", + "out": [ + "v53" + ] + }, + { + "in": [ + "0x01", + "v53" + ], + "op": "sub", + "out": [ + "v54" + ] + }, + { + "in": [ + "v54", + "v41" + ], + "op": "and", + "out": [ + "v57" + ] + }, + { + "in": [], + "op": "gas", + "out": [ + "v58" + ] + }, + { + "in": [ + "0x20", + "v46", + "0x04", + "v46", + "v57", + "v58" + ], + "op": "staticcall", + "out": [ + "v59" + ] + }, + { + "in": [ + "v59" + ], + "op": "iszero", + "out": [ + "v60" + ] + } + ], + "liveness": { "in": [ - "v54", "v41" ], - "op": "and", - "out": [ - "v57" - ] - }, - { - "in": [], - "op": "gas", "out": [ - "v58" - ] - }, - { - "in": [ - "0x20", "v46", - "0x04", - "v46", - "v57", - "v58" - ], - "op": "staticcall", - "out": [ - "v59" - ] - }, - { - "in": [ "v59" - ], - "op": "iszero", - "out": [ - "v60" - ] - } - ], - "liveness": { - "in": [ - "v41" - ], - "out": [ - "v46", - "v59" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block14", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v43" - ] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v44" - ] - }, - { - "in": [ - "v44", - "0x00", - "v43" - ], - "op": "returndatacopy", - "out": [] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v45" - ] - }, - { - "in": [ - "v45", - "v43" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v59", - "targets": [ - "Block21", - "Block20" - ], - "type": "ConditionalJump" - }, - "id": "Block18", - "instructions": [], - "liveness": { - "in": [ - "v46", - "v59" - ], - "out": [ - "v46" - ] - } - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block17", - "instructions": [ - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v61" - ] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v62" - ] - }, - { - "in": [ - "v62", - "0x00", - "v61" - ], - "op": "returndatacopy", - "out": [] - }, - { - "in": [], - "op": "returndatasize", - "out": [ - "v63" - ] - }, - { - "in": [ - "v63", - "v61" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "entries": [ - "Block18", - "Block28" - ], - "exit": { - "type": "Terminated" - }, - "id": "Block21", - "instructions": [ - { - "in": [ - "0x00", - "v93" - ], - "op": "PhiFunction", - "out": [ - "v95" ] }, - { - "in": [ - "0x40" - ], - "op": "mload", - "out": [ - "v94" - ] - }, - { - "in": [ - "v95", - "v94" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x20", - "v94" - ], - "op": "return", - "out": [] - } - ], - "liveness": { - "in": [ - "v95" - ], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v67", - "targets": [ - "Block23", - "Block22" - ], - "type": "ConditionalJump" - }, - "id": "Block20", - "instructions": [ - { - "in": [], - "op": "returndatasize", - "out": [ - "v66" - ] - }, - { - "in": [ - "v66", - "0x20" - ], - "op": "gt", - "out": [ - "v67" - ] - } - ], - "liveness": { - "in": [ - "v46" - ], - "out": [ - "v46" - ] - }, - "type": "BuiltinCall" - }, - { - "entries": [ - "Block20", - "Block22" - ], - "exit": { - "cond": "v80", - "targets": [ - "Block25", - "Block24" - ], - "type": "ConditionalJump" + "type": "BuiltinCall" }, - "id": "Block23", - "instructions": [ - { - "in": [ - "0x20", - "v68" - ], - "op": "PhiFunction", - "out": [ - "v71" - ] - }, - { - "in": [ - "0x1f" - ], - "op": "not", - "out": [ - "v70" - ] - }, - { - "in": [ - "0x1f", - "v71" - ], - "op": "add", - "out": [ - "v72" - ] + { + "exit": { + "type": "Terminated" }, - { - "in": [ - "v70", - "v72" - ], - "op": "and", - "out": [ - "v73" - ] + "id": "Block14", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v43" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v44" + ] + }, + { + "in": [ + "v44", + "0x00", + "v43" + ], + "op": "returndatacopy", + "out": [] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v45" + ] + }, + { + "in": [ + "v45", + "v43" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] }, - { - "in": [ - "v73", - "v46" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v59", + "targets": [ + "Block21", + "Block20" ], - "op": "add", - "out": [ - "v77" - ] + "type": "ConditionalJump" }, - { + "id": "Block18", + "instructions": [], + "liveness": { "in": [ "v46", - "v77" - ], - "op": "lt", - "out": [ - "v78" - ] - }, - { - "in": [ - "0xffffffffffffffff", - "v77" - ], - "op": "gt", - "out": [ - "v79" - ] - }, - { - "in": [ - "v78", - "v79" + "v59" ], - "op": "or", "out": [ - "v80" + "v46" ] } - ], - "liveness": { - "in": [ - "v46", - "v71" - ], - "out": [ - "v46", - "v71", - "v77" - ] }, - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block23" + { + "exit": { + "type": "Terminated" + }, + "id": "Block17", + "instructions": [ + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v61" + ] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v62" + ] + }, + { + "in": [ + "v62", + "0x00", + "v61" + ], + "op": "returndatacopy", + "out": [] + }, + { + "in": [], + "op": "returndatasize", + "out": [ + "v63" + ] + }, + { + "in": [ + "v63", + "v61" + ], + "op": "revert", + "out": [] + } ], - "type": "Jump" - }, - "id": "Block22", - "instructions": [ - { + "liveness": { "in": [], - "op": "returndatasize", - "out": [ - "v68" - ] - } - ], - "liveness": { - "in": [ - "v46" - ], - "out": [ - "v46", - "v68" - ] + "out": [] + }, + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v90", - "targets": [ - "Block28", - "Block27" + { + "entries": [ + "Block18", + "Block28" ], - "type": "ConditionalJump" - }, - "id": "Block25", - "instructions": [ - { + "exit": { + "type": "Terminated" + }, + "id": "Block21", + "instructions": [ + { + "in": [ + "0x00", + "v93" + ], + "op": "PhiFunction", + "out": [ + "v95" + ] + }, + { + "in": [ + "0x40" + ], + "op": "mload", + "out": [ + "v94" + ] + }, + { + "in": [ + "v95", + "v94" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v94" + ], + "op": "return", + "out": [] + } + ], + "liveness": { "in": [ - "v77", - "0x40" + "v95" ], - "op": "mstore", "out": [] }, - { - "in": [ - "v71", - "v46" + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v67", + "targets": [ + "Block23", + "Block22" ], - "op": "add", - "out": [ - "v88" - ] + "type": "ConditionalJump" }, - { + "id": "Block20", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v66" + ] + }, + { + "in": [ + "v66", + "0x20" + ], + "op": "gt", + "out": [ + "v67" + ] + } + ], + "liveness": { "in": [ - "v46", - "v88" + "v46" ], - "op": "sub", "out": [ - "v89" + "v46" ] }, - { - "in": [ - "0x20", - "v89" + "type": "BuiltinCall" + }, + { + "entries": [ + "Block20", + "Block22" + ], + "exit": { + "cond": "v80", + "targets": [ + "Block25", + "Block24" ], - "op": "slt", - "out": [ - "v90" - ] - } - ], - "liveness": { - "in": [ - "v46", - "v71", - "v77" + "type": "ConditionalJump" + }, + "id": "Block23", + "instructions": [ + { + "in": [ + "0x20", + "v68" + ], + "op": "PhiFunction", + "out": [ + "v71" + ] + }, + { + "in": [ + "0x1f" + ], + "op": "not", + "out": [ + "v70" + ] + }, + { + "in": [ + "0x1f", + "v71" + ], + "op": "add", + "out": [ + "v72" + ] + }, + { + "in": [ + "v70", + "v72" + ], + "op": "and", + "out": [ + "v73" + ] + }, + { + "in": [ + "v73", + "v46" + ], + "op": "add", + "out": [ + "v77" + ] + }, + { + "in": [ + "v46", + "v77" + ], + "op": "lt", + "out": [ + "v78" + ] + }, + { + "in": [ + "0xffffffffffffffff", + "v77" + ], + "op": "gt", + "out": [ + "v79" + ] + }, + { + "in": [ + "v78", + "v79" + ], + "op": "or", + "out": [ + "v80" + ] + } ], - "out": [ - "v46" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block24", - "instructions": [ - { + "liveness": { "in": [ - "0x4e487b71", - "0xe0" + "v46", + "v71" ], - "op": "shl", "out": [ - "v81" + "v46", + "v71", + "v77" ] }, - { - "in": [ - "v81", - "0x00" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x41", - "0x04" - ], - "op": "mstore", - "out": [] - }, - { - "in": [ - "0x24", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block21" + { + "exit": { + "targets": [ + "Block23" + ], + "type": "Jump" + }, + "id": "Block22", + "instructions": [ + { + "in": [], + "op": "returndatasize", + "out": [ + "v68" + ] + } ], - "type": "Jump" - }, - "id": "Block28", - "instructions": [ - { + "liveness": { "in": [ "v46" ], - "op": "mload", "out": [ - "v93" + "v46", + "v68" ] - } - ], - "liveness": { - "in": [ - "v46" - ], - "out": [ - "v93" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block27", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + }, + "type": "BuiltinCall" }, - "type": "BuiltinCall" - } - ], - "functions": {} - }, - "subObjects": { - "C_19": { - "blocks": [ { "exit": { - "cond": "v2", + "cond": "v90", "targets": [ - "Block2", - "Block1" + "Block28", + "Block27" ], "type": "ConditionalJump" }, - "id": "Block0", + "id": "Block25", "instructions": [ { - "builtinArgs": [ - "0x80" + "in": [ + "v77", + "0x40" ], - "in": [], - "op": "memoryguard", + "op": "mstore", + "out": [] + }, + { + "in": [ + "v71", + "v46" + ], + "op": "add", "out": [ - "v0" + "v88" ] }, { "in": [ - "v0", - "0x40" + "v46", + "v88" ], - "op": "mstore", - "out": [] + "op": "sub", + "out": [ + "v89" + ] }, { - "in": [], - "op": "callvalue", + "in": [ + "0x20", + "v89" + ], + "op": "slt", "out": [ - "v2" + "v90" ] } ], "liveness": { - "in": [], + "in": [ + "v46", + "v71", + "v77" + ], "out": [ - "v0" + "v46" ] }, "type": "BuiltinCall" @@ -1729,51 +1580,75 @@ Yul Control Flow Graph: "exit": { "type": "Terminated" }, - "id": "Block2", + "id": "Block24", "instructions": [ { - "builtinArgs": [ - "C_19_deployed" + "in": [ + "0x4e487b71", + "0xe0" ], - "in": [], - "op": "datasize", + "op": "shl", "out": [ - "v4" + "v81" ] }, { - "builtinArgs": [ - "C_19_deployed" + "in": [ + "v81", + "0x00" ], - "in": [], - "op": "dataoffset", - "out": [ - "v5" - ] + "op": "mstore", + "out": [] }, { "in": [ - "v4", - "v5", - "v0" + "0x41", + "0x04" ], - "op": "codecopy", + "op": "mstore", "out": [] }, { "in": [ - "v4", - "v0" + "0x24", + "0x00" ], - "op": "return", + "op": "revert", "out": [] } ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block21" + ], + "type": "Jump" + }, + "id": "Block28", + "instructions": [ + { + "in": [ + "v46" + ], + "op": "mload", + "out": [ + "v93" + ] + } + ], "liveness": { "in": [ - "v0" + "v46" ], - "out": [] + "out": [ + "v93" + ] }, "type": "BuiltinCall" }, @@ -1781,7 +1656,7 @@ Yul Control Flow Graph: "exit": { "type": "Terminated" }, - "id": "Block1", + "id": "Block27", "instructions": [ { "in": [ @@ -1799,330 +1674,455 @@ Yul Control Flow Graph: "type": "BuiltinCall" } ], - "functions": {} - }, - "subObjects": { - "C_19_deployed": { - "blocks": [ - { - "exit": { - "cond": "v5", - "targets": [ - "Block2", - "Block1" - ], - "type": "ConditionalJump" - }, - "id": "Block0", - "instructions": [ - { - "builtinArgs": [ - "0x80" - ], - "in": [], - "op": "memoryguard", - "out": [ - "v0" - ] - }, - { - "in": [ - "v0", - "0x40" + "functions": {}, + "subObjects": { + "C_19": { + "blocks": [ + { + "exit": { + "cond": "v2", + "targets": [ + "Block2", + "Block1" ], - "op": "mstore", - "out": [] + "type": "ConditionalJump" }, - { + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "callvalue", + "out": [ + "v2" + ] + } + ], + "liveness": { "in": [], - "op": "calldatasize", "out": [ - "v3" - ] - }, - { - "in": [ - "0x04", - "v3" - ], - "op": "lt", - "out": [ - "v4" + "v0" ] }, - { - "in": [ - "v4" - ], - "op": "iszero", - "out": [ - "v5" - ] - } - ], - "liveness": { - "in": [], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block2", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + "type": "BuiltinCall" }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v11", - "targets": [ - "Block4", - "Block3" - ], - "type": "ConditionalJump" - }, - "id": "Block1", - "instructions": [ - { - "in": [ - "0x00" - ], - "op": "calldataload", - "out": [ - "v7" - ] - }, - { - "in": [ - "v7", - "0xe0" - ], - "op": "shr", - "out": [ - "v9" - ] + { + "exit": { + "type": "Terminated" }, - { - "in": [ - "v9", - "0x26121ff0" - ], - "op": "eq", - "out": [ - "v11" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "targets": [ - "Block2" + "id": "Block2", + "instructions": [ + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "datasize", + "out": [ + "v4" + ] + }, + { + "builtinArgs": [ + "C_19_deployed" + ], + "in": [], + "op": "dataoffset", + "out": [ + "v5" + ] + }, + { + "in": [ + "v4", + "v5", + "v0" + ], + "op": "codecopy", + "out": [] + }, + { + "in": [ + "v4", + "v0" + ], + "op": "return", + "out": [] + } ], - "type": "Jump" - }, - "id": "Block4", - "instructions": [], - "liveness": { - "in": [], - "out": [] - } - }, - { - "exit": { - "cond": "v12", - "targets": [ - "Block6", - "Block5" - ], - "type": "ConditionalJump" - }, - "id": "Block3", - "instructions": [ - { - "in": [], - "op": "callvalue", - "out": [ - "v12" - ] - } - ], - "liveness": { - "in": [ - "v0" - ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "cond": "v17", - "targets": [ - "Block9", - "Block8" - ], - "type": "ConditionalJump" - }, - "id": "Block6", - "instructions": [ - { + "liveness": { "in": [ - "0x03" + "v0" ], - "op": "not", - "out": [ - "v14" - ] - }, - { - "in": [], - "op": "calldatasize", - "out": [ - "v15" - ] + "out": [] }, - { - "in": [ - "v14", - "v15" - ], - "op": "add", - "out": [ - "v16" - ] + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" }, - { - "in": [ - "0x00", - "v16" - ], - "op": "slt", - "out": [ - "v17" - ] - } - ], - "liveness": { - "in": [ - "v0" + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } ], - "out": [ - "v0" - ] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block5", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block9", - "instructions": [ - { - "in": [ - "0x2a", - "v0" - ], - "op": "mstore", + "liveness": { + "in": [], "out": [] }, - { - "in": [ - "0x20", - "v0" - ], - "op": "return", - "out": [] - } - ], - "liveness": { - "in": [ - "v0" + "type": "BuiltinCall" + } + ], + "functions": {}, + "subObjects": { + "C_19_deployed": { + "blocks": [ + { + "exit": { + "cond": "v5", + "targets": [ + "Block2", + "Block1" + ], + "type": "ConditionalJump" + }, + "id": "Block0", + "instructions": [ + { + "builtinArgs": [ + "0x80" + ], + "in": [], + "op": "memoryguard", + "out": [ + "v0" + ] + }, + { + "in": [ + "v0", + "0x40" + ], + "op": "mstore", + "out": [] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v3" + ] + }, + { + "in": [ + "0x04", + "v3" + ], + "op": "lt", + "out": [ + "v4" + ] + }, + { + "in": [ + "v4" + ], + "op": "iszero", + "out": [ + "v5" + ] + } + ], + "liveness": { + "in": [], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block2", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v11", + "targets": [ + "Block4", + "Block3" + ], + "type": "ConditionalJump" + }, + "id": "Block1", + "instructions": [ + { + "in": [ + "0x00" + ], + "op": "calldataload", + "out": [ + "v7" + ] + }, + { + "in": [ + "v7", + "0xe0" + ], + "op": "shr", + "out": [ + "v9" + ] + }, + { + "in": [ + "v9", + "0x26121ff0" + ], + "op": "eq", + "out": [ + "v11" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "targets": [ + "Block2" + ], + "type": "Jump" + }, + "id": "Block4", + "instructions": [], + "liveness": { + "in": [], + "out": [] + } + }, + { + "exit": { + "cond": "v12", + "targets": [ + "Block6", + "Block5" + ], + "type": "ConditionalJump" + }, + "id": "Block3", + "instructions": [ + { + "in": [], + "op": "callvalue", + "out": [ + "v12" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "cond": "v17", + "targets": [ + "Block9", + "Block8" + ], + "type": "ConditionalJump" + }, + "id": "Block6", + "instructions": [ + { + "in": [ + "0x03" + ], + "op": "not", + "out": [ + "v14" + ] + }, + { + "in": [], + "op": "calldatasize", + "out": [ + "v15" + ] + }, + { + "in": [ + "v14", + "v15" + ], + "op": "add", + "out": [ + "v16" + ] + }, + { + "in": [ + "0x00", + "v16" + ], + "op": "slt", + "out": [ + "v17" + ] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [ + "v0" + ] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block5", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block9", + "instructions": [ + { + "in": [ + "0x2a", + "v0" + ], + "op": "mstore", + "out": [] + }, + { + "in": [ + "0x20", + "v0" + ], + "op": "return", + "out": [] + } + ], + "liveness": { + "in": [ + "v0" + ], + "out": [] + }, + "type": "BuiltinCall" + }, + { + "exit": { + "type": "Terminated" + }, + "id": "Block8", + "instructions": [ + { + "in": [ + "0x00", + "0x00" + ], + "op": "revert", + "out": [] + } + ], + "liveness": { + "in": [], + "out": [] + }, + "type": "BuiltinCall" + } ], - "out": [] - }, - "type": "BuiltinCall" - }, - { - "exit": { - "type": "Terminated" - }, - "id": "Block8", - "instructions": [ - { - "in": [ - "0x00", - "0x00" - ], - "op": "revert", - "out": [] - } - ], - "liveness": { - "in": [], - "out": [] + "functions": {}, + "subObjects": {} }, - "type": "BuiltinCall" + "type": "subObject" } - ], - "functions": {} - }, - "subObjects": {}, - "type": "subObject" + }, + "type": "subObject" + } }, "type": "subObject" - }, - "type": "subObject" + } }, "type": "Object" } From 18c4a778fd3a3d2e90e1edc03f80ff37a2668bac Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Wed, 8 Jan 2025 16:09:25 +0100 Subject: [PATCH 0585/1340] Remove unnecessary virtual specifier. --- libevmasm/EVMAssemblyStack.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index cf959de79..55c9fd684 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -50,25 +50,25 @@ class EVMAssemblyStack: public AbstractAssemblyStack std::string const& name() const { return m_name; } - virtual LinkerObject const& object(std::string const& _contractName) const override; - virtual LinkerObject const& runtimeObject(std::string const& _contractName) const override; + LinkerObject const& object(std::string const& _contractName) const override; + LinkerObject const& runtimeObject(std::string const& _contractName) const override; std::shared_ptr const& evmAssembly() const { return m_evmAssembly; } std::shared_ptr const& evmRuntimeAssembly() const { return m_evmRuntimeAssembly; } - virtual std::string const* sourceMapping(std::string const& _contractName) const override; - virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const override; + std::string const* sourceMapping(std::string const& _contractName) const override; + std::string const* runtimeSourceMapping(std::string const& _contractName) const override; - virtual Json assemblyJSON(std::string const& _contractName) const override; - virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const override; + Json assemblyJSON(std::string const& _contractName) const override; + std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const override; - virtual std::string const filesystemFriendlyName(std::string const& _contractName) const override; + std::string const filesystemFriendlyName(std::string const& _contractName) const override; - virtual std::vector contractNames() const override { return {m_name}; } - virtual std::vector sourceNames() const override; + std::vector contractNames() const override { return {m_name}; } + std::vector sourceNames() const override; std::map sourceIndices() const; - virtual bool compilationSuccessful() const override { return m_evmAssembly != nullptr; } + bool compilationSuccessful() const override { return m_evmAssembly != nullptr; } void selectDebugInfo(langutil::DebugInfoSelection _debugInfoSelection) { From d17a4dd777d4d12724455fe92897047fb4b93243 Mon Sep 17 00:00:00 2001 From: santamasa <0xstarker@gmail.com> Date: Wed, 8 Jan 2025 21:10:43 +0300 Subject: [PATCH 0586/1340] docs: typo fix Update CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 273eac602..898042b7f 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -3,7 +3,7 @@ ## Our Pledge In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and +contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socioeconomic status, nationality, personal From d90acc1c77ca9746dcc80ce63d76dd7e4e6c52aa Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 6 Jan 2025 00:52:48 +0100 Subject: [PATCH 0587/1340] Reduce some file system paths' lengths --- .../input.json | 27 ---------------- .../output.json | 32 ------------------- 2 files changed, 59 deletions(-) delete mode 100644 test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/input.json delete mode 100644 test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/output.json diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/input.json b/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/input.json deleted file mode 100644 index e3a42c295..000000000 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/input.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "language": "Solidity", - "sources": - { - "A": - { - "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n\ncontract test { - struct S { - uint x; - } - S s; - function f(bool b) public { - s.x |= b ? 1 : 2; - assert(s.x > 0); - } - }" - } - }, - "settings": - { - "modelChecker": - { - "engine": "all", - "showUnsupported": false - } - } -} diff --git a/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/output.json deleted file mode 100644 index fb599d21d..000000000 --- a/test/cmdlineTests/standard_model_checker_show_unsupported_false_all_engines/standard_model_checker_show_unsupported_false_all_enginesstandard_model_checker_show_unsupported_false_bmc/output.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "errors": - [ - { - "component": "general", - "errorCode": "5840", - "formattedMessage": "Warning: CHC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. - -", - "message": "CHC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", - "severity": "warning", - "type": "Warning" - }, - { - "component": "general", - "errorCode": "2788", - "formattedMessage": "Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. - -", - "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", - "severity": "warning", - "type": "Warning" - } - ], - "sources": - { - "A": - { - "id": 0 - } - } -} From eabc97a252bd27014208e6e23cbfbd9de737b89c Mon Sep 17 00:00:00 2001 From: Marco Date: Fri, 3 Jan 2025 15:45:35 +0100 Subject: [PATCH 0588/1340] typo assembly.rst --- docs/assembly.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/assembly.rst b/docs/assembly.rst index 09e158e48..c1af2907a 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -209,7 +209,7 @@ Local Solidity variables are available for assignments, for example: ``assembly { signextend(, x) }`` -Since Solidity 0.6.0, the name of a inline assembly variable may not +Since Solidity 0.6.0, the name of an inline assembly variable may not shadow any declaration visible in the scope of the inline assembly block (including variable, contract and function declarations). From 0191fd99792cf2e389fb909cdda0b3a307330b02 Mon Sep 17 00:00:00 2001 From: Marco Date: Fri, 3 Jan 2025 15:46:24 +0100 Subject: [PATCH 0589/1340] typo circular_reference_internal_function.sol --- .../bytecodeReferences/circular_reference_internal_function.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsolidity/syntaxTests/bytecodeReferences/circular_reference_internal_function.sol b/test/libsolidity/syntaxTests/bytecodeReferences/circular_reference_internal_function.sol index 0b06b2b7a..f25690aad 100644 --- a/test/libsolidity/syntaxTests/bytecodeReferences/circular_reference_internal_function.sol +++ b/test/libsolidity/syntaxTests/bytecodeReferences/circular_reference_internal_function.sol @@ -1,6 +1,6 @@ contract C { - // Internal uncalled function should not cause an cyclic dep. error + // Internal uncalled function should not cause a cyclic dep. error function foo() internal { new D(); } function callFoo() virtual public { foo(); } } From 94bfae1a941606bd3f90f1c2bf8dcae45dbc904a Mon Sep 17 00:00:00 2001 From: "gmh5225.eth" <13917777+gmh5225@users.noreply.github.com> Date: Tue, 24 Dec 2024 22:34:07 +0800 Subject: [PATCH 0590/1340] fix compilation error on MSVC --- liblangutil/EVMVersion.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index 6f7ac9139..832b6ebaa 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -19,8 +19,9 @@ * EVM versioning. */ -#include #include +#include + using namespace solidity; using namespace solidity::evmasm; @@ -29,7 +30,7 @@ using namespace solidity::langutil; bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersion) const { // EOF version can be only defined since prague - assert(!_eofVersion.has_value() || this->m_version >= prague()); + assert(!_eofVersion.has_value() || static_cast(m_version) >= static_cast(prague().m_version)); switch (_opcode) { From 9446ea1a12385226b26d3ee5229d66e8de9eda92 Mon Sep 17 00:00:00 2001 From: gmh5225 <2315157@qq.com> Date: Sat, 28 Dec 2024 02:55:00 +0800 Subject: [PATCH 0591/1340] Fix MSVC compilation error on EVMVersion comparison --- liblangutil/EVMVersion.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index 832b6ebaa..ac087b8fc 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -19,9 +19,8 @@ * EVM versioning. */ -#include #include - +#include using namespace solidity; using namespace solidity::evmasm; @@ -30,7 +29,7 @@ using namespace solidity::langutil; bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersion) const { // EOF version can be only defined since prague - assert(!_eofVersion.has_value() || static_cast(m_version) >= static_cast(prague().m_version)); + assert(!_eofVersion.has_value() || *this >= prague()); switch (_opcode) { From 4f5adf4444db7763134e0bed37d78c056cf6f059 Mon Sep 17 00:00:00 2001 From: "gmh5225.eth" <13917777+gmh5225@users.noreply.github.com> Date: Tue, 24 Dec 2024 20:05:36 +0800 Subject: [PATCH 0592/1340] fix correct Boost compilation flags --- docs/installing-solidity.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 0d63d4821..57499b812 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -505,7 +505,7 @@ And for Windows: cmake -G "Visual Studio 16 2019" .. In case you want to use the version of boost installed by ``scripts\install_deps.ps1``, you will -additionally need to pass ``-DBoost_DIR="deps\boost\lib\cmake\Boost-*"`` and ``-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded`` +additionally need to pass ``-DBoost_ROOT="deps/boost" -DBoost_INCLUDE_DIR="deps/boost/include"`` and ``-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded`` as arguments to the call to ``cmake``. This should result in the creation of **solidity.sln** in that build directory. From 225ccac729ddcd7bc5ce1e9b3d66511a9d627920 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 9 Jan 2025 16:54:00 +0100 Subject: [PATCH 0593/1340] SMTChecker: Fix error when initializing fixed-sized-bytes array When encoding initialization of an array of fixed-sized bytes, we need to make sure the elements of the inlined array have the right SMT sort. Because of implict conversion from string literals to fixed-sized bytes, we need to pass the information about the desired type when encoding the individual elements. --- Changelog.md | 7 ++++--- libsolidity/formal/SMTEncoder.cpp | 8 +++++--- .../fixed_bytes_array_from_strig_inline_array.sol | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/typecast/fixed_bytes_array_from_strig_inline_array.sol diff --git a/Changelog.md b/Changelog.md index 731640653..521ee8793 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,9 +9,10 @@ Compiler Features: Bugfixes: -* General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. -* Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested. -* Yul: Fix internal compiler error when a code generation error should be reported instead. + * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. + * SMTChecker: Fix SMT logic error when initializing a fixed-sized-bytes array using string literals. + * Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested. + * Yul: Fix internal compiler error when a code generation error should be reported instead. ### 0.8.28 (2024-10-09) diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 7e338d9f8..01627007f 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -428,9 +428,11 @@ void SMTEncoder::endVisit(TupleExpression const& _tuple) { // Add constraints for the length and values as it is known. auto symbArray = std::dynamic_pointer_cast(m_context.expression(_tuple)); - solAssert(symbArray, ""); - - addArrayLiteralAssertions(*symbArray, applyMap(_tuple.components(), [&](auto const& c) { return expr(*c); })); + smtAssert(symbArray, "Inline array must be represented with SymbolicArrayVariable"); + auto originalType = symbArray->originalType(); + auto arrayType = dynamic_cast(originalType); + smtAssert(arrayType, "Type of inline array must be ArrayType"); + addArrayLiteralAssertions(*symbArray, applyMap(_tuple.components(), [&](auto const& c) { return expr(*c, arrayType->baseType()); })); } else { diff --git a/test/libsolidity/smtCheckerTests/typecast/fixed_bytes_array_from_strig_inline_array.sol b/test/libsolidity/smtCheckerTests/typecast/fixed_bytes_array_from_strig_inline_array.sol new file mode 100644 index 000000000..c92fe2a7e --- /dev/null +++ b/test/libsolidity/smtCheckerTests/typecast/fixed_bytes_array_from_strig_inline_array.sol @@ -0,0 +1,14 @@ +contract D { + function test() public pure { + bytes7[2] memory dummyBytes = [bytes7("A"), "B"]; + assert(uint56(dummyBytes[0]) == 0x41000000000000); + assert(uint56(dummyBytes[1]) == 0x42000000000000); + assert(uint56(dummyBytes[1]) == 0x41000000000000); // Should fail + } +} +// ==== +// SMTEngine: chc +// SMTTargets: assert +// ---- +// Warning 6328: (231-280): CHC: Assertion violation happens here.\nCounterexample:\n\ndummyBytes = [0x41000000000000, 0x42000000000000]\n\nTransaction trace:\nD.constructor()\nD.test() +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 32c546f899b1b72fca058d6b50fbb1a8d0f41af6 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:52:32 +0100 Subject: [PATCH 0594/1340] Yul control flow: Add toDot method to liveness --- libyul/backends/evm/ControlFlow.cpp | 5 +++++ libyul/backends/evm/ControlFlow.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/libyul/backends/evm/ControlFlow.cpp b/libyul/backends/evm/ControlFlow.cpp index 3ec123a8e..863fa30f6 100644 --- a/libyul/backends/evm/ControlFlow.cpp +++ b/libyul/backends/evm/ControlFlow.cpp @@ -26,3 +26,8 @@ ControlFlowLiveness::ControlFlowLiveness(ControlFlow const& _controlFlow): mainLiveness(std::make_unique(*_controlFlow.mainGraph)), functionLiveness(_controlFlow.functionGraphs | ranges::views::transform([](auto const& _cfg) { return std::make_unique(*_cfg); }) | ranges::to) { } + +std::string ControlFlowLiveness::toDot() const +{ + return controlFlow.get().toDot(this); +} diff --git a/libyul/backends/evm/ControlFlow.h b/libyul/backends/evm/ControlFlow.h index 6438f330c..394ce00c5 100644 --- a/libyul/backends/evm/ControlFlow.h +++ b/libyul/backends/evm/ControlFlow.h @@ -34,6 +34,8 @@ struct ControlFlowLiveness{ std::reference_wrapper controlFlow; std::unique_ptr mainLiveness; std::vector> functionLiveness; + + std::string toDot() const; }; struct ControlFlow From fce849d558f2cf9bd24518e3efb6c9b7f1bdfc48 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:53:27 +0100 Subject: [PATCH 0595/1340] SSA CFG to dot: Replaces reserved dollar characters in function names --- libyul/backends/evm/SSAControlFlowGraph.cpp | 31 +++++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/libyul/backends/evm/SSAControlFlowGraph.cpp b/libyul/backends/evm/SSAControlFlowGraph.cpp index 8e52e78e7..733f4967d 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.cpp +++ b/libyul/backends/evm/SSAControlFlowGraph.cpp @@ -77,6 +77,25 @@ class SSACFGPrinter ); } + static std::string escape(std::string_view const str) + { + using namespace std::literals; + static constexpr auto replacements = std::array{std::make_tuple('$', "_d_")}; + std::stringstream ss; + for (auto const c: str) + { + auto const it = std::find_if(replacements.begin(), replacements.end(), [c](auto const& replacement) + { + return std::get<0>(replacement) == c; + }); + if (it != replacements.end()) + ss << std::get<1>(*it); + else + ss << c; + } + return ss.str(); + } + std::string formatBlockHandle(SSACFG::BlockId const& _id) const { return fmt::format("Block{}_{}", m_functionIndex, _id.value); @@ -157,7 +176,7 @@ class SSACFGPrinter ); m_result << fmt::format( "{}({})\\l\\\n", - label, + escape(label), fmt::join(operation.inputs | ranges::views::transform(valueToString), ", ") ); } @@ -247,15 +266,15 @@ class SSACFGPrinter void printFunction(Scope::Function const& _fun) { - static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return functionReturnValue.get().name.str(); }; + static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return escape(functionReturnValue.get().name.str()); }; static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", std::get<1>(arg).value); }; - m_result << "FunctionEntry_" << _fun.name.str() << "_" << m_cfg.entry.value << " [label=\""; + m_result << "FunctionEntry_" << escape(_fun.name.str()) << "_" << m_cfg.entry.value << " [label=\""; if (!m_cfg.returns.empty()) - m_result << fmt::format("function {0}:\n {1} := {0}({2})", _fun.name.str(), fmt::join(m_cfg.returns | ranges::views::transform(returnsTransform), ", "), fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + m_result << fmt::format("function {0}:\n {1} := {0}({2})", escape(_fun.name.str()), fmt::join(m_cfg.returns | ranges::views::transform(returnsTransform), ", "), fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); else - m_result << fmt::format("function {0}:\n {0}({1})", _fun.name.str(), fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + m_result << fmt::format("function {0}:\n {0}({1})", escape(_fun.name.str()), fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); m_result << "\"];\n"; - m_result << "FunctionEntry_" << _fun.name.str() << "_" << m_cfg.entry.value << " -> Block" << m_functionIndex << "_" << m_cfg.entry.value << ";\n"; + m_result << "FunctionEntry_" << escape(_fun.name.str()) << "_" << m_cfg.entry.value << " -> Block" << m_functionIndex << "_" << m_cfg.entry.value << ";\n"; printBlock(m_cfg.entry); } From 74314fc77e295659d3772265e7b40166ba9991c6 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:12:56 +0100 Subject: [PATCH 0596/1340] Liveness: Add block exit values to live set for op-wise sets --- libyul/backends/evm/SSACFGLiveness.cpp | 53 ++++++++++++----------- libyul/backends/evm/SSACFGLiveness.h | 1 + libyul/backends/evm/SSAControlFlowGraph.h | 14 +++++- 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/libyul/backends/evm/SSACFGLiveness.cpp b/libyul/backends/evm/SSACFGLiveness.cpp index aecaed6ff..a0bfeb5bb 100644 --- a/libyul/backends/evm/SSACFGLiveness.cpp +++ b/libyul/backends/evm/SSACFGLiveness.cpp @@ -37,6 +37,29 @@ constexpr auto literalsFilter(SSACFG const& _cfg) } } +std::set SSACFGLiveness::blockExitValues(SSACFG::BlockId const& _blockId) const +{ + std::set result; + util::GenericVisitor exitVisitor { + [](SSACFG::BasicBlock::MainExit const&) {}, + [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { + result += _functionReturn.returnValues | ranges::views::filter(literalsFilter(m_cfg)); + }, + [&](SSACFG::BasicBlock::JumpTable const& _jt) { + if (literalsFilter(m_cfg)(_jt.value)) + result.emplace(_jt.value); + }, + [](SSACFG::BasicBlock::Jump const&) {}, + [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { + if (literalsFilter(m_cfg)(_conditionalJump.condition)) + result.emplace(_conditionalJump.condition); + }, + [](SSACFG::BasicBlock::Terminated const&) {} + }; + std::visit(exitVisitor, m_cfg.block(_blockId).exit); + return result; +} + SSACFGLiveness::SSACFGLiveness(SSACFG const& _cfg): m_cfg(_cfg), m_topologicalSort(_cfg), @@ -70,12 +93,7 @@ void SSACFGLiveness::runDagDfs() { auto const& info = m_cfg.valueInfo(phi); yulAssert(std::holds_alternative(info), "value info of phi wasn't PhiValue"); - auto const& entries = m_cfg.block(std::get(info).block).entries; - // this is getting the argument index of the phi function corresponding to the path going - // through "blockId", ie, the currently handled block - auto const it = entries.find(blockId); - yulAssert(it != entries.end()); - auto const argIndex = static_cast(std::distance(entries.begin(), it)); + auto const argIndex = m_cfg.phiArgumentIndex(blockId, _successor); yulAssert(argIndex < std::get(info).arguments.size()); auto const arg = std::get(info).arguments.at(argIndex); if (!std::holds_alternative(m_cfg.valueInfo(arg))) @@ -103,23 +121,7 @@ void SSACFGLiveness::runDagDfs() // for each program point p in B, backwards, do: { // add value ids to the live set that are used in exit blocks - util::GenericVisitor exitVisitor { - [](SSACFG::BasicBlock::MainExit const&) {}, - [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { - live += _functionReturn.returnValues | ranges::views::filter(literalsFilter(m_cfg)); - }, - [&](SSACFG::BasicBlock::JumpTable const& _jt) { - if (literalsFilter(m_cfg)(_jt.value)) - live.emplace(_jt.value); - }, - [](SSACFG::BasicBlock::Jump const&) {}, - [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { - if (literalsFilter(m_cfg)(_conditionalJump.condition)) - live.emplace(_conditionalJump.condition); - }, - [](SSACFG::BasicBlock::Terminated const&) {} - }; - std::visit(exitVisitor, block.exit); + live += blockExitValues(blockId); for (auto const& op: block.operations | ranges::views::reverse) { @@ -163,12 +165,13 @@ void SSACFGLiveness::fillOperationsLiveOut() { for (size_t blockIdValue = 0; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) { - auto const& operations = m_cfg.block(SSACFG::BlockId{blockIdValue}).operations; + SSACFG::BlockId const blockId{blockIdValue}; + auto const& operations = m_cfg.block(blockId).operations; auto& liveOuts = m_operationLiveOuts[blockIdValue]; liveOuts.resize(operations.size()); if (!operations.empty()) { - auto live = m_liveOuts[blockIdValue]; + auto live = m_liveOuts[blockIdValue] + blockExitValues(blockId); auto rit = liveOuts.rbegin(); for (auto const& op: operations | ranges::views::reverse) { diff --git a/libyul/backends/evm/SSACFGLiveness.h b/libyul/backends/evm/SSACFGLiveness.h index b0b9ccb7a..6ec0d1688 100644 --- a/libyul/backends/evm/SSACFGLiveness.h +++ b/libyul/backends/evm/SSACFGLiveness.h @@ -47,6 +47,7 @@ class SSACFGLiveness void runDagDfs(); void runLoopTreeDfs(size_t _loopHeader); void fillOperationsLiveOut(); + std::set blockExitValues(SSACFG::BlockId const& _blockId) const; SSACFG const& m_cfg; ForwardSSACFGTopologicalSort m_topologicalSort; diff --git a/libyul/backends/evm/SSAControlFlowGraph.h b/libyul/backends/evm/SSAControlFlowGraph.h index 00f12fc71..9397e0e20 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.h +++ b/libyul/backends/evm/SSAControlFlowGraph.h @@ -76,7 +76,7 @@ class SSACFG langutil::DebugData::ConstPtr debugData; std::reference_wrapper function; std::reference_wrapper call; - bool const canContinue = true; + bool canContinue; }; struct Operation { @@ -162,6 +162,10 @@ class SSACFG }; struct UnreachableValue {}; using ValueInfo = std::variant; + bool isLiteralValue(ValueId const _var) const + { + return std::holds_alternative(valueInfo(_var)); + } ValueInfo& valueInfo(ValueId const _var) { return m_valueInfos.at(_var.value); @@ -208,6 +212,14 @@ class SSACFG return it->second; } + size_t phiArgumentIndex(BlockId const _source, BlockId const _target) const + { + auto const& targetBlock = block(_target); + auto idx = util::findOffset(targetBlock.entries, _source); + yulAssert(idx, fmt::format("Target block {} not found as entry in one of the exits of the current block {}.", _target.value, _source.value)); + return *idx; + } + std::string toDot( bool _includeDiGraphDefinition=true, std::optional _functionIndex=std::nullopt, From f0010d54fdff0aa4d032050273d4570b609b0c60 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:13:13 +0100 Subject: [PATCH 0597/1340] Liveness: Only perform topological sort on nodes reachable from root --- libyul/backends/evm/SSACFGTopologicalSort.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libyul/backends/evm/SSACFGTopologicalSort.cpp b/libyul/backends/evm/SSACFGTopologicalSort.cpp index 5e3e0c0ec..881e48ea1 100644 --- a/libyul/backends/evm/SSACFGTopologicalSort.cpp +++ b/libyul/backends/evm/SSACFGTopologicalSort.cpp @@ -28,11 +28,7 @@ ForwardSSACFGTopologicalSort::ForwardSSACFGTopologicalSort(SSACFG const& _cfg): yulAssert(m_cfg.entry.value == 0); m_preOrder.reserve(m_cfg.numBlocks()); m_postOrder.reserve(m_cfg.numBlocks()); - for (size_t id = 0; id < m_cfg.numBlocks(); ++id) - { - if (!m_explored[id]) - dfs(id); - } + dfs(0); for (auto const& [v1, v2]: m_potentialBackEdges) if (ancestor(v2, v1)) From a3c07eb5d50a7e1b80292e781ab060c33331db2b Mon Sep 17 00:00:00 2001 From: piguagua Date: Wed, 15 Jan 2025 16:08:42 +0800 Subject: [PATCH 0598/1340] chore: remove redundant word Signed-off-by: piguagua --- libyul/AST.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/AST.h b/libyul/AST.h index 6a49db68e..d5988ee05 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -73,7 +73,7 @@ struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; Lite /// External / internal identifier or label reference struct Identifier { langutil::DebugData::ConstPtr debugData; YulName name; }; /// AST Node representing a reference to one of the built-in functions (as defined by the dialect). -/// In the source it's an actual name, while in the AST we only store a handle that can be used to find the the function in the Dialect +/// In the source it's an actual name, while in the AST we only store a handle that can be used to find the function in the Dialect struct BuiltinName { langutil::DebugData::ConstPtr debugData; BuiltinHandle handle; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand /// side and requires x to occupy exactly one stack slot. From 019d9af824ca7de5225fbd83d533d0ab8c99b973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Jan 2025 16:02:56 +0100 Subject: [PATCH 0599/1340] Ask about compilation pipeline in bug template for github issues --- .github/ISSUE_TEMPLATE/bug_report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index ef411e08a..a53f931ca 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -25,6 +25,7 @@ assignees: '' ## Environment - Compiler version: +- Compilation pipeline (legacy, IR, EOF): - Target EVM version (as per compiler settings): - Framework/IDE (e.g. Truffle or Remix): - EVM execution environment / backend / blockchain client: From 124caf8a93fb09c99f635268f7f4592f93713447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Jan 2025 16:03:11 +0100 Subject: [PATCH 0600/1340] Update framework examples in bug template for github issues --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index a53f931ca..b4f42fd52 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -27,7 +27,7 @@ assignees: '' - Compiler version: - Compilation pipeline (legacy, IR, EOF): - Target EVM version (as per compiler settings): -- Framework/IDE (e.g. Truffle or Remix): +- Framework/IDE (e.g. Foundry, Hardhat, Remix): - EVM execution environment / backend / blockchain client: - Operating system: From fcc44851dd1c61e07ad07336719c2d96a84bf0e3 Mon Sep 17 00:00:00 2001 From: chloefeal <188809157+chloefeal@users.noreply.github.com> Date: Thu, 16 Jan 2025 23:32:27 +0800 Subject: [PATCH 0601/1340] Update Changelog.md Signed-off-by: chloefeal <188809157+chloefeal@users.noreply.github.com> --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 521ee8793..cc094ff11 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1440,7 +1440,7 @@ Language Features: * Introduce ``virtual`` and ``override`` keywords. * Modify ``push(element)`` for dynamic storage arrays such that it does not return the new length anymore. * Yul: Introduce ``leave`` statement that exits the current function. - * JSON AST: Add the function selector of each externally-visible FunctonDefinition to the AST JSON export. + * JSON AST: Add the function selector of each externally-visible FunctionDefinition to the AST JSON export. Compiler Features: * Allow revert strings to be stripped from the binary using the ``--revert-strings`` option or the ``settings.debug.revertStrings`` setting. From ac0f8f0a866a200eb2302a5f6bc871360f762f8c Mon Sep 17 00:00:00 2001 From: chloefeal <188809157+chloefeal@users.noreply.github.com> Date: Thu, 16 Jan 2025 23:32:41 +0800 Subject: [PATCH 0602/1340] Update test/libsolidity/util/ContractABIUtils.h Signed-off-by: chloefeal <188809157+chloefeal@users.noreply.github.com> --- test/libsolidity/util/ContractABIUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsolidity/util/ContractABIUtils.h b/test/libsolidity/util/ContractABIUtils.h index 3f0b1b04e..ec41956ae 100644 --- a/test/libsolidity/util/ContractABIUtils.h +++ b/test/libsolidity/util/ContractABIUtils.h @@ -72,7 +72,7 @@ class ContractABIUtils /// Calculates the encoding size of given _parameters based /// on the size of their types. - static size_t encodingSize(ParameterList const& _paremeters); + static size_t encodingSize(ParameterList const& _parameters); private: /// Parses and translates a single type and returns a list of From ded4c981a574c2342785342e12a24fa580809838 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 10 Jan 2025 11:05:48 +0100 Subject: [PATCH 0603/1340] SMTChecker: Fix parsing of array select and store expressions --- Changelog.md | 1 + libsmtutil/CHCSmtLib2Interface.cpp | 10 +++++++++ .../invariants/array_access_2.sol | 22 +++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 test/libsolidity/smtCheckerTests/invariants/array_access_2.sol diff --git a/Changelog.md b/Changelog.md index 521ee8793..e31cc636b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,7 @@ Compiler Features: Bugfixes: * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. * SMTChecker: Fix SMT logic error when initializing a fixed-sized-bytes array using string literals. + * SMTChecker: Fix SMT logic error when translating invariants involving array store and select operations. * Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested. * Yul: Fix internal compiler error when a code generation error should be reported instead. diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index 0bd74a410..f9bb3b8f6 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -355,6 +355,16 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi auto accessor = maybeTupleAccessor.value(); return smtutil::Expression("dt_accessor_" + accessor.first, std::move(arguments), accessor.second); } + if (op == "select") + { + smtSolverInteractionRequire(arguments.size() == 2, "Select has two arguments: array and index"); + return smtutil::Expression::select(arguments[0], arguments[1]); + } + if (op == "store") + { + smtSolverInteractionRequire(arguments.size() == 3, "Store has three arguments: array, index and element"); + return smtutil::Expression::store(arguments[0], arguments[1], arguments[2]); + } else { std::set boolOperators{"and", "or", "not", "=", "<", ">", "<=", ">=", "=>"}; diff --git a/test/libsolidity/smtCheckerTests/invariants/array_access_2.sol b/test/libsolidity/smtCheckerTests/invariants/array_access_2.sol new file mode 100644 index 000000000..891662f65 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/invariants/array_access_2.sol @@ -0,0 +1,22 @@ +contract C { + constructor() { + int8 v; + (v *= v); + } +} + +contract D { + bool[2] internal a; + + function f() internal view { + do {} while(!(a[1])); + } +} +// ==== +// SMTEngine: chc +// SMTIgnoreInv: no +// SMTSolvers: z3 +// SMTTargets: overflow +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1180: Contract invariant(s) for :D:\n(true || true)\nReentrancy property(ies) for :C:\n(( = 0) && (x!5 = x!4))\nReentrancy property(ies) for :D:\n(( = 0) && (x!6 = x!4) && (a' = a))\n = 0 -> no errors\n = 1 -> Overflow at v *= v\n From cdac6a2ac46b4cd43da42f636dcb5ea136a317a9 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Fri, 17 Jan 2025 13:25:35 +0100 Subject: [PATCH 0604/1340] [libyul] Fix false-negative maybe-uninitialized warning on gcc. --- libyul/optimiser/ForLoopConditionIntoBody.cpp | 5 +++-- libyul/optimiser/UnusedPruner.cpp | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index 6324085e6..b3c78129a 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -32,8 +32,9 @@ void ForLoopConditionIntoBody::run(OptimiserStepContext& _context, Block& _ast) void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) { + std::optional booleanNegationFunctionHandle = m_dialect.booleanNegationFunctionHandle(); if ( - m_dialect.booleanNegationFunctionHandle() && + booleanNegationFunctionHandle && !std::holds_alternative(*_forLoop.condition) && !std::holds_alternative(*_forLoop.condition) ) @@ -47,7 +48,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) std::make_unique( FunctionCall { debugData, - BuiltinName{debugData, *m_dialect.booleanNegationFunctionHandle()}, + BuiltinName{debugData, *booleanNegationFunctionHandle}, util::make_vector(std::move(*_forLoop.condition)) } ), diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index 91568f4d6..5d50e4599 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -81,6 +81,7 @@ void UnusedPruner::operator()(Block& _block) [&](NameWithDebugData const& _typedName) { return used(_typedName.name); } )) { + std::optional discardFunctionHandle = m_dialect.discardFunctionHandle(); if (!varDecl.value) statement = Block{std::move(varDecl.debugData), {}}; else if ( @@ -91,10 +92,10 @@ void UnusedPruner::operator()(Block& _block) subtractReferences(ReferencesCounter::countReferences(*varDecl.value)); statement = Block{std::move(varDecl.debugData), {}}; } - else if (varDecl.variables.size() == 1 && m_dialect.discardFunctionHandle()) + else if (varDecl.variables.size() == 1 && discardFunctionHandle) statement = ExpressionStatement{varDecl.debugData, FunctionCall{ varDecl.debugData, - BuiltinName{varDecl.debugData, *m_dialect.discardFunctionHandle()}, + BuiltinName{varDecl.debugData, *discardFunctionHandle}, {*std::move(varDecl.value)} }}; } From 78e267817fc6f3cc85f3702b12e9c1fb28cb06ca Mon Sep 17 00:00:00 2001 From: ericlehong <193237094+ericlehong@users.noreply.github.com> Date: Fri, 17 Jan 2025 23:47:10 +0800 Subject: [PATCH 0605/1340] Update libevmasm/Assembly.cpp Signed-off-by: ericlehong <193237094+ericlehong@users.noreply.github.com> --- libevmasm/Assembly.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 19201545e..22bff5415 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1667,14 +1667,14 @@ LinkerObject const& Assembly::assembleEOF() const for (auto i: referencedSubIds) { - size_t const subAssemblyPostionInParentObject = ret.bytecode.size(); + size_t const subAssemblyPositionInParentObject = ret.bytecode.size(); auto const& subAssemblyLinkerObject = m_subs[i]->assemble(); // Append subassembly bytecode to the parent assembly result bytecode ret.bytecode += subAssemblyLinkerObject.bytecode; // Add subassembly link references to parent linker object. // Offset accordingly to subassembly position in parent object bytecode for (auto const& [subAssemblyLinkRefPosition, linkRef]: subAssemblyLinkerObject.linkReferences) - ret.linkReferences[subAssemblyPostionInParentObject + subAssemblyLinkRefPosition] = linkRef; + ret.linkReferences[subAssemblyPositionInParentObject + subAssemblyLinkRefPosition] = linkRef; } // TODO: Fill functionDebugData for EOF. It probably should be handled for new code section in the loop above. From 76df9809d10d5fb558a2407cf2965dcfa06b46f7 Mon Sep 17 00:00:00 2001 From: dxsullivan <193140725+dxsullivan@users.noreply.github.com> Date: Sat, 18 Jan 2025 09:13:27 +0800 Subject: [PATCH 0606/1340] Fix function name enumerateOptmisationSteps --- test/yulPhaser/Chromosome.cpp | 4 ++-- test/yulPhaser/Population.cpp | 2 +- test/yulPhaser/TestHelpers.cpp | 2 +- test/yulPhaser/TestHelpers.h | 2 +- test/yulPhaser/TestHelpersTest.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/yulPhaser/Chromosome.cpp b/test/yulPhaser/Chromosome.cpp index 881f70007..5503de1bf 100644 --- a/test/yulPhaser/Chromosome.cpp +++ b/test/yulPhaser/Chromosome.cpp @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(makeRandom_should_use_every_possible_step_with_the_same_pro constexpr int samplesPerStep = 500; constexpr double relativeTolerance = 0.02; - std::map stepIndices = enumerateOptmisationSteps(); + std::map stepIndices = enumerateOptimisationSteps(); auto chromosome = Chromosome::makeRandom(stepIndices.size() * samplesPerStep); std::vector samples; @@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE(randomOptimisationStep_should_return_each_step_with_same_pr constexpr int samplesPerStep = 500; constexpr double relativeTolerance = 0.02; - std::map stepIndices = enumerateOptmisationSteps(); + std::map stepIndices = enumerateOptimisationSteps(); std::vector samples; for (size_t i = 0; i <= stepIndices.size() * samplesPerStep; ++i) samples.push_back(stepIndices.at(Chromosome::randomOptimisationStep())); diff --git a/test/yulPhaser/Population.cpp b/test/yulPhaser/Population.cpp index aed014592..dedaa766f 100644 --- a/test/yulPhaser/Population.cpp +++ b/test/yulPhaser/Population.cpp @@ -185,7 +185,7 @@ BOOST_FIXTURE_TEST_CASE(makeRandom_should_return_population_with_random_chromoso constexpr int chromosomeLength = 30; constexpr double relativeTolerance = 0.01; - std::map stepIndices = enumerateOptmisationSteps(); + std::map stepIndices = enumerateOptimisationSteps(); auto population = Population::makeRandom(m_fitnessMetric, populationSize, chromosomeLength, chromosomeLength); std::vector samples; diff --git a/test/yulPhaser/TestHelpers.cpp b/test/yulPhaser/TestHelpers.cpp index d75b63b4a..baf7fb222 100644 --- a/test/yulPhaser/TestHelpers.cpp +++ b/test/yulPhaser/TestHelpers.cpp @@ -53,7 +53,7 @@ std::vector phaser::test::chromosomeLengths(Population const& _populatio return lengths; } -std::map phaser::test::enumerateOptmisationSteps() +std::map phaser::test::enumerateOptimisationSteps() { std::map stepIndices; size_t i = 0; diff --git a/test/yulPhaser/TestHelpers.h b/test/yulPhaser/TestHelpers.h index f9d0afa4c..adfea7946 100644 --- a/test/yulPhaser/TestHelpers.h +++ b/test/yulPhaser/TestHelpers.h @@ -105,7 +105,7 @@ size_t countDifferences(Chromosome const& _chromosome1, Chromosome const& _chrom /// Assigns indices from 0 to N to all optimisation steps available in the OptimiserSuite. /// This is a convenience helper to make it easier to test their distribution with tools made for /// integers. -std::map enumerateOptmisationSteps(); +std::map enumerateOptimisationSteps(); // STRING UTILITIES diff --git a/test/yulPhaser/TestHelpersTest.cpp b/test/yulPhaser/TestHelpersTest.cpp index 23be74230..08a12f9d2 100644 --- a/test/yulPhaser/TestHelpersTest.cpp +++ b/test/yulPhaser/TestHelpersTest.cpp @@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE(countDifferences_should_count_missing_characters_as_differe BOOST_AUTO_TEST_CASE(enumerateOptimisationSteps_should_assing_indices_to_all_available_optimisation_steps) { std::map stepsAndAbbreviations = OptimiserSuite::stepNameToAbbreviationMap(); - std::map stepsAndIndices = enumerateOptmisationSteps(); + std::map stepsAndIndices = enumerateOptimisationSteps(); BOOST_TEST(stepsAndIndices.size() == stepsAndAbbreviations.size()); std::set stepsSoFar; From d750b9dfce17def575a1177845525e26e96a5c67 Mon Sep 17 00:00:00 2001 From: Skylar Ray <137945430+sky-coderay@users.noreply.github.com> Date: Mon, 20 Jan 2025 14:34:00 +0200 Subject: [PATCH 0607/1340] Fix the name of `RETURNCONTRACT` instruction in EOF assembly output (#15729) * Fix RETURNCONTRACT instruction in AssemblyItem.cpp --------- Co-authored-by: r0qs --- libevmasm/AssemblyItem.cpp | 2 +- test/cmdlineTests/strict_asm_eof_container_prague/output | 4 ++-- test/libyul/objectCompiler/eof/creation_with_immutables.yul | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 424b9eeda..3bc7ef704 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -393,7 +393,7 @@ std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const text = "eofcreate{" + std::to_string(static_cast(data())) + "}"; break; case ReturnContract: - text = "returcontract{" + std::to_string(static_cast(data())) + "}"; + text = "returncontract{" + std::to_string(static_cast(data())) + "}"; break; case RelativeJump: text = "rjump{" + std::string("tag_") + std::to_string(relativeJumpTagID()) + "}"; diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/output b/test/cmdlineTests/strict_asm_eof_container_prague/output index 5d134f277..d38adba18 100644 --- a/test/cmdlineTests/strict_asm_eof_container_prague/output +++ b/test/cmdlineTests/strict_asm_eof_container_prague/output @@ -73,7 +73,7 @@ stop sub_0: assembly { 0x00 dup1 - returcontract{0} + returncontract{0} stop sub_0: assembly { @@ -89,7 +89,7 @@ sub_0: assembly { sub_1: assembly { 0x00 dup1 - returcontract{0} + returncontract{0} stop sub_0: assembly { diff --git a/test/libyul/objectCompiler/eof/creation_with_immutables.yul b/test/libyul/objectCompiler/eof/creation_with_immutables.yul index aaffee722..3d5ef85bc 100644 --- a/test/libyul/objectCompiler/eof/creation_with_immutables.yul +++ b/test/libyul/objectCompiler/eof/creation_with_immutables.yul @@ -69,7 +69,7 @@ object "a" { // /* "source":397:398 */ // 0x00 // /* "source":377:403 */ -// returcontract{0} +// returncontract{0} // stop // // sub_0: assembly { From 53899156aa3dacc43fca67b49f594fe169966e1c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 20 Jan 2025 11:52:49 +0100 Subject: [PATCH 0608/1340] ParserBase: avoid copying around currentLiteral --- liblangutil/ParserBase.cpp | 2 +- liblangutil/ParserBase.h | 3 ++- libsolutil/CommonData.h | 2 +- libyul/AsmParser.cpp | 4 ++-- libyul/AsmParser.h | 2 +- libyul/ObjectParser.cpp | 2 +- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/liblangutil/ParserBase.cpp b/liblangutil/ParserBase.cpp index fde0f27ec..00a38727d 100644 --- a/liblangutil/ParserBase.cpp +++ b/liblangutil/ParserBase.cpp @@ -43,7 +43,7 @@ Token ParserBase::peekNextToken() const return m_scanner->peekNextToken(); } -std::string ParserBase::currentLiteral() const +std::string_view ParserBase::currentLiteral() const { return m_scanner->currentLiteral(); } diff --git a/liblangutil/ParserBase.h b/liblangutil/ParserBase.h index 88fc76a9c..cd84da223 100644 --- a/liblangutil/ParserBase.h +++ b/liblangutil/ParserBase.h @@ -71,7 +71,8 @@ class ParserBase Token currentToken() const; Token peekNextToken() const; std::string tokenName(Token _token); - std::string currentLiteral() const; + /// Points to the current literal. The string view invalidates when the parser advances. + std::string_view currentLiteral() const; virtual Token advance(); ///@} diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index 1a5451ef5..b663ede77 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -470,7 +470,7 @@ inline std::string asString(bytesConstRef _b) } /// Converts a string to a byte array containing the string's (byte) data. -inline bytes asBytes(std::string const& _b) +inline bytes asBytes(std::string_view const _b) { return bytes((uint8_t const*)_b.data(), (uint8_t const*)(_b.data() + _b.size())); } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 66ac22a08..8377b8178 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -779,7 +779,7 @@ void Parser::checkBreakContinuePosition(std::string const& _which) } } -bool Parser::isValidNumberLiteral(std::string const& _literal) +bool Parser::isValidNumberLiteral(std::string_view const _literal) { try { @@ -793,7 +793,7 @@ bool Parser::isValidNumberLiteral(std::string const& _literal) if (boost::starts_with(_literal, "0x")) return true; else - return _literal.find_first_not_of("0123456789") == std::string::npos; + return _literal.find_first_not_of("0123456789") == std::string_view::npos; } void Parser::raiseUnsupportedTypesError(SourceLocation const& _location) const diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index b546e179f..75c1cba87 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -152,7 +152,7 @@ class Parser: public langutil::ParserBase /// Reports an error if we are currently not inside the body part of a for loop. void checkBreakContinuePosition(std::string const& _which); - static bool isValidNumberLiteral(std::string const& _literal); + static bool isValidNumberLiteral(std::string_view _literal); private: Dialect const& m_dialect; diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 123dedcb4..954ade311 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -198,7 +198,7 @@ void ObjectParser::parseData(Object& _containingObject) std::string ObjectParser::parseUniqueName(Object const* _containingObject) { expectToken(Token::StringLiteral, false); - auto const name = currentLiteral(); + std::string const name{currentLiteral()}; if (name.empty()) parserError(3287_error, "Object name cannot be empty."); else if (_containingObject && _containingObject->name == name) From 20e30f50da4b0ea013e1bf3db8b3a2cd84effaa8 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 13 Jan 2025 23:52:46 +0100 Subject: [PATCH 0609/1340] Replace base-clang by ossfuzz base-builder --- .../Dockerfile.ubuntu.clang.ossfuzz | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index 743d924d7..f02cce06a 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -21,8 +21,10 @@ # # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ -FROM gcr.io/oss-fuzz-base/base-clang:latest as base -LABEL version="8" +# FIXME: Workaround for Boost 1.83.0 build failure when using Clang 18 (default since https://github.com/google/oss-fuzz/pull/11714) +# See: https://github.com/google/oss-fuzz/blob/5a9322260c4c66e7eb3e5d922b9fee6621ffd8da/projects/solidity/Dockerfile#L17C1-L18C139 +FROM gcr.io/oss-fuzz-base/base-builder@sha256:19782f7fe8092843368894dbc471ce9b30dd6a2813946071a36e8b05f5b1e27e AS base +LABEL version="9" ARG DEBIAN_FRONTEND=noninteractive @@ -44,6 +46,7 @@ RUN apt-get update; \ openjdk-8-jdk \ pkg-config \ python3-pip \ + python3-dev \ software-properties-common \ sudo \ texinfo \ @@ -59,32 +62,25 @@ RUN apt-get update; \ pygments-lexer-solidity \ pylint \ requests \ - tabulate \ - z3-solver; - -# Install cmake 3.21.2 (minimum requirement is cmake 3.10) -RUN wget https://github.com/Kitware/CMake/releases/download/v3.21.2/cmake-3.21.2-Linux-x86_64.sh; \ - test "$(sha256sum cmake-3.21.2-Linux-x86_64.sh)" = "3310362c6fe4d4b2dc00823835f3d4a7171bbd73deb7d059738494761f1c908c cmake-3.21.2-Linux-x86_64.sh"; \ - chmod +x cmake-3.21.2-Linux-x86_64.sh; \ - ./cmake-3.21.2-Linux-x86_64.sh --skip-license --prefix="/usr" + tabulate; FROM base AS libraries # Boost RUN set -ex; \ cd /usr/src; \ - wget -q 'https://archives.boost.io/release/1.74.0/source/boost_1_74_0.tar.bz2' -O boost.tar.bz2; \ - test "$(sha256sum boost.tar.bz2)" = "83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1 boost.tar.bz2" && \ + wget -q 'https://archives.boost.io/release/1.83.0/source/boost_1_83_0.tar.bz2' -O boost.tar.bz2; \ + test "$(sha256sum boost.tar.bz2)" = "6478edfe2f3305127cffe8caf73ea0176c53769f4bf1585be237eb30798c3b8e boost.tar.bz2" && \ tar -xf boost.tar.bz2; \ rm boost.tar.bz2; \ - cd boost_1_74_0; \ - CXXFLAGS="-stdlib=libc++ -pthread" LDFLAGS="-stdlib=libc++" ./bootstrap.sh --with-toolset=clang --prefix=/usr; \ + cd boost_1_83_0; \ + CXXFLAGS="-std=c++17 -stdlib=libc++ -pthread" LDFLAGS="-stdlib=libc++" ./bootstrap.sh --with-toolset=clang --prefix=/usr; \ ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" headers; \ ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" \ link=static variant=release runtime-link=static \ system filesystem unit_test_framework program_options \ install -j $(($(nproc)/2)); \ - rm -rf /usr/src/boost_1_74_0 + rm -rf /usr/src/boost_1_83_0 # Z3 RUN set -ex; \ From aee707e2bf33c54a26efd9f1b61b892ab65e48bf Mon Sep 17 00:00:00 2001 From: r0qs Date: Fri, 17 Jan 2025 14:30:15 +0100 Subject: [PATCH 0610/1340] Bump Z3 and CVC5 --- .../Dockerfile.ubuntu.clang.ossfuzz | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index f02cce06a..7e70bcc22 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -84,21 +84,17 @@ RUN set -ex; \ # Z3 RUN set -ex; \ - git clone --depth 1 -b z3-4.12.1 https://github.com/Z3Prover/z3.git \ - /usr/src/z3; \ - cd /usr/src/z3; \ - mkdir build; \ - cd build; \ - LDFLAGS=$CXXFLAGS cmake -DZ3_BUILD_LIBZ3_SHARED=OFF -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_BUILD_TYPE=Release ..; \ - make libz3 -j; \ - make install; \ - rm -rf /usr/src/z3 + z3_version="4.13.3"; \ + z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ + wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ + test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ + unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ + rm -f /opt/z3.zip; # Eldarica RUN set -ex; \ apt-get update; \ - apt-get install -qy unzip openjdk-11-jre; \ + apt-get install -qqy openjdk-11-jre; \ eldarica_version="2.1"; \ wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ @@ -107,14 +103,12 @@ RUN set -ex; \ # CVC5 RUN set -ex; \ - cvc5_version="1.1.2"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/cvc5-Linux-static.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "cf291aef67da8eaa8d425a51f67f3f72f36db8b1040655dc799b64e3d69e6086 /opt/cvc5.zip"; \ - unzip /opt/cvc5.zip -x "cvc5-Linux-static/lib/cmake/*" -d /opt; \ - mv /opt/cvc5-Linux-static/bin/* /usr/bin; \ - mv /opt/cvc5-Linux-static/include/* /usr/include; \ - mv /opt/cvc5-Linux-static/lib/* /usr/lib; \ - rm -rf /opt/cvc5-Linux-static /opt/cvc5.zip; + cvc5_version="1.2.0"; \ + cvc5_archive_name="cvc5-Linux-x86_64-static"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ + rm -f /opt/cvc5.zip; # OSSFUZZ: libprotobuf-mutator RUN set -ex; \ From 89e9000a37f893919e3e0cf6640bbff258179343 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 20 Jan 2025 13:11:38 +0100 Subject: [PATCH 0611/1340] Convert spaces to tabs --- .../Dockerfile.ubuntu.clang.ossfuzz | 89 +++++++++---------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index 7e70bcc22..1dbf48e9b 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -68,19 +68,19 @@ FROM base AS libraries # Boost RUN set -ex; \ - cd /usr/src; \ - wget -q 'https://archives.boost.io/release/1.83.0/source/boost_1_83_0.tar.bz2' -O boost.tar.bz2; \ - test "$(sha256sum boost.tar.bz2)" = "6478edfe2f3305127cffe8caf73ea0176c53769f4bf1585be237eb30798c3b8e boost.tar.bz2" && \ - tar -xf boost.tar.bz2; \ - rm boost.tar.bz2; \ - cd boost_1_83_0; \ - CXXFLAGS="-std=c++17 -stdlib=libc++ -pthread" LDFLAGS="-stdlib=libc++" ./bootstrap.sh --with-toolset=clang --prefix=/usr; \ - ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" headers; \ - ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" \ - link=static variant=release runtime-link=static \ - system filesystem unit_test_framework program_options \ - install -j $(($(nproc)/2)); \ - rm -rf /usr/src/boost_1_83_0 + cd /usr/src; \ + wget -q 'https://archives.boost.io/release/1.83.0/source/boost_1_83_0.tar.bz2' -O boost.tar.bz2; \ + test "$(sha256sum boost.tar.bz2)" = "6478edfe2f3305127cffe8caf73ea0176c53769f4bf1585be237eb30798c3b8e boost.tar.bz2" && \ + tar -xf boost.tar.bz2; \ + rm boost.tar.bz2; \ + cd boost_1_83_0; \ + CXXFLAGS="-std=c++17 -stdlib=libc++ -pthread" LDFLAGS="-stdlib=libc++" ./bootstrap.sh --with-toolset=clang --prefix=/usr; \ + ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" headers; \ + ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" \ + link=static variant=release runtime-link=static \ + system filesystem unit_test_framework program_options \ + install -j $(($(nproc)/2)); \ + rm -rf /usr/src/boost_1_83_0 # Z3 RUN set -ex; \ @@ -112,15 +112,14 @@ RUN set -ex; \ # OSSFUZZ: libprotobuf-mutator RUN set -ex; \ - git clone https://github.com/google/libprotobuf-mutator.git \ - /usr/src/libprotobuf-mutator; \ + git clone https://github.com/google/libprotobuf-mutator.git /usr/src/libprotobuf-mutator; \ cd /usr/src/libprotobuf-mutator; \ git checkout 3521f47a2828da9ace403e4ecc4aece1a84feb36; \ 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"; \ + -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/; \ @@ -142,37 +141,37 @@ RUN set -ex; \ # gmp RUN set -ex; \ - # Replace system installed libgmp static library - # with sanitized version. Do not perform apt - # remove because it removes mlton as well that - # we need for building libabicoder - cd /usr/src/; \ - git clone --depth 1 --branch gmp-6.2.1 https://github.com/gmp-mirror/gmp-6.2 gmp/; \ - rm -r gmp/.git/; \ - test \ - "$(tar --create gmp/ --sort=name --mtime=1970-01-01Z --owner=0 --group=0 --numeric-owner | sha256sum)" = \ - "d606ff6a4ce98692f9920031e85ea8fcf4a65ce1426f6f0048b8794aefed174b -"; \ - # NOTE: This removes also libgmp.so, which git depends on - rm -f /usr/lib/x86_64-linux-gnu/libgmp.*; \ - rm -f /usr/include/x86_64-linux-gnu/gmp.h; \ - cd gmp/; \ - autoreconf -i; \ - ./configure --prefix=/usr --enable-static=yes --enable-maintainer-mode; \ - make -j; \ - make check; \ - make install; \ - rm -rf /usr/src/gmp/ + # Replace system installed libgmp static library + # with sanitized version. Do not perform apt + # remove because it removes mlton as well that + # we need for building libabicoder + cd /usr/src/; \ + git clone --depth 1 --branch gmp-6.2.1 https://github.com/gmp-mirror/gmp-6.2 gmp/; \ + rm -r gmp/.git/; \ + test \ + "$(tar --create gmp/ --sort=name --mtime=1970-01-01Z --owner=0 --group=0 --numeric-owner | sha256sum)" = \ + "d606ff6a4ce98692f9920031e85ea8fcf4a65ce1426f6f0048b8794aefed174b -"; \ + # NOTE: This removes also libgmp.so, which git depends on + rm -f /usr/lib/x86_64-linux-gnu/libgmp.*; \ + rm -f /usr/include/x86_64-linux-gnu/gmp.h; \ + cd gmp/; \ + autoreconf -i; \ + ./configure --prefix=/usr --enable-static=yes --enable-maintainer-mode; \ + make -j; \ + make check; \ + make install; \ + rm -rf /usr/src/gmp/ # libabicoder RUN set -ex; \ - cd /usr/src; \ - git clone https://github.com/ekpyron/Yul-Isabelle; \ - cd Yul-Isabelle; \ - cd libabicoder; \ - CXX=clang++ CXXFLAGS="-stdlib=libc++ -pthread" make; \ - cp libabicoder.a /usr/lib; \ - cp abicoder.hpp /usr/include; \ - rm -rf /usr/src/Yul-Isabelle + cd /usr/src; \ + git clone https://github.com/ekpyron/Yul-Isabelle; \ + cd Yul-Isabelle; \ + cd libabicoder; \ + CXX=clang++ CXXFLAGS="-stdlib=libc++ -pthread" make; \ + cp libabicoder.a /usr/lib; \ + cp abicoder.hpp /usr/include; \ + rm -rf /usr/src/Yul-Isabelle FROM base COPY --from=libraries /usr/lib /usr/lib From ed71f949c5888a70d5b827b29cbe579c6fa4c4bf Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 14 Jan 2025 18:55:38 +0100 Subject: [PATCH 0612/1340] Bump ossfuzz image --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 18dc57ebd..c24604c84 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,8 +21,8 @@ parameters: default: "solbuildpackpusher/solidity-buildpack-deps@sha256:534c4eea1ba370a85cf3c106b4a30b43152ba4f695fab5e18577009a5e272146" ubuntu-clang-ossfuzz-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-6 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:8883fa2845bbc1e0922af60439313666e4ba325f67a117e17d78cca3ea6589b3" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-9 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c95b24958c92821f1d409b97fcc4930576603063f088a98e780283ee7ec5b575" emscripten-docker-image: type: string # NOTE: Please remember to update the `scripts/build_emscripten.sh` whenever the hash of this image changes. From b683c8e8e12beccfdf7a357cb4cd3009504c4dca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 22 Jan 2025 00:15:53 +0100 Subject: [PATCH 0613/1340] Fix spelling mistakes and silence false-positives newly reported by codespell --- scripts/codespell_ignored_lines.txt | 1 + test/libsolidity/util/SoltestTypes.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/codespell_ignored_lines.txt b/scripts/codespell_ignored_lines.txt index 7ad83795c..fe99c9f24 100644 --- a/scripts/codespell_ignored_lines.txt +++ b/scripts/codespell_ignored_lines.txt @@ -19,3 +19,4 @@ docker run --rm -v "${OUTPUTDIR}":/tmp/output -v "${SCRIPTDIR}":/tmp/scripts:ro templ("assignEnd", "end := tail"); templ("assignEnd", ""); self.assertIn('401 Client Error: Unauthorized', str(manager.exception)) + a = abd; diff --git a/test/libsolidity/util/SoltestTypes.h b/test/libsolidity/util/SoltestTypes.h index 791cea011..4db9bc43b 100644 --- a/test/libsolidity/util/SoltestTypes.h +++ b/test/libsolidity/util/SoltestTypes.h @@ -32,7 +32,7 @@ namespace solidity::frontend::test T(Invalid, "invalid", 0) \ T(EOS, "EOS", 0) \ T(Whitespace, "_", 0) \ - /* punctuations */ \ + /* punctuation */ \ T(LParen, "(", 0) \ T(RParen, ")", 0) \ T(LBrack, "[", 0) \ From 1682f7f8b12562663263e12951100b1561b08ada Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Tue, 21 Jan 2025 17:45:21 +0100 Subject: [PATCH 0614/1340] SMTChecker: Fix encoding of arguments of cryptographic functions For example, the function ecrecover expect an argument of type fixed bytes, but due to implicit conversion, you can also pass a string literal. We previously did not take this into account in the encoding into SMT, which could let to SMT expressions having wrong sorts. --- Changelog.md | 1 + libsolidity/formal/SMTEncoder.cpp | 10 +++++----- .../crypto/crypto_functions_same_string_literal.sol | 12 +++++++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Changelog.md b/Changelog.md index b0539c403..03a3f7e9b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -12,6 +12,7 @@ Bugfixes: * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. * SMTChecker: Fix SMT logic error when initializing a fixed-sized-bytes array using string literals. * SMTChecker: Fix SMT logic error when translating invariants involving array store and select operations. + * SMTChecker: Fix wrong encoding of string literals as arguments of ``ecrecover`` precompile. * Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested. * Yul: Fix internal compiler error when a code generation error should be reported instead. diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 01627007f..6db9420b8 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -851,7 +851,7 @@ void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall) { auto const& funType = dynamic_cast(*_funCall.expression().annotation().type); auto kind = funType.kind(); - auto arg0 = expr(*_funCall.arguments().at(0)); + auto arg0 = expr(*_funCall.arguments().at(0), TypeProvider::bytesStorage()); std::optional result; if (kind == FunctionType::Kind::KECCAK256) result = smtutil::Expression::select(state().cryptoFunction("keccak256"), arg0); @@ -862,10 +862,10 @@ void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall) else if (kind == FunctionType::Kind::ECRecover) { auto e = state().cryptoFunction("ecrecover"); - auto arg0 = expr(*_funCall.arguments().at(0)); - auto arg1 = expr(*_funCall.arguments().at(1)); - auto arg2 = expr(*_funCall.arguments().at(2)); - auto arg3 = expr(*_funCall.arguments().at(3)); + auto arg0 = expr(*_funCall.arguments().at(0), TypeProvider::fixedBytes(32)); + auto arg1 = expr(*_funCall.arguments().at(1), TypeProvider::uint(8)); + auto arg2 = expr(*_funCall.arguments().at(2), TypeProvider::fixedBytes(32)); + auto arg3 = expr(*_funCall.arguments().at(3), TypeProvider::fixedBytes(32)); auto inputSort = dynamic_cast(*e.sort).domain; auto ecrecoverInput = smtutil::Expression::tuple_constructor( smtutil::Expression(std::make_shared(inputSort), ""), diff --git a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol index 9e5123ab5..67e7899db 100644 --- a/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol +++ b/test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol @@ -5,19 +5,25 @@ contract C { assert(k1 == k2); } - function c2() public pure { + function c2() public pure { bytes32 s1 = sha256("10"); bytes32 s2 = sha256("10"); assert(s1 == s2); } - function c3() public pure { + function c3() public pure { bytes32 r1 = ripemd160("100"); bytes32 r2 = ripemd160("100"); assert(r1 == r2); } + + function c4() public pure { + address e1 = ecrecover("a", 1, hex"bb", unicode"c"); + address e2 = ecrecover("a", 1, hex"bb", unicode"c"); + assert(e1 == e2); + } } // ==== // SMTEngine: chc // ---- -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 444103c81957186aeb0410c02cbc81555391b25d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Jan 2025 16:16:20 +0100 Subject: [PATCH 0615/1340] Split function type documentation into smaller sections --- docs/types/value-types.rst | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 9b5ee447e..b91635a19 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -728,7 +728,7 @@ that has the same data representation as the input, whereas ``toUFixed256x18`` r Function Types -------------- -Function types are the types of functions. Variables of function type +Function types are the types of functions. Variables of a function type can be assigned from functions and function parameters of function type can be used to pass functions to and return functions from function calls. Function types come in two flavours - *internal* and *external* functions: @@ -743,6 +743,20 @@ contract internally. External functions consist of an address and a function signature and they can be passed via and returned from external function calls. +Note that public functions of the current contract can be used both as an +internal and as an external function. To use ``f`` as an internal function, +just use ``f``, if you want to use its external form, use ``this.f``. + +If a function type variable is not initialised, calling it results +in a :ref:`Panic error`. The same happens if you call a function after using ``delete`` +on it. + +.. note:: + Lambda or inline functions are planned but not yet supported. + +Declaration syntax +^^^^^^^^^^^^^^^^^^ + Function types are notated as follows: .. code-block:: solidity @@ -759,7 +773,8 @@ omitted. Note that this only applies to function types. Visibility has to be specified explicitly for functions defined in contracts, they do not have a default. -Conversions: +Conversions +^^^^^^^^^^^ A function type ``A`` is implicitly convertible to a function type ``B`` if and only if their parameter types are identical, their return types are identical, @@ -788,18 +803,10 @@ Which makes it possible to assign a ``payable`` function pointer to a ``non-paya function pointer ensuring both types behave the same way, i.e, both cannot be used to send ether. -If a function type variable is not initialised, calling it results -in a :ref:`Panic error`. The same happens if you call a function after using ``delete`` -on it. - If external function types are used outside of the context of Solidity, they are treated as the ``function`` type, which encodes the address followed by the function identifier together in a single ``bytes24`` type. -Note that public functions of the current contract can be used both as an -internal and as an external function. To use ``f`` as an internal function, -just use ``f``, if you want to use its external form, use ``this.f``. - A function of an internal type can be assigned to a variable of an internal function type regardless of where it is defined. This includes private, internal and public functions of both contracts and libraries as well as free @@ -828,7 +835,8 @@ Libraries are excluded because they require a ``delegatecall`` and use :ref:`a d convention for their selectors `. Functions declared in interfaces do not have definitions so pointing at them does not make sense either. -Members: +Members +^^^^^^^ External (or public) functions have the following members: @@ -843,6 +851,9 @@ External (or public) functions have the following members: respectively. See :ref:`External Function Calls ` for more information. +Examples +^^^^^^^^ + Example that shows how to use the members: .. code-block:: solidity @@ -966,6 +977,3 @@ Another example that uses external function types: exchangeRate = response; } } - -.. note:: - Lambda or inline functions are planned but not yet supported. From 3357ca7b89e0ee715da6fe9585d1944b59b80406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Jan 2025 18:29:12 +0100 Subject: [PATCH 0616/1340] Document function type stability across code changes --- docs/control-structures.rst | 2 ++ docs/introduction-to-smart-contracts.rst | 1 + docs/ir-breaking-changes.rst | 2 ++ docs/security-considerations.rst | 10 ++++++ docs/types/value-types.rst | 43 ++++++++++++++++++++++++ 5 files changed, 58 insertions(+) diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 238d26115..1d21a6e26 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -239,6 +239,8 @@ to limit the amount of gas. If the creation fails (due to out-of-stack, not enough balance or other problems), an exception is thrown. +.. _salted-contract-creations: + Salted contract creations / create2 ----------------------------------- diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 45857c3f8..994cb85d4 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -537,6 +537,7 @@ operations, loops should be preferred over recursive calls. Furthermore, only 63/64th of the gas can be forwarded in a message call, which causes a depth limit of a little less than 1000 in practice. +.. _delegatecall: .. index:: delegatecall, library Delegatecall and Libraries diff --git a/docs/ir-breaking-changes.rst b/docs/ir-breaking-changes.rst index 4917cfc71..e76b779aa 100644 --- a/docs/ir-breaking-changes.rst +++ b/docs/ir-breaking-changes.rst @@ -258,6 +258,8 @@ hiding new and different behavior in existing code. Internals ========= +.. _internal-function-pointers-in-ir: + Internal function pointers -------------------------- diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 92d601043..2b8f7f835 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -371,6 +371,16 @@ If your ``mapping`` information must be deleted, consider using a library simila `iterable mapping `_, allowing you to traverse the keys and delete their values in the appropriate ``mapping``. +Internal Function Pointers in Upgradeable Contracts +=================================================== + +Updating the code of your contract may :ref:`invalidate the values of variables of internal function +types`. +Consider such values ephemeral and avoid storing them in state variables. +If you do, you must ensure that they never persist across code updates and are never used by +other contracts having access to the same storage space as a result of a delegatecall or account +abstraction. + Minor Details ============= diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index b91635a19..6155e093b 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -851,6 +851,49 @@ External (or public) functions have the following members: respectively. See :ref:`External Function Calls ` for more information. +.. _function-type-value-stability-across-contract-updates: + +Value stability across contract updates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An important aspect to consider when using values of function types is whether the value will +remain valid if the underlying code changes. + +The state of the blockchain is not completely immutable and there are multiple ways to place +different code under the same address: + +- Directly deploying different code using :ref:`salted contract creation`. +- Delegating to a different contract via :ref:`DELEGATECALL` + (upgradeable code behind a proxy contract is a common example of this). +- Account abstraction as defined by `EIP-7702 `_. + +External function types can be considered as stable as contract's ABI, which makes them very portable. +Their ABI representation always consists of a contract address and a function selector and it is +perfectly safe to store them long-term or pass them between contracts. +While it is possible for the referenced function to change or disappear, a direct external call +would be affected the same way, so there is no additional risk in such use. + +In case of internal functions, however, the value is an identifier that is strongly tied to +contract's bytecode. +The actual representation of the identifier is an implementation detail and may change between +compiler versions or even :ref:`between different backends`. +Values assigned under a given representation are deterministic (i.e. guaranteed to remain the same +as long as the source code is the same) but are easily affected by changes such as adding, removing +or reordering of functions. +The compiler is also free to remove internal functions that are never used, which may affect other identifiers. +Some representations, e.g. one where identifiers are simply jump targets, may be affected by +virtually any change, even one completely unrelated to internal functions. + +To counter this, the language limits the use of internal function types outside of the context in +which they are valid. +This is why internal function types cannot be used as parameters of external functions (or in any +other way that is exposed in contract's ABI). +However, there are still situations where it is up to the user to decide whether their use is safe or not. +For example long-term storage of such values in state variables is discouraged, but may be safe if +the contract code is never going to be updated. +It is also always possible to side-step any safeguards by using inline assembly. +Such use always needs careful consideration. + Examples ^^^^^^^^ From 4b1bf339b2c8da77fb7c1d638c1f6a9db7768877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Jan 2025 18:29:57 +0100 Subject: [PATCH 0617/1340] Document the fact that in IR codegen only explicitly referenced functions are added to internal dispatch --- docs/ir-breaking-changes.rst | 6 ++++++ docs/types/value-types.rst | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/docs/ir-breaking-changes.rst b/docs/ir-breaking-changes.rst index e76b779aa..30c1c6111 100644 --- a/docs/ir-breaking-changes.rst +++ b/docs/ir-breaking-changes.rst @@ -278,6 +278,12 @@ The ID ``0`` is reserved for uninitialized function pointers which then cause a In the old code generator, internal function pointers are initialized with a special function that always causes a panic. This causes a storage write at construction time for internal function pointers in storage. +.. note:: + The compiler is free to omit internal functions that are never explicitly referenced by name. + As a consequence, assigning to a function type variable in inline assembly does not guarantee + that the assigned value will be included in the internal dispatch. + The function must also be explicitly referenced elsewhere in the code. + Cleanup ------- diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 6155e093b..38d22aebd 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -894,6 +894,13 @@ the contract code is never going to be updated. It is also always possible to side-step any safeguards by using inline assembly. Such use always needs careful consideration. +.. note:: + The removal of unused internal functions only takes into account explicit references to + such functions by name. + Implicit references, such as assigning a new value to a function type variable in inline assembly + may still lead to the removal of the function if it is not also referenced explicitly elsewhere + in the source. + Examples ^^^^^^^^ From 314c27b57c31c405c76cea35b626560293940e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 14 Jan 2025 17:31:40 +0100 Subject: [PATCH 0618/1340] Tests for Yul names clashing with builtins and reserved identifiers --- .../clash_with_non_reserved_pure_yul_builtin.sol | 10 ++++++++++ .../clash_with_reserved_builtin.sol | 12 ++++++++++++ .../clash_with_reserved_non_builtin.sol | 15 +++++++++++++++ .../clash_with_reserved_pure_yul_builtin.sol | 15 +++++++++++++++ .../invalid/builtin_name_as_type.yul | 8 ++++++++ .../clash_with_non_reserved_pure_yul_builtin.yul | 8 ++++++++ .../invalid/clash_with_reserved_builtin.yul | 8 ++++++++ .../invalid/clash_with_reserved_non_builtin.yul | 11 +++++++++++ .../clash_with_reserved_pure_yul_builtin.yul | 8 ++++++++ .../invalid/reserved_identifier_as_type.yul | 10 ++++++++++ 10 files changed, 105 insertions(+) create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/clash_with_non_reserved_pure_yul_builtin.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_builtin.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_non_builtin.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_pure_yul_builtin.sol create mode 100644 test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul create mode 100644 test/libyul/yulSyntaxTests/invalid/clash_with_non_reserved_pure_yul_builtin.yul create mode 100644 test/libyul/yulSyntaxTests/invalid/clash_with_reserved_builtin.yul create mode 100644 test/libyul/yulSyntaxTests/invalid/clash_with_reserved_non_builtin.yul create mode 100644 test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul create mode 100644 test/libyul/yulSyntaxTests/invalid/reserved_identifier_as_type.yul diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_non_reserved_pure_yul_builtin.sol b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_non_reserved_pure_yul_builtin.sol new file mode 100644 index 000000000..9b6ee266c --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_non_reserved_pure_yul_builtin.sol @@ -0,0 +1,10 @@ +contract C { + function f() public pure { + // NOTE: memoryguard is a builtin but only in pure Yul, not inline assembly. + // NOTE: memoryguard is not a reserved identifier. + assembly { function memoryguard() {} } + assembly { function f(memoryguard) {} } + assembly { function f() -> memoryguard {} } + assembly { let memoryguard } + } +} diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_builtin.sol b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_builtin.sol new file mode 100644 index 000000000..7a1f6d5e9 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_builtin.sol @@ -0,0 +1,12 @@ +contract C { + function f() public view { + assembly { + // NOTE: All EVM instruction names are reserved identifiers in Yul. + // NOTE: We do provide builtins corresponding to these instructions. + function add(mstore) -> sstore {} + let coinbase + } + } +} +// ---- +// ParserError 5568: (245-248): Cannot use builtin function name "add" as identifier name. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_non_builtin.sol b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_non_builtin.sol new file mode 100644 index 000000000..52f3a4320 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_non_builtin.sol @@ -0,0 +1,15 @@ +contract C { + function f() public pure { + assembly { + // NOTE: All EVM instruction names are reserved identifiers in Yul. + // NOTE: We don't provide builtins corresponding to these instructions. + function dup1(dup2) -> dup3 {} + let dup4 + } + } +} +// ---- +// DeclarationError 5017: (239-269): The identifier "dup1" is reserved and can not be used. +// DeclarationError 5017: (253-257): The identifier "dup2" is reserved and can not be used. +// DeclarationError 5017: (262-266): The identifier "dup3" is reserved and can not be used. +// DeclarationError 5017: (286-290): The identifier "dup4" is reserved and can not be used. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_pure_yul_builtin.sol b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_pure_yul_builtin.sol new file mode 100644 index 000000000..45b9df386 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_pure_yul_builtin.sol @@ -0,0 +1,15 @@ +contract C { + function f() public view { + assembly { + // NOTE: These are builtins but only in pure Yul, not inline assembly. + // NOTE: Names of these builtins are also reserved identifiers. + function loadimmutable(setimmutable) -> datasize {} + let dataoffset + } + } +} +// ---- +// DeclarationError 5017: (234-285): The identifier "loadimmutable" is reserved and can not be used. +// DeclarationError 5017: (257-269): The identifier "setimmutable" is reserved and can not be used. +// DeclarationError 5017: (274-282): The identifier "datasize" is reserved and can not be used. +// DeclarationError 5017: (302-312): The identifier "dataoffset" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul b/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul new file mode 100644 index 000000000..c15247fcd --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul @@ -0,0 +1,8 @@ +{ + let x: datacopy + x := true: loadimmutable + + function f(y: linkersymbol) {} +} +// ---- +// ParserError 5568: (13-21): Cannot use builtin function name "datacopy" as identifier name. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_non_reserved_pure_yul_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_non_reserved_pure_yul_builtin.yul new file mode 100644 index 000000000..daaed0aa3 --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_non_reserved_pure_yul_builtin.yul @@ -0,0 +1,8 @@ +{ + { function memoryguard() {} } + { function f(memoryguard) {} } + { function f() -> memoryguard {} } + { let memoryguard } +} +// ---- +// ParserError 5568: (17-28): Cannot use builtin function name "memoryguard" as identifier name. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_builtin.yul new file mode 100644 index 000000000..52f76c30c --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_builtin.yul @@ -0,0 +1,8 @@ +{ + // NOTE: All EVM instruction names are reserved identifiers in Yul. + // NOTE: We do provide builtins corresponding to these instructions. + function add(mstore) -> sstore {} + let coinbase +} +// ---- +// ParserError 5568: (160-163): Cannot use builtin function name "add" as identifier name. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_non_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_non_builtin.yul new file mode 100644 index 000000000..bf7ad840c --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_non_builtin.yul @@ -0,0 +1,11 @@ +{ + // NOTE: All EVM instruction names are reserved identifiers in Yul. + // NOTE: We don't provide builtins corresponding to these instructions. + function dup1(dup2) -> dup3 {} + let dup4 +} +// ---- +// DeclarationError 5017: (154-184): The identifier "dup1" is reserved and can not be used. +// DeclarationError 5017: (168-172): The identifier "dup2" is reserved and can not be used. +// DeclarationError 5017: (177-181): The identifier "dup3" is reserved and can not be used. +// DeclarationError 5017: (193-197): The identifier "dup4" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul new file mode 100644 index 000000000..0bc282fe3 --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul @@ -0,0 +1,8 @@ +{ + // NOTE: These are builtins but only in pure Yul, not inline assembly. + // NOTE: Names of these builtins are also reserved identifiers. + function loadimmutable(setimmutable) -> datasize {} + let dataoffset +} +// ---- +// ParserError 5568: (158-171): Cannot use builtin function name "loadimmutable" as identifier name. diff --git a/test/libyul/yulSyntaxTests/invalid/reserved_identifier_as_type.yul b/test/libyul/yulSyntaxTests/invalid/reserved_identifier_as_type.yul new file mode 100644 index 000000000..df46d16b5 --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/reserved_identifier_as_type.yul @@ -0,0 +1,10 @@ +{ + let x: jump + x := true: dup12 + + function f(y: jumpi) {} +} +// ---- +// ParserError 5473: (10-17): Types are not supported in untyped Yul. +// ParserError 5473: (27-38): Types are not supported in untyped Yul. +// ParserError 5473: (55-63): Types are not supported in untyped Yul. From edb6783e43f710cda94b26186c77047add14ca72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 14 Jan 2025 17:18:06 +0100 Subject: [PATCH 0619/1340] Make name clash with a Yul builtin a non-fatal error --- Changelog.md | 1 + libyul/AsmParser.cpp | 8 +++++++- .../inlineAssembly/basefee_reserved_london.sol | 1 + .../inlineAssembly/blobbasefee_reserved_cancun.sol | 1 + .../inlineAssembly/clash_with_reserved_builtin.sol | 3 +++ .../difficulty_disallowed_function_pre_paris.sol | 1 + .../syntaxTests/inlineAssembly/mcopy_reserved_cancun.sol | 1 + .../prevrandao_disallowed_function_post_paris.sol | 1 + .../syntaxTests/inlineAssembly/tload_reserved_cancun.sol | 1 + .../syntaxTests/inlineAssembly/tstore_reserved_cancun.sol | 1 + test/libyul/yulSyntaxTests/blobhash.yul | 1 + .../libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul | 1 - .../eof/extdelegatecall_function_in_eof.yul | 1 - .../yulSyntaxTests/eof/extstaticcall_function_in_eof.yul | 1 - .../yulSyntaxTests/invalid/builtin_name_as_type.yul | 5 +++++ .../invalid/clash_with_non_reserved_pure_yul_builtin.yul | 3 +++ .../invalid/clash_with_reserved_builtin.yul | 3 +++ .../invalid/clash_with_reserved_pure_yul_builtin.yul | 3 +++ test/libyul/yulSyntaxTests/mcopy_as_identifier.yul | 1 + 19 files changed, 34 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index 03a3f7e9b..c00adf0fd 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Language Features: Compiler Features: * Error Reporting: Errors reported during code generation now point at the location of the contract when more fine-grained location is not available. * SMTChecker: Z3 is now a runtime dependency, not a build dependency (except for emscripten build). + * Yul Parser: Make name clash with a builtin a non-fatal error. Bugfixes: diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 66ac22a08..8d8e91e5c 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -755,7 +755,13 @@ YulName Parser::expectAsmIdentifier() { YulName name{currentLiteral()}; if (currentToken() == Token::Identifier && m_dialect.findBuiltin(name.str())) - fatalParserError(5568_error, "Cannot use builtin function name \"" + name.str() + "\" as identifier name."); + // Non-fatal. We'll continue and wrongly parse it as an identifier. May lead to some spurious + // errors after this point, but likely also much more useful ones. + m_errorReporter.parserError( + 5568_error, + currentLocation(), + "Cannot use builtin function name \"" + name.str() + "\" as identifier name." + ); // NOTE: We keep the expectation here to ensure the correct source location for the error above. expectToken(Token::Identifier); return name; diff --git a/test/libsolidity/syntaxTests/inlineAssembly/basefee_reserved_london.sol b/test/libsolidity/syntaxTests/inlineAssembly/basefee_reserved_london.sol index 00ecaf01a..1235dd547 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/basefee_reserved_london.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/basefee_reserved_london.sol @@ -10,3 +10,4 @@ contract C { // EVMVersion: =london // ---- // ParserError 5568: (98-105): Cannot use builtin function name "basefee" as identifier name. +// ParserError 7104: (137-144): Builtin function "basefee" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/blobbasefee_reserved_cancun.sol b/test/libsolidity/syntaxTests/inlineAssembly/blobbasefee_reserved_cancun.sol index 0bab7e36c..4e81c4865 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/blobbasefee_reserved_cancun.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/blobbasefee_reserved_cancun.sol @@ -10,3 +10,4 @@ contract C { // EVMVersion: >=cancun // ---- // ParserError 5568: (98-109): Cannot use builtin function name "blobbasefee" as identifier name. +// ParserError 7104: (141-152): Builtin function "blobbasefee" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_builtin.sol b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_builtin.sol index 7a1f6d5e9..9dbf877d6 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_builtin.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_reserved_builtin.sol @@ -10,3 +10,6 @@ contract C { } // ---- // ParserError 5568: (245-248): Cannot use builtin function name "add" as identifier name. +// ParserError 5568: (249-255): Cannot use builtin function name "mstore" as identifier name. +// ParserError 5568: (260-266): Cannot use builtin function name "sstore" as identifier name. +// ParserError 5568: (286-294): Cannot use builtin function name "coinbase" as identifier name. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/difficulty_disallowed_function_pre_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_disallowed_function_pre_paris.sol index a177e8f63..d55935aad 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/difficulty_disallowed_function_pre_paris.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_disallowed_function_pre_paris.sol @@ -19,3 +19,4 @@ contract C { // EVMVersion: =cancun // ---- // ParserError 5568: (101-106): Cannot use builtin function name "mcopy" as identifier name. +// ParserError 7104: (134-139): Builtin function "mcopy" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol index 6c284a005..7924f52e2 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_disallowed_function_post_paris.sol @@ -19,3 +19,4 @@ contract C { // EVMVersion: >=paris // ---- // ParserError 5568: (101-111): Cannot use builtin function name "prevrandao" as identifier name. +// ParserError 7104: (143-153): Builtin function "prevrandao" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/tload_reserved_cancun.sol b/test/libsolidity/syntaxTests/inlineAssembly/tload_reserved_cancun.sol index 77c988577..b8c09fd59 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/tload_reserved_cancun.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/tload_reserved_cancun.sol @@ -10,3 +10,4 @@ contract C { // EVMVersion: >=cancun // ---- // ParserError 5568: (98-103): Cannot use builtin function name "tload" as identifier name. +// ParserError 7104: (135-140): Builtin function "tload" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/tstore_reserved_cancun.sol b/test/libsolidity/syntaxTests/inlineAssembly/tstore_reserved_cancun.sol index 9f08d985a..9944c84f5 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/tstore_reserved_cancun.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/tstore_reserved_cancun.sol @@ -10,3 +10,4 @@ contract C { // EVMVersion: >=cancun // ---- // ParserError 5568: (98-104): Cannot use builtin function name "tstore" as identifier name. +// ParserError 7104: (136-142): Builtin function "tstore" must be called. diff --git a/test/libyul/yulSyntaxTests/blobhash.yul b/test/libyul/yulSyntaxTests/blobhash.yul index 6337f22c1..272ec13d7 100644 --- a/test/libyul/yulSyntaxTests/blobhash.yul +++ b/test/libyul/yulSyntaxTests/blobhash.yul @@ -13,3 +13,4 @@ // EVMVersion: >=cancun // ---- // ParserError 5568: (20-28): Cannot use builtin function name "blobhash" as identifier name. +// ParserError 5568: (64-72): Cannot use builtin function name "blobhash" as identifier name. diff --git a/test/libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul b/test/libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul index 1e503ca94..021c98dd3 100644 --- a/test/libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul +++ b/test/libyul/yulSyntaxTests/eof/extcall_function_in_eof.yul @@ -8,4 +8,3 @@ object "a" { // bytecodeFormat: >=EOFv1 // ---- // ParserError 5568: (41-48): Cannot use builtin function name "extcall" as identifier name. -// ParserError 8143: (41-48): Expected keyword "data" or "object" or "}". diff --git a/test/libyul/yulSyntaxTests/eof/extdelegatecall_function_in_eof.yul b/test/libyul/yulSyntaxTests/eof/extdelegatecall_function_in_eof.yul index 0515c8d26..e352f1b3a 100644 --- a/test/libyul/yulSyntaxTests/eof/extdelegatecall_function_in_eof.yul +++ b/test/libyul/yulSyntaxTests/eof/extdelegatecall_function_in_eof.yul @@ -8,4 +8,3 @@ object "a" { // bytecodeFormat: >=EOFv1 // ---- // ParserError 5568: (41-56): Cannot use builtin function name "extdelegatecall" as identifier name. -// ParserError 8143: (41-56): Expected keyword "data" or "object" or "}". diff --git a/test/libyul/yulSyntaxTests/eof/extstaticcall_function_in_eof.yul b/test/libyul/yulSyntaxTests/eof/extstaticcall_function_in_eof.yul index fbfb5074b..0db2313a0 100644 --- a/test/libyul/yulSyntaxTests/eof/extstaticcall_function_in_eof.yul +++ b/test/libyul/yulSyntaxTests/eof/extstaticcall_function_in_eof.yul @@ -8,4 +8,3 @@ object "a" { // bytecodeFormat: >=EOFv1 // ---- // ParserError 5568: (41-54): Cannot use builtin function name "extstaticcall" as identifier name. -// ParserError 8143: (41-54): Expected keyword "data" or "object" or "}". diff --git a/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul b/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul index c15247fcd..b9b3346f4 100644 --- a/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul +++ b/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul @@ -6,3 +6,8 @@ } // ---- // ParserError 5568: (13-21): Cannot use builtin function name "datacopy" as identifier name. +// ParserError 5473: (10-21): Types are not supported in untyped Yul. +// ParserError 5568: (37-50): Cannot use builtin function name "loadimmutable" as identifier name. +// ParserError 5473: (31-50): Types are not supported in untyped Yul. +// ParserError 5568: (70-82): Cannot use builtin function name "linkersymbol" as identifier name. +// ParserError 5473: (67-82): Types are not supported in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_non_reserved_pure_yul_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_non_reserved_pure_yul_builtin.yul index daaed0aa3..6f5824423 100644 --- a/test/libyul/yulSyntaxTests/invalid/clash_with_non_reserved_pure_yul_builtin.yul +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_non_reserved_pure_yul_builtin.yul @@ -6,3 +6,6 @@ } // ---- // ParserError 5568: (17-28): Cannot use builtin function name "memoryguard" as identifier name. +// ParserError 5568: (53-64): Cannot use builtin function name "memoryguard" as identifier name. +// ParserError 5568: (93-104): Cannot use builtin function name "memoryguard" as identifier name. +// ParserError 5568: (120-131): Cannot use builtin function name "memoryguard" as identifier name. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_builtin.yul index 52f76c30c..f146f06ae 100644 --- a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_builtin.yul +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_builtin.yul @@ -6,3 +6,6 @@ } // ---- // ParserError 5568: (160-163): Cannot use builtin function name "add" as identifier name. +// ParserError 5568: (164-170): Cannot use builtin function name "mstore" as identifier name. +// ParserError 5568: (175-181): Cannot use builtin function name "sstore" as identifier name. +// ParserError 5568: (193-201): Cannot use builtin function name "coinbase" as identifier name. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul index 0bc282fe3..035efbacc 100644 --- a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul @@ -6,3 +6,6 @@ } // ---- // ParserError 5568: (158-171): Cannot use builtin function name "loadimmutable" as identifier name. +// ParserError 5568: (172-184): Cannot use builtin function name "setimmutable" as identifier name. +// ParserError 5568: (189-197): Cannot use builtin function name "datasize" as identifier name. +// ParserError 5568: (209-219): Cannot use builtin function name "dataoffset" as identifier name. diff --git a/test/libyul/yulSyntaxTests/mcopy_as_identifier.yul b/test/libyul/yulSyntaxTests/mcopy_as_identifier.yul index e48c27d06..be00e0a35 100644 --- a/test/libyul/yulSyntaxTests/mcopy_as_identifier.yul +++ b/test/libyul/yulSyntaxTests/mcopy_as_identifier.yul @@ -12,3 +12,4 @@ // EVMVersion: >=cancun // ---- // ParserError 5568: (20-25): Cannot use builtin function name "mcopy" as identifier name. +// ParserError 5568: (61-66): Cannot use builtin function name "mcopy" as identifier name. From 09db0cc5f9b3365e977b9b44288f36eeffe4e6df Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Jan 2025 16:41:32 +0100 Subject: [PATCH 0620/1340] Add Ubuntu 22.04 image --- .github/workflows/buildpack-deps.yml | 3 +- scripts/ci/buildpack-deps_test_ubuntu2204.sh | 1 + .../buildpack-deps/Dockerfile.ubuntu2204 | 108 ++++++++++++++++++ 3 files changed, 111 insertions(+), 1 deletion(-) create mode 120000 scripts/ci/buildpack-deps_test_ubuntu2204.sh create mode 100644 scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index fe6da11e1..ad2e58270 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -7,6 +7,7 @@ on: - 'scripts/docker/buildpack-deps/Dockerfile.emscripten' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2004' + - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2204' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang' @@ -23,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2404, ubuntu2404.clang] + image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2204, ubuntu2404, ubuntu2404.clang] steps: - uses: actions/checkout@v4 diff --git a/scripts/ci/buildpack-deps_test_ubuntu2204.sh b/scripts/ci/buildpack-deps_test_ubuntu2204.sh new file mode 120000 index 000000000..c07a74de4 --- /dev/null +++ b/scripts/ci/buildpack-deps_test_ubuntu2204.sh @@ -0,0 +1 @@ +build.sh \ No newline at end of file diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 new file mode 100644 index 000000000..9b365a374 --- /dev/null +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -0,0 +1,108 @@ +# vim:syntax=dockerfile +#------------------------------------------------------------------------------ +# Dockerfile for building and testing Solidity Compiler on CI +# Target: Ubuntu 22.04 (Jammy Jellyfish) +# 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 +# +# (c) 2016-2025 solidity contributors. +#------------------------------------------------------------------------------ +FROM buildpack-deps:jammy AS base +LABEL version="1" + +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 \ + cmake \ + jq \ + clang \ + libboost-filesystem-dev \ + libboost-program-options-dev \ + libboost-system-dev \ + libboost-test-dev \ + libcln-dev \ + locales-all \ + lsof \ + ninja-build \ + python3-pip \ + python3-sphinx \ + software-properties-common \ + sudo \ + unzip \ + zip; \ + pip3 install \ + codecov \ + colorama \ + deepdiff \ + parsec \ + pygments-lexer-solidity \ + pylint \ + requests \ + tabulate \ + z3-solver; + +# Eldarica +RUN set -ex; \ + apt-get update; \ + apt-get install -qqy \ + openjdk-11-jre; \ + eldarica_version="2.1"; \ + wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ + test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ + unzip /opt/eld_binaries.zip -d /opt; \ + rm -f /opt/eld_binaries.zip; + +# CVC5 +RUN set -ex; \ + cvc5_version="1.2.0"; \ + cvc5_archive_name="cvc5-Linux-x86_64-static"; \ + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ + rm -f /opt/cvc5.zip; + +# Z3 +RUN set -ex; \ + z3_version="4.13.3"; \ + z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ + wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ + test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ + unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ + rm -f /opt/z3.zip; + +FROM base AS libraries + +# EVMONE +RUN set -ex; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + cd /usr; \ + tar -xf /usr/src/evmone.tar.gz; \ + rm -rf /usr/src/evmone.tar.gz + +FROM base +COPY --from=libraries /usr/lib /usr/lib +COPY --from=libraries /usr/bin /usr/bin +COPY --from=libraries /usr/include /usr/include +COPY --from=libraries /opt/eldarica /opt/eldarica +ENV PATH="$PATH:/opt/eldarica" From 0ea9a40b82cd7ecad8f5d0fa44aa6f3d0206be9f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Jan 2025 18:14:17 +0100 Subject: [PATCH 0621/1340] ci: add build jobs that run on ubuntu 2204 --- .circleci/config.yml | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index c24604c84..be04d2a6f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,6 +11,10 @@ parameters: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-26 default: "solbuildpackpusher/solidity-buildpack-deps@sha256:1f387a77be889f65a2a25986a5c5eccc88cec23fabe6aeaf351790751145c81e" + ubuntu-2204-docker-image: + type: string + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-1 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:d61b0a4a49ac106e6747c1e8037882f1d421b537dba6c96c0a400ca105d85d4d" ubuntu-2404-docker-image: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-2 @@ -551,6 +555,42 @@ defaults: MAKEFLAGS: -j 10 CPUs: 10 + - base_ubuntu2204: &base_ubuntu2204 + docker: + - image: << pipeline.parameters.ubuntu-2204-docker-image >> + environment: &base_ubuntu2204_env + TERM: xterm + CC: gcc + CXX: g++ + MAKEFLAGS: -j 3 + CPUs: 3 + + - base_ubuntu2204_large: &base_ubuntu2204_large + <<: *base_ubuntu2204 + resource_class: large + environment: &base_ubuntu2204_large_env + <<: *base_ubuntu2204_env + MAKEFLAGS: -j 5 + CPUs: 5 + + - base_ubuntu2204_clang: &base_ubuntu2204_clang + docker: + - image: << pipeline.parameters.ubuntu-2204-docker-image >> + environment: &base_ubuntu2204_clang_env + TERM: xterm + CC: clang + CXX: clang++ + MAKEFLAGS: -j 3 + CPUs: 3 + + - base_ubuntu2204_clang_large: &base_ubuntu2204_clang_large + <<: *base_ubuntu2204_clang + resource_class: large + environment: &base_ubuntu2204_clang_large_env + <<: *base_ubuntu2204_clang_env + MAKEFLAGS: -j 5 + CPUs: 5 + - base_ubuntu2404: &base_ubuntu2404 docker: - image: << pipeline.parameters.ubuntu-2404-docker-image >> @@ -1068,6 +1108,23 @@ jobs: - run_build - matrix_notify_failure_unless_pr + b_ubu_2204: + <<: *base_ubuntu2204_large + steps: + - checkout + - run_build + - matrix_notify_failure_unless_pr + + b_ubu_2204_clang: + <<: *base_ubuntu2204_clang_large + environment: + <<: *base_ubuntu2204_clang_large_env + MAKEFLAGS: -j 10 + steps: + - checkout + - run_build + - matrix_notify_failure_unless_pr + b_ubu_ossfuzz: &b_ubu_ossfuzz <<: *base_ubuntu_clang_large steps: @@ -1818,6 +1875,8 @@ workflows: - b_docs: *requires_nothing - b_ubu_cxx20: *requires_nothing - b_ubu_ossfuzz: *requires_nothing + - b_ubu_2204: *requires_nothing + - b_ubu_2204_clang: *requires_nothing # OS/X build and tests - b_osx: *requires_nothing From f499283a94a5fc8063b6586532c7cb2dd3972557 Mon Sep 17 00:00:00 2001 From: planetBoy <140164174+Guayaba221@users.noreply.github.com> Date: Wed, 22 Jan 2025 19:45:43 +0100 Subject: [PATCH 0622/1340] Update buildinfo.cmake --- cmake/scripts/buildinfo.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/scripts/buildinfo.cmake b/cmake/scripts/buildinfo.cmake index 3fb6beb2b..a4e40e87b 100644 --- a/cmake/scripts/buildinfo.cmake +++ b/cmake/scripts/buildinfo.cmake @@ -61,7 +61,7 @@ if (SOL_COMMIT_HASH AND SOL_LOCAL_CHANGES) endif() set(SOL_VERSION_COMMIT "commit.${SOL_COMMIT_HASH}") -set(SOl_VERSION_PLATFORM ETH_BUILD_PLATFORM) +set(SOL_VERSION_PLATFORM ETH_BUILD_PLATFORM) set(SOL_VERSION_BUILDINFO "commit.${SOL_COMMIT_HASH}.${ETH_BUILD_PLATFORM}") set(TMPFILE "${ETH_DST_DIR}/BuildInfo.h.tmp") From 887947bccc1e289f017f754fe41417dca8a897a8 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 23 Jan 2025 11:53:12 +0100 Subject: [PATCH 0623/1340] eof: Fix error message wording. --- libyul/AsmAnalysis.cpp | 2 +- .../eof/extcalls_invalid_in_legacy.yul | 23 ++++++++----------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index fd826eaec..2d0eeae2b 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -783,7 +783,7 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio 4328_error, _location, fmt::format( - "The \"{}\" instruction is only available on EOF.", + "The \"{}\" instruction is only available in EOF.", fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name)) ) ); diff --git a/test/libyul/yulSyntaxTests/eof/extcalls_invalid_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/extcalls_invalid_in_legacy.yul index 6aec96aa2..1a6781802 100644 --- a/test/libyul/yulSyntaxTests/eof/extcalls_invalid_in_legacy.yul +++ b/test/libyul/yulSyntaxTests/eof/extcalls_invalid_in_legacy.yul @@ -1,17 +1,14 @@ -object "a" { - code { - pop(extcall(address(), 0, 0, 0)) - pop(extdelegatecall(address(), 0, 0)) - pop(extstaticcall(address(), 0, 0)) - } +{ + pop(extcall(address(), 0, 0, 0)) + pop(extdelegatecall(address(), 0, 0)) + pop(extstaticcall(address(), 0, 0)) } - // ==== // bytecodeFormat: legacy // ---- -// TypeError 4328: (36-43): The "extcall" instruction is only available on EOF. -// TypeError 3950: (36-63): Expected expression to evaluate to one value, but got 0 values instead. -// TypeError 4328: (77-92): The "extdelegatecall" instruction is only available on EOF. -// TypeError 3950: (77-109): Expected expression to evaluate to one value, but got 0 values instead. -// TypeError 4328: (123-136): The "extstaticcall" instruction is only available on EOF. -// TypeError 3950: (123-153): Expected expression to evaluate to one value, but got 0 values instead. +// TypeError 4328: (10-17): The "extcall" instruction is only available in EOF. +// TypeError 3950: (10-37): Expected expression to evaluate to one value, but got 0 values instead. +// TypeError 4328: (47-62): The "extdelegatecall" instruction is only available in EOF. +// TypeError 3950: (47-79): Expected expression to evaluate to one value, but got 0 values instead. +// TypeError 4328: (89-102): The "extstaticcall" instruction is only available in EOF. +// TypeError 3950: (89-119): Expected expression to evaluate to one value, but got 0 values instead. From b202600e4cfca885ed7adb13f2d1e3631122286b Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 23 Jan 2025 11:53:12 +0100 Subject: [PATCH 0624/1340] eof: Fix unintentionally reserved EOF identifiers in legacy --- libyul/backends/evm/EVMDialect.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index bb7a96953..74599eb1c 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -155,14 +155,13 @@ std::set> createReservedIdentifiers(langutil::EVMVersio auto eofIdentifiersException = [&](evmasm::Instruction _instr) -> bool { - solAssert(!_eofVersion.has_value() || _evmVersion >= langutil::EVMVersion::prague()); - return - !_eofVersion.has_value() && - ( - _instr == evmasm::Instruction::EXTCALL || - _instr == evmasm::Instruction::EXTSTATICCALL || - _instr == evmasm::Instruction::EXTDELEGATECALL - ); + solAssert(!_eofVersion.has_value() || (*_eofVersion == 1 && _evmVersion == langutil::EVMVersion::prague())); + if (_eofVersion.has_value()) + // For EOF every instruction is reserved identifier. + return false; + else + return langutil::EVMVersion::prague().hasOpcode(_instr, 1) && + !langutil::EVMVersion::prague().hasOpcode(_instr, std::nullopt); }; std::set> reserved; From 4436907ea8baa265a99d0ec025d6b25851c1ae1a Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 23 Jan 2025 11:53:12 +0100 Subject: [PATCH 0625/1340] eof: Add better message when EOF builtin used in legcy --- libyul/AsmAnalysis.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 2d0eeae2b..69f2e765e 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -695,11 +695,28 @@ bool AsmAnalyzer::validateInstructions(std::string_view _instructionIdentifier, if (builtinHandle && defaultEVMDialect.builtin(*builtinHandle).instruction.has_value()) return validateInstructions(*defaultEVMDialect.builtin(*builtinHandle).instruction, _location); + solAssert(!m_eofVersion.has_value() || (*m_eofVersion == 1 && m_evmVersion == langutil::EVMVersion::prague())); // TODO: Change `prague()` to `EVMVersion{}` once EOF gets deployed auto const& eofDialect = EVMDialect::strictAssemblyForEVM(EVMVersion::prague(), 1); auto const eofBuiltinHandle = eofDialect.findBuiltin(_instructionIdentifier); - if (eofBuiltinHandle && eofDialect.builtin(*eofBuiltinHandle).instruction.has_value()) - return validateInstructions(*eofDialect.builtin(*eofBuiltinHandle).instruction, _location); + if (eofBuiltinHandle) + { + auto const builtin = eofDialect.builtin(*eofBuiltinHandle); + if (builtin.instruction.has_value()) + return validateInstructions(*builtin.instruction, _location); + else if (!m_eofVersion.has_value()) + { + m_errorReporter.declarationError( + 7223_error, + _location, + fmt::format( + "Builtin function \"{}\" is only available in EOF.", + fmt::arg("function", _instructionIdentifier) + ) + ); + return true; + } + } return false; } @@ -716,8 +733,16 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio yulAssert( _instr != evmasm::Instruction::JUMP && _instr != evmasm::Instruction::JUMPI && - _instr != evmasm::Instruction::JUMPDEST, - ""); + _instr != evmasm::Instruction::JUMPDEST && + _instr != evmasm::Instruction::DATALOADN && + _instr != evmasm::Instruction::EOFCREATE && + _instr != evmasm::Instruction::RETURNCONTRACT && + _instr != evmasm::Instruction::RJUMP && + _instr != evmasm::Instruction::RJUMPI && + _instr != evmasm::Instruction::CALLF && + _instr != evmasm::Instruction::JUMPF && + _instr != evmasm::Instruction::RETF + ); auto errorForVM = [&](ErrorId _errorId, std::string const& vmKindMessage) { m_errorReporter.typeError( From 9032d580e65b42d6053a25d7b8e555fea37bfd9c Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 23 Jan 2025 11:53:12 +0100 Subject: [PATCH 0626/1340] eof: Add tests --- .../eof/auxdataloadn_in_legacy.yul | 4 +-- .../eof/eof_identifiers_in_legacy.yul | 10 ------- .../eof_identifiers_not_defined_in_legacy.yul | 29 +++++++++++++++++++ ...eof_identifiers_not_reserved_in_legacy.yul | 16 ++++++++++ .../eof/eof_names_reserved_in_eof.yul | 17 +++++++++++ ...of_opcodes_identifiers_reserved_in_eof.yul | 17 +++++++++++ 6 files changed, 81 insertions(+), 12 deletions(-) delete mode 100644 test/libyul/yulSyntaxTests/eof/eof_identifiers_in_legacy.yul create mode 100644 test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul create mode 100644 test/libyul/yulSyntaxTests/eof/eof_identifiers_not_reserved_in_legacy.yul create mode 100644 test/libyul/yulSyntaxTests/eof/eof_names_reserved_in_eof.yul create mode 100644 test/libyul/yulSyntaxTests/eof/eof_opcodes_identifiers_reserved_in_eof.yul diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul index 0fe3221f1..47986059e 100644 --- a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul @@ -11,5 +11,5 @@ object "a" { // EVMVersion: >=prague // bytecodeFormat: legacy // ---- -// DeclarationError 4619: (42-54): Function "auxdataloadn" not found. -// TypeError 3950: (42-57): Expected expression to evaluate to one value, but got 0 values instead. \ No newline at end of file +// DeclarationError 7223: (42-54): Builtin function "auxdataloadn" is only available in EOF. +// TypeError 3950: (42-57): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libyul/yulSyntaxTests/eof/eof_identifiers_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/eof_identifiers_in_legacy.yul deleted file mode 100644 index d9d7fde15..000000000 --- a/test/libyul/yulSyntaxTests/eof/eof_identifiers_in_legacy.yul +++ /dev/null @@ -1,10 +0,0 @@ -object "a" { - code { - function extcall() {} - function extstaticcall() {} - function extdelegatecall() {} - } -} - -// ==== -// bytecodeFormat: legacy \ No newline at end of file diff --git a/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul new file mode 100644 index 000000000..ab55fb21d --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul @@ -0,0 +1,29 @@ +{ + auxdataloadn(0) + dataloadn(0) + eofcreate("name", 0, 0, 0, 0) + returncontract("name", 0, 0) + rjump() + rjumpi() + callf(0) + jumpf(0) + retf() + extcall(0, 1, 2, 3) + extstaticcall(0, 1, 2) + extdelegatecall(0, 1, 2) +} +// ==== +// bytecodeFormat: legacy +// ---- +// DeclarationError 7223: (6-18): Builtin function "auxdataloadn" is only available in EOF. +// DeclarationError 4619: (26-35): Function "dataloadn" not found. +// DeclarationError 7223: (43-52): Builtin function "eofcreate" is only available in EOF. +// DeclarationError 4619: (77-91): Function "returncontract" not found. +// DeclarationError 4619: (110-115): Function "rjump" not found. +// DeclarationError 4619: (122-128): Function "rjumpi" not found. +// DeclarationError 4619: (135-140): Function "callf" not found. +// DeclarationError 4619: (148-153): Function "jumpf" not found. +// DeclarationError 4619: (161-165): Function "retf" not found. +// TypeError 4328: (172-179): The "extcall" instruction is only available in EOF. +// TypeError 4328: (196-209): The "extstaticcall" instruction is only available in EOF. +// TypeError 4328: (223-238): The "extdelegatecall" instruction is only available in EOF. diff --git a/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_reserved_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_reserved_in_legacy.yul new file mode 100644 index 000000000..3cb737d4b --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_reserved_in_legacy.yul @@ -0,0 +1,16 @@ +{ + function auxdataloadn() {} + function dataloadn() {} + function eofcreate() {} + function returncontract() {} + function rjump() {} + function rjumpi() {} + function callf() {} + function jumpf() {} + function retf() {} + function extcall() {} + function extstaticcall() {} + function extdelegatecall() {} +} +// ==== +// bytecodeFormat: legacy \ No newline at end of file diff --git a/test/libyul/yulSyntaxTests/eof/eof_names_reserved_in_eof.yul b/test/libyul/yulSyntaxTests/eof/eof_names_reserved_in_eof.yul new file mode 100644 index 000000000..063f8f4a8 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eof_names_reserved_in_eof.yul @@ -0,0 +1,17 @@ +{ + function auxdataloadn() {} + function eofcreate() {} + function returncontract() {} + function extcall() {} + function extdelegatecall() {} + function extstaticcall() {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// ParserError 5568: (15-27): Cannot use builtin function name "auxdataloadn" as identifier name. +// ParserError 5568: (46-55): Cannot use builtin function name "eofcreate" as identifier name. +// ParserError 5568: (74-88): Cannot use builtin function name "returncontract" as identifier name. +// ParserError 5568: (107-114): Cannot use builtin function name "extcall" as identifier name. +// ParserError 5568: (133-148): Cannot use builtin function name "extdelegatecall" as identifier name. +// ParserError 5568: (167-180): Cannot use builtin function name "extstaticcall" as identifier name. diff --git a/test/libyul/yulSyntaxTests/eof/eof_opcodes_identifiers_reserved_in_eof.yul b/test/libyul/yulSyntaxTests/eof/eof_opcodes_identifiers_reserved_in_eof.yul new file mode 100644 index 000000000..17ca120e6 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/eof_opcodes_identifiers_reserved_in_eof.yul @@ -0,0 +1,17 @@ +{ + function dataloadn() {} + function rjump() {} + function rjumpi() {} + function callf() {} + function jumpf() {} + function retf() {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// DeclarationError 5017: (6-29): The identifier "dataloadn" is reserved and can not be used. +// DeclarationError 5017: (34-53): The identifier "rjump" is reserved and can not be used. +// DeclarationError 5017: (58-78): The identifier "rjumpi" is reserved and can not be used. +// DeclarationError 5017: (83-102): The identifier "callf" is reserved and can not be used. +// DeclarationError 5017: (107-126): The identifier "jumpf" is reserved and can not be used. +// DeclarationError 5017: (131-149): The identifier "retf" is reserved and can not be used. From e78424420505dc832cc6c3e0c4f9ebc7d71e3efa Mon Sep 17 00:00:00 2001 From: leopardracer <136604165+leopardracer@users.noreply.github.com> Date: Thu, 23 Jan 2025 17:43:44 +0100 Subject: [PATCH 0627/1340] fix: typos in `libsolidity/analysis/` (#15756) * Update NameAndTypeResolver.cpp * Update ControlFlowAnalyzer.cpp --- libsolidity/analysis/ControlFlowAnalyzer.cpp | 4 ++-- libsolidity/analysis/NameAndTypeResolver.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/analysis/ControlFlowAnalyzer.cpp b/libsolidity/analysis/ControlFlowAnalyzer.cpp index 7ae1aa76e..8c9c6ba5c 100644 --- a/libsolidity/analysis/ControlFlowAnalyzer.cpp +++ b/libsolidity/analysis/ControlFlowAnalyzer.cpp @@ -74,12 +74,12 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod bool propagateFrom(NodeInfo const& _entryNode) { size_t previousUnassignedVariablesAtEntry = unassignedVariablesAtEntry.size(); - size_t previousUninitializedVariableAccessess = uninitializedVariableAccesses.size(); + size_t previousUninitializedVariableAccesses = uninitializedVariableAccesses.size(); unassignedVariablesAtEntry += _entryNode.unassignedVariablesAtExit; uninitializedVariableAccesses += _entryNode.uninitializedVariableAccesses; return unassignedVariablesAtEntry.size() > previousUnassignedVariablesAtEntry || - uninitializedVariableAccesses.size() > previousUninitializedVariableAccessess + uninitializedVariableAccesses.size() > previousUninitializedVariableAccesses ; } }; diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 32ef6d476..766f1bf12 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -716,7 +716,7 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio ); // NOTE: We're registering the function outside of its scope(). This will only affect - // name lookups. An more general alternative would be to modify Scoper to simply assign it + // name lookups. A more general alternative would be to modify Scoper to simply assign it // that scope in the first place, but this would complicate the AST traversal here, which // currently assumes that scopes follow ScopeOpener nesting. registerDeclaration(*m_scopes.at(quantifier->scope()), _declaration, nullptr, nullptr, false /* inactive */, m_errorReporter); From b59eafa9cc7709cea4fb612bb3943c1a5922d424 Mon Sep 17 00:00:00 2001 From: "fuder.eth" <139509124+vtjl10@users.noreply.github.com> Date: Thu, 23 Jan 2025 12:58:59 +0100 Subject: [PATCH 0628/1340] Update SymbolicTypes.cpp --- libsolidity/formal/SymbolicTypes.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index f8e1ebbdc..72739bccf 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -126,15 +126,15 @@ SortPointer smtSort(frontend::Type const& _type) tupleName = tupleSort->name; else if (isContract(*baseType)) // use a common sort for contracts so inheriting contracts do not cause conflicting SMT types - // solc handles types mismtach + // solc handles types mismatch tupleName = "contract"; else if (isFunction(*baseType)) // use a common sort for functions so pure and view modifier do not cause conflicting SMT types - // solc handles types mismtach + // solc handles types mismatch tupleName = "function"; else if (isAddress(*baseType)) // use a common sort for address and address payable so it does not cause conflicting SMT types - // solc handles types mismtach + // solc handles types mismatch tupleName = "address"; else if ( baseType->category() == frontend::Type::Category::Integer || From 6854a62972c95170aad922b07789fedf95b306a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 23 Jan 2025 20:01:43 +0100 Subject: [PATCH 0629/1340] Fix semantic and syntax test dirs not following the same naming convention --- .../abi_decode_calldata.sol | 0 .../abi_decode_simple.sol | 0 .../abi_decode_simple_storage.sol | 0 .../abi_encode_call.sol | 0 .../abi_encode_call_declaration.sol | 0 .../abi_encode_call_is_consistent.sol | 0 .../abi_encode_call_memory.sol | 0 .../abi_encode_call_special_args.sol | 0 .../abi_encode_call_uint_bytes.sol | 0 .../abi_encode_empty_string_v1.sol | 0 .../abi_encode_with_selector.sol | 0 .../abi_encode_with_selectorv2.sol | 0 .../abi_encode_with_signature.sol | 0 .../abi_encode_with_signaturev2.sol | 0 .../contract_array.sol | 0 .../contract_array_v2.sol | 0 .../offset_overflow_in_array_decoding.sol | 0 .../offset_overflow_in_array_decoding_2.sol | 0 .../offset_overflow_in_array_decoding_3.sol | 0 .../array_2d_zeroed_memory_index_access.sol | 0 .../array_array_static.sol | 0 ...c_return_param_zeroed_memory_index_access.sol | 0 .../array_static_zeroed_memory_index_access.sol | 0 .../array_zeroed_memory_index_access.sol | 0 .../a.sol | 0 .../c.sol | 0 .../d.sol | 0 .../D/d.sol | 0 .../c.sol | 0 .../dir/B/b.sol | 0 .../dir/G/g.sol | 0 .../dir/a.sol | 0 .../dir/contract.sol | 2 +- .../h.sol | 0 .../b.sol | 0 .../dir/a.sol | 0 .../dir/contract.sol | 0 .../dot_a.sol | 0 .../dot_dot_b.sol | 0 .../externalSource/non_normalized_paths.sol | 8 ++++---- .../externalSource/relative_imports.sol | 16 ++++++++-------- .../source_name_starting_with_dots.sol | 12 ++++++------ .../prediction_example.sol | 0 .../salted_create.sol | 0 .../salted_create_with_value.sol | 0 .../ancestor.sol | 0 .../base.sol | 0 .../base_multi.sol | 0 .../base_multi_no_constructor.sol | 0 .../base_multi_no_constructor_modifier_style.sol | 0 .../fallback_overrides_receive.sol | 0 .../fallback_with_override.sol | 0 .../fallback_with_override_intermediate.sol | 0 .../fallback_without_override.sol | 0 .../fallback_without_override_intermediate.sol | 0 .../receive_overrides_fallback.sol | 0 .../receive_parameter.sol | 0 .../receive_return_parameter.sol | 0 .../receive_unimplemented.sol | 0 .../receive_with_override.sol | 0 .../receive_with_override_intermediate.sol | 0 .../receive_without_override.sol | 0 .../receive_without_override_intermediate.sol | 0 .../abstract_needed.sol | 0 .../diamond_needed.sol | 0 .../regular_optional.sol | 0 .../dynamic_inline_array.sol | 0 ...claration_and_passing_implicit_conversion.sol | 0 ...n_and_passing_implicit_conversion_strings.sol | 0 ...ne_array_declaration_const_int_conversion.sol | 0 ...array_declaration_const_string_conversion.sol | 0 .../inline_array_declaration_no_type.sol | 0 .../inline_array_declaration_no_type_strings.sol | 0 .../inline_array_fixed_types.sol | 0 .../inline_array_of_mapping_type.sol | 0 .../inline_array_rationals.sol | 0 .../invalid_types_in_inline_array.sol | 0 .../lvalues_as_inline_array.sol | 0 .../unnamed_type_tuple_in_inline_array.sol | 0 .../unnamed_types_in_inline_array_1.sol | 0 .../unnamed_types_in_inline_array_2.sol | 0 .../unnamed_types_in_inline_array_3.sol | 0 .../function_definition_expression.sol | 0 .../function_parameter_return_types_fail.sol | 0 .../function_parameter_return_types_success.sol | 0 .../function_state_mutability_fail.sol | 0 .../function_state_mutability_success.sol | 0 .../selector/function_selector_pure.sol | 0 .../local_variable_selector_not_pure.sol | 0 .../state_variable_selector_contract_name.sol | 0 .../state_variable_selector_not_pure.sol | 0 .../selector/state_variable_selector_super.sol | 0 92 files changed, 19 insertions(+), 19 deletions(-) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_decode_calldata.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_decode_simple.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_decode_simple_storage.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_encode_call.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_encode_call_declaration.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_encode_call_is_consistent.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_encode_call_memory.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_encode_call_special_args.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_encode_call_uint_bytes.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_encode_empty_string_v1.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_encode_with_selector.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_encode_with_selectorv2.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_encode_with_signature.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/abi_encode_with_signaturev2.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/contract_array.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/contract_array_v2.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/offset_overflow_in_array_decoding.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/offset_overflow_in_array_decoding_2.sol (100%) rename test/libsolidity/semanticTests/{abiencodedecode => abiEncodeDecode}/offset_overflow_in_array_decoding_3.sol (100%) rename test/libsolidity/semanticTests/array/{array_memory_allocation => arrayMemoryAllocation}/array_2d_zeroed_memory_index_access.sol (100%) rename test/libsolidity/semanticTests/array/{array_memory_allocation => arrayMemoryAllocation}/array_array_static.sol (100%) rename test/libsolidity/semanticTests/array/{array_memory_allocation => arrayMemoryAllocation}/array_static_return_param_zeroed_memory_index_access.sol (100%) rename test/libsolidity/semanticTests/array/{array_memory_allocation => arrayMemoryAllocation}/array_static_zeroed_memory_index_access.sol (100%) rename test/libsolidity/semanticTests/array/{array_memory_allocation => arrayMemoryAllocation}/array_zeroed_memory_index_access.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_non_normalized_paths => _nonNormalizedPaths}/a.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_non_normalized_paths => _nonNormalizedPaths}/c.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_non_normalized_paths => _nonNormalizedPaths}/d.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_relative_imports => _relativeImports}/D/d.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_relative_imports => _relativeImports}/c.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_relative_imports => _relativeImports}/dir/B/b.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_relative_imports => _relativeImports}/dir/G/g.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_relative_imports => _relativeImports}/dir/a.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_relative_imports => _relativeImports}/dir/contract.sol (76%) rename test/libsolidity/semanticTests/externalSource/{_relative_imports => _relativeImports}/h.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_source_name_starting_with_dots => _sourceNameStartingWithDots}/b.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_source_name_starting_with_dots => _sourceNameStartingWithDots}/dir/a.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_source_name_starting_with_dots => _sourceNameStartingWithDots}/dir/contract.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_source_name_starting_with_dots => _sourceNameStartingWithDots}/dot_a.sol (100%) rename test/libsolidity/semanticTests/externalSource/{_source_name_starting_with_dots => _sourceNameStartingWithDots}/dot_dot_b.sol (100%) rename test/libsolidity/semanticTests/{salted_create => saltedCreate}/prediction_example.sol (100%) rename test/libsolidity/semanticTests/{salted_create => saltedCreate}/salted_create.sol (100%) rename test/libsolidity/semanticTests/{salted_create => saltedCreate}/salted_create_with_value.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{duplicated_constructor_call => duplicatedConstructorCall}/ancestor.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{duplicated_constructor_call => duplicatedConstructorCall}/base.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{duplicated_constructor_call => duplicatedConstructorCall}/base_multi.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{duplicated_constructor_call => duplicatedConstructorCall}/base_multi_no_constructor.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{duplicated_constructor_call => duplicatedConstructorCall}/base_multi_no_constructor_modifier_style.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/fallback_overrides_receive.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/fallback_with_override.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/fallback_with_override_intermediate.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/fallback_without_override.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/fallback_without_override_intermediate.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/receive_overrides_fallback.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/receive_parameter.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/receive_return_parameter.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/receive_unimplemented.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/receive_with_override.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/receive_with_override_intermediate.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/receive_without_override.sol (100%) rename test/libsolidity/syntaxTests/inheritance/{fallback_receive => fallbackReceive}/receive_without_override_intermediate.sol (100%) rename test/libsolidity/syntaxTests/inheritance/override/{interface_exception => interfaceException}/abstract_needed.sol (100%) rename test/libsolidity/syntaxTests/inheritance/override/{interface_exception => interfaceException}/diamond_needed.sol (100%) rename test/libsolidity/syntaxTests/inheritance/override/{interface_exception => interfaceException}/regular_optional.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/dynamic_inline_array.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/inline_array_declaration_and_passing_implicit_conversion.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/inline_array_declaration_and_passing_implicit_conversion_strings.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/inline_array_declaration_const_int_conversion.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/inline_array_declaration_const_string_conversion.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/inline_array_declaration_no_type.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/inline_array_declaration_no_type_strings.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/inline_array_fixed_types.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/inline_array_of_mapping_type.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/inline_array_rationals.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/invalid_types_in_inline_array.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/lvalues_as_inline_array.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/unnamed_type_tuple_in_inline_array.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/unnamed_types_in_inline_array_1.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/unnamed_types_in_inline_array_2.sol (100%) rename test/libsolidity/syntaxTests/{inline_arrays => inlineArrays}/unnamed_types_in_inline_array_3.sol (100%) rename test/libsolidity/syntaxTests/types/{function_types => functionTypes}/function_definition_expression.sol (100%) rename test/libsolidity/syntaxTests/types/{function_types => functionTypes}/function_parameter_return_types_fail.sol (100%) rename test/libsolidity/syntaxTests/types/{function_types => functionTypes}/function_parameter_return_types_success.sol (100%) rename test/libsolidity/syntaxTests/types/{function_types => functionTypes}/function_state_mutability_fail.sol (100%) rename test/libsolidity/syntaxTests/types/{function_types => functionTypes}/function_state_mutability_success.sol (100%) rename test/libsolidity/syntaxTests/types/{function_types => functionTypes}/selector/function_selector_pure.sol (100%) rename test/libsolidity/syntaxTests/types/{function_types => functionTypes}/selector/local_variable_selector_not_pure.sol (100%) rename test/libsolidity/syntaxTests/types/{function_types => functionTypes}/selector/state_variable_selector_contract_name.sol (100%) rename test/libsolidity/syntaxTests/types/{function_types => functionTypes}/selector/state_variable_selector_not_pure.sol (100%) rename test/libsolidity/syntaxTests/types/{function_types => functionTypes}/selector/state_variable_selector_super.sol (100%) diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_calldata.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_calldata.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_decode_calldata.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_calldata.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple_storage.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_decode_simple_storage.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple_storage.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_declaration.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_declaration.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_declaration.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_declaration.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_is_consistent.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_is_consistent.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_is_consistent.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_is_consistent.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_memory.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_memory.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_memory.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_memory.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_special_args.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_special_args.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_special_args.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_special_args.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_uint_bytes.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_uint_bytes.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_call_uint_bytes.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_uint_bytes.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_empty_string_v1.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_empty_string_v1.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_empty_string_v1.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_empty_string_v1.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_selector.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selector.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_selector.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selector.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_selectorv2.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selectorv2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_selectorv2.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selectorv2.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signature.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signature.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signature.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signature.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signaturev2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/abi_encode_with_signaturev2.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signaturev2.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/contract_array.sol b/test/libsolidity/semanticTests/abiEncodeDecode/contract_array.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/contract_array.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/contract_array.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/contract_array_v2.sol b/test/libsolidity/semanticTests/abiEncodeDecode/contract_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/contract_array_v2.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/contract_array_v2.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding.sol b/test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding_2.sol b/test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding_2.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_2.sol diff --git a/test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding_3.sol b/test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_3.sol similarity index 100% rename from test/libsolidity/semanticTests/abiencodedecode/offset_overflow_in_array_decoding_3.sol rename to test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_3.sol diff --git a/test/libsolidity/semanticTests/array/array_memory_allocation/array_2d_zeroed_memory_index_access.sol b/test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_2d_zeroed_memory_index_access.sol similarity index 100% rename from test/libsolidity/semanticTests/array/array_memory_allocation/array_2d_zeroed_memory_index_access.sol rename to test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_2d_zeroed_memory_index_access.sol diff --git a/test/libsolidity/semanticTests/array/array_memory_allocation/array_array_static.sol b/test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_array_static.sol similarity index 100% rename from test/libsolidity/semanticTests/array/array_memory_allocation/array_array_static.sol rename to test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_array_static.sol diff --git a/test/libsolidity/semanticTests/array/array_memory_allocation/array_static_return_param_zeroed_memory_index_access.sol b/test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_static_return_param_zeroed_memory_index_access.sol similarity index 100% rename from test/libsolidity/semanticTests/array/array_memory_allocation/array_static_return_param_zeroed_memory_index_access.sol rename to test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_static_return_param_zeroed_memory_index_access.sol diff --git a/test/libsolidity/semanticTests/array/array_memory_allocation/array_static_zeroed_memory_index_access.sol b/test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_static_zeroed_memory_index_access.sol similarity index 100% rename from test/libsolidity/semanticTests/array/array_memory_allocation/array_static_zeroed_memory_index_access.sol rename to test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_static_zeroed_memory_index_access.sol diff --git a/test/libsolidity/semanticTests/array/array_memory_allocation/array_zeroed_memory_index_access.sol b/test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_zeroed_memory_index_access.sol similarity index 100% rename from test/libsolidity/semanticTests/array/array_memory_allocation/array_zeroed_memory_index_access.sol rename to test/libsolidity/semanticTests/array/arrayMemoryAllocation/array_zeroed_memory_index_access.sol diff --git a/test/libsolidity/semanticTests/externalSource/_non_normalized_paths/a.sol b/test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/a.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_non_normalized_paths/a.sol rename to test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/a.sol diff --git a/test/libsolidity/semanticTests/externalSource/_non_normalized_paths/c.sol b/test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/c.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_non_normalized_paths/c.sol rename to test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/c.sol diff --git a/test/libsolidity/semanticTests/externalSource/_non_normalized_paths/d.sol b/test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/d.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_non_normalized_paths/d.sol rename to test/libsolidity/semanticTests/externalSource/_nonNormalizedPaths/d.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/D/d.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/D/d.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/D/d.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/D/d.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/c.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/c.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/c.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/c.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/dir/B/b.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/dir/B/b.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/dir/B/b.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/dir/B/b.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/dir/G/g.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/dir/G/g.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/dir/G/g.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/dir/G/g.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/dir/a.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/dir/a.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/dir/a.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/dir/a.sol diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/dir/contract.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/dir/contract.sol similarity index 76% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/dir/contract.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/dir/contract.sol index aab81b975..e41d935a2 100644 --- a/test/libsolidity/semanticTests/externalSource/_relative_imports/dir/contract.sol +++ b/test/libsolidity/semanticTests/externalSource/_relativeImports/dir/contract.sol @@ -3,6 +3,6 @@ import {B} from "./B/b.sol"; import {C} from "../c.sol"; import {D} from "../D/d.sol"; import {G} from "./E/../F/../G/./g.sol"; -import {H} from "../../../../_relative_imports/h.sol"; +import {H} from "../../../../_relativeImports/h.sol"; contract Contract { } diff --git a/test/libsolidity/semanticTests/externalSource/_relative_imports/h.sol b/test/libsolidity/semanticTests/externalSource/_relativeImports/h.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_relative_imports/h.sol rename to test/libsolidity/semanticTests/externalSource/_relativeImports/h.sol diff --git a/test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/b.sol b/test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/b.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/b.sol rename to test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/b.sol diff --git a/test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dir/a.sol b/test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dir/a.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dir/a.sol rename to test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dir/a.sol diff --git a/test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dir/contract.sol b/test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dir/contract.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dir/contract.sol rename to test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dir/contract.sol diff --git a/test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dot_a.sol b/test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dot_a.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dot_a.sol rename to test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dot_a.sol diff --git a/test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dot_dot_b.sol b/test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dot_dot_b.sol similarity index 100% rename from test/libsolidity/semanticTests/externalSource/_source_name_starting_with_dots/dot_dot_b.sol rename to test/libsolidity/semanticTests/externalSource/_sourceNameStartingWithDots/dot_dot_b.sol diff --git a/test/libsolidity/semanticTests/externalSource/non_normalized_paths.sol b/test/libsolidity/semanticTests/externalSource/non_normalized_paths.sol index 7316cc7d5..84ad75514 100644 --- a/test/libsolidity/semanticTests/externalSource/non_normalized_paths.sol +++ b/test/libsolidity/semanticTests/externalSource/non_normalized_paths.sol @@ -1,7 +1,7 @@ -==== ExternalSource: _non_normalized_paths//a.sol ==== -==== ExternalSource: C/////c.sol=_non_normalized_paths/c.sol ==== -==== ExternalSource: C/../////D/d.sol=_non_normalized_paths///d.sol ==== -import {A} from "_non_normalized_paths//a.sol"; +==== ExternalSource: _nonNormalizedPaths//a.sol ==== +==== ExternalSource: C/////c.sol=_nonNormalizedPaths/c.sol ==== +==== ExternalSource: C/../////D/d.sol=_nonNormalizedPaths///d.sol ==== +import {A} from "_nonNormalizedPaths//a.sol"; import {C} from "C/////c.sol"; import {D} from "C/../////D/d.sol"; contract Contract { diff --git a/test/libsolidity/semanticTests/externalSource/relative_imports.sol b/test/libsolidity/semanticTests/externalSource/relative_imports.sol index 9a37896bb..e8e402229 100644 --- a/test/libsolidity/semanticTests/externalSource/relative_imports.sol +++ b/test/libsolidity/semanticTests/externalSource/relative_imports.sol @@ -1,11 +1,11 @@ -==== ExternalSource: _relative_imports/dir/contract.sol ==== -==== ExternalSource: _relative_imports/dir/a.sol ==== -==== ExternalSource: _relative_imports/dir/B/b.sol ==== -==== ExternalSource: _relative_imports/c.sol ==== -==== ExternalSource: _relative_imports/D/d.sol ==== -==== ExternalSource: _relative_imports/dir/G/g.sol ==== -==== ExternalSource: _relative_imports/h.sol ==== -import {A, B, C, D, G, H, Contract} from "_relative_imports/dir/contract.sol"; +==== ExternalSource: _relativeImports/dir/contract.sol ==== +==== ExternalSource: _relativeImports/dir/a.sol ==== +==== ExternalSource: _relativeImports/dir/B/b.sol ==== +==== ExternalSource: _relativeImports/c.sol ==== +==== ExternalSource: _relativeImports/D/d.sol ==== +==== ExternalSource: _relativeImports/dir/G/g.sol ==== +==== ExternalSource: _relativeImports/h.sol ==== +import {A, B, C, D, G, H, Contract} from "_relativeImports/dir/contract.sol"; contract CC { } // ---- diff --git a/test/libsolidity/semanticTests/externalSource/source_name_starting_with_dots.sol b/test/libsolidity/semanticTests/externalSource/source_name_starting_with_dots.sol index b671c94f9..bb325b391 100644 --- a/test/libsolidity/semanticTests/externalSource/source_name_starting_with_dots.sol +++ b/test/libsolidity/semanticTests/externalSource/source_name_starting_with_dots.sol @@ -1,9 +1,9 @@ -==== ExternalSource: ./a.sol=_source_name_starting_with_dots/dot_a.sol ==== -==== ExternalSource: ../b.sol=_source_name_starting_with_dots/dot_dot_b.sol ==== -==== ExternalSource: _source_name_starting_with_dots/dir/a.sol ==== -==== ExternalSource: _source_name_starting_with_dots/b.sol ==== -==== ExternalSource: _source_name_starting_with_dots/dir/contract.sol ==== -import {A, B} from "_source_name_starting_with_dots/dir/contract.sol"; +==== ExternalSource: ./a.sol=_sourceNameStartingWithDots/dot_a.sol ==== +==== ExternalSource: ../b.sol=_sourceNameStartingWithDots/dot_dot_b.sol ==== +==== ExternalSource: _sourceNameStartingWithDots/dir/a.sol ==== +==== ExternalSource: _sourceNameStartingWithDots/b.sol ==== +==== ExternalSource: _sourceNameStartingWithDots/dir/contract.sol ==== +import {A, B} from "_sourceNameStartingWithDots/dir/contract.sol"; contract Contract { } // ---- diff --git a/test/libsolidity/semanticTests/salted_create/prediction_example.sol b/test/libsolidity/semanticTests/saltedCreate/prediction_example.sol similarity index 100% rename from test/libsolidity/semanticTests/salted_create/prediction_example.sol rename to test/libsolidity/semanticTests/saltedCreate/prediction_example.sol diff --git a/test/libsolidity/semanticTests/salted_create/salted_create.sol b/test/libsolidity/semanticTests/saltedCreate/salted_create.sol similarity index 100% rename from test/libsolidity/semanticTests/salted_create/salted_create.sol rename to test/libsolidity/semanticTests/saltedCreate/salted_create.sol diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/saltedCreate/salted_create_with_value.sol similarity index 100% rename from test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol rename to test/libsolidity/semanticTests/saltedCreate/salted_create_with_value.sol diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor.sol b/test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/ancestor.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor.sol rename to test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/ancestor.sol diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base.sol b/test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base.sol rename to test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base.sol diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi.sol b/test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi.sol rename to test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi.sol diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor.sol b/test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi_no_constructor.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor.sol rename to test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi_no_constructor.sol diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor_modifier_style.sol b/test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi_no_constructor_modifier_style.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor_modifier_style.sol rename to test/libsolidity/syntaxTests/inheritance/duplicatedConstructorCall/base_multi_no_constructor_modifier_style.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_overrides_receive.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_overrides_receive.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_overrides_receive.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_overrides_receive.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_with_override.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_with_override.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_with_override.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_with_override.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_with_override_intermediate.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_with_override_intermediate.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_with_override_intermediate.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_with_override_intermediate.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_without_override.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_without_override.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_without_override.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_without_override.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_without_override_intermediate.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_without_override_intermediate.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/fallback_without_override_intermediate.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/fallback_without_override_intermediate.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_overrides_fallback.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_overrides_fallback.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_overrides_fallback.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_overrides_fallback.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_parameter.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_parameter.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_parameter.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_parameter.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_return_parameter.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_return_parameter.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_return_parameter.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_return_parameter.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_unimplemented.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_unimplemented.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_unimplemented.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_unimplemented.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_with_override.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_with_override.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_with_override.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_with_override.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_with_override_intermediate.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_with_override_intermediate.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_with_override_intermediate.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_with_override_intermediate.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_without_override.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_without_override.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_without_override.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_without_override.sol diff --git a/test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_without_override_intermediate.sol b/test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_without_override_intermediate.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/fallback_receive/receive_without_override_intermediate.sol rename to test/libsolidity/syntaxTests/inheritance/fallbackReceive/receive_without_override_intermediate.sol diff --git a/test/libsolidity/syntaxTests/inheritance/override/interface_exception/abstract_needed.sol b/test/libsolidity/syntaxTests/inheritance/override/interfaceException/abstract_needed.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/override/interface_exception/abstract_needed.sol rename to test/libsolidity/syntaxTests/inheritance/override/interfaceException/abstract_needed.sol diff --git a/test/libsolidity/syntaxTests/inheritance/override/interface_exception/diamond_needed.sol b/test/libsolidity/syntaxTests/inheritance/override/interfaceException/diamond_needed.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/override/interface_exception/diamond_needed.sol rename to test/libsolidity/syntaxTests/inheritance/override/interfaceException/diamond_needed.sol diff --git a/test/libsolidity/syntaxTests/inheritance/override/interface_exception/regular_optional.sol b/test/libsolidity/syntaxTests/inheritance/override/interfaceException/regular_optional.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/override/interface_exception/regular_optional.sol rename to test/libsolidity/syntaxTests/inheritance/override/interfaceException/regular_optional.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/dynamic_inline_array.sol b/test/libsolidity/syntaxTests/inlineArrays/dynamic_inline_array.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/dynamic_inline_array.sol rename to test/libsolidity/syntaxTests/inlineArrays/dynamic_inline_array.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_and_passing_implicit_conversion.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_and_passing_implicit_conversion.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion_strings.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_and_passing_implicit_conversion_strings.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion_strings.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_and_passing_implicit_conversion_strings.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_int_conversion.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_const_int_conversion.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_int_conversion.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_const_int_conversion.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_string_conversion.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_const_string_conversion.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_string_conversion.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_const_string_conversion.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_no_type.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_no_type.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type_strings.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_no_type_strings.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type_strings.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_declaration_no_type_strings.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_fixed_types.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_fixed_types.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_of_mapping_type.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_of_mapping_type.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_of_mapping_type.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_of_mapping_type.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_rationals.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol rename to test/libsolidity/syntaxTests/inlineArrays/inline_array_rationals.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/invalid_types_in_inline_array.sol b/test/libsolidity/syntaxTests/inlineArrays/invalid_types_in_inline_array.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/invalid_types_in_inline_array.sol rename to test/libsolidity/syntaxTests/inlineArrays/invalid_types_in_inline_array.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/lvalues_as_inline_array.sol b/test/libsolidity/syntaxTests/inlineArrays/lvalues_as_inline_array.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/lvalues_as_inline_array.sol rename to test/libsolidity/syntaxTests/inlineArrays/lvalues_as_inline_array.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/unnamed_type_tuple_in_inline_array.sol b/test/libsolidity/syntaxTests/inlineArrays/unnamed_type_tuple_in_inline_array.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/unnamed_type_tuple_in_inline_array.sol rename to test/libsolidity/syntaxTests/inlineArrays/unnamed_type_tuple_in_inline_array.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_1.sol b/test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_1.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_1.sol rename to test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_1.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_2.sol b/test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_2.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_2.sol rename to test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_2.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_3.sol b/test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_3.sol similarity index 100% rename from test/libsolidity/syntaxTests/inline_arrays/unnamed_types_in_inline_array_3.sol rename to test/libsolidity/syntaxTests/inlineArrays/unnamed_types_in_inline_array_3.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/function_definition_expression.sol b/test/libsolidity/syntaxTests/types/functionTypes/function_definition_expression.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/function_definition_expression.sol rename to test/libsolidity/syntaxTests/types/functionTypes/function_definition_expression.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol b/test/libsolidity/syntaxTests/types/functionTypes/function_parameter_return_types_fail.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_fail.sol rename to test/libsolidity/syntaxTests/types/functionTypes/function_parameter_return_types_fail.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_success.sol b/test/libsolidity/syntaxTests/types/functionTypes/function_parameter_return_types_success.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/function_parameter_return_types_success.sol rename to test/libsolidity/syntaxTests/types/functionTypes/function_parameter_return_types_success.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_fail.sol b/test/libsolidity/syntaxTests/types/functionTypes/function_state_mutability_fail.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/function_state_mutability_fail.sol rename to test/libsolidity/syntaxTests/types/functionTypes/function_state_mutability_fail.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/function_state_mutability_success.sol b/test/libsolidity/syntaxTests/types/functionTypes/function_state_mutability_success.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/function_state_mutability_success.sol rename to test/libsolidity/syntaxTests/types/functionTypes/function_state_mutability_success.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/selector/function_selector_pure.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/function_selector_pure.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/selector/function_selector_pure.sol rename to test/libsolidity/syntaxTests/types/functionTypes/selector/function_selector_pure.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/selector/local_variable_selector_not_pure.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/local_variable_selector_not_pure.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/selector/local_variable_selector_not_pure.sol rename to test/libsolidity/syntaxTests/types/functionTypes/selector/local_variable_selector_not_pure.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_contract_name.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_contract_name.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_contract_name.sol rename to test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_contract_name.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_not_pure.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_not_pure.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_not_pure.sol rename to test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_not_pure.sol diff --git a/test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_super.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_super.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/function_types/selector/state_variable_selector_super.sol rename to test/libsolidity/syntaxTests/types/functionTypes/selector/state_variable_selector_super.sol From 11b770f725d13b7bc9e43f7c43e4ff96e54ba7d4 Mon Sep 17 00:00:00 2001 From: kilavvy <140459108+kilavvy@users.noreply.github.com> Date: Fri, 24 Jan 2025 03:51:41 +0100 Subject: [PATCH 0630/1340] fix typo in `distinguishingProperty` variable name (#15763) * Update FilesystemUtils.cpp * Update OverrideChecker.cpp --- libsolidity/analysis/OverrideChecker.cpp | 4 ++-- test/FilesystemUtils.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libsolidity/analysis/OverrideChecker.cpp b/libsolidity/analysis/OverrideChecker.cpp index f2a99340d..f51aa2b6e 100644 --- a/libsolidity/analysis/OverrideChecker.cpp +++ b/libsolidity/analysis/OverrideChecker.cpp @@ -801,7 +801,7 @@ void OverrideChecker::checkAmbiguousOverridesInternal(std::set _b std::string callableName = _baseCallables.begin()->astNodeName(); if (_baseCallables.begin()->isVariable()) callableName = "function"; - std::string distinguishigProperty = _baseCallables.begin()->distinguishingProperty(); + std::string distinguishingProperty = _baseCallables.begin()->distinguishingProperty(); bool foundVariable = false; for (auto const& base: _baseCallables) @@ -811,7 +811,7 @@ void OverrideChecker::checkAmbiguousOverridesInternal(std::set _b std::string message = "Derived contract must override " + callableName + " \"" + _baseCallables.begin()->name() + - "\". Two or more base classes define " + callableName + " with same " + distinguishigProperty + "."; + "\". Two or more base classes define " + callableName + " with same " + distinguishingProperty + "."; if (foundVariable) message += diff --git a/test/FilesystemUtils.cpp b/test/FilesystemUtils.cpp index 2d917485d..edd9a0d6d 100644 --- a/test/FilesystemUtils.cpp +++ b/test/FilesystemUtils.cpp @@ -44,12 +44,12 @@ void solidity::test::createFilesWithParentDirs(std::set void solidity::test::createFileWithContent(boost::filesystem::path const& _path, std::string const& _content) { if (boost::filesystem::is_regular_file(_path)) - BOOST_THROW_EXCEPTION(std::runtime_error("File already exists: \"" + _path.string() + "\".")); \ + BOOST_THROW_EXCEPTION(std::runtime_error("File already exists: \"" + _path.string() + "\".")); // Use binary mode to avoid line ending conversion on Windows. std::ofstream newFile(_path.string(), std::ofstream::binary); if (newFile.fail() || !boost::filesystem::is_regular_file(_path)) - BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create a file: \"" + _path.string() + "\".")); \ + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create a file: \"" + _path.string() + "\".")); newFile << _content; } From 2d7dc289cd36ba82a7d8d52226be5cea1e7a69a7 Mon Sep 17 00:00:00 2001 From: Maxim Evtush <154841002+maximevtush@users.noreply.github.com> Date: Fri, 24 Jan 2025 04:29:15 +0100 Subject: [PATCH 0631/1340] fix typo in `ExpressionNestingLimitReached` enum value (#15767) * Update yulFuzzerCommon.cpp * Update yulFuzzerCommon.h --- test/tools/ossfuzz/yulFuzzerCommon.cpp | 4 ++-- test/tools/ossfuzz/yulFuzzerCommon.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/tools/ossfuzz/yulFuzzerCommon.cpp b/test/tools/ossfuzz/yulFuzzerCommon.cpp index 033dfc044..b95df8f21 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.cpp +++ b/test/tools/ossfuzz/yulFuzzerCommon.cpp @@ -64,7 +64,7 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( } catch (ExpressionNestingLimitReached const&) { - reason = TerminationReason::ExpresionNestingLimitReached; + reason = TerminationReason::ExpressionNestingLimitReached; } catch (ExplicitlyTerminated const&) { @@ -83,5 +83,5 @@ bool yulFuzzerUtil::resourceLimitsExceeded(TerminationReason _reason) return _reason == yulFuzzerUtil::TerminationReason::StepLimitReached || _reason == yulFuzzerUtil::TerminationReason::TraceLimitReached || - _reason == yulFuzzerUtil::TerminationReason::ExpresionNestingLimitReached; + _reason == yulFuzzerUtil::TerminationReason::ExpressionNestingLimitReached; } diff --git a/test/tools/ossfuzz/yulFuzzerCommon.h b/test/tools/ossfuzz/yulFuzzerCommon.h index 6575db11f..afcb0f2d3 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.h +++ b/test/tools/ossfuzz/yulFuzzerCommon.h @@ -28,7 +28,7 @@ struct yulFuzzerUtil ExplicitlyTerminated, StepLimitReached, TraceLimitReached, - ExpresionNestingLimitReached, + ExpressionNestingLimitReached, None }; From 9cb47312cfcfe0b766d1f46d0da8108d3ce115e8 Mon Sep 17 00:00:00 2001 From: FT <140458077+zeevick10@users.noreply.github.com> Date: Fri, 24 Jan 2025 12:31:24 +0100 Subject: [PATCH 0632/1340] Update StackCompressor.cpp --- libyul/optimiser/StackCompressor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 04b931a24..ae91716e5 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -15,7 +15,7 @@ along with solidity. If not, see . */ /** - * Optimisation stage that aggressively rematerializes certain variables ina a function to free + * Optimisation stage that aggressively rematerializes certain variables in a function to free * space on the stack until it is compilable. */ From 39c14916c25d89f8eab377c84f98ef2a46f1893f Mon Sep 17 00:00:00 2001 From: FT <140458077+zeevick10@users.noreply.github.com> Date: Fri, 24 Jan 2025 12:31:39 +0100 Subject: [PATCH 0633/1340] Update StackCompressor.h --- libyul/optimiser/StackCompressor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index d5590006c..728acb813 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -16,7 +16,7 @@ */ // SPDX-License-Identifier: GPL-3.0 /** - * Optimisation stage that aggressively rematerializes certain variables ina a function to free + * Optimisation stage that aggressively rematerializes certain variables in a function to free * space on the stack until it is compilable. */ From 01ba4a45d98068392cfe1263d0ce729e578a0260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 23 Jan 2025 19:30:43 +0100 Subject: [PATCH 0634/1340] Semantic tests: merge asmForLoop/ with inlineAssembly/ --- .../{asmForLoop => inlineAssembly}/for_loop_break.sol | 0 .../{asmForLoop => inlineAssembly}/for_loop_continue.sol | 0 .../{asmForLoop => inlineAssembly}/for_loop_nested.sol | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/semanticTests/{asmForLoop => inlineAssembly}/for_loop_break.sol (100%) rename test/libsolidity/semanticTests/{asmForLoop => inlineAssembly}/for_loop_continue.sol (100%) rename test/libsolidity/semanticTests/{asmForLoop => inlineAssembly}/for_loop_nested.sol (100%) diff --git a/test/libsolidity/semanticTests/asmForLoop/for_loop_break.sol b/test/libsolidity/semanticTests/inlineAssembly/for_loop_break.sol similarity index 100% rename from test/libsolidity/semanticTests/asmForLoop/for_loop_break.sol rename to test/libsolidity/semanticTests/inlineAssembly/for_loop_break.sol diff --git a/test/libsolidity/semanticTests/asmForLoop/for_loop_continue.sol b/test/libsolidity/semanticTests/inlineAssembly/for_loop_continue.sol similarity index 100% rename from test/libsolidity/semanticTests/asmForLoop/for_loop_continue.sol rename to test/libsolidity/semanticTests/inlineAssembly/for_loop_continue.sol diff --git a/test/libsolidity/semanticTests/asmForLoop/for_loop_nested.sol b/test/libsolidity/semanticTests/inlineAssembly/for_loop_nested.sol similarity index 100% rename from test/libsolidity/semanticTests/asmForLoop/for_loop_nested.sol rename to test/libsolidity/semanticTests/inlineAssembly/for_loop_nested.sol From ea905bd1087005a2c9a55379bcf7e47cc2fa5f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 23 Jan 2025 19:30:08 +0100 Subject: [PATCH 0635/1340] Move loose semantic and syntax tests tests to the right subdirectories --- .../{ => cleanup}/byte_array_to_storage_cleanup.sol | 0 .../semanticTests/{ => cleanup}/dirty_calldata_bytes.sol | 0 .../{ => cleanup}/dirty_calldata_dynamic_array.sol | 0 .../state_variable_initialization.sol} | 0 .../{ => events}/emit_three_identical_events.sol | 0 .../{ => events}/emit_two_identical_events.sol | 0 .../constructor_inheritance_init_order.sol | 0 .../constructor_inheritance_init_order_2.sol | 0 .../constructor_inheritance_init_order_3_legacy.sol | 0 .../constructor_inheritance_init_order_3_viaIR.sol | 0 .../{ => inheritance}/constructor_with_params.sol | 0 .../constructor_with_params_diamond_inheritance.sol | 0 .../constructor_with_params_inheritance.sol | 0 .../constructor_with_params_inheritance_2.sol | 0 .../interface_inheritance_conversions.sol | 0 .../{ => inheritance}/state_variables_init_order.sol | 0 .../{ => inheritance}/state_variables_init_order_2.sol | 0 .../{ => inheritance}/state_variables_init_order_3.sol | 0 .../{ => isoltestTesting}/empty_contract.sol | 0 .../{ => isoltestTesting}/isoltestFormatting.sol | 0 .../{ => optimizer}/unused_store_storage_removal_bug.sol | 0 .../{ => scoping}/c99_scoping_activation.sol | 0 .../semanticTests/{ => statements}/empty_for_loop.sol | 0 .../{ => abiEncoder}/tight_packing_literals.sol | 0 .../{ => abiEncoder}/tight_packing_literals_fine.sol | 0 .../syntaxTests/{ => comments}/multiline_comments.sol | 0 .../syntaxTests/{ => constructor}/constructor_this.sol | 0 .../{ => globalFunctions}/deprecated_functions.sol | 0 .../cycle_checker_function_type.sol | 0 .../missing_functions_duplicate_bug.sol | 0 .../{ => isoltestTesting}/stopAfterAnalysisError.sol | 0 .../stopAfterParsingAnalysisErrorNotShowing.sol | 0 .../{ => isoltestTesting}/stopAfterParsingError.sol | 0 .../{ => literalOperations}/literal_comparisons.sol | 0 .../{ => literals}/upper_case_hex_literals.sol | 0 test/libsolidity/syntaxTests/{ => operators}/negation.sol | 0 .../{ => operators}/signed_rational_modulus.sol | 0 test/libsolidity/syntaxTests/{ => parsing}/unexpected.sol | 0 .../{ => scoping}/double_stateVariable_declaration.sol | 0 .../{ => scoping}/double_variable_declaration.sol | 0 .../syntaxTests/{ => scoping}/duplicate_contract.sol | 0 .../syntaxTests/{ => scoping}/missing_state_variable.sol | 0 .../{ => sizeLimits}/more_than_256_declarationerrors.sol | 0 .../{ => sizeLimits}/more_than_256_importerrors.sol | 0 .../{ => sizeLimits}/more_than_256_syntaxerrors.sol | 0 test/libsolidity/syntaxTests/{ => smoke}/smoke_test.sol | 0 .../syntaxTests/{ => structs}/empty_struct.sol | 0 .../{ => super}/unimplemented_super_function.sol | 0 .../{ => super}/unimplemented_super_function_derived.sol | 0 test/scripts/test_bytecodecompare_prepare_report.py | 8 ++++---- 50 files changed, 4 insertions(+), 4 deletions(-) rename test/libsolidity/semanticTests/{ => cleanup}/byte_array_to_storage_cleanup.sol (100%) rename test/libsolidity/semanticTests/{ => cleanup}/dirty_calldata_bytes.sol (100%) rename test/libsolidity/semanticTests/{ => cleanup}/dirty_calldata_dynamic_array.sol (100%) rename test/libsolidity/semanticTests/{state_var_initialization.sol => constructor/state_variable_initialization.sol} (100%) rename test/libsolidity/semanticTests/{ => events}/emit_three_identical_events.sol (100%) rename test/libsolidity/semanticTests/{ => events}/emit_two_identical_events.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/constructor_inheritance_init_order.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/constructor_inheritance_init_order_2.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/constructor_inheritance_init_order_3_legacy.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/constructor_inheritance_init_order_3_viaIR.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/constructor_with_params.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/constructor_with_params_diamond_inheritance.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/constructor_with_params_inheritance.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/constructor_with_params_inheritance_2.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/interface_inheritance_conversions.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/state_variables_init_order.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/state_variables_init_order_2.sol (100%) rename test/libsolidity/semanticTests/{ => inheritance}/state_variables_init_order_3.sol (100%) rename test/libsolidity/semanticTests/{ => isoltestTesting}/empty_contract.sol (100%) rename test/libsolidity/semanticTests/{ => isoltestTesting}/isoltestFormatting.sol (100%) rename test/libsolidity/semanticTests/{ => optimizer}/unused_store_storage_removal_bug.sol (100%) rename test/libsolidity/semanticTests/{ => scoping}/c99_scoping_activation.sol (100%) rename test/libsolidity/semanticTests/{ => statements}/empty_for_loop.sol (100%) rename test/libsolidity/syntaxTests/{ => abiEncoder}/tight_packing_literals.sol (100%) rename test/libsolidity/syntaxTests/{ => abiEncoder}/tight_packing_literals_fine.sol (100%) rename test/libsolidity/syntaxTests/{ => comments}/multiline_comments.sol (100%) rename test/libsolidity/syntaxTests/{ => constructor}/constructor_this.sol (100%) rename test/libsolidity/syntaxTests/{ => globalFunctions}/deprecated_functions.sol (100%) rename test/libsolidity/syntaxTests/{ => iceRegressionTests}/cycle_checker_function_type.sol (100%) rename test/libsolidity/syntaxTests/{ => iceRegressionTests}/missing_functions_duplicate_bug.sol (100%) rename test/libsolidity/syntaxTests/{ => isoltestTesting}/stopAfterAnalysisError.sol (100%) rename test/libsolidity/syntaxTests/{ => isoltestTesting}/stopAfterParsingAnalysisErrorNotShowing.sol (100%) rename test/libsolidity/syntaxTests/{ => isoltestTesting}/stopAfterParsingError.sol (100%) rename test/libsolidity/syntaxTests/{ => literalOperations}/literal_comparisons.sol (100%) rename test/libsolidity/syntaxTests/{ => literals}/upper_case_hex_literals.sol (100%) rename test/libsolidity/syntaxTests/{ => operators}/negation.sol (100%) rename test/libsolidity/syntaxTests/{ => operators}/signed_rational_modulus.sol (100%) rename test/libsolidity/syntaxTests/{ => parsing}/unexpected.sol (100%) rename test/libsolidity/syntaxTests/{ => scoping}/double_stateVariable_declaration.sol (100%) rename test/libsolidity/syntaxTests/{ => scoping}/double_variable_declaration.sol (100%) rename test/libsolidity/syntaxTests/{ => scoping}/duplicate_contract.sol (100%) rename test/libsolidity/syntaxTests/{ => scoping}/missing_state_variable.sol (100%) rename test/libsolidity/syntaxTests/{ => sizeLimits}/more_than_256_declarationerrors.sol (100%) rename test/libsolidity/syntaxTests/{ => sizeLimits}/more_than_256_importerrors.sol (100%) rename test/libsolidity/syntaxTests/{ => sizeLimits}/more_than_256_syntaxerrors.sol (100%) rename test/libsolidity/syntaxTests/{ => smoke}/smoke_test.sol (100%) rename test/libsolidity/syntaxTests/{ => structs}/empty_struct.sol (100%) rename test/libsolidity/syntaxTests/{ => super}/unimplemented_super_function.sol (100%) rename test/libsolidity/syntaxTests/{ => super}/unimplemented_super_function_derived.sol (100%) diff --git a/test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol b/test/libsolidity/semanticTests/cleanup/byte_array_to_storage_cleanup.sol similarity index 100% rename from test/libsolidity/semanticTests/byte_array_to_storage_cleanup.sol rename to test/libsolidity/semanticTests/cleanup/byte_array_to_storage_cleanup.sol diff --git a/test/libsolidity/semanticTests/dirty_calldata_bytes.sol b/test/libsolidity/semanticTests/cleanup/dirty_calldata_bytes.sol similarity index 100% rename from test/libsolidity/semanticTests/dirty_calldata_bytes.sol rename to test/libsolidity/semanticTests/cleanup/dirty_calldata_bytes.sol diff --git a/test/libsolidity/semanticTests/dirty_calldata_dynamic_array.sol b/test/libsolidity/semanticTests/cleanup/dirty_calldata_dynamic_array.sol similarity index 100% rename from test/libsolidity/semanticTests/dirty_calldata_dynamic_array.sol rename to test/libsolidity/semanticTests/cleanup/dirty_calldata_dynamic_array.sol diff --git a/test/libsolidity/semanticTests/state_var_initialization.sol b/test/libsolidity/semanticTests/constructor/state_variable_initialization.sol similarity index 100% rename from test/libsolidity/semanticTests/state_var_initialization.sol rename to test/libsolidity/semanticTests/constructor/state_variable_initialization.sol diff --git a/test/libsolidity/semanticTests/emit_three_identical_events.sol b/test/libsolidity/semanticTests/events/emit_three_identical_events.sol similarity index 100% rename from test/libsolidity/semanticTests/emit_three_identical_events.sol rename to test/libsolidity/semanticTests/events/emit_three_identical_events.sol diff --git a/test/libsolidity/semanticTests/emit_two_identical_events.sol b/test/libsolidity/semanticTests/events/emit_two_identical_events.sol similarity index 100% rename from test/libsolidity/semanticTests/emit_two_identical_events.sol rename to test/libsolidity/semanticTests/events/emit_two_identical_events.sol diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol b/test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_inheritance_init_order.sol rename to test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order.sol diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol b/test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_2.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol rename to test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_2.sol diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order_3_legacy.sol b/test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_3_legacy.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_inheritance_init_order_3_legacy.sol rename to test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_3_legacy.sol diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order_3_viaIR.sol b/test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_3_viaIR.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_inheritance_init_order_3_viaIR.sol rename to test/libsolidity/semanticTests/inheritance/constructor_inheritance_init_order_3_viaIR.sol diff --git a/test/libsolidity/semanticTests/constructor_with_params.sol b/test/libsolidity/semanticTests/inheritance/constructor_with_params.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_with_params.sol rename to test/libsolidity/semanticTests/inheritance/constructor_with_params.sol diff --git a/test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol b/test/libsolidity/semanticTests/inheritance/constructor_with_params_diamond_inheritance.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_with_params_diamond_inheritance.sol rename to test/libsolidity/semanticTests/inheritance/constructor_with_params_diamond_inheritance.sol diff --git a/test/libsolidity/semanticTests/constructor_with_params_inheritance.sol b/test/libsolidity/semanticTests/inheritance/constructor_with_params_inheritance.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_with_params_inheritance.sol rename to test/libsolidity/semanticTests/inheritance/constructor_with_params_inheritance.sol diff --git a/test/libsolidity/semanticTests/constructor_with_params_inheritance_2.sol b/test/libsolidity/semanticTests/inheritance/constructor_with_params_inheritance_2.sol similarity index 100% rename from test/libsolidity/semanticTests/constructor_with_params_inheritance_2.sol rename to test/libsolidity/semanticTests/inheritance/constructor_with_params_inheritance_2.sol diff --git a/test/libsolidity/semanticTests/interface_inheritance_conversions.sol b/test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol similarity index 100% rename from test/libsolidity/semanticTests/interface_inheritance_conversions.sol rename to test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol diff --git a/test/libsolidity/semanticTests/state_variables_init_order.sol b/test/libsolidity/semanticTests/inheritance/state_variables_init_order.sol similarity index 100% rename from test/libsolidity/semanticTests/state_variables_init_order.sol rename to test/libsolidity/semanticTests/inheritance/state_variables_init_order.sol diff --git a/test/libsolidity/semanticTests/state_variables_init_order_2.sol b/test/libsolidity/semanticTests/inheritance/state_variables_init_order_2.sol similarity index 100% rename from test/libsolidity/semanticTests/state_variables_init_order_2.sol rename to test/libsolidity/semanticTests/inheritance/state_variables_init_order_2.sol diff --git a/test/libsolidity/semanticTests/state_variables_init_order_3.sol b/test/libsolidity/semanticTests/inheritance/state_variables_init_order_3.sol similarity index 100% rename from test/libsolidity/semanticTests/state_variables_init_order_3.sol rename to test/libsolidity/semanticTests/inheritance/state_variables_init_order_3.sol diff --git a/test/libsolidity/semanticTests/empty_contract.sol b/test/libsolidity/semanticTests/isoltestTesting/empty_contract.sol similarity index 100% rename from test/libsolidity/semanticTests/empty_contract.sol rename to test/libsolidity/semanticTests/isoltestTesting/empty_contract.sol diff --git a/test/libsolidity/semanticTests/isoltestFormatting.sol b/test/libsolidity/semanticTests/isoltestTesting/isoltestFormatting.sol similarity index 100% rename from test/libsolidity/semanticTests/isoltestFormatting.sol rename to test/libsolidity/semanticTests/isoltestTesting/isoltestFormatting.sol diff --git a/test/libsolidity/semanticTests/unused_store_storage_removal_bug.sol b/test/libsolidity/semanticTests/optimizer/unused_store_storage_removal_bug.sol similarity index 100% rename from test/libsolidity/semanticTests/unused_store_storage_removal_bug.sol rename to test/libsolidity/semanticTests/optimizer/unused_store_storage_removal_bug.sol diff --git a/test/libsolidity/semanticTests/c99_scoping_activation.sol b/test/libsolidity/semanticTests/scoping/c99_scoping_activation.sol similarity index 100% rename from test/libsolidity/semanticTests/c99_scoping_activation.sol rename to test/libsolidity/semanticTests/scoping/c99_scoping_activation.sol diff --git a/test/libsolidity/semanticTests/empty_for_loop.sol b/test/libsolidity/semanticTests/statements/empty_for_loop.sol similarity index 100% rename from test/libsolidity/semanticTests/empty_for_loop.sol rename to test/libsolidity/semanticTests/statements/empty_for_loop.sol diff --git a/test/libsolidity/syntaxTests/tight_packing_literals.sol b/test/libsolidity/syntaxTests/abiEncoder/tight_packing_literals.sol similarity index 100% rename from test/libsolidity/syntaxTests/tight_packing_literals.sol rename to test/libsolidity/syntaxTests/abiEncoder/tight_packing_literals.sol diff --git a/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol b/test/libsolidity/syntaxTests/abiEncoder/tight_packing_literals_fine.sol similarity index 100% rename from test/libsolidity/syntaxTests/tight_packing_literals_fine.sol rename to test/libsolidity/syntaxTests/abiEncoder/tight_packing_literals_fine.sol diff --git a/test/libsolidity/syntaxTests/multiline_comments.sol b/test/libsolidity/syntaxTests/comments/multiline_comments.sol similarity index 100% rename from test/libsolidity/syntaxTests/multiline_comments.sol rename to test/libsolidity/syntaxTests/comments/multiline_comments.sol diff --git a/test/libsolidity/syntaxTests/constructor_this.sol b/test/libsolidity/syntaxTests/constructor/constructor_this.sol similarity index 100% rename from test/libsolidity/syntaxTests/constructor_this.sol rename to test/libsolidity/syntaxTests/constructor/constructor_this.sol diff --git a/test/libsolidity/syntaxTests/deprecated_functions.sol b/test/libsolidity/syntaxTests/globalFunctions/deprecated_functions.sol similarity index 100% rename from test/libsolidity/syntaxTests/deprecated_functions.sol rename to test/libsolidity/syntaxTests/globalFunctions/deprecated_functions.sol diff --git a/test/libsolidity/syntaxTests/cycle_checker_function_type.sol b/test/libsolidity/syntaxTests/iceRegressionTests/cycle_checker_function_type.sol similarity index 100% rename from test/libsolidity/syntaxTests/cycle_checker_function_type.sol rename to test/libsolidity/syntaxTests/iceRegressionTests/cycle_checker_function_type.sol diff --git a/test/libsolidity/syntaxTests/missing_functions_duplicate_bug.sol b/test/libsolidity/syntaxTests/iceRegressionTests/missing_functions_duplicate_bug.sol similarity index 100% rename from test/libsolidity/syntaxTests/missing_functions_duplicate_bug.sol rename to test/libsolidity/syntaxTests/iceRegressionTests/missing_functions_duplicate_bug.sol diff --git a/test/libsolidity/syntaxTests/stopAfterAnalysisError.sol b/test/libsolidity/syntaxTests/isoltestTesting/stopAfterAnalysisError.sol similarity index 100% rename from test/libsolidity/syntaxTests/stopAfterAnalysisError.sol rename to test/libsolidity/syntaxTests/isoltestTesting/stopAfterAnalysisError.sol diff --git a/test/libsolidity/syntaxTests/stopAfterParsingAnalysisErrorNotShowing.sol b/test/libsolidity/syntaxTests/isoltestTesting/stopAfterParsingAnalysisErrorNotShowing.sol similarity index 100% rename from test/libsolidity/syntaxTests/stopAfterParsingAnalysisErrorNotShowing.sol rename to test/libsolidity/syntaxTests/isoltestTesting/stopAfterParsingAnalysisErrorNotShowing.sol diff --git a/test/libsolidity/syntaxTests/stopAfterParsingError.sol b/test/libsolidity/syntaxTests/isoltestTesting/stopAfterParsingError.sol similarity index 100% rename from test/libsolidity/syntaxTests/stopAfterParsingError.sol rename to test/libsolidity/syntaxTests/isoltestTesting/stopAfterParsingError.sol diff --git a/test/libsolidity/syntaxTests/literal_comparisons.sol b/test/libsolidity/syntaxTests/literalOperations/literal_comparisons.sol similarity index 100% rename from test/libsolidity/syntaxTests/literal_comparisons.sol rename to test/libsolidity/syntaxTests/literalOperations/literal_comparisons.sol diff --git a/test/libsolidity/syntaxTests/upper_case_hex_literals.sol b/test/libsolidity/syntaxTests/literals/upper_case_hex_literals.sol similarity index 100% rename from test/libsolidity/syntaxTests/upper_case_hex_literals.sol rename to test/libsolidity/syntaxTests/literals/upper_case_hex_literals.sol diff --git a/test/libsolidity/syntaxTests/negation.sol b/test/libsolidity/syntaxTests/operators/negation.sol similarity index 100% rename from test/libsolidity/syntaxTests/negation.sol rename to test/libsolidity/syntaxTests/operators/negation.sol diff --git a/test/libsolidity/syntaxTests/signed_rational_modulus.sol b/test/libsolidity/syntaxTests/operators/signed_rational_modulus.sol similarity index 100% rename from test/libsolidity/syntaxTests/signed_rational_modulus.sol rename to test/libsolidity/syntaxTests/operators/signed_rational_modulus.sol diff --git a/test/libsolidity/syntaxTests/unexpected.sol b/test/libsolidity/syntaxTests/parsing/unexpected.sol similarity index 100% rename from test/libsolidity/syntaxTests/unexpected.sol rename to test/libsolidity/syntaxTests/parsing/unexpected.sol diff --git a/test/libsolidity/syntaxTests/double_stateVariable_declaration.sol b/test/libsolidity/syntaxTests/scoping/double_stateVariable_declaration.sol similarity index 100% rename from test/libsolidity/syntaxTests/double_stateVariable_declaration.sol rename to test/libsolidity/syntaxTests/scoping/double_stateVariable_declaration.sol diff --git a/test/libsolidity/syntaxTests/double_variable_declaration.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration.sol similarity index 100% rename from test/libsolidity/syntaxTests/double_variable_declaration.sol rename to test/libsolidity/syntaxTests/scoping/double_variable_declaration.sol diff --git a/test/libsolidity/syntaxTests/duplicate_contract.sol b/test/libsolidity/syntaxTests/scoping/duplicate_contract.sol similarity index 100% rename from test/libsolidity/syntaxTests/duplicate_contract.sol rename to test/libsolidity/syntaxTests/scoping/duplicate_contract.sol diff --git a/test/libsolidity/syntaxTests/missing_state_variable.sol b/test/libsolidity/syntaxTests/scoping/missing_state_variable.sol similarity index 100% rename from test/libsolidity/syntaxTests/missing_state_variable.sol rename to test/libsolidity/syntaxTests/scoping/missing_state_variable.sol diff --git a/test/libsolidity/syntaxTests/more_than_256_declarationerrors.sol b/test/libsolidity/syntaxTests/sizeLimits/more_than_256_declarationerrors.sol similarity index 100% rename from test/libsolidity/syntaxTests/more_than_256_declarationerrors.sol rename to test/libsolidity/syntaxTests/sizeLimits/more_than_256_declarationerrors.sol diff --git a/test/libsolidity/syntaxTests/more_than_256_importerrors.sol b/test/libsolidity/syntaxTests/sizeLimits/more_than_256_importerrors.sol similarity index 100% rename from test/libsolidity/syntaxTests/more_than_256_importerrors.sol rename to test/libsolidity/syntaxTests/sizeLimits/more_than_256_importerrors.sol diff --git a/test/libsolidity/syntaxTests/more_than_256_syntaxerrors.sol b/test/libsolidity/syntaxTests/sizeLimits/more_than_256_syntaxerrors.sol similarity index 100% rename from test/libsolidity/syntaxTests/more_than_256_syntaxerrors.sol rename to test/libsolidity/syntaxTests/sizeLimits/more_than_256_syntaxerrors.sol diff --git a/test/libsolidity/syntaxTests/smoke_test.sol b/test/libsolidity/syntaxTests/smoke/smoke_test.sol similarity index 100% rename from test/libsolidity/syntaxTests/smoke_test.sol rename to test/libsolidity/syntaxTests/smoke/smoke_test.sol diff --git a/test/libsolidity/syntaxTests/empty_struct.sol b/test/libsolidity/syntaxTests/structs/empty_struct.sol similarity index 100% rename from test/libsolidity/syntaxTests/empty_struct.sol rename to test/libsolidity/syntaxTests/structs/empty_struct.sol diff --git a/test/libsolidity/syntaxTests/unimplemented_super_function.sol b/test/libsolidity/syntaxTests/super/unimplemented_super_function.sol similarity index 100% rename from test/libsolidity/syntaxTests/unimplemented_super_function.sol rename to test/libsolidity/syntaxTests/super/unimplemented_super_function.sol diff --git a/test/libsolidity/syntaxTests/unimplemented_super_function_derived.sol b/test/libsolidity/syntaxTests/super/unimplemented_super_function_derived.sol similarity index 100% rename from test/libsolidity/syntaxTests/unimplemented_super_function_derived.sol rename to test/libsolidity/syntaxTests/super/unimplemented_super_function_derived.sol diff --git a/test/scripts/test_bytecodecompare_prepare_report.py b/test/scripts/test_bytecodecompare_prepare_report.py index 28a89ec31..e1987c60c 100644 --- a/test/scripts/test_bytecodecompare_prepare_report.py +++ b/test/scripts/test_bytecodecompare_prepare_report.py @@ -24,7 +24,7 @@ SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_PATH = FIXTURE_DIR / 'smt_contract_with_mixed_newlines.sol' SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_CODE = load_fixture(SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_PATH) -SYNTAX_SMOKE_TEST_SOL_PATH = LIBSOLIDITY_TEST_DIR / 'syntaxTests/smoke_test.sol' +SYNTAX_SMOKE_TEST_SOL_PATH = LIBSOLIDITY_TEST_DIR / 'syntaxTests/smoke/smoke_test.sol' SYNTAX_SMOKE_TEST_SOL_CODE = load_libsolidity_test_case(SYNTAX_SMOKE_TEST_SOL_PATH) LIBRARY_INHERITED2_SOL_JSON_OUTPUT = load_fixture('library_inherited2_sol_json_output.json') @@ -58,19 +58,19 @@ def test_format_report(self): contract_reports=[ ContractReport( contract_name='A', - file_name=Path('syntaxTests/smoke_test.sol'), + file_name=Path('syntaxTests/smoke/smoke_test.sol'), bytecode=None, metadata=None, ), ContractReport( contract_name='B', - file_name=Path('syntaxTests/smoke_test.sol'), + file_name=Path('syntaxTests/smoke/smoke_test.sol'), bytecode=None, metadata='{"language":"Solidity"}', ), ContractReport( contract_name='Lib', - file_name=Path('syntaxTests/smoke_test.sol'), + file_name=Path('syntaxTests/smoke/smoke_test.sol'), bytecode='60566050600b828282398051', metadata=None, ), From 640dd41db40cfa43c5d7209e242352ea75774e49 Mon Sep 17 00:00:00 2001 From: XxAlex74xX <30472093+XxAlex74xX@users.noreply.github.com> Date: Mon, 27 Jan 2025 09:37:09 +0100 Subject: [PATCH 0636/1340] Update natspec-format.rst --- docs/natspec-format.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst index f19106483..2f0d1d6b4 100644 --- a/docs/natspec-format.rst +++ b/docs/natspec-format.rst @@ -209,7 +209,7 @@ JSON file as output for the ``Tree`` contract: "age(uint256)" : { "notice" : "Calculate tree age in years, rounded up, for live trees" - } + }, "leaves()" : { "notice" : "Returns the amount of leaves the tree has." From 57342666ca9b03499d8299b3ff269494647b6787 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 10 Jan 2025 21:20:56 +0100 Subject: [PATCH 0637/1340] SMTChecker: Fix crash in BMC engine regarding state variables Previously, analyzing a call to a getter to a contract then has not been analyzed yet with BMC would result in a crash because BMC would not know about the state variable being accessed. To fix this, we let BMC know about all state variables in all contracts during initialization. --- Changelog.md | 1 + libsolidity/formal/BMC.cpp | 4 +++- libsolidity/formal/SMTEncoder.cpp | 8 +++++++ libsolidity/formal/SMTEncoder.h | 3 +++ .../cross_contract_getter_call.sol | 22 +++++++++++++++++++ 5 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/smtCheckerTests/bmc_coverage/cross_contract_getter_call.sol diff --git a/Changelog.md b/Changelog.md index c00adf0fd..35f9b83be 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,7 @@ Compiler Features: Bugfixes: * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. + * SMTChecker: Fix SMT logic error when analyzing cross-contract getter call with BMC. * SMTChecker: Fix SMT logic error when initializing a fixed-sized-bytes array using string literals. * SMTChecker: Fix SMT logic error when translating invariants involving array store and select operations. * SMTChecker: Fix wrong encoding of string literals as arguments of ``ecrecover`` precompile. diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 679309766..d7bad10e7 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -93,7 +93,9 @@ void BMC::analyze(SourceUnit const& _source, std::map const& _sources) +{ + for (auto const& source: _sources) + for (auto const& node: source->nodes()) + if (auto contract = dynamic_cast(node.get())) + createStateVariables(*contract); +} + smt::SymbolicState& SMTEncoder::state() { return m_context.state(); diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index 3248f1390..f01f6802c 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -439,6 +439,9 @@ class SMTEncoder: public ASTConstVisitor /// Create symbolic variables for the free constants in all @param _sources. void createFreeConstants(std::set const& _sources); + /// Create symbolic variables for all state variables for all contracts in all @param _sources. + void createStateVariables(std::set const& _sources); + /// @returns a note to be added to warnings. std::string extraComment(); diff --git a/test/libsolidity/smtCheckerTests/bmc_coverage/cross_contract_getter_call.sol b/test/libsolidity/smtCheckerTests/bmc_coverage/cross_contract_getter_call.sol new file mode 100644 index 000000000..f36647ed2 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/bmc_coverage/cross_contract_getter_call.sol @@ -0,0 +1,22 @@ +contract C { + D internal d; + constructor() { + d = new D(); + } + function invokeAndCheck() public { + d.set(); + assert(d.n() <= 1); + } +} + +contract D { + uint public n; + function set() external { + n = 1; + } +} +// ==== +// SMTEngine: bmc +// ---- +// Warning 8729: (51-58): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. +// Warning 4661: (112-130): BMC: Assertion violation happens here. From 5d27b0f94ba5d7240aeb2bf8413f6f847afb45a9 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 7 Jan 2025 16:39:19 +0100 Subject: [PATCH 0638/1340] eof: Assert against legacy identifiers/members availability in EOF context. --- .../codegen/ir/IRGeneratorForStatements.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 3ae151593..c716c43a6 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1529,6 +1529,15 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) case FunctionType::Kind::BlockHash: case FunctionType::Kind::BlobHash: { + solAssert( + !m_context.eofVersion().has_value() || functionType->kind() != FunctionType::Kind::GasLeft, + "EOF does not support gasleft." + ); + solAssert( + !m_context.eofVersion().has_value() || functionType->kind() != FunctionType::Kind::Selfdestruct, + "EOF does not support selfdestruct." + ); + static std::map functions = { {FunctionType::Kind::GasLeft, "gas"}, {FunctionType::Kind::Selfdestruct, "selfdestruct"}, @@ -1845,6 +1854,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) ")\n"; else if (member == "code") { + solAssert(!m_context.eofVersion().has_value(), "EOF does not support address.code."); std::string externalCodeFunction = m_utils.externalCodeFunction(); define(_memberAccess) << externalCodeFunction << @@ -1853,10 +1863,13 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) ")\n"; } else if (member == "codehash") + { + solAssert(!m_context.eofVersion().has_value(), "EOF does not support address.codehash."); define(_memberAccess) << "extcodehash(" << expressionAsType(_memberAccess.expression(), *TypeProvider::address()) << ")\n"; + } else if (std::set{"send", "transfer"}.count(member)) { solAssert(dynamic_cast(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable); @@ -1973,6 +1986,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) solAssert(false, "Blockhash has been removed."); else if (member == "creationCode" || member == "runtimeCode") { + solAssert(!m_context.eofVersion().has_value(), "EOF does not support \"" + member + "\"."); Type const* arg = dynamic_cast(*_memberAccess.expression().annotation().type).typeArgument(); auto const& contractType = dynamic_cast(*arg); solAssert(!contractType.isSuper()); From 1832fbd732f387b6e0be72bf96f0bd082acb9515 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Mon, 22 Jul 2024 19:15:14 +0200 Subject: [PATCH 0639/1340] Enable ethdebug debug info and output selection. --- libevmasm/AbstractAssemblyStack.h | 4 + libevmasm/Assembly.cpp | 2 +- libevmasm/EVMAssemblyStack.cpp | 19 + libevmasm/EVMAssemblyStack.h | 6 + liblangutil/DebugInfoSelection.cpp | 12 +- liblangutil/DebugInfoSelection.h | 15 +- libsolidity/codegen/ir/IRGenerator.cpp | 3 +- libsolidity/interface/CompilerStack.cpp | 33 ++ libsolidity/interface/CompilerStack.h | 17 + libsolidity/interface/StandardCompiler.cpp | 88 ++- libyul/YulStack.cpp | 14 +- libyul/YulStack.h | 4 + solc/CommandLineInterface.cpp | 64 +++ solc/CommandLineInterface.h | 2 + solc/CommandLineParser.cpp | 84 ++- solc/CommandLineParser.h | 4 + test/cmdlineTests/ethdebug/args | 1 + test/cmdlineTests/ethdebug/input.sol | 7 + test/cmdlineTests/ethdebug/output | 42 ++ .../ethdebug_and_ethdebug_runtime/args | 1 + .../ethdebug_and_ethdebug_runtime/input.sol | 7 + .../ethdebug_and_ethdebug_runtime/output | 44 ++ test/cmdlineTests/ethdebug_runtime/args | 1 + test/cmdlineTests/ethdebug_runtime/input.sol | 7 + test/cmdlineTests/ethdebug_runtime/output | 42 ++ .../input.json | 24 + .../output.json | 214 ++++++++ .../input.json | 24 + .../output.json | 226 ++++++++ .../input.json | 24 + .../output.json | 214 ++++++++ .../standard_yul_ethdebug_bytecode/args | 1 + .../standard_yul_ethdebug_bytecode/in.yul | 17 + .../standard_yul_ethdebug_bytecode/input.json | 14 + .../output.json | 31 ++ .../args | 1 + .../in.yul | 17 + .../input.json | 11 + .../output.json | 11 + test/cmdlineTests/yul_ethdebug/args | 1 + test/cmdlineTests/yul_ethdebug/input.yul | 18 + test/cmdlineTests/yul_ethdebug/output | 18 + test/cmdlineTests/yul_ethdebug_runtime/args | 1 + test/cmdlineTests/yul_ethdebug_runtime/err | 1 + test/cmdlineTests/yul_ethdebug_runtime/exit | 1 + .../yul_ethdebug_runtime/input.yul | 18 + test/libsolidity/StandardCompiler.cpp | 511 ++++++++++++++++++ test/libyul/Common.cpp | 2 +- test/libyul/EVMCodeTransformTest.cpp | 2 +- test/libyul/ObjectParser.cpp | 2 +- test/solc/CommandLineInterface.cpp | 350 ++++++++++++ test/solc/CommandLineParser.cpp | 43 ++ .../ossfuzz/strictasm_assembly_ossfuzz.cpp | 2 +- test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 2 +- test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp | 2 +- 55 files changed, 2308 insertions(+), 18 deletions(-) create mode 100644 test/cmdlineTests/ethdebug/args create mode 100644 test/cmdlineTests/ethdebug/input.sol create mode 100644 test/cmdlineTests/ethdebug/output create mode 100644 test/cmdlineTests/ethdebug_and_ethdebug_runtime/args create mode 100644 test/cmdlineTests/ethdebug_and_ethdebug_runtime/input.sol create mode 100644 test/cmdlineTests/ethdebug_and_ethdebug_runtime/output create mode 100644 test/cmdlineTests/ethdebug_runtime/args create mode 100644 test/cmdlineTests/ethdebug_runtime/input.sol create mode 100644 test/cmdlineTests/ethdebug_runtime/output create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode/output.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/output.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_bytecode/args create mode 100644 test/cmdlineTests/standard_yul_ethdebug_bytecode/in.yul create mode 100644 test/cmdlineTests/standard_yul_ethdebug_bytecode/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_bytecode/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/args create mode 100644 test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul create mode 100644 test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/output.json create mode 100644 test/cmdlineTests/yul_ethdebug/args create mode 100644 test/cmdlineTests/yul_ethdebug/input.yul create mode 100644 test/cmdlineTests/yul_ethdebug/output create mode 100644 test/cmdlineTests/yul_ethdebug_runtime/args create mode 100644 test/cmdlineTests/yul_ethdebug_runtime/err create mode 100644 test/cmdlineTests/yul_ethdebug_runtime/exit create mode 100644 test/cmdlineTests/yul_ethdebug_runtime/input.yul diff --git a/libevmasm/AbstractAssemblyStack.h b/libevmasm/AbstractAssemblyStack.h index 278edf5c2..c4eb804ee 100644 --- a/libevmasm/AbstractAssemblyStack.h +++ b/libevmasm/AbstractAssemblyStack.h @@ -40,6 +40,10 @@ class AbstractAssemblyStack virtual std::string const* sourceMapping(std::string const& _contractName) const = 0; virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const = 0; + virtual Json ethdebug(std::string const& _contractName) const = 0; + virtual Json ethdebugRuntime(std::string const& _contractName) const = 0; + virtual Json ethdebug() const = 0; + virtual Json assemblyJSON(std::string const& _contractName) const = 0; virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const = 0; diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 22bff5415..ac9f14b15 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -444,7 +444,7 @@ std::string Assembly::assemblyString( { std::ostringstream tmp; assemblyStream(tmp, _debugInfoSelection, "", _sourceCodes); - return tmp.str(); + return (_debugInfoSelection.ethdebug ? "/// ethdebug: enabled\n" : "") + tmp.str(); } Json Assembly::assemblyJSON(std::map const& _sourceIndices, bool _includeSourceList) const diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index df4517fc5..f8b8b4b54 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -103,6 +103,25 @@ std::string const* EVMAssemblyStack::runtimeSourceMapping(std::string const& _co return &m_runtimeSourceMapping; } +Json EVMAssemblyStack::ethdebug(std::string const& _contractName) const +{ + solAssert(_contractName == m_name); + solAssert(m_ethdebug != nullptr); + return *m_ethdebug; +} + +Json EVMAssemblyStack::ethdebugRuntime(std::string const& _contractName) const +{ + solAssert(_contractName == m_name); + solAssert(m_ethdebugRuntime != nullptr); + return *m_ethdebugRuntime; +} + +Json EVMAssemblyStack::ethdebug() const +{ + return {}; +} + Json EVMAssemblyStack::assemblyJSON(std::string const& _contractName) const { solAssert(_contractName == m_name); diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index 55c9fd684..e3888afad 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -59,6 +59,10 @@ class EVMAssemblyStack: public AbstractAssemblyStack std::string const* sourceMapping(std::string const& _contractName) const override; std::string const* runtimeSourceMapping(std::string const& _contractName) const override; + Json ethdebug(std::string const& _contractName) const override; + Json ethdebugRuntime(std::string const& _contractName) const override; + Json ethdebug() const override; + Json assemblyJSON(std::string const& _contractName) const override; std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const override; @@ -87,6 +91,8 @@ class EVMAssemblyStack: public AbstractAssemblyStack langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default(); std::string m_sourceMapping; std::string m_runtimeSourceMapping; + std::unique_ptr m_ethdebug; + std::unique_ptr m_ethdebugRuntime; }; } // namespace solidity::evmasm diff --git a/liblangutil/DebugInfoSelection.cpp b/liblangutil/DebugInfoSelection.cpp index ad0b615c1..dfd623646 100644 --- a/liblangutil/DebugInfoSelection.cpp +++ b/liblangutil/DebugInfoSelection.cpp @@ -49,6 +49,14 @@ DebugInfoSelection const DebugInfoSelection::Only(bool DebugInfoSelection::* _me return result; } +DebugInfoSelection const DebugInfoSelection::AllExcept(std::vector const& _members) noexcept +{ + DebugInfoSelection result = All(); + for (bool DebugInfoSelection::* member: _members) + result.*member = false; + return result; +} + std::optional DebugInfoSelection::fromString(std::string_view _input) { // TODO: Make more stuff constexpr and make it a static_assert(). @@ -56,7 +64,7 @@ std::optional DebugInfoSelection::fromString(std::string_vie solAssert(componentMap().count("none") == 0, ""); if (_input == "all") - return All(); + return AllExceptExperimental(); if (_input == "none") return None(); @@ -74,7 +82,7 @@ std::optional DebugInfoSelection::fromComponents( for (auto const& component: _componentNames) { if (component == "*") - return (_acceptWildcards ? std::make_optional(DebugInfoSelection::All()) : std::nullopt); + return (_acceptWildcards ? std::make_optional(AllExceptExperimental()) : std::nullopt); if (!selection.enable(component)) return std::nullopt; diff --git a/liblangutil/DebugInfoSelection.h b/liblangutil/DebugInfoSelection.h index 3a9432de6..daf4b950f 100644 --- a/liblangutil/DebugInfoSelection.h +++ b/liblangutil/DebugInfoSelection.h @@ -42,7 +42,9 @@ struct DebugInfoSelection static DebugInfoSelection const All(bool _value = true) noexcept; static DebugInfoSelection const None() noexcept { return All(false); } static DebugInfoSelection const Only(bool DebugInfoSelection::* _member) noexcept; - static DebugInfoSelection const Default() noexcept { return All(); } + static DebugInfoSelection const Default() noexcept { return AllExceptExperimental(); } + static DebugInfoSelection const AllExcept(std::vector const& _members) noexcept; + static DebugInfoSelection const AllExceptExperimental() noexcept { return AllExcept({&DebugInfoSelection::ethdebug}); } static std::optional fromString(std::string_view _input); static std::optional fromComponents( @@ -72,13 +74,24 @@ struct DebugInfoSelection {"location", &DebugInfoSelection::location}, {"snippet", &DebugInfoSelection::snippet}, {"ast-id", &DebugInfoSelection::astID}, + {"ethdebug", &DebugInfoSelection::ethdebug}, }; return components; } + std::vector selectedNames() const + { + std::vector result; + for (auto const& component: componentMap()) + if (this->*(component.second)) + result.push_back(component.first); + return result; + } + bool location = false; ///< Include source location. E.g. `@src 3:50:100` bool snippet = false; ///< Include source code snippet next to location. E.g. `@src 3:50:100 "contract C {..."` bool astID = false; ///< Include ID of the Solidity AST node. E.g. `@ast-id 15` + bool ethdebug = false; ///< Include ethdebug related debug information. }; std::ostream& operator<<(std::ostream& _stream, DebugInfoSelection const& _selection); diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index ae2a12c71..dd6503ca1 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -120,7 +120,7 @@ std::string IRGenerator::generate( ); }; - Whiskers t(R"( + Whiskers t(R"(/// ethdebug: enabled /// @use-src object "" { code { @@ -164,6 +164,7 @@ std::string IRGenerator::generate( for (VariableDeclaration const* var: ContractType(_contract).immutableVariables()) m_context.registerImmutableVariable(*var); + t("isEthdebugEnabled", m_context.debugInfoSelection().ethdebug); t("CreationObject", IRNames::creationObject(_contract)); t("sourceLocationCommentCreation", dispenseLocationComment(_contract)); t("library", _contract.isLibrary()); diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 2a859ea24..1791ad45a 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1181,6 +1181,39 @@ Json CompilerStack::interfaceSymbols(std::string const& _contractName) const return interfaceSymbols; } +Json CompilerStack::ethdebug() const +{ + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + solAssert(!m_contracts.empty()); + Json result = Json::object(); + result["sources"] = sourceNames(); + return result; +} + +Json CompilerStack::ethdebug(std::string const& _contractName) const +{ + return ethdebug(contract(_contractName), /* runtime */ false); +} + +Json CompilerStack::ethdebugRuntime(std::string const& _contractName) const +{ + return ethdebug(contract(_contractName), /* runtime */ true); +} + +Json CompilerStack::ethdebug(Contract const& _contract, bool _runtime) const +{ + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + solAssert(_contract.contract); + solUnimplementedAssert(!isExperimentalSolidity()); + if (_runtime) + { + Json result = Json::object(); + return result; + } + Json result = Json::object(); + return result; +} + bytes CompilerStack::cborMetadata(std::string const& _contractName, bool _forIR) const { solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index f36eedde0..2731787a4 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -391,6 +391,18 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// @returns a JSON object with the three members ``methods``, ``events``, ``errors``. Each is a map, mapping identifiers (hashes) to function names. Json interfaceSymbols(std::string const& _contractName) const; + /// @returns a JSON representing the ethdebug data of the specified contract. + /// Prerequisite: Successful call to parse or compile. + Json ethdebug(std::string const& _contractName) const override; + + /// @returns a JSON representing the ethdebug data of the specified contract. + /// Prerequisite: Successful call to parse or compile. + Json ethdebugRuntime(std::string const& _contractName) const override; + + /// @returns a JSON representing the top-level ethdebug data (types, etc.). + /// Prerequisite: Successful call to parse or compile. + Json ethdebug() const override; + /// @returns the Contract Metadata matching the pipeline selected using the viaIR setting. std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); } @@ -571,6 +583,11 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// This will generate the metadata and store it in the Contract object if it is not present yet. std::string const& metadata(Contract const& _contract) const; + /// @returns the Contract ethdebug data. + /// This will generate the JSON object and store it in the Contract object if it is not present yet. + /// Prerequisite: Successful call to parse or compile. + Json ethdebug(Contract const& _contract, bool _runtime) const; + /// @returns the offset of the entry point of the given function into the list of assembly items /// or zero if it is not found or does not exist. size_t functionEntryPoint( diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 9357310c0..bcdb2901d 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -165,7 +165,7 @@ bool hashMatchesContent(std::string const& _hash, std::string const& _content) bool isArtifactRequested(Json const& _outputSelection, std::string const& _artifact, bool _wildcardMatchesExperimental) { - static std::set experimental{"ir", "irAst", "irOptimized", "irOptimizedAst", "yulCFGJson"}; + static std::set experimental{"ir", "irAst", "irOptimized", "irOptimizedAst", "yulCFGJson", "ethdebug"}; for (auto const& selectedArtifactJson: _outputSelection) { std::string const& selectedArtifact = selectedArtifactJson.get(); @@ -173,12 +173,20 @@ bool isArtifactRequested(Json const& _outputSelection, std::string const& _artif _artifact == selectedArtifact || boost::algorithm::starts_with(_artifact, selectedArtifact + ".") ) + { + if (_artifact.find("ethdebug") != std::string::npos) + // only accept exact matches for ethdebug, e.g. evm.bytecode.ethdebug + return selectedArtifact == _artifact; return true; + } else if (selectedArtifact == "*") { // TODO: yulCFGJson is only experimental now, so it should not be matched by "*". if (_artifact == "yulCFGJson") return false; + // TODO: everything ethdebug related is only experimental for now, so it should not be matched by "*". + if (_artifact.find("ethdebug") != std::string::npos) + return false; // "ir", "irOptimized" can only be matched by "*" if activated. if (experimental.count(_artifact) == 0 || _wildcardMatchesExperimental) return true; @@ -237,7 +245,7 @@ bool isArtifactRequested(Json const& _outputSelection, std::string const& _file, std::vector evmObjectComponents(std::string const& _objectKind) { solAssert(_objectKind == "bytecode" || _objectKind == "deployedBytecode", ""); - std::vector components{"", ".object", ".opcodes", ".sourceMap", ".functionDebugData", ".generatedSources", ".linkReferences"}; + std::vector components{"", ".object", ".opcodes", ".sourceMap", ".functionDebugData", ".generatedSources", ".linkReferences", ".ethdebug"}; if (_objectKind == "deployedBytecode") components.push_back(".immutableReferences"); return util::applyMap(components, [&](auto const& _s) { return "evm." + _objectKind + _s; }); @@ -253,7 +261,7 @@ bool isBinaryRequested(Json const& _outputSelection) static std::vector const outputsThatRequireBinaries = std::vector{ "*", "ir", "irAst", "irOptimized", "irOptimizedAst", "yulCFGJson", - "evm.gasEstimates", "evm.legacyAssembly", "evm.assembly" + "evm.gasEstimates", "evm.legacyAssembly", "evm.assembly", "ethdebug" } + evmObjectComponents("bytecode") + evmObjectComponents("deployedBytecode"); for (auto const& fileRequests: _outputSelection) @@ -283,6 +291,21 @@ bool isEvmBytecodeRequested(Json const& _outputSelection) return false; } +/// @returns true if ethdebug was requested. +bool isEthdebugRequested(Json const& _outputSelection) +{ + if (!_outputSelection.is_object()) + return false; + + for (auto const& fileRequests: _outputSelection) + for (auto const& requests: fileRequests) + for (auto const& request: requests) + if (request == "evm.bytecode.ethdebug" || request == "evm.deployedBytecode.ethdebug") + return true; + + return false; +} + /// @returns The set of selected contracts, along with their compiler pipeline configuration, based /// on outputs requested in the JSON. Translates wildcards to the ones understood by CompilerStack. /// Note that as an exception, '*' does not yet match "ir", "irAst", "irOptimized" or "irOptimizedAst". @@ -1152,6 +1175,35 @@ std::variant StandardCompiler::parseI ret.modelCheckerSettings.timeout = modelCheckerSettings["timeout"].get(); } + if ((ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug) || isEthdebugRequested(ret.outputSelection)) + { + if (ret.language != "Solidity" && ret.language != "Yul") + return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' 'ethdebug' is only supported for languages 'Solidity' and 'Yul'."); + } + + if (isEthdebugRequested(ret.outputSelection)) + { + if (ret.language == "Solidity" && !ret.viaIR) + return formatFatalError(Error::Type::FatalError, "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set."); + + if (!ret.debugInfoSelection.has_value()) + { + ret.debugInfoSelection = DebugInfoSelection::Default(); + ret.debugInfoSelection->enable("ethdebug"); + } + else + { + if (!ret.debugInfoSelection->ethdebug && ret.language == "Solidity") + return formatFatalError(Error::Type::FatalError, "'ethdebug' needs to be enabled in 'settings.debug.debugInfo', if 'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' was selected as output."); + } + } + + if ( + ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug && ret.language == "Solidity" && + !pipelineConfig(ret.outputSelection)[""][""].irCodegen && !isEthdebugRequested(ret.outputSelection) + ) + return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected."); + return {std::move(ret)}; } @@ -1235,6 +1287,8 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in creationJSON["functionDebugData"] = formatFunctionDebugData(stack.object(sourceName).functionDebugData); if (evmCreationArtifactRequested("linkReferences")) creationJSON["linkReferences"] = formatLinkReferences(stack.object(sourceName).linkReferences); + if (evmCreationArtifactRequested("ethdebug")) + creationJSON["ethdebug"] = stack.ethdebug(sourceName); evmData["bytecode"] = creationJSON; } @@ -1263,6 +1317,8 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in deployedJSON["linkReferences"] = formatLinkReferences(stack.runtimeObject(sourceName).linkReferences); if (evmDeployedArtifactRequested("immutableReferences")) deployedJSON["immutableReferences"] = formatImmutableReferences(stack.runtimeObject(sourceName).immutableReferences); + if (evmDeployedArtifactRequested("ethdebug")) + deployedJSON["ethdebug"] = stack.ethdebugRuntime(sourceName); evmData["deployedBytecode"] = deployedJSON; } @@ -1503,6 +1559,8 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu creationJSON["linkReferences"] = formatLinkReferences(compilerStack.object(contractName).linkReferences); if (evmCreationArtifactRequested("generatedSources")) creationJSON["generatedSources"] = compilerStack.generatedSources(contractName, /* _runtime */ false); + if (evmCreationArtifactRequested("ethdebug")) + creationJSON["ethdebug"] = compilerStack.ethdebug(contractName); evmData["bytecode"] = creationJSON; } @@ -1533,6 +1591,8 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu deployedJSON["immutableReferences"] = formatImmutableReferences(compilerStack.runtimeObject(contractName).immutableReferences); if (evmDeployedArtifactRequested("generatedSources")) deployedJSON["generatedSources"] = compilerStack.generatedSources(contractName, /* _runtime */ true); + if (evmDeployedArtifactRequested("ethdebug")) + deployedJSON["ethdebug"] = compilerStack.ethdebugRuntime(contractName); evmData["deployedBytecode"] = deployedJSON; } @@ -1546,6 +1606,10 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu contractsOutput[file][name] = contractData; } } + + if (isEthdebugRequested(_inputsAndSettings.outputSelection)) + output["ethdebug"] = compilerStack.ethdebug(); + if (!contractsOutput.empty()) output["contracts"] = contractsOutput; @@ -1597,6 +1661,19 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) return output; } + for (auto const& fileRequests: _inputsAndSettings.outputSelection) + for (auto const& requests: fileRequests) + for (auto const& request: requests) + if (request == "evm.deployedBytecode.ethdebug") + { + output["errors"].emplace_back(formatError( + Error::Type::JSONError, + "general", + "\"evm.deployedBytecode.ethdebug\" cannot be used for Yul." + )); + return output; + } + YulStack stack( _inputsAndSettings.evmVersion, _inputsAndSettings.eofVersion, @@ -1687,6 +1764,8 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) bytecodeJSON["functionDebugData"] = formatFunctionDebugData(selectedObject.bytecode->functionDebugData); if (evmArtifactRequested(kind, "linkReferences")) bytecodeJSON["linkReferences"] = formatLinkReferences(selectedObject.bytecode->linkReferences); + if (evmArtifactRequested(kind, "ethdebug")) + bytecodeJSON["ethdebug"] = selectedObject.ethdebug; if (isDeployed && evmArtifactRequested(kind, "immutableReferences")) bytecodeJSON["immutableReferences"] = formatImmutableReferences(selectedObject.bytecode->immutableReferences); output["contracts"][sourceName][contractName]["evm"][kind] = bytecodeJSON; @@ -1700,6 +1779,9 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "yulCFGJson", wildcardMatchesExperimental)) output["contracts"][sourceName][contractName]["yulCFGJson"] = stack.cfgJson(); + if (isEthdebugRequested(_inputsAndSettings.outputSelection)) + output["ethdebug"] = stack.ethdebug(); + return output; } diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index aa8a32820..f58705e9c 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -273,6 +273,7 @@ YulStack::assembleWithDeployed(std::optional _deployName) {{m_charStream->name(), 0}} ); } + creationObject.ethdebug["not yet implemented @ MachineAssemblyObject::ethdebug"] = true; if (deployedAssembly) { @@ -368,7 +369,7 @@ std::string YulStack::print() const yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->hasCode(), ""); - return m_parserResult->toString( + return (m_debugInfoSelection.ethdebug ? "/// ethdebug: enabled\n" : "") + m_parserResult->toString( m_debugInfoSelection, m_soliditySourceProvider ) + "\n"; @@ -382,6 +383,17 @@ Json YulStack::astJson() const return m_parserResult->toJson(); } +Json YulStack::ethdebug() const +{ + yulAssert(m_parserResult, ""); + yulAssert(m_parserResult->hasCode(), ""); + yulAssert(m_parserResult->analysisInfo, ""); + + Json result = Json::object(); + result["sources"] = Json::array({m_charStream->name()}); + return result; +} + Json YulStack::cfgJson() const { yulAssert(m_parserResult, ""); diff --git a/libyul/YulStack.h b/libyul/YulStack.h index 94688fddc..b745f1b80 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -60,6 +60,7 @@ struct MachineAssemblyObject std::shared_ptr bytecode; std::shared_ptr assembly; std::unique_ptr sourceMappings; + Json ethdebug = Json::object(); }; /* @@ -148,6 +149,9 @@ class YulStack: public langutil::CharStreamProvider // return the JSON representation of the YuL CFG (experimental) Json cfgJson() const; + /// @returns a JSON representing the top-level ethdebug data (types, etc.). + Json ethdebug() const; + /// Return the parsed and analyzed object. std::shared_ptr parserResult() const; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index f2bb4af10..d97e56638 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -151,6 +151,8 @@ static bool needsHumanTargetedStdout(CommandLineOptions const& _options) _options.compiler.outputs.yulCFGJson || _options.compiler.outputs.binary || _options.compiler.outputs.binaryRuntime || + _options.compiler.outputs.ethdebug || + _options.compiler.outputs.ethdebugRuntime || _options.compiler.outputs.metadata || _options.compiler.outputs.natspecUser || _options.compiler.outputs.natspecDev || @@ -551,6 +553,44 @@ void CommandLineInterface::handleGasEstimation(std::string const& _contract) } } +void CommandLineInterface::handleEthdebug() +{ + if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + { + std::string ethdebug{jsonPrint(removeNullMembers(m_compiler->ethdebug()), m_options.formatting.json)}; + if (!m_options.output.dir.empty()) + createFile("ethdebug.json", ethdebug); + else + sout() << "======= Debug Data (ethdebug/format/info/resources) =======" << std::endl << ethdebug << std::endl; + } +} + +void CommandLineInterface::handleEthdebug(std::string const& _contract) +{ + solAssert(CompilerInputModes.count(m_options.input.mode) == 1); + + if (!(m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime)) + return; + + if (m_options.compiler.outputs.ethdebug) + { + std::string ethdebug{jsonPrint(removeNullMembers(m_compiler->ethdebug(_contract)), m_options.formatting.json)}; + if (!m_options.output.dir.empty()) + createFile(m_compiler->filesystemFriendlyName(_contract) + "_ethdebug.json", ethdebug); + else + sout() << "Debug Data (ethdebug/format/program):" << std::endl << ethdebug << std::endl; + } + + if (m_options.compiler.outputs.ethdebugRuntime) + { + std::string ethdebugRuntime{jsonPrint(removeNullMembers(m_compiler->ethdebugRuntime(_contract)), m_options.formatting.json)}; + if (!m_options.output.dir.empty()) + createFile(m_compiler->filesystemFriendlyName(_contract) + "_ethdebug-runtime.json", ethdebugRuntime); + else + sout() << "Debug Data of the runtime part (ethdebug/format/program):" << std::endl << ethdebugRuntime << std::endl; + } +} + void CommandLineInterface::readInputFiles() { solAssert(!m_standardJsonInput.has_value()); @@ -912,6 +952,8 @@ void CommandLineInterface::compile() m_options.compiler.outputs.opcodes || m_options.compiler.outputs.binary || m_options.compiler.outputs.binaryRuntime || + m_options.compiler.outputs.ethdebug || + m_options.compiler.outputs.ethdebugRuntime || (m_options.compiler.combinedJsonRequests && ( m_options.compiler.combinedJsonRequests->binary || m_options.compiler.combinedJsonRequests->binaryRuntime || @@ -1290,6 +1332,17 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y solThrow(CommandLineExecutionError, ""); } + if (m_options.compiler.outputs.ethdebug) + { + Json ethdebugObject = Json::object(); + ethdebugObject["sources"] = m_fileReader.sourceUnits() | ranges::views::keys; + sout() << "======= Debug Data (ethdebug/format/info/resources) =======" << std::endl; + sout() << util::jsonPrint( + ethdebugObject, + m_options.formatting.json + ) << std::endl; + } + for (auto const& [sourceUnitName, yulSource]: m_fileReader.sourceUnits()) { solAssert(_targetMachine == yul::YulStack::Machine::EVM); @@ -1345,6 +1398,14 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y m_options.formatting.json ) << std::endl; } + if (m_options.compiler.outputs.ethdebug) + { + sout() << std::endl << "Debug Data (ethdebug/format/program):" << std::endl; + sout() << util::jsonPrint( + object.ethdebug, + m_options.formatting.json + ) << std::endl; + } } } @@ -1357,6 +1418,8 @@ void CommandLineInterface::outputCompilationResults() // do we need AST output? handleAst(); + handleEthdebug(); + CompilerOutputs astOutputSelection; astOutputSelection.astCompactJson = true; if (m_options.compiler.outputs != CompilerOutputs() && m_options.compiler.outputs != astOutputSelection) @@ -1388,6 +1451,7 @@ void CommandLineInterface::outputCompilationResults() handleTransientStorageLayout(contract); handleNatspec(true, contract); handleNatspec(false, contract); + handleEthdebug(contract); } // end of contracts iteration } diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index ce30a4d71..b8a10c372 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -101,6 +101,7 @@ class CommandLineInterface void handleCombinedJSON(); void handleAst(); + void handleEthdebug(); void handleEVMAssembly(std::string const& _contract); void handleBinary(std::string const& _contract); void handleOpcode(std::string const& _contract); @@ -117,6 +118,7 @@ class CommandLineInterface void handleGasEstimation(std::string const& _contract); void handleStorageLayout(std::string const& _contract); void handleTransientStorageLayout(std::string const& _contract); + void handleEthdebug(std::string const& _contract); /// Tries to read @ m_sourceCodes as a JSONs holding ASTs /// such that they can be imported into the compiler (importASTs()) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 592914404..f62abb3c6 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -474,6 +474,7 @@ void CommandLineParser::parseOutputSelection() CompilerOutputs::componentName(&CompilerOutputs::astCompactJson), CompilerOutputs::componentName(&CompilerOutputs::asmJson), CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson), + CompilerOutputs::componentName(&CompilerOutputs::ethdebug), }; static std::set const evmAssemblyJsonImportModeOutputs = { CompilerOutputs::componentName(&CompilerOutputs::asm_), @@ -651,7 +652,7 @@ General Information)").c_str(), po::value()->default_value(util::toString(DebugInfoSelection::Default())), ("Debug info components to be included in the produced EVM assembly and Yul code. " "Value can be all, none or a comma-separated list containing one or more of the " - "following components: " + util::joinHumanReadable(DebugInfoSelection::componentMap() | ranges::views::keys) + ".").c_str() + "following components: " + util::joinHumanReadable(DebugInfoSelection::Default().selectedNames()) + ".").c_str() ) ( g_strStopAfter.c_str(), @@ -773,9 +774,23 @@ General Information)").c_str(), (CompilerOutputs::componentName(&CompilerOutputs::transientStorageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in transient storage.") ; if (!_forHelp) // Note: We intentionally keep this undocumented for now. + { outputComponents.add_options() - (CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson).c_str(), "Control Flow Graph (CFG) of Yul code in JSON format.") - ; + ( + CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson).c_str(), + "Control Flow Graph (CFG) of Yul code in JSON format." + ); + outputComponents.add_options() + ( + CompilerOutputs::componentName(&CompilerOutputs::ethdebug).c_str(), + "Ethdebug output of all contracts." + ); + outputComponents.add_options() + ( + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime).c_str(), + "Ethdebug output of the runtime part of all contracts." + ); + } desc.add(outputComponents); po::options_description extraOutput("Extra Output"); @@ -1321,6 +1336,14 @@ void CommandLineParser::processArgs() CommandLineValidationError, "Optimizer can only be used for strict assembly. Use --" + g_strStrictAssembly + "." ); + + if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + if (!m_options.output.debugInfoSelection.has_value()) + { + m_options.output.debugInfoSelection = DebugInfoSelection::Default(); + m_options.output.debugInfoSelection->enable("ethdebug"); + } + return; } else if (countEnabledOptions({g_strYulDialect, g_strMachine}) >= 1) @@ -1460,6 +1483,61 @@ void CommandLineParser::processArgs() m_options.input.mode == InputMode::CompilerWithASTImport || m_options.input.mode == InputMode::EVMAssemblerJSON ); + + bool incompatibleEthdebugOutputs = + m_options.compiler.outputs.asmJson || m_options.compiler.outputs.irAstJson || m_options.compiler.outputs.irOptimizedAstJson; + + bool incompatibleEthdebugInputs = m_options.input.mode != InputMode::Compiler; + + static std::string enableEthdebugMessage = + "--" + CompilerOutputs::componentName(&CompilerOutputs::ethdebug) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime); + + static std::string enableIrMessage = + "--" + CompilerOutputs::componentName(&CompilerOutputs::ir) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::irOptimized); + + if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + { + if (!m_options.output.viaIR) + solThrow( + CommandLineValidationError, + enableEthdebugMessage + " output can only be selected, if --via-ir was specified." + ); + + if (incompatibleEthdebugOutputs) + solThrow( + CommandLineValidationError, + enableEthdebugMessage + " output can only be used with " + enableIrMessage + "." + ); + + if (!m_options.output.debugInfoSelection.has_value()) + { + m_options.output.debugInfoSelection = DebugInfoSelection::Default(); + m_options.output.debugInfoSelection->enable("ethdebug"); + } + else + { + if (!m_options.output.debugInfoSelection->ethdebug) + solThrow( + CommandLineValidationError, + "--debug-info must contain ethdebug, when compiling with " + enableEthdebugMessage + "." + ); + } + } + + if ( + m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug && + (!(m_options.compiler.outputs.ir || m_options.compiler.outputs.irOptimized || m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) || incompatibleEthdebugOutputs) + ) + solThrow( + CommandLineValidationError, + "--debug-info ethdebug can only be used with " + enableIrMessage + " and/or " + enableEthdebugMessage + "." + ); + + if (m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug && incompatibleEthdebugInputs) + solThrow( + CommandLineValidationError, + "Invalid input mode for --debug-info ethdebug / --ethdebug / --ethdebug-runtime." + ); } void CommandLineParser::parseCombinedJsonOption() diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 3d187694e..d8141cb4f 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -88,6 +88,8 @@ struct CompilerOutputs {"storage-layout", &CompilerOutputs::storageLayout}, {"transient-storage-layout", &CompilerOutputs::transientStorageLayout}, {"yul-cfg-json", &CompilerOutputs::yulCFGJson}, + {"ethdebug", &CompilerOutputs::ethdebug}, + {"ethdebug-runtime", &CompilerOutputs::ethdebugRuntime}, }; return components; } @@ -110,6 +112,8 @@ struct CompilerOutputs bool metadata = false; bool storageLayout = false; bool transientStorageLayout = false; + bool ethdebug = false; + bool ethdebugRuntime = false; }; struct CombinedJsonRequests diff --git a/test/cmdlineTests/ethdebug/args b/test/cmdlineTests/ethdebug/args new file mode 100644 index 000000000..6edc3b560 --- /dev/null +++ b/test/cmdlineTests/ethdebug/args @@ -0,0 +1 @@ +--ethdebug --via-ir --optimize --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug/input.sol b/test/cmdlineTests/ethdebug/input.sol new file mode 100644 index 000000000..25b9640ca --- /dev/null +++ b/test/cmdlineTests/ethdebug/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} + diff --git a/test/cmdlineTests/ethdebug/output b/test/cmdlineTests/ethdebug/output new file mode 100644 index 000000000..41f243d9c --- /dev/null +++ b/test/cmdlineTests/ethdebug/output @@ -0,0 +1,42 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{"sources":["ethdebug/input.sol"]} + +======= ethdebug/input.sol:C ======= +Optimized IR: +/// ethdebug: enabled +/// @use-src 0:"ethdebug/input.sol" +object "C_6" { + code { + { + /// @src 0:60:101 "contract C {..." + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_6_deployed") + codecopy(_1, dataoffset("C_6_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"ethdebug/input.sol" + object "C_6_deployed" { + code { + { + /// @src 0:60:101 "contract C {..." + if iszero(lt(calldatasize(), 4)) + { + if eq(0x26121ff0, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + return(0, 0) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} + +Debug Data (ethdebug/format/program): +{} diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime/args b/test/cmdlineTests/ethdebug_and_ethdebug_runtime/args new file mode 100644 index 000000000..809fb0988 --- /dev/null +++ b/test/cmdlineTests/ethdebug_and_ethdebug_runtime/args @@ -0,0 +1 @@ +--ethdebug-runtime --ethdebug --via-ir --optimize --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime/input.sol b/test/cmdlineTests/ethdebug_and_ethdebug_runtime/input.sol new file mode 100644 index 000000000..25b9640ca --- /dev/null +++ b/test/cmdlineTests/ethdebug_and_ethdebug_runtime/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} + diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime/output b/test/cmdlineTests/ethdebug_and_ethdebug_runtime/output new file mode 100644 index 000000000..3566824b9 --- /dev/null +++ b/test/cmdlineTests/ethdebug_and_ethdebug_runtime/output @@ -0,0 +1,44 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{"sources":["ethdebug_and_ethdebug_runtime/input.sol"]} + +======= ethdebug_and_ethdebug_runtime/input.sol:C ======= +Optimized IR: +/// ethdebug: enabled +/// @use-src 0:"ethdebug_and_ethdebug_runtime/input.sol" +object "C_6" { + code { + { + /// @src 0:60:101 "contract C {..." + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_6_deployed") + codecopy(_1, dataoffset("C_6_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"ethdebug_and_ethdebug_runtime/input.sol" + object "C_6_deployed" { + code { + { + /// @src 0:60:101 "contract C {..." + if iszero(lt(calldatasize(), 4)) + { + if eq(0x26121ff0, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + return(0, 0) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} + +Debug Data (ethdebug/format/program): +{} +Debug Data of the runtime part (ethdebug/format/program): +{} diff --git a/test/cmdlineTests/ethdebug_runtime/args b/test/cmdlineTests/ethdebug_runtime/args new file mode 100644 index 000000000..dfc603878 --- /dev/null +++ b/test/cmdlineTests/ethdebug_runtime/args @@ -0,0 +1 @@ +--ethdebug-runtime --via-ir --optimize --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_runtime/input.sol b/test/cmdlineTests/ethdebug_runtime/input.sol new file mode 100644 index 000000000..25b9640ca --- /dev/null +++ b/test/cmdlineTests/ethdebug_runtime/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} + diff --git a/test/cmdlineTests/ethdebug_runtime/output b/test/cmdlineTests/ethdebug_runtime/output new file mode 100644 index 000000000..8af39f64e --- /dev/null +++ b/test/cmdlineTests/ethdebug_runtime/output @@ -0,0 +1,42 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{"sources":["ethdebug_runtime/input.sol"]} + +======= ethdebug_runtime/input.sol:C ======= +Optimized IR: +/// ethdebug: enabled +/// @use-src 0:"ethdebug_runtime/input.sol" +object "C_6" { + code { + { + /// @src 0:60:101 "contract C {..." + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_6_deployed") + codecopy(_1, dataoffset("C_6_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"ethdebug_runtime/input.sol" + object "C_6_deployed" { + code { + { + /// @src 0:60:101 "contract C {..." + if iszero(lt(calldatasize(), 4)) + { + if eq(0x26121ff0, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + return(0, 0) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} + +Debug Data of the runtime part (ethdebug/format/program): +{} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json new file mode 100644 index 000000000..e7173abed --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json @@ -0,0 +1,24 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/output.json new file mode 100644 index 000000000..da701aec6 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/output.json @@ -0,0 +1,214 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"A1_14_deployed\") + codecopy(_1, dataoffset(\"A1_14_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xf0fdf834, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 0:112:117 \"x > 0\" */ iszero(/** @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"A2_27_deployed\") + codecopy(_1, dataoffset(\"A2_27_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xf0fdf834, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 0:178:183 \"x > 0\" */ iszero(/** @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"A1_42_deployed\") + codecopy(_1, dataoffset(\"A1_42_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xcd580ff3, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 1:112:117 \"x > 0\" */ iszero(/** @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"B2_55_deployed\") + codecopy(_1, dataoffset(\"B2_55_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xcd580ff3, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 1:178:183 \"x > 0\" */ iszero(/** @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "a.sol", + "b.sol" + ] + }, + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json new file mode 100644 index 000000000..e45f27f3c --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json @@ -0,0 +1,24 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/output.json new file mode 100644 index 000000000..4e41e41c3 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/output.json @@ -0,0 +1,226 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"A1_14_deployed\") + codecopy(_1, dataoffset(\"A1_14_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xf0fdf834, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 0:112:117 \"x > 0\" */ iszero(/** @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"A2_27_deployed\") + codecopy(_1, dataoffset(\"A2_27_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xf0fdf834, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 0:178:183 \"x > 0\" */ iszero(/** @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"A1_42_deployed\") + codecopy(_1, dataoffset(\"A1_42_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xcd580ff3, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 1:112:117 \"x > 0\" */ iszero(/** @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"B2_55_deployed\") + codecopy(_1, dataoffset(\"B2_55_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xcd580ff3, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 1:178:183 \"x > 0\" */ iszero(/** @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "a.sol", + "b.sol" + ] + }, + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json new file mode 100644 index 000000000..9e104dc17 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json @@ -0,0 +1,24 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.deployedBytecode.ethdebug", "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/output.json new file mode 100644 index 000000000..3ad7350a9 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/output.json @@ -0,0 +1,214 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"A1_14_deployed\") + codecopy(_1, dataoffset(\"A1_14_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xf0fdf834, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 0:112:117 \"x > 0\" */ iszero(/** @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"A2_27_deployed\") + codecopy(_1, dataoffset(\"A2_27_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xf0fdf834, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 0:178:183 \"x > 0\" */ iszero(/** @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"A1_42_deployed\") + codecopy(_1, dataoffset(\"A1_42_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xcd580ff3, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 1:112:117 \"x > 0\" */ iszero(/** @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"B2_55_deployed\") + codecopy(_1, dataoffset(\"B2_55_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + if iszero(lt(calldatasize(), 4)) + { + if eq(0xcd580ff3, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + if /** @src 1:178:183 \"x > 0\" */ iszero(/** @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 1) + revert(0, 0x24) + } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "a.sol", + "b.sol" + ] + }, + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode/args b/test/cmdlineTests/standard_yul_ethdebug_bytecode/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode/in.yul b/test/cmdlineTests/standard_yul_ethdebug_bytecode/in.yul new file mode 100644 index 000000000..920aef8e9 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode/input.json new file mode 100644 index 000000000..86761f236 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode/input.json @@ -0,0 +1,14 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_debug_info_print_all/in.yul"]} + }, + "settings": { + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "irOptimized"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode/output.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode/output.json new file mode 100644 index 000000000..0e93c5b77 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode/output.json @@ -0,0 +1,31 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": { + "not yet implemented @ MachineAssemblyObject::ethdebug": true + } + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + { + /// @src 0:77:99 + sstore(0, 42) + } + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "C" + ] + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/args b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul new file mode 100644 index 000000000..920aef8e9 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json new file mode 100644 index 000000000..e132c654f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_debug_info_print_all/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.deployedBytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/output.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/output.json new file mode 100644 index 000000000..1380c31d7 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "\"evm.deployedBytecode.ethdebug\" cannot be used for Yul.", + "message": "\"evm.deployedBytecode.ethdebug\" cannot be used for Yul.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/yul_ethdebug/args b/test/cmdlineTests/yul_ethdebug/args new file mode 100644 index 000000000..715f3fb48 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug/args @@ -0,0 +1 @@ +--ethdebug --strict-assembly --optimize --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug/input.yul b/test/cmdlineTests/yul_ethdebug/input.yul new file mode 100644 index 000000000..acd0b45f5 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug/input.yul @@ -0,0 +1,18 @@ +object "object" { + code { + let a + let b + { + function z() -> y + { y := calldataload(0) } + a := z() + } + { + function z() -> y + { y := calldataload(0x20) } + b := z() + } + sstore(a, b) + } +} + diff --git a/test/cmdlineTests/yul_ethdebug/output b/test/cmdlineTests/yul_ethdebug/output new file mode 100644 index 000000000..702fe057d --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug/output @@ -0,0 +1,18 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{"sources":["yul_ethdebug/input.yul"]} + +======= yul_ethdebug/input.yul (EVM) ======= + +Pretty printed source: +/// ethdebug: enabled +object "object" { + code { + { + sstore(calldataload(0), calldataload(0x20)) + } + } +} + + +Debug Data (ethdebug/format/program): +{"not yet implemented @ MachineAssemblyObject::ethdebug":true} diff --git a/test/cmdlineTests/yul_ethdebug_runtime/args b/test/cmdlineTests/yul_ethdebug_runtime/args new file mode 100644 index 000000000..3bedf2d9e --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_runtime/args @@ -0,0 +1 @@ +--ethdebug-runtime --strict-assembly \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug_runtime/err b/test/cmdlineTests/yul_ethdebug_runtime/err new file mode 100644 index 000000000..ed5894632 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_runtime/err @@ -0,0 +1 @@ +Error: The following outputs are not supported in assembler mode: --ethdebug-runtime. diff --git a/test/cmdlineTests/yul_ethdebug_runtime/exit b/test/cmdlineTests/yul_ethdebug_runtime/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_runtime/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/yul_ethdebug_runtime/input.yul b/test/cmdlineTests/yul_ethdebug_runtime/input.yul new file mode 100644 index 000000000..acd0b45f5 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_runtime/input.yul @@ -0,0 +1,18 @@ +object "object" { + code { + let a + let b + { + function z() -> y + { y := calldataload(0) } + a := z() + } + { + function z() -> y + { y := calldataload(0x20) } + b := z() + } + sstore(a, b) + } +} + diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 4cb0b3c93..80cba3382 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -33,6 +33,7 @@ #include #include +#include using namespace solidity::evmasm; using namespace std::string_literals; @@ -152,6 +153,147 @@ Json compile(std::string _input) return ret; } +Json createLanguageAndSourcesSection(std::string const& _language, std::map const& _sources, bool _contentNode = true) +{ + Json result = Json::object(); + result["language"] = _language; + result["sources"] = Json::object(); + for (auto const& source: _sources) + { + result["sources"][source.first] = Json::object(); + if (_contentNode) + result["sources"][source.first]["content"] = source.second; + else + result["sources"][source.first] = source.second; + } + return result; +} + +class Code +{ +public: + virtual ~Code() = default; + explicit Code(std::map _code = {}) : m_code(std::move(_code)) {} + [[nodiscard]] virtual Json json() const = 0; +protected: + std::map m_code; +}; + +class SolidityCode: public Code +{ +public: + explicit SolidityCode(std::map _code = { + {"fileA", "pragma solidity >=0.0; contract C { function f() public pure {} }"} + }) : Code(std::move(_code)) {} + [[nodiscard]] Json json() const override + { + return createLanguageAndSourcesSection("Solidity", m_code); + } +}; + +class YulCode: public Code +{ +public: + explicit YulCode(std::map _code = { + {"fileA", "{}"} + }) : Code(std::move(_code)) {} + [[nodiscard]] Json json() const override + { + return createLanguageAndSourcesSection("Yul", m_code); + } +}; + +class EvmAssemblyCode: public Code +{ +public: + explicit EvmAssemblyCode(std::map _code = { + {"fileA", Json::parse(R"( + { + "assemblyJson": { + ".code": [ + { + "begin": 36, + "end": 51, + "name": "PUSH", + "source": 0, + "value": "0" + } + ], + "sourceList": [ + "" + ] + } + } + )")} + }) : Code(std::move(_code)) {} + [[nodiscard]] Json json() const override + { + return createLanguageAndSourcesSection("EVMAssembly", m_code, false); + } +}; + +class SolidityAstCode: public Code +{ +public: + explicit SolidityAstCode(std::map _code = { + {"fileA", Json::parse(R"( + { + "ast": { + "absolutePath": "empty_contract.sol", + "exportedSymbols": { + "test": [ + 1 + ] + }, + "id": 2, + "nodeType": "SourceUnit", + "nodes": [ + { + "abstract": false, + "baseContracts": [], + "canonicalName": "test", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 1, + "linearizedBaseContracts": [ + 1 + ], + "name": "test", + "nameLocation": "9:4:0", + "nodeType": "ContractDefinition", + "nodes": [], + "scope": 2, + "src": "0:17:0", + "usedErrors": [] + } + ], + "src": "0:124:0" + }, + "id": 0 + } + )")} + }) : Code(std::move(_code)) {} + [[nodiscard]] Json json() const override + { + return createLanguageAndSourcesSection("SolidityAST", m_code); + } +}; + +Json generateStandardJson(bool _viaIr, Json const& _debugInfoSelection, Json const& _outputSelection, Code const& _code = SolidityCode(), bool _advancedOutputSelection = false) +{ + Json result = _code.json(); + result["settings"] = Json::object(); + result["settings"]["viaIR"] = _viaIr; + if (!_debugInfoSelection.empty()) + result["settings"]["debug"]["debugInfo"] = _debugInfoSelection; + if (_advancedOutputSelection) + result["settings"]["outputSelection"] = _outputSelection; + else + result["settings"]["outputSelection"]["*"]["*"] = _outputSelection; + return result; +} + } // end anonymous namespace BOOST_AUTO_TEST_SUITE(StandardCompiler) @@ -1782,6 +1924,375 @@ BOOST_AUTO_TEST_CASE(source_location_of_bare_block) BOOST_REQUIRE(sourceMap.find(sourceRef) != std::string::npos); } +BOOST_AUTO_TEST_CASE(ethdebug_excluded_from_wildcards) +{ + frontend::StandardCompiler compiler; + // excluded from output selection wildcard + Json result = compiler.compile(generateStandardJson(true, {}, Json::array({"*"}))); + BOOST_REQUIRE(result.dump().find("ethdebug") == std::string::npos); + // excluded from debug info selection wildcard + result = compiler.compile(generateStandardJson(true, {"*"}, Json::array({"ir"}))); + BOOST_REQUIRE(result.dump().find("ethdebug") == std::string::npos); + // excluded from both - just in case ;) + result = compiler.compile(generateStandardJson(true, {"*"}, Json::array({"*"}))); + BOOST_REQUIRE(result.dump().find("ethdebug") == std::string::npos); +} + +BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) +{ + static std::vector>>> tests{ + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"*"})), + "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + std::nullopt, + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"})), + "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + std::nullopt, + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), + "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + std::nullopt, + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), + "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + std::nullopt, + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + std::nullopt, + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"ir"})), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"irOptimized"})), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"ir", "evm.bytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"ir", "evm.deployedBytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"ir", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.deployedBytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"ir"}), YulCode()), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"irOptimized"}), YulCode()), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos; + } + }, + { + generateStandardJson(true, Json::array({"ethdebugs"}), Json::array({"irOptimized"}), YulCode()), + "Invalid value in settings.debug.debugInfo.", + {} + }, + { + generateStandardJson( + true, Json::array({"ethdebug"}), { + {"fileA", {{"contractA", Json::array({"evm.deployedBytecode.bin"})}}}, + {"fileB", {{"contractB", Json::array({"evm.bytecode.bin"})}}} + }, + SolidityCode({ + {"fileA", "pragma solidity >=0.0; contract contractA { function f() public pure {} }"}, + {"fileB", "pragma solidity >=0.0; contract contractB { function f() public pure {} }"} + }), true + ), + "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + std::nullopt, + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"}), EvmAssemblyCode()), + "'settings.debug.debugInfo' 'ethdebug' is only supported for languages 'Solidity' and 'Yul'.", + std::nullopt, + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"}), SolidityAstCode()), + "'settings.debug.debugInfo' 'ethdebug' is only supported for languages 'Solidity' and 'Yul'.", + std::nullopt, + }, + }; + frontend::StandardCompiler compiler; + for (auto const& test: tests) + { + Json result = compiler.compile(std::get<0>(test)); + BOOST_REQUIRE(!std::get<1>(test).empty() ? result.contains("errors") : result.contains("contracts")); + if (!std::get<1>(test).empty()) + for (auto const& e: result["errors"]) + BOOST_REQUIRE(e["message"] == std::get<1>(test)); + if (std::get<2>(test).has_value()) + BOOST_REQUIRE((*std::get<2>(test))(result)); + } +} + +BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) +{ + static std::vector>>> tests{ + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), + "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + std::nullopt + }, + { + generateStandardJson(false, {}, Json::array({"evm.bytecode.ethdebug"})), + "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + std::nullopt + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), + "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + std::nullopt + }, + { + generateStandardJson(false, {}, Json::array({"evm.deployedBytecode.ethdebug"})), + "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + std::nullopt + }, + { + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + std::nullopt + }, + { + generateStandardJson(false, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + std::nullopt + }, + { + generateStandardJson(true, Json::array({"location"}), Json::array({"evm.bytecode.ethdebug"})), + "'ethdebug' needs to be enabled in 'settings.debug.debugInfo', if 'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' was selected as output.", + std::nullopt + }, + { + generateStandardJson(true, Json::array({"location"}), Json::array({"evm.deployedBytecode.ethdebug"})), + "'ethdebug' needs to be enabled in 'settings.debug.debugInfo', if 'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' was selected as output.", + std::nullopt + }, + { + generateStandardJson(true, Json::array({"location"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + "'ethdebug' needs to be enabled in 'settings.debug.debugInfo', if 'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' was selected as output.", + std::nullopt + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && + result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + {}, + [](const Json& result) + { + return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && + result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "ir"})), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug", "ir"})), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebugs"})), + {}, + [](const Json& result) + { + return !result.contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebugs"})), + {}, + [](const Json& result) + { + return !result.contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"})), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && + result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "ir"}), YulCode()), + {}, + [](const Json& result) + { + return result.dump().find("/// ethdebug: enabled") != std::string::npos && result["contracts"]["fileA"]["object"]["evm"]["bytecode"].contains("ethdebug"); + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug", "ir"}), YulCode()), + {"\"evm.deployedBytecode.ethdebug\" cannot be used for Yul."}, + std::nullopt + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"}), YulCode()), + {"\"evm.deployedBytecode.ethdebug\" cannot be used for Yul."}, + std::nullopt + }, + { + generateStandardJson(true, {}, Json::array({"evm.bytecode"})), + {}, + [](const Json& result) + { + return result.dump().find("ethdebug") == std::string::npos; + } + }, + { + generateStandardJson(true, {}, Json::array({"evm.deployedBytecode"})), + {}, + [](const Json& result) + { + return result.dump().find("ethdebug") == std::string::npos; + } + }, + { + generateStandardJson( + true, {}, { + {"fileA", {{"contractA", Json::array({"evm.deployedBytecode.ethdebug"})}}}, + {"fileB", {{"contractB", Json::array({"evm.bytecode.ethdebug"})}}} + }, + SolidityCode({ + {"fileA", "pragma solidity >=0.0; contract contractA { function f() public pure {} }"}, + {"fileB", "pragma solidity >=0.0; contract contractB { function f() public pure {} }"} + }), true + ), + {}, + [](const Json& result) + { + return result["contracts"]["fileA"]["contractA"]["evm"]["deployedBytecode"].contains("ethdebug") && + result["contracts"]["fileB"]["contractB"]["evm"]["bytecode"].contains("ethdebug") && result.contains("ethdebug"); + } + } + }; + frontend::StandardCompiler compiler; + for (auto const& test: tests) + { + Json result = compiler.compile(std::get<0>(test)); + if (!std::get<1>(test).empty()) + for (auto const& e: result["errors"]) + BOOST_REQUIRE(e["message"] == std::get<1>(test)); + if (std::get<2>(test).has_value()) + BOOST_REQUIRE((*std::get<2>(test))(result)); + } +} + BOOST_AUTO_TEST_SUITE_END() } // end namespaces diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index e64558bd4..a9f4c59a7 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -63,7 +63,7 @@ YulStack yul::test::parseYul( _optimiserSettings.has_value() ? *_optimiserSettings : (CommonOptions::get().optimize ? OptimiserSettings::standard() : OptimiserSettings::minimal()), - DebugInfoSelection::All() + DebugInfoSelection::AllExceptExperimental() ); bool successful = yulStack.parseAndAnalyze(_sourceUnitName, _source); if (!successful) diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 624a44c3e..4fff5a22e 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -58,7 +58,7 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, settings, - DebugInfoSelection::All() + DebugInfoSelection::AllExceptExperimental() ); yulStack.parseAndAnalyze("", m_source); if (yulStack.hasErrors()) diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index 23d8aaa57..446348fa0 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE(to_string) solidity::test::CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::none(), - DebugInfoSelection::All() + DebugInfoSelection::AllExceptExperimental() ); BOOST_REQUIRE(asmStack.parseAndAnalyze("source", code)); BOOST_CHECK_EQUAL(asmStack.print(), expectation); diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 6d19df01b..8dfcedac8 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -1412,6 +1412,356 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_ambiguous_import) BOOST_REQUIRE(!result.success); } +BOOST_AUTO_TEST_CASE(cli_ethdebug_no_ethdebug_in_help) +{ + OptionsReaderAndMessages result = runCLI({"solc", "--help"}); + BOOST_REQUIRE(result.stdoutContent.find("ethdebug") == std::string::npos); + // just in case + BOOST_REQUIRE(result.stderrContent.find("ethdebug") == std::string::npos); +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_outputs) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.sol"}); + static std::vector, std::string>> tests{ + { + {"solc", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n" + }, + { + {"solc", "--via-ir", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + }, + { + {"solc", "--via-ir", "--ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + }, + { + {"solc", "--via-ir", "--ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + }, + { + {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + "Error: Option --ethdebug is not supported with --import-asm-json.\n" + }, + { + {"solc", "--via-ir", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + }, + { + {"solc", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n" + }, + { + {"solc", "--via-ir", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + }, + { + {"solc", "--via-ir", "--ethdebug-runtime", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + }, + { + {"solc", "--via-ir", "--ethdebug-runtime", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + }, + { + {"solc", "--ethdebug-runtime", "--import-asm-json", tempDir.path().string() + "/input.json"}, + "Error: Option --ethdebug-runtime is not supported with --import-asm-json.\n" + }, + { + {"solc", "--via-ir", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + }, + { + {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + "Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n" + }, + { + {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + "Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n" + }, + { + {"solc", "--debug-info", "ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, + "Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n" + }, + { + {"solc", "--debug-info", "ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, + "Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n" + }, + { + {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + "Error: Option --debug-info is not supported with --import-asm-json.\n" + }, + { + {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + "Error: Option --debug-info is not supported with --import-asm-json.\n" + }, + { + {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.json"}, + "Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n" + } + }; + for (auto const& test: tests) + { + OptionsReaderAndMessages result = runCLI(test.first, ""); + BOOST_REQUIRE(!result.success); + BOOST_CHECK_EQUAL(result.stderrContent, test.second); + } +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_input_modes) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.json"}); + static std::vector, std::string>> tests{ + { + {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + "Error: Option --ethdebug is not supported with --import-asm-json.\n" + }, + { + {"solc", "--ethdebug", "--via-ir", "--import-asm-json", tempDir.path().string() + "/input.json"}, + "Error: The following options are not supported in the current input mode: --via-ir\n" + }, + { + {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + "Error: Option --ethdebug is not supported with --import-asm-json.\n" + }, + { + {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + "Error: Option --debug-info is not supported with --import-asm-json.\n" + }, + { + {"solc", "--ethdebug", "--import-ast", tempDir.path().string() + "/input.json"}, + "Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n" + }, + { + {"solc", "--ethdebug", "--via-ir", "--import-ast", tempDir.path().string() + "/input.json"}, + "Error: Invalid input mode for --debug-info ethdebug / --ethdebug / --ethdebug-runtime.\n" + }, + { + {"solc", "--debug-info", "ethdebug", "--ir", "--import-ast", tempDir.path().string() + "/input.json"}, + "Error: Invalid input mode for --debug-info ethdebug / --ethdebug / --ethdebug-runtime.\n" + } + }; + for (auto const& test: tests) + { + OptionsReaderAndMessages result = runCLI(test.first, ""); + BOOST_REQUIRE(!result.success); + BOOST_CHECK_EQUAL(result.stderrContent, test.second); + } +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_debug_info_ethdebug) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); + createFilesWithParentDirs({tempDir.path() / "input.yul"}, "{}"); + static std::vector, std::vector, std::vector>> tests{ + { + {"solc", "--debug-info", "ethdebug", tempDir.path().string() + "/input.sol"}, + {"Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n"}, + {}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ir", tempDir.path().string() + "/input.sol"}, + {}, + {"/// ethdebug: enabled"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {}, + {"/// ethdebug: enabled"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, + {}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program):"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data of the runtime part (ethdebug/format/program):"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {}, + {"/// ethdebug: enabled", "Pretty printed source", "Binary representation", "Text representation"}, + }, + { + {"solc", "--ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program):"}, + }, + { + {"solc", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {"Error: The following outputs are not supported in assembler mode: --ethdebug-runtime.\n"}, + {}, + }, + { + {"solc", "--ethdebug", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {"Error: The following outputs are not supported in assembler mode: --ethdebug-runtime.\n"}, + {}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, + {}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, + {}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, + {}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program):", "Debug Data of the runtime part (ethdebug/format/program):"}, + }, + { + {"solc", "--debug-info", "location", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, + {}, + }, + { + {"solc", "--debug-info", "location", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, + {}, + }, + { + {"solc", "--debug-info", "location", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, + {}, + }, + { + {"solc", "--debug-info", "all", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, + {}, + }, + { + {"solc", "--debug-info", "all", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, + {}, + }, + { + {"solc", "--debug-info", "all", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, + {}, + }, + }; + for (auto const& test: tests) + { + OptionsReaderAndMessages result{runCLI(std::get<0>(test), "")}; + BOOST_REQUIRE(!std::get<1>(test).empty() ? !result.success : result.success); + for (auto const& error : std::get<1>(test)) + BOOST_REQUIRE(result.stderrContent == error); + for (auto const& output : std::get<2>(test)) + BOOST_REQUIRE(result.stdoutContent.find(output) != std::string::npos); + } +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_ethdebug_output) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); + static std::vector, std::vector, std::vector>> tests{ + { + {"solc", "--ethdebug", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, + {}, + }, + { + {"solc", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, + {}, + }, + { + {"solc", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, + {}, + }, + { + {"solc", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)"}, + }, + { + {"solc", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data of the runtime part (ethdebug/format/program)"}, + }, + { + {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "Debug Data of the runtime part (ethdebug/format/program)"}, + }, + { + {"solc", "--ethdebug", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "/// ethdebug: enabled"}, + }, + { + {"solc", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, + }, + { + {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, + }, + { + {"solc", "--ethdebug", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "/// ethdebug: enabled"}, + }, + { + {"solc", "--ethdebug-runtime", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, + }, + { + {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, + }, + { + {"solc", "--ethdebug", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "/// ethdebug: enabled"}, + }, + { + {"solc", "--ethdebug-runtime", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, + }, + { + {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + {}, + {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, + }, + }; + for (auto const& test: tests) + { + OptionsReaderAndMessages result{runCLI(std::get<0>(test), "")}; + BOOST_REQUIRE(!std::get<1>(test).empty() ? !result.success : result.success); + for (auto const& error : std::get<1>(test)) + BOOST_REQUIRE(result.stderrContent == error); + for (auto const& output : std::get<2>(test)) + BOOST_REQUIRE(result.stdoutContent.find(output) != std::string::npos); + } +} + BOOST_AUTO_TEST_SUITE_END() } // namespace solidity::frontend::test diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 227b1b921..be3e25d33 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -628,6 +628,49 @@ BOOST_AUTO_TEST_CASE(invalid_optimizer_sequence_without_optimize) } } +BOOST_AUTO_TEST_CASE(ethdebug) +{ + CommandLineOptions commandLineOptions = parseCommandLine({"solc", "contract.sol", "--debug-info", "ethdebug", "--ethdebug", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--debug-info", "ethdebug", "--ethdebug-runtime", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--ethdebug", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); + // debug-info "ethdebug" selected implicitly, + // if compiled with --ethdebug or --ethdebug-runtime and no debug-info was selected. + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--ethdebug-runtime", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--ethdebug", "--ethdebug-runtime", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--debug-info", "ethdebug", "--ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ir, true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--debug-info", "ethdebug", "--ir-optimized"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.irOptimized, true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); + BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace solidity::frontend::test diff --git a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp index 595aecdca..5a9192bc3 100644 --- a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp @@ -41,7 +41,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::minimal(), - langutil::DebugInfoSelection::All() + langutil::DebugInfoSelection::AllExceptExperimental() ); if (!stack.parseAndAnalyze("source", input)) diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index ffeb14702..a4515b309 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -65,7 +65,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), - DebugInfoSelection::All() + DebugInfoSelection::AllExceptExperimental() ); try { diff --git a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp index 7553c81c0..454380492 100644 --- a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp @@ -42,7 +42,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), - DebugInfoSelection::All() + DebugInfoSelection::AllExceptExperimental() ); if (!stack.parseAndAnalyze("source", input)) From 7ea985d54daa79ca623623b719eb4aa9d26f0411 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Thu, 16 Jan 2025 15:24:13 +0100 Subject: [PATCH 0640/1340] Error when ethdebug is used with optimization. --- libsolidity/interface/StandardCompiler.cpp | 3 + solc/CommandLineParser.cpp | 15 +- test/cmdlineTests/ethdebug/args | 2 +- test/cmdlineTests/ethdebug/output | 111 ++- .../ethdebug_and_ethdebug_runtime/args | 2 +- .../ethdebug_and_ethdebug_runtime/output | 111 ++- .../ethdebug_enabled_optimization/args | 1 + .../ethdebug_enabled_optimization/err | 1 + .../ethdebug_enabled_optimization/exit | 1 + .../ethdebug_enabled_optimization/input.sol | 7 + test/cmdlineTests/ethdebug_runtime/args | 2 +- test/cmdlineTests/ethdebug_runtime/output | 111 ++- .../input.json | 4 +- .../output.json | 692 +++++++++++++++--- .../input.json | 4 +- .../output.json | 692 +++++++++++++++--- .../input.json | 24 + .../output.json | 11 + .../input.json | 4 +- .../output.json | 692 +++++++++++++++--- .../input.json | 21 + .../output.json | 11 + .../input.json | 24 + .../output.json | 11 + .../standard_yul_ethdebug_bytecode/input.json | 5 +- .../output.json | 12 +- .../standard_yul_ethdebug_irOptimized/args | 1 + .../standard_yul_ethdebug_irOptimized/in.yul | 17 + .../input.json | 11 + .../output.json | 11 + .../standard_yul_ethdebug_optimize/args | 1 + .../standard_yul_ethdebug_optimize/in.yul | 17 + .../standard_yul_ethdebug_optimize/input.json | 14 + .../output.json | 11 + test/libsolidity/StandardCompiler.cpp | 17 +- test/solc/CommandLineInterface.cpp | 55 +- test/solc/CommandLineParser.cpp | 6 - 37 files changed, 2362 insertions(+), 373 deletions(-) create mode 100644 test/cmdlineTests/ethdebug_enabled_optimization/args create mode 100644 test/cmdlineTests/ethdebug_enabled_optimization/err create mode 100644 test/cmdlineTests/ethdebug_enabled_optimization/exit create mode 100644 test/cmdlineTests/ethdebug_enabled_optimization/input.sol create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/output.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/output.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_optimize/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_optimize/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_irOptimized/args create mode 100644 test/cmdlineTests/standard_yul_ethdebug_irOptimized/in.yul create mode 100644 test/cmdlineTests/standard_yul_ethdebug_irOptimized/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_irOptimized/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize/args create mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize/in.yul create mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize/output.json diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index bcdb2901d..520f4d5f1 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1204,6 +1204,9 @@ std::variant StandardCompiler::parseI ) return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected."); + if (isEthdebugRequested(ret.outputSelection) && (ret.optimiserSettings.runYulOptimiser || isArtifactRequested(ret.outputSelection, "*", "*", "irOptimized", false))) + return formatFatalError(Error::Type::FatalError, "Optimization is not yet supported with ethdebug."); + return {std::move(ret)}; } diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index f62abb3c6..56be4195d 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -1485,15 +1485,18 @@ void CommandLineParser::processArgs() ); bool incompatibleEthdebugOutputs = - m_options.compiler.outputs.asmJson || m_options.compiler.outputs.irAstJson || m_options.compiler.outputs.irOptimizedAstJson; + m_options.compiler.outputs.asmJson || m_options.compiler.outputs.irAstJson || m_options.compiler.outputs.irOptimizedAstJson || + m_options.compiler.outputs.irOptimized || m_options.optimizer.optimizeYul || m_options.optimizer.optimizeEvmasm; bool incompatibleEthdebugInputs = m_options.input.mode != InputMode::Compiler; static std::string enableEthdebugMessage = "--" + CompilerOutputs::componentName(&CompilerOutputs::ethdebug) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime); - static std::string enableIrMessage = - "--" + CompilerOutputs::componentName(&CompilerOutputs::ir) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::irOptimized); + static std::string incompatibleEthdebugOptimizerMessage = + "--" + g_strOptimize + " / --" + CompilerOutputs::componentName(&CompilerOutputs::irOptimized); + + static std::string enableIrMessage = "--" + CompilerOutputs::componentName(&CompilerOutputs::ir); if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) { @@ -1506,7 +1509,7 @@ void CommandLineParser::processArgs() if (incompatibleEthdebugOutputs) solThrow( CommandLineValidationError, - enableEthdebugMessage + " output can only be used with " + enableIrMessage + "." + enableEthdebugMessage + " output can only be used with " + enableIrMessage + ". Optimization is not yet supported with ethdebug, e.g. no support for " + incompatibleEthdebugOptimizerMessage + " yet." ); if (!m_options.output.debugInfoSelection.has_value()) @@ -1526,11 +1529,11 @@ void CommandLineParser::processArgs() if ( m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug && - (!(m_options.compiler.outputs.ir || m_options.compiler.outputs.irOptimized || m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) || incompatibleEthdebugOutputs) + (!(m_options.compiler.outputs.ir || m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) || incompatibleEthdebugOutputs) ) solThrow( CommandLineValidationError, - "--debug-info ethdebug can only be used with " + enableIrMessage + " and/or " + enableEthdebugMessage + "." + "--debug-info ethdebug can only be used with " + enableIrMessage + " and/or " + enableEthdebugMessage + ". Optimization is not yet supported with ethdebug, e.g. no support for " + incompatibleEthdebugOptimizerMessage + " yet." ); if (m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug && incompatibleEthdebugInputs) diff --git a/test/cmdlineTests/ethdebug/args b/test/cmdlineTests/ethdebug/args index 6edc3b560..ac83894b3 100644 --- a/test/cmdlineTests/ethdebug/args +++ b/test/cmdlineTests/ethdebug/args @@ -1 +1 @@ ---ethdebug --via-ir --optimize --ir-optimized \ No newline at end of file +--ethdebug --via-ir --ir \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug/output b/test/cmdlineTests/ethdebug/output index 41f243d9c..375c5cf90 100644 --- a/test/cmdlineTests/ethdebug/output +++ b/test/cmdlineTests/ethdebug/output @@ -2,41 +2,120 @@ {"sources":["ethdebug/input.sol"]} ======= ethdebug/input.sol:C ======= -Optimized IR: +IR: /// ethdebug: enabled /// @use-src 0:"ethdebug/input.sol" object "C_6" { code { - { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + + return(_1, datasize("C_6_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:60:101 "contract C {..." + function constructor_C_6() { + /// @src 0:60:101 "contract C {..." - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize("C_6_deployed") - codecopy(_1, dataoffset("C_6_deployed"), _2) - return(_1, _2) + } + /// @src 0:60:101 "contract C {..." + } /// @use-src 0:"ethdebug/input.sol" object "C_6_deployed" { code { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 0:60:101 "contract C {..." - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 { - if eq(0x26121ff0, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - return(0, 0) - } + // f() + + external_fun_f_5() } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { revert(0, 0) } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + /// @ast-id 5 + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + + } + /// @src 0:60:101 "contract C {..." + } + data ".metadata" hex"" } + } + Debug Data (ethdebug/format/program): {} diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime/args b/test/cmdlineTests/ethdebug_and_ethdebug_runtime/args index 809fb0988..18053bcda 100644 --- a/test/cmdlineTests/ethdebug_and_ethdebug_runtime/args +++ b/test/cmdlineTests/ethdebug_and_ethdebug_runtime/args @@ -1 +1 @@ ---ethdebug-runtime --ethdebug --via-ir --optimize --ir-optimized \ No newline at end of file +--ethdebug-runtime --ethdebug --via-ir --ir \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime/output b/test/cmdlineTests/ethdebug_and_ethdebug_runtime/output index 3566824b9..000f29c4d 100644 --- a/test/cmdlineTests/ethdebug_and_ethdebug_runtime/output +++ b/test/cmdlineTests/ethdebug_and_ethdebug_runtime/output @@ -2,42 +2,121 @@ {"sources":["ethdebug_and_ethdebug_runtime/input.sol"]} ======= ethdebug_and_ethdebug_runtime/input.sol:C ======= -Optimized IR: +IR: /// ethdebug: enabled /// @use-src 0:"ethdebug_and_ethdebug_runtime/input.sol" object "C_6" { code { - { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + + return(_1, datasize("C_6_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:60:101 "contract C {..." + function constructor_C_6() { + /// @src 0:60:101 "contract C {..." - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize("C_6_deployed") - codecopy(_1, dataoffset("C_6_deployed"), _2) - return(_1, _2) + } + /// @src 0:60:101 "contract C {..." + } /// @use-src 0:"ethdebug_and_ethdebug_runtime/input.sol" object "C_6_deployed" { code { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 0:60:101 "contract C {..." - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 { - if eq(0x26121ff0, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - return(0, 0) - } + // f() + + external_fun_f_5() } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { revert(0, 0) } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + /// @ast-id 5 + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + + } + /// @src 0:60:101 "contract C {..." + } + data ".metadata" hex"" } + } + Debug Data (ethdebug/format/program): {} Debug Data of the runtime part (ethdebug/format/program): diff --git a/test/cmdlineTests/ethdebug_enabled_optimization/args b/test/cmdlineTests/ethdebug_enabled_optimization/args new file mode 100644 index 000000000..6edc3b560 --- /dev/null +++ b/test/cmdlineTests/ethdebug_enabled_optimization/args @@ -0,0 +1 @@ +--ethdebug --via-ir --optimize --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_enabled_optimization/err b/test/cmdlineTests/ethdebug_enabled_optimization/err new file mode 100644 index 000000000..082f6feee --- /dev/null +++ b/test/cmdlineTests/ethdebug_enabled_optimization/err @@ -0,0 +1 @@ +Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet. diff --git a/test/cmdlineTests/ethdebug_enabled_optimization/exit b/test/cmdlineTests/ethdebug_enabled_optimization/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/ethdebug_enabled_optimization/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/ethdebug_enabled_optimization/input.sol b/test/cmdlineTests/ethdebug_enabled_optimization/input.sol new file mode 100644 index 000000000..25b9640ca --- /dev/null +++ b/test/cmdlineTests/ethdebug_enabled_optimization/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} + diff --git a/test/cmdlineTests/ethdebug_runtime/args b/test/cmdlineTests/ethdebug_runtime/args index dfc603878..a2193034c 100644 --- a/test/cmdlineTests/ethdebug_runtime/args +++ b/test/cmdlineTests/ethdebug_runtime/args @@ -1 +1 @@ ---ethdebug-runtime --via-ir --optimize --ir-optimized \ No newline at end of file +--ethdebug-runtime --via-ir --ir \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_runtime/output b/test/cmdlineTests/ethdebug_runtime/output index 8af39f64e..8670e379d 100644 --- a/test/cmdlineTests/ethdebug_runtime/output +++ b/test/cmdlineTests/ethdebug_runtime/output @@ -2,41 +2,120 @@ {"sources":["ethdebug_runtime/input.sol"]} ======= ethdebug_runtime/input.sol:C ======= -Optimized IR: +IR: /// ethdebug: enabled /// @use-src 0:"ethdebug_runtime/input.sol" object "C_6" { code { - { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + + return(_1, datasize("C_6_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:60:101 "contract C {..." + function constructor_C_6() { + /// @src 0:60:101 "contract C {..." - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize("C_6_deployed") - codecopy(_1, dataoffset("C_6_deployed"), _2) - return(_1, _2) + } + /// @src 0:60:101 "contract C {..." + } /// @use-src 0:"ethdebug_runtime/input.sol" object "C_6_deployed" { code { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 0:60:101 "contract C {..." - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 { - if eq(0x26121ff0, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - return(0, 0) - } + // f() + + external_fun_f_5() } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { revert(0, 0) } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + /// @ast-id 5 + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + + } + /// @src 0:60:101 "contract C {..." + } + data ".metadata" hex"" } + } + Debug Data of the runtime part (ethdebug/format/program): {} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json index e7173abed..6ac2691c2 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json @@ -11,12 +11,12 @@ "settings": { "viaIR": true, "optimizer": { - "enabled": true + "enabled": false }, "outputSelection": { "*": { "*": [ - "evm.bytecode.ethdebug", "irOptimized" + "evm.bytecode.ethdebug", "ir" ] } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/output.json index da701aec6..fabb25ee6 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/output.json @@ -7,46 +7,175 @@ "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 0:\"a.sol\" object \"A1_14\" { code { - { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_14() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + + return(_1, datasize(\"A1_14_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_14() { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"A1_14_deployed\") - codecopy(_1, dataoffset(\"A1_14_deployed\"), _2) - return(_1, _2) + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 0:\"a.sol\" object \"A1_14_deployed\" { code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 { - if eq(0xf0fdf834, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 0:112:117 \"x > 0\" */ iszero(/** @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // a(uint256) + + external_fun_a_13() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_13() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_13(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 13 + /// @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_13(var_x_3) { + + /// @src 0:112:113 \"x\" + let _1 := var_x_3 + let expr_7 := _1 + /// @src 0:116:117 \"0\" + let expr_8 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_9 := gt(cleanup_t_uint256(expr_7), convert_t_rational_0_by_1_to_t_uint256(expr_8)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_9) + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " }, "A2": { @@ -55,46 +184,175 @@ object \"A1_14\" { "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 0:\"a.sol\" object \"A2_27\" { code { - { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A2_27() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + + return(_1, datasize(\"A2_27_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A2_27() { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"A2_27_deployed\") - codecopy(_1, dataoffset(\"A2_27_deployed\"), _2) - return(_1, _2) + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 0:\"a.sol\" object \"A2_27_deployed\" { code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 { - if eq(0xf0fdf834, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 0:178:183 \"x > 0\" */ iszero(/** @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // a(uint256) + + external_fun_a_26() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_26() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_26(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 26 + /// @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_26(var_x_16) { + + /// @src 0:178:179 \"x\" + let _1 := var_x_16 + let expr_20 := _1 + /// @src 0:182:183 \"0\" + let expr_21 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_22 := gt(cleanup_t_uint256(expr_20), convert_t_rational_0_by_1_to_t_uint256(expr_21)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_22) + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " } }, @@ -105,46 +363,175 @@ object \"A2_27\" { "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 1:\"b.sol\" object \"A1_42\" { code { - { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_42() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + + return(_1, datasize(\"A1_42_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_42() { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"A1_42_deployed\") - codecopy(_1, dataoffset(\"A1_42_deployed\"), _2) - return(_1, _2) + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 1:\"b.sol\" object \"A1_42_deployed\" { code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 { - if eq(0xcd580ff3, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 1:112:117 \"x > 0\" */ iszero(/** @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // b(uint256) + + external_fun_b_41() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_41() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_41(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 41 + /// @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_41(var_x_31) { + + /// @src 1:112:113 \"x\" + let _1 := var_x_31 + let expr_35 := _1 + /// @src 1:116:117 \"0\" + let expr_36 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_37 := gt(cleanup_t_uint256(expr_35), convert_t_rational_0_by_1_to_t_uint256(expr_36)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_37) + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " }, "B2": { @@ -153,46 +540,175 @@ object \"A1_42\" { "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 1:\"b.sol\" object \"B2_55\" { code { - { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_B2_55() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + + return(_1, datasize(\"B2_55_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_B2_55() { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"B2_55_deployed\") - codecopy(_1, dataoffset(\"B2_55_deployed\"), _2) - return(_1, _2) + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 1:\"b.sol\" object \"B2_55_deployed\" { code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 { - if eq(0xcd580ff3, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 1:178:183 \"x > 0\" */ iszero(/** @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // b(uint256) + + external_fun_b_54() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_54() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_54(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 54 + /// @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_54(var_x_44) { + + /// @src 1:178:179 \"x\" + let _1 := var_x_44 + let expr_48 := _1 + /// @src 1:182:183 \"0\" + let expr_49 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_50 := gt(cleanup_t_uint256(expr_48), convert_t_rational_0_by_1_to_t_uint256(expr_49)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_50) + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json index e45f27f3c..bb93f57a8 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json @@ -11,12 +11,12 @@ "settings": { "viaIR": true, "optimizer": { - "enabled": true + "enabled": false }, "outputSelection": { "*": { "*": [ - "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "irOptimized" + "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir" ] } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/output.json index 4e41e41c3..f8fb2ce27 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/output.json @@ -10,46 +10,175 @@ "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 0:\"a.sol\" object \"A1_14\" { code { - { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_14() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + + return(_1, datasize(\"A1_14_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_14() { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"A1_14_deployed\") - codecopy(_1, dataoffset(\"A1_14_deployed\"), _2) - return(_1, _2) + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 0:\"a.sol\" object \"A1_14_deployed\" { code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 { - if eq(0xf0fdf834, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 0:112:117 \"x > 0\" */ iszero(/** @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // a(uint256) + + external_fun_a_13() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_13() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_13(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 13 + /// @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_13(var_x_3) { + + /// @src 0:112:113 \"x\" + let _1 := var_x_3 + let expr_7 := _1 + /// @src 0:116:117 \"0\" + let expr_8 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_9 := gt(cleanup_t_uint256(expr_7), convert_t_rational_0_by_1_to_t_uint256(expr_8)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_9) + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " }, "A2": { @@ -61,46 +190,175 @@ object \"A1_14\" { "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 0:\"a.sol\" object \"A2_27\" { code { - { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A2_27() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + + return(_1, datasize(\"A2_27_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A2_27() { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"A2_27_deployed\") - codecopy(_1, dataoffset(\"A2_27_deployed\"), _2) - return(_1, _2) + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 0:\"a.sol\" object \"A2_27_deployed\" { code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 { - if eq(0xf0fdf834, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 0:178:183 \"x > 0\" */ iszero(/** @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // a(uint256) + + external_fun_a_26() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_26() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_26(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 26 + /// @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_26(var_x_16) { + + /// @src 0:178:179 \"x\" + let _1 := var_x_16 + let expr_20 := _1 + /// @src 0:182:183 \"0\" + let expr_21 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_22 := gt(cleanup_t_uint256(expr_20), convert_t_rational_0_by_1_to_t_uint256(expr_21)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_22) + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " } }, @@ -114,46 +372,175 @@ object \"A2_27\" { "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 1:\"b.sol\" object \"A1_42\" { code { - { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_42() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + + return(_1, datasize(\"A1_42_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_42() { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"A1_42_deployed\") - codecopy(_1, dataoffset(\"A1_42_deployed\"), _2) - return(_1, _2) + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 1:\"b.sol\" object \"A1_42_deployed\" { code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 { - if eq(0xcd580ff3, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 1:112:117 \"x > 0\" */ iszero(/** @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // b(uint256) + + external_fun_b_41() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_41() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_41(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 41 + /// @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_41(var_x_31) { + + /// @src 1:112:113 \"x\" + let _1 := var_x_31 + let expr_35 := _1 + /// @src 1:116:117 \"0\" + let expr_36 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_37 := gt(cleanup_t_uint256(expr_35), convert_t_rational_0_by_1_to_t_uint256(expr_36)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_37) + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " }, "B2": { @@ -165,46 +552,175 @@ object \"A1_42\" { "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 1:\"b.sol\" object \"B2_55\" { code { - { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_B2_55() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + + return(_1, datasize(\"B2_55_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_B2_55() { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"B2_55_deployed\") - codecopy(_1, dataoffset(\"B2_55_deployed\"), _2) - return(_1, _2) + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 1:\"b.sol\" object \"B2_55_deployed\" { code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 { - if eq(0xcd580ff3, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 1:178:183 \"x > 0\" */ iszero(/** @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // b(uint256) + + external_fun_b_54() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_54() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_54(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 54 + /// @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_54(var_x_44) { + + /// @src 1:178:179 \"x\" + let _1 := var_x_44 + let expr_48 := _1 + /// @src 1:182:183 \"0\" + let expr_49 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_50 := gt(cleanup_t_uint256(expr_48), convert_t_rational_0_by_1_to_t_uint256(expr_49)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_50) + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/input.json new file mode 100644 index 000000000..e45f27f3c --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/input.json @@ -0,0 +1,24 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/output.json new file mode 100644 index 000000000..3ed2f577c --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json index 9e104dc17..f8e3ee312 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json @@ -11,12 +11,12 @@ "settings": { "viaIR": true, "optimizer": { - "enabled": true + "enabled": false }, "outputSelection": { "*": { "*": [ - "evm.deployedBytecode.ethdebug", "irOptimized" + "evm.deployedBytecode.ethdebug", "ir" ] } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/output.json index 3ad7350a9..4c7b4ed67 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/output.json @@ -7,46 +7,175 @@ "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 0:\"a.sol\" object \"A1_14\" { code { - { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_14() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + + return(_1, datasize(\"A1_14_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_14() { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"A1_14_deployed\") - codecopy(_1, dataoffset(\"A1_14_deployed\"), _2) - return(_1, _2) + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 0:\"a.sol\" object \"A1_14_deployed\" { code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 { - if eq(0xf0fdf834, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 0:112:117 \"x > 0\" */ iszero(/** @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // a(uint256) + + external_fun_a_13() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_13() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_13(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 13 + /// @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_13(var_x_3) { + + /// @src 0:112:113 \"x\" + let _1 := var_x_3 + let expr_7 := _1 + /// @src 0:116:117 \"0\" + let expr_8 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_9 := gt(cleanup_t_uint256(expr_7), convert_t_rational_0_by_1_to_t_uint256(expr_8)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_9) + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " }, "A2": { @@ -55,46 +184,175 @@ object \"A1_14\" { "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 0:\"a.sol\" object \"A2_27\" { code { - { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A2_27() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + + return(_1, datasize(\"A2_27_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A2_27() { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"A2_27_deployed\") - codecopy(_1, dataoffset(\"A2_27_deployed\"), _2) - return(_1, _2) + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 0:\"a.sol\" object \"A2_27_deployed\" { code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 { - if eq(0xf0fdf834, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 0:178:183 \"x > 0\" */ iszero(/** @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // a(uint256) + + external_fun_a_26() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_26() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_26(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 26 + /// @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_26(var_x_16) { + + /// @src 0:178:179 \"x\" + let _1 := var_x_16 + let expr_20 := _1 + /// @src 0:182:183 \"0\" + let expr_21 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_22 := gt(cleanup_t_uint256(expr_20), convert_t_rational_0_by_1_to_t_uint256(expr_21)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_22) + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " } }, @@ -105,46 +363,175 @@ object \"A2_27\" { "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 1:\"b.sol\" object \"A1_42\" { code { - { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_42() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + + return(_1, datasize(\"A1_42_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_42() { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"A1_42_deployed\") - codecopy(_1, dataoffset(\"A1_42_deployed\"), _2) - return(_1, _2) + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 1:\"b.sol\" object \"A1_42_deployed\" { code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 { - if eq(0xcd580ff3, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 1:112:117 \"x > 0\" */ iszero(/** @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // b(uint256) + + external_fun_b_41() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_41() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_41(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 41 + /// @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_41(var_x_31) { + + /// @src 1:112:113 \"x\" + let _1 := var_x_31 + let expr_35 := _1 + /// @src 1:116:117 \"0\" + let expr_36 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_37 := gt(cleanup_t_uint256(expr_35), convert_t_rational_0_by_1_to_t_uint256(expr_36)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_37) + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " }, "B2": { @@ -153,46 +540,175 @@ object \"A1_42\" { "ethdebug": {} } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 1:\"b.sol\" object \"B2_55\" { code { - { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_B2_55() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + + return(_1, datasize(\"B2_55_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_B2_55() { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" - let _1 := memoryguard(0x80) - mstore(64, _1) - if callvalue() { revert(0, 0) } - let _2 := datasize(\"B2_55_deployed\") - codecopy(_1, dataoffset(\"B2_55_deployed\"), _2) - return(_1, _2) + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + } /// @use-src 1:\"b.sol\" object \"B2_55_deployed\" { code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) { - /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" - if iszero(lt(calldatasize(), 4)) + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 { - if eq(0xcd580ff3, shr(224, calldataload(0))) - { - if callvalue() { revert(0, 0) } - if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } - if /** @src 1:178:183 \"x > 0\" */ iszero(/** @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" */ calldataload(4)) - { - mstore(0, shl(224, 0x4e487b71)) - mstore(4, 1) - revert(0, 0x24) - } - return(0, 0) - } + // b(uint256) + + external_fun_b_54() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_54() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_54(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 54 + /// @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_54(var_x_44) { + + /// @src 1:178:179 \"x\" + let _1 := var_x_44 + let expr_48 := _1 + /// @src 1:182:183 \"0\" + let expr_49 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_50 := gt(cleanup_t_uint256(expr_48), convert_t_rational_0_by_1_to_t_uint256(expr_49)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_50) + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + } + data \".metadata\" hex\"\" } + } + " } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/input.json new file mode 100644 index 000000000..ab13b27ea --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/input.json @@ -0,0 +1,21 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/output.json new file mode 100644 index 000000000..3ed2f577c --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize/input.json new file mode 100644 index 000000000..a8a5cff05 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize/input.json @@ -0,0 +1,24 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize/output.json new file mode 100644 index 000000000..3ed2f577c --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode/input.json index 86761f236..f3346fdd1 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_bytecode/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode/input.json @@ -4,11 +4,8 @@ "C": {"urls": ["standard_yul_debug_info_print_all/in.yul"]} }, "settings": { - "optimizer": { - "enabled": true - }, "outputSelection": { - "*": {"*": ["evm.bytecode.ethdebug", "irOptimized"]} + "*": {"*": ["evm.bytecode.ethdebug", "ir"]} } } } diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode/output.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode/output.json index 0e93c5b77..c9ab1d8f5 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_bytecode/output.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode/output.json @@ -9,14 +9,16 @@ } } }, - "irOptimized": "/// ethdebug: enabled + "ir": "/// ethdebug: enabled /// @use-src 0:\"input.sol\" object \"C_6_deployed\" { code { - { - /// @src 0:77:99 - sstore(0, 42) - } + /// @src 0:60:101 + mstore(64, 128) + fun_f_5() + /// @src 0:77:99 + function fun_f_5() + { sstore(0, 42) } } } " diff --git a/test/cmdlineTests/standard_yul_ethdebug_irOptimized/args b/test/cmdlineTests/standard_yul_ethdebug_irOptimized/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_irOptimized/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_irOptimized/in.yul b/test/cmdlineTests/standard_yul_ethdebug_irOptimized/in.yul new file mode 100644 index 000000000..920aef8e9 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_irOptimized/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_irOptimized/input.json b/test/cmdlineTests/standard_yul_ethdebug_irOptimized/input.json new file mode 100644 index 000000000..89994857f --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_irOptimized/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_debug_info_print_all/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "irOptimized"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_irOptimized/output.json b/test/cmdlineTests/standard_yul_ethdebug_irOptimized/output.json new file mode 100644 index 000000000..3ed2f577c --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_irOptimized/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize/args b/test/cmdlineTests/standard_yul_ethdebug_optimize/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize/in.yul b/test/cmdlineTests/standard_yul_ethdebug_optimize/in.yul new file mode 100644 index 000000000..920aef8e9 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize/input.json b/test/cmdlineTests/standard_yul_ethdebug_optimize/input.json new file mode 100644 index 000000000..fb232f23a --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize/input.json @@ -0,0 +1,14 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_debug_info_print_all/in.yul"]} + }, + "settings": { + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "ir"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize/output.json b/test/cmdlineTests/standard_yul_ethdebug_optimize/output.json new file mode 100644 index 000000000..3ed2f577c --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 80cba3382..3161eba2a 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -1975,7 +1975,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) } }, { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"irOptimized"})), + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"ir"})), {}, [](const Json& result) { @@ -2007,7 +2007,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) } }, { - generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug"})), + generateStandardJson(true, {}, Json::array({"ir", "evm.bytecode.ethdebug"})), {}, [](const Json& result) { @@ -2015,7 +2015,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) } }, { - generateStandardJson(true, {}, Json::array({"irOptimized", "evm.deployedBytecode.ethdebug"})), + generateStandardJson(true, {}, Json::array({"ir", "evm.deployedBytecode.ethdebug"})), {}, [](const Json& result) { @@ -2023,7 +2023,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) } }, { - generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + generateStandardJson(true, {}, Json::array({"ir", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), {}, [](const Json& result) { @@ -2040,14 +2040,11 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) }, { generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"irOptimized"}), YulCode()), - {}, - [](const Json& result) - { - return result.dump().find("/// ethdebug: enabled") != std::string::npos; - } + "Optimization is not yet supported with ethdebug.", + {} }, { - generateStandardJson(true, Json::array({"ethdebugs"}), Json::array({"irOptimized"}), YulCode()), + generateStandardJson(true, Json::array({"ethdebugs"}), Json::array({"ir"}), YulCode()), "Invalid value in settings.debug.debugInfo.", {} }, diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 8dfcedac8..17166268a 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -1431,15 +1431,23 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_outputs) }, { {"solc", "--via-ir", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" + }, + { + {"solc", "--via-ir", "--ethdebug", "--optimize", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" + }, + { + {"solc", "--via-ir", "--ethdebug", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--via-ir", "--ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--via-ir", "--ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, @@ -1447,7 +1455,7 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_outputs) }, { {"solc", "--via-ir", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, @@ -1455,15 +1463,15 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_outputs) }, { {"solc", "--via-ir", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--via-ir", "--ethdebug-runtime", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--via-ir", "--ethdebug-runtime", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--ethdebug-runtime", "--import-asm-json", tempDir.path().string() + "/input.json"}, @@ -1471,23 +1479,23 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_outputs) }, { {"solc", "--via-ir", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized.\n" + "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n" + "Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n" + "Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--debug-info", "ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n" + "Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--debug-info", "ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n" + "Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, @@ -1499,7 +1507,7 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_outputs) }, { {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.json"}, - "Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n" + "Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" } }; for (auto const& test: tests) @@ -1560,7 +1568,7 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_debug_info_ethdebug) static std::vector, std::vector, std::vector>> tests{ { {"solc", "--debug-info", "ethdebug", tempDir.path().string() + "/input.sol"}, - {"Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime.\n"}, + {"Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, {}, }, { @@ -1570,8 +1578,13 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_debug_info_ethdebug) }, { {"solc", "--debug-info", "ethdebug", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {"Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, + {}, + }, + { + {"solc", "--debug-info", "ethdebug", "--optimize", tempDir.path().string() + "/input.sol"}, + {"Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, {}, - {"/// ethdebug: enabled"}, }, { {"solc", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, @@ -1722,33 +1735,33 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_ethdebug_output) }, { {"solc", "--ethdebug", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "/// ethdebug: enabled"}, }, { {"solc", "--ethdebug-runtime", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, }, { {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, }, { {"solc", "--ethdebug", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "/// ethdebug: enabled"}, }, { {"solc", "--ethdebug-runtime", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, }, { {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, }, }; for (auto const& test: tests) diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index be3e25d33..85eeaebe3 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -663,12 +663,6 @@ BOOST_AUTO_TEST_CASE(ethdebug) BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ir, true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); - commandLineOptions = parseCommandLine({"solc", "contract.sol", "--debug-info", "ethdebug", "--ir-optimized"}); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.irOptimized, true); - BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); - BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); } BOOST_AUTO_TEST_SUITE_END() From 3bb6a0138ea7320eb5f72b8056c17951a51833ed Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 28 Jan 2025 11:06:29 +0100 Subject: [PATCH 0641/1340] eof: Fix condition when generating custom error for builtins available in EOF but not in legacy --- libyul/AsmAnalysis.cpp | 7 ++++--- .../eof/eof_identifiers_not_defined_in_legacy.yul | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 69f2e765e..b6dcbb08e 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -690,21 +690,22 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons bool AsmAnalyzer::validateInstructions(std::string_view _instructionIdentifier, langutil::SourceLocation const& _location) { // NOTE: This function uses the default EVM version instead of the currently selected one. - auto const& defaultEVMDialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt); + auto const& defaultEVMDialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}, std::nullopt); auto const builtinHandle = defaultEVMDialect.findBuiltin(_instructionIdentifier); if (builtinHandle && defaultEVMDialect.builtin(*builtinHandle).instruction.has_value()) return validateInstructions(*defaultEVMDialect.builtin(*builtinHandle).instruction, _location); solAssert(!m_eofVersion.has_value() || (*m_eofVersion == 1 && m_evmVersion == langutil::EVMVersion::prague())); // TODO: Change `prague()` to `EVMVersion{}` once EOF gets deployed - auto const& eofDialect = EVMDialect::strictAssemblyForEVM(EVMVersion::prague(), 1); + auto const& eofDialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion::prague(), 1); auto const eofBuiltinHandle = eofDialect.findBuiltin(_instructionIdentifier); if (eofBuiltinHandle) { auto const builtin = eofDialect.builtin(*eofBuiltinHandle); if (builtin.instruction.has_value()) return validateInstructions(*builtin.instruction, _location); - else if (!m_eofVersion.has_value()) + // If builtin is available in EOF but not available in legacy (and we build to legacy) generate custom error. + else if (!m_eofVersion.has_value() && !builtinHandle) { m_errorReporter.declarationError( 7223_error, diff --git a/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul index ab55fb21d..0b786893e 100644 --- a/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul +++ b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul @@ -18,7 +18,7 @@ // DeclarationError 7223: (6-18): Builtin function "auxdataloadn" is only available in EOF. // DeclarationError 4619: (26-35): Function "dataloadn" not found. // DeclarationError 7223: (43-52): Builtin function "eofcreate" is only available in EOF. -// DeclarationError 4619: (77-91): Function "returncontract" not found. +// DeclarationError 7223: (77-91): Builtin function "returncontract" is only available in EOF. // DeclarationError 4619: (110-115): Function "rjump" not found. // DeclarationError 4619: (122-128): Function "rjumpi" not found. // DeclarationError 4619: (135-140): Function "callf" not found. From 677c84a84c240245bf895381baa23ce10a4ba1ba Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 24 Jan 2025 11:22:31 +0100 Subject: [PATCH 0642/1340] eof: Disallow EOF builtins in inline assembly. --- libyul/backends/evm/EVMDialect.cpp | 86 ++++++++++--------- .../invalid/eof/eof_builtins_disallowed.sol | 15 ++++ ...builtins_disallowed_in_inline_assembly.sol | 16 ++++ 3 files changed, 75 insertions(+), 42 deletions(-) create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed_in_inline_assembly.sol diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 74599eb1c..611e95c39 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -381,50 +381,51 @@ std::vector> createBuiltins(langutil::EVMVe } else // EOF context { - builtins.emplace_back(createFunction( - "auxdataloadn", - 1, - 1, - EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::DATALOADN), - ControlFlowSideEffects::fromInstruction(evmasm::Instruction::DATALOADN), - {LiteralKind::Number}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == 1); - Literal const* literal = std::get_if(&_call.arguments.front()); - yulAssert(literal, ""); - yulAssert(literal->value.value() <= std::numeric_limits::max()); - _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); - } - )); - - builtins.emplace_back(createFunction( - "eofcreate", - 5, - 1, - EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE), - ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE), - {LiteralKind::String, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& context - ) { - yulAssert(_call.arguments.size() == 5); - Literal const* literal = std::get_if(&_call.arguments.front()); - auto const formattedLiteral = formatLiteral(*literal); - yulAssert(!util::contains(formattedLiteral, '.')); - auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); - yulAssert(containerID != nullptr); - yulAssert(*containerID <= std::numeric_limits::max()); - _assembly.appendEOFCreate(static_cast(*containerID)); - } + if (_objectAccess) + { + builtins.emplace_back(createFunction( + "auxdataloadn", + 1, + 1, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::DATALOADN), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::DATALOADN), + {LiteralKind::Number}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == 1); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal, ""); + yulAssert(literal->value.value() <= std::numeric_limits::max()); + _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); + } )); - if (_objectAccess) + builtins.emplace_back(createFunction( + "eofcreate", + 5, + 1, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE), + {LiteralKind::String, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& context + ) { + yulAssert(_call.arguments.size() == 5); + Literal const* literal = std::get_if(&_call.arguments.front()); + auto const formattedLiteral = formatLiteral(*literal); + yulAssert(!util::contains(formattedLiteral, '.')); + auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); + yulAssert(containerID != nullptr); + yulAssert(*containerID <= std::numeric_limits::max()); + _assembly.appendEOFCreate(static_cast(*containerID)); + } + )); + builtins.emplace_back(createFunction( "returncontract", 3, @@ -448,6 +449,7 @@ std::vector> createBuiltins(langutil::EVMVe _assembly.appendReturnContract(static_cast(*containerID)); } )); + } } yulAssert( ranges::all_of(builtins, [](std::optional const& _builtinFunction){ diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed.sol new file mode 100644 index 000000000..617aeff98 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed.sol @@ -0,0 +1,15 @@ +contract C { + function f() view public { + assembly { + eofcreate("a", 0, 0, 0, 0) + returncontract("a", 0) + auxdataloadn(0) + } + } +} +// ==== +// bytecodeFormat: legacy +// ---- +// DeclarationError 7223: (75-84): Builtin function "eofcreate" is only available in EOF. +// DeclarationError 7223: (114-128): Builtin function "returncontract" is only available in EOF. +// DeclarationError 7223: (149-161): Builtin function "auxdataloadn" is only available in EOF. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed_in_inline_assembly.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed_in_inline_assembly.sol new file mode 100644 index 000000000..a2a6540ef --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed_in_inline_assembly.sol @@ -0,0 +1,16 @@ +// TODO: They should be available in some way in the context of inline assembly. For now it's disallowed them. +contract C { + function f() view public { + assembly { + eofcreate("a", 0, 0, 0, 0) + returncontract("a", 0) + auxdataloadn(0) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// DeclarationError 4619: (186-195): Function "eofcreate" not found. +// DeclarationError 4619: (225-239): Function "returncontract" not found. +// DeclarationError 4619: (260-272): Function "auxdataloadn" not found. From 233a5081835a04939ccf85dfb5286c0b53d23c66 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Jan 2025 09:36:54 +0100 Subject: [PATCH 0643/1340] Enable c++20 in CMake --- Changelog.md | 4 ++++ cmake/EthCompilerSettings.cmake | 12 ++++++------ cmake/EthToolchains.cmake | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Changelog.md b/Changelog.md index c00adf0fd..f37cfcef0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -18,6 +18,10 @@ Bugfixes: * Yul: Fix internal compiler error when a code generation error should be reported instead. +Build system: + * Switch from C++17 to C++20 as the target standard. + + ### 0.8.28 (2024-10-09) Language Features: diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index ccbd8a6c4..f3db974ae 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -89,9 +89,9 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA # Additional GCC-specific compiler settings. if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") - # Check that we've got GCC 8.0 or newer. - if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0)) - message(FATAL_ERROR "${PROJECT_NAME} requires g++ 8.0 or greater.") + # Check that we've got GCC 11.0 or newer. + if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0)) + message(FATAL_ERROR "${PROJECT_NAME} requires g++ 11.0 or greater.") endif () # Use fancy colors in the compiler diagnostics @@ -99,9 +99,9 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA # Additional Clang-specific compiler settings. elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - # Check that we've got clang 7.0 or newer. - if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.0)) - message(FATAL_ERROR "${PROJECT_NAME} requires clang++ 7.0 or greater.") + # Check that we've got clang 14.0 or newer. + if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0)) + message(FATAL_ERROR "${PROJECT_NAME} requires clang++ 14.0 or greater.") endif () if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") diff --git a/cmake/EthToolchains.cmake b/cmake/EthToolchains.cmake index c2306bd75..1d5dc62f3 100644 --- a/cmake/EthToolchains.cmake +++ b/cmake/EthToolchains.cmake @@ -1,6 +1,6 @@ -# Require C++17. +# Require C++20. if (NOT DEFINED CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 17) # This requires at least CMake 3.8 to accept this C++17 flag. + set(CMAKE_CXX_STANDARD 20) # This requires at least CMake 3.12 to accept this C++20 flag. endif () set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_EXTENSIONS OFF) From 90f07403f9fb9afa454a72f2d2cef7236fdd5f4e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Jan 2025 09:37:42 +0100 Subject: [PATCH 0644/1340] docs: Update minimum compiler versions to gcc11 and clang14 --- docs/installing-solidity.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 57499b812..129d1d3a8 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -372,8 +372,8 @@ Minimum Compiler Versions The following C++ compilers and their minimum versions can build the Solidity codebase: -- `GCC `_, version 8+ -- `Clang `_, version 7+ +- `GCC `_, version 11+ +- `Clang `_, version 14+ - `MSVC `_, version 2019+ Prerequisites - macOS From 044d34e102c7c2d4a9fc42568da13086430b4b73 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Jan 2025 09:38:18 +0100 Subject: [PATCH 0645/1340] ci: remove cxx20 job --- .circleci/config.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index be04d2a6f..da4be0e35 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1093,21 +1093,6 @@ jobs: - solc/solc-static-linux - matrix_notify_failure_unless_pr - # Builds in C++20 mode and uses debug build in order to speed up. - # Do *NOT* store any artifacts or workspace as we don't run tests on this build. - b_ubu_cxx20: - <<: *base_ubuntu2404_large - environment: - <<: *base_ubuntu2404_large_env - CMAKE_BUILD_TYPE: Debug - # gold is more memory-efficient than the default, allows us to stay with the "large" resource class without OOM errors - CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS=-fuse-ld=gold - MAKEFLAGS: -j 6 - steps: - - checkout - - run_build - - matrix_notify_failure_unless_pr - b_ubu_2204: <<: *base_ubuntu2204_large steps: @@ -1873,7 +1858,6 @@ workflows: # build-only - b_docs: *requires_nothing - - b_ubu_cxx20: *requires_nothing - b_ubu_ossfuzz: *requires_nothing - b_ubu_2204: *requires_nothing - b_ubu_2204_clang: *requires_nothing From e97e99366f24029a57f0280a9330bd2bfe776983 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Jan 2025 09:43:15 +0100 Subject: [PATCH 0646/1340] fix various compiler warnings and errors due to version bump and cxx20 --- cmake/EthCompilerSettings.cmake | 8 ++++ libevmasm/ConstantOptimiser.cpp | 22 +++++++++++ libevmasm/ConstantOptimiser.h | 19 ++-------- libevmasm/PeepholeOptimiser.cpp | 6 +++ libevmasm/PeepholeOptimiser.h | 6 +-- libsolidity/ast/Types.cpp | 38 ++++++++++++++----- libsolidity/ast/Types.h | 4 ++ libsolidity/experimental/ast/TypeSystem.cpp | 3 +- .../experimental/ast/TypeSystemHelper.cpp | 2 +- libsolidity/interface/GasEstimator.cpp | 2 +- libyul/optimiser/ExpressionSplitter.cpp | 7 ++++ libyul/optimiser/ExpressionSplitter.h | 8 ++-- libyul/optimiser/FunctionHoister.cpp | 3 ++ libyul/optimiser/FunctionHoister.h | 3 +- solc/CommandLineInterface.cpp | 1 - solc/CommandLineParser.cpp | 3 -- test/EVMHost.cpp | 12 ++++++ test/tools/ossfuzz/CMakeLists.txt | 28 ++++++++------ .../tools/ossfuzz/StackReuseCodegenFuzzer.cpp | 2 +- 19 files changed, 121 insertions(+), 56 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index f3db974ae..cc8435ed3 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -94,6 +94,12 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA message(FATAL_ERROR "${PROJECT_NAME} requires g++ 11.0 or greater.") endif () + # GCC 12 emits warnings for string concatenations with operator+ under O3 + # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105651 + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0) + add_compile_options(-Wno-error=restrict) + endif () + # Use fancy colors in the compiler diagnostics add_compile_options(-fdiagnostics-color) @@ -104,6 +110,8 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA message(FATAL_ERROR "${PROJECT_NAME} requires clang++ 14.0 or greater.") endif () + # use std::invoke_result, superseding std::result_of which has been removed in c++20 + add_compile_definitions(BOOST_ASIO_HAS_STD_INVOKE_RESULT) if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") # Set stack size to 32MB - by default Apple's clang defines a stack size of 8MB. # Normally 16MB is enough to run all tests, but it will exceed the stack, if -DSANITIZE=address is used. diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 6fdb42bd7..7cf00fc9e 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -140,6 +140,11 @@ bigint LiteralMethod::gasNeeded() const ); } +AssemblyItems LiteralMethod::execute(Assembly&) const +{ + return {}; +} + bigint CodeCopyMethod::gasNeeded() const { return combineGas( @@ -226,6 +231,23 @@ AssemblyItems CodeCopyMethod::copyRoutine(AssemblyItem* _pushData) const } } +ComputeMethod::ComputeMethod(Params const& _params, u256 const& _value): + ConstantOptimisationMethod(_params, _value) +{ + m_routine = findRepresentation(m_value); + assertThrow( + checkRepresentation(m_value, m_routine), + OptimizerException, + "Invalid constant expression created." + ); +} +ComputeMethod::~ComputeMethod() = default; + +AssemblyItems ComputeMethod::execute(Assembly&) const +{ + return m_routine; +} + AssemblyItems ComputeMethod::findRepresentation(u256 const& _value) { if (_value < 0x10000) diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index 7a929939e..4952d7985 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -108,7 +108,7 @@ class LiteralMethod: public ConstantOptimisationMethod explicit LiteralMethod(Params const& _params, u256 const& _value): ConstantOptimisationMethod(_params, _value) {} bigint gasNeeded() const override; - AssemblyItems execute(Assembly&) const override { return AssemblyItems{}; } + AssemblyItems execute(Assembly&) const override; }; /** @@ -132,22 +132,11 @@ class CodeCopyMethod: public ConstantOptimisationMethod class ComputeMethod: public ConstantOptimisationMethod { public: - explicit ComputeMethod(Params const& _params, u256 const& _value): - ConstantOptimisationMethod(_params, _value) - { - m_routine = findRepresentation(m_value); - assertThrow( - checkRepresentation(m_value, m_routine), - OptimizerException, - "Invalid constant expression created." - ); - } + ComputeMethod(Params const& _params, u256 const& _value); + ~ComputeMethod() override; bigint gasNeeded() const override { return gasNeeded(m_routine); } - AssemblyItems execute(Assembly&) const override - { - return m_routine; - } + AssemblyItems execute(Assembly&) const override; protected: /// Tries to recursively find a way to compute @a _value. diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 64650eaee..3129efb4d 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -709,6 +709,12 @@ size_t numberOfPops(AssemblyItems const& _items) } +PeepholeOptimiser::PeepholeOptimiser(AssemblyItems& _items, langutil::EVMVersion const _evmVersion): + m_items(_items), + m_evmVersion(_evmVersion) +{ +} + bool PeepholeOptimiser::optimise() { // Avoid referencing immutables too early by using approx. counting in bytesRequired() diff --git a/libevmasm/PeepholeOptimiser.h b/libevmasm/PeepholeOptimiser.h index 8e3161b21..2a1b9ae5b 100644 --- a/libevmasm/PeepholeOptimiser.h +++ b/libevmasm/PeepholeOptimiser.h @@ -43,11 +43,7 @@ class PeepholeOptimisationMethod class PeepholeOptimiser { public: - explicit PeepholeOptimiser(AssemblyItems& _items, langutil::EVMVersion const _evmVersion): - m_items(_items), - m_evmVersion(_evmVersion) - { - } + explicit PeepholeOptimiser(AssemblyItems& _items, langutil::EVMVersion _evmVersion); virtual ~PeepholeOptimiser() = default; bool optimise(); diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 95f249516..c77a6d0b6 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -661,8 +661,12 @@ bool IntegerType::operator==(Type const& _other) const { if (_other.category() != category()) return false; - IntegerType const& other = dynamic_cast(_other); - return other.m_bits == m_bits && other.m_modifier == m_modifier; + return *this == dynamic_cast(_other); +} + +bool IntegerType::operator==(IntegerType const& _other) const +{ + return _other.m_bits == m_bits && _other.m_modifier == m_modifier; } std::string IntegerType::toString(bool) const @@ -1699,17 +1703,21 @@ bool ArrayType::operator==(Type const& _other) const { if (_other.category() != category()) return false; - ArrayType const& other = dynamic_cast(_other); + return *this == dynamic_cast(_other); +} + +bool ArrayType::operator==(ArrayType const& _other) const +{ if ( - !equals(other) || - other.isByteArray() != isByteArray() || - other.isString() != isString() || - other.isDynamicallySized() != isDynamicallySized() + !equals(_other) || + _other.isByteArray() != isByteArray() || + _other.isString() != isString() || + _other.isDynamicallySized() != isDynamicallySized() ) return false; - if (*other.baseType() != *baseType()) + if (*_other.baseType() != *baseType()) return false; - return isDynamicallySized() || length() == other.length(); + return isDynamicallySized() || length() == _other.length(); } BoolResult ArrayType::validForLocation(DataLocation _loc) const @@ -2704,7 +2712,12 @@ bool UserDefinedValueType::operator==(Type const& _other) const if (_other.category() != category()) return false; UserDefinedValueType const& other = dynamic_cast(_other); - return other.definition() == definition(); + return *this == other; +} + +bool UserDefinedValueType::operator==(UserDefinedValueType const& _other) const +{ + return _other.definition() == definition(); } std::string UserDefinedValueType::toString(bool /* _withoutDataLocation */) const @@ -4058,6 +4071,11 @@ bool ModifierType::operator==(Type const& _other) const { if (_other.category() != category()) return false; + return *this == dynamic_cast(_other); +} + +bool ModifierType::operator==(ModifierType const& _other) const +{ ModifierType const& other = dynamic_cast(_other); if (m_parameterTypes.size() != other.m_parameterTypes.size()) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index c64236202..aa14cf6b9 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -495,6 +495,7 @@ class IntegerType: public Type TypeResult unaryOperatorResult(Token _operator) const override; TypeResult binaryOperatorResult(Token _operator, Type const* _other) const override; + bool operator==(IntegerType const& _other) const; bool operator==(Type const& _other) const override; unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : m_bits / 8; } @@ -854,6 +855,7 @@ class ArrayType: public ReferenceType BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override; BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override; std::string richIdentifier() const override; + bool operator==(ArrayType const& _other) const; bool operator==(Type const& _other) const override; unsigned calldataEncodedSize(bool) const override; unsigned calldataEncodedTailSize() const override; @@ -1148,6 +1150,7 @@ class UserDefinedValueType: public Type Declaration const* typeDefinition() const override; std::string richIdentifier() const override; + bool operator==(UserDefinedValueType const& _other) const; bool operator==(Type const& _other) const override; unsigned calldataEncodedSize(bool _padded) const override { return underlyingType().calldataEncodedSize(_padded); } @@ -1625,6 +1628,7 @@ class ModifierType: public Type bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } std::string richIdentifier() const override; bool operator==(Type const& _other) const override; + bool operator==(ModifierType const& _other) const; std::string toString(bool _withoutDataLocation) const override; protected: std::vector> makeStackItems() const override { return {}; } diff --git a/libsolidity/experimental/ast/TypeSystem.cpp b/libsolidity/experimental/ast/TypeSystem.cpp index 059054dcd..5198743ed 100644 --- a/libsolidity/experimental/ast/TypeSystem.cpp +++ b/libsolidity/experimental/ast/TypeSystem.cpp @@ -24,7 +24,8 @@ #include -#include +#include + #include #include #include diff --git a/libsolidity/experimental/ast/TypeSystemHelper.cpp b/libsolidity/experimental/ast/TypeSystemHelper.cpp index 9ad18e160..b01bc0529 100644 --- a/libsolidity/experimental/ast/TypeSystemHelper.cpp +++ b/libsolidity/experimental/ast/TypeSystemHelper.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp index fd3fbbc02..4313fad7f 100644 --- a/libsolidity/interface/GasEstimator.cpp +++ b/libsolidity/interface/GasEstimator.cpp @@ -109,7 +109,7 @@ std::set GasEstimator::finestNodesAtLocation( { std::map locations; std::set nodes; - SimpleASTVisitor visitor(std::function(), [&](ASTNode const& _n) + SimpleASTVisitor visitor([](ASTNode const&) { return false; }, [&](ASTNode const& _n) { if (!locations.count(_n.location())) { diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 1bdaa552b..649bd8583 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -35,6 +35,13 @@ using namespace solidity::yul; using namespace solidity::util; using namespace solidity::langutil; +ExpressionSplitter::ExpressionSplitter(Dialect const& _dialect, NameDispenser& _nameDispenser): + m_dialect(_dialect), + m_nameDispenser(_nameDispenser) +{} + +ExpressionSplitter::~ExpressionSplitter() = default; + void ExpressionSplitter::run(OptimiserStepContext& _context, Block& _ast) { ExpressionSplitter{_context.dialect, _context.dispenser}(_ast); diff --git a/libyul/optimiser/ExpressionSplitter.h b/libyul/optimiser/ExpressionSplitter.h index 2581b23de..739916317 100644 --- a/libyul/optimiser/ExpressionSplitter.h +++ b/libyul/optimiser/ExpressionSplitter.h @@ -68,13 +68,11 @@ class ExpressionSplitter: public ASTModifier void operator()(Block& _block) override; private: - explicit ExpressionSplitter( + ExpressionSplitter( Dialect const& _dialect, NameDispenser& _nameDispenser - ): - m_dialect(_dialect), - m_nameDispenser(_nameDispenser) - { } + ); + ~ExpressionSplitter() override; /// Replaces the expression by a variable if it is a function call or functional /// instruction. The declaration of the variable is appended to m_statementsToPrefix. diff --git a/libyul/optimiser/FunctionHoister.cpp b/libyul/optimiser/FunctionHoister.cpp index 32df3b121..356056a99 100644 --- a/libyul/optimiser/FunctionHoister.cpp +++ b/libyul/optimiser/FunctionHoister.cpp @@ -30,6 +30,9 @@ using namespace solidity; using namespace solidity::yul; +FunctionHoister::FunctionHoister() = default; +FunctionHoister::~FunctionHoister() = default; + void FunctionHoister::operator()(Block& _block) { bool topLevel = m_isTopLevel; diff --git a/libyul/optimiser/FunctionHoister.h b/libyul/optimiser/FunctionHoister.h index 04d7f64e3..8242c9f47 100644 --- a/libyul/optimiser/FunctionHoister.h +++ b/libyul/optimiser/FunctionHoister.h @@ -46,7 +46,8 @@ class FunctionHoister: public ASTModifier void operator()(Block& _block) override; private: - FunctionHoister() = default; + FunctionHoister(); + ~FunctionHoister() override; bool m_isTopLevel = true; std::vector m_functions; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index f2bb4af10..784967c52 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -118,7 +118,6 @@ std::ostream& CommandLineInterface::serr(bool _markAsUsed) static std::string const g_stdinFileName = ""; static std::string const g_strAbi = "abi"; static std::string const g_strAsm = "asm"; -static std::string const g_strAst = "ast"; static std::string const g_strBinary = "bin"; static std::string const g_strBinaryRuntime = "bin-runtime"; static std::string const g_strContracts = "contracts"; diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 592914404..c888d9a53 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -91,7 +91,6 @@ static std::string const g_strOutputDir = "output-dir"; static std::string const g_strOverwrite = "overwrite"; static std::string const g_strRevertStrings = "revert-strings"; static std::string const g_strStopAfter = "stop-after"; -static std::string const g_strParsing = "parsing"; /// Possible arguments to for --revert-strings static std::set const g_revertStringsArgs @@ -102,8 +101,6 @@ static std::set const g_revertStringsArgs revertStringsToString(RevertStrings::VerboseDebug) }; -static std::string const g_strSources = "sources"; -static std::string const g_strSourceList = "sourceList"; static std::string const g_strStandardJSON = "standard-json"; static std::string const g_strStrictAssembly = "strict-assembly"; static std::string const g_strSwarm = "swarm"; diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index fdaf3f35b..5370542c7 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -20,8 +20,20 @@ * for testing purposes. */ +// Weird issue when compiling with O3 on gcc 12 and later due to usage of vector (aka bytes) as std::map key +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98465 +// also clang doesn't know stringop-overread +#if defined(__GNUC__) && !defined(__clang__) // GCC-specific pragma +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overread" +#endif + #include +#if defined(__GNUC__) && !defined(__clang__) // GCC-specific pragma +#pragma GCC diagnostic pop +#endif + #include #include diff --git a/test/tools/ossfuzz/CMakeLists.txt b/test/tools/ossfuzz/CMakeLists.txt index 9449eddba..da1896892 100644 --- a/test/tools/ossfuzz/CMakeLists.txt +++ b/test/tools/ossfuzz/CMakeLists.txt @@ -74,7 +74,16 @@ if (OSSFUZZ) # are auto-generated by the protobuf compiler because the compiler # does not generate warning-free C++ bindings with regard to # upstream Clang builds that are used by ossfuzz. - target_compile_options(yul_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + set( + SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS + -Wno-sign-conversion + -Wno-suggest-destructor-override + -Wno-inconsistent-missing-destructor-override + -Wno-shorten-64-to-32 + -Wno-deprecated + ) + + target_compile_options(yul_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) add_executable( yul_proto_diff_ossfuzz @@ -92,7 +101,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(yul_proto_diff_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(yul_proto_diff_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + target_compile_options(yul_proto_diff_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) add_executable(yul_proto_diff_custom_mutate_ossfuzz yulProto_diff_ossfuzz.cpp @@ -110,7 +119,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(yul_proto_diff_custom_mutate_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(yul_proto_diff_custom_mutate_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + target_compile_options(yul_proto_diff_custom_mutate_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) add_executable(stack_reuse_codegen_ossfuzz StackReuseCodegenFuzzer.cpp @@ -130,12 +139,7 @@ if (OSSFUZZ) set_target_properties(stack_reuse_codegen_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) target_compile_options(stack_reuse_codegen_ossfuzz PUBLIC ${COMPILE_OPTIONS} - -Wno-sign-conversion - -Wno-inconsistent-missing-destructor-override - -Wno-unused-parameter - -Wno-zero-length-array - -Wno-suggest-destructor-override - -Wno-shorten-64-to-32 + ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS} ) add_executable(abiv2_proto_ossfuzz @@ -156,7 +160,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(abiv2_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(abiv2_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + target_compile_options(abiv2_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) add_executable(abiv2_isabelle_ossfuzz AbiV2IsabelleFuzzer.cpp @@ -178,7 +182,7 @@ if (OSSFUZZ) gmp.a ) set_target_properties(abiv2_isabelle_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(abiv2_isabelle_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + target_compile_options(abiv2_isabelle_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) add_executable(sol_proto_ossfuzz solProtoFuzzer.cpp @@ -198,7 +202,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(sol_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(sol_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override -Wno-shorten-64-to-32) + target_compile_options(sol_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} ${SILENCE_PROTOBUF_AUTOGENERATED_WARNINGS}) else() add_library(solc_ossfuzz solc_ossfuzz.cpp diff --git a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp index de2fdd286..71a4ff54a 100644 --- a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp +++ b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp @@ -52,7 +52,7 @@ static evmc::VM evmone = evmc::VM{evmc_create_evmone()}; namespace { /// @returns true if there are recursive functions, false otherwise. -bool recursiveFunctionExists(Dialect const& _dialect, yul::Object& _object) +bool recursiveFunctionExists(Dialect const& /*_dialect*/, yul::Object& _object) { auto recursiveFunctions = CallGraphGenerator::callGraph(_object.code()->root()).recursiveFunctions(); for(auto&& [function, variables]: CompilabilityChecker{ From eceea82223dce3cffb1cf9f4640d6851b3d41969 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Jan 2025 09:43:59 +0100 Subject: [PATCH 0647/1340] ci: switch static to fully static build and bump to ubu 2024 --- .circleci/config.yml | 6 +++--- Changelog.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index da4be0e35..164694e45 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1073,10 +1073,10 @@ jobs: # to avoid glibc incompatibilities. # See: https://github.com/ethereum/solidity/issues/13954 # On large runs 2x faster than on medium. 3x on xlarge. - <<: *base_ubuntu2004_xlarge + <<: *base_ubuntu2404_xlarge environment: - <<: *base_ubuntu2004_xlarge_env - CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DSOLC_STATIC_STDLIBS=ON + <<: *base_ubuntu2404_xlarge_env + CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DSOLC_LINK_STATIC=ON steps: - checkout - run_build diff --git a/Changelog.md b/Changelog.md index f37cfcef0..b942f068f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -19,9 +19,9 @@ Bugfixes: Build system: + * Linux release builds are fully static again and no longer depend on ``glibc``. * Switch from C++17 to C++20 as the target standard. - ### 0.8.28 (2024-10-09) Language Features: From 5833ea3c49275d5af2f0916192e5aa9a9bd0b9cd Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 23 Jan 2025 09:01:27 +0100 Subject: [PATCH 0648/1340] drop ubuntu focal support --- ReleaseChecklist.md | 3 ++- scripts/deps-ppa/static_z3.sh | 2 +- scripts/release_ppa.sh | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index a70afe0cb..758ef79dd 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -94,7 +94,8 @@ At least a day before the release: **SERIOUSLY: DO NOT PROCEED EARLIER!!!** - [ ] *After* the package with the static build is *published*, use it to create packages for older Ubuntu versions. Copy the static package to the [``~ethereum/ethereum`` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum) - for the destination series ``Trusty``, ``Xenial`` and ``Bionic`` while selecting ``Copy existing binaries``. + for the destination series ``Trusty``, ``Xenial``, ``Bionic``, and ``Focal`` + while selecting ``Copy existing binaries``. ### Release solc-js - [ ] Wait until solc-bin was properly deployed. You can test this via remix - a test run through remix is advisable anyway. diff --git a/scripts/deps-ppa/static_z3.sh b/scripts/deps-ppa/static_z3.sh index 9e273188c..140c40c6a 100755 --- a/scripts/deps-ppa/static_z3.sh +++ b/scripts/deps-ppa/static_z3.sh @@ -41,7 +41,7 @@ sourcePPAConfig # Sanity check checkDputEntries "\[cpp-build-deps\]" -DISTRIBUTIONS="focal jammy noble oracular" +DISTRIBUTIONS="jammy noble oracular" for distribution in $DISTRIBUTIONS do diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 773c43cc9..cf8df3d6c 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -66,9 +66,9 @@ sourcePPAConfig packagename=solc # This needs to be a still active release -static_build_distribution=focal +static_build_distribution=noble -DISTRIBUTIONS="focal jammy noble oracular" +DISTRIBUTIONS="jammy noble oracular" if is_release then From e4b82f9c4432155907db3f06acb150f0f597f8e1 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 23 Jan 2025 09:06:20 +0100 Subject: [PATCH 0649/1340] drop ubuntu ubuntu 20.04 docker image --- .github/workflows/buildpack-deps.yml | 1 - .../buildpack-deps/Dockerfile.ubuntu2004 | 108 ------------------ 2 files changed, 109 deletions(-) delete mode 100644 scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index ad2e58270..00d08372d 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -6,7 +6,6 @@ on: paths: - 'scripts/docker/buildpack-deps/Dockerfile.emscripten' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz' - - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2004' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2204' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang' diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 deleted file mode 100644 index 7592f55ec..000000000 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 +++ /dev/null @@ -1,108 +0,0 @@ -# vim:syntax=dockerfile -#------------------------------------------------------------------------------ -# Dockerfile for building and testing Solidity Compiler on CI -# Target: Ubuntu 19.04 (Disco Dingo) -# 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 -# -# (c) 2016-2019 solidity contributors. -#------------------------------------------------------------------------------ -FROM buildpack-deps:focal AS base -LABEL version="26" - -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 \ - cmake \ - jq \ - libboost-filesystem-dev \ - libboost-program-options-dev \ - libboost-system-dev \ - libboost-test-dev \ - lsof \ - ninja-build \ - python3-pip \ - python3-sphinx \ - software-properties-common \ - sudo \ - unzip; \ - pip3 install \ - codecov \ - colorama \ - deepdiff \ - parsec \ - pygments-lexer-solidity \ - pylint \ - requests \ - tabulate \ - z3-solver; - -# TODO: we could eliminate duplication by using a Dockerfile extension like: -# https://github.com/edrevo/dockerfile-plus?tab=readme-ov-file#dockerfile -# or mult-stage builds, then we could define a base image which would be included/used by all the other Dockerfiles. -# Or we could move the common parts to a shell script, copying and calling it from the Dockerfiles. -# Eldarica -RUN set -ex; \ - apt-get update; \ - apt-get install -qqy \ - openjdk-11-jre; \ - eldarica_version="2.1"; \ - wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ - test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ - unzip /opt/eld_binaries.zip -d /opt; \ - rm -f /opt/eld_binaries.zip; - -# CVC5 -RUN set -ex; \ - cvc5_version="1.2.0"; \ - cvc5_archive_name="cvc5-Linux-x86_64-static"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ - unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ - rm -f /opt/cvc5.zip; - -# Z3 -RUN set -ex; \ - z3_version="4.13.3"; \ - z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ - wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ - test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ - unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ - rm -f /opt/z3.zip; - -FROM base AS libraries - -# EVMONE -RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ - cd /usr; \ - tar -xf /usr/src/evmone.tar.gz; \ - rm -rf /usr/src/evmone.tar.gz - -FROM base -COPY --from=libraries /usr/lib /usr/lib -COPY --from=libraries /usr/bin /usr/bin -COPY --from=libraries /usr/include /usr/include -COPY --from=libraries /opt/eldarica /opt/eldarica -ENV PATH="$PATH:/opt/eldarica" From bc0b9c1966355b140e6464ed7d2b3bdc9a39d111 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 23 Jan 2025 12:17:49 +0100 Subject: [PATCH 0650/1340] eof: Update `yulSyntaxTests` tests for EOF --- test/libyul/yulSyntaxTests/builtin_function_literal.yul | 2 ++ test/libyul/yulSyntaxTests/datacopy_shadowing.yul | 2 ++ test/libyul/yulSyntaxTests/dataoffset_shadowing.yul | 2 ++ test/libyul/yulSyntaxTests/datasize_shadowing.yul | 2 ++ .../yulSyntaxTests/eof/builtin_function_literal.yul | 9 +++++++++ test/libyul/yulSyntaxTests/eof/datacopy_shadowing.yul | 7 +++++++ test/libyul/yulSyntaxTests/eof/dataoffset_shadowing.yul | 7 +++++++ test/libyul/yulSyntaxTests/eof/datasize_shadowing.yul | 7 +++++++ .../yulSyntaxTests/eof/loadimmutable_shadowing.yul | 8 ++++++++ ...iltin_with_literal_argument_into_literal_argument.yul | 8 ++++++++ test/libyul/yulSyntaxTests/eof/selfdestruct.yul | 7 +++++++ .../libyul/yulSyntaxTests/eof/setimmutable_shadowing.yul | 8 ++++++++ test/libyul/yulSyntaxTests/hex_switch_case.yul | 2 +- test/libyul/yulSyntaxTests/hex_switch_case_long.yul | 4 ++-- test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul | 2 ++ test/libyul/yulSyntaxTests/loadimmutable.yul | 1 + test/libyul/yulSyntaxTests/loadimmutable_bad_literal.yul | 1 + test/libyul/yulSyntaxTests/loadimmutable_shadowing.yul | 1 + .../loadimmutable_without_setimmutable.yul | 2 ++ test/libyul/yulSyntaxTests/metadata_access.yul | 2 ++ test/libyul/yulSyntaxTests/metadata_access_2.yul | 2 ++ test/libyul/yulSyntaxTests/metadata_access_subobject.yul | 2 ++ test/libyul/yulSyntaxTests/objects/data.yul | 2 ++ test/libyul/yulSyntaxTests/objects/data_access.yul | 2 ++ test/libyul/yulSyntaxTests/objects/datacopy.yul | 2 ++ .../yulSyntaxTests/objects/dataoffset_nonliteral.yul | 2 ++ .../yulSyntaxTests/objects/dataoffset_nonstring.yul | 2 ++ .../yulSyntaxTests/objects/dataoffset_notfound.yul | 2 ++ .../yulSyntaxTests/objects/datasize_nonliteral.yul | 2 ++ .../libyul/yulSyntaxTests/objects/datasize_nonstring.yul | 2 ++ test/libyul/yulSyntaxTests/objects/datasize_notfound.yul | 2 ++ test/libyul/yulSyntaxTests/objects/subobject_access.yul | 2 ++ .../libyul/yulSyntaxTests/opcode_for_function_args_1.yul | 4 ++-- .../libyul/yulSyntaxTests/opcode_for_function_args_2.yul | 4 ++-- test/libyul/yulSyntaxTests/opcode_for_functions.yul | 4 ++-- ...iltin_with_literal_argument_into_literal_argument.yul | 1 + test/libyul/yulSyntaxTests/selfdestruct.yul | 2 ++ test/libyul/yulSyntaxTests/setimmutable.yul | 1 + test/libyul/yulSyntaxTests/setimmutable_bad_literal.yul | 1 + test/libyul/yulSyntaxTests/setimmutable_shadowing.yul | 1 + test/libyul/yulSyntaxTests/simple_functions.yul | 2 +- .../libyul/yulSyntaxTests/string_literal_switch_case.yul | 2 +- .../yulSyntaxTests/string_literal_too_long_immutable.yul | 1 + 43 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 test/libyul/yulSyntaxTests/eof/builtin_function_literal.yul create mode 100644 test/libyul/yulSyntaxTests/eof/datacopy_shadowing.yul create mode 100644 test/libyul/yulSyntaxTests/eof/dataoffset_shadowing.yul create mode 100644 test/libyul/yulSyntaxTests/eof/datasize_shadowing.yul create mode 100644 test/libyul/yulSyntaxTests/eof/loadimmutable_shadowing.yul create mode 100644 test/libyul/yulSyntaxTests/eof/passing_builtin_with_literal_argument_into_literal_argument.yul create mode 100644 test/libyul/yulSyntaxTests/eof/selfdestruct.yul create mode 100644 test/libyul/yulSyntaxTests/eof/setimmutable_shadowing.yul diff --git a/test/libyul/yulSyntaxTests/builtin_function_literal.yul b/test/libyul/yulSyntaxTests/builtin_function_literal.yul index 22f721614..c975648ae 100644 --- a/test/libyul/yulSyntaxTests/builtin_function_literal.yul +++ b/test/libyul/yulSyntaxTests/builtin_function_literal.yul @@ -1,6 +1,8 @@ { datasize(x,1) } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 7000: (4-12): Function "datasize" expects 1 arguments but got 2. // TypeError 9114: (4-12): Function expects direct literals as arguments. diff --git a/test/libyul/yulSyntaxTests/datacopy_shadowing.yul b/test/libyul/yulSyntaxTests/datacopy_shadowing.yul index 3f14f4722..7466af6c3 100644 --- a/test/libyul/yulSyntaxTests/datacopy_shadowing.yul +++ b/test/libyul/yulSyntaxTests/datacopy_shadowing.yul @@ -1,5 +1,7 @@ { function datacopy(a, b, c) {} } +// ==== +// bytecodeFormat: legacy // ---- // ParserError 5568: (15-23): Cannot use builtin function name "datacopy" as identifier name. diff --git a/test/libyul/yulSyntaxTests/dataoffset_shadowing.yul b/test/libyul/yulSyntaxTests/dataoffset_shadowing.yul index fb32fb61c..db02e90e4 100644 --- a/test/libyul/yulSyntaxTests/dataoffset_shadowing.yul +++ b/test/libyul/yulSyntaxTests/dataoffset_shadowing.yul @@ -1,5 +1,7 @@ { function dataoffset(a) -> b {} } +// ==== +// bytecodeFormat: legacy // ---- // ParserError 5568: (15-25): Cannot use builtin function name "dataoffset" as identifier name. diff --git a/test/libyul/yulSyntaxTests/datasize_shadowing.yul b/test/libyul/yulSyntaxTests/datasize_shadowing.yul index 379401754..79e500949 100644 --- a/test/libyul/yulSyntaxTests/datasize_shadowing.yul +++ b/test/libyul/yulSyntaxTests/datasize_shadowing.yul @@ -1,5 +1,7 @@ { function datasize(a) -> b {} } +// ==== +// bytecodeFormat: legacy // ---- // ParserError 5568: (15-23): Cannot use builtin function name "datasize" as identifier name. diff --git a/test/libyul/yulSyntaxTests/eof/builtin_function_literal.yul b/test/libyul/yulSyntaxTests/eof/builtin_function_literal.yul new file mode 100644 index 000000000..d70f5a7bf --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/builtin_function_literal.yul @@ -0,0 +1,9 @@ +{ + auxdataloadn(x,1) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 7000: (6-18): Function "auxdataloadn" expects 1 arguments but got 2. +// TypeError 9114: (6-18): Function expects direct literals as arguments. +// DeclarationError 8198: (19-20): Identifier "x" not found. diff --git a/test/libyul/yulSyntaxTests/eof/datacopy_shadowing.yul b/test/libyul/yulSyntaxTests/eof/datacopy_shadowing.yul new file mode 100644 index 000000000..b44c2ba0d --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/datacopy_shadowing.yul @@ -0,0 +1,7 @@ +{ + function datacopy(a, b, c) {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// DeclarationError 5017: (6-35): The identifier "datacopy" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/eof/dataoffset_shadowing.yul b/test/libyul/yulSyntaxTests/eof/dataoffset_shadowing.yul new file mode 100644 index 000000000..7c525bcc4 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/dataoffset_shadowing.yul @@ -0,0 +1,7 @@ +{ + function dataoffset(a) -> b {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// DeclarationError 5017: (6-36): The identifier "dataoffset" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/eof/datasize_shadowing.yul b/test/libyul/yulSyntaxTests/eof/datasize_shadowing.yul new file mode 100644 index 000000000..573451842 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/datasize_shadowing.yul @@ -0,0 +1,7 @@ +{ + function datasize(a) -> b {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// DeclarationError 5017: (6-34): The identifier "datasize" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/eof/loadimmutable_shadowing.yul b/test/libyul/yulSyntaxTests/eof/loadimmutable_shadowing.yul new file mode 100644 index 000000000..a9fc26067 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/loadimmutable_shadowing.yul @@ -0,0 +1,8 @@ +{ + function loadimmutable(a) {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// dialect: evm +// ---- +// DeclarationError 5017: (6-34): The identifier "loadimmutable" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/eof/passing_builtin_with_literal_argument_into_literal_argument.yul b/test/libyul/yulSyntaxTests/eof/passing_builtin_with_literal_argument_into_literal_argument.yul new file mode 100644 index 000000000..d46c1671b --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/passing_builtin_with_literal_argument_into_literal_argument.yul @@ -0,0 +1,8 @@ +{ + auxdataloadn(auxdataloadn(0)) +} +// ==== +// bytecodeFormat: >=EOFv1 +// dialect: evm +// ---- +// TypeError 9114: (6-18): Function expects direct literals as arguments. diff --git a/test/libyul/yulSyntaxTests/eof/selfdestruct.yul b/test/libyul/yulSyntaxTests/eof/selfdestruct.yul new file mode 100644 index 000000000..7920511eb --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/selfdestruct.yul @@ -0,0 +1,7 @@ +{ + selfdestruct(0x02) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 9132: (3-15): The "selfdestruct" instruction is only available in legacy bytecode VMs (you are currently compiling to EOF). diff --git a/test/libyul/yulSyntaxTests/eof/setimmutable_shadowing.yul b/test/libyul/yulSyntaxTests/eof/setimmutable_shadowing.yul new file mode 100644 index 000000000..83d9a33f6 --- /dev/null +++ b/test/libyul/yulSyntaxTests/eof/setimmutable_shadowing.yul @@ -0,0 +1,8 @@ +{ + function setimmutable(a, b) {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// dialect: evm +// ---- +// DeclarationError 5017: (6-36): The identifier "setimmutable" is reserved and can not be used. diff --git a/test/libyul/yulSyntaxTests/hex_switch_case.yul b/test/libyul/yulSyntaxTests/hex_switch_case.yul index e0d00539a..ec1e3edde 100644 --- a/test/libyul/yulSyntaxTests/hex_switch_case.yul +++ b/test/libyul/yulSyntaxTests/hex_switch_case.yul @@ -1,5 +1,5 @@ { - switch codesize() + switch calldataload(0) case hex"00" {} case hex"1122" {} } diff --git a/test/libyul/yulSyntaxTests/hex_switch_case_long.yul b/test/libyul/yulSyntaxTests/hex_switch_case_long.yul index abdbc6ec1..93035730b 100644 --- a/test/libyul/yulSyntaxTests/hex_switch_case_long.yul +++ b/test/libyul/yulSyntaxTests/hex_switch_case_long.yul @@ -1,7 +1,7 @@ { - switch codesize() + switch calldataload(0) case hex"00" {} case hex"112233445566778899001122334455667788990011223344556677889900112233445566778899001122334455667788990011223344556677889900" {} } // ---- -// TypeError 3069: (53-178): String literal too long (60 > 32) +// TypeError 3069: (58-183): String literal too long (60 > 32) diff --git a/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul b/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul index d5b3847b1..6a5587c97 100644 --- a/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul +++ b/test/libyul/yulSyntaxTests/invalid/pc_disallowed.yul @@ -1,5 +1,7 @@ { pop(pc()) } +// ==== +// bytecodeFormat: legacy // ---- // SyntaxError 2450: (10-12): PC instruction is a low-level EVM feature. Because of that PC is disallowed in strict assembly. diff --git a/test/libyul/yulSyntaxTests/loadimmutable.yul b/test/libyul/yulSyntaxTests/loadimmutable.yul index 6aea058b5..7c40a6503 100644 --- a/test/libyul/yulSyntaxTests/loadimmutable.yul +++ b/test/libyul/yulSyntaxTests/loadimmutable.yul @@ -3,4 +3,5 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/loadimmutable_bad_literal.yul b/test/libyul/yulSyntaxTests/loadimmutable_bad_literal.yul index 2aadd2f20..ea1d7186f 100644 --- a/test/libyul/yulSyntaxTests/loadimmutable_bad_literal.yul +++ b/test/libyul/yulSyntaxTests/loadimmutable_bad_literal.yul @@ -5,6 +5,7 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- // TypeError 5859: (24-25): Function expects string literal. // TypeError 5859: (50-54): Function expects string literal. diff --git a/test/libyul/yulSyntaxTests/loadimmutable_shadowing.yul b/test/libyul/yulSyntaxTests/loadimmutable_shadowing.yul index 8711d0b17..8156bd4fb 100644 --- a/test/libyul/yulSyntaxTests/loadimmutable_shadowing.yul +++ b/test/libyul/yulSyntaxTests/loadimmutable_shadowing.yul @@ -3,5 +3,6 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- // ParserError 5568: (15-28): Cannot use builtin function name "loadimmutable" as identifier name. diff --git a/test/libyul/yulSyntaxTests/loadimmutable_without_setimmutable.yul b/test/libyul/yulSyntaxTests/loadimmutable_without_setimmutable.yul index 8695e938d..42ca7eb2f 100644 --- a/test/libyul/yulSyntaxTests/loadimmutable_without_setimmutable.yul +++ b/test/libyul/yulSyntaxTests/loadimmutable_without_setimmutable.yul @@ -7,5 +7,7 @@ object "C" { } } } +// ==== +// bytecodeFormat: legacy // ---- // CodeGenerationError 1284: Some immutables were read from but never assigned, possibly because of optimization. diff --git a/test/libyul/yulSyntaxTests/metadata_access.yul b/test/libyul/yulSyntaxTests/metadata_access.yul index 63aeb4760..52bf786cd 100644 --- a/test/libyul/yulSyntaxTests/metadata_access.yul +++ b/test/libyul/yulSyntaxTests/metadata_access.yul @@ -21,6 +21,8 @@ object "A" { data ".metadata" "Hello, World!" data ".other" "Hello, World2!" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 3517: (41-49): Unknown data object ".other". // TypeError 3517: (69-77): Unknown data object ".other". diff --git a/test/libyul/yulSyntaxTests/metadata_access_2.yul b/test/libyul/yulSyntaxTests/metadata_access_2.yul index a4b013e85..204409d3e 100644 --- a/test/libyul/yulSyntaxTests/metadata_access_2.yul +++ b/test/libyul/yulSyntaxTests/metadata_access_2.yul @@ -9,5 +9,7 @@ object "A" { data "1" "XYZ" data ".mightbereservedinthefuture" "TRS" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 3517: (90-119): Unknown data object ".mightbereservedinthefuture". diff --git a/test/libyul/yulSyntaxTests/metadata_access_subobject.yul b/test/libyul/yulSyntaxTests/metadata_access_subobject.yul index 216b56ac6..c52ab9e1a 100644 --- a/test/libyul/yulSyntaxTests/metadata_access_subobject.yul +++ b/test/libyul/yulSyntaxTests/metadata_access_subobject.yul @@ -8,5 +8,7 @@ object "A" { data "x" "ABC" } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 3517: (41-54): Unknown data object ".metadata.x". diff --git a/test/libyul/yulSyntaxTests/objects/data.yul b/test/libyul/yulSyntaxTests/objects/data.yul index 47d7b59c7..744a88c64 100644 --- a/test/libyul/yulSyntaxTests/objects/data.yul +++ b/test/libyul/yulSyntaxTests/objects/data.yul @@ -6,4 +6,6 @@ object "A" { data "2" hex"0011" data "3" "hello world this is longer than 32 bytes and should still work" } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/objects/data_access.yul b/test/libyul/yulSyntaxTests/objects/data_access.yul index e9455fafa..681cb5028 100644 --- a/test/libyul/yulSyntaxTests/objects/data_access.yul +++ b/test/libyul/yulSyntaxTests/objects/data_access.yul @@ -6,4 +6,6 @@ object "A" { data "B" hex"00" } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/objects/datacopy.yul b/test/libyul/yulSyntaxTests/objects/datacopy.yul index 6e36025fc..1afb88e27 100644 --- a/test/libyul/yulSyntaxTests/objects/datacopy.yul +++ b/test/libyul/yulSyntaxTests/objects/datacopy.yul @@ -6,4 +6,6 @@ let s := "" datacopy(x, "11", s) } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/objects/dataoffset_nonliteral.yul b/test/libyul/yulSyntaxTests/objects/dataoffset_nonliteral.yul index d53e26281..ba80b462e 100644 --- a/test/libyul/yulSyntaxTests/objects/dataoffset_nonliteral.yul +++ b/test/libyul/yulSyntaxTests/objects/dataoffset_nonliteral.yul @@ -6,5 +6,7 @@ object "A" { data "B" hex"00" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 9114: (47-57): Function expects direct literals as arguments. diff --git a/test/libyul/yulSyntaxTests/objects/dataoffset_nonstring.yul b/test/libyul/yulSyntaxTests/objects/dataoffset_nonstring.yul index 93a981d92..1ac18c19c 100644 --- a/test/libyul/yulSyntaxTests/objects/dataoffset_nonstring.yul +++ b/test/libyul/yulSyntaxTests/objects/dataoffset_nonstring.yul @@ -3,5 +3,7 @@ object "A" { pop(dataoffset(0)) } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 5859: (41-42): Function expects string literal. diff --git a/test/libyul/yulSyntaxTests/objects/dataoffset_notfound.yul b/test/libyul/yulSyntaxTests/objects/dataoffset_notfound.yul index 14df40201..3ee03d66e 100644 --- a/test/libyul/yulSyntaxTests/objects/dataoffset_notfound.yul +++ b/test/libyul/yulSyntaxTests/objects/dataoffset_notfound.yul @@ -4,5 +4,7 @@ object "A" { } data "B" "" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 3517: (41-44): Unknown data object "C". diff --git a/test/libyul/yulSyntaxTests/objects/datasize_nonliteral.yul b/test/libyul/yulSyntaxTests/objects/datasize_nonliteral.yul index 837408b9a..a5179f3e4 100644 --- a/test/libyul/yulSyntaxTests/objects/datasize_nonliteral.yul +++ b/test/libyul/yulSyntaxTests/objects/datasize_nonliteral.yul @@ -6,5 +6,7 @@ object "A" { data "B" hex"00" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 9114: (47-55): Function expects direct literals as arguments. diff --git a/test/libyul/yulSyntaxTests/objects/datasize_nonstring.yul b/test/libyul/yulSyntaxTests/objects/datasize_nonstring.yul index 19042a2df..c8697d06b 100644 --- a/test/libyul/yulSyntaxTests/objects/datasize_nonstring.yul +++ b/test/libyul/yulSyntaxTests/objects/datasize_nonstring.yul @@ -3,5 +3,7 @@ object "A" { pop(datasize(0)) } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 5859: (39-40): Function expects string literal. diff --git a/test/libyul/yulSyntaxTests/objects/datasize_notfound.yul b/test/libyul/yulSyntaxTests/objects/datasize_notfound.yul index 48a2c268e..4fe607a0b 100644 --- a/test/libyul/yulSyntaxTests/objects/datasize_notfound.yul +++ b/test/libyul/yulSyntaxTests/objects/datasize_notfound.yul @@ -4,5 +4,7 @@ object "A" { } data "B" "" } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 3517: (39-42): Unknown data object "C". diff --git a/test/libyul/yulSyntaxTests/objects/subobject_access.yul b/test/libyul/yulSyntaxTests/objects/subobject_access.yul index 59426a0aa..11fd37d9c 100644 --- a/test/libyul/yulSyntaxTests/objects/subobject_access.yul +++ b/test/libyul/yulSyntaxTests/objects/subobject_access.yul @@ -8,4 +8,6 @@ object "A" { code {} } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/opcode_for_function_args_1.yul b/test/libyul/yulSyntaxTests/opcode_for_function_args_1.yul index 00c357bb4..dfe4ed903 100644 --- a/test/libyul/yulSyntaxTests/opcode_for_function_args_1.yul +++ b/test/libyul/yulSyntaxTests/opcode_for_function_args_1.yul @@ -1,5 +1,5 @@ { - function f(gas) {} + function f(mload) {} } // ---- -// ParserError 5568: (14-17): Cannot use builtin function name "gas" as identifier name. +// ParserError 5568: (14-19): Cannot use builtin function name "mload" as identifier name. diff --git a/test/libyul/yulSyntaxTests/opcode_for_function_args_2.yul b/test/libyul/yulSyntaxTests/opcode_for_function_args_2.yul index 989cfce9e..9fdb77277 100644 --- a/test/libyul/yulSyntaxTests/opcode_for_function_args_2.yul +++ b/test/libyul/yulSyntaxTests/opcode_for_function_args_2.yul @@ -1,5 +1,5 @@ { - function f() -> gas {} + function f() -> mload {} } // ---- -// ParserError 5568: (19-22): Cannot use builtin function name "gas" as identifier name. +// ParserError 5568: (19-24): Cannot use builtin function name "mload" as identifier name. diff --git a/test/libyul/yulSyntaxTests/opcode_for_functions.yul b/test/libyul/yulSyntaxTests/opcode_for_functions.yul index 0efc7cbcc..8dea8893d 100644 --- a/test/libyul/yulSyntaxTests/opcode_for_functions.yul +++ b/test/libyul/yulSyntaxTests/opcode_for_functions.yul @@ -1,5 +1,5 @@ { - function gas() {} + function mload() {} } // ---- -// ParserError 5568: (12-15): Cannot use builtin function name "gas" as identifier name. +// ParserError 5568: (12-17): Cannot use builtin function name "mload" as identifier name. diff --git a/test/libyul/yulSyntaxTests/passing_builtin_with_literal_argument_into_literal_argument.yul b/test/libyul/yulSyntaxTests/passing_builtin_with_literal_argument_into_literal_argument.yul index 433d36683..d1e6d50e9 100644 --- a/test/libyul/yulSyntaxTests/passing_builtin_with_literal_argument_into_literal_argument.yul +++ b/test/libyul/yulSyntaxTests/passing_builtin_with_literal_argument_into_literal_argument.yul @@ -3,5 +3,6 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- // TypeError 9114: (6-18): Function expects direct literals as arguments. diff --git a/test/libyul/yulSyntaxTests/selfdestruct.yul b/test/libyul/yulSyntaxTests/selfdestruct.yul index faecf92c3..181e9806d 100644 --- a/test/libyul/yulSyntaxTests/selfdestruct.yul +++ b/test/libyul/yulSyntaxTests/selfdestruct.yul @@ -1,5 +1,7 @@ { selfdestruct(0x02) } +// ==== +// bytecodeFormat: legacy // ---- // Warning 1699: (3-15): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. diff --git a/test/libyul/yulSyntaxTests/setimmutable.yul b/test/libyul/yulSyntaxTests/setimmutable.yul index e1d6a7491..88e38b133 100644 --- a/test/libyul/yulSyntaxTests/setimmutable.yul +++ b/test/libyul/yulSyntaxTests/setimmutable.yul @@ -3,4 +3,5 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- diff --git a/test/libyul/yulSyntaxTests/setimmutable_bad_literal.yul b/test/libyul/yulSyntaxTests/setimmutable_bad_literal.yul index 9e4bc8032..175ab15aa 100644 --- a/test/libyul/yulSyntaxTests/setimmutable_bad_literal.yul +++ b/test/libyul/yulSyntaxTests/setimmutable_bad_literal.yul @@ -5,6 +5,7 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- // TypeError 5859: (22-23): Function expects string literal. // TypeError 5859: (89-93): Function expects string literal. diff --git a/test/libyul/yulSyntaxTests/setimmutable_shadowing.yul b/test/libyul/yulSyntaxTests/setimmutable_shadowing.yul index b76a5de9b..fbcfeb15f 100644 --- a/test/libyul/yulSyntaxTests/setimmutable_shadowing.yul +++ b/test/libyul/yulSyntaxTests/setimmutable_shadowing.yul @@ -3,5 +3,6 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- // ParserError 5568: (15-27): Cannot use builtin function name "setimmutable" as identifier name. diff --git a/test/libyul/yulSyntaxTests/simple_functions.yul b/test/libyul/yulSyntaxTests/simple_functions.yul index 5b63885f2..8d97e4ac0 100644 --- a/test/libyul/yulSyntaxTests/simple_functions.yul +++ b/test/libyul/yulSyntaxTests/simple_functions.yul @@ -2,7 +2,7 @@ function a() {} function f() { mstore(0, 1) } function g() { sstore(0, 1) } - function h() { let x := msize() } + function h() { let x := balance(0x0) } function i() { let z := mload(0) } } // ==== diff --git a/test/libyul/yulSyntaxTests/string_literal_switch_case.yul b/test/libyul/yulSyntaxTests/string_literal_switch_case.yul index 6f0d72229..b69b56c66 100644 --- a/test/libyul/yulSyntaxTests/string_literal_switch_case.yul +++ b/test/libyul/yulSyntaxTests/string_literal_switch_case.yul @@ -1,5 +1,5 @@ { - switch codesize() + switch calldataload(0) case "1" {} case "2" {} } diff --git a/test/libyul/yulSyntaxTests/string_literal_too_long_immutable.yul b/test/libyul/yulSyntaxTests/string_literal_too_long_immutable.yul index 98707451e..d81f69a08 100644 --- a/test/libyul/yulSyntaxTests/string_literal_too_long_immutable.yul +++ b/test/libyul/yulSyntaxTests/string_literal_too_long_immutable.yul @@ -7,4 +7,5 @@ } // ==== // dialect: evm +// bytecodeFormat: legacy // ---- From c64cb1ffcf7061cdd7fa21a4f53632ad5a147b9d Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 28 Jan 2025 23:27:27 +0100 Subject: [PATCH 0651/1340] Fix foundry version for prb-math --- .circleci/config.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 164694e45..8e1e85794 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -834,6 +834,8 @@ defaults: binary_type: native image: cimg/rust:1.74.0-node resource_class: medium + # TODO: Use nightly Foundry builds after https://github.com/PaulRBerg/prb-math/issues/248 is fixed + foundry_version: "v0.3.0" - job_native_test_ext_elementfi: &job_native_test_ext_elementfi <<: *requires_b_ubu_static @@ -1461,6 +1463,9 @@ jobs: python2: type: boolean default: false + foundry_version: + type: string + default: "nightly" docker: - image: << parameters.image >> resource_class: << parameters.resource_class >> @@ -1474,7 +1479,8 @@ jobs: - checkout - attach_workspace: at: /tmp/workspace - - install_foundry + - install_foundry: + version: << parameters.foundry_version >> - run: name: Ensure pnpm is installed if npm is present command: | From 89b20de21d9e30b2953e2eb40311d0486eeed42f Mon Sep 17 00:00:00 2001 From: Skyge <1506186404li@gmail.com> Date: Wed, 29 Jan 2025 15:27:19 +0800 Subject: [PATCH 0652/1340] Update versions flyout menu location. --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index f1608890d..a60dc1b84 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -29,7 +29,7 @@ read our :doc:`contributors guide ` for more details. .. Hint:: You can download this documentation as PDF, HTML or Epub - by clicking on the versions flyout menu in the bottom-left corner and selecting the preferred download format. + by clicking on the versions flyout menu in the bottom-right corner and selecting the preferred download format. Getting Started From 9851010d2ed143f5382b1b2b6e57e3e33f2d5001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 24 Jan 2025 01:42:46 +0100 Subject: [PATCH 0653/1340] Remove obsolete semantic tests for the old-style .value() syntax - The ones in `functionCall` were testing multiple applications of `.value()`, which is no longer possible with the `{value: ...}` syntax. - The ones in `various` became identical when the `.value()` syntax was deprecated. --- .../functionCall/gas_and_value_basic.sol | 2 - .../gas_and_value_brace_syntax.sol | 48 ------------------- .../semanticTests/various/value_complex.sol | 28 ----------- .../semanticTests/various/value_insane.sol | 27 ----------- 4 files changed, 105 deletions(-) delete mode 100644 test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol delete mode 100644 test/libsolidity/semanticTests/various/value_complex.sol delete mode 100644 test/libsolidity/semanticTests/various/value_insane.sol diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index e6187d06e..e7bf053eb 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -13,8 +13,6 @@ contract helper { return flag; } } - - contract test { helper h; diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol deleted file mode 100644 index 41079af03..000000000 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_brace_syntax.sol +++ /dev/null @@ -1,48 +0,0 @@ -contract helper { - bool flag; - - function getBalance() payable public returns(uint256 myBalance) { - return address(this).balance; - } - - function setFlag() public { - flag = true; - } - - function getFlag() public returns(bool fl) { - return flag; - } -} -contract test { - helper h; - constructor() payable { - h = new helper(); - } - - function sendAmount(uint amount) public payable returns(uint256 bal) { - return h.getBalance{value: amount}(); - } - - function outOfGas() public returns(bool ret) { - h.setFlag { - gas: 2 - }(); // should fail due to OOG - return true; - } - - function checkState() public returns(bool flagAfter, uint myBal) { - flagAfter = h.getFlag(); - myBal = address(this).balance; - } -} -// ---- -// constructor(), 20 wei -> -// gas irOptimized: 120218 -// gas irOptimized code: 132000 -// gas legacy: 130583 -// gas legacy code: 261200 -// gas legacyOptimized: 121069 -// gas legacyOptimized code: 147000 -// sendAmount(uint256): 5 -> 5 -// outOfGas() -> FAILURE # call to helper should not succeed but amount should be transferred anyway # -// checkState() -> false, 15 diff --git a/test/libsolidity/semanticTests/various/value_complex.sol b/test/libsolidity/semanticTests/various/value_complex.sol deleted file mode 100644 index 4639d34c7..000000000 --- a/test/libsolidity/semanticTests/various/value_complex.sol +++ /dev/null @@ -1,28 +0,0 @@ -contract helper { - function getBalance() public payable returns (uint256 myBalance) { - return address(this).balance; - } -} - - -contract test { - helper h; - - constructor() payable { - h = new helper(); - } - - function sendAmount(uint256 amount) public payable returns (uint256 bal) { - uint256 someStackElement = 20; - return h.getBalance{value: amount + 3, gas: 1000}(); - } -} -// ---- -// constructor(), 20 wei -> -// gas irOptimized: 114463 -// gas irOptimized code: 58800 -// gas legacy: 120091 -// gas legacy code: 132400 -// gas legacyOptimized: 114536 -// gas legacyOptimized code: 65800 -// sendAmount(uint256): 5 -> 8 diff --git a/test/libsolidity/semanticTests/various/value_insane.sol b/test/libsolidity/semanticTests/various/value_insane.sol deleted file mode 100644 index bc6a803de..000000000 --- a/test/libsolidity/semanticTests/various/value_insane.sol +++ /dev/null @@ -1,27 +0,0 @@ -contract helper { - function getBalance() public payable returns (uint256 myBalance) { - return address(this).balance; - } -} - - -contract test { - helper h; - - constructor() payable { - h = new helper(); - } - - function sendAmount(uint256 amount) public returns (uint256 bal) { - return h.getBalance{value: amount + 3, gas: 1000}(); - } -} -// ---- -// constructor(), 20 wei -> -// gas irOptimized: 114527 -// gas irOptimized code: 59600 -// gas legacy: 120199 -// gas legacy code: 133600 -// gas legacyOptimized: 114568 -// gas legacyOptimized code: 66200 -// sendAmount(uint256): 5 -> 8 From 3b1d78d3e3d5a873b78e24184f746166b5f32389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 23 Jan 2025 19:15:32 +0100 Subject: [PATCH 0654/1340] Adjust semantic tests where possible to make them run unchanged on both EOF and legacy --- .../keccak256_packed_complex_types.sol | 4 +- .../constructor/no_callvalue_check.sol | 12 ++--- .../errors/errors_by_parameter_type.sol | 8 +-- ...quire_error_function_pointer_parameter.sol | 4 +- .../events/event_indexed_function.sol | 4 +- .../events/event_indexed_function2.sol | 8 +-- .../semanticTests/externalContracts/snark.sol | 52 +++++++++---------- .../functionCall/failed_create.sol | 32 ++++++------ .../functionTypes/address_member.sol | 10 ++-- .../function_external_delete_storage.sol | 38 +++++++------- .../immutable/multi_creation.sol | 12 ++--- .../address_overload_resolution.sol | 8 +-- .../interface_inheritance_conversions.sol | 13 ++--- .../inheritance/member_notation_ctor.sol | 6 +-- .../external_function_pointer_address.sol | 8 +-- .../transient_storage_low_level_calls.sol | 12 ++--- .../balance_other_contract.sol | 27 ++-------- .../operator_making_pure_external_call.sol | 12 ++--- .../operator_making_view_external_call.sol | 12 ++--- .../semanticTests/tryCatch/assert.sol | 5 +- .../tryCatch/assert_pre_byzantium.sol | 18 +++++++ .../semanticTests/tryCatch/create.sol | 12 ++--- .../{super_trivial.sol => require.sol} | 2 +- ...{trivial.sol => require_pre_byzantium.sol} | 2 + .../tryCatch/return_function.sol | 4 +- .../various/many_subassemblies.sol | 28 +++++----- .../viaYul/conversion/function_cast.sol | 11 ++-- .../semanticTests/viaYul/function_address.sol | 15 +++--- 28 files changed, 187 insertions(+), 192 deletions(-) create mode 100644 test/libsolidity/semanticTests/tryCatch/assert_pre_byzantium.sol rename test/libsolidity/semanticTests/tryCatch/{super_trivial.sol => require.sol} (87%) rename test/libsolidity/semanticTests/tryCatch/{trivial.sol => require_pre_byzantium.sol} (91%) diff --git a/test/libsolidity/semanticTests/builtinFunctions/keccak256_packed_complex_types.sol b/test/libsolidity/semanticTests/builtinFunctions/keccak256_packed_complex_types.sol index ea6d78189..fbecf750a 100644 --- a/test/libsolidity/semanticTests/builtinFunctions/keccak256_packed_complex_types.sol +++ b/test/libsolidity/semanticTests/builtinFunctions/keccak256_packed_complex_types.sol @@ -7,8 +7,8 @@ contract C { x[2] = y[2] = uint120(type(uint).max - 3); hash1 = keccak256(abi.encodePacked(x)); hash2 = keccak256(abi.encodePacked(y)); - hash3 = keccak256(abi.encodePacked(this.f)); + hash3 = keccak256(abi.encodePacked(C(address(0x1234)))); } } // ---- -// f() -> 0xba4f20407251e4607cd66b90bfea19ec6971699c03e4a4f3ea737d5818ac27ae, 0xba4f20407251e4607cd66b90bfea19ec6971699c03e4a4f3ea737d5818ac27ae, 0x0e9229fb1d2cd02cee4b6c9f25497777014a8766e3479666d1c619066d2887ec +// f() -> 0xba4f20407251e4607cd66b90bfea19ec6971699c03e4a4f3ea737d5818ac27ae, 0xba4f20407251e4607cd66b90bfea19ec6971699c03e4a4f3ea737d5818ac27ae, 0xe7490fade3a8e31113ecb6c0d2635e28a6f5ca8359a57afe914827f41ddf0848 diff --git a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol index 583f1ca37..f21d47341 100644 --- a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol +++ b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol @@ -9,17 +9,17 @@ contract B3 { constructor() payable {} } contract C { function f() public payable returns (bool) { // Make sure none of these revert. - new B1{value: 10}(); - new B2{value: 10}(); - new B3{value: 10}(); + new B1{value: 10, salt: hex"00"}(); + new B2{value: 10, salt: hex"01"}(); + new B3{value: 10, salt: hex"02"}(); return true; } } // ---- // f(), 2000 ether -> true -// gas irOptimized: 117623 +// gas irOptimized: 117688 // gas irOptimized code: 1800 -// gas legacy: 117821 +// gas legacy: 117889 // gas legacy code: 4800 -// gas legacyOptimized: 117690 +// gas legacyOptimized: 117761 // gas legacyOptimized code: 4800 diff --git a/test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol b/test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol index bc70b5bef..906fd0597 100644 --- a/test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol +++ b/test/libsolidity/semanticTests/errors/errors_by_parameter_type.sol @@ -27,10 +27,10 @@ contract C { require(false, E3(S(1, true, "string literal"))); } function e() external view { - require(false, E4(address(this))); + require(false, E4(address(0x1234))); } function f() external view { - require(false, E5(this.a)); + require(false, E5(C(address(0x1234)).a)); } } @@ -41,5 +41,5 @@ contract C { // b() -> FAILURE, hex"47e26897", hex"0000000000000000000000000000000000000000000000000000000000000001" // c() -> FAILURE, hex"8f372c34", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"000000000000000000000000000000000000000000000000000000000000000e", hex"737472696e67206c69746572616c000000000000000000000000000000000000" // d() -> FAILURE, hex"5717173e", hex"0000000000000000000000000000000000000000000000000000000000000020", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000001", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"000000000000000000000000000000000000000000000000000000000000000e", hex"737472696e67206c69746572616c000000000000000000000000000000000000" -// e() -> FAILURE, hex"7efef9ea", hex"000000000000000000000000c06afe3a8444fc0004668591e8306bfb9968e79e" -// f() -> FAILURE, hex"0c3f12eb", hex"c06afe3a8444fc0004668591e8306bfb9968e79e0dbe671f0000000000000000" +// e() -> FAILURE, hex"7efef9ea", hex"0000000000000000000000000000000000000000000000000000000000001234" +// f() -> FAILURE, hex"0c3f12eb", hex"00000000000000000000000000000000000012340dbe671f0000000000000000" diff --git a/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol b/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol index 3af19ca64..7a82d4f81 100644 --- a/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol +++ b/test/libsolidity/semanticTests/errors/require_error_function_pointer_parameter.sol @@ -10,9 +10,9 @@ contract C function f() external view { // more than one stack slot - require(false, CustomError(this.e)); + require(false, CustomError(C(address(0x1234)).e)); } } // ---- -// f() -> FAILURE, hex"271b1dfa", hex"c06afe3a8444fc0004668591e8306bfb9968e79ef37cdc8e0000000000000000" +// f() -> FAILURE, hex"271b1dfa", hex"0000000000000000000000000000000000001234f37cdc8e0000000000000000" diff --git a/test/libsolidity/semanticTests/events/event_indexed_function.sol b/test/libsolidity/semanticTests/events/event_indexed_function.sol index ea7574159..29b19dbe7 100644 --- a/test/libsolidity/semanticTests/events/event_indexed_function.sol +++ b/test/libsolidity/semanticTests/events/event_indexed_function.sol @@ -1,9 +1,9 @@ contract C { event Test(function() external indexed); function f() public { - emit Test(this.f); + emit Test(C(address(0x1234)).f); } } // ---- // f() -> -// ~ emit Test(function): #0xc06afe3a8444fc0004668591e8306bfb9968e79e26121ff00000000000000000 +// ~ emit Test(function): #0x123426121ff00000000000000000 diff --git a/test/libsolidity/semanticTests/events/event_indexed_function2.sol b/test/libsolidity/semanticTests/events/event_indexed_function2.sol index d4c47e868..9587f8c37 100644 --- a/test/libsolidity/semanticTests/events/event_indexed_function2.sol +++ b/test/libsolidity/semanticTests/events/event_indexed_function2.sol @@ -2,14 +2,14 @@ contract C { event TestA(function() external indexed); event TestB(function(uint256) external indexed); function f1() public { - emit TestA(this.f1); + emit TestA(C(address(0x1234)).f1); } function f2(uint256 a) public { - emit TestB(this.f2); + emit TestB(C(address(0x1234)).f2); } } // ---- // f1() -> -// ~ emit TestA(function): #0xc06afe3a8444fc0004668591e8306bfb9968e79ec27fc3050000000000000000 +// ~ emit TestA(function): #0x1234c27fc3050000000000000000 // f2(uint256): 1 -> -// ~ emit TestB(function): #0xc06afe3a8444fc0004668591e8306bfb9968e79ebf3724af0000000000000000 +// ~ emit TestB(function): #0x1234bf3724af0000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index 906279d17..2b1fe023e 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -1,3 +1,5 @@ +pragma abicoder v2; + library Pairing { struct G1Point { uint X; @@ -35,34 +37,26 @@ library Pairing { /// @return r the sum of two points of G1 function add(G1Point memory p1, G1Point memory p2) internal returns (G1Point memory r) { - uint[4] memory input; + uint[6] memory input; input[0] = p1.X; input[1] = p1.Y; input[2] = p2.X; input[3] = p2.Y; - bool success; - assembly { - success := call(sub(gas(), 2000), 6, 0, input, 0xc0, r, 0x60) - // Use "invalid" to make gas estimation work - switch success case 0 { invalid() } - } + (bool success, bytes memory encodedResult) = address(6).call(abi.encode(input)); require(success); + r = abi.decode(encodedResult, (G1Point)); } /// @return r the product of a point on G1 and a scalar, i.e. /// p == p.mul(1) and p.add(p) == p.mul(2) for all points p. function mul(G1Point memory p, uint s) internal returns (G1Point memory r) { - uint[3] memory input; + uint[4] memory input; input[0] = p.X; input[1] = p.Y; input[2] = s; - bool success; - assembly { - success := call(sub(gas(), 2000), 7, 0, input, 0x80, r, 0x60) - // Use "invalid" to make gas estimation work - switch success case 0 { invalid() } - } + (bool success, bytes memory encodedResult) = address(7).call(abi.encode(input)); require(success); + r = abi.decode(encodedResult, (G1Point)); } /// @return the result of computing the pairing check @@ -83,15 +77,19 @@ library Pairing { input[i * 6 + 4] = p2[i].Y[0]; input[i * 6 + 5] = p2[i].Y[1]; } - uint[1] memory out; - bool success; - assembly { - success := call(sub(gas(), 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) - // Use "invalid" to make gas estimation work - switch success case 0 { invalid() } + + bytes memory encodedInput = new bytes(inputSize * 32); + for (uint i = 0; i < inputSize; i++) + { + uint offset = (i + 1) * 32; + uint item = input[i]; + assembly ("memory-safe") { + mstore(add(encodedInput, offset), item) + } } + (bool success, bytes memory encodedResult) = address(8).call(encodedInput); require(success); - return out[0] != 0; + return abi.decode(encodedResult, (bool)); } function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal returns (bool) { G1Point[] memory p1 = new G1Point[](2); @@ -294,11 +292,11 @@ contract Test { // f() -> true // g() -> true // pair() -> true -// gas irOptimized: 270409 -// gas legacy: 275219 -// gas legacyOptimized: 266862 +// gas irOptimized: 275319 +// gas legacy: 293854 +// gas legacyOptimized: 276409 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." -// gas irOptimized: 785720 -// gas legacy: 801903 -// gas legacyOptimized: 770941 +// gas irOptimized: 821446 +// gas legacy: 914211 +// gas legacyOptimized: 820319 diff --git a/test/libsolidity/semanticTests/functionCall/failed_create.sol b/test/libsolidity/semanticTests/functionCall/failed_create.sol index 657b4b5cf..bb6289768 100644 --- a/test/libsolidity/semanticTests/functionCall/failed_create.sol +++ b/test/libsolidity/semanticTests/functionCall/failed_create.sol @@ -2,35 +2,35 @@ contract D { constructor() payable {} } contract C { uint public x; constructor() payable {} - function f(uint amount) public returns (D) { + function f(uint amount) public { x++; - return (new D){value: amount}(); + (new D){value: amount, salt: bytes32(x)}(); } - function stack(uint depth) public payable returns (address) { + function stack(uint depth) public payable { if (depth > 0) - return this.stack(depth - 1); + this.stack(depth - 1); else - return address(f(0)); + f(0); } } // ==== // EVMVersion: >=byzantium // ---- // constructor(), 20 wei -// gas irOptimized: 61548 -// gas irOptimized code: 104600 -// gas legacy: 70147 -// gas legacy code: 215400 -// gas legacyOptimized: 61715 -// gas legacyOptimized code: 106800 -// f(uint256): 20 -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a +// gas irOptimized: 59688 +// gas irOptimized code: 81800 +// gas legacy: 64468 +// gas legacy code: 145400 +// gas legacyOptimized: 60443 +// gas legacyOptimized code: 91200 +// f(uint256): 20 -> // x() -> 1 // f(uint256): 20 -> FAILURE // x() -> 1 // stack(uint256): 1023 -> FAILURE -// gas irOptimized: 252410 -// gas legacy: 476845 -// gas legacyOptimized: 299061 +// gas irOptimized: 298110 +// gas legacy: 527207 +// gas legacyOptimized: 353607 // x() -> 1 -// stack(uint256): 10 -> 0x87948bd7ebbe13a00bfd930c93e4828ab18e3908 +// stack(uint256): 10 -> // x() -> 2 diff --git a/test/libsolidity/semanticTests/functionTypes/address_member.sol b/test/libsolidity/semanticTests/functionTypes/address_member.sol index a5f56f3dc..214752a1f 100644 --- a/test/libsolidity/semanticTests/functionTypes/address_member.sol +++ b/test/libsolidity/semanticTests/functionTypes/address_member.sol @@ -1,10 +1,10 @@ contract C { function f() public view returns (address a1, address a2) { - a1 = this.f.address; - this.f.address; - [this.f.address][0]; - a2 = [this.f.address][0]; + a1 = C(address(0x1234)).f.address; + C(address(0x1234)).f.address; + [C(address(0x1234)).f.address][0]; + a2 = [C(address(0x1234)).f.address][0]; } } // ---- -// f() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e, 0xc06afe3a8444fc0004668591e8306bfb9968e79e +// f() -> 0x1234, 0x1234 diff --git a/test/libsolidity/semanticTests/functionTypes/function_external_delete_storage.sol b/test/libsolidity/semanticTests/functionTypes/function_external_delete_storage.sol index d5e105e5f..1d8d1897c 100644 --- a/test/libsolidity/semanticTests/functionTypes/function_external_delete_storage.sol +++ b/test/libsolidity/semanticTests/functionTypes/function_external_delete_storage.sol @@ -1,17 +1,19 @@ contract C { function() external public x; - uint public y = 0; - function increment() public { - ++y; - } + function f() public {} function set() external { - x = this.increment; + x = this.f; + } + + function isF() external returns (bool) { + return x == this.f; } - function incrementIndirectly() public { - x(); + function isZero() external returns (bool) { + function() external zero; + return x == zero; } function deleteFunction() public { @@ -20,18 +22,14 @@ contract C { } } // ---- -// x() -> 0 -// y() -> 0 -// increment() -> -// y() -> 1 +// isF() -> false +// isZero() -> true +// deleteFunction() -> +// isF() -> false +// isZero() -> true // set() -> -// x() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79ed09de08a0000000000000000 -// increment() -> -// y() -> 2 -// incrementIndirectly() -> -// y() -> 3 +// isF() -> true +// isZero() -> false // deleteFunction() -> -// increment() -> -// y() -> 4 -// incrementIndirectly() -> FAILURE -// y() -> 4 +// isF() -> false +// isZero() -> true diff --git a/test/libsolidity/semanticTests/immutable/multi_creation.sol b/test/libsolidity/semanticTests/immutable/multi_creation.sol index aa8a1ad8a..1036b7f83 100644 --- a/test/libsolidity/semanticTests/immutable/multi_creation.sol +++ b/test/libsolidity/semanticTests/immutable/multi_creation.sol @@ -18,20 +18,20 @@ contract C { uint public y; constructor() { a = 3; - x = (new A()).f(); - y = (new B()).f(); + x = (new A{salt: hex"00"}()).f(); + y = (new B{salt: hex"00"}()).f(); } function f() public returns (uint256, uint, uint) { - return (a, (new A()).f(), (new B()).f()); + return (a, (new A{salt: hex"01"}()).f(), (new B{salt: hex"01"}()).f()); } } // ---- // f() -> 3, 7, 5 -// gas irOptimized: 86796 +// gas irOptimized: 86892 // gas irOptimized code: 37200 -// gas legacy: 87727 +// gas legacy: 87839 // gas legacy code: 60800 -// gas legacyOptimized: 86770 +// gas legacyOptimized: 86870 // gas legacyOptimized code: 37200 // x() -> 7 // y() -> 5 diff --git a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol index 0865ed287..c4d416d9a 100644 --- a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol +++ b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol @@ -11,19 +11,19 @@ contract C { contract D { function f() public returns (uint256) { - return (new C()).balance(); + return (new C{salt: hex"00"}()).balance(); } function g() public returns (uint256) { - return (new C()).transfer(5); + return (new C{salt: hex"01"}()).transfer(5); } } // ---- // f() -> 1 // gas irOptimized: 77051 -// gas legacy: 54480 +// gas legacy: 54553 // gas legacy code: 57800 // g() -> 5 // gas irOptimized: 77106 -// gas legacy: 55016 +// gas legacy: 55090 // gas legacy code: 57800 diff --git a/test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol b/test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol index 62e1e4fba..2448b3e03 100644 --- a/test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol +++ b/test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol @@ -10,26 +10,21 @@ interface SubB is Parent { function subBFun() external returns (uint256); } -contract Impl is SubA, SubB { +contract C is SubA, SubB { function parentFun() override external returns (uint256) { return 1; } function subAFun() override external returns (uint256) { return 2; } function subBFun() override external returns (uint256) { return 3; } -} -contract C { function convertParent() public returns (uint256) { - Parent p = new Impl(); - return p.parentFun(); + return this.parentFun(); } function convertSubA() public returns (uint256, uint256) { - SubA sa = new Impl(); - return (sa.parentFun(), sa.subAFun()); + return (this.parentFun(), this.subAFun()); } function convertSubB() public returns (uint256, uint256) { - SubB sb = new Impl(); - return (sb.parentFun(), sb.subBFun()); + return (this.parentFun(), this.subBFun()); } } // ---- diff --git a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol index b9697c5ae..517d3c148 100644 --- a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol +++ b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol @@ -13,14 +13,14 @@ contract D is M.C { contract A { function g(int p) public returns (int) { - D d = new D(p); + D d = new D{salt: bytes32(uint256(p))}(p); return d.getX(); } } // ---- // g(int256): -1 -> -1 -// gas legacy: 77876 +// gas legacy: 77955 // gas legacy code: 24200 // g(int256): 10 -> 10 -// gas legacy: 77504 +// gas legacy: 77583 // gas legacy code: 24200 diff --git a/test/libsolidity/semanticTests/inlineAssembly/external_function_pointer_address.sol b/test/libsolidity/semanticTests/inlineAssembly/external_function_pointer_address.sol index ae891df5d..dd60679ae 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/external_function_pointer_address.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/external_function_pointer_address.sol @@ -2,16 +2,16 @@ contract C { function testFunction() external {} function testYul() public returns (address adr) { - function() external fp = this.testFunction; + function() external fp = C(address(0x1234)).testFunction; assembly { adr := fp.address } } function testSol() public returns (address) { - return this.testFunction.address; + return C(address(0x1234)).testFunction.address; } } // ---- -// testYul() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e -// testSol() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e +// testYul() -> 0x1234 +// testSol() -> 0x1234 diff --git a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol index e43fc4757..d3714e7df 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_low_level_calls.sol @@ -27,7 +27,7 @@ contract C { function testDelegateCall() external returns (bool) { this.set(5); - D d = new D(); + D d = new D{salt: hex"00"}(); // Caller contract is the owner of the transient storage (bool success, ) = address(d).delegatecall(abi.encodeCall(d.addOne, ())); require(success); @@ -37,7 +37,7 @@ contract C { function testCall() external returns (bool) { this.set(5); - D d = new D(); + D d = new D{salt: hex"01"}(); // Callee/Target contract is the owner of the transient storage (bool success, ) = address(d).call(abi.encodeCall(d.addOne, ())); require(success); @@ -47,7 +47,7 @@ contract C { function tloadAllowedStaticCall() external returns (bool) { this.set(5); - D d = new D(); + D d = new D{salt: hex"02"}(); (bool success, bytes memory result) = address(d).staticcall(abi.encodeCall(d.get, ())); require(success); require(abi.decode(result, (uint)) == 0); @@ -55,7 +55,7 @@ contract C { } function tstoreNotAllowedStaticCall() external returns (bool) { - D d = new D(); + D d = new D{salt: hex"03"}(); (bool success, ) = address(d).staticcall(abi.encodeCall(d.addOne, ())); require(!success); return true; @@ -68,9 +68,9 @@ contract C { // testCall() -> true // tloadAllowedStaticCall() -> true // tstoreNotAllowedStaticCall() -> true -// gas irOptimized: 98419720 +// gas irOptimized: 98419721 // gas irOptimized code: 19000 -// gas legacy: 98409086 +// gas legacy: 98409087 // gas legacy code: 30000 // gas legacyOptimized: 98420962 // gas legacyOptimized code: 17800 diff --git a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol index 1240a8251..92d358294 100644 --- a/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol +++ b/test/libsolidity/semanticTests/isoltestTesting/balance_other_contract.sol @@ -1,30 +1,9 @@ -contract Other { +contract C { constructor() payable { - } - function getAddress() public returns (address) { - return address(this); - } -} -contract ClientReceipt { - Other other; - constructor() payable { - other = new Other{value:500}(); - } - function getAddress() public returns (address) { - return other.getAddress(); + payable(address(0x1234)).transfer(500); } } // ---- // constructor(), 2000 wei -> -// gas irOptimized: 114353 -// gas irOptimized code: 58800 -// gas legacy: 118617 -// gas legacy code: 111400 -// gas legacyOptimized: 114067 -// gas legacyOptimized code: 59800 // balance -> 1500 -// gas irOptimized: 191881 -// gas legacy: 235167 -// gas legacyOptimized: 180756 -// getAddress() -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a -// balance: 0x137aa4dfc0911524504fcd4d98501f179bc13b4a -> 500 +// balance: 0x0000000000000000000000000000000000001234 -> 500 diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol index ec41099ee..56b1159c2 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol @@ -39,13 +39,13 @@ function loadAdder() pure returns (IAdder adder) { contract C { function testMul(Int32 x, Int32 y) public returns (Int32) { - storeAdder(new Adder()); + storeAdder(new Adder{salt: hex"00"}()); return x + y; } function testInc(Int32 x) public returns (Int32) { - storeAdder(new Adder()); + storeAdder(new Adder{salt: hex"01"}()); return -x; } @@ -53,13 +53,13 @@ contract C { // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 -// gas legacy: 56978 +// gas legacy: 57117 // gas legacy code: 127000 -// gas legacyOptimized: 55161 +// gas legacyOptimized: 55246 // gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 // gas irOptimized: 102386 -// gas legacy: 56238 +// gas legacy: 56378 // gas legacy code: 127000 -// gas legacyOptimized: 54851 +// gas legacyOptimized: 54943 // gas legacyOptimized code: 68400 diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol index 7e70eb091..106605c06 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol @@ -45,13 +45,13 @@ function loadAdder() pure returns (IAdderPure adder) { contract C { function testMul(Int32 x, Int32 y) public returns (Int32) { - storeAdder(new Adder()); + storeAdder(new Adder{salt: hex"00"}()); return x + y; } function testInc(Int32 x) public returns (Int32) { - storeAdder(new Adder()); + storeAdder(new Adder{salt: hex"01"}()); return -x; } @@ -59,13 +59,13 @@ contract C { // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 -// gas legacy: 56978 +// gas legacy: 57117 // gas legacy code: 127000 -// gas legacyOptimized: 55161 +// gas legacyOptimized: 55246 // gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 // gas irOptimized: 102386 -// gas legacy: 56238 +// gas legacy: 56378 // gas legacy code: 127000 -// gas legacyOptimized: 54851 +// gas legacyOptimized: 54943 // gas legacyOptimized code: 68400 diff --git a/test/libsolidity/semanticTests/tryCatch/assert.sol b/test/libsolidity/semanticTests/tryCatch/assert.sol index 8b6a7b996..335ef26bf 100644 --- a/test/libsolidity/semanticTests/tryCatch/assert.sol +++ b/test/libsolidity/semanticTests/tryCatch/assert.sol @@ -3,14 +3,15 @@ contract C { assert(x); } function f(bool x) public returns (uint) { - // Set the gas to make this work on pre-byzantium VMs - try this.g{gas: 8000}(x) { + try this.g(x) { return 1; } catch { return 2; } } } +// ==== +// EVMVersion: >=byzantium // ---- // f(bool): true -> 1 // f(bool): false -> 2 diff --git a/test/libsolidity/semanticTests/tryCatch/assert_pre_byzantium.sol b/test/libsolidity/semanticTests/tryCatch/assert_pre_byzantium.sol new file mode 100644 index 000000000..a683f531f --- /dev/null +++ b/test/libsolidity/semanticTests/tryCatch/assert_pre_byzantium.sol @@ -0,0 +1,18 @@ +contract C { + function g(bool x) public pure { + assert(x); + } + function f(bool x) public returns (uint) { + // Set the gas to make this work on pre-byzantium VMs + try this.g{gas: 8000}(x) { + return 1; + } catch { + return 2; + } + } +} +// ==== +// EVMVersion: 1 +// f(bool): false -> 2 diff --git a/test/libsolidity/semanticTests/tryCatch/create.sol b/test/libsolidity/semanticTests/tryCatch/create.sol index 43d0f22f6..4ad40d531 100644 --- a/test/libsolidity/semanticTests/tryCatch/create.sol +++ b/test/libsolidity/semanticTests/tryCatch/create.sol @@ -6,19 +6,19 @@ contract Succeeds { } contract C { - function f() public returns (Reverts x, uint, string memory txt) { + function f() public returns (bool created, string memory txt) { uint i = 3; try new Reverts(i) returns (Reverts r) { - x = r; + created = (address(r) != address(0)); txt = "success"; } catch Error(string memory s) { txt = s; } } - function g() public returns (Succeeds x, uint, string memory txt) { + function g() public returns (bool created, string memory txt) { uint i = 8; try new Succeeds(i) returns (Succeeds r) { - x = r; + created = (address(r) != address(0)); txt = "success"; } catch Error(string memory s) { txt = s; @@ -28,5 +28,5 @@ contract C { // ==== // EVMVersion: >=byzantium // ---- -// f() -> 0, 0, 96, 13, "test message." -// g() -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a, 0, 96, 7, "success" +// f() -> false, 0x40, 13, "test message." +// g() -> true, 0x40, 7, "success" diff --git a/test/libsolidity/semanticTests/tryCatch/super_trivial.sol b/test/libsolidity/semanticTests/tryCatch/require.sol similarity index 87% rename from test/libsolidity/semanticTests/tryCatch/super_trivial.sol rename to test/libsolidity/semanticTests/tryCatch/require.sol index 98fbcddb2..730243208 100644 --- a/test/libsolidity/semanticTests/tryCatch/super_trivial.sol +++ b/test/libsolidity/semanticTests/tryCatch/require.sol @@ -1,5 +1,5 @@ contract C { - function g(bool x) external pure { + function g(bool x) public pure { require(x); } function f(bool x) public returns (uint) { diff --git a/test/libsolidity/semanticTests/tryCatch/trivial.sol b/test/libsolidity/semanticTests/tryCatch/require_pre_byzantium.sol similarity index 91% rename from test/libsolidity/semanticTests/tryCatch/trivial.sol rename to test/libsolidity/semanticTests/tryCatch/require_pre_byzantium.sol index d43477e99..eb9251ec7 100644 --- a/test/libsolidity/semanticTests/tryCatch/trivial.sol +++ b/test/libsolidity/semanticTests/tryCatch/require_pre_byzantium.sol @@ -11,6 +11,8 @@ contract C { } } } +// ==== +// EVMVersion: 1 // f(bool): false -> 2 diff --git a/test/libsolidity/semanticTests/tryCatch/return_function.sol b/test/libsolidity/semanticTests/tryCatch/return_function.sol index 6aac30fe4..396633655 100644 --- a/test/libsolidity/semanticTests/tryCatch/return_function.sol +++ b/test/libsolidity/semanticTests/tryCatch/return_function.sol @@ -1,7 +1,7 @@ contract C { function g() public returns (uint a, function() external h, uint b) { a = 1; - h = this.fun; + h = C(address(0x1234)).fun; b = 9; } function f() public returns (uint, function() external, uint) { @@ -14,4 +14,4 @@ contract C { function fun() public pure {} } // ---- -// f() -> 0x1, 0xc06afe3a8444fc0004668591e8306bfb9968e79e946644cd0000000000000000, 9 +// f() -> 0x1, 0x1234946644cd0000000000000000, 9 diff --git a/test/libsolidity/semanticTests/various/many_subassemblies.sol b/test/libsolidity/semanticTests/various/many_subassemblies.sol index b270c7006..b448d0101 100644 --- a/test/libsolidity/semanticTests/various/many_subassemblies.sol +++ b/test/libsolidity/semanticTests/various/many_subassemblies.sol @@ -15,24 +15,24 @@ contract D { // This is primarily meant to test assembly import via --import-asm-json. // The exported JSON will fail the reimport unless the subassembly indices are parsed // correctly - as hex numbers. - new C0(); - new C1(); - new C2(); - new C3(); - new C4(); - new C5(); - new C6(); - new C7(); - new C8(); - new C9(); - new C10(); + new C0{salt: hex"00"}(); + new C1{salt: hex"01"}(); + new C2{salt: hex"02"}(); + new C3{salt: hex"03"}(); + new C4{salt: hex"04"}(); + new C5{salt: hex"05"}(); + new C6{salt: hex"06"}(); + new C7{salt: hex"07"}(); + new C8{salt: hex"08"}(); + new C9{salt: hex"09"}(); + new C10{salt: hex"0a"}(); } } // ---- // run() -> -// gas irOptimized: 374934 +// gas irOptimized: 375192 // gas irOptimized code: 6600 -// gas legacy: 375119 +// gas legacy: 375404 // gas legacy code: 17600 -// gas legacyOptimized: 375119 +// gas legacyOptimized: 375464 // gas legacyOptimized code: 17600 diff --git a/test/libsolidity/semanticTests/viaYul/conversion/function_cast.sol b/test/libsolidity/semanticTests/viaYul/conversion/function_cast.sol index 843376baa..7aaaa648f 100644 --- a/test/libsolidity/semanticTests/viaYul/conversion/function_cast.sol +++ b/test/libsolidity/semanticTests/viaYul/conversion/function_cast.sol @@ -9,13 +9,14 @@ contract C { return this.g()(x) + 1; } function t() external view returns ( - function(uint) external returns (uint) a, - function(uint) external view returns (uint) b) { - a = this.f; - b = this.f; + function(uint) external returns (uint) a, + function(uint) external view returns (uint) b + ) { + a = C(address(0x1234)).f; + b = C(address(0x1234)).f; } } // ---- // f(uint256): 2 -> 4 // h(uint256): 2 -> 5 -// t() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79eb3de648b0000000000000000, 0xc06afe3a8444fc0004668591e8306bfb9968e79eb3de648b0000000000000000 +// t() -> 0x1234b3de648b0000000000000000, 0x1234b3de648b0000000000000000 diff --git a/test/libsolidity/semanticTests/viaYul/function_address.sol b/test/libsolidity/semanticTests/viaYul/function_address.sol index 0c1c58dd8..a781db753 100644 --- a/test/libsolidity/semanticTests/viaYul/function_address.sol +++ b/test/libsolidity/semanticTests/viaYul/function_address.sol @@ -1,15 +1,18 @@ contract C { function f() external returns (address) { - return this.f.address; + return C(address(0x1234)).f.address; } - function g() external returns (bool) { - return this.f.address == address(this); + function g() external returns (bool, bool) { + return ( + this.f.address == address(this), + C(address(0x1234)).f.address == address(0x1234) + ); } function h(function() external a) public returns (address) { - return a.address; + return a.address; } } // ---- -// f() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e -// g() -> true +// f() -> 0x1234 +// g() -> true, true // h(function): left(0x1122334400112233445566778899AABBCCDDEEFF42424242) -> 0x1122334400112233445566778899AABBCCDDEEFF From f580dfbc38b7a8bcd0a50ebb106cb343e28746e0 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 29 Jan 2025 22:44:32 +0100 Subject: [PATCH 0655/1340] eof: Add test which checks that setting an EOF version results in the experimental flag being set. --- test/libsolidity/Metadata.cpp | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index ed490b9a8..e6cdef036 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -225,6 +225,48 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) } } +BOOST_AUTO_TEST_CASE(metadata_eof_experimental) +{ + // Check that setting an EOF version results in the experimental flag being set. + char const* sourceCode = R"( + pragma solidity >=0.0; + contract test { + function g(function(uint) external returns (uint) x) public {} + } + )"; + for (auto metadataFormat: std::set{ + CompilerStack::MetadataFormat::NoMetadata, + CompilerStack::MetadataFormat::WithReleaseVersionTag, + CompilerStack::MetadataFormat::WithPrereleaseVersionTag + }) + { + CompilerStack compilerStack; + compilerStack.setMetadataFormat(metadataFormat); + compilerStack.setSources({{"", sourceCode}}); + compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); + compilerStack.setViaIR(true); + compilerStack.setEOFVersion(solidity::test::CommonOptions::get().eofVersion()); + compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize); + BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); + bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; + std::string const& metadata = compilerStack.metadata("test"); + BOOST_CHECK(solidity::test::isValidMetadata(metadata)); + + auto const cborMetadata = requireParsedCBORMetadata(bytecode, metadataFormat); + + if ( + metadataFormat == CompilerStack::MetadataFormat::NoMetadata || + !solidity::test::CommonOptions::get().eofVersion().has_value() + ) + BOOST_CHECK(cborMetadata.count("experimental") == 0); + else + { + BOOST_CHECK(cborMetadata.count("experimental") == 1); + BOOST_CHECK(cborMetadata.at("experimental") == "true"); + } + } +} + BOOST_AUTO_TEST_CASE(metadata_relevant_sources) { CompilerStack compilerStack; From 509cd4770270ec0a1e056b440a33d131fb88fa9a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 30 Jan 2025 09:34:41 +0100 Subject: [PATCH 0656/1340] Use clang in alpine docker container --- scripts/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/Dockerfile b/scripts/Dockerfile index 3a1c6a5a7..6df9337ec 100644 --- a/scripts/Dockerfile +++ b/scripts/Dockerfile @@ -6,7 +6,7 @@ MAINTAINER chriseth WORKDIR /solidity # Build dependencies -RUN apk update && apk add boost-dev boost-static build-base cmake git +RUN apk update && apk add boost-dev boost-static build-base cmake git clang #Copy working directory on travis to the image COPY / $WORKDIR @@ -17,7 +17,7 @@ ARG BUILD_CONCURRENCY="0" #Install dependencies, eliminate annoying warnings RUN sed -i -E -e 's/include /include /' /usr/include/boost/asio/detail/socket_types.hpp -RUN cmake -DCMAKE_BUILD_TYPE=Release -DTESTS=0 -DSOLC_LINK_STATIC=1 +RUN cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -DTESTS=0 -DSOLC_LINK_STATIC=1 RUN make solc \ -j$(awk "BEGIN { \ if (${BUILD_CONCURRENCY} != 0) { \ From a669f791834252fe2231f8f6b43ec389b9bae5e1 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 30 Jan 2025 09:40:14 +0100 Subject: [PATCH 0657/1340] Use two jobs for b_ubu_asan compilation --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8e1e85794..0c4e65954 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1040,6 +1040,8 @@ jobs: # See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105562#c27 CMAKE_OPTIONS: -DSANITIZE=address -DPEDANTIC=OFF CMAKE_BUILD_TYPE: Release + # Set the number of jobs to two instead of the default three, so that we do not run out of memory + MAKEFLAGS: -j 2 steps: - build From 46cbf39b8cd76ef613040f0542a3dec93e922047 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 30 Jan 2025 12:13:24 +0100 Subject: [PATCH 0658/1340] Restrict tests using salted instantiation to >=constantinople --- .../semanticTests/constructor/no_callvalue_check.sol | 2 ++ test/libsolidity/semanticTests/functionCall/failed_create.sol | 2 +- test/libsolidity/semanticTests/immutable/multi_creation.sol | 2 ++ .../semanticTests/inheritance/address_overload_resolution.sol | 2 ++ .../semanticTests/inheritance/member_notation_ctor.sol | 2 ++ .../userDefined/operator_making_pure_external_call.sol | 2 ++ .../userDefined/operator_making_view_external_call.sol | 2 ++ test/libsolidity/semanticTests/various/many_subassemblies.sol | 2 ++ 8 files changed, 15 insertions(+), 1 deletion(-) diff --git a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol index f21d47341..a46b6a6a8 100644 --- a/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol +++ b/test/libsolidity/semanticTests/constructor/no_callvalue_check.sol @@ -15,6 +15,8 @@ contract C { return true; } } +// ==== +// EVMVersion: >=constantinople // ---- // f(), 2000 ether -> true // gas irOptimized: 117688 diff --git a/test/libsolidity/semanticTests/functionCall/failed_create.sol b/test/libsolidity/semanticTests/functionCall/failed_create.sol index bb6289768..87bd12d58 100644 --- a/test/libsolidity/semanticTests/functionCall/failed_create.sol +++ b/test/libsolidity/semanticTests/functionCall/failed_create.sol @@ -14,7 +14,7 @@ contract C { } } // ==== -// EVMVersion: >=byzantium +// EVMVersion: >=constantinople // ---- // constructor(), 20 wei // gas irOptimized: 59688 diff --git a/test/libsolidity/semanticTests/immutable/multi_creation.sol b/test/libsolidity/semanticTests/immutable/multi_creation.sol index 1036b7f83..515dd41bb 100644 --- a/test/libsolidity/semanticTests/immutable/multi_creation.sol +++ b/test/libsolidity/semanticTests/immutable/multi_creation.sol @@ -25,6 +25,8 @@ contract C { return (a, (new A{salt: hex"01"}()).f(), (new B{salt: hex"01"}()).f()); } } +// ==== +// EVMVersion: >=constantinople // ---- // f() -> 3, 7, 5 // gas irOptimized: 86892 diff --git a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol index c4d416d9a..90a3f9ec8 100644 --- a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol +++ b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol @@ -18,6 +18,8 @@ contract D { return (new C{salt: hex"01"}()).transfer(5); } } +// ==== +// EVMVersion: >=constantinople // ---- // f() -> 1 // gas irOptimized: 77051 diff --git a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol index 517d3c148..cbedca48c 100644 --- a/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol +++ b/test/libsolidity/semanticTests/inheritance/member_notation_ctor.sol @@ -17,6 +17,8 @@ contract A { return d.getX(); } } +// ==== +// EVMVersion: >=constantinople // ---- // g(int256): -1 -> -1 // gas legacy: 77955 diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol index 56b1159c2..364e589e5 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol @@ -50,6 +50,8 @@ contract C { return -x; } } +// ==== +// EVMVersion: >=constantinople // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol index 106605c06..54048113c 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol @@ -56,6 +56,8 @@ contract C { return -x; } } +// ==== +// EVMVersion: >=constantinople // ---- // testMul(int32,int32): 42, 10 -> 420 // gas irOptimized: 102563 diff --git a/test/libsolidity/semanticTests/various/many_subassemblies.sol b/test/libsolidity/semanticTests/various/many_subassemblies.sol index b448d0101..a320a2aa3 100644 --- a/test/libsolidity/semanticTests/various/many_subassemblies.sol +++ b/test/libsolidity/semanticTests/various/many_subassemblies.sol @@ -28,6 +28,8 @@ contract D { new C10{salt: hex"0a"}(); } } +// ==== +// EVMVersion: >=constantinople // ---- // run() -> // gas irOptimized: 375192 From eb7d79496539fa26ab6586972c538c289ef4c78c Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 12 Dec 2024 12:19:33 +0100 Subject: [PATCH 0659/1340] eof: Enable yul in `SyntaxTest` by default when compiling to EOF --- test/libsolidity/SyntaxTest.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 41c1d0568..4fd3df7cf 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -48,7 +48,9 @@ SyntaxTest::SyntaxTest( { static std::set const compileViaYulAllowedValues{"true", "false"}; - m_compileViaYul = m_reader.stringSetting("compileViaYul", "false"); + auto const eofEnabled = solidity::test::CommonOptions::get().eofVersion().has_value(); + + m_compileViaYul = m_reader.stringSetting("compileViaYul", eofEnabled ? "true" : "false"); if (!util::contains(compileViaYulAllowedValues, m_compileViaYul)) BOOST_THROW_EXCEPTION(std::runtime_error("Invalid compileViaYul value: " + m_compileViaYul + ".")); m_optimiseYul = m_reader.boolSetting("optimize-yul", true); From 3e8008ec50f7046a7d9221c8cd59c0a7fc0344dc Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 27 Jan 2025 17:58:49 +0100 Subject: [PATCH 0660/1340] eof: Update syntax tests. --- .../array/nested_calldata_storage.sol | 13 +++ .../array/nested_calldata_storage2.sol | 13 +++ ...sing_public_state_variable_via_v1_type.sol | 2 + ...rary_function_accepting_storage_struct.sol | 2 + ...rary_function_accepting_storage_struct.sol | 2 + .../abiEncoder/v1_call_to_v2_modifier.sol | 2 + .../v1_constructor_with_v2_modifier.sol | 2 + ...ance_from_contract_calling_v2_function.sol | 2 + ...itance_from_contract_defining_v2_event.sol | 2 + ...itance_from_contract_emitting_v2_event.sol | 2 + .../v1_modifier_overriding_v2_modifier.sol | 2 + .../abiEncoder/v1_v2_v1_modifier_mix.sol | 2 + .../array/nested_calldata_storage.sol | 2 + .../array/nested_calldata_storage2.sol | 2 + .../bytecodeReferences/library_non_called.sol | 2 + .../constants/mod_div_rational.sol | 4 +- .../constructor/nonabiv2_type_abstract.sol | 2 + .../builtin/builtin_type_definition.sol | 1 + .../import_and_call_stdlib_function.sol | 1 + .../functionCalls/calloptions_duplicated.sol | 2 + .../calloptions_on_delegatecall.sol | 2 + .../calloptions_on_staticcall.sol | 1 + .../functionCalls/calloptions_repeated.sol | 1 + .../eof/calloptions_on_delegatecall.sol | 11 +++ .../eof/calloptions_on_staticcall.sol | 12 +++ .../eof/lowlevel_call_options.sol | 9 ++ .../functionCalls/lowlevel_call_options.sol | 2 + .../functionTypes/call_gas_on_function.sol | 3 +- ...r_external_functions_with_call_options.sol | 12 +++ ...xternal_functions_with_extra_gas_slots.sol | 12 --- .../eof/call_gas_on_function.sol | 10 +++ ...ns_with_variable_number_of_stack_slots.sol | 7 +- .../syntaxTests/immutable/creationCode.sol | 2 + .../syntaxTests/immutable/no_assignments.sol | 4 +- .../inlineArrays/inline_array_fixed_types.sol | 4 +- .../inlineArrays/inline_array_rationals.sol | 4 +- .../assignment_from_library.sol | 2 + .../create2_as_variable_post_istanbul.sol | 1 + .../inlineAssembly/evm_byzantium.sol | 1 + .../inlineAssembly/evm_constantinople.sol | 1 + ...dehash_as_variable_post_constantinople.sol | 1 + .../inlineAssembly/hex_switch_case.sol | 3 +- .../inlineAssembly/invalid/pc_disallowed.sol | 2 + .../string_literal_switch_case.sol | 3 +- .../use_msize_without_optimizer.sol | 1 + .../syntaxTests/metaTypes/codeAccess.sol | 2 + .../metaTypes/codeAccessAbstractCreation.sol | 2 + .../metaTypes/codeAccessAbstractRuntime.sol | 2 + .../syntaxTests/metaTypes/codeAccessBase.sol | 2 + .../metaTypes/codeAccessCyclic.sol | 2 + .../metaTypes/codeAccessIsConstant.sol | 2 + .../metaTypes/codeAccessLibrary.sol | 2 + .../metaTypes/codeAccess_super.sol | 2 + .../syntaxTests/metaTypes/codeIsNoLValue.sol | 2 + .../metaTypes/runtimeCodeWarningAssembly.sol | 2 + .../metaTypes/type_runtimecode.sol | 2 + ...e_runtimecode_from_ternary_expression_.sol | 2 + .../303_fixed_type_int_conversion.sol | 4 +- ...304_fixed_type_rational_int_conversion.sol | 4 +- ...ixed_type_rational_fraction_conversion.sol | 4 +- .../307_rational_unary_minus_operation.sol | 4 +- .../312_leading_zero_rationals_convert.sol | 4 +- .../314_fixed_type_zero_handling.sol | 4 +- ..._fixed_type_valid_explicit_conversions.sol | 4 +- .../323_mapping_with_fixed_literal.sol | 4 +- .../324_fixed_points_inside_structs.sol | 4 +- ...8_rational_to_fixed_literal_expression.sol | 4 +- .../343_integer_and_fixed_interaction.sol | 4 +- .../nameAndTypeResolution/497_gasleft.sol | 2 + .../lexer_numbers_with_underscores_fixed.sol | 4 +- .../sizeLimits/bytecode_too_large.sol | 1 + .../bytecode_too_large_abiencoder_v1.sol | 1 + .../functionCallOptions_err.sol | 2 + ...nspecified_encoding_internal_functions.sol | 12 +-- .../types/address/address_members.sol | 2 + .../address/address_payable_selfdestruct.sol | 2 + .../syntaxTests/types/address/codehash.sol | 1 + .../types/address/eof/address_members.sol | 9 ++ ...ional_number_literal_to_fixed_implicit.sol | 4 +- .../address_constantinople.sol | 1 + .../syntaxTests/viewPureChecker/assembly.sol | 2 + .../assembly_constantinople.sol | 1 + .../viewPureChecker/builtin_functions.sol | 2 + .../call_options_without_call.sol | 9 ++ .../viewPureChecker/eof/assembly.sol | 29 +++++++ .../viewPureChecker/eof/builtin_functions.sol | 22 +++++ .../inline_assembly_instructions_allowed.sol | 86 +++++++++++++++++++ ...ine_assembly_instructions_allowed_pure.sol | 85 ++++++++++++++++++ ...ine_assembly_instructions_allowed_view.sol | 85 ++++++++++++++++++ ...nline_assembly_instructions_disallowed.sol | 28 ++++++ ..._assembly_instructions_disallowed_pure.sol | 71 +++++++++++++++ ..._assembly_instructions_disallowed_view.sol | 28 ++++++ .../gas_value_without_call.sol | 2 + .../gas_with_call_nonpayable.sol | 2 + .../inline_assembly_instructions_allowed.sol | 1 + ...ine_assembly_instructions_allowed_pure.sol | 1 + ...ine_assembly_instructions_allowed_view.sol | 1 + ...nline_assembly_instructions_disallowed.sol | 2 + ..._assembly_instructions_disallowed_pure.sol | 2 + ...instructions_disallowed_pure_byzantium.sol | 1 + ...uctions_disallowed_pure_constantinople.sol | 1 + ..._assembly_instructions_disallowed_view.sol | 1 + .../viewPureChecker/staticcall_gas_view.sol | 1 + 103 files changed, 701 insertions(+), 44 deletions(-) create mode 100644 test/libsolidity/semanticTests/array/nested_calldata_storage.sol create mode 100644 test/libsolidity/semanticTests/array/nested_calldata_storage2.sol create mode 100644 test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_delegatecall.sol create mode 100644 test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_staticcall.sol create mode 100644 test/libsolidity/syntaxTests/functionCalls/eof/lowlevel_call_options.sol create mode 100644 test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_call_options.sol delete mode 100644 test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_extra_gas_slots.sol create mode 100644 test/libsolidity/syntaxTests/functionTypes/eof/call_gas_on_function.sol create mode 100644 test/libsolidity/syntaxTests/types/address/eof/address_members.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/call_options_without_call.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/eof/assembly.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/eof/builtin_functions.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_pure.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_view.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_pure.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_view.sol diff --git a/test/libsolidity/semanticTests/array/nested_calldata_storage.sol b/test/libsolidity/semanticTests/array/nested_calldata_storage.sol new file mode 100644 index 000000000..7cc9753be --- /dev/null +++ b/test/libsolidity/semanticTests/array/nested_calldata_storage.sol @@ -0,0 +1,13 @@ +pragma abicoder v2; + +contract C { + uint[][2] public tmp_i; + function i(uint[][2] calldata s) external { tmp_i = s; } +} +// ==== +// compileViaYul: true +// ---- +// i(uint256[][2]): 0x20, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 +// gas irOptimized: 223100 +// tmp_i(uint256,uint256): 0, 0 -> 0x0A01 +// tmp_i(uint256,uint256): 1, 0 -> 0x0B01 diff --git a/test/libsolidity/semanticTests/array/nested_calldata_storage2.sol b/test/libsolidity/semanticTests/array/nested_calldata_storage2.sol new file mode 100644 index 000000000..f8db31b54 --- /dev/null +++ b/test/libsolidity/semanticTests/array/nested_calldata_storage2.sol @@ -0,0 +1,13 @@ +pragma abicoder v2; + +contract C { + uint[][] public tmp_i; + function i(uint[][] calldata s) external { tmp_i = s; } +} +// ==== +// compileViaYul: true +// ---- +// i(uint256[][]): 0x20, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 +// gas irOptimized: 245506 +// tmp_i(uint256,uint256): 0, 0 -> 0x0A01 +// tmp_i(uint256,uint256): 1, 0 -> 0x0B01 diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol index f324d2c33..036a25976 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol @@ -13,4 +13,6 @@ contract D { return a + b; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol index b21b7cfaf..03fb9bae6 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol @@ -19,4 +19,6 @@ contract Test { L.set(item); } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol index 41bc072a5..01d9658ce 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol @@ -19,4 +19,6 @@ contract Test { L.get(item); } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol index 78d7b0512..ef066593c 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol @@ -25,4 +25,6 @@ contract C is B { validate() {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol index 1ac5d713b..b937d1e2d 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol @@ -32,4 +32,6 @@ import "B"; contract D is C { constructor() validate B() validate C() validate {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol index 073a125be..9743d5318 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol @@ -23,4 +23,6 @@ pragma abicoder v1; import "A"; contract C is B {} +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol index 963ed33c7..e4492a4ef 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol @@ -13,4 +13,6 @@ pragma abicoder v1; import "A"; contract D is C {} +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol index 8aa2f8552..5ae4cb0ed 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol @@ -19,4 +19,6 @@ pragma abicoder v1; import "A"; contract D is C {} +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol index dd102cf51..9a809b50a 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol @@ -27,4 +27,6 @@ contract C is B { _; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol index e5df9cc82..6665c42ef 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol @@ -52,4 +52,6 @@ struct Data { contract X { function get() public view returns (Data memory) {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol b/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol index 9aa5fce12..e9ef53842 100644 --- a/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol +++ b/test/libsolidity/syntaxTests/array/nested_calldata_storage.sol @@ -5,5 +5,7 @@ contract C { function i(uint[][2] calldata s) external { tmp_i = s; } } +// ==== +// compileViaYul: false // ---- // UnimplementedFeatureError 1834: (35-127): Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. diff --git a/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol b/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol index f1125b4d2..5db87f0d4 100644 --- a/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol +++ b/test/libsolidity/syntaxTests/array/nested_calldata_storage2.sol @@ -5,5 +5,7 @@ contract C { function i(uint[][] calldata s) external { tmp_i = s; } } +// ==== +// compileViaYul: false // ---- // UnimplementedFeatureError 1834: (35-125): Copying nested calldata dynamic arrays to storage is not implemented in the old code generator. diff --git a/test/libsolidity/syntaxTests/bytecodeReferences/library_non_called.sol b/test/libsolidity/syntaxTests/bytecodeReferences/library_non_called.sol index b7392ff3e..1374c3110 100644 --- a/test/libsolidity/syntaxTests/bytecodeReferences/library_non_called.sol +++ b/test/libsolidity/syntaxTests/bytecodeReferences/library_non_called.sol @@ -7,5 +7,7 @@ library L2 { contract A { function f() public pure { type(L2).creationCode; } } +// ==== +// bytecodeFormat: legacy // ---- // Warning 6133: (157-178): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/constants/mod_div_rational.sol b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol index 68d3bfc7a..b7a4b4518 100644 --- a/test/libsolidity/syntaxTests/constants/mod_div_rational.sol +++ b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol @@ -4,5 +4,7 @@ contract C { fixed a3 = 0 / 0.123; fixed a4 = 0 / -0.123; } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: (0-150): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (28-53): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol b/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol index 2ca22790c..ca52859ff 100644 --- a/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol +++ b/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol @@ -2,4 +2,6 @@ pragma abicoder v1; abstract contract C { constructor(uint[][][] memory t) {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol index 858b9132d..74a659cd8 100644 --- a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol +++ b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol @@ -32,6 +32,7 @@ contract C { // ==== // EVMVersion: >=constantinople // compileViaYul: true +// bytecodeFormat: legacy // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. // Info 4164: (31-61): Inferred type: void diff --git a/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol b/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol index fc75e8594..72af2133f 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol @@ -13,6 +13,7 @@ contract C // ==== // EVMVersion: >=constantinople // compileViaYul: true +// bytecodeFormat: legacy // ---- // Warning 2264: (std.stub:63-92): Experimental features are turned on. Do not use experimental features on live deployments. // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/functionCalls/calloptions_duplicated.sol b/test/libsolidity/syntaxTests/functionCalls/calloptions_duplicated.sol index 3b162a7f2..417eea14d 100644 --- a/test/libsolidity/syntaxTests/functionCalls/calloptions_duplicated.sol +++ b/test/libsolidity/syntaxTests/functionCalls/calloptions_duplicated.sol @@ -8,6 +8,8 @@ contract C { } } // ==== +// bytecodeFormat: legacy +// ==== // EVMVersion: >=constantinople // ---- // TypeError 9886: (78-101): Duplicate option "gas". diff --git a/test/libsolidity/syntaxTests/functionCalls/calloptions_on_delegatecall.sol b/test/libsolidity/syntaxTests/functionCalls/calloptions_on_delegatecall.sol index d719fdcd9..858b9a1d2 100644 --- a/test/libsolidity/syntaxTests/functionCalls/calloptions_on_delegatecall.sol +++ b/test/libsolidity/syntaxTests/functionCalls/calloptions_on_delegatecall.sol @@ -3,6 +3,8 @@ contract C { address(10).delegatecall{value: 7, gas: 3}(""); } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 6189: (56-98): Cannot set option "value" for delegatecall. // Warning 9302: (56-102): Return value of low-level calls not used. diff --git a/test/libsolidity/syntaxTests/functionCalls/calloptions_on_staticcall.sol b/test/libsolidity/syntaxTests/functionCalls/calloptions_on_staticcall.sol index e128f03f1..c525542c7 100644 --- a/test/libsolidity/syntaxTests/functionCalls/calloptions_on_staticcall.sol +++ b/test/libsolidity/syntaxTests/functionCalls/calloptions_on_staticcall.sol @@ -5,6 +5,7 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // TypeError 2842: (56-96): Cannot set option "value" for staticcall. // Warning 9302: (56-100): Return value of low-level calls not used. diff --git a/test/libsolidity/syntaxTests/functionCalls/calloptions_repeated.sol b/test/libsolidity/syntaxTests/functionCalls/calloptions_repeated.sol index 4356efcf9..0961881a1 100644 --- a/test/libsolidity/syntaxTests/functionCalls/calloptions_repeated.sol +++ b/test/libsolidity/syntaxTests/functionCalls/calloptions_repeated.sol @@ -10,6 +10,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // TypeError 1645: (78-110): Function call options have already been set, you have to combine them into a single {...}-option. // TypeError 1645: (120-154): Function call options have already been set, you have to combine them into a single {...}-option. diff --git a/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_delegatecall.sol b/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_delegatecall.sol new file mode 100644 index 000000000..fdbb79b96 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_delegatecall.sol @@ -0,0 +1,11 @@ +contract C { + function foo() pure internal { + address(10).delegatecall{value: 7, gas: 3}(""); + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 6189: (56-98): Cannot set option "value" for delegatecall. +// TypeError 3765: (56-98): Function call option "gas" cannot be used when compiling to EOF. +// Warning 9302: (56-102): Return value of low-level calls not used. diff --git a/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_staticcall.sol b/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_staticcall.sol new file mode 100644 index 000000000..f63837dcf --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_staticcall.sol @@ -0,0 +1,12 @@ +contract C { + function foo() pure internal { + address(10).staticcall{value: 7, gas: 3}(""); + } +} +// ==== +// EVMVersion: >=prague +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 2842: (56-96): Cannot set option "value" for staticcall. +// TypeError 3765: (56-96): Function call option "gas" cannot be used when compiling to EOF. +// Warning 9302: (56-100): Return value of low-level calls not used. diff --git a/test/libsolidity/syntaxTests/functionCalls/eof/lowlevel_call_options.sol b/test/libsolidity/syntaxTests/functionCalls/eof/lowlevel_call_options.sol new file mode 100644 index 000000000..4bc515d7c --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/eof/lowlevel_call_options.sol @@ -0,0 +1,9 @@ +contract C { + function foo() internal { + (bool success, ) = address(10).call{value: 7}(""); + success; + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- diff --git a/test/libsolidity/syntaxTests/functionCalls/lowlevel_call_options.sol b/test/libsolidity/syntaxTests/functionCalls/lowlevel_call_options.sol index da5c17a20..c5ec6de71 100644 --- a/test/libsolidity/syntaxTests/functionCalls/lowlevel_call_options.sol +++ b/test/libsolidity/syntaxTests/functionCalls/lowlevel_call_options.sol @@ -4,4 +4,6 @@ contract C { success; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/functionTypes/call_gas_on_function.sol b/test/libsolidity/syntaxTests/functionTypes/call_gas_on_function.sol index 6b926e2dd..e92d1cfb0 100644 --- a/test/libsolidity/syntaxTests/functionTypes/call_gas_on_function.sol +++ b/test/libsolidity/syntaxTests/functionTypes/call_gas_on_function.sol @@ -4,5 +4,6 @@ contract C { x{gas: 2}(1); } } - +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_call_options.sol b/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_call_options.sol new file mode 100644 index 000000000..da84e6ada --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_call_options.sol @@ -0,0 +1,12 @@ +contract C { + function external_test_function() payable external {} + function comparison_operator_for_external_function_with_extra_slots() external returns (bool) { + return ( + (this.external_test_function{value: 4} == this.external_test_function) && + (this.external_test_function{value: 4} == this.external_test_function{value: 4}) + ); + } +} +// ---- +// TypeError 2271: (201-269): Built-in binary operator == cannot be applied to types function () payable external and function () payable external. +// TypeError 2271: (287-365): Built-in binary operator == cannot be applied to types function () payable external and function () payable external. diff --git a/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_extra_gas_slots.sol b/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_extra_gas_slots.sol deleted file mode 100644 index 12cbe2939..000000000 --- a/test/libsolidity/syntaxTests/functionTypes/comparison_operator_for_external_functions_with_extra_gas_slots.sol +++ /dev/null @@ -1,12 +0,0 @@ -contract C { - function external_test_function() external {} - function comparison_operator_for_external_function_with_extra_slots() external returns (bool) { - return ( - (this.external_test_function{gas: 4} == this.external_test_function) && - (this.external_test_function{gas: 4} == this.external_test_function{gas: 4}) - ); - } -} -// ---- -// TypeError 2271: (193-259): Built-in binary operator == cannot be applied to types function () external and function () external. -// TypeError 2271: (277-351): Built-in binary operator == cannot be applied to types function () external and function () external. diff --git a/test/libsolidity/syntaxTests/functionTypes/eof/call_gas_on_function.sol b/test/libsolidity/syntaxTests/functionTypes/eof/call_gas_on_function.sol new file mode 100644 index 000000000..c4f00843d --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/eof/call_gas_on_function.sol @@ -0,0 +1,10 @@ +contract C { + function (uint) external returns (uint) x; + function f() public { + x{gas: 2}(1); + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 3765: (94-103): Function call option "gas" cannot be used when compiling to EOF. diff --git a/test/libsolidity/syntaxTests/functionTypes/external_functions_with_variable_number_of_stack_slots.sol b/test/libsolidity/syntaxTests/functionTypes/external_functions_with_variable_number_of_stack_slots.sol index 8593bdbf4..a6d8d7c1d 100644 --- a/test/libsolidity/syntaxTests/functionTypes/external_functions_with_variable_number_of_stack_slots.sol +++ b/test/libsolidity/syntaxTests/functionTypes/external_functions_with_variable_number_of_stack_slots.sol @@ -1,8 +1,7 @@ contract C { - function f (address) external returns (bool) { - this.f{gas: 42}.address; + function f (address) payable external returns (bool) { + this.f{value: 42}.address; } } // ---- -// Warning 6321: (56-60): Unnamed return variable can remain unassigned. Add an explicit return with value to all non-reverting code paths or name the variable. -// Warning 2018: (17-102): Function state mutability can be restricted to view +// Warning 6321: (64-68): Unnamed return variable can remain unassigned. Add an explicit return with value to all non-reverting code paths or name the variable. diff --git a/test/libsolidity/syntaxTests/immutable/creationCode.sol b/test/libsolidity/syntaxTests/immutable/creationCode.sol index 0a2282695..32fb4edea 100644 --- a/test/libsolidity/syntaxTests/immutable/creationCode.sol +++ b/test/libsolidity/syntaxTests/immutable/creationCode.sol @@ -7,4 +7,6 @@ contract Test { return type(A).creationCode; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/immutable/no_assignments.sol b/test/libsolidity/syntaxTests/immutable/no_assignments.sol index 7d7948671..92bcac8cf 100644 --- a/test/libsolidity/syntaxTests/immutable/no_assignments.sol +++ b/test/libsolidity/syntaxTests/immutable/no_assignments.sol @@ -1,3 +1,4 @@ +// TODO: This test case should work the same way for EOF but EOF immutables support is not in its final state yet. contract C { uint immutable x; constructor() { @@ -8,6 +9,7 @@ contract C { function f() external view returns(uint) { return x; } } // ==== +// bytecodeFormat: legacy // optimize-yul: true // ---- -// CodeGenerationError 1284: (0-168): Some immutables were read from but never assigned, possibly because of optimization. +// CodeGenerationError 1284: (115-283): Some immutables were read from but never assigned, possibly because of optimization. diff --git a/test/libsolidity/syntaxTests/inlineArrays/inline_array_fixed_types.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_fixed_types.sol index 8e51bd188..7c67a647a 100644 --- a/test/libsolidity/syntaxTests/inlineArrays/inline_array_fixed_types.sol +++ b/test/libsolidity/syntaxTests/inlineArrays/inline_array_fixed_types.sol @@ -3,7 +3,9 @@ contract test { fixed[3] memory a = [fixed(3.5), fixed(-4.25), fixed(967.125)]; } } +// ==== +// compileViaYul: true // ---- // Warning 2072: (50-67): Unused local variable. // Warning 2018: (20-119): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: (0-121): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (71-81): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/inlineArrays/inline_array_rationals.sol b/test/libsolidity/syntaxTests/inlineArrays/inline_array_rationals.sol index 0382672fe..20e9de764 100644 --- a/test/libsolidity/syntaxTests/inlineArrays/inline_array_rationals.sol +++ b/test/libsolidity/syntaxTests/inlineArrays/inline_array_rationals.sol @@ -3,7 +3,9 @@ contract test { ufixed128x3[4] memory a = [ufixed128x3(3.5), 4.125, 2.5, 4.0]; } } +// ==== +// compileViaYul: true // ---- // Warning 2072: (50-73): Unused local variable. // Warning 2018: (20-118): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: (0-120): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (77-93): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_library.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_library.sol index 522ca801d..801bdd7ee 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_library.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_library.sol @@ -8,4 +8,6 @@ contract C { } } } +// ==== +// compileViaYul: false // ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_post_istanbul.sol b/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_post_istanbul.sol index 96a384c54..0468ef093 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_post_istanbul.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/create2_as_variable_post_istanbul.sol @@ -6,4 +6,5 @@ contract c { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/evm_byzantium.sol b/test/libsolidity/syntaxTests/inlineAssembly/evm_byzantium.sol index b08172ebe..e019026f6 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/evm_byzantium.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/evm_byzantium.sol @@ -13,4 +13,5 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople.sol b/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople.sol index 2aff4351a..ddfa80d7f 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople.sol @@ -19,4 +19,5 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_post_constantinople.sol b/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_post_constantinople.sol index 8b34ab906..8ee7f644b 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_post_constantinople.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/extcodehash_as_variable_post_constantinople.sol @@ -7,4 +7,5 @@ contract c { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol b/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol index 038e8c4ff..915048905 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/hex_switch_case.sol @@ -1,10 +1,9 @@ contract C { function f() public pure { assembly { - switch codesize() + switch calldataload(0) case hex"00" {} case hex"1122" {} } } } -// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/pc_disallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/pc_disallowed.sol index 816bb1c0d..1178e9a2b 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/pc_disallowed.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/pc_disallowed.sol @@ -5,5 +5,7 @@ contract C { } } } +// ==== +// bytecodeFormat: legacy // ---- // SyntaxError 2450: (61-63): PC instruction is a low-level EVM feature. Because of that PC is disallowed in strict assembly. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/string_literal_switch_case.sol b/test/libsolidity/syntaxTests/inlineAssembly/string_literal_switch_case.sol index 0a63987e1..d612d10d0 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/string_literal_switch_case.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/string_literal_switch_case.sol @@ -1,10 +1,9 @@ contract C { function f() public pure { assembly { - switch codesize() + switch calldataload(0) case "1" {} case "2" {} } } } -// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/use_msize_without_optimizer.sol b/test/libsolidity/syntaxTests/inlineAssembly/use_msize_without_optimizer.sol index 8cdf96641..d356fe299 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/use_msize_without_optimizer.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/use_msize_without_optimizer.sol @@ -7,4 +7,5 @@ contract C { } // ==== // optimize-yul: false +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccess.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccess.sol index e90443e14..6136665e3 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccess.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccess.sol @@ -9,4 +9,6 @@ contract Test { contract Other { function f(uint) public pure returns (uint) {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractCreation.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractCreation.sol index 2f5c356c0..22f81cfb0 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractCreation.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractCreation.sol @@ -6,5 +6,7 @@ contract Test { abstract contract Other { function f(uint) public returns (uint); } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 9582: (97-121): Member "creationCode" not found or not visible after argument-dependent lookup in type(contract Other). diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractRuntime.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractRuntime.sol index 538a26e78..8019dabb2 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractRuntime.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractRuntime.sol @@ -6,5 +6,7 @@ contract Test { abstract contract Other { function f(uint) public returns (uint); } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 9582: (91-114): Member "runtimeCode" not found or not visible after argument-dependent lookup in type(contract Other). diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessBase.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessBase.sol index c202046cc..c4b3efedd 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessBase.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessBase.sol @@ -21,6 +21,8 @@ contract Test4 is Base { return type(Base).runtimeCode; } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 7813: (166-190): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode". // TypeError 7813: (300-323): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode". diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessCyclic.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessCyclic.sol index 57e3263e3..4a5a760f7 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessCyclic.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessCyclic.sol @@ -8,6 +8,8 @@ contract B { type(A).runtimeCode; } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 7813: (52-71): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode". // TypeError 7813: (133-152): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode". diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessIsConstant.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessIsConstant.sol index cda5d5c34..96303396e 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessIsConstant.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessIsConstant.sol @@ -4,4 +4,6 @@ contract Test { } contract B { function f() public pure {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessLibrary.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessLibrary.sol index f746dc35d..8c7070068 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccessLibrary.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessLibrary.sol @@ -9,4 +9,6 @@ contract Test { contract Library { function f(uint) public pure returns (uint) {} } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccess_super.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccess_super.sol index 7d057e132..a8fef765e 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeAccess_super.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccess_super.sol @@ -9,5 +9,7 @@ contract SuperTest is Other { return type(super).runtimeCode; } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 4259: (177-182): Invalid type for argument in the function call. An enum type, contract type or an integer type is required, but type(contract super SuperTest) provided. diff --git a/test/libsolidity/syntaxTests/metaTypes/codeIsNoLValue.sol b/test/libsolidity/syntaxTests/metaTypes/codeIsNoLValue.sol index c9cade179..2a5127641 100644 --- a/test/libsolidity/syntaxTests/metaTypes/codeIsNoLValue.sol +++ b/test/libsolidity/syntaxTests/metaTypes/codeIsNoLValue.sol @@ -5,6 +5,8 @@ contract Test { } } contract C {} +// ==== +// bytecodeFormat: legacy // ---- // TypeError 4247: (55-75): Expression has to be an lvalue. // TypeError 4247: (100-119): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/metaTypes/runtimeCodeWarningAssembly.sol b/test/libsolidity/syntaxTests/metaTypes/runtimeCodeWarningAssembly.sol index 40eaee040..8e6fcf64e 100644 --- a/test/libsolidity/syntaxTests/metaTypes/runtimeCodeWarningAssembly.sol +++ b/test/libsolidity/syntaxTests/metaTypes/runtimeCodeWarningAssembly.sol @@ -12,6 +12,8 @@ contract C { contract D is C { constructor() {} } +// ==== +// bytecodeFormat: legacy // ---- // Warning 6417: (77-96): The constructor of the contract (or its base) uses inline assembly. Because of that, it might be that the deployed bytecode is different from type(...).runtimeCode. // Warning 6417: (118-137): The constructor of the contract (or its base) uses inline assembly. Because of that, it might be that the deployed bytecode is different from type(...).runtimeCode. diff --git a/test/libsolidity/syntaxTests/metaTypes/type_runtimecode.sol b/test/libsolidity/syntaxTests/metaTypes/type_runtimecode.sol index 6b054b4da..d110b2c8e 100644 --- a/test/libsolidity/syntaxTests/metaTypes/type_runtimecode.sol +++ b/test/libsolidity/syntaxTests/metaTypes/type_runtimecode.sol @@ -6,4 +6,6 @@ contract C { return type(A).runtimeCode; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/type_runtimecode_from_ternary_expression_.sol b/test/libsolidity/syntaxTests/metaTypes/type_runtimecode_from_ternary_expression_.sol index 8fcf65480..f802b9a00 100644 --- a/test/libsolidity/syntaxTests/metaTypes/type_runtimecode_from_ternary_expression_.sol +++ b/test/libsolidity/syntaxTests/metaTypes/type_runtimecode_from_ternary_expression_.sol @@ -9,6 +9,8 @@ contract C { return (getA ? type(A) : type(B)).runtimeCode; } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 9717: (126-133): Invalid mobile type in true expression. // TypeError 3703: (136-143): Invalid mobile type in false expression. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol index 88a407fef..41bb9e046 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/303_fixed_type_int_conversion.sol @@ -7,6 +7,8 @@ contract test { c; d; } } +// ==== +// compileViaYul: true // ---- // Warning 2018: (20-147): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: (0-149): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (93-104): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol index 0e3cb3b6c..2809575b6 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/304_fixed_type_rational_int_conversion.sol @@ -5,6 +5,8 @@ contract test { c; d; } } +// ==== +// compileViaYul: true // ---- // Warning 2018: (20-104): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: (0-106): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (50-61): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol index ada627037..0a13eedcc 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/305_fixed_type_rational_fraction_conversion.sol @@ -5,6 +5,8 @@ contract test { a; d; } } +// ==== +// compileViaYul: true // ---- // Warning 2018: (20-108): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: (0-110): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (50-63): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol index adb9fbe69..d0d11105b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/307_rational_unary_minus_operation.sol @@ -5,5 +5,7 @@ contract test { a; b; } } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: (0-126): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (55-74): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol index e763fa18b..c1586595b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/312_leading_zero_rationals_convert.sol @@ -7,5 +7,7 @@ contract A { a; b; c; d; } } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: (0-289): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (52-70): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol index b9205f01b..07c4017e0 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/314_fixed_type_zero_handling.sol @@ -4,6 +4,8 @@ contract test { ufixed32x1 b = 0; b; } } +// ==== +// compileViaYul: true // ---- // Warning 2018: (20-104): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: (0-106): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (50-65): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol index 1282c24da..84e5b7640 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol @@ -5,6 +5,8 @@ contract test { ufixed8x1 c = ufixed8x1(1/3); c; } } +// ==== +// compileViaYul: true // ---- // Warning 2018: (20-182): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: (0-184): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (67-84): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol index 3ee670cd5..9a714f6b9 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/323_mapping_with_fixed_literal.sol @@ -4,5 +4,7 @@ contract test { fixedString[0.5] = "Half"; } } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: (0-130): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (96-112): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol index ba467a67b..f0ec56875 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/324_fixed_points_inside_structs.sol @@ -5,5 +5,7 @@ contract test { } myStruct a = myStruct(3.125, 3); } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: (0-115): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (94-112): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol index b5162bcd9..7293e0f42 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/328_rational_to_fixed_literal_expression.sol @@ -10,7 +10,9 @@ contract test { a; b; c; d; e; f; g; } } +// ==== +// compileViaYul: true // ---- // Warning 2519: (238-252): This declaration shadows an existing declaration. // Warning 2018: (20-339): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: (0-341): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (50-72): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol index 3ebd54d45..27133cf1d 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/343_integer_and_fixed_interaction.sol @@ -3,7 +3,9 @@ contract test { ufixed a = uint64(1) + ufixed(2); } } +// ==== +// compileViaYul: true // ---- // Warning 2072: (50-58): Unused local variable. // Warning 2018: (20-89): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: (0-91): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (73-82): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/497_gasleft.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/497_gasleft.sol index 3d5acac99..7a5254a1a 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/497_gasleft.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/497_gasleft.sol @@ -1,4 +1,6 @@ contract C { function f() public view returns (uint256 val) { return gasleft(); } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol index 9346264ed..2e1c746ba 100644 --- a/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol +++ b/test/libsolidity/syntaxTests/parsing/lexer_numbers_with_underscores_fixed.sol @@ -6,5 +6,7 @@ contract C { f1; f2; } } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: (0-109): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (46-64): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol index f22b9755d..5ac74bba7 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large.sol @@ -8,5 +8,6 @@ contract test { } // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy // ---- // Warning 5574: (21-27154): Contract code size is 27164 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. diff --git a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol index a0c7267d0..f3091ebf5 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol @@ -8,5 +8,6 @@ contract test { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Warning 5574: (21-27154): Contract code size is 27205 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. diff --git a/test/libsolidity/syntaxTests/specialFunctions/functionCallOptions_err.sol b/test/libsolidity/syntaxTests/specialFunctions/functionCallOptions_err.sol index 071859e53..8e5ebcdeb 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/functionCallOptions_err.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/functionCallOptions_err.sol @@ -5,6 +5,8 @@ contract C { abi.encode(this.f{value: 2, gas: 1}); } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 2056: (60-76): This type cannot be encoded. // TypeError 2056: (92-106): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol index 6ecb4e4ff..a69dcfa92 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol @@ -1,11 +1,11 @@ contract C { - function f() public pure { - bytes32 h = keccak256(abi.encodePacked(keccak256, f, this.f{gas: 2}, blockhash)); + function f() payable public { + bytes32 h = keccak256(abi.encodePacked(keccak256, f, this.f{value: 2}, blockhash)); h; } } // ---- -// TypeError 2056: (91-100): This type cannot be encoded. -// TypeError 2056: (102-103): This type cannot be encoded. -// TypeError 2056: (105-119): This type cannot be encoded. -// TypeError 2056: (121-130): This type cannot be encoded. +// TypeError 2056: (94-103): This type cannot be encoded. +// TypeError 2056: (105-106): This type cannot be encoded. +// TypeError 2056: (108-124): This type cannot be encoded. +// TypeError 2056: (126-135): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/types/address/address_members.sol b/test/libsolidity/syntaxTests/types/address/address_members.sol index 144361b94..9299b65d5 100644 --- a/test/libsolidity/syntaxTests/types/address/address_members.sol +++ b/test/libsolidity/syntaxTests/types/address/address_members.sol @@ -5,4 +5,6 @@ contract C { function i() public view returns (uint) { return f().code.length; } function j() public view returns (uint) { return h().length; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol b/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol index 754ff2c67..449b628d4 100644 --- a/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol +++ b/test/libsolidity/syntaxTests/types/address/address_payable_selfdestruct.sol @@ -3,5 +3,7 @@ contract C { selfdestruct(a); } } +// ==== +// bytecodeFormat: legacy // ---- // Warning 5159: (64-76): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. diff --git a/test/libsolidity/syntaxTests/types/address/codehash.sol b/test/libsolidity/syntaxTests/types/address/codehash.sol index cf7eaabec..00956d97e 100644 --- a/test/libsolidity/syntaxTests/types/address/codehash.sol +++ b/test/libsolidity/syntaxTests/types/address/codehash.sol @@ -5,4 +5,5 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/types/address/eof/address_members.sol b/test/libsolidity/syntaxTests/types/address/eof/address_members.sol new file mode 100644 index 000000000..a1b21de2c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/eof/address_members.sol @@ -0,0 +1,9 @@ +contract C { + function f() public view returns (address) { return address(this); } + function g() public view returns (uint) { return f().balance; } + function h() public pure returns (bytes memory) { return msg.data; } + function j() public pure returns (uint) { return h().length; } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol index e62728770..f76fa8430 100644 --- a/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol +++ b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol @@ -12,5 +12,7 @@ contract C { a; b; c; } } +// ==== +// compileViaYul: true // ---- -// UnimplementedFeatureError 1834: (0-317): Not yet implemented - FixedPointType. +// UnimplementedFeatureError 1834: (66-84): Fixed point types not implemented. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/address_constantinople.sol b/test/libsolidity/syntaxTests/viewPureChecker/address_constantinople.sol index 4387ca60a..e8ee980bf 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/address_constantinople.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/address_constantinople.sol @@ -8,4 +8,5 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol b/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol index cc8ac5e83..9097a166c 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol @@ -27,4 +27,6 @@ contract C { assembly { pop(extcodesize(0)) } } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/assembly_constantinople.sol b/test/libsolidity/syntaxTests/viewPureChecker/assembly_constantinople.sol index ed0b20d53..16f57b2e8 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/assembly_constantinople.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/assembly_constantinople.sol @@ -5,4 +5,5 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol index 4d1710a3a..8f2753213 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol @@ -18,5 +18,7 @@ contract C { } receive() payable external {} } +// ==== +// bytecodeFormat: legacy // ---- // Warning 5159: (122-134): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/call_options_without_call.sol b/test/libsolidity/syntaxTests/viewPureChecker/call_options_without_call.sol new file mode 100644 index 000000000..ea4d20297 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/call_options_without_call.sol @@ -0,0 +1,9 @@ +contract C { + function f() external payable {} + function g(address a) external pure { + a.call{value: 42}; + } + function h() external view { + this.f{value: 42}; + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/assembly.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/assembly.sol new file mode 100644 index 000000000..fad9b7c1f --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/assembly.sol @@ -0,0 +1,29 @@ +contract C { + struct S { uint x; } + S s; + function e() pure public { + assembly { mstore(keccak256(0, 20), mul(s.slot, 2)) } + } + function f() pure public { + uint x; + assembly { x := 7 } + } + function g() view public { + assembly { for {} 1 { pop(sload(0)) } { } pop(calldataload(0)) } + } + function h() view public { + assembly { function g() { pop(blockhash(20)) } } + } + function i() public { + assembly { pop(extcall(0, 1, 2, 3)) } + } + function k() public view { + assembly { pop(balance(0)) } + } + function l() public pure { + assembly { pop(calldataload(0)) } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/builtin_functions.sol new file mode 100644 index 000000000..91ea709fe --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/builtin_functions.sol @@ -0,0 +1,22 @@ +contract C { + function f() public { + payable(this).transfer(1); + require(payable(this).send(2)); + (bool success,) = address(this).delegatecall(""); + require(success); + (success,) = address(this).call(""); + require(success); + } + function g() pure public { + bytes32 x = keccak256("abc"); + bytes32 y = sha256("abc"); + address z = ecrecover(bytes32(uint256(1)), uint8(2), bytes32(uint256(3)), bytes32(uint256(4))); + require(true); + assert(true); + x; y; z; + } + receive() payable external {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed.sol new file mode 100644 index 000000000..81d0f4e56 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed.sol @@ -0,0 +1,86 @@ +contract C { + function f() public { + assembly { + stop() + pop(add(0, 1)) + pop(sub(0, 1)) + pop(mul(0, 1)) + pop(div(0, 1)) + pop(sdiv(0, 1)) + pop(mod(0, 1)) + pop(smod(0, 1)) + pop(exp(0, 1)) + pop(not(0)) + pop(lt(0, 1)) + pop(gt(0, 1)) + pop(slt(0, 1)) + pop(sgt(0, 1)) + pop(eq(0, 1)) + pop(iszero(0)) + pop(and(0, 1)) + pop(or(0, 1)) + pop(xor(0, 1)) + pop(byte(0, 1)) + pop(shl(0, 1)) + pop(shr(0, 1)) + pop(sar(0, 1)) + pop(addmod(0, 1, 2)) + pop(mulmod(0, 1, 2)) + pop(signextend(0, 1)) + pop(keccak256(0, 1)) + pop(0) + pop(mload(0)) + mstore(0, 1) + mstore8(0, 1) + pop(sload(0)) + sstore(0, 1) + pop(address()) + pop(balance(0)) + pop(selfbalance()) + pop(caller()) + pop(callvalue()) + pop(calldataload(0)) + pop(calldatasize()) + calldatacopy(0, 1, 2) + pop(returndatasize()) + returndatacopy(0, 1, 2) + pop(extcall(0, 1, 2, 3)) + pop(extdelegatecall(0, 1, 2)) + pop(extstaticcall(0, 1, 2)) + return(0, 1) + revert(0, 1) + invalid() + log0(0, 1) + log1(0, 1, 2) + log2(0, 1, 2, 3) + log3(0, 1, 2, 3, 4) + log4(0, 1, 2, 3, 4, 5) + pop(chainid()) + pop(basefee()) + pop(origin()) + pop(gasprice()) + pop(blockhash(0)) + pop(coinbase()) + pop(timestamp()) + pop(number()) + pop(prevrandao()) + + mcopy(1, 2, 3) + pop(blobhash(0)) + pop(blobbasefee()) + pop(tload(0)) + tstore(0, 0) + + // NOTE: msize() is allowed only with optimizer disabled + //pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Warning 2394: (1970-1976): Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. +// Warning 5740: (89-1400): Unreachable code. +// Warning 5740: (1413-1425): Unreachable code. +// Warning 5740: (1438-1447): Unreachable code. +// Warning 5740: (1460-1982): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_pure.sol new file mode 100644 index 000000000..f3da4722f --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_pure.sol @@ -0,0 +1,85 @@ +contract C { + function f() public pure { + assembly { + stop() + pop(add(0, 1)) + pop(sub(0, 1)) + pop(mul(0, 1)) + pop(div(0, 1)) + pop(sdiv(0, 1)) + pop(mod(0, 1)) + pop(smod(0, 1)) + pop(exp(0, 1)) + pop(not(0)) + pop(lt(0, 1)) + pop(gt(0, 1)) + pop(slt(0, 1)) + pop(sgt(0, 1)) + pop(eq(0, 1)) + pop(iszero(0)) + pop(and(0, 1)) + pop(or(0, 1)) + pop(xor(0, 1)) + pop(byte(0, 1)) + pop(shl(0, 1)) + pop(shr(0, 1)) + pop(sar(0, 1)) + pop(addmod(0, 1, 2)) + pop(mulmod(0, 1, 2)) + pop(signextend(0, 1)) + pop(keccak256(0, 1)) + pop(0) + pop(mload(0)) + mstore(0, 1) + mstore8(0, 1) + //pop(sload(0)) + //sstore(0, 1) + //pop(address()) + //pop(balance(0)) + //pop(selfbalance()) + //pop(caller()) + //pop(callvalue()) + pop(calldataload(0)) + pop(calldatasize()) + calldatacopy(0, 1, 2) + pop(returndatasize()) + returndatacopy(0, 1, 2) + //pop(extcall(0, 1, 2, 3)) + //pop(extdelegatecall(0, 1, 2)) + //pop(extstaticcall(0, 1, 2)) + return(0, 1) + revert(0, 1) + invalid() + //log0(0, 1) + //log1(0, 1, 2) + //log2(0, 1, 2, 3) + //log3(0, 1, 2, 3, 4) + //log4(0, 1, 2, 3, 4, 5) + //pop(chainid()) + //pop(basefee()) + //pop(origin()) + //pop(gasprice()) + //pop(blockhash(0)) + //pop(coinbase()) + //pop(timestamp()) + //pop(number()) + //pop(prevrandao()) + //pop(gaslimit()) + mcopy(1, 2, 3) + //pop(blobhash(0)) + //pop(blobbasefee()) + //pop(tload(0)) + //tstore(0, 1) + + // NOTE: msize() is allowed only with optimizer disabled + //pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Warning 5740: (94-1425): Unreachable code. +// Warning 5740: (1438-1450): Unreachable code. +// Warning 5740: (1463-1472): Unreachable code. +// Warning 5740: (1939-1953): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_view.sol new file mode 100644 index 000000000..d1a5be036 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_allowed_view.sol @@ -0,0 +1,85 @@ +contract C { + function f() public view { + assembly { + stop() + pop(add(0, 1)) + pop(sub(0, 1)) + pop(mul(0, 1)) + pop(div(0, 1)) + pop(sdiv(0, 1)) + pop(mod(0, 1)) + pop(smod(0, 1)) + pop(exp(0, 1)) + pop(not(0)) + pop(lt(0, 1)) + pop(gt(0, 1)) + pop(slt(0, 1)) + pop(sgt(0, 1)) + pop(eq(0, 1)) + pop(iszero(0)) + pop(and(0, 1)) + pop(or(0, 1)) + pop(xor(0, 1)) + pop(byte(0, 1)) + pop(shl(0, 1)) + pop(shr(0, 1)) + pop(sar(0, 1)) + pop(addmod(0, 1, 2)) + pop(mulmod(0, 1, 2)) + pop(signextend(0, 1)) + pop(keccak256(0, 1)) + pop(0) + pop(mload(0)) + mstore(0, 1) + mstore8(0, 1) + pop(sload(0)) + //sstore(0, 1) + pop(address()) + pop(balance(0)) + pop(selfbalance()) + pop(caller()) + pop(callvalue()) + pop(calldataload(0)) + pop(calldatasize()) + calldatacopy(0, 1, 2) + pop(returndatasize()) + returndatacopy(0, 1, 2) + //pop(extcall(0, 1, 2, 3)) + //pop(extdelegatecall(0, 1, 2)) + pop(extstaticcall(0, 1, 2)) + return(0, 1) + revert(0, 1) + invalid() + //log0(0, 1) + //log1(0, 1, 2) + //log2(0, 1, 2, 3) + //log3(0, 1, 2, 3, 4) + //log4(0, 1, 2, 3, 4, 5) + pop(chainid()) + pop(basefee()) + pop(origin()) + pop(gasprice()) + pop(blockhash(0)) + pop(coinbase()) + pop(timestamp()) + pop(number()) + pop(prevrandao()) + pop(gaslimit()) + mcopy(1, 2, 3) + pop(blobhash(0)) + pop(blobbasefee()) + pop(tload(0)) + //tstore(0, 1) + + // NOTE: msize() is allowed only with optimizer disabled + //pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Warning 5740: (94-1411): Unreachable code. +// Warning 5740: (1424-1436): Unreachable code. +// Warning 5740: (1449-1458): Unreachable code. +// Warning 5740: (1626-2005): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed.sol new file mode 100644 index 000000000..e65ea26bd --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed.sol @@ -0,0 +1,28 @@ +// TODO: eofcreate, returncontract and auxdataloadn are for now disallowed in inline assembly. They need proper design on language level +contract C { + function f() public { + assembly { + linkersymbol("x") + memoryguard(0) + verbatim_1i_1o(hex"600202", 0) + + pop(eofcreate("a", 0, 0, 0, 0)) + returncontract("a", 0, 0, 0) + pop(auxdataloadn(0)) + + pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// SyntaxError 6553: (184-449): The msize instruction cannot be used when the Yul optimizer is activated because it can change its semantics. Either disable the Yul optimizer or do not use the instruction. +// DeclarationError 4619: (207-219): Function "linkersymbol" not found. +// DeclarationError 4619: (237-248): Function "memoryguard" not found. +// DeclarationError 4619: (264-278): Function "verbatim_1i_1o" not found. +// DeclarationError 4619: (312-321): Function "eofcreate" not found. +// TypeError 3950: (312-338): Expected expression to evaluate to one value, but got 0 values instead. +// DeclarationError 4619: (352-366): Function "returncontract" not found. +// DeclarationError 4619: (397-409): Function "auxdataloadn" not found. +// TypeError 3950: (397-412): Expected expression to evaluate to one value, but got 0 values instead. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_pure.sol new file mode 100644 index 000000000..19342ec19 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_pure.sol @@ -0,0 +1,71 @@ +contract C { + function f() public pure { + assembly { + pop(sload(0)) + sstore(0, 1) + pop(address()) + pop(balance(0)) + pop(caller()) + pop(callvalue()) + pop(extcall(0, 1, 2, 3)) + pop(extstaticcall(0, 1, 2)) + pop(extdelegatecall(0, 1, 2)) + log0(0, 1) + log1(0, 1, 2) + log2(0, 1, 2, 3) + log3(0, 1, 2, 3, 4) + log4(0, 1, 2, 3, 4, 5) + pop(origin()) + pop(gasprice()) + pop(blockhash(0)) + pop(coinbase()) + pop(timestamp()) + pop(number()) + pop(gaslimit()) + pop(blobhash(0)) + pop(blobbasefee()) + pop(tload(0)) + tstore(0, 0) + pop(selfbalance()) + pop(chainid()) + pop(basefee()) + pop(prevrandao()) + + // This one is disallowed too but the error suppresses other errors. + //pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Warning 2394: (781-787): Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. +// TypeError 2527: (79-87): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (101-113): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (130-139): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (157-167): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (185-193): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (211-222): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (240-259): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (277-299): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (317-341): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (355-365): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (378-391): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (404-420): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (433-452): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (465-487): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (504-512): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (530-540): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (558-570): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (588-598): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (616-627): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (645-653): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (671-681): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (699-710): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (728-741): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (759-767): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (781-793): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (810-823): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (841-850): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (868-877): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (895-907): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_view.sol new file mode 100644 index 000000000..f8e9bc3ef --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/inline_assembly_instructions_disallowed_view.sol @@ -0,0 +1,28 @@ +contract C { + function f() public view { + assembly { + sstore(0, 1) + pop(extcall(0, 1, 2, 3)) + pop(extdelegatecall(0, 1, 2)) + log0(0, 1) + log1(0, 1, 2) + log2(0, 1, 2, 3) + log3(0, 1, 2, 3, 4) + log4(0, 1, 2, 3, 4, 5) + + // This one is disallowed too but the error suppresses other errors. + //pop(msize()) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// TypeError 8961: (75-87): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (104-123): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (141-165): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (179-189): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (202-215): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (228-244): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (257-276): Function cannot be declared as view because this expression (potentially) modifies the state. +// TypeError 8961: (289-311): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/gas_value_without_call.sol b/test/libsolidity/syntaxTests/viewPureChecker/gas_value_without_call.sol index 41120bf08..f0bfba70c 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/gas_value_without_call.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/gas_value_without_call.sol @@ -11,4 +11,6 @@ contract C { this.f{gas: 42}; } } +// ==== +// bytecodeFormat: legacy // ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol b/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol index 65030cb30..77956ffac 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/gas_with_call_nonpayable.sol @@ -7,6 +7,8 @@ contract C { this.h{gas: 42}(); } } +// ==== +// bytecodeFormat: legacy // ---- // TypeError 8961: (90-109): Function cannot be declared as view because this expression (potentially) modifies the state. // TypeError 8961: (180-197): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol index 886d6de0c..680a8f85f 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed.sol @@ -84,6 +84,7 @@ contract C { } // ==== // EVMVersion: >=paris +// bytecodeFormat: legacy // ---- // Warning 1699: (1754-1766): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. // Warning 5740: (89-1716): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol index 16c75d6f7..5268f7a98 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_pure.sol @@ -83,6 +83,7 @@ contract C { } // ==== // EVMVersion: >=london +// bytecodeFormat: legacy // ---- // Warning 5740: (94-1755): Unreachable code. // Warning 5740: (1768-1780): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol index 0bb92c1fd..e2fa70102 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view.sol @@ -84,6 +84,7 @@ contract C { } // ==== // EVMVersion: >=paris +// bytecodeFormat: legacy // ---- // Warning 5740: (94-1733): Unreachable code. // Warning 5740: (1746-1758): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed.sol index 992a51ad2..ff557e686 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed.sol @@ -15,6 +15,8 @@ contract C { } } } +// ==== +// bytecodeFormat: legacy // ---- // SyntaxError 6553: (47-362): The msize instruction cannot be used when the Yul optimizer is activated because it can change its semantics. Either disable the Yul optimizer or do not use the instruction. // DeclarationError 4619: (70-78): Function "datasize" not found. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol index 665a17eeb..91be09f58 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol @@ -34,6 +34,8 @@ contract C { } } } +// ==== +// bytecodeFormat: legacy // ---- // Warning 1699: (498-510): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. // Warning 5740: (526-853): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol index f0320d8b0..ded86c88a 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_byzantium.sol @@ -7,5 +7,6 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // TypeError 2527: (79-107): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_constantinople.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_constantinople.sol index 30210efc3..47826724e 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_constantinople.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_constantinople.sol @@ -8,6 +8,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // TypeError 2527: (79-93): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". // TypeError 8961: (111-130): Function cannot be declared as pure because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol index b2f241ff0..e2bf4c5d1 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_view.sol @@ -22,6 +22,7 @@ contract C { } // ==== // EVMVersion: >=london +// bytecodeFormat: legacy // ---- // Warning 1699: (308-320): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. // Warning 5740: (336-468): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/staticcall_gas_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/staticcall_gas_view.sol index f49327a92..832f60f97 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/staticcall_gas_view.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/staticcall_gas_view.sol @@ -8,4 +8,5 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- From 52a2557a8ccdade9022ba6566652ab0fc65b75ba Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 30 Jan 2025 15:16:54 +0100 Subject: [PATCH 0661/1340] eof: Make "jump too far" error testable. Add tests. --- libevmasm/Assembly.cpp | 9 ++++++++- .../sizeLimits/eof/bytecode_too_large.sol | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/sizeLimits/eof/bytecode_too_large.sol diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index ac9f14b15..91beb9a7f 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1660,7 +1660,14 @@ LinkerObject const& Assembly::assembleEOF() const ptrdiff_t const relativeJumpOffset = static_cast(tagPos) - (static_cast(refPos) + 2); // This cannot happen in practice because we'll run into section size limit first. - solAssert(-0x8000 <= relativeJumpOffset && relativeJumpOffset <= 0x7FFF, "Relative jump too far"); + if (!(-0x8000 <= relativeJumpOffset && relativeJumpOffset <= 0x7FFF)) + // TODO: Include source location. Note that origin locations we have in debug data are + // not usable for error reporting when compiling pure Yul because they point at the optimized source. + throw Error( + 2703_error, + Error::Type::CodeGenerationError, + "Relative jump too far" + ); solAssert(relativeJumpOffset < -2 || 0 <= relativeJumpOffset, "Relative jump offset into immediate argument."); setBigEndianUint16(ret.bytecode, refPos, static_cast(static_cast(relativeJumpOffset))); } diff --git a/test/libsolidity/syntaxTests/sizeLimits/eof/bytecode_too_large.sol b/test/libsolidity/syntaxTests/sizeLimits/eof/bytecode_too_large.sol new file mode 100644 index 000000000..e7c369577 --- /dev/null +++ b/test/libsolidity/syntaxTests/sizeLimits/eof/bytecode_too_large.sol @@ -0,0 +1,14 @@ +// TODO: Change to proper error when all optimizations implemented for EOF +pragma abicoder v2; + +contract test { + function f() public pure returns (string memory ret) { + // 27000 bytes long data + ret = "........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................"; + } +} +// ==== +// EVMVersion: >=cancun +// bytecodeFormat: >=EOFv1 +// ---- +// CodeGenerationError 2703: (96-27229): Relative jump too far From aa3fe8556d8b11dcbf7f9020e61e6fc3224a6b53 Mon Sep 17 00:00:00 2001 From: r0qs Date: Thu, 30 Jan 2025 17:03:50 +0100 Subject: [PATCH 0662/1340] Fix wrong comment about blobhash behavior --- .../inlineAssembly/blobhash_index_exceeding_blob_count.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsolidity/semanticTests/inlineAssembly/blobhash_index_exceeding_blob_count.sol b/test/libsolidity/semanticTests/inlineAssembly/blobhash_index_exceeding_blob_count.sol index 7063978c5..50a2ea708 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/blobhash_index_exceeding_blob_count.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/blobhash_index_exceeding_blob_count.sol @@ -1,7 +1,7 @@ contract C { function f() public view returns (bytes32 ret) { assembly { - // EIP-4844 specifies that if `index < len(tx.blob_versioned_hashes)`, `blobhash(index)` should return 0. + // EIP-4844 specifies that if `index >= len(tx.blob_versioned_hashes)`, `blobhash(index)` should return 0. // Thus, as we injected only two blob hashes in the transaction context in EVMHost, // the return value of the function below MUST be zero. ret := blobhash(2) From 89fb22463b30fe15dd2014c824a822b53df96f6f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 30 Jan 2025 16:07:32 +0100 Subject: [PATCH 0663/1340] Bump resource class for t_ems_ext_edr from small to medium --- .circleci/config.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0c4e65954..0f75e76cd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1397,11 +1397,12 @@ jobs: - matrix_notify_failure_unless_pr t_ems_ext_edr: - <<: *base_node_small + # Runs out of memory on the small instance + <<: *base_ubuntu2404 docker: - image: cimg/rust:1.79.0-node environment: - <<: *base_node_small_env + <<: *base_ubuntu2404_env EDR_TESTS_SOLC_PATH: /tmp/workspace/soljson.js steps: - checkout From 7add03e281df8d960eabaf5420c6b8220e1ab7a5 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Mon, 27 Jan 2025 17:40:18 +0100 Subject: [PATCH 0664/1340] SMTChecker: Put all information regarding transaction data in one place --- libsolidity/formal/Predicate.cpp | 17 +-------- libsolidity/formal/SymbolicState.h | 22 +----------- libsolidity/formal/SymbolicTypes.cpp | 35 +++++++++++++++++++ libsolidity/formal/SymbolicTypes.h | 2 ++ .../special/tx_data_immutable.sol | 12 ++++--- 5 files changed, 47 insertions(+), 41 deletions(-) diff --git a/libsolidity/formal/Predicate.cpp b/libsolidity/formal/Predicate.cpp index 5cac3a6a9..fe7c03fe1 100644 --- a/libsolidity/formal/Predicate.cpp +++ b/libsolidity/formal/Predicate.cpp @@ -489,22 +489,7 @@ std::map Predicate::expressionSubstitution(smtutil::Ex std::map> Predicate::readTxVars(smtutil::Expression const& _tx) const { - std::map const txVars{ - {"block.basefee", TypeProvider::uint256()}, - {"block.chainid", TypeProvider::uint256()}, - {"block.coinbase", TypeProvider::address()}, - {"block.prevrandao", TypeProvider::uint256()}, - {"block.gaslimit", TypeProvider::uint256()}, - {"block.number", TypeProvider::uint256()}, - {"block.timestamp", TypeProvider::uint256()}, - {"blockhash", TypeProvider::array(DataLocation::Memory, TypeProvider::uint256())}, - {"msg.data", TypeProvider::array(DataLocation::CallData)}, - {"msg.sender", TypeProvider::address()}, - {"msg.sig", TypeProvider::fixedBytes(4)}, - {"msg.value", TypeProvider::uint256()}, - {"tx.gasprice", TypeProvider::uint256()}, - {"tx.origin", TypeProvider::address()} - }; + std::map const txVars = transactionMemberTypes(); std::map> vars; for (auto&& [i, v]: txVars | ranges::views::enumerate) vars.emplace(v.first, expressionToString(_tx.arguments.at(i), v.second)); diff --git a/libsolidity/formal/SymbolicState.h b/libsolidity/formal/SymbolicState.h index ac018df1a..20bfb3f00 100644 --- a/libsolidity/formal/SymbolicState.h +++ b/libsolidity/formal/SymbolicState.h @@ -236,27 +236,7 @@ class SymbolicState /// and the element is a tuple containing the state variables of that contract. std::unique_ptr m_state; - BlockchainVariable m_tx{ - "tx", - { - {"block.basefee", smtutil::SortProvider::uintSort}, - {"block.chainid", smtutil::SortProvider::uintSort}, - {"block.coinbase", smt::smtSort(*TypeProvider::address())}, - {"block.prevrandao", smtutil::SortProvider::uintSort}, - {"block.gaslimit", smtutil::SortProvider::uintSort}, - {"block.number", smtutil::SortProvider::uintSort}, - {"block.timestamp", smtutil::SortProvider::uintSort}, - {"blockhash", std::make_shared(smtutil::SortProvider::uintSort, smtutil::SortProvider::uintSort)}, - // TODO gasleft - {"msg.data", smt::smtSort(*TypeProvider::bytesMemory())}, - {"msg.sender", smt::smtSort(*TypeProvider::address())}, - {"msg.sig", smtutil::SortProvider::uintSort}, - {"msg.value", smtutil::SortProvider::uintSort}, - {"tx.gasprice", smtutil::SortProvider::uintSort}, - {"tx.origin", smt::smtSort(*TypeProvider::address())} - }, - m_context - }; + BlockchainVariable m_tx{"tx", transactionMemberSorts(), m_context}; BlockchainVariable m_crypto{ "crypto", diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 72739bccf..0428ffaa2 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -667,4 +667,39 @@ smtutil::Expression assignMember(smtutil::Expression const _tuple, std::map transactionMemberTypes() +{ + // TODO: gasleft + return { + {"block.basefee", TypeProvider::uint256()}, + {"block.chainid", TypeProvider::uint256()}, + {"block.coinbase", TypeProvider::address()}, + {"block.prevrandao", TypeProvider::uint256()}, + {"block.gaslimit", TypeProvider::uint256()}, + {"block.number", TypeProvider::uint256()}, + {"block.timestamp", TypeProvider::uint256()}, + {"blockhash", TypeProvider::array(DataLocation::Memory, TypeProvider::uint256())}, + {"msg.data", TypeProvider::bytesCalldata()}, + {"msg.sender", TypeProvider::address()}, + {"msg.sig", TypeProvider::fixedBytes(4)}, + {"msg.value", TypeProvider::uint256()}, + {"tx.gasprice", TypeProvider::uint256()}, + {"tx.origin", TypeProvider::address()} + }; +} + +std::map transactionMemberSorts() +{ + // NOTE: `blockhash` needs proper `ArraySort`, `smtSort` wraps array types into array+length pair + auto toSort = [&](auto const& entry) -> SortPointer + { + if (entry.first == "blockhash") + return std::make_shared(SortProvider::uintSort, SortProvider::uintSort); + return smtSort(*entry.second); + }; + auto types = transactionMemberTypes(); + return types + | ranges::views::transform([&](auto const& entry) { return std::make_pair(entry.first, toSort(entry)); }) + | ranges::to>(); +} } diff --git a/libsolidity/formal/SymbolicTypes.h b/libsolidity/formal/SymbolicTypes.h index 747e27b7e..d38dcc045 100644 --- a/libsolidity/formal/SymbolicTypes.h +++ b/libsolidity/formal/SymbolicTypes.h @@ -86,4 +86,6 @@ std::optional symbolicTypeConversion(frontend::Type const* smtutil::Expression member(smtutil::Expression const& _tuple, std::string const& _member); smtutil::Expression assignMember(smtutil::Expression const _tuple, std::map const& _values); +std::map transactionMemberTypes(); +std::map transactionMemberSorts(); } diff --git a/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol b/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol index c66ce5653..21a924b1f 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol @@ -1,5 +1,6 @@ contract C { bytes32 bhash; + uint bfee; address coin; uint dif; uint prevrandao; @@ -15,6 +16,7 @@ contract C { function f() public payable { bhash = blockhash(12); + bfee = block.basefee; coin = block.coinbase; dif = block.difficulty; prevrandao = block.prevrandao; @@ -31,6 +33,7 @@ contract C { fi(); assert(bhash == blockhash(12)); + assert(bfee == block.basefee); assert(coin == block.coinbase); assert(dif == block.difficulty); assert(prevrandao == block.prevrandao); @@ -47,6 +50,7 @@ contract C { function fi() internal view { assert(bhash == blockhash(12)); + assert(bfee == block.basefee); assert(coin == block.coinbase); assert(dif == block.difficulty); assert(prevrandao == block.prevrandao); @@ -64,7 +68,7 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 8417: (293-309): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 8417: (645-661): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 8417: (1127-1143): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Info 1391: CHC: 26 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 8417: (329-345): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (714-730): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (1229-1245): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Info 1391: CHC: 28 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From c02be83df79ace9e037b268b53c8cded41e5876a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 31 Jan 2025 08:17:25 +0100 Subject: [PATCH 0665/1340] Remove cxx20 header containing reference implementation of erase_if --- libsolutil/CMakeLists.txt | 1 - libsolutil/cxx20.h | 64 ------------------- .../backends/evm/ControlFlowGraphBuilder.cpp | 5 +- .../evm/OptimizedEVMCodeTransform.cpp | 1 - .../evm/SSAControlFlowGraphBuilder.cpp | 3 +- libyul/backends/evm/StackLayoutGenerator.cpp | 4 +- libyul/optimiser/DataFlowAnalyzer.cpp | 21 +++--- 7 files changed, 14 insertions(+), 85 deletions(-) delete mode 100644 libsolutil/cxx20.h diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index aac943517..1ec12051a 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -7,7 +7,6 @@ set(sources CommonData.h CommonIO.cpp CommonIO.h - cxx20.h DisjointSet.cpp DisjointSet.h DominatorFinder.h diff --git a/libsolutil/cxx20.h b/libsolutil/cxx20.h deleted file mode 100644 index a21a73e68..000000000 --- a/libsolutil/cxx20.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - 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 -#pragma once - -#include - -// Contains polyfills of STL functions and algorithms that will become available in C++20. -namespace solidity::cxx20 -{ - -// Taken from https://en.cppreference.com/w/cpp/container/map/erase_if. -template -typename std::map::size_type erase_if(std::map& _c, Pred _pred) -{ - auto old_size = _c.size(); - for (auto i = _c.begin(), last = _c.end(); i != last;) - if (_pred(*i)) - i = _c.erase(i); - else - ++i; - return old_size - _c.size(); -} - -// Taken from https://en.cppreference.com/w/cpp/container/unordered_map/erase_if. -template -typename std::unordered_map::size_type -erase_if(std::unordered_map& _c, Pred _pred) -{ - auto old_size = _c.size(); - for (auto i = _c.begin(), last = _c.end(); i != last;) - if (_pred(*i)) - i = _c.erase(i); - else - ++i; - return old_size - _c.size(); -} - -// Taken from https://en.cppreference.com/w/cpp/container/vector/erase2 -template -constexpr typename std::vector::size_type -erase_if(std::vector& c, Pred pred) -{ - auto it = std::remove_if(c.begin(), c.end(), pred); - auto r = std::distance(it, c.end()); - c.erase(it, c.end()); - return static_cast::size_type>(r); -} - -} diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 3986d54a0..d9456e4c3 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include @@ -85,7 +84,7 @@ void cleanUnreachable(CFG& _cfg) // Remove all entries from unreachable nodes from the graph. for (CFG::BasicBlock* node: reachabilityCheck.visited) - cxx20::erase_if(node->entries, [&](CFG::BasicBlock* entry) -> bool { + std::erase_if(node->entries, [&](CFG::BasicBlock* entry) -> bool { return !reachabilityCheck.visited.count(entry); }); @@ -95,7 +94,7 @@ void cleanUnreachable(CFG& _cfg) }), _cfg.functions.end()); // Remove functionInfos which are never referenced. - cxx20::erase_if(_cfg.functionInfo, [&](auto const& entry) -> bool { + std::erase_if(_cfg.functionInfo, [&](auto const& entry) -> bool { return !reachabilityCheck.visited.count(entry.second.entry); }); } diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 139df8af6..bd5c55a3c 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 4597c56a5..bf8cfd92a 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -197,7 +196,7 @@ void SSAControlFlowGraphBuilder::cleanUnreachable() it = block.entries.erase(it); for (auto phi: block.phis) if (auto* phiInfo = std::get_if(&m_graph.valueInfo(phi))) - cxx20::erase_if(phiInfo->arguments, [&](SSACFG::ValueId _arg) { + std::erase_if(phiInfo->arguments, [&](SSACFG::ValueId _arg) { if (isUnreachableValue(_arg)) { maybeTrivialPhi.insert(phi); diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 3d1d5f7b0..ecaa4198b 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -26,8 +26,6 @@ #include #include -#include -#include #include #include @@ -577,7 +575,7 @@ Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _sta for (auto slot: stack2Tail) if (!util::contains(candidate, slot)) candidate.emplace_back(slot); - cxx20::erase_if(candidate, [](StackSlot const& slot) { + std::erase_if(candidate, [](StackSlot const& slot) { return std::holds_alternative(slot) || std::holds_alternative(slot); }); diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index ac08fb0be..b11282bb1 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -32,7 +32,6 @@ #include #include -#include #include @@ -68,7 +67,7 @@ void DataFlowAnalyzer::operator()(ExpressionStatement& _statement) if (auto vars = isSimpleStore(StoreLoadLocation::Storage, _statement)) { ASTModifier::operator()(_statement); - cxx20::erase_if(m_state.environment.storage, mapTuple([&](auto&& key, auto&& value) { + std::erase_if(m_state.environment.storage, mapTuple([&](auto&& key, auto&& value) { return !m_knowledgeBase.knownToBeDifferent(vars->first, key) && vars->second != value; @@ -79,7 +78,7 @@ void DataFlowAnalyzer::operator()(ExpressionStatement& _statement) else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, _statement)) { ASTModifier::operator()(_statement); - cxx20::erase_if(m_state.environment.memory, mapTuple([&](auto&& key, auto&& /* value */) { + std::erase_if(m_state.environment.memory, mapTuple([&](auto&& key, auto&& /* value */) { return !m_knowledgeBase.knownToBeDifferentByAtLeast32(vars->first, key); })); // TODO erase keccak knowledge, but in a more clever way @@ -272,14 +271,14 @@ void DataFlowAnalyzer::handleAssignment(std::set const& _variables, Exp // assignment to slot denoted by "name" m_state.environment.storage.erase(name); // assignment to slot contents denoted by "name" - cxx20::erase_if(m_state.environment.storage, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; })); + std::erase_if(m_state.environment.storage, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; })); // assignment to slot denoted by "name" m_state.environment.memory.erase(name); // assignment to slot contents denoted by "name" - cxx20::erase_if(m_state.environment.keccak, [&name](auto&& _item) { + std::erase_if(m_state.environment.keccak, [&name](auto&& _item) { return _item.first.first == name || _item.first.second == name || _item.second == name; }); - cxx20::erase_if(m_state.environment.memory, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; })); + std::erase_if(m_state.environment.memory, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; })); } } @@ -337,9 +336,9 @@ void DataFlowAnalyzer::clearValues(std::set _variables) auto eraseCondition = mapTuple([&_variables](auto&& key, auto&& value) { return _variables.count(key) || _variables.count(value); }); - cxx20::erase_if(m_state.environment.storage, eraseCondition); - cxx20::erase_if(m_state.environment.memory, eraseCondition); - cxx20::erase_if(m_state.environment.keccak, [&_variables](auto&& _item) { + std::erase_if(m_state.environment.storage, eraseCondition); + std::erase_if(m_state.environment.memory, eraseCondition); + std::erase_if(m_state.environment.keccak, [&_variables](auto&& _item) { return _variables.count(_item.first.first) || _variables.count(_item.first.second) || @@ -464,7 +463,7 @@ void DataFlowAnalyzer::joinKnowledge(Environment const& _olderEnvironment) return; joinKnowledgeHelper(m_state.environment.storage, _olderEnvironment.storage); joinKnowledgeHelper(m_state.environment.memory, _olderEnvironment.memory); - cxx20::erase_if(m_state.environment.keccak, mapTuple([&_olderEnvironment](auto&& key, auto&& currentValue) { + std::erase_if(m_state.environment.keccak, mapTuple([&_olderEnvironment](auto&& key, auto&& currentValue) { YulName const* oldValue = valueOrNullptr(_olderEnvironment.keccak, key); return !oldValue || *oldValue != currentValue; })); @@ -479,7 +478,7 @@ void DataFlowAnalyzer::joinKnowledgeHelper( // This also works for memory because _older is an "older version" // of m_state.environment.memory and thus any overlapping write would have cleared the keys // that are not known to be different inside m_state.environment.memory already. - cxx20::erase_if(_this, mapTuple([&_older](auto&& key, auto&& currentValue){ + std::erase_if(_this, mapTuple([&_older](auto&& key, auto&& currentValue){ YulName const* oldValue = valueOrNullptr(_older, key); return !oldValue || *oldValue != currentValue; })); From 8fe3961654c5031c418ec2df4fb0ef45373c9386 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Mon, 27 Jan 2025 23:18:40 +0100 Subject: [PATCH 0666/1340] SMTChecker: Add support for block.blobbasefee and blobhash() We overapproximate the behaviour here in the same way as for `block.basefee` and `blockhash`. For the first we only add the basic domain constraints and the second is modelled as an uninterpreted function. We also model the fact that the number of blobs in transaction is limited by returning 0 from blobhash() if the argument is greater or equal to the limit. The current limit is 6, but it will soon be increased to 9 in pectra update. Since we overapproximate the behaviour anyway, we can use the pectra limit immediately. --- Changelog.md | 1 + docs/smtchecker.rst | 6 +- libsolidity/formal/BMC.cpp | 1 + libsolidity/formal/CHC.cpp | 1 + libsolidity/formal/SMTEncoder.cpp | 15 ++++ libsolidity/formal/SMTEncoder.h | 1 + libsolidity/formal/SymbolicState.cpp | 6 ++ libsolidity/formal/SymbolicState.h | 3 + libsolidity/formal/SymbolicTypes.cpp | 6 +- scripts/error_codes.py | 1 + .../model_checker_print_query_all/err | 10 +-- .../model_checker_print_query_bmc/err | 4 +- .../model_checker_print_query_chc/err | 6 +- .../err | 2 +- .../err | 2 +- .../err | 7 +- .../model_checker_show_unproved_true_bmc/err | 7 +- .../output.json | 86 +++++++++---------- .../output.json | 14 +-- .../output.json | 20 ++--- .../output.json | 10 +-- .../output.json | 10 +-- .../output.json | 10 +-- .../output.json | 25 ++---- .../output.json | 25 ++---- .../output.json | 14 +-- .../compound_bitwise_or_uint_3.sol | 2 +- .../external_calls/external_safe.sol | 5 +- .../operators/compound_bitwise_or_uint_3.sol | 2 +- ...rator_matches_equivalent_function_call.sol | 4 +- .../special/blobhash_beyond_limit.sol | 11 +++ .../special/tx_data_immutable.sol | 24 ++++-- .../special/tx_data_immutable_fail.sol | 86 +++++++++++-------- .../types/fixed_bytes_access_3.sol | 4 +- 34 files changed, 229 insertions(+), 202 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/special/blobhash_beyond_limit.sol diff --git a/Changelog.md b/Changelog.md index 6caef22b1..cceec2a73 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: * Error Reporting: Errors reported during code generation now point at the location of the contract when more fine-grained location is not available. + * SMTChecker: Support `block.blobbasefee` and `blobhash`. * SMTChecker: Z3 is now a runtime dependency, not a build dependency (except for emscripten build). * Yul Parser: Make name clash with a builtin a non-fatal error. diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index 7db996faf..5de941bf2 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -931,9 +931,9 @@ the arguments. +-----------------------------------+--------------------------------------+ |``addmod``, ``mulmod`` |Supported precisely. | +-----------------------------------+--------------------------------------+ -|``gasleft``, ``blockhash``, |Abstracted with UF. | -|``keccak256``, ``ecrecover`` | | -|``ripemd160`` | | +|``gasleft``, ``blobhash``, |Abstracted with UF. | +|``blockhash``, ``keccak256``, | | +|``ecrecover``, ``ripemd160`` | | +-----------------------------------+--------------------------------------+ |pure functions without |Abstracted with UF | |implementation (external or | | diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index d7bad10e7..86c7eb7a8 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -664,6 +664,7 @@ void BMC::endVisit(FunctionCall const& _funCall) case FunctionType::Kind::ECRecover: case FunctionType::Kind::SHA256: case FunctionType::Kind::RIPEMD160: + case FunctionType::Kind::BlobHash: case FunctionType::Kind::BlockHash: case FunctionType::Kind::AddMod: case FunctionType::Kind::MulMod: diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 9f23aff6f..bd0b3f402 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -641,6 +641,7 @@ void CHC::endVisit(FunctionCall const& _funCall) case FunctionType::Kind::ECRecover: case FunctionType::Kind::SHA256: case FunctionType::Kind::RIPEMD160: + case FunctionType::Kind::BlobHash: case FunctionType::Kind::BlockHash: case FunctionType::Kind::AddMod: case FunctionType::Kind::MulMod: diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index d7b231563..2fecb734a 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -679,6 +679,9 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall) case FunctionType::Kind::BlockHash: defineExpr(_funCall, state().blockhash(expr(*_funCall.arguments().at(0)))); break; + case FunctionType::Kind::BlobHash: + visitBlobHash(_funCall); + break; case FunctionType::Kind::AddMod: case FunctionType::Kind::MulMod: visitAddMulMod(_funCall); @@ -893,6 +896,18 @@ void SMTEncoder::visitGasLeft(FunctionCall const& _funCall) m_context.addAssertion(symbolicVar->currentValue() <= symbolicVar->valueAtIndex(index - 1)); } +void SMTEncoder::visitBlobHash(FunctionCall const& _funCall) +{ + constexpr unsigned BLOB_TRANSACTION_LIMIT = 9; // Since pectra + auto indexExpr = expr(*_funCall.arguments().at(0)); + auto valueExpr = smtutil::Expression::ite( + indexExpr >= BLOB_TRANSACTION_LIMIT, + smtutil::Expression(u256(0)), + state().blobhash(indexExpr) + ); + defineExpr(_funCall, std::move(valueExpr)); +} + void SMTEncoder::visitAddMulMod(FunctionCall const& _funCall) { auto const& funType = dynamic_cast(*_funCall.expression().annotation().type); diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index f01f6802c..d79ae8f82 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -229,6 +229,7 @@ class SMTEncoder: public ASTConstVisitor void visitBytesConcat(FunctionCall const& _funCall); void visitCryptoFunction(FunctionCall const& _funCall); void visitGasLeft(FunctionCall const& _funCall); + void visitBlobHash(FunctionCall const& _funCall); virtual void visitAddMulMod(FunctionCall const& _funCall); void visitWrapUnwrap(FunctionCall const& _funCall); void visitObjectCreation(FunctionCall const& _funCall); diff --git a/libsolidity/formal/SymbolicState.cpp b/libsolidity/formal/SymbolicState.cpp index bf835b801..492e0055b 100644 --- a/libsolidity/formal/SymbolicState.cpp +++ b/libsolidity/formal/SymbolicState.cpp @@ -96,6 +96,11 @@ smtutil::Expression SymbolicState::balance(smtutil::Expression _address) const return smtutil::Expression::select(balances(), std::move(_address)); } +smtutil::Expression SymbolicState::blobhash(smtutil::Expression _blobIndex) const +{ + return smtutil::Expression::select(m_tx.member("blobhash"), std::move(_blobIndex)); +} + smtutil::Expression SymbolicState::blockhash(smtutil::Expression _blockNumber) const { return smtutil::Expression::select(m_tx.member("blockhash"), std::move(_blockNumber)); @@ -222,6 +227,7 @@ smtutil::Expression SymbolicState::txTypeConstraints() const return evmParisConstraints() && smt::symbolicUnknownConstraints(m_tx.member("block.basefee"), TypeProvider::uint256()) && + smt::symbolicUnknownConstraints(m_tx.member("block.blobbasefee"), TypeProvider::uint256()) && smt::symbolicUnknownConstraints(m_tx.member("block.chainid"), TypeProvider::uint256()) && smt::symbolicUnknownConstraints(m_tx.member("block.coinbase"), TypeProvider::address()) && smt::symbolicUnknownConstraints(m_tx.member("block.prevrandao"), TypeProvider::uint256()) && diff --git a/libsolidity/formal/SymbolicState.h b/libsolidity/formal/SymbolicState.h index 20bfb3f00..ca40e695d 100644 --- a/libsolidity/formal/SymbolicState.h +++ b/libsolidity/formal/SymbolicState.h @@ -65,8 +65,10 @@ class BlockchainVariable * - array of address => bool representing whether an address is used by a contract * - storage of contracts * - block and transaction properties, represented as a tuple of: + * - blobhash * - blockhash * - block basefee + * - block blobbasefee * - block chainid * - block coinbase * - block gaslimit @@ -148,6 +150,7 @@ class SymbolicState smtutil::Expression txFunctionConstraints(FunctionDefinition const& _function) const; smtutil::Expression txTypeConstraints() const; smtutil::Expression txNonPayableConstraint() const; + smtutil::Expression blobhash(smtutil::Expression _blobIndex) const; smtutil::Expression blockhash(smtutil::Expression _blockNumber) const; smtutil::Expression evmParisConstraints() const; //@} diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 0428ffaa2..738a48f70 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -672,12 +672,14 @@ std::map transactionMemberTypes() // TODO: gasleft return { {"block.basefee", TypeProvider::uint256()}, + {"block.blobbasefee", TypeProvider::uint256()}, {"block.chainid", TypeProvider::uint256()}, {"block.coinbase", TypeProvider::address()}, {"block.prevrandao", TypeProvider::uint256()}, {"block.gaslimit", TypeProvider::uint256()}, {"block.number", TypeProvider::uint256()}, {"block.timestamp", TypeProvider::uint256()}, + {"blobhash", TypeProvider::array(DataLocation::Memory, TypeProvider::uint256())}, {"blockhash", TypeProvider::array(DataLocation::Memory, TypeProvider::uint256())}, {"msg.data", TypeProvider::bytesCalldata()}, {"msg.sender", TypeProvider::address()}, @@ -690,10 +692,10 @@ std::map transactionMemberTypes() std::map transactionMemberSorts() { - // NOTE: `blockhash` needs proper `ArraySort`, `smtSort` wraps array types into array+length pair + // NOTE: `blockhash` and `blobhash` need proper `ArraySort`, `smtSort()` wraps array types into array+length pair auto toSort = [&](auto const& entry) -> SortPointer { - if (entry.first == "blockhash") + if (entry.first == "blockhash" || entry.first == "blobhash") return std::make_shared(SortProvider::uintSort, SortProvider::uintSort); return smtSort(*entry.second); }; diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 813d08330..50021d986 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -205,6 +205,7 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "7053", # Unimplemented feature error (parsing stage), currently has no tests "2339", # SMTChecker, covered by CL tests "6240", # SMTChecker, covered by CL tests + "2788", # SMTChecker: BMC: verification condition(s) could not be proved "1733", # AsmAnalysis: expecting bool expression (everything is implicitly bool without types in Yul) "9547", # AsmAnalysis: assigning incompatible types in Yul (whitelisted as there are currently no types) } diff --git a/test/cmdlineTests/model_checker_print_query_all/err b/test/cmdlineTests/model_checker_print_query_all/err index 76dff6664..92a3b7f7b 100644 --- a/test/cmdlineTests/model_checker_print_query_all/err +++ b/test/cmdlineTests/model_checker_print_query_all/err @@ -8,7 +8,7 @@ Info: CHC: Requested query: (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -45,7 +45,7 @@ Info: CHC: Requested query: (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -73,7 +73,7 @@ Info: CHC: Requested query: (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -96,7 +96,7 @@ Info: BMC: Requested query: (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -112,7 +112,7 @@ Info: BMC: Requested query: (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) diff --git a/test/cmdlineTests/model_checker_print_query_bmc/err b/test/cmdlineTests/model_checker_print_query_bmc/err index 6fb8440b7..efbc2a3ae 100644 --- a/test/cmdlineTests/model_checker_print_query_bmc/err +++ b/test/cmdlineTests/model_checker_print_query_bmc/err @@ -4,7 +4,7 @@ Info: BMC: Requested query: (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -19,7 +19,7 @@ Info: BMC: Requested query: (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) diff --git a/test/cmdlineTests/model_checker_print_query_chc/err b/test/cmdlineTests/model_checker_print_query_chc/err index 28368f546..9c18265be 100644 --- a/test/cmdlineTests/model_checker_print_query_chc/err +++ b/test/cmdlineTests/model_checker_print_query_chc/err @@ -8,7 +8,7 @@ Info: CHC: Requested query: (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -45,7 +45,7 @@ Info: CHC: Requested query: (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -73,7 +73,7 @@ Info: CHC: Requested query: (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) diff --git a/test/cmdlineTests/model_checker_show_unproved_default_all_engines/err b/test/cmdlineTests/model_checker_show_unproved_default_all_engines/err index 45c38ef35..486cd2c65 100644 --- a/test/cmdlineTests/model_checker_show_unproved_default_all_engines/err +++ b/test/cmdlineTests/model_checker_show_unproved_default_all_engines/err @@ -1,3 +1,3 @@ Warning: CHC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. -Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. +Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/model_checker_show_unproved_default_bmc/err b/test/cmdlineTests/model_checker_show_unproved_default_bmc/err index f8d0af2f4..21041fee1 100644 --- a/test/cmdlineTests/model_checker_show_unproved_default_bmc/err +++ b/test/cmdlineTests/model_checker_show_unproved_default_bmc/err @@ -1 +1 @@ -Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. +Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err b/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err index 83864075d..7a338f614 100644 --- a/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err +++ b/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err @@ -4,9 +4,4 @@ Warning: CHC: Assertion violation might happen here. 10 | assert(s.x > 0); | ^^^^^^^^^^^^^^^ -Warning: BMC: Assertion violation might happen here. - --> model_checker_show_unproved_true_all_engines/input.sol:10:9: - | -10 | assert(s.x > 0); - | ^^^^^^^^^^^^^^^ -Note: +Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/model_checker_show_unproved_true_bmc/err b/test/cmdlineTests/model_checker_show_unproved_true_bmc/err index 84ada7873..21041fee1 100644 --- a/test/cmdlineTests/model_checker_show_unproved_true_bmc/err +++ b/test/cmdlineTests/model_checker_show_unproved_true_bmc/err @@ -1,6 +1 @@ -Warning: BMC: Assertion violation might happen here. - --> model_checker_show_unproved_true_bmc/input.sol:10:9: - | -10 | assert(s.x > 0); - | ^^^^^^^^^^^^^^^ -Note: +Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/standard_model_checker_print_query_all/output.json b/test/cmdlineTests/standard_model_checker_print_query_all/output.json index a800fb34d..1108d7907 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_all/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_all/output.json @@ -1,36 +1,7 @@ { "auxiliaryInputRequested": { "smtlib2queries": { - "0x54683263097e1c4f5e0e75b68e4ebe3e4f7042f899198181df911c8196a1725b": "(set-option :produce-models true) -(set-option :timeout 1000) -(set-logic ALL) -(declare-fun |x_5_3| () Int) -(declare-fun |error_0| () Int) -(declare-fun |this_0| () Int) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-fun |tx_0| () |tx_type|) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-fun |crypto_0| () |crypto_type|) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-fun |abi_0| () |abi_type|) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |state_0| () |state_type|) -(declare-fun |x_5_4| () Int) -(declare-fun |x_5_0| () Int) -(declare-fun |expr_6_0| () Int) -(declare-fun |x_5_1| () Int) -(declare-fun |expr_9_0| () Int) -(declare-fun |expr_10_0| () Int) -(declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) -(declare-const |EVALEXPR_0| Int) -(assert (= |EVALEXPR_0| x_5_1)) -(check-sat) -(get-value (|EVALEXPR_0| )) -", - "0x9cfcd53712a0be144c8e7983b3635498ead1af2624885fb89762eae8c43233e5": "(set-option :timeout 1000) + "0x89dce9b2e59f1b2d3445ec646e15e2609ff358edb66afa7227538979017e0f7b": "(set-option :timeout 1000) (set-logic HORN) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) @@ -39,7 +10,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -76,7 +47,7 @@ (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -104,7 +75,7 @@ (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -113,6 +84,35 @@ (forall ((UNUSED Bool)) (=> error_target_3 false))) (check-sat) +", + "0xca8e4027f5350278d291f782ff3ec7a7f618e8a729beb4173e7dad3f008af497": "(set-option :produce-models true) +(set-option :timeout 1000) +(set-logic ALL) +(declare-fun |x_5_3| () Int) +(declare-fun |error_0| () Int) +(declare-fun |this_0| () Int) +(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-fun |tx_0| () |tx_type|) +(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) +(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) +(declare-fun |crypto_0| () |crypto_type|) +(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) +(declare-fun |abi_0| () |abi_type|) +(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) +(declare-fun |state_0| () |state_type|) +(declare-fun |x_5_4| () Int) +(declare-fun |x_5_0| () Int) +(declare-fun |expr_6_0| () Int) +(declare-fun |x_5_1| () Int) +(declare-fun |expr_9_0| () Int) +(declare-fun |expr_10_0| () Int) +(declare-fun |expr_11_1| () Bool) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(declare-const |EVALEXPR_0| Int) +(assert (= |EVALEXPR_0| x_5_1)) +(check-sat) +(get-value (|EVALEXPR_0| )) " } }, @@ -130,7 +130,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -167,7 +167,7 @@ (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -195,7 +195,7 @@ (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -217,7 +217,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -254,7 +254,7 @@ (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -282,7 +282,7 @@ (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -326,7 +326,7 @@ (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -342,7 +342,7 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) @@ -358,7 +358,7 @@ (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -374,7 +374,7 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) diff --git a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json index cee9d4b9b..a0be6110b 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json @@ -1,12 +1,12 @@ { "auxiliaryInputRequested": { "smtlib2queries": { - "0x2bd3d35071b94d7536d10aad691cee810d94841cca10218c3be21255e258aeb7": "(set-option :produce-models true) + "0x41ee12cade46d5e1c28896216d2b220d2d28b47c925b0191941303216c8635dd": "(set-option :produce-models true) (set-logic ALL) (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -21,7 +21,7 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) @@ -39,7 +39,7 @@ (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -54,7 +54,7 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) @@ -68,7 +68,7 @@ (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -83,7 +83,7 @@ (declare-fun |expr_9_0| () Int) (declare-fun |expr_10_0| () Int) (declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) +(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_5_1)) (check-sat) diff --git a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json index 9553a3cfb..be0d9fa9e 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json @@ -1,7 +1,7 @@ { "auxiliaryInputRequested": { "smtlib2queries": { - "0x9cfcd53712a0be144c8e7983b3635498ead1af2624885fb89762eae8c43233e5": "(set-option :timeout 1000) + "0x89dce9b2e59f1b2d3445ec646e15e2609ff358edb66afa7227538979017e0f7b": "(set-option :timeout 1000) (set-logic HORN) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) @@ -10,7 +10,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -47,7 +47,7 @@ (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -75,7 +75,7 @@ (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -101,7 +101,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -138,7 +138,7 @@ (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -166,7 +166,7 @@ (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) @@ -188,7 +188,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -225,7 +225,7 @@ (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) +(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) (=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) @@ -253,7 +253,7 @@ (=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json index da3b3dcad..de2c2aca0 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_default_all_engines/output.json @@ -12,13 +12,13 @@ }, { "component": "general", - "errorCode": "2788", - "formattedMessage": "Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. + "errorCode": "6002", + "formattedMessage": "Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", - "severity": "warning", - "type": "Warning" + "message": "BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json index da3b3dcad..de2c2aca0 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_false_all_engines/output.json @@ -12,13 +12,13 @@ }, { "component": "general", - "errorCode": "2788", - "formattedMessage": "Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. + "errorCode": "6002", + "formattedMessage": "Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", - "severity": "warning", - "type": "Warning" + "message": "BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json index 67f8df731..0f1ce4e39 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_false_bmc/output.json @@ -2,13 +2,13 @@ "errors": [ { "component": "general", - "errorCode": "2788", - "formattedMessage": "Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. + "errorCode": "6002", + "formattedMessage": "Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", - "severity": "warning", - "type": "Warning" + "message": "BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json index b6153de5e..22c2a4819 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_true_all_engines/output.json @@ -21,28 +21,13 @@ }, { "component": "general", - "errorCode": "7812", - "formattedMessage": "Warning: BMC: Assertion violation might happen here. - --> A:11:7: - | -11 | \t\t\t\t\t\tassert(s.x > 0); - | \t\t\t\t\t\t^^^^^^^^^^^^^^^ -Note: + "errorCode": "6002", + "formattedMessage": "Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "BMC: Assertion violation might happen here.", - "secondarySourceLocations": [ - { - "message": "" - } - ], - "severity": "warning", - "sourceLocation": { - "end": 201, - "file": "A", - "start": 186 - }, - "type": "Warning" + "message": "BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json b/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json index 6c3b57c79..0f1ce4e39 100644 --- a/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_show_unproved_true_bmc/output.json @@ -2,28 +2,13 @@ "errors": [ { "component": "general", - "errorCode": "7812", - "formattedMessage": "Warning: BMC: Assertion violation might happen here. - --> A:11:7: - | -11 | \t\t\t\t\t\tassert(s.x > 0); - | \t\t\t\t\t\t^^^^^^^^^^^^^^^ -Note: + "errorCode": "6002", + "formattedMessage": "Info: BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them. ", - "message": "BMC: Assertion violation might happen here.", - "secondarySourceLocations": [ - { - "message": "" - } - ], - "severity": "warning", - "sourceLocation": { - "end": 201, - "file": "A", - "start": 186 - }, - "type": "Warning" + "message": "BMC: 1 verification condition(s) proved safe! Enable the model checker option \"show proved safe\" to see all of them.", + "severity": "info", + "type": "Info" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json index a3f4cc03d..79037e223 100644 --- a/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json +++ b/test/cmdlineTests/standard_model_checker_solvers_smtlib2/output.json @@ -1,13 +1,13 @@ { "auxiliaryInputRequested": { "smtlib2queries": { - "0x51b9801f3e8e35f2ff5f4538b0636fae81aa84a482cbb486ae4db63bede5ecb5": "(set-option :produce-models true) + "0x1b1a2b4161df2f2869bdcd6ee320ef4c54aded9ae9c0441dd2dd4248f5616d97": "(set-option :produce-models true) (set-logic ALL) (declare-fun |x_3_3| () Int) (declare-fun |error_0| () Int) (declare-fun |this_0| () Int) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |tx_0| () |tx_type|) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) @@ -21,13 +21,13 @@ (declare-fun |expr_7_0| () Int) (declare-fun |expr_8_0| () Int) (declare-fun |expr_9_1| () Bool) -(assert (and (and (and true true) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> (and true true) true) (and (= expr_8_0 0) (and (=> (and true true) (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_0) (and (and (>= x_3_0 0) (<= x_3_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true)))))))) (not expr_9_1))) +(assert (and (and (and true true) (and (= expr_9_1 (> expr_7_0 expr_8_0)) (and (=> (and true true) true) (and (= expr_8_0 0) (and (=> (and true true) (and (>= expr_7_0 0) (<= expr_7_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_7_0 x_3_0) (and (and (>= x_3_0 0) (<= x_3_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true)))))))) (not expr_9_1))) (declare-const |EVALEXPR_0| Int) (assert (= |EVALEXPR_0| x_3_0)) (check-sat) (get-value (|EVALEXPR_0| )) ", - "0xdb239809dcdaa42e35abca69790cb7e11b105f839e37faa8841f0dd9736688d7": "(set-logic HORN) + "0xd2654693bf2b4f42bfe922319928772b52430787451450fda29da1ebea716f19": "(set-logic HORN) (declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) (declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) (declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) @@ -35,7 +35,7 @@ (declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) (declare-fun |interface_0_C_14| (Int |abi_type| |crypto_type| |state_type|) Bool) (declare-fun |nondet_interface_1_C_14| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.basefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) +(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) (declare-fun |summary_constructor_2_C_14| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) (=> (= error_0 0) (nondet_interface_1_C_14 error_0 this_0 abi_0 crypto_0 state_0 state_0))) @@ -72,7 +72,7 @@ (block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1)) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int) (x_3_2 Int)) -(=> (and (and (block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (summary_3_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_2 x_3_1 state_3 x_3_2) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true))))))) true) (summary_4_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_3 x_3_2))) +(=> (and (and (block_9_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (and (summary_3_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_2 x_3_1 state_3 x_3_2) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) (and true (= x_3_1 x_3_0))) true))))))) true) (summary_4_function_f__13_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_3 x_3_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) (=> (and (and (interface_0_C_14 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__13_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 x_3_0 state_1 x_3_1) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1))) @@ -100,7 +100,7 @@ (=> (and (and (implicit_constructor_entry_13_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_14 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) ) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1))) +(=> (and (and (summary_constructor_2_C_14 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_14 this_0 abi_0 crypto_0 state_1))) ) (declare-fun |error_target_3| () Bool) (assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_3_0 Int) (x_3_1 Int)) diff --git a/test/libsolidity/smtCheckerTests/bmc_coverage/compound_bitwise_or_uint_3.sol b/test/libsolidity/smtCheckerTests/bmc_coverage/compound_bitwise_or_uint_3.sol index 02d538d7d..956265380 100644 --- a/test/libsolidity/smtCheckerTests/bmc_coverage/compound_bitwise_or_uint_3.sol +++ b/test/libsolidity/smtCheckerTests/bmc_coverage/compound_bitwise_or_uint_3.sol @@ -12,4 +12,4 @@ contract C { // SMTEngine: bmc // SMTShowUnproved: no // ---- -// Warning 2788: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol index a28e4852b..8afc574a8 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol @@ -6,17 +6,16 @@ contract C { uint x; D d; function f() public { - if (x < 5) + if (x < 4) ++x; } function g() public { d.d(); - assert(x < 6); + assert(x < 5); } } // ==== // SMTEngine: all // SMTTargets: assert -// SMTIgnoreOS: linux // ---- // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_uint_3.sol b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_uint_3.sol index 2650b0897..ff246b362 100644 --- a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_uint_3.sol +++ b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_uint_3.sol @@ -12,4 +12,4 @@ contract C { // SMTEngine: all // ---- // Warning 6328: (125-140): CHC: Assertion violation might happen here. -// Warning 7812: (125-140): BMC: Assertion violation might happen here. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol index 30f6a0ba9..76ad6db55 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol @@ -53,10 +53,10 @@ contract C { } // ==== // SMTEngine: all -// SMTIgnoreOS: macos // SMTTargets: assert // ---- // Warning 6328: (2209-2235): CHC: Assertion violation might happen here. // Warning 6328: (2245-2271): CHC: Assertion violation might happen here. // Info 1391: CHC: 14 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Info 6002: BMC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 7812: (2245-2271): BMC: Assertion violation might happen here. +// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/special/blobhash_beyond_limit.sol b/test/libsolidity/smtCheckerTests/special/blobhash_beyond_limit.sol new file mode 100644 index 000000000..b68a9aa4b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/special/blobhash_beyond_limit.sol @@ -0,0 +1,11 @@ +contract C { + function f(uint index) public view { + uint limit = 9; // Since PECTRA + require(index >= limit); + assert(blobhash(index) == 0); + } +} +// ==== +// SMTEngine: all +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol b/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol index 21a924b1f..e2e7e9ebd 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_data_immutable.sol @@ -1,6 +1,8 @@ contract C { - bytes32 bhash; + bytes32 blob_hash; + bytes32 block_hash; uint bfee; + uint blobfee; address coin; uint dif; uint prevrandao; @@ -15,8 +17,10 @@ contract C { address origin; function f() public payable { - bhash = blockhash(12); + blob_hash = blobhash(1); + block_hash = blockhash(12); bfee = block.basefee; + blobfee = block.blobbasefee; coin = block.coinbase; dif = block.difficulty; prevrandao = block.prevrandao; @@ -32,8 +36,10 @@ contract C { fi(); - assert(bhash == blockhash(12)); + assert(blob_hash == blobhash(1)); + assert(block_hash == blockhash(12)); assert(bfee == block.basefee); + assert(blobfee == block.blobbasefee); assert(coin == block.coinbase); assert(dif == block.difficulty); assert(prevrandao == block.prevrandao); @@ -49,8 +55,10 @@ contract C { } function fi() internal view { - assert(bhash == blockhash(12)); + assert(blob_hash == blobhash(1)); + assert(block_hash == blockhash(12)); assert(bfee == block.basefee); + assert(blobfee == block.blobbasefee); assert(coin == block.coinbase); assert(dif == block.difficulty); assert(prevrandao == block.prevrandao); @@ -68,7 +76,7 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 8417: (329-345): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 8417: (714-730): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 8417: (1229-1245): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Info 1391: CHC: 28 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 8417: (432-448): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (898-914): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (1494-1510): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Info 1391: CHC: 32 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol b/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol index 2b16f2d1a..be8436e82 100644 --- a/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol +++ b/test/libsolidity/smtCheckerTests/special/tx_data_immutable_fail.sol @@ -1,5 +1,8 @@ contract C { - bytes32 bhash; + bytes32 blob_hash; + bytes32 block_hash; + uint bfee; + uint blobfee; address coin; uint dif; uint prevrandao; @@ -14,7 +17,10 @@ contract C { address origin; function f() public payable { - bhash = blockhash(12); + blob_hash = blobhash(1); + block_hash = blockhash(12); + bfee = block.basefee; + blobfee = block.blobbasefee; coin = block.coinbase; dif = block.difficulty; prevrandao = block.prevrandao; @@ -30,8 +36,11 @@ contract C { fi(); - assert(bhash == blockhash(122)); - assert(coin != block.coinbase); + assert(blob_hash == blobhash(2)); + assert(block_hash == blockhash(122)); + assert(bfee != block.basefee); + assert(blobfee != block.blobbasefee); + assert(coin != block.coinbase); assert(dif != block.difficulty); assert(prevrandao != block.prevrandao); assert(glimit != block.gaslimit); @@ -46,7 +55,10 @@ contract C { } function fi() internal view { - assert(bhash == blockhash(122)); + assert(blob_hash == blobhash(2)); + assert(block_hash == blockhash(122)); + assert(bfee != block.basefee); + assert(blobfee != block.blobbasefee); assert(coin != block.coinbase); assert(dif != block.difficulty); assert(prevrandao != block.prevrandao); @@ -65,32 +77,38 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 8417: (293-309): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 8417: (646-662): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 8417: (1129-1145): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. -// Warning 6328: (563-594): CHC: Assertion violation happens here. -// Warning 6328: (598-628): CHC: Assertion violation happens here. -// Warning 6328: (632-663): CHC: Assertion violation happens here. -// Warning 6328: (667-705): CHC: Assertion violation happens here. -// Warning 6328: (709-741): CHC: Assertion violation happens here. -// Warning 6328: (745-775): CHC: Assertion violation happens here. -// Warning 6328: (779-812): CHC: Assertion violation happens here. -// Warning 6328: (816-855): CHC: Assertion violation happens here. -// Warning 6328: (859-887): CHC: Assertion violation happens here. -// Warning 6328: (891-913): CHC: Assertion violation happens here. -// Warning 6328: (917-943): CHC: Assertion violation happens here. -// Warning 6328: (947-976): CHC: Assertion violation happens here. -// Warning 6328: (980-1007): CHC: Assertion violation happens here. -// Warning 6328: (1046-1077): CHC: Assertion violation happens here. -// Warning 6328: (1081-1111): CHC: Assertion violation happens here. -// Warning 6328: (1115-1146): CHC: Assertion violation happens here. -// Warning 6328: (1150-1188): CHC: Assertion violation happens here. -// Warning 6328: (1192-1224): CHC: Assertion violation happens here. -// Warning 6328: (1228-1258): CHC: Assertion violation happens here. -// Warning 6328: (1262-1295): CHC: Assertion violation happens here. -// Warning 6328: (1299-1338): CHC: Assertion violation happens here. -// Warning 6328: (1342-1370): CHC: Assertion violation happens here. -// Warning 6328: (1374-1396): CHC: Assertion violation happens here. -// Warning 6328: (1400-1426): CHC: Assertion violation happens here. -// Warning 6328: (1430-1459): CHC: Assertion violation happens here. -// Warning 6328: (1463-1490): CHC: Assertion violation happens here. +// Warning 8417: (474-490): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (969-985): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 8417: (1580-1596): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// Warning 6328: (744-776): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (780-816): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (820-849): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2e16, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (867-903): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (921-951): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (955-986): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (990-1028): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1032-1064): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1068-1098): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1102-1135): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1139-1178): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1182-1210): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1214-1236): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1240-1266): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1270-1299): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1303-1330): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1369-1401): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1405-1441): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0986, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1445-1474): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1492-1528): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1532-1562): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1566-1597): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0986, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1601-1639): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1643-1675): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1679-1709): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1713-1746): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1750-1789): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0986, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1793-1821): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x2298, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1825-1847): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1851-1877): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0986, block_hash = 0x2298, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1881-1910): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0986, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call +// Warning 6328: (1914-1941): CHC: Assertion violation happens here.\nCounterexample:\nblob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 18446744073709551617, prevrandao = 18446744073709551617, glimit = 0, number = 0, tstamp = 0, mdata = [0x26, 0x12, 0x1f, 0xf0], sender = 0x0, sig = 0x26121ff0, value = 0, gprice = 0, origin = 0x0\n\nTransaction trace:\nC.constructor()\nState: blob_hash = 0x0, block_hash = 0x0, bfee = 0, blobfee = 0, coin = 0x0, dif = 0, prevrandao = 0, glimit = 0, number = 0, tstamp = 0, mdata = [], sender = 0x0, sig = 0x0, value = 0, gprice = 0, origin = 0x0\nC.f(){ block.basefee: 0, block.blobbasefee: 0, block.coinbase: 0x0, block.gaslimit: 0, block.number: 0, block.prevrandao: 18446744073709551617, block.timestamp: 0, msg.data: [0x26, 0x12, 0x1f, 0xf0], msg.sender: 0x0, msg.sig: 0x26121ff0, msg.value: 0, tx.gasprice: 0, tx.origin: 0x0 }\n C.fi() -- internal call diff --git a/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol b/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol index 54f323353..bb4ef0342 100644 --- a/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol +++ b/test/libsolidity/smtCheckerTests/types/fixed_bytes_access_3.sol @@ -30,7 +30,7 @@ contract C { } // ==== // SMTEngine: all +// SMTIgnoreOS: macos // ---- -// Warning 6368: (374-381): CHC: Out of bounds access might happen here. // Warning 6368: (456-462): CHC: Out of bounds access happens here. -// Info 1391: CHC: 12 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 13 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 85074cc17b108362d62d8a6eef3d972afb308ee3 Mon Sep 17 00:00:00 2001 From: Rudko Hanna <162179706+Pistasha@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:51:05 +0200 Subject: [PATCH 0667/1340] fix: correct code comments and references in ArrayUtils, CHC, EncodingContext, and LSP tests (#15801) * Update ArrayUtils.cpp * Update CHC.cpp * Update EncodingContext.h * Update goto_definition_imports.sol * Update goto_definition_imports.sol --- libsolidity/codegen/ArrayUtils.cpp | 2 +- libsolidity/formal/CHC.cpp | 2 +- libsolidity/formal/EncodingContext.h | 2 +- test/libsolidity/lsp/goto/goto_definition_imports.sol | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index 5dd94aebc..455cfe084 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -710,7 +710,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const CompilerUtils(_context).computeHashStatic(); _context << Instruction::SSTORE; // stack: ref new_length current_length - // Store new length: Compule 2*length + 1 and store it. + // Store new length: Compute 2*length + 1 and store it. _context << Instruction::DUP2 << Instruction::DUP1 << Instruction::ADD; _context << u256(1) << Instruction::ADD; // stack: ref new_length current_length 2*new_length+1 diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 9f23aff6f..222a0995b 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -1336,7 +1336,7 @@ void CHC::clearIndices(ContractDefinition const* _contract, FunctionDefinition c void CHC::setCurrentBlock(Predicate const& _block) { - if (m_context.solverStackHeigh() > 0) + if (m_context.solverStackHeight() > 0) m_context.popSolver(); solAssert(m_currentContract, ""); clearIndices(m_currentContract, m_currentFunction); diff --git a/libsolidity/formal/EncodingContext.h b/libsolidity/formal/EncodingContext.h index 35e54ed76..5387184ee 100644 --- a/libsolidity/formal/EncodingContext.h +++ b/libsolidity/formal/EncodingContext.h @@ -142,7 +142,7 @@ class EncodingContext void pushSolver(); void popSolver(); void addAssertion(smtutil::Expression const& _e); - size_t solverStackHeigh() { return m_assertions.size(); } const + size_t solverStackHeight() { return m_assertions.size(); } const smtutil::SolverInterface* solver() { solAssert(m_solver, ""); diff --git a/test/libsolidity/lsp/goto/goto_definition_imports.sol b/test/libsolidity/lsp/goto/goto_definition_imports.sol index dd0267d71..f58bd002c 100644 --- a/test/libsolidity/lsp/goto/goto_definition_imports.sol +++ b/test/libsolidity/lsp/goto/goto_definition_imports.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0; import {Weather as Wetter} from "./lib.sol"; -// ^ @wheatherImportCursor +// ^ @weatherImportCursor import "./lib.sol" as That; // ^^^^ @ThatImport @@ -25,7 +25,7 @@ contract C // ---- // lib: @diagnostics 2072 // -> textDocument/definition { -// "position": @wheatherImportCursor +// "position": @weatherImportCursor // } // <- [ // { From d62ff26a68ea56a2d496ba6d65a5116d3f26f1f2 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 31 Jan 2025 15:53:36 +0100 Subject: [PATCH 0668/1340] tests: Add `outputs` setting to `ObjectCompilerTest` --- test/libyul/ObjectCompilerTest.cpp | 33 ++++++++++++++++++++++-------- test/libyul/ObjectCompilerTest.h | 1 + 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp index f7d331d94..b7e475c91 100644 --- a/test/libyul/ObjectCompilerTest.cpp +++ b/test/libyul/ObjectCompilerTest.cpp @@ -57,6 +57,13 @@ ObjectCompilerTest::ObjectCompilerTest(std::string const& _filename): }, "minimal" ); + + constexpr std::array allowedOutputs = {"Assembly", "Bytecode", "Opcodes", "SourceMappings"}; + boost::split(m_outputSetting, m_reader.stringSetting("outputs", "Assembly,Bytecode,Opcodes,SourceMappings"), boost::is_any_of(",")); + for (auto const& output: m_outputSetting) + if (std::find(allowedOutputs.begin(), allowedOutputs.end(), output) == allowedOutputs.end()) + BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid output type: \"" + output + "\""}); + m_expectation = m_reader.simpleExpectations(); } @@ -78,18 +85,26 @@ TestCase::TestResult ObjectCompilerTest::run(std::ostream& _stream, std::string solAssert(obj.bytecode); solAssert(obj.sourceMappings); - m_obtainedResult = "Assembly:\n" + obj.assembly->assemblyString(yulStack.debugInfoSelection()); + if (std::find(m_outputSetting.begin(), m_outputSetting.end(), "Assembly") != m_outputSetting.end()) + m_obtainedResult = "Assembly:\n" + obj.assembly->assemblyString(yulStack.debugInfoSelection()); if (obj.bytecode->bytecode.empty()) m_obtainedResult += "-- empty bytecode --\n"; else - m_obtainedResult += - "Bytecode: " + - util::toHex(obj.bytecode->bytecode) + - "\nOpcodes: " + - boost::trim_copy(evmasm::disassemble(obj.bytecode->bytecode, solidity::test::CommonOptions::get().evmVersion())) + - "\nSourceMappings:" + - (obj.sourceMappings->empty() ? "" : " " + *obj.sourceMappings) + - "\n"; + { + if (std::find(m_outputSetting.begin(), m_outputSetting.end(), "Bytecode") != m_outputSetting.end()) + m_obtainedResult += "Bytecode: " + util::toHex(obj.bytecode->bytecode); + if (std::find(m_outputSetting.begin(), m_outputSetting.end(), "Opcodes") != m_outputSetting.end()) + { + m_obtainedResult += (!m_obtainedResult.empty() && m_obtainedResult.back() != '\n') ? "\n" : ""; + m_obtainedResult += "Opcodes: " + + boost::trim_copy(evmasm::disassemble(obj.bytecode->bytecode, solidity::test::CommonOptions::get().evmVersion())); + } + if (std::find(m_outputSetting.begin(), m_outputSetting.end(), "SourceMappings") != m_outputSetting.end()) + { + m_obtainedResult += (!m_obtainedResult.empty() && m_obtainedResult.back() != '\n') ? "\n" : ""; + m_obtainedResult += "SourceMappings:" + (obj.sourceMappings->empty() ? "" : " " + *obj.sourceMappings) + "\n"; + } + } return checkResult(_stream, _linePrefix, _formatted); } diff --git a/test/libyul/ObjectCompilerTest.h b/test/libyul/ObjectCompilerTest.h index 604ad0346..7a7941a69 100644 --- a/test/libyul/ObjectCompilerTest.h +++ b/test/libyul/ObjectCompilerTest.h @@ -54,6 +54,7 @@ class ObjectCompilerTest: public solidity::frontend::test::EVMVersionRestrictedT void disambiguate(); frontend::OptimisationPreset m_optimisationPreset; + std::vector m_outputSetting; }; } From c2f14258d86c8cdfad08c2737c47807e90571d93 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 31 Jan 2025 16:14:45 +0100 Subject: [PATCH 0669/1340] eof: Update `semanticTests` tests for EOF --- .../constructor/callvalue_check.sol | 2 + .../deployedCodeExclusion/bound_function.sol | 3 ++ .../library_function.sol | 3 ++ .../deployedCodeExclusion/module_function.sol | 3 ++ .../static_base_function.sol | 3 ++ .../subassembly_deduplication.sol | 3 ++ .../deployedCodeExclusion/super_function.sol | 3 ++ .../virtual_function.sol | 3 ++ .../events/event_emit_from_other_contract.sol | 4 ++ .../semanticTests/experimental/stub.sol | 1 + .../semanticTests/experimental/type_class.sol | 1 + .../freeFunctions/free_runtimecode.sol | 2 + .../functionCall/call_options_overload.sol | 2 + .../calling_nonexisting_contract_throws.sol | 2 + .../eof/call_options_overload.sol | 16 ++++++++ .../eof/calling_nonexisting_contract.sol | 25 ++++++++++++ .../external_call_at_construction_time.sol | 24 ++++++++++++ .../eof/external_call_to_nonexisting.sol | 39 +++++++++++++++++++ .../external_call_at_construction_time.sol | 1 + .../external_call_to_nonexisting.sol | 2 + ...ernal_call_to_nonexisting_debugstrings.sol | 1 + .../functionCall/gas_and_value_basic.sol | 2 + ...eck_on_adding_gas_variable_to_function.sol | 2 + .../transient_storage_selfdestruct.sol | 1 + .../called_contract_has_code.sol | 1 + .../reverts/eof/revert_return_area.sol | 19 +++++++++ .../reverts/revert_return_area.sol | 1 + .../eof/salted_create_with_value.sol | 23 +++++++++++ .../saltedCreate/prediction_example.sol | 1 + .../saltedCreate/salted_create_with_value.sol | 1 + .../semanticTests/shanghai/evmone_support.sol | 1 + .../semanticTests/state/gasleft.sol | 2 + .../semanticTests/various/address_code.sol | 2 + .../various/address_code_complex.sol | 2 + .../various/code_access_content.sol | 2 + .../various/code_access_create.sol | 3 ++ .../various/code_access_padding.sol | 2 + .../various/code_access_runtime.sol | 1 + .../semanticTests/various/code_length.sol | 2 + .../various/code_length_contract_member.sol | 2 + .../semanticTests/various/codehash.sol | 1 + .../various/codehash_assembly.sol | 1 + .../semanticTests/various/create_calldata.sol | 2 + .../semanticTests/various/create_random.sol | 1 + .../various/eof/create_calldata.sol | 21 ++++++++++ .../various/gasleft_decrease.sol | 2 + .../various/selfdestruct_post_cancun.sol | 1 + ...uct_post_cancun_multiple_beneficiaries.sol | 1 + .../selfdestruct_post_cancun_redeploy.sol | 1 + 49 files changed, 244 insertions(+) create mode 100644 test/libsolidity/semanticTests/functionCall/eof/call_options_overload.sol create mode 100644 test/libsolidity/semanticTests/functionCall/eof/calling_nonexisting_contract.sol create mode 100644 test/libsolidity/semanticTests/functionCall/eof/external_call_at_construction_time.sol create mode 100644 test/libsolidity/semanticTests/functionCall/eof/external_call_to_nonexisting.sol create mode 100644 test/libsolidity/semanticTests/reverts/eof/revert_return_area.sol create mode 100644 test/libsolidity/semanticTests/saltedCreate/eof/salted_create_with_value.sol create mode 100644 test/libsolidity/semanticTests/various/eof/create_calldata.sol diff --git a/test/libsolidity/semanticTests/constructor/callvalue_check.sol b/test/libsolidity/semanticTests/constructor/callvalue_check.sol index f45fbed92..10086886a 100644 --- a/test/libsolidity/semanticTests/constructor/callvalue_check.sol +++ b/test/libsolidity/semanticTests/constructor/callvalue_check.sol @@ -11,6 +11,7 @@ contract B4 { constructor() {} } contract C { function createWithValue(bytes memory c, uint256 value) public payable returns (bool) { uint256 y = 0; + // TODO: This test is hard to recreate for EOF as for now eofcreate is disallowed in inline assembly. assembly { y := create(value, add(c, 0x20), mload(c)) } return y != 0; } @@ -29,6 +30,7 @@ contract C { } // ==== // EVMVersion: >homestead +// bytecodeFormat: legacy // ---- // f(uint256), 2000 ether: 0 -> true // f(uint256), 2000 ether: 100 -> false diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/bound_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/bound_function.sol index 64b80422c..69a4bd65b 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/bound_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/bound_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. function longdata(S memory) pure returns (bytes memory) { return "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" @@ -36,5 +37,7 @@ contract C { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/library_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/library_function.sol index 931109199..28843b25d 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/library_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/library_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. library L { function longdata() pure internal returns (bytes memory) { return @@ -30,5 +31,7 @@ contract C { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/module_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/module_function.sol index 018d41055..8e075654f 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/module_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/module_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. ==== Source: mod.sol ==== function longdata() pure returns (bytes memory) { return @@ -32,5 +33,7 @@ contract C { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function.sol index 0f9b023b0..255e99e82 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. abstract contract S { function longdata() internal pure returns (bytes memory) { return @@ -31,5 +32,7 @@ contract C is S { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/subassembly_deduplication.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/subassembly_deduplication.sol index b6ae85b83..442547569 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/subassembly_deduplication.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/subassembly_deduplication.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. contract A { function longdata() pure external returns (bytes memory) { return @@ -37,5 +38,7 @@ contract C { x < 2 * type(A).creationCode.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/super_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/super_function.sol index 9accc54a2..17aabdf83 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/super_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/super_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. abstract contract S { function longdata() internal pure returns (bytes memory) { return @@ -31,5 +32,7 @@ contract C is S { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function.sol index 866fe9dfc..322de3c84 100644 --- a/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function.sol +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test for EOF when subassembly deduplication will be supported for EOF too. abstract contract S { function longdata() internal virtual pure returns (bytes memory); } @@ -35,5 +36,7 @@ contract C is X { return x < data.length; } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol index 61e1bbdd6..e6d800d9b 100644 --- a/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol +++ b/test/libsolidity/semanticTests/events/event_emit_from_other_contract.sol @@ -1,3 +1,5 @@ +// TODO: Implement this test for EOF. Now it's not possible because deployed contract address depends on contract bytecode. +// This means that the address changes when optimisations are applied. contract D { event Deposit(address indexed _from, bytes32 indexed _id, uint _value); function deposit(bytes32 _id) public payable { @@ -13,6 +15,8 @@ contract C { d.deposit(_id); } } +// ==== +// bytecodeFormat: legacy // ---- // constructor() -> // gas irOptimized: 113970 diff --git a/test/libsolidity/semanticTests/experimental/stub.sol b/test/libsolidity/semanticTests/experimental/stub.sol index 6e7a750fe..d2d0999bf 100644 --- a/test/libsolidity/semanticTests/experimental/stub.sol +++ b/test/libsolidity/semanticTests/experimental/stub.sol @@ -92,6 +92,7 @@ contract C { // EVMVersion: >=constantinople // ==== // compileViaYul: true +// bytecodeFormat: legacy // ---- // (): 0 -> 0 // (): 1 -> 544 diff --git a/test/libsolidity/semanticTests/experimental/type_class.sol b/test/libsolidity/semanticTests/experimental/type_class.sol index 69fa568df..7331c0dbd 100644 --- a/test/libsolidity/semanticTests/experimental/type_class.sol +++ b/test/libsolidity/semanticTests/experimental/type_class.sol @@ -63,5 +63,6 @@ contract C { // ==== // EVMVersion: >=constantinople // compileViaYul: true +// bytecodeFormat: legacy // ---- // () -> 1, 0 diff --git a/test/libsolidity/semanticTests/freeFunctions/free_runtimecode.sol b/test/libsolidity/semanticTests/freeFunctions/free_runtimecode.sol index 7a05ff5d0..e414b8205 100644 --- a/test/libsolidity/semanticTests/freeFunctions/free_runtimecode.sol +++ b/test/libsolidity/semanticTests/freeFunctions/free_runtimecode.sol @@ -11,5 +11,7 @@ contract D { return test(); } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> true diff --git a/test/libsolidity/semanticTests/functionCall/call_options_overload.sol b/test/libsolidity/semanticTests/functionCall/call_options_overload.sol index b9eb6ca42..61e979f17 100644 --- a/test/libsolidity/semanticTests/functionCall/call_options_overload.sol +++ b/test/libsolidity/semanticTests/functionCall/call_options_overload.sol @@ -10,6 +10,8 @@ contract C { function bal() external returns (uint) { return address(this).balance; } receive() external payable {} } +// ==== +// bytecodeFormat: legacy // ---- // (), 1 ether // call() -> 1, 2, 2, 2 diff --git a/test/libsolidity/semanticTests/functionCall/calling_nonexisting_contract_throws.sol b/test/libsolidity/semanticTests/functionCall/calling_nonexisting_contract_throws.sol index 229618384..36dfc844d 100644 --- a/test/libsolidity/semanticTests/functionCall/calling_nonexisting_contract_throws.sol +++ b/test/libsolidity/semanticTests/functionCall/calling_nonexisting_contract_throws.sol @@ -21,6 +21,8 @@ contract C { return 7; } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> FAILURE // g() -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/eof/call_options_overload.sol b/test/libsolidity/semanticTests/functionCall/eof/call_options_overload.sol new file mode 100644 index 000000000..1ddc06c1d --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/eof/call_options_overload.sol @@ -0,0 +1,16 @@ +contract C { + function f(uint x) external payable returns (uint) { return 1; } + function f(uint x, uint y) external payable returns (uint) { return 2; } + function call() public payable returns (uint x, uint y) { + x = this.f{value: 10}(2); + y = this.f{value: 10}(2, 3); + } + function bal() external returns (uint) { return address(this).balance; } + receive() external payable {} +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// (), 1 ether +// call() -> 1, 2 +// bal() -> 1000000000000000000 diff --git a/test/libsolidity/semanticTests/functionCall/eof/calling_nonexisting_contract.sol b/test/libsolidity/semanticTests/functionCall/eof/calling_nonexisting_contract.sol new file mode 100644 index 000000000..10b39634d --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/eof/calling_nonexisting_contract.sol @@ -0,0 +1,25 @@ +abstract contract D { + function g() public virtual; +} + + +contract C { + D d = D(address(0x1212)); + + function f() public returns (uint256) { + // This call throws on legacy bytecode because of calling nonexisting contract. Legacy checks that there is + // a non-empty code under under an address. EOF doesn't do it because non-observability assumption + d.g(); + return 7; + } + + function h() public returns (uint256) { + address(d).call(""); // this does not throw (low-level) + return 7; + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// f() -> 7 +// h() -> 7 diff --git a/test/libsolidity/semanticTests/functionCall/eof/external_call_at_construction_time.sol b/test/libsolidity/semanticTests/functionCall/eof/external_call_at_construction_time.sol new file mode 100644 index 000000000..6235562c9 --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/eof/external_call_at_construction_time.sol @@ -0,0 +1,24 @@ +// This tests skipping the extcodesize check. + +contract T { + constructor() { this.f(); } + function f() external {} +} +contract U { + constructor() { this.f(); } + function f() external returns (uint) {} +} + +contract C { + function f(uint c) external returns (uint) { + if (c == 0) new T(); + else if (c == 1) new U(); + return 1 + c; + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// f(uint256): 0 -> 1 +// f(uint256): 1 -> FAILURE +// f(uint256): 2 -> 3 diff --git a/test/libsolidity/semanticTests/functionCall/eof/external_call_to_nonexisting.sol b/test/libsolidity/semanticTests/functionCall/eof/external_call_to_nonexisting.sol new file mode 100644 index 000000000..bc39e9633 --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/eof/external_call_to_nonexisting.sol @@ -0,0 +1,39 @@ +// This tests skipping the extcodesize check. + +interface I { + function a() external pure; + function b() external; + function c() external payable; + function x() external returns (uint); + function y() external returns (string memory); +} +contract C { + I i = I(address(0xcafecafe)); + constructor() payable {} + function f(uint c) external returns (uint) { + if (c == 0) i.a(); + else if (c == 1) i.b(); + else if (c == 2) i.c(); + else if (c == 3) i.c{value: 1}(); + else if (c == 4) i.x(); + else if (c == 5) i.y(); + return 1 + c; + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// constructor(), 1 ether -> +// gas irOptimized: 88853 +// gas irOptimized code: 164400 +// gas legacy: 102721 +// gas legacy code: 334400 +// gas legacyOptimized: 91499 +// gas legacyOptimized code: 196400 +// f(uint256): 0 -> 1 +// f(uint256): 1 -> 2 +// f(uint256): 2 -> 3 +// f(uint256): 3 -> 4 +// f(uint256): 4 -> FAILURE +// f(uint256): 5 -> FAILURE +// f(uint256): 6 -> 7 diff --git a/test/libsolidity/semanticTests/functionCall/external_call_at_construction_time.sol b/test/libsolidity/semanticTests/functionCall/external_call_at_construction_time.sol index 6f7f020fe..c5fa0538e 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_at_construction_time.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_at_construction_time.sol @@ -18,6 +18,7 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // f(uint256): 0 -> FAILURE // f(uint256): 1 -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol index 472921c1d..0031059c0 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting.sol @@ -20,6 +20,8 @@ contract C { return 1 + c; } } +// ==== +// bytecodeFormat: legacy // ---- // constructor(), 1 ether -> // gas irOptimized: 88853 diff --git a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol index d1b6e8e86..a8eafb38e 100644 --- a/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol +++ b/test/libsolidity/semanticTests/functionCall/external_call_to_nonexisting_debugstrings.sol @@ -23,6 +23,7 @@ contract C { // ==== // EVMVersion: >=byzantium // revertStrings: debug +// bytecodeFormat: legacy // ---- // constructor(), 1 ether -> // gas irOptimized: 98698 diff --git a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol index e7bf053eb..7415accab 100644 --- a/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol +++ b/test/libsolidity/semanticTests/functionCall/gas_and_value_basic.sol @@ -34,6 +34,8 @@ contract test { myBal = address(this).balance; } } +// ==== +// bytecodeFormat: legacy // ---- // constructor(), 20 wei -> // gas irOptimized: 120218 diff --git a/test/libsolidity/semanticTests/functionTypes/stack_height_check_on_adding_gas_variable_to_function.sol b/test/libsolidity/semanticTests/functionTypes/stack_height_check_on_adding_gas_variable_to_function.sol index f811988fe..1ca391e81 100644 --- a/test/libsolidity/semanticTests/functionTypes/stack_height_check_on_adding_gas_variable_to_function.sol +++ b/test/libsolidity/semanticTests/functionTypes/stack_height_check_on_adding_gas_variable_to_function.sol @@ -19,5 +19,7 @@ contract C { return true; } } +// ==== +// bytecodeFormat: legacy // ---- // test_function() -> true diff --git a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol index c2066ef8b..26bb09edc 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/transient_storage_selfdestruct.sol @@ -38,6 +38,7 @@ contract D { } // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy // ---- // constructor() -> // gas irOptimized: 127596 diff --git a/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol b/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol index 110b1e50c..d9a654925 100644 --- a/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol +++ b/test/libsolidity/semanticTests/revertStrings/called_contract_has_code.sol @@ -8,5 +8,6 @@ contract C { // ==== // EVMVersion: >=byzantium // revertStrings: debug +// bytecodeFormat: legacy // ---- // g() -> FAILURE, hex"08c379a0", 0x20, 37, "Target contract does not contain", " code" diff --git a/test/libsolidity/semanticTests/reverts/eof/revert_return_area.sol b/test/libsolidity/semanticTests/reverts/eof/revert_return_area.sol new file mode 100644 index 000000000..8cec1ca1d --- /dev/null +++ b/test/libsolidity/semanticTests/reverts/eof/revert_return_area.sol @@ -0,0 +1,19 @@ +contract C { + fallback() external { + revert("abc"); + } + + function f() public returns (uint s, uint r) { + address x = address(this); + assembly { + mstore(0, 7) + s := extcall(x, 0, 0, 0) + returndatacopy(0, 0, 32) + r := mload(0) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// f() -> 0x01, 0x08c379a000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/reverts/revert_return_area.sol b/test/libsolidity/semanticTests/reverts/revert_return_area.sol index 8ab4ca227..5f276f91c 100644 --- a/test/libsolidity/semanticTests/reverts/revert_return_area.sol +++ b/test/libsolidity/semanticTests/reverts/revert_return_area.sol @@ -14,5 +14,6 @@ contract C { } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // f() -> 0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/saltedCreate/eof/salted_create_with_value.sol b/test/libsolidity/semanticTests/saltedCreate/eof/salted_create_with_value.sol new file mode 100644 index 000000000..e6c6f6eb0 --- /dev/null +++ b/test/libsolidity/semanticTests/saltedCreate/eof/salted_create_with_value.sol @@ -0,0 +1,23 @@ +contract B +{ + uint x; + function getBalance() public view returns (uint) { + return address(this).balance * 1000 + x; + } + constructor(uint _x) payable { + x = _x; + } +} + +contract A { + function f() public payable returns (uint, uint, uint) { + B x = new B{salt: "abc1", value: 3}(7); + B y = new B{value: 3, salt: "abc2"}(8); + B z = new B{salt: "abc3", value: 3}(9); + return (x.getBalance(), y.getBalance(), z.getBalance()); + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// f(), 10 ether -> 3007, 3008, 3009 diff --git a/test/libsolidity/semanticTests/saltedCreate/prediction_example.sol b/test/libsolidity/semanticTests/saltedCreate/prediction_example.sol index 7d0e3c8b0..f1f62db03 100644 --- a/test/libsolidity/semanticTests/saltedCreate/prediction_example.sol +++ b/test/libsolidity/semanticTests/saltedCreate/prediction_example.sol @@ -24,6 +24,7 @@ contract C { // ==== // EVMVersion: >=constantinople // compileViaYul: also +// bytecodeFormat: legacy // ---- // createDSalted(bytes32,uint256): 42, 64 -> // gas legacy: 78573 diff --git a/test/libsolidity/semanticTests/saltedCreate/salted_create_with_value.sol b/test/libsolidity/semanticTests/saltedCreate/salted_create_with_value.sol index 25d193577..c810000e5 100644 --- a/test/libsolidity/semanticTests/saltedCreate/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/saltedCreate/salted_create_with_value.sol @@ -19,6 +19,7 @@ contract A { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // f(), 10 ether -> 3007, 3008, 3009 // gas irOptimized: 187022 diff --git a/test/libsolidity/semanticTests/shanghai/evmone_support.sol b/test/libsolidity/semanticTests/shanghai/evmone_support.sol index 359dc516f..4f3c0ee1b 100644 --- a/test/libsolidity/semanticTests/shanghai/evmone_support.sol +++ b/test/libsolidity/semanticTests/shanghai/evmone_support.sol @@ -26,6 +26,7 @@ contract Test { // ==== // compileViaYul: also // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // bytecode() -> 0x20, 4, 0x60205ff300000000000000000000000000000000000000000000000000000000 // isPush0Supported() -> true diff --git a/test/libsolidity/semanticTests/state/gasleft.sol b/test/libsolidity/semanticTests/state/gasleft.sol index 6ce623ce8..2d4a37b48 100644 --- a/test/libsolidity/semanticTests/state/gasleft.sol +++ b/test/libsolidity/semanticTests/state/gasleft.sol @@ -3,6 +3,8 @@ contract C { return gasleft() > 0; } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> true // f() -> true diff --git a/test/libsolidity/semanticTests/various/address_code.sol b/test/libsolidity/semanticTests/various/address_code.sol index 549512eb3..4d810f970 100644 --- a/test/libsolidity/semanticTests/various/address_code.sol +++ b/test/libsolidity/semanticTests/various/address_code.sol @@ -12,6 +12,8 @@ contract C { function g() public view returns (uint) { return address(0).code.length; } function h() public view returns (uint) { return address(1).code.length; } } +// ==== +// bytecodeFormat: legacy // ---- // constructor() -> // gas irOptimized: 70760 diff --git a/test/libsolidity/semanticTests/various/address_code_complex.sol b/test/libsolidity/semanticTests/various/address_code_complex.sol index f2d21c906..d228d99d1 100644 --- a/test/libsolidity/semanticTests/various/address_code_complex.sol +++ b/test/libsolidity/semanticTests/various/address_code_complex.sol @@ -12,6 +12,8 @@ contract C { function f() public returns (bytes memory) { return address(new A()).code; } function g() public returns (uint) { return address(new A()).code.length; } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> 0x20, 0x20, 0x48aa5566000000 // g() -> 0x20 diff --git a/test/libsolidity/semanticTests/various/code_access_content.sol b/test/libsolidity/semanticTests/various/code_access_content.sol index 22ceff337..b8b13b3c6 100644 --- a/test/libsolidity/semanticTests/various/code_access_content.sol +++ b/test/libsolidity/semanticTests/various/code_access_content.sol @@ -36,6 +36,8 @@ contract C { return true; } } +// ==== +// bytecodeFormat: legacy // ---- // testRuntime() -> true // gas legacy: 76575 diff --git a/test/libsolidity/semanticTests/various/code_access_create.sol b/test/libsolidity/semanticTests/various/code_access_create.sol index f5f0b8644..e3a6e0372 100644 --- a/test/libsolidity/semanticTests/various/code_access_create.sol +++ b/test/libsolidity/semanticTests/various/code_access_create.sol @@ -1,3 +1,4 @@ +// TODO: Recreate this test when eofcreate will be allowed in inline assembly. contract D { uint256 x; @@ -21,6 +22,8 @@ contract C { return d.f(); } } +// ==== +// bytecodeFormat: legacy // ---- // test() -> 7 // gas legacy: 76647 diff --git a/test/libsolidity/semanticTests/various/code_access_padding.sol b/test/libsolidity/semanticTests/various/code_access_padding.sol index 831d4bde4..6c07fb4e0 100644 --- a/test/libsolidity/semanticTests/various/code_access_padding.sol +++ b/test/libsolidity/semanticTests/various/code_access_padding.sol @@ -14,5 +14,7 @@ contract C { } } } +// ==== +// bytecodeFormat: legacy // ---- // diff() -> 0 # This checks that the allocation function pads to multiples of 32 bytes # diff --git a/test/libsolidity/semanticTests/various/code_access_runtime.sol b/test/libsolidity/semanticTests/various/code_access_runtime.sol index 10d7c1852..0c848fc59 100644 --- a/test/libsolidity/semanticTests/various/code_access_runtime.sol +++ b/test/libsolidity/semanticTests/various/code_access_runtime.sol @@ -21,6 +21,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // test() -> 42 // gas legacy: 76034 diff --git a/test/libsolidity/semanticTests/various/code_length.sol b/test/libsolidity/semanticTests/various/code_length.sol index 844a0f657..08065b302 100644 --- a/test/libsolidity/semanticTests/various/code_length.sol +++ b/test/libsolidity/semanticTests/various/code_length.sol @@ -57,6 +57,8 @@ contract C { } } +// ==== +// bytecodeFormat: legacy // ---- // constructor() // gas legacy: 66989 diff --git a/test/libsolidity/semanticTests/various/code_length_contract_member.sol b/test/libsolidity/semanticTests/various/code_length_contract_member.sol index ff883139a..79e940080 100644 --- a/test/libsolidity/semanticTests/various/code_length_contract_member.sol +++ b/test/libsolidity/semanticTests/various/code_length_contract_member.sol @@ -11,5 +11,7 @@ contract C { return (s.code.length, s.another.length, address(this).code.length > 50); } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> 0x20, 0x20, true diff --git a/test/libsolidity/semanticTests/various/codehash.sol b/test/libsolidity/semanticTests/various/codehash.sol index fa7dab9da..465e2ee31 100644 --- a/test/libsolidity/semanticTests/various/codehash.sol +++ b/test/libsolidity/semanticTests/various/codehash.sol @@ -13,6 +13,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // f() -> 0x0 // g() -> 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 diff --git a/test/libsolidity/semanticTests/various/codehash_assembly.sol b/test/libsolidity/semanticTests/various/codehash_assembly.sol index fe2210fa1..81c2286d5 100644 --- a/test/libsolidity/semanticTests/various/codehash_assembly.sol +++ b/test/libsolidity/semanticTests/various/codehash_assembly.sol @@ -17,6 +17,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // f() -> 0 // g() -> 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 diff --git a/test/libsolidity/semanticTests/various/create_calldata.sol b/test/libsolidity/semanticTests/various/create_calldata.sol index a5f61d2dd..7e3e32622 100644 --- a/test/libsolidity/semanticTests/various/create_calldata.sol +++ b/test/libsolidity/semanticTests/various/create_calldata.sol @@ -6,6 +6,8 @@ contract C { assert(msg.data.length == 0); } } +// ==== +// bytecodeFormat: legacy // ---- // constructor(): 42 -> // gas irOptimized: 68239 diff --git a/test/libsolidity/semanticTests/various/create_random.sol b/test/libsolidity/semanticTests/various/create_random.sol index 676ec32a8..b053deb44 100644 --- a/test/libsolidity/semanticTests/various/create_random.sol +++ b/test/libsolidity/semanticTests/various/create_random.sol @@ -33,6 +33,7 @@ contract C { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // addr() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e // testRunner() -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a, 0x2c1c30623ddd93e0b765a6caaca0c859eeb0644d diff --git a/test/libsolidity/semanticTests/various/eof/create_calldata.sol b/test/libsolidity/semanticTests/various/eof/create_calldata.sol new file mode 100644 index 000000000..ae1fc39ec --- /dev/null +++ b/test/libsolidity/semanticTests/various/eof/create_calldata.sol @@ -0,0 +1,21 @@ +contract C { + bytes public s; + constructor(uint256 x, bytes memory b) { + // On EOF msg.data contains constructor arguments, while on legacy it's empty + // (arguments are appended to the code). + s = msg.data; + assert(msg.data.length == 288); + uint y; + bytes memory d; + (y, d) = abi.decode(msg.data, (uint256, bytes)); + assert(x == y); + assert(b.length == d.length); + for (uint i = 0; i < b.length; ++i) + assert(b[i] == d[i]); + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// constructor(): 42, 0x20, 0xc0, 1, 2, 3, 4, 5, 6 -> +// s() -> 0x20, 0x0120, 42, 0x20, 0xc0, 1, 2, 3, 4, 5, 6 diff --git a/test/libsolidity/semanticTests/various/gasleft_decrease.sol b/test/libsolidity/semanticTests/various/gasleft_decrease.sol index ab7302743..ea891edc4 100644 --- a/test/libsolidity/semanticTests/various/gasleft_decrease.sol +++ b/test/libsolidity/semanticTests/various/gasleft_decrease.sol @@ -14,6 +14,8 @@ contract C { return true; } } +// ==== +// bytecodeFormat: legacy // ---- // f() -> true // g() -> true diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol index 4cb5c8c71..bf70caee5 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun.sol @@ -62,6 +62,7 @@ contract D { } // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy // ---- // constructor(), 1 ether -> // gas irOptimized: 67028 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol index a58264919..7629fabc1 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_multiple_beneficiaries.sol @@ -33,6 +33,7 @@ contract D { } // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy // ---- // constructor(), 2 ether -> // gas irOptimized: 108104 diff --git a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol index dd550d31a..c9f50046c 100644 --- a/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol +++ b/test/libsolidity/semanticTests/various/selfdestruct_post_cancun_redeploy.sol @@ -80,6 +80,7 @@ contract D { // ==== // EVMVersion: >=cancun +// bytecodeFormat: legacy // ---- // constructor(), 1 ether -> // gas irOptimized: 132974 From 1a1988b2d08eb9e25a9c69d2e58ee910de10fa8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 27 Jan 2025 16:14:46 +0100 Subject: [PATCH 0670/1340] EVMHost: Wrap long hard-coded input/output of ecMul --- test/EVMHost.cpp | 135 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 112 insertions(+), 23 deletions(-) diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 5370542c7..f18140dac 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -927,79 +927,167 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex static std::map const inputOutput{ { - fromHex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "0000000000000000000000000000000000000000000000000000000000000001" + "0000000000000000000000000000000000000000000000000000000000000002" + "0000000000000000000000000000000000000000000000000000000000000002" + "0000000000000000000000000000000000000000000000000000000000000000" + ), { - fromHex("030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4"), + fromHex( + "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd3" + "15ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4" + ), gas_cost } }, { - fromHex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "0000000000000000000000000000000000000000000000000000000000000001" + "0000000000000000000000000000000000000000000000000000000000000002" + "0000000000000000000000000000000000000000000000000000000000000005" + "0000000000000000000000000000000000000000000000000000000000000000" + ), { - fromHex("17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c"), + fromHex( + "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa9" + "01e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c" + ), gas_cost } }, { - fromHex("09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4030f7b0c405c888aff922307ea2cd1c70f64664bab76899500341f4260a209290000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe" + "18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4" + "030f7b0c405c888aff922307ea2cd1c70f64664bab76899500341f4260a20929" + "0000000000000000000000000000000000000000000000000000000000000000" + ), { - fromHex("16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c"), + fromHex( + "16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc" + "1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c" + ), gas_cost } }, { - fromHex("0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e1551dcd4965285ef049512d2d30cbfc1a91acd5baad4a6e19e22e93176197f170000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a" + "04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e" + "1551dcd4965285ef049512d2d30cbfc1a91acd5baad4a6e19e22e93176197f17" + "0000000000000000000000000000000000000000000000000000000000000000" + ), { - fromHex("28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e42832795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f"), + fromHex( + "28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e4283" + "2795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f" + ), gas_cost } }, { - fromHex("0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e0c692b41f1acc961f6ea83bae2c3a1a55c54f766c63ba76989f52c149c17b5e70000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a" + "18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e" + "0c692b41f1acc961f6ea83bae2c3a1a55c54f766c63ba76989f52c149c17b5e7" + "0000000000000000000000000000000000000000000000000000000000000000" + ), { - fromHex("258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6"), + fromHex( + "258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6" + "175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6" + ), gas_cost } }, { - fromHex("0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b0ea71d0abb524cac7cfff5323e1d0b14ab705842426c978f96753ccce258ed930000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d" + "0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b" + "0ea71d0abb524cac7cfff5323e1d0b14ab705842426c978f96753ccce258ed93" + "0000000000000000000000000000000000000000000000000000000000000000" + ), { - fromHex("2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d"), + fromHex( + "2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d" + "2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d" + ), gas_cost } }, { - fromHex("111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b3000000000000000000000000000000000000000e40800000000000000008cdcbc0000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f" + "1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b30" + "00000000000000000000000000000000000000e40800000000000000008cdcbc" + "0000000000000000000000000000000000000000000000000000000000000000" + ), { - fromHex("25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b20050d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8"), + fromHex( + "25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b2005" + "0d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8" + ), gas_cost } }, { - fromHex("17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc502b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a11887420878c0c8e37605291c626585eabbec8d8b97a848fe8d58a37b004583510000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc5" + "02b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a1" + "1887420878c0c8e37605291c626585eabbec8d8b97a848fe8d58a37b00458351" + "0000000000000000000000000000000000000000000000000000000000000000" + ), { - fromHex("2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6"), + fromHex( + "2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b" + "05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6" + ), gas_cost } }, { - fromHex("1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db016086cc934d5cab679c6991a4efcedbab26d7e4fb23b6a1ad4e6b5c2fb59ce50000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f" + "042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db" + "016086cc934d5cab679c6991a4efcedbab26d7e4fb23b6a1ad4e6b5c2fb59ce5" + "0000000000000000000000000000000000000000000000000000000000000000" + ), { - fromHex("1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d"), + fromHex( + "1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf" + "28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d" + ), gas_cost } }, { - fromHex("1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb1eec35a0e955cad4bee5846ae0f1d0b742d8636b278450c534e38e06a60509f90000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc" + "2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb" + "1eec35a0e955cad4bee5846ae0f1d0b742d8636b278450c534e38e06a60509f9" + "0000000000000000000000000000000000000000000000000000000000000000" + ), { - fromHex("1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d501202254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c"), + fromHex( + "1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012" + "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c" + ), gas_cost } }, { - fromHex("232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f82ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda70689c3dc4311426ee11707866b2cbdf9751dacd07245bf99d2113d3f5a8cac470000000000000000000000000000000000000000000000000000000000000000"), + fromHex( + "232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f8" + "2ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda7" + "0689c3dc4311426ee11707866b2cbdf9751dacd07245bf99d2113d3f5a8cac47" + "0000000000000000000000000000000000000000000000000000000000000000" + ), { - fromHex("2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a7071d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5"), + fromHex( + "2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a707" + "1d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5" + ), gas_cost } } @@ -1184,7 +1272,8 @@ evmc::Result EVMHost::precompileBlake2f(evmc_message const&) noexcept evmc::Result EVMHost::precompileGeneric( evmc_message const& _message, - std::map const& _inOut) noexcept + std::map const& _inOut +) noexcept { bytes input(_message.input_data, _message.input_data + _message.input_size); if (_inOut.count(input)) From 8834c4ee2f97c0511498d6bd83483fa3b3f91701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 27 Jan 2025 16:22:05 +0100 Subject: [PATCH 0671/1340] EVMHost: Remove extra zeros from hard-coded ecAdd/ecMull inputs --- test/EVMHost.cpp | 41 ------------------- .../semanticTests/externalContracts/snark.sol | 16 ++++---- 2 files changed, 8 insertions(+), 49 deletions(-) diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index f18140dac..38752dde6 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -664,8 +664,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000000" "1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012" "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -681,8 +679,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000002" "0000000000000000000000000000000000000000000000000000000000000001" "0000000000000000000000000000000000000000000000000000000000000002" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -698,8 +694,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000002" "0000000000000000000000000000000000000000000000000000000000000001" "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -715,8 +709,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "09f5528bdb0ef9354837a0f4b4c9da973bd5b805d359976f719ab0b74e0a7368" "28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e4283" "2795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -732,8 +724,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c" "1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf" "28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -749,8 +739,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "16dabf21b3f25b9665269d98dc17b1da6118251dc0b403ae50e96dfe91239375" "25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b2005" "0d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -766,8 +754,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "1b5ed0e9e8f3ff35589ea81a45cf63887d4a92c099a3be1d97b26f0db96323dd" "16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc" "1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -783,8 +769,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41" "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2" "16da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -800,8 +784,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "1d1f2259c715327bedb42c095af6c0267e4e1be836b4e04b3f0502552f93cca9" "2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b" "05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -817,8 +799,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "0185fbba22de9e698262925665735dbc4d6e8288bc3fc39fae10ca58e16e77f7" "258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6" "175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -834,8 +814,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b" "1496064626ba8bffeb7805f0d16143a65649bb0850333ea512c03fcdaf31e254" "07b4f210ab542533f1ee5633ae4406cd16c63494b537ce3f1cf4afff6f76a48f" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -851,8 +829,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b" "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59" "3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -868,8 +844,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "26dd3d225c9a71476db0cf834232eba84020f3073c6d20c519963e0b98f235e1" "2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a707" "1d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -885,8 +859,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "13cf106acf943c2a331de21c7d5e3351354e7412f2dba2918483a6593a6828d4" "2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d" "2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -902,8 +874,6 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex "2c7cdf62c2498486fd52646e577a06723ce97737b3c958262d78c4a413661e8a" "0aee46a7ea6e80a3675026dfa84019deee2a2dedb1bbe11d7fe124cb3efb4b5a" "044747b6e9176e13ede3a4dfd0d33ccca6321b9acd23bf3683a60adc0366ebaf" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -931,7 +901,6 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000001" "0000000000000000000000000000000000000000000000000000000000000002" "0000000000000000000000000000000000000000000000000000000000000002" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -946,7 +915,6 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex "0000000000000000000000000000000000000000000000000000000000000001" "0000000000000000000000000000000000000000000000000000000000000002" "0000000000000000000000000000000000000000000000000000000000000005" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -961,7 +929,6 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex "09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe" "18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4" "030f7b0c405c888aff922307ea2cd1c70f64664bab76899500341f4260a20929" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -976,7 +943,6 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex "0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a" "04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e" "1551dcd4965285ef049512d2d30cbfc1a91acd5baad4a6e19e22e93176197f17" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -991,7 +957,6 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex "0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a" "18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e" "0c692b41f1acc961f6ea83bae2c3a1a55c54f766c63ba76989f52c149c17b5e7" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -1006,7 +971,6 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex "0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d" "0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b" "0ea71d0abb524cac7cfff5323e1d0b14ab705842426c978f96753ccce258ed93" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -1021,7 +985,6 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex "111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f" "1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b30" "00000000000000000000000000000000000000e40800000000000000008cdcbc" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -1036,7 +999,6 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex "17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc5" "02b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a1" "1887420878c0c8e37605291c626585eabbec8d8b97a848fe8d58a37b00458351" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -1051,7 +1013,6 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex "1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f" "042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db" "016086cc934d5cab679c6991a4efcedbab26d7e4fb23b6a1ad4e6b5c2fb59ce5" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -1066,7 +1027,6 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex "1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc" "2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb" "1eec35a0e955cad4bee5846ae0f1d0b742d8636b278450c534e38e06a60509f9" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( @@ -1081,7 +1041,6 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex "232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f8" "2ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda7" "0689c3dc4311426ee11707866b2cbdf9751dacd07245bf99d2113d3f5a8cac47" - "0000000000000000000000000000000000000000000000000000000000000000" ), { fromHex( diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index 2b1fe023e..c073993e1 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -37,7 +37,7 @@ library Pairing { /// @return r the sum of two points of G1 function add(G1Point memory p1, G1Point memory p2) internal returns (G1Point memory r) { - uint[6] memory input; + uint[4] memory input; input[0] = p1.X; input[1] = p1.Y; input[2] = p2.X; @@ -50,7 +50,7 @@ library Pairing { /// @return r the product of a point on G1 and a scalar, i.e. /// p == p.mul(1) and p.add(p) == p.mul(2) for all points p. function mul(G1Point memory p, uint s) internal returns (G1Point memory r) { - uint[4] memory input; + uint[3] memory input; input[0] = p.X; input[1] = p.Y; input[2] = s; @@ -292,11 +292,11 @@ contract Test { // f() -> true // g() -> true // pair() -> true -// gas irOptimized: 275319 -// gas legacy: 293854 -// gas legacyOptimized: 276409 +// gas irOptimized: 275229 +// gas legacy: 293579 +// gas legacyOptimized: 276313 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." -// gas irOptimized: 821446 -// gas legacy: 914211 -// gas legacyOptimized: 820319 +// gas irOptimized: 818076 +// gas legacy: 904397 +// gas legacyOptimized: 816770 From 87c0b6b46f1dbb391b67d50989e3d28b4bba011d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 28 Jan 2025 16:41:40 +0100 Subject: [PATCH 0672/1340] EVMHost: Ignore trailing input in ecRecover, ecAdd and ecMul precompiles - Our mock implementation only worked for the exact hard-coded inputs we had and failed if there were any trailing bytes. Real precompiles would ignore those bytes. --- test/EVMHost.cpp | 24 +++++++++++--- test/EVMHost.h | 12 ++++++- .../precompiles_ignoring_trailing_input.sol | 32 +++++++++++++++++++ 3 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 test/libsolidity/semanticTests/isoltestTesting/precompiles_ignoring_trailing_input.sol diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 38752dde6..a3d1d427d 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -507,7 +507,7 @@ evmc::Result EVMHost::precompileECRecover(evmc_message const& _message) noexcept } } }; - evmc::Result result = precompileGeneric(_message, inputOutput); + evmc::Result result = precompileGeneric(_message, inputOutput, true /* _ignoresTrailingInput */); // ECRecover will return success with empty response in case of failure if (result.status_code != EVMC_SUCCESS && result.status_code != EVMC_OUT_OF_GAS) return resultWithGas(_message.gas, gas_cost, {}); @@ -884,7 +884,7 @@ evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex } } }; - return precompileGeneric(_message, inputOutput); + return precompileGeneric(_message, inputOutput, true /* _ignoresTrailingInput */); } template @@ -1051,7 +1051,7 @@ evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex } } }; - return precompileGeneric(_message, inputOutput); + return precompileGeneric(_message, inputOutput, true /* _ignoresTrailingInput */); } template @@ -1220,6 +1220,7 @@ evmc::Result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess } } }; + return precompileGeneric(_message, inputOutput); } @@ -1231,10 +1232,23 @@ evmc::Result EVMHost::precompileBlake2f(evmc_message const&) noexcept evmc::Result EVMHost::precompileGeneric( evmc_message const& _message, - std::map const& _inOut + std::map const& _inOut, + bool _ignoresTrailingInput ) noexcept { - bytes input(_message.input_data, _message.input_data + _message.input_size); + size_t meaningfulInputSize = _message.input_size; + if (_ignoresTrailingInput && !_inOut.empty()) + { + // _ignoresTrailingInput only implemented for the case where all inputs have same size. + // Simpler to implement and it's all we need for now. + for (auto const& [input, output]: _inOut) + solAssert(input.size() == _inOut.begin()->first.size()); + + // If there is more input that expected, precompiles tend to simply ignore it. + meaningfulInputSize = std::min(_message.input_size, _inOut.begin()->first.size()); + } + + bytes input(_message.input_data, _message.input_data + meaningfulInputSize); if (_inOut.count(input)) { auto const& ret = _inOut.at(input); diff --git a/test/EVMHost.h b/test/EVMHost.h index 121adbc15..522eb7b72 100644 --- a/test/EVMHost.h +++ b/test/EVMHost.h @@ -124,7 +124,17 @@ class EVMHost: public evmc::MockedHost template static evmc::Result precompileALTBN128PairingProduct(evmc_message const& _message) noexcept; static evmc::Result precompileBlake2f(evmc_message const& _message) noexcept; - static evmc::Result precompileGeneric(evmc_message const& _message, std::map const& _inOut) noexcept; + /// Generic implementation of a precompile for testing, with hard-coded answers for hard-coded inputs. + /// @param _message EVM message to handle. + /// @param _inOut Hard-coded inputs and corresponding outputs to be returned. + /// @param _ignoresTrailingInput Enable if the precompile only cares about the initial part of + /// its input and works exactly the same, regardless of what's in the remaining part. The message will + /// be considered a match for a test input even if it's longer. + static evmc::Result precompileGeneric( + evmc_message const& _message, + std::map const& _inOut, + bool _ignoresTrailingInput = false + ) noexcept; /// @returns a result object with gas usage and result data taken from @a _data. /// The outcome will be a failure if the limit < required. /// @note The return value is only valid as long as @a _data is alive! diff --git a/test/libsolidity/semanticTests/isoltestTesting/precompiles_ignoring_trailing_input.sol b/test/libsolidity/semanticTests/isoltestTesting/precompiles_ignoring_trailing_input.sol new file mode 100644 index 000000000..920c6b06e --- /dev/null +++ b/test/libsolidity/semanticTests/isoltestTesting/precompiles_ignoring_trailing_input.sol @@ -0,0 +1,32 @@ +contract C { + function ecRecover(uint[4] memory input) public returns (bytes memory) { + (bool success, bytes memory encodedOutput) = address(1).call(abi.encode(input)); + require(success); + return encodedOutput; + } + + function ecAdd(uint[4] memory input) public returns (bytes memory) { + (bool success, bytes memory encodedOutput) = address(6).call(abi.encode(input)); + require(success); + return encodedOutput; + } + + function ecMul(uint[3] memory input) public returns (bytes memory) { + (bool success, bytes memory encodedOutput) = address(7).call(abi.encode(input)); + require(success); + return encodedOutput; + } +} +// ---- +// ecRecover(uint256[4]): 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c, 0x000000000000000000000000000000000000000000000000000000000000001c, 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f, 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549 -> 0x20, 0x20, 966588469268559010541288244128342317224451555083 +// ecRecover(uint256[4]): 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c, 0x000000000000000000000000000000000000000000000000000000000000001c, 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f, 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549, 0x01, 0x02, 0x03 -> 0x20, 0x20, 966588469268559010541288244128342317224451555083 + +// ecAdd(uint256[4]): 0x01, 0x02, 0x01, 0x02 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecAdd(uint256[4]): 0x01, 0x02, 0x01, 0x02, 0x01 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecAdd(uint256[4]): 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecAdd(uint256[4]): 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 + +// ecMul(uint256[3]): 0x01, 0x02, 0x02 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecMul(uint256[3]): 0x01, 0x02, 0x02, 0x01 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecMul(uint256[3]): 0x01, 0x02, 0x02, 0x01, 0x02 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 +// ecMul(uint256[3]): 0x01, 0x02, 0x02, 0x01, 0x02, 0x03 -> 0x20, 0x40, 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764 From 349e7fc86c8ffd84fdc2765e9d7f9d71ccca192f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 28 Jan 2025 16:38:42 +0100 Subject: [PATCH 0673/1340] EVMHost: Report unexpected precompile input as a test error rather than a revert - Currently it looks as if EVM reverted, but we should make it clear that we simply don't have a hard-coded value matching the input - Some tests were relying on this behavior - they need specific hard-coded outputs. --- test/EVMHost.cpp | 31 ++++++++++++++++++- .../failing_ecrecover_invalid_input.sol | 4 +-- .../bare_call_no_returndatacopy.sol | 3 +- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index a3d1d427d..897f01c68 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -505,6 +505,30 @@ evmc::Result EVMHost::precompileECRecover(evmc_message const& _message) noexcept fromHex("0000000000000000000000008743523d96a1b2cbe0c6909653a56da18ed484af"), gas_cost } + }, + { + fromHex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "0000000000000000000000000000000000000000000000000000000000000001" + "0000000000000000000000000000000000000000000000000000000000000002" + "0000000000000000000000000000000000000000000000000000000000000003" + ), + { + fromHex(""), + gas_cost + } + }, + { + fromHex( + "77e5189111eb6557e8a637b27ef8fbb15bc61d61c2f00cc48878f3a296e5e0ca" + "0000000000000000000000000000000000000000000000000000000000000000" + "6944c77849b18048f6abe0db8084b0d0d0689cdddb53d2671c36967b58691ad4" + "ef4f06ba4f78319baafd0424365777241af4dfd3da840471b4b4b087b7750d0d" + ), + { + fromHex(""), + gas_cost + } } }; evmc::Result result = precompileGeneric(_message, inputOutput, true /* _ignoresTrailingInput */); @@ -1255,7 +1279,12 @@ evmc::Result EVMHost::precompileGeneric( return resultWithGas(_message.gas, ret.gas_used, ret.output); } else - return resultWithFailure(); + // FIXME: We're in a noexcept function; this will result in terminate() and then abort(). + // Still better than nothing - can't be mistaken for revert and Boost will report test name. + solThrow( + Exception, + "Test output for a precompile not defined for input: " + toHex(input, HexPrefix::Add) + ); } evmc::Result EVMHost::resultWithFailure() noexcept diff --git a/test/libsolidity/semanticTests/ecrecover/failing_ecrecover_invalid_input.sol b/test/libsolidity/semanticTests/ecrecover/failing_ecrecover_invalid_input.sol index 55621bdcd..ee3f4c6be 100644 --- a/test/libsolidity/semanticTests/ecrecover/failing_ecrecover_invalid_input.sol +++ b/test/libsolidity/semanticTests/ecrecover/failing_ecrecover_invalid_input.sol @@ -1,7 +1,7 @@ contract C { // ecrecover should return zero for malformed input - // (v should be 27 or 28, not 1) - // Note that the precompile does not return zero but returns nothing. + // (v should be 27 or 28, not 1) + // Note that the precompile does not return zero but returns nothing. function f() public returns (address) { return ecrecover(bytes32(type(uint256).max), 1, bytes32(uint(2)), bytes32(uint(3))); } diff --git a/test/libsolidity/semanticTests/functionCall/bare_call_no_returndatacopy.sol b/test/libsolidity/semanticTests/functionCall/bare_call_no_returndatacopy.sol index 17b6f74c8..3b3afab3b 100644 --- a/test/libsolidity/semanticTests/functionCall/bare_call_no_returndatacopy.sol +++ b/test/libsolidity/semanticTests/functionCall/bare_call_no_returndatacopy.sol @@ -1,6 +1,7 @@ contract C { function f() public returns (bool) { - (bool success, ) = address(1).call(""); + // Random address, no contract deployed to it. + (bool success, ) = address(0xffff).call(""); return success; } } From caa37d30afe0efe402e9b0f89fda54796c138567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 30 Jan 2025 18:54:56 +0100 Subject: [PATCH 0674/1340] isoltest: Remove duplicate warning about not enforcing gas expectations --- test/soltest.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/soltest.cpp b/test/soltest.cpp index 8e7a3ddcd..9bc60d118 100644 --- a/test/soltest.cpp +++ b/test/soltest.cpp @@ -230,9 +230,6 @@ test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) if (solidity::test::CommonOptions::get().disableSemanticTests) std::cout << std::endl << "--- SKIPPING ALL SEMANTICS TESTS ---" << std::endl << std::endl; - if (!solidity::test::CommonOptions::get().enforceGasTest) - std::cout << std::endl << "WARNING :: Gas Cost Expectations are not being enforced" << std::endl << std::endl; - Batcher batcher(CommonOptions::get().selectedBatch, CommonOptions::get().batches); if (CommonOptions::get().batches > 1) std::cout << "Batch " << CommonOptions::get().selectedBatch << " out of " << CommonOptions::get().batches << std::endl; From eb56b4bfe6fe9996342b27d4fc6a4001725d4446 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 31 Jan 2025 20:12:15 +0100 Subject: [PATCH 0675/1340] SMTChecker: Remove code left over after switch to SMT-LIB interface This is the last occurence of the HAVE_Z3 macro in the codebase. --- libsolidity/formal/BMC.cpp | 11 ----------- scripts/error_codes.py | 1 - 2 files changed, 12 deletions(-) diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 86c7eb7a8..5fb2f5a9f 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -58,17 +58,6 @@ BMC::BMC( if (_settings.solvers.z3 ) solvers.emplace_back(std::make_unique(_smtCallback, _settings.timeout)); m_interface = std::make_unique(std::move(solvers), _settings.timeout); -#if defined (HAVE_Z3) - if (m_settings.solvers.z3) - if (!_smtlib2Responses.empty()) - m_errorReporter.warning( - 5622_error, - "SMT-LIB2 query responses were given in the auxiliary input, " - "but this Solidity binary uses an SMT solver Z3 directly." - "These responses will be ignored." - "Consider disabling Z3 at compilation time in order to use SMT-LIB2 responses." - ); -#endif } void BMC::analyze(SourceUnit const& _source, std::map, smt::EncodingContext::IdCompare> _solvedTargets) diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 50021d986..d99d60c6e 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -246,7 +246,6 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "4802", "4902", "5272", - "5622", "5798", "5840", "7128", From 8fc863d3bb47f0df760cff3e825f21c00216a9c8 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Sat, 1 Feb 2025 10:14:26 +0100 Subject: [PATCH 0676/1340] eof: `objectCompiler` tests updating --- test/libyul/objectCompiler/data.yul | 2 + test/libyul/objectCompiler/datacopy.yul | 1 + .../libyul/objectCompiler/dataoffset_code.yul | 1 + .../libyul/objectCompiler/dataoffset_data.yul | 1 + .../libyul/objectCompiler/dataoffset_self.yul | 1 + test/libyul/objectCompiler/datasize_code.yul | 1 + test/libyul/objectCompiler/datasize_data.yul | 1 + test/libyul/objectCompiler/datasize_self.yul | 1 + .../eof/leading_and_trailing_dots.yul | 30 +++++ .../objectCompiler/eof/long_object_name.yul | 33 +++++ test/libyul/objectCompiler/eof/simple.yul | 19 +++ test/libyul/objectCompiler/eof/smoke.yul | 12 ++ test/libyul/objectCompiler/eof/subObject.yul | 29 +++++ .../objectCompiler/eof/subSubObject.yul | 49 ++++++++ .../objectCompiler/eof/verbatim_bug.yul | 118 ++++++++++++++++++ .../libyul/objectCompiler/function_series.yul | 1 + ...identical_subobjects_creation_deployed.yul | 4 +- .../identical_subobjects_full_debug_info.yul | 4 +- .../identical_subobjects_no_debug_info.yul | 4 +- ...dentical_subobjects_partial_debug_info.yul | 4 +- ...bobjects_partial_debug_info_no_use_src.yul | 4 +- ...cal_subobjects_with_subject_references.yul | 5 +- ..._long_name_does_not_end_up_in_bytecode.yul | 1 + test/libyul/objectCompiler/jump_tags.yul | 1 + .../leading_and_trailing_dots.yul | 5 +- test/libyul/objectCompiler/linkersymbol.yul | 29 ++--- .../objectCompiler/long_object_name.yul | 5 +- test/libyul/objectCompiler/manySubObjects.yul | 5 +- test/libyul/objectCompiler/metadata.yul | 1 + test/libyul/objectCompiler/namedObject.yul | 4 +- .../libyul/objectCompiler/namedObjectCode.yul | 4 +- .../objectCompiler/nested_optimizer.yul | 4 +- test/libyul/objectCompiler/simple.yul | 1 + .../objectCompiler/simple_optimizer.yul | 4 +- test/libyul/objectCompiler/smoke.yul | 1 + .../libyul/objectCompiler/sourceLocations.yul | 1 + test/libyul/objectCompiler/subObject.yul | 1 + .../libyul/objectCompiler/subObjectAccess.yul | 1 + test/libyul/objectCompiler/subSubObject.yul | 1 + test/libyul/objectCompiler/verbatim_bug.yul | 5 +- 40 files changed, 339 insertions(+), 60 deletions(-) create mode 100644 test/libyul/objectCompiler/eof/leading_and_trailing_dots.yul create mode 100644 test/libyul/objectCompiler/eof/long_object_name.yul create mode 100644 test/libyul/objectCompiler/eof/simple.yul create mode 100644 test/libyul/objectCompiler/eof/smoke.yul create mode 100644 test/libyul/objectCompiler/eof/subObject.yul create mode 100644 test/libyul/objectCompiler/eof/subSubObject.yul create mode 100644 test/libyul/objectCompiler/eof/verbatim_bug.yul diff --git a/test/libyul/objectCompiler/data.yul b/test/libyul/objectCompiler/data.yul index 4447a0b8e..53eb24ce1 100644 --- a/test/libyul/objectCompiler/data.yul +++ b/test/libyul/objectCompiler/data.yul @@ -1,10 +1,12 @@ object "a" { code {} // Unreferenced data is not added to the assembled bytecode. + // TODO: This is not implemented for EOF. Should work for legacy and EOF when implemented. data "str" "Hello, World!" } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":22:29 */ diff --git a/test/libyul/objectCompiler/datacopy.yul b/test/libyul/objectCompiler/datacopy.yul index 46a0ec0f7..ea00b4478 100644 --- a/test/libyul/objectCompiler/datacopy.yul +++ b/test/libyul/objectCompiler/datacopy.yul @@ -13,6 +13,7 @@ object "a" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":77:92 */ diff --git a/test/libyul/objectCompiler/dataoffset_code.yul b/test/libyul/objectCompiler/dataoffset_code.yul index 1171303af..2a1aa04a1 100644 --- a/test/libyul/objectCompiler/dataoffset_code.yul +++ b/test/libyul/objectCompiler/dataoffset_code.yul @@ -7,6 +7,7 @@ object "a" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":44:61 */ diff --git a/test/libyul/objectCompiler/dataoffset_data.yul b/test/libyul/objectCompiler/dataoffset_data.yul index 381cb999f..949098681 100644 --- a/test/libyul/objectCompiler/dataoffset_data.yul +++ b/test/libyul/objectCompiler/dataoffset_data.yul @@ -4,6 +4,7 @@ object "a" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":56:75 */ diff --git a/test/libyul/objectCompiler/dataoffset_self.yul b/test/libyul/objectCompiler/dataoffset_self.yul index b6a0552cb..9f82f5568 100644 --- a/test/libyul/objectCompiler/dataoffset_self.yul +++ b/test/libyul/objectCompiler/dataoffset_self.yul @@ -4,6 +4,7 @@ object "a" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":44:59 */ diff --git a/test/libyul/objectCompiler/datasize_code.yul b/test/libyul/objectCompiler/datasize_code.yul index 7bf365031..db2fee4d8 100644 --- a/test/libyul/objectCompiler/datasize_code.yul +++ b/test/libyul/objectCompiler/datasize_code.yul @@ -7,6 +7,7 @@ object "a" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":44:59 */ diff --git a/test/libyul/objectCompiler/datasize_data.yul b/test/libyul/objectCompiler/datasize_data.yul index f0ae32b1b..52afde6fc 100644 --- a/test/libyul/objectCompiler/datasize_data.yul +++ b/test/libyul/objectCompiler/datasize_data.yul @@ -4,6 +4,7 @@ object "a" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":44:61 */ diff --git a/test/libyul/objectCompiler/datasize_self.yul b/test/libyul/objectCompiler/datasize_self.yul index fb5b7fb89..93512f1da 100644 --- a/test/libyul/objectCompiler/datasize_self.yul +++ b/test/libyul/objectCompiler/datasize_self.yul @@ -4,6 +4,7 @@ object "a" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":36:49 */ diff --git a/test/libyul/objectCompiler/eof/leading_and_trailing_dots.yul b/test/libyul/objectCompiler/eof/leading_and_trailing_dots.yul new file mode 100644 index 000000000..f62e24233 --- /dev/null +++ b/test/libyul/objectCompiler/eof/leading_and_trailing_dots.yul @@ -0,0 +1,30 @@ +{ + function e(_._) { + e(0) + } + e(2) + function f(n._) { + f(0) + } + f(2) + function g(_.n) { + g(0) + } + g(2) +} +// ==== +// bytecodeFormat: >=EOFv1 +// outputs: Assembly +// ---- +// Assembly: +// /* "source":53:54 */ +// 0x02 +// /* "source":51:55 */ +// jumpf{code_section_1} +// +// code_section_1: assembly { +// /* "source":136:137 */ +// 0x00 +// /* "source":134:138 */ +// jumpf{code_section_1} +// } diff --git a/test/libyul/objectCompiler/eof/long_object_name.yul b/test/libyul/objectCompiler/eof/long_object_name.yul new file mode 100644 index 000000000..680a26888 --- /dev/null +++ b/test/libyul/objectCompiler/eof/long_object_name.yul @@ -0,0 +1,33 @@ +object "t" { + code { + sstore(0, eofcreate("name_that_is_longer_than_32_bytes_name_that_is_longer_than_32_bytes_name_that_is_longer_than_32_bytes", 0, 0, 0, 0)) + } + object "name_that_is_longer_than_32_bytes_name_that_is_longer_than_32_bytes_name_that_is_longer_than_32_bytes" { + code {} + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// optimizationPreset: full +// outputs: Assembly +// ---- +// Assembly: +// /* "source":180:181 */ +// 0x00 +// /* "source":56:182 */ +// dup1 +// dup1 +// dup1 +// eofcreate{0} +// /* "source":53:54 */ +// 0x00 +// /* "source":46:183 */ +// sstore +// /* "source":22:199 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":330:337 */ +// stop +// } diff --git a/test/libyul/objectCompiler/eof/simple.yul b/test/libyul/objectCompiler/eof/simple.yul new file mode 100644 index 000000000..cfb95fbec --- /dev/null +++ b/test/libyul/objectCompiler/eof/simple.yul @@ -0,0 +1,19 @@ +{ + sstore(0, 1) +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":41:42 */ +// 0x01 +// /* "source":38:39 */ +// 0x00 +// /* "source":31:43 */ +// sstore +// /* "source":27:47 */ +// stop +// Bytecode: ef00010100040200010005040000000080000260015f5500 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP SDIV DIV STOP STOP STOP STOP DUP1 STOP MUL PUSH1 0x1 PUSH0 SSTORE STOP +// SourceMappings: 41:1:0:-:0;38;31:12;27:20 diff --git a/test/libyul/objectCompiler/eof/smoke.yul b/test/libyul/objectCompiler/eof/smoke.yul new file mode 100644 index 000000000..eecfac9a8 --- /dev/null +++ b/test/libyul/objectCompiler/eof/smoke.yul @@ -0,0 +1,12 @@ +{ +} +// ==== +// EVMVersion: >=constantinople +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":27:34 */ +// stop +// Bytecode: ef00010100040200010001040000000080000000 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP +// SourceMappings: 27:7:0:-:0 diff --git a/test/libyul/objectCompiler/eof/subObject.yul b/test/libyul/objectCompiler/eof/subObject.yul new file mode 100644 index 000000000..2f1771d79 --- /dev/null +++ b/test/libyul/objectCompiler/eof/subObject.yul @@ -0,0 +1,29 @@ +object "a" { + code {} + // Unreferenced data is not added to the assembled bytecode. + // TODO: This is not implemented for EOF. Uncomment line below when implemented. + // data "str" "Hello, World!" + // Unreferenced object is not added to the assembled bytecode. + object "sub" { code { sstore(0, 1) } } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":22:29 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":76:77 */ +// 0x01 +// /* "source":73:74 */ +// 0x00 +// /* "source":66:78 */ +// sstore +// /* "source":62:82 */ +// stop +// } +// Bytecode: ef00010100040200010001040000000080000000 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP +// SourceMappings: 22:7:0:-:0 diff --git a/test/libyul/objectCompiler/eof/subSubObject.yul b/test/libyul/objectCompiler/eof/subSubObject.yul new file mode 100644 index 000000000..39dd209bf --- /dev/null +++ b/test/libyul/objectCompiler/eof/subSubObject.yul @@ -0,0 +1,49 @@ +object "a" { + code {} + // Unreferenced data is not added to the assembled bytecode. + // TODO: This is not implemented for EOF. Uncomment line below when implemented. + // data "str" "Hello, World!" + // Unreferenced object is not added to the assembled bytecode. + object "sub" { + code { sstore(0, 1) } + object "subsub" { + code { sstore(2, 3) } + data "str" hex"123456" + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// Assembly: +// /* "source":22:29 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":76:77 */ +// 0x01 +// /* "source":73:74 */ +// 0x00 +// /* "source":66:78 */ +// sstore +// /* "source":62:82 */ +// stop +// stop +// +// sub_0: assembly { +// /* "source":140:141 */ +// 0x03 +// /* "source":137:138 */ +// 0x02 +// /* "source":130:142 */ +// sstore +// /* "source":126:146 */ +// stop +// stop +// data_6adf031833174bbe4c85eafe59ddb54e6584648c2c962c6f94791ab49caa0ad4 123456 +// } +// } +// Bytecode: ef00010100040200010001040000000080000000 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP +// SourceMappings: 22:7:0:-:0 diff --git a/test/libyul/objectCompiler/eof/verbatim_bug.yul b/test/libyul/objectCompiler/eof/verbatim_bug.yul new file mode 100644 index 000000000..704702a53 --- /dev/null +++ b/test/libyul/objectCompiler/eof/verbatim_bug.yul @@ -0,0 +1,118 @@ +object "a" { + code { + let dummy := 0xAABBCCDDEEFF + let input := sload(0) + let output + + switch input + case 0x00 { + // Note that due to a bug the following disappeared from the assembly output. + output := verbatim_1i_1o(hex"506000", dummy) + } + case 0x01 { + output := 1 + } + case 0x02 { + output := verbatim_1i_1o(hex"506002", dummy) + } + case 0x03 { + output := 3 + } + + sstore(0, output) + } +} +// ==== +// EVMVersion: >=shanghai +// bytecodeFormat: >=EOFv1 +// optimizationPreset: full +// outputs: Assembly +// ---- +// Assembly: +// /* "source":65:66 */ +// 0x00 +// /* "source":59:67 */ +// sload +// /* "source":94:95 */ +// 0x00 +// /* "source":108:406 */ +// swap1 +// /* "source":133:225 */ +// dup1 +// /* "source":138:142 */ +// 0x00 +// /* "source":133:225 */ +// eq +// rjumpi{tag_1} +// /* "source":108:406 */ +// tag_2: +// /* "source":238:263 */ +// dup1 +// /* "source":243:247 */ +// 0x01 +// /* "source":238:263 */ +// eq +// rjumpi{tag_3} +// /* "source":108:406 */ +// tag_4: +// /* "source":276:368 */ +// dup1 +// /* "source":281:285 */ +// 0x02 +// /* "source":276:368 */ +// eq +// rjumpi{tag_5} +// /* "source":108:406 */ +// tag_6: +// /* "source":386:390 */ +// 0x03 +// /* "source":381:406 */ +// eq +// rjumpi{tag_7} +// /* "source":108:406 */ +// tag_8: +// /* "source":426:427 */ +// 0x00 +// /* "source":419:436 */ +// sstore +// /* "source":108:406 */ +// stop +// /* "source":391:406 */ +// tag_7: +// /* "source":393:404 */ +// pop +// /* "source":403:404 */ +// 0x03 +// /* "source":391:406 */ +// rjump{tag_8} +// /* "source":286:368 */ +// tag_5: +// /* "source":314:354 */ +// pop +// pop +// /* "source":339:353 */ +// 0xaabbccddeeff +// /* "source":314:354 */ +// verbatimbytecode_506002 +// /* "source":286:368 */ +// rjump{tag_8} +// /* "source":248:263 */ +// tag_3: +// /* "source":250:261 */ +// pop +// pop +// /* "source":260:261 */ +// 0x01 +// /* "source":248:263 */ +// rjump{tag_8} +// /* "source":143:225 */ +// tag_1: +// /* "source":171:211 */ +// pop +// pop +// /* "source":196:210 */ +// 0xaabbccddeeff +// /* "source":171:211 */ +// verbatimbytecode_506000 +// /* "source":143:225 */ +// rjump{tag_8} diff --git a/test/libyul/objectCompiler/function_series.yul b/test/libyul/objectCompiler/function_series.yul index 8750f1649..fd5a5d6c0 100644 --- a/test/libyul/objectCompiler/function_series.yul +++ b/test/libyul/objectCompiler/function_series.yul @@ -13,6 +13,7 @@ object "Contract" { // ==== // EVMVersion: >=shanghai // optimizationPreset: none +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":33:48 */ diff --git a/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul b/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul index 01270ef44..4a29c1498 100644 --- a/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul +++ b/test/libyul/objectCompiler/identical_subobjects_creation_deployed.yul @@ -66,6 +66,7 @@ object "A" { // ==== // EVMVersion: >=constantinople // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // sstore(calldataload(sub(shl(0xff, 0x01), shl(0x7f, 0x01))), calldataload(0x01)) @@ -103,6 +104,3 @@ object "A" { // sstore(calldataload(sub(shl(0xff, 0x01), shl(0x7f, 0x01))), calldataload(0x01)) // stop // } -// Bytecode: 6001356001607f1b600160ff1b03355500fe -// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH1 0x1 PUSH1 0x7F SHL PUSH1 0x1 PUSH1 0xFF SHL SUB CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: :::-:0;;;;;;;;;;; diff --git a/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul index 88ec2c354..9bd6413c9 100644 --- a/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul +++ b/test/libyul/objectCompiler/identical_subobjects_full_debug_info.yul @@ -66,6 +66,7 @@ object "A" { // ==== // EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "A.sol":10:20 */ @@ -110,6 +111,3 @@ object "A" { // sstore(calldataload(0x00), calldataload(0x01)) // stop // } -// Bytecode: 6001355f355500fe -// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: 10:10::-:0;-1:-1;10:10;-1:-1;10:10;-1:-1 diff --git a/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul index 309d99546..0248d61f7 100644 --- a/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul +++ b/test/libyul/objectCompiler/identical_subobjects_no_debug_info.yul @@ -52,6 +52,7 @@ object "A" { // ==== // EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "source":83:84 */ @@ -159,6 +160,3 @@ object "A" { // /* "source":938:1034 */ // stop // } -// Bytecode: 6001355f355500fe -// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: 83:1:0:-:0;70:15;66:1;53:15;46:40;22:80 diff --git a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul index 82c2fd766..10fcc202e 100644 --- a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul +++ b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info.yul @@ -71,6 +71,7 @@ object "A" { // ==== // EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "A.sol":10:20 */ @@ -147,6 +148,3 @@ object "A" { // /* "source":1674:1770 */ // stop // } -// Bytecode: 6001355f355500fe -// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: 10:10::-:0;-1:-1;10:10;-1:-1;10:10;-1:-1 diff --git a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul index 230535525..533abbdd8 100644 --- a/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul +++ b/test/libyul/objectCompiler/identical_subobjects_partial_debug_info_no_use_src.yul @@ -58,6 +58,7 @@ object "A" { // ==== // EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "source":83:84 */ @@ -165,6 +166,3 @@ object "A" { // /* "source":938:1034 */ // stop // } -// Bytecode: 6001355f355500fe -// Opcodes: PUSH1 0x1 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: 83:1:0:-:0;70:15;66:1;53:15;46:40;22:80 diff --git a/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul b/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul index 74f613cdf..c1bd855ad 100644 --- a/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul +++ b/test/libyul/objectCompiler/identical_subobjects_with_subject_references.yul @@ -96,7 +96,9 @@ object "A" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // sstore(calldataload(0x00), calldataload(dataOffset(sub_0))) @@ -162,6 +164,3 @@ object "A" { // stop // data_257dd53638d790f0311f866044a2856def338f9a4d22fce0bdeed5b2d53851a9 307862626262 // } -// Bytecode: 6008355f355500fe6008355f355500fe6008355f355500fe6008355f355500fe6008355f355500fe30786262 -// Opcodes: PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID PUSH1 0x8 CALLDATALOAD PUSH0 CALLDATALOAD SSTORE STOP INVALID ADDRESS PUSH25 0x62620000000000000000000000000000000000000000000000 -// SourceMappings: :::-:0;;;;; diff --git a/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul b/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul index 18d31087f..e77506c30 100644 --- a/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul +++ b/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul @@ -9,6 +9,7 @@ object "a" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":143:185 */ diff --git a/test/libyul/objectCompiler/jump_tags.yul b/test/libyul/objectCompiler/jump_tags.yul index 0d1f1ff79..9261c7765 100644 --- a/test/libyul/objectCompiler/jump_tags.yul +++ b/test/libyul/objectCompiler/jump_tags.yul @@ -12,6 +12,7 @@ object "Contract" { // ==== // optimizationPreset: none +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":33:54 */ diff --git a/test/libyul/objectCompiler/leading_and_trailing_dots.yul b/test/libyul/objectCompiler/leading_and_trailing_dots.yul index ddacd8b45..08dd97021 100644 --- a/test/libyul/objectCompiler/leading_and_trailing_dots.yul +++ b/test/libyul/objectCompiler/leading_and_trailing_dots.yul @@ -14,6 +14,8 @@ } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy +// outputs: Assembly // ---- // Assembly: // /* "source":53:54 */ @@ -25,6 +27,3 @@ // /* "source":134:138 */ // tag_1 // jump // in -// Bytecode: 60025b5f600256 -// Opcodes: PUSH1 0x2 JUMPDEST PUSH0 PUSH1 0x2 JUMP -// SourceMappings: 53:1:0:-:0;108:32;136:1;134:4;:::i diff --git a/test/libyul/objectCompiler/linkersymbol.yul b/test/libyul/objectCompiler/linkersymbol.yul index ba0319108..cab45afa7 100644 --- a/test/libyul/objectCompiler/linkersymbol.yul +++ b/test/libyul/objectCompiler/linkersymbol.yul @@ -2,22 +2,15 @@ object "a" { code { let addr := linkersymbol("contract/test.sol:L") mstore(128, shl(227, 0x18530aaf)) - let success := call(gas(), addr, 0, 128, 4, 128, 0) + sstore(0, balance(addr)) } } // ==== // EVMVersion: >=shanghai +// outputs: Assembly // ---- // Assembly: -// /* "source":190:191 */ -// 0x00 -// /* "source":185:188 */ -// 0x80 -// /* "source":182:183 */ -// 0x04 // /* "source":58:93 */ -// dup2 -// dup4 // linkerSymbol("f919ba91ac99f96129544b80b9516b27a80e376b9dc693819d0b18b7e0395612") // /* "source":127:137 */ // 0x18530aaf @@ -25,15 +18,15 @@ object "a" { // 0xe3 // /* "source":118:138 */ // shl +// /* "source":113:116 */ +// 0x80 // /* "source":106:139 */ -// dup4 // mstore -// /* "source":161:166 */ -// gas -// /* "source":156:192 */ -// call -// /* "source":152:193 */ +// /* "source":162:175 */ +// balance +// /* "source":159:160 */ +// 0x00 +// /* "source":152:176 */ +// sstore +// /* "source":22:192 */ // stop -// Bytecode: 5f6080600481837300000000000000000000000000000000000000006318530aaf60e31b83525af100 -// Opcodes: PUSH0 PUSH1 0x80 PUSH1 0x4 DUP2 DUP4 PUSH20 0x0 PUSH4 0x18530AAF PUSH1 0xE3 SHL DUP4 MSTORE GAS CALL STOP -// SourceMappings: 190:1:0:-:0;185:3;182:1;58:35;;;127:10;122:3;118:20;106:33;;161:5;156:36;152:41 diff --git a/test/libyul/objectCompiler/long_object_name.yul b/test/libyul/objectCompiler/long_object_name.yul index 805beb424..a1f1c7a63 100644 --- a/test/libyul/objectCompiler/long_object_name.yul +++ b/test/libyul/objectCompiler/long_object_name.yul @@ -9,6 +9,8 @@ object "t" { // ==== // EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":56:169 */ @@ -25,6 +27,3 @@ object "t" { // /* "source":317:324 */ // stop // } -// Bytecode: 60015f5500fe -// Opcodes: PUSH1 0x1 PUSH0 SSTORE STOP INVALID -// SourceMappings: 56:113:0:-:0;53:1;46:124;22:164 diff --git a/test/libyul/objectCompiler/manySubObjects.yul b/test/libyul/objectCompiler/manySubObjects.yul index 1a087f9c9..c4879f210 100644 --- a/test/libyul/objectCompiler/manySubObjects.yul +++ b/test/libyul/objectCompiler/manySubObjects.yul @@ -136,6 +136,8 @@ object "root" { } // ==== // EVMVersion: >=shanghai +// outputs: Assembly +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":59:75 */ @@ -472,6 +474,3 @@ object "root" { // stop // } // } -// Bytecode: 61005c5f55600b600155600660025560066003556006600455600660055560066006556006600755600660085560066009556006600a556006600b556006600c556006600d556006600e556006600f556006601055600c60115500fe -// Opcodes: PUSH2 0x5C PUSH0 SSTORE PUSH1 0xB PUSH1 0x1 SSTORE PUSH1 0x6 PUSH1 0x2 SSTORE PUSH1 0x6 PUSH1 0x3 SSTORE PUSH1 0x6 PUSH1 0x4 SSTORE PUSH1 0x6 PUSH1 0x5 SSTORE PUSH1 0x6 PUSH1 0x6 SSTORE PUSH1 0x6 PUSH1 0x7 SSTORE PUSH1 0x6 PUSH1 0x8 SSTORE PUSH1 0x6 PUSH1 0x9 SSTORE PUSH1 0x6 PUSH1 0xA SSTORE PUSH1 0x6 PUSH1 0xB SSTORE PUSH1 0x6 PUSH1 0xC SSTORE PUSH1 0x6 PUSH1 0xD SSTORE PUSH1 0x6 PUSH1 0xE SSTORE PUSH1 0x6 PUSH1 0xF SSTORE PUSH1 0x6 PUSH1 0x10 SSTORE PUSH1 0xC PUSH1 0x11 SSTORE STOP INVALID -// SourceMappings: 59:16:0:-:0;56:1;49:27;99:13;96:1;89:24;136:13;133:1;126:24;173:13;170:1;163:24;210:13;207:1;200:24;247:13;244:1;237:24;284:13;281:1;274:24;321:13;318:1;311:24;358:13;355:1;348:24;395:13;392:1;385:24;433:13;429:2;422:25;471:13;467:2;460:25;509:13;505:2;498:25;547:13;543:2;536:25;585:13;581:2;574:25;623:13;619:2;612:25;661:13;657:2;650:25;699:14;695:2;688:26;25:705 diff --git a/test/libyul/objectCompiler/metadata.yul b/test/libyul/objectCompiler/metadata.yul index dbd802e33..3787710e6 100644 --- a/test/libyul/objectCompiler/metadata.yul +++ b/test/libyul/objectCompiler/metadata.yul @@ -21,6 +21,7 @@ object "A" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":55:68 */ diff --git a/test/libyul/objectCompiler/namedObject.yul b/test/libyul/objectCompiler/namedObject.yul index 66727585d..d236f9ba0 100644 --- a/test/libyul/objectCompiler/namedObject.yul +++ b/test/libyul/objectCompiler/namedObject.yul @@ -3,10 +3,8 @@ object "a" { } // ==== // EVMVersion: >=constantinople +// outputs: Assembly // ---- // Assembly: // /* "source":22:29 */ // stop -// Bytecode: 00 -// Opcodes: STOP -// SourceMappings: 22:7:0:-:0 diff --git a/test/libyul/objectCompiler/namedObjectCode.yul b/test/libyul/objectCompiler/namedObjectCode.yul index efb41524b..e5d16be3e 100644 --- a/test/libyul/objectCompiler/namedObjectCode.yul +++ b/test/libyul/objectCompiler/namedObjectCode.yul @@ -3,6 +3,7 @@ object "a" { } // ==== // EVMVersion: >=shanghai +// outputs: Assembly // ---- // Assembly: // /* "source":36:37 */ @@ -13,6 +14,3 @@ object "a" { // sstore // /* "source":22:42 */ // stop -// Bytecode: 60015f5500 -// Opcodes: PUSH1 0x1 PUSH0 SSTORE STOP -// SourceMappings: 36:1:0:-:0;33;26:12;22:20 diff --git a/test/libyul/objectCompiler/nested_optimizer.yul b/test/libyul/objectCompiler/nested_optimizer.yul index 0275e1665..38b78e6dc 100644 --- a/test/libyul/objectCompiler/nested_optimizer.yul +++ b/test/libyul/objectCompiler/nested_optimizer.yul @@ -17,6 +17,7 @@ object "a" { // ==== // EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "source":58:59 */ @@ -41,6 +42,3 @@ object "a" { // /* "source":101:155 */ // stop // } -// Bytecode: 5f80355500fe -// Opcodes: PUSH0 DUP1 CALLDATALOAD SSTORE STOP INVALID -// SourceMappings: 58:1:0:-:0;41:15;;34:26;22:46 diff --git a/test/libyul/objectCompiler/simple.yul b/test/libyul/objectCompiler/simple.yul index f7f945abf..3af2c0f6a 100644 --- a/test/libyul/objectCompiler/simple.yul +++ b/test/libyul/objectCompiler/simple.yul @@ -3,6 +3,7 @@ } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":41:42 */ diff --git a/test/libyul/objectCompiler/simple_optimizer.yul b/test/libyul/objectCompiler/simple_optimizer.yul index 7348b2e20..db386a1f1 100644 --- a/test/libyul/objectCompiler/simple_optimizer.yul +++ b/test/libyul/objectCompiler/simple_optimizer.yul @@ -7,6 +7,7 @@ // ==== // EVMVersion: >=shanghai // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "source":63:64 */ @@ -18,6 +19,3 @@ // sstore // /* "source":27:73 */ // stop -// Bytecode: 5f80355500 -// Opcodes: PUSH0 DUP1 CALLDATALOAD SSTORE STOP -// SourceMappings: 63:1:0:-:0;46:15;;39:26;27:46 diff --git a/test/libyul/objectCompiler/smoke.yul b/test/libyul/objectCompiler/smoke.yul index 2ca3d62f0..06736baa8 100644 --- a/test/libyul/objectCompiler/smoke.yul +++ b/test/libyul/objectCompiler/smoke.yul @@ -2,6 +2,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":27:34 */ diff --git a/test/libyul/objectCompiler/sourceLocations.yul b/test/libyul/objectCompiler/sourceLocations.yul index a1e55ade4..756260259 100644 --- a/test/libyul/objectCompiler/sourceLocations.yul +++ b/test/libyul/objectCompiler/sourceLocations.yul @@ -30,6 +30,7 @@ object "a" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "abc.sol":0:2 */ diff --git a/test/libyul/objectCompiler/subObject.yul b/test/libyul/objectCompiler/subObject.yul index f394054d7..c10cbaac1 100644 --- a/test/libyul/objectCompiler/subObject.yul +++ b/test/libyul/objectCompiler/subObject.yul @@ -6,6 +6,7 @@ object "a" { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":22:29 */ diff --git a/test/libyul/objectCompiler/subObjectAccess.yul b/test/libyul/objectCompiler/subObjectAccess.yul index 047eae408..1ef30838f 100644 --- a/test/libyul/objectCompiler/subObjectAccess.yul +++ b/test/libyul/objectCompiler/subObjectAccess.yul @@ -67,6 +67,7 @@ object "A" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":57:72 */ diff --git a/test/libyul/objectCompiler/subSubObject.yul b/test/libyul/objectCompiler/subSubObject.yul index a7274ce63..2aa89592b 100644 --- a/test/libyul/objectCompiler/subSubObject.yul +++ b/test/libyul/objectCompiler/subSubObject.yul @@ -12,6 +12,7 @@ object "a" { } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Assembly: // /* "source":22:29 */ diff --git a/test/libyul/objectCompiler/verbatim_bug.yul b/test/libyul/objectCompiler/verbatim_bug.yul index 3858b5984..892ec13fa 100644 --- a/test/libyul/objectCompiler/verbatim_bug.yul +++ b/test/libyul/objectCompiler/verbatim_bug.yul @@ -24,7 +24,9 @@ object "a" { } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // optimizationPreset: full +// outputs: Assembly // ---- // Assembly: // /* "source":65:66 */ @@ -120,6 +122,3 @@ object "a" { // sstore // /* "source":108:406 */ // stop -// Bytecode: 5f80548015603e578060011460365780600214602657600314601f575f55005b5060035f55005b505065aabbccddeeff5060025f55005b505060015f55005b505065aabbccddeeff5060005f5500 -// Opcodes: PUSH0 DUP1 SLOAD DUP1 ISZERO PUSH1 0x3E JUMPI DUP1 PUSH1 0x1 EQ PUSH1 0x36 JUMPI DUP1 PUSH1 0x2 EQ PUSH1 0x26 JUMPI PUSH1 0x3 EQ PUSH1 0x1F JUMPI PUSH0 SSTORE STOP JUMPDEST POP PUSH1 0x3 PUSH0 SSTORE STOP JUMPDEST POP POP PUSH6 0xAABBCCDDEEFF POP PUSH1 0x2 PUSH0 SSTORE STOP JUMPDEST POP POP PUSH1 0x1 PUSH0 SSTORE STOP JUMPDEST POP POP PUSH6 0xAABBCCDDEEFF POP PUSH1 0x0 PUSH0 SSTORE STOP -// SourceMappings: 65:1:0:-:0;59:8;;133:92;;;;238:25;243:4;238:25;;;276:92;281:4;276:92;;;386:4;381:25;;;426:1;419:17;108:298;391:15;393:11;403:1;426;419:17;108:298;286:82;314:40;;339:14;314:40;426:1;419:17;108:298;248:15;250:11;;260:1;426;419:17;108:298;143:82;171:40;;196:14;171:40;426:1;419:17;108:298 From dbcc90d90e78fcd15d25fb3e17412f22a745296d Mon Sep 17 00:00:00 2001 From: irreduciblen <197363205+irreduciblen@users.noreply.github.com> Date: Sat, 1 Feb 2025 16:48:45 +0800 Subject: [PATCH 0677/1340] Fix libsolidity/ast/AST.h --- libsolidity/ast/AST.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index fa2ce2094..5cf488007 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -2054,7 +2054,7 @@ class Assignment: public Expression ): Expression(_id, _location), m_leftHandSide(std::move(_leftHandSide)), - m_assigmentOperator(_assignmentOperator), + m_assignmentOperator(_assignmentOperator), m_rightHandSide(std::move(_rightHandSide)) { solAssert(TokenTraits::isAssignmentOp(_assignmentOperator), ""); @@ -2063,12 +2063,12 @@ class Assignment: public Expression void accept(ASTConstVisitor& _visitor) const override; Expression const& leftHandSide() const { return *m_leftHandSide; } - Token assignmentOperator() const { return m_assigmentOperator; } + Token assignmentOperator() const { return m_assignmentOperator; } Expression const& rightHandSide() const { return *m_rightHandSide; } private: ASTPointer m_leftHandSide; - Token m_assigmentOperator; + Token m_assignmentOperator; ASTPointer m_rightHandSide; }; From 0cab9c6374031773e8a35b079ad67b04183e898e Mon Sep 17 00:00:00 2001 From: imilygathia <197356964+imilygathia@users.noreply.github.com> Date: Sat, 1 Feb 2025 15:13:28 +0800 Subject: [PATCH 0678/1340] tests: fix test case's name --- test/yulPhaser/TestHelpersTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/yulPhaser/TestHelpersTest.cpp b/test/yulPhaser/TestHelpersTest.cpp index 08a12f9d2..d4f698561 100644 --- a/test/yulPhaser/TestHelpersTest.cpp +++ b/test/yulPhaser/TestHelpersTest.cpp @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(countDifferences_should_count_missing_characters_as_differe BOOST_TEST(countDifferences(Chromosome("aa"), Chromosome("cccc")) == 4); } -BOOST_AUTO_TEST_CASE(enumerateOptimisationSteps_should_assing_indices_to_all_available_optimisation_steps) +BOOST_AUTO_TEST_CASE(enumerateOptimisationSteps_should_assign_indices_to_all_available_optimisation_steps) { std::map stepsAndAbbreviations = OptimiserSuite::stepNameToAbbreviationMap(); std::map stepsAndIndices = enumerateOptimisationSteps(); From 2d47ea8d914d5397b5bd15a30e9dc1170b337603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 1 Feb 2025 19:08:01 +0100 Subject: [PATCH 0679/1340] Restrict the test for trailing input in precompiles to >= byzantium EVMs --- .../isoltestTesting/precompiles_ignoring_trailing_input.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/libsolidity/semanticTests/isoltestTesting/precompiles_ignoring_trailing_input.sol b/test/libsolidity/semanticTests/isoltestTesting/precompiles_ignoring_trailing_input.sol index 920c6b06e..ef6abb9a9 100644 --- a/test/libsolidity/semanticTests/isoltestTesting/precompiles_ignoring_trailing_input.sol +++ b/test/libsolidity/semanticTests/isoltestTesting/precompiles_ignoring_trailing_input.sol @@ -17,6 +17,8 @@ contract C { return encodedOutput; } } +// ==== +// EVMVersion: >=byzantium // ---- // ecRecover(uint256[4]): 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c, 0x000000000000000000000000000000000000000000000000000000000000001c, 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f, 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549 -> 0x20, 0x20, 966588469268559010541288244128342317224451555083 // ecRecover(uint256[4]): 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c, 0x000000000000000000000000000000000000000000000000000000000000001c, 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f, 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549, 0x01, 0x02, 0x03 -> 0x20, 0x20, 966588469268559010541288244128342317224451555083 From d7af663f70b718dc3ace0065f9973f1afcdf402f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 1 Feb 2025 19:08:35 +0100 Subject: [PATCH 0680/1340] Make tests for reserved Yul builtins compatible with EOF --- .../invalid/builtin_name_as_type.yul | 16 ++++++++-------- .../clash_with_reserved_pure_yul_builtin.yul | 2 ++ .../clash_with_reserved_pure_yul_builtin_eof.yul | 13 +++++++++++++ 3 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin_eof.yul diff --git a/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul b/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul index b9b3346f4..2e4252af4 100644 --- a/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul +++ b/test/libyul/yulSyntaxTests/invalid/builtin_name_as_type.yul @@ -1,13 +1,13 @@ { - let x: datacopy - x := true: loadimmutable + let x: memoryguard + x := true: linkersymbol function f(y: linkersymbol) {} } // ---- -// ParserError 5568: (13-21): Cannot use builtin function name "datacopy" as identifier name. -// ParserError 5473: (10-21): Types are not supported in untyped Yul. -// ParserError 5568: (37-50): Cannot use builtin function name "loadimmutable" as identifier name. -// ParserError 5473: (31-50): Types are not supported in untyped Yul. -// ParserError 5568: (70-82): Cannot use builtin function name "linkersymbol" as identifier name. -// ParserError 5473: (67-82): Types are not supported in untyped Yul. +// ParserError 5568: (13-24): Cannot use builtin function name "memoryguard" as identifier name. +// ParserError 5473: (10-24): Types are not supported in untyped Yul. +// ParserError 5568: (40-52): Cannot use builtin function name "linkersymbol" as identifier name. +// ParserError 5473: (34-52): Types are not supported in untyped Yul. +// ParserError 5568: (72-84): Cannot use builtin function name "linkersymbol" as identifier name. +// ParserError 5473: (69-84): Types are not supported in untyped Yul. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul index 035efbacc..66698c633 100644 --- a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin.yul @@ -4,6 +4,8 @@ function loadimmutable(setimmutable) -> datasize {} let dataoffset } +// ==== +// bytecodeFormat: legacy // ---- // ParserError 5568: (158-171): Cannot use builtin function name "loadimmutable" as identifier name. // ParserError 5568: (172-184): Cannot use builtin function name "setimmutable" as identifier name. diff --git a/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin_eof.yul b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin_eof.yul new file mode 100644 index 000000000..0466cc9b6 --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/clash_with_reserved_pure_yul_builtin_eof.yul @@ -0,0 +1,13 @@ +{ + // NOTE: These are builtins but only in pure Yul, not inline assembly. + // NOTE: Names of these builtins are also reserved identifiers. + function auxdataloadn(eofcreate) -> returncontract {} + let eofcreate +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// ParserError 5568: (158-170): Cannot use builtin function name "auxdataloadn" as identifier name. +// ParserError 5568: (171-180): Cannot use builtin function name "eofcreate" as identifier name. +// ParserError 5568: (185-199): Cannot use builtin function name "returncontract" as identifier name. +// ParserError 5568: (211-220): Cannot use builtin function name "eofcreate" as identifier name. From 7f9cf570727d27979aa14850cc2e5cdbfcd6f15f Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 3 Feb 2025 12:59:37 +0100 Subject: [PATCH 0681/1340] eof: Pass proper EOF flag to `Assembly` used by `EVMCodeTransformTest` --- test/libyul/EVMCodeTransformTest.cpp | 2 +- ...ction_argument_reuse_without_retparams.yul | 45 +++++++++++++++++++ ...ction_argument_reuse_without_retparams.yul | 1 + 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 test/libyul/evmCodeTransform/stackReuse/eof/function_argument_reuse_without_retparams.yul diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 4fff5a22e..96699b109 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -67,7 +67,7 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin return TestResult::FatalError; } - evmasm::Assembly assembly{CommonOptions::get().evmVersion(), false, std::nullopt, {}}; + evmasm::Assembly assembly{CommonOptions::get().evmVersion(), false, CommonOptions::get().eofVersion(), {}}; EthAssemblyAdapter adapter(assembly); EVMObjectCompiler::compile( *yulStack.parserResult(), diff --git a/test/libyul/evmCodeTransform/stackReuse/eof/function_argument_reuse_without_retparams.yul b/test/libyul/evmCodeTransform/stackReuse/eof/function_argument_reuse_without_retparams.yul new file mode 100644 index 000000000..77423e88c --- /dev/null +++ b/test/libyul/evmCodeTransform/stackReuse/eof/function_argument_reuse_without_retparams.yul @@ -0,0 +1,45 @@ +{ + function f(x, y) { + mstore(0x80, x) + if calldataload(0) { sstore(y, y) } + } + + f(0, 0) +} +// ==== +// bytecodeFormat: >=EOFv1 +// stackOptimization: true +// ---- +// /* "":95:96 */ +// 0x00 +// /* "":90:97 */ +// dup1 +// callf{code_section_1} +// /* "":0:99 */ +// stop +// +// code_section_1: assembly { +// /* "":34:38 */ +// 0x80 +// /* "":27:42 */ +// mstore +// /* "":63:64 */ +// 0x00 +// /* "":50:65 */ +// calldataload +// /* "":47:82 */ +// rjumpi{tag_1} +// /* "":21:86 */ +// tag_2: +// /* "":4:86 */ +// pop +// retf +// /* "":66:82 */ +// tag_1: +// /* "":68:80 */ +// dup1 +// sstore +// /* "":66:82 */ +// 0x00 +// rjump{tag_2} +// } diff --git a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul index 09ce0b84a..c7a82c412 100644 --- a/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul +++ b/test/libyul/evmCodeTransform/stackReuse/function_argument_reuse_without_retparams.yul @@ -8,6 +8,7 @@ } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // stackOptimization: true // ---- // /* "":90:97 */ From 402031c4cf4b47ca329e7c1897361b48e337cb44 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 13 Dec 2024 13:06:19 +0100 Subject: [PATCH 0682/1340] eof: Update `yulOptimizerTests` tests. --- .../branches_for.yul | 10 ++-- .../long_literals_as_builtin_args.yul | 2 + .../non_movable_instr2.yul | 2 + .../object_access.yul | 2 + .../commonSubexpressionEliminator/trivial.yul | 6 +- .../string_as_hex_and_hex_as_string.yul | 2 + .../equalStoreEliminator/branching.yul | 7 +-- .../equalStoreEliminator/functionbody.yul | 12 ++-- .../equalStoreEliminator/verbatim.yul | 4 +- .../constant_representation_datasize.yul | 2 + .../expressionSimplifier/create2_and_mask.yul | 1 + .../expressionSimplifier/create_and_mask.yul | 2 + .../large_byte_access.yul | 2 + .../pop_byte_shr_call.yul | 1 + .../side_effects_in_for_condition.yul | 1 + .../expressionSimplifier/zero_length_read.yul | 5 -- .../zero_length_read_call.yul | 15 +++++ .../zero_length_read_codecopy.yul | 13 +++++ .../expressionSplitter/object_access.yul | 2 + ...d_removes_non_constant_and_not_movable.yul | 2 + .../scoped_var_ref_in_function_call.yul | 2 + .../yulOptimizerTests/fullSuite/aztec.yul | 2 + .../fullSuite/create2_and_mask.yul | 1 + .../fullSuite/create_and_mask.yul | 1 + .../fullSuite/extcodelength.yul | 1 + .../fullSuite/stack_compressor_msize.yul | 4 +- .../unusedFunctionParameterPruner.yul | 4 +- .../unusedFunctionParameterPruner_return.yul | 2 + .../loadResolver/extstaticcall.yul | 29 ++++++++++ .../loadResolver/keccak_crash.yul | 2 + ....yul => memory_with_call_invalidation.yul} | 18 +----- .../memory_with_extcall_invalidation.yul | 22 ++++++++ ...memory_with_function_call_invalidation.yul | 17 ++++++ .../memory_with_mstore_invalidation.yul | 19 +++++++ .../loadResolver/staticcall.yul | 1 + .../loadResolver/zero_length_reads.yul | 1 + .../loadResolver/zero_length_reads_eof.yul | 39 +++++++++++++ .../loopInvariantCodeMotion/complex_move.yul | 4 +- .../loopInvariantCodeMotion/create_sload.yul | 2 + .../move_state_function.yul | 4 +- .../loopInvariantCodeMotion/no_move_gas.yul | 15 +++++ .../no_move_immovables.yul | 20 +++---- .../no_move_memory.yul | 4 +- .../no_move_memory_msize.yul | 4 +- .../loopInvariantCodeMotion/no_move_state.yul | 2 + .../no_move_state_function.yul | 4 +- .../no_move_state_loop.yul | 4 +- .../no_move_state_recursive_function.yul | 4 +- .../no_move_staticall_returndatasize.yul | 2 + .../no_move_storage.yul | 55 ++++--------------- .../no_move_storage_in_body.yul | 24 ++++++++ .../no_move_storage_in_post.yul | 24 ++++++++ .../loopInvariantCodeMotion/simple_state.yul | 4 +- .../rematerialiser/reassign.yul | 4 +- .../rematerialiser/update_asignment_remat.yul | 4 +- .../call_does_not_need_to_write.yul | 2 + .../unusedStoreEliminator/create.yul | 2 + .../create_inside_function.yul | 2 + 58 files changed, 325 insertions(+), 123 deletions(-) create mode 100644 test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_call.yul create mode 100644 test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_codecopy.yul create mode 100644 test/libyul/yulOptimizerTests/loadResolver/extstaticcall.yul rename test/libyul/yulOptimizerTests/loadResolver/{memory_with_different_kinds_of_invalidation.yul => memory_with_call_invalidation.yul} (54%) create mode 100644 test/libyul/yulOptimizerTests/loadResolver/memory_with_extcall_invalidation.yul create mode 100644 test/libyul/yulOptimizerTests/loadResolver/memory_with_function_call_invalidation.yul create mode 100644 test/libyul/yulOptimizerTests/loadResolver/memory_with_mstore_invalidation.yul create mode 100644 test/libyul/yulOptimizerTests/loadResolver/zero_length_reads_eof.yul create mode 100644 test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_gas.yul create mode 100644 test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_body.yul create mode 100644 test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_post.yul diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul index ac4ed1b05..9c569811e 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul @@ -1,17 +1,17 @@ { let a := 1 - let b := codesize() - for { } lt(1, codesize()) { mstore(1, codesize()) a := add(a, codesize()) } { - mstore(1, codesize()) + let b := calldataload(0) + for { } lt(1, calldataload(0)) { mstore(1, calldataload(0)) a := add(a, calldataload(0)) } { + mstore(1, calldataload(0)) } - mstore(1, codesize()) + mstore(1, calldataload(0)) } // ---- // step: commonSubexpressionEliminator // // { // let a := 1 -// let b := codesize() +// let b := calldataload(0) // for { } // lt(1, b) // { diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul index f480bec9e..e4ad176e8 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/long_literals_as_builtin_args.yul @@ -10,6 +10,8 @@ object "AccessControlDefaultAdminRules4233_14" { data "AccessControlDefaultAdminRules4233_14_deployed" "AccessControlDefaultAdminRules4233_14_deployed" } +// ==== +// bytecodeFormat: legacy // ---- // step: commonSubexpressionEliminator // diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul index ed8916e63..210b697f4 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul @@ -2,6 +2,8 @@ let a := gas() let b := gas() } +// ==== +// bytecodeFormat: legacy // ---- // step: commonSubexpressionEliminator // diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul index c8c4e4e13..98645c653 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul @@ -14,6 +14,8 @@ object "main" { } data "abc" "Hello, World!" } +// ==== +// bytecodeFormat: legacy // ---- // step: commonSubexpressionEliminator // diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul index c64fc93f9..ad0168027 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul @@ -1,11 +1,11 @@ { - let a := mul(1, codesize()) - let b := mul(1, codesize()) + let a := mul(1, calldataload(0)) + let b := mul(1, calldataload(0)) } // ---- // step: commonSubexpressionEliminator // // { -// let a := mul(1, codesize()) +// let a := mul(1, calldataload(0)) // let b := a // } diff --git a/test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul b/test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul index f0db2af1b..e2612756e 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/string_as_hex_and_hex_as_string.yul @@ -4,6 +4,8 @@ object "A" { } data 'abc' "1234" } +// ==== +// bytecodeFormat: legacy // ---- // step: disambiguator // diff --git a/test/libyul/yulOptimizerTests/equalStoreEliminator/branching.yul b/test/libyul/yulOptimizerTests/equalStoreEliminator/branching.yul index 63f0d38e4..2f382cab0 100644 --- a/test/libyul/yulOptimizerTests/equalStoreEliminator/branching.yul +++ b/test/libyul/yulOptimizerTests/equalStoreEliminator/branching.yul @@ -4,7 +4,7 @@ sstore(a, b) if calldataload(32) { sstore(a, b) - pop(staticcall(0, 0, 0, 0, 0, 0)) + pop(sload(a)) sstore(a, b) } sstore(a, b) @@ -18,8 +18,5 @@ // let a := calldataload(0) // let b := 20 // sstore(a, b) -// if calldataload(32) -// { -// pop(staticcall(0, 0, 0, 0, 0, 0)) -// } +// if calldataload(32) { pop(sload(a)) } // } diff --git a/test/libyul/yulOptimizerTests/equalStoreEliminator/functionbody.yul b/test/libyul/yulOptimizerTests/equalStoreEliminator/functionbody.yul index 68839721c..cc376652e 100644 --- a/test/libyul/yulOptimizerTests/equalStoreEliminator/functionbody.yul +++ b/test/libyul/yulOptimizerTests/equalStoreEliminator/functionbody.yul @@ -10,7 +10,7 @@ } function g() { - pop(staticcall(0, 0, 0, 0, 0, 0)) + pop(sload(calldataload(0))) } function h(a_, b_) { @@ -21,7 +21,7 @@ } function i() { - pop(delegatecall(0, 0, 0, 0, 0, 0)) + sstore(calldataload(64), 42) } @@ -40,9 +40,7 @@ // g() // } // function g() -// { -// pop(staticcall(0, 0, 0, 0, 0, 0)) -// } +// { pop(sload(calldataload(0))) } // function h(a_, b_) // { // sstore(a_, b_) @@ -50,7 +48,5 @@ // sstore(a_, b_) // } // function i() -// { -// pop(delegatecall(0, 0, 0, 0, 0, 0)) -// } +// { sstore(calldataload(64), 42) } // } diff --git a/test/libyul/yulOptimizerTests/equalStoreEliminator/verbatim.yul b/test/libyul/yulOptimizerTests/equalStoreEliminator/verbatim.yul index fcaddd121..112d704e2 100644 --- a/test/libyul/yulOptimizerTests/equalStoreEliminator/verbatim.yul +++ b/test/libyul/yulOptimizerTests/equalStoreEliminator/verbatim.yul @@ -4,7 +4,7 @@ sstore(a, b) if calldataload(32) { sstore(a, b) - pop(staticcall(0, 0, 0, 0, 0, 0)) + pop(sload(a)) verbatim_0i_0o("xyz") } sstore(a, b) @@ -20,7 +20,7 @@ // sstore(a, b) // if calldataload(32) // { -// pop(staticcall(0, 0, 0, 0, 0, 0)) +// pop(sload(a)) // verbatim_0i_0o("xyz") // } // sstore(a, b) diff --git a/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul index 301f50c6e..4d3be77e8 100644 --- a/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul +++ b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/constant_representation_datasize.yul @@ -26,6 +26,8 @@ object "test" data 'A' "A" } +// ==== +// bytecodeFormat: legacy // ---- // step: equivalentFunctionCombiner // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul index a431c57a6..e635ad5d4 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul @@ -8,6 +8,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // step: expressionSimplifier // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul index 3710cbebd..1f10c90ad 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul @@ -7,6 +7,8 @@ let b := and(0xffffffffffffffffffffffffffffffffffffffff, create(0, 0, 0x20)) sstore(a, b) } +// ==== +// bytecodeFormat: legacy // ---- // step: expressionSimplifier // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul index 19d65dca4..c73fea65c 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/large_byte_access.yul @@ -9,6 +9,8 @@ sstore(9, c) sstore(10, d) } +// ==== +// bytecodeFormat: legacy // ---- // step: expressionSimplifier // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul index abd1b1743..d1e00802f 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_call.yul @@ -3,6 +3,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // step: expressionSimplifier // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul index 9c3a5c8ba..6dc678406 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/side_effects_in_for_condition.yul @@ -5,6 +5,7 @@ } // ==== // EVMVersion: >byzantium +// bytecodeFormat: legacy // ---- // step: expressionSimplifier // diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read.yul index ee7464932..3bc52009e 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read.yul @@ -1,9 +1,7 @@ { revert(calldataload(0), 0) - revert(call(0,0,0,0,0,0,0), 0) calldatacopy(calldataload(1), calldataload(2), 0) return(calldataload(3), 0) - codecopy(calldataload(4), calldataload(5), sub(42,42)) } // ---- // step: expressionSimplifier @@ -12,10 +10,7 @@ // { // let _1 := 0 // revert(0, _1) -// pop(call(_1, _1, _1, _1, _1, _1, _1)) -// revert(0, _1) // calldatacopy(0, calldataload(2), _1) // return(0, _1) -// codecopy(0, calldataload(5), 0) // } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_call.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_call.yul new file mode 100644 index 000000000..4764c6d57 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_call.yul @@ -0,0 +1,15 @@ +{ + revert(call(0,0,0,0,0,0,0), 0) +} +// ==== +// bytecodeFormat: legacy +// ---- +// step: expressionSimplifier +// +// { +// { +// let _1 := 0 +// pop(call(_1, _1, _1, _1, _1, _1, _1)) +// revert(0, _1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_codecopy.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_codecopy.yul new file mode 100644 index 000000000..e3f1085e0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/zero_length_read_codecopy.yul @@ -0,0 +1,13 @@ +{ + codecopy(calldataload(4), calldataload(5), sub(42,42)) +} +// ==== +// bytecodeFormat: legacy +// ---- +// step: expressionSimplifier +// +// { +// { +// codecopy(0, calldataload(5), 0) +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul b/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul index bcd6d0f7b..b362f1568 100644 --- a/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul +++ b/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul @@ -9,6 +9,8 @@ object "main" { } data "abc" "Hello, World!" } +// ==== +// bytecodeFormat: legacy // ---- // step: expressionSplitter // diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul index 0e366e6d4..af609eb60 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul @@ -3,6 +3,8 @@ let a := div(create(0, 0, 0), 0) mstore(0, a) } +// ==== +// bytecodeFormat: legacy // ---- // step: fullSimplify // diff --git a/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul b/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul index 38e5ab210..1820f363c 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul @@ -6,6 +6,8 @@ } f(call(2, 0, 1, mod(x, 8), 1, 1, 1)) } +// ==== +// bytecodeFormat: legacy // ---- // step: fullSimplify // diff --git a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul index 8b26a7ba3..94d4b14ff 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul @@ -1,3 +1,4 @@ +// TODO: Add EOF version of this contract and compare with legacy to see which optimizations are missed. /** * @title Library to validate AZTEC zero-knowledge proofs * @author Zachary Williamson, AZTEC @@ -230,6 +231,7 @@ } // ==== // EVMVersion: >=istanbul +// bytecodeFormat: legacy // ---- // step: fullSuite // diff --git a/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul b/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul index 6ebca20f5..f0c54556a 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/create2_and_mask.yul @@ -8,6 +8,7 @@ } // ==== // EVMVersion: >=shanghai +// bytecodeFormat: legacy // ---- // step: fullSuite // diff --git a/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul b/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul index 078616bb3..984d9a458 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/create_and_mask.yul @@ -8,6 +8,7 @@ } // ==== // EVMVersion: >=istanbul +// bytecodeFormat: legacy // ---- // step: fullSuite // diff --git a/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul b/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul index dd6cdc0e4..772ec67cf 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/extcodelength.yul @@ -18,6 +18,7 @@ } // ==== // EVMVersion: >byzantium +// bytecodeFormat: legacy // ---- // step: fullSuite // diff --git a/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul b/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul index 5fbe8d22e..c7eb0a405 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul @@ -22,7 +22,7 @@ function foo_singlereturn_1(in_1, in_2) -> out { - extcodecopy(1,msize(),1,1) + mstore8(msize(), 42) } a := foo_singlereturn_0() @@ -60,5 +60,5 @@ // default { out := gcd(_b, mod(_a, _b)) } // } // function foo_singlereturn() -// { extcodecopy(1, msize(), 1, 1) } +// { mstore8(msize(), 42) } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul index 6f82ab27a..9d893a7d3 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul @@ -9,7 +9,7 @@ out1 := mload(32) out1 := sload(out1) out2 := add(out1, 1) - extcodecopy(out1, out2, 1, b) + calldatacopy(out2, out1, b) // to prevent foo from getting inlined if iszero(out1) { leave } } @@ -27,7 +27,7 @@ // { // out1 := sload(mload(32)) // out2 := add(out1, 1) -// extcodecopy(out1, out2, 1, b) +// calldatacopy(out2, out1, b) // if iszero(out1) { leave } // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul index b066d998b..f95e6f30d 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul @@ -16,6 +16,8 @@ if iszero(out1) { leave } } } +// ==== +// bytecodeFormat: legacy // ---- // step: fullSuite // diff --git a/test/libyul/yulOptimizerTests/loadResolver/extstaticcall.yul b/test/libyul/yulOptimizerTests/loadResolver/extstaticcall.yul new file mode 100644 index 000000000..b7b4de23b --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/extstaticcall.yul @@ -0,0 +1,29 @@ +{ + let a := 0 + let b := 1 + let c := 2 + sstore(a, b) + mstore(900, 7) + let d := extstaticcall(10, 0, 200) + sstore(add(a, 1), mload(900)) + // Main test objective: replace this sload. + mstore(0, sload(a)) +} +// ==== +// EVMVersion: >=byzantium +// bytecodeFormat: >=EOFv1 +// ---- +// step: loadResolver +// +// { +// { +// let a := 0 +// let b := 1 +// sstore(a, b) +// let _1 := 7 +// mstore(900, _1) +// pop(extstaticcall(10, a, 200)) +// sstore(1, _1) +// mstore(a, b) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul index 18c818d15..c67a0f875 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul @@ -2,6 +2,8 @@ { for {} addmod(keccak256(0x0,create(0x0, 0x0, 0x0)), 0x0, 0x0) {} {} } +// ==== +// bytecodeFormat: legacy // ---- // step: loadResolver // diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_call_invalidation.yul similarity index 54% rename from test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul rename to test/libyul/yulOptimizerTests/loadResolver/memory_with_call_invalidation.yul index 840f19005..88d0ba64d 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_call_invalidation.yul @@ -3,17 +3,9 @@ sstore(0, mload(2)) pop(call(0, 0, 0, 0, 0, 0, 0)) sstore(0, mload(2)) - - mstore(2, 10) - mstore8(calldataload(0), 4) - sstore(0, mload(2)) - - mstore(2, 10) - g() - sstore(0, mload(2)) - - function g() {} } +// ==== +// bytecodeFormat: legacy // ---- // step: loadResolver // @@ -27,11 +19,5 @@ // sstore(_5, _4) // pop(call(_5, _5, _5, _5, _5, _5, _5)) // sstore(_5, mload(_2)) -// let _17 := 10 -// mstore(_2, _17) -// mstore8(calldataload(_5), 4) -// sstore(_5, mload(_2)) -// mstore(_2, _17) -// sstore(_5, _17) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_extcall_invalidation.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_extcall_invalidation.yul new file mode 100644 index 000000000..55c131677 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_extcall_invalidation.yul @@ -0,0 +1,22 @@ +{ + mstore(2, 9) + sstore(0, mload(2)) + pop(extcall(0, 0, 0, 0)) + sstore(0, mload(2)) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// step: loadResolver +// +// { +// { +// let _1 := 9 +// mstore(2, _1) +// let _4 := _1 +// let _5 := 0 +// sstore(_5, _4) +// pop(extcall(_5, _5, _5, _5)) +// sstore(_5, _1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_function_call_invalidation.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_function_call_invalidation.yul new file mode 100644 index 000000000..7181d553a --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_function_call_invalidation.yul @@ -0,0 +1,17 @@ +{ + mstore(2, 10) + g() + sstore(0, mload(2)) + + function g() {} +} +// ---- +// step: loadResolver +// +// { +// { +// let _1 := 10 +// mstore(2, _1) +// sstore(0, _1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_mstore_invalidation.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_mstore_invalidation.yul new file mode 100644 index 000000000..3179ef391 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_mstore_invalidation.yul @@ -0,0 +1,19 @@ +{ + mstore(2, 10) + mstore8(calldataload(0), 4) + sstore(0, mload(2)) +} +// ---- +// step: loadResolver +// +// { +// { +// let _1 := 10 +// let _2 := 2 +// mstore(_2, _1) +// let _3 := 4 +// let _4 := 0 +// mstore8(calldataload(_4), _3) +// sstore(_4, mload(_2)) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul b/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul index 2a72eee3e..ede5dc3e8 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/staticcall.yul @@ -11,6 +11,7 @@ } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // step: loadResolver // diff --git a/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul b/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul index 418221a93..8035d1772 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads.yul @@ -18,6 +18,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // step: loadResolver // diff --git a/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads_eof.yul b/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads_eof.yul new file mode 100644 index 000000000..42e6d11c7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loadResolver/zero_length_reads_eof.yul @@ -0,0 +1,39 @@ +{ + // TODO: The current implementation of YulOptimizerTests ignores subobjects that are not Data. It's impossbile to test + // eofcreate and returncontract now. + returndatacopy(1, 1, 0) + calldatacopy(1, 1, 0) + log0(1, 0) + log1(1, 0, 1) + log2(1, 0, 1, 1) + log3(1, 0, 1, 1, 1) + log4(1, 0, 1, 1, 1, 1) + //pop(eofcreate("a", 1, 1, 1, 0)) + //returncontract("b", 1, 0) + pop(extcall(1, 1, 1, 0)) + pop(extdelegatecall(1, 1, 0)) + pop(extstaticcall(1, 1, 0)) + return(1, 0) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// step: loadResolver +// +// { +// { +// let _1 := 0 +// let _2 := 1 +// returndatacopy(0, _2, _1) +// calldatacopy(0, _2, _1) +// log0(0, _1) +// log1(0, _1, _2) +// log2(0, _1, _2, _2) +// log3(0, _1, _2, _2, _2) +// log4(0, _1, _2, _2, _2, _2) +// pop(extcall(_2, _2, _2, _1)) +// pop(extdelegatecall(_2, 0, _1)) +// pop(extstaticcall(_2, 0, _1)) +// return(0, _1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/complex_move.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/complex_move.yul index 3c11ca65f..cfa38e05a 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/complex_move.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/complex_move.yul @@ -2,7 +2,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { let inv := add(b, 42) - let x := extcodesize(keccak256(mul(mload(inv), 3), 32)) + let x := balance(keccak256(mul(mload(inv), 3), 32)) a := add(x, 1) sstore(a, inv) } @@ -14,7 +14,7 @@ // let b := 1 // let a := 1 // let inv := add(b, 42) -// let x := extcodesize(keccak256(mul(mload(inv), 3), 32)) +// let x := balance(keccak256(mul(mload(inv), 3), 32)) // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { // a := add(x, 1) diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul index 412895037..fa6619d05 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul @@ -11,6 +11,8 @@ let z := f() } } +// ==== +// bytecodeFormat: legacy // ---- // step: loopInvariantCodeMotion // diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul index 1d1a14915..a6ccbb39f 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul @@ -4,7 +4,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let t := extcodesize(f()) + let t := balance(f()) let q := g() } } @@ -14,7 +14,7 @@ // { // let b := 1 // let a := 1 -// let t := extcodesize(f()) +// let t := balance(f()) // let q := g() // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_gas.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_gas.yul new file mode 100644 index 000000000..ae69ae3f7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_gas.yul @@ -0,0 +1,15 @@ +{ + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + let c := gas() + } +} +// ==== +// bytecodeFormat: legacy +// ---- +// step: loopInvariantCodeMotion +// +// { +// let a := 1 +// for { } iszero(eq(a, 10)) { a := add(a, 1) } +// { let c := gas() } +// } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul index 8881fdc84..0c7d68fc7 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul @@ -1,24 +1,20 @@ { - let a := 1 - function f() -> x {invalid()} - function g() -> y {return(0, 0)} - for { let i := 1 } iszero(eq(i, 10)) { a := add(i, 1) } { - let b := f() - let c := gas() - let d := g() - let e := sload(g()) - } + function f() -> x {invalid()} + function g() -> y {return(0, 0)} + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + let b := f() + let d := g() + let e := sload(g()) + } } // ---- // step: loopInvariantCodeMotion // // { // let a := 1 -// let i := 1 -// for { } iszero(eq(i, 10)) { a := add(i, 1) } +// for { } iszero(eq(a, 10)) { a := add(a, 1) } // { // let b := f() -// let c := gas() // let d := g() // let e := sload(g()) // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul index 942a3c580..486921ae6 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul @@ -9,7 +9,7 @@ for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { let inv := add(b, 42) // mload prevents moving of extcodesize - let x := extcodesize(mload(mul(inv, 3))) + let x := balance(mload(mul(inv, 3))) a := add(x, 1) mstore(a, inv) } @@ -31,7 +31,7 @@ // let inv_2 := add(b, 42) // for { } iszero(eq(a_1, 10)) { a_1 := add(a_1, 1) } // { -// let x_3 := extcodesize(mload(mul(inv_2, 3))) +// let x_3 := balance(mload(mul(inv_2, 3))) // a_1 := add(x_3, 1) // mstore(a_1, inv_2) // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul index 2033a9be9..95f968d89 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul @@ -8,7 +8,7 @@ } for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { let inv := add(b, 42) - let x := extcodesize(mload(mul(inv, 3))) + let x := balance(mload(mul(inv, 3))) a := add(x, 1) } } @@ -29,7 +29,7 @@ // let inv_2 := add(b, 42) // for { } iszero(eq(a_1, 10)) { a_1 := add(a_1, 1) } // { -// let x_3 := extcodesize(mload(mul(inv_2, 3))) +// let x_3 := balance(mload(mul(inv_2, 3))) // a_1 := add(x_3, 1) // } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul index fa6c985b4..c2ea86bc8 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul @@ -25,6 +25,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: loopInvariantCodeMotion // diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul index d3dce8d78..c50d1b6c2 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul @@ -7,7 +7,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let t := extcodesize(f()) + let t := balance(f()) let q := sload(g()) } } @@ -19,7 +19,7 @@ // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { -// let t := extcodesize(f()) +// let t := balance(f()) // let q := sload(g()) // } // function f() -> x diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul index 8de9147d8..9745dbe47 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul @@ -4,7 +4,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let t := extcodesize(f()) + let t := balance(f()) let q := g() } } @@ -16,7 +16,7 @@ // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { -// let t := extcodesize(f()) +// let t := balance(f()) // let q := g() // } // function f() -> x diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul index 1eb0ccd6d..b8d4044c5 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul @@ -4,7 +4,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let t := extcodesize(f()) + let t := balance(f()) let q := sload(g()) } } @@ -16,7 +16,7 @@ // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { -// let t := extcodesize(f()) +// let t := balance(f()) // let q := sload(g()) // } // function f() -> x diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_staticall_returndatasize.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_staticall_returndatasize.yul index ae20f4904..a5f2125a0 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_staticall_returndatasize.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_staticall_returndatasize.yul @@ -10,6 +10,8 @@ } } // ==== +// bytecodeFormat: legacy +// ==== // EVMVersion: >=byzantium // ---- // step: loopInvariantCodeMotion diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul index 0ef2fd78a..410f07663 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul @@ -1,30 +1,15 @@ { - let b := 1 - // invalidates storage in post - for { let a := 1 } iszero(eq(a, 10)) { sstore(0x00, 0x01)} { - let inv := add(b, 42) - let x := sload(mul(inv, 3)) - a := add(x, 1) - mstore(a, inv) - } - - // invalidates storage in body - for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let inv := add(b, 42) - let x := sload(mul(inv, 3)) - a := add(x, 1) - sstore(a, inv) - } - - // invalidates state in body - for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { - let inv := add(b, 42) - pop(callcode(100, 0x010, 10, 0x00, 32, 0x0100, 32)) - let x := sload(mul(inv, 3)) - a := add(x, 1) - } - + let b := 1 + // invalidates state in body + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + let inv := add(b, 42) + pop(callcode(100, 0x010, 10, 0x00, 32, 0x0100, 32)) + let x := sload(mul(inv, 3)) + a := add(x, 1) + } } +// ==== +// bytecodeFormat: legacy // ---- // step: loopInvariantCodeMotion // @@ -32,26 +17,10 @@ // let b := 1 // let a := 1 // let inv := add(b, 42) -// for { } iszero(eq(a, 10)) { sstore(0x00, 0x01) } +// for { } iszero(eq(a, 10)) { a := add(a, 1) } // { +// pop(callcode(100, 0x010, 10, 0x00, 32, 0x0100, 32)) // let x := sload(mul(inv, 3)) // a := add(x, 1) -// mstore(a, inv) -// } -// let a_1 := 1 -// let inv_2 := add(b, 42) -// for { } iszero(eq(a_1, 10)) { a_1 := add(a_1, 1) } -// { -// let x_3 := sload(mul(inv_2, 3)) -// a_1 := add(x_3, 1) -// sstore(a_1, inv_2) -// } -// let a_4 := 1 -// let inv_5 := add(b, 42) -// for { } iszero(eq(a_4, 10)) { a_4 := add(a_4, 1) } -// { -// pop(callcode(100, 0x010, 10, 0x00, 32, 0x0100, 32)) -// let x_6 := sload(mul(inv_5, 3)) -// a_4 := add(x_6, 1) // } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_body.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_body.yul new file mode 100644 index 000000000..66a21130b --- /dev/null +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_body.yul @@ -0,0 +1,24 @@ +{ + let b := 1 + // invalidates storage in body + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + let inv := add(b, 42) + let x := sload(mul(inv, 3)) + a := add(x, 1) + sstore(a, inv) + } +} +// ---- +// step: loopInvariantCodeMotion +// +// { +// let b := 1 +// let a := 1 +// let inv := add(b, 42) +// for { } iszero(eq(a, 10)) { a := add(a, 1) } +// { +// let x := sload(mul(inv, 3)) +// a := add(x, 1) +// sstore(a, inv) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_post.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_post.yul new file mode 100644 index 000000000..6859f028b --- /dev/null +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_in_post.yul @@ -0,0 +1,24 @@ +{ + let b := 1 + // invalidates storage in post + for { let a := 1 } iszero(eq(a, 10)) { sstore(0x00, 0x01)} { + let inv := add(b, 42) + let x := sload(mul(inv, 3)) + a := add(x, 1) + mstore(a, inv) + } +} +// ---- +// step: loopInvariantCodeMotion +// +// { +// let b := 1 +// let a := 1 +// let inv := add(b, 42) +// for { } iszero(eq(a, 10)) { sstore(0x00, 0x01) } +// { +// let x := sload(mul(inv, 3)) +// a := add(x, 1) +// mstore(a, inv) +// } +// } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/simple_state.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/simple_state.yul index f8b5a3d53..b087802ef 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/simple_state.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/simple_state.yul @@ -2,7 +2,7 @@ let b := 1 for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { let inv := add(b, 42) - let x := extcodesize(mul(inv, 3)) + let x := balance(mul(inv, 3)) a := add(x, 1) mstore(a, inv) } @@ -14,7 +14,7 @@ // let b := 1 // let a := 1 // let inv := add(b, 42) -// let x := extcodesize(mul(inv, 3)) +// let x := balance(mul(inv, 3)) // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { // a := add(x, 1) diff --git a/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul b/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul index ef6e12ab6..57886d563 100644 --- a/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul +++ b/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul @@ -1,5 +1,5 @@ { - let a := extcodesize(0) + let a := balance(0) let b := a let c := b a := 2 @@ -10,7 +10,7 @@ // step: rematerialiser // // { -// let a := extcodesize(0) +// let a := balance(0) // let b := a // let c := a // a := 2 diff --git a/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul b/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul index bb5f02980..d168b1886 100644 --- a/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul +++ b/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul @@ -1,6 +1,6 @@ // We cannot substitute `a` in `let b := a` { - let a := extcodesize(0) + let a := balance(0) a := mul(a, 2) let b := a } @@ -8,7 +8,7 @@ // step: rematerialiser // // { -// let a := extcodesize(0) +// let a := balance(0) // a := mul(a, 2) // let b := a // } diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/call_does_not_need_to_write.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/call_does_not_need_to_write.yul index eeff779f8..2a65462e8 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/call_does_not_need_to_write.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/call_does_not_need_to_write.yul @@ -12,6 +12,8 @@ sstore(0, mload(0)) } +// ==== +// bytecodeFormat: legacy // ---- // step: unusedStoreEliminator // diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/create.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/create.yul index c3183d9ec..dc339466f 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/create.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/create.yul @@ -4,6 +4,8 @@ pop(create(0, 0, 0)) sstore(x, 20) } +// ==== +// bytecodeFormat: legacy // ---- // step: unusedStoreEliminator // diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/create_inside_function.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/create_inside_function.yul index 782c68663..788e7be21 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/create_inside_function.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/create_inside_function.yul @@ -7,6 +7,8 @@ f() sstore(x, 20) } +// ==== +// bytecodeFormat: legacy // ---- // step: unusedStoreEliminator // From ea58f7eb553d4ec0306fa856a02138cbee6b808c Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 13 Dec 2024 15:23:58 +0100 Subject: [PATCH 0683/1340] eof: Update `yulControlFlowGraph` tests --- .../yulControlFlowGraph/ambiguous_names.yul | 2 + test/libyul/yulControlFlowGraph/complex.yul | 2 + .../yulControlFlowGraph/eof/function.yul | 67 +++++++++++++++++++ test/libyul/yulControlFlowGraph/function.yul | 2 + test/libyul/yulControlFlowGraph/leave.yul | 2 + 5 files changed, 75 insertions(+) create mode 100644 test/libyul/yulControlFlowGraph/eof/function.yul diff --git a/test/libyul/yulControlFlowGraph/ambiguous_names.yul b/test/libyul/yulControlFlowGraph/ambiguous_names.yul index fabeda45b..e7aaeadbb 100644 --- a/test/libyul/yulControlFlowGraph/ambiguous_names.yul +++ b/test/libyul/yulControlFlowGraph/ambiguous_names.yul @@ -14,6 +14,8 @@ function b() {} } } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; diff --git a/test/libyul/yulControlFlowGraph/complex.yul b/test/libyul/yulControlFlowGraph/complex.yul index 4001a9309..718ea6770 100644 --- a/test/libyul/yulControlFlowGraph/complex.yul +++ b/test/libyul/yulControlFlowGraph/complex.yul @@ -43,6 +43,8 @@ } pop(f(1,2)) } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; diff --git a/test/libyul/yulControlFlowGraph/eof/function.yul b/test/libyul/yulControlFlowGraph/eof/function.yul new file mode 100644 index 000000000..5f5ef934b --- /dev/null +++ b/test/libyul/yulControlFlowGraph/eof/function.yul @@ -0,0 +1,67 @@ +{ + function f(a, b) -> r { + let x := add(a,b) + r := sub(x,a) + } + function g() { + sstore(0x01, 0x0101) + } + function h(x) { + h(f(x, 0)) + g() + } + function i() -> v, w { + v := 0x0202 + w := 0x0303 + } + let x, y := i() + h(x) + h(y) +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// digraph CFG { +// nodesep=0.7; +// node[shape=box]; +// +// Entry [label="Entry"]; +// Entry -> Block0; +// Block0 [label="\ +// i: [ ] => [ TMP[i, 0] TMP[i, 1] ]\l\ +// Assignment(x, y): [ TMP[i, 0] TMP[i, 1] ] => [ x y ]\l\ +// h: [ x ] => [ ]\l\ +// "]; +// Block0Exit [label="Terminated"]; +// Block0 -> Block0Exit; +// +// FunctionEntry_f_1 [label="function f(a, b) -> r"]; +// FunctionEntry_f_1 -> Block1; +// Block1 [label="\ +// add: [ b a ] => [ TMP[add, 0] ]\l\ +// Assignment(x): [ TMP[add, 0] ] => [ x ]\l\ +// sub: [ a x ] => [ TMP[sub, 0] ]\l\ +// Assignment(r): [ TMP[sub, 0] ] => [ r ]\l\ +// "]; +// Block1Exit [label="FunctionReturn[f]"]; +// Block1 -> Block1Exit; +// +// FunctionEntry_h_2 [label="function h(x)"]; +// FunctionEntry_h_2 -> Block2; +// Block2 [label="\ +// f: [ 0x00 x ] => [ TMP[f, 0] ]\l\ +// h: [ TMP[f, 0] ] => [ ]\l\ +// "]; +// Block2Exit [label="Terminated"]; +// Block2 -> Block2Exit; +// +// FunctionEntry_i_3 [label="function i() -> v, w"]; +// FunctionEntry_i_3 -> Block3; +// Block3 [label="\ +// Assignment(v): [ 0x0202 ] => [ v ]\l\ +// Assignment(w): [ 0x0303 ] => [ w ]\l\ +// "]; +// Block3Exit [label="FunctionReturn[i]"]; +// Block3 -> Block3Exit; +// +// } diff --git a/test/libyul/yulControlFlowGraph/function.yul b/test/libyul/yulControlFlowGraph/function.yul index f65c7505c..0e3691a42 100644 --- a/test/libyul/yulControlFlowGraph/function.yul +++ b/test/libyul/yulControlFlowGraph/function.yul @@ -18,6 +18,8 @@ h(x) h(y) } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; diff --git a/test/libyul/yulControlFlowGraph/leave.yul b/test/libyul/yulControlFlowGraph/leave.yul index 4d0a63af4..d6f475513 100644 --- a/test/libyul/yulControlFlowGraph/leave.yul +++ b/test/libyul/yulControlFlowGraph/leave.yul @@ -11,6 +11,8 @@ pop(f(0,1)) } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; From 2c323da8b9e29c7301086ccf7bcb06c52d883cc3 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 16 Dec 2024 10:44:02 +0100 Subject: [PATCH 0684/1340] eof: Update `yulStackLayout` tests --- test/libyul/yulStackLayout/complex.yul | 2 + test/libyul/yulStackLayout/eof/function.yul | 102 ++++++++++++++++++++ test/libyul/yulStackLayout/function.yul | 4 +- test/libyul/yulStackLayout/literal_loop.yul | 2 + 4 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 test/libyul/yulStackLayout/eof/function.yul diff --git a/test/libyul/yulStackLayout/complex.yul b/test/libyul/yulStackLayout/complex.yul index 604dca1f4..66390f7d4 100644 --- a/test/libyul/yulStackLayout/complex.yul +++ b/test/libyul/yulStackLayout/complex.yul @@ -48,6 +48,8 @@ } pop(f(1,2)) } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; diff --git a/test/libyul/yulStackLayout/eof/function.yul b/test/libyul/yulStackLayout/eof/function.yul new file mode 100644 index 000000000..a196e46e8 --- /dev/null +++ b/test/libyul/yulStackLayout/eof/function.yul @@ -0,0 +1,102 @@ +{ + function f(a, b) -> r { + let x := add(a,b) + r := sub(x,a) + } + function g() { + sstore(0x01, 0x0101) + } + function h(x) { + h(f(x, 0)) + g() + } + function i() -> v, w { + v := 0x0202 + w := 0x0303 + } + let x, y := i() + h(x) + h(y) + // This call of g() is unreachable too as the one in h() but we wanna cover both cases. + g() +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// digraph CFG { +// nodesep=0.7; +// node[shape=box]; +// +// Entry [label="Entry"]; +// Entry -> Block0; +// Block0 [label="\ +// [ ]\l\ +// [ ]\l\ +// i\l\ +// [ TMP[i, 0] TMP[i, 1] ]\l\ +// [ TMP[i, 0] TMP[i, 1] ]\l\ +// Assignment(x, y)\l\ +// [ x y ]\l\ +// [ x ]\l\ +// h\l\ +// [ ]\l\ +// [ ]\l\ +// "]; +// Block0Exit [label="Terminated"]; +// Block0 -> Block0Exit; +// +// FunctionEntry_f [label="function f(a, b) -> r\l\ +// [ RET b a ]"]; +// FunctionEntry_f -> Block1; +// Block1 [label="\ +// [ a b ]\l\ +// [ a b a ]\l\ +// add\l\ +// [ a TMP[add, 0] ]\l\ +// [ a TMP[add, 0] ]\l\ +// Assignment(x)\l\ +// [ a x ]\l\ +// [ a x ]\l\ +// sub\l\ +// [ TMP[sub, 0] ]\l\ +// [ TMP[sub, 0] ]\l\ +// Assignment(r)\l\ +// [ r ]\l\ +// [ r ]\l\ +// "]; +// Block1Exit [label="FunctionReturn[f]"]; +// Block1 -> Block1Exit; +// +// FunctionEntry_h [label="function h(x)\l\ +// [ RET x ]"]; +// FunctionEntry_h -> Block2; +// Block2 [label="\ +// [ 0x00 x ]\l\ +// [ 0x00 x ]\l\ +// f\l\ +// [ TMP[f, 0] ]\l\ +// [ TMP[f, 0] ]\l\ +// h\l\ +// [ ]\l\ +// [ ]\l\ +// "]; +// Block2Exit [label="Terminated"]; +// Block2 -> Block2Exit; +// +// FunctionEntry_i [label="function i() -> v, w\l\ +// [ RET ]"]; +// FunctionEntry_i -> Block3; +// Block3 [label="\ +// [ ]\l\ +// [ 0x0202 ]\l\ +// Assignment(v)\l\ +// [ v ]\l\ +// [ v 0x0303 ]\l\ +// Assignment(w)\l\ +// [ v w ]\l\ +// [ v w ]\l\ +// "]; +// Block3Exit [label="FunctionReturn[i]"]; +// Block3 -> Block3Exit; +// +// } diff --git a/test/libyul/yulStackLayout/function.yul b/test/libyul/yulStackLayout/function.yul index e01a8dcb3..13f83505d 100644 --- a/test/libyul/yulStackLayout/function.yul +++ b/test/libyul/yulStackLayout/function.yul @@ -17,9 +17,11 @@ let x, y := i() h(x) h(y) - // This calla of g() is unreachable too as the one in h() but we wanna cover both cases. + // This call of g() is unreachable too as the one in h() but we wanna cover both cases. g() } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; diff --git a/test/libyul/yulStackLayout/literal_loop.yul b/test/libyul/yulStackLayout/literal_loop.yul index 841c41062..fee5f7b56 100644 --- a/test/libyul/yulStackLayout/literal_loop.yul +++ b/test/libyul/yulStackLayout/literal_loop.yul @@ -4,6 +4,8 @@ {} {} } +// ==== +// bytecodeFormat: legacy // ---- // digraph CFG { // nodesep=0.7; From c9466e557963237a581ec954331c74d5c1898df9 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 16 Dec 2024 11:17:03 +0100 Subject: [PATCH 0685/1340] eof: Update `yulInterpreterTests` tests --- test/libyul/yulInterpreterTests/and_create.yul | 2 ++ test/libyul/yulInterpreterTests/and_create2.yul | 1 + test/libyul/yulInterpreterTests/create2.yul | 1 + test/libyul/yulInterpreterTests/datacopy.yul | 2 ++ test/libyul/yulInterpreterTests/dataoffset.yul | 2 ++ test/libyul/yulInterpreterTests/datasize.yul | 2 ++ test/libyul/yulInterpreterTests/external_call_to_self.yul | 1 + test/libyul/yulInterpreterTests/external_call_unexecuted.yul | 2 ++ .../libyul/yulInterpreterTests/external_callcode_unexecuted.yul | 2 ++ .../yulInterpreterTests/external_delegatecall_unexecuted.yul | 2 ++ .../yulInterpreterTests/external_staticcall_unexecuted.yul | 1 + test/libyul/yulInterpreterTests/long_object_name.yul | 2 ++ test/libyul/yulInterpreterTests/pop_byte_shr_call.yul | 1 + test/libyul/yulInterpreterTests/side_effect_free.yul | 1 + test/libyul/yulInterpreterTests/zero_length_reads.yul | 1 + .../libyul/yulInterpreterTests/zero_length_reads_and_revert.yul | 1 + 16 files changed, 24 insertions(+) diff --git a/test/libyul/yulInterpreterTests/and_create.yul b/test/libyul/yulInterpreterTests/and_create.yul index da962c3c0..5d8cd6cfd 100644 --- a/test/libyul/yulInterpreterTests/and_create.yul +++ b/test/libyul/yulInterpreterTests/and_create.yul @@ -4,6 +4,8 @@ let b := and(u160max, create(0, u160max, 0)) mstore(0, eq(a, b)) } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // CREATE(0, 0, 0) diff --git a/test/libyul/yulInterpreterTests/and_create2.yul b/test/libyul/yulInterpreterTests/and_create2.yul index 0b83d818f..c076c1203 100644 --- a/test/libyul/yulInterpreterTests/and_create2.yul +++ b/test/libyul/yulInterpreterTests/and_create2.yul @@ -6,6 +6,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // CREATE2(0, 0, 0, 0) diff --git a/test/libyul/yulInterpreterTests/create2.yul b/test/libyul/yulInterpreterTests/create2.yul index b7484f5db..ad6eb5383 100644 --- a/test/libyul/yulInterpreterTests/create2.yul +++ b/test/libyul/yulInterpreterTests/create2.yul @@ -5,6 +5,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // CREATE2(0, 0, 32, 32) diff --git a/test/libyul/yulInterpreterTests/datacopy.yul b/test/libyul/yulInterpreterTests/datacopy.yul index ce5b6ce5c..61a3259a7 100644 --- a/test/libyul/yulInterpreterTests/datacopy.yul +++ b/test/libyul/yulInterpreterTests/datacopy.yul @@ -8,6 +8,8 @@ object "main" } object "sub" { code { sstore(0, 1) } } } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // Memory dump: diff --git a/test/libyul/yulInterpreterTests/dataoffset.yul b/test/libyul/yulInterpreterTests/dataoffset.yul index f5a9aeb12..366ceb4bd 100644 --- a/test/libyul/yulInterpreterTests/dataoffset.yul +++ b/test/libyul/yulInterpreterTests/dataoffset.yul @@ -6,6 +6,8 @@ object "main" } object "sub" { code { sstore(0, 1) } } } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // Memory dump: diff --git a/test/libyul/yulInterpreterTests/datasize.yul b/test/libyul/yulInterpreterTests/datasize.yul index ff80edee7..f03d70836 100644 --- a/test/libyul/yulInterpreterTests/datasize.yul +++ b/test/libyul/yulInterpreterTests/datasize.yul @@ -6,6 +6,8 @@ object "main" } object "sub" { code { sstore(0, 1) } } } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // Memory dump: diff --git a/test/libyul/yulInterpreterTests/external_call_to_self.yul b/test/libyul/yulInterpreterTests/external_call_to_self.yul index 3f5c887b4..b2d69086a 100644 --- a/test/libyul/yulInterpreterTests/external_call_to_self.yul +++ b/test/libyul/yulInterpreterTests/external_call_to_self.yul @@ -11,6 +11,7 @@ } // ==== // simulateExternalCall: true +// bytecodeFormat: legacy // ---- // Trace: // CALL(153, 0x11111111, 0, 64, 32, 256, 32) diff --git a/test/libyul/yulInterpreterTests/external_call_unexecuted.yul b/test/libyul/yulInterpreterTests/external_call_unexecuted.yul index 0a5458b47..93bb9ec03 100644 --- a/test/libyul/yulInterpreterTests/external_call_unexecuted.yul +++ b/test/libyul/yulInterpreterTests/external_call_unexecuted.yul @@ -2,6 +2,8 @@ let x := call(gas(), 0x45, 0x5, 0, 0x20, 0x30, 0x20) sstore(0x64, x) } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // CALL(153, 69, 5, 0, 32, 48, 32) diff --git a/test/libyul/yulInterpreterTests/external_callcode_unexecuted.yul b/test/libyul/yulInterpreterTests/external_callcode_unexecuted.yul index 5245d7443..5d0da5c06 100644 --- a/test/libyul/yulInterpreterTests/external_callcode_unexecuted.yul +++ b/test/libyul/yulInterpreterTests/external_callcode_unexecuted.yul @@ -2,6 +2,8 @@ let x := callcode(gas(), 0x45, 0x5, 0, 0x20, 0x30, 0x20) sstore(100, x) } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // CALLCODE(153, 69, 5, 0, 32, 48, 32) diff --git a/test/libyul/yulInterpreterTests/external_delegatecall_unexecuted.yul b/test/libyul/yulInterpreterTests/external_delegatecall_unexecuted.yul index a827181fc..3e84df570 100644 --- a/test/libyul/yulInterpreterTests/external_delegatecall_unexecuted.yul +++ b/test/libyul/yulInterpreterTests/external_delegatecall_unexecuted.yul @@ -2,6 +2,8 @@ let x := delegatecall(gas(), 0x45, 0, 0x20, 0x30, 0x20) sstore(100, x) } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // DELEGATECALL(153, 69, 0, 32, 48, 32) diff --git a/test/libyul/yulInterpreterTests/external_staticcall_unexecuted.yul b/test/libyul/yulInterpreterTests/external_staticcall_unexecuted.yul index 66ea146a0..664692bad 100644 --- a/test/libyul/yulInterpreterTests/external_staticcall_unexecuted.yul +++ b/test/libyul/yulInterpreterTests/external_staticcall_unexecuted.yul @@ -4,6 +4,7 @@ } // ==== // EVMVersion: >=byzantium +// bytecodeFormat: legacy // ---- // Trace: // STATICCALL(153, 69, 0, 32, 48, 32) diff --git a/test/libyul/yulInterpreterTests/long_object_name.yul b/test/libyul/yulInterpreterTests/long_object_name.yul index ede304029..69b7acbb2 100644 --- a/test/libyul/yulInterpreterTests/long_object_name.yul +++ b/test/libyul/yulInterpreterTests/long_object_name.yul @@ -13,6 +13,8 @@ object "t" { } } } +// ==== +// bytecodeFormat: legacy // ---- // Trace: // Memory dump: diff --git a/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul b/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul index ec9ca2fe6..4386711a1 100644 --- a/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul +++ b/test/libyul/yulInterpreterTests/pop_byte_shr_call.yul @@ -3,6 +3,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // CALL(0, 0, 0, 0, 0, 0, 0) diff --git a/test/libyul/yulInterpreterTests/side_effect_free.yul b/test/libyul/yulInterpreterTests/side_effect_free.yul index adedd299f..d68d57364 100644 --- a/test/libyul/yulInterpreterTests/side_effect_free.yul +++ b/test/libyul/yulInterpreterTests/side_effect_free.yul @@ -14,6 +14,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // Memory dump: diff --git a/test/libyul/yulInterpreterTests/zero_length_reads.yul b/test/libyul/yulInterpreterTests/zero_length_reads.yul index 661db49ff..68cae1b92 100644 --- a/test/libyul/yulInterpreterTests/zero_length_reads.yul +++ b/test/libyul/yulInterpreterTests/zero_length_reads.yul @@ -18,6 +18,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // RETURNDATACOPY(0, 1, 0) diff --git a/test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul b/test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul index 0d0f92420..c9143d791 100644 --- a/test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul +++ b/test/libyul/yulInterpreterTests/zero_length_reads_and_revert.yul @@ -18,6 +18,7 @@ } // ==== // EVMVersion: >=constantinople +// bytecodeFormat: legacy // ---- // Trace: // RETURNDATACOPY(0, 1, 0) From 6ea1dce9e86f2d78a532636366aff5f5e10c09bd Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 31 Jan 2025 22:06:59 +0100 Subject: [PATCH 0686/1340] SMTChecker: Fix parsing bv2int expression from solver's response --- libsmtutil/CHCSmtLib2Interface.cpp | 5 +++++ .../solver_response_involves_bv2int.sol | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 test/libsolidity/smtCheckerTests/invariants/solver_response_involves_bv2int.sol diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index f9bb3b8f6..6b0534296 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -365,6 +365,11 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi smtSolverInteractionRequire(arguments.size() == 3, "Store has three arguments: array, index and element"); return smtutil::Expression::store(arguments[0], arguments[1], arguments[2]); } + if (op == "bv2int") + { + smtSolverInteractionRequire(arguments.size() == 1, "bv2int has one argument"); + return smtutil::Expression::bv2int(arguments[0]); + } else { std::set boolOperators{"and", "or", "not", "=", "<", ">", "<=", ">=", "=>"}; diff --git a/test/libsolidity/smtCheckerTests/invariants/solver_response_involves_bv2int.sol b/test/libsolidity/smtCheckerTests/invariants/solver_response_involves_bv2int.sol new file mode 100644 index 000000000..54609b86a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/invariants/solver_response_involves_bv2int.sol @@ -0,0 +1,16 @@ +// Taken from issue #15770 +contract c { + function f(uint len) public pure returns (bytes memory) { + bytes memory x = new bytes(len); + for (uint i = 0; i < len; i++) { + x[i] = bytes1(uint8(i)); + } + return x; + } +} +// ==== +// SMTEngine: chc +// SMTIgnoreInv: no +// SMTSolvers: z3 +// ---- +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From b14c7efe3f0f091d324b1271d225337dd298d2d8 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Sun, 26 Jan 2025 08:37:25 +0100 Subject: [PATCH 0687/1340] StringUtils: Compatibility of joinHumanReadable with string_view --- libsolutil/StringUtils.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libsolutil/StringUtils.h b/libsolutil/StringUtils.h index 77ffe6735..763f1ea64 100644 --- a/libsolutil/StringUtils.h +++ b/libsolutil/StringUtils.h @@ -67,24 +67,24 @@ std::string joinHumanReadable { auto const itEnd = end(_list); - std::string result; + std::stringstream result; for (auto it = begin(_list); it != itEnd; ) { - std::string element = *it; + auto const& element = *it; bool first = (it == begin(_list)); ++it; if (!first) { if (it == itEnd && !_lastSeparator.empty()) - result += _lastSeparator; // last iteration + result << _lastSeparator; // last iteration else - result += _separator; + result << _separator; } - result += std::move(element); + result << element; } - return result; + return result.str(); } /// Joins collection of strings just like joinHumanReadable, but prepends the separator From 78ec8dd6f93bf5a5b4ca7582f9d491a4f66c3610 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 3 Feb 2025 11:46:27 +0100 Subject: [PATCH 0688/1340] Token: Use string view for isYulKeyword --- liblangutil/Token.cpp | 6 +++--- liblangutil/Token.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/liblangutil/Token.cpp b/liblangutil/Token.cpp index 8a860791f..1c5ae6f4e 100644 --- a/liblangutil/Token.cpp +++ b/liblangutil/Token.cpp @@ -134,20 +134,20 @@ std::string friendlyName(Token tok) } -static Token keywordByName(std::string const& _name) +static Token keywordByName(std::string_view const _name) { // The following macros are used inside TOKEN_LIST and cause non-keyword tokens to be ignored // and keywords to be put inside the keywords variable. #define KEYWORD(name, string, precedence) {string, Token::name}, #define TOKEN(name, string, precedence) - static std::map const keywords({TOKEN_LIST(TOKEN, KEYWORD)}); + static std::map> const keywords({TOKEN_LIST(TOKEN, KEYWORD)}); #undef KEYWORD #undef TOKEN auto it = keywords.find(_name); return it == keywords.end() ? Token::Identifier : it->second; } -bool isYulKeyword(std::string const& _literal) +bool isYulKeyword(std::string_view const _literal) { return _literal == "leave" || isYulKeyword(keywordByName(_literal)); } diff --git a/liblangutil/Token.h b/liblangutil/Token.h index d9438271c..bfbc89bb4 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -377,7 +377,7 @@ namespace TokenTraits return _token > Token::NonExperimentalEnd && _token < Token::ExperimentalEnd; } - bool isYulKeyword(std::string const& _literal); + bool isYulKeyword(std::string_view _literal); Token AssignmentToBinaryOp(Token op); From 40aad416cfe76095d9b216093996cdcaaa6b7f17 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 3 Feb 2025 11:54:12 +0100 Subject: [PATCH 0689/1340] Enable default test running for EOF --- test/TestCase.cpp | 2 +- test/libsolidity/SemanticTest.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/TestCase.cpp b/test/TestCase.cpp index 9505a2caa..104bd1bde 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -150,7 +150,7 @@ void EVMVersionRestrictedTestCase::processBytecodeFormatSetting() // EOF only available since Prague solAssert(!eofVersion.has_value() ||solidity::test::CommonOptions::get().evmVersion() >= langutil::EVMVersion::prague()); - std::string bytecodeFormatString = m_reader.stringSetting("bytecodeFormat", "legacy"); + std::string bytecodeFormatString = m_reader.stringSetting("bytecodeFormat", "legacy,>=EOFv1"); if (bytecodeFormatString == "legacy,>=EOFv1" || bytecodeFormatString == ">=EOFv1,legacy") return; diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index b0bdb95cb..0c3f2f3bc 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -91,7 +91,9 @@ SemanticTest::SemanticTest( if (m_runWithABIEncoderV1Only && !solidity::test::CommonOptions::get().useABIEncoderV1) m_shouldRun = false; - std::string compileViaYul = m_reader.stringSetting("compileViaYul", "also"); + auto const eofEnabled = solidity::test::CommonOptions::get().eofVersion().has_value(); + std::string compileViaYul = m_reader.stringSetting("compileViaYul", eofEnabled ? "true" : "also"); + if (m_runWithABIEncoderV1Only && compileViaYul != "false") BOOST_THROW_EXCEPTION(std::runtime_error( "ABIEncoderV1Only tests cannot be run via yul, " From 055561815b35c77ef71cc143027431f03566115d Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 3 Feb 2025 11:54:12 +0100 Subject: [PATCH 0690/1340] Omit running semantic and syntax tests when compileViaYul is false and EFO enabled. --- test/libsolidity/SemanticTest.cpp | 3 +++ test/libsolidity/SyntaxTest.cpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 0c3f2f3bc..1b66dd60f 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -94,6 +94,9 @@ SemanticTest::SemanticTest( auto const eofEnabled = solidity::test::CommonOptions::get().eofVersion().has_value(); std::string compileViaYul = m_reader.stringSetting("compileViaYul", eofEnabled ? "true" : "also"); + if (compileViaYul == "false" && eofEnabled) + m_shouldRun = false; + if (m_runWithABIEncoderV1Only && compileViaYul != "false") BOOST_THROW_EXCEPTION(std::runtime_error( "ABIEncoderV1Only tests cannot be run via yul, " diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 4fd3df7cf..894471054 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -53,6 +53,10 @@ SyntaxTest::SyntaxTest( m_compileViaYul = m_reader.stringSetting("compileViaYul", eofEnabled ? "true" : "false"); if (!util::contains(compileViaYulAllowedValues, m_compileViaYul)) BOOST_THROW_EXCEPTION(std::runtime_error("Invalid compileViaYul value: " + m_compileViaYul + ".")); + + if (m_compileViaYul == "false" && eofEnabled) + m_shouldRun = false; + m_optimiseYul = m_reader.boolSetting("optimize-yul", true); static std::map const pipelineStages = { From 934716b68529dbea6dc09d066d6cc8806c4e1811 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Mon, 3 Feb 2025 14:46:48 +0100 Subject: [PATCH 0691/1340] SMTChecker: Fix crash on external function call wrapped in 1-tuple The function call needs to be unwrapped from within nested parentheses to get the proper call expression. --- Changelog.md | 1 + libsolidity/formal/SMTEncoder.cpp | 2 +- .../external_call_extra_parentheses_1.sol | 9 +++++++++ .../external_call_extra_parentheses_2.sol | 12 ++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_1.sol create mode 100644 test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_2.sol diff --git a/Changelog.md b/Changelog.md index cceec2a73..cde5636cf 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Compiler Features: Bugfixes: * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. * SMTChecker: Fix SMT logic error when analyzing cross-contract getter call with BMC. + * SMTChecker: Fix SMT logic error when external call has extra effectless parentheses. * SMTChecker: Fix SMT logic error when initializing a fixed-sized-bytes array using string literals. * SMTChecker: Fix SMT logic error when translating invariants involving array store and select operations. * SMTChecker: Fix wrong encoding of string literals as arguments of ``ecrecover`` precompile. diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 2fecb734a..08fd4a256 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -2771,7 +2771,7 @@ TypePointers SMTEncoder::replaceUserTypes(TypePointers const& _types) std::pair SMTEncoder::functionCallExpression(FunctionCall const& _funCall) { - Expression const* callExpr = &_funCall.expression(); + Expression const* callExpr = innermostTuple(_funCall.expression()); auto const* callOptions = dynamic_cast(callExpr); if (callOptions) callExpr = &callOptions->expression(); diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_1.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_1.sol new file mode 100644 index 000000000..a071d0f15 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_1.sol @@ -0,0 +1,9 @@ +contract C { + function f() external {} + function g() public { + (this.f)(); + } +} +// ==== +// SMTEngine: chc +// ---- diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_2.sol new file mode 100644 index 000000000..bbff78aa7 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_extra_parentheses_2.sol @@ -0,0 +1,12 @@ +contract D { + function f() external {} +} + +contract C { + function g(D d) public { + ((d.f))(); + } +} +// ==== +// SMTEngine: chc +// ---- From 4c3b26ddc35971081c460f69cd09cef6c4211b7e Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Mon, 3 Feb 2025 14:52:21 +0100 Subject: [PATCH 0692/1340] SMTChecker: Small cleanup of handling function calls A redundant lambda has been removed. The same function is actually defined as a member of SMTEncoder An error message has been improved. --- libsolidity/formal/CHC.cpp | 11 ----------- libsolidity/formal/SMTEncoder.cpp | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index dd901bc38..d5a1fa580 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -927,17 +927,6 @@ void CHC::internalFunctionCall(FunctionCall const& _funCall) Expression const* calledExpr = &_funCall.expression(); auto funType = dynamic_cast(calledExpr->annotation().type); - auto contractAddressValue = [this](FunctionCall const& _f) { - auto [callExpr, callOptions] = functionCallExpression(_f); - - FunctionType const& funType = dynamic_cast(*callExpr->annotation().type); - if (funType.kind() == FunctionType::Kind::Internal) - return state().thisAddress(); - if (MemberAccess const* callBase = dynamic_cast(callExpr)) - return expr(callBase->expression()); - solAssert(false, "Unreachable!"); - }; - std::vector arguments; for (auto& arg: _funCall.sortedArguments()) arguments.push_back(&(*arg)); diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 08fd4a256..c1a4d61ee 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -2869,7 +2869,7 @@ smtutil::Expression SMTEncoder::contractAddressValue(FunctionCall const& _f) auto [funExpr, funOptions] = functionCallExpression(_f); if (MemberAccess const* callBase = dynamic_cast(funExpr)) return expr(callBase->expression()); - solAssert(false, "Unreachable!"); + smtAssert(false, "Unexpected function call type encountered while getting contract address!"); } VariableDeclaration const* SMTEncoder::publicGetter(Expression const& _expr) const { From f9adfa326092cb3814d3392f120a70ab90ec7841 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Tue, 4 Feb 2025 21:24:32 +0100 Subject: [PATCH 0693/1340] SMTChecker: Make innermostTuple return reference Instead of returning a pointer, to indicate that the method always returns a valid value (and does not need a check for null pointer), we can return a reference. As part of the refactoring, we can actually eliminate one usage of this method. --- libsolidity/formal/Predicate.cpp | 29 +++++-------- libsolidity/formal/SMTEncoder.cpp | 72 +++++++++++++++---------------- libsolidity/formal/SMTEncoder.h | 2 +- 3 files changed, 48 insertions(+), 55 deletions(-) diff --git a/libsolidity/formal/Predicate.cpp b/libsolidity/formal/Predicate.cpp index fe7c03fe1..4b7ca8edb 100644 --- a/libsolidity/formal/Predicate.cpp +++ b/libsolidity/formal/Predicate.cpp @@ -247,24 +247,17 @@ std::string Predicate::formatSummaryCall( { bool visit(MemberAccess const& _memberAccess) { - Expression const* memberExpr = SMTEncoder::innermostTuple(_memberAccess.expression()); - - Type const* exprType = memberExpr->annotation().type; - solAssert(exprType, ""); - if (exprType->category() == Type::Category::Magic) - if (auto const* identifier = dynamic_cast(memberExpr)) - { - ASTString const& name = identifier->name(); - auto memberName = _memberAccess.memberName(); - - // TODO remove this for 0.9.0 - if (name == "block" && memberName == "difficulty") - memberName = "prevrandao"; - - if (name == "block" || name == "msg" || name == "tx") - txVars.insert(name + "." + memberName); - } - + if (auto magicType = dynamic_cast(_memberAccess.expression().annotation().type)) + { + auto memberName = _memberAccess.memberName(); + auto magicKind = magicType->kind(); + // TODO remove this for 0.9.0 + if (magicKind == MagicType::Kind::Block && memberName == "difficulty") + memberName = "prevrandao"; + + if (magicKind == MagicType::Kind::Block || magicKind == MagicType::Kind::Message || magicKind == MagicType::Kind::Transaction) + txVars.insert(magicType->toString(true) + "." + memberName); + } return true; } diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index c1a4d61ee..7c826ab36 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -465,22 +465,22 @@ void SMTEncoder::endVisit(UnaryOperation const& _op) if (*_op.annotation().userDefinedFunction) return; - auto const* subExpr = innermostTuple(_op.subExpression()); + auto const& subExpr = innermostTuple(_op.subExpression()); auto type = _op.annotation().type; switch (_op.getOperator()) { case Token::Not: // ! { solAssert(smt::isBool(*type), ""); - defineExpr(_op, !expr(*subExpr)); + defineExpr(_op, !expr(subExpr)); break; } case Token::Inc: // ++ (pre- or postfix) case Token::Dec: // -- (pre- or postfix) { solAssert(smt::isInteger(*type) || smt::isFixedPoint(*type), ""); - solAssert(subExpr->annotation().willBeWrittenTo, ""); - auto innerValue = expr(*subExpr); + solAssert(subExpr.annotation().willBeWrittenTo, ""); + auto innerValue = expr(subExpr); auto newValue = arithmeticOperation( _op.getOperator() == Token::Inc ? Token::Add : Token::Sub, innerValue, @@ -489,34 +489,34 @@ void SMTEncoder::endVisit(UnaryOperation const& _op) _op ).first; defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue); - assignment(*subExpr, newValue); + assignment(subExpr, newValue); break; } case Token::Sub: // - { - defineExpr(_op, 0 - expr(*subExpr)); + defineExpr(_op, 0 - expr(subExpr)); break; } case Token::Delete: { - if (auto decl = identifierToVariable(*subExpr)) + if (auto decl = identifierToVariable(subExpr)) { m_context.newValue(*decl); m_context.setZeroValue(*decl); } else { - solAssert(m_context.knownExpression(*subExpr), ""); - auto const& symbVar = m_context.expression(*subExpr); + solAssert(m_context.knownExpression(subExpr), ""); + auto const& symbVar = m_context.expression(subExpr); symbVar->increaseIndex(); m_context.setZeroValue(*symbVar); if ( - dynamic_cast(subExpr) || - dynamic_cast(subExpr) + dynamic_cast(&subExpr) || + dynamic_cast(&subExpr) ) - indexOrMemberAssignment(*subExpr, symbVar->currentValue()); + indexOrMemberAssignment(subExpr, symbVar->currentValue()); // Empty push added a zero value anyway, so no need to delete extra. - else if (!isEmptyPush(*subExpr)) + else if (!isEmptyPush(subExpr)) solAssert(false, ""); } break; @@ -1398,14 +1398,14 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess) return true; } - Expression const* memberExpr = innermostTuple(_memberAccess.expression()); + Expression const& memberExpr = innermostTuple(_memberAccess.expression()); - auto const& exprType = memberExpr->annotation().type; + auto const& exprType = memberExpr.annotation().type; solAssert(exprType, ""); if (exprType->category() == Type::Category::Magic) { - if (auto const* identifier = dynamic_cast(memberExpr)) + if (auto const* identifier = dynamic_cast(&memberExpr)) { auto const& name = identifier->name(); solAssert(name == "block" || name == "msg" || name == "tx", ""); @@ -1458,14 +1458,14 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess) } else if (smt::isNonRecursiveStruct(*exprType)) { - memberExpr->accept(*this); - auto const& symbStruct = std::dynamic_pointer_cast(m_context.expression(*memberExpr)); + memberExpr.accept(*this); + auto const& symbStruct = std::dynamic_pointer_cast(m_context.expression(memberExpr)); defineExpr(_memberAccess, symbStruct->member(_memberAccess.memberName())); return false; } else if (exprType->category() == Type::Category::TypeType) { - auto const* decl = expressionToDeclaration(*memberExpr); + auto const* decl = expressionToDeclaration(memberExpr); if (dynamic_cast(decl)) { auto enumType = dynamic_cast(accessType); @@ -1488,10 +1488,10 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess) } else if (exprType->category() == Type::Category::Address) { - memberExpr->accept(*this); + memberExpr.accept(*this); if (_memberAccess.memberName() == "balance") { - defineExpr(_memberAccess, state().balance(expr(*memberExpr))); + defineExpr(_memberAccess, state().balance(expr(memberExpr))); setSymbolicUnknownValue(*m_context.expression(_memberAccess), m_context); m_uninterpretedTerms.insert(&_memberAccess); return false; @@ -1499,10 +1499,10 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess) } else if (exprType->category() == Type::Category::Array) { - memberExpr->accept(*this); + memberExpr.accept(*this); if (_memberAccess.memberName() == "length") { - auto symbArray = std::dynamic_pointer_cast(m_context.expression(*memberExpr)); + auto symbArray = std::dynamic_pointer_cast(m_context.expression(memberExpr)); solAssert(symbArray, ""); defineExpr(_memberAccess, symbArray->length()); m_uninterpretedTerms.insert(&_memberAccess); @@ -2174,16 +2174,16 @@ void SMTEncoder::assignment( void SMTEncoder::tupleAssignment(Expression const& _left, Expression const& _right) { - auto lTuple = dynamic_cast(innermostTuple(_left)); + auto lTuple = dynamic_cast(&innermostTuple(_left)); solAssert(lTuple, ""); - Expression const* right = innermostTuple(_right); + Expression const& right = innermostTuple(_right); auto const& lComponents = lTuple->components(); // If both sides are tuple expressions, we individually and potentially // recursively assign each pair of components. // This is because of potential type conversion. - if (auto rTuple = dynamic_cast(right)) + if (auto rTuple = dynamic_cast(&right)) { auto const& rComponents = rTuple->components(); solAssert(lComponents.size() == rComponents.size(), ""); @@ -2204,13 +2204,13 @@ void SMTEncoder::tupleAssignment(Expression const& _left, Expression const& _rig } else { - auto rType = dynamic_cast(right->annotation().type); + auto rType = dynamic_cast(right.annotation().type); solAssert(rType, ""); auto const& rComponents = rType->components(); solAssert(lComponents.size() == rComponents.size(), ""); - auto symbRight = expr(*right); + auto symbRight = expr(right); solAssert(symbRight.sort->kind == smtutil::Kind::Tuple, ""); for (unsigned i = 0; i < lComponents.size(); ++i) @@ -2737,11 +2737,11 @@ Type const* SMTEncoder::keyType(Type const* _type) solAssert(false, ""); } -Expression const* SMTEncoder::innermostTuple(Expression const& _expr) +Expression const& SMTEncoder::innermostTuple(Expression const& _expr) { auto const* tuple = dynamic_cast(&_expr); if (!tuple || tuple->isInlineArray()) - return &_expr; + return _expr; Expression const* expr = tuple; while (tuple && !tuple->isInlineArray() && tuple->components().size() == 1) @@ -2750,7 +2750,7 @@ Expression const* SMTEncoder::innermostTuple(Expression const& _expr) tuple = dynamic_cast(expr); } solAssert(expr, ""); - return expr; + return *expr; } Type const* SMTEncoder::underlyingType(Type const* _type) @@ -2771,7 +2771,7 @@ TypePointers SMTEncoder::replaceUserTypes(TypePointers const& _types) std::pair SMTEncoder::functionCallExpression(FunctionCall const& _funCall) { - Expression const* callExpr = innermostTuple(_funCall.expression()); + Expression const* callExpr = &innermostTuple(_funCall.expression()); auto const* callOptions = dynamic_cast(callExpr); if (callOptions) callExpr = &callOptions->expression(); @@ -2783,7 +2783,7 @@ Expression const* SMTEncoder::cleanExpression(Expression const& _expr) { auto const* expr = &_expr; if (auto const* tuple = dynamic_cast(expr)) - return cleanExpression(*innermostTuple(*tuple)); + return cleanExpression(innermostTuple(*tuple)); if (auto const* functionCall = dynamic_cast(expr)) if (*functionCall->annotation().kind == FunctionCallKind::TypeConversion) { @@ -2918,7 +2918,7 @@ FunctionDefinition const* SMTEncoder::functionCallToDefinition( if (TupleExpression const* fun = dynamic_cast(calledExpr)) { solAssert(fun->components().size() == 1, ""); - calledExpr = innermostTuple(*calledExpr); + calledExpr = &innermostTuple(*calledExpr); } auto resolveVirtual = [&](auto const* _ref) -> FunctionDefinition const* { @@ -3220,8 +3220,8 @@ std::vector SMTEncoder::symbolicArguments( unsigned firstParam = 0; if (_boundArgumentCall) { - Expression const* calledExpr = innermostTuple(*_boundArgumentCall.value()); - auto const& attachedFunction = dynamic_cast(calledExpr); + Expression const& calledExpr = innermostTuple(*_boundArgumentCall.value()); + auto const& attachedFunction = dynamic_cast(&calledExpr); solAssert(attachedFunction, ""); args.push_back(expr(attachedFunction->expression(), _funParameters.front()->type())); firstParam = 1; diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index d79ae8f82..c6c549151 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -71,7 +71,7 @@ class SMTEncoder: public ASTConstVisitor /// @returns the innermost element in a chain of 1-tuples if applicable, /// otherwise _expr. - static Expression const* innermostTuple(Expression const& _expr); + static Expression const& innermostTuple(Expression const& _expr); /// @returns the underlying type if _type is UserDefinedValueType, /// and _type otherwise. From bbb0caaaf9a570351e03064e402d959125a6b6b2 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Tue, 4 Feb 2025 13:06:27 +0100 Subject: [PATCH 0694/1340] SMTChecker: Fix internal error involving string to bytes conversion This happened when analyzing deployment of a contract and the type conversion was necessary for the constructor argument. --- Changelog.md | 1 + libsolidity/formal/CHC.cpp | 2 +- ...fixed_bytes_constructor_for_deployment.sol | 21 +++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/smtCheckerTests/typecast/string_literal_to_fixed_bytes_constructor_for_deployment.sol diff --git a/Changelog.md b/Changelog.md index cde5636cf..be3209702 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Compiler Features: Bugfixes: * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. * SMTChecker: Fix SMT logic error when analyzing cross-contract getter call with BMC. + * SMTChecker: Fix SMT logic error when contract deployment involves string literal to fixed bytes conversion. * SMTChecker: Fix SMT logic error when external call has extra effectless parentheses. * SMTChecker: Fix SMT logic error when initializing a fixed-sized-bytes array using string literals. * SMTChecker: Fix SMT logic error when translating invariants involving array store and select operations. diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index d5a1fa580..bd3b0d988 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -854,7 +854,7 @@ void CHC::visitDeployment(FunctionCall const& _funCall) auto const& params = constructor->parameters(); solAssert(args.size() == params.size(), ""); for (auto [arg, param]: ranges::zip_view(args, params)) - m_context.addAssertion(expr(*arg) == m_context.variable(*param)->currentValue()); + m_context.addAssertion(expr(*arg, param->type()) == m_context.variable(*param)->currentValue()); } for (auto var: stateVariablesIncludingInheritedAndPrivate(*contract)) m_context.variable(*var)->increaseIndex(); diff --git a/test/libsolidity/smtCheckerTests/typecast/string_literal_to_fixed_bytes_constructor_for_deployment.sol b/test/libsolidity/smtCheckerTests/typecast/string_literal_to_fixed_bytes_constructor_for_deployment.sol new file mode 100644 index 000000000..5226f886d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/typecast/string_literal_to_fixed_bytes_constructor_for_deployment.sol @@ -0,0 +1,21 @@ +contract A { + bytes3 public a; + + constructor(bytes3 _a) payable { + a = _a; + } +} + +contract B { + A a; + + constructor() payable { + a = (new A){value: 10}("abc"); + assert(a.a() == 0x616263); + } +} +// ==== +// SMTEngine: chc +// SMTExtCalls: trusted +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 455da960987d47b95cc137b42d75bb4c889a689b Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 22 Jan 2025 21:44:34 +0100 Subject: [PATCH 0695/1340] Bump evmone to v0.13.0 in buildpack-deps --- .../docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz | 4 ++-- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 | 6 +++--- scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 | 6 +++--- scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index 1dbf48e9b..b5cd64a23 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -24,7 +24,7 @@ # FIXME: Workaround for Boost 1.83.0 build failure when using Clang 18 (default since https://github.com/google/oss-fuzz/pull/11714) # See: https://github.com/google/oss-fuzz/blob/5a9322260c4c66e7eb3e5d922b9fee6621ffd8da/projects/solidity/Dockerfile#L17C1-L18C139 FROM gcr.io/oss-fuzz-base/base-builder@sha256:19782f7fe8092843368894dbc471ce9b30dd6a2813946071a36e8b05f5b1e27e AS base -LABEL version="9" +LABEL version="10" ARG DEBIAN_FRONTEND=noninteractive @@ -130,7 +130,7 @@ RUN set -ex; \ # EVMONE RUN set -ex; \ cd /usr/src; \ - git clone --branch="v0.11.0" --recurse-submodules https://github.com/ethereum/evmone.git; \ + git clone --branch="v0.13.0" --recurse-submodules https://github.com/ethereum/evmone.git; \ cd evmone; \ mkdir build; \ cd build; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index 9b365a374..f66c1d8fd 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -22,7 +22,7 @@ # (c) 2016-2025 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="1" +LABEL version="2" ARG DEBIAN_FRONTEND=noninteractive @@ -94,8 +94,8 @@ FROM base AS libraries # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ rm -rf /usr/src/evmone.tar.gz diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 index eb5439f59..fc372c709 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="2" +LABEL version="3" ARG DEBIAN_FRONTEND=noninteractive @@ -97,8 +97,8 @@ FROM base AS libraries # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ rm -rf /usr/src/evmone.tar.gz diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang index 3b1e3e614..91a31c263 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="3" +LABEL version="4" ARG DEBIAN_FRONTEND=noninteractive @@ -99,8 +99,8 @@ ENV CXX clang++ # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "1c7b5eba0c8c3b3b2a7a05101e2d01a13a2f84b323989a29be66285dba4136ce /usr/src/evmone.tar.gz"; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ rm -rf /usr/src/evmone.tar.gz From 6135aa167c431ddec6f08d531182daf868f87a95 Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 4 Feb 2025 11:40:25 +0100 Subject: [PATCH 0696/1340] Fix ossfuzz build and force use of libc++ --- .../Dockerfile.ubuntu.clang.ossfuzz | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index b5cd64a23..bf228d617 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -21,9 +21,7 @@ # # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ -# FIXME: Workaround for Boost 1.83.0 build failure when using Clang 18 (default since https://github.com/google/oss-fuzz/pull/11714) -# See: https://github.com/google/oss-fuzz/blob/5a9322260c4c66e7eb3e5d922b9fee6621ffd8da/projects/solidity/Dockerfile#L17C1-L18C139 -FROM gcr.io/oss-fuzz-base/base-builder@sha256:19782f7fe8092843368894dbc471ce9b30dd6a2813946071a36e8b05f5b1e27e AS base +FROM gcr.io/oss-fuzz-base/base-builder AS base LABEL version="10" ARG DEBIAN_FRONTEND=noninteractive @@ -37,6 +35,8 @@ RUN apt-get update; \ git \ jq \ libbz2-dev \ + libc++-18-dev \ + libc++abi-18-dev \ liblzma-dev \ libtool \ lsof \ @@ -64,6 +64,10 @@ RUN apt-get update; \ requests \ tabulate; +# Ensure that the expected version of Clang is installed, as the base image may update it in the future: +# https://github.com/google/oss-fuzz/blob/5e96edbdf285045cc82dbca5600cbe994a3b1a74/infra/base-images/base-clang/checkout_build_install_llvm.sh#L57 +RUN test "$(clang -dumpversion | cut -d. -f1)" = "18" || (echo "Error: Clang 18 not found!" && exit 1) + FROM base AS libraries # Boost @@ -74,9 +78,16 @@ RUN set -ex; \ tar -xf boost.tar.bz2; \ rm boost.tar.bz2; \ cd boost_1_83_0; \ - CXXFLAGS="-std=c++17 -stdlib=libc++ -pthread" LDFLAGS="-stdlib=libc++" ./bootstrap.sh --with-toolset=clang --prefix=/usr; \ - ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" headers; \ - ./b2 toolset=clang cxxflags="-stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" \ + export CXXFLAGS="-std=c++20 -nostdinc++ -I/usr/lib/llvm-18/include/c++/v1 -pthread"; \ + export LDFLAGS="-stdlib=libc++ -L/usr/lib/llvm-18/lib"; \ + ./bootstrap.sh --with-toolset=clang --prefix=/usr; \ + ./b2 toolset=clang \ + cxxflags="${CXXFLAGS}" \ + linkflags="${LDFLAGS}" \ + headers; \ + ./b2 toolset=clang \ + cxxflags="${CXXFLAGS}" \ + linkflags="${LDFLAGS}" \ link=static variant=release runtime-link=static \ system filesystem unit_test_framework program_options \ install -j $(($(nproc)/2)); \ @@ -111,10 +122,12 @@ RUN set -ex; \ rm -f /opt/cvc5.zip; # OSSFUZZ: libprotobuf-mutator +# Use commit prior to libprotobuf upgrade that broke solidity build +# See https://github.com/google/oss-fuzz/issues/10237 RUN set -ex; \ git clone https://github.com/google/libprotobuf-mutator.git /usr/src/libprotobuf-mutator; \ cd /usr/src/libprotobuf-mutator; \ - git checkout 3521f47a2828da9ace403e4ecc4aece1a84feb36; \ + git reset --hard 212a7be1eb08e7f9c79732d2aab9b2097085d936; \ mkdir build; \ cd build; \ cmake .. -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON \ @@ -134,7 +147,9 @@ RUN set -ex; \ cd evmone; \ mkdir build; \ cd build; \ - CXX=clang++ cmake -G Ninja -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX="/usr" ..; \ + CXX=clang++ cmake .. -G Ninja \ + -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS="-stdlib=libc++" \ + -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX="/usr"; \ ninja; \ ninja install/strip; \ rm -rf /usr/src/evmone From cdd02d5b182a2092ccb2a9fb8c40c678f7f4399e Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 4 Feb 2025 13:13:48 +0100 Subject: [PATCH 0697/1340] Disable ccache --- scripts/ci/build_ossfuzz.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/build_ossfuzz.sh b/scripts/ci/build_ossfuzz.sh index c44f9baba..64d992994 100755 --- a/scripts/ci/build_ossfuzz.sh +++ b/scripts/ci/build_ossfuzz.sh @@ -18,7 +18,7 @@ function generate_protobuf_bindings function build_fuzzers { cd "${BUILDDIR}" - cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" \ + cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" -DCCACHE=OFF \ -DCMAKE_TOOLCHAIN_FILE="${ROOTDIR}"/cmake/toolchains/libfuzzer.cmake make ossfuzz ossfuzz_proto ossfuzz_abiv2 -j 4 } From 719fc8b083e2d124182cd2a628065fa102461f7c Mon Sep 17 00:00:00 2001 From: r0qs Date: Tue, 4 Feb 2025 13:22:29 +0100 Subject: [PATCH 0698/1340] Remove unused symlink for dropped Ubuntu 20.04 image --- scripts/ci/buildpack-deps_test_ubuntu2004.sh | 1 - 1 file changed, 1 deletion(-) delete mode 120000 scripts/ci/buildpack-deps_test_ubuntu2004.sh diff --git a/scripts/ci/buildpack-deps_test_ubuntu2004.sh b/scripts/ci/buildpack-deps_test_ubuntu2004.sh deleted file mode 120000 index feb6a5927..000000000 --- a/scripts/ci/buildpack-deps_test_ubuntu2004.sh +++ /dev/null @@ -1 +0,0 @@ -./build.sh \ No newline at end of file From 7c15253100721e67e2e4da3f96ae1353311044db Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 22 Jan 2025 21:45:40 +0100 Subject: [PATCH 0699/1340] Bump evmone to v0.13.0 in CI --- .circleci/config.yml | 16 ++++++++-------- .circleci/osx_install_dependencies.sh | 4 ++-- scripts/install_evmone.ps1 | 2 +- test/Common.h | 6 +++--- ...operator_matches_equivalent_function_call.sol | 4 +--- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0f75e76cd..d26ef3bd4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,20 +13,20 @@ parameters: default: "solbuildpackpusher/solidity-buildpack-deps@sha256:1f387a77be889f65a2a25986a5c5eccc88cec23fabe6aeaf351790751145c81e" ubuntu-2204-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-1 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:d61b0a4a49ac106e6747c1e8037882f1d421b537dba6c96c0a400ca105d85d4d" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-2 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:877fcc2589779f8245770711d10db92eda97d338dae76b6a9f27dde1a41b3aa0" ubuntu-2404-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-2 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:92efa8581887e5389b29d3a150112a8433a04ebf5fddf2c65ed6794b4cdf1fe3" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-3 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:ef6a91d7f1434c67fb9e05c6136d80f71c0ad9198479e1a88e3437680993cda4" ubuntu-2404-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-3 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:534c4eea1ba370a85cf3c106b4a30b43152ba4f695fab5e18577009a5e272146" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-4 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:97fb2d1bc002b3624161f539a1d29543c0e6c6f4d9a61f611b9b60e99e18f377" ubuntu-clang-ossfuzz-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-9 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c95b24958c92821f1d409b97fcc4930576603063f088a98e780283ee7ec5b575" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-10 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:bd55d9a3b13c88608709ec442188c414d30f4c49f23dc2ce8b76bf8c90603fc7" emscripten-docker-image: type: string # NOTE: Please remember to update the `scripts/build_emscripten.sh` whenever the hash of this image changes. diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index f618bd9d3..e7a0b9ddf 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -110,10 +110,10 @@ then rm -rf "$z3_dir" # evmone - evmone_version="0.12.0" + evmone_version="0.13.0" evmone_package="evmone-${evmone_version}-darwin-arm64.tar.gz" wget "https://github.com/ethereum/evmone/releases/download/v${evmone_version}/${evmone_package}" - validate_checksum "$evmone_package" e164e0d2b985cc1cca07b501538b2e804bf872d1d8d531f9241d518a886234a6 + validate_checksum "$evmone_package" 49fe6cc35e0e13c48ca2f29a6b85a47f7b25dcd427e14254000d3bc29cddf2a6 sudo tar xzpf "$evmone_package" -C /usr/local rm "$evmone_package" fi diff --git a/scripts/install_evmone.ps1 b/scripts/install_evmone.ps1 index 7295afa01..53fc7b6ee 100644 --- a/scripts/install_evmone.ps1 +++ b/scripts/install_evmone.ps1 @@ -3,6 +3,6 @@ $ErrorActionPreference = "Stop" # Needed for Invoke-WebRequest to work via CI. $progressPreference = "silentlyContinue" -Invoke-WebRequest -URI "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-windows-amd64.zip" -OutFile "evmone.zip" +Invoke-WebRequest -URI "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-windows-amd64.zip" -OutFile "evmone.zip" tar -xf evmone.zip "bin/evmone.dll" mv bin/evmone.dll deps/ diff --git a/test/Common.h b/test/Common.h index 866f6945a..27c208134 100644 --- a/test/Common.h +++ b/test/Common.h @@ -39,13 +39,13 @@ namespace solidity::test #ifdef _WIN32 static constexpr auto evmoneFilename = "evmone.dll"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-windows-amd64.zip"; +static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-windows-amd64.zip"; #elif defined(__APPLE__) static constexpr auto evmoneFilename = "libevmone.dylib"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-darwin-arm64.tar.gz"; +static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-darwin-arm64.tar.gz"; #else static constexpr auto evmoneFilename = "libevmone.so"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.12.0/evmone-0.12.0-linux-x86_64.tar.gz"; +static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz"; #endif struct ConfigException: public util::Exception {}; diff --git a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol index 76ad6db55..76078a582 100644 --- a/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol +++ b/test/libsolidity/smtCheckerTests/operators/userDefined/user_defined_operator_matches_equivalent_function_call.sol @@ -52,11 +52,9 @@ contract C { } } // ==== -// SMTEngine: all +// SMTEngine: chc // SMTTargets: assert // ---- // Warning 6328: (2209-2235): CHC: Assertion violation might happen here. // Warning 6328: (2245-2271): CHC: Assertion violation might happen here. // Info 1391: CHC: 14 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -// Warning 7812: (2245-2271): BMC: Assertion violation might happen here. -// Info 6002: BMC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 6b4ee52513d66f0da68b688ede59c24816dd0b6a Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 3 Feb 2025 21:12:54 +0100 Subject: [PATCH 0700/1340] Introduces EVM version Osaka --- .circleci/soltest_all.sh | 2 +- Changelog.md | 1 + docs/using-the-compiler.rst | 3 ++- liblangutil/EVMVersion.h | 8 ++++++-- scripts/tests.sh | 2 +- test/EVMHost.cpp | 2 ++ test/tools/ossfuzz/protoToYul.cpp | 2 ++ test/tools/ossfuzz/yulProto.proto | 1 + 8 files changed, 16 insertions(+), 5 deletions(-) diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 1c7882448..1e765c6f9 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -31,7 +31,7 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" -DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shanghai cancun prague) +DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shanghai cancun prague osaka) EVMS_WITH_EOF=(prague) # Deserialize the EVM_VALUES array if it was provided as argument or diff --git a/Changelog.md b/Changelog.md index be3209702..0bf7cb988 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: * Error Reporting: Errors reported during code generation now point at the location of the contract when more fine-grained location is not available. + * EVM: Support for the EVM version "Osaka". * SMTChecker: Support `block.blobbasefee` and `blobhash`. * SMTChecker: Z3 is now a runtime dependency, not a build dependency (except for emscripten build). * Yul Parser: Make name clash with a builtin a non-fatal error. diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 48151a637..a5d5b08cc 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -182,6 +182,7 @@ at each version. Backward compatibility is not guaranteed between each version. - Opcode ``mcopy`` is available in assembly (see `EIP-5656 `_). - Opcodes ``tstore`` and ``tload`` are available in assembly (see `EIP-1153 `_). - ``prague`` (**experimental**) +- ``osaka`` (**experimental**) .. index:: ! standard JSON, ! --standard-json .. _compiler-api: @@ -349,7 +350,7 @@ Input Description // Version of the EVM to compile for. // Affects type checking and code generation. Can be homestead, // tangerineWhistle, spuriousDragon, byzantium, constantinople, - // petersburg, istanbul, berlin, london, paris, shanghai, cancun (default) or prague (experimental). + // petersburg, istanbul, berlin, london, paris, shanghai, cancun (default), prague (experimental) or osaka (experimental). "evmVersion": "cancun", // Optional: Change compilation pipeline to go through the Yul intermediate representation. // This is false by default. diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 2201f3c9d..6566f3a4a 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -64,6 +64,7 @@ class EVMVersion: static EVMVersion shanghai() { return {Version::Shanghai}; } static EVMVersion cancun() { return {Version::Cancun}; } static EVMVersion prague() { return {Version::Prague}; } + static EVMVersion osaka() { return {Version::Osaka}; } static std::vector allVersions() { return { @@ -80,6 +81,7 @@ class EVMVersion: shanghai(), cancun(), prague(), + osaka(), }; } @@ -92,7 +94,7 @@ class EVMVersion: } bool isExperimental() const { - return m_version == Version::Prague; + return *this > EVMVersion{}; } bool operator==(EVMVersion const& _other) const { return m_version == _other.m_version; } @@ -115,6 +117,7 @@ class EVMVersion: case Version::Shanghai: return "shanghai"; case Version::Cancun: return "cancun"; case Version::Prague: return "prague"; + case Version::Osaka: return "osaka"; } util::unreachable(); } @@ -155,7 +158,8 @@ class EVMVersion: Paris, Shanghai, Cancun, - Prague + Prague, + Osaka, }; EVMVersion(Version _version): m_version(_version) {} diff --git a/scripts/tests.sh b/scripts/tests.sh index dfbc04773..3d2849369 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -105,7 +105,7 @@ EVM_VERSIONS="homestead byzantium" if [ -z "$CI" ] then - EVM_VERSIONS+=" constantinople petersburg istanbul berlin london paris shanghai cancun prague" + EVM_VERSIONS+=" constantinople petersburg istanbul berlin london paris shanghai cancun prague osaka" fi # And then run the Solidity unit-tests in the matrix combination of optimizer / no optimizer diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 897f01c68..7df39bf71 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -134,6 +134,8 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm): m_evmRevision = EVMC_CANCUN; else if (_evmVersion == langutil::EVMVersion::prague()) m_evmRevision = EVMC_PRAGUE; + else if (_evmVersion == langutil::EVMVersion::osaka()) + m_evmRevision = EVMC_OSAKA; else assertThrow(false, Exception, "Unsupported EVM version"); diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 5a57b779d..cc5f68e71 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -121,6 +121,8 @@ EVMVersion ProtoConverter::evmVersionMapping(Program_Version const& _ver) return EVMVersion::cancun(); case Program::PRAGUE: return EVMVersion::prague(); + case Program::OSAKA: + return EVMVersion::osaka(); } } diff --git a/test/tools/ossfuzz/yulProto.proto b/test/tools/ossfuzz/yulProto.proto index 15ac01396..a22aacb0d 100644 --- a/test/tools/ossfuzz/yulProto.proto +++ b/test/tools/ossfuzz/yulProto.proto @@ -407,6 +407,7 @@ message Program { SHANGHAI = 10; CANCUN = 11; PRAGUE = 12; + OSAKA = 13; } oneof program_oneof { Block block = 1; From 462fd19f9c11dc554e3b2052aaa8a1803ac0c482 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 3 Feb 2025 21:16:08 +0100 Subject: [PATCH 0701/1340] Move EOF support to Osaka Rename tests --- .circleci/soltest_all.sh | 2 +- liblangutil/EVMVersion.cpp | 4 ++-- liblangutil/EVMVersion.h | 3 +++ libyul/AsmAnalysis.cpp | 5 ++--- libyul/backends/evm/EVMDialect.cpp | 7 +++---- libyul/backends/evm/EVMObjectCompiler.cpp | 8 ++++---- test/Common.cpp | 2 +- test/TestCase.cpp | 5 ++--- test/cmdlineTests/strict_asm_eof_container_osaka/args | 1 + .../input.yul | 0 .../output | 2 +- test/cmdlineTests/strict_asm_eof_container_prague/args | 1 - test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args | 1 + .../input.yul | 0 .../output | 2 +- test/cmdlineTests/strict_asm_eof_dataloadn_prague/args | 1 - .../functionCalls/eof/calloptions_on_staticcall.sol | 1 - .../objectCompiler/eof/creation_with_immutables.yul | 1 - test/libyul/objectCompiler/eof/dataloadn.yul | 1 - .../objectCompiler/eof/prune_unreferenced_container.yul | 1 - test/libyul/objectCompiler/eof/rjumps.yul | 1 - .../eof/auxdataloadn_in_eof_invalid_literal_type.yul | 1 - test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul | 1 - 23 files changed, 22 insertions(+), 29 deletions(-) create mode 100644 test/cmdlineTests/strict_asm_eof_container_osaka/args rename test/cmdlineTests/{strict_asm_eof_container_prague => strict_asm_eof_container_osaka}/input.yul (100%) rename test/cmdlineTests/{strict_asm_eof_container_prague => strict_asm_eof_container_osaka}/output (96%) delete mode 100644 test/cmdlineTests/strict_asm_eof_container_prague/args create mode 100644 test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args rename test/cmdlineTests/{strict_asm_eof_dataloadn_prague => strict_asm_eof_dataloadn_osaka}/input.yul (100%) rename test/cmdlineTests/{strict_asm_eof_dataloadn_prague => strict_asm_eof_dataloadn_osaka}/output (88%) delete mode 100644 test/cmdlineTests/strict_asm_eof_dataloadn_prague/args diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 1e765c6f9..216b1ee38 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -32,7 +32,7 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" source "${REPODIR}/scripts/common.sh" DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shanghai cancun prague osaka) -EVMS_WITH_EOF=(prague) +EVMS_WITH_EOF=(osaka) # Deserialize the EVM_VALUES array if it was provided as argument or # set EVM_VALUES to the default values. diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index ac087b8fc..30df93796 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -28,8 +28,8 @@ using namespace solidity::langutil; bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersion) const { - // EOF version can be only defined since prague - assert(!_eofVersion.has_value() || *this >= prague()); + // EOF version can be only defined since osaka + assert(!_eofVersion.has_value() || *this >= EVMVersion::firstWithEOF()); switch (_opcode) { diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 6566f3a4a..a159f2e4b 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -93,6 +93,8 @@ class EVMVersion: return std::nullopt; } + static EVMVersion firstWithEOF() { return {Version::Osaka}; } + bool isExperimental() const { return *this > EVMVersion{}; } @@ -137,6 +139,7 @@ class EVMVersion: bool hasBlobHash() const { return *this >= cancun(); } bool hasMcopy() const { return *this >= cancun(); } bool supportsTransientStorage() const { return *this >= cancun(); } + bool supportsEOF() const { return *this >= firstWithEOF(); } bool hasOpcode(evmasm::Instruction _opcode, std::optional _eofVersion) const; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index b6dcbb08e..7c82d788f 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -695,9 +695,8 @@ bool AsmAnalyzer::validateInstructions(std::string_view _instructionIdentifier, if (builtinHandle && defaultEVMDialect.builtin(*builtinHandle).instruction.has_value()) return validateInstructions(*defaultEVMDialect.builtin(*builtinHandle).instruction, _location); - solAssert(!m_eofVersion.has_value() || (*m_eofVersion == 1 && m_evmVersion == langutil::EVMVersion::prague())); - // TODO: Change `prague()` to `EVMVersion{}` once EOF gets deployed - auto const& eofDialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion::prague(), 1); + solAssert(!m_eofVersion.has_value() || *m_eofVersion == 1); + auto const& eofDialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion::firstWithEOF(), 1); auto const eofBuiltinHandle = eofDialect.findBuiltin(_instructionIdentifier); if (eofBuiltinHandle) { diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 611e95c39..4fa78f023 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -155,13 +155,12 @@ std::set> createReservedIdentifiers(langutil::EVMVersio auto eofIdentifiersException = [&](evmasm::Instruction _instr) -> bool { - solAssert(!_eofVersion.has_value() || (*_eofVersion == 1 && _evmVersion == langutil::EVMVersion::prague())); + solAssert(!_eofVersion.has_value() || (*_eofVersion == 1 && _evmVersion.supportsEOF())); if (_eofVersion.has_value()) // For EOF every instruction is reserved identifier. return false; - else - return langutil::EVMVersion::prague().hasOpcode(_instr, 1) && - !langutil::EVMVersion::prague().hasOpcode(_instr, std::nullopt); + return langutil::EVMVersion::firstWithEOF().hasOpcode(_instr, 1) && + !langutil::EVMVersion::firstWithEOF().hasOpcode(_instr, std::nullopt); }; std::set> reserved; diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index fb61e70f6..30f06bc97 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -76,10 +76,10 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) yulAssert(_object.analysisInfo, "No analysis info."); yulAssert(_object.hasCode(), "No code."); if (evmDialect->eofVersion().has_value()) - yulAssert( - _optimize && (evmDialect->evmVersion() >= langutil::EVMVersion::prague()), - "Experimental EOF support is only available for optimized via-IR compilation and the most recent EVM version." - ); + { + solUnimplementedAssert(_optimize, "EOF supported only for optimized compilation via IR."); + yulAssert(evmDialect->evmVersion().supportsEOF()); + } if (_optimize && evmDialect->evmVersion().canOverchargeGasForCall()) { auto stackErrors = OptimizedEVMCodeTransform::run( diff --git a/test/Common.cpp b/test/Common.cpp index 30738dcfc..bb25d203b 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -162,7 +162,7 @@ void CommonOptions::validate() const std::cout << std::endl << "DO NOT COMMIT THE UPDATED EXPECTATIONS." << std::endl << std::endl; } - assertThrow(!eofVersion().has_value() || evmVersion() >= langutil::EVMVersion::prague(), ConfigException, "EOF is unavailable before Prague fork."); + assertThrow(!eofVersion().has_value() || evmVersion().supportsEOF(), ConfigException, "EOF is unavailable before Osaka fork."); } bool CommonOptions::parse(int argc, char const* const* argv) diff --git a/test/TestCase.cpp b/test/TestCase.cpp index 104bd1bde..da47c26fd 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -146,9 +146,8 @@ void EVMVersionRestrictedTestCase::processEVMVersionSetting() void EVMVersionRestrictedTestCase::processBytecodeFormatSetting() { std::optional eofVersion = solidity::test::CommonOptions::get().eofVersion(); - // TODO: Update if EOF moved to Osaka - // EOF only available since Prague - solAssert(!eofVersion.has_value() ||solidity::test::CommonOptions::get().evmVersion() >= langutil::EVMVersion::prague()); + // EOF only available since Osaka + solAssert(!eofVersion.has_value() || solidity::test::CommonOptions::get().evmVersion().supportsEOF()); std::string bytecodeFormatString = m_reader.stringSetting("bytecodeFormat", "legacy,>=EOFv1"); if (bytecodeFormatString == "legacy,>=EOFv1" || bytecodeFormatString == ">=EOFv1,legacy") diff --git a/test/cmdlineTests/strict_asm_eof_container_osaka/args b/test/cmdlineTests/strict_asm_eof_container_osaka/args new file mode 100644 index 000000000..60abde356 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_container_osaka/args @@ -0,0 +1 @@ + --strict-assembly --experimental-eof-version 1 --evm-version osaka --asm --ir-optimized --bin --debug-info none diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/input.yul b/test/cmdlineTests/strict_asm_eof_container_osaka/input.yul similarity index 100% rename from test/cmdlineTests/strict_asm_eof_container_prague/input.yul rename to test/cmdlineTests/strict_asm_eof_container_osaka/input.yul diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/output b/test/cmdlineTests/strict_asm_eof_container_osaka/output similarity index 96% rename from test/cmdlineTests/strict_asm_eof_container_prague/output rename to test/cmdlineTests/strict_asm_eof_container_osaka/output index d38adba18..81f01798a 100644 --- a/test/cmdlineTests/strict_asm_eof_container_prague/output +++ b/test/cmdlineTests/strict_asm_eof_container_osaka/output @@ -1,5 +1,5 @@ -======= strict_asm_eof_container_prague/input.yul (EVM) ======= +======= strict_asm_eof_container_osaka/input.yul (EVM) ======= Pretty printed source: object "object" { diff --git a/test/cmdlineTests/strict_asm_eof_container_prague/args b/test/cmdlineTests/strict_asm_eof_container_prague/args deleted file mode 100644 index 0078e6e68..000000000 --- a/test/cmdlineTests/strict_asm_eof_container_prague/args +++ /dev/null @@ -1 +0,0 @@ - --strict-assembly --experimental-eof-version 1 --evm-version prague --asm --ir-optimized --bin --debug-info none diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args new file mode 100644 index 000000000..60abde356 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args @@ -0,0 +1 @@ + --strict-assembly --experimental-eof-version 1 --evm-version osaka --asm --ir-optimized --bin --debug-info none diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/input.yul b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/input.yul similarity index 100% rename from test/cmdlineTests/strict_asm_eof_dataloadn_prague/input.yul rename to test/cmdlineTests/strict_asm_eof_dataloadn_osaka/input.yul diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output similarity index 88% rename from test/cmdlineTests/strict_asm_eof_dataloadn_prague/output rename to test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output index 5d2115f95..677c49b88 100644 --- a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/output +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output @@ -1,5 +1,5 @@ -======= strict_asm_eof_dataloadn_prague/input.yul (EVM) ======= +======= strict_asm_eof_dataloadn_osaka/input.yul (EVM) ======= Pretty printed source: object "a" { diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/args b/test/cmdlineTests/strict_asm_eof_dataloadn_prague/args deleted file mode 100644 index 0078e6e68..000000000 --- a/test/cmdlineTests/strict_asm_eof_dataloadn_prague/args +++ /dev/null @@ -1 +0,0 @@ - --strict-assembly --experimental-eof-version 1 --evm-version prague --asm --ir-optimized --bin --debug-info none diff --git a/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_staticcall.sol b/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_staticcall.sol index f63837dcf..d43fb5969 100644 --- a/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_staticcall.sol +++ b/test/libsolidity/syntaxTests/functionCalls/eof/calloptions_on_staticcall.sol @@ -4,7 +4,6 @@ contract C { } } // ==== -// EVMVersion: >=prague // bytecodeFormat: >=EOFv1 // ---- // TypeError 2842: (56-96): Cannot set option "value" for staticcall. diff --git a/test/libyul/objectCompiler/eof/creation_with_immutables.yul b/test/libyul/objectCompiler/eof/creation_with_immutables.yul index 3d5ef85bc..c11cceae8 100644 --- a/test/libyul/objectCompiler/eof/creation_with_immutables.yul +++ b/test/libyul/objectCompiler/eof/creation_with_immutables.yul @@ -27,7 +27,6 @@ object "a" { } // ==== -// EVMVersion: >=prague // bytecodeFormat: >=EOFv1 // ---- // Assembly: diff --git a/test/libyul/objectCompiler/eof/dataloadn.yul b/test/libyul/objectCompiler/eof/dataloadn.yul index 06ebdaa3c..7fda77b9a 100644 --- a/test/libyul/objectCompiler/eof/dataloadn.yul +++ b/test/libyul/objectCompiler/eof/dataloadn.yul @@ -9,7 +9,6 @@ object "a" { } // ==== -// EVMVersion: >=prague // bytecodeFormat: >=EOFv1 // ---- // Assembly: diff --git a/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul b/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul index 0c9f9a382..35f503c70 100644 --- a/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul +++ b/test/libyul/objectCompiler/eof/prune_unreferenced_container.yul @@ -20,7 +20,6 @@ object "a" { } // ==== -// EVMVersion: >=prague // bytecodeFormat: >=EOFv1 // ---- // Assembly: diff --git a/test/libyul/objectCompiler/eof/rjumps.yul b/test/libyul/objectCompiler/eof/rjumps.yul index d5f2f6c21..49665784e 100644 --- a/test/libyul/objectCompiler/eof/rjumps.yul +++ b/test/libyul/objectCompiler/eof/rjumps.yul @@ -9,7 +9,6 @@ object "a" { } // ==== -// EVMVersion: >=prague // bytecodeFormat: >=EOFv1 // ---- // Assembly: diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_literal_type.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_literal_type.yul index 08de0df18..3622a3964 100644 --- a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_literal_type.yul +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_eof_invalid_literal_type.yul @@ -8,7 +8,6 @@ object "a" { } // ==== -// EVMVersion: >=prague // bytecodeFormat: >=EOFv1 // ---- // TypeError 5859: (55-58): Function expects number literal. \ No newline at end of file diff --git a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul index 47986059e..f6af43217 100644 --- a/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul +++ b/test/libyul/yulSyntaxTests/eof/auxdataloadn_in_legacy.yul @@ -8,7 +8,6 @@ object "a" { } // ==== -// EVMVersion: >=prague // bytecodeFormat: legacy // ---- // DeclarationError 7223: (42-54): Builtin function "auxdataloadn" is only available in EOF. From ac4fb25f5eddaaf83de1633543f47b4d8d86eccf Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 11 Feb 2025 13:50:15 +0100 Subject: [PATCH 0702/1340] Yul optimizer utilities use string_view to determine if an identifier is restricted --- libyul/optimiser/NameDispenser.cpp | 2 +- libyul/optimiser/OptimizerUtilities.cpp | 4 ++-- libyul/optimiser/OptimizerUtilities.h | 4 ++-- libyul/optimiser/VarNameCleaner.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp index c2b6b9847..3493c3668 100644 --- a/libyul/optimiser/NameDispenser.cpp +++ b/libyul/optimiser/NameDispenser.cpp @@ -58,7 +58,7 @@ YulName NameDispenser::newName(YulName _nameHint) bool NameDispenser::illegalName(YulName _name) { - return isRestrictedIdentifier(m_dialect, _name) || m_usedNames.count(_name); + return isRestrictedIdentifier(m_dialect, _name.str()) || m_usedNames.contains(_name); } void NameDispenser::reset(Block const& _ast) diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index 8fc225bee..3001d43f8 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -56,9 +56,9 @@ void yul::removeEmptyBlocks(Block& _block) ranges::actions::remove_if(_block.statements, isEmptyBlock); } -bool yul::isRestrictedIdentifier(Dialect const& _dialect, YulName const& _identifier) +bool yul::isRestrictedIdentifier(Dialect const& _dialect, std::string_view const _identifier) { - return _identifier.empty() || hasLeadingOrTrailingDot(_identifier.str()) || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier.str()); + return _identifier.empty() || hasLeadingOrTrailingDot(_identifier) || TokenTraits::isYulKeyword(_identifier) || _dialect.reservedIdentifier(_identifier); } std::optional yul::toEVMInstruction(Dialect const& _dialect, FunctionName const& _name) diff --git a/libyul/optimiser/OptimizerUtilities.h b/libyul/optimiser/OptimizerUtilities.h index 430834d83..d302b4aeb 100644 --- a/libyul/optimiser/OptimizerUtilities.h +++ b/libyul/optimiser/OptimizerUtilities.h @@ -24,11 +24,11 @@ #include #include #include -#include #include #include #include +#include namespace solidity::evmasm { @@ -45,7 +45,7 @@ void removeEmptyBlocks(Block& _block); /// Returns true if a given literal can not be used as an identifier. /// This includes Yul keywords and builtins of the given dialect. -bool isRestrictedIdentifier(Dialect const& _dialect, YulName const& _identifier); +bool isRestrictedIdentifier(Dialect const& _dialect, std::string_view _identifier); /// Helper function that returns the instruction, if the `_name` is a BuiltinFunction std::optional toEVMInstruction(Dialect const& _dialect, FunctionName const& _name); diff --git a/libyul/optimiser/VarNameCleaner.cpp b/libyul/optimiser/VarNameCleaner.cpp index b3a34d283..8d34ce85e 100644 --- a/libyul/optimiser/VarNameCleaner.cpp +++ b/libyul/optimiser/VarNameCleaner.cpp @@ -111,7 +111,7 @@ YulName VarNameCleaner::findCleanName(YulName const& _name) const bool VarNameCleaner::isUsedName(YulName const& _name) const { - return isRestrictedIdentifier(m_dialect, _name) || m_usedNames.count(_name); + return isRestrictedIdentifier(m_dialect, _name.str()) || m_usedNames.contains(_name); } YulName VarNameCleaner::stripSuffix(YulName const& _name) const From b0485e44b629035d68fe9bab14e502a95c89b4ec Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 12 Feb 2025 13:13:51 +0100 Subject: [PATCH 0703/1340] SMTChecker: Fix reporting same target both as safe and unsafe The same verification target can be analyzed in the context of different contracts. If the target is safe in the context of one contract, but can be violated in the context of another contract, model checker may report it both safe and unsafe (depending on the order of the analyzed contract). Note that if one violation of a target has been detected, the same target if ignored later. However, if it was first shown safe, that information would be kept and displayed to the user. The proposed fix checks if an unsafe target has previously been shown safe, and if so, this information is deleted. --- Changelog.md | 1 + libsolidity/formal/CHC.cpp | 8 +++++++- .../free_function_multiple_contracts.sol | 20 +++++++++++++++++++ ...call_with_assertion_inheritance_1_fail.sol | 8 ++++---- .../functions/library_constant.sol | 6 +++--- .../imports/import_library_2.sol | 3 +-- .../base_contract_assertion_fail_1.sol | 1 - .../base_contract_assertion_fail_2.sol | 1 - .../base_contract_assertion_fail_3.sol | 2 +- .../base_contract_assertion_fail_4.sol | 2 +- .../base_contract_assertion_fail_5.sol | 2 +- .../base_contract_assertion_fail_7.sol | 2 +- .../base_contract_assertion_fail_9.sol | 1 - ...tor_state_variable_init_diamond_middle.sol | 6 +++--- .../modifiers/modifier_overriding_4.sol | 8 ++++---- .../modifiers/modifier_two_invocations_2.sol | 4 ++-- .../assignment_chain_tuple_contract_3.sol | 2 +- .../special/msg_value_inheritance_2.sol | 5 ++--- .../special/msg_value_inheritance_3.sol | 4 ++-- 19 files changed, 54 insertions(+), 32 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/functions/free_function_multiple_contracts.sol diff --git a/Changelog.md b/Changelog.md index 0bf7cb988..5886dca26 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Compiler Features: Bugfixes: * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. + * SMTChecker: Fix reporting on targets that are safe in the context of one contract but unsafe in the context of another contract. * SMTChecker: Fix SMT logic error when analyzing cross-contract getter call with BMC. * SMTChecker: Fix SMT logic error when contract deployment involves string literal to fixed bytes conversion. * SMTChecker: Fix SMT logic error when external call has extra effectless parentheses. diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index bd3b0d988..3a5da1e58 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -2169,7 +2169,13 @@ void CHC::checkAndReportTarget( } else if (result == CheckResult::SATISFIABLE) { - solAssert(!_satMsg.empty(), ""); + solAssert(!_satMsg.empty()); + if (auto it = m_safeTargets.find(_target.errorNode); it != m_safeTargets.end()) + { + std::erase_if(it->second, [&](auto const& target) { return target.type == _target.type; }); + if (it->second.empty()) + m_safeTargets.erase(it); + } auto cex = generateCounterexample(model, error().name); if (cex) m_unsafeTargets[_target.errorNode][_target.type] = { diff --git a/test/libsolidity/smtCheckerTests/functions/free_function_multiple_contracts.sol b/test/libsolidity/smtCheckerTests/functions/free_function_multiple_contracts.sol new file mode 100644 index 000000000..49ca28f5c --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/free_function_multiple_contracts.sol @@ -0,0 +1,20 @@ +function check(uint x) pure { + assert(x > 0); +} + +contract C { + function a() public pure { + check(1); + } +} + +contract D { + function b(uint x) public pure { + check(x); + } +} +// ==== +// SMTEngine: chc +// SMTIgnoreCex: no +// ---- +// Warning 6328: (31-44): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\n\nTransaction trace:\nD.constructor()\nD.b(0)\n check(0) -- internal call diff --git a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol index 9f2fca60c..10a07e136 100644 --- a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol +++ b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol @@ -17,7 +17,7 @@ contract C is A { // ==== // SMTEngine: all // ---- -// Warning 6328: (49-63): CHC: Assertion violation happens here. -// Warning 6328: (115-129): CHC: Assertion violation happens here. -// Warning 6328: (147-161): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (49-63): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\nTransaction trace:\nC.constructor() +// Warning 6328: (115-129): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\nTransaction trace:\nC.constructor() +// Warning 6328: (147-161): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\nTransaction trace:\nC.constructor() +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/functions/library_constant.sol b/test/libsolidity/smtCheckerTests/functions/library_constant.sol index 53349f0b6..22fccbe70 100644 --- a/test/libsolidity/smtCheckerTests/functions/library_constant.sol +++ b/test/libsolidity/smtCheckerTests/functions/library_constant.sol @@ -19,6 +19,6 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (103-122): CHC: Assertion violation happens here. -// Warning 4984: (196-201): CHC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (103-122): CHC: Assertion violation happens here.\nCounterexample:\nTON = 1000\n\nTransaction trace:\nl1.constructor()\nState: TON = 1000\nl1.f1() +// Warning 4984: (196-201): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.\nCounterexample:\n\nx = 115792089237316195423570985008687907853269984665640564039457584007913129639935\n\nTransaction trace:\nC.constructor()\nC.f(115792089237316195423570985008687907853269984665640564039457584007913129639935)\n l1.f2(115792089237316195423570985008687907853269984665640564039457584007913129639935, 1) -- internal call +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/imports/import_library_2.sol b/test/libsolidity/smtCheckerTests/imports/import_library_2.sol index a1c3160ea..1046e6a49 100644 --- a/test/libsolidity/smtCheckerTests/imports/import_library_2.sol +++ b/test/libsolidity/smtCheckerTests/imports/import_library_2.sol @@ -25,5 +25,4 @@ contract ERC20 { // ==== // SMTEngine: all // ---- -// Warning 3944: (ERC20.sol:157-162): CHC: Underflow (resulting value less than 0) happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 3944: (ERC20.sol:157-162): CHC: Underflow (resulting value less than 0) happens here.\nCounterexample:\n\namount = 1\n\nTransaction trace:\nERC20.constructor()\nERC20.transferFrom(1){ msg.sender: 0x2e15 }\n SafeMath.sub(0, 1) -- internal call diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_1.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_1.sol index 6ecfed791..d8838195f 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_1.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_1.sol @@ -17,4 +17,3 @@ contract C is B { // SMTIgnoreCex: no // ---- // Warning 6328: (52-66): CHC: Assertion violation happens here.\nCounterexample:\ny = 0, x = 1\n\nTransaction trace:\nC.constructor()\nState: y = 0, x = 0\nC.g()\n B.f() -- internal call -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_2.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_2.sol index 85e2677f7..026ad07ab 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_2.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_2.sol @@ -24,4 +24,3 @@ contract C is B { // SMTIgnoreCex: no // ---- // Warning 6328: (54-68): CHC: Assertion violation happens here.\nCounterexample:\ny = 0, z = 0, w = 0, a = 0, b = 0, x = 1\n\nTransaction trace:\nC.constructor()\nState: y = 0, z = 0, w = 0, a = 0, b = 0, x = 0\nC.g()\n A.f() -- internal call -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_3.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_3.sol index f1481197f..cc5115052 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_3.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_3.sol @@ -30,4 +30,4 @@ contract C is B { // SMTIgnoreCex: no // ---- // Warning 6328: (64-78): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.g()\n B.f() -- internal call\n A.f() -- internal call\n C.v() -- internal call -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_4.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_4.sol index 04b7ea748..adfcb5e23 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_4.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_4.sol @@ -37,4 +37,4 @@ contract C is B, A1 { // SMTIgnoreCex: no // ---- // Warning 6328: (64-78): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.g()\n C.f() -- internal call\n A1.f() -- internal call\n B.f() -- internal call\n A.f() -- internal call\n C.v() -- internal call -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_5.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_5.sol index e386c4b44..89bc75398 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_5.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_5.sol @@ -31,4 +31,4 @@ contract C is B { // SMTIgnoreCex: no // ---- // Warning 6328: (97-111): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.g()\n B.f() -- internal call\n A.f() -- internal call\n C.v() -- internal call\n A.v() -- internal call -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_7.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_7.sol index 45cf7fe18..9c2981bf1 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_7.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_7.sol @@ -24,4 +24,4 @@ contract C is A { // SMTIgnoreCex: no // ---- // Warning 6328: (56-70): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.g()\n A.f() -- internal call\n C.v() -- internal call -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_9.sol b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_9.sol index 9972c7e3f..36b22040a 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_9.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/base_contract_assertion_fail_9.sol @@ -31,4 +31,3 @@ contract C is B { // ---- // Warning 6328: (62-76): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 0\nB.f()\n A.f() -- internal call\n C.v() -- internal call // Warning 6328: (131-145): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\nTransaction trace:\nA.constructor()\nState: x = 0\nA.f()\n A.v() -- internal call -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_diamond_middle.sol b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_diamond_middle.sol index 8590b0bcf..e80e398fe 100644 --- a/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_diamond_middle.sol +++ b/test/libsolidity/smtCheckerTests/inheritance/constructor_state_variable_init_diamond_middle.sol @@ -25,6 +25,6 @@ contract D is B, C { // ==== // SMTEngine: all // ---- -// Warning 6328: (134-148): CHC: Assertion violation happens here. -// Warning 6328: (223-237): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (134-148): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nD.constructor() +// Warning 6328: (223-237): CHC: Assertion violation happens here.\nCounterexample:\nx = 3\n\nTransaction trace:\nD.constructor() +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol index 652dd811f..d0e82665c 100644 --- a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol +++ b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol @@ -36,7 +36,7 @@ contract D is B,C { // ==== // SMTEngine: all // ---- -// Warning 6328: (160-174): CHC: Assertion violation happens here. -// Warning 6328: (193-207): CHC: Assertion violation happens here. -// Warning 6328: (226-240): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (160-174): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\nTransaction trace:\nB.constructor()\nState: x = 0\nA.f() +// Warning 6328: (193-207): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 0\nA.f() +// Warning 6328: (226-240): CHC: Assertion violation happens here.\nCounterexample:\nx = 3\n\nTransaction trace:\nD.constructor()\nState: x = 0\nA.f() +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/modifiers/modifier_two_invocations_2.sol b/test/libsolidity/smtCheckerTests/modifiers/modifier_two_invocations_2.sol index d6bc51ffd..a41c91857 100644 --- a/test/libsolidity/smtCheckerTests/modifiers/modifier_two_invocations_2.sol +++ b/test/libsolidity/smtCheckerTests/modifiers/modifier_two_invocations_2.sol @@ -16,5 +16,5 @@ contract C // ==== // SMTEngine: all // ---- -// Warning 6328: (76-90): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (76-90): CHC: Assertion violation happens here.\nCounterexample:\nx = 3\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.f() +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/assignment_chain_tuple_contract_3.sol b/test/libsolidity/smtCheckerTests/operators/assignment_chain_tuple_contract_3.sol index e53436a0f..1f0fd5829 100644 --- a/test/libsolidity/smtCheckerTests/operators/assignment_chain_tuple_contract_3.sol +++ b/test/libsolidity/smtCheckerTests/operators/assignment_chain_tuple_contract_3.sol @@ -23,4 +23,4 @@ contract D is C { // ---- // Warning 6328: (95-109): CHC: Assertion violation happens here.\nCounterexample:\ny = 3, x = 3\n\nTransaction trace:\nD.constructor()\nState: y = 3, x = 3\nC.f() // Warning 6328: (180-194): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 2\nC.g() -// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_2.sol b/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_2.sol index 942607bd8..f6c182c1e 100644 --- a/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_2.sol +++ b/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_2.sol @@ -14,6 +14,5 @@ contract C is A { // ==== // SMTEngine: all // ---- -// Warning 6328: (60-74): CHC: Assertion violation happens here. -// Warning 6328: (240-254): CHC: Assertion violation happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (60-74): CHC: Assertion violation happens here.\nCounterexample:\nv = 0, x = 115792089237316195423570985008687907853269984665640564039457584007913129637498\n\nTransaction trace:\nC.constructor(){ msg.value: 115792089237316195423570985008687907853269984665640564039457584007913129637498 } +// Warning 6328: (240-254): CHC: Assertion violation happens here.\nCounterexample:\nv = 115792089237316195423570985008687907853269984665640564039457584007913129637498, x = 115792089237316195423570985008687907853269984665640564039457584007913129637498\n\nTransaction trace:\nC.constructor(){ msg.value: 115792089237316195423570985008687907853269984665640564039457584007913129637498 } diff --git a/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_3.sol b/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_3.sol index fc8d6e08f..4a659978f 100644 --- a/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_3.sol +++ b/test/libsolidity/smtCheckerTests/special/msg_value_inheritance_3.sol @@ -18,5 +18,5 @@ contract C is A, B { // ==== // SMTEngine: all // ---- -// Warning 6328: (60-74): CHC: Assertion violation happens here. -// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Warning 6328: (60-74): CHC: Assertion violation happens here.\nCounterexample:\nx = 115792089237316195423570985008687907853269984665640564039457584007913129637498\n\nTransaction trace:\nC.constructor(){ msg.value: 115792089237316195423570985008687907853269984665640564039457584007913129637498 } +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 780fee18a8bbd8002a138fa7b8a3611bbb10ded5 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Wed, 12 Feb 2025 22:10:22 +0100 Subject: [PATCH 0704/1340] Testing: Fix unused variable warning in SMTCheckerTests --- test/libsolidity/SMTCheckerTest.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/libsolidity/SMTCheckerTest.cpp b/test/libsolidity/SMTCheckerTest.cpp index 96a9538f1..d8843e0d3 100644 --- a/test/libsolidity/SMTCheckerTest.cpp +++ b/test/libsolidity/SMTCheckerTest.cpp @@ -131,6 +131,10 @@ SMTCheckerTest::SMTCheckerTest(std::string const& _filename): #elif __linux__ if (os == "linux") m_shouldRun = false; +#else + // On other operating systems this setting is ignored (as we don't test other operating systems in CI), + // but we need to prevent an unused-variable warning. + (void)os; #endif } From 3b965999240510d84d57e7eb12fdad2393ac4d4e Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 31 Jan 2025 21:21:05 +0100 Subject: [PATCH 0705/1340] SMTChecker: Allow printing queries for all solvers Since SMTChecker now uses SMT-LIB to represent the queries and pass them to the solvers, we do not have to restrict this option to the "smtlib2" solver. It can be used with any solver. The query will be logged and then passed to the solver as usual. --- Changelog.md | 1 + libsolidity/formal/BMC.cpp | 5 +- libsolidity/formal/CHC.cpp | 5 +- libsolidity/interface/StandardCompiler.cpp | 3 - solc/CommandLineParser.cpp | 4 - .../model_checker_print_query_all/err | 4 - .../model_checker_print_query_bmc/err | 2 - .../model_checker_print_query_chc/err | 2 - .../args | 1 - .../err | 1 - .../exit | 1 - .../input.sol | 9 -- .../args | 1 - .../err | 1 - .../exit | 1 - .../input.sol | 9 -- .../args | 1 - .../err | 1 - .../exit | 1 - .../input.sol | 9 -- .../output.json | 137 ------------------ .../output.json | 40 ----- .../output.json | 98 ------------- .../input.json | 25 ---- .../output.json | 11 -- .../input.json | 26 ---- .../output.json | 11 -- 27 files changed, 6 insertions(+), 404 deletions(-) delete mode 100644 test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/args delete mode 100644 test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/err delete mode 100644 test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/exit delete mode 100644 test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/input.sol delete mode 100644 test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/args delete mode 100644 test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/err delete mode 100644 test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/exit delete mode 100644 test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/input.sol delete mode 100644 test/cmdlineTests/model_checker_print_query_superflous_solver/args delete mode 100644 test/cmdlineTests/model_checker_print_query_superflous_solver/err delete mode 100644 test/cmdlineTests/model_checker_print_query_superflous_solver/exit delete mode 100644 test/cmdlineTests/model_checker_print_query_superflous_solver/input.sol delete mode 100644 test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/input.json delete mode 100644 test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/output.json delete mode 100644 test/cmdlineTests/standard_model_checker_print_query_superflous_solver/input.json delete mode 100644 test/cmdlineTests/standard_model_checker_print_query_superflous_solver/output.json diff --git a/Changelog.md b/Changelog.md index 5886dca26..c37993488 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: * Error Reporting: Errors reported during code generation now point at the location of the contract when more fine-grained location is not available. * EVM: Support for the EVM version "Osaka". * SMTChecker: Support `block.blobbasefee` and `blobhash`. + * SMTChecker: The option `--model-checker-print-query` no longer requires `--model-checker-solvers smtlib2`. * SMTChecker: Z3 is now a runtime dependency, not a build dependency (except for emscripten build). * Yul Parser: Make name clash with a builtin a non-fatal error. diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 5fb2f5a9f..c29c21e5c 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -49,7 +49,6 @@ BMC::BMC( ): SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _provedSafeReporter, _charStreamProvider) { - solAssert(!_settings.printQuery || _settings.solvers == SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); std::vector> solvers; if (_settings.solvers.smtlib2) solvers.emplace_back(std::make_unique(_smtlib2Responses, _smtCallback, _settings.timeout)); @@ -1262,8 +1261,10 @@ BMC::checkSatisfiableAndGenerateModel(std::vector const& _e 6240_error, "BMC: Requested query:\n" + smtlibCode ); + result = CheckResult::UNKNOWN; } - tie(result, values) = m_interface->check(_expressionsToEvaluate); + else + tie(result, values) = m_interface->check(_expressionsToEvaluate); } catch (smtutil::SolverError const& _e) { diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 3a5da1e58..c313ae54e 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -64,9 +64,7 @@ CHC::CHC( SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _provedSafeReporter, _charStreamProvider), m_smtlib2Responses(_smtlib2Responses), m_smtCallback(_smtCallback) -{ - solAssert(!_settings.printQuery || _settings.solvers == smtutil::SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); -} +{} void CHC::analyze(SourceUnit const& _source) { @@ -1897,6 +1895,7 @@ CHCSolverInterface::QueryResult CHC::query(smtutil::Expression const& _query, la 2339_error, "CHC: Requested query:\n" + smtLibCode ); + return {.answer = CheckResult::UNKNOWN, .invariant = smtutil::Expression(true), .cex = {}}; } auto result = m_interface->query(_query); switch (result.answer) diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 520f4d5f1..cf110079b 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1141,9 +1141,6 @@ std::variant StandardCompiler::parseI if (!printQuery.is_boolean()) return formatFatalError(Error::Type::JSONError, "settings.modelChecker.printQuery must be a Boolean value."); - if (!(ret.modelCheckerSettings.solvers == smtutil::SMTSolverChoice::SMTLIB2())) - return formatFatalError(Error::Type::JSONError, "Only SMTLib2 solver can be enabled to print queries"); - ret.modelCheckerSettings.printQuery = printQuery.get(); } diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index b02b1ed8c..e5b096c2a 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -1435,11 +1435,7 @@ void CommandLineParser::processArgs() } if (m_args.count(g_strModelCheckerPrintQuery)) - { - if (!(m_options.modelChecker.settings.solvers == smtutil::SMTSolverChoice::SMTLIB2())) - solThrow(CommandLineValidationError, "Only SMTLib2 solver can be enabled to print queries"); m_options.modelChecker.settings.printQuery = true; - } if (m_args.count(g_strModelCheckerTargets)) { diff --git a/test/cmdlineTests/model_checker_print_query_all/err b/test/cmdlineTests/model_checker_print_query_all/err index 92a3b7f7b..e696c6ed3 100644 --- a/test/cmdlineTests/model_checker_print_query_all/err +++ b/test/cmdlineTests/model_checker_print_query_all/err @@ -86,8 +86,6 @@ Info: CHC: Requested query: Warning: CHC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. -Warning: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled. - Info: BMC: Requested query: (set-option :produce-models true) (set-option :timeout 1000) @@ -120,5 +118,3 @@ Info: BMC: Requested query: Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. - -Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. diff --git a/test/cmdlineTests/model_checker_print_query_bmc/err b/test/cmdlineTests/model_checker_print_query_bmc/err index efbc2a3ae..4713ac13e 100644 --- a/test/cmdlineTests/model_checker_print_query_bmc/err +++ b/test/cmdlineTests/model_checker_print_query_bmc/err @@ -27,5 +27,3 @@ Info: BMC: Requested query: Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. - -Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. diff --git a/test/cmdlineTests/model_checker_print_query_chc/err b/test/cmdlineTests/model_checker_print_query_chc/err index 9c18265be..a55ad5cea 100644 --- a/test/cmdlineTests/model_checker_print_query_chc/err +++ b/test/cmdlineTests/model_checker_print_query_chc/err @@ -85,5 +85,3 @@ Info: CHC: Requested query: Warning: CHC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query. - -Warning: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled. diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/args b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/args deleted file mode 100644 index 12b7c3245..000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/args +++ /dev/null @@ -1 +0,0 @@ ---model-checker-engine bmc --model-checker-print-query --model-checker-solvers z3 diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/err b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/err deleted file mode 100644 index 1e2296446..000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/err +++ /dev/null @@ -1 +0,0 @@ -Error: Only SMTLib2 solver can be enabled to print queries diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/exit b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/input.sol b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/input.sol deleted file mode 100644 index eb4cd572a..000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_bmc/input.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.0; -contract C -{ - function f() public pure { - uint x = 0; - assert(x == 0); - } -} diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/args b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/args deleted file mode 100644 index e3a8c32d4..000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/args +++ /dev/null @@ -1 +0,0 @@ ---model-checker-engine chc --model-checker-print-query --model-checker-solvers z3 diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/err b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/err deleted file mode 100644 index 1e2296446..000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/err +++ /dev/null @@ -1 +0,0 @@ -Error: Only SMTLib2 solver can be enabled to print queries diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/exit b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/input.sol b/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/input.sol deleted file mode 100644 index eb4cd572a..000000000 --- a/test/cmdlineTests/model_checker_print_query_no_smtlib2_solver_chc/input.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.0; -contract C -{ - function f() public pure { - uint x = 0; - assert(x == 0); - } -} diff --git a/test/cmdlineTests/model_checker_print_query_superflous_solver/args b/test/cmdlineTests/model_checker_print_query_superflous_solver/args deleted file mode 100644 index 64e5d8872..000000000 --- a/test/cmdlineTests/model_checker_print_query_superflous_solver/args +++ /dev/null @@ -1 +0,0 @@ ---model-checker-engine bmc --model-checker-print-query --model-checker-solvers z3,smtlib2 diff --git a/test/cmdlineTests/model_checker_print_query_superflous_solver/err b/test/cmdlineTests/model_checker_print_query_superflous_solver/err deleted file mode 100644 index 1e2296446..000000000 --- a/test/cmdlineTests/model_checker_print_query_superflous_solver/err +++ /dev/null @@ -1 +0,0 @@ -Error: Only SMTLib2 solver can be enabled to print queries diff --git a/test/cmdlineTests/model_checker_print_query_superflous_solver/exit b/test/cmdlineTests/model_checker_print_query_superflous_solver/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/model_checker_print_query_superflous_solver/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/model_checker_print_query_superflous_solver/input.sol b/test/cmdlineTests/model_checker_print_query_superflous_solver/input.sol deleted file mode 100644 index eb4cd572a..000000000 --- a/test/cmdlineTests/model_checker_print_query_superflous_solver/input.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.0; -contract C -{ - function f() public pure { - uint x = 0; - assert(x == 0); - } -} diff --git a/test/cmdlineTests/standard_model_checker_print_query_all/output.json b/test/cmdlineTests/standard_model_checker_print_query_all/output.json index 1108d7907..85c4e142c 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_all/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_all/output.json @@ -1,121 +1,4 @@ { - "auxiliaryInputRequested": { - "smtlib2queries": { - "0x89dce9b2e59f1b2d3445ec646e15e2609ff358edb66afa7227538979017e0f7b": "(set-option :timeout 1000) -(set-logic HORN) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) -) -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) -) -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) -) -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) -) -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) -) -(declare-fun |error_target_3| () Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) -)(assert -(forall ((UNUSED Bool)) -(=> error_target_3 false))) -(check-sat) -", - "0xca8e4027f5350278d291f782ff3ec7a7f618e8a729beb4173e7dad3f008af497": "(set-option :produce-models true) -(set-option :timeout 1000) -(set-logic ALL) -(declare-fun |x_5_3| () Int) -(declare-fun |error_0| () Int) -(declare-fun |this_0| () Int) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-fun |tx_0| () |tx_type|) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-fun |crypto_0| () |crypto_type|) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-fun |abi_0| () |abi_type|) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |state_0| () |state_type|) -(declare-fun |x_5_4| () Int) -(declare-fun |x_5_0| () Int) -(declare-fun |expr_6_0| () Int) -(declare-fun |x_5_1| () Int) -(declare-fun |expr_9_0| () Int) -(declare-fun |expr_10_0| () Int) -(declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) -(declare-const |EVALEXPR_0| Int) -(assert (= |EVALEXPR_0| x_5_1)) -(check-sat) -(get-value (|EVALEXPR_0| )) -" - } - }, "errors": [ { "component": "general", @@ -305,16 +188,6 @@ "severity": "warning", "type": "Warning" }, - { - "component": "general", - "errorCode": "3996", - "formattedMessage": "Warning: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled. - -", - "message": "CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled.", - "severity": "warning", - "type": "Warning" - }, { "component": "general", "errorCode": "6240", @@ -392,16 +265,6 @@ "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", "severity": "warning", "type": "Warning" - }, - { - "component": "general", - "errorCode": "8084", - "formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. - -", - "message": "BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.", - "severity": "warning", - "type": "Warning" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json index a0be6110b..21fdedc40 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_bmc/output.json @@ -1,34 +1,4 @@ { - "auxiliaryInputRequested": { - "smtlib2queries": { - "0x41ee12cade46d5e1c28896216d2b220d2d28b47c925b0191941303216c8635dd": "(set-option :produce-models true) -(set-logic ALL) -(declare-fun |error_0| () Int) -(declare-fun |this_0| () Int) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-fun |tx_0| () |tx_type|) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-fun |crypto_0| () |crypto_type|) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-fun |abi_0| () |abi_type|) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |state_0| () |state_type|) -(declare-fun |x_5_0| () Int) -(declare-fun |expr_6_0| () Int) -(declare-fun |x_5_1| () Int) -(declare-fun |expr_9_0| () Int) -(declare-fun |expr_10_0| () Int) -(declare-fun |expr_11_1| () Bool) -(assert (and (and (and true true) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> (and true true) true) (and (= expr_10_0 0) (and (=> (and true true) (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_1) (and (ite (and true true) (= x_5_1 expr_6_0) (= x_5_1 x_5_0)) (and (=> (and true true) true) (and (= expr_6_0 0) (and (= x_5_0 0) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) true))))))))))) (not expr_11_1))) -(declare-const |EVALEXPR_0| Int) -(assert (= |EVALEXPR_0| x_5_1)) -(check-sat) -(get-value (|EVALEXPR_0| )) -" - } - }, "errors": [ { "component": "general", @@ -101,16 +71,6 @@ "message": "BMC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", "severity": "warning", "type": "Warning" - }, - { - "component": "general", - "errorCode": "8084", - "formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled. - -", - "message": "BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.", - "severity": "warning", - "type": "Warning" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json index be0d9fa9e..57c81ec50 100644 --- a/test/cmdlineTests/standard_model_checker_print_query_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_print_query_chc/output.json @@ -1,92 +1,4 @@ { - "auxiliaryInputRequested": { - "smtlib2queries": { - "0x89dce9b2e59f1b2d3445ec646e15e2609ff358edb66afa7227538979017e0f7b": "(set-option :timeout 1000) -(set-logic HORN) -(declare-datatypes ((|abi_type| 0)) (((|abi_type|)))) -(declare-datatypes ((|ecrecover_input_type| 0)) (((|ecrecover_input_type| (|hash| Int) (|v| Int) (|r| Int) (|s| Int))))) -(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int))))) -(declare-datatypes ((|crypto_type| 0)) (((|crypto_type| (|ecrecover| (Array |ecrecover_input_type| Int)) (|keccak256| (Array |bytes_tuple| Int)) (|ripemd160| (Array |bytes_tuple| Int)) (|sha256| (Array |bytes_tuple| Int)))))) -(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int)))))) -(declare-fun |interface_0_C_16| (Int |abi_type| |crypto_type| |state_type|) Bool) -(declare-fun |nondet_interface_1_C_16| (Int Int |abi_type| |crypto_type| |state_type| |state_type|) Bool) -(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|blobhash| (Array Int Int)) (|block.basefee| Int) (|block.blobbasefee| Int) (|block.chainid| Int) (|block.coinbase| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.prevrandao| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int))))) -(declare-fun |summary_constructor_2_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (this_0 Int)) -(=> (= error_0 0) (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_0))) -) -(declare-fun |summary_3_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(declare-fun |summary_4_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (nondet_interface_1_C_16 error_0 this_0 abi_0 crypto_0 state_0 state_1) true) (and (= error_0 0) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2))) (nondet_interface_1_C_16 error_1 this_0 abi_0 crypto_0 state_0 state_2))) -) -(declare-fun |block_5_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(declare-fun |block_6_f_14_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_5_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true)) true) (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1))) -) -(declare-fun |block_7_return_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(declare-fun |block_8_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true)))))))))) (and (and true (not expr_11_1)) (= error_1 1))) (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_2 Int)) -(=> (block_8_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2) (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (expr_10_0 Int) (expr_11_1 Bool) (expr_6_0 Int) (expr_9_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int) (x_5_2 Int)) -(=> (and (and (block_6_f_14_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (= error_1 error_0) (and (= expr_11_1 (= expr_9_0 expr_10_0)) (and (=> true true) (and (= expr_10_0 0) (and (=> true (and (>= expr_9_0 0) (<= expr_9_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_9_0 x_5_2) (and (= x_5_2 expr_6_0) (and (=> true true) (and (= expr_6_0 0) (and (= x_5_1 0) true))))))))))) true) (block_7_return_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_7_return_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) true) true) (summary_3_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |block_9_function_f__15_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type| Int) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1)) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (funds_2_0 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (state_3 |state_type|) (this_0 Int) (tx_0 |tx_type|) (x_5_1 Int)) -(=> (and (and (block_9_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1 x_5_1) (and (summary_3_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_2 state_3) (and (= state_2 (|state_type| (store (|balances| state_1) this_0 (+ (select (|balances| state_1) this_0) funds_2_0)))) (and (and (>= (+ (select (|balances| state_1) this_0) funds_2_0) 0) (<= (+ (select (|balances| state_1) this_0) funds_2_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (>= funds_2_0 (|msg.value| tx_0)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (and (and (and (and (and (= (|msg.value| tx_0) 0) (= (|msg.sig| tx_0) 638722032)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 38)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 18)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 31)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 240)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4))) (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true))))))) true) (summary_4_function_f__15_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_3))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) -) -(declare-fun |contract_initializer_10_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(declare-fun |contract_initializer_entry_11_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (= state_1 state_0) (= error_0 0)) true) (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |contract_initializer_after_init_12_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (contract_initializer_entry_11_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (contract_initializer_after_init_12_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) true) (contract_initializer_10_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(declare-fun |implicit_constructor_entry_13_C_16| (Int Int |abi_type| |crypto_type| |tx_type| |state_type| |state_type|) Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (and (and (and (= state_1 state_0) (= error_0 0)) true) true) true) (>= (select (|balances| state_1) this_0) (|msg.value| tx_0))) (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true)) (> error_1 0)) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (error_1 Int) (state_0 |state_type|) (state_1 |state_type|) (state_2 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (implicit_constructor_entry_13_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (and (= error_1 0) (and (contract_initializer_10_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_1 state_2) true))) true) (summary_constructor_2_C_16 error_1 this_0 abi_0 crypto_0 tx_0 state_0 state_2))) -) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (summary_constructor_2_C_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) true) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (> (|block.prevrandao| tx_0) 18446744073709551616) (and (>= (|block.basefee| tx_0) 0) (<= (|block.basefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.blobbasefee| tx_0) 0) (<= (|block.blobbasefee| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|block.prevrandao| tx_0) 0) (<= (|block.prevrandao| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|msg.value| tx_0) 0) (<= (|msg.value| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.gasprice| tx_0) 0) (<= (|tx.gasprice| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (= (|msg.value| tx_0) 0)) (= error_0 0))) (interface_0_C_16 this_0 abi_0 crypto_0 state_1))) -) -(declare-fun |error_target_3| () Bool) -(assert (forall( (abi_0 |abi_type|) (crypto_0 |crypto_type|) (error_0 Int) (state_0 |state_type|) (state_1 |state_type|) (this_0 Int) (tx_0 |tx_type|)) -(=> (and (and (interface_0_C_16 this_0 abi_0 crypto_0 state_0) true) (and (summary_4_function_f__15_16 error_0 this_0 abi_0 crypto_0 tx_0 state_0 state_1) (= error_0 1))) error_target_3)) -)(assert -(forall ((UNUSED Bool)) -(=> error_target_3 false))) -(check-sat) -" - } - }, "errors": [ { "component": "general", @@ -275,16 +187,6 @@ "message": "CHC: 1 verification condition(s) could not be proved. Enable the model checker option \"show unproved\" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.", "severity": "warning", "type": "Warning" - }, - { - "component": "general", - "errorCode": "3996", - "formattedMessage": "Warning: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled. - -", - "message": "CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled.", - "severity": "warning", - "type": "Warning" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/input.json b/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/input.json deleted file mode 100644 index 0159c256e..000000000 --- a/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/input.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "language": "Solidity", - "sources": - { - "A": - { - "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n - contract C - { - function f() public pure { - uint x = 0; - assert(x == 0); - } - }" - } - }, - "settings": - { - "modelChecker": - { - "engine": "all", - "printQuery": true - } - } -} diff --git a/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/output.json b/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/output.json deleted file mode 100644 index d675499f9..000000000 --- a/test/cmdlineTests/standard_model_checker_print_query_no_smtlib2_solver/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "Only SMTLib2 solver can be enabled to print queries", - "message": "Only SMTLib2 solver can be enabled to print queries", - "severity": "error", - "type": "JSONError" - } - ] -} diff --git a/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/input.json b/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/input.json deleted file mode 100644 index 9ebda0017..000000000 --- a/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/input.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "language": "Solidity", - "sources": - { - "A": - { - "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\n - contract C - { - function f() public pure { - uint x = 0; - assert(x == 0); - } - }" - } - }, - "settings": - { - "modelChecker": - { - "engine": "all", - "printQuery": true, - "solvers": ["smtlib2", "z3"] - } - } -} diff --git a/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/output.json b/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/output.json deleted file mode 100644 index d675499f9..000000000 --- a/test/cmdlineTests/standard_model_checker_print_query_superflous_solver/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "Only SMTLib2 solver can be enabled to print queries", - "message": "Only SMTLib2 solver can be enabled to print queries", - "severity": "error", - "type": "JSONError" - } - ] -} From 7b22b9c25751a216b821f6a418ef51b8aa7f9a67 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 6 Feb 2025 11:33:38 +0100 Subject: [PATCH 0706/1340] CLI: Allows to run the asm optimizer on imported asm --- Changelog.md | 1 + docs/using-the-compiler.rst | 9 +++++++-- libevmasm/EVMAssemblyStack.cpp | 1 + libevmasm/EVMAssemblyStack.h | 13 +++++++++++-- libsolidity/interface/StandardCompiler.cpp | 19 +++++++++++++++---- libsolidity/interface/StandardCompiler.h | 2 +- solc/CommandLineInterface.cpp | 9 ++++++++- solc/CommandLineParser.cpp | 11 +++++++++-- 8 files changed, 53 insertions(+), 12 deletions(-) diff --git a/Changelog.md b/Changelog.md index 5886dca26..0145ace66 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Language Features: Compiler Features: * Error Reporting: Errors reported during code generation now point at the location of the contract when more fine-grained location is not available. * EVM: Support for the EVM version "Osaka". + * EVM Assembly Import: Allow enabling opcode-based optimizer. * SMTChecker: Support `block.blobbasefee` and `blobhash`. * SMTChecker: Z3 is now a runtime dependency, not a build dependency (except for emscripten build). * Yul Parser: Make name clash with a builtin a non-fatal error. diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index a5d5b08cc..8893f6c50 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -289,6 +289,9 @@ Input Description // enabled an can only be explicitly disabled via 'details'. // WARNING: Before version 0.8.6 omitting this setting was not equivalent to setting // it to false and would result in all components being disabled instead. + // WARNING: Enabling optimizations for EVMAssembly input is allowed but not necessary under normal + // circumstances. It forces the opcode-based optimizer to run again and can produce bytecode that + // is not reproducible from metadata. "enabled": true, // Optimize for how many times you intend to run the code. Optional. Default: 200. // Lower values will optimize more for initial deployment cost, higher @@ -300,12 +303,14 @@ Input Description // all values are provided explicitly. "details": { // Peephole optimizer (opcode-based). Optional. Default: true. - // NOTE: Always runs (even with optimization disabled) unless explicitly turned off here. + // Default for EVMAssembly input: false when optimization is not enabled. + // NOTE: Always runs (even with optimization disabled) except for EVMAssembly input or when explicitly turned off here. "peephole": true, // Inliner (opcode-based). Optional. Default: true when optimization is enabled. "inliner": false, // Unused JUMPDEST remover (opcode-based). Optional. Default: true. - // NOTE: Always runs (even with optimization disabled) unless explicitly turned off here. + // Default for EVMAssembly input: false when optimization is not enabled. + // NOTE: Always runs (even with optimization disabled) except for EVMAssembly input or when explicitly turned off here. "jumpdestRemover": true, // Literal reordering (codegen-based). Optional. Default: true when optimization is enabled. // Moves literals to the right of commutative binary operators during code generation, helping exploit associativity. diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index f8b8b4b54..7cb05bf8b 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -55,6 +55,7 @@ void EVMAssemblyStack::assemble() solAssert(m_evmAssembly->isCreation()); solAssert(!m_evmRuntimeAssembly); + m_evmAssembly->optimise(m_optimiserSettings); m_object = m_evmAssembly->assemble(); // TODO: Check for EOF solAssert(m_evmAssembly->codeSections().size() == 1); diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index e3888afad..2fe63c11c 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -26,6 +26,7 @@ #include #include +#include namespace solidity::evmasm { @@ -33,8 +34,15 @@ namespace solidity::evmasm class EVMAssemblyStack: public AbstractAssemblyStack { public: - explicit EVMAssemblyStack(langutil::EVMVersion _evmVersion, std::optional _eofVersion): - m_evmVersion(_evmVersion), m_eofVersion(_eofVersion) {} + explicit EVMAssemblyStack( + langutil::EVMVersion _evmVersion, + std::optional _eofVersion, + Assembly::OptimiserSettings _optimiserSettings + ): + m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion), + m_optimiserSettings(std::move(_optimiserSettings)) + {} /// Runs parsing and analysis steps. /// Multiple calls overwrite the previous state. @@ -82,6 +90,7 @@ class EVMAssemblyStack: public AbstractAssemblyStack private: langutil::EVMVersion m_evmVersion; std::optional m_eofVersion; + Assembly::OptimiserSettings m_optimiserSettings; std::string m_name; std::shared_ptr m_evmAssembly; std::shared_ptr m_evmRuntimeAssembly; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 520f4d5f1..fb0ea4514 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -564,12 +564,12 @@ std::optional checkOutputSelection(Json const& _outputSelection) /// Validates the optimizer settings and returns them in a parsed object. /// On error returns the json-formatted error message. -std::variant parseOptimizerSettings(Json const& _jsonInput) +std::variant parseOptimizerSettings(std::string_view const _language, Json const& _jsonInput) { if (auto result = checkOptimizerKeys(_jsonInput)) return *result; - OptimiserSettings settings = OptimiserSettings::minimal(); + OptimiserSettings settings = _language == "EVMAssembly" ? OptimiserSettings::none() : OptimiserSettings::minimal(); if (_jsonInput.contains("enabled")) { @@ -907,12 +907,16 @@ std::variant StandardCompiler::parseI if (settings.contains("optimizer")) { - auto optimiserSettings = parseOptimizerSettings(settings["optimizer"]); + auto optimiserSettings = parseOptimizerSettings(ret.language, settings["optimizer"]); if (std::holds_alternative(optimiserSettings)) return std::get(std::move(optimiserSettings)); // was an error else ret.optimiserSettings = std::get(std::move(optimiserSettings)); } + else if (ret.language == "EVMAssembly") + ret.optimiserSettings = OptimiserSettings::none(); + else + ret.optimiserSettings = OptimiserSettings::minimal(); Json const& jsonLibraries = settings.value("libraries", Json::object()); if (!jsonLibraries.is_object()) @@ -1236,7 +1240,14 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in if (!isBinaryRequested(_inputsAndSettings.outputSelection)) return Json::object(); - evmasm::EVMAssemblyStack stack(_inputsAndSettings.evmVersion, _inputsAndSettings.eofVersion); + evmasm::EVMAssemblyStack stack( + _inputsAndSettings.evmVersion, + _inputsAndSettings.eofVersion, + evmasm::Assembly::OptimiserSettings::translateSettings( + _inputsAndSettings.optimiserSettings, + _inputsAndSettings.evmVersion + ) + ); std::string const& sourceName = _inputsAndSettings.jsonSources.begin()->first; // result of structured binding can only be used within lambda from C++20 on. Json const& sourceJson = _inputsAndSettings.jsonSources.begin()->second; try diff --git a/libsolidity/interface/StandardCompiler.h b/libsolidity/interface/StandardCompiler.h index 590d96b9c..665e8b487 100644 --- a/libsolidity/interface/StandardCompiler.h +++ b/libsolidity/interface/StandardCompiler.h @@ -80,7 +80,7 @@ class StandardCompiler std::optional eofVersion; std::vector remappings; RevertStrings revertStrings = RevertStrings::Default; - OptimiserSettings optimiserSettings = OptimiserSettings::minimal(); + OptimiserSettings optimiserSettings; std::optional debugInfoSelection; std::map libraries; bool metadataLiteralSources = false; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 2e553c688..92acad4bd 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -889,7 +889,14 @@ void CommandLineInterface::assembleFromEVMAssemblyJSON() solAssert(m_fileReader.sourceUnits().size() == 1); auto&& [sourceUnitName, source] = *m_fileReader.sourceUnits().begin(); - auto evmAssemblyStack = std::make_unique(m_options.output.evmVersion, m_options.output.eofVersion); + auto evmAssemblyStack = std::make_unique( + m_options.output.evmVersion, + m_options.output.eofVersion, + evmasm::Assembly::OptimiserSettings::translateSettings( + m_options.optimiserSettings(), + m_options.output.evmVersion + ) + ); try { evmAssemblyStack->parseAndAnalyze(sourceUnitName, source); diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index b02b1ed8c..52d158ccd 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -264,7 +264,10 @@ OptimiserSettings CommandLineOptions::optimiserSettings() const if (optimizer.optimizeEvmasm) settings = OptimiserSettings::standard(); else - settings = OptimiserSettings::minimal(); + if (input.mode == InputMode::EVMAssemblerJSON) + settings = OptimiserSettings::none(); + else + settings = OptimiserSettings::minimal(); settings.runYulOptimiser = optimizer.optimizeYul; if (optimizer.optimizeYul) @@ -687,7 +690,10 @@ General Information)").c_str(), ) ( g_strImportEvmAssemblerJson.c_str(), - "Import EVM assembly from JSON. Assumes input is in the format used by --asm-json." + ("Import EVM assembly in JSON format produced by --asm-json. " + "WARNING: --asm-json output is already optimized according to settings stored in metadata. " + "Using --" + g_strOptimize + " in this mode is allowed, but not necessary under normal circumstances. " + "It forces the optimizer to run again and can produce bytecode that is not reproducible from metadata.").c_str() ) ( g_strLSP.c_str(), @@ -1082,6 +1088,7 @@ void CommandLineParser::processArgs() g_strCombinedJson, g_strInputFile, g_strJsonIndent, + g_strOptimize, g_strPrettyJson, "srcmap", "srcmap-runtime", From 34f131e342654ac538ded90c1216e30e98883042 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 12 Feb 2025 10:38:02 +0100 Subject: [PATCH 0707/1340] Adds tests that check imported asm with and without optimize behavior --- .../import_asm_json_no_optimize/args | 1 + .../import_asm_json_no_optimize/output | 19 +++++++++ .../import_asm_json_no_optimize/stdin | 23 +++++++++++ .../import_asm_json_optimize/args | 1 + .../import_asm_json_optimize/exit | 1 + .../import_asm_json_optimize/output | 2 + .../import_asm_json_optimize/stdin | 23 +++++++++++ .../args | 1 - .../err | 1 - .../exit | 1 - .../stdin | 6 --- .../input.json | 37 +++++++++++++++++ .../output.json | 29 ++++++++++++++ .../input.json | 40 +++++++++++++++++++ .../output.json | 12 ++++++ 15 files changed, 188 insertions(+), 9 deletions(-) create mode 100644 test/cmdlineTests/import_asm_json_no_optimize/args create mode 100644 test/cmdlineTests/import_asm_json_no_optimize/output create mode 100644 test/cmdlineTests/import_asm_json_no_optimize/stdin create mode 100644 test/cmdlineTests/import_asm_json_optimize/args create mode 100644 test/cmdlineTests/import_asm_json_optimize/exit create mode 100644 test/cmdlineTests/import_asm_json_optimize/output create mode 100644 test/cmdlineTests/import_asm_json_optimize/stdin delete mode 100644 test/cmdlineTests/import_asm_json_optimize_not_supported/args delete mode 100644 test/cmdlineTests/import_asm_json_optimize_not_supported/err delete mode 100644 test/cmdlineTests/import_asm_json_optimize_not_supported/exit delete mode 100644 test/cmdlineTests/import_asm_json_optimize_not_supported/stdin create mode 100644 test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json create mode 100644 test/cmdlineTests/import_asm_json_standard_json_no_optimize/output.json create mode 100644 test/cmdlineTests/import_asm_json_standard_json_optimize/input.json create mode 100644 test/cmdlineTests/import_asm_json_standard_json_optimize/output.json diff --git a/test/cmdlineTests/import_asm_json_no_optimize/args b/test/cmdlineTests/import_asm_json_no_optimize/args new file mode 100644 index 000000000..0af885908 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_no_optimize/args @@ -0,0 +1 @@ +--import-asm-json - --asm diff --git a/test/cmdlineTests/import_asm_json_no_optimize/output b/test/cmdlineTests/import_asm_json_no_optimize/output new file mode 100644 index 000000000..03aa23879 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_no_optimize/output @@ -0,0 +1,19 @@ +EVM assembly: + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + pop(0x00) + pop + pop + pop + pop + pop + pop + pop + revert diff --git a/test/cmdlineTests/import_asm_json_no_optimize/stdin b/test/cmdlineTests/import_asm_json_no_optimize/stdin new file mode 100644 index 000000000..c7017646a --- /dev/null +++ b/test/cmdlineTests/import_asm_json_no_optimize/stdin @@ -0,0 +1,23 @@ +{ + ".code": [ + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "REVERT" } + ] +} diff --git a/test/cmdlineTests/import_asm_json_optimize/args b/test/cmdlineTests/import_asm_json_optimize/args new file mode 100644 index 000000000..b9370e6e4 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_optimize/args @@ -0,0 +1 @@ +--optimize --import-asm-json - --asm diff --git a/test/cmdlineTests/import_asm_json_optimize/exit b/test/cmdlineTests/import_asm_json_optimize/exit new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_optimize/exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/import_asm_json_optimize/output b/test/cmdlineTests/import_asm_json_optimize/output new file mode 100644 index 000000000..25337fe77 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_optimize/output @@ -0,0 +1,2 @@ +EVM assembly: + revert(0x00, 0x00) diff --git a/test/cmdlineTests/import_asm_json_optimize/stdin b/test/cmdlineTests/import_asm_json_optimize/stdin new file mode 100644 index 000000000..c7017646a --- /dev/null +++ b/test/cmdlineTests/import_asm_json_optimize/stdin @@ -0,0 +1,23 @@ +{ + ".code": [ + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "REVERT" } + ] +} diff --git a/test/cmdlineTests/import_asm_json_optimize_not_supported/args b/test/cmdlineTests/import_asm_json_optimize_not_supported/args deleted file mode 100644 index f649e9740..000000000 --- a/test/cmdlineTests/import_asm_json_optimize_not_supported/args +++ /dev/null @@ -1 +0,0 @@ ---optimize --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_optimize_not_supported/err b/test/cmdlineTests/import_asm_json_optimize_not_supported/err deleted file mode 100644 index 8f42dca78..000000000 --- a/test/cmdlineTests/import_asm_json_optimize_not_supported/err +++ /dev/null @@ -1 +0,0 @@ -Error: Option --optimize is not supported with --import-asm-json. diff --git a/test/cmdlineTests/import_asm_json_optimize_not_supported/exit b/test/cmdlineTests/import_asm_json_optimize_not_supported/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/import_asm_json_optimize_not_supported/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/import_asm_json_optimize_not_supported/stdin b/test/cmdlineTests/import_asm_json_optimize_not_supported/stdin deleted file mode 100644 index f6cc54664..000000000 --- a/test/cmdlineTests/import_asm_json_optimize_not_supported/stdin +++ /dev/null @@ -1,6 +0,0 @@ -{ - ".code": [ - {"name": "DIFFICULTY"}, - {"name": "PREVRANDAO"} - ] -} diff --git a/test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json b/test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json new file mode 100644 index 000000000..d2ba25938 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json @@ -0,0 +1,37 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "REVERT" } + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["evm.assembly"] + } + } + } +} diff --git a/test/cmdlineTests/import_asm_json_standard_json_no_optimize/output.json b/test/cmdlineTests/import_asm_json_standard_json_no_optimize/output.json new file mode 100644 index 000000000..5dc5942bf --- /dev/null +++ b/test/cmdlineTests/import_asm_json_standard_json_no_optimize/output.json @@ -0,0 +1,29 @@ +{ + "contracts": { + "A": { + "": { + "evm": { + "assembly": " 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + pop(0x00) + pop + pop + pop + pop + pop + pop + pop + revert +" + } + } + } + } +} diff --git a/test/cmdlineTests/import_asm_json_standard_json_optimize/input.json b/test/cmdlineTests/import_asm_json_standard_json_optimize/input.json new file mode 100644 index 000000000..d1d458259 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_standard_json_optimize/input.json @@ -0,0 +1,40 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "PUSH", "value": "0" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "POP" }, + { "name": "REVERT" } + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["evm.assembly"] + } + }, + "optimizer": { + "enabled": true + } + } +} diff --git a/test/cmdlineTests/import_asm_json_standard_json_optimize/output.json b/test/cmdlineTests/import_asm_json_standard_json_optimize/output.json new file mode 100644 index 000000000..606862e0a --- /dev/null +++ b/test/cmdlineTests/import_asm_json_standard_json_optimize/output.json @@ -0,0 +1,12 @@ +{ + "contracts": { + "A": { + "": { + "evm": { + "assembly": " revert(0x00, 0x00) +" + } + } + } + } +} From 41f374b76dd289ba52c01327ec57caa7fdfd3298 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 13 Feb 2025 09:40:34 +0100 Subject: [PATCH 0708/1340] Remove evm version from Assembly::OptimiserSettings --- libevmasm/Assembly.cpp | 11 +++++------ libevmasm/Assembly.h | 3 +-- libsolidity/codegen/CompilerContext.h | 2 +- libsolidity/interface/StandardCompiler.cpp | 3 +-- libyul/YulStack.cpp | 2 +- solc/CommandLineInterface.cpp | 3 +-- test/libevmasm/Optimiser.cpp | 6 +++--- 7 files changed, 13 insertions(+), 17 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 91beb9a7f..21cabcbc5 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -819,8 +819,8 @@ std::map const& Assembly::optimiseInternal( _tagsReferencedFromOutside, _settings.expectedExecutionsPerDeployment, isCreation(), - _settings.evmVersion} - .optimise(); + m_evmVersion + }.optimise(); } // TODO: verify this for EOF. if (_settings.runJumpdestRemover && !m_eofVersion.has_value()) @@ -935,7 +935,7 @@ std::map const& Assembly::optimiseInternal( ConstantOptimisationMethod::optimiseConstants( isCreation(), isCreation() ? 1 : _settings.expectedExecutionsPerDeployment, - _settings.evmVersion, + m_evmVersion, *this ); @@ -1769,10 +1769,10 @@ Assembly const* Assembly::subAssemblyById(size_t _subId) const return currentAssembly; } -Assembly::OptimiserSettings Assembly::OptimiserSettings::translateSettings(frontend::OptimiserSettings const& _settings, langutil::EVMVersion const& _evmVersion) +Assembly::OptimiserSettings Assembly::OptimiserSettings::translateSettings(frontend::OptimiserSettings const& _settings) { // Constructing it this way so that we notice changes in the fields. - evmasm::Assembly::OptimiserSettings asmSettings{false, false, false, false, false, false, _evmVersion, 0}; + OptimiserSettings asmSettings{false, false, false, false, false, false, 0}; asmSettings.runInliner = _settings.runInliner; asmSettings.runJumpdestRemover = _settings.runJumpdestRemover; asmSettings.runPeephole = _settings.runPeephole; @@ -1780,6 +1780,5 @@ Assembly::OptimiserSettings Assembly::OptimiserSettings::translateSettings(front asmSettings.runCSE = _settings.runCSE; asmSettings.runConstantOptimiser = _settings.runConstantOptimiser; asmSettings.expectedExecutionsPerDeployment = _settings.expectedExecutionsPerDeployment; - asmSettings.evmVersion = _evmVersion; return asmSettings; } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 92dfb0a44..6f30fa635 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -166,12 +166,11 @@ class Assembly bool runDeduplicate = false; bool runCSE = false; bool runConstantOptimiser = false; - langutil::EVMVersion evmVersion; /// This specifies an estimate on how often each opcode in this assembly will be executed, /// i.e. use a small value to optimise for size and a large value to optimise for runtime gas usage. size_t expectedExecutionsPerDeployment = frontend::OptimiserSettings{}.expectedExecutionsPerDeployment; - static OptimiserSettings translateSettings(frontend::OptimiserSettings const& _settings, langutil::EVMVersion const& _evmVersion); + static OptimiserSettings translateSettings(frontend::OptimiserSettings const& _settings); }; /// Modify and return the current assembly such that creation and execution gas usage diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 17559fbf4..5f50bbefd 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -284,7 +284,7 @@ class CompilerContext void appendToAuxiliaryData(bytes const& _data) { m_asm->appendToAuxiliaryData(_data); } /// Run optimisation step. - void optimise(OptimiserSettings const& _settings) { m_asm->optimise(evmasm::Assembly::OptimiserSettings::translateSettings(_settings, m_evmVersion)); } + void optimise(OptimiserSettings const& _settings) { m_asm->optimise(evmasm::Assembly::OptimiserSettings::translateSettings(_settings)); } /// @returns the runtime context if in creation mode and runtime context is set, nullptr otherwise. CompilerContext* runtimeContext() const { return m_runtimeContext; } diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index fb0ea4514..1671267d7 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1244,8 +1244,7 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in _inputsAndSettings.evmVersion, _inputsAndSettings.eofVersion, evmasm::Assembly::OptimiserSettings::translateSettings( - _inputsAndSettings.optimiserSettings, - _inputsAndSettings.evmVersion + _inputsAndSettings.optimiserSettings ) ); std::string const& sourceName = _inputsAndSettings.jsonSources.begin()->first; // result of structured binding can only be used within lambda from C++20 on. diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index f58705e9c..1ad24998f 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -324,7 +324,7 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) { compileEVM(adapter, optimize); - assembly.optimise(evmasm::Assembly::OptimiserSettings::translateSettings(m_optimiserSettings, m_evmVersion)); + assembly.optimise(evmasm::Assembly::OptimiserSettings::translateSettings(m_optimiserSettings)); std::optional subIndex; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 92acad4bd..4fd730096 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -893,8 +893,7 @@ void CommandLineInterface::assembleFromEVMAssemblyJSON() m_options.output.evmVersion, m_options.output.eofVersion, evmasm::Assembly::OptimiserSettings::translateSettings( - m_options.optimiserSettings(), - m_options.output.evmVersion + m_options.optimiserSettings() ) ); try diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index a8e9afeaf..f4b7034de 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1345,11 +1345,11 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies, *boost::unit_test::precondi settings.runDeduplicate = true; settings.runCSE = true; settings.runConstantOptimiser = true; - settings.evmVersion = solidity::test::CommonOptions::get().evmVersion(); settings.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment; - Assembly main{settings.evmVersion, false, std::nullopt, {}}; - AssemblyPointer sub = std::make_shared(settings.evmVersion, true, std::nullopt, std::string{}); + auto const evmVersion = CommonOptions::get().evmVersion(); + Assembly main{evmVersion, false, std::nullopt, {}}; + AssemblyPointer sub = std::make_shared(evmVersion, true, std::nullopt, std::string{}); sub->append(u256(1)); auto t1 = sub->newTag(); From 20569e4c61f80600801255836c6c163c37b8663e Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 14 Feb 2025 09:15:34 +0100 Subject: [PATCH 0709/1340] eof: Add EOF initial support changelog entry. --- Changelog.md | 1 + docs/using-the-compiler.rst | 1 + 2 files changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index 0145ace66..75bd75eae 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: * Error Reporting: Errors reported during code generation now point at the location of the contract when more fine-grained location is not available. * EVM: Support for the EVM version "Osaka". * EVM Assembly Import: Allow enabling opcode-based optimizer. + * General: The experimental EOF backend implements a subset of EOF sufficient to compile arbitrary high-level Solidity syntax via IR with optimization enabled. * SMTChecker: Support `block.blobbasefee` and `blobhash`. * SMTChecker: Z3 is now a runtime dependency, not a build dependency (except for emscripten build). * Yul Parser: Make name clash with a builtin a non-fatal error. diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 8893f6c50..97db1d7ce 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -183,6 +183,7 @@ at each version. Backward compatibility is not guaranteed between each version. - Opcodes ``tstore`` and ``tload`` are available in assembly (see `EIP-1153 `_). - ``prague`` (**experimental**) - ``osaka`` (**experimental**) + - Experimental compilation to EOF is available starting from this version. (`EIP-7692 `_) .. index:: ! standard JSON, ! --standard-json .. _compiler-api: From 2f11f6539b791f09387d024fe68d3f4aee181b58 Mon Sep 17 00:00:00 2001 From: Maxim Evtush <154841002+maximevtush@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:09:45 +0100 Subject: [PATCH 0710/1340] fix: typos in a few syntax test file names (#15858) * fix typo public_var_parallel_funciton.sol to public_var_parallel_function.sol * gix typo: invalid_variable_mutablity.sol -> invalid_variable_mutability.sol * fix typo: recursive_function_paramter_err.sol -> recursive_function_parameter_err.sol --- ...var_parallel_funciton.sol => public_var_parallel_function.sol} | 0 ...lid_variable_mutablity.sol => invalid_variable_mutability.sol} | 0 ...tion_paramter_err.sol => recursive_function_parameter_err.sol} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/syntaxTests/inheritance/override/{public_var_parallel_funciton.sol => public_var_parallel_function.sol} (100%) rename test/libsolidity/syntaxTests/parsing/{invalid_variable_mutablity.sol => invalid_variable_mutability.sol} (100%) rename test/libsolidity/syntaxTests/userDefinedValueType/{recursive_function_paramter_err.sol => recursive_function_parameter_err.sol} (100%) diff --git a/test/libsolidity/syntaxTests/inheritance/override/public_var_parallel_funciton.sol b/test/libsolidity/syntaxTests/inheritance/override/public_var_parallel_function.sol similarity index 100% rename from test/libsolidity/syntaxTests/inheritance/override/public_var_parallel_funciton.sol rename to test/libsolidity/syntaxTests/inheritance/override/public_var_parallel_function.sol diff --git a/test/libsolidity/syntaxTests/parsing/invalid_variable_mutablity.sol b/test/libsolidity/syntaxTests/parsing/invalid_variable_mutability.sol similarity index 100% rename from test/libsolidity/syntaxTests/parsing/invalid_variable_mutablity.sol rename to test/libsolidity/syntaxTests/parsing/invalid_variable_mutability.sol diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_paramter_err.sol b/test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_parameter_err.sol similarity index 100% rename from test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_paramter_err.sol rename to test/libsolidity/syntaxTests/userDefinedValueType/recursive_function_parameter_err.sol From 868154c56e82d1a8bdd1fc40331e32da7e8d4992 Mon Sep 17 00:00:00 2001 From: kilavvy <140459108+kilavvy@users.noreply.github.com> Date: Fri, 14 Feb 2025 23:42:33 +0100 Subject: [PATCH 0711/1340] fix: typos in a few syntax and natspec test file names (#15864) * typo fix * fix typo * typo fix --- ..._param_description.sol => dev_multiline_param_description.sol} | 0 ...stract_contructor_param.sol => abstract_constructor_param.sol} | 0 ...mory.sol => mapping_struct_recursive_data_location_memory.sol} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/natspecJSON/{dev_mutiline_param_description.sol => dev_multiline_param_description.sol} (100%) rename test/libsolidity/syntaxTests/types/mapping/{abstract_contructor_param.sol => abstract_constructor_param.sol} (100%) rename test/libsolidity/syntaxTests/types/mapping/{mapping_struct_recusrive_data_location_memory.sol => mapping_struct_recursive_data_location_memory.sol} (100%) diff --git a/test/libsolidity/natspecJSON/dev_mutiline_param_description.sol b/test/libsolidity/natspecJSON/dev_multiline_param_description.sol similarity index 100% rename from test/libsolidity/natspecJSON/dev_mutiline_param_description.sol rename to test/libsolidity/natspecJSON/dev_multiline_param_description.sol diff --git a/test/libsolidity/syntaxTests/types/mapping/abstract_contructor_param.sol b/test/libsolidity/syntaxTests/types/mapping/abstract_constructor_param.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/mapping/abstract_contructor_param.sol rename to test/libsolidity/syntaxTests/types/mapping/abstract_constructor_param.sol diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_struct_recusrive_data_location_memory.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_struct_recursive_data_location_memory.sol similarity index 100% rename from test/libsolidity/syntaxTests/types/mapping/mapping_struct_recusrive_data_location_memory.sol rename to test/libsolidity/syntaxTests/types/mapping/mapping_struct_recursive_data_location_memory.sol From 80eb5279eaf771ca3828255163706610660311dc Mon Sep 17 00:00:00 2001 From: Fallengirl <155266340+Fallengirl@users.noreply.github.com> Date: Sat, 15 Feb 2025 14:04:36 +0100 Subject: [PATCH 0712/1340] Fix spelling errors in a few code comments in libsolidity and SMTChecker (#15866) * Update CompilerContext.h * Update BMC.cpp * Update SMTEncoder.h --- libsolidity/codegen/CompilerContext.h | 2 +- libsolidity/formal/BMC.cpp | 2 +- libsolidity/formal/SMTEncoder.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 5f50bbefd..e8c4e9bc7 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -367,7 +367,7 @@ class CompilerContext /// modifier is applied twice, the position of the variable needs to be restored /// after the nested modifier is left. std::map> m_localVariables; - /// The contract currently being compiled. Virtual function lookup starts from this contarct. + /// The contract currently being compiled. Virtual function lookup starts from this contract. ContractDefinition const* m_mostDerivedContract = nullptr; /// Whether to use checked arithmetic. Arithmetic m_arithmetic = Arithmetic::Checked; diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 5fb2f5a9f..1b6be1579 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -459,7 +459,7 @@ bool BMC::visit(ForStatement const& _node) _node.condition()->accept(*this); forCondition = expr(*_node.condition()); } - // asseert that the loop is complete + // assert that the loop is complete m_context.addAssertion(!forCondition || broke || !forConditionOnPreviousIterations); mergeVariables( broke || !forConditionOnPreviousIterations, diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index c6c549151..f926a0d0f 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -508,7 +508,7 @@ class SMTEncoder: public ASTConstVisitor ContractDefinition const* m_currentContract = nullptr; /// Stores the free functions and internal library functions. - /// Those need to be encoded repeatedely for every analyzed contract. + /// Those need to be encoded repeatedly for every analyzed contract. std::set m_freeFunctions; /// Stores the context of the encoding. From e94a1f1415b3041b7555437685609e64727ab7d2 Mon Sep 17 00:00:00 2001 From: xiaobei0715 <1505929057@qq.com> Date: Sat, 15 Feb 2025 14:39:10 +0800 Subject: [PATCH 0713/1340] Updating copyright year to 2025 --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index f57a3b5b9..dc52c96bd 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -114,7 +114,7 @@ def get_github_username_repo(url): # General information about the project. project = 'Solidity' -project_copyright = '2016-2024, The Solidity Authors' +project_copyright = '2016-2025, The Solidity Authors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the From 7f3a8e267e9d39c0b8d428736ae5401f1f80081d Mon Sep 17 00:00:00 2001 From: PixelPilot <161360836+PixelPil0t1@users.noreply.github.com> Date: Sun, 16 Feb 2025 15:49:03 +0100 Subject: [PATCH 0714/1340] Grammar and typo fixes in code comments (#15869) * Update emscripten.jam * Update SSATransform.h --- libyul/optimiser/SSATransform.h | 2 +- scripts/docker/buildpack-deps/emscripten.jam | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libyul/optimiser/SSATransform.h b/libyul/optimiser/SSATransform.h index 64181bf20..4b46d7169 100644 --- a/libyul/optimiser/SSATransform.h +++ b/libyul/optimiser/SSATransform.h @@ -67,7 +67,7 @@ class NameDispenser; * The current value mapping is cleared for a variable a at the end of each block * 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 + * variable references can use the SSA variable. The only exception to this rule is * for loop conditions, as we cannot insert a variable declaration there. * * After this stage, UnusedAssignmentEliminator is recommended to remove the unnecessary diff --git a/scripts/docker/buildpack-deps/emscripten.jam b/scripts/docker/buildpack-deps/emscripten.jam index bc8f0fa00..21768524f 100644 --- a/scripts/docker/buildpack-deps/emscripten.jam +++ b/scripts/docker/buildpack-deps/emscripten.jam @@ -25,7 +25,7 @@ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # -# Boost.Build support for Emscipten. +# Boost.Build support for Emscripten. # # @todo add support for dynamic linking # @todo add support for --js-library, --pre-js, and --post-js options From 76686ecbc67ecfc4577fd33f4ba7fe53fc8c9f57 Mon Sep 17 00:00:00 2001 From: FT <140458077+zeevick10@users.noreply.github.com> Date: Sun, 16 Feb 2025 16:20:14 +0100 Subject: [PATCH 0715/1340] fix: typos in a few test file names (#15867) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix typo: funtion_call.yul to function_call.yul * fix typo: constructer_internal_function_abstract.sol to constructor_internal_function_abstract.sol * fix typo: non_implemented_modifer.sol to non_implemented_modifier.sol --------- Co-authored-by: zeevick10 --- ...on_abstract.sol => constructor_internal_function_abstract.sol} | 0 .../{non_implemented_modifer.sol => non_implemented_modifier.sol} | 0 .../disambiguator/{funtion_call.yul => function_call.yul} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/syntaxTests/constructor/{constructer_internal_function_abstract.sol => constructor_internal_function_abstract.sol} (100%) rename test/libsolidity/syntaxTests/controlFlow/modifiers/{non_implemented_modifer.sol => non_implemented_modifier.sol} (100%) rename test/libyul/yulOptimizerTests/disambiguator/{funtion_call.yul => function_call.yul} (100%) diff --git a/test/libsolidity/syntaxTests/constructor/constructer_internal_function_abstract.sol b/test/libsolidity/syntaxTests/constructor/constructor_internal_function_abstract.sol similarity index 100% rename from test/libsolidity/syntaxTests/constructor/constructer_internal_function_abstract.sol rename to test/libsolidity/syntaxTests/constructor/constructor_internal_function_abstract.sol diff --git a/test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifer.sol b/test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifier.sol similarity index 100% rename from test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifer.sol rename to test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifier.sol diff --git a/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul b/test/libyul/yulOptimizerTests/disambiguator/function_call.yul similarity index 100% rename from test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul rename to test/libyul/yulOptimizerTests/disambiguator/function_call.yul From 68c4aa3c943ce1e238e8fc36296928edd6394f1f Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 10 Feb 2025 19:36:10 +0100 Subject: [PATCH 0716/1340] Add SWAPN/DUPN. --- libevmasm/Assembly.cpp | 22 +++++++++++++-- libevmasm/Assembly.h | 6 +++- libevmasm/AssemblyItem.cpp | 27 +++++++++++++++++- libevmasm/AssemblyItem.h | 18 ++++++++++-- libevmasm/Instruction.cpp | 4 +++ libevmasm/Instruction.h | 26 ++--------------- libevmasm/KnownState.cpp | 4 +-- libevmasm/PeepholeOptimiser.cpp | 2 +- libevmasm/SemanticInformation.cpp | 28 +++++++++++++++++-- libevmasm/SemanticInformation.h | 4 +++ liblangutil/EVMVersion.cpp | 2 ++ libyul/AsmAnalysis.cpp | 4 ++- libyul/backends/evm/AbstractAssembly.h | 7 +++++ libyul/backends/evm/EVMDialect.cpp | 6 ++-- libyul/backends/evm/EthAssemblyAdapter.cpp | 11 ++++++++ libyul/backends/evm/EthAssemblyAdapter.h | 3 ++ libyul/backends/evm/NoOutputAssembly.cpp | 5 ++++ libyul/backends/evm/NoOutputAssembly.h | 2 ++ .../eof_identifiers_not_defined_in_legacy.yul | 4 +++ ...eof_identifiers_not_reserved_in_legacy.yul | 2 ++ ...of_opcodes_identifiers_reserved_in_eof.yul | 4 +++ .../EVMInstructionInterpreter.cpp | 2 ++ 22 files changed, 155 insertions(+), 38 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 21cabcbc5..4dcc6a4b0 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -767,11 +767,21 @@ AssemblyItem Assembly::newImmutableAssignment(std::string const& _identifier) return AssemblyItem{AssignImmutable, h}; } -AssemblyItem Assembly::newAuxDataLoadN(size_t _offset) +AssemblyItem Assembly::newAuxDataLoadN(size_t _offset) const { return AssemblyItem{AuxDataLoadN, _offset}; } +AssemblyItem Assembly::newSwapN(size_t _depth) const +{ + return AssemblyItem::swapN(_depth); +} + +AssemblyItem Assembly::newDupN(size_t _depth) const +{ + return AssemblyItem::dupN(_depth); +} + Assembly& Assembly::optimise(OptimiserSettings const& _settings) { optimiseInternal(_settings, {}); @@ -1558,7 +1568,9 @@ LinkerObject const& Assembly::assembleEOF() const item.instruction() != Instruction::RJUMPI && item.instruction() != Instruction::CALLF && item.instruction() != Instruction::JUMPF && - item.instruction() != Instruction::RETF + item.instruction() != Instruction::RETF && + item.instruction() != Instruction::DUPN && + item.instruction() != Instruction::SWAPN ); solAssert(!(item.instruction() >= Instruction::PUSH0 && item.instruction() <= Instruction::PUSH32)); ret.bytecode += assembleOperation(item); @@ -1636,6 +1648,12 @@ LinkerObject const& Assembly::assembleEOF() const case RetF: ret.bytecode.push_back(static_cast(Instruction::RETF)); break; + case SwapN: + case DupN: + ret.bytecode.push_back(static_cast(item.instruction())); + solAssert(item.data() >= 1 && item.data() <= 256); + ret.bytecode.push_back(static_cast(item.data() - 1)); + break; default: solAssert(false, "Unexpected opcode while assembling."); } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 6f30fa635..30b06dd36 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -88,7 +88,9 @@ class Assembly AssemblyItem newPushLibraryAddress(std::string const& _identifier); AssemblyItem newPushImmutable(std::string const& _identifier); AssemblyItem newImmutableAssignment(std::string const& _identifier); - AssemblyItem newAuxDataLoadN(size_t offset); + AssemblyItem newAuxDataLoadN(size_t offset) const; + AssemblyItem newSwapN(size_t _depth) const; + AssemblyItem newDupN(size_t _depth) const; AssemblyItem const& append(AssemblyItem _i); AssemblyItem const& append(bytes const& _data) { return append(newData(_data)); } @@ -102,6 +104,8 @@ class Assembly void appendImmutable(std::string const& _identifier) { append(newPushImmutable(_identifier)); } void appendImmutableAssignment(std::string const& _identifier) { append(newImmutableAssignment(_identifier)); } void appendAuxDataLoadN(uint16_t _offset) { append(newAuxDataLoadN(_offset));} + void appendSwapN(size_t _depth) { append(newSwapN(_depth)); } + void appendDupN(size_t _depth) { append(newDupN(_depth)); } void appendVerbatim(bytes _data, size_t _arguments, size_t _returnVariables) { diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 3bc7ef704..8a917986f 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -90,6 +91,9 @@ std::pair AssemblyItem::nameAndData(langutil::EVMVersi case JumpF: case RetF: return {instructionInfo(instruction(), _evmVersion).name, ""}; + case SwapN: + case DupN: + return {instructionInfo(instruction(), _evmVersion).name, util::toString(static_cast(data())) }; case Push: return {"PUSH", toStringInHex(data())}; case PushTag: @@ -192,6 +196,10 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, langutil::EVMVersion _ return 2; case ReturnContract: return 2; + case SwapN: + return 2; + case DupN: + return 2; case UndefinedItem: solAssert(false); } @@ -203,6 +211,10 @@ size_t AssemblyItem::arguments() const { if (type() == CallF || type() == JumpF) return functionSignature().argsNum; + else if (type() == SwapN) + return static_cast(data()) + 1; + else if (type() == DupN) + return static_cast(data()); else if (hasInstruction()) { solAssert(instruction() != Instruction::CALLF && instruction() != Instruction::JUMPF); @@ -231,6 +243,9 @@ size_t AssemblyItem::returnValues() const // The latest EVMVersion is used here, since the InstructionInfo is assumed to be // the same across all EVM versions except for the instruction name. return static_cast(instructionInfo(instruction(), EVMVersion()).ret); + case SwapN: + case DupN: + return static_cast(data()) + 1; case Push: case PushTag: case PushData: @@ -270,8 +285,10 @@ bool AssemblyItem::canBeFunctional() const case ConditionalRelativeJump: case CallF: case JumpF: + case SwapN: + case DupN: case RetF: - return !isDupInstruction(instruction()) && !isSwapInstruction(instruction()); + return !SemanticInformation::isDupInstruction(*this) && !SemanticInformation::isSwapInstruction(*this); case Push: case PushTag: case PushData: @@ -410,6 +427,12 @@ std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const case RetF: text = "retf"; break; + case SwapN: + text = "swapn{" + std::to_string(static_cast(data())) + "}"; + break; + case DupN: + text = "dupn{" + std::to_string(static_cast(data())) + "}"; + break; } if (m_jumpType == JumpType::IntoFunction || m_jumpType == JumpType::OutOfFunction) { @@ -435,6 +458,8 @@ std::ostream& solidity::evmasm::operator<<(std::ostream& _out, AssemblyItem cons case CallF: case JumpF: case RetF: + case SwapN: + case DupN: _out << " " << instructionInfo(_item.instruction(), EVMVersion()).name; if (_item.instruction() == Instruction::JUMP || _item.instruction() == Instruction::JUMPI) _out << "\t" << _item.getJumpTypeAsString(); diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index babf2b7b7..b053c5b27 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -62,7 +62,9 @@ enum AssemblyItemType CallF, ///< Jumps to a returning EOF function, adding a new frame to the return stack. JumpF, ///< Jumps to a returning or non-returning EOF function without changing the return stack. RetF, ///< Returns from an EOF function, removing a frame from the return stack. - VerbatimBytecode ///< Contains data that is inserted into the bytecode code section without modification. + VerbatimBytecode, ///< Contains data that is inserted into the bytecode code section without modification. + SwapN, ///< EOF SWAPN with immediate argument. + DupN, ///< EOF DUPN with immediate argument. }; enum class Precision { Precise , Approximate }; @@ -147,6 +149,16 @@ class AssemblyItem solAssert(_tag.type() == Tag); return AssemblyItem(ConditionalRelativeJump, Instruction::RJUMPI, _tag.data(), _debugData); } + static AssemblyItem swapN(size_t _depth, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + solAssert(_depth >= 1 && _depth <= 256); + return AssemblyItem(SwapN, Instruction::SWAPN, _depth, _debugData); + } + static AssemblyItem dupN(size_t _depth, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()) + { + solAssert(_depth >= 1 && _depth <= 256); + return AssemblyItem(DupN, Instruction::DUPN, _depth, _debugData); + } AssemblyItem(AssemblyItem const&) = default; AssemblyItem(AssemblyItem&&) = default; @@ -191,7 +203,9 @@ class AssemblyItem m_type == ConditionalRelativeJump || m_type == CallF || m_type == JumpF || - m_type == RetF; + m_type == RetF || + m_type == SwapN || + m_type == DupN; } /// @returns the instruction of this item (only valid if hasInstruction returns true) Instruction instruction() const diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 649a6c863..dad9804d0 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -172,6 +172,8 @@ std::map const solidity::evmasm::c_instructions = { "CALLF", Instruction::CALLF }, { "RETF", Instruction::RETF }, { "JUMPF", Instruction::JUMPF }, + { "DUPN", Instruction::DUPN }, + { "SWAPN", Instruction::SWAPN }, { "RJUMP", Instruction::RJUMP }, { "RJUMPI", Instruction::RJUMPI }, { "EOFCREATE", Instruction::EOFCREATE }, @@ -339,6 +341,8 @@ static std::map const c_instructionInfo = {Instruction::RETF, {"RETF", 0, 0, 0, true, Tier::RetF}}, {Instruction::CALLF, {"CALLF", 2, 0, 0, true, Tier::CallF}}, {Instruction::JUMPF, {"JUMPF", 2, 0, 0, true, Tier::JumpF}}, + {Instruction::SWAPN, {"SWAPN", 1, 0, 0, false, Tier::VeryLow}}, + {Instruction::DUPN, {"DUPN", 1, 0, 0, false, Tier::VeryLow}}, {Instruction::EOFCREATE, {"EOFCREATE", 1, 4, 1, true, Tier::Special}}, {Instruction::RETURNCONTRACT, {"RETURNCONTRACT", 1, 2, 0, true, Tier::Special}}, {Instruction::CREATE, {"CREATE", 0, 3, 1, true, Tier::Special}}, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index a1b9af364..137144715 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -190,6 +190,8 @@ enum class Instruction: uint8_t CALLF = 0xe3, ///< call function in a EOF code section RETF = 0xe4, ///< return to caller from the code section of EOF container JUMPF = 0xe5, ///< jump to a code section of EOF container without adding a new return stack frame. + DUPN = 0xe6, ///< copies a value at the stack depth given as immediate argument to the top of the stack + SWAPN = 0xe7, ///< swaps the highest value with a value at a stack depth given as immediate argument EOFCREATE = 0xec, ///< create a new account with associated container code. RETURNCONTRACT = 0xee, ///< return container to be deployed with axiliary data filled in. CREATE = 0xf0, ///< create a new account with associated code @@ -232,18 +234,6 @@ inline bool isPushInstruction(Instruction _inst) return Instruction::PUSH0 <= _inst && _inst <= Instruction::PUSH32; } -/// @returns true if the instruction is a DUP -inline bool isDupInstruction(Instruction _inst) -{ - return Instruction::DUP1 <= _inst && _inst <= Instruction::DUP16; -} - -/// @returns true if the instruction is a SWAP -inline bool isSwapInstruction(Instruction _inst) -{ - return Instruction::SWAP1 <= _inst && _inst <= Instruction::SWAP16; -} - /// @returns true if the instruction is a LOG inline bool isLogInstruction(Instruction _inst) { @@ -256,18 +246,6 @@ inline unsigned getPushNumber(Instruction _inst) return static_cast(_inst) - unsigned(Instruction::PUSH0); } -/// @returns the number of DUP Instruction _inst -inline unsigned getDupNumber(Instruction _inst) -{ - return static_cast(_inst) - unsigned(Instruction::DUP1) + 1; -} - -/// @returns the number of SWAP Instruction _inst -inline unsigned getSwapNumber(Instruction _inst) -{ - return static_cast(_inst) - unsigned(Instruction::SWAP1) + 1; -} - /// @returns the number of LOG Instruction _inst inline unsigned getLogNumber(Instruction _inst) { diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 66553bc06..6e1a00465 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -137,14 +137,14 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool setStackElement( m_stackHeight + 1, stackElement( - m_stackHeight - static_cast(instruction) + static_cast(Instruction::DUP1), + m_stackHeight - (static_cast(SemanticInformation::getDupNumber(_item)) - 1), _item.debugData() ) ); else if (SemanticInformation::isSwapInstruction(_item)) swapStackElements( m_stackHeight, - m_stackHeight - 1 - static_cast(instruction) + static_cast(Instruction::SWAP1), + m_stackHeight - 1 - (static_cast(SemanticInformation::getSwapNumber(_item)) - 1), _item.debugData() ); else if (instruction != Instruction::POP) diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 3129efb4d..879f5b327 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -290,7 +290,7 @@ struct DupSwap: SimplePeepholeOptimizerMethod if ( SemanticInformation::isDupInstruction(_dupN) && SemanticInformation::isSwapInstruction(_swapN) && - getDupNumber(_dupN.instruction()) == getSwapNumber(_swapN.instruction()) + SemanticInformation::getDupNumber(_dupN) == SemanticInformation::getSwapNumber(_swapN) ) { *_out = _dupN; diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index a9672efa5..662436ff6 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -312,16 +312,22 @@ bool SemanticInformation::isCommutativeOperation(AssemblyItem const& _item) bool SemanticInformation::isDupInstruction(AssemblyItem const& _item) { + if (_item.type() == evmasm::DupN) + return true; if (_item.type() != evmasm::Operation) return false; - return evmasm::isDupInstruction(_item.instruction()); + auto inst = _item.instruction(); + return Instruction::DUP1 <= inst && inst <= Instruction::DUP16; } bool SemanticInformation::isSwapInstruction(AssemblyItem const& _item) { + if (_item.type() == evmasm::SwapN) + return true; if (_item.type() != evmasm::Operation) return false; - return evmasm::isSwapInstruction(_item.instruction()); + auto inst = _item.instruction(); + return Instruction::SWAP1 <= inst && inst <= Instruction::SWAP16; } bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) @@ -387,6 +393,24 @@ bool SemanticInformation::reverts(Instruction _instruction) } } +size_t SemanticInformation::getDupNumber(AssemblyItem const& _item) +{ + assertThrow(isDupInstruction(_item), OptimizerException, "Not a DUP instruction."); + if (_item.type() == evmasm::DupN) + return static_cast(_item.data()); + auto inst = _item.instruction(); + return static_cast(inst) - static_cast(Instruction::DUP1) + 1; +} + +size_t SemanticInformation::getSwapNumber(AssemblyItem const& _item) +{ + assertThrow(isSwapInstruction(_item), OptimizerException, "Not a swap instruction."); + if (_item.type() == evmasm::SwapN) + return static_cast(_item.data()); + auto inst = _item.instruction(); + return static_cast(inst) - static_cast(Instruction::SWAP1) + 1; +} + bool SemanticInformation::isDeterministic(AssemblyItem const& _item) { assertThrow(_item.type() != VerbatimBytecode, AssemblyException, ""); diff --git a/libevmasm/SemanticInformation.h b/libevmasm/SemanticInformation.h index 457f60052..8dae6acad 100644 --- a/libevmasm/SemanticInformation.h +++ b/libevmasm/SemanticInformation.h @@ -86,6 +86,10 @@ struct SemanticInformation static bool terminatesControlFlow(AssemblyItem const& _item); static bool terminatesControlFlow(Instruction _instruction); static bool reverts(Instruction _instruction); + /// @returns the 1-based DUP depth a DUP AssembleItem @a _item + static size_t getDupNumber(AssemblyItem const& _item); + /// @returns the 1-based SWAP depth a DUP AssembleItem @a _item + static size_t getSwapNumber(AssemblyItem const& _item); /// @returns false if the value put on the stack by _item depends on anything else than /// the information in the current block header, memory, storage, transient storage or stack. static bool isDeterministic(AssemblyItem const& _item); diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index 30df93796..4fbfe8de4 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -84,6 +84,8 @@ bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersi case Instruction::RJUMPI: case Instruction::CALLF: case Instruction::JUMPF: + case Instruction::DUPN: + case Instruction::SWAPN: case Instruction::RETF: case Instruction::EXTCALL: case Instruction::EXTSTATICCALL: diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 7c82d788f..352f16f76 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -741,7 +741,9 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio _instr != evmasm::Instruction::RJUMPI && _instr != evmasm::Instruction::CALLF && _instr != evmasm::Instruction::JUMPF && - _instr != evmasm::Instruction::RETF + _instr != evmasm::Instruction::RETF && + _instr != evmasm::Instruction::DUPN && + _instr != evmasm::Instruction::SWAPN ); auto errorForVM = [&](ErrorId _errorId, std::string const& vmKindMessage) { diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index 7a3e6b742..41f480f44 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -149,6 +149,13 @@ class AbstractAssembly /// EOF auxiliary data in data section and the auxiliary data are different things. virtual void appendToAuxiliaryData(bytes const& _data) = 0; + /// Appends a SWAPN with 1-based indexing for @arg _depth. I.e. a depth of 1 would be equivalent to emitting SWAP1. + /// @arg _depth ranges from 1 to 256. + virtual void appendSwapN(size_t _depth) = 0; + /// Appends a DUPN with 1-based indexing for @arg _depth. I.e. a depth of 1 would be equivalent to emitting DUP1. + /// @arg _depth ranges from 1 to 256. + virtual void appendDupN(size_t _depth) = 0; + /// Mark this assembly as invalid. Any attempt to request bytecode from it should throw. virtual void markAsInvalid() = 0; diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 4fa78f023..d68ef1634 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -211,8 +211,8 @@ std::vector> createBuiltins(langutil::EVMVe auto const opcode = instr.second; if ( - !evmasm::isDupInstruction(opcode) && - !evmasm::isSwapInstruction(opcode) && + !(opcode >= evmasm::Instruction::DUP1 && opcode <= evmasm::Instruction::DUP16) && + !(opcode >= evmasm::Instruction::SWAP1 && opcode <= evmasm::Instruction::SWAP16) && !evmasm::isPushInstruction(opcode) && opcode != evmasm::Instruction::JUMP && opcode != evmasm::Instruction::JUMPI && @@ -224,6 +224,8 @@ std::vector> createBuiltins(langutil::EVMVe opcode != evmasm::Instruction::RJUMPI && opcode != evmasm::Instruction::CALLF && opcode != evmasm::Instruction::JUMPF && + opcode != evmasm::Instruction::DUPN && + opcode != evmasm::Instruction::SWAPN && opcode != evmasm::Instruction::RETF && _evmVersion.hasOpcode(opcode, _eofVersion) && !prevRandaoException(name) diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index b608859e2..960e663df 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -232,6 +232,17 @@ void EthAssemblyAdapter::appendAuxDataLoadN(uint16_t _offset) m_assembly.appendAuxDataLoadN(_offset); } +void EthAssemblyAdapter::appendSwapN(size_t _depth) +{ + m_assembly.appendSwapN(_depth); +} + +void EthAssemblyAdapter::appendDupN(size_t _depth) +{ + m_assembly.appendDupN(_depth); +} + + void EthAssemblyAdapter::markAsInvalid() { m_assembly.markAsInvalid(); diff --git a/libyul/backends/evm/EthAssemblyAdapter.h b/libyul/backends/evm/EthAssemblyAdapter.h index 93e7c816a..dd708b8b3 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.h +++ b/libyul/backends/evm/EthAssemblyAdapter.h @@ -74,6 +74,9 @@ class EthAssemblyAdapter: public AbstractAssembly void appendAuxDataLoadN(uint16_t _offset) override; + void appendSwapN(size_t _depth) override; + void appendDupN(size_t _depth) override; + void markAsInvalid() override; langutil::EVMVersion evmVersion() const override; diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 322191984..78025265f 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -114,6 +114,11 @@ void NoOutputAssembly::appendAssemblySize() appendInstruction(evmasm::Instruction::PUSH1); } +void NoOutputAssembly::appendDupN(size_t) +{ + m_stackHeight++; +} + std::pair, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly(bool, std::string) { yulAssert(false, "Sub assemblies not implemented."); diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h index 64832b083..502f90d85 100644 --- a/libyul/backends/evm/NoOutputAssembly.h +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -90,6 +90,8 @@ class NoOutputAssembly: public AbstractAssembly void appendAuxDataLoadN(uint16_t) override; void appendEOFCreate(ContainerID) override; void appendReturnContract(ContainerID) override; + void appendSwapN(size_t) override {} + void appendDupN(size_t) override; void markAsInvalid() override {} diff --git a/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul index 0b786893e..71137488f 100644 --- a/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul +++ b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_defined_in_legacy.yul @@ -11,6 +11,8 @@ extcall(0, 1, 2, 3) extstaticcall(0, 1, 2) extdelegatecall(0, 1, 2) + swapn() + dupn() } // ==== // bytecodeFormat: legacy @@ -27,3 +29,5 @@ // TypeError 4328: (172-179): The "extcall" instruction is only available in EOF. // TypeError 4328: (196-209): The "extstaticcall" instruction is only available in EOF. // TypeError 4328: (223-238): The "extdelegatecall" instruction is only available in EOF. +// DeclarationError 4619: (252-257): Function "swapn" not found. +// DeclarationError 4619: (264-268): Function "dupn" not found. diff --git a/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_reserved_in_legacy.yul b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_reserved_in_legacy.yul index 3cb737d4b..313e17884 100644 --- a/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_reserved_in_legacy.yul +++ b/test/libyul/yulSyntaxTests/eof/eof_identifiers_not_reserved_in_legacy.yul @@ -11,6 +11,8 @@ function extcall() {} function extstaticcall() {} function extdelegatecall() {} + function swapn() {} + function dupn() {} } // ==== // bytecodeFormat: legacy \ No newline at end of file diff --git a/test/libyul/yulSyntaxTests/eof/eof_opcodes_identifiers_reserved_in_eof.yul b/test/libyul/yulSyntaxTests/eof/eof_opcodes_identifiers_reserved_in_eof.yul index 17ca120e6..6992e4003 100644 --- a/test/libyul/yulSyntaxTests/eof/eof_opcodes_identifiers_reserved_in_eof.yul +++ b/test/libyul/yulSyntaxTests/eof/eof_opcodes_identifiers_reserved_in_eof.yul @@ -5,6 +5,8 @@ function callf() {} function jumpf() {} function retf() {} + function swapn() {} + function dupn() {} } // ==== // bytecodeFormat: >=EOFv1 @@ -15,3 +17,5 @@ // DeclarationError 5017: (83-102): The identifier "callf" is reserved and can not be used. // DeclarationError 5017: (107-126): The identifier "jumpf" is reserved and can not be used. // DeclarationError 5017: (131-149): The identifier "retf" is reserved and can not be used. +// DeclarationError 5017: (154-173): The identifier "swapn" is reserved and can not be used. +// DeclarationError 5017: (178-196): The identifier "dupn" is reserved and can not be used. diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index 94a6c3b1e..31c2ccc97 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -486,6 +486,8 @@ u256 EVMInstructionInterpreter::eval( case Instruction::SWAP14: case Instruction::SWAP15: case Instruction::SWAP16: + case Instruction::SWAPN: + case Instruction::DUPN: yulAssert(false, "Impossible in strict assembly."); case Instruction::DATALOADN: case Instruction::CALLF: From 091dde6f483cd61d23945a783ca64f1c9615e77e Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 14 Feb 2025 12:51:41 +0100 Subject: [PATCH 0717/1340] ConstantEvaluator: Add `tryEvaluate` method that swallows errors --- libsolidity/analysis/ConstantEvaluator.cpp | 14 ++++++++++++++ libsolidity/analysis/ConstantEvaluator.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 8e18183a8..0d953be93 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -269,6 +269,20 @@ std::optional ConstantEvaluator::evaluate( return ConstantEvaluator{_errorReporter}.evaluate(_expr); } +std::optional ConstantEvaluator::tryEvaluate(Expression const& _expr) +{ + ErrorList errorList; + ErrorReporter errorReporter(errorList); + try + { + return ConstantEvaluator{errorReporter}.evaluate(_expr); + } + catch (FatalError const&) + { + return std::nullopt; + } +} + std::optional ConstantEvaluator::evaluate(ASTNode const& _node) { diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index 5b4b34604..297d5f6e8 100644 --- a/libsolidity/analysis/ConstantEvaluator.h +++ b/libsolidity/analysis/ConstantEvaluator.h @@ -57,6 +57,10 @@ class ConstantEvaluator: private ASTConstVisitor Expression const& _expr ); + /// Works the same as `evaluate` but swallows any errors that might occur in the evaluation and simply returns + /// `std::nullopt` instead. + static std::optional tryEvaluate(Expression const& _expr); + /// Performs arbitrary-precision evaluation of a binary operator. Returns nullopt on cases like /// division by zero or e.g. bit operators applied to fractional values. static std::optional evaluateBinaryOperator(Token _operator, rational const& _left, rational const& _right); From de36f55772a1bda6bf6e5523053a4f5e1006cc72 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 14 Feb 2025 12:54:38 +0100 Subject: [PATCH 0718/1340] SMTChecker: Ignore errors that might occur during constant evaluation Previously, if a fatal error would occur during constant evaluation in the model checker, it would throw an exception which the model checker would let escape and crash the compiler. We now use the new API that swallows any errors and the model checker can continue, simply treating the expression as not constant. --- Changelog.md | 1 + libsolidity/formal/SMTEncoder.cpp | 9 ++------- .../operators/constant_evaluation_add.sol | 11 +++++++++++ .../operators/constant_evaluation_bitwise_not.sol | 9 +++++++++ .../operators/constant_evaluation_sub.sol | 11 +++++++++++ 5 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/operators/constant_evaluation_add.sol create mode 100644 test/libsolidity/smtCheckerTests/operators/constant_evaluation_bitwise_not.sol create mode 100644 test/libsolidity/smtCheckerTests/operators/constant_evaluation_sub.sol diff --git a/Changelog.md b/Changelog.md index f6fc05636..731f8d579 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ Compiler Features: Bugfixes: * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. + * SMTChecker: Fix internal compiler error when analyzing overflowing expressions or bitwise negation of unsigned types involving constants. * SMTChecker: Fix reporting on targets that are safe in the context of one contract but unsafe in the context of another contract. * SMTChecker: Fix SMT logic error when analyzing cross-contract getter call with BMC. * SMTChecker: Fix SMT logic error when contract deployment involves string literal to fixed bytes conversion. diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 7c826ab36..a0b71f594 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -3124,13 +3124,8 @@ RationalNumberType const* SMTEncoder::isConstant(Expression const& _expr) if (auto type = dynamic_cast(_expr.annotation().type)) return type; - // _expr may not be constant evaluable. - // In that case we ignore any warnings emitted by the constant evaluator, - // as it will return nullptr in case of failure. - ErrorList l; - ErrorReporter e(l); - if (auto t = ConstantEvaluator::evaluate(e, _expr)) - return TypeProvider::rationalNumber(t->value); + if (auto typedRational = ConstantEvaluator::tryEvaluate(_expr)) + return TypeProvider::rationalNumber(typedRational->value); return nullptr; } diff --git a/test/libsolidity/smtCheckerTests/operators/constant_evaluation_add.sol b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_add.sol new file mode 100644 index 000000000..b174b9478 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_add.sol @@ -0,0 +1,11 @@ +contract C { + uint8 constant N = 255; + + function f() public pure returns (uint8) { + return N + 1; + } +} +// ==== +// SMTEngine: chc +// ---- +// Warning 4984: (104-109): CHC: Overflow (resulting value larger than 255) happens here.\nCounterexample:\nN = 255\n = 0\n\nTransaction trace:\nC.constructor()\nState: N = 255\nC.f() diff --git a/test/libsolidity/smtCheckerTests/operators/constant_evaluation_bitwise_not.sol b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_bitwise_not.sol new file mode 100644 index 000000000..54159b180 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_bitwise_not.sol @@ -0,0 +1,9 @@ +contract C { + uint256 constant largeConstant = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + function test() public pure returns (uint256) { + return ~largeConstant; + } +} +// ==== +// SMTEngine: chc +// ---- diff --git a/test/libsolidity/smtCheckerTests/operators/constant_evaluation_sub.sol b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_sub.sol new file mode 100644 index 000000000..39a9b7cac --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_sub.sol @@ -0,0 +1,11 @@ +contract C { + uint256 public constant B = 1; + + function f() public pure returns (uint256) { + return B - 112; + } +} +// ==== +// SMTEngine: chc +// ---- +// Warning 3944: (113-120): CHC: Underflow (resulting value less than 0) happens here.\nCounterexample:\nB = 1\n = 0\n\nTransaction trace:\nC.constructor()\nState: B = 1\nC.f() From d51fda0d8c3af20987a4f8f0ff7f8560c26f2f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 31 Jan 2025 18:01:48 +0100 Subject: [PATCH 0719/1340] installing-solidity.rst: Remove redundant example of usage via docker --- docs/installing-solidity.rst | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 129d1d3a8..912c501dc 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -83,17 +83,11 @@ and runs it in a new container, passing the ``--help`` argument. docker run ethereum/solc:stable --help -You can specify release build versions in the tag. For example: - -.. code-block:: bash - - docker run ethereum/solc:stable --help - -Note +.. note:: -Specific compiler versions are supported as the Docker image tag such as `ethereum/solc:0.8.23`. We will be passing the -`stable` tag here instead of specific version tag to ensure that users get the latest version by default and avoid the issue of -an out-of-date version. + Specific compiler versions are supported as the Docker image tag such as `ethereum/solc:0.8.23`. + We will be passing the `stable` tag here instead of specific version tag to ensure that users get + the latest version by default and avoid the issue of an out-of-date version. To use the Docker image to compile Solidity files on the host machine, mount a local folder for input and output, and specify the contract to compile. For example: From d23bfb63a593db486db366b0818bec899e8cbdfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 31 Jan 2025 18:17:08 +0100 Subject: [PATCH 0720/1340] installing-solidity.rst: Fix single backticks --- docs/installing-solidity.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 912c501dc..261c07266 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -47,15 +47,15 @@ npm / Node.js ============= Use ``npm`` for a convenient and portable way to install ``solcjs``, a Solidity compiler. The -`solcjs` program has fewer features than the ways to access the compiler described +``solcjs`` program has fewer features than the ways to access the compiler described further down this page. The :ref:`commandline-compiler` documentation assumes you are using the full-featured compiler, ``solc``. The usage of ``solcjs`` is documented inside its own `repository `_. Note: The solc-js project is derived from the C++ -`solc` by using Emscripten, which means that both use the same compiler source code. -`solc-js` can be used in JavaScript projects directly (such as Remix). +``solc`` by using Emscripten, which means that both use the same compiler source code. +``solc-js`` can be used in JavaScript projects directly (such as Remix). Please refer to the solc-js repository for instructions. .. code-block:: bash @@ -85,8 +85,8 @@ and runs it in a new container, passing the ``--help`` argument. .. note:: - Specific compiler versions are supported as the Docker image tag such as `ethereum/solc:0.8.23`. - We will be passing the `stable` tag here instead of specific version tag to ensure that users get + Specific compiler versions are supported as the Docker image tag such as ``ethereum/solc:0.8.23``. + We will be passing the ``stable`` tag here instead of specific version tag to ensure that users get the latest version by default and avoid the issue of an out-of-date version. To use the Docker image to compile Solidity files on the host machine, mount a @@ -212,7 +212,7 @@ out-of-the-box but it is also meant to be friendly to third-party tools: - The content is mirrored to https://binaries.soliditylang.org where it can be easily downloaded over HTTPS without any authentication, rate limiting or the need to use git. -- Content is served with correct `Content-Type` headers and lenient CORS configuration so that it +- Content is served with correct ``Content-Type`` headers and lenient CORS configuration so that it can be directly loaded by tools running in the browser. - Binaries do not require installation or unpacking (exception for older Windows builds bundled with necessary DLLs). From 19002a8f4cb08202334be60b8e4d939e262a86ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 31 Jan 2025 18:18:23 +0100 Subject: [PATCH 0721/1340] installing-solidity.rst: Use full option names and tweak example commands - Also put example paths in /tmp to avoid new root dirs being created if the example is used verbatim --- docs/installing-solidity.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 261c07266..07d82b9c8 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -60,7 +60,7 @@ Please refer to the solc-js repository for instructions. .. code-block:: bash - npm install -g solc + npm install --global solc .. note:: @@ -94,7 +94,13 @@ local folder for input and output, and specify the contract to compile. For exam .. code-block:: bash - docker run -v /local/path:/sources ethereum/solc:stable -o /sources/output --abi --bin /sources/Contract.sol + docker run \ + --volume "/tmp/some/local/path/:/sources/" \ + ethereum/solc:stable \ + /sources/Contract.sol \ + --abi \ + --bin \ + --output-dir /sources/output/ You can also use the standard JSON interface (which is recommended when using the compiler with tooling). When using this interface, it is not necessary to mount any directories as long as the JSON input is From 46006c82fdd9fca8c5ac05200cd73a2d1a526975 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 13 Feb 2025 10:13:12 +0100 Subject: [PATCH 0722/1340] Default comparison operators for frontend optimiser settings --- Changelog.md | 1 + libsolidity/interface/OptimiserSettings.h | 23 ++--------------------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/Changelog.md b/Changelog.md index 731f8d579..00b7df77b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ Compiler Features: Bugfixes: * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. + * Metadata: Fix custom cleanup sequence missing from metadata when other optimizer settings have default values. * SMTChecker: Fix internal compiler error when analyzing overflowing expressions or bitwise negation of unsigned types involving constants. * SMTChecker: Fix reporting on targets that are safe in the context of one contract but unsafe in the context of another contract. * SMTChecker: Fix SMT logic error when analyzing cross-contract getter call with BMC. diff --git a/libsolidity/interface/OptimiserSettings.h b/libsolidity/interface/OptimiserSettings.h index 1f702851c..d282e139d 100644 --- a/libsolidity/interface/OptimiserSettings.h +++ b/libsolidity/interface/OptimiserSettings.h @@ -111,27 +111,8 @@ struct OptimiserSettings util::unreachable(); } - bool operator==(OptimiserSettings const& _other) const - { - return - runOrderLiterals == _other.runOrderLiterals && - runInliner == _other.runInliner && - runJumpdestRemover == _other.runJumpdestRemover && - runPeephole == _other.runPeephole && - runDeduplicate == _other.runDeduplicate && - runCSE == _other.runCSE && - runConstantOptimiser == _other.runConstantOptimiser && - simpleCounterForLoopUncheckedIncrement == _other.simpleCounterForLoopUncheckedIncrement && - optimizeStackAllocation == _other.optimizeStackAllocation && - runYulOptimiser == _other.runYulOptimiser && - yulOptimiserSteps == _other.yulOptimiserSteps && - expectedExecutionsPerDeployment == _other.expectedExecutionsPerDeployment; - } - - bool operator!=(OptimiserSettings const& _other) const - { - return !(*this == _other); - } + bool operator==(OptimiserSettings const& _other) const = default; + bool operator!=(OptimiserSettings const& _other) const = default; /// Move literals to the right of commutative binary operators during code generation. /// This helps exploiting associativity. From cc164838ab46d7af32af90984007053aa6e8da9a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 13 Feb 2025 15:11:46 +0100 Subject: [PATCH 0723/1340] Add test that has a custom cleanup sequence but otherwise default optimizer settings --- test/libsolidity/Metadata.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index e6cdef036..da3822dcd 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -458,16 +458,27 @@ BOOST_AUTO_TEST_CASE(metadata_optimiser_sequence) {"dhfoDgvulfnTUtnIf", "fDn"} }; - auto check = [sourceCode](std::string const& _optimizerSequence, std::string const& _optimizerCleanupSequence) + std::vector settingsToTest; + for (auto const& [optimizerSequence, optimizerCleanupSequence]: sequences) + { + settingsToTest.emplace_back(OptimiserSettings::minimal()); + settingsToTest.back().runYulOptimiser = true; + settingsToTest.back().yulOptimiserSteps = optimizerSequence; + settingsToTest.back().yulOptimiserCleanupSteps = optimizerCleanupSequence; + } + + { + // test that a custom cleanup step sequence does not lead to default standard optimiser settings in metadata + settingsToTest.emplace_back(OptimiserSettings::standard()); + settingsToTest.back().yulOptimiserCleanupSteps = "D"; + } + + auto check = [sourceCode](OptimiserSettings const& _optimizerSettings) { - OptimiserSettings optimizerSettings = OptimiserSettings::minimal(); - optimizerSettings.runYulOptimiser = true; - optimizerSettings.yulOptimiserSteps = _optimizerSequence; - optimizerSettings.yulOptimiserCleanupSteps = _optimizerCleanupSequence; CompilerStack compilerStack; compilerStack.setSources({{"", sourceCode}}); compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); - compilerStack.setOptimiserSettings(optimizerSettings); + compilerStack.setOptimiserSettings(_optimizerSettings); BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); @@ -480,12 +491,12 @@ BOOST_AUTO_TEST_CASE(metadata_optimiser_sequence) BOOST_CHECK(metadata["settings"]["optimizer"]["details"]["yulDetails"].contains("optimizerSteps")); std::string const metadataOptimizerSteps = metadata["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"].get(); - std::string const expectedMetadataOptimiserSteps = _optimizerSequence + ":" + _optimizerCleanupSequence; + std::string const expectedMetadataOptimiserSteps = _optimizerSettings.yulOptimiserSteps + ":" + _optimizerSettings.yulOptimiserCleanupSteps; BOOST_CHECK_EQUAL(metadataOptimizerSteps, expectedMetadataOptimiserSteps); }; - for (auto const& [sequence, cleanupSequence] : sequences) - check(sequence, cleanupSequence); + for (auto const& optimizerSettings: settingsToTest) + check(optimizerSettings); } BOOST_AUTO_TEST_CASE(metadata_license_missing) From 85fe2a007ea2bf7887cf348623060b4d83cc4f13 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 20 Feb 2025 13:42:03 +0100 Subject: [PATCH 0724/1340] Use buildx in docker deploy manual --- scripts/docker_deploy_manual.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index 8753d59c9..1386bcfa1 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -47,13 +47,13 @@ function tag_and_push } rm -rf .git -docker build -t "$image":build -f scripts/Dockerfile . --progress plain +docker buildx build -t "$image":build -f scripts/Dockerfile . --progress=plain tmp_container=$(docker create "$image":build sh) # Alpine image mkdir -p upload docker cp "${tmp_container}":/usr/bin/solc upload/solc-static-linux -docker build -t "$image":build-alpine -f scripts/Dockerfile_alpine . --progress plain +docker buildx build -t "$image":build-alpine -f scripts/Dockerfile_alpine . --progress=plain if [ "$branch" = "develop" ] then From df96847da35d3ddfefd02054826d917b838605f1 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 18 Feb 2025 09:08:17 +0100 Subject: [PATCH 0725/1340] Expands metadata test coverage to more presets and non-default sequence with default cleanup --- test/libsolidity/Metadata.cpp | 60 ++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index da3822dcd..3b7d101d5 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -443,7 +443,7 @@ BOOST_AUTO_TEST_CASE(metadata_revert_strings) BOOST_AUTO_TEST_CASE(metadata_optimiser_sequence) { - char const* sourceCode = R"( + std::string const sourceCode = R"( pragma solidity >=0.0; contract C { } @@ -455,28 +455,34 @@ BOOST_AUTO_TEST_CASE(metadata_optimiser_sequence) {"", ""}, {"", "fDn"}, {"dhfoDgvulfnTUtnIf", "" }, - {"dhfoDgvulfnTUtnIf", "fDn"} + {"dhfoDgvulfnTUtnIf", "fDn"}, + // test that a custom cleanup step sequence does not lead to default standard optimiser settings in metadata + {OptimiserSettings::DefaultYulOptimiserSteps, "D"}, + // test that a custom optimizer sequence does not lead to default standard optimiser settings in metadata + {"dhfoDgvulfnTUtnIf", OptimiserSettings::DefaultYulOptimiserCleanupSteps} }; std::vector settingsToTest; for (auto const& [optimizerSequence, optimizerCleanupSequence]: sequences) { - settingsToTest.emplace_back(OptimiserSettings::minimal()); - settingsToTest.back().runYulOptimiser = true; - settingsToTest.back().yulOptimiserSteps = optimizerSequence; - settingsToTest.back().yulOptimiserCleanupSteps = optimizerCleanupSequence; - } - - { - // test that a custom cleanup step sequence does not lead to default standard optimiser settings in metadata - settingsToTest.emplace_back(OptimiserSettings::standard()); - settingsToTest.back().yulOptimiserCleanupSteps = "D"; + for (auto const& preset: { + OptimiserSettings::none(), + OptimiserSettings::minimal(), + OptimiserSettings::standard(), + OptimiserSettings::full(), + }) + { + settingsToTest.emplace_back(preset); + settingsToTest.back().runYulOptimiser = true; + settingsToTest.back().yulOptimiserSteps = optimizerSequence; + settingsToTest.back().yulOptimiserCleanupSteps = optimizerCleanupSequence; + } } - auto check = [sourceCode](OptimiserSettings const& _optimizerSettings) + auto generateMetadataJson = [](std::string const& _source, OptimiserSettings const& _optimizerSettings) -> Json { CompilerStack compilerStack; - compilerStack.setSources({{"", sourceCode}}); + compilerStack.setSources({{"", _source}}); compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); compilerStack.setOptimiserSettings(_optimizerSettings); @@ -486,17 +492,33 @@ BOOST_AUTO_TEST_CASE(metadata_optimiser_sequence) Json metadata; BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata)); BOOST_CHECK(solidity::test::isValidMetadata(metadata)); - BOOST_CHECK(metadata["settings"]["optimizer"].contains("details")); - BOOST_CHECK(metadata["settings"]["optimizer"]["details"].contains("yulDetails")); - BOOST_CHECK(metadata["settings"]["optimizer"]["details"]["yulDetails"].contains("optimizerSteps")); + return metadata; + }; + + auto checkCustomSettings = [generateMetadataJson, sourceCode](OptimiserSettings const& _optimizerSettings) + { + auto const metadataJson = generateMetadataJson(sourceCode, _optimizerSettings); + BOOST_CHECK(metadataJson["settings"]["optimizer"].contains("details")); + BOOST_CHECK(metadataJson["settings"]["optimizer"]["details"].contains("yulDetails")); + BOOST_CHECK(metadataJson["settings"]["optimizer"]["details"]["yulDetails"].contains("optimizerSteps")); - std::string const metadataOptimizerSteps = metadata["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"].get(); + std::string const metadataOptimizerSteps = metadataJson["settings"]["optimizer"]["details"]["yulDetails"]["optimizerSteps"].get(); std::string const expectedMetadataOptimiserSteps = _optimizerSettings.yulOptimiserSteps + ":" + _optimizerSettings.yulOptimiserCleanupSteps; BOOST_CHECK_EQUAL(metadataOptimizerSteps, expectedMetadataOptimiserSteps); }; for (auto const& optimizerSettings: settingsToTest) - check(optimizerSettings); + checkCustomSettings(optimizerSettings); + + for (auto const& preset: {OptimiserSettings::minimal(), OptimiserSettings::standard(), OptimiserSettings::full()}) + { + auto const metadataJson = generateMetadataJson(sourceCode, preset); + Json expectedOptimizerMetadata = { + {"enabled", preset != OptimiserSettings::minimal()}, + {"runs", preset.expectedExecutionsPerDeployment} + }; + BOOST_CHECK(metadataJson["settings"]["optimizer"] == expectedOptimizerMetadata); + } } BOOST_AUTO_TEST_CASE(metadata_license_missing) From 5c0ba6c25d4e0017ab5d23bd2ed25ad341173821 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 10 Feb 2025 14:33:33 +0100 Subject: [PATCH 0726/1340] Optimize collection of references in dataflow analyzer clearValues Previously, when clearing values in the data flow analyzer, referencing values were gathered by iterating over all variables and checking if they are contained inside any of the gathered references, reflected in a datastructure of form map(variable -> set). Now, it is just checked, if there is any nonempty intersection between the set of variables to clean and the values of the aforementioned map. The check makes use of sets being sorted. In pathological cases like the chains.sol benchmark, this can bring down the compilation time by approx. 50%. No functional changes, overall behavior stays the same. --- libsolutil/CommonData.h | 23 ++++++++++++++++++ libyul/optimiser/DataFlowAnalyzer.cpp | 35 +++++++++++++++------------ libyul/optimiser/DataFlowAnalyzer.h | 7 +++--- libyul/optimiser/Rematerialiser.cpp | 2 +- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index b663ede77..ee3a6eb95 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -551,6 +551,29 @@ void iterateReplacingWindow(std::vector& _vector, F const& _f, std::index_seq } +/// Checks if two collections possess a non-empty intersection. +/// Assumes that both inputs are sorted in ascending order. +template +requires ( + std::forward_iterator> && + std::forward_iterator> +) +bool hasNonemptyIntersectionSorted(Collection1 const& _collection1, Collection2 const& _collection2) +{ + auto it1 = std::ranges::begin(_collection1); + auto it2 = std::ranges::begin(_collection2); + while (it1 != std::ranges::end(_collection1) && it2 != std::ranges::end(_collection2)) + { + if (*it1 == *it2) + return true; + if (*it1 < *it2) + ++it1; + else + ++it2; + } + return false; +} + /// Function that iterates over the vector @param _vector, /// calling the function @param _f on sequences of @tparam N of its /// elements. If @param _f returns a vector, these elements are replaced by diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index b11282bb1..240778135 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -263,9 +263,10 @@ void DataFlowAnalyzer::handleAssignment(std::set const& _variables, Exp } auto const& referencedVariables = movableChecker.referencedVariables(); + std::vector const referencedVariablesSorted(referencedVariables.begin(), referencedVariables.end()); for (auto const& name: _variables) { - m_state.references[name] = referencedVariables; + m_state.sortedReferences[name] = referencedVariablesSorted; if (!_isDeclaration) { // assignment to slot denoted by "name" @@ -310,12 +311,12 @@ void DataFlowAnalyzer::popScope() for (auto const& name: m_variableScopes.back().variables) { m_state.value.erase(name); - m_state.references.erase(name); + m_state.sortedReferences.erase(name); } m_variableScopes.pop_back(); } -void DataFlowAnalyzer::clearValues(std::set _variables) +void DataFlowAnalyzer::clearValues(std::set const& _variablesToClear) { // All variables that reference variables to be cleared also have to be // cleared, but not recursively, since only the value of the original @@ -333,30 +334,32 @@ void DataFlowAnalyzer::clearValues(std::set _variables) // First clear storage knowledge, because we do not have to clear // storage knowledge of variables whose expression has changed, // since the value is still unchanged. - auto eraseCondition = mapTuple([&_variables](auto&& key, auto&& value) { - return _variables.count(key) || _variables.count(value); + auto eraseCondition = mapTuple([&_variablesToClear](auto&& key, auto&& value) { + return _variablesToClear.count(key) || _variablesToClear.count(value); }); std::erase_if(m_state.environment.storage, eraseCondition); std::erase_if(m_state.environment.memory, eraseCondition); - std::erase_if(m_state.environment.keccak, [&_variables](auto&& _item) { + std::erase_if(m_state.environment.keccak, [&_variablesToClear](auto&& _item) { return - _variables.count(_item.first.first) || - _variables.count(_item.first.second) || - _variables.count(_item.second); + _variablesToClear.count(_item.first.first) || + _variablesToClear.count(_item.first.second) || + _variablesToClear.count(_item.second); }); // Also clear variables that reference variables to be cleared. - std::set referencingVariables; - for (auto const& variableToClear: _variables) - for (auto const& [ref, names]: m_state.references) - if (names.count(variableToClear)) - referencingVariables.emplace(ref); + std::set referencingVariablesToClear; + std::vector const sortedVariablesToClear(_variablesToClear.begin(), _variablesToClear.end()); + for (auto const& [referencingVariable, referencedVariables]: m_state.sortedReferences) + // instead of checking each variable in `referencedVariables`, we check if there is any intersection making use of the + // sortedness of the vectors, which can increase performance by up to 50% in pathological cases + if (hasNonemptyIntersectionSorted(referencedVariables, sortedVariablesToClear)) + referencingVariablesToClear.emplace(referencingVariable); // Clear the value and update the reference relation. - for (auto const& name: _variables + referencingVariables) + for (auto const& name: _variablesToClear + referencingVariablesToClear) { m_state.value.erase(name); - m_state.references.erase(name); + m_state.sortedReferences.erase(name); } } diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index 5b1cf25ff..7b731a4eb 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -104,7 +104,7 @@ class DataFlowAnalyzer: public ASTModifier /// @returns the current value of the given variable, if known - always movable. AssignedValue const* variableValue(YulName _variable) const { return util::valueOrNullptr(m_state.value, _variable); } - std::set const* references(YulName _variable) const { return util::valueOrNullptr(m_state.references, _variable); } + std::vector const* sortedReferences(YulName _variable) const { return util::valueOrNullptr(m_state.sortedReferences, _variable); } std::map const& allValues() const { return m_state.value; } std::optional storageValue(YulName _key) const; std::optional memoryValue(YulName _key) const; @@ -122,7 +122,7 @@ class DataFlowAnalyzer: public ASTModifier /// Clears information about the values assigned to the given variables, /// for example at points where control flow is merged. - void clearValues(std::set _names); + void clearValues(std::set const& _variablesToClear); virtual void assignValue(YulName _variable, Expression const* _value); @@ -180,7 +180,8 @@ class DataFlowAnalyzer: public ASTModifier /// Current values of variables, always movable. std::map value; /// m_references[a].contains(b) <=> the current expression assigned to a references b - std::unordered_map> references; + /// The mapped vectors _must always_ be sorted + std::unordered_map> sortedReferences; Environment environment; }; diff --git a/libyul/optimiser/Rematerialiser.cpp b/libyul/optimiser/Rematerialiser.cpp index fe33b10a2..bfcd9d8f6 100644 --- a/libyul/optimiser/Rematerialiser.cpp +++ b/libyul/optimiser/Rematerialiser.cpp @@ -71,7 +71,7 @@ void Rematerialiser::visit(Expression& _e) ) { assertThrow(m_referenceCounts[name] > 0, OptimizerException, ""); - auto variableReferences = references(name); + auto variableReferences = sortedReferences(name); if (!variableReferences || ranges::all_of(*variableReferences, [&](auto const& ref) { return inScope(ref); })) { // update reference counts From e844a8bfb26f7d850b1bf783228e298ad7595f0c Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 23 Jan 2025 14:01:11 -0300 Subject: [PATCH 0727/1340] Parse contract layout specification --- Changelog.md | 1 + docs/grammar/SolidityLexer.g4 | 2 + docs/grammar/SolidityParser.g4 | 13 ++- liblangutil/ErrorReporter.cpp | 11 ++ liblangutil/ErrorReporter.h | 1 + libsolidity/analysis/NameAndTypeResolver.cpp | 4 + libsolidity/analysis/TypeChecker.cpp | 3 + libsolidity/ast/AST.cpp | 11 ++ libsolidity/ast/AST.h | 27 ++++- libsolidity/ast/ASTForward.h | 1 + libsolidity/ast/ASTJsonExporter.cpp | 18 ++- libsolidity/ast/ASTJsonExporter.h | 2 + libsolidity/ast/ASTJsonImporter.cpp | 16 ++- libsolidity/ast/ASTJsonImporter.h | 3 +- libsolidity/ast/ASTVisitor.h | 4 + libsolidity/ast/AST_accept.h | 20 ++++ libsolidity/interface/CompilerStack.cpp | 4 +- libsolidity/parsing/Parser.cpp | 76 ++++++++++++- libsolidity/parsing/Parser.h | 2 + .../args | 1 + .../input.sol | 4 + .../output | 103 ++++++++++++++++++ .../args | 1 + .../inheritance_repeated_definition_error/err | 10 ++ .../exit | 1 + .../stdin | 10 ++ .../args | 1 + .../err | 1 + .../exit | 1 + .../stdin | 62 +++++++++++ .../args | 1 + .../err | 5 + .../exit | 1 + .../stdin | 4 + .../args | 1 + .../err | 5 + .../exit | 1 + .../stdin | 4 + .../args | 1 + .../err | 10 ++ .../exit | 1 + .../stdin | 6 + .../args | 1 + .../err | 1 + .../exit | 1 + .../output | 2 + .../stdin | 4 + .../ASTJSON/storage_layout_specifier.json | 88 +++++++++++++++ .../ASTJSON/storage_layout_specifier.sol | 3 + .../functionCalls/empty_call_options.sol | 8 ++ .../duplicated_inheritance_definition.sol | 5 + .../repeated_inheritance_definition.sol | 7 ++ .../abstract_contract.sol | 4 + .../at_before_layout.sol | 3 + .../contract_named_at.sol | 4 + .../contract_named_layout.sol | 4 + ...tract_with_members_named_layout_and_at.sol | 7 ++ .../duplicated_layout_definition.sol | 3 + .../duplicated_layout_keyword.sol | 4 + .../function_declaration_layout_specified.sol | 5 + ..._declaration_layout_with_no_expression.sol | 6 + .../storageLayoutSpecifier/interface.sol | 3 + ...layout_specification_binary_expression.sol | 4 + .../layout_specification_by_function.sol | 7 ++ ...t_specification_constant_in_expression.sol | 5 + .../layout_specification_no_expression.sol | 3 + .../layout_specified_by_empty_braces.sol | 3 + ...ecified_by_function_empty_call_options.sol | 6 + ...pecified_by_function_with_call_options.sol | 7 ++ .../layout_statement_without_at.sol | 4 + .../layout_with_inheritance.sol | 7 ++ .../storageLayoutSpecifier/library.sol | 3 + .../multi_token_expression.sol | 5 + .../storageLayoutSpecifier/natspec.sol | 10 ++ .../repeated_layout_definition.sol | 5 + .../storageLayoutSpecifier/simple_layout.sol | 6 + .../state_variable_layout_specifier.sol | 5 + .../struct_layout_specifier.sol | 3 + 78 files changed, 684 insertions(+), 16 deletions(-) create mode 100644 test/cmdlineTests/ast_compact_json_storage_layout_specifier/args create mode 100644 test/cmdlineTests/ast_compact_json_storage_layout_specifier/input.sol create mode 100644 test/cmdlineTests/ast_compact_json_storage_layout_specifier/output create mode 100644 test/cmdlineTests/inheritance_repeated_definition_error/args create mode 100644 test/cmdlineTests/inheritance_repeated_definition_error/err create mode 100644 test/cmdlineTests/inheritance_repeated_definition_error/exit create mode 100644 test/cmdlineTests/inheritance_repeated_definition_error/stdin create mode 100644 test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/args create mode 100644 test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/err create mode 100644 test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/exit create mode 100644 test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/stdin create mode 100644 test/cmdlineTests/storage_layout_specifier_codegen_error/args create mode 100644 test/cmdlineTests/storage_layout_specifier_codegen_error/err create mode 100644 test/cmdlineTests/storage_layout_specifier_codegen_error/exit create mode 100644 test/cmdlineTests/storage_layout_specifier_codegen_error/stdin create mode 100644 test/cmdlineTests/storage_layout_specifier_ir_codegen_error/args create mode 100644 test/cmdlineTests/storage_layout_specifier_ir_codegen_error/err create mode 100644 test/cmdlineTests/storage_layout_specifier_ir_codegen_error/exit create mode 100644 test/cmdlineTests/storage_layout_specifier_ir_codegen_error/stdin create mode 100644 test/cmdlineTests/storage_layout_specifier_repeated_definition_error/args create mode 100644 test/cmdlineTests/storage_layout_specifier_repeated_definition_error/err create mode 100644 test/cmdlineTests/storage_layout_specifier_repeated_definition_error/exit create mode 100644 test/cmdlineTests/storage_layout_specifier_repeated_definition_error/stdin create mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/args create mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/err create mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/exit create mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/output create mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/stdin create mode 100644 test/libsolidity/ASTJSON/storage_layout_specifier.json create mode 100644 test/libsolidity/ASTJSON/storage_layout_specifier.sol create mode 100644 test/libsolidity/syntaxTests/functionCalls/empty_call_options.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/duplicated_inheritance_definition.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/repeated_inheritance_definition.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/at_before_layout.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_definition.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_keyword.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_specified.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_with_no_expression.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/interface.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_no_expression.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_empty_braces.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_empty_call_options.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_statement_without_at.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/library.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/natspec.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/repeated_layout_definition.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_layout_specifier.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_layout_specifier.sol diff --git a/Changelog.md b/Changelog.md index 00b7df77b..3eb3abf79 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.8.29 (unreleased) Language Features: + * Introduce syntax for specifying contract storage layout base. Compiler Features: diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index f994c331d..ad3b04098 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -14,6 +14,7 @@ Address: 'address'; Anonymous: 'anonymous'; As: 'as'; Assembly: 'assembly' -> pushMode(AssemblyBlockMode); +At: 'at'; // not a real keyword Bool: 'bool'; Break: 'break'; Bytes: 'bytes'; @@ -54,6 +55,7 @@ Indexed: 'indexed'; Interface: 'interface'; Internal: 'internal'; Is: 'is'; +Layout: 'layout'; // not a real keyword Library: 'library'; Mapping: 'mapping'; Memory: 'memory'; diff --git a/docs/grammar/SolidityParser.g4 b/docs/grammar/SolidityParser.g4 index a344fad54..5ad422913 100644 --- a/docs/grammar/SolidityParser.g4 +++ b/docs/grammar/SolidityParser.g4 @@ -52,9 +52,14 @@ symbolAliases: LBrace aliases+=importAliases (Comma aliases+=importAliases)* RBr /** * Top-level definition of a contract. */ -contractDefinition: +contractDefinition +locals [boolean layoutSet=false, boolean inheritanceSet=false] +: Abstract? Contract name=identifier - inheritanceSpecifierList? + ( + {!$layoutSet}? Layout At expression {$layoutSet = true;} + | {!$inheritanceSet}? inheritanceSpecifierList {$inheritanceSet = true;} + )* LBrace contractBodyElement* RBrace; /** * Top-level definition of an interface. @@ -379,7 +384,7 @@ expression: expression LBrack index=expression? RBrack # IndexAccess | expression LBrack startIndex=expression? Colon endIndex=expression? RBrack # IndexRangeAccess | expression Period (identifier | Address) # MemberAccess - | expression LBrace (namedArgument (Comma namedArgument)*)? RBrace # FunctionCallOptions + | expression LBrace (namedArgument (Comma namedArgument)*) RBrace # FunctionCallOptions | expression callArgumentList # FunctionCall | Payable callArgumentList # PayableConversion | Type LParen typeName RParen # MetaType @@ -420,7 +425,7 @@ inlineArrayExpression: LBrack (expression ( Comma expression)* ) RBrack; /** * Besides regular non-keyword Identifiers, some keywords like 'from' and 'error' can also be used as identifiers. */ -identifier: Identifier | From | Error | Revert | Global | Transient; +identifier: Identifier | From | Error | Revert | Global | Transient | Layout | At; literal: stringLiteral | numberLiteral | booleanLiteral | hexStringLiteral | unicodeStringLiteral; diff --git a/liblangutil/ErrorReporter.cpp b/liblangutil/ErrorReporter.cpp index 8c8bb7ab0..10d7f1d11 100644 --- a/liblangutil/ErrorReporter.cpp +++ b/liblangutil/ErrorReporter.cpp @@ -190,6 +190,17 @@ void ErrorReporter::parserError(ErrorId _error, SourceLocation const& _location, ); } +void ErrorReporter::parserError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description) +{ + error( + _error, + Error::Type::ParserError, + _location, + _secondaryLocation, + _description + ); +} + void ErrorReporter::fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description) { fatalError( diff --git a/liblangutil/ErrorReporter.h b/liblangutil/ErrorReporter.h index 55e4d5621..dc359c1b0 100644 --- a/liblangutil/ErrorReporter.h +++ b/liblangutil/ErrorReporter.h @@ -87,6 +87,7 @@ class ErrorReporter void fatalDeclarationError(ErrorId _error, SourceLocation const& _location, std::string const& _description); void parserError(ErrorId _error, SourceLocation const& _location, std::string const& _description); + void parserError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description); void fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description); diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 766f1bf12..2fb6a6162 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -299,6 +299,10 @@ bool NameAndTypeResolver::resolveNamesAndTypesInternal(ASTNode& _node, bool _res if (!resolveNamesAndTypesInternal(*baseContract, true)) success = false; + if (StorageLayoutSpecifier* storageLayoutSpecifier = contract->storageLayoutSpecifier()) + if (!resolveNamesAndTypesInternal(*storageLayoutSpecifier, true)) + success = false; + setScope(contract); if (success) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index b461fa283..a0d21744d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -86,6 +86,9 @@ bool TypeChecker::visit(ContractDefinition const& _contract) ASTNode::listAccept(_contract.baseContracts(), *this); + if (StorageLayoutSpecifier const* layoutSpecifier = _contract.storageLayoutSpecifier()) + layoutSpecifier->accept(*this); + for (auto const& n: _contract.subNodes()) n->accept(*this); diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index b62ea3e2d..cf3bddf40 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -371,6 +371,17 @@ std::multimap const& ContractDefinition: }); } +StorageLayoutSpecifier::StorageLayoutSpecifier( + int64_t _id, + SourceLocation const& _location, + ASTPointer _baseSlotExpression +): + ASTNode(_id, _location), + m_baseSlotExpression(_baseSlotExpression) +{ + solAssert(m_baseSlotExpression); + solAssert(_location.contains(m_baseSlotExpression->location())); +} TypeNameAnnotation& TypeName::annotation() const { diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 5cf488007..cc5cc9324 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -509,14 +509,16 @@ class ContractDefinition: public Declaration, public StructurallyDocumented, pub std::vector> _baseContracts, std::vector> _subNodes, ContractKind _contractKind = ContractKind::Contract, - bool _abstract = false + bool _abstract = false, + ASTPointer _storageLayoutSpecifier = nullptr ): Declaration(_id, _location, _name, std::move(_nameLocation)), StructurallyDocumented(_documentation), m_baseContracts(std::move(_baseContracts)), m_subNodes(std::move(_subNodes)), m_contractKind(_contractKind), - m_abstract(_abstract) + m_abstract(_abstract), + m_storageLayoutSpecifier(_storageLayoutSpecifier) {} void accept(ASTVisitor& _visitor) override; @@ -586,6 +588,9 @@ class ContractDefinition: public Declaration, public StructurallyDocumented, pub bool abstract() const { return m_abstract; } + StorageLayoutSpecifier const* storageLayoutSpecifier() const { return m_storageLayoutSpecifier.get(); } + StorageLayoutSpecifier* storageLayoutSpecifier() { return m_storageLayoutSpecifier.get(); } + ContractDefinition const* superContract(ContractDefinition const& _mostDerivedContract) const; /// @returns the next constructor in the inheritance hierarchy. FunctionDefinition const* nextConstructor(ContractDefinition const& _mostDerivedContract) const; @@ -597,12 +602,30 @@ class ContractDefinition: public Declaration, public StructurallyDocumented, pub std::vector> m_subNodes; ContractKind m_contractKind; bool m_abstract{false}; + ASTPointer m_storageLayoutSpecifier; util::LazyInit, FunctionTypePointer>>> m_interfaceFunctionList[2]; util::LazyInit> m_interfaceEvents; util::LazyInit> m_definedFunctionsByName; }; + +class StorageLayoutSpecifier : public ASTNode +{ +public: + StorageLayoutSpecifier( + int64_t _id, + SourceLocation const& _location, + ASTPointer _baseSlotExpression + ); + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; + + Expression const& baseSlotExpression() const { solAssert(m_baseSlotExpression); return *m_baseSlotExpression; } +private: + ASTPointer m_baseSlotExpression; +}; + /** * A sequence of identifiers separated by dots used outside the expression context. Inside the expression context, this is a sequence of Identifier and MemberAccess. */ diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h index b8a3a4ae0..d0fe7d97a 100644 --- a/libsolidity/ast/ASTForward.h +++ b/libsolidity/ast/ASTForward.h @@ -98,6 +98,7 @@ class Identifier; class ElementaryTypeNameExpression; class Literal; class StructuredDocumentation; +class StorageLayoutSpecifier; /// Experimental Solidity nodes /// @{ diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 4e7a5cd50..42627b5f7 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -210,6 +210,13 @@ Json ASTJsonExporter::toJson(ASTNode const& _node) return util::removeNullMembers(std::move(m_currentValue)); } +Json ASTJsonExporter::toJson(ASTNode const* _node) +{ + if (!_node) + return Json(); + return toJson(*_node); +} + bool ASTJsonExporter::visit(SourceUnit const& _node) { std::vector> attributes = { @@ -279,6 +286,14 @@ bool ASTJsonExporter::visit(ImportDirective const& _node) return false; } +bool ASTJsonExporter::visit(StorageLayoutSpecifier const& _node) +{ + setJsonNode(_node, "StorageLayoutSpecifier", { + {"baseSlotExpression", toJson(_node.baseSlotExpression())} + }); + return false; +} + bool ASTJsonExporter::visit(ContractDefinition const& _node) { std::vector> attributes = { @@ -293,7 +308,8 @@ bool ASTJsonExporter::visit(ContractDefinition const& _node) std::make_pair("usedEvents", getContainerIds(_node.interfaceEvents(false))), std::make_pair("usedErrors", getContainerIds(_node.interfaceErrors(false))), std::make_pair("nodes", toJson(_node.subNodes())), - std::make_pair("scope", idOrNull(_node.scope())) + std::make_pair("scope", idOrNull(_node.scope())), + std::make_pair("storageLayout", toJson(_node.storageLayoutSpecifier())) }; addIfSet(attributes, "canonicalName", _node.annotation().canonicalName); diff --git a/libsolidity/ast/ASTJsonExporter.h b/libsolidity/ast/ASTJsonExporter.h index c7933120a..3174dc186 100644 --- a/libsolidity/ast/ASTJsonExporter.h +++ b/libsolidity/ast/ASTJsonExporter.h @@ -60,6 +60,7 @@ class ASTJsonExporter: public ASTConstVisitor /// Output the json representation of the AST to _stream. void print(std::ostream& _stream, ASTNode const& _node, util::JsonFormat const& _format); Json toJson(ASTNode const& _node); + Json toJson(ASTNode const* _node); template Json toJson(std::vector> const& _nodes) { @@ -126,6 +127,7 @@ class ASTJsonExporter: public ASTConstVisitor bool visit(ElementaryTypeNameExpression const& _node) override; bool visit(Literal const& _node) override; bool visit(StructuredDocumentation const& _node) override; + bool visit(StorageLayoutSpecifier const& _node) override; void endVisit(EventDefinition const&) override; diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 344bfb39d..d6cd7f438 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -37,6 +37,8 @@ #include #include +#include + namespace solidity::frontend { @@ -255,6 +257,8 @@ ASTPointer ASTJsonImporter::convertJsonToASTNode(Json const& _json) return createLiteral(_json); if (nodeType == "StructuredDocumentation") return createDocumentation(_json); + if (nodeType == "StorageLayoutSpecifier") + return createStorageLayoutSpecifier(_json); else astAssert(false, "Unknown type of ASTNode: " + nodeType); @@ -348,7 +352,17 @@ ASTPointer ASTJsonImporter::createContractDefinition(Json co baseContracts, subNodes, contractKind(_node), - memberAsBool(_node, "abstract") + memberAsBool(_node, "abstract"), + nullOrCast(member(_node, "storageLayout")) + ); +} + +ASTPointer ASTJsonImporter::createStorageLayoutSpecifier(Json const& _node) +{ + astAssert(_node.contains("baseSlotExpression"), "Expected field \"baseSlotExpression\" is missing."); + return createASTNode( + _node, + convertJsonToASTNode(_node["baseSlotExpression"]) ); } diff --git a/libsolidity/ast/ASTJsonImporter.h b/libsolidity/ast/ASTJsonImporter.h index e4a7c2da3..7c5dd5be9 100644 --- a/libsolidity/ast/ASTJsonImporter.h +++ b/libsolidity/ast/ASTJsonImporter.h @@ -131,10 +131,11 @@ class ASTJsonImporter ASTPointer createElementaryTypeNameExpression(Json const& _node); ASTPointer createLiteral(Json const& _node); ASTPointer createDocumentation(Json const& _node); + ASTPointer createStorageLayoutSpecifier(Json const& _node); ///@} // =============== general helper functions =================== - /// @returns the member of a given JSON object, throws if member does not exist + /// @returns the member of a given JSON object or null if member does not exist Json member(Json const& _node, std::string const& _name); /// @returns the appropriate TokenObject used in parsed Strings (pragma directive or operator) Token scanSingleToken(Json const& _node); diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h index f985a4490..010e99ec3 100644 --- a/libsolidity/ast/ASTVisitor.h +++ b/libsolidity/ast/ASTVisitor.h @@ -109,6 +109,7 @@ class ASTVisitor virtual bool visit(ElementaryTypeNameExpression& _node) { return visitNode(_node); } virtual bool visit(Literal& _node) { return visitNode(_node); } virtual bool visit(StructuredDocumentation& _node) { return visitNode(_node); } + virtual bool visit(StorageLayoutSpecifier& _node) { return visitNode(_node); } /// Experimental Solidity nodes /// @{ virtual bool visit(TypeClassDefinition& _node) { return visitNode(_node); } @@ -174,6 +175,7 @@ class ASTVisitor virtual void endVisit(ElementaryTypeNameExpression& _node) { endVisitNode(_node); } virtual void endVisit(Literal& _node) { endVisitNode(_node); } virtual void endVisit(StructuredDocumentation& _node) { endVisitNode(_node); } + virtual void endVisit(StorageLayoutSpecifier& _node) { endVisitNode(_node); } /// Experimental Solidity nodes /// @{ virtual void endVisit(TypeClassDefinition& _node) { endVisitNode(_node); } @@ -261,6 +263,7 @@ class ASTConstVisitor virtual bool visit(ElementaryTypeNameExpression const& _node) { return visitNode(_node); } virtual bool visit(Literal const& _node) { return visitNode(_node); } virtual bool visit(StructuredDocumentation const& _node) { return visitNode(_node); } + virtual bool visit(StorageLayoutSpecifier const& _node) { return visitNode(_node); } /// Experimental Solidity nodes /// @{ virtual bool visit(TypeClassDefinition const& _node) { return visitNode(_node); } @@ -326,6 +329,7 @@ class ASTConstVisitor virtual void endVisit(ElementaryTypeNameExpression const& _node) { endVisitNode(_node); } virtual void endVisit(Literal const& _node) { endVisitNode(_node); } virtual void endVisit(StructuredDocumentation const& _node) { endVisitNode(_node); } + virtual void endVisit(StorageLayoutSpecifier const& _node) { endVisitNode(_node); } /// Experimental Solidity nodes /// @{ virtual void endVisit(TypeClassDefinition const& _node) { endVisitNode(_node); } diff --git a/libsolidity/ast/AST_accept.h b/libsolidity/ast/AST_accept.h index 55ebe2a78..1cd771f9d 100644 --- a/libsolidity/ast/AST_accept.h +++ b/libsolidity/ast/AST_accept.h @@ -93,6 +93,8 @@ void ContractDefinition::accept(ASTVisitor& _visitor) if (m_documentation) m_documentation->accept(_visitor); listAccept(m_baseContracts, _visitor); + if (m_storageLayoutSpecifier) + m_storageLayoutSpecifier->accept(_visitor); listAccept(m_subNodes, _visitor); } _visitor.endVisit(*this); @@ -105,6 +107,8 @@ void ContractDefinition::accept(ASTConstVisitor& _visitor) const if (m_documentation) m_documentation->accept(_visitor); listAccept(m_baseContracts, _visitor); + if (m_storageLayoutSpecifier) + m_storageLayoutSpecifier->accept(_visitor); listAccept(m_subNodes, _visitor); } _visitor.endVisit(*this); @@ -1160,6 +1164,22 @@ void ForAllQuantifier::accept(ASTConstVisitor& _visitor) const } _visitor.endVisit(*this); } + +void StorageLayoutSpecifier::accept(ASTVisitor& _visitor) +{ + if (_visitor.visit(*this)) + m_baseSlotExpression->accept(_visitor); + + _visitor.endVisit(*this); +} + +void StorageLayoutSpecifier::accept(ASTConstVisitor& _visitor) const +{ + if (_visitor.visit(*this)) + m_baseSlotExpression->accept(_visitor); + + _visitor.endVisit(*this); +} /// @} } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 1791ad45a..4e9346ecf 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1104,6 +1104,7 @@ Json const& CompilerStack::storageLayout(Contract const& _contract) const solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); solAssert(_contract.contract); solUnimplementedAssert(!isExperimentalSolidity()); + solUnimplementedAssert(!_contract.contract->storageLayoutSpecifier(), "Storage layout not supported for contract with specified layout base."); return _contract.storageLayout.init([&]{ return StorageLayout().generate(*_contract.contract, DataLocation::Storage); }); } @@ -1523,6 +1524,7 @@ void CompilerStack::compileContract( solAssert(!m_viaIR, ""); solUnimplementedAssert(!m_eofVersion.has_value(), "Experimental EOF support is only available for via-IR compilation."); solAssert(m_stackState >= AnalysisSuccessful, ""); + solUnimplementedAssert(!_contract.storageLayoutSpecifier(), "Code generation is not supported for contracts with specified storage layout base."); if (_otherCompilers.count(&_contract)) return; @@ -1558,7 +1560,7 @@ void CompilerStack::compileContract( void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unoptimizedOnly) { solAssert(m_stackState >= AnalysisSuccessful, ""); - + solUnimplementedAssert(!_contract.storageLayoutSpecifier(), "Code generation is not supported for contracts with specified storage layout base."); Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName()); if (compiledContract.yulIR) { diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 13303170d..dce729de4 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -370,6 +370,31 @@ std::pair Parser::parseContractKind() return std::make_pair(kind, abstract); } +ASTPointer Parser::parseStorageLayoutSpecifier() +{ + RecursionGuard recursionGuard(*this); + ASTNodeFactory nodeFactory(*this); + ASTPointer layoutIdentifier = expectIdentifierToken(); + solAssert(layoutIdentifier && *layoutIdentifier == "layout"); + if ( + m_scanner->currentToken() != Token::Identifier || + m_scanner->currentLiteral() != "at" + ) + m_errorReporter.parserError( + 1994_error, + m_scanner->currentLocation(), + "Expected \'at\' but got " + tokenName(m_scanner->currentToken()) + ); + + advance(); + ASTPointer baseSlotExpression = parseExpression(); + solAssert(baseSlotExpression); + nodeFactory.setEndPositionFromNode(baseSlotExpression); + return nodeFactory.createNode( + baseSlotExpression + ); +} + ASTPointer Parser::parseContractDefinition() { RecursionGuard recursionGuard(*this); @@ -380,16 +405,54 @@ ASTPointer Parser::parseContractDefinition() std::vector> baseContracts; std::vector> subNodes; std::pair contractKind{}; + ASTPointer storageLayoutSpecifier; documentation = parseStructuredDocumentation(); contractKind = parseContractKind(); std::tie(name, nameLocation) = expectIdentifierWithLocation(); - if (m_scanner->currentToken() == Token::Is) - do + while (true) + { + if (m_scanner->currentToken() == Token::Is) { - advance(); - baseContracts.push_back(parseInheritanceSpecifier()); + if (baseContracts.size() != 0) + m_errorReporter.parserError( + 6668_error, + m_scanner->currentLocation(), + SecondarySourceLocation().append("Previous list:", baseContracts[0]->location()), + "More than one inheritance list." + ); + do + { + advance(); + baseContracts.push_back(parseInheritanceSpecifier()); + } + while (m_scanner->currentToken() == Token::Comma); } - while (m_scanner->currentToken() == Token::Comma); + else if ( + m_scanner->currentToken() == Token::Identifier && + m_scanner->currentLiteral() == "layout" && + contractKind.first == ContractKind::Contract + ) + { + if (storageLayoutSpecifier) + m_errorReporter.parserError( + 8714_error, + m_scanner->currentLocation(), + SecondarySourceLocation().append("Previous definition:", storageLayoutSpecifier->location()), + "More than one storage layout definition." + ); + + storageLayoutSpecifier = parseStorageLayoutSpecifier(); + } + else + break; + } + + if (storageLayoutSpecifier && baseContracts.size() > 0) + { + solAssert(!storageLayoutSpecifier->location().intersects(baseContracts[0]->location())); + solAssert(!baseContracts[0]->location().intersects(storageLayoutSpecifier->location())); + } + expectToken(Token::LBrace); while (true) { @@ -443,7 +506,8 @@ ASTPointer Parser::parseContractDefinition() baseContracts, subNodes, contractKind.first, - contractKind.second + contractKind.second, + storageLayoutSpecifier ); } diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 830df05c2..d208c1f8b 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -171,6 +171,8 @@ class Parser: public langutil::ParserBase FunctionCallArguments parseFunctionCallArguments(); FunctionCallArguments parseNamedArguments(); std::pair, langutil::SourceLocation> expectIdentifierWithLocation(); + + ASTPointer parseStorageLayoutSpecifier(); ///@} ///@{ diff --git a/test/cmdlineTests/ast_compact_json_storage_layout_specifier/args b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/args new file mode 100644 index 000000000..76497f217 --- /dev/null +++ b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/args @@ -0,0 +1 @@ +--ast-compact-json --pretty-json --json-indent 4 --allow-paths . diff --git a/test/cmdlineTests/ast_compact_json_storage_layout_specifier/input.sol b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/input.sol new file mode 100644 index 000000000..e6c5250af --- /dev/null +++ b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/input.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C layout at 1234 + 4567 {} diff --git a/test/cmdlineTests/ast_compact_json_storage_layout_specifier/output b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/output new file mode 100644 index 000000000..4fe5fe193 --- /dev/null +++ b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/output @@ -0,0 +1,103 @@ +JSON AST (compact format): + + +======= ast_compact_json_storage_layout_specifier/input.sol ======= +{ + "absolutePath": "ast_compact_json_storage_layout_specifier/input.sol", + "exportedSymbols": { + "C": [ + 6 + ] + }, + "id": 7, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1, + "literals": [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 6, + "linearizedBaseContracts": [ + 6 + ], + "name": "C", + "nameLocation": "69:1:0", + "nodeType": "ContractDefinition", + "nodes": [], + "scope": 7, + "src": "60:35:0", + "storageLayout": { + "baseSlotExpression": { + "commonType": { + "typeIdentifier": "t_rational_5801_by_1", + "typeString": "int_const 5801" + }, + "id": 4, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "leftExpression": { + "hexValue": "31323334", + "id": 2, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "81:4:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_1234_by_1", + "typeString": "int_const 1234" + }, + "value": "1234" + }, + "nodeType": "BinaryOperation", + "operator": "+", + "rightExpression": { + "hexValue": "34353637", + "id": 3, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "88:4:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_4567_by_1", + "typeString": "int_const 4567" + }, + "value": "4567" + }, + "src": "81:11:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_5801_by_1", + "typeString": "int_const 5801" + } + }, + "id": 5, + "nodeType": "StorageLayoutSpecifier", + "src": "71:21:0" + }, + "usedErrors": [], + "usedEvents": [] + } + ], + "src": "36:60:0" +} diff --git a/test/cmdlineTests/inheritance_repeated_definition_error/args b/test/cmdlineTests/inheritance_repeated_definition_error/args new file mode 100644 index 000000000..3cf20d57b --- /dev/null +++ b/test/cmdlineTests/inheritance_repeated_definition_error/args @@ -0,0 +1 @@ +- \ No newline at end of file diff --git a/test/cmdlineTests/inheritance_repeated_definition_error/err b/test/cmdlineTests/inheritance_repeated_definition_error/err new file mode 100644 index 000000000..aa73b10f2 --- /dev/null +++ b/test/cmdlineTests/inheritance_repeated_definition_error/err @@ -0,0 +1,10 @@ +Error: More than one inheritance list. + --> :9:20: + | +9 | contract C is A, B is B { + | ^^ +Note: Previous list: + --> :9:15: + | +9 | contract C is A, B is B { + | ^ diff --git a/test/cmdlineTests/inheritance_repeated_definition_error/exit b/test/cmdlineTests/inheritance_repeated_definition_error/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/inheritance_repeated_definition_error/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/inheritance_repeated_definition_error/stdin b/test/cmdlineTests/inheritance_repeated_definition_error/stdin new file mode 100644 index 000000000..8babcc4f2 --- /dev/null +++ b/test/cmdlineTests/inheritance_repeated_definition_error/stdin @@ -0,0 +1,10 @@ +//SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract A { +} + +contract B { +} + +contract C is A, B is B { +} \ No newline at end of file diff --git a/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/args b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/args new file mode 100644 index 000000000..f0b85640b --- /dev/null +++ b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/args @@ -0,0 +1 @@ +--import-ast - \ No newline at end of file diff --git a/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/err b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/err new file mode 100644 index 000000000..bdb03116e --- /dev/null +++ b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/err @@ -0,0 +1 @@ +Error: Failed to import AST: Expected field "baseSlotExpression" is missing. diff --git a/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/exit b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/stdin b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/stdin new file mode 100644 index 000000000..88bd25df1 --- /dev/null +++ b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/stdin @@ -0,0 +1,62 @@ +{ + "language": "SolidityAST", + "sources": { + "A": { + "AST": { + "absolutePath": "A", + "exportedSymbols": { + "C": [ + 4 + ] + }, + "id": 5, + "license": "GPL-3.0", + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1, + "literals": [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "36:22:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 4, + "linearizedBaseContracts": [ + 4 + ], + "name": "C", + "nameLocation": "69:1:0", + "nodeType": "ContractDefinition", + "nodes": [], + "scope": 5, + "src": "60:28:0", + "storageLayout": { + "id": 3, + "nodeType": "StorageLayoutSpecifier", + "src": "71:16:0" + }, + "usedErrors": [], + "usedEvents": [] + } + ], + "src": "36:53:0" + }, + "id": 0 + } + }, + "settings": { + "outputSelection": { + "*": { "*": [] } + } + } +} \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_codegen_error/args b/test/cmdlineTests/storage_layout_specifier_codegen_error/args new file mode 100644 index 000000000..ccc12f642 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_codegen_error/args @@ -0,0 +1 @@ +--asm - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_codegen_error/err b/test/cmdlineTests/storage_layout_specifier_codegen_error/err new file mode 100644 index 000000000..d1012053f --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_codegen_error/err @@ -0,0 +1,5 @@ +Error: Code generation is not supported for contracts with specified storage layout base. + --> :4:1: + | +4 | contract C layout at 42 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/storage_layout_specifier_codegen_error/exit b/test/cmdlineTests/storage_layout_specifier_codegen_error/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_codegen_error/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/storage_layout_specifier_codegen_error/stdin b/test/cmdlineTests/storage_layout_specifier_codegen_error/stdin new file mode 100644 index 000000000..87066c4d4 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_codegen_error/stdin @@ -0,0 +1,4 @@ +//SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C layout at 42 {} \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/args b/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/args new file mode 100644 index 000000000..a84e2a257 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/args @@ -0,0 +1 @@ +--ir --asm - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/err b/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/err new file mode 100644 index 000000000..d1012053f --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/err @@ -0,0 +1,5 @@ +Error: Code generation is not supported for contracts with specified storage layout base. + --> :4:1: + | +4 | contract C layout at 42 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/exit b/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/stdin b/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/stdin new file mode 100644 index 000000000..87066c4d4 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/stdin @@ -0,0 +1,4 @@ +//SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C layout at 42 {} \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/args b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/args new file mode 100644 index 000000000..3cf20d57b --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/args @@ -0,0 +1 @@ +- \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/err b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/err new file mode 100644 index 000000000..983a9b92c --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/err @@ -0,0 +1,10 @@ +Error: More than one storage layout definition. + --> :5:34: + | +5 | contract C layout at 0x1234 is A layout at 0xABCD { + | ^^^^^^ +Note: Previous definition: + --> :5:12: + | +5 | contract C layout at 0x1234 is A layout at 0xABCD { + | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/exit b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/stdin b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/stdin new file mode 100644 index 000000000..fc2ea9c9b --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_repeated_definition_error/stdin @@ -0,0 +1,6 @@ +//SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract A { +} +contract C layout at 0x1234 is A layout at 0xABCD { +} \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/args b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/args new file mode 100644 index 000000000..93090d6aa --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/args @@ -0,0 +1 @@ +--storage-layout - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/err b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/err new file mode 100644 index 000000000..58e52d14a --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/err @@ -0,0 +1 @@ +Error: Storage layout not supported for contract with specified layout base. diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/exit b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/output b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/output new file mode 100644 index 000000000..c90881588 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/output @@ -0,0 +1,2 @@ + +======= :C ======= diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/stdin b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/stdin new file mode 100644 index 000000000..87066c4d4 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/stdin @@ -0,0 +1,4 @@ +//SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C layout at 42 {} \ No newline at end of file diff --git a/test/libsolidity/ASTJSON/storage_layout_specifier.json b/test/libsolidity/ASTJSON/storage_layout_specifier.json new file mode 100644 index 000000000..5ffa1abe3 --- /dev/null +++ b/test/libsolidity/ASTJSON/storage_layout_specifier.json @@ -0,0 +1,88 @@ +{ + "absolutePath": "a", + "exportedSymbols": { + "C": [ + 5 + ] + }, + "id": 6, + "nodeType": "SourceUnit", + "nodes": [ + { + "abstract": false, + "baseContracts": [], + "canonicalName": "C", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 5, + "linearizedBaseContracts": [ + 5 + ], + "name": "C", + "nameLocation": "9:1:1", + "nodeType": "ContractDefinition", + "nodes": [], + "scope": 6, + "src": "0:35:1", + "storageLayout": { + "baseSlotExpression": { + "commonType": { + "typeIdentifier": "t_rational_5801_by_1", + "typeString": "int_const 5801" + }, + "id": 3, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "leftExpression": { + "hexValue": "31323334", + "id": 1, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "21:4:1", + "typeDescriptions": { + "typeIdentifier": "t_rational_1234_by_1", + "typeString": "int_const 1234" + }, + "value": "1234" + }, + "nodeType": "BinaryOperation", + "operator": "+", + "rightExpression": { + "hexValue": "34353637", + "id": 2, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "28:4:1", + "typeDescriptions": { + "typeIdentifier": "t_rational_4567_by_1", + "typeString": "int_const 4567" + }, + "value": "4567" + }, + "src": "21:11:1", + "typeDescriptions": { + "typeIdentifier": "t_rational_5801_by_1", + "typeString": "int_const 5801" + } + }, + "id": 4, + "nodeType": "StorageLayoutSpecifier", + "src": "11:21:1" + }, + "usedErrors": [], + "usedEvents": [] + } + ], + "src": "0:36:1" +} diff --git a/test/libsolidity/ASTJSON/storage_layout_specifier.sol b/test/libsolidity/ASTJSON/storage_layout_specifier.sol new file mode 100644 index 000000000..1031f2db0 --- /dev/null +++ b/test/libsolidity/ASTJSON/storage_layout_specifier.sol @@ -0,0 +1,3 @@ +contract C layout at 1234 + 4567 {} + +// ---- \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/functionCalls/empty_call_options.sol b/test/libsolidity/syntaxTests/functionCalls/empty_call_options.sol new file mode 100644 index 000000000..6a14c1198 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/empty_call_options.sol @@ -0,0 +1,8 @@ +contract C { + function f() external payable returns (uint) { return 1; } + function g() public { + this.f{}(); + } +} +// ---- +// ParserError 2314: (116-117): Expected ';' but got '{' diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_inheritance_definition.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_inheritance_definition.sol new file mode 100644 index 000000000..1701f7723 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_inheritance_definition.sol @@ -0,0 +1,5 @@ +contract A {} +contract B {} +contract C is A, B is B{ } +// ---- +// ParserError 6668: (47-49): More than one inheritance list. diff --git a/test/libsolidity/syntaxTests/inheritance/repeated_inheritance_definition.sol b/test/libsolidity/syntaxTests/inheritance/repeated_inheritance_definition.sol new file mode 100644 index 000000000..87af62c67 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/repeated_inheritance_definition.sol @@ -0,0 +1,7 @@ +contract A {} +contract B {} +contract C is A is B is B is A{ } +// ---- +// ParserError 6668: (44-46): More than one inheritance list. +// ParserError 6668: (49-51): More than one inheritance list. +// ParserError 6668: (54-56): More than one inheritance list. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol new file mode 100644 index 000000000..f362a5d89 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol @@ -0,0 +1,4 @@ +abstract contract C layout at 42 { } +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/at_before_layout.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/at_before_layout.sol new file mode 100644 index 000000000..fc6b53c36 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/at_before_layout.sol @@ -0,0 +1,3 @@ +contract C at layout 0x1234ABC { } +// ---- +// ParserError 2314: (11-13): Expected '{' but got identifier diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol new file mode 100644 index 000000000..710703520 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol @@ -0,0 +1,4 @@ +contract at layout at 0x1234ABC { } +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol new file mode 100644 index 000000000..9b7b1fc0e --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol @@ -0,0 +1,4 @@ +contract layout layout at 0x1234ABC { } +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol new file mode 100644 index 000000000..5daf8c3c4 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol @@ -0,0 +1,7 @@ +contract C layout at 0x1234 { + uint layout; + function at() public pure { } +} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_definition.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_definition.sol new file mode 100644 index 000000000..4781b87fa --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_definition.sol @@ -0,0 +1,3 @@ +contract C layout at 0x1234 is A, B layout at 0xABC { } +// ---- +// ParserError 8714: (36-42): More than one storage layout definition. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_keyword.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_keyword.sol new file mode 100644 index 000000000..416ca0f64 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/duplicated_layout_keyword.sol @@ -0,0 +1,4 @@ +contract C layout layout at 0x1234ABC { } +// ---- +// ParserError 1994: (18-24): Expected 'at' but got identifier +// ParserError 2314: (28-37): Expected '{' but got 'Number' diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_specified.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_specified.sol new file mode 100644 index 000000000..7f433dabb --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_specified.sol @@ -0,0 +1,5 @@ +contract C { + function f() public pure layout at 32 { } +} +// ---- +// ParserError 2314: (52-54): Expected '{' but got 'Number' diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_with_no_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_with_no_expression.sol new file mode 100644 index 000000000..c28596af7 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_declaration_layout_with_no_expression.sol @@ -0,0 +1,6 @@ +contract C { + function f() public pure layout at { } +} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/interface.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/interface.sol new file mode 100644 index 000000000..2c853e837 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/interface.sol @@ -0,0 +1,3 @@ +interface I layout at 42 { } +// ---- +// ParserError 2314: (12-18): Expected '{' but got identifier diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol new file mode 100644 index 000000000..2623fcaa7 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol @@ -0,0 +1,4 @@ +contract C layout at 0xffff * (0x123 + 0xABC) { } +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol new file mode 100644 index 000000000..3d256c9b1 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol @@ -0,0 +1,7 @@ +function f() pure returns (uint256) { + return 128; +} +contract C layout at f() { } +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol new file mode 100644 index 000000000..3b034da9e --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol @@ -0,0 +1,5 @@ +uint constant X = 42; +contract C layout at 0xffff * (50 - X) { } +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_no_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_no_expression.sol new file mode 100644 index 000000000..5123678b6 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_no_expression.sol @@ -0,0 +1,3 @@ +contract C layout at { } +// ---- +// ParserError 6933: (21-22): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_empty_braces.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_empty_braces.sol new file mode 100644 index 000000000..96a65ff98 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_empty_braces.sol @@ -0,0 +1,3 @@ +contract C layout at { } { } +// ---- +// ParserError 6933: (21-22): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_empty_call_options.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_empty_call_options.sol new file mode 100644 index 000000000..e0b1f4e5c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_empty_call_options.sol @@ -0,0 +1,6 @@ +contract A { + function f() external pure returns (uint) {} +} +contract C is A layout at this.f{}() {} +// ---- +// ParserError 7858: (98-99): Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol new file mode 100644 index 000000000..4bc00778c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol @@ -0,0 +1,7 @@ +contract A { + function f() external pure returns (uint) {} +} +contract C is A layout at this.f{value:123}() {} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_statement_without_at.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_statement_without_at.sol new file mode 100644 index 000000000..b60654629 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_statement_without_at.sol @@ -0,0 +1,4 @@ +contract C layout { } +// ---- +// ParserError 1994: (18-19): Expected 'at' but got '{' +// ParserError 6933: (20-21): Expected primary expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol new file mode 100644 index 000000000..198751482 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol @@ -0,0 +1,7 @@ +contract A { } +contract B { } +contract C is A, B layout at 0x1234 { } +contract D layout at 0xABCD is A, B { } +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/library.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/library.sol new file mode 100644 index 000000000..2848a7c7e --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/library.sol @@ -0,0 +1,3 @@ +library L layout at 42 { } +// ---- +// ParserError 2314: (10-16): Expected '{' but got identifier diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol new file mode 100644 index 000000000..0ecaf0da2 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol @@ -0,0 +1,5 @@ +contract C layout at 5 minutes { } +contract D layout at 2 gwei { } +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/natspec.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/natspec.sol new file mode 100644 index 000000000..d1712a1ff --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/natspec.sol @@ -0,0 +1,10 @@ +contract C layout at + /** + @notice function f should return the value of the base slot for the contract's storage layout + @dev the value returned by f should be in the range of uint256 + */ + f() +{ } +// ==== +// stopAfter: parsing +// ---- \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/repeated_layout_definition.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/repeated_layout_definition.sol new file mode 100644 index 000000000..717694030 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/repeated_layout_definition.sol @@ -0,0 +1,5 @@ +contract C layout at 0x1234 layout at 0xABC layout at 0x4321 layout at 0xCBA { } +// ---- +// ParserError 8714: (28-34): More than one storage layout definition. +// ParserError 8714: (44-50): More than one storage layout definition. +// ParserError 8714: (61-67): More than one storage layout definition. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol new file mode 100644 index 000000000..03a2f8a07 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol @@ -0,0 +1,6 @@ +contract A layout at 0x1234 {} +contract B layout at 1024 {} +contract C layout at "C" {} +// ==== +// stopAfter: parsing +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_layout_specifier.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_layout_specifier.sol new file mode 100644 index 000000000..0f7279fcd --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_layout_specifier.sol @@ -0,0 +1,5 @@ +contract C { + uint x layout at 0xF; +} +// ---- +// ParserError 2314: (24-30): Expected ';' but got identifier diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_layout_specifier.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_layout_specifier.sol new file mode 100644 index 000000000..fa05d1276 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_layout_specifier.sol @@ -0,0 +1,3 @@ +struct S layout at 23 { } +// ---- +// ParserError 2314: (9-15): Expected '{' but got identifier From de3a7b509ed7c446fe4de055410fdd230b22a389 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 19 Feb 2025 10:23:50 +0100 Subject: [PATCH 0728/1340] finds default vendored dependencies via find_package if requested --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 729da0d72..d95b7213e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,11 @@ if (NOT IGNORE_VENDORED_DEPENDENCIES) include(fmtlib) include(nlohmann-json) include(range-v3) +else () + message(WARNING "-- Ignoring vendored dependencies. Will use installed versions if found. Versions may differ from the ones the compiler was tested with. Make sure to run the test suite and thoroughly test the resulting binaries before using them in production.") + find_package(fmt REQUIRED) + find_package(nlohmann_json REQUIRED) + find_package(range-v3 REQUIRED) endif() find_package(Threads) From 04cfcf75c2008288a50ee4e9bf426cc6eda0e816 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 3 Dec 2024 11:58:46 -0300 Subject: [PATCH 0729/1340] Tweak existing tests --- .../syntaxTests/storageLayoutSpecifier/abstract_contract.sol | 3 +-- .../syntaxTests/storageLayoutSpecifier/contract_named_at.sol | 3 +-- .../storageLayoutSpecifier/contract_named_layout.sol | 3 +-- .../contract_with_members_named_layout_and_at.sol | 3 +-- .../layout_specification_binary_expression.sol | 3 +-- .../layout_specification_by_function.sol | 3 +-- .../layout_specification_constant_in_expression.sol | 3 +-- .../layout_specified_by_function_with_call_options.sol | 5 ++--- .../storageLayoutSpecifier/layout_with_inheritance.sol | 3 +-- .../storageLayoutSpecifier/multi_token_expression.sol | 3 +-- .../syntaxTests/storageLayoutSpecifier/simple_layout.sol | 5 ++--- ...layout_specifier.sol => struct_with_layout_specifier.sol} | 0 12 files changed, 13 insertions(+), 24 deletions(-) rename test/libsolidity/syntaxTests/storageLayoutSpecifier/{struct_layout_specifier.sol => struct_with_layout_specifier.sol} (100%) diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol index f362a5d89..dc7a7ce48 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol @@ -1,4 +1,3 @@ abstract contract C layout at 42 { } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 1834: (0-36): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol index 710703520..bbb928cb3 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol @@ -1,4 +1,3 @@ contract at layout at 0x1234ABC { } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 1834: (0-35): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol index 9b7b1fc0e..5c755d610 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol @@ -1,4 +1,3 @@ contract layout layout at 0x1234ABC { } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 1834: (0-39): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol index 5daf8c3c4..9e15ef564 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol @@ -2,6 +2,5 @@ contract C layout at 0x1234 { uint layout; function at() public pure { } } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 1834: (0-82): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol index 2623fcaa7..609178fd0 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol @@ -1,4 +1,3 @@ contract C layout at 0xffff * (0x123 + 0xABC) { } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 1834: (0-49): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol index 3d256c9b1..e9cd65ffe 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol @@ -2,6 +2,5 @@ function f() pure returns (uint256) { return 128; } contract C layout at f() { } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 1834: (56-84): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol index 3b034da9e..471a5a63c 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol @@ -1,5 +1,4 @@ uint constant X = 42; contract C layout at 0xffff * (50 - X) { } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 1834: (22-64): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol index 4bc00778c..aca167f6b 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol @@ -1,7 +1,6 @@ contract A { - function f() external pure returns (uint) {} + function f() external payable returns (uint) {} } contract C is A layout at this.f{value:123}() {} -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 1834: (67-115): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol index 198751482..7c8d483e2 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol @@ -2,6 +2,5 @@ contract A { } contract B { } contract C is A, B layout at 0x1234 { } contract D layout at 0xABCD is A, B { } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 1834: (30-69): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol index 0ecaf0da2..8e048b29e 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol @@ -1,5 +1,4 @@ contract C layout at 5 minutes { } contract D layout at 2 gwei { } -// ==== -// stopAfter: parsing // ---- +// UnimplementedFeatureError 1834: (0-34): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol index 03a2f8a07..116a6c5e4 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol @@ -1,6 +1,5 @@ contract A layout at 0x1234 {} contract B layout at 1024 {} -contract C layout at "C" {} -// ==== -// stopAfter: parsing +contract C layout at 0 {} // ---- +// UnimplementedFeatureError 1834: (0-30): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_layout_specifier.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_with_layout_specifier.sol similarity index 100% rename from test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_layout_specifier.sol rename to test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_with_layout_specifier.sol From ef61400474f8228a49573b33b17cb6ec3cb78fb9 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 3 Dec 2024 11:58:46 -0300 Subject: [PATCH 0730/1340] Add tests --- .../args | 1 + .../stdin | 6 +++++ .../storage_layout_specifier_no_doc.sol | 23 +++++++++++++++++++ .../storageLayoutSpecifier/abi_decode.sol | 3 +++ .../storageLayoutSpecifier/address.sol | 3 +++ .../address_non_constant.sol | 6 +++++ .../storageLayoutSpecifier/array_literal.sol | 3 +++ .../storageLayoutSpecifier/assignment.sol | 4 ++++ .../bitwise_negation_after_cast.sol | 3 +++ .../storageLayoutSpecifier/boolean.sol | 3 +++ .../builtin_functions.sol | 18 +++++++++++++++ .../bytes_length_member.sol | 3 +++ .../constant_divided_by_its_negation.sol | 4 ++++ .../constant_divided_by_zero.sol | 4 ++++ .../constant_from_base_contract.sol | 7 ++++++ .../storageLayoutSpecifier/delete.sol | 4 ++++ .../division_by_zero.sol | 3 +++ .../storageLayoutSpecifier/enum.sol | 5 ++++ .../function_address.sol | 7 ++++++ .../function_defined_in_other_contract.sol | 7 ++++++ .../function_selector.sol | 6 +++++ .../storageLayoutSpecifier/hex_address.sol | 3 +++ .../storageLayoutSpecifier/hex_string.sol | 3 +++ .../hex_string_cast.sol | 3 +++ .../increment_operator.sol | 4 ++++ .../inheriting_from_abstract_contract.sol | 5 ++++ .../inheriting_from_interface.sol | 5 ++++ .../inheriting_from_itself.sol | 3 +++ .../intermediate_operation_out_of_range.sol | 4 ++++ ...already_specified_in_ancestor_contract.sol | 7 ++++++ .../layout_bitwise_negation_literal.sol | 3 +++ .../layout_fractional_number.sol | 7 ++++++ .../layout_specification_bytes.sol | 4 ++++ .../layout_specification_max_value.sol | 3 +++ .../layout_specification_overflow_value.sol | 4 ++++ .../layout_specification_underflow_value.sol | 4 ++++ ...specified_by_attached_library_function.sol | 12 ++++++++++ .../layout_specified_by_bytes_concat.sol | 3 +++ .../layout_specified_by_error.sol | 4 ++++ .../layout_specified_by_event.sol | 4 ++++ ...ayout_specified_by_expression_not_pure.sol | 5 ++++ ...t_specified_by_first_ancestor_contract.sol | 6 +++++ .../layout_specified_by_interface_id.sol | 5 ++++ .../layout_specified_by_kecak256.sol | 3 +++ ...ut_specified_by_last_ancestor_contract.sol | 6 +++++ .../layout_specified_by_module.sol | 9 ++++++++ .../layout_specified_by_other_contract.sol | 4 ++++ .../layout_specified_by_type.sol | 3 +++ .../storageLayoutSpecifier/literal_cast.sol | 3 +++ .../literal_with_underscore.sol | 5 ++++ .../magic_variables.sol | 7 ++++++ .../negative_number.sol | 3 +++ .../storageLayoutSpecifier/precompiles.sol | 4 ++++ .../rational_number_zero_fractional_part.sol | 4 ++++ .../same_ancestor_two_contracts.sol | 5 ++++ .../state_variable_from_base_contract.sol | 7 ++++++ ...ate_variable_getter_from_base_contract.sol | 7 ++++++ .../storageLayoutSpecifier/string.sol | 3 +++ .../struct_defined_in_other_contract.sol | 11 +++++++++ .../ternary_operator.sol | 4 ++++ .../storageLayoutSpecifier/tuple.sol | 3 +++ .../storageLayoutSpecifier/type_uint_max.sol | 3 +++ .../user_defined_operators.sol | 12 ++++++++++ .../user_defined_value_type.sol | 5 ++++ .../user_defined_value_type_unwrap.sol | 5 ++++ .../user_defined_value_type_wrap.sol | 4 ++++ .../value_from_array_literal.sol | 4 ++++ .../value_from_bytes.sol | 4 ++++ 68 files changed, 352 insertions(+) create mode 100644 test/cmdlineTests/storage_layout_already_defined_in_ancestor/args create mode 100644 test/cmdlineTests/storage_layout_already_defined_in_ancestor/stdin create mode 100644 test/libsolidity/natspecJSON/storage_layout_specifier_no_doc.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/address_non_constant.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/assignment.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/builtin_functions.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_length_member.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/delete.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/division_by_zero.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/function_address.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/increment_operator.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_abstract_contract.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_interface.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_itself.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_bitwise_negation_literal.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_fractional_number.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_overflow_value.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_underflow_value.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_attached_library_function.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_error.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_event.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_expression_not_pure.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_with_underscore.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/magic_variables.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/negative_number.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/same_ancestor_two_contracts.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_from_base_contract.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_getter_from_base_contract.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_defined_in_other_contract.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_operators.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol diff --git a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/args b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/args new file mode 100644 index 000000000..3cf20d57b --- /dev/null +++ b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/args @@ -0,0 +1 @@ +- \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/stdin b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/stdin new file mode 100644 index 000000000..a340f7530 --- /dev/null +++ b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/stdin @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +contract A layout at 0x1234 {} +contract B is A {} +contract C layout at 0x1234 is B {} diff --git a/test/libsolidity/natspecJSON/storage_layout_specifier_no_doc.sol b/test/libsolidity/natspecJSON/storage_layout_specifier_no_doc.sol new file mode 100644 index 000000000..9bb8f4a06 --- /dev/null +++ b/test/libsolidity/natspecJSON/storage_layout_specifier_no_doc.sol @@ -0,0 +1,23 @@ +contract C + /// @notice this changes the base slot of the contract storage + layout at + /// @dev the expression must be in range of uint256 + 0x1234 +{ } +// ==== +// stopAfter: analysis +// ---- +// ---- +// :C devdoc +// { +// "kind": "dev", +// "methods": {}, +// "version": 1 +// } +// +// :C userdoc +// { +// "kind": "user", +// "methods": {}, +// "version": 1 +// } diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol new file mode 100644 index 000000000..330f461c2 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol @@ -0,0 +1,3 @@ +contract C layout at abi.decode(abi.encode(42), (uint)) {} +// ---- +// UnimplementedFeatureError 1834: (0-58): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol new file mode 100644 index 000000000..5691c0c90 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol @@ -0,0 +1,3 @@ +contract C layout at address(0x1234) {} +// ---- +// UnimplementedFeatureError 1834: (0-39): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_non_constant.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_non_constant.sol new file mode 100644 index 000000000..2d6d0745a --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_non_constant.sol @@ -0,0 +1,6 @@ +contract A {} + +contract C layout at address(new A()) {} +contract D layout at uint160(address(this)) {} +// ---- +// UnimplementedFeatureError 1834: (15-55): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol new file mode 100644 index 000000000..0f9c73b67 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol @@ -0,0 +1,3 @@ +contract C layout at [1, 2, 3] {} +// ---- +// UnimplementedFeatureError 1834: (0-33): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/assignment.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/assignment.sol new file mode 100644 index 000000000..2849dea65 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/assignment.sol @@ -0,0 +1,4 @@ +contract C layout at 1 = 2 { } +// ---- +// TypeError 4247: (21-22): Expression has to be an lvalue. +// TypeError 7407: (25-26): Type int_const 2 is not implicitly convertible to expected type int_const 1. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol new file mode 100644 index 000000000..01e34b707 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol @@ -0,0 +1,3 @@ +contract C layout at ~uint(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {} +// ---- +// UnimplementedFeatureError 1834: (0-97): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol new file mode 100644 index 000000000..cb4112f41 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol @@ -0,0 +1,3 @@ +contract C layout at true {} +// ---- +// UnimplementedFeatureError 1834: (0-28): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/builtin_functions.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/builtin_functions.sol new file mode 100644 index 000000000..631b1c60b --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/builtin_functions.sol @@ -0,0 +1,18 @@ +contract A layout at block.basefee { } +contract B layout at block.chainid { } +contract C layout at block.number { } +contract D layout at uint160(address(block.coinbase)) { } +contract E layout at block.prevrandao { } +contract F layout at uint(blockhash(0)) { } +contract G layout at msg.value { } +contract H layout at msg.sender { } +contract I layout at msg.data { } +contract J layout at tx.gasprice { } +contract K layout at uint160(tx.origin) { } +contract L layout at address(this).balance { } +contract M layout at uint(address(this).codehash) { } + +// ==== +// EVMVersion: >=paris +// ---- +// UnimplementedFeatureError 1834: (0-38): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_length_member.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_length_member.sol new file mode 100644 index 000000000..b2bb64b19 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_length_member.sol @@ -0,0 +1,3 @@ +contract C layout at bytes("ABCD").length {} +// ---- +// UnimplementedFeatureError 1834: (0-44): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol new file mode 100644 index 000000000..9f8acbeb6 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol @@ -0,0 +1,4 @@ +uint constant N = 100; +contract C layout at N / ~N {} +// ---- +// TypeError 3667: (48-50): Arithmetic error when computing constant value. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol new file mode 100644 index 000000000..f6e3c3805 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol @@ -0,0 +1,4 @@ +uint constant N = 100; +contract C layout at N / 0 {} +// ---- +// TypeError 1211: (44-49): Division by zero. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol new file mode 100644 index 000000000..1995cf698 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol @@ -0,0 +1,7 @@ +contract A { + uint constant x = 10; +} + +contract C is A layout at A.x { } +// ---- +// UnimplementedFeatureError 1834: (42-75): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/delete.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/delete.sol new file mode 100644 index 000000000..b6926b51f --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/delete.sol @@ -0,0 +1,4 @@ +contract C layout at delete 2 { } +// ---- +// TypeError 4247: (28-29): Expression has to be an lvalue. +// TypeError 9767: (21-29): Built-in unary operator delete cannot be applied to type int_const 2. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/division_by_zero.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/division_by_zero.sol new file mode 100644 index 000000000..51ddd9d6c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/division_by_zero.sol @@ -0,0 +1,3 @@ +contract A layout at 1 / 0 {} +// ---- +// TypeError 2271: (21-26): Built-in binary operator / cannot be applied to types int_const 1 and int_const 0. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol new file mode 100644 index 000000000..c9eba88e5 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol @@ -0,0 +1,5 @@ +enum Color {Red, Green, Blue} + +contract C layout at Color.Red {} +// ---- +// UnimplementedFeatureError 1834: (31-64): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_address.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_address.sol new file mode 100644 index 000000000..b6d2b99d9 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_address.sol @@ -0,0 +1,7 @@ +contract A { + function f() public pure {} +} + +contract C is A layout at this.f.address {} +// ---- +// UnimplementedFeatureError 1834: (48-91): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol new file mode 100644 index 000000000..1b8907903 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol @@ -0,0 +1,7 @@ +contract A { + function f() external pure {} +} + +contract C layout at A.f { } +// ---- +// UnimplementedFeatureError 1834: (50-78): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol new file mode 100644 index 000000000..e3b873ca7 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol @@ -0,0 +1,6 @@ +contract A { + function f() public {} +} +contract C is A layout at uint32(this.f.selector) {} +// ---- +// UnimplementedFeatureError 1834: (42-94): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol new file mode 100644 index 000000000..4a6e9401f --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol @@ -0,0 +1,3 @@ +contract C layout at 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF {} +// ---- +// UnimplementedFeatureError 1834: (0-66): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol new file mode 100644 index 000000000..38d1085a8 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol @@ -0,0 +1,3 @@ +contract C layout at hex"616263" {} +// ---- +// UnimplementedFeatureError 1834: (0-35): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol new file mode 100644 index 000000000..031862599 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol @@ -0,0 +1,3 @@ +contract at layout at uint40(bytes5(hex"0011223344")) { } +// ---- +// UnimplementedFeatureError 1834: (0-57): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/increment_operator.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/increment_operator.sol new file mode 100644 index 000000000..b5d0b0651 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/increment_operator.sol @@ -0,0 +1,4 @@ +contract C layout at ++2 { } +// ---- +// TypeError 4247: (23-24): Expression has to be an lvalue. +// TypeError 9767: (21-24): Built-in unary operator ++ cannot be applied to type int_const 2. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_abstract_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_abstract_contract.sol new file mode 100644 index 000000000..850798c93 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_abstract_contract.sol @@ -0,0 +1,5 @@ +abstract contract A { } + +contract C layout at 42 is A { } +// ---- +// UnimplementedFeatureError 1834: (25-57): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_interface.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_interface.sol new file mode 100644 index 000000000..541dea056 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_interface.sol @@ -0,0 +1,5 @@ +interface I { } + +contract C layout at 42 is I { } +// ---- +// UnimplementedFeatureError 1834: (17-49): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_itself.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_itself.sol new file mode 100644 index 000000000..e0e6625ab --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_itself.sol @@ -0,0 +1,3 @@ +contract C layout at 42 is C { } +// ---- +// TypeError 2449: (27-28): Definition of base has to precede definition of derived contract diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol new file mode 100644 index 000000000..b7bae489f --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol @@ -0,0 +1,4 @@ +contract A layout at (2**256 + 1) * 2 - 2**256 - 3 {} +contract B layout at (2**2 - 2**3) * (2**5 - 2**8) {} +// ---- +// UnimplementedFeatureError 1834: (0-54): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol new file mode 100644 index 000000000..8ddfdbfc3 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol @@ -0,0 +1,7 @@ +contract A layout at 0x1234 {} + +contract B is A {} + +contract C is B layout at 0xABCD {} +// ---- +// UnimplementedFeatureError 1834: (0-30): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_bitwise_negation_literal.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_bitwise_negation_literal.sol new file mode 100644 index 000000000..cd74b20db --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_bitwise_negation_literal.sol @@ -0,0 +1,3 @@ +contract C layout at ~0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE {} +// ---- +// UnimplementedFeatureError 1834: (0-91): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_fractional_number.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_fractional_number.sol new file mode 100644 index 000000000..0e24366b1 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_fractional_number.sol @@ -0,0 +1,7 @@ +contract A layout at 3/2 {} +contract B layout at 4.2 {} +contract C layout at .1 {} +contract D layout at 42e-10 {} +contract E layout at 1_7e-10 {} +// ---- +// UnimplementedFeatureError 1834: (0-27): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol new file mode 100644 index 000000000..65923479d --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol @@ -0,0 +1,4 @@ +bytes32 constant b = "bytes"; +contract A layout at b[1] {} +// ---- +// UnimplementedFeatureError 1834: (30-58): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol new file mode 100644 index 000000000..67954bdce --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol @@ -0,0 +1,3 @@ +contract C layout at 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF {} +// ---- +// UnimplementedFeatureError 1834: (0-90): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_overflow_value.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_overflow_value.sol new file mode 100644 index 000000000..ece4273bb --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_overflow_value.sol @@ -0,0 +1,4 @@ +contract A layout at 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 1 {} +contract B layout at 2**256 {} +// ---- +// UnimplementedFeatureError 1834: (0-94): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_underflow_value.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_underflow_value.sol new file mode 100644 index 000000000..953d791cc --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_underflow_value.sol @@ -0,0 +1,4 @@ +contract A layout at 0 - 1 {} +contract B layout at 2**8 - 2**16 {} +// ---- +// UnimplementedFeatureError 1834: (0-29): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_attached_library_function.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_attached_library_function.sol new file mode 100644 index 000000000..b586a271e --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_attached_library_function.sol @@ -0,0 +1,12 @@ +library L { + function f(uint x) public pure returns (uint) { + return x * 2; + } +} + + +contract C layout at 2.f() { + using L for *; +} +// ---- +// UnimplementedFeatureError 1834: (96-145): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol new file mode 100644 index 000000000..93271e125 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol @@ -0,0 +1,3 @@ +contract C layout at uint64(bytes8(bytes.concat("ABCD", "EFGH"))) {} +// ---- +// UnimplementedFeatureError 1834: (0-68): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_error.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_error.sol new file mode 100644 index 000000000..c73dc480d --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_error.sol @@ -0,0 +1,4 @@ +error MyError(); +contract C layout at MyError() {} +// ---- +// TypeError 7757: (38-47): Errors can only be used with revert statements: "revert MyError(args);", or require functions: "require(condition, MyError(args))". diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_event.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_event.sol new file mode 100644 index 000000000..7560fb83b --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_event.sol @@ -0,0 +1,4 @@ +event MyEvent(); +contract C layout at MyEvent() {} +// ---- +// TypeError 3132: (38-47): Event invocations have to be prefixed by "emit". diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_expression_not_pure.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_expression_not_pure.sol new file mode 100644 index 000000000..cbb4e5ed9 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_expression_not_pure.sol @@ -0,0 +1,5 @@ +function f(uint x) returns (uint) { return x + 1; } +contract A layout at f(2) {} +// ---- +// Warning 2018: (0-51): Function state mutability can be restricted to pure +// UnimplementedFeatureError 1834: (52-80): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol new file mode 100644 index 000000000..0549c9d60 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol @@ -0,0 +1,6 @@ +contract A layout at 42 {} +contract B is A {} +contract C is B {} +contract D is C {} +// ---- +// UnimplementedFeatureError 1834: (0-26): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol new file mode 100644 index 000000000..c8bc2abbc --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol @@ -0,0 +1,5 @@ +interface I {} + +contract C layout at uint(bytes32(type(I).interfaceId)) { } +// ---- +// UnimplementedFeatureError 1834: (16-75): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol new file mode 100644 index 000000000..14fb09b10 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol @@ -0,0 +1,3 @@ +contract C layout at uint(keccak256(bytes.concat("ABCD"))) {} +// ---- +// UnimplementedFeatureError 1834: (0-61): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol new file mode 100644 index 000000000..2a783a813 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol @@ -0,0 +1,6 @@ +contract A {} +contract B is A {} +contract C is B layout at 42 {} +contract D is C {} +// ---- +// UnimplementedFeatureError 1834: (33-64): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol new file mode 100644 index 000000000..57d51d587 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol @@ -0,0 +1,9 @@ +==== Source: A ==== +function f() pure {} + +==== Source: B ==== +import "A" as MyModule; + +contract C layout at MyModule {} +// ---- +// UnimplementedFeatureError 1834: (B:25-57): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol new file mode 100644 index 000000000..ee695075e --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol @@ -0,0 +1,4 @@ +contract A {} +contract C layout at A(address(0x1234)) {} +// ---- +// UnimplementedFeatureError 1834: (14-56): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol new file mode 100644 index 000000000..47ae6f0b4 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol @@ -0,0 +1,3 @@ +contract A layout at uint {} +// ---- +// UnimplementedFeatureError 1834: (0-28): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol new file mode 100644 index 000000000..d5bd3825e --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol @@ -0,0 +1,3 @@ +contract at layout at uint(42) { } +// ---- +// UnimplementedFeatureError 1834: (0-34): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_with_underscore.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_with_underscore.sol new file mode 100644 index 000000000..1c3c715f9 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_with_underscore.sol @@ -0,0 +1,5 @@ +contract A layout at 42_0e10 {} +contract B layout at 0x1234_ABCD {} +contract C layout at 1234_000 {} +// ---- +// UnimplementedFeatureError 1834: (0-31): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/magic_variables.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/magic_variables.sol new file mode 100644 index 000000000..44798fdbf --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/magic_variables.sol @@ -0,0 +1,7 @@ +contract A layout at this {} +contract B layout at super {} +contract C layout at msg {} +contract D layout at tx {} +contract E layout at block {} +// ---- +// UnimplementedFeatureError 1834: (0-28): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/negative_number.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/negative_number.sol new file mode 100644 index 000000000..79d8b395b --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/negative_number.sol @@ -0,0 +1,3 @@ +contract A layout at -1 {} +// ---- +// UnimplementedFeatureError 1834: (0-26): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol new file mode 100644 index 000000000..a7e9ee089 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol @@ -0,0 +1,4 @@ +contract A layout at addmod(1, 2, 3) {} +contract B layout at mulmod(3, 2, 1) {} +// ---- +// UnimplementedFeatureError 1834: (0-39): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol new file mode 100644 index 000000000..4d5b2da9c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol @@ -0,0 +1,4 @@ +contract A layout at 42.0 {} +contract B layout at 2.5e10 {} +// ---- +// UnimplementedFeatureError 1834: (0-28): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/same_ancestor_two_contracts.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/same_ancestor_two_contracts.sol new file mode 100644 index 000000000..310f50357 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/same_ancestor_two_contracts.sol @@ -0,0 +1,5 @@ +contract A {} +contract B is A layout at 64 {} +contract C is A layout at 42 {} +// ---- +// UnimplementedFeatureError 1834: (14-45): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_from_base_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_from_base_contract.sol new file mode 100644 index 000000000..67e63924b --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_from_base_contract.sol @@ -0,0 +1,7 @@ +contract A { + uint public x = 10; +} + +contract C is A layout at A.x {} +// ---- +// UnimplementedFeatureError 1834: (40-72): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_getter_from_base_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_getter_from_base_contract.sol new file mode 100644 index 000000000..11c8f449c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_getter_from_base_contract.sol @@ -0,0 +1,7 @@ +contract A { + uint public x = 10; +} + +contract C is A layout at this.x() {} +// ---- +// UnimplementedFeatureError 1834: (40-77): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol new file mode 100644 index 000000000..7f41e64cb --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol @@ -0,0 +1,3 @@ +contract C layout at "MyLayoutBase" {} +// ---- +// UnimplementedFeatureError 1834: (0-38): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_defined_in_other_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_defined_in_other_contract.sol new file mode 100644 index 000000000..4f74c4545 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_defined_in_other_contract.sol @@ -0,0 +1,11 @@ +contract A { + struct SA { + uint x; + uint y; + bytes32 b; + } +} + +contract C is A layout at A.SA { } +// ---- +// UnimplementedFeatureError 1834: (89-123): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol new file mode 100644 index 000000000..5052d8375 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol @@ -0,0 +1,4 @@ +contract A layout at true ? 42 : 94 {} +contract B layout at 255 + (true ? 1 : 0) {} +// ---- +// UnimplementedFeatureError 1834: (0-38): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol new file mode 100644 index 000000000..0dbc2b371 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol @@ -0,0 +1,3 @@ +contract C layout at (1, 2, 3) {} +// ---- +// UnimplementedFeatureError 1834: (0-33): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol new file mode 100644 index 000000000..54ebb32c7 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol @@ -0,0 +1,3 @@ +contract at layout at type(uint).max { } +// ---- +// UnimplementedFeatureError 1834: (0-40): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_operators.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_operators.sol new file mode 100644 index 000000000..e044a6aad --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_operators.sol @@ -0,0 +1,12 @@ +type MyUint is uint; + +using {add as +} for MyUint global; +function add(MyUint a, MyUint b) pure returns (MyUint) { + return MyUint.wrap(2); +} + +contract C layout at MyUint.wrap(1) + MyUint.wrap(2) {} +// ---- +// Warning 5667: (71-79): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning 5667: (81-89): Unused function parameter. Remove or comment out the variable name to silence this warning. +// UnimplementedFeatureError 1834: (145-200): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol new file mode 100644 index 000000000..9287e5a3b --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol @@ -0,0 +1,5 @@ +type MyUint is uint128; +MyUint constant x = MyUint.wrap(42); +contract C layout at x {} +// ---- +// UnimplementedFeatureError 1834: (61-86): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol new file mode 100644 index 000000000..a232939c7 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol @@ -0,0 +1,5 @@ +type MyUint is uint128; +MyUint constant x = MyUint.wrap(42); +contract C layout at MyUint.unwrap(x) {} +// ---- +// UnimplementedFeatureError 1834: (61-101): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol new file mode 100644 index 000000000..e057b6940 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol @@ -0,0 +1,4 @@ +type MyUint is uint128; +contract C layout at MyUint.wrap(42) {} +// ---- +// UnimplementedFeatureError 1834: (24-63): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol new file mode 100644 index 000000000..cce2bfbe9 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol @@ -0,0 +1,4 @@ +contract A layout at [1, 2, 3][0] {} +contract B layout at 255 + [1, 2, 3][0] {} +// ---- +// UnimplementedFeatureError 1834: (0-36): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol new file mode 100644 index 000000000..73fcdc485 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol @@ -0,0 +1,4 @@ +bytes32 constant b = "Solidity"; +contract C layout at uint8(b[1]) {} +// ---- +// UnimplementedFeatureError 1834: (33-68): Code generation is not supported for contracts with specified storage layout base. From 7ef0ef8c19bf7df4341b3e72787d8ac75cf988e6 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 6 Feb 2025 17:37:53 -0300 Subject: [PATCH 0731/1340] Type checker support for storage layout specifier --- libsolidity/analysis/ContractLevelChecker.cpp | 31 +++++++++ libsolidity/analysis/ContractLevelChecker.h | 2 + .../analysis/PostTypeContractLevelChecker.cpp | 69 ++++++++++++++++++- .../analysis/PostTypeContractLevelChecker.h | 2 + libsolidity/ast/AST.cpp | 5 ++ libsolidity/ast/AST.h | 2 + libsolidity/ast/ASTAnnotations.h | 7 ++ .../err | 21 ++++++ .../exit | 1 + .../storageLayoutSpecifier/abi_decode.sol | 2 +- .../abstract_contract.sol | 2 +- .../storageLayoutSpecifier/address.sol | 2 +- .../address_non_constant.sol | 3 +- .../storageLayoutSpecifier/array_literal.sol | 2 +- .../bitwise_negation_after_cast.sol | 2 +- .../storageLayoutSpecifier/boolean.sol | 2 +- .../builtin_functions.sol | 14 +++- .../bytes_length_member.sol | 2 +- .../constant_divided_by_its_negation.sol | 2 +- .../constant_divided_by_zero.sol | 2 +- .../constant_from_base_contract.sol | 2 +- .../storageLayoutSpecifier/enum.sol | 2 +- .../function_address.sol | 2 +- .../function_defined_in_other_contract.sol | 2 +- .../function_selector.sol | 2 +- .../storageLayoutSpecifier/hex_address.sol | 2 +- .../storageLayoutSpecifier/hex_string.sol | 2 +- .../hex_string_cast.sol | 2 +- ...already_specified_in_ancestor_contract.sol | 3 +- .../layout_bitwise_negation_literal.sol | 2 +- .../layout_fractional_number.sol | 6 +- .../layout_specification_by_function.sol | 2 +- .../layout_specification_bytes.sol | 2 +- ...t_specification_constant_in_expression.sol | 2 +- .../layout_specification_overflow_value.sol | 3 +- .../layout_specification_underflow_value.sol | 3 +- ...specified_by_attached_library_function.sol | 2 +- .../layout_specified_by_bytes_concat.sol | 2 +- ...ayout_specified_by_expression_not_pure.sol | 3 +- ...t_specified_by_first_ancestor_contract.sol | 4 +- ...pecified_by_function_with_call_options.sol | 2 +- .../layout_specified_by_interface_id.sol | 2 +- .../layout_specified_by_kecak256.sol | 2 +- ...ut_specified_by_last_ancestor_contract.sol | 2 +- .../layout_specified_by_module.sol | 2 +- .../layout_specified_by_other_contract.sol | 2 +- .../layout_specified_by_type.sol | 2 +- .../storageLayoutSpecifier/literal_cast.sol | 2 +- .../magic_variables.sol | 6 +- .../negative_number.sol | 2 +- .../storageLayoutSpecifier/precompiles.sol | 3 +- .../state_variable_from_base_contract.sol | 2 +- ...ate_variable_getter_from_base_contract.sol | 2 +- .../storageLayoutSpecifier/string.sol | 2 +- .../struct_defined_in_other_contract.sol | 2 +- .../ternary_operator.sol | 3 +- .../storageLayoutSpecifier/tuple.sol | 2 +- .../storageLayoutSpecifier/type_uint_max.sol | 2 +- .../user_defined_operators.sol | 4 +- .../user_defined_value_type.sol | 2 +- .../user_defined_value_type_unwrap.sol | 2 +- .../user_defined_value_type_wrap.sol | 2 +- .../value_from_array_literal.sol | 3 +- .../value_from_bytes.sol | 2 +- 64 files changed, 223 insertions(+), 59 deletions(-) create mode 100644 test/cmdlineTests/storage_layout_already_defined_in_ancestor/err create mode 100644 test/cmdlineTests/storage_layout_already_defined_in_ancestor/exit diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index eaeaf4851..7996fd711 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -97,10 +97,41 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkBaseABICompatibility(_contract); checkPayableFallbackWithoutReceive(_contract); checkStorageSize(_contract); + checkStorageLayoutSpecifier(_contract); return !Error::containsErrors(m_errorReporter.errors()); } +void ContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinition const& _contract) +{ + if (_contract.storageLayoutSpecifier()) + { + solAssert(!_contract.isLibrary() && !_contract.isInterface()); + + if (_contract.abstract()) + m_errorReporter.typeError( + 7587_error, + _contract.storageLayoutSpecifier()->location(), + "Storage layout cannot be specified for abstract contracts." + ); + } + + for (auto const* ancestorContract: _contract.annotation().linearizedBaseContracts | ranges::views::reverse) + { + if (*ancestorContract == _contract) + continue; + if (ancestorContract->storageLayoutSpecifier()) + m_errorReporter.typeError( + 8894_error, + _contract.location(), + SecondarySourceLocation().append( + "Storage layout was already specified here.", + ancestorContract->storageLayoutSpecifier()->location() + ), + "Storage layout can only be specified in the most derived contract." + ); + } +} void ContractLevelChecker::checkDuplicateFunctions(ContractDefinition const& _contract) { /// Checks that two functions with the same name defined in this contract have different diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index 1f5826fdc..f0e521c60 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -90,6 +90,8 @@ class ContractLevelChecker void checkPayableFallbackWithoutReceive(ContractDefinition const& _contract); /// Error if the contract requires too much storage void checkStorageSize(ContractDefinition const& _contract); + /// Checks if the storage layout specifier is properly assigned in the inheritance tree and not applied to an abstract contract + void checkStorageLayoutSpecifier(ContractDefinition const& _contract); OverrideChecker m_overrideChecker; langutil::ErrorReporter& m_errorReporter; diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.cpp b/libsolidity/analysis/PostTypeContractLevelChecker.cpp index 6d8dc416a..b605401e9 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.cpp +++ b/libsolidity/analysis/PostTypeContractLevelChecker.cpp @@ -22,13 +22,19 @@ #include +#include #include +#include +#include #include #include +#include + using namespace solidity; using namespace solidity::langutil; using namespace solidity::frontend; +using namespace solidity::util; bool PostTypeContractLevelChecker::check(SourceUnit const& _sourceUnit) { @@ -51,7 +57,7 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract) for (ErrorDefinition const* error: _contract.interfaceErrors()) { std::string signature = error->functionType(true)->externalSignature(); - uint32_t hash = util::selectorFromSignatureU32(signature); + uint32_t hash = selectorFromSignatureU32(signature); // Fail if there is a different signature for the same hash. if (!errorHashes[hash].empty() && !errorHashes[hash].count(signature)) { @@ -67,5 +73,66 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract) errorHashes[hash][signature] = error->location(); } + if (auto const* layoutSpecifier = _contract.storageLayoutSpecifier()) + checkStorageLayoutSpecifier(*layoutSpecifier); + return !Error::containsErrors(m_errorReporter.errors()); } + +void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(StorageLayoutSpecifier const& _storageLayoutSpecifier) +{ + Expression const& baseSlotExpression = _storageLayoutSpecifier.baseSlotExpression(); + + if (!*baseSlotExpression.annotation().isPure) + { + // TODO: introduce and handle erc7201 as a builtin function + m_errorReporter.typeError( + 1139_error, + baseSlotExpression.location(), + "The base slot of the storage layout must be a compile-time constant expression." + ); + return; + } + + auto const* baseSlotExpressionType = type(baseSlotExpression); + auto const* rationalType = dynamic_cast(baseSlotExpressionType); + if (!rationalType) + { + m_errorReporter.typeError( + 6396_error, + baseSlotExpression.location(), + "The base slot of the storage layout must evaluate to a rational number." + ); + return; + } + + if (rationalType->isFractional()) + { + m_errorReporter.typeError( + 1763_error, + baseSlotExpression.location(), + "The base slot of the storage layout must evaluate to an integer." + ); + return; + } + solAssert(rationalType->value().denominator() == 1); + + if ( + rationalType->value().numerator() < 0 || + rationalType->value().numerator() > std::numeric_limits::max() + ) + { + m_errorReporter.typeError( + 6753_error, + baseSlotExpression.location(), + fmt::format( + "The base slot of the storage layout evaluates to {}, which is outside the range of type uint256.", + formatNumberReadable(rationalType->value().numerator()) + ) + ); + return; + } + + solAssert(baseSlotExpressionType->isImplicitlyConvertibleTo(*TypeProvider::uint256())); + _storageLayoutSpecifier.annotation().baseSlot = u256(rationalType->value().numerator()); +} diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.h b/libsolidity/analysis/PostTypeContractLevelChecker.h index e12e37184..889c16356 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.h +++ b/libsolidity/analysis/PostTypeContractLevelChecker.h @@ -50,6 +50,8 @@ class PostTypeContractLevelChecker /// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings bool check(ContractDefinition const& _contract); + void checkStorageLayoutSpecifier(StorageLayoutSpecifier const& _storageLayoutSpecifier); + langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index cf3bddf40..b59273b18 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -383,6 +383,11 @@ StorageLayoutSpecifier::StorageLayoutSpecifier( solAssert(_location.contains(m_baseSlotExpression->location())); } +StorageLayoutSpecifierAnnotation& StorageLayoutSpecifier::annotation() const +{ + return initAnnotation(); +} + TypeNameAnnotation& TypeName::annotation() const { return initAnnotation(); diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index cc5cc9324..0121bef33 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -622,6 +622,8 @@ class StorageLayoutSpecifier : public ASTNode void accept(ASTConstVisitor& _visitor) const override; Expression const& baseSlotExpression() const { solAssert(m_baseSlotExpression); return *m_baseSlotExpression; } + StorageLayoutSpecifierAnnotation& annotation() const override; + private: ASTPointer m_baseSlotExpression; }; diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 3f817b180..7adfc7a4a 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -173,6 +174,12 @@ struct ContractDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocu std::map internalFunctionIDs; }; +struct StorageLayoutSpecifierAnnotation: ASTAnnotation +{ + // The evaluated value of the expression specifying the contract storage layout base + util::SetOnce baseSlot; +}; + struct CallableDeclarationAnnotation: DeclarationAnnotation { /// The set of functions/modifiers/events this callable overrides. diff --git a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err new file mode 100644 index 000000000..a5ad27954 --- /dev/null +++ b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err @@ -0,0 +1,21 @@ +Error: Storage layout can only be specified in the most derived contract. + --> :5:1: + | +5 | contract B is A {} + | ^^^^^^^^^^^^^^^^^^ +Note: Storage layout was already specified here. + --> :4:12: + | +4 | contract A layout at 0x1234 {} + | ^^^^^^^^^^^^^^^^ + +Error: Storage layout can only be specified in the most derived contract. + --> :6:1: + | +6 | contract C layout at 0x1234 is B {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: Storage layout was already specified here. + --> :4:12: + | +4 | contract A layout at 0x1234 {} + | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/exit b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/exit @@ -0,0 +1 @@ +1 diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol index 330f461c2..920e8d252 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol @@ -1,3 +1,3 @@ contract C layout at abi.decode(abi.encode(42), (uint)) {} // ---- -// UnimplementedFeatureError 1834: (0-58): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-55): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol index dc7a7ce48..3f87f87bb 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract.sol @@ -1,3 +1,3 @@ abstract contract C layout at 42 { } // ---- -// UnimplementedFeatureError 1834: (0-36): Code generation is not supported for contracts with specified storage layout base. +// TypeError 7587: (20-32): Storage layout cannot be specified for abstract contracts. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol index 5691c0c90..fded26fad 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol @@ -1,3 +1,3 @@ contract C layout at address(0x1234) {} // ---- -// UnimplementedFeatureError 1834: (0-39): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-36): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_non_constant.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_non_constant.sol index 2d6d0745a..39e3fcec9 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_non_constant.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_non_constant.sol @@ -3,4 +3,5 @@ contract A {} contract C layout at address(new A()) {} contract D layout at uint160(address(this)) {} // ---- -// UnimplementedFeatureError 1834: (15-55): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (36-52): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (77-99): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol index 0f9c73b67..af6b9424f 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol @@ -1,3 +1,3 @@ contract C layout at [1, 2, 3] {} // ---- -// UnimplementedFeatureError 1834: (0-33): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-30): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol index 01e34b707..6ccb2ff7a 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol @@ -1,3 +1,3 @@ contract C layout at ~uint(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {} // ---- -// UnimplementedFeatureError 1834: (0-97): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-94): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol index cb4112f41..083977c7a 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol @@ -1,3 +1,3 @@ contract C layout at true {} // ---- -// UnimplementedFeatureError 1834: (0-28): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-25): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/builtin_functions.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/builtin_functions.sol index 631b1c60b..7c1bfc1e6 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/builtin_functions.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/builtin_functions.sol @@ -15,4 +15,16 @@ contract M layout at uint(address(this).codehash) { } // ==== // EVMVersion: >=paris // ---- -// UnimplementedFeatureError 1834: (0-38): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (21-34): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (60-73): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (99-111): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (137-169): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (195-211): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (237-255): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (281-290): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (316-326): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (352-360): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (386-397): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (423-441): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (467-488): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (514-542): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_length_member.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_length_member.sol index b2bb64b19..f49e6c2db 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_length_member.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_length_member.sol @@ -1,3 +1,3 @@ contract C layout at bytes("ABCD").length {} // ---- -// UnimplementedFeatureError 1834: (0-44): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (21-41): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol index 9f8acbeb6..b9cdd9dfa 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol @@ -1,4 +1,4 @@ uint constant N = 100; contract C layout at N / ~N {} // ---- -// TypeError 3667: (48-50): Arithmetic error when computing constant value. +// TypeError 6396: (44-50): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol index f6e3c3805..bb97172d9 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol @@ -1,4 +1,4 @@ uint constant N = 100; contract C layout at N / 0 {} // ---- -// TypeError 1211: (44-49): Division by zero. +// TypeError 6396: (44-49): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol index 1995cf698..e06deeaaf 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol @@ -4,4 +4,4 @@ contract A { contract C is A layout at A.x { } // ---- -// UnimplementedFeatureError 1834: (42-75): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (68-71): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol index c9eba88e5..9a264247c 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol @@ -2,4 +2,4 @@ enum Color {Red, Green, Blue} contract C layout at Color.Red {} // ---- -// UnimplementedFeatureError 1834: (31-64): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (52-61): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_address.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_address.sol index b6d2b99d9..a3256f2df 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_address.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_address.sol @@ -4,4 +4,4 @@ contract A { contract C is A layout at this.f.address {} // ---- -// UnimplementedFeatureError 1834: (48-91): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (74-88): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol index 1b8907903..68b2e2460 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol @@ -4,4 +4,4 @@ contract A { contract C layout at A.f { } // ---- -// UnimplementedFeatureError 1834: (50-78): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (71-74): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol index e3b873ca7..98c7b6057 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol @@ -3,4 +3,4 @@ contract A { } contract C is A layout at uint32(this.f.selector) {} // ---- -// UnimplementedFeatureError 1834: (42-94): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (68-91): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol index 4a6e9401f..9e63740d8 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol @@ -1,3 +1,3 @@ contract C layout at 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF {} // ---- -// UnimplementedFeatureError 1834: (0-66): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-63): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol index 38d1085a8..194f0df0e 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol @@ -1,3 +1,3 @@ contract C layout at hex"616263" {} // ---- -// UnimplementedFeatureError 1834: (0-35): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-32): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol index 031862599..a803d005f 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol @@ -1,3 +1,3 @@ contract at layout at uint40(bytes5(hex"0011223344")) { } // ---- -// UnimplementedFeatureError 1834: (0-57): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (22-53): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol index 8ddfdbfc3..d525d9206 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol @@ -4,4 +4,5 @@ contract B is A {} contract C is B layout at 0xABCD {} // ---- -// UnimplementedFeatureError 1834: (0-30): Code generation is not supported for contracts with specified storage layout base. +// TypeError 8894: (32-50): Storage layout can only be specified in the most derived contract. +// TypeError 8894: (52-87): Storage layout can only be specified in the most derived contract. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_bitwise_negation_literal.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_bitwise_negation_literal.sol index cd74b20db..a32382574 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_bitwise_negation_literal.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_bitwise_negation_literal.sol @@ -1,3 +1,3 @@ contract C layout at ~0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE {} // ---- -// UnimplementedFeatureError 1834: (0-91): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6753: (21-88): The base slot of the storage layout evaluates to -2**256 + 1, which is outside the range of type uint256. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_fractional_number.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_fractional_number.sol index 0e24366b1..1f2e1ecd4 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_fractional_number.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_fractional_number.sol @@ -4,4 +4,8 @@ contract C layout at .1 {} contract D layout at 42e-10 {} contract E layout at 1_7e-10 {} // ---- -// UnimplementedFeatureError 1834: (0-27): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1763: (21-24): The base slot of the storage layout must evaluate to an integer. +// TypeError 1763: (49-52): The base slot of the storage layout must evaluate to an integer. +// TypeError 1763: (77-79): The base slot of the storage layout must evaluate to an integer. +// TypeError 1763: (104-110): The base slot of the storage layout must evaluate to an integer. +// TypeError 1763: (135-142): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol index e9cd65ffe..f0c6a0098 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_by_function.sol @@ -3,4 +3,4 @@ function f() pure returns (uint256) { } contract C layout at f() { } // ---- -// UnimplementedFeatureError 1834: (56-84): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (77-80): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol index 65923479d..6f9b39703 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol @@ -1,4 +1,4 @@ bytes32 constant b = "bytes"; contract A layout at b[1] {} // ---- -// UnimplementedFeatureError 1834: (30-58): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (51-55): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol index 471a5a63c..8e6d37ad6 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol @@ -1,4 +1,4 @@ uint constant X = 42; contract C layout at 0xffff * (50 - X) { } // ---- -// UnimplementedFeatureError 1834: (22-64): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (43-60): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_overflow_value.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_overflow_value.sol index ece4273bb..9901af417 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_overflow_value.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_overflow_value.sol @@ -1,4 +1,5 @@ contract A layout at 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 1 {} contract B layout at 2**256 {} // ---- -// UnimplementedFeatureError 1834: (0-94): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6753: (21-91): The base slot of the storage layout evaluates to 2**256, which is outside the range of type uint256. +// TypeError 6753: (116-122): The base slot of the storage layout evaluates to 2**256, which is outside the range of type uint256. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_underflow_value.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_underflow_value.sol index 953d791cc..e1f1b0914 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_underflow_value.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_underflow_value.sol @@ -1,4 +1,5 @@ contract A layout at 0 - 1 {} contract B layout at 2**8 - 2**16 {} // ---- -// UnimplementedFeatureError 1834: (0-29): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6753: (21-26): The base slot of the storage layout evaluates to -1, which is outside the range of type uint256. +// TypeError 6753: (51-63): The base slot of the storage layout evaluates to -65280, which is outside the range of type uint256. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_attached_library_function.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_attached_library_function.sol index b586a271e..6c38d1598 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_attached_library_function.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_attached_library_function.sol @@ -9,4 +9,4 @@ contract C layout at 2.f() { using L for *; } // ---- -// UnimplementedFeatureError 1834: (96-145): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (117-122): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol index 93271e125..d341a5a76 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol @@ -1,3 +1,3 @@ contract C layout at uint64(bytes8(bytes.concat("ABCD", "EFGH"))) {} // ---- -// UnimplementedFeatureError 1834: (0-68): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (21-65): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_expression_not_pure.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_expression_not_pure.sol index cbb4e5ed9..c7a72f727 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_expression_not_pure.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_expression_not_pure.sol @@ -1,5 +1,4 @@ function f(uint x) returns (uint) { return x + 1; } contract A layout at f(2) {} // ---- -// Warning 2018: (0-51): Function state mutability can be restricted to pure -// UnimplementedFeatureError 1834: (52-80): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (73-77): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol index 0549c9d60..77b1ed617 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol @@ -3,4 +3,6 @@ contract B is A {} contract C is B {} contract D is C {} // ---- -// UnimplementedFeatureError 1834: (0-26): Code generation is not supported for contracts with specified storage layout base. +// TypeError 8894: (27-45): Storage layout can only be specified in the most derived contract. +// TypeError 8894: (46-64): Storage layout can only be specified in the most derived contract. +// TypeError 8894: (65-83): Storage layout can only be specified in the most derived contract. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol index aca167f6b..f0b2a2b68 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_with_call_options.sol @@ -3,4 +3,4 @@ contract A { } contract C is A layout at this.f{value:123}() {} // ---- -// UnimplementedFeatureError 1834: (67-115): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (93-112): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol index c8bc2abbc..12304ba8a 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol @@ -2,4 +2,4 @@ interface I {} contract C layout at uint(bytes32(type(I).interfaceId)) { } // ---- -// UnimplementedFeatureError 1834: (16-75): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (37-71): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol index 14fb09b10..539a59c11 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol @@ -1,3 +1,3 @@ contract C layout at uint(keccak256(bytes.concat("ABCD"))) {} // ---- -// UnimplementedFeatureError 1834: (0-61): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (21-58): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol index 2a783a813..0c42f3550 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol @@ -3,4 +3,4 @@ contract B is A {} contract C is B layout at 42 {} contract D is C {} // ---- -// UnimplementedFeatureError 1834: (33-64): Code generation is not supported for contracts with specified storage layout base. +// TypeError 8894: (65-83): Storage layout can only be specified in the most derived contract. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol index 57d51d587..ee4807304 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol @@ -6,4 +6,4 @@ import "A" as MyModule; contract C layout at MyModule {} // ---- -// UnimplementedFeatureError 1834: (B:25-57): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (B:46-54): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol index ee695075e..035e43d24 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol @@ -1,4 +1,4 @@ contract A {} contract C layout at A(address(0x1234)) {} // ---- -// UnimplementedFeatureError 1834: (14-56): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (35-53): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol index 47ae6f0b4..4d48e410f 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol @@ -1,3 +1,3 @@ contract A layout at uint {} // ---- -// UnimplementedFeatureError 1834: (0-28): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-25): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol index d5bd3825e..0f682d779 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol @@ -1,3 +1,3 @@ contract at layout at uint(42) { } // ---- -// UnimplementedFeatureError 1834: (0-34): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (22-30): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/magic_variables.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/magic_variables.sol index 44798fdbf..0558e28db 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/magic_variables.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/magic_variables.sol @@ -4,4 +4,8 @@ contract C layout at msg {} contract D layout at tx {} contract E layout at block {} // ---- -// UnimplementedFeatureError 1834: (0-28): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (21-25): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (50-55): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (80-83): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (108-110): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (135-140): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/negative_number.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/negative_number.sol index 79d8b395b..9e3111f88 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/negative_number.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/negative_number.sol @@ -1,3 +1,3 @@ contract A layout at -1 {} // ---- -// UnimplementedFeatureError 1834: (0-26): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6753: (21-23): The base slot of the storage layout evaluates to -1, which is outside the range of type uint256. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol index a7e9ee089..c87a98eaa 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol @@ -1,4 +1,5 @@ contract A layout at addmod(1, 2, 3) {} contract B layout at mulmod(3, 2, 1) {} // ---- -// UnimplementedFeatureError 1834: (0-39): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-36): The base slot of the storage layout must evaluate to a rational number. +// TypeError 6396: (61-76): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_from_base_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_from_base_contract.sol index 67e63924b..92c0b1147 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_from_base_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_from_base_contract.sol @@ -4,4 +4,4 @@ contract A { contract C is A layout at A.x {} // ---- -// UnimplementedFeatureError 1834: (40-72): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (66-69): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_getter_from_base_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_getter_from_base_contract.sol index 11c8f449c..70e3e4419 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_getter_from_base_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/state_variable_getter_from_base_contract.sol @@ -4,4 +4,4 @@ contract A { contract C is A layout at this.x() {} // ---- -// UnimplementedFeatureError 1834: (40-77): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (66-74): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol index 7f41e64cb..3b8292fe8 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol @@ -1,3 +1,3 @@ contract C layout at "MyLayoutBase" {} // ---- -// UnimplementedFeatureError 1834: (0-38): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-35): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_defined_in_other_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_defined_in_other_contract.sol index 4f74c4545..bb1bcc0e1 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_defined_in_other_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/struct_defined_in_other_contract.sol @@ -8,4 +8,4 @@ contract A { contract C is A layout at A.SA { } // ---- -// UnimplementedFeatureError 1834: (89-123): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (115-119): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol index 5052d8375..f426104cc 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol @@ -1,4 +1,5 @@ contract A layout at true ? 42 : 94 {} contract B layout at 255 + (true ? 1 : 0) {} // ---- -// UnimplementedFeatureError 1834: (0-38): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-35): The base slot of the storage layout must evaluate to a rational number. +// TypeError 6396: (60-80): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol index 0dbc2b371..eb4693e48 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol @@ -1,3 +1,3 @@ contract C layout at (1, 2, 3) {} // ---- -// UnimplementedFeatureError 1834: (0-33): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-30): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol index 54ebb32c7..dd8ee6f9c 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol @@ -1,3 +1,3 @@ contract at layout at type(uint).max { } // ---- -// UnimplementedFeatureError 1834: (0-40): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (22-36): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_operators.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_operators.sol index e044a6aad..14259fd3d 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_operators.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_operators.sol @@ -7,6 +7,4 @@ function add(MyUint a, MyUint b) pure returns (MyUint) { contract C layout at MyUint.wrap(1) + MyUint.wrap(2) {} // ---- -// Warning 5667: (71-79): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning 5667: (81-89): Unused function parameter. Remove or comment out the variable name to silence this warning. -// UnimplementedFeatureError 1834: (145-200): Code generation is not supported for contracts with specified storage layout base. +// TypeError 1139: (166-197): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol index 9287e5a3b..980364168 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol @@ -2,4 +2,4 @@ type MyUint is uint128; MyUint constant x = MyUint.wrap(42); contract C layout at x {} // ---- -// UnimplementedFeatureError 1834: (61-86): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (82-83): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol index a232939c7..b45ee88dd 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol @@ -2,4 +2,4 @@ type MyUint is uint128; MyUint constant x = MyUint.wrap(42); contract C layout at MyUint.unwrap(x) {} // ---- -// UnimplementedFeatureError 1834: (61-101): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (82-98): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol index e057b6940..172fb58ab 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol @@ -1,4 +1,4 @@ type MyUint is uint128; contract C layout at MyUint.wrap(42) {} // ---- -// UnimplementedFeatureError 1834: (24-63): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (45-60): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol index cce2bfbe9..bb56de728 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol @@ -1,4 +1,5 @@ contract A layout at [1, 2, 3][0] {} contract B layout at 255 + [1, 2, 3][0] {} // ---- -// UnimplementedFeatureError 1834: (0-36): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (21-33): The base slot of the storage layout must evaluate to a rational number. +// TypeError 6396: (58-76): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol index 73fcdc485..1f08fa0ec 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol @@ -1,4 +1,4 @@ bytes32 constant b = "Solidity"; contract C layout at uint8(b[1]) {} // ---- -// UnimplementedFeatureError 1834: (33-68): Code generation is not supported for contracts with specified storage layout base. +// TypeError 6396: (54-65): The base slot of the storage layout must evaluate to a rational number. From bff760504bbe92921f7bdd728b03714a82e1e175 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 10 Feb 2025 19:36:10 +0100 Subject: [PATCH 0732/1340] Support for SWAPN/DUPN in EVM Code Transform. --- libevmasm/GasMeter.cpp | 44 +++++-- libevmasm/GasMeter.h | 11 +- libyul/backends/evm/EVMDialect.h | 1 + .../evm/OptimizedEVMCodeTransform.cpp | 46 +++++-- .../backends/evm/OptimizedEVMCodeTransform.h | 4 + libyul/backends/evm/StackHelpers.h | 36 ++++-- libyul/backends/evm/StackLayoutGenerator.cpp | 115 +++++++++++------- libyul/backends/evm/StackLayoutGenerator.h | 27 +++- libyul/optimiser/StackCompressor.cpp | 4 +- libyul/optimiser/StackLimitEvader.cpp | 2 +- test/libyul/StackLayoutGeneratorTest.cpp | 6 +- test/libyul/StackShufflingTest.cpp | 3 +- 12 files changed, 215 insertions(+), 84 deletions(-) diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index 1eff35fb2..fde0819da 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -263,12 +263,11 @@ GasMeter::GasConsumption GasMeter::memoryGas(int _stackPosOffset, int _stackPosS })); } -unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVersion) +namespace { - if (_instruction == Instruction::JUMPDEST) - return 1; - - switch (instructionInfo(_instruction, _evmVersion).gasPriceTier) +std::optional gasCostForTier(Tier _tier) +{ + switch (_tier) { case Tier::Zero: return GasCosts::tier0Gas; case Tier::Base: return GasCosts::tier1Gas; @@ -286,10 +285,21 @@ unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVer case Tier::Special: case Tier::Invalid: - assertThrow(false, OptimizerException, "Invalid gas tier for instruction " + instructionInfo(_instruction, _evmVersion).name); + return std::nullopt; } util::unreachable(); } +} + +unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVersion) +{ + if (_instruction == Instruction::JUMPDEST) + return 1; + + if (auto gasCost = gasCostForTier(instructionInfo(_instruction, _evmVersion).gasPriceTier)) + return *gasCost; + solAssert(false, "Invalid gas tier for instruction " + instructionInfo(_instruction, _evmVersion).name); +} unsigned GasMeter::pushGas(u256 _value, langutil::EVMVersion _evmVersion) { @@ -299,6 +309,24 @@ unsigned GasMeter::pushGas(u256 _value, langutil::EVMVersion _evmVersion) ); } +unsigned GasMeter::swapGas(size_t _depth, langutil::EVMVersion _evmVersion) +{ + if (_depth <= 16) + return runGas(evmasm::swapInstruction(static_cast(_depth)), _evmVersion); + auto gasCost = gasCostForTier(instructionInfo(evmasm::Instruction::SWAPN, _evmVersion).gasPriceTier); + solAssert(gasCost.has_value(), "Expected gas cost for SWAPN to be defined."); + return *gasCost; +} + +unsigned GasMeter::dupGas(size_t _depth, langutil::EVMVersion _evmVersion) +{ + if (_depth <= 16) + return runGas(evmasm::swapInstruction(static_cast(_depth)), _evmVersion); + auto gasCost = gasCostForTier(instructionInfo(evmasm::Instruction::DUPN, _evmVersion).gasPriceTier); + solAssert(gasCost.has_value(), "Expected gas cost for DUPN to be defined."); + return *gasCost; +} + u256 GasMeter::dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersion _evmVersion) { bigint gas = 0; @@ -309,7 +337,7 @@ u256 GasMeter::dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersio } else gas = bigint(GasCosts::createDataGas) * _data.size(); - assertThrow(gas < bigint(u256(-1)), OptimizerException, "Gas cost exceeds 256 bits."); + solAssert(gas < bigint(u256(-1)), "Gas cost exceeds 256 bits."); return u256(gas); } @@ -317,6 +345,6 @@ u256 GasMeter::dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersio u256 GasMeter::dataGas(uint64_t _length, bool _inCreation, langutil::EVMVersion _evmVersion) { bigint gas = bigint(_length) * (_inCreation ? GasCosts::txDataNonZeroGas(_evmVersion) : GasCosts::createDataGas); - assertThrow(gas < bigint(u256(-1)), OptimizerException, "Gas cost exceeds 256 bits."); + solAssert(gas < bigint(u256(-1)), "Gas cost exceeds 256 bits."); return u256(gas); } diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index f202b358e..286999e5c 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -226,9 +226,18 @@ class GasMeter /// change with EVM versions) static unsigned runGas(Instruction _instruction, langutil::EVMVersion _evmVersion); - /// @returns gas costs for push instructions (may change depending on EVM version) + /// @returns gas costs for the cheapest push instructions for the given @a _value + /// (may change depending on EVM version) static unsigned pushGas(u256 _value, langutil::EVMVersion _evmVersion); + /// @returns gas costs for the cheapest swap instructions for the given @a _depth + /// (may change depending on EVM version) + static unsigned swapGas(size_t _depth, langutil::EVMVersion _evmVersion); + + /// @returns gas costs for the cheapest dup instructions for the given @a _depth + /// (may change depending on EVM version) + static unsigned dupGas(size_t _depth, langutil::EVMVersion _evmVersion); + /// @returns the gas cost of the supplied data, depending whether it is in creation code, or not. /// In case of @a _inCreation, the data is only sent as a transaction and is not stored, whereas /// otherwise code will be stored and have to pay "createDataGas" cost. diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 5d5ea90a9..0440daade 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -104,6 +104,7 @@ class EVMDialect: public Dialect langutil::EVMVersion evmVersion() const { return m_evmVersion; } std::optional eofVersion() const { return m_eofVersion; } + size_t reachableStackDepth() const { return m_eofVersion.has_value() ? 256 : 16; } bool providesObjectAccess() const { return m_objectAccess; } diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index bd5c55a3c..07ab758d7 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -23,6 +23,7 @@ #include +#include #include #include @@ -48,7 +49,7 @@ std::vector OptimizedEVMCodeTransform::run( ) { std::unique_ptr dfg = ControlFlowGraphBuilder::build(_analysisInfo, _dialect, _block); - StackLayout stackLayout = StackLayoutGenerator::run(*dfg, !_dialect.eofVersion().has_value()); + StackLayout stackLayout = StackLayoutGenerator::run(*dfg, !_dialect.eofVersion().has_value(), _dialect.reachableStackDepth()); if (_dialect.eofVersion().has_value()) { @@ -229,7 +230,8 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( } return functionLabels; }()), - m_simulateFunctionsWithJumps(_simulateFunctionsWithJumps) + m_simulateFunctionsWithJumps(_simulateFunctionsWithJumps), + m_reachableStackDepth(_dialect.reachableStackDepth()) { } @@ -285,11 +287,11 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr { yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight(), ""); yulAssert(_i > 0 && _i < m_stack.size(), ""); - if (_i <= 16) - m_assembly.appendInstruction(evmasm::swapInstruction(_i)); + if (_i <= m_reachableStackDepth) + appendSwap(_i); else { - int deficit = static_cast(_i) - 16; + int deficit = static_cast(_i) - static_cast(m_reachableStackDepth); StackSlot const& deepSlot = m_stack.at(m_stack.size() - _i - 1); YulName varNameDeep = slotVariableName(deepSlot); YulName varNameTop = slotVariableName(m_stack.back()); @@ -310,22 +312,21 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr [&](StackSlot const& _slot) { yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight(), ""); - // Dup the slot, if already on stack and reachable. if (auto depth = util::findOffset(m_stack | ranges::views::reverse, _slot)) { - if (*depth < 16) + if (*depth < m_reachableStackDepth) { - m_assembly.appendInstruction(evmasm::dupInstruction(static_cast(*depth + 1))); + appendDup(*depth + 1); return; } else if (!canBeFreelyGenerated(_slot)) { - int deficit = static_cast(*depth - 15); + int deficit = static_cast(*depth - (m_reachableStackDepth - 1)); YulName varName = slotVariableName(_slot); std::string msg = (varName.empty() ? "Slot " + stackSlotToString(_slot, m_dialect) : "Variable " + varName.str()) - + " is " + std::to_string(*depth - 15) + " too deep in the stack " + stackToString(m_stack, m_dialect); + + " is " + std::to_string(*depth - (m_reachableStackDepth - 1)) + " too deep in the stack " + stackToString(m_stack, m_dialect); m_stackErrors.emplace_back(StackTooDeepError( m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulName{}, varName, @@ -388,11 +389,34 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr [&]() { m_assembly.appendInstruction(evmasm::Instruction::POP); - } + }, + m_reachableStackDepth ); yulAssert(m_assembly.stackHeight() == static_cast(m_stack.size()), ""); } +void OptimizedEVMCodeTransform::appendSwap(size_t _depth) +{ + if (_depth <= 16) + m_assembly.appendInstruction(evmasm::swapInstruction(static_cast(_depth))); + else + { + yulAssert(_depth <= m_reachableStackDepth); + m_assembly.appendSwapN(_depth); + } +} + +void OptimizedEVMCodeTransform::appendDup(size_t _depth) +{ + if (_depth <= 16) + m_assembly.appendInstruction(evmasm::dupInstruction(static_cast(_depth))); + else + { + yulAssert(_depth <= m_reachableStackDepth); + m_assembly.appendDupN(_depth); + } +} + void OptimizedEVMCodeTransform::operator()(CFG::BasicBlock const& _block) { // Assert that this is the first visit of the block and mark as generated. diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.h b/libyul/backends/evm/OptimizedEVMCodeTransform.h index 88ecc2967..2cb251fba 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.h +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.h @@ -87,6 +87,9 @@ class OptimizedEVMCodeTransform /// Sets the source locations to the one in @a _debugData. void createStackLayout(langutil::DebugData::ConstPtr _debugData, Stack _targetStack); + void appendSwap(size_t _depth); + void appendDup(size_t _depth); + /// Generate code for the given block @a _block. /// Expects the current stack layout m_stack to be a stack layout that is compatible with the /// entry layout expected by the block. @@ -116,6 +119,7 @@ class OptimizedEVMCodeTransform std::vector m_stackErrors; /// True if it simulates functions with jumps. False otherwise. True for legacy bytecode bool m_simulateFunctionsWithJumps = true; + size_t const m_reachableStackDepth{}; }; } diff --git a/libyul/backends/evm/StackHelpers.h b/libyul/backends/evm/StackHelpers.h index 0fd238c40..c5d638471 100644 --- a/libyul/backends/evm/StackHelpers.h +++ b/libyul/backends/evm/StackHelpers.h @@ -56,7 +56,6 @@ inline std::string stackToString(Stack const& _stack, Dialect const& _dialect) } -// Abstraction of stack shuffling operations. Can be defined as actual concept once we switch to C++20. // Used as an interface for the stack shuffler below. // The shuffle operation class is expected to internally keep track of a current stack layout (the "source layout") // that the shuffler is supposed to shuffle to a fixed target stack layout. @@ -65,7 +64,6 @@ inline std::string stackToString(Stack const& _stack, Dialect const& _dialect) // in the interface below. // Based on that information the shuffler decides which is the next optimal operation to perform on the stack // and calls the corresponding entry point in the shuffling operations (swap, pushOrDupTarget or pop). -/* template concept ShuffleOperationConcept = requires(ShuffleOperations ops, size_t sourceOffset, size_t targetOffset, size_t depth) { // Returns true, iff the current slot at sourceOffset in source layout is a suitable slot at targetOffset. @@ -98,11 +96,13 @@ concept ShuffleOperationConcept = requires(ShuffleOperations ops, size_t sourceO { ops.pop() }; // Dups or pushes the slot that is supposed to end up at the given target offset. { ops.pushOrDupTarget(targetOffset) }; + // Maximum reachable depth with swaps and dups. + { ops.reachableStackDepth } -> std::convertible_to; }; -*/ + /// Helper class that can perform shuffling of a source stack layout to a target stack layout via /// abstracted shuffle operations. -template +template class Shuffler { public: @@ -128,10 +128,10 @@ class Shuffler static bool dupDeepSlotIfRequired(ShuffleOperations& _ops) { // Check if the stack is large enough for anything to potentially become unreachable. - if (_ops.sourceSize() < 15) + if (_ops.sourceSize() < (_ops.reachableStackDepth - 1)) return false; // Check whether any deep slot might still be needed later (i.e. we still need to reach it with a DUP or SWAP). - for (size_t sourceOffset: ranges::views::iota(0u, _ops.sourceSize() - 15)) + for (size_t sourceOffset: ranges::views::iota(0u, _ops.sourceSize() - (_ops.reachableStackDepth - 1))) { // This slot needs to be moved. if (!_ops.isCompatible(sourceOffset, sourceOffset)) @@ -256,10 +256,10 @@ class Shuffler ) { // We cannot swap that deep. - if (ops.sourceSize() - offset - 1 > 16) + if (ops.sourceSize() - offset - 1 > ops.reachableStackDepth) { // If there is a reachable slot to be removed, park the current top there. - for (size_t swapDepth: ranges::views::iota(1u, 17u) | ranges::views::reverse) + for (size_t swapDepth: ranges::views::iota(1u, ops.reachableStackDepth + 1u) | ranges::views::reverse) if (ops.sourceMultiplicity(ops.sourceSize() - 1 - swapDepth) < 0) { ops.swap(swapDepth); @@ -327,7 +327,7 @@ class Shuffler yulAssert(ops.sourceMultiplicity(i) == 0 && (ops.targetIsArbitrary(i) || ops.targetMultiplicity(i) == 0), ""); yulAssert(ops.isCompatible(sourceTop, sourceTop), ""); - auto swappableOffsets = ranges::views::iota(size > 17 ? size - 17 : 0u, size); + auto swappableOffsets = ranges::views::iota(size > ops.reachableStackDepth + 1u ? size - (ops.reachableStackDepth + 1u) : 0u, size); // If we find a lower slot that is out of position, but also compatible with the top, swap that up. for (size_t offset: swappableOffsets) @@ -431,7 +431,14 @@ class Multiplicity /// its argument to the stack top. /// @a _pop is a function with signature void() that is called when the top most slot is popped. template -void createStackLayout(Stack& _currentStack, Stack const& _targetStack, Swap _swap, PushOrDup _pushOrDup, Pop _pop) +void createStackLayout( + Stack& _currentStack, + Stack const& _targetStack, + Swap _swap, + PushOrDup _pushOrDup, + Pop _pop, + size_t _reachableStackDepth +) { struct ShuffleOperations { @@ -441,18 +448,21 @@ void createStackLayout(Stack& _currentStack, Stack const& _targetStack, Swap _sw PushOrDup pushOrDupCallback; Pop popCallback; Multiplicity multiplicity; + size_t reachableStackDepth; ShuffleOperations( Stack& _currentStack, Stack const& _targetStack, Swap _swap, PushOrDup _pushOrDup, - Pop _pop + Pop _pop, + size_t _reachableStackDepth ): currentStack(_currentStack), targetStack(_targetStack), swapCallback(_swap), pushOrDupCallback(_pushOrDup), - popCallback(_pop) + popCallback(_pop), + reachableStackDepth(_reachableStackDepth) { for (auto const& slot: currentStack) --multiplicity[slot]; @@ -499,7 +509,7 @@ void createStackLayout(Stack& _currentStack, Stack const& _targetStack, Swap _sw } }; - Shuffler::shuffle(_currentStack, _targetStack, _swap, _pushOrDup, _pop); + Shuffler::shuffle(_currentStack, _targetStack, _swap, _pushOrDup, _pop, _reachableStackDepth); yulAssert(_currentStack.size() == _targetStack.size(), ""); for (auto&& [current, target]: ranges::zip_view(_currentStack, _targetStack)) diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index ecaa4198b..6abb1bb9f 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -45,28 +45,47 @@ using namespace solidity; using namespace solidity::yul; -StackLayout StackLayoutGenerator::run(CFG const& _cfg, bool _simulateFunctionsWithJumps) +StackLayout StackLayoutGenerator::run(CFG const& _cfg, bool _simulateFunctionsWithJumps, size_t _reachableStackDepth) { StackLayout stackLayout{{}, {}}; - StackLayoutGenerator{stackLayout, nullptr, _simulateFunctionsWithJumps}.processEntryPoint(*_cfg.entry); + StackLayoutGenerator{ + stackLayout, + nullptr, + _simulateFunctionsWithJumps, + _reachableStackDepth + }.processEntryPoint(*_cfg.entry); for (auto& functionInfo: _cfg.functionInfo | ranges::views::values) - StackLayoutGenerator{stackLayout, &functionInfo, _simulateFunctionsWithJumps}.processEntryPoint(*functionInfo.entry, &functionInfo); + StackLayoutGenerator{ + stackLayout, + &functionInfo, + _simulateFunctionsWithJumps, + _reachableStackDepth + }.processEntryPoint(*functionInfo.entry, &functionInfo); return stackLayout; } -std::map> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, bool _simulateFunctionsWithJumps) +std::map> StackLayoutGenerator::reportStackTooDeep( + CFG const& _cfg, + bool _simulateFunctionsWithJumps, + size_t _reachableStackDepth +) { std::map> stackTooDeepErrors; - stackTooDeepErrors[YulName{}] = reportStackTooDeep(_cfg, YulName{}, _simulateFunctionsWithJumps); + stackTooDeepErrors[YulName{}] = reportStackTooDeep(_cfg, YulName{}, _simulateFunctionsWithJumps, _reachableStackDepth); for (auto const& function: _cfg.functions) - if (auto errors = reportStackTooDeep(_cfg, function->name, _simulateFunctionsWithJumps); !errors.empty()) + if (auto errors = reportStackTooDeep(_cfg, function->name, _simulateFunctionsWithJumps, _reachableStackDepth); !errors.empty()) stackTooDeepErrors[function->name] = std::move(errors); return stackTooDeepErrors; } -std::vector StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulName _functionName, bool _simulateFunctionsWithJumps) +std::vector StackLayoutGenerator::reportStackTooDeep( + CFG const& _cfg, + YulName _functionName, + bool _simulateFunctionsWithJumps, + size_t _reachableStackDepth +) { StackLayout stackLayout{{}, {}}; CFG::FunctionInfo const* functionInfo = nullptr; @@ -80,23 +99,33 @@ std::vector StackLayoutGenerator::reportStac yulAssert(functionInfo, "Function not found."); } - StackLayoutGenerator generator{stackLayout, functionInfo, _simulateFunctionsWithJumps}; + StackLayoutGenerator generator{stackLayout, functionInfo, _simulateFunctionsWithJumps, _reachableStackDepth}; CFG::BasicBlock const* entry = functionInfo ? functionInfo->entry : _cfg.entry; generator.processEntryPoint(*entry); return generator.reportStackTooDeep(*entry); } -StackLayoutGenerator::StackLayoutGenerator(StackLayout& _layout, CFG::FunctionInfo const* _functionInfo, bool _simulateFunctionsWithJumps): +StackLayoutGenerator::StackLayoutGenerator( + StackLayout& _layout, + CFG::FunctionInfo const* _functionInfo, + bool _simulateFunctionsWithJumps, + size_t _reachableStackDepth +): m_layout(_layout), m_currentFunctionInfo(_functionInfo), - m_simulateFunctionsWithJumps(_simulateFunctionsWithJumps) + m_simulateFunctionsWithJumps(_simulateFunctionsWithJumps), + m_reachableStackDepth(_reachableStackDepth) { } namespace { /// @returns all stack too deep errors that would occur when shuffling @a _source to @a _target. -std::vector findStackTooDeep(Stack const& _source, Stack const& _target) +std::vector findStackTooDeep( + Stack const& _source, + Stack const& _target, + size_t _reachableStackDepth +) { Stack currentStack = _source; std::vector stackTooDeepErrors; @@ -113,9 +142,9 @@ std::vector findStackTooDeep(Stack const& _s _target, [&](unsigned _i) { - if (_i > 16) + if (_i > _reachableStackDepth) stackTooDeepErrors.emplace_back(StackLayoutGenerator::StackTooDeep{ - _i - 16, + _i - _reachableStackDepth, getVariableChoices(currentStack | ranges::views::take_last(_i + 1)) }); }, @@ -125,14 +154,15 @@ std::vector findStackTooDeep(Stack const& _s return; if ( auto depth = util::findOffset(currentStack | ranges::views::reverse, _slot); - depth && *depth >= 16 + depth && *depth >= _reachableStackDepth ) stackTooDeepErrors.emplace_back(StackLayoutGenerator::StackTooDeep{ - *depth - 15, + *depth - (_reachableStackDepth - 1), getVariableChoices(currentStack | ranges::views::take_last(*depth + 1)) }); }, - [&]() {} + [&]() {}, + _reachableStackDepth ); return stackTooDeepErrors; } @@ -142,7 +172,7 @@ std::vector findStackTooDeep(Stack const& _s /// If @a _generateSlotOnTheFly returns true for a slot, this slot should not occur in the ideal stack, but /// rather be generated on the fly during shuffling. template -Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Callable _generateSlotOnTheFly) +Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Callable _generateSlotOnTheFly, size_t _reachableStackDepth) { struct PreviousSlot { size_t slot; }; @@ -174,11 +204,13 @@ Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Calla std::set outputs; Multiplicity multiplicity; Callable generateSlotOnTheFly; + size_t const reachableStackDepth; ShuffleOperations( std::vector>& _layout, Stack const& _post, - Callable _generateSlotOnTheFly - ): layout(_layout), post(_post), generateSlotOnTheFly(_generateSlotOnTheFly) + Callable _generateSlotOnTheFly, + size_t _reachableStackDepth + ): layout(_layout), post(_post), generateSlotOnTheFly(_generateSlotOnTheFly), reachableStackDepth(_reachableStackDepth) { for (auto const& layoutSlot: layout) if (StackSlot const* slot = std::get_if(&layoutSlot)) @@ -241,7 +273,7 @@ Stack createIdealLayout(Stack const& _operationOutput, Stack const& _post, Calla void pop() { layout.pop_back(); } void pushOrDupTarget(size_t _offset) { layout.push_back(post.at(_offset)); } }; - Shuffler::shuffle(layout, _post, _generateSlotOnTheFly); + Shuffler::shuffle(layout, _post, _generateSlotOnTheFly, _reachableStackDepth); // Now we can construct the ideal layout before the operation. // "layout" has shuffled the PreviousSlot{x} to new places using minimal operations to move the operation @@ -280,7 +312,7 @@ Stack StackLayoutGenerator::propagateStackThroughOperation(Stack _exitStack, CFG // Determine the ideal permutation of the slots in _exitLayout that are not operation outputs (and not to be // generated on the fly), s.t. shuffling the `stack + _operation.output` to _exitLayout is cheap. - Stack stack = createIdealLayout(_operation.output, _exitStack, generateSlotOnTheFly); + Stack stack = createIdealLayout(_operation.output, _exitStack, generateSlotOnTheFly, m_reachableStackDepth); // Make sure the resulting previous slots do not overlap with any assignmed variables. if (auto const* assignment = std::get_if(&_operation.operation)) @@ -304,7 +336,7 @@ Stack StackLayoutGenerator::propagateStackThroughOperation(Stack _exitStack, CFG stack.pop_back(); else if (auto offset = util::findOffset(stack | ranges::views::reverse | ranges::views::drop(1), stack.back())) { - if (*offset + 2 < 16) + if (*offset + 2 < m_reachableStackDepth) stack.pop_back(); else break; @@ -322,7 +354,7 @@ Stack StackLayoutGenerator::propagateStackThroughBlock(Stack _exitStack, CFG::Ba for (auto&& [idx, operation]: _block.operations | ranges::views::enumerate | ranges::views::reverse) { Stack newStack = propagateStackThroughOperation(stack, operation, _aggressiveStackCompression); - if (!_aggressiveStackCompression && !findStackTooDeep(newStack, stack).empty()) + if (!_aggressiveStackCompression && !findStackTooDeep(newStack, stack, m_reachableStackDepth).empty()) // If we had stack errors, run again with aggressive stack compression. return propagateStackThroughBlock(std::move(_exitStack), _block, true); stack = std::move(newStack); @@ -443,7 +475,8 @@ std::optional StackLayoutGenerator::getExitLayoutOrStageDependencies( // If the current iteration has already visited both jump targets, start from its entry layout. Stack stack = combineStack( m_layout.blockInfos.at(_conditionalJump.zero).entryLayout, - m_layout.blockInfos.at(_conditionalJump.nonZero).entryLayout + m_layout.blockInfos.at(_conditionalJump.nonZero).entryLayout, + m_reachableStackDepth ); // Additionally, the jump condition has to be at the stack top at exit. stack.emplace_back(_conditionalJump.condition); @@ -546,7 +579,7 @@ void StackLayoutGenerator::stitchConditionalJumps(CFG::BasicBlock const& _block) }); } -Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _stack2) +Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _stack2, size_t _reachableStackDepth) { // TODO: it would be nicer to replace this by a constructive algorithm. // Currently it uses a reduced version of the Heap Algorithm to partly brute-force, which seems @@ -564,9 +597,9 @@ Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _sta Stack stack2Tail = _stack2 | ranges::views::drop(commonPrefix.size()) | ranges::to; if (stack1Tail.empty()) - return commonPrefix + compressStack(stack2Tail); + return commonPrefix + compressStack(stack2Tail, _reachableStackDepth); if (stack2Tail.empty()) - return commonPrefix + compressStack(stack1Tail); + return commonPrefix + compressStack(stack1Tail, _reachableStackDepth); Stack candidate; for (auto slot: stack1Tail) @@ -582,18 +615,18 @@ Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _sta auto evaluate = [&](Stack const& _candidate) -> size_t { size_t numOps = 0; Stack testStack = _candidate; - auto swap = [&](unsigned _swapDepth) { ++numOps; if (_swapDepth > 16) numOps += 1000; }; + auto swap = [&](unsigned _swapDepth) { ++numOps; if (_swapDepth > _reachableStackDepth) numOps += 1000; }; auto dupOrPush = [&](StackSlot const& _slot) { if (canBeFreelyGenerated(_slot)) return; auto depth = util::findOffset(ranges::concat_view(commonPrefix, testStack) | ranges::views::reverse, _slot); - if (depth && *depth >= 16) + if (depth && *depth >= _reachableStackDepth) numOps += 1000; }; - createStackLayout(testStack, stack1Tail, swap, dupOrPush, [&](){}); + createStackLayout(testStack, stack1Tail, swap, dupOrPush, [&](){}, _reachableStackDepth); testStack = _candidate; - createStackLayout(testStack, stack2Tail, swap, dupOrPush, [&](){}); + createStackLayout(testStack, stack2Tail, swap, dupOrPush, [&](){}, _reachableStackDepth); return numOps; }; @@ -644,7 +677,7 @@ std::vector StackLayoutGenerator::reportStac { Stack& operationEntry = m_layout.operationEntryLayout.at(&operation); - stackTooDeepErrors += findStackTooDeep(currentStack, operationEntry); + stackTooDeepErrors += findStackTooDeep(currentStack, operationEntry, m_reachableStackDepth); currentStack = operationEntry; for (size_t i = 0; i < operation.input.size(); i++) currentStack.pop_back(); @@ -658,7 +691,7 @@ std::vector StackLayoutGenerator::reportStac [&](CFG::BasicBlock::Jump const& _jump) { Stack const& targetLayout = m_layout.blockInfos.at(_jump.target).entryLayout; - stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout); + stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout, m_reachableStackDepth); if (!_jump.backwards) _addChild(_jump.target); @@ -669,7 +702,7 @@ std::vector StackLayoutGenerator::reportStac m_layout.blockInfos.at(_conditionalJump.zero).entryLayout, m_layout.blockInfos.at(_conditionalJump.nonZero).entryLayout }) - stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout); + stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout, m_reachableStackDepth); _addChild(_conditionalJump.zero); _addChild(_conditionalJump.nonZero); @@ -681,7 +714,7 @@ std::vector StackLayoutGenerator::reportStac return stackTooDeepErrors; } -Stack StackLayoutGenerator::compressStack(Stack _stack) +Stack StackLayoutGenerator::compressStack(Stack _stack, size_t _reachableStackDepth) { std::optional firstDupOffset; do @@ -699,7 +732,7 @@ Stack StackLayoutGenerator::compressStack(Stack _stack) break; } else if (auto dupDepth = util::findOffset(_stack | ranges::views::reverse | ranges::views::drop(depth + 1), slot)) - if (depth + *dupDepth <= 16) + if (depth + *dupDepth <= _reachableStackDepth) { firstDupOffset = _stack.size() - depth - 1; break; @@ -746,10 +779,10 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi size_t opGas = 0; auto swap = [&](unsigned _swapDepth) { - if (_swapDepth > 16) + if (_swapDepth > m_reachableStackDepth) opGas += 1000; else - opGas += evmasm::GasMeter::runGas(evmasm::swapInstruction(_swapDepth), langutil::EVMVersion()); + opGas += evmasm::GasMeter::swapGas(_swapDepth, langutil::EVMVersion{}); }; auto dupOrPush = [&](StackSlot const& _slot) { @@ -759,8 +792,8 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi { if (auto depth = util::findOffset(_source | ranges::views::reverse, _slot)) { - if (*depth < 16) - opGas += evmasm::GasMeter::runGas(evmasm::dupInstruction(static_cast(*depth + 1)), langutil::EVMVersion()); + if (*depth < m_reachableStackDepth) + opGas += evmasm::GasMeter::dupGas(*depth + 1, langutil::EVMVersion{}); else opGas += 1000; } @@ -777,7 +810,7 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi } }; auto pop = [&]() { opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP,langutil::EVMVersion()); }; - createStackLayout(_source, _target, swap, dupOrPush, pop); + createStackLayout(_source, _target, swap, dupOrPush, pop, m_reachableStackDepth); return opGas; }; /// @returns the number of junk slots to be prepended to @a _targetLayout for an optimal transition from diff --git a/libyul/backends/evm/StackLayoutGenerator.h b/libyul/backends/evm/StackLayoutGenerator.h index 44cbbd43a..9626c7ad1 100644 --- a/libyul/backends/evm/StackLayoutGenerator.h +++ b/libyul/backends/evm/StackLayoutGenerator.h @@ -55,18 +55,32 @@ class StackLayoutGenerator std::vector variableChoices; }; - static StackLayout run(CFG const& _cfg, bool _simulateFunctionsWithJumps); + static StackLayout run(CFG const& _cfg, bool _simulateFunctionsWithJumps, size_t _reachableStackDepth); /// @returns a map from function names to the stack too deep errors occurring in that function. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// The empty string is mapped to the stack too deep errors of the main entry point. - static std::map> reportStackTooDeep(CFG const& _cfg, bool _simulateFunctionsWithJumps); + static std::map> reportStackTooDeep( + CFG const& _cfg, + bool _simulateFunctionsWithJumps, + size_t _reachableStackDepth + ); /// @returns all stack too deep errors in the function named @a _functionName. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// If @a _functionName is empty, the stack too deep errors of the main entry point are reported instead. - static std::vector reportStackTooDeep(CFG const& _cfg, YulName _functionName, bool _simulateFunctionsWithJumps); + static std::vector reportStackTooDeep( + CFG const& _cfg, + YulName _functionName, + bool _simulateFunctionsWithJumps, + size_t _reachableStackDepth + ); private: - StackLayoutGenerator(StackLayout& _context, CFG::FunctionInfo const* _functionInfo, bool _simulateFunctionsWithJumps); + StackLayoutGenerator( + StackLayout& _context, + CFG::FunctionInfo const* _functionInfo, + bool _simulateFunctionsWithJumps, + size_t _reachableStackDepth + ); /// @returns the optimal entry stack layout, s.t. @a _operation can be applied to it and /// the result can be transformed to @a _exitStack with minimal stack shuffling. @@ -100,7 +114,7 @@ class StackLayoutGenerator /// Calculates the ideal stack layout, s.t. both @a _stack1 and @a _stack2 can be achieved with minimal /// stack shuffling when starting from the returned layout. - static Stack combineStack(Stack const& _stack1, Stack const& _stack2); + static Stack combineStack(Stack const& _stack1, Stack const& _stack2, size_t _reachableStackDepth); /// Walks through the CFG and reports any stack too deep errors that would occur when generating code for it /// without countermeasures. @@ -109,7 +123,7 @@ class StackLayoutGenerator /// @returns a copy of @a _stack stripped of all duplicates and slots that can be freely generated. /// Attempts to create a layout that requires a minimal amount of operations to reconstruct the original /// stack @a _stack. - static Stack compressStack(Stack _stack); + static Stack compressStack(Stack _stack, size_t _reachableStackDepth); //// Fills in junk when entering branches that do not need a clean stack in case the result is cheaper. void fillInJunk(CFG::BasicBlock const& _block, CFG::FunctionInfo const* _functionInfo = nullptr); @@ -118,6 +132,7 @@ class StackLayoutGenerator CFG::FunctionInfo const* m_currentFunctionInfo = nullptr; /// True if it simulates functions with jumps. False otherwise. True for legacy bytecode bool m_simulateFunctionsWithJumps = true; + size_t const m_reachableStackDepth{}; }; } diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index ae91716e5..1dac1a66f 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -249,6 +249,7 @@ std::tuple StackCompressor::run( ); bool usesOptimizedCodeGenerator = false; bool simulateFunctionsWithJumps = true; + size_t reachableStackDepth = 16; if (auto evmDialect = dynamic_cast(_object.dialect())) { usesOptimizedCodeGenerator = @@ -256,6 +257,7 @@ std::tuple StackCompressor::run( evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); + reachableStackDepth = evmDialect->reachableStackDepth(); } bool allowMSizeOptimization = !MSizeFinder::containsMSize(*_object.dialect(), _object.code()->root()); Block astRoot = std::get(ASTCopier{}(_object.code()->root())); @@ -270,7 +272,7 @@ std::tuple StackCompressor::run( eliminateVariablesOptimizedCodegen( *_object.dialect(), astRoot, - StackLayoutGenerator::reportStackTooDeep(*cfg, simulateFunctionsWithJumps), + StackLayoutGenerator::reportStackTooDeep(*cfg, simulateFunctionsWithJumps, reachableStackDepth), allowMSizeOptimization ); } diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 766cd4928..d62b3e935 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -141,7 +141,7 @@ Block StackLimitEvader::run( _object.summarizeStructure() ); std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, astRoot); - run(_context, astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg, !evmDialect->eofVersion().has_value())); + run(_context, astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg, !evmDialect->eofVersion().has_value(), evmDialect->reachableStackDepth())); } else { diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 0db063740..841872933 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -233,10 +233,14 @@ TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::s ); bool simulateFunctionsWithJumps = true; + size_t reachableStackDepth = 16; if (auto const* evmDialect = dynamic_cast(&yulStack.dialect())) + { simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); + reachableStackDepth = evmDialect->reachableStackDepth(); + } - StackLayout stackLayout = StackLayoutGenerator::run(*cfg, simulateFunctionsWithJumps); + StackLayout stackLayout = StackLayoutGenerator::run(*cfg, simulateFunctionsWithJumps, reachableStackDepth); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; StackLayoutPrinter printer{output, stackLayout, yulStack.dialect()}; diff --git a/test/libyul/StackShufflingTest.cpp b/test/libyul/StackShufflingTest.cpp index 258bc9204..a58510a41 100644 --- a/test/libyul/StackShufflingTest.cpp +++ b/test/libyul/StackShufflingTest.cpp @@ -174,7 +174,8 @@ TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string [&](){ // pop output << stackToString(m_sourceStack, dialect) << std::endl; output << "POP" << std::endl; - } + }, + 16u // TODO: make it a test setting ); output << stackToString(m_sourceStack, dialect) << std::endl; From 44c0697fce86c5352ca491a498ea7d9fcf8adb32 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 17 Feb 2025 18:31:20 +0100 Subject: [PATCH 0733/1340] Test cases for SWAPN, DUPN and related stack shuffling. --- test/libyul/StackLayoutGeneratorTest.cpp | 11 +- test/libyul/StackShufflingTest.cpp | 18 +- test/libyul/StackShufflingTest.h | 2 + test/libyul/evmCodeTransform/eof_dup256.yul | 2595 +++++++++++++++ test/libyul/evmCodeTransform/eof_swap17.yul | 229 ++ test/libyul/evmCodeTransform/eof_swap256.yul | 2839 +++++++++++++++++ .../pop_early_to_avoid_swap17.stack | 12 + test/libyul/yulStackShuffling/swap17.stack | 13 + .../libyul/yulStackShuffling/swap_cycle.stack | 1 + 9 files changed, 5712 insertions(+), 8 deletions(-) create mode 100644 test/libyul/evmCodeTransform/eof_dup256.yul create mode 100644 test/libyul/evmCodeTransform/eof_swap17.yul create mode 100644 test/libyul/evmCodeTransform/eof_swap256.yul create mode 100644 test/libyul/yulStackShuffling/pop_early_to_avoid_swap17.stack create mode 100644 test/libyul/yulStackShuffling/swap17.stack diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 841872933..86fd6184e 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -232,13 +232,10 @@ TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::s yulStack.parserResult()->code()->root() ); - bool simulateFunctionsWithJumps = true; - size_t reachableStackDepth = 16; - if (auto const* evmDialect = dynamic_cast(&yulStack.dialect())) - { - simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); - reachableStackDepth = evmDialect->reachableStackDepth(); - } + auto const* evmDialect = dynamic_cast(&yulStack.dialect()); + solAssert(evmDialect, "StackLayoutGenerator can only be run on EVM dialects."); + bool simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); + size_t reachableStackDepth = evmDialect->reachableStackDepth(); StackLayout stackLayout = StackLayoutGenerator::run(*cfg, simulateFunctionsWithJumps, reachableStackDepth); diff --git a/test/libyul/StackShufflingTest.cpp b/test/libyul/StackShufflingTest.cpp index a58510a41..58ea124fb 100644 --- a/test/libyul/StackShufflingTest.cpp +++ b/test/libyul/StackShufflingTest.cpp @@ -24,6 +24,7 @@ #include #include +#include using namespace solidity::test; using namespace solidity::util; @@ -136,10 +137,20 @@ bool StackShufflingTest::parse(std::string const& _source) StackShufflingTest::StackShufflingTest(std::string const& _filename): TestCase(_filename) { + processSettings(); m_source = m_reader.source(); m_expectation = m_reader.simpleExpectations(); } +void StackShufflingTest::processSettings() +{ + std::string depthString = m_reader.stringSetting("maximumStackDepth", "16"); + std::optional depth = toUnsignedInt(depthString); + if (!depth.has_value()) + BOOST_THROW_EXCEPTION(std::runtime_error{"Invalid maximum stack depth: \"" + depthString + "\""}); + m_maximumStackDepth = *depth; +} + TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { auto const& dialect = CommonOptions::get().evmDialect(); @@ -150,16 +161,19 @@ TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string } std::ostringstream output; + size_t operations = 0; createStackLayout( m_sourceStack, m_targetStack, [&](unsigned _swapDepth) // swap { + ++operations; output << stackToString(m_sourceStack, dialect) << std::endl; output << "SWAP" << _swapDepth << std::endl; }, [&](StackSlot const& _slot) // dupOrPush { + ++operations; output << stackToString(m_sourceStack, dialect) << std::endl; if (canBeFreelyGenerated(_slot)) output << "PUSH " << stackSlotToString(_slot, dialect) << std::endl; @@ -172,13 +186,15 @@ TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string } }, [&](){ // pop + ++operations; output << stackToString(m_sourceStack, dialect) << std::endl; output << "POP" << std::endl; }, - 16u // TODO: make it a test setting + m_maximumStackDepth ); output << stackToString(m_sourceStack, dialect) << std::endl; + output << operations << " operations" << std::endl; m_obtainedResult = output.str(); return checkResult(_stream, _linePrefix, _formatted); diff --git a/test/libyul/StackShufflingTest.h b/test/libyul/StackShufflingTest.h index 2e2dd12ad..5485ed081 100644 --- a/test/libyul/StackShufflingTest.h +++ b/test/libyul/StackShufflingTest.h @@ -37,8 +37,10 @@ class StackShufflingTest: public TestCase explicit StackShufflingTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: + void processSettings(); bool parse(std::string const& _source); + size_t m_maximumStackDepth{}; Stack m_sourceStack; Stack m_targetStack; std::map m_functions; diff --git a/test/libyul/evmCodeTransform/eof_dup256.yul b/test/libyul/evmCodeTransform/eof_dup256.yul new file mode 100644 index 000000000..a345c7b6d --- /dev/null +++ b/test/libyul/evmCodeTransform/eof_dup256.yul @@ -0,0 +1,2595 @@ +object "main" { + code { + let v0 := calldataload(0) + let v1 := calldataload(1) + let v2 := calldataload(2) + let v3 := calldataload(3) + let v4 := calldataload(4) + let v5 := calldataload(5) + let v6 := calldataload(6) + let v7 := calldataload(7) + let v8 := calldataload(8) + let v9 := calldataload(9) + let v10 := calldataload(10) + let v11 := calldataload(11) + let v12 := calldataload(12) + let v13 := calldataload(13) + let v14 := calldataload(14) + let v15 := calldataload(15) + let v16 := calldataload(16) + let v17 := calldataload(17) + let v18 := calldataload(18) + let v19 := calldataload(19) + let v20 := calldataload(20) + let v21 := calldataload(21) + let v22 := calldataload(22) + let v23 := calldataload(23) + let v24 := calldataload(24) + let v25 := calldataload(25) + let v26 := calldataload(26) + let v27 := calldataload(27) + let v28 := calldataload(28) + let v29 := calldataload(29) + let v30 := calldataload(30) + let v31 := calldataload(31) + let v32 := calldataload(32) + let v33 := calldataload(33) + let v34 := calldataload(34) + let v35 := calldataload(35) + let v36 := calldataload(36) + let v37 := calldataload(37) + let v38 := calldataload(38) + let v39 := calldataload(39) + let v40 := calldataload(40) + let v41 := calldataload(41) + let v42 := calldataload(42) + let v43 := calldataload(43) + let v44 := calldataload(44) + let v45 := calldataload(45) + let v46 := calldataload(46) + let v47 := calldataload(47) + let v48 := calldataload(48) + let v49 := calldataload(49) + let v50 := calldataload(50) + let v51 := calldataload(51) + let v52 := calldataload(52) + let v53 := calldataload(53) + let v54 := calldataload(54) + let v55 := calldataload(55) + let v56 := calldataload(56) + let v57 := calldataload(57) + let v58 := calldataload(58) + let v59 := calldataload(59) + let v60 := calldataload(60) + let v61 := calldataload(61) + let v62 := calldataload(62) + let v63 := calldataload(63) + let v64 := calldataload(64) + let v65 := calldataload(65) + let v66 := calldataload(66) + let v67 := calldataload(67) + let v68 := calldataload(68) + let v69 := calldataload(69) + let v70 := calldataload(70) + let v71 := calldataload(71) + let v72 := calldataload(72) + let v73 := calldataload(73) + let v74 := calldataload(74) + let v75 := calldataload(75) + let v76 := calldataload(76) + let v77 := calldataload(77) + let v78 := calldataload(78) + let v79 := calldataload(79) + let v80 := calldataload(80) + let v81 := calldataload(81) + let v82 := calldataload(82) + let v83 := calldataload(83) + let v84 := calldataload(84) + let v85 := calldataload(85) + let v86 := calldataload(86) + let v87 := calldataload(87) + let v88 := calldataload(88) + let v89 := calldataload(89) + let v90 := calldataload(90) + let v91 := calldataload(91) + let v92 := calldataload(92) + let v93 := calldataload(93) + let v94 := calldataload(94) + let v95 := calldataload(95) + let v96 := calldataload(96) + let v97 := calldataload(97) + let v98 := calldataload(98) + let v99 := calldataload(99) + let v100 := calldataload(100) + let v101 := calldataload(101) + let v102 := calldataload(102) + let v103 := calldataload(103) + let v104 := calldataload(104) + let v105 := calldataload(105) + let v106 := calldataload(106) + let v107 := calldataload(107) + let v108 := calldataload(108) + let v109 := calldataload(109) + let v110 := calldataload(110) + let v111 := calldataload(111) + let v112 := calldataload(112) + let v113 := calldataload(113) + let v114 := calldataload(114) + let v115 := calldataload(115) + let v116 := calldataload(116) + let v117 := calldataload(117) + let v118 := calldataload(118) + let v119 := calldataload(119) + let v120 := calldataload(120) + let v121 := calldataload(121) + let v122 := calldataload(122) + let v123 := calldataload(123) + let v124 := calldataload(124) + let v125 := calldataload(125) + let v126 := calldataload(126) + let v127 := calldataload(127) + let v128 := calldataload(128) + let v129 := calldataload(129) + let v130 := calldataload(130) + let v131 := calldataload(131) + let v132 := calldataload(132) + let v133 := calldataload(133) + let v134 := calldataload(134) + let v135 := calldataload(135) + let v136 := calldataload(136) + let v137 := calldataload(137) + let v138 := calldataload(138) + let v139 := calldataload(139) + let v140 := calldataload(140) + let v141 := calldataload(141) + let v142 := calldataload(142) + let v143 := calldataload(143) + let v144 := calldataload(144) + let v145 := calldataload(145) + let v146 := calldataload(146) + let v147 := calldataload(147) + let v148 := calldataload(148) + let v149 := calldataload(149) + let v150 := calldataload(150) + let v151 := calldataload(151) + let v152 := calldataload(152) + let v153 := calldataload(153) + let v154 := calldataload(154) + let v155 := calldataload(155) + let v156 := calldataload(156) + let v157 := calldataload(157) + let v158 := calldataload(158) + let v159 := calldataload(159) + let v160 := calldataload(160) + let v161 := calldataload(161) + let v162 := calldataload(162) + let v163 := calldataload(163) + let v164 := calldataload(164) + let v165 := calldataload(165) + let v166 := calldataload(166) + let v167 := calldataload(167) + let v168 := calldataload(168) + let v169 := calldataload(169) + let v170 := calldataload(170) + let v171 := calldataload(171) + let v172 := calldataload(172) + let v173 := calldataload(173) + let v174 := calldataload(174) + let v175 := calldataload(175) + let v176 := calldataload(176) + let v177 := calldataload(177) + let v178 := calldataload(178) + let v179 := calldataload(179) + let v180 := calldataload(180) + let v181 := calldataload(181) + let v182 := calldataload(182) + let v183 := calldataload(183) + let v184 := calldataload(184) + let v185 := calldataload(185) + let v186 := calldataload(186) + let v187 := calldataload(187) + let v188 := calldataload(188) + let v189 := calldataload(189) + let v190 := calldataload(190) + let v191 := calldataload(191) + let v192 := calldataload(192) + let v193 := calldataload(193) + let v194 := calldataload(194) + let v195 := calldataload(195) + let v196 := calldataload(196) + let v197 := calldataload(197) + let v198 := calldataload(198) + let v199 := calldataload(199) + let v200 := calldataload(200) + let v201 := calldataload(201) + let v202 := calldataload(202) + let v203 := calldataload(203) + let v204 := calldataload(204) + let v205 := calldataload(205) + let v206 := calldataload(206) + let v207 := calldataload(207) + let v208 := calldataload(208) + let v209 := calldataload(209) + let v210 := calldataload(210) + let v211 := calldataload(211) + let v212 := calldataload(212) + let v213 := calldataload(213) + let v214 := calldataload(214) + let v215 := calldataload(215) + let v216 := calldataload(216) + let v217 := calldataload(217) + let v218 := calldataload(218) + let v219 := calldataload(219) + let v220 := calldataload(220) + let v221 := calldataload(221) + let v222 := calldataload(222) + let v223 := calldataload(223) + let v224 := calldataload(224) + let v225 := calldataload(225) + let v226 := calldataload(226) + let v227 := calldataload(227) + let v228 := calldataload(228) + let v229 := calldataload(229) + let v230 := calldataload(230) + let v231 := calldataload(231) + let v232 := calldataload(232) + let v233 := calldataload(233) + let v234 := calldataload(234) + let v235 := calldataload(235) + let v236 := calldataload(236) + let v237 := calldataload(237) + let v238 := calldataload(238) + let v239 := calldataload(239) + let v240 := calldataload(240) + let v241 := calldataload(241) + let v242 := calldataload(242) + let v243 := calldataload(243) + let v244 := calldataload(244) + let v245 := calldataload(245) + let v246 := calldataload(246) + let v247 := calldataload(247) + let v248 := calldataload(248) + let v249 := calldataload(249) + let v250 := calldataload(250) + let v251 := calldataload(251) + let v252 := calldataload(252) + let v253 := calldataload(253) + let v254 := calldataload(254) + let v255 := calldataload(255) + // The conditional jump splits basic blocks and prevents us from moving the resulting dupn{256} further up. + // At the time of writing, the current code transform would do that and turn it into a less-deep dup otherwise. + if calldataload(256) { revert(0,0) } + sstore(256, v0) + sstore(255, v255) + sstore(254, v254) + sstore(253, v253) + sstore(252, v252) + sstore(251, v251) + sstore(250, v250) + sstore(249, v249) + sstore(248, v248) + sstore(247, v247) + sstore(246, v246) + sstore(245, v245) + sstore(244, v244) + sstore(243, v243) + sstore(242, v242) + sstore(241, v241) + sstore(240, v240) + sstore(239, v239) + sstore(238, v238) + sstore(237, v237) + sstore(236, v236) + sstore(235, v235) + sstore(234, v234) + sstore(233, v233) + sstore(232, v232) + sstore(231, v231) + sstore(230, v230) + sstore(229, v229) + sstore(228, v228) + sstore(227, v227) + sstore(226, v226) + sstore(225, v225) + sstore(224, v224) + sstore(223, v223) + sstore(222, v222) + sstore(221, v221) + sstore(220, v220) + sstore(219, v219) + sstore(218, v218) + sstore(217, v217) + sstore(216, v216) + sstore(215, v215) + sstore(214, v214) + sstore(213, v213) + sstore(212, v212) + sstore(211, v211) + sstore(210, v210) + sstore(209, v209) + sstore(208, v208) + sstore(207, v207) + sstore(206, v206) + sstore(205, v205) + sstore(204, v204) + sstore(203, v203) + sstore(202, v202) + sstore(201, v201) + sstore(200, v200) + sstore(199, v199) + sstore(198, v198) + sstore(197, v197) + sstore(196, v196) + sstore(195, v195) + sstore(194, v194) + sstore(193, v193) + sstore(192, v192) + sstore(191, v191) + sstore(190, v190) + sstore(189, v189) + sstore(188, v188) + sstore(187, v187) + sstore(186, v186) + sstore(185, v185) + sstore(184, v184) + sstore(183, v183) + sstore(182, v182) + sstore(181, v181) + sstore(180, v180) + sstore(179, v179) + sstore(178, v178) + sstore(177, v177) + sstore(176, v176) + sstore(175, v175) + sstore(174, v174) + sstore(173, v173) + sstore(172, v172) + sstore(171, v171) + sstore(170, v170) + sstore(169, v169) + sstore(168, v168) + sstore(167, v167) + sstore(166, v166) + sstore(165, v165) + sstore(164, v164) + sstore(163, v163) + sstore(162, v162) + sstore(161, v161) + sstore(160, v160) + sstore(159, v159) + sstore(158, v158) + sstore(157, v157) + sstore(156, v156) + sstore(155, v155) + sstore(154, v154) + sstore(153, v153) + sstore(152, v152) + sstore(151, v151) + sstore(150, v150) + sstore(149, v149) + sstore(148, v148) + sstore(147, v147) + sstore(146, v146) + sstore(145, v145) + sstore(144, v144) + sstore(143, v143) + sstore(142, v142) + sstore(141, v141) + sstore(140, v140) + sstore(139, v139) + sstore(138, v138) + sstore(137, v137) + sstore(136, v136) + sstore(135, v135) + sstore(134, v134) + sstore(133, v133) + sstore(132, v132) + sstore(131, v131) + sstore(130, v130) + sstore(129, v129) + sstore(128, v128) + sstore(127, v127) + sstore(126, v126) + sstore(125, v125) + sstore(124, v124) + sstore(123, v123) + sstore(122, v122) + sstore(121, v121) + sstore(120, v120) + sstore(119, v119) + sstore(118, v118) + sstore(117, v117) + sstore(116, v116) + sstore(115, v115) + sstore(114, v114) + sstore(113, v113) + sstore(112, v112) + sstore(111, v111) + sstore(110, v110) + sstore(109, v109) + sstore(108, v108) + sstore(107, v107) + sstore(106, v106) + sstore(105, v105) + sstore(104, v104) + sstore(103, v103) + sstore(102, v102) + sstore(101, v101) + sstore(100, v100) + sstore(99, v99) + sstore(98, v98) + sstore(97, v97) + sstore(96, v96) + sstore(95, v95) + sstore(94, v94) + sstore(93, v93) + sstore(92, v92) + sstore(91, v91) + sstore(90, v90) + sstore(89, v89) + sstore(88, v88) + sstore(87, v87) + sstore(86, v86) + sstore(85, v85) + sstore(84, v84) + sstore(83, v83) + sstore(82, v82) + sstore(81, v81) + sstore(80, v80) + sstore(79, v79) + sstore(78, v78) + sstore(77, v77) + sstore(76, v76) + sstore(75, v75) + sstore(74, v74) + sstore(73, v73) + sstore(72, v72) + sstore(71, v71) + sstore(70, v70) + sstore(69, v69) + sstore(68, v68) + sstore(67, v67) + sstore(66, v66) + sstore(65, v65) + sstore(64, v64) + sstore(63, v63) + sstore(62, v62) + sstore(61, v61) + sstore(60, v60) + sstore(59, v59) + sstore(58, v58) + sstore(57, v57) + sstore(56, v56) + sstore(55, v55) + sstore(54, v54) + sstore(53, v53) + sstore(52, v52) + sstore(51, v51) + sstore(50, v50) + sstore(49, v49) + sstore(48, v48) + sstore(47, v47) + sstore(46, v46) + sstore(45, v45) + sstore(44, v44) + sstore(43, v43) + sstore(42, v42) + sstore(41, v41) + sstore(40, v40) + sstore(39, v39) + sstore(38, v38) + sstore(37, v37) + sstore(36, v36) + sstore(35, v35) + sstore(34, v34) + sstore(33, v33) + sstore(32, v32) + sstore(31, v31) + sstore(30, v30) + sstore(29, v29) + sstore(28, v28) + sstore(27, v27) + sstore(26, v26) + sstore(25, v25) + sstore(24, v24) + sstore(23, v23) + sstore(22, v22) + sstore(21, v21) + sstore(20, v20) + sstore(19, v19) + sstore(18, v18) + sstore(17, v17) + sstore(16, v16) + sstore(15, v15) + sstore(14, v14) + sstore(13, v13) + sstore(12, v12) + sstore(11, v11) + sstore(10, v10) + sstore(9, v9) + sstore(8, v8) + sstore(7, v7) + sstore(6, v6) + sstore(5, v5) + sstore(4, v4) + sstore(3, v3) + sstore(2, v2) + sstore(1, v1) + sstore(0, v0) + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// stackOptimization: true +// ---- +// /* "":58:59 */ +// 0x00 +// /* "":45:60 */ +// calldataload +// /* "":92:93 */ +// 0x01 +// /* "":79:94 */ +// calldataload +// /* "":126:127 */ +// 0x02 +// /* "":113:128 */ +// calldataload +// /* "":160:161 */ +// 0x03 +// /* "":147:162 */ +// calldataload +// /* "":194:195 */ +// 0x04 +// /* "":181:196 */ +// calldataload +// /* "":228:229 */ +// 0x05 +// /* "":215:230 */ +// calldataload +// /* "":262:263 */ +// 0x06 +// /* "":249:264 */ +// calldataload +// /* "":296:297 */ +// 0x07 +// /* "":283:298 */ +// calldataload +// /* "":330:331 */ +// 0x08 +// /* "":317:332 */ +// calldataload +// /* "":364:365 */ +// 0x09 +// /* "":351:366 */ +// calldataload +// /* "":399:401 */ +// 0x0a +// /* "":386:402 */ +// calldataload +// /* "":435:437 */ +// 0x0b +// /* "":422:438 */ +// calldataload +// /* "":471:473 */ +// 0x0c +// /* "":458:474 */ +// calldataload +// /* "":507:509 */ +// 0x0d +// /* "":494:510 */ +// calldataload +// /* "":543:545 */ +// 0x0e +// /* "":530:546 */ +// calldataload +// /* "":579:581 */ +// 0x0f +// /* "":566:582 */ +// calldataload +// /* "":615:617 */ +// 0x10 +// /* "":602:618 */ +// calldataload +// /* "":651:653 */ +// 0x11 +// /* "":638:654 */ +// calldataload +// /* "":687:689 */ +// 0x12 +// /* "":674:690 */ +// calldataload +// /* "":723:725 */ +// 0x13 +// /* "":710:726 */ +// calldataload +// /* "":759:761 */ +// 0x14 +// /* "":746:762 */ +// calldataload +// /* "":795:797 */ +// 0x15 +// /* "":782:798 */ +// calldataload +// /* "":831:833 */ +// 0x16 +// /* "":818:834 */ +// calldataload +// /* "":867:869 */ +// 0x17 +// /* "":854:870 */ +// calldataload +// /* "":903:905 */ +// 0x18 +// /* "":890:906 */ +// calldataload +// /* "":939:941 */ +// 0x19 +// /* "":926:942 */ +// calldataload +// /* "":975:977 */ +// 0x1a +// /* "":962:978 */ +// calldataload +// /* "":1011:1013 */ +// 0x1b +// /* "":998:1014 */ +// calldataload +// /* "":1047:1049 */ +// 0x1c +// /* "":1034:1050 */ +// calldataload +// /* "":1083:1085 */ +// 0x1d +// /* "":1070:1086 */ +// calldataload +// /* "":1119:1121 */ +// 0x1e +// /* "":1106:1122 */ +// calldataload +// /* "":1155:1157 */ +// 0x1f +// /* "":1142:1158 */ +// calldataload +// /* "":1191:1193 */ +// 0x20 +// /* "":1178:1194 */ +// calldataload +// /* "":1227:1229 */ +// 0x21 +// /* "":1214:1230 */ +// calldataload +// /* "":1263:1265 */ +// 0x22 +// /* "":1250:1266 */ +// calldataload +// /* "":1299:1301 */ +// 0x23 +// /* "":1286:1302 */ +// calldataload +// /* "":1335:1337 */ +// 0x24 +// /* "":1322:1338 */ +// calldataload +// /* "":1371:1373 */ +// 0x25 +// /* "":1358:1374 */ +// calldataload +// /* "":1407:1409 */ +// 0x26 +// /* "":1394:1410 */ +// calldataload +// /* "":1443:1445 */ +// 0x27 +// /* "":1430:1446 */ +// calldataload +// /* "":1479:1481 */ +// 0x28 +// /* "":1466:1482 */ +// calldataload +// /* "":1515:1517 */ +// 0x29 +// /* "":1502:1518 */ +// calldataload +// /* "":1551:1553 */ +// 0x2a +// /* "":1538:1554 */ +// calldataload +// /* "":1587:1589 */ +// 0x2b +// /* "":1574:1590 */ +// calldataload +// /* "":1623:1625 */ +// 0x2c +// /* "":1610:1626 */ +// calldataload +// /* "":1659:1661 */ +// 0x2d +// /* "":1646:1662 */ +// calldataload +// /* "":1695:1697 */ +// 0x2e +// /* "":1682:1698 */ +// calldataload +// /* "":1731:1733 */ +// 0x2f +// /* "":1718:1734 */ +// calldataload +// /* "":1767:1769 */ +// 0x30 +// /* "":1754:1770 */ +// calldataload +// /* "":1803:1805 */ +// 0x31 +// /* "":1790:1806 */ +// calldataload +// /* "":1839:1841 */ +// 0x32 +// /* "":1826:1842 */ +// calldataload +// /* "":1875:1877 */ +// 0x33 +// /* "":1862:1878 */ +// calldataload +// /* "":1911:1913 */ +// 0x34 +// /* "":1898:1914 */ +// calldataload +// /* "":1947:1949 */ +// 0x35 +// /* "":1934:1950 */ +// calldataload +// /* "":1983:1985 */ +// 0x36 +// /* "":1970:1986 */ +// calldataload +// /* "":2019:2021 */ +// 0x37 +// /* "":2006:2022 */ +// calldataload +// /* "":2055:2057 */ +// 0x38 +// /* "":2042:2058 */ +// calldataload +// /* "":2091:2093 */ +// 0x39 +// /* "":2078:2094 */ +// calldataload +// /* "":2127:2129 */ +// 0x3a +// /* "":2114:2130 */ +// calldataload +// /* "":2163:2165 */ +// 0x3b +// /* "":2150:2166 */ +// calldataload +// /* "":2199:2201 */ +// 0x3c +// /* "":2186:2202 */ +// calldataload +// /* "":2235:2237 */ +// 0x3d +// /* "":2222:2238 */ +// calldataload +// /* "":2271:2273 */ +// 0x3e +// /* "":2258:2274 */ +// calldataload +// /* "":2307:2309 */ +// 0x3f +// /* "":2294:2310 */ +// calldataload +// /* "":2343:2345 */ +// 0x40 +// /* "":2330:2346 */ +// calldataload +// /* "":2379:2381 */ +// 0x41 +// /* "":2366:2382 */ +// calldataload +// /* "":2415:2417 */ +// 0x42 +// /* "":2402:2418 */ +// calldataload +// /* "":2451:2453 */ +// 0x43 +// /* "":2438:2454 */ +// calldataload +// /* "":2487:2489 */ +// 0x44 +// /* "":2474:2490 */ +// calldataload +// /* "":2523:2525 */ +// 0x45 +// /* "":2510:2526 */ +// calldataload +// /* "":2559:2561 */ +// 0x46 +// /* "":2546:2562 */ +// calldataload +// /* "":2595:2597 */ +// 0x47 +// /* "":2582:2598 */ +// calldataload +// /* "":2631:2633 */ +// 0x48 +// /* "":2618:2634 */ +// calldataload +// /* "":2667:2669 */ +// 0x49 +// /* "":2654:2670 */ +// calldataload +// /* "":2703:2705 */ +// 0x4a +// /* "":2690:2706 */ +// calldataload +// /* "":2739:2741 */ +// 0x4b +// /* "":2726:2742 */ +// calldataload +// /* "":2775:2777 */ +// 0x4c +// /* "":2762:2778 */ +// calldataload +// /* "":2811:2813 */ +// 0x4d +// /* "":2798:2814 */ +// calldataload +// /* "":2847:2849 */ +// 0x4e +// /* "":2834:2850 */ +// calldataload +// /* "":2883:2885 */ +// 0x4f +// /* "":2870:2886 */ +// calldataload +// /* "":2919:2921 */ +// 0x50 +// /* "":2906:2922 */ +// calldataload +// /* "":2955:2957 */ +// 0x51 +// /* "":2942:2958 */ +// calldataload +// /* "":2991:2993 */ +// 0x52 +// /* "":2978:2994 */ +// calldataload +// /* "":3027:3029 */ +// 0x53 +// /* "":3014:3030 */ +// calldataload +// /* "":3063:3065 */ +// 0x54 +// /* "":3050:3066 */ +// calldataload +// /* "":3099:3101 */ +// 0x55 +// /* "":3086:3102 */ +// calldataload +// /* "":3135:3137 */ +// 0x56 +// /* "":3122:3138 */ +// calldataload +// /* "":3171:3173 */ +// 0x57 +// /* "":3158:3174 */ +// calldataload +// /* "":3207:3209 */ +// 0x58 +// /* "":3194:3210 */ +// calldataload +// /* "":3243:3245 */ +// 0x59 +// /* "":3230:3246 */ +// calldataload +// /* "":3279:3281 */ +// 0x5a +// /* "":3266:3282 */ +// calldataload +// /* "":3315:3317 */ +// 0x5b +// /* "":3302:3318 */ +// calldataload +// /* "":3351:3353 */ +// 0x5c +// /* "":3338:3354 */ +// calldataload +// /* "":3387:3389 */ +// 0x5d +// /* "":3374:3390 */ +// calldataload +// /* "":3423:3425 */ +// 0x5e +// /* "":3410:3426 */ +// calldataload +// /* "":3459:3461 */ +// 0x5f +// /* "":3446:3462 */ +// calldataload +// /* "":3495:3497 */ +// 0x60 +// /* "":3482:3498 */ +// calldataload +// /* "":3531:3533 */ +// 0x61 +// /* "":3518:3534 */ +// calldataload +// /* "":3567:3569 */ +// 0x62 +// /* "":3554:3570 */ +// calldataload +// /* "":3603:3605 */ +// 0x63 +// /* "":3590:3606 */ +// calldataload +// /* "":3640:3643 */ +// 0x64 +// /* "":3627:3644 */ +// calldataload +// /* "":3678:3681 */ +// 0x65 +// /* "":3665:3682 */ +// calldataload +// /* "":3716:3719 */ +// 0x66 +// /* "":3703:3720 */ +// calldataload +// /* "":3754:3757 */ +// 0x67 +// /* "":3741:3758 */ +// calldataload +// /* "":3792:3795 */ +// 0x68 +// /* "":3779:3796 */ +// calldataload +// /* "":3830:3833 */ +// 0x69 +// /* "":3817:3834 */ +// calldataload +// /* "":3868:3871 */ +// 0x6a +// /* "":3855:3872 */ +// calldataload +// /* "":3906:3909 */ +// 0x6b +// /* "":3893:3910 */ +// calldataload +// /* "":3944:3947 */ +// 0x6c +// /* "":3931:3948 */ +// calldataload +// /* "":3982:3985 */ +// 0x6d +// /* "":3969:3986 */ +// calldataload +// /* "":4020:4023 */ +// 0x6e +// /* "":4007:4024 */ +// calldataload +// /* "":4058:4061 */ +// 0x6f +// /* "":4045:4062 */ +// calldataload +// /* "":4096:4099 */ +// 0x70 +// /* "":4083:4100 */ +// calldataload +// /* "":4134:4137 */ +// 0x71 +// /* "":4121:4138 */ +// calldataload +// /* "":4172:4175 */ +// 0x72 +// /* "":4159:4176 */ +// calldataload +// /* "":4210:4213 */ +// 0x73 +// /* "":4197:4214 */ +// calldataload +// /* "":4248:4251 */ +// 0x74 +// /* "":4235:4252 */ +// calldataload +// /* "":4286:4289 */ +// 0x75 +// /* "":4273:4290 */ +// calldataload +// /* "":4324:4327 */ +// 0x76 +// /* "":4311:4328 */ +// calldataload +// /* "":4362:4365 */ +// 0x77 +// /* "":4349:4366 */ +// calldataload +// /* "":4400:4403 */ +// 0x78 +// /* "":4387:4404 */ +// calldataload +// /* "":4438:4441 */ +// 0x79 +// /* "":4425:4442 */ +// calldataload +// /* "":4476:4479 */ +// 0x7a +// /* "":4463:4480 */ +// calldataload +// /* "":4514:4517 */ +// 0x7b +// /* "":4501:4518 */ +// calldataload +// /* "":4552:4555 */ +// 0x7c +// /* "":4539:4556 */ +// calldataload +// /* "":4590:4593 */ +// 0x7d +// /* "":4577:4594 */ +// calldataload +// /* "":4628:4631 */ +// 0x7e +// /* "":4615:4632 */ +// calldataload +// /* "":4666:4669 */ +// 0x7f +// /* "":4653:4670 */ +// calldataload +// /* "":4704:4707 */ +// 0x80 +// /* "":4691:4708 */ +// calldataload +// /* "":4742:4745 */ +// 0x81 +// /* "":4729:4746 */ +// calldataload +// /* "":4780:4783 */ +// 0x82 +// /* "":4767:4784 */ +// calldataload +// /* "":4818:4821 */ +// 0x83 +// /* "":4805:4822 */ +// calldataload +// /* "":4856:4859 */ +// 0x84 +// /* "":4843:4860 */ +// calldataload +// /* "":4894:4897 */ +// 0x85 +// /* "":4881:4898 */ +// calldataload +// /* "":4932:4935 */ +// 0x86 +// /* "":4919:4936 */ +// calldataload +// /* "":4970:4973 */ +// 0x87 +// /* "":4957:4974 */ +// calldataload +// /* "":5008:5011 */ +// 0x88 +// /* "":4995:5012 */ +// calldataload +// /* "":5046:5049 */ +// 0x89 +// /* "":5033:5050 */ +// calldataload +// /* "":5084:5087 */ +// 0x8a +// /* "":5071:5088 */ +// calldataload +// /* "":5122:5125 */ +// 0x8b +// /* "":5109:5126 */ +// calldataload +// /* "":5160:5163 */ +// 0x8c +// /* "":5147:5164 */ +// calldataload +// /* "":5198:5201 */ +// 0x8d +// /* "":5185:5202 */ +// calldataload +// /* "":5236:5239 */ +// 0x8e +// /* "":5223:5240 */ +// calldataload +// /* "":5274:5277 */ +// 0x8f +// /* "":5261:5278 */ +// calldataload +// /* "":5312:5315 */ +// 0x90 +// /* "":5299:5316 */ +// calldataload +// /* "":5350:5353 */ +// 0x91 +// /* "":5337:5354 */ +// calldataload +// /* "":5388:5391 */ +// 0x92 +// /* "":5375:5392 */ +// calldataload +// /* "":5426:5429 */ +// 0x93 +// /* "":5413:5430 */ +// calldataload +// /* "":5464:5467 */ +// 0x94 +// /* "":5451:5468 */ +// calldataload +// /* "":5502:5505 */ +// 0x95 +// /* "":5489:5506 */ +// calldataload +// /* "":5540:5543 */ +// 0x96 +// /* "":5527:5544 */ +// calldataload +// /* "":5578:5581 */ +// 0x97 +// /* "":5565:5582 */ +// calldataload +// /* "":5616:5619 */ +// 0x98 +// /* "":5603:5620 */ +// calldataload +// /* "":5654:5657 */ +// 0x99 +// /* "":5641:5658 */ +// calldataload +// /* "":5692:5695 */ +// 0x9a +// /* "":5679:5696 */ +// calldataload +// /* "":5730:5733 */ +// 0x9b +// /* "":5717:5734 */ +// calldataload +// /* "":5768:5771 */ +// 0x9c +// /* "":5755:5772 */ +// calldataload +// /* "":5806:5809 */ +// 0x9d +// /* "":5793:5810 */ +// calldataload +// /* "":5844:5847 */ +// 0x9e +// /* "":5831:5848 */ +// calldataload +// /* "":5882:5885 */ +// 0x9f +// /* "":5869:5886 */ +// calldataload +// /* "":5920:5923 */ +// 0xa0 +// /* "":5907:5924 */ +// calldataload +// /* "":5958:5961 */ +// 0xa1 +// /* "":5945:5962 */ +// calldataload +// /* "":5996:5999 */ +// 0xa2 +// /* "":5983:6000 */ +// calldataload +// /* "":6034:6037 */ +// 0xa3 +// /* "":6021:6038 */ +// calldataload +// /* "":6072:6075 */ +// 0xa4 +// /* "":6059:6076 */ +// calldataload +// /* "":6110:6113 */ +// 0xa5 +// /* "":6097:6114 */ +// calldataload +// /* "":6148:6151 */ +// 0xa6 +// /* "":6135:6152 */ +// calldataload +// /* "":6186:6189 */ +// 0xa7 +// /* "":6173:6190 */ +// calldataload +// /* "":6224:6227 */ +// 0xa8 +// /* "":6211:6228 */ +// calldataload +// /* "":6262:6265 */ +// 0xa9 +// /* "":6249:6266 */ +// calldataload +// /* "":6300:6303 */ +// 0xaa +// /* "":6287:6304 */ +// calldataload +// /* "":6338:6341 */ +// 0xab +// /* "":6325:6342 */ +// calldataload +// /* "":6376:6379 */ +// 0xac +// /* "":6363:6380 */ +// calldataload +// /* "":6414:6417 */ +// 0xad +// /* "":6401:6418 */ +// calldataload +// /* "":6452:6455 */ +// 0xae +// /* "":6439:6456 */ +// calldataload +// /* "":6490:6493 */ +// 0xaf +// /* "":6477:6494 */ +// calldataload +// /* "":6528:6531 */ +// 0xb0 +// /* "":6515:6532 */ +// calldataload +// /* "":6566:6569 */ +// 0xb1 +// /* "":6553:6570 */ +// calldataload +// /* "":6604:6607 */ +// 0xb2 +// /* "":6591:6608 */ +// calldataload +// /* "":6642:6645 */ +// 0xb3 +// /* "":6629:6646 */ +// calldataload +// /* "":6680:6683 */ +// 0xb4 +// /* "":6667:6684 */ +// calldataload +// /* "":6718:6721 */ +// 0xb5 +// /* "":6705:6722 */ +// calldataload +// /* "":6756:6759 */ +// 0xb6 +// /* "":6743:6760 */ +// calldataload +// /* "":6794:6797 */ +// 0xb7 +// /* "":6781:6798 */ +// calldataload +// /* "":6832:6835 */ +// 0xb8 +// /* "":6819:6836 */ +// calldataload +// /* "":6870:6873 */ +// 0xb9 +// /* "":6857:6874 */ +// calldataload +// /* "":6908:6911 */ +// 0xba +// /* "":6895:6912 */ +// calldataload +// /* "":6946:6949 */ +// 0xbb +// /* "":6933:6950 */ +// calldataload +// /* "":6984:6987 */ +// 0xbc +// /* "":6971:6988 */ +// calldataload +// /* "":7022:7025 */ +// 0xbd +// /* "":7009:7026 */ +// calldataload +// /* "":7060:7063 */ +// 0xbe +// /* "":7047:7064 */ +// calldataload +// /* "":7098:7101 */ +// 0xbf +// /* "":7085:7102 */ +// calldataload +// /* "":7136:7139 */ +// 0xc0 +// /* "":7123:7140 */ +// calldataload +// /* "":7174:7177 */ +// 0xc1 +// /* "":7161:7178 */ +// calldataload +// /* "":7212:7215 */ +// 0xc2 +// /* "":7199:7216 */ +// calldataload +// /* "":7250:7253 */ +// 0xc3 +// /* "":7237:7254 */ +// calldataload +// /* "":7288:7291 */ +// 0xc4 +// /* "":7275:7292 */ +// calldataload +// /* "":7326:7329 */ +// 0xc5 +// /* "":7313:7330 */ +// calldataload +// /* "":7364:7367 */ +// 0xc6 +// /* "":7351:7368 */ +// calldataload +// /* "":7402:7405 */ +// 0xc7 +// /* "":7389:7406 */ +// calldataload +// /* "":7440:7443 */ +// 0xc8 +// /* "":7427:7444 */ +// calldataload +// /* "":7478:7481 */ +// 0xc9 +// /* "":7465:7482 */ +// calldataload +// /* "":7516:7519 */ +// 0xca +// /* "":7503:7520 */ +// calldataload +// /* "":7554:7557 */ +// 0xcb +// /* "":7541:7558 */ +// calldataload +// /* "":7592:7595 */ +// 0xcc +// /* "":7579:7596 */ +// calldataload +// /* "":7630:7633 */ +// 0xcd +// /* "":7617:7634 */ +// calldataload +// /* "":7668:7671 */ +// 0xce +// /* "":7655:7672 */ +// calldataload +// /* "":7706:7709 */ +// 0xcf +// /* "":7693:7710 */ +// calldataload +// /* "":7744:7747 */ +// 0xd0 +// /* "":7731:7748 */ +// calldataload +// /* "":7782:7785 */ +// 0xd1 +// /* "":7769:7786 */ +// calldataload +// /* "":7820:7823 */ +// 0xd2 +// /* "":7807:7824 */ +// calldataload +// /* "":7858:7861 */ +// 0xd3 +// /* "":7845:7862 */ +// calldataload +// /* "":7896:7899 */ +// 0xd4 +// /* "":7883:7900 */ +// calldataload +// /* "":7934:7937 */ +// 0xd5 +// /* "":7921:7938 */ +// calldataload +// /* "":7972:7975 */ +// 0xd6 +// /* "":7959:7976 */ +// calldataload +// /* "":8010:8013 */ +// 0xd7 +// /* "":7997:8014 */ +// calldataload +// /* "":8048:8051 */ +// 0xd8 +// /* "":8035:8052 */ +// calldataload +// /* "":8086:8089 */ +// 0xd9 +// /* "":8073:8090 */ +// calldataload +// /* "":8124:8127 */ +// 0xda +// /* "":8111:8128 */ +// calldataload +// /* "":8162:8165 */ +// 0xdb +// /* "":8149:8166 */ +// calldataload +// /* "":8200:8203 */ +// 0xdc +// /* "":8187:8204 */ +// calldataload +// /* "":8238:8241 */ +// 0xdd +// /* "":8225:8242 */ +// calldataload +// /* "":8276:8279 */ +// 0xde +// /* "":8263:8280 */ +// calldataload +// /* "":8314:8317 */ +// 0xdf +// /* "":8301:8318 */ +// calldataload +// /* "":8352:8355 */ +// 0xe0 +// /* "":8339:8356 */ +// calldataload +// /* "":8390:8393 */ +// 0xe1 +// /* "":8377:8394 */ +// calldataload +// /* "":8428:8431 */ +// 0xe2 +// /* "":8415:8432 */ +// calldataload +// /* "":8466:8469 */ +// 0xe3 +// /* "":8453:8470 */ +// calldataload +// /* "":8504:8507 */ +// 0xe4 +// /* "":8491:8508 */ +// calldataload +// /* "":8542:8545 */ +// 0xe5 +// /* "":8529:8546 */ +// calldataload +// /* "":8580:8583 */ +// 0xe6 +// /* "":8567:8584 */ +// calldataload +// /* "":8618:8621 */ +// 0xe7 +// /* "":8605:8622 */ +// calldataload +// /* "":8656:8659 */ +// 0xe8 +// /* "":8643:8660 */ +// calldataload +// /* "":8694:8697 */ +// 0xe9 +// /* "":8681:8698 */ +// calldataload +// /* "":8732:8735 */ +// 0xea +// /* "":8719:8736 */ +// calldataload +// /* "":8770:8773 */ +// 0xeb +// /* "":8757:8774 */ +// calldataload +// /* "":8808:8811 */ +// 0xec +// /* "":8795:8812 */ +// calldataload +// /* "":8846:8849 */ +// 0xed +// /* "":8833:8850 */ +// calldataload +// /* "":8884:8887 */ +// 0xee +// /* "":8871:8888 */ +// calldataload +// /* "":8922:8925 */ +// 0xef +// /* "":8909:8926 */ +// calldataload +// /* "":8960:8963 */ +// 0xf0 +// /* "":8947:8964 */ +// calldataload +// /* "":8998:9001 */ +// 0xf1 +// /* "":8985:9002 */ +// calldataload +// /* "":9036:9039 */ +// 0xf2 +// /* "":9023:9040 */ +// calldataload +// /* "":9074:9077 */ +// 0xf3 +// /* "":9061:9078 */ +// calldataload +// /* "":9112:9115 */ +// 0xf4 +// /* "":9099:9116 */ +// calldataload +// /* "":9150:9153 */ +// 0xf5 +// /* "":9137:9154 */ +// calldataload +// /* "":9188:9191 */ +// 0xf6 +// /* "":9175:9192 */ +// calldataload +// /* "":9226:9229 */ +// 0xf7 +// /* "":9213:9230 */ +// calldataload +// /* "":9264:9267 */ +// 0xf8 +// /* "":9251:9268 */ +// calldataload +// /* "":9302:9305 */ +// 0xf9 +// /* "":9289:9306 */ +// calldataload +// /* "":9340:9343 */ +// 0xfa +// /* "":9327:9344 */ +// calldataload +// /* "":9378:9381 */ +// 0xfb +// /* "":9365:9382 */ +// calldataload +// /* "":9416:9419 */ +// 0xfc +// /* "":9403:9420 */ +// calldataload +// /* "":9454:9457 */ +// 0xfd +// /* "":9441:9458 */ +// calldataload +// /* "":9492:9495 */ +// 0xfe +// /* "":9479:9496 */ +// calldataload +// /* "":9530:9533 */ +// 0xff +// /* "":9517:9534 */ +// calldataload +// /* "":9795:9798 */ +// 0x0100 +// /* "":9782:9799 */ +// calldataload +// /* "":9779:9815 */ +// rjumpi{tag_1} +// /* "":25:16281 */ +// tag_2: +// /* "":9824:9839 */ +// dupn{256} +// /* "":9831:9834 */ +// 0x0100 +// /* "":9824:9839 */ +// sstore +// /* "":9855:9858 */ +// 0xff +// /* "":9848:9865 */ +// sstore +// /* "":9881:9884 */ +// 0xfe +// /* "":9874:9891 */ +// sstore +// /* "":9907:9910 */ +// 0xfd +// /* "":9900:9917 */ +// sstore +// /* "":9933:9936 */ +// 0xfc +// /* "":9926:9943 */ +// sstore +// /* "":9959:9962 */ +// 0xfb +// /* "":9952:9969 */ +// sstore +// /* "":9985:9988 */ +// 0xfa +// /* "":9978:9995 */ +// sstore +// /* "":10011:10014 */ +// 0xf9 +// /* "":10004:10021 */ +// sstore +// /* "":10037:10040 */ +// 0xf8 +// /* "":10030:10047 */ +// sstore +// /* "":10063:10066 */ +// 0xf7 +// /* "":10056:10073 */ +// sstore +// /* "":10089:10092 */ +// 0xf6 +// /* "":10082:10099 */ +// sstore +// /* "":10115:10118 */ +// 0xf5 +// /* "":10108:10125 */ +// sstore +// /* "":10141:10144 */ +// 0xf4 +// /* "":10134:10151 */ +// sstore +// /* "":10167:10170 */ +// 0xf3 +// /* "":10160:10177 */ +// sstore +// /* "":10193:10196 */ +// 0xf2 +// /* "":10186:10203 */ +// sstore +// /* "":10219:10222 */ +// 0xf1 +// /* "":10212:10229 */ +// sstore +// /* "":10245:10248 */ +// 0xf0 +// /* "":10238:10255 */ +// sstore +// /* "":10271:10274 */ +// 0xef +// /* "":10264:10281 */ +// sstore +// /* "":10297:10300 */ +// 0xee +// /* "":10290:10307 */ +// sstore +// /* "":10323:10326 */ +// 0xed +// /* "":10316:10333 */ +// sstore +// /* "":10349:10352 */ +// 0xec +// /* "":10342:10359 */ +// sstore +// /* "":10375:10378 */ +// 0xeb +// /* "":10368:10385 */ +// sstore +// /* "":10401:10404 */ +// 0xea +// /* "":10394:10411 */ +// sstore +// /* "":10427:10430 */ +// 0xe9 +// /* "":10420:10437 */ +// sstore +// /* "":10453:10456 */ +// 0xe8 +// /* "":10446:10463 */ +// sstore +// /* "":10479:10482 */ +// 0xe7 +// /* "":10472:10489 */ +// sstore +// /* "":10505:10508 */ +// 0xe6 +// /* "":10498:10515 */ +// sstore +// /* "":10531:10534 */ +// 0xe5 +// /* "":10524:10541 */ +// sstore +// /* "":10557:10560 */ +// 0xe4 +// /* "":10550:10567 */ +// sstore +// /* "":10583:10586 */ +// 0xe3 +// /* "":10576:10593 */ +// sstore +// /* "":10609:10612 */ +// 0xe2 +// /* "":10602:10619 */ +// sstore +// /* "":10635:10638 */ +// 0xe1 +// /* "":10628:10645 */ +// sstore +// /* "":10661:10664 */ +// 0xe0 +// /* "":10654:10671 */ +// sstore +// /* "":10687:10690 */ +// 0xdf +// /* "":10680:10697 */ +// sstore +// /* "":10713:10716 */ +// 0xde +// /* "":10706:10723 */ +// sstore +// /* "":10739:10742 */ +// 0xdd +// /* "":10732:10749 */ +// sstore +// /* "":10765:10768 */ +// 0xdc +// /* "":10758:10775 */ +// sstore +// /* "":10791:10794 */ +// 0xdb +// /* "":10784:10801 */ +// sstore +// /* "":10817:10820 */ +// 0xda +// /* "":10810:10827 */ +// sstore +// /* "":10843:10846 */ +// 0xd9 +// /* "":10836:10853 */ +// sstore +// /* "":10869:10872 */ +// 0xd8 +// /* "":10862:10879 */ +// sstore +// /* "":10895:10898 */ +// 0xd7 +// /* "":10888:10905 */ +// sstore +// /* "":10921:10924 */ +// 0xd6 +// /* "":10914:10931 */ +// sstore +// /* "":10947:10950 */ +// 0xd5 +// /* "":10940:10957 */ +// sstore +// /* "":10973:10976 */ +// 0xd4 +// /* "":10966:10983 */ +// sstore +// /* "":10999:11002 */ +// 0xd3 +// /* "":10992:11009 */ +// sstore +// /* "":11025:11028 */ +// 0xd2 +// /* "":11018:11035 */ +// sstore +// /* "":11051:11054 */ +// 0xd1 +// /* "":11044:11061 */ +// sstore +// /* "":11077:11080 */ +// 0xd0 +// /* "":11070:11087 */ +// sstore +// /* "":11103:11106 */ +// 0xcf +// /* "":11096:11113 */ +// sstore +// /* "":11129:11132 */ +// 0xce +// /* "":11122:11139 */ +// sstore +// /* "":11155:11158 */ +// 0xcd +// /* "":11148:11165 */ +// sstore +// /* "":11181:11184 */ +// 0xcc +// /* "":11174:11191 */ +// sstore +// /* "":11207:11210 */ +// 0xcb +// /* "":11200:11217 */ +// sstore +// /* "":11233:11236 */ +// 0xca +// /* "":11226:11243 */ +// sstore +// /* "":11259:11262 */ +// 0xc9 +// /* "":11252:11269 */ +// sstore +// /* "":11285:11288 */ +// 0xc8 +// /* "":11278:11295 */ +// sstore +// /* "":11311:11314 */ +// 0xc7 +// /* "":11304:11321 */ +// sstore +// /* "":11337:11340 */ +// 0xc6 +// /* "":11330:11347 */ +// sstore +// /* "":11363:11366 */ +// 0xc5 +// /* "":11356:11373 */ +// sstore +// /* "":11389:11392 */ +// 0xc4 +// /* "":11382:11399 */ +// sstore +// /* "":11415:11418 */ +// 0xc3 +// /* "":11408:11425 */ +// sstore +// /* "":11441:11444 */ +// 0xc2 +// /* "":11434:11451 */ +// sstore +// /* "":11467:11470 */ +// 0xc1 +// /* "":11460:11477 */ +// sstore +// /* "":11493:11496 */ +// 0xc0 +// /* "":11486:11503 */ +// sstore +// /* "":11519:11522 */ +// 0xbf +// /* "":11512:11529 */ +// sstore +// /* "":11545:11548 */ +// 0xbe +// /* "":11538:11555 */ +// sstore +// /* "":11571:11574 */ +// 0xbd +// /* "":11564:11581 */ +// sstore +// /* "":11597:11600 */ +// 0xbc +// /* "":11590:11607 */ +// sstore +// /* "":11623:11626 */ +// 0xbb +// /* "":11616:11633 */ +// sstore +// /* "":11649:11652 */ +// 0xba +// /* "":11642:11659 */ +// sstore +// /* "":11675:11678 */ +// 0xb9 +// /* "":11668:11685 */ +// sstore +// /* "":11701:11704 */ +// 0xb8 +// /* "":11694:11711 */ +// sstore +// /* "":11727:11730 */ +// 0xb7 +// /* "":11720:11737 */ +// sstore +// /* "":11753:11756 */ +// 0xb6 +// /* "":11746:11763 */ +// sstore +// /* "":11779:11782 */ +// 0xb5 +// /* "":11772:11789 */ +// sstore +// /* "":11805:11808 */ +// 0xb4 +// /* "":11798:11815 */ +// sstore +// /* "":11831:11834 */ +// 0xb3 +// /* "":11824:11841 */ +// sstore +// /* "":11857:11860 */ +// 0xb2 +// /* "":11850:11867 */ +// sstore +// /* "":11883:11886 */ +// 0xb1 +// /* "":11876:11893 */ +// sstore +// /* "":11909:11912 */ +// 0xb0 +// /* "":11902:11919 */ +// sstore +// /* "":11935:11938 */ +// 0xaf +// /* "":11928:11945 */ +// sstore +// /* "":11961:11964 */ +// 0xae +// /* "":11954:11971 */ +// sstore +// /* "":11987:11990 */ +// 0xad +// /* "":11980:11997 */ +// sstore +// /* "":12013:12016 */ +// 0xac +// /* "":12006:12023 */ +// sstore +// /* "":12039:12042 */ +// 0xab +// /* "":12032:12049 */ +// sstore +// /* "":12065:12068 */ +// 0xaa +// /* "":12058:12075 */ +// sstore +// /* "":12091:12094 */ +// 0xa9 +// /* "":12084:12101 */ +// sstore +// /* "":12117:12120 */ +// 0xa8 +// /* "":12110:12127 */ +// sstore +// /* "":12143:12146 */ +// 0xa7 +// /* "":12136:12153 */ +// sstore +// /* "":12169:12172 */ +// 0xa6 +// /* "":12162:12179 */ +// sstore +// /* "":12195:12198 */ +// 0xa5 +// /* "":12188:12205 */ +// sstore +// /* "":12221:12224 */ +// 0xa4 +// /* "":12214:12231 */ +// sstore +// /* "":12247:12250 */ +// 0xa3 +// /* "":12240:12257 */ +// sstore +// /* "":12273:12276 */ +// 0xa2 +// /* "":12266:12283 */ +// sstore +// /* "":12299:12302 */ +// 0xa1 +// /* "":12292:12309 */ +// sstore +// /* "":12325:12328 */ +// 0xa0 +// /* "":12318:12335 */ +// sstore +// /* "":12351:12354 */ +// 0x9f +// /* "":12344:12361 */ +// sstore +// /* "":12377:12380 */ +// 0x9e +// /* "":12370:12387 */ +// sstore +// /* "":12403:12406 */ +// 0x9d +// /* "":12396:12413 */ +// sstore +// /* "":12429:12432 */ +// 0x9c +// /* "":12422:12439 */ +// sstore +// /* "":12455:12458 */ +// 0x9b +// /* "":12448:12465 */ +// sstore +// /* "":12481:12484 */ +// 0x9a +// /* "":12474:12491 */ +// sstore +// /* "":12507:12510 */ +// 0x99 +// /* "":12500:12517 */ +// sstore +// /* "":12533:12536 */ +// 0x98 +// /* "":12526:12543 */ +// sstore +// /* "":12559:12562 */ +// 0x97 +// /* "":12552:12569 */ +// sstore +// /* "":12585:12588 */ +// 0x96 +// /* "":12578:12595 */ +// sstore +// /* "":12611:12614 */ +// 0x95 +// /* "":12604:12621 */ +// sstore +// /* "":12637:12640 */ +// 0x94 +// /* "":12630:12647 */ +// sstore +// /* "":12663:12666 */ +// 0x93 +// /* "":12656:12673 */ +// sstore +// /* "":12689:12692 */ +// 0x92 +// /* "":12682:12699 */ +// sstore +// /* "":12715:12718 */ +// 0x91 +// /* "":12708:12725 */ +// sstore +// /* "":12741:12744 */ +// 0x90 +// /* "":12734:12751 */ +// sstore +// /* "":12767:12770 */ +// 0x8f +// /* "":12760:12777 */ +// sstore +// /* "":12793:12796 */ +// 0x8e +// /* "":12786:12803 */ +// sstore +// /* "":12819:12822 */ +// 0x8d +// /* "":12812:12829 */ +// sstore +// /* "":12845:12848 */ +// 0x8c +// /* "":12838:12855 */ +// sstore +// /* "":12871:12874 */ +// 0x8b +// /* "":12864:12881 */ +// sstore +// /* "":12897:12900 */ +// 0x8a +// /* "":12890:12907 */ +// sstore +// /* "":12923:12926 */ +// 0x89 +// /* "":12916:12933 */ +// sstore +// /* "":12949:12952 */ +// 0x88 +// /* "":12942:12959 */ +// sstore +// /* "":12975:12978 */ +// 0x87 +// /* "":12968:12985 */ +// sstore +// /* "":13001:13004 */ +// 0x86 +// /* "":12994:13011 */ +// sstore +// /* "":13027:13030 */ +// 0x85 +// /* "":13020:13037 */ +// sstore +// /* "":13053:13056 */ +// 0x84 +// /* "":13046:13063 */ +// sstore +// /* "":13079:13082 */ +// 0x83 +// /* "":13072:13089 */ +// sstore +// /* "":13105:13108 */ +// 0x82 +// /* "":13098:13115 */ +// sstore +// /* "":13131:13134 */ +// 0x81 +// /* "":13124:13141 */ +// sstore +// /* "":13157:13160 */ +// 0x80 +// /* "":13150:13167 */ +// sstore +// /* "":13183:13186 */ +// 0x7f +// /* "":13176:13193 */ +// sstore +// /* "":13209:13212 */ +// 0x7e +// /* "":13202:13219 */ +// sstore +// /* "":13235:13238 */ +// 0x7d +// /* "":13228:13245 */ +// sstore +// /* "":13261:13264 */ +// 0x7c +// /* "":13254:13271 */ +// sstore +// /* "":13287:13290 */ +// 0x7b +// /* "":13280:13297 */ +// sstore +// /* "":13313:13316 */ +// 0x7a +// /* "":13306:13323 */ +// sstore +// /* "":13339:13342 */ +// 0x79 +// /* "":13332:13349 */ +// sstore +// /* "":13365:13368 */ +// 0x78 +// /* "":13358:13375 */ +// sstore +// /* "":13391:13394 */ +// 0x77 +// /* "":13384:13401 */ +// sstore +// /* "":13417:13420 */ +// 0x76 +// /* "":13410:13427 */ +// sstore +// /* "":13443:13446 */ +// 0x75 +// /* "":13436:13453 */ +// sstore +// /* "":13469:13472 */ +// 0x74 +// /* "":13462:13479 */ +// sstore +// /* "":13495:13498 */ +// 0x73 +// /* "":13488:13505 */ +// sstore +// /* "":13521:13524 */ +// 0x72 +// /* "":13514:13531 */ +// sstore +// /* "":13547:13550 */ +// 0x71 +// /* "":13540:13557 */ +// sstore +// /* "":13573:13576 */ +// 0x70 +// /* "":13566:13583 */ +// sstore +// /* "":13599:13602 */ +// 0x6f +// /* "":13592:13609 */ +// sstore +// /* "":13625:13628 */ +// 0x6e +// /* "":13618:13635 */ +// sstore +// /* "":13651:13654 */ +// 0x6d +// /* "":13644:13661 */ +// sstore +// /* "":13677:13680 */ +// 0x6c +// /* "":13670:13687 */ +// sstore +// /* "":13703:13706 */ +// 0x6b +// /* "":13696:13713 */ +// sstore +// /* "":13729:13732 */ +// 0x6a +// /* "":13722:13739 */ +// sstore +// /* "":13755:13758 */ +// 0x69 +// /* "":13748:13765 */ +// sstore +// /* "":13781:13784 */ +// 0x68 +// /* "":13774:13791 */ +// sstore +// /* "":13807:13810 */ +// 0x67 +// /* "":13800:13817 */ +// sstore +// /* "":13833:13836 */ +// 0x66 +// /* "":13826:13843 */ +// sstore +// /* "":13859:13862 */ +// 0x65 +// /* "":13852:13869 */ +// sstore +// /* "":13885:13888 */ +// 0x64 +// /* "":13878:13895 */ +// sstore +// /* "":13911:13913 */ +// 0x63 +// /* "":13904:13919 */ +// sstore +// /* "":13935:13937 */ +// 0x62 +// /* "":13928:13943 */ +// sstore +// /* "":13959:13961 */ +// 0x61 +// /* "":13952:13967 */ +// sstore +// /* "":13983:13985 */ +// 0x60 +// /* "":13976:13991 */ +// sstore +// /* "":14007:14009 */ +// 0x5f +// /* "":14000:14015 */ +// sstore +// /* "":14031:14033 */ +// 0x5e +// /* "":14024:14039 */ +// sstore +// /* "":14055:14057 */ +// 0x5d +// /* "":14048:14063 */ +// sstore +// /* "":14079:14081 */ +// 0x5c +// /* "":14072:14087 */ +// sstore +// /* "":14103:14105 */ +// 0x5b +// /* "":14096:14111 */ +// sstore +// /* "":14127:14129 */ +// 0x5a +// /* "":14120:14135 */ +// sstore +// /* "":14151:14153 */ +// 0x59 +// /* "":14144:14159 */ +// sstore +// /* "":14175:14177 */ +// 0x58 +// /* "":14168:14183 */ +// sstore +// /* "":14199:14201 */ +// 0x57 +// /* "":14192:14207 */ +// sstore +// /* "":14223:14225 */ +// 0x56 +// /* "":14216:14231 */ +// sstore +// /* "":14247:14249 */ +// 0x55 +// /* "":14240:14255 */ +// sstore +// /* "":14271:14273 */ +// 0x54 +// /* "":14264:14279 */ +// sstore +// /* "":14295:14297 */ +// 0x53 +// /* "":14288:14303 */ +// sstore +// /* "":14319:14321 */ +// 0x52 +// /* "":14312:14327 */ +// sstore +// /* "":14343:14345 */ +// 0x51 +// /* "":14336:14351 */ +// sstore +// /* "":14367:14369 */ +// 0x50 +// /* "":14360:14375 */ +// sstore +// /* "":14391:14393 */ +// 0x4f +// /* "":14384:14399 */ +// sstore +// /* "":14415:14417 */ +// 0x4e +// /* "":14408:14423 */ +// sstore +// /* "":14439:14441 */ +// 0x4d +// /* "":14432:14447 */ +// sstore +// /* "":14463:14465 */ +// 0x4c +// /* "":14456:14471 */ +// sstore +// /* "":14487:14489 */ +// 0x4b +// /* "":14480:14495 */ +// sstore +// /* "":14511:14513 */ +// 0x4a +// /* "":14504:14519 */ +// sstore +// /* "":14535:14537 */ +// 0x49 +// /* "":14528:14543 */ +// sstore +// /* "":14559:14561 */ +// 0x48 +// /* "":14552:14567 */ +// sstore +// /* "":14583:14585 */ +// 0x47 +// /* "":14576:14591 */ +// sstore +// /* "":14607:14609 */ +// 0x46 +// /* "":14600:14615 */ +// sstore +// /* "":14631:14633 */ +// 0x45 +// /* "":14624:14639 */ +// sstore +// /* "":14655:14657 */ +// 0x44 +// /* "":14648:14663 */ +// sstore +// /* "":14679:14681 */ +// 0x43 +// /* "":14672:14687 */ +// sstore +// /* "":14703:14705 */ +// 0x42 +// /* "":14696:14711 */ +// sstore +// /* "":14727:14729 */ +// 0x41 +// /* "":14720:14735 */ +// sstore +// /* "":14751:14753 */ +// 0x40 +// /* "":14744:14759 */ +// sstore +// /* "":14775:14777 */ +// 0x3f +// /* "":14768:14783 */ +// sstore +// /* "":14799:14801 */ +// 0x3e +// /* "":14792:14807 */ +// sstore +// /* "":14823:14825 */ +// 0x3d +// /* "":14816:14831 */ +// sstore +// /* "":14847:14849 */ +// 0x3c +// /* "":14840:14855 */ +// sstore +// /* "":14871:14873 */ +// 0x3b +// /* "":14864:14879 */ +// sstore +// /* "":14895:14897 */ +// 0x3a +// /* "":14888:14903 */ +// sstore +// /* "":14919:14921 */ +// 0x39 +// /* "":14912:14927 */ +// sstore +// /* "":14943:14945 */ +// 0x38 +// /* "":14936:14951 */ +// sstore +// /* "":14967:14969 */ +// 0x37 +// /* "":14960:14975 */ +// sstore +// /* "":14991:14993 */ +// 0x36 +// /* "":14984:14999 */ +// sstore +// /* "":15015:15017 */ +// 0x35 +// /* "":15008:15023 */ +// sstore +// /* "":15039:15041 */ +// 0x34 +// /* "":15032:15047 */ +// sstore +// /* "":15063:15065 */ +// 0x33 +// /* "":15056:15071 */ +// sstore +// /* "":15087:15089 */ +// 0x32 +// /* "":15080:15095 */ +// sstore +// /* "":15111:15113 */ +// 0x31 +// /* "":15104:15119 */ +// sstore +// /* "":15135:15137 */ +// 0x30 +// /* "":15128:15143 */ +// sstore +// /* "":15159:15161 */ +// 0x2f +// /* "":15152:15167 */ +// sstore +// /* "":15183:15185 */ +// 0x2e +// /* "":15176:15191 */ +// sstore +// /* "":15207:15209 */ +// 0x2d +// /* "":15200:15215 */ +// sstore +// /* "":15231:15233 */ +// 0x2c +// /* "":15224:15239 */ +// sstore +// /* "":15255:15257 */ +// 0x2b +// /* "":15248:15263 */ +// sstore +// /* "":15279:15281 */ +// 0x2a +// /* "":15272:15287 */ +// sstore +// /* "":15303:15305 */ +// 0x29 +// /* "":15296:15311 */ +// sstore +// /* "":15327:15329 */ +// 0x28 +// /* "":15320:15335 */ +// sstore +// /* "":15351:15353 */ +// 0x27 +// /* "":15344:15359 */ +// sstore +// /* "":15375:15377 */ +// 0x26 +// /* "":15368:15383 */ +// sstore +// /* "":15399:15401 */ +// 0x25 +// /* "":15392:15407 */ +// sstore +// /* "":15423:15425 */ +// 0x24 +// /* "":15416:15431 */ +// sstore +// /* "":15447:15449 */ +// 0x23 +// /* "":15440:15455 */ +// sstore +// /* "":15471:15473 */ +// 0x22 +// /* "":15464:15479 */ +// sstore +// /* "":15495:15497 */ +// 0x21 +// /* "":15488:15503 */ +// sstore +// /* "":15519:15521 */ +// 0x20 +// /* "":15512:15527 */ +// sstore +// /* "":15543:15545 */ +// 0x1f +// /* "":15536:15551 */ +// sstore +// /* "":15567:15569 */ +// 0x1e +// /* "":15560:15575 */ +// sstore +// /* "":15591:15593 */ +// 0x1d +// /* "":15584:15599 */ +// sstore +// /* "":15615:15617 */ +// 0x1c +// /* "":15608:15623 */ +// sstore +// /* "":15639:15641 */ +// 0x1b +// /* "":15632:15647 */ +// sstore +// /* "":15663:15665 */ +// 0x1a +// /* "":15656:15671 */ +// sstore +// /* "":15687:15689 */ +// 0x19 +// /* "":15680:15695 */ +// sstore +// /* "":15711:15713 */ +// 0x18 +// /* "":15704:15719 */ +// sstore +// /* "":15735:15737 */ +// 0x17 +// /* "":15728:15743 */ +// sstore +// /* "":15759:15761 */ +// 0x16 +// /* "":15752:15767 */ +// sstore +// /* "":15783:15785 */ +// 0x15 +// /* "":15776:15791 */ +// sstore +// /* "":15807:15809 */ +// 0x14 +// /* "":15800:15815 */ +// sstore +// /* "":15831:15833 */ +// 0x13 +// /* "":15824:15839 */ +// sstore +// /* "":15855:15857 */ +// 0x12 +// /* "":15848:15863 */ +// sstore +// /* "":15879:15881 */ +// 0x11 +// /* "":15872:15887 */ +// sstore +// /* "":15903:15905 */ +// 0x10 +// /* "":15896:15911 */ +// sstore +// /* "":15927:15929 */ +// 0x0f +// /* "":15920:15935 */ +// sstore +// /* "":15951:15953 */ +// 0x0e +// /* "":15944:15959 */ +// sstore +// /* "":15975:15977 */ +// 0x0d +// /* "":15968:15983 */ +// sstore +// /* "":15999:16001 */ +// 0x0c +// /* "":15992:16007 */ +// sstore +// /* "":16023:16025 */ +// 0x0b +// /* "":16016:16031 */ +// sstore +// /* "":16047:16049 */ +// 0x0a +// /* "":16040:16055 */ +// sstore +// /* "":16071:16072 */ +// 0x09 +// /* "":16064:16077 */ +// sstore +// /* "":16093:16094 */ +// 0x08 +// /* "":16086:16099 */ +// sstore +// /* "":16115:16116 */ +// 0x07 +// /* "":16108:16121 */ +// sstore +// /* "":16137:16138 */ +// 0x06 +// /* "":16130:16143 */ +// sstore +// /* "":16159:16160 */ +// 0x05 +// /* "":16152:16165 */ +// sstore +// /* "":16181:16182 */ +// 0x04 +// /* "":16174:16187 */ +// sstore +// /* "":16203:16204 */ +// 0x03 +// /* "":16196:16209 */ +// sstore +// /* "":16225:16226 */ +// 0x02 +// /* "":16218:16231 */ +// sstore +// /* "":16247:16248 */ +// 0x01 +// /* "":16240:16253 */ +// sstore +// /* "":16269:16270 */ +// 0x00 +// /* "":16262:16275 */ +// sstore +// /* "":25:16281 */ +// stop +// /* "":9800:9815 */ +// tag_1: +// /* "":9811:9812 */ +// 0x00 +// /* "":9802:9813 */ +// dup1 +// revert diff --git a/test/libyul/evmCodeTransform/eof_swap17.yul b/test/libyul/evmCodeTransform/eof_swap17.yul new file mode 100644 index 000000000..1f9b993cc --- /dev/null +++ b/test/libyul/evmCodeTransform/eof_swap17.yul @@ -0,0 +1,229 @@ +object "main" { + code { + // v17 is 17 slots deep in stack - all values in between are still needed - no way to avoid a swapn{17}. + // Running this without EOF, as expected, throws stack-too-deep. + function f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14, v15, v16, v17) { + sstore(17, v17) + sstore(16, v16) + sstore(15, v15) + sstore(14, v14) + sstore(13, v13) + sstore(12, v12) + sstore(11, v11) + sstore(10, v10) + sstore(9, v09) + sstore(8, v08) + sstore(7, v07) + sstore(6, v06) + sstore(5, v05) + sstore(4, v04) + sstore(3, v03) + sstore(2, v02) + sstore(1, v01) + sstore(0, v00) + } + f( + calldataload(0), + calldataload(1), + calldataload(2), + calldataload(3), + calldataload(4), + calldataload(5), + calldataload(6), + calldataload(7), + calldataload(8), + calldataload(9), + calldataload(10), + calldataload(11), + calldataload(12), + calldataload(13), + calldataload(14), + calldataload(15), + calldataload(16), + calldataload(17) + ) + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// stackOptimization: true +// ---- +// /* "":1361:1363 */ +// 0x11 +// /* "":1348:1364 */ +// calldataload +// /* "":1331:1333 */ +// 0x10 +// /* "":1318:1334 */ +// calldataload +// /* "":1301:1303 */ +// 0x0f +// /* "":1288:1304 */ +// calldataload +// /* "":1271:1273 */ +// 0x0e +// /* "":1258:1274 */ +// calldataload +// /* "":1241:1243 */ +// 0x0d +// /* "":1228:1244 */ +// calldataload +// /* "":1211:1213 */ +// 0x0c +// /* "":1198:1214 */ +// calldataload +// /* "":1181:1183 */ +// 0x0b +// /* "":1168:1184 */ +// calldataload +// /* "":1151:1153 */ +// 0x0a +// /* "":1138:1154 */ +// calldataload +// /* "":1122:1123 */ +// 0x09 +// /* "":1109:1124 */ +// calldataload +// /* "":1093:1094 */ +// 0x08 +// /* "":1080:1095 */ +// calldataload +// /* "":1064:1065 */ +// 0x07 +// /* "":1051:1066 */ +// calldataload +// /* "":1035:1036 */ +// 0x06 +// /* "":1022:1037 */ +// calldataload +// /* "":1006:1007 */ +// 0x05 +// /* "":993:1008 */ +// calldataload +// /* "":977:978 */ +// 0x04 +// /* "":964:979 */ +// calldataload +// /* "":948:949 */ +// 0x03 +// /* "":935:950 */ +// calldataload +// /* "":919:920 */ +// 0x02 +// /* "":906:921 */ +// calldataload +// /* "":890:891 */ +// 0x01 +// /* "":877:892 */ +// calldataload +// /* "":861:862 */ +// 0x00 +// /* "":848:863 */ +// calldataload +// /* "":833:1374 */ +// callf{code_section_1} +// /* "":22:1377 */ +// stop +// +// code_section_1: assembly { +// /* "":218:824 */ +// swapn{17} +// swap16 +// swap1 +// swap16 +// swap15 +// swap2 +// swap15 +// swap14 +// swap3 +// swap14 +// swap13 +// swap4 +// swap13 +// swap12 +// swap5 +// swap12 +// swap11 +// swap6 +// swap11 +// swap10 +// swap7 +// swap10 +// swap9 +// swap8 +// swap9 +// /* "":340:342 */ +// 0x11 +// /* "":333:348 */ +// sstore +// /* "":368:370 */ +// 0x10 +// /* "":361:376 */ +// sstore +// /* "":396:398 */ +// 0x0f +// /* "":389:404 */ +// sstore +// /* "":424:426 */ +// 0x0e +// /* "":417:432 */ +// sstore +// /* "":452:454 */ +// 0x0d +// /* "":445:460 */ +// sstore +// /* "":480:482 */ +// 0x0c +// /* "":473:488 */ +// sstore +// /* "":508:510 */ +// 0x0b +// /* "":501:516 */ +// sstore +// /* "":536:538 */ +// 0x0a +// /* "":529:544 */ +// sstore +// /* "":564:565 */ +// 0x09 +// /* "":557:571 */ +// sstore +// /* "":591:592 */ +// 0x08 +// /* "":584:598 */ +// sstore +// /* "":618:619 */ +// 0x07 +// /* "":611:625 */ +// sstore +// /* "":645:646 */ +// 0x06 +// /* "":638:652 */ +// sstore +// /* "":672:673 */ +// 0x05 +// /* "":665:679 */ +// sstore +// /* "":699:700 */ +// 0x04 +// /* "":692:706 */ +// sstore +// /* "":726:727 */ +// 0x03 +// /* "":719:733 */ +// sstore +// /* "":753:754 */ +// 0x02 +// /* "":746:760 */ +// sstore +// /* "":780:781 */ +// 0x01 +// /* "":773:787 */ +// sstore +// /* "":807:808 */ +// 0x00 +// /* "":800:814 */ +// sstore +// /* "":218:824 */ +// retf +// } diff --git a/test/libyul/evmCodeTransform/eof_swap256.yul b/test/libyul/evmCodeTransform/eof_swap256.yul new file mode 100644 index 000000000..f718937be --- /dev/null +++ b/test/libyul/evmCodeTransform/eof_swap256.yul @@ -0,0 +1,2839 @@ +object "main" { + code { + // Triggers a swapn{256}. Generating one more variable results in a stack-too-deep. + // Note that this relies on not running the optimizer here. With optimizer this code + // can become entirely swap-free. + let v0 := calldataload(0) + let v1 := calldataload(1) + let v2 := calldataload(2) + let v3 := calldataload(3) + let v4 := calldataload(4) + let v5 := calldataload(5) + let v6 := calldataload(6) + let v7 := calldataload(7) + let v8 := calldataload(8) + let v9 := calldataload(9) + let v10 := calldataload(10) + let v11 := calldataload(11) + let v12 := calldataload(12) + let v13 := calldataload(13) + let v14 := calldataload(14) + let v15 := calldataload(15) + let v16 := calldataload(16) + let v17 := calldataload(17) + let v18 := calldataload(18) + let v19 := calldataload(19) + let v20 := calldataload(20) + let v21 := calldataload(21) + let v22 := calldataload(22) + let v23 := calldataload(23) + let v24 := calldataload(24) + let v25 := calldataload(25) + let v26 := calldataload(26) + let v27 := calldataload(27) + let v28 := calldataload(28) + let v29 := calldataload(29) + let v30 := calldataload(30) + let v31 := calldataload(31) + let v32 := calldataload(32) + let v33 := calldataload(33) + let v34 := calldataload(34) + let v35 := calldataload(35) + let v36 := calldataload(36) + let v37 := calldataload(37) + let v38 := calldataload(38) + let v39 := calldataload(39) + let v40 := calldataload(40) + let v41 := calldataload(41) + let v42 := calldataload(42) + let v43 := calldataload(43) + let v44 := calldataload(44) + let v45 := calldataload(45) + let v46 := calldataload(46) + let v47 := calldataload(47) + let v48 := calldataload(48) + let v49 := calldataload(49) + let v50 := calldataload(50) + let v51 := calldataload(51) + let v52 := calldataload(52) + let v53 := calldataload(53) + let v54 := calldataload(54) + let v55 := calldataload(55) + let v56 := calldataload(56) + let v57 := calldataload(57) + let v58 := calldataload(58) + let v59 := calldataload(59) + let v60 := calldataload(60) + let v61 := calldataload(61) + let v62 := calldataload(62) + let v63 := calldataload(63) + let v64 := calldataload(64) + let v65 := calldataload(65) + let v66 := calldataload(66) + let v67 := calldataload(67) + let v68 := calldataload(68) + let v69 := calldataload(69) + let v70 := calldataload(70) + let v71 := calldataload(71) + let v72 := calldataload(72) + let v73 := calldataload(73) + let v74 := calldataload(74) + let v75 := calldataload(75) + let v76 := calldataload(76) + let v77 := calldataload(77) + let v78 := calldataload(78) + let v79 := calldataload(79) + let v80 := calldataload(80) + let v81 := calldataload(81) + let v82 := calldataload(82) + let v83 := calldataload(83) + let v84 := calldataload(84) + let v85 := calldataload(85) + let v86 := calldataload(86) + let v87 := calldataload(87) + let v88 := calldataload(88) + let v89 := calldataload(89) + let v90 := calldataload(90) + let v91 := calldataload(91) + let v92 := calldataload(92) + let v93 := calldataload(93) + let v94 := calldataload(94) + let v95 := calldataload(95) + let v96 := calldataload(96) + let v97 := calldataload(97) + let v98 := calldataload(98) + let v99 := calldataload(99) + let v100 := calldataload(100) + let v101 := calldataload(101) + let v102 := calldataload(102) + let v103 := calldataload(103) + let v104 := calldataload(104) + let v105 := calldataload(105) + let v106 := calldataload(106) + let v107 := calldataload(107) + let v108 := calldataload(108) + let v109 := calldataload(109) + let v110 := calldataload(110) + let v111 := calldataload(111) + let v112 := calldataload(112) + let v113 := calldataload(113) + let v114 := calldataload(114) + let v115 := calldataload(115) + let v116 := calldataload(116) + let v117 := calldataload(117) + let v118 := calldataload(118) + let v119 := calldataload(119) + let v120 := calldataload(120) + let v121 := calldataload(121) + let v122 := calldataload(122) + let v123 := calldataload(123) + let v124 := calldataload(124) + let v125 := calldataload(125) + let v126 := calldataload(126) + let v127 := calldataload(127) + let v128 := calldataload(128) + let v129 := calldataload(129) + let v130 := calldataload(130) + let v131 := calldataload(131) + let v132 := calldataload(132) + let v133 := calldataload(133) + let v134 := calldataload(134) + let v135 := calldataload(135) + let v136 := calldataload(136) + let v137 := calldataload(137) + let v138 := calldataload(138) + let v139 := calldataload(139) + let v140 := calldataload(140) + let v141 := calldataload(141) + let v142 := calldataload(142) + let v143 := calldataload(143) + let v144 := calldataload(144) + let v145 := calldataload(145) + let v146 := calldataload(146) + let v147 := calldataload(147) + let v148 := calldataload(148) + let v149 := calldataload(149) + let v150 := calldataload(150) + let v151 := calldataload(151) + let v152 := calldataload(152) + let v153 := calldataload(153) + let v154 := calldataload(154) + let v155 := calldataload(155) + let v156 := calldataload(156) + let v157 := calldataload(157) + let v158 := calldataload(158) + let v159 := calldataload(159) + let v160 := calldataload(160) + let v161 := calldataload(161) + let v162 := calldataload(162) + let v163 := calldataload(163) + let v164 := calldataload(164) + let v165 := calldataload(165) + let v166 := calldataload(166) + let v167 := calldataload(167) + let v168 := calldataload(168) + let v169 := calldataload(169) + let v170 := calldataload(170) + let v171 := calldataload(171) + let v172 := calldataload(172) + let v173 := calldataload(173) + let v174 := calldataload(174) + let v175 := calldataload(175) + let v176 := calldataload(176) + let v177 := calldataload(177) + let v178 := calldataload(178) + let v179 := calldataload(179) + let v180 := calldataload(180) + let v181 := calldataload(181) + let v182 := calldataload(182) + let v183 := calldataload(183) + let v184 := calldataload(184) + let v185 := calldataload(185) + let v186 := calldataload(186) + let v187 := calldataload(187) + let v188 := calldataload(188) + let v189 := calldataload(189) + let v190 := calldataload(190) + let v191 := calldataload(191) + let v192 := calldataload(192) + let v193 := calldataload(193) + let v194 := calldataload(194) + let v195 := calldataload(195) + let v196 := calldataload(196) + let v197 := calldataload(197) + let v198 := calldataload(198) + let v199 := calldataload(199) + let v200 := calldataload(200) + let v201 := calldataload(201) + let v202 := calldataload(202) + let v203 := calldataload(203) + let v204 := calldataload(204) + let v205 := calldataload(205) + let v206 := calldataload(206) + let v207 := calldataload(207) + let v208 := calldataload(208) + let v209 := calldataload(209) + let v210 := calldataload(210) + let v211 := calldataload(211) + let v212 := calldataload(212) + let v213 := calldataload(213) + let v214 := calldataload(214) + let v215 := calldataload(215) + let v216 := calldataload(216) + let v217 := calldataload(217) + let v218 := calldataload(218) + let v219 := calldataload(219) + let v220 := calldataload(220) + let v221 := calldataload(221) + let v222 := calldataload(222) + let v223 := calldataload(223) + let v224 := calldataload(224) + let v225 := calldataload(225) + let v226 := calldataload(226) + let v227 := calldataload(227) + let v228 := calldataload(228) + let v229 := calldataload(229) + let v230 := calldataload(230) + let v231 := calldataload(231) + let v232 := calldataload(232) + let v233 := calldataload(233) + let v234 := calldataload(234) + let v235 := calldataload(235) + let v236 := calldataload(236) + let v237 := calldataload(237) + let v238 := calldataload(238) + let v239 := calldataload(239) + let v240 := calldataload(240) + let v241 := calldataload(241) + let v242 := calldataload(242) + let v243 := calldataload(243) + let v244 := calldataload(244) + let v245 := calldataload(245) + let v246 := calldataload(246) + let v247 := calldataload(247) + let v248 := calldataload(248) + let v249 := calldataload(249) + let v250 := calldataload(250) + let v251 := calldataload(251) + let v252 := calldataload(252) + let v253 := calldataload(253) + let v254 := calldataload(254) + let v255 := calldataload(255) + let v256 := calldataload(256) + sstore(0, v0) + sstore(1, v1) + sstore(2, v2) + sstore(3, v3) + sstore(4, v4) + sstore(5, v5) + sstore(6, v6) + sstore(7, v7) + sstore(8, v8) + sstore(9, v9) + sstore(10, v10) + sstore(11, v11) + sstore(12, v12) + sstore(13, v13) + sstore(14, v14) + sstore(15, v15) + sstore(16, v16) + sstore(17, v17) + sstore(18, v18) + sstore(19, v19) + sstore(20, v20) + sstore(21, v21) + sstore(22, v22) + sstore(23, v23) + sstore(24, v24) + sstore(25, v25) + sstore(26, v26) + sstore(27, v27) + sstore(28, v28) + sstore(29, v29) + sstore(30, v30) + sstore(31, v31) + sstore(32, v32) + sstore(33, v33) + sstore(34, v34) + sstore(35, v35) + sstore(36, v36) + sstore(37, v37) + sstore(38, v38) + sstore(39, v39) + sstore(40, v40) + sstore(41, v41) + sstore(42, v42) + sstore(43, v43) + sstore(44, v44) + sstore(45, v45) + sstore(46, v46) + sstore(47, v47) + sstore(48, v48) + sstore(49, v49) + sstore(50, v50) + sstore(51, v51) + sstore(52, v52) + sstore(53, v53) + sstore(54, v54) + sstore(55, v55) + sstore(56, v56) + sstore(57, v57) + sstore(58, v58) + sstore(59, v59) + sstore(60, v60) + sstore(61, v61) + sstore(62, v62) + sstore(63, v63) + sstore(64, v64) + sstore(65, v65) + sstore(66, v66) + sstore(67, v67) + sstore(68, v68) + sstore(69, v69) + sstore(70, v70) + sstore(71, v71) + sstore(72, v72) + sstore(73, v73) + sstore(74, v74) + sstore(75, v75) + sstore(76, v76) + sstore(77, v77) + sstore(78, v78) + sstore(79, v79) + sstore(80, v80) + sstore(81, v81) + sstore(82, v82) + sstore(83, v83) + sstore(84, v84) + sstore(85, v85) + sstore(86, v86) + sstore(87, v87) + sstore(88, v88) + sstore(89, v89) + sstore(90, v90) + sstore(91, v91) + sstore(92, v92) + sstore(93, v93) + sstore(94, v94) + sstore(95, v95) + sstore(96, v96) + sstore(97, v97) + sstore(98, v98) + sstore(99, v99) + sstore(100, v100) + sstore(101, v101) + sstore(102, v102) + sstore(103, v103) + sstore(104, v104) + sstore(105, v105) + sstore(106, v106) + sstore(107, v107) + sstore(108, v108) + sstore(109, v109) + sstore(110, v110) + sstore(111, v111) + sstore(112, v112) + sstore(113, v113) + sstore(114, v114) + sstore(115, v115) + sstore(116, v116) + sstore(117, v117) + sstore(118, v118) + sstore(119, v119) + sstore(120, v120) + sstore(121, v121) + sstore(122, v122) + sstore(123, v123) + sstore(124, v124) + sstore(125, v125) + sstore(126, v126) + sstore(127, v127) + sstore(128, v128) + sstore(129, v129) + sstore(130, v130) + sstore(131, v131) + sstore(132, v132) + sstore(133, v133) + sstore(134, v134) + sstore(135, v135) + sstore(136, v136) + sstore(137, v137) + sstore(138, v138) + sstore(139, v139) + sstore(140, v140) + sstore(141, v141) + sstore(142, v142) + sstore(143, v143) + sstore(144, v144) + sstore(145, v145) + sstore(146, v146) + sstore(147, v147) + sstore(148, v148) + sstore(149, v149) + sstore(150, v150) + sstore(151, v151) + sstore(152, v152) + sstore(153, v153) + sstore(154, v154) + sstore(155, v155) + sstore(156, v156) + sstore(157, v157) + sstore(158, v158) + sstore(159, v159) + sstore(160, v160) + sstore(161, v161) + sstore(162, v162) + sstore(163, v163) + sstore(164, v164) + sstore(165, v165) + sstore(166, v166) + sstore(167, v167) + sstore(168, v168) + sstore(169, v169) + sstore(170, v170) + sstore(171, v171) + sstore(172, v172) + sstore(173, v173) + sstore(174, v174) + sstore(175, v175) + sstore(176, v176) + sstore(177, v177) + sstore(178, v178) + sstore(179, v179) + sstore(180, v180) + sstore(181, v181) + sstore(182, v182) + sstore(183, v183) + sstore(184, v184) + sstore(185, v185) + sstore(186, v186) + sstore(187, v187) + sstore(188, v188) + sstore(189, v189) + sstore(190, v190) + sstore(191, v191) + sstore(192, v192) + sstore(193, v193) + sstore(194, v194) + sstore(195, v195) + sstore(196, v196) + sstore(197, v197) + sstore(198, v198) + sstore(199, v199) + sstore(200, v200) + sstore(201, v201) + sstore(202, v202) + sstore(203, v203) + sstore(204, v204) + sstore(205, v205) + sstore(206, v206) + sstore(207, v207) + sstore(208, v208) + sstore(209, v209) + sstore(210, v210) + sstore(211, v211) + sstore(212, v212) + sstore(213, v213) + sstore(214, v214) + sstore(215, v215) + sstore(216, v216) + sstore(217, v217) + sstore(218, v218) + sstore(219, v219) + sstore(220, v220) + sstore(221, v221) + sstore(222, v222) + sstore(223, v223) + sstore(224, v224) + sstore(225, v225) + sstore(226, v226) + sstore(227, v227) + sstore(228, v228) + sstore(229, v229) + sstore(230, v230) + sstore(231, v231) + sstore(232, v232) + sstore(233, v233) + sstore(234, v234) + sstore(235, v235) + sstore(236, v236) + sstore(237, v237) + sstore(238, v238) + sstore(239, v239) + sstore(240, v240) + sstore(241, v241) + sstore(242, v242) + sstore(243, v243) + sstore(244, v244) + sstore(245, v245) + sstore(246, v246) + sstore(247, v247) + sstore(248, v248) + sstore(249, v249) + sstore(250, v250) + sstore(251, v251) + sstore(252, v252) + sstore(253, v253) + sstore(254, v254) + sstore(255, v255) + sstore(256, v256) + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// stackOptimization: true +// ---- +// /* "":285:286 */ +// 0x00 +// /* "":272:287 */ +// calldataload +// /* "":319:320 */ +// 0x01 +// /* "":306:321 */ +// calldataload +// /* "":353:354 */ +// 0x02 +// /* "":340:355 */ +// calldataload +// /* "":387:388 */ +// 0x03 +// /* "":374:389 */ +// calldataload +// /* "":421:422 */ +// 0x04 +// /* "":408:423 */ +// calldataload +// /* "":455:456 */ +// 0x05 +// /* "":442:457 */ +// calldataload +// /* "":489:490 */ +// 0x06 +// /* "":476:491 */ +// calldataload +// /* "":523:524 */ +// 0x07 +// /* "":510:525 */ +// calldataload +// /* "":557:558 */ +// 0x08 +// /* "":544:559 */ +// calldataload +// /* "":591:592 */ +// 0x09 +// /* "":578:593 */ +// calldataload +// /* "":626:628 */ +// 0x0a +// /* "":613:629 */ +// calldataload +// /* "":662:664 */ +// 0x0b +// /* "":649:665 */ +// calldataload +// /* "":698:700 */ +// 0x0c +// /* "":685:701 */ +// calldataload +// /* "":734:736 */ +// 0x0d +// /* "":721:737 */ +// calldataload +// /* "":770:772 */ +// 0x0e +// /* "":757:773 */ +// calldataload +// /* "":806:808 */ +// 0x0f +// /* "":793:809 */ +// calldataload +// /* "":842:844 */ +// 0x10 +// /* "":829:845 */ +// calldataload +// /* "":878:880 */ +// 0x11 +// /* "":865:881 */ +// calldataload +// /* "":914:916 */ +// 0x12 +// /* "":901:917 */ +// calldataload +// /* "":950:952 */ +// 0x13 +// /* "":937:953 */ +// calldataload +// /* "":986:988 */ +// 0x14 +// /* "":973:989 */ +// calldataload +// /* "":1022:1024 */ +// 0x15 +// /* "":1009:1025 */ +// calldataload +// /* "":1058:1060 */ +// 0x16 +// /* "":1045:1061 */ +// calldataload +// /* "":1094:1096 */ +// 0x17 +// /* "":1081:1097 */ +// calldataload +// /* "":1130:1132 */ +// 0x18 +// /* "":1117:1133 */ +// calldataload +// /* "":1166:1168 */ +// 0x19 +// /* "":1153:1169 */ +// calldataload +// /* "":1202:1204 */ +// 0x1a +// /* "":1189:1205 */ +// calldataload +// /* "":1238:1240 */ +// 0x1b +// /* "":1225:1241 */ +// calldataload +// /* "":1274:1276 */ +// 0x1c +// /* "":1261:1277 */ +// calldataload +// /* "":1310:1312 */ +// 0x1d +// /* "":1297:1313 */ +// calldataload +// /* "":1346:1348 */ +// 0x1e +// /* "":1333:1349 */ +// calldataload +// /* "":1382:1384 */ +// 0x1f +// /* "":1369:1385 */ +// calldataload +// /* "":1418:1420 */ +// 0x20 +// /* "":1405:1421 */ +// calldataload +// /* "":1454:1456 */ +// 0x21 +// /* "":1441:1457 */ +// calldataload +// /* "":1490:1492 */ +// 0x22 +// /* "":1477:1493 */ +// calldataload +// /* "":1526:1528 */ +// 0x23 +// /* "":1513:1529 */ +// calldataload +// /* "":1562:1564 */ +// 0x24 +// /* "":1549:1565 */ +// calldataload +// /* "":1598:1600 */ +// 0x25 +// /* "":1585:1601 */ +// calldataload +// /* "":1634:1636 */ +// 0x26 +// /* "":1621:1637 */ +// calldataload +// /* "":1670:1672 */ +// 0x27 +// /* "":1657:1673 */ +// calldataload +// /* "":1706:1708 */ +// 0x28 +// /* "":1693:1709 */ +// calldataload +// /* "":1742:1744 */ +// 0x29 +// /* "":1729:1745 */ +// calldataload +// /* "":1778:1780 */ +// 0x2a +// /* "":1765:1781 */ +// calldataload +// /* "":1814:1816 */ +// 0x2b +// /* "":1801:1817 */ +// calldataload +// /* "":1850:1852 */ +// 0x2c +// /* "":1837:1853 */ +// calldataload +// /* "":1886:1888 */ +// 0x2d +// /* "":1873:1889 */ +// calldataload +// /* "":1922:1924 */ +// 0x2e +// /* "":1909:1925 */ +// calldataload +// /* "":1958:1960 */ +// 0x2f +// /* "":1945:1961 */ +// calldataload +// /* "":1994:1996 */ +// 0x30 +// /* "":1981:1997 */ +// calldataload +// /* "":2030:2032 */ +// 0x31 +// /* "":2017:2033 */ +// calldataload +// /* "":2066:2068 */ +// 0x32 +// /* "":2053:2069 */ +// calldataload +// /* "":2102:2104 */ +// 0x33 +// /* "":2089:2105 */ +// calldataload +// /* "":2138:2140 */ +// 0x34 +// /* "":2125:2141 */ +// calldataload +// /* "":2174:2176 */ +// 0x35 +// /* "":2161:2177 */ +// calldataload +// /* "":2210:2212 */ +// 0x36 +// /* "":2197:2213 */ +// calldataload +// /* "":2246:2248 */ +// 0x37 +// /* "":2233:2249 */ +// calldataload +// /* "":2282:2284 */ +// 0x38 +// /* "":2269:2285 */ +// calldataload +// /* "":2318:2320 */ +// 0x39 +// /* "":2305:2321 */ +// calldataload +// /* "":2354:2356 */ +// 0x3a +// /* "":2341:2357 */ +// calldataload +// /* "":2390:2392 */ +// 0x3b +// /* "":2377:2393 */ +// calldataload +// /* "":2426:2428 */ +// 0x3c +// /* "":2413:2429 */ +// calldataload +// /* "":2462:2464 */ +// 0x3d +// /* "":2449:2465 */ +// calldataload +// /* "":2498:2500 */ +// 0x3e +// /* "":2485:2501 */ +// calldataload +// /* "":2534:2536 */ +// 0x3f +// /* "":2521:2537 */ +// calldataload +// /* "":2570:2572 */ +// 0x40 +// /* "":2557:2573 */ +// calldataload +// /* "":2606:2608 */ +// 0x41 +// /* "":2593:2609 */ +// calldataload +// /* "":2642:2644 */ +// 0x42 +// /* "":2629:2645 */ +// calldataload +// /* "":2678:2680 */ +// 0x43 +// /* "":2665:2681 */ +// calldataload +// /* "":2714:2716 */ +// 0x44 +// /* "":2701:2717 */ +// calldataload +// /* "":2750:2752 */ +// 0x45 +// /* "":2737:2753 */ +// calldataload +// /* "":2786:2788 */ +// 0x46 +// /* "":2773:2789 */ +// calldataload +// /* "":2822:2824 */ +// 0x47 +// /* "":2809:2825 */ +// calldataload +// /* "":2858:2860 */ +// 0x48 +// /* "":2845:2861 */ +// calldataload +// /* "":2894:2896 */ +// 0x49 +// /* "":2881:2897 */ +// calldataload +// /* "":2930:2932 */ +// 0x4a +// /* "":2917:2933 */ +// calldataload +// /* "":2966:2968 */ +// 0x4b +// /* "":2953:2969 */ +// calldataload +// /* "":3002:3004 */ +// 0x4c +// /* "":2989:3005 */ +// calldataload +// /* "":3038:3040 */ +// 0x4d +// /* "":3025:3041 */ +// calldataload +// /* "":3074:3076 */ +// 0x4e +// /* "":3061:3077 */ +// calldataload +// /* "":3110:3112 */ +// 0x4f +// /* "":3097:3113 */ +// calldataload +// /* "":3146:3148 */ +// 0x50 +// /* "":3133:3149 */ +// calldataload +// /* "":3182:3184 */ +// 0x51 +// /* "":3169:3185 */ +// calldataload +// /* "":3218:3220 */ +// 0x52 +// /* "":3205:3221 */ +// calldataload +// /* "":3254:3256 */ +// 0x53 +// /* "":3241:3257 */ +// calldataload +// /* "":3290:3292 */ +// 0x54 +// /* "":3277:3293 */ +// calldataload +// /* "":3326:3328 */ +// 0x55 +// /* "":3313:3329 */ +// calldataload +// /* "":3362:3364 */ +// 0x56 +// /* "":3349:3365 */ +// calldataload +// /* "":3398:3400 */ +// 0x57 +// /* "":3385:3401 */ +// calldataload +// /* "":3434:3436 */ +// 0x58 +// /* "":3421:3437 */ +// calldataload +// /* "":3470:3472 */ +// 0x59 +// /* "":3457:3473 */ +// calldataload +// /* "":3506:3508 */ +// 0x5a +// /* "":3493:3509 */ +// calldataload +// /* "":3542:3544 */ +// 0x5b +// /* "":3529:3545 */ +// calldataload +// /* "":3578:3580 */ +// 0x5c +// /* "":3565:3581 */ +// calldataload +// /* "":3614:3616 */ +// 0x5d +// /* "":3601:3617 */ +// calldataload +// /* "":3650:3652 */ +// 0x5e +// /* "":3637:3653 */ +// calldataload +// /* "":3686:3688 */ +// 0x5f +// /* "":3673:3689 */ +// calldataload +// /* "":3722:3724 */ +// 0x60 +// /* "":3709:3725 */ +// calldataload +// /* "":3758:3760 */ +// 0x61 +// /* "":3745:3761 */ +// calldataload +// /* "":3794:3796 */ +// 0x62 +// /* "":3781:3797 */ +// calldataload +// /* "":3830:3832 */ +// 0x63 +// /* "":3817:3833 */ +// calldataload +// /* "":3867:3870 */ +// 0x64 +// /* "":3854:3871 */ +// calldataload +// /* "":3905:3908 */ +// 0x65 +// /* "":3892:3909 */ +// calldataload +// /* "":3943:3946 */ +// 0x66 +// /* "":3930:3947 */ +// calldataload +// /* "":3981:3984 */ +// 0x67 +// /* "":3968:3985 */ +// calldataload +// /* "":4019:4022 */ +// 0x68 +// /* "":4006:4023 */ +// calldataload +// /* "":4057:4060 */ +// 0x69 +// /* "":4044:4061 */ +// calldataload +// /* "":4095:4098 */ +// 0x6a +// /* "":4082:4099 */ +// calldataload +// /* "":4133:4136 */ +// 0x6b +// /* "":4120:4137 */ +// calldataload +// /* "":4171:4174 */ +// 0x6c +// /* "":4158:4175 */ +// calldataload +// /* "":4209:4212 */ +// 0x6d +// /* "":4196:4213 */ +// calldataload +// /* "":4247:4250 */ +// 0x6e +// /* "":4234:4251 */ +// calldataload +// /* "":4285:4288 */ +// 0x6f +// /* "":4272:4289 */ +// calldataload +// /* "":4323:4326 */ +// 0x70 +// /* "":4310:4327 */ +// calldataload +// /* "":4361:4364 */ +// 0x71 +// /* "":4348:4365 */ +// calldataload +// /* "":4399:4402 */ +// 0x72 +// /* "":4386:4403 */ +// calldataload +// /* "":4437:4440 */ +// 0x73 +// /* "":4424:4441 */ +// calldataload +// /* "":4475:4478 */ +// 0x74 +// /* "":4462:4479 */ +// calldataload +// /* "":4513:4516 */ +// 0x75 +// /* "":4500:4517 */ +// calldataload +// /* "":4551:4554 */ +// 0x76 +// /* "":4538:4555 */ +// calldataload +// /* "":4589:4592 */ +// 0x77 +// /* "":4576:4593 */ +// calldataload +// /* "":4627:4630 */ +// 0x78 +// /* "":4614:4631 */ +// calldataload +// /* "":4665:4668 */ +// 0x79 +// /* "":4652:4669 */ +// calldataload +// /* "":4703:4706 */ +// 0x7a +// /* "":4690:4707 */ +// calldataload +// /* "":4741:4744 */ +// 0x7b +// /* "":4728:4745 */ +// calldataload +// /* "":4779:4782 */ +// 0x7c +// /* "":4766:4783 */ +// calldataload +// /* "":4817:4820 */ +// 0x7d +// /* "":4804:4821 */ +// calldataload +// /* "":4855:4858 */ +// 0x7e +// /* "":4842:4859 */ +// calldataload +// /* "":4893:4896 */ +// 0x7f +// /* "":4880:4897 */ +// calldataload +// /* "":4931:4934 */ +// 0x80 +// /* "":4918:4935 */ +// calldataload +// /* "":4969:4972 */ +// 0x81 +// /* "":4956:4973 */ +// calldataload +// /* "":4994:5011 */ +// swap2 +// /* "":5007:5010 */ +// 0x82 +// /* "":4994:5011 */ +// calldataload +// /* "":5032:5049 */ +// swap4 +// /* "":5045:5048 */ +// 0x83 +// /* "":5032:5049 */ +// calldataload +// /* "":5070:5087 */ +// swap6 +// /* "":5083:5086 */ +// 0x84 +// /* "":5070:5087 */ +// calldataload +// /* "":5108:5125 */ +// swap8 +// /* "":5121:5124 */ +// 0x85 +// /* "":5108:5125 */ +// calldataload +// /* "":5146:5163 */ +// swap10 +// /* "":5159:5162 */ +// 0x86 +// /* "":5146:5163 */ +// calldataload +// /* "":5184:5201 */ +// swap12 +// /* "":5197:5200 */ +// 0x87 +// /* "":5184:5201 */ +// calldataload +// /* "":5222:5239 */ +// swap14 +// /* "":5235:5238 */ +// 0x88 +// /* "":5222:5239 */ +// calldataload +// /* "":5260:5277 */ +// swap16 +// /* "":5273:5276 */ +// 0x89 +// /* "":5260:5277 */ +// calldataload +// /* "":5298:5315 */ +// swapn{18} +// /* "":5311:5314 */ +// 0x8a +// /* "":5298:5315 */ +// calldataload +// /* "":5336:5353 */ +// swapn{20} +// /* "":5349:5352 */ +// 0x8b +// /* "":5336:5353 */ +// calldataload +// /* "":5374:5391 */ +// swapn{22} +// /* "":5387:5390 */ +// 0x8c +// /* "":5374:5391 */ +// calldataload +// /* "":5412:5429 */ +// swapn{24} +// /* "":5425:5428 */ +// 0x8d +// /* "":5412:5429 */ +// calldataload +// /* "":5450:5467 */ +// swapn{26} +// /* "":5463:5466 */ +// 0x8e +// /* "":5450:5467 */ +// calldataload +// /* "":5488:5505 */ +// swapn{28} +// /* "":5501:5504 */ +// 0x8f +// /* "":5488:5505 */ +// calldataload +// /* "":5526:5543 */ +// swapn{30} +// /* "":5539:5542 */ +// 0x90 +// /* "":5526:5543 */ +// calldataload +// /* "":5564:5581 */ +// swapn{32} +// /* "":5577:5580 */ +// 0x91 +// /* "":5564:5581 */ +// calldataload +// /* "":5602:5619 */ +// swapn{34} +// /* "":5615:5618 */ +// 0x92 +// /* "":5602:5619 */ +// calldataload +// /* "":5640:5657 */ +// swapn{36} +// /* "":5653:5656 */ +// 0x93 +// /* "":5640:5657 */ +// calldataload +// /* "":5678:5695 */ +// swapn{38} +// /* "":5691:5694 */ +// 0x94 +// /* "":5678:5695 */ +// calldataload +// /* "":5716:5733 */ +// swapn{40} +// /* "":5729:5732 */ +// 0x95 +// /* "":5716:5733 */ +// calldataload +// /* "":5754:5771 */ +// swapn{42} +// /* "":5767:5770 */ +// 0x96 +// /* "":5754:5771 */ +// calldataload +// /* "":5792:5809 */ +// swapn{44} +// /* "":5805:5808 */ +// 0x97 +// /* "":5792:5809 */ +// calldataload +// /* "":5830:5847 */ +// swapn{46} +// /* "":5843:5846 */ +// 0x98 +// /* "":5830:5847 */ +// calldataload +// /* "":5868:5885 */ +// swapn{48} +// /* "":5881:5884 */ +// 0x99 +// /* "":5868:5885 */ +// calldataload +// /* "":5906:5923 */ +// swapn{50} +// /* "":5919:5922 */ +// 0x9a +// /* "":5906:5923 */ +// calldataload +// /* "":5944:5961 */ +// swapn{52} +// /* "":5957:5960 */ +// 0x9b +// /* "":5944:5961 */ +// calldataload +// /* "":5982:5999 */ +// swapn{54} +// /* "":5995:5998 */ +// 0x9c +// /* "":5982:5999 */ +// calldataload +// /* "":6020:6037 */ +// swapn{56} +// /* "":6033:6036 */ +// 0x9d +// /* "":6020:6037 */ +// calldataload +// /* "":6058:6075 */ +// swapn{58} +// /* "":6071:6074 */ +// 0x9e +// /* "":6058:6075 */ +// calldataload +// /* "":6096:6113 */ +// swapn{60} +// /* "":6109:6112 */ +// 0x9f +// /* "":6096:6113 */ +// calldataload +// /* "":6134:6151 */ +// swapn{62} +// /* "":6147:6150 */ +// 0xa0 +// /* "":6134:6151 */ +// calldataload +// /* "":6172:6189 */ +// swapn{64} +// /* "":6185:6188 */ +// 0xa1 +// /* "":6172:6189 */ +// calldataload +// /* "":6210:6227 */ +// swapn{66} +// /* "":6223:6226 */ +// 0xa2 +// /* "":6210:6227 */ +// calldataload +// /* "":6248:6265 */ +// swapn{68} +// /* "":6261:6264 */ +// 0xa3 +// /* "":6248:6265 */ +// calldataload +// /* "":6286:6303 */ +// swapn{70} +// /* "":6299:6302 */ +// 0xa4 +// /* "":6286:6303 */ +// calldataload +// /* "":6324:6341 */ +// swapn{72} +// /* "":6337:6340 */ +// 0xa5 +// /* "":6324:6341 */ +// calldataload +// /* "":6362:6379 */ +// swapn{74} +// /* "":6375:6378 */ +// 0xa6 +// /* "":6362:6379 */ +// calldataload +// /* "":6400:6417 */ +// swapn{76} +// /* "":6413:6416 */ +// 0xa7 +// /* "":6400:6417 */ +// calldataload +// /* "":6438:6455 */ +// swapn{78} +// /* "":6451:6454 */ +// 0xa8 +// /* "":6438:6455 */ +// calldataload +// /* "":6476:6493 */ +// swapn{80} +// /* "":6489:6492 */ +// 0xa9 +// /* "":6476:6493 */ +// calldataload +// /* "":6514:6531 */ +// swapn{82} +// /* "":6527:6530 */ +// 0xaa +// /* "":6514:6531 */ +// calldataload +// /* "":6552:6569 */ +// swapn{84} +// /* "":6565:6568 */ +// 0xab +// /* "":6552:6569 */ +// calldataload +// /* "":6590:6607 */ +// swapn{86} +// /* "":6603:6606 */ +// 0xac +// /* "":6590:6607 */ +// calldataload +// /* "":6628:6645 */ +// swapn{88} +// /* "":6641:6644 */ +// 0xad +// /* "":6628:6645 */ +// calldataload +// /* "":6666:6683 */ +// swapn{90} +// /* "":6679:6682 */ +// 0xae +// /* "":6666:6683 */ +// calldataload +// /* "":6704:6721 */ +// swapn{92} +// /* "":6717:6720 */ +// 0xaf +// /* "":6704:6721 */ +// calldataload +// /* "":6742:6759 */ +// swapn{94} +// /* "":6755:6758 */ +// 0xb0 +// /* "":6742:6759 */ +// calldataload +// /* "":6780:6797 */ +// swapn{96} +// /* "":6793:6796 */ +// 0xb1 +// /* "":6780:6797 */ +// calldataload +// /* "":6818:6835 */ +// swapn{98} +// /* "":6831:6834 */ +// 0xb2 +// /* "":6818:6835 */ +// calldataload +// /* "":6856:6873 */ +// swapn{100} +// /* "":6869:6872 */ +// 0xb3 +// /* "":6856:6873 */ +// calldataload +// /* "":6894:6911 */ +// swapn{102} +// /* "":6907:6910 */ +// 0xb4 +// /* "":6894:6911 */ +// calldataload +// /* "":6932:6949 */ +// swapn{104} +// /* "":6945:6948 */ +// 0xb5 +// /* "":6932:6949 */ +// calldataload +// /* "":6970:6987 */ +// swapn{106} +// /* "":6983:6986 */ +// 0xb6 +// /* "":6970:6987 */ +// calldataload +// /* "":7008:7025 */ +// swapn{108} +// /* "":7021:7024 */ +// 0xb7 +// /* "":7008:7025 */ +// calldataload +// /* "":7046:7063 */ +// swapn{110} +// /* "":7059:7062 */ +// 0xb8 +// /* "":7046:7063 */ +// calldataload +// /* "":7084:7101 */ +// swapn{112} +// /* "":7097:7100 */ +// 0xb9 +// /* "":7084:7101 */ +// calldataload +// /* "":7122:7139 */ +// swapn{114} +// /* "":7135:7138 */ +// 0xba +// /* "":7122:7139 */ +// calldataload +// /* "":7160:7177 */ +// swapn{116} +// /* "":7173:7176 */ +// 0xbb +// /* "":7160:7177 */ +// calldataload +// /* "":7198:7215 */ +// swapn{118} +// /* "":7211:7214 */ +// 0xbc +// /* "":7198:7215 */ +// calldataload +// /* "":7236:7253 */ +// swapn{120} +// /* "":7249:7252 */ +// 0xbd +// /* "":7236:7253 */ +// calldataload +// /* "":7274:7291 */ +// swapn{122} +// /* "":7287:7290 */ +// 0xbe +// /* "":7274:7291 */ +// calldataload +// /* "":7312:7329 */ +// swapn{124} +// /* "":7325:7328 */ +// 0xbf +// /* "":7312:7329 */ +// calldataload +// /* "":7350:7367 */ +// swapn{126} +// /* "":7363:7366 */ +// 0xc0 +// /* "":7350:7367 */ +// calldataload +// /* "":7388:7405 */ +// swapn{128} +// /* "":7401:7404 */ +// 0xc1 +// /* "":7388:7405 */ +// calldataload +// /* "":7426:7443 */ +// swapn{130} +// /* "":7439:7442 */ +// 0xc2 +// /* "":7426:7443 */ +// calldataload +// /* "":7464:7481 */ +// swapn{132} +// /* "":7477:7480 */ +// 0xc3 +// /* "":7464:7481 */ +// calldataload +// /* "":7502:7519 */ +// swapn{134} +// /* "":7515:7518 */ +// 0xc4 +// /* "":7502:7519 */ +// calldataload +// /* "":7540:7557 */ +// swapn{136} +// /* "":7553:7556 */ +// 0xc5 +// /* "":7540:7557 */ +// calldataload +// /* "":7578:7595 */ +// swapn{138} +// /* "":7591:7594 */ +// 0xc6 +// /* "":7578:7595 */ +// calldataload +// /* "":7616:7633 */ +// swapn{140} +// /* "":7629:7632 */ +// 0xc7 +// /* "":7616:7633 */ +// calldataload +// /* "":7654:7671 */ +// swapn{142} +// /* "":7667:7670 */ +// 0xc8 +// /* "":7654:7671 */ +// calldataload +// /* "":7692:7709 */ +// swapn{144} +// /* "":7705:7708 */ +// 0xc9 +// /* "":7692:7709 */ +// calldataload +// /* "":7730:7747 */ +// swapn{146} +// /* "":7743:7746 */ +// 0xca +// /* "":7730:7747 */ +// calldataload +// /* "":7768:7785 */ +// swapn{148} +// /* "":7781:7784 */ +// 0xcb +// /* "":7768:7785 */ +// calldataload +// /* "":7806:7823 */ +// swapn{150} +// /* "":7819:7822 */ +// 0xcc +// /* "":7806:7823 */ +// calldataload +// /* "":7844:7861 */ +// swapn{152} +// /* "":7857:7860 */ +// 0xcd +// /* "":7844:7861 */ +// calldataload +// /* "":7882:7899 */ +// swapn{154} +// /* "":7895:7898 */ +// 0xce +// /* "":7882:7899 */ +// calldataload +// /* "":7920:7937 */ +// swapn{156} +// /* "":7933:7936 */ +// 0xcf +// /* "":7920:7937 */ +// calldataload +// /* "":7958:7975 */ +// swapn{158} +// /* "":7971:7974 */ +// 0xd0 +// /* "":7958:7975 */ +// calldataload +// /* "":7996:8013 */ +// swapn{160} +// /* "":8009:8012 */ +// 0xd1 +// /* "":7996:8013 */ +// calldataload +// /* "":8034:8051 */ +// swapn{162} +// /* "":8047:8050 */ +// 0xd2 +// /* "":8034:8051 */ +// calldataload +// /* "":8072:8089 */ +// swapn{164} +// /* "":8085:8088 */ +// 0xd3 +// /* "":8072:8089 */ +// calldataload +// /* "":8110:8127 */ +// swapn{166} +// /* "":8123:8126 */ +// 0xd4 +// /* "":8110:8127 */ +// calldataload +// /* "":8148:8165 */ +// swapn{168} +// /* "":8161:8164 */ +// 0xd5 +// /* "":8148:8165 */ +// calldataload +// /* "":8186:8203 */ +// swapn{170} +// /* "":8199:8202 */ +// 0xd6 +// /* "":8186:8203 */ +// calldataload +// /* "":8224:8241 */ +// swapn{172} +// /* "":8237:8240 */ +// 0xd7 +// /* "":8224:8241 */ +// calldataload +// /* "":8262:8279 */ +// swapn{174} +// /* "":8275:8278 */ +// 0xd8 +// /* "":8262:8279 */ +// calldataload +// /* "":8300:8317 */ +// swapn{176} +// /* "":8313:8316 */ +// 0xd9 +// /* "":8300:8317 */ +// calldataload +// /* "":8338:8355 */ +// swapn{178} +// /* "":8351:8354 */ +// 0xda +// /* "":8338:8355 */ +// calldataload +// /* "":8376:8393 */ +// swapn{180} +// /* "":8389:8392 */ +// 0xdb +// /* "":8376:8393 */ +// calldataload +// /* "":8414:8431 */ +// swapn{182} +// /* "":8427:8430 */ +// 0xdc +// /* "":8414:8431 */ +// calldataload +// /* "":8452:8469 */ +// swapn{184} +// /* "":8465:8468 */ +// 0xdd +// /* "":8452:8469 */ +// calldataload +// /* "":8490:8507 */ +// swapn{186} +// /* "":8503:8506 */ +// 0xde +// /* "":8490:8507 */ +// calldataload +// /* "":8528:8545 */ +// swapn{188} +// /* "":8541:8544 */ +// 0xdf +// /* "":8528:8545 */ +// calldataload +// /* "":8566:8583 */ +// swapn{190} +// /* "":8579:8582 */ +// 0xe0 +// /* "":8566:8583 */ +// calldataload +// /* "":8604:8621 */ +// swapn{192} +// /* "":8617:8620 */ +// 0xe1 +// /* "":8604:8621 */ +// calldataload +// /* "":8642:8659 */ +// swapn{194} +// /* "":8655:8658 */ +// 0xe2 +// /* "":8642:8659 */ +// calldataload +// /* "":8680:8697 */ +// swapn{196} +// /* "":8693:8696 */ +// 0xe3 +// /* "":8680:8697 */ +// calldataload +// /* "":8718:8735 */ +// swapn{198} +// /* "":8731:8734 */ +// 0xe4 +// /* "":8718:8735 */ +// calldataload +// /* "":8756:8773 */ +// swapn{200} +// /* "":8769:8772 */ +// 0xe5 +// /* "":8756:8773 */ +// calldataload +// /* "":8794:8811 */ +// swapn{202} +// /* "":8807:8810 */ +// 0xe6 +// /* "":8794:8811 */ +// calldataload +// /* "":8832:8849 */ +// swapn{204} +// /* "":8845:8848 */ +// 0xe7 +// /* "":8832:8849 */ +// calldataload +// /* "":8870:8887 */ +// swapn{206} +// /* "":8883:8886 */ +// 0xe8 +// /* "":8870:8887 */ +// calldataload +// /* "":8908:8925 */ +// swapn{208} +// /* "":8921:8924 */ +// 0xe9 +// /* "":8908:8925 */ +// calldataload +// /* "":8946:8963 */ +// swapn{210} +// /* "":8959:8962 */ +// 0xea +// /* "":8946:8963 */ +// calldataload +// /* "":8984:9001 */ +// swapn{212} +// /* "":8997:9000 */ +// 0xeb +// /* "":8984:9001 */ +// calldataload +// /* "":9022:9039 */ +// swapn{214} +// /* "":9035:9038 */ +// 0xec +// /* "":9022:9039 */ +// calldataload +// /* "":9060:9077 */ +// swapn{216} +// /* "":9073:9076 */ +// 0xed +// /* "":9060:9077 */ +// calldataload +// /* "":9098:9115 */ +// swapn{218} +// /* "":9111:9114 */ +// 0xee +// /* "":9098:9115 */ +// calldataload +// /* "":9136:9153 */ +// swapn{220} +// /* "":9149:9152 */ +// 0xef +// /* "":9136:9153 */ +// calldataload +// /* "":9174:9191 */ +// swapn{222} +// /* "":9187:9190 */ +// 0xf0 +// /* "":9174:9191 */ +// calldataload +// /* "":9212:9229 */ +// swapn{224} +// /* "":9225:9228 */ +// 0xf1 +// /* "":9212:9229 */ +// calldataload +// /* "":9250:9267 */ +// swapn{226} +// /* "":9263:9266 */ +// 0xf2 +// /* "":9250:9267 */ +// calldataload +// /* "":9288:9305 */ +// swapn{228} +// /* "":9301:9304 */ +// 0xf3 +// /* "":9288:9305 */ +// calldataload +// /* "":9326:9343 */ +// swapn{230} +// /* "":9339:9342 */ +// 0xf4 +// /* "":9326:9343 */ +// calldataload +// /* "":9364:9381 */ +// swapn{232} +// /* "":9377:9380 */ +// 0xf5 +// /* "":9364:9381 */ +// calldataload +// /* "":9402:9419 */ +// swapn{234} +// /* "":9415:9418 */ +// 0xf6 +// /* "":9402:9419 */ +// calldataload +// /* "":9440:9457 */ +// swapn{236} +// /* "":9453:9456 */ +// 0xf7 +// /* "":9440:9457 */ +// calldataload +// /* "":9478:9495 */ +// swapn{238} +// /* "":9491:9494 */ +// 0xf8 +// /* "":9478:9495 */ +// calldataload +// /* "":9516:9533 */ +// swapn{240} +// /* "":9529:9532 */ +// 0xf9 +// /* "":9516:9533 */ +// calldataload +// /* "":9554:9571 */ +// swapn{242} +// /* "":9567:9570 */ +// 0xfa +// /* "":9554:9571 */ +// calldataload +// /* "":9592:9609 */ +// swapn{244} +// /* "":9605:9608 */ +// 0xfb +// /* "":9592:9609 */ +// calldataload +// /* "":9630:9647 */ +// swapn{246} +// /* "":9643:9646 */ +// 0xfc +// /* "":9630:9647 */ +// calldataload +// /* "":9668:9685 */ +// swapn{248} +// /* "":9681:9684 */ +// 0xfd +// /* "":9668:9685 */ +// calldataload +// /* "":9706:9723 */ +// swapn{250} +// /* "":9719:9722 */ +// 0xfe +// /* "":9706:9723 */ +// calldataload +// /* "":9744:9761 */ +// swapn{252} +// /* "":9757:9760 */ +// 0xff +// /* "":9744:9761 */ +// calldataload +// /* "":9782:9799 */ +// swapn{254} +// /* "":9795:9798 */ +// 0x0100 +// /* "":9782:9799 */ +// calldataload +// /* "":9808:9821 */ +// swapn{256} +// /* "":9815:9816 */ +// 0x00 +// /* "":9808:9821 */ +// sstore +// /* "":9837:9838 */ +// 0x01 +// /* "":9830:9843 */ +// sstore +// /* "":9859:9860 */ +// 0x02 +// /* "":9852:9865 */ +// sstore +// /* "":9881:9882 */ +// 0x03 +// /* "":9874:9887 */ +// sstore +// /* "":9903:9904 */ +// 0x04 +// /* "":9896:9909 */ +// sstore +// /* "":9925:9926 */ +// 0x05 +// /* "":9918:9931 */ +// sstore +// /* "":9947:9948 */ +// 0x06 +// /* "":9940:9953 */ +// sstore +// /* "":9969:9970 */ +// 0x07 +// /* "":9962:9975 */ +// sstore +// /* "":9991:9992 */ +// 0x08 +// /* "":9984:9997 */ +// sstore +// /* "":10013:10014 */ +// 0x09 +// /* "":10006:10019 */ +// sstore +// /* "":10035:10037 */ +// 0x0a +// /* "":10028:10043 */ +// sstore +// /* "":10059:10061 */ +// 0x0b +// /* "":10052:10067 */ +// sstore +// /* "":10083:10085 */ +// 0x0c +// /* "":10076:10091 */ +// sstore +// /* "":10107:10109 */ +// 0x0d +// /* "":10100:10115 */ +// sstore +// /* "":10131:10133 */ +// 0x0e +// /* "":10124:10139 */ +// sstore +// /* "":10155:10157 */ +// 0x0f +// /* "":10148:10163 */ +// sstore +// /* "":10179:10181 */ +// 0x10 +// /* "":10172:10187 */ +// sstore +// /* "":10203:10205 */ +// 0x11 +// /* "":10196:10211 */ +// sstore +// /* "":10227:10229 */ +// 0x12 +// /* "":10220:10235 */ +// sstore +// /* "":10251:10253 */ +// 0x13 +// /* "":10244:10259 */ +// sstore +// /* "":10275:10277 */ +// 0x14 +// /* "":10268:10283 */ +// sstore +// /* "":10299:10301 */ +// 0x15 +// /* "":10292:10307 */ +// sstore +// /* "":10323:10325 */ +// 0x16 +// /* "":10316:10331 */ +// sstore +// /* "":10347:10349 */ +// 0x17 +// /* "":10340:10355 */ +// sstore +// /* "":10371:10373 */ +// 0x18 +// /* "":10364:10379 */ +// sstore +// /* "":10395:10397 */ +// 0x19 +// /* "":10388:10403 */ +// sstore +// /* "":10419:10421 */ +// 0x1a +// /* "":10412:10427 */ +// sstore +// /* "":10443:10445 */ +// 0x1b +// /* "":10436:10451 */ +// sstore +// /* "":10467:10469 */ +// 0x1c +// /* "":10460:10475 */ +// sstore +// /* "":10491:10493 */ +// 0x1d +// /* "":10484:10499 */ +// sstore +// /* "":10515:10517 */ +// 0x1e +// /* "":10508:10523 */ +// sstore +// /* "":10539:10541 */ +// 0x1f +// /* "":10532:10547 */ +// sstore +// /* "":10563:10565 */ +// 0x20 +// /* "":10556:10571 */ +// sstore +// /* "":10587:10589 */ +// 0x21 +// /* "":10580:10595 */ +// sstore +// /* "":10611:10613 */ +// 0x22 +// /* "":10604:10619 */ +// sstore +// /* "":10635:10637 */ +// 0x23 +// /* "":10628:10643 */ +// sstore +// /* "":10659:10661 */ +// 0x24 +// /* "":10652:10667 */ +// sstore +// /* "":10683:10685 */ +// 0x25 +// /* "":10676:10691 */ +// sstore +// /* "":10707:10709 */ +// 0x26 +// /* "":10700:10715 */ +// sstore +// /* "":10731:10733 */ +// 0x27 +// /* "":10724:10739 */ +// sstore +// /* "":10755:10757 */ +// 0x28 +// /* "":10748:10763 */ +// sstore +// /* "":10779:10781 */ +// 0x29 +// /* "":10772:10787 */ +// sstore +// /* "":10803:10805 */ +// 0x2a +// /* "":10796:10811 */ +// sstore +// /* "":10827:10829 */ +// 0x2b +// /* "":10820:10835 */ +// sstore +// /* "":10851:10853 */ +// 0x2c +// /* "":10844:10859 */ +// sstore +// /* "":10875:10877 */ +// 0x2d +// /* "":10868:10883 */ +// sstore +// /* "":10899:10901 */ +// 0x2e +// /* "":10892:10907 */ +// sstore +// /* "":10923:10925 */ +// 0x2f +// /* "":10916:10931 */ +// sstore +// /* "":10947:10949 */ +// 0x30 +// /* "":10940:10955 */ +// sstore +// /* "":10971:10973 */ +// 0x31 +// /* "":10964:10979 */ +// sstore +// /* "":10995:10997 */ +// 0x32 +// /* "":10988:11003 */ +// sstore +// /* "":11019:11021 */ +// 0x33 +// /* "":11012:11027 */ +// sstore +// /* "":11043:11045 */ +// 0x34 +// /* "":11036:11051 */ +// sstore +// /* "":11067:11069 */ +// 0x35 +// /* "":11060:11075 */ +// sstore +// /* "":11091:11093 */ +// 0x36 +// /* "":11084:11099 */ +// sstore +// /* "":11115:11117 */ +// 0x37 +// /* "":11108:11123 */ +// sstore +// /* "":11139:11141 */ +// 0x38 +// /* "":11132:11147 */ +// sstore +// /* "":11163:11165 */ +// 0x39 +// /* "":11156:11171 */ +// sstore +// /* "":11187:11189 */ +// 0x3a +// /* "":11180:11195 */ +// sstore +// /* "":11211:11213 */ +// 0x3b +// /* "":11204:11219 */ +// sstore +// /* "":11235:11237 */ +// 0x3c +// /* "":11228:11243 */ +// sstore +// /* "":11259:11261 */ +// 0x3d +// /* "":11252:11267 */ +// sstore +// /* "":11283:11285 */ +// 0x3e +// /* "":11276:11291 */ +// sstore +// /* "":11307:11309 */ +// 0x3f +// /* "":11300:11315 */ +// sstore +// /* "":11331:11333 */ +// 0x40 +// /* "":11324:11339 */ +// sstore +// /* "":11355:11357 */ +// 0x41 +// /* "":11348:11363 */ +// sstore +// /* "":11379:11381 */ +// 0x42 +// /* "":11372:11387 */ +// sstore +// /* "":11403:11405 */ +// 0x43 +// /* "":11396:11411 */ +// sstore +// /* "":11427:11429 */ +// 0x44 +// /* "":11420:11435 */ +// sstore +// /* "":11451:11453 */ +// 0x45 +// /* "":11444:11459 */ +// sstore +// /* "":11475:11477 */ +// 0x46 +// /* "":11468:11483 */ +// sstore +// /* "":11499:11501 */ +// 0x47 +// /* "":11492:11507 */ +// sstore +// /* "":11523:11525 */ +// 0x48 +// /* "":11516:11531 */ +// sstore +// /* "":11547:11549 */ +// 0x49 +// /* "":11540:11555 */ +// sstore +// /* "":11571:11573 */ +// 0x4a +// /* "":11564:11579 */ +// sstore +// /* "":11595:11597 */ +// 0x4b +// /* "":11588:11603 */ +// sstore +// /* "":11619:11621 */ +// 0x4c +// /* "":11612:11627 */ +// sstore +// /* "":11643:11645 */ +// 0x4d +// /* "":11636:11651 */ +// sstore +// /* "":11667:11669 */ +// 0x4e +// /* "":11660:11675 */ +// sstore +// /* "":11691:11693 */ +// 0x4f +// /* "":11684:11699 */ +// sstore +// /* "":11715:11717 */ +// 0x50 +// /* "":11708:11723 */ +// sstore +// /* "":11739:11741 */ +// 0x51 +// /* "":11732:11747 */ +// sstore +// /* "":11763:11765 */ +// 0x52 +// /* "":11756:11771 */ +// sstore +// /* "":11787:11789 */ +// 0x53 +// /* "":11780:11795 */ +// sstore +// /* "":11811:11813 */ +// 0x54 +// /* "":11804:11819 */ +// sstore +// /* "":11835:11837 */ +// 0x55 +// /* "":11828:11843 */ +// sstore +// /* "":11859:11861 */ +// 0x56 +// /* "":11852:11867 */ +// sstore +// /* "":11883:11885 */ +// 0x57 +// /* "":11876:11891 */ +// sstore +// /* "":11907:11909 */ +// 0x58 +// /* "":11900:11915 */ +// sstore +// /* "":11931:11933 */ +// 0x59 +// /* "":11924:11939 */ +// sstore +// /* "":11955:11957 */ +// 0x5a +// /* "":11948:11963 */ +// sstore +// /* "":11979:11981 */ +// 0x5b +// /* "":11972:11987 */ +// sstore +// /* "":12003:12005 */ +// 0x5c +// /* "":11996:12011 */ +// sstore +// /* "":12027:12029 */ +// 0x5d +// /* "":12020:12035 */ +// sstore +// /* "":12051:12053 */ +// 0x5e +// /* "":12044:12059 */ +// sstore +// /* "":12075:12077 */ +// 0x5f +// /* "":12068:12083 */ +// sstore +// /* "":12099:12101 */ +// 0x60 +// /* "":12092:12107 */ +// sstore +// /* "":12123:12125 */ +// 0x61 +// /* "":12116:12131 */ +// sstore +// /* "":12147:12149 */ +// 0x62 +// /* "":12140:12155 */ +// sstore +// /* "":12171:12173 */ +// 0x63 +// /* "":12164:12179 */ +// sstore +// /* "":12195:12198 */ +// 0x64 +// /* "":12188:12205 */ +// sstore +// /* "":12221:12224 */ +// 0x65 +// /* "":12214:12231 */ +// sstore +// /* "":12247:12250 */ +// 0x66 +// /* "":12240:12257 */ +// sstore +// /* "":12273:12276 */ +// 0x67 +// /* "":12266:12283 */ +// sstore +// /* "":12299:12302 */ +// 0x68 +// /* "":12292:12309 */ +// sstore +// /* "":12325:12328 */ +// 0x69 +// /* "":12318:12335 */ +// sstore +// /* "":12351:12354 */ +// 0x6a +// /* "":12344:12361 */ +// sstore +// /* "":12377:12380 */ +// 0x6b +// /* "":12370:12387 */ +// sstore +// /* "":12403:12406 */ +// 0x6c +// /* "":12396:12413 */ +// sstore +// /* "":12429:12432 */ +// 0x6d +// /* "":12422:12439 */ +// sstore +// /* "":12455:12458 */ +// 0x6e +// /* "":12448:12465 */ +// sstore +// /* "":12481:12484 */ +// 0x6f +// /* "":12474:12491 */ +// sstore +// /* "":12507:12510 */ +// 0x70 +// /* "":12500:12517 */ +// sstore +// /* "":12533:12536 */ +// 0x71 +// /* "":12526:12543 */ +// sstore +// /* "":12559:12562 */ +// 0x72 +// /* "":12552:12569 */ +// sstore +// /* "":12585:12588 */ +// 0x73 +// /* "":12578:12595 */ +// sstore +// /* "":12611:12614 */ +// 0x74 +// /* "":12604:12621 */ +// sstore +// /* "":12637:12640 */ +// 0x75 +// /* "":12630:12647 */ +// sstore +// /* "":12663:12666 */ +// 0x76 +// /* "":12656:12673 */ +// sstore +// /* "":12689:12692 */ +// 0x77 +// /* "":12682:12699 */ +// sstore +// /* "":12715:12718 */ +// 0x78 +// /* "":12708:12725 */ +// sstore +// /* "":12741:12744 */ +// 0x79 +// /* "":12734:12751 */ +// sstore +// /* "":12767:12770 */ +// 0x7a +// /* "":12760:12777 */ +// sstore +// /* "":12793:12796 */ +// 0x7b +// /* "":12786:12803 */ +// sstore +// /* "":12819:12822 */ +// 0x7c +// /* "":12812:12829 */ +// sstore +// /* "":12845:12848 */ +// 0x7d +// /* "":12838:12855 */ +// sstore +// /* "":12871:12874 */ +// 0x7e +// /* "":12864:12881 */ +// sstore +// /* "":12897:12900 */ +// 0x7f +// /* "":12890:12907 */ +// sstore +// /* "":12923:12926 */ +// 0x80 +// /* "":12916:12933 */ +// sstore +// /* "":12949:12952 */ +// 0x81 +// /* "":12942:12959 */ +// sstore +// /* "":12975:12978 */ +// 0x82 +// /* "":12968:12985 */ +// sstore +// /* "":13001:13004 */ +// 0x83 +// /* "":12994:13011 */ +// sstore +// /* "":13027:13030 */ +// 0x84 +// /* "":13020:13037 */ +// sstore +// /* "":13053:13056 */ +// 0x85 +// /* "":13046:13063 */ +// sstore +// /* "":13079:13082 */ +// 0x86 +// /* "":13072:13089 */ +// sstore +// /* "":13105:13108 */ +// 0x87 +// /* "":13098:13115 */ +// sstore +// /* "":13131:13134 */ +// 0x88 +// /* "":13124:13141 */ +// sstore +// /* "":13157:13160 */ +// 0x89 +// /* "":13150:13167 */ +// sstore +// /* "":13183:13186 */ +// 0x8a +// /* "":13176:13193 */ +// sstore +// /* "":13209:13212 */ +// 0x8b +// /* "":13202:13219 */ +// sstore +// /* "":13235:13238 */ +// 0x8c +// /* "":13228:13245 */ +// sstore +// /* "":13261:13264 */ +// 0x8d +// /* "":13254:13271 */ +// sstore +// /* "":13287:13290 */ +// 0x8e +// /* "":13280:13297 */ +// sstore +// /* "":13313:13316 */ +// 0x8f +// /* "":13306:13323 */ +// sstore +// /* "":13339:13342 */ +// 0x90 +// /* "":13332:13349 */ +// sstore +// /* "":13365:13368 */ +// 0x91 +// /* "":13358:13375 */ +// sstore +// /* "":13391:13394 */ +// 0x92 +// /* "":13384:13401 */ +// sstore +// /* "":13417:13420 */ +// 0x93 +// /* "":13410:13427 */ +// sstore +// /* "":13443:13446 */ +// 0x94 +// /* "":13436:13453 */ +// sstore +// /* "":13469:13472 */ +// 0x95 +// /* "":13462:13479 */ +// sstore +// /* "":13495:13498 */ +// 0x96 +// /* "":13488:13505 */ +// sstore +// /* "":13521:13524 */ +// 0x97 +// /* "":13514:13531 */ +// sstore +// /* "":13547:13550 */ +// 0x98 +// /* "":13540:13557 */ +// sstore +// /* "":13573:13576 */ +// 0x99 +// /* "":13566:13583 */ +// sstore +// /* "":13599:13602 */ +// 0x9a +// /* "":13592:13609 */ +// sstore +// /* "":13625:13628 */ +// 0x9b +// /* "":13618:13635 */ +// sstore +// /* "":13651:13654 */ +// 0x9c +// /* "":13644:13661 */ +// sstore +// /* "":13677:13680 */ +// 0x9d +// /* "":13670:13687 */ +// sstore +// /* "":13703:13706 */ +// 0x9e +// /* "":13696:13713 */ +// sstore +// /* "":13729:13732 */ +// 0x9f +// /* "":13722:13739 */ +// sstore +// /* "":13755:13758 */ +// 0xa0 +// /* "":13748:13765 */ +// sstore +// /* "":13781:13784 */ +// 0xa1 +// /* "":13774:13791 */ +// sstore +// /* "":13807:13810 */ +// 0xa2 +// /* "":13800:13817 */ +// sstore +// /* "":13833:13836 */ +// 0xa3 +// /* "":13826:13843 */ +// sstore +// /* "":13859:13862 */ +// 0xa4 +// /* "":13852:13869 */ +// sstore +// /* "":13885:13888 */ +// 0xa5 +// /* "":13878:13895 */ +// sstore +// /* "":13911:13914 */ +// 0xa6 +// /* "":13904:13921 */ +// sstore +// /* "":13937:13940 */ +// 0xa7 +// /* "":13930:13947 */ +// sstore +// /* "":13963:13966 */ +// 0xa8 +// /* "":13956:13973 */ +// sstore +// /* "":13989:13992 */ +// 0xa9 +// /* "":13982:13999 */ +// sstore +// /* "":14015:14018 */ +// 0xaa +// /* "":14008:14025 */ +// sstore +// /* "":14041:14044 */ +// 0xab +// /* "":14034:14051 */ +// sstore +// /* "":14067:14070 */ +// 0xac +// /* "":14060:14077 */ +// sstore +// /* "":14093:14096 */ +// 0xad +// /* "":14086:14103 */ +// sstore +// /* "":14119:14122 */ +// 0xae +// /* "":14112:14129 */ +// sstore +// /* "":14145:14148 */ +// 0xaf +// /* "":14138:14155 */ +// sstore +// /* "":14171:14174 */ +// 0xb0 +// /* "":14164:14181 */ +// sstore +// /* "":14197:14200 */ +// 0xb1 +// /* "":14190:14207 */ +// sstore +// /* "":14223:14226 */ +// 0xb2 +// /* "":14216:14233 */ +// sstore +// /* "":14249:14252 */ +// 0xb3 +// /* "":14242:14259 */ +// sstore +// /* "":14275:14278 */ +// 0xb4 +// /* "":14268:14285 */ +// sstore +// /* "":14301:14304 */ +// 0xb5 +// /* "":14294:14311 */ +// sstore +// /* "":14327:14330 */ +// 0xb6 +// /* "":14320:14337 */ +// sstore +// /* "":14353:14356 */ +// 0xb7 +// /* "":14346:14363 */ +// sstore +// /* "":14379:14382 */ +// 0xb8 +// /* "":14372:14389 */ +// sstore +// /* "":14405:14408 */ +// 0xb9 +// /* "":14398:14415 */ +// sstore +// /* "":14431:14434 */ +// 0xba +// /* "":14424:14441 */ +// sstore +// /* "":14457:14460 */ +// 0xbb +// /* "":14450:14467 */ +// sstore +// /* "":14483:14486 */ +// 0xbc +// /* "":14476:14493 */ +// sstore +// /* "":14509:14512 */ +// 0xbd +// /* "":14502:14519 */ +// sstore +// /* "":14535:14538 */ +// 0xbe +// /* "":14528:14545 */ +// sstore +// /* "":14561:14564 */ +// 0xbf +// /* "":14554:14571 */ +// sstore +// /* "":14587:14590 */ +// 0xc0 +// /* "":14580:14597 */ +// sstore +// /* "":14613:14616 */ +// 0xc1 +// /* "":14606:14623 */ +// sstore +// /* "":14639:14642 */ +// 0xc2 +// /* "":14632:14649 */ +// sstore +// /* "":14665:14668 */ +// 0xc3 +// /* "":14658:14675 */ +// sstore +// /* "":14691:14694 */ +// 0xc4 +// /* "":14684:14701 */ +// sstore +// /* "":14717:14720 */ +// 0xc5 +// /* "":14710:14727 */ +// sstore +// /* "":14743:14746 */ +// 0xc6 +// /* "":14736:14753 */ +// sstore +// /* "":14769:14772 */ +// 0xc7 +// /* "":14762:14779 */ +// sstore +// /* "":14795:14798 */ +// 0xc8 +// /* "":14788:14805 */ +// sstore +// /* "":14821:14824 */ +// 0xc9 +// /* "":14814:14831 */ +// sstore +// /* "":14847:14850 */ +// 0xca +// /* "":14840:14857 */ +// sstore +// /* "":14873:14876 */ +// 0xcb +// /* "":14866:14883 */ +// sstore +// /* "":14899:14902 */ +// 0xcc +// /* "":14892:14909 */ +// sstore +// /* "":14925:14928 */ +// 0xcd +// /* "":14918:14935 */ +// sstore +// /* "":14951:14954 */ +// 0xce +// /* "":14944:14961 */ +// sstore +// /* "":14977:14980 */ +// 0xcf +// /* "":14970:14987 */ +// sstore +// /* "":15003:15006 */ +// 0xd0 +// /* "":14996:15013 */ +// sstore +// /* "":15029:15032 */ +// 0xd1 +// /* "":15022:15039 */ +// sstore +// /* "":15055:15058 */ +// 0xd2 +// /* "":15048:15065 */ +// sstore +// /* "":15081:15084 */ +// 0xd3 +// /* "":15074:15091 */ +// sstore +// /* "":15107:15110 */ +// 0xd4 +// /* "":15100:15117 */ +// sstore +// /* "":15133:15136 */ +// 0xd5 +// /* "":15126:15143 */ +// sstore +// /* "":15159:15162 */ +// 0xd6 +// /* "":15152:15169 */ +// sstore +// /* "":15185:15188 */ +// 0xd7 +// /* "":15178:15195 */ +// sstore +// /* "":15211:15214 */ +// 0xd8 +// /* "":15204:15221 */ +// sstore +// /* "":15237:15240 */ +// 0xd9 +// /* "":15230:15247 */ +// sstore +// /* "":15263:15266 */ +// 0xda +// /* "":15256:15273 */ +// sstore +// /* "":15289:15292 */ +// 0xdb +// /* "":15282:15299 */ +// sstore +// /* "":15315:15318 */ +// 0xdc +// /* "":15308:15325 */ +// sstore +// /* "":15341:15344 */ +// 0xdd +// /* "":15334:15351 */ +// sstore +// /* "":15367:15370 */ +// 0xde +// /* "":15360:15377 */ +// sstore +// /* "":15393:15396 */ +// 0xdf +// /* "":15386:15403 */ +// sstore +// /* "":15419:15422 */ +// 0xe0 +// /* "":15412:15429 */ +// sstore +// /* "":15445:15448 */ +// 0xe1 +// /* "":15438:15455 */ +// sstore +// /* "":15471:15474 */ +// 0xe2 +// /* "":15464:15481 */ +// sstore +// /* "":15497:15500 */ +// 0xe3 +// /* "":15490:15507 */ +// sstore +// /* "":15523:15526 */ +// 0xe4 +// /* "":15516:15533 */ +// sstore +// /* "":15549:15552 */ +// 0xe5 +// /* "":15542:15559 */ +// sstore +// /* "":15575:15578 */ +// 0xe6 +// /* "":15568:15585 */ +// sstore +// /* "":15601:15604 */ +// 0xe7 +// /* "":15594:15611 */ +// sstore +// /* "":15627:15630 */ +// 0xe8 +// /* "":15620:15637 */ +// sstore +// /* "":15653:15656 */ +// 0xe9 +// /* "":15646:15663 */ +// sstore +// /* "":15679:15682 */ +// 0xea +// /* "":15672:15689 */ +// sstore +// /* "":15705:15708 */ +// 0xeb +// /* "":15698:15715 */ +// sstore +// /* "":15731:15734 */ +// 0xec +// /* "":15724:15741 */ +// sstore +// /* "":15757:15760 */ +// 0xed +// /* "":15750:15767 */ +// sstore +// /* "":15783:15786 */ +// 0xee +// /* "":15776:15793 */ +// sstore +// /* "":15809:15812 */ +// 0xef +// /* "":15802:15819 */ +// sstore +// /* "":15835:15838 */ +// 0xf0 +// /* "":15828:15845 */ +// sstore +// /* "":15861:15864 */ +// 0xf1 +// /* "":15854:15871 */ +// sstore +// /* "":15887:15890 */ +// 0xf2 +// /* "":15880:15897 */ +// sstore +// /* "":15913:15916 */ +// 0xf3 +// /* "":15906:15923 */ +// sstore +// /* "":15939:15942 */ +// 0xf4 +// /* "":15932:15949 */ +// sstore +// /* "":15965:15968 */ +// 0xf5 +// /* "":15958:15975 */ +// sstore +// /* "":15991:15994 */ +// 0xf6 +// /* "":15984:16001 */ +// sstore +// /* "":16017:16020 */ +// 0xf7 +// /* "":16010:16027 */ +// sstore +// /* "":16043:16046 */ +// 0xf8 +// /* "":16036:16053 */ +// sstore +// /* "":16069:16072 */ +// 0xf9 +// /* "":16062:16079 */ +// sstore +// /* "":16095:16098 */ +// 0xfa +// /* "":16088:16105 */ +// sstore +// /* "":16121:16124 */ +// 0xfb +// /* "":16114:16131 */ +// sstore +// /* "":16147:16150 */ +// 0xfc +// /* "":16140:16157 */ +// sstore +// /* "":16173:16176 */ +// 0xfd +// /* "":16166:16183 */ +// sstore +// /* "":16199:16202 */ +// 0xfe +// /* "":16192:16209 */ +// sstore +// /* "":16225:16228 */ +// 0xff +// /* "":16218:16235 */ +// sstore +// /* "":16251:16254 */ +// 0x0100 +// /* "":16244:16261 */ +// sstore +// /* "":25:16267 */ +// stop diff --git a/test/libyul/yulStackShuffling/pop_early_to_avoid_swap17.stack b/test/libyul/yulStackShuffling/pop_early_to_avoid_swap17.stack new file mode 100644 index 000000000..6ec0cbb0b --- /dev/null +++ b/test/libyul/yulStackShuffling/pop_early_to_avoid_swap17.stack @@ -0,0 +1,12 @@ +// We avoid a SWAP17 here by first removing duplicates on stack. +[ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk deep ] +[ deep v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk ] +// ---- +// [ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk deep ] +// SWAP1 +// [ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 deep junk ] +// POP +// [ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 deep ] +// SWAP16 +// [ deep v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk ] +// 3 operations diff --git a/test/libyul/yulStackShuffling/swap17.stack b/test/libyul/yulStackShuffling/swap17.stack new file mode 100644 index 000000000..6e62854a9 --- /dev/null +++ b/test/libyul/yulStackShuffling/swap17.stack @@ -0,0 +1,13 @@ +// With a SWAP17 at our disposal, we do not need to first remove duplicates from stack +// as seen in pop_early_to_avoid_swap17.stack. +[ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk deep ] +[ deep v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk ] +// ==== +// maximumStackDepth: 256 +// ---- +// [ junk v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk deep ] +// SWAP17 +// [ deep v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk junk ] +// POP +// [ deep v00 v01 v02 v03 v04 v05 v06 v07 v08 v09 v10 v11 v12 v13 v14 junk ] +// 2 operations diff --git a/test/libyul/yulStackShuffling/swap_cycle.stack b/test/libyul/yulStackShuffling/swap_cycle.stack index fbda89ebf..fd99cea6e 100644 --- a/test/libyul/yulStackShuffling/swap_cycle.stack +++ b/test/libyul/yulStackShuffling/swap_cycle.stack @@ -20,3 +20,4 @@ // [ v1 v0 v2 v3 v4 v5 v6 v7 v9 v10 v11 v12 v13 v14 v15 v16 RET JUNK ] // PUSH JUNK // [ v1 v0 v2 v3 v4 v5 v6 v7 v9 v10 v11 v12 v13 v14 v15 v16 RET JUNK JUNK ] +// 9 operations From 4d38789c12fe4b70ea3ae66b7802421c573007ea Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 26 Feb 2025 16:05:09 +0100 Subject: [PATCH 0734/1340] Do not run StackCompressor and StackLimitEvader on EOF. --- libyul/optimiser/StackCompressor.cpp | 5 ++-- libyul/optimiser/StackLimitEvader.cpp | 17 +++++++++++ libyul/optimiser/Suite.cpp | 30 +++++++++++-------- .../fakeStackLimitEvader/connected.yul | 2 ++ .../fakeStackLimitEvader/function_arg.yul | 2 ++ ...lti_variable_declaration_without_value.yul | 2 ++ .../fakeStackLimitEvader/outer_block.yul | 2 ++ .../fakeStackLimitEvader/return_leave.yul | 2 ++ .../fakeStackLimitEvader/return_one.yul | 2 ++ .../return_one_with_args.yul | 2 ++ .../same_variable_in_lhs_and_rhs.yul | 2 ++ .../fakeStackLimitEvader/stub.yul | 2 ++ .../stackCompressor/noInline.yul | 2 ++ .../stackLimitEvader/cycle.yul | 2 ++ .../stackLimitEvader/cycle_after.yul | 2 ++ .../stackLimitEvader/cycle_after_2.yul | 2 ++ .../stackLimitEvader/cycle_before.yul | 2 ++ .../stackLimitEvader/cycle_before_2.yul | 2 ++ .../stackLimitEvader/cycle_before_after.yul | 2 ++ .../stackLimitEvader/function_arg.yul | 2 ++ .../stackLimitEvader/stub.yul | 2 ++ .../stackLimitEvader/too_many_args_14.yul | 2 ++ .../stackLimitEvader/too_many_args_15.yul | 2 ++ .../stackLimitEvader/too_many_args_16.yul | 2 ++ .../stackLimitEvader/too_many_returns_15.yul | 2 ++ .../stackLimitEvader/too_many_returns_16.yul | 2 ++ .../stackLimitEvader/tree.yul | 2 ++ .../verbatim_many_arguments.yul | 2 ++ .../verbatim_many_arguments_and_returns.yul | 2 ++ .../verbatim_many_returns.yul | 2 ++ 30 files changed, 90 insertions(+), 16 deletions(-) diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 1dac1a66f..3c27cc20f 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -249,15 +249,14 @@ std::tuple StackCompressor::run( ); bool usesOptimizedCodeGenerator = false; bool simulateFunctionsWithJumps = true; - size_t reachableStackDepth = 16; if (auto evmDialect = dynamic_cast(_object.dialect())) { + yulAssert(!evmDialect->eofVersion().has_value(), "StackCompressor does not support EOF."); usesOptimizedCodeGenerator = _optimizeStackAllocation && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); - reachableStackDepth = evmDialect->reachableStackDepth(); } bool allowMSizeOptimization = !MSizeFinder::containsMSize(*_object.dialect(), _object.code()->root()); Block astRoot = std::get(ASTCopier{}(_object.code()->root())); @@ -272,7 +271,7 @@ std::tuple StackCompressor::run( eliminateVariablesOptimizedCodegen( *_object.dialect(), astRoot, - StackLayoutGenerator::reportStackTooDeep(*cfg, simulateFunctionsWithJumps, reachableStackDepth), + StackLayoutGenerator::reportStackTooDeep(*cfg, simulateFunctionsWithJumps, 16u), allowMSizeOptimization ); } diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index d62b3e935..a2a557de9 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -132,6 +132,10 @@ Block StackLimitEvader::run( evmDialect && evmDialect->providesObjectAccess(), "StackLimitEvader can only be run on objects using the EVMDialect with object access." ); + yulAssert( + !evmDialect->eofVersion().has_value(), + "StackLimitEvader does not support EOF." + ); auto astRoot = std::get(ASTCopier{}(_object.code()->root())); if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall()) { @@ -159,6 +163,15 @@ void StackLimitEvader::run( std::map> const& _stackTooDeepErrors ) { + auto const* evmDialect = dynamic_cast(&_context.dialect); + yulAssert( + evmDialect && evmDialect->providesObjectAccess(), + "StackLimitEvader can only be run on objects using the EVMDialect with object access." + ); + yulAssert( + !evmDialect->eofVersion().has_value(), + "StackLimitEvader does not support EOF." + ); std::map> unreachableVariables; for (auto&& [function, stackTooDeepErrors]: _stackTooDeepErrors) { @@ -183,6 +196,10 @@ void StackLimitEvader::run( evmDialect && evmDialect->providesObjectAccess(), "StackLimitEvader can only be run on objects using the EVMDialect with object access." ); + yulAssert( + !evmDialect->eofVersion().has_value(), + "StackLimitEvader does not support EOF." + ); std::vector memoryGuardCalls = findFunctionCalls(_astRoot, "memoryguard", *evmDialect); // Do not optimise, if no ``memoryguard`` call is found. diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 766f96821..17698d74e 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -163,25 +163,29 @@ void OptimiserSuite::run( } if (usesOptimizedCodeGenerator) { + if (!evmDialect->eofVersion().has_value()) { - PROFILER_PROBE("StackCompressor", probe); - _object.setCode(std::make_shared(dialect, std::move(astRoot))); - astRoot = std::get<1>(StackCompressor::run( - _object, - _optimizeStackAllocation, - stackCompressorMaxIterations - )); - } - if (evmDialect->providesObjectAccess()) - { - PROFILER_PROBE("StackLimitEvader", probe); - _object.setCode(std::make_shared(dialect, std::move(astRoot))); - astRoot = StackLimitEvader::run(suite.m_context, _object); + { + PROFILER_PROBE("StackCompressor", probe); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); + astRoot = std::get<1>(StackCompressor::run( + _object, + _optimizeStackAllocation, + stackCompressorMaxIterations + )); + } + if (evmDialect->providesObjectAccess()) + { + PROFILER_PROBE("StackLimitEvader", probe); + _object.setCode(std::make_shared(dialect, std::move(astRoot))); + astRoot = StackLimitEvader::run(suite.m_context, _object); + } } } else if (evmDialect->providesObjectAccess() && _optimizeStackAllocation) { PROFILER_PROBE("StackLimitEvader", probe); + yulAssert(!evmDialect->eofVersion().has_value(), ""); _object.setCode(std::make_shared(dialect, std::move(astRoot))); astRoot = StackLimitEvader::run(suite.m_context, _object); } diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul index 99e92c183..cc2cae6f6 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul @@ -20,6 +20,8 @@ sstore(0, f()) let x, y := g() } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul index 0e5aa9e13..1accb5cef 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul @@ -7,6 +7,8 @@ } sstore(1, h(32)) } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul index 5650b580d..02a974784 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul @@ -7,6 +7,8 @@ let z, $w } } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/outer_block.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/outer_block.yul index 023100cdd..46c3cabb9 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/outer_block.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/outer_block.yul @@ -3,6 +3,8 @@ let $x := 42 sstore(42, $x) } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul index 3b43bd534..a510c65e9 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul @@ -14,6 +14,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one.yul index 50a9d6486..5566f9713 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one.yul @@ -12,6 +12,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul index 706a46c62..42084c16e 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul @@ -12,6 +12,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/same_variable_in_lhs_and_rhs.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/same_variable_in_lhs_and_rhs.yul index e6a9379df..95ede59fa 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/same_variable_in_lhs_and_rhs.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/same_variable_in_lhs_and_rhs.yul @@ -5,6 +5,8 @@ let $z := 42 $z := f($z) } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul index e86619e46..39db59956 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul @@ -23,6 +23,8 @@ g(0) h(1, 2, 3, 4) } +// ==== +// bytecodeFormat: legacy // ---- // step: fakeStackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul b/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul index 1a178abf0..a7e916657 100644 --- a/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul +++ b/test/libyul/yulOptimizerTests/stackCompressor/noInline.yul @@ -2,6 +2,8 @@ let x := 8 function f() { let y := 9 } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackCompressor // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle.yul index 37da7f9b8..1f87ba5b8 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle.yul @@ -44,6 +44,8 @@ sstore(23, g(sload(42))) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after.yul index 4480d012e..5b3aba01f 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after.yul @@ -44,6 +44,8 @@ v := h() } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after_2.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after_2.yul index 4468165f1..c33eea9b3 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after_2.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_after_2.yul @@ -47,6 +47,8 @@ v := h() } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before.yul index e6819ea90..0715f4945 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before.yul @@ -49,6 +49,8 @@ sstore(mul(1,4), a1) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul index a0259b180..59872e4a7 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul @@ -52,6 +52,8 @@ sstore(mul(1,4), a1) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_after.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_after.yul index f5c068d5e..ad9366322 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_after.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_after.yul @@ -53,6 +53,8 @@ v := h() } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/function_arg.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/function_arg.yul index 27f070515..8501a8d02 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/function_arg.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/function_arg.yul @@ -40,6 +40,8 @@ sstore(mul(1,4), a1) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/stub.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/stub.yul index 9f5001c87..338c8e983 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/stub.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/stub.yul @@ -45,6 +45,8 @@ sstore(mul(1,4), a1) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_14.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_14.yul index 02614c492..f6779917e 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_14.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_14.yul @@ -15,6 +15,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_15.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_15.yul index 9ce9be70a..1ad539b30 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_15.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_15.yul @@ -17,6 +17,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_16.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_16.yul index 5a3b3454c..c94c18ac4 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_16.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_args_16.yul @@ -17,6 +17,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_15.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_15.yul index b9d1a5571..a47d38fd0 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_15.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_15.yul @@ -13,6 +13,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_16.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_16.yul index 40553083f..aa144950f 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_16.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/too_many_returns_16.yul @@ -13,6 +13,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul index 8407df5d0..e97e458da 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul @@ -164,6 +164,8 @@ v := sload(mul(42,8)) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments.yul index bde030f68..8a2c52a9a 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments.yul @@ -24,6 +24,8 @@ verbatim_20i_0o("test", a_1, a_2, a_3, a_4, a_5, a_6, a_7, a_8, a_9, a_10, a_11, a_12, a_13, a_14, a_15, a_16, a_17, a_18, a_19, a_20) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul index 46435dd21..e7170a10d 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul @@ -45,6 +45,8 @@ } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul index 47db17e21..e06dd8d8b 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul @@ -7,6 +7,8 @@ sstore(a18, 20) } } +// ==== +// bytecodeFormat: legacy // ---- // step: stackLimitEvader // From 9fdf9b5359ca28b5464e3b18992d4d8898b2d22d Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 26 Feb 2025 20:33:53 +0100 Subject: [PATCH 0735/1340] Pass EVMDialect to StackLayoutGenerator directly. --- .../evm/OptimizedEVMCodeTransform.cpp | 2 +- libyul/backends/evm/StackLayoutGenerator.cpp | 60 +++++++++---------- libyul/backends/evm/StackLayoutGenerator.h | 26 ++++---- libyul/optimiser/StackCompressor.cpp | 8 +-- libyul/optimiser/StackLimitEvader.cpp | 2 +- test/libyul/StackLayoutGeneratorTest.cpp | 4 +- 6 files changed, 50 insertions(+), 52 deletions(-) diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 07ab758d7..69cd046de 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -49,7 +49,7 @@ std::vector OptimizedEVMCodeTransform::run( ) { std::unique_ptr dfg = ControlFlowGraphBuilder::build(_analysisInfo, _dialect, _block); - StackLayout stackLayout = StackLayoutGenerator::run(*dfg, !_dialect.eofVersion().has_value(), _dialect.reachableStackDepth()); + StackLayout stackLayout = StackLayoutGenerator::run(*dfg, _dialect); if (_dialect.eofVersion().has_value()) { diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 6abb1bb9f..69045998c 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -45,22 +45,20 @@ using namespace solidity; using namespace solidity::yul; -StackLayout StackLayoutGenerator::run(CFG const& _cfg, bool _simulateFunctionsWithJumps, size_t _reachableStackDepth) +StackLayout StackLayoutGenerator::run(CFG const& _cfg, EVMDialect const& _evmDialect) { StackLayout stackLayout{{}, {}}; StackLayoutGenerator{ stackLayout, nullptr, - _simulateFunctionsWithJumps, - _reachableStackDepth + _evmDialect }.processEntryPoint(*_cfg.entry); for (auto& functionInfo: _cfg.functionInfo | ranges::views::values) StackLayoutGenerator{ stackLayout, &functionInfo, - _simulateFunctionsWithJumps, - _reachableStackDepth + _evmDialect }.processEntryPoint(*functionInfo.entry, &functionInfo); return stackLayout; @@ -68,14 +66,13 @@ StackLayout StackLayoutGenerator::run(CFG const& _cfg, bool _simulateFunctionsWi std::map> StackLayoutGenerator::reportStackTooDeep( CFG const& _cfg, - bool _simulateFunctionsWithJumps, - size_t _reachableStackDepth + EVMDialect const& _evmDialect ) { std::map> stackTooDeepErrors; - stackTooDeepErrors[YulName{}] = reportStackTooDeep(_cfg, YulName{}, _simulateFunctionsWithJumps, _reachableStackDepth); + stackTooDeepErrors[YulName{}] = reportStackTooDeep(_cfg, YulName{}, _evmDialect); for (auto const& function: _cfg.functions) - if (auto errors = reportStackTooDeep(_cfg, function->name, _simulateFunctionsWithJumps, _reachableStackDepth); !errors.empty()) + if (auto errors = reportStackTooDeep(_cfg, function->name, _evmDialect); !errors.empty()) stackTooDeepErrors[function->name] = std::move(errors); return stackTooDeepErrors; } @@ -83,8 +80,7 @@ std::map> StackLayoutGe std::vector StackLayoutGenerator::reportStackTooDeep( CFG const& _cfg, YulName _functionName, - bool _simulateFunctionsWithJumps, - size_t _reachableStackDepth + EVMDialect const& _evmDialect ) { StackLayout stackLayout{{}, {}}; @@ -99,7 +95,7 @@ std::vector StackLayoutGenerator::reportStac yulAssert(functionInfo, "Function not found."); } - StackLayoutGenerator generator{stackLayout, functionInfo, _simulateFunctionsWithJumps, _reachableStackDepth}; + StackLayoutGenerator generator{stackLayout, functionInfo, _evmDialect}; CFG::BasicBlock const* entry = functionInfo ? functionInfo->entry : _cfg.entry; generator.processEntryPoint(*entry); return generator.reportStackTooDeep(*entry); @@ -108,13 +104,11 @@ std::vector StackLayoutGenerator::reportStac StackLayoutGenerator::StackLayoutGenerator( StackLayout& _layout, CFG::FunctionInfo const* _functionInfo, - bool _simulateFunctionsWithJumps, - size_t _reachableStackDepth + EVMDialect const& _evmDialect ): m_layout(_layout), m_currentFunctionInfo(_functionInfo), - m_simulateFunctionsWithJumps(_simulateFunctionsWithJumps), - m_reachableStackDepth(_reachableStackDepth) + m_evmDialect(_evmDialect) { } @@ -312,7 +306,7 @@ Stack StackLayoutGenerator::propagateStackThroughOperation(Stack _exitStack, CFG // Determine the ideal permutation of the slots in _exitLayout that are not operation outputs (and not to be // generated on the fly), s.t. shuffling the `stack + _operation.output` to _exitLayout is cheap. - Stack stack = createIdealLayout(_operation.output, _exitStack, generateSlotOnTheFly, m_reachableStackDepth); + Stack stack = createIdealLayout(_operation.output, _exitStack, generateSlotOnTheFly, reachableStackDepth()); // Make sure the resulting previous slots do not overlap with any assignmed variables. if (auto const* assignment = std::get_if(&_operation.operation)) @@ -336,7 +330,7 @@ Stack StackLayoutGenerator::propagateStackThroughOperation(Stack _exitStack, CFG stack.pop_back(); else if (auto offset = util::findOffset(stack | ranges::views::reverse | ranges::views::drop(1), stack.back())) { - if (*offset + 2 < m_reachableStackDepth) + if (*offset + 2 < reachableStackDepth()) stack.pop_back(); else break; @@ -354,7 +348,7 @@ Stack StackLayoutGenerator::propagateStackThroughBlock(Stack _exitStack, CFG::Ba for (auto&& [idx, operation]: _block.operations | ranges::views::enumerate | ranges::views::reverse) { Stack newStack = propagateStackThroughOperation(stack, operation, _aggressiveStackCompression); - if (!_aggressiveStackCompression && !findStackTooDeep(newStack, stack, m_reachableStackDepth).empty()) + if (!_aggressiveStackCompression && !findStackTooDeep(newStack, stack, reachableStackDepth()).empty()) // If we had stack errors, run again with aggressive stack compression. return propagateStackThroughBlock(std::move(_exitStack), _block, true); stack = std::move(newStack); @@ -476,7 +470,7 @@ std::optional StackLayoutGenerator::getExitLayoutOrStageDependencies( Stack stack = combineStack( m_layout.blockInfos.at(_conditionalJump.zero).entryLayout, m_layout.blockInfos.at(_conditionalJump.nonZero).entryLayout, - m_reachableStackDepth + reachableStackDepth() ); // Additionally, the jump condition has to be at the stack top at exit. stack.emplace_back(_conditionalJump.condition); @@ -497,7 +491,7 @@ std::optional StackLayoutGenerator::getExitLayoutOrStageDependencies( return StackSlot{_varSlot}; }) | ranges::to; - if (m_simulateFunctionsWithJumps) + if (simulateFunctionsWithJumps()) stack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function}); return stack; }, @@ -677,7 +671,7 @@ std::vector StackLayoutGenerator::reportStac { Stack& operationEntry = m_layout.operationEntryLayout.at(&operation); - stackTooDeepErrors += findStackTooDeep(currentStack, operationEntry, m_reachableStackDepth); + stackTooDeepErrors += findStackTooDeep(currentStack, operationEntry, reachableStackDepth()); currentStack = operationEntry; for (size_t i = 0; i < operation.input.size(); i++) currentStack.pop_back(); @@ -691,7 +685,7 @@ std::vector StackLayoutGenerator::reportStac [&](CFG::BasicBlock::Jump const& _jump) { Stack const& targetLayout = m_layout.blockInfos.at(_jump.target).entryLayout; - stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout, m_reachableStackDepth); + stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout, reachableStackDepth()); if (!_jump.backwards) _addChild(_jump.target); @@ -702,7 +696,7 @@ std::vector StackLayoutGenerator::reportStac m_layout.blockInfos.at(_conditionalJump.zero).entryLayout, m_layout.blockInfos.at(_conditionalJump.nonZero).entryLayout }) - stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout, m_reachableStackDepth); + stackTooDeepErrors += findStackTooDeep(currentStack, targetLayout, reachableStackDepth()); _addChild(_conditionalJump.zero); _addChild(_conditionalJump.nonZero); @@ -769,7 +763,7 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi _addChild(_conditionalJump.zero); _addChild(_conditionalJump.nonZero); }, - [&](CFG::BasicBlock::FunctionReturn const&) { yulAssert(!m_simulateFunctionsWithJumps); }, + [&](CFG::BasicBlock::FunctionReturn const&) { yulAssert(!simulateFunctionsWithJumps()); }, [&](CFG::BasicBlock::Terminated const&) {}, }, _block->exit); }); @@ -779,21 +773,21 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi size_t opGas = 0; auto swap = [&](unsigned _swapDepth) { - if (_swapDepth > m_reachableStackDepth) + if (_swapDepth > reachableStackDepth()) opGas += 1000; else - opGas += evmasm::GasMeter::swapGas(_swapDepth, langutil::EVMVersion{}); + opGas += evmasm::GasMeter::swapGas(_swapDepth, m_evmDialect.evmVersion()); }; auto dupOrPush = [&](StackSlot const& _slot) { if (canBeFreelyGenerated(_slot)) - opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(32), langutil::EVMVersion()); + opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(32), m_evmDialect.evmVersion()); else { if (auto depth = util::findOffset(_source | ranges::views::reverse, _slot)) { - if (*depth < m_reachableStackDepth) - opGas += evmasm::GasMeter::dupGas(*depth + 1, langutil::EVMVersion{}); + if (*depth < reachableStackDepth()) + opGas += evmasm::GasMeter::dupGas(*depth + 1, m_evmDialect.evmVersion()); else opGas += 1000; } @@ -805,12 +799,12 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi yulAssert(util::contains(m_currentFunctionInfo->returnVariables, std::get(_slot))); // Strictly speaking the cost of the PUSH0 depends on the targeted EVM version, but the difference // will not matter here. - opGas += evmasm::GasMeter::pushGas(u256(0), langutil::EVMVersion()); + opGas += evmasm::GasMeter::pushGas(u256(0), m_evmDialect.evmVersion()); } } }; - auto pop = [&]() { opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP,langutil::EVMVersion()); }; - createStackLayout(_source, _target, swap, dupOrPush, pop, m_reachableStackDepth); + auto pop = [&]() { opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP, m_evmDialect.evmVersion()); }; + createStackLayout(_source, _target, swap, dupOrPush, pop, reachableStackDepth()); return opGas; }; /// @returns the number of junk slots to be prepended to @a _targetLayout for an optimal transition from diff --git a/libyul/backends/evm/StackLayoutGenerator.h b/libyul/backends/evm/StackLayoutGenerator.h index 9626c7ad1..bf1b1917b 100644 --- a/libyul/backends/evm/StackLayoutGenerator.h +++ b/libyul/backends/evm/StackLayoutGenerator.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include @@ -55,14 +56,13 @@ class StackLayoutGenerator std::vector variableChoices; }; - static StackLayout run(CFG const& _cfg, bool _simulateFunctionsWithJumps, size_t _reachableStackDepth); + static StackLayout run(CFG const& _cfg, EVMDialect const& _evmDialect); /// @returns a map from function names to the stack too deep errors occurring in that function. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// The empty string is mapped to the stack too deep errors of the main entry point. static std::map> reportStackTooDeep( CFG const& _cfg, - bool _simulateFunctionsWithJumps, - size_t _reachableStackDepth + EVMDialect const& _evmDialect ); /// @returns all stack too deep errors in the function named @a _functionName. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. @@ -70,16 +70,14 @@ class StackLayoutGenerator static std::vector reportStackTooDeep( CFG const& _cfg, YulName _functionName, - bool _simulateFunctionsWithJumps, - size_t _reachableStackDepth + EVMDialect const& _evmDialect ); private: StackLayoutGenerator( StackLayout& _context, CFG::FunctionInfo const* _functionInfo, - bool _simulateFunctionsWithJumps, - size_t _reachableStackDepth + EVMDialect const& _evmDialect ); /// @returns the optimal entry stack layout, s.t. @a _operation can be applied to it and @@ -128,11 +126,19 @@ class StackLayoutGenerator //// Fills in junk when entering branches that do not need a clean stack in case the result is cheaper. void fillInJunk(CFG::BasicBlock const& _block, CFG::FunctionInfo const* _functionInfo = nullptr); + /// True if it simulates functions with jumps. False otherwise. True for legacy bytecode. + bool simulateFunctionsWithJumps() const + { + return !m_evmDialect.eofVersion().has_value(); + } + size_t reachableStackDepth() const + { + return m_evmDialect.reachableStackDepth(); + } + StackLayout& m_layout; CFG::FunctionInfo const* m_currentFunctionInfo = nullptr; - /// True if it simulates functions with jumps. False otherwise. True for legacy bytecode - bool m_simulateFunctionsWithJumps = true; - size_t const m_reachableStackDepth{}; + EVMDialect const& m_evmDialect; }; } diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 3c27cc20f..97d2c0547 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -248,15 +248,14 @@ std::tuple StackCompressor::run( "Need to run the function grouper before the stack compressor." ); bool usesOptimizedCodeGenerator = false; - bool simulateFunctionsWithJumps = true; - if (auto evmDialect = dynamic_cast(_object.dialect())) + auto evmDialect = dynamic_cast(_object.dialect()); + if (evmDialect) { yulAssert(!evmDialect->eofVersion().has_value(), "StackCompressor does not support EOF."); usesOptimizedCodeGenerator = _optimizeStackAllocation && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); - simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); } bool allowMSizeOptimization = !MSizeFinder::containsMSize(*_object.dialect(), _object.code()->root()); Block astRoot = std::get(ASTCopier{}(_object.code()->root())); @@ -268,10 +267,11 @@ std::tuple StackCompressor::run( _object.summarizeStructure() ); std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *_object.dialect(), astRoot); + yulAssert(evmDialect); eliminateVariablesOptimizedCodegen( *_object.dialect(), astRoot, - StackLayoutGenerator::reportStackTooDeep(*cfg, simulateFunctionsWithJumps, 16u), + StackLayoutGenerator::reportStackTooDeep(*cfg, *evmDialect), allowMSizeOptimization ); } diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index a2a557de9..13a3bbd87 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -145,7 +145,7 @@ Block StackLimitEvader::run( _object.summarizeStructure() ); std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, astRoot); - run(_context, astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg, !evmDialect->eofVersion().has_value(), evmDialect->reachableStackDepth())); + run(_context, astRoot, StackLayoutGenerator::reportStackTooDeep(*cfg, *evmDialect)); } else { diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 86fd6184e..eb34eabb1 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -234,10 +234,8 @@ TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::s auto const* evmDialect = dynamic_cast(&yulStack.dialect()); solAssert(evmDialect, "StackLayoutGenerator can only be run on EVM dialects."); - bool simulateFunctionsWithJumps = !evmDialect->eofVersion().has_value(); - size_t reachableStackDepth = evmDialect->reachableStackDepth(); - StackLayout stackLayout = StackLayoutGenerator::run(*cfg, simulateFunctionsWithJumps, reachableStackDepth); + StackLayout stackLayout = StackLayoutGenerator::run(*cfg, *evmDialect); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; StackLayoutPrinter printer{output, stackLayout, yulStack.dialect()}; From 872805b06b6e92615539abe41edea78b8321e0c8 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Wed, 26 Feb 2025 17:13:41 +0100 Subject: [PATCH 0736/1340] Allow --irOptimized output selection in ethdebug. --- libsolidity/interface/StandardCompiler.cpp | 7 +- solc/CommandLineParser.cpp | 19 +- .../debug_info_ethdebug_compatible/args | 1 + .../input.sol | 0 .../debug_info_ethdebug_compatible/output | 193 +++ .../debug_info_ethdebug_incompatible/args | 1 + .../debug_info_ethdebug_incompatible/err | 1 + .../exit | 0 .../input.sol | 0 .../args | 0 .../input.sol | 0 .../output | 8 +- .../args | 1 + .../input.sol | 0 .../output | 79 ++ .../ethdebug_enabled_optimization/err | 1 - .../ethdebug_enabled_optimization_ir/args | 1 + .../ethdebug_enabled_optimization_ir/err | 1 + .../ethdebug_enabled_optimization_ir/exit | 1 + .../input.sol | 7 + .../args | 0 .../err | 1 + .../exit | 1 + .../input.sol | 7 + .../{ethdebug => ethdebug_ir}/args | 0 test/cmdlineTests/ethdebug_ir/input.sol | 7 + .../{ethdebug => ethdebug_ir}/output | 8 +- test/cmdlineTests/ethdebug_iroptimized/args | 1 + .../ethdebug_iroptimized/input.sol | 7 + test/cmdlineTests/ethdebug_iroptimized/output | 77 ++ test/cmdlineTests/ethdebug_no_via_ir/args | 1 + test/cmdlineTests/ethdebug_no_via_ir/err | 1 + test/cmdlineTests/ethdebug_no_via_ir/exit | 1 + .../cmdlineTests/ethdebug_no_via_ir/input.sol | 7 + .../args | 0 .../ethdebug_runtime_ir/input.sol | 7 + .../output | 8 +- .../ethdebug_runtime_iroptimized/args | 1 + .../ethdebug_runtime_iroptimized/input.sol | 7 + .../ethdebug_runtime_iroptimized/output | 77 ++ .../input.json | 29 + .../output.json | 1198 +++++++++++++++++ .../input.json | 26 + .../output.json | 11 + .../input.json | 24 - .../input.json | 24 - .../input.json | 26 + .../output.json | 0 .../input.json | 26 + .../output.json | 522 +++++++ .../input.json | 24 - .../input.json | 26 + .../output.json | 2 +- .../input.json | 26 + .../output.json | 2 +- .../input.json | 25 + .../output.json | 0 .../input.json | 25 + .../output.json | 510 +++++++ .../input.json | 24 - .../input.json | 25 + .../output.json | 0 .../input.json | 25 + .../output.json | 510 +++++++ .../input.json | 22 + .../output.json | 730 ++++++++++ .../input.json | 21 - .../input.json | 22 + .../output.json | 510 +++++++ .../input.json | 22 + .../output.json | 11 + .../input.json | 24 - .../input.json | 25 + .../output.json | 2 +- .../input.json | 25 + .../output.json | 2 +- .../args | 0 .../in.yul | 16 + .../input.json | 16 + .../output.json | 48 + .../args | 0 .../in.yul | 16 + .../input.json | 16 + .../output.json | 11 + .../args | 0 .../in.yul | 0 .../input.json | 2 +- .../output.json | 0 .../args | 1 + .../in.yul | 0 .../input.json | 2 +- .../output.json | 35 + .../input.json | 2 +- .../standard_yul_ethdebug_ir/args | 1 + .../in.yul | 0 .../standard_yul_ethdebug_ir/input.json | 11 + .../standard_yul_ethdebug_ir/output.json | 33 + .../standard_yul_ethdebug_iroptimize/args | 1 + .../standard_yul_ethdebug_iroptimize/in.yul | 17 + .../input.json | 11 + .../output.json | 20 + .../output.json | 11 - .../standard_yul_ethdebug_optimize_ir/args | 1 + .../standard_yul_ethdebug_optimize_ir/in.yul | 17 + .../input.json | 2 +- .../output.json | 11 + .../args | 1 + .../in.yul | 17 + .../input.json | 14 + .../output.json | 11 + test/cmdlineTests/yul_ethdebug/args | 2 +- test/cmdlineTests/yul_ethdebug/output | 11 - test/cmdlineTests/yul_ethdebug_ir/args | 1 + test/cmdlineTests/yul_ethdebug_ir/err | 1 + test/cmdlineTests/yul_ethdebug_ir/exit | 1 + test/cmdlineTests/yul_ethdebug_ir/input.yul | 18 + .../yul_ethdebug_iroptimized/args | 1 + .../yul_ethdebug_iroptimized/input.yul | 18 + .../yul_ethdebug_iroptimized/output | 26 + test/cmdlineTests/yul_ethdebug_optimize/args | 1 + test/cmdlineTests/yul_ethdebug_optimize/err | 1 + test/cmdlineTests/yul_ethdebug_optimize/exit | 1 + .../yul_ethdebug_optimize/input.yul | 18 + .../yul_ethdebug_optimize_iroptimized/args | 1 + .../yul_ethdebug_optimize_iroptimized/err | 1 + .../yul_ethdebug_optimize_iroptimized/exit | 1 + .../input.yul | 18 + test/libsolidity/StandardCompiler.cpp | 100 +- test/solc/CommandLineInterface.cpp | 232 ++-- 129 files changed, 5433 insertions(+), 430 deletions(-) create mode 100644 test/cmdlineTests/debug_info_ethdebug_compatible/args rename test/cmdlineTests/{ethdebug => debug_info_ethdebug_compatible}/input.sol (100%) create mode 100644 test/cmdlineTests/debug_info_ethdebug_compatible/output create mode 100644 test/cmdlineTests/debug_info_ethdebug_incompatible/args create mode 100644 test/cmdlineTests/debug_info_ethdebug_incompatible/err rename test/cmdlineTests/{ethdebug_enabled_optimization => debug_info_ethdebug_incompatible}/exit (100%) rename test/cmdlineTests/{ethdebug_and_ethdebug_runtime => debug_info_ethdebug_incompatible}/input.sol (100%) rename test/cmdlineTests/{ethdebug_and_ethdebug_runtime => ethdebug_and_ethdebug_runtime_ir}/args (100%) rename test/cmdlineTests/{ethdebug_enabled_optimization => ethdebug_and_ethdebug_runtime_ir}/input.sol (100%) rename test/cmdlineTests/{ethdebug_and_ethdebug_runtime => ethdebug_and_ethdebug_runtime_ir}/output (93%) create mode 100644 test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/args rename test/cmdlineTests/{ethdebug_runtime => ethdebug_and_ethdebug_runtime_iroptimized}/input.sol (100%) create mode 100644 test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/output delete mode 100644 test/cmdlineTests/ethdebug_enabled_optimization/err create mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_ir/args create mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_ir/err create mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_ir/exit create mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_ir/input.sol rename test/cmdlineTests/{ethdebug_enabled_optimization => ethdebug_enabled_optimization_iroptimized}/args (100%) create mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/err create mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/exit create mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/input.sol rename test/cmdlineTests/{ethdebug => ethdebug_ir}/args (100%) create mode 100644 test/cmdlineTests/ethdebug_ir/input.sol rename test/cmdlineTests/{ethdebug => ethdebug_ir}/output (95%) create mode 100644 test/cmdlineTests/ethdebug_iroptimized/args create mode 100644 test/cmdlineTests/ethdebug_iroptimized/input.sol create mode 100644 test/cmdlineTests/ethdebug_iroptimized/output create mode 100644 test/cmdlineTests/ethdebug_no_via_ir/args create mode 100644 test/cmdlineTests/ethdebug_no_via_ir/err create mode 100644 test/cmdlineTests/ethdebug_no_via_ir/exit create mode 100644 test/cmdlineTests/ethdebug_no_via_ir/input.sol rename test/cmdlineTests/{ethdebug_runtime => ethdebug_runtime_ir}/args (100%) create mode 100644 test/cmdlineTests/ethdebug_runtime_ir/input.sol rename test/cmdlineTests/{ethdebug_runtime => ethdebug_runtime_ir}/output (94%) create mode 100644 test/cmdlineTests/ethdebug_runtime_iroptimized/args create mode 100644 test/cmdlineTests/ethdebug_runtime_iroptimized/input.sol create mode 100644 test/cmdlineTests/ethdebug_runtime_iroptimized/output create mode 100644 test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json create mode 100644 test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/output.json create mode 100644 test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/input.json create mode 100644 test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json delete mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json delete mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json rename test/cmdlineTests/{standard_output_selection_ethdebug_bytecode_and_deployedbytecode => standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir}/output.json (100%) create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/output.json delete mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/input.json rename test/cmdlineTests/{standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer => standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir}/output.json (85%) create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/input.json rename test/cmdlineTests/{standard_yul_ethdebug_irOptimized => standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized}/output.json (85%) create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json rename test/cmdlineTests/{standard_output_selection_ethdebug_bytecode => standard_output_selection_ethdebug_bytecode_ir}/output.json (100%) create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/output.json delete mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json rename test/cmdlineTests/{standard_output_selection_ethdebug_deployedbytecode => standard_output_selection_ethdebug_deployedbytecode_ir}/output.json (100%) create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/output.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json delete mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_no_viair/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_no_viair/output.json delete mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_optimize/input.json create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/input.json rename test/cmdlineTests/{standard_output_selection_ethdebug_irOptimized => standard_output_selection_ethdebug_optimize_ir}/output.json (85%) create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/input.json rename test/cmdlineTests/{standard_output_selection_ethdebug_optimize => standard_output_selection_ethdebug_optimize_iroptimized}/output.json (85%) rename test/cmdlineTests/{standard_yul_ethdebug_bytecode => standard_yul_debug_info_ethdebug_compatible_output}/args (100%) create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/in.yul create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/output.json rename test/cmdlineTests/{standard_yul_ethdebug_irOptimized => standard_yul_debug_info_ethdebug_incompatible_output}/args (100%) create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/in.yul create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/output.json rename test/cmdlineTests/{standard_yul_ethdebug_optimize => standard_yul_ethdebug_bytecode_ir}/args (100%) rename test/cmdlineTests/{standard_yul_ethdebug_bytecode => standard_yul_ethdebug_bytecode_ir}/in.yul (100%) rename test/cmdlineTests/{standard_yul_ethdebug_bytecode => standard_yul_ethdebug_bytecode_ir}/input.json (68%) rename test/cmdlineTests/{standard_yul_ethdebug_bytecode => standard_yul_ethdebug_bytecode_ir}/output.json (100%) create mode 100644 test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/args rename test/cmdlineTests/{standard_yul_ethdebug_irOptimized => standard_yul_ethdebug_bytecode_iroptimized}/in.yul (100%) rename test/cmdlineTests/{standard_yul_ethdebug_irOptimized => standard_yul_ethdebug_bytecode_iroptimized}/input.json (66%) create mode 100644 test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_ir/args rename test/cmdlineTests/{standard_yul_ethdebug_optimize => standard_yul_ethdebug_ir}/in.yul (100%) create mode 100644 test/cmdlineTests/standard_yul_ethdebug_ir/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_ir/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_iroptimize/args create mode 100644 test/cmdlineTests/standard_yul_ethdebug_iroptimize/in.yul create mode 100644 test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json delete mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize_ir/args create mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize_ir/in.yul rename test/cmdlineTests/{standard_yul_ethdebug_optimize => standard_yul_ethdebug_optimize_ir}/input.json (73%) create mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize_ir/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/args create mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/in.yul create mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/output.json create mode 100644 test/cmdlineTests/yul_ethdebug_ir/args create mode 100644 test/cmdlineTests/yul_ethdebug_ir/err create mode 100644 test/cmdlineTests/yul_ethdebug_ir/exit create mode 100644 test/cmdlineTests/yul_ethdebug_ir/input.yul create mode 100644 test/cmdlineTests/yul_ethdebug_iroptimized/args create mode 100644 test/cmdlineTests/yul_ethdebug_iroptimized/input.yul create mode 100644 test/cmdlineTests/yul_ethdebug_iroptimized/output create mode 100644 test/cmdlineTests/yul_ethdebug_optimize/args create mode 100644 test/cmdlineTests/yul_ethdebug_optimize/err create mode 100644 test/cmdlineTests/yul_ethdebug_optimize/exit create mode 100644 test/cmdlineTests/yul_ethdebug_optimize/input.yul create mode 100644 test/cmdlineTests/yul_ethdebug_optimize_iroptimized/args create mode 100644 test/cmdlineTests/yul_ethdebug_optimize_iroptimized/err create mode 100644 test/cmdlineTests/yul_ethdebug_optimize_iroptimized/exit create mode 100644 test/cmdlineTests/yul_ethdebug_optimize_iroptimized/input.yul diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 230408756..f52ad4e1e 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1200,13 +1200,14 @@ std::variant StandardCompiler::parseI } if ( - ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug && ret.language == "Solidity" && + ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug && (ret.language == "Solidity" || ret.language == "Yul") && !pipelineConfig(ret.outputSelection)[""][""].irCodegen && !isEthdebugRequested(ret.outputSelection) ) return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected."); - if (isEthdebugRequested(ret.outputSelection) && (ret.optimiserSettings.runYulOptimiser || isArtifactRequested(ret.outputSelection, "*", "*", "irOptimized", false))) - return formatFatalError(Error::Type::FatalError, "Optimization is not yet supported with ethdebug."); + if (isEthdebugRequested(ret.outputSelection)) + if (ret.optimiserSettings.runYulOptimiser) + solUnimplemented("Optimization is not yet supported with ethdebug."); return {std::move(ret)}; } diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 1ef477677..25f3048b5 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -1342,12 +1342,18 @@ void CommandLineParser::processArgs() ); if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + { + if (m_options.optimiserSettings().runYulOptimiser) + solUnimplemented( + "Optimization (using --" + g_strOptimize + ") is not yet supported with ethdebug." + ); + if (!m_options.output.debugInfoSelection.has_value()) { m_options.output.debugInfoSelection = DebugInfoSelection::Default(); m_options.output.debugInfoSelection->enable("ethdebug"); } - + } return; } else if (countEnabledOptions({g_strYulDialect, g_strMachine}) >= 1) @@ -1486,17 +1492,14 @@ void CommandLineParser::processArgs() bool incompatibleEthdebugOutputs = m_options.compiler.outputs.asmJson || m_options.compiler.outputs.irAstJson || m_options.compiler.outputs.irOptimizedAstJson || - m_options.compiler.outputs.irOptimized || m_options.optimizer.optimizeYul || m_options.optimizer.optimizeEvmasm; + m_options.optimizer.optimizeYul || m_options.optimizer.optimizeEvmasm; bool incompatibleEthdebugInputs = m_options.input.mode != InputMode::Compiler; static std::string enableEthdebugMessage = "--" + CompilerOutputs::componentName(&CompilerOutputs::ethdebug) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime); - static std::string incompatibleEthdebugOptimizerMessage = - "--" + g_strOptimize + " / --" + CompilerOutputs::componentName(&CompilerOutputs::irOptimized); - - static std::string enableIrMessage = "--" + CompilerOutputs::componentName(&CompilerOutputs::ir); + static std::string enableIrMessage = "--" + CompilerOutputs::componentName(&CompilerOutputs::ir) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::irOptimized); if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) { @@ -1509,7 +1512,7 @@ void CommandLineParser::processArgs() if (incompatibleEthdebugOutputs) solThrow( CommandLineValidationError, - enableEthdebugMessage + " output can only be used with " + enableIrMessage + ". Optimization is not yet supported with ethdebug, e.g. no support for " + incompatibleEthdebugOptimizerMessage + " yet." + enableEthdebugMessage + " output can only be used with " + enableIrMessage + ". Optimization (using --" + g_strOptimize + ") is not yet supported with ethdebug." ); if (!m_options.output.debugInfoSelection.has_value()) @@ -1533,7 +1536,7 @@ void CommandLineParser::processArgs() ) solThrow( CommandLineValidationError, - "--debug-info ethdebug can only be used with " + enableIrMessage + " and/or " + enableEthdebugMessage + ". Optimization is not yet supported with ethdebug, e.g. no support for " + incompatibleEthdebugOptimizerMessage + " yet." + "--debug-info ethdebug can only be used with " + enableIrMessage + " and/or " + enableEthdebugMessage + ". Optimization (using --" + g_strOptimize + ") is not yet supported with ethdebug." ); if (m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug && incompatibleEthdebugInputs) diff --git a/test/cmdlineTests/debug_info_ethdebug_compatible/args b/test/cmdlineTests/debug_info_ethdebug_compatible/args new file mode 100644 index 000000000..74342f38f --- /dev/null +++ b/test/cmdlineTests/debug_info_ethdebug_compatible/args @@ -0,0 +1 @@ +--debug-info ethdebug --via-ir --ir --ir-optimized --ethdebug --ethdebug-runtime diff --git a/test/cmdlineTests/ethdebug/input.sol b/test/cmdlineTests/debug_info_ethdebug_compatible/input.sol similarity index 100% rename from test/cmdlineTests/ethdebug/input.sol rename to test/cmdlineTests/debug_info_ethdebug_compatible/input.sol diff --git a/test/cmdlineTests/debug_info_ethdebug_compatible/output b/test/cmdlineTests/debug_info_ethdebug_compatible/output new file mode 100644 index 000000000..0f9581e7f --- /dev/null +++ b/test/cmdlineTests/debug_info_ethdebug_compatible/output @@ -0,0 +1,193 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{"sources":["debug_info_ethdebug_compatible/input.sol"]} + +======= debug_info_ethdebug_compatible/input.sol:C ======= +IR: +/// ethdebug: enabled +/// @use-src 0:"debug_info_ethdebug_compatible/input.sol" +object "C_6" { + code { + /// @src 0:60:101 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + + return(_1, datasize("C_6_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:60:101 + function constructor_C_6() { + + /// @src 0:60:101 + + } + /// @src 0:60:101 + + } + /// @use-src 0:"debug_info_ethdebug_compatible/input.sol" + object "C_6_deployed" { + code { + /// @src 0:60:101 + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + external_fun_f_5() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + /// @src 0:77:99 + function fun_f_5() { + + } + /// @src 0:60:101 + + } + + data ".metadata" hex"" + } + +} + + +Optimized IR: +/// ethdebug: enabled +/// @use-src 0:"debug_info_ethdebug_compatible/input.sol" +object "C_6" { + code { + { + /// @src 0:60:101 + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + return(_1, datasize("C_6_deployed")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:"debug_info_ethdebug_compatible/input.sol" + object "C_6_deployed" { + code { + { + /// @src 0:60:101 + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0x26121ff0 { external_fun_f() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function abi_decode(headStart, dataEnd) + { + if slt(sub(dataEnd, headStart), 0) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_f() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + abi_decode(4, calldatasize()) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + } + data ".metadata" hex"" + } +} + +Debug Data (ethdebug/format/program): +{} +Debug Data of the runtime part (ethdebug/format/program): +{} diff --git a/test/cmdlineTests/debug_info_ethdebug_incompatible/args b/test/cmdlineTests/debug_info_ethdebug_incompatible/args new file mode 100644 index 000000000..8afe2c9b3 --- /dev/null +++ b/test/cmdlineTests/debug_info_ethdebug_incompatible/args @@ -0,0 +1 @@ +--debug-info ethdebug --via-ir --asm diff --git a/test/cmdlineTests/debug_info_ethdebug_incompatible/err b/test/cmdlineTests/debug_info_ethdebug_incompatible/err new file mode 100644 index 000000000..32401186d --- /dev/null +++ b/test/cmdlineTests/debug_info_ethdebug_incompatible/err @@ -0,0 +1 @@ +Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime. Optimization (using --optimize) is not yet supported with ethdebug. diff --git a/test/cmdlineTests/ethdebug_enabled_optimization/exit b/test/cmdlineTests/debug_info_ethdebug_incompatible/exit similarity index 100% rename from test/cmdlineTests/ethdebug_enabled_optimization/exit rename to test/cmdlineTests/debug_info_ethdebug_incompatible/exit diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime/input.sol b/test/cmdlineTests/debug_info_ethdebug_incompatible/input.sol similarity index 100% rename from test/cmdlineTests/ethdebug_and_ethdebug_runtime/input.sol rename to test/cmdlineTests/debug_info_ethdebug_incompatible/input.sol diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime/args b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/args similarity index 100% rename from test/cmdlineTests/ethdebug_and_ethdebug_runtime/args rename to test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/args diff --git a/test/cmdlineTests/ethdebug_enabled_optimization/input.sol b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/input.sol similarity index 100% rename from test/cmdlineTests/ethdebug_enabled_optimization/input.sol rename to test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/input.sol diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime/output b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/output similarity index 93% rename from test/cmdlineTests/ethdebug_and_ethdebug_runtime/output rename to test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/output index 000f29c4d..38dab05af 100644 --- a/test/cmdlineTests/ethdebug_and_ethdebug_runtime/output +++ b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/output @@ -1,10 +1,10 @@ ======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["ethdebug_and_ethdebug_runtime/input.sol"]} +{"sources":["ethdebug_and_ethdebug_runtime_ir/input.sol"]} -======= ethdebug_and_ethdebug_runtime/input.sol:C ======= +======= ethdebug_and_ethdebug_runtime_ir/input.sol:C ======= IR: /// ethdebug: enabled -/// @use-src 0:"ethdebug_and_ethdebug_runtime/input.sol" +/// @use-src 0:"ethdebug_and_ethdebug_runtime_ir/input.sol" object "C_6" { code { /// @src 0:60:101 "contract C {..." @@ -35,7 +35,7 @@ object "C_6" { /// @src 0:60:101 "contract C {..." } - /// @use-src 0:"ethdebug_and_ethdebug_runtime/input.sol" + /// @use-src 0:"ethdebug_and_ethdebug_runtime_ir/input.sol" object "C_6_deployed" { code { /// @src 0:60:101 "contract C {..." diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/args b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/args new file mode 100644 index 000000000..09535998b --- /dev/null +++ b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/args @@ -0,0 +1 @@ +--ethdebug-runtime --ethdebug --via-ir --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_runtime/input.sol b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/input.sol similarity index 100% rename from test/cmdlineTests/ethdebug_runtime/input.sol rename to test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/input.sol diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/output b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/output new file mode 100644 index 000000000..19a3c9e86 --- /dev/null +++ b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/output @@ -0,0 +1,79 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{"sources":["ethdebug_and_ethdebug_runtime_iroptimized/input.sol"]} + +======= ethdebug_and_ethdebug_runtime_iroptimized/input.sol:C ======= +Optimized IR: +/// ethdebug: enabled +/// @use-src 0:"ethdebug_and_ethdebug_runtime_iroptimized/input.sol" +object "C_6" { + code { + { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + return(_1, datasize("C_6_deployed")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:"ethdebug_and_ethdebug_runtime_iroptimized/input.sol" + object "C_6_deployed" { + code { + { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0x26121ff0 { external_fun_f() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function abi_decode(headStart, dataEnd) + { + if slt(sub(dataEnd, headStart), 0) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_f() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + abi_decode(4, calldatasize()) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + } + data ".metadata" hex"" + } +} + +Debug Data (ethdebug/format/program): +{} +Debug Data of the runtime part (ethdebug/format/program): +{} diff --git a/test/cmdlineTests/ethdebug_enabled_optimization/err b/test/cmdlineTests/ethdebug_enabled_optimization/err deleted file mode 100644 index 082f6feee..000000000 --- a/test/cmdlineTests/ethdebug_enabled_optimization/err +++ /dev/null @@ -1 +0,0 @@ -Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet. diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_ir/args b/test/cmdlineTests/ethdebug_enabled_optimization_ir/args new file mode 100644 index 000000000..38ce714e1 --- /dev/null +++ b/test/cmdlineTests/ethdebug_enabled_optimization_ir/args @@ -0,0 +1 @@ +--ethdebug --via-ir --optimize --ir \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_ir/err b/test/cmdlineTests/ethdebug_enabled_optimization_ir/err new file mode 100644 index 000000000..b2c26e5d8 --- /dev/null +++ b/test/cmdlineTests/ethdebug_enabled_optimization_ir/err @@ -0,0 +1 @@ +Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized. Optimization (using --optimize) is not yet supported with ethdebug. diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_ir/exit b/test/cmdlineTests/ethdebug_enabled_optimization_ir/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/ethdebug_enabled_optimization_ir/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_ir/input.sol b/test/cmdlineTests/ethdebug_enabled_optimization_ir/input.sol new file mode 100644 index 000000000..25b9640ca --- /dev/null +++ b/test/cmdlineTests/ethdebug_enabled_optimization_ir/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} + diff --git a/test/cmdlineTests/ethdebug_enabled_optimization/args b/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/args similarity index 100% rename from test/cmdlineTests/ethdebug_enabled_optimization/args rename to test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/args diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/err b/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/err new file mode 100644 index 000000000..b2c26e5d8 --- /dev/null +++ b/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/err @@ -0,0 +1 @@ +Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized. Optimization (using --optimize) is not yet supported with ethdebug. diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/exit b/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/input.sol b/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/input.sol new file mode 100644 index 000000000..25b9640ca --- /dev/null +++ b/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} + diff --git a/test/cmdlineTests/ethdebug/args b/test/cmdlineTests/ethdebug_ir/args similarity index 100% rename from test/cmdlineTests/ethdebug/args rename to test/cmdlineTests/ethdebug_ir/args diff --git a/test/cmdlineTests/ethdebug_ir/input.sol b/test/cmdlineTests/ethdebug_ir/input.sol new file mode 100644 index 000000000..25b9640ca --- /dev/null +++ b/test/cmdlineTests/ethdebug_ir/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} + diff --git a/test/cmdlineTests/ethdebug/output b/test/cmdlineTests/ethdebug_ir/output similarity index 95% rename from test/cmdlineTests/ethdebug/output rename to test/cmdlineTests/ethdebug_ir/output index 375c5cf90..6713431b6 100644 --- a/test/cmdlineTests/ethdebug/output +++ b/test/cmdlineTests/ethdebug_ir/output @@ -1,10 +1,10 @@ ======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["ethdebug/input.sol"]} +{"sources":["ethdebug_ir/input.sol"]} -======= ethdebug/input.sol:C ======= +======= ethdebug_ir/input.sol:C ======= IR: /// ethdebug: enabled -/// @use-src 0:"ethdebug/input.sol" +/// @use-src 0:"ethdebug_ir/input.sol" object "C_6" { code { /// @src 0:60:101 "contract C {..." @@ -35,7 +35,7 @@ object "C_6" { /// @src 0:60:101 "contract C {..." } - /// @use-src 0:"ethdebug/input.sol" + /// @use-src 0:"ethdebug_ir/input.sol" object "C_6_deployed" { code { /// @src 0:60:101 "contract C {..." diff --git a/test/cmdlineTests/ethdebug_iroptimized/args b/test/cmdlineTests/ethdebug_iroptimized/args new file mode 100644 index 000000000..e048da7bb --- /dev/null +++ b/test/cmdlineTests/ethdebug_iroptimized/args @@ -0,0 +1 @@ +--ethdebug --via-ir --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_iroptimized/input.sol b/test/cmdlineTests/ethdebug_iroptimized/input.sol new file mode 100644 index 000000000..25b9640ca --- /dev/null +++ b/test/cmdlineTests/ethdebug_iroptimized/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} + diff --git a/test/cmdlineTests/ethdebug_iroptimized/output b/test/cmdlineTests/ethdebug_iroptimized/output new file mode 100644 index 000000000..59e2579eb --- /dev/null +++ b/test/cmdlineTests/ethdebug_iroptimized/output @@ -0,0 +1,77 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{"sources":["ethdebug_iroptimized/input.sol"]} + +======= ethdebug_iroptimized/input.sol:C ======= +Optimized IR: +/// ethdebug: enabled +/// @use-src 0:"ethdebug_iroptimized/input.sol" +object "C_6" { + code { + { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + return(_1, datasize("C_6_deployed")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:"ethdebug_iroptimized/input.sol" + object "C_6_deployed" { + code { + { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0x26121ff0 { external_fun_f() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function abi_decode(headStart, dataEnd) + { + if slt(sub(dataEnd, headStart), 0) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_f() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + abi_decode(4, calldatasize()) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + } + data ".metadata" hex"" + } +} + +Debug Data (ethdebug/format/program): +{} diff --git a/test/cmdlineTests/ethdebug_no_via_ir/args b/test/cmdlineTests/ethdebug_no_via_ir/args new file mode 100644 index 000000000..6a019364e --- /dev/null +++ b/test/cmdlineTests/ethdebug_no_via_ir/args @@ -0,0 +1 @@ +--ethdebug --ir --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_no_via_ir/err b/test/cmdlineTests/ethdebug_no_via_ir/err new file mode 100644 index 000000000..2729b6d5d --- /dev/null +++ b/test/cmdlineTests/ethdebug_no_via_ir/err @@ -0,0 +1 @@ +Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified. diff --git a/test/cmdlineTests/ethdebug_no_via_ir/exit b/test/cmdlineTests/ethdebug_no_via_ir/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/ethdebug_no_via_ir/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/ethdebug_no_via_ir/input.sol b/test/cmdlineTests/ethdebug_no_via_ir/input.sol new file mode 100644 index 000000000..25b9640ca --- /dev/null +++ b/test/cmdlineTests/ethdebug_no_via_ir/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} + diff --git a/test/cmdlineTests/ethdebug_runtime/args b/test/cmdlineTests/ethdebug_runtime_ir/args similarity index 100% rename from test/cmdlineTests/ethdebug_runtime/args rename to test/cmdlineTests/ethdebug_runtime_ir/args diff --git a/test/cmdlineTests/ethdebug_runtime_ir/input.sol b/test/cmdlineTests/ethdebug_runtime_ir/input.sol new file mode 100644 index 000000000..25b9640ca --- /dev/null +++ b/test/cmdlineTests/ethdebug_runtime_ir/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} + diff --git a/test/cmdlineTests/ethdebug_runtime/output b/test/cmdlineTests/ethdebug_runtime_ir/output similarity index 94% rename from test/cmdlineTests/ethdebug_runtime/output rename to test/cmdlineTests/ethdebug_runtime_ir/output index 8670e379d..93b7b91f1 100644 --- a/test/cmdlineTests/ethdebug_runtime/output +++ b/test/cmdlineTests/ethdebug_runtime_ir/output @@ -1,10 +1,10 @@ ======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["ethdebug_runtime/input.sol"]} +{"sources":["ethdebug_runtime_ir/input.sol"]} -======= ethdebug_runtime/input.sol:C ======= +======= ethdebug_runtime_ir/input.sol:C ======= IR: /// ethdebug: enabled -/// @use-src 0:"ethdebug_runtime/input.sol" +/// @use-src 0:"ethdebug_runtime_ir/input.sol" object "C_6" { code { /// @src 0:60:101 "contract C {..." @@ -35,7 +35,7 @@ object "C_6" { /// @src 0:60:101 "contract C {..." } - /// @use-src 0:"ethdebug_runtime/input.sol" + /// @use-src 0:"ethdebug_runtime_ir/input.sol" object "C_6_deployed" { code { /// @src 0:60:101 "contract C {..." diff --git a/test/cmdlineTests/ethdebug_runtime_iroptimized/args b/test/cmdlineTests/ethdebug_runtime_iroptimized/args new file mode 100644 index 000000000..f647c52a7 --- /dev/null +++ b/test/cmdlineTests/ethdebug_runtime_iroptimized/args @@ -0,0 +1 @@ +--ethdebug-runtime --via-ir --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_runtime_iroptimized/input.sol b/test/cmdlineTests/ethdebug_runtime_iroptimized/input.sol new file mode 100644 index 000000000..25b9640ca --- /dev/null +++ b/test/cmdlineTests/ethdebug_runtime_iroptimized/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} + diff --git a/test/cmdlineTests/ethdebug_runtime_iroptimized/output b/test/cmdlineTests/ethdebug_runtime_iroptimized/output new file mode 100644 index 000000000..733e47a85 --- /dev/null +++ b/test/cmdlineTests/ethdebug_runtime_iroptimized/output @@ -0,0 +1,77 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{"sources":["ethdebug_runtime_iroptimized/input.sol"]} + +======= ethdebug_runtime_iroptimized/input.sol:C ======= +Optimized IR: +/// ethdebug: enabled +/// @use-src 0:"ethdebug_runtime_iroptimized/input.sol" +object "C_6" { + code { + { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + return(_1, datasize("C_6_deployed")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:"ethdebug_runtime_iroptimized/input.sol" + object "C_6_deployed" { + code { + { + /// @src 0:60:101 "contract C {..." + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0x26121ff0 { external_fun_f() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function abi_decode(headStart, dataEnd) + { + if slt(sub(dataEnd, headStart), 0) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_f() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + abi_decode(4, calldatasize()) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + } + data ".metadata" hex"" + } +} + +Debug Data of the runtime part (ethdebug/format/program): +{} diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json new file mode 100644 index 000000000..422a54f90 --- /dev/null +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json @@ -0,0 +1,29 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "debug": { + "debugInfo": [ + "ethdebug" + ] + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "ir", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/output.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/output.json new file mode 100644 index 000000000..0b8a87baf --- /dev/null +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/output.json @@ -0,0 +1,1198 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + /// @src 0:58:123 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_14() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + + return(_1, datasize(\"A1_14_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:58:123 + function constructor_A1_14() { + + /// @src 0:58:123 + + } + /// @src 0:58:123 + + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + /// @src 0:58:123 + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_13() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_13() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_13(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @src 0:72:121 + function fun_a_13(var_x_3) { + + /// @src 0:112:113 + let _1 := var_x_3 + let expr_7 := _1 + /// @src 0:116:117 + let expr_8 := 0x00 + /// @src 0:112:117 + let expr_9 := gt(cleanup_t_uint256(expr_7), convert_t_rational_0_by_1_to_t_uint256(expr_8)) + /// @src 0:105:118 + assert_helper(expr_9) + + } + /// @src 0:58:123 + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + return(_1, datasize(\"A1_14_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @src 0:72:121 + function fun_a(var_x) + { + /// @src 0:112:113 + let _1 := var_x + let expr := _1 + /// @src 0:116:117 + let expr_1 := 0x00 + /// @src 0:112:117 + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:105:118 + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + /// @src 0:124:189 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A2_27() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + + return(_1, datasize(\"A2_27_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:124:189 + function constructor_A2_27() { + + /// @src 0:124:189 + + } + /// @src 0:124:189 + + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + /// @src 0:124:189 + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_26() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_26() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_26(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @src 0:138:187 + function fun_a_26(var_x_16) { + + /// @src 0:178:179 + let _1 := var_x_16 + let expr_20 := _1 + /// @src 0:182:183 + let expr_21 := 0x00 + /// @src 0:178:183 + let expr_22 := gt(cleanup_t_uint256(expr_20), convert_t_rational_0_by_1_to_t_uint256(expr_21)) + /// @src 0:171:184 + assert_helper(expr_22) + + } + /// @src 0:124:189 + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + return(_1, datasize(\"A2_27_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @src 0:138:187 + function fun_a(var_x) + { + /// @src 0:178:179 + let _1 := var_x + let expr := _1 + /// @src 0:182:183 + let expr_1 := 0x00 + /// @src 0:178:183 + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:171:184 + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + /// @src 1:58:123 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_42() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + + return(_1, datasize(\"A1_42_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:58:123 + function constructor_A1_42() { + + /// @src 1:58:123 + + } + /// @src 1:58:123 + + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + /// @src 1:58:123 + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_41() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_41() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_41(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @src 1:72:121 + function fun_b_41(var_x_31) { + + /// @src 1:112:113 + let _1 := var_x_31 + let expr_35 := _1 + /// @src 1:116:117 + let expr_36 := 0x00 + /// @src 1:112:117 + let expr_37 := gt(cleanup_t_uint256(expr_35), convert_t_rational_0_by_1_to_t_uint256(expr_36)) + /// @src 1:105:118 + assert_helper(expr_37) + + } + /// @src 1:58:123 + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + return(_1, datasize(\"A1_42_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @src 1:72:121 + function fun_b(var_x) + { + /// @src 1:112:113 + let _1 := var_x + let expr := _1 + /// @src 1:116:117 + let expr_1 := 0x00 + /// @src 1:112:117 + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:105:118 + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + /// @src 1:124:189 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_B2_55() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + + return(_1, datasize(\"B2_55_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:124:189 + function constructor_B2_55() { + + /// @src 1:124:189 + + } + /// @src 1:124:189 + + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + /// @src 1:124:189 + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_54() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_54() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_54(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @src 1:138:187 + function fun_b_54(var_x_44) { + + /// @src 1:178:179 + let _1 := var_x_44 + let expr_48 := _1 + /// @src 1:182:183 + let expr_49 := 0x00 + /// @src 1:178:183 + let expr_50 := gt(cleanup_t_uint256(expr_48), convert_t_rational_0_by_1_to_t_uint256(expr_49)) + /// @src 1:171:184 + assert_helper(expr_50) + + } + /// @src 1:124:189 + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + return(_1, datasize(\"B2_55_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @src 1:138:187 + function fun_b(var_x) + { + /// @src 1:178:179 + let _1 := var_x + let expr := _1 + /// @src 1:182:183 + let expr_1 := 0x00 + /// @src 1:178:183 + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:171:184 + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "a.sol", + "b.sol" + ] + }, + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/input.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/input.json new file mode 100644 index 000000000..8f8edcd29 --- /dev/null +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/input.json @@ -0,0 +1,26 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "debug": { + "debugInfo": [ + "ethdebug" + ] + }, + "outputSelection": { + "*": { + "*": [ + "evm.assembly" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json new file mode 100644 index 000000000..963bcd8d7 --- /dev/null +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + "message": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json deleted file mode 100644 index 6ac2691c2..000000000 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/input.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "a.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" - }, - "b.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" - } - }, - "settings": { - "viaIR": true, - "optimizer": { - "enabled": false - }, - "outputSelection": { - "*": { - "*": [ - "evm.bytecode.ethdebug", "ir" - ] - } - } - } -} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json deleted file mode 100644 index bb93f57a8..000000000 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/input.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "a.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" - }, - "b.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" - } - }, - "settings": { - "viaIR": true, - "optimizer": { - "enabled": false - }, - "outputSelection": { - "*": { - "*": [ - "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir" - ] - } - } - } -} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json new file mode 100644 index 000000000..8ed44ca05 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json @@ -0,0 +1,26 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/output.json similarity index 100% rename from test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode/output.json rename to test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/output.json diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json new file mode 100644 index 000000000..27c400f9e --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json @@ -0,0 +1,26 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/output.json new file mode 100644 index 000000000..66b9082dc --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/output.json @@ -0,0 +1,522 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + return(_1, datasize(\"A1_14_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 13 @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:116:117 \"0\" + let expr_1 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + return(_1, datasize(\"A2_27_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 26 @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:182:183 \"0\" + let expr_1 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + return(_1, datasize(\"A1_42_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 41 @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:116:117 \"0\" + let expr_1 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": {} + }, + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + return(_1, datasize(\"B2_55_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 54 @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:182:183 \"0\" + let expr_1 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "a.sol", + "b.sol" + ] + }, + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/input.json deleted file mode 100644 index e45f27f3c..000000000 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/input.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "a.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" - }, - "b.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" - } - }, - "settings": { - "viaIR": true, - "optimizer": { - "enabled": true - }, - "outputSelection": { - "*": { - "*": [ - "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "irOptimized" - ] - } - } - } -} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/input.json new file mode 100644 index 000000000..ad74649f5 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/input.json @@ -0,0 +1,26 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/output.json similarity index 85% rename from test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/output.json rename to test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/output.json index 3ed2f577c..44867c7a7 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/output.json @@ -5,7 +5,7 @@ "formattedMessage": "Optimization is not yet supported with ethdebug.", "message": "Optimization is not yet supported with ethdebug.", "severity": "error", - "type": "FatalError" + "type": "UnimplementedFeatureError" } ] } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/input.json new file mode 100644 index 000000000..ad74649f5 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/input.json @@ -0,0 +1,26 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_irOptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/output.json similarity index 85% rename from test/cmdlineTests/standard_yul_ethdebug_irOptimized/output.json rename to test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/output.json index 3ed2f577c..44867c7a7 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_irOptimized/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/output.json @@ -5,7 +5,7 @@ "formattedMessage": "Optimization is not yet supported with ethdebug.", "message": "Optimization is not yet supported with ethdebug.", "severity": "error", - "type": "FatalError" + "type": "UnimplementedFeatureError" } ] } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json new file mode 100644 index 000000000..35c8f940e --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/output.json similarity index 100% rename from test/cmdlineTests/standard_output_selection_ethdebug_bytecode/output.json rename to test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/output.json diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json new file mode 100644 index 000000000..e4681967f --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/output.json new file mode 100644 index 000000000..d7284ab64 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/output.json @@ -0,0 +1,510 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + return(_1, datasize(\"A1_14_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 13 @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:116:117 \"0\" + let expr_1 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + return(_1, datasize(\"A2_27_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 26 @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:182:183 \"0\" + let expr_1 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + return(_1, datasize(\"A1_42_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 41 @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:116:117 \"0\" + let expr_1 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + return(_1, datasize(\"B2_55_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 54 @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:182:183 \"0\" + let expr_1 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "a.sol", + "b.sol" + ] + }, + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json deleted file mode 100644 index f8e3ee312..000000000 --- a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/input.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "a.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" - }, - "b.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" - } - }, - "settings": { - "viaIR": true, - "optimizer": { - "enabled": false - }, - "outputSelection": { - "*": { - "*": [ - "evm.deployedBytecode.ethdebug", "ir" - ] - } - } - } -} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json new file mode 100644 index 000000000..6239a7275 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.deployedBytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/output.json similarity index 100% rename from test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode/output.json rename to test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/output.json diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json new file mode 100644 index 000000000..fdb6c95b8 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": false + }, + "outputSelection": { + "*": { + "*": [ + "evm.deployedBytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/output.json new file mode 100644 index 000000000..dce2a276e --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/output.json @@ -0,0 +1,510 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + return(_1, datasize(\"A1_14_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 13 @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:116:117 \"0\" + let expr_1 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + return(_1, datasize(\"A2_27_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 26 @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:182:183 \"0\" + let expr_1 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + return(_1, datasize(\"A1_42_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 41 @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:116:117 \"0\" + let expr_1 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "deployedBytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + return(_1, datasize(\"B2_55_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 54 @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:182:183 \"0\" + let expr_1 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "a.sol", + "b.sol" + ] + }, + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json new file mode 100644 index 000000000..5bc9d5467 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json @@ -0,0 +1,22 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json new file mode 100644 index 000000000..fabb25ee6 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json @@ -0,0 +1,730 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_14() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + + return(_1, datasize(\"A1_14_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_14() { + + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_13() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_13() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_13(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 13 + /// @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_13(var_x_3) { + + /// @src 0:112:113 \"x\" + let _1 := var_x_3 + let expr_7 := _1 + /// @src 0:116:117 \"0\" + let expr_8 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_9 := gt(cleanup_t_uint256(expr_7), convert_t_rational_0_by_1_to_t_uint256(expr_8)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_9) + + } + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A2_27() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + + return(_1, datasize(\"A2_27_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + function constructor_A2_27() { + + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xf0fdf834 + { + // a(uint256) + + external_fun_a_26() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_a_26() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_a_26(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 26 + /// @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a_26(var_x_16) { + + /// @src 0:178:179 \"x\" + let _1 := var_x_16 + let expr_20 := _1 + /// @src 0:182:183 \"0\" + let expr_21 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_22 := gt(cleanup_t_uint256(expr_20), convert_t_rational_0_by_1_to_t_uint256(expr_21)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_22) + + } + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_A1_42() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + + return(_1, datasize(\"A1_42_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_A1_42() { + + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_41() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_41() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_41(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 41 + /// @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_41(var_x_31) { + + /// @src 1:112:113 \"x\" + let _1 := var_x_31 + let expr_35 := _1 + /// @src 1:116:117 \"0\" + let expr_36 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_37 := gt(cleanup_t_uint256(expr_35), convert_t_rational_0_by_1_to_t_uint256(expr_36)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_37) + + } + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_B2_55() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + + return(_1, datasize(\"B2_55_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + function constructor_B2_55() { + + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0xcd580ff3 + { + // b(uint256) + + external_fun_b_54() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function cleanup_t_uint256(value) -> cleaned { + cleaned := value + } + + function validator_revert_t_uint256(value) { + if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) } + } + + function abi_decode_t_uint256(offset, end) -> value { + value := calldataload(offset) + validator_revert_t_uint256(value) + } + + function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_b_54() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + let param_0 := abi_decode_tuple_t_uint256(4, calldatasize()) + fun_b_54(param_0) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function cleanup_t_rational_0_by_1(value) -> cleaned { + cleaned := value + } + + function identity(value) -> ret { + ret := value + } + + function convert_t_rational_0_by_1_to_t_uint256(value) -> converted { + converted := cleanup_t_uint256(identity(cleanup_t_rational_0_by_1(value))) + } + + function panic_error_0x01() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x01) + revert(0, 0x24) + } + + function assert_helper(condition) { + if iszero(condition) { panic_error_0x01() } + } + + /// @ast-id 54 + /// @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b_54(var_x_44) { + + /// @src 1:178:179 \"x\" + let _1 := var_x_44 + let expr_48 := _1 + /// @src 1:182:183 \"0\" + let expr_49 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_50 := gt(cleanup_t_uint256(expr_48), convert_t_rational_0_by_1_to_t_uint256(expr_49)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_50) + + } + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + } + }, + "ethdebug": { + "sources": [ + "a.sol", + "b.sol" + ] + }, + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/input.json deleted file mode 100644 index ab13b27ea..000000000 --- a/test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/input.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "a.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" - }, - "b.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" - } - }, - "settings": { - "viaIR": true, - "outputSelection": { - "*": { - "*": [ - "evm.bytecode.ethdebug", "irOptimized" - ] - } - } - } -} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json new file mode 100644 index 000000000..8952a241f --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json @@ -0,0 +1,22 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json new file mode 100644 index 000000000..d7284ab64 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json @@ -0,0 +1,510 @@ +{ + "contracts": { + "a.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A1_14\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_14_deployed\"), datasize(\"A1_14_deployed\")) + return(_1, datasize(\"A1_14_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A1_14_deployed\" { + code { + { + /// @src 0:58:123 \"contract A1 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 13 @src 0:72:121 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:116:117 \"0\" + let expr_1 := 0x00 + /// @src 0:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "A2": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"a.sol\" +object \"A2_27\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A2_27_deployed\"), datasize(\"A2_27_deployed\")) + return(_1, datasize(\"A2_27_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 0:\"a.sol\" + object \"A2_27_deployed\" { + code { + { + /// @src 0:124:189 \"contract A2 { function a(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xf0fdf834 { external_fun_a() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_a() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_a(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 26 @src 0:138:187 \"function a(uint x) public pure { assert(x > 0); }\" + function fun_a(var_x) + { + /// @src 0:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 0:182:183 \"0\" + let expr_1 := 0x00 + /// @src 0:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 0:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + }, + "b.sol": { + "A1": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"A1_42\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"A1_42_deployed\"), datasize(\"A1_42_deployed\")) + return(_1, datasize(\"A1_42_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"A1_42_deployed\" { + code { + { + /// @src 1:58:123 \"contract A1 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 41 @src 1:72:121 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:112:113 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:116:117 \"0\" + let expr_1 := 0x00 + /// @src 1:112:117 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:105:118 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + }, + "B2": { + "evm": { + "bytecode": { + "ethdebug": {} + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 1:\"b.sol\" +object \"B2_55\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"B2_55_deployed\"), datasize(\"B2_55_deployed\")) + return(_1, datasize(\"B2_55_deployed\")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + } + /// @use-src 1:\"b.sol\" + object \"B2_55_deployed\" { + code { + { + /// @src 1:124:189 \"contract B2 { function b(uint x) public pure { assert(x > 0); } }\" + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xcd580ff3 { external_fun_b() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function validator_revert_uint256(value) + { + if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) } + } + function abi_decode_uint256(offset, end) -> value + { + value := calldataload(offset) + validator_revert_uint256(value) + } + function abi_decode_tuple_uint256(headStart, dataEnd) -> value0 + { + if slt(sub(dataEnd, headStart), 32) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + let offset := 0 + value0 := abi_decode_uint256(add(headStart, offset), dataEnd) + } + function abi_encode_tuple(headStart) -> tail + { tail := add(headStart, 0) } + function external_fun_b() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + let param := abi_decode_tuple_uint256(4, calldatasize()) + fun_b(param) + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function panic_error_0x01() + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x01) + revert(0, 0x24) + } + function assert_helper(condition) + { + if iszero(condition) { panic_error_0x01() } + } + /// @ast-id 54 @src 1:138:187 \"function b(uint x) public pure { assert(x > 0); }\" + function fun_b(var_x) + { + /// @src 1:178:179 \"x\" + let _1 := var_x + let expr := _1 + /// @src 1:182:183 \"0\" + let expr_1 := 0x00 + /// @src 1:178:183 \"x > 0\" + let expr_2 := gt(cleanup_uint256(expr), convert_rational_by_to_uint256(expr_1)) + /// @src 1:171:184 \"assert(x > 0)\" + assert_helper(expr_2) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "a.sol", + "b.sol" + ] + }, + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/input.json new file mode 100644 index 000000000..574a8b1c4 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/input.json @@ -0,0 +1,22 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/output.json new file mode 100644 index 000000000..1329babc3 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_no_viair/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + "message": "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize/input.json deleted file mode 100644 index a8a5cff05..000000000 --- a/test/cmdlineTests/standard_output_selection_ethdebug_optimize/input.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "a.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" - }, - "b.sol": { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" - } - }, - "settings": { - "viaIR": true, - "optimizer": { - "enabled": true - }, - "outputSelection": { - "*": { - "*": [ - "evm.bytecode.ethdebug", "ir" - ] - } - } - } -} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/input.json new file mode 100644 index 000000000..a684e0dc0 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "ir" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/output.json similarity index 85% rename from test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/output.json rename to test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/output.json index 3ed2f577c..44867c7a7 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_irOptimized/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/output.json @@ -5,7 +5,7 @@ "formattedMessage": "Optimization is not yet supported with ethdebug.", "message": "Optimization is not yet supported with ethdebug.", "severity": "error", - "type": "FatalError" + "type": "UnimplementedFeatureError" } ] } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/input.json new file mode 100644 index 000000000..1f09e3a70 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/input.json @@ -0,0 +1,25 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "irOptimized" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/output.json similarity index 85% rename from test/cmdlineTests/standard_output_selection_ethdebug_optimize/output.json rename to test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/output.json index 3ed2f577c..44867c7a7 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_optimize/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/output.json @@ -5,7 +5,7 @@ "formattedMessage": "Optimization is not yet supported with ethdebug.", "message": "Optimization is not yet supported with ethdebug.", "severity": "error", - "type": "FatalError" + "type": "UnimplementedFeatureError" } ] } diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode/args b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/args similarity index 100% rename from test/cmdlineTests/standard_yul_ethdebug_bytecode/args rename to test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/args diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/in.yul b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/in.yul new file mode 100644 index 000000000..aa564d00c --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/in.yul @@ -0,0 +1,16 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json new file mode 100644 index 000000000..3e5b81c5e --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json @@ -0,0 +1,16 @@ +{ + "language": "Yul", + "sources": { + "C": { + "urls": [ + "standard_yul_debug_info_ethdebug_compatible_output/in.yul" + ] + } + }, + "settings": { + "debug": {"debugInfo": ["ethdebug"]}, + "outputSelection": { + "*": {"*": ["ir", "irOptimized", "evm.bytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/output.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/output.json new file mode 100644 index 000000000..63d48b80b --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/output.json @@ -0,0 +1,48 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": { + "not yet implemented @ MachineAssemblyObject::ethdebug": true + } + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + /// @src 0:60:101 + mstore(64, 128) + fun_f_5() + /// @src 0:77:99 + function fun_f_5() + { sstore(0, 42) } + } +} +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + { + /// @src 0:60:101 + mstore(64, 128) + fun_f() + } + /// @src 0:77:99 + function fun_f() + { sstore(0, 42) } + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "C" + ] + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_irOptimized/args b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/args similarity index 100% rename from test/cmdlineTests/standard_yul_ethdebug_irOptimized/args rename to test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/args diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/in.yul b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/in.yul new file mode 100644 index 000000000..aa564d00c --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/in.yul @@ -0,0 +1,16 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json new file mode 100644 index 000000000..f05e6f361 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json @@ -0,0 +1,16 @@ +{ + "language": "Yul", + "sources": { + "C": { + "urls": [ + "standard_yul_debug_info_ethdebug_incompatible_output/in.yul" + ] + } + }, + "settings": { + "debug": {"debugInfo": ["ethdebug"]}, + "outputSelection": { + "*": {"*": ["evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/output.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/output.json new file mode 100644 index 000000000..963bcd8d7 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + "message": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize/args b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/args similarity index 100% rename from test/cmdlineTests/standard_yul_ethdebug_optimize/args rename to test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/args diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode/in.yul b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/in.yul similarity index 100% rename from test/cmdlineTests/standard_yul_ethdebug_bytecode/in.yul rename to test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/in.yul diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json similarity index 68% rename from test/cmdlineTests/standard_yul_ethdebug_bytecode/input.json rename to test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json index f3346fdd1..abfb7ee86 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_bytecode/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_debug_info_print_all/in.yul"]} + "C": {"urls": ["standard_yul_ethdebug_bytecode_ir/in.yul"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode/output.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/output.json similarity index 100% rename from test/cmdlineTests/standard_yul_ethdebug_bytecode/output.json rename to test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/output.json diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/args b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_irOptimized/in.yul b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/in.yul similarity index 100% rename from test/cmdlineTests/standard_yul_ethdebug_irOptimized/in.yul rename to test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/in.yul diff --git a/test/cmdlineTests/standard_yul_ethdebug_irOptimized/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json similarity index 66% rename from test/cmdlineTests/standard_yul_ethdebug_irOptimized/input.json rename to test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json index 89994857f..54094c673 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_irOptimized/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_debug_info_print_all/in.yul"]} + "C": {"urls": ["standard_yul_ethdebug_bytecode_iroptimized/in.yul"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json new file mode 100644 index 000000000..d7e3e6be3 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json @@ -0,0 +1,35 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": { + "not yet implemented @ MachineAssemblyObject::ethdebug": true + } + } + }, + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + { + /// @src 0:60:101 + mstore(64, 128) + fun_f() + } + /// @src 0:77:99 + function fun_f() + { sstore(0, 42) } + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "C" + ] + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json index e132c654f..e222dfeda 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_debug_info_print_all/in.yul"]} + "C": {"urls": ["standard_yul_ethdebug_deployed_bytecode/in.yul"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/args b/test/cmdlineTests/standard_yul_ethdebug_ir/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_ir/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize/in.yul b/test/cmdlineTests/standard_yul_ethdebug_ir/in.yul similarity index 100% rename from test/cmdlineTests/standard_yul_ethdebug_optimize/in.yul rename to test/cmdlineTests/standard_yul_ethdebug_ir/in.yul diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_ir/input.json new file mode 100644 index 000000000..3153a378d --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_ir/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_ir/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "ir"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/output.json b/test/cmdlineTests/standard_yul_ethdebug_ir/output.json new file mode 100644 index 000000000..c9ab1d8f5 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_ir/output.json @@ -0,0 +1,33 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": { + "not yet implemented @ MachineAssemblyObject::ethdebug": true + } + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + /// @src 0:60:101 + mstore(64, 128) + fun_f_5() + /// @src 0:77:99 + function fun_f_5() + { sstore(0, 42) } + } +} +" + } + } + }, + "ethdebug": { + "sources": [ + "C" + ] + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/args b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/in.yul b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/in.yul new file mode 100644 index 000000000..920aef8e9 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json new file mode 100644 index 000000000..180abcf31 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_iroptimize/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "irOptimize"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json new file mode 100644 index 000000000..47d0008f1 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json @@ -0,0 +1,20 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": { + "not yet implemented @ MachineAssemblyObject::ethdebug": true + } + } + } + } + } + }, + "ethdebug": { + "sources": [ + "C" + ] + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize/output.json b/test/cmdlineTests/standard_yul_ethdebug_optimize/output.json deleted file mode 100644 index 3ed2f577c..000000000 --- a/test/cmdlineTests/standard_yul_ethdebug_optimize/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "Optimization is not yet supported with ethdebug.", - "message": "Optimization is not yet supported with ethdebug.", - "severity": "error", - "type": "FatalError" - } - ] -} diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/args b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/in.yul b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/in.yul new file mode 100644 index 000000000..920aef8e9 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize/input.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json similarity index 73% rename from test/cmdlineTests/standard_yul_ethdebug_optimize/input.json rename to test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json index fb232f23a..9f0c8b0d5 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_optimize/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_debug_info_print_all/in.yul"]} + "C": {"urls": ["standard_yul_ethdebug_optimize_ir/in.yul"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/output.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/output.json new file mode 100644 index 000000000..44867c7a7 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/args b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/in.yul b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/in.yul new file mode 100644 index 000000000..920aef8e9 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json new file mode 100644 index 000000000..81b637abd --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json @@ -0,0 +1,14 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_optimize_iroptimized/in.yul"]} + }, + "settings": { + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "irOptimized"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/output.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/output.json new file mode 100644 index 000000000..44867c7a7 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Optimization is not yet supported with ethdebug.", + "message": "Optimization is not yet supported with ethdebug.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/cmdlineTests/yul_ethdebug/args b/test/cmdlineTests/yul_ethdebug/args index 715f3fb48..a800f5c34 100644 --- a/test/cmdlineTests/yul_ethdebug/args +++ b/test/cmdlineTests/yul_ethdebug/args @@ -1 +1 @@ ---ethdebug --strict-assembly --optimize --ir-optimized \ No newline at end of file +--ethdebug --strict-assembly \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug/output b/test/cmdlineTests/yul_ethdebug/output index 702fe057d..84ba9317b 100644 --- a/test/cmdlineTests/yul_ethdebug/output +++ b/test/cmdlineTests/yul_ethdebug/output @@ -3,16 +3,5 @@ ======= yul_ethdebug/input.yul (EVM) ======= -Pretty printed source: -/// ethdebug: enabled -object "object" { - code { - { - sstore(calldataload(0), calldataload(0x20)) - } - } -} - - Debug Data (ethdebug/format/program): {"not yet implemented @ MachineAssemblyObject::ethdebug":true} diff --git a/test/cmdlineTests/yul_ethdebug_ir/args b/test/cmdlineTests/yul_ethdebug_ir/args new file mode 100644 index 000000000..6194b51b6 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_ir/args @@ -0,0 +1 @@ +--ethdebug --strict-assembly --ir \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug_ir/err b/test/cmdlineTests/yul_ethdebug_ir/err new file mode 100644 index 000000000..645f7557a --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_ir/err @@ -0,0 +1 @@ +Error: The following outputs are not supported in assembler mode: --ir. diff --git a/test/cmdlineTests/yul_ethdebug_ir/exit b/test/cmdlineTests/yul_ethdebug_ir/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_ir/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/yul_ethdebug_ir/input.yul b/test/cmdlineTests/yul_ethdebug_ir/input.yul new file mode 100644 index 000000000..acd0b45f5 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_ir/input.yul @@ -0,0 +1,18 @@ +object "object" { + code { + let a + let b + { + function z() -> y + { y := calldataload(0) } + a := z() + } + { + function z() -> y + { y := calldataload(0x20) } + b := z() + } + sstore(a, b) + } +} + diff --git a/test/cmdlineTests/yul_ethdebug_iroptimized/args b/test/cmdlineTests/yul_ethdebug_iroptimized/args new file mode 100644 index 000000000..2063d860c --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_iroptimized/args @@ -0,0 +1 @@ +--ethdebug --strict-assembly --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug_iroptimized/input.yul b/test/cmdlineTests/yul_ethdebug_iroptimized/input.yul new file mode 100644 index 000000000..acd0b45f5 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_iroptimized/input.yul @@ -0,0 +1,18 @@ +object "object" { + code { + let a + let b + { + function z() -> y + { y := calldataload(0) } + a := z() + } + { + function z() -> y + { y := calldataload(0x20) } + b := z() + } + sstore(a, b) + } +} + diff --git a/test/cmdlineTests/yul_ethdebug_iroptimized/output b/test/cmdlineTests/yul_ethdebug_iroptimized/output new file mode 100644 index 000000000..e2f0ed7f9 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_iroptimized/output @@ -0,0 +1,26 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{"sources":["yul_ethdebug_iroptimized/input.yul"]} + +======= yul_ethdebug_iroptimized/input.yul (EVM) ======= + +Pretty printed source: +/// ethdebug: enabled +object "object" { + code { + { + let a + let b + a := z() + b := z_1() + sstore(a, b) + } + function z() -> y + { y := calldataload(0) } + function z_1() -> y + { y := calldataload(0x20) } + } +} + + +Debug Data (ethdebug/format/program): +{"not yet implemented @ MachineAssemblyObject::ethdebug":true} diff --git a/test/cmdlineTests/yul_ethdebug_optimize/args b/test/cmdlineTests/yul_ethdebug_optimize/args new file mode 100644 index 000000000..fd081fdaf --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_optimize/args @@ -0,0 +1 @@ +--ethdebug --strict-assembly --optimize \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug_optimize/err b/test/cmdlineTests/yul_ethdebug_optimize/err new file mode 100644 index 000000000..7d6613875 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_optimize/err @@ -0,0 +1 @@ +Error: Optimization (using --optimize) is not yet supported with ethdebug. diff --git a/test/cmdlineTests/yul_ethdebug_optimize/exit b/test/cmdlineTests/yul_ethdebug_optimize/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_optimize/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/yul_ethdebug_optimize/input.yul b/test/cmdlineTests/yul_ethdebug_optimize/input.yul new file mode 100644 index 000000000..acd0b45f5 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_optimize/input.yul @@ -0,0 +1,18 @@ +object "object" { + code { + let a + let b + { + function z() -> y + { y := calldataload(0) } + a := z() + } + { + function z() -> y + { y := calldataload(0x20) } + b := z() + } + sstore(a, b) + } +} + diff --git a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/args b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/args new file mode 100644 index 000000000..715f3fb48 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/args @@ -0,0 +1 @@ +--ethdebug --strict-assembly --optimize --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/err b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/err new file mode 100644 index 000000000..7d6613875 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/err @@ -0,0 +1 @@ +Error: Optimization (using --optimize) is not yet supported with ethdebug. diff --git a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/exit b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/input.yul b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/input.yul new file mode 100644 index 000000000..acd0b45f5 --- /dev/null +++ b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/input.yul @@ -0,0 +1,18 @@ +object "object" { + code { + let a + let b + { + function z() -> y + { y := calldataload(0) } + a := z() + } + { + function z() -> y + { y := calldataload(0x20) } + b := z() + } + sstore(a, b) + } +} + diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 3161eba2a..ec3c7db1c 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -1940,99 +1940,85 @@ BOOST_AUTO_TEST_CASE(ethdebug_excluded_from_wildcards) BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) { - static std::vector>>> tests{ + static std::vector>>> tests{ { generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"*"})), - "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", std::nullopt, }, { generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"})), - "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", std::nullopt, }, { generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), - "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", std::nullopt, }, { generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), - "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", std::nullopt, }, { generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), - "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", std::nullopt, }, { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"ir"})), - {}, + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"irOptimized"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"ir"})), - {}, + generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"irOptimized"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"ir", "evm.bytecode.ethdebug"})), - {}, + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"ir", "evm.deployedBytecode.ethdebug"})), - {}, + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"ir", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), - {}, + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"ir", "evm.bytecode.ethdebug"})), - {}, + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"ir", "evm.deployedBytecode.ethdebug"})), - {}, + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"ir", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), - {}, + generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"ir"}), YulCode()), - {}, + generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"irOptimized"}), YulCode()), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; @@ -2040,13 +2026,10 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) }, { generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"irOptimized"}), YulCode()), - "Optimization is not yet supported with ethdebug.", {} }, { - generateStandardJson(true, Json::array({"ethdebugs"}), Json::array({"ir"}), YulCode()), - "Invalid value in settings.debug.debugInfo.", - {} + generateStandardJson(true, Json::array({"ethdebugs"}), Json::array({"irOptimized"}), YulCode()), {} }, { generateStandardJson( @@ -2059,17 +2042,14 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) {"fileB", "pragma solidity >=0.0; contract contractB { function f() public pure {} }"} }), true ), - "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", std::nullopt, }, { generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"}), EvmAssemblyCode()), - "'settings.debug.debugInfo' 'ethdebug' is only supported for languages 'Solidity' and 'Yul'.", std::nullopt, }, { generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"}), SolidityAstCode()), - "'settings.debug.debugInfo' 'ethdebug' is only supported for languages 'Solidity' and 'Yul'.", std::nullopt, }, }; @@ -2077,66 +2057,52 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) for (auto const& test: tests) { Json result = compiler.compile(std::get<0>(test)); - BOOST_REQUIRE(!std::get<1>(test).empty() ? result.contains("errors") : result.contains("contracts")); - if (!std::get<1>(test).empty()) - for (auto const& e: result["errors"]) - BOOST_REQUIRE(e["message"] == std::get<1>(test)); - if (std::get<2>(test).has_value()) - BOOST_REQUIRE((*std::get<2>(test))(result)); + if (std::get<1>(test).has_value()) + BOOST_REQUIRE((*std::get<1>(test))(result)); } } BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) { - static std::vector>>> tests{ + static std::vector>>> tests{ { generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), - "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", std::nullopt }, { generateStandardJson(false, {}, Json::array({"evm.bytecode.ethdebug"})), - "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", std::nullopt }, { generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), - "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", std::nullopt }, { generateStandardJson(false, {}, Json::array({"evm.deployedBytecode.ethdebug"})), - "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", std::nullopt }, { generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), - "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", std::nullopt }, { generateStandardJson(false, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), - "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set.", std::nullopt }, { generateStandardJson(true, Json::array({"location"}), Json::array({"evm.bytecode.ethdebug"})), - "'ethdebug' needs to be enabled in 'settings.debug.debugInfo', if 'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' was selected as output.", std::nullopt }, { generateStandardJson(true, Json::array({"location"}), Json::array({"evm.deployedBytecode.ethdebug"})), - "'ethdebug' needs to be enabled in 'settings.debug.debugInfo', if 'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' was selected as output.", std::nullopt }, { generateStandardJson(true, Json::array({"location"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), - "'ethdebug' needs to be enabled in 'settings.debug.debugInfo', if 'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' was selected as output.", std::nullopt }, { generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), - {}, [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); @@ -2144,7 +2110,6 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) }, { generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), - {}, [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); @@ -2152,7 +2117,6 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) }, { generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), - {}, [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && @@ -2161,7 +2125,6 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) }, { generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug"})), - {}, [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); @@ -2169,7 +2132,6 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) }, { generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug"})), - {}, [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); @@ -2177,7 +2139,6 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) }, { generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), - {}, [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && @@ -2186,7 +2147,6 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) }, { generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "ir"})), - {}, [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); @@ -2194,7 +2154,6 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) }, { generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug", "ir"})), - {}, [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); @@ -2202,23 +2161,14 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) }, { generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebugs"})), - {}, - [](const Json& result) - { - return !result.contains("ethdebug"); - } + std::nullopt }, { generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebugs"})), - {}, - [](const Json& result) - { - return !result.contains("ethdebug"); - } + std::nullopt }, { generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"})), - {}, [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && @@ -2227,7 +2177,6 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) }, { generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "ir"}), YulCode()), - {}, [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos && result["contracts"]["fileA"]["object"]["evm"]["bytecode"].contains("ethdebug"); @@ -2235,17 +2184,14 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) }, { generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug", "ir"}), YulCode()), - {"\"evm.deployedBytecode.ethdebug\" cannot be used for Yul."}, std::nullopt }, { generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"}), YulCode()), - {"\"evm.deployedBytecode.ethdebug\" cannot be used for Yul."}, std::nullopt }, { generateStandardJson(true, {}, Json::array({"evm.bytecode"})), - {}, [](const Json& result) { return result.dump().find("ethdebug") == std::string::npos; @@ -2253,7 +2199,6 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) }, { generateStandardJson(true, {}, Json::array({"evm.deployedBytecode"})), - {}, [](const Json& result) { return result.dump().find("ethdebug") == std::string::npos; @@ -2270,7 +2215,6 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) {"fileB", "pragma solidity >=0.0; contract contractB { function f() public pure {} }"} }), true ), - {}, [](const Json& result) { return result["contracts"]["fileA"]["contractA"]["evm"]["deployedBytecode"].contains("ethdebug") && @@ -2279,14 +2223,12 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) } }; frontend::StandardCompiler compiler; - for (auto const& test: tests) + for (auto const& [standardJsonToCompile, optionalCheck]: tests) { - Json result = compiler.compile(std::get<0>(test)); - if (!std::get<1>(test).empty()) - for (auto const& e: result["errors"]) - BOOST_REQUIRE(e["message"] == std::get<1>(test)); - if (std::get<2>(test).has_value()) - BOOST_REQUIRE((*std::get<2>(test))(result)); + Json result = compiler.compile(standardJsonToCompile); + BOOST_REQUIRE(!optionalCheck.has_value() ? result.contains("errors") : result.contains("contracts")); + if (optionalCheck.has_value()) + BOOST_REQUIRE((*optionalCheck)(result)); } } diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 17166268a..adfd24b02 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -1424,97 +1424,72 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_outputs) { TemporaryDirectory tempDir(TEST_CASE_NAME); createFilesWithParentDirs({tempDir.path() / "input.sol"}); - static std::vector, std::string>> tests{ + static std::vector> tests{ { {"solc", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n" }, { {"solc", "--via-ir", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--via-ir", "--ethdebug", "--optimize", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" - }, - { - {"solc", "--via-ir", "--ethdebug", "--ir-optimized", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--via-ir", "--ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--via-ir", "--ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, - "Error: Option --ethdebug is not supported with --import-asm-json.\n" }, { {"solc", "--via-ir", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n" }, { {"solc", "--via-ir", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--via-ir", "--ethdebug-runtime", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--via-ir", "--ethdebug-runtime", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--ethdebug-runtime", "--import-asm-json", tempDir.path().string() + "/input.json"}, - "Error: Option --ethdebug-runtime is not supported with --import-asm-json.\n" }, { {"solc", "--via-ir", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - "Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--debug-info", "ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--debug-info", "ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, - "Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" }, { {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, - "Error: Option --debug-info is not supported with --import-asm-json.\n" }, { {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, - "Error: Option --debug-info is not supported with --import-asm-json.\n" }, { {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.json"}, - "Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n" } }; for (auto const& test: tests) { - OptionsReaderAndMessages result = runCLI(test.first, ""); + OptionsReaderAndMessages result = runCLI(test, ""); BOOST_REQUIRE(!result.success); - BOOST_CHECK_EQUAL(result.stderrContent, test.second); } } @@ -1522,41 +1497,33 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_input_modes) { TemporaryDirectory tempDir(TEST_CASE_NAME); createFilesWithParentDirs({tempDir.path() / "input.json"}); - static std::vector, std::string>> tests{ + static std::vector> tests{ { {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, - "Error: Option --ethdebug is not supported with --import-asm-json.\n" }, { {"solc", "--ethdebug", "--via-ir", "--import-asm-json", tempDir.path().string() + "/input.json"}, - "Error: The following options are not supported in the current input mode: --via-ir\n" }, { {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, - "Error: Option --ethdebug is not supported with --import-asm-json.\n" }, { {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, - "Error: Option --debug-info is not supported with --import-asm-json.\n" }, { {"solc", "--ethdebug", "--import-ast", tempDir.path().string() + "/input.json"}, - "Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n" }, { {"solc", "--ethdebug", "--via-ir", "--import-ast", tempDir.path().string() + "/input.json"}, - "Error: Invalid input mode for --debug-info ethdebug / --ethdebug / --ethdebug-runtime.\n" }, { {"solc", "--debug-info", "ethdebug", "--ir", "--import-ast", tempDir.path().string() + "/input.json"}, - "Error: Invalid input mode for --debug-info ethdebug / --ethdebug / --ethdebug-runtime.\n" } }; for (auto const& test: tests) { - OptionsReaderAndMessages result = runCLI(test.first, ""); + OptionsReaderAndMessages result = runCLI(test, ""); BOOST_REQUIRE(!result.success); - BOOST_CHECK_EQUAL(result.stderrContent, test.second); } } @@ -1565,121 +1532,98 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_debug_info_ethdebug) TemporaryDirectory tempDir(TEST_CASE_NAME); createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); createFilesWithParentDirs({tempDir.path() / "input.yul"}, "{}"); - static std::vector, std::vector, std::vector>> tests{ + static std::vector> erroneousCLIFlagCombinations{ { {"solc", "--debug-info", "ethdebug", tempDir.path().string() + "/input.sol"}, - {"Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, - {}, - }, - { - {"solc", "--debug-info", "ethdebug", "--ir", tempDir.path().string() + "/input.sol"}, - {}, - {"/// ethdebug: enabled"}, }, { {"solc", "--debug-info", "ethdebug", "--ir-optimized", tempDir.path().string() + "/input.sol"}, - {"Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, - {}, }, { {"solc", "--debug-info", "ethdebug", "--optimize", tempDir.path().string() + "/input.sol"}, - {"Error: --debug-info ethdebug can only be used with --ir and/or --ethdebug / --ethdebug-runtime. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, - {}, }, { {"solc", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, - {}, - }, - { - {"solc", "--debug-info", "ethdebug", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, - {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program):"}, - }, - { - {"solc", "--debug-info", "ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, - {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data of the runtime part (ethdebug/format/program):"}, - }, - { - {"solc", "--debug-info", "ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, - {}, - {"/// ethdebug: enabled", "Pretty printed source", "Binary representation", "Text representation"}, - }, - { - {"solc", "--ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, - {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program):"}, }, { {"solc", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, - {"Error: The following outputs are not supported in assembler mode: --ethdebug-runtime.\n"}, - {}, }, { {"solc", "--ethdebug", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, - {"Error: The following outputs are not supported in assembler mode: --ethdebug-runtime.\n"}, - {}, }, { {"solc", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, - {}, }, { {"solc", "--debug-info", "ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, - {}, }, { {"solc", "--debug-info", "ethdebug", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, - {}, - }, - { - {"solc", "--debug-info", "ethdebug", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, - {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program):", "Debug Data of the runtime part (ethdebug/format/program):"}, }, { {"solc", "--debug-info", "location", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, - {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, - {}, }, { {"solc", "--debug-info", "location", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, - {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, - {}, }, { {"solc", "--debug-info", "location", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, - {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, - {}, }, { {"solc", "--debug-info", "all", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, - {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, - {}, }, { {"solc", "--debug-info", "all", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, - {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, - {}, }, { {"solc", "--debug-info", "all", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, - {"Error: --debug-info must contain ethdebug, when compiling with --ethdebug / --ethdebug-runtime.\n"}, - {}, }, }; - for (auto const& test: tests) + static std::vector> supportedCLIFlagCombinations{ + { + {"solc", "--debug-info", "ethdebug", "--ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--debug-info", "ethdebug", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + { + "solc", + "--debug-info", + "ethdebug", + "--ethdebug-runtime", + "--via-ir", + tempDir.path().string() + "/input.sol" + }, + }, + { + {"solc", "--debug-info", "ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + }, + { + {"solc", "--ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + }, + { + { + "solc", + "--debug-info", + "ethdebug", + "--ethdebug", + "--ethdebug-runtime", + "--via-ir", + tempDir.path().string() + "/input.sol" + }, + }, + }; + + for (auto const& test: erroneousCLIFlagCombinations) { - OptionsReaderAndMessages result{runCLI(std::get<0>(test), "")}; - BOOST_REQUIRE(!std::get<1>(test).empty() ? !result.success : result.success); - for (auto const& error : std::get<1>(test)) - BOOST_REQUIRE(result.stderrContent == error); - for (auto const& output : std::get<2>(test)) - BOOST_REQUIRE(result.stdoutContent.find(output) != std::string::npos); + OptionsReaderAndMessages result{runCLI(test, "")}; + BOOST_REQUIRE(!result.success); + } + for (auto const& test: supportedCLIFlagCombinations) + { + OptionsReaderAndMessages result{runCLI(test, "")}; + BOOST_REQUIRE(result.success); } } @@ -1687,91 +1631,69 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_ethdebug_output) { TemporaryDirectory tempDir(TEST_CASE_NAME); createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); - static std::vector, std::vector, std::vector>> tests{ + static std::vector> erroneousCLIFlagCombinations{ + { + {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + }, + { + { + "solc", + "--ethdebug-runtime", + "--via-ir", + "--ir-optimized", + "--optimize", + tempDir.path().string() + "/input.sol" + }, + }, + { + {"solc", "--ethdebug", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + }, { {"solc", "--ethdebug", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, - {}, }, { {"solc", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, - {}, }, { {"solc", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified.\n"}, - {}, }, + }; + static std::vector> supportedCLIFlagCombinations{ { {"solc", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, - {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)"}, }, { {"solc", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, - {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data of the runtime part (ethdebug/format/program)"}, }, { {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, - {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "Debug Data of the runtime part (ethdebug/format/program)"}, }, { {"solc", "--ethdebug", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, - {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "/// ethdebug: enabled"}, }, { {"solc", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, - {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, }, { {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, - {}, - {"======= Debug Data (ethdebug/format/info/resources) =======", "Debug Data (ethdebug/format/program)", "Debug Data of the runtime part (ethdebug/format/program)", "/// ethdebug: enabled"}, }, { {"solc", "--ethdebug", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, - {}, }, { {"solc", "--ethdebug-runtime", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, - {}, - }, - { - {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, - {}, - }, - { - {"solc", "--ethdebug", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, - {}, - }, - { - {"solc", "--ethdebug-runtime", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, - {}, - }, - { - {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, - {"Error: --ethdebug / --ethdebug-runtime output can only be used with --ir. Optimization is not yet supported with ethdebug, e.g. no support for --optimize / --ir-optimized yet.\n"}, - {}, }, }; - for (auto const& test: tests) + + for (auto const& test: erroneousCLIFlagCombinations) { - OptionsReaderAndMessages result{runCLI(std::get<0>(test), "")}; - BOOST_REQUIRE(!std::get<1>(test).empty() ? !result.success : result.success); - for (auto const& error : std::get<1>(test)) - BOOST_REQUIRE(result.stderrContent == error); - for (auto const& output : std::get<2>(test)) - BOOST_REQUIRE(result.stdoutContent.find(output) != std::string::npos); + OptionsReaderAndMessages result{runCLI(test, "")}; + BOOST_REQUIRE(!result.success); + } + for (auto const& test: supportedCLIFlagCombinations) + { + OptionsReaderAndMessages result{runCLI(test, "")}; + BOOST_REQUIRE(result.success); } } From 4d96648017c89145a8ff56f4860c7db2d1315440 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 4 Feb 2025 11:00:26 +0100 Subject: [PATCH 0737/1340] Yul: Introduces ASTNodeRegistry --- libyul/ASTLabelRegistry.cpp | 166 ++++++++++++++++++++++++++++++++++++ libyul/ASTLabelRegistry.h | 110 ++++++++++++++++++++++++ libyul/CMakeLists.txt | 2 + 3 files changed, 278 insertions(+) create mode 100644 libyul/ASTLabelRegistry.cpp create mode 100644 libyul/ASTLabelRegistry.h diff --git a/libyul/ASTLabelRegistry.cpp b/libyul/ASTLabelRegistry.cpp new file mode 100644 index 000000000..8f26f2f5b --- /dev/null +++ b/libyul/ASTLabelRegistry.cpp @@ -0,0 +1,166 @@ +/* + 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 + +#include + +#include + +#include + +using namespace solidity::yul; + +ASTLabelRegistry::ASTLabelRegistry(): m_labels{""}, m_idToLabelMapping{0} {} + +ASTLabelRegistry::ASTLabelRegistry(std::vector _labels, std::vector _idToLabelMapping): + m_labels(std::move(_labels)), + m_idToLabelMapping(std::move(_idToLabelMapping)) +{ + yulAssert(!m_labels.empty()); + yulAssert(m_labels[0].empty()); + yulAssert(!m_idToLabelMapping.empty()); + yulAssert(m_idToLabelMapping[0] == 0); + // using vector over vector, as the latter is optimized for space-efficiency + std::vector labelVisited (m_labels.size(), false); + size_t numLabels = 0; + for (auto const& labelIndex: m_idToLabelMapping) + { + if (labelIndex == ghostLabelIndex()) + continue; + yulAssert(labelIndex < m_labels.size()); + // it is possible to have multiple references to the empty label index + // only the id == 0 refers to an actually empty label, otherwise the LabelID is unused + yulAssert( + labelIndex == 0 || !labelVisited[labelIndex], + fmt::format("LabelID {} (label \"{}\") is not unique.", labelIndex, m_labels[labelIndex]) + ); + labelVisited[labelIndex] = true; + if (labelIndex >= 1) + ++numLabels; + } + yulAssert(numLabels + 1 == m_labels.size(), "Unreferenced labels present."); +} + +ASTLabelRegistry::LabelID ASTLabelRegistry::maxID() const +{ + yulAssert(!m_idToLabelMapping.empty()); + return m_idToLabelMapping.size() - 1; +} + +size_t ASTLabelRegistry::idToLabelIndex(LabelID const _id) const +{ + yulAssert(_id < m_idToLabelMapping.size()); + return m_idToLabelMapping[_id]; +} + +std::string_view ASTLabelRegistry::operator[](LabelID const _id) const +{ + auto const labelIndex = idToLabelIndex(_id); + yulAssert(labelIndex != ghostLabelIndex(), "Ghost ids are not explicitly labelled in the registry."); + // not using `unused` here, as we already have evaluated the label index + // an id is unused if it is not id == 0 (empty label) but points at label index 0 + yulAssert(empty(_id) || labelIndex != 0, "Can only query ids that are not unused"); + return m_labels[labelIndex]; +} + +bool ASTLabelRegistry::ghost(LabelID const _id) const +{ + return idToLabelIndex(_id) == ghostLabelIndex(); +} + +bool ASTLabelRegistry::unused(LabelID const _id) const +{ + return !empty(_id) && idToLabelIndex(_id) == 0; +} + +std::optional ASTLabelRegistry::findIDForLabel(std::string_view const _label) const +{ + for (LabelID id = 0; id <= maxID(); ++id) + if ((*this)[id] == _label) + return id; + return std::nullopt; +} + +std::tuple ASTLabelRegistryBuilder::DefinedLabels::tryInsert( + std::string_view const _label, + ASTLabelRegistry::LabelID const _id +) +{ + auto const [it, emplaced] = m_labelToIDMapping.try_emplace(std::string{_label}, _id); + return std::make_tuple(it->second, emplaced); +} + +ASTLabelRegistryBuilder::ASTLabelRegistryBuilder(): + m_nextID(1) +{} + +ASTLabelRegistryBuilder::ASTLabelRegistryBuilder(ASTLabelRegistry const& _existingRegistry) +{ + yulAssert(!_existingRegistry.labels().empty() && _existingRegistry[0].empty()); + for (size_t id = 1; id <= _existingRegistry.maxID(); ++id) + { + if (!ASTLabelRegistry::empty(id) && !_existingRegistry.unused(id)) + { + // ghost ids are not added to the map as they are not explicitly labeled + if (_existingRegistry.ghost(id)) + m_ghosts.push_back(id); + else + { + auto const [_, inserted] = m_definedLabels.tryInsert(_existingRegistry[id], id); + yulAssert(inserted, "Existing registry cannot contain duplicate labels."); + } + } + } + m_nextID = _existingRegistry.maxID() + 1; +} + +ASTLabelRegistry::LabelID ASTLabelRegistryBuilder::define(std::string_view const _label) +{ + auto const [id, inserted] = m_definedLabels.tryInsert(_label, m_nextID); + if (inserted) + m_nextID++; + return id; +} + +ASTLabelRegistry::LabelID ASTLabelRegistryBuilder::addGhost() +{ + m_ghosts.push_back(m_nextID); + return m_nextID++; +} + +ASTLabelRegistry ASTLabelRegistryBuilder::build() const +{ + auto const& labelToIDMapping = m_definedLabels.labelToIDMapping(); + yulAssert(labelToIDMapping.contains("")); + yulAssert(labelToIDMapping.at("") == 0); + + std::vector labels{""}; + labels.reserve(labelToIDMapping.size()); + std::vector idToLabelMapping( m_nextID + 1, 0); + yulAssert(!idToLabelMapping.empty(), "Mapping must at least contain empty label"); + for (auto const& [label, id]: labelToIDMapping) + { + if (ASTLabelRegistry::empty(id)) + continue; + + labels.emplace_back(label); + idToLabelMapping[id] = labels.size() - 1; + } + for (auto const ghostId: m_ghosts) + idToLabelMapping[ghostId] = ASTLabelRegistry::ghostLabelIndex(); + return ASTLabelRegistry{std::move(labels), std::move(idToLabelMapping)}; +} diff --git a/libyul/ASTLabelRegistry.h b/libyul/ASTLabelRegistry.h new file mode 100644 index 000000000..cb7c405af --- /dev/null +++ b/libyul/ASTLabelRegistry.h @@ -0,0 +1,110 @@ +/* + 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 + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace solidity::yul +{ + +/// Instances of the `ASTLabelRegistry` are immutable containers describing a labelling of nodes inside the AST. +/// Each element of the AST that possesses a label has a `ASTLabelRegistry::LabelID`, with which the label can +/// be queried in O(1). +/// Preferred way of creating instances is via `ASTLabelRegistryBuilder` when parsing/importing and +/// via `LabelIDDispenser` during/after optimization. +/// Note: The id == 0 always corresponds to the empty label. Other ids can point at the label index 0, which means that +/// they are unused. To check, whether an id is unused, the `unused` function can be used. +/// Note: There is a special case of ghost ids, which are added during CFG construction. +/// They do not directly correspond to elements of an AST but live inside the CFG. They are assigned the +/// special `std::numeric_limits::max` label index. The labels themselves are - if required - generated from +/// the CFG. +class ASTLabelRegistry +{ +public: + /// unsafe to use from a different registry instance, it is up to the user to safeguard against this + using LabelID = size_t; + + ASTLabelRegistry(); + ASTLabelRegistry(std::vector _labels, std::vector _idToLabelMapping); + + std::string_view operator[](LabelID _id) const; + + static bool constexpr empty(LabelID const _id) { return _id == emptyID(); } + static LabelID constexpr emptyID() { return 0; } + static size_t constexpr ghostLabelIndex() { return std::numeric_limits::max(); } + + bool unused(LabelID _id) const; + bool ghost(LabelID _id) const; + std::vector const& labels() const { return m_labels; } + LabelID maxID() const; + + size_t idToLabelIndex(LabelID _id) const; + /// this is a potentially expensive operation + std::optional findIDForLabel(std::string_view _label) const; + +private: + /// All Yul AST labels present in the registry. + /// Always contains at least an empty label which also serves as a null-state for non-contiguous ID ranges. + /// All items must be unique. + std::vector const m_labels; + + /// Assignment of labels to `LabelID`s. Indices are `LabelID`s and values are indices into `m_labels`. + /// Every label except empty always has exactly one `LabelID` pointing at it. + /// The empty label has one canonical ID, but unused IDs point to it as well. + std::vector const m_idToLabelMapping; +}; + +/// Produces instances of `ASTLabelRegistry`. Preferably used during parsing/importing. +class ASTLabelRegistryBuilder +{ +public: + ASTLabelRegistryBuilder(); + /// Creates a new builder taking an already existing label registry into account. + /// Unused IDs are skipped, ghost IDs are recorded and inserted back into the newly built registry. + explicit ASTLabelRegistryBuilder(ASTLabelRegistry const& _existingRegistry); + + ASTLabelRegistry::LabelID define(std::string_view _label); + ASTLabelRegistry::LabelID addGhost(); + + /// Creates a new label registry based on what was defined and potentially an existing registry. If such registry + /// was provided, all labels (including unused and ghost label IDs) carry over. + ASTLabelRegistry build() const; + +private: + class DefinedLabels + { + public: + std::tuple tryInsert(std::string_view _label, ASTLabelRegistry::LabelID _id); + auto const& labelToIDMapping() const { return m_labelToIDMapping; } + + private: + std::map> m_labelToIDMapping = {{"", 0}}; + }; + + DefinedLabels m_definedLabels; + std::vector m_ghosts; + size_t m_nextID{}; +}; + +} diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index cc4c5051c..fc3302a82 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -7,6 +7,8 @@ add_library(yul AST.h AST.cpp ASTForward.h + ASTLabelRegistry.cpp + ASTLabelRegistry.h AsmJsonConverter.h AsmJsonConverter.cpp AsmJsonImporter.h From 9c0098b221556e4df56c892d7280bfb5b7e10c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 4 Dec 2024 07:26:26 +0100 Subject: [PATCH 0738/1340] Always include a message when throwing a FatalError - It's not shown to the user but it's still useful because we can include it in the assert that gets triggered when a fatal error gets thrown but not reported. --- liblangutil/ErrorReporter.cpp | 9 ++++++--- libsolidity/analysis/TypeChecker.cpp | 4 ++-- libsolidity/parsing/Parser.cpp | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/liblangutil/ErrorReporter.cpp b/liblangutil/ErrorReporter.cpp index 10d7f1d11..9f3e293f5 100644 --- a/liblangutil/ErrorReporter.cpp +++ b/liblangutil/ErrorReporter.cpp @@ -23,6 +23,9 @@ #include #include + +#include + #include #include @@ -121,7 +124,7 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type) if (m_errorCount > c_maxErrorsAllowed) { m_errorList.push_back(std::make_shared(4013_error, Error::Type::Warning, "There are more than 256 errors. Aborting.")); - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, "There are more than 256 errors. Aborting."); } } @@ -131,13 +134,13 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type) void ErrorReporter::fatalError(ErrorId _error, Error::Type _type, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description) { error(_error, _type, _location, _secondaryLocation, _description); - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, _description); } void ErrorReporter::fatalError(ErrorId _error, Error::Type _type, SourceLocation const& _location, std::string const& _description) { error(_error, _type, _location, _description); - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, _description); } ErrorList const& ErrorReporter::errors() const diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index a0d21744d..e56ee157d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1327,7 +1327,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) solAssert(m_errorReporter.hasErrors(), "Should have errors!"); for (auto const& var: variables) if (var && !var->annotation().type) - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, "Type checker failed to determine types of all variables within the declaration."); } return false; @@ -1380,7 +1380,7 @@ bool TypeChecker::visit(Conditional const& _conditional) commonType = falseType; if (!trueType && !falseType) - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, "Both sides of the ternary expression have invalid types."); else if (trueType && falseType) { commonType = Type::commonType(trueType, falseType); diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index dce729de4..720ff2afe 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1539,7 +1539,7 @@ ASTPointer Parser::parseInlineAssembly(ASTPointer con yul::Parser asmParser(m_errorReporter, dialect); std::shared_ptr ast = asmParser.parseInline(m_scanner); if (ast == nullptr) - BOOST_THROW_EXCEPTION(FatalError()); + solThrow(FatalError, "Failed to parse inline assembly."); location.end = nativeLocationOf(ast->root()).end; return std::make_shared(nextID(), location, _docString, dialect, std::move(flags), ast); From 04605d752889125f6c3d064ecd781fe733abf830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 31 Jan 2025 20:12:06 +0100 Subject: [PATCH 0739/1340] Report more info when an unreported fatal error is caught --- libsolidity/analysis/NameAndTypeResolver.cpp | 27 +++++++++++++++----- libsolidity/interface/CompilerStack.cpp | 18 ++++++++++--- libsolidity/parsing/Parser.cpp | 9 +++++-- libyul/AsmAnalysis.cpp | 9 +++++-- libyul/AsmParser.cpp | 9 +++++-- libyul/ObjectParser.cpp | 9 +++++-- 6 files changed, 63 insertions(+), 18 deletions(-) diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 2fb6a6162..2d55b46fc 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -61,9 +61,14 @@ bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit, ASTNode { DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errorReporter, m_globalContext, _currentScope); } - catch (langutil::FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } return false; } return true; @@ -135,9 +140,14 @@ bool NameAndTypeResolver::resolveNamesAndTypes(SourceUnit& _source) return false; } } - catch (langutil::FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } return false; } return true; @@ -150,9 +160,14 @@ bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) m_scopes[nullptr]->registerDeclaration(_declaration, false, true); solAssert(_declaration.scope() == nullptr, "Updated declaration outside global scope."); } - catch (langutil::FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } return false; } return true; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 4e9346ecf..2748c09cd 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -507,9 +507,14 @@ bool CompilerStack::analyze() else if (!analyzeLegacy(noErrors)) noErrors = false; } - catch (FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } noErrors = false; } catch (UnimplementedFeatureError const& _error) @@ -1317,9 +1322,14 @@ StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast) } } } - catch (FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } } return newSources; } diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 720ff2afe..08a319b5b 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -176,9 +176,14 @@ ASTPointer Parser::parse(CharStream& _charStream) solAssert(m_recursionDepth == 0, ""); return nodeFactory.createNode(findLicenseString(nodes), nodes, m_experimentalSolidityEnabledInCurrentSourceUnit); } - catch (FatalError const& error) + catch (FatalError const&) { - solAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + solAssert(false, "Unreported fatal error."); + } return nullptr; } } diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 352f16f76..aa3e23e26 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -75,13 +75,18 @@ bool AsmAnalyzer::analyze(Block const& _block) (*this)(_block); } - catch (FatalError const& error) + catch (FatalError const&) { // NOTE: There's a cap on the number of reported errors, but watcher.ok() will work fine even if // we exceed it because the reporter keeps counting (it just stops adding errors to the list). // Note also that fact of exceeding the cap triggers a FatalError so one can get thrown even // if we don't make any of our errors fatal. - yulAssert(!watcher.ok(), "Unreported fatal error: "s + error.what()); + if (watcher.ok()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + yulAssert(false, "Unreported fatal error."); + } } return watcher.ok(); } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index c061a251a..a6949d7f8 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -127,9 +127,14 @@ std::unique_ptr Parser::parseInline(std::shared_ptr const& _scanne fetchDebugDataFromComment(); return std::make_unique(m_dialect, parseBlock()); } - catch (FatalError const& error) + catch (FatalError const&) { - yulAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + yulAssert(false, "Unreported fatal error."); + } } return nullptr; diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 954ade311..dfa604941 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -63,9 +63,14 @@ std::shared_ptr ObjectParser::parse(std::shared_ptr const& _sca expectToken(Token::EOS); return object; } - catch (FatalError const& error) + catch (FatalError const&) { - yulAssert(m_errorReporter.hasErrors(), "Unreported fatal error: "s + error.what()); + if (!m_errorReporter.hasErrors()) + { + std::cerr << "Unreported fatal error:" << std::endl; + std::cerr << boost::current_exception_diagnostic_information() << std::endl; + yulAssert(false, "Unreported fatal error."); + } } return nullptr; } From d7073bada9705a998b9d48874d9c01fbfd165f26 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 27 Feb 2025 19:23:53 -0300 Subject: [PATCH 0740/1340] Update and add tests --- .../err | 19 ++++--------------- ...already_specified_in_ancestor_contract.sol | 3 +-- ..._specified_by_ancestor_contract_module.sol | 13 +++++++++++++ ...ancestor_contract_multiple_inheritance.sol | 16 ++++++++++++++++ ...t_specified_by_first_ancestor_contract.sol | 4 +--- ...ut_specified_by_last_ancestor_contract.sol | 2 +- 6 files changed, 36 insertions(+), 21 deletions(-) create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_module.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_multiple_inheritance.sol diff --git a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err index a5ad27954..6d5d1dc46 100644 --- a/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err +++ b/test/cmdlineTests/storage_layout_already_defined_in_ancestor/err @@ -1,20 +1,9 @@ -Error: Storage layout can only be specified in the most derived contract. - --> :5:1: +Error: Cannot inherit from a contract with a custom storage layout. + --> :5:15: | 5 | contract B is A {} - | ^^^^^^^^^^^^^^^^^^ -Note: Storage layout was already specified here. - --> :4:12: - | -4 | contract A layout at 0x1234 {} - | ^^^^^^^^^^^^^^^^ - -Error: Storage layout can only be specified in the most derived contract. - --> :6:1: - | -6 | contract C layout at 0x1234 is B {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Note: Storage layout was already specified here. + | ^ +Note: Custom storage layout defined here: --> :4:12: | 4 | contract A layout at 0x1234 {} diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol index d525d9206..3d60cc38d 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_already_specified_in_ancestor_contract.sol @@ -4,5 +4,4 @@ contract B is A {} contract C is B layout at 0xABCD {} // ---- -// TypeError 8894: (32-50): Storage layout can only be specified in the most derived contract. -// TypeError 8894: (52-87): Storage layout can only be specified in the most derived contract. +// TypeError 8894: (46-47): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_module.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_module.sol new file mode 100644 index 000000000..3b1cf05ce --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_module.sol @@ -0,0 +1,13 @@ +==== Source: C ==== +import "M" as M; +import "N" as N; + +contract C is M.A, N.A layout at 0xABCD {} +==== Source: M ==== +contract A layout at 0x1234 {} + +==== Source: N ==== +contract A {} + +// ---- +// TypeError 8894: (C:49-52): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_multiple_inheritance.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_multiple_inheritance.sol new file mode 100644 index 000000000..8b41095fb --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_ancestor_contract_multiple_inheritance.sol @@ -0,0 +1,16 @@ +contract A layout at 1 {} +contract B is A layout at 2 {} + +contract C1 is B {} +contract C2 is A, B {} +contract C3 is B {} + +contract D1 is C1 {} +contract D2 is C2 {} +contract D3 is C3 {} +// ---- +// TypeError 8894: (40-41): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (73-74): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (93-94): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (96-97): Cannot inherit from a contract with a custom storage layout. +// TypeError 8894: (116-117): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol index 77b1ed617..69df5d775 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_first_ancestor_contract.sol @@ -3,6 +3,4 @@ contract B is A {} contract C is B {} contract D is C {} // ---- -// TypeError 8894: (27-45): Storage layout can only be specified in the most derived contract. -// TypeError 8894: (46-64): Storage layout can only be specified in the most derived contract. -// TypeError 8894: (65-83): Storage layout can only be specified in the most derived contract. +// TypeError 8894: (41-42): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol index 0c42f3550..d2ac0e931 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_last_ancestor_contract.sol @@ -3,4 +3,4 @@ contract B is A {} contract C is B layout at 42 {} contract D is C {} // ---- -// TypeError 8894: (65-83): Storage layout can only be specified in the most derived contract. +// TypeError 8894: (79-80): Cannot inherit from a contract with a custom storage layout. From 2995f0455c176fa8906067147bbd76c1a0f15b87 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 27 Feb 2025 19:23:04 -0300 Subject: [PATCH 0741/1340] Improve storage layout specifier error message --- libsolidity/analysis/ContractLevelChecker.cpp | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 7996fd711..a426b8af9 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -30,6 +30,7 @@ #include +#include #include using namespace solidity; @@ -116,19 +117,22 @@ void ContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinition const& ); } - for (auto const* ancestorContract: _contract.annotation().linearizedBaseContracts | ranges::views::reverse) + for (auto const& baseContractSpecifier: _contract.baseContracts()) { - if (*ancestorContract == _contract) - continue; - if (ancestorContract->storageLayoutSpecifier()) + auto const* baseContract = dynamic_cast( + baseContractSpecifier->name().annotation().referencedDeclaration + ); + + solAssert(baseContract); + if (baseContract->storageLayoutSpecifier()) m_errorReporter.typeError( 8894_error, - _contract.location(), + baseContractSpecifier->location(), SecondarySourceLocation().append( - "Storage layout was already specified here.", - ancestorContract->storageLayoutSpecifier()->location() + "Custom storage layout defined here:", + baseContract->storageLayoutSpecifier()->location() ), - "Storage layout can only be specified in the most derived contract." + "Cannot inherit from a contract with a custom storage layout." ); } } From 5fd8593a154c6874a7987058cb1a2c7057325947 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Fri, 28 Feb 2025 00:17:28 -0300 Subject: [PATCH 0742/1340] Fix wrong storage size computation --- Changelog.md | 1 + libsolidity/analysis/ContractLevelChecker.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 3eb3abf79..8144fdf51 100644 --- a/Changelog.md +++ b/Changelog.md @@ -27,6 +27,7 @@ Bugfixes: * SMTChecker: Fix SMT logic error when translating invariants involving array store and select operations. * SMTChecker: Fix wrong encoding of string literals as arguments of ``ecrecover`` precompile. * Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested. + * TypeChecker: Fix supurious compilation errors due to incorrect computation of contract storage size which erroneously included transient storage variables. * Yul: Fix internal compiler error when a code generation error should be reported instead. diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index a426b8af9..c655480bf 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -593,7 +593,10 @@ void ContractLevelChecker::checkStorageSize(ContractDefinition const& _contract) bigint size = 0; for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts | ranges::views::reverse) for (VariableDeclaration const* variable: contract->stateVariables()) - if (!(variable->isConstant() || variable->immutable())) + if ( + !(variable->isConstant() || variable->immutable()) && + variable->referenceLocation() == VariableDeclaration::Location::Unspecified + ) { size += variable->annotation().type->storageSizeUpperBound(); if (size >= bigint(1) << 256) From aae841e4f6ea5e1449eedc72d5e3ed19e404e034 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Fri, 28 Feb 2025 02:15:00 -0300 Subject: [PATCH 0743/1340] Add helper to calculate storage/transient size --- libsolidity/analysis/ContractLevelChecker.cpp | 28 +++++++++---------- libsolidity/analysis/ContractLevelChecker.h | 2 +- libsolidity/ast/ASTUtils.cpp | 16 +++++++++++ libsolidity/ast/ASTUtils.h | 4 +++ scripts/error_codes.py | 1 + 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index c655480bf..08d8fc9f7 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -590,19 +591,16 @@ void ContractLevelChecker::checkPayableFallbackWithoutReceive(ContractDefinition void ContractLevelChecker::checkStorageSize(ContractDefinition const& _contract) { - bigint size = 0; - for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts | ranges::views::reverse) - for (VariableDeclaration const* variable: contract->stateVariables()) - if ( - !(variable->isConstant() || variable->immutable()) && - variable->referenceLocation() == VariableDeclaration::Location::Unspecified - ) - { - size += variable->annotation().type->storageSizeUpperBound(); - if (size >= bigint(1) << 256) - { - m_errorReporter.typeError(7676_error, _contract.location(), "Contract requires too much storage."); - break; - } - } + using enum VariableDeclaration::Location; + for (VariableDeclaration::Location location: {Unspecified, Transient}) + { + bigint size = contractStorageSizeUpperBound(_contract, location); + if (size >= bigint(1) << 256) + { + if (location == Unspecified) + m_errorReporter.typeError(7676_error, _contract.location(), "Contract requires too much storage."); + else + m_errorReporter.typeError(5026_error, _contract.location(), "Contract requires too much transient storage."); + } + } } diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index f0e521c60..e51e39dc3 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -88,7 +88,7 @@ class ContractLevelChecker /// Warns if the contract has a payable fallback, but no receive ether function. void checkPayableFallbackWithoutReceive(ContractDefinition const& _contract); - /// Error if the contract requires too much storage + /// Error if the contract requires too much storage or transient storage void checkStorageSize(ContractDefinition const& _contract); /// Checks if the storage layout specifier is properly assigned in the inheritance tree and not applied to an abstract contract void checkStorageLayoutSpecifier(ContractDefinition const& _contract); diff --git a/libsolidity/ast/ASTUtils.cpp b/libsolidity/ast/ASTUtils.cpp index 7d434f896..7f5ea03a0 100644 --- a/libsolidity/ast/ASTUtils.cpp +++ b/libsolidity/ast/ASTUtils.cpp @@ -107,4 +107,20 @@ Type const* type(VariableDeclaration const& _variable) return _variable.annotation().type; } +bigint contractStorageSizeUpperBound(ContractDefinition const& _contract, VariableDeclaration::Location _location) +{ + solAssert(_location == VariableDeclaration::Location::Unspecified || _location == VariableDeclaration::Location::Transient); + + bigint size = 0; + for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts) + for (VariableDeclaration const* variable: contract->stateVariables()) + if ( + !(variable->isConstant() || variable->immutable()) && + variable->referenceLocation() == _location + ) + size += variable->annotation().type->storageSizeUpperBound(); + + return size; +} + } diff --git a/libsolidity/ast/ASTUtils.h b/libsolidity/ast/ASTUtils.h index b31bd20d5..0f37af719 100644 --- a/libsolidity/ast/ASTUtils.h +++ b/libsolidity/ast/ASTUtils.h @@ -48,4 +48,8 @@ Type const* type(Expression const& _expression); /// (this can happen for variables with non-explicit types before their types are resolved) Type const* type(VariableDeclaration const& _variable); +/// @returns The number of slots occupied by all state variables in contract's inheritance hierarchy, +/// located in @a _location (either storage or transient storage). +bigint contractStorageSizeUpperBound(ContractDefinition const& _contract, VariableDeclaration::Location _location); + } diff --git a/scripts/error_codes.py b/scripts/error_codes.py index d99d60c6e..71206ac43 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -208,6 +208,7 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "2788", # SMTChecker: BMC: verification condition(s) could not be proved "1733", # AsmAnalysis: expecting bool expression (everything is implicitly bool without types in Yul) "9547", # AsmAnalysis: assigning incompatible types in Yul (whitelisted as there are currently no types) + "5026", # ContractLevelChecker: too difficult to exceed transient storage max size due to only value types supported. } assert len(test_ids & white_ids) == 0, "The sets are not supposed to intersect" test_ids |= white_ids From e601d83b62759ca8935b3803791a8c3a8925bbba Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Fri, 28 Feb 2025 00:17:11 -0300 Subject: [PATCH 0744/1340] Add tests --- .../max_size_array_with_transient_state_variables.sol | 8 ++++++++ .../syntaxTests/largeTypes/oversized_array_1d.sol | 5 +++++ .../{oversized_array.sol => oversized_array_2d.sol} | 0 3 files changed, 13 insertions(+) create mode 100644 test/libsolidity/syntaxTests/largeTypes/max_size_array_with_transient_state_variables.sol create mode 100644 test/libsolidity/syntaxTests/largeTypes/oversized_array_1d.sol rename test/libsolidity/syntaxTests/largeTypes/{oversized_array.sol => oversized_array_2d.sol} (100%) diff --git a/test/libsolidity/syntaxTests/largeTypes/max_size_array_with_transient_state_variables.sol b/test/libsolidity/syntaxTests/largeTypes/max_size_array_with_transient_state_variables.sol new file mode 100644 index 000000000..280fb81c8 --- /dev/null +++ b/test/libsolidity/syntaxTests/largeTypes/max_size_array_with_transient_state_variables.sol @@ -0,0 +1,8 @@ +contract C { + uint[2**256 - 1] x; + uint transient y; +} +// ==== +// EVMVersion: >=cancun +// ---- +// Warning 7325: (17-33): Type uint256[115792089237316195423570985008687907853269984665640564039457584007913129639935] covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/largeTypes/oversized_array_1d.sol b/test/libsolidity/syntaxTests/largeTypes/oversized_array_1d.sol new file mode 100644 index 000000000..d46bdd9c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/largeTypes/oversized_array_1d.sol @@ -0,0 +1,5 @@ +contract C { + uint[2**256] x; +} +// ---- +// TypeError 1847: (22-28): Array length too large, maximum is 2**256 - 1. diff --git a/test/libsolidity/syntaxTests/largeTypes/oversized_array.sol b/test/libsolidity/syntaxTests/largeTypes/oversized_array_2d.sol similarity index 100% rename from test/libsolidity/syntaxTests/largeTypes/oversized_array.sol rename to test/libsolidity/syntaxTests/largeTypes/oversized_array_2d.sol From 7ffb394e72c01ffce9fc7ad85998c7be07a97aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 1 Mar 2025 18:59:49 +0100 Subject: [PATCH 0745/1340] Replace assertThrow in tests with asserts/validations/unimplemented checks --- test/Common.cpp | 10 +++++----- test/EVMHost.cpp | 14 ++++++++------ test/Metadata.cpp | 35 ++++++++++++++++++---------------- test/tools/IsolTestOptions.cpp | 2 +- 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/test/Common.cpp b/test/Common.cpp index bb25d203b..8b39d4a53 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -129,22 +129,22 @@ void CommonOptions::addOptions() void CommonOptions::validate() const { - assertThrow( + solRequire( !testPath.empty(), ConfigException, "No test path specified. The --testpath argument must not be empty when given." ); - assertThrow( + solRequire( fs::exists(testPath), ConfigException, "Invalid test path specified." ); - assertThrow( + solRequire( batches > 0, ConfigException, "Batches needs to be at least 1." ); - assertThrow( + solRequire( selectedBatch < batches, ConfigException, "Selected batch has to be less than number of batches." @@ -162,7 +162,7 @@ void CommonOptions::validate() const std::cout << std::endl << "DO NOT COMMIT THE UPDATED EXPECTATIONS." << std::endl << std::endl; } - assertThrow(!eofVersion().has_value() || evmVersion().supportsEOF(), ConfigException, "EOF is unavailable before Osaka fork."); + solRequire(!eofVersion().has_value() || evmVersion().supportsEOF(), ConfigException, "EOF is unavailable before Osaka fork."); } bool CommonOptions::parse(int argc, char const* const* argv) diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 7df39bf71..fcab682a2 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -29,6 +29,7 @@ #endif #include +#include #if defined(__GNUC__) && !defined(__clang__) // GCC-specific pragma #pragma GCC diagnostic pop @@ -105,7 +106,7 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm): if (!m_vm) { std::cerr << "Unable to find evmone library" << std::endl; - assertThrow(false, Exception, ""); + solRequire(false, Exception, ""); } if (_evmVersion == langutil::EVMVersion::homestead()) @@ -137,7 +138,7 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm): else if (_evmVersion == langutil::EVMVersion::osaka()) m_evmRevision = EVMC_OSAKA; else - assertThrow(false, Exception, "Unsupported EVM version"); + solRequire(false, Exception, "Unsupported EVM version"); if (m_evmRevision >= EVMC_PARIS) // This is the value from the merge block. @@ -228,7 +229,7 @@ void EVMHost::newTransactionFrame() void EVMHost::transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recipient, u256 const& _value) noexcept { - assertThrow(u256(convertFromEVMC(_sender.balance)) >= _value, Exception, "Insufficient balance for transfer"); + solRequire(u256(convertFromEVMC(_sender.balance)) >= _value, Exception, "Insufficient balance for transfer"); _sender.balance = convertToEVMC(u256(convertFromEVMC(_sender.balance)) - _value); _recipient.balance = convertToEVMC(u256(convertFromEVMC(_recipient.balance)) + _value); } @@ -329,7 +330,7 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept } else if (value <= 0xffff) { return bytes{128 + 55 + 2, static_cast(value >> 8), static_cast(value)}; } else { - assertThrow(false, Exception, "Can only encode RLP numbers <= 0xffff"); + solUnimplemented("Can only encode RLP numbers <= 0xffff"); } }; @@ -343,7 +344,7 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept ), h160::AlignRight); message.recipient = convertToEVMC(createAddress); - assertThrow(accounts.count(message.recipient) == 0, Exception, "Account cannot exist"); + soltestAssert(accounts.count(message.recipient) == 0, "Account cannot exist"); code = evmc::bytes(message.input_data, message.input_data + message.input_size); } @@ -1320,7 +1321,7 @@ evmc::Result EVMHost::resultWithGas( StorageMap const& EVMHost::get_address_storage(evmc::address const& _addr) { - assertThrow(account_exists(_addr), Exception, "Account does not exist."); + soltestAssert(account_exists(_addr), "Account does not exist."); return accounts[_addr].storage; } @@ -1386,6 +1387,7 @@ void EVMHostPrinter::callRecords() default: assertThrow(false, Exception, "Invalid call kind."); } + unreachable(); }; for (auto const& record: m_host.recorded_calls) diff --git a/test/Metadata.cpp b/test/Metadata.cpp index cdfcdfb19..6b2d1f3d8 100644 --- a/test/Metadata.cpp +++ b/test/Metadata.cpp @@ -20,11 +20,17 @@ * Metadata processing helpers. */ -#include -#include +#include + +#include + +#include + #include #include -#include + +#include +#include namespace solidity::test { @@ -64,11 +70,11 @@ class TinyCBORParser public: explicit TinyCBORParser(bytes const& _metadata): m_pos(0), m_metadata(_metadata) { - assertThrow((m_pos + 1) < _metadata.size(), CBORException, "Input too short."); + solRequire((m_pos + 1) < _metadata.size(), CBORException, "Input too short."); } unsigned mapItemCount() { - assertThrow(nextType() == MajorType::Map, CBORException, "Fixed-length map expected."); + solRequire(nextType() == MajorType::Map, CBORException, "Fixed-length map expected."); return readLength(); } std::string readKey() @@ -89,17 +95,14 @@ class TinyCBORParser m_pos++; if (value == 20) return "false"; - else if (value == 21) + if (value == 21) return "true"; - else - { - assertThrow(false, CBORException, "Unsupported simple value (not a boolean)."); - return ""; // unreachable, but prevents compiler warning. - } + solUnimplemented("Unsupported simple value (not a boolean)."); } - default: - assertThrow(false, CBORException, "Unsupported value type."); + case MajorType::Map: + solUnimplemented("Nested maps not supported."); } + util::unreachable(); } private: enum class MajorType @@ -118,7 +121,7 @@ class TinyCBORParser case 3: return MajorType::TextString; case 5: return MajorType::Map; case 7: return MajorType::SimpleData; - default: assertThrow(false, CBORException, "Unsupported major type."); + default: solUnimplemented("Unsupported major type."); } } unsigned nextImmediate() const { return m_metadata.at(m_pos) & 0x1f; } @@ -130,7 +133,7 @@ class TinyCBORParser if (length == 24) return m_metadata.at(m_pos++); // Unsupported length kind. (Only by this parser.) - assertThrow(false, CBORException, std::string("Unsupported length ") + std::to_string(length)); + solUnimplemented(std::string("Unsupported length ") + std::to_string(length)); } bytes readBytes(unsigned length) { @@ -141,7 +144,7 @@ class TinyCBORParser std::string readString() { // Expect a text string. - assertThrow(nextType() == MajorType::TextString, CBORException, "String expected."); + soltestAssert(nextType() == MajorType::TextString, "String expected."); bytes tmp{readBytes(readLength())}; return std::string{tmp.begin(), tmp.end()}; } diff --git a/test/tools/IsolTestOptions.cpp b/test/tools/IsolTestOptions.cpp index 0994b63a8..e0980c764 100644 --- a/test/tools/IsolTestOptions.cpp +++ b/test/tools/IsolTestOptions.cpp @@ -92,7 +92,7 @@ void IsolTestOptions::validate() const CommonOptions::validate(); static std::string filterString{"[a-zA-Z0-9_/*]*"}; static std::regex filterExpression{filterString}; - assertThrow( + solRequire( regex_match(testFilter, filterExpression), ConfigException, "Invalid test unit filter - can only contain '" + filterString + ": " + testFilter From 7841d882056d1a6b066509d1b2fe113ce40df86e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 1 Mar 2025 18:14:19 +0100 Subject: [PATCH 0746/1340] Add validations against selecting EOF on EVM versions that do not support it --- libsolidity/interface/StandardCompiler.cpp | 3 +++ solc/CommandLineParser.cpp | 3 +++ test/Common.cpp | 6 +++++- test/cmdlineTests/eof_unavailable_before_osaka/args | 1 + test/cmdlineTests/eof_unavailable_before_osaka/err | 1 + test/cmdlineTests/eof_unavailable_before_osaka/exit | 1 + .../eof_unavailable_before_osaka/input.sol | 4 ++++ .../import_asm_json_eof_unavailable_before_osaka/args | 1 + .../import_asm_json_eof_unavailable_before_osaka/err | 1 + .../import_asm_json_eof_unavailable_before_osaka/exit | 1 + .../stdin | 1 + .../standard_eof_unavailable_before_osaka/input.json | 10 ++++++++++ .../standard_eof_unavailable_before_osaka/output.json | 11 +++++++++++ .../input.json | 10 ++++++++++ .../output.json | 11 +++++++++++ .../input.json | 10 ++++++++++ .../output.json | 11 +++++++++++ .../strict_asm_eof_unavailable_before_osaka/args | 1 + .../strict_asm_eof_unavailable_before_osaka/err | 1 + .../strict_asm_eof_unavailable_before_osaka/exit | 1 + .../strict_asm_eof_unavailable_before_osaka/input.yul | 1 + 21 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 test/cmdlineTests/eof_unavailable_before_osaka/args create mode 100644 test/cmdlineTests/eof_unavailable_before_osaka/err create mode 100644 test/cmdlineTests/eof_unavailable_before_osaka/exit create mode 100644 test/cmdlineTests/eof_unavailable_before_osaka/input.sol create mode 100644 test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/args create mode 100644 test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/err create mode 100644 test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/exit create mode 100644 test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/stdin create mode 100644 test/cmdlineTests/standard_eof_unavailable_before_osaka/input.json create mode 100644 test/cmdlineTests/standard_eof_unavailable_before_osaka/output.json create mode 100644 test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/input.json create mode 100644 test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/output.json create mode 100644 test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/input.json create mode 100644 test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/output.json create mode 100644 test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/args create mode 100644 test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/err create mode 100644 test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/exit create mode 100644 test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/input.yul diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index f52ad4e1e..71fbf17e2 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -846,6 +846,9 @@ std::variant StandardCompiler::parseI ret.eofVersion = 1; } + if (ret.eofVersion.has_value() && !ret.evmVersion.supportsEOF()) + return formatFatalError(Error::Type::JSONError, "EOF is not supported by EVM versions earlier than " + EVMVersion::firstWithEOF().name() + "."); + if (settings.contains("debug")) { if (auto result = checkKeys(settings["debug"], {"revertStrings", "debugInfo"}, "settings.debug")) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 25f3048b5..a382c5217 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -1252,6 +1252,9 @@ void CommandLineParser::processArgs() m_options.output.eofVersion = 1; } + if (m_options.output.eofVersion.has_value() && !m_options.output.evmVersion.supportsEOF()) + solThrow(CommandLineValidationError, "EOF is not supported by EVM versions earlier than " + EVMVersion::firstWithEOF().name() + "."); + if (m_args.count(g_strNoOptimizeYul) > 0 && m_args.count(g_strOptimizeYul) > 0) solThrow( CommandLineValidationError, diff --git a/test/Common.cpp b/test/Common.cpp index 8b39d4a53..d39c6db1e 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -162,7 +162,11 @@ void CommonOptions::validate() const std::cout << std::endl << "DO NOT COMMIT THE UPDATED EXPECTATIONS." << std::endl << std::endl; } - solRequire(!eofVersion().has_value() || evmVersion().supportsEOF(), ConfigException, "EOF is unavailable before Osaka fork."); + solRequire( + !eofVersion().has_value() || evmVersion().supportsEOF(), + ConfigException, + "EOF is not supported by EVM versions earlier than " + langutil::EVMVersion::firstWithEOF().name() + "." + ); } bool CommonOptions::parse(int argc, char const* const* argv) diff --git a/test/cmdlineTests/eof_unavailable_before_osaka/args b/test/cmdlineTests/eof_unavailable_before_osaka/args new file mode 100644 index 000000000..90e7e00e2 --- /dev/null +++ b/test/cmdlineTests/eof_unavailable_before_osaka/args @@ -0,0 +1 @@ +--optimize --experimental-eof-version 1 --evm-version cancun diff --git a/test/cmdlineTests/eof_unavailable_before_osaka/err b/test/cmdlineTests/eof_unavailable_before_osaka/err new file mode 100644 index 000000000..cf9a17a7d --- /dev/null +++ b/test/cmdlineTests/eof_unavailable_before_osaka/err @@ -0,0 +1 @@ +Error: EOF is not supported by EVM versions earlier than osaka. diff --git a/test/cmdlineTests/eof_unavailable_before_osaka/exit b/test/cmdlineTests/eof_unavailable_before_osaka/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/eof_unavailable_before_osaka/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/eof_unavailable_before_osaka/input.sol b/test/cmdlineTests/eof_unavailable_before_osaka/input.sol new file mode 100644 index 000000000..f123f6c8b --- /dev/null +++ b/test/cmdlineTests/eof_unavailable_before_osaka/input.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C {} diff --git a/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/args b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/args new file mode 100644 index 000000000..b5d6267fa --- /dev/null +++ b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/args @@ -0,0 +1 @@ +--import-asm-json --experimental-eof-version 1 --evm-version cancun diff --git a/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/err b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/err new file mode 100644 index 000000000..02ce7958c --- /dev/null +++ b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/err @@ -0,0 +1 @@ +Error: Option --evm-version is not supported with --import-asm-json. diff --git a/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/exit b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/stdin b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/stdin new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/stdin @@ -0,0 +1 @@ +{} diff --git a/test/cmdlineTests/standard_eof_unavailable_before_osaka/input.json b/test/cmdlineTests/standard_eof_unavailable_before_osaka/input.json new file mode 100644 index 000000000..071e711e6 --- /dev/null +++ b/test/cmdlineTests/standard_eof_unavailable_before_osaka/input.json @@ -0,0 +1,10 @@ +{ + "language": "Solidity", + "sources": { + "C.sol": {"content": "contract C {}"} + }, + "settings": { + "eofVersion": 1, + "evmVersion": "cancun" + } +} diff --git a/test/cmdlineTests/standard_eof_unavailable_before_osaka/output.json b/test/cmdlineTests/standard_eof_unavailable_before_osaka/output.json new file mode 100644 index 000000000..8b50700db --- /dev/null +++ b/test/cmdlineTests/standard_eof_unavailable_before_osaka/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "EOF is not supported by EVM versions earlier than osaka.", + "message": "EOF is not supported by EVM versions earlier than osaka.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/input.json b/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/input.json new file mode 100644 index 000000000..12cac3b2c --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/input.json @@ -0,0 +1,10 @@ +{ + "language": "EVMAssembly", + "sources": { + "C.sol": {"assemblyJson": {}} + }, + "settings": { + "eofVersion": 1, + "evmVersion": "cancun" + } +} diff --git a/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/output.json b/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/output.json new file mode 100644 index 000000000..8b50700db --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_eof_unavailable_before_osaka/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "EOF is not supported by EVM versions earlier than osaka.", + "message": "EOF is not supported by EVM versions earlier than osaka.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/input.json b/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/input.json new file mode 100644 index 000000000..125792d09 --- /dev/null +++ b/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/input.json @@ -0,0 +1,10 @@ +{ + "language": "Yul", + "sources": { + "C.yul": {"content": "{}"} + }, + "settings": { + "eofVersion": 1, + "evmVersion": "cancun" + } +} diff --git a/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/output.json b/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/output.json new file mode 100644 index 000000000..8b50700db --- /dev/null +++ b/test/cmdlineTests/standard_yul_eof_unavailable_before_osaka/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "EOF is not supported by EVM versions earlier than osaka.", + "message": "EOF is not supported by EVM versions earlier than osaka.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/args b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/args new file mode 100644 index 000000000..7ec243fde --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/args @@ -0,0 +1 @@ +--strict-assembly --experimental-eof-version 1 --evm-version cancun diff --git a/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/err b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/err new file mode 100644 index 000000000..cf9a17a7d --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/err @@ -0,0 +1 @@ +Error: EOF is not supported by EVM versions earlier than osaka. diff --git a/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/exit b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/input.yul b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/input.yul new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/input.yul @@ -0,0 +1 @@ +{} From 24b0ec2e760d4b4a1063d385aebd6bbdad34fddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 1 Mar 2025 18:58:28 +0100 Subject: [PATCH 0747/1340] EVMHostPrinter: Fix EOFCREATE not being handled --- test/EVMHost.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index fcab682a2..983615312 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -1384,8 +1384,8 @@ void EVMHostPrinter::callRecords() return "CREATE"; case evmc_call_kind::EVMC_CREATE2: return "CREATE2"; - default: - assertThrow(false, Exception, "Invalid call kind."); + case evmc_call_kind::EVMC_EOFCREATE: + return "EOFCREATE"; } unreachable(); }; From 252a3a8632bf8a2d1b49c77944c2cfc2572132ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 2 Mar 2025 02:45:07 +0100 Subject: [PATCH 0748/1340] ObjectOptimizer::calculateCacheKey(): Fix flipped boolean conditions - This fixes the error caused by accessing an empty optional. - Switch to static_cast --- Changelog.md | 1 + libyul/ObjectOptimizer.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index 8144fdf51..7b15ce945 100644 --- a/Changelog.md +++ b/Changelog.md @@ -29,6 +29,7 @@ Bugfixes: * Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested. * TypeChecker: Fix supurious compilation errors due to incorrect computation of contract storage size which erroneously included transient storage variables. * Yul: Fix internal compiler error when a code generation error should be reported instead. + * Yul Optimizer: Fix failing debug assertion due to dereferencing of an empty ``optional`` value. Build system: diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index 181cbaa8f..07c25a068 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -154,12 +154,12 @@ std::optional ObjectOptimizer::calculateCacheKey( rawKey += keccak256(asmPrinter(_ast)).asBytes(); rawKey += keccak256(_debugData.formatUseSrcComment()).asBytes(); rawKey += h256(u256(_settings.language)).asBytes(); - rawKey += FixedHash<1>(uint8_t(_settings.optimizeStackAllocation ? 0 : 1)).asBytes(); + rawKey += FixedHash<1>(static_cast(_settings.optimizeStackAllocation ? 1 : 0)).asBytes(); rawKey += h256(u256(_settings.expectedExecutionsPerDeployment)).asBytes(); - rawKey += FixedHash<1>(uint8_t(_isCreation ? 0 : 1)).asBytes(); + rawKey += FixedHash<1>(static_cast(_isCreation ? 1 : 0)).asBytes(); rawKey += keccak256(_settings.evmVersion.name()).asBytes(); yulAssert(!_settings.eofVersion.has_value() || *_settings.eofVersion > 0); - rawKey += FixedHash<1>(uint8_t(_settings.eofVersion ? 0 : *_settings.eofVersion)).asBytes(); + rawKey += FixedHash<1>(static_cast(_settings.eofVersion ? *_settings.eofVersion : 0)).asBytes(); rawKey += keccak256(_settings.yulOptimiserSteps).asBytes(); rawKey += keccak256(_settings.yulOptimiserCleanupSteps).asBytes(); From c9aa6f4d9d505f3ed6d1043e58aec9ed2674737a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 3 Mar 2025 18:16:51 +0100 Subject: [PATCH 0749/1340] ObjectOptimizer::calculateCacheKey(): Cast bool directly in uint_t --- libyul/ObjectOptimizer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index 07c25a068..a09e88791 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -154,9 +154,10 @@ std::optional ObjectOptimizer::calculateCacheKey( rawKey += keccak256(asmPrinter(_ast)).asBytes(); rawKey += keccak256(_debugData.formatUseSrcComment()).asBytes(); rawKey += h256(u256(_settings.language)).asBytes(); - rawKey += FixedHash<1>(static_cast(_settings.optimizeStackAllocation ? 1 : 0)).asBytes(); + static_assert(static_cast(static_cast(2)) == 1); + rawKey += FixedHash<1>(static_cast(_settings.optimizeStackAllocation)).asBytes(); rawKey += h256(u256(_settings.expectedExecutionsPerDeployment)).asBytes(); - rawKey += FixedHash<1>(static_cast(_isCreation ? 1 : 0)).asBytes(); + rawKey += FixedHash<1>(static_cast(_isCreation)).asBytes(); rawKey += keccak256(_settings.evmVersion.name()).asBytes(); yulAssert(!_settings.eofVersion.has_value() || *_settings.eofVersion > 0); rawKey += FixedHash<1>(static_cast(_settings.eofVersion ? *_settings.eofVersion : 0)).asBytes(); From 3286c9ea5c3511ad2fae0bd31c37174af9a92128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 1 Mar 2025 21:55:13 +0100 Subject: [PATCH 0750/1340] CommonSyntaxTest::printErrorList(): Use the colored stream in a less misleading way --- test/CommonSyntaxTest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/CommonSyntaxTest.cpp b/test/CommonSyntaxTest.cpp index 3cb908118..ccf4added 100644 --- a/test/CommonSyntaxTest.cpp +++ b/test/CommonSyntaxTest.cpp @@ -197,15 +197,15 @@ void CommonSyntaxTest::printErrorList( for (auto const& error: _errorList) { { - util::AnsiColorized scope( + util::AnsiColorized formattedStream( _stream, _formatted, {BOLD, SourceReferenceFormatter::errorTextColor(Error::errorSeverity(error.type))} ); - _stream << _linePrefix << Error::formatErrorType(error.type); + formattedStream << _linePrefix << Error::formatErrorType(error.type); if (error.errorId.has_value()) - _stream << ' ' << error.errorId->error; - _stream << ": "; + formattedStream << ' ' << error.errorId->error; + formattedStream << ": "; } if (!error.sourceName.empty() || error.locationStart >= 0 || error.locationEnd >= 0) { From 78854ecf75cc5806a5f9872c29bd8a53fb7f62b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 2 Mar 2025 09:02:22 +0100 Subject: [PATCH 0751/1340] Standard JSON test case for Yul StackTooDeep --- .../in.sol | 10 +++++++ .../input.json | 12 ++++++++ .../output.json | 29 +++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 test/cmdlineTests/standard_stack_too_deep_from_code_transform/in.sol create mode 100644 test/cmdlineTests/standard_stack_too_deep_from_code_transform/input.json create mode 100644 test/cmdlineTests/standard_stack_too_deep_from_code_transform/output.json diff --git a/test/cmdlineTests/standard_stack_too_deep_from_code_transform/in.sol b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/in.sol new file mode 100644 index 000000000..aae75b841 --- /dev/null +++ b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/in.sol @@ -0,0 +1,10 @@ +contract C { + function f() public { + uint b; + abi.encodePacked( + b, b, b, b, b, b, b, b, + b, b, b, b, b, b, b, b, + b, b, b, b, b, b, b, b + ); + } +} diff --git a/test/cmdlineTests/standard_stack_too_deep_from_code_transform/input.json b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/input.json new file mode 100644 index 000000000..a01e842b3 --- /dev/null +++ b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/input.json @@ -0,0 +1,12 @@ +{ + "language": "Solidity", + "sources": { + "in.sol": {"urls": ["standard_stack_too_deep_from_code_transform/in.sol"]} + }, + "settings": { + "viaIR": true, + "outputSelection": { + "*": {"*": ["evm.bytecode"]} + } + } +} diff --git a/test/cmdlineTests/standard_stack_too_deep_from_code_transform/output.json b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/output.json new file mode 100644 index 000000000..dbf1dfdcf --- /dev/null +++ b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/output.json @@ -0,0 +1,29 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "YulException: Cannot swap Variable value23 with Slot 0x20: too deep in the stack by 9 slots in [ RET value23 value22 value21 value20 value19 value18 value17 value16 value15 value14 value13 value12 value11 value10 value9 value8 value7 value6 value5 value4 value3 value2 value1 value0 pos 0x20 ] +memoryguard was present. + --> in.sol:1:1: + | +1 | contract C { + | ^ (Relevant source part starts here and spans across multiple lines). + +", + "message": "Yul exception:Cannot swap Variable value23 with Slot 0x20: too deep in the stack by 9 slots in [ RET value23 value22 value21 value20 value19 value18 value17 value16 value15 value14 value13 value12 value11 value10 value9 value8 value7 value6 value5 value4 value3 value2 value1 value0 pos 0x20 ] +memoryguard was present.", + "severity": "error", + "sourceLocation": { + "end": 206, + "file": "in.sol", + "start": 0 + }, + "type": "YulException" + } + ], + "sources": { + "in.sol": { + "id": 0 + } + } +} From 887ec85bf4e7ac5d8e4dd5143a644346b5b940a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 1 Mar 2025 23:27:38 +0100 Subject: [PATCH 0752/1340] Disentangle handling of failed Yul assertions from Yul StackTooDeep errors --- Changelog.md | 1 + libsolidity/interface/StandardCompiler.cpp | 15 +++++++++++++-- libyul/Exceptions.h | 2 +- solc/CommandLineInterface.cpp | 10 ++++++++++ solc/main.cpp | 6 ++++++ .../stack_too_deep_from_code_transform/args | 1 + .../stack_too_deep_from_code_transform/err | 6 ++++++ .../stack_too_deep_from_code_transform/exit | 1 + .../stack_too_deep_from_code_transform/input.sol | 10 ++++++++++ .../output.json | 2 +- 10 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 test/cmdlineTests/stack_too_deep_from_code_transform/args create mode 100644 test/cmdlineTests/stack_too_deep_from_code_transform/err create mode 100644 test/cmdlineTests/stack_too_deep_from_code_transform/exit create mode 100644 test/cmdlineTests/stack_too_deep_from_code_transform/input.sol diff --git a/Changelog.md b/Changelog.md index 7b15ce945..bb7a20d09 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ Compiler Features: Bugfixes: + * Commandline Interface: Report StackTooDeep errors in compiler mode as proper errors instead of printing diagnostic information meant for internal compiler errors. * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. * Metadata: Fix custom cleanup sequence missing from metadata when other optimizer settings have default values. * SMTChecker: Fix internal compiler error when analyzing overflowing expressions or bitwise negation of unsigned types involving constants. diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 71fbf17e2..eee29f921 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1412,6 +1412,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu )); } } + // NOTE: This includes langutil::StackTooDeepError. catch (CompilerError const& _exception) { errors.emplace_back(formatErrorWithException( @@ -1422,6 +1423,16 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu "Compiler error (" + _exception.lineInfo() + ")" )); } + catch (yul::StackTooDeepError const& _exception) + { + errors.emplace_back(formatErrorWithException( + compilerStack, + _exception, + Error::Type::YulException, + "general", + "" // No prefix needed. These messages already say it's a "stack too deep" error. + )); + } catch (InternalCompilerError const& _exception) { errors.emplace_back(formatErrorWithException( @@ -1437,14 +1448,14 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu // let StandardCompiler::compile handle this throw _exception; } - catch (yul::YulException const& _exception) + catch (YulAssertion const& _exception) { errors.emplace_back(formatErrorWithException( compilerStack, _exception, Error::Type::YulException, "general", - "Yul exception" + "Yul assertion failed (" + _exception.lineInfo() + ")" )); } catch (smtutil::SMTLogicError const& _exception) diff --git a/libyul/Exceptions.h b/libyul/Exceptions.h index f92268180..4f08e192f 100644 --- a/libyul/Exceptions.h +++ b/libyul/Exceptions.h @@ -36,7 +36,7 @@ namespace solidity::yul struct YulException: virtual util::Exception {}; struct OptimizerException: virtual YulException {}; struct CodegenException: virtual YulException {}; -struct YulAssertion: virtual YulException {}; +struct YulAssertion: virtual util::Exception {}; struct StackTooDeepError: virtual YulException { diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 4fd730096..e57cd77a9 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -1009,6 +1009,7 @@ void CommandLineInterface::compile() if (!successful) solThrow(CommandLineExecutionError, ""); } + // NOTE: This includes langutil::StackTooDeepError. catch (CompilerError const& _exception) { m_hasOutput = true; @@ -1018,6 +1019,15 @@ void CommandLineInterface::compile() ); solThrow(CommandLineExecutionError, ""); } + catch (yul::StackTooDeepError const& _exception) + { + m_hasOutput = true; + formatter.printExceptionInformation( + _exception, + Error::errorSeverity(Error::Type::YulException) + ); + solThrow(CommandLineExecutionError, ""); + } } void CommandLineInterface::handleCombinedJSON() diff --git a/solc/main.cpp b/solc/main.cpp index c6c3df7a2..499945594 100644 --- a/solc/main.cpp +++ b/solc/main.cpp @@ -51,6 +51,12 @@ int main(int argc, char** argv) std::cerr << boost::diagnostic_information(_exception); return 2; } + catch (yul::YulAssertion const& _exception) + { + std::cerr << "Yul assertion failed:" << std::endl; + std::cerr << boost::diagnostic_information(_exception); + return 2; + } catch (...) { std::cerr << "Uncaught exception:" << std::endl; diff --git a/test/cmdlineTests/stack_too_deep_from_code_transform/args b/test/cmdlineTests/stack_too_deep_from_code_transform/args new file mode 100644 index 000000000..b182392aa --- /dev/null +++ b/test/cmdlineTests/stack_too_deep_from_code_transform/args @@ -0,0 +1 @@ +--via-ir --bin diff --git a/test/cmdlineTests/stack_too_deep_from_code_transform/err b/test/cmdlineTests/stack_too_deep_from_code_transform/err new file mode 100644 index 000000000..588f4d437 --- /dev/null +++ b/test/cmdlineTests/stack_too_deep_from_code_transform/err @@ -0,0 +1,6 @@ +Error: Cannot swap Variable value23 with Slot 0x20: too deep in the stack by 9 slots in [ RET value23 value22 value21 value20 value19 value18 value17 value16 value15 value14 value13 value12 value11 value10 value9 value8 value7 value6 value5 value4 value3 value2 value1 value0 pos 0x20 ] +memoryguard was present. + --> stack_too_deep_from_code_transform/input.sol:1:1: + | +1 | contract C { + | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/stack_too_deep_from_code_transform/exit b/test/cmdlineTests/stack_too_deep_from_code_transform/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/stack_too_deep_from_code_transform/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/stack_too_deep_from_code_transform/input.sol b/test/cmdlineTests/stack_too_deep_from_code_transform/input.sol new file mode 100644 index 000000000..aae75b841 --- /dev/null +++ b/test/cmdlineTests/stack_too_deep_from_code_transform/input.sol @@ -0,0 +1,10 @@ +contract C { + function f() public { + uint b; + abi.encodePacked( + b, b, b, b, b, b, b, b, + b, b, b, b, b, b, b, b, + b, b, b, b, b, b, b, b + ); + } +} diff --git a/test/cmdlineTests/standard_stack_too_deep_from_code_transform/output.json b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/output.json index dbf1dfdcf..b4b0139fe 100644 --- a/test/cmdlineTests/standard_stack_too_deep_from_code_transform/output.json +++ b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/output.json @@ -10,7 +10,7 @@ memoryguard was present. | ^ (Relevant source part starts here and spans across multiple lines). ", - "message": "Yul exception:Cannot swap Variable value23 with Slot 0x20: too deep in the stack by 9 slots in [ RET value23 value22 value21 value20 value19 value18 value17 value16 value15 value14 value13 value12 value11 value10 value9 value8 value7 value6 value5 value4 value3 value2 value1 value0 pos 0x20 ] + "message": "Cannot swap Variable value23 with Slot 0x20: too deep in the stack by 9 slots in [ RET value23 value22 value21 value20 value19 value18 value17 value16 value15 value14 value13 value12 value11 value10 value9 value8 value7 value6 value5 value4 value3 value2 value1 value0 pos 0x20 ] memoryguard was present.", "severity": "error", "sourceLocation": { From e899fb9da9fedeaa8f922217bde89068cc7918a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 2 Mar 2025 10:06:44 +0100 Subject: [PATCH 0753/1340] StandardCompiler: Provide full ICE output on failed assertions --- libsolidity/interface/StandardCompiler.cpp | 31 ++++++++++------------ 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index eee29f921..6bd5cd231 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -131,7 +131,7 @@ Json formatErrorWithException( ); if (std::string const* description = _exception.comment()) - message = ((_message.length() > 0) ? (_message + ":") : "") + *description; + message = ((_message.length() > 0) ? (_message + ": ") : "") + *description; else message = _message; @@ -1433,14 +1433,12 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu "" // No prefix needed. These messages already say it's a "stack too deep" error. )); } - catch (InternalCompilerError const& _exception) + catch (InternalCompilerError const&) { - errors.emplace_back(formatErrorWithException( - compilerStack, - _exception, + errors.emplace_back(formatError( Error::Type::InternalCompilerError, "general", - "Internal compiler error (" + _exception.lineInfo() + ")" + "Internal compiler error:\n" + boost::current_exception_diagnostic_information() )); } catch (UnimplementedFeatureError const& _exception) @@ -1448,24 +1446,20 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu // let StandardCompiler::compile handle this throw _exception; } - catch (YulAssertion const& _exception) + catch (YulAssertion const&) { - errors.emplace_back(formatErrorWithException( - compilerStack, - _exception, + errors.emplace_back(formatError( Error::Type::YulException, "general", - "Yul assertion failed (" + _exception.lineInfo() + ")" + "Yul assertion failed:\n" + boost::current_exception_diagnostic_information() )); } - catch (smtutil::SMTLogicError const& _exception) + catch (smtutil::SMTLogicError const&) { - errors.emplace_back(formatErrorWithException( - compilerStack, - _exception, + errors.emplace_back(formatError( Error::Type::SMTLogicException, "general", - "SMT logic exception" + "SMT logic error:\n" + boost::current_exception_diagnostic_information() )); } catch (...) @@ -1838,7 +1832,10 @@ Json StandardCompiler::compile(Json const& _input) noexcept } catch (...) { - return formatFatalError(Error::Type::InternalCompilerError, "Internal exception in StandardCompiler::compile: " + boost::current_exception_diagnostic_information()); + return formatFatalError( + Error::Type::InternalCompilerError, + "Uncaught exception:\n" + boost::current_exception_diagnostic_information() + ); } } From 688bd0dea86cd8e2d4d7fb9741722028b96a152a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 2 Mar 2025 00:59:22 +0100 Subject: [PATCH 0754/1340] SourceReferenceFormatter: Don't hide source location of the name of the input file is an empty string --- Changelog.md | 1 + liblangutil/SourceReferenceFormatter.cpp | 6 +++--- test/cmdlineTests/standard_empty_file_name/output.json | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index bb7a20d09..65c04b106 100644 --- a/Changelog.md +++ b/Changelog.md @@ -17,6 +17,7 @@ Compiler Features: Bugfixes: * Commandline Interface: Report StackTooDeep errors in compiler mode as proper errors instead of printing diagnostic information meant for internal compiler errors. + * Error Reporting: Fix error locations not being shown for source files with empty names. * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. * Metadata: Fix custom cleanup sequence missing from metadata when other optimizer settings have default values. * SMTChecker: Fix internal compiler error when analyzing overflowing expressions or bitwise negation of unsigned types involving constants. diff --git a/liblangutil/SourceReferenceFormatter.cpp b/liblangutil/SourceReferenceFormatter.cpp index c48cb328d..12308bf0d 100644 --- a/liblangutil/SourceReferenceFormatter.cpp +++ b/liblangutil/SourceReferenceFormatter.cpp @@ -114,11 +114,11 @@ AnsiColorized SourceReferenceFormatter::diagColored() const void SourceReferenceFormatter::printSourceLocation(SourceReference const& _ref) { - if (_ref.sourceName.empty()) - return; // Nothing we can print here - if (_ref.position.line < 0) { + if (_ref.sourceName.empty()) + return; // Nothing we can print here + frameColored() << "-->"; m_stream << ' ' << _ref.sourceName << '\n'; return; // No line available, nothing else to print diff --git a/test/cmdlineTests/standard_empty_file_name/output.json b/test/cmdlineTests/standard_empty_file_name/output.json index 1fd016e54..b4e525c21 100644 --- a/test/cmdlineTests/standard_empty_file_name/output.json +++ b/test/cmdlineTests/standard_empty_file_name/output.json @@ -4,6 +4,10 @@ "component": "general", "errorCode": "2904", "formattedMessage": "DeclarationError: Declaration \"A\" not found in \"\" (referenced as \".\"). + --> :2:24: + | +2 | pragma solidity >=0.0; import {A} from \".\"; + | ^^^^^^^^^^^^^^^^^^^^ ", "message": "Declaration \"A\" not found in \"\" (referenced as \".\").", From 36ec42d1ae48ada54ca3a3d5095bbea5a9d16373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 2 Mar 2025 00:45:18 +0100 Subject: [PATCH 0755/1340] CompilerStack::loadGeneratedIR(): Include error codes in the assertion message --- libsolidity/interface/CompilerStack.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 2748c09cd..9582939f5 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -827,7 +827,12 @@ YulStack CompilerStack::loadGeneratedIR(std::string const& _ir) const yulAnalysisSuccessful, _ir + "\n\n" "Invalid IR generated:\n" + - SourceReferenceFormatter::formatErrorInformation(stack.errors(), stack) + "\n" + SourceReferenceFormatter::formatErrorInformation( + stack.errors(), + stack, // _charStreamProvider + false, // _colored + true // _withErrorIds + ) + "\n" ); return stack; From c422fa56a02df0de70e94da81148245981f70e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sun, 2 Mar 2025 00:36:36 +0100 Subject: [PATCH 0756/1340] AsmAnalyzer::analyzeStrictAssertCorrect(): Print source and errors when analysis fails --- libyul/AsmAnalysis.cpp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index aa3e23e26..b6ff862b3 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -113,7 +113,36 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( {}, std::move(_objectStructure) ).analyze(_astRoot); - yulAssert(success && !errors.hasErrors(), "Invalid assembly/yul code."); + + if (!success) + { + auto formatErrors = [](ErrorList const& _errorList) { + std::vector formattedErrors; + for (std::shared_ptr const& error: _errorList) + { + yulAssert(error->comment()); + formattedErrors.push_back(fmt::format( + // Intentionally not showing source locations because we don't have the original + // source here and it's unlikely they match the pretty-printed version. + // They may not even match the original source if the AST was modified by the optimizer. + "- {} {}: {}", + Error::formatErrorType(error->type()), + error->errorId().error, + *error->comment() + )); + } + return joinHumanReadable(formattedErrors, "\n"); + }; + + yulAssert(errors.hasErrors(), "Yul analysis failed but did not report any errors."); + yulAssert(false, fmt::format( + "{}\n\nExpected valid Yul, but errors were reported during analysis:\n{}", + AsmPrinter{_dialect}(_astRoot), + formatErrors(errorList) + )); + } + + yulAssert(!errors.hasErrors()); return analysisInfo; } From 8df4c81bc6aa2ce69609f12cb232f52a7d116da2 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 10 Feb 2025 09:38:48 +0100 Subject: [PATCH 0757/1340] Yul FunctionCallFinder uses FunctionHandle instead of strings as search key --- libyul/backends/evm/EVMObjectCompiler.cpp | 7 ++++--- libyul/optimiser/FullInliner.cpp | 11 +++++++---- libyul/optimiser/FunctionCallFinder.cpp | 22 ++++++++++------------ libyul/optimiser/FunctionCallFinder.h | 9 +++------ libyul/optimiser/StackLimitEvader.cpp | 6 ++++-- test/libsolidity/MemoryGuardTest.cpp | 12 ++++++++---- 6 files changed, 36 insertions(+), 31 deletions(-) diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index 30f06bc97..830c32752 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -92,11 +92,12 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) ); if (!stackErrors.empty()) { - yulAssert(_object.dialect()); + yulAssert(evmDialect->providesObjectAccess()); + auto const memoryGuardHandle = evmDialect->findBuiltin("memoryguard"); + yulAssert(memoryGuardHandle, "Compiling with object access, memoryguard should be available as builtin."); std::vector memoryGuardCalls = findFunctionCalls( _object.code()->root(), - "memoryguard", - *_object.dialect() + *memoryGuardHandle ); auto stackError = stackErrors.front(); std::string msg = stackError.comment() ? *stackError.comment() : ""; diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index 4b390f4f2..894ada609 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -83,10 +83,13 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& } // Check for memory guard. - std::vector memoryGuardCalls = findFunctionCalls(_ast, "memoryguard", m_dialect); - // We will perform less aggressive inlining, if no ``memoryguard`` call is found. - if (!memoryGuardCalls.empty()) - m_hasMemoryGuard = true; + if (auto const memoryGuard = m_dialect.findBuiltin("memoryguard")) + { + std::vector memoryGuardCalls = findFunctionCalls(_ast, *memoryGuard); + // We will perform less aggressive inlining, if no ``memoryguard`` call is found. + if (!memoryGuardCalls.empty()) + m_hasMemoryGuard = true; + } } void FullInliner::run(Pass _pass) diff --git a/libyul/optimiser/FunctionCallFinder.cpp b/libyul/optimiser/FunctionCallFinder.cpp index 4c85d77f5..9f5c75b43 100644 --- a/libyul/optimiser/FunctionCallFinder.cpp +++ b/libyul/optimiser/FunctionCallFinder.cpp @@ -19,7 +19,6 @@ #include #include -#include #include using namespace solidity; @@ -32,35 +31,34 @@ class MaybeConstFunctionCallFinder: Base { public: using MaybeConstBlock = std::conditional_t, Block const, Block>; - static std::vector run(MaybeConstBlock& _block, std::string_view const _functionName, Dialect const& _dialect) + static std::vector run(MaybeConstBlock& _block, FunctionHandle const& _functionHandle) { - MaybeConstFunctionCallFinder functionCallFinder(_functionName, _dialect); + MaybeConstFunctionCallFinder functionCallFinder(_functionHandle); functionCallFinder(_block); return functionCallFinder.m_calls; } private: - explicit MaybeConstFunctionCallFinder(std::string_view const _functionName, Dialect const& _dialect): - m_dialect(_dialect), m_functionName(_functionName), m_calls() {} + explicit MaybeConstFunctionCallFinder(FunctionHandle const& _functionHandle): + m_functionHandle(_functionHandle), m_calls() {} using Base::operator(); void operator()(ResultType& _functionCall) override { Base::operator()(_functionCall); - if (resolveFunctionName(_functionCall.functionName, m_dialect) == m_functionName) + if (functionNameToHandle(_functionCall.functionName) == m_functionHandle) m_calls.emplace_back(&_functionCall); } - Dialect const& m_dialect; - std::string_view m_functionName; + FunctionHandle const& m_functionHandle; std::vector m_calls; }; } -std::vector solidity::yul::findFunctionCalls(Block& _block, std::string_view const _functionName, Dialect const& _dialect) +std::vector yul::findFunctionCalls(Block& _block, FunctionHandle const& _functionHandle) { - return MaybeConstFunctionCallFinder::run(_block, _functionName, _dialect); + return MaybeConstFunctionCallFinder::run(_block, _functionHandle); } -std::vector solidity::yul::findFunctionCalls(Block const& _block, std::string_view const _functionName, Dialect const& _dialect) +std::vector yul::findFunctionCalls(Block const& _block, FunctionHandle const& _functionHandle) { - return MaybeConstFunctionCallFinder::run(_block, _functionName, _dialect); + return MaybeConstFunctionCallFinder::run(_block, _functionHandle); } diff --git a/libyul/optimiser/FunctionCallFinder.h b/libyul/optimiser/FunctionCallFinder.h index 1c21a0115..560ecfc38 100644 --- a/libyul/optimiser/FunctionCallFinder.h +++ b/libyul/optimiser/FunctionCallFinder.h @@ -20,28 +20,25 @@ #pragma once -#include +#include -#include #include namespace solidity::yul { -class Dialect; - /** * Finds all calls to a function of a given name using an ASTModifier. * * Prerequisite: Disambiguator */ -std::vector findFunctionCalls(Block& _block, std::string_view _functionName, Dialect const& _dialect); +std::vector findFunctionCalls(Block& _block, FunctionHandle const& _functionHandle); /** * Finds all calls to a function of a given name using an ASTWalker. * * Prerequisite: Disambiguator */ -std::vector findFunctionCalls(Block const& _block, std::string_view _functionName, Dialect const& _dialect); +std::vector findFunctionCalls(Block const& _block, FunctionHandle const& _functionHandle); } diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 13a3bbd87..f70bc0c1d 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -201,7 +201,9 @@ void StackLimitEvader::run( "StackLimitEvader does not support EOF." ); - std::vector memoryGuardCalls = findFunctionCalls(_astRoot, "memoryguard", *evmDialect); + auto const memoryGuardHandle = evmDialect->findBuiltin("memoryguard"); + yulAssert(memoryGuardHandle, "Compiling with object access, memoryguard should be available as builtin."); + std::vector const memoryGuardCalls = findFunctionCalls(_astRoot, *memoryGuardHandle); // Do not optimise, if no ``memoryguard`` call is found. if (memoryGuardCalls.empty()) return; @@ -233,7 +235,7 @@ void StackLimitEvader::run( StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, _astRoot); reservedMemory += 32 * requiredSlots; - for (FunctionCall* memoryGuardCall: findFunctionCalls(_astRoot, "memoryguard", *evmDialect)) + for (FunctionCall* memoryGuardCall: findFunctionCalls(_astRoot, *memoryGuardHandle)) { Literal* literal = std::get_if(&memoryGuardCall->arguments.front()); yulAssert(literal && literal->kind == LiteralKind::Number, ""); diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index 0f4230d5a..f7d07aa44 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -76,11 +76,15 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con } auto handleObject = [&](std::string const& _kind, Object const& _object) { - m_obtainedResult += contractName + "(" + _kind + ") " + (findFunctionCalls( + auto const memoryGuardHandle = yulStack.dialect().findBuiltin("memoryguard"); + m_obtainedResult += contractName + "(" + _kind + ") "; + if (memoryGuardHandle && !findFunctionCalls( _object.code()->root(), - "memoryguard", - yulStack.dialect() - ).empty() ? "false" : "true") + "\n"; + *memoryGuardHandle + ).empty()) + m_obtainedResult += "true\n"; + else + m_obtainedResult += "false\n"; }; handleObject("creation", *yulStack.parserResult()); size_t deployedIndex = yulStack.parserResult()->subIndexByName.at( From b07843da11c632a295c4579537250b0666f1b8b1 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 19 Feb 2025 08:45:05 +0100 Subject: [PATCH 0758/1340] Adds tests using memoryguard identifiers in inline-assembly to assert mangling --- .../args | 1 + .../input.sol | 15 +++ .../output | 123 ++++++++++++++++++ ...guard_with_inline_assembly_identifiers.sol | 26 ++++ 4 files changed, 165 insertions(+) create mode 100644 test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/args create mode 100644 test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/input.sol create mode 100644 test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/output create mode 100644 test/libsolidity/memoryGuardTests/shadowing_memoryguard_with_inline_assembly_identifiers.sol diff --git a/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/args b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/args new file mode 100644 index 000000000..d0fe39023 --- /dev/null +++ b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/args @@ -0,0 +1 @@ +--ir --debug-info none \ No newline at end of file diff --git a/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/input.sol b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/input.sol new file mode 100644 index 000000000..685bec807 --- /dev/null +++ b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/input.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure { + // NOTE: memoryguard is a builtin but only in pure Yul, not inline assembly. + // NOTE: memoryguard is not a reserved identifier. + // The expectation of this test is to not see the shadowed memoryguard within the generated Yul code but rather + // a mangled version of it + assembly { function memoryguard() {} } + assembly { function f(memoryguard) {} } + assembly { function f() -> memoryguard {} } + assembly { let memoryguard } + } +} diff --git a/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/output b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/output new file mode 100644 index 000000000..842580597 --- /dev/null +++ b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/output @@ -0,0 +1,123 @@ +IR: + +/// @use-src 0:"memoryguard_shadowing_by_inline_assembly_identifiers/input.sol" +object "C_10" { + code { + + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_10() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_10_deployed"), datasize("C_10_deployed")) + + return(_1, datasize("C_10_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_10() { + + } + + } + /// @use-src 0:"memoryguard_shadowing_by_inline_assembly_identifiers/input.sol" + object "C_10_deployed" { + code { + + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + external_fun_f_9() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_f_9() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_9() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function fun_f_9() { + + { + function usr$memoryguard() + { } + } + + { + function usr$f(usr$memoryguard) + { } + } + + { + function usr$f() -> usr$memoryguard + { } + } + + { let usr$memoryguard } + + } + + } + + data ".metadata" hex"" + } + +} diff --git a/test/libsolidity/memoryGuardTests/shadowing_memoryguard_with_inline_assembly_identifiers.sol b/test/libsolidity/memoryGuardTests/shadowing_memoryguard_with_inline_assembly_identifiers.sol new file mode 100644 index 000000000..5152882bb --- /dev/null +++ b/test/libsolidity/memoryGuardTests/shadowing_memoryguard_with_inline_assembly_identifiers.sol @@ -0,0 +1,26 @@ +// NOTE: memoryguard is a builtin but only in pure Yul, not inline assembly. +// NOTE: memoryguard is not a reserved identifier. + +contract C { + constructor() { + // The expectation of this test is to see a 'true' outcome, indicating the memoryguard builtin being used + // due to explicitly marking the inline assembly as memory-safe + + assembly ("memory-safe") { mstore(42, 42) function memoryguard() {} } + assembly ("memory-safe") { mstore(42, 42) function f(memoryguard) {} } + assembly ("memory-safe") { mstore(42, 42) function f() -> memoryguard {} } + assembly ("memory-safe") { mstore(42, 42) let memoryguard } + } + + function f() public pure { + // The expectation of this test is to see a 'false' outcome, indicating the memoryguard builtin not being used + + assembly { mstore(42, 42) function memoryguard() {} } + assembly { mstore(42, 42) function f(memoryguard) {} } + assembly { mstore(42, 42) function f() -> memoryguard {} } + assembly { mstore(42, 42) let memoryguard } + } +} +// ---- +// :C(creation) true +// :C(runtime) false From 273a6a4569d928d2e19b842afa6fe60db2ff6fe7 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 3 Mar 2025 14:47:55 +0100 Subject: [PATCH 0759/1340] Bump minimum Node.js version for Solc-Js to v12 --- Changelog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changelog.md b/Changelog.md index 65c04b106..13cc8db13 100644 --- a/Changelog.md +++ b/Changelog.md @@ -38,6 +38,10 @@ Build system: * Linux release builds are fully static again and no longer depend on ``glibc``. * Switch from C++17 to C++20 as the target standard. + +Solc-Js: + * The wrapper now requires at least nodejs v12. + ### 0.8.28 (2024-10-09) Language Features: From e1956d9fdca088e1af94e940c2556681757f0bb8 Mon Sep 17 00:00:00 2001 From: comfsrt <155266597+comfsrt@users.noreply.github.com> Date: Wed, 5 Mar 2025 16:22:39 +0100 Subject: [PATCH 0760/1340] fix errors in comments (#15822) * Update libsolc.cpp * Update ControlFlowBuilder.h * Update ABI.h --- libsolc/libsolc.cpp | 2 +- libsolidity/analysis/ControlFlowBuilder.h | 2 +- libsolidity/interface/ABI.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolc/libsolc.cpp b/libsolc/libsolc.cpp index b49905130..47dddb3ae 100644 --- a/libsolc/libsolc.cpp +++ b/libsolc/libsolc.cpp @@ -63,7 +63,7 @@ std::string takeOverAllocation(char const* _data) abort(); } -/// Resizes a std::std::string to the proper length based on the occurrence of a zero terminator. +/// Resizes a std::string to the proper length based on the occurrence of a zero terminator. void truncateCString(std::string& _data) { size_t pos = _data.find('\0'); diff --git a/libsolidity/analysis/ControlFlowBuilder.h b/libsolidity/analysis/ControlFlowBuilder.h index 93bc52bd6..7af843fca 100644 --- a/libsolidity/analysis/ControlFlowBuilder.h +++ b/libsolidity/analysis/ControlFlowBuilder.h @@ -137,7 +137,7 @@ class ControlFlowBuilder: private ASTConstVisitor, private yul::ASTWalker } /// Merges the control flow of @a _nodes to @a _endNode. - /// If @a _endNode is nullptr, a new node is creates and used as end node. + /// If @a _endNode is nullptr, a new node is created and used as end node. /// Sets the merge destination as current node. /// Note: @a _endNode may be one of the nodes in @a _nodes. template diff --git a/libsolidity/interface/ABI.h b/libsolidity/interface/ABI.h index 22e306c43..65f130247 100644 --- a/libsolidity/interface/ABI.h +++ b/libsolidity/interface/ABI.h @@ -37,7 +37,7 @@ class ABI public: /// Get the ABI Interface of the contract /// @param _contractDef The contract definition - /// @return A JSONrepresentation of the contract's ABI Interface + /// @return A JSON representation of the contract's ABI Interface static Json generate(ContractDefinition const& _contractDef); private: /// @returns a json value suitable for a list of types in function input or output From e745feabeffaa6bb78cc9304f858bc0a9efca13d Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Fri, 20 Dec 2024 16:17:38 -0300 Subject: [PATCH 0761/1340] Add and update tests --- libsolidity/interface/CompilerStack.cpp | 3 - .../args | 1 - .../err | 5 - .../exit | 1 - .../stdin | 4 - .../args | 1 - .../err | 5 - .../exit | 1 - .../storage_layout_specifier_smoke/args | 1 + .../storage_layout_specifier_smoke/output | 85 ++++ .../storage_layout_specifier_smoke/stdin | 9 + .../args | 1 + .../output | 20 + .../stdin | 4 +- .../args | 1 + .../output | 435 ++++++++++++++++++ .../stdin | 31 ++ .../args | 1 - .../err | 1 - .../exit | 1 - .../output | 2 - .../stdin | 4 - .../base_slot_max_value.sol | 7 + .../storageLayoutSpecifier/constructor.sol | 29 ++ .../storageLayoutSpecifier/delete.sol | 30 ++ .../delete_transient_storage.sol | 20 + .../dynamic_array_storage_end.sol | 29 ++ .../function_from_base_contract.sol | 30 ++ .../storageLayoutSpecifier/getters.sol | 9 + .../inheritance_from_abstract_contract.sol | 17 + .../inheritance_from_interface.sol | 15 + ...ritance_from_same_base_state_var_slots.sol | 47 ++ .../inheritance_simple.sol | 16 + ...inheritance_state_variable_slot_offset.sol | 19 + .../inline_assembly_direct_load.sol | 12 + .../inline_assembly_direct_store.sol | 12 + .../last_allowed_storage_slot.sol | 10 + .../mapping_storage_end.sol | 22 + .../multiple_inheritance.sol | 40 ++ .../multiple_inheritance_state_var_slots.sol | 24 + .../state_variable_arithmetic_expression.sol | 20 + .../state_variable_constant_and_immutable.sol | 16 + .../state_variable_dynamic_array.sol | 50 ++ .../state_variable_enum.sol | 18 + .../state_variable_mapping.sol | 33 ++ ...e_variable_reference_types_slot_offset.sol | 33 ++ .../state_variable_slot_offset.sol | 13 + .../state_variable_struct.sol | 39 ++ .../state_variables_transient.sol | 23 + .../storage_reference_array.sol | 21 + .../storage_reference_inheritance.sol | 25 + .../storage_reference_library_function.sol | 31 ++ .../transient_state_variable_slot_offset.sol | 18 + .../variable_cleanup.sol | 15 + .../variable_cleanup_sstore.sol | 20 + .../virtual_functions.sol | 34 ++ ..._contract_inheriting_from_non_abstract.sol | 4 + .../contract_named_at.sol | 1 - .../contract_named_layout.sol | 1 - ...tract_with_members_named_layout_and_at.sol | 1 - .../inheriting_from_abstract_contract.sol | 1 - .../inheriting_from_interface.sol | 1 - .../intermediate_operation_out_of_range.sol | 1 - ...layout_specification_binary_expression.sol | 1 - .../layout_specification_max_value.sol | 1 - .../layout_with_inheritance.sol | 1 - .../literal_with_underscore.sol | 1 - .../multi_token_expression.sol | 1 - .../rational_number_zero_fractional_part.sol | 1 - .../same_ancestor_two_contracts.sol | 1 - .../storageLayoutSpecifier/simple_layout.sol | 1 - 71 files changed, 1387 insertions(+), 45 deletions(-) delete mode 100644 test/cmdlineTests/storage_layout_specifier_codegen_error/args delete mode 100644 test/cmdlineTests/storage_layout_specifier_codegen_error/err delete mode 100644 test/cmdlineTests/storage_layout_specifier_codegen_error/exit delete mode 100644 test/cmdlineTests/storage_layout_specifier_codegen_error/stdin delete mode 100644 test/cmdlineTests/storage_layout_specifier_ir_codegen_error/args delete mode 100644 test/cmdlineTests/storage_layout_specifier_ir_codegen_error/err delete mode 100644 test/cmdlineTests/storage_layout_specifier_ir_codegen_error/exit create mode 100644 test/cmdlineTests/storage_layout_specifier_smoke/args create mode 100644 test/cmdlineTests/storage_layout_specifier_smoke/output create mode 100644 test/cmdlineTests/storage_layout_specifier_smoke/stdin create mode 100644 test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/args create mode 100644 test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/output rename test/cmdlineTests/{storage_layout_specifier_ir_codegen_error => storage_layout_specifier_smoke_ir_codegen}/stdin (57%) create mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output/args create mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output/output create mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output/stdin delete mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/args delete mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/err delete mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/exit delete mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/output delete mode 100644 test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/stdin create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/base_slot_max_value.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/constructor.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/delete.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/delete_transient_storage.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/dynamic_array_storage_end.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/function_from_base_contract.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/getters.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_abstract_contract.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_interface.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_same_base_state_var_slots.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_simple.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_state_variable_slot_offset.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_load.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_store.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/last_allowed_storage_slot.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/mapping_storage_end.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance_state_var_slots.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_arithmetic_expression.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_constant_and_immutable.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_enum.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_mapping.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_reference_types_slot_offset.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_slot_offset.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_struct.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/state_variables_transient.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_array.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_inheritance.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_library_function.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/transient_state_variable_slot_offset.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup_sstore.sol create mode 100644 test/libsolidity/semanticTests/storageLayoutSpecifier/virtual_functions.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract_inheriting_from_non_abstract.sol diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 9582939f5..60ebd7642 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1114,7 +1114,6 @@ Json const& CompilerStack::storageLayout(Contract const& _contract) const solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); solAssert(_contract.contract); solUnimplementedAssert(!isExperimentalSolidity()); - solUnimplementedAssert(!_contract.contract->storageLayoutSpecifier(), "Storage layout not supported for contract with specified layout base."); return _contract.storageLayout.init([&]{ return StorageLayout().generate(*_contract.contract, DataLocation::Storage); }); } @@ -1539,7 +1538,6 @@ void CompilerStack::compileContract( solAssert(!m_viaIR, ""); solUnimplementedAssert(!m_eofVersion.has_value(), "Experimental EOF support is only available for via-IR compilation."); solAssert(m_stackState >= AnalysisSuccessful, ""); - solUnimplementedAssert(!_contract.storageLayoutSpecifier(), "Code generation is not supported for contracts with specified storage layout base."); if (_otherCompilers.count(&_contract)) return; @@ -1575,7 +1573,6 @@ void CompilerStack::compileContract( void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unoptimizedOnly) { solAssert(m_stackState >= AnalysisSuccessful, ""); - solUnimplementedAssert(!_contract.storageLayoutSpecifier(), "Code generation is not supported for contracts with specified storage layout base."); Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName()); if (compiledContract.yulIR) { diff --git a/test/cmdlineTests/storage_layout_specifier_codegen_error/args b/test/cmdlineTests/storage_layout_specifier_codegen_error/args deleted file mode 100644 index ccc12f642..000000000 --- a/test/cmdlineTests/storage_layout_specifier_codegen_error/args +++ /dev/null @@ -1 +0,0 @@ ---asm - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_codegen_error/err b/test/cmdlineTests/storage_layout_specifier_codegen_error/err deleted file mode 100644 index d1012053f..000000000 --- a/test/cmdlineTests/storage_layout_specifier_codegen_error/err +++ /dev/null @@ -1,5 +0,0 @@ -Error: Code generation is not supported for contracts with specified storage layout base. - --> :4:1: - | -4 | contract C layout at 42 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/storage_layout_specifier_codegen_error/exit b/test/cmdlineTests/storage_layout_specifier_codegen_error/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/storage_layout_specifier_codegen_error/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/storage_layout_specifier_codegen_error/stdin b/test/cmdlineTests/storage_layout_specifier_codegen_error/stdin deleted file mode 100644 index 87066c4d4..000000000 --- a/test/cmdlineTests/storage_layout_specifier_codegen_error/stdin +++ /dev/null @@ -1,4 +0,0 @@ -//SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.0; - -contract C layout at 42 {} \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/args b/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/args deleted file mode 100644 index a84e2a257..000000000 --- a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/args +++ /dev/null @@ -1 +0,0 @@ ---ir --asm - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/err b/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/err deleted file mode 100644 index d1012053f..000000000 --- a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/err +++ /dev/null @@ -1,5 +0,0 @@ -Error: Code generation is not supported for contracts with specified storage layout base. - --> :4:1: - | -4 | contract C layout at 42 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/exit b/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/storage_layout_specifier_smoke/args b/test/cmdlineTests/storage_layout_specifier_smoke/args new file mode 100644 index 000000000..b207f3bab --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_smoke/args @@ -0,0 +1 @@ +--no-cbor-metadata --optimize --asm --debug-info none - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_smoke/output b/test/cmdlineTests/storage_layout_specifier_smoke/output new file mode 100644 index 000000000..d1c54c99b --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_smoke/output @@ -0,0 +1,85 @@ + +======= :C ======= +EVM assembly: + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + tag_2: + revert(0x00, 0x00) + tag_3: + tag_4 + tag_5 + jump // in + tag_4: + stop + tag_5: + sload(0x0abc) + tag_7 + swap1 + 0x01 + tag_8 + jump // in + tag_7: + 0x0abc + sstore + jump // out + tag_8: + dup1 + dup3 + add + dup1 + dup3 + gt + iszero + tag_11 + jumpi + 0x4e487b71 + 0xe0 + shl + 0x00 + mstore + 0x11 + 0x04 + mstore + 0x24 + 0x00 + revert + tag_11: + swap3 + swap2 + pop + pop + jump // out +} diff --git a/test/cmdlineTests/storage_layout_specifier_smoke/stdin b/test/cmdlineTests/storage_layout_specifier_smoke/stdin new file mode 100644 index 000000000..7e6575fef --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_smoke/stdin @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0.0; + +contract C layout at 0xABC { + uint x; + function f() public { + x = x + 1; + } +} diff --git a/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/args b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/args new file mode 100644 index 000000000..9ad276caf --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/args @@ -0,0 +1 @@ +--optimize --ir-optimized --debug-info none - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/output b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/output new file mode 100644 index 000000000..de5fd5374 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/output @@ -0,0 +1,20 @@ +Optimized IR: +/// @use-src 0:"" +object "C_7" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + sstore(0x2a, 0x0a) + let _2 := datasize("C_7_deployed") + codecopy(_1, dataoffset("C_7_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"" + object "C_7_deployed" { + code { { revert(0, 0) } } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/stdin b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/stdin similarity index 57% rename from test/cmdlineTests/storage_layout_specifier_ir_codegen_error/stdin rename to test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/stdin index 87066c4d4..c3dbe062f 100644 --- a/test/cmdlineTests/storage_layout_specifier_ir_codegen_error/stdin +++ b/test/cmdlineTests/storage_layout_specifier_smoke_ir_codegen/stdin @@ -1,4 +1,6 @@ //SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.0; -contract C layout at 42 {} \ No newline at end of file +contract C layout at 42 { + uint x = 10; +} \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output/args b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/args new file mode 100644 index 000000000..b8163df7a --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/args @@ -0,0 +1 @@ +--storage-layout --transient-storage-layout --pretty-json --json-indent 4 - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output/output b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/output new file mode 100644 index 000000000..7e5e61de0 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/output @@ -0,0 +1,435 @@ + +======= :A ======= +Contract Storage Layout: +{ + "storage": [ + { + "astId": 3, + "contract": ":A", + "label": "x", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 7, + "contract": ":A", + "label": "y", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} +Contract Transient Storage Layout: +{ + "storage": [ + { + "astId": 5, + "contract": ":A", + "label": "t1", + "offset": 0, + "slot": "0", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} + +======= :B ======= +Contract Storage Layout: +{ + "storage": [ + { + "astId": 12, + "contract": ":B", + "label": "w", + "offset": 0, + "slot": "0", + "type": "t_int8" + } + ], + "types": { + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + } + } +} +Contract Transient Storage Layout: +{ + "storage": [ + { + "astId": 10, + "contract": ":B", + "label": "t2", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 14, + "contract": ":B", + "label": "t3", + "offset": 0, + "slot": "1", + "type": "t_int8" + } + ], + "types": { + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} + +======= :C ======= +Contract Storage Layout: +{ + "storage": [ + { + "astId": 12, + "contract": ":C", + "label": "w", + "offset": 0, + "slot": "0", + "type": "t_int8" + }, + { + "astId": 19, + "contract": ":C", + "label": "z", + "offset": 1, + "slot": "0", + "type": "t_uint128" + }, + { + "astId": 21, + "contract": ":C", + "label": "b", + "offset": 17, + "slot": "0", + "type": "t_bool" + } + ], + "types": { + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + } + } +} +Contract Transient Storage Layout: +{ + "storage": [ + { + "astId": 10, + "contract": ":C", + "label": "t2", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 14, + "contract": ":C", + "label": "t3", + "offset": 0, + "slot": "1", + "type": "t_int8" + }, + { + "astId": 23, + "contract": ":C", + "label": "t4", + "offset": 1, + "slot": "1", + "type": "t_bool" + } + ], + "types": { + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} + +======= :D ======= +Contract Storage Layout: +{ + "storage": [ + { + "astId": 3, + "contract": ":D", + "label": "x", + "offset": 0, + "slot": "100", + "type": "t_uint256" + }, + { + "astId": 7, + "contract": ":D", + "label": "y", + "offset": 0, + "slot": "101", + "type": "t_uint256" + }, + { + "astId": 12, + "contract": ":D", + "label": "w", + "offset": 0, + "slot": "102", + "type": "t_int8" + }, + { + "astId": 19, + "contract": ":D", + "label": "z", + "offset": 1, + "slot": "102", + "type": "t_uint128" + }, + { + "astId": 21, + "contract": ":D", + "label": "b", + "offset": 17, + "slot": "102", + "type": "t_bool" + }, + { + "astId": 32, + "contract": ":D", + "label": "addr", + "offset": 0, + "slot": "103", + "type": "t_address" + }, + { + "astId": 38, + "contract": ":D", + "label": "array", + "offset": 0, + "slot": "104", + "type": "t_array(t_uint256)2_storage" + }, + { + "astId": 42, + "contract": ":D", + "label": "m", + "offset": 0, + "slot": "106", + "type": "t_mapping(t_uint256,t_address)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)2_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[2]", + "numberOfBytes": "64" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + }, + "t_mapping(t_uint256,t_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} +Contract Transient Storage Layout: +{ + "storage": [ + { + "astId": 5, + "contract": ":D", + "label": "t1", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 10, + "contract": ":D", + "label": "t2", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 14, + "contract": ":D", + "label": "t3", + "offset": 0, + "slot": "2", + "type": "t_int8" + }, + { + "astId": 23, + "contract": ":D", + "label": "t4", + "offset": 1, + "slot": "2", + "type": "t_bool" + }, + { + "astId": 34, + "contract": ":D", + "label": "t5", + "offset": 2, + "slot": "2", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_int8": { + "encoding": "inplace", + "label": "int8", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} + +======= :P ======= +Contract Storage Layout: +{ + "storage": [ + { + "astId": 3, + "contract": ":P", + "label": "x", + "offset": 0, + "slot": "200", + "type": "t_uint256" + }, + { + "astId": 7, + "contract": ":P", + "label": "y", + "offset": 0, + "slot": "201", + "type": "t_uint256" + }, + { + "astId": 49, + "contract": ":P", + "label": "q", + "offset": 0, + "slot": "202", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} +Contract Transient Storage Layout: +{ + "storage": [ + { + "astId": 5, + "contract": ":P", + "label": "t1", + "offset": 0, + "slot": "0", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } +} diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output/stdin b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/stdin new file mode 100644 index 000000000..ac391d192 --- /dev/null +++ b/test/cmdlineTests/storage_layout_specifier_storage_layout_output/stdin @@ -0,0 +1,31 @@ +//SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +abstract contract A { + uint x; + uint transient t1; + uint y; +} + +contract B { + uint transient t2; + int8 w; + int8 transient t3; +} + +contract C is B { + uint128 z; + bool b; + bool transient t4; +} + +contract D is A, C layout at 100 { + address addr; + address transient t5; + uint[2] array; + mapping(uint => address) m; +} + +contract P is A layout at 200 { + uint q; +} \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/args b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/args deleted file mode 100644 index 93090d6aa..000000000 --- a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/args +++ /dev/null @@ -1 +0,0 @@ ---storage-layout - \ No newline at end of file diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/err b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/err deleted file mode 100644 index 58e52d14a..000000000 --- a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/err +++ /dev/null @@ -1 +0,0 @@ -Error: Storage layout not supported for contract with specified layout base. diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/exit b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/output b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/output deleted file mode 100644 index c90881588..000000000 --- a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/output +++ /dev/null @@ -1,2 +0,0 @@ - -======= :C ======= diff --git a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/stdin b/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/stdin deleted file mode 100644 index 87066c4d4..000000000 --- a/test/cmdlineTests/storage_layout_specifier_storage_layout_output_error/stdin +++ /dev/null @@ -1,4 +0,0 @@ -//SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.0; - -contract C layout at 42 {} \ No newline at end of file diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/base_slot_max_value.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/base_slot_max_value.sol new file mode 100644 index 000000000..e46543762 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/base_slot_max_value.sol @@ -0,0 +1,7 @@ +contract C layout at 2**256 - 1 { + function f(uint a) public pure returns (uint) { + return a * 2; + } +} +// ---- +// f(uint256): 4 -> 8 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/constructor.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/constructor.sol new file mode 100644 index 000000000..c30f9dab9 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/constructor.sol @@ -0,0 +1,29 @@ +contract A { + uint public x; +} + +contract B is A { + int8 public y; +} + +contract C is B layout at 7 { + uint32 public z; + + constructor(uint _x, int8 _y, uint32 _z) { + x = _x + 1; + y = _y + 2; + z = _z + 3; + } + +} +// ---- +// constructor(): 1, 2, 3 +// gas irOptimized: 104178 +// gas irOptimized code: 30000 +// gas legacy: 114749 +// gas legacy code: 71400 +// gas legacyOptimized: 106296 +// gas legacyOptimized code: 31400 +// x() -> 2 +// y() -> 4 +// z() -> 6 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/delete.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/delete.sol new file mode 100644 index 000000000..a6cc84cce --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/delete.sol @@ -0,0 +1,30 @@ +contract C layout at 42 { + uint[] public array; + + function fillArray() public returns (uint) { + array.push(1); + array.push(2); + array.push(3); + return array.length; + } + function deleteLast() public { + delete array[array.length - 1]; + } + function deleteArray() public { + delete array; + } + function arrayLength() public returns (uint) { + return array.length; + } +} +// ---- +// fillArray() -> 3 +// gas irOptimized: 111121 +// gas legacy: 110730 +// gas legacyOptimized: 110307 +// arrayLength() -> 3 +// array(uint256): 2 -> 3 +// deleteLast() -> +// array(uint256): 2 -> 0 +// deleteArray() -> +// arrayLength() -> 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/delete_transient_storage.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/delete_transient_storage.sol new file mode 100644 index 000000000..b651e0e88 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/delete_transient_storage.sol @@ -0,0 +1,20 @@ +contract C layout at 42 { + uint transient x; + address transient a; + + function f() public { + g(); + delete x; + delete a; + assert(x == 0); + assert(a == address(0)); + } + function g() public { + x = 99; + a = address(0x1234); + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// f() -> \ No newline at end of file diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/dynamic_array_storage_end.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/dynamic_array_storage_end.sol new file mode 100644 index 000000000..54eabe844 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/dynamic_array_storage_end.sol @@ -0,0 +1,29 @@ +contract C layout at 2**256 - 2 { + uint[] array; + + function init() public { + for (uint i = 0; i < 1000; ++i) + array.push(i + 1); + } + function validate() public { + for (uint i = 0; i < 1000; ++i) + require(array[i] == i + 1); + } + function clear() public { + for (uint i = 0; i < 1000; ++i) + array.pop(); + } +} +// ---- +// init() -> +// gas irOptimized: 22738151 +// gas legacy: 22699167 +// gas legacyOptimized: 22541160 +// validate() -> +// gas irOptimized: 2444232 +// gas legacy: 2560245 +// gas legacyOptimized: 2442238 +// clear() -> +// gas irOptimized: 4449608 +// gas legacy: 4300019 +// gas legacyOptimized: 4302413 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/function_from_base_contract.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/function_from_base_contract.sol new file mode 100644 index 000000000..004997c22 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/function_from_base_contract.sol @@ -0,0 +1,30 @@ +contract A { + uint public x; + function f() public returns (uint) { + x = x + 1; + return x; + } +} + +contract B is A { + uint public y; + function g() public virtual returns (uint) { + y = y + 2; + return y; + } +} + +contract C is B layout at 42 { + uint public z; + function test() public returns (uint){ + z = super.g() + A.f(); + return z; + } +} +// ---- +// f() -> 1 +// g() -> 2 +// test() -> 6 +// x() -> 2 +// y() -> 4 +// z() -> 6 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/getters.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/getters.sol new file mode 100644 index 000000000..62a75e7d5 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/getters.sol @@ -0,0 +1,9 @@ +contract C layout at 7 { + uint public x = 1; + int8 public y = 2; + uint32 public z = 3; +} +// ---- +// x() -> 1 +// y() -> 2 +// z() -> 3 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_abstract_contract.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_abstract_contract.sol new file mode 100644 index 000000000..fdf68994b --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_abstract_contract.sol @@ -0,0 +1,17 @@ +abstract contract A { + uint public x; +} + +contract C is A layout at 42 { + uint public y; + function f() public returns (uint) { + x = 12; + x = x - 4; + y = x + 2; + return y; + } +} +// ---- +// f() -> 10 +// x() -> 8 +// y() -> 10 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_interface.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_interface.sol new file mode 100644 index 000000000..8874f28f2 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_interface.sol @@ -0,0 +1,15 @@ +interface I { + function f(uint x) external returns (uint); +} + +contract C is I layout at 42 { + uint public y; + function f(uint x) public returns (uint) { + x = x - 4; + y = x + 2; + return y; + } +} +// ---- +// f(uint256): 8 -> 6 +// y() -> 6 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_same_base_state_var_slots.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_same_base_state_var_slots.sol new file mode 100644 index 000000000..554c3fcd7 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_from_same_base_state_var_slots.sol @@ -0,0 +1,47 @@ +contract A { + uint public x; + function xSlot() public view returns (uint xs) { + assembly { + xs := x.slot + } + } +} + +contract B is A layout at 5 { + uint public y; + function xAndYSlots() public view returns (uint xs, uint ys) { + assembly { + xs := x.slot + ys := y.slot + } + } +} + +contract C is A layout at 9 { + uint public z; + function xAndZSlots() public view returns (uint xs, uint zs) { + assembly { + xs := x.slot + zs := z.slot + } + } +} + +contract Test { + A a = new A(); + B b = new B(); + C c = new C(); + function contractASlots() public view returns (uint) { + return a.xSlot(); + } + function contractBSlots() public view returns (uint, uint) { + return b.xAndYSlots(); + } + function contractCSlots() public view returns (uint, uint) { + return c.xAndZSlots(); + } +} +// ---- +// contractASlots() -> 0 +// contractBSlots() -> 5, 6 +// contractCSlots() -> 9, 10 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_simple.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_simple.sol new file mode 100644 index 000000000..a4eeee5f2 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_simple.sol @@ -0,0 +1,16 @@ +contract A { + uint public x = 10; +} + +contract C is A layout at 42 { + uint public y; + function f() public returns (uint) { + x = x - 4; + y = x + 2; + return y; + } +} +// ---- +// f() -> 8 +// x() -> 6 +// y() -> 8 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_state_variable_slot_offset.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_state_variable_slot_offset.sol new file mode 100644 index 000000000..73304d622 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inheritance_state_variable_slot_offset.sol @@ -0,0 +1,19 @@ +contract A { + uint x; + uint128 y; +} + +contract C is A layout at 7 { + uint32 w; + uint z; + + function xSlotOffset() public returns(uint s, uint o) { assembly { s := x.slot o := x.offset } } + function ySlotOffset() public returns(uint s, uint o) { assembly { s := y.slot o := y.offset } } + function wSlotOffset() public returns(uint s, uint o) { assembly { s := w.slot o := w.offset } } + function zSlotOffset() public returns(uint s, uint o) { assembly { s := z.slot o := z.offset } } +} +// ---- +// xSlotOffset() -> 7, 0 +// ySlotOffset() -> 8, 0 +// wSlotOffset() -> 8, 16 +// zSlotOffset() -> 9, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_load.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_load.sol new file mode 100644 index 000000000..9f5a5491d --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_load.sol @@ -0,0 +1,12 @@ +contract C layout at 42 { + uint public x; + function f() public returns (uint r) { + x = 16; + assembly { + r := sload(42) + } + } +} +// ---- +// f() -> 16 +// x() -> 16 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_store.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_store.sol new file mode 100644 index 000000000..6ea695e66 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/inline_assembly_direct_store.sol @@ -0,0 +1,12 @@ +contract C layout at 42 { + uint public x; + function f() public returns (uint) { + assembly { + sstore(42, 16) + } + return x; + } +} +// ---- +// f() -> 16 +// x() -> 16 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/last_allowed_storage_slot.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/last_allowed_storage_slot.sol new file mode 100644 index 000000000..89900c0f6 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/last_allowed_storage_slot.sol @@ -0,0 +1,10 @@ +contract C layout at 2**256 - 2 { + uint public x; + function f(uint a) public returns (uint) { + x = a * 2; + return x; + } +} +// ---- +// f(uint256): 4 -> 8 +// x() -> 8 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/mapping_storage_end.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/mapping_storage_end.sol new file mode 100644 index 000000000..9745850c0 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/mapping_storage_end.sol @@ -0,0 +1,22 @@ +contract C layout at 2**256 - 2 { + mapping(uint => uint) m; + + function init() public { + for (uint i = 0; i < 1000; ++i) + m[i] = i + 1; + } + + function validate() public { + for (uint i = 0; i < 1000; ++i) + require(m[i] == i + 1); + } +} +// ---- +// init() -> +// gas irOptimized: 22266229 +// gas legacy: 22447245 +// gas legacyOptimized: 22310238 +// validate() -> +// gas irOptimized: 2279210 +// gas legacy: 2456223 +// gas legacyOptimized: 2327216 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance.sol new file mode 100644 index 000000000..1b24b4961 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance.sol @@ -0,0 +1,40 @@ +contract A { + uint public x; + function f(uint a) public { + x = a; + } +} + +contract B is A { + uint public y; + function g(uint a) public { + f(x + a); + y = x + 1; + } +} + +contract C is B { + uint public w; + function h(uint a) public { + g(a); + w = x + y; + } +} + +contract D is A, B, C layout at 42 { + uint public z; + function test() public returns (uint, uint, uint, uint) { + h(1); + z = w + 2; + return (x, y, w, z); + } +} +// ---- +// test() -> 1, 2, 3, 5 +// gas irOptimized: 110112 +// gas legacy: 111881 +// gas legacyOptimized: 110945 +// x() -> 1 +// y() -> 2 +// w() -> 3 +// z() -> 5 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance_state_var_slots.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance_state_var_slots.sol new file mode 100644 index 000000000..dd75b1d25 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/multiple_inheritance_state_var_slots.sol @@ -0,0 +1,24 @@ +contract A { + uint x; +} + +contract B is A { + uint32 y; +} + +contract C is B { + uint160 w; +} + +contract D is A, B, C layout at 2 { + uint z; + function xSlotOffset() public view returns (uint s, uint o) { assembly { s := x.slot o := x.offset } } + function ySlotOffset() public view returns (uint s, uint o) { assembly { s := y.slot o := y.offset } } + function wSlotOffset() public view returns (uint s, uint o) { assembly { s := w.slot o := w.offset } } + function zSlotOffset() public view returns (uint s, uint o) { assembly { s := z.slot o := z.offset } } +} +// ---- +// xSlotOffset() -> 2, 0 +// ySlotOffset() -> 3, 0 +// wSlotOffset() -> 3, 4 +// zSlotOffset() -> 4, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_arithmetic_expression.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_arithmetic_expression.sol new file mode 100644 index 000000000..5dacc81ba --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_arithmetic_expression.sol @@ -0,0 +1,20 @@ +contract C layout at 7 { + uint public x; + uint public y; + uint public z; + + function f(uint a) public returns (uint) { + x = x + a; + y = y + x; + z = y - 2; + + return z; + } +} +// ---- +// f(uint256): 2 -> 0 +// f(uint256): 3 -> 5 +// f(uint256): 5 -> 15 +// x() -> 10 +// y() -> 17 +// z() -> 15 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_constant_and_immutable.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_constant_and_immutable.sol new file mode 100644 index 000000000..6489b1e6b --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_constant_and_immutable.sol @@ -0,0 +1,16 @@ +contract C layout at 42 { + uint constant x = 10; + uint immutable y = 100; + + function f() public view returns (uint) { + require(x > 9); + return x + 1; + } + function g() public view returns (uint) { + require(y > 99); + return y * 2; + } +} +// ---- +// f() -> 11 +// g() -> 200 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol new file mode 100644 index 000000000..1737c35bb --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol @@ -0,0 +1,50 @@ +contract A { + uint[] public arrayA; +} + +contract C is A layout at 42 { + uint[] public arrayC; + + function initA() public returns (uint, uint, uint) { + arrayA.push(1); + arrayA.push(2); + arrayA.push(3); + + return (arrayA[0], arrayA[1], arrayA[2]); + } + function initCFromAInReverse() public returns (uint, uint, uint) { + arrayC = new uint[](3); + arrayC[0] = arrayA[2]; + arrayC[1] = arrayA[1]; + arrayC[2] = arrayA[0]; + + return (arrayC[0], arrayC[1], arrayC[2]); + } + function clearA () public { + arrayA.pop(); + arrayA.pop(); + arrayA.pop(); + } + function arrayALength() public returns (uint) { + return arrayA.length; + } + function arrayCLength() public returns (uint) { + return arrayC.length; + } +} +// ---- +// initA() -> 1, 2, 3 +// gas irOptimized: 111986 +// gas legacy: 111679 +// gas legacyOptimized: 111150 +// arrayA(uint256): 0 -> 1 +// arrayALength() -> 3 +// arrayCLength() -> 0 +// initCFromAInReverse() -> 3, 2, 1 +// gas irOptimized: 121276 +// gas legacy: 121213 +// gas legacyOptimized: 120843 +// clearA() -> +// arrayC(uint256): 0 -> 3 +// arrayALength() -> 0 +// arrayCLength() -> 3 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_enum.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_enum.sol new file mode 100644 index 000000000..663282616 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_enum.sol @@ -0,0 +1,18 @@ +enum Color {Red, Blue, Green } +contract C layout at 42 { + Color c; + function cSlotOffset() public returns(uint s, uint o) { + assembly { s := c.slot o := c.offset } + } + function setBlue() public { + c = Color.Blue; + } + function checkBlue() public view returns (bool) { + return c == Color.Blue; + } +} +// ---- +// cSlotOffset() -> 42, 0 +// checkBlue() -> false +// setBlue() -> +// checkBlue() -> true diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_mapping.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_mapping.sol new file mode 100644 index 000000000..e33df29ea --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_mapping.sol @@ -0,0 +1,33 @@ +contract A { + mapping(uint => bool) locked; +} +contract C layout at 42 is A { + mapping(uint => string) rooms; + + function setup() public { + locked[0] = true; + locked[1] = false; + locked[2] = true; + locked[3] = false; + + rooms[0] = "Empty"; + rooms[1] = "Monster"; + rooms[2] = "Treasure"; + rooms[3] = "Empty"; + } + function open(uint x) public view returns (string memory) { + if (locked[x]) + return "Locked"; + + require(!locked[x]); + return rooms[x]; + } +} +// ---- +// setup() -> +// gas irOptimized: 159082 +// gas legacy: 161738 +// gas legacyOptimized: 160222 +// open(uint256): 3 -> 0x20, 5, "Empty" +// open(uint256): 2 -> 0x20, 6, "Locked" +// open(uint256): 1 -> 0x20, 7, "Monster" diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_reference_types_slot_offset.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_reference_types_slot_offset.sol new file mode 100644 index 000000000..30cbed7f3 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_reference_types_slot_offset.sol @@ -0,0 +1,33 @@ +struct S { + uint x; + address a; + bool b; +} + +contract A { + S public s1; + uint transient t1; +} + +contract C is A layout at 42 { + uint transient t2; + S[][5] dArray; + uint[10][2] sArray; + bytes bArray; + string str; + + + function s1SlotOffset() public returns (uint s, uint o) { assembly { s:= s1.slot o:= s1.offset } } + function dArraySlotOffset() public returns (uint s, uint o) { assembly { s:= dArray.slot o:= dArray.offset } } + function sArraySlotOffset() public returns (uint s, uint o) { assembly { s:= sArray.slot o:= sArray.offset } } + function bArraySlotOffset() public returns (uint s, uint o) { assembly { s:= bArray.slot o:= bArray.offset } } + function strSlotOffset() public returns (uint s, uint o) { assembly { s:= str.slot o:= str.offset } } +} +// ==== +// EVMVersion: >=cancun +// ---- +// s1SlotOffset() -> 42, 0 +// dArraySlotOffset() -> 44, 0 +// sArraySlotOffset() -> 49, 0 +// bArraySlotOffset() -> 69, 0 +// strSlotOffset() -> 70, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_slot_offset.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_slot_offset.sol new file mode 100644 index 000000000..1ce5207eb --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_slot_offset.sol @@ -0,0 +1,13 @@ +contract C layout at 7 { + int8 public x; + int32 public y; + uint256 public z; + + function xSlotOffset() public returns(uint s, uint o) { assembly { s := x.slot o := x.offset } } + function ySlotOffset() public returns(uint s, uint o) { assembly { s := y.slot o := y.offset } } + function zSlotOffset() public returns(uint s, uint o) { assembly { s := z.slot o := z.offset } } +} +// ---- +// xSlotOffset() -> 7, 0 +// ySlotOffset() -> 7, 1 +// zSlotOffset() -> 8, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_struct.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_struct.sol new file mode 100644 index 000000000..5b2b6d558 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_struct.sol @@ -0,0 +1,39 @@ +struct S { + uint x; + address a; + bool b; +} + +contract A { + S public s1; + uint transient t1; +} + +contract C is A layout at 42 { + uint y; + uint8 z; + uint transient t2; + S public s2; + + function initS1() public returns (uint, address, bool) { + s1.x = 7; + s1.a = address(0xABC); + s1.b = true; + + return (s1.x, s1.a, s1.b); + } + function initS2() public returns (uint, address, bool) { + s2.x = 8; + s2.a = address(0xDEF); + s2.b = false; + + return (s2.x, s2.a, s2.b); + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// initS1() -> 7, 0x0abc, 1 +// initS2() -> 8, 0x0def, 0 +// s1() -> 7, 0x0abc, 1 +// s2() -> 8, 0x0def, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variables_transient.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variables_transient.sol new file mode 100644 index 000000000..0c1e0a78a --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variables_transient.sol @@ -0,0 +1,23 @@ +contract C layout at 42 { + int x; + bool transient lock; + + function test() public returns(int) { + x = -1; + lock = true; + f(); + return x; + } + function f() private { + lock = false; + setX(); + } + function setX() private { + require(!lock); + x = 2; + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// test() -> 2 \ No newline at end of file diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_array.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_array.sol new file mode 100644 index 000000000..db14ef558 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_array.sol @@ -0,0 +1,21 @@ +contract C layout at 42 { + uint[] public array; + function initUsingReference() public { + uint[] storage ptr = array; + for(uint i = 0; i < 10; ++i) + ptr.push(i + 1); + + validate(array); + } + function validate(uint[] memory ptr) public pure { + for(uint i = 0; i < 10; ++i) + require(ptr[i] == i + 1); + } +} +// ---- +// initUsingReference() -> +// gas irOptimized: 273556 +// gas legacy: 274795 +// gas legacyOptimized: 271954 +// array(uint256): 0 -> 1 +// array(uint256): 9 -> 10 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_inheritance.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_inheritance.sol new file mode 100644 index 000000000..1a4ee2e6f --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_inheritance.sol @@ -0,0 +1,25 @@ +pragma abicoder v2; +contract A { + struct S { + uint x; + bool b; + } + S public s; +} + +contract C is A layout at 42 { + function InitUsingReference() public { + S storage ptr = s; + ptr.x = 2; + ptr.b = true; + + validate(s); + } + function validate(S memory ptr) public pure { + require(ptr.x == 2); + require(ptr.b); + } +} +// ---- +// InitUsingReference() -> +// s() -> 2, true diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_library_function.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_library_function.sol new file mode 100644 index 000000000..2d17de248 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/storage_reference_library_function.sol @@ -0,0 +1,31 @@ +pragma abicoder v2; + +struct S { + uint x; + bool b; +} + +library L { + function validate(S memory ptr) public { + require(ptr.x == 2); + require(ptr.b); + } +} + +contract A { + S public s; +} + +contract C is A layout at 42 { + function initUsingReference() public { + S storage ptr = s; + ptr.x = 2; + ptr.b = true; + + L.validate(s); + } +} +// ---- +// library: L +// initUsingReference() -> +// s() -> 2, true diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/transient_state_variable_slot_offset.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/transient_state_variable_slot_offset.sol new file mode 100644 index 000000000..c1d8f911d --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/transient_state_variable_slot_offset.sol @@ -0,0 +1,18 @@ +contract C layout at 7 { + int transient x; + int y; + uint transient w; + uint256 z; + + function xSlotOffset() public returns(uint s, uint o) { assembly { s := x.slot o := x.offset } } + function ySlotOffset() public returns(uint s, uint o) { assembly { s := y.slot o := y.offset } } + function wSlotOffset() public returns(uint s, uint o) { assembly { s := w.slot o := w.offset } } + function zSlotOffset() public returns(uint s, uint o) { assembly { s := z.slot o := z.offset } } +} +// ==== +// EVMVersion: >=cancun +// ---- +// xSlotOffset() -> 0, 0 +// ySlotOffset() -> 7, 0 +// wSlotOffset() -> 1, 0 +// zSlotOffset() -> 8, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup.sol new file mode 100644 index 000000000..33ffc5993 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup.sol @@ -0,0 +1,15 @@ +contract C layout at 42 { + uint8 x; + int8 y; + bytes2 b; + // Note the return types are larger than the state variable ones + function f(uint _x, int _y, bytes3 _b) public returns (uint16, int32, bytes32) { + x = uint8(_x); + y = int8(_y); + b = bytes2(_b); + require(b == "ab"); + return (x, y, b); + } +} +// ---- +// f(uint256,int256,bytes3): 0x0100, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f, "abc" -> 0x00, 0x7f, "ab" diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup_sstore.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup_sstore.sol new file mode 100644 index 000000000..bda660d05 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/variable_cleanup_sstore.sol @@ -0,0 +1,20 @@ +contract C layout at 42 { + uint8 x; + int8 y; + bytes2 b; + // Note the return types are larger than the state variable ones + function f() public returns (uint16, int32, bytes16) { + uint32 z = 0; + z = z | 0x10; + z = z | 0x7f00; + z = z | 0x61620000; + + assembly { + sstore(x.slot, z) + } + require(b == "ab"); + return (x, y, b); + } +} +// ---- +// f() -> 0x10, 127, "ab" diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/virtual_functions.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/virtual_functions.sol new file mode 100644 index 000000000..42c917d18 --- /dev/null +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/virtual_functions.sol @@ -0,0 +1,34 @@ +abstract contract A { + uint public x; + function f() public virtual returns (uint); +} + +contract B is A { + uint public y; + function f() public override returns (uint) { + x = 1; + return x; + } + function g() public virtual returns (uint) { + return y; + } +} + +contract C is B layout at 42 { + uint public z; + function g() public override returns (uint) { + y = x + 2; + return y; + } + function h() public returns (uint) { + z = g() + 3; + return z; + } +} +// ---- +// f() -> 1 +// g() -> 3 +// h() -> 6 +// x() -> 1 +// y() -> 3 +// z() -> 6 diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract_inheriting_from_non_abstract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract_inheriting_from_non_abstract.sol new file mode 100644 index 000000000..73dfa42f3 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abstract_contract_inheriting_from_non_abstract.sol @@ -0,0 +1,4 @@ +contract A layout at 0x1234 {} +abstract contract C is A { } +// ---- +// TypeError 8894: (54-55): Cannot inherit from a contract with a custom storage layout. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol index bbb928cb3..c5127249a 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_at.sol @@ -1,3 +1,2 @@ contract at layout at 0x1234ABC { } // ---- -// UnimplementedFeatureError 1834: (0-35): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol index 5c755d610..111a4fc36 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_named_layout.sol @@ -1,3 +1,2 @@ contract layout layout at 0x1234ABC { } // ---- -// UnimplementedFeatureError 1834: (0-39): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol index 9e15ef564..7e448bba7 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_with_members_named_layout_and_at.sol @@ -3,4 +3,3 @@ contract C layout at 0x1234 { function at() public pure { } } // ---- -// UnimplementedFeatureError 1834: (0-82): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_abstract_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_abstract_contract.sol index 850798c93..32d6839ab 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_abstract_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_abstract_contract.sol @@ -2,4 +2,3 @@ abstract contract A { } contract C layout at 42 is A { } // ---- -// UnimplementedFeatureError 1834: (25-57): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_interface.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_interface.sol index 541dea056..c0ac98f57 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_interface.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/inheriting_from_interface.sol @@ -2,4 +2,3 @@ interface I { } contract C layout at 42 is I { } // ---- -// UnimplementedFeatureError 1834: (17-49): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol index b7bae489f..f74c45ed7 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol @@ -1,4 +1,3 @@ contract A layout at (2**256 + 1) * 2 - 2**256 - 3 {} contract B layout at (2**2 - 2**3) * (2**5 - 2**8) {} // ---- -// UnimplementedFeatureError 1834: (0-54): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol index 609178fd0..fffea1458 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_binary_expression.sol @@ -1,3 +1,2 @@ contract C layout at 0xffff * (0x123 + 0xABC) { } // ---- -// UnimplementedFeatureError 1834: (0-49): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol index 67954bdce..793b5b268 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol @@ -1,3 +1,2 @@ contract C layout at 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF {} // ---- -// UnimplementedFeatureError 1834: (0-90): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol index 7c8d483e2..13e094631 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_with_inheritance.sol @@ -3,4 +3,3 @@ contract B { } contract C is A, B layout at 0x1234 { } contract D layout at 0xABCD is A, B { } // ---- -// UnimplementedFeatureError 1834: (30-69): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_with_underscore.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_with_underscore.sol index 1c3c715f9..a5876ab6e 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_with_underscore.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_with_underscore.sol @@ -2,4 +2,3 @@ contract A layout at 42_0e10 {} contract B layout at 0x1234_ABCD {} contract C layout at 1234_000 {} // ---- -// UnimplementedFeatureError 1834: (0-31): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol index 8e048b29e..a9b5abef1 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/multi_token_expression.sol @@ -1,4 +1,3 @@ contract C layout at 5 minutes { } contract D layout at 2 gwei { } // ---- -// UnimplementedFeatureError 1834: (0-34): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol index 4d5b2da9c..e21521e39 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol @@ -1,4 +1,3 @@ contract A layout at 42.0 {} contract B layout at 2.5e10 {} // ---- -// UnimplementedFeatureError 1834: (0-28): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/same_ancestor_two_contracts.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/same_ancestor_two_contracts.sol index 310f50357..58fb725d7 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/same_ancestor_two_contracts.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/same_ancestor_two_contracts.sol @@ -2,4 +2,3 @@ contract A {} contract B is A layout at 64 {} contract C is A layout at 42 {} // ---- -// UnimplementedFeatureError 1834: (14-45): Code generation is not supported for contracts with specified storage layout base. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol index 116a6c5e4..024f5a95f 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/simple_layout.sol @@ -2,4 +2,3 @@ contract A layout at 0x1234 {} contract B layout at 1024 {} contract C layout at 0 {} // ---- -// UnimplementedFeatureError 1834: (0-30): Code generation is not supported for contracts with specified storage layout base. From 73e7917a0dea5a39ac6e40035fe139793d54d0da Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Fri, 20 Dec 2024 09:37:07 -0300 Subject: [PATCH 0762/1340] Storage Layout and Codegen --- Changelog.md | 2 +- .../analysis/PostTypeContractLevelChecker.cpp | 6 ++--- libsolidity/ast/ASTUtils.cpp | 14 +++++++++++ libsolidity/ast/ASTUtils.h | 9 ++++++++ libsolidity/ast/Types.cpp | 23 ++++++++++++------- libsolidity/ast/Types.h | 5 +++- 6 files changed, 45 insertions(+), 14 deletions(-) diff --git a/Changelog.md b/Changelog.md index 13cc8db13..331a68a3f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,7 +1,7 @@ ### 0.8.29 (unreleased) Language Features: - * Introduce syntax for specifying contract storage layout base. + * Allow relocating contract storage to an arbitrary location. Compiler Features: diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.cpp b/libsolidity/analysis/PostTypeContractLevelChecker.cpp index b605401e9..3e5a05499 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.cpp +++ b/libsolidity/analysis/PostTypeContractLevelChecker.cpp @@ -117,10 +117,8 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(StorageLayoutSpec } solAssert(rationalType->value().denominator() == 1); - if ( - rationalType->value().numerator() < 0 || - rationalType->value().numerator() > std::numeric_limits::max() - ) + bigint baseSlot = rationalType->value().numerator(); + if (!(0 <= baseSlot && baseSlot <= std::numeric_limits::max())) { m_errorReporter.typeError( 6753_error, diff --git a/libsolidity/ast/ASTUtils.cpp b/libsolidity/ast/ASTUtils.cpp index 7f5ea03a0..5ae336619 100644 --- a/libsolidity/ast/ASTUtils.cpp +++ b/libsolidity/ast/ASTUtils.cpp @@ -123,4 +123,18 @@ bigint contractStorageSizeUpperBound(ContractDefinition const& _contract, Variab return size; } +u256 layoutBaseForInheritanceHierarchy(ContractDefinition const& _topLevelContract, DataLocation _location) +{ + if (_location != DataLocation::Storage) + { + solAssert(_location == DataLocation::Transient); + return 0; + } + + if (auto const* storageLayoutSpecifier = _topLevelContract.storageLayoutSpecifier()) + return *storageLayoutSpecifier->annotation().baseSlot; + + return 0; +} + } diff --git a/libsolidity/ast/ASTUtils.h b/libsolidity/ast/ASTUtils.h index 0f37af719..d29bda35f 100644 --- a/libsolidity/ast/ASTUtils.h +++ b/libsolidity/ast/ASTUtils.h @@ -18,6 +18,8 @@ #pragma once +#include + namespace solidity::frontend { @@ -26,6 +28,7 @@ class Declaration; class Expression; class SourceUnit; class VariableDeclaration; +class ContractDefinition; /// Find the topmost referenced constant variable declaration when the given variable /// declaration value is an identifier. Works only for constant variable declarations. @@ -52,4 +55,10 @@ Type const* type(VariableDeclaration const& _variable); /// located in @a _location (either storage or transient storage). bigint contractStorageSizeUpperBound(ContractDefinition const& _contract, VariableDeclaration::Location _location); +/// @returns The base slot of the inheritance hierarchy rooted at the specified contract. +/// The value comes from the inheritance specifier of the contract and defaults to zero. +/// The value is zero also when the contract is an interface or a library (and cannot have storage). +/// Assumes analysis was successful. +u256 layoutBaseForInheritanceHierarchy(ContractDefinition const& _topLevelContract, DataLocation _location); + } diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index c77a6d0b6..1a1cf9291 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -138,23 +139,23 @@ void Type::clearCache() const m_stackSize.reset(); } -void StorageOffsets::computeOffsets(TypePointers const& _types) +void StorageOffsets::computeOffsets(TypePointers const& _types, u256 _baseSlot) { - bigint slotOffset = 0; + bigint slotOffset = bigint(_baseSlot); unsigned byteOffset = 0; std::map> offsets; for (size_t i = 0; i < _types.size(); ++i) { Type const* type = _types[i]; - if (!type->canBeStored()) - continue; + solAssert(type->canBeStored()); + solAssert(type->storageBytes() <= 32); if (byteOffset + type->storageBytes() > 32) { // would overflow, go to next slot ++slotOffset; byteOffset = 0; } - solAssert(slotOffset < bigint(1) << 256 ,"Object too large for storage."); + solAssert(slotOffset < bigint(1) << 256, "Object extends past the end of storage."); offsets[i] = std::make_pair(u256(slotOffset), byteOffset); solAssert(type->storageSize() >= 1, "Invalid storage size."); if (type->storageSize() == 1 && byteOffset + type->storageBytes() <= 32) @@ -167,8 +168,11 @@ void StorageOffsets::computeOffsets(TypePointers const& _types) } if (byteOffset > 0) ++slotOffset; - solAssert(slotOffset < bigint(1) << 256, "Object too large for storage."); - m_storageSize = u256(slotOffset); + + solAssert(slotOffset < bigint(1) << 256, "Object extends past the end of storage."); + storageSize = slotOffset - _baseSlot; + solAssert(storageSize < bigint(1) << 256, "Object too large for storage."); + m_storageSize = u256(storageSize); swap(m_offsets, offsets); } @@ -2168,11 +2172,14 @@ std::vector> ContractType for (VariableDeclaration const* variable: contract->stateVariables()) if (!(variable->isConstant() || variable->immutable()) && variable->referenceLocation() == location) variables.push_back(variable); + TypePointers types; for (auto variable: variables) types.push_back(variable->annotation().type); StorageOffsets offsets; - offsets.computeOffsets(types); + u256 layoutBase = 0; + layoutBase = layoutBaseForInheritanceHierarchy(m_contract, _location); + offsets.computeOffsets(types, layoutBase); std::vector> variablesAndOffsets; for (size_t index = 0; index < variables.size(); ++index) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index aa14cf6b9..2a5cdcfc9 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -81,7 +81,10 @@ class StorageOffsets public: /// Resets the StorageOffsets objects and determines the position in storage for each /// of the elements of @a _types. - void computeOffsets(TypePointers const& _types); + /// Calculated positions are absolute and start at @a _baseSlot. + /// Assumes that @a _types is small enough to fit in the area between @a _baseSlot and the end of storage + /// (the caller is responsible for validating that). + void computeOffsets(TypePointers const& _types, u256 _baseSlot = 0); /// @returns the offset of the given member, might be null if the member is not part of storage. std::pair const* offset(size_t _index) const; /// @returns the total number of slots occupied by all members. From b601fb4fadf9fcf126a06f63a188802382a32a7f Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Wed, 26 Feb 2025 23:56:46 -0300 Subject: [PATCH 0763/1340] Type checking fix: error on contract extending past storage end --- .../analysis/PostTypeContractLevelChecker.cpp | 23 ++++++++++++++----- .../analysis/PostTypeContractLevelChecker.h | 2 +- libsolidity/ast/Types.cpp | 8 ++----- .../contract_at_storage_end.sol | 3 +++ ...age_end_with_transient_state_variables.sol | 8 +++++++ .../contract_extends_past_storage_end.sol | 6 +++++ .../contract_too_large_for_storage.sol | 6 +++++ 7 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end_with_transient_state_variables.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_extends_past_storage_end.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_too_large_for_storage.sol diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.cpp b/libsolidity/analysis/PostTypeContractLevelChecker.cpp index 3e5a05499..657f39284 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.cpp +++ b/libsolidity/analysis/PostTypeContractLevelChecker.cpp @@ -73,15 +73,17 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract) errorHashes[hash][signature] = error->location(); } - if (auto const* layoutSpecifier = _contract.storageLayoutSpecifier()) - checkStorageLayoutSpecifier(*layoutSpecifier); + if (_contract.storageLayoutSpecifier()) + checkStorageLayoutSpecifier(_contract); return !Error::containsErrors(m_errorReporter.errors()); } -void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(StorageLayoutSpecifier const& _storageLayoutSpecifier) +void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinition const& _contract) { - Expression const& baseSlotExpression = _storageLayoutSpecifier.baseSlotExpression(); + StorageLayoutSpecifier const* storageLayoutSpecifier = _contract.storageLayoutSpecifier(); + solAssert(storageLayoutSpecifier); + Expression const& baseSlotExpression = storageLayoutSpecifier->baseSlotExpression(); if (!*baseSlotExpression.annotation().isPure) { @@ -125,12 +127,21 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(StorageLayoutSpec baseSlotExpression.location(), fmt::format( "The base slot of the storage layout evaluates to {}, which is outside the range of type uint256.", - formatNumberReadable(rationalType->value().numerator()) + formatNumberReadable(baseSlot) ) ); return; } solAssert(baseSlotExpressionType->isImplicitlyConvertibleTo(*TypeProvider::uint256())); - _storageLayoutSpecifier.annotation().baseSlot = u256(rationalType->value().numerator()); + storageLayoutSpecifier->annotation().baseSlot = u256(baseSlot); + + bigint size = contractStorageSizeUpperBound(_contract, VariableDeclaration::Location::Unspecified); + solAssert(size < bigint(1) << 256); + if (baseSlot + size >= bigint(1) << 256) + m_errorReporter.typeError( + 5015_error, + baseSlotExpression.location(), + "Contract extends past the end of storage when this base slot value is specified." + ); } diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.h b/libsolidity/analysis/PostTypeContractLevelChecker.h index 889c16356..2fa2cb11b 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.h +++ b/libsolidity/analysis/PostTypeContractLevelChecker.h @@ -50,7 +50,7 @@ class PostTypeContractLevelChecker /// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings bool check(ContractDefinition const& _contract); - void checkStorageLayoutSpecifier(StorageLayoutSpecifier const& _storageLayoutSpecifier); + void checkStorageLayoutSpecifier(ContractDefinition const& _contract); langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 1a1cf9291..5f543be0d 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -170,9 +170,7 @@ void StorageOffsets::computeOffsets(TypePointers const& _types, u256 _baseSlot) ++slotOffset; solAssert(slotOffset < bigint(1) << 256, "Object extends past the end of storage."); - storageSize = slotOffset - _baseSlot; - solAssert(storageSize < bigint(1) << 256, "Object too large for storage."); - m_storageSize = u256(storageSize); + m_storageSize = u256(slotOffset - _baseSlot); swap(m_offsets, offsets); } @@ -2177,9 +2175,7 @@ std::vector> ContractType for (auto variable: variables) types.push_back(variable->annotation().type); StorageOffsets offsets; - u256 layoutBase = 0; - layoutBase = layoutBaseForInheritanceHierarchy(m_contract, _location); - offsets.computeOffsets(types, layoutBase); + offsets.computeOffsets(types, layoutBaseForInheritanceHierarchy(m_contract, _location)); std::vector> variablesAndOffsets; for (size_t index = 0; index < variables.size(); ++index) diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end.sol new file mode 100644 index 000000000..29733c9ca --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end.sol @@ -0,0 +1,3 @@ +contract C layout at 2**256 - 1 { +} +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end_with_transient_state_variables.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end_with_transient_state_variables.sol new file mode 100644 index 000000000..fb1008616 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end_with_transient_state_variables.sol @@ -0,0 +1,8 @@ +contract C layout at 2**256 - 1 { + uint transient x; + uint transient y; + uint transient z; +} +// ==== +// EVMVersion: >=cancun +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_extends_past_storage_end.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_extends_past_storage_end.sol new file mode 100644 index 000000000..a3efe6d3a --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_extends_past_storage_end.sol @@ -0,0 +1,6 @@ +contract C layout at 2**256 - 2 { + uint x; + bool b; +} +// ---- +// TypeError 5015: (21-31): Contract extends past the end of storage when this base slot value is specified. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_too_large_for_storage.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_too_large_for_storage.sol new file mode 100644 index 000000000..cfbfd539d --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_too_large_for_storage.sol @@ -0,0 +1,6 @@ +contract C layout at 1 { + uint[2**256 - 1] x; + uint y; +} +// ---- +// TypeError 7676: (0-62): Contract requires too much storage. From 14232980e4b39dee72972f3e142db584f0848a16 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 4 Mar 2025 14:47:40 -0300 Subject: [PATCH 0764/1340] Rename ContractType::stateVariables --- libsolidity/ast/Types.cpp | 2 +- libsolidity/ast/Types.h | 9 ++++++--- libsolidity/codegen/ContractCompiler.cpp | 2 +- libsolidity/codegen/ir/IRGenerator.cpp | 2 +- libsolidity/interface/StorageLayout.cpp | 2 +- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 5f543be0d..02df22dd5 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2150,7 +2150,7 @@ FunctionType const* ContractType::newExpressionType() const return m_constructorType; } -std::vector> ContractType::stateVariables(DataLocation _location) const +std::vector> ContractType::linearizedStateVariables(DataLocation _location) const { VariableDeclaration::Location location; switch (_location) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 2a5cdcfc9..8d2453d8d 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1005,9 +1005,12 @@ class ContractType: public Type /// Returns the function type of the constructor modified to return an object of the contract's type. FunctionType const* newExpressionType() const; - /// @returns a list of all state variables (including inherited) of the contract and their - /// offsets in storage/transient storage. - std::vector> stateVariables(DataLocation _location) const; + /// @returns a list of all state variables in the linearized inheritance hierarchy and + /// their respective slots and offsets in storage/transient storage. + /// It should only be called for the top level contract in order to get the absolute slots and + /// offsets values in storage/transient storage. Otherwise, the slots of the state variables + /// will be relative to the contract position in the hierarchy. + std::vector> linearizedStateVariables(DataLocation _location) const; /// @returns a list of all immutable variables (including inherited) of the contract. std::vector immutableVariables() const; protected: diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 57a23fb80..3a4dca043 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -571,7 +571,7 @@ void ContractCompiler::appendReturnValuePacker(TypePointers const& _typeParamete void ContractCompiler::registerStateVariables(ContractDefinition const& _contract) { for (auto const location: {DataLocation::Storage, DataLocation::Transient}) - for (auto const& var: ContractType(_contract).stateVariables(location)) + for (auto const& var: ContractType(_contract).linearizedStateVariables(location)) m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var)); } diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index dd6503ca1..27f7bedce 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -1175,7 +1175,7 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon m_context.setMostDerivedContract(_contract); for (auto const location: {DataLocation::Storage, DataLocation::Transient}) - for (auto const& var: ContractType(_contract).stateVariables(location)) + for (auto const& var: ContractType(_contract).linearizedStateVariables(location)) m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var)); } diff --git a/libsolidity/interface/StorageLayout.cpp b/libsolidity/interface/StorageLayout.cpp index 8565fec68..05d799d08 100644 --- a/libsolidity/interface/StorageLayout.cpp +++ b/libsolidity/interface/StorageLayout.cpp @@ -36,7 +36,7 @@ Json StorageLayout::generate(ContractDefinition const& _contractDef, DataLocatio solAssert(contractType, ""); Json variables = Json::array(); - for (auto [var, slot, offset]: contractType->stateVariables(_location)) + for (auto [var, slot, offset]: contractType->linearizedStateVariables(_location)) variables.emplace_back(generate(*var, slot, offset)); Json layout; From 3532328324cc479d17b4492de645597a3b5282c1 Mon Sep 17 00:00:00 2001 From: Sebastian Miasojed Date: Wed, 19 Feb 2025 22:51:47 +0100 Subject: [PATCH 0765/1340] Fix stack overflow issue when using soljson compiler --- cmake/EthCompilerSettings.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index cc8435ed3..ab90c3f20 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -170,6 +170,10 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_TABLE_GROWTH=1") # Disable warnings about not being pure asm.js due to memory growth. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-almost-asm") + # Increase stack size from 5MB to 16MB to prevent stack overflow issues. + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s TOTAL_STACK=16mb") + # Increase memory size from 16MB to 32MB since the stack size is now 16MB. + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s INITIAL_MEMORY=32mb") endif() endif() From f3705de1740737f31715ad7758ac4d47b9f5c4f2 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Tue, 27 Aug 2024 12:59:56 +0200 Subject: [PATCH 0766/1340] Ethdebug instructions and source ranges. --- Changelog.md | 1 + libevmasm/Assembly.cpp | 147 +++++++++---- libevmasm/CMakeLists.txt | 2 + libevmasm/Ethdebug.cpp | 115 +++++++++++ libevmasm/Ethdebug.h | 35 ++++ libevmasm/LinkerObject.h | 31 +++ libsolidity/interface/CompilerStack.cpp | 18 +- libsolidity/interface/StandardCompiler.cpp | 16 +- libyul/YulStack.cpp | 17 +- libyul/YulStack.h | 3 - solc/CommandLineInterface.cpp | 26 +-- test/cmdlineTests.sh | 21 ++ .../debug_info_ethdebug_compatible/args | 1 - .../debug_info_ethdebug_compatible/input.sol | 7 - .../debug_info_ethdebug_compatible/output | 193 ------------------ .../debug_info_ethdebug_incompatible/args | 1 - .../debug_info_ethdebug_incompatible/err | 1 - .../ethdebug_and_ethdebug_runtime_ir/args | 1 - .../input.sol | 7 - .../ethdebug_and_ethdebug_runtime_ir/output | 123 ----------- .../args | 1 - .../input.sol | 7 - .../output | 79 ------- .../ethdebug_enabled_optimization_ir/args | 1 - .../ethdebug_enabled_optimization_ir/err | 1 - .../ethdebug_enabled_optimization_ir/exit | 1 - .../input.sol | 7 - .../args | 1 - .../err | 1 - .../exit | 1 - .../input.sol | 7 - .../ethdebug_eof_container_osaka/args | 1 + .../ethdebug_eof_container_osaka/err | 1 + .../exit | 0 .../input.sol | 1 - .../ethdebug_eof_container_osaka/output | 4 + test/cmdlineTests/ethdebug_ir/args | 1 - test/cmdlineTests/ethdebug_ir/input.sol | 7 - test/cmdlineTests/ethdebug_ir/output | 121 ----------- test/cmdlineTests/ethdebug_iroptimized/args | 1 - .../ethdebug_iroptimized/input.sol | 7 - test/cmdlineTests/ethdebug_iroptimized/output | 77 ------- test/cmdlineTests/ethdebug_no_via_ir/args | 1 - test/cmdlineTests/ethdebug_no_via_ir/err | 1 - test/cmdlineTests/ethdebug_no_via_ir/exit | 1 - .../cmdlineTests/ethdebug_no_via_ir/input.sol | 7 - test/cmdlineTests/ethdebug_runtime_ir/args | 1 - .../ethdebug_runtime_ir/input.sol | 7 - test/cmdlineTests/ethdebug_runtime_ir/output | 121 ----------- .../ethdebug_runtime_iroptimized/args | 1 - .../ethdebug_runtime_iroptimized/input.sol | 7 - .../ethdebug_runtime_iroptimized/output | 77 ------- .../output.json | 23 +-- .../strip-ethdebug | 0 .../output.json | 23 +-- .../strip-ethdebug | 0 .../output.json | 23 +-- .../strip-ethdebug | 0 .../output.json | 15 +- .../strip-ethdebug | 0 .../output.json | 15 +- .../strip-ethdebug | 0 .../output.json | 15 +- .../strip-ethdebug | 0 .../output.json | 15 +- .../strip-ethdebug | 0 .../output.json | 15 +- .../strip-ethdebug | 0 .../output.json | 15 +- .../strip-ethdebug | 0 .../output.json | 10 +- .../strip-ethdebug | 0 .../args | 1 + .../in.yul | 11 + .../input.json | 16 ++ .../output.json | 13 ++ .../args | 1 + .../in.yul | 7 + .../input.json | 11 + .../output.json | 127 ++++++++++++ .../output.json | 10 +- .../strip-ethdebug | 0 .../output.json | 10 +- .../strip-ethdebug | 0 .../in.yul | 22 +- .../output.json | 19 +- .../strip-ethdebug | 0 .../args | 1 + .../in.yul | 19 ++ .../input.json | 11 + .../output.json | 17 ++ .../strip-ethdebug | 0 .../standard_yul_ethdebug_ir/output.json | 10 +- .../standard_yul_ethdebug_ir/strip-ethdebug | 0 .../output.json | 10 +- .../strip-ethdebug | 0 test/cmdlineTests/yul_ethdebug/args | 1 - test/cmdlineTests/yul_ethdebug/input.yul | 18 -- test/cmdlineTests/yul_ethdebug/output | 7 - test/cmdlineTests/yul_ethdebug_ir/args | 1 - test/cmdlineTests/yul_ethdebug_ir/err | 1 - test/cmdlineTests/yul_ethdebug_ir/exit | 1 - test/cmdlineTests/yul_ethdebug_ir/input.yul | 18 -- .../yul_ethdebug_iroptimized/args | 1 - .../yul_ethdebug_iroptimized/input.yul | 18 -- .../yul_ethdebug_iroptimized/output | 26 --- test/cmdlineTests/yul_ethdebug_optimize/args | 1 - test/cmdlineTests/yul_ethdebug_optimize/err | 1 - test/cmdlineTests/yul_ethdebug_optimize/exit | 1 - .../yul_ethdebug_optimize/input.yul | 18 -- .../yul_ethdebug_optimize_iroptimized/args | 1 - .../yul_ethdebug_optimize_iroptimized/err | 1 - .../yul_ethdebug_optimize_iroptimized/exit | 1 - .../input.yul | 18 -- test/cmdlineTests/yul_ethdebug_runtime/args | 1 - test/cmdlineTests/yul_ethdebug_runtime/err | 1 - test/cmdlineTests/yul_ethdebug_runtime/exit | 1 - .../yul_ethdebug_runtime/input.yul | 18 -- test/libevmasm/Assembler.cpp | 41 ++++ test/libsolidity/StandardCompiler.cpp | 41 ++++ 120 files changed, 747 insertions(+), 1293 deletions(-) create mode 100644 libevmasm/Ethdebug.cpp create mode 100644 libevmasm/Ethdebug.h delete mode 100644 test/cmdlineTests/debug_info_ethdebug_compatible/args delete mode 100644 test/cmdlineTests/debug_info_ethdebug_compatible/input.sol delete mode 100644 test/cmdlineTests/debug_info_ethdebug_compatible/output delete mode 100644 test/cmdlineTests/debug_info_ethdebug_incompatible/args delete mode 100644 test/cmdlineTests/debug_info_ethdebug_incompatible/err delete mode 100644 test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/args delete mode 100644 test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/input.sol delete mode 100644 test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/output delete mode 100644 test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/args delete mode 100644 test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/input.sol delete mode 100644 test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/output delete mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_ir/args delete mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_ir/err delete mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_ir/exit delete mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_ir/input.sol delete mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/args delete mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/err delete mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/exit delete mode 100644 test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/input.sol create mode 100644 test/cmdlineTests/ethdebug_eof_container_osaka/args create mode 100644 test/cmdlineTests/ethdebug_eof_container_osaka/err rename test/cmdlineTests/{debug_info_ethdebug_incompatible => ethdebug_eof_container_osaka}/exit (100%) rename test/cmdlineTests/{debug_info_ethdebug_incompatible => ethdebug_eof_container_osaka}/input.sol (99%) create mode 100644 test/cmdlineTests/ethdebug_eof_container_osaka/output delete mode 100644 test/cmdlineTests/ethdebug_ir/args delete mode 100644 test/cmdlineTests/ethdebug_ir/input.sol delete mode 100644 test/cmdlineTests/ethdebug_ir/output delete mode 100644 test/cmdlineTests/ethdebug_iroptimized/args delete mode 100644 test/cmdlineTests/ethdebug_iroptimized/input.sol delete mode 100644 test/cmdlineTests/ethdebug_iroptimized/output delete mode 100644 test/cmdlineTests/ethdebug_no_via_ir/args delete mode 100644 test/cmdlineTests/ethdebug_no_via_ir/err delete mode 100644 test/cmdlineTests/ethdebug_no_via_ir/exit delete mode 100644 test/cmdlineTests/ethdebug_no_via_ir/input.sol delete mode 100644 test/cmdlineTests/ethdebug_runtime_ir/args delete mode 100644 test/cmdlineTests/ethdebug_runtime_ir/input.sol delete mode 100644 test/cmdlineTests/ethdebug_runtime_ir/output delete mode 100644 test/cmdlineTests/ethdebug_runtime_iroptimized/args delete mode 100644 test/cmdlineTests/ethdebug_runtime_iroptimized/input.sol delete mode 100644 test/cmdlineTests/ethdebug_runtime_iroptimized/output create mode 100644 test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/strip-ethdebug create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/strip-ethdebug create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/strip-ethdebug create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/strip-ethdebug create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/strip-ethdebug create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/strip-ethdebug create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/strip-ethdebug create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_ir/strip-ethdebug create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/strip-ethdebug create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/strip-ethdebug create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/args create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/in.yul create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_assign_immutable/args create mode 100644 test/cmdlineTests/standard_yul_ethdebug_assign_immutable/in.yul create mode 100644 test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_assign_immutable/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/strip-ethdebug create mode 100644 test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/strip-ethdebug create mode 100644 test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/strip-ethdebug create mode 100644 test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/args create mode 100644 test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/in.yul create mode 100644 test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/strip-ethdebug create mode 100644 test/cmdlineTests/standard_yul_ethdebug_ir/strip-ethdebug create mode 100644 test/cmdlineTests/standard_yul_ethdebug_iroptimize/strip-ethdebug delete mode 100644 test/cmdlineTests/yul_ethdebug/args delete mode 100644 test/cmdlineTests/yul_ethdebug/input.yul delete mode 100644 test/cmdlineTests/yul_ethdebug/output delete mode 100644 test/cmdlineTests/yul_ethdebug_ir/args delete mode 100644 test/cmdlineTests/yul_ethdebug_ir/err delete mode 100644 test/cmdlineTests/yul_ethdebug_ir/exit delete mode 100644 test/cmdlineTests/yul_ethdebug_ir/input.yul delete mode 100644 test/cmdlineTests/yul_ethdebug_iroptimized/args delete mode 100644 test/cmdlineTests/yul_ethdebug_iroptimized/input.yul delete mode 100644 test/cmdlineTests/yul_ethdebug_iroptimized/output delete mode 100644 test/cmdlineTests/yul_ethdebug_optimize/args delete mode 100644 test/cmdlineTests/yul_ethdebug_optimize/err delete mode 100644 test/cmdlineTests/yul_ethdebug_optimize/exit delete mode 100644 test/cmdlineTests/yul_ethdebug_optimize/input.yul delete mode 100644 test/cmdlineTests/yul_ethdebug_optimize_iroptimized/args delete mode 100644 test/cmdlineTests/yul_ethdebug_optimize_iroptimized/err delete mode 100644 test/cmdlineTests/yul_ethdebug_optimize_iroptimized/exit delete mode 100644 test/cmdlineTests/yul_ethdebug_optimize_iroptimized/input.yul delete mode 100644 test/cmdlineTests/yul_ethdebug_runtime/args delete mode 100644 test/cmdlineTests/yul_ethdebug_runtime/err delete mode 100644 test/cmdlineTests/yul_ethdebug_runtime/exit delete mode 100644 test/cmdlineTests/yul_ethdebug_runtime/input.yul diff --git a/Changelog.md b/Changelog.md index 13cc8db13..5a8438c5c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Language Features: Compiler Features: * Error Reporting: Errors reported during code generation now point at the location of the contract when more fine-grained location is not available. + * ethdebug: Experimental support for instructions and source locations. * EVM: Support for the EVM version "Osaka". * EVM Assembly Import: Allow enabling opcode-based optimizer. * General: The experimental EOF backend implements a subset of EOF sufficient to compile arbitrary high-level Solidity syntax via IR with optimization enabled. diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 4dcc6a4b0..a0711cd41 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1281,6 +1281,21 @@ LinkerObject const& Assembly::assembleLegacy() const uint8_t tagPush = static_cast(pushInstruction(bytesPerTag)); uint8_t dataRefPush = static_cast(pushInstruction(bytesPerDataRef)); + LinkerObject::CodeSectionLocation codeSectionLocation; + codeSectionLocation.start = 0; + size_t assemblyItemIndex = 0; + auto assembleInstruction = [&](auto&& _addInstruction) { + size_t start = ret.bytecode.size(); + _addInstruction(); + size_t end = ret.bytecode.size(); + codeSectionLocation.instructionLocations.emplace_back( + LinkerObject::InstructionLocation{ + .start = start, + .end = end, + .assemblyItemIndex = assemblyItemIndex + } + ); + }; for (AssemblyItem const& item: items) { // store position of the invalid jump destination @@ -1290,63 +1305,81 @@ LinkerObject const& Assembly::assembleLegacy() const switch (item.type()) { case Operation: - ret.bytecode += assembleOperation(item); + assembleInstruction([&](){ + ret.bytecode += assembleOperation(item); + }); break; case Push: - ret.bytecode += assemblePush(item); + assembleInstruction([&](){ + ret.bytecode += assemblePush(item); + }); break; case PushTag: { - ret.bytecode.push_back(tagPush); - tagRefs[ret.bytecode.size()] = item.splitForeignPushTag(); - ret.bytecode.resize(ret.bytecode.size() + bytesPerTag); + assembleInstruction([&](){ + ret.bytecode.push_back(tagPush); + tagRefs[ret.bytecode.size()] = item.splitForeignPushTag(); + ret.bytecode.resize(ret.bytecode.size() + bytesPerTag); + }); break; } case PushData: - ret.bytecode.push_back(dataRefPush); - dataRefs.insert(std::make_pair(h256(item.data()), ret.bytecode.size())); - ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + assembleInstruction([&]() { + ret.bytecode.push_back(dataRefPush); + dataRefs.insert(std::make_pair(h256(item.data()), ret.bytecode.size())); + ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + }); break; case PushSub: - assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); - ret.bytecode.push_back(dataRefPush); - subRefs.insert(std::make_pair(static_cast(item.data()), ret.bytecode.size())); - ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + assembleInstruction([&]() { + assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); + ret.bytecode.push_back(dataRefPush); + subRefs.insert(std::make_pair(static_cast(item.data()), ret.bytecode.size())); + ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + }); break; case PushSubSize: { - assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); - auto s = subAssemblyById(static_cast(item.data()))->assemble().bytecode.size(); - item.setPushedValue(u256(s)); - unsigned b = std::max(1, numberEncodingSize(s)); - ret.bytecode.push_back(static_cast(pushInstruction(b))); - ret.bytecode.resize(ret.bytecode.size() + b); - bytesRef byr(&ret.bytecode.back() + 1 - b, b); - toBigEndian(s, byr); + assembleInstruction([&](){ + assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); + auto s = subAssemblyById(static_cast(item.data()))->assemble().bytecode.size(); + item.setPushedValue(u256(s)); + unsigned b = std::max(1, numberEncodingSize(s)); + ret.bytecode.push_back(static_cast(pushInstruction(b))); + ret.bytecode.resize(ret.bytecode.size() + b); + bytesRef byr(&ret.bytecode.back() + 1 - b, b); + toBigEndian(s, byr); + }); break; } case PushProgramSize: { - ret.bytecode.push_back(dataRefPush); - sizeRefs.push_back(static_cast(ret.bytecode.size())); - ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + assembleInstruction([&](){ + ret.bytecode.push_back(dataRefPush); + sizeRefs.push_back(static_cast(ret.bytecode.size())); + ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); + }); break; } case PushLibraryAddress: { - auto const [bytecode, linkRef] = assemblePushLibraryAddress(item, ret.bytecode.size()); - ret.bytecode += bytecode; - ret.linkReferences.insert(linkRef); + assembleInstruction([&]() { + auto const [bytecode, linkRef] = assemblePushLibraryAddress(item, ret.bytecode.size()); + ret.bytecode += bytecode; + ret.linkReferences.insert(linkRef); + }); break; } case PushImmutable: - ret.bytecode.push_back(static_cast(Instruction::PUSH32)); - // Maps keccak back to the "identifier" std::string of that immutable. - ret.immutableReferences[item.data()].first = m_immutables.at(item.data()); - // Record the bytecode offset of the PUSH32 argument. - ret.immutableReferences[item.data()].second.emplace_back(ret.bytecode.size()); - // Advance bytecode by 32 bytes (default initialized). - ret.bytecode.resize(ret.bytecode.size() + 32); + assembleInstruction([&]() { + ret.bytecode.push_back(static_cast(Instruction::PUSH32)); + // Maps keccak back to the "identifier" std::string of that immutable. + ret.immutableReferences[item.data()].first = m_immutables.at(item.data()); + // Record the bytecode offset of the PUSH32 argument. + ret.immutableReferences[item.data()].second.emplace_back(ret.bytecode.size()); + // Advance bytecode by 32 bytes (default initialized). + ret.bytecode.resize(ret.bytecode.size() + 32); + }); break; case VerbatimBytecode: ret.bytecode += assembleVerbatimBytecode(item); @@ -1359,35 +1392,59 @@ LinkerObject const& Assembly::assembleLegacy() const { if (i != offsets.size() - 1) { - ret.bytecode.push_back(uint8_t(Instruction::DUP2)); - ret.bytecode.push_back(uint8_t(Instruction::DUP2)); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::DUP2)); + }); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::DUP2)); + }); } - // TODO: should we make use of the constant optimizer methods for pushing the offsets? - bytes offsetBytes = toCompactBigEndian(u256(offsets[i])); - ret.bytecode.push_back(static_cast(pushInstruction(static_cast(offsetBytes.size())))); - ret.bytecode += offsetBytes; - ret.bytecode.push_back(uint8_t(Instruction::ADD)); - ret.bytecode.push_back(uint8_t(Instruction::MSTORE)); + assembleInstruction([&]() { + // TODO: should we make use of the constant optimizer methods for pushing the offsets? + bytes offsetBytes = toCompactBigEndian(u256(offsets[i])); + ret.bytecode.push_back(static_cast(pushInstruction(static_cast(offsetBytes.size())))); + ret.bytecode += offsetBytes; + }); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::ADD)); + }); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::MSTORE)); + }); } if (offsets.empty()) { - ret.bytecode.push_back(uint8_t(Instruction::POP)); - ret.bytecode.push_back(uint8_t(Instruction::POP)); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::POP)); + }); + assembleInstruction([&]() { + ret.bytecode.push_back(uint8_t(Instruction::POP)); + }); } immutableReferencesBySub.erase(item.data()); break; } case PushDeployTimeAddress: - ret.bytecode += assemblePushDeployTimeAddress(); + assembleInstruction([&]() { + ret.bytecode += assemblePushDeployTimeAddress(); + }); break; case Tag: - ret.bytecode += assembleTag(item, ret.bytecode.size(), true); + assembleInstruction([&](){ + ret.bytecode += assembleTag(item, ret.bytecode.size(), true); + }); break; default: solAssert(false, "Unexpected opcode while assembling."); } + + ++assemblyItemIndex; } + codeSectionLocation.end = ret.bytecode.size(); + + ret.codeSectionLocations.emplace_back(std::move(codeSectionLocation)); + if (!immutableReferencesBySub.empty()) throw langutil::Error( diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index c1918540e..a7441b85e 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -4,6 +4,8 @@ set(sources Assembly.h AssemblyItem.cpp AssemblyItem.h + Ethdebug.cpp + Ethdebug.h EVMAssemblyStack.cpp EVMAssemblyStack.h BlockDeduplicator.cpp diff --git a/libevmasm/Ethdebug.cpp b/libevmasm/Ethdebug.cpp new file mode 100644 index 000000000..7b5de2ba9 --- /dev/null +++ b/libevmasm/Ethdebug.cpp @@ -0,0 +1,115 @@ +/* + 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 + +#include + +using namespace solidity; +using namespace solidity::evmasm; +using namespace solidity::evmasm::ethdebug; + +namespace +{ + +Json programInstructions(Assembly const* _assembly, LinkerObject const& _linkerObject, unsigned _sourceId) +{ + // e.g. interfaces don't have a valid assembly object. + if (_assembly) + { + solUnimplementedAssert(_assembly->eofVersion() == std::nullopt, "ethdebug does not yet support EOF."); + solUnimplementedAssert(_assembly->codeSections().size() == 1, "ethdebug does not yet support multiple code-sections."); + for (auto const& instruction: _assembly->codeSections()[0].items) + solUnimplementedAssert(instruction.type() != VerbatimBytecode, "Verbatim bytecode is currently not supported by ethdebug."); + } + + solAssert(_linkerObject.codeSectionLocations.size() == 1); + solAssert(_linkerObject.codeSectionLocations[0].end <= _linkerObject.bytecode.size()); + Json instructions = Json::array(); + for (size_t i = 0; i < _linkerObject.codeSectionLocations[0].instructionLocations.size(); ++i) + { + solAssert(_assembly); + LinkerObject::InstructionLocation currentInstruction = _linkerObject.codeSectionLocations[0].instructionLocations[i]; + size_t start = currentInstruction.start; + size_t end = currentInstruction.end; + size_t assemblyItemIndex = currentInstruction.assemblyItemIndex; + solAssert(end <= _linkerObject.bytecode.size()); + solAssert(start < end); + solAssert(assemblyItemIndex < _assembly->codeSections().at(0).items.size()); + Json operation = Json::object(); + operation["mnemonic"] = instructionInfo(static_cast(_linkerObject.bytecode[start]), _assembly->evmVersion()).name; + static size_t constexpr instructionSize = 1; + if (start + instructionSize < end) + { + bytes const argumentData( + _linkerObject.bytecode.begin() + static_cast(start) + instructionSize, + _linkerObject.bytecode.begin() + static_cast(end) + ); + solAssert(!argumentData.empty()); + operation["arguments"] = Json::array({util::toHex(argumentData, util::HexPrefix::Add)}); + } + langutil::SourceLocation const& location = _assembly->codeSections().at(0).items.at(assemblyItemIndex).location(); + Json instruction = Json::object(); + instruction["offset"] = start; + instruction["operation"] = operation; + + instruction["context"] = Json::object(); + instruction["context"]["code"] = Json::object(); + instruction["context"]["code"]["source"] = Json::object(); + instruction["context"]["code"]["source"]["id"] = static_cast(_sourceId); + + instruction["context"]["code"]["range"] = Json::object(); + instruction["context"]["code"]["range"]["offset"] = location.start; + instruction["context"]["code"]["range"]["length"] = location.end - location.start; + instructions.emplace_back(instruction); + } + + return instructions; +} + +} // anonymous namespace + +Json ethdebug::program(std::string_view _name, unsigned _sourceId, Assembly const* _assembly, LinkerObject const& _linkerObject) +{ + Json result = Json::object(); + result["contract"] = Json::object(); + result["contract"]["name"] = _name; + result["contract"]["definition"] = Json::object(); + result["contract"]["definition"]["source"] = Json::object(); + result["contract"]["definition"]["source"]["id"] = _sourceId; + result["environment"] = (!_assembly || _assembly->isCreation()) ? "create" : "call"; + result["instructions"] = programInstructions(_assembly, _linkerObject, _sourceId); + return result; +} + +Json ethdebug::resources(std::vector const& _sources, std::string const& _version) +{ + Json sources = Json::array(); + for (size_t id = 0; id < _sources.size(); ++id) + { + Json source = Json::object(); + source["id"] = id; + source["path"] = _sources[id]; + sources.push_back(source); + } + Json result = Json::object(); + result["compilation"] = Json::object(); + result["compilation"]["compiler"] = Json::object(); + result["compilation"]["compiler"]["name"] = "solc"; + result["compilation"]["compiler"]["version"] = _version; + result["compilation"]["sources"] = sources; + return result; +} diff --git a/libevmasm/Ethdebug.h b/libevmasm/Ethdebug.h new file mode 100644 index 000000000..72ac16037 --- /dev/null +++ b/libevmasm/Ethdebug.h @@ -0,0 +1,35 @@ +/* + 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 + +#pragma once + +#include + +#include +#include + +namespace solidity::evmasm::ethdebug +{ + +// returns ethdebug/format/program. +Json program(std::string_view _name, unsigned _sourceId, Assembly const* _assembly, LinkerObject const& _linkerObject); + +// returns ethdebug/format/info/resources +Json resources(std::vector const& _sources, std::string const& _version); + +} // namespace solidity::evmasm::ethdebug diff --git a/libevmasm/LinkerObject.h b/libevmasm/LinkerObject.h index c103a565a..34e696d4e 100644 --- a/libevmasm/LinkerObject.h +++ b/libevmasm/LinkerObject.h @@ -46,6 +46,37 @@ struct LinkerObject /// to a list of offsets into the bytecode that refer to their values. std::map immutableReferences; + struct InstructionLocation + { + /// Absolute position of instruction's opcode within the bytecode. + /// The opcode takes up exactly one byte and is assumed to be followed by its immediate arguments. + size_t start{}; + /// Absolute position of the first byte past the end of the instruction, including potential immediate arguments. + size_t end{}; + /// Index of the AssemblyItem that produced the instruction within the Assembly. + /// While items of most types generate a single instruction, in general it can be more than one. + size_t assemblyItemIndex{}; + }; + struct CodeSectionLocation + { + /// Absolute position of the first byte belonging to the code section. + /// Equal to instructionLocations[0].start if the code section is not empty. + size_t start{}; + /// Absolute position of the first byte past end of the code section. + /// Greater or equal to start. Must be equal if instructionLocations is empty. + size_t end{}; + /// Descriptions of all instructions contained within the code section. + /// The instructions are assumed to fill the whole section, without any gaps or duplicates. + /// The areas between opcodes are assumed to contain their immediate arguments, of size appropriate for the opcode type. + /// The arguments of the last instruction extend to the end of the section. + /// The instructions must be ordered according to their positions (ascending). + std::vector instructionLocations; + }; + /// Descriptions of all code sections in the ascending order of their positions. + /// There are no duplicates and the sections never overlap. + /// Only sections belonging to the top-level assembly are included, even if the bytecode contains subassemblies. + std::vector codeSectionLocations; + struct FunctionDebugData { std::optional bytecodeOffset; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 9582939f5..b927776ce 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -78,13 +78,14 @@ #include #include - #include #include #include #include #include +#include + #include #include @@ -1196,9 +1197,7 @@ Json CompilerStack::ethdebug() const { solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); solAssert(!m_contracts.empty()); - Json result = Json::object(); - result["sources"] = sourceNames(); - return result; + return evmasm::ethdebug::resources(sourceNames(), VersionString); } Json CompilerStack::ethdebug(std::string const& _contractName) const @@ -1216,13 +1215,10 @@ Json CompilerStack::ethdebug(Contract const& _contract, bool _runtime) const solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); solAssert(_contract.contract); solUnimplementedAssert(!isExperimentalSolidity()); - if (_runtime) - { - Json result = Json::object(); - return result; - } - Json result = Json::object(); - return result; + evmasm::LinkerObject const& object = _runtime ? _contract.runtimeObject : _contract.object; + std::shared_ptr const& assembly = _runtime ? _contract.evmRuntimeAssembly : _contract.evmAssembly; + solAssert(sourceIndices().contains(_contract.contract->sourceUnitName())); + return evmasm::ethdebug::program(_contract.contract->name(), sourceIndices()[_contract.contract->sourceUnitName()], assembly.get(), object); } bytes CompilerStack::cborMetadata(std::string const& _contractName, bool _forIR) const diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 6bd5cd231..d5502228b 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -1680,19 +1681,6 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) return output; } - for (auto const& fileRequests: _inputsAndSettings.outputSelection) - for (auto const& requests: fileRequests) - for (auto const& request: requests) - if (request == "evm.deployedBytecode.ethdebug") - { - output["errors"].emplace_back(formatError( - Error::Type::JSONError, - "general", - "\"evm.deployedBytecode.ethdebug\" cannot be used for Yul." - )); - return output; - } - YulStack stack( _inputsAndSettings.evmVersion, _inputsAndSettings.eofVersion, @@ -1799,7 +1787,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) output["contracts"][sourceName][contractName]["yulCFGJson"] = stack.cfgJson(); if (isEthdebugRequested(_inputsAndSettings.outputSelection)) - output["ethdebug"] = stack.ethdebug(); + output["ethdebug"] = evmasm::ethdebug::resources({sourceName}, VersionString); return output; } diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 1ad24998f..5adb8d6d5 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -273,12 +274,15 @@ YulStack::assembleWithDeployed(std::optional _deployName) {{m_charStream->name(), 0}} ); } - creationObject.ethdebug["not yet implemented @ MachineAssemblyObject::ethdebug"] = true; + if (debugInfoSelection().ethdebug) + creationObject.ethdebug = evmasm::ethdebug::program(creationObject.assembly->name(), 0, creationObject.assembly.get(), *creationObject.bytecode.get()); if (deployedAssembly) { deployedObject.bytecode = std::make_shared(deployedAssembly->assemble()); deployedObject.assembly = deployedAssembly; + if (debugInfoSelection().ethdebug) + deployedObject.ethdebug = evmasm::ethdebug::program(deployedObject.assembly->name(), 0, deployedObject.assembly.get(), *deployedObject.bytecode.get()); solAssert(deployedAssembly->codeSections().size() == 1); deployedObject.sourceMappings = std::make_unique( evmasm::AssemblyItem::computeSourceMapping( @@ -383,17 +387,6 @@ Json YulStack::astJson() const return m_parserResult->toJson(); } -Json YulStack::ethdebug() const -{ - yulAssert(m_parserResult, ""); - yulAssert(m_parserResult->hasCode(), ""); - yulAssert(m_parserResult->analysisInfo, ""); - - Json result = Json::object(); - result["sources"] = Json::array({m_charStream->name()}); - return result; -} - Json YulStack::cfgJson() const { yulAssert(m_parserResult, ""); diff --git a/libyul/YulStack.h b/libyul/YulStack.h index b745f1b80..e9d75b6ae 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -149,9 +149,6 @@ class YulStack: public langutil::CharStreamProvider // return the JSON representation of the YuL CFG (experimental) Json cfgJson() const; - /// @returns a JSON representing the top-level ethdebug data (types, etc.). - Json ethdebug() const; - /// Return the parsed and analyzed object. std::shared_ptr parserResult() const; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index e57cd77a9..4a7f34561 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -43,6 +43,7 @@ #include +#include #include #include @@ -1347,26 +1348,25 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y solThrow(CommandLineExecutionError, ""); } - if (m_options.compiler.outputs.ethdebug) - { - Json ethdebugObject = Json::object(); - ethdebugObject["sources"] = m_fileReader.sourceUnits() | ranges::views::keys; - sout() << "======= Debug Data (ethdebug/format/info/resources) =======" << std::endl; - sout() << util::jsonPrint( - ethdebugObject, - m_options.formatting.json - ) << std::endl; - } - for (auto const& [sourceUnitName, yulSource]: m_fileReader.sourceUnits()) { solAssert(_targetMachine == yul::YulStack::Machine::EVM); - std::string machine = "EVM"; - sout() << std::endl << "======= " << sourceUnitName << " (" << machine << ") =======" << std::endl; yul::YulStack const& stack = yulStacks[sourceUnitName]; yul::MachineAssemblyObject const& object = objects[sourceUnitName]; + if (m_options.compiler.outputs.ethdebug) + { + sout() << "======= Debug Data (ethdebug/format/info/resources) =======" << std::endl; + sout() << util::jsonPrint( + evmasm::ethdebug::resources({{sourceUnitName}}, VersionString), + m_options.formatting.json + ) << std::endl; + } + + std::string machine = "EVM"; + sout() << std::endl << "======= " << sourceUnitName << " (" << machine << ") =======" << std::endl; + if (m_options.compiler.outputs.irOptimized) { // NOTE: This actually outputs unoptimized code when the optimizer is disabled but diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 3c781ea78..f68ed53dc 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -220,6 +220,27 @@ json = re.sub(r"\n\s*\n", "\n", json) json = re.sub(r"},(\n{0,1})\n*(\s*(]|}))", r"}\1\2", json) # Remove trailing comma open("$stdout_path", "w").write(json) EOF + # Only do this to files that actually contain ethdebug output, because jq will reformat + # the whole file and its formatting differs from `solc --pretty-json` + if jq 'has("ethdebug")' "$stdout_path" --exit-status > /dev/null; then + local temporary_file + temporary_file=$(mktemp -t cmdline-ethdebug-XXXXXX.tmp) + if [[ -e ${tdir}/strip-ethdebug ]]; then + jq --indent 4 ' + (. | .. | objects | select(has("ethdebug"))) |= (.ethdebug = "") + ' "$stdout_path" > "$temporary_file" + else + jq --indent 4 ' + if .ethdebug.compilation.compiler.version? != null then + .ethdebug.compilation.compiler.version = "" + else + . + end + ' "$stdout_path" > "$temporary_file" + fi + mv "$temporary_file" "$stdout_path" + fi + sed -i.bak -E -e 's/ Consider adding \\"pragma solidity \^[0-9.]*;\\"//g' "$stdout_path" sed -i.bak -E -e 's/\"opcodes\":[[:space:]]*\"[^"]+\"/\"opcodes\":\"\"/g' "$stdout_path" sed -i.bak -E -e 's/\"sourceMap\":[[:space:]]*\"[0-9:;-]+\"/\"sourceMap\":\"\"/g' "$stdout_path" diff --git a/test/cmdlineTests/debug_info_ethdebug_compatible/args b/test/cmdlineTests/debug_info_ethdebug_compatible/args deleted file mode 100644 index 74342f38f..000000000 --- a/test/cmdlineTests/debug_info_ethdebug_compatible/args +++ /dev/null @@ -1 +0,0 @@ ---debug-info ethdebug --via-ir --ir --ir-optimized --ethdebug --ethdebug-runtime diff --git a/test/cmdlineTests/debug_info_ethdebug_compatible/input.sol b/test/cmdlineTests/debug_info_ethdebug_compatible/input.sol deleted file mode 100644 index 25b9640ca..000000000 --- a/test/cmdlineTests/debug_info_ethdebug_compatible/input.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - -contract C { - function f() public {} -} - diff --git a/test/cmdlineTests/debug_info_ethdebug_compatible/output b/test/cmdlineTests/debug_info_ethdebug_compatible/output deleted file mode 100644 index 0f9581e7f..000000000 --- a/test/cmdlineTests/debug_info_ethdebug_compatible/output +++ /dev/null @@ -1,193 +0,0 @@ -======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["debug_info_ethdebug_compatible/input.sol"]} - -======= debug_info_ethdebug_compatible/input.sol:C ======= -IR: -/// ethdebug: enabled -/// @use-src 0:"debug_info_ethdebug_compatible/input.sol" -object "C_6" { - code { - /// @src 0:60:101 - mstore(64, memoryguard(128)) - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - - constructor_C_6() - - let _1 := allocate_unbounded() - codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) - - return(_1, datasize("C_6_deployed")) - - function allocate_unbounded() -> memPtr { - memPtr := mload(64) - } - - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { - revert(0, 0) - } - - /// @src 0:60:101 - function constructor_C_6() { - - /// @src 0:60:101 - - } - /// @src 0:60:101 - - } - /// @use-src 0:"debug_info_ethdebug_compatible/input.sol" - object "C_6_deployed" { - code { - /// @src 0:60:101 - mstore(64, memoryguard(128)) - - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_224_unsigned(calldataload(0)) - switch selector - - case 0x26121ff0 - { - // f() - - external_fun_f_5() - } - - default {} - } - - revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - - function shift_right_224_unsigned(value) -> newValue { - newValue := - - shr(224, value) - - } - - function allocate_unbounded() -> memPtr { - memPtr := mload(64) - } - - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { - revert(0, 0) - } - - function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { - revert(0, 0) - } - - function abi_decode_tuple_(headStart, dataEnd) { - if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } - - } - - function abi_encode_tuple__to__fromStack(headStart ) -> tail { - tail := add(headStart, 0) - - } - - function external_fun_f_5() { - - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) - - } - - function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { - revert(0, 0) - } - - /// @src 0:77:99 - function fun_f_5() { - - } - /// @src 0:60:101 - - } - - data ".metadata" hex"" - } - -} - - -Optimized IR: -/// ethdebug: enabled -/// @use-src 0:"debug_info_ethdebug_compatible/input.sol" -object "C_6" { - code { - { - /// @src 0:60:101 - mstore(64, memoryguard(0x80)) - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - let _1 := allocate_unbounded() - codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) - return(_1, datasize("C_6_deployed")) - } - function allocate_unbounded() -> memPtr - { memPtr := mload(64) } - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - { revert(0, 0) } - } - /// @use-src 0:"debug_info_ethdebug_compatible/input.sol" - object "C_6_deployed" { - code { - { - /// @src 0:60:101 - mstore(64, memoryguard(0x80)) - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_unsigned(calldataload(0)) - switch selector - case 0x26121ff0 { external_fun_f() } - default { } - } - revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - } - function shift_right_unsigned(value) -> newValue - { newValue := shr(224, value) } - function allocate_unbounded() -> memPtr - { memPtr := mload(64) } - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - { revert(0, 0) } - function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() - { revert(0, 0) } - function abi_decode(headStart, dataEnd) - { - if slt(sub(dataEnd, headStart), 0) - { - revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() - } - } - function abi_encode_tuple(headStart) -> tail - { tail := add(headStart, 0) } - function external_fun_f() - { - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - abi_decode(4, calldatasize()) - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple(memPos) - return(memPos, sub(memEnd, memPos)) - } - function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - { revert(0, 0) } - } - data ".metadata" hex"" - } -} - -Debug Data (ethdebug/format/program): -{} -Debug Data of the runtime part (ethdebug/format/program): -{} diff --git a/test/cmdlineTests/debug_info_ethdebug_incompatible/args b/test/cmdlineTests/debug_info_ethdebug_incompatible/args deleted file mode 100644 index 8afe2c9b3..000000000 --- a/test/cmdlineTests/debug_info_ethdebug_incompatible/args +++ /dev/null @@ -1 +0,0 @@ ---debug-info ethdebug --via-ir --asm diff --git a/test/cmdlineTests/debug_info_ethdebug_incompatible/err b/test/cmdlineTests/debug_info_ethdebug_incompatible/err deleted file mode 100644 index 32401186d..000000000 --- a/test/cmdlineTests/debug_info_ethdebug_incompatible/err +++ /dev/null @@ -1 +0,0 @@ -Error: --debug-info ethdebug can only be used with --ir / --ir-optimized and/or --ethdebug / --ethdebug-runtime. Optimization (using --optimize) is not yet supported with ethdebug. diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/args b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/args deleted file mode 100644 index 18053bcda..000000000 --- a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug-runtime --ethdebug --via-ir --ir \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/input.sol b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/input.sol deleted file mode 100644 index 25b9640ca..000000000 --- a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/input.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - -contract C { - function f() public {} -} - diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/output b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/output deleted file mode 100644 index 38dab05af..000000000 --- a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_ir/output +++ /dev/null @@ -1,123 +0,0 @@ -======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["ethdebug_and_ethdebug_runtime_ir/input.sol"]} - -======= ethdebug_and_ethdebug_runtime_ir/input.sol:C ======= -IR: -/// ethdebug: enabled -/// @use-src 0:"ethdebug_and_ethdebug_runtime_ir/input.sol" -object "C_6" { - code { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(128)) - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - - constructor_C_6() - - let _1 := allocate_unbounded() - codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) - - return(_1, datasize("C_6_deployed")) - - function allocate_unbounded() -> memPtr { - memPtr := mload(64) - } - - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { - revert(0, 0) - } - - /// @src 0:60:101 "contract C {..." - function constructor_C_6() { - - /// @src 0:60:101 "contract C {..." - - } - /// @src 0:60:101 "contract C {..." - - } - /// @use-src 0:"ethdebug_and_ethdebug_runtime_ir/input.sol" - object "C_6_deployed" { - code { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(128)) - - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_224_unsigned(calldataload(0)) - switch selector - - case 0x26121ff0 - { - // f() - - external_fun_f_5() - } - - default {} - } - - revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - - function shift_right_224_unsigned(value) -> newValue { - newValue := - - shr(224, value) - - } - - function allocate_unbounded() -> memPtr { - memPtr := mload(64) - } - - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { - revert(0, 0) - } - - function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { - revert(0, 0) - } - - function abi_decode_tuple_(headStart, dataEnd) { - if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } - - } - - function abi_encode_tuple__to__fromStack(headStart ) -> tail { - tail := add(headStart, 0) - - } - - function external_fun_f_5() { - - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) - - } - - function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { - revert(0, 0) - } - - /// @ast-id 5 - /// @src 0:77:99 "function f() public {}" - function fun_f_5() { - - } - /// @src 0:60:101 "contract C {..." - - } - - data ".metadata" hex"" - } - -} - - -Debug Data (ethdebug/format/program): -{} -Debug Data of the runtime part (ethdebug/format/program): -{} diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/args b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/args deleted file mode 100644 index 09535998b..000000000 --- a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug-runtime --ethdebug --via-ir --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/input.sol b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/input.sol deleted file mode 100644 index 25b9640ca..000000000 --- a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/input.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - -contract C { - function f() public {} -} - diff --git a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/output b/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/output deleted file mode 100644 index 19a3c9e86..000000000 --- a/test/cmdlineTests/ethdebug_and_ethdebug_runtime_iroptimized/output +++ /dev/null @@ -1,79 +0,0 @@ -======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["ethdebug_and_ethdebug_runtime_iroptimized/input.sol"]} - -======= ethdebug_and_ethdebug_runtime_iroptimized/input.sol:C ======= -Optimized IR: -/// ethdebug: enabled -/// @use-src 0:"ethdebug_and_ethdebug_runtime_iroptimized/input.sol" -object "C_6" { - code { - { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(0x80)) - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - let _1 := allocate_unbounded() - codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) - return(_1, datasize("C_6_deployed")) - } - function allocate_unbounded() -> memPtr - { memPtr := mload(64) } - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - { revert(0, 0) } - } - /// @use-src 0:"ethdebug_and_ethdebug_runtime_iroptimized/input.sol" - object "C_6_deployed" { - code { - { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(0x80)) - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_unsigned(calldataload(0)) - switch selector - case 0x26121ff0 { external_fun_f() } - default { } - } - revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - } - function shift_right_unsigned(value) -> newValue - { newValue := shr(224, value) } - function allocate_unbounded() -> memPtr - { memPtr := mload(64) } - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - { revert(0, 0) } - function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() - { revert(0, 0) } - function abi_decode(headStart, dataEnd) - { - if slt(sub(dataEnd, headStart), 0) - { - revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() - } - } - function abi_encode_tuple(headStart) -> tail - { tail := add(headStart, 0) } - function external_fun_f() - { - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - abi_decode(4, calldatasize()) - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple(memPos) - return(memPos, sub(memEnd, memPos)) - } - function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - { revert(0, 0) } - } - data ".metadata" hex"" - } -} - -Debug Data (ethdebug/format/program): -{} -Debug Data of the runtime part (ethdebug/format/program): -{} diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_ir/args b/test/cmdlineTests/ethdebug_enabled_optimization_ir/args deleted file mode 100644 index 38ce714e1..000000000 --- a/test/cmdlineTests/ethdebug_enabled_optimization_ir/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug --via-ir --optimize --ir \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_ir/err b/test/cmdlineTests/ethdebug_enabled_optimization_ir/err deleted file mode 100644 index b2c26e5d8..000000000 --- a/test/cmdlineTests/ethdebug_enabled_optimization_ir/err +++ /dev/null @@ -1 +0,0 @@ -Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized. Optimization (using --optimize) is not yet supported with ethdebug. diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_ir/exit b/test/cmdlineTests/ethdebug_enabled_optimization_ir/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/ethdebug_enabled_optimization_ir/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_ir/input.sol b/test/cmdlineTests/ethdebug_enabled_optimization_ir/input.sol deleted file mode 100644 index 25b9640ca..000000000 --- a/test/cmdlineTests/ethdebug_enabled_optimization_ir/input.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - -contract C { - function f() public {} -} - diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/args b/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/args deleted file mode 100644 index 6edc3b560..000000000 --- a/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug --via-ir --optimize --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/err b/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/err deleted file mode 100644 index b2c26e5d8..000000000 --- a/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/err +++ /dev/null @@ -1 +0,0 @@ -Error: --ethdebug / --ethdebug-runtime output can only be used with --ir / --ir-optimized. Optimization (using --optimize) is not yet supported with ethdebug. diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/exit b/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/input.sol b/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/input.sol deleted file mode 100644 index 25b9640ca..000000000 --- a/test/cmdlineTests/ethdebug_enabled_optimization_iroptimized/input.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - -contract C { - function f() public {} -} - diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/args b/test/cmdlineTests/ethdebug_eof_container_osaka/args new file mode 100644 index 000000000..65974c628 --- /dev/null +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/args @@ -0,0 +1 @@ + --experimental-eof-version 1 --evm-version osaka --ethdebug --via-ir diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/err b/test/cmdlineTests/ethdebug_eof_container_osaka/err new file mode 100644 index 000000000..771468597 --- /dev/null +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/err @@ -0,0 +1 @@ +Error: ethdebug does not yet support EOF. diff --git a/test/cmdlineTests/debug_info_ethdebug_incompatible/exit b/test/cmdlineTests/ethdebug_eof_container_osaka/exit similarity index 100% rename from test/cmdlineTests/debug_info_ethdebug_incompatible/exit rename to test/cmdlineTests/ethdebug_eof_container_osaka/exit diff --git a/test/cmdlineTests/debug_info_ethdebug_incompatible/input.sol b/test/cmdlineTests/ethdebug_eof_container_osaka/input.sol similarity index 99% rename from test/cmdlineTests/debug_info_ethdebug_incompatible/input.sol rename to test/cmdlineTests/ethdebug_eof_container_osaka/input.sol index 25b9640ca..415509ef9 100644 --- a/test/cmdlineTests/debug_info_ethdebug_incompatible/input.sol +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/input.sol @@ -4,4 +4,3 @@ pragma solidity >=0.0; contract C { function f() public {} } - diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/output b/test/cmdlineTests/ethdebug_eof_container_osaka/output new file mode 100644 index 000000000..9d002fadc --- /dev/null +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/output @@ -0,0 +1,4 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{"compilation":{"compiler":{"name":"solc","version": ""},"sources":[{"id":0,"path":"ethdebug_eof_container_osaka/input.sol"}]}} + +======= ethdebug_eof_container_osaka/input.sol:C ======= diff --git a/test/cmdlineTests/ethdebug_ir/args b/test/cmdlineTests/ethdebug_ir/args deleted file mode 100644 index ac83894b3..000000000 --- a/test/cmdlineTests/ethdebug_ir/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug --via-ir --ir \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_ir/input.sol b/test/cmdlineTests/ethdebug_ir/input.sol deleted file mode 100644 index 25b9640ca..000000000 --- a/test/cmdlineTests/ethdebug_ir/input.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - -contract C { - function f() public {} -} - diff --git a/test/cmdlineTests/ethdebug_ir/output b/test/cmdlineTests/ethdebug_ir/output deleted file mode 100644 index 6713431b6..000000000 --- a/test/cmdlineTests/ethdebug_ir/output +++ /dev/null @@ -1,121 +0,0 @@ -======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["ethdebug_ir/input.sol"]} - -======= ethdebug_ir/input.sol:C ======= -IR: -/// ethdebug: enabled -/// @use-src 0:"ethdebug_ir/input.sol" -object "C_6" { - code { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(128)) - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - - constructor_C_6() - - let _1 := allocate_unbounded() - codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) - - return(_1, datasize("C_6_deployed")) - - function allocate_unbounded() -> memPtr { - memPtr := mload(64) - } - - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { - revert(0, 0) - } - - /// @src 0:60:101 "contract C {..." - function constructor_C_6() { - - /// @src 0:60:101 "contract C {..." - - } - /// @src 0:60:101 "contract C {..." - - } - /// @use-src 0:"ethdebug_ir/input.sol" - object "C_6_deployed" { - code { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(128)) - - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_224_unsigned(calldataload(0)) - switch selector - - case 0x26121ff0 - { - // f() - - external_fun_f_5() - } - - default {} - } - - revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - - function shift_right_224_unsigned(value) -> newValue { - newValue := - - shr(224, value) - - } - - function allocate_unbounded() -> memPtr { - memPtr := mload(64) - } - - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { - revert(0, 0) - } - - function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { - revert(0, 0) - } - - function abi_decode_tuple_(headStart, dataEnd) { - if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } - - } - - function abi_encode_tuple__to__fromStack(headStart ) -> tail { - tail := add(headStart, 0) - - } - - function external_fun_f_5() { - - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) - - } - - function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { - revert(0, 0) - } - - /// @ast-id 5 - /// @src 0:77:99 "function f() public {}" - function fun_f_5() { - - } - /// @src 0:60:101 "contract C {..." - - } - - data ".metadata" hex"" - } - -} - - -Debug Data (ethdebug/format/program): -{} diff --git a/test/cmdlineTests/ethdebug_iroptimized/args b/test/cmdlineTests/ethdebug_iroptimized/args deleted file mode 100644 index e048da7bb..000000000 --- a/test/cmdlineTests/ethdebug_iroptimized/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug --via-ir --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_iroptimized/input.sol b/test/cmdlineTests/ethdebug_iroptimized/input.sol deleted file mode 100644 index 25b9640ca..000000000 --- a/test/cmdlineTests/ethdebug_iroptimized/input.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - -contract C { - function f() public {} -} - diff --git a/test/cmdlineTests/ethdebug_iroptimized/output b/test/cmdlineTests/ethdebug_iroptimized/output deleted file mode 100644 index 59e2579eb..000000000 --- a/test/cmdlineTests/ethdebug_iroptimized/output +++ /dev/null @@ -1,77 +0,0 @@ -======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["ethdebug_iroptimized/input.sol"]} - -======= ethdebug_iroptimized/input.sol:C ======= -Optimized IR: -/// ethdebug: enabled -/// @use-src 0:"ethdebug_iroptimized/input.sol" -object "C_6" { - code { - { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(0x80)) - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - let _1 := allocate_unbounded() - codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) - return(_1, datasize("C_6_deployed")) - } - function allocate_unbounded() -> memPtr - { memPtr := mload(64) } - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - { revert(0, 0) } - } - /// @use-src 0:"ethdebug_iroptimized/input.sol" - object "C_6_deployed" { - code { - { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(0x80)) - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_unsigned(calldataload(0)) - switch selector - case 0x26121ff0 { external_fun_f() } - default { } - } - revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - } - function shift_right_unsigned(value) -> newValue - { newValue := shr(224, value) } - function allocate_unbounded() -> memPtr - { memPtr := mload(64) } - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - { revert(0, 0) } - function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() - { revert(0, 0) } - function abi_decode(headStart, dataEnd) - { - if slt(sub(dataEnd, headStart), 0) - { - revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() - } - } - function abi_encode_tuple(headStart) -> tail - { tail := add(headStart, 0) } - function external_fun_f() - { - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - abi_decode(4, calldatasize()) - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple(memPos) - return(memPos, sub(memEnd, memPos)) - } - function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - { revert(0, 0) } - } - data ".metadata" hex"" - } -} - -Debug Data (ethdebug/format/program): -{} diff --git a/test/cmdlineTests/ethdebug_no_via_ir/args b/test/cmdlineTests/ethdebug_no_via_ir/args deleted file mode 100644 index 6a019364e..000000000 --- a/test/cmdlineTests/ethdebug_no_via_ir/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug --ir --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_no_via_ir/err b/test/cmdlineTests/ethdebug_no_via_ir/err deleted file mode 100644 index 2729b6d5d..000000000 --- a/test/cmdlineTests/ethdebug_no_via_ir/err +++ /dev/null @@ -1 +0,0 @@ -Error: --ethdebug / --ethdebug-runtime output can only be selected, if --via-ir was specified. diff --git a/test/cmdlineTests/ethdebug_no_via_ir/exit b/test/cmdlineTests/ethdebug_no_via_ir/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/ethdebug_no_via_ir/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/ethdebug_no_via_ir/input.sol b/test/cmdlineTests/ethdebug_no_via_ir/input.sol deleted file mode 100644 index 25b9640ca..000000000 --- a/test/cmdlineTests/ethdebug_no_via_ir/input.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - -contract C { - function f() public {} -} - diff --git a/test/cmdlineTests/ethdebug_runtime_ir/args b/test/cmdlineTests/ethdebug_runtime_ir/args deleted file mode 100644 index a2193034c..000000000 --- a/test/cmdlineTests/ethdebug_runtime_ir/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug-runtime --via-ir --ir \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_runtime_ir/input.sol b/test/cmdlineTests/ethdebug_runtime_ir/input.sol deleted file mode 100644 index 25b9640ca..000000000 --- a/test/cmdlineTests/ethdebug_runtime_ir/input.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - -contract C { - function f() public {} -} - diff --git a/test/cmdlineTests/ethdebug_runtime_ir/output b/test/cmdlineTests/ethdebug_runtime_ir/output deleted file mode 100644 index 93b7b91f1..000000000 --- a/test/cmdlineTests/ethdebug_runtime_ir/output +++ /dev/null @@ -1,121 +0,0 @@ -======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["ethdebug_runtime_ir/input.sol"]} - -======= ethdebug_runtime_ir/input.sol:C ======= -IR: -/// ethdebug: enabled -/// @use-src 0:"ethdebug_runtime_ir/input.sol" -object "C_6" { - code { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(128)) - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - - constructor_C_6() - - let _1 := allocate_unbounded() - codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) - - return(_1, datasize("C_6_deployed")) - - function allocate_unbounded() -> memPtr { - memPtr := mload(64) - } - - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { - revert(0, 0) - } - - /// @src 0:60:101 "contract C {..." - function constructor_C_6() { - - /// @src 0:60:101 "contract C {..." - - } - /// @src 0:60:101 "contract C {..." - - } - /// @use-src 0:"ethdebug_runtime_ir/input.sol" - object "C_6_deployed" { - code { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(128)) - - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_224_unsigned(calldataload(0)) - switch selector - - case 0x26121ff0 - { - // f() - - external_fun_f_5() - } - - default {} - } - - revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - - function shift_right_224_unsigned(value) -> newValue { - newValue := - - shr(224, value) - - } - - function allocate_unbounded() -> memPtr { - memPtr := mload(64) - } - - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { - revert(0, 0) - } - - function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { - revert(0, 0) - } - - function abi_decode_tuple_(headStart, dataEnd) { - if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } - - } - - function abi_encode_tuple__to__fromStack(headStart ) -> tail { - tail := add(headStart, 0) - - } - - function external_fun_f_5() { - - if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode_tuple_(4, calldatasize()) - fun_f_5() - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple__to__fromStack(memPos ) - return(memPos, sub(memEnd, memPos)) - - } - - function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { - revert(0, 0) - } - - /// @ast-id 5 - /// @src 0:77:99 "function f() public {}" - function fun_f_5() { - - } - /// @src 0:60:101 "contract C {..." - - } - - data ".metadata" hex"" - } - -} - - -Debug Data of the runtime part (ethdebug/format/program): -{} diff --git a/test/cmdlineTests/ethdebug_runtime_iroptimized/args b/test/cmdlineTests/ethdebug_runtime_iroptimized/args deleted file mode 100644 index f647c52a7..000000000 --- a/test/cmdlineTests/ethdebug_runtime_iroptimized/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug-runtime --via-ir --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/ethdebug_runtime_iroptimized/input.sol b/test/cmdlineTests/ethdebug_runtime_iroptimized/input.sol deleted file mode 100644 index 25b9640ca..000000000 --- a/test/cmdlineTests/ethdebug_runtime_iroptimized/input.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - -contract C { - function f() public {} -} - diff --git a/test/cmdlineTests/ethdebug_runtime_iroptimized/output b/test/cmdlineTests/ethdebug_runtime_iroptimized/output deleted file mode 100644 index 733e47a85..000000000 --- a/test/cmdlineTests/ethdebug_runtime_iroptimized/output +++ /dev/null @@ -1,77 +0,0 @@ -======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["ethdebug_runtime_iroptimized/input.sol"]} - -======= ethdebug_runtime_iroptimized/input.sol:C ======= -Optimized IR: -/// ethdebug: enabled -/// @use-src 0:"ethdebug_runtime_iroptimized/input.sol" -object "C_6" { - code { - { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(0x80)) - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - let _1 := allocate_unbounded() - codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) - return(_1, datasize("C_6_deployed")) - } - function allocate_unbounded() -> memPtr - { memPtr := mload(64) } - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - { revert(0, 0) } - } - /// @use-src 0:"ethdebug_runtime_iroptimized/input.sol" - object "C_6_deployed" { - code { - { - /// @src 0:60:101 "contract C {..." - mstore(64, memoryguard(0x80)) - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_unsigned(calldataload(0)) - switch selector - case 0x26121ff0 { external_fun_f() } - default { } - } - revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - } - function shift_right_unsigned(value) -> newValue - { newValue := shr(224, value) } - function allocate_unbounded() -> memPtr - { memPtr := mload(64) } - function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - { revert(0, 0) } - function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() - { revert(0, 0) } - function abi_decode(headStart, dataEnd) - { - if slt(sub(dataEnd, headStart), 0) - { - revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() - } - } - function abi_encode_tuple(headStart) -> tail - { tail := add(headStart, 0) } - function external_fun_f() - { - if callvalue() - { - revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() - } - abi_decode(4, calldatasize()) - let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple(memPos) - return(memPos, sub(memEnd, memPos)) - } - function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() - { revert(0, 0) } - } - data ".metadata" hex"" - } -} - -Debug Data of the runtime part (ethdebug/format/program): -{} diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/output.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/output.json index 0b8a87baf..8f198f1f3 100644 --- a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/output.json +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/output.json @@ -4,10 +4,10 @@ "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -298,10 +298,10 @@ object \"A1_14\" { "A2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -594,10 +594,10 @@ object \"A2_27\" { "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -888,10 +888,10 @@ object \"A1_42\" { "B2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -1181,12 +1181,7 @@ object \"B2_55\" { } } }, - "ethdebug": { - "sources": [ - "a.sol", - "b.sol" - ] - }, + "ethdebug": "", "sources": { "a.sol": { "id": 0 diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/strip-ethdebug b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/output.json index f8fb2ce27..7694acea6 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/output.json @@ -4,10 +4,10 @@ "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -184,10 +184,10 @@ object \"A1_14\" { "A2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -366,10 +366,10 @@ object \"A2_27\" { "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -546,10 +546,10 @@ object \"A1_42\" { "B2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -725,12 +725,7 @@ object \"B2_55\" { } } }, - "ethdebug": { - "sources": [ - "a.sol", - "b.sol" - ] - }, + "ethdebug": "", "sources": { "a.sol": { "id": 0 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/output.json index 66b9082dc..b129a0c91 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/output.json @@ -4,10 +4,10 @@ "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -129,10 +129,10 @@ object \"A1_14\" { "A2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -256,10 +256,10 @@ object \"A2_27\" { "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -381,10 +381,10 @@ object \"A1_42\" { "B2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" }, "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -505,12 +505,7 @@ object \"B2_55\" { } } }, - "ethdebug": { - "sources": [ - "a.sol", - "b.sol" - ] - }, + "ethdebug": "", "sources": { "a.sol": { "id": 0 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/output.json index fabb25ee6..c7463f124 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/output.json @@ -4,7 +4,7 @@ "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -181,7 +181,7 @@ object \"A1_14\" { "A2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -360,7 +360,7 @@ object \"A2_27\" { "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -537,7 +537,7 @@ object \"A1_42\" { "B2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -713,12 +713,7 @@ object \"B2_55\" { } } }, - "ethdebug": { - "sources": [ - "a.sol", - "b.sol" - ] - }, + "ethdebug": "", "sources": { "a.sol": { "id": 0 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/output.json index d7284ab64..eab40879c 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/output.json @@ -4,7 +4,7 @@ "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -126,7 +126,7 @@ object \"A1_14\" { "A2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -250,7 +250,7 @@ object \"A2_27\" { "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -372,7 +372,7 @@ object \"A1_42\" { "B2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -493,12 +493,7 @@ object \"B2_55\" { } } }, - "ethdebug": { - "sources": [ - "a.sol", - "b.sol" - ] - }, + "ethdebug": "", "sources": { "a.sol": { "id": 0 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/output.json index 4c7b4ed67..8a8080833 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/output.json @@ -4,7 +4,7 @@ "A1": { "evm": { "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -181,7 +181,7 @@ object \"A1_14\" { "A2": { "evm": { "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -360,7 +360,7 @@ object \"A2_27\" { "A1": { "evm": { "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -537,7 +537,7 @@ object \"A1_42\" { "B2": { "evm": { "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -713,12 +713,7 @@ object \"B2_55\" { } } }, - "ethdebug": { - "sources": [ - "a.sol", - "b.sol" - ] - }, + "ethdebug": "", "sources": { "a.sol": { "id": 0 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/output.json index dce2a276e..4f3bd68ee 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/output.json @@ -4,7 +4,7 @@ "A1": { "evm": { "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -126,7 +126,7 @@ object \"A1_14\" { "A2": { "evm": { "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -250,7 +250,7 @@ object \"A2_27\" { "A1": { "evm": { "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -372,7 +372,7 @@ object \"A1_42\" { "B2": { "evm": { "deployedBytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -493,12 +493,7 @@ object \"B2_55\" { } } }, - "ethdebug": { - "sources": [ - "a.sol", - "b.sol" - ] - }, + "ethdebug": "", "sources": { "a.sol": { "id": 0 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json index fabb25ee6..c7463f124 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json @@ -4,7 +4,7 @@ "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -181,7 +181,7 @@ object \"A1_14\" { "A2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -360,7 +360,7 @@ object \"A2_27\" { "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -537,7 +537,7 @@ object \"A1_42\" { "B2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -713,12 +713,7 @@ object \"B2_55\" { } } }, - "ethdebug": { - "sources": [ - "a.sol", - "b.sol" - ] - }, + "ethdebug": "", "sources": { "a.sol": { "id": 0 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_ir/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_ir/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json index d7284ab64..eab40879c 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json @@ -4,7 +4,7 @@ "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -126,7 +126,7 @@ object \"A1_14\" { "A2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -250,7 +250,7 @@ object \"A2_27\" { "A1": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -372,7 +372,7 @@ object \"A1_42\" { "B2": { "evm": { "bytecode": { - "ethdebug": {} + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -493,12 +493,7 @@ object \"B2_55\" { } } }, - "ethdebug": { - "sources": [ - "a.sol", - "b.sol" - ] - }, + "ethdebug": "", "sources": { "a.sol": { "id": 0 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/strip-ethdebug b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/output.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/output.json index 63d48b80b..2b2f395fa 100644 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/output.json +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/output.json @@ -4,9 +4,7 @@ "C_6_deployed": { "evm": { "bytecode": { - "ethdebug": { - "not yet implemented @ MachineAssemblyObject::ethdebug": true - } + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -40,9 +38,5 @@ object \"C_6_deployed\" { } } }, - "ethdebug": { - "sources": [ - "C" - ] - } + "ethdebug": "" } diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/strip-ethdebug b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/args b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/in.yul b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/in.yul new file mode 100644 index 000000000..182cdc75d --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/in.yul @@ -0,0 +1,11 @@ +{ + let x := 2 + let y := sub(x, 2) + let t := verbatim_2i_1o("abc", x, y) + sstore(t, x) + let r := verbatim_0i_1o("def") + verbatim_0i_0o("xyz") + // more than 32 bytes + verbatim_0i_0o(hex"01020304050607090001020304050607090001020304050607090001020102030405060709000102030405060709000102030405060709000102") + r := 9 +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json new file mode 100644 index 000000000..be4fbb64f --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json @@ -0,0 +1,16 @@ +{ + "language": "Yul", + "sources": { + "C": { + "urls": [ + "standard_yul_debug_info_ethdebug_verbatim_unimplemented/in.yul" + ] + } + }, + "settings": { + "debug": {"debugInfo": ["ethdebug"]}, + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/output.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/output.json new file mode 100644 index 000000000..b645222de --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/output.json @@ -0,0 +1,13 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "UnimplementedFeatureError: Verbatim bytecode is currently not supported by ethdebug. + +", + "message": "Verbatim bytecode is currently not supported by ethdebug.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/args b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/in.yul b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/in.yul new file mode 100644 index 000000000..5c098cc80 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/in.yul @@ -0,0 +1,7 @@ +object "a" { + code { + { + setimmutable(0, "long___name___that___definitely___exceeds___the___thirty___two___byte___limit", 0x1234567890123456789012345678901234567890) + } + } +} \ No newline at end of file diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json new file mode 100644 index 000000000..83acd4c42 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_assign_immutable/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/output.json b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/output.json new file mode 100644 index 000000000..3af82e21d --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/output.json @@ -0,0 +1,127 @@ +{ + "contracts": { + "C": { + "a": { + "evm": { + "bytecode": { + "ethdebug": { + "contract": { + "definition": { + "source": { + "id": 0 + } + }, + "name": "" + }, + "environment": "create", + "instructions": [ + { + "context": { + "code": { + "range": { + "length": 42, + "offset": 165 + }, + "source": { + "id": 0 + } + } + }, + "offset": 0, + "operation": { + "arguments": [ + "0x1234567890123456789012345678901234567890" + ], + "mnemonic": "PUSH20" + } + }, + { + "context": { + "code": { + "range": { + "length": 1, + "offset": 81 + }, + "source": { + "id": 0 + } + } + }, + "offset": 21, + "operation": { + "mnemonic": "PUSH0" + } + }, + { + "context": { + "code": { + "range": { + "length": 140, + "offset": 68 + }, + "source": { + "id": 0 + } + } + }, + "offset": 22, + "operation": { + "mnemonic": "POP" + } + }, + { + "context": { + "code": { + "range": { + "length": 140, + "offset": 68 + }, + "source": { + "id": 0 + } + } + }, + "offset": 23, + "operation": { + "mnemonic": "POP" + } + }, + { + "context": { + "code": { + "range": { + "length": 180, + "offset": 44 + }, + "source": { + "id": 0 + } + } + }, + "offset": 24, + "operation": { + "mnemonic": "STOP" + } + } + ] + } + } + } + } + } + }, + "ethdebug": { + "compilation": { + "compiler": { + "name": "solc", + "version": "" + }, + "sources": [ + { + "id": 0, + "path": "C" + } + ] + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/output.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/output.json index c9ab1d8f5..c1f6523d5 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/output.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/output.json @@ -4,9 +4,7 @@ "C_6_deployed": { "evm": { "bytecode": { - "ethdebug": { - "not yet implemented @ MachineAssemblyObject::ethdebug": true - } + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -25,9 +23,5 @@ object \"C_6_deployed\" { } } }, - "ethdebug": { - "sources": [ - "C" - ] - } + "ethdebug": "" } diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json index d7e3e6be3..2f1d22b4d 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json @@ -4,9 +4,7 @@ "C_6_deployed": { "evm": { "bytecode": { - "ethdebug": { - "not yet implemented @ MachineAssemblyObject::ethdebug": true - } + "ethdebug": "" } }, "irOptimized": "/// ethdebug: enabled @@ -27,9 +25,5 @@ object \"C_6_deployed\" { } } }, - "ethdebug": { - "sources": [ - "C" - ] - } + "ethdebug": "" } diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul index 920aef8e9..d5adfd0c2 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul @@ -1,17 +1,19 @@ -/// @use-src 0:"input.sol" -object "C_6_deployed" { - code { - /// @src 0:60:101 "contract C {..." +object "object" { + code { mstore(64, 128) - - // f() fun_f_5() - - /// @src 0:77:99 "function f() public {}" function fun_f_5() { sstore(0, 42) } - /// @src 0:60:101 "contract C {..." } -} + object "object_deployed" { + code { + mstore(64, 128) + fun_f_5() + function fun_f_5() { + sstore(0, 42) + } + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/output.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/output.json index 1380c31d7..44183e45f 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/output.json +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/output.json @@ -1,11 +1,14 @@ { - "errors": [ - { - "component": "general", - "formattedMessage": "\"evm.deployedBytecode.ethdebug\" cannot be used for Yul.", - "message": "\"evm.deployedBytecode.ethdebug\" cannot be used for Yul.", - "severity": "error", - "type": "JSONError" + "contracts": { + "C": { + "object": { + "evm": { + "deployedBytecode": { + "ethdebug": "" + } + } + } } - ] + }, + "ethdebug": "" } diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/args b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/in.yul b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/in.yul new file mode 100644 index 000000000..d5adfd0c2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/in.yul @@ -0,0 +1,19 @@ +object "object" { + code { + mstore(64, 128) + fun_f_5() + function fun_f_5() { + sstore(0, 42) + } + } + + object "object_deployed" { + code { + mstore(64, 128) + fun_f_5() + function fun_f_5() { + sstore(0, 42) + } + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json new file mode 100644 index 000000000..207790120 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json @@ -0,0 +1,11 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_ethdebug_deployed_bytecode/in.yul"]} + }, + "settings": { + "outputSelection": { + "*": {"*": ["evm.deployedBytecode.ethdebug", "evm.bytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/output.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/output.json new file mode 100644 index 000000000..6d8064a94 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/output.json @@ -0,0 +1,17 @@ +{ + "contracts": { + "C": { + "object": { + "evm": { + "bytecode": { + "ethdebug": "" + }, + "deployedBytecode": { + "ethdebug": "" + } + } + } + } + }, + "ethdebug": "" +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/output.json b/test/cmdlineTests/standard_yul_ethdebug_ir/output.json index c9ab1d8f5..c1f6523d5 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_ir/output.json +++ b/test/cmdlineTests/standard_yul_ethdebug_ir/output.json @@ -4,9 +4,7 @@ "C_6_deployed": { "evm": { "bytecode": { - "ethdebug": { - "not yet implemented @ MachineAssemblyObject::ethdebug": true - } + "ethdebug": "" } }, "ir": "/// ethdebug: enabled @@ -25,9 +23,5 @@ object \"C_6_deployed\" { } } }, - "ethdebug": { - "sources": [ - "C" - ] - } + "ethdebug": "" } diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_ir/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json index 47d0008f1..6323c1157 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json @@ -4,17 +4,11 @@ "C_6_deployed": { "evm": { "bytecode": { - "ethdebug": { - "not yet implemented @ MachineAssemblyObject::ethdebug": true - } + "ethdebug": "" } } } } }, - "ethdebug": { - "sources": [ - "C" - ] - } + "ethdebug": "" } diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/yul_ethdebug/args b/test/cmdlineTests/yul_ethdebug/args deleted file mode 100644 index a800f5c34..000000000 --- a/test/cmdlineTests/yul_ethdebug/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug --strict-assembly \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug/input.yul b/test/cmdlineTests/yul_ethdebug/input.yul deleted file mode 100644 index acd0b45f5..000000000 --- a/test/cmdlineTests/yul_ethdebug/input.yul +++ /dev/null @@ -1,18 +0,0 @@ -object "object" { - code { - let a - let b - { - function z() -> y - { y := calldataload(0) } - a := z() - } - { - function z() -> y - { y := calldataload(0x20) } - b := z() - } - sstore(a, b) - } -} - diff --git a/test/cmdlineTests/yul_ethdebug/output b/test/cmdlineTests/yul_ethdebug/output deleted file mode 100644 index 84ba9317b..000000000 --- a/test/cmdlineTests/yul_ethdebug/output +++ /dev/null @@ -1,7 +0,0 @@ -======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["yul_ethdebug/input.yul"]} - -======= yul_ethdebug/input.yul (EVM) ======= - -Debug Data (ethdebug/format/program): -{"not yet implemented @ MachineAssemblyObject::ethdebug":true} diff --git a/test/cmdlineTests/yul_ethdebug_ir/args b/test/cmdlineTests/yul_ethdebug_ir/args deleted file mode 100644 index 6194b51b6..000000000 --- a/test/cmdlineTests/yul_ethdebug_ir/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug --strict-assembly --ir \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug_ir/err b/test/cmdlineTests/yul_ethdebug_ir/err deleted file mode 100644 index 645f7557a..000000000 --- a/test/cmdlineTests/yul_ethdebug_ir/err +++ /dev/null @@ -1 +0,0 @@ -Error: The following outputs are not supported in assembler mode: --ir. diff --git a/test/cmdlineTests/yul_ethdebug_ir/exit b/test/cmdlineTests/yul_ethdebug_ir/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/yul_ethdebug_ir/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/yul_ethdebug_ir/input.yul b/test/cmdlineTests/yul_ethdebug_ir/input.yul deleted file mode 100644 index acd0b45f5..000000000 --- a/test/cmdlineTests/yul_ethdebug_ir/input.yul +++ /dev/null @@ -1,18 +0,0 @@ -object "object" { - code { - let a - let b - { - function z() -> y - { y := calldataload(0) } - a := z() - } - { - function z() -> y - { y := calldataload(0x20) } - b := z() - } - sstore(a, b) - } -} - diff --git a/test/cmdlineTests/yul_ethdebug_iroptimized/args b/test/cmdlineTests/yul_ethdebug_iroptimized/args deleted file mode 100644 index 2063d860c..000000000 --- a/test/cmdlineTests/yul_ethdebug_iroptimized/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug --strict-assembly --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug_iroptimized/input.yul b/test/cmdlineTests/yul_ethdebug_iroptimized/input.yul deleted file mode 100644 index acd0b45f5..000000000 --- a/test/cmdlineTests/yul_ethdebug_iroptimized/input.yul +++ /dev/null @@ -1,18 +0,0 @@ -object "object" { - code { - let a - let b - { - function z() -> y - { y := calldataload(0) } - a := z() - } - { - function z() -> y - { y := calldataload(0x20) } - b := z() - } - sstore(a, b) - } -} - diff --git a/test/cmdlineTests/yul_ethdebug_iroptimized/output b/test/cmdlineTests/yul_ethdebug_iroptimized/output deleted file mode 100644 index e2f0ed7f9..000000000 --- a/test/cmdlineTests/yul_ethdebug_iroptimized/output +++ /dev/null @@ -1,26 +0,0 @@ -======= Debug Data (ethdebug/format/info/resources) ======= -{"sources":["yul_ethdebug_iroptimized/input.yul"]} - -======= yul_ethdebug_iroptimized/input.yul (EVM) ======= - -Pretty printed source: -/// ethdebug: enabled -object "object" { - code { - { - let a - let b - a := z() - b := z_1() - sstore(a, b) - } - function z() -> y - { y := calldataload(0) } - function z_1() -> y - { y := calldataload(0x20) } - } -} - - -Debug Data (ethdebug/format/program): -{"not yet implemented @ MachineAssemblyObject::ethdebug":true} diff --git a/test/cmdlineTests/yul_ethdebug_optimize/args b/test/cmdlineTests/yul_ethdebug_optimize/args deleted file mode 100644 index fd081fdaf..000000000 --- a/test/cmdlineTests/yul_ethdebug_optimize/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug --strict-assembly --optimize \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug_optimize/err b/test/cmdlineTests/yul_ethdebug_optimize/err deleted file mode 100644 index 7d6613875..000000000 --- a/test/cmdlineTests/yul_ethdebug_optimize/err +++ /dev/null @@ -1 +0,0 @@ -Error: Optimization (using --optimize) is not yet supported with ethdebug. diff --git a/test/cmdlineTests/yul_ethdebug_optimize/exit b/test/cmdlineTests/yul_ethdebug_optimize/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/yul_ethdebug_optimize/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/yul_ethdebug_optimize/input.yul b/test/cmdlineTests/yul_ethdebug_optimize/input.yul deleted file mode 100644 index acd0b45f5..000000000 --- a/test/cmdlineTests/yul_ethdebug_optimize/input.yul +++ /dev/null @@ -1,18 +0,0 @@ -object "object" { - code { - let a - let b - { - function z() -> y - { y := calldataload(0) } - a := z() - } - { - function z() -> y - { y := calldataload(0x20) } - b := z() - } - sstore(a, b) - } -} - diff --git a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/args b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/args deleted file mode 100644 index 715f3fb48..000000000 --- a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug --strict-assembly --optimize --ir-optimized \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/err b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/err deleted file mode 100644 index 7d6613875..000000000 --- a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/err +++ /dev/null @@ -1 +0,0 @@ -Error: Optimization (using --optimize) is not yet supported with ethdebug. diff --git a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/exit b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/input.yul b/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/input.yul deleted file mode 100644 index acd0b45f5..000000000 --- a/test/cmdlineTests/yul_ethdebug_optimize_iroptimized/input.yul +++ /dev/null @@ -1,18 +0,0 @@ -object "object" { - code { - let a - let b - { - function z() -> y - { y := calldataload(0) } - a := z() - } - { - function z() -> y - { y := calldataload(0x20) } - b := z() - } - sstore(a, b) - } -} - diff --git a/test/cmdlineTests/yul_ethdebug_runtime/args b/test/cmdlineTests/yul_ethdebug_runtime/args deleted file mode 100644 index 3bedf2d9e..000000000 --- a/test/cmdlineTests/yul_ethdebug_runtime/args +++ /dev/null @@ -1 +0,0 @@ ---ethdebug-runtime --strict-assembly \ No newline at end of file diff --git a/test/cmdlineTests/yul_ethdebug_runtime/err b/test/cmdlineTests/yul_ethdebug_runtime/err deleted file mode 100644 index ed5894632..000000000 --- a/test/cmdlineTests/yul_ethdebug_runtime/err +++ /dev/null @@ -1 +0,0 @@ -Error: The following outputs are not supported in assembler mode: --ethdebug-runtime. diff --git a/test/cmdlineTests/yul_ethdebug_runtime/exit b/test/cmdlineTests/yul_ethdebug_runtime/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/yul_ethdebug_runtime/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/yul_ethdebug_runtime/input.yul b/test/cmdlineTests/yul_ethdebug_runtime/input.yul deleted file mode 100644 index acd0b45f5..000000000 --- a/test/cmdlineTests/yul_ethdebug_runtime/input.yul +++ /dev/null @@ -1,18 +0,0 @@ -object "object" { - code { - let a - let b - { - function z() -> y - { y := calldataload(0) } - a := z() - } - { - function z() -> y - { y := calldataload(0x20) } - b := z() - } - sstore(a, b) - } -} - diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 3a6383002..6a41f7a73 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -425,6 +426,46 @@ BOOST_AUTO_TEST_CASE(subobject_encode_decode) BOOST_CHECK(assembly.decodeSubPath(assembly.encodeSubPath(subPath)) == subPath); } +BOOST_AUTO_TEST_CASE(ethdebug_program_last_instruction_with_immediate_arguments) +{ + EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion(); + { + Assembly assembly{evmVersion, true, {}, {}}; + assembly.append(AssemblyItem{0x11223344}); + LinkerObject output = assembly.assemble(); + + Json const program = ethdebug::program("", 0, &assembly, output); + BOOST_REQUIRE(program["instructions"].size() == 1); + BOOST_REQUIRE(program["instructions"][0]["operation"]["mnemonic"] == "PUSH4"); + BOOST_REQUIRE(program["instructions"][0]["operation"]["arguments"][0] == "0x11223344"); + } + { + Assembly assembly{evmVersion, true, {}, {}}; + assembly.append(AssemblyItem{Instruction::PUSH0}); + assembly.append(AssemblyItem{0x1122334455}); + LinkerObject output = assembly.assemble(); + + Json const program = ethdebug::program("", 0, &assembly, output); + BOOST_REQUIRE(program["instructions"].size() == 2); + BOOST_REQUIRE(program["instructions"][0]["operation"]["mnemonic"] == "PUSH0"); + BOOST_REQUIRE(!program["instructions"][0]["operation"].contains("arguments")); + BOOST_REQUIRE(program["instructions"][1]["operation"]["mnemonic"] == "PUSH5"); + BOOST_REQUIRE(program["instructions"][1]["operation"]["arguments"][0] == "0x1122334455"); + } +} + +BOOST_AUTO_TEST_CASE(ethdebug_resources) +{ + Json const resources = ethdebug::resources({"sourceA", "sourceB"}, "version1"); + BOOST_REQUIRE(resources["compilation"]["compiler"]["name"] == "solc"); + BOOST_REQUIRE(resources["compilation"]["compiler"]["version"] == "version1"); + BOOST_REQUIRE(resources["compilation"]["sources"].size() == 2); + BOOST_REQUIRE(resources["compilation"]["sources"][0]["id"] == 0); + BOOST_REQUIRE(resources["compilation"]["sources"][0]["path"] == "sourceA"); + BOOST_REQUIRE(resources["compilation"]["sources"][1]["id"] == 1); + BOOST_REQUIRE(resources["compilation"]["sources"][1]["path"] == "sourceB"); +} + BOOST_AUTO_TEST_SUITE_END() } // end namespaces diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index ec3c7db1c..b17f56661 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -2232,6 +2233,46 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) } } +BOOST_DATA_TEST_CASE(ethdebug_output_instructions_smoketest, boost::unit_test::data::make({"deployedBytecode", "bytecode"}), bytecodeType) +{ + frontend::StandardCompiler compiler; + Json result = compiler.compile(generateStandardJson(true, {}, Json::array({std::string("evm.") + bytecodeType + ".ethdebug"}))); + BOOST_REQUIRE(result["contracts"]["fileA"]["C"]["evm"][bytecodeType].contains("ethdebug")); + bool creation = std::string(bytecodeType) == "bytecode"; + Json ethdebugInstructionsToCheck = result["contracts"]["fileA"]["C"]["evm"][bytecodeType]["ethdebug"]; + BOOST_REQUIRE(ethdebugInstructionsToCheck["contract"]["definition"]["source"]["id"] == 0); + BOOST_REQUIRE(ethdebugInstructionsToCheck["contract"]["name"] == "C"); + BOOST_REQUIRE(ethdebugInstructionsToCheck["environment"] == (creation ? "create" : "call")); + BOOST_REQUIRE(ethdebugInstructionsToCheck["instructions"].is_array()); + for (auto const& instruction: ethdebugInstructionsToCheck["instructions"]) + { + BOOST_REQUIRE(instruction.contains("offset")); + BOOST_REQUIRE(instruction.contains("operation")); + BOOST_REQUIRE(instruction["operation"].contains("mnemonic")); + BOOST_REQUIRE(instruction["context"]["code"]["range"].contains("length")); + BOOST_REQUIRE(instruction["context"]["code"]["range"].contains("offset")); + BOOST_REQUIRE(instruction["context"]["code"]["source"].contains("id")); + std::string mnemonic = instruction["operation"]["mnemonic"]; + if (mnemonic.find("PUSH") != std::string::npos) + { + size_t bytesToPush = boost::lexical_cast(mnemonic.substr(4)); + if (bytesToPush > 0) + { + BOOST_REQUIRE(instruction["operation"].contains("arguments")); + BOOST_REQUIRE(instruction["operation"]["arguments"].is_array()); + BOOST_REQUIRE(instruction["operation"]["arguments"].size() == 1); + std::string argument = instruction["operation"]["arguments"][0]; + BOOST_REQUIRE(argument.length() % 2 == 0); + BOOST_REQUIRE(bytesToPush == (argument.length() - 2) / 2); // remove "0x" and calculate actual byte size from hex. + } + else + BOOST_REQUIRE(!instruction["operation"].contains("arguments")); + } + else + BOOST_REQUIRE(!instruction["operation"].contains("arguments")); + } +} + BOOST_AUTO_TEST_SUITE_END() } // end namespaces From 2abfe0baa9f4b64521adf271984951d6760b0453 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Tue, 11 Mar 2025 02:07:46 +0100 Subject: [PATCH 0767/1340] ethdebug: correct handling of abstract contracts. --- libevmasm/Ethdebug.cpp | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/libevmasm/Ethdebug.cpp b/libevmasm/Ethdebug.cpp index 7b5de2ba9..6e635ef57 100644 --- a/libevmasm/Ethdebug.cpp +++ b/libevmasm/Ethdebug.cpp @@ -25,32 +25,27 @@ using namespace solidity::evmasm::ethdebug; namespace { -Json programInstructions(Assembly const* _assembly, LinkerObject const& _linkerObject, unsigned _sourceId) +Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned _sourceId) { - // e.g. interfaces don't have a valid assembly object. - if (_assembly) - { - solUnimplementedAssert(_assembly->eofVersion() == std::nullopt, "ethdebug does not yet support EOF."); - solUnimplementedAssert(_assembly->codeSections().size() == 1, "ethdebug does not yet support multiple code-sections."); - for (auto const& instruction: _assembly->codeSections()[0].items) - solUnimplementedAssert(instruction.type() != VerbatimBytecode, "Verbatim bytecode is currently not supported by ethdebug."); - } + solUnimplementedAssert(_assembly.eofVersion() == std::nullopt, "ethdebug does not yet support EOF."); + solUnimplementedAssert(_assembly.codeSections().size() == 1, "ethdebug does not yet support multiple code-sections."); + for (auto const& instruction: _assembly.codeSections()[0].items) + solUnimplementedAssert(instruction.type() != VerbatimBytecode, "Verbatim bytecode is currently not supported by ethdebug."); solAssert(_linkerObject.codeSectionLocations.size() == 1); solAssert(_linkerObject.codeSectionLocations[0].end <= _linkerObject.bytecode.size()); Json instructions = Json::array(); for (size_t i = 0; i < _linkerObject.codeSectionLocations[0].instructionLocations.size(); ++i) { - solAssert(_assembly); LinkerObject::InstructionLocation currentInstruction = _linkerObject.codeSectionLocations[0].instructionLocations[i]; size_t start = currentInstruction.start; size_t end = currentInstruction.end; size_t assemblyItemIndex = currentInstruction.assemblyItemIndex; solAssert(end <= _linkerObject.bytecode.size()); solAssert(start < end); - solAssert(assemblyItemIndex < _assembly->codeSections().at(0).items.size()); + solAssert(assemblyItemIndex < _assembly.codeSections().at(0).items.size()); Json operation = Json::object(); - operation["mnemonic"] = instructionInfo(static_cast(_linkerObject.bytecode[start]), _assembly->evmVersion()).name; + operation["mnemonic"] = instructionInfo(static_cast(_linkerObject.bytecode[start]), _assembly.evmVersion()).name; static size_t constexpr instructionSize = 1; if (start + instructionSize < end) { @@ -61,7 +56,7 @@ Json programInstructions(Assembly const* _assembly, LinkerObject const& _linkerO solAssert(!argumentData.empty()); operation["arguments"] = Json::array({util::toHex(argumentData, util::HexPrefix::Add)}); } - langutil::SourceLocation const& location = _assembly->codeSections().at(0).items.at(assemblyItemIndex).location(); + langutil::SourceLocation const& location = _assembly.codeSections().at(0).items.at(assemblyItemIndex).location(); Json instruction = Json::object(); instruction["offset"] = start; instruction["operation"] = operation; @@ -90,8 +85,11 @@ Json ethdebug::program(std::string_view _name, unsigned _sourceId, Assembly cons result["contract"]["definition"] = Json::object(); result["contract"]["definition"]["source"] = Json::object(); result["contract"]["definition"]["source"]["id"] = _sourceId; - result["environment"] = (!_assembly || _assembly->isCreation()) ? "create" : "call"; - result["instructions"] = programInstructions(_assembly, _linkerObject, _sourceId); + if (_assembly) + { + result["environment"] = _assembly->isCreation() ? "create" : "call"; + result["instructions"] = programInstructions(*_assembly, _linkerObject, _sourceId); + } return result; } From 9c80b9b62b9ac0d60d6d76affcdcc86659c95072 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 4 Mar 2025 00:18:42 -0300 Subject: [PATCH 0768/1340] Update and add tests --- .../storageLayoutSpecifier/warning_near_the_storage_end.sol | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/warning_near_the_storage_end.sol diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/warning_near_the_storage_end.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/warning_near_the_storage_end.sol new file mode 100644 index 000000000..b1647e463 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/warning_near_the_storage_end.sol @@ -0,0 +1,6 @@ +contract A layout at 2**256 - 2**64 {} +contract C layout at 2**256 - 2**65 { + uint[2**63] x; + uint[2**63] y; +} +// ---- From 529795019c766e2aced54455ce613254b1865df9 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 4 Mar 2025 00:19:40 -0300 Subject: [PATCH 0769/1340] Warn when layout base is near the end of storage --- .../analysis/PostTypeContractLevelChecker.cpp | 61 +++++++++++++++++++ .../analysis/PostTypeContractLevelChecker.h | 2 + ...e_array_with_transient_state_variables.sol | 1 + .../contract_at_storage_end.sol | 1 + ...age_end_with_transient_state_variables.sol | 1 + .../intermediate_operation_out_of_range.sol | 1 + .../layout_specification_max_value.sol | 1 + .../warning_near_the_storage_end.sol | 2 + 8 files changed, 70 insertions(+) diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.cpp b/libsolidity/analysis/PostTypeContractLevelChecker.cpp index 657f39284..c7b7b0961 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.cpp +++ b/libsolidity/analysis/PostTypeContractLevelChecker.cpp @@ -29,6 +29,8 @@ #include #include +#include + #include using namespace solidity; @@ -76,6 +78,8 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract) if (_contract.storageLayoutSpecifier()) checkStorageLayoutSpecifier(_contract); + warnStorageLayoutBaseNearStorageEnd(_contract); + return !Error::containsErrors(m_errorReporter.errors()); } @@ -145,3 +149,60 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinitio "Contract extends past the end of storage when this base slot value is specified." ); } + +namespace +{ + +VariableDeclaration const* findLastStorageVariable(ContractDefinition const& _contract) +{ + for (ContractDefinition const* baseContract: ranges::actions::reverse(_contract.annotation().linearizedBaseContracts)) + for (VariableDeclaration const* stateVariable: ranges::actions::reverse(baseContract->stateVariables())) + if (stateVariable->referenceLocation() == VariableDeclaration::Location::Unspecified) + return stateVariable; + + return nullptr; +} + +} + +void PostTypeContractLevelChecker::warnStorageLayoutBaseNearStorageEnd(ContractDefinition const& _contract) +{ + // In case of most errors the warning is pointless. E.g. if we're already past storage end. + // If the errors were in the layout specifier, we may not even be able to get values to validate. + if (Error::containsErrors(m_errorReporter.errors())) + return; + + bigint storageSize = contractStorageSizeUpperBound(_contract, VariableDeclaration::Location::Unspecified); + u256 baseSlot = layoutBaseForInheritanceHierarchy(_contract, DataLocation::Storage); + solAssert(baseSlot + storageSize <= std::numeric_limits::max()); + + if ( + u256 slotsLeft = std::numeric_limits::max() - baseSlot - u256(storageSize); + slotsLeft <= u256(1) << 64 + ) + { + auto const& location = _contract.storageLayoutSpecifier() ? + _contract.storageLayoutSpecifier()->location() : + _contract.location(); + + VariableDeclaration const* lastStorageVariable = findLastStorageVariable(_contract); + + auto errorID = 3495_error; + std::string errorMsg = "This contract is very close to the end of storage. This limits its future upgradability."; + if (lastStorageVariable) + m_errorReporter.warning( + errorID, + location, + errorMsg, + SecondarySourceLocation{}.append( + fmt::format( + "There are {} storage slots between this state variable and the end of storage.", + formatNumberReadable(slotsLeft) + ), + lastStorageVariable->location() + ) + ); + else + m_errorReporter.warning(errorID, location, errorMsg); + } +} diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.h b/libsolidity/analysis/PostTypeContractLevelChecker.h index 2fa2cb11b..ca7247c46 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.h +++ b/libsolidity/analysis/PostTypeContractLevelChecker.h @@ -52,6 +52,8 @@ class PostTypeContractLevelChecker void checkStorageLayoutSpecifier(ContractDefinition const& _contract); + void warnStorageLayoutBaseNearStorageEnd(ContractDefinition const& _contract); + langutil::ErrorReporter& m_errorReporter; }; diff --git a/test/libsolidity/syntaxTests/largeTypes/max_size_array_with_transient_state_variables.sol b/test/libsolidity/syntaxTests/largeTypes/max_size_array_with_transient_state_variables.sol index 280fb81c8..43acb5b14 100644 --- a/test/libsolidity/syntaxTests/largeTypes/max_size_array_with_transient_state_variables.sol +++ b/test/libsolidity/syntaxTests/largeTypes/max_size_array_with_transient_state_variables.sol @@ -5,4 +5,5 @@ contract C { // ==== // EVMVersion: >=cancun // ---- +// Warning 3495: (0-60): This contract is very close to the end of storage. This limits its future upgradability. // Warning 7325: (17-33): Type uint256[115792089237316195423570985008687907853269984665640564039457584007913129639935] covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end.sol index 29733c9ca..e215c26cf 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end.sol @@ -1,3 +1,4 @@ contract C layout at 2**256 - 1 { } // ---- +// Warning 3495: (11-31): This contract is very close to the end of storage. This limits its future upgradability. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end_with_transient_state_variables.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end_with_transient_state_variables.sol index fb1008616..89012b781 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end_with_transient_state_variables.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/contract_at_storage_end_with_transient_state_variables.sol @@ -6,3 +6,4 @@ contract C layout at 2**256 - 1 { // ==== // EVMVersion: >=cancun // ---- +// Warning 3495: (11-31): This contract is very close to the end of storage. This limits its future upgradability. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol index f74c45ed7..dd298820c 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/intermediate_operation_out_of_range.sol @@ -1,3 +1,4 @@ contract A layout at (2**256 + 1) * 2 - 2**256 - 3 {} contract B layout at (2**2 - 2**3) * (2**5 - 2**8) {} // ---- +// Warning 3495: (11-51): This contract is very close to the end of storage. This limits its future upgradability. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol index 793b5b268..cfdefa1ed 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_max_value.sol @@ -1,2 +1,3 @@ contract C layout at 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF {} // ---- +// Warning 3495: (11-87): This contract is very close to the end of storage. This limits its future upgradability. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/warning_near_the_storage_end.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/warning_near_the_storage_end.sol index b1647e463..5d1f777fd 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/warning_near_the_storage_end.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/warning_near_the_storage_end.sol @@ -4,3 +4,5 @@ contract C layout at 2**256 - 2**65 { uint[2**63] y; } // ---- +// Warning 3495: (11-35): This contract is very close to the end of storage. This limits its future upgradability. +// Warning 3495: (50-74): This contract is very close to the end of storage. This limits its future upgradability. From 05b0efbd04eafec21a43f08925efb82e0c7a1023 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 25 Feb 2025 17:04:22 -0300 Subject: [PATCH 0770/1340] Storage layout specifier docs --- docs/contracts.rst | 1 + docs/contracts/custom-storage-layout.rst | 50 +++++++++++++++++++++ docs/internals/layout_in_storage.rst | 55 ++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 docs/contracts/custom-storage-layout.rst diff --git a/docs/contracts.rst b/docs/contracts.rst index 588b1da00..b47b4aa45 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -23,6 +23,7 @@ There is no "cron" concept in Ethereum to call a function at a particular event .. include:: contracts/transient-storage.rst .. include:: contracts/constant-state-variables.rst +.. include:: contracts/custom-storage-layout.rst .. include:: contracts/functions.rst .. include:: contracts/events.rst diff --git a/docs/contracts/custom-storage-layout.rst b/docs/contracts/custom-storage-layout.rst new file mode 100644 index 000000000..484ca6a8b --- /dev/null +++ b/docs/contracts/custom-storage-layout.rst @@ -0,0 +1,50 @@ +.. index:: ! custom storage layout, ! storage layout specifier, ! layout at, ! base slot + +.. _custom-storage-layout: + +********************* +Custom Storage Layout +********************* + +Contracts can define an arbitrary base slot for its own storage. +The contract's state variables, including those inherited from base contracts, +will be stored from the specified slot instead of the default slot zero. + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.29; + + contract C layout at 0xABCD + 0x1234 { } + +As the previous example shows, this can be done by using ``layout at `` +in the header of a contract definition. + +The layout specifier can be placed either before or after the inheritance specifier, and at most once. +The ``base-slot-expression`` must be an :ref:`integer literal` expression +that can be evaluated at compile time and yield a value in the range of ``uint256``. + +In the case of a custom storage layout specification which places the contract near the storage end, +the number of slots available for static objects is determined by ``max storage size - base slot`` and +the compiler can detect whether the contract extends past the end. +For dynamic typed variables, they are allocated in random locations of the storage, including those before +the layout base slot. +It is also important to mention that, in cases where the contract is near the end of storage, there are +risks related to upgradeability and inline assembly access beyond allocated space. + +The location of a contract's state variable is determined by its position in the hierarchy tree. +Inherited variables will be stored before the state variables declared by the contract itself and +that changes the slots where they should be placed. +Similarly, when a contract specifies a custom storage layout, not only its own storage variables are shifted, +but also all other variables from contracts in the same inheritance tree. +Thus, the storage layout can only be specified at the top most contract of the inheritance tree, assuring +that all contracts of the tree have their layout base properly adjusted. + +The storage layout cannot be specified for abstract contracts, interfaces and libraries. +Also, it is important to note that it does **not** affect transient state variables. + +Further details are explained later when :ref:`layout of storage variables` are described. + +.. warning:: + The identifiers ``layout`` and ``at`` are not reserved keywords of the Solidity language, but + it is strongly recommended to avoid using them since that may change in the future. \ No newline at end of file diff --git a/docs/internals/layout_in_storage.rst b/docs/internals/layout_in_storage.rst index 557a0a0e2..aade16fb3 100644 --- a/docs/internals/layout_in_storage.rst +++ b/docs/internals/layout_in_storage.rst @@ -34,6 +34,61 @@ by the above rules, state variables from different contracts do share the same s The elements of structs and arrays are stored after each other, just as if they were given as individual values. +If a contract specifies a :ref:`custom storage layout`, the slots which +the state variables occupy are shifted according the value defined as the layout base. +The custom layout is specified in the most derived contract and, following the order explained +above, starting from the most base-ward contract's variables, all storage slots are adjusted. + +In the following example, contract ``C`` inherits from contracts ``A`` and ``B`` and also +specifies a custom storage base slot. +The result is that all variable storage slots of the inheritance tree will be adjusted according to +the value specified by ``C``. + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.29; + + struct S { + int32 a; + bool b; + } + + contract A { + uint x; + uint transient y; + uint constant w = 10; + uint immutable z = 12; + } + + contract B { + uint16 i; + uint16 j; + S s; + int8 k; + } + + contract C is A, B layout at 42 { + uint8[10] register; + bool flag; + } + +In the example, the storage layout starts with the inherited +state variable ``x`` stored at the specified base slot ``42``. +Transient, constant and immutable variables are stored in separate +locations and, thus, ``y``, ``w`` and ``z``don't interfere with the layout. +The next variables ``i`` and ``j`` need 2 bytes each and can be packed in +the next slot ``43``, at offsets ``0`` and ``2`` respectively. +Since ``s`` is a struct, its two members are packed contiguously, demanding +both 5 bytes. +Even though they still could fit in slot ``43``, structs and static arrays +always start a new slot as well as any other item after them. +So, according to that ``s`` is placed at slot ``44`` and the next variable, +``k`` at slot ``45``. +Then, variable ``register`` which is an array of 10 positions, starts at slot ``46`` +and demands 80 bytes. Finally, variable, ``flag``, start at slot ``47``, because, +as explained before, variables after structs and arrays always start a new slot. + .. warning:: When using elements that are smaller than 32 bytes, your contract's gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller From b4f9bb090bd2223771d5470aeb48a587ab5c0a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 11 Mar 2025 03:40:14 +0100 Subject: [PATCH 0771/1340] fixup! Storage layout specifier docs --- docs/contracts/custom-storage-layout.rst | 61 +++++++++++++----------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/docs/contracts/custom-storage-layout.rst b/docs/contracts/custom-storage-layout.rst index 484ca6a8b..341975eac 100644 --- a/docs/contracts/custom-storage-layout.rst +++ b/docs/contracts/custom-storage-layout.rst @@ -6,45 +6,52 @@ Custom Storage Layout ********************* -Contracts can define an arbitrary base slot for its own storage. +A contract can define an arbitrary location for its storage using the ``layout`` specifier. The contract's state variables, including those inherited from base contracts, -will be stored from the specified slot instead of the default slot zero. +start from the specified base slot instead of the default slot zero. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.29; - contract C layout at 0xABCD + 0x1234 { } + contract C layout at 0xAAAA + 0x11 { + uint[3] x; // Occupies slots 0xAABB..0xAABD + } -As the previous example shows, this can be done by using ``layout at `` -in the header of a contract definition. +As the above example shows, the specifier uses the ``layout at `` syntax +and is located in the header of a contract definition. -The layout specifier can be placed either before or after the inheritance specifier, and at most once. +The layout specifier can be placed either before or after the inheritance specifier, and can appear at most once. The ``base-slot-expression`` must be an :ref:`integer literal` expression -that can be evaluated at compile time and yield a value in the range of ``uint256``. - -In the case of a custom storage layout specification which places the contract near the storage end, -the number of slots available for static objects is determined by ``max storage size - base slot`` and -the compiler can detect whether the contract extends past the end. -For dynamic typed variables, they are allocated in random locations of the storage, including those before -the layout base slot. -It is also important to mention that, in cases where the contract is near the end of storage, there are -risks related to upgradeability and inline assembly access beyond allocated space. - -The location of a contract's state variable is determined by its position in the hierarchy tree. -Inherited variables will be stored before the state variables declared by the contract itself and -that changes the slots where they should be placed. -Similarly, when a contract specifies a custom storage layout, not only its own storage variables are shifted, -but also all other variables from contracts in the same inheritance tree. -Thus, the storage layout can only be specified at the top most contract of the inheritance tree, assuring -that all contracts of the tree have their layout base properly adjusted. +that can be evaluated at compilation time and yields a value in the range of ``uint256``. + +A custom layout cannot make contract's storage "wrap around". +If the selected base slot would push the statically-sized variables past the end of storage, +the compiler will issue an error. +Note that the data areas of dynamically-sized variables are not affected by this check because +their layout is not linear. +Regardless of the base slot used, their locations are calculated in a way that always puts them +within the range of ``uint256`` and their sizes are not known at compilation time. + +While there are no other limits placed on the base slot, it is recommended to avoid locations that are +too close to the end of the address space. +Leaving too little space may complicate contract upgrades or cause problems for contracts that store +additional values past their allocated space using inline assembly. + +The storage layout can only be specified for the topmost contract of an inheritance tree, and +affects locations of all the storage variables in all the contracts in that tree. +Variables are laid out according to the order of their definitions and the +positions of their contracts in the :ref:`linearized inheritance hierarchy` +and a custom base slot preserves their relative positions, shifting them all by the same amount. The storage layout cannot be specified for abstract contracts, interfaces and libraries. -Also, it is important to note that it does **not** affect transient state variables. +Also, it is important to note that it does *not* affect transient state variables. -Further details are explained later when :ref:`layout of storage variables` are described. +For details about storage layout and the effect of the layout specifier on it see +:ref:`layout of storage variables`. .. warning:: - The identifiers ``layout`` and ``at`` are not reserved keywords of the Solidity language, but - it is strongly recommended to avoid using them since that may change in the future. \ No newline at end of file + The identifiers ``layout`` and ``at`` are not yet reserved as keywords in the language. + It is strongly recommended to avoid using them since they will become reserved in a future + breaking release. From a371a4f8fe33c5a8159ad712e35c9d0c2819da42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 11 Mar 2025 05:17:31 +0100 Subject: [PATCH 0772/1340] fixup! Storage layout specifier docs --- docs/internals/layout_in_storage.rst | 31 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/docs/internals/layout_in_storage.rst b/docs/internals/layout_in_storage.rst index aade16fb3..034bfe29e 100644 --- a/docs/internals/layout_in_storage.rst +++ b/docs/internals/layout_in_storage.rst @@ -34,14 +34,16 @@ by the above rules, state variables from different contracts do share the same s The elements of structs and arrays are stored after each other, just as if they were given as individual values. -If a contract specifies a :ref:`custom storage layout`, the slots which -the state variables occupy are shifted according the value defined as the layout base. +If a contract specifies a :ref:`custom storage layout`, the slots assigned +to static storage variables are shifted according the value defined as the layout base. +Locations of dynamic arrays and mappings are also indirectly affected by this due to shifting +of the static slots they are based on. The custom layout is specified in the most derived contract and, following the order explained above, starting from the most base-ward contract's variables, all storage slots are adjusted. In the following example, contract ``C`` inherits from contracts ``A`` and ``B`` and also specifies a custom storage base slot. -The result is that all variable storage slots of the inheritance tree will be adjusted according to +The result is that all storage variable slots of the inheritance tree are adjusted according to the value specified by ``C``. .. code-block:: solidity @@ -74,19 +76,16 @@ the value specified by ``C``. } In the example, the storage layout starts with the inherited -state variable ``x`` stored at the specified base slot ``42``. +state variable ``x`` stored directly inside the base slot (slot ``42``). Transient, constant and immutable variables are stored in separate -locations and, thus, ``y``, ``w`` and ``z``don't interfere with the layout. -The next variables ``i`` and ``j`` need 2 bytes each and can be packed in -the next slot ``43``, at offsets ``0`` and ``2`` respectively. -Since ``s`` is a struct, its two members are packed contiguously, demanding -both 5 bytes. -Even though they still could fit in slot ``43``, structs and static arrays -always start a new slot as well as any other item after them. -So, according to that ``s`` is placed at slot ``44`` and the next variable, -``k`` at slot ``45``. -Then, variable ``register`` which is an array of 10 positions, starts at slot ``46`` -and demands 80 bytes. Finally, variable, ``flag``, start at slot ``47``, because, +locations and, thus, ``y``, ``w`` and ``z`` have no effect on the storage layout. +The next two variables, ``i`` and ``j``, need 2 bytes each and can be packed together into +slot ``43``, at offsets ``0`` and ``2`` respectively. +Since ``s`` is a struct, its two members are packed contiguously, each taking up 5 bytes. +Even though they both would still fit in slot ``43``, structs and arrays always start a new slot. +Therefore, ``s`` is placed in slot ``44`` and the next variable, ``k``, in slot ``45``. +Then, variable ``register`` which is an array of 10 items, gets into slot ``46`` and takes up 80 bytes. +Finally, variable ``flag`` ends up in slot ``47``, because, as explained before, variables after structs and arrays always start a new slot. .. warning:: @@ -518,4 +517,4 @@ Transient Storage Layout "numberOfBytes": "32" } } - } \ No newline at end of file + } From 3d0904796c6b1802ff28840f6944d8bfd2288f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 11 Mar 2025 05:17:44 +0100 Subject: [PATCH 0773/1340] fixup! Storage layout specifier docs --- docs/internals/layout_in_storage.rst | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/internals/layout_in_storage.rst b/docs/internals/layout_in_storage.rst index 034bfe29e..c9c5f6ee3 100644 --- a/docs/internals/layout_in_storage.rst +++ b/docs/internals/layout_in_storage.rst @@ -88,6 +88,38 @@ Then, variable ``register`` which is an array of 10 items, gets into slot ``46`` Finally, variable ``flag`` ends up in slot ``47``, because, as explained before, variables after structs and arrays always start a new slot. +Overall the storage and transient storage layouts of contract ``C`` can be illustrated as follows: + +- Storage: + :: + + 42 [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx] + 43 [ jjii] + 44 [ baaaa] + 45 [ k] + 46 [ rrrrrrrrrr] + 47 [ f] + +- Transient storage: + :: + + 00 [yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy] + +Note that the storage specifier affects ``A`` and ``B`` only as a part of ``C``'s inheritance hierarchy. +When deployed independently, their storage starts at ``0``: + +- Storage layout of ``A``: + :: + + 00 [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx] + +- Storage layout of ``B``: + :: + + 00 [ jjii] + 01 [ baaaa] + 02 [ k] + .. warning:: When using elements that are smaller than 32 bytes, your contract's gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller From e633eb411d71eaa1b46d774ded876d586420836e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 11 Mar 2025 06:05:48 +0100 Subject: [PATCH 0774/1340] fixup! Storage layout specifier docs --- docs/internals/layout_in_storage.rst | 80 +++++++++++++++++----------- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/docs/internals/layout_in_storage.rst b/docs/internals/layout_in_storage.rst index c9c5f6ee3..319aa4d8b 100644 --- a/docs/internals/layout_in_storage.rst +++ b/docs/internals/layout_in_storage.rst @@ -52,58 +52,74 @@ the value specified by ``C``. pragma solidity ^0.8.29; struct S { - int32 a; - bool b; + int32 x; + bool y; } contract A { - uint x; - uint transient y; - uint constant w = 10; - uint immutable z = 12; + uint a; + uint128 transient b; + uint constant c = 10; + uint immutable d = 12; } contract B { - uint16 i; - uint16 j; + uint8[] e; + mapping(uint => S) f; + uint16 g; + uint16 h; + bytes16 transient i; S s; int8 k; } contract C is A, B layout at 42 { - uint8[10] register; - bool flag; + bytes21 l; + uint8[10] m; + bytes5[8] n; + bytes5 o; } In the example, the storage layout starts with the inherited -state variable ``x`` stored directly inside the base slot (slot ``42``). +state variable ``a`` stored directly inside the base slot (slot ``42``). Transient, constant and immutable variables are stored in separate -locations and, thus, ``y``, ``w`` and ``z`` have no effect on the storage layout. -The next two variables, ``i`` and ``j``, need 2 bytes each and can be packed together into -slot ``43``, at offsets ``0`` and ``2`` respectively. +locations, and thus, ``b``, ``i``, ``c`` and ``d`` have no effect on the storage layout. +Then we get to the dynamic array ``e`` and mapping ``f``. +They both reserve a whole slot whose address will be used to :ref:`calculate` +the location where their data is actually stored. +The slot cannot be shared with any other variable, because the resulting addresses must be unique. +The next two variables, ``g`` and ``h``, need 2 bytes each and can be packed together into +slot ``45``, at offsets ``0`` and ``2`` respectively. Since ``s`` is a struct, its two members are packed contiguously, each taking up 5 bytes. -Even though they both would still fit in slot ``43``, structs and arrays always start a new slot. -Therefore, ``s`` is placed in slot ``44`` and the next variable, ``k``, in slot ``45``. -Then, variable ``register`` which is an array of 10 items, gets into slot ``46`` and takes up 80 bytes. -Finally, variable ``flag`` ends up in slot ``47``, because, -as explained before, variables after structs and arrays always start a new slot. +Even though they both would still fit in slot ``45``, structs and arrays always start a new slot. +Therefore, ``s`` is placed in slot ``46`` and the next variable, ``k``, in slot ``47``. +Base contracts, on the other hand, can share slots with derived ones, so ``l`` does not require an new one. +Then variable ``m``, which is an array of 10 items, gets into slot ``48`` and takes up 10 bytes. +``n`` is an array as well, but due to the size of its items, cannot fill its first slot perfectly +and spills over to the next one. +Finally, variable ``o`` ends up in slot ``51``, even though it is of the same type as items of ``n``. +As explained before, variables after structs and arrays always start a new slot. -Overall the storage and transient storage layouts of contract ``C`` can be illustrated as follows: +Putting it all together, the storage and transient storage layouts of contract ``C`` can be illustrated as follows: - Storage: :: - 42 [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx] - 43 [ jjii] - 44 [ baaaa] - 45 [ k] - 46 [ rrrrrrrrrr] - 47 [ f] + 42 [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] + 43 [eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee] + 44 [ffffffffffffffffffffffffffffffff] + 45 [ hhgg] + 46 [ yxxxx] + 47 [ lllllllllllllllllllllk] + 48 [ mmmmmmmmmm] + 49 [ nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn] + 50 [ nnnnnnnnnn] + 51 [ ooooo] - Transient storage: :: - 00 [yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy] + 00 [iiiiiiiiiiiiiiiibbbbbbbbbbbbbbbb] Note that the storage specifier affects ``A`` and ``B`` only as a part of ``C``'s inheritance hierarchy. When deployed independently, their storage starts at ``0``: @@ -111,14 +127,16 @@ When deployed independently, their storage starts at ``0``: - Storage layout of ``A``: :: - 00 [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx] + 00 [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] - Storage layout of ``B``: :: - 00 [ jjii] - 01 [ baaaa] - 02 [ k] + 00 [eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee] + 01 [ffffffffffffffffffffffffffffffff] + 02 [ hhgg] + 03 [ yxxxx] + 04 [ k] .. warning:: When using elements that are smaller than 32 bytes, your contract's gas usage may be higher. From de966a76f726fd341ee930eb16b92962a1908b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 11 Mar 2025 06:14:31 +0100 Subject: [PATCH 0775/1340] fixup! Storage layout specifier docs --- docs/contracts/custom-storage-layout.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contracts/custom-storage-layout.rst b/docs/contracts/custom-storage-layout.rst index 341975eac..224e77425 100644 --- a/docs/contracts/custom-storage-layout.rst +++ b/docs/contracts/custom-storage-layout.rst @@ -27,9 +27,9 @@ The ``base-slot-expression`` must be an :ref:`integer literal that can be evaluated at compilation time and yields a value in the range of ``uint256``. A custom layout cannot make contract's storage "wrap around". -If the selected base slot would push the statically-sized variables past the end of storage, +If the selected base slot would push the static variables past the end of storage, the compiler will issue an error. -Note that the data areas of dynamically-sized variables are not affected by this check because +Note that the data areas of dynamic arrays and mappings are not affected by this check because their layout is not linear. Regardless of the base slot used, their locations are calculated in a way that always puts them within the range of ``uint256`` and their sizes are not known at compilation time. From 3199cca75f5ad1b29a96eab9177c6c67bb7ac72c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 11 Mar 2025 13:25:31 +0100 Subject: [PATCH 0776/1340] Bump vendored dependencies post-release --- ReleaseChecklist.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 758ef79dd..f55384230 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -121,4 +121,5 @@ At least a day before the release: - [ ] Share the announcement on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im) - [ ] Share the announcement on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org) - [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.ethereum.org/@solidity/release-mistakes). + - [ ] Bump vendored dependencies. - [ ] Lean back, wait for bug reports and repeat from step 1 :). From 44533c991db9058278686372b38cb9c82f5e5757 Mon Sep 17 00:00:00 2001 From: flylai Date: Thu, 27 Feb 2025 20:58:46 +0800 Subject: [PATCH 0777/1340] Correct Chinese translation URL --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index a60dc1b84..11765d3be 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -89,7 +89,7 @@ The English version stands as a reference. You can switch between languages by clicking on the flyout menu in the bottom-left corner and selecting the preferred language. -* `Chinese `_ +* `Chinese `_ * `French `_ * `Indonesian `_ * `Japanese `_ From d85833e5f8ebb16729cfdfc46787fe59970b2786 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 11 Mar 2025 14:39:11 +0100 Subject: [PATCH 0778/1340] docs: fix broken link for apeworkx tool --- docs/resources.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/resources.rst b/docs/resources.rst index e8e8fed58..7c8d61afa 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -19,7 +19,7 @@ General Resources Integrated (Ethereum) Development Environments ============================================== -* `Ape `_ +* `Ape `_ A Python-based web3 development tool for compiling, testing, and interacting with smart contracts. * `Brownie `_ From 90719b22b40794ccccd1d5ba58ff4c1d48d0f18c Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 11 Mar 2025 15:44:22 +0100 Subject: [PATCH 0779/1340] Fix changelog for upcoming release --- Changelog.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index b14ebb2c1..e213ab437 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,8 +10,8 @@ Compiler Features: * EVM: Support for the EVM version "Osaka". * EVM Assembly Import: Allow enabling opcode-based optimizer. * General: The experimental EOF backend implements a subset of EOF sufficient to compile arbitrary high-level Solidity syntax via IR with optimization enabled. - * SMTChecker: Support `block.blobbasefee` and `blobhash`. - * SMTChecker: The option `--model-checker-print-query` no longer requires `--model-checker-solvers smtlib2`. + * SMTChecker: Support ``block.blobbasefee`` and ``blobhash``. + * SMTChecker: The option ``--model-checker-print-query`` no longer requires ``--model-checker-solvers smtlib2``. * SMTChecker: Z3 is now a runtime dependency, not a build dependency (except for emscripten build). * Yul Parser: Make name clash with a builtin a non-fatal error. @@ -30,7 +30,7 @@ Bugfixes: * SMTChecker: Fix SMT logic error when translating invariants involving array store and select operations. * SMTChecker: Fix wrong encoding of string literals as arguments of ``ecrecover`` precompile. * Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested. - * TypeChecker: Fix supurious compilation errors due to incorrect computation of contract storage size which erroneously included transient storage variables. + * TypeChecker: Fix spurious compilation errors due to incorrect computation of contract storage size which erroneously included transient storage variables. * Yul: Fix internal compiler error when a code generation error should be reported instead. * Yul Optimizer: Fix failing debug assertion due to dereferencing of an empty ``optional`` value. From 0c45a5e9129c587a0b07be9937286d50d44fa6c8 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 11 Mar 2025 12:41:02 -0300 Subject: [PATCH 0780/1340] Update changelog and bugs by version --- Changelog.md | 2 +- docs/bugs_by_version.json | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index e213ab437..b1ddcacf6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.8.29 (unreleased) +### 0.8.29 (2025-03-12) Language Features: * Allow relocating contract storage to an arbitrary location. diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 2c3b6487a..60fcdd049 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1906,6 +1906,10 @@ "bugs": [], "released": "2024-10-09" }, + "0.8.29": { + "bugs": [], + "released": "2025-03-12" + }, "0.8.3": { "bugs": [ "FullInlinerNonExpressionSplitArgumentEvaluationOrder", From a61cbb4be63db227cd82ae89181cef33e547b53c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 11 Mar 2025 18:56:13 +0100 Subject: [PATCH 0781/1340] Document the eofVersion field in StandardJSON and metadata --- docs/metadata.rst | 2 ++ docs/using-the-compiler.rst | 3 +++ 2 files changed, 5 insertions(+) diff --git a/docs/metadata.rst b/docs/metadata.rst index a44d98753..063936a9d 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -134,6 +134,8 @@ explanatory purposes. }, // Required for Solidity. "evmVersion": "london", + // Optional: Only present if not null. + "eofVersion": 1, // Required for Solidity: Addresses for libraries used. "libraries": { "MyLib": "0x123123..." diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 97db1d7ce..f1b33c648 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -358,6 +358,9 @@ Input Description // tangerineWhistle, spuriousDragon, byzantium, constantinople, // petersburg, istanbul, berlin, london, paris, shanghai, cancun (default), prague (experimental) or osaka (experimental). "evmVersion": "cancun", + // EVM Object Format version to compile for (optional, experimental). + // Currently the only valid value is 1. If not specified, legacy non-EOF bytecode will be generated. + "eofVersion": null, // Optional: Change compilation pipeline to go through the Yul intermediate representation. // This is false by default. "viaIR": true, From 643caa3625570f69722bb92cc3f04dcad5a9d462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 11 Mar 2025 18:56:44 +0100 Subject: [PATCH 0782/1340] Mark the evmVersion field in StandardJSON as optional --- docs/using-the-compiler.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index f1b33c648..4984d999d 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -353,7 +353,7 @@ Input Description } } }, - // Version of the EVM to compile for. + // Version of the EVM to compile for (optional). // Affects type checking and code generation. Can be homestead, // tangerineWhistle, spuriousDragon, byzantium, constantinople, // petersburg, istanbul, berlin, london, paris, shanghai, cancun (default), prague (experimental) or osaka (experimental). From 6738ce6f3379bbf1c2d5b2fff768d21913aa4d97 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 12 Mar 2025 11:49:55 +0100 Subject: [PATCH 0783/1340] bump fmtlib to 11.1.4 --- deps/fmtlib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/fmtlib b/deps/fmtlib index 0c9fce2ff..123913715 160000 --- a/deps/fmtlib +++ b/deps/fmtlib @@ -1 +1 @@ -Subproject commit 0c9fce2ffefecfdce794e1859584e25877b7b592 +Subproject commit 123913715afeb8a437e6388b4473fcc4753e1c9a From 363f1ae1dedbf47528dd1d76065032e1ed367b2b Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 11 Mar 2025 13:09:38 -0300 Subject: [PATCH 0784/1340] Set next version 0.8.30 --- CMakeLists.txt | 2 +- Changelog.md | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d95b7213e..5b39878f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.29") +set(PROJECT_VERSION "0.8.30") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index b1ddcacf6..47334fd3d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,14 @@ +### 0.8.30 (unreleased) + +Language Features: + + +Compiler Features: + + +Bugfixes: + + ### 0.8.29 (2025-03-12) Language Features: From c84cac865295b87caa273b3ed8aaa31b0b121d99 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 12 Mar 2025 11:44:14 +0100 Subject: [PATCH 0785/1340] release checklist: mention buildx as requirement for docker_deploy_manual --- ReleaseChecklist.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index f55384230..301cf963e 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -6,6 +6,7 @@ - [ ] DockerHub account with push rights to the [``solc`` image](https://hub.docker.com/r/ethereum/solc). - [ ] Launchpad (Ubuntu One) account with a membership in the ["Ethereum" team](https://launchpad.net/~ethereum) and a gnupg key for your email in the ``ethereum.org`` domain (has to be version 1, gpg2 won't work). + - [ ] Ubuntu/Debian dependencies of the Docker script: ``docker-buildx``. - [ ] Ubuntu/Debian dependencies of the PPA scripts: ``devscripts``, ``debhelper``, ``dput``, ``git``, ``wget``, ``ca-certificates``. - [ ] [npm Registry](https://www.npmjs.com) account added as a collaborator for the [``solc`` package](https://www.npmjs.com/package/solc). - [ ] Access to the [solidity_lang Twitter account](https://twitter.com/solidity_lang). @@ -79,6 +80,7 @@ At least a day before the release: - [ ] Update the version and the hash (``sha256sum solidity_$VERSION.tar.gz``) in the [``solidity`` formula in Homebrew core repository](https://github.com/Homebrew/homebrew-core/blob/master/Formula/s/solidity.rb). ### Docker + - [ ] Make sure ``docker-buildx`` is installed. - [ ] Run ``./scripts/docker_deploy_manual.sh v$VERSION``. ### PPA From 40a4d5d420006168e6c73a1a27a9159cb0b515f0 Mon Sep 17 00:00:00 2001 From: Ocenka Date: Fri, 14 Mar 2025 12:28:24 +0000 Subject: [PATCH 0786/1340] Minor spelling fix in external test runners base.py --- scripts/externalTests/runners/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/externalTests/runners/base.py b/scripts/externalTests/runners/base.py index cd94fab6b..477820615 100644 --- a/scripts/externalTests/runners/base.py +++ b/scripts/externalTests/runners/base.py @@ -74,7 +74,7 @@ def __init__(self, argv, config: TestConfig): def setup_solc(self) -> str: if self.solc_binary_type == "solcjs": - # TODO: add support to solc-js + # TODO: add support for solc-js raise NotImplementedError() print("Setting up solc...") solc_version_output = subprocess.check_output( From d547bf2b67668bc1fd85cf4c6713c50cf5db5b80 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 14 Mar 2025 08:50:53 +0100 Subject: [PATCH 0787/1340] Release checklist: Updates style - double backticks -> single backticks - remove single space before bullet points --- ReleaseChecklist.md | 200 ++++++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 100 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 301cf963e..f5e4ec7ca 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -1,127 +1,127 @@ ## Checklist for making a release: ### Requirements - - [ ] GitHub account with access to [solidity](https://github.com/ethereum/solidity), [solc-js](https://github.com/ethereum/solc-js), - [solc-bin](https://github.com/ethereum/solc-bin), [solidity-website](https://github.com/ethereum/solidity-website). - - [ ] DockerHub account with push rights to the [``solc`` image](https://hub.docker.com/r/ethereum/solc). - - [ ] Launchpad (Ubuntu One) account with a membership in the ["Ethereum" team](https://launchpad.net/~ethereum) and - a gnupg key for your email in the ``ethereum.org`` domain (has to be version 1, gpg2 won't work). - - [ ] Ubuntu/Debian dependencies of the Docker script: ``docker-buildx``. - - [ ] Ubuntu/Debian dependencies of the PPA scripts: ``devscripts``, ``debhelper``, ``dput``, ``git``, ``wget``, ``ca-certificates``. - - [ ] [npm Registry](https://www.npmjs.com) account added as a collaborator for the [``solc`` package](https://www.npmjs.com/package/solc). - - [ ] Access to the [solidity_lang Twitter account](https://twitter.com/solidity_lang). - - [ ] [Reddit](https://www.reddit.com) account that is at least 10 days old with a minimum of 20 comment karma (``/r/ethereum`` requirements). +- [ ] GitHub account with access to [solidity](https://github.com/ethereum/solidity), [solc-js](https://github.com/ethereum/solc-js), + [solc-bin](https://github.com/ethereum/solc-bin), [solidity-website](https://github.com/ethereum/solidity-website). +- [ ] DockerHub account with push rights to the [`solc` image](https://hub.docker.com/r/ethereum/solc). +- [ ] Launchpad (Ubuntu One) account with a membership in the ["Ethereum" team](https://launchpad.net/~ethereum) and + a gnupg key for your email in the `ethereum.org` domain (has to be version 1, gpg2 won't work). +- [ ] Ubuntu/Debian dependencies of the Docker script: `docker-buildx`. +- [ ] Ubuntu/Debian dependencies of the PPA scripts: `devscripts`, `debhelper`, `dput`, `git`, `wget`, `ca-certificates`. +- [ ] [npm Registry](https://www.npmjs.com) account added as a collaborator for the [`solc` package](https://www.npmjs.com/package/solc). +- [ ] Access to the [solidity_lang Twitter account](https://twitter.com/solidity_lang). +- [ ] [Reddit](https://www.reddit.com) account that is at least 10 days old with a minimum of 20 comment karma (`/r/ethereum` requirements). ### Pre-flight checks At least a day before the release: - - [ ] Run ``make linkcheck`` from within ``docs/`` and fix any broken links it finds. - Ignore false positives caused by ``href`` anchors and dummy links not meant to work. - **Note**: In order to run the link check, make sure you've built the docs first via ``docs.sh``. - - [ ] Double-check that [the most recent docs builds at readthedocs](https://readthedocs.org/projects/solidity/builds/) succeeded. - - [ ] Make sure that all merged PRs that should have changelog entries do have them. - - [ ] Rerun CI on the top commits of main branches in all repositories that do not have daily activity by creating a test branch or PR: - - [ ] ``solc-js`` - - [ ] ``solc-bin`` (make sure the bytecode comparison check did run) - - [ ] (Optional) Create a prerelease in our Ubuntu PPA by following the steps in the PPA section below on ``develop`` rather than on a tag. - This is recommended especially when dealing with PPA for the first time, when we add a new Ubuntu version or when the PPA scripts were modified in this release cycle. - - [ ] Verify that the release tarball of ``solc-js`` works. - Bump version locally, add ``soljson.js`` from CI, build it, compare the file structure with the previous version, install it locally and try to use it. - - [ ] Review [Learning from Past Releases](https://notes.ethereum.org/@solidity/release-mistakes) to make sure you don't repeat the same mistakes. +- [ ] Run `make linkcheck` from within `docs/` and fix any broken links it finds. + Ignore false positives caused by `href` anchors and dummy links not meant to work. + **Note**: In order to run the link check, make sure you've built the docs first via `docs.sh`. +- [ ] Double-check that [the most recent docs builds at readthedocs](https://readthedocs.org/projects/solidity/builds/) succeeded. +- [ ] Make sure that all merged PRs that should have changelog entries do have them. +- [ ] Rerun CI on the top commits of main branches in all repositories that do not have daily activity by creating a test branch or PR: + - [ ] `solc-js` + - [ ] `solc-bin` (make sure the bytecode comparison check did run) +- [ ] (Optional) Create a prerelease in our Ubuntu PPA by following the steps in the PPA section below on `develop` rather than on a tag. + This is recommended especially when dealing with PPA for the first time, when we add a new Ubuntu version or when the PPA scripts were modified in this release cycle. +- [ ] Verify that the release tarball of `solc-js` works. + Bump version locally, add `soljson.js` from CI, build it, compare the file structure with the previous version, install it locally and try to use it. +- [ ] Review [Learning from Past Releases](https://notes.ethereum.org/@solidity/release-mistakes) to make sure you don't repeat the same mistakes. ### Drafts At least a day before the release: - - [ ] Create a draft PR to sort the changelog. - - [ ] Create draft PRs to bump version in ``solidity`` and ``solc-js``. - **Note**: The ``solc-js`` PR won't pass CI checks yet because it depends on the soljson binary from ``solc-bin``. - - [ ] Create a draft of the release on github. - - [ ] Create a draft PR to update soliditylang.org. - - [ ] Create drafts of blog posts. - - [ ] Prepare drafts of Twitter, Reddit and Solidity Forum announcements. +- [ ] Create a draft PR to sort the changelog. +- [ ] Create draft PRs to bump version in `solidity` and `solc-js`. + **Note**: The `solc-js` PR won't pass CI checks yet because it depends on the soljson binary from `solc-bin`. +- [ ] Create a draft of the release on github. +- [ ] Create a draft PR to update soliditylang.org. +- [ ] Create drafts of blog posts. +- [ ] Prepare drafts of Twitter, Reddit and Solidity Forum announcements. ### Blog Post - - [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the ``Releases`` category and explain some of the new features or concepts. - - [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the ``Security Alerts`` category in case of important bug(s). - - [ ] Get the posts reviewed and approved **before the release starts**. +- [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the `Releases` category and explain some of the new features or concepts. +- [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the `Security Alerts` category in case of important bug(s). +- [ ] Get the posts reviewed and approved **before the release starts**. ### Changelog - - [ ] Sort the changelog entries alphabetically and correct any errors you notice. Commit it. - - [ ] Update the changelog to include a release date. - - [ ] Run ``scripts/update_bugs_by_version.py`` to regenerate ``bugs_by_version.json`` from the changelog and ``bugs.json``. - Make sure that the resulting ``bugs_by_version.json`` has a new, empty entry for the new version. - - [ ] Commit changes, create a pull request and wait for the tests. Then merge it. - - [ ] Copy the changelog into the release blog post. +- [ ] Sort the changelog entries alphabetically and correct any errors you notice. Commit it. +- [ ] Update the changelog to include a release date. +- [ ] Run `scripts/update_bugs_by_version.py` to regenerate `bugs_by_version.json` from the changelog and `bugs.json`. + Make sure that the resulting `bugs_by_version.json` has a new, empty entry for the new version. +- [ ] Commit changes, create a pull request and wait for the tests. Then merge it. +- [ ] Copy the changelog into the release blog post. ### Create the Release - - [ ] Create a [release on GitHub](https://github.com/ethereum/solidity/releases/new). - Set the target to the ``develop`` branch and the tag to the new version, e.g. ``v0.8.5``. - Include the following warning: ``**The release is still in progress. You may see broken links and binaries may not yet be available from all sources.**``. - Do not publish it yet - click the ``Save draft`` button instead. - - [ ] Thank voluntary contributors in the GitHub release notes. - Use ``scripts/list_contributors.sh v`` to get initial list of names. - Remove different variants of the same name manually before using the output. - - [ ] Check that all tests on the latest commit in ``develop`` are green. - - [ ] Click the ``Publish release`` button on the release page, creating the tag. - **Important: Must not be done before all the PRs, including changelog cleanup and date, are merged.** - - [ ] Wait for the CI runs on the tag itself. +- [ ] Create a [release on GitHub](https://github.com/ethereum/solidity/releases/new). + Set the target to the `develop` branch and the tag to the new version, e.g. `v0.8.5`. + Include the following warning: `**The release is still in progress. You may see broken links and binaries may not yet be available from all sources.**`. + Do not publish it yet - click the `Save draft` button instead. +- [ ] Thank voluntary contributors in the GitHub release notes. + Use `scripts/list_contributors.sh v` to get initial list of names. + Remove different variants of the same name manually before using the output. +- [ ] Check that all tests on the latest commit in `develop` are green. +- [ ] Click the `Publish release` button on the release page, creating the tag. + **Important: Must not be done before all the PRs, including changelog cleanup and date, are merged.** +- [ ] Wait for the CI runs on the tag itself. ### Upload Release Artifacts and Publish Binaries - - [ ] Switch to the tag that archives have to be created for. - - [ ] Create the ``prerelease.txt`` file: (``echo -n > prerelease.txt``). - - [ ] Run ``scripts/create_source_tarball.sh`` while being on the tag to create the source tarball. This will create the tarball in a directory called ``upload``. - - [ ] Take the tarball from the upload directory (its name should be ``solidity_x.x.x.tar.gz``, otherwise ``prerelease.txt`` was missing in the step before) and upload the source tarball to the release page. - - [ ] Take the ``github-binaries.tar`` tarball from ``c_release_binaries`` run of the tagged commit in circle-ci and add all binaries from it to the release page. - Make sure it contains four binaries: ``solc-windows.exe``, ``solc-macos``, ``solc-static-linux`` and ``soljson.js``. - - [ ] Take the ``solc-bin-binaries.tar`` tarball from ``c_release_binaries`` run of the tagged commit in circle-ci and add all binaries from it to solc-bin. - - [ ] Run ``npm install`` if you've got a clean checkout of the solc-bin repo. - - [ ] Run ``npm run update -- --reuse-hashes`` in ``solc-bin`` and verify that the script has updated ``list.js``, ``list.txt`` and ``list.json`` files correctly and that symlinks to the new release have been added in ``solc-bin/wasm/`` and ``solc-bin/emscripten-wasm32/``. - - [ ] Create a pull request in solc-bin and merge. +- [ ] Switch to the tag that archives have to be created for. +- [ ] Create the `prerelease.txt` file: (`echo -n > prerelease.txt`). +- [ ] Run `scripts/create_source_tarball.sh` while being on the tag to create the source tarball. This will create the tarball in a directory called `upload`. +- [ ] Take the tarball from the upload directory (its name should be `solidity_x.x.x.tar.gz`, otherwise `prerelease.txt` was missing in the step before) and upload the source tarball to the release page. +- [ ] Take the `github-binaries.tar` tarball from `c_release_binaries` run of the tagged commit in circle-ci and add all binaries from it to the release page. + Make sure it contains four binaries: `solc-windows.exe`, `solc-macos`, `solc-static-linux` and `soljson.js`. +- [ ] Take the `solc-bin-binaries.tar` tarball from `c_release_binaries` run of the tagged commit in circle-ci and add all binaries from it to solc-bin. +- [ ] Run `npm install` if you've got a clean checkout of the solc-bin repo. +- [ ] Run `npm run update -- --reuse-hashes` in `solc-bin` and verify that the script has updated `list.js`, `list.txt` and `list.json` files correctly and that symlinks to the new release have been added in `solc-bin/wasm/` and `solc-bin/emscripten-wasm32/`. +- [ ] Create a pull request in solc-bin and merge. ### Homebrew and MacOS - - [ ] Update the version and the hash (``sha256sum solidity_$VERSION.tar.gz``) in the [``solidity`` formula in Homebrew core repository](https://github.com/Homebrew/homebrew-core/blob/master/Formula/s/solidity.rb). +- [ ] Update the version and the hash (`sha256sum solidity_$VERSION.tar.gz`) in the [`solidity` formula in Homebrew core repository](https://github.com/Homebrew/homebrew-core/blob/master/Formula/s/solidity.rb). ### Docker - - [ ] Make sure ``docker-buildx`` is installed. - - [ ] Run ``./scripts/docker_deploy_manual.sh v$VERSION``. +- [ ] Make sure `docker-buildx` is installed. +- [ ] Run `./scripts/docker_deploy_manual.sh v$VERSION`. ### PPA - - [ ] Create ``.release_ppa_auth`` at the root of your local Solidity checkout and set ``LAUNCHPAD_EMAIL`` and ``LAUNCHPAD_KEYID`` to your key's email and key id. - - [ ] Double-check that the ``DISTRIBUTIONS`` list in ``scripts/release_ppa.sh`` and ``scripts/deps-ppa/static_z3.sh`` contains the most recent versions of Ubuntu. - - [ ] Make sure the [``~ethereum/cpp-build-deps`` PPA repository](https://launchpad.net/~ethereum/+archive/ubuntu/cpp-build-deps) contains ``libz3-static-dev`` builds for all current versions of Ubuntu. - Note that it may be included in the ``z3-static`` multipackage (follow the ``View package details`` link to check). - If not present, run ``scripts/deps-ppa/static_z3.sh`` and wait for the builds to succeed before continuing. - - [ ] Run ``scripts/release_ppa.sh v$VERSION`` to create the PPA release. - This will create a single package containing static binary for older Ubuntu versions in the [``~ethereum/ethereum-static`` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum-static) - and separate packages with dynamically-linked binaries for recent versions (those listed in ``DISTRIBUTIONS``) in the [``~ethereum/ethereum`` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum). - - [ ] Wait for the build to be finished and published for *all architectures* (currently we only build for ``amd64``, but we may add ``arm`` in the future). - **SERIOUSLY: DO NOT PROCEED EARLIER!!!** - - [ ] *After* the package with the static build is *published*, use it to create packages for older Ubuntu versions. - Copy the static package to the [``~ethereum/ethereum`` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum) - for the destination series ``Trusty``, ``Xenial``, ``Bionic``, and ``Focal`` - while selecting ``Copy existing binaries``. +- [ ] Create `.release_ppa_auth` at the root of your local Solidity checkout and set `LAUNCHPAD_EMAIL` and `LAUNCHPAD_KEYID` to your key's email and key id. +- [ ] Double-check that the `DISTRIBUTIONS` list in `scripts/release_ppa.sh` and `scripts/deps-ppa/static_z3.sh` contains the most recent versions of Ubuntu. +- [ ] Make sure the [`~ethereum/cpp-build-deps` PPA repository](https://launchpad.net/~ethereum/+archive/ubuntu/cpp-build-deps) contains `libz3-static-dev` builds for all current versions of Ubuntu. + Note that it may be included in the `z3-static` multipackage (follow the `View package details` link to check). + If not present, run `scripts/deps-ppa/static_z3.sh` and wait for the builds to succeed before continuing. +- [ ] Run `scripts/release_ppa.sh v$VERSION` to create the PPA release. + This will create a single package containing static binary for older Ubuntu versions in the [`~ethereum/ethereum-static` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum-static) + and separate packages with dynamically-linked binaries for recent versions (those listed in `DISTRIBUTIONS`) in the [`~ethereum/ethereum` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum). +- [ ] Wait for the build to be finished and published for *all architectures* (currently we only build for `amd64`, but we may add `arm` in the future). + **SERIOUSLY: DO NOT PROCEED EARLIER!!!** +- [ ] *After* the package with the static build is *published*, use it to create packages for older Ubuntu versions. + Copy the static package to the [`~ethereum/ethereum` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum) + for the destination series `Trusty`, `Xenial`, `Bionic`, and `Focal` + while selecting `Copy existing binaries`. ### Release solc-js - - [ ] Wait until solc-bin was properly deployed. You can test this via remix - a test run through remix is advisable anyway. - - [ ] Increment the version number, create a pull request for that, merge it after tests succeeded. - - [ ] Create a tag using ``git tag --annotate v$VERSION`` and push it with ``git push --tags``. - - [ ] Wait for the CI runs on the tag itself. - - [ ] Take the ``solc-x.y.z.tgz`` artifact from ``build-package`` run on the tagged commit in circle-ci. - Inspect the tarball to ensure that it contains an up-to-date compiler binary (``soljson.js``). - - [ ] Run ``npm publish solc-x.y.z.tgz`` to publish the newly created tarball. +- [ ] Wait until solc-bin was properly deployed. You can test this via remix - a test run through remix is advisable anyway. +- [ ] Increment the version number, create a pull request for that, merge it after tests succeeded. +- [ ] Create a tag using `git tag --annotate v$VERSION` and push it with `git push --tags`. +- [ ] Wait for the CI runs on the tag itself. +- [ ] Take the `solc-x.y.z.tgz` artifact from `build-package` run on the tagged commit in circle-ci. + Inspect the tarball to ensure that it contains an up-to-date compiler binary (`soljson.js`). +- [ ] Run `npm publish solc-x.y.z.tgz` to publish the newly created tarball. ### Post-release - - [ ] Make sure the documentation for the new release has been published successfully. - Go to the [documentation status page at ReadTheDocs](https://readthedocs.org/projects/solidity/) and verify that the new version is listed, works and is marked as default. - - [ ] Remove "still in progress" warning from the [release notes](https://github.com/ethereum/solidity/releases). - - [ ] Merge the [blog posts](https://github.com/ethereum/solidity-website/pulls) related to the release. - - [ ] Create a commit to increase the version number on ``develop`` in ``CMakeLists.txt`` and add a new skeleton changelog entry. - - [ ] Update the release information section [in the source of soliditylang.org](https://github.com/ethereum/solidity-website/blob/main/src/pages/index.tsx). - - [ ] Announce on [Twitter](https://twitter.com/solidity_lang), including links to the release and the blog post. - - [ ] Announce on [Fosstodon](https://fosstodon.org/@solidity/), including links to the release and the blog post. - - [ ] Share the announcement on Reddit in [``/r/ethdev``](https://reddit.com/r/ethdev/), cross-posted to [``/r/ethereum``](https://reddit.com/r/ethereum/). - - [ ] Share the announcement on the [Solidity forum](https://forum.soliditylang.org) in the ``Announcements`` category. - - [ ] Share the announcement on [Project Updates](https://discord.com/channels/420394352083337236/798974456704925696) - - [ ] Share the announcement on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im) - - [ ] Share the announcement on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org) - - [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.ethereum.org/@solidity/release-mistakes). - - [ ] Bump vendored dependencies. - - [ ] Lean back, wait for bug reports and repeat from step 1 :). +- [ ] Make sure the documentation for the new release has been published successfully. + Go to the [documentation status page at ReadTheDocs](https://readthedocs.org/projects/solidity/) and verify that the new version is listed, works and is marked as default. +- [ ] Remove "still in progress" warning from the [release notes](https://github.com/ethereum/solidity/releases). +- [ ] Merge the [blog posts](https://github.com/ethereum/solidity-website/pulls) related to the release. +- [ ] Create a commit to increase the version number on `develop` in `CMakeLists.txt` and add a new skeleton changelog entry. +- [ ] Update the release information section [in the source of soliditylang.org](https://github.com/ethereum/solidity-website/blob/main/src/pages/index.tsx). +- [ ] Announce on [Twitter](https://twitter.com/solidity_lang), including links to the release and the blog post. +- [ ] Announce on [Fosstodon](https://fosstodon.org/@solidity/), including links to the release and the blog post. +- [ ] Share the announcement on Reddit in [`/r/ethdev`](https://reddit.com/r/ethdev/), cross-posted to [`/r/ethereum`](https://reddit.com/r/ethereum/). +- [ ] Share the announcement on the [Solidity forum](https://forum.soliditylang.org) in the `Announcements` category. +- [ ] Share the announcement on [Project Updates](https://discord.com/channels/420394352083337236/798974456704925696) +- [ ] Share the announcement on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im) +- [ ] Share the announcement on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org) +- [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.ethereum.org/@solidity/release-mistakes). +- [ ] Bump vendored dependencies. +- [ ] Lean back, wait for bug reports and repeat from step 1 :). From 70d344a0e93b299b531cbde369713ae067567688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 14 Mar 2025 23:55:49 +0100 Subject: [PATCH 0788/1340] Remove double backticks from CODING_STYLE.md --- CODING_STYLE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CODING_STYLE.md b/CODING_STYLE.md index 2305ae1ec..b70126d91 100644 --- a/CODING_STYLE.md +++ b/CODING_STYLE.md @@ -110,9 +110,9 @@ Use `solAssert` and `solUnimplementedAssert` generously to check assumptions tha 4. Favour declarations close to use; do not habitually declare at top of scope ala C. 5. Pass non-trivial parameters as const reference, unless the data is to be copied into the function, then either pass by const reference or by value and use std::move. 6. If a function returns multiple values, use std::tuple (std::pair acceptable) or better introduce a struct type. Do not use */& arguments. -7. Use parameters of pointer type only if ``nullptr`` is a valid argument, use references otherwise. Often, ``std::optional`` is better suited than a raw pointer. +7. Use parameters of pointer type only if `nullptr` is a valid argument, use references otherwise. Often, `std::optional` is better suited than a raw pointer. 8. Never use a macro where adequate non-preprocessor C++ can be written. -9. Only use ``auto`` if the type is very long and rather irrelevant. +9. Only use `auto` if the type is very long and rather irrelevant. 10. Do not pass bools: prefer enumerations instead. 11. Prefer enum class to straight enum. 12. Always initialize POD variables, even if their value is overwritten later. From 145e281fac9369c920c9628fe4a967f7b71e9193 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 12 Mar 2025 14:13:23 +0100 Subject: [PATCH 0789/1340] Name dependent CSE bug: Compare ASM only --- test/cmdlineTests/~name_dependent_cse_bug/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cmdlineTests/~name_dependent_cse_bug/test.sh b/test/cmdlineTests/~name_dependent_cse_bug/test.sh index 96c3ac23e..710e82b1e 100755 --- a/test/cmdlineTests/~name_dependent_cse_bug/test.sh +++ b/test/cmdlineTests/~name_dependent_cse_bug/test.sh @@ -19,7 +19,7 @@ function assemble_with_variable_name { local variable_name="$2" sed -e "s|__placeholder__|${variable_name}|g" "$input_file" | msg_on_error --no-stderr \ - "$SOLC" --strict-assembly - --optimize --debug-info none | + "$SOLC" --strict-assembly - --optimize --debug-info none --asm | stripCLIDecorations } From 74cd757be52c658a8eef7a81c62d364ee1921652 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 17 Mar 2025 08:52:34 +0100 Subject: [PATCH 0790/1340] SSACFG Builder: Improve function call visitor --- .../evm/SSAControlFlowGraphBuilder.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index bf8cfd92a..69e9e3052 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -548,21 +548,22 @@ void SSAControlFlowGraphBuilder::assign(std::vector SSAControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _call) { bool canContinue = true; - SSACFG::Operation operation = [&](){ - if (BuiltinFunction const* builtin = resolveBuiltinFunction(_call.functionName, m_dialect)) + SSACFG::Operation operation = std::visit(util::GenericVisitor{ + [&](BuiltinName const& _builtinName) { - SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData, *builtin, _call}, {}}; + auto const& builtin = m_dialect.builtin(_builtinName.handle); + SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData, builtin, _call}, {}}; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) - if (!builtin->literalArgument(idx).has_value()) + if (!builtin.literalArgument(idx).has_value()) result.inputs.emplace_back(std::visit(*this, arg)); - for (size_t i = 0; i < builtin->numReturns; ++i) + for (size_t i = 0; i < builtin.numReturns; ++i) result.outputs.emplace_back(m_graph.newVariable(m_currentBlock)); - canContinue = builtin->controlFlowSideEffects.canContinue; + canContinue = builtin.controlFlowSideEffects.canContinue; return result; - } - else + }, + [&](Identifier const& _identifier) { - YulName const functionName{resolveFunctionName(_call.functionName, m_dialect)}; + YulName const& functionName = _identifier.name; Scope::Function const& function = lookupFunction(functionName); auto const* definition = findFunctionDefinition(&function); yulAssert(definition); @@ -574,7 +575,7 @@ std::vector SSAControlFlowGraphBuilder::visitFunctionCall(Funct result.outputs.emplace_back(m_graph.newVariable(m_currentBlock)); return result; } - }(); + }, _call.functionName); auto results = operation.outputs; currentBlock().operations.emplace_back(std::move(operation)); if (!canContinue) From 25463c564dc18cb98750e49d227901087a32940b Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 14 Feb 2025 12:40:18 +0100 Subject: [PATCH 0791/1340] SMTChecker: Fix analysis for selected contracts Previously, when a contract was selected for analysis, the analysis was incorrect. There were two issues. First, the contracts in the same file were considered as entry points even though they were not selected for analysis. Second, the contracts in a different file were mostly ignored, resulting in unsoundness when an external call was made to such a contract in trusted mode. The solution to the above problems is to always create representation of all contracts (in case they are called from the selected contract), but create verification targets only for the selected contracts. --- Changelog.md | 1 + libsolidity/formal/BMC.cpp | 2 +- libsolidity/formal/CHC.cpp | 26 ++++---- libsolidity/formal/ModelCheckerSettings.cpp | 2 +- libsolidity/formal/SMTEncoder.cpp | 13 ++-- libsolidity/formal/SMTEncoder.h | 11 ++-- .../err | 26 -------- .../model_checker_contracts_only_one/err | 2 +- .../output.json | 66 ------------------- .../output.json | 4 +- .../output.json | 4 +- test/libsolidity/SMTCheckerTest.cpp | 11 +++- ...ternal_call_from_constructor_1_trusted.sol | 5 +- ...ternal_call_from_constructor_3_trusted.sol | 5 +- ...lled_from_selection_with_trusted_calls.sol | 11 ++++ ...selected_and_not_called_from_selection.sol | 9 +++ ...selected_and_not_called_from_selection.sol | 13 ++++ ...selected_and_not_called_from_selection.sol | 11 ++++ 18 files changed, 94 insertions(+), 128 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/imports/target_in_imported_contract_analyzed_when_called_from_selection_with_trusted_calls.sol create mode 100644 test/libsolidity/smtCheckerTests/imports/target_in_imported_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol create mode 100644 test/libsolidity/smtCheckerTests/verification_target/target_in_constructor_of_same_source_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol create mode 100644 test/libsolidity/smtCheckerTests/verification_target/target_in_same_source_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol diff --git a/Changelog.md b/Changelog.md index 47334fd3d..3e423c838 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: Bugfixes: +* SMTChecker: Fix incorrect analysis when only a subset of contracts is selected with `--model-checker-contracts`. ### 0.8.29 (2025-03-12) diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index e5521b816..6dcd856ee 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -1068,7 +1068,7 @@ void BMC::addVerificationTarget( Expression const* _expression ) { - if (!m_settings.targets.has(_type) || (m_currentContract && !shouldAnalyze(*m_currentContract))) + if (!m_settings.targets.has(_type) || (m_currentContract && !shouldAnalyzeVerificationTargetsFor(*m_currentContract))) return; BMCVerificationTarget target{ diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index c313ae54e..bab340051 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -89,7 +89,7 @@ void CHC::analyze(SourceUnit const& _source) " If you wish to use Eldarica, please enable Eldarica only." ); - if (!shouldAnalyze(_source)) + if (!shouldAnalyzeVerificationTargetsFor(_source)) return; resetSourceAnalysis(); @@ -131,7 +131,7 @@ std::vector CHC::unhandledQueries() const bool CHC::visit(ContractDefinition const& _contract) { - if (!shouldAnalyze(_contract)) + if (!shouldEncode(_contract)) return false; // Raises UnimplementedFeatureError in the presence of transient storage variables @@ -152,7 +152,7 @@ bool CHC::visit(ContractDefinition const& _contract) void CHC::endVisit(ContractDefinition const& _contract) { - if (!shouldAnalyze(_contract)) + if (!shouldEncode(_contract)) return; for (auto base: _contract.annotation().linearizedBaseContracts) @@ -239,15 +239,14 @@ void CHC::endVisit(ContractDefinition const& _contract) setCurrentBlock(*m_constructorSummaries.at(&_contract)); solAssert(&_contract == m_currentContract, ""); - if (shouldAnalyze(_contract)) - { - auto constructor = _contract.constructor(); - auto txConstraints = state().txTypeConstraints(); - if (!constructor || !constructor->isPayable()) - txConstraints = txConstraints && state().txNonPayableConstraint(); + smtAssert(shouldEncode(_contract)); + auto constructor = _contract.constructor(); + auto txConstraints = state().txTypeConstraints(); + if (!constructor || !constructor->isPayable()) + txConstraints = txConstraints && state().txNonPayableConstraint(); + connectBlocks(m_currentBlock, interface(), txConstraints && errorFlag().currentValue() == 0); + if (shouldAnalyzeVerificationTargetsFor(_contract)) m_queryPlaceholders[&_contract].push_back({txConstraints, errorFlag().currentValue(), m_currentBlock}); - connectBlocks(m_currentBlock, interface(), txConstraints && errorFlag().currentValue() == 0); - } solAssert(m_scopes.back() == &_contract, ""); m_scopes.pop_back(); @@ -338,7 +337,7 @@ void CHC::endVisit(FunctionDefinition const& _function) !_function.isConstructor() && _function.isPublic() && contractFunctions(*m_currentContract).count(&_function) && - shouldAnalyze(*m_currentContract) + shouldEncode(*m_currentContract) ) { defineExternalFunctionInterface(_function, *m_currentContract); @@ -349,8 +348,9 @@ void CHC::endVisit(FunctionDefinition const& _function) auto ifacePre = smt::interfacePre(*m_interfaces.at(m_currentContract), *m_currentContract, m_context); auto sum = externalSummary(_function); - m_queryPlaceholders[&_function].push_back({sum, errorFlag().currentValue(), ifacePre}); connectBlocks(ifacePre, interface(), sum && errorFlag().currentValue() == 0); + if (shouldAnalyzeVerificationTargetsFor(*m_currentContract)) + m_queryPlaceholders[&_function].push_back({sum, errorFlag().currentValue(), ifacePre}); } m_currentFunction = nullptr; diff --git a/libsolidity/formal/ModelCheckerSettings.cpp b/libsolidity/formal/ModelCheckerSettings.cpp index ed4d5ce20..ffeedfe3a 100644 --- a/libsolidity/formal/ModelCheckerSettings.cpp +++ b/libsolidity/formal/ModelCheckerSettings.cpp @@ -123,7 +123,7 @@ std::optional ModelCheckerContracts::fromString(std::stri { auto&& names = sourceContract | ranges::views::split(':') | ranges::to>(); if (names.size() != 2 || names.at(0).empty() || names.at(1).empty()) - return {}; + return std::nullopt; chosen[names.at(0)].insert(names.at(1)); } diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index a0b71f594..740af9382 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -1092,19 +1092,24 @@ void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall) } } -bool SMTEncoder::shouldAnalyze(SourceUnit const& _source) const +bool SMTEncoder::shouldEncode(ContractDefinition const& _contract) const +{ + return _contract.canBeDeployed(); +} + +bool SMTEncoder::shouldAnalyzeVerificationTargetsFor(SourceUnit const& _source) const { return m_settings.contracts.isDefault() || m_settings.contracts.has(*_source.annotation().path); } -bool SMTEncoder::shouldAnalyze(ContractDefinition const& _contract) const +bool SMTEncoder::shouldAnalyzeVerificationTargetsFor(ContractDefinition const& _contract) const { - if (!_contract.canBeDeployed()) + if (!shouldEncode(_contract)) return false; return m_settings.contracts.isDefault() || - m_settings.contracts.has(_contract.sourceUnitName()); + m_settings.contracts.has(_contract.sourceUnitName(), _contract.name()); } void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall) diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index f926a0d0f..5bfb70d81 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -238,11 +238,12 @@ class SMTEncoder: public ASTConstVisitor void visitFunctionIdentifier(Identifier const& _identifier); virtual void visitPublicGetter(FunctionCall const& _funCall); - /// @returns true if @param _contract is set for analysis in the settings - /// and it is not abstract. - bool shouldAnalyze(ContractDefinition const& _contract) const; - /// @returns true if @param _source is set for analysis in the settings. - bool shouldAnalyze(SourceUnit const& _source) const; + /// @returns true if symbolic representation of @param _contract is required for verification + bool shouldEncode(ContractDefinition const& _contract) const; + /// @returns true if the verification targets of @param _contract are actually selected for verification + bool shouldAnalyzeVerificationTargetsFor(ContractDefinition const& _contract) const; + /// @returns true if we should descend into @param _source to look for contracts that should be verified + bool shouldAnalyzeVerificationTargetsFor(SourceUnit const& _source) const; /// @returns the state variable returned by a public getter if /// @a _expr is a call to a public getter, diff --git a/test/cmdlineTests/model_checker_contracts_inexistent_contract/err b/test/cmdlineTests/model_checker_contracts_inexistent_contract/err index 00b97763f..6326537e9 100644 --- a/test/cmdlineTests/model_checker_contracts_inexistent_contract/err +++ b/test/cmdlineTests/model_checker_contracts_inexistent_contract/err @@ -1,27 +1 @@ Warning: Requested contract "C" does not exist in source "model_checker_contracts_inexistent_contract/input.sol". - -Warning: CHC: Assertion violation happens here. -Counterexample: - -x = 0 - -Transaction trace: -B.constructor() -B.f(0) - --> model_checker_contracts_inexistent_contract/input.sol:5:3: - | -5 | assert(x > 0); - | ^^^^^^^^^^^^^ - -Warning: CHC: Assertion violation happens here. -Counterexample: - -y = 0 - -Transaction trace: -A.constructor() -A.g(0) - --> model_checker_contracts_inexistent_contract/input.sol:10:3: - | -10 | assert(y > 0); - | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_contracts_only_one/err b/test/cmdlineTests/model_checker_contracts_only_one/err index 2088e19c7..9c8ade693 100644 --- a/test/cmdlineTests/model_checker_contracts_only_one/err +++ b/test/cmdlineTests/model_checker_contracts_only_one/err @@ -4,7 +4,7 @@ Counterexample: x = 0 Transaction trace: -B.constructor() +A.constructor() B.f(0) --> model_checker_contracts_only_one/input.sol:5:3: | diff --git a/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json b/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json index 22d5f32de..c6bde90df 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_inexistent_contract/output.json @@ -9,72 +9,6 @@ "message": "Requested contract \"C\" does not exist in source \"Source\".", "severity": "warning", "type": "Warning" - }, - { - "component": "general", - "errorCode": "6328", - "formattedMessage": "Warning: CHC: Assertion violation happens here. -Counterexample: - -y = 0 - -Transaction trace: -B.constructor() -B.g(0) - --> Source:5:7: - | -5 | \t\t\t\t\t\tassert(y > 0); - | \t\t\t\t\t\t^^^^^^^^^^^^^ - -", - "message": "CHC: Assertion violation happens here. -Counterexample: - -y = 0 - -Transaction trace: -B.constructor() -B.g(0)", - "severity": "warning", - "sourceLocation": { - "end": 137, - "file": "Source", - "start": 124 - }, - "type": "Warning" - }, - { - "component": "general", - "errorCode": "6328", - "formattedMessage": "Warning: CHC: Assertion violation happens here. -Counterexample: - -x = 0 - -Transaction trace: -A.constructor() -A.f(0) - --> Source:10:7: - | -10 | \t\t\t\t\t\tassert(x > 0); - | \t\t\t\t\t\t^^^^^^^^^^^^^ - -", - "message": "CHC: Assertion violation happens here. -Counterexample: - -x = 0 - -Transaction trace: -A.constructor() -A.f(0)", - "severity": "warning", - "sourceLocation": { - "end": 231, - "file": "Source", - "start": 218 - }, - "type": "Warning" } ], "sources": { diff --git a/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json b/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json index fe287f833..f568de160 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_multi_source/output.json @@ -9,7 +9,7 @@ Counterexample: y = 0 Transaction trace: -B.constructor() +A.constructor() B.g(0) --> Source:5:7: | @@ -23,7 +23,7 @@ Counterexample: y = 0 Transaction trace: -B.constructor() +A.constructor() B.g(0)", "severity": "warning", "sourceLocation": { diff --git a/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json b/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json index e9fc1b4cf..a7ca17b4f 100644 --- a/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json +++ b/test/cmdlineTests/standard_model_checker_contracts_only_one/output.json @@ -9,7 +9,7 @@ Counterexample: y = 0 Transaction trace: -B.constructor() +A.constructor() B.g(0) --> Source:5:7: | @@ -23,7 +23,7 @@ Counterexample: y = 0 Transaction trace: -B.constructor() +A.constructor() B.g(0)", "severity": "warning", "sourceLocation": { diff --git a/test/libsolidity/SMTCheckerTest.cpp b/test/libsolidity/SMTCheckerTest.cpp index d8843e0d3..ce099091f 100644 --- a/test/libsolidity/SMTCheckerTest.cpp +++ b/test/libsolidity/SMTCheckerTest.cpp @@ -32,8 +32,17 @@ SMTCheckerTest::SMTCheckerTest(std::string const& _filename): universalCallback(nullptr, smtCommand) { auto contract = m_reader.stringSetting("SMTContract", ""); - if (!contract.empty()) + auto maybeContracts = ModelCheckerContracts::fromString(contract); + auto isValidContractName = [](std::string const& _name) + { + return !_name.empty() && _name.find_first_of(" \t\n\r:,") == std::string::npos; + }; + if (maybeContracts) + m_modelCheckerSettings.contracts = *maybeContracts; + else if (isValidContractName(contract)) m_modelCheckerSettings.contracts.contracts[""] = {contract}; + else + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid contract specified in SMTContract setting.")); auto extCallsMode = ModelCheckerExtCalls::fromString(m_reader.stringSetting("SMTExtCalls", "untrusted")); if (extCallsMode) diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_1_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_1_trusted.sol index 6f2b717b5..051215bb1 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_1_trusted.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_1_trusted.sol @@ -1,6 +1,6 @@ contract State { function f(uint _x) public pure returns (uint) { - assert(_x < 100); // should fail + assert(_x < 100); // should hold when analyzing only contract C (can fail only when analyzing State as standalone contract) return _x; } } @@ -18,5 +18,4 @@ contract C { // SMTExtCalls: trusted // SMTIgnoreInv: yes // ---- -// Warning 6328: (69-85): CHC: Assertion violation happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_3_trusted.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_3_trusted.sol index 590664055..0f22100d6 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_3_trusted.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_from_constructor_3_trusted.sol @@ -1,6 +1,6 @@ contract State { function f(uint _x) public pure returns (uint) { - assert(_x < 100); // should fail + assert(_x < 100); // should hold when analyzing only contract C (can fail only when analyzing State as standalone contract) return _x; } } @@ -21,5 +21,4 @@ contract C { // SMTEngine: all // SMTExtCalls: trusted // ---- -// Warning 6328: (69-85): CHC: Assertion violation happens here. -// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. +// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/imports/target_in_imported_contract_analyzed_when_called_from_selection_with_trusted_calls.sol b/test/libsolidity/smtCheckerTests/imports/target_in_imported_contract_analyzed_when_called_from_selection_with_trusted_calls.sol new file mode 100644 index 000000000..9389f7d93 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/imports/target_in_imported_contract_analyzed_when_called_from_selection_with_trusted_calls.sol @@ -0,0 +1,11 @@ +==== Source: A.sol ==== +contract A { function a() pure public { assert(false); } } +==== Source: B.sol ==== +import "A.sol"; +contract B { function b(A a) pure public { a.a(); } } +// ==== +// SMTContract: B.sol:B +// SMTEngine: chc +// SMTExtCalls: trusted +// ---- +// Warning 6328: (A.sol:40-53): CHC: Assertion violation happens here.\nCounterexample:\n\na = 0\n\nTransaction trace:\nB.constructor()\nB.b(0)\n A.a() -- trusted external call diff --git a/test/libsolidity/smtCheckerTests/imports/target_in_imported_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol b/test/libsolidity/smtCheckerTests/imports/target_in_imported_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol new file mode 100644 index 000000000..a7c472bbc --- /dev/null +++ b/test/libsolidity/smtCheckerTests/imports/target_in_imported_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol @@ -0,0 +1,9 @@ +==== Source: A.sol ==== +contract A { function a() pure public { assert(false); } } +==== Source: B.sol ==== +import "A.sol"; +contract B { function b() pure public { } } +// ==== +// SMTContract: B.sol:B +// SMTEngine: chc +// ---- diff --git a/test/libsolidity/smtCheckerTests/verification_target/target_in_constructor_of_same_source_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol b/test/libsolidity/smtCheckerTests/verification_target/target_in_constructor_of_same_source_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol new file mode 100644 index 000000000..29d8017cc --- /dev/null +++ b/test/libsolidity/smtCheckerTests/verification_target/target_in_constructor_of_same_source_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol @@ -0,0 +1,13 @@ +contract B { + constructor() { fail(); } + + function fail() pure internal { assert(false); } +} + +contract A { + function safe() pure public { } +} +// ==== +// SMTContract: A +// SMTEngine: chc +// ---- diff --git a/test/libsolidity/smtCheckerTests/verification_target/target_in_same_source_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol b/test/libsolidity/smtCheckerTests/verification_target/target_in_same_source_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol new file mode 100644 index 000000000..f9fcdbb18 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/verification_target/target_in_same_source_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol @@ -0,0 +1,11 @@ +contract B { + function fail() pure public { assert(false); } +} + +contract A { + function safe() pure public { } +} +// ==== +// SMTContract: A +// SMTEngine: chc +// ---- From f2c9eecb46107a6caa1a9604fec7613b027a3d4a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 17 Mar 2025 08:59:15 +0100 Subject: [PATCH 0792/1340] Yul Disambiguator: Don't check for builtins when translating identifiers --- libyul/optimiser/Disambiguator.cpp | 6 +++--- libyul/optimiser/Disambiguator.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libyul/optimiser/Disambiguator.cpp b/libyul/optimiser/Disambiguator.cpp index 55219f6ea..343feb0be 100644 --- a/libyul/optimiser/Disambiguator.cpp +++ b/libyul/optimiser/Disambiguator.cpp @@ -30,15 +30,15 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::util; -YulName Disambiguator::translateIdentifier(YulName _originalName) +YulName Disambiguator::translateIdentifier(YulName const _originalName) { - if (m_dialect.findBuiltin(_originalName.str()) || m_externallyUsedIdentifiers.count(_originalName)) + if (m_externallyUsedIdentifiers.contains(_originalName)) return _originalName; assertThrow(!m_scopes.empty() && m_scopes.back(), OptimizerException, ""); Scope::Identifier const* id = m_scopes.back()->lookup(_originalName); assertThrow(id, OptimizerException, ""); - if (!m_translations.count(id)) + if (!m_translations.contains(id)) m_translations[id] = m_nameDispenser.newName(_originalName); return m_translations.at(id); } diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index 36d178b08..7ff186f0a 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -56,7 +56,7 @@ class Disambiguator: public ASTCopier void leaveScope(Block const& _block) override; void enterFunction(FunctionDefinition const& _function) override; void leaveFunction(FunctionDefinition const& _function) override; - YulName translateIdentifier(YulName _name) override; + YulName translateIdentifier(YulName _originalName) override; void enterScopeInternal(Scope& _scope); void leaveScopeInternal(Scope& _scope); From 8f38f2304a69ad73b3800c5d552c2bda9dd8afff Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 19 Mar 2025 15:45:17 +0100 Subject: [PATCH 0793/1340] Peephole optimiser: Replace apply methods recursion by folding expression --- libevmasm/PeepholeOptimiser.cpp | 67 +++++++++++++++------------------ 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 879f5b327..cc22db9fa 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -690,16 +690,12 @@ struct DeduplicateNextTagSize1 : SimplePeepholeOptimizerMethod +void applyMethods(OptimiserState& _state) { - assertThrow(false, OptimizerException, "Peephole optimizer failed to apply identity."); -} - -template -void applyMethods(OptimiserState& _state, Method, OtherMethods... _other) -{ - if (!Method::apply(_state)) - applyMethods(_state, _other...); + bool continueWithNextMethod = true; + ((continueWithNextMethod && (continueWithNextMethod &= !Method::apply(_state))), ...); + assertThrow(!continueWithNextMethod, OptimizerException, "Peephole optimizer failed to apply identity."); } size_t numberOfPops(AssemblyItems const& _items) @@ -721,33 +717,32 @@ bool PeepholeOptimiser::optimise() auto const approx = evmasm::Precision::Approximate; OptimiserState state {m_items, 0, back_inserter(m_optimisedItems), m_evmVersion}; while (state.i < m_items.size()) - applyMethods( - state, - PushPop(), - OpPop(), - OpStop(), - OpReturnRevert(), - DoublePush(), - DoubleSwap(), - CommutativeSwap(), - SwapComparison(), - DupSwap(), - IsZeroIsZeroJumpI(), - IsZeroIsZeroRJumpI(), // EOF specific - EqIsZeroJumpI(), - EqIsZeroRJumpI(), // EOF specific - DoubleJump(), - DoubleRJump(), // EOF specific - JumpToNext(), - RJumpToNext(), // EOF specific - UnreachableCode(), - DeduplicateNextTagSize3(), - DeduplicateNextTagSize2(), - DeduplicateNextTagSize1(), - TagConjunctions(), - TruthyAnd(), - Identity() - ); + applyMethods< + PushPop, + OpPop, + OpStop, + OpReturnRevert, + DoublePush, + DoubleSwap, + CommutativeSwap, + SwapComparison, + DupSwap, + IsZeroIsZeroJumpI, + IsZeroIsZeroRJumpI, // EOF specific + EqIsZeroJumpI, + EqIsZeroRJumpI, // EOF specific + DoubleJump, + DoubleRJump, // EOF specific + JumpToNext, + RJumpToNext, // EOF specific + UnreachableCode, + DeduplicateNextTagSize3, + DeduplicateNextTagSize2, + DeduplicateNextTagSize1, + TagConjunctions, + TruthyAnd, + Identity + >(state); if (m_optimisedItems.size() < m_items.size() || ( m_optimisedItems.size() == m_items.size() && ( evmasm::bytesRequired(m_optimisedItems, 3, m_evmVersion, approx) < evmasm::bytesRequired(m_items, 3, m_evmVersion, approx) || From 098b854ce59393a1ef48e06de6b031a793486508 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 17 Mar 2025 09:38:07 +0100 Subject: [PATCH 0794/1340] IRGeneratorForStatements does not check for builtin when mangling user identifiers --- .../codegen/ir/IRGeneratorForStatements.cpp | 21 +++++++------------ .../codegen/IRGeneratorForStatements.cpp | 11 +++------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index c716c43a6..5902cfef6 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -63,8 +63,8 @@ struct CopyTranslate: public yul::ASTCopier { using ExternalRefsMap = std::map; - CopyTranslate(yul::Dialect const& _dialect, IRGenerationContext& _context, ExternalRefsMap const& _references): - m_dialect(_dialect), m_context(_context), m_references(_references) {} + CopyTranslate(IRGenerationContext& _context, ExternalRefsMap const& _references): + m_context(_context), m_references(_references) {} using ASTCopier::operator(); @@ -80,14 +80,11 @@ struct CopyTranslate: public yul::ASTCopier yul::YulName translateIdentifier(yul::YulName _name) override { - // Strictly, the dialect used by inline assembly (m_dialect) could be different - // from the Yul dialect we are compiling to. So we are assuming here that the builtin - // functions are identical. This should not be a problem for now since everything - // is EVM anyway. - if (m_dialect.findBuiltin(_name.str())) - return _name; - else - return yul::YulName{"usr$" + _name.str()}; + // Strictly, the dialect used by inline assembly could be different + // from the Yul dialect we are compiling to. By only translating `YulName`s which correspond to Identifiers, + // we are implicitly excluding builtins together with the assumption, that numerical builtin handles + // stay identical. Special care has to be taken, that these numerical handles stay consistent. + return yul::YulName{"usr$" + _name.str()}; } yul::Identifier translate(yul::Identifier const& _identifier) override @@ -209,8 +206,6 @@ struct CopyTranslate: public yul::ASTCopier return yul::Identifier{_identifier.debugData, yul::YulName{value}}; } - - yul::Dialect const& m_dialect; IRGenerationContext& m_context; ExternalRefsMap const& m_references; }; @@ -2294,7 +2289,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) setLocation(_inlineAsm); if (*_inlineAsm.annotation().hasMemoryEffects && !_inlineAsm.annotation().markedMemorySafe) m_context.setMemoryUnsafeInlineAssemblySeen(); - CopyTranslate bodyCopier{_inlineAsm.dialect(), m_context, _inlineAsm.annotation().externalReferences}; + CopyTranslate bodyCopier{m_context, _inlineAsm.annotation().externalReferences}; yul::Statement modified = bodyCopier(_inlineAsm.operations().root()); diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index 80c442b88..14aef1107 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -54,9 +54,8 @@ struct CopyTranslate: public yul::ASTCopier { CopyTranslate( IRGenerationContext const& _context, - yul::Dialect const& _dialect, std::map _references - ): m_context(_context), m_dialect(_dialect), m_references(std::move(_references)) {} + ): m_context(_context), m_references(std::move(_references)) {} using ASTCopier::operator(); @@ -72,10 +71,7 @@ struct CopyTranslate: public yul::ASTCopier yul::YulName translateIdentifier(yul::YulName _name) override { - if (m_dialect.findBuiltin(_name.str())) - return _name; - else - return yul::YulName{"usr$" + _name.str()}; + return yul::YulName{"usr$" + _name.str()}; } yul::Identifier translate(yul::Identifier const& _identifier) override @@ -106,7 +102,6 @@ struct CopyTranslate: public yul::ASTCopier } IRGenerationContext const& m_context; - yul::Dialect const& m_dialect; std::map m_references; }; @@ -129,7 +124,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tupleExpression) bool IRGeneratorForStatements::visit(InlineAssembly const& _assembly) { - CopyTranslate bodyCopier{m_context, _assembly.dialect(), _assembly.annotation().externalReferences}; + CopyTranslate bodyCopier{m_context, _assembly.annotation().externalReferences}; yul::Statement modified = bodyCopier(_assembly.operations().root()); solAssert(std::holds_alternative(modified)); m_code << yul::AsmPrinter(_assembly.dialect())(std::get(modified)) << "\n"; From 08c9f535288b0d5a337c9dd416a47333791b41b9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 12 Mar 2025 16:41:03 +0100 Subject: [PATCH 0795/1340] AssemblyItem gets an optional instruction and the null-state is properly asserted --- libevmasm/AssemblyItem.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index b053c5b27..8b65d77c9 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -105,7 +105,6 @@ class AssemblyItem explicit AssemblyItem(bytes _verbatimData, size_t _arguments, size_t _returnVariables): m_type(VerbatimBytecode), - m_instruction{}, m_verbatimBytecode{{_arguments, _returnVariables, std::move(_verbatimData)}}, m_debugData{langutil::DebugData::create()} {} @@ -195,7 +194,7 @@ class AssemblyItem /// @returns true if the item has m_instruction properly set. bool hasInstruction() const { - return + bool const shouldHaveInstruction = m_type == Operation || m_type == EOFCreate || m_type == ReturnContract || @@ -206,12 +205,14 @@ class AssemblyItem m_type == RetF || m_type == SwapN || m_type == DupN; + solAssert(shouldHaveInstruction == m_instruction.has_value()); + return shouldHaveInstruction; } /// @returns the instruction of this item (only valid if hasInstruction returns true) Instruction instruction() const { solAssert(hasInstruction()); - return m_instruction; + return *m_instruction; } /// @returns true if the type and data of the items are equal. @@ -323,7 +324,7 @@ class AssemblyItem size_t opcodeCount() const noexcept; AssemblyItemType m_type; - Instruction m_instruction; ///< Only valid if m_type == Operation + std::optional m_instruction; ///< Only valid for item types that represent a specific opcode std::shared_ptr m_data; ///< Only valid if m_type != Operation std::optional m_functionSignature; ///< Only valid if m_type == CallF or JumpF /// If m_type == VerbatimBytecode, this holds number of arguments, number of From dd03613b791b3d13d43b95e253c414eeeb27c35b Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 20 Mar 2025 22:26:14 +0100 Subject: [PATCH 0796/1340] SMTChecker: Fix string literal to fixed bytes conversion with user-defined type --- Changelog.md | 1 + libsolidity/formal/SMTEncoder.cpp | 6 ++++-- ...tes_can_be_initialized_from_string_literal.sol | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/userTypes/user_type_over_fixed_bytes_can_be_initialized_from_string_literal.sol diff --git a/Changelog.md b/Changelog.md index 3e423c838..7efefca02 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: * SMTChecker: Fix incorrect analysis when only a subset of contracts is selected with `--model-checker-contracts`. +* SMTChecker: Fix internal compiler error when string literal is used to initialize user-defined type based on fixed bytes. ### 0.8.29 (2025-03-12) diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 740af9382..044ff61d8 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -929,8 +929,10 @@ void SMTEncoder::visitAddMulMod(FunctionCall const& _funCall) void SMTEncoder::visitWrapUnwrap(FunctionCall const& _funCall) { auto const& args = _funCall.arguments(); - solAssert(args.size() == 1, ""); - defineExpr(_funCall, expr(*args.front())); + smtAssert(args.size() == 1, "Expected exactly one argument to wrap/unwrap"); + auto const& funType = dynamic_cast(*_funCall.expression().annotation().type); + auto const* argType = funType.parameterTypes().front(); + defineExpr(_funCall, expr(*args.front(), argType)); } void SMTEncoder::visitObjectCreation(FunctionCall const& _funCall) diff --git a/test/libsolidity/smtCheckerTests/userTypes/user_type_over_fixed_bytes_can_be_initialized_from_string_literal.sol b/test/libsolidity/smtCheckerTests/userTypes/user_type_over_fixed_bytes_can_be_initialized_from_string_literal.sol new file mode 100644 index 000000000..fe64541f1 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/userTypes/user_type_over_fixed_bytes_can_be_initialized_from_string_literal.sol @@ -0,0 +1,15 @@ +type MyBytes is bytes2; + +contract C { + MyBytes b = MyBytes.wrap("ab"); + + function check() view public { + assert(MyBytes.unwrap(b) == 0); // should fail + assert(MyBytes.unwrap(b) == 0x6162); // should hold + } +} +// ==== +// SMTEngine: chc +// ---- +// Warning 6328: (118-148): CHC: Assertion violation happens here.\nCounterexample:\n\n\nTransaction trace:\nC.constructor()\nC.check() +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From d97d7115815314af238de314d710abd4a1aa6868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaan=20Uzdo=C4=9Fan?= Date: Wed, 26 Feb 2025 16:10:25 -0700 Subject: [PATCH 0797/1340] Update metadata docs for "libraries" and "compilationSettings" fields --- docs/metadata.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/metadata.rst b/docs/metadata.rst index 063936a9d..e5945ea52 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -124,11 +124,13 @@ explanatory purposes. "version": 1 // NatSpec version } }, - // Required: Compiler settings. Reflects the settings in the JSON input during compilation. - // Check the documentation of standard JSON input's "settings" field + // Required: Compiler settings. + // Reflects the settings in the JSON input during compilation, except the + // "compilationTarget" and the "libraries" fields. Check each field for details. + // See the standard JSON input's "settings" docs for the rest. "settings": { // Required for Solidity: File path and the name of the contract or library this - // metadata is created for. + // metadata is created for. Not a valid field in the standard JSON input settings. "compilationTarget": { "myDirectory/myFile.sol": "MyContract" }, @@ -137,8 +139,11 @@ explanatory purposes. // Optional: Only present if not null. "eofVersion": 1, // Required for Solidity: Addresses for libraries used. + // Note that metadata has a different format for "libraries" field than the standard JSON input. + // metadata format = { "MyLib.sol:MyLib": "0x123123..." } + // standard JSON input format = { "MyLib.sol": { "MyLib": "0x123123..." } } "libraries": { - "MyLib": "0x123123..." + "MyLib.sol:MyLib": "0x123123..." }, "metadata": { // Reflects the setting used in the input json, defaults to "true" From 2e33f2557c2c91b59c7d5593389992d7f09b26ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaan=20Uzdo=C4=9Fan?= Date: Wed, 26 Feb 2025 16:21:22 -0700 Subject: [PATCH 0798/1340] Update the metdata settings field to refer the rest of the settings to std-json --- docs/metadata.rst | 54 ++++++++++------------------------------------- 1 file changed, 11 insertions(+), 43 deletions(-) diff --git a/docs/metadata.rst b/docs/metadata.rst index e5945ea52..90513ee32 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -124,20 +124,18 @@ explanatory purposes. "version": 1 // NatSpec version } }, - // Required: Compiler settings. - // Reflects the settings in the JSON input during compilation, except the - // "compilationTarget" and the "libraries" fields. Check each field for details. - // See the standard JSON input's "settings" docs for the rest. + // Required: Compiler settings. + // Reflects the settings in the JSON input during compilation, except: + // - Different format: "libraries" field + // - Added field in metadata.settings: "compilationTarget" + // - Not in metadata.settings: "stopAfter", "debug.debugInfo", "outputSelection" + // See the standard JSON input's "settings" field docs for the rest. "settings": { // Required for Solidity: File path and the name of the contract or library this - // metadata is created for. Not a valid field in the standard JSON input settings. + // metadata is created for. This field is not present in the standard JSON input settings. "compilationTarget": { "myDirectory/myFile.sol": "MyContract" }, - // Required for Solidity. - "evmVersion": "london", - // Optional: Only present if not null. - "eofVersion": 1, // Required for Solidity: Addresses for libraries used. // Note that metadata has a different format for "libraries" field than the standard JSON input. // metadata format = { "MyLib.sol:MyLib": "0x123123..." } @@ -145,40 +143,10 @@ explanatory purposes. "libraries": { "MyLib.sol:MyLib": "0x123123..." }, - "metadata": { - // Reflects the setting used in the input json, defaults to "true" - "appendCBOR": true, - // Reflects the setting used in the input json, defaults to "ipfs" - "bytecodeHash": "ipfs", - // Reflects the setting used in the input json, defaults to "false" - "useLiteralContent": true - }, - // Optional: Optimizer settings. The fields "enabled" and "runs" are deprecated - // and are only given for backward-compatibility. - "optimizer": { - "details": { - "constantOptimizer": false, - "cse": false, - "deduplicate": false, - // inliner defaults to "false" - "inliner": false, - // jumpdestRemover defaults to "true" - "jumpdestRemover": true, - "orderLiterals": false, - // peephole defaults to "true" - "peephole": true, - "yul": true, - // Optional: Only present if "yul" is "true" - "yulDetails": { - "optimizerSteps": "dhfoDgvulfnTUtnIf...", - "stackAllocation": false - } - }, - "enabled": true, - "runs": 500 - }, - // Required for Solidity: Sorted list of import remappings. - "remappings": [ ":g=/dir" ] + // ... + // ... + // ... + // The rest of the fields and their defaults same as in std JSON input. }, // Required: Compilation source files/source units, keys are file paths "sources": { From 1f044c153365955b48d19ae90fa8a57db359c870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaan=20Uzdo=C4=9Fan?= Date: Thu, 20 Mar 2025 10:29:03 +0100 Subject: [PATCH 0799/1340] Remove "sorted" in std-json remappings docs --- docs/using-the-compiler.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 4984d999d..23e83baec 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -279,7 +279,7 @@ Input Description { // Optional: Stop compilation after the given stage. Currently only "parsing" is valid here "stopAfter": "parsing", - // Optional: Sorted list of remappings + // Optional: List of remappings "remappings": [ ":g=/dir" ], // Optional: Optimizer settings "optimizer": { From 1ccea419e6770553f15ce80872be21165ba946c5 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 14 Mar 2025 09:24:30 +0100 Subject: [PATCH 0800/1340] AsmAnalysis: Stronger use of fmt, refactor function call analysis --- libyul/AsmAnalysis.cpp | 272 ++++++++++++++++++++++------------------- libyul/AsmAnalysis.h | 19 +-- 2 files changed, 161 insertions(+), 130 deletions(-) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index b6ff862b3..480373d13 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -94,19 +94,28 @@ bool AsmAnalyzer::analyze(Block const& _block) AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Object const& _object) { yulAssert(_object.dialect()); - return analyzeStrictAssertCorrect(*_object.dialect(), _object.code()->root(), _object.summarizeStructure()); + return analyzeStrictAssertCorrect(*_object.dialect(), *_object.code(), _object.summarizeStructure()); +} + +AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( + Dialect const& _dialect, + AST const& _ast, + Object::Structure _objectStructure +) +{ + return analyzeStrictAssertCorrect(_dialect, _ast.root(), std::move(_objectStructure)); } AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( Dialect const& _dialect, Block const& _astRoot, - Object::Structure const _objectStructure + Object::Structure _objectStructure ) { ErrorList errorList; langutil::ErrorReporter errors(errorList); AsmAnalysisInfo analysisInfo; - bool success = yul::AsmAnalyzer( + bool success = AsmAnalyzer( analysisInfo, errors, _dialect, @@ -155,7 +164,7 @@ size_t AsmAnalyzer::operator()(Literal const& _literal) m_errorReporter.typeError( 3069_error, nativeLocationOf(_literal), - "String literal too long (" + std::to_string(formatLiteral(_literal, false /* _validated */ ).size()) + " > 32)" + fmt::format("String literal too long ({} > 32)", formatLiteral(_literal, false /* _validated */ ).size()) ); } else if (_literal.kind == LiteralKind::Number && _literal.value.hint() && bigint(*_literal.value.hint()) > u256(-1)) @@ -170,7 +179,7 @@ size_t AsmAnalyzer::operator()(Literal const& _literal) size_t AsmAnalyzer::operator()(Identifier const& _identifier) { - yulAssert(!_identifier.name.empty(), ""); + yulAssert(!_identifier.name.empty()); auto watcher = m_errorReporter.errorWatcher(); if (m_currentScope->lookup(_identifier.name, GenericVisitor{ @@ -180,7 +189,7 @@ size_t AsmAnalyzer::operator()(Identifier const& _identifier) m_errorReporter.declarationError( 4990_error, nativeLocationOf(_identifier), - "Variable " + _identifier.name.str() + " used before it was declared." + fmt::format("Variable {} used before it was declared.", _identifier.name.str()) ); }, [&](Scope::Function const&) @@ -188,14 +197,15 @@ size_t AsmAnalyzer::operator()(Identifier const& _identifier) m_errorReporter.typeError( 6041_error, nativeLocationOf(_identifier), - "Function " + _identifier.name.str() + " used without being called." + fmt::format("Function {} used without being called.", _identifier.name.str()) ); } })) { if (m_resolver) // We found a local reference, make sure there is no external reference. - m_resolver( + // Used for side effects, e.g., error reporting in TypeChecker, hence ignoring return value + std::ignore = m_resolver( _identifier, yul::IdentifierContext::NonExternal, m_currentScope->insideFunction() @@ -213,7 +223,7 @@ size_t AsmAnalyzer::operator()(Identifier const& _identifier) m_errorReporter.declarationError( 8198_error, nativeLocationOf(_identifier), - "Identifier \"" + _identifier.name.str() + "\" not found." + fmt::format("Identifier \"{}\" not found.", _identifier.name.str()) ); } @@ -229,11 +239,12 @@ void AsmAnalyzer::operator()(ExpressionStatement const& _statement) m_errorReporter.typeError( 3083_error, nativeLocationOf(_statement), - "Top-level expressions are not supposed to return values (this expression returns " + - std::to_string(numReturns) + - " value" + - (numReturns == 1 ? "" : "s") + - "). Use ``pop()`` or assign them." + fmt::format( + "Top-level expressions are not supposed to return values (this expression returns {} value{}). " + "Use ``pop()`` or assign them.", + numReturns, + numReturns == 1 ? "" : "s" + ) ); } @@ -249,9 +260,10 @@ void AsmAnalyzer::operator()(Assignment const& _assignment) m_errorReporter.declarationError( 9005_error, nativeLocationOf(_assignment), - "Variable " + - _variableName.name.str() + - " occurs multiple times on the left-hand side of the assignment." + fmt::format( + "Variable {} occurs multiple times on the left-hand side of the assignment.", + _variableName.name.str() + ) ); size_t numRhsValues = std::visit(*this, *_assignment.value); @@ -260,13 +272,12 @@ void AsmAnalyzer::operator()(Assignment const& _assignment) m_errorReporter.declarationError( 8678_error, nativeLocationOf(_assignment), - "Variable count for assignment to \"" + - joinHumanReadable(applyMap(_assignment.variableNames, [](auto const& _identifier){ return _identifier.name.str(); })) + - "\" does not match number of values (" + - std::to_string(numVariables) + - " vs. " + - std::to_string(numRhsValues) + - ")" + fmt::format( + "Variable count for assignment to \"{}\" does not match number of values ({} vs. {})", + joinHumanReadable(applyMap(_assignment.variableNames, [](auto const& _identifier){ return _identifier.name.str(); })), + numVariables, + numRhsValues + ) ); for (size_t i = 0; i < numVariables; ++i) @@ -296,13 +307,12 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) m_errorReporter.declarationError( 3812_error, nativeLocationOf(_varDecl), - "Variable count mismatch for declaration of \"" + - joinHumanReadable(applyMap(_varDecl.variables, [](auto const& _identifier){ return _identifier.name.str(); })) + - + "\": " + - std::to_string(numVariables) + - " variables and " + - std::to_string(numValues) + - " values." + fmt::format( + "Variable count mismatch for declaration of \"{}\": {} variables and {} values.", + joinHumanReadable(applyMap(_varDecl.variables, [](auto const& _identifier){ return _identifier.name.str(); })), + numVariables, + numValues + ) ); } @@ -314,7 +324,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) void AsmAnalyzer::operator()(FunctionDefinition const& _funDef) { - yulAssert(!_funDef.name.empty(), ""); + yulAssert(!_funDef.name.empty()); expectValidIdentifier(_funDef.name, nativeLocationOf(_funDef)); Block const* virtualBlock = m_info.virtualBlocks.at(&_funDef).get(); yulAssert(virtualBlock, ""); @@ -352,77 +362,89 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) std::optional numReturns; std::vector> const* literalArguments = nullptr; - if (BuiltinFunction const* builtin = resolveBuiltinFunction(_funCall.functionName, m_dialect)) - { - if (builtin->name == "selfdestruct") - m_errorReporter.warning( - 1699_error, - nativeLocationOf(_funCall.functionName), - "\"selfdestruct\" has been deprecated. " - "Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and " - "data associated with an account and only transfers its Ether to the beneficiary, " - "unless executed in the same transaction in which the contract was created (see EIP-6780). " - "Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. " - "Future changes to the EVM might further reduce the functionality of the opcode." - ); - else if ( - m_evmVersion.supportsTransientStorage() && - builtin->name == "tstore" && - !m_errorReporter.hasError({2394}) - ) - m_errorReporter.warning( - 2394_error, - nativeLocationOf(_funCall.functionName), - "Transient storage as defined by EIP-1153 can break the composability of smart contracts: " - "Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, " - "your contract may unintentionally misbehave when invoked multiple times in a complex transaction. " - "To avoid this, be sure to clear all transient storage at the end of any call to your contract. " - "The use of transient storage for reentrancy guards that are cleared at the end of the call is safe." - ); + std::visit( + GenericVisitor { + [&](BuiltinName const& _builtinName) + { + BuiltinFunction const& builtin = m_dialect.builtin(_builtinName.handle); + if (builtin.name == "selfdestruct") + m_errorReporter.warning( + 1699_error, + nativeLocationOf(_builtinName), + "\"selfdestruct\" has been deprecated. " + "Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and " + "data associated with an account and only transfers its Ether to the beneficiary, " + "unless executed in the same transaction in which the contract was created (see EIP-6780). " + "Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. " + "Future changes to the EVM might further reduce the functionality of the opcode." + ); + else if ( + builtin.name == "tstore" && + !m_errorReporter.hasError({2394}) + ) + { + yulAssert(m_evmVersion.supportsTransientStorage(), "tstore is only a builtin on EVMs that support transient storage"); + m_errorReporter.warning( + 2394_error, + nativeLocationOf(_builtinName), + "Transient storage as defined by EIP-1153 can break the composability of smart contracts: " + "Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, " + "your contract may unintentionally misbehave when invoked multiple times in a complex transaction. " + "To avoid this, be sure to clear all transient storage at the end of any call to your contract. " + "The use of transient storage for reentrancy guards that are cleared at the end of the call is safe." + ); + } - numParameters = builtin->numParameters; - numReturns = builtin->numReturns; - if (!builtin->literalArguments.empty()) - literalArguments = &builtin->literalArguments; + numParameters = builtin.numParameters; + numReturns = builtin.numReturns; + if (!builtin.literalArguments.empty()) + literalArguments = &builtin.literalArguments; - validateInstructions(_funCall); - m_sideEffects += builtin->sideEffects; - } - else if (m_currentScope->lookup(YulName{resolveFunctionName(_funCall.functionName, m_dialect)}, GenericVisitor{ - [&](Scope::Variable const&) - { - m_errorReporter.typeError( - 4202_error, - nativeLocationOf(_funCall.functionName), - "Attempt to call variable instead of function." - ); + validateInstructions(_funCall); + m_sideEffects += builtin.sideEffects; + }, + [&](Identifier const& _identifier) + { + bool const identifierInCurrentScope = m_currentScope->lookup(_identifier.name, GenericVisitor{ + [&](Scope::Variable const&) + { + m_errorReporter.typeError( + 4202_error, + nativeLocationOf(_identifier), + "Attempt to call variable instead of function." + ); + }, + [&](Scope::Function const& _fun) + { + numParameters = _fun.numArguments; + numReturns = _fun.numReturns; + } + }); + if (identifierInCurrentScope) + { + if (m_resolver) + // We found a local reference, make sure there is no external reference. + // Used for side effects, e.g., error reporting in TypeChecker, hence ignoring return value + std::ignore = m_resolver( + _identifier, + yul::IdentifierContext::NonExternal, + m_currentScope->insideFunction() + ); + } + else + { + if (!validateInstructions(_funCall)) + m_errorReporter.declarationError( + 4619_error, + nativeLocationOf(_identifier), + fmt::format("Function \"{}\" not found.", _identifier.name.str()) + ); + yulAssert(!watcher.ok(), "Expected a reported error."); + } + } }, - [&](Scope::Function const& _fun) - { - numParameters = _fun.numArguments; - numReturns = _fun.numReturns; - } - })) - { - yulAssert(std::holds_alternative(_funCall.functionName)); - if (m_resolver) - // We found a local reference, make sure there is no external reference. - m_resolver( - std::get(_funCall.functionName), - yul::IdentifierContext::NonExternal, - m_currentScope->insideFunction() - ); - } - else - { - if (!validateInstructions(_funCall)) - m_errorReporter.declarationError( - 4619_error, - nativeLocationOf(_funCall.functionName), - fmt::format("Function \"{}\" not found.", resolveFunctionName(_funCall.functionName, m_dialect)) - ); - yulAssert(!watcher.ok(), "Expected a reported error."); - } + _funCall.functionName + ); if (numParameters && _funCall.arguments.size() != *numParameters) m_errorReporter.typeError( @@ -455,7 +477,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) m_errorReporter.typeError( 5859_error, nativeLocationOf(arg), - "Function expects " + to_string(*literalArgumentKind) + " literal." + fmt::format("Function expects {} literal.", to_string(*literalArgumentKind)) ); else if (*literalArgumentKind == LiteralKind::String) { @@ -467,7 +489,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) m_errorReporter.typeError( 3517_error, nativeLocationOf(arg), - "Unknown data object \"" + formatLiteral(argumentAsLiteral) + "\"." + fmt::format("Unknown data object \"{}\".", formatLiteral(argumentAsLiteral)) ); } else if (functionName.substr(0, "verbatim_"s.size()) == "verbatim_") @@ -499,14 +521,17 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) m_errorReporter.typeError( 7575_error, nativeLocationOf(arg), - "Data name \"" + formattedLiteral + "\" cannot be used as an argument of eofcreate/returncontract. " + - "An object name is only acceptable." + fmt::format( + "Data name \"{}\" cannot be used as an argument of eofcreate/returncontract. " + "An object name is only acceptable.", + formattedLiteral + ) ); else m_errorReporter.typeError( 8970_error, nativeLocationOf(arg), - "Unknown object \"" + formattedLiteral + "\"." + fmt::format("Unknown object \"{}\".", formattedLiteral) ); } } @@ -579,9 +604,7 @@ void AsmAnalyzer::operator()(Switch const& _switch) m_errorReporter.declarationError( 6792_error, nativeLocationOf(_case), - "Duplicate case \"" + - formatLiteral(*_case.value) + - "\" defined." + fmt::format("Duplicate case \"{}\" defined.", formatLiteral(*_case.value)) ); } @@ -631,9 +654,10 @@ void AsmAnalyzer::expectExpression(Expression const& _expr) m_errorReporter.typeError( 3950_error, nativeLocationOf(_expr), - "Expected expression to evaluate to one value, but got " + - std::to_string(numValues) + - " values instead." + fmt::format( + "Expected expression to evaluate to one value, but got {} values instead.", + numValues + ) ); } @@ -645,7 +669,7 @@ void AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal) void AsmAnalyzer::checkAssignment(Identifier const& _variable) { - yulAssert(!_variable.name.empty(), ""); + yulAssert(!_variable.name.empty()); auto watcher = m_errorReporter.errorWatcher(); bool hasVariable = false; bool found = false; @@ -653,7 +677,8 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable) { if (m_resolver) // We found a local reference, make sure there is no external reference. - m_resolver( + // Used for side effects, e.g., error reporting in TypeChecker, hence ignoring return value + std::ignore = m_resolver( _variable, yul::IdentifierContext::NonExternal, m_currentScope->insideFunction() @@ -665,7 +690,7 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable) m_errorReporter.declarationError( 1133_error, nativeLocationOf(_variable), - "Variable " + _variable.name.str() + " used before it was declared." + fmt::format("Variable {} used before it was declared.", _variable.name.str()) ); else hasVariable = true; @@ -698,26 +723,27 @@ Scope& AsmAnalyzer::scope(Block const* _block) void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation const& _location) { + std::string_view const label = _identifier.str(); // NOTE: the leading dot case is handled by the parser not allowing it. - if (boost::ends_with(_identifier.str(), ".")) + if (label.ends_with('.')) m_errorReporter.syntaxError( 3384_error, _location, - "\"" + _identifier.str() + "\" is not a valid identifier (ends with a dot)." + fmt::format("\"{}\" is not a valid identifier (ends with a dot).", label) ); - if (_identifier.str().find("..") != std::string::npos) + if (label.find("..") != std::string::npos) m_errorReporter.syntaxError( 7771_error, _location, - "\"" + _identifier.str() + "\" is not a valid identifier (contains consecutive dots)." + fmt::format("\"{}\" is not a valid identifier (contains consecutive dots).", label) ); - if (m_dialect.reservedIdentifier(_identifier.str())) + if (m_dialect.reservedIdentifier(label)) m_errorReporter.declarationError( 5017_error, _location, - "The identifier \"" + _identifier.str() + "\" is reserved and can not be used." + fmt::format("The identifier \"{}\" is reserved and can not be used.", label) ); } @@ -744,7 +770,7 @@ bool AsmAnalyzer::validateInstructions(std::string_view _instructionIdentifier, 7223_error, _location, fmt::format( - "Builtin function \"{}\" is only available in EOF.", + "Builtin function \"{function}\" is only available in EOF.", fmt::arg("function", _instructionIdentifier) ) ); @@ -844,7 +870,7 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio 4328_error, _location, fmt::format( - "The \"{}\" instruction is only available in EOF.", + "The \"{instruction}\" instruction is only available in EOF.", fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name)) ) ); @@ -899,7 +925,7 @@ bool AsmAnalyzer::validateInstructions(FunctionCall const& _functionCall) ); } -void AsmAnalyzer::validateObjectStructure(langutil::SourceLocation _astRootLocation) +void AsmAnalyzer::validateObjectStructure(langutil::SourceLocation const& _astRootLocation) { if (m_eofVersion.has_value()) { diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index e8c02fbec..51b8cde2b 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -62,7 +62,7 @@ class AsmAnalyzer langutil::ErrorReporter& _errorReporter, Dialect const& _dialect, ExternalIdentifierAccess::Resolver _resolver = ExternalIdentifierAccess::Resolver(), - Object::Structure const _objectStructure = {} + Object::Structure _objectStructure = {} ): m_resolver(std::move(_resolver)), m_info(_analysisInfo), @@ -85,7 +85,12 @@ class AsmAnalyzer static AsmAnalysisInfo analyzeStrictAssertCorrect( Dialect const& _dialect, Block const& _astRoot, - Object::Structure const _objectStructure + Object::Structure _objectStructure + ); + static AsmAnalysisInfo analyzeStrictAssertCorrect( + Dialect const& _dialect, + AST const& _ast, + Object::Structure _objectStructure ); size_t operator()(Literal const& _literal); @@ -98,9 +103,9 @@ class AsmAnalyzer void operator()(If const& _if); void operator()(Switch const& _switch); void operator()(ForLoop const& _forLoop); - void operator()(Break const&) { } - void operator()(Continue const&) { } - void operator()(Leave const&) { } + void operator()(Break const&) const { } + void operator()(Continue const&) const { } + void operator()(Leave const&) const { } void operator()(Block const& _block); /// @returns the worst side effects encountered during analysis (including within defined functions). @@ -109,7 +114,7 @@ class AsmAnalyzer /// Visits the expression, expects that it evaluates to exactly one value. /// Reports errors otherwise. void expectExpression(Expression const& _expr); - void expectUnlimitedStringLiteral(Literal const& _literal); + static void expectUnlimitedStringLiteral(Literal const& _literal); /// Verifies that a variable to be assigned to exists and can be assigned to. void checkAssignment(Identifier const& _variable); @@ -121,7 +126,7 @@ class AsmAnalyzer bool validateInstructions(std::string_view _instrIdentifier, langutil::SourceLocation const& _location); bool validateInstructions(FunctionCall const& _functionCall); - void validateObjectStructure(langutil::SourceLocation _astRootLocation); + void validateObjectStructure(langutil::SourceLocation const& _astRootLocation); yul::ExternalIdentifierAccess::Resolver m_resolver; Scope* m_currentScope = nullptr; From b9cbf1e7db82b74c1c07801a05f663321889ce26 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 21 Mar 2025 09:17:09 +0100 Subject: [PATCH 0801/1340] AsmAnalysis: Improve wording of invalid argument for eofcreate/returncontract error --- libyul/AsmAnalysis.cpp | 2 +- .../yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 480373d13..b36eb48b4 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -523,7 +523,7 @@ size_t AsmAnalyzer::operator()(FunctionCall const& _funCall) nativeLocationOf(arg), fmt::format( "Data name \"{}\" cannot be used as an argument of eofcreate/returncontract. " - "An object name is only acceptable.", + "Only an object name is acceptable.", formattedLiteral ) ); diff --git a/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul index 1e9fad7d0..06bb487d6 100644 --- a/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul +++ b/test/libyul/yulSyntaxTests/eof/eofcreate_invalid_object_name_data.yul @@ -10,4 +10,4 @@ object "a" { // EVMVersion: >=shanghai // bytecodeFormat: >=EOFv1 // ---- -// TypeError 7575: (52-59): Data name "data1" cannot be used as an argument of eofcreate/returncontract. An object name is only acceptable. +// TypeError 7575: (52-59): Data name "data1" cannot be used as an argument of eofcreate/returncontract. Only an object name is acceptable. From d1cbd8dc3f0bd390669a99c8e036b8d6fd215b89 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 17 Mar 2025 11:02:44 +0100 Subject: [PATCH 0802/1340] interpreter uses yul AST instead of separate block and dialect --- test/libyul/YulInterpreterTest.cpp | 3 +-- test/tools/yulInterpreter/Inspector.cpp | 15 +++++++-------- test/tools/yulInterpreter/Inspector.h | 3 +-- test/tools/yulInterpreter/Interpreter.cpp | 5 ++--- test/tools/yulInterpreter/Interpreter.h | 4 ++-- 5 files changed, 13 insertions(+), 17 deletions(-) diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index d97211b97..42e0e7c6f 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -80,8 +80,7 @@ std::string YulInterpreterTest::interpret(std::shared_ptr const& _ { Interpreter::run( state, - *_object->dialect(), - _object->code()->root(), + *_object->code(), /*disableExternalCalls=*/ !m_simulateExternalCallsToSelf, /*disableMemoryTracing=*/ false ); diff --git a/test/tools/yulInterpreter/Inspector.cpp b/test/tools/yulInterpreter/Inspector.cpp index 7746483a3..5fec7f1c5 100644 --- a/test/tools/yulInterpreter/Inspector.cpp +++ b/test/tools/yulInterpreter/Inspector.cpp @@ -31,9 +31,9 @@ using namespace solidity::yul::test; namespace { -void printVariable(YulString const& _name, u256 const& _value) +void printVariable(std::string_view const _name, u256 const& _value) { - std::cout << "\t" << _name.str() << " = " << _value.str(); + std::cout << "\t" << _name << " = " << _value.str(); if (_value != 0) std::cout << " (" << toCompactHexWithPrefix(_value) << ")"; @@ -46,17 +46,16 @@ void printVariable(YulString const& _name, u256 const& _value) void InspectedInterpreter::run( std::shared_ptr _inspector, InterpreterState& _state, - Dialect const& _dialect, - Block const& _ast, + AST const& _ast, bool _disableExternalCalls, bool _disableMemoryTrace ) { Scope scope; - InspectedInterpreter{_inspector, _state, _dialect, scope, _disableExternalCalls, _disableMemoryTrace}(_ast); + InspectedInterpreter{_inspector, _state, _ast.dialect(), scope, _disableExternalCalls, _disableMemoryTrace}(_ast.root()); } -Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std::map const& _variables) +Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std::map const& _variables) { if (m_stepMode == NodeAction::RunNode) { @@ -99,7 +98,7 @@ Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std else if (input == "variables" || input == "v") { for (auto &&[yulStr, val]: _variables) - printVariable(yulStr, val); + printVariable(yulStr.str(), val); std::cout << std::endl; } else if ( @@ -120,7 +119,7 @@ Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std for (auto &&[yulStr, val]: _variables) if (yulStr.str() == varname) { - printVariable(yulStr, val); + printVariable(varname, val); found = true; break; } diff --git a/test/tools/yulInterpreter/Inspector.h b/test/tools/yulInterpreter/Inspector.h index 903ebc114..3ea669b43 100644 --- a/test/tools/yulInterpreter/Inspector.h +++ b/test/tools/yulInterpreter/Inspector.h @@ -103,8 +103,7 @@ class InspectedInterpreter: public Interpreter static void run( std::shared_ptr _inspector, InterpreterState& _state, - Dialect const& _dialect, - Block const& _ast, + AST const& _ast, bool _disableExternalCalls, bool _disableMemoryTracing ); diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index 2709d1b46..05db9f581 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -109,14 +109,13 @@ void InterpreterState::dumpTraceAndState(std::ostream& _out, bool _disableMemory void Interpreter::run( InterpreterState& _state, - Dialect const& _dialect, - Block const& _ast, + AST const& _ast, bool _disableExternalCalls, bool _disableMemoryTrace ) { Scope scope; - Interpreter{_state, _dialect, scope, _disableExternalCalls, _disableMemoryTrace}(_ast); + Interpreter{_state, _ast.dialect(), scope, _disableExternalCalls, _disableMemoryTrace}(_ast.root()); } void Interpreter::operator()(ExpressionStatement const& _expressionStatement) diff --git a/test/tools/yulInterpreter/Interpreter.h b/test/tools/yulInterpreter/Interpreter.h index 427a30d9e..3dd6a4238 100644 --- a/test/tools/yulInterpreter/Interpreter.h +++ b/test/tools/yulInterpreter/Interpreter.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include #include @@ -162,8 +163,7 @@ class Interpreter: public ASTWalker /// activated e.g., Redundant store eliminator, Equal store eliminator. static void run( InterpreterState& _state, - Dialect const& _dialect, - Block const& _ast, + AST const& _ast, bool _disableExternalCalls, bool _disableMemoryTracing ); From 8859625fdeb9a19f538d596d380e0fae28ea108e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 17 Mar 2025 11:02:55 +0100 Subject: [PATCH 0803/1340] yulrun on AST --- test/tools/yulrun.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index 36d488586..a5fa05d93 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -63,6 +63,9 @@ std::pair, std::shared_ptr> parse(st solidity::frontend::OptimiserSettings::none(), DebugInfoSelection::Default() ); + auto const* evmDialect = dynamic_cast(&stack.dialect()); + // TODO: Add EOF support + solUnimplementedAssert(evmDialect && !evmDialect->eofVersion(), "No EOF support for yulrun yet."); if (stack.parseAndAnalyze("--INPUT--", _source)) { yulAssert(!Error::hasErrorsWarningsOrInfos(stack.errors()), "Parsed successfully but had errors."); @@ -87,13 +90,10 @@ void interpret(std::string const& _source, bool _inspect, bool _disableExternalC state.maxTraceSize = 10000; try { - Dialect const& dialect(EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}, std::nullopt)); - if (_inspect) - InspectedInterpreter::run(std::make_shared(_source, state), state, dialect, ast->root(), _disableExternalCalls, /*disableMemoryTracing=*/false); - + InspectedInterpreter::run(std::make_shared(_source, state), state, *ast, _disableExternalCalls, /*disableMemoryTracing=*/false); else - Interpreter::run(state, dialect, ast->root(), _disableExternalCalls, /*disableMemoryTracing=*/false); + Interpreter::run(state, *ast, _disableExternalCalls, /*disableMemoryTracing=*/false); } catch (InterpreterTerminatedGeneric const&) { From dafe00677e1ccf04fb4853d74885cfe7288b25e7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 17 Mar 2025 10:56:53 +0100 Subject: [PATCH 0804/1340] ossfuzz uses yul AST instead of separate block and dialect --- test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 6 ++---- test/tools/ossfuzz/yulFuzzerCommon.cpp | 5 ++--- test/tools/ossfuzz/yulFuzzerCommon.h | 3 +-- test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp | 6 ++---- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index a4515b309..9abf269c8 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -90,8 +90,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) // TODO: Add EOF support yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( os1, - stack.parserResult()->code()->root(), - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(), std::nullopt), + *stack.parserResult()->code(), /*disableMemoryTracing=*/true ); if (yulFuzzerUtil::resourceLimitsExceeded(termReason)) @@ -100,8 +99,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) stack.optimize(); termReason = yulFuzzerUtil::interpret( os2, - stack.parserResult()->code()->root(), - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(), std::nullopt), + *stack.parserResult()->code(), /*disableMemoryTracing=*/true ); diff --git a/test/tools/ossfuzz/yulFuzzerCommon.cpp b/test/tools/ossfuzz/yulFuzzerCommon.cpp index b95df8f21..c34f4351c 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.cpp +++ b/test/tools/ossfuzz/yulFuzzerCommon.cpp @@ -23,8 +23,7 @@ using namespace solidity::yul::test::yul_fuzzer; yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( std::ostream& _os, - yul::Block const& _astRoot, - Dialect const& _dialect, + AST const& _ast, bool _disableMemoryTracing, bool _outputStorageOnly, size_t _maxSteps, @@ -52,7 +51,7 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( TerminationReason reason = TerminationReason::None; try { - Interpreter::run(state, _dialect, _astRoot, true, _disableMemoryTracing); + Interpreter::run(state, _ast, true, _disableMemoryTracing); } catch (StepLimitReached const&) { diff --git a/test/tools/ossfuzz/yulFuzzerCommon.h b/test/tools/ossfuzz/yulFuzzerCommon.h index afcb0f2d3..dcfd0f833 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.h +++ b/test/tools/ossfuzz/yulFuzzerCommon.h @@ -40,8 +40,7 @@ struct yulFuzzerUtil /// eliminator. static TerminationReason interpret( std::ostream& _os, - yul::Block const& _astRoot, - Dialect const& _dialect, + AST const& _ast, bool _disableMemoryTracing = false, bool _outputStorageOnly = false, size_t _maxSteps = maxSteps, diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index d15043972..4edfbf7ba 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -90,8 +90,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // TODO: Add EOF support yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( os1, - stack.parserResult()->code()->root(), - EVMDialect::strictAssemblyForEVMObjects(version, std::nullopt), + *stack.parserResult()->code(), /*disableMemoryTracing=*/true ); @@ -106,8 +105,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // TODO: Add EOF support termReason = yulFuzzerUtil::interpret( os2, - *astRoot, - EVMDialect::strictAssemblyForEVMObjects(version, std::nullopt), + *optimizerTest.optimizedObject()->code(), true ); if (yulFuzzerUtil::resourceLimitsExceeded(termReason)) From 77878e5d4a56ea175d131a2338052ab4ac1e9ceb Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 14 Mar 2025 13:14:01 +0100 Subject: [PATCH 0805/1340] add repeats to external.sh --- test/benchmarks/external.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/test/benchmarks/external.sh b/test/benchmarks/external.sh index b003f0ba1..7ad3279ae 100755 --- a/test/benchmarks/external.sh +++ b/test/benchmarks/external.sh @@ -42,9 +42,10 @@ source "${repo_root}/scripts/common.sh" # shellcheck source=scripts/common_cmdline.sh source "${repo_root}/scripts/common_cmdline.sh" -(( $# <= 1 )) || fail "Too many arguments. Usage: external.sh []" +(( $# <= 2 )) || fail "Too many arguments. Usage: external.sh [] []" solc="${1:-${SOLIDITY_BUILD_DIR}/solc/solc}" +num_repeats="${2:-1}" command_available "$solc" --version command_available "$(type -P time)" --version @@ -65,10 +66,10 @@ function benchmark_project { > /dev/null \ 2> "../stderr-${project}-${pipeline}.log" || true - printf '| %-21s | %8s | %6d s | %9d MiB | %9d |\n' \ + printf '| %-21s | %8s | %6.2f s | %9d MiB | %9d |\n' \ "$project" \ "$pipeline" \ - "$(jq '(.user + .sys) | round' "$time_file")" \ + "$(jq '(.user + .sys) * 100 | round / 100' "$time_file")" \ "$(jq '.mem / 1024 | round' "$time_file")" \ "$(jq '.exit' "$time_file")" cd .. @@ -96,8 +97,12 @@ echo "| File | Pipeline | Time | Memory (peak) | Exit code echo "|-----------------------|----------|---------:|--------------:|----------:|" for project in "${benchmarks[@]}"; do - benchmark_project legacy "$project" - benchmark_project ir "$project" + for ((i=0; i Date: Tue, 25 Mar 2025 20:58:29 +0200 Subject: [PATCH 0806/1340] fix: Remove unnecessary Expression temporary in CHCSmtLib2Interface fix: Remove unnecessary Expression temporary in CHCSmtLib2Interface Update CHCSmtLib2Interface.cpp Update CHCSmtLib2Interface.cpp add repeats to external.sh --- libsmtutil/CHCSmtLib2Interface.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index 6b0534296..04cbad1ad 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -465,9 +465,7 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp smtSolverInteractionRequire(isAtom(nameSortPair[0]), "Invalid format of CHC model"); SortPointer varSort = scopedParser.toSort(nameSortPair[1]); scopedParser.addVariableDeclaration(asAtom(nameSortPair[0]), varSort); - // FIXME: Why Expression here? - Expression arg = scopedParser.toSMTUtilExpression(nameSortPair[0]); - predicateArgs.push_back(arg); + predicateArgs.push_back(scopedParser.toSMTUtilExpression(nameSortPair[0])); } auto parsedInterpretation = scopedParser.toSMTUtilExpression(interpretation); @@ -479,6 +477,7 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp }); Expression predicate(asAtom(args[1]), predicateArgs, SortProvider::boolSort); + // FIXME: Why do we need to represent the predicate as Expression? definitions.push_back(predicate == parsedInterpretation); } return Expression::mkAnd(std::move(definitions)); From a4489211c9a872e81235d35433cdffe318755c77 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 28 Mar 2025 09:30:49 +0100 Subject: [PATCH 0807/1340] SMTChecker: Move helper function towards its only usage We don't need a separate file for a single, relatively small, helper function. --- libsolidity/CMakeLists.txt | 2 - libsolidity/formal/CHC.cpp | 54 +++++++++++++++++++- libsolidity/formal/Invariants.cpp | 85 ------------------------------- libsolidity/formal/Invariants.h | 37 -------------- 4 files changed, 53 insertions(+), 125 deletions(-) delete mode 100644 libsolidity/formal/Invariants.cpp delete mode 100644 libsolidity/formal/Invariants.h diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 5925a50ac..f0289acac 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -117,8 +117,6 @@ set(sources formal/EncodingContext.h formal/ExpressionFormatter.cpp formal/ExpressionFormatter.h - formal/Invariants.cpp - formal/Invariants.h formal/ModelChecker.cpp formal/ModelChecker.h formal/ModelCheckerSettings.cpp diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index bab340051..67878084f 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -19,8 +19,8 @@ #include #include +#include #include -#include #include #include #include @@ -2134,6 +2134,58 @@ void CHC::checkVerificationTargets() m_safeTargets[m_verificationTargets.at(id).errorNode].insert(m_verificationTargets.at(id)); } +namespace +{ +std::map> collectInvariants( + smtutil::Expression const& _proof, + std::set const& _predicates, + ModelCheckerInvariants const& _invariantsSetting +) +{ + std::set targets; + if (_invariantsSetting.has(InvariantType::Contract)) + targets.insert("interface_"); + if (_invariantsSetting.has(InvariantType::Reentrancy)) + targets.insert("nondet_interface_"); + + std::map> equalities; + // Collect equalities where one of the sides is a predicate we're interested in. + util::BreadthFirstSearch{{&_proof}}.run([&](auto&& _expr, auto&& _addChild) { + if (_expr->name == "=") + for (auto const& t: targets) + { + auto arg0 = _expr->arguments.at(0); + auto arg1 = _expr->arguments.at(1); + if (boost::algorithm::starts_with(arg0.name, t)) + equalities.insert({arg0.name, {arg0, std::move(arg1)}}); + else if (boost::algorithm::starts_with(arg1.name, t)) + equalities.insert({arg1.name, {arg1, std::move(arg0)}}); + } + for (auto const& arg: _expr->arguments) + _addChild(&arg); + }); + + std::map> invariants; + for (auto pred: _predicates) + { + auto predName = pred->functor().name; + if (!equalities.count(predName)) + continue; + + solAssert(pred->contextContract(), ""); + + auto const& [predExpr, invExpr] = equalities.at(predName); + + static std::set const ignore{"true", "false"}; + auto r = substitute(invExpr, pred->expressionSubstitution(predExpr)); + // No point in reporting true/false as invariants. + if (!ignore.count(r.name)) + invariants[pred].insert(toSolidityStr(r)); + } + return invariants; +} +} // namespace + void CHC::checkAndReportTarget( CHCVerificationTarget const& _target, std::vector const& _placeholders, diff --git a/libsolidity/formal/Invariants.cpp b/libsolidity/formal/Invariants.cpp deleted file mode 100644 index 017ab1e3a..000000000 --- a/libsolidity/formal/Invariants.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - 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 - -#include - -#include -#include - -#include - -#include - -using boost::algorithm::starts_with; -using namespace solidity; -using namespace solidity::smtutil; -using namespace solidity::frontend::smt; - -namespace solidity::frontend::smt -{ - -std::map> collectInvariants( - smtutil::Expression const& _proof, - std::set const& _predicates, - ModelCheckerInvariants const& _invariantsSetting -) -{ - std::set targets; - if (_invariantsSetting.has(InvariantType::Contract)) - targets.insert("interface_"); - if (_invariantsSetting.has(InvariantType::Reentrancy)) - targets.insert("nondet_interface_"); - - std::map> equalities; - // Collect equalities where one of the sides is a predicate we're interested in. - util::BreadthFirstSearch{{&_proof}}.run([&](auto&& _expr, auto&& _addChild) { - if (_expr->name == "=") - for (auto const& t: targets) - { - auto arg0 = _expr->arguments.at(0); - auto arg1 = _expr->arguments.at(1); - if (starts_with(arg0.name, t)) - equalities.insert({arg0.name, {arg0, std::move(arg1)}}); - else if (starts_with(arg1.name, t)) - equalities.insert({arg1.name, {arg1, std::move(arg0)}}); - } - for (auto const& arg: _expr->arguments) - _addChild(&arg); - }); - - std::map> invariants; - for (auto pred: _predicates) - { - auto predName = pred->functor().name; - if (!equalities.count(predName)) - continue; - - solAssert(pred->contextContract(), ""); - - auto const& [predExpr, invExpr] = equalities.at(predName); - - static std::set const ignore{"true", "false"}; - auto r = substitute(invExpr, pred->expressionSubstitution(predExpr)); - // No point in reporting true/false as invariants. - if (!ignore.count(r.name)) - invariants[pred].insert(toSolidityStr(r)); - } - return invariants; -} - -} diff --git a/libsolidity/formal/Invariants.h b/libsolidity/formal/Invariants.h deleted file mode 100644 index b6459fccd..000000000 --- a/libsolidity/formal/Invariants.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - 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 - -#pragma once - -#include -#include - -#include -#include -#include - -namespace solidity::frontend::smt -{ - -std::map> collectInvariants( - smtutil::Expression const& _proof, - std::set const& _predicates, - ModelCheckerInvariants const& _invariantsSettings -); - -} From 5ea8f2587447a09daa4089322dc06d1f323a16e7 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 19 Mar 2025 13:40:09 +0100 Subject: [PATCH 0808/1340] Add support for enum values in NatSpec --- Changelog.md | 1 + libsolidity/ast/AST.h | 14 ++++- libsolidity/ast/ASTJsonExporter.cpp | 1 + libsolidity/ast/ASTJsonImporter.cpp | 3 +- libsolidity/parsing/Parser.cpp | 3 +- .../ASTJSON/enum_value_natspec.json | 56 +++++++++++++++++++ .../ASTJSON/enum_value_natspec.sol | 11 ++++ .../ASTJSON/enum_value_natspec_parseOnly.json | 50 +++++++++++++++++ .../{enum_no_docs.sol => enum.sol} | 0 .../{docstring_enum.sol => enum_value.sol} | 10 ++-- 10 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 test/libsolidity/ASTJSON/enum_value_natspec.json create mode 100644 test/libsolidity/ASTJSON/enum_value_natspec.sol create mode 100644 test/libsolidity/ASTJSON/enum_value_natspec_parseOnly.json rename test/libsolidity/natspecJSON/{enum_no_docs.sol => enum.sol} (100%) rename test/libsolidity/natspecJSON/{docstring_enum.sol => enum_value.sol} (55%) diff --git a/Changelog.md b/Changelog.md index 7efefca02..525ed2d9e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: +* NatSpec: Capture Natspec documentation of `enum` values in the AST. Bugfixes: diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 0121bef33..9c7cbbded 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -823,11 +823,19 @@ class EnumDefinition: public Declaration, public StructurallyDocumented, public /** * Declaration of an Enum Value */ -class EnumValue: public Declaration +class EnumValue: public Declaration, public StructurallyDocumented { public: - EnumValue(int64_t _id, SourceLocation const& _location, ASTPointer const& _name): - Declaration(_id, _location, _name, _location) {} + EnumValue( + int64_t _id, + SourceLocation const& _location, + ASTPointer const& _name, + ASTPointer _documentation + ): + Declaration(_id, _location, _name, _location), + StructurallyDocumented(std::move(_documentation)) + { + } void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 42627b5f7..4eaa55871 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -430,6 +430,7 @@ bool ASTJsonExporter::visit(EnumValue const& _node) setJsonNode(_node, "EnumValue", { std::make_pair("name", _node.name()), std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), + std::make_pair("documentation", toJson(_node.documentation().get())), }); return false; } diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index d6cd7f438..2d2b66fd8 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -489,7 +489,8 @@ ASTPointer ASTJsonImporter::createEnumValue(Json const& _node) { return createASTNode( _node, - memberAsASTString(_node, "name") + memberAsASTString(_node, "name"), + _node.contains("documentation") && !_node["documentation"].is_null() ? createDocumentation(member(_node, "documentation")) : nullptr ); } diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 08a319b5b..8889e6508 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -824,8 +824,9 @@ ASTPointer Parser::parseEnumValue() { RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); + ASTPointer documentation = parseStructuredDocumentation(); nodeFactory.markEndPosition(); - return nodeFactory.createNode(expectIdentifierToken()); + return nodeFactory.createNode(expectIdentifierToken(), documentation); } ASTPointer Parser::parseEnumDefinition() diff --git a/test/libsolidity/ASTJSON/enum_value_natspec.json b/test/libsolidity/ASTJSON/enum_value_natspec.json new file mode 100644 index 000000000..e468bb987 --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_value_natspec.json @@ -0,0 +1,56 @@ +{ + "absolutePath": "a", + "exportedSymbols": { + "Color": [ + 6 + ] + }, + "id": 7, + "nodeType": "SourceUnit", + "nodes": [ + { + "canonicalName": "Color", + "id": 6, + "members": [ + { + "id": 1, + "name": "Red", + "nameLocation": "17:3:1", + "nodeType": "EnumValue", + "src": "17:3:1" + }, + { + "documentation": { + "id": 2, + "nodeType": "StructuredDocumentation", + "src": "26:57:1", + "text": "@notice example of notice\n @dev example of dev" + }, + "id": 3, + "name": "Green", + "nameLocation": "88:5:1", + "nodeType": "EnumValue", + "src": "88:5:1" + }, + { + "documentation": { + "id": 4, + "nodeType": "StructuredDocumentation", + "src": "99:23:1", + "text": "@dev example of dev" + }, + "id": 5, + "name": "Blue", + "nameLocation": "127:4:1", + "nodeType": "EnumValue", + "src": "127:4:1" + } + ], + "name": "Color", + "nameLocation": "5:5:1", + "nodeType": "EnumDefinition", + "src": "0:164:1" + } + ], + "src": "0:165:1" +} diff --git a/test/libsolidity/ASTJSON/enum_value_natspec.sol b/test/libsolidity/ASTJSON/enum_value_natspec.sol new file mode 100644 index 000000000..e5209d644 --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_value_natspec.sol @@ -0,0 +1,11 @@ +enum Color { + Red, + /// @notice example of notice + /// @dev example of dev + Green, + /// @dev example of dev + Blue + /// @dev beyond last value +} + +// ---- diff --git a/test/libsolidity/ASTJSON/enum_value_natspec_parseOnly.json b/test/libsolidity/ASTJSON/enum_value_natspec_parseOnly.json new file mode 100644 index 000000000..ff3d7c756 --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_value_natspec_parseOnly.json @@ -0,0 +1,50 @@ +{ + "absolutePath": "a", + "id": 7, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 6, + "members": [ + { + "id": 1, + "name": "Red", + "nameLocation": "17:3:1", + "nodeType": "EnumValue", + "src": "17:3:1" + }, + { + "documentation": { + "id": 2, + "nodeType": "StructuredDocumentation", + "src": "26:57:1", + "text": "@notice example of notice\n @dev example of dev" + }, + "id": 3, + "name": "Green", + "nameLocation": "88:5:1", + "nodeType": "EnumValue", + "src": "88:5:1" + }, + { + "documentation": { + "id": 4, + "nodeType": "StructuredDocumentation", + "src": "99:23:1", + "text": "@dev example of dev" + }, + "id": 5, + "name": "Blue", + "nameLocation": "127:4:1", + "nodeType": "EnumValue", + "src": "127:4:1" + } + ], + "name": "Color", + "nameLocation": "5:5:1", + "nodeType": "EnumDefinition", + "src": "0:164:1" + } + ], + "src": "0:165:1" +} diff --git a/test/libsolidity/natspecJSON/enum_no_docs.sol b/test/libsolidity/natspecJSON/enum.sol similarity index 100% rename from test/libsolidity/natspecJSON/enum_no_docs.sol rename to test/libsolidity/natspecJSON/enum.sol diff --git a/test/libsolidity/natspecJSON/docstring_enum.sol b/test/libsolidity/natspecJSON/enum_value.sol similarity index 55% rename from test/libsolidity/natspecJSON/docstring_enum.sol rename to test/libsolidity/natspecJSON/enum_value.sol index d5ace6b14..ccb3233a5 100644 --- a/test/libsolidity/natspecJSON/docstring_enum.sol +++ b/test/libsolidity/natspecJSON/enum_value.sol @@ -1,11 +1,13 @@ contract C { - /// @title example of title - /// @author example of author - /// @notice example of notice - /// @dev example of dev enum Color { + /// @custom red color Red, + /// @title example of title + /// @author example of author + /// @notice example of notice + /// @dev example of dev Green + /// @notice beyond last value } } // ---- From c4b454ac53ad6409cee612ddaf38d467b50a6299 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 2 Apr 2025 13:16:18 +0200 Subject: [PATCH 0809/1340] Docs --- docs/natspec-format.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst index 2f0d1d6b4..40da3e5e3 100644 --- a/docs/natspec-format.rst +++ b/docs/natspec-format.rst @@ -37,7 +37,7 @@ Documentation Example ===================== Documentation is inserted above each ``contract``, ``interface``, ``library``, -``function``, and ``event`` using the Doxygen notation format. +``function``, ``enum``, ``enum`` value and ``event`` using the Doxygen notation format. A ``public`` state variable is equivalent to a ``function`` for the purposes of NatSpec. @@ -116,13 +116,13 @@ in the same way as if it were tagged with ``@notice``. =============== ====================================================================================== ============================= Tag Context =============== ====================================================================================== ============================= -``@title`` A title that should describe the contract/interface contract, library, interface, struct, enum -``@author`` The name of the author contract, library, interface, struct, enum -``@notice`` Explain to an end user what this does contract, library, interface, function, public state variable, event, struct, enum, error -``@dev`` Explain to a developer any extra details contract, library, interface, function, state variable, event, struct, enum, error -``@param`` Documents a parameter just like in Doxygen (must be followed by parameter name) function, event, error -``@return`` Documents the return variables of a contract's function function, public state variable -``@inheritdoc`` Copies all missing tags from the base function (must be followed by the contract name) function, public state variable +``@title`` A title that should describe the contract/interface contract, library, interface, struct, enum, enum values +``@author`` The name of the author contract, library, interface, struct, enum, enum values +``@notice`` Explain to an end user what this does contract, library, interface, function, public state variable, event, struct, enum, enum values error +``@dev`` Explain to a developer any extra details contract, library, interface, function, state variable, event, struct, enum, enum values, error +``@param`` Documents a parameter just like in Doxygen (must be followed by parameter name) function, event, enum values, error +``@return`` Documents the return variables of a contract's function function, enum, enum values, public state variable +``@inheritdoc`` Copies all missing tags from the base function (must be followed by the contract name) function, enum, enum values, public state variable ``@custom:...`` Custom tag, semantics is application-defined everywhere =============== ====================================================================================== ============================= From c6084281e3e7ff0b969235acab44eb409f93f273 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 28 Mar 2025 09:49:35 +0100 Subject: [PATCH 0810/1340] SMTChecker: Refactor processing invariants from the solver Instead of extracting invariants as a single expression containing all predicates and their definitions, we represent invariants as a map from predicate names to the corresponding definitions. Additionally, we need to remember formal arguments of the predicate so we can apply substitutions to the definitions properly. I believe the previous representation was an artifact of how Z3 returns CHC model through its API. The new representation is more fitting for models extracted from SMT-LIB. --- libsmtutil/CHCSmtLib2Interface.cpp | 27 +++++------ libsmtutil/CHCSmtLib2Interface.h | 4 +- libsmtutil/CHCSolverInterface.h | 12 ++++- libsolidity/formal/CHC.cpp | 50 +++++++------------- libsolidity/formal/Predicate.cpp | 30 ++++++------ libsolidity/formal/Predicate.h | 4 +- libsolidity/formal/Z3CHCSmtLib2Interface.cpp | 15 +++--- 7 files changed, 65 insertions(+), 77 deletions(-) diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index 04cbad1ad..b81eeb4fe 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -102,21 +102,18 @@ CHCSolverInterface::QueryResult CHCSmtLib2Interface::query(Expression const& _bl // However, with CHC solvers, the meaning is flipped, UNSAT -> UNSAFE and SAT -> SAFE. // So we have to flip the answer. if (boost::starts_with(response, "sat")) - { - auto maybeInvariants = invariantsFromSolverResponse(response); - return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; - } - else if (boost::starts_with(response, "unsat")) + return {CheckResult::UNSATISFIABLE, invariantsFromSolverResponse(response), {}}; + if (boost::starts_with(response, "unsat")) result = CheckResult::SATISFIABLE; else if (boost::starts_with(response, "unknown")) result = CheckResult::UNKNOWN; else result = CheckResult::ERROR; - return {result, Expression(true), {}}; + return {result, {}, {}}; } catch(smtutil::SMTSolverInteractionError const&) { - return {CheckResult::ERROR, Expression(true), {}}; + return {CheckResult::ERROR, {}, {}}; } } @@ -416,7 +413,7 @@ smtutil::Expression CHCSmtLib2Interface::ScopedParser::toSMTUtilExpression(SMTLi } -std::optional CHCSmtLib2Interface::invariantsFromSolverResponse(std::string const& _response) const +CHCSmtLib2Interface::Invariants CHCSmtLib2Interface::invariantsFromSolverResponse(std::string const& _response) const { std::stringstream ss(_response); std::string answer; @@ -438,7 +435,7 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp smtSolverInteractionRequire(parser.isEOF(), "Error during parsing CHC model"); smtSolverInteractionRequire(!parsedOutput.empty(), "Error during parsing CHC model"); auto& commands = parsedOutput.size() == 1 ? asSubExpressions(parsedOutput[0]) : parsedOutput; - std::vector definitions; + Invariants definitions; for (auto& command: commands) { auto& args = asSubExpressions(command); @@ -456,7 +453,7 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp inlineLetExpressions(interpretation); ScopedParser scopedParser(m_context); auto const& formalArguments = asSubExpressions(args[2]); - std::vector predicateArgs; + std::vector predicateArguments; for (auto const& formalArgument: formalArguments) { smtSolverInteractionRequire(!isAtom(formalArgument), "Invalid format of CHC model"); @@ -465,7 +462,7 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp smtSolverInteractionRequire(isAtom(nameSortPair[0]), "Invalid format of CHC model"); SortPointer varSort = scopedParser.toSort(nameSortPair[1]); scopedParser.addVariableDeclaration(asAtom(nameSortPair[0]), varSort); - predicateArgs.push_back(scopedParser.toSMTUtilExpression(nameSortPair[0])); + predicateArguments.push_back(asAtom(nameSortPair[0])); } auto parsedInterpretation = scopedParser.toSMTUtilExpression(interpretation); @@ -476,11 +473,11 @@ std::optional CHCSmtLib2Interface::invariantsFromSolverResp return first.name < second.name; }); - Expression predicate(asAtom(args[1]), predicateArgs, SortProvider::boolSort); - // FIXME: Why do we need to represent the predicate as Expression? - definitions.push_back(predicate == parsedInterpretation); + std::string const& predicateName = asAtom(args[1]); + smtSolverInteractionRequire(!definitions.contains(predicateName), "Predicates must be unique"); + definitions.emplace(predicateName, InvariantInfo{parsedInterpretation, predicateArguments}); } - return Expression::mkAnd(std::move(definitions)); + return definitions; } namespace diff --git a/libsmtutil/CHCSmtLib2Interface.h b/libsmtutil/CHCSmtLib2Interface.h index 0f8fc061d..5b45f1638 100644 --- a/libsmtutil/CHCSmtLib2Interface.h +++ b/libsmtutil/CHCSmtLib2Interface.h @@ -94,8 +94,8 @@ class CHCSmtLib2Interface: public CHCSolverInterface /// Communicates with the solver via the callback. Throws SMTSolverError on error. virtual std::string querySolver(std::string const& _input); - /// Translates CHC solver response with a model to our representation of invariants. Returns None on error. - std::optional invariantsFromSolverResponse(std::string const& _response) const; + /// Translates CHC solver response with a model to our representation of invariants. + Invariants invariantsFromSolverResponse(std::string const& _response) const; std::set collectVariableNames(Expression const& _expr) const; diff --git a/libsmtutil/CHCSolverInterface.h b/libsmtutil/CHCSolverInterface.h index 8feb18aa8..641d54cfb 100644 --- a/libsmtutil/CHCSolverInterface.h +++ b/libsmtutil/CHCSolverInterface.h @@ -25,6 +25,7 @@ #include #include +#include #include namespace solidity::smtutil @@ -49,10 +50,19 @@ class CHCSolverInterface : public SolverInterface std::map> edges; }; + struct InvariantInfo + { + /// Predicate definition as SMT expression + Expression expression; + /// Names of the formal arguments of the predicate definition + std::vector variableNames; + }; + /// Maps predicate to its definition as given by the solver and the formal arguments of the predicate + using Invariants = std::unordered_map; struct QueryResult { CheckResult answer; - Expression invariant; + Invariants invariants; CexGraph cex; }; /// Takes a function application _expr and checks for reachability. diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index 67878084f..fea13fde2 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -34,9 +34,8 @@ #include #include -#include - #include +#include #include #include #include @@ -1895,7 +1894,7 @@ CHCSolverInterface::QueryResult CHC::query(smtutil::Expression const& _query, la 2339_error, "CHC: Requested query:\n" + smtLibCode ); - return {.answer = CheckResult::UNKNOWN, .invariant = smtutil::Expression(true), .cex = {}}; + return {.answer = CheckResult::UNKNOWN, .invariants = {}, .cex = {}}; } auto result = m_interface->query(_query); switch (result.answer) @@ -2137,7 +2136,7 @@ void CHC::checkVerificationTargets() namespace { std::map> collectInvariants( - smtutil::Expression const& _proof, + CHCSmtLib2Interface::Invariants const& _invariants, std::set const& _predicates, ModelCheckerInvariants const& _invariantsSetting ) @@ -2148,38 +2147,23 @@ std::map> collectInvariants( if (_invariantsSetting.has(InvariantType::Reentrancy)) targets.insert("nondet_interface_"); - std::map> equalities; - // Collect equalities where one of the sides is a predicate we're interested in. - util::BreadthFirstSearch{{&_proof}}.run([&](auto&& _expr, auto&& _addChild) { - if (_expr->name == "=") - for (auto const& t: targets) - { - auto arg0 = _expr->arguments.at(0); - auto arg1 = _expr->arguments.at(1); - if (boost::algorithm::starts_with(arg0.name, t)) - equalities.insert({arg0.name, {arg0, std::move(arg1)}}); - else if (boost::algorithm::starts_with(arg1.name, t)) - equalities.insert({arg1.name, {arg1, std::move(arg0)}}); - } - for (auto const& arg: _expr->arguments) - _addChild(&arg); - }); - std::map> invariants; - for (auto pred: _predicates) + for (auto const* pred: _predicates) { - auto predName = pred->functor().name; - if (!equalities.count(predName)) + smtAssert(pred); + auto const& predName = pred->functor().name; + if (!_invariants.contains(predName)) + continue; + if (ranges::none_of(targets, [&](auto const& _target) { return predName.starts_with(_target); })) continue; - solAssert(pred->contextContract(), ""); + smtAssert(pred->contextContract()); - auto const& [predExpr, invExpr] = equalities.at(predName); + auto const& [definition, formalArguments] = _invariants.at(predName); - static std::set const ignore{"true", "false"}; - auto r = substitute(invExpr, pred->expressionSubstitution(predExpr)); + auto r = substitute(definition, pred->expressionSubstitution(formalArguments)); // No point in reporting true/false as invariants. - if (!ignore.count(r.name)) + if (r.name != "true" && r.name != "false") invariants[pred].insert(toSolidityStr(r)); } return invariants; @@ -2205,7 +2189,7 @@ void CHC::checkAndReportTarget( placeholder.constraints && placeholder.errorExpression == _target.errorId ); auto const& location = _target.errorNode->location(); - auto [result, invariant, model] = query(error(), location); + auto [result, invariants, model] = query(error(), location); if (result == CheckResult::UNSATISFIABLE) { m_safeTargets[_target.errorNode].insert(_target); @@ -2214,9 +2198,9 @@ void CHC::checkAndReportTarget( predicates.insert(pred); for (auto const* pred: m_nondetInterfaces | ranges::views::values) predicates.insert(pred); - std::map> invariants = collectInvariants(invariant, predicates, m_settings.invariants); - for (auto pred: invariants | ranges::views::keys) - m_invariants[pred] += std::move(invariants.at(pred)); + std::map> invariantStrings = collectInvariants(invariants, predicates, m_settings.invariants); + for (auto pred: invariantStrings | ranges::views::keys) + m_invariants[pred] += std::move(invariantStrings.at(pred)); } else if (result == CheckResult::SATISFIABLE) { diff --git a/libsolidity/formal/Predicate.cpp b/libsolidity/formal/Predicate.cpp index 4b7ca8edb..66d8c2405 100644 --- a/libsolidity/formal/Predicate.cpp +++ b/libsolidity/formal/Predicate.cpp @@ -27,12 +27,10 @@ #include #include -#include #include #include -using boost::algorithm::starts_with; using namespace solidity; using namespace solidity::smtutil; using namespace solidity::frontend; @@ -434,15 +432,15 @@ std::pair>, std::vector Predicate::expressionSubstitution(smtutil::Expression const& _predExpr) const +std::map Predicate::expressionSubstitution(std::vector const& _predArgs) const { std::map subst; std::string predName = functor().name; - solAssert(contextContract(), ""); + smtAssert(contextContract()); auto const& stateVars = SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*contextContract()); - auto nArgs = _predExpr.arguments.size(); + auto const nArgs = _predArgs.size(); // The signature of an interface predicate is // interface(this, abiFunctions, (optionally) bytesConcatFunctions, cryptoFunctions, blockchainState, stateVariables). @@ -450,12 +448,13 @@ std::map Predicate::expressionSubstitution(smtutil::Ex // invariant over its state, for example `x <= 0`. if (isInterface()) { + smtAssert(nArgs > 0); size_t shift = txValuesIndex(); - solAssert(starts_with(predName, "interface"), ""); - subst[_predExpr.arguments.at(0).name] = "address(this)"; - solAssert(nArgs == stateVars.size() + shift, ""); + smtAssert(predName.starts_with("interface")); + subst[_predArgs.at(0)] = "address(this)"; + smtAssert(nArgs == stateVars.size() + shift); for (size_t i = nArgs - stateVars.size(); i < nArgs; ++i) - subst[_predExpr.arguments.at(i).name] = stateVars.at(i - shift)->name(); + subst[_predArgs.at(i)] = stateVars.at(i - shift)->name(); } // The signature of a nondet interface predicate is // nondet_interface(error, this, abiFunctions, (optionally) bytesConcatFunctions, cryptoFunctions, blockchainState, stateVariables, blockchainState', stateVariables'). @@ -466,14 +465,15 @@ std::map Predicate::expressionSubstitution(smtutil::Ex // `(x <= 0) => (x' <= 100)`. else if (isNondetInterface()) { - solAssert(starts_with(predName, "nondet_interface"), ""); - subst[_predExpr.arguments.at(0).name] = ""; - subst[_predExpr.arguments.at(1).name] = "address(this)"; - solAssert(nArgs == stateVars.size() * 2 + firstArgIndex(), ""); + smtAssert(nArgs > 1); + smtAssert(predName.starts_with("nondet_interface")); + subst[_predArgs.at(0)] = ""; + subst[_predArgs.at(1)] = "address(this)"; + smtAssert(nArgs == stateVars.size() * 2 + firstArgIndex()); for (size_t i = nArgs - stateVars.size(), s = 0; i < nArgs; ++i, ++s) - subst[_predExpr.arguments.at(i).name] = stateVars.at(s)->name() + "'"; + subst[_predArgs.at(i)] = stateVars.at(s)->name() + "'"; for (size_t i = nArgs - (stateVars.size() * 2 + 1), s = 0; i < nArgs - (stateVars.size() + 1); ++i, ++s) - subst[_predExpr.arguments.at(i).name] = stateVars.at(s)->name(); + subst[_predArgs.at(i)] = stateVars.at(s)->name(); } return subst; diff --git a/libsolidity/formal/Predicate.h b/libsolidity/formal/Predicate.h index f389ab822..7e4ba0f00 100644 --- a/libsolidity/formal/Predicate.h +++ b/libsolidity/formal/Predicate.h @@ -179,9 +179,9 @@ class Predicate /// @returns the values of the local variables used by this predicate. std::pair>, std::vector> localVariableValues(std::vector const& _args) const; - /// @returns a substitution map from the arguments of _predExpr + /// @returns a substitution map from the predicate arguments @p _predArgs /// to a Solidity-like expression. - std::map expressionSubstitution(smtutil::Expression const& _predExprs) const; + std::map expressionSubstitution(std::vector const& _predArgs) const; private: /// Recursively fills _array from _expr. diff --git a/libsolidity/formal/Z3CHCSmtLib2Interface.cpp b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp index 2ceecfcf9..da6f14d96 100644 --- a/libsolidity/formal/Z3CHCSmtLib2Interface.cpp +++ b/libsolidity/formal/Z3CHCSmtLib2Interface.cpp @@ -90,26 +90,23 @@ CHCSolverInterface::QueryResult Z3CHCSmtLib2Interface::query(smtutil::Expression #endif setupSmtCallback(true); if (!boost::starts_with(response, "unsat")) - return {CheckResult::SATISFIABLE, Expression(true), {}}; - return {CheckResult::SATISFIABLE, Expression(true), graphFromZ3Answer(response)}; + return {CheckResult::SATISFIABLE, {}, {}}; + return {CheckResult::SATISFIABLE, {}, graphFromZ3Answer(response)}; } CheckResult result; if (boost::starts_with(response, "sat")) - { - auto maybeInvariants = invariantsFromSolverResponse(response); - return {CheckResult::UNSATISFIABLE, maybeInvariants.value_or(Expression(true)), {}}; - } - else if (boost::starts_with(response, "unknown")) + return {CheckResult::UNSATISFIABLE, invariantsFromSolverResponse(response), {}}; + if (boost::starts_with(response, "unknown")) result = CheckResult::UNKNOWN; else result = CheckResult::ERROR; - return {result, Expression(true), {}}; + return {result, {}, {}}; } catch(smtutil::SMTSolverInteractionError const&) { - return {CheckResult::ERROR, Expression(true), {}}; + return {CheckResult::ERROR, {}, {}}; } } From dbd5521a697eae275afeb5d8a0b256670238f5b9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 4 Apr 2025 07:50:21 +0200 Subject: [PATCH 0811/1340] remove install of obsolete jsoncpp --- .circleci/osx_install_dependencies.sh | 3 --- scripts/install_obsolete_jsoncpp_1_7_4.sh | 24 ----------------------- 2 files changed, 27 deletions(-) delete mode 100755 scripts/install_obsolete_jsoncpp_1_7_4.sh diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index e7a0b9ddf..6e0c859f9 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -59,9 +59,6 @@ then brew install openjdk@11 brew install unzip - # writing to /usr/local/lib need administrative privileges. - sudo ./scripts/install_obsolete_jsoncpp_1_7_4.sh - # boost boost_version="1.84.0" boost_package="boost_${boost_version//./_}.tar.bz2" diff --git a/scripts/install_obsolete_jsoncpp_1_7_4.sh b/scripts/install_obsolete_jsoncpp_1_7_4.sh deleted file mode 100755 index f9de0245d..000000000 --- a/scripts/install_obsolete_jsoncpp_1_7_4.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -set -eu - -TEMPDIR=$(mktemp -d) -( - cd "$TEMPDIR" - jsoncpp_version="1.7.4" - jsoncpp_package="jsoncpp-${jsoncpp_version}.tar.gz" - jsoncpp_sha256=10dcd0677e80727e572a1e462193e51a5fde3e023b99e144b2ee1a469835f769 - wget -O "$jsoncpp_package" https://github.com/open-source-parsers/jsoncpp/archive/${jsoncpp_version}.tar.gz - if ! [ "$(sha256sum "$jsoncpp_package")" = "${jsoncpp_sha256} ${jsoncpp_package}" ] - then - >&2 echo "ERROR: Downloaded jsoncpp source package has wrong checksum." - exit 1 - fi - tar xvzf "$jsoncpp_package" - cd "jsoncpp-${jsoncpp_version}" - mkdir -p build - cd build - cmake -DCMAKE_OSX_ARCHITECTURES:STRING="x86_64;arm64" -DARCHIVE_INSTALL_DIR=. -G "Unix Makefiles" .. - make - make install -) -rm -r "$TEMPDIR" From f323bd4de27b635dab1ba249832a1ec0b054cf4e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 4 Apr 2025 09:07:12 +0200 Subject: [PATCH 0812/1340] cmake: use boost include dirs and version in status message --- cmake/EthDependencies.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 87a5e1b5e..56d90bb47 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -49,8 +49,7 @@ if (NOT TARGET Boost::boost) # header only target add_library(Boost::boost INTERFACE IMPORTED) set_property(TARGET Boost::boost APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS}) endif() -get_property(LOCATION TARGET Boost::boost PROPERTY INTERFACE_INCLUDE_DIRECTORIES) -message(STATUS "Found Boost headers in ${LOCATION}") +message(STATUS "Found Boost ${Boost_VERSION} headers in ${Boost_INCLUDE_DIRS}") foreach (BOOST_COMPONENT IN LISTS BOOST_COMPONENTS) if (NOT TARGET Boost::${BOOST_COMPONENT}) From e6d56997aba55b2805a288b671d14651bd140270 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 4 Apr 2025 09:17:23 +0200 Subject: [PATCH 0813/1340] set CMP0167 to OLD behavior for boost versions < 1.70 --- cmake/EthDependencies.cmake | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 56d90bb47..f79140dd2 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -31,6 +31,10 @@ endif() set(BOOST_COMPONENTS "filesystem;unit_test_framework;program_options;system") +# CMake >= 3.30 should not use the vendored boost +if(POLICY CMP0167) + cmake_policy(SET CMP0167 NEW) +endif() if (WIN32) # Boost 1.77 fixes a bug that causes crashes on Windows for some relative paths in --allow-paths. # See https://github.com/boostorg/filesystem/issues/201 @@ -38,7 +42,16 @@ if (WIN32) else() # Boost 1.65 is the first to also provide boost::get for rvalue-references (#5787). # Boost 1.67 moved container_hash into is own module. - find_package(Boost 1.67.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) + # Boost 1.70 comes with its own BoostConfig.cmake and is the new (non-deprecated) behavior + find_package(Boost 1.70.0 QUIET COMPONENTS ${BOOST_COMPONENTS}) + if (NOT ${Boost_FOUND}) + # If the boost version is < 1.70.0, there is no boost config delivered with it, revert to old behavior + # todo drop this once cmake minimum version >= 3.30 is reached + if(POLICY CMP0167) + cmake_policy(SET CMP0167 OLD) + endif() + find_package(Boost 1.67.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) + endif() endif() # If cmake is older than boost and boost is older than 1.70, From 4c23d04b53cba7bfda8ddf19ead131e88529e003 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 7 Apr 2025 16:00:49 +0200 Subject: [PATCH 0814/1340] Disable pedantic compilation for CMake 4.0.0 and AppleClang 15.0 --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b39878f2..29bf2b0ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,14 @@ endif() find_package(Threads) +if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin" AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + if (CMAKE_VERSION VERSION_EQUAL "4.0.0" AND CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "15.0.0.15000040") + # for Apple clang 15 under cmake 4.0.0, disable pedantic warnings explicitly as it fails to treat boost properly as + # system library, warnings propagate + set(PEDANTIC OFF) + endif() +endif() + if(NOT PEDANTIC) message(WARNING "-- Pedantic build flags turned off. Warnings will not make compilation fail. This is NOT recommended in development builds.") endif() From 2cd97dc2b248edfac74241036cf7327d035bae57 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 8 Apr 2025 11:34:38 +0200 Subject: [PATCH 0815/1340] Use pre-release version of sphinx-a4doc for python 3.13 --- docs/requirements.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index b1b21a869..e0c87915b 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -4,7 +4,9 @@ sphinx_rtd_theme>=0.5.2 pygments-lexer-solidity>=0.7.0 -sphinx-a4doc>=1.6.0 +sphinx-a4doc>=1.6.0; python_version < '3.13' +# todo remove this once there is a version > 1.6.0 +sphinx-a4doc @ git+https://github.com/taminomara/sphinx-a4doc@f63d3b2; python_version >= '3.13' # Sphinx 2.1.0 is the oldest version that accepts a lexer class in add_lexer() sphinx>=2.1.0, <6.0 From 0a6cce58a0e3814db15844c53e05e384e00088fd Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 8 Apr 2025 11:34:59 +0200 Subject: [PATCH 0816/1340] relax sphinx version range to [2.1, 9) --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index e0c87915b..8e058b629 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -9,4 +9,4 @@ sphinx-a4doc>=1.6.0; python_version < '3.13' sphinx-a4doc @ git+https://github.com/taminomara/sphinx-a4doc@f63d3b2; python_version >= '3.13' # Sphinx 2.1.0 is the oldest version that accepts a lexer class in add_lexer() -sphinx>=2.1.0, <6.0 +sphinx>=2.1.0, <9.0 From 971ac4c9ae79c4b7d5d76d23df1e1c9cd75b61ab Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 8 Apr 2025 11:46:21 +0200 Subject: [PATCH 0817/1340] require rtd theme < 3.0.0 --- docs/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 8e058b629..f4c1aae61 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,7 +1,8 @@ # Older versions of sphinx-rtd-theme do not work with never docutils but have a bug in the dependency # which could result in it being installed anyway and the style (especially bullet points) being broken. # See https://github.com/readthedocs/sphinx_rtd_theme/issues/1115 -sphinx_rtd_theme>=0.5.2 +# theme >=3.0.0 removes the display_version option in favor of version_selector and language_selector +sphinx_rtd_theme>=0.5.2, <3.0.0 pygments-lexer-solidity>=0.7.0 sphinx-a4doc>=1.6.0; python_version < '3.13' From 502ebaa8f879e8c5b5440a984030cf30f48c6f8a Mon Sep 17 00:00:00 2001 From: Michael Cho Date: Mon, 31 Mar 2025 16:06:00 -0400 Subject: [PATCH 0818/1340] Add support for upcoming Boost 1.88.0 Boost.Process will make v2 the default in Boost 1.88.0[^1] which breaks compilation of prior code. For a simple fix, this commit updates to use the newer paths for v1 until the code is updated to use v2 API. [^1]: https://github.com/boostorg/process/commit/2ccd97cd48c5468b0609a488b59253efaa381711 --- libsolidity/formal/ModelChecker.cpp | 6 ++++++ libsolidity/interface/SMTSolverCommand.cpp | 9 +++++++++ test/libyul/ControlFlowGraphTest.cpp | 8 ++++++++ test/libyul/SSAControlFlowGraphTest.cpp | 8 ++++++++ test/libyul/StackLayoutGeneratorTest.cpp | 8 ++++++++ 5 files changed, 39 insertions(+) diff --git a/libsolidity/formal/ModelChecker.cpp b/libsolidity/formal/ModelChecker.cpp index 04d96f067..2d5241412 100644 --- a/libsolidity/formal/ModelChecker.cpp +++ b/libsolidity/formal/ModelChecker.cpp @@ -18,7 +18,13 @@ #include +#include +#if (BOOST_VERSION < 108800) #include +#else +#define BOOST_PROCESS_VERSION 1 +#include +#endif #include #include diff --git a/libsolidity/interface/SMTSolverCommand.cpp b/libsolidity/interface/SMTSolverCommand.cpp index 66adfd0c5..e6e0ded62 100644 --- a/libsolidity/interface/SMTSolverCommand.cpp +++ b/libsolidity/interface/SMTSolverCommand.cpp @@ -20,7 +20,16 @@ #include #include +#include +#if (BOOST_VERSION < 108800) #include +#else +#define BOOST_PROCESS_VERSION 1 +#include +#include +#include +#include +#endif namespace solidity::frontend { diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index c0ab37956..594b2f6c9 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -29,7 +29,15 @@ #include #ifdef ISOLTEST +#include +#if (BOOST_VERSION < 108800) #include +#else +#define BOOST_PROCESS_VERSION 1 +#include +#include +#include +#endif #endif using namespace solidity; diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/SSAControlFlowGraphTest.cpp index c23a2ca5f..d2acee7bc 100644 --- a/test/libyul/SSAControlFlowGraphTest.cpp +++ b/test/libyul/SSAControlFlowGraphTest.cpp @@ -28,7 +28,15 @@ #include #ifdef ISOLTEST +#include +#if (BOOST_VERSION < 108800) #include +#else +#define BOOST_PROCESS_VERSION 1 +#include +#include +#include +#endif #endif using namespace solidity; diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index eb34eabb1..0c85b1a7b 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -33,7 +33,15 @@ #include #ifdef ISOLTEST +#include +#if (BOOST_VERSION < 108800) #include +#else +#define BOOST_PROCESS_VERSION 1 +#include +#include +#include +#endif #endif using namespace solidity; From 334b7685525367fe8bbe8781ec260fef0ee44f7b Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 12 Mar 2025 12:28:40 +0100 Subject: [PATCH 0819/1340] Remove Z3 from ppa scripts and add ubunutu plucky. --- scripts/deps-ppa/static_z3.sh | 267 ---------------------------------- scripts/release_ppa.sh | 11 +- 2 files changed, 4 insertions(+), 274 deletions(-) delete mode 100755 scripts/deps-ppa/static_z3.sh diff --git a/scripts/deps-ppa/static_z3.sh b/scripts/deps-ppa/static_z3.sh deleted file mode 100755 index 140c40c6a..000000000 --- a/scripts/deps-ppa/static_z3.sh +++ /dev/null @@ -1,267 +0,0 @@ -#!/usr/bin/env bash -############################################################################## -## This is used to package .deb packages and upload them to the launchpad -## ppa servers for building. -## -## It will clone the Z3 git from github on the specified version tag, -## create a source archive and push it to the ubuntu ppa servers. -## -## This requires the following entries in /etc/dput.cf: -## -## [cpp-build-deps] -## fqdn = ppa.launchpad.net -## method = ftp -## incoming = ~ethereum/cpp-build-deps -## login = anonymous -## -## To interact with launchpad, you need to set the variables $LAUNCHPAD_EMAIL -## and $LAUNCHPAD_KEYID in the file .release_ppa_auth in the root directory of -## the project to your launchpad email and pgp keyid. -## This could for example look like this: -## -## LAUNCHPAD_EMAIL=your-launchpad-email@ethereum.org -## LAUNCHPAD_KEYID=123ABCFFFFFFFF -## -############################################################################## - -set -e - -packagename=z3-static -version="$1" - -REPO_ROOT="$(dirname "$0")/../.." - -# shellcheck source=/dev/null -source "${REPO_ROOT}/scripts/common.sh" - -[[ $version != "" ]] || fail "Usage: $0 " - -sourcePPAConfig - -# Sanity check -checkDputEntries "\[cpp-build-deps\]" - -DISTRIBUTIONS="jammy noble oracular" - -for distribution in $DISTRIBUTIONS -do -cd /tmp/ -rm -rf "$distribution" -mkdir "$distribution" -cd "$distribution" - -pparepo=cpp-build-deps -ppafilesurl=https://launchpad.net/~ethereum/+archive/ubuntu/${pparepo}/+files - -# Fetch source -git clone --branch "z3-${version}" https://github.com/Z3Prover/z3.git -cd z3 - -debversion="${version}" - -CMAKE_OPTIONS="-DZ3_BUILD_LIBZ3_SHARED=OFF -DCMAKE_BUILD_TYPE=Release" - -# gzip will create different tars all the time and we are not allowed -# to upload the same file twice with different contents, so we only -# create it once. -if [ ! -e "/tmp/${packagename}_${debversion}.orig.tar.gz" ] -then - tar --exclude .git -czf "/tmp/${packagename}_${debversion}.orig.tar.gz" . -fi -cp "/tmp/${packagename}_${debversion}.orig.tar.gz" ../ - -# Create debian package information - -mkdir debian -echo 9 > debian/compat -# TODO: the Z3 packages have different build dependencies -cat < debian/control -Source: z3-static -Section: science -Priority: extra -Maintainer: Daniel Kirchner -Build-Depends: debhelper (>= 9.0.0), - cmake, - g++ (>= 5.0), - git, - libgmp-dev, - dh-python, - python3 -Standards-Version: 3.9.6 -Homepage: https://github.com/Z3Prover/z3 -Vcs-Git: https://github.com/Z3Prover/z3.git -Vcs-Browser: https://github.com/Z3Prover/z3 - -Package: z3-static -Architecture: any -Breaks: z3 -Replaces: z3 -Depends: \${misc:Depends}, \${shlibs:Depends} -Description: theorem prover from Microsoft Research - Z3 is a state-of-the art theorem prover from Microsoft Research. It can be - used to check the satisfiability of logical formulas over one or more - theories. Z3 offers a compelling match for software analysis and verification - tools, since several common software constructs map directly into supported - theories. - . - The Z3 input format is an extension of the one defined by the SMT-LIB 2.0 - standard. - - -Package: libz3-static-dev -Section: libdevel -Architecture: any-amd64 -Breaks: libz3-dev -Replaces: libz3-dev -Multi-Arch: same -Depends: \${shlibs:Depends}, \${misc:Depends} -Description: theorem prover from Microsoft Research - development files (static library) - Z3 is a state-of-the art theorem prover from Microsoft Research. It can be - used to check the satisfiability of logical formulas over one or more - theories. Z3 offers a compelling match for software analysis and verification - tools, since several common software constructs map directly into supported - theories. - . - This package can be used to invoke Z3 via its C++ API. -EOF -cat < debian/rules -#!/usr/bin/make -f -# -*- makefile -*- -# Sample debian/rules that uses debhelper. -# -# This file was originally written by Joey Hess and Craig Small. -# As a special exception, when this file is copied by dh-make into a -# dh-make output file, you may use that output file without restriction. -# This special exception was added by Craig Small in version 0.37 of dh-make. -# -# Modified to make a template file for a multi-binary package with separated -# build-arch and build-indep targets by Bill Allombert 2001 - -# Uncomment this to turn on verbose mode. -export DH_VERBOSE=1 - -# This has to be exported to make some magic below work. -export DH_OPTIONS - - -%: - dh \$@ --buildsystem=cmake - -override_dh_auto_test: - -override_dh_shlibdeps: - dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info - -override_dh_auto_configure: - dh_auto_configure -- ${CMAKE_OPTIONS} - -override_dh_auto_install: - dh_auto_install --destdir debian/tmp -EOF -cat < debian/libz3-static-dev.install -usr/include/* -usr/lib/*/libz3.a -usr/lib/*/cmake/z3/* -EOF -cat < debian/z3-static.install -usr/bin/z3 -EOF -cat < debian/copyright -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: z3 -Source: https://github.com/Z3Prover/z3 - -Files: * -Copyright: Microsoft Corporation -License: Expat - Permission is hereby granted, free of charge, to any person obtaining a copy of - this software and associated documentation files (the "Software"), to deal in - the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is furnished to do - so, subject to the following conditions: - . - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - . - THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - -Files: debian/* -Copyright: 2019 Ethereum -License: GPL-3.0+ -This program 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. - . - This package 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 this program. If not, see . - . - On Debian systems, the complete text of the GNU General - Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". -EOF -cat < debian/changelog -z3-static (0.0.1-1ubuntu0) saucy; urgency=low - - * Initial release. - - -- Daniel Mon, 03 Jun 2019 14:50:20 +0000 -EOF -mkdir debian/source -echo "3.0 (quilt)" > debian/source/format -chmod +x debian/rules - -versionsuffix=1ubuntu0~${distribution} -EMAIL="$LAUNCHPAD_EMAIL" dch -v "1:${debversion}-${versionsuffix}" "build of ${version}" - -# build source package -# If packages is rejected because original source is already present, add -# -sd to remove it from the .changes file -# -d disables the build dependencies check -debuild -S -d -sa -us -uc - -# prepare .changes file for Launchpad -sed -i -e "s/UNRELEASED/${distribution}/" -e s/urgency=medium/urgency=low/ ../*.changes - -# check if ubuntu already has the source tarball -( -cd .. -orig="${packagename}_${debversion}.orig.tar.gz" -# shellcheck disable=SC2012 -orig_size=$(ls -l "$orig" | cut -d ' ' -f 5) -orig_sha1=$(sha1sum "$orig" | cut -d ' ' -f 1) -orig_sha256=$(sha256sum "$orig" | cut -d ' ' -f 1) -orig_md5=$(md5sum "$orig" | cut -d ' ' -f 1) - -if wget --quiet -O "$orig-tmp" "$ppafilesurl/$orig" -then - echo "[WARN] Original tarball found in Ubuntu archive, using it instead" - mv "${orig}-tmp" "$orig" - # shellcheck disable=SC2012 - new_size=$(ls -l ./*.orig.tar.gz | cut -d ' ' -f 5) - new_sha1=$(sha1sum "$orig" | cut -d ' ' -f 1) - new_sha256=$(sha256sum "$orig" | cut -d ' ' -f 1) - new_md5=$(md5sum "$orig" | cut -d ' ' -f 1) - sed -i -e "s,$orig_sha1,$new_sha1,g" -e "s,$orig_sha256,$new_sha256,g" -e "s,$orig_size,$new_size,g" -e "s,$orig_md5,$new_md5,g" ./*.dsc - sed -i -e "s,$orig_sha1,$new_sha1,g" -e "s,$orig_sha256,$new_sha256,g" -e "s,$orig_size,$new_size,g" -e "s,$orig_md5,$new_md5,g" ./*.changes -fi -) - -# sign the package -debsign --re-sign -k "${LAUNCHPAD_KEYID}" "../${packagename}_${debversion}-${versionsuffix}_source.changes" - -# upload -dput "${pparepo}" "../${packagename}_${debversion}-${versionsuffix}_source.changes" - -done diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index cf8df3d6c..2d0cbd180 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -68,7 +68,7 @@ packagename=solc # This needs to be a still active release static_build_distribution=noble -DISTRIBUTIONS="jammy noble oracular" +DISTRIBUTIONS="jammy noble oracular plucky" if is_release then @@ -103,17 +103,14 @@ else fi if [ "$distribution" = focal ] then - SMTDEPENDENCY="libz3-static-dev, - libcvc4-dev, + SMTDEPENDENCY="libcvc4-dev, " elif [ "$distribution" = disco ] then - SMTDEPENDENCY="libz3-static-dev, - libcvc4-dev, + SMTDEPENDENCY="libcvc4-dev, " else - SMTDEPENDENCY="libz3-static-dev, - " + SMTDEPENDENCY="" fi CMAKE_OPTIONS="" fi From 38810a3dc2d91aa51b2788a2df9170da421d34c2 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 8 Apr 2025 15:15:38 +0200 Subject: [PATCH 0820/1340] Adjust release checklist. --- ReleaseChecklist.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index f5e4ec7ca..c9fcaba79 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -85,10 +85,7 @@ At least a day before the release: ### PPA - [ ] Create `.release_ppa_auth` at the root of your local Solidity checkout and set `LAUNCHPAD_EMAIL` and `LAUNCHPAD_KEYID` to your key's email and key id. -- [ ] Double-check that the `DISTRIBUTIONS` list in `scripts/release_ppa.sh` and `scripts/deps-ppa/static_z3.sh` contains the most recent versions of Ubuntu. -- [ ] Make sure the [`~ethereum/cpp-build-deps` PPA repository](https://launchpad.net/~ethereum/+archive/ubuntu/cpp-build-deps) contains `libz3-static-dev` builds for all current versions of Ubuntu. - Note that it may be included in the `z3-static` multipackage (follow the `View package details` link to check). - If not present, run `scripts/deps-ppa/static_z3.sh` and wait for the builds to succeed before continuing. +- [ ] Double-check that the `DISTRIBUTIONS` list in `scripts/release_ppa.sh` contains the most recent versions of Ubuntu. - [ ] Run `scripts/release_ppa.sh v$VERSION` to create the PPA release. This will create a single package containing static binary for older Ubuntu versions in the [`~ethereum/ethereum-static` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum-static) and separate packages with dynamically-linked binaries for recent versions (those listed in `DISTRIBUTIONS`) in the [`~ethereum/ethereum` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum). From fd2d543c6b7f6f134c6146dc8013814fd3e44c13 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 8 Apr 2025 15:21:33 +0200 Subject: [PATCH 0821/1340] Also drop libcvc4-dev and smtdependencies generally. --- scripts/release_ppa.sh | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 2d0cbd180..a8d89040f 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -92,7 +92,6 @@ cd "$distribution" if [ "$distribution" = STATIC ] then pparepo=ethereum-static - SMTDEPENDENCY="" CMAKE_OPTIONS="-DSOLC_LINK_STATIC=On -DCMAKE_EXE_LINKER_FLAGS=-static" else if is_release @@ -101,17 +100,6 @@ else else pparepo=ethereum-dev fi - if [ "$distribution" = focal ] - then - SMTDEPENDENCY="libcvc4-dev, - " - elif [ "$distribution" = disco ] - then - SMTDEPENDENCY="libcvc4-dev, - " - else - SMTDEPENDENCY="" - fi CMAKE_OPTIONS="" fi ppafilesurl=https://launchpad.net/~ethereum/+archive/ubuntu/${pparepo}/+files @@ -153,7 +141,7 @@ Source: solc Section: science Priority: extra Maintainer: Christian (Buildserver key) -Build-Depends: ${SMTDEPENDENCY}debhelper (>= 9.0.0), +Build-Depends: debhelper (>= 9.0.0), cmake, g++ (>= 5.0), git, From e13c612202823d158e845df4435e405fd1576dea Mon Sep 17 00:00:00 2001 From: Henry Chu Date: Fri, 4 Apr 2025 16:28:43 +0800 Subject: [PATCH 0822/1340] Language Server: Fix hover crashes on invalid parameters When `textDocument/hover` gets an out-of-range request --- libsolidity/lsp/DocumentHoverHandler.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libsolidity/lsp/DocumentHoverHandler.cpp b/libsolidity/lsp/DocumentHoverHandler.cpp index e5991b765..a4f3de25c 100644 --- a/libsolidity/lsp/DocumentHoverHandler.cpp +++ b/libsolidity/lsp/DocumentHoverHandler.cpp @@ -59,6 +59,11 @@ void DocumentHoverHandler::operator()(MessageID _id, Json const& _args) { auto const [sourceUnitName, lineColumn] = HandlerBase(*this).extractSourceUnitNameAndLineColumn(_args); auto const [sourceNode, sourceOffset] = m_server.astNodeAndOffsetAtSourceLocation(sourceUnitName, lineColumn); + if (!sourceNode) + { + client().reply(_id, Json()); + return; + } MarkdownBuilder markdown; auto rangeToHighlight = toRange(sourceNode->location()); From 1cd7045cd2cf77a813b8b3baecfcfc5eb5b6af25 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 14 Apr 2025 08:52:53 +0200 Subject: [PATCH 0823/1340] Remove disable pedantic mode switch for osx cmake 4.0.0 and clang 15.0.0 --- CMakeLists.txt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29bf2b0ca..5b39878f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,14 +70,6 @@ endif() find_package(Threads) -if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin" AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - if (CMAKE_VERSION VERSION_EQUAL "4.0.0" AND CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "15.0.0.15000040") - # for Apple clang 15 under cmake 4.0.0, disable pedantic warnings explicitly as it fails to treat boost properly as - # system library, warnings propagate - set(PEDANTIC OFF) - endif() -endif() - if(NOT PEDANTIC) message(WARNING "-- Pedantic build flags turned off. Warnings will not make compilation fail. This is NOT recommended in development builds.") endif() From 09715e6d13f3922b96d671cddf463aea6523ad3e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:18:54 +0200 Subject: [PATCH 0824/1340] osx ci: Install Boost to /opt/boost instead of /usr/local --- .circleci/config.yml | 10 ++++++++-- .circleci/osx_install_dependencies.sh | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d26ef3bd4..09b1281c5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -385,7 +385,7 @@ commands: name: Installing dependencies / Restoring dependency cache command: | if [[ -f ~/osx-dependencies-cached ]]; then - echo "Dependency flag exists. Removing /usr/local/ and /opt/homebrew/. These directories will be restored from cache." + echo "Dependency flag exists. Removing /usr/local/, /opt/homebrew/, and /opt/boost. These directories will be restored from cache." # CircleCI is providing the circleci cli tools via some kind of symlink magic. # So we just save the original symlinks and restore them later. @@ -405,6 +405,10 @@ commands: sudo mkdir -p /usr/local/bin sudo chmod 777 /usr/{local,local/bin} + sudo rm -rf /opt/boost + sudo mkdir -p /opt/boost + sudo chmod 777 /opt/boost + mv /tmp/circleci "${circleci_binary_path}" mv /tmp/circleci-agent "${circleci_agent_binary_path}" fi @@ -425,6 +429,7 @@ commands: # Homebrew is installed in /usr/local on intel macs, but in /opt/homebrew on apple silicon. - /usr/local - /opt/homebrew + - /opt/boost - save_cache: key: osx-dependencies-cached-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} paths: @@ -1159,7 +1164,8 @@ jobs: environment: <<: *base_osx_env CMAKE_BUILD_TYPE: Release - CMAKE_OPTIONS: -DCMAKE_OSX_ARCHITECTURES:STRING=x86_64;arm64 + # boost root configured to the prefix used in `osx_install_dependencies.sh` + CMAKE_OPTIONS: -DCMAKE_OSX_ARCHITECTURES:STRING=x86_64;arm64 -DBoost_ROOT=/opt/boost steps: - checkout - install_dependencies_osx diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index 6e0c859f9..367e8cbb4 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -69,7 +69,8 @@ then cd "$boost_dir" ./bootstrap.sh --with-toolset=clang --with-libraries=thread,system,filesystem,program_options,serialization,test # the default number of jobs that b2 is taking, is the number of detected available CPU threads. - sudo ./b2 -a address-model=64 architecture=arm+x86 install + # install boost to /opt/boost, to use it in CMake, specify Boost_ROOT + sudo ./b2 -a address-model=64 architecture=arm+x86 --prefix=/opt/boost install cd .. sudo rm -rf "$boost_dir" From f1c3a2d6eb2e071d5b09a0a472fd5871e342f83f Mon Sep 17 00:00:00 2001 From: closeobserve Date: Sun, 13 Apr 2025 19:13:59 +0800 Subject: [PATCH 0825/1340] chore: remove redundant word in comment Signed-off-by: closeobserve --- libsolidity/codegen/YulUtilFunctions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index 5ea99d603..c28ba855c 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -560,7 +560,7 @@ class YulUtilFunctions /// Signature: (address) -> mpos std::string externalCodeFunction(); - /// @return the name of a function that that checks if two external functions pointers are equal or not + /// @return the name of a function that checks if two external functions pointers are equal or not std::string externalFunctionPointersEqualFunction(); private: From 1706158dbb4e2525695c8cef023b87b37052af4c Mon Sep 17 00:00:00 2001 From: futreall <86553580+futreall@users.noreply.github.com> Date: Tue, 25 Mar 2025 18:41:27 +0200 Subject: [PATCH 0826/1340] Update premium.sol --- test/compilationTests/corion/premium.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/compilationTests/corion/premium.sol b/test/compilationTests/corion/premium.sol index 646ab00e1..2702aa5bb 100644 --- a/test/compilationTests/corion/premium.sol +++ b/test/compilationTests/corion/premium.sol @@ -229,7 +229,7 @@ contract premium is module, safeMath { function transfer(address to, uint256 amount, bytes calldata extraData) isReady external returns (bool success) { /* Launch a transaction where we transfer from a given address to another one. - After thetransaction the approvedCorionPremiumToken function of the receiver’s address is going to be called with the given data. + After the transaction the approvedCorionPremiumToken function of the receiver’s address is going to be called with the given data. @to For who? @amount Amount From a1be4f313dd4120b5cb5994fe93f03c76e1de9ba Mon Sep 17 00:00:00 2001 From: futreall <86553580+futreall@users.noreply.github.com> Date: Tue, 25 Mar 2025 18:41:58 +0200 Subject: [PATCH 0827/1340] Update publisher.sol --- test/compilationTests/corion/publisher.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/compilationTests/corion/publisher.sol b/test/compilationTests/corion/publisher.sol index 311e8d92e..27d90a27e 100644 --- a/test/compilationTests/corion/publisher.sol +++ b/test/compilationTests/corion/publisher.sol @@ -205,8 +205,8 @@ contract publisher is announcementTypes, module, safeMath { If announcement is opposable, anyone owning a token can oppose it Opposition is automatically with the total amount of tokens If the quantity of his tokens changes, the purport of his opposition changes automatically - The prime time is the windup of the announcement, because this is the moment when the number of tokens in opposition are counted. - One address is entitled to be in oppositon only once. An opposition cannot be withdrawn. + The prime time is the windup of the announcement, because this is the moment when the number of tokens in opposition are counted. + One address is entitled to be in opposition only once. An opposition cannot be withdrawn. Running announcements can be opposed only. @id Announcement identification From 513535a75849bf18c44e24f31e56aad4d1b4b94f Mon Sep 17 00:00:00 2001 From: matta Date: Fri, 8 Mar 2024 17:17:06 -0300 Subject: [PATCH 0828/1340] Adding clarity on extcalls with precompiled contracts. --- docs/control-structures.rst | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 1d21a6e26..8a815e10e 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -111,22 +111,35 @@ otherwise, the ``value`` option would not be available. the ``value`` and ``gas`` settings are lost, only ``feed.info{value: 10, gas: 800}()`` performs the function call. -Due to the fact that the EVM considers a call to a non-existing contract to -always succeed, Solidity uses the ``extcodesize`` opcode to check that -the contract that is about to be called actually exists (it contains code) -and causes an exception if it does not. This check is skipped if the return -data will be decoded after the call and thus the ABI decoder will catch the -case of a non-existing contract. +.. warning:: + Due to the fact that the EVM considers a call to a non-existing contract to + always succeed, Solidity uses the ``extcodesize`` opcode to check that + the contract that is about to be called actually exists (it contains code) + and causes an exception if it does not. This check is skipped if the return + data will be decoded after the call and thus the ABI decoder will catch the + case of a non-existing contract. -Note that this check is not performed in case of :ref:`low-level calls ` which -operate on addresses rather than contract instances. + This check is not performed in case of :ref:`low-level calls ` which + operate on addresses rather than contract instances. -.. note:: +.. warning:: Be careful when using high-level calls to :ref:`precompiled contracts `, since the compiler considers them non-existing according to the above logic even though they execute code and can return data. +.. note:: + Since the version 0.8.10, the compiler does not check ``extcodesize`` on + high-level external calls if return data is expected, because an empty code + will be unable to return data, and the ABI decoder will revert. + As a consequence, this allows high-level external calls to precompiled + contracts, since they can return data despite having no code + associated with their addresses. + + Read about :ref:`precompiled contracts ` and + :ref:`low-level calls ` + for more information. + Function calls also cause exceptions if the called contract itself throws an exception or goes out of gas. @@ -901,4 +914,4 @@ in scope in the block that follows. out-of-gas situation and not a deliberate error condition: The caller always retains at least 1/64th of the gas in a call and thus even if the called contract goes out of gas, the caller still - has some gas left. + has some gas left. \ No newline at end of file From 8b85d14f7d1e3cbb476434dec2af60c456af7fe4 Mon Sep 17 00:00:00 2001 From: Bilog WEB3 <155262265+Bilogweb3@users.noreply.github.com> Date: Wed, 26 Feb 2025 09:50:31 +0100 Subject: [PATCH 0829/1340] Update custom.css --- docs/_static/css/custom.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index d2c9c86e7..bdfb5ce0b 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -93,7 +93,7 @@ h1 { } section:first-of-type h1:first-of-type { - font-family: 'Overpass mono', monospace; + font-family: 'Overpass Mono', monospace; font-size: 48px; margin-top: 3rem; margin-bottom: 5rem; From eda68d51fdefd92186bb4390d8b2eaaae2bf7c93 Mon Sep 17 00:00:00 2001 From: PixelPilot <161360836+PixelPil0t1@users.noreply.github.com> Date: Tue, 11 Mar 2025 15:15:18 +0100 Subject: [PATCH 0830/1340] Update events.rst --- docs/contracts/events.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contracts/events.rst b/docs/contracts/events.rst index 8c73c3160..c83970099 100644 --- a/docs/contracts/events.rst +++ b/docs/contracts/events.rst @@ -15,7 +15,7 @@ arguments to be stored in the transaction's log - a special data structure in the blockchain. These logs are associated with the address of the contract that emitted them, are incorporated into the blockchain, and stay there as long as a block is accessible (forever as of now, but this might -change in the future). The Log and its event data is not accessible from within +change in the future). The Log and its event data are not accessible from within contracts (not even from the contract that created them). It is possible to request a Merkle proof for logs, so if From feed69b5cac1e9519b881878b6595a2ee893835f Mon Sep 17 00:00:00 2001 From: argentpapa Date: Fri, 28 Feb 2025 01:17:33 +0800 Subject: [PATCH 0831/1340] Update calling_nonexisting_contract.sol --- .../functionCall/eof/calling_nonexisting_contract.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsolidity/semanticTests/functionCall/eof/calling_nonexisting_contract.sol b/test/libsolidity/semanticTests/functionCall/eof/calling_nonexisting_contract.sol index 10b39634d..a1a53e09d 100644 --- a/test/libsolidity/semanticTests/functionCall/eof/calling_nonexisting_contract.sol +++ b/test/libsolidity/semanticTests/functionCall/eof/calling_nonexisting_contract.sol @@ -8,7 +8,7 @@ contract C { function f() public returns (uint256) { // This call throws on legacy bytecode because of calling nonexisting contract. Legacy checks that there is - // a non-empty code under under an address. EOF doesn't do it because non-observability assumption + // a non-empty code under an address. EOF doesn't do it because non-observability assumption d.g(); return 7; } From ba3fd65cfbc2450d538229febf87ea3863230a67 Mon Sep 17 00:00:00 2001 From: Voronor <129545215+voronor@users.noreply.github.com> Date: Tue, 4 Feb 2025 14:23:39 +0100 Subject: [PATCH 0832/1340] docs: Fix grammar in workflow trigger condition --- scripts/docker/buildpack-deps/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docker/buildpack-deps/README.md b/scripts/docker/buildpack-deps/README.md index 9cfcafd4b..6149165c8 100644 --- a/scripts/docker/buildpack-deps/README.md +++ b/scripts/docker/buildpack-deps/README.md @@ -6,7 +6,7 @@ The `buildpack-deps` docker images are used to compile and test solidity within The creation of the images is triggered by a single workflow, defined in `.github/workflows/buildpack-deps.yml`. For each resulting `buildpack-deps` docker image a strategy is defined in the workflow file - the image variant. -The workflow gets triggered, if any Dockerfile defined in `scripts/docker/buildpack-deps/Dockerfile.*` were changed +The workflow gets triggered, if any Dockerfile defined in `scripts/docker/buildpack-deps/Dockerfile.*` was changed within the PR. ### Versioning From ab77b34e67ae6327f80bdd5098889243b3a86d66 Mon Sep 17 00:00:00 2001 From: emmmm <155267286+eeemmmmmm@users.noreply.github.com> Date: Wed, 26 Feb 2025 09:43:24 +0100 Subject: [PATCH 0833/1340] Update ControlFlowGraphBuilder.h --- libyul/backends/evm/ControlFlowGraphBuilder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.h b/libyul/backends/evm/ControlFlowGraphBuilder.h index 1d0227a56..4a2aae98c 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.h +++ b/libyul/backends/evm/ControlFlowGraphBuilder.h @@ -33,7 +33,7 @@ class ControlFlowGraphBuilder ControlFlowGraphBuilder& operator=(ControlFlowGraphBuilder const&) = delete; static std::unique_ptr build(AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, Block const& _block); - StackSlot operator()(Expression const& _literal); + StackSlot operator()(Expression const& _expression); StackSlot operator()(Literal const& _literal); StackSlot operator()(Identifier const& _identifier); StackSlot operator()(FunctionCall const&); From 10b21b89a6c2c8a00ea27706497607d28bb4cf19 Mon Sep 17 00:00:00 2001 From: "ferranmesas@gmx.es" Date: Fri, 28 Feb 2025 22:52:40 +0100 Subject: [PATCH 0834/1340] Replace temporary std::string with std::string_view in _yulname literal to avoid unnecessary allocations --- libyul/YulString.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/YulString.h b/libyul/YulString.h index d6c13f0d3..329825a44 100644 --- a/libyul/YulString.h +++ b/libyul/YulString.h @@ -165,7 +165,7 @@ class YulString inline YulString operator "" _yulname(char const* _string, std::size_t _size) { - return YulString(std::string(_string, _size)); + return YulString(std::string_view(_string, _size)); } } From 771d8052df8947f781d126fea349734344941a3c Mon Sep 17 00:00:00 2001 From: NeoByteX <160131789+NeoByteXx@users.noreply.github.com> Date: Sat, 22 Feb 2025 08:33:10 +0100 Subject: [PATCH 0835/1340] Fix typo in test script comments --- test/externalTests/brink.sh | 2 +- test/externalTests/elementfi.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/externalTests/brink.sh b/test/externalTests/brink.sh index 02e5fe971..e541481b4 100755 --- a/test/externalTests/brink.sh +++ b/test/externalTests/brink.sh @@ -61,7 +61,7 @@ function brink_test setup_solc "$DIR" "$BINARY_TYPE" "$BINARY_PATH" download_project "$repo" "$ref" "$DIR" - # TODO: Remove this when Brink merges https://github.com/brinktrade/brink-core/pull/52 + # TODO: Remove this once Brink merges PR #52 (https://github.com/brinktrade/brink-core/pull/52). sed -i "s|\(function isValidSignature(bytes \)calldata\( _data, bytes \)calldata\( _signature)\)|\1memory\2memory\3|g" src/Test/MockEIP1271Validator.sol neutralize_package_lock diff --git a/test/externalTests/elementfi.sh b/test/externalTests/elementfi.sh index f34a169e9..aa73ea768 100755 --- a/test/externalTests/elementfi.sh +++ b/test/externalTests/elementfi.sh @@ -93,8 +93,8 @@ function elementfi_test sed -i 's|it(\("should prevent withdrawal of Principal Tokens and Interest Tokens before the tranche expires "\)|it.skip(\1|g' test/trancheTest.ts sed -i 's|it(\("should prevent withdrawal of more Principal Tokens and Interest Tokens than the user has"\)|it.skip(\1|g' test/trancheTest.ts - # This test file is very flaky. There's one particular cases that fails randomly (see - # https://github.com/element-fi/elf-contracts/issues/240) but some others also depends on an external + # This test file is very flaky. There's one particular case that fails randomly (see + # https://github.com/element-fi/elf-contracts/issues/240) but some others also depend on an external # service which makes tests time out when that service is down. # "ProviderError: Too Many Requests error received from eth-mainnet.alchemyapi.io" rm test/mockERC20YearnVaultTest.ts From d22a07012e03cd3a942235aa166f00f0c000dcdb Mon Sep 17 00:00:00 2001 From: Skylar Ray <137945430+sky-coderay@users.noreply.github.com> Date: Fri, 14 Mar 2025 10:08:33 +0200 Subject: [PATCH 0836/1340] fix minor issues Update DataFlowAnalyzer.cpp Update CommonSubexpressionEliminator.cpp /*( -deleted ( --- libyul/CompilabilityChecker.cpp | 2 +- libyul/optimiser/CommonSubexpressionEliminator.cpp | 2 +- libyul/optimiser/DataFlowAnalyzer.cpp | 2 +- libyul/optimiser/Metrics.cpp | 2 +- libyul/optimiser/Rematerialiser.cpp | 2 +- libyul/optimiser/StackCompressor.cpp | 2 +- libyul/optimiser/SyntacticalEquality.cpp | 2 +- libyul/optimiser/UnusedPruner.cpp | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index cc46ecb77..2df14f211 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -1,4 +1,4 @@ -/*( +/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify diff --git a/libyul/optimiser/CommonSubexpressionEliminator.cpp b/libyul/optimiser/CommonSubexpressionEliminator.cpp index 87a14d259..1a6f3911a 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.cpp +++ b/libyul/optimiser/CommonSubexpressionEliminator.cpp @@ -1,4 +1,4 @@ -/*( +/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 240778135..1aecd6bd4 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -1,4 +1,4 @@ -/*( +/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify diff --git a/libyul/optimiser/Metrics.cpp b/libyul/optimiser/Metrics.cpp index 04bfe9a7a..5c3a62426 100644 --- a/libyul/optimiser/Metrics.cpp +++ b/libyul/optimiser/Metrics.cpp @@ -1,4 +1,4 @@ -/*( +/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify diff --git a/libyul/optimiser/Rematerialiser.cpp b/libyul/optimiser/Rematerialiser.cpp index bfcd9d8f6..1d3535fda 100644 --- a/libyul/optimiser/Rematerialiser.cpp +++ b/libyul/optimiser/Rematerialiser.cpp @@ -1,4 +1,4 @@ -/*( +/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 97d2c0547..b0be60d63 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -1,4 +1,4 @@ -/*( +/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify diff --git a/libyul/optimiser/SyntacticalEquality.cpp b/libyul/optimiser/SyntacticalEquality.cpp index e233b57e9..a032e912b 100644 --- a/libyul/optimiser/SyntacticalEquality.cpp +++ b/libyul/optimiser/SyntacticalEquality.cpp @@ -1,4 +1,4 @@ -/*( +/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index 5d50e4599..2f982b164 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -1,4 +1,4 @@ -/*( +/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify From a7ac67cc8f19aed11c9fad10e861a2c318608438 Mon Sep 17 00:00:00 2001 From: Tomass <155266802+zeroprooff@users.noreply.github.com> Date: Thu, 17 Apr 2025 23:09:46 +0200 Subject: [PATCH 0837/1340] fix duplicate EVMHost.cpp --- test/EVMHost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 983615312..6f64b703b 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -399,7 +399,7 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept transfer(sender, destination, value); } - // Populate the access access list (enabled since Berlin). + // Populate the access list (enabled since Berlin). // Note, this will also properly touch the created address. // TODO: support a user supplied access list too if (m_evmRevision >= EVMC_BERLIN) From 02d2c9af23c830667ccbce4e581357a163615dea Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 9 Apr 2025 13:54:18 +0200 Subject: [PATCH 0838/1340] change into test dir for cmdline tests --- test/cmdlineTests.sh | 45 ++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index f68ed53dc..b3327ea98 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -225,7 +225,7 @@ EOF if jq 'has("ethdebug")' "$stdout_path" --exit-status > /dev/null; then local temporary_file temporary_file=$(mktemp -t cmdline-ethdebug-XXXXXX.tmp) - if [[ -e ${tdir}/strip-ethdebug ]]; then + if [[ -e strip-ethdebug ]]; then jq --indent 4 ' (. | .. | objects | select(has("ethdebug"))) |= (.ethdebug = "") ' "$stdout_path" > "$temporary_file" @@ -350,9 +350,11 @@ test_solc_behaviour "${0}" "ctx:=/some/remapping/target" "" "" 1 "" "Error: Inva printTask "Running general commandline tests..." ( - cd "$REPO_ROOT"/test/cmdlineTests/ for tdir in "${selected_tests[@]}" do + # go back to the test root dir + cd "$REPO_ROOT"/test/cmdlineTests/ + if ! [[ -d $tdir ]] then fail "Test directory not found: $tdir" @@ -377,10 +379,13 @@ printTask "Running general commandline tests..." fi fi - scriptFiles="$(ls -1 "${tdir}/test."* 2> /dev/null || true)" + # jump into test dir + cd "${tdir}" + + scriptFiles="$(ls -1 "test."* 2> /dev/null || true)" scriptCount="$(echo "${scriptFiles}" | wc -w)" - inputFiles="$(ls -1 "${tdir}/input."* 2> /dev/null || true)" + inputFiles="$(ls -1 "input."* 2> /dev/null || true)" inputCount="$(echo "${inputFiles}" | wc -w)" (( inputCount <= 1 )) || fail "Ambiguous input. Found input files in multiple formats:"$'\n'"${inputFiles}" (( scriptCount <= 1 )) || fail "Ambiguous input. Found script files in multiple formats:"$'\n'"${scriptFiles}" @@ -388,7 +393,7 @@ printTask "Running general commandline tests..." if (( scriptCount == 1 )) then - if ! "$scriptFiles" + if ! "./$scriptFiles" then fail "Test script ${scriptFiles} failed." fi @@ -399,38 +404,38 @@ printTask "Running general commandline tests..." # Use printf to get rid of the trailing newline inputFile=$(printf "%s" "${inputFiles}") - if [ "${inputFile}" = "${tdir}/input.json" ] + if [ "${inputFile}" = "input.json" ] then - ! [ -e "${tdir}/stdin" ] || fail "Found a file called 'stdin' but redirecting standard input in JSON mode is not allowed." + ! [ -e "stdin" ] || fail "Found a file called 'stdin' but redirecting standard input in JSON mode is not allowed." stdin="${inputFile}" inputFile="" - stdout="$(cat "${tdir}/output.json" 2>/dev/null || true)" - stdoutExpectationFile="${tdir}/output.json" + stdout="$(cat "output.json" 2>/dev/null || true)" + stdoutExpectationFile="output.json" prettyPrintFlags="" - if [[ ! -f "${tdir}/no-pretty-print" ]] + if [[ ! -f "no-pretty-print" ]] then prettyPrintFlags="--pretty-json --json-indent 4" fi - command_args="--standard-json ${prettyPrintFlags} "$(cat "${tdir}/args" 2>/dev/null || true) + command_args="--standard-json ${prettyPrintFlags} "$(cat "args" 2>/dev/null || true) else - if [ -e "${tdir}/stdin" ] + if [ -e "stdin" ] then - stdin="${tdir}/stdin" - [ -f "${tdir}/stdin" ] || fail "'stdin' is not a regular file." + stdin="stdin" + [ -f "stdin" ] || fail "'stdin' is not a regular file." else stdin="" fi - stdout="$(cat "${tdir}/output" 2>/dev/null || true)" - stdoutExpectationFile="${tdir}/output" - command_args=$(cat "${tdir}/args" 2>/dev/null || true) + stdout="$(cat "output" 2>/dev/null || true)" + stdoutExpectationFile="output" + command_args=$(cat "args" 2>/dev/null || true) fi - exitCodeExpectationFile="${tdir}/exit" + exitCodeExpectationFile="exit" exitCode=$(cat "$exitCodeExpectationFile" 2>/dev/null || true) - err="$(cat "${tdir}/err" 2>/dev/null || true)" - stderrExpectationFile="${tdir}/err" + err="$(cat "err" 2>/dev/null || true)" + stderrExpectationFile="err" test_solc_behaviour "$inputFile" \ "$command_args" \ "$stdin" \ From 2fa170efc1517f1ddc82c24d015c95d82f4c1534 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 10 Apr 2025 15:26:42 +0200 Subject: [PATCH 0839/1340] update test expectations with cwd being in test dir --- test/cmdlineTests/abi_via_ir/output | 4 +- .../abiencoderv2_no_warning/output | 2 +- test/cmdlineTests/asm_json/output | 4 +- .../asm_json_no_pretty_print/output | 4 +- .../ast_compact_json_no_pretty_json/output | 4 +- .../output | 4 +- .../ast_compact_json_with_base_path/output | 10 +- test/cmdlineTests/ast_ir/output | 276 +++++++++--------- test/cmdlineTests/combined_json_abi/output | 2 +- .../combined_json_generated_sources/output | 2 +- .../combined_json_no_pretty_print/output | 2 +- .../combined_json_stop_after_parsing/output | 8 +- .../combined_json_with_base_path/output | 16 +- .../combined_json_with_devdoc/output | 4 +- .../combined_json_with_userdoc/output | 4 +- .../constant_optimizer_yul/output | 4 +- .../output | 16 +- .../output | 16 +- .../output | 10 +- .../debug_info_in_yul_snippet_escaping/output | 24 +- test/cmdlineTests/dup_opt_peephole/output | 18 +- test/cmdlineTests/error_codes/err | 12 +- .../ethdebug_eof_container_osaka/output | 4 +- test/cmdlineTests/events_in_abi/output | 4 +- test/cmdlineTests/evm_version_byzantium/err | 2 +- .../evm_version_constantinople/err | 2 +- .../evmasm_difficulty_post_paris/err | 2 +- .../evmasm_difficulty_post_paris/output | 2 +- .../evmasm_difficulty_pre_paris/output | 2 +- .../evmasm_prevrandao_post_paris/output | 2 +- .../evmasm_prevrandao_pre_paris/err | 2 +- .../evmasm_prevrandao_pre_paris/output | 2 +- .../err | 2 +- .../output | 2 +- .../err | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- test/cmdlineTests/exp_base_literal/output | 4 +- test/cmdlineTests/function_debug_info/output | 2 +- .../function_debug_info_via_yul/output | 2 +- test/cmdlineTests/hashes/output | 4 +- .../inline_assembly_function_name_clash/err | 4 +- .../output | 2 +- .../output | 8 +- test/cmdlineTests/ir_compiler_subobjects/err | 2 +- .../ir_compiler_subobjects/output | 12 +- .../output | 4 +- .../ir_optimized_with_optimize/output | 4 +- test/cmdlineTests/ir_subobject_order/output | 20 +- .../ir_unoptimized_with_optimize/output | 4 +- .../output | 4 +- .../output | 4 +- .../output | 4 +- .../keccak_optimization_deploy_code/output | 4 +- .../keccak_optimization_low_runs/output | 4 +- .../linking_qualified_library_name/args | 2 +- .../contract1.sol | 2 +- .../linking_qualified_library_name/output | 4 +- test/cmdlineTests/linking_solidity/args | 2 +- test/cmdlineTests/linking_solidity/output | 4 +- .../args | 2 +- .../output | 18 +- .../linking_strict_assembly/output | 10 +- .../output | 2 +- .../output | 2 +- .../output | 18 +- .../output | 18 +- .../output | 2 +- .../output | 2 +- .../output | 18 +- .../linking_unqualified_library_name/args | 2 +- .../contract1.sol | 2 +- .../contract2.sol | 2 +- .../linking_unqualified_library_name/output | 16 +- .../mcopy_bytes_array_abi_decode/err | 2 +- .../mcopy_bytes_array_abi_decode/output | 4 +- .../output | 4 +- .../output | 4 +- .../output | 4 +- test/cmdlineTests/message_format/err | 18 +- test/cmdlineTests/message_format_utf8/err | 10 +- test/cmdlineTests/metadata/output | 4 +- .../model_checker_bmc_loop_iterations/err | 2 +- .../err | 2 +- .../model_checker_contracts_all/err | 4 +- .../model_checker_contracts_all_explicit/args | 2 +- .../model_checker_contracts_all_explicit/err | 4 +- .../args | 2 +- .../err | 2 +- .../args | 2 +- .../err | 2 +- .../args | 2 +- .../err | 2 +- .../model_checker_contracts_only_one/args | 2 +- .../model_checker_contracts_only_one/err | 4 +- .../cmdlineTests/model_checker_engine_all/err | 2 +- .../cmdlineTests/model_checker_engine_bmc/err | 2 +- .../cmdlineTests/model_checker_engine_chc/err | 2 +- .../model_checker_ext_calls_trusted_chc/err | 2 +- .../model_checker_ext_calls_untrusted_chc/err | 2 +- .../model_checker_invariants_all/err | 4 +- .../model_checker_invariants_contract/err | 2 +- .../model_checker_invariants_contract_eld/err | 2 +- .../err | 4 +- .../model_checker_invariants_reentrancy/err | 2 +- .../err | 2 +- .../err | 2 +- .../err | 2 +- .../err | 6 +- .../err | 6 +- .../err | 6 +- .../err | 2 +- .../model_checker_show_unproved_true_chc/err | 2 +- .../err | 2 +- .../err | 2 +- .../err | 2 +- .../model_checker_solvers_cvc5/err | 2 +- .../model_checker_solvers_cvc5_eld/err | 2 +- .../model_checker_solvers_eld/err | 2 +- .../cmdlineTests/model_checker_solvers_z3/err | 2 +- .../model_checker_solvers_z3_implicit/err | 2 +- .../model_checker_solvers_z3_smtlib2/err | 2 +- .../model_checker_targets_all_all_engines/err | 14 +- .../model_checker_targets_all_bmc/err | 12 +- .../model_checker_targets_all_chc/err | 12 +- .../model_checker_targets_assert_bmc/err | 2 +- .../model_checker_targets_assert_chc/err | 2 +- .../model_checker_targets_balance_bmc/err | 2 +- .../err | 2 +- .../err | 10 +- .../model_checker_targets_default_bmc/err | 8 +- .../model_checker_targets_default_chc/err | 8 +- .../model_checker_targets_div_by_zero_bmc/err | 2 +- .../model_checker_targets_div_by_zero_chc/err | 2 +- .../err | 2 +- .../model_checker_targets_overflow_bmc/err | 2 +- .../model_checker_targets_overflow_chc/err | 2 +- .../model_checker_targets_pop_empty_chc/err | 2 +- .../model_checker_targets_underflow_bmc/err | 2 +- .../model_checker_targets_underflow_chc/err | 2 +- .../err | 6 +- .../err | 6 +- .../err | 4 +- .../err | 4 +- test/cmdlineTests/name_simplifier/output | 4 +- test/cmdlineTests/no_cbor_metadata/output | 2 +- .../no_contract_combined_json/output | 6 +- test/cmdlineTests/no_import_callback/args | 2 +- test/cmdlineTests/no_import_callback/err | 2 +- test/cmdlineTests/object_compiler/output | 34 +-- .../optimize_full_storage_write/output | 16 +- .../optimizer_BlockDeDuplicator/err | 4 +- .../optimizer_BlockDeDuplicator/output | 20 +- .../cmdlineTests/optimizer_array_sload/output | 4 +- .../cmdlineTests/optimizer_inliner_add/output | 30 +- .../output | 24 +- .../output | 58 ++-- .../output | 66 ++--- .../cmdlineTests/optimizer_inliner_inc/output | 28 +- .../optimizer_inliner_multireturn/output | 30 +- test/cmdlineTests/optimizer_user_yul/output | 56 ++-- test/cmdlineTests/require_overload/err | 2 +- .../cmdlineTests/require_with_error_ir/output | 4 +- .../require_with_string_ir/output | 4 +- test/cmdlineTests/revert_strings/output | 4 +- .../stack_too_deep_from_code_transform/err | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../standard_ir_ast_requested/input.json | 2 +- .../cmdlineTests/standard_metadata/input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../standard_optimizer_no_yul/input.json | 2 +- .../standard_optimizer_yul/input.json | 2 +- .../standard_optimizer_yulDetails/input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 6 +- .../output.json | 4 +- .../standard_urls_missing/input.json | 6 +- .../standard_urls_missing/output.json | 12 +- .../standard_yul_cfg_json_export/input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../standard_yul_ethdebug_ir/input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../stop_after_parsing_ast/output | 4 +- .../input.json | 2 +- .../storage_layout_user_defined/err | 2 +- .../storage_layout_user_defined/output | 18 +- .../output | 2 +- .../strict_asm_ast_compact_json/output | 2 +- .../strict_asm_debug_info_print_all/output | 2 +- .../output | 2 +- .../strict_asm_debug_info_print_none/output | 2 +- .../strict_asm_eof_container_osaka/output | 2 +- .../strict_asm_eof_dataloadn_osaka/output | 2 +- .../strict_asm_evm_version_byzantium/output | 4 +- .../output | 4 +- test/cmdlineTests/strict_asm_jump/err | 2 +- .../strict_asm_msize_with_optimizer/output | 2 +- .../strict_asm_msize_without_optimizer/output | 2 +- test/cmdlineTests/strict_asm_only_cr/err | 2 +- .../strict_asm_optimizer_steps/output | 50 ++-- .../output | 10 +- .../output | 2 +- .../output | 2 +- test/cmdlineTests/strict_asm_warning/err | 2 +- test/cmdlineTests/strict_asm_warning/output | 2 +- .../strict_asm_warning_and_error_optimize/err | 4 +- .../strict_asm_warning_optimize/err | 2 +- .../strict_asm_warning_optimize/output | 2 +- .../err | 2 +- .../output | 2 +- .../strict_asm_yul_cfg_json_export/output | 2 +- .../err | 4 +- test/cmdlineTests/too_long_line/err | 2 +- .../too_long_line_both_sides_short/err | 2 +- test/cmdlineTests/too_long_line_edge_in/err | 2 +- test/cmdlineTests/too_long_line_edge_out/err | 2 +- .../cmdlineTests/too_long_line_left_short/err | 2 +- test/cmdlineTests/too_long_line_multiline/err | 2 +- .../too_long_line_right_short/err | 2 +- .../transient_storage_layout/output | 12 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 2 +- .../output | 4 +- test/cmdlineTests/viair_abicoder_v1/err | 2 +- test/cmdlineTests/viair_abicoder_v1/output | 4 +- .../viair_msize_without_optimizer/output | 6 +- .../viair_subobject_optimization/output | 56 ++-- test/cmdlineTests/viair_subobjects/err | 2 +- test/cmdlineTests/viair_subobjects/output | 16 +- test/cmdlineTests/yul_cfg_json_export/output | 6 +- .../yul_function_name_clashes/output | 2 +- .../output | 28 +- test/cmdlineTests/yul_optimize_runs/output | 22 +- .../output | 4 +- test/cmdlineTests/yul_optimizer_steps/output | 4 +- .../output | 4 +- .../yul_optimizer_steps_short_sequence/output | 4 +- .../output | 4 +- .../output | 4 +- .../err | 4 +- .../output | 8 +- test/cmdlineTests/yul_verbatim/output | 34 +-- test/cmdlineTests/yul_verbatim_msize/output | 18 +- 291 files changed, 959 insertions(+), 959 deletions(-) diff --git a/test/cmdlineTests/abi_via_ir/output b/test/cmdlineTests/abi_via_ir/output index 56ba01a4a..3b3fec68d 100644 --- a/test/cmdlineTests/abi_via_ir/output +++ b/test/cmdlineTests/abi_via_ir/output @@ -1,5 +1,5 @@ -======= abi_via_ir/input.sol:C ======= +======= input.sol:C ======= Contract JSON ABI [ { @@ -101,7 +101,7 @@ Contract JSON ABI } ] -======= abi_via_ir/input.sol:L ======= +======= input.sol:L ======= Contract JSON ABI [ { diff --git a/test/cmdlineTests/abiencoderv2_no_warning/output b/test/cmdlineTests/abiencoderv2_no_warning/output index 33f8d2e1f..5b99567cc 100644 --- a/test/cmdlineTests/abiencoderv2_no_warning/output +++ b/test/cmdlineTests/abiencoderv2_no_warning/output @@ -1,4 +1,4 @@ -======= abiencoderv2_no_warning/input.sol:C ======= +======= input.sol:C ======= Function signatures: 3fc03eeb: f((uint256)) diff --git a/test/cmdlineTests/asm_json/output b/test/cmdlineTests/asm_json/output index 820eda6ec..a148e42f0 100644 --- a/test/cmdlineTests/asm_json/output +++ b/test/cmdlineTests/asm_json/output @@ -1,5 +1,5 @@ -======= asm_json/input.sol:C ======= +======= input.sol:C ======= EVM assembly: { ".code": [ @@ -1573,7 +1573,7 @@ EVM assembly: } }, "sourceList": [ - "asm_json/input.sol", + "input.sol", "#utility.yul" ] } diff --git a/test/cmdlineTests/asm_json_no_pretty_print/output b/test/cmdlineTests/asm_json_no_pretty_print/output index 8fce2f482..b2382e186 100644 --- a/test/cmdlineTests/asm_json_no_pretty_print/output +++ b/test/cmdlineTests/asm_json_no_pretty_print/output @@ -1,4 +1,4 @@ -======= asm_json_no_pretty_print/input.sol:C ======= +======= input.sol:C ======= EVM assembly: -{".code":[{"begin":60,"end":160,"name":"PUSH","source":0,"value":"80"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"40"},{"begin":60,"end":160,"name":"MSTORE","source":0},{"begin":60,"end":160,"name":"CALLVALUE","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"ISZERO","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"POP","source":0},{"begin":60,"end":160,"name":"PUSH #[$]","source":0,"value":"0000000000000000000000000000000000000000000000000000000000000000"},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"PUSH [$]","source":0,"value":"0000000000000000000000000000000000000000000000000000000000000000"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"CODECOPY","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"RETURN","source":0}],".data":{"0":{".auxdata":"",".code":[{"begin":60,"end":160,"name":"PUSH","source":0,"value":"80"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"40"},{"begin":60,"end":160,"name":"MSTORE","source":0},{"begin":60,"end":160,"name":"CALLVALUE","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"ISZERO","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"POP","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"4"},{"begin":60,"end":160,"name":"CALLDATASIZE","source":0},{"begin":60,"end":160,"name":"LT","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"2"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"CALLDATALOAD","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"E0"},{"begin":60,"end":160,"name":"SHR","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"B3DE648B"},{"begin":60,"end":160,"name":"EQ","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"3"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"2"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"3"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"4"},{"begin":77,"end":158,"name":"PUSH","source":0,"value":"4"},{"begin":77,"end":158,"name":"DUP1","source":0},{"begin":77,"end":158,"name":"CALLDATASIZE","source":0},{"begin":77,"end":158,"name":"SUB","source":0},{"begin":77,"end":158,"name":"DUP2","source":0},{"begin":77,"end":158,"name":"ADD","source":0},{"begin":77,"end":158,"name":"SWAP1","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"5"},{"begin":77,"end":158,"name":"SWAP2","source":0},{"begin":77,"end":158,"name":"SWAP1","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"6"},{"begin":77,"end":158,"jumpType":"[in]","name":"JUMP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"5"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"7"},{"begin":77,"end":158,"jumpType":"[in]","name":"JUMP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"4"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"STOP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"7"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":123,"end":125,"name":"PUSH","source":0,"value":"2A"},{"begin":118,"end":125,"name":"DUP2","source":0},{"begin":118,"end":125,"name":"PUSH [tag]","source":0,"value":"9"},{"begin":118,"end":125,"name":"SWAP2","source":0},{"begin":118,"end":125,"name":"SWAP1","source":0},{"begin":118,"end":125,"name":"PUSH [tag]","source":0,"value":"10"},{"begin":118,"end":125,"jumpType":"[in]","name":"JUMP","source":0},{"begin":118,"end":125,"name":"tag","source":0,"value":"9"},{"begin":118,"end":125,"name":"JUMPDEST","source":0},{"begin":118,"end":125,"name":"SWAP1","source":0},{"begin":118,"end":125,"name":"POP","source":0},{"begin":147,"end":150,"name":"PUSH","source":0,"value":"64"},{"begin":143,"end":144,"name":"DUP2","source":0},{"begin":143,"end":150,"name":"GT","source":0},{"begin":135,"end":151,"name":"PUSH [tag]","source":0,"value":"11"},{"begin":135,"end":151,"name":"JUMPI","source":0},{"begin":135,"end":151,"name":"PUSH","source":0,"value":"0"},{"begin":135,"end":151,"name":"PUSH","source":0,"value":"0"},{"begin":135,"end":151,"name":"REVERT","source":0},{"begin":135,"end":151,"name":"tag","source":0,"value":"11"},{"begin":135,"end":151,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"POP","source":0},{"begin":77,"end":158,"jumpType":"[out]","name":"JUMP","source":0},{"begin":88,"end":205,"name":"tag","source":1,"value":"13"},{"begin":88,"end":205,"name":"JUMPDEST","source":1},{"begin":197,"end":198,"name":"PUSH","source":1,"value":"0"},{"begin":194,"end":195,"name":"PUSH","source":1,"value":"0"},{"begin":187,"end":199,"name":"REVERT","source":1},{"begin":334,"end":411,"name":"tag","source":1,"value":"15"},{"begin":334,"end":411,"name":"JUMPDEST","source":1},{"begin":371,"end":378,"name":"PUSH","source":1,"value":"0"},{"begin":400,"end":405,"name":"DUP2","source":1},{"begin":389,"end":405,"name":"SWAP1","source":1},{"begin":389,"end":405,"name":"POP","source":1},{"begin":334,"end":411,"name":"SWAP2","source":1},{"begin":334,"end":411,"name":"SWAP1","source":1},{"begin":334,"end":411,"name":"POP","source":1},{"begin":334,"end":411,"jumpType":"[out]","name":"JUMP","source":1},{"begin":417,"end":539,"name":"tag","source":1,"value":"16"},{"begin":417,"end":539,"name":"JUMPDEST","source":1},{"begin":490,"end":514,"name":"PUSH [tag]","source":1,"value":"25"},{"begin":508,"end":513,"name":"DUP2","source":1},{"begin":490,"end":514,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":490,"end":514,"jumpType":"[in]","name":"JUMP","source":1},{"begin":490,"end":514,"name":"tag","source":1,"value":"25"},{"begin":490,"end":514,"name":"JUMPDEST","source":1},{"begin":483,"end":488,"name":"DUP2","source":1},{"begin":480,"end":515,"name":"EQ","source":1},{"begin":470,"end":533,"name":"PUSH [tag]","source":1,"value":"26"},{"begin":470,"end":533,"name":"JUMPI","source":1},{"begin":529,"end":530,"name":"PUSH","source":1,"value":"0"},{"begin":526,"end":527,"name":"PUSH","source":1,"value":"0"},{"begin":519,"end":531,"name":"REVERT","source":1},{"begin":470,"end":533,"name":"tag","source":1,"value":"26"},{"begin":470,"end":533,"name":"JUMPDEST","source":1},{"begin":417,"end":539,"name":"POP","source":1},{"begin":417,"end":539,"jumpType":"[out]","name":"JUMP","source":1},{"begin":545,"end":684,"name":"tag","source":1,"value":"17"},{"begin":545,"end":684,"name":"JUMPDEST","source":1},{"begin":591,"end":596,"name":"PUSH","source":1,"value":"0"},{"begin":629,"end":635,"name":"DUP2","source":1},{"begin":616,"end":636,"name":"CALLDATALOAD","source":1},{"begin":607,"end":636,"name":"SWAP1","source":1},{"begin":607,"end":636,"name":"POP","source":1},{"begin":645,"end":678,"name":"PUSH [tag]","source":1,"value":"28"},{"begin":672,"end":677,"name":"DUP2","source":1},{"begin":645,"end":678,"name":"PUSH [tag]","source":1,"value":"16"},{"begin":645,"end":678,"jumpType":"[in]","name":"JUMP","source":1},{"begin":645,"end":678,"name":"tag","source":1,"value":"28"},{"begin":645,"end":678,"name":"JUMPDEST","source":1},{"begin":545,"end":684,"name":"SWAP3","source":1},{"begin":545,"end":684,"name":"SWAP2","source":1},{"begin":545,"end":684,"name":"POP","source":1},{"begin":545,"end":684,"name":"POP","source":1},{"begin":545,"end":684,"jumpType":"[out]","name":"JUMP","source":1},{"begin":690,"end":1019,"name":"tag","source":1,"value":"6"},{"begin":690,"end":1019,"name":"JUMPDEST","source":1},{"begin":749,"end":755,"name":"PUSH","source":1,"value":"0"},{"begin":798,"end":800,"name":"PUSH","source":1,"value":"20"},{"begin":786,"end":795,"name":"DUP3","source":1},{"begin":777,"end":784,"name":"DUP5","source":1},{"begin":773,"end":796,"name":"SUB","source":1},{"begin":769,"end":801,"name":"SLT","source":1},{"begin":766,"end":885,"name":"ISZERO","source":1},{"begin":766,"end":885,"name":"PUSH [tag]","source":1,"value":"30"},{"begin":766,"end":885,"name":"JUMPI","source":1},{"begin":804,"end":883,"name":"PUSH [tag]","source":1,"value":"31"},{"begin":804,"end":883,"name":"PUSH [tag]","source":1,"value":"13"},{"begin":804,"end":883,"jumpType":"[in]","name":"JUMP","source":1},{"begin":804,"end":883,"name":"tag","source":1,"value":"31"},{"begin":804,"end":883,"name":"JUMPDEST","source":1},{"begin":766,"end":885,"name":"tag","source":1,"value":"30"},{"begin":766,"end":885,"name":"JUMPDEST","source":1},{"begin":924,"end":925,"name":"PUSH","source":1,"value":"0"},{"begin":949,"end":1002,"name":"PUSH [tag]","source":1,"value":"32"},{"begin":994,"end":1001,"name":"DUP5","source":1},{"begin":985,"end":991,"name":"DUP3","source":1},{"begin":974,"end":983,"name":"DUP6","source":1},{"begin":970,"end":992,"name":"ADD","source":1},{"begin":949,"end":1002,"name":"PUSH [tag]","source":1,"value":"17"},{"begin":949,"end":1002,"jumpType":"[in]","name":"JUMP","source":1},{"begin":949,"end":1002,"name":"tag","source":1,"value":"32"},{"begin":949,"end":1002,"name":"JUMPDEST","source":1},{"begin":939,"end":1002,"name":"SWAP2","source":1},{"begin":939,"end":1002,"name":"POP","source":1},{"begin":895,"end":1012,"name":"POP","source":1},{"begin":690,"end":1019,"name":"SWAP3","source":1},{"begin":690,"end":1019,"name":"SWAP2","source":1},{"begin":690,"end":1019,"name":"POP","source":1},{"begin":690,"end":1019,"name":"POP","source":1},{"begin":690,"end":1019,"jumpType":"[out]","name":"JUMP","source":1},{"begin":1025,"end":1205,"name":"tag","source":1,"value":"18"},{"begin":1025,"end":1205,"name":"JUMPDEST","source":1},{"begin":1073,"end":1150,"name":"PUSH","source":1,"value":"4E487B7100000000000000000000000000000000000000000000000000000000"},{"begin":1070,"end":1071,"name":"PUSH","source":1,"value":"0"},{"begin":1063,"end":1151,"name":"MSTORE","source":1},{"begin":1170,"end":1174,"name":"PUSH","source":1,"value":"11"},{"begin":1167,"end":1168,"name":"PUSH","source":1,"value":"4"},{"begin":1160,"end":1175,"name":"MSTORE","source":1},{"begin":1194,"end":1198,"name":"PUSH","source":1,"value":"24"},{"begin":1191,"end":1192,"name":"PUSH","source":1,"value":"0"},{"begin":1184,"end":1199,"name":"REVERT","source":1},{"begin":1211,"end":1402,"name":"tag","source":1,"value":"10"},{"begin":1211,"end":1402,"name":"JUMPDEST","source":1},{"begin":1251,"end":1254,"name":"PUSH","source":1,"value":"0"},{"begin":1270,"end":1290,"name":"PUSH [tag]","source":1,"value":"35"},{"begin":1288,"end":1289,"name":"DUP3","source":1},{"begin":1270,"end":1290,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":1270,"end":1290,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1270,"end":1290,"name":"tag","source":1,"value":"35"},{"begin":1270,"end":1290,"name":"JUMPDEST","source":1},{"begin":1265,"end":1290,"name":"SWAP2","source":1},{"begin":1265,"end":1290,"name":"POP","source":1},{"begin":1304,"end":1324,"name":"PUSH [tag]","source":1,"value":"36"},{"begin":1322,"end":1323,"name":"DUP4","source":1},{"begin":1304,"end":1324,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":1304,"end":1324,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1304,"end":1324,"name":"tag","source":1,"value":"36"},{"begin":1304,"end":1324,"name":"JUMPDEST","source":1},{"begin":1299,"end":1324,"name":"SWAP3","source":1},{"begin":1299,"end":1324,"name":"POP","source":1},{"begin":1347,"end":1348,"name":"DUP3","source":1},{"begin":1344,"end":1345,"name":"DUP3","source":1},{"begin":1340,"end":1349,"name":"ADD","source":1},{"begin":1333,"end":1349,"name":"SWAP1","source":1},{"begin":1333,"end":1349,"name":"POP","source":1},{"begin":1368,"end":1371,"name":"DUP1","source":1},{"begin":1365,"end":1366,"name":"DUP3","source":1},{"begin":1362,"end":1372,"name":"GT","source":1},{"begin":1359,"end":1395,"name":"ISZERO","source":1},{"begin":1359,"end":1395,"name":"PUSH [tag]","source":1,"value":"37"},{"begin":1359,"end":1395,"name":"JUMPI","source":1},{"begin":1375,"end":1393,"name":"PUSH [tag]","source":1,"value":"38"},{"begin":1375,"end":1393,"name":"PUSH [tag]","source":1,"value":"18"},{"begin":1375,"end":1393,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1375,"end":1393,"name":"tag","source":1,"value":"38"},{"begin":1375,"end":1393,"name":"JUMPDEST","source":1},{"begin":1359,"end":1395,"name":"tag","source":1,"value":"37"},{"begin":1359,"end":1395,"name":"JUMPDEST","source":1},{"begin":1211,"end":1402,"name":"SWAP3","source":1},{"begin":1211,"end":1402,"name":"SWAP2","source":1},{"begin":1211,"end":1402,"name":"POP","source":1},{"begin":1211,"end":1402,"name":"POP","source":1},{"begin":1211,"end":1402,"jumpType":"[out]","name":"JUMP","source":1}]}},"sourceList":["asm_json_no_pretty_print/input.sol","#utility.yul"]} +{".code":[{"begin":60,"end":160,"name":"PUSH","source":0,"value":"80"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"40"},{"begin":60,"end":160,"name":"MSTORE","source":0},{"begin":60,"end":160,"name":"CALLVALUE","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"ISZERO","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"POP","source":0},{"begin":60,"end":160,"name":"PUSH #[$]","source":0,"value":"0000000000000000000000000000000000000000000000000000000000000000"},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"PUSH [$]","source":0,"value":"0000000000000000000000000000000000000000000000000000000000000000"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"CODECOPY","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"RETURN","source":0}],".data":{"0":{".auxdata":"",".code":[{"begin":60,"end":160,"name":"PUSH","source":0,"value":"80"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"40"},{"begin":60,"end":160,"name":"MSTORE","source":0},{"begin":60,"end":160,"name":"CALLVALUE","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"ISZERO","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"1"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"POP","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"4"},{"begin":60,"end":160,"name":"CALLDATASIZE","source":0},{"begin":60,"end":160,"name":"LT","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"2"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"CALLDATALOAD","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"E0"},{"begin":60,"end":160,"name":"SHR","source":0},{"begin":60,"end":160,"name":"DUP1","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"B3DE648B"},{"begin":60,"end":160,"name":"EQ","source":0},{"begin":60,"end":160,"name":"PUSH [tag]","source":0,"value":"3"},{"begin":60,"end":160,"name":"JUMPI","source":0},{"begin":60,"end":160,"name":"tag","source":0,"value":"2"},{"begin":60,"end":160,"name":"JUMPDEST","source":0},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"PUSH","source":0,"value":"0"},{"begin":60,"end":160,"name":"REVERT","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"3"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"4"},{"begin":77,"end":158,"name":"PUSH","source":0,"value":"4"},{"begin":77,"end":158,"name":"DUP1","source":0},{"begin":77,"end":158,"name":"CALLDATASIZE","source":0},{"begin":77,"end":158,"name":"SUB","source":0},{"begin":77,"end":158,"name":"DUP2","source":0},{"begin":77,"end":158,"name":"ADD","source":0},{"begin":77,"end":158,"name":"SWAP1","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"5"},{"begin":77,"end":158,"name":"SWAP2","source":0},{"begin":77,"end":158,"name":"SWAP1","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"6"},{"begin":77,"end":158,"jumpType":"[in]","name":"JUMP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"5"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"PUSH [tag]","source":0,"value":"7"},{"begin":77,"end":158,"jumpType":"[in]","name":"JUMP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"4"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"STOP","source":0},{"begin":77,"end":158,"name":"tag","source":0,"value":"7"},{"begin":77,"end":158,"name":"JUMPDEST","source":0},{"begin":123,"end":125,"name":"PUSH","source":0,"value":"2A"},{"begin":118,"end":125,"name":"DUP2","source":0},{"begin":118,"end":125,"name":"PUSH [tag]","source":0,"value":"9"},{"begin":118,"end":125,"name":"SWAP2","source":0},{"begin":118,"end":125,"name":"SWAP1","source":0},{"begin":118,"end":125,"name":"PUSH [tag]","source":0,"value":"10"},{"begin":118,"end":125,"jumpType":"[in]","name":"JUMP","source":0},{"begin":118,"end":125,"name":"tag","source":0,"value":"9"},{"begin":118,"end":125,"name":"JUMPDEST","source":0},{"begin":118,"end":125,"name":"SWAP1","source":0},{"begin":118,"end":125,"name":"POP","source":0},{"begin":147,"end":150,"name":"PUSH","source":0,"value":"64"},{"begin":143,"end":144,"name":"DUP2","source":0},{"begin":143,"end":150,"name":"GT","source":0},{"begin":135,"end":151,"name":"PUSH [tag]","source":0,"value":"11"},{"begin":135,"end":151,"name":"JUMPI","source":0},{"begin":135,"end":151,"name":"PUSH","source":0,"value":"0"},{"begin":135,"end":151,"name":"PUSH","source":0,"value":"0"},{"begin":135,"end":151,"name":"REVERT","source":0},{"begin":135,"end":151,"name":"tag","source":0,"value":"11"},{"begin":135,"end":151,"name":"JUMPDEST","source":0},{"begin":77,"end":158,"name":"POP","source":0},{"begin":77,"end":158,"jumpType":"[out]","name":"JUMP","source":0},{"begin":88,"end":205,"name":"tag","source":1,"value":"13"},{"begin":88,"end":205,"name":"JUMPDEST","source":1},{"begin":197,"end":198,"name":"PUSH","source":1,"value":"0"},{"begin":194,"end":195,"name":"PUSH","source":1,"value":"0"},{"begin":187,"end":199,"name":"REVERT","source":1},{"begin":334,"end":411,"name":"tag","source":1,"value":"15"},{"begin":334,"end":411,"name":"JUMPDEST","source":1},{"begin":371,"end":378,"name":"PUSH","source":1,"value":"0"},{"begin":400,"end":405,"name":"DUP2","source":1},{"begin":389,"end":405,"name":"SWAP1","source":1},{"begin":389,"end":405,"name":"POP","source":1},{"begin":334,"end":411,"name":"SWAP2","source":1},{"begin":334,"end":411,"name":"SWAP1","source":1},{"begin":334,"end":411,"name":"POP","source":1},{"begin":334,"end":411,"jumpType":"[out]","name":"JUMP","source":1},{"begin":417,"end":539,"name":"tag","source":1,"value":"16"},{"begin":417,"end":539,"name":"JUMPDEST","source":1},{"begin":490,"end":514,"name":"PUSH [tag]","source":1,"value":"25"},{"begin":508,"end":513,"name":"DUP2","source":1},{"begin":490,"end":514,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":490,"end":514,"jumpType":"[in]","name":"JUMP","source":1},{"begin":490,"end":514,"name":"tag","source":1,"value":"25"},{"begin":490,"end":514,"name":"JUMPDEST","source":1},{"begin":483,"end":488,"name":"DUP2","source":1},{"begin":480,"end":515,"name":"EQ","source":1},{"begin":470,"end":533,"name":"PUSH [tag]","source":1,"value":"26"},{"begin":470,"end":533,"name":"JUMPI","source":1},{"begin":529,"end":530,"name":"PUSH","source":1,"value":"0"},{"begin":526,"end":527,"name":"PUSH","source":1,"value":"0"},{"begin":519,"end":531,"name":"REVERT","source":1},{"begin":470,"end":533,"name":"tag","source":1,"value":"26"},{"begin":470,"end":533,"name":"JUMPDEST","source":1},{"begin":417,"end":539,"name":"POP","source":1},{"begin":417,"end":539,"jumpType":"[out]","name":"JUMP","source":1},{"begin":545,"end":684,"name":"tag","source":1,"value":"17"},{"begin":545,"end":684,"name":"JUMPDEST","source":1},{"begin":591,"end":596,"name":"PUSH","source":1,"value":"0"},{"begin":629,"end":635,"name":"DUP2","source":1},{"begin":616,"end":636,"name":"CALLDATALOAD","source":1},{"begin":607,"end":636,"name":"SWAP1","source":1},{"begin":607,"end":636,"name":"POP","source":1},{"begin":645,"end":678,"name":"PUSH [tag]","source":1,"value":"28"},{"begin":672,"end":677,"name":"DUP2","source":1},{"begin":645,"end":678,"name":"PUSH [tag]","source":1,"value":"16"},{"begin":645,"end":678,"jumpType":"[in]","name":"JUMP","source":1},{"begin":645,"end":678,"name":"tag","source":1,"value":"28"},{"begin":645,"end":678,"name":"JUMPDEST","source":1},{"begin":545,"end":684,"name":"SWAP3","source":1},{"begin":545,"end":684,"name":"SWAP2","source":1},{"begin":545,"end":684,"name":"POP","source":1},{"begin":545,"end":684,"name":"POP","source":1},{"begin":545,"end":684,"jumpType":"[out]","name":"JUMP","source":1},{"begin":690,"end":1019,"name":"tag","source":1,"value":"6"},{"begin":690,"end":1019,"name":"JUMPDEST","source":1},{"begin":749,"end":755,"name":"PUSH","source":1,"value":"0"},{"begin":798,"end":800,"name":"PUSH","source":1,"value":"20"},{"begin":786,"end":795,"name":"DUP3","source":1},{"begin":777,"end":784,"name":"DUP5","source":1},{"begin":773,"end":796,"name":"SUB","source":1},{"begin":769,"end":801,"name":"SLT","source":1},{"begin":766,"end":885,"name":"ISZERO","source":1},{"begin":766,"end":885,"name":"PUSH [tag]","source":1,"value":"30"},{"begin":766,"end":885,"name":"JUMPI","source":1},{"begin":804,"end":883,"name":"PUSH [tag]","source":1,"value":"31"},{"begin":804,"end":883,"name":"PUSH [tag]","source":1,"value":"13"},{"begin":804,"end":883,"jumpType":"[in]","name":"JUMP","source":1},{"begin":804,"end":883,"name":"tag","source":1,"value":"31"},{"begin":804,"end":883,"name":"JUMPDEST","source":1},{"begin":766,"end":885,"name":"tag","source":1,"value":"30"},{"begin":766,"end":885,"name":"JUMPDEST","source":1},{"begin":924,"end":925,"name":"PUSH","source":1,"value":"0"},{"begin":949,"end":1002,"name":"PUSH [tag]","source":1,"value":"32"},{"begin":994,"end":1001,"name":"DUP5","source":1},{"begin":985,"end":991,"name":"DUP3","source":1},{"begin":974,"end":983,"name":"DUP6","source":1},{"begin":970,"end":992,"name":"ADD","source":1},{"begin":949,"end":1002,"name":"PUSH [tag]","source":1,"value":"17"},{"begin":949,"end":1002,"jumpType":"[in]","name":"JUMP","source":1},{"begin":949,"end":1002,"name":"tag","source":1,"value":"32"},{"begin":949,"end":1002,"name":"JUMPDEST","source":1},{"begin":939,"end":1002,"name":"SWAP2","source":1},{"begin":939,"end":1002,"name":"POP","source":1},{"begin":895,"end":1012,"name":"POP","source":1},{"begin":690,"end":1019,"name":"SWAP3","source":1},{"begin":690,"end":1019,"name":"SWAP2","source":1},{"begin":690,"end":1019,"name":"POP","source":1},{"begin":690,"end":1019,"name":"POP","source":1},{"begin":690,"end":1019,"jumpType":"[out]","name":"JUMP","source":1},{"begin":1025,"end":1205,"name":"tag","source":1,"value":"18"},{"begin":1025,"end":1205,"name":"JUMPDEST","source":1},{"begin":1073,"end":1150,"name":"PUSH","source":1,"value":"4E487B7100000000000000000000000000000000000000000000000000000000"},{"begin":1070,"end":1071,"name":"PUSH","source":1,"value":"0"},{"begin":1063,"end":1151,"name":"MSTORE","source":1},{"begin":1170,"end":1174,"name":"PUSH","source":1,"value":"11"},{"begin":1167,"end":1168,"name":"PUSH","source":1,"value":"4"},{"begin":1160,"end":1175,"name":"MSTORE","source":1},{"begin":1194,"end":1198,"name":"PUSH","source":1,"value":"24"},{"begin":1191,"end":1192,"name":"PUSH","source":1,"value":"0"},{"begin":1184,"end":1199,"name":"REVERT","source":1},{"begin":1211,"end":1402,"name":"tag","source":1,"value":"10"},{"begin":1211,"end":1402,"name":"JUMPDEST","source":1},{"begin":1251,"end":1254,"name":"PUSH","source":1,"value":"0"},{"begin":1270,"end":1290,"name":"PUSH [tag]","source":1,"value":"35"},{"begin":1288,"end":1289,"name":"DUP3","source":1},{"begin":1270,"end":1290,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":1270,"end":1290,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1270,"end":1290,"name":"tag","source":1,"value":"35"},{"begin":1270,"end":1290,"name":"JUMPDEST","source":1},{"begin":1265,"end":1290,"name":"SWAP2","source":1},{"begin":1265,"end":1290,"name":"POP","source":1},{"begin":1304,"end":1324,"name":"PUSH [tag]","source":1,"value":"36"},{"begin":1322,"end":1323,"name":"DUP4","source":1},{"begin":1304,"end":1324,"name":"PUSH [tag]","source":1,"value":"15"},{"begin":1304,"end":1324,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1304,"end":1324,"name":"tag","source":1,"value":"36"},{"begin":1304,"end":1324,"name":"JUMPDEST","source":1},{"begin":1299,"end":1324,"name":"SWAP3","source":1},{"begin":1299,"end":1324,"name":"POP","source":1},{"begin":1347,"end":1348,"name":"DUP3","source":1},{"begin":1344,"end":1345,"name":"DUP3","source":1},{"begin":1340,"end":1349,"name":"ADD","source":1},{"begin":1333,"end":1349,"name":"SWAP1","source":1},{"begin":1333,"end":1349,"name":"POP","source":1},{"begin":1368,"end":1371,"name":"DUP1","source":1},{"begin":1365,"end":1366,"name":"DUP3","source":1},{"begin":1362,"end":1372,"name":"GT","source":1},{"begin":1359,"end":1395,"name":"ISZERO","source":1},{"begin":1359,"end":1395,"name":"PUSH [tag]","source":1,"value":"37"},{"begin":1359,"end":1395,"name":"JUMPI","source":1},{"begin":1375,"end":1393,"name":"PUSH [tag]","source":1,"value":"38"},{"begin":1375,"end":1393,"name":"PUSH [tag]","source":1,"value":"18"},{"begin":1375,"end":1393,"jumpType":"[in]","name":"JUMP","source":1},{"begin":1375,"end":1393,"name":"tag","source":1,"value":"38"},{"begin":1375,"end":1393,"name":"JUMPDEST","source":1},{"begin":1359,"end":1395,"name":"tag","source":1,"value":"37"},{"begin":1359,"end":1395,"name":"JUMPDEST","source":1},{"begin":1211,"end":1402,"name":"SWAP3","source":1},{"begin":1211,"end":1402,"name":"SWAP2","source":1},{"begin":1211,"end":1402,"name":"POP","source":1},{"begin":1211,"end":1402,"name":"POP","source":1},{"begin":1211,"end":1402,"jumpType":"[out]","name":"JUMP","source":1}]}},"sourceList":["input.sol","#utility.yul"]} diff --git a/test/cmdlineTests/ast_compact_json_no_pretty_json/output b/test/cmdlineTests/ast_compact_json_no_pretty_json/output index fb79fd524..43806c055 100644 --- a/test/cmdlineTests/ast_compact_json_no_pretty_json/output +++ b/test/cmdlineTests/ast_compact_json_no_pretty_json/output @@ -1,5 +1,5 @@ JSON AST (compact format): -======= ast_compact_json_no_pretty_json/input.sol ======= -{"absolutePath":"ast_compact_json_no_pretty_json/input.sol","exportedSymbols":{"C":[2]},"id":3,"license":"GPL-3.0","nodeType":"SourceUnit","nodes":[{"id":1,"literals":["solidity",">=","0.0"],"nodeType":"PragmaDirective","src":"36:22:0"},{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":2,"linearizedBaseContracts":[2],"name":"C","nameLocation":"69:1:0","nodeType":"ContractDefinition","nodes":[],"scope":3,"src":"60:13:0","usedErrors":[],"usedEvents":[]}],"src":"36:38:0"} +======= input.sol ======= +{"absolutePath":"input.sol","exportedSymbols":{"C":[2]},"id":3,"license":"GPL-3.0","nodeType":"SourceUnit","nodes":[{"id":1,"literals":["solidity",">=","0.0"],"nodeType":"PragmaDirective","src":"36:22:0"},{"abstract":false,"baseContracts":[],"canonicalName":"C","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":2,"linearizedBaseContracts":[2],"name":"C","nameLocation":"69:1:0","nodeType":"ContractDefinition","nodes":[],"scope":3,"src":"60:13:0","usedErrors":[],"usedEvents":[]}],"src":"36:38:0"} diff --git a/test/cmdlineTests/ast_compact_json_storage_layout_specifier/output b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/output index 4fe5fe193..994286c3b 100644 --- a/test/cmdlineTests/ast_compact_json_storage_layout_specifier/output +++ b/test/cmdlineTests/ast_compact_json_storage_layout_specifier/output @@ -1,9 +1,9 @@ JSON AST (compact format): -======= ast_compact_json_storage_layout_specifier/input.sol ======= +======= input.sol ======= { - "absolutePath": "ast_compact_json_storage_layout_specifier/input.sol", + "absolutePath": "input.sol", "exportedSymbols": { "C": [ 6 diff --git a/test/cmdlineTests/ast_compact_json_with_base_path/output b/test/cmdlineTests/ast_compact_json_with_base_path/output index c61502020..93f7df253 100644 --- a/test/cmdlineTests/ast_compact_json_with_base_path/output +++ b/test/cmdlineTests/ast_compact_json_with_base_path/output @@ -1,9 +1,9 @@ JSON AST (compact format): -======= ast_compact_json_with_base_path/c.sol ======= +======= c.sol ======= { - "absolutePath": "ast_compact_json_with_base_path/c.sol", + "absolutePath": "c.sol", "exportedSymbols": { "C": [ 5 @@ -46,9 +46,9 @@ JSON AST (compact format): ], "src": "36:38:0" } -======= ast_compact_json_with_base_path/input.sol ======= +======= input.sol ======= { - "absolutePath": "ast_compact_json_with_base_path/input.sol", + "absolutePath": "input.sol", "exportedSymbols": { "C": [ 5 @@ -69,7 +69,7 @@ JSON AST (compact format): "src": "36:22:1" }, { - "absolutePath": "ast_compact_json_with_base_path/c.sol", + "absolutePath": "c.sol", "file": "./c.sol", "id": 2, "nameLocation": "-1:-1:-1", diff --git a/test/cmdlineTests/ast_ir/output b/test/cmdlineTests/ast_ir/output index 76f111990..88047ade0 100644 --- a/test/cmdlineTests/ast_ir/output +++ b/test/cmdlineTests/ast_ir/output @@ -2,7 +2,7 @@ IR AST: { "code": { "block": { - "nativeSrc": "59:790:0", + "nativeSrc": "52:790:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -11,7 +11,7 @@ IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "118:2:0", + "nativeSrc": "111:2:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -21,7 +21,7 @@ IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "134:3:0", + "nativeSrc": "127:3:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -30,32 +30,32 @@ IR AST: ], "functionName": { "name": "memoryguard", - "nativeSrc": "122:11:0", + "nativeSrc": "115:11:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "122:16:0", + "nativeSrc": "115:16:0", "nodeType": "YulFunctionCall", "src": "60:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "111:6:0", + "nativeSrc": "104:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "111:28:0", + "nativeSrc": "104:28:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "111:28:0", + "nativeSrc": "104:28:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, { "body": { - "nativeSrc": "163:83:0", + "nativeSrc": "156:83:0", "nodeType": "YulBlock", "src": "60:13:0", "statements": [ @@ -64,15 +64,15 @@ IR AST: "arguments": [], "functionName": { "name": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "nativeSrc": "165:77:0", + "nativeSrc": "158:77:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "165:79:0", + "nativeSrc": "158:79:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "165:79:0", + "nativeSrc": "158:79:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } @@ -82,15 +82,15 @@ IR AST: "arguments": [], "functionName": { "name": "callvalue", - "nativeSrc": "151:9:0", + "nativeSrc": "144:9:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "151:11:0", + "nativeSrc": "144:11:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "148:98:0", + "nativeSrc": "141:98:0", "nodeType": "YulIf", "src": "60:13:0" }, @@ -99,38 +99,38 @@ IR AST: "arguments": [], "functionName": { "name": "constructor_C_2", - "nativeSrc": "256:15:0", + "nativeSrc": "249:15:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "256:17:0", + "nativeSrc": "249:17:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "256:17:0", + "nativeSrc": "249:17:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, { - "nativeSrc": "283:30:0", + "nativeSrc": "276:30:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", "value": { "arguments": [], "functionName": { "name": "allocate_unbounded", - "nativeSrc": "293:18:0", + "nativeSrc": "286:18:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "293:20:0", + "nativeSrc": "286:20:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variables": [ { "name": "_1", - "nativeSrc": "287:2:0", + "nativeSrc": "280:2:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -142,7 +142,7 @@ IR AST: "arguments": [ { "name": "_1", - "nativeSrc": "331:2:0", + "nativeSrc": "324:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, @@ -151,7 +151,7 @@ IR AST: { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "346:14:0", + "nativeSrc": "339:14:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -160,11 +160,11 @@ IR AST: ], "functionName": { "name": "dataoffset", - "nativeSrc": "335:10:0", + "nativeSrc": "328:10:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "335:26:0", + "nativeSrc": "328:26:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, @@ -173,7 +173,7 @@ IR AST: { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "372:14:0", + "nativeSrc": "365:14:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -182,26 +182,26 @@ IR AST: ], "functionName": { "name": "datasize", - "nativeSrc": "363:8:0", + "nativeSrc": "356:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "363:24:0", + "nativeSrc": "356:24:0", "nodeType": "YulFunctionCall", "src": "60:13:0" } ], "functionName": { "name": "codecopy", - "nativeSrc": "322:8:0", + "nativeSrc": "315:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "322:66:0", + "nativeSrc": "315:66:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "322:66:0", + "nativeSrc": "315:66:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, @@ -210,7 +210,7 @@ IR AST: "arguments": [ { "name": "_1", - "nativeSrc": "405:2:0", + "nativeSrc": "398:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, @@ -219,7 +219,7 @@ IR AST: { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "418:14:0", + "nativeSrc": "411:14:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -228,44 +228,44 @@ IR AST: ], "functionName": { "name": "datasize", - "nativeSrc": "409:8:0", + "nativeSrc": "402:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "409:24:0", + "nativeSrc": "402:24:0", "nodeType": "YulFunctionCall", "src": "60:13:0" } ], "functionName": { "name": "return", - "nativeSrc": "398:6:0", + "nativeSrc": "391:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "398:36:0", + "nativeSrc": "391:36:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "398:36:0", + "nativeSrc": "391:36:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, { "body": { - "nativeSrc": "484:43:0", + "nativeSrc": "477:43:0", "nodeType": "YulBlock", "src": "60:13:0", "statements": [ { - "nativeSrc": "498:19:0", + "nativeSrc": "491:19:0", "nodeType": "YulAssignment", "src": "60:13:0", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "514:2:0", + "nativeSrc": "507:2:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -274,18 +274,18 @@ IR AST: ], "functionName": { "name": "mload", - "nativeSrc": "508:5:0", + "nativeSrc": "501:5:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "508:9:0", + "nativeSrc": "501:9:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variableNames": [ { "name": "memPtr", - "nativeSrc": "498:6:0", + "nativeSrc": "491:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" } @@ -294,12 +294,12 @@ IR AST: ] }, "name": "allocate_unbounded", - "nativeSrc": "444:83:0", + "nativeSrc": "437:83:0", "nodeType": "YulFunctionDefinition", "returnVariables": [ { "name": "memPtr", - "nativeSrc": "477:6:0", + "nativeSrc": "470:6:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -309,7 +309,7 @@ IR AST: }, { "body": { - "nativeSrc": "626:36:0", + "nativeSrc": "619:36:0", "nodeType": "YulBlock", "src": "60:13:0", "statements": [ @@ -318,7 +318,7 @@ IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "647:1:0", + "nativeSrc": "640:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -326,7 +326,7 @@ IR AST: }, { "kind": "number", - "nativeSrc": "650:1:0", + "nativeSrc": "643:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -335,34 +335,34 @@ IR AST: ], "functionName": { "name": "revert", - "nativeSrc": "640:6:0", + "nativeSrc": "633:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "640:12:0", + "nativeSrc": "633:12:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "640:12:0", + "nativeSrc": "633:12:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } ] }, "name": "revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb", - "nativeSrc": "537:125:0", + "nativeSrc": "530:125:0", "nodeType": "YulFunctionDefinition", "src": "60:13:0" }, { "body": { - "nativeSrc": "741:59:0", + "nativeSrc": "734:59:0", "nodeType": "YulBlock", "src": "60:13:0", "statements": [] }, "name": "constructor_C_2", - "nativeSrc": "714:86:0", + "nativeSrc": "707:86:0", "nodeType": "YulFunctionDefinition", "src": "60:13:0" } @@ -376,7 +376,7 @@ IR AST: { "code": { "block": { - "nativeSrc": "929:588:0", + "nativeSrc": "915:588:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -385,7 +385,7 @@ IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "996:2:0", + "nativeSrc": "982:2:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -395,7 +395,7 @@ IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "1012:3:0", + "nativeSrc": "998:3:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -404,26 +404,26 @@ IR AST: ], "functionName": { "name": "memoryguard", - "nativeSrc": "1000:11:0", + "nativeSrc": "986:11:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "1000:16:0", + "nativeSrc": "986:16:0", "nodeType": "YulFunctionCall", "src": "60:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "989:6:0", + "nativeSrc": "975:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "989:28:0", + "nativeSrc": "975:28:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "989:28:0", + "nativeSrc": "975:28:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, @@ -432,33 +432,33 @@ IR AST: "arguments": [], "functionName": { "name": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", - "nativeSrc": "1031:77:0", + "nativeSrc": "1017:77:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "1031:79:0", + "nativeSrc": "1017:79:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "1031:79:0", + "nativeSrc": "1017:79:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, { "body": { - "nativeSrc": "1177:77:0", + "nativeSrc": "1163:77:0", "nodeType": "YulBlock", "src": "60:13:0", "statements": [ { - "nativeSrc": "1195:44:0", + "nativeSrc": "1181:44:0", "nodeType": "YulAssignment", "src": "60:13:0", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "1228:3:0", + "nativeSrc": "1214:3:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -466,25 +466,25 @@ IR AST: }, { "name": "value", - "nativeSrc": "1233:5:0", + "nativeSrc": "1219:5:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "shr", - "nativeSrc": "1224:3:0", + "nativeSrc": "1210:3:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "1224:15:0", + "nativeSrc": "1210:15:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variableNames": [ { "name": "newValue", - "nativeSrc": "1195:8:0", + "nativeSrc": "1181:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" } @@ -493,12 +493,12 @@ IR AST: ] }, "name": "shift_right_224_unsigned", - "nativeSrc": "1124:130:0", + "nativeSrc": "1110:130:0", "nodeType": "YulFunctionDefinition", "parameters": [ { "name": "value", - "nativeSrc": "1158:5:0", + "nativeSrc": "1144:5:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -507,7 +507,7 @@ IR AST: "returnVariables": [ { "name": "newValue", - "nativeSrc": "1168:8:0", + "nativeSrc": "1154:8:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -517,19 +517,19 @@ IR AST: }, { "body": { - "nativeSrc": "1308:51:0", + "nativeSrc": "1294:51:0", "nodeType": "YulBlock", "src": "60:13:0", "statements": [ { - "nativeSrc": "1326:19:0", + "nativeSrc": "1312:19:0", "nodeType": "YulAssignment", "src": "60:13:0", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "1342:2:0", + "nativeSrc": "1328:2:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -538,18 +538,18 @@ IR AST: ], "functionName": { "name": "mload", - "nativeSrc": "1336:5:0", + "nativeSrc": "1322:5:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "1336:9:0", + "nativeSrc": "1322:9:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variableNames": [ { "name": "memPtr", - "nativeSrc": "1326:6:0", + "nativeSrc": "1312:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" } @@ -558,12 +558,12 @@ IR AST: ] }, "name": "allocate_unbounded", - "nativeSrc": "1268:91:0", + "nativeSrc": "1254:91:0", "nodeType": "YulFunctionDefinition", "returnVariables": [ { "name": "memPtr", - "nativeSrc": "1301:6:0", + "nativeSrc": "1287:6:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -573,7 +573,7 @@ IR AST: }, { "body": { - "nativeSrc": "1462:44:0", + "nativeSrc": "1448:44:0", "nodeType": "YulBlock", "src": "60:13:0", "statements": [ @@ -582,7 +582,7 @@ IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "1487:1:0", + "nativeSrc": "1473:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -590,7 +590,7 @@ IR AST: }, { "kind": "number", - "nativeSrc": "1490:1:0", + "nativeSrc": "1476:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -599,22 +599,22 @@ IR AST: ], "functionName": { "name": "revert", - "nativeSrc": "1480:6:0", + "nativeSrc": "1466:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "1480:12:0", + "nativeSrc": "1466:12:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "1480:12:0", + "nativeSrc": "1466:12:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } ] }, "name": "revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74", - "nativeSrc": "1373:133:0", + "nativeSrc": "1359:133:0", "nodeType": "YulFunctionDefinition", "src": "60:13:0" } @@ -637,24 +637,24 @@ Optimized IR AST: { "code": { "block": { - "nativeSrc": "58:315:0", + "nativeSrc": "51:315:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "68:299:0", + "nativeSrc": "61:299:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "128:27:0", + "nativeSrc": "121:27:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", "value": { "arguments": [ { "kind": "number", - "nativeSrc": "150:4:0", + "nativeSrc": "143:4:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -663,18 +663,18 @@ Optimized IR AST: ], "functionName": { "name": "memoryguard", - "nativeSrc": "138:11:0", + "nativeSrc": "131:11:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "138:17:0", + "nativeSrc": "131:17:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variables": [ { "name": "_1", - "nativeSrc": "132:2:0", + "nativeSrc": "125:2:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -686,7 +686,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "175:2:0", + "nativeSrc": "168:2:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -694,28 +694,28 @@ Optimized IR AST: }, { "name": "_1", - "nativeSrc": "179:2:0", + "nativeSrc": "172:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "mstore", - "nativeSrc": "168:6:0", + "nativeSrc": "161:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "168:14:0", + "nativeSrc": "161:14:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "168:14:0", + "nativeSrc": "161:14:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, { "body": { - "nativeSrc": "210:16:0", + "nativeSrc": "203:16:0", "nodeType": "YulBlock", "src": "60:13:0", "statements": [ @@ -724,7 +724,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "219:1:0", + "nativeSrc": "212:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -732,7 +732,7 @@ Optimized IR AST: }, { "kind": "number", - "nativeSrc": "222:1:0", + "nativeSrc": "215:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -741,15 +741,15 @@ Optimized IR AST: ], "functionName": { "name": "revert", - "nativeSrc": "212:6:0", + "nativeSrc": "205:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "212:12:0", + "nativeSrc": "205:12:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "212:12:0", + "nativeSrc": "205:12:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } @@ -759,20 +759,20 @@ Optimized IR AST: "arguments": [], "functionName": { "name": "callvalue", - "nativeSrc": "198:9:0", + "nativeSrc": "191:9:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "198:11:0", + "nativeSrc": "191:11:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "195:31:0", + "nativeSrc": "188:31:0", "nodeType": "YulIf", "src": "60:13:0" }, { - "nativeSrc": "239:34:0", + "nativeSrc": "232:34:0", "nodeType": "YulVariableDeclaration", "src": "60:13:0", "value": { @@ -780,7 +780,7 @@ Optimized IR AST: { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "258:14:0", + "nativeSrc": "251:14:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -789,18 +789,18 @@ Optimized IR AST: ], "functionName": { "name": "datasize", - "nativeSrc": "249:8:0", + "nativeSrc": "242:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "249:24:0", + "nativeSrc": "242:24:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, "variables": [ { "name": "_2", - "nativeSrc": "243:2:0", + "nativeSrc": "236:2:0", "nodeType": "YulTypedName", "src": "60:13:0", "type": "" @@ -812,7 +812,7 @@ Optimized IR AST: "arguments": [ { "name": "_1", - "nativeSrc": "295:2:0", + "nativeSrc": "288:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, @@ -821,7 +821,7 @@ Optimized IR AST: { "hexValue": "435f325f6465706c6f796564", "kind": "string", - "nativeSrc": "310:14:0", + "nativeSrc": "303:14:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -830,32 +830,32 @@ Optimized IR AST: ], "functionName": { "name": "dataoffset", - "nativeSrc": "299:10:0", + "nativeSrc": "292:10:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "299:26:0", + "nativeSrc": "292:26:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, { "name": "_2", - "nativeSrc": "327:2:0", + "nativeSrc": "320:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "codecopy", - "nativeSrc": "286:8:0", + "nativeSrc": "279:8:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "286:44:0", + "nativeSrc": "279:44:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "286:44:0", + "nativeSrc": "279:44:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" }, @@ -864,28 +864,28 @@ Optimized IR AST: "arguments": [ { "name": "_1", - "nativeSrc": "350:2:0", + "nativeSrc": "343:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, { "name": "_2", - "nativeSrc": "354:2:0", + "nativeSrc": "347:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" } ], "functionName": { "name": "return", - "nativeSrc": "343:6:0", + "nativeSrc": "336:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "343:14:0", + "nativeSrc": "336:14:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "343:14:0", + "nativeSrc": "336:14:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } @@ -901,12 +901,12 @@ Optimized IR AST: { "code": { "block": { - "nativeSrc": "453:118:0", + "nativeSrc": "439:118:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ { - "nativeSrc": "467:94:0", + "nativeSrc": "453:94:0", "nodeType": "YulBlock", "src": "-1:-1:0", "statements": [ @@ -915,7 +915,7 @@ Optimized IR AST: "arguments": [ { "kind": "number", - "nativeSrc": "542:1:0", + "nativeSrc": "528:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -923,7 +923,7 @@ Optimized IR AST: }, { "kind": "number", - "nativeSrc": "545:1:0", + "nativeSrc": "531:1:0", "nodeType": "YulLiteral", "src": "60:13:0", "type": "", @@ -932,15 +932,15 @@ Optimized IR AST: ], "functionName": { "name": "revert", - "nativeSrc": "535:6:0", + "nativeSrc": "521:6:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, - "nativeSrc": "535:12:0", + "nativeSrc": "521:12:0", "nodeType": "YulFunctionCall", "src": "60:13:0" }, - "nativeSrc": "535:12:0", + "nativeSrc": "521:12:0", "nodeType": "YulExpressionStatement", "src": "60:13:0" } diff --git a/test/cmdlineTests/combined_json_abi/output b/test/cmdlineTests/combined_json_abi/output index 79b539db7..ee63ccb3e 100644 --- a/test/cmdlineTests/combined_json_abi/output +++ b/test/cmdlineTests/combined_json_abi/output @@ -1,6 +1,6 @@ { "contracts": { - "combined_json_abi/input.sol:C": { + "input.sol:C": { "abi": [] } }, diff --git a/test/cmdlineTests/combined_json_generated_sources/output b/test/cmdlineTests/combined_json_generated_sources/output index db7c86ce1..d863bd73a 100644 --- a/test/cmdlineTests/combined_json_generated_sources/output +++ b/test/cmdlineTests/combined_json_generated_sources/output @@ -1,6 +1,6 @@ { "contracts": { - "combined_json_generated_sources/input.sol:C": { + "input.sol:C": { "generated-sources": [], "generated-sources-runtime": [ { diff --git a/test/cmdlineTests/combined_json_no_pretty_print/output b/test/cmdlineTests/combined_json_no_pretty_print/output index 081dc4fa4..34c019b8f 100644 --- a/test/cmdlineTests/combined_json_no_pretty_print/output +++ b/test/cmdlineTests/combined_json_no_pretty_print/output @@ -1 +1 @@ -{"contracts":{"combined_json_no_pretty_print/input.sol:C":{"abi":[]}},"version": ""} +{"contracts":{"input.sol:C":{"abi":[]}},"version": ""} diff --git a/test/cmdlineTests/combined_json_stop_after_parsing/output b/test/cmdlineTests/combined_json_stop_after_parsing/output index 64e66e3f1..fa3707bf2 100644 --- a/test/cmdlineTests/combined_json_stop_after_parsing/output +++ b/test/cmdlineTests/combined_json_stop_after_parsing/output @@ -1,14 +1,14 @@ { "contracts": { - "combined_json_stop_after_parsing/input.sol:C": {} + "input.sol:C": {} }, "sourceList": [ - "combined_json_stop_after_parsing/input.sol" + "input.sol" ], "sources": { - "combined_json_stop_after_parsing/input.sol": { + "input.sol": { "AST": { - "absolutePath": "combined_json_stop_after_parsing/input.sol", + "absolutePath": "input.sol", "id": 3, "license": "GPL-3.0", "nodeType": "SourceUnit", diff --git a/test/cmdlineTests/combined_json_with_base_path/output b/test/cmdlineTests/combined_json_with_base_path/output index 0a3add37e..fe972a631 100644 --- a/test/cmdlineTests/combined_json_with_base_path/output +++ b/test/cmdlineTests/combined_json_with_base_path/output @@ -1,15 +1,15 @@ { "contracts": { - "combined_json_with_base_path/c.sol:C": {} + "c.sol:C": {} }, "sourceList": [ - "combined_json_with_base_path/c.sol", - "combined_json_with_base_path/input.sol" + "c.sol", + "input.sol" ], "sources": { - "combined_json_with_base_path/c.sol": { + "c.sol": { "AST": { - "absolutePath": "combined_json_with_base_path/c.sol", + "absolutePath": "c.sol", "exportedSymbols": { "C": [ 5 @@ -54,9 +54,9 @@ }, "id": 0 }, - "combined_json_with_base_path/input.sol": { + "input.sol": { "AST": { - "absolutePath": "combined_json_with_base_path/input.sol", + "absolutePath": "input.sol", "exportedSymbols": { "C": [ 5 @@ -77,7 +77,7 @@ "src": "36:22:1" }, { - "absolutePath": "combined_json_with_base_path/c.sol", + "absolutePath": "c.sol", "file": "./c.sol", "id": 2, "nameLocation": "-1:-1:-1", diff --git a/test/cmdlineTests/combined_json_with_devdoc/output b/test/cmdlineTests/combined_json_with_devdoc/output index 817018ea6..482245fbc 100644 --- a/test/cmdlineTests/combined_json_with_devdoc/output +++ b/test/cmdlineTests/combined_json_with_devdoc/output @@ -1,6 +1,6 @@ { "contracts": { - "combined_json_with_devdoc/input.sol:C": { + "input.sol:C": { "devdoc": { "details": "This is devdoc.", "kind": "dev", @@ -8,7 +8,7 @@ "version": 1 } }, - "combined_json_with_devdoc/input.sol:D": { + "input.sol:D": { "devdoc": { "kind": "dev", "methods": {}, diff --git a/test/cmdlineTests/combined_json_with_userdoc/output b/test/cmdlineTests/combined_json_with_userdoc/output index 4eb56fe24..0e28af093 100644 --- a/test/cmdlineTests/combined_json_with_userdoc/output +++ b/test/cmdlineTests/combined_json_with_userdoc/output @@ -1,6 +1,6 @@ { "contracts": { - "combined_json_with_userdoc/input.sol:C": { + "input.sol:C": { "userdoc": { "kind": "user", "methods": {}, @@ -8,7 +8,7 @@ "version": 1 } }, - "combined_json_with_userdoc/input.sol:D": { + "input.sol:D": { "userdoc": { "kind": "user", "methods": {}, diff --git a/test/cmdlineTests/constant_optimizer_yul/output b/test/cmdlineTests/constant_optimizer_yul/output index 9c7faa732..c0d3ab934 100644 --- a/test/cmdlineTests/constant_optimizer_yul/output +++ b/test/cmdlineTests/constant_optimizer_yul/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"constant_optimizer_yul/input.sol" +/// @use-src 0:"input.sol" object "C_12" { code { { @@ -15,7 +15,7 @@ object "C_12" { return(_1, _2) } } - /// @use-src 0:"constant_optimizer_yul/input.sol" + /// @use-src 0:"input.sol" object "C_12_deployed" { code { { diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output index 4833a9f62..7ad569ba1 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output @@ -1,7 +1,7 @@ -======= debug_info_in_yul_and_evm_asm_print_all/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "debug_info_in_yul_and_evm_asm_print_all/input.sol":60:101 contract C {... */ + /* "input.sol":60:101 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -21,7 +21,7 @@ tag_1: stop sub_0: assembly { - /* "debug_info_in_yul_and_evm_asm_print_all/input.sol":60:101 contract C {... */ + /* "input.sol":60:101 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -40,7 +40,7 @@ sub_0: assembly { jumpi tag_2: revert(0x00, 0x00) - /* "debug_info_in_yul_and_evm_asm_print_all/input.sol":77:99 function f() public {} */ + /* "input.sol":77:99 function f() public {} */ tag_3: stop @@ -49,7 +49,7 @@ sub_0: assembly { IR: -/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_all/input.sol" +/// @use-src 0:"input.sol" object "C_6" { code { /// @src 0:60:101 "contract C {..." @@ -80,7 +80,7 @@ object "C_6" { /// @src 0:60:101 "contract C {..." } - /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_all/input.sol" + /// @use-src 0:"input.sol" object "C_6_deployed" { code { /// @src 0:60:101 "contract C {..." @@ -163,7 +163,7 @@ object "C_6" { Optimized IR: -/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_all/input.sol" +/// @use-src 0:"input.sol" object "C_6" { code { { @@ -176,7 +176,7 @@ object "C_6" { return(_1, _2) } } - /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_all/input.sol" + /// @use-src 0:"input.sol" object "C_6_deployed" { code { { diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output index 00b04a01a..36ef4d829 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output @@ -1,7 +1,7 @@ -======= debug_info_in_yul_and_evm_asm_print_location_only/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "debug_info_in_yul_and_evm_asm_print_location_only/input.sol":60:101 */ + /* "input.sol":60:101 */ mstore(0x40, 0x80) callvalue dup1 @@ -21,7 +21,7 @@ tag_1: stop sub_0: assembly { - /* "debug_info_in_yul_and_evm_asm_print_location_only/input.sol":60:101 */ + /* "input.sol":60:101 */ mstore(0x40, 0x80) callvalue dup1 @@ -40,7 +40,7 @@ sub_0: assembly { jumpi tag_2: revert(0x00, 0x00) - /* "debug_info_in_yul_and_evm_asm_print_location_only/input.sol":77:99 */ + /* "input.sol":77:99 */ tag_3: stop @@ -49,7 +49,7 @@ sub_0: assembly { IR: -/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_location_only/input.sol" +/// @use-src 0:"input.sol" object "C_6" { code { /// @src 0:60:101 @@ -80,7 +80,7 @@ object "C_6" { /// @src 0:60:101 } - /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_location_only/input.sol" + /// @use-src 0:"input.sol" object "C_6_deployed" { code { /// @src 0:60:101 @@ -162,7 +162,7 @@ object "C_6" { Optimized IR: -/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_location_only/input.sol" +/// @use-src 0:"input.sol" object "C_6" { code { { @@ -175,7 +175,7 @@ object "C_6" { return(_1, _2) } } - /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_location_only/input.sol" + /// @use-src 0:"input.sol" object "C_6_deployed" { code { { diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output index 9527edf76..ea3cb35a2 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output @@ -1,5 +1,5 @@ -======= debug_info_in_yul_and_evm_asm_print_none/input.sol:C ======= +======= input.sol:C ======= EVM assembly: mstore(0x40, 0x80) callvalue @@ -46,7 +46,7 @@ sub_0: assembly { IR: -/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_none/input.sol" +/// @use-src 0:"input.sol" object "C_6" { code { @@ -73,7 +73,7 @@ object "C_6" { } } - /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_none/input.sol" + /// @use-src 0:"input.sol" object "C_6_deployed" { code { @@ -153,7 +153,7 @@ object "C_6" { Optimized IR: -/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_none/input.sol" +/// @use-src 0:"input.sol" object "C_6" { code { { @@ -165,7 +165,7 @@ object "C_6" { return(_1, _2) } } - /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_none/input.sol" + /// @use-src 0:"input.sol" object "C_6_deployed" { code { { diff --git a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output index 975582f66..c29dfd892 100644 --- a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output +++ b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output @@ -1,6 +1,6 @@ IR: -/// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" +/// @use-src 0:"input.sol" object "C_2" { code { /// @src 0:265:278 "contract C {}" @@ -31,7 +31,7 @@ object "C_2" { /// @src 0:265:278 "contract C {}" } - /// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" + /// @use-src 0:"input.sol" object "C_2_deployed" { code { /// @src 0:265:278 "contract C {}" @@ -63,7 +63,7 @@ object "C_2" { Optimized IR: -/// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" +/// @use-src 0:"input.sol" object "C_2" { code { { @@ -76,7 +76,7 @@ object "C_2" { return(_1, _2) } } - /// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" + /// @use-src 0:"input.sol" object "C_2_deployed" { code { { @@ -90,7 +90,7 @@ object "C_2" { IR: -/// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" +/// @use-src 0:"input.sol" object "D_27" { code { /// @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." @@ -121,7 +121,7 @@ object "D_27" { /// @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." } - /// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" + /// @use-src 0:"input.sol" object "D_27_deployed" { code { /// @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." @@ -342,7 +342,7 @@ object "D_27" { } - /// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" + /// @use-src 0:"input.sol" object "C_2" { code { /// @src 0:265:278 "contract C {}" @@ -373,7 +373,7 @@ object "D_27" { /// @src 0:265:278 "contract C {}" } - /// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" + /// @use-src 0:"input.sol" object "C_2_deployed" { code { /// @src 0:265:278 "contract C {}" @@ -410,7 +410,7 @@ object "D_27" { Optimized IR: -/// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" +/// @use-src 0:"input.sol" object "D_27" { code { { @@ -423,7 +423,7 @@ object "D_27" { return(_1, _2) } } - /// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" + /// @use-src 0:"input.sol" object "D_27_deployed" { code { { @@ -499,7 +499,7 @@ object "D_27" { revert(0, 0) } } - /// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" + /// @use-src 0:"input.sol" object "C_2" { code { { @@ -512,7 +512,7 @@ object "D_27" { return(_1, _2) } } - /// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" + /// @use-src 0:"input.sol" object "C_2_deployed" { code { { diff --git a/test/cmdlineTests/dup_opt_peephole/output b/test/cmdlineTests/dup_opt_peephole/output index a9e0203ed..f53e9e2bd 100644 --- a/test/cmdlineTests/dup_opt_peephole/output +++ b/test/cmdlineTests/dup_opt_peephole/output @@ -1,7 +1,7 @@ -======= dup_opt_peephole/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "dup_opt_peephole/input.sol":60:171 contract C {... */ + /* "input.sol":60:171 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -21,7 +21,7 @@ tag_1: stop sub_0: assembly { - /* "dup_opt_peephole/input.sol":60:171 contract C {... */ + /* "input.sol":60:171 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -31,17 +31,17 @@ sub_0: assembly { revert(0x00, 0x00) tag_3: pop - /* "dup_opt_peephole/input.sol":134:135 0 */ + /* "input.sol":134:135 0 */ 0x00 - /* "dup_opt_peephole/input.sol":121:136 calldataload(0) */ + /* "input.sol":121:136 calldataload(0) */ calldataload - /* "dup_opt_peephole/input.sol":160:161 x */ + /* "input.sol":160:161 x */ dup1 - /* "dup_opt_peephole/input.sol":157:158 0 */ + /* "input.sol":157:158 0 */ 0x00 - /* "dup_opt_peephole/input.sol":150:162 sstore(0, x) */ + /* "input.sol":150:162 sstore(0, x) */ sstore - /* "dup_opt_peephole/input.sol":107:166 {... */ + /* "input.sol":107:166 {... */ stop auxdata: diff --git a/test/cmdlineTests/error_codes/err b/test/cmdlineTests/error_codes/err index a10362a86..f3f6fe339 100644 --- a/test/cmdlineTests/error_codes/err +++ b/test/cmdlineTests/error_codes/err @@ -1,29 +1,29 @@ Warning (1878): SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: " to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information. ---> error_codes/input.sol +--> input.sol Error (4937): No visibility specified. Did you intend to add "public"? - --> error_codes/input.sol:2:5: + --> input.sol:2:5: | 2 | function f() { | ^ (Relevant source part starts here and spans across multiple lines). Warning (3420): Source file does not specify required compiler version! ---> error_codes/input.sol +--> input.sol Error (4247): Expression has to be an lvalue. - --> error_codes/input.sol:3:9: + --> input.sol:3:9: | 3 | 2=0; | ^ Error (7407): Type int_const 0 is not implicitly convertible to expected type int_const 2. - --> error_codes/input.sol:3:11: + --> input.sol:3:11: | 3 | 2=0; | ^ Error (2614): Indexed expression has to be a type, mapping or array (is literal_string "") - --> error_codes/input.sol:4:9: + --> input.sol:4:9: | 4 | ""[2]; | ^^ diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/output b/test/cmdlineTests/ethdebug_eof_container_osaka/output index 9d002fadc..b29297ee3 100644 --- a/test/cmdlineTests/ethdebug_eof_container_osaka/output +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/output @@ -1,4 +1,4 @@ ======= Debug Data (ethdebug/format/info/resources) ======= -{"compilation":{"compiler":{"name":"solc","version": ""},"sources":[{"id":0,"path":"ethdebug_eof_container_osaka/input.sol"}]}} +{"compilation":{"compiler":{"name":"solc","version": ""},"sources":[{"id":0,"path":"input.sol"}]}} -======= ethdebug_eof_container_osaka/input.sol:C ======= +======= input.sol:C ======= diff --git a/test/cmdlineTests/events_in_abi/output b/test/cmdlineTests/events_in_abi/output index ab246ef24..220e65ef4 100644 --- a/test/cmdlineTests/events_in_abi/output +++ b/test/cmdlineTests/events_in_abi/output @@ -1,5 +1,5 @@ -======= events_in_abi/input.sol:C ======= +======= input.sol:C ======= Contract JSON ABI [ { @@ -37,7 +37,7 @@ Contract JSON ABI } ] -======= events_in_abi/input.sol:L ======= +======= input.sol:L ======= Contract JSON ABI [ { diff --git a/test/cmdlineTests/evm_version_byzantium/err b/test/cmdlineTests/evm_version_byzantium/err index accbb596c..6815a8524 100644 --- a/test/cmdlineTests/evm_version_byzantium/err +++ b/test/cmdlineTests/evm_version_byzantium/err @@ -1,3 +1,3 @@ Warning: Support for EVM versions older than constantinople is deprecated and will be removed in the future. Warning: Source file does not specify required compiler version! ---> evm_version_byzantium/input.sol +--> input.sol diff --git a/test/cmdlineTests/evm_version_constantinople/err b/test/cmdlineTests/evm_version_constantinople/err index 69f328f54..e3815925a 100644 --- a/test/cmdlineTests/evm_version_constantinople/err +++ b/test/cmdlineTests/evm_version_constantinople/err @@ -1,2 +1,2 @@ Warning: Source file does not specify required compiler version! ---> evm_version_constantinople/input.sol +--> input.sol diff --git a/test/cmdlineTests/evmasm_difficulty_post_paris/err b/test/cmdlineTests/evmasm_difficulty_post_paris/err index d8210184e..8498f4c46 100644 --- a/test/cmdlineTests/evmasm_difficulty_post_paris/err +++ b/test/cmdlineTests/evmasm_difficulty_post_paris/err @@ -1,5 +1,5 @@ Warning: Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. - --> evmasm_difficulty_post_paris/input.sol:6:21: + --> input.sol:6:21: | 6 | uint256 x = block.difficulty; | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/evmasm_difficulty_post_paris/output b/test/cmdlineTests/evmasm_difficulty_post_paris/output index f8c1611e0..6ade453b9 100644 --- a/test/cmdlineTests/evmasm_difficulty_post_paris/output +++ b/test/cmdlineTests/evmasm_difficulty_post_paris/output @@ -1,5 +1,5 @@ -======= evmasm_difficulty_post_paris/input.sol:C ======= +======= input.sol:C ======= EVM assembly: sstore(0x00, prevrandao) stop diff --git a/test/cmdlineTests/evmasm_difficulty_pre_paris/output b/test/cmdlineTests/evmasm_difficulty_pre_paris/output index ad75355f5..26456f276 100644 --- a/test/cmdlineTests/evmasm_difficulty_pre_paris/output +++ b/test/cmdlineTests/evmasm_difficulty_pre_paris/output @@ -1,5 +1,5 @@ -======= evmasm_difficulty_pre_paris/input.sol:C ======= +======= input.sol:C ======= EVM assembly: sstore(0x00, difficulty) stop diff --git a/test/cmdlineTests/evmasm_prevrandao_post_paris/output b/test/cmdlineTests/evmasm_prevrandao_post_paris/output index 47c85bb50..6ade453b9 100644 --- a/test/cmdlineTests/evmasm_prevrandao_post_paris/output +++ b/test/cmdlineTests/evmasm_prevrandao_post_paris/output @@ -1,5 +1,5 @@ -======= evmasm_prevrandao_post_paris/input.sol:C ======= +======= input.sol:C ======= EVM assembly: sstore(0x00, prevrandao) stop diff --git a/test/cmdlineTests/evmasm_prevrandao_pre_paris/err b/test/cmdlineTests/evmasm_prevrandao_pre_paris/err index 5970ec202..429c06395 100644 --- a/test/cmdlineTests/evmasm_prevrandao_pre_paris/err +++ b/test/cmdlineTests/evmasm_prevrandao_pre_paris/err @@ -1,5 +1,5 @@ Warning: "prevrandao" is not supported by the VM version and will be treated as "difficulty". - --> evmasm_prevrandao_pre_paris/input.sol:6:21: + --> input.sol:6:21: | 6 | uint256 x = block.prevrandao; | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/evmasm_prevrandao_pre_paris/output b/test/cmdlineTests/evmasm_prevrandao_pre_paris/output index e41148a83..26456f276 100644 --- a/test/cmdlineTests/evmasm_prevrandao_pre_paris/output +++ b/test/cmdlineTests/evmasm_prevrandao_pre_paris/output @@ -1,5 +1,5 @@ -======= evmasm_prevrandao_pre_paris/input.sol:C ======= +======= input.sol:C ======= EVM assembly: sstore(0x00, difficulty) stop diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/err b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/err index 2e52d9ced..6b7f432f2 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/err +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/err @@ -1,5 +1,5 @@ Warning: Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. - --> evmasm_transient_storage_inline_assembly/input.sol:7:13: + --> input.sol:7:13: | 7 | tstore(0, 123) | ^^^^^^ diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output index 0b4c516ba..adeb0822c 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly/output @@ -1,5 +1,5 @@ -======= evmasm_transient_storage_inline_assembly/input.sol:C ======= +======= input.sol:C ======= EVM assembly: mstore(0x40, 0x80) callvalue diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err index 154da21b6..6b7f432f2 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/err @@ -1,5 +1,5 @@ Warning: Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe. - --> evmasm_transient_storage_inline_assembly_via_ir/input.sol:7:13: + --> input.sol:7:13: | 7 | tstore(0, 123) | ^^^^^^ diff --git a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output index 673bdd0a0..754bc9d45 100644 --- a/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output +++ b/test/cmdlineTests/evmasm_transient_storage_inline_assembly_via_ir/output @@ -1,5 +1,5 @@ -======= evmasm_transient_storage_inline_assembly_via_ir/input.sol:C ======= +======= input.sol:C ======= EVM assembly: 0x80 dup1 diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable/output b/test/cmdlineTests/evmasm_transient_storage_state_variable/output index e80eb3c57..0f2580c80 100644 --- a/test/cmdlineTests/evmasm_transient_storage_state_variable/output +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable/output @@ -1,5 +1,5 @@ -======= evmasm_transient_storage_state_variable/input.sol:C ======= +======= input.sol:C ======= EVM assembly: mstore(0x40, 0x80) callvalue diff --git a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output index 5959fad95..b2f55e1d5 100644 --- a/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output +++ b/test/cmdlineTests/evmasm_transient_storage_state_variable_via_ir/output @@ -1,5 +1,5 @@ -======= evmasm_transient_storage_state_variable_via_ir/input.sol:C ======= +======= input.sol:C ======= EVM assembly: 0x80 dup1 diff --git a/test/cmdlineTests/exp_base_literal/output b/test/cmdlineTests/exp_base_literal/output index 24e5d29be..fb5b35ed0 100644 --- a/test/cmdlineTests/exp_base_literal/output +++ b/test/cmdlineTests/exp_base_literal/output @@ -1,6 +1,6 @@ IR: -/// @use-src 0:"exp_base_literal/input.sol" +/// @use-src 0:"input.sol" object "C_81" { code { /// @src 0:82:370 "contract C {..." @@ -31,7 +31,7 @@ object "C_81" { /// @src 0:82:370 "contract C {..." } - /// @use-src 0:"exp_base_literal/input.sol" + /// @use-src 0:"input.sol" object "C_81_deployed" { code { /// @src 0:82:370 "contract C {..." diff --git a/test/cmdlineTests/function_debug_info/output b/test/cmdlineTests/function_debug_info/output index c1346e33a..aa4512352 100644 --- a/test/cmdlineTests/function_debug_info/output +++ b/test/cmdlineTests/function_debug_info/output @@ -1,6 +1,6 @@ { "contracts": { - "function_debug_info/input.sol:C": { + "input.sol:C": { "function-debug": { "@_34": { "id": 34, diff --git a/test/cmdlineTests/function_debug_info_via_yul/output b/test/cmdlineTests/function_debug_info_via_yul/output index 05c2da48c..c3a828ab3 100644 --- a/test/cmdlineTests/function_debug_info_via_yul/output +++ b/test/cmdlineTests/function_debug_info_via_yul/output @@ -1,6 +1,6 @@ { "contracts": { - "function_debug_info_via_yul/input.sol:C": { + "input.sol:C": { "function-debug": {}, "function-debug-runtime": {} } diff --git a/test/cmdlineTests/hashes/output b/test/cmdlineTests/hashes/output index b010456d3..45eb18359 100644 --- a/test/cmdlineTests/hashes/output +++ b/test/cmdlineTests/hashes/output @@ -1,5 +1,5 @@ -======= hashes/input.sol:C ======= +======= input.sol:C ======= Function signatures: 3fc03eeb: f((uint256)) @@ -12,7 +12,7 @@ Event signatures: 2d4dd5fe18ada5a020a9f5591539a8dc3010a5c074ba6a70e1c956659f02786a: ev(uint256) 81f3fb02f88d32d3bb08c80c9a622ca3b3223292f131c6ad049811f9a8a606dc: libraryEvent(uint256) -======= hashes/input.sol:L ======= +======= input.sol:L ======= Function signatures: Error signatures: diff --git a/test/cmdlineTests/inline_assembly_function_name_clash/err b/test/cmdlineTests/inline_assembly_function_name_clash/err index 5284ffe5c..892a312d0 100644 --- a/test/cmdlineTests/inline_assembly_function_name_clash/err +++ b/test/cmdlineTests/inline_assembly_function_name_clash/err @@ -1,5 +1,5 @@ Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: " to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information. ---> inline_assembly_function_name_clash/input.sol +--> input.sol Warning: Source file does not specify required compiler version! ---> inline_assembly_function_name_clash/input.sol +--> input.sol diff --git a/test/cmdlineTests/inline_assembly_function_name_clash/output b/test/cmdlineTests/inline_assembly_function_name_clash/output index 2fd6ff1f5..d21576ff0 100644 --- a/test/cmdlineTests/inline_assembly_function_name_clash/output +++ b/test/cmdlineTests/inline_assembly_function_name_clash/output @@ -1,6 +1,6 @@ { "contracts": { - "inline_assembly_function_name_clash/input.sol:C": { + "input.sol:C": { "function-debug-runtime": { "abi_decode": { "entryPoint": 80, diff --git a/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output b/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output index 84fd9d0bc..2d715d0ab 100644 --- a/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output +++ b/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"ir_compiler_inheritance_nosubobjects/input.sol" +/// @use-src 0:"input.sol" object "C_7" { code { { @@ -12,7 +12,7 @@ object "C_7" { return(_1, _2) } } - /// @use-src 0:"ir_compiler_inheritance_nosubobjects/input.sol" + /// @use-src 0:"input.sol" object "C_7_deployed" { code { { @@ -25,7 +25,7 @@ object "C_7" { } Optimized IR: -/// @use-src 0:"ir_compiler_inheritance_nosubobjects/input.sol" +/// @use-src 0:"input.sol" object "D_10" { code { { @@ -38,7 +38,7 @@ object "D_10" { return(_1, _2) } } - /// @use-src 0:"ir_compiler_inheritance_nosubobjects/input.sol" + /// @use-src 0:"input.sol" object "D_10_deployed" { code { { diff --git a/test/cmdlineTests/ir_compiler_subobjects/err b/test/cmdlineTests/ir_compiler_subobjects/err index b300ec124..66ebf4229 100644 --- a/test/cmdlineTests/ir_compiler_subobjects/err +++ b/test/cmdlineTests/ir_compiler_subobjects/err @@ -1,5 +1,5 @@ Warning: Unused local variable. - --> ir_compiler_subobjects/input.sol:8:9: + --> input.sol:8:9: | 8 | C c = new C(); | ^^^ diff --git a/test/cmdlineTests/ir_compiler_subobjects/output b/test/cmdlineTests/ir_compiler_subobjects/output index 39ef53f55..08ee8bf5d 100644 --- a/test/cmdlineTests/ir_compiler_subobjects/output +++ b/test/cmdlineTests/ir_compiler_subobjects/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"ir_compiler_subobjects/input.sol" +/// @use-src 0:"input.sol" object "C_3" { code { { @@ -12,7 +12,7 @@ object "C_3" { return(_1, _2) } } - /// @use-src 0:"ir_compiler_subobjects/input.sol" + /// @use-src 0:"input.sol" object "C_3_deployed" { code { { @@ -25,7 +25,7 @@ object "C_3" { } Optimized IR: -/// @use-src 0:"ir_compiler_subobjects/input.sol" +/// @use-src 0:"input.sol" object "D_16" { code { { @@ -38,7 +38,7 @@ object "D_16" { return(_1, _2) } } - /// @use-src 0:"ir_compiler_subobjects/input.sol" + /// @use-src 0:"input.sol" object "D_16_deployed" { code { { @@ -76,7 +76,7 @@ object "D_16" { revert(0, 0) } } - /// @use-src 0:"ir_compiler_subobjects/input.sol" + /// @use-src 0:"input.sol" object "C_3" { code { { @@ -89,7 +89,7 @@ object "D_16" { return(_1, _2) } } - /// @use-src 0:"ir_compiler_subobjects/input.sol" + /// @use-src 0:"input.sol" object "C_3_deployed" { code { { diff --git a/test/cmdlineTests/ir_optimized_transient_storage_value_type/output b/test/cmdlineTests/ir_optimized_transient_storage_value_type/output index 61d289e3f..2f6918cab 100644 --- a/test/cmdlineTests/ir_optimized_transient_storage_value_type/output +++ b/test/cmdlineTests/ir_optimized_transient_storage_value_type/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"ir_optimized_transient_storage_value_type/input.sol" +/// @use-src 0:"input.sol" object "C_14" { code { { @@ -11,7 +11,7 @@ object "C_14" { return(_1, _2) } } - /// @use-src 0:"ir_optimized_transient_storage_value_type/input.sol" + /// @use-src 0:"input.sol" object "C_14_deployed" { code { { diff --git a/test/cmdlineTests/ir_optimized_with_optimize/output b/test/cmdlineTests/ir_optimized_with_optimize/output index 8790e45d3..bae07ea4e 100644 --- a/test/cmdlineTests/ir_optimized_with_optimize/output +++ b/test/cmdlineTests/ir_optimized_with_optimize/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"ir_optimized_with_optimize/input.sol" +/// @use-src 0:"input.sol" object "C_2" { code { { @@ -11,7 +11,7 @@ object "C_2" { return(_1, _2) } } - /// @use-src 0:"ir_optimized_with_optimize/input.sol" + /// @use-src 0:"input.sol" object "C_2_deployed" { code { { revert(0, 0) } } data ".metadata" hex"" diff --git a/test/cmdlineTests/ir_subobject_order/output b/test/cmdlineTests/ir_subobject_order/output index da4390fff..d41b65bf9 100644 --- a/test/cmdlineTests/ir_subobject_order/output +++ b/test/cmdlineTests/ir_subobject_order/output @@ -1,8 +1,8 @@ Optimized IR: -/// @use-src 0:"ir_subobject_order/input.sol" +/// @use-src 0:"input.sol" object "A_13" { code { { revert(0, 0) } } - /// @use-src 0:"ir_subobject_order/input.sol" + /// @use-src 0:"input.sol" object "A_13_deployed" { code { { revert(0, 0) } } data ".metadata" hex"" @@ -10,10 +10,10 @@ object "A_13" { } Optimized IR: -/// @use-src 0:"ir_subobject_order/input.sol" +/// @use-src 0:"input.sol" object "B_7" { code { { revert(0, 0) } } - /// @use-src 0:"ir_subobject_order/input.sol" + /// @use-src 0:"input.sol" object "B_7_deployed" { code { { revert(0, 0) } } data ".metadata" hex"" @@ -21,7 +21,7 @@ object "B_7" { } Optimized IR: -/// @use-src 0:"ir_subobject_order/input.sol" +/// @use-src 0:"input.sol" object "C_33" { code { { @@ -69,24 +69,24 @@ object "C_33" { return(_7, _8) } } - /// @use-src 0:"ir_subobject_order/input.sol" + /// @use-src 0:"input.sol" object "C_33_deployed" { code { { revert(0, 0) } } data ".metadata" hex"" } - /// @use-src 0:"ir_subobject_order/input.sol" + /// @use-src 0:"input.sol" object "A_13" { code { { revert(0, 0) } } - /// @use-src 0:"ir_subobject_order/input.sol" + /// @use-src 0:"input.sol" object "A_13_deployed" { code { { revert(0, 0) } } data ".metadata" hex"" } } - /// @use-src 0:"ir_subobject_order/input.sol" + /// @use-src 0:"input.sol" object "B_7" { code { { revert(0, 0) } } - /// @use-src 0:"ir_subobject_order/input.sol" + /// @use-src 0:"input.sol" object "B_7_deployed" { code { { revert(0, 0) } } data ".metadata" hex"" diff --git a/test/cmdlineTests/ir_unoptimized_with_optimize/output b/test/cmdlineTests/ir_unoptimized_with_optimize/output index c5307123f..b34558d2a 100644 --- a/test/cmdlineTests/ir_unoptimized_with_optimize/output +++ b/test/cmdlineTests/ir_unoptimized_with_optimize/output @@ -1,6 +1,6 @@ IR: -/// @use-src 0:"ir_unoptimized_with_optimize/input.sol" +/// @use-src 0:"input.sol" object "C_2" { code { @@ -27,7 +27,7 @@ object "C_2" { } } - /// @use-src 0:"ir_unoptimized_with_optimize/input.sol" + /// @use-src 0:"input.sol" object "C_2_deployed" { code { diff --git a/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/output b/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/output index f5ecdd8bf..b34558d2a 100644 --- a/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/output +++ b/test/cmdlineTests/ir_unoptimized_with_optimize_via_ir/output @@ -1,6 +1,6 @@ IR: -/// @use-src 0:"ir_unoptimized_with_optimize_via_ir/input.sol" +/// @use-src 0:"input.sol" object "C_2" { code { @@ -27,7 +27,7 @@ object "C_2" { } } - /// @use-src 0:"ir_unoptimized_with_optimize_via_ir/input.sol" + /// @use-src 0:"input.sol" object "C_2_deployed" { code { diff --git a/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output b/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output index 5c822949a..03f556420 100644 --- a/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output +++ b/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"ir_with_assembly_no_memoryguard_creation/input.sol" +/// @use-src 0:"input.sol" object "D_12" { code { { @@ -10,7 +10,7 @@ object "D_12" { return(128, _1) } } - /// @use-src 0:"ir_with_assembly_no_memoryguard_creation/input.sol" + /// @use-src 0:"input.sol" object "D_12_deployed" { code { { diff --git a/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output b/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output index f6be1493e..9d07cd910 100644 --- a/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output +++ b/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"ir_with_assembly_no_memoryguard_runtime/input.sol" +/// @use-src 0:"input.sol" object "D_8" { code { { @@ -12,7 +12,7 @@ object "D_8" { return(_1, _2) } } - /// @use-src 0:"ir_with_assembly_no_memoryguard_runtime/input.sol" + /// @use-src 0:"input.sol" object "D_8_deployed" { code { { diff --git a/test/cmdlineTests/keccak_optimization_deploy_code/output b/test/cmdlineTests/keccak_optimization_deploy_code/output index 8b89ea5b6..839e67521 100644 --- a/test/cmdlineTests/keccak_optimization_deploy_code/output +++ b/test/cmdlineTests/keccak_optimization_deploy_code/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"keccak_optimization_deploy_code/input.sol" +/// @use-src 0:"input.sol" object "C_12" { code { { @@ -14,7 +14,7 @@ object "C_12" { return(128, _1) } } - /// @use-src 0:"keccak_optimization_deploy_code/input.sol" + /// @use-src 0:"input.sol" object "C_12_deployed" { code { { diff --git a/test/cmdlineTests/keccak_optimization_low_runs/output b/test/cmdlineTests/keccak_optimization_low_runs/output index c308d737b..328bdd59e 100644 --- a/test/cmdlineTests/keccak_optimization_low_runs/output +++ b/test/cmdlineTests/keccak_optimization_low_runs/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"keccak_optimization_low_runs/input.sol" +/// @use-src 0:"input.sol" object "C_7" { code { { @@ -12,7 +12,7 @@ object "C_7" { return(_1, _2) } } - /// @use-src 0:"keccak_optimization_low_runs/input.sol" + /// @use-src 0:"input.sol" object "C_7_deployed" { code { { diff --git a/test/cmdlineTests/linking_qualified_library_name/args b/test/cmdlineTests/linking_qualified_library_name/args index dc996f46e..e8a29e815 100644 --- a/test/cmdlineTests/linking_qualified_library_name/args +++ b/test/cmdlineTests/linking_qualified_library_name/args @@ -1 +1 @@ -linking_qualified_library_name/contract1.sol --bin --libraries linking_qualified_library_name/math.sol:Log:0x7777777777777777777777777777777777777777 +contract1.sol --bin --libraries math.sol:Log:0x7777777777777777777777777777777777777777 diff --git a/test/cmdlineTests/linking_qualified_library_name/contract1.sol b/test/cmdlineTests/linking_qualified_library_name/contract1.sol index aedea65fa..d59420962 100644 --- a/test/cmdlineTests/linking_qualified_library_name/contract1.sol +++ b/test/cmdlineTests/linking_qualified_library_name/contract1.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.0; -import "linking_qualified_library_name/math.sol"; +import "math.sol"; contract C { function foo() public { diff --git a/test/cmdlineTests/linking_qualified_library_name/output b/test/cmdlineTests/linking_qualified_library_name/output index 834874bf8..63359661b 100644 --- a/test/cmdlineTests/linking_qualified_library_name/output +++ b/test/cmdlineTests/linking_qualified_library_name/output @@ -1,8 +1,8 @@ -======= linking_qualified_library_name/contract1.sol:C ======= +======= contract1.sol:C ======= Binary: -======= linking_qualified_library_name/math.sol:Log ======= +======= math.sol:Log ======= Binary: diff --git a/test/cmdlineTests/linking_solidity/args b/test/cmdlineTests/linking_solidity/args index 9a958527f..7689b925a 100644 --- a/test/cmdlineTests/linking_solidity/args +++ b/test/cmdlineTests/linking_solidity/args @@ -1 +1 @@ ---bin --bin-runtime --libraries linking_solidity/input.sol:L=0x1234567890123456789012345678901234567890 +--bin --bin-runtime --libraries input.sol:L=0x1234567890123456789012345678901234567890 diff --git a/test/cmdlineTests/linking_solidity/output b/test/cmdlineTests/linking_solidity/output index 307b131b5..ed60e0ccf 100644 --- a/test/cmdlineTests/linking_solidity/output +++ b/test/cmdlineTests/linking_solidity/output @@ -1,11 +1,11 @@ -======= linking_solidity/input.sol:C ======= +======= input.sol:C ======= Binary: Binary of the runtime part: -======= linking_solidity/input.sol:L ======= +======= input.sol:L ======= Binary: Binary of the runtime part: diff --git a/test/cmdlineTests/linking_solidity_unresolved_references/args b/test/cmdlineTests/linking_solidity_unresolved_references/args index 8909b2779..fbbed9f87 100644 --- a/test/cmdlineTests/linking_solidity_unresolved_references/args +++ b/test/cmdlineTests/linking_solidity_unresolved_references/args @@ -1 +1 @@ ---bin --bin-runtime --libraries linking_solidity_unresolved_references/input.sol:L1=0x1234567890123456789012345678901234567890 +--bin --bin-runtime --libraries input.sol:L1=0x1234567890123456789012345678901234567890 diff --git a/test/cmdlineTests/linking_solidity_unresolved_references/output b/test/cmdlineTests/linking_solidity_unresolved_references/output index f42191f51..5df6611de 100644 --- a/test/cmdlineTests/linking_solidity_unresolved_references/output +++ b/test/cmdlineTests/linking_solidity_unresolved_references/output @@ -1,23 +1,23 @@ -======= linking_solidity_unresolved_references/input.sol:C ======= +======= input.sol:C ======= Binary: -__$8ef13d1c56d5343bf69cf9444272079aa5$____$8ef13d1c56d5343bf69cf9444272079aa5$__ +__$a7fb54ac3bf4ba657d4a55d066b3521d62$____$a7fb54ac3bf4ba657d4a55d066b3521d62$__ -// $8ef13d1c56d5343bf69cf9444272079aa5$ -> linking_solidity_unresolved_references/input.sol:L2 -// $8ef13d1c56d5343bf69cf9444272079aa5$ -> linking_solidity_unresolved_references/input.sol:L2 +// $a7fb54ac3bf4ba657d4a55d066b3521d62$ -> input.sol:L2 +// $a7fb54ac3bf4ba657d4a55d066b3521d62$ -> input.sol:L2 Binary of the runtime part: -__$8ef13d1c56d5343bf69cf9444272079aa5$____$8ef13d1c56d5343bf69cf9444272079aa5$__ +__$a7fb54ac3bf4ba657d4a55d066b3521d62$____$a7fb54ac3bf4ba657d4a55d066b3521d62$__ -// $8ef13d1c56d5343bf69cf9444272079aa5$ -> linking_solidity_unresolved_references/input.sol:L2 -// $8ef13d1c56d5343bf69cf9444272079aa5$ -> linking_solidity_unresolved_references/input.sol:L2 +// $a7fb54ac3bf4ba657d4a55d066b3521d62$ -> input.sol:L2 +// $a7fb54ac3bf4ba657d4a55d066b3521d62$ -> input.sol:L2 -======= linking_solidity_unresolved_references/input.sol:L1 ======= +======= input.sol:L1 ======= Binary: Binary of the runtime part: -======= linking_solidity_unresolved_references/input.sol:L2 ======= +======= input.sol:L2 ======= Binary: Binary of the runtime part: diff --git a/test/cmdlineTests/linking_strict_assembly/output b/test/cmdlineTests/linking_strict_assembly/output index 4fa6edc0c..756cc2822 100644 --- a/test/cmdlineTests/linking_strict_assembly/output +++ b/test/cmdlineTests/linking_strict_assembly/output @@ -1,5 +1,5 @@ -======= linking_strict_assembly/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "a" { @@ -16,11 +16,11 @@ Binary representation: 7312345678901234567890123456789012345678905f5500 Text representation: - /* "linking_strict_assembly/input.yul":58:93 */ + /* "input.yul":58:93 */ linkerSymbol("f919ba91ac99f96129544b80b9516b27a80e376b9dc693819d0b18b7e0395612") - /* "linking_strict_assembly/input.yul":113:114 */ + /* "input.yul":113:114 */ 0x00 - /* "linking_strict_assembly/input.yul":106:121 */ + /* "input.yul":106:121 */ sstore - /* "linking_strict_assembly/input.yul":22:137 */ + /* "input.yul":22:137 */ stop diff --git a/test/cmdlineTests/linking_strict_assembly_qualified_library_qualified_reference/output b/test/cmdlineTests/linking_strict_assembly_qualified_library_qualified_reference/output index e4fa4fcbd..f34763100 100644 --- a/test/cmdlineTests/linking_strict_assembly_qualified_library_qualified_reference/output +++ b/test/cmdlineTests/linking_strict_assembly_qualified_library_qualified_reference/output @@ -1,5 +1,5 @@ -======= linking_strict_assembly_qualified_library_qualified_reference/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "a" { diff --git a/test/cmdlineTests/linking_strict_assembly_qualified_library_unqualified_reference/output b/test/cmdlineTests/linking_strict_assembly_qualified_library_unqualified_reference/output index ebf7f6542..d329296eb 100644 --- a/test/cmdlineTests/linking_strict_assembly_qualified_library_unqualified_reference/output +++ b/test/cmdlineTests/linking_strict_assembly_qualified_library_unqualified_reference/output @@ -1,5 +1,5 @@ -======= linking_strict_assembly_qualified_library_unqualified_reference/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "a" { diff --git a/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files/output b/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files/output index 69c0a21f6..f4262400c 100644 --- a/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files/output +++ b/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files/output @@ -1,5 +1,5 @@ -======= linking_strict_assembly_same_library_name_different_files/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "a" { @@ -18,19 +18,19 @@ Binary representation: 731111111111111111111111111111111111111111732222222222222222222222222222222222222222905f5560015500 Text representation: - /* "linking_strict_assembly_same_library_name_different_files/input.yul":59:89 */ + /* "input.yul":59:89 */ linkerSymbol("f3ffc10c396a7cc41ae954b050792839d20947bf73497d30c49a9fda1ea477ec") - /* "linking_strict_assembly_same_library_name_different_files/input.yul":115:145 */ + /* "input.yul":115:145 */ linkerSymbol("c3523432985587641d17c68161d2f700c57aaf4ed21cda4f25d76193c831f97f") - /* "linking_strict_assembly_same_library_name_different_files/input.yul":158:174 */ + /* "input.yul":158:174 */ swap1 - /* "linking_strict_assembly_same_library_name_different_files/input.yul":165:166 */ + /* "input.yul":165:166 */ 0x00 - /* "linking_strict_assembly_same_library_name_different_files/input.yul":158:174 */ + /* "input.yul":158:174 */ sstore - /* "linking_strict_assembly_same_library_name_different_files/input.yul":194:195 */ + /* "input.yul":194:195 */ 0x01 - /* "linking_strict_assembly_same_library_name_different_files/input.yul":187:203 */ + /* "input.yul":187:203 */ sstore - /* "linking_strict_assembly_same_library_name_different_files/input.yul":22:219 */ + /* "input.yul":22:219 */ stop diff --git a/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files_in_link_references/output b/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files_in_link_references/output index 14fafa4e4..a6422d8fb 100644 --- a/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files_in_link_references/output +++ b/test/cmdlineTests/linking_strict_assembly_same_library_name_different_files_in_link_references/output @@ -1,5 +1,5 @@ -======= linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "a" { @@ -18,19 +18,19 @@ Binary representation: 73123456789012345678901234567890123456789073__$c3523432985587641d17c68161d2f700c5$__905f5560015500 Text representation: - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":59:89 */ + /* "input.yul":59:89 */ linkerSymbol("f3ffc10c396a7cc41ae954b050792839d20947bf73497d30c49a9fda1ea477ec") - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":115:145 */ + /* "input.yul":115:145 */ linkerSymbol("c3523432985587641d17c68161d2f700c57aaf4ed21cda4f25d76193c831f97f") - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":158:174 */ + /* "input.yul":158:174 */ swap1 - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":165:166 */ + /* "input.yul":165:166 */ 0x00 - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":158:174 */ + /* "input.yul":158:174 */ sstore - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":194:195 */ + /* "input.yul":194:195 */ 0x01 - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":187:203 */ + /* "input.yul":187:203 */ sstore - /* "linking_strict_assembly_same_library_name_different_files_in_link_references/input.yul":22:219 */ + /* "input.yul":22:219 */ stop diff --git a/test/cmdlineTests/linking_strict_assembly_unqualified_library_qualified_reference/output b/test/cmdlineTests/linking_strict_assembly_unqualified_library_qualified_reference/output index aaf03d073..099b0ce54 100644 --- a/test/cmdlineTests/linking_strict_assembly_unqualified_library_qualified_reference/output +++ b/test/cmdlineTests/linking_strict_assembly_unqualified_library_qualified_reference/output @@ -1,5 +1,5 @@ -======= linking_strict_assembly_unqualified_library_qualified_reference/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "a" { diff --git a/test/cmdlineTests/linking_strict_assembly_unqualified_library_unqualified_reference/output b/test/cmdlineTests/linking_strict_assembly_unqualified_library_unqualified_reference/output index d91d89f5c..b4bb82543 100644 --- a/test/cmdlineTests/linking_strict_assembly_unqualified_library_unqualified_reference/output +++ b/test/cmdlineTests/linking_strict_assembly_unqualified_library_unqualified_reference/output @@ -1,5 +1,5 @@ -======= linking_strict_assembly_unqualified_library_unqualified_reference/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "a" { diff --git a/test/cmdlineTests/linking_strict_assembly_unresolved_references/output b/test/cmdlineTests/linking_strict_assembly_unresolved_references/output index 3b2d84ab3..7b45cae6e 100644 --- a/test/cmdlineTests/linking_strict_assembly_unresolved_references/output +++ b/test/cmdlineTests/linking_strict_assembly_unresolved_references/output @@ -1,5 +1,5 @@ -======= linking_strict_assembly_unresolved_references/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "a" { @@ -18,19 +18,19 @@ Binary representation: 73123456789012345678901234567890123456789073__$fb58009a6b1ecea3b9d99bedd645df4ec3$__905f5560015500 Text representation: - /* "linking_strict_assembly_unresolved_references/input.yul":59:95 */ + /* "input.yul":59:95 */ linkerSymbol("05b0326038374a21e0895480a58bda0768cdcc04c8d18f154362d1ca5223d245") - /* "linking_strict_assembly_unresolved_references/input.yul":121:157 */ + /* "input.yul":121:157 */ linkerSymbol("fb58009a6b1ecea3b9d99bedd645df4ec308f17bc0087e5f39d078f77f809177") - /* "linking_strict_assembly_unresolved_references/input.yul":170:186 */ + /* "input.yul":170:186 */ swap1 - /* "linking_strict_assembly_unresolved_references/input.yul":177:178 */ + /* "input.yul":177:178 */ 0x00 - /* "linking_strict_assembly_unresolved_references/input.yul":170:186 */ + /* "input.yul":170:186 */ sstore - /* "linking_strict_assembly_unresolved_references/input.yul":206:207 */ + /* "input.yul":206:207 */ 0x01 - /* "linking_strict_assembly_unresolved_references/input.yul":199:215 */ + /* "input.yul":199:215 */ sstore - /* "linking_strict_assembly_unresolved_references/input.yul":22:231 */ + /* "input.yul":22:231 */ stop diff --git a/test/cmdlineTests/linking_unqualified_library_name/args b/test/cmdlineTests/linking_unqualified_library_name/args index 6118acf02..08f3b8cd1 100644 --- a/test/cmdlineTests/linking_unqualified_library_name/args +++ b/test/cmdlineTests/linking_unqualified_library_name/args @@ -1 +1 @@ -linking_unqualified_library_name/contract1.sol linking_unqualified_library_name/contract2.sol --bin --libraries Log:0x7777777777777777777777777777777777777777 +contract1.sol contract2.sol --bin --libraries Log:0x7777777777777777777777777777777777777777 diff --git a/test/cmdlineTests/linking_unqualified_library_name/contract1.sol b/test/cmdlineTests/linking_unqualified_library_name/contract1.sol index 38e43f9d4..893c63af0 100644 --- a/test/cmdlineTests/linking_unqualified_library_name/contract1.sol +++ b/test/cmdlineTests/linking_unqualified_library_name/contract1.sol @@ -2,7 +2,7 @@ pragma solidity >=0.0; -import "linking_unqualified_library_name/error.sol"; +import "error.sol"; contract C { function foo() public { diff --git a/test/cmdlineTests/linking_unqualified_library_name/contract2.sol b/test/cmdlineTests/linking_unqualified_library_name/contract2.sol index 6ddb8ad6e..d59420962 100644 --- a/test/cmdlineTests/linking_unqualified_library_name/contract2.sol +++ b/test/cmdlineTests/linking_unqualified_library_name/contract2.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.0; -import "linking_unqualified_library_name/math.sol"; +import "math.sol"; contract C { function foo() public { diff --git a/test/cmdlineTests/linking_unqualified_library_name/output b/test/cmdlineTests/linking_unqualified_library_name/output index be64a93c9..68e254363 100644 --- a/test/cmdlineTests/linking_unqualified_library_name/output +++ b/test/cmdlineTests/linking_unqualified_library_name/output @@ -1,20 +1,20 @@ -======= linking_unqualified_library_name/contract1.sol:C ======= +======= contract1.sol:C ======= Binary: -__$cdf6d5ab08a9335b02e7c2475aa27d04fa$__ +__$4a937a7d3d68a205b3b2520e23ccff31ea$__ -// $cdf6d5ab08a9335b02e7c2475aa27d04fa$ -> linking_unqualified_library_name/error.sol:Log +// $4a937a7d3d68a205b3b2520e23ccff31ea$ -> error.sol:Log -======= linking_unqualified_library_name/contract2.sol:C ======= +======= contract2.sol:C ======= Binary: -__$22584241c2fc4f2884d5222245463779a8$__ +__$b77e1024bb5d89efefbab5fb1f7cb8fde7$__ -// $22584241c2fc4f2884d5222245463779a8$ -> linking_unqualified_library_name/math.sol:Log +// $b77e1024bb5d89efefbab5fb1f7cb8fde7$ -> math.sol:Log -======= linking_unqualified_library_name/error.sol:Log ======= +======= error.sol:Log ======= Binary: -======= linking_unqualified_library_name/math.sol:Log ======= +======= math.sol:Log ======= Binary: diff --git a/test/cmdlineTests/mcopy_bytes_array_abi_decode/err b/test/cmdlineTests/mcopy_bytes_array_abi_decode/err index de32e6629..ead85d933 100644 --- a/test/cmdlineTests/mcopy_bytes_array_abi_decode/err +++ b/test/cmdlineTests/mcopy_bytes_array_abi_decode/err @@ -1,5 +1,5 @@ Warning: Statement has no effect. - --> mcopy_bytes_array_abi_decode/input.sol:7:9: + --> input.sol:7:9: | 7 | abi.decode("abcd", (bytes)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/mcopy_bytes_array_abi_decode/output b/test/cmdlineTests/mcopy_bytes_array_abi_decode/output index 2a24ec834..806094f76 100644 --- a/test/cmdlineTests/mcopy_bytes_array_abi_decode/output +++ b/test/cmdlineTests/mcopy_bytes_array_abi_decode/output @@ -1,6 +1,6 @@ IR: -/// @use-src 0:"mcopy_bytes_array_abi_decode/input.sol" +/// @use-src 0:"input.sol" object "C_15" { code { @@ -27,7 +27,7 @@ object "C_15" { } } - /// @use-src 0:"mcopy_bytes_array_abi_decode/input.sol" + /// @use-src 0:"input.sol" object "C_15_deployed" { code { diff --git a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output index 170cdf1a7..f3cd76695 100644 --- a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output +++ b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"mcopy_bytes_array_returned_from_function/input.sol" +/// @use-src 0:"input.sol" object "C_14" { code { { @@ -11,7 +11,7 @@ object "C_14" { return(_1, _2) } } - /// @use-src 0:"mcopy_bytes_array_returned_from_function/input.sol" + /// @use-src 0:"input.sol" object "C_14_deployed" { code { { diff --git a/test/cmdlineTests/mcopy_string_literal_returned_from_function/output b/test/cmdlineTests/mcopy_string_literal_returned_from_function/output index 548c34de8..3adeae0f5 100644 --- a/test/cmdlineTests/mcopy_string_literal_returned_from_function/output +++ b/test/cmdlineTests/mcopy_string_literal_returned_from_function/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"mcopy_string_literal_returned_from_function/input.sol" +/// @use-src 0:"input.sol" object "C_10" { code { { @@ -11,7 +11,7 @@ object "C_10" { return(_1, _2) } } - /// @use-src 0:"mcopy_string_literal_returned_from_function/input.sol" + /// @use-src 0:"input.sol" object "C_10_deployed" { code { { diff --git a/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/output b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/output index 842580597..1ea3bdf20 100644 --- a/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/output +++ b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/output @@ -1,6 +1,6 @@ IR: -/// @use-src 0:"memoryguard_shadowing_by_inline_assembly_identifiers/input.sol" +/// @use-src 0:"input.sol" object "C_10" { code { @@ -27,7 +27,7 @@ object "C_10" { } } - /// @use-src 0:"memoryguard_shadowing_by_inline_assembly_identifiers/input.sol" + /// @use-src 0:"input.sol" object "C_10_deployed" { code { diff --git a/test/cmdlineTests/message_format/err b/test/cmdlineTests/message_format/err index eee8267e2..1bb6a6469 100644 --- a/test/cmdlineTests/message_format/err +++ b/test/cmdlineTests/message_format/err @@ -1,50 +1,50 @@ Warning: Source file does not specify required compiler version! ---> message_format/input.sol +--> input.sol Warning: Unused local variable. - --> message_format/input.sol:9:27: + --> input.sol:9:27: | 9 | function f() public { int x; } | ^^^^^ Warning: Unused local variable. - --> message_format/input.sol:10:27: + --> input.sol:10:27: | 10 | function g() public { int x; } | ^^^^^ Warning: Unused local variable. - --> message_format/input.sol:99:14: + --> input.sol:99:14: | 99 | /**/ int a; /**/ | ^^^^^ Warning: Unused local variable. - --> message_format/input.sol:100:14: + --> input.sol:100:14: | 100 | /**/ int b; /**/ | ^^^^^ Warning: Unused local variable. - --> message_format/input.sol:101:14: + --> input.sol:101:14: | 101 | /**/ int c; /**/ | ^^^^^ Warning: Function state mutability can be restricted to pure - --> message_format/input.sol:9:5: + --> input.sol:9:5: | 9 | function f() public { int x; } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning: Function state mutability can be restricted to pure - --> message_format/input.sol:10:5: + --> input.sol:10:5: | 10 | function g() public { int x; } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning: Function state mutability can be restricted to pure - --> message_format/input.sol:11:5: + --> input.sol:11:5: | 11 | function h() public { | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/message_format_utf8/err b/test/cmdlineTests/message_format_utf8/err index 58d45127c..e14a048fc 100644 --- a/test/cmdlineTests/message_format_utf8/err +++ b/test/cmdlineTests/message_format_utf8/err @@ -1,29 +1,29 @@ Warning: Statement has no effect. - --> message_format_utf8/input.sol:5:51: + --> input.sol:5:51: | 5 | /* ©©©©ᄅ©©©©© 2017 */ constructor () { unicode"©©©©ᄅ©©©©©" ; } | ^^^^^^^^^^^^^^^^^^^ Warning: Statement has no effect. - --> message_format_utf8/input.sol:9:25: + --> input.sol:9:25: | 9 | unicode"S = π × r²"; | ^^^^^^^^^^^^^^^^^^^ Warning: Statement has no effect. - --> message_format_utf8/input.sol:10:39: + --> input.sol:10:39: | 10 | /* ₀₁₂₃₄⁵⁶⁷⁸⁹ */ unicode"∑ 1/n! ≈ 2.7"; // tabs in-between | ^^^^^^^^^^^^^^^^^^^^^ Warning: Statement has no effect. - --> message_format_utf8/input.sol:11:30: + --> input.sol:11:30: | 11 | /* Ŀŏŗėɯ ïƥŝʉɱ */ unicode"μὴ χεῖρον βέλτιστον"; // tabs in-between and inside | ^^^^^^^^^^ ^^^^^^ ^^^^^^^^^^ Warning: Function state mutability can be restricted to pure - --> message_format_utf8/input.sol:15:2: + --> input.sol:15:2: | 15 | function selector() public returns(uint) { // starts with tab | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/metadata/output b/test/cmdlineTests/metadata/output index b6a684b84..091012889 100644 --- a/test/cmdlineTests/metadata/output +++ b/test/cmdlineTests/metadata/output @@ -1,4 +1,4 @@ -======= metadata/input.sol:C ======= +======= input.sol:C ======= Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"metadata/input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"metadata/input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} diff --git a/test/cmdlineTests/model_checker_bmc_loop_iterations/err b/test/cmdlineTests/model_checker_bmc_loop_iterations/err index cbb2b0f9d..0ec7a09b6 100644 --- a/test/cmdlineTests/model_checker_bmc_loop_iterations/err +++ b/test/cmdlineTests/model_checker_bmc_loop_iterations/err @@ -1,5 +1,5 @@ Warning: BMC: Assertion violation happens here. - --> model_checker_bmc_loop_iterations/input.sol:10:3: + --> input.sol:10:3: | 10 | assert(x == 3); | ^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_bmc_loop_iterations_no_argument/err b/test/cmdlineTests/model_checker_bmc_loop_iterations_no_argument/err index 1bd45b6c6..4b1a2ea3b 100644 --- a/test/cmdlineTests/model_checker_bmc_loop_iterations_no_argument/err +++ b/test/cmdlineTests/model_checker_bmc_loop_iterations_no_argument/err @@ -1 +1 @@ -Error: the argument ('model_checker_bmc_loop_iterations_no_argument/input.sol') for option '--model-checker-bmc-loop-iterations' is invalid +Error: the argument ('input.sol') for option '--model-checker-bmc-loop-iterations' is invalid diff --git a/test/cmdlineTests/model_checker_contracts_all/err b/test/cmdlineTests/model_checker_contracts_all/err index 9135483d5..0d19af174 100644 --- a/test/cmdlineTests/model_checker_contracts_all/err +++ b/test/cmdlineTests/model_checker_contracts_all/err @@ -6,7 +6,7 @@ x = 0 Transaction trace: B.constructor() B.f(0) - --> model_checker_contracts_all/input.sol:5:9: + --> input.sol:5:9: | 5 | assert(x > 0); | ^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ y = 0 Transaction trace: A.constructor() A.g(0) - --> model_checker_contracts_all/input.sol:10:9: + --> input.sol:10:9: | 10 | assert(y > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_contracts_all_explicit/args b/test/cmdlineTests/model_checker_contracts_all_explicit/args index 6e6bee97a..151a636fe 100644 --- a/test/cmdlineTests/model_checker_contracts_all_explicit/args +++ b/test/cmdlineTests/model_checker_contracts_all_explicit/args @@ -1 +1 @@ ---model-checker-engine all --model-checker-contracts model_checker_contracts_all_explicit/input.sol:B,model_checker_contracts_all_explicit/input.sol:A +--model-checker-engine all --model-checker-contracts input.sol:B,input.sol:A diff --git a/test/cmdlineTests/model_checker_contracts_all_explicit/err b/test/cmdlineTests/model_checker_contracts_all_explicit/err index 003c0dffe..25ce2e5e9 100644 --- a/test/cmdlineTests/model_checker_contracts_all_explicit/err +++ b/test/cmdlineTests/model_checker_contracts_all_explicit/err @@ -6,7 +6,7 @@ x = 0 Transaction trace: B.constructor() B.f(0) - --> model_checker_contracts_all_explicit/input.sol:5:3: + --> input.sol:5:3: | 5 | assert(x > 0); | ^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ y = 0 Transaction trace: A.constructor() A.g(0) - --> model_checker_contracts_all_explicit/input.sol:10:3: + --> input.sol:10:3: | 10 | assert(y > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_contracts_inexistent_contract/args b/test/cmdlineTests/model_checker_contracts_inexistent_contract/args index b3c44af85..1128064d8 100644 --- a/test/cmdlineTests/model_checker_contracts_inexistent_contract/args +++ b/test/cmdlineTests/model_checker_contracts_inexistent_contract/args @@ -1 +1 @@ ---model-checker-engine all --model-checker-contracts model_checker_contracts_inexistent_contract/input.sol:C +--model-checker-engine all --model-checker-contracts input.sol:C diff --git a/test/cmdlineTests/model_checker_contracts_inexistent_contract/err b/test/cmdlineTests/model_checker_contracts_inexistent_contract/err index 6326537e9..72f613bf3 100644 --- a/test/cmdlineTests/model_checker_contracts_inexistent_contract/err +++ b/test/cmdlineTests/model_checker_contracts_inexistent_contract/err @@ -1 +1 @@ -Warning: Requested contract "C" does not exist in source "model_checker_contracts_inexistent_contract/input.sol". +Warning: Requested contract "C" does not exist in source "input.sol". diff --git a/test/cmdlineTests/model_checker_contracts_inexistent_source/args b/test/cmdlineTests/model_checker_contracts_inexistent_source/args index 6d91ecc34..b98256bf4 100644 --- a/test/cmdlineTests/model_checker_contracts_inexistent_source/args +++ b/test/cmdlineTests/model_checker_contracts_inexistent_source/args @@ -1 +1 @@ ---model-checker-engine all --model-checker-contracts model_checker_contracts_inexistent_source/A.sol:A +--model-checker-engine all --model-checker-contracts A.sol:A diff --git a/test/cmdlineTests/model_checker_contracts_inexistent_source/err b/test/cmdlineTests/model_checker_contracts_inexistent_source/err index 218588ad8..3c9348259 100644 --- a/test/cmdlineTests/model_checker_contracts_inexistent_source/err +++ b/test/cmdlineTests/model_checker_contracts_inexistent_source/err @@ -1 +1 @@ -Warning: Requested source "model_checker_contracts_inexistent_source/A.sol" does not exist. +Warning: Requested source "A.sol" does not exist. diff --git a/test/cmdlineTests/model_checker_contracts_one_contract_missing/args b/test/cmdlineTests/model_checker_contracts_one_contract_missing/args index 7ea3d3f04..8670db9b5 100644 --- a/test/cmdlineTests/model_checker_contracts_one_contract_missing/args +++ b/test/cmdlineTests/model_checker_contracts_one_contract_missing/args @@ -1 +1 @@ ---model-checker-engine all --model-checker-contracts model_checker_contracts_all_explicit/input.sol:,model_checker_contracts_all_explicit/input.sol:A +--model-checker-engine all --model-checker-contracts input.sol:,input.sol:A diff --git a/test/cmdlineTests/model_checker_contracts_one_contract_missing/err b/test/cmdlineTests/model_checker_contracts_one_contract_missing/err index d4e93bcd7..88e675624 100644 --- a/test/cmdlineTests/model_checker_contracts_one_contract_missing/err +++ b/test/cmdlineTests/model_checker_contracts_one_contract_missing/err @@ -1 +1 @@ -Error: Invalid option for --model-checker-contracts: model_checker_contracts_all_explicit/input.sol:,model_checker_contracts_all_explicit/input.sol:A +Error: Invalid option for --model-checker-contracts: input.sol:,input.sol:A diff --git a/test/cmdlineTests/model_checker_contracts_only_one/args b/test/cmdlineTests/model_checker_contracts_only_one/args index ae76a81d6..ff3ad9e1d 100644 --- a/test/cmdlineTests/model_checker_contracts_only_one/args +++ b/test/cmdlineTests/model_checker_contracts_only_one/args @@ -1 +1 @@ ---model-checker-engine all --model-checker-contracts model_checker_contracts_only_one/input.sol:A +--model-checker-engine all --model-checker-contracts input.sol:A diff --git a/test/cmdlineTests/model_checker_contracts_only_one/err b/test/cmdlineTests/model_checker_contracts_only_one/err index 9c8ade693..4472abefa 100644 --- a/test/cmdlineTests/model_checker_contracts_only_one/err +++ b/test/cmdlineTests/model_checker_contracts_only_one/err @@ -6,7 +6,7 @@ x = 0 Transaction trace: A.constructor() B.f(0) - --> model_checker_contracts_only_one/input.sol:5:3: + --> input.sol:5:3: | 5 | assert(x > 0); | ^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ y = 0 Transaction trace: A.constructor() A.g(0) - --> model_checker_contracts_only_one/input.sol:10:3: + --> input.sol:10:3: | 10 | assert(y > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_engine_all/err b/test/cmdlineTests/model_checker_engine_all/err index 12614fd55..18b877465 100644 --- a/test/cmdlineTests/model_checker_engine_all/err +++ b/test/cmdlineTests/model_checker_engine_all/err @@ -6,7 +6,7 @@ x = 0 Transaction trace: test.constructor() test.f(0) - --> model_checker_engine_all/input.sol:5:3: + --> input.sol:5:3: | 5 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_engine_bmc/err b/test/cmdlineTests/model_checker_engine_bmc/err index ed46539d6..dcedef48b 100644 --- a/test/cmdlineTests/model_checker_engine_bmc/err +++ b/test/cmdlineTests/model_checker_engine_bmc/err @@ -1,5 +1,5 @@ Warning: BMC: Assertion violation happens here. - --> model_checker_engine_bmc/input.sol:5:3: + --> input.sol:5:3: | 5 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_engine_chc/err b/test/cmdlineTests/model_checker_engine_chc/err index 95198fa20..18b877465 100644 --- a/test/cmdlineTests/model_checker_engine_chc/err +++ b/test/cmdlineTests/model_checker_engine_chc/err @@ -6,7 +6,7 @@ x = 0 Transaction trace: test.constructor() test.f(0) - --> model_checker_engine_chc/input.sol:5:3: + --> input.sol:5:3: | 5 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_ext_calls_trusted_chc/err b/test/cmdlineTests/model_checker_ext_calls_trusted_chc/err index e9c2d70a9..58be5002f 100644 --- a/test/cmdlineTests/model_checker_ext_calls_trusted_chc/err +++ b/test/cmdlineTests/model_checker_ext_calls_trusted_chc/err @@ -1,5 +1,5 @@ Warning: Function state mutability can be restricted to pure - --> model_checker_ext_calls_trusted_chc/input.sol:5:2: + --> input.sol:5:2: | 5 | function f() public view returns (uint) { | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/err b/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/err index b06333e43..73b355510 100644 --- a/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/err +++ b/test/cmdlineTests/model_checker_ext_calls_untrusted_chc/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() test.g(0) e.f() -- untrusted external call - --> model_checker_ext_calls_untrusted_chc/input.sol:11:3: + --> input.sol:11:3: | 11 | assert(x == 0); | ^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_invariants_all/err b/test/cmdlineTests/model_checker_invariants_all/err index dcef00b5f..b47334040 100644 --- a/test/cmdlineTests/model_checker_invariants_all/err +++ b/test/cmdlineTests/model_checker_invariants_all/err @@ -1,8 +1,8 @@ Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -Info: Contract invariant(s) for model_checker_invariants_all/input.sol:test: +Info: Contract invariant(s) for input.sol:test: (true || !(x >= 1)) -Reentrancy property(ies) for model_checker_invariants_all/input.sol:test: +Reentrancy property(ies) for input.sol:test: ((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors = 1 -> Assertion failed at assert(x == 0) diff --git a/test/cmdlineTests/model_checker_invariants_contract/err b/test/cmdlineTests/model_checker_invariants_contract/err index 3ecad6b35..2ea993088 100644 --- a/test/cmdlineTests/model_checker_invariants_contract/err +++ b/test/cmdlineTests/model_checker_invariants_contract/err @@ -1,4 +1,4 @@ Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -Info: Contract invariant(s) for model_checker_invariants_contract/input.sol:test: +Info: Contract invariant(s) for input.sol:test: (true || !(x >= 1)) diff --git a/test/cmdlineTests/model_checker_invariants_contract_eld/err b/test/cmdlineTests/model_checker_invariants_contract_eld/err index 29c5a5bc8..4dc823ec8 100644 --- a/test/cmdlineTests/model_checker_invariants_contract_eld/err +++ b/test/cmdlineTests/model_checker_invariants_contract_eld/err @@ -1,4 +1,4 @@ Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -Info: Contract invariant(s) for model_checker_invariants_contract_eld/input.sol:test: +Info: Contract invariant(s) for input.sol:test: (x = 0) diff --git a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err index 7764e89ab..b47334040 100644 --- a/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err +++ b/test/cmdlineTests/model_checker_invariants_contract_reentrancy/err @@ -1,8 +1,8 @@ Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -Info: Contract invariant(s) for model_checker_invariants_contract_reentrancy/input.sol:test: +Info: Contract invariant(s) for input.sol:test: (true || !(x >= 1)) -Reentrancy property(ies) for model_checker_invariants_contract_reentrancy/input.sol:test: +Reentrancy property(ies) for input.sol:test: ((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors = 1 -> Assertion failed at assert(x == 0) diff --git a/test/cmdlineTests/model_checker_invariants_reentrancy/err b/test/cmdlineTests/model_checker_invariants_reentrancy/err index 8891b0e18..42ac3ca73 100644 --- a/test/cmdlineTests/model_checker_invariants_reentrancy/err +++ b/test/cmdlineTests/model_checker_invariants_reentrancy/err @@ -1,6 +1,6 @@ Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. -Info: Reentrancy property(ies) for model_checker_invariants_reentrancy/input.sol:test: +Info: Reentrancy property(ies) for input.sol:test: ((( = 0) && (x!6 = x!4) && (x' = x)) || true || true || true || true) = 0 -> no errors = 1 -> Assertion failed at assert(x == 0) diff --git a/test/cmdlineTests/model_checker_show_proved_safe_default_all_engines/err b/test/cmdlineTests/model_checker_show_proved_safe_default_all_engines/err index b896b21bc..730e43b95 100644 --- a/test/cmdlineTests/model_checker_show_proved_safe_default_all_engines/err +++ b/test/cmdlineTests/model_checker_show_proved_safe_default_all_engines/err @@ -1,5 +1,5 @@ Warning: Function state mutability can be restricted to pure - --> model_checker_show_proved_safe_default_all_engines/input.sol:4:5: + --> input.sol:4:5: | 4 | function f(uint8 x) public { | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/model_checker_show_proved_safe_default_bmc/err b/test/cmdlineTests/model_checker_show_proved_safe_default_bmc/err index f4a2d33e0..7146c5192 100644 --- a/test/cmdlineTests/model_checker_show_proved_safe_default_bmc/err +++ b/test/cmdlineTests/model_checker_show_proved_safe_default_bmc/err @@ -1,5 +1,5 @@ Warning: Function state mutability can be restricted to pure - --> model_checker_show_proved_safe_default_bmc/input.sol:4:5: + --> input.sol:4:5: | 4 | function f(uint8 x) public { | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/model_checker_show_proved_safe_default_chc/err b/test/cmdlineTests/model_checker_show_proved_safe_default_chc/err index ab73c6bf5..730e43b95 100644 --- a/test/cmdlineTests/model_checker_show_proved_safe_default_chc/err +++ b/test/cmdlineTests/model_checker_show_proved_safe_default_chc/err @@ -1,5 +1,5 @@ Warning: Function state mutability can be restricted to pure - --> model_checker_show_proved_safe_default_chc/input.sol:4:5: + --> input.sol:4:5: | 4 | function f(uint8 x) public { | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/model_checker_show_proved_safe_true_all_engines/err b/test/cmdlineTests/model_checker_show_proved_safe_true_all_engines/err index 297eb497a..d45cd29d3 100644 --- a/test/cmdlineTests/model_checker_show_proved_safe_true_all_engines/err +++ b/test/cmdlineTests/model_checker_show_proved_safe_true_all_engines/err @@ -1,17 +1,17 @@ Warning: Function state mutability can be restricted to pure - --> model_checker_show_proved_safe_true_all_engines/input.sol:4:5: + --> input.sol:4:5: | 4 | function f(uint8 x) public { | ^ (Relevant source part starts here and spans across multiple lines). Info: CHC: Assertion violation check is safe! - --> model_checker_show_proved_safe_true_all_engines/input.sol:5:9: + --> input.sol:5:9: | 5 | assert(x >= 0); | ^^^^^^^^^^^^^^ Info: CHC: Assertion violation check is safe! - --> model_checker_show_proved_safe_true_all_engines/input.sol:6:9: + --> input.sol:6:9: | 6 | assert(x < 1000); | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_show_proved_safe_true_bmc/err b/test/cmdlineTests/model_checker_show_proved_safe_true_bmc/err index bcec557f6..6bcf720fa 100644 --- a/test/cmdlineTests/model_checker_show_proved_safe_true_bmc/err +++ b/test/cmdlineTests/model_checker_show_proved_safe_true_bmc/err @@ -1,17 +1,17 @@ Warning: Function state mutability can be restricted to pure - --> model_checker_show_proved_safe_true_bmc/input.sol:4:5: + --> input.sol:4:5: | 4 | function f(uint8 x) public { | ^ (Relevant source part starts here and spans across multiple lines). Info: BMC: Assertion violation check is safe! - --> model_checker_show_proved_safe_true_bmc/input.sol:5:9: + --> input.sol:5:9: | 5 | assert(x >= 0); | ^^^^^^^^^^^^^^ Info: BMC: Assertion violation check is safe! - --> model_checker_show_proved_safe_true_bmc/input.sol:6:9: + --> input.sol:6:9: | 6 | assert(x < 1000); | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_show_proved_safe_true_chc/err b/test/cmdlineTests/model_checker_show_proved_safe_true_chc/err index fc14f4946..d45cd29d3 100644 --- a/test/cmdlineTests/model_checker_show_proved_safe_true_chc/err +++ b/test/cmdlineTests/model_checker_show_proved_safe_true_chc/err @@ -1,17 +1,17 @@ Warning: Function state mutability can be restricted to pure - --> model_checker_show_proved_safe_true_chc/input.sol:4:5: + --> input.sol:4:5: | 4 | function f(uint8 x) public { | ^ (Relevant source part starts here and spans across multiple lines). Info: CHC: Assertion violation check is safe! - --> model_checker_show_proved_safe_true_chc/input.sol:5:9: + --> input.sol:5:9: | 5 | assert(x >= 0); | ^^^^^^^^^^^^^^ Info: CHC: Assertion violation check is safe! - --> model_checker_show_proved_safe_true_chc/input.sol:6:9: + --> input.sol:6:9: | 6 | assert(x < 1000); | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err b/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err index 7a338f614..18f317ac8 100644 --- a/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err +++ b/test/cmdlineTests/model_checker_show_unproved_true_all_engines/err @@ -1,5 +1,5 @@ Warning: CHC: Assertion violation might happen here. - --> model_checker_show_unproved_true_all_engines/input.sol:10:9: + --> input.sol:10:9: | 10 | assert(s.x > 0); | ^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_show_unproved_true_chc/err b/test/cmdlineTests/model_checker_show_unproved_true_chc/err index 8274f4b46..e68e08677 100644 --- a/test/cmdlineTests/model_checker_show_unproved_true_chc/err +++ b/test/cmdlineTests/model_checker_show_unproved_true_chc/err @@ -1,5 +1,5 @@ Warning: CHC: Assertion violation might happen here. - --> model_checker_show_unproved_true_chc/input.sol:10:9: + --> input.sol:10:9: | 10 | assert(s.x > 0); | ^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_show_unsupported_true_all_engines/err b/test/cmdlineTests/model_checker_show_unsupported_true_all_engines/err index 53c664ffc..681a59956 100644 --- a/test/cmdlineTests/model_checker_show_unsupported_true_all_engines/err +++ b/test/cmdlineTests/model_checker_show_unsupported_true_all_engines/err @@ -1,5 +1,5 @@ Warning: Inline assembly may cause SMTChecker to produce spurious warnings (false positives). - --> model_checker_show_unsupported_true_all_engines/input.sol:5:9: + --> input.sol:5:9: | 5 | assembly {} | ^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_show_unsupported_true_bmc/err b/test/cmdlineTests/model_checker_show_unsupported_true_bmc/err index 013a7b0f1..681a59956 100644 --- a/test/cmdlineTests/model_checker_show_unsupported_true_bmc/err +++ b/test/cmdlineTests/model_checker_show_unsupported_true_bmc/err @@ -1,5 +1,5 @@ Warning: Inline assembly may cause SMTChecker to produce spurious warnings (false positives). - --> model_checker_show_unsupported_true_bmc/input.sol:5:9: + --> input.sol:5:9: | 5 | assembly {} | ^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_show_unsupported_true_chc/err b/test/cmdlineTests/model_checker_show_unsupported_true_chc/err index 8dad0cc65..681a59956 100644 --- a/test/cmdlineTests/model_checker_show_unsupported_true_chc/err +++ b/test/cmdlineTests/model_checker_show_unsupported_true_chc/err @@ -1,5 +1,5 @@ Warning: Inline assembly may cause SMTChecker to produce spurious warnings (false positives). - --> model_checker_show_unsupported_true_chc/input.sol:5:9: + --> input.sol:5:9: | 5 | assembly {} | ^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_solvers_cvc5/err b/test/cmdlineTests/model_checker_solvers_cvc5/err index 1c36b103a..dcedef48b 100644 --- a/test/cmdlineTests/model_checker_solvers_cvc5/err +++ b/test/cmdlineTests/model_checker_solvers_cvc5/err @@ -1,5 +1,5 @@ Warning: BMC: Assertion violation happens here. - --> model_checker_solvers_cvc5/input.sol:5:3: + --> input.sol:5:3: | 5 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_solvers_cvc5_eld/err b/test/cmdlineTests/model_checker_solvers_cvc5_eld/err index 81a9f3a56..b2cb66270 100644 --- a/test/cmdlineTests/model_checker_solvers_cvc5_eld/err +++ b/test/cmdlineTests/model_checker_solvers_cvc5_eld/err @@ -1,7 +1,7 @@ Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Warning: BMC: Condition is always false. - --> model_checker_solvers_cvc5_eld/input.sol:6:7: + --> input.sol:6:7: | 6 | if (y == 0) | ^^^^^^ diff --git a/test/cmdlineTests/model_checker_solvers_eld/err b/test/cmdlineTests/model_checker_solvers_eld/err index ff7ad37b3..460764a0e 100644 --- a/test/cmdlineTests/model_checker_solvers_eld/err +++ b/test/cmdlineTests/model_checker_solvers_eld/err @@ -1,5 +1,5 @@ Warning: CHC: Assertion violation happens here. - --> model_checker_solvers_eld/input.sol:5:3: + --> input.sol:5:3: | 5 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_solvers_z3/err b/test/cmdlineTests/model_checker_solvers_z3/err index 67349d8e1..18b877465 100644 --- a/test/cmdlineTests/model_checker_solvers_z3/err +++ b/test/cmdlineTests/model_checker_solvers_z3/err @@ -6,7 +6,7 @@ x = 0 Transaction trace: test.constructor() test.f(0) - --> model_checker_solvers_z3/input.sol:5:3: + --> input.sol:5:3: | 5 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_solvers_z3_implicit/err b/test/cmdlineTests/model_checker_solvers_z3_implicit/err index 98d61828d..18b877465 100644 --- a/test/cmdlineTests/model_checker_solvers_z3_implicit/err +++ b/test/cmdlineTests/model_checker_solvers_z3_implicit/err @@ -6,7 +6,7 @@ x = 0 Transaction trace: test.constructor() test.f(0) - --> model_checker_solvers_z3_implicit/input.sol:5:3: + --> input.sol:5:3: | 5 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_solvers_z3_smtlib2/err b/test/cmdlineTests/model_checker_solvers_z3_smtlib2/err index 5699afcde..18b877465 100644 --- a/test/cmdlineTests/model_checker_solvers_z3_smtlib2/err +++ b/test/cmdlineTests/model_checker_solvers_z3_smtlib2/err @@ -6,7 +6,7 @@ x = 0 Transaction trace: test.constructor() test.f(0) - --> model_checker_solvers_z3_smtlib2/input.sol:5:3: + --> input.sol:5:3: | 5 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_all_all_engines/err b/test/cmdlineTests/model_checker_targets_all_all_engines/err index c67d97b61..e095ba263 100644 --- a/test/cmdlineTests/model_checker_targets_all_all_engines/err +++ b/test/cmdlineTests/model_checker_targets_all_all_engines/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 0) - --> model_checker_targets_all_all_engines/input.sol:7:3: + --> input.sol:7:3: | 7 | --x; | ^^^ @@ -23,7 +23,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 2) - --> model_checker_targets_all_all_engines/input.sol:8:3: + --> input.sol:8:3: | 8 | x + type(uint).max; | ^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_all_all_engines/input.sol:9:3: + --> input.sol:9:3: | 9 | 2 / x; | ^^^^^ @@ -53,7 +53,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_all_all_engines/input.sol:11:3: + --> input.sol:11:3: | 11 | assert(x > 0); | ^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_all_all_engines/input.sol:12:3: + --> input.sol:12:3: | 12 | arr.pop(); | ^^^^^^^^^ @@ -83,7 +83,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_all_all_engines/input.sol:13:3: + --> input.sol:13:3: | 13 | arr[x]; | ^^^^^^ @@ -91,7 +91,7 @@ test.f(0x0, 1) Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Warning: BMC: Condition is always true. - --> model_checker_targets_all_all_engines/input.sol:6:11: + --> input.sol:6:11: | 6 | require(x >= 0); | ^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_all_bmc/err b/test/cmdlineTests/model_checker_targets_all_bmc/err index 27a51a67b..3887cc6b2 100644 --- a/test/cmdlineTests/model_checker_targets_all_bmc/err +++ b/test/cmdlineTests/model_checker_targets_all_bmc/err @@ -1,12 +1,12 @@ Warning: BMC: Condition is always true. - --> model_checker_targets_all_bmc/input.sol:6:11: + --> input.sol:6:11: | 6 | require(x >= 0); | ^^^^^^ Note: Callstack: Warning: BMC: Underflow (resulting value less than 0) happens here. - --> model_checker_targets_all_bmc/input.sol:7:3: + --> input.sol:7:3: | 7 | --x; | ^^^ @@ -19,7 +19,7 @@ Note: Callstack: Note: Warning: BMC: Overflow (resulting value larger than 2**256 - 1) happens here. - --> model_checker_targets_all_bmc/input.sol:8:3: + --> input.sol:8:3: | 8 | x + type(uint).max; | ^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ Note: Callstack: Note: Warning: BMC: Division by zero happens here. - --> model_checker_targets_all_bmc/input.sol:9:3: + --> input.sol:9:3: | 9 | 2 / x; | ^^^^^ @@ -45,7 +45,7 @@ Note: Callstack: Note: Warning: BMC: Insufficient funds happens here. - --> model_checker_targets_all_bmc/input.sol:10:3: + --> input.sol:10:3: | 10 | a.transfer(x); | ^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ Note: Callstack: Note: Warning: BMC: Assertion violation happens here. - --> model_checker_targets_all_bmc/input.sol:11:3: + --> input.sol:11:3: | 11 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_all_chc/err b/test/cmdlineTests/model_checker_targets_all_chc/err index 9c257cefe..c3853983a 100644 --- a/test/cmdlineTests/model_checker_targets_all_chc/err +++ b/test/cmdlineTests/model_checker_targets_all_chc/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 0) - --> model_checker_targets_all_chc/input.sol:7:3: + --> input.sol:7:3: | 7 | --x; | ^^^ @@ -23,7 +23,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 2) - --> model_checker_targets_all_chc/input.sol:8:3: + --> input.sol:8:3: | 8 | x + type(uint).max; | ^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_all_chc/input.sol:9:3: + --> input.sol:9:3: | 9 | 2 / x; | ^^^^^ @@ -53,7 +53,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_all_chc/input.sol:11:3: + --> input.sol:11:3: | 11 | assert(x > 0); | ^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_all_chc/input.sol:12:3: + --> input.sol:12:3: | 12 | arr.pop(); | ^^^^^^^^^ @@ -83,7 +83,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_all_chc/input.sol:13:3: + --> input.sol:13:3: | 13 | arr[x]; | ^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_assert_bmc/err b/test/cmdlineTests/model_checker_targets_assert_bmc/err index 90486bf79..27395c9dc 100644 --- a/test/cmdlineTests/model_checker_targets_assert_bmc/err +++ b/test/cmdlineTests/model_checker_targets_assert_bmc/err @@ -1,5 +1,5 @@ Warning: BMC: Assertion violation happens here. - --> model_checker_targets_assert_bmc/input.sol:11:3: + --> input.sol:11:3: | 11 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_assert_chc/err b/test/cmdlineTests/model_checker_targets_assert_chc/err index 1bf48bfa9..ada7c3d3d 100644 --- a/test/cmdlineTests/model_checker_targets_assert_chc/err +++ b/test/cmdlineTests/model_checker_targets_assert_chc/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_assert_chc/input.sol:11:3: + --> input.sol:11:3: | 11 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_balance_bmc/err b/test/cmdlineTests/model_checker_targets_balance_bmc/err index 39a8aac56..178bd6662 100644 --- a/test/cmdlineTests/model_checker_targets_balance_bmc/err +++ b/test/cmdlineTests/model_checker_targets_balance_bmc/err @@ -1,5 +1,5 @@ Warning: BMC: Insufficient funds happens here. - --> model_checker_targets_balance_bmc/input.sol:10:3: + --> input.sol:10:3: | 10 | a.transfer(x); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_constant_condition_bmc/err b/test/cmdlineTests/model_checker_targets_constant_condition_bmc/err index 6a376dd7e..a7228dd76 100644 --- a/test/cmdlineTests/model_checker_targets_constant_condition_bmc/err +++ b/test/cmdlineTests/model_checker_targets_constant_condition_bmc/err @@ -1,5 +1,5 @@ Warning: BMC: Condition is always true. - --> model_checker_targets_constant_condition_bmc/input.sol:6:11: + --> input.sol:6:11: | 6 | require(x >= 0); | ^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_default_all_engines/err b/test/cmdlineTests/model_checker_targets_default_all_engines/err index 62d3b203c..58cbc01f1 100644 --- a/test/cmdlineTests/model_checker_targets_default_all_engines/err +++ b/test/cmdlineTests/model_checker_targets_default_all_engines/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_default_all_engines/input.sol:9:3: + --> input.sol:9:3: | 9 | 2 / x; | ^^^^^ @@ -23,7 +23,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_default_all_engines/input.sol:11:3: + --> input.sol:11:3: | 11 | assert(x > 0); | ^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_default_all_engines/input.sol:12:3: + --> input.sol:12:3: | 12 | arr.pop(); | ^^^^^^^^^ @@ -53,7 +53,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_default_all_engines/input.sol:13:3: + --> input.sol:13:3: | 13 | arr[x]; | ^^^^^^ @@ -61,7 +61,7 @@ test.f(0x0, 1) Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. Warning: BMC: Condition is always true. - --> model_checker_targets_default_all_engines/input.sol:6:11: + --> input.sol:6:11: | 6 | require(x >= 0); | ^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_default_bmc/err b/test/cmdlineTests/model_checker_targets_default_bmc/err index 1122be36b..bc85e3cb4 100644 --- a/test/cmdlineTests/model_checker_targets_default_bmc/err +++ b/test/cmdlineTests/model_checker_targets_default_bmc/err @@ -1,12 +1,12 @@ Warning: BMC: Condition is always true. - --> model_checker_targets_default_bmc/input.sol:6:11: + --> input.sol:6:11: | 6 | require(x >= 0); | ^^^^^^ Note: Callstack: Warning: BMC: Division by zero happens here. - --> model_checker_targets_default_bmc/input.sol:9:3: + --> input.sol:9:3: | 9 | 2 / x; | ^^^^^ @@ -19,7 +19,7 @@ Note: Callstack: Note: Warning: BMC: Insufficient funds happens here. - --> model_checker_targets_default_bmc/input.sol:10:3: + --> input.sol:10:3: | 10 | a.transfer(x); | ^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ Note: Callstack: Note: Warning: BMC: Assertion violation happens here. - --> model_checker_targets_default_bmc/input.sol:11:3: + --> input.sol:11:3: | 11 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_default_chc/err b/test/cmdlineTests/model_checker_targets_default_chc/err index 70f3c5bc6..e8b738216 100644 --- a/test/cmdlineTests/model_checker_targets_default_chc/err +++ b/test/cmdlineTests/model_checker_targets_default_chc/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_default_chc/input.sol:9:3: + --> input.sol:9:3: | 9 | 2 / x; | ^^^^^ @@ -23,7 +23,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_default_chc/input.sol:11:3: + --> input.sol:11:3: | 11 | assert(x > 0); | ^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_default_chc/input.sol:12:3: + --> input.sol:12:3: | 12 | arr.pop(); | ^^^^^^^^^ @@ -53,7 +53,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_default_chc/input.sol:13:3: + --> input.sol:13:3: | 13 | arr[x]; | ^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_div_by_zero_bmc/err b/test/cmdlineTests/model_checker_targets_div_by_zero_bmc/err index bcf2c0c83..2d554ebce 100644 --- a/test/cmdlineTests/model_checker_targets_div_by_zero_bmc/err +++ b/test/cmdlineTests/model_checker_targets_div_by_zero_bmc/err @@ -1,5 +1,5 @@ Warning: BMC: Division by zero happens here. - --> model_checker_targets_div_by_zero_bmc/input.sol:9:3: + --> input.sol:9:3: | 9 | 2 / x; | ^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err b/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err index 3156dd90b..81616b3be 100644 --- a/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err +++ b/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_div_by_zero_chc/input.sol:9:3: + --> input.sol:9:3: | 9 | 2 / x; | ^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err b/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err index b4426a80e..907a19f1e 100644 --- a/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err +++ b/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_out_of_bounds_chc/input.sol:13:3: + --> input.sol:13:3: | 13 | arr[x]; | ^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_overflow_bmc/err b/test/cmdlineTests/model_checker_targets_overflow_bmc/err index f2f475c30..a0f9ff1e0 100644 --- a/test/cmdlineTests/model_checker_targets_overflow_bmc/err +++ b/test/cmdlineTests/model_checker_targets_overflow_bmc/err @@ -1,5 +1,5 @@ Warning: BMC: Overflow (resulting value larger than 2**256 - 1) happens here. - --> model_checker_targets_overflow_bmc/input.sol:8:3: + --> input.sol:8:3: | 8 | x + type(uint).max; | ^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_overflow_chc/err b/test/cmdlineTests/model_checker_targets_overflow_chc/err index e7f98ff4d..60298f022 100644 --- a/test/cmdlineTests/model_checker_targets_overflow_chc/err +++ b/test/cmdlineTests/model_checker_targets_overflow_chc/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 2) - --> model_checker_targets_overflow_chc/input.sol:8:3: + --> input.sol:8:3: | 8 | x + type(uint).max; | ^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_pop_empty_chc/err b/test/cmdlineTests/model_checker_targets_pop_empty_chc/err index d3478a700..a01248775 100644 --- a/test/cmdlineTests/model_checker_targets_pop_empty_chc/err +++ b/test/cmdlineTests/model_checker_targets_pop_empty_chc/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_pop_empty_chc/input.sol:12:3: + --> input.sol:12:3: | 12 | arr.pop(); | ^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_underflow_bmc/err b/test/cmdlineTests/model_checker_targets_underflow_bmc/err index 2162bec3a..db1463923 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_bmc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_bmc/err @@ -1,5 +1,5 @@ Warning: BMC: Underflow (resulting value less than 0) happens here. - --> model_checker_targets_underflow_bmc/input.sol:7:3: + --> input.sol:7:3: | 7 | --x; | ^^^ diff --git a/test/cmdlineTests/model_checker_targets_underflow_chc/err b/test/cmdlineTests/model_checker_targets_underflow_chc/err index 448b0e25c..57c6649a4 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_chc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_chc/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 0) - --> model_checker_targets_underflow_chc/input.sol:7:3: + --> input.sol:7:3: | 7 | --x; | ^^^ diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_bmc/err b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_bmc/err index 9712b8cb7..670b064ce 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_bmc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_bmc/err @@ -1,5 +1,5 @@ Warning: BMC: Underflow (resulting value less than 0) happens here. - --> model_checker_targets_underflow_overflow_assert_bmc/input.sol:7:3: + --> input.sol:7:3: | 7 | --x; | ^^^ @@ -12,7 +12,7 @@ Note: Callstack: Note: Warning: BMC: Overflow (resulting value larger than 2**256 - 1) happens here. - --> model_checker_targets_underflow_overflow_assert_bmc/input.sol:8:3: + --> input.sol:8:3: | 8 | x + type(uint).max; | ^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ Note: Callstack: Note: Warning: BMC: Assertion violation happens here. - --> model_checker_targets_underflow_overflow_assert_bmc/input.sol:11:3: + --> input.sol:11:3: | 11 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err index a0fbbe61a..4602e7600 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 0) - --> model_checker_targets_underflow_overflow_assert_chc/input.sol:7:3: + --> input.sol:7:3: | 7 | --x; | ^^^ @@ -23,7 +23,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 2) - --> model_checker_targets_underflow_overflow_assert_chc/input.sol:8:3: + --> input.sol:8:3: | 8 | x + type(uint).max; | ^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> model_checker_targets_underflow_overflow_assert_chc/input.sol:11:3: + --> input.sol:11:3: | 11 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_bmc/err b/test/cmdlineTests/model_checker_targets_underflow_overflow_bmc/err index f3675ac5a..ea6dfb99c 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_bmc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_bmc/err @@ -1,5 +1,5 @@ Warning: BMC: Underflow (resulting value less than 0) happens here. - --> model_checker_targets_underflow_overflow_bmc/input.sol:7:3: + --> input.sol:7:3: | 7 | --x; | ^^^ @@ -12,7 +12,7 @@ Note: Callstack: Note: Warning: BMC: Overflow (resulting value larger than 2**256 - 1) happens here. - --> model_checker_targets_underflow_overflow_bmc/input.sol:8:3: + --> input.sol:8:3: | 8 | x + type(uint).max; | ^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err b/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err index 0dcfb1c25..8eed85ac3 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err @@ -8,7 +8,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 0) - --> model_checker_targets_underflow_overflow_chc/input.sol:7:3: + --> input.sol:7:3: | 7 | --x; | ^^^ @@ -23,7 +23,7 @@ Transaction trace: test.constructor() State: arr = [] test.f(0x0, 2) - --> model_checker_targets_underflow_overflow_chc/input.sol:8:3: + --> input.sol:8:3: | 8 | x + type(uint).max; | ^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/name_simplifier/output b/test/cmdlineTests/name_simplifier/output index 04abaf600..8eeff65b9 100644 --- a/test/cmdlineTests/name_simplifier/output +++ b/test/cmdlineTests/name_simplifier/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"name_simplifier/input.sol" +/// @use-src 0:"input.sol" object "C_59" { code { { @@ -12,7 +12,7 @@ object "C_59" { return(_1, _2) } } - /// @use-src 0:"name_simplifier/input.sol" + /// @use-src 0:"input.sol" object "C_59_deployed" { code { { diff --git a/test/cmdlineTests/no_cbor_metadata/output b/test/cmdlineTests/no_cbor_metadata/output index 0328ece3f..295bc228b 100644 --- a/test/cmdlineTests/no_cbor_metadata/output +++ b/test/cmdlineTests/no_cbor_metadata/output @@ -1,4 +1,4 @@ -======= no_cbor_metadata/input.sol:C ======= +======= input.sol:C ======= Binary: 608080604052346013576003908160188239f35b5f80fdfe5f80fd diff --git a/test/cmdlineTests/no_contract_combined_json/output b/test/cmdlineTests/no_contract_combined_json/output index 8c454e341..a408cbdbc 100644 --- a/test/cmdlineTests/no_contract_combined_json/output +++ b/test/cmdlineTests/no_contract_combined_json/output @@ -1,11 +1,11 @@ { "sourceList": [ - "no_contract_combined_json/input.sol" + "input.sol" ], "sources": { - "no_contract_combined_json/input.sol": { + "input.sol": { "AST": { - "absolutePath": "no_contract_combined_json/input.sol", + "absolutePath": "input.sol", "exportedSymbols": {}, "id": 2, "license": "GPL-3.0", diff --git a/test/cmdlineTests/no_import_callback/args b/test/cmdlineTests/no_import_callback/args index e816120d0..7efc6a77b 100644 --- a/test/cmdlineTests/no_import_callback/args +++ b/test/cmdlineTests/no_import_callback/args @@ -1 +1 @@ ---no-import-callback no_import_callback/contract_1.sol +--no-import-callback contract_1.sol diff --git a/test/cmdlineTests/no_import_callback/err b/test/cmdlineTests/no_import_callback/err index 45690e34c..c4e6d5701 100644 --- a/test/cmdlineTests/no_import_callback/err +++ b/test/cmdlineTests/no_import_callback/err @@ -1,5 +1,5 @@ Error: Source "contract_2.sol" not found: No import callback. - --> no_import_callback/contract_1.sol:4:1: + --> contract_1.sol:4:1: | 4 | import "contract_2.sol"; | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/object_compiler/output b/test/cmdlineTests/object_compiler/output index a88851b96..b552b3f24 100644 --- a/test/cmdlineTests/object_compiler/output +++ b/test/cmdlineTests/object_compiler/output @@ -1,5 +1,5 @@ -======= object_compiler/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "MyContract" { @@ -26,40 +26,40 @@ Binary representation: 335f55600880600d5f395ff3fe5f545f5260205ff3 Text representation: - /* "object_compiler/input.yul":65:73 */ + /* "input.yul":65:73 */ caller - /* "object_compiler/input.yul":62:63 */ + /* "input.yul":62:63 */ 0x00 - /* "object_compiler/input.yul":55:74 */ + /* "input.yul":55:74 */ sstore - /* "object_compiler/input.yul":97:116 */ + /* "input.yul":97:116 */ dataSize(sub_0) - /* "object_compiler/input.yul":141:162 */ + /* "input.yul":141:162 */ dup1 dataOffset(sub_0) - /* "object_compiler/input.yul":138:139 */ + /* "input.yul":138:139 */ 0x00 - /* "object_compiler/input.yul":129:167 */ + /* "input.yul":129:167 */ codecopy - /* "object_compiler/input.yul":187:188 */ + /* "input.yul":187:188 */ 0x00 - /* "object_compiler/input.yul":180:193 */ + /* "input.yul":180:193 */ return stop sub_0: assembly { - /* "object_compiler/input.yul":294:295 */ + /* "input.yul":294:295 */ 0x00 - /* "object_compiler/input.yul":288:296 */ + /* "input.yul":288:296 */ sload - /* "object_compiler/input.yul":285:286 */ + /* "input.yul":285:286 */ 0x00 - /* "object_compiler/input.yul":278:297 */ + /* "input.yul":278:297 */ mstore - /* "object_compiler/input.yul":324:328 */ + /* "input.yul":324:328 */ 0x20 - /* "object_compiler/input.yul":321:322 */ + /* "input.yul":321:322 */ 0x00 - /* "object_compiler/input.yul":314:329 */ + /* "input.yul":314:329 */ return } diff --git a/test/cmdlineTests/optimize_full_storage_write/output b/test/cmdlineTests/optimize_full_storage_write/output index 9ebec71f0..53e00008b 100644 --- a/test/cmdlineTests/optimize_full_storage_write/output +++ b/test/cmdlineTests/optimize_full_storage_write/output @@ -1,7 +1,7 @@ -======= optimize_full_storage_write/input.sol:OptimizeFullSlotWrite ======= +======= input.sol:OptimizeFullSlotWrite ======= EVM assembly: - /* "optimize_full_storage_write/input.sol":60:213 contract OptimizeFullSlotWrite {... */ + /* "input.sol":60:213 contract OptimizeFullSlotWrite {... */ mstore(0x40, 0x80) callvalue dup1 @@ -21,7 +21,7 @@ tag_1: stop sub_0: assembly { - /* "optimize_full_storage_write/input.sol":60:213 contract OptimizeFullSlotWrite {... */ + /* "input.sol":60:213 contract OptimizeFullSlotWrite {... */ mstore(0x40, 0x80) callvalue dup1 @@ -40,16 +40,16 @@ sub_0: assembly { jumpi tag_2: revert(0x00, 0x00) - /* "optimize_full_storage_write/input.sol":111:211 function f() public {... */ + /* "input.sol":111:211 function f() public {... */ tag_3: tag_4 - /* "optimize_full_storage_write/input.sol":192:207 nums[3] = 44444 */ + /* "input.sol":192:207 nums[3] = 44444 */ 0xad9c000000000000823500000000000056ce0000000000002b67 - /* "optimize_full_storage_write/input.sol":135:139 nums */ + /* "input.sol":135:139 nums */ 0x00 - /* "optimize_full_storage_write/input.sol":192:207 nums[3] = 44444 */ + /* "input.sol":192:207 nums[3] = 44444 */ sstore - /* "optimize_full_storage_write/input.sol":111:211 function f() public {... */ + /* "input.sol":111:211 function f() public {... */ jump tag_4: stop diff --git a/test/cmdlineTests/optimizer_BlockDeDuplicator/err b/test/cmdlineTests/optimizer_BlockDeDuplicator/err index e29fc4fc3..9d851c2ac 100644 --- a/test/cmdlineTests/optimizer_BlockDeDuplicator/err +++ b/test/cmdlineTests/optimizer_BlockDeDuplicator/err @@ -1,11 +1,11 @@ Warning: Statement has no effect. - --> optimizer_BlockDeDuplicator/input.sol:7:27: + --> input.sol:7:27: | 7 | function f() public { true ? 1 : 3;} | ^^^^^^^^^^^^ Warning: Function state mutability can be restricted to pure - --> optimizer_BlockDeDuplicator/input.sol:7:5: + --> input.sol:7:5: | 7 | function f() public { true ? 1 : 3;} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/optimizer_BlockDeDuplicator/output b/test/cmdlineTests/optimizer_BlockDeDuplicator/output index fb72e4bc1..b3a645be3 100644 --- a/test/cmdlineTests/optimizer_BlockDeDuplicator/output +++ b/test/cmdlineTests/optimizer_BlockDeDuplicator/output @@ -1,23 +1,23 @@ -======= optimizer_BlockDeDuplicator/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "optimizer_BlockDeDuplicator/input.sol":60:213 contract C {... */ + /* "input.sol":60:213 contract C {... */ mstore(0x40, 0x80) - /* "optimizer_BlockDeDuplicator/input.sol":179:210 function() r = true ? fun_x : f */ + /* "input.sol":179:210 function() r = true ? fun_x : f */ 0x00 dup1 sload not(sub(shl(0x40, 0x01), 0x01)) and - /* "optimizer_BlockDeDuplicator/input.sol":201:206 fun_x */ + /* "input.sol":201:206 fun_x */ or(tag_0_7, shl(0x20, tag_2)) sub(shl(0x40, 0x01), 0x01) - /* "optimizer_BlockDeDuplicator/input.sol":179:210 function() r = true ? fun_x : f */ + /* "input.sol":179:210 function() r = true ? fun_x : f */ and or swap1 sstore - /* "optimizer_BlockDeDuplicator/input.sol":60:213 contract C {... */ + /* "input.sol":60:213 contract C {... */ callvalue dup1 iszero @@ -27,10 +27,10 @@ EVM assembly: tag_5: pop jump(tag_6) - /* "optimizer_BlockDeDuplicator/input.sol":138:174 function f() public { true ? 1 : 3;} */ + /* "input.sol":138:174 function f() public { true ? 1 : 3;} */ tag_2: jump // out - /* "optimizer_BlockDeDuplicator/input.sol":60:213 contract C {... */ + /* "input.sol":60:213 contract C {... */ tag_6: dataSize(sub_0) dup1 @@ -42,7 +42,7 @@ tag_6: stop sub_0: assembly { - /* "optimizer_BlockDeDuplicator/input.sol":60:213 contract C {... */ + /* "input.sol":60:213 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -71,7 +71,7 @@ sub_0: assembly { jumpi tag_2: revert(0x00, 0x00) - /* "optimizer_BlockDeDuplicator/input.sol":138:174 function f() public { true ? 1 : 3;} */ + /* "input.sol":138:174 function f() public { true ? 1 : 3;} */ tag_3: stop tag_7: diff --git a/test/cmdlineTests/optimizer_array_sload/output b/test/cmdlineTests/optimizer_array_sload/output index c1e0796f5..a16ac43a0 100644 --- a/test/cmdlineTests/optimizer_array_sload/output +++ b/test/cmdlineTests/optimizer_array_sload/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"optimizer_array_sload/input.sol" +/// @use-src 0:"input.sol" object "Arraysum_34" { code { { @@ -12,7 +12,7 @@ object "Arraysum_34" { return(_1, _2) } } - /// @use-src 0:"optimizer_array_sload/input.sol" + /// @use-src 0:"input.sol" object "Arraysum_34_deployed" { code { { diff --git a/test/cmdlineTests/optimizer_inliner_add/output b/test/cmdlineTests/optimizer_inliner_add/output index 9ebc9977d..e4076c2fb 100644 --- a/test/cmdlineTests/optimizer_inliner_add/output +++ b/test/cmdlineTests/optimizer_inliner_add/output @@ -1,7 +1,7 @@ -======= optimizer_inliner_add/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "optimizer_inliner_add/input.sol":165:305 contract C {... */ + /* "input.sol":165:305 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -21,7 +21,7 @@ tag_1: stop sub_0: assembly { - /* "optimizer_inliner_add/input.sol":165:305 contract C {... */ + /* "input.sol":165:305 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -40,7 +40,7 @@ sub_0: assembly { jumpi tag_2: revert(0x00, 0x00) - /* "optimizer_inliner_add/input.sol":182:303 function f() public pure {... */ + /* "input.sol":182:303 function f() public pure {... */ tag_3: tag_4 tag_5 @@ -48,32 +48,32 @@ sub_0: assembly { tag_4: stop tag_5: - /* "optimizer_inliner_add/input.sol":221:227 uint x */ + /* "input.sol":221:227 uint x */ 0x00 - /* "optimizer_inliner_add/input.sol":217:297 for(uint x = 0; x < 10; x = unsafe_add(x, unsafe_add(x, 1)))... */ + /* "input.sol":217:297 for(uint x = 0; x < 10; x = unsafe_add(x, unsafe_add(x, 1)))... */ tag_7: - /* "optimizer_inliner_add/input.sol":237:239 10 */ + /* "input.sol":237:239 10 */ 0x0a - /* "optimizer_inliner_add/input.sol":233:234 x */ + /* "input.sol":233:234 x */ dup2 - /* "optimizer_inliner_add/input.sol":233:239 x < 10 */ + /* "input.sol":233:239 x < 10 */ lt - /* "optimizer_inliner_add/input.sol":217:297 for(uint x = 0; x < 10; x = unsafe_add(x, unsafe_add(x, 1)))... */ + /* "input.sol":217:297 for(uint x = 0; x < 10; x = unsafe_add(x, unsafe_add(x, 1)))... */ iszero tag_8 jumpi - /* "optimizer_inliner_add/input.sol":149:154 x + y */ + /* "input.sol":149:154 x + y */ dup1 add - /* "optimizer_inliner_add/input.sol":273:274 1 */ + /* "input.sol":273:274 1 */ 0x01 - /* "optimizer_inliner_add/input.sol":149:154 x + y */ + /* "input.sol":149:154 x + y */ add - /* "optimizer_inliner_add/input.sol":217:297 for(uint x = 0; x < 10; x = unsafe_add(x, unsafe_add(x, 1)))... */ + /* "input.sol":217:297 for(uint x = 0; x < 10; x = unsafe_add(x, unsafe_add(x, 1)))... */ jump(tag_7) tag_8: pop - /* "optimizer_inliner_add/input.sol":182:303 function f() public pure {... */ + /* "input.sol":182:303 function f() public pure {... */ jump // out auxdata: diff --git a/test/cmdlineTests/optimizer_inliner_call_from_constructor/output b/test/cmdlineTests/optimizer_inliner_call_from_constructor/output index f42f9de09..8c7b544bb 100644 --- a/test/cmdlineTests/optimizer_inliner_call_from_constructor/output +++ b/test/cmdlineTests/optimizer_inliner_call_from_constructor/output @@ -1,9 +1,9 @@ -======= optimizer_inliner_call_from_constructor/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "optimizer_inliner_call_from_constructor/input.sol":60:263 contract C {... */ + /* "input.sol":60:263 contract C {... */ mstore(0x40, 0x80) - /* "optimizer_inliner_call_from_constructor/input.sol":89:115 constructor() { x = a(); } */ + /* "input.sol":89:115 constructor() { x = a(); } */ callvalue dup1 iszero @@ -12,13 +12,13 @@ EVM assembly: revert(0x00, 0x00) tag_1: pop - /* "optimizer_inliner_call_from_constructor/input.sol":257:258 6 */ + /* "input.sol":257:258 6 */ 0x06 - /* "optimizer_inliner_call_from_constructor/input.sol":105:106 x */ + /* "input.sol":105:106 x */ 0x00 - /* "optimizer_inliner_call_from_constructor/input.sol":105:112 x = a() */ + /* "input.sol":105:112 x = a() */ sstore - /* "optimizer_inliner_call_from_constructor/input.sol":60:263 contract C {... */ + /* "input.sol":60:263 contract C {... */ dataSize(sub_0) dup1 dataOffset(sub_0) @@ -29,7 +29,7 @@ tag_1: stop sub_0: assembly { - /* "optimizer_inliner_call_from_constructor/input.sol":60:263 contract C {... */ + /* "input.sol":60:263 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -48,11 +48,11 @@ sub_0: assembly { jumpi tag_2: revert(0x00, 0x00) - /* "optimizer_inliner_call_from_constructor/input.sol":120:175 function a() public pure returns (uint) { return f(); } */ + /* "input.sol":120:175 function a() public pure returns (uint) { return f(); } */ tag_3: - /* "optimizer_inliner_call_from_constructor/input.sol":257:258 6 */ + /* "input.sol":257:258 6 */ 0x06 - /* "optimizer_inliner_call_from_constructor/input.sol":120:175 function a() public pure returns (uint) { return f(); } */ + /* "input.sol":120:175 function a() public pure returns (uint) { return f(); } */ mload(0x40) /* "#utility.yul":160:185 */ swap1 @@ -62,7 +62,7 @@ sub_0: assembly { 0x20 /* "#utility.yul":133:151 */ add - /* "optimizer_inliner_call_from_constructor/input.sol":120:175 function a() public pure returns (uint) { return f(); } */ + /* "input.sol":120:175 function a() public pure returns (uint) { return f(); } */ mload(0x40) dup1 swap2 diff --git a/test/cmdlineTests/optimizer_inliner_dynamic_reference/output b/test/cmdlineTests/optimizer_inliner_dynamic_reference/output index b1c5c74d9..5313893fc 100644 --- a/test/cmdlineTests/optimizer_inliner_dynamic_reference/output +++ b/test/cmdlineTests/optimizer_inliner_dynamic_reference/output @@ -1,7 +1,7 @@ -======= optimizer_inliner_dynamic_reference/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "optimizer_inliner_dynamic_reference/input.sol":60:367 contract C {... */ + /* "input.sol":60:367 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -21,7 +21,7 @@ tag_1: stop sub_0: assembly { - /* "optimizer_inliner_dynamic_reference/input.sol":60:367 contract C {... */ + /* "input.sol":60:367 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -50,11 +50,11 @@ sub_0: assembly { jumpi tag_2: revert(0x00, 0x00) - /* "optimizer_inliner_dynamic_reference/input.sol":160:215 function a() public pure returns (uint) { return f(); } */ + /* "input.sol":160:215 function a() public pure returns (uint) { return f(); } */ tag_3: - /* "optimizer_inliner_dynamic_reference/input.sol":361:362 6 */ + /* "input.sol":361:362 6 */ 0x06 - /* "optimizer_inliner_dynamic_reference/input.sol":160:215 function a() public pure returns (uint) { return f(); } */ + /* "input.sol":160:215 function a() public pure returns (uint) { return f(); } */ tag_6: mload(0x40) /* "#utility.yul":160:185 */ @@ -65,78 +65,78 @@ sub_0: assembly { 0x20 /* "#utility.yul":133:151 */ add - /* "optimizer_inliner_dynamic_reference/input.sol":160:215 function a() public pure returns (uint) { return f(); } */ + /* "input.sol":160:215 function a() public pure returns (uint) { return f(); } */ mload(0x40) dup1 swap2 sub swap1 return - /* "optimizer_inliner_dynamic_reference/input.sol":246:305 function h() public view returns (uint) { return x() + 1; } */ + /* "input.sol":246:305 function h() public view returns (uint) { return x() + 1; } */ tag_4: tag_6 tag_11 jump // in - /* "optimizer_inliner_dynamic_reference/input.sol":125:155 function g() public { x = f; } */ + /* "input.sol":125:155 function g() public { x = f; } */ tag_5: - /* "optimizer_inliner_dynamic_reference/input.sol":147:148 x */ + /* "input.sol":147:148 x */ 0x00 - /* "optimizer_inliner_dynamic_reference/input.sol":147:152 x = f */ + /* "input.sol":147:152 x = f */ dup1 sload not(0xffffffffffffffff) and - /* "optimizer_inliner_dynamic_reference/input.sol":151:152 f */ + /* "input.sol":151:152 f */ tag_17 - /* "optimizer_inliner_dynamic_reference/input.sol":147:152 x = f */ + /* "input.sol":147:152 x = f */ or swap1 sstore - /* "optimizer_inliner_dynamic_reference/input.sol":125:155 function g() public { x = f; } */ + /* "input.sol":125:155 function g() public { x = f; } */ stop - /* "optimizer_inliner_dynamic_reference/input.sol":209:212 f() */ + /* "input.sol":209:212 f() */ tag_16: - /* "optimizer_inliner_dynamic_reference/input.sol":202:212 return f() */ + /* "input.sol":202:212 return f() */ swap1 pop - /* "optimizer_inliner_dynamic_reference/input.sol":160:215 function a() public pure returns (uint) { return f(); } */ + /* "input.sol":160:215 function a() public pure returns (uint) { return f(); } */ swap1 jump // out - /* "optimizer_inliner_dynamic_reference/input.sol":246:305 function h() public view returns (uint) { return x() + 1; } */ + /* "input.sol":246:305 function h() public view returns (uint) { return x() + 1; } */ tag_11: - /* "optimizer_inliner_dynamic_reference/input.sol":280:284 uint */ + /* "input.sol":280:284 uint */ 0x00 - /* "optimizer_inliner_dynamic_reference/input.sol":295:296 x */ + /* "input.sol":295:296 x */ dup1 sload - /* "optimizer_inliner_dynamic_reference/input.sol":295:298 x() */ + /* "input.sol":295:298 x() */ tag_19 swap1 - /* "optimizer_inliner_dynamic_reference/input.sol":295:296 x */ + /* "input.sol":295:296 x */ dup1 iszero tag_20 mul or - /* "optimizer_inliner_dynamic_reference/input.sol":295:298 x() */ + /* "input.sol":295:298 x() */ 0xffffffff and jump // in tag_19: - /* "optimizer_inliner_dynamic_reference/input.sol":295:302 x() + 1 */ + /* "input.sol":295:302 x() + 1 */ tag_16 swap1 - /* "optimizer_inliner_dynamic_reference/input.sol":301:302 1 */ + /* "input.sol":301:302 1 */ 0x01 - /* "optimizer_inliner_dynamic_reference/input.sol":295:302 x() + 1 */ + /* "input.sol":295:302 x() + 1 */ tag_22 jump // in - /* "optimizer_inliner_dynamic_reference/input.sol":310:365 function f() internal pure returns (uint) { return 6; } */ + /* "input.sol":310:365 function f() internal pure returns (uint) { return 6; } */ tag_17: - /* "optimizer_inliner_dynamic_reference/input.sol":361:362 6 */ + /* "input.sol":361:362 6 */ 0x06 swap1 - /* "optimizer_inliner_dynamic_reference/input.sol":310:365 function f() internal pure returns (uint) { return 6; } */ + /* "input.sol":310:365 function f() internal pure returns (uint) { return 6; } */ jump // out tag_20: tag_25 diff --git a/test/cmdlineTests/optimizer_inliner_dynamic_reference_constructor/output b/test/cmdlineTests/optimizer_inliner_dynamic_reference_constructor/output index 24ecaede0..5997bd1c7 100644 --- a/test/cmdlineTests/optimizer_inliner_dynamic_reference_constructor/output +++ b/test/cmdlineTests/optimizer_inliner_dynamic_reference_constructor/output @@ -1,9 +1,9 @@ -======= optimizer_inliner_dynamic_reference_constructor/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":60:361 contract C {... */ + /* "input.sol":60:361 contract C {... */ mstore(0x40, 0x80) - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":77:101 constructor() { x = f; } */ + /* "input.sol":77:101 constructor() { x = f; } */ callvalue dup1 iszero @@ -12,31 +12,31 @@ EVM assembly: revert(0x00, 0x00) tag_1: pop - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":93:94 x */ + /* "input.sol":93:94 x */ 0x00 - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":93:98 x = f */ + /* "input.sol":93:98 x = f */ dup1 sload not(sub(shl(0x40, 0x01), 0x01)) and - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":97:98 f */ + /* "input.sol":97:98 f */ or(tag_0_12, shl(0x20, tag_4)) sub(shl(0x40, 0x01), 0x01) - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":93:98 x = f */ + /* "input.sol":93:98 x = f */ and or swap1 sstore - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":60:361 contract C {... */ + /* "input.sol":60:361 contract C {... */ jump(tag_5) - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":304:359 function f() internal pure returns (uint) { return 6; } */ + /* "input.sol":304:359 function f() internal pure returns (uint) { return 6; } */ tag_4: - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":355:356 6 */ + /* "input.sol":355:356 6 */ 0x06 swap1 - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":304:359 function f() internal pure returns (uint) { return 6; } */ + /* "input.sol":304:359 function f() internal pure returns (uint) { return 6; } */ jump // out - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":60:361 contract C {... */ + /* "input.sol":60:361 contract C {... */ tag_5: dataSize(sub_0) dup1 @@ -48,7 +48,7 @@ tag_5: stop sub_0: assembly { - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":60:361 contract C {... */ + /* "input.sol":60:361 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -72,11 +72,11 @@ sub_0: assembly { jumpi tag_2: revert(0x00, 0x00) - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":154:209 function a() public pure returns (uint) { return f(); } */ + /* "input.sol":154:209 function a() public pure returns (uint) { return f(); } */ tag_3: - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":355:356 6 */ + /* "input.sol":355:356 6 */ 0x06 - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":154:209 function a() public pure returns (uint) { return f(); } */ + /* "input.sol":154:209 function a() public pure returns (uint) { return f(); } */ tag_5: mload(0x40) /* "#utility.yul":160:185 */ @@ -87,61 +87,61 @@ sub_0: assembly { 0x20 /* "#utility.yul":133:151 */ add - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":154:209 function a() public pure returns (uint) { return f(); } */ + /* "input.sol":154:209 function a() public pure returns (uint) { return f(); } */ mload(0x40) dup1 swap2 sub swap1 return - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":240:299 function h() public view returns (uint) { return x() + 1; } */ + /* "input.sol":240:299 function h() public view returns (uint) { return x() + 1; } */ tag_4: tag_5 tag_10 jump // in - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":203:206 f() */ + /* "input.sol":203:206 f() */ tag_14: - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":196:206 return f() */ + /* "input.sol":196:206 return f() */ swap1 pop - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":154:209 function a() public pure returns (uint) { return f(); } */ + /* "input.sol":154:209 function a() public pure returns (uint) { return f(); } */ swap1 jump // out - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":240:299 function h() public view returns (uint) { return x() + 1; } */ + /* "input.sol":240:299 function h() public view returns (uint) { return x() + 1; } */ tag_10: - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":274:278 uint */ + /* "input.sol":274:278 uint */ 0x00 - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":289:290 x */ + /* "input.sol":289:290 x */ dup1 sload - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":289:292 x() */ + /* "input.sol":289:292 x() */ tag_16 swap1 - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":289:290 x */ + /* "input.sol":289:290 x */ dup1 iszero tag_17 mul or - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":289:292 x() */ + /* "input.sol":289:292 x() */ 0xffffffff and jump // in tag_16: - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":289:296 x() + 1 */ + /* "input.sol":289:296 x() + 1 */ tag_14 swap1 - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":295:296 1 */ + /* "input.sol":295:296 1 */ 0x01 - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":289:296 x() + 1 */ + /* "input.sol":289:296 x() + 1 */ tag_19 jump // in - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":304:359 function f() internal pure returns (uint) { return 6; } */ + /* "input.sol":304:359 function f() internal pure returns (uint) { return 6; } */ tag_12: - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":355:356 6 */ + /* "input.sol":355:356 6 */ 0x06 swap1 - /* "optimizer_inliner_dynamic_reference_constructor/input.sol":304:359 function f() internal pure returns (uint) { return 6; } */ + /* "input.sol":304:359 function f() internal pure returns (uint) { return 6; } */ jump // out tag_17: tag_21 diff --git a/test/cmdlineTests/optimizer_inliner_inc/output b/test/cmdlineTests/optimizer_inliner_inc/output index 3a3639e19..d634bf2d4 100644 --- a/test/cmdlineTests/optimizer_inliner_inc/output +++ b/test/cmdlineTests/optimizer_inliner_inc/output @@ -1,7 +1,7 @@ -======= optimizer_inliner_inc/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "optimizer_inliner_inc/input.sol":157:279 contract C {... */ + /* "input.sol":157:279 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -21,7 +21,7 @@ tag_1: stop sub_0: assembly { - /* "optimizer_inliner_inc/input.sol":157:279 contract C {... */ + /* "input.sol":157:279 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -40,7 +40,7 @@ sub_0: assembly { jumpi tag_2: revert(0x00, 0x00) - /* "optimizer_inliner_inc/input.sol":174:277 function f() public pure {... */ + /* "input.sol":174:277 function f() public pure {... */ tag_3: tag_4 tag_5 @@ -48,29 +48,29 @@ sub_0: assembly { tag_4: stop tag_5: - /* "optimizer_inliner_inc/input.sol":213:219 uint x */ + /* "input.sol":213:219 uint x */ 0x00 - /* "optimizer_inliner_inc/input.sol":209:271 for(uint x = 0; x < 10; x = unsafe_inc(x))... */ + /* "input.sol":209:271 for(uint x = 0; x < 10; x = unsafe_inc(x))... */ tag_7: - /* "optimizer_inliner_inc/input.sol":229:231 10 */ + /* "input.sol":229:231 10 */ 0x0a - /* "optimizer_inliner_inc/input.sol":225:226 x */ + /* "input.sol":225:226 x */ dup2 - /* "optimizer_inliner_inc/input.sol":225:231 x < 10 */ + /* "input.sol":225:231 x < 10 */ lt - /* "optimizer_inliner_inc/input.sol":209:271 for(uint x = 0; x < 10; x = unsafe_inc(x))... */ + /* "input.sol":209:271 for(uint x = 0; x < 10; x = unsafe_inc(x))... */ iszero tag_8 jumpi - /* "optimizer_inliner_inc/input.sol":145:146 1 */ + /* "input.sol":145:146 1 */ 0x01 - /* "optimizer_inliner_inc/input.sol":141:146 x + 1 */ + /* "input.sol":141:146 x + 1 */ add - /* "optimizer_inliner_inc/input.sol":209:271 for(uint x = 0; x < 10; x = unsafe_inc(x))... */ + /* "input.sol":209:271 for(uint x = 0; x < 10; x = unsafe_inc(x))... */ jump(tag_7) tag_8: pop - /* "optimizer_inliner_inc/input.sol":174:277 function f() public pure {... */ + /* "input.sol":174:277 function f() public pure {... */ jump // out auxdata: diff --git a/test/cmdlineTests/optimizer_inliner_multireturn/output b/test/cmdlineTests/optimizer_inliner_multireturn/output index 46d74055a..20de1c219 100644 --- a/test/cmdlineTests/optimizer_inliner_multireturn/output +++ b/test/cmdlineTests/optimizer_inliner_multireturn/output @@ -1,7 +1,7 @@ -======= optimizer_inliner_multireturn/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "optimizer_inliner_multireturn/input.sol":162:298 contract C {... */ + /* "input.sol":162:298 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -21,7 +21,7 @@ tag_1: stop sub_0: assembly { - /* "optimizer_inliner_multireturn/input.sol":162:298 contract C {... */ + /* "input.sol":162:298 contract C {... */ mstore(0x40, 0x80) callvalue dup1 @@ -40,7 +40,7 @@ sub_0: assembly { jumpi tag_2: revert(0x00, 0x00) - /* "optimizer_inliner_multireturn/input.sol":179:296 function f() public pure {... */ + /* "input.sol":179:296 function f() public pure {... */ tag_3: tag_4 tag_5 @@ -48,35 +48,35 @@ sub_0: assembly { tag_4: stop tag_5: - /* "optimizer_inliner_multireturn/input.sol":219:225 uint x */ + /* "input.sol":219:225 uint x */ 0x00 - /* "optimizer_inliner_multireturn/input.sol":241:242 1 */ + /* "input.sol":241:242 1 */ 0x01 - /* "optimizer_inliner_multireturn/input.sol":214:290 for((uint x, uint y) = (0, 1); x < 10; (x, y) = test(x))... */ + /* "input.sol":214:290 for((uint x, uint y) = (0, 1); x < 10; (x, y) = test(x))... */ tag_7: - /* "optimizer_inliner_multireturn/input.sol":249:251 10 */ + /* "input.sol":249:251 10 */ 0x0a - /* "optimizer_inliner_multireturn/input.sol":245:246 x */ + /* "input.sol":245:246 x */ dup3 - /* "optimizer_inliner_multireturn/input.sol":245:251 x < 10 */ + /* "input.sol":245:251 x < 10 */ lt - /* "optimizer_inliner_multireturn/input.sol":214:290 for((uint x, uint y) = (0, 1); x < 10; (x, y) = test(x))... */ + /* "input.sol":214:290 for((uint x, uint y) = (0, 1); x < 10; (x, y) = test(x))... */ iszero tag_8 jumpi pop - /* "optimizer_inliner_multireturn/input.sol":146:147 1 */ + /* "input.sol":146:147 1 */ 0x01 - /* "optimizer_inliner_multireturn/input.sol":142:147 x + 1 */ + /* "input.sol":142:147 x + 1 */ dup2 add swap1 - /* "optimizer_inliner_multireturn/input.sol":214:290 for((uint x, uint y) = (0, 1); x < 10; (x, y) = test(x))... */ + /* "input.sol":214:290 for((uint x, uint y) = (0, 1); x < 10; (x, y) = test(x))... */ jump(tag_7) tag_8: pop pop - /* "optimizer_inliner_multireturn/input.sol":179:296 function f() public pure {... */ + /* "input.sol":179:296 function f() public pure {... */ jump // out auxdata: diff --git a/test/cmdlineTests/optimizer_user_yul/output b/test/cmdlineTests/optimizer_user_yul/output index c106c011b..b18e155bf 100644 --- a/test/cmdlineTests/optimizer_user_yul/output +++ b/test/cmdlineTests/optimizer_user_yul/output @@ -1,71 +1,71 @@ -======= optimizer_user_yul/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "optimizer_user_yul/input.sol":60:518 contract C... */ + /* "input.sol":60:518 contract C... */ mstore(0x40, 0x80) - /* "optimizer_user_yul/input.sol":101:106 int a */ + /* "input.sol":101:106 int a */ 0x00 - /* "optimizer_user_yul/input.sol":181:190 let x,y,z */ + /* "input.sol":181:190 let x,y,z */ 0x00 0x00 0x00 - /* "optimizer_user_yul/input.sol":205:206 1 */ + /* "input.sol":205:206 1 */ 0x01 - /* "optimizer_user_yul/input.sol":202:203 0 */ + /* "input.sol":202:203 0 */ 0x00 - /* "optimizer_user_yul/input.sol":195:207 sstore(0, 1) */ + /* "input.sol":195:207 sstore(0, 1) */ sstore - /* "optimizer_user_yul/input.sol":212:258 for { } sload(4) { } {... */ + /* "input.sol":212:258 for { } sload(4) { } {... */ tag_3: - /* "optimizer_user_yul/input.sol":226:227 4 */ + /* "input.sol":226:227 4 */ 0x04 - /* "optimizer_user_yul/input.sol":220:228 sload(4) */ + /* "input.sol":220:228 sload(4) */ sload - /* "optimizer_user_yul/input.sol":212:258 for { } sload(4) { } {... */ + /* "input.sol":212:258 for { } sload(4) { } {... */ iszero tag_5 jumpi pop - /* "optimizer_user_yul/input.sol":244:253 exp(x, y) */ + /* "input.sol":244:253 exp(x, y) */ dup1 dup3 exp - /* "optimizer_user_yul/input.sol":212:258 for { } sload(4) { } {... */ + /* "input.sol":212:258 for { } sload(4) { } {... */ jump(tag_3) tag_5: - /* "optimizer_user_yul/input.sol":216:219 { } */ + /* "input.sol":216:219 { } */ pop pop pop - /* "optimizer_user_yul/input.sol":268:269 2 */ + /* "input.sol":268:269 2 */ 0x02 - /* "optimizer_user_yul/input.sol":263:269 a := 2 */ + /* "input.sol":263:269 a := 2 */ swap1 pop - /* "optimizer_user_yul/input.sol":369:370 3 */ + /* "input.sol":369:370 3 */ 0x03 - /* "optimizer_user_yul/input.sol":366:367 2 */ + /* "input.sol":366:367 2 */ 0x02 - /* "optimizer_user_yul/input.sol":359:371 sstore(2, 3) */ + /* "input.sol":359:371 sstore(2, 3) */ sstore - /* "optimizer_user_yul/input.sol":390:391 5 */ + /* "input.sol":390:391 5 */ 0x05 - /* "optimizer_user_yul/input.sol":384:392 sload(5) */ + /* "input.sol":384:392 sload(5) */ sload iszero - /* "optimizer_user_yul/input.sol":376:509 for { } sload(5) { } {... */ + /* "input.sol":376:509 for { } sload(5) { } {... */ tag_6: - /* "optimizer_user_yul/input.sol":384:392 sload(5) */ + /* "input.sol":384:392 sload(5) */ dup1 - /* "optimizer_user_yul/input.sol":376:509 for { } sload(5) { } {... */ + /* "input.sol":376:509 for { } sload(5) { } {... */ iszero tag_6 jumpi - /* "optimizer_user_yul/input.sol":380:383 { } */ + /* "input.sol":380:383 { } */ pop - /* "optimizer_user_yul/input.sol":340:513 {... */ + /* "input.sol":340:513 {... */ pop - /* "optimizer_user_yul/input.sol":60:518 contract C... */ + /* "input.sol":60:518 contract C... */ dataSize(sub_0) dup1 dataOffset(sub_0) @@ -76,7 +76,7 @@ tag_6: stop sub_0: assembly { - /* "optimizer_user_yul/input.sol":60:518 contract C... */ + /* "input.sol":60:518 contract C... */ mstore(0x40, 0x80) revert(0x00, 0x00) diff --git a/test/cmdlineTests/require_overload/err b/test/cmdlineTests/require_overload/err index 184c8c22b..c267269fe 100644 --- a/test/cmdlineTests/require_overload/err +++ b/test/cmdlineTests/require_overload/err @@ -1,5 +1,5 @@ Error: No matching declaration found after argument-dependent lookup. - --> require_overload/input.sol:5:9: + --> input.sol:5:9: | 5 | require(this); | ^^^^^^^ diff --git a/test/cmdlineTests/require_with_error_ir/output b/test/cmdlineTests/require_with_error_ir/output index 09515f3cd..236931eea 100644 --- a/test/cmdlineTests/require_with_error_ir/output +++ b/test/cmdlineTests/require_with_error_ir/output @@ -1,6 +1,6 @@ IR: -/// @use-src 0:"require_with_error_ir/input.sol" +/// @use-src 0:"input.sol" object "C_36" { code { @@ -27,7 +27,7 @@ object "C_36" { } } - /// @use-src 0:"require_with_error_ir/input.sol" + /// @use-src 0:"input.sol" object "C_36_deployed" { code { diff --git a/test/cmdlineTests/require_with_string_ir/output b/test/cmdlineTests/require_with_string_ir/output index 3a19db372..9b0bd869f 100644 --- a/test/cmdlineTests/require_with_string_ir/output +++ b/test/cmdlineTests/require_with_string_ir/output @@ -1,6 +1,6 @@ IR: -/// @use-src 0:"require_with_string_ir/input.sol" +/// @use-src 0:"input.sol" object "C_28" { code { @@ -27,7 +27,7 @@ object "C_28" { } } - /// @use-src 0:"require_with_string_ir/input.sol" + /// @use-src 0:"input.sol" object "C_28_deployed" { code { diff --git a/test/cmdlineTests/revert_strings/output b/test/cmdlineTests/revert_strings/output index 0f16ff9d0..1fdb4b884 100644 --- a/test/cmdlineTests/revert_strings/output +++ b/test/cmdlineTests/revert_strings/output @@ -1,6 +1,6 @@ IR: -/// @use-src 0:"revert_strings/input.sol" +/// @use-src 0:"input.sol" object "C_15" { code { /// @src 0:59:147 "contract C {..." @@ -46,7 +46,7 @@ object "C_15" { /// @src 0:59:147 "contract C {..." } - /// @use-src 0:"revert_strings/input.sol" + /// @use-src 0:"input.sol" object "C_15_deployed" { code { /// @src 0:59:147 "contract C {..." diff --git a/test/cmdlineTests/stack_too_deep_from_code_transform/err b/test/cmdlineTests/stack_too_deep_from_code_transform/err index 588f4d437..8820cce05 100644 --- a/test/cmdlineTests/stack_too_deep_from_code_transform/err +++ b/test/cmdlineTests/stack_too_deep_from_code_transform/err @@ -1,6 +1,6 @@ Error: Cannot swap Variable value23 with Slot 0x20: too deep in the stack by 9 slots in [ RET value23 value22 value21 value20 value19 value18 value17 value16 value15 value14 value13 value12 value11 value10 value9 value8 value7 value6 value5 value4 value3 value2 value1 value0 pos 0x20 ] memoryguard was present. - --> stack_too_deep_from_code_transform/input.sol:1:1: + --> input.sol:1:1: | 1 | contract C { | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/input.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/input.json index 3059e1ecd..14dec3178 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/input.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_debug_info_in_yul_and_evm_asm_print_all/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "debug": {"debugInfo": ["*"]}, diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/input.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/input.json index 8e338322b..f2311603a 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/input.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_debug_info_in_yul_and_evm_asm_print_location_only/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "debug": {"debugInfo": ["location"]}, diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/input.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/input.json index c9184d944..09386f2be 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/input.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_debug_info_in_yul_and_evm_asm_print_none/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "debug": {"debugInfo": []}, diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/input.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/input.json index 962688913..cb6ac8446 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/input.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_debug_info_in_yul_and_evm_asm_print_snippet_only/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "debug": {"debugInfo": ["snippet"]}, diff --git a/test/cmdlineTests/standard_irOptimized_ast_requested/input.json b/test/cmdlineTests/standard_irOptimized_ast_requested/input.json index fd1698306..23f17f4ae 100644 --- a/test/cmdlineTests/standard_irOptimized_ast_requested/input.json +++ b/test/cmdlineTests/standard_irOptimized_ast_requested/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_irOptimized_ast_requested/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "outputSelection": {"*": {"*": ["irOptimizedAst"]}} diff --git a/test/cmdlineTests/standard_ir_ast_requested/input.json b/test/cmdlineTests/standard_ir_ast_requested/input.json index 1cb1083a2..07cfc13ed 100644 --- a/test/cmdlineTests/standard_ir_ast_requested/input.json +++ b/test/cmdlineTests/standard_ir_ast_requested/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_ir_ast_requested/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "outputSelection": {"*": {"*": ["irAst"]}} diff --git a/test/cmdlineTests/standard_metadata/input.json b/test/cmdlineTests/standard_metadata/input.json index ae4bfe8f5..8ca8da20a 100644 --- a/test/cmdlineTests/standard_metadata/input.json +++ b/test/cmdlineTests/standard_metadata/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_metadata/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_optimizer_invalid_detail_type/input.json b/test/cmdlineTests/standard_optimizer_invalid_detail_type/input.json index 5d65bb2e2..52c0b9c7a 100644 --- a/test/cmdlineTests/standard_optimizer_invalid_detail_type/input.json +++ b/test/cmdlineTests/standard_optimizer_invalid_detail_type/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_invalid_detail_type/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": {"details": {"peephole": 7}} diff --git a/test/cmdlineTests/standard_optimizer_invalid_details/input.json b/test/cmdlineTests/standard_optimizer_invalid_details/input.json index dbab578d6..b6c590b5e 100644 --- a/test/cmdlineTests/standard_optimizer_invalid_details/input.json +++ b/test/cmdlineTests/standard_optimizer_invalid_details/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_invalid_details/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": {"details": {"notThere": true}} diff --git a/test/cmdlineTests/standard_optimizer_no_yul/input.json b/test/cmdlineTests/standard_optimizer_no_yul/input.json index 42ab767be..ad1199dcf 100644 --- a/test/cmdlineTests/standard_optimizer_no_yul/input.json +++ b/test/cmdlineTests/standard_optimizer_no_yul/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_no_yul/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yul/input.json b/test/cmdlineTests/standard_optimizer_yul/input.json index cf40ef970..7d27780e5 100644 --- a/test/cmdlineTests/standard_optimizer_yul/input.json +++ b/test/cmdlineTests/standard_optimizer_yul/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yul/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails/input.json b/test/cmdlineTests/standard_optimizer_yulDetails/input.json index 6cdf504fd..53f1981d4 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_no_object/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/input.json index 4aba68350..d132a4797 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_no_object/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_no_object/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/input.json index 584b8bf83..dca784c63 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/input.json index 48de0cce3..ebdf48e3a 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nested_delimiter/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nested_delimiter/input.json index 5be769f76..a93f21739 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nested_delimiter/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nested_delimiter/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_invalid_nested_delimiter/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_mutliple_delimiters/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_mutliple_delimiters/input.json index 0bddd9d9d..4caee0761 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_mutliple_delimiters/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_mutliple_delimiters/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_mutliple_delimiters/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/input.json index 2baf7a723..bddd8d531 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_nested_brackets/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/input.json index 1c055d915..08aba5ccc 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/input.json index 511860250..586560917 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_no_yul/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_no_yul/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/input.json index e6f2abaa2..0166a4248 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_type/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/input.json index e3cd50027..554bfe2e5 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/input.json index 6cf7a2334..aa4b172bb 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_cleanup_sequence/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_cleanup_sequence/input.json index b557a9662..c3dde4dd3 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_cleanup_sequence/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_cleanup_sequence/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_with_cleanup_sequence/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_cleanup_sequence/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_cleanup_sequence/input.json index 7d2f529cc..c29391163 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_cleanup_sequence/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_cleanup_sequence/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_with_empty_cleanup_sequence/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_optimisation_sequence/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_optimisation_sequence/input.json index 9c603d6f7..8c4801da5 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_optimisation_sequence/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_optimisation_sequence/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_with_empty_optimisation_sequence/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence/input.json index 5780bea83..9d126b88e 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/input.json index 8e6add377..aecf8d9d5 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_whitespace_newline_sequence_no_yul/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_whitespace_newline_sequence_no_yul/input.json index 321ac8e99..1396b4269 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_whitespace_newline_sequence_no_yul/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_with_whitespace_newline_sequence_no_yul/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_with_whitespace_newline_sequence_no_yul/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/input.json index abd8cc0c8..8ccf21992 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_without_yul/in.sol"]} + "A": {"urls": ["in.sol"]} }, "settings": { "optimizer": {"details": {"yulDetails": 7} diff --git a/test/cmdlineTests/standard_outputs_on_analysis_error_fatal/input.json b/test/cmdlineTests/standard_outputs_on_analysis_error_fatal/input.json index b640f033d..c157a2724 100644 --- a/test/cmdlineTests/standard_outputs_on_analysis_error_fatal/input.json +++ b/test/cmdlineTests/standard_outputs_on_analysis_error_fatal/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_outputs_on_analysis_error_fatal/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/input.json b/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/input.json index 0214e00e8..c157a2724 100644 --- a/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/input.json +++ b/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_outputs_on_analysis_error_fatal_after_current_step/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_outputs_on_analysis_error_non_fatal/input.json b/test/cmdlineTests/standard_outputs_on_analysis_error_non_fatal/input.json index 904ebc5bf..c157a2724 100644 --- a/test/cmdlineTests/standard_outputs_on_analysis_error_non_fatal/input.json +++ b/test/cmdlineTests/standard_outputs_on_analysis_error_non_fatal/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_outputs_on_analysis_error_non_fatal/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_outputs_on_compilation_error/input.json b/test/cmdlineTests/standard_outputs_on_compilation_error/input.json index 855f00768..0555ba5e9 100644 --- a/test/cmdlineTests/standard_outputs_on_compilation_error/input.json +++ b/test/cmdlineTests/standard_outputs_on_compilation_error/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_outputs_on_compilation_error/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "optimizer": {"enabled": true}, diff --git a/test/cmdlineTests/standard_outputs_on_parsing_error/input.json b/test/cmdlineTests/standard_outputs_on_parsing_error/input.json index a0d00c4e9..c157a2724 100644 --- a/test/cmdlineTests/standard_outputs_on_parsing_error/input.json +++ b/test/cmdlineTests/standard_outputs_on_parsing_error/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_outputs_on_parsing_error/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_stack_too_deep_from_code_transform/input.json b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/input.json index a01e842b3..dc86ac684 100644 --- a/test/cmdlineTests/standard_stack_too_deep_from_code_transform/input.json +++ b/test/cmdlineTests/standard_stack_too_deep_from_code_transform/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "in.sol": {"urls": ["standard_stack_too_deep_from_code_transform/in.sol"]} + "in.sol": {"urls": ["in.sol"]} }, "settings": { "viaIR": true, diff --git a/test/cmdlineTests/standard_stop_after_parsing_ast_requested/input.json b/test/cmdlineTests/standard_stop_after_parsing_ast_requested/input.json index 34f157495..c09db6a6e 100644 --- a/test/cmdlineTests/standard_stop_after_parsing_ast_requested/input.json +++ b/test/cmdlineTests/standard_stop_after_parsing_ast_requested/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_stop_after_parsing_ast_requested/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "stopAfter": "parsing", diff --git a/test/cmdlineTests/standard_stop_after_parsing_bytecode_requested/input.json b/test/cmdlineTests/standard_stop_after_parsing_bytecode_requested/input.json index 7ef3d37fd..274ca87c4 100644 --- a/test/cmdlineTests/standard_stop_after_parsing_bytecode_requested/input.json +++ b/test/cmdlineTests/standard_stop_after_parsing_bytecode_requested/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_stop_after_parsing_bytecode_requested/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "stopAfter": "parsing", diff --git a/test/cmdlineTests/standard_stop_after_parsing_non_binary_output_requested/input.json b/test/cmdlineTests/standard_stop_after_parsing_non_binary_output_requested/input.json index ac4d623c7..597468e20 100644 --- a/test/cmdlineTests/standard_stop_after_parsing_non_binary_output_requested/input.json +++ b/test/cmdlineTests/standard_stop_after_parsing_non_binary_output_requested/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_stop_after_parsing_non_binary_output_requested/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "stopAfter": "parsing", diff --git a/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json b/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json index 4d2aea1f1..ecb97bef2 100644 --- a/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json +++ b/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_undeployable_contract_all_outputs/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_urls_existing_and_missing/input.json b/test/cmdlineTests/standard_urls_existing_and_missing/input.json index 686e8128e..575145836 100644 --- a/test/cmdlineTests/standard_urls_existing_and_missing/input.json +++ b/test/cmdlineTests/standard_urls_existing_and_missing/input.json @@ -3,9 +3,9 @@ "sources": { "url_not_found.sol": { "urls": [ - "standard_urls_existing_and_missing/non-existent-contract-1.sol", - "standard_urls_existing_and_missing/contract.sol", - "standard_urls_existing_and_missing/non-existent-contract-2.sol" + "non-existent-contract-1.sol", + "contract.sol", + "non-existent-contract-2.sol" ] } }, diff --git a/test/cmdlineTests/standard_urls_existing_and_missing/output.json b/test/cmdlineTests/standard_urls_existing_and_missing/output.json index e9db1135d..4204cdb45 100644 --- a/test/cmdlineTests/standard_urls_existing_and_missing/output.json +++ b/test/cmdlineTests/standard_urls_existing_and_missing/output.json @@ -2,8 +2,8 @@ "errors": [ { "component": "general", - "formattedMessage": "Cannot import url (\"standard_urls_existing_and_missing/non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".", - "message": "Cannot import url (\"standard_urls_existing_and_missing/non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".", + "formattedMessage": "Cannot import url (\"non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".", + "message": "Cannot import url (\"non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".", "severity": "warning", "type": "Warning" } diff --git a/test/cmdlineTests/standard_urls_missing/input.json b/test/cmdlineTests/standard_urls_missing/input.json index fecc50eb0..5ba6e7161 100644 --- a/test/cmdlineTests/standard_urls_missing/input.json +++ b/test/cmdlineTests/standard_urls_missing/input.json @@ -3,9 +3,9 @@ "sources": { "url_not_found.sol": { "urls": [ - "standard_urls_missing/non-existent-contract-1.sol", - "standard_urls_missing/non-existent-contract.sol", - "standard_urls_missing/non-existent-contract-2.sol" + "non-existent-contract-1.sol", + "non-existent-contract.sol", + "non-existent-contract-2.sol" ] } }, diff --git a/test/cmdlineTests/standard_urls_missing/output.json b/test/cmdlineTests/standard_urls_missing/output.json index 7e2bb3dd5..8f766b055 100644 --- a/test/cmdlineTests/standard_urls_missing/output.json +++ b/test/cmdlineTests/standard_urls_missing/output.json @@ -2,22 +2,22 @@ "errors": [ { "component": "general", - "formattedMessage": "Cannot import url (\"standard_urls_missing/non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".", - "message": "Cannot import url (\"standard_urls_missing/non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".", + "formattedMessage": "Cannot import url (\"non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".", + "message": "Cannot import url (\"non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".", "severity": "error", "type": "IOError" }, { "component": "general", - "formattedMessage": "Cannot import url (\"standard_urls_missing/non-existent-contract.sol\"): File not found. Searched the following locations: \"\".", - "message": "Cannot import url (\"standard_urls_missing/non-existent-contract.sol\"): File not found. Searched the following locations: \"\".", + "formattedMessage": "Cannot import url (\"non-existent-contract.sol\"): File not found. Searched the following locations: \"\".", + "message": "Cannot import url (\"non-existent-contract.sol\"): File not found. Searched the following locations: \"\".", "severity": "error", "type": "IOError" }, { "component": "general", - "formattedMessage": "Cannot import url (\"standard_urls_missing/non-existent-contract-2.sol\"): File not found. Searched the following locations: \"\".", - "message": "Cannot import url (\"standard_urls_missing/non-existent-contract-2.sol\"): File not found. Searched the following locations: \"\".", + "formattedMessage": "Cannot import url (\"non-existent-contract-2.sol\"): File not found. Searched the following locations: \"\".", + "message": "Cannot import url (\"non-existent-contract-2.sol\"): File not found. Searched the following locations: \"\".", "severity": "error", "type": "IOError" } diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/input.json b/test/cmdlineTests/standard_yul_cfg_json_export/input.json index aee56abf8..b5353721e 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/input.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "C": {"urls": ["standard_yul_cfg_json_export/in.sol"]} + "C": {"urls": ["in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_yul_code_generation_error/input.json b/test/cmdlineTests/standard_yul_code_generation_error/input.json index 905eef6c7..0f4da43fc 100644 --- a/test/cmdlineTests/standard_yul_code_generation_error/input.json +++ b/test/cmdlineTests/standard_yul_code_generation_error/input.json @@ -1,6 +1,6 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_code_generation_error/in.yul"]} + "C": {"urls": ["in.yul"]} } } diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json index 3e5b81c5e..e52867fa3 100644 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json @@ -3,7 +3,7 @@ "sources": { "C": { "urls": [ - "standard_yul_debug_info_ethdebug_compatible_output/in.yul" + "in.yul" ] } }, diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json index f05e6f361..c2c501c96 100644 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json @@ -3,7 +3,7 @@ "sources": { "C": { "urls": [ - "standard_yul_debug_info_ethdebug_incompatible_output/in.yul" + "in.yul" ] } }, diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json index be4fbb64f..16ef6ef33 100644 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json @@ -3,7 +3,7 @@ "sources": { "C": { "urls": [ - "standard_yul_debug_info_ethdebug_verbatim_unimplemented/in.yul" + "in.yul" ] } }, diff --git a/test/cmdlineTests/standard_yul_debug_info_print_all/input.json b/test/cmdlineTests/standard_yul_debug_info_print_all/input.json index 1e6ed81a4..705c9ba7c 100644 --- a/test/cmdlineTests/standard_yul_debug_info_print_all/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_print_all/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_debug_info_print_all/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "debug": {"debugInfo": ["*"]}, diff --git a/test/cmdlineTests/standard_yul_debug_info_print_location_only/input.json b/test/cmdlineTests/standard_yul_debug_info_print_location_only/input.json index 867bc6e70..84ad0edad 100644 --- a/test/cmdlineTests/standard_yul_debug_info_print_location_only/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_print_location_only/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_debug_info_print_location_only/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "debug": {"debugInfo": ["location"]}, diff --git a/test/cmdlineTests/standard_yul_debug_info_print_none/input.json b/test/cmdlineTests/standard_yul_debug_info_print_none/input.json index 705cf3879..13681dd8b 100644 --- a/test/cmdlineTests/standard_yul_debug_info_print_none/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_print_none/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_debug_info_print_none/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "debug": {"debugInfo": []}, diff --git a/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/input.json b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/input.json index ee247218f..ed74c0752 100644 --- a/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_debug_info_print_snippet_only/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "debug": {"debugInfo": ["snippet"]}, diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json index 83acd4c42..652620bed 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_ethdebug_assign_immutable/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json index abfb7ee86..67c5fedc7 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_ethdebug_bytecode_ir/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json index 54094c673..17949761f 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_ethdebug_bytecode_iroptimized/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json index e222dfeda..5c5e9c5f7 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_ethdebug_deployed_bytecode/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json index 207790120..655def5c1 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_ethdebug_deployed_bytecode/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_ir/input.json index 3153a378d..67c5fedc7 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_ir/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_ir/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_ethdebug_ir/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json index 180abcf31..b08c9dcd7 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_ethdebug_iroptimize/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json index 9f0c8b0d5..d7aec1f08 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_ethdebug_optimize_ir/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json index 81b637abd..eeabdbcb9 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json @@ -1,7 +1,7 @@ { "language": "Yul", "sources": { - "C": {"urls": ["standard_yul_ethdebug_optimize_iroptimized/in.yul"]} + "C": {"urls": ["in.yul"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/stop_after_parsing_ast/output b/test/cmdlineTests/stop_after_parsing_ast/output index 6cca9557d..e6d54c426 100644 --- a/test/cmdlineTests/stop_after_parsing_ast/output +++ b/test/cmdlineTests/stop_after_parsing_ast/output @@ -1,9 +1,9 @@ JSON AST (compact format): -======= stop_after_parsing_ast/input.sol ======= +======= input.sol ======= { - "absolutePath": "stop_after_parsing_ast/input.sol", + "absolutePath": "input.sol", "id": 4, "license": "GPL-3.0", "nodeType": "SourceUnit", diff --git a/test/cmdlineTests/storage_layout_transient_value_types/input.json b/test/cmdlineTests/storage_layout_transient_value_types/input.json index 8c90a7dde..7a12ca85c 100644 --- a/test/cmdlineTests/storage_layout_transient_value_types/input.json +++ b/test/cmdlineTests/storage_layout_transient_value_types/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "fileA": {"urls": ["storage_layout_transient_value_types/in.sol"]} + "fileA": {"urls": ["in.sol"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/storage_layout_user_defined/err b/test/cmdlineTests/storage_layout_user_defined/err index a9b5f07b1..e3815925a 100644 --- a/test/cmdlineTests/storage_layout_user_defined/err +++ b/test/cmdlineTests/storage_layout_user_defined/err @@ -1,2 +1,2 @@ Warning: Source file does not specify required compiler version! ---> storage_layout_user_defined/input.sol +--> input.sol diff --git a/test/cmdlineTests/storage_layout_user_defined/output b/test/cmdlineTests/storage_layout_user_defined/output index bb7819c66..d5be033ff 100644 --- a/test/cmdlineTests/storage_layout_user_defined/output +++ b/test/cmdlineTests/storage_layout_user_defined/output @@ -1,11 +1,11 @@ -======= storage_layout_user_defined/input.sol:C ======= +======= input.sol:C ======= Contract Storage Layout: { "storage": [ { "astId": 7, - "contract": "storage_layout_user_defined/input.sol:C", + "contract": "input.sol:C", "label": "a", "offset": 0, "slot": "0", @@ -13,7 +13,7 @@ Contract Storage Layout: }, { "astId": 10, - "contract": "storage_layout_user_defined/input.sol:C", + "contract": "input.sol:C", "label": "b", "offset": 16, "slot": "0", @@ -21,7 +21,7 @@ Contract Storage Layout: }, { "astId": 13, - "contract": "storage_layout_user_defined/input.sol:C", + "contract": "input.sol:C", "label": "c", "offset": 0, "slot": "1", @@ -29,7 +29,7 @@ Contract Storage Layout: }, { "astId": 16, - "contract": "storage_layout_user_defined/input.sol:C", + "contract": "input.sol:C", "label": "d", "offset": 16, "slot": "1", @@ -37,7 +37,7 @@ Contract Storage Layout: }, { "astId": 19, - "contract": "storage_layout_user_defined/input.sol:C", + "contract": "input.sol:C", "label": "e", "offset": 17, "slot": "1", @@ -45,7 +45,7 @@ Contract Storage Layout: }, { "astId": 22, - "contract": "storage_layout_user_defined/input.sol:C", + "contract": "input.sol:C", "label": "f", "offset": 18, "slot": "1", @@ -53,7 +53,7 @@ Contract Storage Layout: }, { "astId": 25, - "contract": "storage_layout_user_defined/input.sol:C", + "contract": "input.sol:C", "label": "g", "offset": 19, "slot": "1", @@ -61,7 +61,7 @@ Contract Storage Layout: }, { "astId": 28, - "contract": "storage_layout_user_defined/input.sol:C", + "contract": "input.sol:C", "label": "h", "offset": 20, "slot": "1", diff --git a/test/cmdlineTests/storage_layout_user_defined_no_pretty_print/output b/test/cmdlineTests/storage_layout_user_defined_no_pretty_print/output index 1be4da0b6..54276e472 100644 --- a/test/cmdlineTests/storage_layout_user_defined_no_pretty_print/output +++ b/test/cmdlineTests/storage_layout_user_defined_no_pretty_print/output @@ -1,4 +1,4 @@ -======= storage_layout_user_defined_no_pretty_print/input.sol:C ======= +======= input.sol:C ======= Contract Storage Layout: {"storage":[]} diff --git a/test/cmdlineTests/strict_asm_ast_compact_json/output b/test/cmdlineTests/strict_asm_ast_compact_json/output index b2271c36c..1099f0c12 100644 --- a/test/cmdlineTests/strict_asm_ast_compact_json/output +++ b/test/cmdlineTests/strict_asm_ast_compact_json/output @@ -1,5 +1,5 @@ -======= strict_asm_ast_compact_json/input.yul (EVM) ======= +======= input.yul (EVM) ======= AST: { diff --git a/test/cmdlineTests/strict_asm_debug_info_print_all/output b/test/cmdlineTests/strict_asm_debug_info_print_all/output index 0e58baf57..ea8afb6a2 100644 --- a/test/cmdlineTests/strict_asm_debug_info_print_all/output +++ b/test/cmdlineTests/strict_asm_debug_info_print_all/output @@ -1,5 +1,5 @@ -======= strict_asm_debug_info_print_all/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: /// @use-src 0:"input.sol" diff --git a/test/cmdlineTests/strict_asm_debug_info_print_location_only/output b/test/cmdlineTests/strict_asm_debug_info_print_location_only/output index 17d2f50e2..06448d25a 100644 --- a/test/cmdlineTests/strict_asm_debug_info_print_location_only/output +++ b/test/cmdlineTests/strict_asm_debug_info_print_location_only/output @@ -1,5 +1,5 @@ -======= strict_asm_debug_info_print_location_only/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: /// @use-src 0:"input.sol" diff --git a/test/cmdlineTests/strict_asm_debug_info_print_none/output b/test/cmdlineTests/strict_asm_debug_info_print_none/output index 51f779490..93fc5c73e 100644 --- a/test/cmdlineTests/strict_asm_debug_info_print_none/output +++ b/test/cmdlineTests/strict_asm_debug_info_print_none/output @@ -1,5 +1,5 @@ -======= strict_asm_debug_info_print_none/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: /// @use-src 0:"input.sol" diff --git a/test/cmdlineTests/strict_asm_eof_container_osaka/output b/test/cmdlineTests/strict_asm_eof_container_osaka/output index 81f01798a..3582e09d6 100644 --- a/test/cmdlineTests/strict_asm_eof_container_osaka/output +++ b/test/cmdlineTests/strict_asm_eof_container_osaka/output @@ -1,5 +1,5 @@ -======= strict_asm_eof_container_osaka/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output index 677c49b88..9d256a5dd 100644 --- a/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output @@ -1,5 +1,5 @@ -======= strict_asm_eof_dataloadn_osaka/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "a" { diff --git a/test/cmdlineTests/strict_asm_evm_version_byzantium/output b/test/cmdlineTests/strict_asm_evm_version_byzantium/output index 2840e1d2b..a43e6e47c 100644 --- a/test/cmdlineTests/strict_asm_evm_version_byzantium/output +++ b/test/cmdlineTests/strict_asm_evm_version_byzantium/output @@ -1,5 +1,5 @@ -======= strict_asm_evm_version_byzantium/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { @@ -11,5 +11,5 @@ Binary representation: 00 Text representation: - /* "strict_asm_evm_version_byzantium/input.yul":27:34 */ + /* "input.yul":27:34 */ stop diff --git a/test/cmdlineTests/strict_asm_evm_version_constantinople/output b/test/cmdlineTests/strict_asm_evm_version_constantinople/output index 9362866b4..a43e6e47c 100644 --- a/test/cmdlineTests/strict_asm_evm_version_constantinople/output +++ b/test/cmdlineTests/strict_asm_evm_version_constantinople/output @@ -1,5 +1,5 @@ -======= strict_asm_evm_version_constantinople/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { @@ -11,5 +11,5 @@ Binary representation: 00 Text representation: - /* "strict_asm_evm_version_constantinople/input.yul":27:34 */ + /* "input.yul":27:34 */ stop diff --git a/test/cmdlineTests/strict_asm_jump/err b/test/cmdlineTests/strict_asm_jump/err index c0001f382..419701b46 100644 --- a/test/cmdlineTests/strict_asm_jump/err +++ b/test/cmdlineTests/strict_asm_jump/err @@ -1,5 +1,5 @@ Error: Function "jump" not found. - --> strict_asm_jump/input.yul:1:3: + --> input.yul:1:3: | 1 | { jump(1) } | ^^^^ diff --git a/test/cmdlineTests/strict_asm_msize_with_optimizer/output b/test/cmdlineTests/strict_asm_msize_with_optimizer/output index fbc1e69fa..7f170e22f 100644 --- a/test/cmdlineTests/strict_asm_msize_with_optimizer/output +++ b/test/cmdlineTests/strict_asm_msize_with_optimizer/output @@ -1,5 +1,5 @@ -======= strict_asm_msize_with_optimizer/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { diff --git a/test/cmdlineTests/strict_asm_msize_without_optimizer/output b/test/cmdlineTests/strict_asm_msize_without_optimizer/output index ac19efbcb..2ba00372e 100644 --- a/test/cmdlineTests/strict_asm_msize_without_optimizer/output +++ b/test/cmdlineTests/strict_asm_msize_without_optimizer/output @@ -1,5 +1,5 @@ -======= strict_asm_msize_without_optimizer/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { diff --git a/test/cmdlineTests/strict_asm_only_cr/err b/test/cmdlineTests/strict_asm_only_cr/err index 0879e4f21..334ade78f 100644 --- a/test/cmdlineTests/strict_asm_only_cr/err +++ b/test/cmdlineTests/strict_asm_only_cr/err @@ -1,5 +1,5 @@ Error: Expected keyword "object". - --> strict_asm_only_cr/input.yul:1:2: + --> input.yul:1:2: | 1 | | ^ diff --git a/test/cmdlineTests/strict_asm_optimizer_steps/output b/test/cmdlineTests/strict_asm_optimizer_steps/output index 58c919761..4e20c6218 100644 --- a/test/cmdlineTests/strict_asm_optimizer_steps/output +++ b/test/cmdlineTests/strict_asm_optimizer_steps/output @@ -1,5 +1,5 @@ -======= strict_asm_optimizer_steps/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "C_6" { @@ -27,58 +27,58 @@ Binary representation: 608060405234601357600c60185f39600c5ff35b5f80fdfe608060405236155f555f80fd Text representation: - /* "strict_asm_optimizer_steps/input.yul":59:62 */ + /* "input.yul":59:62 */ 0x80 - /* "strict_asm_optimizer_steps/input.yul":55:57 */ + /* "input.yul":55:57 */ 0x40 - /* "strict_asm_optimizer_steps/input.yul":48:63 */ + /* "input.yul":48:63 */ mstore - /* "strict_asm_optimizer_steps/input.yul":79:90 */ + /* "input.yul":79:90 */ callvalue - /* "strict_asm_optimizer_steps/input.yul":76:107 */ + /* "input.yul":76:107 */ tag_1 jumpi - /* "strict_asm_optimizer_steps/input.yul":160:184 */ + /* "input.yul":160:184 */ dataSize(sub_0) - /* "strict_asm_optimizer_steps/input.yul":132:158 */ + /* "input.yul":132:158 */ dataOffset(sub_0) - /* "strict_asm_optimizer_steps/input.yul":129:130 */ + /* "input.yul":129:130 */ 0x00 - /* "strict_asm_optimizer_steps/input.yul":120:185 */ + /* "input.yul":120:185 */ codecopy - /* "strict_asm_optimizer_steps/input.yul":208:232 */ + /* "input.yul":208:232 */ dataSize(sub_0) - /* "strict_asm_optimizer_steps/input.yul":205:206 */ + /* "input.yul":205:206 */ 0x00 - /* "strict_asm_optimizer_steps/input.yul":198:233 */ + /* "input.yul":198:233 */ return - /* "strict_asm_optimizer_steps/input.yul":91:107 */ + /* "input.yul":91:107 */ tag_1: - /* "strict_asm_optimizer_steps/input.yul":103:104 */ + /* "input.yul":103:104 */ 0x00 - /* "strict_asm_optimizer_steps/input.yul":93:105 */ + /* "input.yul":93:105 */ dup1 revert stop sub_0: assembly { - /* "strict_asm_optimizer_steps/input.yul":334:337 */ + /* "input.yul":334:337 */ 0x80 - /* "strict_asm_optimizer_steps/input.yul":330:332 */ + /* "input.yul":330:332 */ 0x40 - /* "strict_asm_optimizer_steps/input.yul":323:338 */ + /* "input.yul":323:338 */ mstore - /* "strict_asm_optimizer_steps/input.yul":372:386 */ + /* "input.yul":372:386 */ calldatasize - /* "strict_asm_optimizer_steps/input.yul":365:387 */ + /* "input.yul":365:387 */ iszero - /* "strict_asm_optimizer_steps/input.yul":362:363 */ + /* "input.yul":362:363 */ 0x00 - /* "strict_asm_optimizer_steps/input.yul":355:388 */ + /* "input.yul":355:388 */ sstore - /* "strict_asm_optimizer_steps/input.yul":415:416 */ + /* "input.yul":415:416 */ 0x00 - /* "strict_asm_optimizer_steps/input.yul":405:417 */ + /* "input.yul":405:417 */ dup1 revert } diff --git a/test/cmdlineTests/strict_asm_output_selection_asm_only/output b/test/cmdlineTests/strict_asm_output_selection_asm_only/output index 317c9a9ae..08932887f 100644 --- a/test/cmdlineTests/strict_asm_output_selection_asm_only/output +++ b/test/cmdlineTests/strict_asm_output_selection_asm_only/output @@ -1,12 +1,12 @@ -======= strict_asm_output_selection_asm_only/input.yul (EVM) ======= +======= input.yul (EVM) ======= Text representation: - /* "strict_asm_output_selection_asm_only/input.yul":41:43 */ + /* "input.yul":41:43 */ 0x2a - /* "strict_asm_output_selection_asm_only/input.yul":38:39 */ + /* "input.yul":38:39 */ 0x00 - /* "strict_asm_output_selection_asm_only/input.yul":31:44 */ + /* "input.yul":31:44 */ sstore - /* "strict_asm_output_selection_asm_only/input.yul":27:48 */ + /* "input.yul":27:48 */ stop diff --git a/test/cmdlineTests/strict_asm_output_selection_bin_only/output b/test/cmdlineTests/strict_asm_output_selection_bin_only/output index 86d249576..4edd88b33 100644 --- a/test/cmdlineTests/strict_asm_output_selection_bin_only/output +++ b/test/cmdlineTests/strict_asm_output_selection_bin_only/output @@ -1,5 +1,5 @@ -======= strict_asm_output_selection_bin_only/input.yul (EVM) ======= +======= input.yul (EVM) ======= Binary representation: 602a5f5500 diff --git a/test/cmdlineTests/strict_asm_output_selection_ir_optimized_only/output b/test/cmdlineTests/strict_asm_output_selection_ir_optimized_only/output index 1fa4b72c7..15174c71c 100644 --- a/test/cmdlineTests/strict_asm_output_selection_ir_optimized_only/output +++ b/test/cmdlineTests/strict_asm_output_selection_ir_optimized_only/output @@ -1,5 +1,5 @@ -======= strict_asm_output_selection_ir_optimized_only/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { diff --git a/test/cmdlineTests/strict_asm_warning/err b/test/cmdlineTests/strict_asm_warning/err index 0661ae1ff..be47fb6ad 100644 --- a/test/cmdlineTests/strict_asm_warning/err +++ b/test/cmdlineTests/strict_asm_warning/err @@ -1,5 +1,5 @@ Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. - --> strict_asm_warning/input.yul:4:5: + --> input.yul:4:5: | 4 | selfdestruct(0) | ^^^^^^^^^^^^ diff --git a/test/cmdlineTests/strict_asm_warning/output b/test/cmdlineTests/strict_asm_warning/output index 71cb2ce69..b71411dae 100644 --- a/test/cmdlineTests/strict_asm_warning/output +++ b/test/cmdlineTests/strict_asm_warning/output @@ -1,5 +1,5 @@ -======= strict_asm_warning/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { diff --git a/test/cmdlineTests/strict_asm_warning_and_error_optimize/err b/test/cmdlineTests/strict_asm_warning_and_error_optimize/err index 22366e3e7..b008c021a 100644 --- a/test/cmdlineTests/strict_asm_warning_and_error_optimize/err +++ b/test/cmdlineTests/strict_asm_warning_and_error_optimize/err @@ -1,11 +1,11 @@ Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. - --> strict_asm_warning_and_error_optimize/input.yul:4:5: + --> input.yul:4:5: | 4 | selfdestruct() | ^^^^^^^^^^^^ Error: Function "selfdestruct" expects 1 arguments but got 0. - --> strict_asm_warning_and_error_optimize/input.yul:4:5: + --> input.yul:4:5: | 4 | selfdestruct() | ^^^^^^^^^^^^ diff --git a/test/cmdlineTests/strict_asm_warning_optimize/err b/test/cmdlineTests/strict_asm_warning_optimize/err index 098aa00ba..be47fb6ad 100644 --- a/test/cmdlineTests/strict_asm_warning_optimize/err +++ b/test/cmdlineTests/strict_asm_warning_optimize/err @@ -1,5 +1,5 @@ Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. - --> strict_asm_warning_optimize/input.yul:4:5: + --> input.yul:4:5: | 4 | selfdestruct(0) | ^^^^^^^^^^^^ diff --git a/test/cmdlineTests/strict_asm_warning_optimize/output b/test/cmdlineTests/strict_asm_warning_optimize/output index d933dcb05..b71411dae 100644 --- a/test/cmdlineTests/strict_asm_warning_optimize/output +++ b/test/cmdlineTests/strict_asm_warning_optimize/output @@ -1,5 +1,5 @@ -======= strict_asm_warning_optimize/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { diff --git a/test/cmdlineTests/strict_asm_warning_optimize_unreachable/err b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/err index 4535680ba..4465b2c24 100644 --- a/test/cmdlineTests/strict_asm_warning_optimize_unreachable/err +++ b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/err @@ -1,5 +1,5 @@ Warning: "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. - --> strict_asm_warning_optimize_unreachable/input.yul:7:5: + --> input.yul:7:5: | 7 | selfdestruct(0) | ^^^^^^^^^^^^ diff --git a/test/cmdlineTests/strict_asm_warning_optimize_unreachable/output b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/output index 508e9d8ed..a2c2516af 100644 --- a/test/cmdlineTests/strict_asm_warning_optimize_unreachable/output +++ b/test/cmdlineTests/strict_asm_warning_optimize_unreachable/output @@ -1,5 +1,5 @@ -======= strict_asm_warning_optimize_unreachable/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output index c79692c3c..e0bb1af40 100644 --- a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -1,5 +1,5 @@ -======= strict_asm_yul_cfg_json_export/input.yul (EVM) ======= +======= input.yul (EVM) ======= Yul Control Flow Graph: { diff --git a/test/cmdlineTests/structured_documentation_source_location/err b/test/cmdlineTests/structured_documentation_source_location/err index 1f69adf4f..51d3a652e 100644 --- a/test/cmdlineTests/structured_documentation_source_location/err +++ b/test/cmdlineTests/structured_documentation_source_location/err @@ -1,11 +1,11 @@ Error: Documentation tag "@return No value returned" does not contain the name of its return parameter. - --> structured_documentation_source_location/input.sol:4:5: + --> input.sol:4:5: | 4 | /// @param id Some identifier | ^ (Relevant source part starts here and spans across multiple lines). Error: Documentation tag "@return No value returned" does not contain the name of its return parameter. - --> structured_documentation_source_location/input.sol:8:5: + --> input.sol:8:5: | 8 | /// @return No value returned | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/too_long_line/err b/test/cmdlineTests/too_long_line/err index 25620bd4c..626812e5f 100644 --- a/test/cmdlineTests/too_long_line/err +++ b/test/cmdlineTests/too_long_line/err @@ -1,5 +1,5 @@ Error: Identifier not found or not unique. - --> too_long_line/input.sol:5:164: + --> input.sol:5:164: | 5 | ... ffffffffffffffffffffffffffffffffff(announcementType Type, string Announcement, string ... | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/too_long_line_both_sides_short/err b/test/cmdlineTests/too_long_line_both_sides_short/err index 5992d6ea9..194047c58 100644 --- a/test/cmdlineTests/too_long_line_both_sides_short/err +++ b/test/cmdlineTests/too_long_line_both_sides_short/err @@ -1,5 +1,5 @@ Error: Identifier not found or not unique. - --> too_long_line_both_sides_short/input.sol:5:15: + --> input.sol:5:15: | 5 | function f(announcementTypeXXXXXXXXXXXXXXXXXXX ... XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Type, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/too_long_line_edge_in/err b/test/cmdlineTests/too_long_line_edge_in/err index 1d96ea4cd..161e3a20b 100644 --- a/test/cmdlineTests/too_long_line_edge_in/err +++ b/test/cmdlineTests/too_long_line_edge_in/err @@ -1,5 +1,5 @@ Error: Identifier not found or not unique. - --> too_long_line_edge_in/input.sol:5:36: + --> input.sol:5:36: | 5 | function ffffffffffffffffffffff(announcementTypeTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT Ty, string A) onlyOwner external { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/too_long_line_edge_out/err b/test/cmdlineTests/too_long_line_edge_out/err index 3b3b4ee49..6aa17fc03 100644 --- a/test/cmdlineTests/too_long_line_edge_out/err +++ b/test/cmdlineTests/too_long_line_edge_out/err @@ -1,5 +1,5 @@ Error: Identifier not found or not unique. - --> too_long_line_edge_out/input.sol:5:37: + --> input.sol:5:37: | 5 | ... function fffffffffffffffffffffff(announcementTypeTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT Typ, string A) onlyOwner external ... | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/too_long_line_left_short/err b/test/cmdlineTests/too_long_line_left_short/err index 4f2359739..25c35177d 100644 --- a/test/cmdlineTests/too_long_line_left_short/err +++ b/test/cmdlineTests/too_long_line_left_short/err @@ -1,5 +1,5 @@ Error: Identifier not found or not unique. - --> too_long_line_left_short/input.sol:5:15: + --> input.sol:5:15: | 5 | function f(announcementType Type, string Announcement, string ... | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/too_long_line_multiline/err b/test/cmdlineTests/too_long_line_multiline/err index 4523938c6..bfa99eed3 100644 --- a/test/cmdlineTests/too_long_line_multiline/err +++ b/test/cmdlineTests/too_long_line_multiline/err @@ -1,5 +1,5 @@ Error: No visibility specified. Did you intend to add "public"? - --> too_long_line_multiline/input.sol:5:5: + --> input.sol:5:5: | 5 | function f() returns (bytes1 _b, by ... _b7, bytes22 _b22, bytes32 _b32) { | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/too_long_line_right_short/err b/test/cmdlineTests/too_long_line_right_short/err index 7aa26ff07..f17f273b1 100644 --- a/test/cmdlineTests/too_long_line_right_short/err +++ b/test/cmdlineTests/too_long_line_right_short/err @@ -1,5 +1,5 @@ Error: Identifier not found or not unique. - --> too_long_line_right_short/input.sol:5:164: + --> input.sol:5:164: | 5 | ... ffffffffffffffffffffffffffffffffff(announcementType Type, | ^^^^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/transient_storage_layout/output b/test/cmdlineTests/transient_storage_layout/output index 0736271b4..846cb947d 100644 --- a/test/cmdlineTests/transient_storage_layout/output +++ b/test/cmdlineTests/transient_storage_layout/output @@ -1,11 +1,11 @@ -======= transient_storage_layout/input.sol:C ======= +======= input.sol:C ======= Contract Transient Storage Layout: { "storage": [ { "astId": 4, - "contract": "transient_storage_layout/input.sol:C", + "contract": "input.sol:C", "label": "x", "offset": 0, "slot": "0", @@ -13,7 +13,7 @@ Contract Transient Storage Layout: }, { "astId": 8, - "contract": "transient_storage_layout/input.sol:C", + "contract": "input.sol:C", "label": "w", "offset": 0, "slot": "1", @@ -21,7 +21,7 @@ Contract Transient Storage Layout: }, { "astId": 12, - "contract": "transient_storage_layout/input.sol:C", + "contract": "input.sol:C", "label": "b", "offset": 20, "slot": "1", @@ -29,7 +29,7 @@ Contract Transient Storage Layout: }, { "astId": 15, - "contract": "transient_storage_layout/input.sol:C", + "contract": "input.sol:C", "label": "d", "offset": 0, "slot": "2", @@ -60,7 +60,7 @@ Contract Transient Storage Layout: } } -======= transient_storage_layout/input.sol:D ======= +======= input.sol:D ======= Contract Transient Storage Layout: { "storage": [] diff --git a/test/cmdlineTests/transient_storage_layout_value_types/input.json b/test/cmdlineTests/transient_storage_layout_value_types/input.json index 65d9a2231..2b903a2ae 100644 --- a/test/cmdlineTests/transient_storage_layout_value_types/input.json +++ b/test/cmdlineTests/transient_storage_layout_value_types/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "fileA": {"urls": ["transient_storage_layout_value_types/in.sol"]} + "fileA": {"urls": ["in.sol"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/input.json b/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/input.json index e649fc838..7a12ca85c 100644 --- a/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/input.json +++ b/test/cmdlineTests/transient_storage_layout_value_types_interleaved_with_storage/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "fileA": {"urls": ["transient_storage_layout_value_types_interleaved_with_storage/in.sol"]} + "fileA": {"urls": ["in.sol"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/transient_storage_layout_value_types_packed/input.json b/test/cmdlineTests/transient_storage_layout_value_types_packed/input.json index ee7fb0dec..2b903a2ae 100644 --- a/test/cmdlineTests/transient_storage_layout_value_types_packed/input.json +++ b/test/cmdlineTests/transient_storage_layout_value_types_packed/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "fileA": {"urls": ["transient_storage_layout_value_types_packed/in.sol"]} + "fileA": {"urls": ["in.sol"]} }, "settings": { "outputSelection": { diff --git a/test/cmdlineTests/undeployable_contract_empty_outputs/output b/test/cmdlineTests/undeployable_contract_empty_outputs/output index 123edc75d..71059f17f 100644 --- a/test/cmdlineTests/undeployable_contract_empty_outputs/output +++ b/test/cmdlineTests/undeployable_contract_empty_outputs/output @@ -1,5 +1,5 @@ -======= undeployable_contract_empty_outputs/input.sol:C ======= +======= input.sol:C ======= EVM assembly: null Gas estimation: @@ -21,7 +21,7 @@ Function signatures: Contract JSON ABI [] -======= undeployable_contract_empty_outputs/input.sol:I ======= +======= input.sol:I ======= EVM assembly: null Gas estimation: diff --git a/test/cmdlineTests/viair_abicoder_v1/err b/test/cmdlineTests/viair_abicoder_v1/err index 55f8ba4b9..29fa2acd0 100644 --- a/test/cmdlineTests/viair_abicoder_v1/err +++ b/test/cmdlineTests/viair_abicoder_v1/err @@ -1,5 +1,5 @@ Warning (2066): Contract requests the ABI coder v1, which is incompatible with the IR. Using ABI coder v2 instead. - --> viair_abicoder_v1/input.sol:4:1: + --> input.sol:4:1: | 4 | contract test { | ^ (Relevant source part starts here and spans across multiple lines). diff --git a/test/cmdlineTests/viair_abicoder_v1/output b/test/cmdlineTests/viair_abicoder_v1/output index 1c4d6c90e..3d6a58288 100644 --- a/test/cmdlineTests/viair_abicoder_v1/output +++ b/test/cmdlineTests/viair_abicoder_v1/output @@ -1,6 +1,6 @@ IR: -/// @use-src 0:"viair_abicoder_v1/input.sol" +/// @use-src 0:"input.sol" object "test_11" { code { /// @src 0:79:169 "contract test {..." @@ -31,7 +31,7 @@ object "test_11" { /// @src 0:79:169 "contract test {..." } - /// @use-src 0:"viair_abicoder_v1/input.sol" + /// @use-src 0:"input.sol" object "test_11_deployed" { code { /// @src 0:79:169 "contract test {..." diff --git a/test/cmdlineTests/viair_msize_without_optimizer/output b/test/cmdlineTests/viair_msize_without_optimizer/output index f94c973bf..90c18ef94 100644 --- a/test/cmdlineTests/viair_msize_without_optimizer/output +++ b/test/cmdlineTests/viair_msize_without_optimizer/output @@ -1,5 +1,5 @@ -======= viair_msize_without_optimizer/input.sol:C ======= +======= input.sol:C ======= EVM assembly: mstore(0x40, 0x80) jumpi(tag_4, iszero(callvalue)) @@ -173,7 +173,7 @@ sub_0: assembly { } Optimized IR: -/// @use-src 0:"viair_msize_without_optimizer/input.sol" +/// @use-src 0:"input.sol" object "C_7" { code { mstore(64, memoryguard(128)) @@ -192,7 +192,7 @@ object "C_7" { function constructor_C_7() { } } - /// @use-src 0:"viair_msize_without_optimizer/input.sol" + /// @use-src 0:"input.sol" object "C_7_deployed" { code { mstore(64, memoryguard(128)) diff --git a/test/cmdlineTests/viair_subobject_optimization/output b/test/cmdlineTests/viair_subobject_optimization/output index dafba2771..523cff79e 100644 --- a/test/cmdlineTests/viair_subobject_optimization/output +++ b/test/cmdlineTests/viair_subobject_optimization/output @@ -1,7 +1,7 @@ -======= viair_subobject_optimization/input.sol:C ======= +======= input.sol:C ======= EVM assembly: - /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + /* "input.sol":61:668 contract C {... */ 0x80 jumpi(tag_7, callvalue) 0x1f @@ -44,12 +44,12 @@ EVM assembly: jumpi mload sub(shl(0x48, 0x01), 0xbe) - /* "viair_subobject_optimization/input.sol":620:645 x == 0xFFFFFFFFFFFFFFFF42 */ + /* "input.sol":620:645 x == 0xFFFFFFFFFFFFFFFF42 */ eq - /* "viair_subobject_optimization/input.sol":616:661 if (x == 0xFFFFFFFFFFFFFFFF42)... */ + /* "input.sol":616:661 if (x == 0xFFFFFFFFFFFFFFFF42)... */ tag_7 jumpi - /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + /* "input.sol":61:668 contract C {... */ mload(0x40) dataSize(sub_0) swap1 @@ -58,13 +58,13 @@ EVM assembly: dup3 codecopy return - /* "viair_subobject_optimization/input.sol":616:661 if (x == 0xFFFFFFFFFFFFFFFF42)... */ + /* "input.sol":616:661 if (x == 0xFFFFFFFFFFFFFFFF42)... */ tag_7: 0x00 - /* "viair_subobject_optimization/input.sol":653:661 revert() */ + /* "input.sol":653:661 revert() */ dup1 revert - /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + /* "input.sol":61:668 contract C {... */ tag_3: mstore(0x00, shl(0xe0, 0x4e487b71)) mstore(0x04, 0x41) @@ -72,7 +72,7 @@ tag_3: stop sub_0: assembly { - /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + /* "input.sol":61:668 contract C {... */ 0x00 dup1 revert @@ -81,9 +81,9 @@ sub_0: assembly { } -======= viair_subobject_optimization/input.sol:D ======= +======= input.sol:D ======= EVM assembly: - /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ + /* "input.sol":669:772 contract D {... */ 0x80 dup1 0x40 @@ -103,7 +103,7 @@ tag_1: stop sub_0: assembly { - /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ + /* "input.sol":669:772 contract D {... */ 0x80 jumpi(tag_1, iszero(lt(calldatasize, 0x04))) 0x00 @@ -117,10 +117,10 @@ sub_0: assembly { tag_3: jumpi(tag_7, callvalue) jumpi(tag_7, slt(add(not(0x03), calldatasize), 0x00)) - /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ + /* "input.sol":745:765 type(C).creationCode */ dataSize(sub_0) swap1 - /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ + /* "input.sol":669:772 contract D {... */ 0x3f dup3 add @@ -142,7 +142,7 @@ sub_0: assembly { swap2 dup3 mstore - /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ + /* "input.sol":745:765 type(C).creationCode */ dup3 dup2 mstore @@ -153,24 +153,24 @@ sub_0: assembly { dataOffset(sub_0) dup5 codecopy - /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ + /* "input.sol":669:772 contract D {... */ dup2 mload swap3 dup4 swap2 - /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ + /* "input.sol":745:765 type(C).creationCode */ 0x20 - /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ + /* "input.sol":669:772 contract D {... */ dup4 mstore mload dup1 swap2 dup2 - /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ + /* "input.sol":745:765 type(C).creationCode */ 0x20 - /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ + /* "input.sol":669:772 contract D {... */ dup6 add mstore @@ -206,7 +206,7 @@ sub_0: assembly { stop sub_0: assembly { - /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + /* "input.sol":61:668 contract C {... */ 0x80 jumpi(tag_7, callvalue) 0x1f @@ -249,12 +249,12 @@ sub_0: assembly { jumpi mload sub(shl(0x48, 0x01), 0xbe) - /* "viair_subobject_optimization/input.sol":620:645 x == 0xFFFFFFFFFFFFFFFF42 */ + /* "input.sol":620:645 x == 0xFFFFFFFFFFFFFFFF42 */ eq - /* "viair_subobject_optimization/input.sol":616:661 if (x == 0xFFFFFFFFFFFFFFFF42)... */ + /* "input.sol":616:661 if (x == 0xFFFFFFFFFFFFFFFF42)... */ tag_7 jumpi - /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + /* "input.sol":61:668 contract C {... */ mload(0x40) dataSize(sub_0) swap1 @@ -263,13 +263,13 @@ sub_0: assembly { dup3 codecopy return - /* "viair_subobject_optimization/input.sol":616:661 if (x == 0xFFFFFFFFFFFFFFFF42)... */ + /* "input.sol":616:661 if (x == 0xFFFFFFFFFFFFFFFF42)... */ tag_7: 0x00 - /* "viair_subobject_optimization/input.sol":653:661 revert() */ + /* "input.sol":653:661 revert() */ dup1 revert - /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + /* "input.sol":61:668 contract C {... */ tag_3: mstore(0x00, shl(0xe0, 0x4e487b71)) mstore(0x04, 0x41) @@ -277,7 +277,7 @@ sub_0: assembly { stop sub_0: assembly { - /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + /* "input.sol":61:668 contract C {... */ 0x00 dup1 revert diff --git a/test/cmdlineTests/viair_subobjects/err b/test/cmdlineTests/viair_subobjects/err index 5046525be..66ebf4229 100644 --- a/test/cmdlineTests/viair_subobjects/err +++ b/test/cmdlineTests/viair_subobjects/err @@ -1,5 +1,5 @@ Warning: Unused local variable. - --> viair_subobjects/input.sol:8:9: + --> input.sol:8:9: | 8 | C c = new C(); | ^^^ diff --git a/test/cmdlineTests/viair_subobjects/output b/test/cmdlineTests/viair_subobjects/output index 7a6bc8e65..783756e67 100644 --- a/test/cmdlineTests/viair_subobjects/output +++ b/test/cmdlineTests/viair_subobjects/output @@ -1,11 +1,11 @@ -======= viair_subobjects/input.sol:C ======= +======= input.sol:C ======= Binary: Binary of the runtime part: Optimized IR: -/// @use-src 0:"viair_subobjects/input.sol" +/// @use-src 0:"input.sol" object "C_3" { code { { @@ -18,7 +18,7 @@ object "C_3" { return(_1, _2) } } - /// @use-src 0:"viair_subobjects/input.sol" + /// @use-src 0:"input.sol" object "C_3_deployed" { code { { @@ -31,13 +31,13 @@ object "C_3" { } -======= viair_subobjects/input.sol:D ======= +======= input.sol:D ======= Binary: Binary of the runtime part: Optimized IR: -/// @use-src 0:"viair_subobjects/input.sol" +/// @use-src 0:"input.sol" object "D_16" { code { { @@ -50,7 +50,7 @@ object "D_16" { return(_1, _2) } } - /// @use-src 0:"viair_subobjects/input.sol" + /// @use-src 0:"input.sol" object "D_16_deployed" { code { { @@ -88,7 +88,7 @@ object "D_16" { revert(0, 0) } } - /// @use-src 0:"viair_subobjects/input.sol" + /// @use-src 0:"input.sol" object "C_3" { code { { @@ -101,7 +101,7 @@ object "D_16" { return(_1, _2) } } - /// @use-src 0:"viair_subobjects/input.sol" + /// @use-src 0:"input.sol" object "C_3_deployed" { code { { diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index 0508769d7..9affc4206 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -1,5 +1,5 @@ -======= yul_cfg_json_export/input.sol:C ======= +======= input.sol:C ======= Yul Control Flow Graph: { "C_19": { @@ -447,7 +447,7 @@ Yul Control Flow Graph: "type": "Object" } -======= yul_cfg_json_export/input.sol:D ======= +======= input.sol:D ======= Yul Control Flow Graph: { "D_38": { @@ -2127,6 +2127,6 @@ Yul Control Flow Graph: "type": "Object" } -======= yul_cfg_json_export/input.sol:I ======= +======= input.sol:I ======= Yul Control Flow Graph: null diff --git a/test/cmdlineTests/yul_function_name_clashes/output b/test/cmdlineTests/yul_function_name_clashes/output index 2c54b6f50..1d319d284 100644 --- a/test/cmdlineTests/yul_function_name_clashes/output +++ b/test/cmdlineTests/yul_function_name_clashes/output @@ -1,5 +1,5 @@ -======= yul_function_name_clashes/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { diff --git a/test/cmdlineTests/yul_function_name_clashes_different_params/output b/test/cmdlineTests/yul_function_name_clashes_different_params/output index 85884a6a0..fdffb0c31 100644 --- a/test/cmdlineTests/yul_function_name_clashes_different_params/output +++ b/test/cmdlineTests/yul_function_name_clashes_different_params/output @@ -1,5 +1,5 @@ -======= yul_function_name_clashes_different_params/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { @@ -23,37 +23,37 @@ Binary representation: 60056011565b600d60706016565b9055005b5f3590565b359056 Text representation: - /* "yul_function_name_clashes_different_params/input.yul":92:95 */ + /* "input.yul":92:95 */ tag_3 tag_1 jump // in tag_3: - /* "yul_function_name_clashes_different_params/input.yul":113:122 */ + /* "input.yul":113:122 */ tag_4 - /* "yul_function_name_clashes_different_params/input.yul":117:121 */ + /* "input.yul":117:121 */ 0x70 - /* "yul_function_name_clashes_different_params/input.yul":113:122 */ + /* "input.yul":113:122 */ tag_2 jump // in tag_4: - /* "yul_function_name_clashes_different_params/input.yul":135:147 */ + /* "input.yul":135:147 */ swap1 sstore - /* "yul_function_name_clashes_different_params/input.yul":27:284 */ + /* "input.yul":27:284 */ stop - /* "yul_function_name_clashes_different_params/input.yul":166:216 */ + /* "input.yul":166:216 */ tag_1: - /* "yul_function_name_clashes_different_params/input.yul":212:213 */ + /* "input.yul":212:213 */ 0x00 - /* "yul_function_name_clashes_different_params/input.yul":199:214 */ + /* "input.yul":199:214 */ calldataload - /* "yul_function_name_clashes_different_params/input.yul":166:216 */ + /* "input.yul":166:216 */ swap1 jump // out - /* "yul_function_name_clashes_different_params/input.yul":225:278 */ + /* "input.yul":225:278 */ tag_2: - /* "yul_function_name_clashes_different_params/input.yul":261:276 */ + /* "input.yul":261:276 */ calldataload - /* "yul_function_name_clashes_different_params/input.yul":225:278 */ + /* "input.yul":225:278 */ swap1 jump // out diff --git a/test/cmdlineTests/yul_optimize_runs/output b/test/cmdlineTests/yul_optimize_runs/output index 589f8ce1a..ec3dab457 100644 --- a/test/cmdlineTests/yul_optimize_runs/output +++ b/test/cmdlineTests/yul_optimize_runs/output @@ -1,5 +1,5 @@ -======= yul_optimize_runs/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "RunsTest1" { @@ -24,28 +24,28 @@ Binary representation: 602480600a5f395ff3fe7fabc12345000000000000000000000000000000000000000000000000000000005f5500 Text representation: - /* "yul_optimize_runs/input.yul":64:92 */ + /* "input.yul":64:92 */ dataSize(sub_0) - /* "yul_optimize_runs/input.yul":117:147 */ + /* "input.yul":117:147 */ dup1 dataOffset(sub_0) - /* "yul_optimize_runs/input.yul":114:115 */ + /* "input.yul":114:115 */ 0x00 - /* "yul_optimize_runs/input.yul":105:152 */ + /* "input.yul":105:152 */ codecopy - /* "yul_optimize_runs/input.yul":172:173 */ + /* "input.yul":172:173 */ 0x00 - /* "yul_optimize_runs/input.yul":165:178 */ + /* "input.yul":165:178 */ return stop sub_0: assembly { - /* "yul_optimize_runs/input.yul":282:348 */ + /* "input.yul":282:348 */ 0xabc1234500000000000000000000000000000000000000000000000000000000 - /* "yul_optimize_runs/input.yul":279:280 */ + /* "input.yul":279:280 */ 0x00 - /* "yul_optimize_runs/input.yul":272:349 */ + /* "input.yul":272:349 */ sstore - /* "yul_optimize_runs/input.yul":240:373 */ + /* "input.yul":240:373 */ stop } diff --git a/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output index 7b948303e..744bc03a8 100644 --- a/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output +++ b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output @@ -1,4 +1,4 @@ -======= yul_optimizer_disabled_sequence_empty/input.sol:C ======= +======= input.sol:C ======= Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"yul_optimizer_disabled_sequence_empty/input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"yul_optimizer_disabled_sequence_empty/input.sol":{"keccak256":"0xc2db3500808896ce1e69de2fe20cecab7ae2ffbb47cdf6ba8321296d95f49fc5","license":"GPL-3.0","urls":["bzz-raw://fde21393c068cd9f2d2b10ba4782db54f6f1c9a725074b17fa742531076be8a4","dweb:/ipfs/QmeTD6mR7YrWNyRowKRS7xs6cJNeMF3T49GAHzGM1bquyM"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0xc2db3500808896ce1e69de2fe20cecab7ae2ffbb47cdf6ba8321296d95f49fc5","license":"GPL-3.0","urls":["bzz-raw://fde21393c068cd9f2d2b10ba4782db54f6f1c9a725074b17fa742531076be8a4","dweb:/ipfs/QmeTD6mR7YrWNyRowKRS7xs6cJNeMF3T49GAHzGM1bquyM"]}},"version":1} diff --git a/test/cmdlineTests/yul_optimizer_steps/output b/test/cmdlineTests/yul_optimizer_steps/output index bb68a48fa..f9484d2b4 100644 --- a/test/cmdlineTests/yul_optimizer_steps/output +++ b/test/cmdlineTests/yul_optimizer_steps/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"yul_optimizer_steps/input.sol" +/// @use-src 0:"input.sol" object "C_7" { code { { @@ -18,7 +18,7 @@ object "C_7" { function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { revert(0, 0) } } - /// @use-src 0:"yul_optimizer_steps/input.sol" + /// @use-src 0:"input.sol" object "C_7_deployed" { code { { diff --git a/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output index 9687abf64..26be94698 100644 --- a/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output +++ b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"yul_optimizer_steps_nested_brackets/input.sol" +/// @use-src 0:"input.sol" object "C_6" { code { { @@ -21,7 +21,7 @@ object "C_6" { function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { revert(0, 0) } } - /// @use-src 0:"yul_optimizer_steps_nested_brackets/input.sol" + /// @use-src 0:"input.sol" object "C_6_deployed" { code { { diff --git a/test/cmdlineTests/yul_optimizer_steps_short_sequence/output b/test/cmdlineTests/yul_optimizer_steps_short_sequence/output index dc77ce3c5..e93958a5d 100644 --- a/test/cmdlineTests/yul_optimizer_steps_short_sequence/output +++ b/test/cmdlineTests/yul_optimizer_steps_short_sequence/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"yul_optimizer_steps_short_sequence/input.sol" +/// @use-src 0:"input.sol" object "C_8" { code { { @@ -9,7 +9,7 @@ object "C_8" { revert(0, 0) } } - /// @use-src 0:"yul_optimizer_steps_short_sequence/input.sol" + /// @use-src 0:"input.sol" object "C_8_deployed" { code { { diff --git a/test/cmdlineTests/yul_optimizer_steps_with_empty_cleanup_sequence/output b/test/cmdlineTests/yul_optimizer_steps_with_empty_cleanup_sequence/output index 01641c53b..bbfd22e9b 100644 --- a/test/cmdlineTests/yul_optimizer_steps_with_empty_cleanup_sequence/output +++ b/test/cmdlineTests/yul_optimizer_steps_with_empty_cleanup_sequence/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"yul_optimizer_steps_with_empty_cleanup_sequence/input.sol" +/// @use-src 0:"input.sol" object "C_8" { code { { @@ -10,7 +10,7 @@ object "C_8" { revert(0, usr$a) } } - /// @use-src 0:"yul_optimizer_steps_with_empty_cleanup_sequence/input.sol" + /// @use-src 0:"input.sol" object "C_8_deployed" { code { { diff --git a/test/cmdlineTests/yul_optimizer_steps_with_empty_optimization_sequence/output b/test/cmdlineTests/yul_optimizer_steps_with_empty_optimization_sequence/output index b13e6e282..bbfd22e9b 100644 --- a/test/cmdlineTests/yul_optimizer_steps_with_empty_optimization_sequence/output +++ b/test/cmdlineTests/yul_optimizer_steps_with_empty_optimization_sequence/output @@ -1,5 +1,5 @@ Optimized IR: -/// @use-src 0:"yul_optimizer_steps_with_empty_optimization_sequence/input.sol" +/// @use-src 0:"input.sol" object "C_8" { code { { @@ -10,7 +10,7 @@ object "C_8" { revert(0, usr$a) } } - /// @use-src 0:"yul_optimizer_steps_with_empty_optimization_sequence/input.sol" + /// @use-src 0:"input.sol" object "C_8_deployed" { code { { diff --git a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/err b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/err index 95e30df2e..d87be1839 100644 --- a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/err +++ b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/err @@ -1,11 +1,11 @@ Warning: Unused local variable. - --> yul_optimizer_steps_without_optimize_empty_sequence/input.sol:13:9: + --> input.sol:13:9: | 13 | uint b = a; | ^^^^^^ Warning: Unused local variable. - --> yul_optimizer_steps_without_optimize_empty_sequence/input.sol:14:9: + --> input.sol:14:9: | 14 | uint c = a; | ^^^^^^ diff --git a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output index 6873abe60..a7b037775 100644 --- a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output +++ b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output @@ -1,7 +1,7 @@ -======= yul_optimizer_steps_without_optimize_empty_sequence/input.sol:C ======= +======= input.sol:C ======= Optimized IR: -/// @use-src 0:"yul_optimizer_steps_without_optimize_empty_sequence/input.sol" +/// @use-src 0:"input.sol" object "C_28" { code { { @@ -24,7 +24,7 @@ object "C_28" { function constructor_C() { } } - /// @use-src 0:"yul_optimizer_steps_without_optimize_empty_sequence/input.sol" + /// @use-src 0:"input.sol" object "C_28_deployed" { code { { @@ -130,4 +130,4 @@ object "C_28" { } Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"foo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"yul_optimizer_steps_without_optimize_empty_sequence/input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"yul_optimizer_steps_without_optimize_empty_sequence/input.sol":{"keccak256":"0x3fc910e345ce1ee62bfa6b0f66931ee632c08265b25b6139cfbbfe4d2f8d5dd8","license":"GPL-3.0","urls":["bzz-raw://e557e9ad2c2e420a669c06ae456b0b790d77d2d6d492cd8540e6b244388a5140","dweb:/ipfs/QmaNiZmC2Mo3YxGiehs1n3dVTjZwD7FguX7EUtpeshMVuR"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"foo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0x3fc910e345ce1ee62bfa6b0f66931ee632c08265b25b6139cfbbfe4d2f8d5dd8","license":"GPL-3.0","urls":["bzz-raw://e557e9ad2c2e420a669c06ae456b0b790d77d2d6d492cd8540e6b244388a5140","dweb:/ipfs/QmaNiZmC2Mo3YxGiehs1n3dVTjZwD7FguX7EUtpeshMVuR"]}},"version":1} diff --git a/test/cmdlineTests/yul_verbatim/output b/test/cmdlineTests/yul_verbatim/output index 60fc7e6d1..33f86b299 100644 --- a/test/cmdlineTests/yul_verbatim/output +++ b/test/cmdlineTests/yul_verbatim/output @@ -1,5 +1,5 @@ -======= yul_verbatim/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { @@ -20,38 +20,38 @@ Binary representation: 6002808103808261626382815564656678797a010203040506070900010203040506070900010203040506070900010201020304050607090001020304050607090001020304050607090001026009905050505050 Text representation: - /* "yul_verbatim/input.yul":15:16 */ + /* "input.yul":15:16 */ 0x02 - /* "yul_verbatim/input.yul":37:38 */ + /* "input.yul":37:38 */ dup1 - /* "yul_verbatim/input.yul":34:35 */ + /* "input.yul":34:35 */ dup2 - /* "yul_verbatim/input.yul":30:39 */ + /* "input.yul":30:39 */ sub - /* "yul_verbatim/input.yul":78:79 */ + /* "input.yul":78:79 */ dup1 - /* "yul_verbatim/input.yul":75:76 */ + /* "input.yul":75:76 */ dup3 - /* "yul_verbatim/input.yul":53:80 */ + /* "input.yul":53:80 */ verbatimbytecode_616263 - /* "yul_verbatim/input.yul":95:96 */ + /* "input.yul":95:96 */ dup3 - /* "yul_verbatim/input.yul":92:93 */ + /* "input.yul":92:93 */ dup2 - /* "yul_verbatim/input.yul":85:97 */ + /* "input.yul":85:97 */ sstore - /* "yul_verbatim/input.yul":111:132 */ + /* "input.yul":111:132 */ verbatimbytecode_646566 - /* "yul_verbatim/input.yul":137:158 */ + /* "input.yul":137:158 */ verbatimbytecode_78797a - /* "yul_verbatim/input.yul":189:326 */ + /* "input.yul":189:326 */ verbatimbytecode_01020304050607090001020304050607090001020304050607090001020102030405060709000102030405060709000102030405060709000102 - /* "yul_verbatim/input.yul":336:337 */ + /* "input.yul":336:337 */ 0x09 - /* "yul_verbatim/input.yul":331:337 */ + /* "input.yul":331:337 */ swap1 pop - /* "yul_verbatim/input.yul":0:339 */ + /* "input.yul":0:339 */ pop pop pop diff --git a/test/cmdlineTests/yul_verbatim_msize/output b/test/cmdlineTests/yul_verbatim_msize/output index f684bac21..b0acd819d 100644 --- a/test/cmdlineTests/yul_verbatim_msize/output +++ b/test/cmdlineTests/yul_verbatim_msize/output @@ -1,5 +1,5 @@ -======= yul_verbatim_msize/input.yul (EVM) ======= +======= input.yul (EVM) ======= Pretty printed source: object "object" { @@ -17,19 +17,19 @@ Binary representation: 6120005150616160025f5500 Text representation: - /* "yul_verbatim_msize/input.yul":61:67 */ + /* "input.yul":61:67 */ 0x2000 - /* "yul_verbatim_msize/input.yul":55:68 */ + /* "input.yul":55:68 */ mload - /* "yul_verbatim_msize/input.yul":51:69 */ + /* "input.yul":51:69 */ pop - /* "yul_verbatim_msize/input.yul":82:102 */ + /* "input.yul":82:102 */ verbatimbytecode_6161 - /* "yul_verbatim_msize/input.yul":125:126 */ + /* "input.yul":125:126 */ 0x02 - /* "yul_verbatim_msize/input.yul":122:123 */ + /* "input.yul":122:123 */ 0x00 - /* "yul_verbatim_msize/input.yul":115:127 */ + /* "input.yul":115:127 */ sstore - /* "yul_verbatim_msize/input.yul":27:143 */ + /* "input.yul":27:143 */ stop From 880b61bd33f6df5c05d77671f6b534be2957e100 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 13 Feb 2025 15:30:25 +0100 Subject: [PATCH 0840/1340] SMTChecker: Refactor handling of ConstantCondition verification target --- libsolidity/formal/BMC.cpp | 149 +++++++++++++++++-------------------- libsolidity/formal/BMC.h | 30 +++++--- 2 files changed, 90 insertions(+), 89 deletions(-) diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 6dcd856ee..4b494d623 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -247,14 +247,8 @@ bool BMC::visit(IfStatement const& _node) m_context.pushSolver(); _node.condition().accept(*this); - // We ignore called functions here because they have - // specific input values. - if (isRootFunction() && !isInsideLoop()) - addVerificationTarget( - VerificationTargetType::ConstantCondition, - expr(_node.condition()), - &_node.condition() - ); + checkIfConditionIsConstant(_node.condition()); + m_context.popSolver(); resetVariableIndices(std::move(indicesBeforePush)); @@ -283,13 +277,7 @@ bool BMC::visit(Conditional const& _op) auto indicesBeforePush = copyVariableIndices(); m_context.pushSolver(); _op.condition().accept(*this); - - if (isRootFunction() && !isInsideLoop()) - addVerificationTarget( - VerificationTargetType::ConstantCondition, - expr(_op.condition()), - &_op.condition() - ); + checkIfConditionIsConstant(_op.condition()); m_context.popSolver(); resetVariableIndices(std::move(indicesBeforePush)); @@ -690,12 +678,7 @@ void BMC::visitRequire(FunctionCall const& _funCall) auto const& args = _funCall.arguments(); solAssert(args.size() >= 1, ""); solAssert(args.front()->annotation().type->category() == Type::Category::Bool, ""); - if (isRootFunction() && !isInsideLoop()) - addVerificationTarget( - VerificationTargetType::ConstantCondition, - expr(*args.front()), - args.front().get() - ); + checkIfConditionIsConstant(*args.front()); } void BMC::visitAddMulMod(FunctionCall const& _funCall) @@ -933,9 +916,6 @@ void BMC::checkVerificationTarget(BMCVerificationTarget& _target) switch (_target.type) { - case VerificationTargetType::ConstantCondition: - checkConstantCondition(_target); - break; case VerificationTargetType::Underflow: checkUnderflow(_target); break; @@ -951,19 +931,70 @@ void BMC::checkVerificationTarget(BMCVerificationTarget& _target) case VerificationTargetType::Assert: checkAssert(_target); break; + case VerificationTargetType::ConstantCondition: + solAssert(false, "Checks for constant condition are handled separately"); default: solAssert(false, ""); } } -void BMC::checkConstantCondition(BMCVerificationTarget& _target) +void BMC::checkIfConditionIsConstant(Expression const& _condition) { - checkBooleanNotConstant( - *_target.expression, - _target.constraints, - _target.value, - _target.callStack - ); + if ( + !m_settings.targets.has(VerificationTargetType::ConstantCondition) || + (m_currentContract && !shouldEncode(*m_currentContract)) + ) + return; + + // We ignore called functions here because they have specific input values. + // Also, expressions inside loop can have different values in different iterations. + if (!isRootFunction() || isInsideLoop()) + return; + + // Do not check for const-ness if this is a literal. + if (dynamic_cast(&_condition)) + return; + + auto [canBeTrue, canBeFalse] = checkBooleanNotConstant(currentPathConditions() && m_context.assertions(), expr(_condition)); + + // Report based on the result of the checks + if (canBeTrue == CheckResult::ERROR || canBeFalse == CheckResult::ERROR) + m_errorReporter.warning(8592_error, _condition.location(), "BMC: Error trying to invoke SMT solver."); + else if (canBeTrue == CheckResult::CONFLICTING || canBeFalse == CheckResult::CONFLICTING) + m_errorReporter.warning(3356_error, _condition.location(), "BMC: At least two SMT solvers provided conflicting answers. Results might not be sound."); + else if (canBeTrue == CheckResult::UNKNOWN || canBeFalse == CheckResult::UNKNOWN) + { + // Not enough information to make definite claims. + } + else if (canBeTrue == CheckResult::SATISFIABLE && canBeFalse == CheckResult::SATISFIABLE) + { + // Condition can be both true and false for some program runs. + } + + else if (canBeTrue == CheckResult::UNSATISFIABLE && canBeFalse == CheckResult::UNSATISFIABLE) + m_errorReporter.warning(2512_error, _condition.location(), "BMC: Condition unreachable.", SMTEncoder::callStackMessage(m_callStack)); + else + { + std::string description; + if (canBeFalse == smtutil::CheckResult::UNSATISFIABLE) + { + smtAssert(canBeTrue == smtutil::CheckResult::SATISFIABLE); + description = "BMC: Condition is always true."; + } + else + { + smtAssert(canBeTrue == smtutil::CheckResult::UNSATISFIABLE); + smtAssert(canBeFalse == smtutil::CheckResult::SATISFIABLE); + description = "BMC: Condition is always false."; + } + m_errorReporter.warning( + 6838_error, + _condition.location(), + description, + SMTEncoder::callStackMessage(m_callStack) + ); + } + } void BMC::checkUnderflow(BMCVerificationTarget& _target) @@ -1068,6 +1099,7 @@ void BMC::addVerificationTarget( Expression const* _expression ) { + smtAssert(_type != VerificationTargetType::ConstantCondition, "Checks for constant condition are handled separately"); if (!m_settings.targets.has(_type) || (m_currentContract && !shouldAnalyzeVerificationTargetsFor(*m_currentContract))) return; @@ -1081,10 +1113,7 @@ void BMC::addVerificationTarget( m_callStack, modelExpressions() }; - if (_type == VerificationTargetType::ConstantCondition) - checkVerificationTarget(target); - else - m_verificationTargets.emplace_back(std::move(target)); + m_verificationTargets.emplace_back(std::move(target)); } /// Solving. @@ -1188,62 +1217,22 @@ void BMC::checkCondition( m_interface->pop(); } -void BMC::checkBooleanNotConstant( - Expression const& _condition, +BMC::ConstantExpressionCheckResult BMC::checkBooleanNotConstant( smtutil::Expression const& _constraints, - smtutil::Expression const& _value, - std::vector const& _callStack + smtutil::Expression const& _condition ) { - // Do not check for const-ness if this is a constant. - if (dynamic_cast(&_condition)) - return; - m_interface->push(); - m_interface->addAssertion(_constraints && _value); + m_interface->addAssertion(_constraints && _condition); auto positiveResult = checkSatisfiable(); m_interface->pop(); m_interface->push(); - m_interface->addAssertion(_constraints && !_value); + m_interface->addAssertion(_constraints && !_condition); auto negatedResult = checkSatisfiable(); m_interface->pop(); - if (positiveResult == smtutil::CheckResult::ERROR || negatedResult == smtutil::CheckResult::ERROR) - m_errorReporter.warning(8592_error, _condition.location(), "BMC: Error trying to invoke SMT solver."); - else if (positiveResult == smtutil::CheckResult::CONFLICTING || negatedResult == smtutil::CheckResult::CONFLICTING) - m_errorReporter.warning(3356_error, _condition.location(), "BMC: At least two SMT solvers provided conflicting answers. Results might not be sound."); - else if (positiveResult == smtutil::CheckResult::SATISFIABLE && negatedResult == smtutil::CheckResult::SATISFIABLE) - { - // everything fine. - } - else if (positiveResult == smtutil::CheckResult::UNKNOWN || negatedResult == smtutil::CheckResult::UNKNOWN) - { - // can't do anything. - } - else if (positiveResult == smtutil::CheckResult::UNSATISFIABLE && negatedResult == smtutil::CheckResult::UNSATISFIABLE) - m_errorReporter.warning(2512_error, _condition.location(), "BMC: Condition unreachable.", SMTEncoder::callStackMessage(_callStack)); - else - { - std::string description; - if (positiveResult == smtutil::CheckResult::SATISFIABLE) - { - solAssert(negatedResult == smtutil::CheckResult::UNSATISFIABLE, ""); - description = "BMC: Condition is always true."; - } - else - { - solAssert(positiveResult == smtutil::CheckResult::UNSATISFIABLE, ""); - solAssert(negatedResult == smtutil::CheckResult::SATISFIABLE, ""); - description = "BMC: Condition is always false."; - } - m_errorReporter.warning( - 6838_error, - _condition.location(), - description, - SMTEncoder::callStackMessage(_callStack) - ); - } + return {.canBeTrue = positiveResult, .canBeFalse = negatedResult}; } std::pair> diff --git a/libsolidity/formal/BMC.h b/libsolidity/formal/BMC.h index a0ee9a374..67d930c79 100644 --- a/libsolidity/formal/BMC.h +++ b/libsolidity/formal/BMC.h @@ -161,7 +161,6 @@ class BMC: public SMTEncoder void checkVerificationTargets(); void checkVerificationTarget(BMCVerificationTarget& _target); - void checkConstantCondition(BMCVerificationTarget& _target); void checkUnderflow(BMCVerificationTarget& _target); void checkOverflow(BMCVerificationTarget& _target); void checkDivByZero(BMCVerificationTarget& _target); @@ -172,8 +171,13 @@ class BMC: public SMTEncoder smtutil::Expression const& _value, Expression const* _expression ); + /// Special handling of ConstantCondition verification target. + /// The target is checked immediately, unlike the other targets that are queued for checking at the end of analysis. + void checkIfConditionIsConstant(Expression const& _condition); //@} + + /// Solver related. //@{ /// Check that a condition can be satisfied. @@ -188,13 +192,18 @@ class BMC: public SMTEncoder std::string const& _additionalValueName = "", smtutil::Expression const* _additionalValue = nullptr ); - /// Checks that a boolean condition is not constant. Do not warn if the expression - /// is a literal constant. - void checkBooleanNotConstant( - Expression const& _condition, + + struct ConstantExpressionCheckResult + { + smtutil::CheckResult canBeTrue; + smtutil::CheckResult canBeFalse; + }; + + /// Checks whether the given boolean condition is either true or always false under given constraints. + /// Returns the results from the solver for these two checks. + ConstantExpressionCheckResult checkBooleanNotConstant( smtutil::Expression const& _constraints, - smtutil::Expression const& _value, - std::vector const& _callStack + smtutil::Expression const& _condition ); std::pair> checkSatisfiableAndGenerateModel(std::vector const& _expressionsToEvaluate); @@ -222,20 +231,23 @@ class BMC: public SMTEncoder /// Number of verification conditions that could not be proved. size_t m_unprovedAmt = 0; + /// Loop analysis + //@{ enum class LoopControlKind { Continue, Break }; - // Current path conditions and SSA indices for break or continue statement + /// Current path conditions and SSA indices for break or continue statement struct LoopControl { LoopControlKind kind; smtutil::Expression pathConditions; VariableIndices variableIndices; }; - // Loop control statements for every loop + /// Loop control statements for every loop std::stack> m_loopCheckpoints; + //@} }; } From d9083dc11aa70eb3fa6089102c637b31fc9e0a31 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Fri, 21 Mar 2025 18:04:51 +0100 Subject: [PATCH 0841/1340] SMTChecker: Loop conditions should be analyzed as in loop context in BMC Value of loop condition can change between iterations of the loop. Therefore, BMC should be in the "inside loop" state when analyzing loop conditions. --- Changelog.md | 1 + libsolidity/formal/BMC.cpp | 10 +++++++--- ..._first_iteration_and_constant_false_in_second.sol | 10 ++++++++++ ..._first_iteration_and_constant_false_in_second.sol | 12 ++++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/loops/for_loop_condition_constant_true_in_first_iteration_and_constant_false_in_second.sol create mode 100644 test/libsolidity/smtCheckerTests/loops/while_loop_condition_constant_true_in_first_iteration_and_constant_false_in_second.sol diff --git a/Changelog.md b/Changelog.md index 525ed2d9e..e8ccbb525 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: +* SMTChecker: Do not consider loop conditions as constant-condition verification target as this could cause incorrect reports and internal compiler errors. * SMTChecker: Fix incorrect analysis when only a subset of contracts is selected with `--model-checker-contracts`. * SMTChecker: Fix internal compiler error when string literal is used to initialize user-defined type based on fixed bytes. diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 4b494d623..8401c8dbf 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -363,7 +363,9 @@ bool BMC::visit(WhileStatement const& _node) { //after loop iterations are done, we check the loop condition last final time auto indices = copyVariableIndices(); + m_loopCheckpoints.emplace(); _node.condition().accept(*this); + m_loopCheckpoints.pop(); loopCondition = expr(_node.condition()); // assert that the loop is complete m_context.addAssertion(!loopCondition || broke || !loopConditionOnPreviousIterations); @@ -391,13 +393,13 @@ bool BMC::visit(ForStatement const& _node) for (unsigned int i = 0; i < bmcLoopIterations; ++i) { auto indicesBefore = copyVariableIndices(); + m_loopCheckpoints.emplace(); if (_node.condition()) { _node.condition()->accept(*this); // values in loop condition might change during loop iteration forCondition = expr(*_node.condition()); } - m_loopCheckpoints.emplace(); auto indicesAfterCondition = copyVariableIndices(); pushPathCondition(forCondition); @@ -443,8 +445,10 @@ bool BMC::visit(ForStatement const& _node) auto indices = copyVariableIndices(); if (_node.condition()) { + m_loopCheckpoints.emplace(); _node.condition()->accept(*this); forCondition = expr(*_node.condition()); + m_loopCheckpoints.pop(); } // assert that the loop is complete m_context.addAssertion(!forCondition || broke || !forConditionOnPreviousIterations); @@ -932,9 +936,9 @@ void BMC::checkVerificationTarget(BMCVerificationTarget& _target) checkAssert(_target); break; case VerificationTargetType::ConstantCondition: - solAssert(false, "Checks for constant condition are handled separately"); + smtAssert(false, "Checks for constant condition are handled separately"); default: - solAssert(false, ""); + smtAssert(false); } } diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_condition_constant_true_in_first_iteration_and_constant_false_in_second.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_condition_constant_true_in_first_iteration_and_constant_false_in_second.sol new file mode 100644 index 000000000..7e0a85b9b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_condition_constant_true_in_first_iteration_and_constant_false_in_second.sol @@ -0,0 +1,10 @@ +contract Test { + function loop() public pure { + for (uint k = 0; (k == 0 ? true : false); k++) { + } + } +} +// ==== +// SMTEngine: bmc +// SMTTargets: constantCondition +// ---- diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_condition_constant_true_in_first_iteration_and_constant_false_in_second.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_condition_constant_true_in_first_iteration_and_constant_false_in_second.sol new file mode 100644 index 000000000..b367cb803 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_condition_constant_true_in_first_iteration_and_constant_false_in_second.sol @@ -0,0 +1,12 @@ +contract Test { + function loop() public pure { + uint k = 0; + while (k == 0 ? true : false) { + ++k; + } + } +} +// ==== +// SMTEngine: bmc +// SMTTargets: constantCondition +// ---- From b1a9031f5875e8bfd2e8ac670818c954096b8543 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Sat, 29 Mar 2025 20:11:58 +0100 Subject: [PATCH 0842/1340] SMTChecker: Clean up includes --- libsmtutil/SMTLib2Interface.cpp | 3 ++- libsmtutil/SMTPortfolio.h | 3 --- libsmtutil/SolverInterface.h | 3 ++- libsolidity/formal/ArraySlicePredicate.cpp | 2 ++ libsolidity/formal/ArraySlicePredicate.h | 4 ++-- libsolidity/formal/EncodingContext.cpp | 7 +++++++ libsolidity/formal/EncodingContext.h | 5 +---- libsolidity/formal/ExpressionFormatter.cpp | 2 ++ libsolidity/formal/Predicate.cpp | 2 +- libsolidity/formal/Predicate.h | 3 ++- libsolidity/formal/SymbolicTypes.cpp | 1 + libsolidity/formal/SymbolicTypes.h | 1 - libsolidity/formal/SymbolicVariables.cpp | 2 ++ libsolidity/formal/VariableUsage.cpp | 5 +---- 14 files changed, 25 insertions(+), 18 deletions(-) diff --git a/libsmtutil/SMTLib2Interface.cpp b/libsmtutil/SMTLib2Interface.cpp index 0430f0d21..403989ca1 100644 --- a/libsmtutil/SMTLib2Interface.cpp +++ b/libsmtutil/SMTLib2Interface.cpp @@ -25,7 +25,8 @@ #include #include -#include +#include +#include #include #include diff --git a/libsmtutil/SMTPortfolio.h b/libsmtutil/SMTPortfolio.h index b445f40a2..59e0752a3 100644 --- a/libsmtutil/SMTPortfolio.h +++ b/libsmtutil/SMTPortfolio.h @@ -20,10 +20,7 @@ #include -#include -#include -#include #include namespace solidity::smtutil diff --git a/libsmtutil/SolverInterface.h b/libsmtutil/SolverInterface.h index 2639ae024..c434322d5 100644 --- a/libsmtutil/SolverInterface.h +++ b/libsmtutil/SolverInterface.h @@ -26,7 +26,8 @@ #include #include -#include +#include +#include #include #include diff --git a/libsolidity/formal/ArraySlicePredicate.cpp b/libsolidity/formal/ArraySlicePredicate.cpp index 21d5fb1ad..67e635deb 100644 --- a/libsolidity/formal/ArraySlicePredicate.cpp +++ b/libsolidity/formal/ArraySlicePredicate.cpp @@ -18,6 +18,8 @@ #include +#include + #include using namespace solidity; diff --git a/libsolidity/formal/ArraySlicePredicate.h b/libsolidity/formal/ArraySlicePredicate.h index 180a9d189..565dba657 100644 --- a/libsolidity/formal/ArraySlicePredicate.h +++ b/libsolidity/formal/ArraySlicePredicate.h @@ -16,9 +16,9 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#pragma once + #include -#include #include diff --git a/libsolidity/formal/EncodingContext.cpp b/libsolidity/formal/EncodingContext.cpp index e0a09bcf7..cc046cf03 100644 --- a/libsolidity/formal/EncodingContext.cpp +++ b/libsolidity/formal/EncodingContext.cpp @@ -18,12 +18,19 @@ #include +#include + #include using namespace solidity; using namespace solidity::util; using namespace solidity::frontend::smt; +bool EncodingContext::IdCompare::operator()(ASTNode const* lhs, ASTNode const* rhs) const +{ + return lhs->id() < rhs->id(); +} + EncodingContext::EncodingContext(): m_state(*this) { diff --git a/libsolidity/formal/EncodingContext.h b/libsolidity/formal/EncodingContext.h index 5387184ee..e7d577bbf 100644 --- a/libsolidity/formal/EncodingContext.h +++ b/libsolidity/formal/EncodingContext.h @@ -68,10 +68,7 @@ class EncodingContext struct IdCompare { - bool operator()(ASTNode const* lhs, ASTNode const* rhs) const - { - return lhs->id() < rhs->id(); - } + bool operator()(ASTNode const* lhs, ASTNode const* rhs) const; }; /// Variables. diff --git a/libsolidity/formal/ExpressionFormatter.cpp b/libsolidity/formal/ExpressionFormatter.cpp index 865a568f6..dff84c860 100644 --- a/libsolidity/formal/ExpressionFormatter.cpp +++ b/libsolidity/formal/ExpressionFormatter.cpp @@ -20,6 +20,8 @@ #include +#include + #include #include diff --git a/libsolidity/formal/Predicate.cpp b/libsolidity/formal/Predicate.cpp index 66d8c2405..7f742ec18 100644 --- a/libsolidity/formal/Predicate.cpp +++ b/libsolidity/formal/Predicate.cpp @@ -28,7 +28,7 @@ #include -#include +#include #include using namespace solidity; diff --git a/libsolidity/formal/Predicate.h b/libsolidity/formal/Predicate.h index 7e4ba0f00..d523f9554 100644 --- a/libsolidity/formal/Predicate.h +++ b/libsolidity/formal/Predicate.h @@ -19,7 +19,8 @@ #pragma once -#include +#include +#include #include #include diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 738a48f70..11c92a83a 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -20,6 +20,7 @@ #include +#include #include #include #include diff --git a/libsolidity/formal/SymbolicTypes.h b/libsolidity/formal/SymbolicTypes.h index d38dcc045..9259ff64a 100644 --- a/libsolidity/formal/SymbolicTypes.h +++ b/libsolidity/formal/SymbolicTypes.h @@ -19,7 +19,6 @@ #pragma once #include -#include #include namespace solidity::frontend::smt diff --git a/libsolidity/formal/SymbolicVariables.cpp b/libsolidity/formal/SymbolicVariables.cpp index f0cebc46c..29301d095 100644 --- a/libsolidity/formal/SymbolicVariables.cpp +++ b/libsolidity/formal/SymbolicVariables.cpp @@ -18,6 +18,8 @@ #include +#include + #include #include diff --git a/libsolidity/formal/VariableUsage.cpp b/libsolidity/formal/VariableUsage.cpp index ab7c425ae..000dcbc81 100644 --- a/libsolidity/formal/VariableUsage.cpp +++ b/libsolidity/formal/VariableUsage.cpp @@ -18,12 +18,9 @@ #include -#include #include -#include - -#include +#include using namespace solidity; using namespace solidity::util; From 629bb285394593aa5271d1a8dbdf335e71d99ce4 Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Sat, 29 Mar 2025 21:29:24 +0100 Subject: [PATCH 0843/1340] SMTChecker: Remove unused functionality --- libsolidity/CMakeLists.txt | 2 - libsolidity/formal/BMC.cpp | 1 - libsolidity/formal/SMTEncoder.cpp | 9 --- libsolidity/formal/SMTEncoder.h | 2 - libsolidity/formal/VariableUsage.cpp | 115 --------------------------- libsolidity/formal/VariableUsage.h | 65 --------------- 6 files changed, 194 deletions(-) delete mode 100644 libsolidity/formal/VariableUsage.cpp delete mode 100644 libsolidity/formal/VariableUsage.h diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index f0289acac..62f0576dc 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -137,8 +137,6 @@ set(sources formal/SymbolicTypes.h formal/SymbolicVariables.cpp formal/SymbolicVariables.h - formal/VariableUsage.cpp - formal/VariableUsage.h formal/Z3CHCSmtLib2Interface.cpp formal/Z3CHCSmtLib2Interface.h formal/Z3SMTLib2Interface.cpp diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 8401c8dbf..bcd88b6da 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -80,7 +80,6 @@ void BMC::analyze(SourceUnit const& _source, std::map SMTEncoder::touchedVariables(ASTNode const& _node) -{ - std::vector callStack; - for (auto const& call: m_callStack) - callStack.push_back(call.first); - return m_variableUsage.touchedVariables(_node, callStack); -} - Declaration const* SMTEncoder::expressionToDeclaration(Expression const& _expr) const { if (auto const* identifier = dynamic_cast(&_expr)) diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index 5bfb70d81..60cfb9cf9 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -454,7 +453,6 @@ class SMTEncoder: public ASTConstVisitor smtutil::Expression constraints; }; - smt::VariableUsage m_variableUsage; bool m_arrayAssignmentHappened = false; /// Stores the instances of an Uninterpreted Function applied to arguments. diff --git a/libsolidity/formal/VariableUsage.cpp b/libsolidity/formal/VariableUsage.cpp deleted file mode 100644 index 000dcbc81..000000000 --- a/libsolidity/formal/VariableUsage.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - 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 - -#include - -#include - -#include - -using namespace solidity; -using namespace solidity::util; -using namespace solidity::frontend; -using namespace solidity::frontend::smt; - -std::set VariableUsage::touchedVariables(ASTNode const& _node, std::vector const& _outerCallstack) -{ - m_touchedVariables.clear(); - m_callStack.clear(); - m_callStack += _outerCallstack; - if (!m_callStack.empty()) - m_lastCall = m_callStack.back(); - _node.accept(*this); - return m_touchedVariables; -} - -void VariableUsage::endVisit(Identifier const& _identifier) -{ - if (_identifier.annotation().willBeWrittenTo) - checkIdentifier(_identifier); -} - -void VariableUsage::endVisit(IndexAccess const& _indexAccess) -{ - if (_indexAccess.annotation().willBeWrittenTo) - { - /// identifier.annotation().willBeWrittenTo == false, that's why we - /// need to check that before. - auto identifier = dynamic_cast(SMTEncoder::leftmostBase(_indexAccess)); - if (identifier) - checkIdentifier(*identifier); - } -} - -void VariableUsage::endVisit(FunctionCall const& _funCall) -{ - auto scopeContract = currentScopeContract(); - if (m_inlineFunctionCalls(_funCall, scopeContract, m_currentContract)) - if (auto funDef = SMTEncoder::functionCallToDefinition(_funCall, scopeContract, m_currentContract)) - if (find(m_callStack.begin(), m_callStack.end(), funDef) == m_callStack.end()) - funDef->accept(*this); -} - -bool VariableUsage::visit(FunctionDefinition const& _function) -{ - m_callStack.push_back(&_function); - return true; -} - -void VariableUsage::endVisit(FunctionDefinition const&) -{ - solAssert(!m_callStack.empty(), ""); - m_callStack.pop_back(); -} - -void VariableUsage::endVisit(ModifierInvocation const& _modifierInv) -{ - auto const& modifierDef = dynamic_cast(_modifierInv.name().annotation().referencedDeclaration); - if (modifierDef) - modifierDef->accept(*this); -} - -void VariableUsage::endVisit(PlaceholderStatement const&) -{ - solAssert(!m_callStack.empty(), ""); - FunctionDefinition const* funDef = nullptr; - for (auto it = m_callStack.rbegin(); it != m_callStack.rend() && !funDef; ++it) - funDef = dynamic_cast(*it); - solAssert(funDef, ""); - if (funDef->isImplemented()) - funDef->body().accept(*this); -} - -void VariableUsage::checkIdentifier(Identifier const& _identifier) -{ - Declaration const* declaration = _identifier.annotation().referencedDeclaration; - solAssert(declaration, ""); - if (VariableDeclaration const* varDecl = dynamic_cast(declaration)) - { - if (!varDecl->isLocalVariable() || (m_lastCall && varDecl->functionOrModifierDefinition() == m_lastCall)) - m_touchedVariables.insert(varDecl); - } -} - -ContractDefinition const* VariableUsage::currentScopeContract() -{ - for (auto&& f: m_callStack | ranges::views::reverse) - if (auto fun = dynamic_cast(f)) - return fun->annotation().contract; - return nullptr; -} diff --git a/libsolidity/formal/VariableUsage.h b/libsolidity/formal/VariableUsage.h deleted file mode 100644 index 4dc90f8c0..000000000 --- a/libsolidity/formal/VariableUsage.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - 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 - -#pragma once - -#include - -#include -#include - -namespace solidity::frontend::smt -{ - -/** - * This class computes information about which variables are modified in a certain subtree. - */ -class VariableUsage: private ASTConstVisitor -{ -public: - /// @param _outerCallstack the current callstack in the callers context. - std::set touchedVariables(ASTNode const& _node, std::vector const& _outerCallstack); - - /// Sets whether to inline function calls. - void setFunctionInlining(std::function _inlineFunctionCalls) { m_inlineFunctionCalls = _inlineFunctionCalls; } - - void setCurrentContract(ContractDefinition const& _contract) { m_currentContract = &_contract; } - -private: - void endVisit(Identifier const& _node) override; - void endVisit(IndexAccess const& _node) override; - void endVisit(FunctionCall const& _node) override; - bool visit(FunctionDefinition const& _node) override; - void endVisit(FunctionDefinition const& _node) override; - void endVisit(ModifierInvocation const& _node) override; - void endVisit(PlaceholderStatement const& _node) override; - - /// Checks whether an identifier should be added to touchedVariables. - void checkIdentifier(Identifier const& _identifier); - - ContractDefinition const* currentScopeContract(); - - std::set m_touchedVariables; - std::vector m_callStack; - CallableDeclaration const* m_lastCall = nullptr; - ContractDefinition const* m_currentContract = nullptr; - - std::function m_inlineFunctionCalls = [](FunctionCall const&, ContractDefinition const*, ContractDefinition const*) { return false; }; -}; - -} From ae3da8c12ec9f1f22c3e2e1a9b29e5896a8313cf Mon Sep 17 00:00:00 2001 From: Maxim Ryabykh Date: Wed, 2 Oct 2024 11:56:08 +0300 Subject: [PATCH 0844/1340] docs: fixed a mismatch in the name of the function referenced in the micropayment example --- docs/examples/micropayment.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/micropayment.rst b/docs/examples/micropayment.rst index 9a3ad845c..a7b26bb51 100644 --- a/docs/examples/micropayment.rst +++ b/docs/examples/micropayment.rst @@ -274,8 +274,8 @@ Opening the Payment Channel To open the payment channel, Alice deploys the smart contract, attaching the Ether to be escrowed and specifying the intended recipient and a -maximum duration for the channel to exist. This is the function -``SimplePaymentChannel`` in the contract, at the end of this section. +maximum duration for the channel to exist. This is the ``constructor`` +in the ``SimplePaymentChannel`` contract, at the end of this section. Making Payments --------------- From fe7411114cc0c62ad386975a8ea491650b5c709a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 16 Apr 2025 13:37:43 +0200 Subject: [PATCH 0845/1340] EVMAssemblyStack: Add extra accessors that do not require contract name --- libevmasm/EVMAssemblyStack.cpp | 24 +++++++++++++++++------- libevmasm/EVMAssemblyStack.h | 6 ++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index 7cb05bf8b..bed4ff744 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -74,13 +74,13 @@ void EVMAssemblyStack::assemble() LinkerObject const& EVMAssemblyStack::object(std::string const& _contractName) const { solAssert(_contractName == m_name); - return m_object; + return object(); } LinkerObject const& EVMAssemblyStack::runtimeObject(std::string const& _contractName) const { solAssert(_contractName == m_name); - return m_runtimeObject; + return runtimeObject(); } std::map EVMAssemblyStack::sourceIndices() const @@ -95,13 +95,13 @@ std::map EVMAssemblyStack::sourceIndices() const std::string const* EVMAssemblyStack::sourceMapping(std::string const& _contractName) const { solAssert(_contractName == m_name); - return &m_sourceMapping; + return &sourceMapping(); } std::string const* EVMAssemblyStack::runtimeSourceMapping(std::string const& _contractName) const { solAssert(_contractName == m_name); - return &m_runtimeSourceMapping; + return &runtimeSourceMapping(); } Json EVMAssemblyStack::ethdebug(std::string const& _contractName) const @@ -123,20 +123,30 @@ Json EVMAssemblyStack::ethdebug() const return {}; } -Json EVMAssemblyStack::assemblyJSON(std::string const& _contractName) const +Json EVMAssemblyStack::assemblyJSON() const { - solAssert(_contractName == m_name); solAssert(m_evmAssembly); return m_evmAssembly->assemblyJSON(sourceIndices()); } -std::string EVMAssemblyStack::assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const +Json EVMAssemblyStack::assemblyJSON(std::string const& _contractName) const { solAssert(_contractName == m_name); + return assemblyJSON(); +} + +std::string EVMAssemblyStack::assemblyString(StringMap const& _sourceCodes) const +{ solAssert(m_evmAssembly); return m_evmAssembly->assemblyString(m_debugInfoSelection, _sourceCodes); } +std::string EVMAssemblyStack::assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const +{ + solAssert(_contractName == m_name); + return assemblyString(_sourceCodes); +} + std::string const EVMAssemblyStack::filesystemFriendlyName(std::string const& _contractName) const { solAssert(_contractName == m_name); diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index 2fe63c11c..444d444ba 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -58,20 +58,26 @@ class EVMAssemblyStack: public AbstractAssemblyStack std::string const& name() const { return m_name; } + LinkerObject const& object() const { return m_object; } LinkerObject const& object(std::string const& _contractName) const override; + LinkerObject const& runtimeObject() const { return m_runtimeObject; } LinkerObject const& runtimeObject(std::string const& _contractName) const override; std::shared_ptr const& evmAssembly() const { return m_evmAssembly; } std::shared_ptr const& evmRuntimeAssembly() const { return m_evmRuntimeAssembly; } + std::string const& sourceMapping() const { return m_sourceMapping; } std::string const* sourceMapping(std::string const& _contractName) const override; + std::string const& runtimeSourceMapping() const { return m_runtimeSourceMapping; } std::string const* runtimeSourceMapping(std::string const& _contractName) const override; Json ethdebug(std::string const& _contractName) const override; Json ethdebugRuntime(std::string const& _contractName) const override; Json ethdebug() const override; + Json assemblyJSON() const; Json assemblyJSON(std::string const& _contractName) const override; + std::string assemblyString(StringMap const& _sourceCodes) const; std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const override; std::string const filesystemFriendlyName(std::string const& _contractName) const override; From dd01ddda2379e6b9a2cf212e086e2d1ef6eb9340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 14 Mar 2025 04:04:14 +0100 Subject: [PATCH 0846/1340] TestCaseReader: Expose fileName() --- test/TestCaseReader.h | 1 + 1 file changed, 1 insertion(+) diff --git a/test/TestCaseReader.h b/test/TestCaseReader.h index d1ef95be3..5830e97f3 100644 --- a/test/TestCaseReader.h +++ b/test/TestCaseReader.h @@ -59,6 +59,7 @@ class TestCaseReader std::size_t lineNumber() const { return m_lineNumber; } std::map const& settings() const { return m_settings; } std::ifstream& stream() { return m_fileStream; } + boost::filesystem::path const& fileName() const { return m_fileName; } std::string simpleExpectations(); From d3238c08ff61516a6d86a3035a0582aaeb5e5894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 19 Apr 2025 04:36:11 +0200 Subject: [PATCH 0847/1340] Add a transparent comparator to c_instructions to allow string_view lookups --- libevmasm/Instruction.cpp | 2 +- libevmasm/Instruction.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index dad9804d0..b55687635 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -26,7 +26,7 @@ using namespace solidity; using namespace solidity::util; using namespace solidity::evmasm; -std::map const solidity::evmasm::c_instructions = +std::map> const solidity::evmasm::c_instructions = { { "STOP", Instruction::STOP }, { "ADD", Instruction::ADD }, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 137144715..cfdb85d2f 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -322,6 +322,6 @@ InstructionInfo instructionInfo(Instruction _inst, langutil::EVMVersion _evmVers bool isValidInstruction(Instruction _inst); /// Convert from string mnemonic to Instruction type. -extern const std::map c_instructions; +extern const std::map> c_instructions; } From 266c7d49a8b9a9524d841b088410957bb7335e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 14 Mar 2025 04:51:35 +0100 Subject: [PATCH 0848/1340] EVM assembly test case with JSON input --- test/CMakeLists.txt | 2 + test/InteractiveTests.h | 3 + test/TestCase.cpp | 7 +- test/libevmasm/EVMAssemblyTest.cpp | 158 ++++++++++++++++++ test/libevmasm/EVMAssemblyTest.h | 70 ++++++++ .../code_generation_error.asmjson | 14 ++ .../isoltestTesting/invalid_json.asmjson | 3 + .../settings_eof_version.asmjson | 13 ++ .../settings_evm_version.asmjson | 13 ++ ...tings_optimizer_constant_optimizer.asmjson | 14 ++ .../settings_optimizer_cse.asmjson | 16 ++ .../settings_optimizer_deduplicate.asmjson | 26 +++ ...expected_executions_per_deployment.asmjson | 26 +++ .../settings_optimizer_inliner.asmjson | 33 ++++ ...ettings_optimizer_jumpdest_remover.asmjson | 14 ++ .../settings_optimizer_peephole.asmjson | 15 ++ .../settings_optimizer_preset.asmjson | 18 ++ .../isoltestTesting/settings_outputs.asmjson | 10 ++ .../isoltestTesting/smoke.asmjson | 11 ++ test/tools/CMakeLists.txt | 1 + test/tools/isoltest.cpp | 2 +- 21 files changed, 465 insertions(+), 4 deletions(-) create mode 100644 test/libevmasm/EVMAssemblyTest.cpp create mode 100644 test/libevmasm/EVMAssemblyTest.h create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/code_generation_error.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/invalid_json.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/settings_eof_version.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/settings_evm_version.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_constant_optimizer.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_cse.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_deduplicate.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_expected_executions_per_deployment.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_inliner.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_jumpdest_remover.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_peephole.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_preset.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/settings_outputs.asmjson create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/smoke.asmjson diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index da115f0d4..6f48b8a84 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -51,6 +51,8 @@ detect_stray_source_files("${libsolutil_sources}" "libsolutil/") set(libevmasm_sources libevmasm/Assembler.cpp + libevmasm/EVMAssemblyTest.cpp + libevmasm/EVMAssemblyTest.h libevmasm/Optimiser.cpp ) detect_stray_source_files("${libevmasm_sources}" "libevmasm/") diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index e043fcdbe..107a6aae0 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -42,6 +42,8 @@ #include #include +#include + #include namespace solidity::frontend::test @@ -64,6 +66,7 @@ struct Testsuite Testsuite const g_interactiveTestsuites[] = { /* Title Path Subpath SMT NeedsVM Creator function */ + {"EVM Assembly", "libevmasm", "evmAssemblyTests", false, false, &evmasm::test::EVMAssemblyTest::create}, {"Yul Optimizer", "libyul", "yulOptimizerTests", false, false, &yul::test::YulOptimizerTest::create}, {"Yul Interpreter", "libyul", "yulInterpreterTests", false, false, &yul::test::YulInterpreterTest::create}, {"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create}, diff --git a/test/TestCase.cpp b/test/TestCase.cpp index da47c26fd..8a8d2451d 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -51,9 +51,10 @@ void TestCase::printUpdatedSettings(std::ostream& _stream, std::string const& _l bool TestCase::isTestFilename(boost::filesystem::path const& _filename) { std::string extension = _filename.extension().string(); - return (extension == ".sol" || extension == ".yul" || extension == ".stack") && - !boost::starts_with(_filename.string(), "~") && - !boost::starts_with(_filename.string(), "."); + // NOTE: .asmjson rather than .json because JSON files that do not represent test cases exist in some test dirs. + return (extension == ".sol" || extension == ".yul" || extension == ".asmjson" || extension == ".stack") && + !_filename.string().starts_with('~') && + !_filename.string().starts_with('.'); } bool TestCase::shouldRun() diff --git a/test/libevmasm/EVMAssemblyTest.cpp b/test/libevmasm/EVMAssemblyTest.cpp new file mode 100644 index 000000000..b497c5147 --- /dev/null +++ b/test/libevmasm/EVMAssemblyTest.cpp @@ -0,0 +1,158 @@ +/* + 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 . +*/ + +#include + +#include + +#include +#include + +#include +#include +#include + +#include + +using namespace std::string_literals; +using namespace solidity; +using namespace solidity::test; +using namespace solidity::evmasm; +using namespace solidity::evmasm::test; +using namespace solidity::frontend; +using namespace solidity::frontend::test; +using namespace solidity::langutil; +using namespace solidity::util; + +std::vector const EVMAssemblyTest::c_outputLabels = { + "Assembly", + "Bytecode", + "Opcodes", + "SourceMappings", +}; + +std::unique_ptr EVMAssemblyTest::create(Config const& _config) +{ + return std::make_unique(_config.filename); +} + +EVMAssemblyTest::EVMAssemblyTest(std::string const& _filename): + EVMVersionRestrictedTestCase(_filename) +{ + m_source = m_reader.source(); + m_expectation = m_reader.simpleExpectations(); + + if (!_filename.ends_with(".asmjson")) + BOOST_THROW_EXCEPTION(std::runtime_error("Not an assembly test: \"" + _filename + "\". Allowed extensions: .asmjson.")); + + m_selectedOutputs = m_reader.stringSetting("outputs", "Assembly,Bytecode,Opcodes,SourceMappings"); + OptimisationPreset optimizationPreset = m_reader.enumSetting( + "optimizationPreset", + { + {"none", OptimisationPreset::None}, + {"minimal", OptimisationPreset::Minimal}, + {"standard", OptimisationPreset::Standard}, + {"full", OptimisationPreset::Full}, + }, + "none" + ); + m_optimizerSettings = Assembly::OptimiserSettings::translateSettings(OptimiserSettings::preset(optimizationPreset)); + m_optimizerSettings.expectedExecutionsPerDeployment = m_reader.sizetSetting( + "optimizer.expectedExecutionsPerDeployment", + m_optimizerSettings.expectedExecutionsPerDeployment + ); + + auto const optimizerComponentSetting = [&](std::string const& _component, bool& _setting) { + _setting = m_reader.boolSetting("optimizer." + _component, _setting); + }; + optimizerComponentSetting("inliner", m_optimizerSettings.runInliner); + optimizerComponentSetting("jumpdestRemover", m_optimizerSettings.runJumpdestRemover); + optimizerComponentSetting("peephole", m_optimizerSettings.runPeephole); + optimizerComponentSetting("deduplicate", m_optimizerSettings.runDeduplicate); + optimizerComponentSetting("cse", m_optimizerSettings.runCSE); + optimizerComponentSetting("constantOptimizer", m_optimizerSettings.runConstantOptimiser); + + // TODO: Enable when assembly import for EOF is implemented. + if (CommonOptions::get().eofVersion().has_value()) + m_shouldRun = false; +} + +TestCase::TestResult EVMAssemblyTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) +{ + EVMAssemblyStack evmAssemblyStack( + CommonOptions::get().evmVersion(), + CommonOptions::get().eofVersion(), + m_optimizerSettings + ); + + evmAssemblyStack.selectDebugInfo(DebugInfoSelection::AllExceptExperimental()); + + try + { + evmAssemblyStack.parseAndAnalyze(m_reader.fileName().filename().string(), m_source); + } + catch (AssemblyImportException const& _exception) + { + m_obtainedResult = "AssemblyImportException: "s + _exception.what() + "\n"; + return checkResult(_stream, _linePrefix, _formatted); + } + + try + { + evmAssemblyStack.assemble(); + } + catch (Error const& _error) + { + // TODO: EVMAssemblyStack should catch these on its own and provide an error reporter. + soltestAssert(_error.comment(), "Errors must include a message for the user."); + m_obtainedResult = Error::formatErrorType(_error.type()) + ": " + *_error.comment() + "\n"; + return checkResult(_stream, _linePrefix, _formatted); + } + soltestAssert(evmAssemblyStack.compilationSuccessful()); + + auto const produceOutput = [&](std::string const& _output) { + if (_output == "Assembly") + return evmAssemblyStack.assemblyString({{m_reader.fileName().filename().string(), m_source}}); + if (_output == "Bytecode") + return util::toHex(evmAssemblyStack.object().bytecode); + if (_output == "Opcodes") + return disassemble(evmAssemblyStack.object().bytecode, CommonOptions::get().evmVersion()); + if (_output == "SourceMappings") + return evmAssemblyStack.sourceMapping(); + soltestAssert(false); + unreachable(); + }; + + std::set selectedOutputSet; + boost::split(selectedOutputSet, m_selectedOutputs, boost::is_any_of(",")); + for (std::string const& output: c_outputLabels) + if (selectedOutputSet.contains(output)) + { + if (!m_obtainedResult.empty() && m_obtainedResult.back() != '\n') + m_obtainedResult += "\n"; + + // Don't trim on the left to avoid stripping indentation. + std::string content = produceOutput(output); + boost::trim_right(content); + std::string separator = (content.empty() ? "" : (output == "Assembly" ? "\n" : " ")); + m_obtainedResult += output + ":" + separator + content; + } + if (!m_obtainedResult.empty() && m_obtainedResult.back() != '\n') + m_obtainedResult += "\n"; + + return checkResult(_stream, _linePrefix, _formatted); +} diff --git a/test/libevmasm/EVMAssemblyTest.h b/test/libevmasm/EVMAssemblyTest.h new file mode 100644 index 000000000..f8923c0dc --- /dev/null +++ b/test/libevmasm/EVMAssemblyTest.h @@ -0,0 +1,70 @@ +/* + 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 + +#pragma once + +#include + +#include + +#include +#include +#include +#include + +namespace solidity::evmasm::test +{ + +/// Custom test case that runs the final part of the compiler pipeline (assembling into bytecode). +/// Supports assembly JSON format produced by --asm-json. +/// +/// Available settings: +/// - EVMVersion: The range of EVM versions to run the test for. Inherited from EVMVersionRestrictedTestCase. +/// - bytecodeFormat: The range of bytecode formats (EOF/legacy) to run the test for. Inherited from EVMVersionRestrictedTestCase. +/// - outputs: List of outputs to include in the test. The order of values does NOT determine the order +/// in which the outputs are printed. Supported outputs: Assembly, Bytecode, Opcodes, SourceMappings. +/// The default is to print all outputs. +/// - optimizationPreset: Preset to load as the base optimizer settings. +/// One of: none, minimal, standard, full. The default is none. +/// - optimizer.*: A set of detailed optimizer settings applied on top of the base preset. +/// Each one corresponds to a field in Assembly::OptimiserSettings and uses the value from the +/// preset as its default. Available settings: +/// - optimizer.expectedExecutionsPerDeployment (integer) +/// - optimizer.inliner (bool) +/// - optimizer.jumpdestRemover (bool) +/// - optimizer.peephole (bool) +/// - optimizer.deduplicate (bool) +/// - optimizer.cse (bool) +/// - optimizer.constantOptimizer (bool) +class EVMAssemblyTest: public frontend::test::EVMVersionRestrictedTestCase +{ +public: + static std::unique_ptr create(Config const& _config); + + EVMAssemblyTest(std::string const& _filename); + + TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; + +private: + static std::vector const c_outputLabels; + + std::string m_selectedOutputs; + evmasm::Assembly::OptimiserSettings m_optimizerSettings; +}; + +} diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/code_generation_error.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/code_generation_error.asmjson new file mode 100644 index 000000000..4297c5f35 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/code_generation_error.asmjson @@ -0,0 +1,14 @@ +{ + ".code": [ + {"name": "PUSH [$]", "value": "0"} + ], + ".data": { + "0": { + ".code": [ + {"name": "PUSHIMMUTABLE", "value": "x"} + ] + } + } +} +// ---- +// CodeGenerationError: Some immutables were read from but never assigned, possibly because of optimization. diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/invalid_json.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/invalid_json.asmjson new file mode 100644 index 000000000..a834108d1 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/invalid_json.asmjson @@ -0,0 +1,3 @@ +{ +// ---- +// AssemblyImportException: Could not parse JSON file. diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_eof_version.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_eof_version.asmjson new file mode 100644 index 000000000..5785b4b89 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_eof_version.asmjson @@ -0,0 +1,13 @@ +{ + ".code": [ + {"name": "CODESIZE"} + ] +} +// ==== +// bytecodeFormat: legacy +// ---- +// Assembly: +// codesize +// Bytecode: 38 +// Opcodes: CODESIZE +// SourceMappings: :::-:0 diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_evm_version.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_evm_version.asmjson new file mode 100644 index 000000000..a0f042b32 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_evm_version.asmjson @@ -0,0 +1,13 @@ +{ + ".code": [ + {"name": "BLOBBASEFEE"} + ] +} +// ==== +// EVMVersion: >=cancun +// ---- +// Assembly: +// blobbasefee +// Bytecode: 4a +// Opcodes: BLOBBASEFEE +// SourceMappings: :::-:0 diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_constant_optimizer.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_constant_optimizer.asmjson new file mode 100644 index 000000000..a3610217f --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_constant_optimizer.asmjson @@ -0,0 +1,14 @@ +{ + ".code": [ + {"name": "PUSH", "value": "ffffffffffffffff"} + ] +} +// ==== +// optimizationPreset: none +// optimizer.constantOptimizer: true +// ---- +// Assembly: +// sub(shl(0x40, 0x01), 0x01) +// Bytecode: 6001600160401b03 +// Opcodes: PUSH1 0x1 PUSH1 0x1 PUSH1 0x40 SHL SUB +// SourceMappings: :::-:0;;;; diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_cse.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_cse.asmjson new file mode 100644 index 000000000..c8133b43f --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_cse.asmjson @@ -0,0 +1,16 @@ +{ + ".code": [ + {"name": "PUSH", "value": "0"}, + {"name": "DUP2"}, + {"name": "SUB"} + ] +} +// ==== +// optimizationPreset: none +// optimizer.cse: true +// ---- +// Assembly: +// dup1 +// Bytecode: 80 +// Opcodes: DUP1 +// SourceMappings: :::-:0 diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_deduplicate.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_deduplicate.asmjson new file mode 100644 index 000000000..67b87e59e --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_deduplicate.asmjson @@ -0,0 +1,26 @@ +{ + ".code": [ + {"name": "PUSH [tag]", "value": "1"}, + {"name": "PUSH [tag]", "value": "2"}, + {"name": "tag", "value": "1"}, + {"name": "JUMPDEST"}, + {"name": "JUMP"}, + {"name": "tag", "value": "2"}, + {"name": "JUMPDEST"}, + {"name": "JUMP"} + ] +} +// ==== +// optimizationPreset: none +// optimizer.deduplicate: true +// ---- +// Assembly: +// tag_1 +// tag_1 +// tag_1: +// jump +// tag_2: +// jump +// Bytecode: 600460045b565b56 +// Opcodes: PUSH1 0x4 PUSH1 0x4 JUMPDEST JUMP JUMPDEST JUMP +// SourceMappings: :::-:0;;;;; diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_expected_executions_per_deployment.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_expected_executions_per_deployment.asmjson new file mode 100644 index 000000000..b9fd814d5 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_expected_executions_per_deployment.asmjson @@ -0,0 +1,26 @@ +{ + ".code": [ + {"name": "PUSH [$]", "value": "0"} + ], + ".data": { + "0": { + ".code": [ + {"name": "PUSH", "value": "ffffffffffffffff"} + ] + } + } +} +// ==== +// optimizationPreset: standard +// optimizer.expectedExecutionsPerDeployment: 0 +// ---- +// Assembly: +// dataOffset(sub_0) +// stop +// +// sub_0: assembly { +// sub(shl(0x40, 0x01), 0x01) +// } +// Bytecode: 6003fe6001600160401b03 +// Opcodes: PUSH1 0x3 INVALID PUSH1 0x1 PUSH1 0x1 PUSH1 0x40 SHL SUB +// SourceMappings: :::-:0 diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_inliner.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_inliner.asmjson new file mode 100644 index 000000000..81be6392c --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_inliner.asmjson @@ -0,0 +1,33 @@ +{ + ".code": [ + {"name": "PUSH [tag]", "value": "1"}, + {"name": "PUSH [tag]", "value": "2"}, + {"name": "JUMP"}, + {"name": "tag", "value": "1"}, + {"name": "JUMPDEST"}, + {"name": "STOP"}, + {"name": "tag", "value": "2"}, + {"name": "JUMPDEST"}, + {"name": "CALLVALUE"}, + {"name": "SWAP1"}, + {"name": "JUMP"} + ] +} +// ==== +// optimizationPreset: none +// optimizer.inliner: true +// ---- +// Assembly: +// tag_1 +// callvalue +// swap1 +// jump +// tag_1: +// stop +// tag_2: +// callvalue +// swap1 +// jump +// Bytecode: 60053490565b005b349056 +// Opcodes: PUSH1 0x5 CALLVALUE SWAP1 JUMP JUMPDEST STOP JUMPDEST CALLVALUE SWAP1 JUMP +// SourceMappings: :::-:0;;;;;;;;; diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_jumpdest_remover.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_jumpdest_remover.asmjson new file mode 100644 index 000000000..baca77b99 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_jumpdest_remover.asmjson @@ -0,0 +1,14 @@ +{ + ".code": [ + {"name": "tag", "value": "1"}, + {"name": "JUMPDEST"} + ] +} +// ==== +// optimizationPreset: none +// optimizer.jumpdestRemover: true +// ---- +// Assembly: +// Bytecode: +// Opcodes: +// SourceMappings: diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_peephole.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_peephole.asmjson new file mode 100644 index 000000000..f9e7c3b8d --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_peephole.asmjson @@ -0,0 +1,15 @@ +{ + ".code": [ + {"name": "STOP"}, + {"name": "STOP"} + ] +} +// ==== +// optimizationPreset: none +// optimizer.peephole: true +// ---- +// Assembly: +// stop +// Bytecode: 00 +// Opcodes: STOP +// SourceMappings: :::-:0 diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_preset.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_preset.asmjson new file mode 100644 index 000000000..706a3ae8b --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_optimizer_preset.asmjson @@ -0,0 +1,18 @@ +{ + ".code": [ + {"name": "PUSH", "value": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"name": "PUSH", "value": "42"}, + {"name": "PUSH", "value": "24"}, + {"name": "SWAP1"}, + {"name": "ADD"} + ] +} +// ==== +// optimizationPreset: full +// ---- +// Assembly: +// not(0x00) +// 0x66 +// Bytecode: 5f196066 +// Opcodes: PUSH0 NOT PUSH1 0x66 +// SourceMappings: :::-:0;; diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_outputs.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_outputs.asmjson new file mode 100644 index 000000000..2af7b57c3 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/settings_outputs.asmjson @@ -0,0 +1,10 @@ +{ + ".code": [ + {"name": "CALLVALUE"} + ] +} +// ==== +// outputs: SourceMappings,Opcodes +// ---- +// Opcodes: CALLVALUE +// SourceMappings: :::-:0 diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/smoke.asmjson b/test/libevmasm/evmAssemblyTests/isoltestTesting/smoke.asmjson new file mode 100644 index 000000000..99e527a72 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/smoke.asmjson @@ -0,0 +1,11 @@ +{ + ".code": [ + {"name": "CALLVALUE"} + ] +} +// ---- +// Assembly: +// callvalue +// Bytecode: 34 +// Opcodes: CALLVALUE +// SourceMappings: :::-:0 diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 5c1d41b7f..13018bf18 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -18,6 +18,7 @@ add_executable(isoltest ../EVMHost.cpp ../TestCase.cpp ../TestCaseReader.cpp + ../libevmasm/EVMAssemblyTest.cpp ../libsolidity/util/BytesUtils.cpp ../libsolidity/util/Common.cpp ../libsolidity/util/ContractABIUtils.cpp diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index 57ab4af16..32309b005 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -75,7 +75,7 @@ class TestFilter boost::replace_all(filter, "/", "\\/"); boost::replace_all(filter, "*", ".*"); - m_filterExpression = std::regex{"(" + filter + "(\\.sol|\\.yul|\\.stack))"}; + m_filterExpression = std::regex{"(" + filter + "(\\.sol|\\.yul|\\.asmjson|\\.stack))"}; } bool matches(fs::path const& _path, std::string const& _name) const From fe3955111883851f64939783b9f542ccf33f6998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 18 Apr 2025 03:18:05 +0200 Subject: [PATCH 0849/1340] Support human-readable assembly in EVM assembly test case --- test/CMakeLists.txt | 2 + test/TestCase.cpp | 2 +- test/libevmasm/EVMAssemblyTest.cpp | 29 ++- test/libevmasm/EVMAssemblyTest.h | 16 +- test/libevmasm/PlainAssemblyParser.cpp | 180 ++++++++++++++++++ test/libevmasm/PlainAssemblyParser.h | 79 ++++++++ .../isoltestTesting/comments.asm | 34 ++++ .../isoltestTesting/jumps.asm | 56 ++++++ .../isoltestTesting/operations.asm | 53 ++++++ .../evmAssemblyTests/isoltestTesting/push.asm | 35 ++++ .../isoltestTesting/smoke_plain.asm | 16 ++ test/tools/CMakeLists.txt | 1 + test/tools/isoltest.cpp | 2 +- 13 files changed, 497 insertions(+), 8 deletions(-) create mode 100644 test/libevmasm/PlainAssemblyParser.cpp create mode 100644 test/libevmasm/PlainAssemblyParser.h create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/comments.asm create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/jumps.asm create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/operations.asm create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/push.asm create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/smoke_plain.asm diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6f48b8a84..c66963c19 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,6 +54,8 @@ set(libevmasm_sources libevmasm/EVMAssemblyTest.cpp libevmasm/EVMAssemblyTest.h libevmasm/Optimiser.cpp + libevmasm/PlainAssemblyParser.cpp + libevmasm/PlainAssemblyParser.h ) detect_stray_source_files("${libevmasm_sources}" "libevmasm/") diff --git a/test/TestCase.cpp b/test/TestCase.cpp index 8a8d2451d..efc455ff6 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -52,7 +52,7 @@ bool TestCase::isTestFilename(boost::filesystem::path const& _filename) { std::string extension = _filename.extension().string(); // NOTE: .asmjson rather than .json because JSON files that do not represent test cases exist in some test dirs. - return (extension == ".sol" || extension == ".yul" || extension == ".asmjson" || extension == ".stack") && + return (extension == ".sol" || extension == ".yul" || extension == ".asm" || extension == ".asmjson" || extension == ".stack") && !_filename.string().starts_with('~') && !_filename.string().starts_with('.'); } diff --git a/test/libevmasm/EVMAssemblyTest.cpp b/test/libevmasm/EVMAssemblyTest.cpp index b497c5147..0c1dbb07e 100644 --- a/test/libevmasm/EVMAssemblyTest.cpp +++ b/test/libevmasm/EVMAssemblyTest.cpp @@ -17,6 +17,8 @@ #include +#include + #include #include @@ -39,6 +41,7 @@ using namespace solidity::langutil; using namespace solidity::util; std::vector const EVMAssemblyTest::c_outputLabels = { + "InputAssemblyJSON", "Assembly", "Bytecode", "Opcodes", @@ -56,8 +59,12 @@ EVMAssemblyTest::EVMAssemblyTest(std::string const& _filename): m_source = m_reader.source(); m_expectation = m_reader.simpleExpectations(); - if (!_filename.ends_with(".asmjson")) - BOOST_THROW_EXCEPTION(std::runtime_error("Not an assembly test: \"" + _filename + "\". Allowed extensions: .asmjson.")); + if (_filename.ends_with(".asmjson")) + m_assemblyFormat = AssemblyFormat::JSON; + else if (_filename.ends_with(".asm")) + m_assemblyFormat = AssemblyFormat::Plain; + else + BOOST_THROW_EXCEPTION(std::runtime_error("Not an assembly test: \"" + _filename + "\". Allowed extensions: .asm, .asmjson.")); m_selectedOutputs = m_reader.stringSetting("outputs", "Assembly,Bytecode,Opcodes,SourceMappings"); OptimisationPreset optimizationPreset = m_reader.enumSetting( @@ -101,9 +108,23 @@ TestCase::TestResult EVMAssemblyTest::run(std::ostream& _stream, std::string con evmAssemblyStack.selectDebugInfo(DebugInfoSelection::AllExceptExperimental()); + std::string assemblyJSON; + switch (m_assemblyFormat) + { + case AssemblyFormat::JSON: + assemblyJSON = m_source; + break; + case AssemblyFormat::Plain: + assemblyJSON = jsonPrint( + PlainAssemblyParser{}.parse(m_reader.fileName().filename().string(), m_source), + {JsonFormat::Pretty, 4} + ); + break; + } + try { - evmAssemblyStack.parseAndAnalyze(m_reader.fileName().filename().string(), m_source); + evmAssemblyStack.parseAndAnalyze(m_reader.fileName().filename().string(), assemblyJSON); } catch (AssemblyImportException const& _exception) { @@ -125,6 +146,8 @@ TestCase::TestResult EVMAssemblyTest::run(std::ostream& _stream, std::string con soltestAssert(evmAssemblyStack.compilationSuccessful()); auto const produceOutput = [&](std::string const& _output) { + if (_output == "InputAssemblyJSON") + return assemblyJSON; if (_output == "Assembly") return evmAssemblyStack.assemblyString({{m_reader.fileName().filename().string(), m_source}}); if (_output == "Bytecode") diff --git a/test/libevmasm/EVMAssemblyTest.h b/test/libevmasm/EVMAssemblyTest.h index f8923c0dc..9059fd716 100644 --- a/test/libevmasm/EVMAssemblyTest.h +++ b/test/libevmasm/EVMAssemblyTest.h @@ -31,14 +31,17 @@ namespace solidity::evmasm::test { /// Custom test case that runs the final part of the compiler pipeline (assembling into bytecode). -/// Supports assembly JSON format produced by --asm-json. +/// Supports two kinds of input (depending on file extension): +/// - .asmjson: assembly JSON format produced by --asm-json. +/// - .asm: plain assembly, a more limited but human-readable format that is internally converted +/// to assembly JSON. /// /// Available settings: /// - EVMVersion: The range of EVM versions to run the test for. Inherited from EVMVersionRestrictedTestCase. /// - bytecodeFormat: The range of bytecode formats (EOF/legacy) to run the test for. Inherited from EVMVersionRestrictedTestCase. /// - outputs: List of outputs to include in the test. The order of values does NOT determine the order -/// in which the outputs are printed. Supported outputs: Assembly, Bytecode, Opcodes, SourceMappings. -/// The default is to print all outputs. +/// in which the outputs are printed. Supported outputs: InputAssemblyJSON, Assembly, Bytecode, Opcodes, SourceMappings. +/// The default is to print all outputs except InputAssemblyJSON. /// - optimizationPreset: Preset to load as the base optimizer settings. /// One of: none, minimal, standard, full. The default is none. /// - optimizer.*: A set of detailed optimizer settings applied on top of the base preset. @@ -61,8 +64,15 @@ class EVMAssemblyTest: public frontend::test::EVMVersionRestrictedTestCase TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: + enum class AssemblyFormat + { + JSON, + Plain, + }; + static std::vector const c_outputLabels; + AssemblyFormat m_assemblyFormat{}; std::string m_selectedOutputs; evmasm::Assembly::OptimiserSettings m_optimizerSettings; }; diff --git a/test/libevmasm/PlainAssemblyParser.cpp b/test/libevmasm/PlainAssemblyParser.cpp new file mode 100644 index 000000000..0fb9d62c8 --- /dev/null +++ b/test/libevmasm/PlainAssemblyParser.cpp @@ -0,0 +1,180 @@ +/* + 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 . +*/ + +#include + +#include +#include + +#include + +#include + +#include + +#include + +#include + +using namespace std::string_literals; +using namespace solidity; +using namespace solidity::test; +using namespace solidity::evmasm; +using namespace solidity::evmasm::test; +using namespace solidity::langutil; + +Json PlainAssemblyParser::parse(std::string _sourceName, std::string const& _source) +{ + m_sourceName = std::move(_sourceName); + Json codeJSON = Json::array(); + std::istringstream sourceStream(_source); + while (getline(sourceStream, m_line)) + { + advanceLine(m_line); + if (m_lineTokens.empty()) + continue; + + if (c_instructions.contains(currentToken().value)) + { + expectNoMoreArguments(); + codeJSON.push_back({{"name", currentToken().value}}); + } + else if (currentToken().value == "PUSH") + { + if (hasMoreTokens() && nextToken().value == "[tag]") + { + advanceToken(); + std::string_view tagID = expectArgument(); + expectNoMoreArguments(); + codeJSON.push_back({{"name", "PUSH [tag]"}, {"value", tagID}}); + } + else + { + std::string_view immediateArgument = expectArgument(); + expectNoMoreArguments(); + + if (!immediateArgument.starts_with("0x")) + BOOST_THROW_EXCEPTION(std::runtime_error(formatError("The immediate argument to PUSH must be a hex number prefixed with '0x'."))); + + immediateArgument.remove_prefix("0x"s.size()); + codeJSON.push_back({{"name", "PUSH"}, {"value", immediateArgument}}); + } + } + else if (currentToken().value == "tag") + { + std::string_view tagID = expectArgument(); + expectNoMoreArguments(); + + codeJSON.push_back({{"name", "tag"}, {"value", tagID}}); + codeJSON.push_back({{"name", "JUMPDEST"}}); + } + else + BOOST_THROW_EXCEPTION(std::runtime_error(formatError("Unknown instruction."))); + } + return {{".code", codeJSON}}; +} + +PlainAssemblyParser::Token const& PlainAssemblyParser::currentToken() const +{ + soltestAssert(m_tokenIndex < m_lineTokens.size()); + return m_lineTokens[m_tokenIndex]; +} + +PlainAssemblyParser::Token const& PlainAssemblyParser::nextToken() const +{ + soltestAssert(m_tokenIndex + 1 < m_lineTokens.size()); + return m_lineTokens[m_tokenIndex + 1]; +} + +bool PlainAssemblyParser::advanceToken() +{ + if (!hasMoreTokens()) + return false; + + ++m_tokenIndex; + return true; +} + +std::string_view PlainAssemblyParser::expectArgument() +{ + bool hasArgument = advanceToken(); + if (!hasArgument) + BOOST_THROW_EXCEPTION(std::runtime_error(formatError("Missing argument(s)."))); + + return currentToken().value; +} + +void PlainAssemblyParser::expectNoMoreArguments() +{ + bool hasArgument = advanceToken(); + if (hasArgument) + BOOST_THROW_EXCEPTION(std::runtime_error(formatError("Too many arguments."))); +} + +void PlainAssemblyParser::advanceLine(std::string_view _line) +{ + ++m_lineNumber; + m_line = _line; + m_lineTokens = tokenizeLine(m_line); + m_tokenIndex = 0; +} + +std::vector PlainAssemblyParser::tokenizeLine(std::string_view _line) +{ + auto const notWhiteSpace = [](char _c) { return !isWhiteSpace(_c); }; + + std::vector tokens; + auto tokenLocation = boost::find_token(_line, notWhiteSpace, boost::token_compress_on); + while (!tokenLocation.empty()) + { + std::string_view value{tokenLocation.begin(), tokenLocation.end()}; + if (value.starts_with("//")) + break; + + tokens.push_back({ + .value = value, + .position = static_cast(std::distance(_line.begin(), tokenLocation.begin())), + }); + soltestAssert(!value.empty()); + soltestAssert(tokens.back().position < _line.size()); + soltestAssert(tokens.back().position + value.size() <= _line.size()); + + std::string_view tail{tokenLocation.end(), _line.end()}; + tokenLocation = boost::find_token(tail, notWhiteSpace, boost::token_compress_on); + } + + return tokens; +} + +std::string PlainAssemblyParser::formatError(std::string_view _message) const +{ + std::string lineNumberString = std::to_string(m_lineNumber); + std::string padding(lineNumberString.size(), ' '); + std::string underline = std::string(currentToken().position, ' ') + std::string(currentToken().value.size(), '^'); + return fmt::format( + "Error while parsing plain assembly: {}\n" + "{}--> {}\n" + "{} | \n" + "{} | {}\n" + "{} | {}\n", + _message, + padding, m_sourceName, + padding, + m_lineNumber, m_line, + padding, underline + ); +} diff --git a/test/libevmasm/PlainAssemblyParser.h b/test/libevmasm/PlainAssemblyParser.h new file mode 100644 index 000000000..0154af5f7 --- /dev/null +++ b/test/libevmasm/PlainAssemblyParser.h @@ -0,0 +1,79 @@ +/* + 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 + +#pragma once + +#include + +#include +#include +#include + +namespace solidity::evmasm::test +{ + +/// Parser for the plain assembly format. The format is meant to be good enough for humans to read +/// while being straightforward to map to the assembly JSON format that solc can import. +/// +/// Syntax: +/// - Every line consists of zero or more whitespace-separated tokens. +/// - A token that begins with `//` starts a comment, which extends to the end of the line. +/// - A non-empty line represents a single assembly item. +/// - The name of the item is the first thing on the line and may consist of one or more tokens. +/// - One or more arguments follow the name. +/// +/// Supported items: +/// - All instruction names. +/// - PUSH +/// - PUSH [tag] +/// - tag +class PlainAssemblyParser +{ +public: + /// Parses plain assembly format and returns the equivalent assembly JSON. + /// Errors are reported by throwing runtime_error. + Json parse(std::string _sourceName, std::string const& _source); + +protected: + struct Token + { + std::string_view value; ///< Substring of m_line that represents a complete token. + size_t position; ///< Position of the first character of the token within m_line. + }; + + Token const& currentToken() const; + Token const& nextToken() const; + bool hasMoreTokens() const { return m_tokenIndex + 1 < m_lineTokens.size(); } + + bool advanceToken(); + std::string_view expectArgument(); + void expectNoMoreArguments(); + void advanceLine(std::string_view _line); + + static std::vector tokenizeLine(std::string_view _line); + std::string formatError(std::string_view _message) const; + +private: + std::string m_sourceName; ///< Name of the file the source comes from. + size_t m_lineNumber = 0; ///< The number of the current line within the source, 1-based. + std::string m_line; ///< The current line, unparsed. + std::vector m_lineTokens; ///< Decomposition of the current line into tokens (does not include comments). + size_t m_tokenIndex = 0; ///< Points at a token within m_lineTokens. +}; + +} diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/comments.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/comments.asm new file mode 100644 index 000000000..13dca3ad1 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/comments.asm @@ -0,0 +1,34 @@ +// +//// comment + // comment +CALLVALUE // 0xff +CALLVALUE //0xff + +PUSH 0xff // comment // //0xff +// + +// +// ==== +// outputs: InputAssemblyJSON,Assembly,Bytecode,Opcodes,SourceMappings +// ---- +// InputAssemblyJSON: { +// ".code": [ +// { +// "name": "CALLVALUE" +// }, +// { +// "name": "CALLVALUE" +// }, +// { +// "name": "PUSH", +// "value": "ff" +// } +// ] +// } +// Assembly: +// callvalue +// callvalue +// 0xff +// Bytecode: 343460ff +// Opcodes: CALLVALUE CALLVALUE PUSH1 0xFF +// SourceMappings: :::-:0;; diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/jumps.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/jumps.asm new file mode 100644 index 000000000..be92671d8 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/jumps.asm @@ -0,0 +1,56 @@ +PUSH [tag] 1 +JUMP +tag 1 +PUSH 0x01 +JUMPI +PUSH [tag] 0x012AB +tag 0x012AB +// ==== +// outputs: InputAssemblyJSON,Assembly,Bytecode,Opcodes,SourceMappings +// ---- +// InputAssemblyJSON: { +// ".code": [ +// { +// "name": "PUSH [tag]", +// "value": "1" +// }, +// { +// "name": "JUMP" +// }, +// { +// "name": "tag", +// "value": "1" +// }, +// { +// "name": "JUMPDEST" +// }, +// { +// "name": "PUSH", +// "value": "01" +// }, +// { +// "name": "JUMPI" +// }, +// { +// "name": "PUSH [tag]", +// "value": "0x012AB" +// }, +// { +// "name": "tag", +// "value": "0x012AB" +// }, +// { +// "name": "JUMPDEST" +// } +// ] +// } +// Assembly: +// jump(tag_1) +// tag_1: +// 0x01 +// jumpi +// tag_4779 +// tag_4779: +// Bytecode: 6003565b60015760095b +// Opcodes: PUSH1 0x3 JUMP JUMPDEST PUSH1 0x1 JUMPI PUSH1 0x9 JUMPDEST +// SourceMappings: :::-:0;;;;;; diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/operations.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/operations.asm new file mode 100644 index 000000000..923b0a6b1 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/operations.asm @@ -0,0 +1,53 @@ +NUMBER +SLOAD +ADDRESS +ORIGIN +ADD +DUP1 +SWAP1 +MSTORE8 +STOP +// ==== +// outputs: InputAssemblyJSON,Assembly,Bytecode,Opcodes,SourceMappings +// ---- +// InputAssemblyJSON: { +// ".code": [ +// { +// "name": "NUMBER" +// }, +// { +// "name": "SLOAD" +// }, +// { +// "name": "ADDRESS" +// }, +// { +// "name": "ORIGIN" +// }, +// { +// "name": "ADD" +// }, +// { +// "name": "DUP1" +// }, +// { +// "name": "SWAP1" +// }, +// { +// "name": "MSTORE8" +// }, +// { +// "name": "STOP" +// } +// ] +// } +// Assembly: +// sload(number) +// add(origin, address) +// dup1 +// swap1 +// mstore8 +// stop +// Bytecode: 435430320180905300 +// Opcodes: NUMBER SLOAD ADDRESS ORIGIN ADD DUP1 SWAP1 MSTORE8 STOP +// SourceMappings: :::-:0;;;;;;;; diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/push.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/push.asm new file mode 100644 index 000000000..51bc16050 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/push.asm @@ -0,0 +1,35 @@ +PUSH 0x0 +PUSH 0x1 +PUSH 0x0123456789ABCDEF +PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// ==== +// outputs: InputAssemblyJSON,Assembly,Bytecode,Opcodes,SourceMappings +// ---- +// InputAssemblyJSON: { +// ".code": [ +// { +// "name": "PUSH", +// "value": "0" +// }, +// { +// "name": "PUSH", +// "value": "1" +// }, +// { +// "name": "PUSH", +// "value": "0123456789ABCDEF" +// }, +// { +// "name": "PUSH", +// "value": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" +// } +// ] +// } +// Assembly: +// 0x00 +// 0x01 +// 0x0123456789abcdef +// 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// Bytecode: 5f6001670123456789abcdef7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// Opcodes: PUSH0 PUSH1 0x1 PUSH8 0x123456789ABCDEF PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +// SourceMappings: :::-:0;;; diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/smoke_plain.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/smoke_plain.asm new file mode 100644 index 000000000..a1714241f --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/smoke_plain.asm @@ -0,0 +1,16 @@ +CALLVALUE +// ==== +// outputs: InputAssemblyJSON,Assembly,Bytecode,Opcodes,SourceMappings +// ---- +// InputAssemblyJSON: { +// ".code": [ +// { +// "name": "CALLVALUE" +// } +// ] +// } +// Assembly: +// callvalue +// Bytecode: 34 +// Opcodes: CALLVALUE +// SourceMappings: :::-:0 diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 13018bf18..289f2f2de 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(isoltest ../TestCase.cpp ../TestCaseReader.cpp ../libevmasm/EVMAssemblyTest.cpp + ../libevmasm/PlainAssemblyParser.cpp ../libsolidity/util/BytesUtils.cpp ../libsolidity/util/Common.cpp ../libsolidity/util/ContractABIUtils.cpp diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index 32309b005..26efc0890 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -75,7 +75,7 @@ class TestFilter boost::replace_all(filter, "/", "\\/"); boost::replace_all(filter, "*", ".*"); - m_filterExpression = std::regex{"(" + filter + "(\\.sol|\\.yul|\\.asmjson|\\.stack))"}; + m_filterExpression = std::regex{"(" + filter + "(\\.sol|\\.yul|\\.asm|\\.asmjson|\\.stack))"}; } bool matches(fs::path const& _path, std::string const& _name) const From 975ee1325833c6784adff85072c55c3ecf9439fc Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 9 Apr 2025 15:30:26 +0200 Subject: [PATCH 0850/1340] eof: Enable peephole optimizer for EOF. --- libevmasm/Assembly.cpp | 3 +- libevmasm/AssemblyItem.h | 2 +- libevmasm/PeepholeOptimiser.cpp | 12 ++++-- test/Common.cpp | 7 ++++ test/Common.h | 4 ++ test/libevmasm/Optimiser.cpp | 40 +++++++++++++++++++ .../objectCompiler/eof/256_subcontainers.yul | 8 ++-- 7 files changed, 65 insertions(+), 11 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index a0711cd41..9dd203a0f 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -843,8 +843,7 @@ std::map const& Assembly::optimiseInternal( } } - // TODO: verify this for EOF. - if (_settings.runPeephole && !m_eofVersion.has_value()) + if (_settings.runPeephole) { for (auto& codeSection: m_codeSections) { diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 8b65d77c9..0dfe07497 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -244,7 +244,7 @@ class AssemblyItem /// Shortcut that avoids constructing an AssemblyItem just to perform the comparison. bool operator==(Instruction _instr) const { - return type() == Operation && instruction() == _instr; + return hasInstruction() && instruction() == _instr; } bool operator!=(Instruction _instr) const { return !operator==(_instr); } diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index cc22db9fa..267700e45 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -563,7 +563,9 @@ struct TruthyAnd: SimplePeepholeOptimizerMethod } }; -/// Removes everything after a JUMP (or similar) until the next JUMPDEST. +/// Removes everything after an non-continuing instruction until the next Tag. +/// Note: JUMPF can return but to the caller's parent call frame. +/// So it won't continue from the next to the JUMPF instruction struct UnreachableCode { static bool apply(OptimiserState& _state) @@ -572,14 +574,18 @@ struct UnreachableCode auto end = _state.items.end(); if (it == end) return false; + if ( it[0] != Instruction::JUMP && - it[0] != Instruction::RJUMP && it[0] != Instruction::RETURN && it[0] != Instruction::STOP && it[0] != Instruction::INVALID && it[0] != Instruction::SELFDESTRUCT && - it[0] != Instruction::REVERT + it[0] != Instruction::REVERT && + it[0] != Instruction::RJUMP && + it[0] != Instruction::JUMPF && + it[0] != Instruction::RETF && + it[0] != Instruction::RETURNCONTRACT ) return false; diff --git a/test/Common.cpp b/test/Common.cpp index d39c6db1e..142afda22 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -313,6 +313,13 @@ boost::unit_test::precondition::predicate_t nonEOF() }; } +boost::unit_test::precondition::predicate_t onEOF() +{ + return [](boost::unit_test::test_unit_id) { + return solidity::test::CommonOptions::get().eofVersion().has_value(); + }; +} + boost::unit_test::precondition::predicate_t minEVMVersionCheck(langutil::EVMVersion _minEVMVersion) { return [_minEVMVersion](boost::unit_test::test_unit_id) { diff --git a/test/Common.h b/test/Common.h index 27c208134..e331c497a 100644 --- a/test/Common.h +++ b/test/Common.h @@ -116,6 +116,10 @@ boost::unit_test::precondition::predicate_t minEVMVersionCheck(langutil::EVMVers /// @return A predicate (function) that can be passed into @a boost::unit_test::precondition(). boost::unit_test::precondition::predicate_t nonEOF(); +/// Helper that can be used to skip tests when the legacy bytecode is not supported by the test case. +/// @return A predicate (function) that can be passed into @a boost::unit_test::precondition(). +boost::unit_test::precondition::predicate_t onEOF(); + bool loadVMs(CommonOptions const& _options); /** diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index f4b7034de..4e344c174 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1009,6 +1009,46 @@ BOOST_AUTO_TEST_CASE(clear_unreachable_code) ); } +BOOST_AUTO_TEST_CASE(clear_unreachable_code_eof, *boost::unit_test::precondition(onEOF())) +{ + for (auto const& blockTerminatingItem: + { + AssemblyItem::relativeJumpTo(AssemblyItem(Tag, 1)), + AssemblyItem::jumpToFunction(1, 0, 0), + AssemblyItem::functionReturn(), + AssemblyItem::returnContract(0), + } + ) + { + AssemblyItems items{ + blockTerminatingItem, + u256(0), + Instruction::SLOAD, + AssemblyItem(Tag, 2), + u256(5), + u256(6), + Instruction::SSTORE, + blockTerminatingItem, + u256(5), + u256(6) + }; + AssemblyItems expectation{ + blockTerminatingItem, + AssemblyItem(Tag, 2), + u256(5), + u256(6), + Instruction::SSTORE, + blockTerminatingItem, + }; + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); + } +} + BOOST_AUTO_TEST_CASE(deduplicateNextTagBlockSize3) { AssemblyItems items{ diff --git a/test/libyul/objectCompiler/eof/256_subcontainers.yul b/test/libyul/objectCompiler/eof/256_subcontainers.yul index fac0f7b5d..9306dcbbd 100644 --- a/test/libyul/objectCompiler/eof/256_subcontainers.yul +++ b/test/libyul/objectCompiler/eof/256_subcontainers.yul @@ -2823,8 +2823,6 @@ object "a" { // dup1 // eofcreate{255} // /* "source":12286:12321 */ -// pop -// /* "source":22:12337 */ // stop // stop // @@ -4107,6 +4105,6 @@ object "a" { // /* "source":24612:24619 */ // stop // } -// Bytecode: ef00010100040200010701030100001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001404000000008000045f808080ec00505f808080ec01505f808080ec02505f808080ec03505f808080ec04505f808080ec05505f808080ec06505f808080ec07505f808080ec08505f808080ec09505f808080ec0a505f808080ec0b505f808080ec0c505f808080ec0d505f808080ec0e505f808080ec0f505f808080ec10505f808080ec11505f808080ec12505f808080ec13505f808080ec14505f808080ec15505f808080ec16505f808080ec17505f808080ec18505f808080ec19505f808080ec1a505f808080ec1b505f808080ec1c505f808080ec1d505f808080ec1e505f808080ec1f505f808080ec20505f808080ec21505f808080ec22505f808080ec23505f808080ec24505f808080ec25505f808080ec26505f808080ec27505f808080ec28505f808080ec29505f808080ec2a505f808080ec2b505f808080ec2c505f808080ec2d505f808080ec2e505f808080ec2f505f808080ec30505f808080ec31505f808080ec32505f808080ec33505f808080ec34505f808080ec35505f808080ec36505f808080ec37505f808080ec38505f808080ec39505f808080ec3a505f808080ec3b505f808080ec3c505f808080ec3d505f808080ec3e505f808080ec3f505f808080ec40505f808080ec41505f808080ec42505f808080ec43505f808080ec44505f808080ec45505f808080ec46505f808080ec47505f808080ec48505f808080ec49505f808080ec4a505f808080ec4b505f808080ec4c505f808080ec4d505f808080ec4e505f808080ec4f505f808080ec50505f808080ec51505f808080ec52505f808080ec53505f808080ec54505f808080ec55505f808080ec56505f808080ec57505f808080ec58505f808080ec59505f808080ec5a505f808080ec5b505f808080ec5c505f808080ec5d505f808080ec5e505f808080ec5f505f808080ec60505f808080ec61505f808080ec62505f808080ec63505f808080ec64505f808080ec65505f808080ec66505f808080ec67505f808080ec68505f808080ec69505f808080ec6a505f808080ec6b505f808080ec6c505f808080ec6d505f808080ec6e505f808080ec6f505f808080ec70505f808080ec71505f808080ec72505f808080ec73505f808080ec74505f808080ec75505f808080ec76505f808080ec77505f808080ec78505f808080ec79505f808080ec7a505f808080ec7b505f808080ec7c505f808080ec7d505f808080ec7e505f808080ec7f505f808080ec80505f808080ec81505f808080ec82505f808080ec83505f808080ec84505f808080ec85505f808080ec86505f808080ec87505f808080ec88505f808080ec89505f808080ec8a505f808080ec8b505f808080ec8c505f808080ec8d505f808080ec8e505f808080ec8f505f808080ec90505f808080ec91505f808080ec92505f808080ec93505f808080ec94505f808080ec95505f808080ec96505f808080ec97505f808080ec98505f808080ec99505f808080ec9a505f808080ec9b505f808080ec9c505f808080ec9d505f808080ec9e505f808080ec9f505f808080eca0505f808080eca1505f808080eca2505f808080eca3505f808080eca4505f808080eca5505f808080eca6505f808080eca7505f808080eca8505f808080eca9505f808080ecaa505f808080ecab505f808080ecac505f808080ecad505f808080ecae505f808080ecaf505f808080ecb0505f808080ecb1505f808080ecb2505f808080ecb3505f808080ecb4505f808080ecb5505f808080ecb6505f808080ecb7505f808080ecb8505f808080ecb9505f808080ecba505f808080ecbb505f808080ecbc505f808080ecbd505f808080ecbe505f808080ecbf505f808080ecc0505f808080ecc1505f808080ecc2505f808080ecc3505f808080ecc4505f808080ecc5505f808080ecc6505f808080ecc7505f808080ecc8505f808080ecc9505f808080ecca505f808080eccb505f808080eccc505f808080eccd505f808080ecce505f808080eccf505f808080ecd0505f808080ecd1505f808080ecd2505f808080ecd3505f808080ecd4505f808080ecd5505f808080ecd6505f808080ecd7505f808080ecd8505f808080ecd9505f808080ecda505f808080ecdb505f808080ecdc505f808080ecdd505f808080ecde505f808080ecdf505f808080ece0505f808080ece1505f808080ece2505f808080ece3505f808080ece4505f808080ece5505f808080ece6505f808080ece7505f808080ece8505f808080ece9505f808080ecea505f808080eceb505f808080ecec505f808080eced505f808080ecee505f808080ecef505f808080ecf0505f808080ecf1505f808080ecf2505f808080ecf3505f808080ecf4505f808080ecf5505f808080ecf6505f808080ecf7505f808080ecf8505f808080ecf9505f808080ecfa505f808080ecfb505f808080ecfc505f808080ecfd505f808080ecfe505f808080ecff5000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000 -// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD SMOD ADD SUB ADD STOP STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ DIV STOP STOP STOP STOP DUP1 STOP DIV PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x10 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x11 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x12 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x13 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x14 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x15 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x16 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x17 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x18 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x19 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x20 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x21 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x22 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x23 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x24 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x25 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x26 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x27 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x28 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x29 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x30 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x31 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x32 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x33 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x34 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x35 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x36 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x37 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x38 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x39 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x40 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x41 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x42 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x43 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x44 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x45 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x46 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x47 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x48 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x49 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x50 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x51 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x52 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x53 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x54 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x55 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x56 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x57 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x58 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x59 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x60 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x61 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x62 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x63 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x64 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x65 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x66 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x67 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x68 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x69 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x70 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x71 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x72 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x73 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x74 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x75 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x76 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x77 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x78 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x79 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x80 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x81 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x82 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x83 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x84 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x85 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x86 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x87 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x88 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x89 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x90 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x91 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x92 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x93 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x94 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x95 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x96 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x97 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x98 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x99 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xED POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFF POP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP -// SourceMappings: 78:1:0:-:0;50:30;;;;46:35;126:1;98:30;;;;94:35;174:1;146:30;;;;142:35;222:1;194:30;;;;190:35;270:1;242:30;;;;238:35;318:1;290:30;;;;286:35;366:1;338:30;;;;334:35;414:1;386:30;;;;382:35;462:1;434:30;;;;430:35;510:1;482:30;;;;478:35;558:1;530:30;;;;526:35;606:1;578:30;;;;574:35;654:1;626:30;;;;622:35;702:1;674:30;;;;670:35;750:1;722:30;;;;718:35;798:1;770:30;;;;766:35;846:1;818:30;;;;814:35;894:1;866:30;;;;862:35;942:1;914:30;;;;910:35;990:1;962:30;;;;958:35;1038:1;1010:30;;;;1006:35;1086:1;1058:30;;;;1054:35;1134:1;1106:30;;;;1102:35;1182:1;1154:30;;;;1150:35;1230:1;1202:30;;;;1198:35;1278:1;1250:30;;;;1246:35;1326:1;1298:30;;;;1294:35;1374:1;1346:30;;;;1342:35;1422:1;1394:30;;;;1390:35;1470:1;1442:30;;;;1438:35;1518:1;1490:30;;;;1486:35;1566:1;1538:30;;;;1534:35;1614:1;1586:30;;;;1582:35;1662:1;1634:30;;;;1630:35;1710:1;1682:30;;;;1678:35;1758:1;1730:30;;;;1726:35;1806:1;1778:30;;;;1774:35;1854:1;1826:30;;;;1822:35;1902:1;1874:30;;;;1870:35;1950:1;1922:30;;;;1918:35;1998:1;1970:30;;;;1966:35;2046:1;2018:30;;;;2014:35;2094:1;2066:30;;;;2062:35;2142:1;2114:30;;;;2110:35;2190:1;2162:30;;;;2158:35;2238:1;2210:30;;;;2206:35;2286:1;2258:30;;;;2254:35;2334:1;2306:30;;;;2302:35;2382:1;2354:30;;;;2350:35;2430:1;2402:30;;;;2398:35;2478:1;2450:30;;;;2446:35;2526:1;2498:30;;;;2494:35;2574:1;2546:30;;;;2542:35;2622:1;2594:30;;;;2590:35;2670:1;2642:30;;;;2638:35;2718:1;2690:30;;;;2686:35;2766:1;2738:30;;;;2734:35;2814:1;2786:30;;;;2782:35;2862:1;2834:30;;;;2830:35;2910:1;2882:30;;;;2878:35;2958:1;2930:30;;;;2926:35;3006:1;2978:30;;;;2974:35;3054:1;3026:30;;;;3022:35;3102:1;3074:30;;;;3070:35;3150:1;3122:30;;;;3118:35;3198:1;3170:30;;;;3166:35;3246:1;3218:30;;;;3214:35;3294:1;3266:30;;;;3262:35;3342:1;3314:30;;;;3310:35;3390:1;3362:30;;;;3358:35;3438:1;3410:30;;;;3406:35;3486:1;3458:30;;;;3454:35;3534:1;3506:30;;;;3502:35;3582:1;3554:30;;;;3550:35;3630:1;3602:30;;;;3598:35;3678:1;3650:30;;;;3646:35;3726:1;3698:30;;;;3694:35;3774:1;3746:30;;;;3742:35;3822:1;3794:30;;;;3790:35;3870:1;3842:30;;;;3838:35;3918:1;3890:30;;;;3886:35;3966:1;3938:30;;;;3934:35;4014:1;3986:30;;;;3982:35;4062:1;4034:30;;;;4030:35;4110:1;4082:30;;;;4078:35;4158:1;4130:30;;;;4126:35;4206:1;4178:30;;;;4174:35;4254:1;4226:30;;;;4222:35;4302:1;4274:30;;;;4270:35;4350:1;4322:30;;;;4318:35;4398:1;4370:30;;;;4366:35;4446:1;4418:30;;;;4414:35;4494:1;4466:30;;;;4462:35;4542:1;4514:30;;;;4510:35;4590:1;4562:30;;;;4558:35;4638:1;4610:30;;;;4606:35;4686:1;4658:30;;;;4654:35;4734:1;4706:30;;;;4702:35;4782:1;4754:30;;;;4750:35;4830:1;4802:30;;;;4798:35;4878:1;4850:30;;;;4846:35;4926:1;4898:30;;;;4894:35;4974:1;4946:30;;;;4942:35;5022:1;4994:30;;;;4990:35;5070:1;5042:30;;;;5038:35;5118:1;5090:30;;;;5086:35;5166:1;5138:30;;;;5134:35;5214:1;5186:30;;;;5182:35;5262:1;5234:30;;;;5230:35;5310:1;5282:30;;;;5278:35;5358:1;5330:30;;;;5326:35;5406:1;5378:30;;;;5374:35;5454:1;5426:30;;;;5422:35;5502:1;5474:30;;;;5470:35;5550:1;5522:30;;;;5518:35;5598:1;5570:30;;;;5566:35;5646:1;5618:30;;;;5614:35;5694:1;5666:30;;;;5662:35;5742:1;5714:30;;;;5710:35;5790:1;5762:30;;;;5758:35;5838:1;5810:30;;;;5806:35;5886:1;5858:30;;;;5854:35;5934:1;5906:30;;;;5902:35;5982:1;5954:30;;;;5950:35;6030:1;6002:30;;;;5998:35;6078:1;6050:30;;;;6046:35;6126:1;6098:30;;;;6094:35;6174:1;6146:30;;;;6142:35;6222:1;6194:30;;;;6190:35;6270:1;6242:30;;;;6238:35;6318:1;6290:30;;;;6286:35;6366:1;6338:30;;;;6334:35;6414:1;6386:30;;;;6382:35;6462:1;6434:30;;;;6430:35;6510:1;6482:30;;;;6478:35;6558:1;6530:30;;;;6526:35;6606:1;6578:30;;;;6574:35;6654:1;6626:30;;;;6622:35;6702:1;6674:30;;;;6670:35;6750:1;6722:30;;;;6718:35;6798:1;6770:30;;;;6766:35;6846:1;6818:30;;;;6814:35;6894:1;6866:30;;;;6862:35;6942:1;6914:30;;;;6910:35;6990:1;6962:30;;;;6958:35;7038:1;7010:30;;;;7006:35;7086:1;7058:30;;;;7054:35;7134:1;7106:30;;;;7102:35;7182:1;7154:30;;;;7150:35;7230:1;7202:30;;;;7198:35;7278:1;7250:30;;;;7246:35;7326:1;7298:30;;;;7294:35;7374:1;7346:30;;;;7342:35;7422:1;7394:30;;;;7390:35;7470:1;7442:30;;;;7438:35;7518:1;7490:30;;;;7486:35;7566:1;7538:30;;;;7534:35;7614:1;7586:30;;;;7582:35;7662:1;7634:30;;;;7630:35;7710:1;7682:30;;;;7678:35;7758:1;7730:30;;;;7726:35;7806:1;7778:30;;;;7774:35;7854:1;7826:30;;;;7822:35;7902:1;7874:30;;;;7870:35;7950:1;7922:30;;;;7918:35;7998:1;7970:30;;;;7966:35;8046:1;8018:30;;;;8014:35;8094:1;8066:30;;;;8062:35;8142:1;8114:30;;;;8110:35;8190:1;8162:30;;;;8158:35;8238:1;8210:30;;;;8206:35;8286:1;8258:30;;;;8254:35;8334:1;8306:30;;;;8302:35;8382:1;8354:30;;;;8350:35;8430:1;8402:30;;;;8398:35;8478:1;8450:30;;;;8446:35;8526:1;8498:30;;;;8494:35;8574:1;8546:30;;;;8542:35;8622:1;8594:30;;;;8590:35;8670:1;8642:30;;;;8638:35;8718:1;8690:30;;;;8686:35;8766:1;8738:30;;;;8734:35;8814:1;8786:30;;;;8782:35;8862:1;8834:30;;;;8830:35;8910:1;8882:30;;;;8878:35;8958:1;8930:30;;;;8926:35;9006:1;8978:30;;;;8974:35;9054:1;9026:30;;;;9022:35;9102:1;9074:30;;;;9070:35;9150:1;9122:30;;;;9118:35;9198:1;9170:30;;;;9166:35;9246:1;9218:30;;;;9214:35;9294:1;9266:30;;;;9262:35;9342:1;9314:30;;;;9310:35;9390:1;9362:30;;;;9358:35;9438:1;9410:30;;;;9406:35;9486:1;9458:30;;;;9454:35;9534:1;9506:30;;;;9502:35;9582:1;9554:30;;;;9550:35;9630:1;9602:30;;;;9598:35;9678:1;9650:30;;;;9646:35;9726:1;9698:30;;;;9694:35;9774:1;9746:30;;;;9742:35;9822:1;9794:30;;;;9790:35;9870:1;9842:30;;;;9838:35;9918:1;9890:30;;;;9886:35;9966:1;9938:30;;;;9934:35;10014:1;9986:30;;;;9982:35;10062:1;10034:30;;;;10030:35;10110:1;10082:30;;;;10078:35;10158:1;10130:30;;;;10126:35;10206:1;10178:30;;;;10174:35;10254:1;10226:30;;;;10222:35;10302:1;10274:30;;;;10270:35;10350:1;10322:30;;;;10318:35;10398:1;10370:30;;;;10366:35;10446:1;10418:30;;;;10414:35;10494:1;10466:30;;;;10462:35;10542:1;10514:30;;;;10510:35;10590:1;10562:30;;;;10558:35;10638:1;10610:30;;;;10606:35;10686:1;10658:30;;;;10654:35;10734:1;10706:30;;;;10702:35;10782:1;10754:30;;;;10750:35;10830:1;10802:30;;;;10798:35;10878:1;10850:30;;;;10846:35;10926:1;10898:30;;;;10894:35;10974:1;10946:30;;;;10942:35;11022:1;10994:30;;;;10990:35;11070:1;11042:30;;;;11038:35;11118:1;11090:30;;;;11086:35;11166:1;11138:30;;;;11134:35;11214:1;11186:30;;;;11182:35;11262:1;11234:30;;;;11230:35;11310:1;11282:30;;;;11278:35;11358:1;11330:30;;;;11326:35;11406:1;11378:30;;;;11374:35;11454:1;11426:30;;;;11422:35;11502:1;11474:30;;;;11470:35;11550:1;11522:30;;;;11518:35;11598:1;11570:30;;;;11566:35;11646:1;11618:30;;;;11614:35;11694:1;11666:30;;;;11662:35;11742:1;11714:30;;;;11710:35;11790:1;11762:30;;;;11758:35;11838:1;11810:30;;;;11806:35;11886:1;11858:30;;;;11854:35;11934:1;11906:30;;;;11902:35;11982:1;11954:30;;;;11950:35;12030:1;12002:30;;;;11998:35;12078:1;12050:30;;;;12046:35;12126:1;12098:30;;;;12094:35;12174:1;12146:30;;;;12142:35;12222:1;12194:30;;;;12190:35;12270:1;12242:30;;;;12238:35;12318:1;12290:30;;;;12286:35;22:12315 +// Bytecode: ef00010100040200010700030100001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001400140014001404000000008000045f808080ec00505f808080ec01505f808080ec02505f808080ec03505f808080ec04505f808080ec05505f808080ec06505f808080ec07505f808080ec08505f808080ec09505f808080ec0a505f808080ec0b505f808080ec0c505f808080ec0d505f808080ec0e505f808080ec0f505f808080ec10505f808080ec11505f808080ec12505f808080ec13505f808080ec14505f808080ec15505f808080ec16505f808080ec17505f808080ec18505f808080ec19505f808080ec1a505f808080ec1b505f808080ec1c505f808080ec1d505f808080ec1e505f808080ec1f505f808080ec20505f808080ec21505f808080ec22505f808080ec23505f808080ec24505f808080ec25505f808080ec26505f808080ec27505f808080ec28505f808080ec29505f808080ec2a505f808080ec2b505f808080ec2c505f808080ec2d505f808080ec2e505f808080ec2f505f808080ec30505f808080ec31505f808080ec32505f808080ec33505f808080ec34505f808080ec35505f808080ec36505f808080ec37505f808080ec38505f808080ec39505f808080ec3a505f808080ec3b505f808080ec3c505f808080ec3d505f808080ec3e505f808080ec3f505f808080ec40505f808080ec41505f808080ec42505f808080ec43505f808080ec44505f808080ec45505f808080ec46505f808080ec47505f808080ec48505f808080ec49505f808080ec4a505f808080ec4b505f808080ec4c505f808080ec4d505f808080ec4e505f808080ec4f505f808080ec50505f808080ec51505f808080ec52505f808080ec53505f808080ec54505f808080ec55505f808080ec56505f808080ec57505f808080ec58505f808080ec59505f808080ec5a505f808080ec5b505f808080ec5c505f808080ec5d505f808080ec5e505f808080ec5f505f808080ec60505f808080ec61505f808080ec62505f808080ec63505f808080ec64505f808080ec65505f808080ec66505f808080ec67505f808080ec68505f808080ec69505f808080ec6a505f808080ec6b505f808080ec6c505f808080ec6d505f808080ec6e505f808080ec6f505f808080ec70505f808080ec71505f808080ec72505f808080ec73505f808080ec74505f808080ec75505f808080ec76505f808080ec77505f808080ec78505f808080ec79505f808080ec7a505f808080ec7b505f808080ec7c505f808080ec7d505f808080ec7e505f808080ec7f505f808080ec80505f808080ec81505f808080ec82505f808080ec83505f808080ec84505f808080ec85505f808080ec86505f808080ec87505f808080ec88505f808080ec89505f808080ec8a505f808080ec8b505f808080ec8c505f808080ec8d505f808080ec8e505f808080ec8f505f808080ec90505f808080ec91505f808080ec92505f808080ec93505f808080ec94505f808080ec95505f808080ec96505f808080ec97505f808080ec98505f808080ec99505f808080ec9a505f808080ec9b505f808080ec9c505f808080ec9d505f808080ec9e505f808080ec9f505f808080eca0505f808080eca1505f808080eca2505f808080eca3505f808080eca4505f808080eca5505f808080eca6505f808080eca7505f808080eca8505f808080eca9505f808080ecaa505f808080ecab505f808080ecac505f808080ecad505f808080ecae505f808080ecaf505f808080ecb0505f808080ecb1505f808080ecb2505f808080ecb3505f808080ecb4505f808080ecb5505f808080ecb6505f808080ecb7505f808080ecb8505f808080ecb9505f808080ecba505f808080ecbb505f808080ecbc505f808080ecbd505f808080ecbe505f808080ecbf505f808080ecc0505f808080ecc1505f808080ecc2505f808080ecc3505f808080ecc4505f808080ecc5505f808080ecc6505f808080ecc7505f808080ecc8505f808080ecc9505f808080ecca505f808080eccb505f808080eccc505f808080eccd505f808080ecce505f808080eccf505f808080ecd0505f808080ecd1505f808080ecd2505f808080ecd3505f808080ecd4505f808080ecd5505f808080ecd6505f808080ecd7505f808080ecd8505f808080ecd9505f808080ecda505f808080ecdb505f808080ecdc505f808080ecdd505f808080ecde505f808080ecdf505f808080ece0505f808080ece1505f808080ece2505f808080ece3505f808080ece4505f808080ece5505f808080ece6505f808080ece7505f808080ece8505f808080ece9505f808080ecea505f808080eceb505f808080ecec505f808080eced505f808080ecee505f808080ecef505f808080ecf0505f808080ecf1505f808080ecf2505f808080ecf3505f808080ecf4505f808080ecf5505f808080ecf6505f808080ecf7505f808080ecf8505f808080ecf9505f808080ecfa505f808080ecfb505f808080ecfc505f808080ecfd505f808080ecfe505f808080ecff00ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000ef00010100040200010001040000000080000000 +// Opcodes: 0xEF STOP ADD ADD STOP DIV MUL STOP ADD SMOD STOP SUB ADD STOP STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ STOP EQ DIV STOP STOP STOP STOP DUP1 STOP DIV PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x10 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x11 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x12 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x13 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x14 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x15 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x16 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x17 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x18 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x19 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x1F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x20 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x21 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x22 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x23 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x24 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x25 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x26 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x27 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x28 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x29 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x2F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x30 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x31 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x32 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x33 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x34 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x35 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x36 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x37 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x38 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x39 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x3F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x40 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x41 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x42 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x43 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x44 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x45 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x46 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x47 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x48 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x49 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x4F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x50 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x51 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x52 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x53 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x54 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x55 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x56 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x57 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x58 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x59 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x5F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x60 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x61 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x62 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x63 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x64 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x65 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x66 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x67 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x68 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x69 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x6F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x70 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x71 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x72 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x73 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x74 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x75 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x76 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x77 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x78 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x79 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x7F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x80 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x81 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x82 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x83 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x84 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x85 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x86 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x87 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x88 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x89 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x8F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x90 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x91 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x92 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x93 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x94 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x95 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x96 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x97 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x98 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x99 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9A POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9B POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9C POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9D POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9E POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0x9F POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xA9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xAF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xB9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xBF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xC9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xCF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xD9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xDF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xE9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xED POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xEF POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF0 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF1 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF2 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF3 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF4 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF5 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF6 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF7 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF8 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xF9 POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFA POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFB POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFC POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFD POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFE POP PUSH0 DUP1 DUP1 DUP1 EOFCREATE 0xFF STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP 0xEF STOP ADD ADD STOP DIV MUL STOP ADD STOP ADD DIV STOP STOP STOP STOP DUP1 STOP STOP STOP +// SourceMappings: 78:1:0:-:0;50:30;;;;46:35;126:1;98:30;;;;94:35;174:1;146:30;;;;142:35;222:1;194:30;;;;190:35;270:1;242:30;;;;238:35;318:1;290:30;;;;286:35;366:1;338:30;;;;334:35;414:1;386:30;;;;382:35;462:1;434:30;;;;430:35;510:1;482:30;;;;478:35;558:1;530:30;;;;526:35;606:1;578:30;;;;574:35;654:1;626:30;;;;622:35;702:1;674:30;;;;670:35;750:1;722:30;;;;718:35;798:1;770:30;;;;766:35;846:1;818:30;;;;814:35;894:1;866:30;;;;862:35;942:1;914:30;;;;910:35;990:1;962:30;;;;958:35;1038:1;1010:30;;;;1006:35;1086:1;1058:30;;;;1054:35;1134:1;1106:30;;;;1102:35;1182:1;1154:30;;;;1150:35;1230:1;1202:30;;;;1198:35;1278:1;1250:30;;;;1246:35;1326:1;1298:30;;;;1294:35;1374:1;1346:30;;;;1342:35;1422:1;1394:30;;;;1390:35;1470:1;1442:30;;;;1438:35;1518:1;1490:30;;;;1486:35;1566:1;1538:30;;;;1534:35;1614:1;1586:30;;;;1582:35;1662:1;1634:30;;;;1630:35;1710:1;1682:30;;;;1678:35;1758:1;1730:30;;;;1726:35;1806:1;1778:30;;;;1774:35;1854:1;1826:30;;;;1822:35;1902:1;1874:30;;;;1870:35;1950:1;1922:30;;;;1918:35;1998:1;1970:30;;;;1966:35;2046:1;2018:30;;;;2014:35;2094:1;2066:30;;;;2062:35;2142:1;2114:30;;;;2110:35;2190:1;2162:30;;;;2158:35;2238:1;2210:30;;;;2206:35;2286:1;2258:30;;;;2254:35;2334:1;2306:30;;;;2302:35;2382:1;2354:30;;;;2350:35;2430:1;2402:30;;;;2398:35;2478:1;2450:30;;;;2446:35;2526:1;2498:30;;;;2494:35;2574:1;2546:30;;;;2542:35;2622:1;2594:30;;;;2590:35;2670:1;2642:30;;;;2638:35;2718:1;2690:30;;;;2686:35;2766:1;2738:30;;;;2734:35;2814:1;2786:30;;;;2782:35;2862:1;2834:30;;;;2830:35;2910:1;2882:30;;;;2878:35;2958:1;2930:30;;;;2926:35;3006:1;2978:30;;;;2974:35;3054:1;3026:30;;;;3022:35;3102:1;3074:30;;;;3070:35;3150:1;3122:30;;;;3118:35;3198:1;3170:30;;;;3166:35;3246:1;3218:30;;;;3214:35;3294:1;3266:30;;;;3262:35;3342:1;3314:30;;;;3310:35;3390:1;3362:30;;;;3358:35;3438:1;3410:30;;;;3406:35;3486:1;3458:30;;;;3454:35;3534:1;3506:30;;;;3502:35;3582:1;3554:30;;;;3550:35;3630:1;3602:30;;;;3598:35;3678:1;3650:30;;;;3646:35;3726:1;3698:30;;;;3694:35;3774:1;3746:30;;;;3742:35;3822:1;3794:30;;;;3790:35;3870:1;3842:30;;;;3838:35;3918:1;3890:30;;;;3886:35;3966:1;3938:30;;;;3934:35;4014:1;3986:30;;;;3982:35;4062:1;4034:30;;;;4030:35;4110:1;4082:30;;;;4078:35;4158:1;4130:30;;;;4126:35;4206:1;4178:30;;;;4174:35;4254:1;4226:30;;;;4222:35;4302:1;4274:30;;;;4270:35;4350:1;4322:30;;;;4318:35;4398:1;4370:30;;;;4366:35;4446:1;4418:30;;;;4414:35;4494:1;4466:30;;;;4462:35;4542:1;4514:30;;;;4510:35;4590:1;4562:30;;;;4558:35;4638:1;4610:30;;;;4606:35;4686:1;4658:30;;;;4654:35;4734:1;4706:30;;;;4702:35;4782:1;4754:30;;;;4750:35;4830:1;4802:30;;;;4798:35;4878:1;4850:30;;;;4846:35;4926:1;4898:30;;;;4894:35;4974:1;4946:30;;;;4942:35;5022:1;4994:30;;;;4990:35;5070:1;5042:30;;;;5038:35;5118:1;5090:30;;;;5086:35;5166:1;5138:30;;;;5134:35;5214:1;5186:30;;;;5182:35;5262:1;5234:30;;;;5230:35;5310:1;5282:30;;;;5278:35;5358:1;5330:30;;;;5326:35;5406:1;5378:30;;;;5374:35;5454:1;5426:30;;;;5422:35;5502:1;5474:30;;;;5470:35;5550:1;5522:30;;;;5518:35;5598:1;5570:30;;;;5566:35;5646:1;5618:30;;;;5614:35;5694:1;5666:30;;;;5662:35;5742:1;5714:30;;;;5710:35;5790:1;5762:30;;;;5758:35;5838:1;5810:30;;;;5806:35;5886:1;5858:30;;;;5854:35;5934:1;5906:30;;;;5902:35;5982:1;5954:30;;;;5950:35;6030:1;6002:30;;;;5998:35;6078:1;6050:30;;;;6046:35;6126:1;6098:30;;;;6094:35;6174:1;6146:30;;;;6142:35;6222:1;6194:30;;;;6190:35;6270:1;6242:30;;;;6238:35;6318:1;6290:30;;;;6286:35;6366:1;6338:30;;;;6334:35;6414:1;6386:30;;;;6382:35;6462:1;6434:30;;;;6430:35;6510:1;6482:30;;;;6478:35;6558:1;6530:30;;;;6526:35;6606:1;6578:30;;;;6574:35;6654:1;6626:30;;;;6622:35;6702:1;6674:30;;;;6670:35;6750:1;6722:30;;;;6718:35;6798:1;6770:30;;;;6766:35;6846:1;6818:30;;;;6814:35;6894:1;6866:30;;;;6862:35;6942:1;6914:30;;;;6910:35;6990:1;6962:30;;;;6958:35;7038:1;7010:30;;;;7006:35;7086:1;7058:30;;;;7054:35;7134:1;7106:30;;;;7102:35;7182:1;7154:30;;;;7150:35;7230:1;7202:30;;;;7198:35;7278:1;7250:30;;;;7246:35;7326:1;7298:30;;;;7294:35;7374:1;7346:30;;;;7342:35;7422:1;7394:30;;;;7390:35;7470:1;7442:30;;;;7438:35;7518:1;7490:30;;;;7486:35;7566:1;7538:30;;;;7534:35;7614:1;7586:30;;;;7582:35;7662:1;7634:30;;;;7630:35;7710:1;7682:30;;;;7678:35;7758:1;7730:30;;;;7726:35;7806:1;7778:30;;;;7774:35;7854:1;7826:30;;;;7822:35;7902:1;7874:30;;;;7870:35;7950:1;7922:30;;;;7918:35;7998:1;7970:30;;;;7966:35;8046:1;8018:30;;;;8014:35;8094:1;8066:30;;;;8062:35;8142:1;8114:30;;;;8110:35;8190:1;8162:30;;;;8158:35;8238:1;8210:30;;;;8206:35;8286:1;8258:30;;;;8254:35;8334:1;8306:30;;;;8302:35;8382:1;8354:30;;;;8350:35;8430:1;8402:30;;;;8398:35;8478:1;8450:30;;;;8446:35;8526:1;8498:30;;;;8494:35;8574:1;8546:30;;;;8542:35;8622:1;8594:30;;;;8590:35;8670:1;8642:30;;;;8638:35;8718:1;8690:30;;;;8686:35;8766:1;8738:30;;;;8734:35;8814:1;8786:30;;;;8782:35;8862:1;8834:30;;;;8830:35;8910:1;8882:30;;;;8878:35;8958:1;8930:30;;;;8926:35;9006:1;8978:30;;;;8974:35;9054:1;9026:30;;;;9022:35;9102:1;9074:30;;;;9070:35;9150:1;9122:30;;;;9118:35;9198:1;9170:30;;;;9166:35;9246:1;9218:30;;;;9214:35;9294:1;9266:30;;;;9262:35;9342:1;9314:30;;;;9310:35;9390:1;9362:30;;;;9358:35;9438:1;9410:30;;;;9406:35;9486:1;9458:30;;;;9454:35;9534:1;9506:30;;;;9502:35;9582:1;9554:30;;;;9550:35;9630:1;9602:30;;;;9598:35;9678:1;9650:30;;;;9646:35;9726:1;9698:30;;;;9694:35;9774:1;9746:30;;;;9742:35;9822:1;9794:30;;;;9790:35;9870:1;9842:30;;;;9838:35;9918:1;9890:30;;;;9886:35;9966:1;9938:30;;;;9934:35;10014:1;9986:30;;;;9982:35;10062:1;10034:30;;;;10030:35;10110:1;10082:30;;;;10078:35;10158:1;10130:30;;;;10126:35;10206:1;10178:30;;;;10174:35;10254:1;10226:30;;;;10222:35;10302:1;10274:30;;;;10270:35;10350:1;10322:30;;;;10318:35;10398:1;10370:30;;;;10366:35;10446:1;10418:30;;;;10414:35;10494:1;10466:30;;;;10462:35;10542:1;10514:30;;;;10510:35;10590:1;10562:30;;;;10558:35;10638:1;10610:30;;;;10606:35;10686:1;10658:30;;;;10654:35;10734:1;10706:30;;;;10702:35;10782:1;10754:30;;;;10750:35;10830:1;10802:30;;;;10798:35;10878:1;10850:30;;;;10846:35;10926:1;10898:30;;;;10894:35;10974:1;10946:30;;;;10942:35;11022:1;10994:30;;;;10990:35;11070:1;11042:30;;;;11038:35;11118:1;11090:30;;;;11086:35;11166:1;11138:30;;;;11134:35;11214:1;11186:30;;;;11182:35;11262:1;11234:30;;;;11230:35;11310:1;11282:30;;;;11278:35;11358:1;11330:30;;;;11326:35;11406:1;11378:30;;;;11374:35;11454:1;11426:30;;;;11422:35;11502:1;11474:30;;;;11470:35;11550:1;11522:30;;;;11518:35;11598:1;11570:30;;;;11566:35;11646:1;11618:30;;;;11614:35;11694:1;11666:30;;;;11662:35;11742:1;11714:30;;;;11710:35;11790:1;11762:30;;;;11758:35;11838:1;11810:30;;;;11806:35;11886:1;11858:30;;;;11854:35;11934:1;11906:30;;;;11902:35;11982:1;11954:30;;;;11950:35;12030:1;12002:30;;;;11998:35;12078:1;12050:30;;;;12046:35;12126:1;12098:30;;;;12094:35;12174:1;12146:30;;;;12142:35;12222:1;12194:30;;;;12190:35;12270:1;12242:30;;;;12238:35;12318:1;12290:30;;;;12286:35 From 03fde2ae36f3a306d14788c175c649d508d6ed42 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 23 Apr 2025 12:27:48 +0200 Subject: [PATCH 0851/1340] eof: Add peephole optimiser tests for EOF specific optimisations --- test/libevmasm/Optimiser.cpp | 136 +++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 4e344c174..b53205e95 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1049,6 +1049,142 @@ BOOST_AUTO_TEST_CASE(clear_unreachable_code_eof, *boost::unit_test::precondition } } +BOOST_AUTO_TEST_CASE(is_zero_is_zero_rjumpi, *boost::unit_test::precondition(onEOF())) +{ + AssemblyItems items{ + u256(1), + Instruction::ISZERO, + Instruction::ISZERO, + AssemblyItem::conditionalRelativeJumpTo(AssemblyItem(Tag, 1)), + u256(0), + Instruction::SLOAD, + AssemblyItem(Tag, 1), + }; + + AssemblyItems expectation{ + u256(1), + AssemblyItem::conditionalRelativeJumpTo(AssemblyItem(Tag, 1)), + u256(0), + Instruction::SLOAD, + AssemblyItem(Tag, 1), + }; + + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + +BOOST_AUTO_TEST_CASE(equal_is_zero_rjumpi, *boost::unit_test::precondition(onEOF())) +{ + AssemblyItems items{ + u256(1), + u256(2), + Instruction::EQ, + Instruction::ISZERO, + AssemblyItem::conditionalRelativeJumpTo(AssemblyItem(Tag, 1)), + u256(0), + Instruction::SLOAD, + AssemblyItem(Tag, 1), + }; + + AssemblyItems expectation{ + u256(1), + u256(2), + Instruction::SUB, + AssemblyItem::conditionalRelativeJumpTo(AssemblyItem(Tag, 1)), + u256(0), + Instruction::SLOAD, + AssemblyItem(Tag, 1), + }; + + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + +BOOST_AUTO_TEST_CASE(double_rjump, *boost::unit_test::precondition(onEOF())) +{ + AssemblyItems items{ + u256(1), + AssemblyItem::conditionalRelativeJumpTo(AssemblyItem(Tag, 1)), + AssemblyItem::relativeJumpTo(AssemblyItem(Tag, 2)), + AssemblyItem(Tag, 1), + u256(0), + Instruction::SLOAD, + AssemblyItem(Tag, 2), + }; + + AssemblyItems expectation{ + u256(1), + Instruction::ISZERO, + AssemblyItem::conditionalRelativeJumpTo(AssemblyItem(Tag, 2)), + AssemblyItem(Tag, 1), + u256(0), + Instruction::SLOAD, + AssemblyItem(Tag, 2), + }; + + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + +BOOST_AUTO_TEST_CASE(rjump_to_next, *boost::unit_test::precondition(onEOF())) +{ + AssemblyItems items{ + AssemblyItem::relativeJumpTo(AssemblyItem(Tag, 1)), + AssemblyItem(Tag, 1), + u256(0), + Instruction::SLOAD, + }; + + AssemblyItems expectation{ + AssemblyItem(Tag, 1), + u256(0), + Instruction::SLOAD, + }; + + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + +BOOST_AUTO_TEST_CASE(rjumpi_to_next, *boost::unit_test::precondition(onEOF())) +{ + AssemblyItems items{ + AssemblyItem::conditionalRelativeJumpTo(AssemblyItem(Tag, 1)), + AssemblyItem(Tag, 1), + u256(0), + Instruction::SLOAD, + }; + + AssemblyItems expectation{ + Instruction::POP, + AssemblyItem(Tag, 1), + u256(0), + Instruction::SLOAD, + }; + + PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion()); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + BOOST_AUTO_TEST_CASE(deduplicateNextTagBlockSize3) { AssemblyItems items{ From 649c8ee32826476600f67e2f879859563c92dc00 Mon Sep 17 00:00:00 2001 From: Maximilian Hubert <64627729+gap-editor@users.noreply.github.com> Date: Sat, 26 Apr 2025 17:40:13 +0200 Subject: [PATCH 0852/1340] Update SMTPortfolio.cpp --- libsmtutil/SMTPortfolio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsmtutil/SMTPortfolio.cpp b/libsmtutil/SMTPortfolio.cpp index 94c92f390..e6f6e9913 100644 --- a/libsmtutil/SMTPortfolio.cpp +++ b/libsmtutil/SMTPortfolio.cpp @@ -78,7 +78,7 @@ void SMTPortfolio::addAssertion(Expression const& _expr) * Ideally all solvers answer the query and agree on what the answer is * (all say SAT or all say UNSAT). * - * The actual logic as as follows: + * The actual logic as follows: * 1) If at least one solver answers the query, all the non-answer results are ignored. * Here SAT/UNSAT is preferred over UNKNOWN since it's an actual answer, and over ERROR * because one buggy solver/integration shouldn't break the portfolio. From 76e80168f10e560f159309edf3448f48fb80dc0e Mon Sep 17 00:00:00 2001 From: Maximilian Hubert <64627729+gap-editor@users.noreply.github.com> Date: Mon, 28 Apr 2025 11:27:07 +0200 Subject: [PATCH 0853/1340] Update SMTPortfolio.cpp --- libsmtutil/SMTPortfolio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsmtutil/SMTPortfolio.cpp b/libsmtutil/SMTPortfolio.cpp index e6f6e9913..fb82f3c69 100644 --- a/libsmtutil/SMTPortfolio.cpp +++ b/libsmtutil/SMTPortfolio.cpp @@ -78,7 +78,7 @@ void SMTPortfolio::addAssertion(Expression const& _expr) * Ideally all solvers answer the query and agree on what the answer is * (all say SAT or all say UNSAT). * - * The actual logic as follows: + * The actual logic is as follows: * 1) If at least one solver answers the query, all the non-answer results are ignored. * Here SAT/UNSAT is preferred over UNKNOWN since it's an actual answer, and over ERROR * because one buggy solver/integration shouldn't break the portfolio. From cc78330e3ad84767014f6fead28bf3a6b53e55f7 Mon Sep 17 00:00:00 2001 From: Afounso Souza Date: Sun, 4 May 2025 22:29:19 +0200 Subject: [PATCH 0854/1340] Update Types.cpp --- libsolidity/ast/Types.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 02df22dd5..f5c83b0cf 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1648,7 +1648,7 @@ BoolResult ArrayType::isImplicitlyConvertibleTo(Type const& _convertTo) const } else { - // Conversion to storage pointer or to memory, we de not copy element-for-element here, so + // Conversion to storage pointer or to memory, we do not copy element-for-element here, so // require that the base type is the same, not only convertible. // This disallows assignment of nested dynamic arrays from storage to memory for now. if ( From 09fc1d4a21504a9cfd0c645a7754015c18933eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 25 Apr 2025 06:10:31 +0200 Subject: [PATCH 0855/1340] PlainAssemblyParser: Store the stream globally in the class --- test/libevmasm/PlainAssemblyParser.cpp | 37 +++++++++++++++++++------- test/libevmasm/PlainAssemblyParser.h | 14 +++++----- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/test/libevmasm/PlainAssemblyParser.cpp b/test/libevmasm/PlainAssemblyParser.cpp index 0fb9d62c8..4d09043b1 100644 --- a/test/libevmasm/PlainAssemblyParser.cpp +++ b/test/libevmasm/PlainAssemblyParser.cpp @@ -28,8 +28,6 @@ #include -#include - using namespace std::string_literals; using namespace solidity; using namespace solidity::test; @@ -39,15 +37,21 @@ using namespace solidity::langutil; Json PlainAssemblyParser::parse(std::string _sourceName, std::string const& _source) { + m_sourceStream = std::istringstream(_source); m_sourceName = std::move(_sourceName); Json codeJSON = Json::array(); - std::istringstream sourceStream(_source); - while (getline(sourceStream, m_line)) + m_lineNumber = 0; + + if (!m_line.has_value()) + advanceLine(); + + while (m_line.has_value()) { - advanceLine(m_line); if (m_lineTokens.empty()) + { + advanceLine(); continue; - + } if (c_instructions.contains(currentToken().value)) { expectNoMoreArguments(); @@ -84,6 +88,8 @@ Json PlainAssemblyParser::parse(std::string _sourceName, std::string const& _sou } else BOOST_THROW_EXCEPTION(std::runtime_error(formatError("Unknown instruction."))); + + advanceLine(); } return {{".code", codeJSON}}; } @@ -125,12 +131,20 @@ void PlainAssemblyParser::expectNoMoreArguments() BOOST_THROW_EXCEPTION(std::runtime_error(formatError("Too many arguments."))); } -void PlainAssemblyParser::advanceLine(std::string_view _line) +bool PlainAssemblyParser::advanceLine() { + std::string line; + if (!getline(m_sourceStream, line)) + { + m_line = std::nullopt; + return false; + } + ++m_lineNumber; - m_line = _line; - m_lineTokens = tokenizeLine(m_line); + m_line = std::move(line); + m_lineTokens = tokenizeLine(*m_line); m_tokenIndex = 0; + return true; } std::vector PlainAssemblyParser::tokenizeLine(std::string_view _line) @@ -162,6 +176,9 @@ std::vector PlainAssemblyParser::tokenizeLine(std::s std::string PlainAssemblyParser::formatError(std::string_view _message) const { + soltestAssert(m_line.has_value()); + soltestAssert(!m_lineTokens.empty()); + std::string lineNumberString = std::to_string(m_lineNumber); std::string padding(lineNumberString.size(), ' '); std::string underline = std::string(currentToken().position, ' ') + std::string(currentToken().value.size(), '^'); @@ -174,7 +191,7 @@ std::string PlainAssemblyParser::formatError(std::string_view _message) const _message, padding, m_sourceName, padding, - m_lineNumber, m_line, + m_lineNumber, *m_line, padding, underline ); } diff --git a/test/libevmasm/PlainAssemblyParser.h b/test/libevmasm/PlainAssemblyParser.h index 0154af5f7..95cc3ee8f 100644 --- a/test/libevmasm/PlainAssemblyParser.h +++ b/test/libevmasm/PlainAssemblyParser.h @@ -20,6 +20,7 @@ #include +#include #include #include #include @@ -63,17 +64,18 @@ class PlainAssemblyParser bool advanceToken(); std::string_view expectArgument(); void expectNoMoreArguments(); - void advanceLine(std::string_view _line); + bool advanceLine(); static std::vector tokenizeLine(std::string_view _line); std::string formatError(std::string_view _message) const; private: - std::string m_sourceName; ///< Name of the file the source comes from. - size_t m_lineNumber = 0; ///< The number of the current line within the source, 1-based. - std::string m_line; ///< The current line, unparsed. - std::vector m_lineTokens; ///< Decomposition of the current line into tokens (does not include comments). - size_t m_tokenIndex = 0; ///< Points at a token within m_lineTokens. + std::istringstream m_sourceStream; ///< The source code being parsed. + std::string m_sourceName; ///< Name of the file the source comes from. + size_t m_lineNumber = 0; ///< The number of the current line within the source, 1-based. + std::optional m_line; ///< The current line, unparsed. + std::vector m_lineTokens; ///< Decomposition of the current line into tokens (does not include comments). + size_t m_tokenIndex = 0; ///< Points at a token within m_lineTokens. }; } From 73af6528bdd323d8c62fea2788525ad191a8ee3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 25 Apr 2025 06:17:46 +0200 Subject: [PATCH 0856/1340] PlainAssemblyParser: Syntax for subassemblies --- test/libevmasm/PlainAssemblyParser.cpp | 56 +++++- test/libevmasm/PlainAssemblyParser.h | 11 ++ .../isoltestTesting/empty.asm | 10 + .../isoltestTesting/subassemblies.asm | 69 +++++++ .../isoltestTesting/subassemblies_empty.asm | 34 ++++ .../isoltestTesting/subassemblies_nested.asm | 171 ++++++++++++++++++ 6 files changed, 347 insertions(+), 4 deletions(-) create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/empty.asm create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies.asm create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies_empty.asm create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies_nested.asm diff --git a/test/libevmasm/PlainAssemblyParser.cpp b/test/libevmasm/PlainAssemblyParser.cpp index 4d09043b1..c8fbfeaeb 100644 --- a/test/libevmasm/PlainAssemblyParser.cpp +++ b/test/libevmasm/PlainAssemblyParser.cpp @@ -39,11 +39,16 @@ Json PlainAssemblyParser::parse(std::string _sourceName, std::string const& _sou { m_sourceStream = std::istringstream(_source); m_sourceName = std::move(_sourceName); - Json codeJSON = Json::array(); m_lineNumber = 0; - if (!m_line.has_value()) - advanceLine(); + advanceLine(); + return parseAssembly(0); +} + +Json PlainAssemblyParser::parseAssembly(size_t _nestingLevel) +{ + Json assemblyJSON = {{".code", Json::array()}}; + Json& codeJSON = assemblyJSON[".code"]; while (m_line.has_value()) { @@ -52,6 +57,25 @@ Json PlainAssemblyParser::parse(std::string _sourceName, std::string const& _sou advanceLine(); continue; } + + size_t newLevel = parseNestingLevel(); + if (newLevel > _nestingLevel) + BOOST_THROW_EXCEPTION(std::runtime_error(formatError("Indentation does not match the current subassembly nesting level."))); + + if (newLevel < _nestingLevel) + return assemblyJSON; + + if (currentToken().value == ".sub") + { + advanceLine(); + + std::string nextDataIndex = std::to_string(assemblyJSON[".data"].size()); + assemblyJSON[".data"][nextDataIndex] = parseAssembly(_nestingLevel + 1); + continue; + } + else if (assemblyJSON.contains(".data")) + BOOST_THROW_EXCEPTION(std::runtime_error(formatError("The code of an assembly must be specified before its subassemblies."))); + if (c_instructions.contains(currentToken().value)) { expectNoMoreArguments(); @@ -91,7 +115,21 @@ Json PlainAssemblyParser::parse(std::string _sourceName, std::string const& _sou advanceLine(); } - return {{".code", codeJSON}}; + + return assemblyJSON; +} + +size_t PlainAssemblyParser::parseNestingLevel() const +{ + std::string_view indentationString = indentation(); + + if (indentationString != std::string(indentationString.size(), ' ')) + BOOST_THROW_EXCEPTION(std::runtime_error(formatError("Non-space characters used for indentation."))); + + if (indentationString.size() % 4 != 0) + BOOST_THROW_EXCEPTION(std::runtime_error(formatError("Each indentation level must consist of 4 spaces."))); + + return indentationString.size() / 4; } PlainAssemblyParser::Token const& PlainAssemblyParser::currentToken() const @@ -106,6 +144,16 @@ PlainAssemblyParser::Token const& PlainAssemblyParser::nextToken() const return m_lineTokens[m_tokenIndex + 1]; } +std::string_view PlainAssemblyParser::indentation() const +{ + soltestAssert(m_line.has_value()); + + if (m_lineTokens.empty()) + return *m_line; + + return std::string_view(*m_line).substr(0, m_lineTokens.at(0).position); +} + bool PlainAssemblyParser::advanceToken() { if (!hasMoreTokens()) diff --git a/test/libevmasm/PlainAssemblyParser.h b/test/libevmasm/PlainAssemblyParser.h index 95cc3ee8f..5332b3202 100644 --- a/test/libevmasm/PlainAssemblyParser.h +++ b/test/libevmasm/PlainAssemblyParser.h @@ -37,12 +37,18 @@ namespace solidity::evmasm::test /// - A non-empty line represents a single assembly item. /// - The name of the item is the first thing on the line and may consist of one or more tokens. /// - One or more arguments follow the name. +/// - Indentation determines assembly nesting level (4 spaces per level). +/// - A new subassembly starts with '.sub' and contains all subsequent lines at a higher nesting level. +/// The first line at the same or lower nesting level ends the subassembly. +/// - Subassemblies can be nested to arbitrary depth. +/// - The code of an assembly must be specified before its subassemblies. /// /// Supported items: /// - All instruction names. /// - PUSH /// - PUSH [tag] /// - tag +/// - .sub class PlainAssemblyParser { public: @@ -57,10 +63,15 @@ class PlainAssemblyParser size_t position; ///< Position of the first character of the token within m_line. }; + Json parseAssembly(size_t _nestingLevel); + size_t parseNestingLevel() const; + Token const& currentToken() const; Token const& nextToken() const; bool hasMoreTokens() const { return m_tokenIndex + 1 < m_lineTokens.size(); } + std::string_view indentation() const; + bool advanceToken(); std::string_view expectArgument(); void expectNoMoreArguments(); diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/empty.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/empty.asm new file mode 100644 index 000000000..a3c0ef539 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/empty.asm @@ -0,0 +1,10 @@ +// ==== +// outputs: InputAssemblyJSON,Assembly,Bytecode,Opcodes,SourceMappings +// ---- +// InputAssemblyJSON: { +// ".code": [] +// } +// Assembly: +// Bytecode: +// Opcodes: +// SourceMappings: diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies.asm new file mode 100644 index 000000000..7dc1a5150 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies.asm @@ -0,0 +1,69 @@ +PUSH 0x2 +DUP1 +ADD + +.sub + PUSH 0x42 + DUP1 + MUL + +.sub + STOP +// ==== +// outputs: InputAssemblyJSON,Assembly,Bytecode,Opcodes,SourceMappings +// ---- +// InputAssemblyJSON: { +// ".code": [ +// { +// "name": "PUSH", +// "value": "2" +// }, +// { +// "name": "DUP1" +// }, +// { +// "name": "ADD" +// } +// ], +// ".data": { +// "0": { +// ".code": [ +// { +// "name": "PUSH", +// "value": "42" +// }, +// { +// "name": "DUP1" +// }, +// { +// "name": "MUL" +// } +// ] +// }, +// "1": { +// ".code": [ +// { +// "name": "STOP" +// } +// ] +// } +// } +// } +// Assembly: +// 0x02 +// dup1 +// add +// stop +// +// sub_0: assembly { +// 0x42 +// dup1 +// mul +// } +// +// sub_1: assembly { +// stop +// } +// Bytecode: 60028001fe +// Opcodes: PUSH1 0x2 DUP1 ADD INVALID +// SourceMappings: :::-:0;; diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies_empty.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies_empty.asm new file mode 100644 index 000000000..8914710db --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies_empty.asm @@ -0,0 +1,34 @@ +.sub +.sub +.sub +// ==== +// outputs: InputAssemblyJSON,Assembly,Bytecode,Opcodes,SourceMappings +// ---- +// InputAssemblyJSON: { +// ".code": [], +// ".data": { +// "0": { +// ".code": [] +// }, +// "1": { +// ".code": [] +// }, +// "2": { +// ".code": [] +// } +// } +// } +// Assembly: +// stop +// +// sub_0: assembly { +// } +// +// sub_1: assembly { +// } +// +// sub_2: assembly { +// } +// Bytecode: fe +// Opcodes: INVALID +// SourceMappings: diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies_nested.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies_nested.asm new file mode 100644 index 000000000..59beb9b69 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/subassemblies_nested.asm @@ -0,0 +1,171 @@ +TIMESTAMP +TIMESTAMP + +.sub + TIMESTAMP + + .sub + TIMESTAMP + .sub + TIMESTAMP + .sub + TIMESTAMP + .sub + TIMESTAMP + .sub + TIMESTAMP +.sub + NUMBER + SLOAD + .sub + NUMBER + MLOAD + .sub + NUMBER + TLOAD + +// ==== +// outputs: InputAssemblyJSON,Assembly,Bytecode,Opcodes,SourceMappings +// ---- +// InputAssemblyJSON: { +// ".code": [ +// { +// "name": "TIMESTAMP" +// }, +// { +// "name": "TIMESTAMP" +// } +// ], +// ".data": { +// "0": { +// ".code": [ +// { +// "name": "TIMESTAMP" +// } +// ], +// ".data": { +// "0": { +// ".code": [ +// { +// "name": "TIMESTAMP" +// } +// ] +// }, +// "1": { +// ".code": [ +// { +// "name": "TIMESTAMP" +// } +// ], +// ".data": { +// "0": { +// ".code": [ +// { +// "name": "TIMESTAMP" +// } +// ], +// ".data": { +// "0": { +// ".code": [ +// { +// "name": "TIMESTAMP" +// } +// ] +// } +// } +// } +// } +// }, +// "2": { +// ".code": [ +// { +// "name": "TIMESTAMP" +// } +// ] +// } +// } +// }, +// "1": { +// ".code": [ +// { +// "name": "NUMBER" +// }, +// { +// "name": "SLOAD" +// } +// ], +// ".data": { +// "0": { +// ".code": [ +// { +// "name": "NUMBER" +// }, +// { +// "name": "MLOAD" +// } +// ], +// ".data": { +// "0": { +// ".code": [ +// { +// "name": "NUMBER" +// }, +// { +// "name": "TLOAD" +// } +// ] +// } +// } +// } +// } +// } +// } +// } +// Assembly: +// timestamp +// timestamp +// stop +// +// sub_0: assembly { +// timestamp +// stop +// +// sub_0: assembly { +// timestamp +// } +// +// sub_1: assembly { +// timestamp +// stop +// +// sub_0: assembly { +// timestamp +// stop +// +// sub_0: assembly { +// timestamp +// } +// } +// } +// +// sub_2: assembly { +// timestamp +// } +// } +// +// sub_1: assembly { +// sload(number) +// stop +// +// sub_0: assembly { +// mload(number) +// stop +// +// sub_0: assembly { +// tload(number) +// } +// } +// } +// Bytecode: 4242fe +// Opcodes: TIMESTAMP TIMESTAMP INVALID +// SourceMappings: :::-:0; From 202933bf14e3bd8349416f3cd185dfda488ef33f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 25 Apr 2025 07:58:58 +0200 Subject: [PATCH 0857/1340] PlainAssemblyParser: Support pushing assembly sizes and offsets --- test/libevmasm/PlainAssemblyParser.cpp | 15 +++- test/libevmasm/PlainAssemblyParser.h | 2 + .../isoltestTesting/pushsize.asm | 33 +++++++++ .../isoltestTesting/pushsubsize.asm | 72 +++++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/pushsize.asm create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/pushsubsize.asm diff --git a/test/libevmasm/PlainAssemblyParser.cpp b/test/libevmasm/PlainAssemblyParser.cpp index c8fbfeaeb..07b680474 100644 --- a/test/libevmasm/PlainAssemblyParser.cpp +++ b/test/libevmasm/PlainAssemblyParser.cpp @@ -76,7 +76,7 @@ Json PlainAssemblyParser::parseAssembly(size_t _nestingLevel) else if (assemblyJSON.contains(".data")) BOOST_THROW_EXCEPTION(std::runtime_error(formatError("The code of an assembly must be specified before its subassemblies."))); - if (c_instructions.contains(currentToken().value)) + if (c_instructions.contains(currentToken().value) || currentToken().value == "PUSHSIZE") { expectNoMoreArguments(); codeJSON.push_back({{"name", currentToken().value}}); @@ -90,6 +90,19 @@ Json PlainAssemblyParser::parseAssembly(size_t _nestingLevel) expectNoMoreArguments(); codeJSON.push_back({{"name", "PUSH [tag]"}, {"value", tagID}}); } + else if (hasMoreTokens() && (nextToken().value == "[$]" || nextToken().value == "#[$]")) + { + std::string pushType = std::string(nextToken().value); + advanceToken(); + std::string_view subassemblyID = expectArgument(); + expectNoMoreArguments(); + + if (!subassemblyID.starts_with("0x")) + BOOST_THROW_EXCEPTION(std::runtime_error(formatError("The subassembly ID must be a hex number prefixed with '0x'."))); + + subassemblyID.remove_prefix("0x"s.size()); + codeJSON.push_back({{"name", "PUSH " + pushType}, {"value", subassemblyID}}); + } else { std::string_view immediateArgument = expectArgument(); diff --git a/test/libevmasm/PlainAssemblyParser.h b/test/libevmasm/PlainAssemblyParser.h index 5332b3202..9318d1662 100644 --- a/test/libevmasm/PlainAssemblyParser.h +++ b/test/libevmasm/PlainAssemblyParser.h @@ -48,6 +48,8 @@ namespace solidity::evmasm::test /// - PUSH /// - PUSH [tag] /// - tag +/// - PUSH [$] +/// - PUSH #[$] /// - .sub class PlainAssemblyParser { diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/pushsize.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/pushsize.asm new file mode 100644 index 000000000..3c92687c4 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/pushsize.asm @@ -0,0 +1,33 @@ +PUSHSIZE + +.sub + PUSHSIZE +// ==== +// outputs: InputAssemblyJSON,Assembly,Bytecode,Opcodes,SourceMappings +// ---- +// InputAssemblyJSON: { +// ".code": [ +// { +// "name": "PUSHSIZE" +// } +// ], +// ".data": { +// "0": { +// ".code": [ +// { +// "name": "PUSHSIZE" +// } +// ] +// } +// } +// } +// Assembly: +// bytecodeSize +// stop +// +// sub_0: assembly { +// bytecodeSize +// } +// Bytecode: 6003fe +// Opcodes: PUSH1 0x3 INVALID +// SourceMappings: :::-:0 diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/pushsubsize.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/pushsubsize.asm new file mode 100644 index 000000000..1b51c22a8 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/pushsubsize.asm @@ -0,0 +1,72 @@ +PUSH [$] 0x0000 +PUSH #[$] 0x0000 + +.sub + PUSH [$] 0x0 + PUSH #[$] 0x2 + + .sub + .sub + .sub +// ==== +// outputs: InputAssemblyJSON,Assembly,Bytecode,Opcodes,SourceMappings +// ---- +// InputAssemblyJSON: { +// ".code": [ +// { +// "name": "PUSH [$]", +// "value": "0000" +// }, +// { +// "name": "PUSH #[$]", +// "value": "0000" +// } +// ], +// ".data": { +// "0": { +// ".code": [ +// { +// "name": "PUSH [$]", +// "value": "0" +// }, +// { +// "name": "PUSH #[$]", +// "value": "2" +// } +// ], +// ".data": { +// "0": { +// ".code": [] +// }, +// "1": { +// ".code": [] +// }, +// "2": { +// ".code": [] +// } +// } +// } +// } +// } +// Assembly: +// dataOffset(sub_0) +// dataSize(sub_0) +// stop +// +// sub_0: assembly { +// dataOffset(sub_0) +// dataSize(sub_2) +// stop +// +// sub_0: assembly { +// } +// +// sub_1: assembly { +// } +// +// sub_2: assembly { +// } +// } +// Bytecode: 60056005fe60056000fe +// Opcodes: PUSH1 0x5 PUSH1 0x5 INVALID PUSH1 0x5 PUSH1 0x0 INVALID +// SourceMappings: :::-:0; From 78107e344ce526695a5a989250d01812a248d536 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Sun, 27 Apr 2025 11:01:00 +0200 Subject: [PATCH 0858/1340] Assembly item asserts that it's not implicity constructed by instruction for swapn/dupn --- libevmasm/AssemblyItem.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 0dfe07497..8386bf2dd 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -85,7 +85,10 @@ class AssemblyItem m_type(Operation), m_instruction(_i), m_debugData(std::move(_debugData)) - {} + { + solAssert(_i != Instruction::SWAPN, "Construct via AssemblyItem::swapN"); + solAssert(_i != Instruction::DUPN, "Construct via AssemblyItem::dupN"); + } AssemblyItem(AssemblyItemType _type, u256 _data = 0, langutil::DebugData::ConstPtr _debugData = langutil::DebugData::create()): m_type(_type), m_debugData(std::move(_debugData)) From 49c2e551c12f8fde4dccd59d07be0ad5637060dd Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 28 Apr 2025 17:57:02 -0300 Subject: [PATCH 0859/1340] Set prague as EVM default version --- .circleci/config.yml | 2 +- .circleci/soltest_all.sh | 2 +- Changelog.md | 1 + docs/using-the-compiler.rst | 8 ++--- liblangutil/EVMVersion.h | 2 +- scripts/externalTests/common.sh | 2 +- scripts/externalTests/runners/base.py | 2 +- scripts/tests.sh | 2 +- .../mcopy_bytes_array_abi_decode/args | 2 +- .../args | 2 +- .../args | 2 +- test/cmdlineTests/metadata/output | 2 +- .../standard_metadata/output.json | 2 +- .../output.json | 2 +- .../output.json | 2 +- .../output.json | 2 +- .../output.json | 4 +-- .../output | 2 +- .../output | 2 +- test/libsolidity/StandardCompiler.cpp | 32 ++++--------------- 20 files changed, 30 insertions(+), 47 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 09b1281c5..80b3c5358 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,7 +34,7 @@ parameters: default: "solbuildpackpusher/solidity-buildpack-deps@sha256:98f963ed799a0d206ef8e7b5475f847e0dea53b7fdea9618bbc6106a62730bd2" evm-version: type: string - default: cancun + default: prague orbs: win: circleci/windows@2.2.0 diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 216b1ee38..56aa1c3be 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -38,7 +38,7 @@ EVMS_WITH_EOF=(osaka) # set EVM_VALUES to the default values. IFS=" " read -ra EVM_VALUES <<< "${1:-${DEFAULT_EVM_VALUES[@]}}" -DEFAULT_EVM=cancun +DEFAULT_EVM=prague OPTIMIZE_VALUES=(0 1) EOF_VERSIONS=(0 1) diff --git a/Changelog.md b/Changelog.md index e8ccbb525..cbaa42521 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: +* EVM: Set default EVM Version to `prague`. * NatSpec: Capture Natspec documentation of `enum` values in the AST. diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 23e83baec..a3943ea94 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -176,12 +176,12 @@ at each version. Backward compatibility is not guaranteed between each version. - Introduces ``prevrandao()`` and ``block.prevrandao``, and changes the semantics of the now deprecated ``block.difficulty``, disallowing ``difficulty()`` in inline assembly (see `EIP-4399 `_). - ``shanghai`` - Smaller code size and gas savings due to the introduction of ``push0`` (see `EIP-3855 `_). -- ``cancun`` (**default**) +- ``cancun`` - The block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) can be accessed via the global ``block.blobbasefee`` or ``blobbasefee()`` in inline assembly. - Introduces ``blobhash()`` in inline assembly and a corresponding global function to retrieve versioned hashes of blobs associated with the transaction (see `EIP-4844 `_). - Opcode ``mcopy`` is available in assembly (see `EIP-5656 `_). - Opcodes ``tstore`` and ``tload`` are available in assembly (see `EIP-1153 `_). -- ``prague`` (**experimental**) +- ``prague`` (**default**) - ``osaka`` (**experimental**) - Experimental compilation to EOF is available starting from this version. (`EIP-7692 `_) @@ -356,8 +356,8 @@ Input Description // Version of the EVM to compile for (optional). // Affects type checking and code generation. Can be homestead, // tangerineWhistle, spuriousDragon, byzantium, constantinople, - // petersburg, istanbul, berlin, london, paris, shanghai, cancun (default), prague (experimental) or osaka (experimental). - "evmVersion": "cancun", + // petersburg, istanbul, berlin, london, paris, shanghai, cancun, prague (default) or osaka (experimental). + "evmVersion": "prague", // EVM Object Format version to compile for (optional, experimental). // Currently the only valid value is 1. If not specified, legacy non-EOF bytecode will be generated. "eofVersion": null, diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index a159f2e4b..38580621a 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -167,7 +167,7 @@ class EVMVersion: EVMVersion(Version _version): m_version(_version) {} - Version m_version = Version::Cancun; + Version m_version = Version::Prague; }; } diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index 2983b30c2..26f27b07b 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -22,7 +22,7 @@ set -e # Requires $REPO_ROOT to be defined and "${REPO_ROOT}/scripts/common.sh" to be included before. -CURRENT_EVM_VERSION=cancun +CURRENT_EVM_VERSION=prague AVAILABLE_PRESETS=( legacy-no-optimize diff --git a/scripts/externalTests/runners/base.py b/scripts/externalTests/runners/base.py index 477820615..20ba67ddb 100644 --- a/scripts/externalTests/runners/base.py +++ b/scripts/externalTests/runners/base.py @@ -41,7 +41,7 @@ from test_helpers import settings_from_preset from test_helpers import SettingsPreset -CURRENT_EVM_VERSION: str = "cancun" +CURRENT_EVM_VERSION: str = "prague" @dataclass class TestConfig: diff --git a/scripts/tests.sh b/scripts/tests.sh index 3d2849369..5ff962be6 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -115,7 +115,7 @@ do for vm in $EVM_VERSIONS do FORCE_ABIV1_RUNS="no" - if [[ "$vm" == "cancun" ]] + if [[ "$vm" == "prague" ]] then FORCE_ABIV1_RUNS="no yes" # run both in paris fi diff --git a/test/cmdlineTests/mcopy_bytes_array_abi_decode/args b/test/cmdlineTests/mcopy_bytes_array_abi_decode/args index 4a03d8d93..a346a1eb7 100644 --- a/test/cmdlineTests/mcopy_bytes_array_abi_decode/args +++ b/test/cmdlineTests/mcopy_bytes_array_abi_decode/args @@ -1 +1 @@ ---evm-version cancun --no-cbor-metadata --via-ir --ir --debug-info none +--no-cbor-metadata --via-ir --ir --debug-info none diff --git a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/args b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/args index c74711ba8..a582f88e9 100644 --- a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/args +++ b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/args @@ -1 +1 @@ ---evm-version cancun --no-cbor-metadata --via-ir --optimize --ir-optimized --debug-info none +--no-cbor-metadata --via-ir --optimize --ir-optimized --debug-info none diff --git a/test/cmdlineTests/mcopy_string_literal_returned_from_function/args b/test/cmdlineTests/mcopy_string_literal_returned_from_function/args index c74711ba8..a582f88e9 100644 --- a/test/cmdlineTests/mcopy_string_literal_returned_from_function/args +++ b/test/cmdlineTests/mcopy_string_literal_returned_from_function/args @@ -1 +1 @@ ---evm-version cancun --no-cbor-metadata --via-ir --optimize --ir-optimized --debug-info none +--no-cbor-metadata --via-ir --optimize --ir-optimized --debug-info none diff --git a/test/cmdlineTests/metadata/output b/test/cmdlineTests/metadata/output index 091012889..a62f2ed14 100644 --- a/test/cmdlineTests/metadata/output +++ b/test/cmdlineTests/metadata/output @@ -1,4 +1,4 @@ ======= input.sol:C ======= Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"prague","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} diff --git a/test/cmdlineTests/standard_metadata/output.json b/test/cmdlineTests/standard_metadata/output.json index 5b9c8504f..155e15db1 100644 --- a/test/cmdlineTests/standard_metadata/output.json +++ b/test/cmdlineTests/standard_metadata/output.json @@ -2,7 +2,7 @@ "contracts": { "C": { "C": { - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2\",\"dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS\"]}},\"version\":1}" + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2\",\"dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS\"]}},\"version\":1}" } } }, diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json index c461a1485..07087b30f 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json @@ -2,7 +2,7 @@ "contracts": { "A": { "C": { - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" } } }, diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json index c461a1485..07087b30f 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json @@ -2,7 +2,7 @@ "contracts": { "A": { "C": { - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" } } }, diff --git a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json index 0fa7fcff3..eae7a321f 100644 --- a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json +++ b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json @@ -32,7 +32,7 @@ "x()": "0c55699c" } }, - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x67a13ebd685e4c6f792e71eb747dac57edb99e94d04d841ee6c979ae517934ce\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://665b000da768823654f680d02686c1e59d682a0b3882e43a77fed9f80ce64ae8\",\"dweb:/ipfs/QmVnKvuidH6KiCdNQpoAQUtDbB8hXkafVLXWMNitUcxnqC\"]}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x67a13ebd685e4c6f792e71eb747dac57edb99e94d04d841ee6c979ae517934ce\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://665b000da768823654f680d02686c1e59d682a0b3882e43a77fed9f80ce64ae8\",\"dweb:/ipfs/QmVnKvuidH6KiCdNQpoAQUtDbB8hXkafVLXWMNitUcxnqC\"]}},\"version\":1}", "storageLayout": { "storage": [], "types": null diff --git a/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json b/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json index 3869f7c65..be87a5176 100644 --- a/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json +++ b/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json @@ -35,7 +35,7 @@ "irAst": null, "irOptimized": "", "irOptimizedAst": null, - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", "storageLayout": { "storage": [], "types": null @@ -84,7 +84,7 @@ "irAst": null, "irOptimized": "", "irOptimizedAst": null, - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"I\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"I\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", "storageLayout": { "storage": [], "types": null diff --git a/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output index 744bc03a8..de60e7d1d 100644 --- a/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output +++ b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output @@ -1,4 +1,4 @@ ======= input.sol:C ======= Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0xc2db3500808896ce1e69de2fe20cecab7ae2ffbb47cdf6ba8321296d95f49fc5","license":"GPL-3.0","urls":["bzz-raw://fde21393c068cd9f2d2b10ba4782db54f6f1c9a725074b17fa742531076be8a4","dweb:/ipfs/QmeTD6mR7YrWNyRowKRS7xs6cJNeMF3T49GAHzGM1bquyM"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"prague","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0xc2db3500808896ce1e69de2fe20cecab7ae2ffbb47cdf6ba8321296d95f49fc5","license":"GPL-3.0","urls":["bzz-raw://fde21393c068cd9f2d2b10ba4782db54f6f1c9a725074b17fa742531076be8a4","dweb:/ipfs/QmeTD6mR7YrWNyRowKRS7xs6cJNeMF3T49GAHzGM1bquyM"]}},"version":1} diff --git a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output index a7b037775..2b32c23ee 100644 --- a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output +++ b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output @@ -130,4 +130,4 @@ object "C_28" { } Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"foo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0x3fc910e345ce1ee62bfa6b0f66931ee632c08265b25b6139cfbbfe4d2f8d5dd8","license":"GPL-3.0","urls":["bzz-raw://e557e9ad2c2e420a669c06ae456b0b790d77d2d6d492cd8540e6b244388a5140","dweb:/ipfs/QmaNiZmC2Mo3YxGiehs1n3dVTjZwD7FguX7EUtpeshMVuR"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"foo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"prague","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0x3fc910e345ce1ee62bfa6b0f66931ee632c08265b25b6139cfbbfe4d2f8d5dd8","license":"GPL-3.0","urls":["bzz-raw://e557e9ad2c2e420a669c06ae456b0b790d77d2d6d492cd8540e6b244388a5140","dweb:/ipfs/QmaNiZmC2Mo3YxGiehs1n3dVTjZwD7FguX7EUtpeshMVuR"]}},"version":1} diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index b17f56661..5360a2778 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1170,33 +1171,14 @@ BOOST_AUTO_TEST_CASE(evm_version) )"; }; Json result; - result = compile(inputForVersion("\"evmVersion\": \"homestead\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"homestead\"") != std::string::npos); - result = compile(inputForVersion("\"evmVersion\": \"tangerineWhistle\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"tangerineWhistle\"") != std::string::npos); - result = compile(inputForVersion("\"evmVersion\": \"spuriousDragon\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"spuriousDragon\"") != std::string::npos); - result = compile(inputForVersion("\"evmVersion\": \"byzantium\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"byzantium\"") != std::string::npos); - result = compile(inputForVersion("\"evmVersion\": \"constantinople\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"constantinople\"") != std::string::npos); - result = compile(inputForVersion("\"evmVersion\": \"petersburg\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"petersburg\"") != std::string::npos); - result = compile(inputForVersion("\"evmVersion\": \"istanbul\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"istanbul\"") != std::string::npos); - result = compile(inputForVersion("\"evmVersion\": \"berlin\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"berlin\"") != std::string::npos); - result = compile(inputForVersion("\"evmVersion\": \"london\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"london\"") != std::string::npos); - result = compile(inputForVersion("\"evmVersion\": \"paris\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"paris\"") != std::string::npos); - result = compile(inputForVersion("\"evmVersion\": \"shanghai\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"shanghai\"") != std::string::npos); - result = compile(inputForVersion("\"evmVersion\": \"cancun\",")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"cancun\"") != std::string::npos); + for (auto const& version: langutil::EVMVersion::allVersions()) + { + result = compile(inputForVersion(fmt::format("\"evmVersion\": \"{}\",", version.name()))); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find(fmt::format("\"evmVersion\":\"{}\"", version.name())) != std::string::npos); + } // test default result = compile(inputForVersion("")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"cancun\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"prague\"") != std::string::npos); // test invalid result = compile(inputForVersion("\"evmVersion\": \"invalid\",")); BOOST_CHECK(result["errors"][0]["message"].get() == "Invalid EVM version requested."); From ca699f9b02a59270afd8f43c28d15c9a63d301ff Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 6 May 2025 11:47:39 -0300 Subject: [PATCH 0860/1340] bump hardhat version --- test/externalTests/gp2.sh | 5 +---- test/externalTests/pool-together.sh | 4 +--- test/externalTests/uniswap.sh | 5 +---- test/externalTests/zeppelin.sh | 5 +---- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/test/externalTests/gp2.sh b/test/externalTests/gp2.sh index 20ea586f5..d648de592 100755 --- a/test/externalTests/gp2.sh +++ b/test/externalTests/gp2.sh @@ -66,10 +66,7 @@ function gp2_test force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" force_hardhat_unlimited_contract_size "$config_file" "$config_var" yarn - # We require to install hardhat 2.20.0 due to support for evm version cancun, otherwise we get the following error: - # Invalid value {"blockGasLimit":12500000,"hardfork":"cancun","allowUnlimitedContractSize":true} for HardhatConfig.networks.hardhat - Expected a value of type HardhatNetworkConfig. - # See: https://github.com/NomicFoundation/hardhat/issues/4176 - yarn add hardhat@2.20.0 + yarn add hardhat # Ignore bench directory which fails to compile with current hardhat and ethers versions. # bench/trace/gas.ts:123:19 - error TS2339: Property 'equals' does not exist on type 'Uint8Array'. diff --git a/test/externalTests/pool-together.sh b/test/externalTests/pool-together.sh index 0fc8aafbd..2eb47912c 100755 --- a/test/externalTests/pool-together.sh +++ b/test/externalTests/pool-together.sh @@ -66,9 +66,7 @@ function pool_together_test force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" yarn install - # Hardhat 2.20.0 is the last version that works. Newer versions throw this error: - # Unexpected config HardhatConfig.networks.hardhat.initialBaseFeePerGas found - This field is only valid for networks with EIP-1559. Try a newer hardfork or remove it. - yarn add hardhat@2.20.0 + yarn add hardhat # These come with already compiled artifacts. We want them recompiled with latest compiler. rm -r node_modules/@pooltogether/yield-source-interface/artifacts/ diff --git a/test/externalTests/uniswap.sh b/test/externalTests/uniswap.sh index f3d78e6e3..575fcf309 100755 --- a/test/externalTests/uniswap.sh +++ b/test/externalTests/uniswap.sh @@ -90,10 +90,7 @@ function uniswap_test # TODO: Remove when https://github.com/ethers-io/ethers.js/discussions/2849 is resolved. pnpm install ethers@5.6.1 - # We set hardhat version to 2.20.0 since version 2.21.0 has issues with solidity-coverage plugin - # that often causes out-of-memory errors. - # See hardhat note about the issue here: https://github.com/NomicFoundation/hardhat/releases/tag/hardhat@2.21.0 - pnpm install hardhat@2.20.0 + pnpm install hardhat replace_version_pragmas diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index b9e65562e..86d2495da 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -105,10 +105,7 @@ function zeppelin_test force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" npm install - # We require to install hardhat 2.20.0 due to support for evm version cancun, otherwise we get the following error: - # Invalid value {"blockGasLimit":10000000,"allowUnlimitedContractSize":true,"hardfork":"cancun"} for HardhatConfig.networks.hardhat - Expected a value of type HardhatNetworkConfig. - # See: https://github.com/NomicFoundation/hardhat/issues/4176 - npm install hardhat@2.20.0 + npm install hardhat replace_version_pragmas for preset in $SELECTED_PRESETS; do From 24d534f67009c62feb336940e6711526d0905390 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 6 May 2025 14:59:13 -0300 Subject: [PATCH 0861/1340] Increase resource for uniswap ext test --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 80b3c5358..6c88b9d19 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -831,6 +831,7 @@ defaults: project: uniswap binary_type: native image: cimg/node:18.16 + resource_class: medium # Tests run out of memory on a smaller machine - job_native_test_ext_prb_math: &job_native_test_ext_prb_math <<: *requires_b_ubu_static From 13d734fd22990508a256c4c591310e78b8247112 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 6 May 2025 17:24:18 -0300 Subject: [PATCH 0862/1340] Workaround for openzepellin ext test --- test/externalTests/zeppelin.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 86d2495da..9bc3e2913 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -101,6 +101,10 @@ function zeppelin_test # Here only the testToInt(248) and testToInt(256) cases fail so change the loop range to skip them sed -i "s|range(8, 256, 8)\(.forEach(bits => testToInt(bits));\)|range(8, 240, 8)\1|" test/utils/math/SafeCast.test.js + # TODO: Remove when next hardhat version releases, the fix is already merged: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5663 + # Fails with ProviderError: Invalid transaction: GasFloorMoreThanGasLimit + sed -i "177s|+ 2_000n|+ 10_000n|" test/metatx/ERC2771Forwarder.test.js + neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" From 1e6842c2c312a124c8ffb28fa0097ebd58f5e990 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 7 May 2025 09:39:30 +0200 Subject: [PATCH 0863/1340] Fix broken docs links --- docs/contracts/inheritance.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contracts/inheritance.rst b/docs/contracts/inheritance.rst index fccfee609..8a2d12afd 100644 --- a/docs/contracts/inheritance.rst +++ b/docs/contracts/inheritance.rst @@ -548,7 +548,7 @@ Multiple Inheritance and Linearization Languages that allow multiple inheritance have to deal with several problems. One is the `Diamond Problem `_. -Solidity is similar to Python in that it uses "`C3 Linearization `_" +Solidity is similar to Python in that it uses C3 Linearization to force a specific order in the directed acyclic graph (DAG) of base classes. This results in the desirable property of monotonicity but disallows some inheritance graphs. Especially, the order in From 1c8d4016f5394d9804864339515b995210eaff5a Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 7 May 2025 10:46:23 +0200 Subject: [PATCH 0864/1340] Set changelog release date --- Changelog.md | 5 +---- docs/bugs_by_version.json | 4 ++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index cbaa42521..9a1139e9c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,7 +1,4 @@ -### 0.8.30 (unreleased) - -Language Features: - +### 0.8.30 (2025-05-07) Compiler Features: * EVM: Set default EVM Version to `prague`. diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 60fcdd049..1a210b885 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1923,6 +1923,10 @@ ], "released": "2021-03-23" }, + "0.8.30": { + "bugs": [], + "released": "2025-05-07" + }, "0.8.4": { "bugs": [ "FullInlinerNonExpressionSplitArgumentEvaluationOrder", From e313827e5441d306f6cb28c95c50b451cbf47b4a Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 7 May 2025 14:04:08 +0200 Subject: [PATCH 0865/1340] Set version to 0.8.31 --- CMakeLists.txt | 2 +- Changelog.md | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b39878f2..1e477cf3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.30") +set(PROJECT_VERSION "0.8.31") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index 9a1139e9c..967e54881 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,14 @@ +### 0.8.31 (unreleased) + +Language Features: + + +Compiler Features: + + +Bugfixes: + + ### 0.8.30 (2025-05-07) Compiler Features: From 895eb45c8afa147529af66b9431dc39f6d0ac9a9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 9 May 2025 15:59:11 +0200 Subject: [PATCH 0866/1340] Add literal assignment to SSACFG --- libyul/YulControlFlowGraphExporter.cpp | 14 +++++++++++--- libyul/backends/evm/SSAControlFlowGraph.cpp | 21 ++++++++++++++++----- libyul/backends/evm/SSAControlFlowGraph.h | 8 ++++++-- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/libyul/YulControlFlowGraphExporter.cpp b/libyul/YulControlFlowGraphExporter.cpp index 65c0805f9..1ce7f58fc 100644 --- a/libyul/YulControlFlowGraphExporter.cpp +++ b/libyul/YulControlFlowGraphExporter.cpp @@ -177,12 +177,20 @@ Json YulControlFlowGraphExporter::toJson(SSACFG const& _cfg, SSACFG::BlockId _bl Json YulControlFlowGraphExporter::toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation) { Json opJson = Json::object(); - std::visit(util::GenericVisitor{ - [&](SSACFG::Call const& _call) { + std::visit(GenericVisitor{ + [&](SSACFG::Call const& _call) + { _ret["type"] = "FunctionCall"; opJson["op"] = _call.function.get().name.str(); }, - [&](SSACFG::BuiltinCall const& _call) { + [&](SSACFG::LiteralAssignment const&) + { + yulAssert(_operation.inputs.size() == 1); + yulAssert(_cfg.isLiteralValue(_operation.inputs.back())); + _ret["type"] = "LiteralAssignment"; + }, + [&](SSACFG::BuiltinCall const& _call) + { _ret["type"] = "BuiltinCall"; Json builtinArgsJson = Json::array(); auto const& builtin = _call.builtin.get(); diff --git a/libyul/backends/evm/SSAControlFlowGraph.cpp b/libyul/backends/evm/SSAControlFlowGraph.cpp index 733f4967d..215fe7358 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.cpp +++ b/libyul/backends/evm/SSAControlFlowGraph.cpp @@ -168,17 +168,28 @@ class SSACFGPrinter [&](SSACFG::BuiltinCall const& _call) { return _call.builtin.get().name; }, + [&](SSACFG::LiteralAssignment const&) + { + yulAssert(operation.inputs.size() == 1); + return varToString(m_cfg, operation.inputs.back()); + } }, operation.kind); if (!operation.outputs.empty()) m_result << fmt::format( "{} := ", fmt::join(operation.outputs | ranges::views::transform(valueToString), ", ") ); - m_result << fmt::format( - "{}({})\\l\\\n", - escape(label), - fmt::join(operation.inputs | ranges::views::transform(valueToString), ", ") - ); + if (std::holds_alternative(operation.kind)) + m_result << fmt::format( + "{}\\l\\\n", + escape(label) + ); + else + m_result << fmt::format( + "{}({})\\l\\\n", + escape(label), + fmt::join(operation.inputs | ranges::views::transform(valueToString), ", ") + ); } m_result << "\"];\n"; std::visit(GenericVisitor{ diff --git a/libyul/backends/evm/SSAControlFlowGraph.h b/libyul/backends/evm/SSAControlFlowGraph.h index 9397e0e20..ee1bdf3b4 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.h +++ b/libyul/backends/evm/SSAControlFlowGraph.h @@ -78,10 +78,14 @@ class SSACFG std::reference_wrapper call; bool canContinue; }; + struct LiteralAssignment + { + langutil::DebugData::ConstPtr debugData; + }; struct Operation { std::vector outputs{}; - std::variant kind; + std::variant kind; std::vector inputs{}; }; struct BasicBlock @@ -199,7 +203,7 @@ class SSACFG } ValueId newLiteral(langutil::DebugData::ConstPtr _debugData, u256 _value) { - auto [it, inserted] = m_literals.emplace(_value, SSACFG::ValueId{m_valueInfos.size()}); + auto [it, inserted] = m_literals.emplace(_value, ValueId{m_valueInfos.size()}); if (inserted) m_valueInfos.emplace_back(LiteralValue{std::move(_debugData), _value}); else From d790750c2abd66a86201c44d73e8074cd5076a84 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 9 May 2025 16:01:06 +0200 Subject: [PATCH 0867/1340] Add option to keep literal assignments in SSACFG builder --- libyul/YulStack.cpp | 8 +- .../evm/SSAControlFlowGraphBuilder.cpp | 65 +++++--- .../backends/evm/SSAControlFlowGraphBuilder.h | 7 +- .../standard_yul_cfg_json_export/output.json | 128 ++++++++------- test/cmdlineTests/yul_cfg_json_export/output | 128 ++++++++------- test/libyul/SSAControlFlowGraphTest.cpp | 3 +- .../libyul/yulSSAControlFlowGraph/complex.yul | 75 ++++----- .../yulSSAControlFlowGraph/complex2.yul | 80 +++++----- .../yulSSAControlFlowGraph/function.yul | 6 +- .../yulSSAControlFlowGraph/nested_for.yul | 147 +++++++++--------- .../nested_function.yul | 10 +- 11 files changed, 367 insertions(+), 290 deletions(-) diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 5adb8d6d5..85709b987 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -394,11 +394,15 @@ Json YulStack::cfgJson() const yulAssert(m_parserResult->analysisInfo, ""); // FIXME: we should not regenerate the cfg, but for now this is sufficient for testing purposes auto exportCFGFromObject = [&](Object const& _object) -> Json { + // with this set to `true`, assignments of the type `let x := 42` are preserved and added as assignment + // operations to the control flow graphs + bool constexpr keepLiteralAssignments = true; // NOTE: The block Ids are reset for each object std::unique_ptr controlFlow = SSAControlFlowGraphBuilder::build( - *_object.analysisInfo.get(), + *_object.analysisInfo, languageToDialect(m_language, m_evmVersion, m_eofVersion), - _object.code()->root() + _object.code()->root(), + keepLiteralAssignments ); std::unique_ptr liveness = std::make_unique(*controlFlow); YulControlFlowGraphExporter exporter(*controlFlow, liveness.get()); diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 69e9e3052..19308617c 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -20,16 +20,18 @@ */ #include -#include -#include + #include +#include #include +#include #include #include #include #include +#include #include #include #include @@ -49,26 +51,29 @@ SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder( SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, - Dialect const& _dialect + Dialect const& _dialect, + bool _keepLiteralAssignments ): m_controlFlow(_controlFlow), m_graph(_graph), m_info(_analysisInfo), m_sideEffects(_sideEffects), - m_dialect(_dialect) + m_dialect(_dialect), + m_keepLiteralAssignments(_keepLiteralAssignments) { } std::unique_ptr SSAControlFlowGraphBuilder::build( AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, - Block const& _block + Block const& _block, + bool _keepLiteralAssignments ) { ControlFlowSideEffectsCollector sideEffects(_dialect, _block); auto controlFlow = std::make_unique(); - SSAControlFlowGraphBuilder builder(*controlFlow, *controlFlow->mainGraph, _analysisInfo, sideEffects, _dialect); + SSAControlFlowGraphBuilder builder(*controlFlow, *controlFlow->mainGraph, _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments); builder.m_currentBlock = controlFlow->mainGraph->makeBlock(debugDataOf(_block)); builder.sealBlock(builder.m_currentBlock); builder(_block); @@ -147,8 +152,8 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId [](SSACFG::BasicBlock::Terminated&) {} }, block.exit); } - for (auto& [_, currentVariableDefs]: m_currentDef) - std::replace(currentVariableDefs.begin(), currentVariableDefs.end(), _phi, same); + for (auto& currentVariableDefs: m_currentDef | ranges::views::values) + ranges::replace(currentVariableDefs, _phi, same); for (auto phiUse: phiUses) tryRemoveTrivialPhi(phiUse); @@ -178,11 +183,6 @@ void SSAControlFlowGraphBuilder::cleanUnreachable() }, block.exit); }); - auto isUnreachableValue = [&](SSACFG::ValueId const& _value) -> bool { - auto* valueInfo = std::get_if(&m_graph.valueInfo(_value)); - return (valueInfo) ? true : false; - }; - // Remove all entries from unreachable nodes from the graph. for (SSACFG::BlockId blockId: reachabilityCheck.visited) { @@ -197,7 +197,7 @@ void SSAControlFlowGraphBuilder::cleanUnreachable() for (auto phi: block.phis) if (auto* phiInfo = std::get_if(&m_graph.valueInfo(phi))) std::erase_if(phiInfo->arguments, [&](SSACFG::ValueId _arg) { - if (isUnreachableValue(_arg)) + if (std::holds_alternative(m_graph.valueInfo(_arg))) { maybeTrivialPhi.insert(phi); return true; @@ -240,7 +240,7 @@ void SSAControlFlowGraphBuilder::buildFunctionGraph( cfg.arguments = arguments; cfg.returns = returns; - SSAControlFlowGraphBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect); + SSAControlFlowGraphBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_keepLiteralAssignments); builder.m_currentBlock = cfg.entry; builder.m_functionDefinitions = m_functionDefinitions; for (auto&& [var, varId]: cfg.arguments) @@ -273,6 +273,11 @@ void SSAControlFlowGraphBuilder::operator()(Assignment const& _assignment) void SSAControlFlowGraphBuilder::operator()(VariableDeclaration const& _variableDeclaration) { + // if we have no value (like in `let a` without right-hand side), we can just skip this. the variable(s) will be + // added when first needed + if (!_variableDeclaration.value) + return; + assign( _variableDeclaration.variables | ranges::views::transform([&](auto& _var) { return std::ref(lookupVariable(_var.name)); }) | ranges::to, _variableDeclaration.value.get() @@ -533,15 +538,27 @@ void SSAControlFlowGraphBuilder::assign(std::vector std::vector { if (auto const* functionCall = std::get_if(_expression)) return visitFunctionCall(*functionCall); - else if (_expression) + if (_expression) return {std::visit(*this, *_expression)}; - else - return {_variables.size(), zero()}; + return {_variables.size(), zero()}; }(); yulAssert(rhs.size() == _variables.size()); for (auto const& [var, value]: ranges::zip_view(_variables, rhs)) - writeVariable(var, m_currentBlock, value); + { + if (m_keepLiteralAssignments && m_graph.isLiteralValue(value)) + { + SSACFG::Operation assignment{ + .outputs = {m_graph.newVariable(m_currentBlock)}, + .kind = SSACFG::LiteralAssignment{}, + .inputs = {value} + }; + currentBlock().operations.emplace_back(assignment); + writeVariable(var, m_currentBlock, assignment.outputs.back()); + } + else + writeVariable(var, m_currentBlock, value); + } } @@ -610,7 +627,7 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::readVariableRecursive(Scope::Variabl // incomplete block val = m_graph.newPhi(_block); block.phis.insert(val); - info.incompletePhis.emplace_back(val, std::ref(_variable)); + info.incompletePhis.emplace_back(val, _variable); } else if (block.entries.size() == 1) // one predecessor: no phi needed @@ -633,7 +650,7 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::addPhiOperands(Scope::Variable const { yulAssert(std::holds_alternative(m_graph.valueInfo(_phi))); auto& phi = std::get(m_graph.valueInfo(_phi)); - for (auto pred: m_graph.block(phi.block).entries) + for (auto const& pred: m_graph.block(phi.block).entries) phi.arguments.emplace_back(readVariable(_variable, pred)); // we call tryRemoveTrivialPhi explicitly to avoid removing trivial phis in unsealed blocks return _phi; @@ -660,14 +677,14 @@ Scope::Variable const& SSAControlFlowGraphBuilder::lookupVariable(YulName _name) yulAssert(m_scope, ""); Scope::Variable const* var = nullptr; if (m_scope->lookup(_name, util::GenericVisitor{ - [&](Scope::Variable& _var) { var = &_var; }, - [](Scope::Function&) + [&](Scope::Variable const& _var) { var = &_var; }, + [](Scope::Function const&) { yulAssert(false, "Function not removed during desugaring."); } })) { - yulAssert(var, ""); + yulAssert(var); return *var; }; yulAssert(false, "External identifier access unimplemented."); diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.h b/libyul/backends/evm/SSAControlFlowGraphBuilder.h index a3a723f67..8cd214146 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.h +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.h @@ -44,7 +44,8 @@ class SSAControlFlowGraphBuilder SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, - Dialect const& _dialect + Dialect const& _dialect, + bool _keepLiteralAssignments ); public: SSAControlFlowGraphBuilder(SSAControlFlowGraphBuilder const&) = delete; @@ -52,7 +53,8 @@ class SSAControlFlowGraphBuilder static std::unique_ptr build( AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, - Block const& _block + Block const& _block, + bool _keepLiteralAssignments ); void operator()(ExpressionStatement const& _statement); @@ -92,6 +94,7 @@ class SSAControlFlowGraphBuilder AsmAnalysisInfo const& m_info; ControlFlowSideEffectsCollector const& m_sideEffects; Dialect const& m_dialect; + bool const m_keepLiteralAssignments; std::vector> m_functionDefinitions; SSACFG::BlockId m_currentBlock; SSACFG::BasicBlock& currentBlock() { return m_graph.block(m_currentBlock); } diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index 303d51bbb..a9c5ca7a6 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -1221,16 +1221,27 @@ "type": "ConditionalJump" }, "id": "Block18", - "instructions": [], + "instructions": [ + { + "in": [ + "0x00" + ], + "out": [ + "v64" + ] + } + ], "liveness": { "in": [ "v46", "v59" ], "out": [ - "v46" + "v46", + "v64" ] - } + }, + "type": "LiteralAssignment" }, { "exit": { @@ -1297,12 +1308,12 @@ "instructions": [ { "in": [ - "0x00", - "v93" + "v64", + "v95" ], "op": "PhiFunction", "out": [ - "v95" + "v97" ] }, { @@ -1311,13 +1322,13 @@ ], "op": "mload", "out": [ - "v94" + "v96" ] }, { "in": [ - "v95", - "v94" + "v97", + "v96" ], "op": "mstore", "out": [] @@ -1325,7 +1336,7 @@ { "in": [ "0x20", - "v94" + "v96" ], "op": "return", "out": [] @@ -1333,7 +1344,7 @@ ], "liveness": { "in": [ - "v95" + "v97" ], "out": [] }, @@ -1341,7 +1352,7 @@ }, { "exit": { - "cond": "v67", + "cond": "v69", "targets": [ "Block23", "Block22" @@ -1350,21 +1361,29 @@ }, "id": "Block20", "instructions": [ + { + "in": [ + "0x20" + ], + "out": [ + "v67" + ] + }, { "in": [], "op": "returndatasize", "out": [ - "v66" + "v68" ] }, { "in": [ - "v66", + "v68", "0x20" ], "op": "gt", "out": [ - "v67" + "v69" ] } ], @@ -1373,7 +1392,8 @@ "v46" ], "out": [ - "v46" + "v46", + "v67" ] }, "type": "BuiltinCall" @@ -1384,7 +1404,7 @@ "Block22" ], "exit": { - "cond": "v80", + "cond": "v82", "targets": [ "Block25", "Block24" @@ -1395,12 +1415,12 @@ "instructions": [ { "in": [ - "0x20", - "v68" + "v67", + "v70" ], "op": "PhiFunction", "out": [ - "v71" + "v73" ] }, { @@ -1409,79 +1429,79 @@ ], "op": "not", "out": [ - "v70" + "v72" ] }, { "in": [ "0x1f", - "v71" + "v73" ], "op": "add", "out": [ - "v72" + "v74" ] }, { "in": [ - "v70", - "v72" + "v72", + "v74" ], "op": "and", "out": [ - "v73" + "v75" ] }, { "in": [ - "v73", + "v75", "v46" ], "op": "add", "out": [ - "v77" + "v79" ] }, { "in": [ "v46", - "v77" + "v79" ], "op": "lt", "out": [ - "v78" + "v80" ] }, { "in": [ "0xffffffffffffffff", - "v77" + "v79" ], "op": "gt", "out": [ - "v79" + "v81" ] }, { "in": [ - "v78", - "v79" + "v80", + "v81" ], "op": "or", "out": [ - "v80" + "v82" ] } ], "liveness": { "in": [ "v46", - "v71" + "v73" ], "out": [ "v46", - "v71", - "v77" + "v73", + "v79" ] }, "type": "BuiltinCall" @@ -1499,7 +1519,7 @@ "in": [], "op": "returndatasize", "out": [ - "v68" + "v70" ] } ], @@ -1509,14 +1529,14 @@ ], "out": [ "v46", - "v68" + "v70" ] }, "type": "BuiltinCall" }, { "exit": { - "cond": "v90", + "cond": "v92", "targets": [ "Block28", "Block27" @@ -1527,7 +1547,7 @@ "instructions": [ { "in": [ - "v77", + "v79", "0x40" ], "op": "mstore", @@ -1535,40 +1555,40 @@ }, { "in": [ - "v71", + "v73", "v46" ], "op": "add", "out": [ - "v88" + "v90" ] }, { "in": [ "v46", - "v88" + "v90" ], "op": "sub", "out": [ - "v89" + "v91" ] }, { "in": [ "0x20", - "v89" + "v91" ], "op": "slt", "out": [ - "v90" + "v92" ] } ], "liveness": { "in": [ "v46", - "v71", - "v77" + "v73", + "v79" ], "out": [ "v46" @@ -1589,12 +1609,12 @@ ], "op": "shl", "out": [ - "v81" + "v83" ] }, { "in": [ - "v81", + "v83", "0x00" ], "op": "mstore", @@ -1638,7 +1658,7 @@ ], "op": "mload", "out": [ - "v93" + "v95" ] } ], @@ -1647,7 +1667,7 @@ "v46" ], "out": [ - "v93" + "v95" ] }, "type": "BuiltinCall" diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index 9affc4206..2620d53a9 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -1221,16 +1221,27 @@ Yul Control Flow Graph: "type": "ConditionalJump" }, "id": "Block18", - "instructions": [], + "instructions": [ + { + "in": [ + "0x00" + ], + "out": [ + "v64" + ] + } + ], "liveness": { "in": [ "v46", "v59" ], "out": [ - "v46" + "v46", + "v64" ] - } + }, + "type": "LiteralAssignment" }, { "exit": { @@ -1297,12 +1308,12 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "0x00", - "v93" + "v64", + "v95" ], "op": "PhiFunction", "out": [ - "v95" + "v97" ] }, { @@ -1311,13 +1322,13 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v94" + "v96" ] }, { "in": [ - "v95", - "v94" + "v97", + "v96" ], "op": "mstore", "out": [] @@ -1325,7 +1336,7 @@ Yul Control Flow Graph: { "in": [ "0x20", - "v94" + "v96" ], "op": "return", "out": [] @@ -1333,7 +1344,7 @@ Yul Control Flow Graph: ], "liveness": { "in": [ - "v95" + "v97" ], "out": [] }, @@ -1341,7 +1352,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v67", + "cond": "v69", "targets": [ "Block23", "Block22" @@ -1350,21 +1361,29 @@ Yul Control Flow Graph: }, "id": "Block20", "instructions": [ + { + "in": [ + "0x20" + ], + "out": [ + "v67" + ] + }, { "in": [], "op": "returndatasize", "out": [ - "v66" + "v68" ] }, { "in": [ - "v66", + "v68", "0x20" ], "op": "gt", "out": [ - "v67" + "v69" ] } ], @@ -1373,7 +1392,8 @@ Yul Control Flow Graph: "v46" ], "out": [ - "v46" + "v46", + "v67" ] }, "type": "BuiltinCall" @@ -1384,7 +1404,7 @@ Yul Control Flow Graph: "Block22" ], "exit": { - "cond": "v80", + "cond": "v82", "targets": [ "Block25", "Block24" @@ -1395,12 +1415,12 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "0x20", - "v68" + "v67", + "v70" ], "op": "PhiFunction", "out": [ - "v71" + "v73" ] }, { @@ -1409,79 +1429,79 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v70" + "v72" ] }, { "in": [ "0x1f", - "v71" + "v73" ], "op": "add", "out": [ - "v72" + "v74" ] }, { "in": [ - "v70", - "v72" + "v72", + "v74" ], "op": "and", "out": [ - "v73" + "v75" ] }, { "in": [ - "v73", + "v75", "v46" ], "op": "add", "out": [ - "v77" + "v79" ] }, { "in": [ "v46", - "v77" + "v79" ], "op": "lt", "out": [ - "v78" + "v80" ] }, { "in": [ "0xffffffffffffffff", - "v77" + "v79" ], "op": "gt", "out": [ - "v79" + "v81" ] }, { "in": [ - "v78", - "v79" + "v80", + "v81" ], "op": "or", "out": [ - "v80" + "v82" ] } ], "liveness": { "in": [ "v46", - "v71" + "v73" ], "out": [ "v46", - "v71", - "v77" + "v73", + "v79" ] }, "type": "BuiltinCall" @@ -1499,7 +1519,7 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v68" + "v70" ] } ], @@ -1509,14 +1529,14 @@ Yul Control Flow Graph: ], "out": [ "v46", - "v68" + "v70" ] }, "type": "BuiltinCall" }, { "exit": { - "cond": "v90", + "cond": "v92", "targets": [ "Block28", "Block27" @@ -1527,7 +1547,7 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v77", + "v79", "0x40" ], "op": "mstore", @@ -1535,40 +1555,40 @@ Yul Control Flow Graph: }, { "in": [ - "v71", + "v73", "v46" ], "op": "add", "out": [ - "v88" + "v90" ] }, { "in": [ "v46", - "v88" + "v90" ], "op": "sub", "out": [ - "v89" + "v91" ] }, { "in": [ "0x20", - "v89" + "v91" ], "op": "slt", "out": [ - "v90" + "v92" ] } ], "liveness": { "in": [ "v46", - "v71", - "v77" + "v73", + "v79" ], "out": [ "v46" @@ -1589,12 +1609,12 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v81" + "v83" ] }, { "in": [ - "v81", + "v83", "0x00" ], "op": "mstore", @@ -1638,7 +1658,7 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v93" + "v95" ] } ], @@ -1647,7 +1667,7 @@ Yul Control Flow Graph: "v46" ], "out": [ - "v93" + "v95" ] }, "type": "BuiltinCall" diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/SSAControlFlowGraphTest.cpp index d2acee7bc..087a79e97 100644 --- a/test/libyul/SSAControlFlowGraphTest.cpp +++ b/test/libyul/SSAControlFlowGraphTest.cpp @@ -73,7 +73,8 @@ TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::st std::unique_ptr controlFlow = SSAControlFlowGraphBuilder::build( *yulStack.parserResult()->analysisInfo, yulStack.dialect(), - yulStack.parserResult()->code()->root() + yulStack.parserResult()->code()->root(), + true ); ControlFlowLiveness liveness(*controlFlow); m_obtainedResult = controlFlow->toDot(&liveness); diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index 6fb0453c1..ecb1b7cfe 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -63,29 +63,30 @@ // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 17)\nLiveIn: v0,v1\l\ -// LiveOut: v0,v1\l\n"]; +// LiveOut: v0,v1,v4\l\nv4 := 42\l\ +// "]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1; (1, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nv5 := φ(\l\ -// Block 0 => 42,\l\ -// Block 21 => v43\l\ +// Block 1; (1, max 17)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6\l\nv6 := φ(\l\ +// Block 0 => v4,\l\ +// Block 21 => v44\l\ // )\l\ -// v6 := lt(v0, v5)\l\ +// v7 := lt(v0, v6)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_1Exit:0 -> Block1_4 [style="solid"]; // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2; (2, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ -// v8 := eq(0, v7)\l\ +// Block 2; (2, max 17)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6,v8\l\nv8 := mload(v6)\l\ +// v9 := eq(0, v8)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_2Exit:0 -> Block1_7 [style="solid"]; // Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ @@ -102,11 +103,11 @@ // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7; (5, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ +// Block 7; (5, max 17)\nLiveIn: v0,v1,v6,v8\l\ +// LiveOut: v0,v1,v6,v8\l\nv14 := eq(1, v8)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit [label="{ If v14 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_7Exit:0 -> Block1_10 [style="solid"]; // Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ @@ -116,11 +117,11 @@ // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10; (7, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ +// Block 10; (7, max 17)\nLiveIn: v0,v1,v6,v8\l\ +// LiveOut: v0,v1,v6,v8\l\nv21 := eq(2, v8)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit [label="{ If v21 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_10Exit:0 -> Block1_13 [style="solid"]; // Block1_10Exit:1 -> Block1_12 [style="solid"]; // Block1_12 [label="\ @@ -131,31 +132,31 @@ // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13; (9, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ +// Block 13; (9, max 17)\nLiveIn: v0,v1,v6,v8\l\ +// LiveOut: v0,v1,v6\l\nv26 := eq(3, v8)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit [label="{ If v26 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15; (10, max 14)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nsstore(2056, 8)\l\ +// Block 15; (10, max 14)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6\l\nsstore(2056, 8)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16; (15, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ +// Block 16; (15, max 17)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6\l\nv30 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v29 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit [label="{ If v30 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5; (11, max 14)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nsstore(2827, 11)\l\ +// Block 5; (11, max 14)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6\l\nsstore(2827, 11)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; @@ -167,30 +168,30 @@ // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18; (17, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nsstore(2570, 10)\l\ +// Block 18; (17, max 17)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6\l\nsstore(2570, 10)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3; (12, max 14)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ -// v44 := calldataload(v43)\l\ +// Block 3; (12, max 14)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v44\l\nv44 := add(1, v6)\l\ +// v45 := calldataload(v44)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v44 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit [label="{ If v45 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v43\l\ -// LiveOut: \l\nsstore(v43, 0)\l\ +// Block 20; (13, max 13)\nLiveIn: v44\l\ +// LiveOut: \l\nsstore(v44, 0)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v0,v1,v43\l\ -// LiveOut: v0,v1,v43\l\nsstore(65535, 255)\l\ +// Block 21; (14, max 14)\nLiveIn: v0,v1,v44\l\ +// LiveOut: v0,v1,v44\l\nsstore(65535, 255)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index c3ea8b94f..d4e8b432d 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -79,36 +79,38 @@ // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 17)\nLiveIn: v0,v1\l\ -// LiveOut: v0,v1\l\n"]; +// LiveOut: v0,v1,v4\l\nv4 := 42\l\ +// "]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1; (1, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nv5 := φ(\l\ -// Block 0 => 42,\l\ -// Block 21 => v43\l\ +// Block 1; (1, max 17)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6\l\nv6 := φ(\l\ +// Block 0 => v4,\l\ +// Block 21 => v44\l\ // )\l\ -// v6 := lt(v0, v5)\l\ +// v7 := lt(v0, v6)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_1Exit:0 -> Block1_4 [style="solid"]; // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2; (2, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5,v7\l\nv7 := mload(v5)\l\ -// v8 := eq(0, v7)\l\ +// Block 2; (2, max 17)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6,v8\l\nv8 := mload(v6)\l\ +// v9 := eq(0, v8)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_2Exit:0 -> Block1_7 [style="solid"]; // Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ // Block 4; (4, max 4)\nLiveIn: \l\ -// LiveOut: \l\nsstore(3084, 12)\l\ +// LiveOut: v78\l\nsstore(3084, 12)\l\ +// v78 := 27\l\ // "]; -// Block1_4Exit [label="FunctionReturn[27]"]; +// Block1_4Exit [label="FunctionReturn[v78]"]; // Block1_4 -> Block1_4Exit; // Block1_6 [label="\ // Block 6; (3, max 4)\nLiveIn: \l\ @@ -118,11 +120,11 @@ // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7; (5, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7\l\nv13 := eq(1, v7)\l\ +// Block 7; (5, max 17)\nLiveIn: v0,v1,v6,v8\l\ +// LiveOut: v0,v1,v6,v8\l\nv14 := eq(1, v8)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit [label="{ If v14 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_7Exit:0 -> Block1_10 [style="solid"]; // Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ @@ -132,11 +134,11 @@ // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10; (7, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5,v7\l\nv20 := eq(2, v7)\l\ +// Block 10; (7, max 17)\nLiveIn: v0,v1,v6,v8\l\ +// LiveOut: v0,v1,v6,v8\l\nv21 := eq(2, v8)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit [label="{ If v21 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_10Exit:0 -> Block1_13 [style="solid"]; // Block1_10Exit:1 -> Block1_12 [style="solid"]; // Block1_12 [label="\ @@ -147,31 +149,31 @@ // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13; (9, max 17)\nLiveIn: v0,v1,v5,v7\l\ -// LiveOut: v0,v1,v5\l\nv25 := eq(3, v7)\l\ +// Block 13; (9, max 17)\nLiveIn: v0,v1,v6,v8\l\ +// LiveOut: v0,v1,v6\l\nv26 := eq(3, v8)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit [label="{ If v26 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15; (10, max 14)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nsstore(2056, 8)\l\ +// Block 15; (10, max 14)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6\l\nsstore(2056, 8)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16; (15, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nv29 := mload(v1)\l\ +// Block 16; (15, max 17)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6\l\nv30 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v29 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit [label="{ If v30 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5; (11, max 14)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nsstore(2827, 11)\l\ +// Block 5; (11, max 14)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6\l\nsstore(2827, 11)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; @@ -183,30 +185,30 @@ // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18; (17, max 17)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v5\l\nsstore(2570, 10)\l\ +// Block 18; (17, max 17)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v6\l\nsstore(2570, 10)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3; (12, max 14)\nLiveIn: v0,v1,v5\l\ -// LiveOut: v0,v1,v43\l\nv43 := add(1, v5)\l\ -// v44 := calldataload(v43)\l\ +// Block 3; (12, max 14)\nLiveIn: v0,v1,v6\l\ +// LiveOut: v0,v1,v44\l\nv44 := add(1, v6)\l\ +// v45 := calldataload(v44)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v44 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit [label="{ If v45 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v43\l\ -// LiveOut: \l\nsstore(v43, 0)\l\ +// Block 20; (13, max 13)\nLiveIn: v44\l\ +// LiveOut: \l\nsstore(v44, 0)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v0,v1,v43\l\ -// LiveOut: v0,v1,v43\l\nsstore(65535, 255)\l\ +// Block 21; (14, max 14)\nLiveIn: v0,v1,v44\l\ +// LiveOut: v0,v1,v44\l\nsstore(65535, 255)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/yulSSAControlFlowGraph/function.yul index acf1a37aa..e2d8c1d52 100644 --- a/test/libyul/yulSSAControlFlowGraph/function.yul +++ b/test/libyul/yulSSAControlFlowGraph/function.yul @@ -67,7 +67,9 @@ // FunctionEntry_i_0 -> Block4_0; // Block4_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\n"]; -// Block4_0Exit [label="FunctionReturn[514, 771]"]; +// LiveOut: v2,v4\l\nv2 := 514\l\ +// v4 := 771\l\ +// "]; +// Block4_0Exit [label="FunctionReturn[v2, v4]"]; // Block4_0 -> Block4_0Exit; // } diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/yulSSAControlFlowGraph/nested_for.yul index b088e3b55..f57a5ca29 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_for.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_for.yul @@ -27,25 +27,27 @@ // Entry0 -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 24)\nLiveIn: \l\ -// LiveOut: \l\n"]; +// LiveOut: v1\l\nv1 := 0\l\ +// "]; // Block0_0 -> Block0_0Exit [arrowhead=none]; // Block0_0Exit [label="Jump" shape=oval]; // Block0_0Exit -> Block0_1 [style="solid"]; // Block0_1 [label="\ -// Block 1; (1, max 24)\nLiveIn: v2\l\ -// LiveOut: v2\l\nv2 := φ(\l\ -// Block 0 => 0,\l\ -// Block 3 => v36\l\ +// Block 1; (1, max 24)\nLiveIn: v3\l\ +// LiveOut: v3\l\nv3 := φ(\l\ +// Block 0 => v1,\l\ +// Block 3 => v41\l\ // )\l\ -// v3 := lt(3, v2)\l\ +// v4 := lt(3, v3)\l\ // "]; // Block0_1 -> Block0_1Exit; -// Block0_1Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_1Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_1Exit:0 -> Block0_4 [style="solid"]; // Block0_1Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2; (2, max 23)\nLiveIn: v2\l\ -// LiveOut: v2\l\n"]; +// Block 2; (2, max 23)\nLiveIn: v3\l\ +// LiveOut: v3,v5\l\nv5 := 0\l\ +// "]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; // Block0_2Exit -> Block0_5 [style="solid"]; @@ -55,164 +57,167 @@ // Block0_4Exit [label="MainExit"]; // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ -// Block 5; (3, max 23)\nLiveIn: v2,v4\l\ -// LiveOut: v2,v4\l\nv4 := φ(\l\ -// Block 2 => 0,\l\ -// Block 7 => v35\l\ +// Block 5; (3, max 23)\nLiveIn: v3,v6\l\ +// LiveOut: v3,v6\l\nv6 := φ(\l\ +// Block 2 => v5,\l\ +// Block 7 => v40\l\ // )\l\ -// v5 := lt(3, v4)\l\ +// v7 := lt(3, v6)\l\ // "]; // Block0_5 -> Block0_5Exit; -// Block0_5Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_5Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_5Exit:0 -> Block0_8 [style="solid"]; // Block0_5Exit:1 -> Block0_6 [style="solid"]; // Block0_6 [label="\ -// Block 6; (4, max 21)\nLiveIn: v2,v4\l\ -// LiveOut: v2,v4\l\n"]; +// Block 6; (4, max 21)\nLiveIn: v3,v6\l\ +// LiveOut: v3,v6,v8\l\nv8 := 0\l\ +// "]; // Block0_6 -> Block0_6Exit [arrowhead=none]; // Block0_6Exit [label="Jump" shape=oval]; // Block0_6Exit -> Block0_9 [style="solid"]; // Block0_8 [label="\ -// Block 8; (22, max 23)\nLiveIn: v2\l\ -// LiveOut: v2\l\n"]; +// Block 8; (22, max 23)\nLiveIn: v3\l\ +// LiveOut: v3\l\n"]; // Block0_8 -> Block0_8Exit [arrowhead=none]; // Block0_8Exit [label="Jump" shape=oval]; // Block0_8Exit -> Block0_3 [style="solid"]; // Block0_9 [label="\ -// Block 9; (5, max 21)\nLiveIn: v2,v4,v6\l\ -// LiveOut: v2,v4,v6\l\nv6 := φ(\l\ -// Block 6 => 0,\l\ -// Block 11 => v31\l\ +// Block 9; (5, max 21)\nLiveIn: v3,v6,v9\l\ +// LiveOut: v3,v6,v9\l\nv9 := φ(\l\ +// Block 6 => v8,\l\ +// Block 11 => v36\l\ // )\l\ -// v7 := lt(3, v6)\l\ +// v10 := lt(3, v9)\l\ // "]; // Block0_9 -> Block0_9Exit; -// Block0_9Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_9Exit [label="{ If v10 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_9Exit:0 -> Block0_12 [style="solid"]; // Block0_9Exit:1 -> Block0_10 [style="solid"]; // Block0_3 [label="\ -// Block 3; (23, max 23)\nLiveIn: v2\l\ -// LiveOut: v36\l\nv36 := add(1, v2)\l\ +// Block 3; (23, max 23)\nLiveIn: v3\l\ +// LiveOut: v41\l\nv41 := add(1, v3)\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; // Block0_3Exit -> Block0_1 [style="dashed"]; // Block0_10 [label="\ -// Block 10; (6, max 19)\nLiveIn: v2,v4,v6\l\ -// LiveOut: v2,v4,v6\l\n"]; +// Block 10; (6, max 19)\nLiveIn: v3,v6,v9\l\ +// LiveOut: v3,v6,v9\l\n"]; // Block0_10 -> Block0_10Exit; // Block0_10Exit [label="{ If 0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_10Exit:0 -> Block0_14 [style="solid"]; // Block0_10Exit:1 -> Block0_13 [style="solid"]; // Block0_12 [label="\ -// Block 12; (20, max 21)\nLiveIn: v2,v4\l\ -// LiveOut: v2,v4\l\n"]; +// Block 12; (20, max 21)\nLiveIn: v3,v6\l\ +// LiveOut: v3,v6\l\n"]; // Block0_12 -> Block0_12Exit [arrowhead=none]; // Block0_12Exit [label="Jump" shape=oval]; // Block0_12Exit -> Block0_7 [style="solid"]; // Block0_13 [label="\ -// Block 13; (7, max 19)\nLiveIn: v2,v4,v6\l\ -// LiveOut: v2,v4,v6\l\n"]; +// Block 13; (7, max 19)\nLiveIn: v3,v6,v9\l\ +// LiveOut: v3,v6,v9,v11\l\nv11 := 0\l\ +// "]; // Block0_13 -> Block0_13Exit [arrowhead=none]; // Block0_13Exit [label="Jump" shape=oval]; // Block0_13Exit -> Block0_15 [style="solid"]; // Block0_14 [label="\ -// Block 14; (12, max 19)\nLiveIn: v2,v4,v6\l\ -// LiveOut: v2,v4,v6\l\n"]; +// Block 14; (12, max 19)\nLiveIn: v3,v6,v9\l\ +// LiveOut: v3,v6,v9\l\n"]; // Block0_14 -> Block0_14Exit; // Block0_14Exit [label="{ If 1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_14Exit:0 -> Block0_20 [style="solid"]; // Block0_14Exit:1 -> Block0_19 [style="solid"]; // Block0_7 [label="\ -// Block 7; (21, max 21)\nLiveIn: v2,v4\l\ -// LiveOut: v2,v35\l\nv35 := add(1, v4)\l\ +// Block 7; (21, max 21)\nLiveIn: v3,v6\l\ +// LiveOut: v3,v40\l\nv40 := add(1, v6)\l\ // "]; // Block0_7 -> Block0_7Exit [arrowhead=none]; // Block0_7Exit [label="Jump" shape=oval]; // Block0_7Exit -> Block0_5 [style="dashed"]; // Block0_15 [label="\ -// Block 15; (8, max 19)\nLiveIn: v2,v4,v6,v8\l\ -// LiveOut: v2,v4,v6,v8\l\nv8 := φ(\l\ -// Block 13 => 0,\l\ -// Block 17 => v16\l\ +// Block 15; (8, max 19)\nLiveIn: v3,v6,v9,v12\l\ +// LiveOut: v3,v6,v9,v12\l\nv12 := φ(\l\ +// Block 13 => v11,\l\ +// Block 17 => v20\l\ // )\l\ -// v9 := lt(3, v8)\l\ +// v13 := lt(3, v12)\l\ // "]; // Block0_15 -> Block0_15Exit; -// Block0_15Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_15Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_15Exit:0 -> Block0_18 [style="solid"]; // Block0_15Exit:1 -> Block0_16 [style="solid"]; // Block0_19 [label="\ -// Block 19; (13, max 19)\nLiveIn: v2,v4,v6\l\ -// LiveOut: v2,v4,v6\l\n"]; +// Block 19; (13, max 19)\nLiveIn: v3,v6,v9\l\ +// LiveOut: v3,v6,v9,v23\l\nv23 := 0\l\ +// "]; // Block0_19 -> Block0_19Exit [arrowhead=none]; // Block0_19Exit [label="Jump" shape=oval]; // Block0_19Exit -> Block0_21 [style="solid"]; // Block0_20 [label="\ -// Block 20; (18, max 19)\nLiveIn: v2,v4,v6\l\ -// LiveOut: v2,v4,v6\l\n"]; +// Block 20; (18, max 19)\nLiveIn: v3,v6,v9\l\ +// LiveOut: v3,v6,v9\l\n"]; // Block0_20 -> Block0_20Exit [arrowhead=none]; // Block0_20Exit [label="Jump" shape=oval]; // Block0_20Exit -> Block0_11 [style="solid"]; // Block0_16 [label="\ -// Block 16; (9, max 10)\nLiveIn: v2,v4,v6,v8\l\ -// LiveOut: v2,v4,v6,v8\l\nv13 := add(v4, v2)\l\ -// v14 := add(v6, v13)\l\ -// sstore(v14, v8)\l\ +// Block 16; (9, max 10)\nLiveIn: v3,v6,v9,v12\l\ +// LiveOut: v3,v6,v9,v12\l\nv17 := add(v6, v3)\l\ +// v18 := add(v9, v17)\l\ +// sstore(v18, v12)\l\ // "]; // Block0_16 -> Block0_16Exit [arrowhead=none]; // Block0_16Exit [label="Jump" shape=oval]; // Block0_16Exit -> Block0_17 [style="solid"]; // Block0_18 [label="\ -// Block 18; (11, max 19)\nLiveIn: v2,v4,v6\l\ -// LiveOut: v2,v4,v6\l\n"]; +// Block 18; (11, max 19)\nLiveIn: v3,v6,v9\l\ +// LiveOut: v3,v6,v9\l\n"]; // Block0_18 -> Block0_18Exit [arrowhead=none]; // Block0_18Exit [label="Jump" shape=oval]; // Block0_18Exit -> Block0_14 [style="solid"]; // Block0_21 [label="\ -// Block 21; (14, max 19)\nLiveIn: v2,v4,v6,v19\l\ -// LiveOut: v2,v4,v6,v19\l\nv19 := φ(\l\ -// Block 19 => 0,\l\ -// Block 23 => v26\l\ +// Block 21; (14, max 19)\nLiveIn: v3,v6,v9,v24\l\ +// LiveOut: v3,v6,v9,v24\l\nv24 := φ(\l\ +// Block 19 => v23,\l\ +// Block 23 => v31\l\ // )\l\ -// v20 := lt(3, v19)\l\ +// v25 := lt(3, v24)\l\ // "]; // Block0_21 -> Block0_21Exit; -// Block0_21Exit [label="{ If v20 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_21Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_21Exit:0 -> Block0_24 [style="solid"]; // Block0_21Exit:1 -> Block0_22 [style="solid"]; // Block0_11 [label="\ -// Block 11; (19, max 19)\nLiveIn: v2,v4,v6\l\ -// LiveOut: v2,v4,v31\l\nv31 := add(1, v6)\l\ +// Block 11; (19, max 19)\nLiveIn: v3,v6,v9\l\ +// LiveOut: v3,v6,v36\l\nv36 := add(1, v9)\l\ // "]; // Block0_11 -> Block0_11Exit [arrowhead=none]; // Block0_11Exit [label="Jump" shape=oval]; // Block0_11Exit -> Block0_9 [style="dashed"]; // Block0_17 [label="\ -// Block 17; (10, max 10)\nLiveIn: v2,v4,v6,v8\l\ -// LiveOut: v2,v4,v6,v16\l\nv16 := add(1, v8)\l\ +// Block 17; (10, max 10)\nLiveIn: v3,v6,v9,v12\l\ +// LiveOut: v3,v6,v9,v20\l\nv20 := add(1, v12)\l\ // "]; // Block0_17 -> Block0_17Exit [arrowhead=none]; // Block0_17Exit [label="Jump" shape=oval]; // Block0_17Exit -> Block0_15 [style="dashed"]; // Block0_22 [label="\ -// Block 22; (15, max 16)\nLiveIn: v2,v4,v6,v19\l\ -// LiveOut: v2,v4,v6,v19\l\nv24 := add(v4, v2)\l\ -// v25 := add(v6, v24)\l\ -// sstore(v25, v19)\l\ +// Block 22; (15, max 16)\nLiveIn: v3,v6,v9,v24\l\ +// LiveOut: v3,v6,v9,v24\l\nv29 := add(v6, v3)\l\ +// v30 := add(v9, v29)\l\ +// sstore(v30, v24)\l\ // "]; // Block0_22 -> Block0_22Exit [arrowhead=none]; // Block0_22Exit [label="Jump" shape=oval]; // Block0_22Exit -> Block0_23 [style="solid"]; // Block0_24 [label="\ -// Block 24; (17, max 19)\nLiveIn: v2,v4,v6\l\ -// LiveOut: v2,v4,v6\l\n"]; +// Block 24; (17, max 19)\nLiveIn: v3,v6,v9\l\ +// LiveOut: v3,v6,v9\l\n"]; // Block0_24 -> Block0_24Exit [arrowhead=none]; // Block0_24Exit [label="Jump" shape=oval]; // Block0_24Exit -> Block0_20 [style="solid"]; // Block0_23 [label="\ -// Block 23; (16, max 16)\nLiveIn: v2,v4,v6,v19\l\ -// LiveOut: v2,v4,v6,v26\l\nv26 := add(1, v19)\l\ +// Block 23; (16, max 16)\nLiveIn: v3,v6,v9,v24\l\ +// LiveOut: v3,v6,v9,v31\l\nv31 := add(1, v24)\l\ // "]; // Block0_23 -> Block0_23Exit [arrowhead=none]; // Block0_23Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/nested_function.yul b/test/libyul/yulSSAControlFlowGraph/nested_function.yul index acda15ce8..037e1f006 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_function.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_function.yul @@ -78,8 +78,9 @@ // FunctionEntry_w_0 -> Block4_0; // Block4_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\n"]; -// Block4_0Exit [label="FunctionReturn[1]"]; +// LiveOut: v2\l\nv2 := 1\l\ +// "]; +// Block4_0Exit [label="FunctionReturn[v2]"]; // Block4_0 -> Block4_0Exit; // FunctionEntry_v_0 [label="function v: // r := v()"]; @@ -95,8 +96,9 @@ // FunctionEntry_w_0 -> Block6_0; // Block6_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\n"]; -// Block6_0Exit [label="FunctionReturn[17]"]; +// LiveOut: v2\l\nv2 := 17\l\ +// "]; +// Block6_0Exit [label="FunctionReturn[v2]"]; // Block6_0 -> Block6_0Exit; // FunctionEntry_cycle1_0 [label="function cycle1: // r := cycle1()"]; From fe890f4d519677c1b49ac5e2cd62d19e7bc2a01c Mon Sep 17 00:00:00 2001 From: fhf <710790342@qq.com> Date: Mon, 28 Apr 2025 21:33:44 +0800 Subject: [PATCH 0868/1340] update docs: fix the position of flyout menu --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 11765d3be..73295404d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -86,7 +86,7 @@ Community contributors help translate this documentation into several languages. Note that they have varying degrees of completeness and up-to-dateness. The English version stands as a reference. -You can switch between languages by clicking on the flyout menu in the bottom-left corner +You can switch between languages by clicking on the flyout menu in the bottom-right corner and selecting the preferred language. * `Chinese `_ From e0daa3c05df3fa2b921362fa4161aaa40530b84d Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 13 May 2025 11:47:04 +0200 Subject: [PATCH 0869/1340] assign zero value to not explicitly initialized variables during ssa cfg construction --- .../evm/SSAControlFlowGraphBuilder.cpp | 5 --- .../default_initialized_variable.yul | 42 +++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 19308617c..101fd2eb3 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -273,11 +273,6 @@ void SSAControlFlowGraphBuilder::operator()(Assignment const& _assignment) void SSAControlFlowGraphBuilder::operator()(VariableDeclaration const& _variableDeclaration) { - // if we have no value (like in `let a` without right-hand side), we can just skip this. the variable(s) will be - // added when first needed - if (!_variableDeclaration.value) - return; - assign( _variableDeclaration.variables | ranges::views::transform([&](auto& _var) { return std::ref(lookupVariable(_var.name)); }) | ranges::to, _variableDeclaration.value.get() diff --git a/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul b/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul new file mode 100644 index 000000000..92ea33382 --- /dev/null +++ b/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul @@ -0,0 +1,42 @@ +{ + let x + if mload(42) { + x := 5 + } + sstore(x, x) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans"] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry0 [label="Entry"]; +// Entry0 -> Block0_0; +// Block0_0 [label="\ +// Block 0; (0, max 2)\nLiveIn: \l\ +// LiveOut: v1\l\nv1 := 0\l\ +// v3 := mload(42)\l\ +// "]; +// Block0_0 -> Block0_0Exit; +// Block0_0Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit:0 -> Block0_2 [style="solid"]; +// Block0_0Exit:1 -> Block0_1 [style="solid"]; +// Block0_1 [label="\ +// Block 1; (1, max 2)\nLiveIn: \l\ +// LiveOut: v5\l\nv5 := 5\l\ +// "]; +// Block0_1 -> Block0_1Exit [arrowhead=none]; +// Block0_1Exit [label="Jump" shape=oval]; +// Block0_1Exit -> Block0_2 [style="solid"]; +// Block0_2 [label="\ +// Block 2; (2, max 2)\nLiveIn: v6\l\ +// LiveOut: \l\nv6 := φ(\l\ +// Block 0 => v1,\l\ +// Block 1 => v5\l\ +// )\l\ +// sstore(v6, v6)\l\ +// "]; +// Block0_2Exit [label="MainExit"]; +// Block0_2 -> Block0_2Exit; +// } From 27c16d0734a09f67c001c1f8b746ae78b6a1f7cd Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 14 May 2025 10:33:41 +0200 Subject: [PATCH 0870/1340] update fmtlib to 11.2.0 --- deps/fmtlib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/fmtlib b/deps/fmtlib index 123913715..40626af88 160000 --- a/deps/fmtlib +++ b/deps/fmtlib @@ -1 +1 @@ -Subproject commit 123913715afeb8a437e6388b4473fcc4753e1c9a +Subproject commit 40626af88bd7df9a5fb80be7b25ac85b122d6c21 From 287b66a15e37a35e859f93018b7d0a87dd45d1c7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:18:53 +0200 Subject: [PATCH 0871/1340] Add instruction location info to eof assembly --- libevmasm/Assembly.cpp | 64 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 9dd203a0f..670165a0b 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -53,6 +53,54 @@ using namespace solidity::evmasm; using namespace solidity::langutil; using namespace solidity::util; +namespace +{ + +/// Produces instruction location info in RAII style. When an assembly instruction is added to the bytecode, +/// this class can be instantiated in that scope. It will record the current bytecode size (before addition) +/// and, at destruction time, record the new bytecode size. This information is then added to an external +/// instruction locations vector. +/// If the instruction decomposes into multiple individual evm instructions, `emit` can be +/// called for all but the last one (which will be emitted by the destructor). +class InstructionLocationEmitter +{ +public: + InstructionLocationEmitter( + std::vector& _instructionLocations, + bytes const& _bytecode, + size_t const _assemblyItemIndex + ): + m_instructionLocations(_instructionLocations), + m_bytecode(_bytecode), + m_assemblyItemIndex(_assemblyItemIndex), + m_instructionLocationStart(_bytecode.size()) + {} + + ~InstructionLocationEmitter() + { + emit(); + } + + void emit() + { + auto const end = m_bytecode.size(); + m_instructionLocations.push_back(LinkerObject::InstructionLocation{ + .start = m_instructionLocationStart, + .end = end, + .assemblyItemIndex = m_assemblyItemIndex + }); + m_instructionLocationStart = end; + } + +private: + std::vector& m_instructionLocations; + bytes const& m_bytecode; + size_t const m_assemblyItemIndex{}; + size_t m_instructionLocationStart{}; +}; + +} + std::map> Assembly::s_sharedSourceNames; AssemblyItem const& Assembly::append(AssemblyItem _i) @@ -1606,9 +1654,17 @@ LinkerObject const& Assembly::assembleEOF() const for (auto&& [codeSectionIndex, codeSection]: m_codeSections | ranges::views::enumerate) { auto const sectionStart = ret.bytecode.size(); + + std::vector instructionLocations; + instructionLocations.reserve(codeSection.items.size()); + solAssert(!codeSection.items.empty(), "Empty code section."); - for (AssemblyItem const& item: codeSection.items) + + for (auto const& [assemblyItemIndex, item]: codeSection.items | ranges::views::enumerate) { + // collect instruction locations via side effects + InstructionLocationEmitter instructionLocationEmitter {instructionLocations, ret.bytecode, assemblyItemIndex}; + // store position of the invalid jump destination if (item.type() != Tag && m_tagPositionsInBytecode[0] == std::numeric_limits::max()) m_tagPositionsInBytecode[0] = ret.bytecode.size(); @@ -1724,6 +1780,12 @@ LinkerObject const& Assembly::assembleEOF() const "Code section too large for EOF." ); setBigEndianUint16(ret.bytecode, codeSectionSizePositions[codeSectionIndex], ret.bytecode.size() - sectionStart); + + ret.codeSectionLocations.push_back(LinkerObject::CodeSectionLocation{ + .start = sectionStart, + .end = ret.bytecode.size(), + .instructionLocations = std::move(instructionLocations) + }); } for (auto const& [refPos, tagId]: tagRef) From a5e20d2dc05b42f27bb0fe1092502b1a799a014c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 10 Apr 2025 10:54:11 +0200 Subject: [PATCH 0872/1340] Refactor legacy assemble to also use RAII instruction location construction --- libevmasm/Assembly.cpp | 158 +++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 101 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 670165a0b..019683c9d 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -1329,22 +1329,12 @@ LinkerObject const& Assembly::assembleLegacy() const uint8_t dataRefPush = static_cast(pushInstruction(bytesPerDataRef)); LinkerObject::CodeSectionLocation codeSectionLocation; + codeSectionLocation.instructionLocations.reserve(items.size()); codeSectionLocation.start = 0; - size_t assemblyItemIndex = 0; - auto assembleInstruction = [&](auto&& _addInstruction) { - size_t start = ret.bytecode.size(); - _addInstruction(); - size_t end = ret.bytecode.size(); - codeSectionLocation.instructionLocations.emplace_back( - LinkerObject::InstructionLocation{ - .start = start, - .end = end, - .assemblyItemIndex = assemblyItemIndex - } - ); - }; - for (AssemblyItem const& item: items) + for (auto const& [assemblyItemIndex, item]: items | ranges::views::enumerate) { + // collect instruction locations via side effects + InstructionLocationEmitter instructionLocationEmitter(codeSectionLocation.instructionLocations, ret.bytecode, assemblyItemIndex); // store position of the invalid jump destination if (item.type() != Tag && m_tagPositionsInBytecode[0] == std::numeric_limits::max()) m_tagPositionsInBytecode[0] = ret.bytecode.size(); @@ -1352,81 +1342,59 @@ LinkerObject const& Assembly::assembleLegacy() const switch (item.type()) { case Operation: - assembleInstruction([&](){ - ret.bytecode += assembleOperation(item); - }); + ret.bytecode += assembleOperation(item); break; case Push: - assembleInstruction([&](){ - ret.bytecode += assemblePush(item); - }); + ret.bytecode += assemblePush(item); break; case PushTag: - { - assembleInstruction([&](){ - ret.bytecode.push_back(tagPush); - tagRefs[ret.bytecode.size()] = item.splitForeignPushTag(); - ret.bytecode.resize(ret.bytecode.size() + bytesPerTag); - }); + ret.bytecode.push_back(tagPush); + tagRefs[ret.bytecode.size()] = item.splitForeignPushTag(); + ret.bytecode.resize(ret.bytecode.size() + bytesPerTag); break; - } case PushData: - assembleInstruction([&]() { - ret.bytecode.push_back(dataRefPush); - dataRefs.insert(std::make_pair(h256(item.data()), ret.bytecode.size())); - ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); - }); + ret.bytecode.push_back(dataRefPush); + dataRefs.insert(std::make_pair(h256(item.data()), ret.bytecode.size())); + ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); break; case PushSub: - assembleInstruction([&]() { - assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); - ret.bytecode.push_back(dataRefPush); - subRefs.insert(std::make_pair(static_cast(item.data()), ret.bytecode.size())); - ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); - }); + assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); + ret.bytecode.push_back(dataRefPush); + subRefs.insert(std::make_pair(static_cast(item.data()), ret.bytecode.size())); + ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); break; case PushSubSize: { - assembleInstruction([&](){ - assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); - auto s = subAssemblyById(static_cast(item.data()))->assemble().bytecode.size(); - item.setPushedValue(u256(s)); - unsigned b = std::max(1, numberEncodingSize(s)); - ret.bytecode.push_back(static_cast(pushInstruction(b))); - ret.bytecode.resize(ret.bytecode.size() + b); - bytesRef byr(&ret.bytecode.back() + 1 - b, b); - toBigEndian(s, byr); - }); + assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); + auto s = subAssemblyById(static_cast(item.data()))->assemble().bytecode.size(); + item.setPushedValue(u256(s)); + unsigned b = std::max(1, numberEncodingSize(s)); + ret.bytecode.push_back(static_cast(pushInstruction(b))); + ret.bytecode.resize(ret.bytecode.size() + b); + bytesRef byr(&ret.bytecode.back() + 1 - b, b); + toBigEndian(s, byr); break; } case PushProgramSize: - { - assembleInstruction([&](){ - ret.bytecode.push_back(dataRefPush); - sizeRefs.push_back(static_cast(ret.bytecode.size())); - ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); - }); + ret.bytecode.push_back(dataRefPush); + sizeRefs.push_back(static_cast(ret.bytecode.size())); + ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); break; - } case PushLibraryAddress: { - assembleInstruction([&]() { - auto const [bytecode, linkRef] = assemblePushLibraryAddress(item, ret.bytecode.size()); - ret.bytecode += bytecode; - ret.linkReferences.insert(linkRef); - }); + auto const [bytecode, linkRef] = assemblePushLibraryAddress(item, ret.bytecode.size()); + ret.bytecode += bytecode; + ret.linkReferences.insert(linkRef); break; } case PushImmutable: - assembleInstruction([&]() { - ret.bytecode.push_back(static_cast(Instruction::PUSH32)); - // Maps keccak back to the "identifier" std::string of that immutable. - ret.immutableReferences[item.data()].first = m_immutables.at(item.data()); - // Record the bytecode offset of the PUSH32 argument. - ret.immutableReferences[item.data()].second.emplace_back(ret.bytecode.size()); - // Advance bytecode by 32 bytes (default initialized). - ret.bytecode.resize(ret.bytecode.size() + 32); - }); + ret.bytecode.push_back(static_cast(Instruction::PUSH32)); + // Maps keccak back to the "identifier" std::string of that immutable. + ret.immutableReferences[item.data()].first = m_immutables.at(item.data()); + // Record the bytecode offset of the PUSH32 argument. + ret.immutableReferences[item.data()].second.emplace_back(ret.bytecode.size()); + // Advance bytecode by 32 bytes (default initialized). + ret.bytecode.resize(ret.bytecode.size() + 32); break; case VerbatimBytecode: ret.bytecode += assembleVerbatimBytecode(item); @@ -1439,53 +1407,41 @@ LinkerObject const& Assembly::assembleLegacy() const { if (i != offsets.size() - 1) { - assembleInstruction([&]() { - ret.bytecode.push_back(uint8_t(Instruction::DUP2)); - }); - assembleInstruction([&]() { - ret.bytecode.push_back(uint8_t(Instruction::DUP2)); - }); + ret.bytecode.push_back(static_cast(Instruction::DUP2)); + // This item type decomposes into multiple evm instructions, so we manually call emit() + instructionLocationEmitter.emit(); + ret.bytecode.push_back(static_cast(Instruction::DUP2)); + instructionLocationEmitter.emit(); } - assembleInstruction([&]() { - // TODO: should we make use of the constant optimizer methods for pushing the offsets? - bytes offsetBytes = toCompactBigEndian(u256(offsets[i])); - ret.bytecode.push_back(static_cast(pushInstruction(static_cast(offsetBytes.size())))); - ret.bytecode += offsetBytes; - }); - assembleInstruction([&]() { - ret.bytecode.push_back(uint8_t(Instruction::ADD)); - }); - assembleInstruction([&]() { - ret.bytecode.push_back(uint8_t(Instruction::MSTORE)); - }); + // TODO: should we make use of the constant optimizer methods for pushing the offsets? + bytes offsetBytes = toCompactBigEndian(u256(offsets[i])); + ret.bytecode.push_back(static_cast(pushInstruction(static_cast(offsetBytes.size())))); + ret.bytecode += offsetBytes; + instructionLocationEmitter.emit(); + ret.bytecode.push_back(static_cast(Instruction::ADD)); + instructionLocationEmitter.emit(); + ret.bytecode.push_back(static_cast(Instruction::MSTORE)); + // No emit needed here, it's taken care of by the destructor of instructionLocationEmitter. } if (offsets.empty()) { - assembleInstruction([&]() { - ret.bytecode.push_back(uint8_t(Instruction::POP)); - }); - assembleInstruction([&]() { - ret.bytecode.push_back(uint8_t(Instruction::POP)); - }); + ret.bytecode.push_back(static_cast(Instruction::POP)); + instructionLocationEmitter.emit(); + ret.bytecode.push_back(static_cast(Instruction::POP)); + // no emit needed here, it's taken care of by the destructor of instructionLocationEmitter } immutableReferencesBySub.erase(item.data()); break; } case PushDeployTimeAddress: - assembleInstruction([&]() { - ret.bytecode += assemblePushDeployTimeAddress(); - }); + ret.bytecode += assemblePushDeployTimeAddress(); break; case Tag: - assembleInstruction([&](){ - ret.bytecode += assembleTag(item, ret.bytecode.size(), true); - }); + ret.bytecode += assembleTag(item, ret.bytecode.size(), true); break; default: solAssert(false, "Unexpected opcode while assembling."); } - - ++assemblyItemIndex; } codeSectionLocation.end = ret.bytecode.size(); From 6ae63c268c1b3ce94aa9230f40bf24f465cb6a8f Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Wed, 14 May 2025 15:26:37 -0300 Subject: [PATCH 0873/1340] Mention that dots are still allowed in variables/function names in yul-only mode --- docs/assembly.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/assembly.rst b/docs/assembly.rst index c1af2907a..3f00ab6a8 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -216,6 +216,7 @@ shadow any declaration visible in the scope of the inline assembly block Since Solidity 0.7.0, variables and functions declared inside the inline assembly block may not contain ``.``, but using ``.`` is valid to access Solidity variables from outside the inline assembly block. +However, it is still valid to use dots if you use Solidity in Yul-only mode. Things to Avoid --------------- From 54979c198c2519611d8491afd8fd41b8a588da05 Mon Sep 17 00:00:00 2001 From: Henry Chu Date: Tue, 20 May 2025 12:36:43 +0800 Subject: [PATCH 0874/1340] Add nullptr checking for rename logging --- libsolidity/lsp/RenameSymbol.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libsolidity/lsp/RenameSymbol.cpp b/libsolidity/lsp/RenameSymbol.cpp index 497ee50fb..b832029e4 100644 --- a/libsolidity/lsp/RenameSymbol.cpp +++ b/libsolidity/lsp/RenameSymbol.cpp @@ -65,7 +65,8 @@ void RenameSymbol::operator()(MessageID _id, Json const& _args) .translateLineColumnToPosition(lineColumn); solAssert(cursorBytePosition.has_value(), "Expected source pos"); - extractNameAndDeclaration(*sourceNode, *cursorBytePosition); + if (sourceNode != nullptr) + extractNameAndDeclaration(*sourceNode, *cursorBytePosition); // Find all source units using this symbol for (auto const& [name, content]: fileRepository().sourceUnits()) @@ -156,7 +157,8 @@ void RenameSymbol::extractNameAndDeclaration(ASTNode const& _node, int _cursorBy else solAssert(false, "Unexpected ASTNODE id: " + std::to_string(_node.id())); - lspDebug(fmt::format("Goal: rename '{}', loc: {}-{}", m_symbolName, m_declarationToRename->nameLocation().start, m_declarationToRename->nameLocation().end)); + if (m_declarationToRename != nullptr) + lspDebug(fmt::format("Goal: rename '{}', loc: {}-{}", m_symbolName, m_declarationToRename->nameLocation().start, m_declarationToRename->nameLocation().end)); } void RenameSymbol::extractNameAndDeclaration(ImportDirective const& _importDirective, int _cursorBytePosition) From 446610b6db27e16517fb51a18bd99d79e0463ae1 Mon Sep 17 00:00:00 2001 From: James Niken Date: Thu, 22 May 2025 21:19:48 +0200 Subject: [PATCH 0875/1340] Replace Reference StandardCompiler.cpp --- test/libsolidity/StandardCompiler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 5360a2778..62c72ad45 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -822,7 +822,7 @@ BOOST_AUTO_TEST_CASE(filename_with_colon) "language": "Solidity", "settings": { "outputSelection": { - "http://github.com/ethereum/solidity/std/StandardToken.sol": { + "https://github.com/ethereum/solidity/blob/develop/test/compilationTests/gnosis/Tokens/StandardToken.sol": { "A": [ "abi" ] @@ -830,7 +830,7 @@ BOOST_AUTO_TEST_CASE(filename_with_colon) } }, "sources": { - "http://github.com/ethereum/solidity/std/StandardToken.sol": { + "https://github.com/ethereum/solidity/blob/develop/test/compilationTests/gnosis/Tokens/StandardToken.sol": { "content": "contract A { }" } } @@ -838,7 +838,7 @@ BOOST_AUTO_TEST_CASE(filename_with_colon) )"; Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json contract = getContractResult(result, "http://github.com/ethereum/solidity/std/StandardToken.sol", "A"); + Json contract = getContractResult(result, "https://github.com/ethereum/solidity/blob/develop/test/compilationTests/gnosis/Tokens/StandardToken.sol", "A"); BOOST_CHECK(contract.is_object()); BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); From e96a23725afa6bd7bfb09d0f4f134ab8ae705444 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 7 Feb 2025 12:00:36 +0100 Subject: [PATCH 0876/1340] Yul: add label id dispenser --- libyul/CMakeLists.txt | 2 + libyul/optimiser/LabelIDDispenser.cpp | 167 ++++++++++++++++++++++++++ libyul/optimiser/LabelIDDispenser.h | 73 +++++++++++ 3 files changed, 242 insertions(+) create mode 100644 libyul/optimiser/LabelIDDispenser.cpp create mode 100644 libyul/optimiser/LabelIDDispenser.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index fc3302a82..68756fca9 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -145,6 +145,8 @@ add_library(yul optimiser/InlinableExpressionFunctionFinder.h optimiser/KnowledgeBase.cpp optimiser/KnowledgeBase.h + optimiser/LabelIDDispenser.cpp + optimiser/LabelIDDispenser.h optimiser/LoadResolver.cpp optimiser/LoadResolver.h optimiser/LoopInvariantCodeMotion.cpp diff --git a/libyul/optimiser/LabelIDDispenser.cpp b/libyul/optimiser/LabelIDDispenser.cpp new file mode 100644 index 000000000..6d4e476cb --- /dev/null +++ b/libyul/optimiser/LabelIDDispenser.cpp @@ -0,0 +1,167 @@ +/* + 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 + +#include + +#include + +#include + +#include +#include +#include + +using namespace solidity::yul; + +namespace +{ +bool isInvalidLabel( + std::string_view const _label, + std::set> const& _reservedLabels, + Dialect const& _dialect +) +{ + return isRestrictedIdentifier(_dialect, _label) || _reservedLabels.contains(_label); +} +} + +LabelIDDispenser::LabelIDDispenser(ASTLabelRegistry const& _labels, std::set const& _reservedLabels): + m_labels(_labels), + m_reservedLabels(_reservedLabels.begin(), _reservedLabels.end()) +{} + +LabelIDDispenser::LabelID LabelIDDispenser::newID(LabelID const _parent) +{ + auto const parentLabelID = resolveParentLabelID(_parent); + yulAssert(!m_labels.ghost(parentLabelID), "Use newGhost to add new ghosts."); + m_idToLabelMapping.push_back(parentLabelID); + return m_idToLabelMapping.size() + m_labels.maxID(); +} + +LabelIDDispenser::LabelID LabelIDDispenser::newGhost() +{ + m_idToLabelMapping.push_back(ASTLabelRegistry::ghostLabelIndex()); + return m_idToLabelMapping.size() + m_labels.maxID(); +} + +LabelIDDispenser::LabelID LabelIDDispenser::resolveParentLabelID(LabelID _id) const +{ + yulAssert(_id < m_idToLabelMapping.size() + m_labels.maxID() + 1, "ID exceeds bounds."); + // bigger than maxID means that the input label id was spawned by this dispenser + if (_id > m_labels.maxID()) + _id = m_idToLabelMapping[_id - m_labels.maxID() - 1]; + yulAssert( + _id <= m_labels.maxID() && !m_labels.unused(_id), + "We can have at most one level of indirection and the derived-from label cannot be unused." + ); + return _id; +} + +bool LabelIDDispenser::ghost(LabelID const _id) const +{ + yulAssert(_id < m_idToLabelMapping.size() + m_labels.maxID() + 1, "ID exceeds bounds."); + if (_id > m_labels.maxID()) + return m_idToLabelMapping[_id - m_labels.maxID() - 1] == ASTLabelRegistry::ghostLabelIndex(); + + return m_labels.ghost(_id); +} + +ASTLabelRegistry LabelIDDispenser::generateNewLabels(Dialect const& _dialect) const +{ + auto const usedIDs = + ranges::views::iota(static_cast(1), m_idToLabelMapping.size() + m_labels.maxID() + 1) | + ranges::to; + return generateNewLabels(usedIDs, _dialect); +} + +ASTLabelRegistry LabelIDDispenser::generateNewLabels(std::set const& _usedIDs, Dialect const& _dialect) const +{ + if (_usedIDs.empty()) + return {}; + + auto const& originalLabels = m_labels.labels(); + + std::vector reusedLabels (originalLabels.size()); + // this means that everything that is derived from empty needs to be generated + reusedLabels[0] = true; + + // start with the empty label + std::vector labels{""}; + labels.reserve(originalLabels.size()+1); + + // 0 maps to "" + yulAssert(!_usedIDs.empty()); + std::vector idToLabelMap (*std::prev(_usedIDs.end()) + 1); + + std::set> alreadyDefinedLabels = m_reservedLabels; + + // we record which labels have to be newly generated, some we can just take over from the existing registry + std::vector toGenerate; + for (auto const& id: _usedIDs) + { + if (ghost(id)) + { + idToLabelMap[id] = ASTLabelRegistry::ghostLabelIndex(); + continue; + } + + auto const parentLabelID = resolveParentLabelID(id); + + auto const originalLabelIndex = m_labels.idToLabelIndex(parentLabelID); + std::string const& originalLabel = originalLabels[originalLabelIndex]; + + // It is important that the used ids are in ascending order to ensure that ids which occur in the provided AST + // and have unchanged IDs will have their labels reused first, before anything derived from it gets assigned + // said label. + static_assert(std::is_same_v, std::set>); + + // if we haven't already reused the label, check that either the id didn't change, then we can just + // take over the old label, otherwise check that it is a valid label and then reuse + if (!reusedLabels[originalLabelIndex] && (parentLabelID == id || !isInvalidLabel(originalLabel, m_reservedLabels, _dialect))) + { + labels.push_back(originalLabel); + idToLabelMap[id] = labels.size() - 1; + alreadyDefinedLabels.insert(originalLabel); + reusedLabels[originalLabelIndex] = true; + } + else + toGenerate.push_back(id); + } + + std::vector labelSuffixes(m_labels.maxID() + 1, 1); + for (auto const& id: toGenerate) + { + yulAssert(!ghost(id)); + + auto const parentLabelID = resolveParentLabelID(id); + auto const parentLabelIndex = m_labels.idToLabelIndex(parentLabelID); + auto const& parentLabel = originalLabels[parentLabelIndex]; + + std::string generatedLabel = parentLabel; + do + { + generatedLabel = format(FMT_COMPILE("{}_{}"), parentLabel, labelSuffixes[parentLabelID]++); + } while (isInvalidLabel(generatedLabel, alreadyDefinedLabels, _dialect)); + + labels.push_back(generatedLabel); + idToLabelMap[id] = labels.size() - 1; + alreadyDefinedLabels.insert(generatedLabel); + } + + return ASTLabelRegistry{std::move(labels), std::move(idToLabelMap)}; +} diff --git a/libyul/optimiser/LabelIDDispenser.h b/libyul/optimiser/LabelIDDispenser.h new file mode 100644 index 000000000..0168fadcf --- /dev/null +++ b/libyul/optimiser/LabelIDDispenser.h @@ -0,0 +1,73 @@ +/* + 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 + +#pragma once + +#include + +#include +#include + +namespace solidity::yul +{ + +class Dialect; + +/// Can spawn new `LabelID`s which depend on `LabelID`s from a parent label registry. Once generation is completed, +/// a new `ASTLabelRegistry` can be generated based on the used subset of spawned and original IDs. +class LabelIDDispenser +{ +public: + using LabelID = ASTLabelRegistry::LabelID; + /// A set of reserved labels may be provided, which is excluded when generating new labels. If a reserved label + /// already appears in the label registry and is used as-is in the AST, it will be reused despite it being + /// provided here. + /// Original labels will always be preserved even if they are not valid Yul identifiers. + explicit LabelIDDispenser( + ASTLabelRegistry const& _labels, + std::set const& _reserved = {} + ); + + ASTLabelRegistry const& labels() const { return m_labels; } + + /// Spawns a new LabelID which depends on a parent LabelID that will be used for its string representation. + /// Parent must not be unused. For spawning new ghost labels, `newGhost` must be used. + LabelID newID(LabelID _parent = 0); + /// Spawns a new ghost label. + LabelID newGhost(); + + /// Creates a new label registry based on the added labels. + /// Ghost IDs are always preserved, as these are not referenced in the AST. + /// Labels are guaranteed to be valid and not reserved if and only if they were valid and not reserved in the + /// original registry. No new invalid and/or reserved labels are introduced. + ASTLabelRegistry generateNewLabels(std::set const& _usedIDs, Dialect const& _dialect) const; + ASTLabelRegistry generateNewLabels(Dialect const& _dialect) const; +private: + /// For newly added label IDs, this yields the parent ID which is contained in the provided registry. + /// For label IDs which already are not new, this function is the identity. + LabelID resolveParentLabelID(LabelID _id) const; + bool ghost(LabelID _id) const; + + ASTLabelRegistry const& m_labels; + /// Reserved labels, equipped with the transparent less comparison operator to be able to handle string_view. + std::set> m_reservedLabels; + /// Contains references to parent label IDs. Indices are new IDs offset by `m_labels.maxID() + 1`. + std::vector m_idToLabelMapping; +}; + +} From 30caf713e20ac5fc90f347677d9dad779ab7ae45 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Sun, 1 Jun 2025 10:47:18 +0200 Subject: [PATCH 0877/1340] Remove deprecated whitespace in literal operator declaration --- liblangutil/Exceptions.h | 2 +- libyul/YulString.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/liblangutil/Exceptions.h b/liblangutil/Exceptions.h index c441a6d2f..2f2fdcb4c 100644 --- a/liblangutil/Exceptions.h +++ b/liblangutil/Exceptions.h @@ -163,7 +163,7 @@ struct ErrorId bool operator!=(ErrorId const& _rhs) const { return !(*this == _rhs); } bool operator<(ErrorId const& _rhs) const { return error < _rhs.error; } }; -constexpr ErrorId operator"" _error(unsigned long long _error) { return ErrorId{ _error }; } +constexpr ErrorId operator""_error(unsigned long long _error) { return ErrorId{ _error }; } class Error: virtual public util::Exception { diff --git a/libyul/YulString.h b/libyul/YulString.h index 329825a44..80d58f3ed 100644 --- a/libyul/YulString.h +++ b/libyul/YulString.h @@ -163,7 +163,7 @@ class YulString YulStringRepository::Handle m_handle{ 0, YulStringRepository::emptyHash() }; }; -inline YulString operator "" _yulname(char const* _string, std::size_t _size) +inline YulString operator""_yulname(char const* _string, std::size_t _size) { return YulString(std::string_view(_string, _size)); } From fe1a69005bd1e434420eb4628f95aad1ebb0b47d Mon Sep 17 00:00:00 2001 From: "fuder.eth" Date: Tue, 13 May 2025 15:55:17 +0300 Subject: [PATCH 0878/1340] Rename emitted emmited to emitted emited to emitted --- ...ed_in_base_contract.sol => event_emitted_in_base_contract.sol} | 0 ...emmited.sol => event_from_aggregated_contract_not_emitted.sol} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/ABIJson/{event_emited_in_base_contract.sol => event_emitted_in_base_contract.sol} (100%) rename test/libsolidity/ABIJson/{event_from_aggregated_contract_not_emmited.sol => event_from_aggregated_contract_not_emitted.sol} (100%) diff --git a/test/libsolidity/ABIJson/event_emited_in_base_contract.sol b/test/libsolidity/ABIJson/event_emitted_in_base_contract.sol similarity index 100% rename from test/libsolidity/ABIJson/event_emited_in_base_contract.sol rename to test/libsolidity/ABIJson/event_emitted_in_base_contract.sol diff --git a/test/libsolidity/ABIJson/event_from_aggregated_contract_not_emmited.sol b/test/libsolidity/ABIJson/event_from_aggregated_contract_not_emitted.sol similarity index 100% rename from test/libsolidity/ABIJson/event_from_aggregated_contract_not_emmited.sol rename to test/libsolidity/ABIJson/event_from_aggregated_contract_not_emitted.sol From c5fc3ddb6aa5e986beb0048077bc15eedf5fb876 Mon Sep 17 00:00:00 2001 From: FT <140458077+zeevick10@users.noreply.github.com> Date: Wed, 7 May 2025 10:22:15 +0200 Subject: [PATCH 0879/1340] Update TestFileParserTests.cpp --- test/libsolidity/util/TestFileParserTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsolidity/util/TestFileParserTests.cpp b/test/libsolidity/util/TestFileParserTests.cpp index 4bb4aed3a..c0badfb21 100644 --- a/test/libsolidity/util/TestFileParserTests.cpp +++ b/test/libsolidity/util/TestFileParserTests.cpp @@ -798,7 +798,7 @@ BOOST_AUTO_TEST_CASE(call_arguments_tuple_invalid_empty) BOOST_REQUIRE_THROW(parse(source), TestParserError); } -BOOST_AUTO_TEST_CASE(call_arguments_tuple_invalid_parantheses) +BOOST_AUTO_TEST_CASE(call_arguments_tuple_invalid_parentheses) { char const* source = R"( // f((uint8,() -> FAILURE From 2b1a9e5063639071c596436ef6dae7ec9c72a056 Mon Sep 17 00:00:00 2001 From: FT <140458077+zeevick10@users.noreply.github.com> Date: Wed, 7 May 2025 10:29:02 +0200 Subject: [PATCH 0880/1340] Update protoToAbiV2.cpp --- test/tools/ossfuzz/protoToAbiV2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/tools/ossfuzz/protoToAbiV2.cpp b/test/tools/ossfuzz/protoToAbiV2.cpp index 1511390eb..693dbe79b 100644 --- a/test/tools/ossfuzz/protoToAbiV2.cpp +++ b/test/tools/ossfuzz/protoToAbiV2.cpp @@ -5,7 +5,7 @@ /// Convenience macros /// Returns a valid Solidity integer width w such that 8 <= w <= 256. -#define INTWIDTH(z, n, _ununsed) BOOST_PP_MUL(BOOST_PP_ADD(n, 1), 8) +#define INTWIDTH(z, n, _unused) BOOST_PP_MUL(BOOST_PP_ADD(n, 1), 8) /// Using declaration that aliases long boost multiprecision types with /// s(u) where is a valid Solidity integer width and "s" /// stands for "signed" and "u" for "unsigned". From 403b548d300a721ad47b11e9e216255548314341 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 4 Jun 2025 15:10:28 +0200 Subject: [PATCH 0881/1340] Fix shellcheck script --- scripts/yul_coverage.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/yul_coverage.sh b/scripts/yul_coverage.sh index b2b16675c..73c5084fd 100755 --- a/scripts/yul_coverage.sh +++ b/scripts/yul_coverage.sh @@ -111,18 +111,18 @@ function test_file if OUTPUT=$("${SOLC}" --ir "${SOL_FILE}" 2>&1); then SUCCESS+=("${SOL_FILE}") - show_output_if ${SHOW_SUCCESSFUL} + show_output_if "${SHOW_SUCCESSFUL}" else FAILED+=("${SOL_FILE}") if [[ ${OUTPUT} == *"UnimplementedFeatureError"* ]]; then UNIMPLEMENTED_FEATURE_ERRORS+=("${SOL_FILE}") - show_output_if ${SHOW_UNIMPLEMENTED_FEATURE_ERRORS} + show_output_if "${SHOW_UNIMPLEMENTED_FEATURE_ERRORS}" elif [[ ${OUTPUT} == *"InternalCompilerError"* ]]; then INTERNAL_COMPILER_ERRORS+=("${SOL_FILE}") - show_output_if ${SHOW_INTERNAL_COMPILER_ERRORS} + show_output_if "${SHOW_INTERNAL_COMPILER_ERRORS}" else OTHER_ERRORS+=("${SOL_FILE}") - show_output_if ${SHOW_OTHER_ERRORS} + show_output_if "${SHOW_OTHER_ERRORS}" fi fi } From bcddfb4a346da9e9a5dcf5e8e0ac610d71d28ec7 Mon Sep 17 00:00:00 2001 From: otc group Date: Wed, 4 Jun 2025 19:08:21 +0200 Subject: [PATCH 0882/1340] fix typo in file's name --- ...call_parent.sol => overridden_function_static_call_parent.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/smtCheckerTests/inheritance/{overriden_function_static_call_parent.sol => overridden_function_static_call_parent.sol} (100%) diff --git a/test/libsolidity/smtCheckerTests/inheritance/overriden_function_static_call_parent.sol b/test/libsolidity/smtCheckerTests/inheritance/overridden_function_static_call_parent.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/inheritance/overriden_function_static_call_parent.sol rename to test/libsolidity/smtCheckerTests/inheritance/overridden_function_static_call_parent.sol From 725f8f7f477f27ff699840183c583ee93a0fd022 Mon Sep 17 00:00:00 2001 From: David Klank <155117116+davidjsonn@users.noreply.github.com> Date: Thu, 5 Jun 2025 17:31:44 +0300 Subject: [PATCH 0883/1340] replace 404 reference Natspec.cpp --- libsolidity/interface/Natspec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/interface/Natspec.cpp b/libsolidity/interface/Natspec.cpp index a0da7b54b..a997ef09d 100644 --- a/libsolidity/interface/Natspec.cpp +++ b/libsolidity/interface/Natspec.cpp @@ -19,7 +19,7 @@ * @author Lefteris * @date 2014 * Takes the parsed AST and produces the Natspec documentation: - * https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format + * https://docs.soliditylang.org/en/latest/natspec-format.html * * Can generally deal with JSON files */ From 7b011232925d4482072315e627d0ab4c2c3bec97 Mon Sep 17 00:00:00 2001 From: Kendra Karol Sevilla Date: Fri, 6 Jun 2025 23:47:38 +0200 Subject: [PATCH 0884/1340] fix typo in comment --- libsolidity/ast/AST.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 9c7cbbded..a4e19582b 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1151,7 +1151,7 @@ class VariableDeclaration: public Declaration, public StructurallyDocumented bool isCallableOrCatchParameter() const; /// @returns true if this variable is a return parameter of a function. bool isReturnParameter() const; - /// @returns true if this variable is a parameter of the success or failure clausse + /// @returns true if this variable is a parameter of the success or failure clause /// of a try/catch statement. bool isTryCatchParameter() const; /// @returns true if this variable is a local variable or return parameter. From d75bd3983ce39e1113886c3453c49cd34b73c640 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Sat, 12 Apr 2025 07:30:38 +0200 Subject: [PATCH 0885/1340] Ethdebug requires assembly instance --- libevmasm/Ethdebug.cpp | 2 +- libevmasm/Ethdebug.h | 2 +- libsolidity/interface/CompilerStack.cpp | 5 ++++- libyul/YulStack.cpp | 4 ++-- test/libevmasm/Assembler.cpp | 4 ++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libevmasm/Ethdebug.cpp b/libevmasm/Ethdebug.cpp index 6e635ef57..025160006 100644 --- a/libevmasm/Ethdebug.cpp +++ b/libevmasm/Ethdebug.cpp @@ -77,7 +77,7 @@ Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerO } // anonymous namespace -Json ethdebug::program(std::string_view _name, unsigned _sourceId, Assembly const* _assembly, LinkerObject const& _linkerObject) +Json ethdebug::program(std::string_view _name, unsigned _sourceId, Assembly const& _assembly, LinkerObject const& _linkerObject) { Json result = Json::object(); result["contract"] = Json::object(); diff --git a/libevmasm/Ethdebug.h b/libevmasm/Ethdebug.h index 72ac16037..fdb693b19 100644 --- a/libevmasm/Ethdebug.h +++ b/libevmasm/Ethdebug.h @@ -27,7 +27,7 @@ namespace solidity::evmasm::ethdebug { // returns ethdebug/format/program. -Json program(std::string_view _name, unsigned _sourceId, Assembly const* _assembly, LinkerObject const& _linkerObject); +Json program(std::string_view _name, unsigned _sourceId, Assembly const& _assembly, LinkerObject const& _linkerObject); // returns ethdebug/format/info/resources Json resources(std::vector const& _sources, std::string const& _version); diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 1b0a299f7..975ed3c19 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1216,8 +1216,11 @@ Json CompilerStack::ethdebug(Contract const& _contract, bool _runtime) const solUnimplementedAssert(!isExperimentalSolidity()); evmasm::LinkerObject const& object = _runtime ? _contract.runtimeObject : _contract.object; std::shared_ptr const& assembly = _runtime ? _contract.evmRuntimeAssembly : _contract.evmAssembly; + if (!assembly) + return {}; + solAssert(sourceIndices().contains(_contract.contract->sourceUnitName())); - return evmasm::ethdebug::program(_contract.contract->name(), sourceIndices()[_contract.contract->sourceUnitName()], assembly.get(), object); + return evmasm::ethdebug::program(_contract.contract->name(), sourceIndices()[_contract.contract->sourceUnitName()], *assembly, object); } bytes CompilerStack::cborMetadata(std::string const& _contractName, bool _forIR) const diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 85709b987..b59b4781f 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -275,14 +275,14 @@ YulStack::assembleWithDeployed(std::optional _deployName) ); } if (debugInfoSelection().ethdebug) - creationObject.ethdebug = evmasm::ethdebug::program(creationObject.assembly->name(), 0, creationObject.assembly.get(), *creationObject.bytecode.get()); + creationObject.ethdebug = evmasm::ethdebug::program(creationObject.assembly->name(), 0, *creationObject.assembly, *creationObject.bytecode); if (deployedAssembly) { deployedObject.bytecode = std::make_shared(deployedAssembly->assemble()); deployedObject.assembly = deployedAssembly; if (debugInfoSelection().ethdebug) - deployedObject.ethdebug = evmasm::ethdebug::program(deployedObject.assembly->name(), 0, deployedObject.assembly.get(), *deployedObject.bytecode.get()); + deployedObject.ethdebug = evmasm::ethdebug::program(deployedObject.assembly->name(), 0, *deployedObject.assembly, *deployedObject.bytecode); solAssert(deployedAssembly->codeSections().size() == 1); deployedObject.sourceMappings = std::make_unique( evmasm::AssemblyItem::computeSourceMapping( diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 6a41f7a73..32855cfbc 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -434,7 +434,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_program_last_instruction_with_immediate_arguments) assembly.append(AssemblyItem{0x11223344}); LinkerObject output = assembly.assemble(); - Json const program = ethdebug::program("", 0, &assembly, output); + Json const program = ethdebug::program("", 0, assembly, output); BOOST_REQUIRE(program["instructions"].size() == 1); BOOST_REQUIRE(program["instructions"][0]["operation"]["mnemonic"] == "PUSH4"); BOOST_REQUIRE(program["instructions"][0]["operation"]["arguments"][0] == "0x11223344"); @@ -445,7 +445,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_program_last_instruction_with_immediate_arguments) assembly.append(AssemblyItem{0x1122334455}); LinkerObject output = assembly.assemble(); - Json const program = ethdebug::program("", 0, &assembly, output); + Json const program = ethdebug::program("", 0, assembly, output); BOOST_REQUIRE(program["instructions"].size() == 2); BOOST_REQUIRE(program["instructions"][0]["operation"]["mnemonic"] == "PUSH0"); BOOST_REQUIRE(!program["instructions"][0]["operation"].contains("arguments")); From 43b0f062d9b68ffbd5fc2d558e33a2bb2f76732d Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 8 Apr 2025 16:41:37 +0200 Subject: [PATCH 0886/1340] Ethdebug instructions output over multiple code sections --- Changelog.md | 2 +- libevmasm/Ethdebug.cpp | 85 ++++++++++++++++++++++++++++-------------- 2 files changed, 57 insertions(+), 30 deletions(-) diff --git a/Changelog.md b/Changelog.md index 967e54881..a2e814bda 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,7 +4,7 @@ Language Features: Compiler Features: - +* ethdebug: Experimental support for instructions and source locations under EOF. Bugfixes: diff --git a/libevmasm/Ethdebug.cpp b/libevmasm/Ethdebug.cpp index 025160006..0a4c56ddd 100644 --- a/libevmasm/Ethdebug.cpp +++ b/libevmasm/Ethdebug.cpp @@ -18,6 +18,8 @@ #include +#include + using namespace solidity; using namespace solidity::evmasm; using namespace solidity::evmasm::ethdebug; @@ -25,25 +27,35 @@ using namespace solidity::evmasm::ethdebug; namespace { -Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned _sourceId) +std::vector codeSectionInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned _sourceId, size_t const _codeSectionIndex) { - solUnimplementedAssert(_assembly.eofVersion() == std::nullopt, "ethdebug does not yet support EOF."); - solUnimplementedAssert(_assembly.codeSections().size() == 1, "ethdebug does not yet support multiple code-sections."); - for (auto const& instruction: _assembly.codeSections()[0].items) - solUnimplementedAssert(instruction.type() != VerbatimBytecode, "Verbatim bytecode is currently not supported by ethdebug."); - - solAssert(_linkerObject.codeSectionLocations.size() == 1); - solAssert(_linkerObject.codeSectionLocations[0].end <= _linkerObject.bytecode.size()); - Json instructions = Json::array(); - for (size_t i = 0; i < _linkerObject.codeSectionLocations[0].instructionLocations.size(); ++i) + solAssert(_codeSectionIndex < _linkerObject.codeSectionLocations.size()); + solAssert(_codeSectionIndex < _assembly.codeSections().size()); + auto const& locations = _linkerObject.codeSectionLocations[_codeSectionIndex]; + auto const& codeSection = _assembly.codeSections().at(_codeSectionIndex); + + std::vector instructions; + instructions.reserve(codeSection.items.size()); + + bool const codeSectionContainsVerbatim = ranges::any_of( + codeSection.items, + [](auto const& _instruction) { return _instruction.type() == VerbatimBytecode; } + ); + solUnimplementedAssert(!codeSectionContainsVerbatim, "Verbatim bytecode is currently not supported by ethdebug."); + + for (auto const& currentInstruction: locations.instructionLocations) { - LinkerObject::InstructionLocation currentInstruction = _linkerObject.codeSectionLocations[0].instructionLocations[i]; - size_t start = currentInstruction.start; - size_t end = currentInstruction.end; - size_t assemblyItemIndex = currentInstruction.assemblyItemIndex; + size_t const start = currentInstruction.start; + size_t const end = currentInstruction.end; + + // some instructions do not contribute to the bytecode + if (start == end) + continue; + + size_t const assemblyItemIndex = currentInstruction.assemblyItemIndex; solAssert(end <= _linkerObject.bytecode.size()); solAssert(start < end); - solAssert(assemblyItemIndex < _assembly.codeSections().at(0).items.size()); + solAssert(assemblyItemIndex < codeSection.items.size()); Json operation = Json::object(); operation["mnemonic"] = instructionInfo(static_cast(_linkerObject.bytecode[start]), _assembly.evmVersion()).name; static size_t constexpr instructionSize = 1; @@ -56,25 +68,40 @@ Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerO solAssert(!argumentData.empty()); operation["arguments"] = Json::array({util::toHex(argumentData, util::HexPrefix::Add)}); } - langutil::SourceLocation const& location = _assembly.codeSections().at(0).items.at(assemblyItemIndex).location(); - Json instruction = Json::object(); - instruction["offset"] = start; - instruction["operation"] = operation; - - instruction["context"] = Json::object(); - instruction["context"]["code"] = Json::object(); - instruction["context"]["code"]["source"] = Json::object(); - instruction["context"]["code"]["source"]["id"] = static_cast(_sourceId); - - instruction["context"]["code"]["range"] = Json::object(); - instruction["context"]["code"]["range"]["offset"] = location.start; - instruction["context"]["code"]["range"]["length"] = location.end - location.start; - instructions.emplace_back(instruction); + langutil::SourceLocation const& location = codeSection.items.at(assemblyItemIndex).location(); + instructions.emplace_back(Json{ + { "offset", start }, + {"operation", operation }, + { + "context", { + "code", { + "source", { + { "id", static_cast(_sourceId) }, + }, + "range", { + { "offset", location.start }, + { "length", location.end - location.start } + } + } + } + } + }); } return instructions; } +Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned _sourceId) +{ + auto const numCodeSections = _assembly.codeSections().size(); + solAssert(numCodeSections == _linkerObject.codeSectionLocations.size()); + + std::vector instructionInfo; + for (size_t codeSectionIndex = 0; codeSectionIndex < numCodeSections; ++codeSectionIndex) + instructionInfo += codeSectionInstructions(_assembly, _linkerObject, _sourceId, codeSectionIndex); + return instructionInfo; +} + } // anonymous namespace Json ethdebug::program(std::string_view _name, unsigned _sourceId, Assembly const& _assembly, LinkerObject const& _linkerObject) From 4ea1d47423ca28907bef2610a81c0031e43b1c34 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 11 Apr 2025 10:48:54 +0200 Subject: [PATCH 0887/1340] Add ethdebug schema --- libevmasm/CMakeLists.txt | 2 + libevmasm/EthdebugSchema.cpp | 143 +++++++++++++++++++++++++++++ libevmasm/EthdebugSchema.h | 172 +++++++++++++++++++++++++++++++++++ 3 files changed, 317 insertions(+) create mode 100644 libevmasm/EthdebugSchema.cpp create mode 100644 libevmasm/EthdebugSchema.h diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index a7441b85e..74aaeb6c2 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -6,6 +6,8 @@ set(sources AssemblyItem.h Ethdebug.cpp Ethdebug.h + EthdebugSchema.cpp + EthdebugSchema.h EVMAssemblyStack.cpp EVMAssemblyStack.h BlockDeduplicator.cpp diff --git a/libevmasm/EthdebugSchema.cpp b/libevmasm/EthdebugSchema.cpp new file mode 100644 index 000000000..c54b7167f --- /dev/null +++ b/libevmasm/EthdebugSchema.cpp @@ -0,0 +1,143 @@ +/* + 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 + +#include + +#include +#include + +using namespace solidity; +using namespace solidity::evmasm::ethdebug; + +void schema::data::to_json(Json& _json, HexValue const& _hexValue) +{ + _json = util::toHex(_hexValue.value, util::HexPrefix::Add); +} + +void schema::data::to_json(Json& _json, Unsigned const& _unsigned) +{ + std::visit(util::GenericVisitor{ + [&](HexValue const& _hexValue) { _json = _hexValue; }, + [&](std::uint64_t const _value) { _json = _value; } + }, _unsigned.value); +} + +void schema::materials::to_json(Json& _json, ID const& _id) +{ + std::visit(util::GenericVisitor{ + [&](std::string const& _hexValue) { _json = _hexValue; }, + [&](std::uint64_t const _value) { _json = _value; } + }, _id.value); +} + +void schema::materials::to_json(Json& _json, Reference const& _source) +{ + _json["id"] = _source.id; + if (_source.type) + _json["type"] = *_source.type == Reference::Type::Compilation ? "compilation" : "source"; +} + +void schema::materials::to_json(Json& _json, SourceRange::Range const& _range) +{ + _json["length"] = _range.length; + _json["offset"] = _range.offset; +} + + +void schema::materials::to_json(Json& _json, SourceRange const& _sourceRange) +{ + _json["source"] = _sourceRange.source; + if (_sourceRange.range) + _json["range"] = *_sourceRange.range; +} + +void schema::to_json(Json& _json, Program::Contract const& _contract) +{ + if (_contract.name) + _json["name"] = *_contract.name; + _json["definition"] = _contract.definition; +} + +void schema::program::to_json(Json& _json, Context::Variable const& _contextVariable) +{ + auto const numProperties = + _contextVariable.identifier.has_value() + + _contextVariable.declaration.has_value(); + solRequire(numProperties >= 1, EthdebugException, "Context variable has no properties."); + if (_contextVariable.identifier) + { + solRequire(!_contextVariable.identifier->empty(), EthdebugException, "Variable identifier must not be empty."); + _json["identifier"] = *_contextVariable.identifier; + } + if (_contextVariable.declaration) + _json["declaration"] = *_contextVariable.declaration; +} + +void schema::program::to_json(Json& _json, Context const& _context) +{ + solRequire(_context.code.has_value() + _context.remark.has_value() + _context.variables.has_value() >= 1, EthdebugException, "Context needs >=1 properties."); + if (_context.code) + _json["code"] = *_context.code; + if (_context.variables) + { + solRequire(!_context.variables->empty(), EthdebugException, "Context variables must not be empty if provided."); + _json["variables"] = *_context.variables; + } + if (_context.remark) + _json["remark"] = *_context.remark; +} + +void schema::program::to_json(Json& _json, Instruction::Operation const& _operation) +{ + _json = { {"mnemonic", _operation.mnemonic} }; + if (!_operation.arguments.empty()) + _json["arguments"] = _operation.arguments; +} + +void schema::program::to_json(Json& _json, Instruction const& _instruction) +{ + _json["offset"] = _instruction.offset; + if (_instruction.operation) + _json["operation"] = *_instruction.operation; + if (_instruction.context) + _json["context"] = *_instruction.context; +} + +void schema::to_json(Json& _json, Program const& _program) +{ + if (_program.compilation) + _json["compilation"] = *_program.compilation; + _json["contract"] = _program.contract; + _json["environment"] = _program.environment; + if (_program.context) + _json["context"] = *_program.context; + _json["instructions"] = _program.instructions; +} + +void schema::to_json(Json& _json, Program::Environment const& _environment) +{ + switch (_environment) + { + case Program::Environment::CALL: + _json = "call"; + break; + case Program::Environment::CREATE: + _json = "create"; + break; + } +} diff --git a/libevmasm/EthdebugSchema.h b/libevmasm/EthdebugSchema.h new file mode 100644 index 000000000..5fc8f78fd --- /dev/null +++ b/libevmasm/EthdebugSchema.h @@ -0,0 +1,172 @@ +/* + 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 + +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace solidity::evmasm::ethdebug::schema +{ + +struct EthdebugException: virtual util::Exception {}; + +namespace data +{ + +struct HexValue +{ + bytes value; +}; + +struct Unsigned +{ + template + Unsigned(T const _value) + { + solRequire(static_cast(_value) <= std::numeric_limits::max(), EthdebugException, "Too large value."); + value = static_cast(_value); + } + template + Unsigned(T const _value) + { + solRequire(_value >= 0, EthdebugException, "NonNegativeValue got negative value."); + solRequire(static_cast>(_value) <= std::numeric_limits::max(), EthdebugException, "Too large value."); + value = static_cast(_value); + } + Unsigned(HexValue&& _value): value(std::move(_value)) {} + + std::variant value; +}; + +} + +namespace materials +{ + +struct ID +{ + std::variant value; +}; + +struct Reference +{ + enum class Type { Compilation, Source }; + ID id; + std::optional type; +}; + +struct SourceRange +{ + struct Range + { + data::Unsigned length; + data::Unsigned offset; + }; + + Reference source; + std::optional range; +}; + +} + +namespace program +{ + +struct Context +{ + struct Variable + { + std::optional identifier; + std::optional declaration; + // TODO: type + // TODO: pointer according to ethdebug/format/spec/pointer + }; + + std::optional code; + std::optional> variables; + std::optional remark; +}; + +struct Instruction +{ + struct Operation + { + std::string mnemonic; + std::vector arguments; + }; + + data::Unsigned offset; + std::optional operation; + std::optional context; +}; + +} + +struct Program +{ + enum class Environment + { + CALL, CREATE + }; + + struct Contract + { + std::optional name; + materials::SourceRange definition; + }; + + std::optional compilation; + Contract contract; + Environment environment; + std::optional context; + std::vector instructions; +}; + +namespace data +{ +void to_json(Json& _json, HexValue const& _hexValue); +void to_json(Json& _json, Unsigned const& _unsigned); +} + +namespace materials +{ +void to_json(Json& _json, ID const& _id); +void to_json(Json& _json, Reference const& _source); +void to_json(Json& _json, SourceRange::Range const& _range); +void to_json(Json& _json, SourceRange const& _sourceRange); +} + +namespace program +{ +void to_json(Json& _json, Context::Variable const& _contextVariable); +void to_json(Json& _json, Context const& _context); +void to_json(Json& _json, Instruction::Operation const& _operation); +void to_json(Json& _json, Instruction const& _instruction); +} + +void to_json(Json& _json, Program::Contract const& _contract); +void to_json(Json& _json, Program::Environment const& _environment); +void to_json(Json& _json, Program const& _program); + +} From 3b924e6429e646feaa8f75ca0577435c63df3e0e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 9 Apr 2025 15:22:54 +0200 Subject: [PATCH 0888/1340] Ethdebug uses schema for serialization --- libevmasm/Ethdebug.cpp | 131 ++++++++++++++++---------- libevmasm/Ethdebug.h | 2 +- test/libsolidity/StandardCompiler.cpp | 9 +- 3 files changed, 87 insertions(+), 55 deletions(-) diff --git a/libevmasm/Ethdebug.cpp b/libevmasm/Ethdebug.cpp index 0a4c56ddd..8b87aadd0 100644 --- a/libevmasm/Ethdebug.cpp +++ b/libevmasm/Ethdebug.cpp @@ -18,6 +18,8 @@ #include +#include + #include using namespace solidity; @@ -27,14 +29,66 @@ using namespace solidity::evmasm::ethdebug; namespace { -std::vector codeSectionInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned _sourceId, size_t const _codeSectionIndex) +schema::program::Instruction::Operation instructionOperation(Assembly const& _assembly, LinkerObject const& _linkerObject, size_t const _start, size_t const _end) +{ + solAssert(_end <= _linkerObject.bytecode.size()); + solAssert(_start < _end); + schema::program::Instruction::Operation operation; + operation.mnemonic = instructionInfo(static_cast(_linkerObject.bytecode[_start]), _assembly.evmVersion()).name; + static size_t constexpr instructionSize = 1; + if (_start + instructionSize < _end) + { + bytes const argumentData( + _linkerObject.bytecode.begin() + static_cast(_start) + instructionSize, + _linkerObject.bytecode.begin() + static_cast(_end) + ); + solAssert(!argumentData.empty()); + operation.arguments = {{schema::data::HexValue{argumentData}}}; + } + return operation; +} + +schema::materials::SourceRange::Range locationRange(langutil::SourceLocation const& _location) +{ + return { + .length = schema::data::Unsigned{_location.end - _location.start}, + .offset = schema::data::Unsigned{_location.start} + }; +} + +schema::materials::Reference sourceReference(unsigned _sourceID) +{ + return { + .id = schema::materials::ID{_sourceID}, + .type = std::nullopt + }; +} + +std::optional instructionContext(Assembly::CodeSection const& _codeSection, size_t _assemblyItemIndex, unsigned _sourceID) +{ + solAssert(_assemblyItemIndex < _codeSection.items.size()); + langutil::SourceLocation const& location = _codeSection.items.at(_assemblyItemIndex).location(); + if (!location.isValid()) + return std::nullopt; + + return schema::program::Context{ + schema::materials::SourceRange{ + .source = sourceReference(_sourceID), + .range = locationRange(location) + }, + std::nullopt, + std::nullopt + }; +} + +std::vector codeSectionInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned const _sourceID, size_t const _codeSectionIndex) { solAssert(_codeSectionIndex < _linkerObject.codeSectionLocations.size()); solAssert(_codeSectionIndex < _assembly.codeSections().size()); auto const& locations = _linkerObject.codeSectionLocations[_codeSectionIndex]; auto const& codeSection = _assembly.codeSections().at(_codeSectionIndex); - std::vector instructions; + std::vector instructions; instructions.reserve(codeSection.items.size()); bool const codeSectionContainsVerbatim = ranges::any_of( @@ -52,72 +106,47 @@ std::vector codeSectionInstructions(Assembly const& _assembly, LinkerObjec if (start == end) continue; - size_t const assemblyItemIndex = currentInstruction.assemblyItemIndex; - solAssert(end <= _linkerObject.bytecode.size()); - solAssert(start < end); - solAssert(assemblyItemIndex < codeSection.items.size()); - Json operation = Json::object(); - operation["mnemonic"] = instructionInfo(static_cast(_linkerObject.bytecode[start]), _assembly.evmVersion()).name; - static size_t constexpr instructionSize = 1; - if (start + instructionSize < end) - { - bytes const argumentData( - _linkerObject.bytecode.begin() + static_cast(start) + instructionSize, - _linkerObject.bytecode.begin() + static_cast(end) - ); - solAssert(!argumentData.empty()); - operation["arguments"] = Json::array({util::toHex(argumentData, util::HexPrefix::Add)}); - } - langutil::SourceLocation const& location = codeSection.items.at(assemblyItemIndex).location(); - instructions.emplace_back(Json{ - { "offset", start }, - {"operation", operation }, - { - "context", { - "code", { - "source", { - { "id", static_cast(_sourceId) }, - }, - "range", { - { "offset", location.start }, - { "length", location.end - location.start } - } - } - } - } + instructions.emplace_back(schema::program::Instruction{ + .offset = schema::data::Unsigned{start}, + .operation = instructionOperation(_assembly, _linkerObject, start, end), + .context = instructionContext(codeSection, currentInstruction.assemblyItemIndex, _sourceID) }); } return instructions; } -Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned _sourceId) +std::vector programInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned const _sourceID) { auto const numCodeSections = _assembly.codeSections().size(); solAssert(numCodeSections == _linkerObject.codeSectionLocations.size()); - std::vector instructionInfo; + std::vector instructionInfo; for (size_t codeSectionIndex = 0; codeSectionIndex < numCodeSections; ++codeSectionIndex) - instructionInfo += codeSectionInstructions(_assembly, _linkerObject, _sourceId, codeSectionIndex); + instructionInfo += codeSectionInstructions(_assembly, _linkerObject, _sourceID, codeSectionIndex); return instructionInfo; } } // anonymous namespace -Json ethdebug::program(std::string_view _name, unsigned _sourceId, Assembly const& _assembly, LinkerObject const& _linkerObject) +Json ethdebug::program(std::string_view _name, unsigned _sourceID, Assembly const& _assembly, LinkerObject const& _linkerObject) { - Json result = Json::object(); - result["contract"] = Json::object(); - result["contract"]["name"] = _name; - result["contract"]["definition"] = Json::object(); - result["contract"]["definition"]["source"] = Json::object(); - result["contract"]["definition"]["source"]["id"] = _sourceId; - if (_assembly) - { - result["environment"] = _assembly->isCreation() ? "create" : "call"; - result["instructions"] = programInstructions(*_assembly, _linkerObject, _sourceId); - } - return result; + return schema::Program{ + .compilation = std::nullopt, + .contract = { + .name = std::string{_name}, + .definition = { + .source = { + .id = {_sourceID}, + .type = std::nullopt + }, + .range = std::nullopt + } + }, + .environment = _assembly.isCreation() ? schema::Program::Environment::CREATE : schema::Program::Environment::CALL, + .context = std::nullopt, + .instructions = programInstructions(_assembly, _linkerObject, _sourceID) + }; } Json ethdebug::resources(std::vector const& _sources, std::string const& _version) diff --git a/libevmasm/Ethdebug.h b/libevmasm/Ethdebug.h index fdb693b19..2e0df3484 100644 --- a/libevmasm/Ethdebug.h +++ b/libevmasm/Ethdebug.h @@ -27,7 +27,7 @@ namespace solidity::evmasm::ethdebug { // returns ethdebug/format/program. -Json program(std::string_view _name, unsigned _sourceId, Assembly const& _assembly, LinkerObject const& _linkerObject); +Json program(std::string_view _name, unsigned _sourceID, Assembly const& _assembly, LinkerObject const& _linkerObject); // returns ethdebug/format/info/resources Json resources(std::vector const& _sources, std::string const& _version); diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 62c72ad45..b9e31c5e3 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -2231,9 +2231,12 @@ BOOST_DATA_TEST_CASE(ethdebug_output_instructions_smoketest, boost::unit_test::d BOOST_REQUIRE(instruction.contains("offset")); BOOST_REQUIRE(instruction.contains("operation")); BOOST_REQUIRE(instruction["operation"].contains("mnemonic")); - BOOST_REQUIRE(instruction["context"]["code"]["range"].contains("length")); - BOOST_REQUIRE(instruction["context"]["code"]["range"].contains("offset")); - BOOST_REQUIRE(instruction["context"]["code"]["source"].contains("id")); + if (instruction.contains("context")) + { + BOOST_REQUIRE(instruction["context"]["code"]["range"].contains("length")); + BOOST_REQUIRE(instruction["context"]["code"]["range"].contains("offset")); + BOOST_REQUIRE(instruction["context"]["code"]["source"].contains("id")); + } std::string mnemonic = instruction["operation"]["mnemonic"]; if (mnemonic.find("PUSH") != std::string::npos) { From 89a0f9142491cf08c8ce438723fe27f6c52fc083 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 9 Apr 2025 15:23:21 +0200 Subject: [PATCH 0889/1340] Update test expectations with eof-enabled ethdebug --- .../ethdebug_eof_container_osaka/args | 2 +- .../ethdebug_eof_container_osaka/err | 1 - .../ethdebug_eof_container_osaka/exit | 1 - .../ethdebug_eof_container_osaka/output | 251 +++++++++++++++++- 4 files changed, 251 insertions(+), 4 deletions(-) delete mode 100644 test/cmdlineTests/ethdebug_eof_container_osaka/err delete mode 100644 test/cmdlineTests/ethdebug_eof_container_osaka/exit diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/args b/test/cmdlineTests/ethdebug_eof_container_osaka/args index 65974c628..16466b842 100644 --- a/test/cmdlineTests/ethdebug_eof_container_osaka/args +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/args @@ -1 +1 @@ - --experimental-eof-version 1 --evm-version osaka --ethdebug --via-ir + --experimental-eof-version 1 --evm-version osaka --ethdebug --via-ir --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/err b/test/cmdlineTests/ethdebug_eof_container_osaka/err deleted file mode 100644 index 771468597..000000000 --- a/test/cmdlineTests/ethdebug_eof_container_osaka/err +++ /dev/null @@ -1 +0,0 @@ -Error: ethdebug does not yet support EOF. diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/exit b/test/cmdlineTests/ethdebug_eof_container_osaka/exit deleted file mode 100644 index d00491fd7..000000000 --- a/test/cmdlineTests/ethdebug_eof_container_osaka/exit +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/output b/test/cmdlineTests/ethdebug_eof_container_osaka/output index b29297ee3..e9b57d885 100644 --- a/test/cmdlineTests/ethdebug_eof_container_osaka/output +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/output @@ -1,4 +1,253 @@ ======= Debug Data (ethdebug/format/info/resources) ======= -{"compilation":{"compiler":{"name":"solc","version": ""},"sources":[{"id":0,"path":"input.sol"}]}} +{ + "compilation": { + "compiler": { + "name": "solc", + "version": "" + }, + "sources": [ + { + "id": 0, + "path": "input.sol" + } + ] + } +} ======= input.sol:C ======= +Debug Data (ethdebug/format/program): +{ + "contract": { + "definition": { + "source": { + "id": 0 + } + }, + "name": "C" + }, + "environment": "create", + "instructions": [ + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 30, + "operation": { + "arguments": [ + "0x80" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 32, + "operation": { + "arguments": [ + "0x40" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 34, + "operation": { + "mnemonic": "MSTORE" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 35, + "operation": { + "mnemonic": "CALLVALUE" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 36, + "operation": { + "arguments": [ + "0x0005" + ], + "mnemonic": "RJUMPI" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 39, + "operation": { + "mnemonic": "PUSH0" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 40, + "operation": { + "arguments": [ + "0x80" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 42, + "operation": { + "arguments": [ + "0x00" + ], + "mnemonic": "RETURNCONTRACT" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 44, + "operation": { + "arguments": [ + "0x0001" + ], + "mnemonic": "JUMPF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 47, + "operation": { + "mnemonic": "PUSH0" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 48, + "operation": { + "mnemonic": "DUP1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 49, + "operation": { + "mnemonic": "REVERT" + } + } + ] +} From 482f64b64ba6fbacf7db42148a8a8914b8a33e56 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 11 Apr 2025 11:37:46 +0200 Subject: [PATCH 0890/1340] Test ethdebug output when requested in standard json under EOF --- .../args | 1 + .../in.yul | 16 +++++++ .../input.json | 18 ++++++++ .../output.json | 42 +++++++++++++++++++ .../strip-ethdebug | 0 .../standard_yul_ethdebug_eof/args | 1 + .../standard_yul_ethdebug_eof/in.yul | 17 ++++++++ .../standard_yul_ethdebug_eof/input.json | 13 ++++++ .../standard_yul_ethdebug_eof/output.json | 42 +++++++++++++++++++ .../standard_yul_ethdebug_eof/strip-ethdebug | 0 10 files changed, 150 insertions(+) create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/args create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/in.yul create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/output.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/strip-ethdebug create mode 100644 test/cmdlineTests/standard_yul_ethdebug_eof/args create mode 100644 test/cmdlineTests/standard_yul_ethdebug_eof/in.yul create mode 100644 test/cmdlineTests/standard_yul_ethdebug_eof/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_eof/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_eof/strip-ethdebug diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/args b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/in.yul b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/in.yul new file mode 100644 index 000000000..aa564d00c --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/in.yul @@ -0,0 +1,16 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json new file mode 100644 index 000000000..a8c3436c1 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json @@ -0,0 +1,18 @@ +{ + "language": "Yul", + "sources": { + "C": { + "urls": [ + "in.yul" + ] + } + }, + "settings": { + "eofVersion": 1, + "evmVersion": "osaka", + "debug": {"debugInfo": ["ethdebug"]}, + "outputSelection": { + "*": {"*": ["ir", "irOptimized", "evm.bytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/output.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/output.json new file mode 100644 index 000000000..2b2f395fa --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/output.json @@ -0,0 +1,42 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + /// @src 0:60:101 + mstore(64, 128) + fun_f_5() + /// @src 0:77:99 + function fun_f_5() + { sstore(0, 42) } + } +} +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + { + /// @src 0:60:101 + mstore(64, 128) + fun_f() + } + /// @src 0:77:99 + function fun_f() + { sstore(0, 42) } + } +} +" + } + } + }, + "ethdebug": "" +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/strip-ethdebug b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/strip-ethdebug new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_yul_ethdebug_eof/args b/test/cmdlineTests/standard_yul_ethdebug_eof/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_eof/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_eof/in.yul b/test/cmdlineTests/standard_yul_ethdebug_eof/in.yul new file mode 100644 index 000000000..920aef8e9 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_eof/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_eof/input.json b/test/cmdlineTests/standard_yul_ethdebug_eof/input.json new file mode 100644 index 000000000..4e33c4267 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_eof/input.json @@ -0,0 +1,13 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["in.yul"]} + }, + "settings": { + "eofVersion": 1, + "evmVersion": "osaka", + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir", "irOptimized"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_eof/output.json b/test/cmdlineTests/standard_yul_ethdebug_eof/output.json new file mode 100644 index 000000000..2b2f395fa --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_eof/output.json @@ -0,0 +1,42 @@ +{ + "contracts": { + "C": { + "C_6_deployed": { + "evm": { + "bytecode": { + "ethdebug": "" + } + }, + "ir": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + /// @src 0:60:101 + mstore(64, 128) + fun_f_5() + /// @src 0:77:99 + function fun_f_5() + { sstore(0, 42) } + } +} +", + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"input.sol\" +object \"C_6_deployed\" { + code { + { + /// @src 0:60:101 + mstore(64, 128) + fun_f() + } + /// @src 0:77:99 + function fun_f() + { sstore(0, 42) } + } +} +" + } + } + }, + "ethdebug": "" +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_eof/strip-ethdebug b/test/cmdlineTests/standard_yul_ethdebug_eof/strip-ethdebug new file mode 100644 index 000000000..e69de29bb From 059bd8ee43fc8f767492f219060b5adfc68a8cda Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 6 May 2025 13:16:51 +0200 Subject: [PATCH 0891/1340] Add tests for ethdebug output on abstract contracts and interfaces --- test/cmdlineTests/ethdebug_on_abstract/args | 1 + .../ethdebug_on_abstract/input.sol | 6 +++ test/cmdlineTests/ethdebug_on_abstract/output | 19 +++++++ test/cmdlineTests/ethdebug_on_interface/args | 1 + .../ethdebug_on_interface/input.sol | 6 +++ .../cmdlineTests/ethdebug_on_interface/output | 19 +++++++ .../input.json | 27 ++++++++++ .../output.json | 54 +++++++++++++++++++ 8 files changed, 133 insertions(+) create mode 100644 test/cmdlineTests/ethdebug_on_abstract/args create mode 100644 test/cmdlineTests/ethdebug_on_abstract/input.sol create mode 100644 test/cmdlineTests/ethdebug_on_abstract/output create mode 100644 test/cmdlineTests/ethdebug_on_interface/args create mode 100644 test/cmdlineTests/ethdebug_on_interface/input.sol create mode 100644 test/cmdlineTests/ethdebug_on_interface/output create mode 100644 test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json create mode 100644 test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/output.json diff --git a/test/cmdlineTests/ethdebug_on_abstract/args b/test/cmdlineTests/ethdebug_on_abstract/args new file mode 100644 index 000000000..c6018b329 --- /dev/null +++ b/test/cmdlineTests/ethdebug_on_abstract/args @@ -0,0 +1 @@ +--ethdebug --via-ir --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ethdebug_on_abstract/input.sol b/test/cmdlineTests/ethdebug_on_abstract/input.sol new file mode 100644 index 000000000..29ff21a20 --- /dev/null +++ b/test/cmdlineTests/ethdebug_on_abstract/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +abstract contract C { + function f() public virtual returns (bytes32); +} diff --git a/test/cmdlineTests/ethdebug_on_abstract/output b/test/cmdlineTests/ethdebug_on_abstract/output new file mode 100644 index 000000000..744ec0e77 --- /dev/null +++ b/test/cmdlineTests/ethdebug_on_abstract/output @@ -0,0 +1,19 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{ + "compilation": { + "compiler": { + "name": "solc", + "version": "" + }, + "sources": [ + { + "id": 0, + "path": "input.sol" + } + ] + } +} + +======= input.sol:C ======= +Debug Data (ethdebug/format/program): +null diff --git a/test/cmdlineTests/ethdebug_on_interface/args b/test/cmdlineTests/ethdebug_on_interface/args new file mode 100644 index 000000000..c6018b329 --- /dev/null +++ b/test/cmdlineTests/ethdebug_on_interface/args @@ -0,0 +1 @@ +--ethdebug --via-ir --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ethdebug_on_interface/input.sol b/test/cmdlineTests/ethdebug_on_interface/input.sol new file mode 100644 index 000000000..cd008c45b --- /dev/null +++ b/test/cmdlineTests/ethdebug_on_interface/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +interface C { + function f() external; +} diff --git a/test/cmdlineTests/ethdebug_on_interface/output b/test/cmdlineTests/ethdebug_on_interface/output new file mode 100644 index 000000000..744ec0e77 --- /dev/null +++ b/test/cmdlineTests/ethdebug_on_interface/output @@ -0,0 +1,19 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{ + "compilation": { + "compiler": { + "name": "solc", + "version": "" + }, + "sources": [ + { + "id": 0, + "path": "input.sol" + } + ] + } +} + +======= input.sol:C ======= +Debug Data (ethdebug/format/program): +null diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json new file mode 100644 index 000000000..06b2d86e9 --- /dev/null +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json @@ -0,0 +1,27 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\n\nabstract contract C {\n function f() public virtual returns (bytes32);\n}\n" + }, + "b.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\n\ninterface C {\n function f() external;\n}\n" + } + }, + "settings": { + "viaIR": true, + "debug": { + "debugInfo": [ + "ethdebug" + ] + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/output.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/output.json new file mode 100644 index 000000000..57b266801 --- /dev/null +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/output.json @@ -0,0 +1,54 @@ +{ + "contracts": { + "a.sol": { + "C": { + "evm": { + "bytecode": { + "ethdebug": null + }, + "deployedBytecode": { + "ethdebug": null + } + } + } + }, + "b.sol": { + "C": { + "evm": { + "bytecode": { + "ethdebug": null + }, + "deployedBytecode": { + "ethdebug": null + } + } + } + } + }, + "ethdebug": { + "compilation": { + "compiler": { + "name": "solc", + "version": "" + }, + "sources": [ + { + "id": 0, + "path": "a.sol" + }, + { + "id": 1, + "path": "b.sol" + } + ] + } + }, + "sources": { + "a.sol": { + "id": 0 + }, + "b.sol": { + "id": 1 + } + } +} From dd25b24f12556921f99adf05268302a5e1b7f991 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 15 May 2025 16:05:23 +0200 Subject: [PATCH 0892/1340] Changelog uses single blank line between headlines --- Changelog.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index a2e814bda..18e0deeaf 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,13 +2,11 @@ Language Features: - Compiler Features: * ethdebug: Experimental support for instructions and source locations under EOF. Bugfixes: - ### 0.8.30 (2025-05-07) Compiler Features: From 1401089b42d13476b7380fe2569313fe16710230 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Thu, 5 Jun 2025 17:13:17 +0200 Subject: [PATCH 0893/1340] Export literal assignments as operation --- libyul/YulControlFlowGraphExporter.cpp | 4 +- .../standard_yul_cfg_json_export/output.json | 61 ++++++++++--------- .../strict_asm_yul_cfg_json_export/output | 16 ++--- test/cmdlineTests/yul_cfg_json_export/output | 61 ++++++++++--------- 4 files changed, 72 insertions(+), 70 deletions(-) diff --git a/libyul/YulControlFlowGraphExporter.cpp b/libyul/YulControlFlowGraphExporter.cpp index 1ce7f58fc..f0ad055f2 100644 --- a/libyul/YulControlFlowGraphExporter.cpp +++ b/libyul/YulControlFlowGraphExporter.cpp @@ -187,7 +187,7 @@ Json YulControlFlowGraphExporter::toJson(Json& _ret, SSACFG const& _cfg, SSACFG: { yulAssert(_operation.inputs.size() == 1); yulAssert(_cfg.isLiteralValue(_operation.inputs.back())); - _ret["type"] = "LiteralAssignment"; + opJson["op"] = "LiteralAssignment"; }, [&](SSACFG::BuiltinCall const& _call) { @@ -210,7 +210,7 @@ Json YulControlFlowGraphExporter::toJson(Json& _ret, SSACFG const& _cfg, SSACFG: } if (!builtinArgsJson.empty()) - opJson["builtinArgs"] = builtinArgsJson; + opJson["literalArgs"] = builtinArgsJson; opJson["op"] = _call.builtin.get().name; }, diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index a9c5ca7a6..ac416d331 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -17,10 +17,10 @@ "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" @@ -57,20 +57,20 @@ "id": "Block2", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19_deployed" ], - "in": [], "op": "datasize", "out": [ "v4" ] }, { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19_deployed" ], - "in": [], "op": "dataoffset", "out": [ "v5" @@ -140,10 +140,10 @@ "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" @@ -464,10 +464,10 @@ "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" @@ -504,20 +504,20 @@ "id": "Block2", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "D_38_deployed" ], - "in": [], "op": "datasize", "out": [ "v4" ] }, { - "builtinArgs": [ + "in": [], + "literalArgs": [ "D_38_deployed" ], - "in": [], "op": "dataoffset", "out": [ "v5" @@ -587,10 +587,10 @@ "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" @@ -845,10 +845,10 @@ "id": "Block9", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19" ], - "in": [], "op": "datasize", "out": [ "v18" @@ -940,10 +940,10 @@ "id": "Block12", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19" ], - "in": [], "op": "dataoffset", "out": [ "v35" @@ -1226,6 +1226,7 @@ "in": [ "0x00" ], + "op": "LiteralAssignment", "out": [ "v64" ] @@ -1240,8 +1241,7 @@ "v46", "v64" ] - }, - "type": "LiteralAssignment" + } }, { "exit": { @@ -1365,6 +1365,7 @@ "in": [ "0x20" ], + "op": "LiteralAssignment", "out": [ "v67" ] @@ -1710,10 +1711,10 @@ "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" @@ -1750,20 +1751,20 @@ "id": "Block2", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19_deployed" ], - "in": [], "op": "datasize", "out": [ "v4" ] }, { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19_deployed" ], - "in": [], "op": "dataoffset", "out": [ "v5" @@ -1833,10 +1834,10 @@ "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output index e0bb1af40..40f8186a1 100644 --- a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -17,10 +17,10 @@ Yul Control Flow Graph: "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" @@ -57,20 +57,20 @@ Yul Control Flow Graph: "id": "Block2", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19_deployed" ], - "in": [], "op": "datasize", "out": [ "v4" ] }, { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19_deployed" ], - "in": [], "op": "dataoffset", "out": [ "v5" @@ -140,10 +140,10 @@ Yul Control Flow Graph: "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index 2620d53a9..1e22b8462 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -16,10 +16,10 @@ Yul Control Flow Graph: "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" @@ -56,20 +56,20 @@ Yul Control Flow Graph: "id": "Block2", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19_deployed" ], - "in": [], "op": "datasize", "out": [ "v4" ] }, { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19_deployed" ], - "in": [], "op": "dataoffset", "out": [ "v5" @@ -139,10 +139,10 @@ Yul Control Flow Graph: "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" @@ -464,10 +464,10 @@ Yul Control Flow Graph: "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" @@ -504,20 +504,20 @@ Yul Control Flow Graph: "id": "Block2", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "D_38_deployed" ], - "in": [], "op": "datasize", "out": [ "v4" ] }, { - "builtinArgs": [ + "in": [], + "literalArgs": [ "D_38_deployed" ], - "in": [], "op": "dataoffset", "out": [ "v5" @@ -587,10 +587,10 @@ Yul Control Flow Graph: "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" @@ -845,10 +845,10 @@ Yul Control Flow Graph: "id": "Block9", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19" ], - "in": [], "op": "datasize", "out": [ "v18" @@ -940,10 +940,10 @@ Yul Control Flow Graph: "id": "Block12", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19" ], - "in": [], "op": "dataoffset", "out": [ "v35" @@ -1226,6 +1226,7 @@ Yul Control Flow Graph: "in": [ "0x00" ], + "op": "LiteralAssignment", "out": [ "v64" ] @@ -1240,8 +1241,7 @@ Yul Control Flow Graph: "v46", "v64" ] - }, - "type": "LiteralAssignment" + } }, { "exit": { @@ -1365,6 +1365,7 @@ Yul Control Flow Graph: "in": [ "0x20" ], + "op": "LiteralAssignment", "out": [ "v67" ] @@ -1710,10 +1711,10 @@ Yul Control Flow Graph: "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" @@ -1750,20 +1751,20 @@ Yul Control Flow Graph: "id": "Block2", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19_deployed" ], - "in": [], "op": "datasize", "out": [ "v4" ] }, { - "builtinArgs": [ + "in": [], + "literalArgs": [ "C_19_deployed" ], - "in": [], "op": "dataoffset", "out": [ "v5" @@ -1833,10 +1834,10 @@ Yul Control Flow Graph: "id": "Block0", "instructions": [ { - "builtinArgs": [ + "in": [], + "literalArgs": [ "0x80" ], - "in": [], "op": "memoryguard", "out": [ "v0" From 41eb541e5a2b5eacb36297a559d6aed3a976fa31 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 16 Apr 2025 14:18:26 +0200 Subject: [PATCH 0894/1340] Compare ethdebug output to program schema --- .circleci/config.yml | 18 +++++++ test/ethdebugSchemaTests/conftest.py | 49 ++++++++++++++++++ test/ethdebugSchemaTests/input_file.json | 27 ++++++++++ test/ethdebugSchemaTests/input_file_eof.json | 29 +++++++++++ .../test_ethdebug_schema_conformity.py | 51 +++++++++++++++++++ 5 files changed, 174 insertions(+) create mode 100644 test/ethdebugSchemaTests/conftest.py create mode 100644 test/ethdebugSchemaTests/input_file.json create mode 100644 test/ethdebugSchemaTests/input_file_eof.json create mode 100755 test/ethdebugSchemaTests/test_ethdebug_schema_conformity.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 6c88b9d19..def71c0bf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -952,6 +952,8 @@ jobs: chk_pylint: <<: *base_ubuntu2404_small steps: + - install_python3: + packages: pyyaml jsonschema pytest - checkout - run: pylint --version - run: @@ -1535,6 +1537,19 @@ jobs: - reports/externalTests/ - matrix_notify_failure_unless_pr + t_ethdebug_output_validity: + <<: *base_node_small + steps: + - checkout + - attach_workspace: + at: /tmp/workspace + - install_python3: + packages: pyyaml jsonschema pytest + - run: + name: Ethdebug validity tests + command: | + pytest test/ethdebugSchemaTests --solc-binary-path=/tmp/workspace/solc/solc-static-linux -v + c_ext_benchmarks: <<: *base_node_small steps: @@ -1928,6 +1943,9 @@ workflows: #- t_ext: *job_native_compile_ext_chainlink #- t_ext: *job_native_compile_ext_bleeps + - t_ethdebug_output_validity: + <<: *requires_b_ubu_static + - c_ext_benchmarks: <<: *requires_nothing requires: diff --git a/test/ethdebugSchemaTests/conftest.py b/test/ethdebugSchemaTests/conftest.py new file mode 100644 index 000000000..3f6a278f3 --- /dev/null +++ b/test/ethdebugSchemaTests/conftest.py @@ -0,0 +1,49 @@ +import shutil +import subprocess +from pathlib import Path + +import pytest +import referencing +import yaml +from referencing.jsonschema import DRAFT202012 + + +def pytest_addoption(parser): + parser.addoption("--solc-binary-path", type=Path, required=True, help="Path to the solidity compiler binary.") + + +@pytest.fixture +def solc_path(request): + solc_path = request.config.getoption("--solc-binary-path") + assert solc_path.is_file() + assert solc_path.exists() + return solc_path + + +@pytest.fixture(scope="module") +def ethdebug_clone_dir(tmpdir_factory): + temporary_dir = Path(tmpdir_factory.mktemp("data")) + yield temporary_dir + shutil.rmtree(temporary_dir) + + +@pytest.fixture(scope="module") +def ethdebug_schema_repository(ethdebug_clone_dir): + process = subprocess.run( + ["git", "clone", "https://github.com/ethdebug/format.git", ethdebug_clone_dir], + encoding="utf8", + capture_output=True, + check=True + ) + assert process.returncode == 0 + + registry = referencing.Registry() + for path in (ethdebug_clone_dir / "schemas").rglob("*.yaml"): + with open(path, "r", encoding="utf8") as f: + schema = yaml.safe_load(f) + if "$id" in schema: + resource = referencing.Resource.from_contents(schema, DRAFT202012) + registry = resource @ registry + else: + raise ValueError(f"Schema did not define an $id: {path}") + return registry diff --git a/test/ethdebugSchemaTests/input_file.json b/test/ethdebugSchemaTests/input_file.json new file mode 100644 index 000000000..7daf7afd6 --- /dev/null +++ b/test/ethdebugSchemaTests/input_file.json @@ -0,0 +1,27 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "viaIR": true, + "debug": { + "debugInfo": [ + "ethdebug" + ] + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug" + ] + } + } + } +} diff --git a/test/ethdebugSchemaTests/input_file_eof.json b/test/ethdebugSchemaTests/input_file_eof.json new file mode 100644 index 000000000..046206532 --- /dev/null +++ b/test/ethdebugSchemaTests/input_file_eof.json @@ -0,0 +1,29 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function a(uint x) public pure { assert(x > 0); } } contract A2 { function a(uint x) public pure { assert(x > 0); } }" + }, + "b.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract A1 { function b(uint x) public pure { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }" + } + }, + "settings": { + "eofVersion": 1, + "evmVersion": "osaka", + "viaIR": true, + "debug": { + "debugInfo": [ + "ethdebug" + ] + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug" + ] + } + } + } +} diff --git a/test/ethdebugSchemaTests/test_ethdebug_schema_conformity.py b/test/ethdebugSchemaTests/test_ethdebug_schema_conformity.py new file mode 100755 index 000000000..6a349e7b1 --- /dev/null +++ b/test/ethdebugSchemaTests/test_ethdebug_schema_conformity.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +import json +import subprocess +from pathlib import Path + +import jsonschema +import pytest + + +def get_nested_value(dictionary, *keys): + for key in keys: + dictionary = dictionary[key] + return dictionary + + +@pytest.fixture(params=["input_file.json", "input_file_eof.json"]) +def solc_output(request, solc_path): + testfile_dir = Path(__file__).parent + with open(testfile_dir / request.param, "r", encoding="utf8") as f: + source = json.load(f) + + process = subprocess.run( + [solc_path, "--standard-json"], + input=json.dumps(source), + encoding="utf8", + capture_output=True, + check=True, + ) + assert process.returncode == 0 + return json.loads(process.stdout) + + +@pytest.mark.parametrize("output_selection", ["evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"], ids=str) +def test_program_schema( + output_selection, + ethdebug_schema_repository, + solc_output +): + validator = jsonschema.Draft202012Validator( + schema={"$ref": "schema:ethdebug/format/program"}, + registry=ethdebug_schema_repository + ) + assert "contracts" in solc_output + for contract in solc_output["contracts"].keys(): + contract_output = solc_output["contracts"][contract] + assert len(contract_output) > 0 + for source in contract_output.keys(): + source_output = contract_output[source] + ethdebug_data = get_nested_value(source_output, *(output_selection.split("."))) + validator.validate(ethdebug_data) From b04a46b13b9b50770214b74e19158158d5684d12 Mon Sep 17 00:00:00 2001 From: Coder <161350311+MamunC0der@users.noreply.github.com> Date: Wed, 11 Jun 2025 18:56:03 +0200 Subject: [PATCH 0895/1340] Fix broken HackMD link in release checklist (#16080) * Update ReleaseChecklist.md --- ReleaseChecklist.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index c9fcaba79..acaabca63 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -26,7 +26,7 @@ At least a day before the release: This is recommended especially when dealing with PPA for the first time, when we add a new Ubuntu version or when the PPA scripts were modified in this release cycle. - [ ] Verify that the release tarball of `solc-js` works. Bump version locally, add `soljson.js` from CI, build it, compare the file structure with the previous version, install it locally and try to use it. -- [ ] Review [Learning from Past Releases](https://notes.ethereum.org/@solidity/release-mistakes) to make sure you don't repeat the same mistakes. +- [ ] Review [Learning from Past Releases](https://notes.argot.org/@solidity-release-mistakes) to make sure you don't repeat the same mistakes. ### Drafts At least a day before the release: @@ -119,6 +119,6 @@ At least a day before the release: - [ ] Share the announcement on [Project Updates](https://discord.com/channels/420394352083337236/798974456704925696) - [ ] Share the announcement on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im) - [ ] Share the announcement on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org) -- [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.ethereum.org/@solidity/release-mistakes). +- [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.argot.org/@solidity-release-mistakes). - [ ] Bump vendored dependencies. - [ ] Lean back, wait for bug reports and repeat from step 1 :). From 637a8a11da2892d4c65cdb7d5f843d5b559fe822 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 16 Jun 2025 14:48:04 +0200 Subject: [PATCH 0896/1340] Fix b_osx homebrew issue --- .circleci/osx_install_dependencies.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index 367e8cbb4..3ac380e36 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -48,6 +48,8 @@ function validate_checksum { if [ ! -f /usr/local/lib/libz3.a ] # if this file does not exists (cache was not restored), rebuild dependencies then + brew uninstall temurin17 + brew untap homebrew/homebrew-cask-versions brew update brew upgrade brew install cmake From 48d1c9f4c02fc7f789c19ba74c9e5c86974450e3 Mon Sep 17 00:00:00 2001 From: kilavvy <140459108+kilavvy@users.noreply.github.com> Date: Tue, 17 Jun 2025 13:14:44 +0200 Subject: [PATCH 0897/1340] Rename dev_return_desc_multiple_unamed_mixed.sol to dev_return_desc_multiple_unnamed_mixed.sol --- ...named_mixed.sol => dev_return_desc_multiple_unnamed_mixed.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/natspecJSON/{dev_return_desc_multiple_unamed_mixed.sol => dev_return_desc_multiple_unnamed_mixed.sol} (100%) diff --git a/test/libsolidity/natspecJSON/dev_return_desc_multiple_unamed_mixed.sol b/test/libsolidity/natspecJSON/dev_return_desc_multiple_unnamed_mixed.sol similarity index 100% rename from test/libsolidity/natspecJSON/dev_return_desc_multiple_unamed_mixed.sol rename to test/libsolidity/natspecJSON/dev_return_desc_multiple_unnamed_mixed.sol From e6d1fea4e183dae891c4be56b26d30530c7e3028 Mon Sep 17 00:00:00 2001 From: kilavvy <140459108+kilavvy@users.noreply.github.com> Date: Tue, 17 Jun 2025 13:16:16 +0200 Subject: [PATCH 0898/1340] Rename dev_return_desc_multiple_unamed_mixed_2.sol to dev_return_desc_multiple_unnamed_mixed_2.sol --- ...d_mixed_2.sol => dev_return_desc_multiple_unnamed_mixed_2.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/natspecJSON/{dev_return_desc_multiple_unamed_mixed_2.sol => dev_return_desc_multiple_unnamed_mixed_2.sol} (100%) diff --git a/test/libsolidity/natspecJSON/dev_return_desc_multiple_unamed_mixed_2.sol b/test/libsolidity/natspecJSON/dev_return_desc_multiple_unnamed_mixed_2.sol similarity index 100% rename from test/libsolidity/natspecJSON/dev_return_desc_multiple_unamed_mixed_2.sol rename to test/libsolidity/natspecJSON/dev_return_desc_multiple_unnamed_mixed_2.sol From 9a4100a08c711837c5f350eb0dc2608d6dabc1cf Mon Sep 17 00:00:00 2001 From: kilavvy <140459108+kilavvy@users.noreply.github.com> Date: Tue, 17 Jun 2025 13:16:53 +0200 Subject: [PATCH 0899/1340] Rename dev_return_desc_multiple_unamed.sol to dev_return_desc_multiple_unnamed.sol --- ...c_multiple_unamed.sol => dev_return_desc_multiple_unnamed.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/natspecJSON/{dev_return_desc_multiple_unamed.sol => dev_return_desc_multiple_unnamed.sol} (100%) diff --git a/test/libsolidity/natspecJSON/dev_return_desc_multiple_unamed.sol b/test/libsolidity/natspecJSON/dev_return_desc_multiple_unnamed.sol similarity index 100% rename from test/libsolidity/natspecJSON/dev_return_desc_multiple_unamed.sol rename to test/libsolidity/natspecJSON/dev_return_desc_multiple_unnamed.sol From 67288d658b1e0d0e6abdff6ca5787c24d6e3cf3f Mon Sep 17 00:00:00 2001 From: Emmanuel Ferdman Date: Wed, 21 May 2025 09:05:59 -0700 Subject: [PATCH 0900/1340] Correct the regex calls Signed-off-by: Emmanuel Ferdman --- scripts/wasm-rebuild/docker-scripts/isolate_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/wasm-rebuild/docker-scripts/isolate_tests.py b/scripts/wasm-rebuild/docker-scripts/isolate_tests.py index 41487325e..cc84f89bb 100755 --- a/scripts/wasm-rebuild/docker-scripts/isolate_tests.py +++ b/scripts/wasm-rebuild/docker-scripts/isolate_tests.py @@ -46,7 +46,7 @@ def extract_and_write(f, path): def write_cases(f, tests): cleaned_filename = f.replace(".","_").replace("-","_").replace(" ","_").lower() for test in tests: - remainder = re.sub(r'^ {4}', '', test, 0, re.MULTILINE) + remainder = re.sub(r'^ {4}', '', test, count=0, flags=re.MULTILINE) source_code_hash = hashlib.sha256(test).hexdigest() with open(f'test_{source_code_hash}_{cleaned_filename}.sol', 'w', encoding='utf8') as _f: _f.write(remainder) From fbd9d1a7fb2bc7139a6c293e7ccc6eb3e594c8df Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 3 Jul 2025 09:11:02 +0200 Subject: [PATCH 0901/1340] ci: add "--break-system-packages" to pip install `pip install` or even `pip install --user` on its own does not work anymore on recent ubuntu versions to prevent breaking system packages (PEP 0668) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index def71c0bf..8b69287b8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -127,7 +127,7 @@ commands: if [[ "<< parameters.packages >>" != "" ]] then echo "Installing additional packages..." - python3 -m pip install --user << parameters.packages >> + python3 -m pip install --user --break-system-packages << parameters.packages >> fi install_foundry: From aa1dae1f09500a785fb6770247d2d268ab8dae45 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 10 Jul 2025 14:13:40 +0200 Subject: [PATCH 0902/1340] external tests: pin gnosis to v1.4.1 it fails with a type error in OZ for v1.5.0 --- test/externalTests/gnosis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/gnosis.sh b/test/externalTests/gnosis.sh index 416d36153..397786d65 100755 --- a/test/externalTests/gnosis.sh +++ b/test/externalTests/gnosis.sh @@ -37,7 +37,7 @@ function test_fn { npm test; } function gnosis_safe_test { local repo="https://github.com/safe-global/safe-contracts.git" - local ref="" + local ref="v1.4.1" local config_file="hardhat.config.ts" local config_var=userConfig From 4efb2b33f998200bf74d03685e7fe9b523f3a343 Mon Sep 17 00:00:00 2001 From: emmmm <155267286+eeemmmmmm@users.noreply.github.com> Date: Wed, 2 Jul 2025 08:21:00 +0200 Subject: [PATCH 0903/1340] Replace string comparison with empty() method in DocStringParser --- libsolidity/parsing/DocStringParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/parsing/DocStringParser.cpp b/libsolidity/parsing/DocStringParser.cpp index b9f358e02..13e43a948 100644 --- a/libsolidity/parsing/DocStringParser.cpp +++ b/libsolidity/parsing/DocStringParser.cpp @@ -163,7 +163,7 @@ DocStringParser::iter DocStringParser::parseDocTag(iter _pos, iter _end, std::st { // TODO: need to check for @(start of a tag) between here and the end of line // for all cases. - if (!m_lastTag || _tag != "") + if (!m_lastTag || !_tag.empty()) { if (_tag == "param") return parseDocTagParam(_pos, _end); From a81065a01e9b0d3ab10849d3b2ca50f2bc9af6fd Mon Sep 17 00:00:00 2001 From: emmmm <155267286+eeemmmmmm@users.noreply.github.com> Date: Wed, 2 Jul 2025 08:21:32 +0200 Subject: [PATCH 0904/1340] Replace string comparison with empty() method in Parser --- libsolidity/parsing/Parser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 8889e6508..ddffdb600 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -217,7 +217,7 @@ void Parser::parsePragmaVersion(SourceLocation const& _location, std::vector Parser::parseStructuredDocumentation() { - if (m_scanner->currentCommentLiteral() != "") + if (!m_scanner->currentCommentLiteral().empty()) { ASTNodeFactory nodeFactory{*this}; nodeFactory.setLocation(m_scanner->currentCommentLocation()); @@ -1445,7 +1445,7 @@ ASTPointer Parser::parseStatement(bool _allowUnchecked) RecursionGuard recursionGuard(*this); ASTPointer docString; ASTPointer statement; - if (m_scanner->currentCommentLiteral() != "") + if (!m_scanner->currentCommentLiteral().empty()) docString = std::make_shared(m_scanner->currentCommentLiteral()); switch (m_scanner->currentToken()) { From 66541b9f265994e3f1eeb4d1b50b22b87d66f9a2 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 11 Jul 2025 09:05:19 +0200 Subject: [PATCH 0905/1340] yulrun: Move dialect check of parse step after analyze The yul stack only has a dialect set when it is past the analysis stage --- test/tools/yulrun.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index a5fa05d93..99d9df1a9 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -63,11 +63,11 @@ std::pair, std::shared_ptr> parse(st solidity::frontend::OptimiserSettings::none(), DebugInfoSelection::Default() ); - auto const* evmDialect = dynamic_cast(&stack.dialect()); - // TODO: Add EOF support - solUnimplementedAssert(evmDialect && !evmDialect->eofVersion(), "No EOF support for yulrun yet."); if (stack.parseAndAnalyze("--INPUT--", _source)) { + auto const* evmDialect = dynamic_cast(&stack.dialect()); + // TODO: Add EOF support + solUnimplementedAssert(evmDialect && !evmDialect->eofVersion(), "No EOF support for yulrun yet."); yulAssert(!Error::hasErrorsWarningsOrInfos(stack.errors()), "Parsed successfully but had errors."); return make_pair(stack.parserResult()->code(), stack.parserResult()->analysisInfo); } From 53df4b721445ee7ad891a7795a03f6bfcf6e0912 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 25 Apr 2025 14:04:14 +0200 Subject: [PATCH 0906/1340] Add EVMVersion::current() helper --- liblangutil/EVMVersion.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 38580621a..f771d9f1c 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -28,8 +28,6 @@ #include #include -#include - namespace solidity::evmasm { @@ -44,13 +42,13 @@ namespace solidity::langutil * A version specifier of the EVM we want to compile to. * Defaults to the latest version deployed on Ethereum Mainnet at the time of compiler release. */ -class EVMVersion: - boost::less_than_comparable, - boost::equality_comparable +class EVMVersion { public: EVMVersion() = default; + static EVMVersion current() { return {currentVersion}; } + static EVMVersion homestead() { return {Version::Homestead}; } static EVMVersion tangerineWhistle() { return {Version::TangerineWhistle}; } static EVMVersion spuriousDragon() { return {Version::SpuriousDragon}; } @@ -96,11 +94,10 @@ class EVMVersion: static EVMVersion firstWithEOF() { return {Version::Osaka}; } bool isExperimental() const { - return *this > EVMVersion{}; + return m_version > currentVersion; } - bool operator==(EVMVersion const& _other) const { return m_version == _other.m_version; } - bool operator<(EVMVersion const& _other) const { return m_version < _other.m_version; } + auto operator<=>(EVMVersion const&) const = default; std::string name() const { @@ -164,10 +161,11 @@ class EVMVersion: Prague, Osaka, }; + static auto constexpr currentVersion = Version::Prague; EVMVersion(Version _version): m_version(_version) {} - Version m_version = Version::Prague; + Version m_version = currentVersion; }; } From 70592afd73a9d8fe3bf6ae4598c6de6f495e66e5 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 20 Mar 2025 09:12:05 +0100 Subject: [PATCH 0907/1340] First define _all_ EVM functions, then declare them based on EVM version and configuration --- libyul/backends/evm/EVMDialect.cpp | 611 ++++++++++++++--------- libyul/backends/evm/EVMDialect.h | 2 +- libyul/backends/evm/NoOutputAssembly.cpp | 42 +- 3 files changed, 405 insertions(+), 250 deletions(-) diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index d68ef1634..87cd876ae 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -21,17 +21,21 @@ #include +#include #include #include -#include + #include #include #include #include #include -#include +#include + #include +#include +#include #include #include @@ -56,55 +60,32 @@ std::tuple constexpr verbatimIndexToArgsAndRets(size_t _index) return std::make_tuple(_index - numRets * EVMDialect::verbatimMaxInputSlots, numRets); } -BuiltinFunctionForEVM createEVMFunction( - langutil::EVMVersion _evmVersion, - std::string const& _name, - evmasm::Instruction _instruction -) +bool isLowLevelStackManipulationInstruction(evmasm::Instruction const& _instruction) { - BuiltinFunctionForEVM f; - evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction, _evmVersion); - f.name = _name; - f.numParameters = static_cast(info.args); - f.numReturns = static_cast(info.ret); - f.sideEffects = EVMDialect::sideEffectsOfInstruction(_instruction); - f.controlFlowSideEffects = ControlFlowSideEffects::fromInstruction(_instruction); - f.isMSize = _instruction == evmasm::Instruction::MSIZE; - f.literalArguments.clear(); - f.instruction = _instruction; - f.generateCode = [_instruction]( - FunctionCall const&, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - _assembly.appendInstruction(_instruction); - }; - return f; + return + _instruction == evmasm::Instruction::SWAPN || + evmasm::SemanticInformation::isSwapInstruction(_instruction) || + _instruction == evmasm::Instruction::DUPN || + evmasm::SemanticInformation::isDupInstruction(_instruction) || + isPushInstruction(_instruction); } -BuiltinFunctionForEVM createFunction( - std::string const& _name, - size_t _params, - size_t _returns, - SideEffects _sideEffects, - ControlFlowSideEffects _controlFlowSideEffects, - std::vector> _literalArguments, - std::function _generateCode -) +bool isLowLevelControlFlowInstruction(evmasm::Instruction const& _instruction) { - yulAssert(_literalArguments.size() == _params || _literalArguments.empty(), ""); - - BuiltinFunctionForEVM f; - f.name = _name; - f.numParameters = _params; - f.numReturns = _returns; - f.sideEffects = _sideEffects; - f.controlFlowSideEffects = _controlFlowSideEffects; - f.literalArguments = std::move(_literalArguments); - f.isMSize = false; - f.instruction = {}; - f.generateCode = std::move(_generateCode); - return f; + switch (_instruction) + { + case evmasm::Instruction::JUMP: + case evmasm::Instruction::JUMPI: + case evmasm::Instruction::JUMPDEST: + case evmasm::Instruction::JUMPF: + case evmasm::Instruction::RJUMP: + case evmasm::Instruction::RJUMPI: + case evmasm::Instruction::RETF: + case evmasm::Instruction::CALLF: + return true; + default: + return false; + } } std::set> createReservedIdentifiers(langutil::EVMVersion _evmVersion, std::optional _eofVersion) @@ -195,47 +176,7 @@ std::set> createReservedIdentifiers(langutil::EVMVersio return reserved; } -std::vector> createBuiltins(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess) -{ - - // Exclude prevrandao as builtin for VMs before paris and difficulty for VMs after paris. - auto prevRandaoException = [&](std::string const& _instrName) -> bool - { - return (_instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris()) || (_instrName == "difficulty" && _evmVersion >= langutil::EVMVersion::paris()); - }; - - std::vector> builtins; - for (auto const& instr: evmasm::c_instructions) - { - std::string name = toLower(instr.first); - auto const opcode = instr.second; - - if ( - !(opcode >= evmasm::Instruction::DUP1 && opcode <= evmasm::Instruction::DUP16) && - !(opcode >= evmasm::Instruction::SWAP1 && opcode <= evmasm::Instruction::SWAP16) && - !evmasm::isPushInstruction(opcode) && - opcode != evmasm::Instruction::JUMP && - opcode != evmasm::Instruction::JUMPI && - opcode != evmasm::Instruction::JUMPDEST && - opcode != evmasm::Instruction::DATALOADN && - opcode != evmasm::Instruction::EOFCREATE && - opcode != evmasm::Instruction::RETURNCONTRACT && - opcode != evmasm::Instruction::RJUMP && - opcode != evmasm::Instruction::RJUMPI && - opcode != evmasm::Instruction::CALLF && - opcode != evmasm::Instruction::JUMPF && - opcode != evmasm::Instruction::DUPN && - opcode != evmasm::Instruction::SWAPN && - opcode != evmasm::Instruction::RETF && - _evmVersion.hasOpcode(opcode, _eofVersion) && - !prevRandaoException(name) - ) - builtins.emplace_back(createEVMFunction(_evmVersion, name, opcode)); - else - builtins.emplace_back(std::nullopt); - } - - auto const createIfObjectAccess = [_objectAccess]( +BuiltinFunctionForEVM createFunction( std::string const& _name, size_t _params, size_t _returns, @@ -243,64 +184,200 @@ std::vector> createBuiltins(langutil::EVMVe ControlFlowSideEffects _controlFlowSideEffects, std::vector> _literalArguments, std::function _generateCode - ) -> std::optional + ) +{ + yulAssert(_literalArguments.size() == _params || _literalArguments.empty(), ""); + + BuiltinFunctionForEVM f; + f.name = _name; + f.numParameters = _params; + f.numReturns = _returns; + f.sideEffects = _sideEffects; + f.controlFlowSideEffects = _controlFlowSideEffects; + f.literalArguments = std::move(_literalArguments); + f.isMSize = false; + f.instruction = {}; + f.generateCode = std::move(_generateCode); + return f; +} + +class BuiltinFunctionCollection +{ + static size_t constexpr instructionBit = 0; + static size_t constexpr replacedInstructionBit = 1; + static size_t constexpr objectAccessBit = 2; + static size_t constexpr requiresEOFBit = 3; + static size_t constexpr requiresNonEOFBit = 4; +public: + struct BuiltinDescription { - if (!_objectAccess) - return std::nullopt; - return createFunction(_name, _params, _returns, _sideEffects, _controlFlowSideEffects, std::move(_literalArguments), std::move(_generateCode)); + /// whether the corresponding evm builtin function is an instruction builtin + bool instruction() const { return value.test(instructionBit); } + /// whether the corresponding evm builtin has been replaced by another builtin, ie, should be skipped + bool replaced() const { return value.test(replacedInstructionBit); } + /// if true, the evm builtin function is only valid when object access is given + bool requiresObjectAccess() const { return value.test(objectAccessBit); } + /// if true, the evm builtin function is only valid if EOF is enabled + bool requiresEOF() const { return value.test(requiresEOFBit); } + /// if true, the evm builtin function is only valid if EOF is not enabled + bool requiresNonEOF() const { return value.test(requiresNonEOFBit); } + + BuiltinDescription operator|(BuiltinDescription const& _other) const + { + return { value | _other.value }; + } + + std::bitset<5> value; }; - builtins.emplace_back(createIfObjectAccess("linkersymbol", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - _assembly.appendLinkerSymbol(formatLiteral(std::get(arg))); - })); - builtins.emplace_back(createIfObjectAccess( - "memoryguard", - 1, - 1, - SideEffects{}, - ControlFlowSideEffects{}, - {LiteralKind::Number}, - []( - FunctionCall const& _call, + static std::vector> const& builtins() + { + static BuiltinFunctionCollection const instance; + return instance.m_builtinFunctions; + } + +private: + static BuiltinDescription constexpr instruction{1 << instructionBit}; + static BuiltinDescription constexpr replaced{1 << replacedInstructionBit}; + static BuiltinDescription constexpr objectAccess{1 << objectAccessBit}; + static BuiltinDescription constexpr requiresEOF{1 << requiresEOFBit}; + static BuiltinDescription constexpr requiresNonEOF{1 << requiresNonEOFBit}; + + BuiltinFunctionCollection() + { + for (auto const& [name, opcode]: evmasm::c_instructions) + { + if (evmasm::SemanticInformation::isSwapInstruction(opcode) || evmasm::SemanticInformation::isDupInstruction(opcode)) + continue; + + if ( + opcode != evmasm::Instruction::DATALOADN && + opcode != evmasm::Instruction::EOFCREATE && + opcode != evmasm::Instruction::RETURNCONTRACT + ) + { + // difficulty was replaced by prevrandao after london + if (opcode == evmasm::Instruction::PREVRANDAO && name == "DIFFICULTY") + m_builtinFunctions.emplace_back(instruction, instructionBuiltin(opcode, langutil::EVMVersion::london())); + else + m_builtinFunctions.emplace_back(instruction, instructionBuiltin(opcode, langutil::EVMVersion::current())); + } + else + // these opcodes are replaced by explicit builtin functions + m_builtinFunctions.emplace_back(instruction | replaced, BuiltinFunctionForEVM{}); + } + + m_builtinFunctions.emplace_back(objectAccess, linkersymbolBuiltin()); + m_builtinFunctions.emplace_back(objectAccess, memoryguardBuiltin()); + + m_builtinFunctions.emplace_back(objectAccess | requiresNonEOF, datasizeBuiltin()); + m_builtinFunctions.emplace_back(objectAccess | requiresNonEOF, dataoffsetBuiltin()); + m_builtinFunctions.emplace_back(objectAccess | requiresNonEOF, datacopyBuiltin()); + m_builtinFunctions.emplace_back(objectAccess | requiresNonEOF, setimmutableBuiltin()); + m_builtinFunctions.emplace_back(objectAccess | requiresNonEOF, loadimmutableBuiltin()); + + m_builtinFunctions.emplace_back(objectAccess | requiresEOF, auxdataloadnBuiltin()); + m_builtinFunctions.emplace_back(objectAccess | requiresEOF, eofcreateBuiltin()); + m_builtinFunctions.emplace_back(objectAccess | requiresEOF, returncontractBuiltin()); + + yulAssert( + ranges::all_of(m_builtinFunctions, [](std::tuple const& _builtin) { + return std::get<1>(_builtin).name.substr(0, "verbatim_"s.size()) != "verbatim_"; + }), + "Builtin functions besides verbatim should not start with the verbatim_ prefix." + ); + } + + static BuiltinFunctionForEVM instructionBuiltin(evmasm::Instruction const& _instruction, langutil::EVMVersion const& _evmVersion) + { + evmasm::InstructionInfo const info = evmasm::instructionInfo(_instruction, _evmVersion); + BuiltinFunctionForEVM f; + f.name = toLower(info.name); + f.numParameters = static_cast(info.args); + f.numReturns = static_cast(info.ret); + f.sideEffects = EVMDialect::sideEffectsOfInstruction(_instruction); + f.controlFlowSideEffects = ControlFlowSideEffects::fromInstruction(_instruction); + f.isMSize = _instruction == evmasm::Instruction::MSIZE; + f.literalArguments.clear(); + f.instruction = _instruction; + f.generateCode = [_instruction]( + FunctionCall const&, AbstractAssembly& _assembly, BuiltinContext& - ) { - yulAssert(_call.arguments.size() == 1, ""); - Literal const* literal = std::get_if(&_call.arguments.front()); - yulAssert(literal, ""); - _assembly.appendConstant(literal->value.value()); - }) - ); - if (!_eofVersion.has_value()) + ) + { + _assembly.appendInstruction(_instruction); + }; + return f; + } + + static BuiltinFunctionForEVM linkersymbolBuiltin() { - builtins.emplace_back(createIfObjectAccess("datasize", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& _context - ) { - yulAssert(_context.currentObject, "No object available."); - yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - YulName const dataName (formatLiteral(std::get(arg))); - if (_context.currentObject->name == dataName.str()) - _assembly.appendAssemblySize(); - else - { - std::vector subIdPath = - _context.subIDs.count(dataName.str()) == 0 ? - _context.currentObject->pathToSubObject(dataName.str()) : - std::vector{_context.subIDs.at(dataName.str())}; - yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); - _assembly.appendDataSize(subIdPath); + return createFunction( + "linkersymbol", + 1, + 1, + SideEffects{}, + ControlFlowSideEffects{}, + {LiteralKind::String}, + [](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) { + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + _assembly.appendLinkerSymbol(formatLiteral(std::get(arg))); } - })); - builtins.emplace_back(createIfObjectAccess("dataoffset", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( + ); + } + + static BuiltinFunctionForEVM memoryguardBuiltin() + { + return createFunction( + "memoryguard", + 1, + 1, + SideEffects{}, + ControlFlowSideEffects{}, + {LiteralKind::Number}, + [](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) { + yulAssert(_call.arguments.size() == 1, ""); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal, ""); + _assembly.appendConstant(literal->value.value()); + } + ); + } + + static BuiltinFunctionForEVM datasizeBuiltin() + { + return createFunction( + "datasize", + 1, + 1, + SideEffects{}, + ControlFlowSideEffects{}, + {LiteralKind::String}, + [](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& _context) { + yulAssert(_context.currentObject, "No object available."); + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + YulName const dataName (formatLiteral(std::get(arg))); + if (_context.currentObject->name == dataName.str()) + _assembly.appendAssemblySize(); + else + { + std::vector subIdPath = + _context.subIDs.count(dataName.str()) == 0 ? + _context.currentObject->pathToSubObject(dataName.str()) : + std::vector{_context.subIDs.at(dataName.str())}; + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + _assembly.appendDataSize(subIdPath); + } + } + ); + } + + static BuiltinFunctionForEVM dataoffsetBuiltin() + { + return createFunction("dataoffset", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& _context @@ -320,8 +397,12 @@ std::vector> createBuiltins(langutil::EVMVe yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); _assembly.appendDataOffset(subIdPath); } - })); - builtins.emplace_back(createIfObjectAccess( + }); + } + + static BuiltinFunctionForEVM datacopyBuiltin() + { + return createFunction( "datacopy", 3, 0, @@ -335,8 +416,12 @@ std::vector> createBuiltins(langutil::EVMVe ) { _assembly.appendInstruction(evmasm::Instruction::CODECOPY); } - )); - builtins.emplace_back(createIfObjectAccess( + ); + } + + static BuiltinFunctionForEVM setimmutableBuiltin() + { + return createFunction( "setimmutable", 3, 0, @@ -362,8 +447,12 @@ std::vector> createBuiltins(langutil::EVMVe auto const identifier = (formatLiteral(std::get(_call.arguments[1]))); _assembly.appendImmutableAssignment(identifier); } - )); - builtins.emplace_back(createIfObjectAccess( + ); + } + + static BuiltinFunctionForEVM loadimmutableBuiltin() + { + return createFunction( "loadimmutable", 1, 1, @@ -378,86 +467,131 @@ std::vector> createBuiltins(langutil::EVMVe yulAssert(_call.arguments.size() == 1, ""); _assembly.appendImmutable(formatLiteral(std::get(_call.arguments.front()))); } - )); + ); + } + + static BuiltinFunctionForEVM auxdataloadnBuiltin() + { + return createFunction( + "auxdataloadn", + 1, + 1, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::DATALOADN), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::DATALOADN), + {LiteralKind::Number}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == 1); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal, ""); + yulAssert(literal->value.value() <= std::numeric_limits::max()); + _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); + } + ); + } + + static BuiltinFunctionForEVM eofcreateBuiltin() + { + return createFunction( + "eofcreate", + 5, + 1, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE), + {LiteralKind::String, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& context + ) { + yulAssert(_call.arguments.size() == 5); + Literal const* literal = std::get_if(&_call.arguments.front()); + auto const formattedLiteral = formatLiteral(*literal); + yulAssert(!util::contains(formattedLiteral, '.')); + auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); + yulAssert(containerID != nullptr); + yulAssert(*containerID <= std::numeric_limits::max()); + _assembly.appendEOFCreate(static_cast(*containerID)); + } + ); } - else // EOF context + + static BuiltinFunctionForEVM returncontractBuiltin() { - if (_objectAccess) + return createFunction( + "returncontract", + 3, + 0, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::RETURNCONTRACT), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::RETURNCONTRACT), + {LiteralKind::String, std::nullopt, std::nullopt}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& context + ) { + yulAssert(_call.arguments.size() == 3); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal); + auto const formattedLiteral = formatLiteral(*literal); + yulAssert(!util::contains(formattedLiteral, '.')); + auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); + yulAssert(containerID != nullptr); + yulAssert(*containerID <= std::numeric_limits::max()); + _assembly.appendReturnContract(static_cast(*containerID)); + } + ); + } + + std::vector> m_builtinFunctions; +}; + +/// Make sure to only add builtins in a way that is consistent over EVM versions. If the order depends on the +/// EVM version - which can easily happen using conditionals -, different dialects' builtin handles +/// become inherently incompatible. +std::vector createBuiltins(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess) +{ + std::vector builtins; + builtins.reserve(BuiltinFunctionCollection::builtins().size()); + + for (auto const& [description, builtin]: BuiltinFunctionCollection::builtins()) + { + bool builtinShouldBeAdded = true; + if (description.instruction()) { - builtins.emplace_back(createFunction( - "auxdataloadn", - 1, - 1, - EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::DATALOADN), - ControlFlowSideEffects::fromInstruction(evmasm::Instruction::DATALOADN), - {LiteralKind::Number}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == 1); - Literal const* literal = std::get_if(&_call.arguments.front()); - yulAssert(literal, ""); - yulAssert(literal->value.value() <= std::numeric_limits::max()); - _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); - } - )); - - builtins.emplace_back(createFunction( - "eofcreate", - 5, - 1, - EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE), - ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE), - {LiteralKind::String, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& context - ) { - yulAssert(_call.arguments.size() == 5); - Literal const* literal = std::get_if(&_call.arguments.front()); - auto const formattedLiteral = formatLiteral(*literal); - yulAssert(!util::contains(formattedLiteral, '.')); - auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); - yulAssert(containerID != nullptr); - yulAssert(*containerID <= std::numeric_limits::max()); - _assembly.appendEOFCreate(static_cast(*containerID)); - } - )); - - builtins.emplace_back(createFunction( - "returncontract", - 3, - 0, - EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::RETURNCONTRACT), - ControlFlowSideEffects::fromInstruction(evmasm::Instruction::RETURNCONTRACT), - {LiteralKind::String, std::nullopt, std::nullopt}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& context - ) { - yulAssert(_call.arguments.size() == 3); - Literal const* literal = std::get_if(&_call.arguments.front()); - yulAssert(literal); - auto const formattedLiteral = formatLiteral(*literal); - yulAssert(!util::contains(formattedLiteral, '.')); - auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); - yulAssert(containerID != nullptr); - yulAssert(*containerID <= std::numeric_limits::max()); - _assembly.appendReturnContract(static_cast(*containerID)); - } - )); + if (description.replaced()) + builtinShouldBeAdded = false; + else + { + // Exclude prevrandao as builtin for VMs before paris and difficulty for VMs after paris. + auto prevRandaoException = [&](std::string_view const _instrName) -> bool + { + return (_instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris()) || (_instrName == "difficulty" && _evmVersion >= langutil::EVMVersion::paris()); + }; + + yulAssert(builtin.instruction); + auto const& _opcode = *builtin.instruction; + builtinShouldBeAdded = + !isLowLevelControlFlowInstruction(_opcode) && + !isLowLevelStackManipulationInstruction(_opcode) && + _evmVersion.hasOpcode(_opcode, _eofVersion) && + !prevRandaoException(builtin.name); + } } + + builtinShouldBeAdded &= !description.requiresObjectAccess() || _objectAccess; + builtinShouldBeAdded &= !description.requiresEOF() || _eofVersion.has_value(); + builtinShouldBeAdded &= !description.requiresNonEOF() || !_eofVersion.has_value(); + + if (builtinShouldBeAdded) + builtins.emplace_back(&builtin); + else + builtins.emplace_back(nullptr); } - yulAssert( - ranges::all_of(builtins, [](std::optional const& _builtinFunction){ - return !_builtinFunction || _builtinFunction->name.substr(0, "verbatim_"s.size()) != "verbatim_"; - }), - "Builtin functions besides verbatim should not start with the verbatim_ prefix." - ); + return builtins; } @@ -482,14 +616,14 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, std::optional // ids are offset by the maximum number of verbatim functions m_builtinFunctionsByName[maybeBuiltin->name] = BuiltinHandle{index + verbatimIDOffset}; - m_discardFunction = findBuiltin("pop"); - m_equalityFunction = findBuiltin("eq"); - m_booleanNegationFunction = findBuiltin("iszero"); - m_memoryStoreFunction = findBuiltin("mstore"); - m_memoryLoadFunction = findBuiltin("mload"); - m_storageStoreFunction = findBuiltin("sstore"); - m_storageLoadFunction = findBuiltin("sload"); - m_hashFunction = findBuiltin("keccak256"); + m_discardFunction = EVMDialect::findBuiltin("pop"); + m_equalityFunction = EVMDialect::findBuiltin("eq"); + m_booleanNegationFunction = EVMDialect::findBuiltin("iszero"); + m_memoryStoreFunction = EVMDialect::findBuiltin("mstore"); + m_memoryLoadFunction = EVMDialect::findBuiltin("mload"); + m_storageStoreFunction = EVMDialect::findBuiltin("sstore"); + m_storageLoadFunction = EVMDialect::findBuiltin("sload"); + m_hashFunction = EVMDialect::findBuiltin("keccak256"); m_auxiliaryBuiltinHandles.add = EVMDialect::findBuiltin("add"); m_auxiliaryBuiltinHandles.exp = EVMDialect::findBuiltin("exp"); @@ -529,8 +663,8 @@ BuiltinFunctionForEVM const& EVMDialect::builtin(BuiltinHandle const& _handle) c } yulAssert(_handle.id - verbatimIDOffset < m_functions.size()); - auto const& maybeBuiltin = m_functions[_handle.id - verbatimIDOffset]; - yulAssert(maybeBuiltin.has_value()); + auto const* maybeBuiltin = m_functions[_handle.id - verbatimIDOffset]; + yulAssert(maybeBuiltin); return *maybeBuiltin; } @@ -563,22 +697,7 @@ EVMDialect const& EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion _ SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instruction) { - auto translate = [](evmasm::SemanticInformation::Effect _e) -> SideEffects::Effect - { - return static_cast(_e); - }; - - return SideEffects{ - evmasm::SemanticInformation::movable(_instruction), - evmasm::SemanticInformation::movableApartFromEffects(_instruction), - evmasm::SemanticInformation::canBeRemoved(_instruction), - evmasm::SemanticInformation::canBeRemovedIfNoMSize(_instruction), - true, // cannotLoop - translate(evmasm::SemanticInformation::otherState(_instruction)), - translate(evmasm::SemanticInformation::storage(_instruction)), - translate(evmasm::SemanticInformation::memory(_instruction)), - translate(evmasm::SemanticInformation::transientStorage(_instruction)), - }; + return ranges::views::keys(m_builtinFunctionsByName) | ranges::to; } BuiltinFunctionForEVM EVMDialect::createVerbatimFunctionFromHandle(BuiltinHandle const& _handle) diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 0440daade..73136ef6e 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -125,7 +125,7 @@ class EVMDialect: public Dialect langutil::EVMVersion const m_evmVersion; std::optional m_eofVersion; std::unordered_map m_builtinFunctionsByName; - std::vector> m_functions; + std::vector m_functions; std::array, verbatimIDOffset> mutable m_verbatimFunctions{}; std::set> m_reserved; diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 78025265f..55e034399 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -207,9 +207,45 @@ void NoOutputAssembly::appendReturnContract(ContainerID) NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom): EVMDialect(_copyFrom.evmVersion(), _copyFrom.eofVersion(), _copyFrom.providesObjectAccess()) { - for (auto& fun: m_functions) - if (fun) - modifyBuiltinToNoOutput(*fun); + // save the modified functions here - note that this only has to be done once because we modify all of + // them in one go, later just reference pointers to this static vector + static std::vector const noOutputBuiltins = [] + { + std::vector modifiedBuiltins; + modifiedBuiltins.reserve(allBuiltins().functions().size()); + + for (auto const& [_, builtin]: allBuiltins().functions()) + { + auto noOutputFunction = builtin; + modifyBuiltinToNoOutput(noOutputFunction); + modifiedBuiltins.push_back(std::move(noOutputFunction)); + } + + return modifiedBuiltins; + }(); + + m_functions = [&] + { + std::vector result; + result.reserve(m_functions.size()); + for (auto const* builtinFunction: m_functions) + { + if (builtinFunction) + { + auto it = noOutputBuiltins.find(builtinFunction); + if (it == noOutputBuiltins.end()) + { + auto noOutputFunction = *builtinFunction; + modifyBuiltinToNoOutput(noOutputFunction); + it = noOutputBuiltins.emplace(builtinFunction, std::move(noOutputFunction)).first; + } + result.emplace_back(&it->second); + } + else + result.emplace_back(nullptr); + } + return result; + }(); } BuiltinFunctionForEVM const& NoOutputEVMDialect::builtin(BuiltinHandle const& _handle) const From 90078897b6dd0f4455908594feee85fef37df0e1 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 28 Apr 2025 10:48:06 +0200 Subject: [PATCH 0908/1340] Separate out builtin function collection into its own class This makes for a better separation between the declarations and the logic that defines builtins. # Conflicts: # libyul/backends/evm/EVMDialect.cpp --- libyul/CMakeLists.txt | 2 + libyul/backends/evm/EVMBuiltins.cpp | 419 +++++++++++++++++++++ libyul/backends/evm/EVMBuiltins.h | 120 ++++++ libyul/backends/evm/EVMDialect.cpp | 444 ++--------------------- libyul/backends/evm/EVMDialect.h | 36 +- libyul/backends/evm/NoOutputAssembly.cpp | 61 ++-- libyul/backends/evm/NoOutputAssembly.h | 3 + 7 files changed, 601 insertions(+), 484 deletions(-) create mode 100644 libyul/backends/evm/EVMBuiltins.cpp create mode 100644 libyul/backends/evm/EVMBuiltins.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 68756fca9..58390d956 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -58,6 +58,8 @@ add_library(yul backends/evm/ControlFlowGraphBuilder.h backends/evm/EthAssemblyAdapter.cpp backends/evm/EthAssemblyAdapter.h + backends/evm/EVMBuiltins.cpp + backends/evm/EVMBuiltins.h backends/evm/EVMCodeTransform.cpp backends/evm/EVMCodeTransform.h backends/evm/EVMDialect.cpp diff --git a/libyul/backends/evm/EVMBuiltins.cpp b/libyul/backends/evm/EVMBuiltins.cpp new file mode 100644 index 000000000..d8a3d5c8e --- /dev/null +++ b/libyul/backends/evm/EVMBuiltins.cpp @@ -0,0 +1,419 @@ +/* + 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 + +#include + +#include +#include +#include + +#include + +#include + +#include + +using namespace solidity; +using namespace solidity::yul; + +namespace +{ + +BuiltinFunctionForEVM createFunction( + std::string const& _name, + size_t _params, + size_t _returns, + SideEffects _sideEffects, + ControlFlowSideEffects _controlFlowSideEffects, + std::vector> _literalArguments, + std::function _generateCode +) +{ + yulAssert(_literalArguments.size() == _params || _literalArguments.empty(), ""); + + BuiltinFunctionForEVM f; + f.name = _name; + f.numParameters = _params; + f.numReturns = _returns; + f.sideEffects = _sideEffects; + f.controlFlowSideEffects = _controlFlowSideEffects; + f.literalArguments = std::move(_literalArguments); + f.isMSize = false; + f.instruction = {}; + f.generateCode = std::move(_generateCode); + return f; +} + +BuiltinFunctionForEVM instructionBuiltin(evmasm::Instruction const& _instruction, langutil::EVMVersion const& _evmVersion) +{ + evmasm::InstructionInfo const info = evmasm::instructionInfo(_instruction, _evmVersion); + BuiltinFunctionForEVM f; + f.name = util::toLower(info.name); + f.numParameters = static_cast(info.args); + f.numReturns = static_cast(info.ret); + f.sideEffects = EVMBuiltins::sideEffectsOfInstruction(_instruction); + f.controlFlowSideEffects = ControlFlowSideEffects::fromInstruction(_instruction); + f.isMSize = _instruction == evmasm::Instruction::MSIZE; + f.literalArguments.clear(); + f.instruction = _instruction; + f.generateCode = [_instruction]( + FunctionCall const&, + AbstractAssembly& _assembly, + BuiltinContext& + ) + { + _assembly.appendInstruction(_instruction); + }; + return f; +} + +BuiltinFunctionForEVM linkersymbolBuiltin() +{ + return createFunction( + "linkersymbol", + 1, + 1, + SideEffects{}, + ControlFlowSideEffects{}, + {LiteralKind::String}, + [](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) { + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + _assembly.appendLinkerSymbol(formatLiteral(std::get(arg))); + } + ); +} + +BuiltinFunctionForEVM memoryguardBuiltin() +{ + return createFunction( + "memoryguard", + 1, + 1, + SideEffects{}, + ControlFlowSideEffects{}, + {LiteralKind::Number}, + [](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) { + yulAssert(_call.arguments.size() == 1, ""); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal, ""); + _assembly.appendConstant(literal->value.value()); + } + ); +} + +BuiltinFunctionForEVM datasizeBuiltin() +{ + return createFunction( + "datasize", + 1, + 1, + SideEffects{}, + ControlFlowSideEffects{}, + {LiteralKind::String}, + [](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& _context) { + yulAssert(_context.currentObject, "No object available."); + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + YulName const dataName (formatLiteral(std::get(arg))); + if (_context.currentObject->name == dataName.str()) + _assembly.appendAssemblySize(); + else + { + std::vector subIdPath = + _context.subIDs.count(dataName.str()) == 0 ? + _context.currentObject->pathToSubObject(dataName.str()) : + std::vector{_context.subIDs.at(dataName.str())}; + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + _assembly.appendDataSize(subIdPath); + } + } + ); +} + +BuiltinFunctionForEVM dataoffsetBuiltin() +{ + return createFunction("dataoffset", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& _context + ) { + yulAssert(_context.currentObject, "No object available."); + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + YulName const dataName (formatLiteral(std::get(arg))); + if (_context.currentObject->name == dataName.str()) + _assembly.appendConstant(0); + else + { + std::vector subIdPath = + _context.subIDs.count(dataName.str()) == 0 ? + _context.currentObject->pathToSubObject(dataName.str()) : + std::vector{_context.subIDs.at(dataName.str())}; + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + _assembly.appendDataOffset(subIdPath); + } + }); +} + +BuiltinFunctionForEVM datacopyBuiltin() +{ + return createFunction( + "datacopy", + 3, + 0, + EVMBuiltins::sideEffectsOfInstruction(evmasm::Instruction::CODECOPY), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::CODECOPY), + {}, + []( + FunctionCall const&, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + _assembly.appendInstruction(evmasm::Instruction::CODECOPY); + } + ); +} + +BuiltinFunctionForEVM setimmutableBuiltin() +{ + return createFunction( + "setimmutable", + 3, + 0, + SideEffects{ + false, // movable + false, // movableApartFromEffects + false, // canBeRemoved + false, // canBeRemovedIfNotMSize + true, // cannotLoop + SideEffects::None, // otherState + SideEffects::None, // storage + SideEffects::Write, // memory + SideEffects::None // transientStorage + }, + ControlFlowSideEffects{}, + {std::nullopt, LiteralKind::String, std::nullopt}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == 3, ""); + auto const identifier = (formatLiteral(std::get(_call.arguments[1]))); + _assembly.appendImmutableAssignment(identifier); + } + ); +} + +BuiltinFunctionForEVM loadimmutableBuiltin() +{ + return createFunction( + "loadimmutable", + 1, + 1, + SideEffects{}, + ControlFlowSideEffects{}, + {LiteralKind::String}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == 1, ""); + _assembly.appendImmutable(formatLiteral(std::get(_call.arguments.front()))); + } + ); +} + +BuiltinFunctionForEVM auxdataloadnBuiltin() +{ + return createFunction( + "auxdataloadn", + 1, + 1, + EVMBuiltins::sideEffectsOfInstruction(evmasm::Instruction::DATALOADN), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::DATALOADN), + {LiteralKind::Number}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == 1); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal, ""); + yulAssert(literal->value.value() <= std::numeric_limits::max()); + _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); + } + ); +} + +BuiltinFunctionForEVM eofcreateBuiltin() +{ + return createFunction( + "eofcreate", + 5, + 1, + EVMBuiltins::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE), + {LiteralKind::String, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& context + ) { + yulAssert(_call.arguments.size() == 5); + Literal const* literal = std::get_if(&_call.arguments.front()); + auto const formattedLiteral = formatLiteral(*literal); + yulAssert(!util::contains(formattedLiteral, '.')); + auto const* containerID = util::valueOrNullptr(context.subIDs, formattedLiteral); + yulAssert(containerID != nullptr); + yulAssert(*containerID <= std::numeric_limits::max()); + _assembly.appendEOFCreate(static_cast(*containerID)); + } + ); +} + +BuiltinFunctionForEVM returncontractBuiltin() +{ + return createFunction( + "returncontract", + 3, + 0, + EVMBuiltins::sideEffectsOfInstruction(evmasm::Instruction::RETURNCONTRACT), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::RETURNCONTRACT), + {LiteralKind::String, std::nullopt, std::nullopt}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& context + ) { + yulAssert(_call.arguments.size() == 3); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal); + auto const formattedLiteral = formatLiteral(*literal); + yulAssert(!util::contains(formattedLiteral, '.')); + auto const* containerID = util::valueOrNullptr(context.subIDs, formattedLiteral); + yulAssert(containerID != nullptr); + yulAssert(*containerID <= std::numeric_limits::max()); + _assembly.appendReturnContract(static_cast(*containerID)); + } + ); +} + +} + +EVMBuiltins::EVMBuiltins() +{ + for (auto const& [name, opcode]: evmasm::c_instructions) + { + if ( + opcode == evmasm::Instruction::SWAPN || + opcode == evmasm::Instruction::DUPN || + evmasm::SemanticInformation::isSwapInstruction(opcode) || + evmasm::SemanticInformation::isDupInstruction(opcode) + ) + continue; + + // difficulty was replaced by prevrandao after london + if (opcode == evmasm::Instruction::PREVRANDAO && name == "DIFFICULTY") + m_scopesAndFunctions.emplace_back(instruction, instructionBuiltin(opcode, langutil::EVMVersion::london())); + else + m_scopesAndFunctions.emplace_back(instruction, instructionBuiltin(opcode, langutil::EVMVersion::current())); + + // these are replaced by 'proper' builtin functions + if ( + opcode == evmasm::Instruction::DATALOADN || + opcode == evmasm::Instruction::EOFCREATE || + opcode == evmasm::Instruction::RETURNCONTRACT + ) + std::get<0>(m_scopesAndFunctions.back()) |= replaced; + } + + m_scopesAndFunctions.emplace_back(objectAccess, linkersymbolBuiltin()); + m_scopesAndFunctions.emplace_back(objectAccess, memoryguardBuiltin()); + + m_scopesAndFunctions.emplace_back(objectAccess | requiresNonEOF, datasizeBuiltin()); + m_scopesAndFunctions.emplace_back(objectAccess | requiresNonEOF, dataoffsetBuiltin()); + m_scopesAndFunctions.emplace_back(objectAccess | requiresNonEOF, datacopyBuiltin()); + m_scopesAndFunctions.emplace_back(objectAccess | requiresNonEOF, setimmutableBuiltin()); + m_scopesAndFunctions.emplace_back(objectAccess | requiresNonEOF, loadimmutableBuiltin()); + + m_scopesAndFunctions.emplace_back(objectAccess | requiresEOF, auxdataloadnBuiltin()); + m_scopesAndFunctions.emplace_back(objectAccess | requiresEOF, eofcreateBuiltin()); + m_scopesAndFunctions.emplace_back(objectAccess | requiresEOF, returncontractBuiltin()); + + static size_t constexpr verbatimPrefixLength = std::char_traits::length("verbatim_"); + for (auto const& [scope, builtin]: m_scopesAndFunctions) + { + yulAssert( + builtin.name.substr(0, verbatimPrefixLength) != "verbatim_", + "Builtin functions besides verbatim should not start with the verbatim_ prefix." + ); + yulAssert(!(scope.requiresEOF() && scope.requiresNonEOF()), "Mutually exclusive scopes"); + } +} + +BuiltinFunctionForEVM EVMBuiltins::createVerbatimFunction(size_t const _arguments, size_t const _returnVariables) +{ + BuiltinFunctionForEVM builtinFunction = createFunction( + "verbatim_" + std::to_string(_arguments) + "i_" + std::to_string(_returnVariables) + "o", + 1 + _arguments, + _returnVariables, + SideEffects::worst(), + ControlFlowSideEffects::worst(), // Worst control flow side effects because verbatim can do anything. + std::vector>{LiteralKind::String} + std::vector>(_arguments), + [=]( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == (1 + _arguments), ""); + Expression const& bytecode = _call.arguments.front(); + + _assembly.appendVerbatim( + util::asBytes(formatLiteral(std::get(bytecode))), + _arguments, + _returnVariables + ); + } + ); + builtinFunction.isMSize = true; + return builtinFunction; +} + +SideEffects EVMBuiltins::sideEffectsOfInstruction(evmasm::Instruction _instruction) +{ + auto translate = [](evmasm::SemanticInformation::Effect _e) -> SideEffects::Effect + { + return static_cast(_e); + }; + + return SideEffects{ + evmasm::SemanticInformation::movable(_instruction), + evmasm::SemanticInformation::movableApartFromEffects(_instruction), + evmasm::SemanticInformation::canBeRemoved(_instruction), + evmasm::SemanticInformation::canBeRemovedIfNoMSize(_instruction), + true, // cannotLoop + translate(evmasm::SemanticInformation::otherState(_instruction)), + translate(evmasm::SemanticInformation::storage(_instruction)), + translate(evmasm::SemanticInformation::memory(_instruction)), + translate(evmasm::SemanticInformation::transientStorage(_instruction)), + }; +} diff --git a/libyul/backends/evm/EVMBuiltins.h b/libyul/backends/evm/EVMBuiltins.h new file mode 100644 index 000000000..c4b383dda --- /dev/null +++ b/libyul/backends/evm/EVMBuiltins.h @@ -0,0 +1,120 @@ +/* + 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 + +#pragma once + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace solidity::yul +{ + +class Object; + +/// Context used during code generation. +struct BuiltinContext +{ + Object const* currentObject = nullptr; + /// Mapping from named objects to abstract assembly sub IDs. + std::map subIDs; + + std::map functionIDs; +}; + +struct BuiltinFunctionForEVM: public BuiltinFunction +{ + std::optional instruction; + /// Function to generate code for the given function call and append it to the abstract + /// assembly. Expects all non-literal arguments of the call to be on stack in reverse order + /// (i.e. right-most argument pushed first). + /// Expects the caller to set the source location. + std::function generateCode; +}; + +/// Collection of all possible EVM builtin functions. +/// Each builtin can have one (or multiple) scopes, which define whether, e.g., it requires object access. +/// Using this class as single source of truth for builtin functions makes sure that these are consistent over +/// EVM dialects. If the order were to depend on the EVM dialect - which can easily happen using conditionals -, +/// different dialects' builtin handles become inherently incompatible. +class EVMBuiltins +{ + static std::size_t constexpr instructionBit = 0; + static std::size_t constexpr replacedInstructionBit = 1; + static std::size_t constexpr objectAccessBit = 2; + static std::size_t constexpr requiresEOFBit = 3; + static std::size_t constexpr requiresNonEOFBit = 4; + +public: + struct Scopes + { + /// whether the corresponding evm builtin function is an instruction builtin + bool instruction() const { return value.test(instructionBit); } + /// whether the corresponding evm builtin has been replaced by another builtin, ie, should be skipped + bool replaced() const { return value.test(replacedInstructionBit); } + /// if true, the evm builtin function is only valid when object access is given + bool requiresObjectAccess() const { return value.test(objectAccessBit); } + /// if true, the evm builtin function is only valid if EOF is enabled + bool requiresEOF() const { return value.test(requiresEOFBit); } + /// if true, the evm builtin function is only valid if EOF is not enabled + bool requiresNonEOF() const { return value.test(requiresNonEOFBit); } + + Scopes operator|(Scopes const& _other) const + { + Scopes result = *this; + result |= _other; + return result; + } + + Scopes& operator|=(Scopes const& _other) + { + value |= _other.value; + return *this; + } + + std::bitset<5> value; + }; + + EVMBuiltins(); + + std::vector> const& functions() const { return m_scopesAndFunctions; } + + /// Creates a verbatim builtin function. These are not part of the usual builtin functions collection and + /// must be cached in the dialect creating them. + static BuiltinFunctionForEVM createVerbatimFunction(size_t _arguments, size_t _returnVariables); + static SideEffects sideEffectsOfInstruction(evmasm::Instruction _instruction); + +private: + static Scopes constexpr instruction{1 << instructionBit}; + static Scopes constexpr replaced{1 << replacedInstructionBit}; + static Scopes constexpr objectAccess{1 << objectAccessBit}; + static Scopes constexpr requiresEOF{1 << requiresEOFBit}; + static Scopes constexpr requiresNonEOF{1 << requiresNonEOFBit}; + + std::vector> m_scopesAndFunctions; +}; + +} diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 87cd876ae..c903b9c4d 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include @@ -176,393 +175,22 @@ std::set> createReservedIdentifiers(langutil::EVMVersio return reserved; } -BuiltinFunctionForEVM createFunction( - std::string const& _name, - size_t _params, - size_t _returns, - SideEffects _sideEffects, - ControlFlowSideEffects _controlFlowSideEffects, - std::vector> _literalArguments, - std::function _generateCode - ) -{ - yulAssert(_literalArguments.size() == _params || _literalArguments.empty(), ""); - - BuiltinFunctionForEVM f; - f.name = _name; - f.numParameters = _params; - f.numReturns = _returns; - f.sideEffects = _sideEffects; - f.controlFlowSideEffects = _controlFlowSideEffects; - f.literalArguments = std::move(_literalArguments); - f.isMSize = false; - f.instruction = {}; - f.generateCode = std::move(_generateCode); - return f; -} - -class BuiltinFunctionCollection -{ - static size_t constexpr instructionBit = 0; - static size_t constexpr replacedInstructionBit = 1; - static size_t constexpr objectAccessBit = 2; - static size_t constexpr requiresEOFBit = 3; - static size_t constexpr requiresNonEOFBit = 4; -public: - struct BuiltinDescription - { - /// whether the corresponding evm builtin function is an instruction builtin - bool instruction() const { return value.test(instructionBit); } - /// whether the corresponding evm builtin has been replaced by another builtin, ie, should be skipped - bool replaced() const { return value.test(replacedInstructionBit); } - /// if true, the evm builtin function is only valid when object access is given - bool requiresObjectAccess() const { return value.test(objectAccessBit); } - /// if true, the evm builtin function is only valid if EOF is enabled - bool requiresEOF() const { return value.test(requiresEOFBit); } - /// if true, the evm builtin function is only valid if EOF is not enabled - bool requiresNonEOF() const { return value.test(requiresNonEOFBit); } - - BuiltinDescription operator|(BuiltinDescription const& _other) const - { - return { value | _other.value }; - } - - std::bitset<5> value; - }; - - static std::vector> const& builtins() - { - static BuiltinFunctionCollection const instance; - return instance.m_builtinFunctions; - } - -private: - static BuiltinDescription constexpr instruction{1 << instructionBit}; - static BuiltinDescription constexpr replaced{1 << replacedInstructionBit}; - static BuiltinDescription constexpr objectAccess{1 << objectAccessBit}; - static BuiltinDescription constexpr requiresEOF{1 << requiresEOFBit}; - static BuiltinDescription constexpr requiresNonEOF{1 << requiresNonEOFBit}; - - BuiltinFunctionCollection() - { - for (auto const& [name, opcode]: evmasm::c_instructions) - { - if (evmasm::SemanticInformation::isSwapInstruction(opcode) || evmasm::SemanticInformation::isDupInstruction(opcode)) - continue; - - if ( - opcode != evmasm::Instruction::DATALOADN && - opcode != evmasm::Instruction::EOFCREATE && - opcode != evmasm::Instruction::RETURNCONTRACT - ) - { - // difficulty was replaced by prevrandao after london - if (opcode == evmasm::Instruction::PREVRANDAO && name == "DIFFICULTY") - m_builtinFunctions.emplace_back(instruction, instructionBuiltin(opcode, langutil::EVMVersion::london())); - else - m_builtinFunctions.emplace_back(instruction, instructionBuiltin(opcode, langutil::EVMVersion::current())); - } - else - // these opcodes are replaced by explicit builtin functions - m_builtinFunctions.emplace_back(instruction | replaced, BuiltinFunctionForEVM{}); - } - - m_builtinFunctions.emplace_back(objectAccess, linkersymbolBuiltin()); - m_builtinFunctions.emplace_back(objectAccess, memoryguardBuiltin()); - - m_builtinFunctions.emplace_back(objectAccess | requiresNonEOF, datasizeBuiltin()); - m_builtinFunctions.emplace_back(objectAccess | requiresNonEOF, dataoffsetBuiltin()); - m_builtinFunctions.emplace_back(objectAccess | requiresNonEOF, datacopyBuiltin()); - m_builtinFunctions.emplace_back(objectAccess | requiresNonEOF, setimmutableBuiltin()); - m_builtinFunctions.emplace_back(objectAccess | requiresNonEOF, loadimmutableBuiltin()); - - m_builtinFunctions.emplace_back(objectAccess | requiresEOF, auxdataloadnBuiltin()); - m_builtinFunctions.emplace_back(objectAccess | requiresEOF, eofcreateBuiltin()); - m_builtinFunctions.emplace_back(objectAccess | requiresEOF, returncontractBuiltin()); - - yulAssert( - ranges::all_of(m_builtinFunctions, [](std::tuple const& _builtin) { - return std::get<1>(_builtin).name.substr(0, "verbatim_"s.size()) != "verbatim_"; - }), - "Builtin functions besides verbatim should not start with the verbatim_ prefix." - ); - } - - static BuiltinFunctionForEVM instructionBuiltin(evmasm::Instruction const& _instruction, langutil::EVMVersion const& _evmVersion) - { - evmasm::InstructionInfo const info = evmasm::instructionInfo(_instruction, _evmVersion); - BuiltinFunctionForEVM f; - f.name = toLower(info.name); - f.numParameters = static_cast(info.args); - f.numReturns = static_cast(info.ret); - f.sideEffects = EVMDialect::sideEffectsOfInstruction(_instruction); - f.controlFlowSideEffects = ControlFlowSideEffects::fromInstruction(_instruction); - f.isMSize = _instruction == evmasm::Instruction::MSIZE; - f.literalArguments.clear(); - f.instruction = _instruction; - f.generateCode = [_instruction]( - FunctionCall const&, - AbstractAssembly& _assembly, - BuiltinContext& - ) - { - _assembly.appendInstruction(_instruction); - }; - return f; - } - - static BuiltinFunctionForEVM linkersymbolBuiltin() - { - return createFunction( - "linkersymbol", - 1, - 1, - SideEffects{}, - ControlFlowSideEffects{}, - {LiteralKind::String}, - [](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) { - yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - _assembly.appendLinkerSymbol(formatLiteral(std::get(arg))); - } - ); - } - - static BuiltinFunctionForEVM memoryguardBuiltin() - { - return createFunction( - "memoryguard", - 1, - 1, - SideEffects{}, - ControlFlowSideEffects{}, - {LiteralKind::Number}, - [](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext&) { - yulAssert(_call.arguments.size() == 1, ""); - Literal const* literal = std::get_if(&_call.arguments.front()); - yulAssert(literal, ""); - _assembly.appendConstant(literal->value.value()); - } - ); - } - - static BuiltinFunctionForEVM datasizeBuiltin() - { - return createFunction( - "datasize", - 1, - 1, - SideEffects{}, - ControlFlowSideEffects{}, - {LiteralKind::String}, - [](FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& _context) { - yulAssert(_context.currentObject, "No object available."); - yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - YulName const dataName (formatLiteral(std::get(arg))); - if (_context.currentObject->name == dataName.str()) - _assembly.appendAssemblySize(); - else - { - std::vector subIdPath = - _context.subIDs.count(dataName.str()) == 0 ? - _context.currentObject->pathToSubObject(dataName.str()) : - std::vector{_context.subIDs.at(dataName.str())}; - yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); - _assembly.appendDataSize(subIdPath); - } - } - ); - } - - static BuiltinFunctionForEVM dataoffsetBuiltin() - { - return createFunction("dataoffset", 1, 1, SideEffects{}, ControlFlowSideEffects{}, {LiteralKind::String}, []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& _context - ) { - yulAssert(_context.currentObject, "No object available."); - yulAssert(_call.arguments.size() == 1, ""); - Expression const& arg = _call.arguments.front(); - YulName const dataName (formatLiteral(std::get(arg))); - if (_context.currentObject->name == dataName.str()) - _assembly.appendConstant(0); - else - { - std::vector subIdPath = - _context.subIDs.count(dataName.str()) == 0 ? - _context.currentObject->pathToSubObject(dataName.str()) : - std::vector{_context.subIDs.at(dataName.str())}; - yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); - _assembly.appendDataOffset(subIdPath); - } - }); - } - - static BuiltinFunctionForEVM datacopyBuiltin() - { - return createFunction( - "datacopy", - 3, - 0, - EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::CODECOPY), - ControlFlowSideEffects::fromInstruction(evmasm::Instruction::CODECOPY), - {}, - []( - FunctionCall const&, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - _assembly.appendInstruction(evmasm::Instruction::CODECOPY); - } - ); - } - - static BuiltinFunctionForEVM setimmutableBuiltin() - { - return createFunction( - "setimmutable", - 3, - 0, - SideEffects{ - false, // movable - false, // movableApartFromEffects - false, // canBeRemoved - false, // canBeRemovedIfNotMSize - true, // cannotLoop - SideEffects::None, // otherState - SideEffects::None, // storage - SideEffects::Write, // memory - SideEffects::None // transientStorage - }, - ControlFlowSideEffects{}, - {std::nullopt, LiteralKind::String, std::nullopt}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == 3, ""); - auto const identifier = (formatLiteral(std::get(_call.arguments[1]))); - _assembly.appendImmutableAssignment(identifier); - } - ); - } - - static BuiltinFunctionForEVM loadimmutableBuiltin() - { - return createFunction( - "loadimmutable", - 1, - 1, - SideEffects{}, - ControlFlowSideEffects{}, - {LiteralKind::String}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == 1, ""); - _assembly.appendImmutable(formatLiteral(std::get(_call.arguments.front()))); - } - ); - } - - static BuiltinFunctionForEVM auxdataloadnBuiltin() - { - return createFunction( - "auxdataloadn", - 1, - 1, - EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::DATALOADN), - ControlFlowSideEffects::fromInstruction(evmasm::Instruction::DATALOADN), - {LiteralKind::Number}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == 1); - Literal const* literal = std::get_if(&_call.arguments.front()); - yulAssert(literal, ""); - yulAssert(literal->value.value() <= std::numeric_limits::max()); - _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); - } - ); - } - - static BuiltinFunctionForEVM eofcreateBuiltin() - { - return createFunction( - "eofcreate", - 5, - 1, - EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE), - ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE), - {LiteralKind::String, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& context - ) { - yulAssert(_call.arguments.size() == 5); - Literal const* literal = std::get_if(&_call.arguments.front()); - auto const formattedLiteral = formatLiteral(*literal); - yulAssert(!util::contains(formattedLiteral, '.')); - auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); - yulAssert(containerID != nullptr); - yulAssert(*containerID <= std::numeric_limits::max()); - _assembly.appendEOFCreate(static_cast(*containerID)); - } - ); - } - - static BuiltinFunctionForEVM returncontractBuiltin() - { - return createFunction( - "returncontract", - 3, - 0, - EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::RETURNCONTRACT), - ControlFlowSideEffects::fromInstruction(evmasm::Instruction::RETURNCONTRACT), - {LiteralKind::String, std::nullopt, std::nullopt}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& context - ) { - yulAssert(_call.arguments.size() == 3); - Literal const* literal = std::get_if(&_call.arguments.front()); - yulAssert(literal); - auto const formattedLiteral = formatLiteral(*literal); - yulAssert(!util::contains(formattedLiteral, '.')); - auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); - yulAssert(containerID != nullptr); - yulAssert(*containerID <= std::numeric_limits::max()); - _assembly.appendReturnContract(static_cast(*containerID)); - } - ); - } - - std::vector> m_builtinFunctions; -}; - -/// Make sure to only add builtins in a way that is consistent over EVM versions. If the order depends on the -/// EVM version - which can easily happen using conditionals -, different dialects' builtin handles -/// become inherently incompatible. -std::vector createBuiltins(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess) +std::vector createDialectBuiltins( + std::vector> const& _allBuiltins, + langutil::EVMVersion const _evmVersion, + std::optional const _eofVersion, + bool const _objectAccess +) { std::vector builtins; - builtins.reserve(BuiltinFunctionCollection::builtins().size()); + builtins.reserve(_allBuiltins.size()); - for (auto const& [description, builtin]: BuiltinFunctionCollection::builtins()) + for (auto const& [scopes, builtin]: _allBuiltins) { bool builtinShouldBeAdded = true; - if (description.instruction()) + if (scopes.instruction()) { - if (description.replaced()) + if (scopes.replaced()) builtinShouldBeAdded = false; else { @@ -582,9 +210,9 @@ std::vector createBuiltins(langutil::EVMVersion _e } } - builtinShouldBeAdded &= !description.requiresObjectAccess() || _objectAccess; - builtinShouldBeAdded &= !description.requiresEOF() || _eofVersion.has_value(); - builtinShouldBeAdded &= !description.requiresNonEOF() || !_eofVersion.has_value(); + builtinShouldBeAdded &= !scopes.requiresObjectAccess() || _objectAccess; + builtinShouldBeAdded &= !scopes.requiresEOF() || _eofVersion.has_value(); + builtinShouldBeAdded &= !scopes.requiresNonEOF() || !_eofVersion.has_value(); if (builtinShouldBeAdded) builtins.emplace_back(&builtin); @@ -603,12 +231,11 @@ std::regex const& verbatimPattern() } - EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, std::optional _eofVersion, bool _objectAccess): m_objectAccess(_objectAccess), m_evmVersion(_evmVersion), m_eofVersion(_eofVersion), - m_functions(createBuiltins(_evmVersion, _eofVersion, _objectAccess)), + m_functions(createDialectBuiltins(allBuiltins().functions(), _evmVersion, _eofVersion, _objectAccess)), m_reserved(createReservedIdentifiers(_evmVersion, _eofVersion)) { for (auto const& [index, maybeBuiltin]: m_functions | ranges::views::enumerate) @@ -668,13 +295,12 @@ BuiltinFunctionForEVM const& EVMDialect::builtin(BuiltinHandle const& _handle) c return *maybeBuiltin; } - bool EVMDialect::reservedIdentifier(std::string_view _name) const { if (m_objectAccess) if (_name.substr(0, "verbatim"s.size()) == "verbatim") return true; - return m_reserved.count(_name) != 0; + return m_reserved.contains(_name); } EVMDialect const& EVMDialect::strictAssemblyForEVM(langutil::EVMVersion _evmVersion, std::optional _eofVersion) @@ -695,42 +321,14 @@ EVMDialect const& EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion _ return *dialects[{_evmVersion, _eofVersion}]; } -SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instruction) +std::set EVMDialect::builtinFunctionNames() const { return ranges::views::keys(m_builtinFunctionsByName) | ranges::to; } BuiltinFunctionForEVM EVMDialect::createVerbatimFunctionFromHandle(BuiltinHandle const& _handle) { - return std::apply(createVerbatimFunction, verbatimIndexToArgsAndRets(_handle.id)); -} - -BuiltinFunctionForEVM EVMDialect::createVerbatimFunction(size_t _arguments, size_t _returnVariables) -{ - BuiltinFunctionForEVM builtinFunction = createFunction( - "verbatim_" + std::to_string(_arguments) + "i_" + std::to_string(_returnVariables) + "o", - 1 + _arguments, - _returnVariables, - SideEffects::worst(), - ControlFlowSideEffects::worst(), // Worst control flow side effects because verbatim can do anything. - std::vector>{LiteralKind::String} + std::vector>(_arguments), - [=]( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == (1 + _arguments), ""); - Expression const& bytecode = _call.arguments.front(); - - _assembly.appendVerbatim( - asBytes(formatLiteral(std::get(bytecode))), - _arguments, - _returnVariables - ); - } - ); - builtinFunction.isMSize = true; - return builtinFunction; + return std::apply(EVMBuiltins::createVerbatimFunction, verbatimIndexToArgsAndRets(_handle.id)); } BuiltinHandle EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVariables) const @@ -745,7 +343,13 @@ BuiltinHandle EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVari auto& verbatimFunctionPtr = m_verbatimFunctions[verbatimIndex]; !verbatimFunctionPtr ) - verbatimFunctionPtr = std::make_unique(createVerbatimFunction(_arguments, _returnVariables)); + verbatimFunctionPtr = std::make_unique(EVMBuiltins::createVerbatimFunction(_arguments, _returnVariables)); return {verbatimIndex}; } + +EVMBuiltins const& EVMDialect::allBuiltins() +{ + static EVMBuiltins const builtins; + return builtins; +} diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 73136ef6e..96723e919 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -25,11 +25,15 @@ #include #include -#include +#include + #include -#include +#include +#include #include +#include +#include namespace solidity::yul { @@ -37,29 +41,6 @@ namespace solidity::yul struct FunctionCall; class Object; -/** - * Context used during code generation. - */ -struct BuiltinContext -{ - Object const* currentObject = nullptr; - /// Mapping from named objects to abstract assembly sub IDs. - std::map subIDs; - - std::map functionIDs; -}; - -struct BuiltinFunctionForEVM: public BuiltinFunction -{ - std::optional instruction; - /// Function to generate code for the given function call and append it to the abstract - /// assembly. Expects all non-literal arguments of the call to be on stack in reverse order - /// (i.e. right-most argument pushed first). - /// Expects the caller to set the source location. - std::function generateCode; -}; - - /** * Yul dialect for EVM as a backend. * The main difference is that the builtin functions take an AbstractAssembly for the @@ -108,19 +89,18 @@ class EVMDialect: public Dialect bool providesObjectAccess() const { return m_objectAccess; } - static SideEffects sideEffectsOfInstruction(evmasm::Instruction _instruction); - static size_t constexpr verbatimMaxInputSlots = 100; static size_t constexpr verbatimMaxOutputSlots = 100; protected: static bool constexpr isVerbatimHandle(BuiltinHandle const& _handle) { return _handle.id < verbatimIDOffset; } static BuiltinFunctionForEVM createVerbatimFunctionFromHandle(BuiltinHandle const& _handle); - static BuiltinFunctionForEVM createVerbatimFunction(size_t _arguments, size_t _returnVariables); BuiltinHandle verbatimFunction(size_t _arguments, size_t _returnVariables) const; static size_t constexpr verbatimIDOffset = verbatimMaxInputSlots * verbatimMaxOutputSlots; + static EVMBuiltins const& allBuiltins(); + bool const m_objectAccess; langutil::EVMVersion const m_evmVersion; std::optional m_eofVersion; diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 55e034399..90713b0e2 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -26,6 +26,7 @@ #include +#include #include using namespace solidity; @@ -208,44 +209,17 @@ NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom): EVMDialect(_copyFrom.evmVersion(), _copyFrom.eofVersion(), _copyFrom.providesObjectAccess()) { // save the modified functions here - note that this only has to be done once because we modify all of - // them in one go, later just reference pointers to this static vector - static std::vector const noOutputBuiltins = [] - { - std::vector modifiedBuiltins; - modifiedBuiltins.reserve(allBuiltins().functions().size()); - - for (auto const& [_, builtin]: allBuiltins().functions()) - { - auto noOutputFunction = builtin; - modifyBuiltinToNoOutput(noOutputFunction); - modifiedBuiltins.push_back(std::move(noOutputFunction)); - } + // them in one go, later reference pointers to this static vector + static std::vector noOutputBuiltins = defineNoOutputBuiltins(); - return modifiedBuiltins; - }(); - - m_functions = [&] + m_functions.reserve(m_functions.size()); + for (auto const& [index, builtinFunction]: m_functions | ranges::views::enumerate) { - std::vector result; - result.reserve(m_functions.size()); - for (auto const* builtinFunction: m_functions) - { - if (builtinFunction) - { - auto it = noOutputBuiltins.find(builtinFunction); - if (it == noOutputBuiltins.end()) - { - auto noOutputFunction = *builtinFunction; - modifyBuiltinToNoOutput(noOutputFunction); - it = noOutputBuiltins.emplace(builtinFunction, std::move(noOutputFunction)).first; - } - result.emplace_back(&it->second); - } - else - result.emplace_back(nullptr); - } - return result; - }(); + if (builtinFunction) + m_functions.emplace_back(&noOutputBuiltins[index]); + else + m_functions.emplace_back(nullptr); + } } BuiltinFunctionForEVM const& NoOutputEVMDialect::builtin(BuiltinHandle const& _handle) const @@ -262,3 +236,18 @@ BuiltinFunctionForEVM const& NoOutputEVMDialect::builtin(BuiltinHandle const& _h } return EVMDialect::builtin(_handle); } + +std::vector NoOutputEVMDialect::defineNoOutputBuiltins() +{ + std::vector modifiedBuiltins; + modifiedBuiltins.reserve(allBuiltins().functions().size()); + + for (auto const& [_, builtin]: allBuiltins().functions()) + { + auto noOutputFunction = builtin; + modifyBuiltinToNoOutput(noOutputFunction); + modifiedBuiltins.push_back(std::move(noOutputFunction)); + } + + return modifiedBuiltins; +} diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h index 502f90d85..0a9ade346 100644 --- a/libyul/backends/evm/NoOutputAssembly.h +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -114,6 +114,9 @@ class NoOutputEVMDialect: public EVMDialect explicit NoOutputEVMDialect(EVMDialect const& _copyFrom); BuiltinFunctionForEVM const& builtin(BuiltinHandle const& _handle) const override; + +private: + static std::vector defineNoOutputBuiltins(); }; From e465a316b96f2e4dec795b0129c1def3a41c3270 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 28 Apr 2025 14:23:42 +0200 Subject: [PATCH 0909/1340] Add allEOFVersions to EVMVersion --- liblangutil/EVMVersion.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index f771d9f1c..f5e7b3d34 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -23,6 +23,7 @@ #include +#include #include #include #include @@ -83,6 +84,14 @@ class EVMVersion }; } + static auto constexpr allEOFVersions() + { + return std::array{ + std::optional(), + std::make_optional(1) + }; + } + static std::optional fromString(std::string const& _version) { for (auto const& v: allVersions()) From e39aaeb1d951f49ece3c99e26b669d63e6150db5 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 28 Apr 2025 14:24:04 +0200 Subject: [PATCH 0910/1340] EVMVersion::allVersions is constexpr --- liblangutil/EVMVersion.h | 37 ++++++++++++++++++------------------ solc/CommandLineParser.cpp | 2 +- test/tools/fuzzer_common.cpp | 2 +- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index f5e7b3d34..b5489de0b 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -27,7 +27,6 @@ #include #include #include -#include namespace solidity::evmasm @@ -50,23 +49,23 @@ class EVMVersion static EVMVersion current() { return {currentVersion}; } - static EVMVersion homestead() { return {Version::Homestead}; } - static EVMVersion tangerineWhistle() { return {Version::TangerineWhistle}; } - static EVMVersion spuriousDragon() { return {Version::SpuriousDragon}; } - static EVMVersion byzantium() { return {Version::Byzantium}; } - static EVMVersion constantinople() { return {Version::Constantinople}; } - static EVMVersion petersburg() { return {Version::Petersburg}; } - static EVMVersion istanbul() { return {Version::Istanbul}; } - static EVMVersion berlin() { return {Version::Berlin}; } - static EVMVersion london() { return {Version::London}; } - static EVMVersion paris() { return {Version::Paris}; } - static EVMVersion shanghai() { return {Version::Shanghai}; } - static EVMVersion cancun() { return {Version::Cancun}; } - static EVMVersion prague() { return {Version::Prague}; } - static EVMVersion osaka() { return {Version::Osaka}; } - - static std::vector allVersions() { - return { + static EVMVersion constexpr homestead() { return {Version::Homestead}; } + static EVMVersion constexpr tangerineWhistle() { return {Version::TangerineWhistle}; } + static EVMVersion constexpr spuriousDragon() { return {Version::SpuriousDragon}; } + static EVMVersion constexpr byzantium() { return {Version::Byzantium}; } + static EVMVersion constexpr constantinople() { return {Version::Constantinople}; } + static EVMVersion constexpr petersburg() { return {Version::Petersburg}; } + static EVMVersion constexpr istanbul() { return {Version::Istanbul}; } + static EVMVersion constexpr berlin() { return {Version::Berlin}; } + static EVMVersion constexpr london() { return {Version::London}; } + static EVMVersion constexpr paris() { return {Version::Paris}; } + static EVMVersion constexpr shanghai() { return {Version::Shanghai}; } + static EVMVersion constexpr cancun() { return {Version::Cancun}; } + static EVMVersion constexpr prague() { return {Version::Prague}; } + static EVMVersion constexpr osaka() { return {Version::Osaka}; } + + static auto constexpr allVersions() { + return std::array{ homestead(), tangerineWhistle(), spuriousDragon(), @@ -172,7 +171,7 @@ class EVMVersion }; static auto constexpr currentVersion = Version::Prague; - EVMVersion(Version _version): m_version(_version) {} + constexpr EVMVersion(Version _version): m_version(_version) {} Version m_version = currentVersion; }; diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index a382c5217..50ce02bd1 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -596,7 +596,7 @@ General Information)").c_str(), auto const annotateEVMVersion = [](EVMVersion const& _version) { return _version.name() + (_version.isExperimental() ? " (experimental)" : ""); }; - std::vector allEVMVersions = EVMVersion::allVersions(); + static auto constexpr allEVMVersions = EVMVersion::allVersions(); std::string annotatedEVMVersions = util::joinHumanReadable( allEVMVersions | ranges::views::transform(annotateEVMVersion), ", ", diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index 6a70c1cc8..8cc30c199 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -39,7 +39,7 @@ using namespace solidity::frontend; using namespace solidity::langutil; using namespace solidity::util; -static std::vector s_evmVersions = EVMVersion::allVersions(); +static auto constexpr s_evmVersions = EVMVersion::allVersions(); void FuzzerUtil::testCompilerJsonInterface(std::string const& _input, bool _optimize, bool _quiet) { From 55e29b69e9c8b108e834b98bebd46e11e4153989 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 20 Mar 2025 11:31:46 +0100 Subject: [PATCH 0911/1340] EVMDialect: add test that enforces builtin handle compatibility Between current default dialect as well as latest dialect and all other dialects. --- libyul/backends/evm/EVMDialect.h | 8 ++ test/CMakeLists.txt | 1 + test/libyul/EVMDialectCompatibility.cpp | 167 ++++++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 test/libyul/EVMDialectCompatibility.cpp diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 96723e919..9f5760089 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -45,6 +45,10 @@ class Object; * Yul dialect for EVM as a backend. * The main difference is that the builtin functions take an AbstractAssembly for the * code generation. + * + * Builtins are defined so that their handles stay compatible over different dialect flavors - be it with/without + * object access, with/without EOF, different versions. It may be, of course, that these builtins are no longer defined. + * The ones that _are_ defined, though, remain under the same handle. */ class EVMDialect: public Dialect { @@ -81,6 +85,8 @@ class EVMDialect: public Dialect AuxiliaryBuiltinHandles const& auxiliaryBuiltinHandles() const { return m_auxiliaryBuiltinHandles; } static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _evmVersion, std::optional _eofVersion); + /// Builtins with and without object access are compatible, i.e., builtin handles without object access are not + /// invalidated and still point to the same function. static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _evmVersion, std::optional _eofVersion); langutil::EVMVersion evmVersion() const { return m_evmVersion; } @@ -92,6 +98,8 @@ class EVMDialect: public Dialect static size_t constexpr verbatimMaxInputSlots = 100; static size_t constexpr verbatimMaxOutputSlots = 100; + std::set builtinFunctionNames() const; + protected: static bool constexpr isVerbatimHandle(BuiltinHandle const& _handle) { return _handle.id < verbatimIDOffset; } static BuiltinFunctionForEVM createVerbatimFunctionFromHandle(BuiltinHandle const& _handle); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c66963c19..b0cd991f7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -149,6 +149,7 @@ set(libyul_sources libyul/ControlFlowSideEffectsTest.h libyul/EVMCodeTransformTest.cpp libyul/EVMCodeTransformTest.h + libyul/EVMDialectCompatibility.cpp libyul/FunctionSideEffects.cpp libyul/FunctionSideEffects.h libyul/Inliner.cpp diff --git a/test/libyul/EVMDialectCompatibility.cpp b/test/libyul/EVMDialectCompatibility.cpp new file mode 100644 index 000000000..6c8c5a60a --- /dev/null +++ b/test/libyul/EVMDialectCompatibility.cpp @@ -0,0 +1,167 @@ +/* + 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 + +#include + +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +namespace bdata = boost::unit_test::data; + +using namespace solidity; +using namespace solidity::yul; + +namespace +{ + +struct EVMDialectConfigurationToTest +{ + EVMDialect const& dialect() const + { + return objectAccess ? EVMDialect::strictAssemblyForEVMObjects(evmVersion, eofVersion) : EVMDialect::strictAssemblyForEVM(evmVersion, eofVersion); + } + + friend std::ostream& operator<<(std::ostream& _out, EVMDialectConfigurationToTest const& _config) + { + _out << fmt::format( + "EVMConfigurationToTest[{}, eof={}, objectAccess={}]", + _config.evmVersion.name(), + _config.eofVersion.has_value() ? std::to_string(*_config.eofVersion) : "null", + _config.objectAccess + ); + return _out; + } + + langutil::EVMVersion evmVersion; + std::optional eofVersion; + bool objectAccess; +}; + +template +std::vector generateConfigs(EVMVersionCollection const& _evmVersions, std::vector const& _objectAccess = {false, true}) +{ + std::vector configs; + for (bool const objectAccess: _objectAccess) + for (auto const& eofVersion: langutil::EVMVersion::allEOFVersions()) + for (auto const& evmVersion: _evmVersions) + if (!eofVersion || evmVersion.supportsEOF()) + configs.push_back(EVMDialectConfigurationToTest{evmVersion, eofVersion, objectAccess}); + + return configs; +} +} + +BOOST_AUTO_TEST_SUITE(EVMDialectCompatibility) + +/// Test for both current and latest (source) EVM dialect that for all other (target) dialects and all builtins in the +/// source dialect, if the builtin exists for both source and target, they have the same handle. +/// Note: The comparison is packed into a single BOOST_REQUIRE to avoid massive amounts of output on cout. +BOOST_DATA_TEST_CASE( + builtin_function_handle_compatibility, + bdata::monomorphic::grid( + bdata::make(generateConfigs(std::array{langutil::EVMVersion::current(), langutil::EVMVersion::allVersions().back()})), + bdata::make(generateConfigs(langutil::EVMVersion::allVersions())) + ), + sourceDialectConfiguration, + evmDialectConfigurationToTest +) +{ + auto const& sourceDialect = sourceDialectConfiguration.dialect(); + auto const& dialectToTestAgainst = evmDialectConfigurationToTest.dialect(); + + std::set const builtinNames = sourceDialect.builtinFunctionNames(); + std::vector sourceHandles; + sourceHandles.reserve(builtinNames.size()); + std::vector> testHandles; + testHandles.reserve(builtinNames.size()); + + for (auto const& builtinFunctionName: builtinNames) + { + std::optional sourceHandle = sourceDialect.findBuiltin(builtinFunctionName); + soltestAssert(sourceHandle.has_value()); + sourceHandles.push_back(*sourceHandle); + testHandles.push_back(dialectToTestAgainst.findBuiltin(builtinFunctionName)); + } + + BOOST_REQUIRE([&]() -> boost::test_tools::predicate_result + { + boost::test_tools::predicate_result result{true}; + for (auto const& [name, sourceBuiltin, testBuiltin]: ranges::views::zip(builtinNames, sourceHandles, testHandles)) + if (testBuiltin && sourceBuiltin != *testBuiltin) + { + result = false; + result.message() << fmt::format("Builtin \"{}\" had a mismatch of builtin handles: {} =/= {}.", name, sourceBuiltin.id, testBuiltin->id); + } + return result; + }()); +} + +/// Test that for all inline-dialects the corresponding object dialect contains all inline-dialect builtins and they +/// have the same handle. +BOOST_DATA_TEST_CASE( + builtin_inline_to_object_compatibility, + bdata::make(generateConfigs(langutil::EVMVersion::allVersions(), {false})), + configToTest +) +{ + auto const& dialect = EVMDialect::strictAssemblyForEVM(configToTest.evmVersion, configToTest.eofVersion); + auto const& dialectForObjects = EVMDialect::strictAssemblyForEVMObjects(configToTest.evmVersion, configToTest.eofVersion); + + std::set const inlineBuiltinNames = dialect.builtinFunctionNames(); + + std::vector inlineHandles; + inlineHandles.reserve(inlineBuiltinNames.size()); + std::vector> objectHandles; + objectHandles.reserve(inlineBuiltinNames.size()); + + for (auto const& builtinFunctionName: inlineBuiltinNames) + { + std::optional handle = dialect.findBuiltin(builtinFunctionName); + soltestAssert(handle.has_value()); + inlineHandles.push_back(*handle); + objectHandles.push_back(dialectForObjects.findBuiltin(builtinFunctionName)); + } + + BOOST_REQUIRE([&]() -> boost::test_tools::predicate_result + { + boost::test_tools::predicate_result result{true}; + for (auto const& [name, inlineHandle, objectHandle]: ranges::views::zip(inlineBuiltinNames, inlineHandles, objectHandles)) + if (!objectHandle || inlineHandle != *objectHandle) + { + result = false; + result.message() + << fmt::format("Builtin \"{}\" had a mismatch of builtin handles: {} != ", name, inlineHandle.id) + << (objectHandle.has_value() ? std::to_string(objectHandle->id) : "null"); + } + return result; + }()); +} + +BOOST_AUTO_TEST_SUITE_END() From 35282a89786c4a5ba8a43e20853a752d1c678f1b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 21 Jul 2025 10:47:02 +0200 Subject: [PATCH 0912/1340] CI: Update cimg/node to 20.19 for gp2 and pool together Requirement of the micro-eth-signer dependency --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8b69287b8..0f4d2b6eb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -823,7 +823,7 @@ defaults: # NOTE: test suite disabled due to dependence on a specific version of Hardhat # which does not support shanghai EVM. compile_only: 1 - image: cimg/node:18.16 + image: cimg/node:20.19 - job_native_test_ext_uniswap: &job_native_test_ext_uniswap <<: *requires_b_ubu_static @@ -876,7 +876,7 @@ defaults: binary_type: native # NOTE: test suite disabled due to constant failures. compile_only: 1 - image: cimg/node:18.16 + image: cimg/node:20.19 - job_b_ubu_asan_clang: &job_b_ubu_asan_clang <<: *on_all_tags_and_branches From fde1aaf38af395d3a4d6c9c3a54189f30b1182b5 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 21 Jul 2025 09:27:06 +0200 Subject: [PATCH 0913/1340] Yul: NoOutputAssembly assigns functions instead of appending There was an error in that the functions were already part of the dialect (via the parent constructor) and the no output versions were appended instead of overwritten. This causes the vector to be re-allocated and therefore could invalidate pointers to its elements. --- libyul/backends/evm/NoOutputAssembly.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 90713b0e2..1acc0d0ae 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -212,13 +212,13 @@ NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom): // them in one go, later reference pointers to this static vector static std::vector noOutputBuiltins = defineNoOutputBuiltins(); - m_functions.reserve(m_functions.size()); + yulAssert(m_functions.size() == noOutputBuiltins.size(), "Function count mismatch."); for (auto const& [index, builtinFunction]: m_functions | ranges::views::enumerate) { if (builtinFunction) - m_functions.emplace_back(&noOutputBuiltins[index]); + m_functions[index] = &noOutputBuiltins[index]; else - m_functions.emplace_back(nullptr); + m_functions[index] = nullptr; } } From 2593de82e6c46324455d26f3c146281cfa5216c7 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Tue, 22 Jul 2025 12:04:14 +0200 Subject: [PATCH 0914/1340] Fix solidity public calls url --- docs/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 3cdadef95..2d5faa550 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -32,7 +32,7 @@ the team and contributors are working on, you can join our public team call: - Wednesdays at 3PM CET/CEST. -The call takes place on `Jitsi `_. +The call takes place on `Jitsi `_. How to Report Issues ==================== From bf6548ba70f81e08ea030ccafa1dd7bfc8d01d99 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 18 Mar 2025 10:24:04 +0100 Subject: [PATCH 0915/1340] Add tests with non-zero PUSH #[$] asm instructions --- .../args | 1 + .../input.yul | 19 ++++ .../output | 101 ++++++++++++++++++ .../nontrivial_subassembly_ids.asm | 61 +++++++++++ 4 files changed, 182 insertions(+) create mode 100644 test/cmdlineTests/asm_json_subassembly_id_representation/args create mode 100644 test/cmdlineTests/asm_json_subassembly_id_representation/input.yul create mode 100644 test/cmdlineTests/asm_json_subassembly_id_representation/output create mode 100644 test/libevmasm/evmAssemblyTests/isoltestTesting/nontrivial_subassembly_ids.asm diff --git a/test/cmdlineTests/asm_json_subassembly_id_representation/args b/test/cmdlineTests/asm_json_subassembly_id_representation/args new file mode 100644 index 000000000..52d48e24a --- /dev/null +++ b/test/cmdlineTests/asm_json_subassembly_id_representation/args @@ -0,0 +1 @@ +--asm-json --pretty-json --strict-assembly --json-indent 4 \ No newline at end of file diff --git a/test/cmdlineTests/asm_json_subassembly_id_representation/input.yul b/test/cmdlineTests/asm_json_subassembly_id_representation/input.yul new file mode 100644 index 000000000..b6db74e7e --- /dev/null +++ b/test/cmdlineTests/asm_json_subassembly_id_representation/input.yul @@ -0,0 +1,19 @@ +object "root" { + code { + // this produces non-zero PUSH #[$] assembly item values + mstore(42, datasize("sub1.sub1_2")) + mstore(42, datasize("sub2.sub2_2")) + } + object "sub1" { + code {} + object "sub1_2" { + code {} + } + } + object "sub2" { + code {} + object "sub2_2" { + code {} + } + } +} diff --git a/test/cmdlineTests/asm_json_subassembly_id_representation/output b/test/cmdlineTests/asm_json_subassembly_id_representation/output new file mode 100644 index 000000000..709f9158b --- /dev/null +++ b/test/cmdlineTests/asm_json_subassembly_id_representation/output @@ -0,0 +1,101 @@ + +======= input.yul (EVM) ======= + +EVM assembly: +{ + ".code": [ + { + "begin": 60, + "end": 83, + "name": "PUSH #[$]", + "source": -1, + "value": "000000000000000000000000000000000000000000000000ffffffffffffffff" + }, + { + "begin": 56, + "end": 58, + "name": "PUSH", + "source": -1, + "value": "2A" + }, + { + "begin": 49, + "end": 84, + "name": "MSTORE", + "source": -1 + }, + { + "begin": 108, + "end": 131, + "name": "PUSH #[$]", + "source": -1, + "value": "000000000000000000000000000000000000000000000000fffffffffffffffe" + }, + { + "begin": 104, + "end": 106, + "name": "PUSH", + "source": -1, + "value": "2A" + }, + { + "begin": 97, + "end": 132, + "name": "MSTORE", + "source": -1 + }, + { + "begin": 25, + "end": 148, + "name": "STOP", + "source": -1 + } + ], + ".data": { + "0": { + ".code": [ + { + "begin": 182, + "end": 189, + "name": "STOP", + "source": -1 + } + ], + ".data": { + "0": { + ".code": [ + { + "begin": 233, + "end": 240, + "name": "STOP", + "source": -1 + } + ] + } + } + }, + "1": { + ".code": [ + { + "begin": 290, + "end": 297, + "name": "STOP", + "source": -1 + } + ], + ".data": { + "0": { + ".code": [ + { + "begin": 341, + "end": 348, + "name": "STOP", + "source": -1 + } + ] + } + } + } + }, + "sourceList": [] +} diff --git a/test/libevmasm/evmAssemblyTests/isoltestTesting/nontrivial_subassembly_ids.asm b/test/libevmasm/evmAssemblyTests/isoltestTesting/nontrivial_subassembly_ids.asm new file mode 100644 index 000000000..bcf9b03a7 --- /dev/null +++ b/test/libevmasm/evmAssemblyTests/isoltestTesting/nontrivial_subassembly_ids.asm @@ -0,0 +1,61 @@ +// sub_0 and children +PUSH #[$] 0x0000 +// negative indices for nested subobjects in DFS order +PUSH #[$] 0x000000000000000000000000000000000000000000000000ffffffffffffffff +PUSH #[$] 0x000000000000000000000000000000000000000000000000fffffffffffffffe +PUSH #[$] 0x000000000000000000000000000000000000000000000000fffffffffffffffd +PUSH #[$] 0x000000000000000000000000000000000000000000000000fffffffffffffffc +// sub_1 and children +PUSH #[$] 0x0001 +PUSH #[$] 0x000000000000000000000000000000000000000000000000fffffffffffffffb + +.sub + // referencing sub_0.sub_0 from inside sub_0 + PUSH #[$] 0x0000 + // referencing sub_0.sub_0.sub_0 from inside sub_0 + PUSH #[$] 0x000000000000000000000000000000000000000000000000ffffffffffffffff + .sub + .sub + .sub + .sub +.sub + .sub +// ---- +// Assembly: +// dataSize(sub_0) +// dataSize(sub_0.sub_0) +// dataSize(sub_0.sub_0.sub_0) +// dataSize(sub_0.sub_1) +// dataSize(sub_0.sub_2) +// dataSize(sub_1) +// dataSize(sub_1.sub_0) +// stop +// +// sub_0: assembly { +// dataSize(sub_0) +// dataSize(sub_0.sub_0) +// stop +// +// sub_0: assembly { +// stop +// +// sub_0: assembly { +// } +// } +// +// sub_1: assembly { +// } +// +// sub_2: assembly { +// } +// } +// +// sub_1: assembly { +// stop +// +// sub_0: assembly { +// } +// } +// Bytecode: 6005600160006000600060016000fe +// Opcodes: PUSH1 0x5 PUSH1 0x1 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 INVALID +// SourceMappings: :::-:0;;;;;; From 57f39fa81d2075cc46d00cd60bd7a528a56a031f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:58:03 +0100 Subject: [PATCH 0916/1340] Make subassembly IDs based on fixed-size 64 bit uint --- Changelog.md | 1 + libevmasm/Assembly.cpp | 68 +++++++++++----------- libevmasm/Assembly.h | 26 +++++---- libevmasm/AssemblyItem.cpp | 37 ++++++------ libevmasm/AssemblyItem.h | 7 ++- libevmasm/BlockDeduplicator.cpp | 4 +- libevmasm/BlockDeduplicator.h | 9 +-- libevmasm/CMakeLists.txt | 1 + libevmasm/EVMAssemblyStack.cpp | 2 +- libevmasm/Inliner.cpp | 2 +- libevmasm/JumpdestRemover.cpp | 6 +- libevmasm/JumpdestRemover.h | 4 +- libevmasm/SubAssemblyID.h | 62 ++++++++++++++++++++ libsolidity/codegen/Compiler.h | 2 +- libsolidity/codegen/CompilerContext.h | 10 ++-- libsolidity/codegen/ContractCompiler.cpp | 10 ++-- libsolidity/codegen/ContractCompiler.h | 6 +- libyul/CompilabilityChecker.cpp | 4 +- libyul/Object.cpp | 8 +-- libyul/Object.h | 8 ++- libyul/ObjectOptimizer.cpp | 2 +- libyul/YulStack.cpp | 8 +-- libyul/backends/evm/AbstractAssembly.h | 4 +- libyul/backends/evm/EVMBuiltins.cpp | 16 ++--- libyul/backends/evm/EthAssemblyAdapter.cpp | 4 +- libyul/backends/evm/EthAssemblyAdapter.h | 2 +- libyul/backends/evm/NoOutputAssembly.cpp | 2 +- test/libevmasm/Assembler.cpp | 14 ++--- test/libevmasm/Optimiser.cpp | 2 +- 29 files changed, 202 insertions(+), 129 deletions(-) create mode 100644 libevmasm/SubAssemblyID.h diff --git a/Changelog.md b/Changelog.md index 18e0deeaf..8220e6d74 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Compiler Features: * ethdebug: Experimental support for instructions and source locations under EOF. Bugfixes: +* Assembler: Fix not using a fixed-width type for IDs being assigned to subassemblies nested more than one level away, resulting in inconsistent `--asm-json` output between target architectures. ### 0.8.30 (2025-05-07) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 019683c9d..3fe31771f 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -715,17 +716,17 @@ std::pair, std::vector> Assembly::fromJSO return std::make_pair(result, _level == 0 ? parsedSourceList : std::vector{}); } -void Assembly::encodeAllPossibleSubPathsInAssemblyTree(std::vector _pathFromRoot, std::vector _assembliesOnPath) +void Assembly::encodeAllPossibleSubPathsInAssemblyTree(std::vector _pathFromRoot, std::vector _assembliesOnPath) { _assembliesOnPath.push_back(this); - for (_pathFromRoot.push_back(0); _pathFromRoot.back() < m_subs.size(); ++_pathFromRoot.back()) + for (_pathFromRoot.push_back(SubAssemblyID{0}); _pathFromRoot.back().value < m_subs.size(); ++_pathFromRoot.back().value) { for (size_t distanceFromRoot = 0; distanceFromRoot < _assembliesOnPath.size(); ++distanceFromRoot) _assembliesOnPath[distanceFromRoot]->encodeSubPath( _pathFromRoot | ranges::views::drop_exactly(distanceFromRoot) | ranges::to ); - m_subs[_pathFromRoot.back()]->encodeAllPossibleSubPathsInAssemblyTree(_pathFromRoot, _assembliesOnPath); + m_subs[_pathFromRoot.back().asIndex()]->encodeAllPossibleSubPathsInAssemblyTree(_pathFromRoot, _assembliesOnPath); } } @@ -846,20 +847,20 @@ std::map const& Assembly::optimiseInternal( // Run optimisation for sub-assemblies. // TODO: verify and double-check this for EOF. - for (size_t subId = 0; subId < m_subs.size(); ++subId) + for (SubAssemblyID subID{0}; subID.value < m_subs.size(); ++subID.value) { OptimiserSettings settings = _settings; - Assembly& sub = *m_subs[subId]; + Assembly& sub = *m_subs[subID.asIndex()]; std::set referencedTags; for (auto& codeSection: m_codeSections) - referencedTags += JumpdestRemover::referencedTags(codeSection.items, subId); + referencedTags += JumpdestRemover::referencedTags(codeSection.items, subID); std::map const& subTagReplacements = sub.optimiseInternal( settings, referencedTags ); // Apply the replacements (can be empty). for (auto& codeSection: m_codeSections) - BlockDeduplicator::applyTagReplacement(codeSection.items, subTagReplacements, subId); + BlockDeduplicator::applyTagReplacement(codeSection.items, subTagReplacements, subID); } std::map tagReplacements; @@ -1235,7 +1236,7 @@ LinkerObject const& Assembly::assemble() const [[nodiscard]] bytes Assembly::assembleTag(AssemblyItem const& _item, size_t _pos, bool _addJumpDest) const { solRequire(_item.data() != 0, AssemblyException, "Invalid tag position."); - solRequire(_item.splitForeignPushTag().first == std::numeric_limits::max(), AssemblyException, "Foreign tag."); + solRequire(_item.splitForeignPushTag().first.empty(), AssemblyException, "Foreign tag."); solRequire(_pos < 0xffffffffL, AssemblyException, "Tag too large."); size_t tagId = static_cast(_item.data()); solRequire(m_tagPositionsInBytecode[tagId] == std::numeric_limits::max(), AssemblyException, "Duplicate tag position."); @@ -1306,10 +1307,10 @@ LinkerObject const& Assembly::assembleLegacy() const if (item.type() == PushTag) { auto [subId, tagId] = item.splitForeignPushTag(); - if (subId == std::numeric_limits::max()) + if (subId.empty()) continue; - assertThrow(subId < m_subs.size(), AssemblyException, "Invalid sub id"); - auto subTagPosition = m_subs[subId]->m_tagPositionsInBytecode.at(tagId); + solAssert(subId.value < m_subs.size(), "Invalid sub id"); + auto subTagPosition = m_subs[subId.asIndex()]->m_tagPositionsInBytecode.at(tagId); assertThrow(subTagPosition != std::numeric_limits::max(), AssemblyException, "Reference to tag without position."); bytesPerTag = std::max(bytesPerTag, numberEncodingSize(subTagPosition)); } @@ -1358,15 +1359,15 @@ LinkerObject const& Assembly::assembleLegacy() const ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); break; case PushSub: - assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); + solAssert(item.data() <= std::numeric_limits::max()); ret.bytecode.push_back(dataRefPush); - subRefs.insert(std::make_pair(static_cast(item.data()), ret.bytecode.size())); + subRefs.emplace(SubAssemblyID{item.data()}, ret.bytecode.size()); ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); break; case PushSubSize: { - assertThrow(item.data() <= std::numeric_limits::max(), AssemblyException, ""); - auto s = subAssemblyById(static_cast(item.data()))->assemble().bytecode.size(); + solAssert(item.data() <= std::numeric_limits::max()); + auto s = subAssemblyById(SubAssemblyID{item.data()})->assemble().bytecode.size(); item.setPushedValue(u256(s)); unsigned b = std::max(1, numberEncodingSize(s)); ret.bytecode.push_back(static_cast(pushInstruction(b))); @@ -1481,14 +1482,12 @@ LinkerObject const& Assembly::assembleLegacy() const } for (auto const& i: tagRefs) { - size_t subId; - size_t tagId; - std::tie(subId, tagId) = i.second; - assertThrow(subId == std::numeric_limits::max() || subId < m_subs.size(), AssemblyException, "Invalid sub id"); + auto [subId, tagId] = i.second; + solAssert(subId.empty() || subId.value < m_subs.size(), "Invalid sub id"); std::vector const& tagPositions = - subId == std::numeric_limits::max() ? + subId.empty() ? m_tagPositionsInBytecode : - m_subs[subId]->m_tagPositionsInBytecode; + m_subs[subId.asIndex()]->m_tagPositionsInBytecode; assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag."); size_t pos = tagPositions[tagId]; assertThrow(pos != std::numeric_limits::max(), AssemblyException, "Reference to tag without position."); @@ -1813,14 +1812,13 @@ LinkerObject const& Assembly::assembleEOF() const return ret; } -std::vector Assembly::decodeSubPath(size_t _subObjectId) const +std::vector Assembly::decodeSubPath(SubAssemblyID _subObjectId) const { - if (_subObjectId < m_subs.size()) + if (_subObjectId.value < m_subs.size()) return {_subObjectId}; - auto subIdPathIt = find_if( - m_subPaths.begin(), - m_subPaths.end(), + auto subIdPathIt = ranges::find_if( + m_subPaths, [_subObjectId](auto const& subId) { return subId.second == _subObjectId; } ); @@ -1828,32 +1826,32 @@ std::vector Assembly::decodeSubPath(size_t _subObjectId) const return subIdPathIt->first; } -size_t Assembly::encodeSubPath(std::vector const& _subPath) +SubAssemblyID Assembly::encodeSubPath(std::vector const& _subPath) { assertThrow(!_subPath.empty(), AssemblyException, ""); if (_subPath.size() == 1) { - assertThrow(_subPath[0] < m_subs.size(), AssemblyException, ""); + solAssert(_subPath[0].value < m_subs.size()); return _subPath[0]; } - if (m_subPaths.find(_subPath) == m_subPaths.end()) + if (!m_subPaths.contains(_subPath)) { - size_t objectId = std::numeric_limits::max() - m_subPaths.size(); - assertThrow(objectId >= m_subs.size(), AssemblyException, ""); + SubAssemblyID const objectId{std::numeric_limits::max() - m_subPaths.size()}; + solAssert(objectId.value >= m_subs.size()); m_subPaths[_subPath] = objectId; } return m_subPaths[_subPath]; } -Assembly const* Assembly::subAssemblyById(size_t _subId) const +Assembly const* Assembly::subAssemblyById(SubAssemblyID const _subId) const { - std::vector subIds = decodeSubPath(_subId); + std::vector subIDs = decodeSubPath(_subId); Assembly const* currentAssembly = this; - for (size_t currentSubId: subIds) + for (auto const& subID: subIDs) { - currentAssembly = currentAssembly->m_subs.at(currentSubId).get(); + currentAssembly = currentAssembly->m_subs.at(subID.asIndex()).get(); assertThrow(currentAssembly, AssemblyException, ""); } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 30b06dd36..f931c438e 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -47,9 +48,9 @@ using AssemblyPointer = std::shared_ptr; class Assembly { - using TagRefs = std::map>; + using TagRefs = std::map>; using DataRefs = std::multimap; - using SubAssemblyRefs = std::multimap; + using SubAssemblyRefs = std::multimap; using ProgramSizeRefs = std::vector; using LinkRef = std::pair; @@ -81,8 +82,8 @@ class Assembly AssemblyItem newData(bytes const& _data) { util::h256 h(util::keccak256(util::asString(_data))); m_data[h] = _data; return AssemblyItem(PushData, h); } bytes const& data(util::h256 const& _i) const { return m_data.at(_i); } AssemblyItem newSub(AssemblyPointer const& _sub) { m_subs.push_back(_sub); return AssemblyItem(PushSub, m_subs.size() - 1); } - Assembly const& sub(size_t _sub) const { return *m_subs.at(_sub); } - Assembly& sub(size_t _sub) { return *m_subs.at(_sub); } + Assembly const& sub(SubAssemblyID const _sub) const { return *m_subs.at(_sub.asIndex()); } + Assembly& sub(SubAssemblyID const _sub) { return *m_subs.at(_sub.asIndex()); } size_t numSubs() const { return m_subs.size(); } AssemblyItem newPushSubSize(u256 const& _subId) { return AssemblyItem(PushSubSize, _subId); } AssemblyItem newPushLibraryAddress(std::string const& _identifier); @@ -142,9 +143,9 @@ class Assembly /// Adds a subroutine to the code (in the data section) and pushes its size (via a tag) /// on the stack. @returns the pushsub assembly item. AssemblyItem appendSubroutine(AssemblyPointer const& _assembly) { auto sub = newSub(_assembly); append(newPushSubSize(size_t(sub.data()))); return sub; } - void pushSubroutineSize(size_t _subRoutine) { append(newPushSubSize(_subRoutine)); } + void pushSubroutineSize(SubAssemblyID _subRoutine) { append(newPushSubSize(_subRoutine.value)); } /// Pushes the offset of the subroutine. - void pushSubroutineOffset(size_t _subRoutine) { append(AssemblyItem(PushSub, _subRoutine)); } + void pushSubroutineOffset(SubAssemblyID _subRoutine) { append(AssemblyItem(PushSub, _subRoutine.value)); } /// Appends @a _data literally to the very end of the bytecode. void appendToAuxiliaryData(bytes const& _data) { m_auxiliaryData += _data; } @@ -216,8 +217,8 @@ class Assembly /// Mark this assembly as invalid. Calling ``assemble`` on it will throw. void markAsInvalid() { m_invalid = true; } - std::vector decodeSubPath(size_t _subObjectId) const; - size_t encodeSubPath(std::vector const& _subPath); + std::vector decodeSubPath(SubAssemblyID _subObjectId) const; + SubAssemblyID encodeSubPath(std::vector const& _subPath); bool isCreation() const { return m_creation; } @@ -265,9 +266,9 @@ class Assembly private: bool m_invalid = false; - Assembly const* subAssemblyById(size_t _subId) const; + Assembly const* subAssemblyById(SubAssemblyID _subId) const; - void encodeAllPossibleSubPathsInAssemblyTree(std::vector _pathFromRoot = {}, std::vector _assembliesOnPath = {}); + void encodeAllPossibleSubPathsInAssemblyTree(std::vector _pathFromRoot = {}, std::vector _assembliesOnPath = {}); std::shared_ptr sharedSourceName(std::string const& _name) const; @@ -315,7 +316,10 @@ class Assembly /// Map from a vector representing a path to a particular sub assembly to sub assembly id. /// This map is used only for sub-assemblies which are not direct sub-assemblies (where path is having more than one value). - std::map, size_t> m_subPaths; + /// Nested/indirect SubAssemblyIDs are assigned negative unsigned 64 bit integers, i.e., the `i`th indirect + /// index corresponds to `std::numeric_limits::max() - i` in contrast to direct indices which occupy + /// the non-negative half of the index space. + std::map, SubAssemblyID> m_subPaths; /// Contains the tag replacements relevant for super-assemblies. /// If set, it means the optimizer has run and we will not run it again. diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 8a917986f..80df5ce74 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -50,7 +50,7 @@ std::string toStringInHex(u256 _value) } -AssemblyItem AssemblyItem::toSubAssemblyTag(size_t _subId) const +AssemblyItem AssemblyItem::toSubAssemblyTag(SubAssemblyID _subId) const { assertThrow(data() < (u256(1) << 64), util::Exception, "Tag already has subassembly set."); assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); @@ -61,20 +61,21 @@ AssemblyItem AssemblyItem::toSubAssemblyTag(size_t _subId) const return r; } -std::pair AssemblyItem::splitForeignPushTag() const +std::pair AssemblyItem::splitForeignPushTag() const { solAssert(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump); u256 combined = u256(data()); - size_t subId = static_cast((combined >> 64) - 1); + // the combined u256 is 'dirty', so we can't use the conversion constructor of SubAssemblyID here + SubAssemblyID const subID{static_cast((combined >> 64) - 1)}; size_t tag = static_cast(combined & 0xffffffffffffffffULL); - return std::make_pair(subId, tag); + return std::make_pair(subID, tag); } size_t AssemblyItem::relativeJumpTagID() const { solAssert(m_type == RelativeJump || m_type == ConditionalRelativeJump); auto const [subId, tagId] = splitForeignPushTag(); - solAssert(subId == std::numeric_limits::max(), "Relative jump to sub"); + solAssert(subId.empty(), "Relative jump to sub"); return tagId; } @@ -130,13 +131,13 @@ std::pair AssemblyItem::nameAndData(langutil::EVMVersi util::unreachable(); } -void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag) +void AssemblyItem::setPushTagSubIdAndTag(SubAssemblyID _subId, size_t _tag) { solAssert(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump); - solAssert(!(m_type == RelativeJump || m_type == ConditionalRelativeJump) || _subId == std::numeric_limits::max()); + solAssert(!(m_type == RelativeJump || m_type == ConditionalRelativeJump) || _subId.empty()); u256 data = _tag; - if (_subId != std::numeric_limits::max()) - data |= (u256(_subId) + 1) << 64; + if (!_subId.empty()) + data |= (u256(_subId.value) + 1) << 64; setData(data); } @@ -352,13 +353,11 @@ std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const break; case PushTag: { - size_t sub{0}; - size_t tag{0}; - std::tie(sub, tag) = splitForeignPushTag(); - if (sub == std::numeric_limits::max()) + auto [sub, tag] = splitForeignPushTag(); + if (sub.empty()) text = std::string("tag_") + std::to_string(tag); else - text = std::string("tag_") + std::to_string(sub) + "_" + std::to_string(tag); + text = std::string("tag_") + std::to_string(sub.value) + "_" + std::to_string(tag); break; } case Tag: @@ -372,8 +371,8 @@ std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const case PushSubSize: { std::vector subPathComponents; - for (size_t subPathComponentId: _assembly.decodeSubPath(static_cast(data()))) - subPathComponents.emplace_back("sub_" + std::to_string(subPathComponentId)); + for (SubAssemblyID subPathComponentId: _assembly.decodeSubPath(SubAssemblyID{data()})) + subPathComponents.emplace_back("sub_" + std::to_string(subPathComponentId.value)); text = (type() == PushSub ? "dataOffset"s : "dataSize"s) + "(" + @@ -469,11 +468,11 @@ std::ostream& solidity::evmasm::operator<<(std::ostream& _out, AssemblyItem cons break; case PushTag: { - size_t subId = _item.splitForeignPushTag().first; - if (subId == std::numeric_limits::max()) + SubAssemblyID subId = _item.splitForeignPushTag().first; + if (subId.empty()) _out << " PushTag " << _item.splitForeignPushTag().second; else - _out << " PushTag " << subId << ":" << _item.splitForeignPushTag().second; + _out << " PushTag " << subId.value << ":" << _item.splitForeignPushTag().second; break; } case Tag: diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 8386bf2dd..dcb4bf3a7 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -171,14 +172,14 @@ class AssemblyItem AssemblyItem pushTag() const { solAssert(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump); return AssemblyItem(PushTag, data()); } /// Converts the tag to a subassembly tag. This has to be called in order to move a tag across assemblies. /// @param _subId the identifier of the subassembly the tag is taken from. - AssemblyItem toSubAssemblyTag(size_t _subId) const; + AssemblyItem toSubAssemblyTag(SubAssemblyID _subId) const; /// @returns splits the data of the push tag into sub assembly id and actual tag id. /// The sub assembly id of non-foreign push tags is -1. - std::pair splitForeignPushTag() const; + std::pair splitForeignPushTag() const; /// @returns relative jump target tag ID. Asserts that it is not foreign tag. size_t relativeJumpTagID() const; /// Sets sub-assembly part and tag for a push tag. - void setPushTagSubIdAndTag(size_t _subId, size_t _tag); + void setPushTagSubIdAndTag(SubAssemblyID _subId, size_t _tag); AssemblyItemType type() const { return m_type; } u256 const& data() const { solAssert(m_type != Operation && m_data != nullptr); return *m_data; } diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp index 3ba8cfcd3..5c9c5a840 100644 --- a/libevmasm/BlockDeduplicator.cpp +++ b/libevmasm/BlockDeduplicator.cpp @@ -101,14 +101,14 @@ bool BlockDeduplicator::deduplicate() bool BlockDeduplicator::applyTagReplacement( AssemblyItems& _items, std::map const& _replacements, - size_t _subId + SubAssemblyID _subId ) { bool changed = false; for (AssemblyItem& item: _items) if (item.type() == PushTag || item.type() == RelativeJump || item.type() == ConditionalRelativeJump) { - size_t subId; + SubAssemblyID subId; size_t tagId; std::tie(subId, tagId) = item.splitForeignPushTag(); if (subId != _subId) diff --git a/libevmasm/BlockDeduplicator.h b/libevmasm/BlockDeduplicator.h index fb83b317e..26bcf59dc 100644 --- a/libevmasm/BlockDeduplicator.h +++ b/libevmasm/BlockDeduplicator.h @@ -24,10 +24,11 @@ #pragma once +#include + #include #include - #include #include #include @@ -52,14 +53,14 @@ class BlockDeduplicator /// @returns the tags that were replaced. std::map const& replacedTags() const { return m_replacedTags; } - /// Replaces all PushTag operations insied @a _items that match a key in - /// @a _replacements by the respective value. If @a _subID is not -1, only + /// Replaces all PushTag operations inside @a _items that match a key in + /// @a _replacements by the respective value. If @a _subID is not empty, only /// apply the replacement for foreign tags from this sub id. /// @returns true iff a replacement was performed. static bool applyTagReplacement( AssemblyItems& _items, std::map const& _replacements, - size_t _subID = size_t(-1) + SubAssemblyID _subID = {} ); private: diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index 74aaeb6c2..55ae30e7c 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -44,6 +44,7 @@ set(sources SimplificationRule.h SimplificationRules.cpp SimplificationRules.h + SubAssemblyID.h ) add_library(evmasm ${sources}) diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index bed4ff744..34a5c8a2a 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -62,7 +62,7 @@ void EVMAssemblyStack::assemble() m_sourceMapping = AssemblyItem::computeSourceMapping(m_evmAssembly->codeSections().front().items, sourceIndices()); if (m_evmAssembly->numSubs() > 0) { - m_evmRuntimeAssembly = std::make_shared(m_evmAssembly->sub(0)); + m_evmRuntimeAssembly = std::make_shared(m_evmAssembly->sub(SubAssemblyID{0})); solAssert(m_evmRuntimeAssembly && !m_evmRuntimeAssembly->isCreation()); // TODO: Check for EOF solAssert(m_evmRuntimeAssembly->codeSections().size() == 1); diff --git a/libevmasm/Inliner.cpp b/libevmasm/Inliner.cpp index f3358128c..f32a03ab5 100644 --- a/libevmasm/Inliner.cpp +++ b/libevmasm/Inliner.cpp @@ -71,7 +71,7 @@ std::optional getLocalTag(AssemblyItem const& _item) if (_item.type() != PushTag && _item.type() != Tag) return std::nullopt; auto [subId, tag] = _item.splitForeignPushTag(); - if (subId != std::numeric_limits::max()) + if (!subId.empty()) return std::nullopt; return tag; } diff --git a/libevmasm/JumpdestRemover.cpp b/libevmasm/JumpdestRemover.cpp index 7ded5ae90..84bec59d1 100644 --- a/libevmasm/JumpdestRemover.cpp +++ b/libevmasm/JumpdestRemover.cpp @@ -32,7 +32,7 @@ using namespace solidity::evmasm; bool JumpdestRemover::optimise(std::set const& _tagsReferencedFromOutside) { - std::set references{referencedTags(m_items, std::numeric_limits::max())}; + std::set references{referencedTags(m_items, SubAssemblyID{})}; references.insert(_tagsReferencedFromOutside.begin(), _tagsReferencedFromOutside.end()); size_t initialSize = m_items.size(); @@ -45,7 +45,7 @@ bool JumpdestRemover::optimise(std::set const& _tagsReferencedFromOutsid if (_item.type() != Tag) return false; auto asmIdAndTag = _item.splitForeignPushTag(); - assertThrow(asmIdAndTag.first == std::numeric_limits::max(), OptimizerException, "Sub-assembly tag used as label."); + solAssert(asmIdAndTag.first.empty(), "Sub-assembly tag used as label."); size_t tag = asmIdAndTag.second; return !references.count(tag); } @@ -54,7 +54,7 @@ bool JumpdestRemover::optimise(std::set const& _tagsReferencedFromOutsid return m_items.size() != initialSize; } -std::set JumpdestRemover::referencedTags(AssemblyItems const& _items, size_t _subId) +std::set JumpdestRemover::referencedTags(AssemblyItems const& _items, SubAssemblyID _subId) { std::set ret; for (auto const& item: _items) diff --git a/libevmasm/JumpdestRemover.h b/libevmasm/JumpdestRemover.h index e07550e2d..f344e543c 100644 --- a/libevmasm/JumpdestRemover.h +++ b/libevmasm/JumpdestRemover.h @@ -21,6 +21,8 @@ */ #pragma once +#include + #include #include #include @@ -39,7 +41,7 @@ class JumpdestRemover /// @returns a set of all tags from the given sub-assembly that are referenced /// from the given list of items. - static std::set referencedTags(AssemblyItems const& _items, size_t _subId); + static std::set referencedTags(AssemblyItems const& _items, SubAssemblyID _subId); private: AssemblyItems& m_items; diff --git a/libevmasm/SubAssemblyID.h b/libevmasm/SubAssemblyID.h new file mode 100644 index 000000000..48fb49894 --- /dev/null +++ b/libevmasm/SubAssemblyID.h @@ -0,0 +1,62 @@ +/* + 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 + +#pragma once + +#include + +#include + +#include +#include +#include +#include + +namespace solidity::evmasm +{ + +/// Sub assembly ID representing class. Based on fixed-size 64-bit unsigned int. +/// An empty / root state is reflected by a value that is set to max and can be queried via the `empty()` member +/// function. +struct SubAssemblyID +{ + using ValueType = uint64_t; + SubAssemblyID() = default; + SubAssemblyID(ValueType const _value): value(_value) {} + explicit SubAssemblyID(u256 const& _data) + { + solAssert(_data <= std::numeric_limits::max()); + value = static_cast(_data); + } + + size_t asIndex() const + { + if constexpr(sizeof(ValueType) > sizeof(size_t)) + { + solAssert(value < std::numeric_limits::max()); + return static_cast(value); + } + return value; + } + bool empty() const { return value == std::numeric_limits::max(); } + auto operator<=>(SubAssemblyID const&) const = default; + + ValueType value = std::numeric_limits::max(); +}; + +} diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index bc801ff57..1df3e3cb4 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -70,7 +70,7 @@ class Compiler private: OptimiserSettings const m_optimiserSettings; CompilerContext m_runtimeContext; - size_t m_runtimeSub = size_t(-1); ///< Identifier of the runtime sub-assembly, if present. + evmasm::SubAssemblyID m_runtimeSub{}; ///< Identifier of the runtime sub-assembly, if present. CompilerContext m_context; }; diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index e8c4e9bc7..638ee6939 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -75,7 +75,7 @@ class CompilerContext m_yulUtilFunctions(m_evmVersion, _eofVersion, m_revertStrings, m_yulFunctionCollector) { if (m_runtimeContext) - m_runtimeSub = size_t(m_asm->newSub(m_runtimeContext->m_asm).data()); + m_runtimeSub = evmasm::SubAssemblyID{m_asm->newSub(m_runtimeContext->m_asm).data()}; } langutil::EVMVersion const& evmVersion() const { return m_evmVersion; } @@ -227,9 +227,9 @@ class CompilerContext /// on the stack. @returns the pushsub assembly item. evmasm::AssemblyItem addSubroutine(evmasm::AssemblyPointer const& _assembly) { return m_asm->appendSubroutine(_assembly); } /// Pushes the size of the subroutine. - void pushSubroutineSize(size_t _subRoutine) { m_asm->pushSubroutineSize(_subRoutine); } + void pushSubroutineSize(evmasm::SubAssemblyID _subRoutine) { m_asm->pushSubroutineSize(_subRoutine); } /// Pushes the offset of the subroutine. - void pushSubroutineOffset(size_t _subRoutine) { m_asm->pushSubroutineOffset(_subRoutine); } + void pushSubroutineOffset(evmasm::SubAssemblyID _subRoutine) { m_asm->pushSubroutineOffset(_subRoutine); } /// Pushes the size of the final program void appendProgramSize() { m_asm->appendProgramSize(); } /// Adds data to the data section, pushes a reference to the stack @@ -289,7 +289,7 @@ class CompilerContext /// @returns the runtime context if in creation mode and runtime context is set, nullptr otherwise. CompilerContext* runtimeContext() const { return m_runtimeContext; } /// @returns the identifier of the runtime subroutine. - size_t runtimeSub() const { return m_runtimeSub; } + evmasm::SubAssemblyID runtimeSub() const { return m_runtimeSub; } /// @returns a const reference to the underlying assembly. evmasm::Assembly const& assembly() const { return *m_asm; } @@ -376,7 +376,7 @@ class CompilerContext /// The runtime context if in Creation mode, this is used for generating tags that would be stored into the storage and then used at runtime. CompilerContext *m_runtimeContext; /// The index of the runtime subroutine. - size_t m_runtimeSub = std::numeric_limits::max(); + evmasm::SubAssemblyID m_runtimeSub{}; /// An index of low-level function labels by name. std::map m_lowLevelFunctions; /// Collector for yul functions. diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 3a4dca043..fc5ec2917 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -108,7 +108,7 @@ void ContractCompiler::compileContract( appendFunctionSelector(_contract); } -size_t ContractCompiler::compileConstructor( +SubAssemblyID ContractCompiler::compileConstructor( ContractDefinition const& _contract, std::map> const& _otherCompilers ) @@ -167,7 +167,7 @@ void ContractCompiler::appendInitAndConstructorCode(ContractDefinition const& _c } } -size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _contract) +SubAssemblyID ContractCompiler::packIntoContractCreator(ContractDefinition const& _contract) { solAssert(!!m_runtimeCompiler, ""); solAssert(!_contract.isLibrary(), "Tried to use contract creator or library."); @@ -186,7 +186,7 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont CompilerContext::LocationSetter locationSetter(m_context, _contract); m_context << deployRoutine; - solAssert(m_context.runtimeSub() != std::numeric_limits::max(), "Runtime sub not registered"); + solAssert(!m_context.runtimeSub().empty(), "Runtime sub not registered"); ContractType contractType(_contract); auto const& immutables = contractType.immutableVariables(); @@ -220,7 +220,7 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont return m_context.runtimeSub(); } -size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract) +SubAssemblyID ContractCompiler::deployLibrary(ContractDefinition const& _contract) { solAssert(!!m_runtimeCompiler, ""); solAssert(_contract.isLibrary(), "Tried to deploy contract as library."); @@ -230,7 +230,7 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract) CompilerContext::LocationSetter locationSetter(m_context, _contract); - solAssert(m_context.runtimeSub() != std::numeric_limits::max(), "Runtime sub not registered"); + solAssert(!m_context.runtimeSub().empty(), "Runtime sub not registered"); m_context.pushSubroutineSize(m_context.runtimeSub()); m_context.pushSubroutineOffset(m_context.runtimeSub()); // This code replaces the address added by appendDeployTimeAddress(). diff --git a/libsolidity/codegen/ContractCompiler.h b/libsolidity/codegen/ContractCompiler.h index 592b67039..e342bbc5f 100644 --- a/libsolidity/codegen/ContractCompiler.h +++ b/libsolidity/codegen/ContractCompiler.h @@ -58,7 +58,7 @@ class ContractCompiler: private ASTConstVisitor ); /// Compiles the constructor part of the contract. /// @returns the identifier of the runtime sub-assembly. - size_t compileConstructor( + evmasm::SubAssemblyID compileConstructor( ContractDefinition const& _contract, std::map> const& _otherCompilers ); @@ -73,11 +73,11 @@ class ContractCompiler: private ASTConstVisitor /// Adds the code that is run at creation time. Should be run after exchanging the run-time context /// with a new and initialized context. Adds the constructor code. /// @returns the identifier of the runtime sub assembly - size_t packIntoContractCreator(ContractDefinition const& _contract); + evmasm::SubAssemblyID packIntoContractCreator(ContractDefinition const& _contract); /// Appends code that deploys the given contract as a library. /// Will also add code that modifies the contract in memory by injecting the current address /// for the call protector. - size_t deployLibrary(ContractDefinition const& _contract); + evmasm::SubAssemblyID deployLibrary(ContractDefinition const& _contract); /// Appends state variable initialisation and constructor code. void appendInitAndConstructorCode(ContractDefinition const& _contract); void appendBaseConstructor(FunctionDefinition const& _constructor); diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index 2df14f211..6cd598746 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -49,9 +49,9 @@ CompilabilityChecker::CompilabilityChecker( BuiltinContext builtinContext; builtinContext.currentObject = &_object; if (!_object.name.empty()) - builtinContext.subIDs[_object.name] = 1; + builtinContext.subIDs[_object.name] = {1}; for (auto const& subNode: _object.subObjects) - builtinContext.subIDs[subNode->name] = 1; + builtinContext.subIDs[subNode->name] = {1}; NoOutputAssembly assembly{evmDialect->evmVersion()}; CodeTransform transform( assembly, diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 54ec6a3cf..bb0441287 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -169,7 +169,7 @@ Object::Structure Object::summarizeStructure() const return structure; } -std::vector Object::pathToSubObject(std::string_view _qualifiedName) const +std::vector Object::pathToSubObject(std::string_view _qualifiedName) const { yulAssert(_qualifiedName != name, ""); yulAssert(subIndexByName.count(name) == 0, ""); @@ -181,7 +181,7 @@ std::vector Object::pathToSubObject(std::string_view _qualifiedName) con std::vector subObjectPathComponents; boost::algorithm::split(subObjectPathComponents, _qualifiedName, boost::is_any_of(".")); - std::vector path; + std::vector path; Object const* object = this; for (std::string const& currentSubObjectName: subObjectPathComponents) { @@ -193,8 +193,8 @@ std::vector Object::pathToSubObject(std::string_view _qualifiedName) con ); object = dynamic_cast(object->subObjects[subIndexIt->second].get()); yulAssert(object, "Assembly object <" + std::string(_qualifiedName) + "> not found or does not contain code."); - yulAssert(object->subId != std::numeric_limits::max(), ""); - path.push_back({object->subId}); + yulAssert(!object->subId.empty()); + path.emplace_back(object->subId); } return path; diff --git a/libyul/Object.h b/libyul/Object.h index c865b906e..a816db11b 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -24,6 +24,8 @@ #include #include +#include + #include #include @@ -135,14 +137,14 @@ class Object: public ObjectNode /// pathToSubObject("E2.F3.H4") == {1, 0, 2} /// pathToSubObject("A1.E2") == {1} /// The path must not lead to a @a Data object (will throw in that case). - std::vector pathToSubObject(std::string_view _qualifiedName) const; + std::vector pathToSubObject(std::string_view _qualifiedName) const; std::shared_ptr code() const; void setCode(std::shared_ptr const& _ast, std::shared_ptr = nullptr); bool hasCode() const; - /// sub id for object if it is subobject of another object, max value if it is not subobject - size_t subId = std::numeric_limits::max(); + /// sub id for object if it is subobject of another object, max value / empty if it is not subobject + evmasm::SubAssemblyID subId{}; std::vector> subObjects; std::map> subIndexByName; diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index a09e88791..63f372bf6 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -56,7 +56,7 @@ Dialect const& yul::languageToDialect(Language _language, EVMVersion _version, s void ObjectOptimizer::optimize(Object& _object, Settings const& _settings) { - yulAssert(_object.subId == std::numeric_limits::max(), "Not a top-level object."); + yulAssert(_object.subId.empty(), "Not a top-level object."); optimize(_object, _settings, true /* _isCreation */); } diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index b59b4781f..52c6241c6 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -330,15 +330,15 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) assembly.optimise(evmasm::Assembly::OptimiserSettings::translateSettings(m_optimiserSettings)); - std::optional subIndex; + std::optional subIndex; // Pick matching assembly if name was given if (_deployName.has_value()) { for (size_t i = 0; i < assembly.numSubs(); i++) - if (assembly.sub(i).name() == _deployName) + if (assembly.sub({i}).name() == _deployName) { - subIndex = i; + subIndex = {i}; break; } @@ -346,7 +346,7 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) } // Otherwise use heuristic: If there is a single sub-assembly, this is likely the object to be deployed. else if (assembly.numSubs() == 1) - subIndex = 0; + subIndex = {0}; if (subIndex.has_value()) { diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index 41f480f44..3108729b9 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -25,6 +25,8 @@ #include +#include + #include #include #include @@ -55,7 +57,7 @@ class AbstractAssembly { public: using LabelID = size_t; - using SubID = size_t; + using SubID = evmasm::SubAssemblyID; using ContainerID = uint8_t; using FunctionID = uint16_t; enum class JumpType { Ordinary, IntoFunction, OutOfFunction }; diff --git a/libyul/backends/evm/EVMBuiltins.cpp b/libyul/backends/evm/EVMBuiltins.cpp index d8a3d5c8e..bc4590632 100644 --- a/libyul/backends/evm/EVMBuiltins.cpp +++ b/libyul/backends/evm/EVMBuiltins.cpp @@ -135,10 +135,10 @@ BuiltinFunctionForEVM datasizeBuiltin() _assembly.appendAssemblySize(); else { - std::vector subIdPath = + std::vector subIdPath = _context.subIDs.count(dataName.str()) == 0 ? _context.currentObject->pathToSubObject(dataName.str()) : - std::vector{_context.subIDs.at(dataName.str())}; + std::vector{_context.subIDs.at(dataName.str())}; yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); _assembly.appendDataSize(subIdPath); } @@ -161,10 +161,10 @@ BuiltinFunctionForEVM dataoffsetBuiltin() _assembly.appendConstant(0); else { - std::vector subIdPath = + std::vector subIdPath = _context.subIDs.count(dataName.str()) == 0 ? _context.currentObject->pathToSubObject(dataName.str()) : - std::vector{_context.subIDs.at(dataName.str())}; + std::vector{_context.subIDs.at(dataName.str())}; yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); _assembly.appendDataOffset(subIdPath); } @@ -284,8 +284,8 @@ BuiltinFunctionForEVM eofcreateBuiltin() yulAssert(!util::contains(formattedLiteral, '.')); auto const* containerID = util::valueOrNullptr(context.subIDs, formattedLiteral); yulAssert(containerID != nullptr); - yulAssert(*containerID <= std::numeric_limits::max()); - _assembly.appendEOFCreate(static_cast(*containerID)); + yulAssert(containerID->value <= std::numeric_limits::max()); + _assembly.appendEOFCreate(static_cast(containerID->value)); } ); } @@ -311,8 +311,8 @@ BuiltinFunctionForEVM returncontractBuiltin() yulAssert(!util::contains(formattedLiteral, '.')); auto const* containerID = util::valueOrNullptr(context.subIDs, formattedLiteral); yulAssert(containerID != nullptr); - yulAssert(*containerID <= std::numeric_limits::max()); - _assembly.appendReturnContract(static_cast(*containerID)); + yulAssert(containerID->value <= std::numeric_limits::max()); + _assembly.appendReturnContract(static_cast(containerID->value)); } ); } diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index 960e663df..47bd3ffb6 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -142,7 +142,7 @@ std::pair, AbstractAssembly::SubID> EthAssembl { std::shared_ptr assembly{std::make_shared(m_assembly.evmVersion(), _creation, m_assembly.eofVersion(), std::move(_name))}; auto sub = m_assembly.newSub(assembly); - return {std::make_shared(*assembly), static_cast(sub.data())}; + return {std::make_shared(*assembly), SubID{sub.data()}}; } AbstractAssembly::FunctionID EthAssemblyAdapter::registerFunction(uint8_t _args, uint8_t _rets, bool _nonReturning) @@ -207,7 +207,7 @@ void EthAssemblyAdapter::appendDataSize(std::vector con AbstractAssembly::SubID EthAssemblyAdapter::appendData(bytes const& _data) { evmasm::AssemblyItem pushData = m_assembly.newData(_data); - SubID subID = m_nextDataCounter++; + SubID const subID{m_nextDataCounter++}; m_dataHashBySubId[subID] = pushData.data(); return subID; } diff --git a/libyul/backends/evm/EthAssemblyAdapter.h b/libyul/backends/evm/EthAssemblyAdapter.h index dd708b8b3..ffdd26f14 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.h +++ b/libyul/backends/evm/EthAssemblyAdapter.h @@ -88,6 +88,6 @@ class EthAssemblyAdapter: public AbstractAssembly evmasm::Assembly& m_assembly; std::map m_dataHashBySubId; - size_t m_nextDataCounter = std::numeric_limits::max() / 2; + SubID::ValueType m_nextDataCounter = std::numeric_limits::max() / 2; }; } diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index 1acc0d0ae..bd98d18ff 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -176,7 +176,7 @@ void NoOutputAssembly::appendDataSize(std::vector const AbstractAssembly::SubID NoOutputAssembly::appendData(bytes const&) { - return 1; + return {1}; } diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 32855cfbc..4432a4f2e 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -109,11 +109,11 @@ BOOST_AUTO_TEST_CASE(all_assembly_items, *boost::unit_test::precondition(nonEOF( // PushSubSize auto sub = _assembly.appendSubroutine(_subAsmPtr); // PushSub - _assembly.pushSubroutineOffset(static_cast(sub.data())); + _assembly.pushSubroutineOffset(SubAssemblyID(sub.data())); // PushSubSize auto verbatim_sub = _assembly.appendSubroutine(_verbatimAsmPtr); // PushSub - _assembly.pushSubroutineOffset(static_cast(verbatim_sub.data())); + _assembly.pushSubroutineOffset(SubAssemblyID(verbatim_sub.data())); // PushDeployTimeAddress _assembly.append(PushDeployTimeAddress); // AssignImmutable. @@ -332,7 +332,7 @@ BOOST_AUTO_TEST_CASE(immutable, *boost::unit_test::precondition(nonEOF())) _assembly.appendImmutableAssignment("someOtherImmutable"); auto sub = _assembly.appendSubroutine(_subAsmPtr); - _assembly.pushSubroutineOffset(static_cast(sub.data())); + _assembly.pushSubroutineOffset(SubAssemblyID(sub.data())); checkCompilation(_assembly); @@ -418,11 +418,11 @@ BOOST_AUTO_TEST_CASE(subobject_encode_decode) assembly.appendSubroutine(subAsmPtr); subAsmPtr->appendSubroutine(subSubAsmPtr); - BOOST_CHECK(assembly.encodeSubPath({0}) == 0); - BOOST_REQUIRE_THROW(assembly.encodeSubPath({1}), solidity::evmasm::AssemblyException); - BOOST_REQUIRE_THROW(assembly.decodeSubPath(1), solidity::evmasm::AssemblyException); + BOOST_CHECK(assembly.encodeSubPath({SubAssemblyID{0}}).value == 0); + BOOST_REQUIRE_THROW(assembly.encodeSubPath({SubAssemblyID{1}}), solidity::langutil::InternalCompilerError); + BOOST_REQUIRE_THROW(assembly.decodeSubPath(SubAssemblyID{1}), solidity::evmasm::AssemblyException); - std::vector subPath{0, 0}; + std::vector subPath{{0}, {0}}; BOOST_CHECK(assembly.decodeSubPath(assembly.encodeSubPath(subPath)) == subPath); } diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index b53205e95..01e1f9ac6 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1546,7 +1546,7 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies, *boost::unit_test::precondi sub->append(t4.pushTag()); sub->append(Instruction::JUMP); - size_t subId = static_cast(main.appendSubroutine(sub).data()); + SubAssemblyID subId{main.appendSubroutine(sub).data()}; main.append(t1.toSubAssemblyTag(subId)); main.append(t1.toSubAssemblyTag(subId)); main.append(u256(8)); From f6b95db7d42660254fbf946e32e04c5eb562d03a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 19 Mar 2025 10:45:10 +0100 Subject: [PATCH 0917/1340] Add test with non-zero PUSH #[$] to solc-js tests --- test/externalTests/solc-js/asm-json.js | 45 ++++++++++++++++++++++++++ test/externalTests/solc-js/solc-js.sh | 3 ++ 2 files changed, 48 insertions(+) create mode 100644 test/externalTests/solc-js/asm-json.js diff --git a/test/externalTests/solc-js/asm-json.js b/test/externalTests/solc-js/asm-json.js new file mode 100644 index 000000000..b41c35947 --- /dev/null +++ b/test/externalTests/solc-js/asm-json.js @@ -0,0 +1,45 @@ +const tape = require('tape'); +const fs = require('fs'); +const solc = require('../index.js'); + +tape('ASM Json output consistency', function (t) { + t.test('Nested structure', function(st) { + const testdir = 'test/'; + const output = JSON.parse(solc.compile(JSON.stringify({ + language: 'Solidity', + settings: { + viaIR: true, + outputSelection: { + '*': { + '*': ['evm.legacyAssembly'] + } + } + }, + sources: { + C: { + content: fs.readFileSync(testdir + 'code_access_runtime.sol', 'utf8') + } + } + }))); + st.ok(output); + + function containsAssemblyItem(assemblyJSON, assemblyItem) { + if (Array.isArray(assemblyJSON)) + return assemblyJSON.some(item => containsAssemblyItem(item, assemblyItem)); + else if (typeof assemblyJSON === 'object' && assemblyJSON !== null) { + if (assemblyJSON.name === assemblyItem.name && assemblyJSON.value === assemblyItem.value) + return true; + return Object.values(assemblyJSON).some(value => containsAssemblyItem(value, assemblyItem)); + } + return false; + } + + // regression test that there is indeed a negative subassembly index in there + // and it is based on a 64 bit uint + const targetObject = { + "name": "PUSH #[$]", + "value": "000000000000000000000000000000000000000000000000ffffffffffffffff" + }; + st.equal(containsAssemblyItem(output["contracts"]["C"]["C"]["evm"]["legacyAssembly"], targetObject), true) + }); +}); diff --git a/test/externalTests/solc-js/solc-js.sh b/test/externalTests/solc-js/solc-js.sh index af325326c..f4e62b6da 100755 --- a/test/externalTests/solc-js/solc-js.sh +++ b/test/externalTests/solc-js/solc-js.sh @@ -48,6 +48,9 @@ function solcjs_test printLog "Copying contracts..." cp -Rf "$SOLCJS_INPUT_DIR/DAO" test/ + printLog "Copying test with non-zero subassembly access" + cp -f "$TEST_DIR"/test/libsolidity/semanticTests/various/code_access_runtime.sol test/ + printLog "Copying SMTChecker tests..." # We do not copy all tests because that takes too long. cp -Rf "$TEST_DIR"/test/libsolidity/smtCheckerTests/external_calls test/smtCheckerTests/ From 683ad061bc10ea445d0ee9924dda0168b3020fa7 Mon Sep 17 00:00:00 2001 From: MozirDmitriy Date: Mon, 28 Jul 2025 10:13:13 +0300 Subject: [PATCH 0918/1340] Fix typo in fitsPrecisionBase2 function comment --- libsolidity/analysis/ConstantEvaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 0d953be93..691d273d5 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -59,7 +59,7 @@ bool fitsPrecisionExp(bigint const& _base, bigint const& _exp) return bitsNeeded <= bitsMax; } -/// Checks whether _mantissa * (2 ** _expBase10) fits into 4096 bits. +/// Checks whether _mantissa * (2 ** _expBase2) fits into 4096 bits. bool fitsPrecisionBase2(bigint const& _mantissa, uint32_t _expBase2) { return fitsPrecisionBaseX(_mantissa, 1.0, _expBase2); From 84dd7077c49eb670c0145e16d15836df50014f0e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 30 Jul 2025 09:30:37 +0200 Subject: [PATCH 0919/1340] ssa cfg builder: treat constant conditions in jumpi explicitly --- .../evm/SSAControlFlowGraphBuilder.cpp | 41 ++++++---- test/libyul/yulSSAControlFlowGraph/if.yul | 17 ++-- .../yulSSAControlFlowGraph/if_const.yul | 31 ++++++++ .../yulSSAControlFlowGraph/nested_for.yul | 78 ++++++++++--------- 4 files changed, 107 insertions(+), 60 deletions(-) create mode 100644 test/libyul/yulSSAControlFlowGraph/if_const.yul diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 101fd2eb3..5022bd04f 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -287,20 +287,33 @@ void SSAControlFlowGraphBuilder::operator()(FunctionDefinition const& _functionD void SSAControlFlowGraphBuilder::operator()(If const& _if) { - auto condition = std::visit(*this, *_if.condition); - auto ifBranch = m_graph.makeBlock(debugDataOf(_if.body)); - auto afterIf = m_graph.makeBlock(debugDataOf(currentBlock())); - conditionalJump( - debugDataOf(_if), - condition, - ifBranch, - afterIf - ); - sealBlock(ifBranch); - m_currentBlock = ifBranch; - (*this)(_if.body); - jump(debugDataOf(_if.body), afterIf); - sealBlock(afterIf); + std::optional constantCondition; + if (auto const* literalCondition = std::get_if(_if.condition.get())) + constantCondition = literalCondition->value.value() != 0; + // deal with literal (constant) conditions explicitly + if (constantCondition) + { + if (*constantCondition) + // Always true - skip conditional, just execute if branch + (*this)(_if.body); + } + else + { + auto condition = std::visit(*this, *_if.condition); + auto ifBranch = m_graph.makeBlock(debugDataOf(_if.body)); + auto afterIf = m_graph.makeBlock(debugDataOf(currentBlock())); + conditionalJump( + debugDataOf(_if), + condition, + ifBranch, + afterIf + ); + sealBlock(ifBranch); + m_currentBlock = ifBranch; + (*this)(_if.body); + jump(debugDataOf(_if.body), afterIf); + sealBlock(afterIf); + } } void SSAControlFlowGraphBuilder::operator()(Switch const& _switch) diff --git a/test/libyul/yulSSAControlFlowGraph/if.yul b/test/libyul/yulSSAControlFlowGraph/if.yul index e2a66ab74..f8639b2cc 100644 --- a/test/libyul/yulSSAControlFlowGraph/if.yul +++ b/test/libyul/yulSSAControlFlowGraph/if.yul @@ -1,6 +1,6 @@ { let x := calldataload(3) - if 0 { + if mload(42) { x := calldataload(77) } let y := calldataload(x) @@ -17,26 +17,27 @@ // Block0_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ // LiveOut: v1\l\nv1 := calldataload(3)\l\ +// v3 := mload(42)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If 0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_0Exit:0 -> Block0_2 [style="solid"]; // Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v4\l\nv4 := calldataload(77)\l\ +// LiveOut: v5\l\nv5 := calldataload(77)\l\ // "]; // Block0_1 -> Block0_1Exit [arrowhead=none]; // Block0_1Exit [label="Jump" shape=oval]; // Block0_1Exit -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: v5\l\ -// LiveOut: \l\nv5 := φ(\l\ +// Block 2; (2, max 2)\nLiveIn: v6\l\ +// LiveOut: \l\nv6 := φ(\l\ // Block 0 => v1,\l\ -// Block 1 => v4\l\ +// Block 1 => v5\l\ // )\l\ -// v6 := calldataload(v5)\l\ -// sstore(0, v6)\l\ +// v7 := calldataload(v6)\l\ +// sstore(0, v7)\l\ // "]; // Block0_2Exit [label="MainExit"]; // Block0_2 -> Block0_2Exit; diff --git a/test/libyul/yulSSAControlFlowGraph/if_const.yul b/test/libyul/yulSSAControlFlowGraph/if_const.yul new file mode 100644 index 000000000..26a3c094c --- /dev/null +++ b/test/libyul/yulSSAControlFlowGraph/if_const.yul @@ -0,0 +1,31 @@ +{ + let x := calldataload(3) + // this should not appear in the output at all + if 0 { + x := calldataload(77) + } + // this should avoid a conditional jump + if 33 { + x := calldataload(42) + } + let y := calldataload(x) + sstore(y, 0) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans"] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry0 [label="Entry"]; +// Entry0 -> Block0_0; +// Block0_0 [label="\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nv1 := calldataload(3)\l\ +// v3 := calldataload(42)\l\ +// v4 := calldataload(v3)\l\ +// sstore(0, v4)\l\ +// "]; +// Block0_0Exit [label="MainExit"]; +// Block0_0 -> Block0_0Exit; +// } diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/yulSSAControlFlowGraph/nested_for.yul index f57a5ca29..6efb3552a 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_for.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_for.yul @@ -2,12 +2,12 @@ for { let i := 0 } lt(i, 3) { i := add(i, 1) } { for { let j := 0 } lt(j, 3) { j := add(j, 1) } { for { let k := 0 } lt(k, 3) { k := add(k, 1) } { - if 0 { + if mload(0) { for { let l := 0 } lt(l, 3) { l := add(l, 1) } { sstore(l, add(add(i,j),k)) } } - if 1 { + if mload(1) { for { let l := 0 } lt(l, 3) { l := add(l, 1) } { sstore(l, add(add(i,j),k)) } @@ -36,7 +36,7 @@ // Block 1; (1, max 24)\nLiveIn: v3\l\ // LiveOut: v3\l\nv3 := φ(\l\ // Block 0 => v1,\l\ -// Block 3 => v41\l\ +// Block 3 => v43\l\ // )\l\ // v4 := lt(3, v3)\l\ // "]; @@ -60,7 +60,7 @@ // Block 5; (3, max 23)\nLiveIn: v3,v6\l\ // LiveOut: v3,v6\l\nv6 := φ(\l\ // Block 2 => v5,\l\ -// Block 7 => v40\l\ +// Block 7 => v42\l\ // )\l\ // v7 := lt(3, v6)\l\ // "]; @@ -85,7 +85,7 @@ // Block 9; (5, max 21)\nLiveIn: v3,v6,v9\l\ // LiveOut: v3,v6,v9\l\nv9 := φ(\l\ // Block 6 => v8,\l\ -// Block 11 => v36\l\ +// Block 11 => v38\l\ // )\l\ // v10 := lt(3, v9)\l\ // "]; @@ -95,16 +95,17 @@ // Block0_9Exit:1 -> Block0_10 [style="solid"]; // Block0_3 [label="\ // Block 3; (23, max 23)\nLiveIn: v3\l\ -// LiveOut: v41\l\nv41 := add(1, v3)\l\ +// LiveOut: v43\l\nv43 := add(1, v3)\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; // Block0_3Exit -> Block0_1 [style="dashed"]; // Block0_10 [label="\ // Block 10; (6, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9\l\n"]; +// LiveOut: v3,v6,v9\l\nv11 := mload(0)\l\ +// "]; // Block0_10 -> Block0_10Exit; -// Block0_10Exit [label="{ If 0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_10Exit [label="{ If v11 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_10Exit:0 -> Block0_14 [style="solid"]; // Block0_10Exit:1 -> Block0_13 [style="solid"]; // Block0_12 [label="\ @@ -115,40 +116,41 @@ // Block0_12Exit -> Block0_7 [style="solid"]; // Block0_13 [label="\ // Block 13; (7, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9,v11\l\nv11 := 0\l\ +// LiveOut: v3,v6,v9,v12\l\nv12 := 0\l\ // "]; // Block0_13 -> Block0_13Exit [arrowhead=none]; // Block0_13Exit [label="Jump" shape=oval]; // Block0_13Exit -> Block0_15 [style="solid"]; // Block0_14 [label="\ // Block 14; (12, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9\l\n"]; +// LiveOut: v3,v6,v9\l\nv24 := mload(1)\l\ +// "]; // Block0_14 -> Block0_14Exit; -// Block0_14Exit [label="{ If 1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_14Exit [label="{ If v24 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_14Exit:0 -> Block0_20 [style="solid"]; // Block0_14Exit:1 -> Block0_19 [style="solid"]; // Block0_7 [label="\ // Block 7; (21, max 21)\nLiveIn: v3,v6\l\ -// LiveOut: v3,v40\l\nv40 := add(1, v6)\l\ +// LiveOut: v3,v42\l\nv42 := add(1, v6)\l\ // "]; // Block0_7 -> Block0_7Exit [arrowhead=none]; // Block0_7Exit [label="Jump" shape=oval]; // Block0_7Exit -> Block0_5 [style="dashed"]; // Block0_15 [label="\ -// Block 15; (8, max 19)\nLiveIn: v3,v6,v9,v12\l\ -// LiveOut: v3,v6,v9,v12\l\nv12 := φ(\l\ -// Block 13 => v11,\l\ -// Block 17 => v20\l\ +// Block 15; (8, max 19)\nLiveIn: v3,v6,v9,v13\l\ +// LiveOut: v3,v6,v9,v13\l\nv13 := φ(\l\ +// Block 13 => v12,\l\ +// Block 17 => v21\l\ // )\l\ -// v13 := lt(3, v12)\l\ +// v14 := lt(3, v13)\l\ // "]; // Block0_15 -> Block0_15Exit; -// Block0_15Exit [label="{ If v13 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_15Exit [label="{ If v14 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_15Exit:0 -> Block0_18 [style="solid"]; // Block0_15Exit:1 -> Block0_16 [style="solid"]; // Block0_19 [label="\ // Block 19; (13, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9,v23\l\nv23 := 0\l\ +// LiveOut: v3,v6,v9,v25\l\nv25 := 0\l\ // "]; // Block0_19 -> Block0_19Exit [arrowhead=none]; // Block0_19Exit [label="Jump" shape=oval]; @@ -160,10 +162,10 @@ // Block0_20Exit [label="Jump" shape=oval]; // Block0_20Exit -> Block0_11 [style="solid"]; // Block0_16 [label="\ -// Block 16; (9, max 10)\nLiveIn: v3,v6,v9,v12\l\ -// LiveOut: v3,v6,v9,v12\l\nv17 := add(v6, v3)\l\ -// v18 := add(v9, v17)\l\ -// sstore(v18, v12)\l\ +// Block 16; (9, max 10)\nLiveIn: v3,v6,v9,v13\l\ +// LiveOut: v3,v6,v9,v13\l\nv18 := add(v6, v3)\l\ +// v19 := add(v9, v18)\l\ +// sstore(v19, v13)\l\ // "]; // Block0_16 -> Block0_16Exit [arrowhead=none]; // Block0_16Exit [label="Jump" shape=oval]; @@ -175,36 +177,36 @@ // Block0_18Exit [label="Jump" shape=oval]; // Block0_18Exit -> Block0_14 [style="solid"]; // Block0_21 [label="\ -// Block 21; (14, max 19)\nLiveIn: v3,v6,v9,v24\l\ -// LiveOut: v3,v6,v9,v24\l\nv24 := φ(\l\ -// Block 19 => v23,\l\ -// Block 23 => v31\l\ +// Block 21; (14, max 19)\nLiveIn: v3,v6,v9,v26\l\ +// LiveOut: v3,v6,v9,v26\l\nv26 := φ(\l\ +// Block 19 => v25,\l\ +// Block 23 => v33\l\ // )\l\ -// v25 := lt(3, v24)\l\ +// v27 := lt(3, v26)\l\ // "]; // Block0_21 -> Block0_21Exit; -// Block0_21Exit [label="{ If v25 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_21Exit [label="{ If v27 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_21Exit:0 -> Block0_24 [style="solid"]; // Block0_21Exit:1 -> Block0_22 [style="solid"]; // Block0_11 [label="\ // Block 11; (19, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v36\l\nv36 := add(1, v9)\l\ +// LiveOut: v3,v6,v38\l\nv38 := add(1, v9)\l\ // "]; // Block0_11 -> Block0_11Exit [arrowhead=none]; // Block0_11Exit [label="Jump" shape=oval]; // Block0_11Exit -> Block0_9 [style="dashed"]; // Block0_17 [label="\ -// Block 17; (10, max 10)\nLiveIn: v3,v6,v9,v12\l\ -// LiveOut: v3,v6,v9,v20\l\nv20 := add(1, v12)\l\ +// Block 17; (10, max 10)\nLiveIn: v3,v6,v9,v13\l\ +// LiveOut: v3,v6,v9,v21\l\nv21 := add(1, v13)\l\ // "]; // Block0_17 -> Block0_17Exit [arrowhead=none]; // Block0_17Exit [label="Jump" shape=oval]; // Block0_17Exit -> Block0_15 [style="dashed"]; // Block0_22 [label="\ -// Block 22; (15, max 16)\nLiveIn: v3,v6,v9,v24\l\ -// LiveOut: v3,v6,v9,v24\l\nv29 := add(v6, v3)\l\ -// v30 := add(v9, v29)\l\ -// sstore(v30, v24)\l\ +// Block 22; (15, max 16)\nLiveIn: v3,v6,v9,v26\l\ +// LiveOut: v3,v6,v9,v26\l\nv31 := add(v6, v3)\l\ +// v32 := add(v9, v31)\l\ +// sstore(v32, v26)\l\ // "]; // Block0_22 -> Block0_22Exit [arrowhead=none]; // Block0_22Exit [label="Jump" shape=oval]; @@ -216,8 +218,8 @@ // Block0_24Exit [label="Jump" shape=oval]; // Block0_24Exit -> Block0_20 [style="solid"]; // Block0_23 [label="\ -// Block 23; (16, max 16)\nLiveIn: v3,v6,v9,v24\l\ -// LiveOut: v3,v6,v9,v31\l\nv31 := add(1, v24)\l\ +// Block 23; (16, max 16)\nLiveIn: v3,v6,v9,v26\l\ +// LiveOut: v3,v6,v9,v33\l\nv33 := add(1, v26)\l\ // "]; // Block0_23 -> Block0_23Exit [arrowhead=none]; // Block0_23Exit [label="Jump" shape=oval]; From 140fdbd654687d11be889fa4039b68840d674d2f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 30 Jul 2025 10:12:46 +0200 Subject: [PATCH 0920/1340] ssa cfg builder: treat constant switches explicitly --- .../evm/SSAControlFlowGraphBuilder.cpp | 22 ++++++++ .../yulSSAControlFlowGraph/switch_const.yul | 55 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 test/libyul/yulSSAControlFlowGraph/switch_const.yul diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 5022bd04f..35e2e4935 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -355,6 +355,28 @@ void SSAControlFlowGraphBuilder::operator()(Switch const& _switch) } else { + if (auto const* constantExpression = std::get_if(_switch.expression.get())) + { + Case const* matchedCase = nullptr; + // select case that matches (or default if available) + for (auto const& switchCase: _switch.cases) + { + if (!switchCase.value) + matchedCase = &switchCase; + if (switchCase.value && switchCase.value->value.value() == constantExpression->value.value()) + { + matchedCase = &switchCase; + break; + } + } + if (matchedCase) + { + // inject directly into the current block + (*this)(matchedCase->body); + } + return; + } + std::optional equalityBuiltinHandle = m_dialect.equalityFunctionHandle(); yulAssert(equalityBuiltinHandle); diff --git a/test/libyul/yulSSAControlFlowGraph/switch_const.yul b/test/libyul/yulSSAControlFlowGraph/switch_const.yul new file mode 100644 index 000000000..3de0537dc --- /dev/null +++ b/test/libyul/yulSSAControlFlowGraph/switch_const.yul @@ -0,0 +1,55 @@ +{ + let x := calldataload(3) + + // this should yield calldataload(88) directly + switch 1 + case 0 { + x := calldataload(77) + } + case 1 { + x := calldataload(88) + } + default { + x := calldataload(99) + } + + // this should yield the default case + switch 55 + case 0 { + x := calldataload(77) + } + case 1 { + x := calldataload(88) + } + default { + x := calldataload(99) + } + + // this should be skipped entirely + switch 66 + case 0 { + x := calldataload(77) + } + case 1 { + x := calldataload(88) + } + sstore(x, 0) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans"] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry0 [label="Entry"]; +// Entry0 -> Block0_0; +// Block0_0 [label="\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nv1 := calldataload(3)\l\ +// v4 := calldataload(88)\l\ +// v7 := calldataload(99)\l\ +// sstore(0, v7)\l\ +// "]; +// Block0_0Exit [label="MainExit"]; +// Block0_0 -> Block0_0Exit; +// } From 3d4a3c8ddef9182596e89c76b8aa9f4f5d82f372 Mon Sep 17 00:00:00 2001 From: sudo rm -rf --no-preserve-root / Date: Thu, 24 Jul 2025 12:17:15 +0200 Subject: [PATCH 0921/1340] docs: fix unnecessary `uint160(bytes20(b))` casting Resolves: https://github.com/ethereum/solidity/issues/16129. --- docs/types/value-types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 38d22aebd..57fa7b3da 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -229,7 +229,7 @@ Operators: To reduce conversion ambiguity, starting with version 0.4.24, the compiler will force you to make the truncation explicit in the conversion. Take for example the 32-byte value ``0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC``. - You can use ``address(uint160(bytes20(b)))``, which results in ``0x111122223333444455556666777788889999aAaa``, + You can use ``address(bytes20(b))``, which results in ``0x111122223333444455556666777788889999aAaa``, or you can use ``address(uint160(uint256(b)))``, which results in ``0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc``. .. note:: From ab68eaf116be0985baa598e35f94e8546202cda1 Mon Sep 17 00:00:00 2001 From: GarmashAlex Date: Tue, 13 May 2025 19:22:29 +0300 Subject: [PATCH 0922/1340] fix typos in comments --- libyul/backends/evm/StackLayoutGenerator.cpp | 2 +- test/compilationTests/corion/provider.sol | 2 +- test/compilationTests/corion/schelling.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 69045998c..f6d1108ee 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -308,7 +308,7 @@ Stack StackLayoutGenerator::propagateStackThroughOperation(Stack _exitStack, CFG // generated on the fly), s.t. shuffling the `stack + _operation.output` to _exitLayout is cheap. Stack stack = createIdealLayout(_operation.output, _exitStack, generateSlotOnTheFly, reachableStackDepth()); - // Make sure the resulting previous slots do not overlap with any assignmed variables. + // Make sure the resulting previous slots do not overlap with any assigned variables. if (auto const* assignment = std::get_if(&_operation.operation)) for (auto& stackSlot: stack) if (auto const* varSlot = std::get_if(&stackSlot)) diff --git a/test/compilationTests/corion/provider.sol b/test/compilationTests/corion/provider.sol index 524390b2e..435ddcc30 100644 --- a/test/compilationTests/corion/provider.sol +++ b/test/compilationTests/corion/provider.sol @@ -185,7 +185,7 @@ contract provider is module, safeMath, announcementTypes { } function setRightForInterest(uint256 oldValue, uint256 newValue, bool priv) internal { /* - It checks if the provider has enough connected captital to be able to get from the token emission. + It checks if the provider has enough connected capital to be able to get from the token emission. In case the provider is not able to get the share from the token emission then the connected capital will not count to the value of the globalFunds, to the current schelling round. @oldValue old diff --git a/test/compilationTests/corion/schelling.sol b/test/compilationTests/corion/schelling.sol index 96b530d26..9c57fe16f 100644 --- a/test/compilationTests/corion/schelling.sol +++ b/test/compilationTests/corion/schelling.sol @@ -256,7 +256,7 @@ contract schelling is module, announcementTypes, schellingVars { @_moduleHandler Address of ModuleHandler. @_db Address of the database. @_forReplace This address will be replaced with the old one or not. - @_icoExpansionAddress This address can turn schelling runds during ICO. + @_icoExpansionAddress This address can turn schelling funds during ICO. */ db = schellingDB(_db); super.registerModuleHandler(_moduleHandler); From 5dba5c5c389a5b98de285a8f3e440396c961b4a3 Mon Sep 17 00:00:00 2001 From: Shane Date: Sat, 25 Jan 2025 12:52:10 +0800 Subject: [PATCH 0923/1340] Replace "External accounts" with "Externally-owned accounts" for accuracy --- docs/introduction-to-smart-contracts.rst | 6 +++--- docs/security-considerations.rst | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 994cb85d4..74b537cca 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -131,7 +131,7 @@ This contract introduces some new concepts, let us go through them one by one. The line ``address public minter;`` declares a state variable of type :ref:`address
`. The ``address`` type is a 160-bit value that does not allow any arithmetic operations. It is suitable for storing addresses of contracts, or a hash of the public half -of a keypair belonging to :ref:`external accounts`. +of a keypair belonging to :ref:`externally-owned accounts`. The keyword ``public`` automatically generates a function that allows you to access the current value of the state variable from outside of the contract. Without this keyword, other contracts have no way to access the variable. @@ -338,11 +338,11 @@ Accounts ======== There are two kinds of accounts in Ethereum which share the same -address space: **External accounts** that are controlled by +address space: **Externally-owned accounts** that are controlled by public-private key pairs (i.e. humans) and **contract accounts** which are controlled by the code stored together with the account. -The address of an external account is determined from +The address of an externally-owned account is determined from the public key while the address of a contract is determined at the time the contract is created (it is derived from the creator address and the number diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 2b8f7f835..eb42993e6 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -144,7 +144,7 @@ Please be explicit about such cases in the documentation of your contracts. Sending and Receiving Ether =========================== -- Neither contracts nor "external accounts" are currently able to prevent someone from sending them Ether. +- Neither contracts nor "externally-owned accounts" are currently able to prevent someone from sending them Ether. Contracts can react on and reject a regular transfer, but there are ways to move Ether without creating a message call. One way is to simply "mine to" the contract address and the second way is using ``selfdestruct(x)``. From ce366e770a99b12e264e963b6f3c9fc829069d37 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 5 Aug 2025 17:47:15 +0200 Subject: [PATCH 0924/1340] Fix external ENS test --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0f4d2b6eb..ed4a29b6d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -779,7 +779,7 @@ defaults: name: t_native_test_ext_ens project: ens binary_type: native - image: cimg/node:18.16 + image: cimg/node:lts - job_native_compile_ext_trident: &job_native_compile_ext_trident <<: *requires_b_ubu_static From 37d4a729742a7f367bf454f85f17d9b25d011731 Mon Sep 17 00:00:00 2001 From: Tronica Date: Thu, 20 Mar 2025 10:01:53 +0100 Subject: [PATCH 0925/1340] chore(scripts): improve readability of regressions.py and splitSources.py Co-authored-by: clonker <1685266+clonker@users.noreply.github.com> --- scripts/regressions.py | 10 +++++----- scripts/splitSources.py | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/regressions.py b/scripts/regressions.py index e30c0aeb9..7de108ef3 100755 --- a/scripts/regressions.py +++ b/scripts/regressions.py @@ -22,15 +22,15 @@ def __init__(self, interval=300): thread.start() def run(self): - """ Runs until the main Python thread exits. """ - ## Print a newline at the very beginning. + """ Run indefinitely until the main Python thread exits. """ + ## Print an initial newline at the very beginning. print("") while True: # Print dot print(".") time.sleep(self.interval) -class regressor: +class Regressor: _re_sanitizer_log = re.compile(r"""ERROR: (libFuzzer|UndefinedBehaviorSanitizer)""") def __init__(self, description, args): @@ -87,7 +87,7 @@ def process_log(self, logfile): False -> Failure """ - ## Log may contain non ASCII characters, so we simply stringify them + ## Log may contain non-ASCII characters, so we simply stringify them ## since they don't matter for regular expression matching with open(logfile, 'rb', encoding=None) as f: rawtext = str(f.read()) @@ -122,5 +122,5 @@ def run(self): if __name__ == '__main__': dotprinter = PrintDotsThread() - tool = regressor(DESCRIPTION, sys.argv[1:]) + tool = Regressor(DESCRIPTION, sys.argv[1:]) sys.exit(not tool.run()) diff --git a/scripts/splitSources.py b/scripts/splitSources.py index 5e783b2d5..878600b17 100755 --- a/scripts/splitSources.py +++ b/scripts/splitSources.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # # This script reads a syntaxTest file and writes all -# sources into their own files. If one source-name specifies subdirectories +# sources into separate files. If a source name specifies subdirectories, # those will be created too. # Usage: scripts/splitSources.py pathToTestfile @@ -18,7 +18,7 @@ def uncaught_exception_hook(exc_type, exc_value, exc_traceback): # The script `scripts/ASTImportTest.sh` will interpret return code 3 # as a critical error (because of the uncaught exception) and will # terminate further execution. - print("Unhandled exception: %s", "".join(traceback.format_exception(exc_type, exc_value, exc_traceback))) + print("Unhandled exception: " + "".join(traceback.format_exception(exc_type, exc_value, exc_traceback))) sys.exit(3) @@ -42,7 +42,7 @@ def writeSourceToFile(lines): with open(srcName, mode='a+', encoding='utf8', newline='') as f: for idx, line in enumerate(lines[1:]): # write to file - if line[:12] != "==== Source:": + if not line.startswith("==== Source:"): f.write(line + '\n') # recursive call if there is another source From d578b6bdb781c6e24a30b7b3ab535002e4d87378 Mon Sep 17 00:00:00 2001 From: radik878 Date: Tue, 5 Aug 2025 16:16:01 +0300 Subject: [PATCH 0926/1340] Fix comparison operator of CHCVerificationTarget --- libsolidity/formal/CHC.h | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/libsolidity/formal/CHC.h b/libsolidity/formal/CHC.h index 8ecef3960..43033118a 100644 --- a/libsolidity/formal/CHC.h +++ b/libsolidity/formal/CHC.h @@ -74,18 +74,10 @@ class CHC: public SMTEncoder friend bool operator<(CHCVerificationTarget const& _a, CHCVerificationTarget const& _b) { - return _a.errorId < _b.errorId; - } - }; - - struct SafeTargetsCompare - { - bool operator()(CHCVerificationTarget const & _lhs, CHCVerificationTarget const & _rhs) const - { - if (_lhs.errorNode->id() == _rhs.errorNode->id()) - return _lhs.type < _rhs.type; + if (_a.errorNode->id() == _b.errorNode->id()) + return _a.type < _b.type; else - return _lhs.errorNode->id() == _rhs.errorNode->id(); + return _a.errorNode->id() < _b.errorNode->id(); } }; @@ -96,7 +88,7 @@ class CHC: public SMTEncoder std::string message; }; - std::map, smt::EncodingContext::IdCompare> const& safeTargets() const { return m_safeTargets; } + std::map, smt::EncodingContext::IdCompare> const& safeTargets() const { return m_safeTargets; } std::map, smt::EncodingContext::IdCompare> const& unsafeTargets() const { return m_unsafeTargets; } /// This is used if the Horn solver is not directly linked into this binary. @@ -434,7 +426,7 @@ class CHC: public SMTEncoder std::map m_verificationTargets; /// Targets proved safe. - std::map, smt::EncodingContext::IdCompare> m_safeTargets; + std::map, smt::EncodingContext::IdCompare> m_safeTargets; /// Targets proved unsafe. std::map, smt::EncodingContext::IdCompare> m_unsafeTargets; /// Targets not proved. From c78de76b993a8d2944d3d552318d1601029cb27a Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Mon, 11 Aug 2025 14:42:46 +0200 Subject: [PATCH 0927/1340] SSA-CFG: Tiny code simplifications --- .../evm/SSAControlFlowGraphBuilder.cpp | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp index 35e2e4935..0af08e39d 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp @@ -109,7 +109,7 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId m_graph.block(phiInfo->block).phis.erase(_phi); - std::set phiUses; + std::vector phiUses; for (size_t blockIdValue = 0; blockIdValue < m_graph.numBlocks(); ++blockIdValue) { auto& block = m_graph.block(SSACFG::BlockId{blockIdValue}); @@ -126,18 +126,13 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId usedInPhi = true; } if (usedInPhi) - phiUses.emplace(blockPhi); + phiUses.push_back(blockPhi); } for (auto& op: block.operations) - std::replace(op.inputs.begin(), op.inputs.end(), _phi, same); + ranges::replace(op.inputs, _phi, same); std::visit(util::GenericVisitor{ [_phi, same](SSACFG::BasicBlock::FunctionReturn& _functionReturn) { - std::replace( - _functionReturn.returnValues.begin(), - _functionReturn.returnValues.end(), - _phi, - same - ); + ranges::replace(_functionReturn.returnValues,_phi, same); }, [_phi, same](SSACFG::BasicBlock::ConditionalJump& _condJump) { if (_condJump.condition == _phi) @@ -188,22 +183,17 @@ void SSAControlFlowGraphBuilder::cleanUnreachable() { auto& block = m_graph.block(blockId); - std::set maybeTrivialPhi; - for (auto it = block.entries.begin(); it != block.entries.end();) - if (reachabilityCheck.visited.count(*it)) - it++; - else - it = block.entries.erase(it); + std::vector maybeTrivialPhi; + std::erase_if(block.entries, [&](auto const& entry) { return !reachabilityCheck.visited.contains(entry); }); for (auto phi: block.phis) if (auto* phiInfo = std::get_if(&m_graph.valueInfo(phi))) - std::erase_if(phiInfo->arguments, [&](SSACFG::ValueId _arg) { - if (std::holds_alternative(m_graph.valueInfo(_arg))) - { - maybeTrivialPhi.insert(phi); - return true; - } - return false; + { + auto erasedCount = std::erase_if(phiInfo->arguments, [&](SSACFG::ValueId _arg) { + return std::holds_alternative(m_graph.valueInfo(_arg)); }); + if (erasedCount > 0) + maybeTrivialPhi.push_back(phi); + } // After removing a phi argument, we might end up with a trivial phi that can be removed. for (auto phi: maybeTrivialPhi) From 47e0335095b25fdd71e074af1d0e1c4678b3788c Mon Sep 17 00:00:00 2001 From: Patrick Collins <54278053+PatrickAlphaC@users.noreply.github.com> Date: Mon, 9 Jun 2025 09:50:22 -0400 Subject: [PATCH 0928/1340] feat: added updraft glossary for solidity and smart contract terms --- docs/resources.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/resources.rst b/docs/resources.rst index 7c8d61afa..43161f7d0 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -15,6 +15,7 @@ General Resources * `awesome-solidity `_ * `Solidity by Example `_ * `Solidity documentation community translations `_ +* `Solidity and Smart Contract Glossary `_ Integrated (Ethereum) Development Environments ============================================== From 68364ab3a94c9b0ee779c535622d34132e9f74d9 Mon Sep 17 00:00:00 2001 From: phrwlk Date: Thu, 14 Aug 2025 18:41:35 +0000 Subject: [PATCH 0929/1340] refactor(formal): remove unused clear()/solver() --- libsolidity/formal/EncodingContext.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/libsolidity/formal/EncodingContext.h b/libsolidity/formal/EncodingContext.h index e7d577bbf..9d38f4b55 100644 --- a/libsolidity/formal/EncodingContext.h +++ b/libsolidity/formal/EncodingContext.h @@ -44,9 +44,6 @@ class EncodingContext void resetUniqueId(); /// Returns the current fresh slack id and increments it. unsigned newUniqueId(); - /// Clears the entire context, erasing everything. - /// To be used before a model checking engine starts. - void clear(); /// Sets the current solver used by the current engine for /// SMT variable declaration. @@ -139,12 +136,7 @@ class EncodingContext void pushSolver(); void popSolver(); void addAssertion(smtutil::Expression const& _e); - size_t solverStackHeight() { return m_assertions.size(); } const - smtutil::SolverInterface* solver() - { - solAssert(m_solver, ""); - return m_solver; - } + size_t solverStackHeight() const { return m_assertions.size(); } //@} SymbolicState& state() { return m_state; } From 116735fed904c3897f413245570480acf5b2262f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 8 Aug 2025 10:54:11 +0200 Subject: [PATCH 0930/1340] Yul expression simplifier: Don't substitute out of scope variables In some circumstances (in particular if not the AST is not in SSA form), it could happen that the ExpressionSimplifier would substitute out-of-scope variables. --- Changelog.md | 1 + libyul/optimiser/ExpressionSimplifier.cpp | 15 ++- .../args | 1 + .../input.sol | 101 ++++++++++++++++++ .../output | 4 + .../expressionSimplifier/invalid_match.yul | 34 ++++++ 6 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/args create mode 100644 test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/input.sol create mode 100644 test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/output create mode 100644 test/libyul/yulOptimizerTests/expressionSimplifier/invalid_match.yul diff --git a/Changelog.md b/Changelog.md index 8220e6d74..63ed87ffb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: Bugfixes: * Assembler: Fix not using a fixed-width type for IDs being assigned to subassemblies nested more than one level away, resulting in inconsistent `--asm-json` output between target architectures. +* Yul Optimizer: Fix edge case in which invalid Yul code is produced by ExpressionSimplifier due to expressions being substituted that contain out-of-scope variables. ### 0.8.30 (2025-05-07) diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index 4aa7be1bb..9f362215c 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -45,7 +46,19 @@ void ExpressionSimplifier::visit(Expression& _expression) while (auto const* match = SimplificationRules::findFirstMatch( _expression, m_dialect, - [this](YulName _var) { return variableValue(_var); } + [this](YulName const& _var) -> AssignedValue const* { + AssignedValue const* value = variableValue(_var); + if (!value || !value->value) + return nullptr; + + // check that all variables in the value expression are in current scope + MovableChecker const checker(m_dialect, *value->value); + for (YulName const& referencedVar: checker.referencedVariables()) + if (!inScope(referencedVar)) + return nullptr; // don't substitute if any referenced var is out of scope + + return value; + } )) { auto const* evmDialect = dynamic_cast(&m_dialect); diff --git a/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/args b/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/args new file mode 100644 index 000000000..302841a3a --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/args @@ -0,0 +1 @@ + --optimize --yul-optimizations Md[F]vtDI[jxVpjCDpTnvon]TFSI[v]:Etcns --via-ir --bin diff --git a/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/input.sol b/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/input.sol new file mode 100644 index 000000000..72b2c8858 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/input.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-3.0 +// reproducing https://github.com/ethereum/solidity/issues/16155 + +pragma solidity ^0.8.19; + +contract PlaceholderContract { + function tZhBDeXU4NnUR6(bool assert_in1) internal virtual returns (int128) { + return (( + (assert_in1 && false) + ? (int128(638) - int128(932)) + : (assert_in1 ? int128(923) : int128(392)) + ) / ((int128(517) * int128(573)) / (int128(273) % int128(605)))); + } + + function QtdPeAwoi7LD( + bool assert_in1, + bool assert_in2 + ) internal pure returns (int128) { + return (( + (assert_in2 || assert_in1) + ? (int128(478) % int128(983)) + : (int128(298) + int128(316)) + ) + + ( + (assert_in1 && assert_in1) + ? (int128(71) / int128(885)) + : (-int128(596)) + )); + } + + function fmMG$apfQ14W86hu_3M( + bool assert_out2 + ) internal virtual returns (bool) { + return assert_out2; + } + + function check_entrypoint( + bool /*assert_in0*/, + bool assert_in1, + bool assert_in2, + bool /*assert_in3*/ + ) public { + unchecked { + bool assert_out1 = (tZhBDeXU4NnUR6(assert_in1) < + QtdPeAwoi7LD(assert_in1, assert_in2)); + bool assert_out2 = (((( + false + ? (int128(638) - int128(932)) + : (((( + (!(!assert_in1)) + ? int128(923) + : ((int128(392) + (int128(0) & int128(82))) & + ((int128(0) + int128(392)) & int128(392))) + ) + int128(0)) - (int128(77) & int128(0))) / + (int128(1) | int128(0))) + ) / + ((int128(573) * int128(517)) / + (-(-(-(int128(0) + (-(int128(273) % int128(605))))))))) < + (( + (true && (assert_in2 || assert_in1)) + ? (((int128(478) % int128(983)) - int128(76)) + + int128(76)) + : (int128(298) + int128(316)) + ) + + ( + assert_in1 + ? (int128(73) + + ((((int128(71) - int128(94)) + int128(94)) / + int128(885)) - int128(73))) + : (-int128(596)) + ))) || + ((((int128(0) | + ( + false + ? (int128(638) - int128(932)) + : (( + (!(!(!(!assert_in1)))) + ? int128(923) + : (int128(392) & + ((int128(82) & int128(0)) + + int128(392))) + ) | int128(0)) + )) / + ((int128(573) * int128(517)) / + ((-(-(-(int128(0) - (int128(273) % int128(605)))))) + + int128(0)))) | int128(0)) < + (( + (((assert_in2 || assert_in1) && true) && true) + ? (int128(478) % int128(983)) + : (int128(298) + int128(316)) + ) + + ( + ((true && assert_in1) && assert_in1) + ? (((int128(71) - int128(94)) + int128(94)) / + int128(885)) + : (-int128(596)) + )))); + assert((assert_out1 == fmMG$apfQ14W86hu_3M(assert_out2))); + } + } +} diff --git a/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/output b/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/output new file mode 100644 index 000000000..38be40752 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/output @@ -0,0 +1,4 @@ + +======= input.sol:PlaceholderContract ======= +Binary: + diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/invalid_match.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/invalid_match.yul new file mode 100644 index 000000000..28beb0383 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/invalid_match.yul @@ -0,0 +1,34 @@ +// regression test for https://github.com/ethereum/solidity/issues/16155 +{ + function identity(value) -> ret { ret := value } + + function f() -> ret + { + let id1 := identity(0x01) + let x := 0x05 + { + let const_six := 0x06 + let id2 := identity(0x01) + x := or(0x06, id2) + } + // check that we don't substitute `or(const_six, id2)` for `x` + ret := or(id1, x) + } + + mstore(42, f()) +} +// ---- +// step: expressionSimplifier +// +// { +// { mstore(42, f()) } +// function identity(value) -> ret +// { ret := value } +// function f() -> ret_1 +// { +// let id1 := identity(0x01) +// let x := 0x05 +// { x := or(0x06, id1) } +// ret_1 := or(id1, x) +// } +// } From 7e48f204c932465a254b837c83f2fd68c393131d Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 18 Aug 2025 15:59:40 +0200 Subject: [PATCH 0931/1340] Pin hardhat to last 2.x.x version (cherry picked from commit 9697efebffc0b091606f484b8a6104b543fcb658) --- test/externalTests/gp2.sh | 3 ++- test/externalTests/pool-together.sh | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/externalTests/gp2.sh b/test/externalTests/gp2.sh index d648de592..e0f694365 100755 --- a/test/externalTests/gp2.sh +++ b/test/externalTests/gp2.sh @@ -66,7 +66,8 @@ function gp2_test force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" force_hardhat_unlimited_contract_size "$config_file" "$config_var" yarn - yarn add hardhat + # Hardhat 3.0+ breaks the test suite + yarn add hardhat@2.26.3 # Ignore bench directory which fails to compile with current hardhat and ethers versions. # bench/trace/gas.ts:123:19 - error TS2339: Property 'equals' does not exist on type 'Uint8Array'. diff --git a/test/externalTests/pool-together.sh b/test/externalTests/pool-together.sh index 2eb47912c..4f1c68814 100755 --- a/test/externalTests/pool-together.sh +++ b/test/externalTests/pool-together.sh @@ -66,7 +66,8 @@ function pool_together_test force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" yarn install - yarn add hardhat + # Hardhat 3.0+ breaks the test suite + yarn add hardhat@2.26.3 # These come with already compiled artifacts. We want them recompiled with latest compiler. rm -r node_modules/@pooltogether/yield-source-interface/artifacts/ From 539416a155f907a837826706d7a5c3f95892b32c Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 14 Aug 2025 14:24:07 +0200 Subject: [PATCH 0932/1340] Bump node image to lts for pool together and gp2 --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ed4a29b6d..544b6161c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -823,14 +823,14 @@ defaults: # NOTE: test suite disabled due to dependence on a specific version of Hardhat # which does not support shanghai EVM. compile_only: 1 - image: cimg/node:20.19 + image: cimg/node:lts - job_native_test_ext_uniswap: &job_native_test_ext_uniswap <<: *requires_b_ubu_static name: t_native_test_ext_uniswap project: uniswap binary_type: native - image: cimg/node:18.16 + image: cimg/node:lts resource_class: medium # Tests run out of memory on a smaller machine - job_native_test_ext_prb_math: &job_native_test_ext_prb_math @@ -848,7 +848,7 @@ defaults: name: t_native_test_ext_elementfi project: elementfi binary_type: native - image: cimg/node:18.16 + image: cimg/node:lts resource_class: medium - job_native_test_ext_brink: &job_native_test_ext_brink @@ -856,7 +856,7 @@ defaults: name: t_native_test_ext_brink project: brink binary_type: native - image: cimg/node:18.16 + image: cimg/node:lts - job_native_compile_ext_chainlink: &job_native_compile_ext_chainlink <<: *requires_b_ubu_static @@ -876,7 +876,7 @@ defaults: binary_type: native # NOTE: test suite disabled due to constant failures. compile_only: 1 - image: cimg/node:20.19 + image: cimg/node:lts - job_b_ubu_asan_clang: &job_b_ubu_asan_clang <<: *on_all_tags_and_branches From db18d42bdeccf305695e477c74fc2a4141493c5e Mon Sep 17 00:00:00 2001 From: Michael Cho Date: Tue, 12 Aug 2025 18:55:45 -0400 Subject: [PATCH 0933/1340] Fix build with Boost 1.89.0 Boost.System has been header-only since Boost 1.69 and will be dropping the compatibility stub library in Boost 1.89 (boostorg/system@7a495bb). Since the `system` component is only needed for Boost < 1.69, it can be added to `BOOST_COMPONENTS` in the fallback find_package. Signed-off-by: Michael Cho --- cmake/EthDependencies.cmake | 3 ++- libsolutil/CMakeLists.txt | 2 +- test/tools/CMakeLists.txt | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index f79140dd2..c2a8179b5 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -29,7 +29,7 @@ if (WIN32) option(Boost_USE_STATIC_RUNTIME "Link Boost against static C++ runtime libraries" ON) endif() -set(BOOST_COMPONENTS "filesystem;unit_test_framework;program_options;system") +set(BOOST_COMPONENTS "filesystem;unit_test_framework;program_options") # CMake >= 3.30 should not use the vendored boost if(POLICY CMP0167) @@ -50,6 +50,7 @@ else() if(POLICY CMP0167) cmake_policy(SET CMP0167 OLD) endif() + list(APPEND BOOST_COMPONENTS system) find_package(Boost 1.67.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) endif() endif() diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index 1ec12051a..01749c02b 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -47,7 +47,7 @@ set(sources ) add_library(solutil ${sources}) -target_link_libraries(solutil PUBLIC Boost::boost Boost::filesystem Boost::system range-v3 fmt::fmt-header-only nlohmann_json::nlohmann_json) +target_link_libraries(solutil PUBLIC Boost::boost Boost::filesystem ${Boost_SYSTEM_LIBRARY} range-v3 fmt::fmt-header-only nlohmann_json::nlohmann_json) target_include_directories(solutil PUBLIC "${PROJECT_SOURCE_DIR}") add_dependencies(solutil solidity_BuildInfo.h) diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 289f2f2de..31bdf34ee 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -5,10 +5,10 @@ add_executable(yulrun yulrun.cpp) target_link_libraries(yulrun PRIVATE yulInterpreter libsolc evmasm Boost::boost Boost::program_options) add_executable(solfuzzer afl_fuzzer.cpp fuzzer_common.cpp) -target_link_libraries(solfuzzer PRIVATE libsolc evmasm Boost::boost Boost::program_options Boost::system) +target_link_libraries(solfuzzer PRIVATE libsolc evmasm Boost::boost Boost::program_options ${Boost_SYSTEM_LIBRARY}) add_executable(yulopti yulopti.cpp) -target_link_libraries(yulopti PRIVATE solidity Boost::boost Boost::program_options Boost::system) +target_link_libraries(yulopti PRIVATE solidity Boost::boost Boost::program_options ${Boost_SYSTEM_LIBRARY}) add_executable(isoltest isoltest.cpp From a6a6081ba93bf3e0b8a3ad07839f4bba9bf2a68f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 15 Aug 2025 10:53:37 +0200 Subject: [PATCH 0934/1340] update to boost 1.70.0 for non-windows builds --- Changelog.md | 3 +++ cmake/EthDependencies.cmake | 12 ++---------- docs/installing-solidity.rst | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Changelog.md b/Changelog.md index 63ed87ffb..df45a558f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,9 @@ Bugfixes: * Assembler: Fix not using a fixed-width type for IDs being assigned to subassemblies nested more than one level away, resulting in inconsistent `--asm-json` output between target architectures. * Yul Optimizer: Fix edge case in which invalid Yul code is produced by ExpressionSimplifier due to expressions being substituted that contain out-of-scope variables. +Build System: +* Update to boost 1.70.0 for non-windows builds. + ### 0.8.30 (2025-05-07) Compiler Features: diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index c2a8179b5..453c6d14c 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -42,17 +42,9 @@ if (WIN32) else() # Boost 1.65 is the first to also provide boost::get for rvalue-references (#5787). # Boost 1.67 moved container_hash into is own module. + # Boost 1.69 boost::system is header-only and no longer needs to be fetched as component # Boost 1.70 comes with its own BoostConfig.cmake and is the new (non-deprecated) behavior - find_package(Boost 1.70.0 QUIET COMPONENTS ${BOOST_COMPONENTS}) - if (NOT ${Boost_FOUND}) - # If the boost version is < 1.70.0, there is no boost config delivered with it, revert to old behavior - # todo drop this once cmake minimum version >= 3.30 is reached - if(POLICY CMP0167) - cmake_policy(SET CMP0167 OLD) - endif() - list(APPEND BOOST_COMPONENTS system) - find_package(Boost 1.67.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) - endif() + find_package(Boost 1.70.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) endif() # If cmake is older than boost and boost is older than 1.70, diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 07d82b9c8..14c0be34a 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -327,7 +327,7 @@ The following are dependencies for all builds of Solidity: | Windows, 3.13+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ | `Boost`_ (version 1.77+ on | C++ libraries. | -| Windows, 1.67+ otherwise) | | +| Windows, 1.70+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ | `Git`_ | Command-line tool for retrieving source code. | +-----------------------------------+-------------------------------------------------------+ From 6b7413c743c31a297c5ac546eb55b0907d8187ed Mon Sep 17 00:00:00 2001 From: Fibonacci747 Date: Mon, 25 Aug 2025 08:58:19 +0200 Subject: [PATCH 0935/1340] fix: correct fromHex function documentation --- libsolutil/CommonData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index ee3a6eb95..74fe792c2 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -453,7 +453,7 @@ int fromHex(char _i, WhenError _throw); /// Converts a (printable) ASCII hex string into the corresponding byte stream. /// @example fromHex("41626261") == asBytes("Abba") -/// If _throw = ThrowType::DontThrow, it replaces bad hex characters with 0's, otherwise it will throw an exception. +/// If _throw = WhenError::DontThrow, it returns an empty bytes array on any validation error, otherwise it will throw an exception. bytes fromHex(std::string const& _s, WhenError _throw = WhenError::DontThrow); /// Converts byte array to a string containing the same (binary) data. Unless /// the byte array happens to contain ASCII data, this won't be printable. From 01a821f8b902c3c57cea34ae80420c734bc210bf Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 27 Aug 2025 11:32:51 +0200 Subject: [PATCH 0936/1340] ci: filter for python files when verifying optimization rule formal proofs --- scripts/run_proofs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run_proofs.sh b/scripts/run_proofs.sh index db6b0e02b..e23603e64 100755 --- a/scripts/run_proofs.sh +++ b/scripts/run_proofs.sh @@ -10,7 +10,7 @@ git fetch origin error=0 for new_proof in $(git diff origin/develop --name-only test/formal/) do - if [ -e "$new_proof" ]; then + if [[ -e "$new_proof" ]] && [[ "$new_proof" == *.py ]]; then set +e echo "Proving $new_proof..." output=$(python3 "$new_proof") From 4dbfe8ea65efcfc64c7a261a530dbd279f769878 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 27 Aug 2025 11:21:44 +0200 Subject: [PATCH 0937/1340] docs: update links to argotorg and ipsilon where appropriate --- .circleci/config.yml | 10 +++++----- .circleci/osx_install_dependencies.sh | 2 +- .circleci/parallel_bytecode_report.sh | 2 +- .github/workflows/welcome-external-pr.yml | 2 +- CODING_STYLE.md | 2 +- README.md | 2 +- ReleaseChecklist.md | 16 +++++++-------- SECURITY.md | 2 +- docs/050-breaking-changes.rst | 2 +- docs/060-breaking-changes.rst | 2 +- docs/070-breaking-changes.rst | 2 +- docs/080-breaking-changes.rst | 2 +- docs/bugs.rst | 4 ++-- docs/contributing.rst | 20 +++++++++---------- docs/index.rst | 2 +- docs/installing-solidity.rst | 18 ++++++++--------- docs/internals/optimizer.rst | 2 +- docs/layout-of-source-files.rst | 2 +- docs/path-resolution.rst | 4 ++-- docs/resources.rst | 4 ++-- docs/smtchecker.rst | 2 +- .../experimental/analysis/Analysis.cpp | 2 +- libsolidity/interface/ImportRemapper.h | 2 +- libsolidity/interface/Natspec.h | 2 +- .../Dockerfile.ubuntu.clang.ossfuzz | 2 +- .../buildpack-deps/Dockerfile.ubuntu2204 | 2 +- .../buildpack-deps/Dockerfile.ubuntu2404 | 2 +- .../Dockerfile.ubuntu2404.clang | 2 +- scripts/docker_deploy_manual.sh | 2 +- scripts/docs_version_pragma_check.sh | 2 +- scripts/download_ossfuzz_corpus.sh | 2 +- scripts/externalTests/common.sh | 2 +- scripts/install_evmone.ps1 | 2 +- scripts/release_ppa.sh | 8 ++++---- .../bytecode_reports_for_modified_binaries.sh | 2 +- .../docker-scripts/rebuild_tags.sh | 4 ++-- test/Common.h | 6 +++--- test/buglistTests.js | 2 +- .../input.sol | 2 +- .../test.py | 2 +- .../~deduplicator-verbatim-bug/test.sh | 2 +- .../~name_dependent_cse_bug/test.sh | 2 +- test/evmc/README.md | 8 ++++---- test/evmc/evmc.h | 2 +- test/externalTests/euler.sh | 2 +- test/externalTests/gp2.sh | 2 +- test/formal/README.md | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 2 +- test/libsolidity/SolidityOptimizer.cpp | 2 +- test/libsolidity/StandardCompiler.cpp | 6 +++--- ..._1d_array_into_2d_memory_array_element.sol | 2 +- .../asm_address_constant_regression.sol | 2 +- .../structs/copy_from_storage.sol | 2 +- .../array/copy_from_function_type.sol | 2 +- ...recursive_struct_nested_mapping_memory.sol | 2 +- .../expressionSimplifier/invalid_match.yul | 2 +- .../yulOptimizerTests/fullSuite/aztec.yul | 2 +- .../loadResolver/keccak_crash.yul | 2 +- .../tools/ossfuzz/StackReuseCodegenFuzzer.cpp | 2 +- test/tools/ossfuzz/abiV2Proto.proto | 2 +- tools/yulPhaser/README.md | 2 +- 61 files changed, 103 insertions(+), 103 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 544b6161c..d206beb69 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -745,7 +745,7 @@ defaults: # Parameterized Job Templates # Separate compile-only runs of those external tests where a full run takes much longer. - # Also see https://github.com/ethereum/solidity/pull/14234 for why we excluded those + # Also see https://github.com/argotorg/solidity/pull/14234 for why we excluded those # external tests from the nightly jobs. - job_ems_compile_ext_colony: &job_ems_compile_ext_colony <<: *requires_b_ems @@ -1083,7 +1083,7 @@ jobs: b_ubu_static: # We temporarily keep building static release binaries on ubuntu 20.04 # to avoid glibc incompatibilities. - # See: https://github.com/ethereum/solidity/issues/13954 + # See: https://github.com/argotorg/solidity/issues/13954 # On large runs 2x faster than on medium. 3x on xlarge. <<: *base_ubuntu2404_xlarge environment: @@ -1140,7 +1140,7 @@ jobs: - run: name: Regression tests command: | - git clone https://github.com/ethereum/solidity-fuzzing-corpus /tmp/solidity-fuzzing-corpus + git clone https://github.com/argotorg/solidity-fuzzing-corpus /tmp/solidity-fuzzing-corpus mkdir -p test_results scripts/regressions.py -o test_results - store_test_results: @@ -1333,7 +1333,7 @@ jobs: <<: *base_ubuntu2404_env ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 # Suppress CLN memory leak. - # See: https://github.com/ethereum/solidity/issues/13891 for details. + # See: https://github.com/argotorg/solidity/issues/13891 for details. LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp:print_suppressions=0 steps: - cmdline_tests @@ -1349,7 +1349,7 @@ jobs: SOLTEST_FLAGS: --no-smt ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 # Suppress CLN memory leak. - # See: https://github.com/ethereum/solidity/issues/13891 for details. + # See: https://github.com/argotorg/solidity/issues/13891 for details. LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp steps: - soltest diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index 3ac380e36..f47e08210 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -112,7 +112,7 @@ then # evmone evmone_version="0.13.0" evmone_package="evmone-${evmone_version}-darwin-arm64.tar.gz" - wget "https://github.com/ethereum/evmone/releases/download/v${evmone_version}/${evmone_package}" + wget "https://github.com/ipsilon/evmone/releases/download/v${evmone_version}/${evmone_package}" validate_checksum "$evmone_package" 49fe6cc35e0e13c48ca2f29a6b85a47f7b25dcd427e14254000d3bc29cddf2a6 sudo tar xzpf "$evmone_package" -C /usr/local rm "$evmone_package" diff --git a/.circleci/parallel_bytecode_report.sh b/.circleci/parallel_bytecode_report.sh index ee9dfde9f..0cb5b7f9b 100755 --- a/.circleci/parallel_bytecode_report.sh +++ b/.circleci/parallel_bytecode_report.sh @@ -57,7 +57,7 @@ if [[ $binary_type == native || $binary_type == "osx_intel" ]]; then --report-file "../bytecode-report-${label}-${interface}-${preset}.txt" else echo "Installing solc-js" - git clone --depth 1 https://github.com/ethereum/solc-js.git solc-js + git clone --depth 1 https://github.com/argotorg/solc-js.git solc-js cp "$binary_path" solc-js/soljson.js cd solc-js/ diff --git a/.github/workflows/welcome-external-pr.yml b/.github/workflows/welcome-external-pr.yml index ac8d1362e..b795a36b0 100644 --- a/.github/workflows/welcome-external-pr.yml +++ b/.github/workflows/welcome-external-pr.yml @@ -27,7 +27,7 @@ jobs: "Thank you for your contribution to the Solidity compiler! A team member will follow up shortly." "\n\n" "If you haven't read our [contributing guidelines](https://docs.soliditylang.org/en/latest/contributing.html) and our " - "[review checklist](https://github.com/ethereum/solidity/blob/develop/ReviewChecklist.md) before, " + "[review checklist](https://github.com/argotorg/solidity/blob/develop/ReviewChecklist.md) before, " "please do it now, this makes the reviewing process and accepting your contribution smoother." "\n\n" "If you have any questions or need our help, feel free to post them in the PR or talk to us directly on the " diff --git a/CODING_STYLE.md b/CODING_STYLE.md index b70126d91..0ff6e1b35 100644 --- a/CODING_STYLE.md +++ b/CODING_STYLE.md @@ -46,7 +46,7 @@ foo->bar(someLongVariableName, cout << "some very long string that contains completely irrelevant text that talks about this and that and contains the words \"lorem\" and \"ipsum\"" << endl; ``` -To set indentation and tab width settings uniformly, the repository contains an [EditorConfig](https://editorconfig.org/) [`.editorconfig`](https://github.com/ethereum/solidity/blob/develop/.editorconfig) file, which describes some of the styles used and which is recognized by many IDE's and editors. +To set indentation and tab width settings uniformly, the repository contains an [EditorConfig](https://editorconfig.org/) [`.editorconfig`](https://github.com/argotorg/solidity/blob/develop/.editorconfig) file, which describes some of the styles used and which is recognized by many IDE's and editors. ## 1. Namespaces diff --git a/README.md b/README.md index 2d8e02322..884aca484 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Please follow the if you want to help. You can find our current feature and bug priorities for forthcoming -releases in the [projects section](https://github.com/ethereum/solidity/projects). +releases in the [projects section](https://github.com/argotorg/solidity/projects). ## Maintainers The Solidity programming language and compiler are open-source community projects governed by a core team. diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index acaabca63..f0148cd0e 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -1,8 +1,8 @@ ## Checklist for making a release: ### Requirements -- [ ] GitHub account with access to [solidity](https://github.com/ethereum/solidity), [solc-js](https://github.com/ethereum/solc-js), - [solc-bin](https://github.com/ethereum/solc-bin), [solidity-website](https://github.com/ethereum/solidity-website). +- [ ] GitHub account with access to [solidity](https://github.com/argotorg/solidity), [solc-js](https://github.com/argotorg/solc-js), + [solc-bin](https://github.com/argotorg/solc-bin), [solidity-website](https://github.com/argotorg/solidity-website). - [ ] DockerHub account with push rights to the [`solc` image](https://hub.docker.com/r/ethereum/solc). - [ ] Launchpad (Ubuntu One) account with a membership in the ["Ethereum" team](https://launchpad.net/~ethereum) and a gnupg key for your email in the `ethereum.org` domain (has to be version 1, gpg2 won't work). @@ -39,8 +39,8 @@ At least a day before the release: - [ ] Prepare drafts of Twitter, Reddit and Solidity Forum announcements. ### Blog Post -- [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the `Releases` category and explain some of the new features or concepts. -- [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the `Security Alerts` category in case of important bug(s). +- [ ] Create a post on [solidity-website](https://github.com/argotorg/solidity-website/tree/main/src/posts) in the `Releases` category and explain some of the new features or concepts. +- [ ] Create a post on [solidity-website](https://github.com/argotorg/solidity-website/tree/main/src/posts) in the `Security Alerts` category in case of important bug(s). - [ ] Get the posts reviewed and approved **before the release starts**. ### Changelog @@ -52,7 +52,7 @@ At least a day before the release: - [ ] Copy the changelog into the release blog post. ### Create the Release -- [ ] Create a [release on GitHub](https://github.com/ethereum/solidity/releases/new). +- [ ] Create a [release on GitHub](https://github.com/argotorg/solidity/releases/new). Set the target to the `develop` branch and the tag to the new version, e.g. `v0.8.5`. Include the following warning: `**The release is still in progress. You may see broken links and binaries may not yet be available from all sources.**`. Do not publish it yet - click the `Save draft` button instead. @@ -108,10 +108,10 @@ At least a day before the release: ### Post-release - [ ] Make sure the documentation for the new release has been published successfully. Go to the [documentation status page at ReadTheDocs](https://readthedocs.org/projects/solidity/) and verify that the new version is listed, works and is marked as default. -- [ ] Remove "still in progress" warning from the [release notes](https://github.com/ethereum/solidity/releases). -- [ ] Merge the [blog posts](https://github.com/ethereum/solidity-website/pulls) related to the release. +- [ ] Remove "still in progress" warning from the [release notes](https://github.com/argotorg/solidity/releases). +- [ ] Merge the [blog posts](https://github.com/argotorg/solidity-website/pulls) related to the release. - [ ] Create a commit to increase the version number on `develop` in `CMakeLists.txt` and add a new skeleton changelog entry. -- [ ] Update the release information section [in the source of soliditylang.org](https://github.com/ethereum/solidity-website/blob/main/src/pages/index.tsx). +- [ ] Update the release information section [in the source of soliditylang.org](https://github.com/argotorg/solidity-website/blob/main/src/pages/index.tsx). - [ ] Announce on [Twitter](https://twitter.com/solidity_lang), including links to the release and the blog post. - [ ] Announce on [Fosstodon](https://fosstodon.org/@solidity/), including links to the release and the blog post. - [ ] Share the announcement on Reddit in [`/r/ethdev`](https://reddit.com/r/ethdev/), cross-posted to [`/r/ethereum`](https://reddit.com/r/ethereum/). diff --git a/SECURITY.md b/SECURITY.md index d319b332f..8cb2b0eb8 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -49,4 +49,4 @@ The Solidity team maintains the following JSON-formatted lists of patched securi [1]: https://bounty.ethereum.org/ [2]: https://bounty.ethereum.org/#rules [3]: https://docs.soliditylang.org/en/develop/bugs.html -[4]: https://github.com/ethereum/solidity/blob/develop/docs/bugs_by_version.json +[4]: https://github.com/argotorg/solidity/blob/develop/docs/bugs_by_version.json diff --git a/docs/050-breaking-changes.rst b/docs/050-breaking-changes.rst index a40bbcf6e..19f05adff 100644 --- a/docs/050-breaking-changes.rst +++ b/docs/050-breaking-changes.rst @@ -6,7 +6,7 @@ This section highlights the main breaking changes introduced in Solidity version 0.5.0, along with the reasoning behind the changes and how to update affected code. For the full list check -`the release changelog `_. +`the release changelog `_. .. note:: Contracts compiled with Solidity v0.5.0 can still interface with contracts diff --git a/docs/060-breaking-changes.rst b/docs/060-breaking-changes.rst index e7c93057f..c2a6ceb1e 100644 --- a/docs/060-breaking-changes.rst +++ b/docs/060-breaking-changes.rst @@ -6,7 +6,7 @@ This section highlights the main breaking changes introduced in Solidity version 0.6.0, along with the reasoning behind the changes and how to update affected code. For the full list check -`the release changelog `_. +`the release changelog `_. Changes the Compiler Might not Warn About diff --git a/docs/070-breaking-changes.rst b/docs/070-breaking-changes.rst index 05e98a4dc..a966b547a 100644 --- a/docs/070-breaking-changes.rst +++ b/docs/070-breaking-changes.rst @@ -6,7 +6,7 @@ This section highlights the main breaking changes introduced in Solidity version 0.7.0, along with the reasoning behind the changes and how to update affected code. For the full list check -`the release changelog `_. +`the release changelog `_. Silent Changes of the Semantics diff --git a/docs/080-breaking-changes.rst b/docs/080-breaking-changes.rst index 9d1f3347b..91712b33f 100644 --- a/docs/080-breaking-changes.rst +++ b/docs/080-breaking-changes.rst @@ -5,7 +5,7 @@ Solidity v0.8.0 Breaking Changes This section highlights the main breaking changes introduced in Solidity version 0.8.0. For the full list check -`the release changelog `_. +`the release changelog `_. Silent Changes of the Semantics =============================== diff --git a/docs/bugs.rst b/docs/bugs.rst index f7f18e9a7..0cb3cdb54 100644 --- a/docs/bugs.rst +++ b/docs/bugs.rst @@ -8,12 +8,12 @@ List of Known Bugs Below, you can find a JSON-formatted list of some of the known security-relevant bugs in the Solidity compiler. The file itself is hosted in the `GitHub repository -`_. +`_. The list stretches back as far as version 0.3.0, bugs known to be present only in versions preceding that are not listed. There is another file called `bugs_by_version.json -`_, +`_, which can be used to check which bugs affect a specific version of the compiler. Contract source verification tools and also other tools interacting with diff --git a/docs/contributing.rst b/docs/contributing.rst index 2d5faa550..6bf89cc92 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -8,8 +8,8 @@ In particular, we appreciate support in the following areas: * Reporting issues. * Fixing and responding to `Solidity's GitHub issues - `_, especially those tagged as - `"good first issue" `_ which are + `_, especially those tagged as + `"good first issue" `_ which are meant as introductory issues for external contributors. * Improving the documentation. * `Translating `_ the documentation into more languages. @@ -38,7 +38,7 @@ How to Report Issues ==================== To report an issue, please use the -`GitHub issues tracker `_. When +`GitHub issues tracker `_. When reporting issues, please mention the following details: * Solidity version. @@ -76,11 +76,11 @@ New features and bugfixes should be added to the ``Changelog.md`` file: please follow the style of previous entries, when applicable. Finally, please make sure you respect the `coding style -`_ +`_ for this project. Also, even though we do CI testing, please test your code and ensure that it builds locally before submitting a pull request. -We highly recommend going through our `review checklist `_ before submitting the pull request. +We highly recommend going through our `review checklist `_ before submitting the pull request. We thoroughly review every PR and will help you get it right, but there are many common problems that can be easily avoided, making the review much smoother. Thank you for your help! @@ -92,7 +92,7 @@ Prerequisites ------------- For running all compiler tests you may want to optionally install a few -dependencies (`evmone `_, +dependencies (`evmone `_, `z3 `_, `Eldarica `_, `cvc5 `). @@ -119,7 +119,7 @@ application ``soltest`` (or its wrapper ``scripts/soltest.sh``), as well as comm compilation tests. The test system automatically tries to discover the location of -the `evmone `_ for running the semantic tests. +the `evmone `_ for running the semantic tests. The ``evmone`` library must be located in the ``deps`` or ``deps/lib`` directory relative to the current working directory, to its parent or its parent's parent. Alternatively, an explicit location @@ -277,7 +277,7 @@ Command-line Tests Our suite of end-to-end command-line tests checks the behaviour of the compiler binary as a whole in various scenarios. -These tests are located in `test/cmdlineTests/ `_, +These tests are located in `test/cmdlineTests/ `_, one per subdirectory, and can be executed using the ``cmdlineTests.sh`` script. By default the script runs all available tests. @@ -547,7 +547,7 @@ The Solidity forum serves as the place to propose and discuss new language featu the early stages of ideation or modifications of existing features. As soon as proposals get more tangible, their -implementation will also be discussed in the `Solidity GitHub repository `_ +implementation will also be discussed in the `Solidity GitHub repository `_ in the form of issues. In addition to the forum and issue discussions, we regularly host language design discussion calls in which selected @@ -557,7 +557,7 @@ We are also sharing feedback surveys and other content that is relevant to langu If you want to know where the team is standing in terms of implementing new features, you can follow the implementation status in the `Solidity GitHub project `_. Issues in the design backlog need further specification and will either be discussed in a language design call or in a regular team call. You can -see the upcoming changes for the next breaking release by changing from the default branch (`develop`) to the `breaking branch `_. +see the upcoming changes for the next breaking release by changing from the default branch (`develop`) to the `breaking branch `_. For ad-hoc cases and questions, you can reach out to us via the `Solidity-dev Gitter channel `_ — a dedicated chatroom for conversations around the Solidity compiler and language development. diff --git a/docs/index.rst b/docs/index.rst index 73295404d..77d06cd6b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -14,7 +14,7 @@ With Solidity, you can create contracts for uses such as voting, crowdfunding, b When deploying contracts, you should use the latest released version of Solidity. Apart from exceptional cases, only the latest version receives -`security fixes `_. +`security fixes `_. Furthermore, breaking changes, as well as new features, are introduced regularly. We currently use a 0.y.z version number `to indicate this fast pace of change `_. diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 14c0be34a..6f085539b 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -33,7 +33,7 @@ Remix `Access Remix online `_, you do not need to install anything. If you want to use it without connection to the Internet, go to -https://github.com/ethereum/remix-live/tree/gh-pages#readme and follow the instructions on that page. +https://github.com/argotorg/remix-live/tree/gh-pages#readme and follow the instructions on that page. Remix is also a convenient option for testing nightly builds without installing multiple Solidity versions. @@ -51,7 +51,7 @@ Use ``npm`` for a convenient and portable way to install ``solcjs``, a Solidity further down this page. The :ref:`commandline-compiler` documentation assumes you are using the full-featured compiler, ``solc``. The usage of ``solcjs`` is documented inside its own -`repository `_. +`repository `_. Note: The solc-js project is derived from the C++ ``solc`` by using Emscripten, which means that both use the same compiler source code. @@ -115,7 +115,7 @@ Linux Packages ============== Binary packages of Solidity are available at -`solidity/releases `_. +`solidity/releases `_. We also have PPAs for Ubuntu, you can get the latest stable version using the following commands: @@ -256,7 +256,7 @@ Each one includes a ``list.json`` file listing the available binaries. For examp This means that: - You can find the binary in the same directory under the name - `solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js `_. + `solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js `_. Note that the file might be a symlink, and you will need to resolve it yourself if you are not using git to download it or your file system does not support symlinks. - The binary is also mirrored at https://binaries.soliditylang.org/emscripten-wasm32/solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js. @@ -304,8 +304,8 @@ This means that: in the long-term. .. _IPFS: https://ipfs.io -.. _solc-bin: https://github.com/ethereum/solc-bin/ -.. _Solidity release page on GitHub: https://github.com/ethereum/solidity/releases +.. _solc-bin: https://github.com/argotorg/solc-bin/ +.. _Solidity release page on GitHub: https://github.com/argotorg/solidity/releases .. _sha3sum: https://github.com/maandree/sha3sum .. _keccak256() function from ethereumjs-util: https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/modules/_hash_.md#const-keccak256 .. _WebAssembly builds: https://emscripten.org/docs/compiling/WebAssembly.html @@ -365,7 +365,7 @@ The following are dependencies for all builds of Solidity: Doing this is not recommended for general use but may be necessary when using a toolchain we are not testing with or trying to build an older version with newer tools. If you encounter such warnings, please consider - `reporting them `_. + `reporting them `_. Minimum Compiler Versions ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -447,7 +447,7 @@ To clone the source code, execute the following command: .. code-block:: bash - git clone --recursive https://github.com/ethereum/solidity.git + git clone --recursive https://github.com/argotorg/solidity.git cd solidity If you want to help develop Solidity, @@ -463,7 +463,7 @@ you should fork Solidity and add your personal fork as a second remote: If you want to re-build a released Solidity compiler, then please use the source tarball on the GitHub release page: - https://github.com/ethereum/solidity/releases/download/v0.X.Y/solidity_0.X.Y.tar.gz + https://github.com/argotorg/solidity/releases/download/v0.X.Y/solidity_0.X.Y.tar.gz (not the "Source code" provided by GitHub). diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index 4d02d3e18..8c737371c 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -11,7 +11,7 @@ The Solidity compiler involves optimizations at three different levels (in order - Optimizing transformations on the Yul IR code. - Optimizations at the opcode level. -The opcode-based optimizer applies a set of `simplification rules `_ +The opcode-based optimizer applies a set of `simplification rules `_ to opcodes. It also combines equal code sets and removes unused code. The Yul-based optimizer is much more powerful, because it can work across function diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index 600f2ed0f..e51b3ad98 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -159,7 +159,7 @@ The :ref:`build instructions` explain how to activate this op It is activated for the Ubuntu PPA releases in most versions, but not for the Docker images, Windows binaries or the statically-built Linux binaries. It can be activated for solc-js via the -`smtCallback `_ if you have an SMT solver +`smtCallback `_ if you have an SMT solver installed locally and run solc-js via node (not via the browser). If you use ``pragma experimental SMTChecker;``, then you get additional diff --git a/docs/path-resolution.rst b/docs/path-resolution.rst index ff4930bc9..492959bc1 100644 --- a/docs/path-resolution.rst +++ b/docs/path-resolution.rst @@ -39,7 +39,7 @@ compilation fails. By default, the command-line compiler provides the *Host Filesystem Loader* - a rudimentary callback that interprets a source unit name as a path in the local filesystem. This callback can be disabled using the ``--no-import-callback`` command-line option. -The `JavaScript interface `_ does not provide any by default, +The `JavaScript interface `_ does not provide any by default, but one can be provided by the user. This mechanism can be used to obtain source code from locations other than the local filesystem (which may not even be accessible, e.g. when the compiler is running in a browser). @@ -83,7 +83,7 @@ The initial content of the VFS depends on how you invoke the compiler: #. **Standard JSON** When using the :ref:`Standard JSON ` API (via either the `JavaScript interface - `_ or the ``--standard-json`` command-line option) + `_ or the ``--standard-json`` command-line option) you provide input in JSON format, containing, among other things, the content of all your source files: diff --git a/docs/resources.rst b/docs/resources.rst index 43161f7d0..3ba0620f9 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -8,8 +8,8 @@ General Resources * `Ethereum.org Developers page `_ * `Ethereum StackExchange `_ * `Solidity website `_ -* `Solidity changelog `_ -* `Solidity codebase on GitHub `_ +* `Solidity changelog `_ +* `Solidity codebase on GitHub `_ * `Solidity language users chat `_ * `Solidity compiler developers chat `_ * `awesome-solidity `_ diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index 5de941bf2..69b620dbc 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -828,7 +828,7 @@ option ``--model-checker-solvers {all,cvc5,eld,smtlib2,z3}`` or the JSON option - ``cvc5`` is used via its binary which must be installed in the system. Only BMC uses ``cvc5``. - ``eld`` is used via its binary which must be installed in the system. Only CHC uses ``eld``, and only if ``z3`` is not enabled. - ``smtlib2`` outputs SMT/Horn queries in the `smtlib2 `_ format. - These can be used together with the compiler's `callback mechanism `_ so that + These can be used together with the compiler's `callback mechanism `_ so that any solver binary from the system can be employed to synchronously return the results of the queries to the compiler. This can be used by both BMC and CHC depending on which solvers are called. - ``z3`` is available statically in ``soljson.js`` (from Solidity 0.6.9), that is, the JavaScript binary of the compiler. Otherwise it is used via its binary which must be installed in the system. diff --git a/libsolidity/experimental/analysis/Analysis.cpp b/libsolidity/experimental/analysis/Analysis.cpp index 441700675..fa14d37ab 100644 --- a/libsolidity/experimental/analysis/Analysis.cpp +++ b/libsolidity/experimental/analysis/Analysis.cpp @@ -164,7 +164,7 @@ bool Analysis::check(std::vector> const& _sour SyntaxRestrictor, TypeClassRegistration, TypeRegistration, - // TODO move after step introduced in https://github.com/ethereum/solidity/pull/14578, but before TypeInference + // TODO move after step introduced in https://github.com/argotorg/solidity/pull/14578, but before TypeInference FunctionDependencyAnalysis, TypeInference, DebugWarner diff --git a/libsolidity/interface/ImportRemapper.h b/libsolidity/interface/ImportRemapper.h index 66946d091..45166a1ec 100644 --- a/libsolidity/interface/ImportRemapper.h +++ b/libsolidity/interface/ImportRemapper.h @@ -63,7 +63,7 @@ class ImportRemapper static std::optional parseRemapping(std::string_view _input); private: - /// list of path prefix remappings, e.g. mylibrary: github.com/ethereum = /usr/local/ethereum + /// list of path prefix remappings, e.g. mylibrary: github.com/argotorg = /usr/local/argotorg /// "context:prefix=target" std::vector m_remappings = {}; }; diff --git a/libsolidity/interface/Natspec.h b/libsolidity/interface/Natspec.h index 994f1350c..11cc7b622 100644 --- a/libsolidity/interface/Natspec.h +++ b/libsolidity/interface/Natspec.h @@ -73,7 +73,7 @@ class Natspec /// of a method's return notice documentation static Json extractReturnParameterDocs(std::multimap const& _tags, std::vector const& _returnParameterNames); - /// Temporary function until https://github.com/ethereum/solidity/issues/11114 is implemented. + /// Temporary function until https://github.com/argotorg/solidity/issues/11114 is implemented. /// @return all events defined in the contract and its base contracts and all events /// that are emitted during the execution of the contract, but allowing only unique signatures. /// In case of conflict between a library event and a contract one, selects the latter diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index bf228d617..465f2de0a 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -143,7 +143,7 @@ RUN set -ex; \ # EVMONE RUN set -ex; \ cd /usr/src; \ - git clone --branch="v0.13.0" --recurse-submodules https://github.com/ethereum/evmone.git; \ + git clone --branch="v0.13.0" --recurse-submodules https://github.com/ipsilon/evmone.git; \ cd evmone; \ mkdir build; \ cd build; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index f66c1d8fd..48272ed95 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -94,7 +94,7 @@ FROM base AS libraries # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 index fc372c709..475d4e83c 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 @@ -97,7 +97,7 @@ FROM base AS libraries # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang index 91a31c263..18cf813fe 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang @@ -99,7 +99,7 @@ ENV CXX clang++ # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index 1386bcfa1..196a3b36c 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -13,7 +13,7 @@ if (( $# < 1 || $# > 3 )); then fi branch="$1" -repo_url="${2:-https://github.com/ethereum/solidity.git}" +repo_url="${2:-https://github.com/argotorg/solidity.git}" if (( $# >= 3 )); then [[ $3 == --no-push ]] || fail "Invalid flag: $3. Expected --no-push." diff --git a/scripts/docs_version_pragma_check.sh b/scripts/docs_version_pragma_check.sh index c927cfb1e..46605539f 100755 --- a/scripts/docs_version_pragma_check.sh +++ b/scripts/docs_version_pragma_check.sh @@ -181,7 +181,7 @@ SOLTMPDIR=$(mktemp -d) if [[ ! -f "$solc_bin" ]] then echo "Downloading release from github..." - if wget -q "https://github.com/ethereum/solidity/releases/download/v$version/solc-static-linux" >/dev/null + if wget -q "https://github.com/argotorg/solidity/releases/download/v$version/solc-static-linux" >/dev/null then mv solc-static-linux "$solc_bin" else diff --git a/scripts/download_ossfuzz_corpus.sh b/scripts/download_ossfuzz_corpus.sh index 92478caf6..a741934a3 100755 --- a/scripts/download_ossfuzz_corpus.sh +++ b/scripts/download_ossfuzz_corpus.sh @@ -1,4 +1,4 @@ #!/usr/bin/env sh set -e cd /tmp -git clone --depth 1 https://github.com/ethereum/solidity-fuzzing-corpus.git +git clone --depth 1 https://github.com/argotorg/solidity-fuzzing-corpus.git diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index 26f27b07b..6e435da95 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -83,7 +83,7 @@ function setup_solc printLog "Setting up solc-js..." if [[ $solcjs_dir == "" ]]; then printLog "Cloning branch ${solcjs_branch}..." - git clone --depth 1 -b "$solcjs_branch" https://github.com/ethereum/solc-js.git "$install_dir" + git clone --depth 1 -b "$solcjs_branch" https://github.com/argotorg/solc-js.git "$install_dir" else printLog "Using local solc-js from ${solcjs_dir}..." cp -ra "$solcjs_dir" solc diff --git a/scripts/install_evmone.ps1 b/scripts/install_evmone.ps1 index 53fc7b6ee..3e2a1f819 100644 --- a/scripts/install_evmone.ps1 +++ b/scripts/install_evmone.ps1 @@ -3,6 +3,6 @@ $ErrorActionPreference = "Stop" # Needed for Invoke-WebRequest to work via CI. $progressPreference = "silentlyContinue" -Invoke-WebRequest -URI "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-windows-amd64.zip" -OutFile "evmone.zip" +Invoke-WebRequest -URI "https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-windows-amd64.zip" -OutFile "evmone.zip" tar -xf evmone.zip "bin/evmone.dll" mv bin/evmone.dll deps/ diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index a8d89040f..6c1fd51db 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -105,7 +105,7 @@ fi ppafilesurl=https://launchpad.net/~ethereum/+archive/ubuntu/${pparepo}/+files # Fetch source -git clone --depth 2 --recursive https://github.com/ethereum/solidity.git -b "$branch" +git clone --depth 2 --recursive https://github.com/argotorg/solidity.git -b "$branch" mv solidity solc # Determine version @@ -152,8 +152,8 @@ Build-Depends: debhelper (>= 9.0.0), scons Standards-Version: 3.9.5 Homepage: https://ethereum.org -Vcs-Git: https://github.com/ethereum/solidity.git -Vcs-Browser: https://github.com/ethereum/solidity +Vcs-Git: https://github.com/argotorg/solidity.git +Vcs-Browser: https://github.com/argotorg/solidity Package: solc Architecture: any-amd64 @@ -201,7 +201,7 @@ EOF cat < debian/copyright Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: solc -Source: https://github.com/ethereum/solidity +Source: https://github.com/argotorg/solidity Files: * Copyright: 2014-2016 Ethereum diff --git a/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh b/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh index bd6251913..50a7f53dd 100755 --- a/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh +++ b/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh @@ -109,7 +109,7 @@ export LC_ALL=C cd "$tmp_dir" -git clone https://github.com/ethereum/solc-js.git "$solcjs_dir" +git clone https://github.com/argotorg/solc-js.git "$solcjs_dir" cd "$solcjs_dir" npm install npm run build diff --git a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh index 9ef9caaa8..b1d816ae3 100755 --- a/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh +++ b/scripts/wasm-rebuild/docker-scripts/rebuild_tags.sh @@ -24,8 +24,8 @@ while (( "$#" )); do shift done -SOLIDITY_REPO_URL="https://github.com/ethereum/solidity" -SOLC_JS_REPO_URL="https://github.com/ethereum/solc-js" +SOLIDITY_REPO_URL="https://github.com/argotorg/solidity" +SOLC_JS_REPO_URL="https://github.com/argotorg/solc-js" SOLC_JS_BRANCH=wasmRebuildTests RELEASE_URL="https://binaries.soliditylang.org/bin" RELEASE_COMMIT_LIST_URL="$RELEASE_URL/list.txt" diff --git a/test/Common.h b/test/Common.h index e331c497a..a8a0a4e83 100644 --- a/test/Common.h +++ b/test/Common.h @@ -39,13 +39,13 @@ namespace solidity::test #ifdef _WIN32 static constexpr auto evmoneFilename = "evmone.dll"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-windows-amd64.zip"; +static constexpr auto evmoneDownloadLink = "https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-windows-amd64.zip"; #elif defined(__APPLE__) static constexpr auto evmoneFilename = "libevmone.dylib"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-darwin-arm64.tar.gz"; +static constexpr auto evmoneDownloadLink = "https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-darwin-arm64.tar.gz"; #else static constexpr auto evmoneFilename = "libevmone.so"; -static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz"; +static constexpr auto evmoneDownloadLink = "https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz"; #endif struct ConfigException: public util::Exception {}; diff --git a/test/buglistTests.js b/test/buglistTests.js index f24f0cb68..2d141776c 100755 --- a/test/buglistTests.js +++ b/test/buglistTests.js @@ -76,7 +76,7 @@ async function checkJSONPath(name, buggy, fine) var jsonPath = bugsByName[name].check['ast-compact-json-path'] if (jsonPath !== undefined) { - var url = "http://github.com/ethereum/solidity/releases/download/v" + bugsByName[name].introduced + "/solc-static-linux" + var url = "https://github.com/argotorg/solidity/releases/download/v" + bugsByName[name].introduced + "/solc-static-linux" try { var tmpdir = await mktemp.createDir('XXXXX') var binary = tmpdir + "/solc-static-linux" diff --git a/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/input.sol b/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/input.sol index 72b2c8858..3a4dcef6b 100644 --- a/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/input.sol +++ b/test/cmdlineTests/yul_optimizer_steps_invalid_substitution_in_expression_simplifier/input.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0 -// reproducing https://github.com/ethereum/solidity/issues/16155 +// reproducing https://github.com/argotorg/solidity/issues/16155 pragma solidity ^0.8.19; diff --git a/test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/test.py b/test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/test.py index e15293b8e..692fa10c0 100755 --- a/test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/test.py +++ b/test/cmdlineTests/~bytecode_equivalence_with_unused_contracts/test.py @@ -35,7 +35,7 @@ def test_bytecode_equivalence(): ) ) - # Repro for https://github.com/ethereum/solidity/issues/14829 + # Repro for https://github.com/argotorg/solidity/issues/14829 save_bytecode( Path("B.bin"), solc_bin_report( diff --git a/test/cmdlineTests/~deduplicator-verbatim-bug/test.sh b/test/cmdlineTests/~deduplicator-verbatim-bug/test.sh index 19b57e8ca..98eb041e8 100755 --- a/test/cmdlineTests/~deduplicator-verbatim-bug/test.sh +++ b/test/cmdlineTests/~deduplicator-verbatim-bug/test.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -eo pipefail -# This is a regression test against https://github.com/ethereum/solidity/issues/14640 +# This is a regression test against https://github.com/argotorg/solidity/issues/14640 # The bug caused the block deduplicator to incorrectly merge two blocks which have # verbatim items surrounded by identical opcodes. Due to the bug, the contents of # the verbatim were ignored and the blocks merged into a single one. diff --git a/test/cmdlineTests/~name_dependent_cse_bug/test.sh b/test/cmdlineTests/~name_dependent_cse_bug/test.sh index 710e82b1e..898b36596 100755 --- a/test/cmdlineTests/~name_dependent_cse_bug/test.sh +++ b/test/cmdlineTests/~name_dependent_cse_bug/test.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -eo pipefail -# This is a regression test against https://github.com/ethereum/solidity/issues/14494 +# This is a regression test against https://github.com/argotorg/solidity/issues/14494 # Due to the bug, a decision about which variable to use to replace a subexpression in CSE would # depend on sorting order of variable names. A variable not being used as a replacement could lead # to it being unused in general and removed by Unused Pruner. This would show up as a difference diff --git a/test/evmc/README.md b/test/evmc/README.md index 35fb11901..c1f2f53d1 100644 --- a/test/evmc/README.md +++ b/test/evmc/README.md @@ -1,10 +1,10 @@ # EVMC -This is an import of [EVMC](https://github.com/ethereum/evmc) version [12.0.0](https://github.com/ethereum/evmc/releases/tag/v12.0.0). +This is an import of [EVMC](https://github.com/ipsilon/evmc) version [12.0.0](https://github.com/ipsilon/evmc/releases/tag/v12.0.0). Steps when upgrading: -- Copy all from [include/evmc](https://github.com/ethereum/evmc/tree/master/include/evmc) to [test/evmc](https://github.com/ethereum/solidity/tree/develop/test/evmc) +- Copy all from [include/evmc](https://github.com/ipsilon/evmc/tree/master/include/evmc) to [test/evmc](https://github.com/argotorg/solidity/tree/develop/test/evmc) - Note that you should delete (or not copy in the first place) `tooling.hpp` and `instructions.h`. -- Copy [`loader.c`](https://github.com/ethereum/evmc/blob/master/lib/loader/loader.c) to [test/evmc](https://github.com/ethereum/solidity/tree/develop/test/evmc) +- Copy [`loader.c`](https://github.com/ipsilon/evmc/blob/master/lib/loader/loader.c) to [test/evmc](https://github.com/argotorg/solidity/tree/develop/test/evmc) - `MockedAccount.storage` in `mocked_host.hpp` should be changed to a `map` from `unordered_map` as ordering is important for fuzzing. You'll also need to include ``. - See [PR #11094](https://github.com/ethereum/solidity/pull/11094) for more details. + See [PR #11094](https://github.com/argotorg/solidity/pull/11094) for more details. diff --git a/test/evmc/evmc.h b/test/evmc/evmc.h index bec847597..3bc3996c3 100644 --- a/test/evmc/evmc.h +++ b/test/evmc/evmc.h @@ -278,7 +278,7 @@ typedef evmc_bytes32 (*evmc_get_block_hash_fn)(struct evmc_host_context* context * * @note * In case new status codes are needed, please create an issue or pull request - * in the EVMC repository (https://github.com/ethereum/evmc). + * in the EVMC repository (https://github.com/ipsilon/evmc). */ enum evmc_status_code { diff --git a/test/externalTests/euler.sh b/test/externalTests/euler.sh index 9ede1a340..9ccfcd781 100755 --- a/test/externalTests/euler.sh +++ b/test/externalTests/euler.sh @@ -33,7 +33,7 @@ SELECTED_PRESETS="$3" function compile_fn { npm run compile; } function test_fn { - # The default timeout of 20000 ms is too short for unoptimized code (https://github.com/ethereum/solidity/pull/12765). + # The default timeout of 20000 ms is too short for unoptimized code (https://github.com/argotorg/solidity/pull/12765). TEST_TIMEOUT=100000 npx --no hardhat --no-compile test } diff --git a/test/externalTests/gp2.sh b/test/externalTests/gp2.sh index e0f694365..fb3348237 100755 --- a/test/externalTests/gp2.sh +++ b/test/externalTests/gp2.sh @@ -94,7 +94,7 @@ function gp2_test src/contracts/GPv2Settlement.sol # This test is not supposed to work. The compiler is supposed to enforce zero padding since - # at least 0.5.8 (see https://github.com/ethereum/solidity/pull/5815). For some reason the + # at least 0.5.8 (see https://github.com/argotorg/solidity/pull/5815). For some reason the # test worked on 0.7.6 but no longer works on 0.8.x. sed -i 's|it\(("invalid EVM transaction encoding does not change order hash"\)|it.skip\1|g' test/GPv2Signing.test.ts diff --git a/test/formal/README.md b/test/formal/README.md index 83bd79e76..21176ee4a 100644 --- a/test/formal/README.md +++ b/test/formal/README.md @@ -1,4 +1,4 @@ -The Solidity compiler implements several [optimization rules](https://github.com/ethereum/solidity/blob/develop/libevmasm/RuleList.h). +The Solidity compiler implements several [optimization rules](https://github.com/argotorg/solidity/blob/develop/libevmasm/RuleList.h). This directory contains an effort to formally prove the correctness of those rules in: diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 76699c2e3..57422dbb8 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1691,7 +1691,7 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi) // ABI_CHECK(callContractFunction("f()"), encodeArgs(1 + 2 + 3)); //} -// Disabled until https://github.com/ethereum/solidity/issues/715 is implemented +// Disabled until https://github.com/argotorg/solidity/issues/715 is implemented //BOOST_AUTO_TEST_CASE(constant_struct) //{ // char const* sourceCode = R"( diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index d52ad6b9c..832299baf 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -256,7 +256,7 @@ BOOST_AUTO_TEST_CASE(storage_write_in_loops) compareVersions("f(uint256)", 36); } -// Test disabled with https://github.com/ethereum/solidity/pull/762 +// Test disabled with https://github.com/argotorg/solidity/pull/762 // Information in joining branches is not retained anymore. BOOST_AUTO_TEST_CASE(retain_information_in_branches) { diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index b9e31c5e3..93a632032 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -822,7 +822,7 @@ BOOST_AUTO_TEST_CASE(filename_with_colon) "language": "Solidity", "settings": { "outputSelection": { - "https://github.com/ethereum/solidity/blob/develop/test/compilationTests/gnosis/Tokens/StandardToken.sol": { + "https://github.com/argotorg/solidity/blob/develop/test/compilationTests/gnosis/Tokens/StandardToken.sol": { "A": [ "abi" ] @@ -830,7 +830,7 @@ BOOST_AUTO_TEST_CASE(filename_with_colon) } }, "sources": { - "https://github.com/ethereum/solidity/blob/develop/test/compilationTests/gnosis/Tokens/StandardToken.sol": { + "https://github.com/argotorg/solidity/blob/develop/test/compilationTests/gnosis/Tokens/StandardToken.sol": { "content": "contract A { }" } } @@ -838,7 +838,7 @@ BOOST_AUTO_TEST_CASE(filename_with_colon) )"; Json result = compile(input); BOOST_CHECK(containsAtMostWarnings(result)); - Json contract = getContractResult(result, "https://github.com/ethereum/solidity/blob/develop/test/compilationTests/gnosis/Tokens/StandardToken.sol", "A"); + Json contract = getContractResult(result, "https://github.com/argotorg/solidity/blob/develop/test/compilationTests/gnosis/Tokens/StandardToken.sol", "A"); BOOST_CHECK(contract.is_object()); BOOST_CHECK(contract["abi"].is_array()); BOOST_CHECK_EQUAL(util::jsonCompactPrint(contract["abi"]), "[]"); diff --git a/test/libsolidity/semanticTests/array/copying/calldata_1d_array_into_2d_memory_array_element.sol b/test/libsolidity/semanticTests/array/copying/calldata_1d_array_into_2d_memory_array_element.sol index e78d5bdd8..babc3c739 100644 --- a/test/libsolidity/semanticTests/array/copying/calldata_1d_array_into_2d_memory_array_element.sol +++ b/test/libsolidity/semanticTests/array/copying/calldata_1d_array_into_2d_memory_array_element.sol @@ -1,4 +1,4 @@ -// Example from https://github.com/ethereum/solidity/issues/12558 +// Example from https://github.com/argotorg/solidity/issues/12558 pragma abicoder v2; contract C { function f(uint[] calldata a) external returns (uint[][] memory) { diff --git a/test/libsolidity/semanticTests/constants/asm_address_constant_regression.sol b/test/libsolidity/semanticTests/constants/asm_address_constant_regression.sol index ae405d8f3..9e256ad6b 100644 --- a/test/libsolidity/semanticTests/constants/asm_address_constant_regression.sol +++ b/test/libsolidity/semanticTests/constants/asm_address_constant_regression.sol @@ -1,4 +1,4 @@ -// Test for regression of https://github.com/ethereum/solidity/issues/8406 +// Test for regression of https://github.com/argotorg/solidity/issues/8406 contract C { address constant e = 0x1212121212121212121212121000002134593163; diff --git a/test/libsolidity/semanticTests/structs/copy_from_storage.sol b/test/libsolidity/semanticTests/structs/copy_from_storage.sol index b3d730453..ab66e91df 100644 --- a/test/libsolidity/semanticTests/structs/copy_from_storage.sol +++ b/test/libsolidity/semanticTests/structs/copy_from_storage.sol @@ -1,5 +1,5 @@ pragma abicoder v2; -// Example from https://github.com/ethereum/solidity/issues/12558 +// Example from https://github.com/argotorg/solidity/issues/12558 struct S { uint x; } diff --git a/test/libsolidity/syntaxTests/array/copy_from_function_type.sol b/test/libsolidity/syntaxTests/array/copy_from_function_type.sol index b79509468..2ac295d35 100644 --- a/test/libsolidity/syntaxTests/array/copy_from_function_type.sol +++ b/test/libsolidity/syntaxTests/array/copy_from_function_type.sol @@ -1,4 +1,4 @@ -// Example from https://github.com/ethereum/solidity/issues/12558 +// Example from https://github.com/argotorg/solidity/issues/12558 pragma abicoder v2; contract C { function() external[1][] s0; diff --git a/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_nested_mapping_memory.sol b/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_nested_mapping_memory.sol index c8708e3e0..8351a8e00 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_nested_mapping_memory.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_nested_mapping_memory.sol @@ -2,7 +2,7 @@ library a { struct b { mapping (uint => b) c ; } - // Segfaults in https://github.com/ethereum/solidity/issues/9443 + // Segfaults in https://github.com/argotorg/solidity/issues/9443 function d(b memory) public {} } // ---- diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/invalid_match.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/invalid_match.yul index 28beb0383..36c08228f 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/invalid_match.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/invalid_match.yul @@ -1,4 +1,4 @@ -// regression test for https://github.com/ethereum/solidity/issues/16155 +// regression test for https://github.com/argotorg/solidity/issues/16155 { function identity(value) -> ret { ret := value } diff --git a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul index 94d4b14ff..e3ac520cc 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul @@ -12,7 +12,7 @@ * Stay tuned for updates! * * Permission to use as test case in the Solidity compiler granted by the author: - * https://github.com/ethereum/solidity/pull/5713#issuecomment-449042830 + * https://github.com/argotorg/solidity/pull/5713#issuecomment-449042830 **/ { validateJoinSplit() diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul index c67a0f875..cc00b1eab 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_crash.yul @@ -1,4 +1,4 @@ -// This test used to crash: https://github.com/ethereum/solidity/issues/11801 +// This test used to crash: https://github.com/argotorg/solidity/issues/11801 { for {} addmod(keccak256(0x0,create(0x0, 0x0, 0x0)), 0x0, 0x0) {} {} } diff --git a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp index 71a4ff54a..5bd5dd359 100644 --- a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp +++ b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp @@ -80,7 +80,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) ); std::string yul_source = converter.programToString(_input); // Do not fuzz the EVM Version field. - // See https://github.com/ethereum/solidity/issues/12590 + // See https://github.com/argotorg/solidity/issues/12590 langutil::EVMVersion version; EVMHost hostContext(version, evmone); hostContext.reset(); diff --git a/test/tools/ossfuzz/abiV2Proto.proto b/test/tools/ossfuzz/abiV2Proto.proto index ec6fe1d55..be4cdb99c 100644 --- a/test/tools/ossfuzz/abiV2Proto.proto +++ b/test/tools/ossfuzz/abiV2Proto.proto @@ -66,7 +66,7 @@ message NonValueType { } // TODO: Add more types -// See https://github.com/ethereum/solidity/issues/6749 +// See https://github.com/argotorg/solidity/issues/6749 message Type { oneof type_oneof { ValueType vtype = 1; diff --git a/tools/yulPhaser/README.md b/tools/yulPhaser/README.md index 99004d4c9..e7be23994 100644 --- a/tools/yulPhaser/README.md +++ b/tools/yulPhaser/README.md @@ -85,7 +85,7 @@ The difficult part is providing a fairly representative set of input files. If the files you give do not need certain optimisations the tool will find sequences that do not use these optimisations and perform badly for programs that could benefit from them. If all the provided files greatly benefit from a specific optimisation, the sequence may not work well for programs that do not. -We have conducted [a set of rough experiments](https://github.com/ethereum/solidity/issues/7806#issuecomment-598644491) to evaluate some combinations of parameter values. +We have conducted [a set of rough experiments](https://github.com/argotorg/solidity/issues/7806#issuecomment-598644491) to evaluate some combinations of parameter values. The conclusions were used to adjust the defaults but you might still benefit from some general observations: 1. The algorithm that performed the best was `GEWEP`. From c5fa337aefc183694d0e14823e896ae4cda0fbd4 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Wed, 27 Aug 2025 12:13:38 +0200 Subject: [PATCH 0938/1340] Bump dockerfile label version --- scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz | 2 +- scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 | 2 +- scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 | 2 +- scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index 465f2de0a..c14039d90 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-builder AS base -LABEL version="10" +LABEL version="11" ARG DEBIAN_FRONTEND=noninteractive diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 index 48272ed95..be3daee90 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 @@ -22,7 +22,7 @@ # (c) 2016-2025 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:jammy AS base -LABEL version="2" +LABEL version="3" ARG DEBIAN_FRONTEND=noninteractive diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 index 475d4e83c..1edf6f37e 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="3" +LABEL version="4" ARG DEBIAN_FRONTEND=noninteractive diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang index 18cf813fe..3622cc7eb 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="4" +LABEL version="5" ARG DEBIAN_FRONTEND=noninteractive From 0232abc6db66e396856b0fa2ae71c2fb36dcc5b2 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 27 Aug 2025 14:23:04 +0200 Subject: [PATCH 0939/1340] ci: rename osx-dependencies -> macos-dependencies --- .circleci/config.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d206beb69..219321ab6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -380,11 +380,11 @@ commands: steps: - restore_cache: keys: - - osx-dependencies-cached-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} + - macos-dependencies-cached-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} - run: name: Installing dependencies / Restoring dependency cache command: | - if [[ -f ~/osx-dependencies-cached ]]; then + if [[ -f ~/macos-dependencies-cached ]]; then echo "Dependency flag exists. Removing /usr/local/, /opt/homebrew/, and /opt/boost. These directories will be restored from cache." # CircleCI is providing the circleci cli tools via some kind of symlink magic. @@ -414,7 +414,7 @@ commands: fi - restore_cache: keys: - - osx-dependencies-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} + - macos-dependencies-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} # DO NOT EDIT between here and save_cache, but rather edit ./circleci/osx_install_dependencies.sh # WARNING! If you do edit anything here instead, remember to invalidate the cache manually. - run: @@ -422,18 +422,18 @@ commands: command: .circleci/osx_install_dependencies.sh - run: name: Mark dependencies as cached - command: touch ~/osx-dependencies-cached + command: touch ~/macos-dependencies-cached - save_cache: - key: osx-dependencies-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} + key: macos-dependencies-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} paths: # Homebrew is installed in /usr/local on intel macs, but in /opt/homebrew on apple silicon. - /usr/local - /opt/homebrew - /opt/boost - save_cache: - key: osx-dependencies-cached-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} + key: macos-dependencies-cached-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} paths: - - ~/osx-dependencies-cached + - ~/macos-dependencies-cached defaults: From 029a9806417f7af4c83e070a3444d63857f57450 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Wed, 27 Aug 2025 18:43:59 +0200 Subject: [PATCH 0940/1340] Update project_slug in download_benchmarks.py --- scripts/externalTests/download_benchmarks.py | 4 ++-- test/scripts/test_externalTests_benchmark_downloader.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/externalTests/download_benchmarks.py b/scripts/externalTests/download_benchmarks.py index 0f8a65036..386367798 100755 --- a/scripts/externalTests/download_benchmarks.py +++ b/scripts/externalTests/download_benchmarks.py @@ -123,8 +123,8 @@ def download_benchmarks( debug_requests: bool = False, silent: bool = False, ) -> Status: - github = Github('ethereum/solidity', debug_requests) - circleci = CircleCI('ethereum/solidity', debug_requests) + github = Github('argotorg/solidity', debug_requests) + circleci = CircleCI('argotorg/solidity', debug_requests) expected_commit_hash = None if branch is None and pull_request_id is None and base_of_pr is None: diff --git a/test/scripts/test_externalTests_benchmark_downloader.py b/test/scripts/test_externalTests_benchmark_downloader.py index f9ca9ae72..2df72d90b 100644 --- a/test/scripts/test_externalTests_benchmark_downloader.py +++ b/test/scripts/test_externalTests_benchmark_downloader.py @@ -36,7 +36,7 @@ def _git_run_command_mock(command): def _requests_get_mock(url, params, headers, timeout): response_mock = Mock() - if url == 'https://api.github.com/repos/ethereum/solidity/pulls/12818': + if url == 'https://api.github.com/repos/argotorg/solidity/pulls/12818': response_mock.json.return_value = { "head": { "ref": "benchmark-downloader", @@ -50,7 +50,7 @@ def _requests_get_mock(url, params, headers, timeout): return response_mock if ( - url == 'https://circleci.com/api/v2/project/gh/ethereum/solidity/pipeline' and + url == 'https://circleci.com/api/v2/project/gh/argotorg/solidity/pipeline' and params.get('branch') == 'develop' ): response_mock.json.return_value = { @@ -97,7 +97,7 @@ def _requests_get_mock(url, params, headers, timeout): return response_mock if ( - url == 'https://circleci.com/api/v2/project/gh/ethereum/solidity/pipeline' and + url == 'https://circleci.com/api/v2/project/gh/argotorg/solidity/pipeline' and params.get('branch') == 'benchmark-downloader' ): response_mock.json.return_value = { @@ -156,7 +156,7 @@ def _requests_get_mock(url, params, headers, timeout): } return response_mock - if url == 'https://circleci.com/api/v2/project/gh/ethereum/solidity/1018023/artifacts': + if url == 'https://circleci.com/api/v2/project/gh/argotorg/solidity/1018023/artifacts': if ( os.environ.get('CIRCLECI_TOKEN') == 'valid_token' and headers.get('Circle-Token') == os.environ.get('CIRCLECI_TOKEN') From 69af5ee0be572f06d199a1484fb3861f29af0156 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Thu, 28 Aug 2025 15:07:29 +0200 Subject: [PATCH 0941/1340] Replace unmaintained GitHub Action for PR comments --- .github/workflows/buildpack-deps.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index 00d08372d..b277565a8 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -1,5 +1,8 @@ name: buildpack-deps +permissions: + pull-requests: write + on: pull_request: branches: [ develop ] @@ -38,9 +41,6 @@ jobs: - name: comment PR if: "env.DOCKER_IMAGE" - # NOTE: Can't update to v1.3.1 due to an error: `/entrypoint.sh:5:in 'require_relative': cannot load such file -- /lib/github (LoadError)` - uses: unsplash/comment-on-pr@ffe8f97ccc63ce12c3c23c6885b169db67958d3b #v1.3.0 + uses: thollander/actions-comment-pull-request@v3 with: - msg: "`${{ env.DOCKER_IMAGE }} ${{ env.DOCKER_REPO_DIGEST }}`." - check_for_duplicate_msg: false - + message: "`${{ env.DOCKER_IMAGE }} ${{ env.DOCKER_REPO_DIGEST }}`." From 50598a32e2c1a47f5d2166bbcb91684853c681c7 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Fri, 29 Aug 2025 13:24:13 +0200 Subject: [PATCH 0942/1340] Update Solidity project board link --- docs/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 6bf89cc92..45b15e579 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -555,7 +555,7 @@ topics, issues or feature implementations are debated in detail. The invitation We are also sharing feedback surveys and other content that is relevant to language design in the forum. -If you want to know where the team is standing in terms of implementing new features, you can follow the implementation status in the `Solidity GitHub project `_. +If you want to know where the team is standing in terms of implementing new features, you can follow the implementation status in the `Solidity GitHub project `_. Issues in the design backlog need further specification and will either be discussed in a language design call or in a regular team call. You can see the upcoming changes for the next breaking release by changing from the default branch (`develop`) to the `breaking branch `_. From 5991ef62bc5f20798bd5d84e7bb371dcc2053f24 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Tue, 2 Sep 2025 19:40:51 +0200 Subject: [PATCH 0943/1340] Change bot account --- scripts/ci/post_style_errors_on_github.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ci/post_style_errors_on_github.sh b/scripts/ci/post_style_errors_on_github.sh index b0bf1bda7..db7614179 100755 --- a/scripts/ci/post_style_errors_on_github.sh +++ b/scripts/ci/post_style_errors_on_github.sh @@ -26,7 +26,7 @@ function post_error_to_github --url "$GITHUB_API_URL" \ --header 'accept: application/vnd.github.v3+json' \ --header 'content-type: application/json' \ - -u "stackenbotten:$GITHUB_ACCESS_TOKEN" \ + -u "stackenbotten3000:$GITHUB_ACCESS_TOKEN" \ --data "{\"body\": \"There was an error when running \`$CIRCLE_JOB\` for commit \`$CIRCLE_SHA1\`:\n\`\`\`\n$FORMATTED_ERROR_MSG\n\`\`\`\nPlease check that your changes are working as intended.\"}" } @@ -47,7 +47,7 @@ function post_review_comment_to_github --url "$GITHUB_API_URL" \ --header 'accept: application/vnd.github.v3+json, application/vnd.github.comfort-fade-preview+json' \ --header 'content-type: application/json' \ - -u "stackenbotten:$GITHUB_ACCESS_TOKEN" \ + -u "stackenbotten3000:$GITHUB_ACCESS_TOKEN" \ --data "{\"commit_id\": \"$CIRCLE_SHA1\", \"path\": \"$ERROR_PATH\", \"line\": $ERROR_LINE, \"side\": \"RIGHT\", \"body\": \"Coding style error\"}" done < "$ERROR_LOG" } From 5b4389af996ee56b60df2b12477bdca99a70d5b0 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Mon, 8 Sep 2025 18:44:26 +0200 Subject: [PATCH 0944/1340] Grant pull-requests write permission to enable welcome-external-pr bot commenting --- .github/workflows/welcome-external-pr.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/welcome-external-pr.yml b/.github/workflows/welcome-external-pr.yml index b795a36b0..035e2bf5b 100644 --- a/.github/workflows/welcome-external-pr.yml +++ b/.github/workflows/welcome-external-pr.yml @@ -5,6 +5,10 @@ on: types: - opened +permissions: + pull-requests: write + contents: read + env: DRY_RUN: false From a3480a3b8aa34824958b20b380c45e3233ad6f6a Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Wed, 10 Sep 2025 11:56:16 +0200 Subject: [PATCH 0945/1340] Pin GitHub Actions workflows to specific release commits --- .github/workflows/buildpack-deps.yml | 4 ++-- .github/workflows/stale.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index b277565a8..5e49f2f32 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -29,7 +29,7 @@ jobs: image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2204, ubuntu2404, ubuntu2404.clang] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 @@ -41,6 +41,6 @@ jobs: - name: comment PR if: "env.DOCKER_IMAGE" - uses: thollander/actions-comment-pull-request@v3 + uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1 with: message: "`${{ env.DOCKER_IMAGE }} ${{ env.DOCKER_REPO_DIGEST }}`." diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 0b3447282..aaf800217 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -19,7 +19,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v6 + - uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0 with: debug-only: false days-before-issue-stale: ${{ env.BEFORE_ISSUE_STALE }} From f71b385216997d20c1d3d92354a68b95cb925fb7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 24 Sep 2025 16:45:23 +0200 Subject: [PATCH 0946/1340] CI re-enable full prb-math preset matrix --- test/externalTests/prb-math.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/externalTests/prb-math.py b/test/externalTests/prb-math.py index 0cfefb843..029311d0a 100755 --- a/test/externalTests/prb-math.py +++ b/test/externalTests/prb-math.py @@ -52,16 +52,13 @@ def configure(self): name="PRBMath", repo_url="https://github.com/PaulRBerg/prb-math.git", ref="", - compile_only_presets=[ - # pylint: disable=line-too-long - # SettingsPreset.IR_NO_OPTIMIZE, # Error: Yul exception:Variable expr_15699_address is 2 slot(s) too deep inside the stack. Stack too deep. - # SettingsPreset.IR_OPTIMIZE_EVM_ONLY, # Error: Yul exception:Variable expr_15699_address is 2 slot(s) too deep inside the stack. Stack too deep. - ], settings_presets=[ SettingsPreset.LEGACY_NO_OPTIMIZE, SettingsPreset.LEGACY_OPTIMIZE_EVM_ONLY, SettingsPreset.LEGACY_OPTIMIZE_EVM_YUL, + SettingsPreset.IR_NO_OPTIMIZE, SettingsPreset.IR_OPTIMIZE_EVM_YUL, + SettingsPreset.IR_OPTIMIZE_EVM_ONLY, ], ) From 88cbcfb8c6c924e65c756a93af3e3950b7069df0 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 25 Sep 2025 11:40:58 +0200 Subject: [PATCH 0947/1340] CI: Use nightly foundry version for prb-math and switch to prb-math main ref --- .circleci/config.yml | 4 +--- test/externalTests/prb-math.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 219321ab6..4c79434a8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -839,9 +839,7 @@ defaults: project: prb-math binary_type: native image: cimg/rust:1.74.0-node - resource_class: medium - # TODO: Use nightly Foundry builds after https://github.com/PaulRBerg/prb-math/issues/248 is fixed - foundry_version: "v0.3.0" + resource_class: large # Tests run out of memory on a smaller machine - job_native_test_ext_elementfi: &job_native_test_ext_elementfi <<: *requires_b_ubu_static diff --git a/test/externalTests/prb-math.py b/test/externalTests/prb-math.py index 029311d0a..afdca1313 100755 --- a/test/externalTests/prb-math.py +++ b/test/externalTests/prb-math.py @@ -51,7 +51,7 @@ def configure(self): test_config = TestConfig( name="PRBMath", repo_url="https://github.com/PaulRBerg/prb-math.git", - ref="", + ref="main", settings_presets=[ SettingsPreset.LEGACY_NO_OPTIMIZE, SettingsPreset.LEGACY_OPTIMIZE_EVM_ONLY, From 6795a558da76e88b004dfd0fdf1b2773a3494e01 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 25 Sep 2025 16:54:32 +0200 Subject: [PATCH 0948/1340] CI: Install python3-dev, librairo2-dev, and pkg-config before building docs --- .circleci/config.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4c79434a8..f198be892 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1235,6 +1235,11 @@ jobs: steps: - checkout - setup_prerelease_commit_hash + - run: + name: Install build system dependencies + command: | + apt-get update + apt-get install --quiet=2 --no-install-recommends python3-dev libcairo2-dev pkg-config - run: name: Build documentation command: docs/docs.sh From 5997617131253f6457e7b9363ddea694231f647c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 29 Sep 2025 22:15:11 +0200 Subject: [PATCH 0949/1340] docs: use sphinx-syntax over sphinx-a4doc --- docs/_static/css/custom-dark.css | 2 +- docs/conf.py | 9 ++++++--- docs/grammar.rst | 8 ++++---- docs/requirements.txt | 11 +++++------ 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/docs/_static/css/custom-dark.css b/docs/_static/css/custom-dark.css index 044a8f800..1294a6f64 100644 --- a/docs/_static/css/custom-dark.css +++ b/docs/_static/css/custom-dark.css @@ -590,6 +590,6 @@ stroke: white; } -:root[style*=dark] .a4 .sig-name { +:root[style*=dark] .sig-name { background-color: transparent !important; } diff --git a/docs/conf.py b/docs/conf.py index dc52c96bd..44da93dba 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -92,13 +92,15 @@ def get_github_username_repo(url): # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx_a4doc', + 'sphinx_syntax', 'html_extra_template_renderer', 'remix_code_links', 'sphinx.ext.imgconverter', ] -a4_base_path = os.path.dirname(__file__) + '/grammar' +syntax_base_path = 'grammar' +# generate link anchors compatible with Sphinx-A4Doc’s naming +syntax_a4doc_compat_links = True # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -182,7 +184,8 @@ def get_github_username_repo(url): # documentation. html_theme_options = { 'logo_only': True, - 'display_version': True, + 'version_selector': True, + 'language_selector': True, } # Add any paths that contain custom themes here, relative to this directory. diff --git a/docs/grammar.rst b/docs/grammar.rst index 788b6d695..d58cbb41a 100644 --- a/docs/grammar.rst +++ b/docs/grammar.rst @@ -2,12 +2,12 @@ Language Grammar **************** -.. a4:autogrammar:: SolidityParser - :only-reachable-from: SolidityParser.sourceUnit +.. syntax:autogrammar:: SolidityParser.g4 + :root-rule: SolidityParser.sourceUnit :undocumented: :cc-to-dash: -.. a4:autogrammar:: SolidityLexer - :only-reachable-from: SolidityParser.sourceUnit +.. syntax:autogrammar:: SolidityLexer.g4 + :root-rule: SolidityParser.sourceUnit :fragments: :cc-to-dash: \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt index f4c1aae61..8f5f27fff 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,12 +2,11 @@ # which could result in it being installed anyway and the style (especially bullet points) being broken. # See https://github.com/readthedocs/sphinx_rtd_theme/issues/1115 # theme >=3.0.0 removes the display_version option in favor of version_selector and language_selector -sphinx_rtd_theme>=0.5.2, <3.0.0 +# Use rtd theme version that supports sphinx>=8.0 +sphinx_rtd_theme>=3.0.0 pygments-lexer-solidity>=0.7.0 -sphinx-a4doc>=1.6.0; python_version < '3.13' -# todo remove this once there is a version > 1.6.0 -sphinx-a4doc @ git+https://github.com/taminomara/sphinx-a4doc@f63d3b2; python_version >= '3.13' +sphinx-syntax>=1.0.1 -# Sphinx 2.1.0 is the oldest version that accepts a lexer class in add_lexer() -sphinx>=2.1.0, <9.0 +# Sphinx version constraints for sphinx-syntax compatibility +sphinx>=8.0.0, <9.0.0 From 89aafb968beb2601cca4aa0097b4172da1db8195 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 30 Sep 2025 11:48:18 +0200 Subject: [PATCH 0950/1340] bump rtd os to ubuntu 24.04 and python 3.13 --- .readthedocs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index c0c139b7e..bb8101224 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,9 +1,9 @@ version: 2 build: - os: ubuntu-22.04 + os: ubuntu-24.04 tools: - python: "3.11" + python: "3.13" sphinx: builder: html From 292bfd43432757a701ee0025f689a39ec68e4daf Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 30 Sep 2025 10:51:11 +0200 Subject: [PATCH 0951/1340] dockerfiles: bump emscripten to v21 containing boost 1.83.0 --- .../buildpack-deps/Dockerfile.emscripten | 72 ++++++++++--------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten index d8eb9a903..007729d41 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -33,26 +33,29 @@ # Using $(em-config CACHE)/sysroot/usr seems to work, though, and still has cmake find the # dependencies automatically. FROM emscripten/emsdk:3.1.19 AS base -LABEL version="20" +LABEL version="21" ADD emscripten.jam /usr/src -RUN set -ex && \ - apt-get update && \ +RUN <<-EOF + set -ex + apt-get update apt-get install -qqy --no-install-recommends \ lsof \ lz4 \ python3 \ python3-pip \ sudo && \ - pip3 install requests; + pip3 install requests +EOF # Install Z3 -RUN set -ex && \ - cd /usr/src && \ - git clone https://github.com/Z3Prover/z3.git -b z3-4.13.3 --depth 1 && \ - cd z3 && \ - mkdir build && \ - cd build && \ +RUN <<-EOF + set -ex + cd /usr/src + git clone https://github.com/Z3Prover/z3.git -b z3-4.13.3 --depth 1 + cd z3 + mkdir build + cd build emcmake cmake \ -DCMAKE_INSTALL_PREFIX=$(em-config CACHE)/sysroot/usr \ -DCMAKE_BUILD_TYPE=MinSizeRel \ @@ -62,33 +65,38 @@ RUN set -ex && \ -DZ3_BUILD_EXECUTABLE=OFF \ -DZ3_SINGLE_THREADED=ON \ -DCMAKE_CXX_FLAGS="-s DISABLE_EXCEPTION_CATCHING=0" \ - .. && \ - make && \ - make install && \ + .. + make + make install rm -r /usr/src/z3 +EOF # Install Boost -RUN set -ex && \ - cd /usr/src && \ - wget -q 'https://archives.boost.io/release/1.75.0/source/boost_1_75_0.tar.bz2' -O boost.tar.bz2 && \ - test "$(sha256sum boost.tar.bz2)" = "953db31e016db7bb207f11432bef7df100516eeb746843fa0486a222e3fd49cb boost.tar.bz2" && \ - tar -xf boost.tar.bz2 && \ - rm boost.tar.bz2 && \ - cd boost_1_75_0 && \ - mv ../emscripten.jam . && \ - ./bootstrap.sh && \ - echo "using emscripten : : em++ ;" >> project-config.jam && \ +RUN <<-EOF + set -ex + cd /usr/src + wget -q 'https://archives.boost.io/release/1.83.0/source/boost_1_83_0.tar.bz2' -O boost.tar.bz2 + test "$(sha256sum boost.tar.bz2)" = "6478edfe2f3305127cffe8caf73ea0176c53769f4bf1585be237eb30798c3b8e boost.tar.bz2" + tar -xf boost.tar.bz2 + rm boost.tar.bz2 + cd boost_1_83_0 + mv ../emscripten.jam . + ./bootstrap.sh + echo "using emscripten : : em++ ;" >> project-config.jam ./b2 toolset=emscripten link=static variant=release threading=single runtime-link=static \ --with-system --with-filesystem --with-test --with-program_options \ cxxflags="-s DISABLE_EXCEPTION_CATCHING=0 -Wno-unused-local-typedef -Wno-variadic-macros -Wno-c99-extensions -Wno-all" \ - --prefix=$(em-config CACHE)/sysroot/usr install && \ - rm -r /usr/src/boost_1_75_0 + --prefix=$(em-config CACHE)/sysroot/usr install + rm -r /usr/src/boost_1_83_0 +EOF # CVC5 -RUN set -ex; \ - cvc5_version="1.2.0"; \ - cvc5_archive_name="cvc5-Linux-x86_64-static"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ - unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ - rm -f /opt/cvc5.zip; +RUN <<-EOF + set -ex + cvc5_version="1.2.0" + cvc5_archive_name="cvc5-Linux-x86_64-static" + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip + test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip" + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin + rm -f /opt/cvc5.zip +EOF From fff81f3cf3e4587b54ad915ac982823a92d96d77 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 20 Aug 2025 15:52:20 +0200 Subject: [PATCH 0952/1340] CI: Add job that tests minimum requirement versions for linux --- .circleci/config.yml | 53 +++++++++++-- .../install_and_check_minimum_requirements.sh | 75 +++++++++++++++++++ 2 files changed, 121 insertions(+), 7 deletions(-) create mode 100755 scripts/ci/install_and_check_minimum_requirements.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index f198be892..ac8d48d6d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -198,6 +198,19 @@ commands: fi echo -n "$CIRCLE_SHA1" > commit_hash.txt + install_and_check_minimum_requirements: + parameters: + compiler: + description: "Compiler to check: gcc or clang" + type: enum + enum: + - gcc + - clang + steps: + - run: + name: Install and check minimum requirements + command: scripts/ci/install_and_check_minimum_requirements.sh "--<< parameters.compiler >>" + run_build: steps: - run: @@ -1103,23 +1116,43 @@ jobs: - solc/solc-static-linux - matrix_notify_failure_unless_pr - b_ubu_2204: - <<: *base_ubuntu2204_large + b_ubu_min_req: + <<: *base_ubuntu2404_large steps: - checkout + - install_and_check_minimum_requirements: + compiler: gcc - run_build + - store_artifacts_solc + - persist_executables_to_workspace - matrix_notify_failure_unless_pr + - build - b_ubu_2204_clang: - <<: *base_ubuntu2204_clang_large + b_ubu_min_req_clang: + <<: *base_ubuntu2404_clang_large environment: - <<: *base_ubuntu2204_clang_large_env + <<: *base_ubuntu2404_clang_large_env MAKEFLAGS: -j 10 steps: - checkout + - install_and_check_minimum_requirements: + compiler: clang - run_build - matrix_notify_failure_unless_pr + t_ubu_min_req_soltest: + <<: *base_ubuntu2404_large + parallelism: 20 + environment: + <<: *base_ubuntu2404_large_env + EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 + OPTIMIZE: 0 + # Skip semantic tests due to evmone compatibility issues with Ubuntu 22.04 + SOLTEST_FLAGS: --no-semantic-tests --no-smt + steps: + - soltest + b_ubu_ossfuzz: &b_ubu_ossfuzz <<: *base_ubuntu_clang_large steps: @@ -1893,8 +1926,14 @@ workflows: # build-only - b_docs: *requires_nothing - b_ubu_ossfuzz: *requires_nothing - - b_ubu_2204: *requires_nothing - - b_ubu_2204_clang: *requires_nothing + + # build and test with minimum supported versions of dependencies + - b_ubu_min_req_clang: *requires_nothing + - b_ubu_min_req: *requires_nothing + - t_ubu_min_req_soltest: + <<: *on_all_tags_and_branches + requires: + - b_ubu_min_req # OS/X build and tests - b_osx: *requires_nothing diff --git a/scripts/ci/install_and_check_minimum_requirements.sh b/scripts/ci/install_and_check_minimum_requirements.sh new file mode 100755 index 000000000..db3ff0fec --- /dev/null +++ b/scripts/ci/install_and_check_minimum_requirements.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +set -euo pipefail + +# minimum boost version +BOOST_VERSION=1.83 + +# minimum cmake version +CMAKE_MAJOR=3 +CMAKE_MINOR=13 +CMAKE_PATCH=0 +CMAKE_FULL_VERSION="${CMAKE_MAJOR}.${CMAKE_MINOR}.${CMAKE_PATCH}" + +# minimum gcc/clang versions +GCC_VERSION=13.3.0 +CLANG_VERSION=18.1.3 + +# which compiler version to check in this script +check_gcc=false +check_clang=false + +while (( $# > 0 )); do + case "$1" in + --gcc) + check_gcc=true + shift + ;; + --clang) + check_clang=true + shift + ;; + *) + echo "Unknown option: $1" + echo "Usage: $0 [--gcc] [--clang]" + exit 1 + ;; + esac +done + +echo "-- Removing boost and CMake from the system" +sudo apt-get --quiet=2 remove --purge 'libboost*' +sudo apt-get --quiet=2 remove --purge cmake + +echo "-- Installing Boost ${BOOST_VERSION}" +sudo apt-get --quiet=2 update +sudo apt-get --quiet=2 install libboost${BOOST_VERSION}-all-dev +installed_boost_version=$(dpkg-query --showformat='${Version}' --show libboost${BOOST_VERSION}-all-dev 2>/dev/null || echo "none") +if [[ $installed_boost_version != ${BOOST_VERSION}* ]]; then + echo "Error: installed version of boost is $installed_boost_version, expected $BOOST_VERSION" + exit 1 +fi + +echo "-- Installing CMake ${CMAKE_FULL_VERSION}" +wget "https://cmake.org/files/v${CMAKE_MAJOR}.${CMAKE_MINOR}/cmake-${CMAKE_FULL_VERSION}-Linux-x86_64.tar.gz" +tar --extract --gzip --file "cmake-${CMAKE_FULL_VERSION}-Linux-x86_64.tar.gz" +sudo mv "cmake-${CMAKE_FULL_VERSION}-Linux-x86_64" "/opt/cmake-${CMAKE_FULL_VERSION}" +sudo ln --symbolic "/opt/cmake-${CMAKE_FULL_VERSION}/bin/"* /usr/local/bin/ +echo "-- Installed $(cmake --version)" + +if [[ "$check_gcc" == true ]]; then + installed_gcc_version=$(gcc -dumpfullversion -dumpversion || echo "none") + if [[ "$installed_gcc_version" != "$GCC_VERSION" ]]; then + echo "Error: installed version of gcc is $installed_gcc_version, expected $GCC_VERSION" + exit 1 + fi + echo "-- gcc version check passed: $installed_gcc_version" +fi + +if [[ "$check_clang" == true ]]; then + installed_clang_version=$(clang -dumpfullversion -dumpversion || echo "none") + if [[ "$installed_clang_version" != "$CLANG_VERSION" ]]; then + echo "Error: installed version of clang is $installed_clang_version, expected $CLANG_VERSION" + exit 1 + fi + echo "-- clang version check passed: $installed_clang_version" +fi From cbaa5ab9926ad132fe3845cf907f6758703ba29e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:09:41 +0200 Subject: [PATCH 0953/1340] Deps: Update minimum version requirements of Boost to 1.83.0 for non-windows builds and of GCC and Clang to 13.3 and 18.1.3, respectively. Fixes infinite recursion on `boost::rational` comparison affecting compiler binaries built with GCC<14.0 and Boost<1.75. --- .circleci/config.yml | 4 ++-- Changelog.md | 2 +- cmake/EthDependencies.cmake | 4 +++- docs/installing-solidity.rst | 10 +++++++--- scripts/ci/install_and_check_minimum_requirements.sh | 2 ++ 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ac8d48d6d..20c6bc2a8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,8 +30,8 @@ parameters: emscripten-docker-image: type: string # NOTE: Please remember to update the `scripts/build_emscripten.sh` whenever the hash of this image changes. - # solbuildpackpusher/solidity-buildpack-deps:emscripten-20 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:98f963ed799a0d206ef8e7b5475f847e0dea53b7fdea9618bbc6106a62730bd2" + # solbuildpackpusher/solidity-buildpack-deps:emscripten-21 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:fc53d68a4680ffa7d5f70164e13a903478964f15bcc07434d74833a05f4fbc19" evm-version: type: string default: prague diff --git a/Changelog.md b/Changelog.md index df45a558f..53039947b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,7 +10,7 @@ Bugfixes: * Yul Optimizer: Fix edge case in which invalid Yul code is produced by ExpressionSimplifier due to expressions being substituted that contain out-of-scope variables. Build System: -* Update to boost 1.70.0 for non-windows builds. +* Update minimum version requirements of Boost to 1.83.0 for non-windows builds and of GCC and Clang to 13.3 and 18.1.3, respectively. Fixes infinite recursion on `boost::rational` comparison affecting compiler binaries built with GCC<14.0 and Boost<1.75. ### 0.8.30 (2025-05-07) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 453c6d14c..ac810c50d 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -44,7 +44,9 @@ else() # Boost 1.67 moved container_hash into is own module. # Boost 1.69 boost::system is header-only and no longer needs to be fetched as component # Boost 1.70 comes with its own BoostConfig.cmake and is the new (non-deprecated) behavior - find_package(Boost 1.70.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) + # Boost 1.75 fixes infinite recursion on `boost::rational` comparison with GCC<14.0 under C++20 + # Boost 1.83 is the version that comes with Ubuntu 24.04. + find_package(Boost 1.83.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) endif() # If cmake is older than boost and boost is older than 1.70, diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 6f085539b..6c6d6029a 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -320,6 +320,8 @@ Prerequisites - All Operating Systems The following are dependencies for all builds of Solidity: +.. Note: This has to be kept in sync with `scripts/ci/install_and_check_minimum_requirements.sh`. + +-----------------------------------+-------------------------------------------------------+ | Software | Notes | +===================================+=======================================================+ @@ -327,7 +329,7 @@ The following are dependencies for all builds of Solidity: | Windows, 3.13+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ | `Boost`_ (version 1.77+ on | C++ libraries. | -| Windows, 1.70+ otherwise) | | +| Windows, 1.83+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ | `Git`_ | Command-line tool for retrieving source code. | +-----------------------------------+-------------------------------------------------------+ @@ -372,8 +374,10 @@ Minimum Compiler Versions The following C++ compilers and their minimum versions can build the Solidity codebase: -- `GCC `_, version 11+ -- `Clang `_, version 14+ +.. Note: Minimum versions for GCC and Clang are based on availability in Ubuntu 24.04. + +- `GCC `_, version 13.3+ +- `Clang `_, version 18.1.3+ - `MSVC `_, version 2019+ Prerequisites - macOS diff --git a/scripts/ci/install_and_check_minimum_requirements.sh b/scripts/ci/install_and_check_minimum_requirements.sh index db3ff0fec..bc167b673 100755 --- a/scripts/ci/install_and_check_minimum_requirements.sh +++ b/scripts/ci/install_and_check_minimum_requirements.sh @@ -1,6 +1,8 @@ #!/usr/bin/env bash set -euo pipefail +# These versions must be kept in sync with the docs in `docs/installing-solidity.rst#building-from-source`. + # minimum boost version BOOST_VERSION=1.83 From 8c1e48917228bda980a3b1d307e874ce80c8371e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 22 Sep 2025 12:46:39 +0200 Subject: [PATCH 0954/1340] CI: Prune 2204 jobs from the config --- .circleci/config.yml | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 20c6bc2a8..076c7b8d1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,10 +11,6 @@ parameters: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-26 default: "solbuildpackpusher/solidity-buildpack-deps@sha256:1f387a77be889f65a2a25986a5c5eccc88cec23fabe6aeaf351790751145c81e" - ubuntu-2204-docker-image: - type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2204-2 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:877fcc2589779f8245770711d10db92eda97d338dae76b6a9f27dde1a41b3aa0" ubuntu-2404-docker-image: type: string # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-3 @@ -573,42 +569,6 @@ defaults: MAKEFLAGS: -j 10 CPUs: 10 - - base_ubuntu2204: &base_ubuntu2204 - docker: - - image: << pipeline.parameters.ubuntu-2204-docker-image >> - environment: &base_ubuntu2204_env - TERM: xterm - CC: gcc - CXX: g++ - MAKEFLAGS: -j 3 - CPUs: 3 - - - base_ubuntu2204_large: &base_ubuntu2204_large - <<: *base_ubuntu2204 - resource_class: large - environment: &base_ubuntu2204_large_env - <<: *base_ubuntu2204_env - MAKEFLAGS: -j 5 - CPUs: 5 - - - base_ubuntu2204_clang: &base_ubuntu2204_clang - docker: - - image: << pipeline.parameters.ubuntu-2204-docker-image >> - environment: &base_ubuntu2204_clang_env - TERM: xterm - CC: clang - CXX: clang++ - MAKEFLAGS: -j 3 - CPUs: 3 - - - base_ubuntu2204_clang_large: &base_ubuntu2204_clang_large - <<: *base_ubuntu2204_clang - resource_class: large - environment: &base_ubuntu2204_clang_large_env - <<: *base_ubuntu2204_clang_env - MAKEFLAGS: -j 5 - CPUs: 5 - - base_ubuntu2404: &base_ubuntu2404 docker: - image: << pipeline.parameters.ubuntu-2404-docker-image >> @@ -1148,8 +1108,6 @@ jobs: EVM: << pipeline.parameters.evm-version >> EOF_VERSION: 0 OPTIMIZE: 0 - # Skip semantic tests due to evmone compatibility issues with Ubuntu 22.04 - SOLTEST_FLAGS: --no-semantic-tests --no-smt steps: - soltest From 7e994ce17c83b111e77b0ff9f97fc91435a8a896 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 30 Sep 2025 09:00:39 +0200 Subject: [PATCH 0955/1340] Move ssa pipeline things into own subdirectory --- libyul/CMakeLists.txt | 28 +++---- libyul/YulStack.cpp | 10 +-- libyul/backends/evm/{ => ssa}/ControlFlow.cpp | 9 +- libyul/backends/evm/{ => ssa}/ControlFlow.h | 11 +-- .../LivenessAnalysis.cpp} | 14 ++-- .../LivenessAnalysis.h} | 12 +-- .../SSACFG.cpp} | 13 +-- .../{SSAControlFlowGraph.h => ssa/SSACFG.h} | 6 +- .../SSACFGBuilder.cpp} | 83 +++++++++---------- .../SSACFGBuilder.h} | 14 ++-- .../evm/ssa/SSACFGJsonExporter.cpp} | 24 +++--- .../evm/ssa/SSACFGJsonExporter.h} | 18 ++-- .../evm/{ => ssa}/SSACFGLoopNestingForest.cpp | 4 +- .../evm/{ => ssa}/SSACFGLoopNestingForest.h | 6 +- .../evm/{ => ssa}/SSACFGTopologicalSort.cpp | 4 +- .../evm/{ => ssa}/SSACFGTopologicalSort.h | 4 +- test/libyul/SSAControlFlowGraphTest.cpp | 6 +- 17 files changed, 133 insertions(+), 133 deletions(-) rename libyul/backends/evm/{ => ssa}/ControlFlow.cpp (78%) rename libyul/backends/evm/{ => ssa}/ControlFlow.h (89%) rename libyul/backends/evm/{SSACFGLiveness.cpp => ssa/LivenessAnalysis.cpp} (93%) rename libyul/backends/evm/{SSACFGLiveness.h => ssa/LivenessAnalysis.h} (87%) rename libyul/backends/evm/{SSAControlFlowGraph.cpp => ssa/SSACFG.cpp} (96%) rename libyul/backends/evm/{SSAControlFlowGraph.h => ssa/SSACFG.h} (98%) rename libyul/backends/evm/{SSAControlFlowGraphBuilder.cpp => ssa/SSACFGBuilder.cpp} (88%) rename libyul/backends/evm/{SSAControlFlowGraphBuilder.h => ssa/SSACFGBuilder.h} (93%) rename libyul/{YulControlFlowGraphExporter.cpp => backends/evm/ssa/SSACFGJsonExporter.cpp} (86%) rename libyul/{YulControlFlowGraphExporter.h => backends/evm/ssa/SSACFGJsonExporter.h} (72%) rename libyul/backends/evm/{ => ssa}/SSACFGLoopNestingForest.cpp (96%) rename libyul/backends/evm/{ => ssa}/SSACFGLoopNestingForest.h (93%) rename libyul/backends/evm/{ => ssa}/SSACFGTopologicalSort.cpp (96%) rename libyul/backends/evm/{ => ssa}/SSACFGTopologicalSort.h (96%) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 58390d956..e70a6e7b6 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -42,8 +42,6 @@ add_library(yul ScopeFiller.h Utilities.cpp Utilities.h - YulControlFlowGraphExporter.h - YulControlFlowGraphExporter.cpp YulName.h YulString.h backends/evm/AbstractAssembly.h @@ -51,8 +49,6 @@ add_library(yul backends/evm/AsmCodeGen.h backends/evm/ConstantOptimiser.cpp backends/evm/ConstantOptimiser.h - backends/evm/ControlFlow.cpp - backends/evm/ControlFlow.h backends/evm/ControlFlowGraph.h backends/evm/ControlFlowGraphBuilder.cpp backends/evm/ControlFlowGraphBuilder.h @@ -72,21 +68,25 @@ add_library(yul backends/evm/NoOutputAssembly.cpp backends/evm/OptimizedEVMCodeTransform.cpp backends/evm/OptimizedEVMCodeTransform.h - backends/evm/SSACFGLiveness.cpp - backends/evm/SSACFGLiveness.h - backends/evm/SSACFGLoopNestingForest.cpp - backends/evm/SSACFGLoopNestingForest.h - backends/evm/SSACFGTopologicalSort.cpp - backends/evm/SSACFGTopologicalSort.h - backends/evm/SSAControlFlowGraph.cpp - backends/evm/SSAControlFlowGraph.h - backends/evm/SSAControlFlowGraphBuilder.cpp - backends/evm/SSAControlFlowGraphBuilder.h backends/evm/StackHelpers.h backends/evm/StackLayoutGenerator.cpp backends/evm/StackLayoutGenerator.h backends/evm/VariableReferenceCounter.h backends/evm/VariableReferenceCounter.cpp + backends/evm/ssa/ControlFlow.cpp + backends/evm/ssa/ControlFlow.h + backends/evm/ssa/LivenessAnalysis.cpp + backends/evm/ssa/LivenessAnalysis.h + backends/evm/ssa/SSACFGLoopNestingForest.cpp + backends/evm/ssa/SSACFGLoopNestingForest.h + backends/evm/ssa/SSACFGTopologicalSort.cpp + backends/evm/ssa/SSACFGTopologicalSort.h + backends/evm/ssa/SSACFG.cpp + backends/evm/ssa/SSACFG.h + backends/evm/ssa/SSACFGBuilder.cpp + backends/evm/ssa/SSACFGBuilder.h + backends/evm/ssa/SSACFGJsonExporter.h + backends/evm/ssa/SSACFGJsonExporter.cpp optimiser/ASTCopier.cpp optimiser/ASTCopier.h optimiser/ASTWalker.cpp diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 52c6241c6..75b39134f 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -20,7 +20,8 @@ #include #include -#include +#include +#include #include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -398,14 +398,14 @@ Json YulStack::cfgJson() const // operations to the control flow graphs bool constexpr keepLiteralAssignments = true; // NOTE: The block Ids are reset for each object - std::unique_ptr controlFlow = SSAControlFlowGraphBuilder::build( + std::unique_ptr controlFlow = ssa::SSACFGBuilder::build( *_object.analysisInfo, languageToDialect(m_language, m_evmVersion, m_eofVersion), _object.code()->root(), keepLiteralAssignments ); - std::unique_ptr liveness = std::make_unique(*controlFlow); - YulControlFlowGraphExporter exporter(*controlFlow, liveness.get()); + std::unique_ptr liveness = std::make_unique(*controlFlow); + ssa::SSACFGJsonExporter exporter(*controlFlow, liveness.get()); return exporter.run(); }; diff --git a/libyul/backends/evm/ControlFlow.cpp b/libyul/backends/evm/ssa/ControlFlow.cpp similarity index 78% rename from libyul/backends/evm/ControlFlow.cpp rename to libyul/backends/evm/ssa/ControlFlow.cpp index 863fa30f6..fb560d6dd 100644 --- a/libyul/backends/evm/ControlFlow.cpp +++ b/libyul/backends/evm/ssa/ControlFlow.cpp @@ -16,15 +16,16 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#include + #include -using namespace solidity::yul; +using namespace solidity::yul::ssa; ControlFlowLiveness::ControlFlowLiveness(ControlFlow const& _controlFlow): controlFlow(_controlFlow), - mainLiveness(std::make_unique(*_controlFlow.mainGraph)), - functionLiveness(_controlFlow.functionGraphs | ranges::views::transform([](auto const& _cfg) { return std::make_unique(*_cfg); }) | ranges::to) + mainLiveness(std::make_unique(*_controlFlow.mainGraph)), + functionLiveness(_controlFlow.functionGraphs | ranges::views::transform([](auto const& _cfg) { return std::make_unique(*_cfg); }) | ranges::to) { } std::string ControlFlowLiveness::toDot() const diff --git a/libyul/backends/evm/ControlFlow.h b/libyul/backends/evm/ssa/ControlFlow.h similarity index 89% rename from libyul/backends/evm/ControlFlow.h rename to libyul/backends/evm/ssa/ControlFlow.h index 394ce00c5..314545643 100644 --- a/libyul/backends/evm/ControlFlow.h +++ b/libyul/backends/evm/ssa/ControlFlow.h @@ -18,12 +18,13 @@ #pragma once +#include +#include + #include #include -#include -#include -namespace solidity::yul +namespace solidity::yul::ssa { struct ControlFlow; @@ -32,8 +33,8 @@ struct ControlFlowLiveness{ explicit ControlFlowLiveness(ControlFlow const& _controlFlow); std::reference_wrapper controlFlow; - std::unique_ptr mainLiveness; - std::vector> functionLiveness; + std::unique_ptr mainLiveness; + std::vector> functionLiveness; std::string toDot() const; }; diff --git a/libyul/backends/evm/SSACFGLiveness.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp similarity index 93% rename from libyul/backends/evm/SSACFGLiveness.cpp rename to libyul/backends/evm/ssa/LivenessAnalysis.cpp index a0bfeb5bb..49f077feb 100644 --- a/libyul/backends/evm/SSACFGLiveness.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -16,7 +16,7 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#include #include @@ -24,7 +24,7 @@ #include #include -using namespace solidity::yul; +using namespace solidity::yul::ssa; namespace { @@ -37,7 +37,7 @@ constexpr auto literalsFilter(SSACFG const& _cfg) } } -std::set SSACFGLiveness::blockExitValues(SSACFG::BlockId const& _blockId) const +std::set LivenessAnalysis::blockExitValues(SSACFG::BlockId const& _blockId) const { std::set result; util::GenericVisitor exitVisitor { @@ -60,7 +60,7 @@ std::set SSACFGLiveness::blockExitValues(SSACFG::BlockId const& return result; } -SSACFGLiveness::SSACFGLiveness(SSACFG const& _cfg): +LivenessAnalysis::LivenessAnalysis(SSACFG const& _cfg): m_cfg(_cfg), m_topologicalSort(_cfg), m_loopNestingForest(m_topologicalSort), @@ -75,7 +75,7 @@ SSACFGLiveness::SSACFGLiveness(SSACFG const& _cfg): fillOperationsLiveOut(); } -void SSACFGLiveness::runDagDfs() +void LivenessAnalysis::runDagDfs() { // SSA Book, Algorithm 9.2 for (auto const blockIdValue: m_topologicalSort.postOrder()) @@ -137,7 +137,7 @@ void SSACFGLiveness::runDagDfs() } } -void SSACFGLiveness::runLoopTreeDfs(size_t const _loopHeader) +void LivenessAnalysis::runLoopTreeDfs(size_t const _loopHeader) { // SSA Book, Algorithm 9.3 if (m_loopNestingForest.loopNodes().count(_loopHeader) > 0) @@ -161,7 +161,7 @@ void SSACFGLiveness::runLoopTreeDfs(size_t const _loopHeader) } } -void SSACFGLiveness::fillOperationsLiveOut() +void LivenessAnalysis::fillOperationsLiveOut() { for (size_t blockIdValue = 0; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) { diff --git a/libyul/backends/evm/SSACFGLiveness.h b/libyul/backends/evm/ssa/LivenessAnalysis.h similarity index 87% rename from libyul/backends/evm/SSACFGLiveness.h rename to libyul/backends/evm/ssa/LivenessAnalysis.h index 6ec0d1688..74b7f20fa 100644 --- a/libyul/backends/evm/SSACFGLiveness.h +++ b/libyul/backends/evm/ssa/LivenessAnalysis.h @@ -18,25 +18,25 @@ #pragma once -#include -#include -#include +#include +#include +#include #include #include #include -namespace solidity::yul +namespace solidity::yul::ssa { /// Performs liveness analysis on a reducible SSA CFG following Algorithm 9.1 in [1]. /// /// [1] Rastello, Fabrice, and Florent Bouchez Tichadou, eds. SSA-based Compiler Design. Springer, 2022. -class SSACFGLiveness +class LivenessAnalysis { public: using LivenessData = std::set; - explicit SSACFGLiveness(SSACFG const& _cfg); + explicit LivenessAnalysis(SSACFG const& _cfg); LivenessData const& liveIn(SSACFG::BlockId _blockId) const { return m_liveIns[_blockId.value]; } LivenessData const& liveOut(SSACFG::BlockId _blockId) const { return m_liveOuts[_blockId.value]; } diff --git a/libyul/backends/evm/SSAControlFlowGraph.cpp b/libyul/backends/evm/ssa/SSACFG.cpp similarity index 96% rename from libyul/backends/evm/SSAControlFlowGraph.cpp rename to libyul/backends/evm/ssa/SSACFG.cpp index 215fe7358..180753424 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -16,9 +16,9 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#include -#include +#include #include #include @@ -33,18 +33,19 @@ using namespace solidity; using namespace solidity::util; using namespace solidity::yul; +using namespace solidity::yul::ssa; namespace { class SSACFGPrinter { public: - SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness): + SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness): m_cfg(_cfg), m_functionIndex(0), m_liveness(_liveness) { printBlock(_blockId); } - SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function, SSACFGLiveness const* _liveness): + SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function, LivenessAnalysis const* _liveness): m_cfg(_cfg), m_functionIndex(_functionIndex), m_liveness(_liveness) { printFunction(_function); @@ -291,7 +292,7 @@ class SSACFGPrinter SSACFG const& m_cfg; size_t m_functionIndex; - SSACFGLiveness const* m_liveness; + LivenessAnalysis const* m_liveness; std::stringstream m_result{}; }; } @@ -299,7 +300,7 @@ class SSACFGPrinter std::string SSACFG::toDot( bool _includeDiGraphDefinition, std::optional _functionIndex, - SSACFGLiveness const* _liveness + LivenessAnalysis const* _liveness ) const { std::ostringstream output; diff --git a/libyul/backends/evm/SSAControlFlowGraph.h b/libyul/backends/evm/ssa/SSACFG.h similarity index 98% rename from libyul/backends/evm/SSAControlFlowGraph.h rename to libyul/backends/evm/ssa/SSACFG.h index ee1bdf3b4..32768ca6b 100644 --- a/libyul/backends/evm/SSAControlFlowGraph.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -35,9 +35,9 @@ #include #include -namespace solidity::yul +namespace solidity::yul::ssa { -class SSACFGLiveness; +class LivenessAnalysis; class SSACFG { @@ -227,7 +227,7 @@ class SSACFG std::string toDot( bool _includeDiGraphDefinition=true, std::optional _functionIndex=std::nullopt, - SSACFGLiveness const* _liveness=nullptr + LivenessAnalysis const* _liveness=nullptr ) const; private: std::deque m_valueInfos; diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp similarity index 88% rename from libyul/backends/evm/SSAControlFlowGraphBuilder.cpp rename to libyul/backends/evm/ssa/SSACFGBuilder.cpp index 0af08e39d..92b49e7fc 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -19,9 +19,10 @@ * Transformation of a Yul AST into a control flow graph. */ -#include +#include + +#include -#include #include #include #include @@ -42,11 +43,9 @@ using namespace solidity; using namespace solidity::yul; +using namespace solidity::yul::ssa; -namespace solidity::yul -{ - -SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder( +SSACFGBuilder::SSACFGBuilder( ControlFlow& _controlFlow, SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, @@ -63,7 +62,7 @@ SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder( { } -std::unique_ptr SSAControlFlowGraphBuilder::build( +std::unique_ptr SSACFGBuilder::build( AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, Block const& _block, @@ -73,7 +72,7 @@ std::unique_ptr SSAControlFlowGraphBuilder::build( ControlFlowSideEffectsCollector sideEffects(_dialect, _block); auto controlFlow = std::make_unique(); - SSAControlFlowGraphBuilder builder(*controlFlow, *controlFlow->mainGraph, _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments); + SSACFGBuilder builder(*controlFlow, *controlFlow->mainGraph, _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments); builder.m_currentBlock = controlFlow->mainGraph->makeBlock(debugDataOf(_block)); builder.sealBlock(builder.m_currentBlock); builder(_block); @@ -84,7 +83,7 @@ std::unique_ptr SSAControlFlowGraphBuilder::build( return controlFlow; } -SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) +SSACFG::ValueId SSACFGBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) { // TODO: double-check if this is sane auto const* phiInfo = std::get_if(&m_graph.valueInfo(_phi)); @@ -157,7 +156,7 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi(SSACFG::ValueId } /// Removes edges to blocks that are not reachable. -void SSAControlFlowGraphBuilder::cleanUnreachable() +void SSACFGBuilder::cleanUnreachable() { // Determine which blocks are reachable from the entry. util::BreadthFirstSearch reachabilityCheck{{m_graph.entry}}; @@ -201,7 +200,7 @@ void SSAControlFlowGraphBuilder::cleanUnreachable() } } -void SSAControlFlowGraphBuilder::buildFunctionGraph( +void SSACFGBuilder::buildFunctionGraph( Scope::Function const* _function, FunctionDefinition const* _functionDefinition ) @@ -230,7 +229,7 @@ void SSAControlFlowGraphBuilder::buildFunctionGraph( cfg.arguments = arguments; cfg.returns = returns; - SSAControlFlowGraphBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_keepLiteralAssignments); + SSACFGBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_keepLiteralAssignments); builder.m_currentBlock = cfg.entry; builder.m_functionDefinitions = m_functionDefinitions; for (auto&& [var, varId]: cfg.arguments) @@ -245,7 +244,7 @@ void SSAControlFlowGraphBuilder::buildFunctionGraph( builder.cleanUnreachable(); } -void SSAControlFlowGraphBuilder::operator()(ExpressionStatement const& _expressionStatement) +void SSACFGBuilder::operator()(ExpressionStatement const& _expressionStatement) { auto const* functionCall = std::get_if(&_expressionStatement.expression); yulAssert(functionCall); @@ -253,7 +252,7 @@ void SSAControlFlowGraphBuilder::operator()(ExpressionStatement const& _expressi yulAssert(results.empty()); } -void SSAControlFlowGraphBuilder::operator()(Assignment const& _assignment) +void SSACFGBuilder::operator()(Assignment const& _assignment) { assign( _assignment.variableNames | ranges::views::transform([&](auto& _var) { return std::ref(lookupVariable(_var.name)); }) | ranges::to, @@ -261,7 +260,7 @@ void SSAControlFlowGraphBuilder::operator()(Assignment const& _assignment) ); } -void SSAControlFlowGraphBuilder::operator()(VariableDeclaration const& _variableDeclaration) +void SSACFGBuilder::operator()(VariableDeclaration const& _variableDeclaration) { assign( _variableDeclaration.variables | ranges::views::transform([&](auto& _var) { return std::ref(lookupVariable(_var.name)); }) | ranges::to, @@ -269,13 +268,13 @@ void SSAControlFlowGraphBuilder::operator()(VariableDeclaration const& _variable ); } -void SSAControlFlowGraphBuilder::operator()(FunctionDefinition const& _functionDefinition) +void SSACFGBuilder::operator()(FunctionDefinition const& _functionDefinition) { Scope::Function const& function = lookupFunction(_functionDefinition.name); buildFunctionGraph(&function, &_functionDefinition); } -void SSAControlFlowGraphBuilder::operator()(If const& _if) +void SSACFGBuilder::operator()(If const& _if) { std::optional constantCondition; if (auto const* literalCondition = std::get_if(_if.condition.get())) @@ -306,7 +305,7 @@ void SSAControlFlowGraphBuilder::operator()(If const& _if) } } -void SSAControlFlowGraphBuilder::operator()(Switch const& _switch) +void SSACFGBuilder::operator()(Switch const& _switch) { auto expression = std::visit(*this, *_switch.expression); @@ -418,7 +417,7 @@ void SSAControlFlowGraphBuilder::operator()(Switch const& _switch) sealBlock(afterSwitch); } } -void SSAControlFlowGraphBuilder::operator()(ForLoop const& _loop) +void SSACFGBuilder::operator()(ForLoop const& _loop) { ScopedSaveAndRestore scopeRestore(m_scope, m_info.scopes.at(&_loop.pre).get()); (*this)(_loop.pre); @@ -481,7 +480,7 @@ void SSAControlFlowGraphBuilder::operator()(ForLoop const& _loop) m_currentBlock = afterLoop; } -void SSAControlFlowGraphBuilder::operator()(Break const& _break) +void SSACFGBuilder::operator()(Break const& _break) { yulAssert(!m_forLoopInfo.empty()); auto currentBlockDebugData = debugDataOf(currentBlock()); @@ -490,7 +489,7 @@ void SSAControlFlowGraphBuilder::operator()(Break const& _break) sealBlock(m_currentBlock); } -void SSAControlFlowGraphBuilder::operator()(Continue const& _continue) +void SSACFGBuilder::operator()(Continue const& _continue) { yulAssert(!m_forLoopInfo.empty()); auto currentBlockDebugData = debugDataOf(currentBlock()); @@ -499,7 +498,7 @@ void SSAControlFlowGraphBuilder::operator()(Continue const& _continue) sealBlock(m_currentBlock); } -void SSAControlFlowGraphBuilder::operator()(Leave const& _leaveStatement) +void SSACFGBuilder::operator()(Leave const& _leaveStatement) { auto currentBlockDebugData = debugDataOf(currentBlock()); currentBlock().exit = SSACFG::BasicBlock::FunctionReturn{ @@ -512,7 +511,7 @@ void SSAControlFlowGraphBuilder::operator()(Leave const& _leaveStatement) sealBlock(m_currentBlock); } -void SSAControlFlowGraphBuilder::registerFunctionDefinition(FunctionDefinition const& _functionDefinition) +void SSACFGBuilder::registerFunctionDefinition(FunctionDefinition const& _functionDefinition) { yulAssert(m_scope, ""); yulAssert(m_scope->identifiers.count(_functionDefinition.name), ""); @@ -521,7 +520,7 @@ void SSAControlFlowGraphBuilder::registerFunctionDefinition(FunctionDefinition c m_functionDefinitions.emplace_back(&function, &_functionDefinition); } -void SSAControlFlowGraphBuilder::operator()(Block const& _block) +void SSACFGBuilder::operator()(Block const& _block) { ScopedSaveAndRestore saveScope(m_scope, m_info.scopes.at(&_block).get()); // gather all function definitions so that they are visible to each other's subgraphs @@ -535,25 +534,25 @@ void SSAControlFlowGraphBuilder::operator()(Block const& _block) std::visit(*this, statement); } -SSACFG::ValueId SSAControlFlowGraphBuilder::operator()(FunctionCall const& _call) +SSACFG::ValueId SSACFGBuilder::operator()(FunctionCall const& _call) { auto results = visitFunctionCall(_call); yulAssert(results.size() == 1); return results.front(); } -SSACFG::ValueId SSAControlFlowGraphBuilder::operator()(Identifier const& _identifier) +SSACFG::ValueId SSACFGBuilder::operator()(Identifier const& _identifier) { auto const& var = lookupVariable(_identifier.name); return readVariable(var, m_currentBlock); } -SSACFG::ValueId SSAControlFlowGraphBuilder::operator()(Literal const& _literal) +SSACFG::ValueId SSACFGBuilder::operator()(Literal const& _literal) { return m_graph.newLiteral(debugDataOf(currentBlock()), _literal.value.value()); } -void SSAControlFlowGraphBuilder::assign(std::vector> _variables, Expression const* _expression) +void SSACFGBuilder::assign(std::vector> _variables, Expression const* _expression) { auto rhs = [&]() -> std::vector { if (auto const* functionCall = std::get_if(_expression)) @@ -582,7 +581,7 @@ void SSAControlFlowGraphBuilder::assign(std::vector SSAControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _call) +std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const& _call) { bool canContinue = true; SSACFG::Operation operation = std::visit(util::GenericVisitor{ @@ -624,19 +623,19 @@ std::vector SSAControlFlowGraphBuilder::visitFunctionCall(Funct return results; } -SSACFG::ValueId SSAControlFlowGraphBuilder::zero() +SSACFG::ValueId SSACFGBuilder::zero() { return m_graph.newLiteral(debugDataOf(currentBlock()), 0u); } -SSACFG::ValueId SSAControlFlowGraphBuilder::readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block) +SSACFG::ValueId SSACFGBuilder::readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block) { if (auto const& def = currentDef(_variable, _block)) return *def; return readVariableRecursive(_variable, _block); } -SSACFG::ValueId SSAControlFlowGraphBuilder::readVariableRecursive(Scope::Variable const& _variable, SSACFG::BlockId _block) +SSACFG::ValueId SSACFGBuilder::readVariableRecursive(Scope::Variable const& _variable, SSACFG::BlockId _block) { auto& block = m_graph.block(_block); auto& info = blockInfo(_block); @@ -666,7 +665,7 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::readVariableRecursive(Scope::Variabl return val; } -SSACFG::ValueId SSAControlFlowGraphBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi) +SSACFG::ValueId SSACFGBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi) { yulAssert(std::holds_alternative(m_graph.valueInfo(_phi))); auto& phi = std::get(m_graph.valueInfo(_phi)); @@ -676,12 +675,12 @@ SSACFG::ValueId SSAControlFlowGraphBuilder::addPhiOperands(Scope::Variable const return _phi; } -void SSAControlFlowGraphBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value) +void SSACFGBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value) { currentDef(_variable, _block) = _value; } -Scope::Function const& SSAControlFlowGraphBuilder::lookupFunction(YulName _name) const +Scope::Function const& SSACFGBuilder::lookupFunction(YulName _name) const { Scope::Function const* function = nullptr; yulAssert(m_scope->lookup(_name, util::GenericVisitor{ @@ -692,7 +691,7 @@ Scope::Function const& SSAControlFlowGraphBuilder::lookupFunction(YulName _name) return *function; } -Scope::Variable const& SSAControlFlowGraphBuilder::lookupVariable(YulName _name) const +Scope::Variable const& SSACFGBuilder::lookupVariable(YulName _name) const { yulAssert(m_scope, ""); Scope::Variable const* var = nullptr; @@ -710,7 +709,7 @@ Scope::Variable const& SSAControlFlowGraphBuilder::lookupVariable(YulName _name) yulAssert(false, "External identifier access unimplemented."); } -void SSAControlFlowGraphBuilder::sealBlock(SSACFG::BlockId _block) +void SSACFGBuilder::sealBlock(SSACFG::BlockId _block) { // this method deviates from Algorithm 4 in the reference paper, // as it would lead to tryRemoveTrivialPhi being called on unsealed blocks @@ -724,7 +723,7 @@ void SSAControlFlowGraphBuilder::sealBlock(SSACFG::BlockId _block) } -void SSAControlFlowGraphBuilder::conditionalJump( +void SSACFGBuilder::conditionalJump( langutil::DebugData::ConstPtr _debugData, SSACFG::ValueId _condition, SSACFG::BlockId _nonZero, @@ -742,7 +741,7 @@ void SSAControlFlowGraphBuilder::conditionalJump( m_currentBlock = {}; } -void SSAControlFlowGraphBuilder::jump( +void SSACFGBuilder::jump( langutil::DebugData::ConstPtr _debugData, SSACFG::BlockId _target ) @@ -753,7 +752,7 @@ void SSAControlFlowGraphBuilder::jump( m_currentBlock = _target; } -void SSAControlFlowGraphBuilder::tableJump( +void SSACFGBuilder::tableJump( langutil::DebugData::ConstPtr _debugData, SSACFG::ValueId _value, std::map _cases, @@ -770,7 +769,7 @@ void SSAControlFlowGraphBuilder::tableJump( m_currentBlock = {}; } -FunctionDefinition const* SSAControlFlowGraphBuilder::findFunctionDefinition(Scope::Function const* _function) const +FunctionDefinition const* SSACFGBuilder::findFunctionDefinition(Scope::Function const* _function) const { auto it = std::find_if( m_functionDefinitions.begin(), @@ -781,5 +780,3 @@ FunctionDefinition const* SSAControlFlowGraphBuilder::findFunctionDefinition(Sco return std::get<1>(*it); return nullptr; } - -} diff --git a/libyul/backends/evm/SSAControlFlowGraphBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h similarity index 93% rename from libyul/backends/evm/SSAControlFlowGraphBuilder.h rename to libyul/backends/evm/ssa/SSACFGBuilder.h index 8cd214146..7b497db2a 100644 --- a/libyul/backends/evm/SSAControlFlowGraphBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -29,17 +29,17 @@ */ #pragma once +#include #include -#include -#include +#include #include -namespace solidity::yul +namespace solidity::yul::ssa { -class SSAControlFlowGraphBuilder +class SSACFGBuilder { - SSAControlFlowGraphBuilder( + SSACFGBuilder( ControlFlow& _controlFlow, SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, @@ -48,8 +48,8 @@ class SSAControlFlowGraphBuilder bool _keepLiteralAssignments ); public: - SSAControlFlowGraphBuilder(SSAControlFlowGraphBuilder const&) = delete; - SSAControlFlowGraphBuilder& operator=(SSAControlFlowGraphBuilder const&) = delete; + SSACFGBuilder(SSACFGBuilder const&) = delete; + SSACFGBuilder& operator=(SSACFGBuilder const&) = delete; static std::unique_ptr build( AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, diff --git a/libyul/YulControlFlowGraphExporter.cpp b/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp similarity index 86% rename from libyul/YulControlFlowGraphExporter.cpp rename to libyul/backends/evm/ssa/SSACFGJsonExporter.cpp index f0ad055f2..58a72d05a 100644 --- a/libyul/YulControlFlowGraphExporter.cpp +++ b/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp @@ -16,8 +16,8 @@ */ // SPDX-License-Identifier: GPL-3.0 +#include #include -#include #include #include @@ -27,15 +27,13 @@ #include using namespace solidity; -using namespace solidity::langutil; -using namespace solidity::util; -using namespace solidity::yul; +using namespace solidity::yul::ssa; -YulControlFlowGraphExporter::YulControlFlowGraphExporter(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness): m_controlFlow(_controlFlow), m_liveness(_liveness) +SSACFGJsonExporter::SSACFGJsonExporter(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness): m_controlFlow(_controlFlow), m_liveness(_liveness) { } -std::string YulControlFlowGraphExporter::varToString(SSACFG const& _cfg, SSACFG::ValueId _var) +std::string SSACFGJsonExporter::varToString(SSACFG const& _cfg, SSACFG::ValueId _var) { if (_var.value == std::numeric_limits::max()) return std::string("INVALID"); @@ -56,7 +54,7 @@ std::string YulControlFlowGraphExporter::varToString(SSACFG const& _cfg, SSACFG: ); } -Json YulControlFlowGraphExporter::run() +Json SSACFGJsonExporter::run() { if (m_liveness) yulAssert(&m_liveness->controlFlow.get() == &m_controlFlow); @@ -73,7 +71,7 @@ Json YulControlFlowGraphExporter::run() return yulObjectJson; } -Json YulControlFlowGraphExporter::exportFunction(SSACFG const& _cfg, SSACFGLiveness const* _liveness) +Json SSACFGJsonExporter::exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness) { Json functionJson = Json::object(); functionJson["type"] = "Function"; @@ -85,7 +83,7 @@ Json YulControlFlowGraphExporter::exportFunction(SSACFG const& _cfg, SSACFGLiven return functionJson; } -Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, SSACFGLiveness const* _liveness) +Json SSACFGJsonExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis const* _liveness) { Json blocksJson = Json::array(); util::BreadthFirstSearch bfs{{{_entryId}}}; @@ -132,7 +130,7 @@ Json YulControlFlowGraphExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockI return blocksJson; } -Json YulControlFlowGraphExporter::toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness) +Json SSACFGJsonExporter::toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness) { auto const valueToString = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; @@ -174,10 +172,10 @@ Json YulControlFlowGraphExporter::toJson(SSACFG const& _cfg, SSACFG::BlockId _bl return blockJson; } -Json YulControlFlowGraphExporter::toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation) +Json SSACFGJsonExporter::toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation) { Json opJson = Json::object(); - std::visit(GenericVisitor{ + std::visit(util::GenericVisitor{ [&](SSACFG::Call const& _call) { _ret["type"] = "FunctionCall"; @@ -222,7 +220,7 @@ Json YulControlFlowGraphExporter::toJson(Json& _ret, SSACFG const& _cfg, SSACFG: return opJson; } -Json YulControlFlowGraphExporter::toJson(SSACFG const& _cfg, std::vector const& _values) +Json SSACFGJsonExporter::toJson(SSACFG const& _cfg, std::vector const& _values) { Json ret = Json::array(); for (auto const& value: _values) diff --git a/libyul/YulControlFlowGraphExporter.h b/libyul/backends/evm/ssa/SSACFGJsonExporter.h similarity index 72% rename from libyul/YulControlFlowGraphExporter.h rename to libyul/backends/evm/ssa/SSACFGJsonExporter.h index 91f9d040e..719859581 100644 --- a/libyul/YulControlFlowGraphExporter.h +++ b/libyul/backends/evm/ssa/SSACFGJsonExporter.h @@ -18,26 +18,28 @@ #pragma once -#include +#include #include #include -using namespace solidity; -using namespace yul; +namespace solidity::yul::ssa +{ -class YulControlFlowGraphExporter +class SSACFGJsonExporter { public: - YulControlFlowGraphExporter(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness=nullptr); + SSACFGJsonExporter(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness=nullptr); Json run(); - Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness); - Json exportFunction(SSACFG const& _cfg, SSACFGLiveness const* _liveness); + Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness); + Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness); std::string varToString(SSACFG const& _cfg, SSACFG::ValueId _var); private: ControlFlow const& m_controlFlow; ControlFlowLiveness const* m_liveness; - Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, SSACFGLiveness const* _liveness); + Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness); Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation); Json toJson(SSACFG const& _cfg, std::vector const& _values); }; + +} diff --git a/libyul/backends/evm/SSACFGLoopNestingForest.cpp b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp similarity index 96% rename from libyul/backends/evm/SSACFGLoopNestingForest.cpp rename to libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp index b28597813..bbd171a45 100644 --- a/libyul/backends/evm/SSACFGLoopNestingForest.cpp +++ b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp @@ -16,9 +16,9 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#include -using namespace solidity::yul; +using namespace solidity::yul::ssa; SSACFGLoopNestingForest::SSACFGLoopNestingForest(ForwardSSACFGTopologicalSort const& _sort): m_sort(_sort), diff --git a/libyul/backends/evm/SSACFGLoopNestingForest.h b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h similarity index 93% rename from libyul/backends/evm/SSACFGLoopNestingForest.h rename to libyul/backends/evm/ssa/SSACFGLoopNestingForest.h index 0aad6ab39..56cd5ace7 100644 --- a/libyul/backends/evm/SSACFGLoopNestingForest.h +++ b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h @@ -18,8 +18,8 @@ #pragma once -#include -#include +#include +#include #include @@ -27,7 +27,7 @@ #include #include -namespace solidity::yul +namespace solidity::yul::ssa { /// Constructs a loop nesting forest for an SSACFG using Tarjan's algorithm [1]. diff --git a/libyul/backends/evm/SSACFGTopologicalSort.cpp b/libyul/backends/evm/ssa/SSACFGTopologicalSort.cpp similarity index 96% rename from libyul/backends/evm/SSACFGTopologicalSort.cpp rename to libyul/backends/evm/ssa/SSACFGTopologicalSort.cpp index 881e48ea1..222a9774a 100644 --- a/libyul/backends/evm/SSACFGTopologicalSort.cpp +++ b/libyul/backends/evm/ssa/SSACFGTopologicalSort.cpp @@ -16,9 +16,9 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#include -using namespace solidity::yul; +using namespace solidity::yul::ssa; ForwardSSACFGTopologicalSort::ForwardSSACFGTopologicalSort(SSACFG const& _cfg): m_cfg(_cfg), diff --git a/libyul/backends/evm/SSACFGTopologicalSort.h b/libyul/backends/evm/ssa/SSACFGTopologicalSort.h similarity index 96% rename from libyul/backends/evm/SSACFGTopologicalSort.h rename to libyul/backends/evm/ssa/SSACFGTopologicalSort.h index 025054b95..5eb12545d 100644 --- a/libyul/backends/evm/SSACFGTopologicalSort.h +++ b/libyul/backends/evm/ssa/SSACFGTopologicalSort.h @@ -18,13 +18,13 @@ #pragma once -#include +#include #include #include #include -namespace solidity::yul +namespace solidity::yul::ssa { /// Performs a topological sort on the forward CFG (no back/cross edges) diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/SSAControlFlowGraphTest.cpp index 087a79e97..18f1c7c25 100644 --- a/test/libyul/SSAControlFlowGraphTest.cpp +++ b/test/libyul/SSAControlFlowGraphTest.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include @@ -70,13 +70,13 @@ TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::st return TestResult::FatalError; } - std::unique_ptr controlFlow = SSAControlFlowGraphBuilder::build( + std::unique_ptr controlFlow = ssa::SSACFGBuilder::build( *yulStack.parserResult()->analysisInfo, yulStack.dialect(), yulStack.parserResult()->code()->root(), true ); - ControlFlowLiveness liveness(*controlFlow); + ssa::ControlFlowLiveness liveness(*controlFlow); m_obtainedResult = controlFlow->toDot(&liveness); auto result = checkResult(_stream, _linePrefix, _formatted); From 2f5dc0d5fc2bedc268b0979dec0a591f0a197538 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 29 Sep 2025 17:10:09 +0200 Subject: [PATCH 0956/1340] SSA CFG liveness contains (max) variable usage counts. If a variable is referenced downstream, a counter gets incremented. If it gets used different amount of times in different branches, we take the max of these. The number reflects how many times a value is going to be used downstream _at most_. --- libyul/backends/evm/ssa/LivenessAnalysis.cpp | 209 +++++++++++++++--- libyul/backends/evm/ssa/LivenessAnalysis.h | 84 ++++++- libyul/backends/evm/ssa/SSACFG.cpp | 4 +- .../backends/evm/ssa/SSACFGJsonExporter.cpp | 2 +- .../standard_yul_cfg_json_export/output.json | 20 +- test/cmdlineTests/yul_cfg_json_export/output | 20 +- .../libyul/yulSSAControlFlowGraph/complex.yul | 50 ++--- .../yulSSAControlFlowGraph/complex2.yul | 52 ++--- .../default_initialized_variable.yul | 6 +- .../yulSSAControlFlowGraph/function.yul | 8 +- test/libyul/yulSSAControlFlowGraph/if.yul | 6 +- .../yulSSAControlFlowGraph/nested_for.yul | 94 ++++---- .../nested_function.yul | 24 +- test/libyul/yulSSAControlFlowGraph/switch.yul | 12 +- 14 files changed, 399 insertions(+), 192 deletions(-) diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp index 49f077feb..42d2cf39c 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -20,7 +20,10 @@ #include +#include +#include #include + #include #include @@ -28,38 +31,154 @@ using namespace solidity::yul::ssa; namespace { -constexpr auto literalsFilter(SSACFG const& _cfg) +constexpr auto excludingLiteralsFilter(SSACFG const& _cfg) +{ + return [&_cfg](LivenessAnalysis::LivenessData::Value const& _valueId) -> bool + { + return !std::holds_alternative(_cfg.valueInfo(_valueId)); + }; +} +constexpr auto unreachableFilter(SSACFG const& _cfg) { - return [&_cfg](SSACFG::ValueId const& _valueId) -> bool + return [&_cfg](LivenessAnalysis::LivenessData::Value const& _valueId) -> bool { - return !std::holds_alternative(_cfg.valueInfo(_valueId));; + return std::holds_alternative(_cfg.valueInfo(_valueId)); }; } } -std::set LivenessAnalysis::blockExitValues(SSACFG::BlockId const& _blockId) const +bool LivenessAnalysis::LivenessData::contains(Value const& _valueId) const +{ + return findEntry(_valueId) != m_liveCounts.end(); +} + +LivenessAnalysis::LivenessData::Count LivenessAnalysis::LivenessData::count(Value const& _valueId) const +{ + if ( + auto const it = findEntry(_valueId); + it != m_liveCounts.end() + ) + return it->second; + return 0; +} + +LivenessAnalysis::LivenessData::LiveCounts::const_iterator LivenessAnalysis::LivenessData::begin() const +{ + return m_liveCounts.begin(); +} + +LivenessAnalysis::LivenessData::LiveCounts::const_iterator LivenessAnalysis::LivenessData::end() const +{ + return m_liveCounts.end(); +} + +LivenessAnalysis::LivenessData::LiveCounts::size_type LivenessAnalysis::LivenessData::size() const +{ + return m_liveCounts.size(); +} + +bool LivenessAnalysis::LivenessData::empty() const { return m_liveCounts.empty(); } + +void LivenessAnalysis::LivenessData::insert(Value const& _value, Count _count) +{ + if (_count == 0) + return; + + auto it = findEntry(_value); + if (it != m_liveCounts.end()) + it->second += _count; + else + m_liveCounts.emplace_back(_value, _count); +} + +LivenessAnalysis::LivenessData& LivenessAnalysis::LivenessData::maxUnion(LivenessData const& _other) +{ + for (auto const& [value, count]: _other.m_liveCounts) + { + auto it = findEntry(value); + if (it != m_liveCounts.end()) + it->second = std::max(it->second, count); + else + m_liveCounts.emplace_back(value, count); + } + return *this; +} + +LivenessAnalysis::LivenessData& LivenessAnalysis::LivenessData::operator+=(LivenessData const& _other) { - std::set result; - util::GenericVisitor exitVisitor { + for (auto const& [valueId, count]: _other.m_liveCounts) + insert(valueId, count); + return *this; +} + +LivenessAnalysis::LivenessData& LivenessAnalysis::LivenessData::operator-=(LivenessData const& _other) +{ + std::erase_if(m_liveCounts, [&](auto const& entry) { return _other.contains(entry.first); }); + return *this; +} + +void LivenessAnalysis::LivenessData::erase(Value const& _value) +{ + if ( + auto const it = findEntry(_value); + it != m_liveCounts.end() + ) + m_liveCounts.erase(it); +} + +void LivenessAnalysis::LivenessData::remove(Value const& _value, Count _count) +{ + if (_count == 0) + return; + + auto it = findEntry(_value); + if (it != m_liveCounts.end()) + { + if (it->second <= _count) + m_liveCounts.erase(it); + else + it->second -= _count; + } +} + + +LivenessAnalysis::LivenessData LivenessAnalysis::blockExitValues(SSACFG::BlockId const& _blockId) const +{ + LivenessData result; + util::GenericVisitor exitVisitor{ [](SSACFG::BasicBlock::MainExit const&) {}, - [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { - result += _functionReturn.returnValues | ranges::views::filter(literalsFilter(m_cfg)); + [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) + { + for (auto const& valueId: _functionReturn.returnValues | ranges::views::filter(excludingLiteralsFilter(m_cfg))) + result.insert(valueId); }, - [&](SSACFG::BasicBlock::JumpTable const& _jt) { - if (literalsFilter(m_cfg)(_jt.value)) - result.emplace(_jt.value); + [&](SSACFG::BasicBlock::JumpTable const& _jt) + { + if (excludingLiteralsFilter(m_cfg)(_jt.value)) + result.insert(_jt.value); }, [](SSACFG::BasicBlock::Jump const&) {}, - [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { - if (literalsFilter(m_cfg)(_conditionalJump.condition)) - result.emplace(_conditionalJump.condition); + [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) + { + if (excludingLiteralsFilter(m_cfg)(_conditionalJump.condition)) + result.insert(_conditionalJump.condition); }, - [](SSACFG::BasicBlock::Terminated const&) {} - }; + [](SSACFG::BasicBlock::Terminated const&) {}}; std::visit(exitVisitor, m_cfg.block(_blockId).exit); return result; } + +LivenessAnalysis::LivenessData::LiveCounts::iterator LivenessAnalysis::LivenessData::findEntry(Value const& _value) +{ + return ranges::find_if(m_liveCounts, [&](auto const& _entry) { return _entry.first == _value; }); +} + +LivenessAnalysis::LivenessData::LiveCounts::const_iterator LivenessAnalysis::LivenessData::findEntry(Value const& _value) const +{ + return ranges::find_if(m_liveCounts, [&](auto const& _entry) { return _entry.first == _value; }); +} + LivenessAnalysis::LivenessAnalysis(SSACFG const& _cfg): m_cfg(_cfg), m_topologicalSort(_cfg), @@ -75,6 +194,14 @@ LivenessAnalysis::LivenessAnalysis(SSACFG const& _cfg): fillOperationsLiveOut(); } +LivenessAnalysis::LivenessData LivenessAnalysis::used(SSACFG::BlockId const _blockId) const +{ + auto used = liveIn(_blockId); + for (auto const& [valueId, count]: liveOut(_blockId)) + used.remove(valueId, count); + return used; +} + void LivenessAnalysis::runDagDfs() { // SSA Book, Algorithm 9.2 @@ -85,7 +212,7 @@ void LivenessAnalysis::runDagDfs() auto const& block = m_cfg.block(blockId); // live <- PhiUses(B) - std::set live{}; + LivenessData live{}; block.forEachExit( [&](SSACFG::BlockId const& _successor) { @@ -105,15 +232,21 @@ void LivenessAnalysis::runDagDfs() block.forEachExit( [&](SSACFG::BlockId const& _successor) { if (!m_topologicalSort.backEdge(blockId, _successor)) - live += m_liveIns[_successor.value] - m_cfg.block(_successor).phis; + { + // LiveIn(S) - PhiDefs(S) + auto liveInWithoutPhiDefs = m_liveIns[_successor.value]; + for (auto const& phiId: m_cfg.block(_successor).phis) + liveInWithoutPhiDefs.erase(phiId); + live.maxUnion(liveInWithoutPhiDefs); + } }); if (std::holds_alternative(block.exit)) - live += std::get(block.exit).returnValues - | ranges::views::filter(literalsFilter(m_cfg)); + for (auto const& returnValue: std::get(block.exit).returnValues | ranges::views::filter(excludingLiteralsFilter(m_cfg))) + live.insert(returnValue); // clean out unreachables - live = live | ranges::views::filter([&](auto const& valueId) { return !std::holds_alternative(m_cfg.valueInfo(valueId)); }) | ranges::to; + live.eraseIf([&](auto const& _entry) { return unreachableFilter(m_cfg)(_entry.first); }); // LiveOut(B) <- live m_liveOuts[blockId.value] = live; @@ -126,35 +259,39 @@ void LivenessAnalysis::runDagDfs() for (auto const& op: block.operations | ranges::views::reverse) { // remove variables defined at p from live - live -= op.outputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; + live.eraseAll(op.outputs | ranges::views::filter(excludingLiteralsFilter(m_cfg)) | ranges::to); // add uses at p to live - live += op.inputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; + live.insertAll(op.inputs | ranges::views::filter(excludingLiteralsFilter(m_cfg)) | ranges::to); } } // livein(b) <- live \cup PhiDefs(B) - m_liveIns[blockId.value] = live + block.phis; + for (auto const& phi: block.phis) + live.insert(phi); + m_liveIns[blockId.value] = live; } } void LivenessAnalysis::runLoopTreeDfs(size_t const _loopHeader) { // SSA Book, Algorithm 9.3 - if (m_loopNestingForest.loopNodes().count(_loopHeader) > 0) + if (m_loopNestingForest.loopNodes().contains(_loopHeader)) { // the loop header block id auto const& block = m_cfg.block(SSACFG::BlockId{_loopHeader}); // LiveLoop <- LiveIn(B_N) - PhiDefs(B_N) - auto liveLoop = m_liveIns[_loopHeader] - block.phis; + auto liveLoop = m_liveIns[_loopHeader]; + for (auto const& phi: block.phis) + liveLoop.erase(phi); // must be live out of header if live in of children - m_liveOuts[_loopHeader] += liveLoop; + m_liveOuts[_loopHeader].maxUnion(liveLoop); // for each blockId \in children(loopHeader) for (size_t blockIdValue = 0; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) if (m_loopNestingForest.loopParents()[blockIdValue] == _loopHeader) { // propagate loop liveness information down to the loop header's children - m_liveIns[blockIdValue] += liveLoop; - m_liveOuts[blockIdValue] += liveLoop; + m_liveIns[blockIdValue].maxUnion(liveLoop); + m_liveOuts[blockIdValue].maxUnion(liveLoop); runLoopTreeDfs(blockIdValue); } @@ -163,21 +300,23 @@ void LivenessAnalysis::runLoopTreeDfs(size_t const _loopHeader) void LivenessAnalysis::fillOperationsLiveOut() { - for (size_t blockIdValue = 0; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) + for (SSACFG::BlockId blockId{0}; blockId.value < m_cfg.numBlocks(); ++blockId.value) { - SSACFG::BlockId const blockId{blockIdValue}; auto const& operations = m_cfg.block(blockId).operations; - auto& liveOuts = m_operationLiveOuts[blockIdValue]; + auto& liveOuts = m_operationLiveOuts[blockId.value]; liveOuts.resize(operations.size()); if (!operations.empty()) { - auto live = m_liveOuts[blockIdValue] + blockExitValues(blockId); + auto live = m_liveOuts[blockId.value]; + live += blockExitValues(blockId); auto rit = liveOuts.rbegin(); for (auto const& op: operations | ranges::views::reverse) { *rit = live; - live -= op.outputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; - live += op.inputs | ranges::views::filter(literalsFilter(m_cfg)) | ranges::to; + for (auto const& output: op.outputs | ranges::views::filter(excludingLiteralsFilter(m_cfg))) + live.erase(output); + for (auto const& input: op.inputs | ranges::views::filter(excludingLiteralsFilter(m_cfg))) + live.insert(input); ++rit; } } diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.h b/libyul/backends/evm/ssa/LivenessAnalysis.h index 74b7f20fa..6462af86d 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.h +++ b/libyul/backends/evm/ssa/LivenessAnalysis.h @@ -22,8 +22,6 @@ #include #include -#include -#include #include namespace solidity::yul::ssa @@ -35,19 +33,89 @@ namespace solidity::yul::ssa class LivenessAnalysis { public: - using LivenessData = std::set; + class LivenessData + { + public: + using Count = std::uint32_t; + using Value = SSACFG::ValueId; + using LiveCounts = std::vector>; + + LivenessData() = default; + template Sentinel> + LivenessData(Iter begin, Sentinel end): m_liveCounts(begin, end) { + } + explicit LivenessData(LiveCounts&& _liveCounts): m_liveCounts(std::move(_liveCounts)) {} + + bool contains(Value const& _valueId) const; + Count count(Value const& _valueId) const; + LiveCounts::const_iterator begin() const; + LiveCounts::const_iterator end() const; + LiveCounts::size_type size() const; + bool empty() const; + + // Core modification + /// Add value with count (default 1), incrementing if already present + void insert(Value const& _value, Count _count = 1); + /// Remove value completely regardless of count + void erase(Value const& _value); + /// Decrement value count, removing if count reaches zero + void remove(Value const& _value, Count _count = 1); + + // Set operations + /// Add all entries from other, summing counts + LivenessData& operator+=(LivenessData const& _other); + /// Remove all values present in other + LivenessData& operator-=(LivenessData const& _other); + /// Union with other, taking max count for each value + LivenessData& maxUnion(LivenessData const& _other); + + // Bulk operations + /// Insert all values from range with count 1 each + template + void insertAll(Range const& _values) + { + for (auto const& value: _values) + insert(value); + } + + /// Erase all values from range + template + void eraseAll(Range const& _values) + { + for (auto const& value: _values) + erase(value); + } + + // Conditional removal + /// Remove all entries matching predicate + template + void eraseIf(Predicate&& _predicate) + { + std::erase_if(m_liveCounts, std::forward(_predicate)); + } + + private: + LiveCounts::iterator findEntry(Value const& _value); + LiveCounts::const_iterator findEntry(Value const& _value) const; + + /// Usage counts represent the total number of times each variable will be used + /// downstream across all possible execution paths from this program point. + LiveCounts m_liveCounts; + }; explicit LivenessAnalysis(SSACFG const& _cfg); - LivenessData const& liveIn(SSACFG::BlockId _blockId) const { return m_liveIns[_blockId.value]; } - LivenessData const& liveOut(SSACFG::BlockId _blockId) const { return m_liveOuts[_blockId.value]; } + LivenessData const& liveIn(SSACFG::BlockId const _blockId) const { return m_liveIns[_blockId.value]; } + LivenessData const& liveOut(SSACFG::BlockId const _blockId) const { return m_liveOuts[_blockId.value]; } + LivenessData used(SSACFG::BlockId _blockId) const; std::vector const& operationsLiveOut(SSACFG::BlockId _blockId) const { return m_operationLiveOuts[_blockId.value]; } ForwardSSACFGTopologicalSort const& topologicalSort() const { return m_topologicalSort; } -private: + SSACFG const& cfg() const { return m_cfg; } +private: void runDagDfs(); - void runLoopTreeDfs(size_t _loopHeader); + void runLoopTreeDfs(std::size_t _loopHeader); void fillOperationsLiveOut(); - std::set blockExitValues(SSACFG::BlockId const& _blockId) const; + LivenessData blockExitValues(SSACFG::BlockId const& _blockId) const; SSACFG const& m_cfg; ForwardSSACFGTopologicalSort m_topologicalSort; diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 180753424..9a98a08ba 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -145,11 +145,11 @@ class SSACFGPrinter ); m_result << fmt::format( "LiveIn: {}\\l\\\n", - fmt::join(m_liveness->liveIn(_id) | ranges::views::transform(valueToString), ",") + fmt::join(m_liveness->liveIn(_id) | ranges::views::transform([&](auto const& liveIn) { return valueToString(SSACFG::ValueId{liveIn.first}) + fmt::format("[{}]", liveIn.second); }), ", ") ); m_result << fmt::format( "LiveOut: {}\\l\\n", - fmt::join(m_liveness->liveOut(_id) | ranges::views::transform(valueToString), ",") + fmt::join(m_liveness->liveOut(_id) | ranges::views::transform([&](auto const& liveOut) { return valueToString(SSACFG::ValueId{liveOut.first}) + fmt::format("[{}]", liveOut.second); }), ", ") ); } else diff --git a/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp b/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp index 58a72d05a..68f65d377 100644 --- a/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp +++ b/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp @@ -132,7 +132,7 @@ Json SSACFGJsonExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryI Json SSACFGJsonExporter::toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness) { - auto const valueToString = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; + auto const valueToString = [&](LivenessAnalysis::LivenessData::LiveCounts::value_type const& _live) { return varToString(_cfg, _live.first); }; Json blockJson = Json::object(); auto const& block = _cfg.block(_blockId); diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index ac416d331..07b1c3f63 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -901,8 +901,8 @@ ], "out": [ "v0", - "v18", - "v24" + "v24", + "v18" ] }, "type": "BuiltinCall" @@ -992,8 +992,8 @@ "liveness": { "in": [ "v0", - "v18", - "v24" + "v24", + "v18" ], "out": [ "v41" @@ -1238,8 +1238,8 @@ "v59" ], "out": [ - "v46", - "v64" + "v64", + "v46" ] } }, @@ -1393,8 +1393,8 @@ "v46" ], "out": [ - "v46", - "v67" + "v67", + "v46" ] }, "type": "BuiltinCall" @@ -1529,8 +1529,8 @@ "v46" ], "out": [ - "v46", - "v70" + "v70", + "v46" ] }, "type": "BuiltinCall" diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index 1e22b8462..cf93e76fd 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -901,8 +901,8 @@ Yul Control Flow Graph: ], "out": [ "v0", - "v18", - "v24" + "v24", + "v18" ] }, "type": "BuiltinCall" @@ -992,8 +992,8 @@ Yul Control Flow Graph: "liveness": { "in": [ "v0", - "v18", - "v24" + "v24", + "v18" ], "out": [ "v41" @@ -1238,8 +1238,8 @@ Yul Control Flow Graph: "v59" ], "out": [ - "v46", - "v64" + "v64", + "v46" ] } }, @@ -1393,8 +1393,8 @@ Yul Control Flow Graph: "v46" ], "out": [ - "v46", - "v67" + "v67", + "v46" ] }, "type": "BuiltinCall" @@ -1529,8 +1529,8 @@ Yul Control Flow Graph: "v46" ], "out": [ - "v46", - "v70" + "v70", + "v46" ] }, "type": "BuiltinCall" diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index ecb1b7cfe..e4f29d07e 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -62,15 +62,15 @@ // c := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0; (0, max 17)\nLiveIn: v0,v1\l\ -// LiveOut: v0,v1,v4\l\nv4 := 42\l\ +// Block 0; (0, max 17)\nLiveIn: v1[1], v0[1]\l\ +// LiveOut: v4[1], v1[1], v0[1]\l\nv4 := 42\l\ // "]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1; (1, max 17)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6\l\nv6 := φ(\l\ +// Block 1; (1, max 17)\nLiveIn: v6[4], v1[1], v0[1]\l\ +// LiveOut: v6[2], v1[1], v0[1]\l\nv6 := φ(\l\ // Block 0 => v4,\l\ // Block 21 => v44\l\ // )\l\ @@ -81,8 +81,8 @@ // Block1_1Exit:0 -> Block1_4 [style="solid"]; // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2; (2, max 17)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6,v8\l\nv8 := mload(v6)\l\ +// Block 2; (2, max 17)\nLiveIn: v6[2], v1[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v8[3], v0[1]\l\nv8 := mload(v6)\l\ // v9 := eq(0, v8)\l\ // "]; // Block1_2 -> Block1_2Exit; @@ -103,8 +103,8 @@ // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7; (5, max 17)\nLiveIn: v0,v1,v6,v8\l\ -// LiveOut: v0,v1,v6,v8\l\nv14 := eq(1, v8)\l\ +// Block 7; (5, max 17)\nLiveIn: v6[1], v1[1], v8[3], v0[1]\l\ +// LiveOut: v6[1], v1[1], v8[2], v0[1]\l\nv14 := eq(1, v8)\l\ // "]; // Block1_7 -> Block1_7Exit; // Block1_7Exit [label="{ If v14 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -117,8 +117,8 @@ // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10; (7, max 17)\nLiveIn: v0,v1,v6,v8\l\ -// LiveOut: v0,v1,v6,v8\l\nv21 := eq(2, v8)\l\ +// Block 10; (7, max 17)\nLiveIn: v6[1], v1[1], v8[2], v0[1]\l\ +// LiveOut: v6[1], v1[1], v8[1], v0[1]\l\nv21 := eq(2, v8)\l\ // "]; // Block1_10 -> Block1_10Exit; // Block1_10Exit [label="{ If v21 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -132,31 +132,31 @@ // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13; (9, max 17)\nLiveIn: v0,v1,v6,v8\l\ -// LiveOut: v0,v1,v6\l\nv26 := eq(3, v8)\l\ +// Block 13; (9, max 17)\nLiveIn: v6[1], v1[1], v8[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v0[1]\l\nv26 := eq(3, v8)\l\ // "]; // Block1_13 -> Block1_13Exit; // Block1_13Exit [label="{ If v26 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15; (10, max 14)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6\l\nsstore(2056, 8)\l\ +// Block 15; (10, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2056, 8)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16; (15, max 17)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6\l\nv30 := mload(v1)\l\ +// Block 16; (15, max 17)\nLiveIn: v6[1], v1[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v0[1]\l\nv30 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; // Block1_16Exit [label="{ If v30 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5; (11, max 14)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6\l\nsstore(2827, 11)\l\ +// Block 5; (11, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2827, 11)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; @@ -168,15 +168,15 @@ // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18; (17, max 17)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6\l\nsstore(2570, 10)\l\ +// Block 18; (17, max 17)\nLiveIn: v6[1], v1[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2570, 10)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3; (12, max 14)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v44\l\nv44 := add(1, v6)\l\ +// Block 3; (12, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ +// LiveOut: v44[1], v1[1], v0[1]\l\nv44 := add(1, v6)\l\ // v45 := calldataload(v44)\l\ // "]; // Block1_3 -> Block1_3Exit; @@ -184,14 +184,14 @@ // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v44\l\ +// Block 20; (13, max 13)\nLiveIn: v44[1]\l\ // LiveOut: \l\nsstore(v44, 0)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v0,v1,v44\l\ -// LiveOut: v0,v1,v44\l\nsstore(65535, 255)\l\ +// Block 21; (14, max 14)\nLiveIn: v44[1], v1[1], v0[1]\l\ +// LiveOut: v44[1], v1[1], v0[1]\l\nsstore(65535, 255)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index d4e8b432d..6e94670ba 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -78,15 +78,15 @@ // c := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0; (0, max 17)\nLiveIn: v0,v1\l\ -// LiveOut: v0,v1,v4\l\nv4 := 42\l\ +// Block 0; (0, max 17)\nLiveIn: v1[1], v0[1]\l\ +// LiveOut: v4[1], v1[1], v0[1]\l\nv4 := 42\l\ // "]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1; (1, max 17)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6\l\nv6 := φ(\l\ +// Block 1; (1, max 17)\nLiveIn: v6[4], v1[1], v0[1]\l\ +// LiveOut: v6[2], v1[1], v0[1]\l\nv6 := φ(\l\ // Block 0 => v4,\l\ // Block 21 => v44\l\ // )\l\ @@ -97,8 +97,8 @@ // Block1_1Exit:0 -> Block1_4 [style="solid"]; // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2; (2, max 17)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6,v8\l\nv8 := mload(v6)\l\ +// Block 2; (2, max 17)\nLiveIn: v6[2], v1[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v8[3], v0[1]\l\nv8 := mload(v6)\l\ // v9 := eq(0, v8)\l\ // "]; // Block1_2 -> Block1_2Exit; @@ -107,7 +107,7 @@ // Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ // Block 4; (4, max 4)\nLiveIn: \l\ -// LiveOut: v78\l\nsstore(3084, 12)\l\ +// LiveOut: v78[1]\l\nsstore(3084, 12)\l\ // v78 := 27\l\ // "]; // Block1_4Exit [label="FunctionReturn[v78]"]; @@ -120,8 +120,8 @@ // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7; (5, max 17)\nLiveIn: v0,v1,v6,v8\l\ -// LiveOut: v0,v1,v6,v8\l\nv14 := eq(1, v8)\l\ +// Block 7; (5, max 17)\nLiveIn: v6[1], v1[1], v8[3], v0[1]\l\ +// LiveOut: v6[1], v1[1], v8[2], v0[1]\l\nv14 := eq(1, v8)\l\ // "]; // Block1_7 -> Block1_7Exit; // Block1_7Exit [label="{ If v14 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -134,8 +134,8 @@ // Block1_9Exit [label="FunctionReturn[0]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10; (7, max 17)\nLiveIn: v0,v1,v6,v8\l\ -// LiveOut: v0,v1,v6,v8\l\nv21 := eq(2, v8)\l\ +// Block 10; (7, max 17)\nLiveIn: v6[1], v1[1], v8[2], v0[1]\l\ +// LiveOut: v6[1], v1[1], v8[1], v0[1]\l\nv21 := eq(2, v8)\l\ // "]; // Block1_10 -> Block1_10Exit; // Block1_10Exit [label="{ If v21 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; @@ -149,31 +149,31 @@ // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13; (9, max 17)\nLiveIn: v0,v1,v6,v8\l\ -// LiveOut: v0,v1,v6\l\nv26 := eq(3, v8)\l\ +// Block 13; (9, max 17)\nLiveIn: v6[1], v1[1], v8[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v0[1]\l\nv26 := eq(3, v8)\l\ // "]; // Block1_13 -> Block1_13Exit; // Block1_13Exit [label="{ If v26 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15; (10, max 14)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6\l\nsstore(2056, 8)\l\ +// Block 15; (10, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2056, 8)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16; (15, max 17)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6\l\nv30 := mload(v1)\l\ +// Block 16; (15, max 17)\nLiveIn: v6[1], v1[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v0[1]\l\nv30 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; // Block1_16Exit [label="{ If v30 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5; (11, max 14)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6\l\nsstore(2827, 11)\l\ +// Block 5; (11, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2827, 11)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; @@ -185,15 +185,15 @@ // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18; (17, max 17)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v6\l\nsstore(2570, 10)\l\ +// Block 18; (17, max 17)\nLiveIn: v6[1], v1[1], v0[1]\l\ +// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2570, 10)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3; (12, max 14)\nLiveIn: v0,v1,v6\l\ -// LiveOut: v0,v1,v44\l\nv44 := add(1, v6)\l\ +// Block 3; (12, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ +// LiveOut: v44[1], v1[1], v0[1]\l\nv44 := add(1, v6)\l\ // v45 := calldataload(v44)\l\ // "]; // Block1_3 -> Block1_3Exit; @@ -201,14 +201,14 @@ // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v44\l\ +// Block 20; (13, max 13)\nLiveIn: v44[1]\l\ // LiveOut: \l\nsstore(v44, 0)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v0,v1,v44\l\ -// LiveOut: v0,v1,v44\l\nsstore(65535, 255)\l\ +// Block 21; (14, max 14)\nLiveIn: v44[1], v1[1], v0[1]\l\ +// LiveOut: v44[1], v1[1], v0[1]\l\nsstore(65535, 255)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul b/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul index 92ea33382..799bd94ca 100644 --- a/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul +++ b/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul @@ -15,7 +15,7 @@ // Entry0 -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: v1\l\nv1 := 0\l\ +// LiveOut: v1[1]\l\nv1 := 0\l\ // v3 := mload(42)\l\ // "]; // Block0_0 -> Block0_0Exit; @@ -24,13 +24,13 @@ // Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v5\l\nv5 := 5\l\ +// LiveOut: v5[1]\l\nv5 := 5\l\ // "]; // Block0_1 -> Block0_1Exit [arrowhead=none]; // Block0_1Exit [label="Jump" shape=oval]; // Block0_1Exit -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: v6\l\ +// Block 2; (2, max 2)\nLiveIn: v6[3]\l\ // LiveOut: \l\nv6 := φ(\l\ // Block 0 => v1,\l\ // Block 1 => v5\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/yulSSAControlFlowGraph/function.yul index e2d8c1d52..e12583676 100644 --- a/test/libyul/yulSSAControlFlowGraph/function.yul +++ b/test/libyul/yulSSAControlFlowGraph/function.yul @@ -37,8 +37,8 @@ // r := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0; (0, max 0)\nLiveIn: v0,v1\l\ -// LiveOut: v4\l\nv3 := add(v1, v0)\l\ +// Block 0; (0, max 0)\nLiveIn: v0[2], v1[1]\l\ +// LiveOut: v4[1]\l\nv3 := add(v1, v0)\l\ // v4 := sub(v0, v3)\l\ // "]; // Block1_0Exit [label="FunctionReturn[v4]"]; @@ -56,7 +56,7 @@ // h(v0)"]; // FunctionEntry_h_0 -> Block3_0; // Block3_0 [label="\ -// Block 0; (0, max 0)\nLiveIn: v0\l\ +// Block 0; (0, max 0)\nLiveIn: v0[1]\l\ // LiveOut: \l\nv2 := f(0, v0)\l\ // h(v2)\l\ // "]; @@ -67,7 +67,7 @@ // FunctionEntry_i_0 -> Block4_0; // Block4_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v2,v4\l\nv2 := 514\l\ +// LiveOut: v2[1], v4[1]\l\nv2 := 514\l\ // v4 := 771\l\ // "]; // Block4_0Exit [label="FunctionReturn[v2, v4]"]; diff --git a/test/libyul/yulSSAControlFlowGraph/if.yul b/test/libyul/yulSSAControlFlowGraph/if.yul index f8639b2cc..16fc8957d 100644 --- a/test/libyul/yulSSAControlFlowGraph/if.yul +++ b/test/libyul/yulSSAControlFlowGraph/if.yul @@ -16,7 +16,7 @@ // Entry0 -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: v1\l\nv1 := calldataload(3)\l\ +// LiveOut: v1[1]\l\nv1 := calldataload(3)\l\ // v3 := mload(42)\l\ // "]; // Block0_0 -> Block0_0Exit; @@ -25,13 +25,13 @@ // Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v5\l\nv5 := calldataload(77)\l\ +// LiveOut: v5[1]\l\nv5 := calldataload(77)\l\ // "]; // Block0_1 -> Block0_1Exit [arrowhead=none]; // Block0_1Exit [label="Jump" shape=oval]; // Block0_1Exit -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: v6\l\ +// Block 2; (2, max 2)\nLiveIn: v6[2]\l\ // LiveOut: \l\nv6 := φ(\l\ // Block 0 => v1,\l\ // Block 1 => v5\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/yulSSAControlFlowGraph/nested_for.yul index 6efb3552a..8d5060951 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_for.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_for.yul @@ -27,14 +27,14 @@ // Entry0 -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 24)\nLiveIn: \l\ -// LiveOut: v1\l\nv1 := 0\l\ +// LiveOut: v1[1]\l\nv1 := 0\l\ // "]; // Block0_0 -> Block0_0Exit [arrowhead=none]; // Block0_0Exit [label="Jump" shape=oval]; // Block0_0Exit -> Block0_1 [style="solid"]; // Block0_1 [label="\ -// Block 1; (1, max 24)\nLiveIn: v3\l\ -// LiveOut: v3\l\nv3 := φ(\l\ +// Block 1; (1, max 24)\nLiveIn: v3[3]\l\ +// LiveOut: v3[1]\l\nv3 := φ(\l\ // Block 0 => v1,\l\ // Block 3 => v43\l\ // )\l\ @@ -45,8 +45,8 @@ // Block0_1Exit:0 -> Block0_4 [style="solid"]; // Block0_1Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2; (2, max 23)\nLiveIn: v3\l\ -// LiveOut: v3,v5\l\nv5 := 0\l\ +// Block 2; (2, max 23)\nLiveIn: v3[1]\l\ +// LiveOut: v5[1], v3[1]\l\nv5 := 0\l\ // "]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; @@ -57,8 +57,8 @@ // Block0_4Exit [label="MainExit"]; // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ -// Block 5; (3, max 23)\nLiveIn: v3,v6\l\ -// LiveOut: v3,v6\l\nv6 := φ(\l\ +// Block 5; (3, max 23)\nLiveIn: v6[3], v3[1]\l\ +// LiveOut: v6[1], v3[1]\l\nv6 := φ(\l\ // Block 2 => v5,\l\ // Block 7 => v42\l\ // )\l\ @@ -69,21 +69,21 @@ // Block0_5Exit:0 -> Block0_8 [style="solid"]; // Block0_5Exit:1 -> Block0_6 [style="solid"]; // Block0_6 [label="\ -// Block 6; (4, max 21)\nLiveIn: v3,v6\l\ -// LiveOut: v3,v6,v8\l\nv8 := 0\l\ +// Block 6; (4, max 21)\nLiveIn: v6[1], v3[1]\l\ +// LiveOut: v8[1], v6[1], v3[1]\l\nv8 := 0\l\ // "]; // Block0_6 -> Block0_6Exit [arrowhead=none]; // Block0_6Exit [label="Jump" shape=oval]; // Block0_6Exit -> Block0_9 [style="solid"]; // Block0_8 [label="\ -// Block 8; (22, max 23)\nLiveIn: v3\l\ -// LiveOut: v3\l\n"]; +// Block 8; (22, max 23)\nLiveIn: v3[1]\l\ +// LiveOut: v3[1]\l\n"]; // Block0_8 -> Block0_8Exit [arrowhead=none]; // Block0_8Exit [label="Jump" shape=oval]; // Block0_8Exit -> Block0_3 [style="solid"]; // Block0_9 [label="\ -// Block 9; (5, max 21)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9\l\nv9 := φ(\l\ +// Block 9; (5, max 21)\nLiveIn: v9[3], v6[1], v3[1]\l\ +// LiveOut: v9[1], v6[1], v3[1]\l\nv9 := φ(\l\ // Block 6 => v8,\l\ // Block 11 => v38\l\ // )\l\ @@ -94,51 +94,51 @@ // Block0_9Exit:0 -> Block0_12 [style="solid"]; // Block0_9Exit:1 -> Block0_10 [style="solid"]; // Block0_3 [label="\ -// Block 3; (23, max 23)\nLiveIn: v3\l\ -// LiveOut: v43\l\nv43 := add(1, v3)\l\ +// Block 3; (23, max 23)\nLiveIn: v3[1]\l\ +// LiveOut: v43[1]\l\nv43 := add(1, v3)\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; // Block0_3Exit -> Block0_1 [style="dashed"]; // Block0_10 [label="\ -// Block 10; (6, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9\l\nv11 := mload(0)\l\ +// Block 10; (6, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ +// LiveOut: v9[1], v6[1], v3[1]\l\nv11 := mload(0)\l\ // "]; // Block0_10 -> Block0_10Exit; // Block0_10Exit [label="{ If v11 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_10Exit:0 -> Block0_14 [style="solid"]; // Block0_10Exit:1 -> Block0_13 [style="solid"]; // Block0_12 [label="\ -// Block 12; (20, max 21)\nLiveIn: v3,v6\l\ -// LiveOut: v3,v6\l\n"]; +// Block 12; (20, max 21)\nLiveIn: v6[1], v3[1]\l\ +// LiveOut: v6[1], v3[1]\l\n"]; // Block0_12 -> Block0_12Exit [arrowhead=none]; // Block0_12Exit [label="Jump" shape=oval]; // Block0_12Exit -> Block0_7 [style="solid"]; // Block0_13 [label="\ -// Block 13; (7, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9,v12\l\nv12 := 0\l\ +// Block 13; (7, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ +// LiveOut: v12[1], v9[1], v6[1], v3[1]\l\nv12 := 0\l\ // "]; // Block0_13 -> Block0_13Exit [arrowhead=none]; // Block0_13Exit [label="Jump" shape=oval]; // Block0_13Exit -> Block0_15 [style="solid"]; // Block0_14 [label="\ -// Block 14; (12, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9\l\nv24 := mload(1)\l\ +// Block 14; (12, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ +// LiveOut: v9[1], v6[1], v3[1]\l\nv24 := mload(1)\l\ // "]; // Block0_14 -> Block0_14Exit; // Block0_14Exit [label="{ If v24 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_14Exit:0 -> Block0_20 [style="solid"]; // Block0_14Exit:1 -> Block0_19 [style="solid"]; // Block0_7 [label="\ -// Block 7; (21, max 21)\nLiveIn: v3,v6\l\ -// LiveOut: v3,v42\l\nv42 := add(1, v6)\l\ +// Block 7; (21, max 21)\nLiveIn: v6[1], v3[1]\l\ +// LiveOut: v42[1], v3[1]\l\nv42 := add(1, v6)\l\ // "]; // Block0_7 -> Block0_7Exit [arrowhead=none]; // Block0_7Exit [label="Jump" shape=oval]; // Block0_7Exit -> Block0_5 [style="dashed"]; // Block0_15 [label="\ -// Block 15; (8, max 19)\nLiveIn: v3,v6,v9,v13\l\ -// LiveOut: v3,v6,v9,v13\l\nv13 := φ(\l\ +// Block 15; (8, max 19)\nLiveIn: v13[4], v9[1], v6[1], v3[1]\l\ +// LiveOut: v13[2], v9[1], v6[1], v3[1]\l\nv13 := φ(\l\ // Block 13 => v12,\l\ // Block 17 => v21\l\ // )\l\ @@ -149,21 +149,21 @@ // Block0_15Exit:0 -> Block0_18 [style="solid"]; // Block0_15Exit:1 -> Block0_16 [style="solid"]; // Block0_19 [label="\ -// Block 19; (13, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9,v25\l\nv25 := 0\l\ +// Block 19; (13, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ +// LiveOut: v25[1], v9[1], v6[1], v3[1]\l\nv25 := 0\l\ // "]; // Block0_19 -> Block0_19Exit [arrowhead=none]; // Block0_19Exit [label="Jump" shape=oval]; // Block0_19Exit -> Block0_21 [style="solid"]; // Block0_20 [label="\ -// Block 20; (18, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9\l\n"]; +// Block 20; (18, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ +// LiveOut: v9[1], v6[1], v3[1]\l\n"]; // Block0_20 -> Block0_20Exit [arrowhead=none]; // Block0_20Exit [label="Jump" shape=oval]; // Block0_20Exit -> Block0_11 [style="solid"]; // Block0_16 [label="\ -// Block 16; (9, max 10)\nLiveIn: v3,v6,v9,v13\l\ -// LiveOut: v3,v6,v9,v13\l\nv18 := add(v6, v3)\l\ +// Block 16; (9, max 10)\nLiveIn: v13[2], v9[1], v6[1], v3[1]\l\ +// LiveOut: v13[1], v9[1], v6[1], v3[1]\l\nv18 := add(v6, v3)\l\ // v19 := add(v9, v18)\l\ // sstore(v19, v13)\l\ // "]; @@ -171,14 +171,14 @@ // Block0_16Exit [label="Jump" shape=oval]; // Block0_16Exit -> Block0_17 [style="solid"]; // Block0_18 [label="\ -// Block 18; (11, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9\l\n"]; +// Block 18; (11, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ +// LiveOut: v9[1], v6[1], v3[1]\l\n"]; // Block0_18 -> Block0_18Exit [arrowhead=none]; // Block0_18Exit [label="Jump" shape=oval]; // Block0_18Exit -> Block0_14 [style="solid"]; // Block0_21 [label="\ -// Block 21; (14, max 19)\nLiveIn: v3,v6,v9,v26\l\ -// LiveOut: v3,v6,v9,v26\l\nv26 := φ(\l\ +// Block 21; (14, max 19)\nLiveIn: v26[4], v9[1], v6[1], v3[1]\l\ +// LiveOut: v26[2], v9[1], v6[1], v3[1]\l\nv26 := φ(\l\ // Block 19 => v25,\l\ // Block 23 => v33\l\ // )\l\ @@ -189,22 +189,22 @@ // Block0_21Exit:0 -> Block0_24 [style="solid"]; // Block0_21Exit:1 -> Block0_22 [style="solid"]; // Block0_11 [label="\ -// Block 11; (19, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v38\l\nv38 := add(1, v9)\l\ +// Block 11; (19, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ +// LiveOut: v38[1], v6[1], v3[1]\l\nv38 := add(1, v9)\l\ // "]; // Block0_11 -> Block0_11Exit [arrowhead=none]; // Block0_11Exit [label="Jump" shape=oval]; // Block0_11Exit -> Block0_9 [style="dashed"]; // Block0_17 [label="\ -// Block 17; (10, max 10)\nLiveIn: v3,v6,v9,v13\l\ -// LiveOut: v3,v6,v9,v21\l\nv21 := add(1, v13)\l\ +// Block 17; (10, max 10)\nLiveIn: v13[1], v9[1], v6[1], v3[1]\l\ +// LiveOut: v21[1], v9[1], v6[1], v3[1]\l\nv21 := add(1, v13)\l\ // "]; // Block0_17 -> Block0_17Exit [arrowhead=none]; // Block0_17Exit [label="Jump" shape=oval]; // Block0_17Exit -> Block0_15 [style="dashed"]; // Block0_22 [label="\ -// Block 22; (15, max 16)\nLiveIn: v3,v6,v9,v26\l\ -// LiveOut: v3,v6,v9,v26\l\nv31 := add(v6, v3)\l\ +// Block 22; (15, max 16)\nLiveIn: v26[2], v9[1], v6[1], v3[1]\l\ +// LiveOut: v26[1], v9[1], v6[1], v3[1]\l\nv31 := add(v6, v3)\l\ // v32 := add(v9, v31)\l\ // sstore(v32, v26)\l\ // "]; @@ -212,14 +212,14 @@ // Block0_22Exit [label="Jump" shape=oval]; // Block0_22Exit -> Block0_23 [style="solid"]; // Block0_24 [label="\ -// Block 24; (17, max 19)\nLiveIn: v3,v6,v9\l\ -// LiveOut: v3,v6,v9\l\n"]; +// Block 24; (17, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ +// LiveOut: v9[1], v6[1], v3[1]\l\n"]; // Block0_24 -> Block0_24Exit [arrowhead=none]; // Block0_24Exit [label="Jump" shape=oval]; // Block0_24Exit -> Block0_20 [style="solid"]; // Block0_23 [label="\ -// Block 23; (16, max 16)\nLiveIn: v3,v6,v9,v26\l\ -// LiveOut: v3,v6,v9,v33\l\nv33 := add(1, v26)\l\ +// Block 23; (16, max 16)\nLiveIn: v26[1], v9[1], v6[1], v3[1]\l\ +// LiveOut: v33[1], v9[1], v6[1], v3[1]\l\nv33 := add(1, v26)\l\ // "]; // Block0_23 -> Block0_23Exit [arrowhead=none]; // Block0_23Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/nested_function.yul b/test/libyul/yulSSAControlFlowGraph/nested_function.yul index 037e1f006..4387e54aa 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_function.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_function.yul @@ -46,8 +46,8 @@ // r := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// Block 0; (0, max 0)\nLiveIn: v0,v1\l\ -// LiveOut: v4\l\nv3 := add(v1, v0)\l\ +// Block 0; (0, max 0)\nLiveIn: v0[2], v1[1]\l\ +// LiveOut: v4[1]\l\nv3 := add(v1, v0)\l\ // v4 := sub(v0, v3)\l\ // "]; // Block1_0Exit [label="FunctionReturn[v4]"]; @@ -69,7 +69,7 @@ // FunctionEntry_z_0 -> Block3_0; // Block3_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v1\l\nv1 := w()\l\ +// LiveOut: v1[1]\l\nv1 := w()\l\ // "]; // Block3_0Exit [label="FunctionReturn[v1]"]; // Block3_0 -> Block3_0Exit; @@ -78,7 +78,7 @@ // FunctionEntry_w_0 -> Block4_0; // Block4_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v2\l\nv2 := 1\l\ +// LiveOut: v2[1]\l\nv2 := 1\l\ // "]; // Block4_0Exit [label="FunctionReturn[v2]"]; // Block4_0 -> Block4_0Exit; @@ -87,7 +87,7 @@ // FunctionEntry_v_0 -> Block5_0; // Block5_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v1\l\nv1 := w()\l\ +// LiveOut: v1[1]\l\nv1 := w()\l\ // "]; // Block5_0Exit [label="FunctionReturn[v1]"]; // Block5_0 -> Block5_0Exit; @@ -96,7 +96,7 @@ // FunctionEntry_w_0 -> Block6_0; // Block6_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v2\l\nv2 := 17\l\ +// LiveOut: v2[1]\l\nv2 := 17\l\ // "]; // Block6_0Exit [label="FunctionReturn[v2]"]; // Block6_0 -> Block6_0Exit; @@ -113,14 +113,14 @@ // Block7_0Exit:1 -> Block7_1 [style="solid"]; // Block7_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v3\l\nv3 := cycle2()\l\ +// LiveOut: v3[1]\l\nv3 := cycle2()\l\ // "]; // Block7_1 -> Block7_1Exit [arrowhead=none]; // Block7_1Exit [label="Jump" shape=oval]; // Block7_1Exit -> Block7_2 [style="solid"]; // Block7_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: v4\l\ -// LiveOut: v4\l\nv4 := φ(\l\ +// Block 2; (2, max 2)\nLiveIn: v4[3]\l\ +// LiveOut: v4[1]\l\nv4 := φ(\l\ // Block 0 => 0,\l\ // Block 1 => v3\l\ // )\l\ @@ -140,14 +140,14 @@ // Block8_0Exit:1 -> Block8_1 [style="solid"]; // Block8_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v3\l\nv3 := cycle1()\l\ +// LiveOut: v3[1]\l\nv3 := cycle1()\l\ // "]; // Block8_1 -> Block8_1Exit [arrowhead=none]; // Block8_1Exit [label="Jump" shape=oval]; // Block8_1Exit -> Block8_2 [style="solid"]; // Block8_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: v4\l\ -// LiveOut: v4\l\nv4 := φ(\l\ +// Block 2; (2, max 2)\nLiveIn: v4[3]\l\ +// LiveOut: v4[1]\l\nv4 := φ(\l\ // Block 0 => 0,\l\ // Block 1 => v3\l\ // )\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/switch.yul b/test/libyul/yulSSAControlFlowGraph/switch.yul index 10573b012..5a670467e 100644 --- a/test/libyul/yulSSAControlFlowGraph/switch.yul +++ b/test/libyul/yulSSAControlFlowGraph/switch.yul @@ -23,7 +23,7 @@ // Entry0 -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 5)\nLiveIn: \l\ -// LiveOut: v3\l\nv1 := calldataload(3)\l\ +// LiveOut: v3[1]\l\nv1 := calldataload(3)\l\ // v3 := sload(0)\l\ // v4 := eq(0, v3)\l\ // "]; @@ -33,13 +33,13 @@ // Block0_0Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ // Block 2; (1, max 2)\nLiveIn: \l\ -// LiveOut: v6\l\nv6 := calldataload(77)\l\ +// LiveOut: v6[1]\l\nv6 := calldataload(77)\l\ // "]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; // Block0_2Exit -> Block0_1 [style="solid"]; // Block0_3 [label="\ -// Block 3; (3, max 5)\nLiveIn: v3\l\ +// Block 3; (3, max 5)\nLiveIn: v3[1]\l\ // LiveOut: \l\nv7 := eq(1, v3)\l\ // "]; // Block0_3 -> Block0_3Exit; @@ -47,7 +47,7 @@ // Block0_3Exit:0 -> Block0_5 [style="solid"]; // Block0_3Exit:1 -> Block0_4 [style="solid"]; // Block0_1 [label="\ -// Block 1; (2, max 2)\nLiveIn: v13\l\ +// Block 1; (2, max 2)\nLiveIn: v13[2]\l\ // LiveOut: \l\nv13 := φ(\l\ // Block 2 => v6,\l\ // Block 4 => v10,\l\ @@ -59,14 +59,14 @@ // Block0_1 -> Block0_1Exit; // Block0_4 [label="\ // Block 4; (4, max 4)\nLiveIn: \l\ -// LiveOut: v10\l\nv10 := calldataload(88)\l\ +// LiveOut: v10[1]\l\nv10 := calldataload(88)\l\ // "]; // Block0_4 -> Block0_4Exit [arrowhead=none]; // Block0_4Exit [label="Jump" shape=oval]; // Block0_4Exit -> Block0_1 [style="solid"]; // Block0_5 [label="\ // Block 5; (5, max 5)\nLiveIn: \l\ -// LiveOut: v12\l\nv12 := calldataload(99)\l\ +// LiveOut: v12[1]\l\nv12 := calldataload(99)\l\ // "]; // Block0_5 -> Block0_5Exit [arrowhead=none]; // Block0_5Exit [label="Jump" shape=oval]; From 4baeaa02c4a05e1aede29fb00f55a80d8b27cff6 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 6 Oct 2025 15:01:16 +0200 Subject: [PATCH 0957/1340] docs: ignore sphinx syntax warnings --- docs/conf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index 44da93dba..3f7dc3e35 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -172,6 +172,10 @@ def get_github_username_repo(url): # If true, keep warnings as "system message" paragraphs in the built documents. #keep_warnings = False +suppress_warnings = [ + # Suppress sphinx-syntax warnings, in particular `diagram descriptions can't have custom resolver_data` + 'sphinx_syntax', +] # -- Options for HTML output ---------------------------------------------- From e734de85b7ab1ccf1638d83caf07a1e30b3a5dfc Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 7 Oct 2025 08:57:53 +0200 Subject: [PATCH 0958/1340] ci: bump macos.m1.medium.gen1 with xcode 15.0.0 to macos.m4pro.medium with xcode 15.4.0 --- .circleci/config.yml | 8 ++++---- .circleci/osx_install_dependencies.sh | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 076c7b8d1..cf0857942 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -514,12 +514,12 @@ defaults: - base_osx: &base_osx macos: - xcode: "15.0.0" - resource_class: macos.m1.medium.gen1 + xcode: 15.4.0 + resource_class: m4pro.medium environment: &base_osx_env TERM: xterm - MAKEFLAGS: -j5 - CPUs: 5 + MAKEFLAGS: -j8 + CPUs: 8 - base_ubuntu_clang: &base_ubuntu_clang docker: diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index f47e08210..b449c4781 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -48,8 +48,6 @@ function validate_checksum { if [ ! -f /usr/local/lib/libz3.a ] # if this file does not exists (cache was not restored), rebuild dependencies then - brew uninstall temurin17 - brew untap homebrew/homebrew-cask-versions brew update brew upgrade brew install cmake From 11614754832d85cc7f739c895690fd88236fa5c1 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 8 Oct 2025 08:00:43 +0200 Subject: [PATCH 0959/1340] Bump zeppelin node version to lts --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index cf0857942..48d86a97c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -744,7 +744,7 @@ defaults: name: t_native_test_ext_zeppelin project: zeppelin binary_type: native - image: cimg/node:18.16 + image: cimg/node:lts resource_class: large - job_native_test_ext_ens: &job_native_test_ext_ens From 173a5341ac87709db612315f8809ef5784932954 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 6 Oct 2025 11:25:04 +0200 Subject: [PATCH 0960/1340] testing: run yul optimizer tests on all code subobjects --- test/libyul/YulOptimizerTestCommon.cpp | 24 +++++++----- .../fullSuite/sub_objects.yul | 39 +++++++++++++++++++ 2 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 test/libyul/yulOptimizerTests/fullSuite/sub_objects.yul diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 19b2176c1..cd54318c1 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -66,6 +66,8 @@ #include +#include + #include using namespace solidity; @@ -81,15 +83,6 @@ YulOptimizerTestCommon::YulOptimizerTestCommon(std::shared_ptr _ob { soltestAssert(m_object && m_optimizedObject); - if ( - std::any_of( - m_object->subObjects.begin(), - m_object->subObjects.end(), - [](auto const& subObject) { return dynamic_cast(subObject.get()) == nullptr;} - ) - ) - solUnimplemented("The current implementation of YulOptimizerTests ignores subobjects that are not Data."); - m_namedSteps = { {"disambiguator", [&]() { return disambiguate(); }}, {"nameDisplacer", [&]() { @@ -496,8 +489,19 @@ void YulOptimizerTestCommon::setStep(std::string const& _optimizerStep) bool YulOptimizerTestCommon::runStep() { - if (m_namedSteps.count(m_optimizerStep)) + if (m_namedSteps.contains(m_optimizerStep)) { + for (auto const& [ix, subNode]: m_object->subObjects | ranges::views::enumerate) + if (auto const subObject = std::dynamic_pointer_cast(subNode)) + { + YulOptimizerTestCommon subTest(subObject); + subTest.setStep(m_optimizerStep); + subTest.run(); + auto const optimizedSubObject = std::dynamic_pointer_cast(m_optimizedObject->subObjects[ix]); + yulAssert(optimizedSubObject); + optimizedSubObject->setCode(subTest.m_optimizedObject->code()); + } + auto block = m_namedSteps[m_optimizerStep](); m_optimizedObject->setCode(std::make_shared(*m_object->dialect(), std::move(block))); } diff --git a/test/libyul/yulOptimizerTests/fullSuite/sub_objects.yul b/test/libyul/yulOptimizerTests/fullSuite/sub_objects.yul new file mode 100644 index 000000000..08c64fd4c --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/sub_objects.yul @@ -0,0 +1,39 @@ +// nested object to show that optimizations are applied at all levels +object "A" { + code + { + mstore(43, 33) // removed by optimizer as it's transient and otherwise unused + } + + object "B" + { + code + { + let y := 42 + sstore(y, y) // persists + mstore(y, y) // removed + } + + object "C" + { + code + { + let x := 55 + sstore(x, x) // persists + mstore(x, x) // removed + } + } + } +} +// ---- +// step: fullSuite +// +// object "A" { +// code { { } } +// object "B" { +// code { { sstore(42, 42) } } +// object "C" { +// code { { sstore(55, 55) } } +// } +// } +// } From 2787cd3765bee066a0278637cd225e179f83060e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 8 Oct 2025 10:49:32 +0200 Subject: [PATCH 0961/1340] ssacfg: add bridge finder --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/ssa/BridgeFinder.h | 129 +++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 libyul/backends/evm/ssa/BridgeFinder.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index e70a6e7b6..78fef861b 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -73,6 +73,7 @@ add_library(yul backends/evm/StackLayoutGenerator.h backends/evm/VariableReferenceCounter.h backends/evm/VariableReferenceCounter.cpp + backends/evm/ssa/BridgeFinder.h backends/evm/ssa/ControlFlow.cpp backends/evm/ssa/ControlFlow.h backends/evm/ssa/LivenessAnalysis.cpp diff --git a/libyul/backends/evm/ssa/BridgeFinder.h b/libyul/backends/evm/ssa/BridgeFinder.h new file mode 100644 index 000000000..6a7ebeef9 --- /dev/null +++ b/libyul/backends/evm/ssa/BridgeFinder.h @@ -0,0 +1,129 @@ +/* + 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 + + +#pragma once + +#include + +#include + +#include +#include +#include + +namespace solidity::yul::ssa +{ +/// Detect bridges according to Algorithm 1 of https://arxiv.org/pdf/2108.07346.pdf. +/// +/// A bridge in an undirected graph is an edge whose removal increases the number of connected components. In control +/// flow analysis, bridge vertices are critical articulation points where removing the vertex would disconnect +/// reachable code from unreachable code. This implementation adapts the bridge-finding algorithm to directed control +/// flow graphs by treating them as undirected, then validating edge directionality to identify vertices that gate +/// access to subsequent blocks. +/// +/// We use bridges to determine blocks in which it is fine to introduce junk slots on the stack at any point in time. +class BridgeFinder +{ +public: + explicit BridgeFinder(SSACFG const& _cfg): + m_cfg(_cfg), + m_bridgeVertex(_cfg.numBlocks()), + m_visited(_cfg.numBlocks()), + m_disc(_cfg.numBlocks()), + m_low(_cfg.numBlocks()) + { + size_t time = 0; + dfs(time, _cfg.entry, std::nullopt); + } + + bool bridgeVertex(SSACFG::BlockId const& _blockId) const + { + return m_bridgeVertex[_blockId.value]; + } + +private: + void dfs(size_t& _time, SSACFG::BlockId const& _vertex, std::optional const& _parent) + { + m_visited[_vertex.value] = true; + m_disc[_vertex.value] = _time; + m_low[_vertex.value] = _time; + ++_time; + + auto const& currentBlock = m_cfg.block(_vertex); + currentBlock.forEachExit([&](SSACFG::BlockId const& _exit) + { + processNeighbor(_exit, _time, _vertex, currentBlock.entries, _parent); + }); + + for (SSACFG::BlockId const neighbor: currentBlock.entries) + processNeighbor(neighbor, _time, _vertex, currentBlock.entries, _parent); + } + + void processNeighbor( + SSACFG::BlockId const& _neighbor, + size_t& _time, + SSACFG::BlockId const& _vertex, + std::set const& _vertexEntries, + std::optional const& _parent + ) + { + if (_neighbor == _parent) + return; + + if (!m_visited[_neighbor.value]) + { + dfs(_time, _neighbor, _vertex); + m_low[_vertex.value] = std::min(m_low[_vertex.value], m_low[_neighbor.value]); + if (m_low[_neighbor.value] > m_disc[_vertex.value]) + { + // vertex <-> neighbor is a bridge in the undirected graph + bool const edgeNeighborToVertex = _vertexEntries.contains(_neighbor); + bool const edgeVertexToNeighbor = m_cfg.block(_neighbor).entries.contains(_vertex); + + // special case: if it's the entry itself, we mark it as bridge vertex (provided correct orientation), + // so that functions which do nothing but revert have their whole tree marked as such (sans loops) + if (!_parent) + m_bridgeVertex[_vertex.value] = edgeVertexToNeighbor; + // Since we are not really undirected, check if we don't have a cycle (u -> v and v -> u) and see, + // which edge really exists here. + // Then record the targeted vertex as bridge vertex. + if (edgeVertexToNeighbor && !edgeNeighborToVertex) + // bridge vertex -> neighbor + m_bridgeVertex[_neighbor.value] = true; + else if (edgeNeighborToVertex && !edgeVertexToNeighbor) + // bridge neighbor -> vertex + m_bridgeVertex[_vertex.value] = true; + } + } + else + m_low[_vertex.value] = std::min(m_low[_vertex.value], m_disc[_neighbor.value]); + } + + SSACFG const& m_cfg; + // determines whether a vertex is a bridge vertex. optimizing for performance over space with u8. + std::vector m_bridgeVertex; + // determines whether a vertex is visited. optimizing for performance over space with u8. + std::vector m_visited; + // vertex discovery time + std::vector m_disc; + // minimum discovery time of subtree - if m_low[child] > m_low[parent], we have a bridge + std::vector m_low; +}; + +} From 19a78fbd06ffff2d49927f1bac9d235d61a246a4 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 8 Oct 2025 11:17:10 +0200 Subject: [PATCH 0962/1340] ssacfg: add termination path analysis --- libyul/CMakeLists.txt | 2 + .../evm/ssa/JunkAdmittingBlocksFinder.cpp | 73 +++++++++++++++++++ .../evm/ssa/JunkAdmittingBlocksFinder.h | 46 ++++++++++++ libyul/backends/evm/ssa/SSACFG.h | 52 +++++++++---- 4 files changed, 160 insertions(+), 13 deletions(-) create mode 100644 libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.cpp create mode 100644 libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 78fef861b..15b06a623 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -76,6 +76,8 @@ add_library(yul backends/evm/ssa/BridgeFinder.h backends/evm/ssa/ControlFlow.cpp backends/evm/ssa/ControlFlow.h + backends/evm/ssa/JunkAdmittingBlocksFinder.cpp + backends/evm/ssa/JunkAdmittingBlocksFinder.h backends/evm/ssa/LivenessAnalysis.cpp backends/evm/ssa/LivenessAnalysis.h backends/evm/ssa/SSACFGLoopNestingForest.cpp diff --git a/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.cpp b/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.cpp new file mode 100644 index 000000000..d7c9202ef --- /dev/null +++ b/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.cpp @@ -0,0 +1,73 @@ +/* + 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 + +#include + +#include + +namespace solidity::yul::ssa +{ + +JunkAdmittingBlocksFinder::JunkAdmittingBlocksFinder(SSACFG const& _cfg, ForwardSSACFGTopologicalSort const& _topologicalSort): + m_blockAllowsJunk(_cfg.numBlocks(), false) +{ + // special case: only one block here, we mark it as junkable in case it's not a function return + if (_topologicalSort.preOrder().size() == 1) + { + SSACFG::BlockId const id {_topologicalSort.preOrder().front()}; + m_blockAllowsJunk[id.value] = !_cfg.block(id).isFunctionReturnBlock(); + return; + } + + // Find all bridges, i.e., vertices, which upon removal increase the number of connected components. + // Translated to SSA CFGs this means: + // - control flow that enters a bridge vertex never returns to a previously visited block + // - there is no parallel path to a child of the vertex, ie, adding junk is fine in terms of stack balance + BridgeFinder const bridgeFinder(_cfg); + + // of the bridge vertices, we have the exclude the ones that can lead to a function return + std::vector toVisit; + for (auto const blockIndex: _topologicalSort.preOrder()) + { + SSACFG::BlockId const blockId {blockIndex}; + m_blockAllowsJunk[blockIndex] = bridgeFinder.bridgeVertex(blockId) || _cfg.block(blockId).isTerminationBlock(); + if (_cfg.block(blockId).isFunctionReturnBlock()) + toVisit.emplace_back(SSACFG::BlockId{blockIndex}); + } + + std::vector visited(_cfg.numBlocks(), false); + while (!toVisit.empty()) + { + auto const blockId = toVisit.back(); + auto const& block = _cfg.block(blockId); + toVisit.pop_back(); + + m_blockAllowsJunk[blockId.value] = false; + visited[blockId.value] = true; + for (auto const& entry: block.entries) + if (!visited[entry.value]) + toVisit.emplace_back(entry); + } +} + +bool JunkAdmittingBlocksFinder::allowsAdditionOfJunk(SSACFG::BlockId const& _blockId) const +{ + return m_blockAllowsJunk[_blockId.value]; +} + +} diff --git a/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.h b/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.h new file mode 100644 index 000000000..e567603dd --- /dev/null +++ b/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.h @@ -0,0 +1,46 @@ +/* + 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 + +#pragma once + +#include +#include + +#include +#include + +namespace solidity::yul::ssa +{ + +/// Identifies blocks where stack balance constraints can be relaxed. +/// These are blocks that inevitably terminate down the line (i.e., there is no path to a function return exit) and +/// which are "bridge vertices". For a bridge, the graph decomposes into `G1` and `G2` with a singular edge `e=(v1->v2)` +/// between them. Therefore, traversal into `G2` cannot escape back into `G1` and in particular there cannot be a +/// parallel path into G2 that has relaxed constraints with respect to introducing junk. Consequently, there cannot be +/// a situation in which a junk-bloated stack has to be unified with a slimmer stack layout stemming from another path +/// into `G2`. +class JunkAdmittingBlocksFinder +{ +public: + explicit JunkAdmittingBlocksFinder(SSACFG const& _cfg, ForwardSSACFGTopologicalSort const& _topologicalSort); + bool allowsAdditionOfJunk(SSACFG::BlockId const& _blockId) const; +private: + std::vector m_blockAllowsJunk; +}; + +} diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 32768ca6b..5ea8247ce 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -52,17 +52,14 @@ class SSACFG struct BlockId { size_t value = std::numeric_limits::max(); - bool operator<(BlockId const& _rhs) const { return value < _rhs.value; } - bool operator==(BlockId const& _rhs) const { return value == _rhs.value; } - bool operator!=(BlockId const& _rhs) const { return value != _rhs.value; } + auto operator<=>(BlockId const&) const = default; }; struct ValueId { - size_t value = std::numeric_limits::max(); - bool hasValue() const { return value != std::numeric_limits::max(); } - bool operator<(ValueId const& _rhs) const { return value < _rhs.value; } - bool operator==(ValueId const& _rhs) const { return value == _rhs.value; } - bool operator!=(ValueId const& _rhs) const { return value != _rhs.value; } + using ValueType = size_t; + ValueType value = std::numeric_limits::max(); + bool hasValue() const { return value != std::numeric_limits::max(); } + auto operator<=>(ValueId const&) const = default; }; struct BuiltinCall @@ -93,26 +90,26 @@ class SSACFG struct MainExit {}; struct ConditionalJump { - langutil::DebugData::ConstPtr debugData; + langutil::DebugData::ConstPtr debugData{}; ValueId condition; BlockId nonZero; BlockId zero; }; struct Jump { - langutil::DebugData::ConstPtr debugData; + langutil::DebugData::ConstPtr debugData{}; BlockId target; }; struct JumpTable { - langutil::DebugData::ConstPtr debugData; + langutil::DebugData::ConstPtr debugData{}; ValueId value; std::map cases; BlockId defaultCase; }; struct FunctionReturn { - langutil::DebugData::ConstPtr debugData; + langutil::DebugData::ConstPtr debugData{}; std::vector returnValues; }; struct Terminated {}; @@ -138,6 +135,26 @@ class SSACFG _callable(jumpTable->defaultCase); } } + + bool isMainExitBlock() const + { + return std::holds_alternative(exit); + } + + bool isTerminationBlock() const + { + return std::holds_alternative(exit); + } + + bool isFunctionReturnBlock() const + { + return std::holds_alternative(exit); + } + + bool isJumpBlock() const + { + return std::holds_alternative(exit); + } }; BlockId makeBlock(langutil::DebugData::ConstPtr _debugData) { @@ -148,6 +165,7 @@ class SSACFG BasicBlock& block(BlockId _id) { return m_blocks.at(_id.value); } BasicBlock const& block(BlockId _id) const { return m_blocks.at(_id.value); } size_t numBlocks() const { return m_blocks.size(); } + private: std::vector m_blocks; public: @@ -170,13 +188,21 @@ class SSACFG { return std::holds_alternative(valueInfo(_var)); } + bool isPhiValue(ValueId const _var) const + { + return std::holds_alternative(valueInfo(_var)); + } ValueInfo& valueInfo(ValueId const _var) { return m_valueInfos.at(_var.value); } ValueInfo const& valueInfo(ValueId const _var) const { - return m_valueInfos.at(_var.value); + return valueInfo(_var.value); + } + ValueInfo const& valueInfo(ValueId::ValueType const _var) const + { + return m_valueInfos.at(_var); } ValueId newPhi(BlockId const _definingBlock) { From 9bc0122405c5cb785e070dde7b91c9b1a39be67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 17:19:06 +0200 Subject: [PATCH 0963/1340] Consistency tweaks and syntax cleanup in scripts that deal with solc version --- scripts/build.sh | 18 ++++---- scripts/ci/build.sh | 16 +++---- scripts/ci/build_emscripten.sh | 13 +++--- scripts/create_source_tarball.sh | 72 ++++++++++++++++---------------- 4 files changed, 57 insertions(+), 62 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index 6edd60bd9..5d7765e6b 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,26 +1,26 @@ #!/usr/bin/env bash set -e -ROOTDIR="$(dirname "$0")/.." +ROOTDIR=$(dirname "$0")/.. BUILDDIR="${ROOTDIR}/build" -if [[ $# -eq 0 ]]; then +if (( $# == 0 )); then BUILD_TYPE=Release else BUILD_TYPE="$1" fi -if [[ "$(git tag --points-at HEAD 2>/dev/null)" == v* ]]; then - touch "${ROOTDIR}/prerelease.txt" +if [[ $(git tag --points-at HEAD 2> /dev/null) == v* ]]; then + touch "${ROOTDIR}/prerelease.txt" fi -mkdir -p "${BUILDDIR}" -cd "${BUILDDIR}" +mkdir -p "$BUILDDIR" +cd "$BUILDDIR" cmake .. -DCMAKE_BUILD_TYPE="$BUILD_TYPE" "${@:2}" make -j2 -if [[ "${CI}" == "" ]]; then - echo "Installing ..." - sudo make install +if [[ $CI == "" ]]; then + echo "Installing ..." + sudo make install fi diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh index e1d119a06..1acec5a20 100755 --- a/scripts/ci/build.sh +++ b/scripts/ci/build.sh @@ -9,27 +9,23 @@ prerelease_source="${1:-ci}" cd "${ROOTDIR}" -# shellcheck disable=SC2166 -if [ "$CIRCLE_BRANCH" = release -o -n "$CIRCLE_TAG" -o -n "$FORCE_RELEASE" ] -then - echo -n >prerelease.txt +if [[ $CIRCLE_BRANCH == release || -n $CIRCLE_TAG || -n $FORCE_RELEASE ]]; then + echo -n > prerelease.txt else # Use last commit date rather than build date to avoid ending up with builds for # different platforms having different version strings (and therefore producing different bytecode) # if the CI is triggered just before midnight. - TZ=UTC git show --quiet --date="format-local:%Y.%-m.%-d" --format="${prerelease_source}.%cd" >prerelease.txt + TZ=UTC git show --quiet --date="format-local:%Y.%-m.%-d" --format="${prerelease_source}.%cd" > prerelease.txt fi -if [ -n "$CIRCLE_SHA1" ] -then - echo -n "$CIRCLE_SHA1" >commit_hash.txt +if [[ -n $CIRCLE_SHA1 ]]; then + echo -n "$CIRCLE_SHA1" > commit_hash.txt fi mkdir -p build cd build -# shellcheck disable=SC2166 -[ -n "$COVERAGE" -a "$CIRCLE_BRANCH" != release -a -z "$CIRCLE_TAG" ] && CMAKE_OPTIONS="$CMAKE_OPTIONS -DCOVERAGE=ON" +[[ -n $COVERAGE && $CIRCLE_BRANCH != release && -z $CIRCLE_TAG ]] && CMAKE_OPTIONS="$CMAKE_OPTIONS -DCOVERAGE=ON" # shellcheck disable=SC2086 cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" $CMAKE_OPTIONS diff --git a/scripts/ci/build_emscripten.sh b/scripts/ci/build_emscripten.sh index e4d25f195..836c4d41c 100755 --- a/scripts/ci/build_emscripten.sh +++ b/scripts/ci/build_emscripten.sh @@ -45,19 +45,16 @@ function build() { cd "${ROOT_DIR}" - # shellcheck disable=SC2166 - if [[ "$CIRCLE_BRANCH" = release || -n "$CIRCLE_TAG" || -n "$FORCE_RELEASE" || "$(git tag --points-at HEAD 2>/dev/null)" == v* ]] - then - echo -n >prerelease.txt + if [[ $CIRCLE_BRANCH == release || -n $CIRCLE_TAG || -n $FORCE_RELEASE || $(git tag --points-at HEAD 2> /dev/null) == v* ]]; then + echo -n > prerelease.txt else # Use last commit date rather than build date to avoid ending up with builds for # different platforms having different version strings (and therefore producing different bytecode) # if the CI is triggered just before midnight. - TZ=UTC git show --quiet --date="format-local:%Y.%-m.%-d" --format="${prerelease_source}.%cd" >prerelease.txt + TZ=UTC git show --quiet --date="format-local:%Y.%-m.%-d" --format="${prerelease_source}.%cd" > prerelease.txt fi - if [ -n "$CIRCLE_SHA1" ] - then - echo -n "$CIRCLE_SHA1" >commit_hash.txt + if [[ -n $CIRCLE_SHA1 ]]; then + echo -n "$CIRCLE_SHA1" > commit_hash.txt fi # Disable warnings for unqualified `move()` calls, introduced and enabled by diff --git a/scripts/create_source_tarball.sh b/scripts/create_source_tarball.sh index f5e2892ac..1a3099245 100755 --- a/scripts/create_source_tarball.sh +++ b/scripts/create_source_tarball.sh @@ -1,39 +1,41 @@ -#!/usr/bin/env sh -# - -set -e +#!/usr/bin/env bash +set -euo pipefail REPO_ROOT="$(dirname "$0")"/.. -( - cd "$REPO_ROOT" - version=$(scripts/get_version.sh) - commithash=$(git rev-parse --short=8 HEAD) - commitdate=$(git show --format=%ci HEAD | head -n 1 | cut - -b1-10 | sed -e 's/-0?/./' | sed -e 's/-0?/./') +cd "$REPO_ROOT" +version=$(scripts/get_version.sh) +commit_hash=$(git rev-parse --short=8 HEAD) +commit_date=$(git show --format=%ci HEAD | head -n 1 | cut - -b1-10 | sed -e 's/-0?/./' | sed -e 's/-0?/./') + +# File exists and has zero size -> not a prerelease +if [[ -e prerelease.txt && ! -s prerelease.txt ]]; then + version_string="$version" +else + version_string="${version}-nightly-${commit_date}-${commit_hash}" +fi + +TEMPDIR=$(mktemp -d -t "solc-src-tarball-XXXXXX") +SOLDIR="${TEMPDIR}/solidity_${version_string}/" +mkdir "$SOLDIR" + +# Ensure that submodules are initialized. +git submodule update --init --recursive +# Store the current source +git checkout-index --all --prefix="$SOLDIR" +# shellcheck disable=SC2016 +SOLDIR="$SOLDIR" git submodule foreach 'git checkout-index --all --prefix="${SOLDIR}/${sm_path}/"' - # file exists and has zero size -> not a prerelease - if [ -e prerelease.txt ] && [ ! -s prerelease.txt ] - then - versionstring="$version" - else - versionstring="$version-nightly-$commitdate-$commithash" - fi +# Include the commit hash and prerelease suffix in the tarball +echo "$commit_hash" > "${SOLDIR}/commit_hash.txt" +[[ -e prerelease.txt && ! -s prerelease.txt ]] && cp prerelease.txt "${SOLDIR}/" - TEMPDIR=$(mktemp -d) - SOLDIR="$TEMPDIR/solidity_$versionstring/" - mkdir "$SOLDIR" - # Ensure that submodules are initialized. - git submodule update --init --recursive - # Store the current source - git checkout-index -a --prefix="$SOLDIR" - # shellcheck disable=SC2016 - SOLDIR="$SOLDIR" git submodule foreach 'git checkout-index -a --prefix="$SOLDIR/$sm_path/"' - # Store the commit hash - echo "$commithash" > "$SOLDIR/commit_hash.txt" - if [ -e prerelease.txt ] && [ ! -s prerelease.txt ] - then - cp prerelease.txt "$SOLDIR/" - fi - mkdir -p "$REPO_ROOT/upload" - tar --owner 0 --group 0 -czf "$REPO_ROOT/upload/solidity_$versionstring.tar.gz" -C "$TEMPDIR" "solidity_$versionstring" - rm -r "$TEMPDIR" -) +mkdir -p "$REPO_ROOT/upload" +tar \ + --owner 0 \ + --group 0 \ + --create \ + --gzip \ + --file "${REPO_ROOT}/upload/solidity_${version_string}.tar.gz" \ + --directory "$TEMPDIR" \ + "solidity_${version_string}" +rm -r "$TEMPDIR" From 893cf591152b580869d965f8abad2b812bf45517 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Mon, 13 Oct 2025 17:24:45 +0200 Subject: [PATCH 0964/1340] Remove ubuntu 22.04 buildpackdeps and ci --- .github/workflows/buildpack-deps.yml | 3 +- scripts/ci/buildpack-deps_test_ubuntu2204.sh | 1 - .../buildpack-deps/Dockerfile.ubuntu2204 | 108 ------------------ 3 files changed, 1 insertion(+), 111 deletions(-) delete mode 120000 scripts/ci/buildpack-deps_test_ubuntu2204.sh delete mode 100644 scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index 5e49f2f32..0671c5b39 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -9,7 +9,6 @@ on: paths: - 'scripts/docker/buildpack-deps/Dockerfile.emscripten' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz' - - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2204' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang' @@ -26,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2204, ubuntu2404, ubuntu2404.clang] + image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2404, ubuntu2404.clang] steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 diff --git a/scripts/ci/buildpack-deps_test_ubuntu2204.sh b/scripts/ci/buildpack-deps_test_ubuntu2204.sh deleted file mode 120000 index c07a74de4..000000000 --- a/scripts/ci/buildpack-deps_test_ubuntu2204.sh +++ /dev/null @@ -1 +0,0 @@ -build.sh \ No newline at end of file diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 deleted file mode 100644 index be3daee90..000000000 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2204 +++ /dev/null @@ -1,108 +0,0 @@ -# vim:syntax=dockerfile -#------------------------------------------------------------------------------ -# Dockerfile for building and testing Solidity Compiler on CI -# Target: Ubuntu 22.04 (Jammy Jellyfish) -# 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 -# -# (c) 2016-2025 solidity contributors. -#------------------------------------------------------------------------------ -FROM buildpack-deps:jammy AS base -LABEL version="3" - -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 \ - cmake \ - jq \ - clang \ - libboost-filesystem-dev \ - libboost-program-options-dev \ - libboost-system-dev \ - libboost-test-dev \ - libcln-dev \ - locales-all \ - lsof \ - ninja-build \ - python3-pip \ - python3-sphinx \ - software-properties-common \ - sudo \ - unzip \ - zip; \ - pip3 install \ - codecov \ - colorama \ - deepdiff \ - parsec \ - pygments-lexer-solidity \ - pylint \ - requests \ - tabulate \ - z3-solver; - -# Eldarica -RUN set -ex; \ - apt-get update; \ - apt-get install -qqy \ - openjdk-11-jre; \ - eldarica_version="2.1"; \ - wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip; \ - test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip"; \ - unzip /opt/eld_binaries.zip -d /opt; \ - rm -f /opt/eld_binaries.zip; - -# CVC5 -RUN set -ex; \ - cvc5_version="1.2.0"; \ - cvc5_archive_name="cvc5-Linux-x86_64-static"; \ - wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip; \ - test "$(sha256sum /opt/cvc5.zip)" = "d18f174ff9a11923c32c3f871f844ed16bd77a28f51050b8e7c8d821c98a1c2e /opt/cvc5.zip"; \ - unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ - rm -f /opt/cvc5.zip; - -# Z3 -RUN set -ex; \ - z3_version="4.13.3"; \ - z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ - wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ - test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ - unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ - rm -f /opt/z3.zip; - -FROM base AS libraries - -# EVMONE -RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ - cd /usr; \ - tar -xf /usr/src/evmone.tar.gz; \ - rm -rf /usr/src/evmone.tar.gz - -FROM base -COPY --from=libraries /usr/lib /usr/lib -COPY --from=libraries /usr/bin /usr/bin -COPY --from=libraries /usr/include /usr/include -COPY --from=libraries /opt/eldarica /opt/eldarica -ENV PATH="$PATH:/opt/eldarica" From 0ec7faf3dfb23296dc6130da45839ffcd8a09bdd Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Tue, 14 Oct 2025 12:57:39 +0200 Subject: [PATCH 0965/1340] Remove ubuntu 2004 from buildpackdeps workflow --- .github/workflows/buildpack-deps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index 0671c5b39..c4c84dae1 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -25,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2004, ubuntu2404, ubuntu2404.clang] + image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2404, ubuntu2404.clang] steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 From d8b4bd871135cbb08d77366709778e73669c7f76 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Tue, 14 Oct 2025 13:00:29 +0200 Subject: [PATCH 0966/1340] Use z3-solver python package instead of z3 binaries --- .../docker/buildpack-deps/Dockerfile.ubuntu2404 | 14 +++----------- .../buildpack-deps/Dockerfile.ubuntu2404.clang | 14 +++----------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 index 1edf6f37e..a67fd248c 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="4" +LABEL version="5" ARG DEBIAN_FRONTEND=noninteractive @@ -31,6 +31,7 @@ ARG DEBIAN_FRONTEND=noninteractive ENV PIP_BREAK_SYSTEM_PACKAGES 1 RUN set -ex; \ + z3_version="4.13.3"; \ 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 ; \ @@ -62,7 +63,7 @@ RUN set -ex; \ pylint \ requests \ tabulate \ - z3-solver; + z3-solver=="${z3_version}"; # Eldarica RUN set -ex; \ @@ -84,15 +85,6 @@ RUN set -ex; \ unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ rm -f /opt/cvc5.zip; -# Z3 -RUN set -ex; \ - z3_version="4.13.3"; \ - z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ - wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ - test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ - unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ - rm -f /opt/z3.zip; - FROM base AS libraries # EVMONE diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang index 3622cc7eb..ec339cbcb 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="5" +LABEL version="6" ARG DEBIAN_FRONTEND=noninteractive @@ -31,6 +31,7 @@ ARG DEBIAN_FRONTEND=noninteractive ENV PIP_BREAK_SYSTEM_PACKAGES 1 RUN set -ex; \ + z3_version="4.13.3"; \ 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 ; \ @@ -60,7 +61,7 @@ RUN set -ex; \ pylint \ requests \ tabulate \ - z3-solver; + z3-solver=="${z3_version}"; # Eldarica RUN set -ex; \ @@ -83,15 +84,6 @@ RUN set -ex; \ unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin; \ rm -f /opt/cvc5.zip; -# Z3 -RUN set -ex; \ - z3_version="4.13.3"; \ - z3_archive_name="z3-${z3_version}-x64-glibc-2.35"; \ - wget "https://github.com/Z3Prover/z3/releases/download/z3-${z3_version}/${z3_archive_name}.zip" -O /opt/z3.zip; \ - test "$(sha256sum /opt/z3.zip)" = "32c7377026733c9d7b33c21cd77a68f50ba682367207b031a6bfd80140a8722f /opt/z3.zip"; \ - unzip -j /opt/z3.zip "${z3_archive_name}/bin/z3" -d /usr/bin; \ - rm -f /opt/z3.zip; - FROM base AS libraries ENV CC clang From ab3ab422fc4e4532fc1802bd172f663b0018f65f Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Wed, 15 Oct 2025 14:34:19 +0200 Subject: [PATCH 0967/1340] Use a read-only GitHub token when retrieving PR information --- .circleci/config.yml | 8 ++++---- scripts/common/rest_api_helpers.py | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 48d86a97c..dfa64175d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -142,8 +142,8 @@ commands: FOUNDRY_REPO="foundry-rs/foundry" FOUNDRY_VERSION="<< parameters.version >>" # Make authenticated requests when the Github token is available - if [[ -n "$GITHUB_ACCESS_TOKEN" ]]; then - EXTRA_HEADERS=(--header 'Authorization: Bearer '"${GITHUB_ACCESS_TOKEN}") + if [[ -n "$GITHUB_READ_TOKEN" ]]; then + EXTRA_HEADERS=(--header 'Authorization: Bearer '"${GITHUB_READ_TOKEN}") fi FOUNDRY_RELEASE_SHA=$(curl \ --silent \ @@ -1418,8 +1418,8 @@ jobs: name: Retrieve EDR latest release tag command: | # Make authenticated requests when the Github token is available - if [[ -n "$GITHUB_ACCESS_TOKEN" ]]; then - EXTRA_HEADERS=(--header "Authorization: Bearer ${GITHUB_ACCESS_TOKEN}") + if [[ -n "$GITHUB_READ_TOKEN" ]]; then + EXTRA_HEADERS=(--header "Authorization: Bearer ${GITHUB_READ_TOKEN}") fi EDR_LATEST_RELEASE_TAG=$( curl \ diff --git a/scripts/common/rest_api_helpers.py b/scripts/common/rest_api_helpers.py index caae2b5db..9b2f94261 100644 --- a/scripts/common/rest_api_helpers.py +++ b/scripts/common/rest_api_helpers.py @@ -84,10 +84,13 @@ def __init__(self, project_slug: str, debug_requests: bool): self.debug_requests = debug_requests def pull_request(self, pr_id: int) -> dict: + # GITHUB_READ_TOKEN should be a PAT with read-only permissions + # This is used by CircleCI and local scripts to avoid GitHub API rate limits + headers = {'Authorization': f'Bearer {environ.get("GITHUB_READ_TOKEN")}'} if 'GITHUB_READ_TOKEN' in environ else {} return query_api( f'{self.BASE_URL}/repos/{self.project_slug}/pulls/{pr_id}', {}, - {}, + headers, self.debug_requests ) From b36dd21cc27271731ff3eec75903594f4c67afdf Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 9 Oct 2025 14:33:43 -0300 Subject: [PATCH 0968/1340] bump evmone to 0.16.0 in ubuntu images --- .../buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz | 12 ++++-------- scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 | 8 ++++---- .../buildpack-deps/Dockerfile.ubuntu2404.clang | 8 ++++---- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index c14039d90..5a96e6889 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-builder AS base -LABEL version="11" +LABEL version="12" ARG DEBIAN_FRONTEND=noninteractive @@ -64,10 +64,6 @@ RUN apt-get update; \ requests \ tabulate; -# Ensure that the expected version of Clang is installed, as the base image may update it in the future: -# https://github.com/google/oss-fuzz/blob/5e96edbdf285045cc82dbca5600cbe994a3b1a74/infra/base-images/base-clang/checkout_build_install_llvm.sh#L57 -RUN test "$(clang -dumpversion | cut -d. -f1)" = "18" || (echo "Error: Clang 18 not found!" && exit 1) - FROM base AS libraries # Boost @@ -78,8 +74,8 @@ RUN set -ex; \ tar -xf boost.tar.bz2; \ rm boost.tar.bz2; \ cd boost_1_83_0; \ - export CXXFLAGS="-std=c++20 -nostdinc++ -I/usr/lib/llvm-18/include/c++/v1 -pthread"; \ - export LDFLAGS="-stdlib=libc++ -L/usr/lib/llvm-18/lib"; \ + export CXXFLAGS="$CXXFLAGS -std=c++20 -nostdinc++ -I/usr/local/include/c++/v1 -I/usr/local/include/x86_64-unknown-linux-gnu/c++/v1 -pthread"; \ + export LDFLAGS="$LDFLAGS -stdlib=libc++ -lpthread"; \ ./bootstrap.sh --with-toolset=clang --prefix=/usr; \ ./b2 toolset=clang \ cxxflags="${CXXFLAGS}" \ @@ -143,7 +139,7 @@ RUN set -ex; \ # EVMONE RUN set -ex; \ cd /usr/src; \ - git clone --branch="v0.13.0" --recurse-submodules https://github.com/ipsilon/evmone.git; \ + git clone --branch="v0.16.0" --recurse-submodules https://github.com/ipsilon/evmone.git; \ cd evmone; \ mkdir build; \ cd build; \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 index a67fd248c..9cf381f76 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 @@ -22,13 +22,13 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="5" +LABEL version="6" ARG DEBIAN_FRONTEND=noninteractive # From Python3.11, pip requires a virtual environment, and will thus terminate when installing packages globally. # Since we're building this image from scratch, it's perfectly fine to use the below flag. -ENV PIP_BREAK_SYSTEM_PACKAGES 1 +ENV PIP_BREAK_SYSTEM_PACKAGES=1 RUN set -ex; \ z3_version="4.13.3"; \ @@ -89,8 +89,8 @@ FROM base AS libraries # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ipsilon/evmone/releases/download/v0.16.0/evmone-0.16.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "09a59e07bde21bbf08b821db9097ef4db9ff06f1484b7b14497a16a701e72233 /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ rm -rf /usr/src/evmone.tar.gz diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang index ec339cbcb..aec6fe6e2 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang @@ -22,13 +22,13 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="6" +LABEL version="7" ARG DEBIAN_FRONTEND=noninteractive # From Python3.11, pip requires a virtual environment, and will thus terminate when installing packages globally. # Since we're building this image from scratch, it's perfectly fine to use the below flag. -ENV PIP_BREAK_SYSTEM_PACKAGES 1 +ENV PIP_BREAK_SYSTEM_PACKAGES=1 RUN set -ex; \ z3_version="4.13.3"; \ @@ -91,8 +91,8 @@ ENV CXX clang++ # EVMONE RUN set -ex; \ - wget -O /usr/src/evmone.tar.gz https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz; \ - test "$(sha256sum /usr/src/evmone.tar.gz)" = "94efc7fa27ff94018003ad95a62c20b17a45f027d434eb642c8e345e8d4d3cad /usr/src/evmone.tar.gz"; \ + wget -O /usr/src/evmone.tar.gz https://github.com/ipsilon/evmone/releases/download/v0.16.0/evmone-0.16.0-linux-x86_64.tar.gz; \ + test "$(sha256sum /usr/src/evmone.tar.gz)" = "09a59e07bde21bbf08b821db9097ef4db9ff06f1484b7b14497a16a701e72233 /usr/src/evmone.tar.gz"; \ cd /usr; \ tar -xf /usr/src/evmone.tar.gz; \ rm -rf /usr/src/evmone.tar.gz From 0544fd1c4914c4d238897cb8e11ed8bafee052c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 15:44:04 +0200 Subject: [PATCH 0969/1340] ReleaseChecklist: Announcing releases on EF Discord is no longer possible --- ReleaseChecklist.md | 1 - 1 file changed, 1 deletion(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index f0148cd0e..9680ead14 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -116,7 +116,6 @@ At least a day before the release: - [ ] Announce on [Fosstodon](https://fosstodon.org/@solidity/), including links to the release and the blog post. - [ ] Share the announcement on Reddit in [`/r/ethdev`](https://reddit.com/r/ethdev/), cross-posted to [`/r/ethereum`](https://reddit.com/r/ethereum/). - [ ] Share the announcement on the [Solidity forum](https://forum.soliditylang.org) in the `Announcements` category. -- [ ] Share the announcement on [Project Updates](https://discord.com/channels/420394352083337236/798974456704925696) - [ ] Share the announcement on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im) - [ ] Share the announcement on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org) - [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.argot.org/@solidity-release-mistakes). From 6cd81cee0ac053a1ac641caf1cd8739a078e187d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 16:04:51 +0200 Subject: [PATCH 0970/1340] ReleaseChecklist: Wording tweaks --- ReleaseChecklist.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 9680ead14..36aab323a 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -1,4 +1,4 @@ -## Checklist for making a release: +## Checklist for making a Solidity release ### Requirements - [ ] GitHub account with access to [solidity](https://github.com/argotorg/solidity), [solc-js](https://github.com/argotorg/solc-js), @@ -59,19 +59,19 @@ At least a day before the release: - [ ] Thank voluntary contributors in the GitHub release notes. Use `scripts/list_contributors.sh v` to get initial list of names. Remove different variants of the same name manually before using the output. -- [ ] Check that all tests on the latest commit in `develop` are green. +- [ ] Check that all tests on the latest commit on `develop` are green. - [ ] Click the `Publish release` button on the release page, creating the tag. **Important: Must not be done before all the PRs, including changelog cleanup and date, are merged.** - [ ] Wait for the CI runs on the tag itself. ### Upload Release Artifacts and Publish Binaries - [ ] Switch to the tag that archives have to be created for. -- [ ] Create the `prerelease.txt` file: (`echo -n > prerelease.txt`). -- [ ] Run `scripts/create_source_tarball.sh` while being on the tag to create the source tarball. This will create the tarball in a directory called `upload`. -- [ ] Take the tarball from the upload directory (its name should be `solidity_x.x.x.tar.gz`, otherwise `prerelease.txt` was missing in the step before) and upload the source tarball to the release page. -- [ ] Take the `github-binaries.tar` tarball from `c_release_binaries` run of the tagged commit in circle-ci and add all binaries from it to the release page. +- [ ] Create the `prerelease.txt` file: `echo -n > prerelease.txt`. +- [ ] Run `scripts/create_source_tarball.sh` to create the source tarball. This will create the tarball in a directory called `upload`. +- [ ] Take the tarball from the upload directory (its name should be `solidity_x.x.x.tar.gz`, otherwise `prerelease.txt` was missing in the step before) and upload it to the release page. +- [ ] Take the `github-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to the release page. Make sure it contains four binaries: `solc-windows.exe`, `solc-macos`, `solc-static-linux` and `soljson.js`. -- [ ] Take the `solc-bin-binaries.tar` tarball from `c_release_binaries` run of the tagged commit in circle-ci and add all binaries from it to solc-bin. +- [ ] Take the `solc-bin-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to solc-bin. - [ ] Run `npm install` if you've got a clean checkout of the solc-bin repo. - [ ] Run `npm run update -- --reuse-hashes` in `solc-bin` and verify that the script has updated `list.js`, `list.txt` and `list.json` files correctly and that symlinks to the new release have been added in `solc-bin/wasm/` and `solc-bin/emscripten-wasm32/`. - [ ] Create a pull request in solc-bin and merge. @@ -101,7 +101,7 @@ At least a day before the release: - [ ] Increment the version number, create a pull request for that, merge it after tests succeeded. - [ ] Create a tag using `git tag --annotate v$VERSION` and push it with `git push --tags`. - [ ] Wait for the CI runs on the tag itself. -- [ ] Take the `solc-x.y.z.tgz` artifact from `build-package` run on the tagged commit in circle-ci. +- [ ] Take the `solc-x.y.z.tgz` artifact from `build-package` run on the tagged commit on Circle CI. Inspect the tarball to ensure that it contains an up-to-date compiler binary (`soljson.js`). - [ ] Run `npm publish solc-x.y.z.tgz` to publish the newly created tarball. @@ -116,8 +116,8 @@ At least a day before the release: - [ ] Announce on [Fosstodon](https://fosstodon.org/@solidity/), including links to the release and the blog post. - [ ] Share the announcement on Reddit in [`/r/ethdev`](https://reddit.com/r/ethdev/), cross-posted to [`/r/ethereum`](https://reddit.com/r/ethereum/). - [ ] Share the announcement on the [Solidity forum](https://forum.soliditylang.org) in the `Announcements` category. -- [ ] Share the announcement on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im) -- [ ] Share the announcement on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org) +- [ ] Share the announcement on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im). +- [ ] Share the announcement on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org). - [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.argot.org/@solidity-release-mistakes). - [ ] Bump vendored dependencies. - [ ] Lean back, wait for bug reports and repeat from step 1 :). From b05924eee5b035cded1ddf89fd1cf513e431727a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 16:05:18 +0200 Subject: [PATCH 0971/1340] ReleaseChecklist: Add a separate checklist for prereleases --- ReleaseChecklist.md | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 36aab323a..1b038ee96 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -1,6 +1,6 @@ -## Checklist for making a Solidity release +# Checklist for making a Solidity release -### Requirements +## Requirements - [ ] GitHub account with access to [solidity](https://github.com/argotorg/solidity), [solc-js](https://github.com/argotorg/solc-js), [solc-bin](https://github.com/argotorg/solc-bin), [solidity-website](https://github.com/argotorg/solidity-website). - [ ] DockerHub account with push rights to the [`solc` image](https://hub.docker.com/r/ethereum/solc). @@ -12,6 +12,8 @@ - [ ] Access to the [solidity_lang Twitter account](https://twitter.com/solidity_lang). - [ ] [Reddit](https://www.reddit.com) account that is at least 10 days old with a minimum of 20 comment karma (`/r/ethereum` requirements). +## Full release + ### Pre-flight checks At least a day before the release: - [ ] Run `make linkcheck` from within `docs/` and fix any broken links it finds. @@ -121,3 +123,32 @@ At least a day before the release: - [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.argot.org/@solidity-release-mistakes). - [ ] Bump vendored dependencies. - [ ] Lean back, wait for bug reports and repeat from step 1 :). + +## Prerelease +- [ ] Check that all tests on the latest commit on `develop` or `breaking` branch (whichever was chosen for the prerelease) are green. +- [ ] Create a [release on GitHub](https://github.com/argotorg/solidity/releases/new). + - Set the target to the `develop` or `breaking` branch and the tag to the new version with a prerelease suffix, e.g. `v0.8.5-pre.6`. + Version matches the next release (`develop`) or the next breaking release (`breaking`). + The prerelease number in the suffix is 1-based, sequential, resets after a full release and is counted separately for `develop` and `breaking`. + - Include the following warning: `**The release is still in progress. You may see broken links and binaries may not yet be available from all sources.**`. + - Include the current, incomplete changelog. + - Check the `Set as a pre-release` box. + - Click the `Publish release` button on the release page, creating the tag. +- [ ] Wait for the CI runs on the tag itself. +- [ ] Switch to the tag that archives have to be created for. +- [ ] Create the `prerelease.txt` file: `scripts/prerelease_suffix.sh pre "$(git describe --tags --exact-match)" > prerelease.txt`. +- [ ] Run `scripts/create_source_tarball.sh` to create the source tarball. This will create the tarball in a directory called `upload`. +- [ ] Take the tarball from the upload directory (its name should be `solidity_x.x.x-pre.N.tar.gz`, if `prerelease.txt` was created correctly) and upload it to the release page. +- [ ] Take the `github-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to the release page. + Make sure it contains four binaries: `solc-windows.exe`, `solc-macos`, `solc-static-linux` and `soljson.js`. +- [ ] Take the `solc-bin-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to solc-bin. +- [ ] Run `npm install` if you've got a clean checkout of the solc-bin repo. +- [ ] Run `npm run update -- --reuse-hashes` in `solc-bin` and verify that the script has updated `list.js`, `list.txt` and `list.json` files correctly and that symlinks to the new release have been added in `solc-bin/wasm/` and `solc-bin/emscripten-wasm32/`. +- [ ] Create a pull request in solc-bin and merge. +- [ ] Remove "still in progress" warning from the [release notes](https://github.com/argotorg/solidity/releases). +- [ ] Mention it on [Twitter](https://twitter.com/solidity_lang). +- [ ] Mention it on [Fosstodon](https://fosstodon.org/@solidity/). +- [ ] Mention it on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im). +- [ ] Mention it on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org). +- [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.argot.org/@solidity-release-mistakes). +- [ ] Lean back, wait for bug reports and repeat from step 1 :). From b02d17691fc66f3e0d85487028f6466df3b12db0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 14 Oct 2025 19:11:27 +0200 Subject: [PATCH 0972/1340] installing-solidity.rst: Update information about prerelases --- docs/installing-solidity.rst | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 6c6d6029a..c9286952e 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -14,13 +14,12 @@ addition, patch-level releases with major release 0 (i.e. 0.x.y) will not contain breaking changes. That means code that compiles with version 0.x.y can be expected to compile with 0.x.z where z > y. -In addition to releases, we provide **nightly development builds** to make -it easy for developers to try out upcoming features and -provide early feedback. Note, however, that while the nightly builds are usually -very stable, they contain bleeding-edge code from the development branch and are -not guaranteed to be always working. Despite our best efforts, they might -contain undocumented and/or broken changes that will not become a part of an -actual release. They are not meant for production use. +In addition to releases, we provide **prereleases** and **nightly development builds** to make it +easy for developers to try out upcoming features and provide early feedback. +Note that such builds contain bleeding-edge code from the development branch and are not guaranteed +to be of the same quality as full releases. +Despite our best efforts, they might contain undocumented and/or broken changes that will not +become a part of an actual release. They are not meant for production use. When deploying contracts, you should use the latest released version of Solidity. This is because breaking changes, as well as new features and bug fixes are introduced regularly. @@ -544,7 +543,7 @@ The Version String in Detail The Solidity version string contains four parts: - the version number -- pre-release tag, usually set to ``develop.YYYY.MM.DD`` or ``nightly.YYYY.MM.DD`` +- pre-release tag, usually set to ``develop.YYYY.MM.DD``, ``pre.N`` or ``nightly.YYYY.MM.DD`` - commit in the format of ``commit.GITHASH`` - platform, which has an arbitrary number of items, containing details about the platform and compiler @@ -553,9 +552,11 @@ If there are local modifications, the commit will be postfixed with ``.mod``. These parts are combined as required by SemVer, where the Solidity pre-release tag equals to the SemVer pre-release and the Solidity commit and platform combined make up the SemVer build metadata. -A release example: ``0.4.8+commit.60cc1668.Emscripten.clang``. +Examples: -A pre-release example: ``0.4.9-nightly.2017.1.17+commit.6ecb4aa3.Emscripten.clang`` +- release: ``0.4.8+commit.60cc1668.Emscripten.clang`` +- pre-release: ``0.4.9-pre.3+commit.fb60450bc.Emscripten.clang`` +- nightly build: ``0.4.9-nightly.2017.1.17+commit.6ecb4aa3.Emscripten.clang`` Important Information About Versioning ====================================== @@ -563,14 +564,14 @@ Important Information About Versioning After a release is made, the patch version level is bumped, because we assume that only patch level changes follow. When changes are merged, the version should be bumped according to SemVer and the severity of the change. Finally, a release is always made with the version -of the current nightly build, but without the ``prerelease`` specifier. +of the current build, but without the ``prerelease`` specifier. Example: 1. The 0.4.0 release is made. -2. The nightly build has a version of 0.4.1 from now on. +2. Nightly builds and preerelases have a version of 0.4.1 from now on. 3. Non-breaking changes are introduced --> no change in version. 4. A breaking change is introduced --> version is bumped to 0.5.0. 5. The 0.5.0 release is made. -This behavior works well with the :ref:`version pragma `. +This behavior works well with the :ref:`version pragma `. From 5b0f5f01e1838f6f47a7271e03287bf570f4abd0 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 6 Oct 2025 12:26:44 -0300 Subject: [PATCH 0973/1340] bump evmone version in CI to 0.16.0 --- .circleci/config.yml | 12 ++++++------ .circleci/osx_install_dependencies.sh | 4 ++-- scripts/install_evmone.ps1 | 2 +- test/Common.h | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 48d86a97c..0931fae8e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,16 +13,16 @@ parameters: default: "solbuildpackpusher/solidity-buildpack-deps@sha256:1f387a77be889f65a2a25986a5c5eccc88cec23fabe6aeaf351790751145c81e" ubuntu-2404-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-3 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:ef6a91d7f1434c67fb9e05c6136d80f71c0ad9198479e1a88e3437680993cda4" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-6 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c0412c53e59ce0c96bde4c08e7332ea12e4cadba9bbac829621947897fa21272" ubuntu-2404-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-4 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:97fb2d1bc002b3624161f539a1d29543c0e6c6f4d9a61f611b9b60e99e18f377" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-7 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:7466ed23590cf14e60da884894723bcdab064742f017dcfcce015999b4f9143b" ubuntu-clang-ossfuzz-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-10 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:bd55d9a3b13c88608709ec442188c414d30f4c49f23dc2ce8b76bf8c90603fc7" + # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-12 + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c7088af5082bf764244a6251ecf3dd29d280d2cd2cd071f011f7f32e0326f426" emscripten-docker-image: type: string # NOTE: Please remember to update the `scripts/build_emscripten.sh` whenever the hash of this image changes. diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index b449c4781..dd5a8397b 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -108,10 +108,10 @@ then rm -rf "$z3_dir" # evmone - evmone_version="0.13.0" + evmone_version="0.16.0" evmone_package="evmone-${evmone_version}-darwin-arm64.tar.gz" wget "https://github.com/ipsilon/evmone/releases/download/v${evmone_version}/${evmone_package}" - validate_checksum "$evmone_package" 49fe6cc35e0e13c48ca2f29a6b85a47f7b25dcd427e14254000d3bc29cddf2a6 + validate_checksum "$evmone_package" d26bcf7ada6c712b669ee70cbd8b534f80dadb6207fa15e15d1517d2b6823aa8 sudo tar xzpf "$evmone_package" -C /usr/local rm "$evmone_package" fi diff --git a/scripts/install_evmone.ps1 b/scripts/install_evmone.ps1 index 3e2a1f819..9025d6957 100644 --- a/scripts/install_evmone.ps1 +++ b/scripts/install_evmone.ps1 @@ -3,6 +3,6 @@ $ErrorActionPreference = "Stop" # Needed for Invoke-WebRequest to work via CI. $progressPreference = "silentlyContinue" -Invoke-WebRequest -URI "https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-windows-amd64.zip" -OutFile "evmone.zip" +Invoke-WebRequest -URI "https://github.com/ipsilon/evmone/releases/download/v0.16.0/evmone-0.16.0-windows-amd64.zip" -OutFile "evmone.zip" tar -xf evmone.zip "bin/evmone.dll" mv bin/evmone.dll deps/ diff --git a/test/Common.h b/test/Common.h index a8a0a4e83..1ab7509b9 100644 --- a/test/Common.h +++ b/test/Common.h @@ -39,13 +39,13 @@ namespace solidity::test #ifdef _WIN32 static constexpr auto evmoneFilename = "evmone.dll"; -static constexpr auto evmoneDownloadLink = "https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-windows-amd64.zip"; +static constexpr auto evmoneDownloadLink = "https://github.com/ipsilon/evmone/releases/download/v0.16.0/evmone-0.16.0-windows-amd64.zip"; #elif defined(__APPLE__) static constexpr auto evmoneFilename = "libevmone.dylib"; -static constexpr auto evmoneDownloadLink = "https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-darwin-arm64.tar.gz"; +static constexpr auto evmoneDownloadLink = "https://github.com/ipsilon/evmone/releases/download/v0.16.0/evmone-0.16.0-darwin-arm64.tar.gz"; #else static constexpr auto evmoneFilename = "libevmone.so"; -static constexpr auto evmoneDownloadLink = "https://github.com/ipsilon/evmone/releases/download/v0.13.0/evmone-0.13.0-linux-x86_64.tar.gz"; +static constexpr auto evmoneDownloadLink = "https://github.com/ipsilon/evmone/releases/download/v0.16.0/evmone-0.16.0-linux-x86_64.tar.gz"; #endif struct ConfigException: public util::Exception {}; From b36da102110e5abd12a25eda581183b1da66af8f Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Wed, 15 Oct 2025 12:26:15 -0300 Subject: [PATCH 0974/1340] Remove EOF from soltest flags --- .circleci/soltest_all.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 56aa1c3be..86e62c333 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -40,7 +40,8 @@ IFS=" " read -ra EVM_VALUES <<< "${1:-${DEFAULT_EVM_VALUES[@]}}" DEFAULT_EVM=prague OPTIMIZE_VALUES=(0 1) -EOF_VERSIONS=(0 1) +# TODO: EOF is marked as experimental in evmone. Reenable when proper handling for that is added here. +EOF_VERSIONS=(0) # Run for ABI encoder v1, without SMTChecker tests. EVM="${DEFAULT_EVM}" \ From b90f21e9328696db9316d6de7b64d8b5592f68b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Oct 2025 13:25:28 +0200 Subject: [PATCH 0975/1340] Remove the unused install_cmake.sh script --- scripts/install_cmake.sh | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100755 scripts/install_cmake.sh diff --git a/scripts/install_cmake.sh b/scripts/install_cmake.sh deleted file mode 100755 index 0533de723..000000000 --- a/scripts/install_cmake.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env sh - -# This script downloads the CMake binary and installs it in ~/.local directory -# (the cmake executable will be in ~/.local/bin). -# This is mostly suitable for CIs, not end users. - -set -eu - -VERSION_MAJOR=3 -VERSION_MINOR=15 -VERSION_MICRO=2 -VERSION=$VERSION_MAJOR.$VERSION_MINOR.$VERSION_MICRO -PREFIX="/usr/local" - -OS=$(uname -s) -case $OS in -Linux) SHA256=f8cbec2abc433938bd9378b129d1d288bb33b8b5a277afe19644683af6e32a59;; -Darwin) SHA256=7ec056d641b8cbea98b220efdcc99da1991758a370063dcac3a0cd388d6b30b6;; -esac - -BIN=$PREFIX/bin - -PATH=$PREFIX/bin:$PATH - -if test -f $BIN/cmake && ($BIN/cmake --version | grep -q "$VERSION"); then - echo "CMake $VERSION already installed in $BIN" -else - FILE=cmake-$VERSION-$OS-x86_64.tar.gz - URL=https://cmake.org/files/v$VERSION_MAJOR.$VERSION_MINOR/$FILE - TMPFILE=$(mktemp --tmpdir "cmake-$VERSION-$OS-x86_64.XXXXXXXX.tar.gz") - echo "Downloading CMake ($URL)..." - wget "$URL" -O "$TMPFILE" -nv - if ! (shasum -a256 "$TMPFILE" | grep -q "$SHA256"); then - echo "Checksum mismatch ($TMPFILE)" - exit 1 - fi - mkdir -p "$PREFIX" - tar xzf "$TMPFILE" -C "$PREFIX" --strip 1 - rm "$TMPFILE" -fi From e4421c06ed1472d11275a7b1e92b7853b29069da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Oct 2025 13:26:19 +0200 Subject: [PATCH 0976/1340] Rewrite build_win.ps1 in Bash --- .circleci/build_win.ps1 | 26 ----------------------- .circleci/config.yml | 3 +-- scripts/ci/build_win.sh | 46 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 28 deletions(-) delete mode 100644 .circleci/build_win.ps1 create mode 100755 scripts/ci/build_win.sh diff --git a/.circleci/build_win.ps1 b/.circleci/build_win.ps1 deleted file mode 100644 index e95caa7c1..000000000 --- a/.circleci/build_win.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -$ErrorActionPreference = "Stop" - -cd "$PSScriptRoot\.." - -if ("$Env:FORCE_RELEASE" -Or "$Env:CIRCLE_TAG") { - New-Item prerelease.txt -type file - Write-Host "Building release version." -} -else { - # Use last commit date rather than build date to avoid ending up with builds for - # different platforms having different version strings (and therefore producing different bytecode) - # if the CI is triggered just before midnight. - $last_commit_timestamp = git log -1 --date=unix --format=%cd HEAD - $last_commit_date = (Get-Date -Date "1970-01-01 00:00:00Z").toUniversalTime().addSeconds($last_commit_timestamp).ToString("yyyy.M.d") - -join("ci.", $last_commit_date) | out-file -encoding ascii prerelease.txt -} - -mkdir build -cd build -$boost_dir=(Resolve-Path $PSScriptRoot\..\deps\boost\lib\cmake\Boost-*) -..\deps\cmake\bin\cmake -G "Visual Studio 16 2019" -DBoost_DIR="$boost_dir\" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_INSTALL_PREFIX="$PSScriptRoot\..\upload" .. -if ( -not $? ) { throw "CMake configure failed." } -msbuild solidity.sln /p:Configuration=Release /m:10 /v:minimal -if ( -not $? ) { throw "Build failed." } -..\deps\cmake\bin\cmake --build . -j 10 --target install --config Release -if ( -not $? ) { throw "Install target failed." } diff --git a/.circleci/config.yml b/.circleci/config.yml index 0931fae8e..0b526ae70 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1640,8 +1640,7 @@ jobs: - .\deps - run: name: "Building solidity" - command: .circleci/build_win.ps1 - shell: powershell.exe + command: scripts/ci/build_win.sh - run: name: "Run solc.exe to make sure build was successful." command: .\build\solc\Release\solc.exe --version diff --git a/scripts/ci/build_win.sh b/scripts/ci/build_win.sh new file mode 100755 index 000000000..647cb02d9 --- /dev/null +++ b/scripts/ci/build_win.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -euo pipefail + +(( $# <= 1 )) || { >&2 echo "Usage: $0 [PRERELEASE_SOURCE]"; exit 1; } +prerelease_source="${1:-ci}" +ROOTDIR="$(realpath "$(dirname "$0")/../../")" +FORCE_RELEASE="${FORCE_RELEASE:-}" +CIRCLE_TAG="${CIRCLE_TAG:-}" + +cd "$ROOTDIR" +if [[ $FORCE_RELEASE != "" || $CIRCLE_TAG != "" ]]; then + echo -n > prerelease.txt +else + # Use last commit date rather than build date to avoid ending up with builds for + # different platforms having different version strings (and therefore producing different bytecode) + # if the CI is triggered just before midnight. + # NOTE: The -local suffix makes git not use the timezone from the commit but instead convert to + # local one, which we explicitly set to UTC. + # NOTE: git --date is supposed to support the %-m/%-d format too, but it does not seem to + # work on Windows. Without it we get leading zeros for month and day. + last_commit_date=$(TZ=UTC git show --quiet --date="format-local:%Y-%m-%d" --format="%cd") + last_commit_date_stripped=$(date --date="$last_commit_date" "+%Y.%-m.%-d") + echo -n "${prerelease_source}.${last_commit_date_stripped}" > prerelease.txt +fi + +mkdir -p build/ +cd build/ + +# NOTE: Using an array to force Bash to do wildcard expansion +boost_dir=("${ROOTDIR}/deps/boost/lib/cmake/Boost-"*) + +"${ROOTDIR}/deps/cmake/bin/cmake" \ + -G "Visual Studio 16 2019" \ + -DBoost_DIR="${boost_dir[*]}" \ + -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded \ + -DCMAKE_INSTALL_PREFIX="${ROOTDIR}/uploads/" \ + .. +MSBuild.exe solidity.sln \ + -property:Configuration=Release \ + -maxCpuCount:10 \ + -verbosity:minimal +"${ROOTDIR}/deps/cmake/bin/cmake" \ + --build . \ + -j 10 \ + --target install \ + --config Release From 049980bfd1c9d99216b3d9853a1e66a9d0855342 Mon Sep 17 00:00:00 2001 From: Saw-mon & Natalie <3140080+Saw-mon-and-Natalie@users.noreply.github.com> Date: Wed, 16 Jul 2025 05:28:03 +0200 Subject: [PATCH 0977/1340] add CLZ to YUL build-in instruction for Osaka --- Changelog.md | 1 + docs/grammar/SolidityLexer.g4 | 2 +- docs/yul.rst | 6 +++-- libevmasm/Instruction.cpp | 2 ++ libevmasm/Instruction.h | 1 + libevmasm/SimplificationRule.h | 1 + liblangutil/EVMVersion.cpp | 2 ++ liblangutil/EVMVersion.h | 1 + libyul/AsmAnalysis.cpp | 2 ++ libyul/backends/evm/EVMDialect.cpp | 7 ++++++ scripts/test_antlr_grammar.sh | 2 ++ .../semanticTests/inlineAssembly/clz.sol | 25 +++++++++++++++++++ .../inlineAssembly/clz_pre_osaka.sol | 21 ++++++++++++++++ .../syntaxTests/inlineAssembly/clz.sol | 10 ++++++++ .../inlineAssembly/clz_pre_osaka.sol | 12 +++++++++ .../inlineAssembly/clz_reserved_osaka.sol | 14 +++++++++++ test/libyul/yulInterpreterTests/clz.yul | 15 +++++++++++ test/libyul/yulSyntaxTests/clz.yul | 16 ++++++++++++ test/libyul/yulSyntaxTests/clz_pre_osaka.yul | 14 +++++++++++ .../EVMInstructionInterpreter.cpp | 2 ++ 20 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 test/libsolidity/semanticTests/inlineAssembly/clz.sol create mode 100644 test/libsolidity/semanticTests/inlineAssembly/clz_pre_osaka.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/clz.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/clz_pre_osaka.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/clz_reserved_osaka.sol create mode 100644 test/libyul/yulInterpreterTests/clz.yul create mode 100644 test/libyul/yulSyntaxTests/clz.yul create mode 100644 test/libyul/yulSyntaxTests/clz_pre_osaka.yul diff --git a/Changelog.md b/Changelog.md index 53039947b..14752060a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.8.31 (unreleased) Language Features: +* Yul: Introduce builtin ``clz(x)`` for counting leading zeoros. Compiler Features: * ethdebug: Experimental support for instructions and source locations under EOF. diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index ad3b04098..510b1f180 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -300,7 +300,7 @@ YulHex: 'hex'; YulEVMBuiltin: 'stop' | 'add' | 'sub' | 'mul' | 'div' | 'sdiv' | 'mod' | 'smod' | 'exp' | 'not' | 'lt' | 'gt' | 'slt' | 'sgt' | 'eq' | 'iszero' | 'and' | 'or' | 'xor' | 'byte' - | 'shl' | 'shr' | 'sar' | 'addmod' | 'mulmod' | 'signextend' | 'keccak256' + | 'shl' | 'shr' | 'sar' | 'clz' | 'addmod' | 'mulmod' | 'signextend' | 'keccak256' | 'pop' | 'mload' | 'mstore' | 'mstore8' | 'sload' | 'sstore' | 'tload' | 'tstore'| 'msize' | 'gas' | 'address' | 'balance' | 'selfbalance' | 'caller' | 'callvalue' | 'calldataload' | 'calldatasize' | 'calldatacopy' | 'extcodesize' | 'extcodecopy' | 'returndatasize' diff --git a/docs/yul.rst b/docs/yul.rst index c81c9562a..698d3de17 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -752,8 +752,8 @@ This document does not want to be a full description of the Ethereum virtual mac Please refer to a different document if you are interested in the precise semantics. Opcodes marked with ``-`` do not return a result and all others return exactly one value. -Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L``, ``P`` and ``N`` are present since Frontier, -Homestead, Byzantium, Constantinople, Istanbul, London, Paris or Cancun respectively. +Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L``, ``P``, ``N``, ``R`` and ``O`` are present since +Frontier, Homestead, Byzantium, Constantinople, Istanbul, London, Paris, Cancun, Prague or Osaka respectively. In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to but not including position ``b``, ``storage[p]`` signifies the storage contents at slot ``p``, and @@ -812,6 +812,8 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a +-------------------------+-----+---+-----------------------------------------------------------------+ | sar(x, y) | | C | signed arithmetic shift right y by x bits | +-------------------------+-----+---+-----------------------------------------------------------------+ +| clz(x) | | O | leading zeros of x in binary representation, 256 if x == 0 | ++-------------------------+-----+---+-----------------------------------------------------------------+ | addmod(x, y, m) | | F | (x + y) % m with arbitrary precision arithmetic, 0 if m == 0 | +-------------------------+-----+---+-----------------------------------------------------------------+ | mulmod(x, y, m) | | F | (x * y) % m with arbitrary precision arithmetic, 0 if m == 0 | diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index b55687635..e6648d562 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -51,6 +51,7 @@ std::map> const solidity::evmasm::c_instru { "SHL", Instruction::SHL }, { "SHR", Instruction::SHR }, { "SAR", Instruction::SAR }, + { "CLZ", Instruction::CLZ }, { "ADDMOD", Instruction::ADDMOD }, { "MULMOD", Instruction::MULMOD }, { "SIGNEXTEND", Instruction::SIGNEXTEND }, @@ -219,6 +220,7 @@ static std::map const c_instructionInfo = {Instruction::SHL, {"SHL", 0, 2, 1, false, Tier::VeryLow}}, {Instruction::SHR, {"SHR", 0, 2, 1, false, Tier::VeryLow}}, {Instruction::SAR, {"SAR", 0, 2, 1, false, Tier::VeryLow}}, + {Instruction::CLZ, {"CLZ", 0, 1, 1, false, Tier::Low}}, {Instruction::ADDMOD, {"ADDMOD", 0, 3, 1, false, Tier::Mid}}, {Instruction::MULMOD, {"MULMOD", 0, 3, 1, false, Tier::Mid}}, {Instruction::SIGNEXTEND, {"SIGNEXTEND", 0, 2, 1, false, Tier::Low}}, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index cfdb85d2f..d5b30f463 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -61,6 +61,7 @@ enum class Instruction: uint8_t SHL, ///< bitwise SHL operation SHR, ///< bitwise SHR operation SAR, ///< bitwise SAR operation + CLZ, ///< count of leading zeros in binary representation KECCAK256 = 0x20, ///< compute KECCAK-256 hash diff --git a/libevmasm/SimplificationRule.h b/libevmasm/SimplificationRule.h index 6d34a5041..ea1baa9e5 100644 --- a/libevmasm/SimplificationRule.h +++ b/libevmasm/SimplificationRule.h @@ -98,6 +98,7 @@ struct EVMBuiltins static auto constexpr SHL = PatternGenerator{}; static auto constexpr SHR = PatternGenerator{}; static auto constexpr SAR = PatternGenerator{}; + static auto constexpr CLZ = PatternGenerator{}; static auto constexpr ADDMOD = PatternGenerator{}; static auto constexpr MULMOD = PatternGenerator{}; static auto constexpr SIGNEXTEND = PatternGenerator{}; diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index 4fbfe8de4..33f49ff91 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -42,6 +42,8 @@ bool EVMVersion::hasOpcode(Instruction _opcode, std::optional _eofVersi case Instruction::SHR: case Instruction::SAR: return hasBitwiseShifting(); + case Instruction::CLZ: + return hasCLZ(); case Instruction::CREATE2: return !_eofVersion.has_value() && hasCreate2(); case Instruction::EXTCODEHASH: diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index b5489de0b..799fd2e0f 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -133,6 +133,7 @@ class EVMVersion bool supportsReturndata() const { return *this >= byzantium(); } bool hasStaticCall() const { return *this >= byzantium(); } bool hasBitwiseShifting() const { return *this >= constantinople(); } + bool hasCLZ() const { return *this >= osaka(); } bool hasCreate2() const { return *this >= constantinople(); } bool hasExtCodeHash() const { return *this >= constantinople(); } bool hasChainID() const { return *this >= istanbul(); } diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index b36eb48b4..79d8bfd26 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -834,6 +834,8 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio errorForVM(7458_error, "only available for Constantinople-compatible"); else if (_instr == evmasm::Instruction::SAR && !m_evmVersion.hasBitwiseShifting()) errorForVM(2054_error, "only available for Constantinople-compatible"); + else if (_instr == evmasm::Instruction::CLZ && !m_evmVersion.hasCLZ()) + errorForVM(4948_error, "only available for Osaka-compatible"); else if (_instr == evmasm::Instruction::CREATE2 && !m_evmVersion.hasCreate2()) errorForVM(6166_error, "only available for Constantinople-compatible"); else if (_instr == evmasm::Instruction::EXTCODEHASH && !m_evmVersion.hasExtCodeHash()) diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index c903b9c4d..adb57f577 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -132,6 +132,12 @@ std::set> createReservedIdentifiers(langutil::EVMVersio _evmVersion < langutil::EVMVersion::cancun() && (_instr == evmasm::Instruction::TSTORE || _instr == evmasm::Instruction::TLOAD); }; + // TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name + // clz for VMs before osaka. + auto clzException = [&](evmasm::Instruction _instr) -> bool + { + return _instr == evmasm::Instruction::CLZ && _evmVersion < langutil::EVMVersion::osaka(); + }; auto eofIdentifiersException = [&](evmasm::Instruction _instr) -> bool { @@ -154,6 +160,7 @@ std::set> createReservedIdentifiers(langutil::EVMVersio !blobBaseFeeException(instr.second) && !mcopyException(instr.second) && !transientStorageException(instr.second) && + !clzException(instr.second) && !eofIdentifiersException(instr.second) ) reserved.emplace(name); diff --git a/scripts/test_antlr_grammar.sh b/scripts/test_antlr_grammar.sh index 5256b8128..02e9a634f 100755 --- a/scripts/test_antlr_grammar.sh +++ b/scripts/test_antlr_grammar.sh @@ -131,6 +131,8 @@ done < <( # Skipping a test with "let blobhash := ..." grep -v -E 'inlineAssembly/blobhash_pre_cancun.sol' | grep -v -E 'inlineAssembly/blobhash_pre_cancun_not_reserved.sol' | + # Skipping a test with "let clz := ..." + grep -v -E 'inlineAssembly/clz_pre_osaka.sol' | # Skipping tests with "let tstore/tload := ..." grep -v -E 'inlineAssembly/tload_tstore_not_reserved_before_cancun.sol' | # Skipping license error, unrelated to the grammar diff --git a/test/libsolidity/semanticTests/inlineAssembly/clz.sol b/test/libsolidity/semanticTests/inlineAssembly/clz.sol new file mode 100644 index 000000000..ae4db6901 --- /dev/null +++ b/test/libsolidity/semanticTests/inlineAssembly/clz.sol @@ -0,0 +1,25 @@ +contract C { + function f() public view returns (bytes32 ret) { + assembly { + ret := clz(0) + } + } + + function g() public view returns (bytes32 ret) { + assembly { + ret := clz(1) + } + } + + function h() public view returns (bytes32 ret) { + assembly { + ret := clz(0x4000000000000000000000000000000000000000000000000000000000000000) + } + } +} +// ==== +// EVMVersion: >=osaka +// ---- +// f() -> 256 +// g() -> 255 +// h() -> 1 \ No newline at end of file diff --git a/test/libsolidity/semanticTests/inlineAssembly/clz_pre_osaka.sol b/test/libsolidity/semanticTests/inlineAssembly/clz_pre_osaka.sol new file mode 100644 index 000000000..ec01f7ccb --- /dev/null +++ b/test/libsolidity/semanticTests/inlineAssembly/clz_pre_osaka.sol @@ -0,0 +1,21 @@ +contract C { + function f() public pure returns (uint ret) { + assembly { + let clz := 1 + ret := clz + } + } + function g() public pure returns (uint ret) { + assembly { + function clz() -> r { + r := 1000 + } + ret := clz() + } + } +} +// ==== +// EVMVersion: 1 +// g() -> 1000 diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clz.sol b/test/libsolidity/syntaxTests/inlineAssembly/clz.sol new file mode 100644 index 000000000..720a01089 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/clz.sol @@ -0,0 +1,10 @@ +contract C { + function f(uint256 x) public pure returns (bytes32 ret) { + assembly { + ret := clz(x) + } + } +} +// ==== +// EVMVersion: >=osaka +// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clz_pre_osaka.sol b/test/libsolidity/syntaxTests/inlineAssembly/clz_pre_osaka.sol new file mode 100644 index 000000000..8fa3d543f --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/clz_pre_osaka.sol @@ -0,0 +1,12 @@ +contract C { + function f(uint256 x) public pure returns (bytes32 ret) { + assembly { + ret := clz(x) + } + } +} +// ==== +// EVMVersion: =prague +// ---- +// TypeError 4948: (113-116): The "clz" instruction is only available for Osaka-compatible VMs (you are currently compiling for "prague"). +// DeclarationError 8678: (106-119): Variable count for assignment to "ret" does not match number of values (1 vs. 0) diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clz_reserved_osaka.sol b/test/libsolidity/syntaxTests/inlineAssembly/clz_reserved_osaka.sol new file mode 100644 index 000000000..697b48931 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/clz_reserved_osaka.sol @@ -0,0 +1,14 @@ +contract C { + function f() public pure returns (uint ret) { + assembly { + function clz() -> r { + r := 1000 + } + ret := clz() + } + } +} +// ==== +// EVMVersion: >=osaka +// ---- +// ParserError 5568: (103-106): Cannot use builtin function name "clz" as identifier name. diff --git a/test/libyul/yulInterpreterTests/clz.yul b/test/libyul/yulInterpreterTests/clz.yul new file mode 100644 index 000000000..eab0542d2 --- /dev/null +++ b/test/libyul/yulInterpreterTests/clz.yul @@ -0,0 +1,15 @@ +{ + sstore(0, clz(0)) + sstore(1, clz(1)) + sstore(2, clz(0xff)) +} +// ==== +// EVMVersion: >=osaka +// ---- +// Trace: +// Memory dump: +// Storage dump: +// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000000000000000000000000000000000100 +// 0000000000000000000000000000000000000000000000000000000000000001: 00000000000000000000000000000000000000000000000000000000000000ff +// 0000000000000000000000000000000000000000000000000000000000000002: 00000000000000000000000000000000000000000000000000000000000000f8 +// Transient storage dump: diff --git a/test/libyul/yulSyntaxTests/clz.yul b/test/libyul/yulSyntaxTests/clz.yul new file mode 100644 index 000000000..ee183bc2b --- /dev/null +++ b/test/libyul/yulSyntaxTests/clz.yul @@ -0,0 +1,16 @@ +{ + { + let clz := 1 + } + + { + function clz() {} + clz() + } +} + +// ==== +// EVMVersion: >=osaka +// ---- +// ParserError 5568: (20-23): Cannot use builtin function name "clz" as identifier name. +// ParserError 5568: (59-62): Cannot use builtin function name "clz" as identifier name. diff --git a/test/libyul/yulSyntaxTests/clz_pre_osaka.yul b/test/libyul/yulSyntaxTests/clz_pre_osaka.yul new file mode 100644 index 000000000..e623fd771 --- /dev/null +++ b/test/libyul/yulSyntaxTests/clz_pre_osaka.yul @@ -0,0 +1,14 @@ +{ + { + let clz := 1 + } + + { + function clz() {} + clz() + } +} + +// ==== +// EVMVersion: Date: Thu, 24 Jul 2025 01:25:48 +0200 Subject: [PATCH 0978/1340] some minor adjustments for Changelog and Yul docs for CLZ --- Changelog.md | 2 +- docs/yul.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index 14752060a..748495074 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,7 +1,7 @@ ### 0.8.31 (unreleased) Language Features: -* Yul: Introduce builtin ``clz(x)`` for counting leading zeoros. +* Yul: Introduce builtin `clz(x)` for counting the number of leading zero bits in a 256-bit word. Compiler Features: * ethdebug: Experimental support for instructions and source locations under EOF. diff --git a/docs/yul.rst b/docs/yul.rst index 698d3de17..5c8086b00 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -752,8 +752,8 @@ This document does not want to be a full description of the Ethereum virtual mac Please refer to a different document if you are interested in the precise semantics. Opcodes marked with ``-`` do not return a result and all others return exactly one value. -Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L``, ``P``, ``N``, ``R`` and ``O`` are present since -Frontier, Homestead, Byzantium, Constantinople, Istanbul, London, Paris, Cancun, Prague or Osaka respectively. +Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L``, ``P``, ``N`` and ``O`` are present since +Frontier, Homestead, Byzantium, Constantinople, Istanbul, London, Paris, Cancun or Osaka respectively. In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to but not including position ``b``, ``storage[p]`` signifies the storage contents at slot ``p``, and @@ -812,7 +812,7 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a +-------------------------+-----+---+-----------------------------------------------------------------+ | sar(x, y) | | C | signed arithmetic shift right y by x bits | +-------------------------+-----+---+-----------------------------------------------------------------+ -| clz(x) | | O | leading zeros of x in binary representation, 256 if x == 0 | +| clz(x) | | O | number of leading zero bits of x, 256 if x == 0 | +-------------------------+-----+---+-----------------------------------------------------------------+ | addmod(x, y, m) | | F | (x + y) % m with arbitrary precision arithmetic, 0 if m == 0 | +-------------------------+-----+---+-----------------------------------------------------------------+ From 92429395bcf6326d9fbbdd53bfd2c945bb5a0420 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 16 Oct 2025 08:50:36 +0200 Subject: [PATCH 0979/1340] Yul: Implement CLZ exception in EVMDialect with `hasCLZ` function also resolve a whitespace issue in one test --- libyul/backends/evm/EVMDialect.cpp | 2 +- test/libyul/yulSyntaxTests/clz_pre_osaka.yul | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index adb57f577..62f0d7a69 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -136,7 +136,7 @@ std::set> createReservedIdentifiers(langutil::EVMVersio // clz for VMs before osaka. auto clzException = [&](evmasm::Instruction _instr) -> bool { - return _instr == evmasm::Instruction::CLZ && _evmVersion < langutil::EVMVersion::osaka(); + return _instr == evmasm::Instruction::CLZ && !_evmVersion.hasCLZ(); }; auto eofIdentifiersException = [&](evmasm::Instruction _instr) -> bool diff --git a/test/libyul/yulSyntaxTests/clz_pre_osaka.yul b/test/libyul/yulSyntaxTests/clz_pre_osaka.yul index e623fd771..738096598 100644 --- a/test/libyul/yulSyntaxTests/clz_pre_osaka.yul +++ b/test/libyul/yulSyntaxTests/clz_pre_osaka.yul @@ -11,4 +11,4 @@ // ==== // EVMVersion: Date: Thu, 16 Oct 2025 11:53:26 +0200 Subject: [PATCH 0980/1340] Fix nested list indentation on the prerelease checklist --- ReleaseChecklist.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 1b038ee96..727675fce 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -127,13 +127,13 @@ At least a day before the release: ## Prerelease - [ ] Check that all tests on the latest commit on `develop` or `breaking` branch (whichever was chosen for the prerelease) are green. - [ ] Create a [release on GitHub](https://github.com/argotorg/solidity/releases/new). - - Set the target to the `develop` or `breaking` branch and the tag to the new version with a prerelease suffix, e.g. `v0.8.5-pre.6`. - Version matches the next release (`develop`) or the next breaking release (`breaking`). - The prerelease number in the suffix is 1-based, sequential, resets after a full release and is counted separately for `develop` and `breaking`. - - Include the following warning: `**The release is still in progress. You may see broken links and binaries may not yet be available from all sources.**`. - - Include the current, incomplete changelog. - - Check the `Set as a pre-release` box. - - Click the `Publish release` button on the release page, creating the tag. + - Set the target to the `develop` or `breaking` branch and the tag to the new version with a prerelease suffix, e.g. `v0.8.5-pre.6`. + Version matches the next release (`develop`) or the next breaking release (`breaking`). + The prerelease number in the suffix is 1-based, sequential, resets after a full release and is counted separately for `develop` and `breaking`. + - Include the following warning: `**The release is still in progress. You may see broken links and binaries may not yet be available from all sources.**`. + - Include the current, incomplete changelog. + - Check the `Set as a pre-release` box. + - Click the `Publish release` button on the release page, creating the tag. - [ ] Wait for the CI runs on the tag itself. - [ ] Switch to the tag that archives have to be created for. - [ ] Create the `prerelease.txt` file: `scripts/prerelease_suffix.sh pre "$(git describe --tags --exact-match)" > prerelease.txt`. From b53554f9dbe45a32fae9c7ada518beb3b8a3d2c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 22:14:47 +0200 Subject: [PATCH 0981/1340] docs/conf.py: Fix wrong assumption that missing prerelease.txt represents a release --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 3f7dc3e35..74e45fa2a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -126,7 +126,7 @@ def get_github_username_repo(url): with open('../CMakeLists.txt', 'r', encoding='utf8') as f: version = re.search('PROJECT_VERSION "([^"]+)"', f.read()).group(1) # The full version, including alpha/beta/rc tags. -if not os.path.isfile('../prerelease.txt') or os.path.getsize('../prerelease.txt') == 0: +if os.path.isfile('../prerelease.txt') and os.path.getsize('../prerelease.txt') == 0: release = version else: # This is a prerelease version From 6c068b3049f7351d22ca02ae401d68ab22c2d8ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Oct 2025 19:29:10 +0200 Subject: [PATCH 0982/1340] docs/conf.py: Include the content of prerelease.txt in the version string --- docs/conf.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 74e45fa2a..e71535b9a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -128,8 +128,10 @@ def get_github_username_repo(url): # The full version, including alpha/beta/rc tags. if os.path.isfile('../prerelease.txt') and os.path.getsize('../prerelease.txt') == 0: release = version +elif os.path.isfile('../prerelease.txt'): + with open('../prerelease.txt', 'r', encoding='utf8') as prerelease_file: + release = version + '-' + prerelease_file.read() else: - # This is a prerelease version release = version + '-develop' # The language for content autogenerated by Sphinx. Refer to documentation From 15964caad18dd06a41ddf039c330f0e60213870d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 21:13:40 +0200 Subject: [PATCH 0983/1340] Remove special-casing of the `release` branch - I think we used to have such a branch in the past, but we no longer do and it being handled specially would be completely unexpected by everyone at this point. --- .circleci/config.yml | 2 +- scripts/ci/build.sh | 4 ++-- scripts/ci/build_emscripten.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 58bcb2b9f..bb8acb97b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -187,7 +187,7 @@ commands: - run: name: Store commit hash and prerelease command: | - if [[ $CIRCLE_BRANCH == release || -n $CIRCLE_TAG ]]; then + if [[ -n $CIRCLE_TAG ]]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh index 1acec5a20..451638371 100755 --- a/scripts/ci/build.sh +++ b/scripts/ci/build.sh @@ -9,7 +9,7 @@ prerelease_source="${1:-ci}" cd "${ROOTDIR}" -if [[ $CIRCLE_BRANCH == release || -n $CIRCLE_TAG || -n $FORCE_RELEASE ]]; then +if [[ -n $CIRCLE_TAG || -n $FORCE_RELEASE ]]; then echo -n > prerelease.txt else # Use last commit date rather than build date to avoid ending up with builds for @@ -25,7 +25,7 @@ fi mkdir -p build cd build -[[ -n $COVERAGE && $CIRCLE_BRANCH != release && -z $CIRCLE_TAG ]] && CMAKE_OPTIONS="$CMAKE_OPTIONS -DCOVERAGE=ON" +[[ -n $COVERAGE && -z $CIRCLE_TAG ]] && CMAKE_OPTIONS="$CMAKE_OPTIONS -DCOVERAGE=ON" # shellcheck disable=SC2086 cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" $CMAKE_OPTIONS diff --git a/scripts/ci/build_emscripten.sh b/scripts/ci/build_emscripten.sh index 836c4d41c..71fc888ea 100755 --- a/scripts/ci/build_emscripten.sh +++ b/scripts/ci/build_emscripten.sh @@ -45,7 +45,7 @@ function build() { cd "${ROOT_DIR}" - if [[ $CIRCLE_BRANCH == release || -n $CIRCLE_TAG || -n $FORCE_RELEASE || $(git tag --points-at HEAD 2> /dev/null) == v* ]]; then + if [[ -n $CIRCLE_TAG || -n $FORCE_RELEASE || $(git tag --points-at HEAD 2> /dev/null) == v* ]]; then echo -n > prerelease.txt else # Use last commit date rather than build date to avoid ending up with builds for From 5c21b7fad3a4348743c36a6433b01b776776a4a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 19:19:49 +0200 Subject: [PATCH 0984/1340] Do not store CIRCLE_SHA1 in commit_hash.txt - It is not necessary, because when missing, our CMake config will fetch it from git. --- .circleci/config.yml | 9 ++++----- scripts/ci/build.sh | 4 ---- scripts/ci/build_emscripten.sh | 3 --- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bb8acb97b..fc267010a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -182,17 +182,16 @@ commands: # -------------------------------------------------------------------------- # Build Commands - setup_prerelease_commit_hash: + setup_prerelease: steps: - run: - name: Store commit hash and prerelease + name: Store prerelease suffix command: | if [[ -n $CIRCLE_TAG ]]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi - echo -n "$CIRCLE_SHA1" > commit_hash.txt install_and_check_minimum_requirements: parameters: @@ -1115,7 +1114,7 @@ jobs: <<: *base_ubuntu_clang_large steps: - checkout - - setup_prerelease_commit_hash + - setup_prerelease - run_build_ossfuzz - persist_ossfuzz_executables_to_workspace - matrix_notify_failure_unless_pr @@ -1225,7 +1224,7 @@ jobs: <<: *base_ubuntu2404_small steps: - checkout - - setup_prerelease_commit_hash + - setup_prerelease - run: name: Install build system dependencies command: | diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh index 451638371..fae017d32 100755 --- a/scripts/ci/build.sh +++ b/scripts/ci/build.sh @@ -18,10 +18,6 @@ else TZ=UTC git show --quiet --date="format-local:%Y.%-m.%-d" --format="${prerelease_source}.%cd" > prerelease.txt fi -if [[ -n $CIRCLE_SHA1 ]]; then - echo -n "$CIRCLE_SHA1" > commit_hash.txt -fi - mkdir -p build cd build diff --git a/scripts/ci/build_emscripten.sh b/scripts/ci/build_emscripten.sh index 71fc888ea..9da9f9bc5 100755 --- a/scripts/ci/build_emscripten.sh +++ b/scripts/ci/build_emscripten.sh @@ -53,9 +53,6 @@ function build() { # if the CI is triggered just before midnight. TZ=UTC git show --quiet --date="format-local:%Y.%-m.%-d" --format="${prerelease_source}.%cd" > prerelease.txt fi - if [[ -n $CIRCLE_SHA1 ]]; then - echo -n "$CIRCLE_SHA1" > commit_hash.txt - fi # Disable warnings for unqualified `move()` calls, introduced and enabled by # default in clang-16 which is what the emscripten docker image uses. From 2b950bb878b4accb08567d2296179a16c8411257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 19:08:08 +0200 Subject: [PATCH 0985/1340] create_source_tarball.sh: Fail when commit_hash.txt is present instead of ignoring it --- scripts/create_source_tarball.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/create_source_tarball.sh b/scripts/create_source_tarball.sh index 1a3099245..af13899cd 100755 --- a/scripts/create_source_tarball.sh +++ b/scripts/create_source_tarball.sh @@ -2,6 +2,9 @@ set -euo pipefail REPO_ROOT="$(dirname "$0")"/.. +# shellcheck source=scripts/common.sh +source "${REPO_ROOT}/scripts/common.sh" + cd "$REPO_ROOT" version=$(scripts/get_version.sh) commit_hash=$(git rev-parse --short=8 HEAD) @@ -14,6 +17,11 @@ else version_string="${version}-nightly-${commit_date}-${commit_hash}" fi +# The only purpose of commit_hash.txt is to make it possible to build the compiler without git. +# It is not meant as an override of the real hash. +[[ ! -e commit_hash.txt ]] || \ + fail "commit_hash.txt is present in the repository root, but will not be used to override the commit hash for the source package." + TEMPDIR=$(mktemp -d -t "solc-src-tarball-XXXXXX") SOLDIR="${TEMPDIR}/solidity_${version_string}/" mkdir "$SOLDIR" From a3874f09541b1a47ab354378a63d490e6ec7b1ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 18:56:42 +0200 Subject: [PATCH 0986/1340] create_source_tarball.sh: Use prerelease name from prerelease.txt when available instead of hard-coding "nightly" --- scripts/create_source_tarball.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/create_source_tarball.sh b/scripts/create_source_tarball.sh index af13899cd..28e41edf0 100755 --- a/scripts/create_source_tarball.sh +++ b/scripts/create_source_tarball.sh @@ -13,6 +13,8 @@ commit_date=$(git show --format=%ci HEAD | head -n 1 | cut - -b1-10 | sed -e 's/ # File exists and has zero size -> not a prerelease if [[ -e prerelease.txt && ! -s prerelease.txt ]]; then version_string="$version" +elif [[ -e prerelease.txt ]]; then + version_string="${version}-$(cat prerelease.txt)-${commit_hash}" else version_string="${version}-nightly-${commit_date}-${commit_hash}" fi From af138bf2ce5934adae7316418ea3c29ed84bea1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 15 Oct 2025 18:51:12 +0200 Subject: [PATCH 0987/1340] create_source_tarball.sh: Use UTC timezone when determining the prerelease date --- scripts/create_source_tarball.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create_source_tarball.sh b/scripts/create_source_tarball.sh index 28e41edf0..c175b5045 100755 --- a/scripts/create_source_tarball.sh +++ b/scripts/create_source_tarball.sh @@ -8,7 +8,7 @@ source "${REPO_ROOT}/scripts/common.sh" cd "$REPO_ROOT" version=$(scripts/get_version.sh) commit_hash=$(git rev-parse --short=8 HEAD) -commit_date=$(git show --format=%ci HEAD | head -n 1 | cut - -b1-10 | sed -e 's/-0?/./' | sed -e 's/-0?/./') +commit_date=$(TZ=UTC git show --quiet --date="format-local:%Y.%-m.%-d" --format="%cd") # File exists and has zero size -> not a prerelease if [[ -e prerelease.txt && ! -s prerelease.txt ]]; then From 8fe0df0761ef47c004488da0a00a30ce1fc86336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 19:43:39 +0200 Subject: [PATCH 0988/1340] Unify the prerelease suffix logic across all scripts and CI --- .circleci/config.yml | 6 +----- scripts/build.sh | 6 ++++-- scripts/ci/build.sh | 9 +-------- scripts/ci/build_emscripten.sh | 9 +-------- scripts/ci/build_win.sh | 15 +-------------- scripts/prerelease_suffix.sh | 27 +++++++++++++++++++++++++++ 6 files changed, 35 insertions(+), 37 deletions(-) create mode 100755 scripts/prerelease_suffix.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index fc267010a..e5f4d3cb3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -187,11 +187,7 @@ commands: - run: name: Store prerelease suffix command: | - if [[ -n $CIRCLE_TAG ]]; then - echo -n > prerelease.txt; - else - date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; - fi + "scripts/prerelease_suffix.sh" nightly "$CIRCLE_TAG" > prerelease.txt install_and_check_minimum_requirements: parameters: diff --git a/scripts/build.sh b/scripts/build.sh index 5d7765e6b..33d7bb7c5 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -10,8 +10,10 @@ else BUILD_TYPE="$1" fi -if [[ $(git tag --points-at HEAD 2> /dev/null) == v* ]]; then - touch "${ROOTDIR}/prerelease.txt" +# Intentionally not using prerelease_suffix.sh here. We do not want lingering prerelease.txt in +# dev builds, accidentally overriding version when someone runs the build manually. +if [[ $(git tag --points-at HEAD 2> /dev/null) =~ ^v[0-9.]+$ ]]; then + echo -n > prerelease.txt fi mkdir -p "$BUILDDIR" diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh index fae017d32..b7f7e92f5 100755 --- a/scripts/ci/build.sh +++ b/scripts/ci/build.sh @@ -9,14 +9,7 @@ prerelease_source="${1:-ci}" cd "${ROOTDIR}" -if [[ -n $CIRCLE_TAG || -n $FORCE_RELEASE ]]; then - echo -n > prerelease.txt -else - # Use last commit date rather than build date to avoid ending up with builds for - # different platforms having different version strings (and therefore producing different bytecode) - # if the CI is triggered just before midnight. - TZ=UTC git show --quiet --date="format-local:%Y.%-m.%-d" --format="${prerelease_source}.%cd" > prerelease.txt -fi +"${ROOTDIR}/scripts/prerelease_suffix.sh" "$prerelease_source" "$CIRCLE_TAG" > prerelease.txt mkdir -p build cd build diff --git a/scripts/ci/build_emscripten.sh b/scripts/ci/build_emscripten.sh index 9da9f9bc5..50c851af8 100755 --- a/scripts/ci/build_emscripten.sh +++ b/scripts/ci/build_emscripten.sh @@ -45,14 +45,7 @@ function build() { cd "${ROOT_DIR}" - if [[ -n $CIRCLE_TAG || -n $FORCE_RELEASE || $(git tag --points-at HEAD 2> /dev/null) == v* ]]; then - echo -n > prerelease.txt - else - # Use last commit date rather than build date to avoid ending up with builds for - # different platforms having different version strings (and therefore producing different bytecode) - # if the CI is triggered just before midnight. - TZ=UTC git show --quiet --date="format-local:%Y.%-m.%-d" --format="${prerelease_source}.%cd" > prerelease.txt - fi + "${SCRIPT_DIR}/prerelease_suffix.sh" "$prerelease_source" "$(git tag --points-at HEAD 2> /dev/null)" > prerelease.txt # Disable warnings for unqualified `move()` calls, introduced and enabled by # default in clang-16 which is what the emscripten docker image uses. diff --git a/scripts/ci/build_win.sh b/scripts/ci/build_win.sh index 647cb02d9..64d63c58f 100755 --- a/scripts/ci/build_win.sh +++ b/scripts/ci/build_win.sh @@ -8,20 +8,7 @@ FORCE_RELEASE="${FORCE_RELEASE:-}" CIRCLE_TAG="${CIRCLE_TAG:-}" cd "$ROOTDIR" -if [[ $FORCE_RELEASE != "" || $CIRCLE_TAG != "" ]]; then - echo -n > prerelease.txt -else - # Use last commit date rather than build date to avoid ending up with builds for - # different platforms having different version strings (and therefore producing different bytecode) - # if the CI is triggered just before midnight. - # NOTE: The -local suffix makes git not use the timezone from the commit but instead convert to - # local one, which we explicitly set to UTC. - # NOTE: git --date is supposed to support the %-m/%-d format too, but it does not seem to - # work on Windows. Without it we get leading zeros for month and day. - last_commit_date=$(TZ=UTC git show --quiet --date="format-local:%Y-%m-%d" --format="%cd") - last_commit_date_stripped=$(date --date="$last_commit_date" "+%Y.%-m.%-d") - echo -n "${prerelease_source}.${last_commit_date_stripped}" > prerelease.txt -fi +"${ROOTDIR}/scripts/prerelease_suffix.sh" "$prerelease_source" "$CIRCLE_TAG" > prerelease.txt mkdir -p build/ cd build/ diff --git a/scripts/prerelease_suffix.sh b/scripts/prerelease_suffix.sh new file mode 100755 index 000000000..dc70f706e --- /dev/null +++ b/scripts/prerelease_suffix.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +(( $# <= 2 )) || { >&2 echo "Usage: $0 [PRERELEASE_SOURCE] [GIT_TAG]"; exit 1; } +prerelease_source="${1:-nightly}" +git_tag="${2:-}" +FORCE_RELEASE="${FORCE_RELEASE:-}" + +GNU_DATE="date" +if [[ "$OSTYPE" == "darwin"* ]]; then + GNU_DATE=gdate +fi + +if [[ $FORCE_RELEASE != "" || $git_tag == v* ]]; then + echo -n +else + # Use last commit date rather than build date to avoid ending up with builds for + # different platforms having different version strings (and therefore producing different bytecode) + # if the CI is triggered just before midnight. + # NOTE: The -local suffix makes git not use the timezone from the commit but instead convert to + # local one, which we explicitly set to UTC. + # NOTE: git --date is supposed to support the %-m/%-d format too, but it does not seem to + # work on Windows. Without it we get leading zeros for month and day. + last_commit_date=$(TZ=UTC git show --quiet --date="format-local:%Y-%m-%d" --format="%cd") + last_commit_date_stripped=$("$GNU_DATE" --date "$last_commit_date" "+%Y.%-m.%-d") + echo -n "${prerelease_source}.${last_commit_date_stripped}" +fi From 8439e2abdb471bb7d19e98c06226cd25af002cf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 22:50:47 +0200 Subject: [PATCH 0989/1340] Handle tagged prereleases separately from releases and other prereleases --- .circleci/config.yml | 1 + scripts/create_source_tarball.sh | 20 ++++++++++++++------ scripts/prerelease_suffix.sh | 4 +++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e5f4d3cb3..5d3db526a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1001,6 +1001,7 @@ jobs: <<: *base_ubuntu2404_xlarge steps: - build + - run: cat prerelease.txt # x64 ASAN build, for testing for memory related bugs b_ubu_asan: &b_ubu_asan diff --git a/scripts/create_source_tarball.sh b/scripts/create_source_tarball.sh index c175b5045..0e135ad82 100755 --- a/scripts/create_source_tarball.sh +++ b/scripts/create_source_tarball.sh @@ -8,14 +8,22 @@ source "${REPO_ROOT}/scripts/common.sh" cd "$REPO_ROOT" version=$(scripts/get_version.sh) commit_hash=$(git rev-parse --short=8 HEAD) -commit_date=$(TZ=UTC git show --quiet --date="format-local:%Y.%-m.%-d" --format="%cd") -# File exists and has zero size -> not a prerelease -if [[ -e prerelease.txt && ! -s prerelease.txt ]]; then - version_string="$version" -elif [[ -e prerelease.txt ]]; then - version_string="${version}-$(cat prerelease.txt)-${commit_hash}" +if [[ -e prerelease.txt ]]; then + prerelease_suffix=$(cat prerelease.txt) + if [[ $prerelease_suffix == "" ]]; then + # File exists and has zero size -> not a prerelease + version_string="$version" + elif [[ $prerelease_suffix == pre.* ]]; then + # Tagged prerelease -> unambiguous, so commit hash not needed + version_string="${version}-${prerelease_suffix}" + else + # Nightly/develop/other prerelease -> include commit hash + version_string="${version}-${prerelease_suffix}-${commit_hash}" + fi else + # Nightly/develop/other prerelease -> include commit hash + default prerelease suffix + commit_date=$(TZ=UTC git show --quiet --date="format-local:%Y.%-m.%-d" --format="%cd") version_string="${version}-nightly-${commit_date}-${commit_hash}" fi diff --git a/scripts/prerelease_suffix.sh b/scripts/prerelease_suffix.sh index dc70f706e..2913b12fb 100755 --- a/scripts/prerelease_suffix.sh +++ b/scripts/prerelease_suffix.sh @@ -11,8 +11,10 @@ if [[ "$OSTYPE" == "darwin"* ]]; then GNU_DATE=gdate fi -if [[ $FORCE_RELEASE != "" || $git_tag == v* ]]; then +if [[ $FORCE_RELEASE != "" || $git_tag =~ ^v[0-9.]+$ ]]; then echo -n +elif [[ $git_tag =~ ^v[0-9.]+-pre. ]]; then + echo -n "pre.${git_tag#*-pre.}" else # Use last commit date rather than build date to avoid ending up with builds for # different platforms having different version strings (and therefore producing different bytecode) From 5667f96aee8b501abf9223ec1963540b9bde6066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 16 Oct 2025 17:05:52 +0200 Subject: [PATCH 0990/1340] bytecode_reports_for_modified_binaries.sh: Do not try to iterate over platform binaries when nothing was modified --- scripts/solc-bin/bytecode_reports_for_modified_binaries.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh b/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh index 50a7f53dd..39b45a6e6 100755 --- a/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh +++ b/scripts/solc-bin/bytecode_reports_for_modified_binaries.sh @@ -124,7 +124,12 @@ modified_release_versions=$( uniq ) echo "Release versions modified in the commit range:" -echo "$modified_release_versions" +if [[ $modified_release_versions != "" ]]; then + echo "$modified_release_versions" +else + echo "No modified binaries found." + exit 0 +fi # NOTE: We want perform the check when the soljson-* files in bin/ and wasm/ are modified too # because in that case the symlinks in emscripten-wasm32/ and emscripten-asmjs/ might remain From 4a772b6492f258bc59a8686299234196bd66d65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 16 Oct 2025 17:39:41 +0200 Subject: [PATCH 0991/1340] create_source_tarball.sh: Copy prerelease.txt also when it's non-empty --- scripts/create_source_tarball.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create_source_tarball.sh b/scripts/create_source_tarball.sh index 0e135ad82..9ccbec222 100755 --- a/scripts/create_source_tarball.sh +++ b/scripts/create_source_tarball.sh @@ -45,7 +45,7 @@ SOLDIR="$SOLDIR" git submodule foreach 'git checkout-index --all --prefix="${SOL # Include the commit hash and prerelease suffix in the tarball echo "$commit_hash" > "${SOLDIR}/commit_hash.txt" -[[ -e prerelease.txt && ! -s prerelease.txt ]] && cp prerelease.txt "${SOLDIR}/" +[[ -e prerelease.txt ]] && cp prerelease.txt "${SOLDIR}/" mkdir -p "$REPO_ROOT/upload" tar \ From 439ae46cb42ec1883f188949b48ee4135959c1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 16 Oct 2025 12:39:41 +0200 Subject: [PATCH 0992/1340] Build the source tarball in CI --- .circleci/config.yml | 12 ++++++++++++ ReleaseChecklist.md | 10 ++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5d3db526a..6b596f2b1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1842,6 +1842,17 @@ jobs: - matrix_notify_failure_unless_pr - matrix_notify_release_unless_pr + c_source_tarball: + <<: *base_ubuntu2404_small + steps: + - checkout + - setup_prerelease + - run: scripts/create_source_tarball.sh + - store_artifacts: + path: upload/ + - matrix_notify_failure_unless_pr + - matrix_notify_release_unless_pr + b_alpine_docker: <<: *base_cimg_small steps: @@ -2017,6 +2028,7 @@ workflows: - b_osx - b_win - b_ems + - c_source_tarball: *requires_nothing nightly: diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 727675fce..fe751e896 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -67,10 +67,7 @@ At least a day before the release: - [ ] Wait for the CI runs on the tag itself. ### Upload Release Artifacts and Publish Binaries -- [ ] Switch to the tag that archives have to be created for. -- [ ] Create the `prerelease.txt` file: `echo -n > prerelease.txt`. -- [ ] Run `scripts/create_source_tarball.sh` to create the source tarball. This will create the tarball in a directory called `upload`. -- [ ] Take the tarball from the upload directory (its name should be `solidity_x.x.x.tar.gz`, otherwise `prerelease.txt` was missing in the step before) and upload it to the release page. +- [ ] Take the source tarball (`solidity_x.x.x.tar.gz`) from `c_source_tarball` run of the tagged commit on Circle CI and upload it to the release page. - [ ] Take the `github-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to the release page. Make sure it contains four binaries: `solc-windows.exe`, `solc-macos`, `solc-static-linux` and `soljson.js`. - [ ] Take the `solc-bin-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to solc-bin. @@ -135,10 +132,7 @@ At least a day before the release: - Check the `Set as a pre-release` box. - Click the `Publish release` button on the release page, creating the tag. - [ ] Wait for the CI runs on the tag itself. -- [ ] Switch to the tag that archives have to be created for. -- [ ] Create the `prerelease.txt` file: `scripts/prerelease_suffix.sh pre "$(git describe --tags --exact-match)" > prerelease.txt`. -- [ ] Run `scripts/create_source_tarball.sh` to create the source tarball. This will create the tarball in a directory called `upload`. -- [ ] Take the tarball from the upload directory (its name should be `solidity_x.x.x-pre.N.tar.gz`, if `prerelease.txt` was created correctly) and upload it to the release page. +- [ ] Take the source tarball (`solidity_x.x.x-pre.N.tar.gz`) from `c_source_tarball` run of the tagged commit on Circle CI and upload it to the release page. - [ ] Take the `github-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to the release page. Make sure it contains four binaries: `solc-windows.exe`, `solc-macos`, `solc-static-linux` and `soljson.js`. - [ ] Take the `solc-bin-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to solc-bin. From d74f97be00e32720c1e37fb74b93652991b58b40 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Thu, 16 Oct 2025 16:51:21 +0200 Subject: [PATCH 0993/1340] Bump emscripten docker image --- scripts/build_emscripten.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index 93556a557..a723752ec 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -33,9 +33,9 @@ if (( $# != 0 )); then params="$(printf "%q " "${@}")" fi -# solbuildpackpusher/solidity-buildpack-deps:emscripten-20` +# solbuildpackpusher/solidity-buildpack-deps:emscripten-21 # NOTE: Without `safe.directory` git would assume it's not safe to operate on /root/project since it's owned by a different user. # See https://github.blog/2022-04-12-git-security-vulnerability-announced/ docker run -v "$(pwd):/root/project" -w /root/project \ - solbuildpackpusher/solidity-buildpack-deps@sha256:98f963ed799a0d206ef8e7b5475f847e0dea53b7fdea9618bbc6106a62730bd2 \ + solbuildpackpusher/solidity-buildpack-deps@sha256:fc53d68a4680ffa7d5f70164e13a903478964f15bcc07434d74833a05f4fbc19 \ /bin/bash -c "git config --global --add safe.directory /root/project && ./scripts/ci/build_emscripten.sh ${params}" From 8615ed7bef1231b465f8a176e9b50704fedb3c12 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Wed, 15 Oct 2025 12:51:50 +0200 Subject: [PATCH 0994/1340] Migrate from dockerhub to ghcr.io --- .circleci/config.yml | 2 +- .github/workflows/buildpack-deps.yml | 12 ++++++++---- scripts/Dockerfile | 8 ++++---- scripts/Dockerfile_alpine | 3 ++- scripts/docker_deploy_manual.sh | 8 ++++++-- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6b596f2b1..081005225 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1866,7 +1866,7 @@ jobs: command: scripts/docker_deploy_manual.sh develop "file://$PWD" --no-push - run: name: Smoke test - command: docker run --pull=never ethereum/solc:build-alpine --version + command: docker run --pull=never ghcr.io/argotorg/solc:build-alpine --version - matrix_notify_failure_unless_pr workflows: diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index c4c84dae1..d4e7c5a7e 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -16,8 +16,7 @@ jobs: buildpack-deps: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - DOCKER_REPOSITORY: solbuildpackpusher/solidity-buildpack-deps + DOCKER_REPOSITORY: ghcr.io/argotorg/solidity-buildpack-deps IMAGE_NAME: buildpack-deps runs-on: ubuntu-latest @@ -32,11 +31,16 @@ jobs: with: fetch-depth: 0 + - name: Log in to GitHub Container Registry + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Upgrade ${{ env.IMAGE_NAME }}-${{ matrix.image_variant }} run: | - echo ${DOCKERHUB_TOKEN} | docker login -u solbuildpackpusher --password-stdin scripts/ci/docker_upgrade.sh ${{ env.IMAGE_NAME }} ${{ matrix.image_variant }} ${{ env.DOCKER_REPOSITORY }} - docker logout - name: comment PR if: "env.DOCKER_IMAGE" diff --git a/scripts/Dockerfile b/scripts/Dockerfile index 6df9337ec..fa9f65b6f 100644 --- a/scripts/Dockerfile +++ b/scripts/Dockerfile @@ -1,6 +1,4 @@ FROM alpine AS build -MAINTAINER chriseth -#Official solidity docker image #Establish working directory as solidity WORKDIR /solidity @@ -8,8 +6,8 @@ WORKDIR /solidity # Build dependencies RUN apk update && apk add boost-dev boost-static build-base cmake git clang -#Copy working directory on travis to the image -COPY / $WORKDIR +#Copy working directory to the image +COPY . /solidity # Number of parallel jobs during build # or 0 for auto-computing (max(1, CPU_core_count * 2/3), a greedy value) @@ -34,5 +32,7 @@ RUN make solc \ RUN strip solc/solc FROM scratch +LABEL org.opencontainers.image.source=https://github.com/argotorg/solidity +LABEL maintainer="Solidity Team " COPY --from=build /solidity/solc/solc /usr/bin/solc ENTRYPOINT ["/usr/bin/solc"] diff --git a/scripts/Dockerfile_alpine b/scripts/Dockerfile_alpine index 21bba4566..8db45d102 100644 --- a/scripts/Dockerfile_alpine +++ b/scripts/Dockerfile_alpine @@ -1,5 +1,6 @@ FROM alpine -MAINTAINER chriseth +LABEL org.opencontainers.image.source=https://github.com/argotorg/solidity +LABEL maintainer="Solidity Team " COPY upload/solc-static-linux /usr/local/bin/solc ENTRYPOINT ["/usr/local/bin/solc"] diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index 196a3b36c..c17119ce0 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -6,7 +6,7 @@ REPO_ROOT="$(dirname "$0")/.." # shellcheck source=scripts/common.sh source "${REPO_ROOT}/scripts/common.sh" -image="ethereum/solc" +image="ghcr.io/argotorg/solc" if (( $# < 1 || $# > 3 )); then fail "Usage: $0 [repo URL] [--no-push]" @@ -22,7 +22,11 @@ else publish=true fi -#docker login +# NOTE: Login to GHCR before running this script with a PAT: +# echo $GHCR_TOKEN | docker login ghcr.io -u USERNAME --password-stdin +# +# Create a classic PAT with write:packages scope only visiting the following url: +# https://github.com/settings/tokens/new?scopes=write:packages DIR=$(mktemp -d) ( From 93871f56c09ee80f013c3bbff67c2c3229292947 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:52:51 +0200 Subject: [PATCH 0995/1340] Change docker registry on CI --- .circleci/config.yml | 20 ++++++++++---------- scripts/build_emscripten.sh | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 081005225..76f349a42 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,25 +9,25 @@ version: 2.1 parameters: ubuntu-2004-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-26 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:1f387a77be889f65a2a25986a5c5eccc88cec23fabe6aeaf351790751145c81e" + # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2004-26 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:1f387a77be889f65a2a25986a5c5eccc88cec23fabe6aeaf351790751145c81e" ubuntu-2404-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404-6 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c0412c53e59ce0c96bde4c08e7332ea12e4cadba9bbac829621947897fa21272" + # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404-6 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:c0412c53e59ce0c96bde4c08e7332ea12e4cadba9bbac829621947897fa21272" ubuntu-2404-clang-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu2404.clang-7 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:7466ed23590cf14e60da884894723bcdab064742f017dcfcce015999b4f9143b" + # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.clang-7 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:7466ed23590cf14e60da884894723bcdab064742f017dcfcce015999b4f9143b" ubuntu-clang-ossfuzz-docker-image: type: string - # solbuildpackpusher/solidity-buildpack-deps:ubuntu.clang.ossfuzz-12 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c7088af5082bf764244a6251ecf3dd29d280d2cd2cd071f011f7f32e0326f426" + # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu.clang.ossfuzz-12 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:c7088af5082bf764244a6251ecf3dd29d280d2cd2cd071f011f7f32e0326f426" emscripten-docker-image: type: string # NOTE: Please remember to update the `scripts/build_emscripten.sh` whenever the hash of this image changes. - # solbuildpackpusher/solidity-buildpack-deps:emscripten-21 - default: "solbuildpackpusher/solidity-buildpack-deps@sha256:fc53d68a4680ffa7d5f70164e13a903478964f15bcc07434d74833a05f4fbc19" + # ghcr.io/argotorg/solidity-buildpack-deps:emscripten-21 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:fc53d68a4680ffa7d5f70164e13a903478964f15bcc07434d74833a05f4fbc19" evm-version: type: string default: prague diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index a723752ec..aae4b5c1f 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -33,9 +33,9 @@ if (( $# != 0 )); then params="$(printf "%q " "${@}")" fi -# solbuildpackpusher/solidity-buildpack-deps:emscripten-21 +# ghcr.io/argotorg/solidity-buildpack-deps:emscripten-21 # NOTE: Without `safe.directory` git would assume it's not safe to operate on /root/project since it's owned by a different user. # See https://github.blog/2022-04-12-git-security-vulnerability-announced/ docker run -v "$(pwd):/root/project" -w /root/project \ - solbuildpackpusher/solidity-buildpack-deps@sha256:fc53d68a4680ffa7d5f70164e13a903478964f15bcc07434d74833a05f4fbc19 \ + ghcr.io/argotorg/solidity-buildpack-deps@sha256:fc53d68a4680ffa7d5f70164e13a903478964f15bcc07434d74833a05f4fbc19 \ /bin/bash -c "git config --global --add safe.directory /root/project && ./scripts/ci/build_emscripten.sh ${params}" From 10c874957b30867417f9113985a29a9c1b00d8fe Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:06:54 +0200 Subject: [PATCH 0996/1340] Update the Docker registry in the Solidity documentation --- docs/installing-solidity.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index c9286952e..6f3dfbb7f 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -71,7 +71,7 @@ Please refer to the solc-js repository for instructions. Docker ====== -Docker images of Solidity builds are available using the ``solc`` image from the ``ethereum`` organization. +Docker images of Solidity builds are available using the `solc `_ image from the argotorg organization on ghcr.io. Use the ``stable`` tag for the latest released version, and ``nightly`` for potentially unstable changes in the ``develop`` branch. The Docker image runs the compiler executable so that you can pass all compiler arguments to it. @@ -80,11 +80,11 @@ and runs it in a new container, passing the ``--help`` argument. .. code-block:: bash - docker run ethereum/solc:stable --help + docker run ghcr.io/argotorg/solc:stable --help .. note:: - Specific compiler versions are supported as the Docker image tag such as ``ethereum/solc:0.8.23``. + Specific compiler versions are supported as the Docker image tag such as ``ghcr.io/argotorg/solc:0.8.23``. We will be passing the ``stable`` tag here instead of specific version tag to ensure that users get the latest version by default and avoid the issue of an out-of-date version. @@ -95,7 +95,7 @@ local folder for input and output, and specify the contract to compile. For exam docker run \ --volume "/tmp/some/local/path/:/sources/" \ - ethereum/solc:stable \ + ghcr.io/argotorg/solc:stable \ /sources/Contract.sol \ --abi \ --bin \ @@ -108,7 +108,7 @@ self-contained (i.e. it does not refer to any external files that would have to .. code-block:: bash - docker run ethereum/solc:stable --standard-json < input.json > output.json + docker run ghcr.io/argotorg/solc:stable --standard-json < input.json > output.json Linux Packages ============== From 2086874cc85224756f2724d92fa1c7644f45fded Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Oct 2025 10:04:49 +0200 Subject: [PATCH 0997/1340] EVM instruction interpreter: record linker symbols --- .../EVMInstructionInterpreter.cpp | 21 ++++++++++++++----- .../EVMInstructionInterpreter.h | 4 ++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index c3ce0ed23..cec5d5501 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -534,7 +534,8 @@ u256 EVMInstructionInterpreter::evalBuiltin( return u256(keccak256(arg)) & 0xfff; } } - else if (fun == "datacopy") + + if (fun == "datacopy") { // This is identical to codecopy. if ( @@ -550,11 +551,21 @@ u256 EVMInstructionInterpreter::evalBuiltin( ); return 0; } - else if (fun == "memoryguard") + + if (fun == "memoryguard") return _evaluatedArguments.at(0); - else - yulAssert(false, "Unknown builtin: " + fun); - return 0; + + if (fun == "linkersymbol") + { + yulAssert(_arguments.size() == 1); + yulAssert(std::holds_alternative(_arguments[0])); + std::string const placeholder = formatLiteral(std::get(_arguments[0])); + h256 const identifier(keccak256(placeholder)); + m_linkerSymbols.emplace(identifier, placeholder); + return 0; + } + + yulAssert(false, "Unknown builtin: " + fun); } diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.h b/test/tools/yulInterpreter/EVMInstructionInterpreter.h index d3d221112..dac72ce6a 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.h +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.h @@ -168,6 +168,10 @@ class EVMInstructionInterpreter InterpreterState& m_state; /// Flag to disable trace of instructions that write to memory. bool m_disableMemoryWriteInstructions; + /// mapping from linker identifier (hash of literal) to original string representation, populated by linkersymbol + /// calls + std::map m_linkerSymbols; + public: /// Maximum length for range-based memory access operations. static constexpr unsigned s_maxRangeSize = 0xffff; From 343373b06d40805f6a14f4bbc5fe2cfab959c08e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:15:48 +0200 Subject: [PATCH 0998/1340] Make disjoint set datastructure templatized over value type with explicit instantiation --- libsolutil/DisjointSet.cpp | 26 ++++++++++++++++++-------- libsolutil/DisjointSet.h | 3 ++- test/libsolutil/DisjointSet.cpp | 12 ++++++------ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/libsolutil/DisjointSet.cpp b/libsolutil/DisjointSet.cpp index 43d3bfa18..ef15ea4b5 100644 --- a/libsolutil/DisjointSet.cpp +++ b/libsolutil/DisjointSet.cpp @@ -24,7 +24,8 @@ using namespace solidity::util; -ContiguousDisjointSet::ContiguousDisjointSet(size_t const _numNodes): +template +ContiguousDisjointSet::ContiguousDisjointSet(size_t const _numNodes): m_parents(_numNodes), m_neighbors(_numNodes), m_sizes(_numNodes, static_cast(1)), @@ -35,9 +36,11 @@ ContiguousDisjointSet::ContiguousDisjointSet(size_t const _numNodes): std::iota(m_neighbors.begin(), m_neighbors.end(), 0); } -size_t ContiguousDisjointSet::numSets() const { return m_numSets; } +template +size_t ContiguousDisjointSet::numSets() const { return m_numSets; } -ContiguousDisjointSet::value_type ContiguousDisjointSet::find(value_type const _element) const +template +typename ContiguousDisjointSet::value_type ContiguousDisjointSet::find(value_type const _element) const { solAssert(_element < m_parents.size()); // path halving @@ -50,7 +53,8 @@ ContiguousDisjointSet::value_type ContiguousDisjointSet::find(value_type const _ return rootElement; } -void ContiguousDisjointSet::merge(value_type const _x, value_type const _y, bool const _mergeBySize) +template +void ContiguousDisjointSet::merge(value_type const _x, value_type const _y, bool const _mergeBySize) { auto xRoot = find(_x); auto yRoot = find(_y); @@ -69,17 +73,20 @@ void ContiguousDisjointSet::merge(value_type const _x, value_type const _y, bool --m_numSets; } -bool ContiguousDisjointSet::sameSubset(value_type const _x, value_type const _y) const +template +bool ContiguousDisjointSet::sameSubset(value_type const _x, value_type const _y) const { return find(_x) == find(_y); } -ContiguousDisjointSet::size_type ContiguousDisjointSet::sizeOfSubset(value_type const _x) const +template +typename ContiguousDisjointSet::size_type ContiguousDisjointSet::sizeOfSubset(value_type const _x) const { return m_sizes[find(_x)]; } -std::set ContiguousDisjointSet::subset(value_type const _x) const +template +std::set::value_type> ContiguousDisjointSet::subset(value_type const _x) const { solAssert(_x < m_parents.size()); std::set result{_x}; @@ -92,7 +99,8 @@ std::set ContiguousDisjointSet::subset(value_ return result; } -std::vector> ContiguousDisjointSet::subsets() const +template +std::vector::value_type>> ContiguousDisjointSet::subsets() const { std::vector> result; std::vector visited(m_parents.size(), false); @@ -107,3 +115,5 @@ std::vector> ContiguousDisjointSet:: } return result; } + +template class solidity::util::ContiguousDisjointSet; diff --git a/libsolutil/DisjointSet.h b/libsolutil/DisjointSet.h index 02792cbe6..0d5b048cb 100644 --- a/libsolutil/DisjointSet.h +++ b/libsolutil/DisjointSet.h @@ -31,11 +31,12 @@ namespace solidity::util /// [1] https://en.wikipedia.org/wiki/Disjoint-set_data_structure /// [2] Tarjan, Robert E., and Jan Van Leeuwen. "Worst-case analysis of set union algorithms." /// Journal of the ACM (JACM) 31.2 (1984): 245-281. +template class ContiguousDisjointSet { public: using size_type = size_t; - using value_type = size_t; + using value_type = ValueType; /// Constructs a new disjoint set datastructure with `_numNodes` elements and each element in its own individual set explicit ContiguousDisjointSet(size_t _numNodes); diff --git a/test/libsolutil/DisjointSet.cpp b/test/libsolutil/DisjointSet.cpp index 338138b6a..8fcc994bd 100644 --- a/test/libsolutil/DisjointSet.cpp +++ b/test/libsolutil/DisjointSet.cpp @@ -29,8 +29,8 @@ BOOST_AUTO_TEST_SUITE(DisjointSetTest) BOOST_AUTO_TEST_CASE(full_union) { - ContiguousDisjointSet ds(10); - for (size_t i = 1; i < 10; ++i) + ContiguousDisjointSet ds(10); + for (std::uint32_t i = 1; i < 10; ++i) { BOOST_CHECK(!ds.sameSubset(0, i)); ds.merge(0, i); @@ -42,16 +42,16 @@ BOOST_AUTO_TEST_CASE(full_union) std::set fullSet{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; BOOST_CHECK_EQUAL_COLLECTIONS(subsets[0].begin(), subsets[0].end(), fullSet.begin(), fullSet.end()); - for (size_t i = 1; i < 10; ++i) BOOST_CHECK_EQUAL(ds.find(0), ds.find(i)); + for (std::uint32_t i = 1; i < 10; ++i) BOOST_CHECK_EQUAL(ds.find(0), ds.find(i)); } BOOST_AUTO_TEST_CASE(pairs) { - ContiguousDisjointSet ds(10); + ContiguousDisjointSet ds(10); BOOST_CHECK_EQUAL(ds.numSets(), 10); BOOST_CHECK_EQUAL(ds.subsets().size(), 10); - auto const checkPair = [&](size_t expectedNumSubsets, size_t x, size_t y) + auto const checkPair = [&](size_t expectedNumSubsets, std::uint32_t x, std::uint32_t y) { BOOST_CHECK_EQUAL(ds.numSets(), expectedNumSubsets); BOOST_CHECK_EQUAL(ds.subsets().size(), expectedNumSubsets); @@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE(pairs) BOOST_AUTO_TEST_CASE(merge_with_fixed_representative) { - ContiguousDisjointSet ds(10); + ContiguousDisjointSet ds(10); ds.merge(5, 3, false); BOOST_CHECK_EQUAL(ds.find(5), 5); ds.merge(1, 2); From 1ea88b839979075619ff2721230dbf8156d8c105 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:21:46 +0200 Subject: [PATCH 0999/1340] SSACFG: Use tagged union for ValueId --- libyul/backends/evm/ssa/ControlFlow.cpp | 3 +- libyul/backends/evm/ssa/ControlFlow.h | 30 ++-- libyul/backends/evm/ssa/LivenessAnalysis.cpp | 46 +++--- libyul/backends/evm/ssa/LivenessAnalysis.h | 5 +- libyul/backends/evm/ssa/SSACFG.cpp | 77 +++++---- libyul/backends/evm/ssa/SSACFG.h | 143 ++++++++++------ libyul/backends/evm/ssa/SSACFGBuilder.cpp | 54 +++--- .../evm/ssa/SSACFGLoopNestingForest.cpp | 18 +- .../evm/ssa/SSACFGLoopNestingForest.h | 20 ++- .../evm/ssa/SSACFGTopologicalSort.cpp | 6 +- .../backends/evm/ssa/SSACFGTopologicalSort.h | 26 +-- .../libyul/yulSSAControlFlowGraph/complex.yul | 102 ++++++------ .../yulSSAControlFlowGraph/complex2.yul | 122 +++++++------- .../default_initialized_variable.yul | 18 +- .../yulSSAControlFlowGraph/function.yul | 24 +-- test/libyul/yulSSAControlFlowGraph/if.yul | 20 +-- .../yulSSAControlFlowGraph/if_const.yul | 10 +- .../yulSSAControlFlowGraph/nested_for.yul | 154 +++++++++--------- .../nested_function.yul | 66 ++++---- test/libyul/yulSSAControlFlowGraph/switch.yul | 32 ++-- .../yulSSAControlFlowGraph/switch_const.yul | 10 +- 21 files changed, 523 insertions(+), 463 deletions(-) diff --git a/libyul/backends/evm/ssa/ControlFlow.cpp b/libyul/backends/evm/ssa/ControlFlow.cpp index fb560d6dd..16026ab30 100644 --- a/libyul/backends/evm/ssa/ControlFlow.cpp +++ b/libyul/backends/evm/ssa/ControlFlow.cpp @@ -24,8 +24,7 @@ using namespace solidity::yul::ssa; ControlFlowLiveness::ControlFlowLiveness(ControlFlow const& _controlFlow): controlFlow(_controlFlow), - mainLiveness(std::make_unique(*_controlFlow.mainGraph)), - functionLiveness(_controlFlow.functionGraphs | ranges::views::transform([](auto const& _cfg) { return std::make_unique(*_cfg); }) | ranges::to) + cfgLiveness(_controlFlow.functionGraphs | ranges::views::transform([](auto const& _cfg) { return std::make_unique(*_cfg); }) | ranges::to) { } std::string ControlFlowLiveness::toDot() const diff --git a/libyul/backends/evm/ssa/ControlFlow.h b/libyul/backends/evm/ssa/ControlFlow.h index 314545643..ea07d4d4e 100644 --- a/libyul/backends/evm/ssa/ControlFlow.h +++ b/libyul/backends/evm/ssa/ControlFlow.h @@ -24,6 +24,8 @@ #include #include +#include + namespace solidity::yul::ssa { @@ -33,44 +35,52 @@ struct ControlFlowLiveness{ explicit ControlFlowLiveness(ControlFlow const& _controlFlow); std::reference_wrapper controlFlow; - std::unique_ptr mainLiveness; - std::vector> functionLiveness; + std::vector> cfgLiveness; std::string toDot() const; }; struct ControlFlow { - std::unique_ptr mainGraph{std::make_unique()}; - std::vector> functionGraphs{}; - std::vector> functionGraphMapping{}; + using FunctionGraphID = std::uint32_t; - SSACFG const* functionGraph(Scope::Function const* _function) + static FunctionGraphID constexpr mainGraphID() noexcept { return 0; } + + SSACFG const* mainGraph() const { return functionGraph(mainGraphID()); } + + SSACFG const* functionGraph(Scope::Function const* _function) const { - auto it = std::find_if(functionGraphMapping.begin(), functionGraphMapping.end(), [_function](auto const& tup) { return _function == std::get<0>(tup); }); + auto it = ranges::find_if(functionGraphMapping, [_function](auto const& tup) { return _function == std::get<0>(tup); }); if (it != functionGraphMapping.end()) return std::get<1>(*it); return nullptr; } + SSACFG const* functionGraph(FunctionGraphID const _id) const + { + return functionGraphs.at(_id).get(); + } + std::string toDot(ControlFlowLiveness const* _liveness=nullptr) const { if (_liveness) yulAssert(&_liveness->controlFlow.get() == this); std::ostringstream output; output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; - output << mainGraph->toDot(false, std::nullopt, _liveness ? _liveness->mainLiveness.get() : nullptr); for (size_t index=0; index < functionGraphs.size(); ++index) output << functionGraphs[index]->toDot( false, - index+1, - _liveness ? _liveness->functionLiveness[index].get() : nullptr + index, + _liveness ? _liveness->cfgLiveness[index].get() : nullptr ); output << "}\n"; return output.str(); } + + std::vector> functionGraphs{}; + std::vector> functionGraphMapping{}; }; } diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp index 42d2cf39c..d97ff0097 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -31,18 +31,11 @@ using namespace solidity::yul::ssa; namespace { -constexpr auto excludingLiteralsFilter(SSACFG const& _cfg) +constexpr auto excludingLiteralsFilter() { - return [&_cfg](LivenessAnalysis::LivenessData::Value const& _valueId) -> bool + return [](LivenessAnalysis::LivenessData::Value const& _valueId) -> bool { - return !std::holds_alternative(_cfg.valueInfo(_valueId)); - }; -} -constexpr auto unreachableFilter(SSACFG const& _cfg) -{ - return [&_cfg](LivenessAnalysis::LivenessData::Value const& _valueId) -> bool - { - return std::holds_alternative(_cfg.valueInfo(_valueId)); + return !_valueId.isLiteral(); }; } } @@ -149,18 +142,18 @@ LivenessAnalysis::LivenessData LivenessAnalysis::blockExitValues(SSACFG::BlockId [](SSACFG::BasicBlock::MainExit const&) {}, [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { - for (auto const& valueId: _functionReturn.returnValues | ranges::views::filter(excludingLiteralsFilter(m_cfg))) + for (auto const& valueId: _functionReturn.returnValues | ranges::views::filter(excludingLiteralsFilter())) result.insert(valueId); }, [&](SSACFG::BasicBlock::JumpTable const& _jt) { - if (excludingLiteralsFilter(m_cfg)(_jt.value)) + if (excludingLiteralsFilter()(_jt.value)) result.insert(_jt.value); }, [](SSACFG::BasicBlock::Jump const&) {}, [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { - if (excludingLiteralsFilter(m_cfg)(_conditionalJump.condition)) + if (excludingLiteralsFilter()(_conditionalJump.condition)) result.insert(_conditionalJump.condition); }, [](SSACFG::BasicBlock::Terminated const&) {}}; @@ -218,12 +211,11 @@ void LivenessAnalysis::runDagDfs() { for (auto const& phi: m_cfg.block(_successor).phis) { - auto const& info = m_cfg.valueInfo(phi); - yulAssert(std::holds_alternative(info), "value info of phi wasn't PhiValue"); - auto const argIndex = m_cfg.phiArgumentIndex(blockId, _successor); - yulAssert(argIndex < std::get(info).arguments.size()); - auto const arg = std::get(info).arguments.at(argIndex); - if (!std::holds_alternative(m_cfg.valueInfo(arg))) + auto const& info = m_cfg.phiInfo(phi); + auto const& argIndex = m_cfg.phiArgumentIndex(blockId, _successor); + yulAssert(argIndex < info.arguments.size()); + auto const& arg = info.arguments.at(argIndex); + if (!arg.isLiteral()) live.insert(arg); } }); @@ -242,11 +234,11 @@ void LivenessAnalysis::runDagDfs() }); if (std::holds_alternative(block.exit)) - for (auto const& returnValue: std::get(block.exit).returnValues | ranges::views::filter(excludingLiteralsFilter(m_cfg))) + for (auto const& returnValue: std::get(block.exit).returnValues | ranges::views::filter(excludingLiteralsFilter())) live.insert(returnValue); // clean out unreachables - live.eraseIf([&](auto const& _entry) { return unreachableFilter(m_cfg)(_entry.first); }); + live.eraseIf([&](auto const& _entry) { return _entry.first.isUnreachable(); }); // LiveOut(B) <- live m_liveOuts[blockId.value] = live; @@ -259,9 +251,9 @@ void LivenessAnalysis::runDagDfs() for (auto const& op: block.operations | ranges::views::reverse) { // remove variables defined at p from live - live.eraseAll(op.outputs | ranges::views::filter(excludingLiteralsFilter(m_cfg)) | ranges::to); + live.eraseAll(op.outputs | ranges::views::filter(excludingLiteralsFilter()) | ranges::to); // add uses at p to live - live.insertAll(op.inputs | ranges::views::filter(excludingLiteralsFilter(m_cfg)) | ranges::to); + live.insertAll(op.inputs | ranges::views::filter(excludingLiteralsFilter()) | ranges::to); } } @@ -272,7 +264,7 @@ void LivenessAnalysis::runDagDfs() } } -void LivenessAnalysis::runLoopTreeDfs(size_t const _loopHeader) +void LivenessAnalysis::runLoopTreeDfs(SSACFG::BlockId::ValueType const _loopHeader) { // SSA Book, Algorithm 9.3 if (m_loopNestingForest.loopNodes().contains(_loopHeader)) @@ -286,7 +278,7 @@ void LivenessAnalysis::runLoopTreeDfs(size_t const _loopHeader) // must be live out of header if live in of children m_liveOuts[_loopHeader].maxUnion(liveLoop); // for each blockId \in children(loopHeader) - for (size_t blockIdValue = 0; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) + for (SSACFG::BlockId::ValueType blockIdValue = 0u; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) if (m_loopNestingForest.loopParents()[blockIdValue] == _loopHeader) { // propagate loop liveness information down to the loop header's children @@ -313,9 +305,9 @@ void LivenessAnalysis::fillOperationsLiveOut() for (auto const& op: operations | ranges::views::reverse) { *rit = live; - for (auto const& output: op.outputs | ranges::views::filter(excludingLiteralsFilter(m_cfg))) + for (auto const& output: op.outputs | ranges::views::filter(excludingLiteralsFilter())) live.erase(output); - for (auto const& input: op.inputs | ranges::views::filter(excludingLiteralsFilter(m_cfg))) + for (auto const& input: op.inputs | ranges::views::filter(excludingLiteralsFilter())) live.insert(input); ++rit; } diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.h b/libyul/backends/evm/ssa/LivenessAnalysis.h index 6462af86d..b34a790bf 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.h +++ b/libyul/backends/evm/ssa/LivenessAnalysis.h @@ -42,8 +42,7 @@ class LivenessAnalysis LivenessData() = default; template Sentinel> - LivenessData(Iter begin, Sentinel end): m_liveCounts(begin, end) { - } + LivenessData(Iter begin, Sentinel end): m_liveCounts(begin, end) {} explicit LivenessData(LiveCounts&& _liveCounts): m_liveCounts(std::move(_liveCounts)) {} bool contains(Value const& _valueId) const; @@ -113,7 +112,7 @@ class LivenessAnalysis private: void runDagDfs(); - void runLoopTreeDfs(std::size_t _loopHeader); + void runLoopTreeDfs(SSACFG::BlockId::ValueType _loopHeader); void fillOperationsLiveOut(); LivenessData blockExitValues(SSACFG::BlockId const& _blockId) const; diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 9a98a08ba..a785c51aa 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -28,6 +28,8 @@ #include #pragma GCC diagnostic pop +#include + #include using namespace solidity; @@ -43,41 +45,23 @@ class SSACFGPrinter SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness): m_cfg(_cfg), m_functionIndex(0), m_liveness(_liveness) { + if (_liveness) + m_junkAdmittingBlocks = std::make_unique(_cfg, _liveness->topologicalSort()); printBlock(_blockId); } SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function, LivenessAnalysis const* _liveness): m_cfg(_cfg), m_functionIndex(_functionIndex), m_liveness(_liveness) { + if (_liveness) + m_junkAdmittingBlocks = std::make_unique(_cfg, _liveness->topologicalSort()); printFunction(_function); } friend std::ostream& operator<<(std::ostream& stream, SSACFGPrinter const& printer) { stream << printer.m_result.str(); return stream; } -private: - static std::string varToString(SSACFG const& _cfg, SSACFG::ValueId _var) { - if (_var.value == std::numeric_limits::max()) - return "INVALID"; - auto const& info = _cfg.valueInfo(_var); - return std::visit( - GenericVisitor{ - [&](SSACFG::UnreachableValue const&) -> std::string { - return "[unreachable]"; - }, - [&](SSACFG::PhiValue const&) -> std::string { - return fmt::format("v{}", _var.value); - }, - [&](SSACFG::VariableValue const&) -> std::string { - return fmt::format("v{}", _var.value); - }, - [&](SSACFG::LiteralValue const& _literal) -> std::string { - return formatNumberReadable(_literal.value); - } - }, - info - ); - } +private: static std::string escape(std::string_view const str) { using namespace std::literals; @@ -113,7 +97,7 @@ class SSACFGPrinter static std::string formatPhi(SSACFG const& _cfg, SSACFG::PhiValue const& _phiValue) { - auto const transform = [&](SSACFG::ValueId const& valueId) { return varToString(_cfg, valueId); }; + auto const transform = [&](SSACFG::ValueId const& valueId) { return valueId.str(_cfg); }; std::vector formattedArgs; formattedArgs.reserve(_phiValue.arguments.size()); for (auto const& [arg, entry]: ranges::zip_view(_phiValue.arguments | ranges::views::transform(transform), _cfg.block(_phiValue.block).entries)) @@ -126,7 +110,7 @@ class SSACFGPrinter void writeBlock(SSACFG::BlockId const& _id, SSACFG::BasicBlock const& _block) { - auto const valueToString = [&](SSACFG::ValueId const& valueId) { return varToString(m_cfg, valueId); }; + auto const valueToString = [&](SSACFG::ValueId const& valueId) { return valueId.str(m_cfg); }; bool entryBlock = _id.value == 0 && m_functionIndex == 0; if (entryBlock) { @@ -134,11 +118,15 @@ class SSACFGPrinter m_result << fmt::format("Entry{} -> {};\n", m_functionIndex, formatBlockHandle(_id)); } { + std::string revertPathInfo; + if (m_junkAdmittingBlocks) + revertPathInfo = m_junkAdmittingBlocks->allowsAdditionOfJunk(_id) ? "fillcolor=\"#FF746C\", style=filled, " : ""; if (m_liveness) { m_result << fmt::format( - "{} [label=\"\\\nBlock {}; ({}, max {})\\n", + "{} [{}label=\"\\\nBlock {}; ({}, max {})\\n", formatBlockHandle(_id), + revertPathInfo, _id.value, m_liveness->topologicalSort().preOrderIndexOf(_id.value), m_liveness->topologicalSort().maxSubtreePreOrderIndexOf(_id.value) @@ -151,14 +139,19 @@ class SSACFGPrinter "LiveOut: {}\\l\\n", fmt::join(m_liveness->liveOut(_id) | ranges::views::transform([&](auto const& liveOut) { return valueToString(SSACFG::ValueId{liveOut.first}) + fmt::format("[{}]", liveOut.second); }), ", ") ); + auto const usedVariables = m_liveness->used(_id); + m_result << fmt::format( + "Used: {}\\l\\n", + fmt::join(usedVariables | ranges::views::transform([&](auto const& used) { return valueToString(SSACFG::ValueId{used.first}) + fmt::format("[{}]", used.second); }), ", ") + ); } else - m_result << fmt::format("{} [label=\"\\\nBlock {}\\n", formatBlockHandle(_id), _id.value); + m_result << fmt::format("{} [{}label=\"\\\nBlock {}\\n", formatBlockHandle(_id), revertPathInfo, _id.value); + for (auto const& phi: _block.phis) { - auto const* phiValue = std::get_if(&m_cfg.valueInfo(phi)); - solAssert(phiValue); - m_result << fmt::format("v{} := {}\\l\\\n", phi.value, formatPhi(m_cfg, *phiValue)); + auto const& phiInfo = m_cfg.phiInfo(phi); + m_result << fmt::format("phi{} := {}\\l\\\n", phi.value(), formatPhi(m_cfg, phiInfo)); } for (auto const& operation: _block.operations) { @@ -172,7 +165,7 @@ class SSACFGPrinter [&](SSACFG::LiteralAssignment const&) { yulAssert(operation.inputs.size() == 1); - return varToString(m_cfg, operation.inputs.back()); + return operation.inputs.back().str(m_cfg); } }, operation.kind); if (!operation.outputs.empty()) @@ -210,7 +203,7 @@ class SSACFGPrinter m_result << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); m_result << fmt::format( "{}Exit [label=\"{{ If {} | {{ <0> Zero | <1> NonZero }}}}\" shape=Mrecord];\n", - formatBlockHandle(_id), varToString(m_cfg, _conditionalJump.condition) + formatBlockHandle(_id), _conditionalJump.condition.str(m_cfg) ); m_result << formatEdge(_id, _conditionalJump.zero, "0"); m_result << formatEdge(_id, _conditionalJump.nonZero, "1"); @@ -279,7 +272,7 @@ class SSACFGPrinter void printFunction(Scope::Function const& _fun) { static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return escape(functionReturnValue.get().name.str()); }; - static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", std::get<1>(arg).value); }; + static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", std::get<1>(arg).value()); }; m_result << "FunctionEntry_" << escape(_fun.name.str()) << "_" << m_cfg.entry.value << " [label=\""; if (!m_cfg.returns.empty()) m_result << fmt::format("function {0}:\n {1} := {0}({2})", escape(_fun.name.str()), fmt::join(m_cfg.returns | ranges::views::transform(returnsTransform), ", "), fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); @@ -291,12 +284,28 @@ class SSACFGPrinter } SSACFG const& m_cfg; + std::unique_ptr m_junkAdmittingBlocks; size_t m_functionIndex; LivenessAnalysis const* m_liveness; std::stringstream m_result{}; }; } +std::string SSACFG::ValueId::str(SSACFG const& _cfg) const +{ + if (!hasValue()) + return "INVALID"; + switch (kind()) + { + case Kind::Literal: return toCompactHexWithPrefix(_cfg.literalInfo(*this).value); + case Kind::Variable: return fmt::format("v{}", value()); + case Kind::Phi: return fmt::format("phi{}", value()); + case Kind::Unreachable: return "[unreachable]"; + } + unreachable(); +} + + std::string SSACFG::toDot( bool _includeDiGraphDefinition, std::optional _functionIndex, @@ -305,7 +314,7 @@ std::string SSACFG::toDot( { std::ostringstream output; if (_includeDiGraphDefinition) - output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; + output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\", rankdir=LR]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; if (function) output << SSACFGPrinter(*this, _functionIndex ? *_functionIndex : static_cast(1), *function, _liveness); else diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 5ea8247ce..40537cfcd 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -51,15 +51,50 @@ class SSACFG struct BlockId { - size_t value = std::numeric_limits::max(); + using ValueType = std::uint32_t; + ValueType value = std::numeric_limits::max(); + bool hasValue() const { return value != std::numeric_limits::max(); } auto operator<=>(BlockId const&) const = default; }; - struct ValueId + class ValueId { - using ValueType = size_t; - ValueType value = std::numeric_limits::max(); - bool hasValue() const { return value != std::numeric_limits::max(); } + public: + enum class Kind: std::uint8_t + { + Literal, + Variable, + Phi, + Unreachable + }; + using ValueType = std::uint32_t; + + constexpr ValueId() = default; + constexpr ValueId(ValueType const _value, Kind const _kind): m_value(_value), m_kind(_kind) {} + constexpr ValueId(ValueId const&) = default; + constexpr ValueId(ValueId&&) = default; + constexpr ValueId& operator=(ValueId const&) = default; + constexpr ValueId& operator=(ValueId&&) = default; + + static ValueId constexpr makeLiteral(ValueType const& _value) { return ValueId{_value, Kind::Literal}; } + static ValueId constexpr makeVariable(ValueType const& _value) { return ValueId{_value, Kind::Variable}; } + static ValueId constexpr makePhi(ValueType const& _value) { return ValueId{_value, Kind::Phi}; } + static ValueId constexpr makeUnreachable() { return ValueId{0u, Kind::Unreachable}; } + + bool constexpr isLiteral() const noexcept { return m_kind == Kind::Literal; } + bool constexpr isVariable() const noexcept { return m_kind == Kind::Variable; } + bool constexpr isPhi() const noexcept { return m_kind == Kind::Phi; } + bool constexpr isUnreachable() const noexcept { return m_kind == Kind::Unreachable; } + + bool constexpr hasValue() const { return m_value != std::numeric_limits::max(); } + ValueType constexpr value() const noexcept { return m_value; } + Kind constexpr kind() const noexcept { return m_kind; } + std::string str(SSACFG const& _cfg) const; + auto operator<=>(ValueId const&) const = default; + + private: + ValueType m_value{std::numeric_limits::max()}; + Kind m_kind{Kind::Unreachable}; }; struct BuiltinCall @@ -158,7 +193,7 @@ class SSACFG }; BlockId makeBlock(langutil::DebugData::ConstPtr _debugData) { - BlockId blockId { m_blocks.size() }; + BlockId blockId { static_cast(m_blocks.size()) }; m_blocks.emplace_back(BasicBlock{std::move(_debugData), {}, {}, {}, BasicBlock::Terminated{}}); return blockId; } @@ -183,63 +218,47 @@ class SSACFG std::vector arguments; }; struct UnreachableValue {}; - using ValueInfo = std::variant; - bool isLiteralValue(ValueId const _var) const - { - return std::holds_alternative(valueInfo(_var)); - } - bool isPhiValue(ValueId const _var) const - { - return std::holds_alternative(valueInfo(_var)); - } - ValueInfo& valueInfo(ValueId const _var) - { - return m_valueInfos.at(_var.value); - } - ValueInfo const& valueInfo(ValueId const _var) const - { - return valueInfo(_var.value); - } - ValueInfo const& valueInfo(ValueId::ValueType const _var) const - { - return m_valueInfos.at(_var); - } ValueId newPhi(BlockId const _definingBlock) { - ValueId id { m_valueInfos.size() }; - auto block = m_blocks.at(_definingBlock.value); - m_valueInfos.emplace_back(PhiValue{debugDataOf(block), _definingBlock, {}}); - return id; + auto const& block = m_blocks.at(_definingBlock.value); + m_phis.emplace_back(PhiValue{debugDataOf(block), _definingBlock, std::vector{}}); + auto const value = m_phis.size() - 1; + yulAssert(value < std::numeric_limits::max()); + return ValueId::makePhi(static_cast(value)); } ValueId newVariable(BlockId const _definingBlock) { - ValueId id { m_valueInfos.size() }; - auto block = m_blocks.at(_definingBlock.value); - m_valueInfos.emplace_back(VariableValue{debugDataOf(block), _definingBlock}); - return id; + auto const& block = m_blocks.at(_definingBlock.value); + m_variables.emplace_back(VariableValue{debugDataOf(block), _definingBlock}); + auto const value = m_variables.size() - 1; + yulAssert(value < std::numeric_limits::max()); + return ValueId::makeVariable(static_cast(value)); } + ValueId unreachableValue() { if (!m_unreachableValue) - { - m_unreachableValue = ValueId { m_valueInfos.size() }; - m_valueInfos.emplace_back(UnreachableValue{}); - } + m_unreachableValue = ValueId::makeUnreachable(); return *m_unreachableValue; } + ValueId newLiteral(langutil::DebugData::ConstPtr _debugData, u256 _value) { - auto [it, inserted] = m_literals.emplace(_value, ValueId{m_valueInfos.size()}); - if (inserted) - m_valueInfos.emplace_back(LiteralValue{std::move(_debugData), _value}); - else + auto const it = m_literalMapping.find(_value); + if (it != m_literalMapping.end()) { - yulAssert(_value == it->first); - yulAssert(std::holds_alternative(m_valueInfos.at(it->second.value))); - yulAssert(std::get(m_valueInfos.at(it->second.value)).value == _value); + ValueId const& valueId = it->second; + yulAssert(valueId.hasValue() && m_literals[valueId.value()].value == _value); + return valueId; } - yulAssert(it->second.value < m_valueInfos.size()); - return it->second; + + + m_literals.emplace_back(LiteralValue{std::move(_debugData), std::move(_value)}); + auto const value = m_literals.size() - 1; + yulAssert(value < std::numeric_limits::max()); + auto const literalId = ValueId::makeLiteral(static_cast(value)); + m_literalMapping.emplace(_value, literalId); + return literalId; } size_t phiArgumentIndex(BlockId const _source, BlockId const _target) const @@ -255,9 +274,33 @@ class SSACFG std::optional _functionIndex=std::nullopt, LivenessAnalysis const* _liveness=nullptr ) const; + + PhiValue const& phiInfo(ValueId const& _valueId) const + { + yulAssert(_valueId.hasValue() && _valueId.isPhi()); + return m_phis.at(_valueId.value()); + } + PhiValue& phiInfo(ValueId const& _valueId) + { + yulAssert(_valueId.hasValue() && _valueId.isPhi()); + return m_phis.at(_valueId.value()); + } + LiteralValue const& literalInfo(ValueId const& _valueId) const + { + yulAssert(_valueId.hasValue() && _valueId.isLiteral()); + return m_literals.at(_valueId.value()); + } + VariableValue const& variableInfo(ValueId const& _valueId) const + { + yulAssert(_valueId.hasValue() && _valueId.isVariable()); + return m_variables.at(_valueId.value()); + } + private: - std::deque m_valueInfos; - std::map m_literals; + std::vector m_literals; + std::map m_literalMapping; + std::vector m_phis; + std::vector m_variables; std::optional m_unreachableValue; public: langutil::DebugData::ConstPtr debugData; diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 92b49e7fc..59e28b1b8 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -72,13 +72,16 @@ std::unique_ptr SSACFGBuilder::build( ControlFlowSideEffectsCollector sideEffects(_dialect, _block); auto controlFlow = std::make_unique(); - SSACFGBuilder builder(*controlFlow, *controlFlow->mainGraph, _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments); - builder.m_currentBlock = controlFlow->mainGraph->makeBlock(debugDataOf(_block)); + controlFlow->functionGraphs.emplace_back(std::make_unique()); + controlFlow->functionGraphMapping.emplace_back(nullptr, controlFlow->functionGraphs.back().get()); + SSACFG& mainGraph = *controlFlow->functionGraphs.back(); + SSACFGBuilder builder(*controlFlow, mainGraph, _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments); + builder.m_currentBlock = mainGraph.makeBlock(debugDataOf(_block)); builder.sealBlock(builder.m_currentBlock); builder(_block); if (!builder.blockInfo(builder.m_currentBlock).sealed) builder.sealBlock(builder.m_currentBlock); - controlFlow->mainGraph->block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; + mainGraph.block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; builder.cleanUnreachable(); return controlFlow; } @@ -86,12 +89,11 @@ std::unique_ptr SSACFGBuilder::build( SSACFG::ValueId SSACFGBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) { // TODO: double-check if this is sane - auto const* phiInfo = std::get_if(&m_graph.valueInfo(_phi)); - yulAssert(phiInfo); - yulAssert(blockInfo(phiInfo->block).sealed); + auto const& phiInfo = m_graph.phiInfo(_phi); + yulAssert(blockInfo(phiInfo.block).sealed); SSACFG::ValueId same; - for (SSACFG::ValueId arg: phiInfo->arguments) + for (SSACFG::ValueId arg: phiInfo.arguments) { if (arg == same || arg == _phi) continue; // unique value or self-reference @@ -106,19 +108,19 @@ SSACFG::ValueId SSACFGBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) same = m_graph.unreachableValue(); } - m_graph.block(phiInfo->block).phis.erase(_phi); + m_graph.block(phiInfo.block).phis.erase(_phi); std::vector phiUses; - for (size_t blockIdValue = 0; blockIdValue < m_graph.numBlocks(); ++blockIdValue) + for (SSACFG::BlockId::ValueType blockIdValue = 0; blockIdValue < m_graph.numBlocks(); ++blockIdValue) { auto& block = m_graph.block(SSACFG::BlockId{blockIdValue}); for (auto blockPhi: block.phis) { + yulAssert(blockPhi.hasValue()); yulAssert(blockPhi != _phi, "Phis should be defined in exactly one block, _phi was erased."); - auto* blockPhiInfo = std::get_if(&m_graph.valueInfo(blockPhi)); - yulAssert(blockPhiInfo); + auto& blockPhiInfo = m_graph.phiInfo(blockPhi); bool usedInPhi = false; - for (auto& arg: blockPhiInfo->arguments) + for (auto& arg: blockPhiInfo.arguments) if (arg == _phi) { arg = same; @@ -185,14 +187,15 @@ void SSACFGBuilder::cleanUnreachable() std::vector maybeTrivialPhi; std::erase_if(block.entries, [&](auto const& entry) { return !reachabilityCheck.visited.contains(entry); }); for (auto phi: block.phis) - if (auto* phiInfo = std::get_if(&m_graph.valueInfo(phi))) - { - auto erasedCount = std::erase_if(phiInfo->arguments, [&](SSACFG::ValueId _arg) { - return std::holds_alternative(m_graph.valueInfo(_arg)); - }); - if (erasedCount > 0) - maybeTrivialPhi.push_back(phi); - } + { + yulAssert(phi.hasValue()); + auto& phiInfo = m_graph.phiInfo(phi); + auto const erasedCount = std::erase_if(phiInfo.arguments, [&](SSACFG::ValueId const _arg) { + return _arg.isUnreachable(); + }); + if (erasedCount > 0) + maybeTrivialPhi.push_back(phi); + } // After removing a phi argument, we might end up with a trivial phi that can be removed. for (auto phi: maybeTrivialPhi) @@ -565,7 +568,7 @@ void SSACFGBuilder::assign(std::vector(m_graph.valueInfo(_phi))); - auto& phi = std::get(m_graph.valueInfo(_phi)); - for (auto const& pred: m_graph.block(phi.block).entries) - phi.arguments.emplace_back(readVariable(_variable, pred)); + for (auto const& pred: m_graph.block(m_graph.phiInfo(_phi).block).entries) + { + auto const var = readVariable(_variable, pred); + m_graph.phiInfo(_phi).arguments.emplace_back(var); + } // we call tryRemoveTrivialPhi explicitly to avoid removing trivial phis in unsealed blocks return _phi; } diff --git a/libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp index bbd171a45..c5c422a46 100644 --- a/libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp +++ b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp @@ -18,17 +18,19 @@ #include +#include + using namespace solidity::yul::ssa; SSACFGLoopNestingForest::SSACFGLoopNestingForest(ForwardSSACFGTopologicalSort const& _sort): m_sort(_sort), m_cfg(_sort.cfg()), m_vertexPartition(m_cfg.numBlocks()), - m_loopParents(m_cfg.numBlocks(), std::numeric_limits::max()) + m_loopParents(m_cfg.numBlocks(), std::numeric_limits::max()) { auto dfsOrder = m_sort.preOrder(); // we go from innermost to outermost - std::reverse(dfsOrder.begin(), dfsOrder.end()); + ranges::reverse(dfsOrder); for (auto const& blockId: dfsOrder) findLoop(blockId); @@ -36,18 +38,18 @@ SSACFGLoopNestingForest::SSACFGLoopNestingForest(ForwardSSACFGTopologicalSort co // get the root nodes for (auto loopHeader: m_loopNodes) { - while (m_loopParents[loopHeader] != std::numeric_limits::max()) + while (m_loopParents[loopHeader] != std::numeric_limits::max()) loopHeader = m_loopParents[loopHeader]; m_loopRootNodes.insert(loopHeader); } } -void SSACFGLoopNestingForest::findLoop(size_t const _potentialHeader) +void SSACFGLoopNestingForest::findLoop(BlockIdValue const _potentialHeader) { - if (m_sort.backEdgeTargets().count(_potentialHeader) > 0) + if (m_sort.backEdgeTargets().contains(_potentialHeader)) { - std::set loopBody; - std::set workList; + std::set loopBody; + std::set workList; for (auto const pred: m_cfg.block(SSACFG::BlockId{_potentialHeader}).entries) { auto const representative = m_vertexPartition.find(pred.value); @@ -78,7 +80,7 @@ void SSACFGLoopNestingForest::findLoop(size_t const _potentialHeader) collapse(loopBody, _potentialHeader); } } -void SSACFGLoopNestingForest::collapse(std::set const& _loopBody, size_t _loopHeader) +void SSACFGLoopNestingForest::collapse(std::set const& _loopBody, BlockIdValue _loopHeader) { for (auto const z: _loopBody) { diff --git a/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h index 56cd5ace7..4654cbf13 100644 --- a/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h +++ b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h @@ -36,26 +36,28 @@ namespace solidity::yul::ssa /// ACM Transactions on Programming Languages and Systems (TOPLAS) 21.2 (1999): 175-188. class SSACFGLoopNestingForest { + using BlockIdValue = SSACFG::BlockId::ValueType; + public: explicit SSACFGLoopNestingForest(ForwardSSACFGTopologicalSort const& _sort); /// blocks which are not contained in a loop get assigned the loop parent numeric_limit::max() - std::vector const& loopParents() const { return m_loopParents; } + std::vector const& loopParents() const { return m_loopParents; } /// all loop nodes (entry blocks for loops), also nested ones - std::set const& loopNodes() const { return m_loopNodes; } + std::set const& loopNodes() const { return m_loopNodes; } /// root loop nodes in the forest for outer-most loops - std::set const& loopRootNodes() const { return m_loopRootNodes; } + std::set const& loopRootNodes() const { return m_loopRootNodes; } private: - void findLoop(size_t _potentialHeader); - void collapse(std::set const& _loopBody, size_t _loopHeader); + void findLoop(BlockIdValue _potentialHeader); + void collapse(std::set const& _loopBody, BlockIdValue _loopHeader); ForwardSSACFGTopologicalSort const& m_sort; SSACFG const& m_cfg; - util::ContiguousDisjointSet m_vertexPartition; - std::vector m_loopParents; - std::set m_loopNodes; - std::set m_loopRootNodes; + util::ContiguousDisjointSet m_vertexPartition; + std::vector m_loopParents; + std::set m_loopNodes; + std::set m_loopRootNodes; }; } diff --git a/libyul/backends/evm/ssa/SSACFGTopologicalSort.cpp b/libyul/backends/evm/ssa/SSACFGTopologicalSort.cpp index 222a9774a..3a1ca43c5 100644 --- a/libyul/backends/evm/ssa/SSACFGTopologicalSort.cpp +++ b/libyul/backends/evm/ssa/SSACFGTopologicalSort.cpp @@ -35,10 +35,10 @@ ForwardSSACFGTopologicalSort::ForwardSSACFGTopologicalSort(SSACFG const& _cfg): m_backEdgeTargets.insert(v2); } -void ForwardSSACFGTopologicalSort::dfs(size_t const _vertex) { +void ForwardSSACFGTopologicalSort::dfs(SSACFG::BlockId::ValueType const _vertex) { yulAssert(!m_explored[_vertex]); m_explored[_vertex] = true; - m_blockWisePreOrder[_vertex] = m_preOrder.size(); + m_blockWisePreOrder[_vertex] = static_cast(m_preOrder.size()); m_blockWiseMaxSubtreePreOrder[_vertex] = m_blockWisePreOrder[_vertex]; m_preOrder.push_back(_vertex); @@ -55,7 +55,7 @@ void ForwardSSACFGTopologicalSort::dfs(size_t const _vertex) { m_postOrder.push_back(_vertex); } -bool ForwardSSACFGTopologicalSort::ancestor(size_t const _block1, size_t const _block2) const { +bool ForwardSSACFGTopologicalSort::ancestor(SSACFG::BlockId::ValueType const _block1, SSACFG::BlockId::ValueType const _block2) const { yulAssert(_block1 < m_blockWisePreOrder.size()); yulAssert(_block2 < m_blockWisePreOrder.size()); diff --git a/libyul/backends/evm/ssa/SSACFGTopologicalSort.h b/libyul/backends/evm/ssa/SSACFGTopologicalSort.h index 5eb12545d..39c2eebc3 100644 --- a/libyul/backends/evm/ssa/SSACFGTopologicalSort.h +++ b/libyul/backends/evm/ssa/SSACFGTopologicalSort.h @@ -33,26 +33,26 @@ class ForwardSSACFGTopologicalSort public: explicit ForwardSSACFGTopologicalSort(SSACFG const& _cfg); - std::vector const& preOrder() const { return m_preOrder; } - std::vector const& postOrder() const { return m_postOrder; } - std::set const& backEdgeTargets() const { return m_backEdgeTargets; } + std::vector const& preOrder() const { return m_preOrder; } + std::vector const& postOrder() const { return m_postOrder; } + std::set const& backEdgeTargets() const { return m_backEdgeTargets; } SSACFG const& cfg() const { return m_cfg; } bool backEdge(SSACFG::BlockId const& _block1, SSACFG::BlockId const& _block2) const; - size_t preOrderIndexOf(size_t _block) const { return m_blockWisePreOrder[_block]; } - size_t maxSubtreePreOrderIndexOf(size_t _block) const { return m_blockWiseMaxSubtreePreOrder[_block]; } + SSACFG::BlockId::ValueType preOrderIndexOf(SSACFG::BlockId::ValueType _block) const { return m_blockWisePreOrder[_block]; } + SSACFG::BlockId::ValueType maxSubtreePreOrderIndexOf(SSACFG::BlockId::ValueType _block) const { return m_blockWiseMaxSubtreePreOrder[_block]; } private: - void dfs(size_t _vertex); + void dfs(SSACFG::BlockId::ValueType _vertex); /// Checks if block1 is an ancestor of block2, ie there's a path from block1 to block2 in the dfs tree - bool ancestor(size_t _block1, size_t _block2) const; + bool ancestor(SSACFG::BlockId::ValueType _block1, SSACFG::BlockId::ValueType _block2) const; SSACFG const& m_cfg; std::vector m_explored{}; - std::vector m_postOrder{}; - std::vector m_preOrder{}; - std::vector m_blockWisePreOrder{}; - std::vector m_blockWiseMaxSubtreePreOrder{}; - std::vector> m_potentialBackEdges{}; - std::set m_backEdgeTargets{}; + std::vector m_postOrder{}; + std::vector m_preOrder{}; + std::vector m_blockWisePreOrder{}; + std::vector m_blockWiseMaxSubtreePreOrder{}; + std::vector> m_potentialBackEdges{}; + std::set m_backEdgeTargets{}; }; } diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index e4f29d07e..24ab7af12 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -51,10 +51,10 @@ // // Entry0 [label="Entry"]; // Entry0 -> Block0_0; -// Block0_0 [label="\ +// Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nv2 := f(2, 1)\l\ -// pop(v2)\l\ +// LiveOut: \l\nUsed: \l\nv0 := f(0x02, 0x01)\l\ +// pop(v0)\l\ // "]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; @@ -63,135 +63,135 @@ // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 17)\nLiveIn: v1[1], v0[1]\l\ -// LiveOut: v4[1], v1[1], v0[1]\l\nv4 := 42\l\ +// LiveOut: v2[1], v1[1], v0[1]\l\nUsed: \l\nv2 := 0x2a\l\ // "]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1; (1, max 17)\nLiveIn: v6[4], v1[1], v0[1]\l\ -// LiveOut: v6[2], v1[1], v0[1]\l\nv6 := φ(\l\ -// Block 0 => v4,\l\ -// Block 21 => v44\l\ +// Block 1; (1, max 17)\nLiveIn: phi1[4], v1[1], v0[1]\l\ +// LiveOut: phi1[2], v1[1], v0[1]\l\nUsed: phi1[2]\l\nphi1 := φ(\l\ +// Block 0 => v2,\l\ +// Block 21 => v10\l\ // )\l\ -// v7 := lt(v0, v6)\l\ +// v3 := lt(v0, phi1)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_1Exit:0 -> Block1_4 [style="solid"]; // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2; (2, max 17)\nLiveIn: v6[2], v1[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v8[3], v0[1]\l\nv8 := mload(v6)\l\ -// v9 := eq(0, v8)\l\ +// Block 2; (2, max 17)\nLiveIn: phi1[2], v1[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v4[3], v0[1]\l\nUsed: phi1[1]\l\nv4 := mload(phi1)\l\ +// v5 := eq(0x00, v4)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_2Exit:0 -> Block1_7 [style="solid"]; // Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ // Block 4; (4, max 4)\nLiveIn: \l\ -// LiveOut: \l\nsstore(3084, 12)\l\ +// LiveOut: \l\nUsed: \l\nsstore(0x0c0c, 0x0c)\l\ // "]; -// Block1_4Exit [label="FunctionReturn[0]"]; +// Block1_4Exit [label="FunctionReturn[0x00]"]; // Block1_4 -> Block1_4Exit; // Block1_6 [label="\ // Block 6; (3, max 4)\nLiveIn: \l\ -// LiveOut: \l\nsstore(514, 2)\l\ +// LiveOut: \l\nUsed: \l\nsstore(0x0202, 0x02)\l\ // "]; // Block1_6 -> Block1_6Exit [arrowhead=none]; // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7; (5, max 17)\nLiveIn: v6[1], v1[1], v8[3], v0[1]\l\ -// LiveOut: v6[1], v1[1], v8[2], v0[1]\l\nv14 := eq(1, v8)\l\ +// Block 7; (5, max 17)\nLiveIn: phi1[1], v1[1], v4[3], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v4[2], v0[1]\l\nUsed: v4[1]\l\nv6 := eq(0x01, v4)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v14 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_7Exit:0 -> Block1_10 [style="solid"]; // Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ // Block 9; (6, max 6)\nLiveIn: \l\ -// LiveOut: \l\nsstore(1028, 4)\l\ +// LiveOut: \l\nUsed: \l\nsstore(0x0404, 0x04)\l\ // "]; -// Block1_9Exit [label="FunctionReturn[0]"]; +// Block1_9Exit [label="FunctionReturn[0x00]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10; (7, max 17)\nLiveIn: v6[1], v1[1], v8[2], v0[1]\l\ -// LiveOut: v6[1], v1[1], v8[1], v0[1]\l\nv21 := eq(2, v8)\l\ +// Block 10; (7, max 17)\nLiveIn: phi1[1], v1[1], v4[2], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v4[1], v0[1]\l\nUsed: v4[1]\l\nv7 := eq(0x02, v4)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v21 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_10Exit:0 -> Block1_13 [style="solid"]; // Block1_10Exit:1 -> Block1_12 [style="solid"]; -// Block1_12 [label="\ +// Block1_12 [fillcolor="#FF746C", style=filled, label="\ // Block 12; (8, max 8)\nLiveIn: \l\ -// LiveOut: \l\nsstore(1542, 6)\l\ -// revert(0, 0)\l\ +// LiveOut: \l\nUsed: \l\nsstore(0x0606, 0x06)\l\ +// revert(0x00, 0x00)\l\ // "]; // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13; (9, max 17)\nLiveIn: v6[1], v1[1], v8[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v0[1]\l\nv26 := eq(3, v8)\l\ +// Block 13; (9, max 17)\nLiveIn: phi1[1], v1[1], v4[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: v4[1]\l\nv8 := eq(0x03, v4)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v26 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15; (10, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2056, 8)\l\ +// Block 15; (10, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0808, 0x08)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16; (15, max 17)\nLiveIn: v6[1], v1[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v0[1]\l\nv30 := mload(v1)\l\ +// Block 16; (15, max 17)\nLiveIn: phi1[1], v1[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nv9 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v30 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5; (11, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2827, 11)\l\ +// Block 5; (11, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0b0b, 0x0b)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; // Block1_5Exit -> Block1_3 [style="solid"]; -// Block1_17 [label="\ +// Block1_17 [fillcolor="#FF746C", style=filled, label="\ // Block 17; (16, max 16)\nLiveIn: \l\ -// LiveOut: \l\nreturn(0, 0)\l\ +// LiveOut: \l\nUsed: \l\nreturn(0x00, 0x00)\l\ // "]; // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18; (17, max 17)\nLiveIn: v6[1], v1[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2570, 10)\l\ +// Block 18; (17, max 17)\nLiveIn: phi1[1], v1[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0a0a, 0x0a)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3; (12, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ -// LiveOut: v44[1], v1[1], v0[1]\l\nv44 := add(1, v6)\l\ -// v45 := calldataload(v44)\l\ +// Block 3; (12, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ +// LiveOut: v10[1], v1[1], v0[1]\l\nUsed: phi1[1]\l\nv10 := add(0x01, phi1)\l\ +// v11 := calldataload(v10)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v45 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit [label="{ If v11 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v44[1]\l\ -// LiveOut: \l\nsstore(v44, 0)\l\ +// Block 20; (13, max 13)\nLiveIn: v10[1]\l\ +// LiveOut: \l\nUsed: v10[1]\l\nsstore(v10, 0x00)\l\ // "]; -// Block1_20Exit [label="FunctionReturn[0]"]; +// Block1_20Exit [label="FunctionReturn[0x00]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v44[1], v1[1], v0[1]\l\ -// LiveOut: v44[1], v1[1], v0[1]\l\nsstore(65535, 255)\l\ +// Block 21; (14, max 14)\nLiveIn: v10[1], v1[1], v0[1]\l\ +// LiveOut: v10[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index 6e94670ba..9910d8356 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -58,19 +58,19 @@ // // Entry0 [label="Entry"]; // Entry0 -> Block0_0; -// Block0_0 [label="\ +// Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nsstore(1, 1)\l\ -// v2 := f(2, 1)\l\ -// pop(v2)\l\ -// v4 := sload(0)\l\ -// v6 := add(v4, 5)\l\ -// v8 := sload(4)\l\ -// v9 := f(v8, v6)\l\ -// sstore(v9, v6)\l\ -// v10 := sload(5)\l\ -// v11 := f(v10, v9)\l\ -// sstore(v11, 1)\l\ +// LiveOut: \l\nUsed: \l\nsstore(0x01, 0x01)\l\ +// v0 := f(0x02, 0x01)\l\ +// pop(v0)\l\ +// v1 := sload(0x00)\l\ +// v2 := add(v1, 0x05)\l\ +// v3 := sload(0x04)\l\ +// v4 := f(v3, v2)\l\ +// sstore(v4, v2)\l\ +// v5 := sload(0x05)\l\ +// v6 := f(v5, v4)\l\ +// sstore(v6, 0x01)\l\ // "]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; @@ -79,136 +79,136 @@ // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 17)\nLiveIn: v1[1], v0[1]\l\ -// LiveOut: v4[1], v1[1], v0[1]\l\nv4 := 42\l\ +// LiveOut: v2[1], v1[1], v0[1]\l\nUsed: \l\nv2 := 0x2a\l\ // "]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1; (1, max 17)\nLiveIn: v6[4], v1[1], v0[1]\l\ -// LiveOut: v6[2], v1[1], v0[1]\l\nv6 := φ(\l\ -// Block 0 => v4,\l\ -// Block 21 => v44\l\ +// Block 1; (1, max 17)\nLiveIn: phi1[4], v1[1], v0[1]\l\ +// LiveOut: phi1[2], v1[1], v0[1]\l\nUsed: phi1[2]\l\nphi1 := φ(\l\ +// Block 0 => v2,\l\ +// Block 21 => v10\l\ // )\l\ -// v7 := lt(v0, v6)\l\ +// v3 := lt(v0, phi1)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_1Exit:0 -> Block1_4 [style="solid"]; // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2; (2, max 17)\nLiveIn: v6[2], v1[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v8[3], v0[1]\l\nv8 := mload(v6)\l\ -// v9 := eq(0, v8)\l\ +// Block 2; (2, max 17)\nLiveIn: phi1[2], v1[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v4[3], v0[1]\l\nUsed: phi1[1]\l\nv4 := mload(phi1)\l\ +// v5 := eq(0x00, v4)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_2Exit:0 -> Block1_7 [style="solid"]; // Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ // Block 4; (4, max 4)\nLiveIn: \l\ -// LiveOut: v78[1]\l\nsstore(3084, 12)\l\ -// v78 := 27\l\ +// LiveOut: v12[1]\l\nUsed: \l\nsstore(0x0c0c, 0x0c)\l\ +// v12 := 0x1b\l\ // "]; -// Block1_4Exit [label="FunctionReturn[v78]"]; +// Block1_4Exit [label="FunctionReturn[v12]"]; // Block1_4 -> Block1_4Exit; // Block1_6 [label="\ // Block 6; (3, max 4)\nLiveIn: \l\ -// LiveOut: \l\nsstore(514, 2)\l\ +// LiveOut: \l\nUsed: \l\nsstore(0x0202, 0x02)\l\ // "]; // Block1_6 -> Block1_6Exit [arrowhead=none]; // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7; (5, max 17)\nLiveIn: v6[1], v1[1], v8[3], v0[1]\l\ -// LiveOut: v6[1], v1[1], v8[2], v0[1]\l\nv14 := eq(1, v8)\l\ +// Block 7; (5, max 17)\nLiveIn: phi1[1], v1[1], v4[3], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v4[2], v0[1]\l\nUsed: v4[1]\l\nv6 := eq(0x01, v4)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v14 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_7Exit:0 -> Block1_10 [style="solid"]; // Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ // Block 9; (6, max 6)\nLiveIn: \l\ -// LiveOut: \l\nsstore(1028, 4)\l\ +// LiveOut: \l\nUsed: \l\nsstore(0x0404, 0x04)\l\ // "]; -// Block1_9Exit [label="FunctionReturn[0]"]; +// Block1_9Exit [label="FunctionReturn[0x00]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10; (7, max 17)\nLiveIn: v6[1], v1[1], v8[2], v0[1]\l\ -// LiveOut: v6[1], v1[1], v8[1], v0[1]\l\nv21 := eq(2, v8)\l\ +// Block 10; (7, max 17)\nLiveIn: phi1[1], v1[1], v4[2], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v4[1], v0[1]\l\nUsed: v4[1]\l\nv7 := eq(0x02, v4)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v21 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_10Exit:0 -> Block1_13 [style="solid"]; // Block1_10Exit:1 -> Block1_12 [style="solid"]; -// Block1_12 [label="\ +// Block1_12 [fillcolor="#FF746C", style=filled, label="\ // Block 12; (8, max 8)\nLiveIn: \l\ -// LiveOut: \l\nsstore(1542, 6)\l\ -// revert(0, 0)\l\ +// LiveOut: \l\nUsed: \l\nsstore(0x0606, 0x06)\l\ +// revert(0x00, 0x00)\l\ // "]; // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13; (9, max 17)\nLiveIn: v6[1], v1[1], v8[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v0[1]\l\nv26 := eq(3, v8)\l\ +// Block 13; (9, max 17)\nLiveIn: phi1[1], v1[1], v4[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: v4[1]\l\nv8 := eq(0x03, v4)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v26 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15; (10, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2056, 8)\l\ +// Block 15; (10, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0808, 0x08)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16; (15, max 17)\nLiveIn: v6[1], v1[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v0[1]\l\nv30 := mload(v1)\l\ +// Block 16; (15, max 17)\nLiveIn: phi1[1], v1[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nv9 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v30 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5; (11, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2827, 11)\l\ +// Block 5; (11, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0b0b, 0x0b)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; // Block1_5Exit -> Block1_3 [style="solid"]; -// Block1_17 [label="\ +// Block1_17 [fillcolor="#FF746C", style=filled, label="\ // Block 17; (16, max 16)\nLiveIn: \l\ -// LiveOut: \l\nreturn(0, 0)\l\ +// LiveOut: \l\nUsed: \l\nreturn(0x00, 0x00)\l\ // "]; // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18; (17, max 17)\nLiveIn: v6[1], v1[1], v0[1]\l\ -// LiveOut: v6[1], v1[1], v0[1]\l\nsstore(2570, 10)\l\ +// Block 18; (17, max 17)\nLiveIn: phi1[1], v1[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0a0a, 0x0a)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3; (12, max 14)\nLiveIn: v6[1], v1[1], v0[1]\l\ -// LiveOut: v44[1], v1[1], v0[1]\l\nv44 := add(1, v6)\l\ -// v45 := calldataload(v44)\l\ +// Block 3; (12, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ +// LiveOut: v10[1], v1[1], v0[1]\l\nUsed: phi1[1]\l\nv10 := add(0x01, phi1)\l\ +// v11 := calldataload(v10)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v45 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit [label="{ If v11 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v44[1]\l\ -// LiveOut: \l\nsstore(v44, 0)\l\ +// Block 20; (13, max 13)\nLiveIn: v10[1]\l\ +// LiveOut: \l\nUsed: v10[1]\l\nsstore(v10, 0x00)\l\ // "]; -// Block1_20Exit [label="FunctionReturn[0]"]; +// Block1_20Exit [label="FunctionReturn[0x00]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v44[1], v1[1], v0[1]\l\ -// LiveOut: v44[1], v1[1], v0[1]\l\nsstore(65535, 255)\l\ +// Block 21; (14, max 14)\nLiveIn: v10[1], v1[1], v0[1]\l\ +// LiveOut: v10[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul b/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul index 799bd94ca..14a80dadc 100644 --- a/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul +++ b/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul @@ -15,27 +15,27 @@ // Entry0 -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: v1[1]\l\nv1 := 0\l\ -// v3 := mload(42)\l\ +// LiveOut: v0[1]\l\nUsed: \l\nv0 := 0x00\l\ +// v1 := mload(0x2a)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_0Exit:0 -> Block0_2 [style="solid"]; // Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v5[1]\l\nv5 := 5\l\ +// LiveOut: v2[1]\l\nUsed: \l\nv2 := 0x05\l\ // "]; // Block0_1 -> Block0_1Exit [arrowhead=none]; // Block0_1Exit [label="Jump" shape=oval]; // Block0_1Exit -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: v6[3]\l\ -// LiveOut: \l\nv6 := φ(\l\ -// Block 0 => v1,\l\ -// Block 1 => v5\l\ +// Block 2; (2, max 2)\nLiveIn: phi0[3]\l\ +// LiveOut: \l\nUsed: phi0[3]\l\nphi0 := φ(\l\ +// Block 0 => v0,\l\ +// Block 1 => v2\l\ // )\l\ -// sstore(v6, v6)\l\ +// sstore(phi0, phi0)\l\ // "]; // Block0_2Exit [label="MainExit"]; // Block0_2 -> Block0_2Exit; diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/yulSSAControlFlowGraph/function.yul index e12583676..f5090b826 100644 --- a/test/libyul/yulSSAControlFlowGraph/function.yul +++ b/test/libyul/yulSSAControlFlowGraph/function.yul @@ -26,9 +26,9 @@ // // Entry0 [label="Entry"]; // Entry0 -> Block0_0; -// Block0_0 [label="\ +// Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nv0, v1 := i()\l\ +// LiveOut: \l\nUsed: \l\nv0, v1 := i()\l\ // h(v0)\l\ // "]; // Block0_0Exit [label="Terminated"]; @@ -38,27 +38,27 @@ // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 0)\nLiveIn: v0[2], v1[1]\l\ -// LiveOut: v4[1]\l\nv3 := add(v1, v0)\l\ -// v4 := sub(v0, v3)\l\ +// LiveOut: v3[1]\l\nUsed: v0[2], v1[1]\l\nv2 := add(v1, v0)\l\ +// v3 := sub(v0, v2)\l\ // "]; -// Block1_0Exit [label="FunctionReturn[v4]"]; +// Block1_0Exit [label="FunctionReturn[v3]"]; // Block1_0 -> Block1_0Exit; // FunctionEntry_g_0 [label="function g: // g()"]; // FunctionEntry_g_0 -> Block2_0; // Block2_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nsstore(257, 1)\l\ +// LiveOut: \l\nUsed: \l\nsstore(0x0101, 0x01)\l\ // "]; // Block2_0Exit [label="FunctionReturn[]"]; // Block2_0 -> Block2_0Exit; // FunctionEntry_h_0 [label="function h: // h(v0)"]; // FunctionEntry_h_0 -> Block3_0; -// Block3_0 [label="\ +// Block3_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: v0[1]\l\ -// LiveOut: \l\nv2 := f(0, v0)\l\ -// h(v2)\l\ +// LiveOut: \l\nUsed: v0[1]\l\nv1 := f(0x00, v0)\l\ +// h(v1)\l\ // "]; // Block3_0Exit [label="Terminated"]; // Block3_0 -> Block3_0Exit; @@ -67,9 +67,9 @@ // FunctionEntry_i_0 -> Block4_0; // Block4_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v2[1], v4[1]\l\nv2 := 514\l\ -// v4 := 771\l\ +// LiveOut: v0[1], v1[1]\l\nUsed: \l\nv0 := 0x0202\l\ +// v1 := 0x0303\l\ // "]; -// Block4_0Exit [label="FunctionReturn[v2, v4]"]; +// Block4_0Exit [label="FunctionReturn[v0, v1]"]; // Block4_0 -> Block4_0Exit; // } diff --git a/test/libyul/yulSSAControlFlowGraph/if.yul b/test/libyul/yulSSAControlFlowGraph/if.yul index 16fc8957d..540947e18 100644 --- a/test/libyul/yulSSAControlFlowGraph/if.yul +++ b/test/libyul/yulSSAControlFlowGraph/if.yul @@ -16,28 +16,28 @@ // Entry0 -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: v1[1]\l\nv1 := calldataload(3)\l\ -// v3 := mload(42)\l\ +// LiveOut: v0[1]\l\nUsed: \l\nv0 := calldataload(0x03)\l\ +// v1 := mload(0x2a)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_0Exit:0 -> Block0_2 [style="solid"]; // Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v5[1]\l\nv5 := calldataload(77)\l\ +// LiveOut: v2[1]\l\nUsed: \l\nv2 := calldataload(0x4d)\l\ // "]; // Block0_1 -> Block0_1Exit [arrowhead=none]; // Block0_1Exit [label="Jump" shape=oval]; // Block0_1Exit -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: v6[2]\l\ -// LiveOut: \l\nv6 := φ(\l\ -// Block 0 => v1,\l\ -// Block 1 => v5\l\ +// Block 2; (2, max 2)\nLiveIn: phi0[2]\l\ +// LiveOut: \l\nUsed: phi0[2]\l\nphi0 := φ(\l\ +// Block 0 => v0,\l\ +// Block 1 => v2\l\ // )\l\ -// v7 := calldataload(v6)\l\ -// sstore(0, v7)\l\ +// v3 := calldataload(phi0)\l\ +// sstore(0x00, v3)\l\ // "]; // Block0_2Exit [label="MainExit"]; // Block0_2 -> Block0_2Exit; diff --git a/test/libyul/yulSSAControlFlowGraph/if_const.yul b/test/libyul/yulSSAControlFlowGraph/if_const.yul index 26a3c094c..d8be1eaf2 100644 --- a/test/libyul/yulSSAControlFlowGraph/if_const.yul +++ b/test/libyul/yulSSAControlFlowGraph/if_const.yul @@ -19,12 +19,12 @@ // // Entry0 [label="Entry"]; // Entry0 -> Block0_0; -// Block0_0 [label="\ +// Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nv1 := calldataload(3)\l\ -// v3 := calldataload(42)\l\ -// v4 := calldataload(v3)\l\ -// sstore(0, v4)\l\ +// LiveOut: \l\nUsed: \l\nv0 := calldataload(0x03)\l\ +// v1 := calldataload(0x2a)\l\ +// v2 := calldataload(v1)\l\ +// sstore(0x00, v2)\l\ // "]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/yulSSAControlFlowGraph/nested_for.yul index 8d5060951..e9e575140 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_for.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_for.yul @@ -25,201 +25,201 @@ // // Entry0 [label="Entry"]; // Entry0 -> Block0_0; -// Block0_0 [label="\ +// Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 24)\nLiveIn: \l\ -// LiveOut: v1[1]\l\nv1 := 0\l\ +// LiveOut: v0[1]\l\nUsed: \l\nv0 := 0x00\l\ // "]; // Block0_0 -> Block0_0Exit [arrowhead=none]; // Block0_0Exit [label="Jump" shape=oval]; // Block0_0Exit -> Block0_1 [style="solid"]; -// Block0_1 [label="\ -// Block 1; (1, max 24)\nLiveIn: v3[3]\l\ -// LiveOut: v3[1]\l\nv3 := φ(\l\ -// Block 0 => v1,\l\ -// Block 3 => v43\l\ +// Block0_1 [fillcolor="#FF746C", style=filled, label="\ +// Block 1; (1, max 24)\nLiveIn: phi0[3]\l\ +// LiveOut: phi0[1]\l\nUsed: phi0[2]\l\nphi0 := φ(\l\ +// Block 0 => v0,\l\ +// Block 3 => v20\l\ // )\l\ -// v4 := lt(3, v3)\l\ +// v1 := lt(0x03, phi0)\l\ // "]; // Block0_1 -> Block0_1Exit; -// Block0_1Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_1Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_1Exit:0 -> Block0_4 [style="solid"]; // Block0_1Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2; (2, max 23)\nLiveIn: v3[1]\l\ -// LiveOut: v5[1], v3[1]\l\nv5 := 0\l\ +// Block 2; (2, max 23)\nLiveIn: phi0[1]\l\ +// LiveOut: v2[1], phi0[1]\l\nUsed: \l\nv2 := 0x00\l\ // "]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; // Block0_2Exit -> Block0_5 [style="solid"]; -// Block0_4 [label="\ +// Block0_4 [fillcolor="#FF746C", style=filled, label="\ // Block 4; (24, max 24)\nLiveIn: \l\ -// LiveOut: \l\n"]; +// LiveOut: \l\nUsed: \l\n"]; // Block0_4Exit [label="MainExit"]; // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ -// Block 5; (3, max 23)\nLiveIn: v6[3], v3[1]\l\ -// LiveOut: v6[1], v3[1]\l\nv6 := φ(\l\ -// Block 2 => v5,\l\ -// Block 7 => v42\l\ +// Block 5; (3, max 23)\nLiveIn: phi1[3], phi0[1]\l\ +// LiveOut: phi1[1], phi0[1]\l\nUsed: phi1[2]\l\nphi1 := φ(\l\ +// Block 2 => v2,\l\ +// Block 7 => v19\l\ // )\l\ -// v7 := lt(3, v6)\l\ +// v3 := lt(0x03, phi1)\l\ // "]; // Block0_5 -> Block0_5Exit; -// Block0_5Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_5Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_5Exit:0 -> Block0_8 [style="solid"]; // Block0_5Exit:1 -> Block0_6 [style="solid"]; // Block0_6 [label="\ -// Block 6; (4, max 21)\nLiveIn: v6[1], v3[1]\l\ -// LiveOut: v8[1], v6[1], v3[1]\l\nv8 := 0\l\ +// Block 6; (4, max 21)\nLiveIn: phi1[1], phi0[1]\l\ +// LiveOut: v4[1], phi1[1], phi0[1]\l\nUsed: \l\nv4 := 0x00\l\ // "]; // Block0_6 -> Block0_6Exit [arrowhead=none]; // Block0_6Exit [label="Jump" shape=oval]; // Block0_6Exit -> Block0_9 [style="solid"]; // Block0_8 [label="\ -// Block 8; (22, max 23)\nLiveIn: v3[1]\l\ -// LiveOut: v3[1]\l\n"]; +// Block 8; (22, max 23)\nLiveIn: phi0[1]\l\ +// LiveOut: phi0[1]\l\nUsed: \l\n"]; // Block0_8 -> Block0_8Exit [arrowhead=none]; // Block0_8Exit [label="Jump" shape=oval]; // Block0_8Exit -> Block0_3 [style="solid"]; // Block0_9 [label="\ -// Block 9; (5, max 21)\nLiveIn: v9[3], v6[1], v3[1]\l\ -// LiveOut: v9[1], v6[1], v3[1]\l\nv9 := φ(\l\ -// Block 6 => v8,\l\ -// Block 11 => v38\l\ +// Block 9; (5, max 21)\nLiveIn: phi2[3], phi1[1], phi0[1]\l\ +// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: phi2[2]\l\nphi2 := φ(\l\ +// Block 6 => v4,\l\ +// Block 11 => v18\l\ // )\l\ -// v10 := lt(3, v9)\l\ +// v5 := lt(0x03, phi2)\l\ // "]; // Block0_9 -> Block0_9Exit; -// Block0_9Exit [label="{ If v10 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_9Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_9Exit:0 -> Block0_12 [style="solid"]; // Block0_9Exit:1 -> Block0_10 [style="solid"]; // Block0_3 [label="\ -// Block 3; (23, max 23)\nLiveIn: v3[1]\l\ -// LiveOut: v43[1]\l\nv43 := add(1, v3)\l\ +// Block 3; (23, max 23)\nLiveIn: phi0[1]\l\ +// LiveOut: v20[1]\l\nUsed: phi0[1]\l\nv20 := add(0x01, phi0)\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; // Block0_3Exit -> Block0_1 [style="dashed"]; // Block0_10 [label="\ -// Block 10; (6, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ -// LiveOut: v9[1], v6[1], v3[1]\l\nv11 := mload(0)\l\ +// Block 10; (6, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv6 := mload(0x00)\l\ // "]; // Block0_10 -> Block0_10Exit; -// Block0_10Exit [label="{ If v11 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_10Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_10Exit:0 -> Block0_14 [style="solid"]; // Block0_10Exit:1 -> Block0_13 [style="solid"]; // Block0_12 [label="\ -// Block 12; (20, max 21)\nLiveIn: v6[1], v3[1]\l\ -// LiveOut: v6[1], v3[1]\l\n"]; +// Block 12; (20, max 21)\nLiveIn: phi1[1], phi0[1]\l\ +// LiveOut: phi1[1], phi0[1]\l\nUsed: \l\n"]; // Block0_12 -> Block0_12Exit [arrowhead=none]; // Block0_12Exit [label="Jump" shape=oval]; // Block0_12Exit -> Block0_7 [style="solid"]; // Block0_13 [label="\ -// Block 13; (7, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ -// LiveOut: v12[1], v9[1], v6[1], v3[1]\l\nv12 := 0\l\ +// Block 13; (7, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: v7[1], phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv7 := 0x00\l\ // "]; // Block0_13 -> Block0_13Exit [arrowhead=none]; // Block0_13Exit [label="Jump" shape=oval]; // Block0_13Exit -> Block0_15 [style="solid"]; // Block0_14 [label="\ -// Block 14; (12, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ -// LiveOut: v9[1], v6[1], v3[1]\l\nv24 := mload(1)\l\ +// Block 14; (12, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv12 := mload(0x01)\l\ // "]; // Block0_14 -> Block0_14Exit; -// Block0_14Exit [label="{ If v24 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_14Exit [label="{ If v12 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_14Exit:0 -> Block0_20 [style="solid"]; // Block0_14Exit:1 -> Block0_19 [style="solid"]; // Block0_7 [label="\ -// Block 7; (21, max 21)\nLiveIn: v6[1], v3[1]\l\ -// LiveOut: v42[1], v3[1]\l\nv42 := add(1, v6)\l\ +// Block 7; (21, max 21)\nLiveIn: phi1[1], phi0[1]\l\ +// LiveOut: v19[1], phi0[1]\l\nUsed: phi1[1]\l\nv19 := add(0x01, phi1)\l\ // "]; // Block0_7 -> Block0_7Exit [arrowhead=none]; // Block0_7Exit [label="Jump" shape=oval]; // Block0_7Exit -> Block0_5 [style="dashed"]; // Block0_15 [label="\ -// Block 15; (8, max 19)\nLiveIn: v13[4], v9[1], v6[1], v3[1]\l\ -// LiveOut: v13[2], v9[1], v6[1], v3[1]\l\nv13 := φ(\l\ -// Block 13 => v12,\l\ -// Block 17 => v21\l\ +// Block 15; (8, max 19)\nLiveIn: phi3[4], phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: phi3[2], phi2[1], phi1[1], phi0[1]\l\nUsed: phi3[2]\l\nphi3 := φ(\l\ +// Block 13 => v7,\l\ +// Block 17 => v11\l\ // )\l\ -// v14 := lt(3, v13)\l\ +// v8 := lt(0x03, phi3)\l\ // "]; // Block0_15 -> Block0_15Exit; -// Block0_15Exit [label="{ If v14 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_15Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_15Exit:0 -> Block0_18 [style="solid"]; // Block0_15Exit:1 -> Block0_16 [style="solid"]; // Block0_19 [label="\ -// Block 19; (13, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ -// LiveOut: v25[1], v9[1], v6[1], v3[1]\l\nv25 := 0\l\ +// Block 19; (13, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: v13[1], phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv13 := 0x00\l\ // "]; // Block0_19 -> Block0_19Exit [arrowhead=none]; // Block0_19Exit [label="Jump" shape=oval]; // Block0_19Exit -> Block0_21 [style="solid"]; // Block0_20 [label="\ -// Block 20; (18, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ -// LiveOut: v9[1], v6[1], v3[1]\l\n"]; +// Block 20; (18, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\n"]; // Block0_20 -> Block0_20Exit [arrowhead=none]; // Block0_20Exit [label="Jump" shape=oval]; // Block0_20Exit -> Block0_11 [style="solid"]; // Block0_16 [label="\ -// Block 16; (9, max 10)\nLiveIn: v13[2], v9[1], v6[1], v3[1]\l\ -// LiveOut: v13[1], v9[1], v6[1], v3[1]\l\nv18 := add(v6, v3)\l\ -// v19 := add(v9, v18)\l\ -// sstore(v19, v13)\l\ +// Block 16; (9, max 10)\nLiveIn: phi3[2], phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: phi3[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi3[1]\l\nv9 := add(phi1, phi0)\l\ +// v10 := add(phi2, v9)\l\ +// sstore(v10, phi3)\l\ // "]; // Block0_16 -> Block0_16Exit [arrowhead=none]; // Block0_16Exit [label="Jump" shape=oval]; // Block0_16Exit -> Block0_17 [style="solid"]; // Block0_18 [label="\ -// Block 18; (11, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ -// LiveOut: v9[1], v6[1], v3[1]\l\n"]; +// Block 18; (11, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\n"]; // Block0_18 -> Block0_18Exit [arrowhead=none]; // Block0_18Exit [label="Jump" shape=oval]; // Block0_18Exit -> Block0_14 [style="solid"]; // Block0_21 [label="\ -// Block 21; (14, max 19)\nLiveIn: v26[4], v9[1], v6[1], v3[1]\l\ -// LiveOut: v26[2], v9[1], v6[1], v3[1]\l\nv26 := φ(\l\ -// Block 19 => v25,\l\ -// Block 23 => v33\l\ +// Block 21; (14, max 19)\nLiveIn: phi9[4], phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: phi9[2], phi2[1], phi1[1], phi0[1]\l\nUsed: phi9[2]\l\nphi9 := φ(\l\ +// Block 19 => v13,\l\ +// Block 23 => v17\l\ // )\l\ -// v27 := lt(3, v26)\l\ +// v14 := lt(0x03, phi9)\l\ // "]; // Block0_21 -> Block0_21Exit; -// Block0_21Exit [label="{ If v27 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_21Exit [label="{ If v14 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_21Exit:0 -> Block0_24 [style="solid"]; // Block0_21Exit:1 -> Block0_22 [style="solid"]; // Block0_11 [label="\ -// Block 11; (19, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ -// LiveOut: v38[1], v6[1], v3[1]\l\nv38 := add(1, v9)\l\ +// Block 11; (19, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: v18[1], phi1[1], phi0[1]\l\nUsed: phi2[1]\l\nv18 := add(0x01, phi2)\l\ // "]; // Block0_11 -> Block0_11Exit [arrowhead=none]; // Block0_11Exit [label="Jump" shape=oval]; // Block0_11Exit -> Block0_9 [style="dashed"]; // Block0_17 [label="\ -// Block 17; (10, max 10)\nLiveIn: v13[1], v9[1], v6[1], v3[1]\l\ -// LiveOut: v21[1], v9[1], v6[1], v3[1]\l\nv21 := add(1, v13)\l\ +// Block 17; (10, max 10)\nLiveIn: phi3[1], phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: v11[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi3[1]\l\nv11 := add(0x01, phi3)\l\ // "]; // Block0_17 -> Block0_17Exit [arrowhead=none]; // Block0_17Exit [label="Jump" shape=oval]; // Block0_17Exit -> Block0_15 [style="dashed"]; // Block0_22 [label="\ -// Block 22; (15, max 16)\nLiveIn: v26[2], v9[1], v6[1], v3[1]\l\ -// LiveOut: v26[1], v9[1], v6[1], v3[1]\l\nv31 := add(v6, v3)\l\ -// v32 := add(v9, v31)\l\ -// sstore(v32, v26)\l\ +// Block 22; (15, max 16)\nLiveIn: phi9[2], phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: phi9[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi9[1]\l\nv15 := add(phi1, phi0)\l\ +// v16 := add(phi2, v15)\l\ +// sstore(v16, phi9)\l\ // "]; // Block0_22 -> Block0_22Exit [arrowhead=none]; // Block0_22Exit [label="Jump" shape=oval]; // Block0_22Exit -> Block0_23 [style="solid"]; // Block0_24 [label="\ -// Block 24; (17, max 19)\nLiveIn: v9[1], v6[1], v3[1]\l\ -// LiveOut: v9[1], v6[1], v3[1]\l\n"]; +// Block 24; (17, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\n"]; // Block0_24 -> Block0_24Exit [arrowhead=none]; // Block0_24Exit [label="Jump" shape=oval]; // Block0_24Exit -> Block0_20 [style="solid"]; // Block0_23 [label="\ -// Block 23; (16, max 16)\nLiveIn: v26[1], v9[1], v6[1], v3[1]\l\ -// LiveOut: v33[1], v9[1], v6[1], v3[1]\l\nv33 := add(1, v26)\l\ +// Block 23; (16, max 16)\nLiveIn: phi9[1], phi2[1], phi1[1], phi0[1]\l\ +// LiveOut: v17[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi9[1]\l\nv17 := add(0x01, phi9)\l\ // "]; // Block0_23 -> Block0_23Exit [arrowhead=none]; // Block0_23Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/nested_function.yul b/test/libyul/yulSSAControlFlowGraph/nested_function.yul index 4387e54aa..2ae7f5522 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_function.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_function.yul @@ -37,9 +37,9 @@ // // Entry0 [label="Entry"]; // Entry0 -> Block0_0; -// Block0_0 [label="\ +// Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\n"]; +// LiveOut: \l\nUsed: \l\n"]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_f_0 [label="function f: @@ -47,20 +47,20 @@ // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 0)\nLiveIn: v0[2], v1[1]\l\ -// LiveOut: v4[1]\l\nv3 := add(v1, v0)\l\ -// v4 := sub(v0, v3)\l\ +// LiveOut: v3[1]\l\nUsed: v0[2], v1[1]\l\nv2 := add(v1, v0)\l\ +// v3 := sub(v0, v2)\l\ // "]; -// Block1_0Exit [label="FunctionReturn[v4]"]; +// Block1_0Exit [label="FunctionReturn[v3]"]; // Block1_0 -> Block1_0Exit; // FunctionEntry_g_0 [label="function g: // g()"]; // FunctionEntry_g_0 -> Block2_0; // Block2_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nv1 := v()\l\ -// v2 := f(2, v1)\l\ -// v3 := z()\l\ -// sstore(v2, v3)\l\ +// LiveOut: \l\nUsed: \l\nv0 := v()\l\ +// v1 := f(0x02, v0)\l\ +// v2 := z()\l\ +// sstore(v1, v2)\l\ // "]; // Block2_0Exit [label="FunctionReturn[]"]; // Block2_0 -> Block2_0Exit; @@ -69,89 +69,89 @@ // FunctionEntry_z_0 -> Block3_0; // Block3_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v1[1]\l\nv1 := w()\l\ +// LiveOut: v0[1]\l\nUsed: \l\nv0 := w()\l\ // "]; -// Block3_0Exit [label="FunctionReturn[v1]"]; +// Block3_0Exit [label="FunctionReturn[v0]"]; // Block3_0 -> Block3_0Exit; // FunctionEntry_w_0 [label="function w: // rw1 := w()"]; // FunctionEntry_w_0 -> Block4_0; // Block4_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v2[1]\l\nv2 := 1\l\ +// LiveOut: v0[1]\l\nUsed: \l\nv0 := 0x01\l\ // "]; -// Block4_0Exit [label="FunctionReturn[v2]"]; +// Block4_0Exit [label="FunctionReturn[v0]"]; // Block4_0 -> Block4_0Exit; // FunctionEntry_v_0 [label="function v: // r := v()"]; // FunctionEntry_v_0 -> Block5_0; // Block5_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v1[1]\l\nv1 := w()\l\ +// LiveOut: v0[1]\l\nUsed: \l\nv0 := w()\l\ // "]; -// Block5_0Exit [label="FunctionReturn[v1]"]; +// Block5_0Exit [label="FunctionReturn[v0]"]; // Block5_0 -> Block5_0Exit; // FunctionEntry_w_0 [label="function w: // rw2 := w()"]; // FunctionEntry_w_0 -> Block6_0; // Block6_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v2[1]\l\nv2 := 17\l\ +// LiveOut: v0[1]\l\nUsed: \l\nv0 := 0x11\l\ // "]; -// Block6_0Exit [label="FunctionReturn[v2]"]; +// Block6_0Exit [label="FunctionReturn[v0]"]; // Block6_0 -> Block6_0Exit; // FunctionEntry_cycle1_0 [label="function cycle1: // r := cycle1()"]; // FunctionEntry_cycle1_0 -> Block7_0; // Block7_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: \l\nv2 := mload(3)\l\ +// LiveOut: \l\nUsed: \l\nv0 := mload(0x03)\l\ // "]; // Block7_0 -> Block7_0Exit; -// Block7_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block7_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block7_0Exit:0 -> Block7_2 [style="solid"]; // Block7_0Exit:1 -> Block7_1 [style="solid"]; // Block7_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v3[1]\l\nv3 := cycle2()\l\ +// LiveOut: v1[1]\l\nUsed: \l\nv1 := cycle2()\l\ // "]; // Block7_1 -> Block7_1Exit [arrowhead=none]; // Block7_1Exit [label="Jump" shape=oval]; // Block7_1Exit -> Block7_2 [style="solid"]; // Block7_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: v4[3]\l\ -// LiveOut: v4[1]\l\nv4 := φ(\l\ -// Block 0 => 0,\l\ -// Block 1 => v3\l\ +// Block 2; (2, max 2)\nLiveIn: phi0[3]\l\ +// LiveOut: phi0[1]\l\nUsed: phi0[2]\l\nphi0 := φ(\l\ +// Block 0 => 0x00,\l\ +// Block 1 => v1\l\ // )\l\ // "]; -// Block7_2Exit [label="FunctionReturn[v4]"]; +// Block7_2Exit [label="FunctionReturn[phi0]"]; // Block7_2 -> Block7_2Exit; // FunctionEntry_cycle2_0 [label="function cycle2: // r := cycle2()"]; // FunctionEntry_cycle2_0 -> Block8_0; // Block8_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: \l\nv2 := mload(4)\l\ +// LiveOut: \l\nUsed: \l\nv0 := mload(0x04)\l\ // "]; // Block8_0 -> Block8_0Exit; -// Block8_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block8_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block8_0Exit:0 -> Block8_2 [style="solid"]; // Block8_0Exit:1 -> Block8_1 [style="solid"]; // Block8_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v3[1]\l\nv3 := cycle1()\l\ +// LiveOut: v1[1]\l\nUsed: \l\nv1 := cycle1()\l\ // "]; // Block8_1 -> Block8_1Exit [arrowhead=none]; // Block8_1Exit [label="Jump" shape=oval]; // Block8_1Exit -> Block8_2 [style="solid"]; // Block8_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: v4[3]\l\ -// LiveOut: v4[1]\l\nv4 := φ(\l\ -// Block 0 => 0,\l\ -// Block 1 => v3\l\ +// Block 2; (2, max 2)\nLiveIn: phi0[3]\l\ +// LiveOut: phi0[1]\l\nUsed: phi0[2]\l\nphi0 := φ(\l\ +// Block 0 => 0x00,\l\ +// Block 1 => v1\l\ // )\l\ // "]; -// Block8_2Exit [label="FunctionReturn[v4]"]; +// Block8_2Exit [label="FunctionReturn[phi0]"]; // Block8_2 -> Block8_2Exit; // } diff --git a/test/libyul/yulSSAControlFlowGraph/switch.yul b/test/libyul/yulSSAControlFlowGraph/switch.yul index 5a670467e..56e50d562 100644 --- a/test/libyul/yulSSAControlFlowGraph/switch.yul +++ b/test/libyul/yulSSAControlFlowGraph/switch.yul @@ -23,50 +23,50 @@ // Entry0 -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 5)\nLiveIn: \l\ -// LiveOut: v3[1]\l\nv1 := calldataload(3)\l\ -// v3 := sload(0)\l\ -// v4 := eq(0, v3)\l\ +// LiveOut: v1[1]\l\nUsed: \l\nv0 := calldataload(0x03)\l\ +// v1 := sload(0x00)\l\ +// v2 := eq(0x00, v1)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_0Exit:0 -> Block0_3 [style="solid"]; // Block0_0Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ // Block 2; (1, max 2)\nLiveIn: \l\ -// LiveOut: v6[1]\l\nv6 := calldataload(77)\l\ +// LiveOut: v3[1]\l\nUsed: \l\nv3 := calldataload(0x4d)\l\ // "]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; // Block0_2Exit -> Block0_1 [style="solid"]; // Block0_3 [label="\ -// Block 3; (3, max 5)\nLiveIn: v3[1]\l\ -// LiveOut: \l\nv7 := eq(1, v3)\l\ +// Block 3; (3, max 5)\nLiveIn: v1[1]\l\ +// LiveOut: \l\nUsed: v1[1]\l\nv4 := eq(0x01, v1)\l\ // "]; // Block0_3 -> Block0_3Exit; -// Block0_3Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_3Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_3Exit:0 -> Block0_5 [style="solid"]; // Block0_3Exit:1 -> Block0_4 [style="solid"]; // Block0_1 [label="\ -// Block 1; (2, max 2)\nLiveIn: v13[2]\l\ -// LiveOut: \l\nv13 := φ(\l\ -// Block 2 => v6,\l\ -// Block 4 => v10,\l\ -// Block 5 => v12\l\ +// Block 1; (2, max 2)\nLiveIn: phi0[2]\l\ +// LiveOut: \l\nUsed: phi0[2]\l\nphi0 := φ(\l\ +// Block 2 => v3,\l\ +// Block 4 => v5,\l\ +// Block 5 => v6\l\ // )\l\ -// sstore(0, v13)\l\ +// sstore(0x00, phi0)\l\ // "]; // Block0_1Exit [label="MainExit"]; // Block0_1 -> Block0_1Exit; // Block0_4 [label="\ // Block 4; (4, max 4)\nLiveIn: \l\ -// LiveOut: v10[1]\l\nv10 := calldataload(88)\l\ +// LiveOut: v5[1]\l\nUsed: \l\nv5 := calldataload(0x58)\l\ // "]; // Block0_4 -> Block0_4Exit [arrowhead=none]; // Block0_4Exit [label="Jump" shape=oval]; // Block0_4Exit -> Block0_1 [style="solid"]; // Block0_5 [label="\ // Block 5; (5, max 5)\nLiveIn: \l\ -// LiveOut: v12[1]\l\nv12 := calldataload(99)\l\ +// LiveOut: v6[1]\l\nUsed: \l\nv6 := calldataload(0x63)\l\ // "]; // Block0_5 -> Block0_5Exit [arrowhead=none]; // Block0_5Exit [label="Jump" shape=oval]; diff --git a/test/libyul/yulSSAControlFlowGraph/switch_const.yul b/test/libyul/yulSSAControlFlowGraph/switch_const.yul index 3de0537dc..559061195 100644 --- a/test/libyul/yulSSAControlFlowGraph/switch_const.yul +++ b/test/libyul/yulSSAControlFlowGraph/switch_const.yul @@ -43,12 +43,12 @@ // // Entry0 [label="Entry"]; // Entry0 -> Block0_0; -// Block0_0 [label="\ +// Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nv1 := calldataload(3)\l\ -// v4 := calldataload(88)\l\ -// v7 := calldataload(99)\l\ -// sstore(0, v7)\l\ +// LiveOut: \l\nUsed: \l\nv0 := calldataload(0x03)\l\ +// v1 := calldataload(0x58)\l\ +// v2 := calldataload(0x63)\l\ +// sstore(0x00, v2)\l\ // "]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; From d5d29bd78f54c2b0445d8c46d14eeb69b47576e3 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:30:46 +0200 Subject: [PATCH 1000/1340] SSACFG: exporting to json is stateless --- libyul/YulStack.cpp | 3 +- .../backends/evm/ssa/SSACFGJsonExporter.cpp | 249 +++++----- libyul/backends/evm/ssa/SSACFGJsonExporter.h | 20 +- .../standard_yul_cfg_json_export/output.json | 444 +++++++++--------- .../strict_asm_yul_cfg_json_export/output | 58 +-- test/cmdlineTests/yul_cfg_json_export/output | 444 +++++++++--------- 6 files changed, 590 insertions(+), 628 deletions(-) diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 75b39134f..34de47b92 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -405,8 +405,7 @@ Json YulStack::cfgJson() const keepLiteralAssignments ); std::unique_ptr liveness = std::make_unique(*controlFlow); - ssa::SSACFGJsonExporter exporter(*controlFlow, liveness.get()); - return exporter.run(); + return ssa::json::exportControlFlow(*controlFlow, liveness.get()); }; std::function>)> exportCFGFromSubObjects; diff --git a/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp b/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp index 68f65d377..9b03c13c9 100644 --- a/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp +++ b/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp @@ -17,73 +17,119 @@ // SPDX-License-Identifier: GPL-3.0 #include + #include #include #include +#include +#include #include -#include #include using namespace solidity; +using namespace solidity::yul; using namespace solidity::yul::ssa; +using namespace solidity::yul::ssa::json; -SSACFGJsonExporter::SSACFGJsonExporter(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness): m_controlFlow(_controlFlow), m_liveness(_liveness) +namespace +{ +Json toJson(SSACFG const& _cfg, std::vector const& _values) { + Json ret = Json::array(); + for (auto const& value: _values) + ret.push_back(value.str(_cfg)); + return ret; } -std::string SSACFGJsonExporter::varToString(SSACFG const& _cfg, SSACFG::ValueId _var) +Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation) { - if (_var.value == std::numeric_limits::max()) - return std::string("INVALID"); - auto const& info = _cfg.valueInfo(_var); - return std::visit( - util::GenericVisitor{ - [&](SSACFG::UnreachableValue const&) -> std::string { - return "[unreachable]"; - }, - [&](SSACFG::LiteralValue const& _literal) { - return toCompactHexWithPrefix(_literal.value); - }, - [&](auto const&) { - return "v" + std::to_string(_var.value); - } + Json opJson = Json::object(); + std::visit(util::GenericVisitor{ + [&](SSACFG::Call const& _call) { + _ret["type"] = "FunctionCall"; + opJson["op"] = _call.function.get().name.str(); }, - info - ); -} + [&](SSACFG::LiteralAssignment const&) { + yulAssert(_operation.inputs.size() == 1); + yulAssert(_operation.inputs.back().isLiteral()); + opJson["op"] = "LiteralAssignment"; + }, + [&](SSACFG::BuiltinCall const& _call) { + _ret["type"] = "BuiltinCall"; + Json builtinArgsJson = Json::array(); + auto const& builtin = _call.builtin.get(); + if (!builtin.literalArguments.empty()) + { + auto const& functionCallArgs = _call.call.get().arguments; + for (size_t i = 0; i < builtin.literalArguments.size(); ++i) + { + std::optional const& argument = builtin.literalArguments[i]; + if (argument.has_value() && i < functionCallArgs.size()) + { + // The function call argument at index i must be a literal if builtin.literalArguments[i] is not nullopt + yulAssert(std::holds_alternative(functionCallArgs[i])); + builtinArgsJson.push_back(formatLiteral(std::get(functionCallArgs[i]))); + } + } + } -Json SSACFGJsonExporter::run() -{ - if (m_liveness) - yulAssert(&m_liveness->controlFlow.get() == &m_controlFlow); + if (!builtinArgsJson.empty()) + opJson["literalArgs"] = builtinArgsJson; - Json yulObjectJson = Json::object(); - yulObjectJson["blocks"] = exportBlock(*m_controlFlow.mainGraph, SSACFG::BlockId{0}, m_liveness ? m_liveness->mainLiveness.get() : nullptr); + opJson["op"] = _call.builtin.get().name; + }, + }, _operation.kind); - Json functionsJson = Json::object(); - size_t index = 0; - for (auto const& [function, functionGraph]: m_controlFlow.functionGraphMapping) - functionsJson[function->name.str()] = exportFunction(*functionGraph, m_liveness ? m_liveness->functionLiveness[index++].get() : nullptr); - yulObjectJson["functions"] = functionsJson; + opJson["in"] = toJson(_cfg, _operation.inputs); + opJson["out"] = toJson(_cfg, _operation.outputs); - return yulObjectJson; + return opJson; } -Json SSACFGJsonExporter::exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness) +Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness) { - Json functionJson = Json::object(); - functionJson["type"] = "Function"; - functionJson["entry"] = "Block" + std::to_string(_cfg.entry.value); - static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", std::get<1>(_arg).value); }; - functionJson["arguments"] = _cfg.arguments | ranges::views::transform(argsTransform) | ranges::to; - functionJson["numReturns"] = _cfg.returns.size(); - functionJson["blocks"] = exportBlock(_cfg, _cfg.entry, _liveness); - return functionJson; + auto const valueToString = [&](LivenessAnalysis::LivenessData::LiveCounts::value_type const& _live) { return _live.first.str(_cfg); }; + + Json blockJson = Json::object(); + auto const& block = _cfg.block(_blockId); + + blockJson["id"] = "Block" + std::to_string(_blockId.value); + if (_liveness) + { + Json livenessJson = Json::object(); + livenessJson["in"] = _liveness->liveIn(_blockId) + | ranges::views::transform(valueToString) + | ranges::to(); + livenessJson["out"] = _liveness->liveOut(_blockId) + | ranges::views::transform(valueToString) + | ranges::to(); + blockJson["liveness"] = livenessJson; + } + blockJson["instructions"] = Json::array(); + if (!block.phis.empty()) + { + blockJson["entries"] = block.entries + | ranges::views::transform([](auto const& entry) { return "Block" + std::to_string(entry.value); }) + | ranges::to(); + for (auto const& phi: block.phis) + { + auto const& phiInfo = _cfg.phiInfo(phi); + Json phiJson = Json::object(); + phiJson["op"] = "PhiFunction"; + phiJson["in"] = toJson(_cfg, phiInfo.arguments); + phiJson["out"] = toJson(_cfg, std::vector{phi}); + blockJson["instructions"].push_back(phiJson); + } + } + for (auto const& operation: block.operations) + blockJson["instructions"].push_back(toJson(blockJson, _cfg, operation)); + + return blockJson; } -Json SSACFGJsonExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis const* _liveness) +Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis const* _liveness) { Json blocksJson = Json::array(); util::BreadthFirstSearch bfs{{{_entryId}}}; @@ -97,16 +143,14 @@ Json SSACFGJsonExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryI [&](SSACFG::BasicBlock::MainExit const&) { exitBlockJson["type"] = "MainExit"; }, - [&](SSACFG::BasicBlock::Jump const& _jump) - { + [&](SSACFG::BasicBlock::Jump const& _jump){ exitBlockJson["targets"] = { "Block" + std::to_string(_jump.target.value) }; exitBlockJson["type"] = "Jump"; _addChild(_jump.target); }, - [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) - { + [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { exitBlockJson["targets"] = { "Block" + std::to_string(_conditionalJump.zero.value), "Block" + std::to_string(_conditionalJump.nonZero.value) }; - exitBlockJson["cond"] = varToString(_cfg, _conditionalJump.condition); + exitBlockJson["cond"] = _conditionalJump.condition.str(_cfg); exitBlockJson["type"] = "ConditionalJump"; _addChild(_conditionalJump.zero); @@ -130,100 +174,35 @@ Json SSACFGJsonExporter::exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryI return blocksJson; } -Json SSACFGJsonExporter::toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness) +Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness) { - auto const valueToString = [&](LivenessAnalysis::LivenessData::LiveCounts::value_type const& _live) { return varToString(_cfg, _live.first); }; - - Json blockJson = Json::object(); - auto const& block = _cfg.block(_blockId); - - blockJson["id"] = "Block" + std::to_string(_blockId.value); - if (_liveness) - { - Json livenessJson = Json::object(); - livenessJson["in"] = _liveness->liveIn(_blockId) - | ranges::views::transform(valueToString) - | ranges::to(); - livenessJson["out"] = _liveness->liveOut(_blockId) - | ranges::views::transform(valueToString) - | ranges::to(); - blockJson["liveness"] = livenessJson; - } - blockJson["instructions"] = Json::array(); - if (!block.phis.empty()) - { - blockJson["entries"] = block.entries - | ranges::views::transform([](auto const& entry) { return "Block" + std::to_string(entry.value); }) - | ranges::to(); - for (auto const& phi: block.phis) - { - auto* phiInfo = std::get_if(&_cfg.valueInfo(phi)); - yulAssert(phiInfo); - Json phiJson = Json::object(); - phiJson["op"] = "PhiFunction"; - phiJson["in"] = toJson(_cfg, phiInfo->arguments); - phiJson["out"] = toJson(_cfg, std::vector{phi}); - blockJson["instructions"].push_back(phiJson); - } - } - for (auto const& operation: block.operations) - blockJson["instructions"].push_back(toJson(blockJson, _cfg, operation)); + Json functionJson = Json::object(); + functionJson["type"] = "Function"; + functionJson["entry"] = "Block" + std::to_string(_cfg.entry.value); + static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", std::get<1>(_arg).value()); }; + functionJson["arguments"] = _cfg.arguments | ranges::views::transform(argsTransform) | ranges::to; + functionJson["numReturns"] = _cfg.returns.size(); + functionJson["blocks"] = exportBlock(_cfg, _cfg.entry, _liveness); + return functionJson; +} - return blockJson; } -Json SSACFGJsonExporter::toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation) +Json json::exportControlFlow(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness) { - Json opJson = Json::object(); - std::visit(util::GenericVisitor{ - [&](SSACFG::Call const& _call) - { - _ret["type"] = "FunctionCall"; - opJson["op"] = _call.function.get().name.str(); - }, - [&](SSACFG::LiteralAssignment const&) - { - yulAssert(_operation.inputs.size() == 1); - yulAssert(_cfg.isLiteralValue(_operation.inputs.back())); - opJson["op"] = "LiteralAssignment"; - }, - [&](SSACFG::BuiltinCall const& _call) - { - _ret["type"] = "BuiltinCall"; - Json builtinArgsJson = Json::array(); - auto const& builtin = _call.builtin.get(); - if (!builtin.literalArguments.empty()) - { - auto const& functionCallArgs = _call.call.get().arguments; - for (size_t i = 0; i < builtin.literalArguments.size(); ++i) - { - std::optional const& argument = builtin.literalArguments[i]; - if (argument.has_value() && i < functionCallArgs.size()) - { - // The function call argument at index i must be a literal if builtin.literalArguments[i] is not nullopt - yulAssert(std::holds_alternative(functionCallArgs[i])); - builtinArgsJson.push_back(formatLiteral(std::get(functionCallArgs[i]))); - } - } - } - - if (!builtinArgsJson.empty()) - opJson["literalArgs"] = builtinArgsJson; - - opJson["op"] = _call.builtin.get().name; - }, - }, _operation.kind); + if (_liveness) + yulAssert(&_liveness->controlFlow.get() == &_controlFlow); - opJson["in"] = toJson(_cfg, _operation.inputs); - opJson["out"] = toJson(_cfg, _operation.outputs); + Json yulObjectJson = Json::object(); + yulObjectJson["blocks"] = exportBlock(*_controlFlow.mainGraph(), SSACFG::BlockId{0}, _liveness ? _liveness->cfgLiveness.front().get() : nullptr); - return opJson; -} + Json functionsJson = Json::object(); + size_t index = 1; + for (auto const& [function, functionGraph]: _controlFlow.functionGraphMapping | ranges::views::drop(1)) + { + functionsJson[function->name.str()] = exportFunction(*functionGraph, _liveness ? _liveness->cfgLiveness[index++].get() : nullptr); + } + yulObjectJson["functions"] = functionsJson; -Json SSACFGJsonExporter::toJson(SSACFG const& _cfg, std::vector const& _values) -{ - Json ret = Json::array(); - for (auto const& value: _values) - ret.push_back(varToString(_cfg, value)); - return ret; + return yulObjectJson; } diff --git a/libyul/backends/evm/ssa/SSACFGJsonExporter.h b/libyul/backends/evm/ssa/SSACFGJsonExporter.h index 719859581..08f846fc5 100644 --- a/libyul/backends/evm/ssa/SSACFGJsonExporter.h +++ b/libyul/backends/evm/ssa/SSACFGJsonExporter.h @@ -20,26 +20,10 @@ #include #include -#include -namespace solidity::yul::ssa +namespace solidity::yul::ssa::json { -class SSACFGJsonExporter -{ -public: - SSACFGJsonExporter(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness=nullptr); - Json run(); - Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness); - Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness); - std::string varToString(SSACFG const& _cfg, SSACFG::ValueId _var); - -private: - ControlFlow const& m_controlFlow; - ControlFlowLiveness const* m_liveness; - Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness); - Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation); - Json toJson(SSACFG const& _cfg, std::vector const& _values); -}; +Json exportControlFlow(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness); } diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index 07b1c3f63..09674ec77 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -7,7 +7,7 @@ "blocks": [ { "exit": { - "cond": "v2", + "cond": "v1", "targets": [ "Block2", "Block1" @@ -38,7 +38,7 @@ "in": [], "op": "callvalue", "out": [ - "v2" + "v1" ] } ], @@ -63,7 +63,7 @@ ], "op": "datasize", "out": [ - "v4" + "v2" ] }, { @@ -73,13 +73,13 @@ ], "op": "dataoffset", "out": [ - "v5" + "v3" ] }, { "in": [ - "v4", - "v5", + "v2", + "v3", "v0" ], "op": "codecopy", @@ -87,7 +87,7 @@ }, { "in": [ - "v4", + "v2", "v0" ], "op": "return", @@ -130,7 +130,7 @@ "blocks": [ { "exit": { - "cond": "v5", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -161,26 +161,26 @@ "in": [], "op": "calldatasize", "out": [ - "v3" + "v1" ] }, { "in": [ "0x04", - "v3" + "v1" ], "op": "lt", "out": [ - "v4" + "v2" ] }, { "in": [ - "v4" + "v2" ], "op": "iszero", "out": [ - "v5" + "v3" ] } ], @@ -215,7 +215,7 @@ }, { "exit": { - "cond": "v11", + "cond": "v6", "targets": [ "Block4", "Block3" @@ -230,27 +230,27 @@ ], "op": "calldataload", "out": [ - "v7" + "v4" ] }, { "in": [ - "v7", + "v4", "0xe0" ], "op": "shr", "out": [ - "v9" + "v5" ] }, { "in": [ - "v9", + "v5", "0x26121ff0" ], "op": "eq", "out": [ - "v11" + "v6" ] } ], @@ -280,7 +280,7 @@ }, { "exit": { - "cond": "v12", + "cond": "v7", "targets": [ "Block6", "Block5" @@ -293,7 +293,7 @@ "in": [], "op": "callvalue", "out": [ - "v12" + "v7" ] } ], @@ -309,7 +309,7 @@ }, { "exit": { - "cond": "v17", + "cond": "v11", "targets": [ "Block9", "Block8" @@ -324,34 +324,34 @@ ], "op": "not", "out": [ - "v14" + "v8" ] }, { "in": [], "op": "calldatasize", "out": [ - "v15" + "v9" ] }, { "in": [ - "v14", - "v15" + "v8", + "v9" ], "op": "add", "out": [ - "v16" + "v10" ] }, { "in": [ "0x00", - "v16" + "v10" ], "op": "slt", "out": [ - "v17" + "v11" ] } ], @@ -454,7 +454,7 @@ "blocks": [ { "exit": { - "cond": "v2", + "cond": "v1", "targets": [ "Block2", "Block1" @@ -485,7 +485,7 @@ "in": [], "op": "callvalue", "out": [ - "v2" + "v1" ] } ], @@ -510,7 +510,7 @@ ], "op": "datasize", "out": [ - "v4" + "v2" ] }, { @@ -520,13 +520,13 @@ ], "op": "dataoffset", "out": [ - "v5" + "v3" ] }, { "in": [ - "v4", - "v5", + "v2", + "v3", "v0" ], "op": "codecopy", @@ -534,7 +534,7 @@ }, { "in": [ - "v4", + "v2", "v0" ], "op": "return", @@ -577,7 +577,7 @@ "blocks": [ { "exit": { - "cond": "v5", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -608,26 +608,26 @@ "in": [], "op": "calldatasize", "out": [ - "v3" + "v1" ] }, { "in": [ "0x04", - "v3" + "v1" ], "op": "lt", "out": [ - "v4" + "v2" ] }, { "in": [ - "v4" + "v2" ], "op": "iszero", "out": [ - "v5" + "v3" ] } ], @@ -662,7 +662,7 @@ }, { "exit": { - "cond": "v11", + "cond": "v6", "targets": [ "Block4", "Block3" @@ -677,27 +677,27 @@ ], "op": "calldataload", "out": [ - "v7" + "v4" ] }, { "in": [ - "v7", + "v4", "0xe0" ], "op": "shr", "out": [ - "v9" + "v5" ] }, { "in": [ - "v9", + "v5", "0x26121ff0" ], "op": "eq", "out": [ - "v11" + "v6" ] } ], @@ -727,7 +727,7 @@ }, { "exit": { - "cond": "v12", + "cond": "v7", "targets": [ "Block6", "Block5" @@ -740,7 +740,7 @@ "in": [], "op": "callvalue", "out": [ - "v12" + "v7" ] } ], @@ -756,7 +756,7 @@ }, { "exit": { - "cond": "v17", + "cond": "v11", "targets": [ "Block9", "Block8" @@ -771,34 +771,34 @@ ], "op": "not", "out": [ - "v14" + "v8" ] }, { "in": [], "op": "calldatasize", "out": [ - "v15" + "v9" ] }, { "in": [ - "v14", - "v15" + "v8", + "v9" ], "op": "add", "out": [ - "v16" + "v10" ] }, { "in": [ "0x00", - "v16" + "v10" ], "op": "slt", "out": [ - "v17" + "v11" ] } ], @@ -835,7 +835,7 @@ }, { "exit": { - "cond": "v28", + "cond": "v16", "targets": [ "Block12", "Block11" @@ -851,47 +851,47 @@ ], "op": "datasize", "out": [ - "v18" + "v12" ] }, { "in": [ - "v18", + "v12", "v0" ], "op": "add", "out": [ - "v24" + "v13" ] }, { "in": [ "v0", - "v24" + "v13" ], "op": "lt", "out": [ - "v25" + "v14" ] }, { "in": [ "0xffffffffffffffff", - "v24" + "v13" ], "op": "gt", "out": [ - "v27" + "v15" ] }, { "in": [ - "v25", - "v27" + "v14", + "v15" ], "op": "or", "out": [ - "v28" + "v16" ] } ], @@ -901,8 +901,8 @@ ], "out": [ "v0", - "v24", - "v18" + "v13", + "v12" ] }, "type": "BuiltinCall" @@ -930,7 +930,7 @@ }, { "exit": { - "cond": "v42", + "cond": "v21", "targets": [ "Block15", "Block14" @@ -946,13 +946,13 @@ ], "op": "dataoffset", "out": [ - "v35" + "v18" ] }, { "in": [ + "v12", "v18", - "v35", "v0" ], "op": "datacopy", @@ -961,42 +961,42 @@ { "in": [ "v0", - "v24" + "v13" ], "op": "sub", "out": [ - "v40" + "v19" ] }, { "in": [ - "v40", + "v19", "v0", "0x00" ], "op": "create", "out": [ - "v41" + "v20" ] }, { "in": [ - "v41" + "v20" ], "op": "iszero", "out": [ - "v42" + "v21" ] } ], "liveness": { "in": [ "v0", - "v24", - "v18" + "v13", + "v12" ], "out": [ - "v41" + "v20" ] }, "type": "BuiltinCall" @@ -1014,12 +1014,12 @@ ], "op": "shl", "out": [ - "v30" + "v17" ] }, { "in": [ - "v30", + "v17", "0x00" ], "op": "mstore", @@ -1050,7 +1050,7 @@ }, { "exit": { - "cond": "v60", + "cond": "v32", "targets": [ "Block18", "Block17" @@ -1065,7 +1065,7 @@ ], "op": "mload", "out": [ - "v46" + "v25" ] }, { @@ -1075,13 +1075,13 @@ ], "op": "shl", "out": [ - "v49" + "v26" ] }, { "in": [ - "v49", - "v46" + "v26", + "v25" ], "op": "mstore", "out": [] @@ -1093,67 +1093,67 @@ ], "op": "shl", "out": [ - "v53" + "v27" ] }, { "in": [ "0x01", - "v53" + "v27" ], "op": "sub", "out": [ - "v54" + "v28" ] }, { "in": [ - "v54", - "v41" + "v28", + "v20" ], "op": "and", "out": [ - "v57" + "v29" ] }, { "in": [], "op": "gas", "out": [ - "v58" + "v30" ] }, { "in": [ "0x20", - "v46", + "v25", "0x04", - "v46", - "v57", - "v58" + "v25", + "v29", + "v30" ], "op": "staticcall", "out": [ - "v59" + "v31" ] }, { "in": [ - "v59" + "v31" ], "op": "iszero", "out": [ - "v60" + "v32" ] } ], "liveness": { "in": [ - "v41" + "v20" ], "out": [ - "v46", - "v59" + "v25", + "v31" ] }, "type": "BuiltinCall" @@ -1170,21 +1170,21 @@ ], "op": "mload", "out": [ - "v43" + "v22" ] }, { "in": [], "op": "returndatasize", "out": [ - "v44" + "v23" ] }, { "in": [ - "v44", + "v23", "0x00", - "v43" + "v22" ], "op": "returndatacopy", "out": [] @@ -1193,13 +1193,13 @@ "in": [], "op": "returndatasize", "out": [ - "v45" + "v24" ] }, { "in": [ - "v45", - "v43" + "v24", + "v22" ], "op": "revert", "out": [] @@ -1213,7 +1213,7 @@ }, { "exit": { - "cond": "v59", + "cond": "v31", "targets": [ "Block21", "Block20" @@ -1228,18 +1228,18 @@ ], "op": "LiteralAssignment", "out": [ - "v64" + "v36" ] } ], "liveness": { "in": [ - "v46", - "v59" + "v25", + "v31" ], "out": [ - "v64", - "v46" + "v36", + "v25" ] } }, @@ -1255,21 +1255,21 @@ ], "op": "mload", "out": [ - "v61" + "v33" ] }, { "in": [], "op": "returndatasize", "out": [ - "v62" + "v34" ] }, { "in": [ - "v62", + "v34", "0x00", - "v61" + "v33" ], "op": "returndatacopy", "out": [] @@ -1278,13 +1278,13 @@ "in": [], "op": "returndatasize", "out": [ - "v63" + "v35" ] }, { "in": [ - "v63", - "v61" + "v35", + "v33" ], "op": "revert", "out": [] @@ -1308,12 +1308,12 @@ "instructions": [ { "in": [ - "v64", - "v95" + "v36", + "v52" ], "op": "PhiFunction", "out": [ - "v97" + "phi26" ] }, { @@ -1322,13 +1322,13 @@ ], "op": "mload", "out": [ - "v96" + "v53" ] }, { "in": [ - "v97", - "v96" + "phi26", + "v53" ], "op": "mstore", "out": [] @@ -1336,7 +1336,7 @@ { "in": [ "0x20", - "v96" + "v53" ], "op": "return", "out": [] @@ -1344,7 +1344,7 @@ ], "liveness": { "in": [ - "v97" + "phi26" ], "out": [] }, @@ -1352,7 +1352,7 @@ }, { "exit": { - "cond": "v69", + "cond": "v39", "targets": [ "Block23", "Block22" @@ -1367,34 +1367,34 @@ ], "op": "LiteralAssignment", "out": [ - "v67" + "v37" ] }, { "in": [], "op": "returndatasize", "out": [ - "v68" + "v38" ] }, { "in": [ - "v68", + "v38", "0x20" ], "op": "gt", "out": [ - "v69" + "v39" ] } ], "liveness": { "in": [ - "v46" + "v25" ], "out": [ - "v67", - "v46" + "v37", + "v25" ] }, "type": "BuiltinCall" @@ -1405,7 +1405,7 @@ "Block22" ], "exit": { - "cond": "v82", + "cond": "v47", "targets": [ "Block25", "Block24" @@ -1416,12 +1416,12 @@ "instructions": [ { "in": [ - "v67", - "v70" + "v37", + "v40" ], "op": "PhiFunction", "out": [ - "v73" + "phi14" ] }, { @@ -1430,79 +1430,79 @@ ], "op": "not", "out": [ - "v72" + "v41" ] }, { "in": [ "0x1f", - "v73" + "phi14" ], "op": "add", "out": [ - "v74" + "v42" ] }, { "in": [ - "v72", - "v74" + "v41", + "v42" ], "op": "and", "out": [ - "v75" + "v43" ] }, { "in": [ - "v75", - "v46" + "v43", + "v25" ], "op": "add", "out": [ - "v79" + "v44" ] }, { "in": [ - "v46", - "v79" + "v25", + "v44" ], "op": "lt", "out": [ - "v80" + "v45" ] }, { "in": [ "0xffffffffffffffff", - "v79" + "v44" ], "op": "gt", "out": [ - "v81" + "v46" ] }, { "in": [ - "v80", - "v81" + "v45", + "v46" ], "op": "or", "out": [ - "v82" + "v47" ] } ], "liveness": { "in": [ - "v46", - "v73" + "v25", + "phi14" ], "out": [ - "v46", - "v73", - "v79" + "v25", + "phi14", + "v44" ] }, "type": "BuiltinCall" @@ -1520,24 +1520,24 @@ "in": [], "op": "returndatasize", "out": [ - "v70" + "v40" ] } ], "liveness": { "in": [ - "v46" + "v25" ], "out": [ - "v70", - "v46" + "v40", + "v25" ] }, "type": "BuiltinCall" }, { "exit": { - "cond": "v92", + "cond": "v51", "targets": [ "Block28", "Block27" @@ -1548,7 +1548,7 @@ "instructions": [ { "in": [ - "v79", + "v44", "0x40" ], "op": "mstore", @@ -1556,43 +1556,43 @@ }, { "in": [ - "v73", - "v46" + "phi14", + "v25" ], "op": "add", "out": [ - "v90" + "v49" ] }, { "in": [ - "v46", - "v90" + "v25", + "v49" ], "op": "sub", "out": [ - "v91" + "v50" ] }, { "in": [ "0x20", - "v91" + "v50" ], "op": "slt", "out": [ - "v92" + "v51" ] } ], "liveness": { "in": [ - "v46", - "v73", - "v79" + "v25", + "phi14", + "v44" ], "out": [ - "v46" + "v25" ] }, "type": "BuiltinCall" @@ -1610,12 +1610,12 @@ ], "op": "shl", "out": [ - "v83" + "v48" ] }, { "in": [ - "v83", + "v48", "0x00" ], "op": "mstore", @@ -1655,20 +1655,20 @@ "instructions": [ { "in": [ - "v46" + "v25" ], "op": "mload", "out": [ - "v95" + "v52" ] } ], "liveness": { "in": [ - "v46" + "v25" ], "out": [ - "v95" + "v52" ] }, "type": "BuiltinCall" @@ -1701,7 +1701,7 @@ "blocks": [ { "exit": { - "cond": "v2", + "cond": "v1", "targets": [ "Block2", "Block1" @@ -1732,7 +1732,7 @@ "in": [], "op": "callvalue", "out": [ - "v2" + "v1" ] } ], @@ -1757,7 +1757,7 @@ ], "op": "datasize", "out": [ - "v4" + "v2" ] }, { @@ -1767,13 +1767,13 @@ ], "op": "dataoffset", "out": [ - "v5" + "v3" ] }, { "in": [ - "v4", - "v5", + "v2", + "v3", "v0" ], "op": "codecopy", @@ -1781,7 +1781,7 @@ }, { "in": [ - "v4", + "v2", "v0" ], "op": "return", @@ -1824,7 +1824,7 @@ "blocks": [ { "exit": { - "cond": "v5", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -1855,26 +1855,26 @@ "in": [], "op": "calldatasize", "out": [ - "v3" + "v1" ] }, { "in": [ "0x04", - "v3" + "v1" ], "op": "lt", "out": [ - "v4" + "v2" ] }, { "in": [ - "v4" + "v2" ], "op": "iszero", "out": [ - "v5" + "v3" ] } ], @@ -1909,7 +1909,7 @@ }, { "exit": { - "cond": "v11", + "cond": "v6", "targets": [ "Block4", "Block3" @@ -1924,27 +1924,27 @@ ], "op": "calldataload", "out": [ - "v7" + "v4" ] }, { "in": [ - "v7", + "v4", "0xe0" ], "op": "shr", "out": [ - "v9" + "v5" ] }, { "in": [ - "v9", + "v5", "0x26121ff0" ], "op": "eq", "out": [ - "v11" + "v6" ] } ], @@ -1974,7 +1974,7 @@ }, { "exit": { - "cond": "v12", + "cond": "v7", "targets": [ "Block6", "Block5" @@ -1987,7 +1987,7 @@ "in": [], "op": "callvalue", "out": [ - "v12" + "v7" ] } ], @@ -2003,7 +2003,7 @@ }, { "exit": { - "cond": "v17", + "cond": "v11", "targets": [ "Block9", "Block8" @@ -2018,34 +2018,34 @@ ], "op": "not", "out": [ - "v14" + "v8" ] }, { "in": [], "op": "calldatasize", "out": [ - "v15" + "v9" ] }, { "in": [ - "v14", - "v15" + "v8", + "v9" ], "op": "add", "out": [ - "v16" + "v10" ] }, { "in": [ "0x00", - "v16" + "v10" ], "op": "slt", "out": [ - "v17" + "v11" ] } ], diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output index 40f8186a1..7554c2340 100644 --- a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -7,7 +7,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v2", + "cond": "v1", "targets": [ "Block2", "Block1" @@ -38,7 +38,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v2" + "v1" ] } ], @@ -63,7 +63,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v4" + "v2" ] }, { @@ -73,13 +73,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v5" + "v3" ] }, { "in": [ - "v4", - "v5", + "v2", + "v3", "v0" ], "op": "codecopy", @@ -87,7 +87,7 @@ Yul Control Flow Graph: }, { "in": [ - "v4", + "v2", "v0" ], "op": "return", @@ -130,7 +130,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v5", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -161,26 +161,26 @@ Yul Control Flow Graph: "in": [], "op": "calldatasize", "out": [ - "v3" + "v1" ] }, { "in": [ "0x04", - "v3" + "v1" ], "op": "lt", "out": [ - "v4" + "v2" ] }, { "in": [ - "v4" + "v2" ], "op": "iszero", "out": [ - "v5" + "v3" ] } ], @@ -215,7 +215,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v11", + "cond": "v6", "targets": [ "Block4", "Block3" @@ -230,27 +230,27 @@ Yul Control Flow Graph: ], "op": "calldataload", "out": [ - "v7" + "v4" ] }, { "in": [ - "v7", + "v4", "0xe0" ], "op": "shr", "out": [ - "v9" + "v5" ] }, { "in": [ - "v9", + "v5", "0x26121ff0" ], "op": "eq", "out": [ - "v11" + "v6" ] } ], @@ -280,7 +280,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v12", + "cond": "v7", "targets": [ "Block6", "Block5" @@ -293,7 +293,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v12" + "v7" ] } ], @@ -309,7 +309,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v17", + "cond": "v11", "targets": [ "Block9", "Block8" @@ -324,34 +324,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v14" + "v8" ] }, { "in": [], "op": "calldatasize", "out": [ - "v15" + "v9" ] }, { "in": [ - "v14", - "v15" + "v8", + "v9" ], "op": "add", "out": [ - "v16" + "v10" ] }, { "in": [ "0x00", - "v16" + "v10" ], "op": "slt", "out": [ - "v17" + "v11" ] } ], diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index cf93e76fd..d1aeaed52 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -6,7 +6,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v2", + "cond": "v1", "targets": [ "Block2", "Block1" @@ -37,7 +37,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v2" + "v1" ] } ], @@ -62,7 +62,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v4" + "v2" ] }, { @@ -72,13 +72,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v5" + "v3" ] }, { "in": [ - "v4", - "v5", + "v2", + "v3", "v0" ], "op": "codecopy", @@ -86,7 +86,7 @@ Yul Control Flow Graph: }, { "in": [ - "v4", + "v2", "v0" ], "op": "return", @@ -129,7 +129,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v5", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -160,26 +160,26 @@ Yul Control Flow Graph: "in": [], "op": "calldatasize", "out": [ - "v3" + "v1" ] }, { "in": [ "0x04", - "v3" + "v1" ], "op": "lt", "out": [ - "v4" + "v2" ] }, { "in": [ - "v4" + "v2" ], "op": "iszero", "out": [ - "v5" + "v3" ] } ], @@ -214,7 +214,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v11", + "cond": "v6", "targets": [ "Block4", "Block3" @@ -229,27 +229,27 @@ Yul Control Flow Graph: ], "op": "calldataload", "out": [ - "v7" + "v4" ] }, { "in": [ - "v7", + "v4", "0xe0" ], "op": "shr", "out": [ - "v9" + "v5" ] }, { "in": [ - "v9", + "v5", "0x26121ff0" ], "op": "eq", "out": [ - "v11" + "v6" ] } ], @@ -279,7 +279,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v12", + "cond": "v7", "targets": [ "Block6", "Block5" @@ -292,7 +292,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v12" + "v7" ] } ], @@ -308,7 +308,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v17", + "cond": "v11", "targets": [ "Block9", "Block8" @@ -323,34 +323,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v14" + "v8" ] }, { "in": [], "op": "calldatasize", "out": [ - "v15" + "v9" ] }, { "in": [ - "v14", - "v15" + "v8", + "v9" ], "op": "add", "out": [ - "v16" + "v10" ] }, { "in": [ "0x00", - "v16" + "v10" ], "op": "slt", "out": [ - "v17" + "v11" ] } ], @@ -454,7 +454,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v2", + "cond": "v1", "targets": [ "Block2", "Block1" @@ -485,7 +485,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v2" + "v1" ] } ], @@ -510,7 +510,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v4" + "v2" ] }, { @@ -520,13 +520,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v5" + "v3" ] }, { "in": [ - "v4", - "v5", + "v2", + "v3", "v0" ], "op": "codecopy", @@ -534,7 +534,7 @@ Yul Control Flow Graph: }, { "in": [ - "v4", + "v2", "v0" ], "op": "return", @@ -577,7 +577,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v5", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -608,26 +608,26 @@ Yul Control Flow Graph: "in": [], "op": "calldatasize", "out": [ - "v3" + "v1" ] }, { "in": [ "0x04", - "v3" + "v1" ], "op": "lt", "out": [ - "v4" + "v2" ] }, { "in": [ - "v4" + "v2" ], "op": "iszero", "out": [ - "v5" + "v3" ] } ], @@ -662,7 +662,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v11", + "cond": "v6", "targets": [ "Block4", "Block3" @@ -677,27 +677,27 @@ Yul Control Flow Graph: ], "op": "calldataload", "out": [ - "v7" + "v4" ] }, { "in": [ - "v7", + "v4", "0xe0" ], "op": "shr", "out": [ - "v9" + "v5" ] }, { "in": [ - "v9", + "v5", "0x26121ff0" ], "op": "eq", "out": [ - "v11" + "v6" ] } ], @@ -727,7 +727,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v12", + "cond": "v7", "targets": [ "Block6", "Block5" @@ -740,7 +740,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v12" + "v7" ] } ], @@ -756,7 +756,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v17", + "cond": "v11", "targets": [ "Block9", "Block8" @@ -771,34 +771,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v14" + "v8" ] }, { "in": [], "op": "calldatasize", "out": [ - "v15" + "v9" ] }, { "in": [ - "v14", - "v15" + "v8", + "v9" ], "op": "add", "out": [ - "v16" + "v10" ] }, { "in": [ "0x00", - "v16" + "v10" ], "op": "slt", "out": [ - "v17" + "v11" ] } ], @@ -835,7 +835,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v28", + "cond": "v16", "targets": [ "Block12", "Block11" @@ -851,47 +851,47 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v18" + "v12" ] }, { "in": [ - "v18", + "v12", "v0" ], "op": "add", "out": [ - "v24" + "v13" ] }, { "in": [ "v0", - "v24" + "v13" ], "op": "lt", "out": [ - "v25" + "v14" ] }, { "in": [ "0xffffffffffffffff", - "v24" + "v13" ], "op": "gt", "out": [ - "v27" + "v15" ] }, { "in": [ - "v25", - "v27" + "v14", + "v15" ], "op": "or", "out": [ - "v28" + "v16" ] } ], @@ -901,8 +901,8 @@ Yul Control Flow Graph: ], "out": [ "v0", - "v24", - "v18" + "v13", + "v12" ] }, "type": "BuiltinCall" @@ -930,7 +930,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v42", + "cond": "v21", "targets": [ "Block15", "Block14" @@ -946,13 +946,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v35" + "v18" ] }, { "in": [ + "v12", "v18", - "v35", "v0" ], "op": "datacopy", @@ -961,42 +961,42 @@ Yul Control Flow Graph: { "in": [ "v0", - "v24" + "v13" ], "op": "sub", "out": [ - "v40" + "v19" ] }, { "in": [ - "v40", + "v19", "v0", "0x00" ], "op": "create", "out": [ - "v41" + "v20" ] }, { "in": [ - "v41" + "v20" ], "op": "iszero", "out": [ - "v42" + "v21" ] } ], "liveness": { "in": [ "v0", - "v24", - "v18" + "v13", + "v12" ], "out": [ - "v41" + "v20" ] }, "type": "BuiltinCall" @@ -1014,12 +1014,12 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v30" + "v17" ] }, { "in": [ - "v30", + "v17", "0x00" ], "op": "mstore", @@ -1050,7 +1050,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v60", + "cond": "v32", "targets": [ "Block18", "Block17" @@ -1065,7 +1065,7 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v46" + "v25" ] }, { @@ -1075,13 +1075,13 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v49" + "v26" ] }, { "in": [ - "v49", - "v46" + "v26", + "v25" ], "op": "mstore", "out": [] @@ -1093,67 +1093,67 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v53" + "v27" ] }, { "in": [ "0x01", - "v53" + "v27" ], "op": "sub", "out": [ - "v54" + "v28" ] }, { "in": [ - "v54", - "v41" + "v28", + "v20" ], "op": "and", "out": [ - "v57" + "v29" ] }, { "in": [], "op": "gas", "out": [ - "v58" + "v30" ] }, { "in": [ "0x20", - "v46", + "v25", "0x04", - "v46", - "v57", - "v58" + "v25", + "v29", + "v30" ], "op": "staticcall", "out": [ - "v59" + "v31" ] }, { "in": [ - "v59" + "v31" ], "op": "iszero", "out": [ - "v60" + "v32" ] } ], "liveness": { "in": [ - "v41" + "v20" ], "out": [ - "v46", - "v59" + "v25", + "v31" ] }, "type": "BuiltinCall" @@ -1170,21 +1170,21 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v43" + "v22" ] }, { "in": [], "op": "returndatasize", "out": [ - "v44" + "v23" ] }, { "in": [ - "v44", + "v23", "0x00", - "v43" + "v22" ], "op": "returndatacopy", "out": [] @@ -1193,13 +1193,13 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v45" + "v24" ] }, { "in": [ - "v45", - "v43" + "v24", + "v22" ], "op": "revert", "out": [] @@ -1213,7 +1213,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v59", + "cond": "v31", "targets": [ "Block21", "Block20" @@ -1228,18 +1228,18 @@ Yul Control Flow Graph: ], "op": "LiteralAssignment", "out": [ - "v64" + "v36" ] } ], "liveness": { "in": [ - "v46", - "v59" + "v25", + "v31" ], "out": [ - "v64", - "v46" + "v36", + "v25" ] } }, @@ -1255,21 +1255,21 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v61" + "v33" ] }, { "in": [], "op": "returndatasize", "out": [ - "v62" + "v34" ] }, { "in": [ - "v62", + "v34", "0x00", - "v61" + "v33" ], "op": "returndatacopy", "out": [] @@ -1278,13 +1278,13 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v63" + "v35" ] }, { "in": [ - "v63", - "v61" + "v35", + "v33" ], "op": "revert", "out": [] @@ -1308,12 +1308,12 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v64", - "v95" + "v36", + "v52" ], "op": "PhiFunction", "out": [ - "v97" + "phi26" ] }, { @@ -1322,13 +1322,13 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v96" + "v53" ] }, { "in": [ - "v97", - "v96" + "phi26", + "v53" ], "op": "mstore", "out": [] @@ -1336,7 +1336,7 @@ Yul Control Flow Graph: { "in": [ "0x20", - "v96" + "v53" ], "op": "return", "out": [] @@ -1344,7 +1344,7 @@ Yul Control Flow Graph: ], "liveness": { "in": [ - "v97" + "phi26" ], "out": [] }, @@ -1352,7 +1352,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v69", + "cond": "v39", "targets": [ "Block23", "Block22" @@ -1367,34 +1367,34 @@ Yul Control Flow Graph: ], "op": "LiteralAssignment", "out": [ - "v67" + "v37" ] }, { "in": [], "op": "returndatasize", "out": [ - "v68" + "v38" ] }, { "in": [ - "v68", + "v38", "0x20" ], "op": "gt", "out": [ - "v69" + "v39" ] } ], "liveness": { "in": [ - "v46" + "v25" ], "out": [ - "v67", - "v46" + "v37", + "v25" ] }, "type": "BuiltinCall" @@ -1405,7 +1405,7 @@ Yul Control Flow Graph: "Block22" ], "exit": { - "cond": "v82", + "cond": "v47", "targets": [ "Block25", "Block24" @@ -1416,12 +1416,12 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v67", - "v70" + "v37", + "v40" ], "op": "PhiFunction", "out": [ - "v73" + "phi14" ] }, { @@ -1430,79 +1430,79 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v72" + "v41" ] }, { "in": [ "0x1f", - "v73" + "phi14" ], "op": "add", "out": [ - "v74" + "v42" ] }, { "in": [ - "v72", - "v74" + "v41", + "v42" ], "op": "and", "out": [ - "v75" + "v43" ] }, { "in": [ - "v75", - "v46" + "v43", + "v25" ], "op": "add", "out": [ - "v79" + "v44" ] }, { "in": [ - "v46", - "v79" + "v25", + "v44" ], "op": "lt", "out": [ - "v80" + "v45" ] }, { "in": [ "0xffffffffffffffff", - "v79" + "v44" ], "op": "gt", "out": [ - "v81" + "v46" ] }, { "in": [ - "v80", - "v81" + "v45", + "v46" ], "op": "or", "out": [ - "v82" + "v47" ] } ], "liveness": { "in": [ - "v46", - "v73" + "v25", + "phi14" ], "out": [ - "v46", - "v73", - "v79" + "v25", + "phi14", + "v44" ] }, "type": "BuiltinCall" @@ -1520,24 +1520,24 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v70" + "v40" ] } ], "liveness": { "in": [ - "v46" + "v25" ], "out": [ - "v70", - "v46" + "v40", + "v25" ] }, "type": "BuiltinCall" }, { "exit": { - "cond": "v92", + "cond": "v51", "targets": [ "Block28", "Block27" @@ -1548,7 +1548,7 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v79", + "v44", "0x40" ], "op": "mstore", @@ -1556,43 +1556,43 @@ Yul Control Flow Graph: }, { "in": [ - "v73", - "v46" + "phi14", + "v25" ], "op": "add", "out": [ - "v90" + "v49" ] }, { "in": [ - "v46", - "v90" + "v25", + "v49" ], "op": "sub", "out": [ - "v91" + "v50" ] }, { "in": [ "0x20", - "v91" + "v50" ], "op": "slt", "out": [ - "v92" + "v51" ] } ], "liveness": { "in": [ - "v46", - "v73", - "v79" + "v25", + "phi14", + "v44" ], "out": [ - "v46" + "v25" ] }, "type": "BuiltinCall" @@ -1610,12 +1610,12 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v83" + "v48" ] }, { "in": [ - "v83", + "v48", "0x00" ], "op": "mstore", @@ -1655,20 +1655,20 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v46" + "v25" ], "op": "mload", "out": [ - "v95" + "v52" ] } ], "liveness": { "in": [ - "v46" + "v25" ], "out": [ - "v95" + "v52" ] }, "type": "BuiltinCall" @@ -1701,7 +1701,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v2", + "cond": "v1", "targets": [ "Block2", "Block1" @@ -1732,7 +1732,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v2" + "v1" ] } ], @@ -1757,7 +1757,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v4" + "v2" ] }, { @@ -1767,13 +1767,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v5" + "v3" ] }, { "in": [ - "v4", - "v5", + "v2", + "v3", "v0" ], "op": "codecopy", @@ -1781,7 +1781,7 @@ Yul Control Flow Graph: }, { "in": [ - "v4", + "v2", "v0" ], "op": "return", @@ -1824,7 +1824,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v5", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -1855,26 +1855,26 @@ Yul Control Flow Graph: "in": [], "op": "calldatasize", "out": [ - "v3" + "v1" ] }, { "in": [ "0x04", - "v3" + "v1" ], "op": "lt", "out": [ - "v4" + "v2" ] }, { "in": [ - "v4" + "v2" ], "op": "iszero", "out": [ - "v5" + "v3" ] } ], @@ -1909,7 +1909,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v11", + "cond": "v6", "targets": [ "Block4", "Block3" @@ -1924,27 +1924,27 @@ Yul Control Flow Graph: ], "op": "calldataload", "out": [ - "v7" + "v4" ] }, { "in": [ - "v7", + "v4", "0xe0" ], "op": "shr", "out": [ - "v9" + "v5" ] }, { "in": [ - "v9", + "v5", "0x26121ff0" ], "op": "eq", "out": [ - "v11" + "v6" ] } ], @@ -1974,7 +1974,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v12", + "cond": "v7", "targets": [ "Block6", "Block5" @@ -1987,7 +1987,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v12" + "v7" ] } ], @@ -2003,7 +2003,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v17", + "cond": "v11", "targets": [ "Block9", "Block8" @@ -2018,34 +2018,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v14" + "v8" ] }, { "in": [], "op": "calldatasize", "out": [ - "v15" + "v9" ] }, { "in": [ - "v14", - "v15" + "v8", + "v9" ], "op": "add", "out": [ - "v16" + "v10" ] }, { "in": [ "0x00", - "v16" + "v10" ], "op": "slt", "out": [ - "v17" + "v11" ] } ], From 74ea280441897d33b28b3838eed8be984ebd1481 Mon Sep 17 00:00:00 2001 From: ParKing666 <123419961+ParKing666@users.noreply.github.com> Date: Mon, 27 Oct 2025 10:27:35 +0100 Subject: [PATCH 1001/1340] Update smtchecker.rst: fix int128 range is from -2^127 to 2^127-1, was ^128. In the text description of the State Properties paragraph: [...] As an example, consider a 2D grid where both axis have coordinates in the range (-2^128, 2^128 - 1). [...] In the example: [...] require(x > type(int128).min && x < type(int128).max); require(y > type(int128).min && y < type(int128).max); [...] With int128 we use a bit for the sign, then 127 bits remain for the value. Changed in the text description to be coherent: ...in the range (-2^127, 2^127 - 1). --- docs/smtchecker.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index 69b620dbc..4f1b49c8d 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -263,7 +263,7 @@ A common type of properties in smart contracts are properties that involve the state of the contract. Multiple transactions might be needed to make an assertion fail for such a property. -As an example, consider a 2D grid where both axis have coordinates in the range (-2^128, 2^128 - 1). +As an example, consider a 2D grid where both axis have coordinates in the range (-2^127, 2^127 - 1). Let us place a robot at position (0, 0). The robot can only move diagonally, one step at a time, and cannot move outside the grid. The robot's state machine can be represented by the smart contract below. From b5de13ae07686e0e1f1d69a76322efccf7941639 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 24 Oct 2025 12:49:31 +0200 Subject: [PATCH 1002/1340] CI: add arm image to buildpack deps, make runs-on explicit --- .github/workflows/buildpack-deps.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml index d4e7c5a7e..528722534 100644 --- a/.github/workflows/buildpack-deps.yml +++ b/.github/workflows/buildpack-deps.yml @@ -1,6 +1,7 @@ name: buildpack-deps permissions: + packages: write pull-requests: write on: @@ -11,20 +12,31 @@ on: - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang' + - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm' jobs: buildpack-deps: + runs-on: ${{ matrix.runs-on }} + env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DOCKER_REPOSITORY: ghcr.io/argotorg/solidity-buildpack-deps IMAGE_NAME: buildpack-deps - runs-on: ubuntu-latest - strategy: fail-fast: false matrix: - image_variant: [emscripten, ubuntu.clang.ossfuzz, ubuntu2404, ubuntu2404.clang] + include: + - image_variant: emscripten + runs-on: ubuntu-latest + - image_variant: ubuntu.clang.ossfuzz + runs-on: ubuntu-latest + - image_variant: ubuntu2404 + runs-on: ubuntu-latest + - image_variant: ubuntu2404.clang + runs-on: ubuntu-latest + - image_variant: ubuntu2404.arm + runs-on: ubuntu-24.04-arm steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 From b0b8857b795944b81a6f5aa72baf31551aa80f68 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 24 Oct 2025 12:35:59 +0200 Subject: [PATCH 1003/1340] CI: add arm image --- .../ci/buildpack-deps_test_ubuntu2404.arm.sh | 1 + .../buildpack-deps/Dockerfile.ubuntu2404.arm | 111 ++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 120000 scripts/ci/buildpack-deps_test_ubuntu2404.arm.sh create mode 100644 scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm diff --git a/scripts/ci/buildpack-deps_test_ubuntu2404.arm.sh b/scripts/ci/buildpack-deps_test_ubuntu2404.arm.sh new file mode 120000 index 000000000..c07a74de4 --- /dev/null +++ b/scripts/ci/buildpack-deps_test_ubuntu2404.arm.sh @@ -0,0 +1 @@ +build.sh \ No newline at end of file diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm new file mode 100644 index 000000000..a24549d4b --- /dev/null +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm @@ -0,0 +1,111 @@ +# vim:syntax=dockerfile +#------------------------------------------------------------------------------ +# Dockerfile for building and testing Solidity Compiler on CI +# Target: Ubuntu 24.04 (Noble) +# 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 +# +# (c) 2016-2025 solidity contributors. +#------------------------------------------------------------------------------ +FROM --platform=linux/arm64 buildpack-deps:noble AS base +LABEL version="1" + +ARG DEBIAN_FRONTEND=noninteractive + +# From Python3.11, pip requires a virtual environment, and will thus terminate when installing packages globally. +# Since we're building this image from scratch, it's perfectly fine to use the below flag. +ENV PIP_BREAK_SYSTEM_PACKAGES=1 + +RUN <<-EOF + set -ex + z3_version="4.13.3" + 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 --quiet=2 --no-install-recommends \ + build-essential \ + cmake \ + jq \ + libboost-filesystem-dev \ + libboost-program-options-dev \ + libboost-system-dev \ + libboost-test-dev \ + libcln-dev \ + locales-all \ + lsof \ + ninja-build \ + python3-pip \ + python3-sphinx \ + software-properties-common \ + sudo \ + unzip \ + zip + pip3 install \ + codecov \ + colorama \ + deepdiff \ + parsec \ + pygments-lexer-solidity \ + pylint \ + requests \ + tabulate \ + z3-solver=="${z3_version}" +EOF + +# Eldarica +RUN <<-EOF + set -ex + apt-get update + apt-get install --quiet=2 openjdk-11-jre + eldarica_version="2.1" + wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /opt/eld_binaries.zip + test "$(sha256sum /opt/eld_binaries.zip)" = "0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c /opt/eld_binaries.zip" + unzip /opt/eld_binaries.zip -d /opt + rm -f /opt/eld_binaries.zip +EOF + +# CVC5 +RUN <<-EOF + set -ex + cvc5_version="1.2.0" + cvc5_archive_name="cvc5-Linux-arm64-static" + wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /opt/cvc5.zip + test "$(sha256sum /opt/cvc5.zip)" = "142ac177af1ce37922308f69fe519d06e6cb4d0a62a312f28c25001e94c2fb56 /opt/cvc5.zip" + unzip -j /opt/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/bin + rm -f /opt/cvc5.zip +EOF + +FROM base AS libraries + +# EVMONE (built from source, no arm release available) +RUN <<-EOF + set -ex + git clone --depth=1 --recurse-submodules --branch v0.16.0 https://github.com/ipsilon/evmone.git /tmp/evmone + mkdir -p /tmp/evmone/build + cd /tmp/evmone/build + cmake .. + make -j + make install +EOF + +FROM base +COPY --from=libraries /usr/lib /usr/lib +COPY --from=libraries /usr/bin /usr/bin +COPY --from=libraries /usr/include /usr/include +COPY --from=libraries /opt/eldarica /opt/eldarica +ENV PATH="$PATH:/opt/eldarica" From 43ecb694853ebac08fb46eb588aa6f30e73d4ad4 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 24 Oct 2025 13:28:09 +0200 Subject: [PATCH 1004/1340] ci: build linux arm static binaries --- .circleci/compare_bytecode_reports.sh | 1 + .circleci/config.yml | 70 +++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/.circleci/compare_bytecode_reports.sh b/.circleci/compare_bytecode_reports.sh index 7574b0656..529d5fc79 100755 --- a/.circleci/compare_bytecode_reports.sh +++ b/.circleci/compare_bytecode_reports.sh @@ -28,6 +28,7 @@ no_cli_platforms=( ) native_platforms=( ubuntu2004-static + ubuntu_arm ubuntu osx osx_intel diff --git a/.circleci/config.yml b/.circleci/config.yml index 76f349a42..f0c0c1fd3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,6 +15,10 @@ parameters: type: string # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404-6 default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:c0412c53e59ce0c96bde4c08e7332ea12e4cadba9bbac829621947897fa21272" + ubuntu-2404-arm-docker-image: + type: string + # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.arm-1 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:6cdb928fa8743d0b5d515c2c489b8d545c541f2370af28d5d3a71532056a0f22" ubuntu-2404-clang-docker-image: type: string # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.clang-7 @@ -606,6 +610,24 @@ defaults: MAKEFLAGS: -j 5 CPUs: 5 + - base_ubuntu2404_arm_medium: &base_ubuntu2404_arm_medium + docker: + - image: << pipeline.parameters.ubuntu-2404-arm-docker-image >> + resource_class: arm.medium + environment: &base_ubuntu2404_arm_medium_env + TERM: xterm + MAKEFLAGS: -j 2 + CPUs: 2 + + - base_ubuntu2404_arm_large: &base_ubuntu2404_arm_large + docker: + - image: << pipeline.parameters.ubuntu-2404-arm-docker-image >> + resource_class: arm.large + environment: &base_ubuntu2404_arm_large_env + TERM: xterm + MAKEFLAGS: -j 7 + CPUs: 7 + - base_ubuntu2404_xlarge: &base_ubuntu2404_xlarge <<: *base_ubuntu2404 resource_class: xlarge @@ -1072,6 +1094,31 @@ jobs: - solc/solc-static-linux - matrix_notify_failure_unless_pr + b_ubu_static_arm: + <<: *base_ubuntu2404_arm_large + environment: + <<: *base_ubuntu2404_arm_large_env + CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DSOLC_LINK_STATIC=ON + steps: + - checkout + - run_build + - run: + name: strip binary + command: strip build/solc/solc + - store_artifacts: + path: build/solc/solc + destination: solc-static-linux-arm + - run: mv build/solc/solc build/solc/solc-static-linux-arm + - run: mv build/solc/soltest build/solc/soltest-linux-arm + - run: mv build/solc/solfuzzer build/solc/solfuzzer-linux-arm + - persist_to_workspace: + root: build + paths: + - solc/solc-static-linux-arm + - test/soltest-linux-arm + - test/tools/solfuzzer-linux-arm + - matrix_notify_failure_unless_pr + b_ubu_min_req: <<: *base_ubuntu2404_large steps: @@ -1770,6 +1817,22 @@ jobs: binary_path: "build/solc/Release/solc.exe" preset: "<< parameters.preset >>" + b_bytecode_ubu_arm: + parameters: + preset: + type: string + <<: *base_ubuntu2404_arm_medium + parallelism: 2 # For prepare_bytecode_report + steps: + - checkout + - attach_workspace: + at: build + - prepare_bytecode_report: + label: "ubuntu_arm" + binary_type: native + binary_path: "build/solc/solc-static-linux-arm" + preset: "<< parameters.preset >>" + b_bytecode_ems: parameters: preset: @@ -1910,6 +1973,7 @@ workflows: # Static build - b_ubu_static: *requires_nothing + - b_ubu_static_arm: *requires_nothing # Ubuntu build and tests - b_ubu: *requires_nothing @@ -1990,6 +2054,11 @@ workflows: matrix: *bytecode_compare_preset_matrix requires: - b_ubu + - b_bytecode_ubu_arm: + <<: *on_all_tags_and_branches + matrix: *bytecode_compare_preset_matrix + requires: + - b_ubu_static_arm - b_bytecode_win: <<: *on_all_tags_and_branches matrix: *bytecode_compare_preset_matrix @@ -2015,6 +2084,7 @@ workflows: requires: - b_bytecode_ubu_static - b_bytecode_ubu + - b_bytecode_ubu_arm - b_bytecode_win - b_bytecode_osx - b_bytecode_osx_intel From be37565066eefb8fa79740698d39d11c8a704b2e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 27 Oct 2025 21:10:49 +0100 Subject: [PATCH 1005/1340] Enable Linux arm64 binaries for testing and releases. --- .circleci/config.yml | 42 +++++++++++++++++++++++++----------------- Changelog.md | 1 + ReleaseChecklist.md | 4 ++-- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f0c0c1fd3..476b72eb3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -284,6 +284,16 @@ commands: - test/soltest - test/tools/solfuzzer + persist_executables_to_workspace_arm: + description: Persist compiled target executables to workspace on Linux arm64 + steps: + - persist_to_workspace: + root: build + paths: + - solc/solc-static-linux-arm + - test/soltest-linux-arm + - test/tools/solfuzzer-linux-arm + persist_executables_to_workspace_osx: description: Persist compiled target executables to workspace on macOS steps: @@ -1109,14 +1119,9 @@ jobs: path: build/solc/solc destination: solc-static-linux-arm - run: mv build/solc/solc build/solc/solc-static-linux-arm - - run: mv build/solc/soltest build/solc/soltest-linux-arm - - run: mv build/solc/solfuzzer build/solc/solfuzzer-linux-arm - - persist_to_workspace: - root: build - paths: - - solc/solc-static-linux-arm - - test/soltest-linux-arm - - test/tools/solfuzzer-linux-arm + - run: mv build/test/soltest build/test/soltest-linux-arm + - run: mv build/test/tools/solfuzzer build/test/tools/solfuzzer-linux-arm + - persist_executables_to_workspace_arm - matrix_notify_failure_unless_pr b_ubu_min_req: @@ -1874,10 +1879,11 @@ jobs: name: Gather and rename binaries from dependent jobs command: | mkdir github/ - cp workspace/solc/solc-static-linux github/solc-static-linux - cp workspace/build/solc/solc github/solc-macos - cp workspace/solc/Release/solc.exe github/solc-windows.exe - cp workspace/soljson.js github/soljson.js + cp workspace/solc/solc-static-linux github/solc-static-linux + cp workspace/solc/solc-static-linux-arm github/solc-static-linux-arm + cp workspace/build/solc/solc github/solc-macos + cp workspace/solc/Release/solc.exe github/solc-windows.exe + cp workspace/soljson.js github/soljson.js cd github/ tar --create --file ../github-binaries.tar * @@ -1891,12 +1897,13 @@ jobs: sed -En 's/^Version: ([0-9.]+.*\+commit\.[0-9a-f]+(\.mod)?).*$/\1/p' ) - mkdir -p solc-bin/{linux-amd64,macosx-amd64,windows-amd64,bin} + mkdir -p solc-bin/{linux-amd64,linux-arm64,macosx-amd64,windows-amd64,bin} - mv github/solc-static-linux "solc-bin/linux-amd64/solc-linux-amd64-v${full_version}" - mv github/solc-macos "solc-bin/macosx-amd64/solc-macosx-amd64-v${full_version}" - mv github/solc-windows.exe "solc-bin/windows-amd64/solc-windows-amd64-v${full_version}.exe" - mv github/soljson.js "solc-bin/bin/soljson-v${full_version}.js" + mv github/solc-static-linux-arm "solc-bin/linux-arm64/solc-linux-arm64-v${full_version}" + mv github/solc-static-linux "solc-bin/linux-amd64/solc-linux-amd64-v${full_version}" + mv github/solc-macos "solc-bin/macosx-amd64/solc-macosx-amd64-v${full_version}" + mv github/solc-windows.exe "solc-bin/windows-amd64/solc-windows-amd64-v${full_version}.exe" + mv github/soljson.js "solc-bin/bin/soljson-v${full_version}.js" cd solc-bin/ tar --create --file ../solc-bin-binaries.tar * @@ -2094,6 +2101,7 @@ workflows: - c_release_binaries: <<: *on_version_tags requires: + - b_ubu_static_arm - b_ubu_static - b_osx - b_win diff --git a/Changelog.md b/Changelog.md index 748495074..f772f6dd8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,7 @@ Bugfixes: * Yul Optimizer: Fix edge case in which invalid Yul code is produced by ExpressionSimplifier due to expressions being substituted that contain out-of-scope variables. Build System: +* Enable Linux arm64 binaries for testing and releases. * Update minimum version requirements of Boost to 1.83.0 for non-windows builds and of GCC and Clang to 13.3 and 18.1.3, respectively. Fixes infinite recursion on `boost::rational` comparison affecting compiler binaries built with GCC<14.0 and Boost<1.75. ### 0.8.30 (2025-05-07) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index fe751e896..d8d63b09a 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -69,7 +69,7 @@ At least a day before the release: ### Upload Release Artifacts and Publish Binaries - [ ] Take the source tarball (`solidity_x.x.x.tar.gz`) from `c_source_tarball` run of the tagged commit on Circle CI and upload it to the release page. - [ ] Take the `github-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to the release page. - Make sure it contains four binaries: `solc-windows.exe`, `solc-macos`, `solc-static-linux` and `soljson.js`. + Make sure it contains five binaries: `solc-windows.exe`, `solc-macos`, `solc-static-linux`, `solc-static-linux-arm`, and `soljson.js`. - [ ] Take the `solc-bin-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to solc-bin. - [ ] Run `npm install` if you've got a clean checkout of the solc-bin repo. - [ ] Run `npm run update -- --reuse-hashes` in `solc-bin` and verify that the script has updated `list.js`, `list.txt` and `list.json` files correctly and that symlinks to the new release have been added in `solc-bin/wasm/` and `solc-bin/emscripten-wasm32/`. @@ -134,7 +134,7 @@ At least a day before the release: - [ ] Wait for the CI runs on the tag itself. - [ ] Take the source tarball (`solidity_x.x.x-pre.N.tar.gz`) from `c_source_tarball` run of the tagged commit on Circle CI and upload it to the release page. - [ ] Take the `github-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to the release page. - Make sure it contains four binaries: `solc-windows.exe`, `solc-macos`, `solc-static-linux` and `soljson.js`. + Make sure it contains five binaries: `solc-windows.exe`, `solc-macos`, `solc-static-linux`, `solc-static-linux-arm` and `soljson.js`. - [ ] Take the `solc-bin-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to solc-bin. - [ ] Run `npm install` if you've got a clean checkout of the solc-bin repo. - [ ] Run `npm run update -- --reuse-hashes` in `solc-bin` and verify that the script has updated `list.js`, `list.txt` and `list.json` files correctly and that symlinks to the new release have been added in `solc-bin/wasm/` and `solc-bin/emscripten-wasm32/`. From 45fdbccf5b187723f4be66b0e8e1e1e713577b3b Mon Sep 17 00:00:00 2001 From: ParKing666 <123419961+ParKing666@users.noreply.github.com> Date: Sun, 26 Oct 2025 17:57:11 +0100 Subject: [PATCH 1006/1340] Fix: max int8 has 7 bits set to 1, not 8 bits before: 0000...0000 1111 1111 after: 0000...0000 0111 1111 --- docs/internals/variable_cleanup.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/internals/variable_cleanup.rst b/docs/internals/variable_cleanup.rst index bab3c8bef..6def08f22 100644 --- a/docs/internals/variable_cleanup.rst +++ b/docs/internals/variable_cleanup.rst @@ -91,7 +91,7 @@ Positive 0000...0000 0000 0001 0000...0000 0000 0010 .... - 0000...0000 1111 1111 + 0000...0000 0111 1111 The compiler will ``signextend`` the sign bit, which is 1 for negative and 0 for positive values, overwriting the higher bits: From 2129c0d6e5c7327f8bf2dcebfb13b080a68d509e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Sat, 1 Nov 2025 14:02:57 +0100 Subject: [PATCH 1007/1340] docs: fix links to solc-bin github page and remix offline installation --- docs/installing-solidity.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 6f3dfbb7f..bda0d102b 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -32,7 +32,7 @@ Remix `Access Remix online `_, you do not need to install anything. If you want to use it without connection to the Internet, go to -https://github.com/argotorg/remix-live/tree/gh-pages#readme and follow the instructions on that page. +https://github.com/ethereum/remix-live/tree/gh-pages#readme and follow the instructions on that page. Remix is also a convenient option for testing nightly builds without installing multiple Solidity versions. @@ -291,14 +291,14 @@ This means that: .. warning:: - The binaries are also available at https://ethereum.github.io/solc-bin/ but this page + The binaries are also available at https://argotorg.github.io/solc-bin/ but this page stopped being updated just after the release of version 0.7.2, will not receive any new releases or nightly builds for any platform and does not serve the new directory structure, including non-emscripten builds. If you are using it, please switch to https://binaries.soliditylang.org, which is a drop-in replacement. This allows us to make changes to the underlying hosting in a transparent way and - minimize disruption. Unlike the ``ethereum.github.io`` domain, which we do not have any control + minimize disruption. Unlike the ``argotorg.github.io`` domain, which we do not have any control over, ``binaries.soliditylang.org`` is guaranteed to work and maintain the same URL structure in the long-term. From 9d2a907c2ffa903ae928105e07f44a573b665f18 Mon Sep 17 00:00:00 2001 From: Doryu Date: Sun, 2 Nov 2025 20:28:19 +0100 Subject: [PATCH 1008/1340] Update isolate_tests.py --- scripts/wasm-rebuild/docker-scripts/isolate_tests.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/wasm-rebuild/docker-scripts/isolate_tests.py b/scripts/wasm-rebuild/docker-scripts/isolate_tests.py index cc84f89bb..fa7b68a64 100755 --- a/scripts/wasm-rebuild/docker-scripts/isolate_tests.py +++ b/scripts/wasm-rebuild/docker-scripts/isolate_tests.py @@ -7,8 +7,7 @@ import re import os import hashlib -# Pylint for some reason insists that isfile() is unused -from os.path import join, isfile # pylint: disable=unused-import +from os.path import join def extract_test_cases(path): From dff13e351561e51c75baa320904456ff8cc55099 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:31:35 +0100 Subject: [PATCH 1009/1340] SSACFG backend: add stack abstraction --- libyul/CMakeLists.txt | 4 +- libyul/backends/evm/ssa/Stack.cpp | 97 ++++++++++ libyul/backends/evm/ssa/Stack.h | 305 ++++++++++++++++++++++++++++++ 3 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 libyul/backends/evm/ssa/Stack.cpp create mode 100644 libyul/backends/evm/ssa/Stack.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 15b06a623..ff94a3905 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -88,8 +88,10 @@ add_library(yul backends/evm/ssa/SSACFG.h backends/evm/ssa/SSACFGBuilder.cpp backends/evm/ssa/SSACFGBuilder.h - backends/evm/ssa/SSACFGJsonExporter.h backends/evm/ssa/SSACFGJsonExporter.cpp + backends/evm/ssa/SSACFGJsonExporter.h + backends/evm/ssa/Stack.cpp + backends/evm/ssa/Stack.h optimiser/ASTCopier.cpp optimiser/ASTCopier.h optimiser/ASTWalker.cpp diff --git a/libyul/backends/evm/ssa/Stack.cpp b/libyul/backends/evm/ssa/Stack.cpp new file mode 100644 index 000000000..17c8c3f44 --- /dev/null +++ b/libyul/backends/evm/ssa/Stack.cpp @@ -0,0 +1,97 @@ +/* + 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 + +#include + +#include + +#include +#include + +namespace +{ +size_t junkTailSize(solidity::yul::ssa::StackData const& _stackData) +{ + auto junkTail = _stackData | ranges::views::take_while([](auto const& slot) { return slot.isJunk(); }); + return static_cast(ranges::distance(junkTail)); +} +} + +namespace solidity::yul::ssa +{ + +std::string slotToString(StackSlot const& _slot) +{ + switch (_slot.kind()) + { + case StackSlot::Kind::ValueID: + if (_slot.isLiteralValueID()) + return fmt::format("lit{}", _slot.valueID().value()); + else + return fmt::format("v{}", _slot.valueID().value()); + case StackSlot::Kind::Junk: + return "JUNK"; + case StackSlot::Kind::FunctionCallReturnLabel: + return fmt::format("FunctionCallReturnLabel[{}]", _slot.functionCallReturnLabel()); + case StackSlot::Kind::FunctionReturnLabel: + return fmt::format("ReturnLabel[{}]", _slot.functionReturnLabel()); + } + util::unreachable(); +} + +std::string slotToString(StackSlot const& _slot, SSACFG const& _cfg) +{ + if (_slot.kind() == StackSlot::Kind::ValueID) + return _slot.valueID().str(_cfg); + + return slotToString(_slot); +} + +std::string stackToString(StackData const& _stackData) +{ + auto const numJunk = junkTailSize(_stackData); + if (numJunk > 0) + return fmt::format( + "[JUNK x {}, {}]", + numJunk, + fmt::join(_stackData | ranges::views::drop(numJunk) | ranges::views::transform([&](auto const& _slot) { return slotToString(_slot); }), ", ") + ); + + return fmt::format( + "[{}]", + fmt::join(_stackData | ranges::views::transform([&](auto const& _slot) { return slotToString(_slot); }), ", ") + ); +} + +std::string stackToString(StackData const& _stackData, SSACFG const& _cfg) +{ + auto const numJunk = junkTailSize(_stackData); + if (numJunk > 0) + return fmt::format( + "[JUNK x {}, {}]", + numJunk, + fmt::join(_stackData | ranges::views::drop(numJunk) | ranges::views::transform([&](auto const& _slot) { return slotToString(_slot, _cfg); }), ", ") + ); + + return fmt::format( + "[{}]", + fmt::join(_stackData | ranges::views::transform([&](auto const& _slot) { return slotToString(_slot, _cfg); }), ", ") + ); +} + +} diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h new file mode 100644 index 000000000..20207ebc7 --- /dev/null +++ b/libyul/backends/evm/ssa/Stack.h @@ -0,0 +1,305 @@ +/* + 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 + +#pragma once + +#include +#include + +#include +#include + +#include +#include + +namespace solidity::yul +{ + +struct FunctionCall; + +namespace ssa +{ + +/// Registry for tracking function call sites. +/// +/// Maps FunctionCall AST nodes to unique numeric IDs. These IDs are used +/// to generate return labels for function calls in the EVM bytecode. +class CallSites +{ +public: + using CallSiteID = std::uint32_t; + + std::optional callSiteID(FunctionCall const* _functionCall) const + { + if (auto const it = ranges::find(m_data, _functionCall); it != m_data.end()) + return static_cast(std::distance(m_data.begin(), it)); + return std::nullopt; + } + + FunctionCall const& functionCall(CallSiteID _callSite) const + { + yulAssert(_callSite < m_data.size()); + return *m_data[_callSite]; + } + + CallSiteID addCallSite(FunctionCall const* _functionCall) + { + if (auto const id = callSiteID(_functionCall)) + return *id; + yulAssert(_functionCall); + m_data.emplace_back(_functionCall); + return static_cast(m_data.size() - 1); + } +private: + std::vector m_data; +}; + +/// A discriminated union corresponding to a single EVM stack slot. +/// Can represent: +/// - ValueID: SSA values (including literals) +/// - Junk: Placeholder/unused values +/// - FunctionCallReturnLabel: Return addresses for function calls +/// - FunctionReturnLabel: Identifies the calling function's graph +/// +/// Memory layout is optimized: 8 bytes size for cache efficiency, trivially copyable, standard layout, trivial +class StackSlot +{ +public: + enum struct Kind: std::uint8_t + { + ValueID, // u32 + Junk, // empty + FunctionCallReturnLabel, // index into corresponding stack layout's call sites + FunctionReturnLabel // identifying the function graph via ControlFlow + }; + + constexpr StackSlot() = default; + constexpr StackSlot(StackSlot const&) = default; + constexpr StackSlot(StackSlot&&) = default; + constexpr StackSlot& operator=(StackSlot const&) = default; + constexpr StackSlot& operator=(StackSlot&&) = default; + + constexpr bool isValueID() const noexcept { return kind() == Kind::ValueID; } + constexpr bool isLiteralValueID() const noexcept { return m_valueIdKind == SSACFG::ValueId::Kind::Literal; } + constexpr bool isFunctionReturnLabel() const noexcept { return kind() == Kind::FunctionReturnLabel; } + constexpr bool isFunctionCallReturnLabel() const noexcept { return kind() == Kind::FunctionCallReturnLabel; } + constexpr bool isJunk() const noexcept { return kind() == Kind::Junk; } + constexpr Kind kind() const noexcept { return m_kind; } + + ControlFlow::FunctionGraphID functionReturnLabel() const { yulAssert(isFunctionReturnLabel()); return m_payload; } + CallSites::CallSiteID functionCallReturnLabel() const { yulAssert(isFunctionCallReturnLabel()); return m_payload; } + SSACFG::ValueId valueID() const { yulAssert(isValueID()); return {m_payload, m_valueIdKind}; } + + static constexpr StackSlot makeJunk() { return {0, Kind::Junk}; } + static constexpr StackSlot makeValueID(SSACFG::ValueId const& _valueID) { return {_valueID.value(), Kind::ValueID, _valueID.kind()}; } + static constexpr StackSlot makeFunctionReturnLabel(ControlFlow::FunctionGraphID const _graphID) { return {_graphID, Kind::FunctionReturnLabel}; } + static constexpr StackSlot makeFunctionCallReturnLabel(CallSites::CallSiteID const _callSiteID) { return {_callSiteID, Kind::FunctionCallReturnLabel}; } + + auto operator<=>(StackSlot const&) const = default; +private: + constexpr StackSlot(std::uint32_t const _payload, Kind const _kind, SSACFG::ValueId::Kind const _valueIdKind = SSACFG::ValueId::Kind::Unreachable): + m_payload(_payload), + m_kind(_kind), + m_valueIdKind(_valueIdKind) + {} + + /// interpretation depends on kind + std::uint32_t m_payload; + Kind m_kind; + SSACFG::ValueId::Kind m_valueIdKind; +}; +static_assert(sizeof(StackSlot) == 8, "Want cache efficiency, benchmark this if you go beyond 8 bytes"); +static_assert(std::is_trivially_copyable_v, "Should be able to use memcpy semantics"); +static_assert(std::is_standard_layout_v, "Want to have a predictable layout"); +static_assert(std::is_trivial_v, "Want to have no init/cpy overhead"); + +using StackData = std::vector; +std::string slotToString(StackSlot const& _slot); +std::string slotToString(StackSlot const& _slot, SSACFG const& _cfg); +std::string stackToString(StackData const& _stackData, SSACFG const& _cfg); +std::string stackToString(StackData const& _stackData); + +template +concept StackManipulationCallbackConcept = requires( + StackManipulationCallback& _callback, + StackSlot _slot, + size_t _depth +) +{ + { _callback.swap(_depth) } -> std::same_as; + { _callback.dup(_depth) } -> std::same_as; + { _callback.push(_slot) } -> std::same_as; + { _callback.pop() } -> std::same_as; +}; + +struct NoOpStackManipulationCallbacks +{ + static void swap(size_t) {} + static void dup(size_t) {} + static void push(StackSlot const&) {} + static void pop() {} +}; +static_assert(StackManipulationCallbackConcept); + +template< + StackManipulationCallbackConcept CallbacksType = NoOpStackManipulationCallbacks +> +class Stack +{ + static size_t constexpr reachableStackDepth = 16; +public: + using Callbacks = CallbacksType; + + using Slot = StackSlot; + using Data = StackData; + + /// Array index into stack from the bottom (offset 0 = bottom). + /// Natural for array-like access and iteration; used when treating the stack as a data structure. + struct Offset + { + explicit constexpr Offset(size_t _value) : value(_value) {} + size_t value; + auto operator<=>(Offset const&) const = default; + }; + // comparison operations with size_t + friend constexpr auto operator<=>(Offset lhs, size_t rhs) noexcept { return lhs.value <=> rhs; } + friend constexpr auto operator<=>(size_t lhs, Offset rhs) noexcept { return lhs <=> rhs.value; } + + /// Distance from the stack top (depth 0 = top). + /// Natural for stack operations (SWAP1 = swap with depth 1); used for operations that + /// conceptually work "from the top". + struct Depth + { + explicit constexpr Depth(size_t _value) : value(_value) {} + size_t value; + auto operator<=>(Depth const&) const = default; + }; + // comparison operations with size_t + friend constexpr auto operator<=>(Depth lhs, size_t rhs) noexcept { return lhs.value <=> rhs; } + friend constexpr auto operator<=>(size_t lhs, Depth rhs) noexcept { return lhs <=> rhs.value; } + + Stack( + Data& _data, + Callbacks _callbacks + ): + m_data(&_data), + m_callbacks(std::move(_callbacks)) + {} + + Slot const& top() const + { + yulAssert(!m_data->empty()); + return m_data->back(); + } + + void swap(Depth const& _depth) { swap(depthToOffset(_depth)); } + void swap(Offset const& _offset) + { + yulAssert(swapReachable(_offset), "Stack too deep"); + std::swap((*m_data)[_offset.value], m_data->back()); + if constexpr (!std::is_same_v) + m_callbacks.swap(offsetToDepth(_offset).value); + } + + /// if the stack state needs to be updated without notifying the callback, the template parameter can be set to false + template + void pop() + { + yulAssert(!m_data->empty()); + m_data->pop_back(); + if constexpr (callback && !std::is_same_v) + m_callbacks.pop(); + } + + /// if the stack state needs to be updated without notifying the callback, the template parameter can be set to false + template + void push(Slot const& _slot) + { + m_data->emplace_back(_slot); + if constexpr (callback && !std::is_same_v) + m_callbacks.push(_slot); + } + + void dup(Depth const& _depth) { dup(depthToOffset(_depth)); } + void dup(Offset const& _offset) + { + yulAssert(dupReachable(_offset), "Stack too deep"); + m_data->push_back((*m_data)[_offset.value]); + if constexpr (!std::is_same_v) + m_callbacks.dup(offsetToDepth(_offset).value + 1); + } + + bool dupReachable(Offset const& _offset) const noexcept { return dupReachable(offsetToDepth(_offset)); } + bool dupReachable(Depth const& _depth) const noexcept { return _depth < size() && _depth.value + 1 <= reachableStackDepth; } + bool swapReachable(Offset const& _offset) const noexcept { return swapReachable(offsetToDepth(_offset)); } + bool swapReachable(Depth const& _depth) const noexcept { return _depth < size() && 1 <= _depth.value && _depth.value <= reachableStackDepth; } + + void declareJunk(Depth const& _depth) { (*m_data)[depthToOffset(_depth).value] = Slot::makeJunk(); } + + Slot const& slot(Depth const& _depth) const { return (*m_data)[depthToOffset(_depth).value]; } + Slot const& slot(Offset const& _offset) const { return slot(offsetToDepth(_offset)); } + bool empty() const noexcept { return size() == 0; } + size_t size() const noexcept { return m_data->size(); } + + std::optional findSlotDepth(Slot const& _value) const + { + auto rview = *this | ranges::views::reverse; + auto it = ranges::find(rview, _value); + + if (it == ranges::end(rview)) + return std::nullopt; + + return Depth{static_cast(std::distance(ranges::begin(rview), it))}; + } + + static bool constexpr canBeFreelyGenerated(Slot const& _slot) + { + return _slot.isLiteralValueID() || _slot.isJunk() || _slot.isFunctionCallReturnLabel(); + } + + Slot const& operator[](Offset const& _index) const noexcept { return (*m_data)[_index.value]; } + auto begin() const { return ranges::begin(*m_data); } + auto end() const { return ranges::end(*m_data); } + + Data const& data() const + { + return *m_data; + } + + Callbacks const& callbacks() const { return m_callbacks; } + + /// index scheme conversion offset -> depth + Depth offsetToDepth(Offset const& _offset) const + { + yulAssert(_offset < size(), "Offset out of range"); + return Depth{size() - _offset.value - 1}; + } + /// index scheme conversion depth -> offset + Offset depthToOffset(Depth const& _depth) const + { + yulAssert(_depth < size(), "Depth out of range"); + return Offset{size() - _depth.value - 1}; + } + +private: + Data* m_data; + Callbacks m_callbacks; +}; + +} +} From b65295c39d03a85e37280241f43f19ef0403e297 Mon Sep 17 00:00:00 2001 From: Doryu Date: Tue, 4 Nov 2025 20:04:51 +0100 Subject: [PATCH 1010/1340] Update parse_eth_gas_report.py --- scripts/externalTests/parse_eth_gas_report.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/scripts/externalTests/parse_eth_gas_report.py b/scripts/externalTests/parse_eth_gas_report.py index c5cc58e58..ea8cbba66 100755 --- a/scripts/externalTests/parse_eth_gas_report.py +++ b/scripts/externalTests/parse_eth_gas_report.py @@ -115,13 +115,11 @@ def to_json(self): def parse_bool(input_string: str) -> bool: - if input_string == 'true': - return True - elif input_string == 'false': - return True - else: + if input_string not in ('true', 'false'): raise ValueError(f"Invalid boolean value: '{input_string}'") + return input_string == 'true' + def parse_optional_int(input_string: str, default: Optional[int] = None) -> Optional[int]: if input_string.strip() == '-': From bb3013529678e50785b58f222f92daffa00a1f69 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 1 Dec 2025 15:21:50 +0100 Subject: [PATCH 1011/1340] Bump ext-uniswap node to large --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 476b72eb3..1bb787062 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -831,7 +831,7 @@ defaults: project: uniswap binary_type: native image: cimg/node:lts - resource_class: medium # Tests run out of memory on a smaller machine + resource_class: large # Tests run out of memory on a smaller machine - job_native_test_ext_prb_math: &job_native_test_ext_prb_math <<: *requires_b_ubu_static From cd1f865427f4ad83229e3c4fddec409073073124 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Fri, 21 Nov 2025 12:22:10 -0300 Subject: [PATCH 1012/1340] Set osaka as default EVM version --- .circleci/config.yml | 2 +- .circleci/soltest_all.sh | 2 +- Changelog.md | 1 + docs/using-the-compiler.rst | 11 +++++---- liblangutil/EVMVersion.h | 2 +- scripts/externalTests/common.sh | 2 +- scripts/externalTests/runners/base.py | 2 +- scripts/tests.sh | 4 ++-- test/cmdlineTests/metadata/output | 2 +- .../standard_metadata/output.json | 2 +- .../output.json | 2 +- .../output.json | 2 +- .../output.json | 2 +- .../output.json | 4 ++-- .../output | 2 +- .../output | 2 +- test/libsolidity/StandardCompiler.cpp | 23 ++++++++++--------- 17 files changed, 35 insertions(+), 32 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1bb787062..6255d2834 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,7 +34,7 @@ parameters: default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:fc53d68a4680ffa7d5f70164e13a903478964f15bcc07434d74833a05f4fbc19" evm-version: type: string - default: prague + default: osaka orbs: win: circleci/windows@2.2.0 diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 86e62c333..8d6fc486b 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -38,7 +38,7 @@ EVMS_WITH_EOF=(osaka) # set EVM_VALUES to the default values. IFS=" " read -ra EVM_VALUES <<< "${1:-${DEFAULT_EVM_VALUES[@]}}" -DEFAULT_EVM=prague +DEFAULT_EVM=osaka OPTIMIZE_VALUES=(0 1) # TODO: EOF is marked as experimental in evmone. Reenable when proper handling for that is added here. EOF_VERSIONS=(0) diff --git a/Changelog.md b/Changelog.md index f772f6dd8..72551a4f8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: * ethdebug: Experimental support for instructions and source locations under EOF. +* EVM: Set default EVM Version to `osaka`. Bugfixes: * Assembler: Fix not using a fixed-width type for IDs being assigned to subassemblies nested more than one level away, resulting in inconsistent `--asm-json` output between target architectures. diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index a3943ea94..93d61af29 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -181,9 +181,9 @@ at each version. Backward compatibility is not guaranteed between each version. - Introduces ``blobhash()`` in inline assembly and a corresponding global function to retrieve versioned hashes of blobs associated with the transaction (see `EIP-4844 `_). - Opcode ``mcopy`` is available in assembly (see `EIP-5656 `_). - Opcodes ``tstore`` and ``tload`` are available in assembly (see `EIP-1153 `_). -- ``prague`` (**default**) -- ``osaka`` (**experimental**) - - Experimental compilation to EOF is available starting from this version. (`EIP-7692 `_) +- ``prague`` +- ``osaka`` (**default**) + - ``clz`` builtin function is available in inline assembly. (`EIP-7939 `_) .. index:: ! standard JSON, ! --standard-json .. _compiler-api: @@ -356,10 +356,11 @@ Input Description // Version of the EVM to compile for (optional). // Affects type checking and code generation. Can be homestead, // tangerineWhistle, spuriousDragon, byzantium, constantinople, - // petersburg, istanbul, berlin, london, paris, shanghai, cancun, prague (default) or osaka (experimental). - "evmVersion": "prague", + // petersburg, istanbul, berlin, london, paris, shanghai, cancun, prague or osaka (default). + "evmVersion": "osaka", // EVM Object Format version to compile for (optional, experimental). // Currently the only valid value is 1. If not specified, legacy non-EOF bytecode will be generated. + // Requires `evmVersion` >= osaka. "eofVersion": null, // Optional: Change compilation pipeline to go through the Yul intermediate representation. // This is false by default. diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 799fd2e0f..d4b25e100 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -170,7 +170,7 @@ class EVMVersion Prague, Osaka, }; - static auto constexpr currentVersion = Version::Prague; + static auto constexpr currentVersion = Version::Osaka; constexpr EVMVersion(Version _version): m_version(_version) {} diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index 6e435da95..88c656ca2 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -22,7 +22,7 @@ set -e # Requires $REPO_ROOT to be defined and "${REPO_ROOT}/scripts/common.sh" to be included before. -CURRENT_EVM_VERSION=prague +CURRENT_EVM_VERSION=osaka AVAILABLE_PRESETS=( legacy-no-optimize diff --git a/scripts/externalTests/runners/base.py b/scripts/externalTests/runners/base.py index 20ba67ddb..1158ebced 100644 --- a/scripts/externalTests/runners/base.py +++ b/scripts/externalTests/runners/base.py @@ -41,7 +41,7 @@ from test_helpers import settings_from_preset from test_helpers import SettingsPreset -CURRENT_EVM_VERSION: str = "prague" +CURRENT_EVM_VERSION: str = "osaka" @dataclass class TestConfig: diff --git a/scripts/tests.sh b/scripts/tests.sh index 5ff962be6..22df9a396 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -115,9 +115,9 @@ do for vm in $EVM_VERSIONS do FORCE_ABIV1_RUNS="no" - if [[ "$vm" == "prague" ]] + if [[ "$vm" == "osaka" ]] then - FORCE_ABIV1_RUNS="no yes" # run both in paris + FORCE_ABIV1_RUNS="no yes" # run both when testing the current EVM version fi for abiv1 in $FORCE_ABIV1_RUNS do diff --git a/test/cmdlineTests/metadata/output b/test/cmdlineTests/metadata/output index a62f2ed14..3e390b70a 100644 --- a/test/cmdlineTests/metadata/output +++ b/test/cmdlineTests/metadata/output @@ -1,4 +1,4 @@ ======= input.sol:C ======= Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"prague","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"osaka","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} diff --git a/test/cmdlineTests/standard_metadata/output.json b/test/cmdlineTests/standard_metadata/output.json index 155e15db1..143527278 100644 --- a/test/cmdlineTests/standard_metadata/output.json +++ b/test/cmdlineTests/standard_metadata/output.json @@ -2,7 +2,7 @@ "contracts": { "C": { "C": { - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2\",\"dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS\"]}},\"version\":1}" + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2\",\"dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS\"]}},\"version\":1}" } } }, diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json index 07087b30f..7c0a853e6 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/output.json @@ -2,7 +2,7 @@ "contracts": { "A": { "C": { - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" } } }, diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json index 07087b30f..7c0a853e6 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/output.json @@ -2,7 +2,7 @@ "contracts": { "A": { "C": { - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"A\":\"C\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":true,\"orderLiterals\":false,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false,\"yulDetails\":{\"optimizerSteps\":\":\"}},\"runs\":200},\"remappings\":[]},\"sources\":{\"A\":{\"keccak256\":\"0xb284c39999cb85b80be315a6e9e322adf67a783c66e91ba4439168694580a66d\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://098cee915fad095b8a996813768bd7d5e8c9e40c405e8c43d0572bb7bbc17334\",\"dweb:/ipfs/QmZmUzvSryrrD7pJ9S32iQnEWn4QBL4J1NdbQqL2Xc3yTr\"]}},\"version\":1}" } } }, diff --git a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json index eae7a321f..bce13b38e 100644 --- a/test/cmdlineTests/standard_outputs_on_compilation_error/output.json +++ b/test/cmdlineTests/standard_outputs_on_compilation_error/output.json @@ -32,7 +32,7 @@ "x()": "0c55699c" } }, - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x67a13ebd685e4c6f792e71eb747dac57edb99e94d04d841ee6c979ae517934ce\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://665b000da768823654f680d02686c1e59d682a0b3882e43a77fed9f80ce64ae8\",\"dweb:/ipfs/QmVnKvuidH6KiCdNQpoAQUtDbB8hXkafVLXWMNitUcxnqC\"]}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0x67a13ebd685e4c6f792e71eb747dac57edb99e94d04d841ee6c979ae517934ce\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://665b000da768823654f680d02686c1e59d682a0b3882e43a77fed9f80ce64ae8\",\"dweb:/ipfs/QmVnKvuidH6KiCdNQpoAQUtDbB8hXkafVLXWMNitUcxnqC\"]}},\"version\":1}", "storageLayout": { "storage": [], "types": null diff --git a/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json b/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json index be87a5176..9dec9899a 100644 --- a/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json +++ b/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json @@ -35,7 +35,7 @@ "irAst": null, "irOptimized": "", "irOptimizedAst": null, - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", "storageLayout": { "storage": [], "types": null @@ -84,7 +84,7 @@ "irAst": null, "irOptimized": "", "irOptimizedAst": null, - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"I\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"I\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", "storageLayout": { "storage": [], "types": null diff --git a/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output index de60e7d1d..a8d3556c8 100644 --- a/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output +++ b/test/cmdlineTests/yul_optimizer_disabled_sequence_empty/output @@ -1,4 +1,4 @@ ======= input.sol:C ======= Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"prague","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0xc2db3500808896ce1e69de2fe20cecab7ae2ffbb47cdf6ba8321296d95f49fc5","license":"GPL-3.0","urls":["bzz-raw://fde21393c068cd9f2d2b10ba4782db54f6f1c9a725074b17fa742531076be8a4","dweb:/ipfs/QmeTD6mR7YrWNyRowKRS7xs6cJNeMF3T49GAHzGM1bquyM"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"osaka","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0xc2db3500808896ce1e69de2fe20cecab7ae2ffbb47cdf6ba8321296d95f49fc5","license":"GPL-3.0","urls":["bzz-raw://fde21393c068cd9f2d2b10ba4782db54f6f1c9a725074b17fa742531076be8a4","dweb:/ipfs/QmeTD6mR7YrWNyRowKRS7xs6cJNeMF3T49GAHzGM1bquyM"]}},"version":1} diff --git a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output index 2b32c23ee..0c4c0acec 100644 --- a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output +++ b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output @@ -130,4 +130,4 @@ object "C_28" { } Metadata: -{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"foo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"prague","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0x3fc910e345ce1ee62bfa6b0f66931ee632c08265b25b6139cfbbfe4d2f8d5dd8","license":"GPL-3.0","urls":["bzz-raw://e557e9ad2c2e420a669c06ae456b0b790d77d2d6d492cd8540e6b244388a5140","dweb:/ipfs/QmaNiZmC2Mo3YxGiehs1n3dVTjZwD7FguX7EUtpeshMVuR"]}},"version":1} +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"foo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"osaka","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"details":{"constantOptimizer":false,"cse":false,"deduplicate":false,"inliner":false,"jumpdestRemover":true,"orderLiterals":false,"peephole":true,"simpleCounterForLoopUncheckedIncrement":true,"yul":false,"yulDetails":{"optimizerSteps":":"}},"runs":200},"remappings":[]},"sources":{"input.sol":{"keccak256":"0x3fc910e345ce1ee62bfa6b0f66931ee632c08265b25b6139cfbbfe4d2f8d5dd8","license":"GPL-3.0","urls":["bzz-raw://e557e9ad2c2e420a669c06ae456b0b790d77d2d6d492cd8540e6b244388a5140","dweb:/ipfs/QmaNiZmC2Mo3YxGiehs1n3dVTjZwD7FguX7EUtpeshMVuR"]}},"version":1} diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 93a632032..7be21863a 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -38,6 +38,7 @@ #include using namespace solidity::evmasm; +using namespace solidity::langutil; using namespace std::string_literals; namespace solidity::frontend::test @@ -46,15 +47,15 @@ namespace solidity::frontend::test namespace { -langutil::Error::Severity str2Severity(std::string const& _cat) +Error::Severity str2Severity(std::string const& _cat) { - std::map cats{ - {"info", langutil::Error::Severity::Info}, - {"Info", langutil::Error::Severity::Info}, - {"warning", langutil::Error::Severity::Warning}, - {"Warning", langutil::Error::Severity::Warning}, - {"error", langutil::Error::Severity::Error}, - {"Error", langutil::Error::Severity::Error} + std::map cats{ + {"info", Error::Severity::Info}, + {"Info", Error::Severity::Info}, + {"warning", Error::Severity::Warning}, + {"Warning", Error::Severity::Warning}, + {"error", Error::Severity::Error}, + {"Error", Error::Severity::Error} }; return cats.at(_cat); } @@ -86,7 +87,7 @@ bool containsAtMostWarnings(Json const& _compilerResult) { BOOST_REQUIRE(error.is_object()); BOOST_REQUIRE(error["severity"].is_string()); - if (langutil::Error::isError(str2Severity(error["severity"].get()))) + if (Error::isError(str2Severity(error["severity"].get()))) return false; } @@ -1171,14 +1172,14 @@ BOOST_AUTO_TEST_CASE(evm_version) )"; }; Json result; - for (auto const& version: langutil::EVMVersion::allVersions()) + for (auto const& version: EVMVersion::allVersions()) { result = compile(inputForVersion(fmt::format("\"evmVersion\": \"{}\",", version.name()))); BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find(fmt::format("\"evmVersion\":\"{}\"", version.name())) != std::string::npos); } // test default result = compile(inputForVersion("")); - BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find("\"evmVersion\":\"prague\"") != std::string::npos); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find(fmt::format("\"evmVersion\":\"{}\"", EVMVersion::current().name())) != std::string::npos); // test invalid result = compile(inputForVersion("\"evmVersion\": \"invalid\",")); BOOST_CHECK(result["errors"][0]["message"].get() == "Invalid EVM version requested."); From 25ec75c786feb4b73f287e0ff5304bc5677ea1ff Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 2 Dec 2025 12:06:03 +0100 Subject: [PATCH 1013/1340] Set blockGasLimit to 2^24 for external tests --- scripts/externalTests/common.sh | 12 ++++++++++++ test/externalTests/gp2.sh | 3 ++- test/externalTests/pool-together.sh | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index 88c656ca2..0465a4fec 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -334,6 +334,12 @@ function force_hardhat_compiler_settings echo "module.exports.solidity = ${compiler_settings};" echo "module.exports.networks.hardhat = module.exports.networks.hardhat || { hardfork: '${evm_version}' }" echo "module.exports.networks.hardhat.hardfork = '${evm_version}'" + if [[ $evm_version == "osaka" ]]; then + # Transaction gas limit introduced by EIP-7825; the default value is 30_000_000 + # and should be automatically handled by EDR - however, EDR with the relevant change + # was not released in time. + echo "module.exports.networks.hardhat.blockGasLimit = 16_777_216" + fi else [[ $config_file == *\.ts ]] || assertFail [[ $config_var_name != "" ]] || assertFail @@ -342,6 +348,12 @@ function force_hardhat_compiler_settings echo "${config_var_name}.solidity = {compilers: [${compiler_settings}]};" echo "${config_var_name}.networks!.hardhat = ${config_var_name}.networks!.hardhat ?? { hardfork: '${evm_version}' };" echo "${config_var_name}.networks!.hardhat!.hardfork = '${evm_version}'" + if [[ $evm_version == "osaka" ]]; then + # Transaction gas limit introduced by EIP-7825; the default value is 30_000_000 + # and should be automatically handled by EDR - however, EDR with the relevant change + # was not released in time. + echo "${config_var_name}.networks!.hardhat!.blockGasLimit = 16_777_216" + fi fi >> "$config_file" } diff --git a/test/externalTests/gp2.sh b/test/externalTests/gp2.sh index fb3348237..cc8b56b66 100755 --- a/test/externalTests/gp2.sh +++ b/test/externalTests/gp2.sh @@ -67,7 +67,8 @@ function gp2_test force_hardhat_unlimited_contract_size "$config_file" "$config_var" yarn # Hardhat 3.0+ breaks the test suite - yarn add hardhat@2.26.3 + # v2.27.1 is the last v2 Hardhat (introduces Osaka support) + yarn add hardhat@2.27.1 # Ignore bench directory which fails to compile with current hardhat and ethers versions. # bench/trace/gas.ts:123:19 - error TS2339: Property 'equals' does not exist on type 'Uint8Array'. diff --git a/test/externalTests/pool-together.sh b/test/externalTests/pool-together.sh index 4f1c68814..e871b4e57 100755 --- a/test/externalTests/pool-together.sh +++ b/test/externalTests/pool-together.sh @@ -67,7 +67,8 @@ function pool_together_test force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" yarn install # Hardhat 3.0+ breaks the test suite - yarn add hardhat@2.26.3 + # v2.27.1 is the last v2 Hardhat (introduces Osaka support) + yarn add hardhat@2.27.1 # These come with already compiled artifacts. We want them recompiled with latest compiler. rm -r node_modules/@pooltogether/yield-source-interface/artifacts/ From 5fc0f341aa681965d7dcea2ddda7c66c101af53b Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 2 Dec 2025 18:02:43 +0100 Subject: [PATCH 1014/1340] Disable RSA suite in OZ-contracts --- test/externalTests/zeppelin.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 9bc3e2913..99df125bb 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -105,6 +105,9 @@ function zeppelin_test # Fails with ProviderError: Invalid transaction: GasFloorMoreThanGasLimit sed -i "177s|+ 2_000n|+ 10_000n|" test/metatx/ERC2771Forwarder.test.js + # Fails under evmVersion=osaka, likely due to transaction gas limits introduced by EIP-7825 or by the modexp upper bound EIP-7823. + sed -i "s|describe(\('RSA'\)|describe.skip(\1|g" test/utils/cryptography/RSA.test.js + neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" From b1acbf78a6ac749d25e97b42f5bdc21a3a995827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 14:20:02 +0200 Subject: [PATCH 1015/1340] Discontinue support for Ubuntu PPAs --- .gitignore | 3 - Changelog.md | 1 + ReleaseChecklist.md | 18 --- docs/installing-solidity.rst | 20 +-- scripts/common.sh | 22 --- scripts/release_ppa.sh | 292 ----------------------------------- 6 files changed, 4 insertions(+), 352 deletions(-) delete mode 100755 scripts/release_ppa.sh diff --git a/.gitignore b/.gitignore index a9430fd98..8d7ee768a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ /commit_hash.txt /prerelease.txt -# Auth config for ppa release -/.release_ppa_auth - # Compiled Object files *.slo *.lo diff --git a/Changelog.md b/Changelog.md index 72551a4f8..b34e4d4cb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Bugfixes: Build System: * Enable Linux arm64 binaries for testing and releases. +* Ubuntu PPA Packages: Discontinue the PPA as a binary distribution channel. * Update minimum version requirements of Boost to 1.83.0 for non-windows builds and of GCC and Clang to 13.3 and 18.1.3, respectively. Fixes infinite recursion on `boost::rational` comparison affecting compiler binaries built with GCC<14.0 and Boost<1.75. ### 0.8.30 (2025-05-07) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index d8d63b09a..4eada5f65 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -4,10 +4,7 @@ - [ ] GitHub account with access to [solidity](https://github.com/argotorg/solidity), [solc-js](https://github.com/argotorg/solc-js), [solc-bin](https://github.com/argotorg/solc-bin), [solidity-website](https://github.com/argotorg/solidity-website). - [ ] DockerHub account with push rights to the [`solc` image](https://hub.docker.com/r/ethereum/solc). -- [ ] Launchpad (Ubuntu One) account with a membership in the ["Ethereum" team](https://launchpad.net/~ethereum) and - a gnupg key for your email in the `ethereum.org` domain (has to be version 1, gpg2 won't work). - [ ] Ubuntu/Debian dependencies of the Docker script: `docker-buildx`. -- [ ] Ubuntu/Debian dependencies of the PPA scripts: `devscripts`, `debhelper`, `dput`, `git`, `wget`, `ca-certificates`. - [ ] [npm Registry](https://www.npmjs.com) account added as a collaborator for the [`solc` package](https://www.npmjs.com/package/solc). - [ ] Access to the [solidity_lang Twitter account](https://twitter.com/solidity_lang). - [ ] [Reddit](https://www.reddit.com) account that is at least 10 days old with a minimum of 20 comment karma (`/r/ethereum` requirements). @@ -24,8 +21,6 @@ At least a day before the release: - [ ] Rerun CI on the top commits of main branches in all repositories that do not have daily activity by creating a test branch or PR: - [ ] `solc-js` - [ ] `solc-bin` (make sure the bytecode comparison check did run) -- [ ] (Optional) Create a prerelease in our Ubuntu PPA by following the steps in the PPA section below on `develop` rather than on a tag. - This is recommended especially when dealing with PPA for the first time, when we add a new Ubuntu version or when the PPA scripts were modified in this release cycle. - [ ] Verify that the release tarball of `solc-js` works. Bump version locally, add `soljson.js` from CI, build it, compare the file structure with the previous version, install it locally and try to use it. - [ ] Review [Learning from Past Releases](https://notes.argot.org/@solidity-release-mistakes) to make sure you don't repeat the same mistakes. @@ -82,19 +77,6 @@ At least a day before the release: - [ ] Make sure `docker-buildx` is installed. - [ ] Run `./scripts/docker_deploy_manual.sh v$VERSION`. -### PPA -- [ ] Create `.release_ppa_auth` at the root of your local Solidity checkout and set `LAUNCHPAD_EMAIL` and `LAUNCHPAD_KEYID` to your key's email and key id. -- [ ] Double-check that the `DISTRIBUTIONS` list in `scripts/release_ppa.sh` contains the most recent versions of Ubuntu. -- [ ] Run `scripts/release_ppa.sh v$VERSION` to create the PPA release. - This will create a single package containing static binary for older Ubuntu versions in the [`~ethereum/ethereum-static` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum-static) - and separate packages with dynamically-linked binaries for recent versions (those listed in `DISTRIBUTIONS`) in the [`~ethereum/ethereum` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum). -- [ ] Wait for the build to be finished and published for *all architectures* (currently we only build for `amd64`, but we may add `arm` in the future). - **SERIOUSLY: DO NOT PROCEED EARLIER!!!** -- [ ] *After* the package with the static build is *published*, use it to create packages for older Ubuntu versions. - Copy the static package to the [`~ethereum/ethereum` PPA](https://launchpad.net/~ethereum/+archive/ubuntu/ethereum) - for the destination series `Trusty`, `Xenial`, `Bionic`, and `Focal` - while selecting `Copy existing binaries`. - ### Release solc-js - [ ] Wait until solc-bin was properly deployed. You can test this via remix - a test run through remix is advisable anyway. - [ ] Increment the version number, create a pull request for that, merge it after tests succeeded. diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index bda0d102b..01a2f3820 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -116,23 +116,9 @@ Linux Packages Binary packages of Solidity are available at `solidity/releases `_. -We also have PPAs for Ubuntu, you can get the latest stable -version using the following commands: - -.. code-block:: bash - - sudo add-apt-repository ppa:ethereum/ethereum - sudo apt-get update - sudo apt-get install solc - -The nightly version can be installed using these commands: - -.. code-block:: bash - - sudo add-apt-repository ppa:ethereum/ethereum - sudo add-apt-repository ppa:ethereum/ethereum-dev - sudo apt-get update - sudo apt-get install solc +Ubuntu packages for versions up to 0.8.30 are available in the +`ethereum/ethereum PPA `_. +However, we have discontinued this distribution method and future versions will not be added there. Furthermore, some Linux distributions provide their own packages. These packages are not directly maintained by us but usually kept up-to-date by the respective package maintainers. diff --git a/scripts/common.sh b/scripts/common.sh index 0ca602ee6..a25fe5a82 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -40,28 +40,6 @@ else function printLog { echo -e "$(tput setaf 3)$1$(tput sgr0)"; } fi -function checkDputEntries -{ - local pattern="$1" - grep "${pattern}" /etc/dput.cf --quiet || \ - fail "Error: Missing ${pattern//\\/} section in /etc/dput.cf (check top comment in release_ppa.sh for more information)." -} - -function sourcePPAConfig -{ - [[ "$LAUNCHPAD_KEYID" == "" && "$LAUNCHPAD_EMAIL" == "" ]] || fail - - # source keyid and email from .release_ppa_auth - if [[ -e .release_ppa_auth ]] - then - # shellcheck source=/dev/null - source "${REPO_ROOT}/.release_ppa_auth" - fi - - [[ "$LAUNCHPAD_KEYID" != "" && "$LAUNCHPAD_EMAIL" != "" ]] || \ - fail "Error: Couldn't find variables \$LAUNCHPAD_KEYID or \$LAUNCHPAD_EMAIL in sourced file .release_ppa_auth (check top comment in $0 for more information)." -} - function printStackTrace { printWarning "" diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh deleted file mode 100755 index 6c1fd51db..000000000 --- a/scripts/release_ppa.sh +++ /dev/null @@ -1,292 +0,0 @@ -#!/usr/bin/env bash -############################################################################## -## This is used to package .deb packages and upload them to the launchpad -## ppa servers for building. -## -## You can pass a branch name as argument to this script (which, if no argument is given, -## will default to "develop"). -## -## If the given branch matches a release version tag, the resulting package will be uploaded to -## ethereum/ethereum PPA, or ethereum/ethereum-dev PPA otherwise. -## -## It will clone the Solidity git from github, determine the version, -## create a source archive and push it to the ubuntu ppa servers. -## -## To interact with launchpad, you need to set the variables $LAUNCHPAD_EMAIL -## and $LAUNCHPAD_KEYID in the file .release_ppa_auth in the root directory of -## the project to your launchpad email and pgp keyid. -## This could for example look like this: -## -## LAUNCHPAD_EMAIL=your-launchpad-email@ethereum.org -## LAUNCHPAD_KEYID=123ABCFFFFFFFF -## -## Additionally the following entries in /etc/dput.cf are required: -## -## [ethereum-dev] -## fqdn = ppa.launchpad.net -## method = ftp -## incoming = ~ethereum/ethereum-dev -## login = anonymous -## -## [ethereum] -## fqdn = ppa.launchpad.net -## method = ftp -## incoming = ~ethereum/ethereum -## login = anonymous -## -## [ethereum-static] -## fqdn = ppa.launchpad.net -## method = ftp -## incoming = ~ethereum/ethereum-static -## login = anonymous -## -############################################################################## - -set -e - - -REPO_ROOT="$(dirname "$0")/.." - -# shellcheck source=scripts/common.sh -source "${REPO_ROOT}/scripts/common.sh" - -if [ -z "$1" ] -then - branch=develop -else - branch=$1 -fi - -is_release() { - [[ "${branch}" =~ ^v[0-9]+(\.[0-9]+)*$ ]] -} - -sourcePPAConfig - -packagename=solc - -# This needs to be a still active release -static_build_distribution=noble - -DISTRIBUTIONS="jammy noble oracular plucky" - -if is_release -then - DISTRIBUTIONS="$DISTRIBUTIONS STATIC" - - # Sanity checks - checkDputEntries "\[ethereum\]" - checkDputEntries "\[ethereum-static\]" -else - # Sanity check - checkDputEntries "\[ethereum-dev\]" -fi - -for distribution in $DISTRIBUTIONS -do -cd /tmp/ -rm -rf "$distribution" -mkdir "$distribution" -cd "$distribution" - -if [ "$distribution" = STATIC ] -then - pparepo=ethereum-static - CMAKE_OPTIONS="-DSOLC_LINK_STATIC=On -DCMAKE_EXE_LINKER_FLAGS=-static" -else - if is_release - then - pparepo=ethereum - else - pparepo=ethereum-dev - fi - CMAKE_OPTIONS="" -fi -ppafilesurl=https://launchpad.net/~ethereum/+archive/ubuntu/${pparepo}/+files - -# Fetch source -git clone --depth 2 --recursive https://github.com/argotorg/solidity.git -b "$branch" -mv solidity solc - -# Determine version -cd solc -version=$("$(dirname "$0")/get_version.sh") -commithash=$(git rev-parse --short=8 HEAD) -commitdate=$(git show --format=%ci HEAD | head -n 1 | cut - -b1-10 | sed -e 's/-0?/./' | sed -e 's/-0?/./') - -echo "$commithash" > commit_hash.txt -if is_release -then - debversion="$version" - echo -n > prerelease.txt # proper release -else - debversion="$version~develop-$commitdate-$commithash" -fi - -# gzip will create different tars all the time and we are not allowed -# to upload the same file twice with different contents, so we only -# create it once. -if [ ! -e "/tmp/${packagename}_${debversion}.orig.tar.gz" ] -then - tar --exclude .git -czf "/tmp/${packagename}_${debversion}.orig.tar.gz" . -fi -cp "/tmp/${packagename}_${debversion}.orig.tar.gz" ../ - -# Create debian package information - -mkdir debian -echo 9 > debian/compat -cat < debian/control -Source: solc -Section: science -Priority: extra -Maintainer: Christian (Buildserver key) -Build-Depends: debhelper (>= 9.0.0), - cmake, - g++ (>= 5.0), - git, - libgmp-dev, - libboost-all-dev, - automake, - libtool, - scons -Standards-Version: 3.9.5 -Homepage: https://ethereum.org -Vcs-Git: https://github.com/argotorg/solidity.git -Vcs-Browser: https://github.com/argotorg/solidity - -Package: solc -Architecture: any-amd64 -Multi-Arch: same -Depends: \${shlibs:Depends}, \${misc:Depends} -Conflicts: libethereum (<= 1.2.9) -Description: Solidity compiler. - The commandline interface to the Solidity smart contract compiler. -EOF -cat < debian/rules -#!/usr/bin/make -f -# -*- makefile -*- -# Sample debian/rules that uses debhelper. -# -# This file was originally written by Joey Hess and Craig Small. -# As a special exception, when this file is copied by dh-make into a -# dh-make output file, you may use that output file without restriction. -# This special exception was added by Craig Small in version 0.37 of dh-make. -# -# Modified to make a template file for a multi-binary package with separated -# build-arch and build-indep targets by Bill Allombert 2001 - -# Uncomment this to turn on verbose mode. -export DH_VERBOSE=1 - -# This has to be exported to make some magic below work. -export DH_OPTIONS - - -%: - dh \$@ --buildsystem=cmake #--with sphinxdoc - -override_dh_auto_test: - -#override_dh_installdocs: -# make -C docs html -# dh_installdocs docs/_build/html - -override_dh_shlibdeps: - dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info - -override_dh_auto_configure: - dh_auto_configure -- -DTESTS=OFF -DFETCHCONTENT_FULLY_DISCONNECTED=OFF ${CMAKE_OPTIONS} -EOF -cat < debian/copyright -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: solc -Source: https://github.com/argotorg/solidity - -Files: * -Copyright: 2014-2016 Ethereum -License: GPL-3.0+ - -Files: debian/* -Copyright: 2016 Ethereum -License: GPL-3.0+ - -License: GPL-3.0+ - This program 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. - . - This package 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 this program. If not, see . - . - On Debian systems, the complete text of the GNU General - Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". -EOF -cat < debian/changelog -solc (0.0.1-0ubuntu1) saucy; urgency=low - - * Initial release. - - -- Christian Mon, 03 Feb 2016 14:50:20 +0000 -EOF -echo docs > debian/docs -mkdir debian/source -echo "3.0 (quilt)" > debian/source/format -chmod +x debian/rules - -versionsuffix=0ubuntu1~${distribution} -# bump version / add entry to changelog -EMAIL="$LAUNCHPAD_EMAIL" dch -v "1:${debversion}-${versionsuffix}" "git build of ${commithash}" - - -# build source package -# If packages is rejected because original source is already present, add -# -sd to remove it from the .changes file -# -d disables the build dependencies check -debuild -S -d -sa -us -uc - -# prepare .changes file for Launchpad -if [ "$distribution" = STATIC ] -then - sed -i -e "s/UNRELEASED/${static_build_distribution}/" -e s/urgency=medium/urgency=low/ ../*.changes -else - sed -i -e "s/UNRELEASED/${distribution}/" -e s/urgency=medium/urgency=low/ ../*.changes -fi - -# check if ubuntu already has the source tarball -( -cd .. -orig="${packagename}_${debversion}.orig.tar.gz" -# shellcheck disable=SC2012 -orig_size=$(ls -l "$orig" | cut -d ' ' -f 5) -orig_sha1=$(sha1sum "$orig" | cut -d ' ' -f 1) -orig_sha256=$(sha256sum "$orig" | cut -d ' ' -f 1) -orig_md5=$(md5sum "$orig" | cut -d ' ' -f 1) - -if wget --quiet -O "$orig-tmp" "$ppafilesurl/$orig" -then - echo "[WARN] Original tarball found in Ubuntu archive, using it instead" - mv "$orig-tmp" "$orig" - # shellcheck disable=SC2012 - new_size=$(ls -l ./*.orig.tar.gz | cut -d ' ' -f 5) - new_sha1=$(sha1sum "$orig" | cut -d ' ' -f 1) - new_sha256=$(sha256sum "$orig" | cut -d ' ' -f 1) - new_md5=$(md5sum "$orig" | cut -d ' ' -f 1) - sed -i -e "s,$orig_sha1,$new_sha1,g" -e "s,$orig_sha256,$new_sha256,g" -e "s,$orig_size,$new_size,g" -e "s,$orig_md5,$new_md5,g" ./*.dsc - sed -i -e "s,$orig_sha1,$new_sha1,g" -e "s,$orig_sha256,$new_sha256,g" -e "s,$orig_size,$new_size,g" -e "s,$orig_md5,$new_md5,g" ./*.changes -fi -) - -# sign the package -debsign --re-sign -k "${LAUNCHPAD_KEYID}" "../${packagename}_${debversion}-${versionsuffix}_source.changes" - -# upload -dput "${pparepo}" "../${packagename}_${debversion}-${versionsuffix}_source.changes" - -done From 9cda966876b699156521bc83ac48d88d0aee28f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 2 Dec 2025 19:37:52 +0100 Subject: [PATCH 1016/1340] Docs: Remove outdated paragraph about installing a solver being required for SMTChecker pragmas --- docs/layout-of-source-files.rst | 9 --------- 1 file changed, 9 deletions(-) diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index e51b3ad98..58b38400f 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -153,15 +153,6 @@ since Solidity 0.7.4. SMTChecker ~~~~~~~~~~ -This component has to be enabled when the Solidity compiler is built -and therefore it is not available in all Solidity binaries. -The :ref:`build instructions` explain how to activate this option. -It is activated for the Ubuntu PPA releases in most versions, -but not for the Docker images, Windows binaries or the -statically-built Linux binaries. It can be activated for solc-js via the -`smtCallback `_ if you have an SMT solver -installed locally and run solc-js via node (not via the browser). - If you use ``pragma experimental SMTChecker;``, then you get additional :ref:`safety warnings` which are obtained by querying an SMT solver. From e4e515c07530127487a57594f7eb9a6e7911465d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 2 Dec 2025 19:38:35 +0100 Subject: [PATCH 1017/1340] Docs: Deprecation note for SMTChecker pragma --- docs/layout-of-source-files.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index 58b38400f..e2c7a859a 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -160,6 +160,11 @@ The component does not yet support all features of the Solidity language and likely outputs many warnings. In case it reports unsupported features, the analysis may not be fully sound. +.. note:: + + The ``SMTChecker`` pragma is deprecated and will be removed. + To enable SMTChecker, simply select :ref:`select an engine` when invoking the compiler. + .. index:: source file, ! import, module, source unit .. _import: From f4173b2a7e4c975f0cda7ee665cab0b9404d985e Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 18 Aug 2025 20:35:10 -0300 Subject: [PATCH 1018/1340] Emit deprecation warnings for abi coder v1, contract comparisons, memory-safe-assembly, send and transfer functions, and virtual modifiers. --- Changelog.md | 5 ++++ libsolidity/analysis/DocStringTagParser.cpp | 11 +++++++-- libsolidity/analysis/SyntaxChecker.cpp | 18 +++++++++++++++ libsolidity/analysis/TypeChecker.cpp | 23 +++++++++++++++++++ .../model_checker_targets_all_all_engines/err | 6 +++++ .../model_checker_targets_all_bmc/err | 6 +++++ .../model_checker_targets_all_chc/err | 6 +++++ .../model_checker_targets_assert_bmc/err | 6 +++++ .../model_checker_targets_assert_chc/err | 6 +++++ .../model_checker_targets_balance_bmc/err | 6 +++++ .../model_checker_targets_balance_chc/err | 6 +++++ .../err | 6 +++++ .../err | 5 ++++ .../err | 6 +++++ .../model_checker_targets_default_bmc/err | 6 +++++ .../model_checker_targets_default_chc/err | 6 +++++ .../model_checker_targets_div_by_zero_bmc/err | 6 +++++ .../model_checker_targets_div_by_zero_chc/err | 6 +++++ .../err | 5 ++++ .../err | 6 +++++ .../model_checker_targets_overflow_bmc/err | 6 +++++ .../model_checker_targets_overflow_chc/err | 6 +++++ .../model_checker_targets_pop_empty_bmc/err | 5 ++++ .../model_checker_targets_pop_empty_chc/err | 6 +++++ .../model_checker_targets_underflow_bmc/err | 6 +++++ .../model_checker_targets_underflow_chc/err | 6 +++++ .../err | 6 +++++ .../err | 6 +++++ .../err | 6 +++++ .../err | 6 +++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 21 +++++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 21 +++++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 21 +++++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ .../output.json | 19 +++++++++++++++ test/cmdlineTests/viair_abicoder_v1/err | 6 +++++ .../blockchain_state/balance_spend.sol | 1 + .../blockchain_state/balance_spend_2.sol | 1 + .../blockchain_state/decreasing_balance.sol | 1 + .../blockchain_state/free_function_2.sol | 3 ++- .../blockchain_state/library_internal_2.sol | 3 ++- .../blockchain_state/library_public_2.sol | 7 +++--- .../blockchain_state/transfer_1.sol | 3 ++- .../blockchain_state/transfer_2.sol | 2 ++ .../blockchain_state/transfer_3.sol | 3 ++- .../blockchain_state/transfer_4.sol | 1 + .../smtCheckerTests/bmc_coverage/funds.sol | 1 + .../deployment/deploy_trusted_addresses.sol | 1 + .../deployment/deploy_untrusted_addresses.sol | 5 ++-- .../functions/getters/array_of_structs_1.sol | 1 + .../functions/getters/array_of_structs_2.sol | 1 + .../functions/getters/array_of_structs_3.sol | 3 ++- .../functions/getters/contract.sol | 3 ++- .../functions/getters/struct_4.sol | 3 ++- .../modifiers/modifier_abstract.sol | 1 + .../modifiers/modifier_overriding_1.sol | 3 ++- .../modifiers/modifier_overriding_2.sol | 2 ++ .../modifiers/modifier_overriding_3.sol | 4 +++- .../modifiers/modifier_overriding_4.sol | 4 ++++ .../modifier_virtual_static_call_1.sol | 1 + .../modifier_virtual_static_call_2.sol | 3 ++- .../types/address_transfer.sol | 5 ++-- .../types/address_transfer_2.sol | 8 ++++--- .../types/address_transfer_3.sol | 1 + .../types/address_transfer_insufficient.sol | 8 ++++--- .../smtCheckerTests/types/contract.sol | 3 ++- .../smtCheckerTests/types/contract_2.sol | 3 ++- .../smtCheckerTests/types/contract_3.sol | 3 +++ .../types/contract_address_conversion_2.sol | 1 + .../abiEncoder/conflicting_settings.sol | 1 + .../conflicting_settings_reverse.sol | 1 + ...flicting_settings_reverse_experimental.sol | 1 + .../syntaxTests/abiEncoder/select_v1.sol | 1 + .../abiEncoder/select_v1_quoted_string.sol | 1 + .../syntaxTests/abiEncoder/selected_twice.sol | 2 ++ ...sing_public_state_variable_via_v1_type.sol | 1 + ...sing_public_state_variable_via_v2_type.sol | 1 + ...rary_function_accepting_storage_struct.sol | 1 + ...all_to_v2_constructor_accepting_struct.sol | 1 + ...on_accepting_struct_via_named_argument.sol | 1 + ...ract_function_pointer_accepting_struct.sol | 1 + ...unction_returning_dynamic_string_array.sol | 1 + ..._v2_contract_function_returning_struct.sol | 1 + ...on_returning_struct_with_dynamic_array.sol | 1 + .../v1_call_to_v2_event_accepting_struct.sol | 1 + ...ary_attached_function_returning_struct.sol | 1 + ...rary_function_accepting_storage_struct.sol | 1 + ...o_v2_library_function_returning_struct.sol | 1 + .../abiEncoder/v1_call_to_v2_modifier.sol | 1 + .../v1_constructor_with_v2_modifier.sol | 2 ++ ...ance_from_contract_calling_v2_function.sol | 1 + ...itance_from_contract_defining_v2_event.sol | 1 + ..._defining_v2_function_accepting_struct.sol | 1 + ..._defining_v2_function_returning_struct.sol | 1 + ...itance_from_contract_emitting_v2_event.sol | 1 + .../v1_modifier_overriding_v2_modifier.sol | 2 ++ .../abiEncoder/v1_v2_v1_modifier_mix.sol | 3 +++ .../abiEncoder/v2_v1_v1_modifier_sandwich.sol | 2 ++ .../abiEncoder/v2_v1_v2_modifier_sandwich.sol | 1 + .../array/calldata_multi_dynamic_V1.sol | 1 + .../syntaxTests/constructor/nonabiv2_type.sol | 1 + .../constructor/nonabiv2_type_abstract.sol | 1 + .../implemented_without_placeholder.sol | 1 + .../modifier_different_functions.sol | 1 + .../modifiers/modifier_override.sol | 1 + .../modifiers/non_implemented_modifier.sol | 2 ++ ...icit_conversion_of_super_in_comparison.sol | 3 +++ .../errors/no_structs_in_abiv1.sol | 1 + .../syntaxTests/events/event_nested_array.sol | 1 + .../events/event_nested_array_in_struct.sol | 1 + .../syntaxTests/events/event_struct.sol | 1 + .../events/event_struct_indexed.sol | 1 + .../syntaxTests/getter/nested_structs.sol | 1 + .../inheritance_virtual_modifiers.sol | 2 ++ .../inheritance_abi_encoder_mismatch_1.sol | 1 + .../inheritance_abi_encoder_mismatch_2.sol | 2 ++ ..._data_location_change_illegal_internal.sol | 1 + .../override/modifier_ambiguous.sol | 2 ++ .../override/modifier_ambiguous_fail.sol | 2 ++ ...modifier_inherited_different_signature.sol | 2 ++ ...inherited_different_signature_override.sol | 3 +++ ...ase_and_unique_implementation_modifier.sol | 3 +++ .../virtual/modifier_virtual_err.sol | 1 + .../inheritance/virtual/simple.sol | 1 + ...memory_safe_dialect_string_and_comment.sol | 3 ++- .../inlineAssembly/natspec_multi.sol | 2 ++ .../natspec_multi_swallowed.sol | 1 + .../modifiers/definition_in_contract.sol | 3 +++ .../definition_in_contract_unimplemented.sol | 1 + .../modifiers/definition_in_interface.sol | 2 ++ .../modifiers/definition_in_library.sol | 1 + .../definition_in_library_unimplemented.sol | 1 + .../modifiers/empty_modifier_body.sol | 2 ++ .../modifiers/empty_modifier_err.sol | 2 ++ .../modifiers/legal_modifier_override.sol | 1 + .../modifiers/modifier_abstract_override.sol | 2 ++ ...ple_inheritance_unimplemented_override.sol | 2 ++ .../unimplemented_function_and_modifier.sol | 1 + .../unimplemented_override_unimplemented.sol | 3 +++ .../modifiers/use_unimplemented_from_base.sol | 2 ++ .../use_unimplemented_on_overridden_func.sol | 1 + .../modifiers/use_unimplemented_static.sol | 2 ++ ...045_returning_multi_dimensional_arrays.sol | 1 + ...urning_multi_dimensional_static_arrays.sol | 1 + ...048_returning_arrays_in_structs_arrays.sol | 1 + .../346_unused_return_value_send.sol | 1 + .../405_address_checksum_type_deduction.sol | 1 + .../413_address_methods.sol | 2 ++ ...es_not_error_transfer_payable_fallback.sol | 1 + .../535_address_overload_resolution.sol | 1 + .../585_abi_decode_with_unsupported_types.sol | 1 + .../bytecode_too_large_abiencoder_v1.sol | 1 + .../abi_encodePacked_nested_dynamic_array.sol | 1 + .../abi_encode_nested_dynamic_array.sol | 1 + .../specialFunctions/abi_encode_structs.sol | 1 + .../abi_decode_nested_dynamic_array.sol | 1 + .../abidecode/abi_decode_struct.sol | 1 + .../viewPureChecker/builtin_functions.sol | 2 ++ .../builtin_functions_view_fail.sol | 2 ++ .../viewPureChecker/eof/builtin_functions.sol | 2 ++ 178 files changed, 851 insertions(+), 28 deletions(-) create mode 100644 test/cmdlineTests/model_checker_targets_constant_condition_chc/err create mode 100644 test/cmdlineTests/model_checker_targets_out_of_bounds_bmc/err create mode 100644 test/cmdlineTests/model_checker_targets_pop_empty_bmc/err diff --git a/Changelog.md b/Changelog.md index b34e4d4cb..ba3e76659 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,11 @@ Language Features: Compiler Features: * ethdebug: Experimental support for instructions and source locations under EOF. * EVM: Set default EVM Version to `osaka`. +* DocString Parser: Warn about deprecation of inline assembly special comment `memory-safe-assembly`. +* Syntax Checker: Warn about deprecation of ABI coder v1. +* Syntax Checker: Warn about deprecation of virtual modifiers. +* Type Checker: Warn about deprecation of `send` and `transfer` functions on instances of `address`. +* Type Checker: Warn about deprecation of comparisons between variables of contract types. Bugfixes: * Assembler: Fix not using a fixed-width type for IDs being assigned to subassemblies nested more than one level away, resulting in inconsistent `--asm-json` output between target architectures. diff --git a/libsolidity/analysis/DocStringTagParser.cpp b/libsolidity/analysis/DocStringTagParser.cpp index 5d95f42e9..b7fef128d 100644 --- a/libsolidity/analysis/DocStringTagParser.cpp +++ b/libsolidity/analysis/DocStringTagParser.cpp @@ -206,11 +206,18 @@ bool DocStringTagParser::visit(InlineAssembly const& _assembly) m_errorReporter.warning( 8544_error, _assembly.location(), - "Inline assembly marked as memory safe using both a NatSpec tag and an assembly flag. " - "If you are not concerned with backwards compatibility, only use the assembly flag, " + "Inline assembly marked as memory safe using both a NatSpec tag and an assembly block annotation. " + "If you are not concerned with backwards compatibility, only use the assembly block annotation, " "otherwise only use the NatSpec tag." ); _assembly.annotation().markedMemorySafe = true; + m_errorReporter.warning( + 2424_error, + _assembly.location(), + "Natspec memory-safe-assembly special comment for inline assembly is deprecated and " + "scheduled for removal. " + "Use the memory-safe block annotation instead." + ); } else m_errorReporter.warning( diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 1e3f5f1c2..9bf784b36 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -149,6 +149,16 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma) ); else m_sourceUnit->annotation().useABICoderV2 = (_pragma.literals()[1] == "v2"); + + if ( + _pragma.literals().size() > 1 && + _pragma.literals()[1] == "v1" + ) + m_errorReporter.warning( + 9511_error, + _pragma.location(), + "ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead." + ); } else if (_pragma.literals()[0] == "solidity") { @@ -184,6 +194,14 @@ void SyntaxChecker::endVisit(ModifierDefinition const& _modifier) { if (_modifier.isImplemented() && !m_placeholderFound) m_errorReporter.syntaxError(2883_error, _modifier.body().location(), "Modifier body does not contain '_'."); + + if (_modifier.markedVirtual()) + m_errorReporter.warning( + 8429_error, + _modifier.location(), + "Virtual modifiers are deprecated and scheduled for removal." + ); + m_placeholderFound = false; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e56ee157d..9e29983ba 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1829,6 +1829,16 @@ void TypeChecker::endVisit(BinaryOperation const& _operation) ) ); } + if ( + TokenTraits::isCompareOp(_operation.getOperator()) && + commonType->category() == Type::Category::Contract + ) + m_errorReporter.warning( + 9170_error, + _operation.location(), + "Comparison of variables of contract type is deprecated and scheduled for removal. " + "Use an explicit cast to address type and compare the addresses instead." + ); } Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType( @@ -3212,6 +3222,19 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if (contractType && contractType->isSuper()) requiredLookup = VirtualLookup::Super; } + + if ( + funType->kind() == FunctionType::Kind::Send || + funType->kind() == FunctionType::Kind::Transfer + ) + m_errorReporter.warning( + 9207_error, + _memberAccess.location(), + fmt::format( + "'{}' is deprecated and scheduled for removal. Use 'call{{value: }}(\"\")' instead.", + funType->kind() == FunctionType::Kind::Send ? "send" : "transfer" + ) + ); } annotation.requiredLookup = requiredLookup; diff --git a/test/cmdlineTests/model_checker_targets_all_all_engines/err b/test/cmdlineTests/model_checker_targets_all_all_engines/err index e095ba263..3e3871bf1 100644 --- a/test/cmdlineTests/model_checker_targets_all_all_engines/err +++ b/test/cmdlineTests/model_checker_targets_all_all_engines/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Underflow (resulting value less than 0) happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/model_checker_targets_all_bmc/err b/test/cmdlineTests/model_checker_targets_all_bmc/err index 3887cc6b2..025e85f32 100644 --- a/test/cmdlineTests/model_checker_targets_all_bmc/err +++ b/test/cmdlineTests/model_checker_targets_all_bmc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: BMC: Condition is always true. --> input.sol:6:11: | diff --git a/test/cmdlineTests/model_checker_targets_all_chc/err b/test/cmdlineTests/model_checker_targets_all_chc/err index c3853983a..0c04c2f2c 100644 --- a/test/cmdlineTests/model_checker_targets_all_chc/err +++ b/test/cmdlineTests/model_checker_targets_all_chc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Underflow (resulting value less than 0) happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/model_checker_targets_assert_bmc/err b/test/cmdlineTests/model_checker_targets_assert_bmc/err index 27395c9dc..255066b7c 100644 --- a/test/cmdlineTests/model_checker_targets_assert_bmc/err +++ b/test/cmdlineTests/model_checker_targets_assert_bmc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: BMC: Assertion violation happens here. --> input.sol:11:3: | diff --git a/test/cmdlineTests/model_checker_targets_assert_chc/err b/test/cmdlineTests/model_checker_targets_assert_chc/err index ada7c3d3d..096773e68 100644 --- a/test/cmdlineTests/model_checker_targets_assert_chc/err +++ b/test/cmdlineTests/model_checker_targets_assert_chc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Assertion violation happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/model_checker_targets_balance_bmc/err b/test/cmdlineTests/model_checker_targets_balance_bmc/err index 178bd6662..5576730bf 100644 --- a/test/cmdlineTests/model_checker_targets_balance_bmc/err +++ b/test/cmdlineTests/model_checker_targets_balance_bmc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: BMC: Insufficient funds happens here. --> input.sol:10:3: | diff --git a/test/cmdlineTests/model_checker_targets_balance_chc/err b/test/cmdlineTests/model_checker_targets_balance_chc/err index 57bfe4267..c6d3091d1 100644 --- a/test/cmdlineTests/model_checker_targets_balance_chc/err +++ b/test/cmdlineTests/model_checker_targets_balance_chc/err @@ -1 +1,7 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:11:3: + | +11 | a.transfer(x); + | ^^^^^^^^^^ + Info: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/cmdlineTests/model_checker_targets_constant_condition_bmc/err b/test/cmdlineTests/model_checker_targets_constant_condition_bmc/err index a7228dd76..1e73c50a0 100644 --- a/test/cmdlineTests/model_checker_targets_constant_condition_bmc/err +++ b/test/cmdlineTests/model_checker_targets_constant_condition_bmc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: BMC: Condition is always true. --> input.sol:6:11: | diff --git a/test/cmdlineTests/model_checker_targets_constant_condition_chc/err b/test/cmdlineTests/model_checker_targets_constant_condition_chc/err new file mode 100644 index 000000000..4876e9366 --- /dev/null +++ b/test/cmdlineTests/model_checker_targets_constant_condition_chc/err @@ -0,0 +1,5 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:11:3: + | +11 | a.transfer(x); + | ^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_default_all_engines/err b/test/cmdlineTests/model_checker_targets_default_all_engines/err index 58cbc01f1..763f8f16c 100644 --- a/test/cmdlineTests/model_checker_targets_default_all_engines/err +++ b/test/cmdlineTests/model_checker_targets_default_all_engines/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Division by zero happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/model_checker_targets_default_bmc/err b/test/cmdlineTests/model_checker_targets_default_bmc/err index bc85e3cb4..d7499c998 100644 --- a/test/cmdlineTests/model_checker_targets_default_bmc/err +++ b/test/cmdlineTests/model_checker_targets_default_bmc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: BMC: Condition is always true. --> input.sol:6:11: | diff --git a/test/cmdlineTests/model_checker_targets_default_chc/err b/test/cmdlineTests/model_checker_targets_default_chc/err index e8b738216..d4a342ac0 100644 --- a/test/cmdlineTests/model_checker_targets_default_chc/err +++ b/test/cmdlineTests/model_checker_targets_default_chc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Division by zero happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/model_checker_targets_div_by_zero_bmc/err b/test/cmdlineTests/model_checker_targets_div_by_zero_bmc/err index 2d554ebce..ee8c7cc37 100644 --- a/test/cmdlineTests/model_checker_targets_div_by_zero_bmc/err +++ b/test/cmdlineTests/model_checker_targets_div_by_zero_bmc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: BMC: Division by zero happens here. --> input.sol:9:3: | diff --git a/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err b/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err index 81616b3be..3e0027248 100644 --- a/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err +++ b/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Division by zero happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/model_checker_targets_out_of_bounds_bmc/err b/test/cmdlineTests/model_checker_targets_out_of_bounds_bmc/err new file mode 100644 index 000000000..4876e9366 --- /dev/null +++ b/test/cmdlineTests/model_checker_targets_out_of_bounds_bmc/err @@ -0,0 +1,5 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:11:3: + | +11 | a.transfer(x); + | ^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err b/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err index 907a19f1e..9026ef934 100644 --- a/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err +++ b/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Out of bounds access happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/model_checker_targets_overflow_bmc/err b/test/cmdlineTests/model_checker_targets_overflow_bmc/err index a0f9ff1e0..81dd72c23 100644 --- a/test/cmdlineTests/model_checker_targets_overflow_bmc/err +++ b/test/cmdlineTests/model_checker_targets_overflow_bmc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: BMC: Overflow (resulting value larger than 2**256 - 1) happens here. --> input.sol:8:3: | diff --git a/test/cmdlineTests/model_checker_targets_overflow_chc/err b/test/cmdlineTests/model_checker_targets_overflow_chc/err index 60298f022..178b59a44 100644 --- a/test/cmdlineTests/model_checker_targets_overflow_chc/err +++ b/test/cmdlineTests/model_checker_targets_overflow_chc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Overflow (resulting value larger than 2**256 - 1) happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/model_checker_targets_pop_empty_bmc/err b/test/cmdlineTests/model_checker_targets_pop_empty_bmc/err new file mode 100644 index 000000000..4876e9366 --- /dev/null +++ b/test/cmdlineTests/model_checker_targets_pop_empty_bmc/err @@ -0,0 +1,5 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:11:3: + | +11 | a.transfer(x); + | ^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_pop_empty_chc/err b/test/cmdlineTests/model_checker_targets_pop_empty_chc/err index a01248775..e4c1bbc0e 100644 --- a/test/cmdlineTests/model_checker_targets_pop_empty_chc/err +++ b/test/cmdlineTests/model_checker_targets_pop_empty_chc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Empty array "pop" happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/model_checker_targets_underflow_bmc/err b/test/cmdlineTests/model_checker_targets_underflow_bmc/err index db1463923..e4b29a98c 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_bmc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_bmc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: BMC: Underflow (resulting value less than 0) happens here. --> input.sol:7:3: | diff --git a/test/cmdlineTests/model_checker_targets_underflow_chc/err b/test/cmdlineTests/model_checker_targets_underflow_chc/err index 57c6649a4..f9fbf82ee 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_chc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_chc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Underflow (resulting value less than 0) happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_bmc/err b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_bmc/err index 670b064ce..72a947456 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_bmc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_bmc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: BMC: Underflow (resulting value less than 0) happens here. --> input.sol:7:3: | diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err index 4602e7600..f91c06702 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Underflow (resulting value less than 0) happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_bmc/err b/test/cmdlineTests/model_checker_targets_underflow_overflow_bmc/err index ea6dfb99c..e6d8c061a 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_bmc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_bmc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: BMC: Underflow (resulting value less than 0) happens here. --> input.sol:7:3: | diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err b/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err index 8eed85ac3..44faa5ae8 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err @@ -1,3 +1,9 @@ +Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. + --> input.sol:10:3: + | +10 | a.transfer(x); + | ^^^^^^^^^^ + Warning: CHC: Underflow (resulting value less than 0) happens here. Counterexample: arr = [] diff --git a/test/cmdlineTests/standard_model_checker_targets_assert_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_assert_bmc/output.json index 9e90ec538..5cbb28b97 100644 --- a/test/cmdlineTests/standard_model_checker_targets_assert_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_assert_bmc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "4661", diff --git a/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json index bf4fa6626..d7cfd4a82 100644 --- a/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "6328", diff --git a/test/cmdlineTests/standard_model_checker_targets_balance_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_balance_bmc/output.json index 6c2c90c98..faeb47498 100644 --- a/test/cmdlineTests/standard_model_checker_targets_balance_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_balance_bmc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "1236", diff --git a/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json index 9d3e40b70..a323ac1ed 100644 --- a/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_balance_chc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "1391", diff --git a/test/cmdlineTests/standard_model_checker_targets_constantCondition_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_constantCondition_bmc/output.json index 9bfdf0b02..74897928f 100644 --- a/test/cmdlineTests/standard_model_checker_targets_constantCondition_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_constantCondition_bmc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "6838", diff --git a/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json index f047ff70a..d6a7b5a4e 100644 --- a/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json @@ -1,4 +1,25 @@ { + "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + } + ], "sources": { "A": { "id": 0 diff --git a/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json b/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json index 8f20d854b..964bcd6c6 100644 --- a/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_default_all_engines/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "4281", diff --git a/test/cmdlineTests/standard_model_checker_targets_default_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_default_bmc/output.json index e055d38d2..00e90a5c3 100644 --- a/test/cmdlineTests/standard_model_checker_targets_default_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_default_bmc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "6838", diff --git a/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json index e045a8bff..5f1f5a9c5 100644 --- a/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_default_chc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "4281", diff --git a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_bmc/output.json index 6ba0e6f82..ccca7af6b 100644 --- a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_bmc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "3046", diff --git a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json index 0789c7999..e5a54e4c8 100644 --- a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "4281", diff --git a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_bmc/output.json index f047ff70a..d6a7b5a4e 100644 --- a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_bmc/output.json @@ -1,4 +1,25 @@ { + "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + } + ], "sources": { "A": { "id": 0 diff --git a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json index f5f49fb50..ecb01eac3 100644 --- a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "6368", diff --git a/test/cmdlineTests/standard_model_checker_targets_overflow_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_overflow_bmc/output.json index 8d34765cd..5dbe011f1 100644 --- a/test/cmdlineTests/standard_model_checker_targets_overflow_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_overflow_bmc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "2661", diff --git a/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json index 9beb30a35..1b0078d57 100644 --- a/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "4984", diff --git a/test/cmdlineTests/standard_model_checker_targets_pop_empty_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_pop_empty_bmc/output.json index f047ff70a..d6a7b5a4e 100644 --- a/test/cmdlineTests/standard_model_checker_targets_pop_empty_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_pop_empty_bmc/output.json @@ -1,4 +1,25 @@ { + "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + } + ], "sources": { "A": { "id": 0 diff --git a/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json index 4cccf8456..6ac6acd96 100644 --- a/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "2529", diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_bmc/output.json index df17886b2..448c4285f 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_bmc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "4144", diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json index 442f2f47a..67218582b 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "3944", diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_bmc/output.json index c80d3e22a..ce83f3f28 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_bmc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "4144", diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json index e5719640a..8f28e7961 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "3944", diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_bmc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_bmc/output.json index de02d57c9..2162e723f 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_bmc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_bmc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "4144", diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json index 6fb8762e4..97442455c 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json @@ -1,5 +1,24 @@ { "errors": [ + { + "component": "general", + "errorCode": "9207", + "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. + --> A:11:7: + | +11 | \t\t\t\t\t\ta.transfer(x); + | \t\t\t\t\t\t^^^^^^^^^^ + +", + "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", + "severity": "warning", + "sourceLocation": { + "end": 234, + "file": "A", + "start": 224 + }, + "type": "Warning" + }, { "component": "general", "errorCode": "3944", diff --git a/test/cmdlineTests/viair_abicoder_v1/err b/test/cmdlineTests/viair_abicoder_v1/err index 29fa2acd0..ca7671fe3 100644 --- a/test/cmdlineTests/viair_abicoder_v1/err +++ b/test/cmdlineTests/viair_abicoder_v1/err @@ -1,3 +1,9 @@ +Warning (9511): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. + --> input.sol:3:1: + | +3 | pragma abicoder v1; + | ^^^^^^^^^^^^^^^^^^^ + Warning (2066): Contract requests the ABI coder v1, which is incompatible with the IR. Using ABI coder v2 instead. --> input.sol:4:1: | diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol index 720ab5695..01c0a1900 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend.sol @@ -18,5 +18,6 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- +// Warning 9207: (175-186): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Warning 6328: (280-314): CHC: Assertion violation happens here. // Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol index 3ceac964f..94c793df0 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/balance_spend_2.sol @@ -17,6 +17,7 @@ contract C { // SMTIgnoreCex: yes // SMTIgnoreOS: macos // ---- +// Warning 9207: (141-152): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Warning 8656: (141-156): CHC: Insufficient funds happens here. // Warning 6328: (193-226): CHC: Assertion violation happens here. // Warning 6328: (245-279): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/decreasing_balance.sol b/test/libsolidity/smtCheckerTests/blockchain_state/decreasing_balance.sol index df35a2785..75a02b7b5 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/decreasing_balance.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/decreasing_balance.sol @@ -18,4 +18,5 @@ contract C { // ==== // SMTEngine: all // ---- +// Warning 9207: (160-170): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/free_function_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/free_function_2.sol index 3b7c0f9dc..64900cbcb 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/free_function_2.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/free_function_2.sol @@ -19,5 +19,6 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 6328: (258-274): CHC: Assertion violation happens here. +// Warning 9207: (33-43): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 6328: (258-274): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\na = 0x7e1e\nb1 = 38\nb2 = 37\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.f(0x7e1e){ msg.value: 17 }\n l(0x7e1e) -- internal call // Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/library_internal_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/library_internal_2.sol index 826af0bf8..d6203e381 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/library_internal_2.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/library_internal_2.sol @@ -22,5 +22,6 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 6328: (315-331): CHC: Assertion violation happens here. +// Warning 9207: (87-97): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 6328: (315-331): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\na = 0x7e1e\nb1 = 38\nb2 = 37\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.f(0x7e1e){ msg.value: 17 }\n L.l(0x7e1e) -- internal call // Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/library_public_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/library_public_2.sol index 02e29be8d..4689dceba 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/library_public_2.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/library_public_2.sol @@ -20,7 +20,8 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- +// Warning 9207: (54-64): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Warning 4588: (238-243): Assertion checker does not yet implement this type of function call. -// Warning 8656: (54-67): CHC: Insufficient funds happens here. -// Warning 6328: (282-298): CHC: Assertion violation happens here. -// Warning 6328: (317-331): CHC: Assertion violation happens here. +// Warning 8656: (54-67): CHC: Insufficient funds happens here.\nCounterexample:\n\na = 0x0\n\nTransaction trace:\nL.constructor()\nL.l(0x0) +// Warning 6328: (282-298): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\na = 0x0\nb1 = 15923\nb2 = 15924\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.f(0x0){ msg.value: 15923 } +// Warning 6328: (317-331): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\na = 0x0\nb1 = 15923\nb2 = 15924\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.f(0x0){ msg.value: 15923 } diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_1.sol b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_1.sol index 169257edf..086eb2549 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_1.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_1.sol @@ -11,5 +11,6 @@ contract C { // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 6328: (166-201): CHC: Assertion violation happens here. +// Warning 9207: (96-106): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 6328: (166-201): CHC: Assertion violation happens here.\nCounterexample:\n\na = 0x0\n\nTransaction trace:\nC.constructor()\nC.f(0x0) // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_2.sol b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_2.sol index ed5b4c90f..033163516 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_2.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_2.sol @@ -11,4 +11,6 @@ contract C { // ==== // SMTEngine: chc // ---- +// Warning 9207: (133-151): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 9207: (167-185): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_3.sol b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_3.sol index 4b3318b6b..d4f3eec99 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_3.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_3.sol @@ -8,4 +8,5 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 8656: (76-97): CHC: Insufficient funds happens here. +// Warning 9207: (76-94): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 8656: (76-97): CHC: Insufficient funds happens here.\nCounterexample:\nrecipient = 0x0\n\nTransaction trace:\nC.constructor()\nState: recipient = 0x0\nC.shouldFail() diff --git a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_4.sol b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_4.sol index ab0c4a81e..838154ec3 100644 --- a/test/libsolidity/smtCheckerTests/blockchain_state/transfer_4.sol +++ b/test/libsolidity/smtCheckerTests/blockchain_state/transfer_4.sol @@ -9,4 +9,5 @@ contract C { // ==== // SMTEngine: all // ---- +// Warning 9207: (101-119): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/bmc_coverage/funds.sol b/test/libsolidity/smtCheckerTests/bmc_coverage/funds.sol index 737443e64..a8f90f161 100644 --- a/test/libsolidity/smtCheckerTests/bmc_coverage/funds.sol +++ b/test/libsolidity/smtCheckerTests/bmc_coverage/funds.sol @@ -6,4 +6,5 @@ contract C { // ==== // SMTEngine: bmc // ---- +// Warning 9207: (55-65): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Warning 1236: (55-70): BMC: Insufficient funds happens here. diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_addresses.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_addresses.sol index 01c68790c..b0b159f47 100644 --- a/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_addresses.sol +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_trusted_addresses.sol @@ -16,4 +16,5 @@ contract C { // SMTEngine: all // SMTExtCalls: trusted // ---- +// Warning 9170: (107-115): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. // Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_addresses.sol b/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_addresses.sol index c934e152b..4de7eaa49 100644 --- a/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_addresses.sol +++ b/test/libsolidity/smtCheckerTests/deployment/deploy_untrusted_addresses.sol @@ -15,8 +15,9 @@ contract C { // ==== // SMTEngine: all // ---- +// Warning 9170: (107-115): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. // Warning 8729: (70-77): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. // Warning 8729: (88-95): Contract deployment is only supported in the trusted mode for external calls with the CHC engine. // Warning 6328: (100-116): CHC: Assertion violation happens here.\nCounterexample:\n\nd1 = 0\nd2 = 0\n\nTransaction trace:\nC.constructor()\nC.f() -// Warning 6328: (163-199): CHC: Assertion violation happens here.\nCounterexample:\n\nd1 = 21238\nd2 = 21238\n\nTransaction trace:\nC.constructor()\nC.f() -// Warning 6328: (246-282): CHC: Assertion violation happens here.\nCounterexample:\n\nd1 = 21238\nd2 = 21238\n\nTransaction trace:\nC.constructor()\nC.f() +// Warning 6328: (163-199): CHC: Assertion violation happens here.\nCounterexample:\n\nd1 = 11797\nd2 = 11797\n\nTransaction trace:\nC.constructor()\nC.f() +// Warning 6328: (246-282): CHC: Assertion violation happens here.\nCounterexample:\n\nd1 = 8855\nd2 = 8855\n\nTransaction trace:\nC.constructor()\nC.f() diff --git a/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_1.sol b/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_1.sol index 209b00f5f..73f1e4aee 100644 --- a/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_1.sol +++ b/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_1.sol @@ -15,4 +15,5 @@ contract D { // ==== // SMTEngine: all // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_2.sol b/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_2.sol index b62611b51..52389a4f7 100644 --- a/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_2.sol +++ b/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_2.sol @@ -20,5 +20,6 @@ contract D { // SMTEngine: all // SMTIgnoreCex: no // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // Warning 6328: (267-281): CHC: Assertion violation happens here.\nCounterexample:\nitems = [{x: 42, y: 43}]\na = 42\nb = 43\n\nTransaction trace:\nD.constructor()\nState: items = []\nD.test() // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_3.sol b/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_3.sol index abe50e8a5..2fee43bfb 100644 --- a/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_3.sol +++ b/test/libsolidity/smtCheckerTests/functions/getters/array_of_structs_3.sol @@ -21,5 +21,6 @@ contract D { // ==== // SMTEngine: all // ---- -// Warning 6328: (322-336): CHC: Assertion violation happens here. +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. +// Warning 6328: (322-336): CHC: Assertion violation happens here.\nCounterexample:\nitems = [{x: 42, y: 43, arr: [0]}]\ntmp = [0]\na = 42\nb = 43\n\nTransaction trace:\nD.constructor()\nState: items = []\nD.test() // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/functions/getters/contract.sol b/test/libsolidity/smtCheckerTests/functions/getters/contract.sol index 7da893bd3..ba95fcee1 100644 --- a/test/libsolidity/smtCheckerTests/functions/getters/contract.sol +++ b/test/libsolidity/smtCheckerTests/functions/getters/contract.sol @@ -12,5 +12,6 @@ contract C { // ==== // SMTEngine: all // ---- -// Warning 6328: (123-158): CHC: Assertion violation happens here. +// Warning 9170: (97-103): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. +// Warning 6328: (123-158): CHC: Assertion violation happens here.\nCounterexample:\nd = 0\ne = 0\n\nTransaction trace:\nC.constructor()\nState: d = 0\nC.f() // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/functions/getters/struct_4.sol b/test/libsolidity/smtCheckerTests/functions/getters/struct_4.sol index 345959354..928580207 100644 --- a/test/libsolidity/smtCheckerTests/functions/getters/struct_4.sol +++ b/test/libsolidity/smtCheckerTests/functions/getters/struct_4.sol @@ -18,7 +18,8 @@ contract C { // ==== // SMTEngine: all // ---- +// Warning 9170: (206-214): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. // Warning 2072: (146-183): Unused local variable. // Warning 8364: (187-193): Assertion checker does not yet implement type function () view external returns (contract D,function () external returns (uint256)) -// Warning 6328: (234-269): CHC: Assertion violation happens here. +// Warning 6328: (234-269): CHC: Assertion violation happens here.\nCounterexample:\ns = {d: 0, f: 0}\nd = 0\nf = 0\n\nTransaction trace:\nC.constructor()\nState: s = {d: 0, f: 0}\nC.test() // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/modifiers/modifier_abstract.sol b/test/libsolidity/smtCheckerTests/modifiers/modifier_abstract.sol index 9d541b629..3ed457a0c 100644 --- a/test/libsolidity/smtCheckerTests/modifiers/modifier_abstract.sol +++ b/test/libsolidity/smtCheckerTests/modifiers/modifier_abstract.sol @@ -5,3 +5,4 @@ abstract contract A { // ==== // SMTEngine: all // ---- +// Warning 8429: (51-72): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_1.sol b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_1.sol index 9165ed133..9c1a59df9 100644 --- a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_1.sol +++ b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_1.sol @@ -20,5 +20,6 @@ contract B is A { // ==== // SMTEngine: all // ---- -// Warning 6328: (209-223): CHC: Assertion violation happens here. +// Warning 8429: (64-93): Virtual modifiers are deprecated and scheduled for removal. +// Warning 6328: (209-223): CHC: Assertion violation happens here.\nCounterexample:\ns = 42\nx = 42\n\nTransaction trace:\nB.constructor()\nState: s = 0\nB.set(42)\nState: s = 42\nA.f() // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_2.sol b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_2.sol index fd9dc9008..28df58db2 100644 --- a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_2.sol +++ b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_2.sol @@ -23,4 +23,6 @@ contract C is B { // ==== // SMTEngine: all // ---- +// Warning 8429: (113-136): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (159-213): Virtual modifiers are deprecated and scheduled for removal. // Warning 6328: (66-75): CHC: Assertion violation happens here.\nCounterexample:\ns = false\n\nTransaction trace:\nB.constructor()\nState: s = false\nA.f() diff --git a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_3.sol b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_3.sol index f85e1b3ba..a213caee1 100644 --- a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_3.sol +++ b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_3.sol @@ -18,5 +18,7 @@ contract B is A { // ==== // SMTEngine: all // ---- -// Warning 6328: (94-104): CHC: Assertion violation happens here. +// Warning 8429: (125-148): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (171-238): Virtual modifiers are deprecated and scheduled for removal. +// Warning 6328: (94-104): CHC: Assertion violation happens here.\nCounterexample:\ns = true\nx = true\n\nTransaction trace:\nB.constructor()\nState: s = false\nA.f() // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol index d0e82665c..87e5517ee 100644 --- a/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol +++ b/test/libsolidity/smtCheckerTests/modifiers/modifier_overriding_4.sol @@ -36,6 +36,10 @@ contract D is B,C { // ==== // SMTEngine: all // ---- +// Warning 8429: (262-294): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (317-367): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (390-440): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (465-520): Virtual modifiers are deprecated and scheduled for removal. // Warning 6328: (160-174): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\nTransaction trace:\nB.constructor()\nState: x = 0\nA.f() // Warning 6328: (193-207): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\nTransaction trace:\nC.constructor()\nState: x = 0\nA.f() // Warning 6328: (226-240): CHC: Assertion violation happens here.\nCounterexample:\nx = 3\n\nTransaction trace:\nD.constructor()\nState: x = 0\nA.f() diff --git a/test/libsolidity/smtCheckerTests/modifiers/modifier_virtual_static_call_1.sol b/test/libsolidity/smtCheckerTests/modifiers/modifier_virtual_static_call_1.sol index 40bc6d93e..998337d04 100644 --- a/test/libsolidity/smtCheckerTests/modifiers/modifier_virtual_static_call_1.sol +++ b/test/libsolidity/smtCheckerTests/modifiers/modifier_virtual_static_call_1.sol @@ -10,3 +10,4 @@ contract C is A { // ==== // SMTEngine: all // ---- +// Warning 8429: (17-52): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/smtCheckerTests/modifiers/modifier_virtual_static_call_2.sol b/test/libsolidity/smtCheckerTests/modifiers/modifier_virtual_static_call_2.sol index b270fb2bb..0d32bcd64 100644 --- a/test/libsolidity/smtCheckerTests/modifiers/modifier_virtual_static_call_2.sol +++ b/test/libsolidity/smtCheckerTests/modifiers/modifier_virtual_static_call_2.sol @@ -20,5 +20,6 @@ contract C is A { // ==== // SMTEngine: all // ---- -// Warning 6328: (83-98): CHC: Assertion violation happens here. +// Warning 8429: (27-122): Virtual modifiers are deprecated and scheduled for removal. +// Warning 6328: (83-98): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n = 0\n\nTransaction trace:\nC.constructor()\nState: x = 0\nC.f() // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/address_transfer.sol b/test/libsolidity/smtCheckerTests/types/address_transfer.sol index 1430e15cb..734a70c80 100644 --- a/test/libsolidity/smtCheckerTests/types/address_transfer.sol +++ b/test/libsolidity/smtCheckerTests/types/address_transfer.sol @@ -11,5 +11,6 @@ contract C // ==== // SMTEngine: all // ---- -// Warning 8656: (98-113): CHC: Insufficient funds happens here. -// Warning 6328: (162-186): CHC: Assertion violation happens here. +// Warning 9207: (98-108): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 8656: (98-113): CHC: Insufficient funds happens here.\nCounterexample:\n\na = 0x51f0\nx = 100\n\nTransaction trace:\nC.constructor()\nC.f(0x51f0) +// Warning 6328: (162-186): CHC: Assertion violation happens here.\nCounterexample:\n\na = 0x0\nx = 100\n\nTransaction trace:\nC.constructor()\nC.f(0x0) diff --git a/test/libsolidity/smtCheckerTests/types/address_transfer_2.sol b/test/libsolidity/smtCheckerTests/types/address_transfer_2.sol index ce6492d9e..0d558b85a 100644 --- a/test/libsolidity/smtCheckerTests/types/address_transfer_2.sol +++ b/test/libsolidity/smtCheckerTests/types/address_transfer_2.sol @@ -15,6 +15,8 @@ contract C // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 8656: (184-199): CHC: Insufficient funds happens here. -// Warning 8656: (203-218): CHC: Insufficient funds happens here. -// Warning 6328: (262-291): CHC: Assertion violation happens here. +// Warning 9207: (184-194): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 9207: (203-213): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 8656: (184-199): CHC: Insufficient funds happens here.\nCounterexample:\n\nx = 100\na = 0x6532\nb = 0xffffffffffffffffffffffffffffffffffffed9d\n\nTransaction trace:\nC.constructor()\nC.f(100, 0x6532, 0xffffffffffffffffffffffffffffffffffffed9d) +// Warning 8656: (203-218): CHC: Insufficient funds happens here.\nCounterexample:\n\nx = 100\na = 0x08c0\nb = 0x7992\n\nTransaction trace:\nC.constructor()\nC.f(100, 0x08c0, 0x7992) +// Warning 6328: (262-291): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 100\na = 0x08c1\nb = 0x08c0\n\nTransaction trace:\nC.constructor()\nC.f(100, 0x08c1, 0x08c0) diff --git a/test/libsolidity/smtCheckerTests/types/address_transfer_3.sol b/test/libsolidity/smtCheckerTests/types/address_transfer_3.sol index 3f9cc22c7..5d0de5021 100644 --- a/test/libsolidity/smtCheckerTests/types/address_transfer_3.sol +++ b/test/libsolidity/smtCheckerTests/types/address_transfer_3.sol @@ -13,4 +13,5 @@ contract C // ==== // SMTEngine: all // ---- +// Warning 9207: (126-136): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/address_transfer_insufficient.sol b/test/libsolidity/smtCheckerTests/types/address_transfer_insufficient.sol index 55a96026e..5a9f88aae 100644 --- a/test/libsolidity/smtCheckerTests/types/address_transfer_insufficient.sol +++ b/test/libsolidity/smtCheckerTests/types/address_transfer_insufficient.sol @@ -12,6 +12,8 @@ contract C // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 8656: (101-116): CHC: Insufficient funds happens here. -// Warning 8656: (120-136): CHC: Insufficient funds happens here. -// Warning 6328: (180-204): CHC: Assertion violation happens here. +// Warning 9207: (101-111): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 9207: (120-130): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 8656: (101-116): CHC: Insufficient funds happens here.\nCounterexample:\n\na = 0x0\nb = 0x0\n\nTransaction trace:\nC.constructor()\nC.f(0x0, 0x0) +// Warning 8656: (120-136): CHC: Insufficient funds happens here.\nCounterexample:\n\na = 0x0\nb = 0x0\n\nTransaction trace:\nC.constructor()\nC.f(0x0, 0x0) +// Warning 6328: (180-204): CHC: Assertion violation happens here.\nCounterexample:\n\na = 0x0476\nb = 0x0476\n\nTransaction trace:\nC.constructor()\nC.f(0x0476, 0x0476) diff --git a/test/libsolidity/smtCheckerTests/types/contract.sol b/test/libsolidity/smtCheckerTests/types/contract.sol index 0ddc3e650..a631fe1c8 100644 --- a/test/libsolidity/smtCheckerTests/types/contract.sol +++ b/test/libsolidity/smtCheckerTests/types/contract.sol @@ -8,4 +8,5 @@ contract C // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 6328: (51-65): CHC: Assertion violation happens here. +// Warning 9170: (58-64): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. +// Warning 6328: (51-65): CHC: Assertion violation happens here.\nCounterexample:\n\nc = 0\nd = 1\n\nTransaction trace:\nC.constructor()\nC.f(0, 1) diff --git a/test/libsolidity/smtCheckerTests/types/contract_2.sol b/test/libsolidity/smtCheckerTests/types/contract_2.sol index 2357852d5..262c157b5 100644 --- a/test/libsolidity/smtCheckerTests/types/contract_2.sol +++ b/test/libsolidity/smtCheckerTests/types/contract_2.sol @@ -13,4 +13,5 @@ contract C // SMTEngine: all // SMTIgnoreCex: yes // ---- -// Warning 6328: (76-90): CHC: Assertion violation happens here. +// Warning 9170: (83-89): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. +// Warning 6328: (76-90): CHC: Assertion violation happens here.\nCounterexample:\n\nc = 0\nd = 1\n\nTransaction trace:\nC.constructor()\nC.f(0, 1) diff --git a/test/libsolidity/smtCheckerTests/types/contract_3.sol b/test/libsolidity/smtCheckerTests/types/contract_3.sol index 657999c0b..0ddf195ba 100644 --- a/test/libsolidity/smtCheckerTests/types/contract_3.sol +++ b/test/libsolidity/smtCheckerTests/types/contract_3.sol @@ -9,4 +9,7 @@ contract C // ==== // SMTEngine: all // ---- +// Warning 9170: (64-70): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. +// Warning 9170: (83-89): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. +// Warning 9170: (101-107): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/types/contract_address_conversion_2.sol b/test/libsolidity/smtCheckerTests/types/contract_address_conversion_2.sol index 0b395c187..f79878993 100644 --- a/test/libsolidity/smtCheckerTests/types/contract_address_conversion_2.sol +++ b/test/libsolidity/smtCheckerTests/types/contract_address_conversion_2.sol @@ -10,4 +10,5 @@ contract C // ==== // SMTEngine: all // ---- +// Warning 9170: (121-127): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings.sol b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings.sol index da81a3bc6..f7e41bd61 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings.sol @@ -2,3 +2,4 @@ pragma abicoder v2; pragma abicoder v1; // ---- // SyntaxError 3845: (34-53): ABI coder has already been selected for this source unit. +// Warning 9511: (34-53): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol index f06b2458c..feacbbeb3 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol @@ -1,4 +1,5 @@ pragma abicoder v1; pragma abicoder v2; // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // SyntaxError 3845: (20-39): ABI coder has already been selected for this source unit. diff --git a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol index 855378e9e..884d03132 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol @@ -1,4 +1,5 @@ pragma abicoder v1; pragma experimental ABIEncoderV2; // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // SyntaxError 8273: (20-53): ABI coder v1 has already been selected through "pragma abicoder v1". diff --git a/test/libsolidity/syntaxTests/abiEncoder/select_v1.sol b/test/libsolidity/syntaxTests/abiEncoder/select_v1.sol index 1beb5f0ec..ab430610c 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/select_v1.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/select_v1.sol @@ -1,2 +1,3 @@ pragma abicoder v1; // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/select_v1_quoted_string.sol b/test/libsolidity/syntaxTests/abiEncoder/select_v1_quoted_string.sol index a6c26efdc..b8083cd35 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/select_v1_quoted_string.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/select_v1_quoted_string.sol @@ -1,2 +1,3 @@ pragma abicoder "v1"; // ---- +// Warning 9511: (0-21): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/selected_twice.sol b/test/libsolidity/syntaxTests/abiEncoder/selected_twice.sol index 424c2c7f2..172ee0b57 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/selected_twice.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/selected_twice.sol @@ -1,4 +1,6 @@ pragma abicoder v1; pragma abicoder v1; // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // SyntaxError 3845: (20-39): ABI coder has already been selected for this source unit. +// Warning 9511: (20-39): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol index 036a25976..f6bc52a1e 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v1_type.sol @@ -16,3 +16,4 @@ contract D { // ==== // bytecodeFormat: legacy // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v2_type.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v2_type.sol index feaf895e1..7a5fbc571 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v2_type.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_accessing_public_state_variable_via_v2_type.sol @@ -14,5 +14,6 @@ contract D { } } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 7364: (222-260): Different number of components on the left hand side (1) than on the right hand side (2). // TypeError 9574: (222-260): Type uint256 is not implicitly convertible to expected type struct Item memory. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol index 03fb9bae6..61763429b 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol @@ -22,3 +22,4 @@ contract Test { // ==== // bytecodeFormat: legacy // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_constructor_accepting_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_constructor_accepting_struct.sol index 3ee6f75a1..d114c7192 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_constructor_accepting_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_constructor_accepting_struct.sol @@ -18,4 +18,5 @@ contract Test { } } // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2443: (B:91-100): The type of this parameter, struct C.Item memory, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_accepting_struct_via_named_argument.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_accepting_struct_via_named_argument.sol index c02faba18..078e977e9 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_accepting_struct_via_named_argument.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_accepting_struct_via_named_argument.sol @@ -18,4 +18,5 @@ contract Test { } } // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2443: (B:119-129): The type of this parameter, struct C.Item memory, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_pointer_accepting_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_pointer_accepting_struct.sol index 674ce4e32..8c67e6088 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_pointer_accepting_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_pointer_accepting_struct.sol @@ -20,4 +20,5 @@ contract Test { } } // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2443: (B:166-175): The type of this parameter, struct C.Item memory, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_dynamic_string_array.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_dynamic_string_array.sol index 5379bdb50..1f7c8d754 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_dynamic_string_array.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_dynamic_string_array.sol @@ -14,4 +14,5 @@ contract D { } } // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2428: (B:85-105): The type of return parameter 1, string[] memory, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct.sol index d2b0e1ffe..c5dbe401b 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct.sol @@ -18,4 +18,5 @@ contract Test { } } // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2428: (B:90-112): The type of return parameter 1, struct C.Item memory, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct_with_dynamic_array.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct_with_dynamic_array.sol index 0aa9973aa..6117b79cc 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct_with_dynamic_array.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct_with_dynamic_array.sol @@ -18,4 +18,5 @@ contract Test { } } // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2428: (B:90-112): The type of return parameter 1, struct C.Item memory, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_event_accepting_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_event_accepting_struct.sol index e86841868..e78a5a193 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_event_accepting_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_event_accepting_struct.sol @@ -17,4 +17,5 @@ contract Test { } } // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2443: (B:94-104): The type of this parameter, struct L.Item memory, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_attached_function_returning_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_attached_function_returning_struct.sol index bb3651d4f..bb394cc7a 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_attached_function_returning_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_attached_function_returning_struct.sol @@ -20,4 +20,5 @@ contract D { } } // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2428: (B:106-117): The type of return parameter 1, struct L.Item memory, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol index 01d9658ce..0a6c80b7c 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol @@ -22,3 +22,4 @@ contract Test { // ==== // bytecodeFormat: legacy // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_returning_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_returning_struct.sol index c6ba75225..4a32c474a 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_returning_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_returning_struct.sol @@ -18,4 +18,5 @@ contract Test { } } // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2428: (B:90-97): The type of return parameter 1, struct L.Item memory, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol index ef066593c..63b082834 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_modifier.sol @@ -28,3 +28,4 @@ contract C is B { // ==== // bytecodeFormat: legacy // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol index b937d1e2d..84a58a812 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_constructor_with_v2_modifier.sol @@ -35,3 +35,5 @@ contract D is C { // ==== // bytecodeFormat: legacy // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. +// Warning 9511: (C:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol index 9743d5318..bae6d83c8 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_calling_v2_function.sol @@ -26,3 +26,4 @@ contract C is B {} // ==== // bytecodeFormat: legacy // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol index e4492a4ef..accaa7d6b 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_event.sol @@ -16,3 +16,4 @@ contract D is C {} // ==== // bytecodeFormat: legacy // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_function_accepting_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_function_accepting_struct.sol index c37bad41c..977303681 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_function_accepting_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_function_accepting_struct.sol @@ -14,4 +14,5 @@ import "A"; contract D is C {} // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 6594: (B:33-51): Contract "D" does not use ABI coder v2 but wants to inherit from a contract which uses types that require it. Use "pragma abicoder v2;" for the inheriting contract as well to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_function_returning_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_function_returning_struct.sol index f25754246..2a3e41a40 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_function_returning_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_defining_v2_function_returning_struct.sol @@ -14,4 +14,5 @@ import "A"; contract D is C {} // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 6594: (B:33-51): Contract "D" does not use ABI coder v2 but wants to inherit from a contract which uses types that require it. Use "pragma abicoder v2;" for the inheriting contract as well to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol index 5ae4cb0ed..791163be5 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_inheritance_from_contract_emitting_v2_event.sol @@ -22,3 +22,4 @@ contract D is C {} // ==== // bytecodeFormat: legacy // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol index 9a809b50a..bae4a1b1d 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_modifier_overriding_v2_modifier.sol @@ -30,3 +30,5 @@ contract C is B { // ==== // bytecodeFormat: legacy // ---- +// Warning 8429: (A:156-234): Virtual modifiers are deprecated and scheduled for removal. +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol index 6665c42ef..75e3ae94c 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_v2_v1_modifier_mix.sol @@ -55,3 +55,6 @@ contract X { // ==== // bytecodeFormat: legacy // ---- +// Warning 9511: (V1A:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. +// Warning 9511: (V1B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. +// Warning 9511: (C:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v2_v1_v1_modifier_sandwich.sol b/test/libsolidity/syntaxTests/abiEncoder/v2_v1_v1_modifier_sandwich.sol index 45fed616c..9946c538c 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v2_v1_v1_modifier_sandwich.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v2_v1_v1_modifier_sandwich.sol @@ -29,4 +29,6 @@ contract C is B { {} } // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. +// Warning 9511: (C:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2428: (B:80-102): The type of return parameter 1, struct Data memory, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v2_v1_v2_modifier_sandwich.sol b/test/libsolidity/syntaxTests/abiEncoder/v2_v1_v2_modifier_sandwich.sol index 5bc10f53e..980a93248 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v2_v1_v2_modifier_sandwich.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v2_v1_v2_modifier_sandwich.sol @@ -30,4 +30,5 @@ contract C is B { {} } // ---- +// Warning 9511: (B:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2428: (B:80-102): The type of return parameter 1, struct Data memory, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/array/calldata_multi_dynamic_V1.sol b/test/libsolidity/syntaxTests/array/calldata_multi_dynamic_V1.sol index 754270ecf..54fbda567 100644 --- a/test/libsolidity/syntaxTests/array/calldata_multi_dynamic_V1.sol +++ b/test/libsolidity/syntaxTests/array/calldata_multi_dynamic_V1.sol @@ -4,5 +4,6 @@ contract Test { function g(uint[][1] calldata) external { } } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 4957: (51-68): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. // TypeError 4957: (98-116): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/constructor/nonabiv2_type.sol b/test/libsolidity/syntaxTests/constructor/nonabiv2_type.sol index 8e0c323b8..580261afe 100644 --- a/test/libsolidity/syntaxTests/constructor/nonabiv2_type.sol +++ b/test/libsolidity/syntaxTests/constructor/nonabiv2_type.sol @@ -3,4 +3,5 @@ contract C { constructor(uint[][][] memory t) {} } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 4957: (46-65): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. Alternatively, make the contract abstract and supply the constructor arguments from a derived contract. diff --git a/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol b/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol index ca52859ff..712322f1f 100644 --- a/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol +++ b/test/libsolidity/syntaxTests/constructor/nonabiv2_type_abstract.sol @@ -5,3 +5,4 @@ abstract contract C { // ==== // bytecodeFormat: legacy // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. diff --git a/test/libsolidity/syntaxTests/controlFlow/modifiers/implemented_without_placeholder.sol b/test/libsolidity/syntaxTests/controlFlow/modifiers/implemented_without_placeholder.sol index 08b4ef12e..a2a6bf661 100644 --- a/test/libsolidity/syntaxTests/controlFlow/modifiers/implemented_without_placeholder.sol +++ b/test/libsolidity/syntaxTests/controlFlow/modifiers/implemented_without_placeholder.sol @@ -6,3 +6,4 @@ abstract contract A { } // ---- // SyntaxError 2883: (129-132): Modifier body does not contain '_'. +// Warning 8429: (106-132): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/controlFlow/modifiers/modifier_different_functions.sol b/test/libsolidity/syntaxTests/controlFlow/modifiers/modifier_different_functions.sol index 63d915369..81ff63e3d 100644 --- a/test/libsolidity/syntaxTests/controlFlow/modifiers/modifier_different_functions.sol +++ b/test/libsolidity/syntaxTests/controlFlow/modifiers/modifier_different_functions.sol @@ -9,4 +9,5 @@ contract A { } } // ---- +// Warning 8429: (140-172): Virtual modifiers are deprecated and scheduled for removal. // TypeError 3464: (118-132): This variable is of storage pointer type and can be returned without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/modifiers/modifier_override.sol b/test/libsolidity/syntaxTests/controlFlow/modifiers/modifier_override.sol index 3c5eb80ee..7a9ea5e46 100644 --- a/test/libsolidity/syntaxTests/controlFlow/modifiers/modifier_override.sol +++ b/test/libsolidity/syntaxTests/controlFlow/modifiers/modifier_override.sol @@ -13,5 +13,6 @@ contract B is A { } } // ---- +// Warning 8429: (71-115): Virtual modifiers are deprecated and scheduled for removal. // Warning 5740: (65-69): Unreachable code. // TypeError 3464: (49-63): This variable is of storage pointer type and can be returned without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifier.sol b/test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifier.sol index 61aede05e..670639cc9 100644 --- a/test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifier.sol +++ b/test/libsolidity/syntaxTests/controlFlow/modifiers/non_implemented_modifier.sol @@ -4,3 +4,5 @@ abstract contract A { } modifier mod() virtual; } +// ---- +// Warning 8429: (106-129): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/conversion/implicit_conversion_of_super_in_comparison.sol b/test/libsolidity/syntaxTests/conversion/implicit_conversion_of_super_in_comparison.sol index 708713b6b..1d9e488ce 100644 --- a/test/libsolidity/syntaxTests/conversion/implicit_conversion_of_super_in_comparison.sol +++ b/test/libsolidity/syntaxTests/conversion/implicit_conversion_of_super_in_comparison.sol @@ -21,7 +21,10 @@ contract C { // ---- // TypeError 2271: (144-157): Built-in binary operator != cannot be applied to types type(contract super C) and contract C. // TypeError 2271: (167-180): Built-in binary operator != cannot be applied to types contract C and type(contract super C). +// Warning 9170: (167-180): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. // TypeError 2271: (254-264): Built-in binary operator != cannot be applied to types type(contract super C) and contract C. // TypeError 2271: (274-284): Built-in binary operator != cannot be applied to types contract C and type(contract super C). +// Warning 9170: (274-284): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. // TypeError 2271: (349-359): Built-in binary operator != cannot be applied to types type(contract super C) and contract D. // TypeError 2271: (369-379): Built-in binary operator != cannot be applied to types contract D and type(contract super C). +// Warning 9170: (369-379): Comparison of variables of contract type is deprecated and scheduled for removal. Use an explicit cast to address type and compare the addresses instead. diff --git a/test/libsolidity/syntaxTests/errors/no_structs_in_abiv1.sol b/test/libsolidity/syntaxTests/errors/no_structs_in_abiv1.sol index 8727a2852..7c3ba5137 100644 --- a/test/libsolidity/syntaxTests/errors/no_structs_in_abiv1.sol +++ b/test/libsolidity/syntaxTests/errors/no_structs_in_abiv1.sol @@ -4,4 +4,5 @@ contract C { error MyError(S); } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 3061: (70-71): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_nested_array.sol b/test/libsolidity/syntaxTests/events/event_nested_array.sol index 2491dae6e..a518aa936 100644 --- a/test/libsolidity/syntaxTests/events/event_nested_array.sol +++ b/test/libsolidity/syntaxTests/events/event_nested_array.sol @@ -3,4 +3,5 @@ contract c { event E(uint[][]); } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 3061: (45-53): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_nested_array_in_struct.sol b/test/libsolidity/syntaxTests/events/event_nested_array_in_struct.sol index ee868a715..dee271021 100644 --- a/test/libsolidity/syntaxTests/events/event_nested_array_in_struct.sol +++ b/test/libsolidity/syntaxTests/events/event_nested_array_in_struct.sol @@ -4,4 +4,5 @@ contract c { event E(S); } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 3061: (81-82): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_struct.sol b/test/libsolidity/syntaxTests/events/event_struct.sol index ac6355fe0..062fe4ba0 100644 --- a/test/libsolidity/syntaxTests/events/event_struct.sol +++ b/test/libsolidity/syntaxTests/events/event_struct.sol @@ -4,4 +4,5 @@ contract c { event E(S); } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 3061: (71-72): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_struct_indexed.sol b/test/libsolidity/syntaxTests/events/event_struct_indexed.sol index 7e3393400..5171bf017 100644 --- a/test/libsolidity/syntaxTests/events/event_struct_indexed.sol +++ b/test/libsolidity/syntaxTests/events/event_struct_indexed.sol @@ -4,4 +4,5 @@ contract c { event E(S indexed); } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 3061: (71-80): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/getter/nested_structs.sol b/test/libsolidity/syntaxTests/getter/nested_structs.sol index 36886bacf..ecde4773b 100644 --- a/test/libsolidity/syntaxTests/getter/nested_structs.sol +++ b/test/libsolidity/syntaxTests/getter/nested_structs.sol @@ -9,4 +9,5 @@ contract C { mapping(uint256 => X) public m; } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2763: (108-138): The following types are only supported for getters in ABI coder v2: struct C.Y memory. Either remove "public" or use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/immutable/inheritance_virtual_modifiers.sol b/test/libsolidity/syntaxTests/immutable/inheritance_virtual_modifiers.sol index 31f510dcc..1250d86d2 100644 --- a/test/libsolidity/syntaxTests/immutable/inheritance_virtual_modifiers.sol +++ b/test/libsolidity/syntaxTests/immutable/inheritance_virtual_modifiers.sol @@ -17,3 +17,5 @@ contract C is B { _; f(x); } } +// ---- +// Warning 8429: (88-137): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/imports/inheritance_abi_encoder_mismatch_1.sol b/test/libsolidity/syntaxTests/imports/inheritance_abi_encoder_mismatch_1.sol index 891f57e8d..2b1b920c5 100644 --- a/test/libsolidity/syntaxTests/imports/inheritance_abi_encoder_mismatch_1.sol +++ b/test/libsolidity/syntaxTests/imports/inheritance_abi_encoder_mismatch_1.sol @@ -17,4 +17,5 @@ pragma abicoder v1; import "./B.sol"; contract C is B { } // ---- +// Warning 9511: (C.sol:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 6594: (C.sol:38-57): Contract "C" does not use ABI coder v2 but wants to inherit from a contract which uses types that require it. Use "pragma abicoder v2;" for the inheriting contract as well to enable the feature. diff --git a/test/libsolidity/syntaxTests/imports/inheritance_abi_encoder_mismatch_2.sol b/test/libsolidity/syntaxTests/imports/inheritance_abi_encoder_mismatch_2.sol index c92221f3a..d4b6996e7 100644 --- a/test/libsolidity/syntaxTests/imports/inheritance_abi_encoder_mismatch_2.sol +++ b/test/libsolidity/syntaxTests/imports/inheritance_abi_encoder_mismatch_2.sol @@ -16,4 +16,6 @@ pragma abicoder v1; import "./B.sol"; contract C is B { } // ---- +// Warning 9511: (B.sol:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. +// Warning 9511: (C.sol:0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 6594: (B.sol:38-57): Contract "B" does not use ABI coder v2 but wants to inherit from a contract which uses types that require it. Use "pragma abicoder v2;" for the inheriting contract as well to enable the feature. diff --git a/test/libsolidity/syntaxTests/inheritance/dataLocation/modifier_parameter_data_location_change_illegal_internal.sol b/test/libsolidity/syntaxTests/inheritance/dataLocation/modifier_parameter_data_location_change_illegal_internal.sol index a4856d9f0..bfceb0489 100644 --- a/test/libsolidity/syntaxTests/inheritance/dataLocation/modifier_parameter_data_location_change_illegal_internal.sol +++ b/test/libsolidity/syntaxTests/inheritance/dataLocation/modifier_parameter_data_location_change_illegal_internal.sol @@ -10,4 +10,5 @@ contract B is A { } } // ---- +// Warning 8429: (26-66): Virtual modifiers are deprecated and scheduled for removal. // TypeError 1078: (153-214): Override changes modifier signature. diff --git a/test/libsolidity/syntaxTests/inheritance/override/modifier_ambiguous.sol b/test/libsolidity/syntaxTests/inheritance/override/modifier_ambiguous.sol index 00aeed0cd..4f87fc779 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/modifier_ambiguous.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/modifier_ambiguous.sol @@ -8,3 +8,5 @@ contract C is A, B { modifier f() override(A,B) { _; } } // ---- +// Warning 8429: (17-44): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (64-91): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/inheritance/override/modifier_ambiguous_fail.sol b/test/libsolidity/syntaxTests/inheritance/override/modifier_ambiguous_fail.sol index 7332f0817..fe663c6bf 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/modifier_ambiguous_fail.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/modifier_ambiguous_fail.sol @@ -7,4 +7,6 @@ contract B { contract C is A, B { } // ---- +// Warning 8429: (17-44): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (64-91): Virtual modifiers are deprecated and scheduled for removal. // TypeError 6480: (94-116): Derived contract must override modifier "f". Two or more base classes define modifier with same name. diff --git a/test/libsolidity/syntaxTests/inheritance/override/modifier_inherited_different_signature.sol b/test/libsolidity/syntaxTests/inheritance/override/modifier_inherited_different_signature.sol index 428f38e62..5c4356741 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/modifier_inherited_different_signature.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/modifier_inherited_different_signature.sol @@ -7,4 +7,6 @@ contract B { contract C is A, B { } // ---- +// Warning 8429: (17-50): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (70-97): Virtual modifiers are deprecated and scheduled for removal. // TypeError 6480: (100-122): Derived contract must override modifier "f". Two or more base classes define modifier with same name. diff --git a/test/libsolidity/syntaxTests/inheritance/override/modifier_inherited_different_signature_override.sol b/test/libsolidity/syntaxTests/inheritance/override/modifier_inherited_different_signature_override.sol index 7791ea725..9669a02d0 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/modifier_inherited_different_signature_override.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/modifier_inherited_different_signature_override.sol @@ -8,4 +8,7 @@ contract C is A, B { modifier f() virtual override(A, B) { _; } } // ---- +// Warning 8429: (17-50): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (70-97): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (125-167): Virtual modifiers are deprecated and scheduled for removal. // TypeError 1078: (125-167): Override changes modifier signature. diff --git a/test/libsolidity/syntaxTests/inheritance/override/nonintermediate_common_base_and_unique_implementation_modifier.sol b/test/libsolidity/syntaxTests/inheritance/override/nonintermediate_common_base_and_unique_implementation_modifier.sol index deda228fa..0c582f3c5 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/nonintermediate_common_base_and_unique_implementation_modifier.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/nonintermediate_common_base_and_unique_implementation_modifier.sol @@ -16,4 +16,7 @@ contract B is IJ } contract C is A, B {} // ---- +// Warning 8429: (14-41): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (58-85): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (111-154): Virtual modifiers are deprecated and scheduled for removal. // TypeError 6480: (229-250): Derived contract must override modifier "f". Two or more base classes define modifier with same name. diff --git a/test/libsolidity/syntaxTests/inheritance/virtual/modifier_virtual_err.sol b/test/libsolidity/syntaxTests/inheritance/virtual/modifier_virtual_err.sol index 85824c86b..52625e72c 100644 --- a/test/libsolidity/syntaxTests/inheritance/virtual/modifier_virtual_err.sol +++ b/test/libsolidity/syntaxTests/inheritance/virtual/modifier_virtual_err.sol @@ -4,4 +4,5 @@ library test { } } // ---- +// Warning 8429: (19-38): Virtual modifiers are deprecated and scheduled for removal. // TypeError 3275: (19-38): Modifiers in a library cannot be virtual. diff --git a/test/libsolidity/syntaxTests/inheritance/virtual/simple.sol b/test/libsolidity/syntaxTests/inheritance/virtual/simple.sol index 892118a13..e74f5a3e0 100644 --- a/test/libsolidity/syntaxTests/inheritance/virtual/simple.sol +++ b/test/libsolidity/syntaxTests/inheritance/virtual/simple.sol @@ -5,3 +5,4 @@ contract C modifier modi() virtual {_;} } // ---- +// Warning 8429: (83-111): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/memory_safe_dialect_string_and_comment.sol b/test/libsolidity/syntaxTests/inlineAssembly/memory_safe_dialect_string_and_comment.sol index 9d0fd3e1c..12ccf94ff 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/memory_safe_dialect_string_and_comment.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/memory_safe_dialect_string_and_comment.sol @@ -4,4 +4,5 @@ function f() pure { } } // ---- -// Warning 8544: (63-104): Inline assembly marked as memory safe using both a NatSpec tag and an assembly flag. If you are not concerned with backwards compatibility, only use the assembly flag, otherwise only use the NatSpec tag. +// Warning 8544: (63-104): Inline assembly marked as memory safe using both a NatSpec tag and an assembly block annotation. If you are not concerned with backwards compatibility, only use the assembly block annotation, otherwise only use the NatSpec tag. +// Warning 2424: (63-104): Natspec memory-safe-assembly special comment for inline assembly is deprecated and scheduled for removal. Use the memory-safe block annotation instead. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi.sol b/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi.sol index 945d62b06..48b9ba79c 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi.sol @@ -15,9 +15,11 @@ function f() pure { // Warning 6269: (189-200): Unexpected NatSpec tag "after" with value "bogus-value" in inline assembly. // Warning 6269: (189-200): Unexpected NatSpec tag "before" with value "bogus-value" in inline assembly. // Warning 8787: (189-200): Unexpected value for @solidity tag in inline assembly: a +// Warning 2424: (189-200): Natspec memory-safe-assembly special comment for inline assembly is deprecated and scheduled for removal. Use the memory-safe block annotation instead. // Warning 8787: (189-200): Unexpected value for @solidity tag in inline assembly: b // Warning 8787: (189-200): Unexpected value for @solidity tag in inline assembly: c // Warning 8787: (189-200): Unexpected value for @solidity tag in inline assembly: d +// Warning 2424: (289-300): Natspec memory-safe-assembly special comment for inline assembly is deprecated and scheduled for removal. Use the memory-safe block annotation instead. // Warning 8787: (289-300): Unexpected value for @solidity tag in inline assembly: a // Warning 4377: (289-300): Value for @solidity tag in inline assembly specified multiple times: a // Warning 4377: (289-300): Value for @solidity tag in inline assembly specified multiple times: memory-safe-assembly diff --git a/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi_swallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi_swallowed.sol index 74be1232d..9d148b0b3 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi_swallowed.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/natspec_multi_swallowed.sol @@ -14,6 +14,7 @@ function f() pure { // ---- // Warning 6269: (177-188): Unexpected NatSpec tag "after" with value "bogus-value" in inline assembly. // Warning 6269: (177-188): Unexpected NatSpec tag "before" with value "@solidity a memory-safe-assembly b c d" in inline assembly. +// Warning 2424: (277-288): Natspec memory-safe-assembly special comment for inline assembly is deprecated and scheduled for removal. Use the memory-safe block annotation instead. // Warning 8787: (277-288): Unexpected value for @solidity tag in inline assembly: a // Warning 4377: (277-288): Value for @solidity tag in inline assembly specified multiple times: a // Warning 4377: (277-288): Value for @solidity tag in inline assembly specified multiple times: memory-safe-assembly diff --git a/test/libsolidity/syntaxTests/modifiers/definition_in_contract.sol b/test/libsolidity/syntaxTests/modifiers/definition_in_contract.sol index 9b0a805ad..ff3b924c6 100644 --- a/test/libsolidity/syntaxTests/modifiers/definition_in_contract.sol +++ b/test/libsolidity/syntaxTests/modifiers/definition_in_contract.sol @@ -9,3 +9,6 @@ abstract contract A { modifier muv virtual; } // ---- +// Warning 8429: (39-65): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (117-143): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (148-169): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/modifiers/definition_in_contract_unimplemented.sol b/test/libsolidity/syntaxTests/modifiers/definition_in_contract_unimplemented.sol index 2018ae4ea..8b60105ae 100644 --- a/test/libsolidity/syntaxTests/modifiers/definition_in_contract_unimplemented.sol +++ b/test/libsolidity/syntaxTests/modifiers/definition_in_contract_unimplemented.sol @@ -3,5 +3,6 @@ contract C { modifier muv virtual; } // ---- +// Warning 8429: (34-55): Virtual modifiers are deprecated and scheduled for removal. // TypeError 3656: (0-57): Contract "C" should be marked as abstract. // TypeError 8063: (17-29): Modifiers without implementation must be marked virtual. diff --git a/test/libsolidity/syntaxTests/modifiers/definition_in_interface.sol b/test/libsolidity/syntaxTests/modifiers/definition_in_interface.sol index 2f8281bde..56e5bb02f 100644 --- a/test/libsolidity/syntaxTests/modifiers/definition_in_interface.sol +++ b/test/libsolidity/syntaxTests/modifiers/definition_in_interface.sol @@ -5,6 +5,8 @@ interface I { modifier muv virtual; } // ---- +// Warning 8429: (57-83): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (88-109): Virtual modifiers are deprecated and scheduled for removal. // TypeError 6408: (18-35): Modifiers cannot be defined or declared in interfaces. // TypeError 6408: (40-52): Modifiers cannot be defined or declared in interfaces. // TypeError 8063: (40-52): Modifiers without implementation must be marked virtual. diff --git a/test/libsolidity/syntaxTests/modifiers/definition_in_library.sol b/test/libsolidity/syntaxTests/modifiers/definition_in_library.sol index 6acbf3a0f..34503d727 100644 --- a/test/libsolidity/syntaxTests/modifiers/definition_in_library.sol +++ b/test/libsolidity/syntaxTests/modifiers/definition_in_library.sol @@ -2,4 +2,5 @@ library L { modifier mv virtual { _; } } // ---- +// Warning 8429: (16-42): Virtual modifiers are deprecated and scheduled for removal. // TypeError 3275: (16-42): Modifiers in a library cannot be virtual. diff --git a/test/libsolidity/syntaxTests/modifiers/definition_in_library_unimplemented.sol b/test/libsolidity/syntaxTests/modifiers/definition_in_library_unimplemented.sol index 5fbc35682..a239d86ce 100644 --- a/test/libsolidity/syntaxTests/modifiers/definition_in_library_unimplemented.sol +++ b/test/libsolidity/syntaxTests/modifiers/definition_in_library_unimplemented.sol @@ -3,5 +3,6 @@ library L { modifier muv virtual; } // ---- +// Warning 8429: (33-54): Virtual modifiers are deprecated and scheduled for removal. // TypeError 8063: (16-28): Modifiers without implementation must be marked virtual. // TypeError 3275: (33-54): Modifiers in a library cannot be virtual. diff --git a/test/libsolidity/syntaxTests/modifiers/empty_modifier_body.sol b/test/libsolidity/syntaxTests/modifiers/empty_modifier_body.sol index 0c0e821f5..d9abfbbde 100644 --- a/test/libsolidity/syntaxTests/modifiers/empty_modifier_body.sol +++ b/test/libsolidity/syntaxTests/modifiers/empty_modifier_body.sol @@ -13,3 +13,5 @@ contract D is C { } } // ---- +// Warning 8429: (22-51): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (134-153): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/modifiers/empty_modifier_err.sol b/test/libsolidity/syntaxTests/modifiers/empty_modifier_err.sol index e9e03f304..bc466e471 100644 --- a/test/libsolidity/syntaxTests/modifiers/empty_modifier_err.sol +++ b/test/libsolidity/syntaxTests/modifiers/empty_modifier_err.sol @@ -5,6 +5,8 @@ contract C is B { } abstract contract D {modifier m;} // ---- +// Warning 8429: (12-31): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (55-74): Virtual modifiers are deprecated and scheduled for removal. // TypeError 3656: (0-32): Contract "A" should be marked as abstract. // TypeError 3656: (76-95): Contract "C" should be marked as abstract. // TypeError 8063: (118-129): Modifiers without implementation must be marked virtual. diff --git a/test/libsolidity/syntaxTests/modifiers/legal_modifier_override.sol b/test/libsolidity/syntaxTests/modifiers/legal_modifier_override.sol index 62356abb1..2fff2d427 100644 --- a/test/libsolidity/syntaxTests/modifiers/legal_modifier_override.sol +++ b/test/libsolidity/syntaxTests/modifiers/legal_modifier_override.sol @@ -1,3 +1,4 @@ contract A { modifier mod(uint a) virtual { _; } } contract B is A { modifier mod(uint a) override { _; } } // ---- +// Warning 8429: (13-48): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/modifiers/modifier_abstract_override.sol b/test/libsolidity/syntaxTests/modifiers/modifier_abstract_override.sol index dd3ef4499..e4c2a5cd2 100644 --- a/test/libsolidity/syntaxTests/modifiers/modifier_abstract_override.sol +++ b/test/libsolidity/syntaxTests/modifiers/modifier_abstract_override.sol @@ -8,4 +8,6 @@ contract C is B { function f() m public {} } // ---- +// Warning 8429: (17-44): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (78-108): Virtual modifiers are deprecated and scheduled for removal. // TypeError 4593: (78-108): Overriding an implemented modifier with an unimplemented modifier is not allowed. diff --git a/test/libsolidity/syntaxTests/modifiers/multiple_inheritance_unimplemented_override.sol b/test/libsolidity/syntaxTests/modifiers/multiple_inheritance_unimplemented_override.sol index 81e1c3565..f78b0b9fd 100644 --- a/test/libsolidity/syntaxTests/modifiers/multiple_inheritance_unimplemented_override.sol +++ b/test/libsolidity/syntaxTests/modifiers/multiple_inheritance_unimplemented_override.sol @@ -9,3 +9,5 @@ contract C is A, B { function f() m public {} } // ---- +// Warning 8429: (17-44): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (73-94): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/modifiers/unimplemented_function_and_modifier.sol b/test/libsolidity/syntaxTests/modifiers/unimplemented_function_and_modifier.sol index bf823748c..702ac5ba7 100644 --- a/test/libsolidity/syntaxTests/modifiers/unimplemented_function_and_modifier.sol +++ b/test/libsolidity/syntaxTests/modifiers/unimplemented_function_and_modifier.sol @@ -26,6 +26,7 @@ contract E is A { modifier mod() override { _;} } // ---- +// Warning 8429: (110-133): Virtual modifiers are deprecated and scheduled for removal. // TypeError 3656: (137-254): Contract "B" should be marked as abstract. // TypeError 3656: (256-344): Contract "C" should be marked as abstract. // TypeError 3656: (346-466): Contract "D" should be marked as abstract. diff --git a/test/libsolidity/syntaxTests/modifiers/unimplemented_override_unimplemented.sol b/test/libsolidity/syntaxTests/modifiers/unimplemented_override_unimplemented.sol index ae041ebfc..dbc6b0657 100644 --- a/test/libsolidity/syntaxTests/modifiers/unimplemented_override_unimplemented.sol +++ b/test/libsolidity/syntaxTests/modifiers/unimplemented_override_unimplemented.sol @@ -9,3 +9,6 @@ abstract contract C is B { function f() m public {} } // ---- +// Warning 8429: (26-47): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (81-111): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (145-175): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/modifiers/use_unimplemented_from_base.sol b/test/libsolidity/syntaxTests/modifiers/use_unimplemented_from_base.sol index 6d6423e7e..77d06eca3 100644 --- a/test/libsolidity/syntaxTests/modifiers/use_unimplemented_from_base.sol +++ b/test/libsolidity/syntaxTests/modifiers/use_unimplemented_from_base.sol @@ -6,3 +6,5 @@ contract B is A { modifier m() virtual override { _; } } // ---- +// Warning 8429: (26-47): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (101-137): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/modifiers/use_unimplemented_on_overridden_func.sol b/test/libsolidity/syntaxTests/modifiers/use_unimplemented_on_overridden_func.sol index 5f6de4ce8..91aeb91f8 100644 --- a/test/libsolidity/syntaxTests/modifiers/use_unimplemented_on_overridden_func.sol +++ b/test/libsolidity/syntaxTests/modifiers/use_unimplemented_on_overridden_func.sol @@ -6,3 +6,4 @@ abstract contract B is A { function f() public override {} } // ---- +// Warning 8429: (26-47): Virtual modifiers are deprecated and scheduled for removal. diff --git a/test/libsolidity/syntaxTests/modifiers/use_unimplemented_static.sol b/test/libsolidity/syntaxTests/modifiers/use_unimplemented_static.sol index a6fcd7eaf..26f4ebee6 100644 --- a/test/libsolidity/syntaxTests/modifiers/use_unimplemented_static.sol +++ b/test/libsolidity/syntaxTests/modifiers/use_unimplemented_static.sol @@ -9,4 +9,6 @@ contract C is A, B { function f() B.m public {} } // ---- +// Warning 8429: (17-44): Virtual modifiers are deprecated and scheduled for removal. +// Warning 8429: (73-94): Virtual modifiers are deprecated and scheduled for removal. // TypeError 1835: (174-177): Cannot call unimplemented modifier. The modifier has no implementation in the referenced contract. Refer to it by its unqualified name if you want to call the implementation from the most derived contract. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/045_returning_multi_dimensional_arrays.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/045_returning_multi_dimensional_arrays.sol index c9075a4cd..6490d0067 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/045_returning_multi_dimensional_arrays.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/045_returning_multi_dimensional_arrays.sol @@ -3,4 +3,5 @@ contract C { function f() public pure returns (string[][] memory) {} } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 4957: (71-88): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/046_returning_multi_dimensional_static_arrays.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/046_returning_multi_dimensional_static_arrays.sol index ee8c7f18d..17829bcdd 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/046_returning_multi_dimensional_static_arrays.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/046_returning_multi_dimensional_static_arrays.sol @@ -3,4 +3,5 @@ contract C { function f() public pure returns (uint[][2] memory) {} } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 4957: (71-87): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/048_returning_arrays_in_structs_arrays.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/048_returning_arrays_in_structs_arrays.sol index 77c77831e..77a11a6d9 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/048_returning_arrays_in_structs_arrays.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/048_returning_arrays_in_structs_arrays.sol @@ -4,4 +4,5 @@ contract C { function f() public pure returns (S memory x) {} } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 4957: (100-110): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/346_unused_return_value_send.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/346_unused_return_value_send.sol index 80787c10c..88f172cd7 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/346_unused_return_value_send.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/346_unused_return_value_send.sol @@ -4,4 +4,5 @@ contract test { } } // ---- +// Warning 9207: (50-77): 'send' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Warning 5878: (50-80): Failure condition of 'send' ignored. Consider using 'transfer' instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/405_address_checksum_type_deduction.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/405_address_checksum_type_deduction.sol index 25acbfd42..07f268f02 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/405_address_checksum_type_deduction.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/405_address_checksum_type_deduction.sol @@ -4,3 +4,4 @@ contract C { } } // ---- +// Warning 9207: (47-107): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol index ad57224cd..b8678efa6 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol @@ -10,3 +10,5 @@ contract C { } } // ---- +// Warning 9207: (227-236): 'send' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 9207: (249-262): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/466_does_not_error_transfer_payable_fallback.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/466_does_not_error_transfer_payable_fallback.sol index 642ae8360..d897d8171 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/466_does_not_error_transfer_payable_fallback.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/466_does_not_error_transfer_payable_fallback.sol @@ -13,3 +13,4 @@ contract B { } } // ---- +// Warning 9207: (227-246): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/535_address_overload_resolution.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/535_address_overload_resolution.sol index a36aeed86..673632940 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/535_address_overload_resolution.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/535_address_overload_resolution.sol @@ -17,4 +17,5 @@ contract D { } } // ---- +// Warning 9207: (187-209): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Warning 2018: (17-134): Function state mutability can be restricted to view diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/585_abi_decode_with_unsupported_types.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/585_abi_decode_with_unsupported_types.sol index abbf76182..d7127f618 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/585_abi_decode_with_unsupported_types.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/585_abi_decode_with_unsupported_types.sol @@ -6,4 +6,5 @@ contract C { } } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 9611: (118-119): Decoding type struct C.s memory not supported. diff --git a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol index f3091ebf5..599267274 100644 --- a/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol +++ b/test/libsolidity/syntaxTests/sizeLimits/bytecode_too_large_abiencoder_v1.sol @@ -10,4 +10,5 @@ contract test { // EVMVersion: >=shanghai // bytecodeFormat: legacy // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // Warning 5574: (21-27154): Contract code size is 27205 bytes and exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on Mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encodePacked_nested_dynamic_array.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encodePacked_nested_dynamic_array.sol index c10dc10f2..4b1f5905c 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/abi_encodePacked_nested_dynamic_array.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encodePacked_nested_dynamic_array.sol @@ -5,4 +5,5 @@ contract C { } } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 9578: (89-119): Type not supported in packed mode. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encode_nested_dynamic_array.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_nested_dynamic_array.sol index 8c679258c..f46c46845 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/abi_encode_nested_dynamic_array.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_nested_dynamic_array.sol @@ -5,4 +5,5 @@ contract C { } } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2056: (86-116): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encode_structs.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_structs.sol index a7d0e3dbe..8b194ff6a 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/abi_encode_structs.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_structs.sol @@ -12,6 +12,7 @@ contract C { } } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 2056: (151-152): This type cannot be encoded. // TypeError 2056: (154-155): This type cannot be encoded. // TypeError 9578: (220-221): Type not supported in packed mode. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_nested_dynamic_array.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_nested_dynamic_array.sol index 1981b04bf..256728a7e 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_nested_dynamic_array.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_nested_dynamic_array.sol @@ -5,4 +5,5 @@ contract C { } } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 9611: (92-101): Decoding type uint256[][3] memory not supported. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_struct.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_struct.sol index dd981b54c..04ec0f78b 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_struct.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_struct.sol @@ -9,4 +9,5 @@ contract C { } } // ---- +// Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // TypeError 9611: (118-119): Decoding type struct S memory not supported. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol index 8f2753213..4d54097d5 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol @@ -21,4 +21,6 @@ contract C { // ==== // bytecodeFormat: legacy // ---- +// Warning 9207: (47-69): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 9207: (90-108): 'send' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Warning 5159: (122-134): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol index 4f9efcdb5..347fd3fde 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol @@ -20,6 +20,8 @@ contract C { } } // ---- +// Warning 9207: (52-74): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 9207: (132-150): 'send' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. // Warning 5159: (201-213): "selfdestruct" has been deprecated. Note that, starting from the Cancun hard fork, the underlying opcode no longer deletes the code and data associated with an account and only transfers its Ether to the beneficiary, unless executed in the same transaction in which the contract was created (see EIP-6780). Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. // TypeError 8961: (52-77): Function cannot be declared as view because this expression (potentially) modifies the state. // TypeError 8961: (132-153): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/eof/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/eof/builtin_functions.sol index 91ea709fe..a974e26e7 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/eof/builtin_functions.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/eof/builtin_functions.sol @@ -20,3 +20,5 @@ contract C { // ==== // bytecodeFormat: >=EOFv1 // ---- +// Warning 9207: (47-69): 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. +// Warning 9207: (90-108): 'send' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. From dbeb8762388e32df51585092c7905b7039b6bd8f Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 2 Sep 2025 16:51:44 -0300 Subject: [PATCH 1019/1340] Update docs --- docs/assembly.rst | 5 +- docs/cheatsheet.rst | 4 +- docs/common-patterns.rst | 12 +- docs/contracts/functions.rst | 6 +- docs/contracts/inheritance.rst | 9 +- docs/control-structures.rst | 15 +-- docs/examples/blind-auction.rst | 21 ++-- docs/examples/micropayment.rst | 15 ++- docs/examples/safe-remote.rst | 15 ++- docs/layout-of-source-files.rst | 8 +- docs/security-considerations.rst | 14 ++- docs/types/reference-types.rst | 6 +- docs/types/value-types.rst | 178 ++++++++++++++++------------ docs/units-and-global-variables.rst | 14 ++- 14 files changed, 198 insertions(+), 124 deletions(-) diff --git a/docs/assembly.rst b/docs/assembly.rst index 3f00ab6a8..0458e3196 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -381,8 +381,9 @@ of Solidity, you can use a special comment to annotate an assembly block as memo ... } -Note that we will disallow the annotation via comment in a future breaking release; so, if you are not concerned with -backward-compatibility with older compiler versions, prefer using the dialect string. +.. warning:: + The ``memory-safe-assembly`` special comment is deprecated and scheduled for removal. + In new code targeting recent compilers, use the assembly block annotation. Advanced Safe Use of Memory --------------------------- diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index 79aa6e65d..1a3085f12 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -53,8 +53,8 @@ Members of ``address`` - ``
.staticcall(bytes memory) returns (bool, bytes memory)``: issue low-level ``STATICCALL`` with the given payload, returns success condition and return data - ``
.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, - returns ``false`` on failure -- ``
.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure + returns ``false`` on failure (deprecated) +- ``
.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure (deprecated) .. index:: blockhash, blobhash, block, block;basefee, block;blobbasefee, block;chainid, block;coinbase, block;difficulty, block;gaslimit, block;number, block;prevrandao, block;timestamp .. index:: gasleft, msg;data, msg;sender, msg;sig, msg;value, tx;gasprice, tx;origin diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index cbc219b53..4051f0f30 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -57,7 +57,8 @@ you receive the funds of the person who is now the richest. // Remember to zero the pending refund before // sending to prevent reentrancy attacks pendingWithdrawals[msg.sender] = 0; - payable(msg.sender).transfer(amount); + (bool success, ) = payable(msg.sender).call{value: amount}(""); + require(success); } } @@ -84,7 +85,8 @@ This is as opposed to the more intuitive sending pattern: function becomeRichest() public payable { if (msg.value <= mostSent) revert NotEnoughEther(); // This line can cause problems (explained below). - richest.transfer(msg.value); + (bool success, ) = richest.call{value: msg.value}(""); + require(success); richest = payable(msg.sender); mostSent = msg.value; } @@ -210,8 +212,10 @@ restrictions highly readable. revert NotEnoughEther(); _; - if (msg.value > amount) - payable(msg.sender).transfer(msg.value - amount); + if (msg.value > amount) { + (bool success, ) = payable(msg.sender).call{value: msg.value - amount}(""); + require(success); + } } function forceOwnerChange(address newOwner) diff --git a/docs/contracts/functions.rst b/docs/contracts/functions.rst index a3a275538..163a891f1 100644 --- a/docs/contracts/functions.rst +++ b/docs/contracts/functions.rst @@ -310,6 +310,10 @@ will consume more gas than the 2300 gas stipend: - Calling an external function which consumes a large amount of gas - Sending Ether +.. warning:: + ``send()`` and ``transfer()`` are deprecated and scheduled for removal. + See the section on :ref:`send ` and :ref:`transfer ` for more information. + .. warning:: When Ether is sent directly to a contract (without a function call, i.e. sender uses ``send`` or ``transfer``) but the receiving contract does not define a receive Ether function or a payable fallback function, @@ -319,7 +323,6 @@ will consume more gas than the 2300 gas stipend: not recommended, since the fallback is invoked and would not fail for interface confusions on the part of the sender). - .. warning:: A contract without a receive Ether function can receive Ether as a recipient of a *coinbase transaction* (aka *miner block reward*) @@ -440,6 +443,7 @@ operations as long as there is enough gas passed on to it. // If someone sends Ether to that contract, // the transfer will fail, i.e. this returns false here. + // This will report a warning (deprecation) return testPayable.send(2 ether); } diff --git a/docs/contracts/inheritance.rst b/docs/contracts/inheritance.rst index 8a2d12afd..778cd1c26 100644 --- a/docs/contracts/inheritance.rst +++ b/docs/contracts/inheritance.rst @@ -377,8 +377,8 @@ of the variable: .. _modifier-overriding: -Modifier Overriding -=================== +Modifier Overriding (deprecated) +================================ Function modifiers can override each other. This works in the same way as :ref:`function overriding ` (except that there is no overloading for modifiers). The @@ -392,6 +392,7 @@ and the ``override`` keyword must be used in the overriding modifier: contract Base { + // This will report a warning (deprecation) modifier foo() virtual {_;} } @@ -411,11 +412,13 @@ explicitly: contract Base1 { + // This will report a warning (deprecation) modifier foo() virtual {_;} } contract Base2 { + // This will report a warning (deprecation) modifier foo() virtual {_;} } @@ -424,6 +427,8 @@ explicitly: modifier foo() override(Base1, Base2) {_;} } +.. warning:: + ``virtual`` modifiers are deprecated and scheduled for removal. .. index:: ! constructor diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 8a815e10e..c567ddc52 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -692,16 +692,16 @@ and ``assert`` for internal error checking. :force: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.5.0 <0.9.0; + pragma solidity >=0.6.2 <0.9.0; contract Sharer { function sendHalf(address payable addr) public payable returns (uint balance) { require(msg.value % 2 == 0, "Even value required."); uint balanceBeforeTransfer = address(this).balance; - addr.transfer(msg.value / 2); - // Since transfer throws an exception on failure and - // cannot call back here, there should be no way for us to - // still have half of the Ether. + (bool success, ) = addr.call{value: msg.value / 2}(""); + require(success); + // Since require will stop execution and revert if success is false, + // there should be no way for us to still have half of the Ether. assert(address(this).balance == balanceBeforeTransfer - msg.value / 2); return address(this).balance; } @@ -775,7 +775,8 @@ together with ``revert`` and the equivalent ``require``: if (msg.sender != owner) revert Unauthorized(); - payable(msg.sender).transfer(address(this).balance); + (bool success, ) = payable(msg.sender).call{value: address(this).balance}(""); + require(success); } } @@ -914,4 +915,4 @@ in scope in the block that follows. out-of-gas situation and not a deliberate error condition: The caller always retains at least 1/64th of the gas in a call and thus even if the called contract goes out of gas, the caller still - has some gas left. \ No newline at end of file + has some gas left. diff --git a/docs/examples/blind-auction.rst b/docs/examples/blind-auction.rst index 47e19033f..e5e3184a8 100644 --- a/docs/examples/blind-auction.rst +++ b/docs/examples/blind-auction.rst @@ -118,13 +118,14 @@ to receive their Ether - contracts cannot activate themselves. if (amount > 0) { // It is important to set this to zero because the recipient // can call this function again as part of the receiving call - // before `send` returns. + // before `call` returns. pendingReturns[msg.sender] = 0; // msg.sender is not of type `address payable` and must be // explicitly converted using `payable(msg.sender)` in order - // use the member function `send()`. - if (!payable(msg.sender).send(amount)) { + // use the member function `call()`. + (bool success, ) = payable(msg.sender).call{value: amount}(""); + if (!success) { // No need to call throw here, just reset the amount owing pendingReturns[msg.sender] = amount; return false; @@ -160,7 +161,8 @@ to receive their Ether - contracts cannot activate themselves. emit AuctionEnded(highestBidder, highestBid); // 3. Interaction - beneficiary.transfer(highestBid); + (bool success, ) = beneficiary.call{value: highestBid}(""); + require(success); } } @@ -310,7 +312,8 @@ invalid bids. // the same deposit. bidToCheck.blindedBid = bytes32(0); } - payable(msg.sender).transfer(refund); + (bool success, ) = payable(msg.sender).call{value: refund}(""); + require(success); } /// Withdraw a bid that was overbid. @@ -319,11 +322,12 @@ invalid bids. if (amount > 0) { // It is important to set this to zero because the recipient // can call this function again as part of the receiving call - // before `transfer` returns (see the remark above about + // before `call` returns (see the remark above about // conditions -> effects -> interaction). pendingReturns[msg.sender] = 0; - payable(msg.sender).transfer(amount); + (bool success, ) = payable(msg.sender).call{value: amount}(""); + require(success); } } @@ -336,7 +340,8 @@ invalid bids. if (ended) revert AuctionEndAlreadyCalled(); emit AuctionEnded(highestBidder, highestBid); ended = true; - beneficiary.transfer(highestBid); + (bool success, ) = beneficiary.call{value: highestBid}(""); + require(success); } // This is an "internal" function which means that it diff --git a/docs/examples/micropayment.rst b/docs/examples/micropayment.rst index a7b26bb51..373627c3d 100644 --- a/docs/examples/micropayment.rst +++ b/docs/examples/micropayment.rst @@ -185,7 +185,8 @@ The full contract // this recreates the message that was signed on the client bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender, amount, nonce, this))); require(recoverSigner(message, signature) == owner); - payable(msg.sender).transfer(amount); + (bool success, ) = payable(msg.sender).call{value: amount}(""); + require(success); } /// freeze the contract and reclaim the leftover funds. @@ -195,7 +196,8 @@ The full contract { require(msg.sender == owner); freeze(); - payable(msg.sender).transfer(address(this).balance); + (bool success, ) = payable(msg.sender).call{value: address(this).balance}(""); + require(success); } /// signature methods. @@ -406,9 +408,11 @@ The full contract require(msg.sender == recipient); require(isValidSignature(amount, signature)); - recipient.transfer(amount); + (bool success, ) = recipient.call{value: amount}(""); + require(success); freeze(); - sender.transfer(address(this).balance); + (success, ) = sender.call{value: address(this).balance}(""); + require(success); } /// the sender can extend the expiration at any time @@ -430,7 +434,8 @@ The full contract { require(block.timestamp >= expiration); freeze(); - sender.transfer(address(this).balance); + (bool success, ) = sender.call{value: address(this).balance}(""); + require(success); } function isValidSignature(uint256 amount, bytes memory signature) diff --git a/docs/examples/safe-remote.rst b/docs/examples/safe-remote.rst index a2651af23..dd2a86b14 100644 --- a/docs/examples/safe-remote.rst +++ b/docs/examples/safe-remote.rst @@ -93,11 +93,12 @@ you can use state machine-like constructs inside a contract. { emit Aborted(); state = State.Inactive; - // We use transfer here directly. It is + // We use call here directly. It is // reentrancy-safe, because it is the // last call in this function and we // already changed the state. - seller.transfer(address(this).balance); + (bool success, ) = seller.call{value: address(this).balance}(""); + require(success); } /// Confirm the purchase as buyer. @@ -124,11 +125,12 @@ you can use state machine-like constructs inside a contract. { emit ItemReceived(); // It is important to change the state first because - // otherwise, the contracts called using `send` below + // otherwise, the contracts called using `call` below // can call in again here. state = State.Release; - buyer.transfer(value); + (bool success, ) = buyer.call{value: value}(""); + require(success); } /// This function refunds the seller, i.e. @@ -140,10 +142,11 @@ you can use state machine-like constructs inside a contract. { emit SellerRefunded(); // It is important to change the state first because - // otherwise, the contracts called using `send` below + // otherwise, the contracts called using `call` below // can call in again here. state = State.Inactive; - seller.transfer(3 * value); + (bool success, ) = seller.call{value: 3 * value}(""); + require(success); } } diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index e2c7a859a..94ef43525 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -103,10 +103,14 @@ select between the two implementations of the ABI encoder and decoder. The new ABI coder (v2) is able to encode and decode arbitrarily nested arrays and structs. Apart from supporting more types, it involves more extensive validation and safety checks, which may result in higher gas costs, but also heightened -security. It is considered -non-experimental as of Solidity 0.6.0 and it is enabled by default starting +security. +It is considered non-experimental as of Solidity 0.6.0 and it is enabled by default starting with Solidity 0.8.0. The old ABI coder can still be selected using ``pragma abicoder v1;``. +.. warning:: + The ABI coder v1 is deprecated and scheduled for removal. + Use ABI coder v2 instead. + The set of types supported by the new encoder is a strict superset of the ones supported by the old one. Contracts that use it can interact with ones that do not without limitations. The reverse is possible only as long as the diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index eb42993e6..af0e4c318 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -65,6 +65,7 @@ To give an example, the following code contains a bug (it is just a snippet and mapping(address => uint) shares; /// Withdraw your share. function withdraw() public { + // This will report a warning (deprecation) if (payable(msg.sender).send(shares[msg.sender])) shares[msg.sender] = 0; } @@ -76,7 +77,7 @@ Ether transfer can always include code execution, so the recipient could be a contract that calls back into ``withdraw``. This would let it get multiple refunds and, basically, retrieve all the Ether in the contract. In particular, the following contract will allow an attacker to refund multiple times -as it uses ``call`` which forwards all remaining gas by default: +as it uses ``call`` which does not limit the amount of gas that is forwarded by default: .. code-block:: solidity @@ -100,7 +101,7 @@ To avoid reentrancy, you can use the Checks-Effects-Interactions pattern as demo .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.6.0 <0.9.0; + pragma solidity >=0.6.2 <0.9.0; contract Fund { /// @dev Mapping of ether shares of the contract. @@ -109,7 +110,8 @@ To avoid reentrancy, you can use the Checks-Effects-Interactions pattern as demo function withdraw() public { uint share = shares[msg.sender]; shares[msg.sender] = 0; - payable(msg.sender).transfer(share); + (bool success, ) = payable(msg.sender).call{value: share}(""); + require(success); } } @@ -158,8 +160,9 @@ Sending and Receiving Ether (for example in the "details" section in Remix). - There is a way to forward more gas to the receiving contract using ``addr.call{value: x}("")``. - This is essentially the same as ``addr.transfer(x)``, only that it forwards all remaining gas - and opens up the ability for the recipient to perform more expensive actions + This is essentially the same as ``addr.transfer(x)``, only that it forwards all remaining gas, + subject to additional limits imposed by some EVM versions (such as the `63/64th rule `_ + introduced by ``tangerineWhistle``), and opens up the ability for the recipient to perform more expensive actions (and it returns a failure code instead of automatically propagating the error). This might include calling back into the sending contract or other state changes you might not have thought of. So it allows for great flexibility for honest users but also for malicious actors. @@ -255,6 +258,7 @@ Let's say you have a wallet contract like this: function transferTo(address payable dest, uint amount) public { // THE BUG IS RIGHT HERE, you must use msg.sender instead of tx.origin require(tx.origin == owner); + // This will report a warning (deprecation) dest.transfer(amount); } } diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 79ba8da6e..b07a54f45 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -680,7 +680,7 @@ shown in the following example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.6.0 <0.9.0; + pragma solidity >=0.6.2 <0.9.0; // Defines a new type with two fields. // Declaring a struct outside of a contract allows @@ -729,8 +729,8 @@ shown in the following example: return false; uint amount = c.amount; c.amount = 0; - c.beneficiary.transfer(amount); - return true; + (bool success, ) = c.beneficiary.call{value: amount}(""); + return success; } } diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 57fa7b3da..035857d7a 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -242,118 +242,148 @@ Members of Addresses For a quick reference of all members of address, see :ref:`address_related`. +.. _balance-transfer-address-members: + * ``balance`` and ``transfer`` -It is possible to query the balance of an address using the property ``balance`` -and to send Ether (in units of wei) to a payable address using the ``transfer`` function: + It is possible to query the balance of an address using the property ``balance`` + and to send Ether (in units of wei) to a payable address using the ``transfer`` function: -.. code-block:: solidity - :force: + .. code-block:: solidity + :force: - address payable x = payable(0x123); - address myAddress = address(this); - if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10); + address payable x = payable(0x123); + address myAddress = address(this); + if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10); -The ``transfer`` function fails if the balance of the current contract is not large enough -or if the Ether transfer is rejected by the receiving account. The ``transfer`` function -reverts on failure. + The ``transfer`` function fails if the balance of the current contract is not large enough + or if the Ether transfer is rejected by the receiving account. The ``transfer`` function + reverts on failure. -.. note:: - If ``x`` is a contract address, its code (more specifically: its :ref:`receive-ether-function`, if present, or otherwise its :ref:`fallback-function`, if present) will be executed together with the ``transfer`` call (this is a feature of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted and the current contract will stop with an exception. + .. note:: + If ``x`` is a contract address, its code (more specifically: its :ref:`receive-ether-function`, if present, or otherwise its :ref:`fallback-function`, if present) will be executed together with the ``transfer`` call (this is a feature of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted and the current contract will stop with an exception. + + .. warning:: + ``transfer`` is deprecated and scheduled for removal. + Simple ether transfers can still be performed using the :ref:`call function ` + with with an optionally provided maximum amount of gas and empty payload, i.e., ``call{value: }("")``. + By default this forwards all the remaining gas, subject to additional limits imposed by some EVM versions + (such as the `63/64th rule `_ introduced by ``tangerineWhistle``). + As with any external call, the ``gas`` call option can be used to set a lower limit. + + While it is possible to recreate the functionality by explicitly setting the limit to the value of the stipend (2300 gas), + this value no longer holds its original meaning due to changing opcode costs. + It is recommended to use different means to protect against reentrancy. + +.. _send-address-member: * ``send`` -``send`` is the low-level counterpart of ``transfer``. If the execution fails, the current contract will not stop with an exception, but ``send`` will return ``false``. + ``send`` is the low-level counterpart of ``transfer``. If the execution fails, the current contract will not stop with an exception, but ``send`` will return ``false``. -.. warning:: - There are some dangers in using ``send``: The transfer fails if the call stack depth is at 1024 - (this can always be forced by the caller) and it also fails if the recipient runs out of gas. So in order - to make safe Ether transfers, always check the return value of ``send``, use ``transfer`` or even better: - use a pattern where the recipient withdraws the Ether. + .. warning:: + There are some dangers in using ``send``: The transfer fails if the call stack depth is at 1024 + (this can always be forced by the caller) and it also fails if the recipient runs out of gas. So in order + to make safe Ether transfers, always check the return value of ``send``, use ``transfer`` or even better: + use a pattern where the recipient withdraws the Ether. + + .. warning:: + ``send`` is deprecated and scheduled for removal. + Simple ether transfers can still be performed using the :ref:`call function ` + with with an optionally provided maximum amount of gas and empty payload, i.e., ``call{value: }("")``. + By default this forwards all the remaining gas, subject to additional limits imposed by some EVM versions + (such as the `63/64th rule `_ introduced by ``tangerineWhistle``). + As with any external call, the ``gas`` call option can be used to set a lower limit. + + While it is possible to recreate the functionality by explicitly setting the limit to the value of the stipend (2300 gas), + this value no longer holds its original meaning due to changing opcode costs. + It is recommended to use different means to protect against reentrancy. + +.. _address_call_functions: * ``call``, ``delegatecall`` and ``staticcall`` -In order to interface with contracts that do not adhere to the ABI, -or to get more direct control over the encoding, -the functions ``call``, ``delegatecall`` and ``staticcall`` are provided. -They all take a single ``bytes memory`` parameter and -return the success condition (as a ``bool``) and the returned data -(``bytes memory``). -The functions ``abi.encode``, ``abi.encodePacked``, ``abi.encodeWithSelector`` -and ``abi.encodeWithSignature`` can be used to encode structured data. + In order to interface with contracts that do not adhere to the ABI, + or to get more direct control over the encoding, + the functions ``call``, ``delegatecall`` and ``staticcall`` are provided. + They all take a single ``bytes memory`` parameter and + return the success condition (as a ``bool``) and the returned data + (``bytes memory``). + The functions ``abi.encode``, ``abi.encodePacked``, ``abi.encodeWithSelector`` + and ``abi.encodeWithSignature`` can be used to encode structured data. -Example: + Example: -.. code-block:: solidity + .. code-block:: solidity - bytes memory payload = abi.encodeWithSignature("register(string)", "MyName"); - (bool success, bytes memory returnData) = address(nameReg).call(payload); - require(success); + bytes memory payload = abi.encodeWithSignature("register(string)", "MyName"); + (bool success, bytes memory returnData) = address(nameReg).call(payload); + require(success); -.. warning:: - All these functions are low-level functions and should be used with care. - Specifically, any unknown contract might be malicious and if you call it, you - hand over control to that contract which could in turn call back into - your contract, so be prepared for changes to your state variables - when the call returns. The regular way to interact with other contracts - is to call a function on a contract object (``x.f()``). + .. warning:: + All these functions are low-level functions and should be used with care. + Specifically, any unknown contract might be malicious and if you call it, you + hand over control to that contract which could in turn call back into + your contract, so be prepared for changes to your state variables + when the call returns. The regular way to interact with other contracts + is to call a function on a contract object (``x.f()``). -.. note:: - Previous versions of Solidity allowed these functions to receive - arbitrary arguments and would also handle a first argument of type - ``bytes4`` differently. These edge cases were removed in version 0.5.0. + .. note:: + Previous versions of Solidity allowed these functions to receive + arbitrary arguments and would also handle a first argument of type + ``bytes4`` differently. These edge cases were removed in version 0.5.0. -It is possible to adjust the supplied gas with the ``gas`` modifier: + It is possible to adjust the supplied gas with the ``gas`` modifier: -.. code-block:: solidity + .. code-block:: solidity - address(nameReg).call{gas: 1000000}(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call{gas: 1000000}(abi.encodeWithSignature("register(string)", "MyName")); -Similarly, the supplied Ether value can be controlled too: + Similarly, the supplied Ether value can be controlled too: -.. code-block:: solidity + .. code-block:: solidity - address(nameReg).call{value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call{value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); -Lastly, these modifiers can be combined. Their order does not matter: + Lastly, these modifiers can be combined. Their order does not matter: -.. code-block:: solidity + .. code-block:: solidity - address(nameReg).call{gas: 1000000, value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call{gas: 1000000, value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); -In a similar way, the function ``delegatecall`` can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. + In a similar way, the function ``delegatecall`` can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. -.. note:: - Prior to homestead, only a limited variant called ``callcode`` was available that did not provide access to the original ``msg.sender`` and ``msg.value`` values. This function was removed in version 0.5.0. + .. note:: + Prior to homestead, only a limited variant called ``callcode`` was available that did not provide access to the original ``msg.sender`` and ``msg.value`` values. This function was removed in version 0.5.0. -Since byzantium ``staticcall`` can be used as well. This is basically the same as ``call``, but will revert if the called function modifies the state in any way. + Since byzantium ``staticcall`` can be used as well. This is basically the same as ``call``, but will revert if the called function modifies the state in any way. -All three functions ``call``, ``delegatecall`` and ``staticcall`` are very low-level functions and should only be used as a *last resort* as they break the type-safety of Solidity. + All three functions ``call``, ``delegatecall`` and ``staticcall`` are very low-level functions and should only be used as a *last resort* as they break the type-safety of Solidity. -The ``gas`` option is available on all three methods, while the ``value`` option is only available -on ``call``. + The ``gas`` option is available on all three methods, while the ``value`` option is only available + on ``call``. -.. note:: - It is best to avoid relying on hardcoded gas values in your smart contract code, - regardless of whether state is read from or written to, as this can have many pitfalls. - Also, access to gas might change in the future. + .. note:: + It is best to avoid relying on hardcoded gas values in your smart contract code, + regardless of whether state is read from or written to, as this can have many pitfalls. + Also, access to gas might change in the future. * ``code`` and ``codehash`` -You can query the deployed code for any smart contract. Use ``.code`` to get the EVM bytecode as a -``bytes memory``, which might be empty. Use ``.codehash`` to get the Keccak-256 hash of that code -(as a ``bytes32``). Note that ``addr.codehash`` is cheaper than using ``keccak256(addr.code)``. + You can query the deployed code for any smart contract. Use ``.code`` to get the EVM bytecode as a + ``bytes memory``, which might be empty. Use ``.codehash`` to get the Keccak-256 hash of that code + (as a ``bytes32``). Note that ``addr.codehash`` is cheaper than using ``keccak256(addr.code)``. -.. warning:: - The output of ``addr.codehash`` may be ``0`` if the account associated with ``addr`` is empty or non-existent - (i.e., it has no code, zero balance, and zero nonce as defined by `EIP-161 `_). - If the account has no code but a non-zero balance or nonce, then ``addr.codehash`` will output the Keccak-256 hash of empty data - (i.e., ``keccak256("")`` which is equal to ``c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470``), as defined by - `EIP-1052 `_. + .. warning:: + The output of ``addr.codehash`` may be ``0`` if the account associated with ``addr`` is empty or non-existent + (i.e., it has no code, zero balance, and zero nonce as defined by `EIP-161 `_). + If the account has no code but a non-zero balance or nonce, then ``addr.codehash`` will output the Keccak-256 hash of empty data + (i.e., ``keccak256("")`` which is equal to ``c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470``), as defined by + `EIP-1052 `_. -.. note:: - All contracts can be converted to ``address`` type, so it is possible to query the balance of the - current contract using ``address(this).balance``. + .. note:: + All contracts can be converted to ``address`` type, so it is possible to query the balance of the + current contract using ``address(this).balance``. .. index:: ! contract type, ! type; contract diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index fce4cf96d..4d8fed283 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -252,6 +252,7 @@ Mathematical and Cryptographic Functions Members of Address Types ------------------------ +These members are explained in more detail in the section on :ref:`members of address `. ``
.balance`` (``uint256``) balance of the :ref:`address` in Wei @@ -268,14 +269,21 @@ Members of Address Types ``
.send(uint256 amount) returns (bool)`` send given amount of Wei to :ref:`address`, returns ``false`` on failure, forwards 2300 gas stipend, not adjustable +.. warning:: + ``send()`` and ``transfer()`` are deprecated and scheduled for removal. + See the section on :ref:`send ` and :ref:`transfer ` for more information. + ``
.call(bytes memory) returns (bool, bytes memory)`` - issue low-level ``CALL`` with the given payload, returns success condition and return data, forwards all available gas, adjustable + issue low-level ``CALL`` with the given payload, returns success condition and return data, + forwards all available gas (subject to additional limits imposed by some EVM versions), adjustable ``
.delegatecall(bytes memory) returns (bool, bytes memory)`` - issue low-level ``DELEGATECALL`` with the given payload, returns success condition and return data, forwards all available gas, adjustable + issue low-level ``DELEGATECALL`` with the given payload, returns success condition and return data, + forwards all available gas (subject to additional limits imposed by some EVM versions), adjustable ``
.staticcall(bytes memory) returns (bool, bytes memory)`` - issue low-level ``STATICCALL`` with the given payload, returns success condition and return data, forwards all available gas, adjustable + issue low-level ``STATICCALL`` with the given payload, returns success condition and return data, + forwards all available gas (subject to additional limits imposed by some EVM versions), adjustable For more information, see the section on :ref:`address`. From b60f11076417e5540d3f82a5d2bec4b67f124b42 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Fri, 22 Aug 2025 15:38:12 -0300 Subject: [PATCH 1020/1340] zeppelin ext test workaround --- test/externalTests/zeppelin.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index 99df125bb..aca8311ac 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -108,6 +108,25 @@ function zeppelin_test # Fails under evmVersion=osaka, likely due to transaction gas limits introduced by EIP-7825 or by the modexp upper bound EIP-7823. sed -i "s|describe(\('RSA'\)|describe.skip(\1|g" test/utils/cryptography/RSA.test.js + cat <<-EOF >> "$config_file" + const { TASK_COMPILE_SOLIDITY_COMPILE } = require("hardhat/builtin-tasks/task-names"); + + task(TASK_COMPILE_SOLIDITY_COMPILE) + .setAction(async (args, hre, runSuper) => { + const result = await runSuper(args); + + result.output.errors = (result.output.errors || []).filter(err => { + if (err.severity === "warning" && err.message.includes("deprecated")) { + return false; // suppress this warning + } + return true; + }); + + return result; + }); + +EOF + neutralize_package_json_hooks force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" From 809c719ff5fbfd156b72a69eaf136f3fe39e16a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 16 Oct 2025 18:55:14 +0200 Subject: [PATCH 1021/1340] Exclude docs of dependencies from the source tarball --- scripts/create_source_tarball.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/create_source_tarball.sh b/scripts/create_source_tarball.sh index 9ccbec222..dd21612f9 100755 --- a/scripts/create_source_tarball.sh +++ b/scripts/create_source_tarball.sh @@ -43,6 +43,11 @@ git checkout-index --all --prefix="$SOLDIR" # shellcheck disable=SC2016 SOLDIR="$SOLDIR" git submodule foreach 'git checkout-index --all --prefix="${SOLDIR}/${sm_path}/"' +# Documentation is pretty heavy and not necessary to build the compiler. +# Especially nlohmann-json has several huge images, which blow up the size of the compressed tarball. +# shellcheck disable=SC2016 +SOLDIR="$SOLDIR" git submodule foreach 'rm -rf "${SOLDIR}/${sm_path}/"doc/; rm -rf "${SOLDIR}/${sm_path}/"docs/' + # Include the commit hash and prerelease suffix in the tarball echo "$commit_hash" > "${SOLDIR}/commit_hash.txt" [[ -e prerelease.txt ]] && cp prerelease.txt "${SOLDIR}/" From 11083858f8b51f3774dbd8296eab5dfd35c79b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 3 Dec 2025 02:50:28 +0100 Subject: [PATCH 1022/1340] ReleaseChecklist: Update the requirements for docker releases --- ReleaseChecklist.md | 3 ++- scripts/docker_deploy_manual.sh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 4eada5f65..0449dce26 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -3,7 +3,8 @@ ## Requirements - [ ] GitHub account with access to [solidity](https://github.com/argotorg/solidity), [solc-js](https://github.com/argotorg/solc-js), [solc-bin](https://github.com/argotorg/solc-bin), [solidity-website](https://github.com/argotorg/solidity-website). -- [ ] DockerHub account with push rights to the [`solc` image](https://hub.docker.com/r/ethereum/solc). +- [ ] Personal Access Token (PAT) with `write:packages` scope to access Github's container registry. + You can generate one by visiting https://github.com/settings/tokens/new?scopes=write:packages. - [ ] Ubuntu/Debian dependencies of the Docker script: `docker-buildx`. - [ ] [npm Registry](https://www.npmjs.com) account added as a collaborator for the [`solc` package](https://www.npmjs.com/package/solc). - [ ] Access to the [solidity_lang Twitter account](https://twitter.com/solidity_lang). diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index c17119ce0..715147765 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -25,7 +25,7 @@ fi # NOTE: Login to GHCR before running this script with a PAT: # echo $GHCR_TOKEN | docker login ghcr.io -u USERNAME --password-stdin # -# Create a classic PAT with write:packages scope only visiting the following url: +# Create a classic PAT with write:packages scope by visiting the following URL: # https://github.com/settings/tokens/new?scopes=write:packages DIR=$(mktemp -d) From 032d0bfecd105a4ef0f6109cf1b6e88342850f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 3 Dec 2025 02:51:26 +0100 Subject: [PATCH 1023/1340] ReleaseChecklist: Remove checkboxes from requirements - This is not something we go through during a release so we never check them anyway. --- ReleaseChecklist.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 0449dce26..b78edc2de 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -1,14 +1,14 @@ # Checklist for making a Solidity release ## Requirements -- [ ] GitHub account with access to [solidity](https://github.com/argotorg/solidity), [solc-js](https://github.com/argotorg/solc-js), +- GitHub account with access to [solidity](https://github.com/argotorg/solidity), [solc-js](https://github.com/argotorg/solc-js), [solc-bin](https://github.com/argotorg/solc-bin), [solidity-website](https://github.com/argotorg/solidity-website). -- [ ] Personal Access Token (PAT) with `write:packages` scope to access Github's container registry. +- Personal Access Token (PAT) with `write:packages` scope to access Github's container registry. You can generate one by visiting https://github.com/settings/tokens/new?scopes=write:packages. -- [ ] Ubuntu/Debian dependencies of the Docker script: `docker-buildx`. -- [ ] [npm Registry](https://www.npmjs.com) account added as a collaborator for the [`solc` package](https://www.npmjs.com/package/solc). -- [ ] Access to the [solidity_lang Twitter account](https://twitter.com/solidity_lang). -- [ ] [Reddit](https://www.reddit.com) account that is at least 10 days old with a minimum of 20 comment karma (`/r/ethereum` requirements). +- Ubuntu/Debian dependencies of the Docker script: `docker-buildx`. +- [npm Registry](https://www.npmjs.com) account added as a collaborator for the [`solc` package](https://www.npmjs.com/package/solc). +- Access to the [solidity_lang Twitter account](https://twitter.com/solidity_lang). +- [Reddit](https://www.reddit.com) account that is at least 10 days old with a minimum of 20 comment karma (`/r/ethereum` requirements). ## Full release From 28ca8e62a0673a5f6ee36065e3dca7d01c80c6fb Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Sat, 15 Mar 2025 12:09:55 -0300 Subject: [PATCH 1024/1340] Update and add tests --- .../storageLayoutSpecifier/abi_decode.sol | 2 +- .../storageLayoutSpecifier/address.sol | 2 +- .../storageLayoutSpecifier/address_constant.sol | 6 ++++++ .../storageLayoutSpecifier/array_literal.sol | 2 +- .../bitwise_negation_after_cast.sol | 2 +- .../storageLayoutSpecifier/bool_constant.sol | 4 ++++ .../storageLayoutSpecifier/boolean.sol | 2 +- .../storageLayoutSpecifier/bytes_constant.sol | 6 ++++++ .../constant_divided_by_its_negation.sol | 2 +- .../constant_divided_by_zero.sol | 2 +- .../constant_from_base_contract.sol | 2 +- .../constant_from_module.sol | 8 ++++++++ .../constant_initialized_from_builtin.sol | 7 +++++++ .../constant_initialized_from_cast.sol | 4 ++++ ...constant_initialized_from_other_constant.sol | 4 ++++ ...tant_initialized_with_literal_expression.sol | 3 +++ ...zed_with_unlimited_arithmetic_expression.sol | 7 +++++++ .../syntaxTests/storageLayoutSpecifier/enum.sol | 2 +- .../function_defined_in_other_contract.sol | 2 +- .../function_selector.sol | 2 +- .../storageLayoutSpecifier/hex_address.sol | 2 +- .../storageLayoutSpecifier/hex_string.sol | 2 +- .../storageLayoutSpecifier/hex_string_cast.sol | 2 +- .../storageLayoutSpecifier/immutables.sol | 17 +++++++++++++++++ .../storageLayoutSpecifier/int_constant.sol | 7 +++++++ .../layout_specification_bytes.sol | 2 +- ...out_specification_constant_in_expression.sol | 1 - .../layout_specified_by_interface_id.sol | 2 +- .../layout_specified_by_module.sol | 2 +- .../layout_specified_by_other_contract.sol | 2 +- .../layout_specified_by_type.sol | 2 +- .../storageLayoutSpecifier/literal_cast.sol | 2 +- .../storageLayoutSpecifier/precompiles.sol | 4 ++-- ...rational_number_without_fractional_part.sol} | 1 + .../storageLayoutSpecifier/string.sol | 2 +- .../storageLayoutSpecifier/ternary_operator.sol | 4 ++-- .../storageLayoutSpecifier/tuple.sol | 2 +- .../storageLayoutSpecifier/type_uint_max.sol | 2 +- .../user_defined_value_type.sol | 2 +- .../user_defined_value_type_unwrap.sol | 2 +- .../user_defined_value_type_wrap.sol | 2 +- .../value_from_array_literal.sol | 4 ++-- .../storageLayoutSpecifier/value_from_bytes.sol | 2 +- 43 files changed, 107 insertions(+), 34 deletions(-) create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/address_constant.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/bool_constant.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_constant.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_module.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_builtin.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_cast.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_other_constant.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_literal_expression.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_unlimited_arithmetic_expression.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/immutables.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/int_constant.sol rename test/libsolidity/syntaxTests/storageLayoutSpecifier/{rational_number_zero_fractional_part.sol => rational_number_without_fractional_part.sol} (70%) diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol index 920e8d252..498e39abf 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/abi_decode.sol @@ -1,3 +1,3 @@ contract C layout at abi.decode(abi.encode(42), (uint)) {} // ---- -// TypeError 6396: (21-55): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (21-55): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol index fded26fad..b351ab009 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address.sol @@ -1,3 +1,3 @@ contract C layout at address(0x1234) {} // ---- -// TypeError 6396: (21-36): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (21-36): The base slot of the storage layout must evaluate to an integer (the type is 'address' instead). diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_constant.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_constant.sol new file mode 100644 index 000000000..3eda177fc --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_constant.sol @@ -0,0 +1,6 @@ +address constant x = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; +contract C layout at x { + +} +// ---- +// TypeError 1763: (86-87): The base slot of the storage layout must evaluate to an integer (the type is 'address' instead). diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol index af6b9424f..56b5f0971 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/array_literal.sol @@ -1,3 +1,3 @@ contract C layout at [1, 2, 3] {} // ---- -// TypeError 6396: (21-30): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (21-30): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol index 6ccb2ff7a..6c7cd0efb 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bitwise_negation_after_cast.sol @@ -1,3 +1,3 @@ contract C layout at ~uint(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {} // ---- -// TypeError 6396: (21-94): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (21-94): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bool_constant.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bool_constant.sol new file mode 100644 index 000000000..e4835ca77 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bool_constant.sol @@ -0,0 +1,4 @@ +bool constant x = false; +contract C layout at x {} +// ---- +// TypeError 1763: (46-47): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol index 083977c7a..5391cee68 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/boolean.sol @@ -1,3 +1,3 @@ contract C layout at true {} // ---- -// TypeError 6396: (21-25): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (21-25): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_constant.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_constant.sol new file mode 100644 index 000000000..ce4e252a0 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/bytes_constant.sol @@ -0,0 +1,6 @@ +bytes32 constant CONST1 = "12345"; +contract A layout at CONST1 {} +contract C layout at CONST1[1] {} +// ---- +// TypeError 1763: (56-62): The base slot of the storage layout must evaluate to an integer (the type is 'bytes32' instead). +// TypeError 1763: (87-96): The base slot of the storage layout must evaluate to an integer (the type is 'bytes1' instead). diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol index b9cdd9dfa..9f8acbeb6 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_its_negation.sol @@ -1,4 +1,4 @@ uint constant N = 100; contract C layout at N / ~N {} // ---- -// TypeError 6396: (44-50): The base slot of the storage layout must evaluate to a rational number. +// TypeError 3667: (48-50): Arithmetic error when computing constant value. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol index bb97172d9..e3ba099a1 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_divided_by_zero.sol @@ -1,4 +1,4 @@ uint constant N = 100; contract C layout at N / 0 {} // ---- -// TypeError 6396: (44-49): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (44-49): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol index e06deeaaf..1a0bd451b 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_base_contract.sol @@ -4,4 +4,4 @@ contract A { contract C is A layout at A.x { } // ---- -// TypeError 6396: (68-71): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (68-71): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_module.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_module.sol new file mode 100644 index 000000000..8be06de6c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_from_module.sol @@ -0,0 +1,8 @@ +==== Source: A ==== +uint constant x = 77; + +==== Source: B ==== +import "A" as M; +contract C layout at M.x{ } +// ---- +// TypeError 1505: (B:38-41): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_builtin.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_builtin.sol new file mode 100644 index 000000000..a95cb5609 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_builtin.sol @@ -0,0 +1,7 @@ +uint constant x = addmod(10, 2, 8); +uint constant y = mulmod(10, 2, 8); +contract C layout at x {} +contract D layout at y {} +// ---- +// TypeError 1505: (93-94): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. +// TypeError 1505: (119-120): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_cast.sol new file mode 100644 index 000000000..fd75c94a4 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_cast.sol @@ -0,0 +1,4 @@ +uint constant x = uint(42); +contract C layout at x {} +// ---- +// TypeError 1505: (49-50): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_other_constant.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_other_constant.sol new file mode 100644 index 000000000..1b135b32b --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_from_other_constant.sol @@ -0,0 +1,4 @@ +uint constant x = 42; +uint constant y = x * 2; +contract C layout at y {} +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_literal_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_literal_expression.sol new file mode 100644 index 000000000..1a06c0198 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_literal_expression.sol @@ -0,0 +1,3 @@ +uint constant x = ((2**5 + 2**5) * (2 ** 10 + 1 << 1)) % 2**256 - 1; +contract C layout at x {} +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_unlimited_arithmetic_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_unlimited_arithmetic_expression.sol new file mode 100644 index 000000000..98c133e16 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_unlimited_arithmetic_expression.sol @@ -0,0 +1,7 @@ +uint constant CONST1 = 1.23e100 / 2e50; +contract C layout at CONST1 {} +uint constant CONST2 = 2**256 * (500e-3); +contract D layout at CONST2 {} +uint constant CONST3 = (2**255 * 2) - (2**256 + 1) + 1; +contract E layout at CONST3 {} +// ---- \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol index 9a264247c..8c995bec7 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/enum.sol @@ -2,4 +2,4 @@ enum Color {Red, Green, Blue} contract C layout at Color.Red {} // ---- -// TypeError 6396: (52-61): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (52-61): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol index 68b2e2460..e7a6f1178 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_defined_in_other_contract.sol @@ -4,4 +4,4 @@ contract A { contract C layout at A.f { } // ---- -// TypeError 6396: (71-74): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (71-74): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol index 98c7b6057..98ebfb775 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/function_selector.sol @@ -3,4 +3,4 @@ contract A { } contract C is A layout at uint32(this.f.selector) {} // ---- -// TypeError 6396: (68-91): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (68-91): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol index 9e63740d8..f403c91be 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_address.sol @@ -1,3 +1,3 @@ contract C layout at 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF {} // ---- -// TypeError 6396: (21-63): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (21-63): The base slot of the storage layout must evaluate to an integer (the type is 'address' instead). diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol index 194f0df0e..e3bca428a 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string.sol @@ -1,3 +1,3 @@ contract C layout at hex"616263" {} // ---- -// TypeError 6396: (21-32): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (21-32): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol index a803d005f..b807f2829 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/hex_string_cast.sol @@ -1,3 +1,3 @@ contract at layout at uint40(bytes5(hex"0011223344")) { } // ---- -// TypeError 6396: (22-53): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (22-53): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/immutables.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/immutables.sol new file mode 100644 index 000000000..065d6290c --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/immutables.sol @@ -0,0 +1,17 @@ +function f() returns (uint) { + return 2; +} + +contract A { + address immutable a = 0x0000000000000000000000000000000000000001; + uint immutable x = 1; // considered pure by the compiler (initialized with a literal) + uint immutable y = f(); // considered not pure by the compiler (initialized with a function) +} + +contract B is A layout at A.a { } +contract C is A layout at A.x { } +contract D is A layout at A.y { } +// ---- +// TypeError 1139: (346-349): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (380-383): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1139: (414-417): The base slot of the storage layout must be a compile-time constant expression. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/int_constant.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/int_constant.sol new file mode 100644 index 000000000..1299f1347 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/int_constant.sol @@ -0,0 +1,7 @@ +int constant x = -42; +int constant y = 64; +contract C layout at x {} +contract D layout at y {} +// ---- +// TypeError 6753: (64-65): The base slot of the storage layout evaluates to -42, which is outside the range of type uint256. +// TypeError 1481: (90-91): Base slot expression of type 'int256' is not convertible to uint256. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol index 6f9b39703..b386d5e51 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_bytes.sol @@ -1,4 +1,4 @@ bytes32 constant b = "bytes"; contract A layout at b[1] {} // ---- -// TypeError 6396: (51-55): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (51-55): The base slot of the storage layout must evaluate to an integer (the type is 'bytes1' instead). diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol index 8e6d37ad6..2f0891e86 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specification_constant_in_expression.sol @@ -1,4 +1,3 @@ uint constant X = 42; contract C layout at 0xffff * (50 - X) { } // ---- -// TypeError 6396: (43-60): The base slot of the storage layout must evaluate to a rational number. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol index 12304ba8a..a48172d40 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_interface_id.sol @@ -2,4 +2,4 @@ interface I {} contract C layout at uint(bytes32(type(I).interfaceId)) { } // ---- -// TypeError 6396: (37-71): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (37-71): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol index ee4807304..639527500 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_module.sol @@ -6,4 +6,4 @@ import "A" as MyModule; contract C layout at MyModule {} // ---- -// TypeError 6396: (B:46-54): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (B:46-54): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol index 035e43d24..12589208f 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_other_contract.sol @@ -1,4 +1,4 @@ contract A {} contract C layout at A(address(0x1234)) {} // ---- -// TypeError 6396: (35-53): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (35-53): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol index 4d48e410f..225336b67 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_type.sol @@ -1,3 +1,3 @@ contract A layout at uint {} // ---- -// TypeError 6396: (21-25): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (21-25): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol index 0f682d779..067e23cf4 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/literal_cast.sol @@ -1,3 +1,3 @@ contract at layout at uint(42) { } // ---- -// TypeError 6396: (22-30): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (22-30): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol index c87a98eaa..f8f876207 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/precompiles.sol @@ -1,5 +1,5 @@ contract A layout at addmod(1, 2, 3) {} contract B layout at mulmod(3, 2, 1) {} // ---- -// TypeError 6396: (21-36): The base slot of the storage layout must evaluate to a rational number. -// TypeError 6396: (61-76): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (21-36): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. +// TypeError 1505: (61-76): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_without_fractional_part.sol similarity index 70% rename from test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol rename to test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_without_fractional_part.sol index e21521e39..216a9dc1e 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_zero_fractional_part.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/rational_number_without_fractional_part.sol @@ -1,3 +1,4 @@ contract A layout at 42.0 {} contract B layout at 2.5e10 {} +contract C layout at 12/3 {} // ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol index 3b8292fe8..a6686af39 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/string.sol @@ -1,3 +1,3 @@ contract C layout at "MyLayoutBase" {} // ---- -// TypeError 6396: (21-35): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (21-35): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol index f426104cc..d73bd2890 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/ternary_operator.sol @@ -1,5 +1,5 @@ contract A layout at true ? 42 : 94 {} contract B layout at 255 + (true ? 1 : 0) {} // ---- -// TypeError 6396: (21-35): The base slot of the storage layout must evaluate to a rational number. -// TypeError 6396: (60-80): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (21-35): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. +// TypeError 1505: (60-80): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol index eb4693e48..73d1fec74 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/tuple.sol @@ -1,3 +1,3 @@ contract C layout at (1, 2, 3) {} // ---- -// TypeError 6396: (21-30): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (21-30): The base slot of the storage layout must evaluate to an integer. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol index dd8ee6f9c..6f53097c5 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/type_uint_max.sol @@ -1,3 +1,3 @@ contract at layout at type(uint).max { } // ---- -// TypeError 6396: (22-36): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (22-36): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol index 980364168..3e721a399 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type.sol @@ -2,4 +2,4 @@ type MyUint is uint128; MyUint constant x = MyUint.wrap(42); contract C layout at x {} // ---- -// TypeError 6396: (82-83): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (82-83): The base slot of the storage layout must evaluate to an integer (the type is 'MyUint' instead). diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol index b45ee88dd..a4ba0a802 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_unwrap.sol @@ -2,4 +2,4 @@ type MyUint is uint128; MyUint constant x = MyUint.wrap(42); contract C layout at MyUint.unwrap(x) {} // ---- -// TypeError 6396: (82-98): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (82-98): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol index 172fb58ab..4f3d8f883 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/user_defined_value_type_wrap.sol @@ -1,4 +1,4 @@ type MyUint is uint128; contract C layout at MyUint.wrap(42) {} // ---- -// TypeError 6396: (45-60): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1763: (45-60): The base slot of the storage layout must evaluate to an integer (the type is 'MyUint' instead). diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol index bb56de728..929b9d088 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_array_literal.sol @@ -1,5 +1,5 @@ contract A layout at [1, 2, 3][0] {} contract B layout at 255 + [1, 2, 3][0] {} // ---- -// TypeError 6396: (21-33): The base slot of the storage layout must evaluate to a rational number. -// TypeError 6396: (58-76): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (21-33): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. +// TypeError 1505: (58-76): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol index 1f08fa0ec..8c6dfea77 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/value_from_bytes.sol @@ -1,4 +1,4 @@ bytes32 constant b = "Solidity"; contract C layout at uint8(b[1]) {} // ---- -// TypeError 6396: (54-65): The base slot of the storage layout must evaluate to a rational number. +// TypeError 1505: (54-65): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. From 6300a440cf1ecc2407bb456be3700a36060b2325 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Sat, 15 Mar 2025 12:10:44 -0300 Subject: [PATCH 1025/1340] Allow constants in custom storage layout expression --- Changelog.md | 2 + docs/contracts/custom-storage-layout.rst | 1 + .../analysis/PostTypeContractLevelChecker.cpp | 80 ++++++++++++++++--- .../address_constant.sol | 4 +- ...d_with_unlimited_arithmetic_expression.sol | 2 +- 5 files changed, 72 insertions(+), 17 deletions(-) diff --git a/Changelog.md b/Changelog.md index ba3e76659..0a35b2a87 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: * Yul: Introduce builtin `clz(x)` for counting the number of leading zero bits in a 256-bit word. Compiler Features: +* Custom Storage Layout: Allow using `constant` state variables in the base slot expression. * ethdebug: Experimental support for instructions and source locations under EOF. * EVM: Set default EVM Version to `osaka`. * DocString Parser: Warn about deprecation of inline assembly special comment `memory-safe-assembly`. @@ -12,6 +13,7 @@ Compiler Features: * Type Checker: Warn about deprecation of `send` and `transfer` functions on instances of `address`. * Type Checker: Warn about deprecation of comparisons between variables of contract types. + Bugfixes: * Assembler: Fix not using a fixed-width type for IDs being assigned to subassemblies nested more than one level away, resulting in inconsistent `--asm-json` output between target architectures. * Yul Optimizer: Fix edge case in which invalid Yul code is produced by ExpressionSimplifier due to expressions being substituted that contain out-of-scope variables. diff --git a/docs/contracts/custom-storage-layout.rst b/docs/contracts/custom-storage-layout.rst index 224e77425..72f281d7f 100644 --- a/docs/contracts/custom-storage-layout.rst +++ b/docs/contracts/custom-storage-layout.rst @@ -25,6 +25,7 @@ and is located in the header of a contract definition. The layout specifier can be placed either before or after the inheritance specifier, and can appear at most once. The ``base-slot-expression`` must be an :ref:`integer literal` expression that can be evaluated at compilation time and yields a value in the range of ``uint256``. +The use of constants initialized using such expressions is also allowed. A custom layout cannot make contract's storage "wrap around". If the selected base slot would push the static variables past the end of storage, diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.cpp b/libsolidity/analysis/PostTypeContractLevelChecker.cpp index c7b7b0961..f8f4b6ef6 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.cpp +++ b/libsolidity/analysis/PostTypeContractLevelChecker.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -101,29 +102,71 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinitio } auto const* baseSlotExpressionType = type(baseSlotExpression); + auto const* integerType = dynamic_cast(baseSlotExpressionType); auto const* rationalType = dynamic_cast(baseSlotExpressionType); - if (!rationalType) + if ( + !integerType && + !rationalType + ) { + std::string errorMsg = "The base slot of the storage layout must evaluate to an integer"; + if (dynamic_cast(baseSlotExpressionType)) + errorMsg += " (the type is 'address' instead)"; + else if (auto const* fixedBytesType = dynamic_cast(baseSlotExpressionType)) + errorMsg += fmt::format( + " (the type is 'bytes{}' instead)", + fixedBytesType->numBytes() + ) + ; + else if (auto const* userDefinedType = dynamic_cast(baseSlotExpressionType)) + errorMsg += fmt::format( + " (the type is '{}' instead)", + userDefinedType->canonicalName() + ) + ; + errorMsg += "."; + m_errorReporter.typeError( - 6396_error, + 1763_error, baseSlotExpression.location(), - "The base slot of the storage layout must evaluate to a rational number." + errorMsg ); return; } - if (rationalType->isFractional()) + rational baseSlotRationalValue; + if (integerType) { - m_errorReporter.typeError( - 1763_error, - baseSlotExpression.location(), - "The base slot of the storage layout must evaluate to an integer." - ); - return; + std::optional typedRational = ConstantEvaluator::evaluate(m_errorReporter, baseSlotExpression); + if (!typedRational) + { + m_errorReporter.typeError( + 1505_error, + baseSlotExpression.location(), + "The base slot expression contains elements that are not yet supported " + "by the internal constant evaluator and therefore cannot be evaluated at compilation time." + ); + return; + } + baseSlotRationalValue = typedRational->value; + } + else + { + solAssert(rationalType); + if (rationalType->isFractional()) + { + m_errorReporter.typeError( + ErrorId{1763}, + baseSlotExpression.location(), + "The base slot of the storage layout must evaluate to an integer." + ); + return; + } + baseSlotRationalValue = rationalType->value(); } - solAssert(rationalType->value().denominator() == 1); - bigint baseSlot = rationalType->value().numerator(); + solAssert(baseSlotRationalValue.denominator() == 1); + bigint baseSlot = baseSlotRationalValue.numerator(); if (!(0 <= baseSlot && baseSlot <= std::numeric_limits::max())) { m_errorReporter.typeError( @@ -137,7 +180,18 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinitio return; } - solAssert(baseSlotExpressionType->isImplicitlyConvertibleTo(*TypeProvider::uint256())); + if (!baseSlotExpressionType->isImplicitlyConvertibleTo(*TypeProvider::uint256())) + { + m_errorReporter.typeError( + 1481_error, + baseSlotExpression.location(), + fmt::format( + "Base slot expression of type '{}' is not convertible to uint256.", + baseSlotExpressionType->humanReadableName() + ) + ); + return; + } storageLayoutSpecifier->annotation().baseSlot = u256(baseSlot); bigint size = contractStorageSizeUpperBound(_contract, VariableDeclaration::Location::Unspecified); diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_constant.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_constant.sol index 3eda177fc..da9449b67 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_constant.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/address_constant.sol @@ -1,6 +1,4 @@ address constant x = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; -contract C layout at x { - -} +contract C layout at x {} // ---- // TypeError 1763: (86-87): The base slot of the storage layout must evaluate to an integer (the type is 'address' instead). diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_unlimited_arithmetic_expression.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_unlimited_arithmetic_expression.sol index 98c133e16..926bff554 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_unlimited_arithmetic_expression.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/constant_initialized_with_unlimited_arithmetic_expression.sol @@ -4,4 +4,4 @@ uint constant CONST2 = 2**256 * (500e-3); contract D layout at CONST2 {} uint constant CONST3 = (2**255 * 2) - (2**256 + 1) + 1; contract E layout at CONST3 {} -// ---- \ No newline at end of file +// ---- From 67abe75d44735b3d6b852c790e49e01d94797cb4 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 2 Dec 2025 22:56:11 -0300 Subject: [PATCH 1026/1340] sort changelog v.0.8.31 --- Changelog.md | 7 +++++-- docs/bugs_by_version.json | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index 0a35b2a87..a75193adb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,13 +1,14 @@ -### 0.8.31 (unreleased) +### 0.8.31 (2025-12-03) Language Features: * Yul: Introduce builtin `clz(x)` for counting the number of leading zero bits in a 256-bit word. + Compiler Features: * Custom Storage Layout: Allow using `constant` state variables in the base slot expression. +* DocString Parser: Warn about deprecation of inline assembly special comment `memory-safe-assembly`. * ethdebug: Experimental support for instructions and source locations under EOF. * EVM: Set default EVM Version to `osaka`. -* DocString Parser: Warn about deprecation of inline assembly special comment `memory-safe-assembly`. * Syntax Checker: Warn about deprecation of ABI coder v1. * Syntax Checker: Warn about deprecation of virtual modifiers. * Type Checker: Warn about deprecation of `send` and `transfer` functions on instances of `address`. @@ -18,11 +19,13 @@ Bugfixes: * Assembler: Fix not using a fixed-width type for IDs being assigned to subassemblies nested more than one level away, resulting in inconsistent `--asm-json` output between target architectures. * Yul Optimizer: Fix edge case in which invalid Yul code is produced by ExpressionSimplifier due to expressions being substituted that contain out-of-scope variables. + Build System: * Enable Linux arm64 binaries for testing and releases. * Ubuntu PPA Packages: Discontinue the PPA as a binary distribution channel. * Update minimum version requirements of Boost to 1.83.0 for non-windows builds and of GCC and Clang to 13.3 and 18.1.3, respectively. Fixes infinite recursion on `boost::rational` comparison affecting compiler binaries built with GCC<14.0 and Boost<1.75. + ### 0.8.30 (2025-05-07) Compiler Features: diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 1a210b885..881f5eabe 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1927,6 +1927,10 @@ "bugs": [], "released": "2025-05-07" }, + "0.8.31": { + "bugs": [], + "released": "2025-12-03" + }, "0.8.4": { "bugs": [ "FullInlinerNonExpressionSplitArgumentEvaluationOrder", From 886bf48051632d01b745aa8f542b965276454e57 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 2 Dec 2025 16:11:56 -0300 Subject: [PATCH 1027/1340] Set version to 0.8.32 --- CMakeLists.txt | 2 +- Changelog.md | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e477cf3a..f4d67e243 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.31") +set(PROJECT_VERSION "0.8.32") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index a75193adb..5cd6133f2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,12 @@ +### 0.8.32 (unreleased) + +Language Features: + +Compiler Features: + +Bugfixes: + + ### 0.8.31 (2025-12-03) Language Features: From b7ce492bb651f1f80d5d5a4d675d97972387e70b Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Wed, 3 Dec 2025 16:35:56 -0300 Subject: [PATCH 1028/1340] Move changelog entries to correct section --- Changelog.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Changelog.md b/Changelog.md index 5cd6133f2..1aa6bc64b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,18 +10,18 @@ Bugfixes: ### 0.8.31 (2025-12-03) Language Features: -* Yul: Introduce builtin `clz(x)` for counting the number of leading zero bits in a 256-bit word. - - -Compiler Features: * Custom Storage Layout: Allow using `constant` state variables in the base slot expression. * DocString Parser: Warn about deprecation of inline assembly special comment `memory-safe-assembly`. -* ethdebug: Experimental support for instructions and source locations under EOF. -* EVM: Set default EVM Version to `osaka`. * Syntax Checker: Warn about deprecation of ABI coder v1. * Syntax Checker: Warn about deprecation of virtual modifiers. * Type Checker: Warn about deprecation of `send` and `transfer` functions on instances of `address`. * Type Checker: Warn about deprecation of comparisons between variables of contract types. +* Yul: Introduce builtin `clz(x)` for counting the number of leading zero bits in a 256-bit word. + + +Compiler Features: +* ethdebug: Experimental support for instructions and source locations under EOF. +* EVM: Set default EVM Version to `osaka`. Bugfixes: From ec00d77b89dae6444ef689d2c6c7b21a1c19f638 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:53:06 -0300 Subject: [PATCH 1029/1340] Update release checklist with docker login info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- ReleaseChecklist.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index b78edc2de..9c3b2f896 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -42,6 +42,7 @@ At least a day before the release: - [ ] Get the posts reviewed and approved **before the release starts**. ### Changelog +- [ ] Ensure that all changelog entries are correctly classified as language or compiler features. - [ ] Sort the changelog entries alphabetically and correct any errors you notice. Commit it. - [ ] Update the changelog to include a release date. - [ ] Run `scripts/update_bugs_by_version.py` to regenerate `bugs_by_version.json` from the changelog and `bugs.json`. @@ -76,6 +77,7 @@ At least a day before the release: ### Docker - [ ] Make sure `docker-buildx` is installed. +- [ ] Run `echo $GHCR_TOKEN | docker login ghcr.io --username $GH_USERNAME --password-stdin` where `$GH_USERNAME` is your GitHub username and `$GHCR_TOKEN` is a PAT with `write:packages` scope. - [ ] Run `./scripts/docker_deploy_manual.sh v$VERSION`. ### Release solc-js From 7b39f83127382f9fb057567cc04035cd838e5627 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 4 Dec 2025 15:09:49 -0300 Subject: [PATCH 1030/1340] Copy libevmone to Linux ARM machine --- scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm index a24549d4b..663928220 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm @@ -22,7 +22,7 @@ # (c) 2016-2025 solidity contributors. #------------------------------------------------------------------------------ FROM --platform=linux/arm64 buildpack-deps:noble AS base -LABEL version="1" +LABEL version="2" ARG DEBIAN_FRONTEND=noninteractive @@ -104,6 +104,7 @@ RUN <<-EOF EOF FROM base +COPY --from=libraries /usr/local/lib/libevmone* /usr/lib COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin COPY --from=libraries /usr/include /usr/include From 6ac7d73b23d9e7b1c6fbb02fcd1cde77537bd2e3 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Thu, 4 Dec 2025 18:33:31 -0300 Subject: [PATCH 1031/1340] Disable partial clone and fetch all objects on alpine --- .circleci/config.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6255d2834..6109d0561 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1931,6 +1931,12 @@ jobs: # This job is only meant to run nightly so build time is not an issue. docker_layer_caching: false - checkout + - run: + name: Disable partial clone and fetch all objects + command: | + git config remote.origin.promisor false + git config --unset remote.origin.partialclonefilter + git fetch --refetch origin - run: name: Build and tag the container command: scripts/docker_deploy_manual.sh develop "file://$PWD" --no-push From 37653a0f95d4c3330e3d2564cd77946b963043dd Mon Sep 17 00:00:00 2001 From: blishko Date: Fri, 5 Dec 2025 11:24:57 +0100 Subject: [PATCH 1032/1340] SMTChecker: Use Eldarica in more tests Eldarica is more reliable on Z3 and results in fewer differences of behaviour across different platforms. The disadvantage is that Eldarica often takes longer to solve the problems than Z3. --- .../external_calls/external_call_indirect_2.sol | 2 +- .../external_calls/external_call_indirect_5.sol | 1 + .../smtCheckerTests/functions/functions_external_2.sol | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol index 16779bb89..d6575fdc2 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_2.sol @@ -47,7 +47,7 @@ contract C { // ==== // SMTEngine: chc // SMTExtCalls: trusted -// SMTIgnoreOS: macos +// SMTSolvers: eld // ---- // Warning 6328: (434-455): CHC: Assertion violation happens here. // Warning 6328: (1270-1291): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol index 26d39838e..da3077c84 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_call_indirect_5.sol @@ -46,6 +46,7 @@ contract C { // SMTContract: C // SMTEngine: chc // SMTExtCalls: trusted +// SMTSolvers: eld // ---- // Warning 6328: (601-622): CHC: Assertion violation happens here. // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol b/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol index d3373b62d..cbac9fbbb 100644 --- a/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol +++ b/test/libsolidity/smtCheckerTests/functions/functions_external_2.sol @@ -20,9 +20,9 @@ contract C } } // ==== -// SMTEngine: all +// SMTEngine: chc // SMTIgnoreCex: yes -// SMTIgnoreOS: macos +// SMTSolvers: eld // ---- // Warning 6328: (234-253): CHC: Assertion violation happens here. // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From bdf3c50ea0229d086e6b38a1c520f45204a36ca7 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Fri, 5 Dec 2025 19:08:54 -0300 Subject: [PATCH 1033/1340] Update fmtlib to 12.1.0 --- deps/fmtlib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/fmtlib b/deps/fmtlib index 40626af88..407c905e4 160000 --- a/deps/fmtlib +++ b/deps/fmtlib @@ -1 +1 @@ -Subproject commit 40626af88bd7df9a5fb80be7b25ac85b122d6c21 +Subproject commit 407c905e45ad75fc29bf0f9bb7c5c2fd3475976f From e0773b9fadc5cd6fcf718314ce511500501f8a56 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 2 Dec 2025 23:21:47 -0300 Subject: [PATCH 1034/1340] run soltest and cli tests on arm --- .circleci/config.yml | 49 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6109d0561..8c7a56018 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -701,6 +701,11 @@ defaults: requires: - b_ubu_static + - requires_b_ubu_static_arm: &requires_b_ubu_static_arm + <<: *on_all_tags_and_branches + requires: + - b_ubu_static_arm + - requires_b_archlinux: &requires_b_archlinux <<: *on_all_tags_and_branches requires: @@ -1104,7 +1109,7 @@ jobs: - solc/solc-static-linux - matrix_notify_failure_unless_pr - b_ubu_static_arm: + b_ubu_static_arm: &b_ubu_static_arm <<: *base_ubuntu2404_arm_large environment: <<: *base_ubuntu2404_arm_large_env @@ -1293,6 +1298,28 @@ jobs: steps: - soltest_all + t_ubu_arm_soltest: &t_ubu_arm_soltest + <<: *base_ubuntu2404_arm_medium + parallelism: 20 + environment: + <<: *base_ubuntu2404_arm_medium_env + EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 + OPTIMIZE: 0 + steps: + - checkout + - attach_workspace: + at: build + - run: + name: Create symbolic link with expected soltest binary name + command: | + ln --symbolic --relative build/test/soltest-linux-arm build/test/soltest + - run_soltest + - store_test_results: + path: test_results/ + - store_artifacts_test_results + - matrix_notify_failure_unless_pr + t_ubu_soltest_deprecated_evm_versions: &t_ubu_soltest_deprecated_evm_versions <<: *base_ubuntu2404_large parallelism: 50 @@ -1355,6 +1382,24 @@ jobs: steps: - cmdline_tests + t_ubu_arm_cli: &t_ubu_arm_cli + <<: *base_ubuntu2404_arm_medium + parallelism: 8 # Should match number of tests in .circleci/parallel_cli_tests.py + steps: + - checkout + - attach_workspace: + at: build + - run: + name: Create symbolic link with expected solc and solfuzzer binaries name + command: | + ln --symbolic --relative build/solc/solc-static-linux-arm build/solc/solc + ln --symbolic --relative build/test/tools/solfuzzer-linux-arm build/test/tools/solfuzzer + - run_cmdline_tests + - store_test_results: + path: test_results/ + - store_artifacts_test_results + - matrix_notify_failure_unless_pr + t_ubu_force_release_cli: &t_ubu_force_release_cli <<: *t_ubu_cli @@ -1991,8 +2036,10 @@ workflows: # Ubuntu build and tests - b_ubu: *requires_nothing - t_ubu_cli: *requires_b_ubu + - t_ubu_arm_cli: *requires_b_ubu_static_arm - t_ubu_locale: *requires_b_ubu - t_ubu_soltest_all: *requires_b_ubu + - t_ubu_arm_soltest: *requires_b_ubu_static_arm - b_ubu_clang: *requires_nothing - t_ubu_clang_soltest: *requires_b_ubu_clang - t_ubu_lsp: *requires_b_ubu From 9763e9f5d0e95f4f3d2920c7bec7e821e24edeea Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 4 Dec 2025 18:25:04 -0300 Subject: [PATCH 1035/1340] Use new Linux ARM image --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8c7a56018..69ae1999f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,8 +17,8 @@ parameters: default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:c0412c53e59ce0c96bde4c08e7332ea12e4cadba9bbac829621947897fa21272" ubuntu-2404-arm-docker-image: type: string - # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.arm-1 - default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:6cdb928fa8743d0b5d515c2c489b8d545c541f2370af28d5d3a71532056a0f22" + # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.arm-2 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:27b03c1c4688e5d69b10e0539460346a3dee3b10b0e04fb406b9707c6f0dd95e" ubuntu-2404-clang-docker-image: type: string # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.clang-7 From 8d563631f2e9a04555b9149513fd4eae283b0ee1 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Sat, 6 Dec 2025 16:09:16 -0300 Subject: [PATCH 1036/1340] Update nlohmann-json to v3.12.0 --- deps/nlohmann-json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/nlohmann-json b/deps/nlohmann-json index 9cca280a4..55f93686c 160000 --- a/deps/nlohmann-json +++ b/deps/nlohmann-json @@ -1 +1 @@ -Subproject commit 9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03 +Subproject commit 55f93686c01528224f448c19128836e7df245f72 From 37ce297ec64d1e32cad82c1fc370a9702a44447b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 10 Dec 2025 11:50:42 +0100 Subject: [PATCH 1037/1340] contributing.rst: Add a link to the public call agenda --- docs/contributing.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/contributing.rst b/docs/contributing.rst index 45b15e579..b5eb3c08e 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -34,6 +34,9 @@ the team and contributors are working on, you can join our public team call: The call takes place on `Jitsi `_. +New topics can be freely added to the `agenda `_ +and will be scheduled for discussion on the nearest call. + How to Report Issues ==================== From 51e91352c0b08cf813fe4458a0ea1be3470e14fb Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 3 Dec 2025 17:00:30 +0100 Subject: [PATCH 1038/1340] Fix constantness of event and error selectors. Reported by https://github.com/argotorg/solidity/issues/13137 --- libsolidity/analysis/TypeChecker.cpp | 27 ++++++++++++++----- .../event_error_selector_pure_assignment.sol | 20 ++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 test/libsolidity/syntaxTests/types/functionTypes/selector/event_error_selector_pure_assignment.sol diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 9e29983ba..f5c093dbd 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3280,18 +3280,31 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) auto const* functionType = dynamic_cast(exprType); functionType && functionType->hasDeclaration() && - dynamic_cast(&functionType->declaration()) && memberName == "selector" ) - if (auto const* parentAccess = dynamic_cast(&_memberAccess.expression())) + { + if (dynamic_cast(&functionType->declaration())) { - bool isPure = *parentAccess->expression().annotation().isPure; - if (auto const* exprInt = dynamic_cast(&parentAccess->expression())) - if (exprInt->name() == "this" || exprInt->name() == "super") - isPure = true; + if (auto const* parentAccess = dynamic_cast(&_memberAccess.expression())) + { + bool isPure = *parentAccess->expression().annotation().isPure; + // Accessing a function selector using `super|this.f.selector`. + if (auto const* exprInt = dynamic_cast(&parentAccess->expression())) + if (exprInt->name() == "this" || exprInt->name() == "super") + isPure = true; - annotation.isPure = isPure; + annotation.isPure = isPure; + } } + // In case of event or error definition the selector is always compile-time constant, as it can be + // a keccak256 hash of the event signature or a function selector in case of an error. + else if ( + dynamic_cast(&functionType->declaration()) || + dynamic_cast(&functionType->declaration()) + ) + annotation.isPure = true; + } + if ( auto const* varDecl = dynamic_cast(annotation.referencedDeclaration); !annotation.isPure.set() && diff --git a/test/libsolidity/syntaxTests/types/functionTypes/selector/event_error_selector_pure_assignment.sol b/test/libsolidity/syntaxTests/types/functionTypes/selector/event_error_selector_pure_assignment.sol new file mode 100644 index 000000000..263e8f8a1 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/functionTypes/selector/event_error_selector_pure_assignment.sol @@ -0,0 +1,20 @@ +event EvExt(); +error ErExt(); + +bytes32 constant eventExtSelectorGlobal = EvExt.selector; +bytes4 constant errorExtSelectorGlobal = ErExt.selector; + +contract C { + event Ev(); + error Er(); + + bytes4 constant errorExtSelector = ErExt.selector; + bytes32 constant eventExtSelector = EvExt.selector; + + bytes4 constant errorSelector = Er.selector; + bytes32 constant eventSelector = Ev.selector; + + bytes4 constant errorSelectorC = C.Er.selector; + bytes32 constant eventSelectorC = C.Ev.selector; +} +// ---- From 4ec10c9343225595cb1d2655f4c66b29349f59c9 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 8 Dec 2025 09:56:06 +0100 Subject: [PATCH 1039/1340] Add the changelog entry. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update Changelog.md Co-authored-by: Nikola Matić --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 1aa6bc64b..42d679caa 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: Bugfixes: +* TypeChecker: Fix error and event selectors not being considered compile-time constant. ### 0.8.31 (2025-12-03) From befaeda28009ce126bfa3c4b26f2877433e30fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 15 Dec 2025 10:27:20 +0100 Subject: [PATCH 1040/1340] Always update stale gas expectations, even if below threshold --- test/libsolidity/SemanticTest.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 1b66dd60f..890a51596 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -579,22 +579,16 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp io_test.call().expectations.gasUsedForCodeDeposit.count(setting) ); - // We don't check gas if enforce gas cost is not active - // or test is run with abi encoder v1 only - // or gas used less than threshold for enforcing feature - // or the test has used up all available gas (test will fail anyway) - // or setting is "ir" and it's not included in expectations - // or if the called function is an isoltest builtin e.g. `smokeTest` or `storageEmpty` - if ( - !m_enforceGasCost || - m_gasUsed < m_enforceGasCostMinValue || - m_gasUsed >= InitialGas || - (setting == "ir" && io_test.call().expectations.gasUsedExcludingCode.count(setting) == 0) || - io_test.call().kind == FunctionCall::Kind::Builtin - ) + bool uninteresting = + m_gasUsed < m_enforceGasCostMinValue || // gas used less than threshold for enforcing feature + m_gasUsed >= InitialGas || // test has used up all available gas (test will fail anyway) + setting == "ir" || + io_test.call().kind == FunctionCall::Kind::Builtin; // isoltest builtin e.g. `smokeTest` or `storageEmpty` + bool gasValueMissing = !io_test.call().expectations.gasUsedExcludingCode.contains(setting); + if (!m_enforceGasCost || (gasValueMissing && uninteresting)) return true; - solAssert(!m_runWithABIEncoderV1Only, ""); + solAssert(!m_runWithABIEncoderV1Only); // NOTE: Cost excluding code is unlikely to be negative but it may still be possible due to refunds. // We'll deal with it when we actually have a test case like that. From 16ab579bdb49afd7d5d10af011c6348df0d90028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 15 Dec 2025 11:30:41 +0100 Subject: [PATCH 1041/1340] Update stale gas expectations that dropped below the default 100k threshold --- ...ode_v2_in_modifier_used_in_v1_contract.sol | 3 +- .../abiEncoderV2/calldata_array.sol | 4 +- .../array/array_storage_length_access.sol | 2 +- ...rray_storage_push_empty_length_address.sol | 6 +- .../array/array_storage_push_pop.sol | 6 +- .../array/byte_array_storage_layout.sol | 10 ++-- .../copying/array_copy_cleanup_uint128.sol | 6 +- .../array_copy_clear_storage_packed.sol | 12 ++-- ...ray_copy_storage_storage_static_simple.sol | 4 +- .../copying/array_copy_target_leftover2.sol | 6 +- ...o_storage_dynamic_different_mutability.sol | 2 +- .../copying/arrays_from_and_to_storage.sol | 2 +- .../copying/bytes_storage_to_storage.sol | 4 +- ...sted_array_element_calldata_to_storage.sol | 4 +- ...nested_array_element_memory_to_storage.sol | 4 +- .../delete/delete_storage_array_packed.sol | 6 +- .../array/dynamic_array_cleanup.sol | 6 +- .../array/fixed_array_cleanup.sol | 6 +- .../array/pop/byte_array_pop_copy_long.sol | 6 +- .../array/push/array_push_packed_array.sol | 6 +- .../array/push/push_no_args_2d.sol | 2 +- ...ing_explicit_downcast_during_emissions.sol | 3 +- .../events/event_indexed_mixed.sol | 6 +- .../events/event_signature_in_library.sol | 3 +- .../externalContracts/FixedFeeRegistrar.sol | 6 +- .../externalContracts/prbmath_signed.sol | 58 +++++++++--------- .../externalContracts/prbmath_unsigned.sol | 60 +++++++++---------- .../externalContracts/ramanujan_pi.sol | 4 +- .../externalContracts/strings.sol | 24 ++++---- .../functionCall/send_zero_ether.sol | 6 +- .../functionTypes/store_function.sol | 3 +- .../address_overload_resolution.sol | 6 +- ...d_function_calldata_calldata_interface.sol | 3 +- ...ted_function_calldata_memory_interface.sol | 3 +- .../interface_inheritance_conversions.sol | 10 ++-- .../keccak_yul_optimization.sol | 12 ++-- .../libraries/using_library_structs.sol | 2 +- .../operator_making_pure_external_call.sol | 6 +- .../operator_making_view_external_call.sol | 6 +- .../struct_delete_storage_nested_small.sol | 2 +- ...truct_delete_storage_with_arrays_small.sol | 2 +- .../calldata_to_storage.sol | 18 +++--- .../userDefinedValueType/erc20.sol | 36 +++++------ .../memory_to_storage.sol | 18 +++--- ...cost_abstraction_comparison_elementary.sol | 24 ++++---- ...ost_abstraction_comparison_userdefined.sol | 24 ++++---- .../various/codebalance_assembly.sol | 3 +- .../various/contract_binary_dependencies.sol | 3 +- .../semanticTests/various/erc20.sol | 34 +++++------ 49 files changed, 254 insertions(+), 238 deletions(-) diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol index 8df4090c3..78da59648 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol @@ -38,6 +38,7 @@ contract C is B { } // ---- // test() -> 5, 10 -// gas irOptimized: 87337 +// gas irOptimized: 65040 +// gas irOptimized code: 26200 // gas legacy: 66250 // gas legacy code: 36400 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol index cdce1b95a..739c4c840 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol @@ -21,5 +21,5 @@ contract C { // f(uint256[][1]): 32, 32, 1, 42 -> true // f(uint256[][1]): 32, 32, 8, 421, 422, 423, 424, 425, 426, 427, 428 -> true // gas irOptimized: 120978 -// gas legacy: 101568 -// gas legacyOptimized: 119092 +// gas legacy: 98324 +// gas legacyOptimized: 94348 diff --git a/test/libsolidity/semanticTests/array/array_storage_length_access.sol b/test/libsolidity/semanticTests/array/array_storage_length_access.sol index 47fddc554..4f7308c24 100644 --- a/test/libsolidity/semanticTests/array/array_storage_length_access.sol +++ b/test/libsolidity/semanticTests/array/array_storage_length_access.sol @@ -12,7 +12,7 @@ contract C { // set_get_length(uint256): 10 -> 10 // set_get_length(uint256): 20 -> 20 // set_get_length(uint256): 0xFF -> 0xFF -// gas irOptimized: 96690 +// gas irOptimized: 98764 // gas legacy: 128571 // gas legacyOptimized: 110143 // set_get_length(uint256): 0xFFF -> 0xFFF diff --git a/test/libsolidity/semanticTests/array/array_storage_push_empty_length_address.sol b/test/libsolidity/semanticTests/array/array_storage_push_empty_length_address.sol index 607e1ecd3..bf06393a6 100644 --- a/test/libsolidity/semanticTests/array/array_storage_push_empty_length_address.sol +++ b/test/libsolidity/semanticTests/array/array_storage_push_empty_length_address.sol @@ -17,9 +17,9 @@ contract C { // set_get_length(uint256): 10 -> 10 // set_get_length(uint256): 20 -> 20 // set_get_length(uint256): 0 -> 0 -// gas irOptimized: 77628 -// gas legacy: 77730 -// gas legacyOptimized: 77162 +// gas irOptimized: 76123 +// gas legacy: 75618 +// gas legacyOptimized: 75076 // set_get_length(uint256): 0xFF -> 0xFF // gas irOptimized: 168565 // gas legacy: 696850 diff --git a/test/libsolidity/semanticTests/array/array_storage_push_pop.sol b/test/libsolidity/semanticTests/array/array_storage_push_pop.sol index a4c7d34d7..609944ddc 100644 --- a/test/libsolidity/semanticTests/array/array_storage_push_pop.sol +++ b/test/libsolidity/semanticTests/array/array_storage_push_pop.sol @@ -13,9 +13,9 @@ contract C { // set_get_length(uint256): 1 -> 0 // set_get_length(uint256): 10 -> 0 // set_get_length(uint256): 20 -> 0 -// gas irOptimized: 106222 -// gas legacy: 105722 -// gas legacyOptimized: 103508 +// gas irOptimized: 87226 +// gas legacy: 85609 +// gas legacyOptimized: 83462 // set_get_length(uint256): 0xFF -> 0 // gas irOptimized: 833586 // gas legacy: 807764 diff --git a/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol b/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol index 060cafe39..68e4b5d62 100644 --- a/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol +++ b/test/libsolidity/semanticTests/array/byte_array_storage_layout.sol @@ -41,15 +41,15 @@ contract c { // ---- // storageEmpty -> 1 // test_short() -> 1780731860627700044960722568376587075150542249149356309979516913770823710 -// gas legacy: 59838 -// gas legacyOptimized: 58606 +// gas legacy: 57661 +// gas legacyOptimized: 57073 // storageEmpty -> 0 // test_long() -> 67 -// gas irOptimized: 89148 +// gas irOptimized: 89482 // gas legacy: 101607 // gas legacyOptimized: 100479 // storageEmpty -> 0 // test_pop() -> 1780731860627700044960722568376592200742329637303199754547598369979433020 -// gas legacy: 61930 -// gas legacyOptimized: 59404 +// gas legacy: 58079 +// gas legacyOptimized: 56932 // storageEmpty -> 0 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol index 761feebec..e1cfa7ce7 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol @@ -21,6 +21,6 @@ contract C { } // ---- // f() -> true -// gas irOptimized: 92740 -// gas legacy: 93035 -// gas legacyOptimized: 92257 +// gas irOptimized: 73992 +// gas legacy: 74395 +// gas legacyOptimized: 73794 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol index 13cb9c28f..43827773c 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol @@ -40,11 +40,11 @@ contract C { } // ---- // f() -> 0 -// gas irOptimized: 92800 -// gas legacy: 93006 -// gas legacyOptimized: 92261 +// gas irOptimized: 74056 +// gas legacy: 74372 +// gas legacyOptimized: 73796 // g() -> 0 // h() -> 0 -// gas irOptimized: 92862 -// gas legacy: 93028 -// gas legacyOptimized: 92303 +// gas irOptimized: 74126 +// gas legacy: 74398 +// gas legacyOptimized: 73833 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_simple.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_simple.sol index 2fccff774..84642c143 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_simple.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_simple.sol @@ -11,5 +11,5 @@ contract C { } // ---- // test() -> left(0x01), left(0x02) -// gas legacy: 90001 -// gas legacyOptimized: 89085 +// gas legacy: 89698 +// gas legacyOptimized: 88928 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover2.sol b/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover2.sol index 0a2bcffce..dd49c7a97 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover2.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover2.sol @@ -19,6 +19,6 @@ contract c { } // ---- // test() -> 0x04000000000000000000000000000000000000000000000000, 0x0, 0x0 -// gas irOptimized: 93858 -// gas legacy: 97451 -// gas legacyOptimized: 94200 +// gas irOptimized: 91348 +// gas legacy: 96648 +// gas legacyOptimized: 93841 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol index 2bb3bcf33..d121b22d4 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol @@ -52,4 +52,4 @@ contract C { // gas legacy: 108295 // gas legacyOptimized: 102162 // copyInternalArrayOfFunctionType() -> true -// gas legacy: 104178 +// gas legacy: 36192 diff --git a/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol b/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol index af2983b06..93b541620 100644 --- a/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol @@ -10,7 +10,7 @@ contract Test { } // ---- // set(uint24[]): 0x20, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 -> 18 -// gas irOptimized: 99616 +// gas irOptimized: 95505 // gas legacy: 103509 // gas legacyOptimized: 101266 // data(uint256): 7 -> 8 diff --git a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol index fe758fe8f..d00f5573a 100644 --- a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol @@ -33,8 +33,8 @@ contract c { // gas legacy: 148692 // gas legacyOptimized: 148699 // f(uint256): 12 -> 0x20, 0x0c, 0x0102030405060708090a0b0000000000000000000000000000000000000000 -// gas legacy: 59345 -// gas legacyOptimized: 57279 +// gas legacy: 59751 +// gas legacyOptimized: 57208 // f(uint256): 129 -> 0x20, 0x81, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f, 29063324697304692433803953038474361308315562010425523193971352996434451193439, 0x606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f, -57896044618658097711785492504343953926634992332820282019728792003956564819968 // gas irOptimized: 416918 // gas legacy: 458997 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_element_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_element_calldata_to_storage.sol index 5040a72ca..89eeb27dc 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_element_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_element_calldata_to_storage.sol @@ -25,5 +25,5 @@ contract C { // ---- // test(uint8[2][2][2]): 1, 2, 3, 4, 5, 6, 7, 8 // test2(uint8[2][2]): 1, 2, 3, 4 -// gas irOptimized: 119939 -// gas legacyOptimized: 120228 +// gas irOptimized: 72076 +// gas legacyOptimized: 95103 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_element_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_element_memory_to_storage.sol index 2f4b4ca7c..bd74ae015 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_element_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_element_memory_to_storage.sol @@ -25,5 +25,5 @@ contract C { // ---- // test(uint8[2][2][2]): 1, 2, 3, 4, 5, 6, 7, 8 // test2(uint8[2][2]): 1, 2, 3, 4 -// gas irOptimized: 119939 -// gas legacyOptimized: 120228 +// gas irOptimized: 73031 +// gas legacyOptimized: 96288 diff --git a/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol b/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol index 9665201c9..f486a50cf 100644 --- a/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol +++ b/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol @@ -14,6 +14,6 @@ contract C { } // ---- // f() -> 0, 0, 0 -// gas irOptimized: 90992 -// gas legacy: 111037 -// gas legacyOptimized: 109633 +// gas irOptimized: 88026 +// gas legacy: 88800 +// gas legacyOptimized: 87700 diff --git a/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol b/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol index b2be566a9..285bc5f6f 100644 --- a/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/dynamic_array_cleanup.sol @@ -19,9 +19,9 @@ contract c { // gas legacyOptimized: 515555 // storageEmpty -> 0 // halfClear() -> -// gas irOptimized: 113961 -// gas legacy: 113257 -// gas legacyOptimized: 113120 +// gas irOptimized: 91472 +// gas legacy: 90567 +// gas legacyOptimized: 90457 // storageEmpty -> 0 // fullClear() -> // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol index ebe2186fd..b4ba8b47f 100644 --- a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol @@ -15,7 +15,7 @@ contract c { // gas legacyOptimized: 466238 // storageEmpty -> 0 // clear() -> -// gas irOptimized: 122148 -// gas legacy: 122440 -// gas legacyOptimized: 122259 +// gas irOptimized: 97705 +// gas legacy: 97919 +// gas legacyOptimized: 97790 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol b/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol index c64d93c12..01d2d83f9 100644 --- a/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol +++ b/test/libsolidity/semanticTests/array/pop/byte_array_pop_copy_long.sol @@ -9,6 +9,6 @@ contract c { } // ---- // test() -> 0x20, 29, 0x0303030303030303030303030303030303030303030303030303030303000000 -// gas irOptimized: 109310 -// gas legacy: 101220 -// gas legacyOptimized: 123422 +// gas irOptimized: 85778 +// gas legacy: 97666 +// gas legacyOptimized: 96874 diff --git a/test/libsolidity/semanticTests/array/push/array_push_packed_array.sol b/test/libsolidity/semanticTests/array/push/array_push_packed_array.sol index e7a3bdbd1..e6c010230 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_packed_array.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_packed_array.sol @@ -13,6 +13,6 @@ contract c { } // ---- // test() -> 1, 2, 3, 4 -// gas irOptimized: 93017 -// gas legacy: 92798 -// gas legacyOptimized: 92062 +// gas irOptimized: 92545 +// gas legacy: 92756 +// gas legacyOptimized: 92045 diff --git a/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol b/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol index 3b35719db..626c65871 100644 --- a/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol +++ b/test/libsolidity/semanticTests/array/push/push_no_args_2d.sol @@ -36,7 +36,7 @@ contract C { // f(uint256,uint256): 84, 128 -> // gas irOptimized: 118708 // gas legacy: 109977 -// gas legacyOptimized: 96331 +// gas legacyOptimized: 98446 // l() -> 2 // ll(uint256): 1 -> 85 // a(uint256,uint256): 0, 42 -> 64 diff --git a/test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast_during_emissions.sol b/test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast_during_emissions.sol index 742c02693..08bfac8c2 100644 --- a/test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast_during_emissions.sol +++ b/test/libsolidity/semanticTests/cleanup/indexed_log_topic_during_explicit_downcast_during_emissions.sol @@ -12,6 +12,7 @@ contract C { // ---- // constructor() -> // ~ emit ev0(bytes1): #"1" -// gas legacy: 168735 +// gas legacy: 58919 +// gas legacy code: 33600 // j() -> // ~ emit ev0(bytes1): #"1" diff --git a/test/libsolidity/semanticTests/events/event_indexed_mixed.sol b/test/libsolidity/semanticTests/events/event_indexed_mixed.sol index ad753ef16..66c7f8b5f 100644 --- a/test/libsolidity/semanticTests/events/event_indexed_mixed.sol +++ b/test/libsolidity/semanticTests/events/event_indexed_mixed.sol @@ -11,6 +11,6 @@ contract C { // ---- // deposit() -> // ~ emit E(uint256,uint256,uint256,bytes): #0x02, 0x01, 0x03, 0x60, 0x03, "def" -// gas irOptimized: 23709 -// gas legacy: 24342 -// gas legacyOptimized: 23753 +// gas irOptimized: 23695 +// gas legacy: 24328 +// gas legacyOptimized: 23752 diff --git a/test/libsolidity/semanticTests/events/event_signature_in_library.sol b/test/libsolidity/semanticTests/events/event_signature_in_library.sol index d8dc0f158..0991cd28a 100644 --- a/test/libsolidity/semanticTests/events/event_signature_in_library.sol +++ b/test/libsolidity/semanticTests/events/event_signature_in_library.sol @@ -18,4 +18,5 @@ contract C { // ---- // constructor() // ~ emit E((uint8,int16),(uint8,int16)): #0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5, 0x00, 0x00 -// gas legacy: 150602 +// gas legacy: 62552 +// gas legacy code: 1600 diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index 47feaf525..e89eeba98 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -82,9 +82,9 @@ contract FixedFeeRegistrar is Registrar { // gas legacyOptimized code: 388000 // reserve(string), 69 ether: 0x20, 3, "abc" -> // ~ emit Changed(string): #0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 -// gas irOptimized: 45967 -// gas legacy: 46842 -// gas legacyOptimized: 46091 +// gas irOptimized: 45741 +// gas legacy: 46698 +// gas legacyOptimized: 45948 // owner(string): 0x20, 3, "abc" -> 0x1212121212121212121212121212120000000012 // reserve(string), 70 ether: 0x20, 3, "def" -> // ~ emit Changed(string): #0x34607c9bbfeb9c23509680f04363f298fdb0b5f9abe327304ecd1daca08cda9c diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index cb345757f..35e083d5c 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -55,42 +55,42 @@ contract test { // gas legacyOptimized: 178012 // gas legacyOptimized code: 1669600 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 -// gas irOptimized: 22137 -// gas legacy: 22767 -// gas legacyOptimized: 22282 +// gas irOptimized: 22045 +// gas legacy: 22736 +// gas legacyOptimized: 22264 // exp(int256): 3141592653589793238 -> 23140692632779268978 -// gas irOptimized: 24545 -// gas legacy: 25203 -// gas legacyOptimized: 24357 +// gas irOptimized: 24452 +// gas legacy: 25124 +// gas legacyOptimized: 24351 // exp2(int256): 3141592653589793238 -> 8824977827076287620 -// gas irOptimized: 24257 -// gas legacy: 24864 -// gas legacyOptimized: 24110 +// gas irOptimized: 24162 +// gas legacy: 24787 +// gas legacyOptimized: 24105 // gm(int256,int256): 3141592653589793238, 88714123 -> 16694419339601 -// gas irOptimized: 22970 -// gas legacy: 23228 -// gas legacyOptimized: 22683 +// gas irOptimized: 22805 +// gas legacy: 23202 +// gas legacyOptimized: 22685 // log10(int256): 3141592653589793238 -> 4971498726941338506 -// gas irOptimized: 30609 -// gas legacy: 32934 -// gas legacyOptimized: 30323 +// gas irOptimized: 30300 +// gas legacy: 32841 +// gas legacyOptimized: 30249 // log2(int256): 3141592653589793238 -> 1651496129472318782 -// gas irOptimized: 28819 -// gas legacy: 31067 -// gas legacyOptimized: 28426 +// gas irOptimized: 28566 +// gas legacy: 30979 +// gas legacyOptimized: 28357 // mul(int256,int256): 3141592653589793238, 88714123 -> 278703637 -// gas irOptimized: 22225 -// gas legacy: 22807 -// gas legacyOptimized: 22295 +// gas irOptimized: 22147 +// gas legacy: 22775 +// gas legacyOptimized: 22288 // pow(int256,uint256): 3141592653589793238, 5 -> 306019684785281453040 -// gas irOptimized: 22635 -// gas legacy: 23508 +// gas irOptimized: 22488 +// gas legacy: 23453 // gas legacyOptimized: 22921 // sqrt(int256): 3141592653589793238 -> 1772453850905516027 -// gas irOptimized: 22650 -// gas legacy: 22802 -// gas legacyOptimized: 22422 +// gas irOptimized: 22458 +// gas legacy: 22784 +// gas legacyOptimized: 22420 // benchmark(int256): 3141592653589793238 -> 998882724338592125, 1000000000000000000, 1000000000000000000 -// gas irOptimized: 36630 -// gas legacy: 36673 -// gas legacyOptimized: 34729 +// gas irOptimized: 34893 +// gas legacy: 35244 +// gas legacyOptimized: 33996 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index 5902ba490..38d2a20ba 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -55,42 +55,42 @@ contract test { // gas legacyOptimized: 168857 // gas legacyOptimized code: 1556200 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 -// gas irOptimized: 22004 -// gas legacy: 22497 -// gas legacyOptimized: 22010 +// gas irOptimized: 21912 +// gas legacy: 22475 +// gas legacyOptimized: 21998 // exp(uint256): 3141592653589793238 -> 23140692632779268978 -// gas irOptimized: 24444 -// gas legacy: 25104 -// gas legacyOptimized: 24258 +// gas irOptimized: 24334 +// gas legacy: 25026 +// gas legacyOptimized: 24253 // exp2(uint256): 3141592653589793238 -> 8824977827076287620 -// gas irOptimized: 24198 -// gas legacy: 24814 -// gas legacyOptimized: 24062 +// gas irOptimized: 24115 +// gas legacy: 24738 +// gas legacyOptimized: 24058 // gm(uint256,uint256): 3141592653589793238, 88714123 -> 16694419339601 -// gas irOptimized: 22950 -// gas legacy: 23269 -// gas legacyOptimized: 22724 +// gas irOptimized: 22786 +// gas legacy: 23244 +// gas legacyOptimized: 22727 // log10(uint256): 3141592653589793238 -> 0x44fe4fc084a52b8a -// gas irOptimized: 30269 -// gas legacy: 32898 -// gas legacyOptimized: 29925 +// gas irOptimized: 30079 +// gas legacy: 32808 +// gas legacyOptimized: 29912 // log2(uint256): 3141592653589793238 -> 1651496129472318782 -// gas irOptimized: 28235 -// gas legacy: 30986 -// gas legacyOptimized: 28001 +// gas irOptimized: 28107 +// gas legacy: 30900 +// gas legacyOptimized: 27994 // mul(uint256,uint256): 3141592653589793238, 88714123 -> 278703637 -// gas irOptimized: 22048 -// gas legacy: 22604 -// gas legacyOptimized: 22090 +// gas irOptimized: 21988 +// gas legacy: 22581 +// gas legacyOptimized: 22089 // pow(uint256,uint256): 3141592653589793238, 5 -> 306019684785281453040 -// gas irOptimized: 22406 -// gas legacy: 23245 -// gas legacyOptimized: 22646 +// gas irOptimized: 22316 +// gas legacy: 23196 +// gas legacyOptimized: 22652 // sqrt(uint256): 3141592653589793238 -> 1772453850905516027 -// gas irOptimized: 22672 -// gas legacy: 22820 -// gas legacyOptimized: 22440 +// gas irOptimized: 22481 +// gas legacy: 22803 +// gas legacyOptimized: 22439 // benchmark(uint256): 3141592653589793238 -> 998882724338592125, 1000000000000000000, 1000000000000000000 -// gas irOptimized: 35603 -// gas legacy: 35385 -// gas legacyOptimized: 33449 +// gas irOptimized: 33961 +// gas legacy: 34006 +// gas legacyOptimized: 32724 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index 70a3004ac..a98e83001 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -40,6 +40,6 @@ contract test { // gas legacyOptimized: 82667 // gas legacyOptimized code: 369200 // prb_pi() -> 3141592656369545286 -// gas irOptimized: 57478 +// gas irOptimized: 55036 // gas legacy: 100657 -// gas legacyOptimized: 75735 +// gas legacyOptimized: 74311 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index cb9616bbe..8deb86ed5 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -56,21 +56,21 @@ contract test { // gas legacyOptimized: 102639 // gas legacyOptimized code: 612400 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 -// gas irOptimized: 22660 -// gas legacy: 23190 -// gas legacyOptimized: 22508 +// gas irOptimized: 22646 +// gas legacy: 23168 +// gas legacyOptimized: 22488 // roundtrip(string): 0x20, 11, "hello world" -> 0x20, 11, "hello world" -// gas irOptimized: 23408 -// gas legacy: 23820 -// gas legacyOptimized: 23123 +// gas irOptimized: 23225 +// gas legacy: 23674 +// gas legacyOptimized: 22991 // utf8len(string): 0x20, 16, "\xf0\x9f\x98\x83\xf0\x9f\x98\x83\xf0\x9f\x98\x83\xf0\x9f\x98\x83" -> 4 # Input: "😃😃😃😃" # -// gas irOptimized: 24026 -// gas legacy: 25716 -// gas legacyOptimized: 24115 +// gas irOptimized: 23956 +// gas legacy: 25621 +// gas legacyOptimized: 24096 // multiconcat(string,uint256): 0x40, 3, 11, "hello world" -> 0x20, 0x58, 0x68656c6c6f20776f726c6468656c6c6f20776f726c6468656c6c6f20776f726c, 0x6468656c6c6f20776f726c6468656c6c6f20776f726c6468656c6c6f20776f72, 49027192869463622675296414541903001712009715982962058146354235762728281047040 # concatenating 3 times # -// gas irOptimized: 28440 -// gas legacy: 31621 -// gas legacyOptimized: 27914 +// gas irOptimized: 27630 +// gas legacy: 30778 +// gas legacyOptimized: 27519 // benchmark(string,bytes32): 0x40, 0x0842021, 8, "solidity" -> 0x2020 // gas irOptimized: 1976778 // gas legacy: 4234020 diff --git a/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol b/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol index 94a721323..8eeaf7b51 100644 --- a/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol +++ b/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol @@ -15,8 +15,10 @@ contract Main { } // ---- // constructor(), 20 wei -> -// gas irOptimized: 100264 +// gas irOptimized: 56314 +// gas irOptimized code: 37400 // gas legacy: 57555 // gas legacy code: 53000 -// gas legacyOptimized: 100361 +// gas legacyOptimized: 56463 +// gas legacyOptimized code: 39600 // s() -> true diff --git a/test/libsolidity/semanticTests/functionTypes/store_function.sol b/test/libsolidity/semanticTests/functionTypes/store_function.sol index eeab740aa..904bc705f 100644 --- a/test/libsolidity/semanticTests/functionTypes/store_function.sol +++ b/test/libsolidity/semanticTests/functionTypes/store_function.sol @@ -25,7 +25,8 @@ contract C { } // ---- // t() -> 9 -// gas irOptimized: 99064 +// gas irOptimized: 77300 +// gas irOptimized code: 19000 // gas legacy: 79492 // gas legacy code: 69600 // gas legacyOptimized: 77587 diff --git a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol index 90a3f9ec8..f339b5244 100644 --- a/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol +++ b/test/libsolidity/semanticTests/inheritance/address_overload_resolution.sol @@ -22,10 +22,12 @@ contract D { // EVMVersion: >=constantinople // ---- // f() -> 1 -// gas irOptimized: 77051 +// gas irOptimized: 54014 +// gas irOptimized code: 20200 // gas legacy: 54553 // gas legacy code: 57800 // g() -> 5 -// gas irOptimized: 77106 +// gas irOptimized: 54042 +// gas irOptimized code: 20200 // gas legacy: 55090 // gas legacy code: 57800 diff --git a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol index f64a2e12a..e9013d6f5 100644 --- a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol +++ b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_calldata_interface.sol @@ -22,6 +22,7 @@ contract B { } // ---- // g() -> 42 -// gas irOptimized: 80813 +// gas irOptimized: 54536 +// gas irOptimized code: 24800 // gas legacy: 55868 // gas legacy code: 66600 diff --git a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol index 07beb2c53..36ed37062 100644 --- a/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol +++ b/test/libsolidity/semanticTests/inheritance/inherited_function_calldata_memory_interface.sol @@ -22,7 +22,8 @@ contract B { } // ---- // g() -> 42 -// gas irOptimized: 100282 +// gas irOptimized: 54828 +// gas irOptimized code: 42000 // gas legacy: 56839 // gas legacy code: 123600 // gas legacyOptimized: 55001 diff --git a/test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol b/test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol index 2448b3e03..95f48f60a 100644 --- a/test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol +++ b/test/libsolidity/semanticTests/inheritance/interface_inheritance_conversions.sol @@ -29,10 +29,10 @@ contract C is SubA, SubB { } // ---- // convertParent() -> 1 -// gas irOptimized: 85524 +// gas irOptimized: 21793 // convertSubA() -> 1, 2 -// gas irOptimized: 86155 -// gas legacy: 99047 +// gas irOptimized: 22459 +// gas legacy: 23286 // convertSubB() -> 1, 3 -// gas irOptimized: 86098 -// gas legacy: 98981 +// gas irOptimized: 22330 +// gas legacy: 23154 diff --git a/test/libsolidity/semanticTests/inlineAssembly/keccak_yul_optimization.sol b/test/libsolidity/semanticTests/inlineAssembly/keccak_yul_optimization.sol index 88088bbda..e3344bf5d 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/keccak_yul_optimization.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/keccak_yul_optimization.sol @@ -24,10 +24,10 @@ contract C { } // ---- // f() -> 0xcdb56c384a9682c600315e3470157a4cf7638d0d33e9dae5c40ffd2644fc5a80 -// gas irOptimized: 22239 -// gas legacy: 23385 -// gas legacyOptimized: 23092 +// gas irOptimized: 22212 +// gas legacy: 23378 +// gas legacyOptimized: 23089 // g() -> 0xcdb56c384a9682c600315e3470157a4cf7638d0d33e9dae5c40ffd2644fc5a80 -// gas irOptimized: 21277 -// gas legacy: 21462 -// gas legacyOptimized: 21256 +// gas irOptimized: 21251 +// gas legacy: 21456 +// gas legacyOptimized: 21254 diff --git a/test/libsolidity/semanticTests/libraries/using_library_structs.sol b/test/libsolidity/semanticTests/libraries/using_library_structs.sol index c2ecf1036..15398e312 100644 --- a/test/libsolidity/semanticTests/libraries/using_library_structs.sol +++ b/test/libsolidity/semanticTests/libraries/using_library_structs.sol @@ -20,5 +20,5 @@ contract Test { // ---- // library: Lib // f() -> 7, 8 -// gas irOptimized: 101818 +// gas irOptimized: 97577 // gas legacy: 101428 diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol index 364e589e5..b901cab03 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_pure_external_call.sol @@ -54,13 +54,15 @@ contract C { // EVMVersion: >=constantinople // ---- // testMul(int32,int32): 42, 10 -> 420 -// gas irOptimized: 102563 +// gas irOptimized: 54784 +// gas irOptimized code: 40600 // gas legacy: 57117 // gas legacy code: 127000 // gas legacyOptimized: 55246 // gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 -// gas irOptimized: 102386 +// gas irOptimized: 54621 +// gas irOptimized code: 40600 // gas legacy: 56378 // gas legacy code: 127000 // gas legacyOptimized: 54943 diff --git a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol index 54048113c..15501b3fc 100644 --- a/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol +++ b/test/libsolidity/semanticTests/operators/userDefined/operator_making_view_external_call.sol @@ -60,13 +60,15 @@ contract C { // EVMVersion: >=constantinople // ---- // testMul(int32,int32): 42, 10 -> 420 -// gas irOptimized: 102563 +// gas irOptimized: 54784 +// gas irOptimized code: 40600 // gas legacy: 57117 // gas legacy code: 127000 // gas legacyOptimized: 55246 // gas legacyOptimized code: 68400 // testInc(int32): 42 -> 43 -// gas irOptimized: 102386 +// gas irOptimized: 54621 +// gas irOptimized code: 40600 // gas legacy: 56378 // gas legacy code: 127000 // gas legacyOptimized: 54943 diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol index 57bf38e52..a8e29dcad 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol @@ -33,4 +33,4 @@ contract C { // compileViaYul: true // ---- // f() -> 0, 0, 0 -// gas irOptimized: 117101 +// gas irOptimized: 93830 diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol index 2345fea3c..871c614f5 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol @@ -27,4 +27,4 @@ contract C { // compileViaYul: true // ---- // f() -> 0 -// gas irOptimized: 111570 +// gas irOptimized: 89435 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/calldata_to_storage.sol b/test/libsolidity/semanticTests/userDefinedValueType/calldata_to_storage.sol index c3d58811a..292b9fbfe 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/calldata_to_storage.sol @@ -23,19 +23,19 @@ contract C { // ---- // s() -> 0, 0, 0x00, 0 // f((uint8,uint16,bytes2,uint8)): 1, 0xff, "ab", 15 -> -// gas irOptimized: 44405 -// gas legacy: 47200 -// gas legacyOptimized: 44923 +// gas irOptimized: 44237 +// gas legacy: 47154 +// gas legacyOptimized: 45018 // s() -> 1, 0xff, 0x6162000000000000000000000000000000000000000000000000000000000000, 15 // g(uint16[]): 0x20, 3, 1, 2, 3 -> 0x20, 3, 1, 2, 3 -// gas irOptimized: 69097 -// gas legacy: 75466 -// gas legacyOptimized: 74255 +// gas irOptimized: 68578 +// gas legacy: 75429 +// gas legacyOptimized: 74244 // small(uint256): 0 -> 1 // small(uint256): 1 -> 2 // h(bytes2[]): 0x20, 3, "ab", "cd", "ef" -> 0x20, 3, "ab", "cd", "ef" -// gas irOptimized: 69174 -// gas legacy: 75156 -// gas legacyOptimized: 74342 +// gas irOptimized: 68635 +// gas legacy: 75125 +// gas legacyOptimized: 74331 // l(uint256): 0 -> 0x6162000000000000000000000000000000000000000000000000000000000000 // l(uint256): 1 -> 0x6364000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol index 0e0759d62..acd9ea840 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol @@ -120,29 +120,29 @@ contract ERC20 { // gas legacyOptimized: 127464 // gas legacyOptimized code: 285400 // totalSupply() -> 20 -// gas irOptimized: 23415 -// gas legacy: 23653 -// gas legacyOptimized: 23368 +// gas irOptimized: 23334 +// gas legacy: 23645 +// gas legacyOptimized: 23367 // transfer(address,uint256): 2, 5 -> true // ~ emit Transfer(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x05 -// gas irOptimized: 48471 -// gas legacy: 49572 -// gas legacyOptimized: 48575 +// gas irOptimized: 50997 +// gas legacy: 52323 +// gas legacyOptimized: 51380 // decreaseAllowance(address,uint256): 2, 0 -> true // ~ emit Approval(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x00 -// gas irOptimized: 26275 -// gas legacy: 27204 -// gas legacyOptimized: 26317 +// gas irOptimized: 26054 +// gas legacy: 27165 +// gas legacyOptimized: 26320 // decreaseAllowance(address,uint256): 2, 1 -> FAILURE, hex"4e487b71", 0x11 -// gas irOptimized: 24042 -// gas legacy: 24506 -// gas legacyOptimized: 24077 +// gas irOptimized: 23954 +// gas legacy: 24500 +// gas legacyOptimized: 24076 // transfer(address,uint256): 2, 14 -> true // ~ emit Transfer(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x0e -// gas irOptimized: 28571 -// gas legacy: 29672 -// gas legacyOptimized: 28675 +// gas irOptimized: 33897 +// gas legacy: 35223 +// gas legacyOptimized: 34280 // transfer(address,uint256): 2, 2 -> FAILURE, hex"4e487b71", 0x11 -// gas irOptimized: 24071 -// gas legacy: 24492 -// gas legacyOptimized: 24074 +// gas irOptimized: 23990 +// gas legacy: 24483 +// gas legacyOptimized: 24072 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/memory_to_storage.sol b/test/libsolidity/semanticTests/userDefinedValueType/memory_to_storage.sol index db745dce3..585249f2f 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/memory_to_storage.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/memory_to_storage.sol @@ -23,19 +23,19 @@ contract C { // ---- // s() -> 0, 0, 0x00, 0 // f((uint8,uint16,bytes2,uint8)): 1, 0xff, "ab", 15 -> -// gas irOptimized: 44473 -// gas legacy: 46213 -// gas legacyOptimized: 44671 +// gas irOptimized: 44360 +// gas legacy: 46189 +// gas legacyOptimized: 44673 // s() -> 1, 0xff, 0x6162000000000000000000000000000000000000000000000000000000000000, 15 // g(uint16[]): 0x20, 3, 1, 2, 3 -> 0x20, 3, 1, 2, 3 -// gas irOptimized: 69555 -// gas legacy: 76557 -// gas legacyOptimized: 74834 +// gas irOptimized: 68898 +// gas legacy: 76511 +// gas legacyOptimized: 74832 // small(uint256): 0 -> 1 // small(uint256): 1 -> 2 // h(bytes2[]): 0x20, 3, "ab", "cd", "ef" -> 0x20, 3, "ab", "cd", "ef" -// gas irOptimized: 69617 -// gas legacy: 76238 -// gas legacyOptimized: 74921 +// gas irOptimized: 68937 +// gas legacy: 76198 +// gas legacyOptimized: 74919 // l(uint256): 0 -> 0x6162000000000000000000000000000000000000000000000000000000000000 // l(uint256): 1 -> 0x6364000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/zero_cost_abstraction_comparison_elementary.sol b/test/libsolidity/semanticTests/userDefinedValueType/zero_cost_abstraction_comparison_elementary.sol index 2c5a15bb9..c254d9abd 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/zero_cost_abstraction_comparison_elementary.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/zero_cost_abstraction_comparison_elementary.sol @@ -17,18 +17,18 @@ contract C { } // ---- // getX() -> 0 -// gas irOptimized: 23379 -// gas legacy: 23479 -// gas legacyOptimized: 23311 +// gas irOptimized: 23311 +// gas legacy: 23473 +// gas legacyOptimized: 23309 // setX(int256): 5 -> -// gas irOptimized: 43510 -// gas legacy: 43724 -// gas legacyOptimized: 43516 +// gas irOptimized: 43464 +// gas legacy: 43718 +// gas legacyOptimized: 43513 // getX() -> 5 -// gas irOptimized: 23379 -// gas legacy: 23479 -// gas legacyOptimized: 23311 +// gas irOptimized: 23311 +// gas legacy: 23473 +// gas legacyOptimized: 23309 // add(int256,int256): 200, 99 -> 299 -// gas irOptimized: 21764 -// gas legacy: 22394 -// gas legacyOptimized: 21813 +// gas irOptimized: 21623 +// gas legacy: 22354 +// gas legacyOptimized: 21768 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/zero_cost_abstraction_comparison_userdefined.sol b/test/libsolidity/semanticTests/userDefinedValueType/zero_cost_abstraction_comparison_userdefined.sol index 2f275c543..89f811862 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/zero_cost_abstraction_comparison_userdefined.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/zero_cost_abstraction_comparison_userdefined.sol @@ -18,18 +18,18 @@ contract C { } // ---- // getX() -> 0 -// gas irOptimized: 23379 -// gas legacy: 23608 -// gas legacyOptimized: 23311 +// gas irOptimized: 23311 +// gas legacy: 23599 +// gas legacyOptimized: 23309 // setX(int256): 5 -> -// gas irOptimized: 43510 -// gas legacy: 43724 -// gas legacyOptimized: 43516 +// gas irOptimized: 43464 +// gas legacy: 43718 +// gas legacyOptimized: 43513 // getX() -> 5 -// gas irOptimized: 23379 -// gas legacy: 23608 -// gas legacyOptimized: 23311 +// gas irOptimized: 23311 +// gas legacy: 23599 +// gas legacyOptimized: 23309 // add(int256,int256): 200, 99 -> 299 -// gas irOptimized: 21764 -// gas legacy: 22523 -// gas legacyOptimized: 21813 +// gas irOptimized: 21623 +// gas legacy: 22480 +// gas legacyOptimized: 21768 diff --git a/test/libsolidity/semanticTests/various/codebalance_assembly.sol b/test/libsolidity/semanticTests/various/codebalance_assembly.sol index fad0d3e5b..6faffd639 100644 --- a/test/libsolidity/semanticTests/various/codebalance_assembly.sol +++ b/test/libsolidity/semanticTests/various/codebalance_assembly.sol @@ -21,7 +21,8 @@ contract C { // EVMVersion: >=constantinople // ---- // constructor(), 23 wei -> -// gas legacy: 100517 +// gas legacy: 56667 +// gas legacy code: 42000 // f() -> 0 // g() -> 1 // h() -> 23 diff --git a/test/libsolidity/semanticTests/various/contract_binary_dependencies.sol b/test/libsolidity/semanticTests/various/contract_binary_dependencies.sol index 0ebf772fb..d1fae4b7f 100644 --- a/test/libsolidity/semanticTests/various/contract_binary_dependencies.sol +++ b/test/libsolidity/semanticTests/various/contract_binary_dependencies.sol @@ -17,4 +17,5 @@ contract C { } // ---- // constructor() -> -// gas irOptimized: 100415 +// gas irOptimized: 56611 +// gas irOptimized code: 39400 diff --git a/test/libsolidity/semanticTests/various/erc20.sol b/test/libsolidity/semanticTests/various/erc20.sol index 1cc77270f..13b914d9b 100644 --- a/test/libsolidity/semanticTests/various/erc20.sol +++ b/test/libsolidity/semanticTests/various/erc20.sol @@ -103,29 +103,29 @@ contract ERC20 { // gas legacyOptimized: 126934 // gas legacyOptimized code: 282000 // totalSupply() -> 20 -// gas irOptimized: 23415 -// gas legacy: 23524 -// gas legacyOptimized: 23368 +// gas irOptimized: 23334 +// gas legacy: 23519 +// gas legacyOptimized: 23367 // transfer(address,uint256): 2, 5 -> true // ~ emit Transfer(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x05 -// gas irOptimized: 48471 -// gas legacy: 49317 -// gas legacyOptimized: 48491 +// gas irOptimized: 51054 +// gas legacy: 52073 +// gas legacyOptimized: 51298 // decreaseAllowance(address,uint256): 2, 0 -> true // ~ emit Approval(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x00 -// gas irOptimized: 26275 -// gas legacy: 27012 -// gas legacyOptimized: 26275 +// gas irOptimized: 26087 +// gas legacy: 26977 +// gas legacyOptimized: 26279 // decreaseAllowance(address,uint256): 2, 1 -> FAILURE, hex"4e487b71", 0x11 -// gas irOptimized: 24042 -// gas legacy: 24467 +// gas irOptimized: 23981 +// gas legacy: 24462 // gas legacyOptimized: 24056 // transfer(address,uint256): 2, 14 -> true // ~ emit Transfer(address,address,uint256): #0x1212121212121212121212121212120000000012, #0x02, 0x0e -// gas irOptimized: 28571 -// gas legacy: 29417 -// gas legacyOptimized: 28591 +// gas irOptimized: 33954 +// gas legacy: 34973 +// gas legacyOptimized: 34198 // transfer(address,uint256): 2, 2 -> FAILURE, hex"4e487b71", 0x11 -// gas irOptimized: 24071 -// gas legacy: 24453 -// gas legacyOptimized: 24053 +// gas irOptimized: 24020 +// gas legacy: 24445 +// gas legacyOptimized: 24052 From da092b5b2640b74df6ed20aa404e3e3f4eddff4e Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Tue, 16 Dec 2025 17:00:02 +0100 Subject: [PATCH 1042/1340] Move constantinople and petersburg runs to nightly --- .circleci/config.yml | 2 +- .circleci/soltest_all.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 69ae1999f..3cab7fbad 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1328,7 +1328,7 @@ jobs: - attach_workspace: at: build - run_soltest_all: - evm_versions: homestead byzantium + evm_versions: homestead byzantium constantinople petersburg - store_test_results: path: test_results/ - store_artifacts_test_results diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 8d6fc486b..effbc33da 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -31,7 +31,7 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" -DEFAULT_EVM_VALUES=(constantinople petersburg istanbul berlin london paris shanghai cancun prague osaka) +DEFAULT_EVM_VALUES=(istanbul berlin london paris shanghai cancun prague osaka) EVMS_WITH_EOF=(osaka) # Deserialize the EVM_VALUES array if it was provided as argument or From eaaba5f4a581605d0ecdf52c910792ccc5f6aa90 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 8 Dec 2025 17:17:00 +0100 Subject: [PATCH 1043/1340] Apply fix --- libsolidity/codegen/ExpressionCompiler.cpp | 1 + libsolidity/codegen/ir/IRGeneratorForStatements.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 85634906e..2927444e2 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -2133,6 +2133,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) dynamic_cast(_memberAccess.annotation().referencedDeclaration) || dynamic_cast(_memberAccess.annotation().referencedDeclaration) || dynamic_cast(_memberAccess.annotation().referencedDeclaration) || + dynamic_cast(_memberAccess.annotation().referencedDeclaration) || category == Type::Category::TypeType || category == Type::Category::Module, "" diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 5902cfef6..66736da5f 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2252,6 +2252,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) dynamic_cast(_memberAccess.annotation().referencedDeclaration) || dynamic_cast(_memberAccess.annotation().referencedDeclaration) || dynamic_cast(_memberAccess.annotation().referencedDeclaration) || + dynamic_cast(_memberAccess.annotation().referencedDeclaration) || category == Type::Category::TypeType || category == Type::Category::Module, "" From 910350b0609a5df76bf26807da840dcbe675d704 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 8 Dec 2025 17:17:09 +0100 Subject: [PATCH 1044/1340] Add tests --- ...t_event_from_module_via_member_access.json | 1046 +++++++++++++++++ ...it_event_from_module_via_member_access.sol | 18 + .../error_from_module_via_member_access.json | 544 +++++++++ .../error_from_module_via_member_access.sol | 22 + ...it_event_from_module_via_member_access.sol | 115 ++ .../error_from_module_via_member_access.sol | 127 ++ ...or_throw_from_module_via_member_access.sol | 31 + ...ent_emit_from_module_via_member_access.sol | 26 + 8 files changed, 1929 insertions(+) create mode 100644 test/libsolidity/ASTJSON/emit_event_from_module_via_member_access.json create mode 100644 test/libsolidity/ASTJSON/emit_event_from_module_via_member_access.sol create mode 100644 test/libsolidity/ASTJSON/error_from_module_via_member_access.json create mode 100644 test/libsolidity/ASTJSON/error_from_module_via_member_access.sol create mode 100644 test/libsolidity/natspecJSON/emit_event_from_module_via_member_access.sol create mode 100644 test/libsolidity/natspecJSON/error_from_module_via_member_access.sol create mode 100644 test/libsolidity/semanticTests/errors/error_throw_from_module_via_member_access.sol create mode 100644 test/libsolidity/semanticTests/events/event_emit_from_module_via_member_access.sol diff --git a/test/libsolidity/ASTJSON/emit_event_from_module_via_member_access.json b/test/libsolidity/ASTJSON/emit_event_from_module_via_member_access.json new file mode 100644 index 000000000..a33847450 --- /dev/null +++ b/test/libsolidity/ASTJSON/emit_event_from_module_via_member_access.json @@ -0,0 +1,1046 @@ +[ +{ + "absolutePath": "A.sol", + "exportedSymbols": { + "AContract": [ + 17 + ], + "TransferA": [ + 8 + ] + }, + "id": 18, + "nodeType": "SourceUnit", + "nodes": [ + { + "anonymous": false, + "eventSelector": "ef0684aa87ada311bea2dad2b653ce28cd604aa1c10a123df8fb2f789c3178f0", + "id": 8, + "name": "TransferA", + "nameLocation": "6:9:1", + "nodeType": "EventDefinition", + "parameters": { + "id": 7, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2, + "indexed": true, + "mutability": "mutable", + "name": "from", + "nameLocation": "32:4:1", + "nodeType": "VariableDeclaration", + "scope": 8, + "src": "16:20:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "16:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 4, + "indexed": true, + "mutability": "mutable", + "name": "to", + "nameLocation": "54:2:1", + "nodeType": "VariableDeclaration", + "scope": 8, + "src": "38:18:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 3, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "38:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 6, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nameLocation": "63:6:1", + "nodeType": "VariableDeclaration", + "scope": 8, + "src": "58:11:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 5, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "58:4:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "15:55:1" + }, + "src": "0:71:1" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "AContract", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 17, + "linearizedBaseContracts": [ + 17 + ], + "name": "AContract", + "nameLocation": "81:9:1", + "nodeType": "ContractDefinition", + "nodes": [ + { + "anonymous": false, + "eventSelector": "665f5beb8eab22c2d0fba9f14e33a83ad719ffbed2f484458c23490e8577adc9", + "id": 16, + "name": "TransferAContract", + "nameLocation": "103:17:1", + "nodeType": "EventDefinition", + "parameters": { + "id": 15, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 10, + "indexed": true, + "mutability": "mutable", + "name": "from", + "nameLocation": "137:4:1", + "nodeType": "VariableDeclaration", + "scope": 16, + "src": "121:20:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 9, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "121:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 12, + "indexed": true, + "mutability": "mutable", + "name": "to", + "nameLocation": "159:2:1", + "nodeType": "VariableDeclaration", + "scope": 16, + "src": "143:18:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 11, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "143:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 14, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nameLocation": "168:6:1", + "nodeType": "VariableDeclaration", + "scope": 16, + "src": "163:11:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 13, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "163:4:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "120:55:1" + }, + "src": "97:79:1" + } + ], + "scope": 18, + "src": "72:106:1", + "usedErrors": [], + "usedEvents": [ + 16 + ] + } + ], + "src": "0:179:1" +}, +{ + "absolutePath": "ERC20.sol", + "exportedSymbols": { + "A": [ + 19 + ], + "ERC20": [ + 74 + ] + }, + "id": 75, + "nodeType": "SourceUnit", + "nodes": [ + { + "absolutePath": "A.sol", + "file": "A.sol", + "id": 19, + "nameLocation": "12:1:2", + "nodeType": "ImportDirective", + "scope": 75, + "sourceUnit": 18, + "src": "0:27:2", + "symbolAliases": [], + "unitAlias": "A" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "ERC20", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 74, + "linearizedBaseContracts": [ + 74 + ], + "name": "ERC20", + "nameLocation": "37:5:2", + "nodeType": "ContractDefinition", + "nodes": [ + { + "anonymous": false, + "eventSelector": "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "id": 27, + "name": "Transfer", + "nameLocation": "55:8:2", + "nodeType": "EventDefinition", + "parameters": { + "id": 26, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 21, + "indexed": true, + "mutability": "mutable", + "name": "from", + "nameLocation": "80:4:2", + "nodeType": "VariableDeclaration", + "scope": 27, + "src": "64:20:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 20, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "64:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 23, + "indexed": true, + "mutability": "mutable", + "name": "to", + "nameLocation": "102:2:2", + "nodeType": "VariableDeclaration", + "scope": 27, + "src": "86:18:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 22, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "86:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 25, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nameLocation": "111:6:2", + "nodeType": "VariableDeclaration", + "scope": 27, + "src": "106:11:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 24, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "106:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "63:55:2" + }, + "src": "49:70:2" + }, + { + "body": { + "id": 72, + "nodeType": "Block", + "src": "145:181:2", + "statements": [ + { + "eventCall": { + "arguments": [ + { + "arguments": [ + { + "hexValue": "31", + "id": 33, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "177:1:2", + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "id": 32, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "169:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 31, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "169:7:2", + "typeDescriptions": {} + } + }, + "id": 34, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "169:10:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "arguments": [ + { + "hexValue": "32", + "id": 37, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "189:1:2", + "typeDescriptions": { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + }, + "value": "2" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + } + ], + "id": 36, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "181:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 35, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "181:7:2", + "typeDescriptions": {} + } + }, + "id": 38, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "181:10:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "hexValue": "33", + "id": 39, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "193:1:2", + "typeDescriptions": { + "typeIdentifier": "t_rational_3_by_1", + "typeString": "int_const 3" + }, + "value": "3" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_rational_3_by_1", + "typeString": "int_const 3" + } + ], + "id": 30, + "name": "Transfer", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 27, + "src": "160:8:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,address,uint256)" + } + }, + "id": 40, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "160:35:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 41, + "nodeType": "EmitStatement", + "src": "155:40:2" + }, + { + "eventCall": { + "arguments": [ + { + "arguments": [ + { + "hexValue": "31", + "id": 47, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "230:1:2", + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "id": 46, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "222:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 45, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "222:7:2", + "typeDescriptions": {} + } + }, + "id": 48, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "222:10:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "arguments": [ + { + "hexValue": "32", + "id": 51, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "242:1:2", + "typeDescriptions": { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + }, + "value": "2" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + } + ], + "id": 50, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "234:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 49, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "234:7:2", + "typeDescriptions": {} + } + }, + "id": 52, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "234:10:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "hexValue": "33", + "id": 53, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "246:1:2", + "typeDescriptions": { + "typeIdentifier": "t_rational_3_by_1", + "typeString": "int_const 3" + }, + "value": "3" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_rational_3_by_1", + "typeString": "int_const 3" + } + ], + "expression": { + "id": 42, + "name": "A", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 19, + "src": "210:1:2", + "typeDescriptions": { + "typeIdentifier": "t_module_18", + "typeString": "module \"A.sol\"" + } + }, + "id": 44, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "212:9:2", + "memberName": "TransferA", + "nodeType": "MemberAccess", + "referencedDeclaration": 8, + "src": "210:11:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,address,uint256)" + } + }, + "id": 54, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "210:38:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 55, + "nodeType": "EmitStatement", + "src": "205:43:2" + }, + { + "eventCall": { + "arguments": [ + { + "arguments": [ + { + "hexValue": "31", + "id": 63, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "301:1:2", + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "id": 62, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "293:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 61, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "293:7:2", + "typeDescriptions": {} + } + }, + "id": 64, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "293:10:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "arguments": [ + { + "hexValue": "32", + "id": 67, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "313:1:2", + "typeDescriptions": { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + }, + "value": "2" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + } + ], + "id": 66, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "305:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 65, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "305:7:2", + "typeDescriptions": {} + } + }, + "id": 68, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "305:10:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "hexValue": "33", + "id": 69, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "317:1:2", + "typeDescriptions": { + "typeIdentifier": "t_rational_3_by_1", + "typeString": "int_const 3" + }, + "value": "3" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_rational_3_by_1", + "typeString": "int_const 3" + } + ], + "expression": { + "expression": { + "id": 56, + "name": "A", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 19, + "src": "263:1:2", + "typeDescriptions": { + "typeIdentifier": "t_module_18", + "typeString": "module \"A.sol\"" + } + }, + "id": 59, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "265:9:2", + "memberName": "AContract", + "nodeType": "MemberAccess", + "referencedDeclaration": 17, + "src": "263:11:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_AContract_$17_$", + "typeString": "type(contract AContract)" + } + }, + "id": 60, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "275:17:2", + "memberName": "TransferAContract", + "nodeType": "MemberAccess", + "referencedDeclaration": 16, + "src": "263:29:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,address,uint256)" + } + }, + "id": 70, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "263:56:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 71, + "nodeType": "EmitStatement", + "src": "258:61:2" + } + ] + }, + "functionSelector": "26121ff0", + "id": 73, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f", + "nameLocation": "133:1:2", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 28, + "nodeType": "ParameterList", + "parameters": [], + "src": "135:2:2" + }, + "returnParameters": { + "id": 29, + "nodeType": "ParameterList", + "parameters": [], + "src": "145:0:2" + }, + "scope": 74, + "src": "124:202:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + } + ], + "scope": 75, + "src": "28:300:2", + "usedErrors": [], + "usedEvents": [ + 8, + 16, + 27 + ] + } + ], + "src": "0:329:2" +} +] diff --git a/test/libsolidity/ASTJSON/emit_event_from_module_via_member_access.sol b/test/libsolidity/ASTJSON/emit_event_from_module_via_member_access.sol new file mode 100644 index 000000000..fa9614e21 --- /dev/null +++ b/test/libsolidity/ASTJSON/emit_event_from_module_via_member_access.sol @@ -0,0 +1,18 @@ +==== Source: A.sol ==== +event TransferA(address indexed from, address indexed to, uint amount); +contract AContract { + event TransferAContract(address indexed from, address indexed to, uint amount); +} + +==== Source: ERC20.sol ==== +import * as A from "A.sol"; +contract ERC20 { + event Transfer(address indexed from, address indexed to, uint amount); + function f () public { + emit Transfer(address(1), address(2), 3); + emit A.TransferA(address(1), address(2), 3); + emit A.AContract.TransferAContract(address(1), address(2), 3); + } +} + +// ---- diff --git a/test/libsolidity/ASTJSON/error_from_module_via_member_access.json b/test/libsolidity/ASTJSON/error_from_module_via_member_access.json new file mode 100644 index 000000000..db9062891 --- /dev/null +++ b/test/libsolidity/ASTJSON/error_from_module_via_member_access.json @@ -0,0 +1,544 @@ +[ +{ + "absolutePath": "A.sol", + "exportedSymbols": { + "AContract": [ + 9 + ], + "ErrorA": [ + 4 + ] + }, + "id": 10, + "nodeType": "SourceUnit", + "nodes": [ + { + "errorSelector": "23b0db14", + "id": 4, + "name": "ErrorA", + "nameLocation": "6:6:1", + "nodeType": "ErrorDefinition", + "parameters": { + "id": 3, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2, + "mutability": "mutable", + "name": "msg", + "nameLocation": "20:3:1", + "nodeType": "VariableDeclaration", + "scope": 4, + "src": "13:10:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 1, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "13:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "12:12:1" + }, + "src": "0:25:1" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "AContract", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 9, + "linearizedBaseContracts": [ + 9 + ], + "name": "AContract", + "nameLocation": "35:9:1", + "nodeType": "ContractDefinition", + "nodes": [ + { + "errorSelector": "e00f4941", + "id": 8, + "name": "ErrorAContract", + "nameLocation": "57:14:1", + "nodeType": "ErrorDefinition", + "parameters": { + "id": 7, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 6, + "mutability": "mutable", + "name": "msg", + "nameLocation": "79:3:1", + "nodeType": "VariableDeclaration", + "scope": 8, + "src": "72:10:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 5, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "72:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "71:12:1" + }, + "src": "51:33:1" + } + ], + "scope": 10, + "src": "26:60:1", + "usedErrors": [ + 8 + ], + "usedEvents": [] + } + ], + "src": "0:87:1" +}, +{ + "absolutePath": "B.sol", + "exportedSymbols": { + "A": [ + 11 + ], + "BContract": [ + 46 + ] + }, + "id": 47, + "nodeType": "SourceUnit", + "nodes": [ + { + "absolutePath": "A.sol", + "file": "A.sol", + "id": 11, + "nameLocation": "12:1:2", + "nodeType": "ImportDirective", + "scope": 47, + "sourceUnit": 10, + "src": "0:27:2", + "symbolAliases": [], + "unitAlias": "A" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "BContract", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 46, + "linearizedBaseContracts": [ + 46 + ], + "name": "BContract", + "nameLocation": "37:9:2", + "nodeType": "ContractDefinition", + "nodes": [ + { + "errorSelector": "1e012d26", + "id": 15, + "name": "ErrorBContract", + "nameLocation": "59:14:2", + "nodeType": "ErrorDefinition", + "parameters": { + "id": 14, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 13, + "mutability": "mutable", + "name": "msg", + "nameLocation": "81:3:2", + "nodeType": "VariableDeclaration", + "scope": 15, + "src": "74:10:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 12, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "74:6:2", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "73:12:2" + }, + "src": "53:33:2" + }, + { + "body": { + "id": 22, + "nodeType": "Block", + "src": "113:52:2", + "statements": [ + { + "errorCall": { + "arguments": [ + { + "hexValue": "736f6d65206572726f72", + "id": 19, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "145:12:2", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_b4ae9cd779cde5df80ff601d28c3fa893d24133d1b4e6fdffbb3a05b40d7a577", + "typeString": "literal_string \"some error\"" + }, + "value": "some error" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_b4ae9cd779cde5df80ff601d28c3fa893d24133d1b4e6fdffbb3a05b40d7a577", + "typeString": "literal_string \"some error\"" + } + ], + "id": 18, + "name": "ErrorBContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 15, + "src": "130:14:2", + "typeDescriptions": { + "typeIdentifier": "t_function_error_pure$_t_string_memory_ptr_$returns$_t_error_$", + "typeString": "function (string memory) pure returns (error)" + } + }, + "id": 20, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "130:28:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_error", + "typeString": "error" + } + }, + "id": 21, + "nodeType": "RevertStatement", + "src": "123:35:2" + } + ] + }, + "functionSelector": "c27fc305", + "id": 23, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f1", + "nameLocation": "100:2:2", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 16, + "nodeType": "ParameterList", + "parameters": [], + "src": "103:2:2" + }, + "returnParameters": { + "id": 17, + "nodeType": "ParameterList", + "parameters": [], + "src": "113:0:2" + }, + "scope": 46, + "src": "91:74:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 32, + "nodeType": "Block", + "src": "192:46:2", + "statements": [ + { + "errorCall": { + "arguments": [ + { + "hexValue": "736f6d65206572726f72", + "id": 29, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "218:12:2", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_b4ae9cd779cde5df80ff601d28c3fa893d24133d1b4e6fdffbb3a05b40d7a577", + "typeString": "literal_string \"some error\"" + }, + "value": "some error" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_b4ae9cd779cde5df80ff601d28c3fa893d24133d1b4e6fdffbb3a05b40d7a577", + "typeString": "literal_string \"some error\"" + } + ], + "expression": { + "id": 26, + "name": "A", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 11, + "src": "209:1:2", + "typeDescriptions": { + "typeIdentifier": "t_module_10", + "typeString": "module \"A.sol\"" + } + }, + "id": 28, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "211:6:2", + "memberName": "ErrorA", + "nodeType": "MemberAccess", + "referencedDeclaration": 4, + "src": "209:8:2", + "typeDescriptions": { + "typeIdentifier": "t_function_error_pure$_t_string_memory_ptr_$returns$_t_error_$", + "typeString": "function (string memory) pure returns (error)" + } + }, + "id": 30, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "209:22:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_error", + "typeString": "error" + } + }, + "id": 31, + "nodeType": "RevertStatement", + "src": "202:29:2" + } + ] + }, + "functionSelector": "9942ec6f", + "id": 33, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f2", + "nameLocation": "179:2:2", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 24, + "nodeType": "ParameterList", + "parameters": [], + "src": "182:2:2" + }, + "returnParameters": { + "id": 25, + "nodeType": "ParameterList", + "parameters": [], + "src": "192:0:2" + }, + "scope": 46, + "src": "170:68:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 44, + "nodeType": "Block", + "src": "265:64:2", + "statements": [ + { + "errorCall": { + "arguments": [ + { + "hexValue": "736f6d65206572726f72", + "id": 41, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "309:12:2", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_b4ae9cd779cde5df80ff601d28c3fa893d24133d1b4e6fdffbb3a05b40d7a577", + "typeString": "literal_string \"some error\"" + }, + "value": "some error" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_b4ae9cd779cde5df80ff601d28c3fa893d24133d1b4e6fdffbb3a05b40d7a577", + "typeString": "literal_string \"some error\"" + } + ], + "expression": { + "expression": { + "id": 36, + "name": "A", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 11, + "src": "282:1:2", + "typeDescriptions": { + "typeIdentifier": "t_module_10", + "typeString": "module \"A.sol\"" + } + }, + "id": 39, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "284:9:2", + "memberName": "AContract", + "nodeType": "MemberAccess", + "referencedDeclaration": 9, + "src": "282:11:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_AContract_$9_$", + "typeString": "type(contract AContract)" + } + }, + "id": 40, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "294:14:2", + "memberName": "ErrorAContract", + "nodeType": "MemberAccess", + "referencedDeclaration": 8, + "src": "282:26:2", + "typeDescriptions": { + "typeIdentifier": "t_function_error_pure$_t_string_memory_ptr_$returns$_t_error_$", + "typeString": "function (string memory) pure returns (error)" + } + }, + "id": 42, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "282:40:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_error", + "typeString": "error" + } + }, + "id": 43, + "nodeType": "RevertStatement", + "src": "275:47:2" + } + ] + }, + "functionSelector": "aaf05f3d", + "id": 45, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "f3", + "nameLocation": "252:2:2", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 34, + "nodeType": "ParameterList", + "parameters": [], + "src": "255:2:2" + }, + "returnParameters": { + "id": 35, + "nodeType": "ParameterList", + "parameters": [], + "src": "265:0:2" + }, + "scope": 46, + "src": "243:86:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + } + ], + "scope": 47, + "src": "28:303:2", + "usedErrors": [ + 4, + 8, + 15 + ], + "usedEvents": [] + } + ], + "src": "0:332:2" +} +] diff --git a/test/libsolidity/ASTJSON/error_from_module_via_member_access.sol b/test/libsolidity/ASTJSON/error_from_module_via_member_access.sol new file mode 100644 index 000000000..74c29fabb --- /dev/null +++ b/test/libsolidity/ASTJSON/error_from_module_via_member_access.sol @@ -0,0 +1,22 @@ +==== Source: A.sol ==== +error ErrorA(string msg); +contract AContract { + error ErrorAContract(string msg); +} + +==== Source: B.sol ==== +import * as A from "A.sol"; +contract BContract { + error ErrorBContract(string msg); + function f1 () public { + revert ErrorBContract("some error"); + } + function f2 () public { + revert A.ErrorA("some error"); + } + function f3 () public { + revert A.AContract.ErrorAContract("some error"); + } +} + +// ---- diff --git a/test/libsolidity/natspecJSON/emit_event_from_module_via_member_access.sol b/test/libsolidity/natspecJSON/emit_event_from_module_via_member_access.sol new file mode 100644 index 000000000..39d1644fe --- /dev/null +++ b/test/libsolidity/natspecJSON/emit_event_from_module_via_member_access.sol @@ -0,0 +1,115 @@ +==== Source: A.sol ==== +/// @notice This event is emitted when a transfer from A occurs. +/// @param from The source account. +/// @param to The destination account. +/// @param amount The amount. +/// @dev A test case! +event TransferA(address indexed from, address indexed to, uint amount); + +contract AContract { + /// @notice This event is emitted when a transfer from AContract occurs. + /// @param from The source account. + /// @param to The destination account. + /// @param amount The amount. + /// @dev A test case! + event TransferAContract(address indexed from, address indexed to, uint amount); +} + +==== Source: ERC20.sol ==== +import * as A from "A.sol"; +contract ERC20 { + /// @notice This event is emitted when a transfer from ERC20 occurs. + /// @param from The source account. + /// @param to The destination account. + /// @param amount The amount. + /// @dev A test case! + event Transfer(address indexed from, address indexed to, uint amount); + + function test() public { + emit Transfer(address(1), address(5), 1); + emit A.AContract.TransferAContract(address(1), address(5), 1); + emit A.TransferA(address(1), address(5), 1); + } +} + +// ---- +// ---- +// A.sol:AContract devdoc +// { +// "events": { +// "TransferAContract(address,address,uint256)": { +// "details": "A test case!", +// "params": { +// "amount": "The amount.", +// "from": "The source account.", +// "to": "The destination account." +// } +// } +// }, +// "kind": "dev", +// "methods": {}, +// "version": 1 +// } +// +// A.sol:AContract userdoc +// { +// "events": { +// "TransferAContract(address,address,uint256)": { +// "notice": "This event is emitted when a transfer from AContract occurs." +// } +// }, +// "kind": "user", +// "methods": {}, +// "version": 1 +// } +// +// ERC20.sol:ERC20 devdoc +// { +// "events": { +// "Transfer(address,address,uint256)": { +// "details": "A test case!", +// "params": { +// "amount": "The amount.", +// "from": "The source account.", +// "to": "The destination account." +// } +// }, +// "TransferA(address,address,uint256)": { +// "details": "A test case!", +// "params": { +// "amount": "The amount.", +// "from": "The source account.", +// "to": "The destination account." +// } +// }, +// "TransferAContract(address,address,uint256)": { +// "details": "A test case!", +// "params": { +// "amount": "The amount.", +// "from": "The source account.", +// "to": "The destination account." +// } +// } +// }, +// "kind": "dev", +// "methods": {}, +// "version": 1 +// } +// +// ERC20.sol:ERC20 userdoc +// { +// "events": { +// "Transfer(address,address,uint256)": { +// "notice": "This event is emitted when a transfer from ERC20 occurs." +// }, +// "TransferA(address,address,uint256)": { +// "notice": "This event is emitted when a transfer from A occurs." +// }, +// "TransferAContract(address,address,uint256)": { +// "notice": "This event is emitted when a transfer from AContract occurs." +// } +// }, +// "kind": "user", +// "methods": {}, +// "version": 1 +// } diff --git a/test/libsolidity/natspecJSON/error_from_module_via_member_access.sol b/test/libsolidity/natspecJSON/error_from_module_via_member_access.sol new file mode 100644 index 000000000..0c2e44e3c --- /dev/null +++ b/test/libsolidity/natspecJSON/error_from_module_via_member_access.sol @@ -0,0 +1,127 @@ +==== Source: A.sol ==== +/// Something failed. +/// @dev an error. +/// @param a first parameter +/// @param b second parameter +error E(uint a, uint b); + +contract AContract { + /// Something failed. + /// @dev an error. + /// @param a first parameter + /// @param b second parameter + error EAContract(uint a, uint b); +} + +==== Source: ERC20.sol ==== +import * as A from "A.sol"; +contract ERC20 { + /// Something failed. + /// @dev an error. + /// @param a first parameter + /// @param b second parameter + error EERC20(uint a, uint b); + + function f(uint a) public pure { + if (a > 0) + revert EERC20(1, 2); + else if (a < 0) + revert A.AContract.EAContract(5, 6); + else + revert A.E(5, 6); + } +} + +// ---- +// ---- +// A.sol:AContract devdoc +// { +// "errors": { +// "EAContract(uint256,uint256)": [ +// { +// "details": "an error.", +// "params": { +// "a": "first parameter", +// "b": "second parameter" +// } +// } +// ] +// }, +// "kind": "dev", +// "methods": {}, +// "version": 1 +// } +// +// A.sol:AContract userdoc +// { +// "errors": { +// "EAContract(uint256,uint256)": [ +// { +// "notice": "Something failed." +// } +// ] +// }, +// "kind": "user", +// "methods": {}, +// "version": 1 +// } +// +// ERC20.sol:ERC20 devdoc +// { +// "errors": { +// "E(uint256,uint256)": [ +// { +// "details": "an error.", +// "params": { +// "a": "first parameter", +// "b": "second parameter" +// } +// } +// ], +// "EAContract(uint256,uint256)": [ +// { +// "details": "an error.", +// "params": { +// "a": "first parameter", +// "b": "second parameter" +// } +// } +// ], +// "EERC20(uint256,uint256)": [ +// { +// "details": "an error.", +// "params": { +// "a": "first parameter", +// "b": "second parameter" +// } +// } +// ] +// }, +// "kind": "dev", +// "methods": {}, +// "version": 1 +// } +// +// ERC20.sol:ERC20 userdoc +// { +// "errors": { +// "E(uint256,uint256)": [ +// { +// "notice": "Something failed." +// } +// ], +// "EAContract(uint256,uint256)": [ +// { +// "notice": "Something failed." +// } +// ], +// "EERC20(uint256,uint256)": [ +// { +// "notice": "Something failed." +// } +// ] +// }, +// "kind": "user", +// "methods": {}, +// "version": 1 +// } diff --git a/test/libsolidity/semanticTests/errors/error_throw_from_module_via_member_access.sol b/test/libsolidity/semanticTests/errors/error_throw_from_module_via_member_access.sol new file mode 100644 index 000000000..f9b968694 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/error_throw_from_module_via_member_access.sol @@ -0,0 +1,31 @@ +==== Source: A.sol ==== +error ErrorA(string msg); +==== Source: B.sol ==== +import * as A from "A.sol"; + +error ErrorB(string msg); + +contract BContract { + error ErrorB(string msg); +} +==== Source: C.sol ==== +import * as B from "B.sol"; + +contract CContract { + function error1() external { + revert B.ErrorB("B error"); + } + + function error2() external { + revert B.BContract.ErrorB("B.BContract error"); + } + + function error3() external { + revert B.A.ErrorA("B.A error"); + } +} + +// ---- +// error1() -> FAILURE, hex"a5f9ec67", 0x20, 7, "B error" +// error2() -> FAILURE, hex"a5f9ec67", 0x20, 17, "B.BContract error" +// error3() -> FAILURE, hex"23b0db14", 0x20, 9, "B.A error" diff --git a/test/libsolidity/semanticTests/events/event_emit_from_module_via_member_access.sol b/test/libsolidity/semanticTests/events/event_emit_from_module_via_member_access.sol new file mode 100644 index 000000000..b944ea114 --- /dev/null +++ b/test/libsolidity/semanticTests/events/event_emit_from_module_via_member_access.sol @@ -0,0 +1,26 @@ +==== Source: A.sol ==== +event Transfer(address indexed _from, address indexed _to, uint256 _value); +==== Source: B.sol ==== +import * as A from "A.sol"; + +event Transfer(address indexed _from, address indexed _to, uint256 _value); + +contract BContract { + event Transfer(address indexed _from, address indexed _to, uint256 _value); +} +==== Source: C.sol ==== +import * as B from "B.sol"; + +contract CContract { + function returnAddress() external { + emit B.Transfer(address(0x0b), address(0x0c), 0x0d); + emit B.BContract.Transfer(address(0x0e), address(0x0f), 0x10); + emit B.A.Transfer(address(0x11), address(0x12), 0x13); + } +} + +// ---- +// returnAddress() -> +// ~ emit Transfer(address,address,uint256): #0x0b, #0x0c, 0x0d +// ~ emit Transfer(address,address,uint256): #0x0e, #0x0f, 0x10 +// ~ emit Transfer(address,address,uint256): #0x11, #0x12, 0x13 From 53a9efb068522a92ad89d487e8aa30389e700ee9 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 10 Dec 2025 14:27:12 +0100 Subject: [PATCH 1045/1340] Update parser error message and tests results. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- libsolidity/parsing/Parser.cpp | 2 +- .../standard_outputs_on_parsing_error/output.json | 4 ++-- .../syntaxTests/freeFunctions/free_constructor.sol | 2 +- test/libsolidity/syntaxTests/freeFunctions/free_fallback.sol | 2 +- test/libsolidity/syntaxTests/freeFunctions/free_receive.sol | 2 +- test/libsolidity/syntaxTests/parsing/unexpected.sol | 2 +- .../layout_specified_by_function_empty_call_options.sol | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index ddffdb600..77b702673 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -170,7 +170,7 @@ ASTPointer Parser::parse(CharStream& _charStream) expectToken(Token::Semicolon); } else - fatalParserError(7858_error, "Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition."); + fatalParserError(7858_error, "Expected pragma, import directive or contract/interface/library/user-defined type/constant/function/error/event definition."); } } solAssert(m_recursionDepth == 0, ""); diff --git a/test/cmdlineTests/standard_outputs_on_parsing_error/output.json b/test/cmdlineTests/standard_outputs_on_parsing_error/output.json index 6730d772e..39610363e 100644 --- a/test/cmdlineTests/standard_outputs_on_parsing_error/output.json +++ b/test/cmdlineTests/standard_outputs_on_parsing_error/output.json @@ -3,14 +3,14 @@ { "component": "general", "errorCode": "7858", - "formattedMessage": "ParserError: Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition. + "formattedMessage": "ParserError: Expected pragma, import directive or contract/interface/library/user-defined type/constant/function/error/event definition. --> C:5:14: | 5 | contract C {}} | ^ ", - "message": "Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition.", + "message": "Expected pragma, import directive or contract/interface/library/user-defined type/constant/function/error/event definition.", "severity": "error", "sourceLocation": { "end": 121, diff --git a/test/libsolidity/syntaxTests/freeFunctions/free_constructor.sol b/test/libsolidity/syntaxTests/freeFunctions/free_constructor.sol index 787898357..5e263606d 100644 --- a/test/libsolidity/syntaxTests/freeFunctions/free_constructor.sol +++ b/test/libsolidity/syntaxTests/freeFunctions/free_constructor.sol @@ -1,3 +1,3 @@ constructor() {} // ---- -// ParserError 7858: (0-11): Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition. +// ParserError 7858: (0-11): Expected pragma, import directive or contract/interface/library/user-defined type/constant/function/error/event definition. diff --git a/test/libsolidity/syntaxTests/freeFunctions/free_fallback.sol b/test/libsolidity/syntaxTests/freeFunctions/free_fallback.sol index 897ed5964..cec4c7de0 100644 --- a/test/libsolidity/syntaxTests/freeFunctions/free_fallback.sol +++ b/test/libsolidity/syntaxTests/freeFunctions/free_fallback.sol @@ -1,3 +1,3 @@ fallback(){} // ---- -// ParserError 7858: (0-8): Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition. +// ParserError 7858: (0-8): Expected pragma, import directive or contract/interface/library/user-defined type/constant/function/error/event definition. diff --git a/test/libsolidity/syntaxTests/freeFunctions/free_receive.sol b/test/libsolidity/syntaxTests/freeFunctions/free_receive.sol index 83dfee446..ad021b221 100644 --- a/test/libsolidity/syntaxTests/freeFunctions/free_receive.sol +++ b/test/libsolidity/syntaxTests/freeFunctions/free_receive.sol @@ -1,3 +1,3 @@ receive() {} // ---- -// ParserError 7858: (0-7): Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition. +// ParserError 7858: (0-7): Expected pragma, import directive or contract/interface/library/user-defined type/constant/function/error/event definition. diff --git a/test/libsolidity/syntaxTests/parsing/unexpected.sol b/test/libsolidity/syntaxTests/parsing/unexpected.sol index c6fae414c..9dd495c8b 100644 --- a/test/libsolidity/syntaxTests/parsing/unexpected.sol +++ b/test/libsolidity/syntaxTests/parsing/unexpected.sol @@ -1,3 +1,3 @@ unexpected // ---- -// ParserError 7858: (0-10): Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition. +// ParserError 7858: (0-10): Expected pragma, import directive or contract/interface/library/user-defined type/constant/function/error/event definition. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_empty_call_options.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_empty_call_options.sol index e0b1f4e5c..79bcb8878 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_empty_call_options.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_function_empty_call_options.sol @@ -3,4 +3,4 @@ contract A { } contract C is A layout at this.f{}() {} // ---- -// ParserError 7858: (98-99): Expected pragma, import directive or contract/interface/library/struct/enum/constant/function/error definition. +// ParserError 7858: (98-99): Expected pragma, import directive or contract/interface/library/user-defined type/constant/function/error/event definition. From dad604cbdfc79f8f70b6c8433082b4b66fe76cec Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 10 Dec 2025 14:37:19 +0100 Subject: [PATCH 1046/1340] Update changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 42d679caa..7ed3d7ef6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: Bugfixes: +* Codegen: Fix internal compiler error when emitting events via module member access. * TypeChecker: Fix error and event selectors not being considered compile-time constant. From 2d6ecc5f501f49b6537a6756e12e5a60e9e46cd7 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Wed, 17 Dec 2025 13:49:09 -0300 Subject: [PATCH 1047/1340] legacy: Fix handling of storage array boundaries (deletion, cleanup, and copy) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniel Kirchner Co-authored-by: clonker <1685266+clonker@users.noreply.github.com> Co-authored-by: Kamil Śliwak --- libsolidity/codegen/ArrayUtils.cpp | 469 ++++------------------------- libsolidity/codegen/ArrayUtils.h | 10 +- 2 files changed, 68 insertions(+), 411 deletions(-) diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index 455cfe084..841161fa9 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -46,256 +46,65 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons // this copies source to target and also clears target if it was larger // need to leave "target_ref target_byte_off" on the stack at the end - // stack layout: [source_ref] [source length] target_ref (top) + // stack layout: source_ref [source length] target_ref (top) solAssert(_targetType.location() == DataLocation::Storage, ""); - Type const* targetBaseType = _targetType.baseType(); - Type const* sourceBaseType = _sourceType.baseType(); - // TODO unroll loop for small sizes - bool sourceIsStorage = _sourceType.location() == DataLocation::Storage; bool fromCalldata = _sourceType.location() == DataLocation::CallData; - bool directCopy = sourceIsStorage && sourceBaseType->isValueType() && *sourceBaseType == *targetBaseType; - bool haveByteOffsetSource = !directCopy && sourceIsStorage && sourceBaseType->storageBytes() <= 16; - bool haveByteOffsetTarget = !directCopy && targetBaseType->storageBytes() <= 16; - unsigned byteOffsetSize = (haveByteOffsetSource ? 1u : 0u) + (haveByteOffsetTarget ? 1u : 0u); + bool haveSourceLengthOnStack = fromCalldata && _sourceType.isDynamicallySized(); - // stack: source_ref [source_length] target_ref - // store target_ref for (unsigned i = _sourceType.sizeOnStack(); i > 0; --i) m_context << swapInstruction(i); // stack: target_ref source_ref [source_length] - if (_targetType.isByteArrayOrString()) + if (_sourceType.baseType()->category() == Type::Category::Array) { - // stack: target_ref source_ref [source_length] - if (fromCalldata && _sourceType.isDynamicallySized()) - { - // stack: target_ref source_ref source_length - m_context << Instruction::SWAP1; - // stack: target_ref source_length source_ref - m_context << Instruction::DUP3; - // stack: target_ref source_length source_ref target_ref - m_context.callYulFunction( - m_context.utilFunctions().copyByteArrayToStorageFunction(_sourceType, _targetType), - 3, - 0 - ); - } - else - { - // stack: target_ref source_ref - m_context << Instruction::DUP2; - // stack: target_ref source_ref target_ref - m_context.callYulFunction( - m_context.utilFunctions().copyByteArrayToStorageFunction(_sourceType, _targetType), - 2, - 0 - ); - } - // stack: target_ref - return; + // TODO: This limitation can now be removed since we use Yul utility functions that handle nested arrays correctly. + // The old inline assembly implementation couldn't handle nested calldata dynamic arrays, but the Yul functions + // support them through recursive calls. We keep this check temporarily for backward compatibility. + auto const& sourceBaseArrayType = dynamic_cast(*_sourceType.baseType()); + solUnimplementedAssert( + !fromCalldata || + !_sourceType.isDynamicallyEncoded() || + !sourceBaseArrayType.isDynamicallySized(), + "Copying nested calldata dynamic arrays to storage is not implemented in the old code generator." + ); } - - // retrieve source length - if (_sourceType.location() != DataLocation::CallData || !_sourceType.isDynamicallySized()) - retrieveLength(_sourceType); // otherwise, length is already there - if (_sourceType.location() == DataLocation::Memory && _sourceType.isDynamicallySized()) + else { - // increment source pointer to point to data - m_context << Instruction::SWAP1 << u256(0x20); - m_context << Instruction::ADD << Instruction::SWAP1; + // TODO: This limitation can now be removed since we use Yul utility functions that handle non-value types correctly. + // The old inline assembly implementation couldn't handle copying arrays of non-value types from memory or calldata to storage, + // but the Yul functions support them. We keep this check temporarily for backward compatibility. + bool fromMemoryOrCalldata = _sourceType.location() == DataLocation::Memory || _sourceType.location() == DataLocation::CallData; + solUnimplementedAssert( + _sourceType.baseType()->isValueType() || !fromMemoryOrCalldata, + "Copying of type " + _sourceType.toString(false) + " to storage is not supported in legacy (only supported by the IR pipeline). " + + "Hint: try compiling with `--via-ir` (CLI) or the equivalent `viaIR: true` (Standard JSON)." + ); } - // stack: target_ref source_ref source_length - Type const* targetType = &_targetType; - Type const* sourceType = &_sourceType; - m_context.callLowLevelFunction( - "$copyArrayToStorage_" + sourceType->identifier() + "_to_" + targetType->identifier(), - 3, - 1, - [=](CompilerContext& _context) - { - ArrayUtils utils(_context); - ArrayType const& _sourceType = dynamic_cast(*sourceType); - ArrayType const& _targetType = dynamic_cast(*targetType); - // stack: target_ref source_ref source_length - _context << Instruction::DUP3; - // stack: target_ref source_ref source_length target_ref - utils.retrieveLength(_targetType); - // stack: target_ref source_ref source_length target_ref target_length - if (_targetType.isDynamicallySized()) - { - // store new target length - solAssert(!_targetType.isByteArrayOrString()); - _context << Instruction::DUP3 << Instruction::DUP3 << Instruction::SSTORE; - } - if (sourceBaseType->category() == Type::Category::Mapping) - { - solAssert(targetBaseType->category() == Type::Category::Mapping, ""); - solAssert(_sourceType.location() == DataLocation::Storage, ""); - // nothing to copy - _context - << Instruction::POP << Instruction::POP - << Instruction::POP << Instruction::POP; - return; - } - // stack: target_ref source_ref source_length target_ref target_length - // compute hashes (data positions) - _context << Instruction::SWAP1; - if (_targetType.isDynamicallySized()) - CompilerUtils(_context).computeHashStatic(); - // stack: target_ref source_ref source_length target_length target_data_pos - _context << Instruction::SWAP1; - utils.convertLengthToSize(_targetType); - _context << Instruction::DUP2 << Instruction::ADD; - // stack: target_ref source_ref source_length target_data_pos target_data_end - _context << Instruction::SWAP3; - // stack: target_ref target_data_end source_length target_data_pos source_ref - - evmasm::AssemblyItem copyLoopEndWithoutByteOffset = _context.newTag(); - solAssert(!_targetType.isByteArrayOrString()); - // skip copying if source length is zero - _context << Instruction::DUP3 << Instruction::ISZERO; - _context.appendConditionalJumpTo(copyLoopEndWithoutByteOffset); - - if (_sourceType.location() == DataLocation::Storage && _sourceType.isDynamicallySized()) - CompilerUtils(_context).computeHashStatic(); - // stack: target_ref target_data_end source_length target_data_pos source_data_pos - _context << Instruction::SWAP2; - utils.convertLengthToSize(_sourceType); - _context << Instruction::DUP3 << Instruction::ADD; - // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end - if (haveByteOffsetTarget) - _context << u256(0); - if (haveByteOffsetSource) - _context << u256(0); - // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] - evmasm::AssemblyItem copyLoopStart = _context.newTag(); - _context << copyLoopStart; - // check for loop condition - _context - << dupInstruction(3 + byteOffsetSize) << dupInstruction(2 + byteOffsetSize) - << Instruction::GT << Instruction::ISZERO; - evmasm::AssemblyItem copyLoopEnd = _context.appendConditionalJump(); - // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] - // copy - if (sourceBaseType->category() == Type::Category::Array) - { - solAssert(byteOffsetSize == 0, "Byte offset for array as base type."); - auto const& sourceBaseArrayType = dynamic_cast(*sourceBaseType); - - solUnimplementedAssert( - _sourceType.location() != DataLocation::CallData || - !_sourceType.isDynamicallyEncoded() || - !sourceBaseArrayType.isDynamicallySized(), - "Copying nested calldata dynamic arrays to storage is not implemented in the old code generator." - ); - _context << Instruction::DUP3; - if (sourceBaseArrayType.location() == DataLocation::Memory) - _context << Instruction::MLOAD; - _context << Instruction::DUP3; - utils.copyArrayToStorage(dynamic_cast(*targetBaseType), sourceBaseArrayType); - _context << Instruction::POP; - } - else if (directCopy) - { - solAssert(byteOffsetSize == 0, "Byte offset for direct copy."); - _context - << Instruction::DUP3 << Instruction::SLOAD - << Instruction::DUP3 << Instruction::SSTORE; - } - else - { - // Note that we have to copy each element on its own in case conversion is involved. - // We might copy too much if there is padding at the last element, but this way end - // checking is easier. - // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] - _context << dupInstruction(3 + byteOffsetSize); - if (_sourceType.location() == DataLocation::Storage) - { - if (haveByteOffsetSource) - _context << Instruction::DUP2; - else - _context << u256(0); - StorageItem(_context, *sourceBaseType).retrieveValue(SourceLocation(), true); - } - else if (sourceBaseType->isValueType()) - CompilerUtils(_context).loadFromMemoryDynamic(*sourceBaseType, fromCalldata, true, false); - else - solUnimplemented("Copying of type " + _sourceType.toString(false) + " to storage is not supported in legacy (only supported by the IR pipeline). Hint: try compiling with `--via-ir` (CLI) or the equivalent `viaIR: true` (Standard JSON)"); - // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] ... - assertThrow( - 2 + byteOffsetSize + sourceBaseType->sizeOnStack() <= 16, - StackTooDeepError, - util::stackTooDeepString - ); - // fetch target storage reference - _context << dupInstruction(2 + byteOffsetSize + sourceBaseType->sizeOnStack()); - if (haveByteOffsetTarget) - _context << dupInstruction(1 + byteOffsetSize + sourceBaseType->sizeOnStack()); - else - _context << u256(0); - StorageItem(_context, *targetBaseType).storeValue(*sourceBaseType, SourceLocation(), true); - } - // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] - // increment source - if (haveByteOffsetSource) - utils.incrementByteOffset(sourceBaseType->storageBytes(), 1, haveByteOffsetTarget ? 5 : 4); - else - { - _context << swapInstruction(2 + byteOffsetSize); - if (sourceIsStorage) - _context << sourceBaseType->storageSize(); - else if (_sourceType.location() == DataLocation::Memory) - _context << sourceBaseType->memoryHeadSize(); - else - _context << sourceBaseType->calldataHeadSize(); - _context - << Instruction::ADD - << swapInstruction(2 + byteOffsetSize); - } - // increment target - if (haveByteOffsetTarget) - utils.incrementByteOffset(targetBaseType->storageBytes(), byteOffsetSize, byteOffsetSize + 2); - else - _context - << swapInstruction(1 + byteOffsetSize) - << targetBaseType->storageSize() - << Instruction::ADD - << swapInstruction(1 + byteOffsetSize); - _context.appendJumpTo(copyLoopStart); - _context << copyLoopEnd; - if (haveByteOffsetTarget) - { - // clear elements that might be left over in the current slot in target - // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end target_byte_offset [source_byte_offset] - _context << dupInstruction(byteOffsetSize) << Instruction::ISZERO; - evmasm::AssemblyItem copyCleanupLoopEnd = _context.appendConditionalJump(); - _context << dupInstruction(2 + byteOffsetSize) << dupInstruction(1 + byteOffsetSize); - StorageItem(_context, *targetBaseType).setToZero(SourceLocation(), true); - utils.incrementByteOffset(targetBaseType->storageBytes(), byteOffsetSize, byteOffsetSize + 2); - _context.appendJumpTo(copyLoopEnd); - - _context << copyCleanupLoopEnd; - _context << Instruction::POP; // might pop the source, but then target is popped next - } - if (haveByteOffsetSource) - _context << Instruction::POP; - _context << copyLoopEndWithoutByteOffset; + if (haveSourceLengthOnStack) + { + // stack: target_ref source_ref source_length + m_context << Instruction::SWAP1; + // stack: target_ref source_length source_ref + m_context << Instruction::DUP3; + // stack: target_ref source_length source_ref target_ref + } + else + { + // stack: target_ref source_ref + m_context << Instruction::DUP2; + // stack: target_ref source_ref target_ref + } - // zero-out leftovers in target - // stack: target_ref target_data_end source_data_pos target_data_pos_updated source_data_end - _context << Instruction::POP << Instruction::SWAP1 << Instruction::POP; - // stack: target_ref target_data_end target_data_pos_updated - if (targetBaseType->storageBytes() < 32) - utils.clearStorageLoop(TypeProvider::uint256()); - else - utils.clearStorageLoop(targetBaseType); - _context << Instruction::POP; - } + m_context.callYulFunction( + m_context.utilFunctions().copyArrayToStorageFunction(_sourceType, _targetType), + haveSourceLengthOnStack ? 3 : 2, + 0 ); + // stack: target_ref } void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWordBoundaries) const @@ -586,9 +395,9 @@ void ArrayUtils::clearArray(ArrayType const& _typeIn) const } else { - _context << Instruction::DUP1 << _type.length(); + _context << _type.length(); ArrayUtils(_context).convertLengthToSize(_type); - _context << Instruction::ADD << Instruction::SWAP1; + // stack: storage_ref slot_count if (_type.baseType()->storageBytes() < 32) ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256()); else @@ -623,13 +432,12 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const } // stack: ref old_length convertLengthToSize(_type); - // compute data positions + // stack: ref slot_count m_context << Instruction::SWAP1; CompilerUtils(m_context).computeHashStatic(); - // stack: len data_pos - m_context << Instruction::SWAP1 << Instruction::DUP2 << Instruction::ADD - << Instruction::SWAP1; - // stack: data_pos_end data_pos + // stack: slot_count data_pos + m_context << Instruction::SWAP1; + // stack: data_pos slot_count if (_type.storageStride() < 32) clearStorageLoop(TypeProvider::uint256()); else @@ -639,156 +447,6 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const m_context << Instruction::POP; } -void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const -{ - Type const* type = &_typeIn; - m_context.callLowLevelFunction( - "$resizeDynamicArray_" + _typeIn.identifier(), - 2, - 0, - [type](CompilerContext& _context) - { - ArrayType const& _type = dynamic_cast(*type); - solAssert(_type.location() == DataLocation::Storage, ""); - solAssert(_type.isDynamicallySized(), ""); - if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32) - solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type."); - - unsigned stackHeightStart = _context.stackHeight(); - evmasm::AssemblyItem resizeEnd = _context.newTag(); - - // stack: ref new_length - // fetch old length - ArrayUtils(_context).retrieveLength(_type, 1); - // stack: ref new_length old_length - solAssert(_context.stackHeight() - stackHeightStart == 3 - 2, "2"); - - // Special case for short byte arrays, they are stored together with their length - if (_type.isByteArrayOrString()) - { - evmasm::AssemblyItem regularPath = _context.newTag(); - // We start by a large case-distinction about the old and new length of the byte array. - - _context << Instruction::DUP3 << Instruction::SLOAD; - // stack: ref new_length current_length ref_value - - solAssert(_context.stackHeight() - stackHeightStart == 4 - 2, "3"); - _context << Instruction::DUP2 << u256(31) << Instruction::LT; - evmasm::AssemblyItem currentIsLong = _context.appendConditionalJump(); - _context << Instruction::DUP3 << u256(31) << Instruction::LT; - evmasm::AssemblyItem newIsLong = _context.appendConditionalJump(); - - // Here: short -> short - - // Compute 1 << (256 - 8 * new_size) - evmasm::AssemblyItem shortToShort = _context.newTag(); - _context << shortToShort; - _context << Instruction::DUP3 << u256(8) << Instruction::MUL; - _context << u256(0x100) << Instruction::SUB; - _context << u256(2) << Instruction::EXP; - // Divide and multiply by that value, clearing bits. - _context << Instruction::DUP1 << Instruction::SWAP2; - _context << Instruction::DIV << Instruction::MUL; - // Insert 2*length. - _context << Instruction::DUP3 << Instruction::DUP1 << Instruction::ADD; - _context << Instruction::OR; - // Store. - _context << Instruction::DUP4 << Instruction::SSTORE; - solAssert(_context.stackHeight() - stackHeightStart == 3 - 2, "3"); - _context.appendJumpTo(resizeEnd); - - _context.adjustStackOffset(1); // we have to do that because of the jumps - // Here: short -> long - - _context << newIsLong; - // stack: ref new_length current_length ref_value - solAssert(_context.stackHeight() - stackHeightStart == 4 - 2, "3"); - // Zero out lower-order byte. - _context << u256(0xff) << Instruction::NOT << Instruction::AND; - // Store at data location. - _context << Instruction::DUP4; - CompilerUtils(_context).computeHashStatic(); - _context << Instruction::SSTORE; - // stack: ref new_length current_length - // Store new length: Compute 2*length + 1 and store it. - _context << Instruction::DUP2 << Instruction::DUP1 << Instruction::ADD; - _context << u256(1) << Instruction::ADD; - // stack: ref new_length current_length 2*new_length+1 - _context << Instruction::DUP4 << Instruction::SSTORE; - solAssert(_context.stackHeight() - stackHeightStart == 3 - 2, "3"); - _context.appendJumpTo(resizeEnd); - - _context.adjustStackOffset(1); // we have to do that because of the jumps - - _context << currentIsLong; - _context << Instruction::DUP3 << u256(31) << Instruction::LT; - _context.appendConditionalJumpTo(regularPath); - - // Here: long -> short - // Read the first word of the data and store it on the stack. Clear the data location and - // then jump to the short -> short case. - - // stack: ref new_length current_length ref_value - solAssert(_context.stackHeight() - stackHeightStart == 4 - 2, "3"); - _context << Instruction::POP << Instruction::DUP3; - CompilerUtils(_context).computeHashStatic(); - _context << Instruction::DUP1 << Instruction::SLOAD << Instruction::SWAP1; - // stack: ref new_length current_length first_word data_location - _context << Instruction::DUP3; - ArrayUtils(_context).convertLengthToSize(_type); - _context << Instruction::DUP2 << Instruction::ADD << Instruction::SWAP1; - // stack: ref new_length current_length first_word data_location_end data_location - ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256()); - _context << Instruction::POP; - // stack: ref new_length current_length first_word - solAssert(_context.stackHeight() - stackHeightStart == 4 - 2, "3"); - _context.appendJumpTo(shortToShort); - - _context << regularPath; - // stack: ref new_length current_length ref_value - _context << Instruction::POP; - } - - // Change of length for a regular array (i.e. length at location, data at KECCAK256(location)). - // stack: ref new_length old_length - // store new length - _context << Instruction::DUP2; - if (_type.isByteArrayOrString()) - // For a "long" byte array, store length as 2*length+1 - _context << Instruction::DUP1 << Instruction::ADD << u256(1) << Instruction::ADD; - _context << Instruction::DUP4 << Instruction::SSTORE; - // skip if size is not reduced - _context << Instruction::DUP2 << Instruction::DUP2 - << Instruction::GT << Instruction::ISZERO; - _context.appendConditionalJumpTo(resizeEnd); - - // size reduced, clear the end of the array - // stack: ref new_length old_length - ArrayUtils(_context).convertLengthToSize(_type); - _context << Instruction::DUP2; - ArrayUtils(_context).convertLengthToSize(_type); - // stack: ref new_length old_size new_size - // compute data positions - _context << Instruction::DUP4; - CompilerUtils(_context).computeHashStatic(); - // stack: ref new_length old_size new_size data_pos - _context << Instruction::SWAP2 << Instruction::DUP3 << Instruction::ADD; - // stack: ref new_length data_pos new_size delete_end - _context << Instruction::SWAP2 << Instruction::ADD; - // stack: ref new_length delete_end delete_start - if (_type.storageStride() < 32) - ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256()); - else - ArrayUtils(_context).clearStorageLoop(_type.baseType()); - - _context << resizeEnd; - // cleanup - _context << Instruction::POP << Instruction::POP << Instruction::POP; - solAssert(_context.stackHeight() == stackHeightStart - 2, ""); - } - ); -} - void ArrayUtils::incrementDynamicArraySize(ArrayType const& _type) const { solAssert(_type.location() == DataLocation::Storage, ""); @@ -936,29 +594,32 @@ void ArrayUtils::clearStorageLoop(Type const* _type) const _context << Instruction::POP; return; } - // stack: end_pos pos - + // stack: start_pos slot_count + // Initialize loop counter i = 0 + _context << u256(0); + // stack: start_pos slot_count i evmasm::AssemblyItem loopStart = _context.appendJumpToNew(); _context << loopStart; - // check for loop condition - _context << - Instruction::DUP1 << - Instruction::DUP3 << - Instruction::GT << - Instruction::ISZERO; + // check for loop condition: !(slot_count > i) = (i >= slot_count) + _context << Instruction::DUP1 << Instruction::DUP3 << Instruction::GT << Instruction::ISZERO; evmasm::AssemblyItem zeroLoopEnd = _context.newTag(); _context.appendConditionalJumpTo(zeroLoopEnd); - // delete + // stack: start_pos slot_count i + // compute storage position: start_pos + i + _context << Instruction::DUP3 << Instruction::DUP2 << Instruction::ADD; + // stack: start_pos slot_count i (start_pos+i) + // delete storage slot _context << u256(0); - StorageItem(_context, *_type).setToZero(SourceLocation(), false); - _context << Instruction::POP; - // increment + StorageItem(_context, *_type).setToZero(SourceLocation(), /* _removeReference = */ true); + // stack: start_pos slot_count i + // increment counter: i += storageSize _context << _type->storageSize() << Instruction::ADD; _context.appendJumpTo(loopStart); // cleanup _context << zeroLoopEnd; - _context << Instruction::POP; - + // stack: start_pos slot_count i + _context << Instruction::POP << Instruction::POP; + // stack: start_pos solAssert(_context.stackHeight() == stackHeightStart - 1, ""); } ); diff --git a/libsolidity/codegen/ArrayUtils.h b/libsolidity/codegen/ArrayUtils.h index 326084cb6..a62df8a7b 100644 --- a/libsolidity/codegen/ArrayUtils.h +++ b/libsolidity/codegen/ArrayUtils.h @@ -61,10 +61,6 @@ class ArrayUtils /// Stack pre: reference (excludes byte offset) /// Stack post: void clearDynamicArray(ArrayType const& _type) const; - /// Changes the size of a dynamic array and clears the tail if it is shortened. - /// Stack pre: reference (excludes byte offset) new_length - /// Stack post: - void resizeDynamicArray(ArrayType const& _type) const; /// Increments the size of a dynamic array by one. /// Does not touch the new data element. In case of a byte array, this might move the /// data. @@ -76,9 +72,9 @@ class ArrayUtils /// Stack pre: reference /// Stack post: void popStorageArrayElement(ArrayType const& _type) const; - /// Appends a loop that clears a sequence of storage slots of the given type (excluding end). - /// Stack pre: end_ref start_ref - /// Stack post: end_ref + /// Appends a loop that clears a sequence of storage slots of the given type. + /// Stack pre: start_ref slot_count + /// Stack post: start_ref void clearStorageLoop(Type const* _type) const; /// Converts length to size (number of storage slots or calldata/memory bytes). /// if @a _pad then add padding to multiples of 32 bytes for calldata/memory. From eb4149477d6663fc61b59eacf5b4df4125a6c710 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Wed, 17 Dec 2025 13:49:14 -0300 Subject: [PATCH 1048/1340] via-ir: Fix handling of storage array boundaries (deletion and cleanup) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniel Kirchner Co-authored-by: Kamil Śliwak --- libsolidity/codegen/YulUtilFunctions.cpp | 43 +++++++++++++++--------- libsolidity/codegen/YulUtilFunctions.h | 11 +++--- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index ffeaa790e..4c0a70269 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -1419,14 +1419,13 @@ std::string YulUtilFunctions::cleanUpStorageArrayEndFunction(ArrayType const& _t let newSlotCount := (startIndex) let arrayDataStart := (array) let deleteStart := add(arrayDataStart, newSlotCount) - let deleteEnd := add(arrayDataStart, oldSlotCount) // if we are dealing with packed array and offset is greater than zero // we have to partially clear last slot that is still used, so decreasing start by one let offset := mul(mod(startIndex, ), ) if gt(offset, 0) { (sub(deleteStart, 1), offset) } - (deleteStart, deleteEnd) + (deleteStart, sub(oldSlotCount, newSlotCount)) } )") ("convertToSize", arrayConvertLengthToSize(_type)) @@ -1474,11 +1473,17 @@ std::string YulUtilFunctions::cleanUpDynamicByteArrayEndSlotsFunction(ArrayType _args = {"array", "len", "startIndex"}; return Whiskers(R"( if gt(len, 31) { - let dataArea := (array) - let deleteStart := add(dataArea, (startIndex)) - // If we are clearing array to be short byte array, we want to clear only data starting from array data area. - if lt(startIndex, 32) { deleteStart := dataArea } - (deleteStart, add(dataArea, (len))) + if gt(len, startIndex) { + let dataArea := (array) + let oldSlotCount := (len) + let newSlotCount := (startIndex) + // If we are clearing array to be short byte array, we want to clear only data starting from array data area. + if lt(startIndex, 32) { + newSlotCount := 0 + } + let deleteStart := add(dataArea, newSlotCount) + (deleteStart, sub(oldSlotCount, newSlotCount)) + } } )") ("dataLocation", arrayDataAreaFunction(_type)) @@ -1496,14 +1501,21 @@ std::string YulUtilFunctions::decreaseByteArraySizeFunction(ArrayType const& _ty function (array, data, oldLen, newLen) { switch lt(newLen, 32) case 0 { + // NOTE: This branch (newLen >= 32) is currently unreachable from Solidity code. + // All delete operations use newLen=0, and assignment uses copyByteArrayToStorageFunction. + // However, we maintain correct logic here for future-proofing and consistency. + let newSlots := (newLen) + let oldSlots := (oldLen) let arrayDataStart := (array) - let deleteStart := add(arrayDataStart, (newLen)) + let deleteStart := add(arrayDataStart, newSlots) // we have to partially clear last slot that is still used let offset := and(newLen, 0x1f) if offset { (sub(deleteStart, 1), offset) } - (deleteStart, add(arrayDataStart, (oldLen))) + if gt(oldSlots, newSlots) { + (deleteStart, sub(oldSlots, newSlots)) + } sstore(array, or(mul(2, newLen), 1)) } @@ -1511,8 +1523,9 @@ std::string YulUtilFunctions::decreaseByteArraySizeFunction(ArrayType const& _ty switch gt(oldLen, 31) case 1 { let arrayDataStart := (array) - // clear whole old array, as we are transforming to short bytes array - (add(arrayDataStart, 1), add(arrayDataStart, (oldLen))) + // Clear whole old array, as we are transforming to short bytes array. + // () will clear the first slot after copying its content. + (add(arrayDataStart, 1), sub((oldLen), 1)) (array, newLen) } default { @@ -1826,10 +1839,10 @@ std::string YulUtilFunctions::clearStorageRangeFunction(Type const& _type) return m_functionCollector.createFunction(functionName, [&]() { return Whiskers(R"( - function (start, end) { - for {} lt(start, end) { start := add(start, ) } + function (startSlot, slotCount) { + for { let i := 0 } lt(i, slotCount) { i := add(i, ) } { - (start, 0) + (add(startSlot, i), 0) } } )") @@ -1861,7 +1874,7 @@ std::string YulUtilFunctions::clearStorageArrayFunction(ArrayType const& _type) (slot, 0) - (slot, add(slot, ())) + (slot, ()) } )") diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index c28ba855c..f4172017b 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -266,8 +266,11 @@ class YulUtilFunctions std::string storageArrayPushZeroFunction(ArrayType const& _type); /// @returns the name of a function that will clear the storage area given - /// by the start and end (exclusive) parameters (slots). - /// signature: (start, end) + /// by the start position and number of slots to clear. The start position is in terms of storage slots and we + /// assume that the beginning of the clear range starts at the beginning of the start slot. + /// `slot_count` is assumed to be a multiple of `_type.storageSize()`. The function clears storage in increments + /// of `_type.storageSize()` and does not perform any runtime checks. + /// signature: (start_slot, slot_count) std::string clearStorageRangeFunction(Type const& _type); /// @returns the name of a function that will clear the given storage array @@ -297,7 +300,7 @@ class YulUtilFunctions /// The function reverts for too large lengths. std::string arrayAllocationSizeFunction(ArrayType const& _type); - /// @returns the name of a function that converts a storage slot number + /// @returns the name of a function that converts a storage slot number, /// a memory pointer or a calldata pointer to the slot number / memory pointer / calldata pointer /// for the data position of an array which is stored in that slot / memory area / calldata area. std::string arrayDataAreaFunction(ArrayType const& _type); @@ -618,7 +621,7 @@ class YulUtilFunctions std::string cleanUpDynamicByteArrayEndSlotsFunction(ArrayType const& _type); /// @returns the name of a function that increases size of byte array - /// when we resize byte array frextractUsedSetLenom < 32 elements to >= 32 elements or we push to byte array of size 31 copying of data will occur + /// when we resize byte array from < 32 elements to >= 32 elements or we push to byte array of size 31 copying of data will occur /// signature: (array, data, oldLen, newLen) std::string increaseByteArraySizeFunction(ArrayType const& _type); From 4f0e20cf36e1107141f5b9aef13adddb1e05c03d Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Wed, 17 Dec 2025 13:48:21 -0300 Subject: [PATCH 1049/1340] Add test for arrays at storage boundaries and extend coverage of legacy and via-ir on deletion, partial assigments and copy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniel Kirchner Co-authored-by: Kamil Śliwak --- test/libsolidity/SolidityOptimizer.cpp | 4 +- .../abi_decode_simple_storage.sol | 4 +- .../abiEncoderV1/abi_decode_v2_storage.sol | 4 +- .../struct/struct_storage_ptr.sol | 6 +- .../calldata_overlapped_dynamic_arrays.sol | 6 +- .../abiEncoderV2/storage_array_encoding.sol | 10 +- .../arrays_complex_from_and_to_storage.sol | 6 +- .../array/bytes_length_member.sol | 4 +- .../array/constant_var_as_array_length.sol | 4 +- .../copying/array_copy_calldata_storage.sol | 6 +- .../copying/array_copy_cleanup_uint128.sol | 6 +- .../copying/array_copy_cleanup_uint40.sol | 6 +- .../copying/array_copy_clear_storage.sol | 6 +- .../array_copy_clear_storage_packed.sol | 12 +- .../copying/array_copy_different_packing.sol | 4 +- .../copying/array_copy_including_array.sol | 12 +- .../array/copying/array_copy_nested_array.sol | 6 +- ...ay_copy_storage_storage_different_base.sol | 4 +- ..._storage_storage_different_base_nested.sol | 6 +- .../array_copy_storage_storage_dyn_dyn.sol | 6 +- ...y_copy_storage_storage_dynamic_dynamic.sol | 4 +- ...ay_copy_storage_storage_static_dynamic.sol | 4 +- ...ray_copy_storage_storage_static_simple.sol | 4 +- ...ray_copy_storage_storage_static_static.sol | 6 +- .../array_copy_storage_storage_struct.sol | 6 +- .../copying/array_copy_target_leftover.sol | 6 +- .../copying/array_copy_target_leftover2.sol | 6 +- .../copying/array_copy_target_simple.sol | 6 +- .../copying/array_copy_target_simple_2.sol | 6 +- .../copying/array_elements_to_mapping.sol | 6 +- .../array_nested_calldata_to_storage.sol | 4 +- .../array_nested_memory_to_storage.sol | 14 +- ...on_external_storage_to_storage_dynamic.sol | 6 +- ...o_storage_dynamic_different_mutability.sol | 6 +- .../array_of_struct_calldata_to_storage.sol | 2 +- ..._containing_arrays_calldata_to_storage.sol | 2 +- .../array/copying/array_to_mapping.sol | 6 +- .../copying/arrays_from_and_to_storage.sol | 4 +- .../array/copying/bytes_inside_mappings.sol | 7 +- .../copying/bytes_storage_to_storage.sol | 23 +-- .../calldata_array_dynamic_to_storage.sol | 6 +- ...nup_during_multi_element_per_slot_copy.sol | 12 +- .../copy_byte_array_in_struct_to_storage.sol | 9 +- .../copying/copy_byte_array_to_storage.sol | 6 +- .../copy_function_internal_storage_array.sol | 6 +- ...opy_internal_function_array_to_storage.sol | 4 +- .../array/copying/copy_removes_bytes_data.sol | 3 +- .../copying/copying_bytes_multiassign.sol | 6 +- ...d_array_of_structs_calldata_to_storage.sol | 6 +- ...ted_array_of_structs_memory_to_storage.sol | 6 +- .../function_type_array_to_storage.sol | 12 +- .../memory_dyn_2d_bytes_to_storage.sol | 6 +- ...sted_array_element_calldata_to_storage.sol | 2 +- ...nested_array_element_memory_to_storage.sol | 2 +- ...ested_array_element_storage_to_storage.sol | 12 +- ...d_array_of_structs_calldata_to_storage.sol | 6 +- ...ted_array_of_structs_memory_to_storage.sol | 6 +- ...amic_array_element_calldata_to_storage.sol | 4 +- .../copying/storage_memory_nested_bytes.sol | 2 +- .../array/delete/bytes_delete_element.sol | 4 +- .../array/delete/delete_bytes_array.sol | 1 + .../delete/delete_storage_array_packed.sol | 6 +- .../array/fixed_array_cleanup.sol | 6 +- ...nvalid_encoding_for_storage_byte_array.sol | 6 +- .../long_byte_array_cleanup_after_delete.sol | 77 ++++++++ ...rray_cleanup_after_overwrite_with_long.sol | 105 +++++++++++ .../array/nested_calldata_storage2.sol | 2 +- .../array/pop/array_pop_array_transition.sol | 6 +- .../push/array_push_nested_from_calldata.sol | 4 +- .../array/push/array_push_struct.sol | 4 +- .../array/push/nested_bytes_push.sol | 2 +- .../copy_from_calldata_removes_bytes_data.sol | 3 +- .../cleanup/byte_array_to_storage_cleanup.sol | 13 +- .../constructor/arrays_in_constructors.sol | 4 +- .../bytes_in_constructors_packer.sol | 6 +- .../bytes_in_constructors_unpacker.sol | 6 +- .../constructor_static_array_argument.sol | 4 +- .../event_dynamic_nested_array_storage_v2.sol | 2 +- .../fallback/call_forward_bytes.sol | 1 + .../storage/empty_nonempty_empty.sol | 5 +- .../storage/static_array_copy_cleanup.sol | 94 ++++++++++ ...ray_and_partial_assignment_with_layout.sol | 54 ++++++ .../storage_boundary_array_assignment.sol | 28 +++ .../storage/storage_boundary_array_copy.sol | 61 +++++++ .../storage/storage_boundary_array_delete.sol | 34 ++++ ...dary_array_delete_overlapping_variable.sol | 40 ++++ ...array_packing_not_overlapping_variable.sol | 63 +++++++ ...rage_boundary_array_partial_assignment.sol | 41 +++++ .../storage_boundary_delete_overflow_bug.sol | 80 ++++++++ .../storage/storage_boundary_packed_array.sol | 35 ++++ ...rage_boundary_struct_array_mixed_types.sol | 172 ++++++++++++++++++ ...torage_boundary_struct_array_multislot.sol | 128 +++++++++++++ .../storage_boundary_struct_array_packed.sol | 128 +++++++++++++ .../storage/storage_packed_array_copy.sol | 35 ++++ .../state_variable_dynamic_array.sol | 6 +- .../state_variable_mapping.sol | 2 +- .../structs/copy_from_mapping.sol | 4 +- .../copy_struct_array_from_storage.sol | 4 +- .../copy_substructures_from_mapping.sol | 4 +- .../structs/copy_substructures_to_mapping.sol | 12 +- .../semanticTests/structs/copy_to_mapping.sol | 12 +- ...truct_containing_bytes_copy_and_delete.sol | 4 +- .../struct_delete_storage_nested_small.sol | 2 +- .../struct_delete_storage_with_array.sol | 12 +- ...truct_delete_storage_with_arrays_small.sol | 2 +- .../mapping/copy_from_mapping_to_mapping.sol | 4 +- .../userDefinedValueType/calldata.sol | 12 +- .../calldata_to_storage.sol | 10 +- .../memory_to_storage.sol | 8 +- .../semanticTests/various/address_code.sol | 6 +- .../semanticTests/various/create_calldata.sol | 6 +- .../various/destructuring_assignment.sol | 6 +- .../skip_dynamic_types_for_structs.sol | 4 +- ...alldata_struct_array_to_storage_legacy.sol | 16 ++ ..._memory_struct_array_to_storage_legacy.sol | 17 ++ 115 files changed, 1502 insertions(+), 277 deletions(-) create mode 100644 test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_delete.sol create mode 100644 test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol create mode 100644 test/libsolidity/semanticTests/storage/static_array_copy_cleanup.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_array_and_partial_assignment_with_layout.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_array_assignment.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_array_copy.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_array_delete.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_array_delete_overlapping_variable.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_array_packing_not_overlapping_variable.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_array_partial_assignment.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_delete_overflow_bug.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_packed_array.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_boundary_struct_array_packed.sol create mode 100644 test/libsolidity/semanticTests/storage/storage_packed_array_copy.sol create mode 100644 test/libsolidity/syntaxTests/array/copy_calldata_struct_array_to_storage_legacy.sol create mode 100644 test/libsolidity/syntaxTests/array/copy_memory_struct_array_to_storage_legacy.sol diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 832299baf..b3116a372 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -634,8 +634,8 @@ BOOST_AUTO_TEST_CASE(optimise_multi_stores) )"; compileBothVersions(sourceCode); compareVersions("f()"); - BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 8); - BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 7); + BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 9); + BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 6); } BOOST_AUTO_TEST_CASE(optimise_constant_to_codecopy) diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple_storage.sol b/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple_storage.sol index 54ce693d5..6c4fd52b3 100644 --- a/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple_storage.sol +++ b/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple_storage.sol @@ -8,6 +8,6 @@ contract C { } // ---- // f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg" -// gas irOptimized: 135499 +// gas irOptimized: 135441 // gas legacy: 137095 -// gas legacyOptimized: 135823 +// gas legacyOptimized: 135828 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol index 5c3bcba97..e5aa910ce 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol @@ -21,6 +21,6 @@ contract C { } // ---- // f() -> 0x20, 0x8, 0x40, 0x3, 0x9, 0xa, 0xb -// gas irOptimized: 203167 +// gas irOptimized: 203109 // gas legacy: 206263 -// gas legacyOptimized: 203172 +// gas legacyOptimized: 203177 diff --git a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol index ed983c77b..ff98c66ca 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol @@ -24,6 +24,6 @@ contract C { // ---- // library: L // f() -> 8, 7, 1, 2, 7, 12 -// gas irOptimized: 166761 -// gas legacy: 169273 -// gas legacyOptimized: 167243 +// gas irOptimized: 166766 +// gas legacy: 170486 +// gas legacyOptimized: 167252 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol index aa1e494c2..302aeb5de 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol @@ -33,8 +33,8 @@ contract C { // f_which(uint256[],uint256[2],uint256): 0x40, 1, 2, 1, 5, 6 -> 0x20, 0x40, 5, 2 // f_which(uint256[],uint256[2],uint256): 0x40, 1, 2, 1 -> FAILURE // f_storage(uint256[],uint256[2]): 0x20, 1, 2 -> 0x20, 0x60, 0x20, 1, 2 -// gas irOptimized: 111409 -// gas legacy: 112707 -// gas legacyOptimized: 111845 +// gas irOptimized: 111356 +// gas legacy: 113826 +// gas legacyOptimized: 111724 // f_storage(uint256[],uint256[2]): 0x40, 1, 2, 5, 6 -> 0x20, 0x80, 0x20, 2, 5, 6 // f_storage(uint256[],uint256[2]): 0x40, 1, 2, 5 -> FAILURE diff --git a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol index 9599af6c8..31f759d3b 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol @@ -18,10 +18,10 @@ contract C { // EVMVersion: >homestead // ---- // h(uint256[2][]): 0x20, 3, 123, 124, 223, 224, 323, 324 -> 32, 256, 0x20, 3, 123, 124, 223, 224, 323, 324 -// gas irOptimized: 180080 -// gas legacy: 184233 -// gas legacyOptimized: 180856 +// gas irOptimized: 180022 +// gas legacy: 186541 +// gas legacyOptimized: 180429 // i(uint256[2][2]): 123, 124, 223, 224 -> 32, 128, 123, 124, 223, 224 // gas irOptimized: 112031 -// gas legacy: 115091 -// gas legacyOptimized: 112657 +// gas legacy: 116683 +// gas legacyOptimized: 112303 diff --git a/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol b/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol index a9d08ec0c..ac3cd8495 100644 --- a/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol +++ b/test/libsolidity/semanticTests/array/arrays_complex_from_and_to_storage.sol @@ -12,9 +12,9 @@ contract Test { } // ---- // set(uint24[3][]): 0x20, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12 -> 0x06 -// gas irOptimized: 185216 -// gas legacy: 211054 -// gas legacyOptimized: 206077 +// gas irOptimized: 185221 +// gas legacy: 199970 +// gas legacyOptimized: 186342 // data(uint256,uint256): 0x02, 0x02 -> 0x09 // data(uint256,uint256): 0x05, 0x01 -> 0x11 // data(uint256,uint256): 0x06, 0x00 -> FAILURE diff --git a/test/libsolidity/semanticTests/array/bytes_length_member.sol b/test/libsolidity/semanticTests/array/bytes_length_member.sol index 5159538bc..85b9282c6 100644 --- a/test/libsolidity/semanticTests/array/bytes_length_member.sol +++ b/test/libsolidity/semanticTests/array/bytes_length_member.sol @@ -13,7 +13,7 @@ contract c { // ---- // getLength() -> 0 // set(): 1, 2 -> true -// gas irOptimized: 110422 +// gas irOptimized: 110393 // gas legacy: 110951 -// gas legacyOptimized: 110576 +// gas legacyOptimized: 110577 // getLength() -> 68 diff --git a/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol b/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol index 342f3218f..833c9dec3 100644 --- a/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol +++ b/test/libsolidity/semanticTests/array/constant_var_as_array_length.sol @@ -10,9 +10,9 @@ contract C { // constructor(): 1, 2, 3 -> // gas irOptimized: 124991 // gas irOptimized code: 14800 -// gas legacy: 134317 +// gas legacy: 142553 // gas legacy code: 46200 -// gas legacyOptimized: 127166 +// gas legacyOptimized: 126306 // gas legacyOptimized code: 23400 // a(uint256): 0 -> 1 // a(uint256): 1 -> 2 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol index ecfe565f1..8131e7434 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol @@ -20,7 +20,7 @@ contract c { } // ---- // store(uint256[9],uint8[3][]): 21, 22, 23, 24, 25, 26, 27, 28, 29, 0x140, 4, 1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33 -> 32 -// gas irOptimized: 647725 -// gas legacy: 694354 -// gas legacyOptimized: 693849 +// gas irOptimized: 647730 +// gas legacy: 659420 +// gas legacyOptimized: 648899 // retrieve() -> 9, 28, 9, 28, 4, 3, 32 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol index e1cfa7ce7..ba05d8fb6 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint128.sol @@ -21,6 +21,6 @@ contract C { } // ---- // f() -> true -// gas irOptimized: 73992 -// gas legacy: 74395 -// gas legacyOptimized: 73794 +// gas irOptimized: 73981 +// gas legacy: 75550 +// gas legacyOptimized: 73812 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol index d65f4f37c..e4e7bf62f 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_cleanup_uint40.sol @@ -46,6 +46,6 @@ contract C { } // ---- // f() -> true -// gas irOptimized: 122541 -// gas legacy: 124643 -// gas legacyOptimized: 122801 +// gas irOptimized: 122596 +// gas legacy: 125651 +// gas legacyOptimized: 121668 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol index e9f1448a2..f206b432c 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage.sol @@ -13,6 +13,6 @@ contract C { } // ---- // f() -> 0 -// gas irOptimized: 108229 -// gas legacy: 108216 -// gas legacyOptimized: 107625 +// gas irOptimized: 108096 +// gas legacy: 110351 +// gas legacyOptimized: 107708 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol index 43827773c..12d9bf1fd 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_clear_storage_packed.sol @@ -40,11 +40,11 @@ contract C { } // ---- // f() -> 0 -// gas irOptimized: 74056 -// gas legacy: 74372 -// gas legacyOptimized: 73796 +// gas irOptimized: 74044 +// gas legacy: 75528 +// gas legacyOptimized: 73861 // g() -> 0 // h() -> 0 -// gas irOptimized: 74126 -// gas legacy: 74398 -// gas legacyOptimized: 73833 +// gas irOptimized: 74114 +// gas legacy: 75553 +// gas legacyOptimized: 73904 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol b/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol index ee564d01a..1bbb54191 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_different_packing.sol @@ -19,5 +19,5 @@ contract c { // ---- // test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x05000000000000000000000000000000000000000000000000 // gas irOptimized: 208415 -// gas legacy: 220711 -// gas legacyOptimized: 220097 +// gas legacy: 220059 +// gas legacyOptimized: 211458 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol index bb621fcc8..ba50c7300 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol @@ -35,12 +35,12 @@ contract c { } // ---- // test() -> 0x02000202 -// gas irOptimized: 4549676 -// gas legacy: 4475394 -// gas legacyOptimized: 4447665 +// gas irOptimized: 4560468 +// gas legacy: 4536566 +// gas legacyOptimized: 4456759 // storageEmpty -> 1 // clear() -> 0, 0 -// gas irOptimized: 4478184 -// gas legacy: 4407185 -// gas legacyOptimized: 4381337 +// gas irOptimized: 4488719 +// gas legacy: 4407780 +// gas legacyOptimized: 4385089 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol b/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol index 2d325a804..34d6c75ef 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_nested_array.sol @@ -12,6 +12,6 @@ contract c { } // ---- // test(uint256[2][]): 32, 3, 7, 8, 9, 10, 11, 12 -> 10 -// gas irOptimized: 689552 -// gas legacy: 686176 -// gas legacyOptimized: 685611 +// gas irOptimized: 689539 +// gas legacy: 713478 +// gas legacyOptimized: 690424 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol index 54639df55..af31d4b8e 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol @@ -18,5 +18,5 @@ contract c { // ---- // test() -> 5, 4 // gas irOptimized: 205667 -// gas legacy: 213863 -// gas legacyOptimized: 212901 +// gas legacy: 207971 +// gas legacyOptimized: 204828 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol index ad745ff42..6b1dd7ff0 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base_nested.sol @@ -21,6 +21,6 @@ contract c { } // ---- // test() -> 3, 4 -// gas irOptimized: 169669 -// gas legacy: 175415 -// gas legacyOptimized: 172533 +// gas irOptimized: 169553 +// gas legacy: 182361 +// gas legacyOptimized: 169554 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol index a38685404..98e2f5adb 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dyn_dyn.sol @@ -15,9 +15,9 @@ contract c { // ---- // setData1(uint256,uint256,uint256): 10, 5, 4 -> // copyStorageStorage() -> -// gas irOptimized: 111350 -// gas legacy: 109272 -// gas legacyOptimized: 109262 +// gas irOptimized: 111321 +// gas legacy: 112434 +// gas legacyOptimized: 111494 // getData2(uint256): 5 -> 10, 4 // setData1(uint256,uint256,uint256): 0, 0, 0 -> // copyStorageStorage() -> diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol index 83df3aef8..5a66704b5 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol @@ -18,5 +18,5 @@ contract c { // ---- // test() -> 5, 4 // gas irOptimized: 253591 -// gas legacy: 250892 -// gas legacyOptimized: 250045 +// gas legacy: 253664 +// gas legacyOptimized: 252200 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol index 94e57c96d..29d8bc0eb 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_dynamic.sol @@ -12,5 +12,5 @@ contract c { // ---- // test() -> 9, 4 // gas irOptimized: 123180 -// gas legacy: 123566 -// gas legacyOptimized: 123202 +// gas legacy: 124642 +// gas legacyOptimized: 123345 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_simple.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_simple.sol index 84642c143..29e62dd3c 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_simple.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_simple.sol @@ -11,5 +11,5 @@ contract C { } // ---- // test() -> left(0x01), left(0x02) -// gas legacy: 89698 -// gas legacyOptimized: 88928 +// gas legacy: 69235 +// gas legacyOptimized: 66974 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol index d1f2cbded..65ce65654 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol @@ -14,6 +14,6 @@ contract c { } // ---- // test() -> 8, 0 -// gas irOptimized: 196251 -// gas legacy: 194842 -// gas legacyOptimized: 194281 +// gas irOptimized: 196370 +// gas legacy: 210073 +// gas legacyOptimized: 196759 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol index e638f2dad..f1cd76a3a 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_struct.sol @@ -17,7 +17,7 @@ contract c { } // ---- // test() -> 4, 5 -// gas irOptimized: 190628 -// gas legacy: 190828 -// gas legacyOptimized: 189657 +// gas irOptimized: 190676 +// gas legacy: 210706 +// gas legacyOptimized: 190472 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol b/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol index 22105f642..2deb372fa 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover.sol @@ -17,6 +17,6 @@ contract c { } // ---- // test() -> 0xffffffff, 0x0000000000000000000000000a00090008000700060005000400030002000100, 0x0000000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 100496 -// gas legacy: 158109 -// gas legacyOptimized: 141019 +// gas irOptimized: 100506 +// gas legacy: 146700 +// gas legacyOptimized: 122680 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover2.sol b/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover2.sol index dd49c7a97..706130082 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover2.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_target_leftover2.sol @@ -19,6 +19,6 @@ contract c { } // ---- // test() -> 0x04000000000000000000000000000000000000000000000000, 0x0, 0x0 -// gas irOptimized: 91348 -// gas legacy: 96648 -// gas legacyOptimized: 93841 +// gas irOptimized: 91320 +// gas legacy: 97777 +// gas legacyOptimized: 91993 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol index 27fb9f0c5..054d61c67 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple.sol @@ -18,6 +18,6 @@ contract c { } // ---- // test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x0 -// gas irOptimized: 273543 -// gas legacy: 282601 -// gas legacyOptimized: 281510 +// gas irOptimized: 273548 +// gas legacy: 280148 +// gas legacyOptimized: 274502 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol index 980e414d1..7ceadf481 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_target_simple_2.sol @@ -18,6 +18,6 @@ contract c { } // ---- // test() -> 0x01000000000000000000000000000000000000000000000000, 0x02000000000000000000000000000000000000000000000000, 0x03000000000000000000000000000000000000000000000000, 0x04000000000000000000000000000000000000000000000000, 0x00 -// gas irOptimized: 232995 -// gas legacy: 235694 -// gas legacyOptimized: 235193 +// gas irOptimized: 233012 +// gas legacy: 239400 +// gas legacyOptimized: 233948 diff --git a/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol b/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol index becc3d4cd..a1849bd65 100644 --- a/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol +++ b/test/libsolidity/semanticTests/array/copying/array_elements_to_mapping.sol @@ -52,9 +52,9 @@ contract C { } // ---- // from_storage() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -// gas irOptimized: 149868 -// gas legacy: 150737 -// gas legacyOptimized: 148690 +// gas irOptimized: 149856 +// gas legacy: 156721 +// gas legacyOptimized: 149000 // from_storage_ptr() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 // from_memory() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 // from_calldata(uint8[][]): 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol index 5d4e5b45e..ffa0c68ad 100644 --- a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol @@ -38,10 +38,10 @@ contract c { // compileViaYul: true // ---- // test1(uint256[][]): 0x20, 2, 0x40, 0x40, 2, 23, 42 -> 2, 65 -// gas irOptimized: 181029 +// gas irOptimized: 180918 // test2(uint256[][2]): 0x20, 0x40, 0x40, 2, 23, 42 -> 2, 65 // gas irOptimized: 157604 // test3(uint256[2][]): 0x20, 2, 23, 42, 23, 42 -> 2, 65 -// gas irOptimized: 134801 +// gas irOptimized: 134685 // test4(uint256[2][2]): 23, 42, 23, 42 -> 65 // gas irOptimized: 111177 diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol index b892ec991..933a1ab1b 100644 --- a/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol @@ -38,12 +38,14 @@ contract Test { } // ---- // test() -> 24 -// gas irOptimized: 226734 -// gas legacy: 227083 -// gas legacyOptimized: 226529 +// gas irOptimized: 226647 +// gas legacy: 229060 +// gas legacyOptimized: 226495 // test1() -> 3 // test2() -> 6 +// gas irOptimized: 95905 +// gas legacy: 100519 // test3() -> 24 -// gas irOptimized: 141319 -// gas legacy: 142238 -// gas legacyOptimized: 141365 +// gas irOptimized: 141297 +// gas legacy: 146668 +// gas legacyOptimized: 141331 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol index ab3c172d3..e3b9cdaad 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol @@ -45,7 +45,7 @@ contract C { } // ---- // copyExternalStorageArrayOfFunctionType() -> true -// gas irOptimized: 104566 -// gas legacy: 108554 -// gas legacyOptimized: 102405 +// gas irOptimized: 104629 +// gas legacy: 111170 +// gas legacyOptimized: 104620 // copyInternalArrayOfFunctionType() -> true diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol index d121b22d4..92b61b929 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic_different_mutability.sol @@ -49,7 +49,7 @@ contract C { // ---- // copyExternalStorageArraysOfFunctionType() -> true // gas irOptimized: 104238 -// gas legacy: 108295 -// gas legacyOptimized: 102162 +// gas legacy: 110911 +// gas legacyOptimized: 104377 // copyInternalArrayOfFunctionType() -> true -// gas legacy: 36192 +// gas legacy: 38695 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol index 3147401cf..e4b3d14fd 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_struct_calldata_to_storage.sol @@ -17,4 +17,4 @@ contract C { // compileViaYul: true // ---- // f((uint128,uint64,uint128)[]): 0x20, 3, 0, 0, 12, 0, 11, 0, 10, 0, 0 -> 10, 11, 12 -// gas irOptimized: 120747 +// gas irOptimized: 120751 diff --git a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol index 09037719a..acc968389 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_structs_containing_arrays_calldata_to_storage.sol @@ -23,4 +23,4 @@ contract C { // compileViaYul: true // ---- // f((uint256[])[]): 0x20, 3, 0x60, 0x60, 0x60, 0x20, 3, 1, 2, 3 -> 3, 1 -// gas irOptimized: 327456 +// gas irOptimized: 327461 diff --git a/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol b/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol index c5519e83a..667685c9c 100644 --- a/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol +++ b/test/libsolidity/semanticTests/array/copying/array_to_mapping.sol @@ -37,8 +37,8 @@ contract C { } // ---- // from_storage() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -// gas irOptimized: 147755 -// gas legacy: 148892 -// gas legacyOptimized: 146917 +// gas irOptimized: 147749 +// gas legacy: 154218 +// gas legacyOptimized: 147020 // from_storage_ptr() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 // from_memory() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 diff --git a/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol b/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol index 93b541620..fea2c895d 100644 --- a/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol @@ -11,8 +11,8 @@ contract Test { // ---- // set(uint24[]): 0x20, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 -> 18 // gas irOptimized: 95505 -// gas legacy: 103509 -// gas legacyOptimized: 101266 +// gas legacy: 104176 +// gas legacyOptimized: 96785 // data(uint256): 7 -> 8 // data(uint256): 15 -> 16 // data(uint256): 18 -> FAILURE diff --git a/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol b/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol index 90012eed4..4ab381f4e 100644 --- a/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol +++ b/test/libsolidity/semanticTests/array/copying/bytes_inside_mappings.sol @@ -5,17 +5,20 @@ contract c { } // ---- // set(uint256): 1, 2 -> true -// gas irOptimized: 110550 +// gas irOptimized: 110560 // gas legacy: 111310 // gas legacyOptimized: 110741 // set(uint256): 2, 2, 3, 4, 5 -> true -// gas irOptimized: 177501 +// gas irOptimized: 177511 // gas legacy: 178312 // gas legacyOptimized: 177716 // storageEmpty -> 0 // copy(uint256,uint256): 1, 2 -> true +// gas irOptimized: 48421 // storageEmpty -> 0 // copy(uint256,uint256): 99, 1 -> true +// gas irOptimized: 35641 // storageEmpty -> 0 // copy(uint256,uint256): 99, 2 -> true +// gas irOptimized: 35641 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol index d00f5573a..37769cb49 100644 --- a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol @@ -19,23 +19,24 @@ contract c { // f(uint256): 31 -> 0x20, 0x1f, 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e00 // gas irOptimized: 103268 // gas legacy: 112904 -// gas legacyOptimized: 112647 +// gas legacyOptimized: 112645 // f(uint256): 32 -> 0x20, 0x20, 1780731860627700044960722568376592200742329637303199754547598369979440671 // gas irOptimized: 117825 // gas legacy: 128964 -// gas legacyOptimized: 128854 +// gas legacyOptimized: 128859 // f(uint256): 33 -> 0x20, 33, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x2000000000000000000000000000000000000000000000000000000000000000 -// gas irOptimized: 124091 -// gas legacy: 136092 -// gas legacyOptimized: 135469 +// gas irOptimized: 123888 +// gas legacy: 135510 +// gas legacyOptimized: 135218 // f(uint256): 63 -> 0x20, 0x3f, 1780731860627700044960722568376592200742329637303199754547598369979440671, 14532552714582660066924456880521368950258152170031413196862950297402215316992 -// gas irOptimized: 127151 -// gas legacy: 148692 -// gas legacyOptimized: 148699 +// gas irOptimized: 126948 +// gas legacy: 148110 +// gas legacyOptimized: 148448 // f(uint256): 12 -> 0x20, 0x0c, 0x0102030405060708090a0b0000000000000000000000000000000000000000 -// gas legacy: 59751 -// gas legacyOptimized: 57208 +// gas irOptimized: 54204 +// gas legacy: 59832 +// gas legacyOptimized: 57268 // f(uint256): 129 -> 0x20, 0x81, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f, 29063324697304692433803953038474361308315562010425523193971352996434451193439, 0x606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f, -57896044618658097711785492504343953926634992332820282019728792003956564819968 // gas irOptimized: 416918 // gas legacy: 458997 -// gas legacyOptimized: 460664 +// gas legacyOptimized: 460669 diff --git a/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol b/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol index 3df22c725..400834772 100644 --- a/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/calldata_array_dynamic_to_storage.sol @@ -9,6 +9,6 @@ contract C { } // ---- // f(uint256[]): 0x20, 0x03, 0x1, 0x2, 0x3 -> 0x1 -// gas irOptimized: 111084 -// gas legacy: 111548 -// gas legacyOptimized: 111321 +// gas irOptimized: 110973 +// gas legacy: 112436 +// gas legacyOptimized: 111313 diff --git a/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol b/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol index e6284072d..cdc3c4f66 100644 --- a/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol +++ b/test/libsolidity/semanticTests/array/copying/cleanup_during_multi_element_per_slot_copy.sol @@ -16,10 +16,10 @@ contract C { } // ---- // constructor() -// gas irOptimized: 90065 -// gas irOptimized code: 149000 -// gas legacy: 89553 -// gas legacy code: 126200 -// gas legacyOptimized: 83556 -// gas legacyOptimized code: 98200 +// gas irOptimized: 89349 +// gas irOptimized code: 140200 +// gas legacy: 100902 +// gas legacy code: 271400 +// gas legacyOptimized: 83062 +// gas legacyOptimized code: 91800 // f() -> 0 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol index 787973c5f..9a68f88d8 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_in_struct_to_storage.sol @@ -37,10 +37,11 @@ contract C { // f() -> 0x40, 0x80, 6, 0x6162636465660000000000000000000000000000000000000000000000000000, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000 // gas irOptimized: 179405 // gas legacy: 180675 -// gas legacyOptimized: 179686 +// gas legacyOptimized: 179690 // g() -> 0x40, 0xc0, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000, 0x11, 0x3132333435363738393233343536373839000000000000000000000000000000 -// gas irOptimized: 106338 -// gas legacy: 109415 -// gas legacyOptimized: 106600 +// gas irOptimized: 106381 +// gas legacy: 109472 +// gas legacyOptimized: 106648 // h() -> 0x40, 0x60, 0x00, 0x00 +// gas irOptimized: 46948 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol index fc274bf47..caa059661 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_byte_array_to_storage.sol @@ -46,6 +46,6 @@ contract C { } // ---- // f() -> 0xff -// gas irOptimized: 143857 -// gas legacy: 153404 -// gas legacyOptimized: 146676 +// gas irOptimized: 143935 +// gas legacy: 153487 +// gas legacyOptimized: 146748 diff --git a/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol b/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol index 7db82f891..5fc981340 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_function_internal_storage_array.sol @@ -15,6 +15,6 @@ contract C { } // ---- // test() -> 7 -// gas irOptimized: 122459 -// gas legacy: 205176 -// gas legacyOptimized: 204971 +// gas irOptimized: 122575 +// gas legacy: 208558 +// gas legacyOptimized: 202409 diff --git a/test/libsolidity/semanticTests/array/copying/copy_internal_function_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/copy_internal_function_array_to_storage.sol index 95ba9d8ed..6c1d061d3 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_internal_function_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_internal_function_array_to_storage.sol @@ -18,6 +18,6 @@ contract C { } // ---- // one() -> 3 -// gas legacy: 140253 -// gas legacyOptimized: 140093 +// gas legacy: 142687 +// gas legacyOptimized: 135991 // two() -> FAILURE, hex"4e487b71", 0x51 diff --git a/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol b/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol index 46216e912..6872995d1 100644 --- a/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol +++ b/test/libsolidity/semanticTests/array/copying/copy_removes_bytes_data.sol @@ -9,7 +9,8 @@ contract c { // set(): 1, 2, 3, 4, 5 -> true // gas irOptimized: 177344 // gas legacy: 177953 -// gas legacyOptimized: 177550 +// gas legacyOptimized: 177551 // storageEmpty -> 0 // reset() -> true +// gas irOptimized: 47341 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol b/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol index ce4344e87..d29feccf4 100644 --- a/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol +++ b/test/libsolidity/semanticTests/array/copying/copying_bytes_multiassign.sol @@ -18,13 +18,15 @@ contract sender { } // ---- // (): 7 -> -// gas irOptimized: 110822 +// gas irOptimized: 110735 // gas legacy: 111388 -// gas legacyOptimized: 111065 +// gas legacyOptimized: 111066 // val() -> 0 // forward(bool): true -> true +// gas irOptimized: 49573 // val() -> 0x80 // forward(bool): false -> true +// gas irOptimized: 31410 // val() -> 0x80 // forward(bool): true -> true // val() -> 0x80 diff --git a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol index 672e7435f..5c64ba63f 100644 --- a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_calldata_to_storage.sol @@ -31,8 +31,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][][]): 0x20, 1, 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 327921 +// gas irOptimized: 327936 // test2((uint8[],uint8[2])[][1][]): 0x20, 2, 0x40, 0x0160, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13, 0x20, 1, 0x20, 0x60, 31, 37, 2, 23, 29 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 141162 +// gas irOptimized: 141168 // test3((uint8[],uint8[2])[1][][2]): 0x20, 0x40, 0x60, 0, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 188442 +// gas irOptimized: 188448 diff --git a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol index f232d8aba..12c40849f 100644 --- a/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/elements_of_nested_array_of_structs_memory_to_storage.sol @@ -31,8 +31,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][][]): 0x20, 1, 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 332567 +// gas irOptimized: 332582 // test2((uint8[],uint8[2])[][1][]): 0x20, 2, 0x40, 0x0160, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13, 0x20, 1, 0x20, 0x60, 31, 37, 2, 23, 29 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 145409 +// gas irOptimized: 145415 // test3((uint8[],uint8[2])[1][][2]): 0x20, 0x40, 0x60, 0, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 192248 +// gas irOptimized: 192254 diff --git a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol index 640046a11..a5cf48011 100644 --- a/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/function_type_array_to_storage.sol @@ -46,11 +46,11 @@ contract C { } // ---- // test() -> 0x20, 0x14, "[a called][b called]" -// gas irOptimized: 116518 -// gas legacy: 118841 -// gas legacyOptimized: 116843 +// gas irOptimized: 116512 +// gas legacy: 120226 +// gas legacyOptimized: 116941 // test2() -> 0x20, 0x14, "[b called][a called]" // test3() -> 0x20, 0x14, "[b called][a called]" -// gas irOptimized: 103144 -// gas legacy: 102654 -// gas legacyOptimized: 101556 +// gas irOptimized: 103138 +// gas legacy: 105192 +// gas legacyOptimized: 103752 diff --git a/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol b/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol index 8a4d870b2..93eb84427 100644 --- a/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/memory_dyn_2d_bytes_to_storage.sol @@ -18,6 +18,6 @@ contract C { } // ---- // f() -> 3 -// gas irOptimized: 128296 -// gas legacy: 129077 -// gas legacyOptimized: 128210 +// gas irOptimized: 128301 +// gas legacy: 129528 +// gas legacyOptimized: 128171 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_element_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_element_calldata_to_storage.sol index 89eeb27dc..f9d14b59e 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_element_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_element_calldata_to_storage.sol @@ -26,4 +26,4 @@ contract C { // test(uint8[2][2][2]): 1, 2, 3, 4, 5, 6, 7, 8 // test2(uint8[2][2]): 1, 2, 3, 4 // gas irOptimized: 72076 -// gas legacyOptimized: 95103 +// gas legacyOptimized: 72086 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_element_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_element_memory_to_storage.sol index bd74ae015..d604a11e6 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_element_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_element_memory_to_storage.sol @@ -26,4 +26,4 @@ contract C { // test(uint8[2][2][2]): 1, 2, 3, 4, 5, 6, 7, 8 // test2(uint8[2][2]): 1, 2, 3, 4 // gas irOptimized: 73031 -// gas legacyOptimized: 96288 +// gas legacyOptimized: 73155 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol index f3934fec0..1a3fb70e0 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol @@ -71,14 +71,14 @@ contract C { // ---- // test1() -> // gas irOptimized: 150488 -// gas legacy: 150949 -// gas legacyOptimized: 150906 +// gas legacy: 156275 +// gas legacyOptimized: 151018 // test2() -> FAILURE // gas irOptimized: 150389 -// gas legacy: 150672 -// gas legacyOptimized: 150575 +// gas legacy: 155998 +// gas legacyOptimized: 150684 // test3() -> // gas irOptimized: 124300 -// gas legacy: 125333 -// gas legacyOptimized: 125127 +// gas legacy: 130649 +// gas legacyOptimized: 125142 // test4() -> FAILURE diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol index 7621b2477..b27fe9e06 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_calldata_to_storage.sol @@ -29,8 +29,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 304788 +// gas irOptimized: 304750 // test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 116653 +// gas irOptimized: 116659 // test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 187994 +// gas irOptimized: 187942 diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol index 8ec3f7769..146de2f2a 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_of_structs_memory_to_storage.sol @@ -29,8 +29,8 @@ contract C { // compileViaYul: true // ---- // test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -// gas irOptimized: 309072 +// gas irOptimized: 309034 // test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 118314 +// gas irOptimized: 118320 // test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -// gas irOptimized: 191045 +// gas irOptimized: 190993 diff --git a/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol index 57b3dc521..7583f5ab4 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_dynamic_array_element_calldata_to_storage.sol @@ -30,7 +30,7 @@ contract C { // compileViaYul: true // ---- // test(uint8[][][]): 0x20, 2, 0x40, 0x60, 0, 2, 0x40, 0x80, 1, 7, 2, 8, 9 -// gas irOptimized: 137897 +// gas irOptimized: 137891 // test2(uint8[][]): 0x20, 2, 0x40, 0x80, 1, 7, 2, 8, 9 -// gas irOptimized: 164482 +// gas irOptimized: 164249 // gas legacyOptimized: 120228 diff --git a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol index e5a6ae53b..3f52085f4 100644 --- a/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol +++ b/test/libsolidity/semanticTests/array/copying/storage_memory_nested_bytes.sol @@ -13,4 +13,4 @@ contract C { // f() -> 0x20, 0x02, 0x40, 0x80, 3, 0x6162630000000000000000000000000000000000000000000000000000000000, 0x99, 44048183304486788312148433451363384677562265908331949128489393215789685032262, 32241931068525137014058842823026578386641954854143559838526554899205067598957, 49951309422467613961193228765530489307475214998374779756599339590522149884499, 0x54555658595a6162636465666768696a6b6c6d6e6f707172737475767778797a, 0x4142434445464748494a4b4c4d4e4f5051525354555658595a00000000000000 // gas irOptimized: 202083 // gas legacy: 204327 -// gas legacyOptimized: 202899 +// gas legacyOptimized: 202903 diff --git a/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol b/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol index f776626ae..03c47f69b 100644 --- a/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol +++ b/test/libsolidity/semanticTests/array/delete/bytes_delete_element.sol @@ -16,6 +16,6 @@ contract c { } // ---- // test1() -> true -// gas irOptimized: 218449 +// gas irOptimized: 218420 // gas legacy: 242263 -// gas legacyOptimized: 241182 +// gas legacyOptimized: 241187 diff --git a/test/libsolidity/semanticTests/array/delete/delete_bytes_array.sol b/test/libsolidity/semanticTests/array/delete/delete_bytes_array.sol index b735d182d..32a96c72c 100644 --- a/test/libsolidity/semanticTests/array/delete/delete_bytes_array.sol +++ b/test/libsolidity/semanticTests/array/delete/delete_bytes_array.sol @@ -32,3 +32,4 @@ contract C { // ---- // f() -> 0 // g() -> 0 +// gas irOptimized: 56617 diff --git a/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol b/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol index f486a50cf..23b0466e7 100644 --- a/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol +++ b/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol @@ -14,6 +14,6 @@ contract C { } // ---- // f() -> 0, 0, 0 -// gas irOptimized: 88026 -// gas legacy: 88800 -// gas legacyOptimized: 87700 +// gas irOptimized: 88028 +// gas legacy: 88799 +// gas legacyOptimized: 87706 diff --git a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol index b4ba8b47f..af0ec6b7f 100644 --- a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol @@ -15,7 +15,7 @@ contract c { // gas legacyOptimized: 466238 // storageEmpty -> 0 // clear() -> -// gas irOptimized: 97705 -// gas legacy: 97919 -// gas legacyOptimized: 97790 +// gas irOptimized: 97800 +// gas legacy: 97947 +// gas legacyOptimized: 97882 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol b/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol index 95df74b4d..a53d00eaa 100644 --- a/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol +++ b/test/libsolidity/semanticTests/array/invalid_encoding_for_storage_byte_array.sol @@ -40,16 +40,18 @@ contract C { // copyFromStorageShort() // x() -> 0x20, 3, 0x6162630000000000000000000000000000000000000000000000000000000000 // copyFromStorageLong() -// gas irOptimized: 121095 +// gas irOptimized: 121092 // gas legacy: 121904 -// gas legacyOptimized: 121388 +// gas legacyOptimized: 121393 // x() -> 0x20, 0x25, 0x3132333435363738393031323334353637383930313233343536373839303132, 0x3334353637000000000000000000000000000000000000000000000000000000 // copyToStorage() // x() -> 0x20, 0x25, 0x3132333435363738393031323334353637383930313233343536373839303132, 0x3334353637000000000000000000000000000000000000000000000000000000 // y() -> 0x20, 0x25, 0x3132333435363738393031323334353637383930313233343536373839303132, 0x3334353637000000000000000000000000000000000000000000000000000000 // del() +// gas irOptimized: 29404 // x() -> 0x20, 0x00 // invalidateXLong() +// gas irOptimized: 47028 // x() -> FAILURE, hex"4e487b71", 0x22 // abiEncode() -> FAILURE, hex"4e487b71", 0x22 // abiEncodePacked() -> FAILURE, hex"4e487b71", 0x22 diff --git a/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_delete.sol b/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_delete.sol new file mode 100644 index 000000000..b638664aa --- /dev/null +++ b/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_delete.sol @@ -0,0 +1,77 @@ +contract C { + bytes testArray; + + struct Canary { + uint256 value; + } + + function getCanary() internal pure returns (Canary storage canary) { + assembly { + mstore(0, testArray.slot) + let testArrayDataArea := keccak256(0, 0x20) + // testArray's data area occupies 3 slots when filled. Canary goes right after + canary.slot := add(testArrayDataArea, 3) + } + } + + constructor() { + Canary storage canary = getCanary(); + canary.value = type(uint256).max; + } + + function getArrayDataAreaSlot() public pure returns (uint256 slot) { + assembly { + mstore(0, testArray.slot) + slot := keccak256(0, 0x20) + } + assert(slot == 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563); + return slot; + } + + function getCanarySlot() public pure returns (uint256) { + return getArrayDataAreaSlot() + 3; + } + + function checkSlots() public view returns (uint256, uint256, uint256, uint256, uint256) { + uint256 dataSlot = getArrayDataAreaSlot(); + uint256 slot0; + uint256 slot1; + uint256 slot2; + uint256 slot3; + assembly { + slot0 := sload(dataSlot) + slot1 := sload(add(dataSlot, 1)) + slot2 := sload(add(dataSlot, 2)) + slot3 := sload(add(dataSlot, 3)) + } + return (slot0, slot1, slot2, slot3, testArray.length); + } + + function fillArray() public { + // Fill testArray to exactly 96 bytes (3 slots in its data area) + for (uint i = 0; i < 96; i++) { + testArray.push(bytes1(uint8(i + 1))); + } + } + + function deleteArray() public { + // Should clear 3 slots without touching canary + delete testArray; + } + + function canaryValue() public view returns (uint256) { + return getCanary().value; + } +} +// ---- +// getArrayDataAreaSlot() -> 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563 +// getCanarySlot() -> 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566 +// checkSlots() -> 0, 0, 0, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// fillArray() +// gas irOptimized: 197289 +// gas legacy: 220574 +// gas legacyOptimized: 206839 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// deleteArray() +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol b/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol new file mode 100644 index 000000000..edb00809b --- /dev/null +++ b/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol @@ -0,0 +1,105 @@ +contract C { + bytes testArray; + + struct Canary { + uint256 value; + } + + function getCanary() internal pure returns (Canary storage canary) { + assembly { + mstore(0, testArray.slot) + let testArrayDataArea := keccak256(0, 0x20) + // testArray's data area occupies 3 slots when filled. Canary goes right after + canary.slot := add(testArrayDataArea, 3) + } + } + + constructor() { + Canary storage canary = getCanary(); + canary.value = type(uint256).max; // Should not be overwritten + } + + function fillArray() public { + // Fill testArray to exactly 96 bytes (3 slots in its data area) + for (uint i = 0; i < 96; i++) { + testArray.push(bytes1(uint8(i + 1))); + } + } + + function shrinkArray() public returns (uint256) { + // Shrink from 96 to 50 bytes. Should clear slot 2 without touching canary + bytes memory newData = new bytes(50); + for (uint i = 0; i < 50; i++) { + newData[i] = bytes1(uint8(i + 2)); + } + testArray = newData; + return testArray.length; + } + + function canaryValue() public view returns (uint256) { + return getCanary().value; + } + + function arrayLength() public view returns (uint256) { + return testArray.length; + } + + function getDataSlotContent(uint256 index) public view returns (bytes32 value) { + assembly { + mstore(0, testArray.slot) + let testArrayDataArea := keccak256(0, 0x20) + let slot := add(testArrayDataArea, index) + value := sload(slot) + } + return value; + } + + function checkSlots() public view returns (bytes32, bytes32, bytes32, uint256, uint256) { + return ( + getDataSlotContent(0), // First data slot + getDataSlotContent(1), // Second data slot (partial cleanup expected) + getDataSlotContent(2), // Third data slot (should be cleared after shrink) + canaryValue(), // Canary value (should never change) + arrayLength() // Current array length + ); + } + + function getSlot1LastBytes() public view returns (bytes14 lastBytes) { + // Get the last 14 bytes of slot 1, which should be zero after partial cleanup + bytes32 slot1 = getDataSlotContent(1); + assembly { + // Shift left by 18 bytes (144 bits) to move the last 14 bytes to the front + lastBytes := shl(144, slot1) + } + return lastBytes; + } + + function getArrayBytes(uint256 start, uint256 count) public view returns (bytes memory) { + bytes memory result = new bytes(count); + for (uint i = 0; i < count && start + i < testArray.length; i++) { + result[i] = testArray[start + i]; + } + return result; + } +} +// ---- +// arrayLength() ->0 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// fillArray() +// gas irOptimized: 197352 +// gas legacy: 220574 +// gas legacyOptimized: 206839 +// arrayLength() ->96 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// getArrayBytes(uint256,uint256): 0, 5 -> 0x20, 5, 0x0102030405000000000000000000000000000000000000000000000000000000 +// getArrayBytes(uint256,uint256): 32, 5 -> 0x20, 5, 0x2122232425000000000000000000000000000000000000000000000000000000 +// getArrayBytes(uint256,uint256): 64, 5 -> 0x20, 5, 0x4142434445000000000000000000000000000000000000000000000000000000 +// shrinkArray() -> 50 +// arrayLength() ->50 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// getArrayBytes(uint256,uint256): 0, 5 -> 0x20, 5, 0x0203040506000000000000000000000000000000000000000000000000000000 +// getArrayBytes(uint256,uint256): 32, 5 -> 0x20, 5, 0x2223242526000000000000000000000000000000000000000000000000000000 +// getArrayBytes(uint256,uint256): 45, 5 -> 0x20, 5, 0x2f30313233000000000000000000000000000000000000000000000000000000 +// getSlot1LastBytes() -> 0 +// getDataSlotContent(uint256): 2 -> 0 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/test/libsolidity/semanticTests/array/nested_calldata_storage2.sol b/test/libsolidity/semanticTests/array/nested_calldata_storage2.sol index f8db31b54..f3cb51187 100644 --- a/test/libsolidity/semanticTests/array/nested_calldata_storage2.sol +++ b/test/libsolidity/semanticTests/array/nested_calldata_storage2.sol @@ -8,6 +8,6 @@ contract C { // compileViaYul: true // ---- // i(uint256[][]): 0x20, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -// gas irOptimized: 245506 +// gas irOptimized: 245511 // tmp_i(uint256,uint256): 0, 0 -> 0x0A01 // tmp_i(uint256,uint256): 1, 0 -> 0x0B01 diff --git a/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol b/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol index 96fb11a2d..3b9639716 100644 --- a/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol +++ b/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol @@ -23,7 +23,7 @@ contract c { } // ---- // test() -> 1, 2, 3 -// gas irOptimized: 1828226 -// gas legacy: 1822464 -// gas legacyOptimized: 1813404 +// gas irOptimized: 1828383 +// gas legacy: 1841995 +// gas legacyOptimized: 1821687 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol b/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol index 77ae8c4e2..83c5c1724 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_nested_from_calldata.sol @@ -13,5 +13,5 @@ contract C { // ---- // f(uint120[]): 0x20, 3, 1, 2, 3 -> 1 // gas irOptimized: 112852 -// gas legacy: 113657 -// gas legacyOptimized: 113465 +// gas legacy: 114404 +// gas legacyOptimized: 113087 diff --git a/test/libsolidity/semanticTests/array/push/array_push_struct.sol b/test/libsolidity/semanticTests/array/push/array_push_struct.sol index 92f071e1f..4e1e8b4b3 100644 --- a/test/libsolidity/semanticTests/array/push/array_push_struct.sol +++ b/test/libsolidity/semanticTests/array/push/array_push_struct.sol @@ -21,5 +21,5 @@ contract c { // ---- // test() -> 2, 3, 4, 5 // gas irOptimized: 135329 -// gas legacy: 147437 -// gas legacyOptimized: 146429 +// gas legacy: 139481 +// gas legacyOptimized: 135795 diff --git a/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol b/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol index 5633199d4..04b2a4a73 100644 --- a/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol +++ b/test/libsolidity/semanticTests/array/push/nested_bytes_push.sol @@ -15,4 +15,4 @@ contract C { // f() -> // gas irOptimized: 179534 // gas legacy: 181013 -// gas legacyOptimized: 180397 +// gas legacyOptimized: 180406 diff --git a/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol b/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol index 33ab18450..c3f2e8d75 100644 --- a/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol +++ b/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol @@ -11,7 +11,8 @@ contract c { // (): 1, 2, 3, 4, 5 -> // gas irOptimized: 155122 // gas legacy: 155473 -// gas legacyOptimized: 155295 +// gas legacyOptimized: 155296 // checkIfDataIsEmpty() -> false // sendMessage() -> true, 0x40, 0 +// gas irOptimized: 41925 // checkIfDataIsEmpty() -> true diff --git a/test/libsolidity/semanticTests/cleanup/byte_array_to_storage_cleanup.sol b/test/libsolidity/semanticTests/cleanup/byte_array_to_storage_cleanup.sol index 238f96b7e..4c75ad452 100644 --- a/test/libsolidity/semanticTests/cleanup/byte_array_to_storage_cleanup.sol +++ b/test/libsolidity/semanticTests/cleanup/byte_array_to_storage_cleanup.sol @@ -28,13 +28,14 @@ contract C { // compileViaYul: also // ---- // constructor() -> -// gas irOptimized: 82100 -// gas irOptimized code: 357600 -// gas legacy: 101532 -// gas legacy code: 604800 -// gas legacyOptimized: 84956 -// gas legacyOptimized code: 391800 +// gas irOptimized: 82586 +// gas irOptimized code: 363600 +// gas legacy: 101811 +// gas legacy code: 608200 +// gas legacyOptimized: 85196 +// gas legacyOptimized code: 394800 // h() -> 0x20, 0x40, 0x00, 0 // ~ emit ev(uint256[],uint256): 0x40, 0x21, 0x02, 0x00, 0x00 // g() -> 0x20, 0x40, 0, 0x00 // f(bytes): 0x20, 33, 0, -1 -> 0x20, 0x22, 0, 0xff00000000000000000000000000000000000000000000000000000000000000 +// gas irOptimized: 54117 diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index aeeb1a0c1..76a4dd961 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -28,7 +28,7 @@ contract Creator { // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 // gas irOptimized: 327784 // gas irOptimized code: 94000 -// gas legacy: 336623 +// gas legacy: 338477 // gas legacy code: 244800 -// gas legacyOptimized: 329515 +// gas legacyOptimized: 329166 // gas legacyOptimized code: 117000 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index 55abe4804..91be8e378 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -26,9 +26,9 @@ contract Creator { // bytecodeFormat: legacy,>=EOFv1 // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" -// gas irOptimized: 169292 +// gas irOptimized: 169297 // gas irOptimized code: 99600 -// gas legacy: 172941 +// gas legacy: 172946 // gas legacy code: 239800 -// gas legacyOptimized: 169815 +// gas legacyOptimized: 169823 // gas legacyOptimized code: 118600 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol index 13db633b9..8a072f3eb 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol @@ -10,11 +10,11 @@ contract Test { // bytecodeFormat: legacy,>=EOFv1 // ---- // constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> -// gas irOptimized: 181465 +// gas irOptimized: 181629 // gas irOptimized code: 78400 -// gas legacy: 195212 +// gas legacy: 195484 // gas legacy code: 109400 -// gas legacyOptimized: 181608 +// gas legacyOptimized: 181853 // gas legacyOptimized code: 71400 // m_x() -> 7 // m_s() -> 0x20, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" diff --git a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol index ed4eb6e4d..cc196a95c 100644 --- a/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol +++ b/test/libsolidity/semanticTests/constructor/constructor_static_array_argument.sol @@ -13,9 +13,9 @@ contract C { // constructor(): 1, 2, 3, 4 -> // gas irOptimized: 148129 // gas irOptimized code: 23000 -// gas legacy: 157977 +// gas legacy: 166201 // gas legacy code: 60400 -// gas legacyOptimized: 149973 +// gas legacyOptimized: 149177 // gas legacyOptimized code: 26200 // a() -> 1 // b(uint256): 0 -> 2 diff --git a/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol b/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol index 1ff58d65b..42b9b50dd 100644 --- a/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol +++ b/test/libsolidity/semanticTests/events/event_dynamic_nested_array_storage_v2.sol @@ -16,5 +16,5 @@ contract C { // createEvent(uint256): 42 -> // ~ emit E(uint256[][]): 0x20, 0x02, 0x40, 0xa0, 0x02, 0x2a, 0x2b, 0x02, 0x2c, 0x2d // gas irOptimized: 185148 -// gas legacy: 187493 +// gas legacy: 188615 // gas legacyOptimized: 184548 diff --git a/test/libsolidity/semanticTests/fallback/call_forward_bytes.sol b/test/libsolidity/semanticTests/fallback/call_forward_bytes.sol index 7bf3aee3a..dfd3d658f 100644 --- a/test/libsolidity/semanticTests/fallback/call_forward_bytes.sol +++ b/test/libsolidity/semanticTests/fallback/call_forward_bytes.sol @@ -20,6 +20,7 @@ contract sender { // forward() -> true // val() -> 8 // clear() -> true +// gas irOptimized: 29243 // val() -> 8 // forward() -> true // val() -> 0x80 diff --git a/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol b/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol index 8a795373e..8d72f7c04 100644 --- a/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol +++ b/test/libsolidity/semanticTests/storage/empty_nonempty_empty.sol @@ -22,11 +22,12 @@ contract Test { // set(bytes): 0x20, 0 // storageEmpty -> 1 // set(bytes): 0x20, 66, "12345678901234567890123456789012", "12345678901234567890123456789012", "12" -// gas irOptimized: 111849 +// gas irOptimized: 111820 // gas legacy: 112734 -// gas legacyOptimized: 112084 +// gas legacyOptimized: 112089 // storageEmpty -> 0 // set(bytes): 0x20, 3, "abc" +// gas irOptimized: 33989 // storageEmpty -> 0 // set(bytes): 0x20, 0 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/storage/static_array_copy_cleanup.sol b/test/libsolidity/semanticTests/storage/static_array_copy_cleanup.sol new file mode 100644 index 000000000..ca471161d --- /dev/null +++ b/test/libsolidity/semanticTests/storage/static_array_copy_cleanup.sol @@ -0,0 +1,94 @@ +contract C { + struct S { + uint64 a; + uint64 b; + uint64 c; + uint64 d; + // All fit in one slot (4 * 64 = 256 bits) + } + + S[5] source; + S[10] dest; + uint256 public canary = type(uint256).max; + + function fillSource() public { + for (uint i = 0; i < 5; i++) { + source[i] = S({ + a: uint64(1 + i * 4), + b: uint64(2 + i * 4), + c: uint64(3 + i * 4), + d: uint64(4 + i * 4) + }); + } + } + + function fillDest() public { + for (uint i = 0; i < 10; i++) { + dest[i] = S({ + a: uint64(100 + i * 4), + b: uint64(101 + i * 4), + c: uint64(102 + i * 4), + d: uint64(103 + i * 4) + }); + } + } + + function copySourceToDest() public { + dest = source; + } + + function deleteSource() public { + delete source; + } + + function deleteDest() public { + delete dest; + } + + function getSourceAsUint() public view returns (uint64[20] memory result) { + for (uint i = 0; i < 5; i++) { + result[i * 4] = source[i].a; + result[i * 4 + 1] = source[i].b; + result[i * 4 + 2] = source[i].c; + result[i * 4 + 3] = source[i].d; + } + } + + function getDestAsUint() public view returns (uint64[40] memory result) { + for (uint i = 0; i < 10; i++) { + result[i * 4] = dest[i].a; + result[i * 4 + 1] = dest[i].b; + result[i * 4 + 2] = dest[i].c; + result[i * 4 + 3] = dest[i].d; + } + } +} +// ---- +// canary() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// getSourceAsUint() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// getDestAsUint() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// fillSource() +// gas irOptimized: 135018 +// gas legacy: 146851 +// gas legacyOptimized: 137549 +// canary() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// getSourceAsUint() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 +// fillDest() +// gas irOptimized: 248706 +// gas legacy: 272468 +// gas legacyOptimized: 253871 +// canary() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// getSourceAsUint() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 +// getDestAsUint() -> 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139 +// copySourceToDest() +// canary() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// getSourceAsUint() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 +// getDestAsUint() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// deleteSource() +// canary() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// getSourceAsUint() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// getDestAsUint() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// deleteDest() +// canary() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// getSourceAsUint() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// getDestAsUint() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_array_and_partial_assignment_with_layout.sol b/test/libsolidity/semanticTests/storage/storage_boundary_array_and_partial_assignment_with_layout.sol new file mode 100644 index 000000000..1e2637c85 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_array_and_partial_assignment_with_layout.sol @@ -0,0 +1,54 @@ +contract C layout at 2**256 - 5 { + uint256 a; + + function getArray() internal pure returns (uint256[10][1] storage _x) { + assembly { + _x.slot := a.slot + } + } + + function fillArray() public { + uint256[10][1] storage _x = getArray(); + for (uint i = 1; i < 10; i++) + _x[0][i] = i; + } + + function partialAssignArrayBeforeStorageBoundary() public { + uint256[10][1] storage _x = getArray(); + _x[0] = [11, 12, 13]; + } + + function partialAssignArrayCrossStorageBoundary() public { + uint256[10][1] storage _x = getArray(); + _x[0] = [14, 15, 16, 17, 18, 19, 20]; + } + + function clearArray() public { + uint256[10][1] storage _x = getArray(); + delete _x[0]; + } + + function x() public view returns (uint256[10] memory) { + return getArray()[0]; + } +} +// ---- +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// fillArray() +// gas irOptimized: 220749 +// gas legacy: 221473 +// gas legacyOptimized: 220915 +// partialAssignArrayBeforeStorageBoundary() +// x() -> 11, 12, 13, 0, 0, 0, 0, 0, 0, 0 +// fillArray() +// gas irOptimized: 186549 +// gas legacy: 187273 +// gas legacyOptimized: 186715 +// x() -> 11, 1, 2, 3, 4, 5, 6, 7, 8, 9 +// partialAssignArrayCrossStorageBoundary() +// x() -> 14, 15, 16, 17, 18, 19, 20, 0, 0, 0 +// clearArray() +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 44183 +// gas legacy: 46007 +// gas legacyOptimized: 43907 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_array_assignment.sol b/test/libsolidity/semanticTests/storage/storage_boundary_array_assignment.sol new file mode 100644 index 000000000..0de66a714 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_array_assignment.sol @@ -0,0 +1,28 @@ +contract C { + function getArray() internal pure returns (uint256[10][1] storage _x) { + assembly { + _x.slot := sub(0, 5) + } + } + + function assignArray(uint256[10] memory y) public { + uint256[10][1] storage _x = getArray(); + _x[0] = y; + } + + function x() public view returns (uint256[10] memory) { + return getArray()[0]; + } +} +// ---- +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// assignArray(uint256[10]): 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> +// gas irOptimized: 245236 +// gas legacy: 249351 +// gas legacyOptimized: 245365 +// x() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 +// assignArray(uint256[10]): 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 -> +// x() -> 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 +// gas irOptimized: 44183 +// gas legacy: 46012 +// gas legacyOptimized: 43907 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_array_copy.sol b/test/libsolidity/semanticTests/storage/storage_boundary_array_copy.sol new file mode 100644 index 000000000..949edc490 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_array_copy.sol @@ -0,0 +1,61 @@ +contract C { + constructor() { + uint256[10][1] storage _x = getX(); + _x[0] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + } + + function getX() internal pure returns (uint256[10][1] storage _x) { + assembly { + _x.slot := sub(0, 5) + } + } + + function getY() internal pure returns (uint256[10][1] storage _y) { + assembly { + _y.slot := 5 + } + } + + function copyXToY() public { + uint256[10][1] storage _x = getX(); + uint256[10][1] storage _y = getY(); + _y[0] = _x[0]; + } + + function clearX() public { + uint256[10][1] storage _x = getX(); + delete _x[0]; + } + + function copyYToX() public { + uint256[10][1] storage _x = getX(); + uint256[10][1] storage _y = getY(); + _x[0] = _y[0]; + } + + function x() public view returns (uint256[10] memory) { + return getX()[0]; + } + + function y() public view returns (uint256[10] memory) { + return getY()[0]; + } +} +// ---- +// x() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 +// y() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// copyXToY() +// gas irOptimized: 264224 +// gas legacy: 265434 +// gas legacyOptimized: 264247 +// x() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 +// y() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 +// clearX() +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// y() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 +// copyYToX() +// gas irOptimized: 266243 +// gas legacy: 267456 +// gas legacyOptimized: 266280 +// x() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 +// y() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_array_delete.sol b/test/libsolidity/semanticTests/storage/storage_boundary_array_delete.sol new file mode 100644 index 000000000..20d2e2ec9 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_array_delete.sol @@ -0,0 +1,34 @@ +contract C { + function getArray() internal pure returns (uint256[10][1] storage _x) { + assembly { + _x.slot := sub(0, 5) + } + } + + function fillArray() public { + uint256[10][1] storage _x = getArray(); + for (uint i = 1; i < 10; i++) + _x[0][i] = i; + } + + function clearArray() public { + uint256[10][1] storage _x = getArray(); + delete _x[0]; + } + + function x() public view returns (uint256[10] memory) { + return getArray()[0]; + } +} +// ---- +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// fillArray() +// gas irOptimized: 220705 +// gas legacy: 221434 +// gas legacyOptimized: 220871 +// x() -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +// clearArray() +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 44183 +// gas legacy: 46012 +// gas legacyOptimized: 43907 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_array_delete_overlapping_variable.sol b/test/libsolidity/semanticTests/storage/storage_boundary_array_delete_overlapping_variable.sol new file mode 100644 index 000000000..3bb605cc9 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_array_delete_overlapping_variable.sol @@ -0,0 +1,40 @@ +contract C { + uint256 public y = 42; + + function getArray() internal pure returns (uint256[10][1] storage _x) { + assembly { + _x.slot := sub(0, 5) + } + } + + function fillArray() public { + uint256[10][1] storage _x = getArray(); + for (uint i = 1; i < 10; i++) + _x[0][i] = i; + } + + function clearArray() public { + uint256[10][1] storage _x = getArray(); + delete _x[0]; + } + + function x() public view returns (uint256[10] memory) { + return getArray()[0]; + } +} + +// ---- +// y() -> 42 +// x() -> 0, 0, 0, 0, 0, 42, 0, 0, 0, 0 +// fillArray() +// gas irOptimized: 203627 +// gas legacy: 204356 +// gas legacyOptimized: 203793 +// y() -> 5 +// x() -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +// clearArray() +// y() -> 0 +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 44183 +// gas legacy: 46012 +// gas legacyOptimized: 43907 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_array_packing_not_overlapping_variable.sol b/test/libsolidity/semanticTests/storage/storage_boundary_array_packing_not_overlapping_variable.sol new file mode 100644 index 000000000..77a6158ac --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_array_packing_not_overlapping_variable.sol @@ -0,0 +1,63 @@ +contract C { + struct Canary { + uint256 value; + } + + constructor() { + Canary storage canary = getCanary(); + canary.value = type(uint256).max; // Should not be overwritten + } + + function getArray() internal pure returns (uint64[10][1] storage _x) { + // Array of 10 * uint64 values (8 bytes each) + // Packs 4 uint64 per slot -> 3 slots total (slots -1, 0, 1) + assembly { + _x.slot := sub(0, 1) + } + } + + function getCanary() internal pure returns (Canary storage canary) { + // Canary at slot 2, right after the array ends at slot 1 + assembly { + canary.slot := 2 + } + } + + function fillArray() public { + uint64[10][1] storage _x = getArray(); + for (uint64 i = 0; i < 10; i++) + _x[0][i] = i; + } + + function shrinkTo5() public { + uint64[10][1] storage _x = getArray(); + // Resize by assigning a smaller array + // This should clear items [5..9] without touching y + _x[0] = [uint64(11), 12, 13, 14, 15]; + } + + function clearArray() public { + uint64[10][1] storage _x = getArray(); + delete _x[0]; + } + + function x() public view returns (uint64[10] memory) { + return getArray()[0]; + } + + function canaryValue() public view returns (uint256) { + return getCanary().value; + } +} +// ---- +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// fillArray() +// x() -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// shrinkTo5() +// x() -> 11, 12, 13, 14, 15, 0, 0, 0, 0, 0 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// clearArray() +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_array_partial_assignment.sol b/test/libsolidity/semanticTests/storage/storage_boundary_array_partial_assignment.sol new file mode 100644 index 000000000..c4e3ee779 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_array_partial_assignment.sol @@ -0,0 +1,41 @@ +contract C { + function getArray() internal pure returns (uint256[10][1] storage _x) { + assembly { + _x.slot := sub(0, 5) + } + } + + function fillArray() public { + uint256[10][1] storage _x = getArray(); + for (uint i = 1; i < 10; i++) + _x[0][i] = i; + } + + function x() public view returns (uint256[10] memory) { + return getArray()[0]; + } + + function partialAssignArrayBeforeStorageBoundary() public { + uint256[10][1] storage _x = getArray(); + _x[0] = [21, 22, 23]; + } + + function partialAssignArrayCrossStorageBoundary() public { + uint256[10][1] storage _x = getArray(); + _x[0] = [11, 12, 13, 14, 15, 16, 17]; + } +} +// ---- +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// fillArray() +// gas irOptimized: 220727 +// gas legacy: 221456 +// gas legacyOptimized: 220893 +// x() -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +// partialAssignArrayCrossStorageBoundary() +// x() -> 11, 12, 13, 14, 15, 16, 17, 0, 0, 0 +// partialAssignArrayBeforeStorageBoundary() +// x() -> 21, 22, 23, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 44183 +// gas legacy: 46012 +// gas legacyOptimized: 43907 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_delete_overflow_bug.sol b/test/libsolidity/semanticTests/storage/storage_boundary_delete_overflow_bug.sol new file mode 100644 index 000000000..3ffb77747 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_delete_overflow_bug.sol @@ -0,0 +1,80 @@ +contract C { + mapping(string => uint256[256][2**240]) m; + + function getSlot() internal view returns (uint256) { + uint256[256][2**240] storage _x = m["v 2.2.3"]; + uint256 slot; + assembly { + slot := _x.slot + } + assert(slot == 0xffdb3f1d9f54eb0b5012935c286c508459d381405d269e01c15f4ec2826edbbf); + return slot; + } + + function getIndex() internal view returns (uint256) { + uint256 slot = getSlot(); + // Pick the largest index such that `slot + 256 * index` <= `2**256 - 1` + uint256 index = (type(uint256).max - slot) / 256; + assert(index <= type(uint240).max); + assert((type(uint256).max - slot + 1) % 256 != 0); + + return index; + } + + function getArray() internal view returns (uint256[256][2**240] storage _x) { + uint256 s = getSlot(); + assembly { + _x.slot := s + } + } + + function fillArray() public { + uint256[256][2**240] storage _x = getArray(); + for (uint i = 1; i < 256; i++) + _x[getIndex()][i] = i; + } + + function partialAssignArray() public { + uint256[256][2**240] storage _x = getArray(); + _x[getIndex()] = [11, 22, 33, 44, 55, 66, 77, 88, 99]; + } + + function clearArray() public { + uint256[256][2**240] storage _x = getArray(); + delete _x[getIndex()]; + } + + function x() public view returns (uint256[256] memory) { + return getArray()[getIndex()]; + } +} + +// ---- +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 604108 +// gas legacy: 644983 +// gas legacyOptimized: 598016 +// fillArray() +// gas irOptimized: 5782148 +// gas legacy: 6044562 +// gas legacyOptimized: 5853893 +// x() -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 +// gas irOptimized: 604108 +// gas legacy: 644983 +// gas legacyOptimized: 598016 +// partialAssignArray() +// gas irOptimized: 1067376 +// gas legacy: 1177356 +// gas legacyOptimized: 1068067 +// x() -> 11, 22, 33, 44, 55, 66, 77, 88, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 604108 +// gas legacy: 644983 +// gas legacyOptimized: 598016 +// clearArray() +// gas irOptimized: 580378 +// gas legacy: 582976 +// gas legacyOptimized: 581290 +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 604108 +// gas legacy: 644983 +// gas legacyOptimized: 598016 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_packed_array.sol b/test/libsolidity/semanticTests/storage/storage_boundary_packed_array.sol new file mode 100644 index 000000000..aa30a2bca --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_packed_array.sol @@ -0,0 +1,35 @@ +contract C { + function getArray() internal pure returns (uint64[40][1] storage _x) { + assembly { + _x.slot := sub(0, 5) + } + } + + function fillArray() public { + uint64[40][1] storage _x = getArray(); + for (uint64 i = 1; i < 40; i++) + _x[0][i] = i; + } + + function clearArray() public { + uint64[40][1] storage _x = getArray(); + delete _x[0]; + } + + function x() public view returns (uint64[40] memory) { + return getArray()[0]; + } +} +// ---- +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// fillArray() +// gas irOptimized: 254227 +// gas legacy: 258712 +// gas legacyOptimized: 257258 +// x() -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 +// clearArray() +// gas irOptimized: 57426 +// x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 48087 +// gas legacy: 64080 +// gas legacyOptimized: 56602 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol new file mode 100644 index 000000000..213dee1da --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol @@ -0,0 +1,172 @@ +pragma abicoder v2; + +contract C { + struct S { + uint256 a; // slot 0 (bytes 0-31) + uint128 b; // slot 1 (bytes 0-15) + uint64 c; // slot 1 (bytes 16-23) + bytes32 d; // slot 2 (bytes 0-31) + bool e; // slot 3 (byte 0) + // Total: 4 slots per struct + } + + struct Canary { + uint256 value; + } + + function getBoundaryArray() internal pure returns (S[10][1] storage arr) { + // 10 structs * 4 slots = 40 slots total + // Starts at -20, ends at slot 19 + assembly { + arr.slot := sub(0, 20) + } + } + + function getDest() internal pure returns (S[10][1] storage arr) { + assembly { + arr.slot := 21 + } + } + + function getCanary() internal pure returns (Canary storage canary) { + // Array ends at slot 19, canary at slot 20 + assembly { + canary.slot := 20 + } + } + + constructor() { + Canary storage canary = getCanary(); + canary.value = type(uint256).max; + } + + function fillBoundaryArray() public { + S[10][1] storage arr = getBoundaryArray(); + for (uint i = 0; i < 10; i++) { + arr[0][i] = S({ + a: 1 + i * 5, + b: uint128(2 + i * 5), + c: uint64(3 + i * 5), + d: bytes32(uint256(4 + i * 5)), + e: true + }); + } + } + + function deleteBoundaryArray() public { + S[10][1] storage arr = getBoundaryArray(); + delete arr[0]; + } + + function copyFromBoundary() public { + S[10][1] storage source = getBoundaryArray(); + S[10][1] storage dest = getDest(); + dest[0] = source[0]; + } + + function copyToBoundary() public { + S[10][1] storage source = getDest(); + S[10][1] storage dest = getBoundaryArray(); + dest[0] = source[0]; + } + + function fillDestArray() public { + S[10][1] storage dest = getDest(); + for (uint i = 0; i < 10; i++) { + dest[0][i] = S({ + a: 51 + i * 5, + b: uint128(52 + i * 5), + c: uint64(53 + i * 5), + d: bytes32(uint256(54 + i * 5)), + e: true + }); + } + } + + function boundaryArray() public view returns (S[10] memory) { + return getBoundaryArray()[0]; + } + + function destArray() public view returns (S[10] memory) { + return getDest()[0]; + } + + function canaryValue() public view returns (uint256) { + return getCanary().value; + } +} +// ---- +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 113169 +// gas legacy: 120742 +// gas legacyOptimized: 112518 +// destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 113078 +// gas legacy: 120738 +// gas legacyOptimized: 112505 +// fillBoundaryArray() +// gas irOptimized: 912522 +// gas legacy: 930728 +// gas legacyOptimized: 916628 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 1, 2, 3, 4, true, 6, 7, 8, 9, true, 11, 12, 13, 14, true, 16, 17, 18, 19, true, 21, 22, 23, 24, true, 26, 27, 28, 29, true, 31, 32, 33, 34, true, 36, 37, 38, 39, true, 41, 42, 43, 44, true, 46, 47, 48, 49, true +// gas irOptimized: 113169 +// gas legacy: 120742 +// gas legacyOptimized: 112518 +// destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 113078 +// gas legacy: 120738 +// gas legacyOptimized: 112505 +// copyFromBoundary() +// gas irOptimized: 994579 +// gas legacy: 1023407 +// gas legacyOptimized: 994746 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 1, 2, 3, 4, true, 6, 7, 8, 9, true, 11, 12, 13, 14, true, 16, 17, 18, 19, true, 21, 22, 23, 24, true, 26, 27, 28, 29, true, 31, 32, 33, 34, true, 36, 37, 38, 39, true, 41, 42, 43, 44, true, 46, 47, 48, 49, true +// gas irOptimized: 113169 +// gas legacy: 120742 +// gas legacyOptimized: 112518 +// destArray() -> 1, 2, 3, 4, true, 6, 7, 8, 9, true, 11, 12, 13, 14, true, 16, 17, 18, 19, true, 21, 22, 23, 24, true, 26, 27, 28, 29, true, 31, 32, 33, 34, true, 36, 37, 38, 39, true, 41, 42, 43, 44, true, 46, 47, 48, 49, true +// gas irOptimized: 113078 +// gas legacy: 120738 +// gas legacyOptimized: 112505 +// fillDestArray() +// gas irOptimized: 200426 +// gas legacy: 218746 +// gas legacyOptimized: 204648 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 1, 2, 3, 4, true, 6, 7, 8, 9, true, 11, 12, 13, 14, true, 16, 17, 18, 19, true, 21, 22, 23, 24, true, 26, 27, 28, 29, true, 31, 32, 33, 34, true, 36, 37, 38, 39, true, 41, 42, 43, 44, true, 46, 47, 48, 49, true +// gas irOptimized: 113169 +// gas legacy: 120742 +// gas legacyOptimized: 112518 +// destArray() -> 51, 52, 53, 54, true, 56, 57, 58, 59, true, 61, 62, 63, 64, true, 66, 67, 68, 69, true, 71, 72, 73, 74, true, 76, 77, 78, 79, true, 81, 82, 83, 84, true, 86, 87, 88, 89, true, 91, 92, 93, 94, true, 96, 97, 98, 99, true +// gas irOptimized: 113078 +// gas legacy: 120738 +// gas legacyOptimized: 112505 +// copyToBoundary() +// gas irOptimized: 282623 +// gas legacy: 311362 +// gas legacyOptimized: 282712 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 51, 52, 53, 54, true, 56, 57, 58, 59, true, 61, 62, 63, 64, true, 66, 67, 68, 69, true, 71, 72, 73, 74, true, 76, 77, 78, 79, true, 81, 82, 83, 84, true, 86, 87, 88, 89, true, 91, 92, 93, 94, true, 96, 97, 98, 99, true +// gas irOptimized: 113169 +// gas legacy: 120742 +// gas legacyOptimized: 112518 +// destArray() -> 51, 52, 53, 54, true, 56, 57, 58, 59, true, 61, 62, 63, 64, true, 66, 67, 68, 69, true, 71, 72, 73, 74, true, 76, 77, 78, 79, true, 81, 82, 83, 84, true, 86, 87, 88, 89, true, 91, 92, 93, 94, true, 96, 97, 98, 99, true +// gas irOptimized: 113078 +// gas legacy: 120738 +// gas legacyOptimized: 112505 +// deleteBoundaryArray() +// gas irOptimized: 177968 +// gas legacy: 180997 +// gas legacyOptimized: 178175 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// gas irOptimized: 113169 +// gas legacy: 120742 +// gas legacyOptimized: 112518 +// destArray() -> 51, 52, 53, 54, true, 56, 57, 58, 59, true, 61, 62, 63, 64, true, 66, 67, 68, 69, true, 71, 72, 73, 74, true, 76, 77, 78, 79, true, 81, 82, 83, 84, true, 86, 87, 88, 89, true, 91, 92, 93, 94, true, 96, 97, 98, 99, true +// gas irOptimized: 113078 +// gas legacy: 120738 +// gas legacyOptimized: 112505 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol new file mode 100644 index 000000000..55e36cd08 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol @@ -0,0 +1,128 @@ +pragma abicoder v2; + +contract C { + struct S { + uint256 a; + uint256 b; + uint256 c; + // 3 slots per struct + } + + struct Canary { + uint256 value; + } + + function getBoundaryArray() internal pure returns (S[10][1] storage arr) { + // 10 structs, each 3 slots = 30 slots total + assembly { + arr.slot := sub(0, 15) + } + } + + function getDest() internal pure returns (S[10][1] storage arr) { + assembly { + arr.slot := 16 + } + } + + function getCanary() internal pure returns (Canary storage canary) { + assembly { + canary.slot := 15 + } + } + + constructor() { + Canary storage canary = getCanary(); + canary.value = type(uint256).max; + } + + function fillBoundaryArray() public { + S[10][1] storage arr = getBoundaryArray(); + for (uint i = 0; i < 10; i++) { + arr[0][i] = S({ + a: 1 + i * 3, + b: 2 + i * 3, + c: 3 + i * 3 + }); + } + } + + function deleteBoundaryArray() public { + S[10][1] storage arr = getBoundaryArray(); + delete arr[0]; + } + + function copyFromBoundary() public { + S[10][1] storage source = getBoundaryArray(); + S[10][1] storage dest = getDest(); + dest[0] = source[0]; + } + + function copyToBoundary() public { + S[10][1] storage source = getDest(); + S[10][1] storage dest = getBoundaryArray(); + dest[0] = source[0]; + } + + function fillDestArray() public { + S[10][1] storage dest = getDest(); + for (uint i = 0; i < 10; i++) { + dest[0][i] = S({ + a: 31 + i * 3, + b: 32 + i * 3, + c: 33 + i * 3 + }); + } + } + + function boundaryArray() public view returns (S[10] memory) { + return getBoundaryArray()[0]; + } + + function destArray() public view returns (S[10] memory) { + return getDest()[0]; + } + + function canaryValue() public view returns (uint256) { + return getCanary().value; + } +} +// ---- +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// fillBoundaryArray() +// gas irOptimized: 688719 +// gas legacy: 700075 +// gas legacyOptimized: 691605 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 +// destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// copyFromBoundary() +// gas irOptimized: 748779 +// gas legacy: 767297 +// gas legacyOptimized: 748756 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 +// destArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 +// fillDestArray() +// gas irOptimized: 175623 +// gas legacy: 187093 +// gas legacyOptimized: 178625 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 +// destArray() -> 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 +// copyToBoundary() +// gas irOptimized: 235823 +// gas legacy: 254252 +// gas legacyOptimized: 235722 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 +// destArray() -> 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 +// deleteBoundaryArray() +// gas irOptimized: 137824 +// gas legacy: 137973 +// gas legacyOptimized: 137743 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// destArray() -> 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_packed.sol b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_packed.sol new file mode 100644 index 000000000..5b4085acf --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_packed.sol @@ -0,0 +1,128 @@ +pragma abicoder v2; + +contract C { + struct S { + uint64 a; + uint64 b; + uint64 c; + uint64 d; + // All fit in one slot (4 * 64 = 256 bits) + } + + struct Canary { + uint256 value; + } + + function getBoundaryArray() internal pure returns (S[10][1] storage arr) { + // 10 structs, each 1 slot = 10 slots total + assembly { + arr.slot := sub(0, 5) + } + } + + function getDest() internal pure returns (S[10][1] storage arr) { + assembly { + arr.slot := 6 + } + } + + function getCanary() internal pure returns (Canary storage canary) { + // Array ends at slot 4, canary at slot 5 + assembly { + canary.slot := 5 + } + } + + constructor() { + Canary storage canary = getCanary(); + canary.value = type(uint256).max; + } + + function fillBoundaryArray() public { + S[10][1] storage arr = getBoundaryArray(); + for (uint i = 0; i < 10; i++) { + arr[0][i] = S({ + a: uint64(1 + i * 4), + b: uint64(2 + i * 4), + c: uint64(3 + i * 4), + d: uint64(4 + i * 4) + }); + } + } + + function deleteBoundaryArray() public { + S[10][1] storage arr = getBoundaryArray(); + delete arr[0]; + } + + function copyFromBoundary() public { + S[10][1] storage source = getBoundaryArray(); + S[10][1] storage dest = getDest(); + dest[0] = source[0]; + } + + function copyToBoundary() public { + S[10][1] storage source = getDest(); + S[10][1] storage dest = getBoundaryArray(); + dest[0] = source[0]; + } + + function fillDestArray() public { + S[10][1] storage dest = getDest(); + for (uint i = 0; i < 10; i++) { + dest[0][i] = S({ + a: uint64(41 + i * 4), + b: uint64(42 + i * 4), + c: uint64(43 + i * 4), + d: uint64(44 + i * 4) + }); + } + } + + function boundaryArray() public view returns (S[10] memory) { + return getBoundaryArray()[0]; + } + + function destArray() public view returns (S[10] memory) { + return getDest()[0]; + } + + function canaryValue() public view returns (uint256) { + return getCanary().value; + } +} +// ---- +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// fillBoundaryArray() +// gas irOptimized: 248990 +// gas legacy: 272856 +// gas legacyOptimized: 253856 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 +// destArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// copyFromBoundary() +// gas irOptimized: 274279 +// gas legacy: 298927 +// gas legacyOptimized: 272256 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 +// destArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 +// fillDestArray() +// gas legacy: 101874 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 +// destArray() -> 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 +// gas legacy: 59729 +// copyToBoundary() +// gas irOptimized: 103323 +// gas legacy: 127882 +// gas legacyOptimized: 101222 +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 +// destArray() -> 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 +// deleteBoundaryArray() +// canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// destArray() -> 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 diff --git a/test/libsolidity/semanticTests/storage/storage_packed_array_copy.sol b/test/libsolidity/semanticTests/storage/storage_packed_array_copy.sol new file mode 100644 index 000000000..d4edc5aec --- /dev/null +++ b/test/libsolidity/semanticTests/storage/storage_packed_array_copy.sol @@ -0,0 +1,35 @@ +contract C { + bytes8[9] _x; // 4 per slot + bytes17[10] _y; // 1 per slot, no offset counter + + constructor() { + for (uint256 i = 0; i < _x.length; ++i) _x[i] = bytes8(uint64(i)); + _y[8] = _y[9] = bytes8(uint64(2)); + } + + function getXAsUint() public view returns (uint64[9] memory result) { + for (uint i = 0; i < 9; i++) { + result[i] = uint64(_x[i]); + } + } + + function getYAsUint() public view returns (uint64[10] memory result) { + for (uint i = 0; i < 10; i++) { + result[i] = uint64(bytes8(_y[i])); + } + } + + function copy() public { + _y = _x; + } +} + +// ---- +// getXAsUint() -> 0, 1, 2, 3, 4, 5, 6, 7, 8 +// getYAsUint() -> 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 +// copy() +// gas irOptimized: 190810 +// gas legacy: 195580 +// gas legacyOptimized: 190906 +// getXAsUint() -> 0, 1, 2, 3, 4, 5, 6, 7, 8 +// getYAsUint() -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol index 1737c35bb..bcad9609e 100644 --- a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_dynamic_array.sol @@ -41,9 +41,9 @@ contract C is A layout at 42 { // arrayALength() -> 3 // arrayCLength() -> 0 // initCFromAInReverse() -> 3, 2, 1 -// gas irOptimized: 121276 -// gas legacy: 121213 -// gas legacyOptimized: 120843 +// gas irOptimized: 121281 +// gas legacy: 121937 +// gas legacyOptimized: 120853 // clearA() -> // arrayC(uint256): 0 -> 3 // arrayALength() -> 0 diff --git a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_mapping.sol b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_mapping.sol index e33df29ea..47c4786c8 100644 --- a/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_mapping.sol +++ b/test/libsolidity/semanticTests/storageLayoutSpecifier/state_variable_mapping.sol @@ -27,7 +27,7 @@ contract C layout at 42 is A { // setup() -> // gas irOptimized: 159082 // gas legacy: 161738 -// gas legacyOptimized: 160222 +// gas legacyOptimized: 160218 // open(uint256): 3 -> 0x20, 5, "Empty" // open(uint256): 2 -> 0x20, 6, "Locked" // open(uint256): 1 -> 0x20, 7, "Monster" diff --git a/test/libsolidity/semanticTests/structs/copy_from_mapping.sol b/test/libsolidity/semanticTests/structs/copy_from_mapping.sol index 037ff2067..fccdf0030 100644 --- a/test/libsolidity/semanticTests/structs/copy_from_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_from_mapping.sol @@ -37,7 +37,7 @@ contract C { // ---- // to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 121282 -// gas legacy: 122977 -// gas legacyOptimized: 121652 +// gas legacy: 125480 +// gas legacyOptimized: 121695 // to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 diff --git a/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol b/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol index 600eb35ab..50babde56 100644 --- a/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol +++ b/test/libsolidity/semanticTests/structs/copy_struct_array_from_storage.sol @@ -88,8 +88,8 @@ contract Test { // ---- // test1() -> true // gas irOptimized: 152965 -// gas legacy: 153010 -// gas legacyOptimized: 152636 +// gas legacy: 155952 +// gas legacyOptimized: 152864 // test2() -> true // test3() -> true // test4() -> true diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol index 7188e1bef..9f0b7cbe6 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_from_mapping.sol @@ -45,7 +45,7 @@ contract C { // ---- // to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 121454 -// gas legacy: 123114 -// gas legacyOptimized: 121659 +// gas legacy: 125617 +// gas legacyOptimized: 121699 // to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 diff --git a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol index 54b659ba0..3e8649571 100644 --- a/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_substructures_to_mapping.sol @@ -53,13 +53,13 @@ contract C { // ---- // from_memory() -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 122720 -// gas legacy: 130131 -// gas legacyOptimized: 128648 +// gas legacy: 125558 +// gas legacyOptimized: 123322 // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 121424 -// gas legacy: 123190 -// gas legacyOptimized: 121758 +// gas legacy: 125693 +// gas legacyOptimized: 121804 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 114852 -// gas legacy: 122423 -// gas legacyOptimized: 120698 +// gas legacy: 117950 +// gas legacyOptimized: 115526 diff --git a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol index d020998b4..b31d0e580 100644 --- a/test/libsolidity/semanticTests/structs/copy_to_mapping.sol +++ b/test/libsolidity/semanticTests/structs/copy_to_mapping.sol @@ -46,16 +46,16 @@ contract C { // ---- // from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 121515 -// gas legacy: 123051 -// gas legacyOptimized: 121704 +// gas legacy: 125554 +// gas legacyOptimized: 121747 // from_storage() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 121559 -// gas legacy: 123109 -// gas legacyOptimized: 121756 +// gas legacy: 125612 +// gas legacyOptimized: 121799 // from_memory() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 122740 -// gas legacy: 129996 -// gas legacyOptimized: 128644 +// gas legacy: 125423 +// gas legacyOptimized: 123323 // from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 21, 3, 0x666f6f0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 // gas irOptimized: 114824 // gas legacy: 118207 diff --git a/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol b/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol index e50265e51..3912a4655 100644 --- a/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol +++ b/test/libsolidity/semanticTests/structs/struct_containing_bytes_copy_and_delete.sol @@ -25,7 +25,7 @@ contract c { // set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true // gas irOptimized: 133557 // gas legacy: 134624 -// gas legacyOptimized: 133856 +// gas legacyOptimized: 133857 // test(uint256): 32 -> "3" // storageEmpty -> 0 // copy() -> true @@ -33,7 +33,7 @@ contract c { // set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true // gas irOptimized: 133557 // gas legacy: 134624 -// gas legacyOptimized: 133856 +// gas legacyOptimized: 133857 // storageEmpty -> 0 // del() -> true // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol index a8e29dcad..12cbf0799 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_nested_small.sol @@ -33,4 +33,4 @@ contract C { // compileViaYul: true // ---- // f() -> 0, 0, 0 -// gas irOptimized: 93830 +// gas irOptimized: 93835 diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol index cea110566..cd49ea27a 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol @@ -42,10 +42,10 @@ contract C { } // ---- // f() -> -// gas irOptimized: 113465 -// gas legacy: 113591 -// gas legacyOptimized: 113098 +// gas irOptimized: 113388 +// gas legacy: 113588 +// gas legacyOptimized: 113104 // g() -> -// gas irOptimized: 118828 -// gas legacy: 118764 -// gas legacyOptimized: 118168 +// gas irOptimized: 118768 +// gas legacy: 118766 +// gas legacyOptimized: 118188 diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol index 871c614f5..1a047049f 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_arrays_small.sol @@ -27,4 +27,4 @@ contract C { // compileViaYul: true // ---- // f() -> 0 -// gas irOptimized: 89435 +// gas irOptimized: 89468 diff --git a/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol b/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol index 26e8294e3..47fa27fe3 100644 --- a/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol +++ b/test/libsolidity/semanticTests/types/mapping/copy_from_mapping_to_mapping.sol @@ -30,5 +30,5 @@ contract C { // ---- // f() -> 0x20, 7, 8, 9, 0xa0, 13, 2, 0x40, 0xa0, 2, 3, 4, 2, 3, 4 // gas irOptimized: 197102 -// gas legacy: 199887 -// gas legacyOptimized: 196845 +// gas legacy: 205706 +// gas legacyOptimized: 196739 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol index 015d51c1f..03c6e11bc 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol @@ -49,13 +49,13 @@ contract C { } // ---- // test_f() -> true -// gas irOptimized: 122201 -// gas legacy: 125333 -// gas legacyOptimized: 122693 +// gas irOptimized: 122114 +// gas legacy: 126162 +// gas legacyOptimized: 122757 // test_g() -> true -// gas irOptimized: 106408 -// gas legacy: 111133 -// gas legacyOptimized: 106925 +// gas irOptimized: 106248 +// gas legacy: 111824 +// gas legacyOptimized: 106606 // addresses(uint256): 0 -> 0x18 // addresses(uint256): 1 -> 0x19 // addresses(uint256): 3 -> 0x1b diff --git a/test/libsolidity/semanticTests/userDefinedValueType/calldata_to_storage.sol b/test/libsolidity/semanticTests/userDefinedValueType/calldata_to_storage.sol index 292b9fbfe..0815a2da7 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/calldata_to_storage.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/calldata_to_storage.sol @@ -25,17 +25,17 @@ contract C { // f((uint8,uint16,bytes2,uint8)): 1, 0xff, "ab", 15 -> // gas irOptimized: 44237 // gas legacy: 47154 -// gas legacyOptimized: 45018 +// gas legacyOptimized: 44982 // s() -> 1, 0xff, 0x6162000000000000000000000000000000000000000000000000000000000000, 15 // g(uint16[]): 0x20, 3, 1, 2, 3 -> 0x20, 3, 1, 2, 3 // gas irOptimized: 68578 -// gas legacy: 75429 -// gas legacyOptimized: 74244 +// gas legacy: 71400 +// gas legacyOptimized: 69139 // small(uint256): 0 -> 1 // small(uint256): 1 -> 2 // h(bytes2[]): 0x20, 3, "ab", "cd", "ef" -> 0x20, 3, "ab", "cd", "ef" // gas irOptimized: 68635 -// gas legacy: 75125 -// gas legacyOptimized: 74331 +// gas legacy: 71231 +// gas legacyOptimized: 69289 // l(uint256): 0 -> 0x6162000000000000000000000000000000000000000000000000000000000000 // l(uint256): 1 -> 0x6364000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/memory_to_storage.sol b/test/libsolidity/semanticTests/userDefinedValueType/memory_to_storage.sol index 585249f2f..6e07e74e9 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/memory_to_storage.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/memory_to_storage.sol @@ -29,13 +29,13 @@ contract C { // s() -> 1, 0xff, 0x6162000000000000000000000000000000000000000000000000000000000000, 15 // g(uint16[]): 0x20, 3, 1, 2, 3 -> 0x20, 3, 1, 2, 3 // gas irOptimized: 68898 -// gas legacy: 76511 -// gas legacyOptimized: 74832 +// gas legacy: 72336 +// gas legacyOptimized: 69607 // small(uint256): 0 -> 1 // small(uint256): 1 -> 2 // h(bytes2[]): 0x20, 3, "ab", "cd", "ef" -> 0x20, 3, "ab", "cd", "ef" // gas irOptimized: 68937 -// gas legacy: 76198 -// gas legacyOptimized: 74919 +// gas legacy: 72167 +// gas legacyOptimized: 69802 // l(uint256): 0 -> 0x6162000000000000000000000000000000000000000000000000000000000000 // l(uint256): 1 -> 0x6364000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/various/address_code.sol b/test/libsolidity/semanticTests/various/address_code.sol index 4d810f970..eda17b3c2 100644 --- a/test/libsolidity/semanticTests/various/address_code.sol +++ b/test/libsolidity/semanticTests/various/address_code.sol @@ -16,11 +16,11 @@ contract C { // bytecodeFormat: legacy // ---- // constructor() -> -// gas irOptimized: 70760 +// gas irOptimized: 70924 // gas irOptimized code: 94600 -// gas legacy: 82428 +// gas legacy: 82688 // gas legacy code: 153800 -// gas legacyOptimized: 69400 +// gas legacyOptimized: 69675 // gas legacyOptimized code: 79200 // initCode() -> 0x20, 0 // f() -> true diff --git a/test/libsolidity/semanticTests/various/create_calldata.sol b/test/libsolidity/semanticTests/various/create_calldata.sol index 7e3e32622..c4d17d429 100644 --- a/test/libsolidity/semanticTests/various/create_calldata.sol +++ b/test/libsolidity/semanticTests/various/create_calldata.sol @@ -10,10 +10,10 @@ contract C { // bytecodeFormat: legacy // ---- // constructor(): 42 -> -// gas irOptimized: 68239 +// gas irOptimized: 68387 // gas irOptimized code: 69000 -// gas legacy: 78076 +// gas legacy: 78348 // gas legacy code: 90200 -// gas legacyOptimized: 68321 +// gas legacyOptimized: 68548 // gas legacyOptimized code: 64600 // s() -> 0x20, 0 diff --git a/test/libsolidity/semanticTests/various/destructuring_assignment.sol b/test/libsolidity/semanticTests/various/destructuring_assignment.sol index a961870ee..44fcd0f6a 100644 --- a/test/libsolidity/semanticTests/various/destructuring_assignment.sol +++ b/test/libsolidity/semanticTests/various/destructuring_assignment.sol @@ -33,6 +33,6 @@ contract C { } // ---- // f(bytes): 0x20, 0x5, "abcde" -> 0 -// gas irOptimized: 242027 -// gas legacy: 243281 -// gas legacyOptimized: 242392 +// gas irOptimized: 242037 +// gas legacy: 246685 +// gas legacyOptimized: 242396 diff --git a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol index 8430da4e8..1af8a0419 100644 --- a/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol +++ b/test/libsolidity/semanticTests/various/skip_dynamic_types_for_structs.sol @@ -20,5 +20,5 @@ contract C { // ---- // g() -> 2, 6 // gas irOptimized: 178195 -// gas legacy: 180653 -// gas legacyOptimized: 179144 +// gas legacy: 181357 +// gas legacyOptimized: 179055 diff --git a/test/libsolidity/syntaxTests/array/copy_calldata_struct_array_to_storage_legacy.sol b/test/libsolidity/syntaxTests/array/copy_calldata_struct_array_to_storage_legacy.sol new file mode 100644 index 000000000..8c45b5b9f --- /dev/null +++ b/test/libsolidity/syntaxTests/array/copy_calldata_struct_array_to_storage_legacy.sol @@ -0,0 +1,16 @@ +contract C { + struct S { + uint256 a; + uint256 b; + } + + S[] storageArray; + + function copyFromCalldata(S[] calldata calldataArray) public { + storageArray = calldataArray; + } +} +// ==== +// compileViaYul: false +// ---- +// UnimplementedFeatureError 1834: (0-208): Copying of type struct C.S calldata[] calldata to storage is not supported in legacy (only supported by the IR pipeline). Hint: try compiling with `--via-ir` (CLI) or the equivalent `viaIR: true` (Standard JSON). diff --git a/test/libsolidity/syntaxTests/array/copy_memory_struct_array_to_storage_legacy.sol b/test/libsolidity/syntaxTests/array/copy_memory_struct_array_to_storage_legacy.sol new file mode 100644 index 000000000..86e8bf1f6 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/copy_memory_struct_array_to_storage_legacy.sol @@ -0,0 +1,17 @@ +contract C { + struct S { + uint256 a; + uint256 b; + } + + S[] storageArray; + + function copyFromMemory() public { + S[] memory memArray = new S[](3); + storageArray = memArray; + } +} +// ==== +// compileViaYul: false +// ---- +// UnimplementedFeatureError 1834: (0-217): Copying of type struct C.S memory[] memory to storage is not supported in legacy (only supported by the IR pipeline). Hint: try compiling with `--via-ir` (CLI) or the equivalent `viaIR: true` (Standard JSON). From 1ebf5395e9ccc46ea239a2cdbd2a83e0a9379753 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Wed, 17 Dec 2025 13:48:39 -0300 Subject: [PATCH 1050/1340] Update Changelog.md and add bug entry for LostStorageArrayWriteOnSlotOverflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- Changelog.md | 3 + docs/bugs.json | 10 +++ docs/bugs_by_version.json | 142 +++++++++++++++++++++++++++++++++++--- 3 files changed, 146 insertions(+), 9 deletions(-) diff --git a/Changelog.md b/Changelog.md index 7ed3d7ef6..27e1cb33a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,8 @@ ### 0.8.32 (unreleased) +Important Bugfixes: +* Code Generator: Fix a bug in clearing/copying of arrays that straddle the end of storage, potentially resulting in assignment/initialization/`delete`/`push()`/`pop()` skipping some or all of the intended storage writes. + Language Features: Compiler Features: diff --git a/docs/bugs.json b/docs/bugs.json index 800524669..0c0b0493d 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -1,4 +1,14 @@ [ + { + "uid": "SOL-2025-1", + "name": "LostStorageArrayWriteOnSlotOverflow", + "summary": "Operations that involve clearing or copying from arrays that straddle the end of storage could result in silent data retention.", + "description": "Solidity makes it possible to define variables that extend past the last (2**256-th) slot of storage, which results in wrap-around back to slot zero. Since EVM uses 256-bit integer arithmetic, most operations on such variables just work. The only situation which requires special attention is iteration against absolute slot addresses: the invariant that the last slot belonging to a variable has the highest address does not hold. When implemented incorrectly, a loop over an array will immediately terminate if the container spans the end of storage - due to the initial position already being greater than the end position. This affected storage array clearing loops generated by both evmasm and IR pipelines. Additionally, (only in the evmasm pipeline) copying operations whose source was an array straddling the end of storage were also affected. At the language level, the buggy code would be generated for array assignment, array initialization, delete operator, .pop() and .push(). Note that a clearing loop is inserted by the compiler not only for invocations of the delete operator, but also to zero storage when overwriting a longer array with a shorter one, popping an element or even pushing an empty element to a dynamic array. Since clearing is a separate loop, it is possible for the bug to only affect it and not the copy operation it follows (which is always the case in the IR pipeline). The bug is extremely unlikely to be triggered accidentally due to the probabilistic impossibility of a short dynamic array being allocated right at the storage boundary. On the other hand, scenarios in which a user may place a static array there intentionally do not seem realistic and are limited to unusual layouts, in which a contract does not place any storage variables at slot zero (otherwise they would overlap the array).", + "link": "https://blog.soliditylang.org/2025/12/18/lost-storage-array-write-on-slot-overflow-bug/", + "introduced": "0.1.0", + "fixed": "0.8.32", + "severity": "low" + }, { "uid": "SOL-2023-3", "name": "VerbatimInvalidDeduplication", diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 881f5eabe..94e814892 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1,6 +1,7 @@ { "0.1.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -23,6 +24,7 @@ }, "0.1.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -45,6 +47,7 @@ }, "0.1.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -67,6 +70,7 @@ }, "0.1.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -89,6 +93,7 @@ }, "0.1.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -112,6 +117,7 @@ }, "0.1.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -135,6 +141,7 @@ }, "0.1.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -160,6 +167,7 @@ }, "0.1.7": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -185,6 +193,7 @@ }, "0.2.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -211,6 +220,7 @@ }, "0.2.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -237,6 +247,7 @@ }, "0.2.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -263,6 +274,7 @@ }, "0.3.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -291,6 +303,7 @@ }, "0.3.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -318,6 +331,7 @@ }, "0.3.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -345,6 +359,7 @@ }, "0.3.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -371,6 +386,7 @@ }, "0.3.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -397,6 +413,7 @@ }, "0.3.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -423,6 +440,7 @@ }, "0.3.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -447,6 +465,7 @@ }, "0.4.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -471,6 +490,7 @@ }, "0.4.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -495,6 +515,7 @@ }, "0.4.10": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -518,6 +539,7 @@ }, "0.4.11": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -540,6 +562,7 @@ }, "0.4.12": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -561,6 +584,7 @@ }, "0.4.13": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -582,6 +606,7 @@ }, "0.4.14": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -602,6 +627,7 @@ }, "0.4.15": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -621,6 +647,7 @@ }, "0.4.16": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -643,6 +670,7 @@ }, "0.4.17": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -666,6 +694,7 @@ }, "0.4.18": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -688,6 +717,7 @@ }, "0.4.19": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -711,6 +741,7 @@ }, "0.4.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -734,6 +765,7 @@ }, "0.4.20": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -757,6 +789,7 @@ }, "0.4.21": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -780,6 +813,7 @@ }, "0.4.22": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -803,6 +837,7 @@ }, "0.4.23": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -825,6 +860,7 @@ }, "0.4.24": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -847,6 +883,7 @@ }, "0.4.25": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -867,6 +904,7 @@ }, "0.4.26": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -884,6 +922,7 @@ }, "0.4.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -906,6 +945,7 @@ }, "0.4.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -927,6 +967,7 @@ }, "0.4.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -951,6 +992,7 @@ }, "0.4.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -974,6 +1016,7 @@ }, "0.4.7": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -997,6 +1040,7 @@ }, "0.4.8": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -1020,6 +1064,7 @@ }, "0.4.9": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -1043,6 +1088,7 @@ }, "0.5.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1063,6 +1109,7 @@ }, "0.5.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1083,6 +1130,7 @@ }, "0.5.10": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1101,6 +1149,7 @@ }, "0.5.11": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1118,6 +1167,7 @@ }, "0.5.12": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1135,6 +1185,7 @@ }, "0.5.13": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1152,6 +1203,7 @@ }, "0.5.14": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1171,6 +1223,7 @@ }, "0.5.15": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1189,6 +1242,7 @@ }, "0.5.16": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1206,6 +1260,7 @@ }, "0.5.17": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1222,6 +1277,7 @@ }, "0.5.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1242,6 +1298,7 @@ }, "0.5.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1262,6 +1319,7 @@ }, "0.5.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1282,6 +1340,7 @@ }, "0.5.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1304,6 +1363,7 @@ }, "0.5.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1326,6 +1386,7 @@ }, "0.5.7": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1346,6 +1407,7 @@ }, "0.5.8": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1367,6 +1429,7 @@ }, "0.5.9": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1387,6 +1450,7 @@ }, "0.6.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1405,6 +1469,7 @@ }, "0.6.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1422,6 +1487,7 @@ }, "0.6.10": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1438,6 +1504,7 @@ }, "0.6.11": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1454,6 +1521,7 @@ }, "0.6.12": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1470,6 +1538,7 @@ }, "0.6.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", @@ -1488,6 +1557,7 @@ }, "0.6.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", @@ -1506,6 +1576,7 @@ }, "0.6.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", @@ -1524,6 +1595,7 @@ }, "0.6.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", @@ -1542,6 +1614,7 @@ }, "0.6.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", @@ -1559,6 +1632,7 @@ }, "0.6.7": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1577,6 +1651,7 @@ }, "0.6.8": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1592,6 +1667,7 @@ }, "0.6.9": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1609,6 +1685,7 @@ }, "0.7.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1625,6 +1702,7 @@ }, "0.7.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1642,6 +1720,7 @@ }, "0.7.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1658,6 +1737,7 @@ }, "0.7.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1673,6 +1753,7 @@ }, "0.7.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1687,6 +1768,7 @@ }, "0.7.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1701,6 +1783,7 @@ }, "0.7.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1715,6 +1798,7 @@ }, "0.8.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1729,6 +1813,7 @@ }, "0.8.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1743,6 +1828,7 @@ }, "0.8.10": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1755,6 +1841,7 @@ }, "0.8.11": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1768,6 +1855,7 @@ }, "0.8.12": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1781,6 +1869,7 @@ }, "0.8.13": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1795,6 +1884,7 @@ }, "0.8.14": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1807,6 +1897,7 @@ }, "0.8.15": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1817,6 +1908,7 @@ }, "0.8.16": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1826,6 +1918,7 @@ }, "0.8.17": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" @@ -1834,6 +1927,7 @@ }, "0.8.18": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" @@ -1842,6 +1936,7 @@ }, "0.8.19": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" @@ -1850,6 +1945,7 @@ }, "0.8.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1864,6 +1960,7 @@ }, "0.8.20": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" @@ -1872,46 +1969,63 @@ }, "0.8.21": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication" ], "released": "2023-07-19" }, "0.8.22": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication" ], "released": "2023-10-25" }, "0.8.23": { - "bugs": [], + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], "released": "2023-11-08" }, "0.8.24": { - "bugs": [], + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], "released": "2024-01-25" }, "0.8.25": { - "bugs": [], + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], "released": "2024-03-14" }, "0.8.26": { - "bugs": [], + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], "released": "2024-05-21" }, "0.8.27": { - "bugs": [], + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], "released": "2024-09-04" }, "0.8.28": { - "bugs": [], + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], "released": "2024-10-09" }, "0.8.29": { - "bugs": [], + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], "released": "2025-03-12" }, "0.8.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1924,15 +2038,20 @@ "released": "2021-03-23" }, "0.8.30": { - "bugs": [], + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], "released": "2025-05-07" }, "0.8.31": { - "bugs": [], + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], "released": "2025-12-03" }, "0.8.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1945,6 +2064,7 @@ }, "0.8.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1958,6 +2078,7 @@ }, "0.8.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1971,6 +2092,7 @@ }, "0.8.7": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1984,6 +2106,7 @@ }, "0.8.8": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1998,6 +2121,7 @@ }, "0.8.9": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", From b34a0545eef0e9424e4e5bf6d6bf07c65a94dbc6 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 17 Dec 2025 13:13:33 +0100 Subject: [PATCH 1051/1340] Fix `string|bytes.concat` assignment to a constant variable. --- libsolidity/analysis/TypeChecker.cpp | 17 +++++++++++++++++ libsolidity/ast/Types.cpp | 4 +++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index f5c093dbd..8556487ff 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3271,11 +3271,28 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) // TODO some members might be pure, but for example `address(0x123).balance` is not pure // although every subexpression is, so leaving this limited for now. if (auto tt = dynamic_cast(exprType)) + { if ( tt->actualType()->category() == Type::Category::Enum || tt->actualType()->category() == Type::Category::UserDefinedValueType ) annotation.isPure = true; + + // `concat` purity depends also on its arguments, but this is checked later, in visit(FunctionCall...) + // This covers `bytes.concat` and `string.concat`. + if (tt->actualType()->category() == Type::Category::Array) + { + if ( + auto const* funcType = dynamic_cast(annotation.type); + funcType && + ( + funcType->kind() == FunctionType::Kind::StringConcat || + funcType->kind() == FunctionType::Kind::BytesConcat + ) + ) + annotation.isPure = true; + } + } if ( auto const* functionType = dynamic_cast(exprType); functionType && diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index f5c83b0cf..316d99ba3 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3713,7 +3713,9 @@ bool FunctionType::isPure() const m_kind == Kind::ABIDecode || m_kind == Kind::MetaType || m_kind == Kind::Wrap || - m_kind == Kind::Unwrap; + m_kind == Kind::Unwrap || + m_kind == Kind::BytesConcat || + m_kind == Kind::StringConcat; } TypePointers FunctionType::parseElementaryTypeVector(strings const& _types) From f4b7f98893f570365319673ba64339b61e5e7497 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 17 Dec 2025 13:14:08 +0100 Subject: [PATCH 1052/1340] Add syntax tests. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- .../initialization/abi_decode_const_args.sol | 7 ++ .../abi_decode_non_const_args.sol | 9 +++ .../abi_encode_call_const_args.sol | 5 ++ .../abi_encode_call_non_const_args.sol | 11 +++ .../abi_encoding_builtin_const_args.sol} | 0 .../abi_encoding_builtin_non_const_args.sol | 13 +++ .../addmod_by_zero.sol} | 0 .../addmod_mulmod_rational_arg.sol} | 0 .../initialization/block_tx_msg_property.sol | 80 +++++++++++++++++++ .../bytes_concat_const_args.sol | 11 +++ .../bytes_concat_non_const_args.sol | 17 ++++ .../constant_with_cyclic_dependency_1.sol} | 0 .../constant_with_cyclic_dependency_2.sol} | 0 .../constant_with_cyclic_dependency_3.sol} | 0 .../constant_with_cyclic_dependency_4.sol} | 0 .../constant_with_cyclic_dependency_5.sol} | 0 .../constant_with_cyclic_dependency_file.sol} | 0 ...th_cyclic_dependency_file_and_library.sol} | 0 ...nstant_with_cyclic_dependency_library.sol} | 0 .../{ => initialization}/division_by_zero.sol | 0 .../function_pointer_call.sol} | 0 .../math_builtin_opcode_based_const_args.sol | 14 ++++ ...th_builtin_opcode_based_non_const_args.sol | 12 +++ ...th_builtin_precompile_based_const_args.sol | 16 ++++ ...uiltin_precompile_based_non_const_args.sol | 10 +++ .../modulo_by_zero.sol} | 0 .../mulmod_by_zero.sol} | 0 .../string_concat_const_args.sol | 9 +++ .../string_concat_non_const_args.sol | 14 ++++ .../constants/initialization/type_info.sol | 23 ++++++ 30 files changed, 251 insertions(+) create mode 100644 test/libsolidity/syntaxTests/constants/initialization/abi_decode_const_args.sol create mode 100644 test/libsolidity/syntaxTests/constants/initialization/abi_decode_non_const_args.sol create mode 100644 test/libsolidity/syntaxTests/constants/initialization/abi_encode_call_const_args.sol create mode 100644 test/libsolidity/syntaxTests/constants/initialization/abi_encode_call_non_const_args.sol rename test/libsolidity/syntaxTests/constants/{abi_encoding_constant.sol => initialization/abi_encoding_builtin_const_args.sol} (100%) create mode 100644 test/libsolidity/syntaxTests/constants/initialization/abi_encoding_builtin_non_const_args.sol rename test/libsolidity/syntaxTests/constants/{addmod_zero.sol => initialization/addmod_by_zero.sol} (100%) rename test/libsolidity/syntaxTests/constants/{addmod_mulmod_rational.sol => initialization/addmod_mulmod_rational_arg.sol} (100%) create mode 100644 test/libsolidity/syntaxTests/constants/initialization/block_tx_msg_property.sol create mode 100644 test/libsolidity/syntaxTests/constants/initialization/bytes_concat_const_args.sol create mode 100644 test/libsolidity/syntaxTests/constants/initialization/bytes_concat_non_const_args.sol rename test/libsolidity/syntaxTests/constants/{cyclic_dependency_1.sol => initialization/constant_with_cyclic_dependency_1.sol} (100%) rename test/libsolidity/syntaxTests/constants/{cyclic_dependency_2.sol => initialization/constant_with_cyclic_dependency_2.sol} (100%) rename test/libsolidity/syntaxTests/constants/{cyclic_dependency_3.sol => initialization/constant_with_cyclic_dependency_3.sol} (100%) rename test/libsolidity/syntaxTests/constants/{cyclic_dependency_4.sol => initialization/constant_with_cyclic_dependency_4.sol} (100%) rename test/libsolidity/syntaxTests/constants/{cyclic_dependency_5.sol => initialization/constant_with_cyclic_dependency_5.sol} (100%) rename test/libsolidity/syntaxTests/constants/{cyclic_dependency_file_constants.sol => initialization/constant_with_cyclic_dependency_file.sol} (100%) rename test/libsolidity/syntaxTests/constants/{cyclic_dependency_file_and_library_constants.sol => initialization/constant_with_cyclic_dependency_file_and_library.sol} (100%) rename test/libsolidity/syntaxTests/constants/{cyclic_dependency_library_constants.sol => initialization/constant_with_cyclic_dependency_library.sol} (100%) rename test/libsolidity/syntaxTests/constants/{ => initialization}/division_by_zero.sol (100%) rename test/libsolidity/syntaxTests/constants/{assign_constant_function_value.sol => initialization/function_pointer_call.sol} (100%) create mode 100644 test/libsolidity/syntaxTests/constants/initialization/math_builtin_opcode_based_const_args.sol create mode 100644 test/libsolidity/syntaxTests/constants/initialization/math_builtin_opcode_based_non_const_args.sol create mode 100644 test/libsolidity/syntaxTests/constants/initialization/math_builtin_precompile_based_const_args.sol create mode 100644 test/libsolidity/syntaxTests/constants/initialization/math_builtin_precompile_based_non_const_args.sol rename test/libsolidity/syntaxTests/constants/{mod_zero.sol => initialization/modulo_by_zero.sol} (100%) rename test/libsolidity/syntaxTests/constants/{mulmod_zero.sol => initialization/mulmod_by_zero.sol} (100%) create mode 100644 test/libsolidity/syntaxTests/constants/initialization/string_concat_const_args.sol create mode 100644 test/libsolidity/syntaxTests/constants/initialization/string_concat_non_const_args.sol create mode 100644 test/libsolidity/syntaxTests/constants/initialization/type_info.sol diff --git a/test/libsolidity/syntaxTests/constants/initialization/abi_decode_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/abi_decode_const_args.sol new file mode 100644 index 000000000..6f597ae73 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/abi_decode_const_args.sol @@ -0,0 +1,7 @@ +bytes constant aEncoded = abi.encode( + hex"aaaa" +); + +contract A { + bytes constant a = abi.decode(aEncoded, (bytes)); +} diff --git a/test/libsolidity/syntaxTests/constants/initialization/abi_decode_non_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/abi_decode_non_const_args.sol new file mode 100644 index 000000000..e5772333a --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/abi_decode_non_const_args.sol @@ -0,0 +1,9 @@ +contract A { + function encoded() private view returns (bytes memory) { + return abi.encode(hex"aaaa"); + } + + bytes constant a = abi.decode(encoded(), (bytes)); +} +// ---- +// TypeError 8349: (142-172): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/constants/initialization/abi_encode_call_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/abi_encode_call_const_args.sol new file mode 100644 index 000000000..e716694cc --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/abi_encode_call_const_args.sol @@ -0,0 +1,5 @@ +contract A { + bool constant FLAG = true; + function f(uint, bool) external {} + bytes constant fCallA = abi.encodeCall(A.f, (123, FLAG)); +} diff --git a/test/libsolidity/syntaxTests/constants/initialization/abi_encode_call_non_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/abi_encode_call_non_const_args.sol new file mode 100644 index 000000000..b49213742 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/abi_encode_call_non_const_args.sol @@ -0,0 +1,11 @@ +contract A { + function f(uint a) external {} + + function getA() private view returns(uint) { + return 1; + } + + bytes constant fCallA = abi.encodeCall(A.f, (getA())); +} +// ---- +// TypeError 8349: (151-180): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/constants/abi_encoding_constant.sol b/test/libsolidity/syntaxTests/constants/initialization/abi_encoding_builtin_const_args.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/abi_encoding_constant.sol rename to test/libsolidity/syntaxTests/constants/initialization/abi_encoding_builtin_const_args.sol diff --git a/test/libsolidity/syntaxTests/constants/initialization/abi_encoding_builtin_non_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/abi_encoding_builtin_non_const_args.sol new file mode 100644 index 000000000..7e399a0d0 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/abi_encoding_builtin_non_const_args.sol @@ -0,0 +1,13 @@ +contract C { + uint k = 1; + + bytes32 constant a = keccak256(abi.encode(1, k)); + bytes32 constant b = keccak256(abi.encodePacked(uint(1), k)); + bytes32 constant c = keccak256(abi.encodeWithSelector(0x12345678, k, 2)); + bytes32 constant d = keccak256(abi.encodeWithSignature("f()", 1, k)); +} +// ---- +// TypeError 8349: (55-82): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (109-148): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (175-226): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (253-300): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/constants/addmod_zero.sol b/test/libsolidity/syntaxTests/constants/initialization/addmod_by_zero.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/addmod_zero.sol rename to test/libsolidity/syntaxTests/constants/initialization/addmod_by_zero.sol diff --git a/test/libsolidity/syntaxTests/constants/addmod_mulmod_rational.sol b/test/libsolidity/syntaxTests/constants/initialization/addmod_mulmod_rational_arg.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/addmod_mulmod_rational.sol rename to test/libsolidity/syntaxTests/constants/initialization/addmod_mulmod_rational_arg.sol diff --git a/test/libsolidity/syntaxTests/constants/initialization/block_tx_msg_property.sol b/test/libsolidity/syntaxTests/constants/initialization/block_tx_msg_property.sol new file mode 100644 index 000000000..54381a257 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/block_tx_msg_property.sol @@ -0,0 +1,80 @@ +bytes32 constant blockhGlobal = blockhash(1); +bytes32 constant blobhGlobal = blobhash(1); +uint constant bfGlobal = block.basefee; +uint constant blobbfGlobal = block.blobbasefee; +uint constant chainIdGlobal = block.chainid; +address constant coinbaseGlobal = block.coinbase; +uint constant diffGlobal = block.difficulty; +uint constant gaslimitGlobal = block.gaslimit; +uint constant numberGlobal = block.number; +uint constant prevrandaoGlobal = block.prevrandao; +uint constant timestampGlobal = block.timestamp; +uint constant gGlobal = gasleft(); +bytes constant dataGlobal = msg.data; +address constant senderGlobal = msg.sender; +bytes4 constant sigGlobal = msg.sig; +uint constant valueGlobal = msg.value; +uint constant gaspriceGlobal = tx.gasprice; +address constant originGlobal = tx.origin; + +contract A { + bytes32 constant blockh = blockhash(1); + bytes32 constant blobh = blobhash(1); + uint constant bf = block.basefee; + uint constant blobbf = block.blobbasefee; + uint constant chainId = block.chainid; + address constant coinbase = block.coinbase; + uint constant diff = block.difficulty; + uint constant gaslimit = block.gaslimit; + uint constant number = block.number; + uint constant prevrandao = block.prevrandao; + uint constant timestamp = block.timestamp; + uint constant g = gasleft(); + bytes constant data = msg.data; + address constant sender = msg.sender; + bytes4 constant sig = msg.sig; + uint constant value = msg.value; + uint constant gasprice = tx.gasprice; + address constant origin = tx.origin; +} +// ==== +// EVMVersion: >=cancun +// ---- +// TypeError 8349: (32-44): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (77-88): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (115-128): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (159-176): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (208-221): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (257-271): Initial value for constant variable has to be compile-time constant. +// Warning 8417: (300-316): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// TypeError 8349: (300-316): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (349-363): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (394-406): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (441-457): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (491-506): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (532-541): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (571-579): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (613-623): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (653-660): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (690-699): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (732-743): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (777-786): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (832-844): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (875-886): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (911-924): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (953-970): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1000-1013): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1047-1061): Initial value for constant variable has to be compile-time constant. +// Warning 8417: (1088-1104): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain. +// TypeError 8349: (1088-1104): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1135-1149): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1178-1190): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1223-1239): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1271-1286): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1310-1319): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1347-1355): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1387-1397): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1425-1432): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1460-1469): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1500-1511): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (1543-1552): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/constants/initialization/bytes_concat_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/bytes_concat_const_args.sol new file mode 100644 index 000000000..2d87ba56c --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/bytes_concat_const_args.sol @@ -0,0 +1,11 @@ +bytes constant aaaa = hex"aaaa"; + +bytes constant abcGlobal = bytes.concat(aaaa, hex"bbbb", hex"cccc"); + +contract A { + bytes public constant abc = bytes.concat(aaaa, hex"bbbb", hex"cccc"); + + bytes public constant abcCopy = abc; + bytes public constant abcGlobalCopy = abcGlobal; + bytes public constant abcabc = bytes.concat(abc, abcGlobal); +} diff --git a/test/libsolidity/syntaxTests/constants/initialization/bytes_concat_non_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/bytes_concat_non_const_args.sol new file mode 100644 index 000000000..225731c1f --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/bytes_concat_non_const_args.sol @@ -0,0 +1,17 @@ +contract A { + function getData() public view returns (bytes memory) { + return msg.data; + } + + function getDataPure() public pure returns (bytes memory) { + return hex"ffff"; + } + + bytes constant abData = bytes.concat(hex"aaaa", hex"bbbb", msg.data); + bytes constant abgetData = bytes.concat(hex"aaaa", hex"bbbb", getData()); + bytes constant abgetDataPure = bytes.concat(hex"aaaa", hex"bbbb", getDataPure()); +} +// ---- +// TypeError 8349: (230-274): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (307-352): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (389-438): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_1.sol b/test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_1.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/cyclic_dependency_1.sol rename to test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_1.sol diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol b/test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_2.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol rename to test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_2.sol diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_3.sol b/test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_3.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/cyclic_dependency_3.sol rename to test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_3.sol diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol b/test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_4.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol rename to test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_4.sol diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_5.sol b/test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_5.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/cyclic_dependency_5.sol rename to test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_5.sol diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_file_constants.sol b/test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_file.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/cyclic_dependency_file_constants.sol rename to test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_file.sol diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_file_and_library_constants.sol b/test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_file_and_library.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/cyclic_dependency_file_and_library_constants.sol rename to test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_file_and_library.sol diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_library_constants.sol b/test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_library.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/cyclic_dependency_library_constants.sol rename to test/libsolidity/syntaxTests/constants/initialization/constant_with_cyclic_dependency_library.sol diff --git a/test/libsolidity/syntaxTests/constants/division_by_zero.sol b/test/libsolidity/syntaxTests/constants/initialization/division_by_zero.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/division_by_zero.sol rename to test/libsolidity/syntaxTests/constants/initialization/division_by_zero.sol diff --git a/test/libsolidity/syntaxTests/constants/assign_constant_function_value.sol b/test/libsolidity/syntaxTests/constants/initialization/function_pointer_call.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/assign_constant_function_value.sol rename to test/libsolidity/syntaxTests/constants/initialization/function_pointer_call.sol diff --git a/test/libsolidity/syntaxTests/constants/initialization/math_builtin_opcode_based_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/math_builtin_opcode_based_const_args.sol new file mode 100644 index 000000000..aa13e02b4 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/math_builtin_opcode_based_const_args.sol @@ -0,0 +1,14 @@ +uint256 constant k = 7; +bytes constant data = hex"ffff"; + +uint256 constant amodGlobal = addmod(1, 8, k); +uint256 constant mmodGlobal = mulmod(1, 8, k); +bytes32 constant keccakGlobal = keccak256(hex"ffff"); +bytes32 constant keccakConstArgGlobal = keccak256(data); + +contract A { + uint256 constant amod = addmod(1, 8, k); + uint256 constant mmod = mulmod(1, 8, k); + bytes32 constant keccak = keccak256(hex"ffff"); + bytes32 constant keccakConstArg = keccak256(data); +} diff --git a/test/libsolidity/syntaxTests/constants/initialization/math_builtin_opcode_based_non_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/math_builtin_opcode_based_non_const_args.sol new file mode 100644 index 000000000..208437ab7 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/math_builtin_opcode_based_non_const_args.sol @@ -0,0 +1,12 @@ +contract A { + uint256 k = 7; + uint256 constant amod = addmod(1, 8, k); + uint256 constant mmod = mulmod(1, 8, k); + + bytes data = hex"ffff"; + bytes32 constant keccak = keccak256(data); +} +// ---- +// TypeError 8349: (60-75): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (105-120): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (181-196): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/constants/initialization/math_builtin_precompile_based_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/math_builtin_precompile_based_const_args.sol new file mode 100644 index 000000000..57626ec2f --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/math_builtin_precompile_based_const_args.sol @@ -0,0 +1,16 @@ +uint8 constant k = 1; +bytes constant data = hex"ffff"; + +bytes32 constant sGlobal = sha256(hex"ffff"); +bytes32 constant sConstArgGlobal = sha256(data); +address constant addrGlobal = ecrecover("1234", k, "0", abi.decode("", (bytes2))); +bytes20 constant ripemdGlobal = ripemd160(hex"ffff"); +bytes20 constant ripemdConstArgGlobal = ripemd160(data); + +contract A { + bytes32 constant s = sha256(hex"ffff"); + bytes32 constant sConstArg = sha256(data); + address constant addr = ecrecover("1234", k, "0", abi.decode("", (bytes2))); + bytes20 constant ripemd = ripemd160(hex"ffff"); + bytes20 constant ripemdConstArg = ripemd160(data); +} diff --git a/test/libsolidity/syntaxTests/constants/initialization/math_builtin_precompile_based_non_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/math_builtin_precompile_based_non_const_args.sol new file mode 100644 index 000000000..fef5ccc88 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/math_builtin_precompile_based_non_const_args.sol @@ -0,0 +1,10 @@ +contract A { + bytes data = hex"ffff"; + bytes32 constant sha = sha256(data); + bytes20 constant ripemd = ripemd160(data); + address constant addr = ecrecover("1234", 1, "0", abi.decode(data, (bytes2))); +} +// ---- +// TypeError 8349: (68-80): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (112-127): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (157-210): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/constants/mod_zero.sol b/test/libsolidity/syntaxTests/constants/initialization/modulo_by_zero.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/mod_zero.sol rename to test/libsolidity/syntaxTests/constants/initialization/modulo_by_zero.sol diff --git a/test/libsolidity/syntaxTests/constants/mulmod_zero.sol b/test/libsolidity/syntaxTests/constants/initialization/mulmod_by_zero.sol similarity index 100% rename from test/libsolidity/syntaxTests/constants/mulmod_zero.sol rename to test/libsolidity/syntaxTests/constants/initialization/mulmod_by_zero.sol diff --git a/test/libsolidity/syntaxTests/constants/initialization/string_concat_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/string_concat_const_args.sol new file mode 100644 index 000000000..bc676d101 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/string_concat_const_args.sol @@ -0,0 +1,9 @@ +string constant abcGlobal = string.concat("aaaa", "bbbb", "cccc"); + +contract A { + string public constant abc = string.concat("aaaa", "bbbb","cccc"); + + string public constant abcCopy = abc; + string public constant abcGlobalCopy = abcGlobal; + string public constant abcabc = string.concat(abc, abcGlobal); +} diff --git a/test/libsolidity/syntaxTests/constants/initialization/string_concat_non_const_args.sol b/test/libsolidity/syntaxTests/constants/initialization/string_concat_non_const_args.sol new file mode 100644 index 000000000..f8b4aa6e2 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/string_concat_non_const_args.sol @@ -0,0 +1,14 @@ +contract A { + string name = "name"; + + function getName() public view returns (string memory) { + return name; + } + + string public constant abName = string.concat("aaaa", "bbbb", name); + + string public constant abgetName = string.concat("aaaa", "bbbb",getName()); +} +// ---- +// TypeError 8349: (165-200): Initial value for constant variable has to be compile-time constant. +// TypeError 8349: (242-281): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/constants/initialization/type_info.sol b/test/libsolidity/syntaxTests/constants/initialization/type_info.sol new file mode 100644 index 000000000..51cfaa3a5 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/initialization/type_info.sol @@ -0,0 +1,23 @@ +string constant aNameGlobal = type(A).name; +bytes4 constant iNameGlobal = type(I).interfaceId; +uint256 constant minGlobal = type(uint256).min; +uint256 constant maxGlobal = type(uint256).max; +bytes constant creationCodeBGlobal = type(B).creationCode; +bytes constant runtimeCodeBGlobal = type(B).runtimeCode; + +contract B { +} + +interface I { + function hello() external pure; + function world(int) external pure; +} + +contract A { + string constant aName = type(A).name; + bytes4 constant iName = type(I).interfaceId; + uint256 constant min = type(uint256).min; + uint256 constant max = type(uint256).max; + bytes constant creationCodeB = type(B).creationCode; + bytes constant runtimeCodeB = type(B).runtimeCode; +} From a4bd1b760aef7e8deaec6c4303a36cf9fed5ac1c Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 17 Dec 2025 13:14:21 +0100 Subject: [PATCH 1053/1340] Add semantic test --- .../semanticTests/constants/assign_type_info.sol | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 test/libsolidity/semanticTests/constants/assign_type_info.sol diff --git a/test/libsolidity/semanticTests/constants/assign_type_info.sol b/test/libsolidity/semanticTests/constants/assign_type_info.sol new file mode 100644 index 000000000..0fca83d54 --- /dev/null +++ b/test/libsolidity/semanticTests/constants/assign_type_info.sol @@ -0,0 +1,13 @@ +contract A { +} + +contract B { + bytes constant creationCode = type(A).creationCode; + bytes constant runtimeCode = type(A).runtimeCode; + + function nonEmptyCode() public pure returns (bool) { + return creationCode.length > 0 && runtimeCode.length > 0; + } +} +// ---- +// nonEmptyCode() -> true From ba32d8b5ab93219ff343e7162d619c0e66f011f0 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 17 Dec 2025 13:14:50 +0100 Subject: [PATCH 1054/1340] Update tests. Change error message. --- .../storageLayoutSpecifier/layout_specified_by_bytes_concat.sol | 2 +- .../storageLayoutSpecifier/layout_specified_by_kecak256.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol index d341a5a76..77860af8e 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_bytes_concat.sol @@ -1,3 +1,3 @@ contract C layout at uint64(bytes8(bytes.concat("ABCD", "EFGH"))) {} // ---- -// TypeError 1139: (21-65): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1505: (21-65): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol index 539a59c11..0b35d60d8 100644 --- a/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/layout_specified_by_kecak256.sol @@ -1,3 +1,3 @@ contract C layout at uint(keccak256(bytes.concat("ABCD"))) {} // ---- -// TypeError 1139: (21-58): The base slot of the storage layout must be a compile-time constant expression. +// TypeError 1505: (21-58): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. From 91a49db7188cba31dc272726e57d17255ca837e4 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 17 Dec 2025 13:15:12 +0100 Subject: [PATCH 1055/1340] Update tests. Modify to avoid the no effect warning. --- .../array/concat/bytes_concat_valid_type_literal.sol | 4 ++-- .../concat/bytes_concat_wrong_type_empty_string_literal.sol | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/libsolidity/syntaxTests/array/concat/bytes_concat_valid_type_literal.sol b/test/libsolidity/syntaxTests/array/concat/bytes_concat_valid_type_literal.sol index f39e90396..ff003ca8a 100644 --- a/test/libsolidity/syntaxTests/array/concat/bytes_concat_valid_type_literal.sol +++ b/test/libsolidity/syntaxTests/array/concat/bytes_concat_valid_type_literal.sol @@ -1,6 +1,6 @@ contract C { - function f() public pure { - bytes.concat( + function f() public pure returns (bytes memory) { + return bytes.concat( hex"00", hex"aabbcc", unicode"abc", diff --git a/test/libsolidity/syntaxTests/array/concat/bytes_concat_wrong_type_empty_string_literal.sol b/test/libsolidity/syntaxTests/array/concat/bytes_concat_wrong_type_empty_string_literal.sol index afba249f8..a58cf9f3d 100644 --- a/test/libsolidity/syntaxTests/array/concat/bytes_concat_wrong_type_empty_string_literal.sol +++ b/test/libsolidity/syntaxTests/array/concat/bytes_concat_wrong_type_empty_string_literal.sol @@ -1,6 +1,6 @@ contract C { - function f() public pure { - bytes.concat(hex"", unicode"", ""); + function f() public pure returns (bytes memory) { + return bytes.concat(hex"", unicode"", ""); } } // ---- From 2c0acc50c4fac51e6d2ee3ea876061b7721ac663 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 17 Dec 2025 13:15:25 +0100 Subject: [PATCH 1056/1340] Update changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 27e1cb33a..26f28d21d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,7 @@ Compiler Features: Bugfixes: * Codegen: Fix internal compiler error when emitting events via module member access. * TypeChecker: Fix error and event selectors not being considered compile-time constant. +* TypeChecker: Fix `string.concat` and `bytes.concat` with constant arguments not being considered compile-time constant. ### 0.8.31 (2025-12-03) From eb6a45904a3e7e3c7e35eff7cc5d813658848034 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 17 Dec 2025 14:19:37 +0100 Subject: [PATCH 1057/1340] Add sanity check in the end of `TypeChecker::visit(MemberAccess const& _memberAccess)` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- libsolidity/analysis/TypeChecker.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 8556487ff..ab8f00a30 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3409,6 +3409,16 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if (!annotation.isPure.set()) annotation.isPure = false; + if ( + auto const* funcType = dynamic_cast(annotation.type); + funcType && + funcType->kind() != FunctionType::Kind::Declaration && + funcType->kind() != FunctionType::Kind::Internal && + funcType->kind() != FunctionType::Kind::Error && + funcType->kind() != FunctionType::Kind::Event + ) + solAssert(funcType->isPure() == *annotation.isPure); + return false; } From b28145c60e490a7504ca1c2e4edac16f5ec2e5e7 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Thu, 11 Dec 2025 10:10:47 -0300 Subject: [PATCH 1058/1340] Update docs about solc-bin.ethereum.org deprecation in favor of binaries.soliditylang.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- docs/installing-solidity.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 01a2f3820..97a754eaa 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -270,10 +270,11 @@ This means that: if you want to be sure whether you are downloading a wasm or an asm.js binary. - Use ``list.json`` instead of ``list.js`` and ``list.txt``. The JSON list format contains all the information from the old ones and more. - - Use https://binaries.soliditylang.org instead of https://solc-bin.ethereum.org. To keep things - simple we moved almost everything related to the compiler under the new ``soliditylang.org`` - domain and this applies to ``solc-bin`` too. While the new domain is recommended, the old one - is still fully supported and guaranteed to point at the same location. + +.. warning:: + - The solc-bin.ethereum.org domain is no longer supported. Going forward, + we recommend any tools which are still using it as the source of Solidity binaries + to switch to binaries.soliditylang.org. .. warning:: From 1c61064d0851acc5dc565e6bac10bf327ed79a2d Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 18 Dec 2025 06:02:37 +0100 Subject: [PATCH 1059/1340] Fix changelog for 0.8.32 --- Changelog.md | 5 +---- docs/bugs_by_version.json | 4 ++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index 26f28d21d..ad0916815 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,11 +1,8 @@ -### 0.8.32 (unreleased) +### 0.8.32 (2025-12-18) Important Bugfixes: * Code Generator: Fix a bug in clearing/copying of arrays that straddle the end of storage, potentially resulting in assignment/initialization/`delete`/`push()`/`pop()` skipping some or all of the intended storage writes. -Language Features: - -Compiler Features: Bugfixes: * Codegen: Fix internal compiler error when emitting events via module member access. diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 94e814892..2ecc3c235 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -2049,6 +2049,10 @@ ], "released": "2025-12-03" }, + "0.8.32": { + "bugs": [], + "released": "2025-12-18" + }, "0.8.4": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", From 1ebf887357df5afc6e31ff19825eb9f4784a56a9 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Wed, 17 Dec 2025 17:28:00 -0300 Subject: [PATCH 1060/1340] set version to 0.8.33 --- CMakeLists.txt | 2 +- Changelog.md | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f4d67e243..5792563eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.32") +set(PROJECT_VERSION "0.8.33") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index ad0916815..9f533332e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,12 @@ +### 0.8.33 (unreleased) + +Language Features: + +Compiler Features: + +Bugfixes: + + ### 0.8.32 (2025-12-18) Important Bugfixes: From c6aecabaddc313dd81d28bc2a4e47434d4c1b95f Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 18 Dec 2025 14:51:27 +0100 Subject: [PATCH 1061/1340] Remove the sanity check. --- libsolidity/analysis/TypeChecker.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index ab8f00a30..8556487ff 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3409,16 +3409,6 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if (!annotation.isPure.set()) annotation.isPure = false; - if ( - auto const* funcType = dynamic_cast(annotation.type); - funcType && - funcType->kind() != FunctionType::Kind::Declaration && - funcType->kind() != FunctionType::Kind::Internal && - funcType->kind() != FunctionType::Kind::Error && - funcType->kind() != FunctionType::Kind::Event - ) - solAssert(funcType->isPure() == *annotation.isPure); - return false; } From 27af4dcfb9247707efe002d0ce6aac9185fdbd72 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 18 Dec 2025 14:57:57 +0100 Subject: [PATCH 1062/1340] Add tests. --- .../syntaxTests/constants/access_via_getter.sol | 8 ++++++++ .../syntaxTests/immutable/access_via_getter.sol | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 test/libsolidity/syntaxTests/constants/access_via_getter.sol create mode 100644 test/libsolidity/syntaxTests/immutable/access_via_getter.sol diff --git a/test/libsolidity/syntaxTests/constants/access_via_getter.sol b/test/libsolidity/syntaxTests/constants/access_via_getter.sol new file mode 100644 index 000000000..686c5a039 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/access_via_getter.sol @@ -0,0 +1,8 @@ +contract Counter { + uint256 public constant MIN_LIQUIDITY = 1000; + + function run() view public { + this.MIN_LIQUIDITY(); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/immutable/access_via_getter.sol b/test/libsolidity/syntaxTests/immutable/access_via_getter.sol new file mode 100644 index 000000000..6ce9e42c4 --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/access_via_getter.sol @@ -0,0 +1,8 @@ +contract Counter { + uint256 public immutable MIN_LIQUIDITY = 1000; + + function run() view public { + this.MIN_LIQUIDITY(); + } +} +// ---- From 07bf6e13a88a6f831b2b0055214aa8bc6cf75f09 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 18 Dec 2025 15:04:37 +0100 Subject: [PATCH 1063/1340] Update changelog. --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 9f533332e..61bde4e25 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: Bugfixes: +* TypeChecker: Fix internal error when accessing getters of constant variables. ### 0.8.32 (2025-12-18) From c8ebb1104691ddcb463bcdbc5f9a5fa743de33ab Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 18 Dec 2025 17:36:49 +0100 Subject: [PATCH 1064/1340] Sort changelog and date for 0.8.33 --- Changelog.md | 6 +----- docs/bugs_by_version.json | 4 ++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index 61bde4e25..cb78695bc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,8 +1,4 @@ -### 0.8.33 (unreleased) - -Language Features: - -Compiler Features: +### 0.8.33 (2025-12-18) Bugfixes: * TypeChecker: Fix internal error when accessing getters of constant variables. diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 2ecc3c235..8a4d2fe23 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -2053,6 +2053,10 @@ "bugs": [], "released": "2025-12-18" }, + "0.8.33": { + "bugs": [], + "released": "2025-12-18" + }, "0.8.4": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", From a50affba1afa11cbd0b4a656dc5a753fc5be0137 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 18 Dec 2025 12:36:09 -0300 Subject: [PATCH 1065/1340] Set version to 0.8.34 --- CMakeLists.txt | 2 +- Changelog.md | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5792563eb..82afc5b67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.33") +set(PROJECT_VERSION "0.8.34") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index cb78695bc..655e66e54 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,12 @@ +### 0.8.34 (unreleased) + +Language Features: + +Compiler Features: + +Bugfixes: + + ### 0.8.33 (2025-12-18) Bugfixes: From 779f590beb82d11e39dcec821507fb4d4b660c60 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Thu, 18 Dec 2025 00:19:12 -0300 Subject: [PATCH 1066/1340] Add Constantinople EVM version requirement to long byte array cleanup test due to the use of shl --- .../array/long_byte_array_cleanup_after_overwrite_with_long.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol b/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol index edb00809b..c796881c4 100644 --- a/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol +++ b/test/libsolidity/semanticTests/array/long_byte_array_cleanup_after_overwrite_with_long.sol @@ -82,6 +82,8 @@ contract C { return result; } } +// ==== +// EVMVersion: >=constantinople // ---- // arrayLength() ->0 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff From 7e371ddc0561033ccca7ffa1cee8f29ffee12ab5 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Sun, 21 Dec 2025 17:06:57 -0300 Subject: [PATCH 1067/1340] Enables pipefail globally so parsing errors fail CI instead of being silently ignored --- scripts/externalTests/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index 0465a4fec..c6f5ef6d3 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -18,7 +18,7 @@ # # (c) 2019 solidity contributors. #------------------------------------------------------------------------------ -set -e +set -eo pipefail # Requires $REPO_ROOT to be defined and "${REPO_ROOT}/scripts/common.sh" to be included before. From e882f5343565183a3b290e60df2f9b7ce907d6b4 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Sun, 21 Dec 2025 17:07:15 -0300 Subject: [PATCH 1068/1340] Fix external tests for hardhat-gas-reporter v2 compatibility --- scripts/externalTests/common.sh | 4 ++-- scripts/externalTests/parse_eth_gas_report.py | 17 +++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/scripts/externalTests/common.sh b/scripts/externalTests/common.sh index c6f5ef6d3..7e480343a 100644 --- a/scripts/externalTests/common.sh +++ b/scripts/externalTests/common.sh @@ -434,9 +434,9 @@ function eth_gas_reporter_settings echo " enabled: true," echo " gasPrice: 1," # Gas price does not matter to us at all. Set to whatever to avoid API call. echo " noColors: true," - echo " showTimeSpent: false," # We're not interested in test timing - echo " onlyCalledMethods: true," # Exclude entries with no gas for shorter report + echo " showUncalledMethods: false," # Exclude entries with no gas for shorter report echo " showMethodSig: true," # Should make diffs more stable if there are overloaded functions + echo " reportFormat: 'legacy'," # Use v1.x format for compatibility with parse_eth_gas_report.py echo " outputFile: \"$(gas_report_path "$preset")\"" echo "}" } diff --git a/scripts/externalTests/parse_eth_gas_report.py b/scripts/externalTests/parse_eth_gas_report.py index ea8cbba66..d7dbe45fa 100755 --- a/scripts/externalTests/parse_eth_gas_report.py +++ b/scripts/externalTests/parse_eth_gas_report.py @@ -10,8 +10,8 @@ REPORT_HEADER_REGEX = re.compile(r''' ^[|\s]+ Solc[ ]version:\s*(?P[\w\d.]+) [|\s]+ Optimizer[ ]enabled:\s*(?P[\w]+) - [|\s]+ Runs:\s*(?P[\d]+) - [|\s]+ Block[ ]limit:\s*(?P[\d]+)\s*gas + [|\s]+ Runs:\s*(?P[\d,]+) + [|\s]+ Block[ ]limit:\s*(?P[\d,]+)\s*gas [|\s]+$ ''', re.VERBOSE) METHOD_HEADER_REGEX = re.compile(r'^[|\s]+Methods[|\s]+$') @@ -122,10 +122,11 @@ def parse_bool(input_string: str) -> bool: def parse_optional_int(input_string: str, default: Optional[int] = None) -> Optional[int]: - if input_string.strip() == '-': + stripped = input_string.strip().replace(',', '') + if stripped == '-': return default - return int(input_string) + return int(stripped) def parse_report_header(line: str) -> Optional[dict]: @@ -136,8 +137,8 @@ def parse_report_header(line: str) -> Optional[dict]: return { 'solc_version': match.group('solc_version'), 'optimize': parse_bool(match.group('optimize')), - 'runs': int(match.group('runs')), - 'block_limit': int(match.group('block_limit')), + 'runs': int(match.group('runs').replace(',', '')), + 'block_limit': int(match.group('block_limit').replace(',', '')), } @@ -147,7 +148,7 @@ def parse_method_row(line: str, line_number: int) -> Optional[Tuple[str, str, Me raise ReportParsingError("Expected a table row with method details.", line, line_number) avg_gas = parse_optional_int(match['avg']) - call_count = int(match['call_count']) + call_count = int(match['call_count'].strip().replace(',', '')) if avg_gas is None and call_count == 0: # No calls, no gas values. Uninteresting. Skip the row. @@ -174,7 +175,7 @@ def parse_deployment_row(line: str, line_number: int) -> Tuple[str, int, int, in match['contract'].strip(), parse_optional_int(match['min'].strip()), parse_optional_int(match['max'].strip()), - int(match['avg'].strip()), + int(match['avg'].strip().replace(',', '')), ) From 1cd9bc2ff5f1d2a12c01980d5a9cb9bf322f6370 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Mon, 22 Dec 2025 10:43:52 -0300 Subject: [PATCH 1069/1340] Bump hardhat-gas-reporter to v2 in gp2 external test --- test/externalTests/gp2.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/externalTests/gp2.sh b/test/externalTests/gp2.sh index cc8b56b66..78f21e8e2 100755 --- a/test/externalTests/gp2.sh +++ b/test/externalTests/gp2.sh @@ -68,7 +68,8 @@ function gp2_test yarn # Hardhat 3.0+ breaks the test suite # v2.27.1 is the last v2 Hardhat (introduces Osaka support) - yarn add hardhat@2.27.1 + # hardhat-gas-reporter v2 is required for compatibility with our injected gas reporter settings + yarn add hardhat@2.27.1 hardhat-gas-reporter@^2 # Ignore bench directory which fails to compile with current hardhat and ethers versions. # bench/trace/gas.ts:123:19 - error TS2339: Property 'equals' does not exist on type 'Uint8Array'. From d2711509d64320129b7b8fd0535fde4f28cf0e85 Mon Sep 17 00:00:00 2001 From: Manuel Wedler Date: Wed, 17 Dec 2025 09:48:09 +0100 Subject: [PATCH 1070/1340] ci: Replace `t_ubu_soltest_all` with `t_ubu_soltest` --- .circleci/config.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3cab7fbad..12fab84cd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1292,6 +1292,18 @@ jobs: destination: docs-html - matrix_notify_failure_unless_pr + t_ubu_soltest: &t_ubu_soltest + <<: *base_ubuntu2404_large + parallelism: 20 + environment: + <<: *base_ubuntu2404_large_env + EVM: << pipeline.parameters.evm-version >> + EOF_VERSION: 0 + OPTIMIZE: 0 + SOLTEST_FLAGS: --no-smt + steps: + - soltest + t_ubu_soltest_all: &t_ubu_soltest_all <<: *base_ubuntu2404_large parallelism: 50 @@ -2038,7 +2050,7 @@ workflows: - t_ubu_cli: *requires_b_ubu - t_ubu_arm_cli: *requires_b_ubu_static_arm - t_ubu_locale: *requires_b_ubu - - t_ubu_soltest_all: *requires_b_ubu + - t_ubu_soltest: *requires_b_ubu - t_ubu_arm_soltest: *requires_b_ubu_static_arm - b_ubu_clang: *requires_nothing - t_ubu_clang_soltest: *requires_b_ubu_clang From 78dd4d15d0ebbc53246e4460d305cceaa5e74727 Mon Sep 17 00:00:00 2001 From: Manuel Wedler Date: Mon, 22 Dec 2025 09:21:13 +0100 Subject: [PATCH 1071/1340] ci: Remove `t_ubu_soltest_all` job --- .circleci/config.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 12fab84cd..557b08f8f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1304,12 +1304,6 @@ jobs: steps: - soltest - t_ubu_soltest_all: &t_ubu_soltest_all - <<: *base_ubuntu2404_large - parallelism: 50 - steps: - - soltest_all - t_ubu_arm_soltest: &t_ubu_arm_soltest <<: *base_ubuntu2404_arm_medium parallelism: 20 @@ -1384,9 +1378,10 @@ jobs: - soltest t_ubu_force_release_soltest_all: &t_ubu_force_release_soltest_all - # NOTE: This definition is identical to t_ubu_soltest_all but in the workflow we make it depend on - # a different job (b_ubu_force_release) so the workspace it attaches contains a different executable. - <<: *t_ubu_soltest_all + <<: *base_ubuntu2404_large + parallelism: 50 + steps: + - soltest_all t_ubu_cli: &t_ubu_cli <<: *base_ubuntu2404_small From 41b20a7e64d56ccb8c0ad54062967d99bee613e6 Mon Sep 17 00:00:00 2001 From: Manuel Wedler Date: Mon, 22 Dec 2025 09:24:32 +0100 Subject: [PATCH 1072/1340] ci: Remove `--no-smt` flag from `t_ubu_soltest` job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Śliwak --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 557b08f8f..2276350e0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1300,7 +1300,6 @@ jobs: EVM: << pipeline.parameters.evm-version >> EOF_VERSION: 0 OPTIMIZE: 0 - SOLTEST_FLAGS: --no-smt steps: - soltest From 2b7dedf518d5221d566ca73d3322646267a2546c Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Tue, 6 Jan 2026 09:08:48 +0100 Subject: [PATCH 1073/1340] Add ccache to buildpack-deps images --- .circleci/osx_install_dependencies.sh | 1 + scripts/ci/docker_upgrade.sh | 1 + scripts/docker/buildpack-deps/Dockerfile.emscripten | 3 ++- scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz | 3 ++- scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 | 3 ++- scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm | 3 ++- scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang | 3 ++- 7 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index dd5a8397b..0666211b7 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -51,6 +51,7 @@ then brew update brew upgrade brew install cmake + brew install ccache brew install wget brew install coreutils brew install diffutils diff --git a/scripts/ci/docker_upgrade.sh b/scripts/ci/docker_upgrade.sh index c2077239a..533982a37 100755 --- a/scripts/ci/docker_upgrade.sh +++ b/scripts/ci/docker_upgrade.sh @@ -55,6 +55,7 @@ docker run \ --rm \ --volume "${PWD}:/project" \ -u "$(id -u "${USER}"):$(id -g "${USER}")" \ + -e CCACHE_DIR=/tmp/ccache \ "${IMAGE_NAME}" \ bash -c "/project/scripts/ci/${IMAGE_NAME}_test_${IMAGE_VARIANT}.sh" diff --git a/scripts/docker/buildpack-deps/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten index 007729d41..67c9ec61a 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -33,7 +33,7 @@ # Using $(em-config CACHE)/sysroot/usr seems to work, though, and still has cmake find the # dependencies automatically. FROM emscripten/emsdk:3.1.19 AS base -LABEL version="21" +LABEL version="22" ADD emscripten.jam /usr/src RUN <<-EOF @@ -41,6 +41,7 @@ RUN <<-EOF apt-get update apt-get install -qqy --no-install-recommends \ lsof \ + ccache \ lz4 \ python3 \ python3-pip \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz index 5a96e6889..08c091cd7 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2021 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-builder AS base -LABEL version="12" +LABEL version="13" ARG DEBIAN_FRONTEND=noninteractive @@ -31,6 +31,7 @@ RUN apt-get update; \ automake \ bison \ build-essential \ + ccache \ curl \ git \ jq \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 index 9cf381f76..8f5c1aec8 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404 @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="6" +LABEL version="7" ARG DEBIAN_FRONTEND=noninteractive @@ -39,6 +39,7 @@ RUN set -ex; \ apt-get install -qqy --no-install-recommends \ build-essential \ cmake \ + ccache \ jq \ libboost-filesystem-dev \ libboost-program-options-dev \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm index 663928220..cc58ed679 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm @@ -22,7 +22,7 @@ # (c) 2016-2025 solidity contributors. #------------------------------------------------------------------------------ FROM --platform=linux/arm64 buildpack-deps:noble AS base -LABEL version="2" +LABEL version="3" ARG DEBIAN_FRONTEND=noninteractive @@ -40,6 +40,7 @@ RUN <<-EOF apt-get install --quiet=2 --no-install-recommends \ build-essential \ cmake \ + ccache \ jq \ libboost-filesystem-dev \ libboost-program-options-dev \ diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang index aec6fe6e2..9a9928514 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang @@ -22,7 +22,7 @@ # (c) 2016-2024 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:noble AS base -LABEL version="7" +LABEL version="8" ARG DEBIAN_FRONTEND=noninteractive @@ -40,6 +40,7 @@ RUN set -ex; \ build-essential \ clang \ cmake \ + ccache \ jq \ libboost-filesystem-dev \ libboost-program-options-dev \ From 009ea626be2df0724e5df876f2cc831e40c72651 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 6 Jan 2026 13:29:43 +0100 Subject: [PATCH 1074/1340] CI: Batched antlr check --- scripts/AntlrBatchTestRig.java | 104 +++++++++++++++++++++++++++++ scripts/test_antlr_grammar.sh | 118 ++++++++++++++------------------- 2 files changed, 155 insertions(+), 67 deletions(-) create mode 100644 scripts/AntlrBatchTestRig.java diff --git a/scripts/AntlrBatchTestRig.java b/scripts/AntlrBatchTestRig.java new file mode 100644 index 000000000..91a924c33 --- /dev/null +++ b/scripts/AntlrBatchTestRig.java @@ -0,0 +1,104 @@ +import org.antlr.v4.runtime.*; +import java.io.*; +import java.nio.file.*; + +public class AntlrBatchTestRig { + public static void main(String[] args) throws Exception { + if (args.length < 1) { + System.err.println("Usage: AntlrBatchTestRig [file2] ..."); + System.exit(1); + } + + int exitCode = 0; + for (String filePath: args) { + try { + if (!testFile(filePath)) + exitCode = 1; + } catch (Exception e) { + System.err.println("ERROR:" + filePath + ":" + e.getMessage()); + exitCode = 1; + } + } + System.exit(exitCode); + } + + private static boolean testFile(String filePath) throws Exception { + // Detect mode based on file extension + String mode = filePath.endsWith(".yul") ? "yul" : "sol"; + String content = new String(Files.readAllBytes(Paths.get(filePath))); + + // Check if file expects parser error + boolean expectsError = content.contains("// ParserError"); + + CharStream input; + if (mode.equals("sol")) { + // Remove ExternalSource lines for Solidity files + content = content.replaceAll("(?m)^==== ExternalSource:.*$", ""); + input = CharStreams.fromString(content); + } else { + // Wrap Yul in assembly statement + input = CharStreams.fromString("assembly " + content); + } + + SolidityLexer lexer = new SolidityLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + SolidityParser parser = new SolidityParser(tokens); + + // Remove default error listeners and add custom one + parser.removeErrorListeners(); + lexer.removeErrorListeners(); + + ErrorCollector errorCollector = new ErrorCollector(); + parser.addErrorListener(errorCollector); + lexer.addErrorListener(errorCollector); + + // Parse based on mode + if (mode.equals("sol")) { + parser.sourceUnit(); + } else { + parser.assemblyStatement(); + } + + boolean hasErrors = errorCollector.hasErrors(); + + // Output result + if (expectsError) { + if (hasErrors) { + System.out.println("PASS:" + filePath + ":FAILED_AS_EXPECTED"); + } else { + System.out.println("FAIL:" + filePath + ":SUCCEEDED_DESPITE_PARSER_ERROR"); + return false; + } + } else { + if (!hasErrors) { + System.out.println("PASS:" + filePath + ":OK"); + } else { + System.out.println("FAIL:" + filePath + ":" + errorCollector.getErrors()); + return false; + } + } + return true; + } + + static class ErrorCollector extends BaseErrorListener { + private StringBuilder errors = new StringBuilder(); + private boolean hasErrors = false; + + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, + int line, int charPositionInLine, + String msg, RecognitionException e) { + hasErrors = true; + errors.append("line ").append(line).append(":").append(charPositionInLine) + .append(" ").append(msg).append("\n"); + } + + public boolean hasErrors() { + return hasErrors; + } + + public String getErrors() { + return errors.toString(); + } + } +} diff --git a/scripts/test_antlr_grammar.sh b/scripts/test_antlr_grammar.sh index 02e9a634f..c8e008c06 100755 --- a/scripts/test_antlr_grammar.sh +++ b/scripts/test_antlr_grammar.sh @@ -10,6 +10,7 @@ ROOT_DIR=$(${READLINK} -f "$(dirname "$0")"/..) WORKDIR="${ROOT_DIR}/build/antlr" ANTLR_JAR="${ROOT_DIR}/build/deps/antlr4.jar" ANTLR_JAR_URI="https://www.antlr.org/download/antlr-4.8-complete.jar" +BATCH_SIZE=100 # Process 100 files per JVM invocation SGR_RESET="\033[0m" SGR_BOLD="\033[1m" @@ -17,9 +18,6 @@ SGR_GREEN="\033[32m" SGR_RED="\033[31m" SGR_BLUE="\033[34m" -vt_cursor_up() { echo -ne "\033[A"; } -vt_cursor_begin_of_line() { echo -ne "\r"; } - function download_antlr4 { if [[ ! -e "$ANTLR_JAR" ]] @@ -47,61 +45,10 @@ java -jar "${ANTLR_JAR}" SolidityParser.g4 SolidityLexer.g4 -o "${WORKDIR}/src/" # Compile lexer/parser sources javac -classpath "${ANTLR_JAR}" "${WORKDIR}/src/"*.java -d "${WORKDIR}/target/" -) -# Run tests -failed_count=0 -function test_file -{ - local SOL_FILE - SOL_FILE="$(${READLINK} -m "${1}")" - local cur=${2} - local max=${3} - local solOrYul=${4} - - echo -e "${SGR_BLUE}[${cur}/${max}] Testing ${SOL_FILE}${SGR_RESET} ..." - local output - if [[ "${solOrYul}" == "sol" ]]; then - output=$( - grep -v "^==== ExternalSource:" "${SOL_FILE}" | java \ - -classpath "${ANTLR_JAR}:${WORKDIR}/target/" \ - "org.antlr.v4.gui.TestRig" \ - Solidity \ - sourceUnit 2>&1 - ) - else - output=$( - echo "assembly $(cat "${SOL_FILE}")" | java \ - -classpath "${ANTLR_JAR}:${WORKDIR}/target/" \ - "org.antlr.v4.gui.TestRig" \ - Solidity \ - assemblyStatement 2>&1 - ) - fi - vt_cursor_up - vt_cursor_begin_of_line - if grep -qE "^\/\/ ParserError" "${SOL_FILE}"; then - if [[ "${output}" != "" ]] - then - echo -e "${SGR_BLUE}[${cur}/${max}] Testing ${SOL_FILE}${SGR_RESET} ${SGR_BOLD}${SGR_GREEN}FAILED AS EXPECTED${SGR_RESET}" - else - echo -e "${SGR_BLUE}[${cur}/${max}] Testing ${SOL_FILE}${SGR_RESET} ${SGR_BOLD}${SGR_RED}SUCCEEDED DESPITE PARSER ERROR${SGR_RESET}" - echo "${output}" - failed_count=$((failed_count + 1)) - exit 1 - fi - else - if [[ "${output}" == "" ]] - then - echo -e "${SGR_BLUE}[${cur}/${max}] Testing ${SOL_FILE}${SGR_RESET} ${SGR_BOLD}${SGR_GREEN}OK${SGR_RESET}" - else - echo -e "${SGR_BLUE}[${cur}/${max}] Testing ${SOL_FILE}${SGR_RESET} ${SGR_BOLD}${SGR_RED}FAILED${SGR_RESET}" - echo "${output}" - failed_count=$((failed_count + 1)) - exit 1 - fi - fi -} +# Compile AntlrBatchTestRig +javac -classpath "${ANTLR_JAR}:${WORKDIR}/target/" "${ROOT_DIR}/scripts/AntlrBatchTestRig.java" -d "${WORKDIR}/target/" +) # we only want to use files that do not contain excluded parser errors, analysis errors or multi-source files. SOL_FILES=() @@ -154,17 +101,54 @@ done < <( "${ROOT_DIR}/test/libyul/yulOptimizerTests" ) -num_tests=$((${#SOL_FILES[*]} + ${#YUL_FILES[*]})) +# Combine all files into one array +ALL_FILES=("${SOL_FILES[@]}" "${YUL_FILES[@]}") +num_tests=${#ALL_FILES[@]} +failed_count=0 test_count=0 -for SOL_FILE in "${SOL_FILES[@]}" -do - test_count=$((test_count + 1)) - test_file "${SOL_FILE}" ${test_count} $num_tests "sol" -done -for YUL_FILE in "${YUL_FILES[@]}" -do - test_count=$((test_count + 1)) - test_file "${YUL_FILE}" ${test_count} $num_tests "yul" + +echo "Testing $num_tests files..." + +# Process all files in batches +for ((i=0; i<${#ALL_FILES[@]}; i+=BATCH_SIZE)); do + batch=("${ALL_FILES[@]:i:BATCH_SIZE}") + batch_size=${#batch[@]} + + echo "Processing batch $((i/BATCH_SIZE + 1)) (${batch_size} files)..." + + # Run batch + output=$(java -classpath "${ANTLR_JAR}:${WORKDIR}/target/" AntlrBatchTestRig "${batch[@]}" 2>&1) || true + + # Parse output + while IFS= read -r line; do + if [[ -z "$line" ]]; then + continue + fi + + test_count=$((test_count + 1)) + + if [[ "$line" =~ ^PASS:(.+):(.*) ]]; then + file="${BASH_REMATCH[1]}" + status="${BASH_REMATCH[2]}" + if [[ "$status" == "FAILED_AS_EXPECTED" ]]; then + echo -e "${SGR_BLUE}[${test_count}/${num_tests}] ${file}${SGR_RESET} ${SGR_BOLD}${SGR_GREEN}FAILED AS EXPECTED${SGR_RESET}" + else + echo -e "${SGR_BLUE}[${test_count}/${num_tests}] ${file}${SGR_RESET} ${SGR_BOLD}${SGR_GREEN}OK${SGR_RESET}" + fi + elif [[ "$line" =~ ^FAIL:(.+):(.*) ]]; then + file="${BASH_REMATCH[1]}" + error="${BASH_REMATCH[2]}" + echo -e "${SGR_BLUE}[${test_count}/${num_tests}] ${file}${SGR_RESET} ${SGR_BOLD}${SGR_RED}FAILED${SGR_RESET}" + echo "$error" + failed_count=$((failed_count + 1)) + elif [[ "$line" =~ ^ERROR:(.+):(.*) ]]; then + file="${BASH_REMATCH[1]}" + error="${BASH_REMATCH[2]}" + echo -e "${SGR_BLUE}[${test_count}/${num_tests}] ${file}${SGR_RESET} ${SGR_BOLD}${SGR_RED}ERROR${SGR_RESET}" + echo "$error" + failed_count=$((failed_count + 1)) + fi + done <<< "$output" done echo "Summary: ${failed_count} of $num_tests sources failed." From 98af07f1e46cff0eeadd134caf4f13f2bd31aed7 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Fri, 5 Sep 2025 19:03:33 +0200 Subject: [PATCH 1075/1340] Add Slippy to the list of Solidity tools --- docs/resources.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/resources.rst b/docs/resources.rst index 3ba0620f9..52df87fdd 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -133,6 +133,9 @@ Solidity Tools * `Scaffold-ETH 2 `_ Forkable Ethereum development stack focused on fast product iterations. +* `Slippy `_ + A simple and powerful linter for Solidity. + * `sol2uml `_ Unified Modeling Language (UML) class diagram generator for Solidity contracts. From fb900032cc341b3bd0aaad032232ea598741b778 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Fri, 19 Dec 2025 10:53:12 +0000 Subject: [PATCH 1076/1340] Add 'slippy' to codespell's whitelist --- scripts/codespell_whitelist.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/codespell_whitelist.txt b/scripts/codespell_whitelist.txt index 7bcbf6ad1..e3a45b947 100644 --- a/scripts/codespell_whitelist.txt +++ b/scripts/codespell_whitelist.txt @@ -2,3 +2,4 @@ nd compilability keypair wast +slippy From 1d6e22d2f03873a8333ebfc26d395f22b917170b Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Wed, 7 Jan 2026 10:55:07 +0100 Subject: [PATCH 1077/1340] Speed up CI builds with ccache (seeded from develop) --- .circleci/config.yml | 210 +++++++++++++++++++++++--- .circleci/osx_install_dependencies.sh | 1 + scripts/ci/build.sh | 16 +- scripts/ci/build_emscripten.sh | 12 ++ scripts/ci/build_ossfuzz.sh | 17 ++- scripts/ci/build_win.sh | 26 +++- scripts/install_deps.ps1 | 11 ++ 7 files changed, 265 insertions(+), 28 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2276350e0..1c141d647 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,25 +13,25 @@ parameters: default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:1f387a77be889f65a2a25986a5c5eccc88cec23fabe6aeaf351790751145c81e" ubuntu-2404-docker-image: type: string - # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404-6 - default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:c0412c53e59ce0c96bde4c08e7332ea12e4cadba9bbac829621947897fa21272" + # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404-7 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:e52bd8fbb38908f203c6866e39562548faf26e5b7a5174f9860b44aae2b8f0cd" ubuntu-2404-arm-docker-image: type: string - # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.arm-2 - default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:27b03c1c4688e5d69b10e0539460346a3dee3b10b0e04fb406b9707c6f0dd95e" + # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.arm-3 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:1e6dbf9a9173f2645449281a1e11918a95ca6dc04e59aa9d70824cffc44697ed" ubuntu-2404-clang-docker-image: type: string - # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.clang-7 - default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:7466ed23590cf14e60da884894723bcdab064742f017dcfcce015999b4f9143b" + # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.clang-8 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:e283c8ec6a59c76565c89b856d8019af2fa5beb96f27d3064fc4dda42bf3524d" ubuntu-clang-ossfuzz-docker-image: type: string - # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu.clang.ossfuzz-12 - default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:c7088af5082bf764244a6251ecf3dd29d280d2cd2cd071f011f7f32e0326f426" + # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu.clang.ossfuzz-13 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:2acb5d6f254ece25a96096f26960b5fe114eb86ceca92312cd20d59c096bf6e4" emscripten-docker-image: type: string # NOTE: Please remember to update the `scripts/build_emscripten.sh` whenever the hash of this image changes. - # ghcr.io/argotorg/solidity-buildpack-deps:emscripten-21 - default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:fc53d68a4680ffa7d5f70164e13a903478964f15bcc07434d74833a05f4fbc19" + # ghcr.io/argotorg/solidity-buildpack-deps:emscripten-22 + default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:b9c953144d82cca5553f65626bc43b8af456dbc8966f8732ff9522f33ca8d722" evm-version: type: string default: osaka @@ -208,15 +208,98 @@ commands: run_build: steps: - - run: - name: Build - command: scripts/ci/build.sh + # TODO: remove the line below + # Before merging this PR we need to use an alternative develop branch to test the functionality, `ci-ccache` + + # On `ci-ccache` and `breaking` we intentionally do NOT restore any ccache, so every run starts from scratch. + # Tags always skip ccache. Other branches restore the most recent cache produced on `ci-ccache`. + - when: + condition: + and: + - equal: ["", << pipeline.git.tag >>] + - not: + or: + - equal: ["ci-ccache", << pipeline.git.branch >>] + - equal: ["breaking", << pipeline.git.branch >>] + steps: + - restore_cache: + keys: + # Reuse cache produced on ci-ccache (prefix match; restores the most recent). + - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- + # WARNING! If you edit anything between here and save_cache, remember to bump version or invalidate the cache manually. + - when: + condition: + and: + - equal: ["", << pipeline.git.tag >>] + steps: + - run: + name: Build (ccache) + command: CCACHE_ENABLED=1 scripts/ci/build.sh + - when: + condition: + or: + - not: + equal: ["", << pipeline.git.tag >>] + steps: + - run: + name: Build (no ccache) + command: scripts/ci/build.sh + + # On `ci-ccache` we always generate a fresh cache by never restoring and by saving under a unique key. + - when: + condition: + equal: ["ci-ccache", << pipeline.git.branch >>] + steps: + - save_cache: + key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache-{{ .Revision }} + paths: + - ~/.ccache run_build_ossfuzz: steps: - - run: - name: Build_ossfuzz - command: scripts/ci/build_ossfuzz.sh + # On `ci-ccache` and `breaking` we intentionally do NOT restore any ccache, so every run starts from scratch. + # Tags always skip ccache. Other branches restore the most recent cache produced on `ci-ccache`. + - when: + condition: + and: + - equal: ["", << pipeline.git.tag >>] + - not: + or: + - equal: ["ci-ccache", << pipeline.git.branch >>] + - equal: ["breaking", << pipeline.git.branch >>] + steps: + - restore_cache: + keys: + # Reuse cache produced on ci-ccache (prefix match; restores the most recent). + - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- + # WARNING! If you edit anything between here and save_cache, remember to bump version or invalidate the cache manually. + - when: + condition: + and: + - equal: ["", << pipeline.git.tag >>] + steps: + - run: + name: Build_ossfuzz (ccache) + command: CCACHE_ENABLED=1 scripts/ci/build_ossfuzz.sh + - when: + condition: + or: + - not: + equal: ["", << pipeline.git.tag >>] + steps: + - run: + name: Build_ossfuzz (no ccache) + command: scripts/ci/build_ossfuzz.sh + + # On `ci-ccache` we always generate a fresh cache by never restoring and by saving under a unique key. + - when: + condition: + equal: ["ci-ccache", << pipeline.git.branch >>] + steps: + - save_cache: + key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache-{{ .Revision }} + paths: + - ~/.ccache run_proofs: steps: @@ -1197,7 +1280,7 @@ jobs: - run: name: Install build dependencies command: | - pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake git openssh tar + pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake ccache git openssh tar - checkout - run_build - store_artifacts_solc @@ -1257,10 +1340,50 @@ jobs: MAKEFLAGS: -j 10 steps: - checkout - - run: - name: Build - command: | - scripts/ci/build_emscripten.sh + # On `ci-ccache` and `breaking` we intentionally do NOT restore any ccache, so every run starts from scratch. + # Tags always skip ccache. Other branches restore the most recent cache produced on `ci-ccache`. + - when: + condition: + and: + - equal: ["", << pipeline.git.tag >>] + - not: + or: + - equal: ["ci-ccache", << pipeline.git.branch >>] + - equal: ["breaking", << pipeline.git.branch >>] + steps: + - restore_cache: + keys: + # Reuse cache produced on ci-ccache (prefix match; restores the most recent). + - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- + # WARNING! If you edit anything between here and save_cache, remember to bump version or invalidate the cache manually. + - when: + condition: + and: + - equal: ["", << pipeline.git.tag >>] + steps: + - run: + name: Build (ccache) + command: CCACHE_ENABLED=1 scripts/ci/build_emscripten.sh + - when: + condition: + or: + - not: + equal: ["", << pipeline.git.tag >>] + steps: + - run: + name: Build (no ccache) + command: | + scripts/ci/build_emscripten.sh + + # On `ci-ccache` we always generate a fresh cache by never restoring and by saving under a unique key. + - when: + condition: + equal: ["ci-ccache", << pipeline.git.branch >>] + steps: + - save_cache: + key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache-{{ .Revision }} + paths: + - ~/.ccache - store_artifacts: path: upload/soljson.js destination: soljson.js @@ -1737,9 +1860,48 @@ jobs: key: dependencies-win-{{ arch }}-{{ checksum "scripts/install_deps.ps1" }} paths: - .\deps - - run: - name: "Building solidity" - command: scripts/ci/build_win.sh + # On `ci-ccache` and `breaking` we intentionally do NOT restore any ccache, so every run starts from scratch. + # Tags always skip ccache. Other branches restore the most recent cache produced on `ci-ccache`. + - when: + condition: + and: + - equal: ["", << pipeline.git.tag >>] + - not: + or: + - equal: ["ci-ccache", << pipeline.git.branch >>] + - equal: ["breaking", << pipeline.git.branch >>] + steps: + - restore_cache: + keys: + # Reuse cache produced on ci-ccache (prefix match; restores the most recent). + - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- + # WARNING! If you edit anything between here and save_cache, remember to bump version or invalidate the cache manually. + - when: + condition: + and: + - equal: ["", << pipeline.git.tag >>] + steps: + - run: + name: "Building solidity (ccache)" + command: CCACHE_ENABLED=1 scripts/ci/build_win.sh + - when: + condition: + or: + - not: + equal: ["", << pipeline.git.tag >>] + steps: + - run: + name: "Building solidity (no ccache)" + command: scripts/ci/build_win.sh + # On `ci-ccache` we always generate a fresh cache by never restoring and by saving under a unique key. + - when: + condition: + equal: ["ci-ccache", << pipeline.git.branch >>] + steps: + - save_cache: + key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache-{{ .Revision }} + paths: + - ~/.ccache - run: name: "Run solc.exe to make sure build was successful." command: .\build\solc\Release\solc.exe --version diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index dd5a8397b..0666211b7 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -51,6 +51,7 @@ then brew update brew upgrade brew install cmake + brew install ccache brew install wget brew install coreutils brew install diffutils diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh index b7f7e92f5..769455903 100755 --- a/scripts/ci/build.sh +++ b/scripts/ci/build.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -ex -ROOTDIR="$(dirname "$0")/../.." +ROOTDIR="$(realpath "$(dirname "$0")/../..")" # shellcheck source=scripts/common.sh source "${ROOTDIR}/scripts/common.sh" @@ -16,7 +16,21 @@ cd build [[ -n $COVERAGE && -z $CIRCLE_TAG ]] && CMAKE_OPTIONS="$CMAKE_OPTIONS -DCOVERAGE=ON" +if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + export CCACHE_BASEDIR="$ROOTDIR" + export CCACHE_NOHASHDIR=1 + CMAKE_OPTIONS="${CMAKE_OPTIONS:-} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" +fi + # shellcheck disable=SC2086 cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" $CMAKE_OPTIONS +if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + ccache -z +fi + cmake --build . + +if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + ccache -s +fi diff --git a/scripts/ci/build_emscripten.sh b/scripts/ci/build_emscripten.sh index 50c851af8..bf19bad36 100755 --- a/scripts/ci/build_emscripten.sh +++ b/scripts/ci/build_emscripten.sh @@ -54,6 +54,15 @@ function build() { # TODO: This can be removed if and when all usages of `move()` in our codebase use the `std::` qualifier. CMAKE_CXX_FLAGS="-Wno-unqualified-std-cast-call" + if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + export CCACHE_DIR="$HOME/.ccache" + CCACHE_BASEDIR="$(pwd)" + export CCACHE_BASEDIR + export CCACHE_NOHASHDIR=1 + mkdir -p "$CCACHE_DIR" + ccache -z + fi + mkdir -p "$build_dir" cd "$build_dir" emcmake cmake \ @@ -64,6 +73,9 @@ function build() { -DTESTS=0 \ .. make soljson + if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + ccache -s + fi cd .. mkdir -p upload diff --git a/scripts/ci/build_ossfuzz.sh b/scripts/ci/build_ossfuzz.sh index 64d992994..729b54d1d 100755 --- a/scripts/ci/build_ossfuzz.sh +++ b/scripts/ci/build_ossfuzz.sh @@ -18,9 +18,22 @@ function generate_protobuf_bindings function build_fuzzers { cd "${BUILDDIR}" - cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" -DCCACHE=OFF \ - -DCMAKE_TOOLCHAIN_FILE="${ROOTDIR}"/cmake/toolchains/libfuzzer.cmake + if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + export CCACHE_BASEDIR="$ROOTDIR" + export CCACHE_NOHASHDIR=1 + CMAKE_OPTIONS="${CMAKE_OPTIONS:-} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" + fi + # shellcheck disable=SC2086 + cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" \ + -DCMAKE_TOOLCHAIN_FILE="${ROOTDIR}"/cmake/toolchains/libfuzzer.cmake \ + $CMAKE_OPTIONS + if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + ccache -z + fi make ossfuzz ossfuzz_proto ossfuzz_abiv2 -j 4 + if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + ccache -s + fi } generate_protobuf_bindings diff --git a/scripts/ci/build_win.sh b/scripts/ci/build_win.sh index 64d63c58f..8233f3aa6 100755 --- a/scripts/ci/build_win.sh +++ b/scripts/ci/build_win.sh @@ -10,18 +10,39 @@ CIRCLE_TAG="${CIRCLE_TAG:-}" cd "$ROOTDIR" "${ROOTDIR}/scripts/prerelease_suffix.sh" "$prerelease_source" "$CIRCLE_TAG" > prerelease.txt +if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + export CCACHE_BASEDIR="$ROOTDIR" + export CCACHE_NOHASHDIR=1 + export CCACHE_COMPILERTYPE=msvc + # Hard-coded MSVC cl.exe path + CCACHE_COMPILER="C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe" + export CCACHE_COMPILER + PATH="$ROOTDIR/deps/ccache:$(dirname "$CCACHE_COMPILER"):$PATH" + export PATH + # Use a Windows-style path for Visual Studio globals. + WIN_PWD="$(pwd -W)" + # Visual Studio generator doesn't use compiler launchers; use ccache masquerade. + # See https://github.com/ccache/ccache/wiki/MS-Visual-Studio + CMAKE_OPTIONS="${CMAKE_OPTIONS:-} -DCMAKE_VS_GLOBALS=CLToolPath=${WIN_PWD}/deps/ccache;UseMultiToolTask=true" +fi + mkdir -p build/ cd build/ # NOTE: Using an array to force Bash to do wildcard expansion boost_dir=("${ROOTDIR}/deps/boost/lib/cmake/Boost-"*) -"${ROOTDIR}/deps/cmake/bin/cmake" \ + # shellcheck disable=SC2086 + "${ROOTDIR}/deps/cmake/bin/cmake" \ -G "Visual Studio 16 2019" \ -DBoost_DIR="${boost_dir[*]}" \ -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded \ -DCMAKE_INSTALL_PREFIX="${ROOTDIR}/uploads/" \ + ${CMAKE_OPTIONS:-} \ .. +if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + ccache -z +fi MSBuild.exe solidity.sln \ -property:Configuration=Release \ -maxCpuCount:10 \ @@ -31,3 +52,6 @@ MSBuild.exe solidity.sln \ -j 10 \ --target install \ --config Release +if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + ccache -s +fi diff --git a/scripts/install_deps.ps1 b/scripts/install_deps.ps1 index ad4f5bdad..bf8673581 100644 --- a/scripts/install_deps.ps1 +++ b/scripts/install_deps.ps1 @@ -14,6 +14,17 @@ if ( -not (Test-Path "$PSScriptRoot\..\deps\boost") ) { mv cmake-3.27.4-windows-x86_64 "$PSScriptRoot\..\deps\cmake" Remove-Item cmake.zip + Invoke-WebRequest -URI "https://github.com/ccache/ccache/releases/download/v4.12.2/ccache-4.12.2-windows-x86_64.zip" -OutFile ccache.zip + if ((Get-FileHash ccache.zip).Hash -ne "82c1b130b25cc162531dc7a062dc5ea99349cd536bc9eba8a66d976802d66516") { + throw 'Downloaded ccache package has wrong checksum.' + } + tar -xf ccache.zip + mv ccache-4.12.2-windows-x86_64 "$PSScriptRoot\..\deps\ccache" + # ccache MSVC guide: https://github.com/ccache/ccache/wiki/MS-Visual-Studio + # Replace ccache.exe as cl.exe so MSBuild still sees "cl.exe" while ccache wraps the real compiler. + Copy-Item -Force "$PSScriptRoot\..\deps\ccache\ccache.exe" "$PSScriptRoot\..\deps\ccache\cl.exe" + Remove-Item ccache.zip + # FIXME: The default user agent results in Artifactory treating Invoke-WebRequest as a browser # and serving it a page that requires JavaScript. Invoke-WebRequest -URI "https://archives.boost.io/release/1.83.0/source/boost_1_83_0.zip" -OutFile boost.zip -UserAgent "" From d68a7cdf89808f68c0566b021fc12c4ab5816f80 Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Wed, 7 Jan 2026 11:39:08 +0100 Subject: [PATCH 1078/1340] Set CCACHE_DIR and create directory if CCACHE_ENABLED --- scripts/ci/build.sh | 2 ++ scripts/ci/build_ossfuzz.sh | 2 ++ scripts/ci/build_win.sh | 2 ++ 3 files changed, 6 insertions(+) diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh index 769455903..385d2d898 100755 --- a/scripts/ci/build.sh +++ b/scripts/ci/build.sh @@ -17,9 +17,11 @@ cd build [[ -n $COVERAGE && -z $CIRCLE_TAG ]] && CMAKE_OPTIONS="$CMAKE_OPTIONS -DCOVERAGE=ON" if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + export CCACHE_DIR="$HOME/.ccache" export CCACHE_BASEDIR="$ROOTDIR" export CCACHE_NOHASHDIR=1 CMAKE_OPTIONS="${CMAKE_OPTIONS:-} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" + mkdir -p "$CCACHE_DIR" fi # shellcheck disable=SC2086 diff --git a/scripts/ci/build_ossfuzz.sh b/scripts/ci/build_ossfuzz.sh index 729b54d1d..883c939b8 100755 --- a/scripts/ci/build_ossfuzz.sh +++ b/scripts/ci/build_ossfuzz.sh @@ -19,9 +19,11 @@ function build_fuzzers { cd "${BUILDDIR}" if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + export CCACHE_DIR="$HOME/.ccache" export CCACHE_BASEDIR="$ROOTDIR" export CCACHE_NOHASHDIR=1 CMAKE_OPTIONS="${CMAKE_OPTIONS:-} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" + mkdir -p "$CCACHE_DIR" fi # shellcheck disable=SC2086 cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" \ diff --git a/scripts/ci/build_win.sh b/scripts/ci/build_win.sh index 8233f3aa6..ea820705d 100755 --- a/scripts/ci/build_win.sh +++ b/scripts/ci/build_win.sh @@ -11,6 +11,7 @@ cd "$ROOTDIR" "${ROOTDIR}/scripts/prerelease_suffix.sh" "$prerelease_source" "$CIRCLE_TAG" > prerelease.txt if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then + export CCACHE_DIR="$HOME/.ccache" export CCACHE_BASEDIR="$ROOTDIR" export CCACHE_NOHASHDIR=1 export CCACHE_COMPILERTYPE=msvc @@ -24,6 +25,7 @@ if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then # Visual Studio generator doesn't use compiler launchers; use ccache masquerade. # See https://github.com/ccache/ccache/wiki/MS-Visual-Studio CMAKE_OPTIONS="${CMAKE_OPTIONS:-} -DCMAKE_VS_GLOBALS=CLToolPath=${WIN_PWD}/deps/ccache;UseMultiToolTask=true" + mkdir -p "$CCACHE_DIR" fi mkdir -p build/ From 2243156ebd88193bff483fa6b5495d474948a46f Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Thu, 8 Jan 2026 14:22:56 +0100 Subject: [PATCH 1079/1340] enforce CCACHE_KEY and fix Windows ccache CMake globals --- .circleci/config.yml | 55 ++++++++++++++++++++++++++++++++--------- scripts/ci/build_win.sh | 5 +++- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1c141d647..8d9081beb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -75,6 +75,17 @@ commands: event: release condition: on_success + ensure_ccache_key: + description: "Fail fast when CCACHE_KEY is missing." + steps: + - run: + name: Check CCACHE_KEY + command: | + if [ -z "${CCACHE_KEY:-}" ]; then + echo "CCACHE_KEY is not set. Please set it in CircleCI environment settings." + exit 1 + fi + prepare_bytecode_report: description: "Generate bytecode report and upload it as an artifact." parameters: @@ -208,6 +219,11 @@ commands: run_build: steps: + - when: + condition: + equal: ["", << pipeline.git.tag >>] + steps: + - ensure_ccache_key # TODO: remove the line below # Before merging this PR we need to use an alternative develop branch to test the functionality, `ci-ccache` @@ -226,7 +242,7 @@ commands: keys: # Reuse cache produced on ci-ccache (prefix match; restores the most recent). - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- - # WARNING! If you edit anything between here and save_cache, remember to bump version or invalidate the cache manually. + # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - when: condition: and: @@ -234,7 +250,7 @@ commands: steps: - run: name: Build (ccache) - command: CCACHE_ENABLED=1 scripts/ci/build.sh + command: CCACHE_ENABLED=${CCACHE_ENABLED:-1} scripts/ci/build.sh - when: condition: or: @@ -251,12 +267,17 @@ commands: equal: ["ci-ccache", << pipeline.git.branch >>] steps: - save_cache: - key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache-{{ .Revision }} + key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache paths: - ~/.ccache run_build_ossfuzz: steps: + - when: + condition: + equal: ["", << pipeline.git.tag >>] + steps: + - ensure_ccache_key # On `ci-ccache` and `breaking` we intentionally do NOT restore any ccache, so every run starts from scratch. # Tags always skip ccache. Other branches restore the most recent cache produced on `ci-ccache`. - when: @@ -272,7 +293,7 @@ commands: keys: # Reuse cache produced on ci-ccache (prefix match; restores the most recent). - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- - # WARNING! If you edit anything between here and save_cache, remember to bump version or invalidate the cache manually. + # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - when: condition: and: @@ -280,7 +301,7 @@ commands: steps: - run: name: Build_ossfuzz (ccache) - command: CCACHE_ENABLED=1 scripts/ci/build_ossfuzz.sh + command: CCACHE_ENABLED=${CCACHE_ENABLED:-1} scripts/ci/build_ossfuzz.sh - when: condition: or: @@ -297,7 +318,7 @@ commands: equal: ["ci-ccache", << pipeline.git.branch >>] steps: - save_cache: - key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache-{{ .Revision }} + key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache paths: - ~/.ccache @@ -1340,6 +1361,11 @@ jobs: MAKEFLAGS: -j 10 steps: - checkout + - when: + condition: + equal: ["", << pipeline.git.tag >>] + steps: + - ensure_ccache_key # On `ci-ccache` and `breaking` we intentionally do NOT restore any ccache, so every run starts from scratch. # Tags always skip ccache. Other branches restore the most recent cache produced on `ci-ccache`. - when: @@ -1355,7 +1381,7 @@ jobs: keys: # Reuse cache produced on ci-ccache (prefix match; restores the most recent). - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- - # WARNING! If you edit anything between here and save_cache, remember to bump version or invalidate the cache manually. + # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - when: condition: and: @@ -1363,7 +1389,7 @@ jobs: steps: - run: name: Build (ccache) - command: CCACHE_ENABLED=1 scripts/ci/build_emscripten.sh + command: CCACHE_ENABLED=${CCACHE_ENABLED:-1} scripts/ci/build_emscripten.sh - when: condition: or: @@ -1381,7 +1407,7 @@ jobs: equal: ["ci-ccache", << pipeline.git.branch >>] steps: - save_cache: - key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache-{{ .Revision }} + key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache paths: - ~/.ccache - store_artifacts: @@ -1860,6 +1886,11 @@ jobs: key: dependencies-win-{{ arch }}-{{ checksum "scripts/install_deps.ps1" }} paths: - .\deps + - when: + condition: + equal: ["", << pipeline.git.tag >>] + steps: + - ensure_ccache_key # On `ci-ccache` and `breaking` we intentionally do NOT restore any ccache, so every run starts from scratch. # Tags always skip ccache. Other branches restore the most recent cache produced on `ci-ccache`. - when: @@ -1875,7 +1906,7 @@ jobs: keys: # Reuse cache produced on ci-ccache (prefix match; restores the most recent). - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- - # WARNING! If you edit anything between here and save_cache, remember to bump version or invalidate the cache manually. + # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - when: condition: and: @@ -1883,7 +1914,7 @@ jobs: steps: - run: name: "Building solidity (ccache)" - command: CCACHE_ENABLED=1 scripts/ci/build_win.sh + command: CCACHE_ENABLED=${CCACHE_ENABLED:-1} scripts/ci/build_win.sh - when: condition: or: @@ -1899,7 +1930,7 @@ jobs: equal: ["ci-ccache", << pipeline.git.branch >>] steps: - save_cache: - key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache-{{ .Revision }} + key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache paths: - ~/.ccache - run: diff --git a/scripts/ci/build_win.sh b/scripts/ci/build_win.sh index ea820705d..ee64243f4 100755 --- a/scripts/ci/build_win.sh +++ b/scripts/ci/build_win.sh @@ -6,6 +6,7 @@ prerelease_source="${1:-ci}" ROOTDIR="$(realpath "$(dirname "$0")/../../")" FORCE_RELEASE="${FORCE_RELEASE:-}" CIRCLE_TAG="${CIRCLE_TAG:-}" +CMAKE_VS_GLOBALS_ARG=() cd "$ROOTDIR" "${ROOTDIR}/scripts/prerelease_suffix.sh" "$prerelease_source" "$CIRCLE_TAG" > prerelease.txt @@ -24,7 +25,8 @@ if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then WIN_PWD="$(pwd -W)" # Visual Studio generator doesn't use compiler launchers; use ccache masquerade. # See https://github.com/ccache/ccache/wiki/MS-Visual-Studio - CMAKE_OPTIONS="${CMAKE_OPTIONS:-} -DCMAKE_VS_GLOBALS=CLToolPath=${WIN_PWD}/deps/ccache;UseMultiToolTask=true" + CMAKE_VS_GLOBALS="CLToolPath=${WIN_PWD}/deps/ccache;UseMultiToolTask=true" + CMAKE_VS_GLOBALS_ARG=(-DCMAKE_VS_GLOBALS="$CMAKE_VS_GLOBALS") mkdir -p "$CCACHE_DIR" fi @@ -40,6 +42,7 @@ boost_dir=("${ROOTDIR}/deps/boost/lib/cmake/Boost-"*) -DBoost_DIR="${boost_dir[*]}" \ -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded \ -DCMAKE_INSTALL_PREFIX="${ROOTDIR}/uploads/" \ + "${CMAKE_VS_GLOBALS_ARG[@]}" \ ${CMAKE_OPTIONS:-} \ .. if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then From e1e2ebe86da6502823b3eb9576ceeaf72c4ef137 Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Thu, 8 Jan 2026 15:07:35 +0100 Subject: [PATCH 1080/1340] Programmatically find the path of cl.exe --- scripts/ci/build_win.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/ci/build_win.sh b/scripts/ci/build_win.sh index ee64243f4..5a3baf327 100755 --- a/scripts/ci/build_win.sh +++ b/scripts/ci/build_win.sh @@ -16,8 +16,12 @@ if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then export CCACHE_BASEDIR="$ROOTDIR" export CCACHE_NOHASHDIR=1 export CCACHE_COMPILERTYPE=msvc - # Hard-coded MSVC cl.exe path - CCACHE_COMPILER="C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe" + VSWHERE="C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe" + CCACHE_COMPILER="$("$VSWHERE" -latest -products "*" \ + -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 \ + -version "[16.0,17.0)" \ + -find "VC/Tools/MSVC/*/bin/Hostx64/x64/cl.exe" | sort -V | tail -n 1 | tr -d '\r')" + CCACHE_COMPILER="${CCACHE_COMPILER//\\//}" export CCACHE_COMPILER PATH="$ROOTDIR/deps/ccache:$(dirname "$CCACHE_COMPILER"):$PATH" export PATH From c2bf44142ab3057e1a731843ae0aef149e1f9c59 Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Thu, 8 Jan 2026 15:17:56 +0100 Subject: [PATCH 1081/1340] Remove the version filter in the command to find cl.exe --- scripts/ci/build_win.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/ci/build_win.sh b/scripts/ci/build_win.sh index 5a3baf327..01c062ec5 100755 --- a/scripts/ci/build_win.sh +++ b/scripts/ci/build_win.sh @@ -19,7 +19,6 @@ if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then VSWHERE="C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe" CCACHE_COMPILER="$("$VSWHERE" -latest -products "*" \ -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 \ - -version "[16.0,17.0)" \ -find "VC/Tools/MSVC/*/bin/Hostx64/x64/cl.exe" | sort -V | tail -n 1 | tr -d '\r')" CCACHE_COMPILER="${CCACHE_COMPILER//\\//}" export CCACHE_COMPILER From 9b8d22abb56ad379dfedea64f751cde3185f11aa Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Thu, 8 Jan 2026 15:24:56 +0100 Subject: [PATCH 1082/1340] Fix vswhere command --- scripts/ci/build_win.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/build_win.sh b/scripts/ci/build_win.sh index 01c062ec5..b88051985 100755 --- a/scripts/ci/build_win.sh +++ b/scripts/ci/build_win.sh @@ -19,7 +19,7 @@ if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then VSWHERE="C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe" CCACHE_COMPILER="$("$VSWHERE" -latest -products "*" \ -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 \ - -find "VC/Tools/MSVC/*/bin/Hostx64/x64/cl.exe" | sort -V | tail -n 1 | tr -d '\r')" + -find "VC/Tools/MSVC/*/bin/Hostx64/x64/cl.exe" | head -n 1 | tr -d '\r')" CCACHE_COMPILER="${CCACHE_COMPILER//\\//}" export CCACHE_COMPILER PATH="$ROOTDIR/deps/ccache:$(dirname "$CCACHE_COMPILER"):$PATH" From 4bb922571121a97421d5470cfa2d6286ea311f6e Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Thu, 8 Jan 2026 15:39:31 +0100 Subject: [PATCH 1083/1340] Fix CCACHE_COMPILER extraction --- scripts/ci/build_win.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/ci/build_win.sh b/scripts/ci/build_win.sh index b88051985..07604c8eb 100755 --- a/scripts/ci/build_win.sh +++ b/scripts/ci/build_win.sh @@ -16,10 +16,12 @@ if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then export CCACHE_BASEDIR="$ROOTDIR" export CCACHE_NOHASHDIR=1 export CCACHE_COMPILERTYPE=msvc - VSWHERE="C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe" - CCACHE_COMPILER="$("$VSWHERE" -latest -products "*" \ + VSWHERE="${VSWHERE:-C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe}" + VS_INSTALL="$("$VSWHERE" -latest -products "*" \ -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 \ - -find "VC/Tools/MSVC/*/bin/Hostx64/x64/cl.exe" | head -n 1 | tr -d '\r')" + -property installationPath | tr -d '\r')" + VCTOOLS_VERSION="$(tr -d '\r' < "$VS_INSTALL/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt")" + CCACHE_COMPILER="$VS_INSTALL/VC/Tools/MSVC/$VCTOOLS_VERSION/bin/Hostx64/x64/cl.exe" CCACHE_COMPILER="${CCACHE_COMPILER//\\//}" export CCACHE_COMPILER PATH="$ROOTDIR/deps/ccache:$(dirname "$CCACHE_COMPILER"):$PATH" From b6d0d788d49cf28ca14162893d03adac3fcb5f9b Mon Sep 17 00:00:00 2001 From: 0xcharry Date: Sun, 11 Jan 2026 16:55:23 +0100 Subject: [PATCH 1084/1340] Update JSON.cpp --- libsolutil/JSON.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libsolutil/JSON.cpp b/libsolutil/JSON.cpp index 548fdfe0b..8633a44c4 100644 --- a/libsolutil/JSON.cpp +++ b/libsolutil/JSON.cpp @@ -149,7 +149,6 @@ bool jsonParseStrict(std::string const& _input, Json& _json, std::string* _errs /* allow exceptions */ true, /* ignore_comments */true ); - _errs = {}; return true; } catch (Json::parse_error const& e) From 95caef252520fa52bfce38e69052da0945132588 Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Mon, 12 Jan 2026 09:24:16 +0100 Subject: [PATCH 1085/1340] Refactor config.yml to re-use ccache restore and save commands --- .circleci/config.yml | 135 +++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 90 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8d9081beb..de63a363f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -86,6 +86,44 @@ commands: exit 1 fi + restore_ccache_if_allowed: + description: "Restore ccache unless on a tag or a skipped branch." + parameters: + # TODO: remove the line below + # Before merging this PR we need to use an alternative develop branch to test the functionality, `ci-ccache` + skip_branches_regex: + description: "Regex of branches that should skip restoring the cache." + type: string + default: "^(ci-ccache|breaking)$" + steps: + # Tags always skip ccache. Selected branches intentionally start from scratch. + - when: + condition: + and: + - equal: ["", << pipeline.git.tag >>] + - not: + matches: + pattern: "<< parameters.skip_branches_regex >>" + value: << pipeline.git.branch >> + steps: + - restore_cache: + keys: + # Reuse cache produced on ci-ccache (prefix match; restores the most recent). + - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- + + save_ccache_if_develop: + description: "Save a fresh ccache only on the ci-ccache branch." + steps: + # On `ci-ccache` we always generate a fresh cache by never restoring and by saving under a unique key. + - when: + condition: + equal: ["ci-ccache", << pipeline.git.branch >>] + steps: + - save_cache: + key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache + paths: + - ~/.ccache + prepare_bytecode_report: description: "Generate bytecode report and upload it as an artifact." parameters: @@ -224,24 +262,7 @@ commands: equal: ["", << pipeline.git.tag >>] steps: - ensure_ccache_key - # TODO: remove the line below - # Before merging this PR we need to use an alternative develop branch to test the functionality, `ci-ccache` - - # On `ci-ccache` and `breaking` we intentionally do NOT restore any ccache, so every run starts from scratch. - # Tags always skip ccache. Other branches restore the most recent cache produced on `ci-ccache`. - - when: - condition: - and: - - equal: ["", << pipeline.git.tag >>] - - not: - or: - - equal: ["ci-ccache", << pipeline.git.branch >>] - - equal: ["breaking", << pipeline.git.branch >>] - steps: - - restore_cache: - keys: - # Reuse cache produced on ci-ccache (prefix match; restores the most recent). - - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- + - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - when: condition: @@ -261,15 +282,7 @@ commands: name: Build (no ccache) command: scripts/ci/build.sh - # On `ci-ccache` we always generate a fresh cache by never restoring and by saving under a unique key. - - when: - condition: - equal: ["ci-ccache", << pipeline.git.branch >>] - steps: - - save_cache: - key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache - paths: - - ~/.ccache + - save_ccache_if_develop run_build_ossfuzz: steps: @@ -278,21 +291,7 @@ commands: equal: ["", << pipeline.git.tag >>] steps: - ensure_ccache_key - # On `ci-ccache` and `breaking` we intentionally do NOT restore any ccache, so every run starts from scratch. - # Tags always skip ccache. Other branches restore the most recent cache produced on `ci-ccache`. - - when: - condition: - and: - - equal: ["", << pipeline.git.tag >>] - - not: - or: - - equal: ["ci-ccache", << pipeline.git.branch >>] - - equal: ["breaking", << pipeline.git.branch >>] - steps: - - restore_cache: - keys: - # Reuse cache produced on ci-ccache (prefix match; restores the most recent). - - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- + - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - when: condition: @@ -312,15 +311,7 @@ commands: name: Build_ossfuzz (no ccache) command: scripts/ci/build_ossfuzz.sh - # On `ci-ccache` we always generate a fresh cache by never restoring and by saving under a unique key. - - when: - condition: - equal: ["ci-ccache", << pipeline.git.branch >>] - steps: - - save_cache: - key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache - paths: - - ~/.ccache + - save_ccache_if_develop run_proofs: steps: @@ -1366,21 +1357,7 @@ jobs: equal: ["", << pipeline.git.tag >>] steps: - ensure_ccache_key - # On `ci-ccache` and `breaking` we intentionally do NOT restore any ccache, so every run starts from scratch. - # Tags always skip ccache. Other branches restore the most recent cache produced on `ci-ccache`. - - when: - condition: - and: - - equal: ["", << pipeline.git.tag >>] - - not: - or: - - equal: ["ci-ccache", << pipeline.git.branch >>] - - equal: ["breaking", << pipeline.git.branch >>] - steps: - - restore_cache: - keys: - # Reuse cache produced on ci-ccache (prefix match; restores the most recent). - - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- + - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - when: condition: @@ -1401,15 +1378,7 @@ jobs: command: | scripts/ci/build_emscripten.sh - # On `ci-ccache` we always generate a fresh cache by never restoring and by saving under a unique key. - - when: - condition: - equal: ["ci-ccache", << pipeline.git.branch >>] - steps: - - save_cache: - key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache - paths: - - ~/.ccache + - save_ccache_if_develop - store_artifacts: path: upload/soljson.js destination: soljson.js @@ -1891,21 +1860,7 @@ jobs: equal: ["", << pipeline.git.tag >>] steps: - ensure_ccache_key - # On `ci-ccache` and `breaking` we intentionally do NOT restore any ccache, so every run starts from scratch. - # Tags always skip ccache. Other branches restore the most recent cache produced on `ci-ccache`. - - when: - condition: - and: - - equal: ["", << pipeline.git.tag >>] - - not: - or: - - equal: ["ci-ccache", << pipeline.git.branch >>] - - equal: ["breaking", << pipeline.git.branch >>] - steps: - - restore_cache: - keys: - # Reuse cache produced on ci-ccache (prefix match; restores the most recent). - - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- + - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - when: condition: From bd615db148d3e3a2b76a52af0202043e1c06346d Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Mon, 12 Jan 2026 11:27:04 +0100 Subject: [PATCH 1086/1340] Add revision to the cache key to avoid skipping cache generation for duplicate key --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index de63a363f..1b6a309fc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -120,7 +120,7 @@ commands: equal: ["ci-ccache", << pipeline.git.branch >>] steps: - save_cache: - key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache + key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache-{{ .Revision }} paths: - ~/.ccache From be1df0710601fda269610953b75c7bf92684f965 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 14 Jan 2026 00:54:35 +0100 Subject: [PATCH 1087/1340] CLI Parser: Use defaulted comparison operators for options --- solc/CommandLineParser.cpp | 57 -------------------------------------- solc/CommandLineParser.h | 57 ++++++++++++++++++++++++++++---------- 2 files changed, 42 insertions(+), 72 deletions(-) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 50ce02bd1..534eb57d1 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -157,14 +157,6 @@ void CommandLineParser::checkMutuallyExclusive(std::vector const& _ } } -bool CompilerOutputs::operator==(CompilerOutputs const& _other) const noexcept -{ - for (bool CompilerOutputs::* member: componentMap() | ranges::views::values) - if (this->*member != _other.*member) - return false; - return true; -} - std::ostream& operator<<(std::ostream& _out, CompilerOutputs const& _selection) { std::vector serializedSelection; @@ -187,15 +179,6 @@ std::string const& CompilerOutputs::componentName(bool CompilerOutputs::* _compo solAssert(false, ""); } -bool CombinedJsonRequests::operator==(CombinedJsonRequests const& _other) const noexcept -{ - for (bool CombinedJsonRequests::* member: componentMap() | ranges::views::values) - if (this->*member != _other.*member) - return false; - return true; -} - - std::ostream& operator<<(std::ostream& _out, CombinedJsonRequests const& _requests) { std::vector serializedRequests; @@ -217,46 +200,6 @@ std::string const& CombinedJsonRequests::componentName(bool CombinedJsonRequests solAssert(false, ""); } -bool CommandLineOptions::operator==(CommandLineOptions const& _other) const noexcept -{ - return - input.paths == _other.input.paths && - input.remappings == _other.input.remappings && - input.addStdin == _other.input.addStdin && - input.basePath == _other.input.basePath && - input.includePaths == _other.input.includePaths && - input.allowedDirectories == _other.input.allowedDirectories && - input.ignoreMissingFiles == _other.input.ignoreMissingFiles && - input.noImportCallback == _other.input.noImportCallback && - output.dir == _other.output.dir && - output.overwriteFiles == _other.output.overwriteFiles && - output.evmVersion == _other.output.evmVersion && - output.viaIR == _other.output.viaIR && - output.revertStrings == _other.output.revertStrings && - output.debugInfoSelection == _other.output.debugInfoSelection && - output.stopAfter == _other.output.stopAfter && - output.eofVersion == _other.output.eofVersion && - input.mode == _other.input.mode && - assembly.targetMachine == _other.assembly.targetMachine && - assembly.inputLanguage == _other.assembly.inputLanguage && - linker.libraries == _other.linker.libraries && - formatting.json == _other.formatting.json && - formatting.coloredOutput == _other.formatting.coloredOutput && - formatting.withErrorIds == _other.formatting.withErrorIds && - compiler.outputs == _other.compiler.outputs && - compiler.estimateGas == _other.compiler.estimateGas && - compiler.combinedJsonRequests == _other.compiler.combinedJsonRequests && - metadata.format == _other.metadata.format && - metadata.hash == _other.metadata.hash && - metadata.literalSources == _other.metadata.literalSources && - optimizer.optimizeEvmasm == _other.optimizer.optimizeEvmasm && - optimizer.optimizeYul == _other.optimizer.optimizeYul && - optimizer.expectedExecutionsPerDeployment == _other.optimizer.expectedExecutionsPerDeployment && - optimizer.yulSteps == _other.optimizer.yulSteps && - modelChecker.initialize == _other.modelChecker.initialize && - modelChecker.settings == _other.modelChecker.settings; -} - OptimiserSettings CommandLineOptions::optimiserSettings() const { OptimiserSettings settings; diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index d8141cb4f..46743232b 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -62,8 +62,8 @@ enum class InputMode struct CompilerOutputs { - bool operator!=(CompilerOutputs const& _other) const noexcept { return !(*this == _other); } - bool operator==(CompilerOutputs const& _other) const noexcept; + bool operator!=(CompilerOutputs const& _other) const noexcept = default; + bool operator==(CompilerOutputs const& _other) const noexcept = default; friend std::ostream& operator<<(std::ostream& _out, CompilerOutputs const& _requests); static std::string const& componentName(bool CompilerOutputs::* _component); @@ -118,8 +118,8 @@ struct CompilerOutputs struct CombinedJsonRequests { - bool operator!=(CombinedJsonRequests const& _other) const noexcept { return !(*this == _other); } - bool operator==(CombinedJsonRequests const& _other) const noexcept; + bool operator!=(CombinedJsonRequests const& _other) const noexcept = default; + bool operator==(CombinedJsonRequests const& _other) const noexcept = default; friend std::ostream& operator<<(std::ostream& _out, CombinedJsonRequests const& _requests); static std::string const& componentName(bool CombinedJsonRequests::* _component); @@ -170,13 +170,16 @@ struct CombinedJsonRequests struct CommandLineOptions { - bool operator==(CommandLineOptions const& _other) const noexcept; - bool operator!=(CommandLineOptions const& _other) const noexcept { return !(*this == _other); } + bool operator==(CommandLineOptions const& _other) const noexcept = default; + bool operator!=(CommandLineOptions const& _other) const noexcept = default; OptimiserSettings optimiserSettings() const; - struct + struct Input { + bool operator==(Input const&) const noexcept = default; + bool operator!=(Input const&) const noexcept = default; + InputMode mode = InputMode::Compiler; std::set paths; std::vector remappings; @@ -188,8 +191,11 @@ struct CommandLineOptions bool noImportCallback = false; } input; - struct + struct Output { + bool operator==(Output const&) const noexcept = default; + bool operator!=(Output const&) const noexcept = default; + boost::filesystem::path dir; bool overwriteFiles = false; langutil::EVMVersion evmVersion; @@ -200,48 +206,69 @@ struct CommandLineOptions std::optional eofVersion; } output; - struct + struct Assembly { + bool operator==(Assembly const&) const noexcept = default; + bool operator!=(Assembly const&) const noexcept = default; + yul::YulStack::Machine targetMachine = yul::YulStack::Machine::EVM; yul::YulStack::Language inputLanguage = yul::YulStack::Language::StrictAssembly; } assembly; - struct + struct Linker { + bool operator==(Linker const&) const noexcept = default; + bool operator!=(Linker const&) const noexcept = default; + std::map libraries; // library name -> address } linker; - struct + struct Formatting { + bool operator==(Formatting const&) const noexcept = default; + bool operator!=(Formatting const&) const noexcept = default; + util::JsonFormat json; std::optional coloredOutput; bool withErrorIds = false; } formatting; - struct + struct Compiler { + bool operator==(Compiler const&) const noexcept = default; + bool operator!=(Compiler const&) const noexcept = default; + CompilerOutputs outputs; bool estimateGas = false; std::optional combinedJsonRequests; } compiler; - struct + struct Metadata { + bool operator==(Metadata const&) const noexcept = default; + bool operator!=(Metadata const&) const noexcept = default; + CompilerStack::MetadataFormat format = CompilerStack::defaultMetadataFormat(); CompilerStack::MetadataHash hash = CompilerStack::MetadataHash::IPFS; bool literalSources = false; } metadata; - struct + struct Optimizer { + bool operator==(Optimizer const&) const noexcept = default; + bool operator!=(Optimizer const&) const noexcept = default; + bool optimizeEvmasm = false; bool optimizeYul = false; std::optional expectedExecutionsPerDeployment; std::optional yulSteps; } optimizer; - struct + struct ModelChecker { + bool operator==(ModelChecker const&) const noexcept = default; + bool operator!=(ModelChecker const&) const noexcept = default; + bool initialize = false; ModelCheckerSettings settings; } modelChecker; From 6d538dd2056cd6dc9b8abfe15ebda1e1b5301f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 20 Dec 2025 01:05:26 +0100 Subject: [PATCH 1088/1340] ReleaseChecklist: Split off Comms and Documentation sections from Post-release --- ReleaseChecklist.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 9c3b2f896..f56ec55fe 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -89,12 +89,13 @@ At least a day before the release: Inspect the tarball to ensure that it contains an up-to-date compiler binary (`soljson.js`). - [ ] Run `npm publish solc-x.y.z.tgz` to publish the newly created tarball. -### Post-release +### Documentation - [ ] Make sure the documentation for the new release has been published successfully. Go to the [documentation status page at ReadTheDocs](https://readthedocs.org/projects/solidity/) and verify that the new version is listed, works and is marked as default. - [ ] Remove "still in progress" warning from the [release notes](https://github.com/argotorg/solidity/releases). + +### Comms - [ ] Merge the [blog posts](https://github.com/argotorg/solidity-website/pulls) related to the release. -- [ ] Create a commit to increase the version number on `develop` in `CMakeLists.txt` and add a new skeleton changelog entry. - [ ] Update the release information section [in the source of soliditylang.org](https://github.com/argotorg/solidity-website/blob/main/src/pages/index.tsx). - [ ] Announce on [Twitter](https://twitter.com/solidity_lang), including links to the release and the blog post. - [ ] Announce on [Fosstodon](https://fosstodon.org/@solidity/), including links to the release and the blog post. @@ -102,6 +103,9 @@ At least a day before the release: - [ ] Share the announcement on the [Solidity forum](https://forum.soliditylang.org) in the `Announcements` category. - [ ] Share the announcement on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im). - [ ] Share the announcement on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org). + +### Post-release +- [ ] Create a commit to increase the version number on `develop` in `CMakeLists.txt` and add a new skeleton changelog entry. - [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.argot.org/@solidity-release-mistakes). - [ ] Bump vendored dependencies. - [ ] Lean back, wait for bug reports and repeat from step 1 :). From 5e28f2a5a1ec43f2b6951971f51398500317de90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 20 Dec 2025 01:10:28 +0100 Subject: [PATCH 1089/1340] ReleaseChecklist: New step to verify links in release notes --- ReleaseChecklist.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index f56ec55fe..637f8dc8a 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -97,6 +97,7 @@ At least a day before the release: ### Comms - [ ] Merge the [blog posts](https://github.com/argotorg/solidity-website/pulls) related to the release. - [ ] Update the release information section [in the source of soliditylang.org](https://github.com/argotorg/solidity-website/blob/main/src/pages/index.tsx). +- [ ] Verify that the link to the blog post in [release notes](https://github.com/argotorg/solidity/releases) is not broken. - [ ] Announce on [Twitter](https://twitter.com/solidity_lang), including links to the release and the blog post. - [ ] Announce on [Fosstodon](https://fosstodon.org/@solidity/), including links to the release and the blog post. - [ ] Share the announcement on Reddit in [`/r/ethdev`](https://reddit.com/r/ethdev/), cross-posted to [`/r/ethereum`](https://reddit.com/r/ethereum/). From 4629368a8df56b84ca3b03ade67446b8e1634e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 20 Dec 2025 01:17:09 +0100 Subject: [PATCH 1090/1340] ReleaseChecklist: Emphasize that blog/website drafts should be created ahead of time and only merged after release --- ReleaseChecklist.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 637f8dc8a..d9f6b84a8 100644 --- a/ReleaseChecklist.md +++ b/ReleaseChecklist.md @@ -36,10 +36,11 @@ At least a day before the release: - [ ] Create drafts of blog posts. - [ ] Prepare drafts of Twitter, Reddit and Solidity Forum announcements. -### Blog Post +### Website/Blog Updates - [ ] Create a post on [solidity-website](https://github.com/argotorg/solidity-website/tree/main/src/posts) in the `Releases` category and explain some of the new features or concepts. - [ ] Create a post on [solidity-website](https://github.com/argotorg/solidity-website/tree/main/src/posts) in the `Security Alerts` category in case of important bug(s). -- [ ] Get the posts reviewed and approved **before the release starts**. +- [ ] Update the release information section [in the source of soliditylang.org](https://github.com/argotorg/solidity-website/blob/main/src/pages/index.tsx). +- [ ] Get the PR(s) for the above reviewed and approved **before the release starts**, but don't merge them yet. ### Changelog - [ ] Ensure that all changelog entries are correctly classified as language or compiler features. @@ -95,8 +96,7 @@ At least a day before the release: - [ ] Remove "still in progress" warning from the [release notes](https://github.com/argotorg/solidity/releases). ### Comms -- [ ] Merge the [blog posts](https://github.com/argotorg/solidity-website/pulls) related to the release. -- [ ] Update the release information section [in the source of soliditylang.org](https://github.com/argotorg/solidity-website/blob/main/src/pages/index.tsx). +- [ ] Merge the blog posts and website updates prepared for the release. - [ ] Verify that the link to the blog post in [release notes](https://github.com/argotorg/solidity/releases) is not broken. - [ ] Announce on [Twitter](https://twitter.com/solidity_lang), including links to the release and the blog post. - [ ] Announce on [Fosstodon](https://fosstodon.org/@solidity/), including links to the release and the blog post. From 7bd6b273180c798d559163c4cdec52e627d45d58 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 11 Dec 2025 02:29:33 -0300 Subject: [PATCH 1091/1340] Replace transfer with call in smt tests --- .../model_checker_targets_assert_chc/err | 12 ++---- .../input.sol | 5 ++- .../err | 5 --- .../input.sol | 3 +- .../model_checker_targets_div_by_zero_chc/err | 7 +--- .../input.sol | 5 ++- .../model_checker_targets_error/input.sol | 5 ++- .../err | 12 ++---- .../input.sol | 5 ++- .../model_checker_targets_overflow_chc/err | 7 +--- .../input.sol | 5 ++- .../model_checker_targets_pop_empty_chc/err | 12 ++---- .../input.sol | 5 ++- .../model_checker_targets_underflow_chc/err | 7 +--- .../input.sol | 5 ++- .../err | 14 +++---- .../input.sol | 5 ++- .../err | 8 +--- .../input.sol | 5 ++- .../input.json | 3 +- .../output.json | 33 +++++------------ .../input.json | 3 +- .../output.json | 21 ----------- .../input.json | 3 +- .../output.json | 21 +---------- .../input.json | 3 +- .../input.json | 3 +- .../output.json | 33 +++++------------ .../input.json | 3 +- .../output.json | 21 +---------- .../input.json | 3 +- .../output.json | 33 +++++------------ .../input.json | 3 +- .../output.json | 21 +---------- .../input.json | 3 +- .../output.json | 37 +++++++------------ .../input.json | 3 +- .../output.json | 23 ++---------- .../input.json | 3 +- .../input.json | 3 +- .../input.json | 3 +- 41 files changed, 128 insertions(+), 286 deletions(-) delete mode 100644 test/cmdlineTests/model_checker_targets_constant_condition_chc/err diff --git a/test/cmdlineTests/model_checker_targets_assert_chc/err b/test/cmdlineTests/model_checker_targets_assert_chc/err index 096773e68..fb4d9fcc5 100644 --- a/test/cmdlineTests/model_checker_targets_assert_chc/err +++ b/test/cmdlineTests/model_checker_targets_assert_chc/err @@ -1,20 +1,16 @@ -Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. - --> input.sol:10:3: - | -10 | a.transfer(x); - | ^^^^^^^^^^ - Warning: CHC: Assertion violation happens here. Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> input.sol:11:3: + a.call{value: x}("") -- untrusted external call + --> input.sol:12:3: | -11 | assert(x > 0); +12 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_assert_chc/input.sol b/test/cmdlineTests/model_checker_targets_assert_chc/input.sol index 33b5bfab3..0061441c0 100644 --- a/test/cmdlineTests/model_checker_targets_assert_chc/input.sol +++ b/test/cmdlineTests/model_checker_targets_assert_chc/input.sol @@ -7,9 +7,10 @@ contract test { --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(""); + require(success); assert(x > 0); arr.pop(); arr[x]; } -} \ No newline at end of file +} diff --git a/test/cmdlineTests/model_checker_targets_constant_condition_chc/err b/test/cmdlineTests/model_checker_targets_constant_condition_chc/err deleted file mode 100644 index 4876e9366..000000000 --- a/test/cmdlineTests/model_checker_targets_constant_condition_chc/err +++ /dev/null @@ -1,5 +0,0 @@ -Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. - --> input.sol:11:3: - | -11 | a.transfer(x); - | ^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_constant_condition_chc/input.sol b/test/cmdlineTests/model_checker_targets_constant_condition_chc/input.sol index 4b521b3de..4103252ca 100644 --- a/test/cmdlineTests/model_checker_targets_constant_condition_chc/input.sol +++ b/test/cmdlineTests/model_checker_targets_constant_condition_chc/input.sol @@ -8,7 +8,8 @@ contract test { --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(""); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err b/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err index 3e0027248..b9b84f291 100644 --- a/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err +++ b/test/cmdlineTests/model_checker_targets_div_by_zero_chc/err @@ -1,14 +1,9 @@ -Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. - --> input.sol:10:3: - | -10 | a.transfer(x); - | ^^^^^^^^^^ - Warning: CHC: Division by zero happens here. Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() diff --git a/test/cmdlineTests/model_checker_targets_div_by_zero_chc/input.sol b/test/cmdlineTests/model_checker_targets_div_by_zero_chc/input.sol index 33b5bfab3..0061441c0 100644 --- a/test/cmdlineTests/model_checker_targets_div_by_zero_chc/input.sol +++ b/test/cmdlineTests/model_checker_targets_div_by_zero_chc/input.sol @@ -7,9 +7,10 @@ contract test { --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(""); + require(success); assert(x > 0); arr.pop(); arr[x]; } -} \ No newline at end of file +} diff --git a/test/cmdlineTests/model_checker_targets_error/input.sol b/test/cmdlineTests/model_checker_targets_error/input.sol index 33b5bfab3..0061441c0 100644 --- a/test/cmdlineTests/model_checker_targets_error/input.sol +++ b/test/cmdlineTests/model_checker_targets_error/input.sol @@ -7,9 +7,10 @@ contract test { --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(""); + require(success); assert(x > 0); arr.pop(); arr[x]; } -} \ No newline at end of file +} diff --git a/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err b/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err index 9026ef934..cefc67349 100644 --- a/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err +++ b/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/err @@ -1,20 +1,16 @@ -Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. - --> input.sol:10:3: - | -10 | a.transfer(x); - | ^^^^^^^^^^ - Warning: CHC: Out of bounds access happens here. Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> input.sol:13:3: + a.call{value: x}("") -- untrusted external call + --> input.sol:14:3: | -13 | arr[x]; +14 | arr[x]; | ^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/input.sol b/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/input.sol index 33b5bfab3..0061441c0 100644 --- a/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/input.sol +++ b/test/cmdlineTests/model_checker_targets_out_of_bounds_chc/input.sol @@ -7,9 +7,10 @@ contract test { --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(""); + require(success); assert(x > 0); arr.pop(); arr[x]; } -} \ No newline at end of file +} diff --git a/test/cmdlineTests/model_checker_targets_overflow_chc/err b/test/cmdlineTests/model_checker_targets_overflow_chc/err index 178b59a44..bbaee1778 100644 --- a/test/cmdlineTests/model_checker_targets_overflow_chc/err +++ b/test/cmdlineTests/model_checker_targets_overflow_chc/err @@ -1,14 +1,9 @@ -Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. - --> input.sol:10:3: - | -10 | a.transfer(x); - | ^^^^^^^^^^ - Warning: CHC: Overflow (resulting value larger than 2**256 - 1) happens here. Counterexample: arr = [] a = 0x0 x = 1 +success = false Transaction trace: test.constructor() diff --git a/test/cmdlineTests/model_checker_targets_overflow_chc/input.sol b/test/cmdlineTests/model_checker_targets_overflow_chc/input.sol index 33b5bfab3..0061441c0 100644 --- a/test/cmdlineTests/model_checker_targets_overflow_chc/input.sol +++ b/test/cmdlineTests/model_checker_targets_overflow_chc/input.sol @@ -7,9 +7,10 @@ contract test { --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(""); + require(success); assert(x > 0); arr.pop(); arr[x]; } -} \ No newline at end of file +} diff --git a/test/cmdlineTests/model_checker_targets_pop_empty_chc/err b/test/cmdlineTests/model_checker_targets_pop_empty_chc/err index e4c1bbc0e..78524bd90 100644 --- a/test/cmdlineTests/model_checker_targets_pop_empty_chc/err +++ b/test/cmdlineTests/model_checker_targets_pop_empty_chc/err @@ -1,20 +1,16 @@ -Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. - --> input.sol:10:3: - | -10 | a.transfer(x); - | ^^^^^^^^^^ - Warning: CHC: Empty array "pop" happens here. Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> input.sol:12:3: + a.call{value: x}("") -- untrusted external call + --> input.sol:13:3: | -12 | arr.pop(); +13 | arr.pop(); | ^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_pop_empty_chc/input.sol b/test/cmdlineTests/model_checker_targets_pop_empty_chc/input.sol index 33b5bfab3..0061441c0 100644 --- a/test/cmdlineTests/model_checker_targets_pop_empty_chc/input.sol +++ b/test/cmdlineTests/model_checker_targets_pop_empty_chc/input.sol @@ -7,9 +7,10 @@ contract test { --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(""); + require(success); assert(x > 0); arr.pop(); arr[x]; } -} \ No newline at end of file +} diff --git a/test/cmdlineTests/model_checker_targets_underflow_chc/err b/test/cmdlineTests/model_checker_targets_underflow_chc/err index f9fbf82ee..f24521558 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_chc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_chc/err @@ -1,14 +1,9 @@ -Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. - --> input.sol:10:3: - | -10 | a.transfer(x); - | ^^^^^^^^^^ - Warning: CHC: Underflow (resulting value less than 0) happens here. Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() diff --git a/test/cmdlineTests/model_checker_targets_underflow_chc/input.sol b/test/cmdlineTests/model_checker_targets_underflow_chc/input.sol index 33b5bfab3..0061441c0 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_chc/input.sol +++ b/test/cmdlineTests/model_checker_targets_underflow_chc/input.sol @@ -7,9 +7,10 @@ contract test { --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(""); + require(success); assert(x > 0); arr.pop(); arr[x]; } -} \ No newline at end of file +} diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err index f91c06702..8388d76ed 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/err @@ -1,14 +1,9 @@ -Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. - --> input.sol:10:3: - | -10 | a.transfer(x); - | ^^^^^^^^^^ - Warning: CHC: Underflow (resulting value less than 0) happens here. Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() @@ -24,6 +19,7 @@ Counterexample: arr = [] a = 0x0 x = 1 +success = false Transaction trace: test.constructor() @@ -39,12 +35,14 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> input.sol:11:3: + a.call{value: x}("") -- untrusted external call + --> input.sol:12:3: | -11 | assert(x > 0); +12 | assert(x > 0); | ^^^^^^^^^^^^^ diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/input.sol b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/input.sol index 33b5bfab3..0061441c0 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/input.sol +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_assert_chc/input.sol @@ -7,9 +7,10 @@ contract test { --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(""); + require(success); assert(x > 0); arr.pop(); arr[x]; } -} \ No newline at end of file +} diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err b/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err index 44faa5ae8..5751c9072 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/err @@ -1,14 +1,9 @@ -Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }("")' instead. - --> input.sol:10:3: - | -10 | a.transfer(x); - | ^^^^^^^^^^ - Warning: CHC: Underflow (resulting value less than 0) happens here. Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() @@ -24,6 +19,7 @@ Counterexample: arr = [] a = 0x0 x = 1 +success = false Transaction trace: test.constructor() diff --git a/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/input.sol b/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/input.sol index 33b5bfab3..0061441c0 100644 --- a/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/input.sol +++ b/test/cmdlineTests/model_checker_targets_underflow_overflow_chc/input.sol @@ -7,9 +7,10 @@ contract test { --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(""); + require(success); assert(x > 0); arr.pop(); arr[x]; } -} \ No newline at end of file +} diff --git a/test/cmdlineTests/standard_model_checker_targets_assert_chc/input.json b/test/cmdlineTests/standard_model_checker_targets_assert_chc/input.json index a9a7b3fcd..e28a8d225 100644 --- a/test/cmdlineTests/standard_model_checker_targets_assert_chc/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_assert_chc/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json index d7cfd4a82..6bdd27918 100644 --- a/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_assert_chc/output.json @@ -1,24 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "9207", - "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. - --> A:11:7: - | -11 | \t\t\t\t\t\ta.transfer(x); - | \t\t\t\t\t\t^^^^^^^^^^ - -", - "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", - "severity": "warning", - "sourceLocation": { - "end": 234, - "file": "A", - "start": 224 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "6328", @@ -27,14 +8,16 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> A:12:7: + a.call{value: x}(\"\") -- untrusted external call + --> A:13:7: | -12 | \t\t\t\t\t\tassert(x > 0); +13 | \t\t\t\t\t\tassert(x > 0); | \t\t\t\t\t\t^^^^^^^^^^^^^ ", @@ -43,16 +26,18 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] -test.f(0x0, 1)", +test.f(0x0, 1) + a.call{value: x}(\"\") -- untrusted external call", "severity": "warning", "sourceLocation": { - "end": 258, + "end": 308, "file": "A", - "start": 245 + "start": 295 }, "type": "Warning" } diff --git a/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/input.json b/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/input.json index 365ca122b..a7e2be429 100644 --- a/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json index d6a7b5a4e..f047ff70a 100644 --- a/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_constantCondition_chc/output.json @@ -1,25 +1,4 @@ { - "errors": [ - { - "component": "general", - "errorCode": "9207", - "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. - --> A:11:7: - | -11 | \t\t\t\t\t\ta.transfer(x); - | \t\t\t\t\t\t^^^^^^^^^^ - -", - "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", - "severity": "warning", - "sourceLocation": { - "end": 234, - "file": "A", - "start": 224 - }, - "type": "Warning" - } - ], "sources": { "A": { "id": 0 diff --git a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/input.json b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/input.json index 1c7af8d5c..c7476efac 100644 --- a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json index e5a54e4c8..867decb52 100644 --- a/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_div_by_zero_chc/output.json @@ -1,24 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "9207", - "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. - --> A:11:7: - | -11 | \t\t\t\t\t\ta.transfer(x); - | \t\t\t\t\t\t^^^^^^^^^^ - -", - "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", - "severity": "warning", - "sourceLocation": { - "end": 234, - "file": "A", - "start": 224 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "4281", @@ -27,6 +8,7 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() @@ -43,6 +25,7 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() diff --git a/test/cmdlineTests/standard_model_checker_targets_empty_array/input.json b/test/cmdlineTests/standard_model_checker_targets_empty_array/input.json index cb51e4905..40ccfcbeb 100644 --- a/test/cmdlineTests/standard_model_checker_targets_empty_array/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_empty_array/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/input.json b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/input.json index cd0ba6d13..63ccad902 100644 --- a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json index ecb01eac3..80d919066 100644 --- a/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_out_of_bounds_chc/output.json @@ -1,24 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "9207", - "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. - --> A:11:7: - | -11 | \t\t\t\t\t\ta.transfer(x); - | \t\t\t\t\t\t^^^^^^^^^^ - -", - "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", - "severity": "warning", - "sourceLocation": { - "end": 234, - "file": "A", - "start": 224 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "6368", @@ -27,14 +8,16 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> A:14:7: + a.call{value: x}(\"\") -- untrusted external call + --> A:15:7: | -14 | \t\t\t\t\t\tarr[x]; +15 | \t\t\t\t\t\tarr[x]; | \t\t\t\t\t\t^^^^^^ ", @@ -43,16 +26,18 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] -test.f(0x0, 1)", +test.f(0x0, 1) + a.call{value: x}(\"\") -- untrusted external call", "severity": "warning", "sourceLocation": { - "end": 289, + "end": 339, "file": "A", - "start": 283 + "start": 333 }, "type": "Warning" } diff --git a/test/cmdlineTests/standard_model_checker_targets_overflow_chc/input.json b/test/cmdlineTests/standard_model_checker_targets_overflow_chc/input.json index 522d2480c..0141cbdb0 100644 --- a/test/cmdlineTests/standard_model_checker_targets_overflow_chc/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_overflow_chc/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json index 1b0078d57..6180cdef7 100644 --- a/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_overflow_chc/output.json @@ -1,24 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "9207", - "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. - --> A:11:7: - | -11 | \t\t\t\t\t\ta.transfer(x); - | \t\t\t\t\t\t^^^^^^^^^^ - -", - "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", - "severity": "warning", - "sourceLocation": { - "end": 234, - "file": "A", - "start": 224 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "4984", @@ -27,6 +8,7 @@ Counterexample: arr = [] a = 0x0 x = 1 +success = false Transaction trace: test.constructor() @@ -43,6 +25,7 @@ Counterexample: arr = [] a = 0x0 x = 1 +success = false Transaction trace: test.constructor() diff --git a/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/input.json b/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/input.json index 7d2dc69e3..430201dbf 100644 --- a/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json index 6ac6acd96..ee0e0a6ef 100644 --- a/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_pop_empty_chc/output.json @@ -1,24 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "9207", - "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. - --> A:11:7: - | -11 | \t\t\t\t\t\ta.transfer(x); - | \t\t\t\t\t\t^^^^^^^^^^ - -", - "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", - "severity": "warning", - "sourceLocation": { - "end": 234, - "file": "A", - "start": 224 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "2529", @@ -27,14 +8,16 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> A:13:7: + a.call{value: x}(\"\") -- untrusted external call + --> A:14:7: | -13 | \t\t\t\t\t\tarr.pop(); +14 | \t\t\t\t\t\tarr.pop(); | \t\t\t\t\t\t^^^^^^^^^ ", @@ -43,16 +26,18 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] -test.f(0x0, 1)", +test.f(0x0, 1) + a.call{value: x}(\"\") -- untrusted external call", "severity": "warning", "sourceLocation": { - "end": 275, + "end": 325, "file": "A", - "start": 266 + "start": 316 }, "type": "Warning" } diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_chc/input.json b/test/cmdlineTests/standard_model_checker_targets_underflow_chc/input.json index ca33d2fdc..e590fcd4d 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_chc/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_chc/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json index 67218582b..373646fa7 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_chc/output.json @@ -1,24 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "9207", - "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. - --> A:11:7: - | -11 | \t\t\t\t\t\ta.transfer(x); - | \t\t\t\t\t\t^^^^^^^^^^ - -", - "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", - "severity": "warning", - "sourceLocation": { - "end": 234, - "file": "A", - "start": 224 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "3944", @@ -27,6 +8,7 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() @@ -43,6 +25,7 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/input.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/input.json index 50f0e82dc..6d4ad0c74 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json index 8f28e7961..0ab2d1d98 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_assert_chc/output.json @@ -1,24 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "9207", - "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. - --> A:11:7: - | -11 | \t\t\t\t\t\ta.transfer(x); - | \t\t\t\t\t\t^^^^^^^^^^ - -", - "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", - "severity": "warning", - "sourceLocation": { - "end": 234, - "file": "A", - "start": 224 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "3944", @@ -27,6 +8,7 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() @@ -43,6 +25,7 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() @@ -64,6 +47,7 @@ Counterexample: arr = [] a = 0x0 x = 1 +success = false Transaction trace: test.constructor() @@ -80,6 +64,7 @@ Counterexample: arr = [] a = 0x0 x = 1 +success = false Transaction trace: test.constructor() @@ -101,14 +86,16 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] test.f(0x0, 1) - --> A:12:7: + a.call{value: x}(\"\") -- untrusted external call + --> A:13:7: | -12 | \t\t\t\t\t\tassert(x > 0); +13 | \t\t\t\t\t\tassert(x > 0); | \t\t\t\t\t\t^^^^^^^^^^^^^ ", @@ -117,16 +104,18 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = true Transaction trace: test.constructor() State: arr = [] -test.f(0x0, 1)", +test.f(0x0, 1) + a.call{value: x}(\"\") -- untrusted external call", "severity": "warning", "sourceLocation": { - "end": 258, + "end": 308, "file": "A", - "start": 245 + "start": 295 }, "type": "Warning" } diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/input.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/input.json index 9fc834fd8..a03420305 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json index 97442455c..44c3d2340 100644 --- a/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json +++ b/test/cmdlineTests/standard_model_checker_targets_underflow_overflow_chc/output.json @@ -1,24 +1,5 @@ { "errors": [ - { - "component": "general", - "errorCode": "9207", - "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead. - --> A:11:7: - | -11 | \t\t\t\t\t\ta.transfer(x); - | \t\t\t\t\t\t^^^^^^^^^^ - -", - "message": "'transfer' is deprecated and scheduled for removal. Use 'call{value: }(\"\")' instead.", - "severity": "warning", - "sourceLocation": { - "end": 234, - "file": "A", - "start": 224 - }, - "type": "Warning" - }, { "component": "general", "errorCode": "3944", @@ -27,6 +8,7 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() @@ -43,6 +25,7 @@ Counterexample: arr = [] a = 0x0 x = 0 +success = false Transaction trace: test.constructor() @@ -64,6 +47,7 @@ Counterexample: arr = [] a = 0x0 x = 1 +success = false Transaction trace: test.constructor() @@ -80,6 +64,7 @@ Counterexample: arr = [] a = 0x0 x = 1 +success = false Transaction trace: test.constructor() diff --git a/test/cmdlineTests/standard_model_checker_targets_wrong_target_types/input.json b/test/cmdlineTests/standard_model_checker_targets_wrong_target_types/input.json index a89271975..3e8b7414f 100644 --- a/test/cmdlineTests/standard_model_checker_targets_wrong_target_types/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_wrong_target_types/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_wrong_target_types_2/input.json b/test/cmdlineTests/standard_model_checker_targets_wrong_target_types_2/input.json index 136ce0978..0f450668d 100644 --- a/test/cmdlineTests/standard_model_checker_targets_wrong_target_types_2/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_wrong_target_types_2/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; diff --git a/test/cmdlineTests/standard_model_checker_targets_wrong_targets/input.json b/test/cmdlineTests/standard_model_checker_targets_wrong_targets/input.json index 1788fb6d5..a2f360675 100644 --- a/test/cmdlineTests/standard_model_checker_targets_wrong_targets/input.json +++ b/test/cmdlineTests/standard_model_checker_targets_wrong_targets/input.json @@ -11,7 +11,8 @@ --x; x + type(uint).max; 2 / x; - a.transfer(x); + (bool success, ) = a.call{value: x}(\"\"); + require(success); assert(x > 0); arr.pop(); arr[x]; From 041b918885a642a28525a3d1f4a2dda3d26f8a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 10 Oct 2025 20:45:01 +0200 Subject: [PATCH 1092/1340] Reword docs about linux packages and add info about Nix --- docs/installing-solidity.rst | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 97a754eaa..f061829ec 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -113,23 +113,34 @@ self-contained (i.e. it does not refer to any external files that would have to Linux Packages ============== -Binary packages of Solidity are available at -`solidity/releases `_. +We provide :ref:`standalone binaries ` of the compiler that should run on most +distributions without any additional installation steps. Ubuntu packages for versions up to 0.8.30 are available in the `ethereum/ethereum PPA `_. However, we have discontinued this distribution method and future versions will not be added there. -Furthermore, some Linux distributions provide their own packages. These packages are not directly -maintained by us but usually kept up-to-date by the respective package maintainers. +Some Linux distributions provide their own packages. +These packages are not directly maintained by us but usually kept up-to-date by the respective +package maintainers. -For example, Arch Linux has packages for the latest development version as AUR packages: `solidity `_ -and `solidity-bin `_. +Unofficial, community-maintained scripts for building and installing the compiler are also +available for some distributions: + +- Arch Linux / (AUR): + + - `solidity `_ (builds from source), + - `solidity-bin `_ (uses our standalone binaries). + +- Nix: + + - `solc.nix `_ (builds from source). .. note:: - Please be aware that `AUR `_ packages - are user-produced content and unofficial packages. Exercise caution when using them. + Please be aware that these scripts are produced and maintained by users and not vetted in any + way by the distro maintainers. + Exercise caution when using them. There is also a `snap package `_, however, it is **currently unmaintained**. It is installable in all the `supported Linux distros `_. To @@ -192,6 +203,8 @@ Install it using ``brew``: # eg. Install 0.4.8 brew install solidity.rb +.. _static-binaries: + Static Binaries =============== From c1975a232f5a77d9ccd38b1fafbb0b3251c88c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 11 May 2024 17:33:03 +0200 Subject: [PATCH 1093/1340] Remove the prerequisite steps from the default optimizer sequence --- Changelog.md | 1 + docs/using-the-compiler.rst | 2 +- libsolidity/interface/OptimiserSettings.h | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index 655e66e54..d1bc022e3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,7 @@ Language Features: Compiler Features: +* Yul Optimizer: Remove redundant prerequisite steps from the default optimizer sequence. Bugfixes: diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 93d61af29..dbc797079 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -349,7 +349,7 @@ Input Description // In particular if the whole value consists only of the delimiter, both sequences are empty. // Note that there are several hard-coded steps that always run, even when both sequences are empty. // For more information see "The Optimizer > Selecting Optimizations". - "optimizerSteps": "dhfoDgvulfnTUtnIf..." + "optimizerSteps": "dfDvulfnTUtnIf..." } } }, diff --git a/libsolidity/interface/OptimiserSettings.h b/libsolidity/interface/OptimiserSettings.h index d282e139d..eec1e42b0 100644 --- a/libsolidity/interface/OptimiserSettings.h +++ b/libsolidity/interface/OptimiserSettings.h @@ -42,7 +42,7 @@ enum class OptimisationPreset struct OptimiserSettings { static char constexpr DefaultYulOptimiserSteps[] = - "dhfoDgvulfnTUtnIf" // None of these can make stack problems worse + "dfDvulfnTUtnIf" // None of these can make stack problems worse "xa[r]EscLM" // Turn into SSA and simplify "Vcul [j]" // Reverse SSA @@ -51,13 +51,13 @@ struct OptimiserSettings "Trpeul" // Run functional expression inliner "xa[r]cL" // Turn into SSA again and simplify - "gvifM" // Run full inliner + "vifM" // Run full inliner "CTUca[r]LSsTFOtfDnca[r]Iulc" // SSA plus simplify "scCTUt" - "gvifM" // Run full inliner + "vifM" // Run full inliner "x[scCTUt] TOntnfDIul" // Perform structural simplification - "gvifM" // Run full inliner + "vifM" // Run full inliner "jmul[jul] VcTOcul jmul"; // Make source short and pretty From 2583eccd17cf70cc8ff984e6866b197d6259fe58 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 6 Jan 2026 12:59:30 +0100 Subject: [PATCH 1094/1340] EVM instruction interpreter: Add support for loadimmutable and setimmutable Theoretically, loadimmutable inserts a placeholder into the contract to be deployed which is then replaced by setimmutable once the runtime code is loaded into memory. The interpreter is mainly used for differential fuzzing so we should satisfy that correct code never fails and we can still detect bugs otherwise, most of the time. Therefore loadimmutable is decoupled from setimmutable and just returns a random value (hash of the identifier), setimmutable is treated as a no-op. --- .../isoltestTesting/loadimmutable.yul | 11 ++++++++++ .../isoltestTesting/setimmutable_stub.yul | 9 +++++++++ .../EVMInstructionInterpreter.cpp | 20 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 test/libyul/yulInterpreterTests/isoltestTesting/loadimmutable.yul create mode 100644 test/libyul/yulInterpreterTests/isoltestTesting/setimmutable_stub.yul diff --git a/test/libyul/yulInterpreterTests/isoltestTesting/loadimmutable.yul b/test/libyul/yulInterpreterTests/isoltestTesting/loadimmutable.yul new file mode 100644 index 000000000..3b13520f1 --- /dev/null +++ b/test/libyul/yulInterpreterTests/isoltestTesting/loadimmutable.yul @@ -0,0 +1,11 @@ +{ + // yields some value based on the hash of the argument literal + let value := loadimmutable("address") + mstore(0, value) +} +// ---- +// Trace: +// Memory dump: +// 0: 421683f821a0574472445355be6d2b769119e8515f8376a1d7878523dfdecf7b +// Storage dump: +// Transient storage dump: diff --git a/test/libyul/yulInterpreterTests/isoltestTesting/setimmutable_stub.yul b/test/libyul/yulInterpreterTests/isoltestTesting/setimmutable_stub.yul new file mode 100644 index 000000000..2becc61b6 --- /dev/null +++ b/test/libyul/yulInterpreterTests/isoltestTesting/setimmutable_stub.yul @@ -0,0 +1,9 @@ +{ + // implemented as no-op + setimmutable(42, "42", 42) +} +// ---- +// Trace: +// Memory dump: +// Storage dump: +// Transient storage dump: diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index cec5d5501..9d46c2b89 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -565,6 +565,26 @@ u256 EVMInstructionInterpreter::evalBuiltin( return 0; } + if (fun == "loadimmutable") + { + yulAssert(_arguments.size() == 1); + yulAssert(std::holds_alternative(_arguments[0])); + std::string const identifier = formatLiteral(std::get(_arguments[0])); + // Return a deterministic value based on the identifier. + // This is sufficient for differential fuzzing since the same identifier + // will always return the same value, maintaining trace equivalence. + return u256(h256(keccak256(identifier))); + } + + if (fun == "setimmutable") + { + yulAssert(_arguments.size() == 3); + // No-op: The real implementation patches placeholder bytes in memory-loaded runtime code. + // For differential fuzzing, this ensures correct code never fails (no false positives), though some + // bugs in setimmutable handling may not be detected (potential false negatives). + return 0; + } + yulAssert(false, "Unknown builtin: " + fun); } From 940aa92a382f210cc0b679fadbd5b8b264ec84ae Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 19 Jan 2026 17:46:35 +0100 Subject: [PATCH 1095/1340] EVMInstruction Interpreter: Improve linkersymbol to not just yield constant 0 --- .../isoltestTesting/linkersymbol.yul | 11 +++++++++++ .../yulInterpreter/EVMInstructionInterpreter.cpp | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 test/libyul/yulInterpreterTests/isoltestTesting/linkersymbol.yul diff --git a/test/libyul/yulInterpreterTests/isoltestTesting/linkersymbol.yul b/test/libyul/yulInterpreterTests/isoltestTesting/linkersymbol.yul new file mode 100644 index 000000000..d7b896c14 --- /dev/null +++ b/test/libyul/yulInterpreterTests/isoltestTesting/linkersymbol.yul @@ -0,0 +1,11 @@ +{ + // yields some value based on the hash of the argument literal + let value := linkersymbol("address") + mstore(0, value) +} +// ---- +// Trace: +// Memory dump: +// 0: 421683f821a0574472445355be6d2b769119e8515f8376a1d7878523dfdecf7b +// Storage dump: +// Transient storage dump: diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index 9d46c2b89..8081a9df6 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -562,7 +562,7 @@ u256 EVMInstructionInterpreter::evalBuiltin( std::string const placeholder = formatLiteral(std::get(_arguments[0])); h256 const identifier(keccak256(placeholder)); m_linkerSymbols.emplace(identifier, placeholder); - return 0; + return u256(identifier); } if (fun == "loadimmutable") From e80f7db293eb32e3a974753c40a45bf5c36c5c72 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Mon, 26 Jan 2026 18:39:25 +0100 Subject: [PATCH 1096/1340] Fix style check to detect misaligned pointer declarations --- scripts/check_style.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/check_style.sh b/scripts/check_style.sh index d67f7b60c..5ea0e07d5 100755 --- a/scripts/check_style.sh +++ b/scripts/check_style.sh @@ -55,7 +55,7 @@ FORMATERROR=$( preparedGrep "^ [^*]|[^*] | [^*]" # uses spaces for indentation or mixes spaces and tabs preparedGrep "[a-zA-Z0-9_]\s*[&][a-zA-Z_]" | grep -E -v "return [&]" # right-aligned reference ampersand (needs to exclude return) # right-aligned reference pointer star (needs to exclude return and comments) - preparedGrep "[a-zA-Z0-9_]\s*[*][a-zA-Z_]" | grep -E -v -e "return [*]" -e "^* [*]" -e "^*//.*" + preparedGrep "[a-zA-Z0-9_]\s*[*][a-zA-Z_]" | grep -E -v -e "return [*]" -e ":[0-9]+:\s*\*\s" -e "//" # unqualified move()/forward() checks, i.e. make sure that std::move() and std::forward() are used instead of move() and forward() preparedGrep "move\(.+\)" | grep -v "std::move" | grep -E "[^a-z]move" preparedGrep "forward\(.+\)" | grep -v "std::forward" | grep -E "[^a-z]forward" From b8d14a5a251e20ec02df329c34519061b697f646 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Mon, 26 Jan 2026 18:41:46 +0100 Subject: [PATCH 1097/1340] Fix pointer declaration alignment style --- libsolidity/analysis/ControlFlowBuilder.h | 2 +- libsolidity/analysis/TypeChecker.cpp | 2 +- libsolidity/ast/Types.cpp | 2 +- libsolidity/codegen/CompilerContext.h | 2 +- libsolidity/codegen/ExpressionCompiler.cpp | 2 +- libyul/backends/evm/StackLayoutGenerator.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libsolidity/analysis/ControlFlowBuilder.h b/libsolidity/analysis/ControlFlowBuilder.h index 7af843fca..92ebe4f88 100644 --- a/libsolidity/analysis/ControlFlowBuilder.h +++ b/libsolidity/analysis/ControlFlowBuilder.h @@ -152,7 +152,7 @@ class ControlFlowBuilder: private ASTConstVisitor, private yul::ASTWalker CFGNode* newLabel(); CFGNode* createLabelHere(); - void placeAndConnectLabel(CFGNode *_node); + void placeAndConnectLabel(CFGNode* _node); CFG::NodeContainer& m_nodeContainer; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 8556487ff..b54e591d2 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1447,7 +1447,7 @@ void TypeChecker::checkExpressionAssignment(Type const& _type, Expression const& { bool isLocalOrReturn = false; if (auto const* identifier = dynamic_cast(&_expression)) - if (auto const *variableDeclaration = dynamic_cast(identifier->annotation().referencedDeclaration)) + if (auto const* variableDeclaration = dynamic_cast(identifier->annotation().referencedDeclaration)) if (variableDeclaration->isLocalOrReturn()) isLocalOrReturn = true; if (!isLocalOrReturn) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 316d99ba3..8454fd130 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3474,7 +3474,7 @@ MemberList::MemberMap FunctionType::nativeMembers(ASTNode const* _scope) const if (auto const* functionDefinition = dynamic_cast(m_declaration)) { solAssert(functionDefinition->visibility() > Visibility::Internal, ""); - auto const *contract = dynamic_cast(m_declaration->scope()); + auto const* contract = dynamic_cast(m_declaration->scope()); solAssert(contract, ""); solAssert(contract->isLibrary(), ""); return {{"selector", TypeProvider::fixedBytes(4)}}; diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 638ee6939..49a996c6c 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -374,7 +374,7 @@ class CompilerContext /// Stack of current visited AST nodes, used for location attachment std::stack m_visitedNodes; /// The runtime context if in Creation mode, this is used for generating tags that would be stored into the storage and then used at runtime. - CompilerContext *m_runtimeContext; + CompilerContext* m_runtimeContext; /// The index of the runtime subroutine. evmasm::SubAssemblyID m_runtimeSub{}; /// An index of low-level function labels by name. diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 2927444e2..49313c892 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -2298,7 +2298,7 @@ bool ExpressionCompiler::visit(IndexRangeAccess const& _indexAccess) Type const& baseType = *_indexAccess.baseExpression().annotation().type; - ArrayType const *arrayType = dynamic_cast(&baseType); + ArrayType const* arrayType = dynamic_cast(&baseType); if (!arrayType) if (ArraySliceType const* sliceType = dynamic_cast(&baseType)) arrayType = &sliceType->arrayType(); diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index f6d1108ee..9a37adeb2 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -371,7 +371,7 @@ void StackLayoutGenerator::processEntryPoint(CFG::BasicBlock const& _entry, CFG: // entry layout of the backwards jump target as the initial exit layout of the backwards-jumping block. while (!toVisit.empty()) { - CFG::BasicBlock const *block = *toVisit.begin(); + CFG::BasicBlock const* block = *toVisit.begin(); toVisit.pop_front(); if (visited.count(block)) From 2eea2ae53c2ebe5e15238c19954d43768afc745e Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Mon, 26 Jan 2026 18:48:31 +0100 Subject: [PATCH 1098/1340] Fix unnecessary escaping in comment exclusion regex --- scripts/check_style.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/check_style.sh b/scripts/check_style.sh index 5ea0e07d5..7188f84f2 100755 --- a/scripts/check_style.sh +++ b/scripts/check_style.sh @@ -59,7 +59,7 @@ FORMATERROR=$( # unqualified move()/forward() checks, i.e. make sure that std::move() and std::forward() are used instead of move() and forward() preparedGrep "move\(.+\)" | grep -v "std::move" | grep -E "[^a-z]move" preparedGrep "forward\(.+\)" | grep -v "std::forward" | grep -E "[^a-z]forward" -) | grep -E -v -e "^[a-zA-Z\./]*:[0-9]*:\s*\/(\/|\*)" -e "^test/" || true +) | grep -E -v -e "^[a-zA-Z./]*:[0-9]*:\s*/[/*]" -e "^test/" || true ) # Special error handling for `using namespace std;` exclusion, since said statement can be present in the test directory From 12004a1a5a3a5c1f0207a1762cb47002cbe2ef10 Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Wed, 28 Jan 2026 10:58:51 +0100 Subject: [PATCH 1099/1340] Refactor ccache build commands into a single `run_with_ccache_unless_tag` command - Remove CCACHE_ENABLED and use CCACHE_DISABLE instead --- .circleci/config.yml | 163 +++++++++++---------------------- scripts/ci/build.sh | 20 ++-- scripts/ci/build_emscripten.sh | 18 ++-- scripts/ci/build_ossfuzz.sh | 20 ++-- scripts/ci/build_win.sh | 52 +++++------ 5 files changed, 97 insertions(+), 176 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1b6a309fc..2fd7fe83a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -75,16 +75,20 @@ commands: event: release condition: on_success - ensure_ccache_key: - description: "Fail fast when CCACHE_KEY is missing." + ensure_ccache_key_unless_tag: + description: "Fail fast when CCACHE_KEY is missing (skipped on tags)." steps: - - run: - name: Check CCACHE_KEY - command: | - if [ -z "${CCACHE_KEY:-}" ]; then - echo "CCACHE_KEY is not set. Please set it in CircleCI environment settings." - exit 1 - fi + - when: + condition: + equal: ["", << pipeline.git.tag >>] + steps: + - run: + name: Check CCACHE_KEY + command: | + if [ -z "${CCACHE_KEY:-}" ]; then + echo "CCACHE_KEY is not set. Please set it in CircleCI environment settings." + exit 1 + fi restore_ccache_if_allowed: description: "Restore ccache unless on a tag or a skipped branch." @@ -123,6 +127,29 @@ commands: key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache-{{ .Revision }} paths: - ~/.ccache + run_with_ccache_unless_tag: + description: "Run a command with ccache enabled unless building a tag." + parameters: + command: + type: string + step_name: + type: string + steps: + - when: + condition: + equal: ["", << pipeline.git.tag >>] + steps: + - run: + name: << parameters.step_name >> (ccache) + command: << parameters.command >> + - when: + condition: + not: + equal: ["", << pipeline.git.tag >>] + steps: + - run: + name: << parameters.step_name >> (no ccache) + command: CCACHE_DISABLE=1 << parameters.command >> prepare_bytecode_report: description: "Generate bytecode report and upload it as an artifact." @@ -257,60 +284,22 @@ commands: run_build: steps: - - when: - condition: - equal: ["", << pipeline.git.tag >>] - steps: - - ensure_ccache_key + - ensure_ccache_key_unless_tag - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - - when: - condition: - and: - - equal: ["", << pipeline.git.tag >>] - steps: - - run: - name: Build (ccache) - command: CCACHE_ENABLED=${CCACHE_ENABLED:-1} scripts/ci/build.sh - - when: - condition: - or: - - not: - equal: ["", << pipeline.git.tag >>] - steps: - - run: - name: Build (no ccache) - command: scripts/ci/build.sh - + - run_with_ccache_unless_tag: + step_name: Build + command: scripts/ci/build.sh - save_ccache_if_develop run_build_ossfuzz: steps: - - when: - condition: - equal: ["", << pipeline.git.tag >>] - steps: - - ensure_ccache_key + - ensure_ccache_key_unless_tag - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - - when: - condition: - and: - - equal: ["", << pipeline.git.tag >>] - steps: - - run: - name: Build_ossfuzz (ccache) - command: CCACHE_ENABLED=${CCACHE_ENABLED:-1} scripts/ci/build_ossfuzz.sh - - when: - condition: - or: - - not: - equal: ["", << pipeline.git.tag >>] - steps: - - run: - name: Build_ossfuzz (no ccache) - command: scripts/ci/build_ossfuzz.sh - + - run_with_ccache_unless_tag: + step_name: Build_ossfuzz + command: scripts/ci/build_ossfuzz.sh - save_ccache_if_develop run_proofs: @@ -1352,32 +1341,12 @@ jobs: MAKEFLAGS: -j 10 steps: - checkout - - when: - condition: - equal: ["", << pipeline.git.tag >>] - steps: - - ensure_ccache_key + - ensure_ccache_key_unless_tag - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - - when: - condition: - and: - - equal: ["", << pipeline.git.tag >>] - steps: - - run: - name: Build (ccache) - command: CCACHE_ENABLED=${CCACHE_ENABLED:-1} scripts/ci/build_emscripten.sh - - when: - condition: - or: - - not: - equal: ["", << pipeline.git.tag >>] - steps: - - run: - name: Build (no ccache) - command: | - scripts/ci/build_emscripten.sh - + - run_with_ccache_unless_tag: + step_name: Build + command: scripts/ci/build_emscripten.sh - save_ccache_if_develop - store_artifacts: path: upload/soljson.js @@ -1855,39 +1824,13 @@ jobs: key: dependencies-win-{{ arch }}-{{ checksum "scripts/install_deps.ps1" }} paths: - .\deps - - when: - condition: - equal: ["", << pipeline.git.tag >>] - steps: - - ensure_ccache_key + - ensure_ccache_key_unless_tag - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - - when: - condition: - and: - - equal: ["", << pipeline.git.tag >>] - steps: - - run: - name: "Building solidity (ccache)" - command: CCACHE_ENABLED=${CCACHE_ENABLED:-1} scripts/ci/build_win.sh - - when: - condition: - or: - - not: - equal: ["", << pipeline.git.tag >>] - steps: - - run: - name: "Building solidity (no ccache)" - command: scripts/ci/build_win.sh - # On `ci-ccache` we always generate a fresh cache by never restoring and by saving under a unique key. - - when: - condition: - equal: ["ci-ccache", << pipeline.git.branch >>] - steps: - - save_cache: - key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache - paths: - - ~/.ccache + - run_with_ccache_unless_tag: + step_name: "Building solidity" + command: scripts/ci/build_win.sh + - save_ccache_if_develop - run: name: "Run solc.exe to make sure build was successful." command: .\build\solc\Release\solc.exe --version diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh index 385d2d898..e31b3f6f0 100755 --- a/scripts/ci/build.sh +++ b/scripts/ci/build.sh @@ -16,23 +16,17 @@ cd build [[ -n $COVERAGE && -z $CIRCLE_TAG ]] && CMAKE_OPTIONS="$CMAKE_OPTIONS -DCOVERAGE=ON" -if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then - export CCACHE_DIR="$HOME/.ccache" - export CCACHE_BASEDIR="$ROOTDIR" - export CCACHE_NOHASHDIR=1 - CMAKE_OPTIONS="${CMAKE_OPTIONS:-} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" - mkdir -p "$CCACHE_DIR" -fi +export CCACHE_DIR="$HOME/.ccache" +export CCACHE_BASEDIR="$ROOTDIR" +export CCACHE_NOHASHDIR=1 +CMAKE_OPTIONS="${CMAKE_OPTIONS:-} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" +mkdir -p "$CCACHE_DIR" # shellcheck disable=SC2086 cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" $CMAKE_OPTIONS -if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then - ccache -z -fi +ccache -z cmake --build . -if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then - ccache -s -fi +ccache -s diff --git a/scripts/ci/build_emscripten.sh b/scripts/ci/build_emscripten.sh index bf19bad36..035eedccb 100755 --- a/scripts/ci/build_emscripten.sh +++ b/scripts/ci/build_emscripten.sh @@ -54,14 +54,12 @@ function build() { # TODO: This can be removed if and when all usages of `move()` in our codebase use the `std::` qualifier. CMAKE_CXX_FLAGS="-Wno-unqualified-std-cast-call" - if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then - export CCACHE_DIR="$HOME/.ccache" - CCACHE_BASEDIR="$(pwd)" - export CCACHE_BASEDIR - export CCACHE_NOHASHDIR=1 - mkdir -p "$CCACHE_DIR" - ccache -z - fi + export CCACHE_DIR="$HOME/.ccache" + CCACHE_BASEDIR="$(pwd)" + export CCACHE_BASEDIR + export CCACHE_NOHASHDIR=1 + mkdir -p "$CCACHE_DIR" + ccache -z mkdir -p "$build_dir" cd "$build_dir" @@ -73,9 +71,7 @@ function build() { -DTESTS=0 \ .. make soljson - if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then - ccache -s - fi + ccache -s cd .. mkdir -p upload diff --git a/scripts/ci/build_ossfuzz.sh b/scripts/ci/build_ossfuzz.sh index 883c939b8..f3e65d22d 100755 --- a/scripts/ci/build_ossfuzz.sh +++ b/scripts/ci/build_ossfuzz.sh @@ -18,24 +18,18 @@ function generate_protobuf_bindings function build_fuzzers { cd "${BUILDDIR}" - if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then - export CCACHE_DIR="$HOME/.ccache" - export CCACHE_BASEDIR="$ROOTDIR" - export CCACHE_NOHASHDIR=1 - CMAKE_OPTIONS="${CMAKE_OPTIONS:-} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" - mkdir -p "$CCACHE_DIR" - fi + export CCACHE_DIR="$HOME/.ccache" + export CCACHE_BASEDIR="$ROOTDIR" + export CCACHE_NOHASHDIR=1 + CMAKE_OPTIONS="${CMAKE_OPTIONS:-} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" + mkdir -p "$CCACHE_DIR" # shellcheck disable=SC2086 cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" \ -DCMAKE_TOOLCHAIN_FILE="${ROOTDIR}"/cmake/toolchains/libfuzzer.cmake \ $CMAKE_OPTIONS - if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then - ccache -z - fi + ccache -z make ossfuzz ossfuzz_proto ossfuzz_abiv2 -j 4 - if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then - ccache -s - fi + ccache -s } generate_protobuf_bindings diff --git a/scripts/ci/build_win.sh b/scripts/ci/build_win.sh index 07604c8eb..bd464647e 100755 --- a/scripts/ci/build_win.sh +++ b/scripts/ci/build_win.sh @@ -11,29 +11,27 @@ CMAKE_VS_GLOBALS_ARG=() cd "$ROOTDIR" "${ROOTDIR}/scripts/prerelease_suffix.sh" "$prerelease_source" "$CIRCLE_TAG" > prerelease.txt -if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then - export CCACHE_DIR="$HOME/.ccache" - export CCACHE_BASEDIR="$ROOTDIR" - export CCACHE_NOHASHDIR=1 - export CCACHE_COMPILERTYPE=msvc - VSWHERE="${VSWHERE:-C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe}" - VS_INSTALL="$("$VSWHERE" -latest -products "*" \ - -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 \ - -property installationPath | tr -d '\r')" - VCTOOLS_VERSION="$(tr -d '\r' < "$VS_INSTALL/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt")" - CCACHE_COMPILER="$VS_INSTALL/VC/Tools/MSVC/$VCTOOLS_VERSION/bin/Hostx64/x64/cl.exe" - CCACHE_COMPILER="${CCACHE_COMPILER//\\//}" - export CCACHE_COMPILER - PATH="$ROOTDIR/deps/ccache:$(dirname "$CCACHE_COMPILER"):$PATH" - export PATH - # Use a Windows-style path for Visual Studio globals. - WIN_PWD="$(pwd -W)" - # Visual Studio generator doesn't use compiler launchers; use ccache masquerade. - # See https://github.com/ccache/ccache/wiki/MS-Visual-Studio - CMAKE_VS_GLOBALS="CLToolPath=${WIN_PWD}/deps/ccache;UseMultiToolTask=true" - CMAKE_VS_GLOBALS_ARG=(-DCMAKE_VS_GLOBALS="$CMAKE_VS_GLOBALS") - mkdir -p "$CCACHE_DIR" -fi +export CCACHE_DIR="$HOME/.ccache" +export CCACHE_BASEDIR="$ROOTDIR" +export CCACHE_NOHASHDIR=1 +export CCACHE_COMPILERTYPE=msvc +VSWHERE="${VSWHERE:-C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe}" +VS_INSTALL="$("$VSWHERE" -latest -products "*" \ + -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 \ + -property installationPath | tr -d '\r')" +VCTOOLS_VERSION="$(tr -d '\r' < "$VS_INSTALL/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt")" +CCACHE_COMPILER="$VS_INSTALL/VC/Tools/MSVC/$VCTOOLS_VERSION/bin/Hostx64/x64/cl.exe" +CCACHE_COMPILER="${CCACHE_COMPILER//\\//}" +export CCACHE_COMPILER +PATH="$ROOTDIR/deps/ccache:$(dirname "$CCACHE_COMPILER"):$PATH" +export PATH +# Use a Windows-style path for Visual Studio globals. +WIN_PWD="$(pwd -W)" +# Visual Studio generator doesn't use compiler launchers; use ccache masquerade. +# See https://github.com/ccache/ccache/wiki/MS-Visual-Studio +CMAKE_VS_GLOBALS="CLToolPath=${WIN_PWD}/deps/ccache;UseMultiToolTask=true" +CMAKE_VS_GLOBALS_ARG=(-DCMAKE_VS_GLOBALS="$CMAKE_VS_GLOBALS") +mkdir -p "$CCACHE_DIR" mkdir -p build/ cd build/ @@ -50,9 +48,7 @@ boost_dir=("${ROOTDIR}/deps/boost/lib/cmake/Boost-"*) "${CMAKE_VS_GLOBALS_ARG[@]}" \ ${CMAKE_OPTIONS:-} \ .. -if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then - ccache -z -fi +ccache -z MSBuild.exe solidity.sln \ -property:Configuration=Release \ -maxCpuCount:10 \ @@ -62,6 +58,4 @@ MSBuild.exe solidity.sln \ -j 10 \ --target install \ --config Release -if [[ "${CCACHE_ENABLED:-}" == "1" ]]; then - ccache -s -fi +ccache -s From 81070d39868353ddada3f6c37ce052061f14ebec Mon Sep 17 00:00:00 2001 From: cui Date: Thu, 29 Jan 2026 16:41:30 +0800 Subject: [PATCH 1100/1340] perf: opt SimplePeepholeOptimizerMethod (#16426) perf: opt SimplePeepholeOptimizerMethod --- libevmasm/PeepholeOptimiser.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 267700e45..7cd7c5e96 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -117,9 +117,10 @@ struct OpPop: SimplePeepholeOptimizerMethod if (_pop == Instruction::POP && _op.type() == Operation) { Instruction instr = _op.instruction(); - if (instructionInfo(instr, langutil::EVMVersion()).ret == 1 && !instructionInfo(instr, langutil::EVMVersion()).sideEffects) + auto const& info = instructionInfo(instr, langutil::EVMVersion()); + if (info.ret == 1 && !info.sideEffects) { - for (int j = 0; j < instructionInfo(instr, langutil::EVMVersion()).args; j++) + for (int j = 0; j < info.args; j++) *_out = {Instruction::POP, _op.debugData()}; return true; } From 04833a570c6f01f2f7f1a9d853321c327a66283b Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Mon, 2 Feb 2026 11:35:17 +0100 Subject: [PATCH 1101/1340] Update ccache commands to use 'develop' branch instead of 'ci-ccache' --- .circleci/config.yml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2fd7fe83a..8e4cd2fbf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -93,12 +93,10 @@ commands: restore_ccache_if_allowed: description: "Restore ccache unless on a tag or a skipped branch." parameters: - # TODO: remove the line below - # Before merging this PR we need to use an alternative develop branch to test the functionality, `ci-ccache` skip_branches_regex: description: "Regex of branches that should skip restoring the cache." type: string - default: "^(ci-ccache|breaking)$" + default: "^(develop|breaking)$" steps: # Tags always skip ccache. Selected branches intentionally start from scratch. - when: @@ -112,19 +110,19 @@ commands: steps: - restore_cache: keys: - # Reuse cache produced on ci-ccache (prefix match; restores the most recent). - - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache- + # Reuse cache produced on develop (prefix match; restores the most recent). + - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-develop- save_ccache_if_develop: - description: "Save a fresh ccache only on the ci-ccache branch." + description: "Save a fresh ccache only on the develop branch." steps: - # On `ci-ccache` we always generate a fresh cache by never restoring and by saving under a unique key. + # On `develop` we always generate a fresh cache by never restoring and by saving under a unique key. - when: condition: - equal: ["ci-ccache", << pipeline.git.branch >>] + equal: ["develop", << pipeline.git.branch >>] steps: - save_cache: - key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-ci-ccache-{{ .Revision }} + key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-develop-{{ .Revision }} paths: - ~/.ccache run_with_ccache_unless_tag: From 21e284ee234c6f5ae972ca66762ef0f7f1e578bd Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Fri, 19 Dec 2025 23:14:27 -0300 Subject: [PATCH 1102/1340] evmasm: Remove unused return value from `clearStorageLoop()` --- libsolidity/codegen/ArrayUtils.cpp | 16 +++++++--------- libsolidity/codegen/ArrayUtils.h | 2 +- .../array/copying/array_copy_including_array.sol | 8 ++++---- .../array/delete/delete_storage_array_packed.sol | 4 ++-- .../semanticTests/array/fixed_array_cleanup.sol | 4 ++-- .../array/pop/array_pop_array_transition.sol | 4 ++-- .../storage_boundary_delete_overflow_bug.sol | 4 ++-- ...storage_boundary_struct_array_mixed_types.sol | 4 ++-- .../storage_boundary_struct_array_multislot.sol | 4 ++-- .../structs/struct_delete_storage_with_array.sol | 8 ++++---- .../userDefinedValueType/calldata.sol | 8 ++++---- 11 files changed, 32 insertions(+), 34 deletions(-) diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index 841161fa9..80ee9553c 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -402,7 +402,6 @@ void ArrayUtils::clearArray(ArrayType const& _typeIn) const ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256()); else ArrayUtils(_context).clearStorageLoop(_type.baseType()); - _context << Instruction::POP; } solAssert(_context.stackHeight() == stackHeightStart - 2, ""); } @@ -425,9 +424,10 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const // stack: ref old_length m_context << Instruction::DUP1 << u256(31) << Instruction::LT; evmasm::AssemblyItem longByteArray = m_context.appendConditionalJump(); - m_context << Instruction::POP; + // Short byte array: no data slots to clear, just pop and exit + m_context << Instruction::POP << Instruction::POP; m_context.appendJumpTo(endTag); - m_context.adjustStackOffset(1); // needed because of jump + m_context.adjustStackOffset(2); // the longByteArray path has 2 more items on stack m_context << longByteArray; } // stack: ref old_length @@ -444,7 +444,6 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const clearStorageLoop(_type.baseType()); // cleanup m_context << endTag; - m_context << Instruction::POP; } void ArrayUtils::incrementDynamicArraySize(ArrayType const& _type) const @@ -585,13 +584,13 @@ void ArrayUtils::clearStorageLoop(Type const* _type) const m_context.callLowLevelFunction( "$clearStorageLoop_" + _type->identifier(), 2, - 1, + 0, [_type](CompilerContext& _context) { unsigned stackHeightStart = _context.stackHeight(); if (_type->category() == Type::Category::Mapping) { - _context << Instruction::POP; + _context << Instruction::POP << Instruction::POP; return; } // stack: start_pos slot_count @@ -618,9 +617,8 @@ void ArrayUtils::clearStorageLoop(Type const* _type) const // cleanup _context << zeroLoopEnd; // stack: start_pos slot_count i - _context << Instruction::POP << Instruction::POP; - // stack: start_pos - solAssert(_context.stackHeight() == stackHeightStart - 1, ""); + _context << Instruction::POP << Instruction::POP << Instruction::POP; + solAssert(_context.stackHeight() == stackHeightStart - 2, ""); } ); } diff --git a/libsolidity/codegen/ArrayUtils.h b/libsolidity/codegen/ArrayUtils.h index a62df8a7b..a5eda28f5 100644 --- a/libsolidity/codegen/ArrayUtils.h +++ b/libsolidity/codegen/ArrayUtils.h @@ -74,7 +74,7 @@ class ArrayUtils void popStorageArrayElement(ArrayType const& _type) const; /// Appends a loop that clears a sequence of storage slots of the given type. /// Stack pre: start_ref slot_count - /// Stack post: start_ref + /// Stack post: void clearStorageLoop(Type const* _type) const; /// Converts length to size (number of storage slots or calldata/memory bytes). /// if @a _pad then add padding to multiples of 32 bytes for calldata/memory. diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol index ba50c7300..5f1dae910 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol @@ -36,11 +36,11 @@ contract c { // ---- // test() -> 0x02000202 // gas irOptimized: 4560468 -// gas legacy: 4536566 -// gas legacyOptimized: 4456759 +// gas legacy: 4536539 +// gas legacyOptimized: 4456732 // storageEmpty -> 1 // clear() -> 0, 0 // gas irOptimized: 4488719 -// gas legacy: 4407780 -// gas legacyOptimized: 4385089 +// gas legacy: 4407759 +// gas legacyOptimized: 4385068 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol b/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol index 23b0466e7..cf416c16d 100644 --- a/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol +++ b/test/libsolidity/semanticTests/array/delete/delete_storage_array_packed.sol @@ -15,5 +15,5 @@ contract C { // ---- // f() -> 0, 0, 0 // gas irOptimized: 88028 -// gas legacy: 88799 -// gas legacyOptimized: 87706 +// gas legacy: 88796 +// gas legacyOptimized: 87704 diff --git a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol index af0ec6b7f..86484ecde 100644 --- a/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol +++ b/test/libsolidity/semanticTests/array/fixed_array_cleanup.sol @@ -16,6 +16,6 @@ contract c { // storageEmpty -> 0 // clear() -> // gas irOptimized: 97800 -// gas legacy: 97947 -// gas legacyOptimized: 97882 +// gas legacy: 97944 +// gas legacyOptimized: 97880 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol b/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol index 3b9639716..ed4e9b877 100644 --- a/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol +++ b/test/libsolidity/semanticTests/array/pop/array_pop_array_transition.sol @@ -24,6 +24,6 @@ contract c { // ---- // test() -> 1, 2, 3 // gas irOptimized: 1828383 -// gas legacy: 1841995 -// gas legacyOptimized: 1821687 +// gas legacy: 1841877 +// gas legacyOptimized: 1821569 // storageEmpty -> 1 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_delete_overflow_bug.sol b/test/libsolidity/semanticTests/storage/storage_boundary_delete_overflow_bug.sol index 3ffb77747..09aae988e 100644 --- a/test/libsolidity/semanticTests/storage/storage_boundary_delete_overflow_bug.sol +++ b/test/libsolidity/semanticTests/storage/storage_boundary_delete_overflow_bug.sol @@ -72,8 +72,8 @@ contract C { // gas legacyOptimized: 598016 // clearArray() // gas irOptimized: 580378 -// gas legacy: 582976 -// gas legacyOptimized: 581290 +// gas legacy: 582973 +// gas legacyOptimized: 581299 // x() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // gas irOptimized: 604108 // gas legacy: 644983 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol index 213dee1da..444f86286 100644 --- a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol +++ b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_mixed_types.sol @@ -159,8 +159,8 @@ contract C { // gas legacyOptimized: 112505 // deleteBoundaryArray() // gas irOptimized: 177968 -// gas legacy: 180997 -// gas legacyOptimized: 178175 +// gas legacy: 180995 +// gas legacyOptimized: 178182 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // gas irOptimized: 113169 diff --git a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol index 55e36cd08..05ad53cf0 100644 --- a/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol +++ b/test/libsolidity/semanticTests/storage/storage_boundary_struct_array_multislot.sol @@ -121,8 +121,8 @@ contract C { // destArray() -> 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 // deleteBoundaryArray() // gas irOptimized: 137824 -// gas legacy: 137973 -// gas legacyOptimized: 137743 +// gas legacy: 137971 +// gas legacyOptimized: 137750 // canaryValue() -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // boundaryArray() -> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // destArray() -> 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 diff --git a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol index cd49ea27a..7ae78437e 100644 --- a/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol +++ b/test/libsolidity/semanticTests/structs/struct_delete_storage_with_array.sol @@ -43,9 +43,9 @@ contract C { // ---- // f() -> // gas irOptimized: 113388 -// gas legacy: 113588 -// gas legacyOptimized: 113104 +// gas legacy: 113583 +// gas legacyOptimized: 113119 // g() -> // gas irOptimized: 118768 -// gas legacy: 118766 -// gas legacyOptimized: 118188 +// gas legacy: 118761 +// gas legacyOptimized: 118203 diff --git a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol index 03c6e11bc..63f1ff1dd 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/calldata.sol @@ -50,12 +50,12 @@ contract C { // ---- // test_f() -> true // gas irOptimized: 122114 -// gas legacy: 126162 -// gas legacyOptimized: 122757 +// gas legacy: 126159 +// gas legacyOptimized: 122742 // test_g() -> true // gas irOptimized: 106248 -// gas legacy: 111824 -// gas legacyOptimized: 106606 +// gas legacy: 111821 +// gas legacyOptimized: 106591 // addresses(uint256): 0 -> 0x18 // addresses(uint256): 1 -> 0x19 // addresses(uint256): 3 -> 0x1b From cd1472967ce453feadbc8c3822559c1ece5acd17 Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Mon, 2 Feb 2026 15:55:24 +0100 Subject: [PATCH 1103/1340] Remove CCACHE_KEY from cache keys in CircleCI config --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8e4cd2fbf..70060258a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -111,7 +111,7 @@ commands: - restore_cache: keys: # Reuse cache produced on develop (prefix match; restores the most recent). - - v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-develop- + - v1-ccache-{{ .Environment.CIRCLE_JOB }}-develop- save_ccache_if_develop: description: "Save a fresh ccache only on the develop branch." @@ -122,7 +122,7 @@ commands: equal: ["develop", << pipeline.git.branch >>] steps: - save_cache: - key: v1-{{ .Environment.CCACHE_KEY }}-ccache-{{ .Environment.CIRCLE_JOB }}-develop-{{ .Revision }} + key: v1-ccache-{{ .Environment.CIRCLE_JOB }}-develop-{{ .Revision }} paths: - ~/.ccache run_with_ccache_unless_tag: From b8e0364bb678ffca2090becdeb6c48b13339abbb Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Mon, 2 Feb 2026 16:13:41 +0100 Subject: [PATCH 1104/1340] Remove `ensure_ccache_key_unless_tag` and its usages --- .circleci/config.yml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 70060258a..ff4246399 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -75,21 +75,6 @@ commands: event: release condition: on_success - ensure_ccache_key_unless_tag: - description: "Fail fast when CCACHE_KEY is missing (skipped on tags)." - steps: - - when: - condition: - equal: ["", << pipeline.git.tag >>] - steps: - - run: - name: Check CCACHE_KEY - command: | - if [ -z "${CCACHE_KEY:-}" ]; then - echo "CCACHE_KEY is not set. Please set it in CircleCI environment settings." - exit 1 - fi - restore_ccache_if_allowed: description: "Restore ccache unless on a tag or a skipped branch." parameters: @@ -282,7 +267,6 @@ commands: run_build: steps: - - ensure_ccache_key_unless_tag - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - run_with_ccache_unless_tag: @@ -292,7 +276,6 @@ commands: run_build_ossfuzz: steps: - - ensure_ccache_key_unless_tag - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - run_with_ccache_unless_tag: @@ -1339,7 +1322,6 @@ jobs: MAKEFLAGS: -j 10 steps: - checkout - - ensure_ccache_key_unless_tag - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - run_with_ccache_unless_tag: @@ -1822,7 +1804,6 @@ jobs: key: dependencies-win-{{ arch }}-{{ checksum "scripts/install_deps.ps1" }} paths: - .\deps - - ensure_ccache_key_unless_tag - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings - run_with_ccache_unless_tag: From eb3dc0c425d5e6b462fb6737fe0e1793df13c87c Mon Sep 17 00:00:00 2001 From: Marco Castignoli Date: Mon, 2 Feb 2026 16:24:44 +0100 Subject: [PATCH 1105/1340] Fix comment for resetting ccache --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ff4246399..27a331cd7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -268,7 +268,7 @@ commands: run_build: steps: - restore_ccache_if_allowed - # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings + # WARNING! If you edit anything between here and save_cache, remember to invalidate the cache manually by bumping the version - run_with_ccache_unless_tag: step_name: Build command: scripts/ci/build.sh @@ -277,7 +277,7 @@ commands: run_build_ossfuzz: steps: - restore_ccache_if_allowed - # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings + # WARNING! If you edit anything between here and save_cache, remember to invalidate the cache manually by bumping the version - run_with_ccache_unless_tag: step_name: Build_ossfuzz command: scripts/ci/build_ossfuzz.sh @@ -1323,7 +1323,7 @@ jobs: steps: - checkout - restore_ccache_if_allowed - # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings + # WARNING! If you edit anything between here and save_cache, remember to invalidate the cache manually by bumping the version - run_with_ccache_unless_tag: step_name: Build command: scripts/ci/build_emscripten.sh @@ -1805,7 +1805,7 @@ jobs: paths: - .\deps - restore_ccache_if_allowed - # WARNING! If you edit anything between here and save_cache, remember to bump the CCACHE_KEY version in CircleCI environment settings + # WARNING! If you edit anything between here and save_cache, remember to invalidate the cache manually by bumping the version - run_with_ccache_unless_tag: step_name: "Building solidity" command: scripts/ci/build_win.sh From abeaab4409e10ac03f644d71f176e98a7d935177 Mon Sep 17 00:00:00 2001 From: Jacopo Pierantozzi Date: Thu, 29 Jan 2026 12:47:03 +0100 Subject: [PATCH 1106/1340] Clarify remapping rules in path-resolution documentation --- docs/path-resolution.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/path-resolution.rst b/docs/path-resolution.rst index 492959bc1..2339a3624 100644 --- a/docs/path-resolution.rst +++ b/docs/path-resolution.rst @@ -629,9 +629,9 @@ Here are the detailed rules governing the behavior of remappings: #. **At most one remapping is applied to a single import.** - - If multiple remappings match the same source unit name, the one with the longest matching - prefix is chosen. - - If prefixes are identical, the one specified last wins. + - If multiple remappings match the same source unit name, the one with the longest matching context is chosen. + - If contexts are identical, the one with the longest matching prefix is chosen. + - If contexts and prefixes are identical, the one specified last wins. - Remappings do not work on other remappings. For example ``a=b b=c c=d`` will not result in ``a`` being remapped to ``d``. From cf1a3b07aba8c6588bba8bb8827ed0632ed0bbb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 26 Apr 2025 00:54:14 +0200 Subject: [PATCH 1107/1340] EVMAssemblyTest: Warn about custom expectedExecutionsPerDeployment having no effect --- test/libevmasm/EVMAssemblyTest.cpp | 11 +++++++++++ test/libevmasm/EVMAssemblyTest.h | 1 + 2 files changed, 12 insertions(+) diff --git a/test/libevmasm/EVMAssemblyTest.cpp b/test/libevmasm/EVMAssemblyTest.cpp index 0c1dbb07e..3bc43b188 100644 --- a/test/libevmasm/EVMAssemblyTest.cpp +++ b/test/libevmasm/EVMAssemblyTest.cpp @@ -78,10 +78,13 @@ EVMAssemblyTest::EVMAssemblyTest(std::string const& _filename): "none" ); m_optimizerSettings = Assembly::OptimiserSettings::translateSettings(OptimiserSettings::preset(optimizationPreset)); + size_t defaultExpectedExecutionsPerDeployment = m_optimizerSettings.expectedExecutionsPerDeployment; m_optimizerSettings.expectedExecutionsPerDeployment = m_reader.sizetSetting( "optimizer.expectedExecutionsPerDeployment", m_optimizerSettings.expectedExecutionsPerDeployment ); + m_usingDefaultExpectedExecutionsPerDeployment = + m_optimizerSettings.expectedExecutionsPerDeployment == defaultExpectedExecutionsPerDeployment; auto const optimizerComponentSetting = [&](std::string const& _component, bool& _setting) { _setting = m_reader.boolSetting("optimizer." + _component, _setting); @@ -132,6 +135,14 @@ TestCase::TestResult EVMAssemblyTest::run(std::ostream& _stream, std::string con return checkResult(_stream, _linePrefix, _formatted); } + soltestAssert(evmAssemblyStack.evmAssembly()); + if (!m_usingDefaultExpectedExecutionsPerDeployment && evmAssemblyStack.evmAssembly()->numSubs() == 0) + // This is a common mistake. We can't issue a warning here, so let's report it as an error. + BOOST_THROW_EXCEPTION(std::runtime_error( + "The custom value specified for optimizer.expectedExecutionsPerDeployment has no effect " + "on the creation assembly, which is the only assembly in the test." + )); + try { evmAssemblyStack.assemble(); diff --git a/test/libevmasm/EVMAssemblyTest.h b/test/libevmasm/EVMAssemblyTest.h index 9059fd716..9a276ddeb 100644 --- a/test/libevmasm/EVMAssemblyTest.h +++ b/test/libevmasm/EVMAssemblyTest.h @@ -75,6 +75,7 @@ class EVMAssemblyTest: public frontend::test::EVMVersionRestrictedTestCase AssemblyFormat m_assemblyFormat{}; std::string m_selectedOutputs; evmasm::Assembly::OptimiserSettings m_optimizerSettings; + bool m_usingDefaultExpectedExecutionsPerDeployment{}; }; } From f0486ba76b6ba4c3ff9b7892026b652036ca8fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 2 Feb 2026 17:54:09 +0100 Subject: [PATCH 1108/1340] CI: Move constantinople and petersburg EVM runs back from nightly to the main workflow --- .circleci/config.yml | 2 +- .circleci/soltest_all.sh | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 27a331cd7..55f12f669 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1400,7 +1400,7 @@ jobs: - attach_workspace: at: build - run_soltest_all: - evm_versions: homestead byzantium constantinople petersburg + evm_versions: homestead byzantium - store_test_results: path: test_results/ - store_artifacts_test_results diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index effbc33da..6f8ea14f3 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -31,7 +31,18 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" -DEFAULT_EVM_VALUES=(istanbul berlin london paris shanghai cancun prague osaka) +DEFAULT_EVM_VALUES=( + constantinople + petersburg + istanbul + berlin + london + paris + shanghai + cancun + prague + osaka +) EVMS_WITH_EOF=(osaka) # Deserialize the EVM_VALUES array if it was provided as argument or From fc639436584ddbdbf517cf1e12bbeff3bfda38f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 2 Feb 2026 18:05:34 +0100 Subject: [PATCH 1109/1340] CI: Replace homestead with prague and petersburg in the nightly run - homestead is useful on PRs while prague and petersburg did not introduce any changes in EVM behavior - Rename the job and explain why we're doing it --- .circleci/config.yml | 19 +++++++++++++++---- .circleci/soltest_all.sh | 3 +-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 55f12f669..1ca83b526 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -299,7 +299,7 @@ commands: run_soltest_all: parameters: # NOTE: If not specified, soltest_all.sh will use the default values as specified in the script. - # In other words, it will execute for all EVM versions that are not marked as deprecated. + # In other words, it will execute for all EVM versions that are not marked as low priority. evm_versions: description: "List of EVM versions (separated by space)." type: string @@ -1392,7 +1392,7 @@ jobs: - store_artifacts_test_results - matrix_notify_failure_unless_pr - t_ubu_soltest_deprecated_evm_versions: &t_ubu_soltest_deprecated_evm_versions + t_ubu_soltest_low_priority_evm_versions: &t_ubu_soltest_low_priority_evm_versions <<: *base_ubuntu2404_large parallelism: 50 steps: @@ -1400,7 +1400,18 @@ jobs: - attach_workspace: at: build - run_soltest_all: - evm_versions: homestead byzantium + # We test most EVM versions on every PR. The ones below are the exceptions. + # + # We do not test these at all. We were never doing that and no point starting now since + # they are deprecated anyway: + # - tangerineWhistle + # - spuriousDragon + # + # These have a low chance of breaking so we only run them in nightly to save credits: + # - byzantium: deprecated, if it breaks, homestead likely will as well + # - petersburg: no changes compared to constantinople + # - prague: no changes compared to cancun + evm_versions: byzantium petersburg prague - store_test_results: path: test_results/ - store_artifacts_test_results @@ -2259,7 +2270,7 @@ workflows: # Deprecated EVM versions tests - b_ubu: *requires_nothing - - t_ubu_soltest_deprecated_evm_versions: *requires_b_ubu + - t_ubu_soltest_low_priority_evm_versions: *requires_b_ubu # Build in a Docker container (on Alpine Linux) - b_alpine_docker: *requires_nothing diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 6f8ea14f3..389061859 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -32,15 +32,14 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" source "${REPODIR}/scripts/common.sh" DEFAULT_EVM_VALUES=( + homestead constantinople - petersburg istanbul berlin london paris shanghai cancun - prague osaka ) EVMS_WITH_EOF=(osaka) From 5e6d9f15793a8bdd712e5b2a507aa08b8e9c3941 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 2 Feb 2026 10:42:18 +0100 Subject: [PATCH 1110/1340] Add arithmetic concept and arithmetic string parsing utilities --- libsolutil/Common.h | 8 ++++++++ libsolutil/StringUtils.cpp | 2 ++ libsolutil/StringUtils.h | 15 +++++++++++++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/libsolutil/Common.h b/libsolutil/Common.h index c908c13ae..5ee0e1159 100644 --- a/libsolutil/Common.h +++ b/libsolutil/Common.h @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -52,6 +53,13 @@ namespace solidity { +namespace concepts +{ +/// Concept denoting some arithmetic type. +template +concept arithmetic = std::integral || std::floating_point; +} + // Binary data types. using bytes = std::vector; using bytesRef = util::vector_ref; diff --git a/libsolutil/StringUtils.cpp b/libsolutil/StringUtils.cpp index f5d2bbfb3..50191c083 100644 --- a/libsolutil/StringUtils.cpp +++ b/libsolutil/StringUtils.cpp @@ -26,6 +26,8 @@ #include +#include + #include #include #include diff --git a/libsolutil/StringUtils.h b/libsolutil/StringUtils.h index 763f1ea64..87f46252e 100644 --- a/libsolutil/StringUtils.h +++ b/libsolutil/StringUtils.h @@ -27,11 +27,11 @@ #include #include -#include - #include +#include #include #include +#include #include #include @@ -208,4 +208,15 @@ inline std::string indent(std::string const& _input, bool _indentEmptyLines = fa return prefixLines(_input, " ", !_indentEmptyLines); } +/// Parses an arithmetic value from a `string_view` without allocating and/or throwing. Returns `nullopt` on error. +template +std::optional parseArithmetic(std::string_view const sv) +{ + T result; + auto const errorCondition = std::from_chars(sv.data(), sv.data() + sv.size(), result).ec; + if (errorCondition == std::errc()) + return result; + return std::nullopt; +} + } From 31ef2784308f4c24e722949ad93c4eaf145854db Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:09:51 +0100 Subject: [PATCH 1111/1340] Pull Stack Depth and Offset definitions out of the Stack itself They do not depend on the callbacks template at all. --- libyul/backends/evm/ssa/Stack.h | 52 +++++++++++++++++---------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index 20207ebc7..31f7ac150 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -156,6 +156,31 @@ struct NoOpStackManipulationCallbacks }; static_assert(StackManipulationCallbackConcept); +/// Array index into stack from the bottom (offset 0 = bottom). +/// Natural for array-like access and iteration; used when treating the stack as a data structure. +struct StackOffset +{ + explicit constexpr StackOffset(size_t _value) : value(_value) {} + size_t value; + auto operator<=>(StackOffset const&) const = default; +}; +// comparison operations with size_t +constexpr auto operator<=>(StackOffset const lhs, size_t const rhs) noexcept { return lhs.value <=> rhs; } +constexpr auto operator<=>(size_t const lhs, StackOffset const rhs) noexcept { return lhs <=> rhs.value; } + +/// Distance from the stack top (depth 0 = top). +/// Natural for stack operations (SWAP1 = swap with depth 1); used for operations that +/// conceptually work "from the top". +struct StackDepth +{ + explicit constexpr StackDepth(size_t _value) : value(_value) {} + size_t value; + auto operator<=>(StackDepth const&) const = default; +}; +// comparison operations with size_t +constexpr auto operator<=>(StackDepth const lhs, size_t const rhs) noexcept { return lhs.value <=> rhs; } +constexpr auto operator<=>(size_t const lhs, StackDepth const rhs) noexcept { return lhs <=> rhs.value; } + template< StackManipulationCallbackConcept CallbacksType = NoOpStackManipulationCallbacks > @@ -167,31 +192,8 @@ class Stack using Slot = StackSlot; using Data = StackData; - - /// Array index into stack from the bottom (offset 0 = bottom). - /// Natural for array-like access and iteration; used when treating the stack as a data structure. - struct Offset - { - explicit constexpr Offset(size_t _value) : value(_value) {} - size_t value; - auto operator<=>(Offset const&) const = default; - }; - // comparison operations with size_t - friend constexpr auto operator<=>(Offset lhs, size_t rhs) noexcept { return lhs.value <=> rhs; } - friend constexpr auto operator<=>(size_t lhs, Offset rhs) noexcept { return lhs <=> rhs.value; } - - /// Distance from the stack top (depth 0 = top). - /// Natural for stack operations (SWAP1 = swap with depth 1); used for operations that - /// conceptually work "from the top". - struct Depth - { - explicit constexpr Depth(size_t _value) : value(_value) {} - size_t value; - auto operator<=>(Depth const&) const = default; - }; - // comparison operations with size_t - friend constexpr auto operator<=>(Depth lhs, size_t rhs) noexcept { return lhs.value <=> rhs; } - friend constexpr auto operator<=>(size_t lhs, Depth rhs) noexcept { return lhs <=> rhs.value; } + using Depth = StackDepth; + using Offset = StackOffset; Stack( Data& _data, From e1cb8431760d8822728f67151fc9bdefc10abf01 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:10:15 +0100 Subject: [PATCH 1112/1340] Fix dup implementation in ssa Stack abstraction --- libyul/backends/evm/ssa/Stack.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index 31f7ac150..a98977380 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -240,10 +240,11 @@ class Stack void dup(Depth const& _depth) { dup(depthToOffset(_depth)); } void dup(Offset const& _offset) { - yulAssert(dupReachable(_offset), "Stack too deep"); + auto const depth = offsetToDepth(_offset); + yulAssert(dupReachable(depth), "Stack too deep"); m_data->push_back((*m_data)[_offset.value]); if constexpr (!std::is_same_v) - m_callbacks.dup(offsetToDepth(_offset).value + 1); + m_callbacks.dup(depth.value + 1); } bool dupReachable(Offset const& _offset) const noexcept { return dupReachable(offsetToDepth(_offset)); } From 0d10f892b5ee1175b22bd4683c2d9abc99e1e6df Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:15:28 +0100 Subject: [PATCH 1113/1340] Simplify stack and slot to string functions for ssa Stack --- libyul/backends/evm/ssa/SSACFG.h | 39 ++++++++++++++++++++++++ libyul/backends/evm/ssa/Stack.cpp | 50 ++----------------------------- libyul/backends/evm/ssa/Stack.h | 2 -- 3 files changed, 41 insertions(+), 50 deletions(-) diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 40537cfcd..49d5a4e94 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -316,3 +316,42 @@ class SSACFG }; } + +template<> +struct fmt::formatter +{ + static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } + + template + auto format(solidity::yul::ssa::SSACFG::BlockId const& _blockId, FormatContext& _ctx) const -> decltype(_ctx.out()) + { + if (!_blockId.hasValue()) + return fmt::format_to(_ctx.out(), "empty"); + return fmt::format_to(_ctx.out(), "{}", _blockId.value); + } +}; + +template<> +struct fmt::formatter +{ + static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } + + template + auto format(solidity::yul::ssa::SSACFG::ValueId const& _valueId, FormatContext& _ctx) const -> decltype(_ctx.out()) + { + if (!_valueId.hasValue()) + return fmt::format_to(_ctx.out(), "empty"); + switch (_valueId.kind()) + { + case solidity::yul::ssa::SSACFG::ValueId::Kind::Literal: + return fmt::format_to(_ctx.out(), "lit{}", _valueId.value()); + case solidity::yul::ssa::SSACFG::ValueId::Kind::Variable: + return fmt::format_to(_ctx.out(), "v{}", _valueId.value()); + case solidity::yul::ssa::SSACFG::ValueId::Kind::Phi: + return fmt::format_to(_ctx.out(), "phi{}", _valueId.value()); + case solidity::yul::ssa::SSACFG::ValueId::Kind::Unreachable: + return fmt::format_to(_ctx.out(), "unreachable"); + } + solidity::util::unreachable(); + } +}; diff --git a/libyul/backends/evm/ssa/Stack.cpp b/libyul/backends/evm/ssa/Stack.cpp index 17c8c3f44..59534019d 100644 --- a/libyul/backends/evm/ssa/Stack.cpp +++ b/libyul/backends/evm/ssa/Stack.cpp @@ -18,20 +18,9 @@ #include +#include #include -#include -#include - -namespace -{ -size_t junkTailSize(solidity::yul::ssa::StackData const& _stackData) -{ - auto junkTail = _stackData | ranges::views::take_while([](auto const& slot) { return slot.isJunk(); }); - return static_cast(ranges::distance(junkTail)); -} -} - namespace solidity::yul::ssa { @@ -40,10 +29,7 @@ std::string slotToString(StackSlot const& _slot) switch (_slot.kind()) { case StackSlot::Kind::ValueID: - if (_slot.isLiteralValueID()) - return fmt::format("lit{}", _slot.valueID().value()); - else - return fmt::format("v{}", _slot.valueID().value()); + return fmt::format("{}", _slot.valueID()); case StackSlot::Kind::Junk: return "JUNK"; case StackSlot::Kind::FunctionCallReturnLabel: @@ -54,44 +40,12 @@ std::string slotToString(StackSlot const& _slot) util::unreachable(); } -std::string slotToString(StackSlot const& _slot, SSACFG const& _cfg) -{ - if (_slot.kind() == StackSlot::Kind::ValueID) - return _slot.valueID().str(_cfg); - - return slotToString(_slot); -} - std::string stackToString(StackData const& _stackData) { - auto const numJunk = junkTailSize(_stackData); - if (numJunk > 0) - return fmt::format( - "[JUNK x {}, {}]", - numJunk, - fmt::join(_stackData | ranges::views::drop(numJunk) | ranges::views::transform([&](auto const& _slot) { return slotToString(_slot); }), ", ") - ); - return fmt::format( "[{}]", fmt::join(_stackData | ranges::views::transform([&](auto const& _slot) { return slotToString(_slot); }), ", ") ); } -std::string stackToString(StackData const& _stackData, SSACFG const& _cfg) -{ - auto const numJunk = junkTailSize(_stackData); - if (numJunk > 0) - return fmt::format( - "[JUNK x {}, {}]", - numJunk, - fmt::join(_stackData | ranges::views::drop(numJunk) | ranges::views::transform([&](auto const& _slot) { return slotToString(_slot, _cfg); }), ", ") - ); - - return fmt::format( - "[{}]", - fmt::join(_stackData | ranges::views::transform([&](auto const& _slot) { return slotToString(_slot, _cfg); }), ", ") - ); -} - } diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index a98977380..95ff377e7 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -130,8 +130,6 @@ static_assert(std::is_trivial_v, "Want to have no init/cpy overhead") using StackData = std::vector; std::string slotToString(StackSlot const& _slot); -std::string slotToString(StackSlot const& _slot, SSACFG const& _cfg); -std::string stackToString(StackData const& _stackData, SSACFG const& _cfg); std::string stackToString(StackData const& _stackData); template From 02af154f6b61e706ea00460506f36967a78acf2d Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:15:51 +0100 Subject: [PATCH 1114/1340] Add the ssa stack shuffler --- libyul/CMakeLists.txt | 2 + libyul/backends/evm/ssa/StackShuffler.cpp | 165 +++++ libyul/backends/evm/ssa/StackShuffler.h | 853 ++++++++++++++++++++++ 3 files changed, 1020 insertions(+) create mode 100644 libyul/backends/evm/ssa/StackShuffler.cpp create mode 100644 libyul/backends/evm/ssa/StackShuffler.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index ff94a3905..9d0bfe1e2 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -92,6 +92,8 @@ add_library(yul backends/evm/ssa/SSACFGJsonExporter.h backends/evm/ssa/Stack.cpp backends/evm/ssa/Stack.h + backends/evm/ssa/StackShuffler.cpp + backends/evm/ssa/StackShuffler.h optimiser/ASTCopier.cpp optimiser/ASTCopier.h optimiser/ASTWalker.cpp diff --git a/libyul/backends/evm/ssa/StackShuffler.cpp b/libyul/backends/evm/ssa/StackShuffler.cpp new file mode 100644 index 000000000..b42d2bb24 --- /dev/null +++ b/libyul/backends/evm/ssa/StackShuffler.cpp @@ -0,0 +1,165 @@ +/* + 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 + +#include + +#include +#include + +using namespace solidity::yul::ssa; +using namespace solidity::yul::ssa::detail; + +Target::Target(StackData const& _args, LivenessAnalysis::LivenessData const& _liveOut, std::size_t const _targetSize): + args(_args), + liveOut(_liveOut), + size(_targetSize), + tailSize(_targetSize - _args.size()) +{ + minCount.reserve(_args.size() + _liveOut.size()); + for (auto const& arg: _args) + if (!arg.isJunk()) + ++minCount[arg]; + for (auto const& _liveValueId: _liveOut | ranges::views::keys) + ++minCount[StackSlot::makeValueID(_liveValueId)]; +} + +State::State(StackData const& _stackData, Target const& _target, std::size_t const _reachableStackDepth): + m_stackData(_stackData), + m_target(_target), + m_reachableStackDepth(_reachableStackDepth) +{ + m_histogram.reserve(_stackData.size()); + m_histogramReachable.reserve(_stackData.size()); + m_histogramTail.reserve(_stackData.size()); + m_histogramArgs.reserve(_target.args.size()); + for (auto const& [i, slot]: _stackData | ranges::views::enumerate) + { + // we don't care about junk in the tail + if (i < _target.tailSize && slot.isJunk()) + continue; + // we purposefully skip over junk in the target args as they are always 'correct' + if (i >= _target.tailSize && i < _target.size && _target.args[i - _target.tailSize].isJunk()) + continue; + + ++m_histogram[slot]; + if (i < _target.tailSize) + ++m_histogramTail[slot]; + else if (i < _target.size) + ++m_histogramArgs[slot]; + if (_stackData.size() - i - 1 < _reachableStackDepth) + ++m_histogramReachable[slot]; + } +} + +std::size_t State::size() const +{ + return m_stackData.size(); +} + +std::size_t State::count(StackSlot const& _slot) const +{ + return util::valueOrDefault(m_histogram, _slot, static_cast(0)); +} + +std::size_t State::countInArgs(StackSlot const& _slot) const +{ + return util::valueOrDefault(m_histogramArgs, _slot, static_cast(0)); +} + +std::size_t State::countInTail(StackSlot const& _slot) const +{ + return util::valueOrDefault(m_histogramTail, _slot, static_cast(0)); +} + +std::size_t State::countReachable(StackSlot const& _slot) const +{ + return util::valueOrDefault(m_histogramReachable, _slot, static_cast(0)); +} + +std::size_t State::targetMinCount(StackSlot const& _slot) const +{ + return util::valueOrDefault(m_target.minCount, _slot, static_cast(0)); +} + +std::size_t State::targetArgsCount(StackSlot const& _slot) const +{ + return static_cast(ranges::count(m_target.args, _slot)); +} + +bool State::admissible() const +{ + if (m_target.size != m_stackData.size()) + return false; + + // check if the args are correct + for (size_t i = 0; i < m_target.args.size(); ++i) + if (!isArgsCompatible(StackOffset{m_stackData.size() - i - 1}, StackOffset{m_stackData.size() - i - 1})) + return false; + + // check if the distribution is correct (implying that the stack is admissible as JUNK target args are not counted) + for (auto const& [targetSlot, targetMinCount]: m_target.minCount) + if (count(targetSlot) < targetMinCount) + return false; + return true; +} + +bool State::requiredInArgs(StackSlot const& _slot) const +{ + return ranges::find(m_target.args, _slot) != ranges::end(m_target.args); +} + +bool State::requiredInTail(StackSlot const& _slot) const +{ + return _slot.isValueID() && m_target.liveOut.contains(_slot.valueID()); +} + +bool State::offsetInTargetArgsRegion(StackOffset const _offset) const +{ + return _offset.value >= m_target.size - m_target.args.size() && _offset.value < m_target.size; +} + +StackSlot const& State::targetArg(StackOffset const _targetOffset) const +{ + yulAssert(offsetInTargetArgsRegion(_targetOffset)); + return m_target.args[_targetOffset.value - m_target.tailSize]; +} + +bool State::isArgsCompatible(StackOffset const _sourceOffset, StackOffset const _targetOffset) const +{ + if (_sourceOffset >= m_stackData.size() || !offsetInTargetArgsRegion(_targetOffset)) + return false; + auto const& arg = targetArg(_targetOffset); + return arg.isJunk() || m_stackData[_sourceOffset.value] == arg; +} + +bool State::targetArbitrary(StackOffset const _targetOffset) const +{ + return targetArg(_targetOffset).isJunk(); +} + +bool State::isSourceCompatible(StackOffset const _sourceOffset1, StackOffset const _sourceOffset2) const +{ + return _sourceOffset1 < m_stackData.size() && + _sourceOffset2 < m_stackData.size() && + m_stackData[_sourceOffset1.value] == m_stackData[_sourceOffset2.value]; +} + +Target const& State::target() const +{ + return m_target; +} diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h new file mode 100644 index 000000000..983505bb2 --- /dev/null +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -0,0 +1,853 @@ +/* + 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 + +#pragma once + +#include +#include + +#include + +#include + +#include +#include + +namespace solidity::yul::ssa +{ + +namespace detail +{ +/// Contains information about the shuffling target, aggregates over args and live out to +/// provide a lower bound for the slot distribution. +struct Target +{ + Target(StackData const& _args, LivenessAnalysis::LivenessData const& _liveOut, std::size_t _targetSize); + + StackData const& args; + LivenessAnalysis::LivenessData const& liveOut; + std::size_t const size; + std::size_t const tailSize; + boost::container::flat_map minCount; +}; +/// Current state of the stack vs the shuffling target. +class State +{ +public: + State(StackData const& _stackData, Target const& _target, std::size_t _reachableStackDepth); + + std::size_t size() const; + /// How many of `_slot` do we have on stack + std::size_t count(StackSlot const& _slot) const; + /// How many of `_slot` do we have in the args section of the stack + std::size_t countInArgs(StackSlot const& _slot) const; + /// How many of `_slot` do we have in the tail section of the stack + std::size_t countInTail(StackSlot const& _slot) const; + /// How many of `_slot` are (dup) reachable on stack + std::size_t countReachable(StackSlot const& _slot) const; + + /// Obtain the amount of the provided slot that is required for distribution correctness + std::size_t targetMinCount(StackSlot const& _slot) const; + /// Obtain the amount of the provided slot that is required in target args + std::size_t targetArgsCount(StackSlot const& _slot) const; + + /// Checks if the state is compatible with the target + bool admissible() const; + + /// Checks if a particular slot is required in the target args + bool requiredInArgs(StackSlot const& _slot) const; + /// Checks if a particular slot is required in the target tail + bool requiredInTail(StackSlot const& _slot) const; + + /// Checks if an offset is in the target args (bounded from below by tail size, from above by target size) + bool offsetInTargetArgsRegion(StackOffset _offset) const; + /// Retrieves the required argument slot for a specific stack offset + StackSlot const& targetArg(StackOffset _targetOffset) const; + /// Checks the current stack offset is args-compatible with a target stack offset, meaning the target offset is + /// in the target args region and either a wildcard slot (JUNK) or a precise match for the slot at `_sourceOffset` + bool isArgsCompatible(StackOffset _sourceOffset, StackOffset _targetOffset) const; + /// Checks if the slot at `_targetOffset` admits any slot + bool targetArbitrary(StackOffset _targetOffset) const; + /// Yields whether two slots on the current stack are same, respecting stack size limits + bool isSourceCompatible(StackOffset _sourceOffset1, StackOffset _sourceOffset2) const; + /// Shuffling target information + Target const& target() const; + + /// A range of offsets `[argsBegin, argsEnd)` intersected with the current stack size + auto stackArgsRange() const + { + return ranges::views::iota(std::min(m_target.tailSize, m_stackData.size()), std::min(m_target.size, m_stackData.size())) | ranges::views::transform([](auto _i) { return StackOffset{_i}; }); + } + + /// A range of offsets `[0, argsBegin)` intersected with the current stack size + auto stackTailRange() const + { + return ranges::views::iota(0u, std::min(m_target.tailSize, m_stackData.size())) | ranges::views::transform([](auto _i) { return StackOffset{_i}; }); + } + + /// A range of offsets `[0, stackSize)` + auto stackRange() const + { + return ranges::views::iota(0u, m_stackData.size()) | ranges::views::transform([&](auto _i) { return StackOffset{_i}; }); + } + + /// A reversed range of offsets `[stackSize - reachableStackDepth - 1, stackSize)` + auto stackSwapReachableRange() const + { + return ranges::views::iota(0u, std::min(m_stackData.size(), m_reachableStackDepth + 1)) | ranges::views::transform([&](auto _i) { return StackOffset{m_stackData.size() - _i - 1}; }); + } + + /// A reversed range of offsets `[stackSize - reachableStackDepth - 1, stackSize)` + auto stackDupReachableRange() const + { + return ranges::views::iota(0u, std::min(m_stackData.size(), m_reachableStackDepth)) | ranges::views::transform([&](auto _i) { return StackOffset{m_stackData.size() - _i - 1}; }); + } + +private: + StackData const& m_stackData; + Target const& m_target; + std::size_t const m_reachableStackDepth; + boost::container::flat_map m_histogramTail; + boost::container::flat_map m_histogramArgs; + boost::container::flat_map m_histogramReachable; + boost::container::flat_map m_histogram; +}; +} + +template +class StackShuffler +{ + using Slot = StackSlot; + +public: + static void shuffle( + Stack& _stack, + StackData const& _args, + LivenessAnalysis::LivenessData const& _liveOut, + std::size_t _targetStackSize + ) + { + detail::Target const target(_args, _liveOut, _targetStackSize); + yulAssert(_liveOut.size() <= target.size, "not enough tail space"); + { + // check that all required values are on stack + detail::State const state(_stack.data(), target, ReachableStackDepth); + for (auto const& liveVariable: _liveOut | ranges::views::keys | ranges::views::transform(Slot::makeValueID)) + yulAssert(_stack.canBeFreelyGenerated(liveVariable) || ranges::find(_stack.data(), liveVariable) != ranges::end(_stack.data())); + for (auto const& arg: _args) + yulAssert(_stack.canBeFreelyGenerated(arg) || ranges::find(_stack.data(), arg) != ranges::end(_stack.data())); + } + + static std::size_t constexpr maxIterations = 1000; + std::size_t i = 0; + while (i < maxIterations) + { + detail::State const state(_stack.data(), target, ReachableStackDepth); + if (!shuffleStep(_stack, state)) + { + yulAssert(state.admissible()); + break; + } + ++i; + } + + yulAssert(i < maxIterations, fmt::format("Maximum iterations reached on {}", stackToString(_stack.data()))); + } + +private: + /// Make a local step in stack space that should bring us closer to the target. Returns true if more shuffling + /// is required, returns false if finished. + static bool shuffleStep(Stack& _stack, detail::State const& _state) + { + // if the stack is too large, we try to shrink it + if (_stack.size() > _state.target().size) + { + if (shrinkStack(_stack, _state)) + return true; + // couldn't shrink to required size, need to spill to memory or increase target size + yulAssert(false, "stack too deep"); + } + yulAssert(_stack.size() <= _state.target().size, "I1 violated: Stack size too large"); + + // after this, all current slots are either in acceptable positions or at least dup-reachable + if (auto unreachableOffset = allNecessarySlotsReachableOrFinal(_stack, _state)) + { + // !allNecessarySlotsReachableOrFinal(ops) ≡ ¬(∀s: reachable(s) ∨ final(s)) ≡ ∃s: ¬reachable(s) ∧ ¬final(s) + if (shrinkStack(_stack, _state)) + return true; + + yulAssert(false, fmt::format("stack too deep, couldn't reach offset {}", unreachableOffset->value)); + } + + // this will either grow the tail as needed, swap down something from args that needs to be in the tail, + // or return false when there's nothing to be done + if (fixTailSlot(_stack, _state)) + return true; + + // fixing tail slot fills up the tail so that now the stack must reach into the args region but also not + // exceed it as per our first invariant + yulAssert(_state.target().tailSize <= _stack.size() && _stack.size() <= _state.target().size); + + // if the stack reaches into the args region try fixing a slot in there until there's nothing left to be fixed + // within the target size constraints + if (fixArgsSlot(_stack, _state)) + return true; + + // if there are no args, we should be done now + if (_state.target().args.empty()) + return false; + yulAssert(_stack.size() == _state.target().size); + + // check whether we are done + if (_state.admissible()) + return false; + + // We couldn't improve the args tail or args situation, and we are not admissible yet, so try to reduce the + // stack size and pop something that we don't need so we make space to dup/push stuff within target size + if (shrinkStack(_stack, _state)) + return true; + + yulAssert(false, "reached final and forbidden state"); + } + + /// Select an optimal slot to dup based on liveness analysis. + /// Prioritizes slots that have the highest deficit with respect to liveOut counts. + static std::optional selectOptimalSlotToDup(Stack const& _stack, detail::State const& _state) + { + std::optional bestSlot; + int bestDeficit = 0; // Only consider positive deficits + + // Iterate through all slots on the stack that can be DUPed + for (StackOffset offset: _state.stackDupReachableRange() | ranges::views::reverse) + { + Slot const& slot = _stack[offset]; + + // Skip junk slots + if (slot.isJunk()) + continue; + + // Calculate deficit: how many more of this slot do we need? + // Uses the deficit of slots which we need to produce more of based on usage counts in liveness. + // Prioritizes slots that need more copies to be consumed down the line. + int currentCount = static_cast(_state.count(slot)); + + int liveOutCount = 0; + if (slot.isValueID() && _state.target().liveOut.contains(slot.valueID())) + liveOutCount = static_cast(_state.target().liveOut.count(slot.valueID())); + int deficit = liveOutCount - currentCount; + + // Update best if this deficit is higher + if (deficit > bestDeficit) + { + bestDeficit = deficit; + bestSlot = _stack.offsetToDepth(offset); + } + } + + return bestSlot; + } + + /// Dups the deepest reachable slot in the tail that is required in args + static bool dupDeepestRelevantTailSlot(Stack& _stack, detail::State const& _state) + { + // dup up the deepest slot that is required in args (or compress if unreachable) + for (StackOffset offset: _state.stackRange()) + { + // if we need the slot in args and there's no slot of the same kind further up + if ( + _state.requiredInArgs(_stack[offset]) && + ranges::find(ranges::begin(_stack) + static_cast(offset.value) + 1, ranges::end(_stack), _stack[offset]) == ranges::end(_stack) + ) + { + // dup if we can + if (_stack.dupReachable(offset)) + { + _stack.dup(offset); + return true; + } + + // try to compress + if (shrinkStack(_stack, _state)) + return true; + + yulAssert(false, fmt::format("Stack too deep: can't reach slot at offset {}", offset.value)); + } + } + return false; + } + + /// If dupping an ideal slot causes a slot that will still be required to become unreachable, then dup + /// the latter slot first + static bool dupDeepSlotIfRequired(Stack& _stack, detail::State const& _state) + { + // Check if the stack is large enough for anything to potentially become unreachable. + if (_stack.size() < ReachableStackDepth - 1) + return false; + // Check whether any deep slot might still be needed later (i.e. we still need to reach it with a DUP or SWAP). + for (StackOffset sourceOffset{0u}; sourceOffset < _stack.size() - (ReachableStackDepth - 1); ++sourceOffset.value) + { + // This slot needs to be moved into args and there is no tail slot of the same kind further up in the stack. + auto const& endangeredSlot = _stack[sourceOffset]; + // no need to dup deep junk + if (endangeredSlot.isJunk()) + continue; + // check if we have more of the same slot further up in the stack + bool const neededInArgs = _state.targetArgsCount(endangeredSlot) > _state.countInArgs(endangeredSlot); + bool const needMore = _state.targetMinCount(endangeredSlot) > _state.count(endangeredSlot); + if (neededInArgs || needMore) + { + // if we ever need more of a slot then this can only happen if it is something we require + // in the arguments + yulAssert(_state.requiredInArgs(endangeredSlot)); + + auto const haveMoreAbove = [&] + { + for (StackOffset offset{sourceOffset.value + 1}; offset < _stack.size(); ++offset.value) + { + if (_stack[offset] == endangeredSlot) + return true; + } + return false; + }(); + + // if we have more of the same further above, just unconditionally skip this one + if (haveMoreAbove) + continue; + + if (_stack.dupReachable(sourceOffset)) + { + + // if we can safely swap the current stack top with the endangered slot, we do that instead of DUP + if ( + !_state.isArgsCompatible(sourceOffset, sourceOffset) && // the offset isn't already in the right position wrt args + !_state.isArgsCompatible(StackOffset{_stack.size() - 1}, StackOffset{_stack.size() - 1}) && // the top isn't already in the right position wrt args + ( + !_state.requiredInArgs(_stack.top()) || // current top can go into tail, ie it's not required as arg or + _state.countReachable(_stack.top()) > 1 // there's more of it in reachable stack depth + ) && + ( + _state.target().tailSize <= sourceOffset.value || // sourceOffset not in tail + !_state.requiredInTail(endangeredSlot) || // we're in tail but sourceOffset not needed in tail + (_state.countInTail(endangeredSlot) > 1 && _state.requiredInTail(endangeredSlot)) // swapping source offset away from tail doesn't decrease tail correctness + ) + ) + { + // top can go into the tail bit, swap it down + _stack.swap(sourceOffset); + return true; + } + else + { + // we need more of the slot that is about to go out of reach, dup it + _stack.dup(sourceOffset); + return true; + } + } + else + { + std::optional depth = _stack.findSlotDepth(_stack[sourceOffset]); + yulAssert(depth); + // if there's a shallower slot with the same info that is reachable, skip this one + if (*depth < _stack.offsetToDepth(sourceOffset)) + continue; + + // the slot we need something in the args region of is unreachable, try compressing the stack, + // first looking at the top + if (shrinkStack(_stack, _state)) + return true; + + yulAssert(false, fmt::format("Stack too deep, can't reach slot at depth {}", depth->value)); + } + } + } + return false; + } + + /// Tries to fix a slot in the args section of the stack + static bool fixArgsSlot(Stack& _stack, detail::State const& _state) + { + yulAssert(_stack.size() <= _state.target().size, "this method assumes that the stack isn't too large"); + if (_stack.size() < _state.target().tailSize) + return false; + + // if we have at least one slot in the args section, try to fix something there + if (!_stack.empty() && _stack.size() >= _state.target().tailSize) + { + StackOffset const stackTop{_stack.size() - 1}; + // if the stack top isn't where it likes to be right now, try to put it somewhere more sensible + if (!_state.isArgsCompatible(stackTop, stackTop)) + { + // if the stack top should go into the tail but isn't there yet and we have enough of it in args + if ( + _state.requiredInTail(_stack[stackTop]) && + _state.countInTail(_stack[stackTop]) == 0 && + _state.countInArgs(_stack[stackTop]) > _state.targetArgsCount(_stack[stackTop]) + ) + { + // try swapping it with something in the tail that also fixes the top + for (StackOffset offset: _state.stackTailRange()) + if (_stack.swapReachable(offset) && _state.isArgsCompatible(offset, stackTop)) + { + _stack.swap(offset); + return true; + } + // otherwise try swapping it with something that needs to go into args + for (StackOffset offset: _state.stackTailRange()) + if (_stack.swapReachable(offset) && _state.countInArgs(_stack[offset]) < _state.targetArgsCount(_stack[offset])) + { + _stack.swap(offset); + return true; + } + // otherwise try swapping it with something that can be popped + for (StackOffset offset: _state.stackTailRange()) + if (_stack.swapReachable(offset) && _stack.canBeFreelyGenerated(_stack[offset]) && !_stack[offset].isLiteralValueID()) + { + _stack.swap(offset); + return true; + } + // otherwise try swapping it with a literal + for (StackOffset offset: _state.stackTailRange()) + if (_stack.swapReachable(offset) && _stack[offset].isLiteralValueID()) + { + _stack.swap(offset); + return true; + } + } + // try finding a slot that is compatible with the top and also admits the current top: + // - could be that the top slot is used elsewhere in the args (exclude junk) + // - could be that the top slot is something that is only required in the tail + for (StackOffset offset: _state.stackArgsRange()) + if ( + offset != stackTop && + _stack[offset] != _stack[stackTop] && // don't swap identical values (no-op) + _stack.swapReachable(offset) && + _state.isArgsCompatible(offset, stackTop) && + _state.isArgsCompatible(stackTop, offset) && + !_state.targetArbitrary(offset) + ) + { + _stack.swap(offset); + return true; + } + + // try finding a slot in args that wants to have the top, swap that + for (StackOffset offset: _state.stackArgsRange()) + if ( + offset != stackTop && + _stack[offset] != _stack[stackTop] && // don't swap identical values (no-op) + _stack.swapReachable(offset) && + !_state.isArgsCompatible(offset, offset) && + _state.isArgsCompatible(stackTop, offset) + ) + { + _stack.swap(offset); + return true; + } + + // try swapping top with a tail slot that has what we need at top + for (StackOffset tailOffset: _state.stackTailRange()) + if ( + _stack.swapReachable(tailOffset) && + _state.isArgsCompatible(tailOffset, stackTop) && + (!_state.requiredInTail(_stack[tailOffset]) || _state.countInTail(_stack[tailOffset]) > 1) && + // current top can safely go to tail (not needed in args, or we have excess) + ( + !_state.requiredInArgs(_stack[stackTop]) || + _state.countInArgs(_stack[stackTop]) > _state.targetArgsCount(_stack[stackTop]) + ) + ) + { + _stack.swap(tailOffset); + return true; + } + } + + // swap up any slot in args that is out of position and has a slot available in args that it can occupy + for (StackOffset offset: _state.stackArgsRange()) + { + bool const reachable = _stack.swapReachable(offset); + bool const identical = _state.isArgsCompatible(offset, stackTop) && !_state.targetArbitrary(stackTop); + if ( + reachable && + !identical && // we wouldn't just be swapping identical things + ( + !_state.isArgsCompatible(offset, offset) || // the slot at offset isn't final + (_state.targetArbitrary(offset) && !_stack.slot(offset).isJunk()) // or the target is arbitrary and the current slot isn't already junk + ) + ) + { + // for each `targetOffset` in target args, see if we can't swap the out of position `offset` to `targetOffset` + for (StackOffset targetOffset: _state.stackArgsRange()) + if ( + targetOffset != offset && // we shouldn't be looking at the very same offset + _stack.swapReachable(targetOffset) && // the target offset should be within reach + _state.isArgsCompatible(offset, targetOffset) && // we can put offset -> targetOffset + !_state.isArgsCompatible(targetOffset, targetOffset) // targetOffset doesn't like where it is + ) + { + if (offset != stackTop) + // swap up slot at offset + _stack.swap(offset); + // bring slot at offset into fixed position + _stack.swap(targetOffset); + return true; + } + } + } + } + + // dup up whatever is missing + if (_stack.size() < _state.target().size) + { + if (dupDeepSlotIfRequired(_stack, _state)) + return true; + + { + StackOffset const targetOffset{_stack.size()}; + if (_state.count(_state.targetArg(targetOffset)) < _state.targetMinCount(_state.targetArg(targetOffset))) + { + auto const sourceDepth = _stack.findSlotDepth(_state.targetArg(targetOffset)); + if (!sourceDepth) + { + _stack.push(_state.targetArg(targetOffset)); + return true; + } + + if (!_stack.dupReachable(*sourceDepth)) + yulAssert(false, fmt::format("todo: stack too deep handling, couldn't dup up arg {}", slotToString(_state.targetArg(_stack.depthToOffset(*sourceDepth))))); + _stack.dup(*sourceDepth); + return true; + } + } + + // if we can't directly produce targetOffset, take the deepest arg that we don't have enough of and dup/push that + // First, prioritize duping args that are on the stack over pushing freely-generatable ones + for (StackOffset offset{_state.target().tailSize}; offset < _state.target().size; ++offset.value) + { + Slot const& arg = _state.targetArg(offset); + if (!arg.isJunk() && (_state.count(arg) < _state.targetMinCount(arg) || _state.countInArgs(arg) < _state.targetArgsCount(arg))) + { + if (auto sourceDepth = _stack.findSlotDepth(arg)) + { + if (_stack.dupReachable(*sourceDepth)) + { + _stack.dup(*sourceDepth); + return true; + } + yulAssert(false, "stack too deep handling"); + } + yulAssert(_stack.canBeFreelyGenerated(arg)); + _stack.push(arg); + return true; + } + } + + // Try to dup the optimal slot based on liveness analysis + if (auto slotToDup = selectOptimalSlotToDup(_stack, _state)) + _stack.dup(*slotToDup); + else + // If no suitable slot found, push junk + _stack.push(Slot::makeJunk()); + return true; + } + + // if we're at size and have to push or dup something to satisfy args + if (_stack.size() == _state.target().size) + { + for (auto const& arg: _state.target().args) + if (_state.count(arg) < _state.targetMinCount(arg)) + { + // we have asserted that all relevant slots are reachable or final, so the arg must either be + // within dup-reach or we can just push it + if (auto depth = _stack.findSlotDepth(arg)) + { + yulAssert(depth->value == 0 || _stack.swapReachable(*depth)); + // if we can't outright dup the slot, let's shrink the stack first + if (!_stack.dupReachable(*depth)) + { + yulAssert(shrinkStack(_stack, _state), "stack too deep, need to spill arg to memory"); + return true; + } + _stack.dup(*depth); + return true; + } + else + { + yulAssert(_stack.canBeFreelyGenerated(arg)); + if (!dupDeepSlotIfRequired(_stack, _state)) + _stack.push(arg); + return true; + } + } + } + return false; + } + + /// Grows the tail if too small, otherwise tries swapping something down from args if its required in tail but not + /// there yet. + static bool fixTailSlot(Stack& _stack, detail::State const& _state) + { + yulAssert(_stack.size() <= _state.target().size, "this method assumes that the stack isn't exceeding target size"); + for (StackOffset offset: _state.stackArgsRange() | ranges::views::reverse) + { + Slot const& slotAtOffset = _stack[offset]; + if ( + _state.requiredInTail(slotAtOffset) && // if we need the slot in tail + _state.countInTail(slotAtOffset) == 0 // if we don't have the slot in tail right now + ) + { + // If we don't have enough copies of this slot, dup first instead of swapping. + if (_state.count(slotAtOffset) < _state.targetMinCount(slotAtOffset)) + { + if (_stack.dupReachable(offset)) + { + _stack.dup(offset); + return true; + } + } + + // find the lowest swappable slot in tail that needs to go to args, swap + for (StackOffset tailOffset: _state.stackTailRange()) + { + auto const& slotAtTailOffset = _stack[tailOffset]; + if ( + _stack.swapReachable(tailOffset) && // we can swap that deep + (!_state.requiredInTail(slotAtTailOffset) || _state.countInTail(slotAtTailOffset) > 1) && // dont need it in tail or it's available more than once + _state.requiredInArgs(slotAtTailOffset) && // we need the tail offset slot in args + _state.targetArgsCount(slotAtTailOffset) > _state.countInArgs(slotAtTailOffset) // we don't already have enough of it in args + ) + { + // bring up offset slot if necessary + if (offset != StackOffset{_stack.size() - 1}) + _stack.swap(offset); + // swap offset slot down into tail + _stack.swap(tailOffset); + return true; + } + } + // find the lowest swappable slot in tail that can be popped but is no literal, swap + for (StackOffset tailOffset: _state.stackTailRange()) + if ( + _stack.swapReachable(tailOffset) && + _stack.canBeFreelyGenerated(_stack[tailOffset]) && + !_stack[tailOffset].isLiteralValueID() + ) + { + // bring up offset slot if necessary + if (offset != StackOffset{_stack.size() - 1}) + _stack.swap(offset); + // swap offset slot down into tail + _stack.swap(tailOffset); + return true; + } + // find the lowest swappable slot in tail that is a literal, swap + for (StackOffset tailOffset: _state.stackTailRange()) + if ( + _stack.swapReachable(tailOffset) && + _stack[tailOffset].isLiteralValueID() + ) + { + // bring up offset slot if necessary + if (offset != StackOffset{_stack.size() - 1}) + _stack.swap(offset); + // swap offset slot down into tail + _stack.swap(tailOffset); + return true; + } + // we needed to bring the slot into tail but couldn't, not enough stack target space -> spill to memory + yulAssert(false, "stack too deep: couldn't swap args slot into tail without moving something else out that is required there"); + } + } + + if (_stack.size() < _state.target().tailSize) + { + // if something is on the verge of going out of scope by duping something, dup that first + if (dupDeepSlotIfRequired(_stack, _state)) + return true; + + // dup up the deepest slot that needs to go into args so we avoid having to fish it back up later + if (dupDeepestRelevantTailSlot(_stack, _state)) + return true; + + // Try to dup the optimal slot based on liveness analysis + if (auto slotToDup = selectOptimalSlotToDup(_stack, _state)) + _stack.dup(*slotToDup); + else + // If no suitable slot found, push junk + _stack.push(Slot::makeJunk()); + return true; + } + return false; + } + + /// Tries to compress the stack + static bool shrinkStack(Stack& _stack, detail::State const& _state) + { + yulAssert(!_stack.empty(), "Stack is empty, can't shrink"); + + StackOffset const stackTop{_stack.size() - 1}; + // pop top if it is junk (ie actual junk, not in args, not in live out) + if ( + _stack[stackTop].isJunk() || + (!_state.requiredInArgs(_stack[stackTop]) && !_state.requiredInTail(_stack[stackTop])) + ) + { + _stack.pop(); + return true; + } + + // swap top to suitable position, prioritizing args region + { + if (_state.requiredInArgs(_stack[stackTop])) + { + for (StackOffset argsOffset: _state.stackArgsRange()) + if ( + _stack[argsOffset] != _stack[stackTop] && // don't swap identical values (no-op) + _stack.swapReachable(argsOffset) && + _state.isArgsCompatible(stackTop, argsOffset) && + !_state.isArgsCompatible(argsOffset, argsOffset) + ) + { + _stack.swap(argsOffset); + return true; + } + } + // we don't need it in args but in tail + if (!_state.requiredInArgs(_stack[stackTop]) && _state.requiredInTail(_stack[stackTop])) + { + // pop when at least one of the two conditions is fulfilled + // - the top slot is contained in tail, and we're in args or excess region + // - there's more than one in tail + if ( + ( + _state.countInTail(_stack[stackTop]) >= 1 && + (_state.offsetInTargetArgsRegion(stackTop) || _stack.size() > _state.target().size) + ) || _state.countInTail(_stack[stackTop]) > 1 + ) + { + _stack.pop(); + return true; + } + + // if we need it down there, try to swap down + for (StackOffset tailOffset: _state.stackTailRange() | ranges::views::reverse) + if ( + _stack[tailOffset] != _stack[stackTop] && // don't swap identical values (no-op) + _stack.swapReachable(tailOffset) && // we can reach the offset + !(_state.requiredInTail(_stack[tailOffset]) && _state.countInTail(_stack[tailOffset]) <= 1) // it's okay to swap the tail offset out + ) + { + _stack.swap(tailOffset); + return true; + } + } + } + // pop junk (but not if JUNK is exactly what's needed at that position) + for (StackOffset offset: _state.stackSwapReachableRange()) + if (_stack[offset].isJunk() && !_state.isArgsCompatible(offset, offset)) + { + if (offset != stackTop && _stack[offset] != _stack[stackTop]) + _stack.swap(offset); + _stack.pop(); + return true; + } + + // pop something that can be freely generated except for literals + // (but not if it's already in a compatible position) + for (StackOffset offset: _state.stackSwapReachableRange()) + if ( + _stack.canBeFreelyGenerated(_stack[offset]) && + !_stack[offset].isLiteralValueID() && + !_state.isArgsCompatible(offset, offset) + ) + { + if (offset != stackTop && _stack[offset] != _stack[stackTop]) + _stack.swap(offset); + _stack.pop(); + return true; + } + + // pop anything that isn't in position and we have more than one of + for (StackOffset offset: _state.stackSwapReachableRange()) + if (_state.count(_stack[offset]) > _state.targetMinCount(_stack[offset])) + { + if (offset != stackTop && _stack[offset] != _stack[stackTop]) + _stack.swap(offset); + _stack.pop(); + return true; + } + // pop anything that can be freely generated + for (StackOffset offset: _state.stackSwapReachableRange()) + if (_stack.canBeFreelyGenerated(_stack[offset])) + { + if (offset != stackTop && _stack[offset] != _stack[stackTop]) + _stack.swap(offset); + _stack.pop(); + return true; + } + return false; + } + + /// Checks if all current slots are either in a position that is compatible with the target or, if not, are dup-reachable. + static std::optional allNecessarySlotsReachableOrFinal(Stack const& _stack, detail::State const& _state) + { + // check that args are either in position or reachable + for (StackOffset offset{_state.target().tailSize}; offset < _state.target().size; ++offset.value) + if ( + offset < _state.size() && + !_state.isArgsCompatible(offset, offset) + ) + { + // find first occurrence of the slot + std::optional depth = _stack.findSlotDepth(_state.targetArg(offset)); + + if (!depth) + { + // if there is no occurrence of the slot anywhere, we must be able to freely generate it + yulAssert(_stack.canBeFreelyGenerated(_state.targetArg(offset))); + } + else + { + if (!_stack.swapReachable(*depth)) + return _stack.depthToOffset(*depth); + } + } + // distribution check: all we have to dup can be duped + for (StackOffset const offset: _state.stackRange()) + { + auto const& slotAtOffset = _stack[offset]; + // we don't have enough of the slot + if ( + _state.count(slotAtOffset) < _state.targetMinCount(slotAtOffset) && + !_stack.dupReachable(offset) + ) + { + // find first occurrence of the slot + std::optional depth = _stack.findSlotDepth(slotAtOffset); + // it must exist + yulAssert(depth); + if (!_stack.dupReachable(*depth)) + return _stack.depthToOffset(*depth); + } + } + + return std::nullopt; + } +}; + +} From b2cb2af6f21841f3cfe52abaf3484bcce7afff05 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:51:16 +0100 Subject: [PATCH 1115/1340] Add stack shuffler test --- test/CMakeLists.txt | 2 + test/InteractiveTests.h | 3 + test/libyul/ssa/StackShufflerTest.cpp | 453 ++++++++++++++++++++++++++ test/libyul/ssa/StackShufflerTest.h | 36 ++ test/tools/CMakeLists.txt | 2 + 5 files changed, 496 insertions(+) create mode 100644 test/libyul/ssa/StackShufflerTest.cpp create mode 100644 test/libyul/ssa/StackShufflerTest.h diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b0cd991f7..f36ae4147 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -173,6 +173,8 @@ set(libyul_sources libyul/YulOptimizerTest.h libyul/YulOptimizerTestCommon.cpp libyul/YulOptimizerTestCommon.h + libyul/ssa/StackShufflerTest.cpp + libyul/ssa/StackShufflerTest.h ) detect_stray_source_files("${libyul_sources}" "libyul/") diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index 107a6aae0..ff2725471 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -30,6 +30,8 @@ #include #include #include + +#include #include #include #include @@ -72,6 +74,7 @@ Testsuite const g_interactiveTestsuites[] = { {"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create}, {"Yul Control Flow Graph", "libyul", "yulControlFlowGraph", false, false, &yul::test::ControlFlowGraphTest::create}, {"Yul SSA Control Flow Graph", "libyul", "yulSSAControlFlowGraph", false, false, &yul::test::SSAControlFlowGraphTest::create}, + {"Yul SSA StackShuffling", "libyul", "ssa/stackShuffler", false, false, &yul::ssa::test::ShufflingTest::create}, {"Yul Stack Layout", "libyul", "yulStackLayout", false, false, &yul::test::StackLayoutGeneratorTest::create}, {"Yul Stack Shuffling", "libyul", "yulStackShuffling", false, false, &yul::test::StackShufflingTest::create}, {"Control Flow Side Effects", "libyul", "controlFlowSideEffects", false, false, &yul::test::ControlFlowSideEffectsTest::create}, diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp new file mode 100644 index 000000000..3c8c964e7 --- /dev/null +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -0,0 +1,453 @@ +/* + 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 + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace solidity; +using namespace solidity::yul::ssa; +using namespace solidity::yul::ssa::test; + +namespace +{ +std::string_view constexpr parserKeyInitialStack {"initial"}; +std::string_view constexpr parserKeyStackTop {"targetStackTop"}; +std::string_view constexpr parserKeyTailSet {"targetStackTailSet"}; +std::string_view constexpr parserKeyStackSize {"targetStackSize"}; + +using Liveness = LivenessAnalysis::LivenessData; +using Slot = StackSlot; +using ValueId = SSACFG::ValueId; +struct StackManipulationCallbacks +{ + void swap(size_t _depth) const + { + if (hook) + (*hook)(fmt::format("SWAP{}", _depth)); + } + void dup(size_t const _depth) const + { + if (hook) + (*hook)(fmt::format("DUP{}", _depth)); + } + void push(Slot const& _slot) const + { + if (hook) + (*hook)(fmt::format("PUSH {}", slotToString(_slot))); + } + void pop() const + { + if (hook) + (*hook)("POP"); + } + + std::optional> hook = std::nullopt; +}; +using TestStack = Stack; + +/// removes leading and trailing whitespace from a string view +std::string_view trim(std::string_view s) +{ + s.remove_prefix(std::min(s.find_first_not_of(" \t\r\v\n"), s.size())); + s.remove_suffix(std::min(s.size() - s.find_last_not_of(" \t\r\v\n") - 1, s.size())); + return s; +} + +/// Parse a value ID token like "v172", "phi109", "lit7", or "JUNK". +Slot parseSlot(std::string_view token) +{ + if (token == "JUNK") + return Slot::makeJunk(); + + if (token.starts_with("v")) + { + if (auto const num = util::parseArithmetic(token.substr(1))) + return Slot::makeValueID(ValueId::makeVariable(*num)); + throw std::runtime_error(fmt::format("Couldn't parse variable token: {}", token)); + } + + if (token.starts_with("phi")) + { + if (auto const num = util::parseArithmetic(token.substr(3))) + return Slot::makeValueID(ValueId::makePhi(*num)); + throw std::runtime_error(fmt::format("Couldn't parse phi token: {}", token)); + } + + if (token.starts_with("lit")) + { + if (auto const num = util::parseArithmetic(token.substr(3))) + return Slot::makeValueID(ValueId::makeLiteral(*num)); + throw std::runtime_error(fmt::format("Couldn't parse literal token: {}", token)); + } + throw std::runtime_error(fmt::format("Unknown token: {}", token)); +} + +/// Parse a string like "[v172, phi109, lit7, JUNK]" into Stack::Data +TestStack::Data parseSlots(std::string_view _input, char const brackBegin = '[', char const brackEnd = ']') +{ + TestStack::Data result; + + // trim and remove brackets + { + _input = trim(_input); + yulAssert(_input.starts_with(brackBegin)); + _input.remove_prefix(1); + yulAssert(_input.ends_with(brackEnd)); + _input.remove_suffix(1); + } + + for (auto&& slotToken: ranges::views::split(_input, ',')) + { + auto const slotTokenBegin = ranges::begin(slotToken); + auto const slotTokenEnd = ranges::end(slotToken); + + std::string_view token; + if(slotTokenBegin != slotTokenEnd) + token = {&*slotTokenBegin, static_cast(ranges::distance(slotTokenBegin, slotTokenEnd))}; + token = trim(token); + yulAssert(!token.empty(), "Empty token."); + result.push_back(parseSlot(token)); + } + return result; +} + +/// Parse liveness like "{phi109, phi150, v172}" +/// Returns Liveness with reference count 1 for each value +Liveness parseLiveness(std::string_view _input) +{ + auto const slots = parseSlots(_input, '{', '}'); + std::vector> liveCounts; + liveCounts.reserve(slots.size()); + for (auto const& slot: slots) + { + yulAssert(slot.isValueID(), "Only value IDs are permitted in liveness definition."); + liveCounts.emplace_back(slot.valueID(), 1); + } + return {liveCounts.begin(), liveCounts.end()}; +} + +struct ShuffleTestInput +{ + std::optional initial; + std::optional targetStackTop; + std::optional targetStackTailSet; + std::optional targetStackSize; + + bool valid() const + { + return initial.has_value() && + targetStackTop.has_value() && + targetStackTailSet.has_value() && + targetStackSize.has_value(); + } + + static ShuffleTestInput parse(std::string_view _source) + { + ShuffleTestInput result; + + auto const stripComment = [](std::string_view sv) -> std::string_view + { + auto const pos = sv.find("//"); + if (pos != std::string_view::npos) + return sv.substr(0, pos); + return sv; + }; + + for (auto&& lineRange: ranges::views::split(_source, '\n')) + { + auto lineBegin = ranges::begin(lineRange); + auto lineEnd = ranges::end(lineRange); + if (lineBegin == lineEnd) + continue; + + std::string_view line{&*lineBegin, static_cast(ranges::distance(lineBegin, lineEnd))}; + line = trim(stripComment(line)); + if (line.empty()) + continue; + + auto const colonPos = line.find(':'); + if (colonPos == std::string_view::npos) + continue; + + auto const key = trim(line.substr(0, colonPos)); + auto const value = trim(line.substr(colonPos + 1)); + + if (key == parserKeyInitialStack) + result.initial = parseSlots(value, '[', ']'); + else if (key == parserKeyStackTop) + result.targetStackTop = parseSlots(value, '[', ']'); + else if (key == parserKeyTailSet) + result.targetStackTailSet = parseLiveness(value); + else if (key == parserKeyStackSize) + { + if (auto num = util::parseArithmetic(value)) + result.targetStackSize = *num; + else + throw std::runtime_error(fmt::format("Couldn't parse targetStackSize: {}", value)); + } + + } + return result; + } +}; + +/// Records a shuffling trace and produces formatted output into some ostream when going out of scope +class TraceRecorder +{ + static size_t constexpr operationColumnWidth = 12; + static size_t constexpr slotColumnWidth = 7; + static char constexpr junkSymbol = '*'; + +public: + TraceRecorder(std::ostream& _out, TestStack::Data const& _targetArgs, Liveness const& _targetTail, size_t _targetStackSize): + m_out(_out), + m_targetArgs(_targetArgs), + m_targetTail(_targetTail), + m_targetStackSize(_targetStackSize), + m_targetTailSize( + [&] { + yulAssert(_targetStackSize >= m_targetArgs.size()); + return _targetStackSize - m_targetArgs.size(); + }() + ) + {} + + void record(std::string const& _operation, TestStack::Data const& _stack) + { + m_entries.push_back(TraceEntry{_operation, _stack}); + } + + ~TraceRecorder() + { + if (m_entries.empty()) + return; + + size_t maxStackDepth = 0; + for (const auto& [operation, stackAfter]: m_entries) + maxStackDepth = std::max(maxStackDepth, stackAfter.size()); + + if (maxStackDepth == 0) + return; + + bool const hasExcess = maxStackDepth > m_targetStackSize; + + emitHeader(maxStackDepth, hasExcess); + emitSeparatorLine(maxStackDepth, hasExcess); + for (auto const& entry: m_entries) + emitDataRow(entry, hasExcess); + emitSeparatorLine(maxStackDepth, hasExcess); + emitTargetRow(hasExcess); + } + +private: + struct TraceEntry { + std::string operation; + TestStack::Data stackAfter; + }; + + std::ostream& m_out; + std::vector m_entries; + TestStack::Data const& m_targetArgs; + Liveness const& m_targetTail; + size_t const m_targetStackSize; + size_t const m_targetTailSize; + + void emitSeparator(size_t const _index, bool const _hasExcess, char const _junction) const + { + bool const endOfTargetTail = _index == m_targetTailSize && !m_targetArgs.empty() && m_targetTailSize > 0; + bool const endOfTargetStackWithExcess = _hasExcess && _index == m_targetTailSize + m_targetArgs.size(); + if (endOfTargetTail || endOfTargetStackWithExcess) + m_out << ' ' << _junction; + } + + void emitHeader(size_t const _maxStackDepth, bool const _hasExcess) const + { + m_out << fmt::format("{:>{}}", "", operationColumnWidth) << "|"; + for (size_t i = 0; i < _maxStackDepth; ++i) + { + emitSeparator(i, _hasExcess, '|'); + m_out << fmt::format("{:>{}}", i, slotColumnWidth); + } + m_out << "\n"; + } + + void emitSeparatorLine(size_t const _maxStackDepth, bool const _hasExcess) const + { + m_out << fmt::format("{:>{}}", "", operationColumnWidth) << '+'; + for (size_t i = 0; i < _maxStackDepth; ++i) + { + emitSeparator(i, _hasExcess, '+'); + m_out << std::string(slotColumnWidth, '-'); + } + m_out << '\n'; + } + + void emitDataRow(TraceEntry const& _entry, bool const _hasExcess) const + { + m_out << fmt::format("{:>{}}", _entry.operation, operationColumnWidth) << "|"; + for (size_t i = 0; i < _entry.stackAfter.size(); ++i) + { + emitSeparator(i, _hasExcess, '|'); + auto const& slot = _entry.stackAfter[i]; + std::string slotStr = slot.isJunk() ? std::string(1, junkSymbol) : slotToString(slot); + m_out << fmt::format("{:>{}}", slotStr, slotColumnWidth); + } + m_out << '\n'; + } + + void emitTargetRow(bool const _hasExcess) const + { + m_out << fmt::format("{:>{}}", "(target)", operationColumnWidth) << "|"; + + // Print tail region with set notation + if (m_targetTailSize > 0 && !(m_targetTail.empty() && m_targetArgs.empty())) + { + std::string const tailSetStr = fmt::format( + "{{{}}}", + fmt::join( + m_targetTail | ranges::views::keys | ranges::views::transform( + [](auto const& id) { return slotToString(Slot::makeValueID(id)); } + ), + ", " + ) + ); + m_out << fmt::format("{:>{}}", tailSetStr, m_targetTailSize * slotColumnWidth); + } + + // Args separator + if (!m_targetArgs.empty() && m_targetTailSize > 0) + m_out << " |"; + + // Print args region + for (auto const& slot: m_targetArgs) + { + std::string slotStr = slot.isJunk() ? std::string(1, junkSymbol) : slotToString(slot); + m_out << fmt::format("{:>{}}", slotStr, slotColumnWidth); + } + + // Excess separator + if (_hasExcess) + m_out << " |"; + + m_out << '\n'; + } +}; +} + +std::unique_ptr ShufflingTest::create(Config const& _config) +{ + return std::make_unique(_config.filename); +} + +ShufflingTest::ShufflingTest(std::string const& _filename): TestCase(_filename) +{ + m_source = m_reader.source(); + auto dialectName = m_reader.stringSetting("dialect", "evm"); + soltestAssert(dialectName == "evm"); + m_expectation = m_reader.simpleExpectations(); +} + +ShufflingTest::TestResult ShufflingTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) +{ + auto const testConfig = ShuffleTestInput::parse(m_source); + if (!testConfig.valid()) + { + static constexpr std::string_view formatHelp = R"(initial: [, ...] +targetStackTop: [, ...] +targetStackTailSet: {, ...} +targetStackSize: + +Where is one of: + v - variable + phi - phi node + lit - literal + JUNK - junk slot + +Lines starting with // are comments. Comments at the end of lines are supported, too.)"; + util::AnsiColorized out(_stream, _formatted, {util::formatting::BOLD, util::formatting::RED}); + out << _linePrefix << fmt::format("Error parsing source. Expected format:") << '\n'; + + for (auto const line: ranges::views::split(formatHelp, '\n')) + { + auto const lineSVBegin = ranges::begin(line); + auto const lineSVEnd = ranges::end(line); + std::string_view lineSV; + if (lineSVBegin != lineSVEnd) + lineSV = {&*lineSVBegin, static_cast(ranges::distance(lineSVBegin, lineSVEnd))}; + out << _linePrefix << " " << lineSV << '\n'; + } + return TestResult::FatalError; + } + + auto stackData = *testConfig.initial; + std::ostringstream oss; + { + TraceRecorder trace(oss, *testConfig.targetStackTop, *testConfig.targetStackTailSet, *testConfig.targetStackSize); + trace.record("(initial)", *testConfig.initial); + TestStack stack(stackData, {.hook = [&](std::string const& op){ trace.record(op, stackData); }}); + StackShuffler::shuffle( + stack, + *testConfig.targetStackTop, + *testConfig.targetStackTailSet, + *testConfig.targetStackSize + ); + } + // check stack data + { + yulAssert(*testConfig.targetStackSize >= testConfig.targetStackTop->size()); + auto const tailSize = *testConfig.targetStackSize - testConfig.targetStackTop->size(); + yulAssert(stackData.size() == *testConfig.targetStackSize); + for (const auto& valueID: *testConfig.targetStackTailSet | ranges::views::keys) + { + auto const findIt = ranges::find( + stackData.begin(), + stackData.begin() + static_cast(tailSize), + StackSlot::makeValueID(valueID) + ); + yulAssert(findIt != ranges::end(stackData)); + } + for (std::size_t offset = tailSize; offset < *testConfig.targetStackSize; ++offset) + { + auto const& targetSlot = testConfig.targetStackTop->at(offset - tailSize); + yulAssert(targetSlot.isJunk() || stackData[offset] == targetSlot); + } + } + m_obtainedResult = oss.str(); + + + return checkResult(_stream, _linePrefix, _formatted); +} diff --git a/test/libyul/ssa/StackShufflerTest.h b/test/libyul/ssa/StackShufflerTest.h new file mode 100644 index 000000000..14b0d98f6 --- /dev/null +++ b/test/libyul/ssa/StackShufflerTest.h @@ -0,0 +1,36 @@ +/* + 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 + +#pragma once + +#include + +#include + +namespace solidity::yul::ssa::test +{ + +class ShufflingTest: public frontend::test::TestCase +{ +public: + static std::unique_ptr create(Config const& _config); + explicit ShufflingTest(std::string const& _filename); + TestResult run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) override; +}; + +} diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 31bdf34ee..7b7331c77 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -53,6 +53,8 @@ add_executable(isoltest ../libyul/YulOptimizerTest.cpp ../libyul/YulOptimizerTestCommon.cpp ../libyul/YulInterpreterTest.cpp + ../libyul/ssa/StackShufflerTest.cpp + ../libyul/ssa/StackShufflerTest.h ) target_compile_definitions(isoltest PRIVATE ISOLTEST) target_link_libraries(isoltest PRIVATE evmc libsolc solidity yulInterpreter evmasm Boost::boost Boost::program_options Boost::unit_test_framework Threads::Threads) From 70d774f70ac92a22cacc3b8b038f6f8034c3a960 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 2 Feb 2026 12:14:43 +0100 Subject: [PATCH 1116/1340] Add stack shuffler tests --- .../deep_argument_dup_order.stack | 14 ++ .../stackShuffler/deep_argument_shrink.stack | 20 +++ .../ssa/stackShuffler/dup_up_args.stack | 18 +++ test/libyul/ssa/stackShuffler/empty.stack | 14 ++ test/libyul/ssa/stackShuffler/grow.stack | 12 ++ .../ssa/stackShuffler/introduce_junk.stack | 17 +++ .../ssa/stackShuffler/reduce_size.stack | 13 ++ .../satisfy_tail_requirements.stack | 30 +++++ .../stackShuffler/shrink_and_grow_a_lot.stack | 122 ++++++++++++++++++ .../stackShuffler/superfluous_top_slots.stack | 18 +++ .../stackShuffler/swap_junk_over_pop.stack | 14 ++ 11 files changed, 292 insertions(+) create mode 100644 test/libyul/ssa/stackShuffler/deep_argument_dup_order.stack create mode 100644 test/libyul/ssa/stackShuffler/deep_argument_shrink.stack create mode 100644 test/libyul/ssa/stackShuffler/dup_up_args.stack create mode 100644 test/libyul/ssa/stackShuffler/empty.stack create mode 100644 test/libyul/ssa/stackShuffler/grow.stack create mode 100644 test/libyul/ssa/stackShuffler/introduce_junk.stack create mode 100644 test/libyul/ssa/stackShuffler/reduce_size.stack create mode 100644 test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack create mode 100644 test/libyul/ssa/stackShuffler/shrink_and_grow_a_lot.stack create mode 100644 test/libyul/ssa/stackShuffler/superfluous_top_slots.stack create mode 100644 test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack diff --git a/test/libyul/ssa/stackShuffler/deep_argument_dup_order.stack b/test/libyul/ssa/stackShuffler/deep_argument_dup_order.stack new file mode 100644 index 000000000..3dbbcf438 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/deep_argument_dup_order.stack @@ -0,0 +1,14 @@ +// if lit0 is pushed first, v129 can no longer be duped up +initial: [v129, v43, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v101, JUNK, v130, v131] +targetStackTop: [v43, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, lit0, v129] +targetStackTailSet: {v129} +targetStackSize: 18 +// ---- +// | 0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +// +------- +----------------------------------------------------------------------------------------------------------------------- +// (initial)| v129 | v43 * * * * * * * * * * v101 * v130 v131 +// DUP16| v129 | v43 * * * * * * * * * * v101 * v130 v131 v129 +// PUSH lit0| v129 | v43 * * * * * * * * * * v101 * v130 v131 v129 lit0 +// SWAP1| v129 | v43 * * * * * * * * * * v101 * v130 v131 lit0 v129 +// +------- +----------------------------------------------------------------------------------------------------------------------- +// (target)| {v129} | v43 * * * * * * * * * * * * * * lit0 v129 diff --git a/test/libyul/ssa/stackShuffler/deep_argument_shrink.stack b/test/libyul/ssa/stackShuffler/deep_argument_shrink.stack new file mode 100644 index 000000000..b7fdbcbaf --- /dev/null +++ b/test/libyul/ssa/stackShuffler/deep_argument_shrink.stack @@ -0,0 +1,20 @@ +// the shuffler has to first shrink the stack to reach v12 for args +initial: [v12, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v68, JUNK, phi111, v84, v86] +targetStackTop: [v12, v86] +targetStackTailSet: {v68, v84, phi111} +targetStackSize: 19 +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 17 18 +// +----------------------------------------------------------------------------------------------------------------------- +-------------- +// (initial)| v12 * * * * * * * * * * * * v68 * phi111 v84 | v86 +// SWAP3| v12 * * * * * * * * * * * * v68 v86 phi111 v84 | * +// POP| v12 * * * * * * * * * * * * v68 v86 phi111 v84 +// SWAP2| v12 * * * * * * * * * * * * v68 v84 phi111 v86 +// SWAP4| v12 * * * * * * * * * * * v86 v68 v84 phi111 * +// POP| v12 * * * * * * * * * * * v86 v68 v84 phi111 +// SWAP15| phi111 * * * * * * * * * * * v86 v68 v84 v12 +// DUP4| phi111 * * * * * * * * * * * v86 v68 v84 v12 v86 +// DUP2| phi111 * * * * * * * * * * * v86 v68 v84 v12 v86 | v12 +// DUP2| phi111 * * * * * * * * * * * v86 v68 v84 v12 v86 | v12 v86 +// +----------------------------------------------------------------------------------------------------------------------- +-------------- +// (target)| {v68, v84, phi111} | v12 v86 diff --git a/test/libyul/ssa/stackShuffler/dup_up_args.stack b/test/libyul/ssa/stackShuffler/dup_up_args.stack new file mode 100644 index 000000000..f3be04a89 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/dup_up_args.stack @@ -0,0 +1,18 @@ +// populate args by a sequence of dups +initial: [JUNK, v12, phi9, phi13, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v65, v67] +targetStackTop: [lit27, phi13, phi9, v12, v67] +targetStackTailSet: {phi9, v12, phi13, v65} +targetStackSize: 21 +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 16 17 18 19 20 +// +---------------------------------------------------------------------------------------------------------------- +----------------------------------- +// (initial)| * v12 phi9 phi13 * * * * * * * * v65 v67 +// DUP13| * v12 phi9 phi13 * * * * * * * * v65 v67 v12 +// DUP13| * v12 phi9 phi13 * * * * * * * * v65 v67 v12 phi9 +// PUSH lit27| * v12 phi9 phi13 * * * * * * * * v65 v67 v12 phi9 | lit27 +// DUP14| * v12 phi9 phi13 * * * * * * * * v65 v67 v12 phi9 | lit27 phi13 +// DUP3| * v12 phi9 phi13 * * * * * * * * v65 v67 v12 phi9 | lit27 phi13 phi9 +// DUP5| * v12 phi9 phi13 * * * * * * * * v65 v67 v12 phi9 | lit27 phi13 phi9 v12 +// DUP7| * v12 phi9 phi13 * * * * * * * * v65 v67 v12 phi9 | lit27 phi13 phi9 v12 v67 +// +---------------------------------------------------------------------------------------------------------------- +----------------------------------- +// (target)| {phi9, v12, phi13, v65} | lit27 phi13 phi9 v12 v67 diff --git a/test/libyul/ssa/stackShuffler/empty.stack b/test/libyul/ssa/stackShuffler/empty.stack new file mode 100644 index 000000000..077660d6f --- /dev/null +++ b/test/libyul/ssa/stackShuffler/empty.stack @@ -0,0 +1,14 @@ +// populate an empty stack with junk +initial: [] +targetStackTop: [] +targetStackTailSet: {} +targetStackSize: 3 +// ---- +// | 0 1 2 +// +--------------------- +// (initial)| +// PUSH JUNK| * +// PUSH JUNK| * * +// PUSH JUNK| * * * +// +--------------------- +// (target)| diff --git a/test/libyul/ssa/stackShuffler/grow.stack b/test/libyul/ssa/stackShuffler/grow.stack new file mode 100644 index 000000000..4c07f8e36 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/grow.stack @@ -0,0 +1,12 @@ +// need to grow the stack to reach target stack size but still fulfill args requirements +initial: [JUNK, JUNK, JUNK, v15] +targetStackTop: [JUNK, JUNK, JUNK, JUNK, v15] +targetStackTailSet: {} +targetStackSize: 5 +// ---- +// | 0 1 2 3 4 +// +----------------------------------- +// (initial)| * * * v15 +// DUP1| * * * v15 v15 +// +----------------------------------- +// (target)| * * * * v15 diff --git a/test/libyul/ssa/stackShuffler/introduce_junk.stack b/test/libyul/ssa/stackShuffler/introduce_junk.stack new file mode 100644 index 000000000..54b29a9a3 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/introduce_junk.stack @@ -0,0 +1,17 @@ +// some of the slots in the initial stack no longer appear in the target / are junk +initial: [v189, phi112, JUNK, v204, JUNK, JUNK, JUNK, v185, JUNK, v188, v190, v191, JUNK, v199, phi112, phi112, v205, v206] +targetStackTop: [v199, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v185, JUNK, v188, v190, v191, JUNK, v189, JUNK, v206, v205, v204] +targetStackTailSet: {} +targetStackSize: 18 +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +// +------------------------------------------------------------------------------------------------------------------------------ +// (initial)| v189 phi112 * v204 * * * v185 * v188 v190 v191 * v199 phi112 phi112 v205 v206 +// SWAP2| v189 phi112 * v204 * * * v185 * v188 v190 v191 * v199 phi112 v206 v205 phi112 +// POP| v189 phi112 * v204 * * * v185 * v188 v190 v191 * v199 phi112 v206 v205 +// SWAP16| v205 phi112 * v204 * * * v185 * v188 v190 v191 * v199 phi112 v206 v189 +// SWAP3| v205 phi112 * v204 * * * v185 * v188 v190 v191 * v189 phi112 v206 v199 +// SWAP16| v199 phi112 * v204 * * * v185 * v188 v190 v191 * v189 phi112 v206 v205 +// DUP14| v199 phi112 * v204 * * * v185 * v188 v190 v191 * v189 phi112 v206 v205 v204 +// +------------------------------------------------------------------------------------------------------------------------------ +// (target)| v199 * * * * * * v185 * v188 v190 v191 * v189 * v206 v205 v204 diff --git a/test/libyul/ssa/stackShuffler/reduce_size.stack b/test/libyul/ssa/stackShuffler/reduce_size.stack new file mode 100644 index 000000000..d6a670619 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/reduce_size.stack @@ -0,0 +1,13 @@ +// v199 can be popped as it's already contained in the tail +initial: [JUNK, v189, phi112, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v185, phi115, v188, v190, v191, phi113, v199, phi112, v199, v202] +targetStackTop: [v202] +targetStackTailSet: {phi112, phi113, phi115, v185, v188, v189, v190, v191, v199} +targetStackSize: 19 +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 18 | 19 +// +------------------------------------------------------------------------------------------------------------------------------ +------- +------- +// (initial)| * v189 phi112 * * * * * * * v185 phi115 v188 v190 v191 phi113 v199 phi112 | v199 | v202 +// SWAP1| * v189 phi112 * * * * * * * v185 phi115 v188 v190 v191 phi113 v199 phi112 | v202 | v199 +// POP| * v189 phi112 * * * * * * * v185 phi115 v188 v190 v191 phi113 v199 phi112 | v202 +// +------------------------------------------------------------------------------------------------------------------------------ +------- +------- +// (target)| {phi112, phi113, phi115, v185, v188, v189, v190, v191, v199} | v202 | diff --git a/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack b/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack new file mode 100644 index 000000000..e685f0660 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack @@ -0,0 +1,30 @@ +// here, we have to create one more instance of v10 to be able to satisfy the tail requirements +initial: [v2, v3, v4, v5, v6, v7, v8, v9, v10] +targetStackTop: [lit3, v9, v8, v7, v6, v5, v4, v3, v2, v10] +targetStackTailSet: {v10} +targetStackSize: 17 +// ---- +// | 0 1 2 3 4 5 6 | 7 8 9 10 11 12 13 14 15 16 +// +------------------------------------------------- +---------------------------------------------------------------------- +// (initial)| v2 v3 v4 v5 v6 v7 v8 | v9 v10 +// DUP1| v2 v3 v4 v5 v6 v7 v8 | v9 v10 v10 +// SWAP9| v10 v3 v4 v5 v6 v7 v8 | v9 v10 v2 +// SWAP2| v10 v3 v4 v5 v6 v7 v8 | v2 v10 v9 +// SWAP1| v10 v3 v4 v5 v6 v7 v8 | v2 v9 v10 +// PUSH lit3| v10 v3 v4 v5 v6 v7 v8 | v2 v9 v10 lit3 +// SWAP3| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v10 v2 +// DUP5| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v10 v2 v8 +// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v2 v10 +// DUP7| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v2 v10 v7 +// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v10 v2 +// DUP9| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v10 v2 v6 +// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v2 v10 +// DUP11| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v2 v10 v5 +// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v10 v2 +// DUP13| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v10 v2 v4 +// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v2 v10 +// DUP15| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v2 v10 v3 +// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v3 v10 v2 +// SWAP1| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v3 v2 v10 +// +------------------------------------------------- +---------------------------------------------------------------------- +// (target)| {v10} | lit3 v9 v8 v7 v6 v5 v4 v3 v2 v10 diff --git a/test/libyul/ssa/stackShuffler/shrink_and_grow_a_lot.stack b/test/libyul/ssa/stackShuffler/shrink_and_grow_a_lot.stack new file mode 100644 index 000000000..7d4f68a8a --- /dev/null +++ b/test/libyul/ssa/stackShuffler/shrink_and_grow_a_lot.stack @@ -0,0 +1,122 @@ +// the stack top needs a very deep slot +initial: [v55, v71, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v94] +targetStackTop: [lit11, v55] +targetStackTailSet: {v55, v71, v94} +targetStackSize: 54 +// todo: instead of alternating swap1 + pop, we should be (eg) doing swap16 and then a sequence of 16 pops +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 52 53 +// +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-------------- +// (initial)| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * * v94 +// SWAP1| v55 v71 * * * * * * * * * * * * * v94 * +// POP| v55 v71 * * * * * * * * * * * * * v94 +// DUP16| v55 v71 * * * * * * * * * * * * * v94 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// DUP1| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 +// PUSH lit11| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 | lit11 +// DUP2| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 | lit11 v55 +// +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-------------- +// (target)| {v55, v71, v94} | lit11 v55 diff --git a/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack b/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack new file mode 100644 index 000000000..87d9ea9a8 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack @@ -0,0 +1,18 @@ +// todo: The upper two junk slots should be popped immediately, they are completely superfluous. +initial: [JUNK, JUNK, v56, v57, JUNK, JUNK] +targetStackTop: [JUNK, JUNK, v56, v57, lit0, v56, lit11] +targetStackTailSet: {} +targetStackSize: 7 +// ---- +// | 0 1 2 3 4 5 6 | 7 +// +------------------------------------------------- +------- +// (initial)| * * v56 v57 * * +// PUSH lit11| * * v56 v57 * * lit11 +// DUP5| * * v56 v57 * * lit11 | v56 +// SWAP2| * * v56 v57 * v56 lit11 | * +// POP| * * v56 v57 * v56 lit11 +// PUSH lit0| * * v56 v57 * v56 lit11 | lit0 +// SWAP3| * * v56 v57 lit0 v56 lit11 | * +// POP| * * v56 v57 lit0 v56 lit11 +// +------------------------------------------------- +------- +// (target)| * * v56 v57 lit0 v56 lit11 | diff --git a/test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack b/test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack new file mode 100644 index 000000000..56f623b75 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack @@ -0,0 +1,14 @@ +// here, the algorithm should prefer a swap of junk into tail over pop and dup +initial: [v0, JUNK, v2] +targetStackTop: [lit2, v2, v0] +targetStackTailSet: {} +targetStackSize: 4 +// ---- +// | 0 | 1 2 3 +// +------- +--------------------- +// (initial)| v0 | * v2 +// PUSH lit2| v0 | * v2 lit2 +// SWAP2| v0 | lit2 v2 * +// SWAP3| * | lit2 v2 v0 +// +------- +--------------------- +// (target)| {} | lit2 v2 v0 From 8f643082c250abbebba5a4f81d88129041ca4e4a Mon Sep 17 00:00:00 2001 From: Tilak Madichetti Date: Sat, 29 Mar 2025 13:14:35 +0530 Subject: [PATCH 1117/1340] Update resources.rst --- docs/resources.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/resources.rst b/docs/resources.rst index 52df87fdd..3dac252ee 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -107,7 +107,7 @@ Solidity Tools Tool to generate Solidity interface source from a given ABI JSON. * `Aderyn `_ - Rust-based solidity smart contract static analyzer designed to help find vulnerabilities in Solidity code bases. + Rust-based solidity smart contract static analyzer designed to help find vulnerabilities in Solidity code bases. Comes with `VS Code Extension ` for easy use. * `Doxity `_ Documentation Generator for Solidity. From 1a499f10f0fd4cfc0563bd1770627573c0086c5b Mon Sep 17 00:00:00 2001 From: Tilak Madichetti Date: Mon, 23 Jun 2025 08:22:18 +0000 Subject: [PATCH 1118/1340] fix --- docs/resources.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/resources.rst b/docs/resources.rst index 3dac252ee..7fdb55367 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -78,6 +78,9 @@ Editor Integrations * Visual Studio Code (VS Code) + * `Aderyn Visual Studio Code extension `_ + Solidity Smart contract analyzer designed to help find vulnerabilities. It supports projects built with Hardhat, Foundry, or any custom framework. + * `Ethereum Remix Visual Studio Code extension `_ Ethereum Remix extension pack for VS Code 💡 Note: As per the official repository, this extension has been removed from the VSCODE marketplace and will be replaced by a dedicated stand-alone desktop application. @@ -107,7 +110,7 @@ Solidity Tools Tool to generate Solidity interface source from a given ABI JSON. * `Aderyn `_ - Rust-based solidity smart contract static analyzer designed to help find vulnerabilities in Solidity code bases. Comes with `VS Code Extension ` for easy use. + Command Line Tool that helps find vulnerabilities in Solidity smart contracts. It supports projects built with Hardhat, Foundry, or any custom framework. * `Doxity `_ Documentation Generator for Solidity. From 7e2fb2d4739e135a9622df778e50af52a05cc134 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 4 Feb 2026 10:30:36 +0100 Subject: [PATCH 1119/1340] Fix `check_style.sh`. Replace `\s` to `[[:space:]]` --- scripts/check_style.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/check_style.sh b/scripts/check_style.sh index 7188f84f2..5a744de78 100755 --- a/scripts/check_style.sh +++ b/scripts/check_style.sh @@ -47,19 +47,19 @@ FORMATERROR=$( ( preparedGrep "#include \"" | grep -E -v -e "license.h" -e "BuildInfo.h" # Use include with <> characters preparedGrep "\<(if|for|while|switch)\(" # no space after "if", "for", "while" or "switch" - preparedGrep "\\s*\([^=]*\>\s:\s.*\)" # no space before range based for-loop - preparedGrep "\\s*\(.*\)\s*\{\s*$" # "{\n" on same line as "if" + preparedGrep "\[[:space:]]*\([^=]*\>[[:space:]]:[[:space:]].*\)" # no space before range based for-loop + preparedGrep "\[[:space:]]*\(.*\)[[:space:]]*\{[[:space:]]*$" # "{\n" on same line as "if" preparedGrep "namespace .*\{" - preparedGrep "[,\(<]\s*const " # const on left side of type - preparedGrep "^\s*(static)?\s*const " # const on left side of type (beginning of line) + preparedGrep "[,\(<][[:space:]]*const " # const on left side of type + preparedGrep "^[[:space:]]*(static)?[[:space:]]*const " # const on left side of type (beginning of line) preparedGrep "^ [^*]|[^*] | [^*]" # uses spaces for indentation or mixes spaces and tabs - preparedGrep "[a-zA-Z0-9_]\s*[&][a-zA-Z_]" | grep -E -v "return [&]" # right-aligned reference ampersand (needs to exclude return) + preparedGrep "[a-zA-Z0-9_][[:space:]]*[&][a-zA-Z_]" | grep -E -v "return [&]" # right-aligned reference ampersand (needs to exclude return) # right-aligned reference pointer star (needs to exclude return and comments) - preparedGrep "[a-zA-Z0-9_]\s*[*][a-zA-Z_]" | grep -E -v -e "return [*]" -e ":[0-9]+:\s*\*\s" -e "//" + preparedGrep "[a-zA-Z0-9_][[:space:]]*[*][a-zA-Z_]" | grep -E -v -e "return [*]" -e ":[0-9]+:[[:space:]]*\*[[:space:]]" -e "//" # unqualified move()/forward() checks, i.e. make sure that std::move() and std::forward() are used instead of move() and forward() preparedGrep "move\(.+\)" | grep -v "std::move" | grep -E "[^a-z]move" preparedGrep "forward\(.+\)" | grep -v "std::forward" | grep -E "[^a-z]forward" -) | grep -E -v -e "^[a-zA-Z./]*:[0-9]*:\s*/[/*]" -e "^test/" || true +) | grep -E -v -e "^[a-zA-Z./]*:[0-9]*:[[:space:]]*/[/*]" -e "^test/" || true ) # Special error handling for `using namespace std;` exclusion, since said statement can be present in the test directory From 64f26d919034c0e9060a90386bcd76d434f13129 Mon Sep 17 00:00:00 2001 From: davidekete Date: Sat, 7 Feb 2026 15:27:12 +0100 Subject: [PATCH 1120/1340] update information about using Remix offline --- docs/installing-solidity.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index f061829ec..7e372ea4e 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -31,8 +31,7 @@ Remix *We recommend Remix for small contracts and for quickly learning Solidity.* `Access Remix online `_, you do not need to install anything. -If you want to use it without connection to the Internet, go to -https://github.com/ethereum/remix-live/tree/gh-pages#readme and follow the instructions on that page. +If you want to use it without connection to the Internet, download Remix Desktop from `the releases page `_. Remix is also a convenient option for testing nightly builds without installing multiple Solidity versions. From 39bf0830b80fd5de8dbac5312d78c0e4eec8f0ad Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 9 Feb 2026 11:18:53 +0100 Subject: [PATCH 1121/1340] move SSACFGTopologicalSort -> traversal/ForwardTopologicalSort --- libyul/CMakeLists.txt | 4 ++-- .../backends/evm/ssa/JunkAdmittingBlocksFinder.cpp | 2 +- libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.h | 4 ++-- libyul/backends/evm/ssa/LivenessAnalysis.h | 6 +++--- libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp | 2 +- libyul/backends/evm/ssa/SSACFGLoopNestingForest.h | 6 +++--- .../ForwardTopologicalSort.cpp} | 12 ++++++------ .../ForwardTopologicalSort.h} | 6 +++--- 8 files changed, 21 insertions(+), 21 deletions(-) rename libyul/backends/evm/ssa/{SSACFGTopologicalSort.cpp => traversal/ForwardTopologicalSort.cpp} (83%) rename libyul/backends/evm/ssa/{SSACFGTopologicalSort.h => traversal/ForwardTopologicalSort.h} (94%) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 9d0bfe1e2..2e62f6d94 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -82,8 +82,6 @@ add_library(yul backends/evm/ssa/LivenessAnalysis.h backends/evm/ssa/SSACFGLoopNestingForest.cpp backends/evm/ssa/SSACFGLoopNestingForest.h - backends/evm/ssa/SSACFGTopologicalSort.cpp - backends/evm/ssa/SSACFGTopologicalSort.h backends/evm/ssa/SSACFG.cpp backends/evm/ssa/SSACFG.h backends/evm/ssa/SSACFGBuilder.cpp @@ -94,6 +92,8 @@ add_library(yul backends/evm/ssa/Stack.h backends/evm/ssa/StackShuffler.cpp backends/evm/ssa/StackShuffler.h + backends/evm/ssa/traversal/ForwardTopologicalSort.cpp + backends/evm/ssa/traversal/ForwardTopologicalSort.h optimiser/ASTCopier.cpp optimiser/ASTCopier.h optimiser/ASTWalker.cpp diff --git a/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.cpp b/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.cpp index d7c9202ef..e0519db61 100644 --- a/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.cpp +++ b/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.cpp @@ -23,7 +23,7 @@ namespace solidity::yul::ssa { -JunkAdmittingBlocksFinder::JunkAdmittingBlocksFinder(SSACFG const& _cfg, ForwardSSACFGTopologicalSort const& _topologicalSort): +JunkAdmittingBlocksFinder::JunkAdmittingBlocksFinder(SSACFG const& _cfg, traversal::ForwardTopologicalSort const& _topologicalSort): m_blockAllowsJunk(_cfg.numBlocks(), false) { // special case: only one block here, we mark it as junkable in case it's not a function return diff --git a/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.h b/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.h index e567603dd..6d2104b03 100644 --- a/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.h +++ b/libyul/backends/evm/ssa/JunkAdmittingBlocksFinder.h @@ -18,7 +18,7 @@ #pragma once -#include +#include #include #include @@ -37,7 +37,7 @@ namespace solidity::yul::ssa class JunkAdmittingBlocksFinder { public: - explicit JunkAdmittingBlocksFinder(SSACFG const& _cfg, ForwardSSACFGTopologicalSort const& _topologicalSort); + explicit JunkAdmittingBlocksFinder(SSACFG const& _cfg, traversal::ForwardTopologicalSort const& _topologicalSort); bool allowsAdditionOfJunk(SSACFG::BlockId const& _blockId) const; private: std::vector m_blockAllowsJunk; diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.h b/libyul/backends/evm/ssa/LivenessAnalysis.h index b34a790bf..5a19cb0bd 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.h +++ b/libyul/backends/evm/ssa/LivenessAnalysis.h @@ -18,7 +18,7 @@ #pragma once -#include +#include #include #include @@ -107,7 +107,7 @@ class LivenessAnalysis LivenessData const& liveOut(SSACFG::BlockId const _blockId) const { return m_liveOuts[_blockId.value]; } LivenessData used(SSACFG::BlockId _blockId) const; std::vector const& operationsLiveOut(SSACFG::BlockId _blockId) const { return m_operationLiveOuts[_blockId.value]; } - ForwardSSACFGTopologicalSort const& topologicalSort() const { return m_topologicalSort; } + traversal::ForwardTopologicalSort const& topologicalSort() const { return m_topologicalSort; } SSACFG const& cfg() const { return m_cfg; } private: @@ -117,7 +117,7 @@ class LivenessAnalysis LivenessData blockExitValues(SSACFG::BlockId const& _blockId) const; SSACFG const& m_cfg; - ForwardSSACFGTopologicalSort m_topologicalSort; + traversal::ForwardTopologicalSort m_topologicalSort; SSACFGLoopNestingForest m_loopNestingForest; std::vector m_liveIns; std::vector m_liveOuts; diff --git a/libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp index c5c422a46..6adff4023 100644 --- a/libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp +++ b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.cpp @@ -22,7 +22,7 @@ using namespace solidity::yul::ssa; -SSACFGLoopNestingForest::SSACFGLoopNestingForest(ForwardSSACFGTopologicalSort const& _sort): +SSACFGLoopNestingForest::SSACFGLoopNestingForest(traversal::ForwardTopologicalSort const& _sort): m_sort(_sort), m_cfg(_sort.cfg()), m_vertexPartition(m_cfg.numBlocks()), diff --git a/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h index 4654cbf13..2ee833335 100644 --- a/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h +++ b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h @@ -18,7 +18,7 @@ #pragma once -#include +#include #include #include @@ -39,7 +39,7 @@ class SSACFGLoopNestingForest using BlockIdValue = SSACFG::BlockId::ValueType; public: - explicit SSACFGLoopNestingForest(ForwardSSACFGTopologicalSort const& _sort); + explicit SSACFGLoopNestingForest(traversal::ForwardTopologicalSort const& _sort); /// blocks which are not contained in a loop get assigned the loop parent numeric_limit::max() std::vector const& loopParents() const { return m_loopParents; } @@ -51,7 +51,7 @@ class SSACFGLoopNestingForest void findLoop(BlockIdValue _potentialHeader); void collapse(std::set const& _loopBody, BlockIdValue _loopHeader); - ForwardSSACFGTopologicalSort const& m_sort; + traversal::ForwardTopologicalSort const& m_sort; SSACFG const& m_cfg; util::ContiguousDisjointSet m_vertexPartition; diff --git a/libyul/backends/evm/ssa/SSACFGTopologicalSort.cpp b/libyul/backends/evm/ssa/traversal/ForwardTopologicalSort.cpp similarity index 83% rename from libyul/backends/evm/ssa/SSACFGTopologicalSort.cpp rename to libyul/backends/evm/ssa/traversal/ForwardTopologicalSort.cpp index 3a1ca43c5..f880954ab 100644 --- a/libyul/backends/evm/ssa/SSACFGTopologicalSort.cpp +++ b/libyul/backends/evm/ssa/traversal/ForwardTopologicalSort.cpp @@ -16,11 +16,11 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#include -using namespace solidity::yul::ssa; +using namespace solidity::yul::ssa::traversal; -ForwardSSACFGTopologicalSort::ForwardSSACFGTopologicalSort(SSACFG const& _cfg): +ForwardTopologicalSort::ForwardTopologicalSort(SSACFG const& _cfg): m_cfg(_cfg), m_explored(m_cfg.numBlocks(), false), m_blockWisePreOrder(m_cfg.numBlocks(), 0), m_blockWiseMaxSubtreePreOrder(m_cfg.numBlocks(), 0) @@ -35,7 +35,7 @@ ForwardSSACFGTopologicalSort::ForwardSSACFGTopologicalSort(SSACFG const& _cfg): m_backEdgeTargets.insert(v2); } -void ForwardSSACFGTopologicalSort::dfs(SSACFG::BlockId::ValueType const _vertex) { +void ForwardTopologicalSort::dfs(SSACFG::BlockId::ValueType const _vertex) { yulAssert(!m_explored[_vertex]); m_explored[_vertex] = true; m_blockWisePreOrder[_vertex] = static_cast(m_preOrder.size()); @@ -55,7 +55,7 @@ void ForwardSSACFGTopologicalSort::dfs(SSACFG::BlockId::ValueType const _vertex) m_postOrder.push_back(_vertex); } -bool ForwardSSACFGTopologicalSort::ancestor(SSACFG::BlockId::ValueType const _block1, SSACFG::BlockId::ValueType const _block2) const { +bool ForwardTopologicalSort::ancestor(SSACFG::BlockId::ValueType const _block1, SSACFG::BlockId::ValueType const _block2) const { yulAssert(_block1 < m_blockWisePreOrder.size()); yulAssert(_block2 < m_blockWisePreOrder.size()); @@ -67,7 +67,7 @@ bool ForwardSSACFGTopologicalSort::ancestor(SSACFG::BlockId::ValueType const _bl return node1VisitedBeforeNode2 && node2InSubtreeOfNode1; } -bool ForwardSSACFGTopologicalSort::backEdge(SSACFG::BlockId const& _block1, SSACFG::BlockId const& _block2) const +bool ForwardTopologicalSort::backEdge(SSACFG::BlockId const& _block1, SSACFG::BlockId const& _block2) const { if (ancestor(_block2.value, _block1.value)) { diff --git a/libyul/backends/evm/ssa/SSACFGTopologicalSort.h b/libyul/backends/evm/ssa/traversal/ForwardTopologicalSort.h similarity index 94% rename from libyul/backends/evm/ssa/SSACFGTopologicalSort.h rename to libyul/backends/evm/ssa/traversal/ForwardTopologicalSort.h index 39c2eebc3..b11663597 100644 --- a/libyul/backends/evm/ssa/SSACFGTopologicalSort.h +++ b/libyul/backends/evm/ssa/traversal/ForwardTopologicalSort.h @@ -24,14 +24,14 @@ #include #include -namespace solidity::yul::ssa +namespace solidity::yul::ssa::traversal { /// Performs a topological sort on the forward CFG (no back/cross edges) -class ForwardSSACFGTopologicalSort +class ForwardTopologicalSort { public: - explicit ForwardSSACFGTopologicalSort(SSACFG const& _cfg); + explicit ForwardTopologicalSort(SSACFG const& _cfg); std::vector const& preOrder() const { return m_preOrder; } std::vector const& postOrder() const { return m_postOrder; } From d783ff9813bf5243355b882fb1901b1f94c899a7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 9 Feb 2026 11:22:31 +0100 Subject: [PATCH 1122/1340] move SSA CFG json exporter into io subdirectory and namespace --- libyul/CMakeLists.txt | 4 ++-- libyul/YulStack.cpp | 4 ++-- .../{SSACFGJsonExporter.cpp => io/JSONExporter.cpp} | 10 ++++------ .../ssa/{SSACFGJsonExporter.h => io/JSONExporter.h} | 2 +- 4 files changed, 9 insertions(+), 11 deletions(-) rename libyul/backends/evm/ssa/{SSACFGJsonExporter.cpp => io/JSONExporter.cpp} (95%) rename libyul/backends/evm/ssa/{SSACFGJsonExporter.h => io/JSONExporter.h} (95%) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 2e62f6d94..d425283b6 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -86,12 +86,12 @@ add_library(yul backends/evm/ssa/SSACFG.h backends/evm/ssa/SSACFGBuilder.cpp backends/evm/ssa/SSACFGBuilder.h - backends/evm/ssa/SSACFGJsonExporter.cpp - backends/evm/ssa/SSACFGJsonExporter.h backends/evm/ssa/Stack.cpp backends/evm/ssa/Stack.h backends/evm/ssa/StackShuffler.cpp backends/evm/ssa/StackShuffler.h + backends/evm/ssa/io/JSONExporter.cpp + backends/evm/ssa/io/JSONExporter.h backends/evm/ssa/traversal/ForwardTopologicalSort.cpp backends/evm/ssa/traversal/ForwardTopologicalSort.h optimiser/ASTCopier.cpp diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 34de47b92..ae32c0f25 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -405,7 +405,7 @@ Json YulStack::cfgJson() const keepLiteralAssignments ); std::unique_ptr liveness = std::make_unique(*controlFlow); - return ssa::json::exportControlFlow(*controlFlow, liveness.get()); + return ssa::io::json::exportControlFlow(*controlFlow, liveness.get()); }; std::function>)> exportCFGFromSubObjects; diff --git a/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp similarity index 95% rename from libyul/backends/evm/ssa/SSACFGJsonExporter.cpp rename to libyul/backends/evm/ssa/io/JSONExporter.cpp index 9b03c13c9..df4e4d814 100644 --- a/libyul/backends/evm/ssa/SSACFGJsonExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -16,7 +16,7 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#include #include @@ -31,7 +31,7 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::yul::ssa; -using namespace solidity::yul::ssa::json; +using namespace solidity::yul::ssa::io::json; namespace { @@ -134,8 +134,6 @@ Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis Json blocksJson = Json::array(); util::BreadthFirstSearch bfs{{{_entryId}}}; bfs.run([&](SSACFG::BlockId _blockId, auto _addChild) { - auto const& block = _cfg.block(_blockId); - // Convert current block to JSON Json blockJson = toJson(_cfg, _blockId, _liveness); Json exitBlockJson = Json::object(); @@ -166,7 +164,7 @@ Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis [&](SSACFG::BasicBlock::JumpTable const&) { yulAssert(false); } - }, block.exit); + }, _cfg.block(_blockId).exit); blockJson["exit"] = exitBlockJson; blocksJson.emplace_back(blockJson); }); @@ -188,7 +186,7 @@ Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness) } -Json json::exportControlFlow(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness) +Json io::json::exportControlFlow(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness) { if (_liveness) yulAssert(&_liveness->controlFlow.get() == &_controlFlow); diff --git a/libyul/backends/evm/ssa/SSACFGJsonExporter.h b/libyul/backends/evm/ssa/io/JSONExporter.h similarity index 95% rename from libyul/backends/evm/ssa/SSACFGJsonExporter.h rename to libyul/backends/evm/ssa/io/JSONExporter.h index 08f846fc5..5cca634aa 100644 --- a/libyul/backends/evm/ssa/SSACFGJsonExporter.h +++ b/libyul/backends/evm/ssa/io/JSONExporter.h @@ -21,7 +21,7 @@ #include #include -namespace solidity::yul::ssa::json +namespace solidity::yul::ssa::io::json { Json exportControlFlow(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness); From 05457c1f171abe383500d9646d2ee0a860d525d5 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:36:34 +0100 Subject: [PATCH 1123/1340] Add SSA CFG Dot exporter base --- libyul/CMakeLists.txt | 2 + .../backends/evm/ssa/io/DotExporterBase.cpp | 220 ++++++++++++++++++ libyul/backends/evm/ssa/io/DotExporterBase.h | 93 ++++++++ 3 files changed, 315 insertions(+) create mode 100644 libyul/backends/evm/ssa/io/DotExporterBase.cpp create mode 100644 libyul/backends/evm/ssa/io/DotExporterBase.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index d425283b6..d07b25a50 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -90,6 +90,8 @@ add_library(yul backends/evm/ssa/Stack.h backends/evm/ssa/StackShuffler.cpp backends/evm/ssa/StackShuffler.h + backends/evm/ssa/io/DotExporterBase.cpp + backends/evm/ssa/io/DotExporterBase.h backends/evm/ssa/io/JSONExporter.cpp backends/evm/ssa/io/JSONExporter.h backends/evm/ssa/traversal/ForwardTopologicalSort.cpp diff --git a/libyul/backends/evm/ssa/io/DotExporterBase.cpp b/libyul/backends/evm/ssa/io/DotExporterBase.cpp new file mode 100644 index 000000000..23541422a --- /dev/null +++ b/libyul/backends/evm/ssa/io/DotExporterBase.cpp @@ -0,0 +1,220 @@ +/* + 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 + +#include + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtautological-compare" +#include +#pragma GCC diagnostic pop + +#include +#include + +using namespace solidity; +using namespace solidity::util; +using namespace solidity::yul; +using namespace solidity::yul::ssa; +using namespace solidity::yul::ssa::io; + +DotExporterBase::DotExporterBase(SSACFG const& _cfg, size_t const _functionIndex, RankDir const _rankDir): + m_cfg(_cfg), + m_functionIndex(_functionIndex), + m_rankDir(_rankDir) +{ +} + +std::string DotExporterBase::escapeId(std::string_view const _str) +{ + std::string result; + result.reserve(_str.size()); + for (auto const c: _str) + { + if (std::isalnum(static_cast(c)) || c == '_') + result += c; + else + result += '_'; + } + return result; +} + +std::string DotExporterBase::escapeLabel(std::string_view const _str) +{ + std::string result; + result.reserve(_str.size()); + for (auto const c: _str) + { + if (c == '"' || c == '\\') + result += '\\'; + result += c; + } + return result; +} + +std::string DotExporterBase::formatBlockHandle(SSACFG::BlockId _id) const +{ + return fmt::format("Block{}_{}", m_functionIndex, _id.value); +} + +std::string DotExporterBase::formatEdge(SSACFG::BlockId _source, SSACFG::BlockId _target, std::optional const& _exitPort) +{ + std::string const style = edgeStyle(_source, _target) == EdgeStyle::Dashed ? "dashed" : "solid"; + if (_exitPort) + return fmt::format("{}Exit:{} -> {} [style=\"{}\"];\n", formatBlockHandle(_source), *_exitPort, formatBlockHandle(_target), style); + else + return fmt::format("{}Exit -> {} [style=\"{}\"];\n", formatBlockHandle(_source), formatBlockHandle(_target), style); +} + +void DotExporterBase::writeBlock(std::ostream& _out, SSACFG::BlockId const _id) +{ + auto const& block = m_cfg.block(_id); + + auto const attributes = blockNodeAttributes(_id); + std::string attrStr; + for (auto const& [name, value]: attributes) + attrStr += fmt::format("{}={}, ", name, value); + _out << fmt::format("{} [{}label=\"", formatBlockHandle(_id), attrStr); + writeBlockLabel(_out, _id); + _out << "\"];\n"; + + std::visit(GenericVisitor{ + [&](SSACFG::BasicBlock::MainExit const&) + { + _out << fmt::format("{}Exit [label=\"MainExit\"];\n", formatBlockHandle(_id)); + _out << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); + }, + [&](SSACFG::BasicBlock::Jump const& _jump) + { + _out << fmt::format("{} -> {}Exit [arrowhead=none];\n", formatBlockHandle(_id), formatBlockHandle(_id)); + _out << fmt::format("{}Exit [label=\"Jump\" shape=oval];\n", formatBlockHandle(_id)); + _out << formatEdge(_id, _jump.target); + }, + [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) + { + _out << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); + _out << fmt::format( + "{}Exit [label=\"{{ If {} | {{ <0> Zero | <1> NonZero }}}}\" shape=Mrecord];\n", + formatBlockHandle(_id), _conditionalJump.condition.str(m_cfg) + ); + _out << formatEdge(_id, _conditionalJump.zero, "0"); + _out << formatEdge(_id, _conditionalJump.nonZero, "1"); + }, + [&](SSACFG::BasicBlock::JumpTable const& jt) + { + _out << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); + std::string options; + for (auto const& jumpCase: jt.cases) + { + if (!options.empty()) + options += " | "; + options += fmt::format("<{0}> {0}", formatNumber(jumpCase.first)); + } + if (!options.empty()) + options += " | "; + options += " default"; + _out << fmt::format("{}Exit [label=\"{{ JT | {{ {} }} }}\" shape=Mrecord];\n", formatBlockHandle(_id), options); + for (auto const& jumpCase: jt.cases) + _out << formatEdge(_id, jumpCase.second, formatNumber(jumpCase.first)); + _out << formatEdge(_id, jt.defaultCase, "default"); + }, + [&](SSACFG::BasicBlock::FunctionReturn const& fr) + { + auto const valueToString = [&](SSACFG::ValueId const& valueId) { return valueId.str(m_cfg); }; + _out << fmt::format("{}Exit [label=\"FunctionReturn[{}]\"];\n", + formatBlockHandle(_id), + fmt::join(fr.returnValues | ranges::views::transform(valueToString), ", ") + ); + _out << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); + }, + [&](SSACFG::BasicBlock::Terminated const&) + { + _out << fmt::format("{}Exit [label=\"Terminated\"];\n", formatBlockHandle(_id)); + _out << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); + } + }, block.exit); +} + +void DotExporterBase::traverse(std::ostream& _out, SSACFG::BlockId _entry) +{ + std::vector explored(m_cfg.numBlocks(), false); + explored[_entry.value] = true; + + std::deque toVisit{}; + toVisit.emplace_back(_entry); + + while (!toVisit.empty()) + { + auto const id = toVisit.front(); + toVisit.pop_front(); + writeBlock(_out, id); + m_cfg.block(id).forEachExit( + [&](SSACFG::BlockId const& _exitBlock) + { + if (!explored[_exitBlock.value]) + { + explored[_exitBlock.value] = true; + toVisit.emplace_back(_exitBlock); + } + } + ); + } +} + +std::string DotExporterBase::exportBlocks(SSACFG::BlockId _entry, bool _wrapInDigraph) +{ + std::ostringstream out; + if (_wrapInDigraph) + out << fmt::format("digraph SSACFG {{\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\", rankdir={}]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n", m_rankDir); + out << fmt::format("Entry [label=\"Entry\"];\n"); + out << fmt::format("Entry -> {};\n", formatBlockHandle(_entry)); + traverse(out, _entry); + if (_wrapInDigraph) + out << "}\n"; + return out.str(); +} + +std::string DotExporterBase::exportFunction(Scope::Function const& _function, bool _wrapInDigraph) +{ + std::ostringstream out; + if (_wrapInDigraph) + out << fmt::format("digraph SSACFG {{\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\", rankdir={}]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n", m_rankDir); + + static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return escapeLabel(functionReturnValue.get().name.str()); }; + static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", std::get<1>(arg).value()); }; + auto const entryHandle = fmt::format("FunctionEntry_{}_{}", escapeId(_function.name.str()), m_cfg.entry.value); + if (!m_cfg.returns.empty()) + out << fmt::format("{} [label=\"function {}:\n {} := {}({})\"];\n", + entryHandle, escapeLabel(_function.name.str()), + fmt::join(m_cfg.returns | ranges::views::transform(returnsTransform), ", "), + escapeLabel(_function.name.str()), + fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + else + out << fmt::format("{} [label=\"function {}:\n {}({})\"];\n", + entryHandle, escapeLabel(_function.name.str()), + escapeLabel(_function.name.str()), + fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + out << fmt::format("{} -> {};\n", entryHandle, formatBlockHandle(m_cfg.entry)); + traverse(out, m_cfg.entry); + + if (_wrapInDigraph) + out << "}\n"; + return out.str(); +} diff --git a/libyul/backends/evm/ssa/io/DotExporterBase.h b/libyul/backends/evm/ssa/io/DotExporterBase.h new file mode 100644 index 000000000..f7fcdcda2 --- /dev/null +++ b/libyul/backends/evm/ssa/io/DotExporterBase.h @@ -0,0 +1,93 @@ +/* + 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 + +#pragma once + +#include + +#include + +#include +#include +#include +#include + +namespace solidity::yul::ssa::io +{ + +/// Base class for exporting an SSACFG to Graphviz dot format. +/// Handles graph structure (BFS traversal, edges, exit nodes, entry nodes) and +/// delegates block content rendering to derived classes via writeBlockLabel(). +class DotExporterBase +{ +public: + enum class EdgeStyle { Solid, Dashed }; + enum class RankDir { TB, BT, LR, RL }; + + DotExporterBase(SSACFG const& _cfg, size_t _functionIndex, RankDir _rankDir = RankDir::LR); + virtual ~DotExporterBase() = default; + + std::string exportBlocks(SSACFG::BlockId _entry, bool _wrapInDigraph = true); + std::string exportFunction(Scope::Function const& _function, bool _wrapInDigraph = true); + +protected: + /// Override to write the content inside a block's dot label. + /// Everything between the opening `label="` and the closing `"` is the responsibility of this method. + virtual void writeBlockLabel(std::ostream& _out, SSACFG::BlockId _blockId) = 0; + + /// Override to provide extra node attributes (e.g., fillcolor). + virtual std::vector> blockNodeAttributes(SSACFG::BlockId) { return {}; } + + /// Override to customize edge style (e.g., dashed for back edges). + virtual EdgeStyle edgeStyle(SSACFG::BlockId, SSACFG::BlockId) { return EdgeStyle::Solid; } + + std::string formatBlockHandle(SSACFG::BlockId _id) const; + /// Escapes a string for use in dot node IDs (replaces non-alphanumeric characters with underscores). + static std::string escapeId(std::string_view _str); + /// Escapes a string for use inside dot label text (escapes quotes and backslashes). + static std::string escapeLabel(std::string_view _str); + + SSACFG const& m_cfg; + size_t m_functionIndex; + RankDir m_rankDir; + +private: + void writeBlock(std::ostream& _out, SSACFG::BlockId _id); + std::string formatEdge(SSACFG::BlockId _source, SSACFG::BlockId _target, std::optional const& _exitPort = std::nullopt); + void traverse(std::ostream& _out, SSACFG::BlockId _entry); +}; + +} + +template<> +struct fmt::formatter: fmt::formatter +{ + auto format(solidity::yul::ssa::io::DotExporterBase::RankDir _rankDir, fmt::format_context& _ctx) const + { + using RankDir = solidity::yul::ssa::io::DotExporterBase::RankDir; + std::string_view name; + switch (_rankDir) + { + case RankDir::TB: name = "TB"; break; + case RankDir::BT: name = "BT"; break; + case RankDir::LR: name = "LR"; break; + case RankDir::RL: name = "RL"; break; + } + return fmt::formatter::format(name, _ctx); + } +}; From e3c73c208717c11612b62f6ca5c137465bd23b9b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:37:02 +0100 Subject: [PATCH 1124/1340] Use Dot Exporter Base in `toDot` of SSACFG --- libyul/backends/evm/ssa/SSACFG.cpp | 319 +++++------------- .../libyul/yulSSAControlFlowGraph/complex.yul | 4 +- .../yulSSAControlFlowGraph/complex2.yul | 4 +- .../default_initialized_variable.yul | 4 +- .../yulSSAControlFlowGraph/function.yul | 4 +- test/libyul/yulSSAControlFlowGraph/if.yul | 4 +- .../yulSSAControlFlowGraph/if_const.yul | 4 +- .../yulSSAControlFlowGraph/nested_for.yul | 4 +- .../nested_function.yul | 4 +- test/libyul/yulSSAControlFlowGraph/switch.yul | 4 +- .../yulSSAControlFlowGraph/switch_const.yul | 4 +- 11 files changed, 109 insertions(+), 250 deletions(-) diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index a785c51aa..24cc77091 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -19,6 +19,8 @@ #include #include +#include +#include #include #include @@ -28,8 +30,6 @@ #include #pragma GCC diagnostic pop -#include - #include using namespace solidity; @@ -39,256 +39,120 @@ using namespace solidity::yul::ssa; namespace { -class SSACFGPrinter + +std::string formatPhi(SSACFG const& _cfg, SSACFG::PhiValue const& _phiValue) +{ + auto const transform = [&](SSACFG::ValueId const& valueId) { return valueId.str(_cfg); }; + std::vector formattedArgs; + formattedArgs.reserve(_phiValue.arguments.size()); + for (auto const& [arg, entry]: ranges::zip_view(_phiValue.arguments | ranges::views::transform(transform), _cfg.block(_phiValue.block).entries)) + formattedArgs.push_back(fmt::format("Block {} => {}", entry.value, arg)); + if (!formattedArgs.empty()) + return fmt::format("φ(\\l\\\n\t{}\\l\\\n)", fmt::join(formattedArgs, ",\\l\\\n\t")); + else + return "φ()"; +} + +class SSACFGDotExporter: public io::DotExporterBase { public: - SSACFGPrinter(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness): - m_cfg(_cfg), m_functionIndex(0), m_liveness(_liveness) + SSACFGDotExporter(SSACFG const& _cfg, size_t _functionIndex, LivenessAnalysis const* _liveness): + DotExporterBase(_cfg, _functionIndex), + m_liveness(_liveness) { if (_liveness) m_junkAdmittingBlocks = std::make_unique(_cfg, _liveness->topologicalSort()); - printBlock(_blockId); - } - SSACFGPrinter(SSACFG const& _cfg, size_t _functionIndex, Scope::Function const& _function, LivenessAnalysis const* _liveness): - m_cfg(_cfg), m_functionIndex(_functionIndex), m_liveness(_liveness) - { - if (_liveness) - m_junkAdmittingBlocks = std::make_unique(_cfg, _liveness->topologicalSort()); - printFunction(_function); - } - friend std::ostream& operator<<(std::ostream& stream, SSACFGPrinter const& printer) { - stream << printer.m_result.str(); - return stream; } -private: - static std::string escape(std::string_view const str) +protected: + void writeBlockLabel(std::ostream& _out, SSACFG::BlockId _blockId) override { - using namespace std::literals; - static constexpr auto replacements = std::array{std::make_tuple('$', "_d_")}; - std::stringstream ss; - for (auto const c: str) + auto const& block = m_cfg.block(_blockId); + auto const valueToString = [&](SSACFG::ValueId const& valueId) { return valueId.str(m_cfg); }; + + if (m_liveness) { - auto const it = std::find_if(replacements.begin(), replacements.end(), [c](auto const& replacement) - { - return std::get<0>(replacement) == c; - }); - if (it != replacements.end()) - ss << std::get<1>(*it); - else - ss << c; + _out << fmt::format( + "\\\nBlock {}; ({}, max {})\\n", + _blockId.value, + m_liveness->topologicalSort().preOrderIndexOf(_blockId.value), + m_liveness->topologicalSort().maxSubtreePreOrderIndexOf(_blockId.value) + ); + _out << fmt::format( + "LiveIn: {}\\l\\\n", + fmt::join(m_liveness->liveIn(_blockId) | ranges::views::transform([&](auto const& liveIn) { return valueToString(SSACFG::ValueId{liveIn.first}) + fmt::format("[{}]", liveIn.second); }), ", ") + ); + _out << fmt::format( + "LiveOut: {}\\l\\n", + fmt::join(m_liveness->liveOut(_blockId) | ranges::views::transform([&](auto const& liveOut) { return valueToString(SSACFG::ValueId{liveOut.first}) + fmt::format("[{}]", liveOut.second); }), ", ") + ); + auto const usedVariables = m_liveness->used(_blockId); + _out << fmt::format( + "Used: {}\\l\\n", + fmt::join(usedVariables | ranges::views::transform([&](auto const& used) { return valueToString(SSACFG::ValueId{used.first}) + fmt::format("[{}]", used.second); }), ", ") + ); } - return ss.str(); - } - - std::string formatBlockHandle(SSACFG::BlockId const& _id) const - { - return fmt::format("Block{}_{}", m_functionIndex, _id.value); - } - - std::string formatEdge(SSACFG::BlockId const& _v, SSACFG::BlockId const& _w, std::optional const& _vPort = std::nullopt) - { - std::string const style = m_liveness && m_liveness->topologicalSort().backEdge(_v, _w) ? "dashed" : "solid"; - if (_vPort) - return fmt::format("{}Exit:{} -> {} [style=\"{}\"];\n", formatBlockHandle(_v), *_vPort, formatBlockHandle(_w), style); - else - return fmt::format("{}Exit -> {} [style=\"{}\"];\n", formatBlockHandle(_v), formatBlockHandle(_w), style); - } - - static std::string formatPhi(SSACFG const& _cfg, SSACFG::PhiValue const& _phiValue) - { - auto const transform = [&](SSACFG::ValueId const& valueId) { return valueId.str(_cfg); }; - std::vector formattedArgs; - formattedArgs.reserve(_phiValue.arguments.size()); - for (auto const& [arg, entry]: ranges::zip_view(_phiValue.arguments | ranges::views::transform(transform), _cfg.block(_phiValue.block).entries)) - formattedArgs.push_back(fmt::format("Block {} => {}", entry.value, arg)); - if (!formattedArgs.empty()) - return fmt::format("φ(\\l\\\n\t{}\\l\\\n)", fmt::join(formattedArgs, ",\\l\\\n\t")); else - return "φ()"; - } + _out << fmt::format("\\\nBlock {}\\n", _blockId.value); - void writeBlock(SSACFG::BlockId const& _id, SSACFG::BasicBlock const& _block) - { - auto const valueToString = [&](SSACFG::ValueId const& valueId) { return valueId.str(m_cfg); }; - bool entryBlock = _id.value == 0 && m_functionIndex == 0; - if (entryBlock) + for (auto const& phi: block.phis) { - m_result << fmt::format("Entry{} [label=\"Entry\"];\n", m_functionIndex); - m_result << fmt::format("Entry{} -> {};\n", m_functionIndex, formatBlockHandle(_id)); + auto const& phiInfo = m_cfg.phiInfo(phi); + _out << fmt::format("phi{} := {}\\l\\\n", phi.value(), formatPhi(m_cfg, phiInfo)); } + for (auto const& operation: block.operations) { - std::string revertPathInfo; - if (m_junkAdmittingBlocks) - revertPathInfo = m_junkAdmittingBlocks->allowsAdditionOfJunk(_id) ? "fillcolor=\"#FF746C\", style=filled, " : ""; - if (m_liveness) - { - m_result << fmt::format( - "{} [{}label=\"\\\nBlock {}; ({}, max {})\\n", - formatBlockHandle(_id), - revertPathInfo, - _id.value, - m_liveness->topologicalSort().preOrderIndexOf(_id.value), - m_liveness->topologicalSort().maxSubtreePreOrderIndexOf(_id.value) - ); - m_result << fmt::format( - "LiveIn: {}\\l\\\n", - fmt::join(m_liveness->liveIn(_id) | ranges::views::transform([&](auto const& liveIn) { return valueToString(SSACFG::ValueId{liveIn.first}) + fmt::format("[{}]", liveIn.second); }), ", ") - ); - m_result << fmt::format( - "LiveOut: {}\\l\\n", - fmt::join(m_liveness->liveOut(_id) | ranges::views::transform([&](auto const& liveOut) { return valueToString(SSACFG::ValueId{liveOut.first}) + fmt::format("[{}]", liveOut.second); }), ", ") - ); - auto const usedVariables = m_liveness->used(_id); - m_result << fmt::format( - "Used: {}\\l\\n", - fmt::join(usedVariables | ranges::views::transform([&](auto const& used) { return valueToString(SSACFG::ValueId{used.first}) + fmt::format("[{}]", used.second); }), ", ") - ); - } - else - m_result << fmt::format("{} [{}label=\"\\\nBlock {}\\n", formatBlockHandle(_id), revertPathInfo, _id.value); - - for (auto const& phi: _block.phis) - { - auto const& phiInfo = m_cfg.phiInfo(phi); - m_result << fmt::format("phi{} := {}\\l\\\n", phi.value(), formatPhi(m_cfg, phiInfo)); - } - for (auto const& operation: _block.operations) - { - std::string const label = std::visit(GenericVisitor{ - [&](SSACFG::Call const& _call) { - return _call.function.get().name.str(); - }, - [&](SSACFG::BuiltinCall const& _call) { - return _call.builtin.get().name; - }, - [&](SSACFG::LiteralAssignment const&) - { - yulAssert(operation.inputs.size() == 1); - return operation.inputs.back().str(m_cfg); - } - }, operation.kind); - if (!operation.outputs.empty()) - m_result << fmt::format( - "{} := ", - fmt::join(operation.outputs | ranges::views::transform(valueToString), ", ") - ); - if (std::holds_alternative(operation.kind)) - m_result << fmt::format( - "{}\\l\\\n", - escape(label) - ); - else - m_result << fmt::format( - "{}({})\\l\\\n", - escape(label), - fmt::join(operation.inputs | ranges::views::transform(valueToString), ", ") - ); - } - m_result << "\"];\n"; - std::visit(GenericVisitor{ - [&](SSACFG::BasicBlock::MainExit const&) - { - m_result << fmt::format("{}Exit [label=\"MainExit\"];\n", formatBlockHandle(_id)); - m_result << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); - }, - [&](SSACFG::BasicBlock::Jump const& _jump) - { - m_result << fmt::format("{} -> {}Exit [arrowhead=none];\n", formatBlockHandle(_id), formatBlockHandle(_id)); - m_result << fmt::format("{}Exit [label=\"Jump\" shape=oval];\n", formatBlockHandle(_id)); - m_result << formatEdge(_id, _jump.target); - }, - [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) - { - m_result << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); - m_result << fmt::format( - "{}Exit [label=\"{{ If {} | {{ <0> Zero | <1> NonZero }}}}\" shape=Mrecord];\n", - formatBlockHandle(_id), _conditionalJump.condition.str(m_cfg) - ); - m_result << formatEdge(_id, _conditionalJump.zero, "0"); - m_result << formatEdge(_id, _conditionalJump.nonZero, "1"); - }, - [&](SSACFG::BasicBlock::JumpTable const& jt) - { - m_result << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); - std::string options; - for (auto const& jumpCase: jt.cases) - { - if (!options.empty()) - options += " | "; - options += fmt::format("<{0}> {0}", formatNumber(jumpCase.first)); - } - if (!options.empty()) - options += " | "; - options += " default"; - m_result << fmt::format("{}Exit [label=\"{{ JT | {{ {} }} }}\" shape=Mrecord];\n", formatBlockHandle(_id), options); - for (auto const& jumpCase: jt.cases) - m_result << formatEdge(_id, jumpCase.second, formatNumber(jumpCase.first)); - m_result << formatEdge(_id, jt.defaultCase, "default"); + std::string const label = std::visit(GenericVisitor{ + [&](SSACFG::Call const& _call) { + return _call.function.get().name.str(); }, - [&](SSACFG::BasicBlock::FunctionReturn const& fr) - { - m_result << formatBlockHandle(_id) << "Exit [label=\"FunctionReturn[" - << fmt::format("{}", fmt::join(fr.returnValues | ranges::views::transform(valueToString), ", ")) - << "]\"];\n"; - m_result << formatBlockHandle(_id) << " -> " << formatBlockHandle(_id) << "Exit;\n"; + [&](SSACFG::BuiltinCall const& _call) { + return _call.builtin.get().name; }, - [&](SSACFG::BasicBlock::Terminated const&) + [&](SSACFG::LiteralAssignment const&) { - m_result << formatBlockHandle(_id) << "Exit [label=\"Terminated\"];\n"; - m_result << formatBlockHandle(_id) << " -> " << formatBlockHandle(_id) << "Exit;\n"; + yulAssert(operation.inputs.size() == 1); + return operation.inputs.back().str(m_cfg); } - }, _block.exit); + }, operation.kind); + if (!operation.outputs.empty()) + _out << fmt::format( + "{} := ", + fmt::join(operation.outputs | ranges::views::transform(valueToString), ", ") + ); + if (std::holds_alternative(operation.kind)) + _out << fmt::format( + "{}\\l\\\n", + escapeLabel(label) + ); + else + _out << fmt::format( + "{}({})\\l\\\n", + escapeLabel(label), + fmt::join(operation.inputs | ranges::views::transform(valueToString), ", ") + ); } } - void printBlock(SSACFG::BlockId const& _rootId) + std::vector> blockNodeAttributes(SSACFG::BlockId _blockId) override { - std::set explored{}; - explored.insert(_rootId); - - std::deque toVisit{}; - toVisit.emplace_back(_rootId); - - while (!toVisit.empty()) - { - auto const id = toVisit.front(); - toVisit.pop_front(); - auto const& block = m_cfg.block(id); - writeBlock(id, block); - block.forEachExit( - [&](SSACFG::BlockId const& _exitBlock) - { - if (explored.count(_exitBlock) == 0) - { - explored.insert(_exitBlock); - toVisit.emplace_back(_exitBlock); - } - } - ); - } + if (m_junkAdmittingBlocks && m_junkAdmittingBlocks->allowsAdditionOfJunk(_blockId)) + return {{"fillcolor", "\"#FF746C\""}, {"style", "filled"}}; + return {}; } - void printFunction(Scope::Function const& _fun) + EdgeStyle edgeStyle(SSACFG::BlockId _source, SSACFG::BlockId _target) override { - static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return escape(functionReturnValue.get().name.str()); }; - static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", std::get<1>(arg).value()); }; - m_result << "FunctionEntry_" << escape(_fun.name.str()) << "_" << m_cfg.entry.value << " [label=\""; - if (!m_cfg.returns.empty()) - m_result << fmt::format("function {0}:\n {1} := {0}({2})", escape(_fun.name.str()), fmt::join(m_cfg.returns | ranges::views::transform(returnsTransform), ", "), fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); - else - m_result << fmt::format("function {0}:\n {0}({1})", escape(_fun.name.str()), fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); - m_result << "\"];\n"; - m_result << "FunctionEntry_" << escape(_fun.name.str()) << "_" << m_cfg.entry.value << " -> Block" << m_functionIndex << "_" << m_cfg.entry.value << ";\n"; - printBlock(m_cfg.entry); + if (m_liveness && m_liveness->topologicalSort().backEdge(_source, _target)) + return EdgeStyle::Dashed; + return EdgeStyle::Solid; } - SSACFG const& m_cfg; - std::unique_ptr m_junkAdmittingBlocks; - size_t m_functionIndex; +private: LivenessAnalysis const* m_liveness; - std::stringstream m_result{}; + std::unique_ptr m_junkAdmittingBlocks; }; + } std::string SSACFG::ValueId::str(SSACFG const& _cfg) const @@ -312,14 +176,9 @@ std::string SSACFG::toDot( LivenessAnalysis const* _liveness ) const { - std::ostringstream output; - if (_includeDiGraphDefinition) - output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\", rankdir=LR]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; + SSACFGDotExporter exporter(*this, _functionIndex.value_or(function ? 1 : 0), _liveness); if (function) - output << SSACFGPrinter(*this, _functionIndex ? *_functionIndex : static_cast(1), *function, _liveness); + return exporter.exportFunction(*function, _includeDiGraphDefinition); else - output << SSACFGPrinter(*this, entry, _liveness); - if (_includeDiGraphDefinition) - output << "}\n"; - return output.str(); + return exporter.exportBlocks(entry, _includeDiGraphDefinition); } diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/yulSSAControlFlowGraph/complex.yul index 24ab7af12..4f16122e3 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex.yul @@ -49,8 +49,8 @@ // graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // -// Entry0 [label="Entry"]; -// Entry0 -> Block0_0; +// Entry [label="Entry"]; +// Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\nUsed: \l\nv0 := f(0x02, 0x01)\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/yulSSAControlFlowGraph/complex2.yul index 9910d8356..d82c400e8 100644 --- a/test/libyul/yulSSAControlFlowGraph/complex2.yul +++ b/test/libyul/yulSSAControlFlowGraph/complex2.yul @@ -56,8 +56,8 @@ // graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // -// Entry0 [label="Entry"]; -// Entry0 -> Block0_0; +// Entry [label="Entry"]; +// Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\nUsed: \l\nsstore(0x01, 0x01)\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul b/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul index 14a80dadc..45893e8ac 100644 --- a/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul +++ b/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul @@ -11,8 +11,8 @@ // graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // -// Entry0 [label="Entry"]; -// Entry0 -> Block0_0; +// Entry [label="Entry"]; +// Entry -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ // LiveOut: v0[1]\l\nUsed: \l\nv0 := 0x00\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/yulSSAControlFlowGraph/function.yul index f5090b826..e2140d316 100644 --- a/test/libyul/yulSSAControlFlowGraph/function.yul +++ b/test/libyul/yulSSAControlFlowGraph/function.yul @@ -24,8 +24,8 @@ // graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // -// Entry0 [label="Entry"]; -// Entry0 -> Block0_0; +// Entry [label="Entry"]; +// Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\nUsed: \l\nv0, v1 := i()\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/if.yul b/test/libyul/yulSSAControlFlowGraph/if.yul index 540947e18..f884d3348 100644 --- a/test/libyul/yulSSAControlFlowGraph/if.yul +++ b/test/libyul/yulSSAControlFlowGraph/if.yul @@ -12,8 +12,8 @@ // graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // -// Entry0 [label="Entry"]; -// Entry0 -> Block0_0; +// Entry [label="Entry"]; +// Entry -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ // LiveOut: v0[1]\l\nUsed: \l\nv0 := calldataload(0x03)\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/if_const.yul b/test/libyul/yulSSAControlFlowGraph/if_const.yul index d8be1eaf2..f8bab3f48 100644 --- a/test/libyul/yulSSAControlFlowGraph/if_const.yul +++ b/test/libyul/yulSSAControlFlowGraph/if_const.yul @@ -17,8 +17,8 @@ // graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // -// Entry0 [label="Entry"]; -// Entry0 -> Block0_0; +// Entry [label="Entry"]; +// Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\nUsed: \l\nv0 := calldataload(0x03)\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/yulSSAControlFlowGraph/nested_for.yul index e9e575140..55edb2ea6 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_for.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_for.yul @@ -23,8 +23,8 @@ // graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // -// Entry0 [label="Entry"]; -// Entry0 -> Block0_0; +// Entry [label="Entry"]; +// Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 24)\nLiveIn: \l\ // LiveOut: v0[1]\l\nUsed: \l\nv0 := 0x00\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/nested_function.yul b/test/libyul/yulSSAControlFlowGraph/nested_function.yul index 2ae7f5522..876768d66 100644 --- a/test/libyul/yulSSAControlFlowGraph/nested_function.yul +++ b/test/libyul/yulSSAControlFlowGraph/nested_function.yul @@ -35,8 +35,8 @@ // graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // -// Entry0 [label="Entry"]; -// Entry0 -> Block0_0; +// Entry [label="Entry"]; +// Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\nUsed: \l\n"]; diff --git a/test/libyul/yulSSAControlFlowGraph/switch.yul b/test/libyul/yulSSAControlFlowGraph/switch.yul index 56e50d562..3114bbca3 100644 --- a/test/libyul/yulSSAControlFlowGraph/switch.yul +++ b/test/libyul/yulSSAControlFlowGraph/switch.yul @@ -19,8 +19,8 @@ // graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // -// Entry0 [label="Entry"]; -// Entry0 -> Block0_0; +// Entry [label="Entry"]; +// Entry -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 5)\nLiveIn: \l\ // LiveOut: v1[1]\l\nUsed: \l\nv0 := calldataload(0x03)\l\ diff --git a/test/libyul/yulSSAControlFlowGraph/switch_const.yul b/test/libyul/yulSSAControlFlowGraph/switch_const.yul index 559061195..56116eb3b 100644 --- a/test/libyul/yulSSAControlFlowGraph/switch_const.yul +++ b/test/libyul/yulSSAControlFlowGraph/switch_const.yul @@ -41,8 +41,8 @@ // graph[fontname="DejaVu Sans"] // node[shape=box,fontname="DejaVu Sans"]; // -// Entry0 [label="Entry"]; -// Entry0 -> Block0_0; +// Entry [label="Entry"]; +// Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\nUsed: \l\nv0 := calldataload(0x03)\l\ From 025600fa4517bef01ed9e972f38137ff9dd5e38b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:56:08 +0100 Subject: [PATCH 1125/1340] Add phi inverse function for ssa-based cfgs --- libyul/CMakeLists.txt | 2 ++ libyul/backends/evm/ssa/PhiInverse.cpp | 46 ++++++++++++++++++++++++++ libyul/backends/evm/ssa/PhiInverse.h | 46 ++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 libyul/backends/evm/ssa/PhiInverse.cpp create mode 100644 libyul/backends/evm/ssa/PhiInverse.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index d07b25a50..2c0f6d446 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -80,6 +80,8 @@ add_library(yul backends/evm/ssa/JunkAdmittingBlocksFinder.h backends/evm/ssa/LivenessAnalysis.cpp backends/evm/ssa/LivenessAnalysis.h + backends/evm/ssa/PhiInverse.cpp + backends/evm/ssa/PhiInverse.h backends/evm/ssa/SSACFGLoopNestingForest.cpp backends/evm/ssa/SSACFGLoopNestingForest.h backends/evm/ssa/SSACFG.cpp diff --git a/libyul/backends/evm/ssa/PhiInverse.cpp b/libyul/backends/evm/ssa/PhiInverse.cpp new file mode 100644 index 000000000..c88b132ad --- /dev/null +++ b/libyul/backends/evm/ssa/PhiInverse.cpp @@ -0,0 +1,46 @@ +/* + 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 + +#include + +using namespace solidity::yul::ssa; + +PhiInverse::PhiInverse(SSACFG const& _cfg, SSACFG::BlockId const& _from, SSACFG::BlockId const& _to) +{ + auto const argIndex = _cfg.phiArgumentIndex(_from, _to); + for (auto const& phiId: _cfg.block(_to).phis) + { + auto const& phiInfo = _cfg.phiInfo(phiId); + m_phiToPreImage[phiId] = phiInfo.arguments[argIndex]; + } +} + +bool PhiInverse::noOp() const +{ + return m_phiToPreImage.empty(); +} + +SSACFG::ValueId PhiInverse::operator()(SSACFG::ValueId _valueId) const +{ + return util::valueOrDefault(m_phiToPreImage, _valueId, _valueId); +} + +std::map const& PhiInverse::data() const +{ + return m_phiToPreImage; +} diff --git a/libyul/backends/evm/ssa/PhiInverse.h b/libyul/backends/evm/ssa/PhiInverse.h new file mode 100644 index 000000000..3f29aae46 --- /dev/null +++ b/libyul/backends/evm/ssa/PhiInverse.h @@ -0,0 +1,46 @@ +/* + 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 + +#pragma once + +#include + +#include + +namespace solidity::yul::ssa +{ + +/// If Block `_from` -> Block `_to` and `_to` has phi functions `v_k := phi(..., _from => v_i, ...)`, this transform +/// pulls values `v_k` back to `v_i`. +class PhiInverse +{ +public: + PhiInverse() = default; + PhiInverse(SSACFG const& _cfg, SSACFG::BlockId const& _from, SSACFG::BlockId const& _to); + + /// whether the transform is guaranteed to be a no-op, ie, there is no phi function in `_to` + bool noOp() const; + SSACFG::ValueId operator()(SSACFG::ValueId _valueId) const; + + std::map const& data() const; + +private: + std::map m_phiToPreImage = {}; +}; + +} From b3a7948f07fec360c9841ee2237fe36823a23caa Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:56:29 +0100 Subject: [PATCH 1126/1340] ssa-cfg stack abstraction can also declare junk based on offsets --- libyul/backends/evm/ssa/Stack.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index 95ff377e7..834e21078 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -250,7 +250,8 @@ class Stack bool swapReachable(Offset const& _offset) const noexcept { return swapReachable(offsetToDepth(_offset)); } bool swapReachable(Depth const& _depth) const noexcept { return _depth < size() && 1 <= _depth.value && _depth.value <= reachableStackDepth; } - void declareJunk(Depth const& _depth) { (*m_data)[depthToOffset(_depth).value] = Slot::makeJunk(); } + void declareJunk(Offset const& _offset) { (*m_data)[_offset.value] = Slot::makeJunk(); } + void declareJunk(Depth const& _depth) { declareJunk(depthToOffset(_depth)); } Slot const& slot(Depth const& _depth) const { return (*m_data)[depthToOffset(_depth).value]; } Slot const& slot(Offset const& _offset) const { return slot(offsetToDepth(_offset)); } From 746871abd44bbd8cf79882749f56b0d150386ee9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:57:07 +0100 Subject: [PATCH 1127/1340] Define what constitutes a stack layout for SSA-CFGs --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/ssa/StackLayout.h | 60 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 libyul/backends/evm/ssa/StackLayout.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 2c0f6d446..893b32e94 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -90,6 +90,7 @@ add_library(yul backends/evm/ssa/SSACFGBuilder.h backends/evm/ssa/Stack.cpp backends/evm/ssa/Stack.h + backends/evm/ssa/StackLayout.h backends/evm/ssa/StackShuffler.cpp backends/evm/ssa/StackShuffler.h backends/evm/ssa/io/DotExporterBase.cpp diff --git a/libyul/backends/evm/ssa/StackLayout.h b/libyul/backends/evm/ssa/StackLayout.h new file mode 100644 index 000000000..d0cd81972 --- /dev/null +++ b/libyul/backends/evm/ssa/StackLayout.h @@ -0,0 +1,60 @@ +/* + 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 + +#pragma once + +#include + +#include + +namespace solidity::yul::ssa +{ + +struct BlockLayout +{ + // stack layout required to enter the block + StackData stackIn; + // stack layout required to execute the i-th operation in the block + std::vector operationIn; + // stack after the block was executed + StackData stackOut; +}; + +/// For each (reachable) block in the SSACFG one block layout +class SSACFGStackLayout +{ +public: + SSACFGStackLayout(std::size_t const _numBlocks): m_blockLayouts(_numBlocks) {} + + std::optional& operator[](SSACFG::BlockId const& _blockId) + { + yulAssert(_blockId.hasValue() && _blockId.value < m_blockLayouts.size()); + return m_blockLayouts[_blockId.value]; + } + + std::optional const& operator[](SSACFG::BlockId const& _blockId) const + { + yulAssert(_blockId.hasValue() && _blockId.value < m_blockLayouts.size()); + return m_blockLayouts[_blockId.value]; + } + +private: + std::vector> m_blockLayouts; +}; + +} From d2de781babf0c32a6a24f46d4296b8ba558907f5 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:57:27 +0100 Subject: [PATCH 1128/1340] Add SSA-CFG stack layout generator --- libyul/CMakeLists.txt | 2 + .../backends/evm/ssa/StackLayoutGenerator.cpp | 311 ++++++++++++++++++ .../backends/evm/ssa/StackLayoutGenerator.h | 51 +++ 3 files changed, 364 insertions(+) create mode 100644 libyul/backends/evm/ssa/StackLayoutGenerator.cpp create mode 100644 libyul/backends/evm/ssa/StackLayoutGenerator.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 893b32e94..dcc0f923a 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -91,6 +91,8 @@ add_library(yul backends/evm/ssa/Stack.cpp backends/evm/ssa/Stack.h backends/evm/ssa/StackLayout.h + backends/evm/ssa/StackLayoutGenerator.cpp + backends/evm/ssa/StackLayoutGenerator.h backends/evm/ssa/StackShuffler.cpp backends/evm/ssa/StackShuffler.h backends/evm/ssa/io/DotExporterBase.cpp diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp new file mode 100644 index 000000000..04abd8b64 --- /dev/null +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -0,0 +1,311 @@ +/* + 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 + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +using namespace solidity::yul::ssa; + +namespace +{ +void handlePhiFunctions(StackData& _stackData, PhiInverse const& _phiInverse, LivenessAnalysis::LivenessData const& _liveness) +{ + // add any phi function values here that are not already contained in the stack + for (auto const& [phi, preImage]: _phiInverse.data()) + { + auto reversedStackData = _stackData | ranges::views::reverse; + auto it = ranges::find(reversedStackData, StackSlot::makeValueID(preImage)); + if (_liveness.contains(preImage)) + { + // Both the phi function and the preimage are part of the live-in set. + // If the preimage occurs more than once on the stack, one occurrence is + // symbolically replaced by the phi function; otherwise, we push the phi value. + if (ranges::count(_stackData, StackSlot::makeValueID(preImage)) > 1) + *it = StackSlot::makeValueID(phi); + else + _stackData.emplace_back(StackSlot::makeValueID(phi)); + } + else + { + // replace all occurrences of the preimage with the phi value + ranges::replace(_stackData, StackSlot::makeValueID(preImage), StackSlot::makeValueID(phi)); + // if it's not contained, push it (could be derived from a literal) + if (it == ranges::end(reversedStackData)) + _stackData.emplace_back(StackSlot::makeValueID(phi)); + } + } +} + +using StackType = Stack; + +void declareJunk(StackType& _stack, LivenessAnalysis::LivenessData const& _live) +{ + for (StackOffset offset{0}; offset < _stack.size(); ++offset.value) + { + auto const& slot = _stack[offset]; + if (slot.isValueID() && !_live.contains(slot.valueID())) + _stack.declareJunk(offset); + } +} + +} + +SSACFGStackLayout StackLayoutGenerator::generate(LivenessAnalysis const& _liveness, CallSites const& _callSites) +{ + return StackLayoutGenerator(_liveness, _callSites).m_resultLayout; +} + +StackLayoutGenerator::StackLayoutGenerator(LivenessAnalysis const& _liveness, CallSites const& _callSites): + m_cfg(_liveness.cfg()), + m_liveness(_liveness), + m_callSites(_callSites), + m_junkAdmittingBlocksFinder(std::make_unique(_liveness.cfg(), _liveness.topologicalSort())), + m_resultLayout(m_cfg.numBlocks()) +{ + // traverse the cfg layer-wise using Kahn's algorithm: + // if a block is visited, the predecessors of that block have already their exit layouts defined + // with minor exceptions when dealing with back-edges + { + // Future optimization: it might be beneficial to revisit the loop heads (back edge targets) after the first iteration + std::vector inDegreesIgnoringBackedges(m_cfg.numBlocks(), 0); + + for (SSACFG::BlockId id{0}; id.value < m_cfg.numBlocks(); ++id.value) + for (auto const& entry: m_cfg.block(id).entries) + if (!m_liveness.topologicalSort().backEdge(entry, id)) + inDegreesIgnoringBackedges[id.value] += 1; + + std::queue traversalQueue; + traversalQueue.push(m_cfg.entry); + + std::size_t numVisited = 0; + while (!traversalQueue.empty()) + { + auto currentBlockId = traversalQueue.front(); + traversalQueue.pop(); + + visitBlock(currentBlockId); + + m_cfg.block(currentBlockId).forEachExit([&](SSACFG::BlockId const& _exit){ + if (--inDegreesIgnoringBackedges[_exit.value] == 0) + traversalQueue.push(_exit); + }); + ++numVisited; + } + yulAssert(numVisited == m_liveness.topologicalSort().preOrder().size()); + } +} + +void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) +{ + // we already have an input layout defined, return + if (m_resultLayout[_blockId]) + return; + BlockLayout blockLayout{}; + + if (_blockId == m_cfg.entry) + { + if (m_cfg.function) + blockLayout.stackIn = + m_cfg.arguments | + ranges::views::reverse | + ranges::views::transform([](auto&& _variableAndValueId) -> Slot { return Slot::makeValueID(std::get<1>(_variableAndValueId)); }) | + ranges::to; + m_resultLayout[_blockId] = blockLayout; + return; + } + + auto const& block = m_cfg.block(_blockId); + + std::vector> parentExits; + for (auto const& entry: block.entries) + if (m_resultLayout[entry]) + parentExits.emplace_back(entry, &m_resultLayout[entry]->stackOut); + + yulAssert(!parentExits.empty(), fmt::format("None of the parents of block {} were generated", _blockId)); + + if (block.entries.size() == 1) + { + // pass through + yulAssert(parentExits.size() == 1); + blockLayout.stackIn = *parentExits[0].second; + + if (!block.phis.empty()) + handlePhiFunctions(blockLayout.stackIn, PhiInverse(m_cfg, parentExits[0].first, _blockId), m_liveness.liveIn(_blockId)); + } + else + { + // we have more than one entry and need to unify or at the very least apply phi fct. + auto const& liveIn = m_liveness.liveIn(_blockId); + std::vector cumulativeCosts(parentExits.size(), std::numeric_limits::max()); + for (std::size_t i = 0; i < parentExits.size(); ++i) + { + if (!parentExits[i].second) + continue; + std::size_t cumulativeCost = 0; + auto referenceStackIn = *parentExits[i].second; + { + StackType stack(referenceStackIn, {}); + declareJunk(stack, liveIn); + } + handlePhiFunctions(referenceStackIn, PhiInverse(m_cfg, parentExits[i].first, _blockId), liveIn); + for (std::size_t j = 0; j < parentExits.size(); ++j) + { + if (j != i) + { + if (parentExits[j].second != nullptr) + { + auto otherStackIn = *parentExits[j].second; + StackType stack(otherStackIn, {}); + StackShuffler::shuffle( + stack, + stackPreImage(referenceStackIn, PhiInverse(m_cfg, parentExits[j].first, _blockId)), + {}, + referenceStackIn.size() + ); + cumulativeCost += stack.callbacks().numOps; + } + } + } + cumulativeCosts[i] = cumulativeCost; + } + auto const argMin = static_cast( + std::distance(cumulativeCosts.begin(), ranges::min_element(cumulativeCosts)) + ); + yulAssert(parentExits[argMin].second); + blockLayout.stackIn = *parentExits[argMin].second; + StackType stack(blockLayout.stackIn, {}); + declareJunk(stack, liveIn); + handlePhiFunctions(blockLayout.stackIn, PhiInverse(m_cfg, parentExits[argMin].first, _blockId), liveIn); + } + m_resultLayout[_blockId] = blockLayout; +} + +void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) +{ + defineStackIn(_blockId); + yulAssert(m_resultLayout[_blockId]); + BlockLayout& blockLayout = *m_resultLayout[_blockId]; + + SSACFG::BasicBlock const& block = m_cfg.block(_blockId); + + StackData currentStackData = blockLayout.stackIn; + StackType stack(currentStackData, {}); + bool const junkCanBeAdded = m_junkAdmittingBlocksFinder->allowsAdditionOfJunk(_blockId); + + auto const& operationsLiveOut = m_liveness.operationsLiveOut(_blockId); + blockLayout.operationIn.reserve(block.operations.size()); + for (std::size_t operationIndex = 0; operationIndex < block.operations.size(); ++operationIndex) + { + SSACFG::Operation const& operation = block.operations[operationIndex]; + LivenessAnalysis::LivenessData opLiveOut = operationsLiveOut[operationIndex]; + auto opLiveOutWithoutOutputs = opLiveOut; + for (auto const& output: operation.outputs) + opLiveOutWithoutOutputs.erase(output); + + std::vector requiredStackTop; + if (auto const* call = std::get_if(&operation.kind)) + if (call->canContinue) + { + auto const callSiteID = m_callSites.callSiteID(&call->call.get()); + yulAssert(callSiteID.has_value()); + requiredStackTop.emplace_back(Slot::makeFunctionCallReturnLabel(*callSiteID)); + } + requiredStackTop += operation.inputs | ranges::views::transform(Slot::makeValueID); + + for (StackType::Depth depth{0}; depth < stack.size(); ++depth.value) + if ( + stack.slot(depth).isValueID() && + !opLiveOutWithoutOutputs.contains(stack.slot(depth).valueID()) && + ranges::find(requiredStackTop, stack.slot(depth)) == ranges::end(requiredStackTop) + ) + stack.declareJunk(depth); + + std::size_t const targetSize = findOptimalTargetSize(stack.data(), requiredStackTop, opLiveOutWithoutOutputs, junkCanBeAdded); + StackShuffler::shuffle( + stack, + requiredStackTop, + opLiveOutWithoutOutputs, + targetSize + ); + + blockLayout.operationIn.push_back(currentStackData); + for (std::size_t i = 0; i < requiredStackTop.size(); ++i) + stack.pop(); + for (auto const& val: operation.outputs) + stack.push(Slot::makeValueID(val)); + } + + if (auto const* cjump = std::get_if(&block.exit)) + { + auto const& zeroLiveIn = m_liveness.liveIn(cjump->zero); + auto const& blockLiveOut = m_liveness.liveOut(_blockId); + + // check if we have to do anything (dup the condition, bring it to the top etc) + bool const conditionSlotAlreadyFinal = + !blockLiveOut.contains(cjump->condition) && // if our live out does not contain the condition (ie we dont have to dup it) + !stack.empty() && // our stack is not empty + stack.top().isValueID() && stack.top().valueID() == cjump->condition; // and the condition is already on top + if (!conditionSlotAlreadyFinal) + { + auto const condition = Slot::makeValueID(cjump->condition); + auto const targetSize = findOptimalTargetSize(stack.data(), {condition}, blockLiveOut, false); + StackShuffler::shuffle( + stack, {condition}, blockLiveOut, targetSize + ); + } + + yulAssert(!stack.empty() && stack.top().isValueID() && stack.top().valueID() == cjump->condition); + yulAssert(m_cfg.block(cjump->nonZero).phis.empty()); + + // define zero and non-zero stack in layouts + { + std::optional& nonZeroLayout = m_resultLayout[cjump->nonZero]; + yulAssert(!nonZeroLayout, "There should be no way to reach this block other than by going through the parent."); + nonZeroLayout = BlockLayout{}; + nonZeroLayout->stackIn = currentStackData; + // Remove condition; consumed by JUMPI + nonZeroLayout->stackIn.pop_back(); + + if ( + std::optional& zeroLayout = m_resultLayout[cjump->zero]; + !zeroLayout + ) + { + // same as nonzero stack in initially + zeroLayout = nonZeroLayout; + handlePhiFunctions(zeroLayout->stackIn, PhiInverse(m_cfg, _blockId, cjump->zero), zeroLiveIn); + StackType zeroStack(zeroLayout->stackIn, {}); + declareJunk(zeroStack, zeroLiveIn); + } + } + } + + blockLayout.stackOut = currentStackData; +} diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.h b/libyul/backends/evm/ssa/StackLayoutGenerator.h new file mode 100644 index 000000000..c9d45c72a --- /dev/null +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.h @@ -0,0 +1,51 @@ +/* + 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 + +#pragma once + +#include +#include + +#include + +namespace solidity::yul::ssa +{ + +class JunkAdmittingBlocksFinder; + +class StackLayoutGenerator +{ +public: + using Slot = StackSlot; + static SSACFGStackLayout generate(LivenessAnalysis const& _liveness, CallSites const& _callSites); + +private: + explicit StackLayoutGenerator(LivenessAnalysis const& _liveness, CallSites const& _callSites); + + void defineStackIn(SSACFG::BlockId const& _blockId); + void visitBlock(SSACFG::BlockId const& _blockId); + + SSACFG const& m_cfg; + LivenessAnalysis const& m_liveness; + CallSites const& m_callSites; + + std::unique_ptr m_junkAdmittingBlocksFinder; + SSACFGStackLayout m_resultLayout; +}; + +} From 22b1b120be84e072c63e380d0b442c18000b0efd Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 4 Feb 2026 22:47:46 +0100 Subject: [PATCH 1129/1340] Add SSA-CFG StackUtils --- libyul/CMakeLists.txt | 2 + libyul/backends/evm/ssa/StackUtils.cpp | 143 +++++++++++++++++++++++++ libyul/backends/evm/ssa/StackUtils.h | 43 ++++++++ 3 files changed, 188 insertions(+) create mode 100644 libyul/backends/evm/ssa/StackUtils.cpp create mode 100644 libyul/backends/evm/ssa/StackUtils.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index dcc0f923a..d52dbba0d 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -95,6 +95,8 @@ add_library(yul backends/evm/ssa/StackLayoutGenerator.h backends/evm/ssa/StackShuffler.cpp backends/evm/ssa/StackShuffler.h + backends/evm/ssa/StackUtils.cpp + backends/evm/ssa/StackUtils.h backends/evm/ssa/io/DotExporterBase.cpp backends/evm/ssa/io/DotExporterBase.h backends/evm/ssa/io/JSONExporter.cpp diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp new file mode 100644 index 000000000..3f2d28423 --- /dev/null +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -0,0 +1,143 @@ +/* + 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 + +#include + +#include + +#include + +#include + +using namespace solidity::yul::ssa; + +StackData solidity::yul::ssa::stackPreImage(StackData _stack, PhiInverse const& _phiInverse) +{ + if (!_phiInverse.noOp()) + for (auto& slot: _stack) + if (slot.isValueID()) + slot = StackSlot::makeValueID(_phiInverse(slot.valueID())); + return _stack; +} + +std::size_t solidity::yul::ssa::findOptimalTargetSize +( + StackData const& _stackData, + StackData const& _targetArgs, + LivenessAnalysis::LivenessData const& _targetLiveOut, + bool const _canIntroduceJunk +) +{ + std::size_t const minSize = _targetLiveOut.size() + _targetArgs.size(); + boost::container::flat_map deficit; + for (auto const& v: _targetLiveOut | ranges::views::keys) + deficit[StackSlot::makeValueID(v)]++; + for (auto const& arg: _targetArgs) + deficit[arg]++; + for (auto const& slot: _stackData) + if (auto it = deficit.find(slot); it != deficit.end()) + it->second = it->second > 0 ? it->second - 1 : 0; + + std::size_t const pivot = _canIntroduceJunk ? _stackData.size() + _targetArgs.size() : _stackData.size() + ranges::accumulate(deficit | ranges::views::values, 0u); + std::size_t const startSize = std::max(pivot, minSize); + static std::size_t constexpr maxUpwardExpansion = 32; + + StackData data; + data.reserve(startSize + maxUpwardExpansion); + auto const evaluateCost = [&](std::size_t const _targetSize) -> std::size_t + { + data = _stackData; + Stack countOpsStack(data, {}); + StackShuffler::shuffle(countOpsStack, _targetArgs, _targetLiveOut, _targetSize); + yulAssert(countOpsStack.size() == _targetSize); + return countOpsStack.callbacks().numOps; + }; + + std::size_t bestCost = evaluateCost(startSize); + auto result = startSize; + + // On non-reverting paths, only search downward from pivot to avoid growing the stack. + // On reverting paths, search in both directions since stack cleanup doesn't matter. + static std::size_t constexpr stopAfter = 3; + std::size_t consecutiveIncreases = 0; + // search downward + { + std::size_t size = startSize; + while (size > minSize) + { + --size; + auto const cost = evaluateCost(size); + if (cost < bestCost) + { + bestCost = cost; + result = size; + consecutiveIncreases = 0; + } + else if (++consecutiveIncreases >= stopAfter) + break; + } + } + // search upward (only on reverting paths) + if (_canIntroduceJunk) + { + consecutiveIncreases = 0; + for (std::size_t size = startSize + 1; size <= startSize + maxUpwardExpansion; ++size) + { + auto const cost = evaluateCost(size); + if (cost < bestCost) + { + bestCost = cost; + result = size; + consecutiveIncreases = 0; + } + else if (++consecutiveIncreases >= stopAfter) + break; + } + } + return result; +} + +CallSites solidity::yul::ssa::gatherCallSites(SSACFG const& _cfg) +{ + CallSites result; + std::vector visited(_cfg.numBlocks(), false); + visited[_cfg.entry.value] = true; + std::vector toVisit; + toVisit.reserve(_cfg.numBlocks()); + toVisit.push_back(_cfg.entry); + + while (!toVisit.empty()) + { + auto const blockId = toVisit.back(); + toVisit.pop_back(); + auto const& block = _cfg.block(blockId); + block.forEachExit([&toVisit, &visited](SSACFG::BlockId const& _exitBlockId){ + if (!visited[_exitBlockId.value]) + { + visited[_exitBlockId.value] = true; + toVisit.push_back(_exitBlockId); + } + }); + + for (auto const& operation: block.operations) + if (auto const* call = std::get_if(&operation.kind)) + if (call->canContinue) + result.addCallSite(&call->call.get()); + } + return result; +} diff --git a/libyul/backends/evm/ssa/StackUtils.h b/libyul/backends/evm/ssa/StackUtils.h new file mode 100644 index 000000000..6f5e991a0 --- /dev/null +++ b/libyul/backends/evm/ssa/StackUtils.h @@ -0,0 +1,43 @@ +/* + 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 + +#pragma once + +#include +#include + +namespace solidity::yul::ssa +{ + +struct CountingInstructionsCallbacks +{ + std::size_t numOps = 0; + void swap(std::size_t) { ++numOps; } + void dup(std::size_t) { ++numOps; } + void push(StackSlot const&) { ++numOps; } + void pop() { ++numOps; } +}; + +/// Transform stack data by replacing all its phi variables with their respective preimages. +StackData stackPreImage(StackData _stack, PhiInverse const& _phiInverse); + +std::size_t findOptimalTargetSize(StackData const& _stackData, StackData const& _targetArgs, LivenessAnalysis::LivenessData const& _targetLiveOut, bool _canIntroduceJunk); + +CallSites gatherCallSites(SSACFG const& _cfg); + +} From 889679b01e23d439eddc5085101af92822753b7a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 5 Feb 2026 14:46:54 +0100 Subject: [PATCH 1130/1340] Add SSA-CFG StackLayoutGenerator test --- test/CMakeLists.txt | 2 + test/InteractiveTests.h | 4 +- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 216 +++++++++++++++++++ test/libyul/ssa/StackLayoutGeneratorTest.h | 37 ++++ test/libyul/ssa/StackShufflerTest.cpp | 4 +- test/libyul/ssa/StackShufflerTest.h | 2 +- test/tools/CMakeLists.txt | 2 + 7 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 test/libyul/ssa/StackLayoutGeneratorTest.cpp create mode 100644 test/libyul/ssa/StackLayoutGeneratorTest.h diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f36ae4147..02a45088f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -173,6 +173,8 @@ set(libyul_sources libyul/YulOptimizerTest.h libyul/YulOptimizerTestCommon.cpp libyul/YulOptimizerTestCommon.h + libyul/ssa/StackLayoutGeneratorTest.cpp + libyul/ssa/StackLayoutGeneratorTest.h libyul/ssa/StackShufflerTest.cpp libyul/ssa/StackShufflerTest.h ) diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index ff2725471..7930dc32d 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -74,7 +75,8 @@ Testsuite const g_interactiveTestsuites[] = { {"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create}, {"Yul Control Flow Graph", "libyul", "yulControlFlowGraph", false, false, &yul::test::ControlFlowGraphTest::create}, {"Yul SSA Control Flow Graph", "libyul", "yulSSAControlFlowGraph", false, false, &yul::test::SSAControlFlowGraphTest::create}, - {"Yul SSA StackShuffling", "libyul", "ssa/stackShuffler", false, false, &yul::ssa::test::ShufflingTest::create}, + {"Yul SSA StackShuffling", "libyul", "ssa/stackShuffler", false, false, &yul::test::ssa::ShufflingTest::create}, + {"Yul SSA StackLayoutGenerator","libyul", "ssa/stackLayoutGenerator", false, false, &yul::test::ssa::StackLayoutGeneratorTest::create}, {"Yul Stack Layout", "libyul", "yulStackLayout", false, false, &yul::test::StackLayoutGeneratorTest::create}, {"Yul Stack Shuffling", "libyul", "yulStackShuffling", false, false, &yul::test::StackShufflingTest::create}, {"Control Flow Side Effects", "libyul", "controlFlowSideEffects", false, false, &yul::test::ControlFlowSideEffectsTest::create}, diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp new file mode 100644 index 000000000..a7ddad529 --- /dev/null +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -0,0 +1,216 @@ +/* + 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 + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#ifdef ISOLTEST +#include +#if (BOOST_VERSION < 108800) +#include +#else +#define BOOST_PROCESS_VERSION 1 +#include +#include +#include +#endif +#endif + +using namespace solidity; +using namespace solidity::util; +using namespace solidity::yul::ssa; +using namespace solidity::yul::test::ssa; + +namespace +{ + +class StackLayoutDotExporter: public io::DotExporterBase +{ +public: + StackLayoutDotExporter(SSACFG const& _cfg, std::size_t _functionIndex, SSACFGStackLayout const& _layout): + DotExporterBase(_cfg, _functionIndex), + m_layout(_layout) + { + } + +protected: + void writeBlockLabel(std::ostream& _out, SSACFG::BlockId _blockId) override + { + auto const& block = m_cfg.block(_blockId); + auto const& blockLayout = m_layout[_blockId]; + yulAssert(blockLayout.has_value()); + + _out << "\\\n"; + _out << "IN: " << stackToString(blockLayout->stackIn) << "\\l\\\n"; + + for (std::size_t i = 0; i < block.operations.size(); ++i) + { + auto const& operation = block.operations[i]; + yulAssert(i < blockLayout->operationIn.size()); + auto operationStack = blockLayout->operationIn[i]; + + _out << "\\l\\\n"; + _out << stackToString(operationStack) << "\\l\\\n"; + + std::visit(GenericVisitor{ + [&](SSACFG::Call const& _call) { + _out << escapeLabel(_call.function.get().name.str()); + }, + [&](SSACFG::BuiltinCall const& _call) { + _out << escapeLabel(_call.builtin.get().name); + }, + [&](SSACFG::LiteralAssignment const&) { + yulAssert(operation.inputs.size() == 1); + _out << escapeLabel(operation.inputs.back().str(m_cfg)); + } + }, operation.kind); + _out << "\\l\\\n"; + + yulAssert(operation.inputs.size() <= operationStack.size()); + for (std::size_t j = 0; j < operation.inputs.size(); ++j) + operationStack.pop_back(); + for (auto const& output: operation.outputs) + operationStack.push_back(StackSlot::makeValueID(output)); + _out << stackToString(operationStack) << "\\l\\\n"; + } + + _out << "\\l\\\n"; + _out << "OUT: " << stackToString(blockLayout->stackOut) << "\\l\\\n"; + } + +private: + SSACFGStackLayout const& m_layout; +}; + +} + +std::unique_ptr StackLayoutGeneratorTest::create(Config const& _config) +{ + return std::make_unique(_config.filename); +} + +StackLayoutGeneratorTest::StackLayoutGeneratorTest(std::string const& _filename): TestCase(_filename) +{ + m_source = m_reader.source(); + auto dialectName = m_reader.stringSetting("dialect", "evm"); + soltestAssert(dialectName == "evm"); + m_expectation = m_reader.simpleExpectations(); +} + +frontend::test::TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) +{ + static std::string_view constexpr SUBOBJECT_GRAPH_SEPARATOR = "\n>>>>> GRAPH SEPARATOR\n"; + YulStack const yulStack = yul::test::parseYul(m_source); + if (yulStack.hasErrors()) + { + yul::test::printYulErrors(yulStack, _stream, _linePrefix, _formatted); + return TestResult::FatalError; + } + + std::set visited; + visited.insert(yulStack.parserResult().get()); + + std::vector toVisit{yulStack.parserResult().get()}; + while (!toVisit.empty()) + { + auto const& object = *toVisit.back(); + toVisit.pop_back(); + + std::unique_ptr const controlFlow = SSACFGBuilder::build( + *object.analysisInfo, + *object.dialect(), + object.code()->root(), + false + ); + // insert separator + if (!m_obtainedResult.empty()) + m_obtainedResult += SUBOBJECT_GRAPH_SEPARATOR; + + m_obtainedResult += "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\", rankdir=LR]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; + + for (std::size_t index = 0; index < controlFlow->functionGraphs.size(); ++index) + { + auto const& cfg = *controlFlow->functionGraphs[index]; + SSACFGStackLayout const layout = StackLayoutGenerator::generate( + LivenessAnalysis(cfg), + gatherCallSites(cfg) + ); + StackLayoutDotExporter exporter(cfg, index, layout); + if (cfg.function) + m_obtainedResult += exporter.exportFunction(*cfg.function, false); + else + m_obtainedResult += exporter.exportBlocks(cfg.entry, false); + } + + m_obtainedResult += "}\n"; + + for (auto const& subNode: object.subObjects) + if (auto subObject = std::dynamic_pointer_cast(subNode)) + if (!visited.contains(subObject.get())) + { + visited.insert(subObject.get()); + toVisit.push_back(subObject.get()); + } + } + + auto const result = checkResult(_stream, _linePrefix, _formatted); + +#ifdef ISOLTEST + char* graphDisplayer = nullptr; + if (result == TestResult::Failure) + graphDisplayer = getenv("ISOLTEST_DISPLAY_GRAPHS_FAILURE"); + else if (result == TestResult::Success) + graphDisplayer = getenv("ISOLTEST_DISPLAY_GRAPHS_SUCCESS"); + + if (graphDisplayer) + { + if (result == TestResult::Success) + std::cout << std::endl << m_source << std::endl; + for (auto const dotRange: ranges::views::split(m_obtainedResult, SUBOBJECT_GRAPH_SEPARATOR)) + { + std::string_view dot(&*dotRange.begin(), static_cast(ranges::distance(dotRange))); + boost::process::opstream pipe; + boost::process::child child(graphDisplayer, boost::process::std_in < pipe); + + pipe << dot; + pipe.flush(); + pipe.pipe().close(); + if (result == TestResult::Success) + child.wait(); + else + child.detach(); + } + } +#endif + + return result; +} diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.h b/test/libyul/ssa/StackLayoutGeneratorTest.h new file mode 100644 index 000000000..7b66363f3 --- /dev/null +++ b/test/libyul/ssa/StackLayoutGeneratorTest.h @@ -0,0 +1,37 @@ +/* + 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 + +#pragma once + + +#include + +#include + +namespace solidity::yul::test::ssa +{ + +class StackLayoutGeneratorTest: public frontend::test::TestCase +{ +public: + static std::unique_ptr create(Config const& _config); + explicit StackLayoutGeneratorTest(std::string const& _filename); + TestResult run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) override; +}; + +} diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index 3c8c964e7..cd24b3b5e 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -39,8 +39,10 @@ #include using namespace solidity; +using namespace solidity::yul; using namespace solidity::yul::ssa; -using namespace solidity::yul::ssa::test; +using namespace solidity::yul::test; +using namespace solidity::yul::test::ssa; namespace { diff --git a/test/libyul/ssa/StackShufflerTest.h b/test/libyul/ssa/StackShufflerTest.h index 14b0d98f6..37f9b61e5 100644 --- a/test/libyul/ssa/StackShufflerTest.h +++ b/test/libyul/ssa/StackShufflerTest.h @@ -22,7 +22,7 @@ #include -namespace solidity::yul::ssa::test +namespace solidity::yul::test::ssa { class ShufflingTest: public frontend::test::TestCase diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 7b7331c77..0a1c33873 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -53,6 +53,8 @@ add_executable(isoltest ../libyul/YulOptimizerTest.cpp ../libyul/YulOptimizerTestCommon.cpp ../libyul/YulInterpreterTest.cpp + ../libyul/ssa/StackLayoutGeneratorTest.cpp + ../libyul/ssa/StackLayoutGeneratorTest.h ../libyul/ssa/StackShufflerTest.cpp ../libyul/ssa/StackShufflerTest.h ) From b0d0ac1a212096ada177c3b875d22cdfdd511017 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 9 Feb 2026 14:33:04 +0100 Subject: [PATCH 1131/1340] Add SSA CFG stack layout generation tests --- .../ssa/stackLayoutGenerator/dead_code.yul | 79 ++++++++++++ .../ssa/stackLayoutGenerator/function.yul | 106 ++++++++++++++++ .../ssa/stackLayoutGenerator/multi_return.yul | 59 +++++++++ .../ssa/stackLayoutGenerator/nested_for.yul | 119 ++++++++++++++++++ .../ssa/stackLayoutGenerator/recursion.yul | 71 +++++++++++ .../ssa/stackLayoutGenerator/simple_for.yul | 100 +++++++++++++++ .../ssa/stackLayoutGenerator/simple_if.yul | 76 +++++++++++ .../ssa/stackLayoutGenerator/switch.yul | 95 ++++++++++++++ 8 files changed, 705 insertions(+) create mode 100644 test/libyul/ssa/stackLayoutGenerator/dead_code.yul create mode 100644 test/libyul/ssa/stackLayoutGenerator/function.yul create mode 100644 test/libyul/ssa/stackLayoutGenerator/multi_return.yul create mode 100644 test/libyul/ssa/stackLayoutGenerator/nested_for.yul create mode 100644 test/libyul/ssa/stackLayoutGenerator/recursion.yul create mode 100644 test/libyul/ssa/stackLayoutGenerator/simple_for.yul create mode 100644 test/libyul/ssa/stackLayoutGenerator/simple_if.yul create mode 100644 test/libyul/ssa/stackLayoutGenerator/switch.yul diff --git a/test/libyul/ssa/stackLayoutGenerator/dead_code.yul b/test/libyul/ssa/stackLayoutGenerator/dead_code.yul new file mode 100644 index 000000000..adba2a345 --- /dev/null +++ b/test/libyul/ssa/stackLayoutGenerator/dead_code.yul @@ -0,0 +1,79 @@ +{ + let x := calldataload(0) + if x { + revert(0, 0) + } + let y := calldataload(32) + if y { + revert(0, 0) + } + sstore(x, y) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans", rankdir=LR] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry [label="Entry"]; +// Entry -> Block0_0; +// Block0_0 [label="\ +// IN: []\l\ +// \l\ +// [lit0]\l\ +// calldataload\l\ +// [v0]\l\ +// \l\ +// OUT: [v0, v0]\l\ +// "]; +// Block0_0 -> Block0_0Exit; +// Block0_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit:0 -> Block0_2 [style="solid"]; +// Block0_0Exit:1 -> Block0_1 [style="solid"]; +// Block0_1 [label="\ +// IN: [v0]\l\ +// \l\ +// [JUNK, lit0, lit0]\l\ +// revert\l\ +// [JUNK]\l\ +// \l\ +// OUT: [JUNK]\l\ +// "]; +// Block0_1Exit [label="Terminated"]; +// Block0_1 -> Block0_1Exit; +// Block0_2 [label="\ +// IN: [v0]\l\ +// \l\ +// [v0, lit1]\l\ +// calldataload\l\ +// [v0, v1]\l\ +// \l\ +// OUT: [v0, v1, v1]\l\ +// "]; +// Block0_2 -> Block0_2Exit; +// Block0_2Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_2Exit:0 -> Block0_5 [style="solid"]; +// Block0_2Exit:1 -> Block0_4 [style="solid"]; +// Block0_4 [label="\ +// IN: [v0, v1]\l\ +// \l\ +// [JUNK, JUNK, lit0, lit0]\l\ +// revert\l\ +// [JUNK, JUNK]\l\ +// \l\ +// OUT: [JUNK, JUNK]\l\ +// "]; +// Block0_4Exit [label="Terminated"]; +// Block0_4 -> Block0_4Exit; +// Block0_5 [label="\ +// IN: [v0, v1]\l\ +// \l\ +// [v0, v1, v0]\l\ +// sstore\l\ +// [v0]\l\ +// \l\ +// OUT: [v0]\l\ +// "]; +// Block0_5Exit [label="MainExit"]; +// Block0_5 -> Block0_5Exit; +// } diff --git a/test/libyul/ssa/stackLayoutGenerator/function.yul b/test/libyul/ssa/stackLayoutGenerator/function.yul new file mode 100644 index 000000000..a134c36f8 --- /dev/null +++ b/test/libyul/ssa/stackLayoutGenerator/function.yul @@ -0,0 +1,106 @@ +{ + function f(a, b) -> r { + let x := add(a,b) + r := sub(x,a) + } + function g() { + sstore(0x01, 0x0101) + } + function h(x) { + h(f(x, 0)) + g() + } + function i() -> v, w { + v := 0x0202 + w := 0x0303 + } + let x, y := i() + h(x) + h(y) + // This call of g() is unreachable too as the one in h() but we wanna cover both cases. + g() +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans", rankdir=LR] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry [label="Entry"]; +// Entry -> Block0_0; +// Block0_0 [label="\ +// IN: []\l\ +// \l\ +// [FunctionCallReturnLabel[0]]\l\ +// i\l\ +// [FunctionCallReturnLabel[0], v0, v1]\l\ +// \l\ +// [v0, JUNK, v0]\l\ +// h\l\ +// [v0, JUNK]\l\ +// \l\ +// OUT: [v0, JUNK]\l\ +// "]; +// Block0_0Exit [label="Terminated"]; +// Block0_0 -> Block0_0Exit; +// FunctionEntry_f_0 [label="function f: +// r := f(v0, v1)"]; +// FunctionEntry_f_0 -> Block1_0; +// Block1_0 [label="\ +// IN: [v1, v0]\l\ +// \l\ +// [v0, v1, v0]\l\ +// add\l\ +// [v0, v2]\l\ +// \l\ +// [v0, v2]\l\ +// sub\l\ +// [v3]\l\ +// \l\ +// OUT: [v3]\l\ +// "]; +// Block1_0Exit [label="FunctionReturn[v3]"]; +// Block1_0 -> Block1_0Exit; +// FunctionEntry_g_0 [label="function g: +// g()"]; +// FunctionEntry_g_0 -> Block2_0; +// Block2_0 [label="\ +// IN: []\l\ +// \l\ +// [lit0, lit1]\l\ +// sstore\l\ +// []\l\ +// \l\ +// OUT: []\l\ +// "]; +// Block2_0Exit [label="FunctionReturn[]"]; +// Block2_0 -> Block2_0Exit; +// FunctionEntry_h_0 [label="function h: +// h(v0)"]; +// FunctionEntry_h_0 -> Block3_0; +// Block3_0 [label="\ +// IN: [v0]\l\ +// \l\ +// [v0, FunctionCallReturnLabel[0], lit0, v0]\l\ +// f\l\ +// [v0, FunctionCallReturnLabel[0], v1]\l\ +// \l\ +// [JUNK, v1]\l\ +// h\l\ +// [JUNK]\l\ +// \l\ +// OUT: [JUNK]\l\ +// "]; +// Block3_0Exit [label="Terminated"]; +// Block3_0 -> Block3_0Exit; +// FunctionEntry_i_0 [label="function i: +// v, w := i()"]; +// FunctionEntry_i_0 -> Block4_0; +// Block4_0 [label="\ +// IN: []\l\ +// \l\ +// OUT: []\l\ +// "]; +// Block4_0Exit [label="FunctionReturn[0x0202, 0x0303]"]; +// Block4_0 -> Block4_0Exit; +// } diff --git a/test/libyul/ssa/stackLayoutGenerator/multi_return.yul b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul new file mode 100644 index 000000000..c1f2b94d4 --- /dev/null +++ b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul @@ -0,0 +1,59 @@ +{ + function pair(a) -> x, y { + x := add(a, 1) + y := add(a, 2) + } + let p, q := pair(42) + let r, s := pair(p) + sstore(q, add(r, s)) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans", rankdir=LR] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry [label="Entry"]; +// Entry -> Block0_0; +// Block0_0 [label="\ +// IN: []\l\ +// \l\ +// [FunctionCallReturnLabel[0], lit0]\l\ +// pair\l\ +// [FunctionCallReturnLabel[0], v0, v1]\l\ +// \l\ +// [v0, v1, FunctionCallReturnLabel[1], v0]\l\ +// pair\l\ +// [v0, v1, FunctionCallReturnLabel[1], v2, v3]\l\ +// \l\ +// [JUNK, v1, v2, v3, v2]\l\ +// add\l\ +// [JUNK, v1, v2, v4]\l\ +// \l\ +// [JUNK, v1, JUNK, v4, v1]\l\ +// sstore\l\ +// [JUNK, v1, JUNK]\l\ +// \l\ +// OUT: [JUNK, v1, JUNK]\l\ +// "]; +// Block0_0Exit [label="MainExit"]; +// Block0_0 -> Block0_0Exit; +// FunctionEntry_pair_0 [label="function pair: +// x, y := pair(v0)"]; +// FunctionEntry_pair_0 -> Block1_0; +// Block1_0 [label="\ +// IN: [v0]\l\ +// \l\ +// [v0, lit1, v0]\l\ +// add\l\ +// [v0, v1]\l\ +// \l\ +// [v1, lit2, v0]\l\ +// add\l\ +// [v1, v2]\l\ +// \l\ +// OUT: [v1, v2]\l\ +// "]; +// Block1_0Exit [label="FunctionReturn[v1, v2]"]; +// Block1_0 -> Block1_0Exit; +// } diff --git a/test/libyul/ssa/stackLayoutGenerator/nested_for.yul b/test/libyul/ssa/stackLayoutGenerator/nested_for.yul new file mode 100644 index 000000000..f595c19b2 --- /dev/null +++ b/test/libyul/ssa/stackLayoutGenerator/nested_for.yul @@ -0,0 +1,119 @@ +{ + let s + for {let i := 0} lt(i, 10) {i := add(i, 1)} { + for {let j := 0} lt(j, 10) {j := add(j, 1)} { + s := add(s, mul(i, j)) + } + } + mstore(0, s) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans", rankdir=LR] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry [label="Entry"]; +// Entry -> Block0_0; +// Block0_0 [label="\ +// IN: []\l\ +// \l\ +// OUT: []\l\ +// "]; +// Block0_0 -> Block0_0Exit [arrowhead=none]; +// Block0_0Exit [label="Jump" shape=oval]; +// Block0_0Exit -> Block0_1 [style="solid"]; +// Block0_1 [label="\ +// IN: [phi0, phi4]\l\ +// \l\ +// [phi0, phi4, lit1, phi0]\l\ +// lt\l\ +// [phi0, phi4, v0]\l\ +// \l\ +// OUT: [phi0, phi4, v0]\l\ +// "]; +// Block0_1 -> Block0_1Exit; +// Block0_1Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_1Exit:0 -> Block0_4 [style="solid"]; +// Block0_1Exit:1 -> Block0_2 [style="solid"]; +// Block0_2 [label="\ +// IN: [phi0, phi4]\l\ +// \l\ +// OUT: [phi0, phi4]\l\ +// "]; +// Block0_2 -> Block0_2Exit [arrowhead=none]; +// Block0_2Exit [label="Jump" shape=oval]; +// Block0_2Exit -> Block0_5 [style="solid"]; +// Block0_4 [label="\ +// IN: [JUNK, phi4]\l\ +// \l\ +// [JUNK, phi4, lit0]\l\ +// mstore\l\ +// [JUNK]\l\ +// \l\ +// OUT: [JUNK]\l\ +// "]; +// Block0_4Exit [label="MainExit"]; +// Block0_4 -> Block0_4Exit; +// Block0_5 [label="\ +// IN: [phi0, JUNK, phi1, phi3]\l\ +// \l\ +// [phi0, JUNK, phi1, phi3, lit1, phi1]\l\ +// lt\l\ +// [phi0, JUNK, phi1, phi3, v1]\l\ +// \l\ +// OUT: [phi0, JUNK, phi1, phi3, v1]\l\ +// "]; +// Block0_5 -> Block0_5Exit; +// Block0_5Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_5Exit:0 -> Block0_8 [style="solid"]; +// Block0_5Exit:1 -> Block0_6 [style="solid"]; +// Block0_6 [label="\ +// IN: [phi0, JUNK, phi1, phi3]\l\ +// \l\ +// [phi0, JUNK, phi1, phi3, phi1, phi0]\l\ +// mul\l\ +// [phi0, JUNK, phi1, phi3, v2]\l\ +// \l\ +// [phi0, JUNK, phi1, v2, phi3]\l\ +// add\l\ +// [phi0, JUNK, phi1, v3]\l\ +// \l\ +// OUT: [phi0, JUNK, phi1, v3]\l\ +// "]; +// Block0_6 -> Block0_6Exit [arrowhead=none]; +// Block0_6Exit [label="Jump" shape=oval]; +// Block0_6Exit -> Block0_7 [style="solid"]; +// Block0_8 [label="\ +// IN: [phi0, JUNK, JUNK, phi3]\l\ +// \l\ +// OUT: [phi0, JUNK, JUNK, phi3]\l\ +// "]; +// Block0_8 -> Block0_8Exit [arrowhead=none]; +// Block0_8Exit [label="Jump" shape=oval]; +// Block0_8Exit -> Block0_3 [style="solid"]; +// Block0_7 [label="\ +// IN: [phi0, JUNK, phi1, v3]\l\ +// \l\ +// [phi0, JUNK, v3, lit2, phi1]\l\ +// add\l\ +// [phi0, JUNK, v3, v4]\l\ +// \l\ +// OUT: [phi0, JUNK, v3, v4]\l\ +// "]; +// Block0_7 -> Block0_7Exit [arrowhead=none]; +// Block0_7Exit [label="Jump" shape=oval]; +// Block0_7Exit -> Block0_5 [style="solid"]; +// Block0_3 [label="\ +// IN: [phi0, JUNK, JUNK, phi3]\l\ +// \l\ +// [phi3, JUNK, JUNK, lit2, phi0]\l\ +// add\l\ +// [phi3, JUNK, JUNK, v5]\l\ +// \l\ +// OUT: [phi3, JUNK, JUNK, v5]\l\ +// "]; +// Block0_3 -> Block0_3Exit [arrowhead=none]; +// Block0_3Exit [label="Jump" shape=oval]; +// Block0_3Exit -> Block0_1 [style="solid"]; +// } diff --git a/test/libyul/ssa/stackLayoutGenerator/recursion.yul b/test/libyul/ssa/stackLayoutGenerator/recursion.yul new file mode 100644 index 000000000..4a33f172d --- /dev/null +++ b/test/libyul/ssa/stackLayoutGenerator/recursion.yul @@ -0,0 +1,71 @@ +{ + function sum(n) -> s { + if n { + s := add(n, sum(sub(n, 1))) + } + } + mstore(0, sum(10)) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans", rankdir=LR] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry [label="Entry"]; +// Entry -> Block0_0; +// Block0_0 [label="\ +// IN: []\l\ +// \l\ +// [FunctionCallReturnLabel[0], lit0]\l\ +// sum\l\ +// [FunctionCallReturnLabel[0], v0]\l\ +// \l\ +// [v0, lit1]\l\ +// mstore\l\ +// []\l\ +// \l\ +// OUT: []\l\ +// "]; +// Block0_0Exit [label="MainExit"]; +// Block0_0 -> Block0_0Exit; +// FunctionEntry_sum_0 [label="function sum: +// s := sum(v0)"]; +// FunctionEntry_sum_0 -> Block1_0; +// Block1_0 [label="\ +// IN: [v0]\l\ +// \l\ +// OUT: [v0, v0]\l\ +// "]; +// Block1_0 -> Block1_0Exit; +// Block1_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_0Exit:0 -> Block1_2 [style="solid"]; +// Block1_0Exit:1 -> Block1_1 [style="solid"]; +// Block1_1 [label="\ +// IN: [v0]\l\ +// \l\ +// [v0, lit1, v0]\l\ +// sub\l\ +// [v0, v1]\l\ +// \l\ +// [v0, FunctionCallReturnLabel[0], v1]\l\ +// sum\l\ +// [v0, FunctionCallReturnLabel[0], v2]\l\ +// \l\ +// [v2, v0]\l\ +// add\l\ +// [v3]\l\ +// \l\ +// OUT: [v3]\l\ +// "]; +// Block1_1 -> Block1_1Exit [arrowhead=none]; +// Block1_1Exit [label="Jump" shape=oval]; +// Block1_1Exit -> Block1_2 [style="solid"]; +// Block1_2 [label="\ +// IN: [JUNK, phi0]\l\ +// \l\ +// OUT: [JUNK, phi0]\l\ +// "]; +// Block1_2Exit [label="FunctionReturn[phi0]"]; +// Block1_2 -> Block1_2Exit; +// } diff --git a/test/libyul/ssa/stackLayoutGenerator/simple_for.yul b/test/libyul/ssa/stackLayoutGenerator/simple_for.yul new file mode 100644 index 000000000..f245c5f17 --- /dev/null +++ b/test/libyul/ssa/stackLayoutGenerator/simple_for.yul @@ -0,0 +1,100 @@ +{ + let x + for {let i := 0} x {i := add(i, 1)} { + if mload(i) { + x := add(x, i) + x := add(x, mload(32)) + } + } + mstore(x, 33) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans", rankdir=LR] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry [label="Entry"]; +// Entry -> Block0_0; +// Block0_0 [label="\ +// IN: []\l\ +// \l\ +// OUT: []\l\ +// "]; +// Block0_0 -> Block0_0Exit [arrowhead=none]; +// Block0_0Exit [label="Jump" shape=oval]; +// Block0_0Exit -> Block0_1 [style="solid"]; +// Block0_1 [label="\ +// IN: [phi0, phi1]\l\ +// \l\ +// OUT: [phi0, phi1, phi0]\l\ +// "]; +// Block0_1 -> Block0_1Exit; +// Block0_1Exit [label="{ If phi0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_1Exit:0 -> Block0_4 [style="solid"]; +// Block0_1Exit:1 -> Block0_2 [style="solid"]; +// Block0_2 [label="\ +// IN: [phi0, phi1]\l\ +// \l\ +// [phi0, phi1, phi1]\l\ +// mload\l\ +// [phi0, phi1, v0]\l\ +// \l\ +// OUT: [phi0, phi1, v0]\l\ +// "]; +// Block0_2 -> Block0_2Exit; +// Block0_2Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_2Exit:0 -> Block0_6 [style="solid"]; +// Block0_2Exit:1 -> Block0_5 [style="solid"]; +// Block0_4 [label="\ +// IN: [phi0, JUNK]\l\ +// \l\ +// [phi0, JUNK, lit3, phi0]\l\ +// mstore\l\ +// [phi0, JUNK]\l\ +// \l\ +// OUT: [phi0, JUNK]\l\ +// "]; +// Block0_4Exit [label="MainExit"]; +// Block0_4 -> Block0_4Exit; +// Block0_5 [label="\ +// IN: [phi0, phi1]\l\ +// \l\ +// [phi1, phi1, phi0]\l\ +// add\l\ +// [phi1, v1]\l\ +// \l\ +// [phi1, v1, lit1]\l\ +// mload\l\ +// [phi1, v1, v2]\l\ +// \l\ +// [phi1, v2, v1]\l\ +// add\l\ +// [phi1, v3]\l\ +// \l\ +// OUT: [phi1, v3]\l\ +// "]; +// Block0_5 -> Block0_5Exit [arrowhead=none]; +// Block0_5Exit [label="Jump" shape=oval]; +// Block0_5Exit -> Block0_6 [style="solid"]; +// Block0_6 [label="\ +// IN: [phi3, phi1]\l\ +// \l\ +// OUT: [phi3, phi1]\l\ +// "]; +// Block0_6 -> Block0_6Exit [arrowhead=none]; +// Block0_6Exit [label="Jump" shape=oval]; +// Block0_6Exit -> Block0_3 [style="solid"]; +// Block0_3 [label="\ +// IN: [phi3, phi1]\l\ +// \l\ +// [phi3, lit2, phi1]\l\ +// add\l\ +// [phi3, v4]\l\ +// \l\ +// OUT: [phi3, v4]\l\ +// "]; +// Block0_3 -> Block0_3Exit [arrowhead=none]; +// Block0_3Exit [label="Jump" shape=oval]; +// Block0_3Exit -> Block0_1 [style="solid"]; +// } diff --git a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul new file mode 100644 index 000000000..f9e0039e3 --- /dev/null +++ b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul @@ -0,0 +1,76 @@ +{ + function f(a, b) -> c { + if mload(a) { + a := add(a, 2) + revert(a, a) + } + c := add(a, b) + } + mstore(42, f(0, 1)) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans", rankdir=LR] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry [label="Entry"]; +// Entry -> Block0_0; +// Block0_0 [label="\ +// IN: []\l\ +// \l\ +// [FunctionCallReturnLabel[0], lit0, lit1]\l\ +// f\l\ +// [FunctionCallReturnLabel[0], v0]\l\ +// \l\ +// [v0, lit2]\l\ +// mstore\l\ +// []\l\ +// \l\ +// OUT: []\l\ +// "]; +// Block0_0Exit [label="MainExit"]; +// Block0_0 -> Block0_0Exit; +// FunctionEntry_f_0 [label="function f: +// c := f(v0, v1)"]; +// FunctionEntry_f_0 -> Block1_0; +// Block1_0 [label="\ +// IN: [v1, v0]\l\ +// \l\ +// [v1, v0, v0]\l\ +// mload\l\ +// [v1, v0, v2]\l\ +// \l\ +// OUT: [v1, v0, v2]\l\ +// "]; +// Block1_0 -> Block1_0Exit; +// Block1_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_0Exit:0 -> Block1_2 [style="solid"]; +// Block1_0Exit:1 -> Block1_1 [style="solid"]; +// Block1_1 [label="\ +// IN: [v1, v0]\l\ +// \l\ +// [JUNK, v0, lit1, v0]\l\ +// add\l\ +// [JUNK, v0, v3]\l\ +// \l\ +// [JUNK, JUNK, v3, v3]\l\ +// revert\l\ +// [JUNK, JUNK]\l\ +// \l\ +// OUT: [JUNK, JUNK]\l\ +// "]; +// Block1_1Exit [label="Terminated"]; +// Block1_1 -> Block1_1Exit; +// Block1_2 [label="\ +// IN: [v1, v0]\l\ +// \l\ +// [v1, v0]\l\ +// add\l\ +// [v4]\l\ +// \l\ +// OUT: [v4]\l\ +// "]; +// Block1_2Exit [label="FunctionReturn[v4]"]; +// Block1_2 -> Block1_2Exit; +// } diff --git a/test/libyul/ssa/stackLayoutGenerator/switch.yul b/test/libyul/ssa/stackLayoutGenerator/switch.yul new file mode 100644 index 000000000..898944d37 --- /dev/null +++ b/test/libyul/ssa/stackLayoutGenerator/switch.yul @@ -0,0 +1,95 @@ +{ + let x := 0x0101 + let y := 0x0202 + let z := 0x0303 + switch sload(x) + case 0 { + x := 0x42 + } + case 1 { + y := 0x42 + } + default { + sstore(z, z) + } + + sstore(0x0404, y) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans", rankdir=LR] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry [label="Entry"]; +// Entry -> Block0_0; +// Block0_0 [label="\ +// IN: []\l\ +// \l\ +// [lit0]\l\ +// sload\l\ +// [v0]\l\ +// \l\ +// [v0, lit3, v0]\l\ +// eq\l\ +// [v0, v1]\l\ +// \l\ +// OUT: [v0, v1]\l\ +// "]; +// Block0_0 -> Block0_0Exit; +// Block0_0Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit:0 -> Block0_3 [style="solid"]; +// Block0_0Exit:1 -> Block0_2 [style="solid"]; +// Block0_2 [label="\ +// IN: [v0]\l\ +// \l\ +// OUT: [v0]\l\ +// "]; +// Block0_2 -> Block0_2Exit [arrowhead=none]; +// Block0_2Exit [label="Jump" shape=oval]; +// Block0_2Exit -> Block0_1 [style="solid"]; +// Block0_3 [label="\ +// IN: [v0]\l\ +// \l\ +// [lit5, v0]\l\ +// eq\l\ +// [v2]\l\ +// \l\ +// OUT: [v2]\l\ +// "]; +// Block0_3 -> Block0_3Exit; +// Block0_3Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_3Exit:0 -> Block0_5 [style="solid"]; +// Block0_3Exit:1 -> Block0_4 [style="solid"]; +// Block0_1 [label="\ +// IN: [JUNK, phi0]\l\ +// \l\ +// [JUNK, phi0, lit6]\l\ +// sstore\l\ +// [JUNK]\l\ +// \l\ +// OUT: [JUNK]\l\ +// "]; +// Block0_1Exit [label="MainExit"]; +// Block0_1 -> Block0_1Exit; +// Block0_4 [label="\ +// IN: []\l\ +// \l\ +// OUT: []\l\ +// "]; +// Block0_4 -> Block0_4Exit [arrowhead=none]; +// Block0_4Exit [label="Jump" shape=oval]; +// Block0_4Exit -> Block0_1 [style="solid"]; +// Block0_5 [label="\ +// IN: []\l\ +// \l\ +// [lit2, lit2]\l\ +// sstore\l\ +// []\l\ +// \l\ +// OUT: []\l\ +// "]; +// Block0_5 -> Block0_5Exit [arrowhead=none]; +// Block0_5Exit [label="Jump" shape=oval]; +// Block0_5Exit -> Block0_1 [style="solid"]; +// } From 4b0ced45d4244abc392cfcb3caa6b3f39030dc6e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:53:50 +0100 Subject: [PATCH 1132/1340] fix broken doc links --- docs/060-breaking-changes.rst | 2 +- docs/installing-solidity.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/060-breaking-changes.rst b/docs/060-breaking-changes.rst index c2a6ceb1e..030c59988 100644 --- a/docs/060-breaking-changes.rst +++ b/docs/060-breaking-changes.rst @@ -119,7 +119,7 @@ Metadata Hash Options The compiler now appends the `IPFS `_ hash of the metadata file to the end of the bytecode by default (for details, see documentation on :doc:`contract metadata `). Before 0.6.0, the compiler appended the -`Swarm `_ hash by default, and in order to still support this behavior, +`Swarm `_ hash by default, and in order to still support this behavior, the new command-line option ``--metadata-hash`` was introduced. It allows you to select the hash to be produced and appended, by passing either ``ipfs`` or ``swarm`` as value to the ``--metadata-hash`` command-line option. Passing the value ``none`` completely removes the hash. diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 7e372ea4e..a3a50a56e 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -142,7 +142,7 @@ available for some distributions: Exercise caution when using them. There is also a `snap package `_, however, it is **currently unmaintained**. -It is installable in all the `supported Linux distros `_. To +It is installable in all the `supported Linux distros `_. To install the latest stable version of solc: .. code-block:: bash From ffd11b3cf15118c5f99699eed497a12178165fb7 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 12 Feb 2026 15:20:02 +0100 Subject: [PATCH 1133/1340] Test cases --- .../args | 1 + .../input.sol | 15 ++ .../output | 214 ++++++++++++++++++ ...fter_inherited_storage_same_value_type.sol | 26 +++ ...storage_mapping_delete_same_value_type.sol | 23 ++ ..._storage_struct_delete_same_value_type.sol | 28 +++ ...fore_inherited_storage_same_value_type.sol | 26 +++ ...storage_mapping_delete_same_value_type.sol | 23 ++ ..._storage_struct_delete_same_value_type.sol | 28 +++ ...storage_bool_array_transient_uint256_1.sol | 26 +++ ...storage_bool_array_transient_uint256_2.sol | 26 +++ .../delete_storage_u256_transient_u256_1.sol | 22 ++ .../delete_storage_u256_transient_u256_2.sol | 22 ++ 13 files changed, 480 insertions(+) create mode 100644 test/cmdlineTests/storage_transient_storage_collision_ir_output/args create mode 100644 test/cmdlineTests/storage_transient_storage_collision_ir_output/input.sol create mode 100644 test/cmdlineTests/storage_transient_storage_collision_ir_output/output create mode 100644 test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_inherited_storage_same_value_type.sol create mode 100644 test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_mapping_delete_same_value_type.sol create mode 100644 test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol create mode 100644 test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_inherited_storage_same_value_type.sol create mode 100644 test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_mapping_delete_same_value_type.sol create mode 100644 test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol create mode 100644 test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_1.sol create mode 100644 test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_2.sol create mode 100644 test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_1.sol create mode 100644 test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_2.sol diff --git a/test/cmdlineTests/storage_transient_storage_collision_ir_output/args b/test/cmdlineTests/storage_transient_storage_collision_ir_output/args new file mode 100644 index 000000000..b7ec904f1 --- /dev/null +++ b/test/cmdlineTests/storage_transient_storage_collision_ir_output/args @@ -0,0 +1 @@ +--ir-optimized --evm-version cancun --debug-info none diff --git a/test/cmdlineTests/storage_transient_storage_collision_ir_output/input.sol b/test/cmdlineTests/storage_transient_storage_collision_ir_output/input.sol new file mode 100644 index 000000000..e7d393015 --- /dev/null +++ b/test/cmdlineTests/storage_transient_storage_collision_ir_output/input.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + uint256 transient varTransient; + uint256 public varStorage = 0xeeeeeeeeee; + + function foo() external returns (uint256) { + varTransient = 0xffffffff; + delete varTransient; + delete varStorage; + + return varStorage; + } +} diff --git a/test/cmdlineTests/storage_transient_storage_collision_ir_output/output b/test/cmdlineTests/storage_transient_storage_collision_ir_output/output new file mode 100644 index 000000000..e3a251b2d --- /dev/null +++ b/test/cmdlineTests/storage_transient_storage_collision_ir_output/output @@ -0,0 +1,214 @@ +Optimized IR: +/// @use-src 0:"input.sol" +object "C_25" { + code { + { + mstore(64, memoryguard(0x80)) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + constructor_C() + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_25_deployed"), datasize("C_25_deployed")) + return(_1, datasize("C_25_deployed")) + } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function shift_left(value) -> newValue + { newValue := shl(0, value) } + function update_byte_slice_shift(value, toInsert) -> result + { + let mask := not(0) + toInsert := shift_left(toInsert) + value := and(value, not(mask)) + result := or(value, and(toInsert, mask)) + } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function prepare_store_uint256(value) -> ret + { ret := value } + function update_storage_value_offset_rational_by_to_uint256(slot, value) + { + let convertedValue := convert_rational_by_to_uint256(value) + sstore(slot, update_byte_slice_shift(sload(slot), prepare_store_uint256(convertedValue))) + } + function constructor_C() + { + let expr := 0xeeeeeeeeee + update_storage_value_offset_rational_by_to_uint256(0x00, expr) + } + } + /// @use-src 0:"input.sol" + object "C_25_deployed" { + code { + { + mstore(64, memoryguard(0x80)) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + switch selector + case 0xc2985578 { external_fun_foo() } + case 0xff2558ff { external_fun_varStorage() } + default { } + } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { newValue := shr(224, value) } + function allocate_unbounded() -> memPtr + { memPtr := mload(64) } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function abi_decode(headStart, dataEnd) + { + if slt(sub(dataEnd, headStart), 0) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + } + function cleanup_uint256(value) -> cleaned + { cleaned := value } + function abi_encode_uint256_to_uint256(value, pos) + { + mstore(pos, cleanup_uint256(value)) + } + function abi_encode_uint256(headStart, value0) -> tail + { + tail := add(headStart, 32) + abi_encode_uint256_to_uint256(value0, add(headStart, 0)) + } + function external_fun_foo() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + abi_decode(4, calldatasize()) + let ret := fun_foo() + let memPos := allocate_unbounded() + let memEnd := abi_encode_uint256(memPos, ret) + return(memPos, sub(memEnd, memPos)) + } + function shift_right_unsigned_dynamic(bits, value) -> newValue + { newValue := shr(bits, value) } + function cleanup_from_storage_uint256(value) -> cleaned + { cleaned := value } + function extract_from_storage_value_dynamict_uint256(slot_value, offset) -> value + { + value := cleanup_from_storage_uint256(shift_right_unsigned_dynamic(mul(offset, 8), slot_value)) + } + function read_from_storage_split_dynamic_uint256(slot, offset) -> value + { + value := extract_from_storage_value_dynamict_uint256(sload(slot), offset) + } + function getter_fun_varStorage() -> ret + { + let slot := 0 + let offset := 0 + ret := read_from_storage_split_dynamic_uint256(slot, offset) + } + function external_fun_varStorage() + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + abi_decode(4, calldatasize()) + let ret := getter_fun_varStorage() + let memPos := allocate_unbounded() + let memEnd := abi_encode_uint256(memPos, ret) + return(memPos, sub(memEnd, memPos)) + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + function zero_value_for_split_uint256() -> ret + { ret := 0 } + function cleanup_rational_by(value) -> cleaned + { cleaned := value } + function identity(value) -> ret + { ret := value } + function convert_rational_by_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_rational_by(value))) + } + function shift_left(value) -> newValue + { newValue := shl(0, value) } + function update_byte_slice_shift(value, toInsert) -> result + { + let mask := not(0) + toInsert := shift_left(toInsert) + value := and(value, not(mask)) + result := or(value, and(toInsert, mask)) + } + function convert_uint256_to_uint256(value) -> converted + { + converted := cleanup_uint256(identity(cleanup_uint256(value))) + } + function prepare_store_uint256(value) -> ret + { ret := value } + function update_transient_storage_value_offset_uint256_to_uint256(slot, value) + { + let convertedValue := convert_uint256_to_uint256(value) + tstore(slot, update_byte_slice_shift(tload(slot), prepare_store_uint256(convertedValue))) + } + function shift_left_dynamic(bits, value) -> newValue + { newValue := shl(bits, value) } + function update_byte_slice_dynamic32(value, shiftBytes, toInsert) -> result + { + let shiftBits := mul(shiftBytes, 8) + let mask := shift_left_dynamic(shiftBits, not(0)) + toInsert := shift_left_dynamic(shiftBits, toInsert) + value := and(value, not(mask)) + result := or(value, and(toInsert, mask)) + } + function update_transient_storage_value_uint256_to_uint256(slot, offset, value) + { + let convertedValue := convert_uint256_to_uint256(value) + tstore(slot, update_byte_slice_dynamic32(tload(slot), offset, prepare_store_uint256(convertedValue))) + } + function storage_set_to_zero_uint256(slot, offset) + { + let zero := zero_value_for_split_uint256() + update_transient_storage_value_uint256_to_uint256(slot, offset, zero) + } + function shift_right_0_unsigned(value) -> newValue + { newValue := shr(0, value) } + function extract_from_storage_value_offset_uint256(slot_value) -> value + { + value := cleanup_from_storage_uint256(shift_right_0_unsigned(slot_value)) + } + function read_from_storage_split_offset_uint256(slot) -> value + { + value := extract_from_storage_value_offset_uint256(sload(slot)) + } + function fun_foo() -> var + { + let zero_uint256 := zero_value_for_split_uint256() + var := zero_uint256 + let expr := 0xffffffff + let _1 := convert_rational_by_to_uint256(expr) + update_transient_storage_value_offset_uint256_to_uint256(0x00, _1) + storage_set_to_zero_uint256(0x00, 0) + storage_set_to_zero_uint256(0x00, 0) + let _2 := read_from_storage_split_offset_uint256(0x00) + let expr_1 := _2 + var := expr_1 + leave + } + } + data ".metadata" hex"" + } +} diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_inherited_storage_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_inherited_storage_same_value_type.sol new file mode 100644 index 000000000..f4badbc98 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_inherited_storage_same_value_type.sol @@ -0,0 +1,26 @@ +contract Base { + uint256 public x; + + function deleteX() internal { + delete x; + } +} + +contract C is Base { + uint256 transient t; + + function setAndClear() external { + x = 1; + t = 2; + deleteX(); + delete t; + assert(t == 0); + } +} + +// ==== +// EVMVersion: >=cancun +// compileViaYul: true +// ---- +// setAndClear() -> +// x() -> 1 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_mapping_delete_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_mapping_delete_same_value_type.sol new file mode 100644 index 000000000..b1a388321 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_mapping_delete_same_value_type.sol @@ -0,0 +1,23 @@ +contract C { + mapping(uint256 => uint256) m; + uint256 transient t; + + function setAndClear() external { + m[0] = 1; + t = 2; + delete m[0]; + delete t; + assert(t == 2); + } + + function getM() external view returns (uint256) { + return m[0]; + } +} + +// ==== +// EVMVersion: >=cancun +// compileViaYul: true +// ---- +// setAndClear() -> +// getM() -> 0 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol new file mode 100644 index 000000000..33a0dc2de --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol @@ -0,0 +1,28 @@ +contract C { + struct S { + uint256 a; + address b; + } + + S s; + uint256 transient t; + + function setAndDelete() external { + s.a = 1; + s.b = address(0x1234); + t = 2; + delete s; + delete t; + assert(t == 2); + } + + function getS() external view returns (uint256, address) { + return (s.a, s.b); + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: true +// ---- +// setAndDelete() -> +// getS() -> 0, 0 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_inherited_storage_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_inherited_storage_same_value_type.sol new file mode 100644 index 000000000..8e40422a9 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_inherited_storage_same_value_type.sol @@ -0,0 +1,26 @@ +contract Base { + uint256 public x; + + function deleteX() internal { + delete x; + } +} + +contract C is Base { + uint256 transient t; + + function setAndClear() external { + x = 1; + t = 2; + delete t; + assert(t == 0); + deleteX(); + } +} + +// ==== +// EVMVersion: >=cancun +// compileViaYul: true +// ---- +// setAndClear() -> +// x() -> 1 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_mapping_delete_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_mapping_delete_same_value_type.sol new file mode 100644 index 000000000..129fafad7 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_mapping_delete_same_value_type.sol @@ -0,0 +1,23 @@ +contract C { + mapping(uint256 => uint256) m; + uint256 transient t; + + function setAndClear() external { + m[0] = 1; + t = 2; + delete t; + assert(t == 0); + delete m[0]; + } + + function getM() external view returns (uint256) { + return m[0]; + } +} + +// ==== +// EVMVersion: >=cancun +// compileViaYul: true +// ---- +// setAndClear() -> +// getM() -> 1 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol new file mode 100644 index 000000000..d499d0618 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol @@ -0,0 +1,28 @@ +contract C { + struct S { + uint256 a; + address b; + } + + S s; + uint256 transient t; + + function setAndDelete() external { + s.a = 1; + s.b = address(0x1234); + t = 2; + delete t; + assert(t == 0); + delete s; + } + + function getS() external view returns (uint256, address) { + return (s.a, s.b); + } +} +// ==== +// EVMVersion: >=cancun +// compileViaYul: true +// ---- +// setAndDelete() -> +// getS() -> 1, 0 diff --git a/test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_1.sol b/test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_1.sol new file mode 100644 index 000000000..4d84b23f7 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_1.sol @@ -0,0 +1,26 @@ +pragma solidity >=0.0; + +contract C { + bool[3] flags = [true, true, true]; + uint256 transient temp; + + function f() external { + temp = 0xffffffff; + assert(temp == 0xffffffff); + delete temp; + delete flags; + } + + function getFlags() external returns(bool[3] memory) + { + return flags; + } +} + +// ==== +// EVMVersion: >=cancun +// compileViaYul: true +// ---- +// getFlags() -> true, true, true +// f() -> +// getFlags() -> true, true, true diff --git a/test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_2.sol b/test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_2.sol new file mode 100644 index 000000000..f95b191c1 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_2.sol @@ -0,0 +1,26 @@ +pragma solidity >=0.0; + +contract C { + bool[3] flags = [true, true, true]; + uint256 transient temp; + + function f() external { + temp = 0xffffffff; + assert(temp == 0xffffffff); + delete flags; + delete temp; + } + + function getFlags() external returns(bool[3] memory) + { + return flags; + } +} + +// ==== +// EVMVersion: >=cancun +// compileViaYul: true +// ---- +// getFlags() -> true, true, true +// f() -> +// getFlags() -> false, false, false diff --git a/test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_1.sol b/test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_1.sol new file mode 100644 index 000000000..08f8120be --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_1.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + uint256 transient varTransient; + uint256 public varStorage = 0xeeeeeeeeee; + + function foo() external { + varTransient = 0xffffffff; + assert(varTransient == 0xffffffff); + delete varTransient; + delete varStorage; + } +} + +// ==== +// EVMVersion: >=cancun +// compileViaYul: true +// ---- +// varStorage() -> 0xeeeeeeeeee +// foo() -> +// varStorage() -> 0xeeeeeeeeee diff --git a/test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_2.sol b/test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_2.sol new file mode 100644 index 000000000..03e06747a --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_2.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + uint256 transient varTransient; + uint256 public varStorage = 0xeeeeeeeeee; + + function foo() external { + varTransient = 0xffffffff; + assert(varTransient == 0xffffffff); + delete varStorage; + delete varTransient; + } +} + +// ==== +// EVMVersion: >=cancun +// compileViaYul: true +// ---- +// varStorage() -> 0xeeeeeeeeee +// foo() -> +// varStorage() -> 0 From 580a72900dab63e14be7d171cf88f5cfce4d52a0 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 12 Feb 2026 15:20:49 +0100 Subject: [PATCH 1134/1340] Changelog --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index d1bc022e3..9bf32bf25 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,8 @@ ### 0.8.34 (unreleased) +Important Bugfixes: +* Yul IR Code Generation: Fix a bug that could result in clearing a storage variable instead of a transient storage variable at the same position in the layout (and vice-versa). + Language Features: Compiler Features: From 12ede4f2650038b7f4c38ed1ef52b5d2da7d2dda Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 12 Feb 2026 15:22:09 +0100 Subject: [PATCH 1135/1340] Fix transient/storage collision when deleting --- libsolidity/codegen/YulUtilFunctions.cpp | 17 ++++++++++- .../output | 14 +++++++-- ...fter_inherited_storage_same_value_type.sol | 3 +- ...rage_array_delete_different_base_type.sol} | 9 ++---- ...after_storage_array_pop_same_base_type.sol | 30 +++++++++++++++++++ ..._after_storage_delete_same_value_type.sol} | 10 ++----- ...storage_mapping_delete_same_value_type.sol | 3 +- ..._storage_struct_delete_same_value_type.sol | 8 ++--- ...fore_inherited_storage_same_value_type.sol | 3 +- ...rage_array_delete_different_base_type.sol} | 11 +++---- ...rray_partial_assignment_same_base_type.sol | 27 +++++++++++++++++ ...before_storage_delete_same_value_type.sol} | 12 +++----- ...storage_mapping_delete_same_value_type.sol | 3 +- ..._storage_struct_delete_same_value_type.sol | 8 ++--- 14 files changed, 109 insertions(+), 49 deletions(-) rename test/libsolidity/semanticTests/storage/{delete_storage_bool_array_transient_uint256_2.sol => delete_overlapping_transient_after_storage_array_delete_different_base_type.sol} (75%) create mode 100644 test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_array_pop_same_base_type.sol rename test/libsolidity/semanticTests/storage/{delete_storage_u256_transient_u256_2.sol => delete_overlapping_transient_after_storage_delete_same_value_type.sol} (63%) rename test/libsolidity/semanticTests/storage/{delete_storage_bool_array_transient_uint256_1.sol => delete_overlapping_transient_before_storage_array_delete_different_base_type.sol} (67%) create mode 100644 test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_array_partial_assignment_same_base_type.sol rename test/libsolidity/semanticTests/storage/{delete_storage_u256_transient_u256_1.sol => delete_overlapping_transient_before_storage_delete_same_value_type.sol} (57%) diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 4c0a70269..bb18217f2 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -4357,7 +4357,22 @@ std::string YulUtilFunctions::zeroValueFunction(Type const& _type, bool _splitFu std::string YulUtilFunctions::storageSetToZeroFunction(Type const& _type, VariableDeclaration::Location _location) { - std::string const functionName = "storage_set_to_zero_" + _type.identifier(); + solAssert( + _location == VariableDeclaration::Location::Transient || + _location == VariableDeclaration::Location::Unspecified, + "Invalid location for the storage_set_to_zero function" + ); + + if (dynamic_cast(&_type)) + solAssert( + _location == VariableDeclaration::Location::Unspecified && + _type.dataStoredIn(DataLocation::Storage) + ); + + std::string const functionName = + (_location == VariableDeclaration::Location::Transient ? "transient_"s : "") + + "storage_set_to_zero_" + + _type.identifier(); return m_functionCollector.createFunction(functionName, [&]() { if (_type.isValueType()) diff --git a/test/cmdlineTests/storage_transient_storage_collision_ir_output/output b/test/cmdlineTests/storage_transient_storage_collision_ir_output/output index e3a251b2d..dd8abeb33 100644 --- a/test/cmdlineTests/storage_transient_storage_collision_ir_output/output +++ b/test/cmdlineTests/storage_transient_storage_collision_ir_output/output @@ -179,11 +179,21 @@ object "C_25" { let convertedValue := convert_uint256_to_uint256(value) tstore(slot, update_byte_slice_dynamic32(tload(slot), offset, prepare_store_uint256(convertedValue))) } - function storage_set_to_zero_uint256(slot, offset) + function transient_storage_set_to_zero_uint256(slot, offset) { let zero := zero_value_for_split_uint256() update_transient_storage_value_uint256_to_uint256(slot, offset, zero) } + function update_storage_value_uint256_to_uint256(slot, offset, value) + { + let convertedValue := convert_uint256_to_uint256(value) + sstore(slot, update_byte_slice_dynamic32(sload(slot), offset, prepare_store_uint256(convertedValue))) + } + function storage_set_to_zero_uint256(slot, offset) + { + let zero := zero_value_for_split_uint256() + update_storage_value_uint256_to_uint256(slot, offset, zero) + } function shift_right_0_unsigned(value) -> newValue { newValue := shr(0, value) } function extract_from_storage_value_offset_uint256(slot_value) -> value @@ -201,7 +211,7 @@ object "C_25" { let expr := 0xffffffff let _1 := convert_rational_by_to_uint256(expr) update_transient_storage_value_offset_uint256_to_uint256(0x00, _1) - storage_set_to_zero_uint256(0x00, 0) + transient_storage_set_to_zero_uint256(0x00, 0) storage_set_to_zero_uint256(0x00, 0) let _2 := read_from_storage_split_offset_uint256(0x00) let expr_1 := _2 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_inherited_storage_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_inherited_storage_same_value_type.sol index f4badbc98..dae46cd32 100644 --- a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_inherited_storage_same_value_type.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_inherited_storage_same_value_type.sol @@ -20,7 +20,6 @@ contract C is Base { // ==== // EVMVersion: >=cancun -// compileViaYul: true // ---- // setAndClear() -> -// x() -> 1 +// x() -> 0 diff --git a/test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_2.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_array_delete_different_base_type.sol similarity index 75% rename from test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_2.sol rename to test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_array_delete_different_base_type.sol index f95b191c1..d9a904f3c 100644 --- a/test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_2.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_array_delete_different_base_type.sol @@ -1,14 +1,12 @@ -pragma solidity >=0.0; - contract C { bool[3] flags = [true, true, true]; uint256 transient temp; - function f() external { + function setAndClear() external { temp = 0xffffffff; - assert(temp == 0xffffffff); delete flags; delete temp; + assert(temp == 0); } function getFlags() external returns(bool[3] memory) @@ -19,8 +17,7 @@ contract C { // ==== // EVMVersion: >=cancun -// compileViaYul: true // ---- // getFlags() -> true, true, true -// f() -> +// setAndClear() -> // getFlags() -> false, false, false diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_array_pop_same_base_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_array_pop_same_base_type.sol new file mode 100644 index 000000000..76dc10c43 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_array_pop_same_base_type.sol @@ -0,0 +1,30 @@ +contract C { + uint256[] arr; + uint256 transient t; + + function pushArr() external { + arr.push(1); + } + + function setAndClear() external { + t = 2; + delete t; + assert(t == 0); + arr.pop(); + } + + // Get value at index 0, which should have been cleared after arr.pop() + function getArr() external returns (uint256 value) { + assembly { + mstore(0, arr.slot) + value := sload(keccak256(0x00, 0x20)) + } + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// pushArr() -> +// getArr() -> 1 +// setAndClear() -> +// getArr() -> 0 diff --git a/test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_2.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_delete_same_value_type.sol similarity index 63% rename from test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_2.sol rename to test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_delete_same_value_type.sol index 03e06747a..ad206c6ee 100644 --- a/test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_2.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_delete_same_value_type.sol @@ -1,22 +1,18 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - contract C { uint256 transient varTransient; uint256 public varStorage = 0xeeeeeeeeee; - function foo() external { + function setAndClear() external { varTransient = 0xffffffff; - assert(varTransient == 0xffffffff); delete varStorage; delete varTransient; + assert(varTransient == 0); } } // ==== // EVMVersion: >=cancun -// compileViaYul: true // ---- // varStorage() -> 0xeeeeeeeeee -// foo() -> +// setAndClear() -> // varStorage() -> 0 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_mapping_delete_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_mapping_delete_same_value_type.sol index b1a388321..842cd4750 100644 --- a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_mapping_delete_same_value_type.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_mapping_delete_same_value_type.sol @@ -7,7 +7,7 @@ contract C { t = 2; delete m[0]; delete t; - assert(t == 2); + assert(t == 0); } function getM() external view returns (uint256) { @@ -17,7 +17,6 @@ contract C { // ==== // EVMVersion: >=cancun -// compileViaYul: true // ---- // setAndClear() -> // getM() -> 0 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol index 33a0dc2de..703816296 100644 --- a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol @@ -4,16 +4,14 @@ contract C { address b; } - S s; + S s = S(1, address(0x1234)); uint256 transient t; function setAndDelete() external { - s.a = 1; - s.b = address(0x1234); t = 2; delete s; delete t; - assert(t == 2); + assert(t == 0); } function getS() external view returns (uint256, address) { @@ -22,7 +20,7 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: true // ---- +// getS() -> 1, 4660 // setAndDelete() -> // getS() -> 0, 0 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_inherited_storage_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_inherited_storage_same_value_type.sol index 8e40422a9..3af1b66e5 100644 --- a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_inherited_storage_same_value_type.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_inherited_storage_same_value_type.sol @@ -20,7 +20,6 @@ contract C is Base { // ==== // EVMVersion: >=cancun -// compileViaYul: true // ---- // setAndClear() -> -// x() -> 1 +// x() -> 0 diff --git a/test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_1.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_array_delete_different_base_type.sol similarity index 67% rename from test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_1.sol rename to test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_array_delete_different_base_type.sol index 4d84b23f7..c2e1c1a24 100644 --- a/test/libsolidity/semanticTests/storage/delete_storage_bool_array_transient_uint256_1.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_array_delete_different_base_type.sol @@ -1,13 +1,11 @@ -pragma solidity >=0.0; - contract C { bool[3] flags = [true, true, true]; uint256 transient temp; - function f() external { + function setAndClear() external { temp = 0xffffffff; - assert(temp == 0xffffffff); delete temp; + assert(temp == 0); delete flags; } @@ -19,8 +17,7 @@ contract C { // ==== // EVMVersion: >=cancun -// compileViaYul: true // ---- // getFlags() -> true, true, true -// f() -> -// getFlags() -> true, true, true +// setAndClear() -> +// getFlags() -> false, false, false diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_array_partial_assignment_same_base_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_array_partial_assignment_same_base_type.sol new file mode 100644 index 000000000..a9d3e0ae7 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_array_partial_assignment_same_base_type.sol @@ -0,0 +1,27 @@ +contract C { + uint256[2] small; + uint256[4] large; + uint256 transient t; + + function setAndClear() external { + large = [1,2,3,4]; + small = [10, 20]; + t = 99; + + delete t; + assert(t == 0); + large = small; + } + + function getLarge() external view returns (uint256[4] memory) { + return large; + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// setAndClear() -> +// gas irOptimized: 124683 +// gas legacy: 127807 +// gas legacyOptimized: 124828 +// getLarge() -> 10, 20, 0, 0 diff --git a/test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_1.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_delete_same_value_type.sol similarity index 57% rename from test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_1.sol rename to test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_delete_same_value_type.sol index 08f8120be..26e34fc26 100644 --- a/test/libsolidity/semanticTests/storage/delete_storage_u256_transient_u256_1.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_delete_same_value_type.sol @@ -1,22 +1,18 @@ -// SPDX-License-Identifier: GPL-2.0 -pragma solidity >=0.0; - contract C { uint256 transient varTransient; uint256 public varStorage = 0xeeeeeeeeee; - function foo() external { + function setAndClear() external { varTransient = 0xffffffff; - assert(varTransient == 0xffffffff); delete varTransient; + assert(varTransient == 0); delete varStorage; } } // ==== // EVMVersion: >=cancun -// compileViaYul: true // ---- // varStorage() -> 0xeeeeeeeeee -// foo() -> -// varStorage() -> 0xeeeeeeeeee +// setAndClear() -> +// varStorage() -> 0 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_mapping_delete_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_mapping_delete_same_value_type.sol index 129fafad7..6e262c8a6 100644 --- a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_mapping_delete_same_value_type.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_mapping_delete_same_value_type.sol @@ -17,7 +17,6 @@ contract C { // ==== // EVMVersion: >=cancun -// compileViaYul: true // ---- // setAndClear() -> -// getM() -> 1 +// getM() -> 0 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol index d499d0618..c2127c9ba 100644 --- a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol @@ -4,12 +4,10 @@ contract C { address b; } - S s; + S s = S(1, address(0x1234)); uint256 transient t; function setAndDelete() external { - s.a = 1; - s.b = address(0x1234); t = 2; delete t; assert(t == 0); @@ -22,7 +20,7 @@ contract C { } // ==== // EVMVersion: >=cancun -// compileViaYul: true // ---- +// getS() -> 1, 4660 // setAndDelete() -> -// getS() -> 1, 0 +// getS() -> 0, 0 From 57e789309840a528eb868a6de25f56f27c52820e Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 13 Feb 2026 11:10:47 +0100 Subject: [PATCH 1136/1340] Bug list entry --- docs/bugs.json | 14 ++++++++++++++ docs/bugs_by_version.json | 12 ++++++++++-- ...after_storage_struct_delete_same_value_type.sol | 2 +- ...efore_storage_struct_delete_same_value_type.sol | 2 +- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/docs/bugs.json b/docs/bugs.json index 0c0b0493d..5f8d1a162 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -1,4 +1,18 @@ [ + { + "uid": "SOL-2026-1", + "name": "TransientStorageClearingHelperCollision", + "summary": "Clearing both storage and transient storage variables in the same contract may result in only one of these locations being cleared.", + "description": "The IR-based code generator provides a set of Yul helper functions for basic operations, such as clearing, copying, encoding or type conversions. Not all functions are used by every contract. The codegen appends them to the generated sources individually, only when an operation that would invoke one of them is encountered. Utility functions are often specialized for different types and locations. Since Yul does not support generic functions, specialization is done by generating multiple versions of the same function, with the information distinguishing the variants embedded in their names. However, if not all the necessary bits of distinguishing information are properly accounted for, two helpers may end up with the same name, causing a collision. In this situation the codegen includes only one of them, with calls to both variants invoking it. This happened with the ``set_to_zero`` helper used when an area of transient or persistent storage needs to be cleared. The helper name was missing the location information, which resulted in a collision between the persistent and transient storage variants for the same type. This meant that contracts clearing both locations would actually clear only one, leaving the other untouched. Which location ended up being cleared depended on the order in which the code generator processed the input. The necessary condition to trigger the bug was the use of ``delete`` operator on a transient storage variable. This was due to value types being the only types supported in transient storage and ``delete`` being the only operation invoking the helper allowed on such types. The other necessary condition was clearing of persistent storage and in this case the range of affected operations was wider: operator ``delete``, array ``pop()`` or assignment that resulted in a longer array being overwritten with a shorter one. The cleared variable itself also did not necessarily have to be of the same type. It was enough that a matching value type was nested in it. It also did not always have to be the exact same value type - clearing operations on reference types are usually performed at slot granularity, treating every slot as ``uint256`` rather than clearing every value packed into it individually. To trigger the bug both operations had to be present within the same piece of bytecode. Independent contracts, not related through inheritance, would not affect each other this way. The presence of one operation only in creation code and the other only in deployed code would not trigger the bug either.", + "link": "https://blog.soliditylang.org/2026/02/18/transient-storage-clearing-helper-collision-bug/", + "introduced": "0.8.28", + "fixed": "0.8.34", + "severity": "high", + "conditions": { + "viaIR": true, + "evmVersion": ">=cancun" + } + }, { "uid": "SOL-2025-1", "name": "LostStorageArrayWriteOnSlotOverflow", diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 8a4d2fe23..c76c6e7c1 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -2013,12 +2013,14 @@ }, "0.8.28": { "bugs": [ + "TransientStorageClearingHelperCollision", "LostStorageArrayWriteOnSlotOverflow" ], "released": "2024-10-09" }, "0.8.29": { "bugs": [ + "TransientStorageClearingHelperCollision", "LostStorageArrayWriteOnSlotOverflow" ], "released": "2025-03-12" @@ -2039,22 +2041,28 @@ }, "0.8.30": { "bugs": [ + "TransientStorageClearingHelperCollision", "LostStorageArrayWriteOnSlotOverflow" ], "released": "2025-05-07" }, "0.8.31": { "bugs": [ + "TransientStorageClearingHelperCollision", "LostStorageArrayWriteOnSlotOverflow" ], "released": "2025-12-03" }, "0.8.32": { - "bugs": [], + "bugs": [ + "TransientStorageClearingHelperCollision" + ], "released": "2025-12-18" }, "0.8.33": { - "bugs": [], + "bugs": [ + "TransientStorageClearingHelperCollision" + ], "released": "2025-12-18" }, "0.8.4": { diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol index 703816296..04b8d47cf 100644 --- a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol @@ -21,6 +21,6 @@ contract C { // ==== // EVMVersion: >=cancun // ---- -// getS() -> 1, 4660 +// getS() -> 1, 0x1234 // setAndDelete() -> // getS() -> 0, 0 diff --git a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol index c2127c9ba..1c9cc4965 100644 --- a/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol +++ b/test/libsolidity/semanticTests/storage/delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol @@ -21,6 +21,6 @@ contract C { // ==== // EVMVersion: >=cancun // ---- -// getS() -> 1, 4660 +// getS() -> 1, 0x1234 // setAndDelete() -> // getS() -> 0, 0 From e958997006159edca53cd25d6cbd2bc8869b0acd Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 18 Feb 2026 09:45:19 +0100 Subject: [PATCH 1137/1340] Changelog for 0.8.34 --- Changelog.md | 5 +---- docs/bugs_by_version.json | 4 ++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index 9bf32bf25..e4b13172c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,15 +1,12 @@ -### 0.8.34 (unreleased) +### 0.8.34 (2026-02-18) Important Bugfixes: * Yul IR Code Generation: Fix a bug that could result in clearing a storage variable instead of a transient storage variable at the same position in the layout (and vice-versa). -Language Features: Compiler Features: * Yul Optimizer: Remove redundant prerequisite steps from the default optimizer sequence. -Bugfixes: - ### 0.8.33 (2025-12-18) diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index c76c6e7c1..c5576d4b2 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -2065,6 +2065,10 @@ ], "released": "2025-12-18" }, + "0.8.34": { + "bugs": [], + "released": "2026-02-18" + }, "0.8.4": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", From 6a8f003a8da7a7142d9ec6a8595a95d6897b891d Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 18 Feb 2026 13:38:11 +0100 Subject: [PATCH 1138/1340] Set version to 0.8.35 --- CMakeLists.txt | 2 +- Changelog.md | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82afc5b67..410acd86f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.34") +set(PROJECT_VERSION "0.8.35") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index e4b13172c..f6e4733f6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,12 @@ +### 0.8.35 (unreleased) + +Language Features: + +Compiler Features: + +Bugfixes: + + ### 0.8.34 (2026-02-18) Important Bugfixes: From 98f84a78dc7e212b365944a0fed4a99a66c503c6 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 17 Feb 2026 18:00:32 +0100 Subject: [PATCH 1139/1340] update docker image of scripts/build_emscripten.sh the newer image contains ccache --- scripts/build_emscripten.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index aae4b5c1f..e6e8c0a0d 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -33,9 +33,9 @@ if (( $# != 0 )); then params="$(printf "%q " "${@}")" fi -# ghcr.io/argotorg/solidity-buildpack-deps:emscripten-21 +# ghcr.io/argotorg/solidity-buildpack-deps:emscripten-22 # NOTE: Without `safe.directory` git would assume it's not safe to operate on /root/project since it's owned by a different user. # See https://github.blog/2022-04-12-git-security-vulnerability-announced/ docker run -v "$(pwd):/root/project" -w /root/project \ - ghcr.io/argotorg/solidity-buildpack-deps@sha256:fc53d68a4680ffa7d5f70164e13a903478964f15bcc07434d74833a05f4fbc19 \ + ghcr.io/argotorg/solidity-buildpack-deps@sha256:b9c953144d82cca5553f65626bc43b8af456dbc8966f8732ff9522f33ca8d722 \ /bin/bash -c "git config --global --add safe.directory /root/project && ./scripts/ci/build_emscripten.sh ${params}" From 30f20186f642439ee6e491eb608061ab4ad43dfc Mon Sep 17 00:00:00 2001 From: Olexandr88 Date: Thu, 19 Feb 2026 16:38:07 +0200 Subject: [PATCH 1140/1340] optimiser: avoid double lookup in translateIdentifier (#16468) * optimiser: avoid double lookup in translateIdentifier Signed-off-by: Olexandr88 * Update libyul/optimiser/ASTCopier.cpp Co-authored-by: clonker <1685266+clonker@users.noreply.github.com> --------- Signed-off-by: Olexandr88 Co-authored-by: clonker <1685266+clonker@users.noreply.github.com> --- libyul/optimiser/ASTCopier.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libyul/optimiser/ASTCopier.cpp b/libyul/optimiser/ASTCopier.cpp index 9e85651ad..2a913f8f9 100644 --- a/libyul/optimiser/ASTCopier.cpp +++ b/libyul/optimiser/ASTCopier.cpp @@ -180,7 +180,5 @@ NameWithDebugData ASTCopier::translate(NameWithDebugData const& _typedName) YulName FunctionCopier::translateIdentifier(YulName _name) { - if (m_translations.count(_name)) - return m_translations.at(_name); - return _name; + return util::valueOrDefault(m_translations, _name, _name); } From e050973fa5eaf3b8c9be71432abfec95f4f67473 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 24 Feb 2026 10:53:00 +0100 Subject: [PATCH 1141/1340] Remove jump tables from SSA CFG --- libyul/backends/evm/ssa/LivenessAnalysis.cpp | 5 - libyul/backends/evm/ssa/SSACFG.h | 15 +- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 176 ++++++------------ libyul/backends/evm/ssa/SSACFGBuilder.h | 7 - .../backends/evm/ssa/io/DotExporterBase.cpp | 22 --- libyul/backends/evm/ssa/io/JSONExporter.cpp | 3 - 6 files changed, 60 insertions(+), 168 deletions(-) diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp index d97ff0097..2e93a5f14 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -145,11 +145,6 @@ LivenessAnalysis::LivenessData LivenessAnalysis::blockExitValues(SSACFG::BlockId for (auto const& valueId: _functionReturn.returnValues | ranges::views::filter(excludingLiteralsFilter())) result.insert(valueId); }, - [&](SSACFG::BasicBlock::JumpTable const& _jt) - { - if (excludingLiteralsFilter()(_jt.value)) - result.insert(_jt.value); - }, [](SSACFG::BasicBlock::Jump const&) {}, [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) { diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 49d5a4e94..dcb0a2649 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -135,13 +135,6 @@ class SSACFG langutil::DebugData::ConstPtr debugData{}; BlockId target; }; - struct JumpTable - { - langutil::DebugData::ConstPtr debugData{}; - ValueId value; - std::map cases; - BlockId defaultCase; - }; struct FunctionReturn { langutil::DebugData::ConstPtr debugData{}; @@ -152,7 +145,7 @@ class SSACFG std::set entries; std::set phis; std::vector operations; - std::variant exit = MainExit{}; + std::variant exit = MainExit{}; template void forEachExit(Callable&& _callable) const { @@ -163,12 +156,6 @@ class SSACFG _callable(conditionalJump->nonZero); _callable(conditionalJump->zero); } - else if (auto* jumpTable = std::get_if(&exit)) - { - for (auto _case: jumpTable->cases | ranges::views::values) - _callable(_case); - _callable(jumpTable->defaultCase); - } } bool isMainExitBlock() const diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 59e28b1b8..bc39c74fb 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -139,10 +139,6 @@ SSACFG::ValueId SSACFGBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) if (_condJump.condition == _phi) _condJump.condition = same; }, - [_phi, same](SSACFG::BasicBlock::JumpTable& _jumpTable) { - if (_jumpTable.value == _phi) - _jumpTable.value = same; - }, [](SSACFG::BasicBlock::Jump&) {}, [](SSACFG::BasicBlock::MainExit&) {}, [](SSACFG::BasicBlock::Terminated&) {} @@ -172,7 +168,6 @@ void SSACFGBuilder::cleanUnreachable() _addChild(_jump.zero); _addChild(_jump.nonZero); }, - [](SSACFG::BasicBlock::JumpTable const&) { yulAssert(false); }, [](SSACFG::BasicBlock::FunctionReturn const&) {}, [](SSACFG::BasicBlock::Terminated const&) {}, [](SSACFG::BasicBlock::MainExit const&) {} @@ -312,113 +307,77 @@ void SSACFGBuilder::operator()(Switch const& _switch) { auto expression = std::visit(*this, *_switch.expression); - auto useJumpTableForSwitch = [](Switch const&) { - // TODO: check for EOF support & tight switch values. - return false; - }; - if (useJumpTableForSwitch(_switch)) + if (auto const* constantExpression = std::get_if(_switch.expression.get())) { - // TODO: also generate a subtraction to shift tight, but non-zero switch cases - or, alternative, - // transform to zero-based tight switches on Yul if possible. - std::map cases; - std::optional defaultCase; - std::vector>> children; - for (auto const& _case: _switch.cases) + Case const* matchedCase = nullptr; + // select case that matches (or default if available) + for (auto const& switchCase: _switch.cases) { - auto blockId = m_graph.makeBlock(debugDataOf(_case.body)); - if (_case.value) - cases[_case.value->value.value()] = blockId; - else - defaultCase = blockId; - children.emplace_back(blockId, std::ref(_case.body)); + if (!switchCase.value) + matchedCase = &switchCase; + if (switchCase.value && switchCase.value->value.value() == constantExpression->value.value()) + { + matchedCase = &switchCase; + break; + } } - auto afterSwitch = m_graph.makeBlock(debugDataOf(currentBlock())); - - tableJump(debugDataOf(_switch), expression, cases, defaultCase ? *defaultCase : afterSwitch); - for (auto [blockId, block]: children) + if (matchedCase) { - sealBlock(blockId); - m_currentBlock = blockId; - (*this)(block); - jump(debugDataOf(currentBlock()), afterSwitch); + // inject directly into the current block + (*this)(matchedCase->body); } - sealBlock(afterSwitch); - m_currentBlock = afterSwitch; + return; } - else - { - if (auto const* constantExpression = std::get_if(_switch.expression.get())) - { - Case const* matchedCase = nullptr; - // select case that matches (or default if available) - for (auto const& switchCase: _switch.cases) - { - if (!switchCase.value) - matchedCase = &switchCase; - if (switchCase.value && switchCase.value->value.value() == constantExpression->value.value()) - { - matchedCase = &switchCase; - break; - } - } - if (matchedCase) - { - // inject directly into the current block - (*this)(matchedCase->body); - } - return; - } - - std::optional equalityBuiltinHandle = m_dialect.equalityFunctionHandle(); - yulAssert(equalityBuiltinHandle); - auto makeValueCompare = [&](Case const& _case) { - FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(FunctionCall{ + std::optional equalityBuiltinHandle = m_dialect.equalityFunctionHandle(); + yulAssert(equalityBuiltinHandle); + + auto makeValueCompare = [&](Case const& _case) { + FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(FunctionCall{ + debugDataOf(_case), + BuiltinName{{}, *equalityBuiltinHandle}, + {*_case.value /* skip second argument */ } + }); + auto outputValue = m_graph.newVariable(m_currentBlock); + currentBlock().operations.emplace_back(SSACFG::Operation{ + {outputValue}, + SSACFG::BuiltinCall{ debugDataOf(_case), - BuiltinName{{}, *equalityBuiltinHandle}, - {*_case.value /* skip second argument */ } - }); - auto outputValue = m_graph.newVariable(m_currentBlock); - currentBlock().operations.emplace_back(SSACFG::Operation{ - {outputValue}, - SSACFG::BuiltinCall{ - debugDataOf(_case), - m_dialect.builtin(*equalityBuiltinHandle), - ghostCall - }, - {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression} - }); - return outputValue; - }; + m_dialect.builtin(*equalityBuiltinHandle), + ghostCall + }, + {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression} + }); + return outputValue; + }; - auto afterSwitch = m_graph.makeBlock(debugDataOf(currentBlock())); - yulAssert(!_switch.cases.empty(), ""); - for (auto const& switchCase: _switch.cases | ranges::views::drop_last(1)) - { - yulAssert(switchCase.value, ""); - auto caseBranch = m_graph.makeBlock(debugDataOf(switchCase.body)); - auto elseBranch = m_graph.makeBlock(debugDataOf(_switch)); - - conditionalJump(debugDataOf(switchCase), makeValueCompare(switchCase), caseBranch, elseBranch); - sealBlock(caseBranch); - sealBlock(elseBranch); - m_currentBlock = caseBranch; - (*this)(switchCase.body); - jump(debugDataOf(switchCase.body), afterSwitch); - m_currentBlock = elseBranch; - } - Case const& switchCase = _switch.cases.back(); - if (switchCase.value) - { - auto caseBranch = m_graph.makeBlock(debugDataOf(switchCase.body)); - conditionalJump(debugDataOf(switchCase), makeValueCompare(switchCase), caseBranch, afterSwitch); - sealBlock(caseBranch); - m_currentBlock = caseBranch; - } + auto afterSwitch = m_graph.makeBlock(debugDataOf(currentBlock())); + yulAssert(!_switch.cases.empty(), ""); + for (auto const& switchCase: _switch.cases | ranges::views::drop_last(1)) + { + yulAssert(switchCase.value, ""); + auto caseBranch = m_graph.makeBlock(debugDataOf(switchCase.body)); + auto elseBranch = m_graph.makeBlock(debugDataOf(_switch)); + + conditionalJump(debugDataOf(switchCase), makeValueCompare(switchCase), caseBranch, elseBranch); + sealBlock(caseBranch); + sealBlock(elseBranch); + m_currentBlock = caseBranch; (*this)(switchCase.body); jump(debugDataOf(switchCase.body), afterSwitch); - sealBlock(afterSwitch); + m_currentBlock = elseBranch; } + Case const& switchCase = _switch.cases.back(); + if (switchCase.value) + { + auto caseBranch = m_graph.makeBlock(debugDataOf(switchCase.body)); + conditionalJump(debugDataOf(switchCase), makeValueCompare(switchCase), caseBranch, afterSwitch); + sealBlock(caseBranch); + m_currentBlock = caseBranch; + } + (*this)(switchCase.body); + jump(debugDataOf(switchCase.body), afterSwitch); + sealBlock(afterSwitch); } void SSACFGBuilder::operator()(ForLoop const& _loop) { @@ -756,23 +715,6 @@ void SSACFGBuilder::jump( m_currentBlock = _target; } -void SSACFGBuilder::tableJump( - langutil::DebugData::ConstPtr _debugData, - SSACFG::ValueId _value, - std::map _cases, - SSACFG::BlockId _defaultCase) -{ - for (auto caseBlock: _cases | ranges::views::values) - { - yulAssert(!blockInfo(caseBlock).sealed); - m_graph.block(caseBlock).entries.insert(m_currentBlock); - } - yulAssert(!blockInfo(_defaultCase).sealed); - m_graph.block(_defaultCase).entries.insert(m_currentBlock); - currentBlock().exit = SSACFG::BasicBlock::JumpTable{std::move(_debugData), _value, std::move(_cases), _defaultCase}; - m_currentBlock = {}; -} - FunctionDefinition const* SSACFGBuilder::findFunctionDefinition(Scope::Function const* _function) const { auto it = std::find_if( diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index 7b497db2a..331d8b52f 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -147,13 +147,6 @@ class SSACFGBuilder SSACFG::BlockId _target ); - void tableJump( - langutil::DebugData::ConstPtr _debugData, - SSACFG::ValueId _value, - std::map _cases, - SSACFG::BlockId _defaultCase - ); - FunctionDefinition const* findFunctionDefinition(Scope::Function const* _function) const; }; diff --git a/libyul/backends/evm/ssa/io/DotExporterBase.cpp b/libyul/backends/evm/ssa/io/DotExporterBase.cpp index 23541422a..9a62dcc83 100644 --- a/libyul/backends/evm/ssa/io/DotExporterBase.cpp +++ b/libyul/backends/evm/ssa/io/DotExporterBase.cpp @@ -21,13 +21,9 @@ #include #include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtautological-compare" #include -#pragma GCC diagnostic pop #include -#include using namespace solidity; using namespace solidity::util; @@ -117,24 +113,6 @@ void DotExporterBase::writeBlock(std::ostream& _out, SSACFG::BlockId const _id) _out << formatEdge(_id, _conditionalJump.zero, "0"); _out << formatEdge(_id, _conditionalJump.nonZero, "1"); }, - [&](SSACFG::BasicBlock::JumpTable const& jt) - { - _out << fmt::format("{} -> {}Exit;\n", formatBlockHandle(_id), formatBlockHandle(_id)); - std::string options; - for (auto const& jumpCase: jt.cases) - { - if (!options.empty()) - options += " | "; - options += fmt::format("<{0}> {0}", formatNumber(jumpCase.first)); - } - if (!options.empty()) - options += " | "; - options += " default"; - _out << fmt::format("{}Exit [label=\"{{ JT | {{ {} }} }}\" shape=Mrecord];\n", formatBlockHandle(_id), options); - for (auto const& jumpCase: jt.cases) - _out << formatEdge(_id, jumpCase.second, formatNumber(jumpCase.first)); - _out << formatEdge(_id, jt.defaultCase, "default"); - }, [&](SSACFG::BasicBlock::FunctionReturn const& fr) { auto const valueToString = [&](SSACFG::ValueId const& valueId) { return valueId.str(m_cfg); }; diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index df4e4d814..fdd400d94 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -160,9 +160,6 @@ Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis }, [&](SSACFG::BasicBlock::Terminated const&) { exitBlockJson["type"] = "Terminated"; - }, - [&](SSACFG::BasicBlock::JumpTable const&) { - yulAssert(false); } }, _cfg.block(_blockId).exit); blockJson["exit"] = exitBlockJson; From f04245962572b71ba88fb0310fce8e83e762bd50 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Tue, 24 Feb 2026 18:36:46 +0100 Subject: [PATCH 1142/1340] Fix wrong indices in nested-array-element-storage-to-storage test --- ...ested_array_element_storage_to_storage.sol | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol index 1a3fb70e0..2e3352693 100644 --- a/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol +++ b/test/libsolidity/semanticTests/array/copying/nested_array_element_storage_to_storage.sol @@ -9,7 +9,7 @@ contract C { uint8[][] dst1; uint8[][] dst2; uint8[][2] dst3; - uint8[][] dst4; + uint8[2][] dst4; constructor() { src1[1] = new uint8[][](2); @@ -45,10 +45,10 @@ contract C { dst2 = src2[0]; require(dst2.length == 2); - require(dst2[0][0] == src2[1][0][0]); - require(dst2[0][1] == src2[1][0][1]); - require(dst2[1][0] == src2[1][1][0]); - require(dst2[1][1] == src2[1][1][1]); + require(dst2[0][0] == src2[0][0][0]); + require(dst2[0][1] == src2[0][0][1]); + require(dst2[1][0] == src2[0][1][0]); + require(dst2[1][1] == src2[0][1][1]); } function test3() public { @@ -61,24 +61,22 @@ contract C { function test4() public { dst4 = src4[1]; - require(dst4.length == 2); - require(dst4[0][0] == src4[0][0][0]); - require(dst4[0][1] == src4[0][0][1]); - require(dst4[1][0] == src4[0][1][0]); - require(dst4[1][1] == src4[0][1][1]); + require(dst4.length == 1); + require(dst4[0][0] == src4[1][0][0]); + require(dst4[0][1] == src4[1][0][1]); } } // ---- // test1() -> -// gas irOptimized: 150488 +// gas irOptimized: 150449 // gas legacy: 156275 -// gas legacyOptimized: 151018 -// test2() -> FAILURE -// gas irOptimized: 150389 -// gas legacy: 155998 -// gas legacyOptimized: 150684 +// gas legacyOptimized: 150983 +// test2() -> +// gas irOptimized: 147342 +// gas legacy: 153508 +// gas legacyOptimized: 148067 // test3() -> // gas irOptimized: 124300 // gas legacy: 130649 // gas legacyOptimized: 125142 -// test4() -> FAILURE +// test4() -> From 36b7ff50194ded41d6c104c7b27753886b4c53a7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 24 Feb 2026 15:40:14 +0100 Subject: [PATCH 1143/1340] Use unordered maps for FunctionReferenceResolver --- libyul/FunctionReferenceResolver.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libyul/FunctionReferenceResolver.h b/libyul/FunctionReferenceResolver.h index dcc5f50e5..1f07abe5d 100644 --- a/libyul/FunctionReferenceResolver.h +++ b/libyul/FunctionReferenceResolver.h @@ -20,6 +20,8 @@ #include +#include + namespace solidity::yul { @@ -33,15 +35,15 @@ class FunctionReferenceResolver: private ASTWalker { public: explicit FunctionReferenceResolver(Block const& _ast); - std::map const& references() const { return m_functionReferences; } + std::unordered_map const& references() const { return m_functionReferences; } private: using ASTWalker::operator(); void operator()(FunctionCall const& _functionCall) override; void operator()(Block const& _block) override; - std::map m_functionReferences; - std::vector> m_scopes; + std::unordered_map m_functionReferences; + std::vector> m_scopes; }; From f3cc67d4662b75722556ffc83e5d462956a74afe Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 24 Feb 2026 15:42:02 +0100 Subject: [PATCH 1144/1340] Optimize control flow side effects collector eliminate the make_shared double allocation + atomic refcount per node use unordered map and set over ordered ones --- Changelog.md | 1 + libyul/ControlFlowSideEffectsCollector.cpp | 4 ++-- libyul/ControlFlowSideEffectsCollector.h | 24 +++++++++---------- .../backends/evm/ControlFlowGraphBuilder.cpp | 2 +- libyul/backends/evm/ControlFlowGraphBuilder.h | 6 +++-- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/Changelog.md b/Changelog.md index f6e4733f6..ed752bf35 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,6 +14,7 @@ Important Bugfixes: Compiler Features: +* Yul Optimizer: Improve performance of control flow side effects collector and function references resolver. * Yul Optimizer: Remove redundant prerequisite steps from the default optimizer sequence. diff --git a/libyul/ControlFlowSideEffectsCollector.cpp b/libyul/ControlFlowSideEffectsCollector.cpp index 28089b029..3c4297285 100644 --- a/libyul/ControlFlowSideEffectsCollector.cpp +++ b/libyul/ControlFlowSideEffectsCollector.cpp @@ -162,8 +162,8 @@ void ControlFlowBuilder::newConnectedNode() ControlFlowNode* ControlFlowBuilder::newNode() { - m_nodes.emplace_back(std::make_shared()); - return m_nodes.back().get(); + m_nodes.emplace_back(); + return &m_nodes.back(); } diff --git a/libyul/ControlFlowSideEffectsCollector.h b/libyul/ControlFlowSideEffectsCollector.h index 2ef7a4bfa..6228db2e4 100644 --- a/libyul/ControlFlowSideEffectsCollector.h +++ b/libyul/ControlFlowSideEffectsCollector.h @@ -21,10 +21,10 @@ #include #include -#include -#include -#include +#include #include +#include +#include namespace solidity::yul { @@ -56,7 +56,7 @@ class ControlFlowBuilder: private ASTWalker /// Computes the control-flows of all function defined in the block. /// Assumes the functions are hoisted to the topmost block. explicit ControlFlowBuilder(Block const& _ast); - std::map const& functionFlows() const { return m_functionFlows; } + std::unordered_map const& functionFlows() const { return m_functionFlows; } private: using ASTWalker::operator(); @@ -72,14 +72,14 @@ class ControlFlowBuilder: private ASTWalker void newConnectedNode(); ControlFlowNode* newNode(); - std::vector> m_nodes; + std::deque m_nodes; ControlFlowNode* m_currentNode = nullptr; ControlFlowNode const* m_leave = nullptr; ControlFlowNode const* m_break = nullptr; ControlFlowNode const* m_continue = nullptr; - std::map m_functionFlows; + std::unordered_map m_functionFlows; }; @@ -96,7 +96,7 @@ class ControlFlowSideEffectsCollector Block const& _ast ); - std::map const& functionSideEffects() const + std::unordered_map const& functionSideEffects() const { return m_functionSideEffects; } @@ -124,15 +124,15 @@ class ControlFlowSideEffectsCollector Dialect const& m_dialect; ControlFlowBuilder m_cfgBuilder; /// Function references, but only for calls to user-defined functions. - std::map m_functionReferences; + std::unordered_map m_functionReferences; /// Side effects of user-defined functions, is being constructod. - std::map m_functionSideEffects; + std::unordered_map m_functionSideEffects; /// Control flow nodes still to process, per function. - std::map> m_pendingNodes; + std::unordered_map> m_pendingNodes; /// Control flow nodes already processed, per function. - std::map> m_processedNodes; + std::unordered_map> m_processedNodes; /// Set of reachable function calls nodes in each function (including calls to builtins). - std::map> m_functionCalls; + std::unordered_map> m_functionCalls; }; diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index d9456e4c3..614503e18 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -258,7 +258,7 @@ std::unique_ptr ControlFlowGraphBuilder::build( ControlFlowGraphBuilder::ControlFlowGraphBuilder( CFG& _graph, AsmAnalysisInfo const& _analysisInfo, - std::map const& _functionSideEffects, + std::unordered_map const& _functionSideEffects, Dialect const& _dialect ): m_graph(_graph), diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.h b/libyul/backends/evm/ControlFlowGraphBuilder.h index 4a2aae98c..ba3735365 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.h +++ b/libyul/backends/evm/ControlFlowGraphBuilder.h @@ -23,6 +23,8 @@ #include #include +#include + namespace solidity::yul { @@ -56,7 +58,7 @@ class ControlFlowGraphBuilder ControlFlowGraphBuilder( CFG& _graph, AsmAnalysisInfo const& _analysisInfo, - std::map const& _functionSideEffects, + std::unordered_map const& _functionSideEffects, Dialect const& _dialect ); void registerFunction(FunctionDefinition const& _function); @@ -79,7 +81,7 @@ class ControlFlowGraphBuilder ); CFG& m_graph; AsmAnalysisInfo const& m_info; - std::map const& m_functionSideEffects; + std::unordered_map const& m_functionSideEffects; Dialect const& m_dialect; CFG::BasicBlock* m_currentBlock = nullptr; Scope* m_scope = nullptr; From f481d1c5837d25cb944e3a9c3dacd46f8cdd97f7 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 6 Oct 2025 14:14:05 +0200 Subject: [PATCH 1145/1340] Introduce experimental flag/option --- libsolidity/interface/CompilerStack.cpp | 6 ++ libsolidity/interface/CompilerStack.h | 4 ++ scripts/ASTImportTest.sh | 4 +- solc/CommandLineInterface.cpp | 1 + solc/CommandLineParser.cpp | 68 ++++++++++++++++++ solc/CommandLineParser.h | 3 + .../args | 2 +- .../asm_json_yul_export_evm_asm_import/args | 2 +- test/cmdlineTests/ast_ir/args | 2 +- .../ast_json_import_wrong_evmVersion/args | 2 +- .../eof_unavailable_before_osaka/args | 2 +- .../args | 1 + .../err | 1 + .../exit | 1 + .../input.sol | 6 ++ .../ethdebug_eof_container_osaka/args | 2 +- test/cmdlineTests/ethdebug_on_abstract/args | 2 +- test/cmdlineTests/ethdebug_on_interface/args | 2 +- .../args | 1 + .../err | 1 + .../exit | 1 + .../input.sol | 6 ++ .../experimental_flag_with_standard_json/args | 1 + .../experimental_flag_with_standard_json/err | 1 + .../experimental_flag_with_standard_json/exit | 1 + .../input.json | 0 .../import_asm_json_all_valid_flags/args | 2 +- .../args | 2 +- .../args | 2 +- .../args | 2 +- .../import_asm_json_invalid_data_not_hex/args | 2 +- .../args | 2 +- .../args | 2 +- .../import_asm_json_invalid_value/args | 2 +- .../args | 2 +- .../import_asm_json_no_optimize/args | 2 +- .../import_asm_json_no_value/args | 2 +- .../import_asm_json_non_unique_sources/args | 2 +- .../import_asm_json_optimize/args | 2 +- .../args | 2 +- .../args | 2 +- .../import_asm_json_unrecognized_field/args | 2 +- .../import_asm_json_untagged_jumpdest/args | 2 +- .../import_asm_json_verbatim/args | 2 +- .../import_asm_json_yul_more_subobjects/args | 2 +- .../import_asm_json_yul_subobjects/args | 2 +- .../args | 2 +- .../strict_asm_eof_container_osaka/args | 2 +- .../strict_asm_eof_dataloadn_osaka/args | 2 +- .../args | 2 +- .../strict_asm_yul_cfg_json_export/args | 2 +- .../undeployable_contract_empty_outputs/args | 2 +- test/cmdlineTests/yul_cfg_json_export/args | 2 +- test/lsp.py | 7 +- test/solc/CommandLineInterface.cpp | 67 +++++++++--------- test/solc/CommandLineParser.cpp | 70 +++++++++++++++++-- 56 files changed, 244 insertions(+), 77 deletions(-) create mode 100644 test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/args create mode 100644 test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/err create mode 100644 test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/exit create mode 100644 test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/input.sol create mode 100644 test/cmdlineTests/experimental_feature_without_experimental_flag/args create mode 100644 test/cmdlineTests/experimental_feature_without_experimental_flag/err create mode 100644 test/cmdlineTests/experimental_feature_without_experimental_flag/exit create mode 100644 test/cmdlineTests/experimental_feature_without_experimental_flag/input.sol create mode 100644 test/cmdlineTests/experimental_flag_with_standard_json/args create mode 100644 test/cmdlineTests/experimental_flag_with_standard_json/err create mode 100644 test/cmdlineTests/experimental_flag_with_standard_json/exit create mode 100644 test/cmdlineTests/experimental_flag_with_standard_json/input.json diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 975ed3c19..d9e703fc3 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -229,6 +229,12 @@ void CompilerStack::setViaIR(bool _viaIR) m_viaIR = _viaIR; } +void CompilerStack::setExperimental(bool _experimental) +{ + solAssert(m_stackState < ParsedAndImported, "Must set experimental before parsing."); + m_experimental = _experimental; +} + void CompilerStack::setEVMVersion(langutil::EVMVersion _version) { solAssert(m_stackState < ParsedAndImported, "Must set EVM version before parsing."); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 2731787a4..eb765d3c6 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -223,6 +223,9 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// Must be set before parsing. void setViaIR(bool _viaIR); + /// Sets the experimental toggle to allow usage of experimental features. + void setExperimental(bool _experimental); + /// Set the EVM version used before running compile. /// When called without an argument it will revert to the default version. /// Must be set before parsing. @@ -607,6 +610,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac RevertStrings m_revertStrings = RevertStrings::Default; State m_stopAfter = State::CompilationSuccessful; bool m_viaIR = false; + bool m_experimental = false; langutil::EVMVersion m_evmVersion; std::optional m_eofVersion; ModelCheckerSettings m_modelCheckerSettings; diff --git a/scripts/ASTImportTest.sh b/scripts/ASTImportTest.sh index c7f504087..370aab9bd 100755 --- a/scripts/ASTImportTest.sh +++ b/scripts/ASTImportTest.sh @@ -117,7 +117,7 @@ function test_ast_import_export_equivalence local input_files=( "${@:2}" ) local export_command=("$SOLC" --combined-json ast --pretty-json --json-indent 4 "${input_files[@]}") - local import_command=("$SOLC" --import-ast --combined-json ast --pretty-json --json-indent 4 expected.json) + local import_command=("$SOLC" --experimental --import-ast --combined-json ast --pretty-json --json-indent 4 expected.json) local import_via_standard_json_command=("$SOLC" --combined-json ast --pretty-json --json-indent 4 --standard-json standard_json_input.json) # export ast - save ast json as expected result (silently) @@ -228,7 +228,7 @@ function test_evmjson_import_export_equivalence local bin_file_from_asm_import bin_file_from_asm_import="import/$(basename "${asm_json_file}" .json).bin" - local import_options=(--bin --import-asm-json "${asm_json_file}") + local import_options=(--experimental --bin --import-asm-json "${asm_json_file}") run_solc_store_stdout "${bin_file_from_asm_import}" "${import_options[@]}" stripCLIDecorations < "$bin_file_from_asm_import" > tmpfile diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 4a7f34561..90c67868d 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -927,6 +927,7 @@ void CommandLineInterface::compile() try { + m_compiler->setExperimental(m_options.experimental); if (m_options.metadata.literalSources) m_compiler->useMetadataLiteralSources(true); m_compiler->setMetadataFormat(m_options.metadata.format); diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 534eb57d1..6720b9fe8 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -50,6 +50,7 @@ static std::string const g_strEVMVersion = "evm-version"; static std::string const g_strEOFVersion = "experimental-eof-version"; static std::string const g_strViaIR = "via-ir"; static std::string const g_strExperimentalViaIR = "experimental-via-ir"; +static std::string const g_strExperimental = "experimental"; static std::string const g_strGas = "gas"; static std::string const g_strHelp = "help"; static std::string const g_strImportAst = "import-ast"; @@ -157,6 +158,32 @@ void CommandLineParser::checkMutuallyExclusive(std::vector const& _ } } +void CommandLineParser::checkExperimental(std::vector const& _optionNames) const +{ + if (!m_args.contains(g_strExperimental) && countEnabledOptions(_optionNames) > 0) + { + solThrow( + CommandLineValidationError, + "The following options are only available in experimental mode: " + joinOptionNames(_optionNames) + ". " + + "To enable experimental mode, use the --experimental flag." + ); + } + + if (m_args.count(g_strEVMVersion)) + { + std::optional versionOption = EVMVersion::fromString(m_args[g_strEVMVersion].as()); + if (versionOption && versionOption->isExperimental()) + // TODO: Cover with test when the Amsterdam version is introduced + solThrow( + CommandLineValidationError, + fmt::format( + "EVM version '{}' is experimental and can only be selected in experimental mode." + "To enable experimental mode, use the --experimental flag", versionOption->name() + ) + ); + } +} + std::ostream& operator<<(std::ostream& _out, CompilerOutputs const& _selection) { std::vector serializedSelection; @@ -879,6 +906,17 @@ General Information)").c_str(), ; desc.add(smtCheckerOptions); + po::options_description experimentalOptions("Experimental options"); + experimentalOptions.add_options() + ( + g_strExperimental.c_str(), + "Enable experimental mode. Note that enabling experimental mode by itself will not " + "enable any experimental features, but will simply allow for such features to be enabled in the " + "usual manner, whether by using specific flags or pragmas." + ) + ; + desc.add(experimentalOptions); + desc.add_options()(g_strInputFile.c_str(), po::value>(), "input file"); return desc; } @@ -922,6 +960,9 @@ void CommandLineParser::processArgs() else if (m_args.count(g_strColor) > 0) m_options.formatting.coloredOutput = true; + if (m_args.contains(g_strExperimental)) + m_options.experimental = true; + checkMutuallyExclusive({ g_strHelp, g_strLicense, @@ -935,6 +976,18 @@ void CommandLineParser::processArgs() g_strImportEvmAssemblerJson, }); + checkExperimental({ + g_strLSP, + g_strImportAst, + g_strImportEvmAssemblerJson, + "ir-ast-json", + "ir-optimized-ast-json", + "yul-cfg-json", + "ethdebug", + "ethdebug-runtime", + g_strEOFVersion, + }); + if (m_args.count(g_strHelp) > 0) m_options.input.mode = InputMode::Help; else if (m_args.count(g_strLicense) > 0) @@ -963,6 +1016,14 @@ void CommandLineParser::processArgs() ) return; + if (m_options.experimental && m_options.input.mode == InputMode::StandardJson) + solThrow( + CommandLineValidationError, + "Standard JSON input mode is incompatible with the --" + g_strExperimental + " flag. " + "Instead, please use the 'settings.experimental' setting in your Standard JSON input file to " + "enable experimental mode." + ); + if (m_args.count(g_strYul) > 0) solThrow( CommandLineValidationError, @@ -1035,6 +1096,7 @@ void CommandLineParser::processArgs() g_strPrettyJson, "srcmap", "srcmap-runtime", + g_strExperimental, }; for (auto const& [optionName, optionValue]: m_args) @@ -1102,6 +1164,12 @@ void CommandLineParser::processArgs() if (!m_options.output.debugInfoSelection.has_value()) solThrow(CommandLineValidationError, "Invalid value for --" + g_strDebugInfo + " option: " + optionValue); + if (!m_options.experimental && m_options.output.debugInfoSelection->ethdebug) + solThrow( + CommandLineValidationError, + "--" + g_strDebugInfo + " ethdebug can only be used by toggling the --" + g_strExperimental + " flag." + ); + if (m_options.output.debugInfoSelection->snippet && !m_options.output.debugInfoSelection->location) solThrow(CommandLineValidationError, "To use 'snippet' with --" + g_strDebugInfo + " you must select also 'location'."); } diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 46743232b..6c32b5ee0 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -272,6 +272,8 @@ struct CommandLineOptions bool initialize = false; ModelCheckerSettings settings; } modelChecker; + + bool experimental = false; }; /// Parses the command-line arguments and produces a filled-out CommandLineOptions structure. @@ -323,6 +325,7 @@ class CommandLineParser void parseOutputSelection(); void checkMutuallyExclusive(std::vector const& _optionNames); + void checkExperimental(std::vector const& _optionNames) const; size_t countEnabledOptions(std::vector const& _optionNames) const; static std::string joinOptionNames(std::vector const& _optionNames, std::string _separator = ", "); diff --git a/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/args b/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/args index c1bc80dab..5634b014d 100644 --- a/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/args +++ b/test/cmdlineTests/asm_json_import_sourcelist_with_null_elements/args @@ -1 +1 @@ ---pretty-json --json-indent 4 --import-asm-json - +--pretty-json --json-indent 4 --experimental --import-asm-json - diff --git a/test/cmdlineTests/asm_json_yul_export_evm_asm_import/args b/test/cmdlineTests/asm_json_yul_export_evm_asm_import/args index 15c962831..7000d519f 100644 --- a/test/cmdlineTests/asm_json_yul_export_evm_asm_import/args +++ b/test/cmdlineTests/asm_json_yul_export_evm_asm_import/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm --bin --asm-json --pretty-json --json-indent 4 +--experimental --import-asm-json - --opcodes --asm --bin --asm-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ast_ir/args b/test/cmdlineTests/ast_ir/args index d254bff83..ab35cc76b 100644 --- a/test/cmdlineTests/ast_ir/args +++ b/test/cmdlineTests/ast_ir/args @@ -1 +1 @@ ---ir-ast-json --ir-optimized-ast-json --optimize --pretty-json --json-indent 4 +--experimental --ir-ast-json --ir-optimized-ast-json --optimize --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ast_json_import_wrong_evmVersion/args b/test/cmdlineTests/ast_json_import_wrong_evmVersion/args index d8fddfec6..d6692d825 100644 --- a/test/cmdlineTests/ast_json_import_wrong_evmVersion/args +++ b/test/cmdlineTests/ast_json_import_wrong_evmVersion/args @@ -1 +1 @@ ---evm-version=homestead --import-ast --combined-json ast --pretty-json +--experimental --evm-version=homestead --import-ast --combined-json ast --pretty-json diff --git a/test/cmdlineTests/eof_unavailable_before_osaka/args b/test/cmdlineTests/eof_unavailable_before_osaka/args index 90e7e00e2..7e9b7ee93 100644 --- a/test/cmdlineTests/eof_unavailable_before_osaka/args +++ b/test/cmdlineTests/eof_unavailable_before_osaka/args @@ -1 +1 @@ ---optimize --experimental-eof-version 1 --evm-version cancun +--experimental --optimize --experimental-eof-version 1 --evm-version cancun diff --git a/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/args b/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/args new file mode 100644 index 000000000..7b4e521b0 --- /dev/null +++ b/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/args @@ -0,0 +1 @@ +--debug-info ethdebug diff --git a/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/err b/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/err new file mode 100644 index 000000000..d8327f90b --- /dev/null +++ b/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/err @@ -0,0 +1 @@ +Error: --debug-info ethdebug can only be used by toggling the --experimental flag. diff --git a/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/exit b/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/input.sol b/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/input.sol new file mode 100644 index 000000000..415509ef9 --- /dev/null +++ b/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/args b/test/cmdlineTests/ethdebug_eof_container_osaka/args index 16466b842..49c5bc838 100644 --- a/test/cmdlineTests/ethdebug_eof_container_osaka/args +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/args @@ -1 +1 @@ - --experimental-eof-version 1 --evm-version osaka --ethdebug --via-ir --pretty-json --json-indent 4 +--experimental --experimental-eof-version 1 --evm-version osaka --ethdebug --via-ir --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ethdebug_on_abstract/args b/test/cmdlineTests/ethdebug_on_abstract/args index c6018b329..c345d483a 100644 --- a/test/cmdlineTests/ethdebug_on_abstract/args +++ b/test/cmdlineTests/ethdebug_on_abstract/args @@ -1 +1 @@ ---ethdebug --via-ir --pretty-json --json-indent 4 +--experimental --ethdebug --via-ir --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ethdebug_on_interface/args b/test/cmdlineTests/ethdebug_on_interface/args index c6018b329..c345d483a 100644 --- a/test/cmdlineTests/ethdebug_on_interface/args +++ b/test/cmdlineTests/ethdebug_on_interface/args @@ -1 +1 @@ ---ethdebug --via-ir --pretty-json --json-indent 4 +--experimental --ethdebug --via-ir --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/experimental_feature_without_experimental_flag/args b/test/cmdlineTests/experimental_feature_without_experimental_flag/args new file mode 100644 index 000000000..a5ec4617b --- /dev/null +++ b/test/cmdlineTests/experimental_feature_without_experimental_flag/args @@ -0,0 +1 @@ +--ir-ast-json diff --git a/test/cmdlineTests/experimental_feature_without_experimental_flag/err b/test/cmdlineTests/experimental_feature_without_experimental_flag/err new file mode 100644 index 000000000..1b73066ce --- /dev/null +++ b/test/cmdlineTests/experimental_feature_without_experimental_flag/err @@ -0,0 +1 @@ +Error: The following options are only available in experimental mode: --lsp, --import-ast, --import-asm-json, --ir-ast-json, --ir-optimized-ast-json, --yul-cfg-json, --ethdebug, --ethdebug-runtime, --experimental-eof-version. To enable experimental mode, use the --experimental flag. diff --git a/test/cmdlineTests/experimental_feature_without_experimental_flag/exit b/test/cmdlineTests/experimental_feature_without_experimental_flag/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/experimental_feature_without_experimental_flag/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/experimental_feature_without_experimental_flag/input.sol b/test/cmdlineTests/experimental_feature_without_experimental_flag/input.sol new file mode 100644 index 000000000..0bea95d1e --- /dev/null +++ b/test/cmdlineTests/experimental_feature_without_experimental_flag/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/experimental_flag_with_standard_json/args b/test/cmdlineTests/experimental_flag_with_standard_json/args new file mode 100644 index 000000000..1c31d6967 --- /dev/null +++ b/test/cmdlineTests/experimental_flag_with_standard_json/args @@ -0,0 +1 @@ +--experimental diff --git a/test/cmdlineTests/experimental_flag_with_standard_json/err b/test/cmdlineTests/experimental_flag_with_standard_json/err new file mode 100644 index 000000000..81d8411e5 --- /dev/null +++ b/test/cmdlineTests/experimental_flag_with_standard_json/err @@ -0,0 +1 @@ +Error: Standard JSON input mode is incompatible with the --experimental flag. Instead, please use the 'settings.experimental' setting in your Standard JSON input file to enable experimental mode. diff --git a/test/cmdlineTests/experimental_flag_with_standard_json/exit b/test/cmdlineTests/experimental_flag_with_standard_json/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/experimental_flag_with_standard_json/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/experimental_flag_with_standard_json/input.json b/test/cmdlineTests/experimental_flag_with_standard_json/input.json new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/import_asm_json_all_valid_flags/args b/test/cmdlineTests/import_asm_json_all_valid_flags/args index e6010eac3..a1e89d7ae 100644 --- a/test/cmdlineTests/import_asm_json_all_valid_flags/args +++ b/test/cmdlineTests/import_asm_json_all_valid_flags/args @@ -1 +1 @@ ---pretty-json --json-indent 4 --combined-json bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime --asm --bin --bin-runtime --asm-json --import-asm-json - +--experimental --pretty-json --json-indent 4 --combined-json bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime --asm --bin --bin-runtime --asm-json --import-asm-json - diff --git a/test/cmdlineTests/import_asm_json_difficulty_prevrandao/args b/test/cmdlineTests/import_asm_json_difficulty_prevrandao/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_difficulty_prevrandao/args +++ b/test/cmdlineTests/import_asm_json_difficulty_prevrandao/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/args b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/args index b5d6267fa..7293bf52a 100644 --- a/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/args +++ b/test/cmdlineTests/import_asm_json_eof_unavailable_before_osaka/args @@ -1 +1 @@ ---import-asm-json --experimental-eof-version 1 --evm-version cancun +--experimental --import-asm-json --experimental-eof-version 1 --evm-version cancun diff --git a/test/cmdlineTests/import_asm_json_hex_subassembly_indices/args b/test/cmdlineTests/import_asm_json_hex_subassembly_indices/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_hex_subassembly_indices/args +++ b/test/cmdlineTests/import_asm_json_hex_subassembly_indices/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_invalid_data_not_hex/args b/test/cmdlineTests/import_asm_json_invalid_data_not_hex/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_invalid_data_not_hex/args +++ b/test/cmdlineTests/import_asm_json_invalid_data_not_hex/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_invalid_data_not_object/args b/test/cmdlineTests/import_asm_json_invalid_data_not_object/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_invalid_data_not_object/args +++ b/test/cmdlineTests/import_asm_json_invalid_data_not_object/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/args b/test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/args +++ b/test/cmdlineTests/import_asm_json_invalid_jumptype_instruction/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_invalid_value/args b/test/cmdlineTests/import_asm_json_invalid_value/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_invalid_value/args +++ b/test/cmdlineTests/import_asm_json_invalid_value/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_missing_subobject_indices/args b/test/cmdlineTests/import_asm_json_missing_subobject_indices/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_missing_subobject_indices/args +++ b/test/cmdlineTests/import_asm_json_missing_subobject_indices/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_no_optimize/args b/test/cmdlineTests/import_asm_json_no_optimize/args index 0af885908..9dcc671fb 100644 --- a/test/cmdlineTests/import_asm_json_no_optimize/args +++ b/test/cmdlineTests/import_asm_json_no_optimize/args @@ -1 +1 @@ ---import-asm-json - --asm +--experimental --import-asm-json - --asm diff --git a/test/cmdlineTests/import_asm_json_no_value/args b/test/cmdlineTests/import_asm_json_no_value/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_no_value/args +++ b/test/cmdlineTests/import_asm_json_no_value/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_non_unique_sources/args b/test/cmdlineTests/import_asm_json_non_unique_sources/args index d27cc7bb2..772c307ad 100644 --- a/test/cmdlineTests/import_asm_json_non_unique_sources/args +++ b/test/cmdlineTests/import_asm_json_non_unique_sources/args @@ -1 +1 @@ ---asm-json --import-asm-json - +--experimental --asm-json --import-asm-json - diff --git a/test/cmdlineTests/import_asm_json_optimize/args b/test/cmdlineTests/import_asm_json_optimize/args index b9370e6e4..1a7274261 100644 --- a/test/cmdlineTests/import_asm_json_optimize/args +++ b/test/cmdlineTests/import_asm_json_optimize/args @@ -1 +1 @@ ---optimize --import-asm-json - --asm +--experimental --optimize --import-asm-json - --asm diff --git a/test/cmdlineTests/import_asm_json_out_of_range_data_index/args b/test/cmdlineTests/import_asm_json_out_of_range_data_index/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_out_of_range_data_index/args +++ b/test/cmdlineTests/import_asm_json_out_of_range_data_index/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_random_order_data_index/args b/test/cmdlineTests/import_asm_json_random_order_data_index/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_random_order_data_index/args +++ b/test/cmdlineTests/import_asm_json_random_order_data_index/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_unrecognized_field/args b/test/cmdlineTests/import_asm_json_unrecognized_field/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_unrecognized_field/args +++ b/test/cmdlineTests/import_asm_json_unrecognized_field/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_untagged_jumpdest/args b/test/cmdlineTests/import_asm_json_untagged_jumpdest/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_untagged_jumpdest/args +++ b/test/cmdlineTests/import_asm_json_untagged_jumpdest/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_verbatim/args b/test/cmdlineTests/import_asm_json_verbatim/args index 2b4b3a153..a31c9320b 100644 --- a/test/cmdlineTests/import_asm_json_verbatim/args +++ b/test/cmdlineTests/import_asm_json_verbatim/args @@ -1 +1 @@ ---import-asm-json - --opcodes --asm +--experimental --import-asm-json - --opcodes --asm diff --git a/test/cmdlineTests/import_asm_json_yul_more_subobjects/args b/test/cmdlineTests/import_asm_json_yul_more_subobjects/args index 58dfc8cc7..7de136d4b 100644 --- a/test/cmdlineTests/import_asm_json_yul_more_subobjects/args +++ b/test/cmdlineTests/import_asm_json_yul_more_subobjects/args @@ -1 +1 @@ ---import-asm-json - --opcodes +--experimental --import-asm-json - --opcodes diff --git a/test/cmdlineTests/import_asm_json_yul_subobjects/args b/test/cmdlineTests/import_asm_json_yul_subobjects/args index 58dfc8cc7..7de136d4b 100644 --- a/test/cmdlineTests/import_asm_json_yul_subobjects/args +++ b/test/cmdlineTests/import_asm_json_yul_subobjects/args @@ -1 +1 @@ ---import-asm-json - --opcodes +--experimental --import-asm-json - --opcodes diff --git a/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/args b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/args index f0b85640b..811190e2a 100644 --- a/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/args +++ b/test/cmdlineTests/standard_cli_import_ast_storage_layout_specifier_missing_expression/args @@ -1 +1 @@ ---import-ast - \ No newline at end of file +--experimental --import-ast - diff --git a/test/cmdlineTests/strict_asm_eof_container_osaka/args b/test/cmdlineTests/strict_asm_eof_container_osaka/args index 60abde356..1a99e4be6 100644 --- a/test/cmdlineTests/strict_asm_eof_container_osaka/args +++ b/test/cmdlineTests/strict_asm_eof_container_osaka/args @@ -1 +1 @@ - --strict-assembly --experimental-eof-version 1 --evm-version osaka --asm --ir-optimized --bin --debug-info none +--experimental --strict-assembly --experimental-eof-version 1 --evm-version osaka --asm --ir-optimized --bin --debug-info none diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args index 60abde356..1a99e4be6 100644 --- a/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/args @@ -1 +1 @@ - --strict-assembly --experimental-eof-version 1 --evm-version osaka --asm --ir-optimized --bin --debug-info none +--experimental --strict-assembly --experimental-eof-version 1 --evm-version osaka --asm --ir-optimized --bin --debug-info none diff --git a/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/args b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/args index 7ec243fde..c7b8a5a6a 100644 --- a/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/args +++ b/test/cmdlineTests/strict_asm_eof_unavailable_before_osaka/args @@ -1 +1 @@ ---strict-assembly --experimental-eof-version 1 --evm-version cancun +--experimental --strict-assembly --experimental-eof-version 1 --evm-version cancun diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/args b/test/cmdlineTests/strict_asm_yul_cfg_json_export/args index 1147466b5..ecd27ca32 100644 --- a/test/cmdlineTests/strict_asm_yul_cfg_json_export/args +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/args @@ -1 +1 @@ ---strict-assembly --optimize --yul-cfg-json --pretty-json --json-indent 4 +--experimental --strict-assembly --optimize --yul-cfg-json --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/undeployable_contract_empty_outputs/args b/test/cmdlineTests/undeployable_contract_empty_outputs/args index 74c8e867f..17068d35d 100644 --- a/test/cmdlineTests/undeployable_contract_empty_outputs/args +++ b/test/cmdlineTests/undeployable_contract_empty_outputs/args @@ -1 +1 @@ ---bin --bin-runtime --opcodes --asm --ir --ir-ast-json --ir-optimized --ir-optimized-ast-json --gas --asm-json --abi --hashes --optimize --pretty-json --json-indent 4 +--experimental --bin --bin-runtime --opcodes --asm --ir --ir-ast-json --ir-optimized --ir-optimized-ast-json --gas --asm-json --abi --hashes --optimize --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/yul_cfg_json_export/args b/test/cmdlineTests/yul_cfg_json_export/args index 4af41df67..b03ca0ef5 100644 --- a/test/cmdlineTests/yul_cfg_json_export/args +++ b/test/cmdlineTests/yul_cfg_json_export/args @@ -1 +1 @@ ---via-ir --optimize --yul-cfg-json --pretty-json --json-indent 4 +--experimental --via-ir --optimize --yul-cfg-json --pretty-json --json-indent 4 diff --git a/test/lsp.py b/test/lsp.py index 11007ae82..266a29fcc 100755 --- a/test/lsp.py +++ b/test/lsp.py @@ -882,7 +882,12 @@ def main(self) -> int: title: str = test_fn.__name__[5:] print(f"{SGR_TEST_BEGIN}Testing {title} ...{SGR_RESET}") try: - with JsonRpcProcess(self.solc_path, ["--lsp"], trace_io=self.trace_io, print_pid=self.print_solc_pid) as solc: + with JsonRpcProcess( + self.solc_path, + ["--experimental", "--lsp"], + trace_io=self.trace_io, + print_pid=self.print_solc_pid + ) as solc: test_fn(solc) self.test_counter.passed += 1 except ExpectationFailed: diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index adfd24b02..d1c43be5b 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -1534,61 +1534,62 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_debug_info_ethdebug) createFilesWithParentDirs({tempDir.path() / "input.yul"}, "{}"); static std::vector> erroneousCLIFlagCombinations{ { - {"solc", "--debug-info", "ethdebug", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "ethdebug", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ir-optimized", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--optimize", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--optimize", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {"solc", "--experimental", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, }, { - {"solc", "--ethdebug", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {"solc", "--experimental", "--ethdebug", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, }, { - {"solc", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "location", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "location", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "location", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "location", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "location", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "location", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "all", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "all", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "all", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "all", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "all", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "all", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, }, }; static std::vector> supportedCLIFlagCombinations{ { - {"solc", "--debug-info", "ethdebug", "--ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { { "solc", + "--experimental", "--debug-info", "ethdebug", "--ethdebug-runtime", @@ -1597,14 +1598,15 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_debug_info_ethdebug) }, }, { - {"solc", "--debug-info", "ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, }, { - {"solc", "--ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {"solc", "--experimental", "--ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, }, { { "solc", + "--experimental", "--debug-info", "ethdebug", "--ethdebug", @@ -1633,11 +1635,12 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_ethdebug_output) createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); static std::vector> erroneousCLIFlagCombinations{ { - {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, }, { { "solc", + "--experimental", "--ethdebug-runtime", "--via-ir", "--ir-optimized", @@ -1646,42 +1649,42 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_ethdebug_output) }, }, { - {"solc", "--ethdebug", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--ethdebug", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, }, }; static std::vector> supportedCLIFlagCombinations{ { - {"solc", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--ethdebug", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--ethdebug", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--ethdebug-runtime", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-runtime", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, }, }; diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 85eeaebe3..705ae3f73 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -110,6 +110,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) "/tmp=/usr/lib/", "a:b=c/d", ":contract.sol=", + "--experimental", "--base-path=/home/user/", "--include-path=/usr/lib/include/", "--include-path=/home/user/include", @@ -163,6 +164,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) }; CommandLineOptions expectedOptions; + expectedOptions.experimental = true; expectedOptions.input.mode = inputMode; expectedOptions.input.paths = {"contract.sol", "/tmp/projects/token.sol", "/home/user/lib/dex.sol", "file", "input.json"}; expectedOptions.input.remappings = { @@ -249,7 +251,7 @@ BOOST_AUTO_TEST_CASE(no_import_callback) {"solc", "--standard-json", "--no-import-callback", "input.json"}, {"solc", "--assemble", "--no-import-callback", "input.yul"}, {"solc", "--strict-assembly", "--no-import-callback", "input.yul"}, - {"solc", "--import-ast", "--no-import-callback", "ast.json"}, + {"solc", "--experimental", "--import-ast", "--no-import-callback", "ast.json"}, {"solc", "--link", "--no-import-callback", "input.bin"}, }; @@ -482,6 +484,8 @@ BOOST_AUTO_TEST_CASE(optimizer_flags) for (auto const& [optimizerFlags, expectedOptimizerSettings]: settingsMap) { std::vector commandLine = {"solc", inputModeFlag, "file"}; + if (inputMode == InputMode::CompilerWithASTImport) + commandLine.emplace_back("--experimental"); commandLine += optimizerFlags; BOOST_CHECK(parseCommandLine(commandLine).optimiserSettings() == expectedOptimizerSettings); } @@ -630,34 +634,34 @@ BOOST_AUTO_TEST_CASE(invalid_optimizer_sequence_without_optimize) BOOST_AUTO_TEST_CASE(ethdebug) { - CommandLineOptions commandLineOptions = parseCommandLine({"solc", "contract.sol", "--debug-info", "ethdebug", "--ethdebug", "--via-ir"}); + CommandLineOptions commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--debug-info", "ethdebug", "--ethdebug", "--via-ir"}); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); - commandLineOptions = parseCommandLine({"solc", "contract.sol", "--debug-info", "ethdebug", "--ethdebug-runtime", "--via-ir"}); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--debug-info", "ethdebug", "--ethdebug-runtime", "--via-ir"}); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); - commandLineOptions = parseCommandLine({"solc", "contract.sol", "--ethdebug", "--via-ir"}); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--ethdebug", "--via-ir"}); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); // debug-info "ethdebug" selected implicitly, // if compiled with --ethdebug or --ethdebug-runtime and no debug-info was selected. BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); - commandLineOptions = parseCommandLine({"solc", "contract.sol", "--ethdebug-runtime", "--via-ir"}); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--ethdebug-runtime", "--via-ir"}); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); - commandLineOptions = parseCommandLine({"solc", "contract.sol", "--ethdebug", "--ethdebug-runtime", "--via-ir"}); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--ethdebug", "--ethdebug-runtime", "--via-ir"}); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); - commandLineOptions = parseCommandLine({"solc", "contract.sol", "--debug-info", "ethdebug", "--ir"}); + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--debug-info", "ethdebug", "--ir"}); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ir, true); @@ -665,6 +669,58 @@ BOOST_AUTO_TEST_CASE(ethdebug) BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); } +BOOST_AUTO_TEST_CASE(experimental_features_without_experimental_flag) +{ + std::vector const experimentalFeatures { + "--lsp", + "--import-ast", + "--import-asm-json", + "--ir-ast-json", + "--ir-optimized-ast-json", + "--yul-cfg-json", + "--ethdebug", + "--ethdebug-runtime" + }; + + std::string const expectedErrorMessage { + "The following options are only available in experimental mode: --lsp, --import-ast, --import-asm-json, " + "--ir-ast-json, --ir-optimized-ast-json, --yul-cfg-json, --ethdebug, --ethdebug-runtime, --experimental-eof-version. " + "To enable experimental mode, use the --experimental flag." + }; + + auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedErrorMessage; }; + + for (auto const& experimentalFeature: experimentalFeatures) + { + std::vector const commandLineOptions{"solc", experimentalFeature, "contract.sol"}; + BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage); + } + + std::vector const commandLineOptions{"solc", "--experimental-eof-version", "1", "contract.sol"}; + BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage); +} + +BOOST_AUTO_TEST_CASE(debug_info_ethdebug_without_experimental_flag) +{ + std::string const expectedErrorMessage { "--debug-info ethdebug can only be used by toggling the --experimental flag." }; + auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedErrorMessage; }; + + std::vector const commandLineOptions{"solc", "--debug-info", "ethdebug", "contract.sol"}; + BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage); +} + +BOOST_AUTO_TEST_CASE(experimental_flag_with_standard_json) +{ + std::string const expectedErrorMessage { + "Standard JSON input mode is incompatible with the --experimental flag. " + "Instead, please use the 'settings.experimental' setting in your Standard JSON input file to enable experimental mode." + }; + auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedErrorMessage; }; + + std::vector const commandLineOptions{"solc", "--experimental", "--standard-json", "input.json"}; + BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace solidity::frontend::test From adc2c30992d75c539e1d9934326d4091f368c0b5 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 20 Oct 2025 12:26:14 +0200 Subject: [PATCH 1146/1340] Cover experimental pragmas and tests --- libsolidity/analysis/SyntaxChecker.cpp | 6 ++++++ libsolidity/analysis/SyntaxChecker.h | 10 ++++++++-- libsolidity/interface/CompilerStack.cpp | 7 ++++++- test/libsolidity/Assembly.cpp | 2 +- test/libsolidity/FunctionDependencyGraphTest.cpp | 2 ++ test/libsolidity/FunctionDependencyGraphTest.h | 2 -- test/libsolidity/Metadata.cpp | 2 ++ test/libsolidity/SemanticTest.cpp | 1 + test/libsolidity/SolidityExpressionCompiler.cpp | 2 +- test/libsolidity/SyntaxTest.cpp | 4 +++- test/libsolidity/SyntaxTest.h | 1 + test/libsolidity/semanticTests/experimental/stub.sol | 1 + .../semanticTests/experimental/type_class.sol | 1 + test/libsolidity/smtCheckerTests/options/pragma.sol | 2 ++ .../struct_constructor_fixed_bytes_from_string_1.sol | 2 ++ .../abiEncoder/conflicting_settings_reverse.sol | 2 ++ .../conflicting_settings_reverse_experimental.sol | 2 ++ .../syntaxTests/abiEncoder/same_setting_twice.sol | 2 ++ .../syntaxTests/abiEncoder/selected_twice_v2.sol | 2 ++ .../experimental/builtin/builtin_type_definition.sol | 1 + .../builtin/builtin_type_definition_duplicate.sol | 1 + .../builtin/builtin_type_definition_unknown.sol | 1 + .../forall/undeclared_type_variable_in_function.sol | 1 + ...undeclared_type_variable_in_quantified_function.sol | 1 + .../forall/undeclared_type_variable_in_type_class.sol | 1 + .../experimental/import/experimental_solidity.sol | 1 + ...xperimental_solidity_multisource_not_all_enable.sol | 1 + .../import/experimental_solidity_out_of_order_1.sol | 1 + .../import/experimental_solidity_out_of_order_2.sol | 1 + .../import/experimental_solidity_wrong_evm_version.sol | 1 + .../experimental/import/parsing_stdlib_import_1.sol | 1 + .../experimental/import/parsing_stdlib_import_2.sol | 1 + .../experimental/import/parsing_stdlib_import_3.sol | 1 + .../experimental/import/parsing_stdlib_import_4.sol | 1 + .../inference/import_and_call_stdlib_function.sol | 1 + .../instantiation_invalid_type_constructor.sol | 1 + ...ntiation_member_type_does_not_match_declaration.sol | 1 + .../inference/instantiation_not_for_class.sol | 1 + .../experimental/inference/invalid_type_referenced.sol | 1 + .../monomorphic_function_call_type_mismatch.sol | 1 + .../inference/polymorphic_function_call.sol | 1 + .../polymorphic_function_call_let_polymorphism.sol | 1 + .../polymorphic_function_call_type_mismatch.sol | 1 + .../experimental/inference/polymorphic_type.sol | 1 + .../inference/polymorphic_type_abs_and_rep.sol | 1 + .../polymorphic_type_instantiation_and_operators.sol | 1 + ...ariable_multi_use_function_parameter_and_return.sol | 1 + .../type_variable_multi_use_function_parameters.sol | 1 + .../experimental/parsing/forall_free_function.sol | 1 + .../parsing/forall_free_function_no_type_var.sol | 1 + .../parsing/forall_free_function_with_sorts.sol | 1 + .../experimental/parsing/forall_type_class.sol | 1 + .../parsing/forall_type_class_instantiation.sol | 1 + .../pragma/experimental_empty_string_literal.sol | 2 ++ .../pragma/experimental_multiple_experimental.sol | 2 ++ .../pragma/experimental_multiple_same_line.sol | 2 ++ .../pragma/experimental_pragma_duplicate.sol | 2 ++ .../syntaxTests/pragma/experimental_pragma_empty.sol | 2 ++ .../experimental_pragma_unknown_string_literal.sol | 2 ++ .../experimental_pragma_without_experimental_mode.sol | 4 ++++ .../syntaxTests/pragma/experimental_test_warning.sol | 2 ++ .../pragma/experimental_unknown_number_literal.sol | 2 ++ .../experimental_unknown_quoted_string_literal.sol | 2 ++ 63 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 test/libsolidity/syntaxTests/pragma/experimental_pragma_without_experimental_mode.sol diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 9bf784b36..8253eec49 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -83,6 +83,12 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma) else if (_pragma.literals()[0] == "experimental") { solAssert(m_sourceUnit, ""); + if (!m_experimental) + m_errorReporter.syntaxError( + 2816_error, + _pragma.location(), + "Experimental pragmas can only be used if the experimental mode has been enabled." + ); std::vector literals(_pragma.literals().begin() + 1, _pragma.literals().end()); if (literals.empty()) m_errorReporter.syntaxError( diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index 69bda229f..9babfe47e 100644 --- a/libsolidity/analysis/SyntaxChecker.h +++ b/libsolidity/analysis/SyntaxChecker.h @@ -45,9 +45,12 @@ class SyntaxChecker: private ASTConstVisitor { public: /// @param _errorReporter provides the error logging functionality. - SyntaxChecker(langutil::ErrorReporter& _errorReporter, bool _useYulOptimizer): + /// @param _useYulOptimizer indicates whether Yul optimizer is enabled. + /// @param _experimental indicates whether the experimental toggle (option) is enabled. + SyntaxChecker(langutil::ErrorReporter& _errorReporter, bool _useYulOptimizer, bool _experimental): m_errorReporter(_errorReporter), - m_useYulOptimizer(_useYulOptimizer) + m_useYulOptimizer(_useYulOptimizer), + m_experimental(_experimental) {} bool checkSyntax(ASTNode const& _astRoot); @@ -112,6 +115,9 @@ class SyntaxChecker: private ASTConstVisitor /// Flag that indicates whether we are inside an unchecked block. bool m_uncheckedArithmetic = false; + /// Flag that indicates whether experimental mode is toggled. + bool m_experimental = false; + int m_inLoopDepth = 0; std::optional m_currentContractKind; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index d9e703fc3..2ed72db0f 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -473,7 +473,7 @@ bool CompilerStack::analyze() { bool experimentalSolidity = isExperimentalSolidity(); - SyntaxChecker syntaxChecker(m_errorReporter, m_optimiserSettings.runYulOptimiser); + SyntaxChecker syntaxChecker(m_errorReporter, m_optimiserSettings.runYulOptimiser, m_experimental); for (Source const* source: m_sourceOrder) if (source->ast && !syntaxChecker.checkSyntax(*source->ast)) noErrors = false; @@ -767,6 +767,10 @@ bool CompilerStack::compile(State _stopAfter) std::map> otherCompilers; for (Source const* source: m_sourceOrder) + { + if (source->ast && !m_experimental) + solAssert(source->ast->annotation().experimentalFeatures.empty()); + for (ASTPointer const& node: source->ast->nodes()) if (auto contract = dynamic_cast(node.get())) if (isRequestedContract(*contract)) @@ -801,6 +805,7 @@ bool CompilerStack::compile(State _stopAfter) if (m_errorReporter.hasErrors()) return false; } + } solAssert(!m_errorReporter.hasErrors()); m_stackState = CompilationSuccessful; diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index bf9c6b16a..85d6a3982 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -66,7 +66,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr _sourceCode) BOOST_CHECK(!!sourceUnit); Scoper::assignScopes(*sourceUnit); - BOOST_REQUIRE(SyntaxChecker(errorReporter, false).checkSyntax(*sourceUnit)); + BOOST_REQUIRE(SyntaxChecker(errorReporter, false, false).checkSyntax(*sourceUnit)); GlobalContext globalContext(solidity::test::CommonOptions::get().evmVersion()); NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter, false); DeclarationTypeChecker declarationTypeChecker(errorReporter, solidity::test::CommonOptions::get().evmVersion()); diff --git a/test/libsolidity/FunctionDependencyGraphTest.cpp b/test/libsolidity/FunctionDependencyGraphTest.cpp index c7992d2a2..ded643e68 100644 --- a/test/libsolidity/FunctionDependencyGraphTest.cpp +++ b/test/libsolidity/FunctionDependencyGraphTest.cpp @@ -42,6 +42,8 @@ TestCase::TestResult FunctionDependencyGraphTest::run(std::ostream& _stream, std compiler().setSources(StringMap{{"", m_source}}); compiler().setViaIR(true); compiler().setOptimiserSettings(OptimiserSettings::none()); + // Experimental on by default as this is an extension of the initial experimental Solidity + compiler().setExperimental(true); if (!compiler().compile(CompilerStack::AnalysisSuccessful)) { printPrefixed(_stream, formatErrors(filteredErrors(), _formatted), _linePrefix); diff --git a/test/libsolidity/FunctionDependencyGraphTest.h b/test/libsolidity/FunctionDependencyGraphTest.h index 83f3eb0ab..4b6b78a97 100644 --- a/test/libsolidity/FunctionDependencyGraphTest.h +++ b/test/libsolidity/FunctionDependencyGraphTest.h @@ -24,8 +24,6 @@ #include #include -#include -#include namespace solidity::frontend::test { diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index 3b7d101d5..0b6bae28d 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -104,6 +104,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize); compilerStack.setMetadataHash(metadataHash); + compilerStack.setExperimental(true); // Experimental pragma requires it BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; std::string const& metadata = compilerStack.metadata("test"); @@ -177,6 +178,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize); compilerStack.setMetadataHash(metadataHash); + compilerStack.setExperimental(true); // Experimental pragma requires it BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; std::string const& metadata = compilerStack.metadata("test"); diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 890a51596..296467ae2 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -112,6 +112,7 @@ SemanticTest::SemanticTest( m_revertStrings = revertStrings.value(); m_allowNonExistingFunctions = m_reader.boolSetting("allowNonExistingFunctions", false); + m_compiler.setExperimental(m_reader.boolSetting("experimental", false)); parseExpectations(m_reader.stream()); soltestAssert(!m_tests.empty(), "No tests specified in " + _filename); diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index b6d40eed0..d64ffac5b 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -126,7 +126,7 @@ bytes compileFirstExpression( ErrorReporter errorReporter(errors); GlobalContext globalContext(solidity::test::CommonOptions::get().evmVersion()); Scoper::assignScopes(*sourceUnit); - BOOST_REQUIRE(SyntaxChecker(errorReporter, false).checkSyntax(*sourceUnit)); + BOOST_REQUIRE(SyntaxChecker(errorReporter, false, false).checkSyntax(*sourceUnit)); NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter, false); resolver.registerDeclarations(*sourceUnit); BOOST_REQUIRE_MESSAGE(resolver.resolveNamesAndTypes(*sourceUnit), "Resolving names failed"); diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 894471054..23b92bcb1 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -51,13 +51,14 @@ SyntaxTest::SyntaxTest( auto const eofEnabled = solidity::test::CommonOptions::get().eofVersion().has_value(); m_compileViaYul = m_reader.stringSetting("compileViaYul", eofEnabled ? "true" : "false"); - if (!util::contains(compileViaYulAllowedValues, m_compileViaYul)) + if (!compileViaYulAllowedValues.contains(m_compileViaYul)) BOOST_THROW_EXCEPTION(std::runtime_error("Invalid compileViaYul value: " + m_compileViaYul + ".")); if (m_compileViaYul == "false" && eofEnabled) m_shouldRun = false; m_optimiseYul = m_reader.boolSetting("optimize-yul", true); + m_experimental = m_reader.boolSetting("experimental", false); static std::map const pipelineStages = { {"parsing", PipelineStage::Parsing}, @@ -81,6 +82,7 @@ void SyntaxTest::setupCompiler(CompilerStack& _compiler) OptimiserSettings::minimal() ); _compiler.setViaIR(m_compileViaYul == "true"); + _compiler.setExperimental(m_experimental); _compiler.setMetadataFormat(CompilerStack::MetadataFormat::NoMetadata); _compiler.setMetadataHash(CompilerStack::MetadataHash::None); } diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index 085a32f94..9c52acd9b 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -53,6 +53,7 @@ class SyntaxTest: public AnalysisFramework, public solidity::test::CommonSyntaxT virtual void filterObtainedErrors(); bool m_optimiseYul{}; + bool m_experimental{false}; std::string m_compileViaYul{}; langutil::Error::Severity m_minSeverity{}; PipelineStage m_stopAfter; diff --git a/test/libsolidity/semanticTests/experimental/stub.sol b/test/libsolidity/semanticTests/experimental/stub.sol index d2d0999bf..7cc1c3033 100644 --- a/test/libsolidity/semanticTests/experimental/stub.sol +++ b/test/libsolidity/semanticTests/experimental/stub.sol @@ -89,6 +89,7 @@ contract C { } } // ==== +// experimental: true // EVMVersion: >=constantinople // ==== // compileViaYul: true diff --git a/test/libsolidity/semanticTests/experimental/type_class.sol b/test/libsolidity/semanticTests/experimental/type_class.sol index 7331c0dbd..4f101a147 100644 --- a/test/libsolidity/semanticTests/experimental/type_class.sol +++ b/test/libsolidity/semanticTests/experimental/type_class.sol @@ -61,6 +61,7 @@ contract C { } // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // bytecodeFormat: legacy diff --git a/test/libsolidity/smtCheckerTests/options/pragma.sol b/test/libsolidity/smtCheckerTests/options/pragma.sol index b3e35ee02..af2f644ad 100644 --- a/test/libsolidity/smtCheckerTests/options/pragma.sol +++ b/test/libsolidity/smtCheckerTests/options/pragma.sol @@ -4,6 +4,8 @@ contract C { assert(x > 0); } } +// ==== +// experimental: true // ---- // Warning 5523: (0-31): The SMTChecker pragma has been deprecated and will be removed in the future. Please use the "model checker engine" compiler setting to activate the SMTChecker instead. If the pragma is enabled, all engines will be used. // Warning 6328: (90-103): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\n\nTransaction trace:\nC.constructor()\nC.f(0) diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_constructor_fixed_bytes_from_string_1.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_constructor_fixed_bytes_from_string_1.sol index 30d6da4a4..f31b9ca88 100644 --- a/test/libsolidity/smtCheckerTests/types/struct/struct_constructor_fixed_bytes_from_string_1.sol +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_constructor_fixed_bytes_from_string_1.sol @@ -9,6 +9,8 @@ contract C { assert(S({a:2, b:""}).a == 0); // should fail } } +// ==== +// experimental: true // ---- // Warning 5523: (0-31): The SMTChecker pragma has been deprecated and will be removed in the future. Please use the "model checker engine" compiler setting to activate the SMTChecker instead. If the pragma is enabled, all engines will be used. // Warning 6328: (178-207): CHC: Assertion violation happens here. diff --git a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol index feacbbeb3..19a29b524 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol @@ -1,5 +1,7 @@ pragma abicoder v1; pragma abicoder v2; +// ==== +// experimental: true // ---- // Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // SyntaxError 3845: (20-39): ABI coder has already been selected for this source unit. diff --git a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol index 884d03132..022aa76a2 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol @@ -1,5 +1,7 @@ pragma abicoder v1; pragma experimental ABIEncoderV2; +// ==== +// experimental: true // ---- // Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // SyntaxError 8273: (20-53): ABI coder v1 has already been selected through "pragma abicoder v1". diff --git a/test/libsolidity/syntaxTests/abiEncoder/same_setting_twice.sol b/test/libsolidity/syntaxTests/abiEncoder/same_setting_twice.sol index 0303bcb14..fcdc2d5bb 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/same_setting_twice.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/same_setting_twice.sol @@ -1,4 +1,6 @@ pragma experimental ABIEncoderV2; pragma abicoder v2; +// ==== +// experimental: true // ---- // SyntaxError 3845: (34-53): ABI coder has already been selected for this source unit. diff --git a/test/libsolidity/syntaxTests/abiEncoder/selected_twice_v2.sol b/test/libsolidity/syntaxTests/abiEncoder/selected_twice_v2.sol index 0b296da3a..848efa83e 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/selected_twice_v2.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/selected_twice_v2.sol @@ -1,3 +1,5 @@ pragma abicoder v2; pragma experimental ABIEncoderV2; +// ==== +// experimental: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol index 74a659cd8..f4d53061f 100644 --- a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol +++ b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition.sol @@ -30,6 +30,7 @@ contract C { } } // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // bytecodeFormat: legacy diff --git a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition_duplicate.sol b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition_duplicate.sol index 28f6c39fd..720bb8c27 100644 --- a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition_duplicate.sol +++ b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition_duplicate.sol @@ -9,6 +9,7 @@ type word2 = __builtin("word"); type fun1(T, U) = __builtin("fun"); type fun2(T, U) = __builtin("fun"); // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition_unknown.sol b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition_unknown.sol index 90072f198..0dc19b7f8 100644 --- a/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition_unknown.sol +++ b/test/libsolidity/syntaxTests/experimental/builtin/builtin_type_definition_unknown.sol @@ -2,6 +2,7 @@ pragma experimental solidity; type someUnknownType = __builtin("someUnknownType"); // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_function.sol b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_function.sol index da1169969..ef6331740 100644 --- a/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_function.sol +++ b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_function.sol @@ -7,6 +7,7 @@ function f(p: P, q: T(Q)) { let s: S; } // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_quantified_function.sol b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_quantified_function.sol index 91b734569..5113860bd 100644 --- a/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_quantified_function.sol +++ b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_quantified_function.sol @@ -5,6 +5,7 @@ function f(b: B) { let c: C; } // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_type_class.sol b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_type_class.sol index 8af0cce82..c78603516 100644 --- a/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_type_class.sol +++ b/test/libsolidity/syntaxTests/experimental/forall/undeclared_type_variable_in_type_class.sol @@ -10,6 +10,7 @@ instantiation T(Y): C { function f(self: T(Z)) {} } // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/experimental/import/experimental_solidity.sol b/test/libsolidity/syntaxTests/experimental/import/experimental_solidity.sol index a84ac0e75..011043f66 100644 --- a/test/libsolidity/syntaxTests/experimental/import/experimental_solidity.sol +++ b/test/libsolidity/syntaxTests/experimental/import/experimental_solidity.sol @@ -1,5 +1,6 @@ pragma experimental solidity; // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_multisource_not_all_enable.sol b/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_multisource_not_all_enable.sol index fe4125e84..79f226535 100644 --- a/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_multisource_not_all_enable.sol +++ b/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_multisource_not_all_enable.sol @@ -19,6 +19,7 @@ contract D { A a; } // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // ParserError 2141: (B.sol:0-29): File declares "pragma experimental solidity". If you want to enable the experimental mode, all source units must include the pragma. diff --git a/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_out_of_order_1.sol b/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_out_of_order_1.sol index d6741b0d3..1ceecba27 100644 --- a/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_out_of_order_1.sol +++ b/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_out_of_order_1.sol @@ -2,6 +2,7 @@ contract A {} pragma experimental solidity; // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // ParserError 8185: (45-45): Experimental pragma "solidity" can only be set at the beginning of the source unit. diff --git a/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_out_of_order_2.sol b/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_out_of_order_2.sol index 940bd3fbb..6d1ba15e2 100644 --- a/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_out_of_order_2.sol +++ b/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_out_of_order_2.sol @@ -10,6 +10,7 @@ struct A uint256 x; } // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // ParserError 8185: (83-89): Experimental pragma "solidity" can only be set at the beginning of the source unit. diff --git a/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_wrong_evm_version.sol b/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_wrong_evm_version.sol index 3e070535b..be5a30d52 100644 --- a/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_wrong_evm_version.sol +++ b/test/libsolidity/syntaxTests/experimental/import/experimental_solidity_wrong_evm_version.sol @@ -3,6 +3,7 @@ pragma experimental solidity; contract C {} // ==== +// experimental: true // EVMVersion: =constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_2.sol b/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_2.sol index bdc66e4ad..cc3146664 100644 --- a/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_2.sol +++ b/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_2.sol @@ -2,6 +2,7 @@ pragma experimental solidity; import std.stub as stub; // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_3.sol b/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_3.sol index 1bb340536..26b9589d0 100644 --- a/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_3.sol +++ b/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_3.sol @@ -2,6 +2,7 @@ pragma experimental solidity; import { identity } from std.stub; // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_4.sol b/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_4.sol index 64a67fe6c..36df8c7c1 100644 --- a/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_4.sol +++ b/test/libsolidity/syntaxTests/experimental/import/parsing_stdlib_import_4.sol @@ -2,6 +2,7 @@ pragma experimental solidity; import * as stub from std.stub; // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol b/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol index 72af2133f..bbb255568 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/import_and_call_stdlib_function.sol @@ -11,6 +11,7 @@ contract C } // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // bytecodeFormat: legacy diff --git a/test/libsolidity/syntaxTests/experimental/inference/instantiation_invalid_type_constructor.sol b/test/libsolidity/syntaxTests/experimental/inference/instantiation_invalid_type_constructor.sol index 0245deb1f..15c400932 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/instantiation_invalid_type_constructor.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/instantiation_invalid_type_constructor.sol @@ -6,6 +6,7 @@ function f() {} instantiation f: C {} // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/inference/instantiation_member_type_does_not_match_declaration.sol b/test/libsolidity/syntaxTests/experimental/inference/instantiation_member_type_does_not_match_declaration.sol index 1c845b8ee..47d282a1a 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/instantiation_member_type_does_not_match_declaration.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/instantiation_member_type_does_not_match_declaration.sol @@ -11,6 +11,7 @@ instantiation T: C { function f(self: U) {} } // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/inference/instantiation_not_for_class.sol b/test/libsolidity/syntaxTests/experimental/inference/instantiation_not_for_class.sol index c48fff74f..89217a56d 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/instantiation_not_for_class.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/instantiation_not_for_class.sol @@ -5,6 +5,7 @@ type U; instantiation T: U {} // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/inference/invalid_type_referenced.sol b/test/libsolidity/syntaxTests/experimental/inference/invalid_type_referenced.sol index ac097bf39..98bd7890c 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/invalid_type_referenced.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/invalid_type_referenced.sol @@ -7,6 +7,7 @@ class Self: C function g(self: Self, x: f); } // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/experimental/inference/monomorphic_function_call_type_mismatch.sol b/test/libsolidity/syntaxTests/experimental/inference/monomorphic_function_call_type_mismatch.sol index e7af573ae..d32b2ba0e 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/monomorphic_function_call_type_mismatch.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/monomorphic_function_call_type_mismatch.sol @@ -9,6 +9,7 @@ function run(a: U, b: T) { f(a, b); } // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call.sol b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call.sol index c9c7e0110..a6c44c0f3 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call.sol @@ -11,6 +11,7 @@ function run(a: T, b: U(T), c: U(U(T))) { f(b, b, c); } // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call_let_polymorphism.sol b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call_let_polymorphism.sol index 1a43d0807..159796a2b 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call_let_polymorphism.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call_let_polymorphism.sol @@ -13,6 +13,7 @@ function run(a: T, b: U) { g(b); } // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call_type_mismatch.sol b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call_type_mismatch.sol index 74f102a88..433a74c4b 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call_type_mismatch.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call_type_mismatch.sol @@ -10,6 +10,7 @@ function run(a: T(V)) { f(a); } // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type.sol b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type.sol index 85f810a9d..88e0da7de 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type.sol @@ -13,6 +13,7 @@ function run() { let y: T(V, Y, Z: D); } // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_abs_and_rep.sol b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_abs_and_rep.sol index ebebf6daf..b5311bd1b 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_abs_and_rep.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_abs_and_rep.sol @@ -18,6 +18,7 @@ function fun() { U.abs(t); } // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_instantiation_and_operators.sol b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_instantiation_and_operators.sol index c26436e06..93323dee0 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_instantiation_and_operators.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_instantiation_and_operators.sol @@ -46,6 +46,7 @@ function fun(a: T(int: P3), b: T(str: P4)) { C.foo(b, b); } // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameter_and_return.sol b/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameter_and_return.sol index 00cd7b120..1fe995332 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameter_and_return.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameter_and_return.sol @@ -10,6 +10,7 @@ function test(t: T, u: U) { t = f(u); } // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameters.sol b/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameters.sol index 7122cdd9e..47ccc6754 100644 --- a/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameters.sol +++ b/test/libsolidity/syntaxTests/experimental/inference/type_variable_multi_use_function_parameters.sol @@ -10,6 +10,7 @@ function test(t: T, u: U) { f(t, u); } // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function.sol b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function.sol index ba22a9fae..2b5236f79 100644 --- a/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function.sol +++ b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function.sol @@ -6,6 +6,7 @@ function f(a: A) {} forall (A, B) function g(a: A, b: B) {} // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_no_type_var.sol b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_no_type_var.sol index 66753fdd0..a6f5dd61f 100644 --- a/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_no_type_var.sol +++ b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_no_type_var.sol @@ -3,6 +3,7 @@ pragma experimental solidity; forall () function f(x: ()) {} // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_with_sorts.sol b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_with_sorts.sol index 1ab09fd2b..0e69f79b3 100644 --- a/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_with_sorts.sol +++ b/test/libsolidity/syntaxTests/experimental/parsing/forall_free_function_with_sorts.sol @@ -9,6 +9,7 @@ function f(a: A: Class1, b: B: Class1) {} forall A: Class1 function g(a: A) {} // ==== +// experimental: true // EVMVersion: >=constantinople // compileViaYul: true // ---- diff --git a/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class.sol b/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class.sol index aa0012eac..0dd5b74b5 100644 --- a/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class.sol +++ b/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class.sol @@ -3,6 +3,7 @@ pragma experimental solidity; forall (A, B) class Self: C {} // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // ParserError 5709: (45-50): Expected a function definition. diff --git a/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class_instantiation.sol b/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class_instantiation.sol index 31573447a..5d90e0e32 100644 --- a/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class_instantiation.sol +++ b/test/libsolidity/syntaxTests/experimental/parsing/forall_type_class_instantiation.sol @@ -7,6 +7,7 @@ class Self: C {} forall (A, B) instantiation T: C {} // ==== +// experimental: true // EVMVersion: >=constantinople // ---- // ParserError 5709: (72-85): Expected a function definition. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_empty_string_literal.sol b/test/libsolidity/syntaxTests/pragma/experimental_empty_string_literal.sol index 963ef5884..c97f46495 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_empty_string_literal.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_empty_string_literal.sol @@ -1,3 +1,5 @@ pragma experimental ""; +// ==== +// experimental: true // ---- // SyntaxError 3250: (0-23): Empty experimental feature name is invalid. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol b/test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol index 49fe597ec..204c4eada 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol @@ -1,4 +1,6 @@ pragma experimental experimental __test; +// ==== +// experimental: true // ---- // SyntaxError 6022: (0-40): Stray arguments. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_multiple_same_line.sol b/test/libsolidity/syntaxTests/pragma/experimental_multiple_same_line.sol index f88c0e0d8..f6210a871 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_multiple_same_line.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_multiple_same_line.sol @@ -1,3 +1,5 @@ pragma experimental unsupportedName unsupportedName; +// ==== +// experimental: true // ---- // SyntaxError 6022: (0-52): Stray arguments. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_pragma_duplicate.sol b/test/libsolidity/syntaxTests/pragma/experimental_pragma_duplicate.sol index 042b5464c..caebd6447 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_pragma_duplicate.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_pragma_duplicate.sol @@ -1,5 +1,7 @@ pragma experimental __test; pragma experimental __test; +// ==== +// experimental: true // ---- // Warning 2264: (0-27): Experimental features are turned on. Do not use experimental features on live deployments. // SyntaxError 1231: (28-55): Duplicate experimental feature name. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_pragma_empty.sol b/test/libsolidity/syntaxTests/pragma/experimental_pragma_empty.sol index d45e7e6af..2360d4e4d 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_pragma_empty.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_pragma_empty.sol @@ -1,3 +1,5 @@ pragma experimental; +// ==== +// experimental: true // ---- // SyntaxError 9679: (0-20): Experimental feature name is missing. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_pragma_unknown_string_literal.sol b/test/libsolidity/syntaxTests/pragma/experimental_pragma_unknown_string_literal.sol index 76be60ce8..4a52ec831 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_pragma_unknown_string_literal.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_pragma_unknown_string_literal.sol @@ -1,3 +1,5 @@ pragma experimental unsupportedName; +// ==== +// experimental: true // ---- // SyntaxError 8491: (0-36): Unsupported experimental feature name. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_pragma_without_experimental_mode.sol b/test/libsolidity/syntaxTests/pragma/experimental_pragma_without_experimental_mode.sol new file mode 100644 index 000000000..d5ba45b70 --- /dev/null +++ b/test/libsolidity/syntaxTests/pragma/experimental_pragma_without_experimental_mode.sol @@ -0,0 +1,4 @@ +pragma experimental __test; +// ---- +// SyntaxError 2816: (0-27): Experimental pragmas can only be used if the experimental mode has been enabled. +// Warning 2264: (0-27): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_test_warning.sol b/test/libsolidity/syntaxTests/pragma/experimental_test_warning.sol index 31f46fbb8..2706c2f31 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_test_warning.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_test_warning.sol @@ -1,3 +1,5 @@ pragma experimental __test; +// ==== +// experimental: true // ---- // Warning 2264: (0-27): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_unknown_number_literal.sol b/test/libsolidity/syntaxTests/pragma/experimental_unknown_number_literal.sol index f8e8267a0..4329b387b 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_unknown_number_literal.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_unknown_number_literal.sol @@ -1,3 +1,5 @@ pragma experimental 123; +// ==== +// experimental: true // ---- // SyntaxError 8491: (0-24): Unsupported experimental feature name. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_unknown_quoted_string_literal.sol b/test/libsolidity/syntaxTests/pragma/experimental_unknown_quoted_string_literal.sol index a08a0489b..9c6927510 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_unknown_quoted_string_literal.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_unknown_quoted_string_literal.sol @@ -1,3 +1,5 @@ pragma experimental "unsupportedName"; +// ==== +// experimental: true // ---- // SyntaxError 8491: (0-38): Unsupported experimental feature name. From 168b4a386a8c0bf5753d815d77ea3a21e102ad61 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 20 Nov 2025 07:44:36 +0100 Subject: [PATCH 1147/1340] Introduce experimental option in standard JSON --- libsolidity/interface/StandardCompiler.cpp | 59 +++- libsolidity/interface/StandardCompiler.h | 1 + scripts/ASTImportTest.sh | 2 +- .../input.json | 1 + .../input.json | 1 + .../standard_import_asm_json/input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../standard_import_ast/input.json | 1 + .../input.json | 1 + .../standard_import_with_comments/input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../standard_ir_ast_requested/input.json | 1 + .../input.json | 8 + .../output.json | 11 + .../standard_no_experimental_eof/input.json | 12 + .../standard_no_experimental_eof/output.json | 11 + .../input.json | 19 ++ .../output.json | 11 + .../input.json | 15 + .../output.json | 11 + .../input.json | 17 + .../output.json | 11 + .../input.json | 23 ++ .../output.json | 11 + .../input.json | 12 + .../output.json | 11 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../standard_yul_cfg_json_export/input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../input.json | 1 + .../standard_yul_ethdebug_eof/input.json | 1 + .../standard_yul_ethdebug_ir/input.json | 1 + .../input.json | 1 + test/ethdebugSchemaTests/input_file.json | 1 + test/ethdebugSchemaTests/input_file_eof.json | 1 + test/libsolidity/StandardCompiler.cpp | 315 +++++++++++++++--- 56 files changed, 548 insertions(+), 50 deletions(-) create mode 100644 test/cmdlineTests/standard_no_experimental_ast_import/input.json create mode 100644 test/cmdlineTests/standard_no_experimental_ast_import/output.json create mode 100644 test/cmdlineTests/standard_no_experimental_eof/input.json create mode 100644 test/cmdlineTests/standard_no_experimental_eof/output.json create mode 100644 test/cmdlineTests/standard_no_experimental_ethdebug/input.json create mode 100644 test/cmdlineTests/standard_no_experimental_ethdebug/output.json create mode 100644 test/cmdlineTests/standard_no_experimental_ir_ast_output/input.json create mode 100644 test/cmdlineTests/standard_no_experimental_ir_ast_output/output.json create mode 100644 test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/input.json create mode 100644 test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/output.json create mode 100644 test/cmdlineTests/standard_no_experimental_yul_ethdebug/input.json create mode 100644 test/cmdlineTests/standard_no_experimental_yul_ethdebug/output.json create mode 100644 test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/input.json create mode 100644 test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/output.json diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index d5502228b..419c3fac5 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -46,6 +46,8 @@ #include #include +#include + using namespace solidity; using namespace solidity::yul; using namespace solidity::frontend; @@ -298,10 +300,28 @@ bool isEthdebugRequested(Json const& _outputSelection) if (!_outputSelection.is_object()) return false; + static std::array const ethdebugArtifacts{"ethdebug", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"}; + for (auto const& fileRequests: _outputSelection) for (auto const& requests: fileRequests) for (auto const& request: requests) - if (request == "evm.bytecode.ethdebug" || request == "evm.deployedBytecode.ethdebug") + if (ranges::contains(ethdebugArtifacts, request.get())) + return true; + + return false; +} + +bool isExperimentalArtifactRequested(Json const& _outputSelection) +{ + static std::array const experimentalArtifacts{"irAst", "irOptimizedAst", "yulCFGJson"}; + + if (isEthdebugRequested(_outputSelection)) + return true; + + for (auto const& fileRequests: _outputSelection) + for (auto const& requests: fileRequests) + for (auto const& request: requests) + if (ranges::contains(experimentalArtifacts, request.get())) return true; return false; @@ -430,7 +450,7 @@ std::optional checkAuxiliaryInputKeys(Json const& _input) std::optional checkSettingsKeys(Json const& _input) { - static std::set keys{"debug", "evmVersion", "eofVersion", "libraries", "metadata", "modelChecker", "optimizer", "outputSelection", "remappings", "stopAfter", "viaIR"}; + static std::set keys{"debug", "evmVersion", "experimental", "eofVersion", "libraries", "metadata", "modelChecker", "optimizer", "outputSelection", "remappings", "stopAfter", "viaIR"}; return checkKeys(_input, keys, "settings"); } @@ -803,6 +823,13 @@ std::variant StandardCompiler::parseI if (auto result = checkSettingsKeys(settings)) return *result; + if (settings.contains("experimental")) + { + if (!settings["experimental"].is_boolean()) + return formatFatalError(Error::Type::JSONError, "\"settings.experimental\" must be a Boolean."); + ret.experimental = settings["experimental"].get(); + } + if (settings.contains("stopAfter")) { if (!settings["stopAfter"].is_string()) @@ -1213,6 +1240,22 @@ std::variant StandardCompiler::parseI if (ret.optimiserSettings.runYulOptimiser) solUnimplemented("Optimization is not yet supported with ethdebug."); + if (!ret.experimental) + { + if (ret.language == "SolidityAST" || ret.language == "EVMAssembly") + return formatFatalError(Error::Type::FatalError, "'SolidityAST' and 'EVMAssembly' inputs are experimental, and can only be used by toggling the 'settings.experimental' option."); + + if (ret.evmVersion.isExperimental()) + // TODO: Cover with test when the Amsterdam version is introduced + return formatFatalError(Error::Type::FatalError, fmt::format("EVM version {} is experimental, and can only be used by toggling the 'settings.experimental' option.", ret.evmVersion.name())); + + if (isExperimentalArtifactRequested(ret.outputSelection)) + return formatFatalError(Error::Type::FatalError, "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option."); + + if (ret.eofVersion) + return formatFatalError(Error::Type::FatalError, "'eofVersion' is experimental, and can only be used by toggling the 'settings.experimental' option."); + } + return {std::move(ret)}; } @@ -1238,6 +1281,7 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in solAssert(_inputsAndSettings.language == "EVMAssembly"); solAssert(_inputsAndSettings.sources.empty()); solAssert(_inputsAndSettings.jsonSources.size() == 1); + solAssert(_inputsAndSettings.experimental); if (!isBinaryRequested(_inputsAndSettings.outputSelection)) return Json::object(); @@ -1373,6 +1417,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu compilerStack.setMetadataHash(_inputsAndSettings.metadataHash); compilerStack.selectContracts(pipelineConfig(_inputsAndSettings.outputSelection)); compilerStack.setModelCheckerSettings(_inputsAndSettings.modelCheckerSettings); + compilerStack.setExperimental(_inputsAndSettings.experimental); Json errors = std::move(_inputsAndSettings.errors); @@ -1772,7 +1817,10 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) if (evmArtifactRequested(kind, "linkReferences")) bytecodeJSON["linkReferences"] = formatLinkReferences(selectedObject.bytecode->linkReferences); if (evmArtifactRequested(kind, "ethdebug")) + { + solAssert(_inputsAndSettings.experimental); bytecodeJSON["ethdebug"] = selectedObject.ethdebug; + } if (isDeployed && evmArtifactRequested(kind, "immutableReferences")) bytecodeJSON["immutableReferences"] = formatImmutableReferences(selectedObject.bytecode->immutableReferences); output["contracts"][sourceName][contractName]["evm"][kind] = bytecodeJSON; @@ -1784,11 +1832,16 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "evm.assembly", wildcardMatchesExperimental)) output["contracts"][sourceName][contractName]["evm"]["assembly"] = object.assembly->assemblyString(stack.debugInfoSelection()); if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "yulCFGJson", wildcardMatchesExperimental)) + { + solAssert(_inputsAndSettings.experimental, ""); output["contracts"][sourceName][contractName]["yulCFGJson"] = stack.cfgJson(); + } if (isEthdebugRequested(_inputsAndSettings.outputSelection)) + { + solAssert(_inputsAndSettings.experimental, ""); output["ethdebug"] = evmasm::ethdebug::resources({sourceName}, VersionString); - + } return output; } diff --git a/libsolidity/interface/StandardCompiler.h b/libsolidity/interface/StandardCompiler.h index 665e8b487..493e637cd 100644 --- a/libsolidity/interface/StandardCompiler.h +++ b/libsolidity/interface/StandardCompiler.h @@ -89,6 +89,7 @@ class StandardCompiler Json outputSelection; ModelCheckerSettings modelCheckerSettings = ModelCheckerSettings{}; bool viaIR = false; + bool experimental = false; }; /// Parses the input json (and potentially invokes the read callback) and either returns diff --git a/scripts/ASTImportTest.sh b/scripts/ASTImportTest.sh index 370aab9bd..3eff30562 100755 --- a/scripts/ASTImportTest.sh +++ b/scripts/ASTImportTest.sh @@ -139,7 +139,7 @@ function test_ast_import_export_equivalence echo ". += {\"sources\":" > _ast_json.json jq .sources expected.json >> _ast_json.json echo "}" >> _ast_json.json - echo "{\"language\": \"SolidityAST\", \"settings\": {\"outputSelection\": {\"*\": {\"\": [\"ast\"]}}}}" > standard_json.json + echo "{\"language\": \"SolidityAST\", \"settings\": {\"experimental\": true, \"outputSelection\": {\"*\": {\"\": [\"ast\"]}}}}" > standard_json.json jq --from-file _ast_json.json standard_json.json > standard_json_input.json # (re)import ast via standard json - and export it again as obtained result (silently) diff --git a/test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json b/test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json index d2ba25938..c21bbe63f 100644 --- a/test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json +++ b/test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json @@ -28,6 +28,7 @@ } }, "settings": { + "experimental": true, "outputSelection": { "*": { "": ["evm.assembly"] diff --git a/test/cmdlineTests/import_asm_json_standard_json_optimize/input.json b/test/cmdlineTests/import_asm_json_standard_json_optimize/input.json index d1d458259..6cb30f6f5 100644 --- a/test/cmdlineTests/import_asm_json_standard_json_optimize/input.json +++ b/test/cmdlineTests/import_asm_json_standard_json_optimize/input.json @@ -28,6 +28,7 @@ } }, "settings": { + "experimental": true, "outputSelection": { "*": { "": ["evm.assembly"] diff --git a/test/cmdlineTests/standard_import_asm_json/input.json b/test/cmdlineTests/standard_import_asm_json/input.json index 112f48045..a457d48e2 100644 --- a/test/cmdlineTests/standard_import_asm_json/input.json +++ b/test/cmdlineTests/standard_import_asm_json/input.json @@ -19,6 +19,7 @@ } }, "settings": { + "experimental": true, "outputSelection": { "*": { "": ["*"] diff --git a/test/cmdlineTests/standard_import_asm_json_immutable_references/input.json b/test/cmdlineTests/standard_import_asm_json_immutable_references/input.json index 0619f8d03..d193ff8a2 100644 --- a/test/cmdlineTests/standard_import_asm_json_immutable_references/input.json +++ b/test/cmdlineTests/standard_import_asm_json_immutable_references/input.json @@ -34,6 +34,7 @@ } }, "settings": { + "experimental": true, "outputSelection": { "*": { "": [ diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_opcode/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_opcode/input.json index 2e3e22cc4..732b05fd8 100644 --- a/test/cmdlineTests/standard_import_asm_json_invalid_opcode/input.json +++ b/test/cmdlineTests/standard_import_asm_json_invalid_opcode/input.json @@ -19,6 +19,7 @@ } }, "settings": { + "experimental": true, "outputSelection": { "*": { "": ["evm.bytecode"] diff --git a/test/cmdlineTests/standard_import_asm_json_link_references/input.json b/test/cmdlineTests/standard_import_asm_json_link_references/input.json index 47693fa14..4c5b45c14 100644 --- a/test/cmdlineTests/standard_import_asm_json_link_references/input.json +++ b/test/cmdlineTests/standard_import_asm_json_link_references/input.json @@ -26,6 +26,7 @@ } }, "settings": { + "experimental": true, "outputSelection": { "*": { "": [ diff --git a/test/cmdlineTests/standard_import_asm_json_no_output_selection/input.json b/test/cmdlineTests/standard_import_asm_json_no_output_selection/input.json index 1cd9c3c7d..ce746eb20 100644 --- a/test/cmdlineTests/standard_import_asm_json_no_output_selection/input.json +++ b/test/cmdlineTests/standard_import_asm_json_no_output_selection/input.json @@ -19,6 +19,7 @@ } }, "settings": { + "experimental": true, "outputSelection": { "*": { "": [ diff --git a/test/cmdlineTests/standard_import_ast/input.json b/test/cmdlineTests/standard_import_ast/input.json index 5ae7a5297..b33dcb57e 100644 --- a/test/cmdlineTests/standard_import_ast/input.json +++ b/test/cmdlineTests/standard_import_ast/input.json @@ -83,6 +83,7 @@ } }, "settings": { + "experimental": true, "outputSelection": { "*": { "": [ diff --git a/test/cmdlineTests/standard_import_ast_select_bytecode/input.json b/test/cmdlineTests/standard_import_ast_select_bytecode/input.json index 6458cb7e1..2bddcea9e 100644 --- a/test/cmdlineTests/standard_import_ast_select_bytecode/input.json +++ b/test/cmdlineTests/standard_import_ast_select_bytecode/input.json @@ -38,6 +38,7 @@ } }, "settings": { + "experimental": true, "outputSelection": { "*": { "*": [ diff --git a/test/cmdlineTests/standard_import_with_comments/input.json b/test/cmdlineTests/standard_import_with_comments/input.json index 4ed88177c..ef43cc0e1 100644 --- a/test/cmdlineTests/standard_import_with_comments/input.json +++ b/test/cmdlineTests/standard_import_with_comments/input.json @@ -84,6 +84,7 @@ } }, "settings": { + "experimental": true, "outputSelection": { "*": { "": [ diff --git a/test/cmdlineTests/standard_import_with_comments_simple/input.json b/test/cmdlineTests/standard_import_with_comments_simple/input.json index 21faca8c6..3ff3afc65 100644 --- a/test/cmdlineTests/standard_import_with_comments_simple/input.json +++ b/test/cmdlineTests/standard_import_with_comments_simple/input.json @@ -76,6 +76,7 @@ } }, "settings": { + "experimental": true, "outputSelection": { "*": { "": ["ast"] diff --git a/test/cmdlineTests/standard_irOptimized_ast_requested/input.json b/test/cmdlineTests/standard_irOptimized_ast_requested/input.json index 23f17f4ae..128724c84 100644 --- a/test/cmdlineTests/standard_irOptimized_ast_requested/input.json +++ b/test/cmdlineTests/standard_irOptimized_ast_requested/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.sol"]} }, "settings": { + "experimental": true, "outputSelection": {"*": {"*": ["irOptimizedAst"]}} } } diff --git a/test/cmdlineTests/standard_ir_ast_requested/input.json b/test/cmdlineTests/standard_ir_ast_requested/input.json index 07cfc13ed..829099045 100644 --- a/test/cmdlineTests/standard_ir_ast_requested/input.json +++ b/test/cmdlineTests/standard_ir_ast_requested/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.sol"]} }, "settings": { + "experimental": true, "outputSelection": {"*": {"*": ["irAst"]}} } } diff --git a/test/cmdlineTests/standard_no_experimental_ast_import/input.json b/test/cmdlineTests/standard_no_experimental_ast_import/input.json new file mode 100644 index 000000000..8ddd5ef8b --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_ast_import/input.json @@ -0,0 +1,8 @@ +{ + "language": "SolidityAST", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + } +} diff --git a/test/cmdlineTests/standard_no_experimental_ast_import/output.json b/test/cmdlineTests/standard_no_experimental_ast_import/output.json new file mode 100644 index 000000000..792d6b4c1 --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_ast_import/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'SolidityAST' and 'EVMAssembly' inputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "message": "'SolidityAST' and 'EVMAssembly' inputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_no_experimental_eof/input.json b/test/cmdlineTests/standard_no_experimental_eof/input.json new file mode 100644 index 000000000..8892caf27 --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_eof/input.json @@ -0,0 +1,12 @@ +{ + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + }, + "settings": { + "eofVersion": 1, + "evmVersion": "osaka" + } +} diff --git a/test/cmdlineTests/standard_no_experimental_eof/output.json b/test/cmdlineTests/standard_no_experimental_eof/output.json new file mode 100644 index 000000000..653fbc85a --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_eof/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'eofVersion' is experimental, and can only be used by toggling the 'settings.experimental' option.", + "message": "'eofVersion' is experimental, and can only be used by toggling the 'settings.experimental' option.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_no_experimental_ethdebug/input.json b/test/cmdlineTests/standard_no_experimental_ethdebug/input.json new file mode 100644 index 000000000..b11fdac34 --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_ethdebug/input.json @@ -0,0 +1,19 @@ +{ + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + }, + "settings": { + "viaIR": true, + "debug": { + "debugInfo": ["ethdebug"] + }, + "outputSelection": { + "A.sol": { + "A": ["ethdebug","evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"] + } + } + } +} diff --git a/test/cmdlineTests/standard_no_experimental_ethdebug/output.json b/test/cmdlineTests/standard_no_experimental_ethdebug/output.json new file mode 100644 index 000000000..6f132c1cd --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_ethdebug/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "message": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_no_experimental_ir_ast_output/input.json b/test/cmdlineTests/standard_no_experimental_ir_ast_output/input.json new file mode 100644 index 000000000..4b6c7776e --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_ir_ast_output/input.json @@ -0,0 +1,15 @@ +{ + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + }, + "settings": { + "outputSelection": { + "A.sol": { + "A": ["irAst"] + } + } + } +} diff --git a/test/cmdlineTests/standard_no_experimental_ir_ast_output/output.json b/test/cmdlineTests/standard_no_experimental_ir_ast_output/output.json new file mode 100644 index 000000000..6f132c1cd --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_ir_ast_output/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "message": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/input.json b/test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/input.json new file mode 100644 index 000000000..6944eacb7 --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/input.json @@ -0,0 +1,17 @@ +{ + "language": "Yul", + "sources": + { + "A": + { + "content": "{ let x := mload(0) sstore(add(x, 0), 0) }" + } + }, + "settings": { + "optimizer": { + "enabled": true + }, + "viaIR": true, + "outputSelection": {"*": {"*": ["yulCFGJson"]}} + } +} diff --git a/test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/output.json new file mode 100644 index 000000000..6f132c1cd --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "message": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_no_experimental_yul_ethdebug/input.json b/test/cmdlineTests/standard_no_experimental_yul_ethdebug/input.json new file mode 100644 index 000000000..9754b3d06 --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_yul_ethdebug/input.json @@ -0,0 +1,23 @@ +{ + "language": "Yul", + "sources": + { + "A": + { + "content": "{ let x := mload(0) sstore(add(x, 0), 0) }" + } + }, + "settings": + { + "viaIR": true, + "debug": { + "debugInfo": [ + "ethdebug" + ] + }, + "outputSelection": + { + "*": { "*": ["evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"], "": [ "*" ] } + } + } +} diff --git a/test/cmdlineTests/standard_no_experimental_yul_ethdebug/output.json b/test/cmdlineTests/standard_no_experimental_yul_ethdebug/output.json new file mode 100644 index 000000000..6f132c1cd --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_yul_ethdebug/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "message": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/input.json b/test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/input.json new file mode 100644 index 000000000..ea91a74eb --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/input.json @@ -0,0 +1,12 @@ +{ + "language": "Yul", + "sources": { + "A": + { + "content": "{ let x := mload(0) sstore(add(x, 0), 0) }" + } + }, + "settings": { + "outputSelection": {"*": {"*": ["irAst"]}} + } +} diff --git a/test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/output.json b/test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/output.json new file mode 100644 index 000000000..6f132c1cd --- /dev/null +++ b/test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "message": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json index 422a54f90..72f16c0ea 100644 --- a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "debug": { "debugInfo": [ diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json index 06b2d86e9..8d85b0ffa 100644 --- a/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "debug": { "debugInfo": [ diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json index 8ed44ca05..2fd0aecf8 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "optimizer": { "enabled": false diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json index 27c400f9e..58fb7b42f 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "optimizer": { "enabled": false diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json index 35c8f940e..292c86e37 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "optimizer": { "enabled": false diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json index e4681967f..2e4bb8ec9 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "optimizer": { "enabled": false diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json index 6239a7275..cd6a3d15b 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "optimizer": { "enabled": false diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json index fdb6c95b8..d9a5104f4 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "optimizer": { "enabled": false diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json index 5bc9d5467..f60133269 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "outputSelection": { "*": { diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json index 8952a241f..fb1e11bbc 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "outputSelection": { "*": { diff --git a/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json b/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json index ecb97bef2..7c56ed851 100644 --- a/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json +++ b/test/cmdlineTests/standard_undeployable_contract_all_outputs/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.sol"]} }, "settings": { + "experimental": true, "outputSelection": { "*": { "*": ["*", "ir", "irAst", "irOptimized", "irOptimizedAst"] diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/input.json b/test/cmdlineTests/standard_yul_cfg_json_export/input.json index b5353721e..24c3126a3 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/input.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.sol"]} }, "settings": { + "experimental": true, "optimizer": { "enabled": true }, diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json index e52867fa3..755d770fe 100644 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json @@ -8,6 +8,7 @@ } }, "settings": { + "experimental": true, "debug": {"debugInfo": ["ethdebug"]}, "outputSelection": { "*": {"*": ["ir", "irOptimized", "evm.bytecode.ethdebug"]} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json index a8c3436c1..b83ec361c 100644 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json @@ -8,6 +8,7 @@ } }, "settings": { + "experimental": true, "eofVersion": 1, "evmVersion": "osaka", "debug": {"debugInfo": ["ethdebug"]}, diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json index 16ef6ef33..eac38e3db 100644 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_verbatim_unimplemented/input.json @@ -8,6 +8,7 @@ } }, "settings": { + "experimental": true, "debug": {"debugInfo": ["ethdebug"]}, "outputSelection": { "*": {"*": ["evm.bytecode.ethdebug"]} diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json index 652620bed..89127b977 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.yul"]} }, "settings": { + "experimental": true, "outputSelection": { "*": {"*": ["evm.bytecode.ethdebug"]} } diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json index 67c5fedc7..9d5829df0 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.yul"]} }, "settings": { + "experimental": true, "outputSelection": { "*": {"*": ["evm.bytecode.ethdebug", "ir"]} } diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json index 17949761f..da8378a8b 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.yul"]} }, "settings": { + "experimental": true, "outputSelection": { "*": {"*": ["evm.bytecode.ethdebug", "irOptimized"]} } diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json index 5c5e9c5f7..fcfcaf3bd 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.yul"]} }, "settings": { + "experimental": true, "outputSelection": { "*": {"*": ["evm.deployedBytecode.ethdebug"]} } diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json index 655def5c1..2bedd407b 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.yul"]} }, "settings": { + "experimental": true, "outputSelection": { "*": {"*": ["evm.deployedBytecode.ethdebug", "evm.bytecode.ethdebug"]} } diff --git a/test/cmdlineTests/standard_yul_ethdebug_eof/input.json b/test/cmdlineTests/standard_yul_ethdebug_eof/input.json index 4e33c4267..3455e61d7 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_eof/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_eof/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.yul"]} }, "settings": { + "experimental": true, "eofVersion": 1, "evmVersion": "osaka", "outputSelection": { diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_ir/input.json index 67c5fedc7..9d5829df0 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_ir/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_ir/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.yul"]} }, "settings": { + "experimental": true, "outputSelection": { "*": {"*": ["evm.bytecode.ethdebug", "ir"]} } diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json index b08c9dcd7..2d3610908 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.yul"]} }, "settings": { + "experimental": true, "outputSelection": { "*": {"*": ["evm.bytecode.ethdebug", "irOptimize"]} } diff --git a/test/ethdebugSchemaTests/input_file.json b/test/ethdebugSchemaTests/input_file.json index 7daf7afd6..31c06ba8b 100644 --- a/test/ethdebugSchemaTests/input_file.json +++ b/test/ethdebugSchemaTests/input_file.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "debug": { "debugInfo": [ diff --git a/test/ethdebugSchemaTests/input_file_eof.json b/test/ethdebugSchemaTests/input_file_eof.json index 046206532..df0c734c1 100644 --- a/test/ethdebugSchemaTests/input_file_eof.json +++ b/test/ethdebugSchemaTests/input_file_eof.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "eofVersion": 1, "evmVersion": "osaka", "viaIR": true, diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 7be21863a..cffddcfd0 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -297,6 +297,13 @@ Json generateStandardJson(bool _viaIr, Json const& _debugInfoSelection, Json con return result; } +Json generateExperimentalStandardJson(bool _viaIr, Json const& _debugInfoSelection, Json const& _outputSelection, Code const& _code = SolidityCode(), bool _advancedOutputSelection = false) +{ + Json result = generateStandardJson(_viaIr, _debugInfoSelection, _outputSelection, _code, _advancedOutputSelection); + result["settings"]["experimental"] = true; + return result; +} + } // end anonymous namespace BOOST_AUTO_TEST_SUITE(StandardCompiler) @@ -1926,97 +1933,97 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) { static std::vector>>> tests{ { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"*"})), + generateExperimentalStandardJson(false, Json::array({"ethdebug"}), Json::array({"*"})), std::nullopt, }, { - generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"})), + generateExperimentalStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"})), std::nullopt, }, { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), + generateExperimentalStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), std::nullopt, }, { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), std::nullopt, }, { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), std::nullopt, }, { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"irOptimized"})), + generateExperimentalStandardJson(false, Json::array({"ethdebug"}), Json::array({"irOptimized"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"irOptimized"})), + generateExperimentalStandardJson(false, Json::array({"ethdebug"}), Json::array({"irOptimized"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug"})), + generateExperimentalStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"irOptimized", "evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(true, {}, Json::array({"irOptimized", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug"})), + generateExperimentalStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"irOptimized", "evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(true, {}, Json::array({"irOptimized", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(true, {}, Json::array({"irOptimized", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"irOptimized"}), YulCode()), + generateExperimentalStandardJson(true, Json::array({"ethdebug"}), Json::array({"irOptimized"}), YulCode()), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos; } }, { - generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"irOptimized"}), YulCode()), + generateExperimentalStandardJson(true, Json::array({"ethdebug"}), Json::array({"irOptimized"}), YulCode()), {} }, { - generateStandardJson(true, Json::array({"ethdebugs"}), Json::array({"irOptimized"}), YulCode()), {} + generateExperimentalStandardJson(true, Json::array({"ethdebugs"}), Json::array({"irOptimized"}), YulCode()), {} }, { - generateStandardJson( + generateExperimentalStandardJson( true, Json::array({"ethdebug"}), { {"fileA", {{"contractA", Json::array({"evm.deployedBytecode.bin"})}}}, {"fileB", {{"contractB", Json::array({"evm.bytecode.bin"})}}} @@ -2029,11 +2036,11 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) std::nullopt, }, { - generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"}), EvmAssemblyCode()), + generateExperimentalStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"}), EvmAssemblyCode()), std::nullopt, }, { - generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"}), SolidityAstCode()), + generateExperimentalStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"}), SolidityAstCode()), std::nullopt, }, }; @@ -2050,57 +2057,57 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) { static std::vector>>> tests{ { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), + generateExperimentalStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), std::nullopt }, { - generateStandardJson(false, {}, Json::array({"evm.bytecode.ethdebug"})), + generateExperimentalStandardJson(false, {}, Json::array({"evm.bytecode.ethdebug"})), std::nullopt }, { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), std::nullopt }, { - generateStandardJson(false, {}, Json::array({"evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(false, {}, Json::array({"evm.deployedBytecode.ethdebug"})), std::nullopt }, { - generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), std::nullopt }, { - generateStandardJson(false, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(false, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), std::nullopt }, { - generateStandardJson(true, Json::array({"location"}), Json::array({"evm.bytecode.ethdebug"})), + generateExperimentalStandardJson(true, Json::array({"location"}), Json::array({"evm.bytecode.ethdebug"})), std::nullopt }, { - generateStandardJson(true, Json::array({"location"}), Json::array({"evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(true, Json::array({"location"}), Json::array({"evm.deployedBytecode.ethdebug"})), std::nullopt }, { - generateStandardJson(true, Json::array({"location"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(true, Json::array({"location"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), std::nullopt }, { - generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), + generateExperimentalStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); } }, { - generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); } }, { - generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && @@ -2108,21 +2115,21 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) } }, { - generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug"})), + generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug"})), [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); } }, { - generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); } }, { - generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), + generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && @@ -2130,29 +2137,29 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) } }, { - generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "ir"})), + generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "ir"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); } }, { - generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug", "ir"})), + generateExperimentalStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug", "ir"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); } }, { - generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebugs"})), + generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode.ethdebugs"})), std::nullopt }, { - generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebugs"})), + generateExperimentalStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebugs"})), std::nullopt }, { - generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"})), + generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"})), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && @@ -2160,36 +2167,36 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) } }, { - generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "ir"}), YulCode()), + generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "ir"}), YulCode()), [](const Json& result) { return result.dump().find("/// ethdebug: enabled") != std::string::npos && result["contracts"]["fileA"]["object"]["evm"]["bytecode"].contains("ethdebug"); } }, { - generateStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug", "ir"}), YulCode()), + generateExperimentalStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug", "ir"}), YulCode()), std::nullopt }, { - generateStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"}), YulCode()), + generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"}), YulCode()), std::nullopt }, { - generateStandardJson(true, {}, Json::array({"evm.bytecode"})), + generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode"})), [](const Json& result) { return result.dump().find("ethdebug") == std::string::npos; } }, { - generateStandardJson(true, {}, Json::array({"evm.deployedBytecode"})), + generateExperimentalStandardJson(true, {}, Json::array({"evm.deployedBytecode"})), [](const Json& result) { return result.dump().find("ethdebug") == std::string::npos; } }, { - generateStandardJson( + generateExperimentalStandardJson( true, {}, { {"fileA", {{"contractA", Json::array({"evm.deployedBytecode.ethdebug"})}}}, {"fileB", {{"contractB", Json::array({"evm.bytecode.ethdebug"})}}} @@ -2219,7 +2226,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) BOOST_DATA_TEST_CASE(ethdebug_output_instructions_smoketest, boost::unit_test::data::make({"deployedBytecode", "bytecode"}), bytecodeType) { frontend::StandardCompiler compiler; - Json result = compiler.compile(generateStandardJson(true, {}, Json::array({std::string("evm.") + bytecodeType + ".ethdebug"}))); + Json result = compiler.compile(generateExperimentalStandardJson(true, {}, Json::array({std::string("evm.") + bytecodeType + ".ethdebug"}))); BOOST_REQUIRE(result["contracts"]["fileA"]["C"]["evm"][bytecodeType].contains("ethdebug")); bool creation = std::string(bytecodeType) == "bytecode"; Json ethdebugInstructionsToCheck = result["contracts"]["fileA"]["C"]["evm"][bytecodeType]["ethdebug"]; @@ -2259,6 +2266,222 @@ BOOST_DATA_TEST_CASE(ethdebug_output_instructions_smoketest, boost::unit_test::d } } +BOOST_AUTO_TEST_CASE(no_experimental_import_ast_solidity_evmasm) +{ + frontend::StandardCompiler compiler; + { + char const* input = R"( + { + "language": "SolidityAST", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + } + } + )"; + + Json parsedInput; + BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); + Json result = compiler.compile(parsedInput); + BOOST_CHECK(containsError(result, "FatalError", "'SolidityAST' and 'EVMAssembly' inputs are experimental, and can only be used by toggling the 'settings.experimental' option.")); + } + { + char const* input = R"( + { + "language": "SolidityAST", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { "name": "PUSH", "value": "0" } + ] + } + } + } + } + )"; + + Json parsedInput; + BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); + Json result = compiler.compile(parsedInput); + BOOST_CHECK(containsError(result, "FatalError", "'SolidityAST' and 'EVMAssembly' inputs are experimental, and can only be used by toggling the 'settings.experimental' option.")); + } +} + +BOOST_AUTO_TEST_CASE(no_experimental_invalid_output_selection) +{ + frontend::StandardCompiler compiler; + { + char const* input = R"( + { + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + }, + "settings": { + "outputSelection": { + "A.sol": { + "A": ["irAst"] + } + } + } + } + )"; + + Json parsedInput; + BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); + Json result = compiler.compile(parsedInput); + BOOST_CHECK( + containsError( + result, + "FatalError", "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option." + ) + ); + } + { + char const* input = R"( + { + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + }, + "settings": { + "outputSelection": { + "A.sol": { + "A": ["irOptimizedAst"] + } + } + } + } + )"; + + Json parsedInput; + BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); + Json result = compiler.compile(parsedInput); + BOOST_CHECK( + containsError( + result, + "FatalError", "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option." + ) + ); + } + { + char const* input = R"( + { + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + }, + "settings": { + "outputSelection": { + "A.sol": { + "A": ["yulCFGJson"] + } + } + } + } + )"; + + Json parsedInput; + BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); + Json result = compiler.compile(parsedInput); + BOOST_CHECK( + containsError( + result, + "FatalError", "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option." + ) + ); } +} + +BOOST_AUTO_TEST_CASE(no_experimental_ethdebug) +{ + frontend::StandardCompiler compiler; + char const* input = R"( + { + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + }, + "settings": { + "viaIR": true, + "debug": { + "debugInfo": ["ethdebug"] + }, + "outputSelection": { + "A.sol": { + "A": ["evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"] + } + } + } + } + )"; + + Json parsedInput; + BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); + Json result = compiler.compile(parsedInput); + BOOST_CHECK( + containsError( + result, + "FatalError", "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option." + ) + );} + +BOOST_AUTO_TEST_CASE(no_experimental_eof) +{ + frontend::StandardCompiler compiler; + char const* input = R"( + { + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + }, + "settings": { + "eofVersion": 1, + "evmVersion": "osaka" + } + } + )"; + + Json parsedInput; + BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); + Json result = compiler.compile(parsedInput); + BOOST_CHECK(containsError(result, "FatalError", "'eofVersion' is experimental, and can only be used by toggling the 'settings.experimental' option.")); +} + +BOOST_AUTO_TEST_CASE(experimental_non_boolean) +{ + frontend::StandardCompiler compiler; + char const* input = R"( + { + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + }, + "settings": { + "experimental": 1 + } + } + )"; + + Json parsedInput; + BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); + Json result = compiler.compile(parsedInput); + BOOST_CHECK(containsError(result, "JSONError", "\"settings.experimental\" must be a Boolean.")); +} + BOOST_AUTO_TEST_SUITE_END() } // end namespaces From 65a1e53235ab84b82ee8a03e1c118c9e8a8506a6 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 14 Jan 2026 20:21:26 +0100 Subject: [PATCH 1148/1340] Documentation for experimental mode --- docs/using-the-compiler.rst | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index dbc797079..a1ca2e066 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -281,6 +281,8 @@ Input Description "stopAfter": "parsing", // Optional: List of remappings "remappings": [ ":g=/dir" ], + // Optional: Experimental mode toggle (Default: false) + "experimental": false, // Optional: Optimizer settings "optimizer": { // Turn on the optimizer. Optional. Default: false. @@ -696,3 +698,42 @@ Error Types 13. ``YulException``: Error during Yul code generation - this should be reported as an issue. 14. ``Warning``: A warning, which didn't stop the compilation, but should be addressed if possible. 15. ``Info``: Information that the compiler thinks the user might find useful, but is not dangerous and does not necessarily need to be addressed. + +.. index:: ! Experimental mode, ! --experimental +.. _experimental-mode: + +Experimental Mode +***************** + +Experimental mode has been introduced as of version 0.8.34 as an additional safeguard when using experimental features. +Prior to version 0.8.34, all experimental features not requiring an explicit ``pragma experimental ...`` in source file(s) +were freely available to be used without any additional safeguards. Given that experimental features are sparsely documented, +if at all, often not adequately tested, and thus not intended for production use, we decided to add the ``--experimental`` +flag to the command line interface, and the analogous ``settings.experimental`` boolean setting to the Standard JSON interface. +Going forward, usage of any experimental feature will require the experimental mode to be toggled. + +The table below details all currently available experimental features. + ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ +| Feature | ID | Affects bytecode | Flag/pragma | ++=======================+==========================+==================+===================================================================+ +| AST import | ``ast-import`` | yes | ``--import-ast`` | ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ +| LSP | ``lsp`` | yes | ``--lsp`` | ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ +| EVM Assembly import | ``evmasm-import`` | yes | ``--import-asm-json`` | ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ +| Generic Solidity | ``generic-solidity`` | yes | ``pragma experimental solidity`` | ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ +| IR AST | ``ir-ast`` | no | ``--ir-ast-json``, ``--ir-optimized-ast-json`` | ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ +| EOF | ``eof`` | yes | ``--experimental-eof-version`` | ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ +| Osaka EVM | ``evm-osaka`` | yes | ``--evm-version osaka`` | ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ +| Ethdebug | ``ethdebug`` | no | ``--ethdebug``, ``--ethdebug-runtime``, ``--debug-info ethdebug`` | ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ +| Yul SSA CFG exporter | ``yul-ssa-cfg-exporter`` | no | ``--yul-cfg-json`` | ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ +| SSA CFG codegen | ``ssa-cfg-codegen`` | yes | ``--ssa-cfg-codegen`` (not yet on ``develop``) | ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ From d9fc8bec0eebb73bfb0a53eff9ab6bf1973cda4e Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 14 Jan 2026 20:31:31 +0100 Subject: [PATCH 1149/1340] Changelog --- Changelog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changelog.md b/Changelog.md index ed752bf35..823d346c7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,10 @@ Language Features: Compiler Features: +* Commandline Interface: Introduce `--experimental` flag required for enabling the experimental mode. +* General: Restrict the existing experimental features (`generic-solidity`, `lsp`, `ethdebug`, `eof`, `evm`, `ast-import`, `evmasm-import`, `ir-ast`, `ssa-cfg`) to experimental mode. +* Metadata: Store the state of the experimental mode in JSON and CBOR metadata. In CBOR this broadens the meaning of the existing `experimental` field, which used to indicate only the presence of certain experimental pragmas in the source. +* Standard JSON Interface: Introduce `settings.experimental` setting required for enabling the experimental mode. Bugfixes: From 23002f01c45f4a8d85c2e4b690a9115172d2f3c5 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 21 Jan 2026 11:53:58 +0100 Subject: [PATCH 1150/1340] Add experimental mode to metadata --- docs/metadata.rst | 11 +- docs/using-the-compiler.rst | 41 +- libsolidity/interface/CompilerStack.cpp | 19 +- test/cmdlineTests/metadata_experimental/args | 1 + .../metadata_experimental/input.sol | 4 + .../cmdlineTests/metadata_experimental/output | 556 ++++++++++++++++++ .../standard_metadata_experimental/args | 1 + .../standard_metadata_experimental/in.sol | 4 + .../standard_metadata_experimental/input.json | 18 + .../output.json | 77 +++ .../output.json | 4 +- test/libsolidity/Metadata.cpp | 8 +- 12 files changed, 719 insertions(+), 25 deletions(-) create mode 100644 test/cmdlineTests/metadata_experimental/args create mode 100644 test/cmdlineTests/metadata_experimental/input.sol create mode 100644 test/cmdlineTests/metadata_experimental/output create mode 100644 test/cmdlineTests/standard_metadata_experimental/args create mode 100644 test/cmdlineTests/standard_metadata_experimental/in.sol create mode 100644 test/cmdlineTests/standard_metadata_experimental/input.json create mode 100644 test/cmdlineTests/standard_metadata_experimental/output.json diff --git a/docs/metadata.rst b/docs/metadata.rst index 90513ee32..ee0bcbf1a 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -136,6 +136,12 @@ explanatory purposes. "compilationTarget": { "myDirectory/myFile.sol": "MyContract" }, + // Optional (false if omitted): Indicates whether experimental mode has been enabled. + // Always matches the value of the `experimental` flag in CBOR metadata. + // Note that experimental mode being enabled does not necessarily mean that any + // experimental features were actually used, or if they were, that those features + // affected the bytecode. + "experimental": true, // Required for Solidity: Addresses for libraries used. // Note that metadata has a different format for "libraries" field than the standard JSON input. // metadata format = { "MyLib.sol:MyLib": "0x123123..." } @@ -198,11 +204,12 @@ Below are all the possible fields: { "ipfs": "", - // If "bytecodeHash" was "bzzr1" in compiler settings not "ipfs" but "bzzr1" + // Present if "bytecodeHash" was "bzzr1" in compiler settings "bzzr1": "", // Previous versions were using "bzzr0" instead of "bzzr1" "bzzr0": "", - // If any experimental features that affect code generation are used + // Present if experimental mode has been enabled either via "--experimental" flag or + // "settings.experimental" option in Standard JSON "experimental": true, "solc": "" } diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index a1ca2e066..cd39a6f2d 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -282,7 +282,9 @@ Input Description // Optional: List of remappings "remappings": [ ":g=/dir" ], // Optional: Experimental mode toggle (Default: false) - "experimental": false, + // Makes it possible to use experimental features (but does not enable any such feature by itself). + // The use of this mode is recorded in contract metadata. + "experimental": true, // Optional: Optimizer settings "optimizer": { // Turn on the optimizer. Optional. Default: false. @@ -705,12 +707,29 @@ Error Types Experimental Mode ***************** -Experimental mode has been introduced as of version 0.8.34 as an additional safeguard when using experimental features. -Prior to version 0.8.34, all experimental features not requiring an explicit ``pragma experimental ...`` in source file(s) -were freely available to be used without any additional safeguards. Given that experimental features are sparsely documented, -if at all, often not adequately tested, and thus not intended for production use, we decided to add the ``--experimental`` -flag to the command line interface, and the analogous ``settings.experimental`` boolean setting to the Standard JSON interface. -Going forward, usage of any experimental feature will require the experimental mode to be toggled. +Some language and compiler features included in stable releases are not themselves considered stable. +They are sparsely documented, if at all, often not adequately tested, and thus not yet intended for production use. +In many cases it is possible to develop a big feature incrementally, with each iteration being already stable. +Sometimes, however, it is preferable to start with a prototype and stabilize it over multiple releases, while receiving feedback from users. +To prevent accidental use, such features can be only accessed by enabling the experimental mode. + +There are no backwards compatibility guarantees for experimental features. +They are subject to change in breaking ways in non-breaking releases of the compiler. +Only major changes affecting them are recorded in the changelog. + +To enable the experimental mode, use the ``--experimental`` flag on the command line, +or the analogous ``settings.experimental`` boolean setting in the Standard JSON input. + +Note that the use of this mode is recorded in the metadata: + +- ``experimental`` flag in CBOR metadata is set to ``true``, +- ``settings.experimental`` in JSON metadata is set to ``true``, + +.. note:: + Prior to version 0.8.34, most of the experimental features were usable without any extra safeguards. + Some were gated behind ``pragma experimental``, but this was not done consistently. + The information about them was also only recorded in CBOR metadata and even then not always. + The main goal of the experimental mode is to systematize this and make users fully aware when relying on features which are unfinished or not production-ready. The table below details all currently available experimental features. @@ -719,21 +738,19 @@ The table below details all currently available experimental features. +=======================+==========================+==================+===================================================================+ | AST import | ``ast-import`` | yes | ``--import-ast`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| LSP | ``lsp`` | yes | ``--lsp`` | +| LSP | ``lsp`` | no | ``--lsp`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ | EVM Assembly import | ``evmasm-import`` | yes | ``--import-asm-json`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| Generic Solidity | ``generic-solidity`` | yes | ``pragma experimental solidity`` | +| Core Solidity | ``core-solidity`` | yes | ``pragma experimental solidity`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ | IR AST | ``ir-ast`` | no | ``--ir-ast-json``, ``--ir-optimized-ast-json`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ | EOF | ``eof`` | yes | ``--experimental-eof-version`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| Osaka EVM | ``evm-osaka`` | yes | ``--evm-version osaka`` | +| Non-mainnet EVMs | ``evm`` | yes | ``--evm-version `` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ | Ethdebug | ``ethdebug`` | no | ``--ethdebug``, ``--ethdebug-runtime``, ``--debug-info ethdebug`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ | Yul SSA CFG exporter | ``yul-ssa-cfg-exporter`` | no | ``--yul-cfg-json`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| SSA CFG codegen | ``ssa-cfg-codegen`` | yes | ``--ssa-cfg-codegen`` (not yet on ``develop``) | -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 2ed72db0f..d7f2881c2 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -533,6 +533,10 @@ bool CompilerStack::analyze() if (!noErrors) return false; + for (Source const* source: m_sourceOrder) + if (source->ast && !m_experimental) + solAssert(source->ast->annotation().experimentalFeatures.empty()); + m_stackState = AnalysisSuccessful; return true; } @@ -767,10 +771,6 @@ bool CompilerStack::compile(State _stopAfter) std::map> otherCompilers; for (Source const* source: m_sourceOrder) - { - if (source->ast && !m_experimental) - solAssert(source->ast->annotation().experimentalFeatures.empty()); - for (ASTPointer const& node: source->ast->nodes()) if (auto contract = dynamic_cast(node.get())) if (isRequestedContract(*contract)) @@ -805,7 +805,6 @@ bool CompilerStack::compile(State _stopAfter) if (m_errorReporter.hasErrors()) return false; } - } solAssert(!m_errorReporter.hasErrors()); m_stackState = CompilationSuccessful; @@ -1827,6 +1826,8 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR if (_forIR) meta["settings"]["viaIR"] = _forIR; meta["settings"]["evmVersion"] = m_evmVersion.name(); + if (m_experimental) + meta["settings"]["experimental"] = m_experimental; if (m_eofVersion.has_value()) meta["settings"]["eofVersion"] = *m_eofVersion; meta["settings"]["compilationTarget"][_contract.contract->sourceUnitName()] = @@ -1938,10 +1939,14 @@ bytes CompilerStack::createCBORMetadata(Contract const& _contract, bool _forIR) if (m_metadataFormat == MetadataFormat::NoMetadata) return bytes{}; - bool const experimentalMode = !onlySafeExperimentalFeaturesActivated( + bool const usesExperimentalSyntax = !_contract.contract->sourceUnit().annotation().experimentalFeatures.empty(); + bool const onlySafeExperimentalFeatures = !onlySafeExperimentalFeaturesActivated( _contract.contract->sourceUnit().annotation().experimentalFeatures ); + if (m_eofVersion.has_value() || (usesExperimentalSyntax && !onlySafeExperimentalFeatures)) + solAssert(m_experimental, "Experimental mode not toggled"); + std::string meta = (_forIR == m_viaIR ? metadata(_contract) : createMetadata(_contract, _forIR)); MetadataCBOREncoder encoder; @@ -1953,7 +1958,7 @@ bytes CompilerStack::createCBORMetadata(Contract const& _contract, bool _forIR) else solAssert(m_metadataHash == MetadataHash::None, "Invalid metadata hash"); - if (experimentalMode || m_eofVersion.has_value()) + if (m_experimental) encoder.pushBool("experimental", true); if (m_metadataFormat == MetadataFormat::WithReleaseVersionTag) encoder.pushBytes("solc", VersionCompactBytes); diff --git a/test/cmdlineTests/metadata_experimental/args b/test/cmdlineTests/metadata_experimental/args new file mode 100644 index 000000000..4a834e560 --- /dev/null +++ b/test/cmdlineTests/metadata_experimental/args @@ -0,0 +1 @@ +--metadata --experimental --via-ir --ethdebug --no-cbor-metadata --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/metadata_experimental/input.sol b/test/cmdlineTests/metadata_experimental/input.sol new file mode 100644 index 000000000..a3a86cc8d --- /dev/null +++ b/test/cmdlineTests/metadata_experimental/input.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +contract C {} diff --git a/test/cmdlineTests/metadata_experimental/output b/test/cmdlineTests/metadata_experimental/output new file mode 100644 index 000000000..dc9145d5e --- /dev/null +++ b/test/cmdlineTests/metadata_experimental/output @@ -0,0 +1,556 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{ + "compilation": { + "compiler": { + "name": "solc", + "version": "" + }, + "sources": [ + { + "id": 0, + "path": "input.sol" + } + ] + } +} + +======= input.sol:C ======= +Metadata: +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"osaka","experimental":true,"libraries":{},"metadata":{"appendCBOR":false,"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[],"viaIR":true},"sources":{"input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} +Debug Data (ethdebug/format/program): +{ + "contract": { + "definition": { + "source": { + "id": 0 + } + }, + "name": "C" + }, + "environment": "create", + "instructions": [ + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 0, + "operation": { + "arguments": [ + "0x80" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 2, + "operation": { + "arguments": [ + "0x40" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 4, + "operation": { + "mnemonic": "MSTORE" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 5, + "operation": { + "mnemonic": "CALLVALUE" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 6, + "operation": { + "arguments": [ + "0x19" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 8, + "operation": { + "mnemonic": "JUMPI" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 9, + "operation": { + "arguments": [ + "0x0e" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 11, + "operation": { + "arguments": [ + "0x1d" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 13, + "operation": { + "mnemonic": "JUMP" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 14, + "operation": { + "mnemonic": "JUMPDEST" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 15, + "operation": { + "arguments": [ + "0x08" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 17, + "operation": { + "arguments": [ + "0x28" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 19, + "operation": { + "mnemonic": "DUP3" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 20, + "operation": { + "mnemonic": "CODECOPY" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 21, + "operation": { + "arguments": [ + "0x08" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 23, + "operation": { + "mnemonic": "SWAP1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 24, + "operation": { + "mnemonic": "RETURN" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 25, + "operation": { + "mnemonic": "JUMPDEST" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 26, + "operation": { + "arguments": [ + "0x23" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 28, + "operation": { + "mnemonic": "JUMP" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 29, + "operation": { + "mnemonic": "JUMPDEST" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 30, + "operation": { + "arguments": [ + "0x40" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 32, + "operation": { + "mnemonic": "MLOAD" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 33, + "operation": { + "mnemonic": "SWAP1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 34, + "operation": { + "mnemonic": "JUMP" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 35, + "operation": { + "mnemonic": "JUMPDEST" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 36, + "operation": { + "mnemonic": "PUSH0" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 37, + "operation": { + "mnemonic": "DUP1" + } + }, + { + "context": { + "code": { + "range": { + "length": 13, + "offset": 56 + }, + "source": { + "id": 0 + } + } + }, + "offset": 38, + "operation": { + "mnemonic": "REVERT" + } + } + ] +} diff --git a/test/cmdlineTests/standard_metadata_experimental/args b/test/cmdlineTests/standard_metadata_experimental/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_metadata_experimental/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_metadata_experimental/in.sol b/test/cmdlineTests/standard_metadata_experimental/in.sol new file mode 100644 index 000000000..a3a86cc8d --- /dev/null +++ b/test/cmdlineTests/standard_metadata_experimental/in.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +contract C {} diff --git a/test/cmdlineTests/standard_metadata_experimental/input.json b/test/cmdlineTests/standard_metadata_experimental/input.json new file mode 100644 index 000000000..fddbca92e --- /dev/null +++ b/test/cmdlineTests/standard_metadata_experimental/input.json @@ -0,0 +1,18 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["in.sol"]} + }, + "settings": { + "experimental": true, + "viaIR": true, + "debug": { + "debugInfo": [ + "ethdebug" + ] + }, + "outputSelection": { + "*": {"*": ["metadata", "ir"]} + } + } +} diff --git a/test/cmdlineTests/standard_metadata_experimental/output.json b/test/cmdlineTests/standard_metadata_experimental/output.json new file mode 100644 index 000000000..755a59486 --- /dev/null +++ b/test/cmdlineTests/standard_metadata_experimental/output.json @@ -0,0 +1,77 @@ +{ + "contracts": { + "C": { + "C": { + "ir": "/// ethdebug: enabled +/// @use-src 0:\"C\" +object \"C_2\" { + code { + /// @src 0:56:69 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_2() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"C_2_deployed\"), datasize(\"C_2_deployed\")) + + return(_1, datasize(\"C_2_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:56:69 + function constructor_C_2() { + + /// @src 0:56:69 + + } + /// @src 0:56:69 + + } + /// @use-src 0:\"C\" + object \"C_2_deployed\" { + code { + /// @src 0:56:69 + mstore(64, memoryguard(128)) + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + } + + data \".metadata\" hex\"\" + } + +} + +", + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"osaka\",\"experimental\":true,\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[],\"viaIR\":true},\"sources\":{\"C\":{\"keccak256\":\"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2\",\"dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS\"]}},\"version\":1}" + } + } + }, + "sources": { + "C": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json b/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json index 9dec9899a..16239faf1 100644 --- a/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json +++ b/test/cmdlineTests/standard_undeployable_contract_all_outputs/output.json @@ -35,7 +35,7 @@ "irAst": null, "irOptimized": "", "irOptimizedAst": null, - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"C\"},\"evmVersion\":\"osaka\",\"experimental\":true,\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", "storageLayout": { "storage": [], "types": null @@ -84,7 +84,7 @@ "irAst": null, "irOptimized": "", "irOptimizedAst": null, - "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"I\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"C\":\"I\"},\"evmVersion\":\"osaka\",\"experimental\":true,\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"C\":{\"keccak256\":\"0xa8b7bfe5eff9112e6573d2860721faef28e8920ee251acb458303a05c1ec7df2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a2333e25b5034de4f98729e0a737309ba8e0db4371016f312e8f991f6f01613f\",\"dweb:/ipfs/QmVLwS2grVYV6qiDvNmeEYWzb6WDne9Ze47NXERSLPM4fJ\"]}},\"version\":1}", "storageLayout": { "storage": [], "types": null diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index 0b6bae28d..8b54acc66 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -112,7 +112,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) auto const cborMetadata = requireParsedCBORMetadata(bytecode, metadataFormat); if (metadataHash == CompilerStack::MetadataHash::None) - BOOST_CHECK(cborMetadata.size() == (metadataFormat == CompilerStack::MetadataFormat::NoMetadata ? 0 : 1)); + BOOST_CHECK(cborMetadata.size() == (metadataFormat == CompilerStack::MetadataFormat::NoMetadata ? 0 : 2)); else { bytes hash; @@ -132,16 +132,20 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) if (metadataFormat != CompilerStack::MetadataFormat::NoMetadata) { - BOOST_CHECK(cborMetadata.size() == 2); + BOOST_CHECK(cborMetadata.size() == 3); BOOST_CHECK(cborMetadata.count(hashMethod) == 1); BOOST_CHECK(cborMetadata.at(hashMethod) == util::toHex(hash)); } } if (metadataFormat == CompilerStack::MetadataFormat::NoMetadata) + { BOOST_CHECK(cborMetadata.count("solc") == 0); + BOOST_CHECK(cborMetadata.count("experimental") == 0); + } else { + BOOST_CHECK(cborMetadata.at("experimental") == "true"); BOOST_CHECK(cborMetadata.count("solc") == 1); if (metadataFormat == CompilerStack::MetadataFormat::WithReleaseVersionTag) BOOST_CHECK(cborMetadata.at("solc") == util::toHex(VersionCompactBytes)); From cad1676fcda3e46fbde48df0c67e1320280871dc Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 6 Feb 2026 14:48:59 +0100 Subject: [PATCH 1151/1340] Address review comments --- docs/metadata.rst | 1 + docs/using-the-compiler.rst | 4 +- libsolidity/analysis/SyntaxChecker.cpp | 17 +- libsolidity/analysis/SyntaxChecker.h | 4 +- libsolidity/interface/CompilerStack.cpp | 30 ++-- libsolidity/interface/StandardCompiler.cpp | 24 +-- solc/CommandLineParser.cpp | 88 ++++++----- solc/CommandLineParser.h | 4 +- .../err | 2 +- .../input.json | 2 +- .../standard_eof_no_experimental/output.json | 11 ++ .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 0 .../input.json | 0 .../output.json | 4 +- .../standard_no_experimental_eof/output.json | 11 -- .../output.json | 11 -- .../output.json | 11 -- .../output.json | 11 -- .../output.json | 11 -- .../output.json | 11 -- .../output.json | 4 +- .../input.json | 1 + .../input.json | 1 + .../input.json | 2 +- .../output.json | 11 ++ .../input.json | 1 + .../input.json | 1 + .../input.json | 0 .../output.json | 11 ++ .../input.json | 0 .../output.json | 11 ++ .../input.json | 1 + .../input.json | 0 .../output.json | 11 ++ .../input.json | 1 + .../input.json | 1 + .../input.json | 0 .../output.json | 11 ++ test/libsolidity/Assembly.cpp | 2 +- .../FunctionDependencyGraphTest.cpp | 2 +- test/libsolidity/Metadata.cpp | 16 +- .../SolidityExpressionCompiler.cpp | 2 +- test/libsolidity/StandardCompiler.cpp | 149 +----------------- test/libsolidity/SyntaxTest.h | 2 +- .../smtCheckerTests/options/pragma.sol | 2 - ..._constructor_fixed_bytes_from_string_1.sol | 6 +- .../conflicting_settings_reverse.sol | 2 - ...flicting_settings_reverse_experimental.sol | 2 - .../abiEncoder/same_setting_twice.sol | 2 - .../abiEncoder/selected_twice_v2.sol | 2 - .../experimental_empty_string_literal.sol | 2 - .../experimental_multiple_experimental.sol | 2 - .../experimental_multiple_same_line.sol | 2 - .../pragma/experimental_pragma_empty.sol | 2 - ...rimental_pragma_unknown_string_literal.sol | 2 - ...ental_pragma_without_experimental_mode.sol | 7 +- .../experimental_unknown_number_literal.sol | 2 - ...rimental_unknown_quoted_string_literal.sol | 2 - test/lsp.py | 8 +- test/solc/CommandLineInterface.cpp | 8 - test/solc/CommandLineParser.cpp | 2 +- 64 files changed, 202 insertions(+), 351 deletions(-) rename test/cmdlineTests/{standard_no_experimental_eof => standard_eof_no_experimental}/input.json (65%) create mode 100644 test/cmdlineTests/standard_eof_no_experimental/output.json rename test/cmdlineTests/{import_asm_json_standard_json_optimize => standard_import_asm_json_no_optimize}/input.json (100%) rename test/cmdlineTests/{import_asm_json_standard_json_optimize => standard_import_asm_json_no_optimize}/output.json (100%) rename test/cmdlineTests/{import_asm_json_standard_json_no_optimize => standard_import_asm_json_optimize}/input.json (100%) rename test/cmdlineTests/{import_asm_json_standard_json_no_optimize => standard_import_asm_json_optimize}/output.json (100%) rename test/cmdlineTests/{standard_no_experimental_ast_import => standard_import_ast_no_experimental}/input.json (100%) rename test/cmdlineTests/{standard_no_experimental_ast_import => standard_import_ast_no_experimental}/output.json (59%) delete mode 100644 test/cmdlineTests/standard_no_experimental_eof/output.json delete mode 100644 test/cmdlineTests/standard_no_experimental_ethdebug/output.json delete mode 100644 test/cmdlineTests/standard_no_experimental_ir_ast_output/output.json delete mode 100644 test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/output.json delete mode 100644 test/cmdlineTests/standard_no_experimental_yul_ethdebug/output.json delete mode 100644 test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/output.json rename test/cmdlineTests/{standard_no_experimental_ethdebug => standard_output_selection_ethdebug_no_experimental}/input.json (79%) create mode 100644 test/cmdlineTests/standard_output_selection_ethdebug_no_experimental/output.json rename test/cmdlineTests/{standard_no_experimental_ir_ast_output => standard_output_selection_ir_ast_no_experimental}/input.json (100%) create mode 100644 test/cmdlineTests/standard_output_selection_ir_ast_no_experimental/output.json rename test/cmdlineTests/{standard_no_experimental_yul_cfg_json_export => standard_output_selection_yul_cfg_json_no_experimental}/input.json (100%) create mode 100644 test/cmdlineTests/standard_output_selection_yul_cfg_json_no_experimental/output.json rename test/cmdlineTests/{standard_no_experimental_yul_ethdebug => standard_yul_ethdebug_no_experimental}/input.json (100%) create mode 100644 test/cmdlineTests/standard_yul_ethdebug_no_experimental/output.json rename test/cmdlineTests/{standard_no_experimental_yul_ir_ast_requested => standard_yul_ir_ast_no_experimental}/input.json (100%) create mode 100644 test/cmdlineTests/standard_yul_ir_ast_no_experimental/output.json diff --git a/docs/metadata.rst b/docs/metadata.rst index ee0bcbf1a..b4a8d7cfc 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -203,6 +203,7 @@ Below are all the possible fields: .. code-block:: javascript { + // Present if "bytecodeHash" was "ipfs" in compiler settings "ipfs": "", // Present if "bytecodeHash" was "bzzr1" in compiler settings "bzzr1": "", diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index cd39a6f2d..15f4f859a 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -742,7 +742,7 @@ The table below details all currently available experimental features. +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ | EVM Assembly import | ``evmasm-import`` | yes | ``--import-asm-json`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| Core Solidity | ``core-solidity`` | yes | ``pragma experimental solidity`` | +| Generic Solidity | ``generic-solidity`` | yes | ``pragma experimental solidity`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ | IR AST | ``ir-ast`` | no | ``--ir-ast-json``, ``--ir-optimized-ast-json`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ @@ -752,5 +752,5 @@ The table below details all currently available experimental features. +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ | Ethdebug | ``ethdebug`` | no | ``--ethdebug``, ``--ethdebug-runtime``, ``--debug-info ethdebug`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| Yul SSA CFG exporter | ``yul-ssa-cfg-exporter`` | no | ``--yul-cfg-json`` | +| Yul SSA CFG exporter | ``ssa-cfg`` | no | ``--yul-cfg-json`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 8253eec49..e8777069f 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -83,12 +83,6 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma) else if (_pragma.literals()[0] == "experimental") { solAssert(m_sourceUnit, ""); - if (!m_experimental) - m_errorReporter.syntaxError( - 2816_error, - _pragma.location(), - "Experimental pragmas can only be used if the experimental mode has been enabled." - ); std::vector literals(_pragma.literals().begin() + 1, _pragma.literals().end()); if (literals.empty()) m_errorReporter.syntaxError( @@ -116,7 +110,16 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma) auto feature = ExperimentalFeatureNames.at(literal); m_sourceUnit->annotation().experimentalFeatures.insert(feature); if (!ExperimentalFeatureWithoutWarning.count(feature)) - m_errorReporter.warning(2264_error, _pragma.location(), "Experimental features are turned on. Do not use experimental features on live deployments."); + { + if (!m_experimental) + m_errorReporter.syntaxError( + 2816_error, + _pragma.location(), + "Experimental pragmas can only be used if experimental mode is enabled. To enable experimental mode, use the --experimental flag." + ); + else + m_errorReporter.warning(2264_error, _pragma.location(), "Experimental features are turned on. Do not use experimental features on live deployments."); + } if (feature == ExperimentalFeature::ABIEncoderV2) { diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index 9babfe47e..8a6e27cb1 100644 --- a/libsolidity/analysis/SyntaxChecker.h +++ b/libsolidity/analysis/SyntaxChecker.h @@ -46,7 +46,7 @@ class SyntaxChecker: private ASTConstVisitor public: /// @param _errorReporter provides the error logging functionality. /// @param _useYulOptimizer indicates whether Yul optimizer is enabled. - /// @param _experimental indicates whether the experimental toggle (option) is enabled. + /// @param _experimental indicates whether the experimental mode is enabled. SyntaxChecker(langutil::ErrorReporter& _errorReporter, bool _useYulOptimizer, bool _experimental): m_errorReporter(_errorReporter), m_useYulOptimizer(_useYulOptimizer), @@ -115,7 +115,7 @@ class SyntaxChecker: private ASTConstVisitor /// Flag that indicates whether we are inside an unchecked block. bool m_uncheckedArithmetic = false; - /// Flag that indicates whether experimental mode is toggled. + /// Flag that indicates whether the experimental mode is enabled. bool m_experimental = false; int m_inLoopDepth = 0; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index d7f2881c2..3583ae535 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -456,6 +456,19 @@ void CompilerStack::importASTs(std::map const& _sources) storeContractDefinitions(); } +namespace +{ + +bool onlySafeExperimentalFeaturesActivated(std::set const& _features) +{ + for (auto const feature: _features) + if (!ExperimentalFeatureWithoutWarning.contains(feature)) + return false; + return true; +} + +} + bool CompilerStack::analyze() { solAssert(m_stackState == ParsedAndImported, "Must call analyze only after parsing was successful."); @@ -535,7 +548,7 @@ bool CompilerStack::analyze() for (Source const* source: m_sourceOrder) if (source->ast && !m_experimental) - solAssert(source->ast->annotation().experimentalFeatures.empty()); + solAssert(onlySafeExperimentalFeaturesActivated(source->ast->annotation().experimentalFeatures)); m_stackState = AnalysisSuccessful; return true; @@ -1456,17 +1469,6 @@ void CompilerStack::annotateInternalFunctionIDs() } } -namespace -{ -bool onlySafeExperimentalFeaturesActivated(std::set const& features) -{ - for (auto const feature: features) - if (!ExperimentalFeatureWithoutWarning.count(feature)) - return false; - return true; -} -} - void CompilerStack::assembleYul( ContractDefinition const& _contract, std::shared_ptr _assembly, @@ -1940,12 +1942,12 @@ bytes CompilerStack::createCBORMetadata(Contract const& _contract, bool _forIR) return bytes{}; bool const usesExperimentalSyntax = !_contract.contract->sourceUnit().annotation().experimentalFeatures.empty(); - bool const onlySafeExperimentalFeatures = !onlySafeExperimentalFeaturesActivated( + bool const onlySafeExperimentalFeatures = onlySafeExperimentalFeaturesActivated( _contract.contract->sourceUnit().annotation().experimentalFeatures ); if (m_eofVersion.has_value() || (usesExperimentalSyntax && !onlySafeExperimentalFeatures)) - solAssert(m_experimental, "Experimental mode not toggled"); + solAssert(m_experimental, "Experimental mode not enabled"); std::string meta = (_forIR == m_viaIR ? metadata(_contract) : createMetadata(_contract, _forIR)); diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 419c3fac5..20e3fd45c 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -826,7 +826,7 @@ std::variant StandardCompiler::parseI if (settings.contains("experimental")) { if (!settings["experimental"].is_boolean()) - return formatFatalError(Error::Type::JSONError, "\"settings.experimental\" must be a Boolean."); + return formatFatalError(Error::Type::JSONError, "'settings.experimental' must be a Boolean."); ret.experimental = settings["experimental"].get(); } @@ -1230,11 +1230,13 @@ std::variant StandardCompiler::parseI } } - if ( - ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug && (ret.language == "Solidity" || ret.language == "Yul") && - !pipelineConfig(ret.outputSelection)[""][""].irCodegen && !isEthdebugRequested(ret.outputSelection) - ) - return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected."); + if (ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug) + { + if (!ret.experimental) + return formatFatalError(Error::Type::FatalError, "Ethdebug annotations are experimental and can only be included in ‘settings.debug.debugInfo’ by enabling the ‘settings.experimental’ option."); + if (!pipelineConfig(ret.outputSelection)[""][""].irCodegen && !isEthdebugRequested(ret.outputSelection)) + return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected."); + } if (isEthdebugRequested(ret.outputSelection)) if (ret.optimiserSettings.runYulOptimiser) @@ -1243,17 +1245,17 @@ std::variant StandardCompiler::parseI if (!ret.experimental) { if (ret.language == "SolidityAST" || ret.language == "EVMAssembly") - return formatFatalError(Error::Type::FatalError, "'SolidityAST' and 'EVMAssembly' inputs are experimental, and can only be used by toggling the 'settings.experimental' option."); + return formatFatalError(Error::Type::FatalError, "'SolidityAST' and 'EVMAssembly' inputs are experimental and can only be used with the 'settings.experimental' option enabled."); if (ret.evmVersion.isExperimental()) // TODO: Cover with test when the Amsterdam version is introduced - return formatFatalError(Error::Type::FatalError, fmt::format("EVM version {} is experimental, and can only be used by toggling the 'settings.experimental' option.", ret.evmVersion.name())); + return formatFatalError(Error::Type::FatalError, fmt::format("EVM version '{}' is experimental and can only be used with the 'settings.experimental' option enabled.", ret.evmVersion.name())); if (isExperimentalArtifactRequested(ret.outputSelection)) - return formatFatalError(Error::Type::FatalError, "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option."); + return formatFatalError(Error::Type::FatalError, "'irAst', 'irOptimizedAst', 'yulCFGJson', and 'ethdebug' outputs are experimental and can only be used with the 'settings.experimental' option enabled."); - if (ret.eofVersion) - return formatFatalError(Error::Type::FatalError, "'eofVersion' is experimental, and can only be used by toggling the 'settings.experimental' option."); + if (ret.eofVersion.has_value()) + return formatFatalError(Error::Type::FatalError, "'eofVersion' setting is experimental and can only be used with the 'settings.experimental' option enabled."); } return {std::move(ret)}; diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 6720b9fe8..b11adf037 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -164,21 +164,29 @@ void CommandLineParser::checkExperimental(std::vector const& _optio { solThrow( CommandLineValidationError, - "The following options are only available in experimental mode: " + joinOptionNames(_optionNames) + ". " + - "To enable experimental mode, use the --experimental flag." + fmt::format( + "The following options are only available in experimental mode: {}. " + "To enable experimental mode, use the --{} flag.", + joinOptionNames(_optionNames), + g_strExperimental + ) ); } - if (m_args.count(g_strEVMVersion)) + if (m_args.contains(g_strEVMVersion)) { - std::optional versionOption = EVMVersion::fromString(m_args[g_strEVMVersion].as()); - if (versionOption && versionOption->isExperimental()) + std::string versionOptionStr = m_args[g_strEVMVersion].as(); + std::optional versionOption = langutil::EVMVersion::fromString(versionOptionStr); + + if (versionOption.has_value() && versionOption->isExperimental()) // TODO: Cover with test when the Amsterdam version is introduced solThrow( CommandLineValidationError, fmt::format( - "EVM version '{}' is experimental and can only be selected in experimental mode." - "To enable experimental mode, use the --experimental flag", versionOption->name() + "EVM version '{}' is experimental and can only be selected in experimental mode. " + "To enable experimental mode, use the --{} flag", + m_options.output.evmVersion.name(), + g_strExperimental ) ); } @@ -502,7 +510,7 @@ void CommandLineParser::parseOutputSelection() // TODO: restrict EOF version to correct EVM version. } -po::options_description CommandLineParser::optionsDescription(bool _forHelp) +po::options_description CommandLineParser::optionsDescription() { // Declare the supported options. po::options_description desc((R"(solc, the Solidity commandline compiler. @@ -590,19 +598,18 @@ General Information)").c_str(), ("Select desired EVM version: " + annotatedEVMVersions + ".").c_str() ) ; - if (!_forHelp) // Note: We intentionally keep this undocumented for now. - outputOptions.add_options() - ( - g_strEOFVersion.c_str(), - // Declared as uint64_t, since uint8_t will be parsed as character by boost. - po::value()->value_name("version")->implicit_value(1), - "Select desired EOF version. Currently the only valid value is 1. " - "If not specified, legacy non-EOF bytecode will be generated." - ) - ( - g_strYul.c_str(), "The typed Yul dialect is no longer supported. For regular Yul compilation use --strict-assembly instead." - ) - ; + outputOptions.add_options() + ( + g_strEOFVersion.c_str(), + // Declared as uint64_t, since uint8_t will be parsed as character by boost. + po::value()->value_name("version")->implicit_value(1), + "Select desired EOF version. Currently the only valid value is 1. " + "If not specified, legacy non-EOF bytecode will be generated." + ) + ( + g_strYul.c_str(), "The typed Yul dialect is no longer supported. For regular Yul compilation use --strict-assembly instead." + ) + ; outputOptions.add_options() ( g_strExperimentalViaIR.c_str(), @@ -746,24 +753,21 @@ General Information)").c_str(), (CompilerOutputs::componentName(&CompilerOutputs::storageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in storage.") (CompilerOutputs::componentName(&CompilerOutputs::transientStorageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in transient storage.") ; - if (!_forHelp) // Note: We intentionally keep this undocumented for now. - { - outputComponents.add_options() - ( - CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson).c_str(), - "Control Flow Graph (CFG) of Yul code in JSON format." - ); - outputComponents.add_options() - ( - CompilerOutputs::componentName(&CompilerOutputs::ethdebug).c_str(), - "Ethdebug output of all contracts." - ); - outputComponents.add_options() - ( - CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime).c_str(), - "Ethdebug output of the runtime part of all contracts." - ); - } + outputComponents.add_options() + ( + CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson).c_str(), + "Control Flow Graph (CFG) of Yul code in JSON format." + ); + outputComponents.add_options() + ( + CompilerOutputs::componentName(&CompilerOutputs::ethdebug).c_str(), + "Ethdebug output of all contracts." + ); + outputComponents.add_options() + ( + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime).c_str(), + "Ethdebug output of the runtime part of all contracts." + ); desc.add(outputComponents); po::options_description extraOutput("Extra Output"); @@ -1167,7 +1171,11 @@ void CommandLineParser::processArgs() if (!m_options.experimental && m_options.output.debugInfoSelection->ethdebug) solThrow( CommandLineValidationError, - "--" + g_strDebugInfo + " ethdebug can only be used by toggling the --" + g_strExperimental + " flag." + fmt::format( + "Ethdebug annotations are experimental and can only be included in --{} in experimental mode. To enable experimental mode, use the --{} flag.", + g_strDebugInfo, + g_strExperimental + ) ); if (m_options.output.debugInfoSelection->snippet && !m_options.output.debugInfoSelection->location) diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 6c32b5ee0..bdb5fef2f 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -288,12 +288,12 @@ class CommandLineParser CommandLineOptions const& options() const { return m_options; } - static void printHelp(std::ostream& _out) { _out << optionsDescription(true /* _forHelp */); } + static void printHelp(std::ostream& _out) { _out << optionsDescription(); } private: /// @returns a specification of all named command-line options accepted by the compiler. /// The object can be used to parse command-line arguments or to generate the help screen. - static boost::program_options::options_description optionsDescription(bool _forHelp = false); + static boost::program_options::options_description optionsDescription(); /// @returns a specification of all positional command-line arguments accepted by the compiler. /// The object can be used to parse command-line arguments or to generate the help screen. diff --git a/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/err b/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/err index d8327f90b..a7b9ca900 100644 --- a/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/err +++ b/test/cmdlineTests/ethdebug_debuginfo_without_experimental_flag/err @@ -1 +1 @@ -Error: --debug-info ethdebug can only be used by toggling the --experimental flag. +Error: Ethdebug annotations are experimental and can only be included in --debug-info in experimental mode. To enable experimental mode, use the --experimental flag. diff --git a/test/cmdlineTests/standard_no_experimental_eof/input.json b/test/cmdlineTests/standard_eof_no_experimental/input.json similarity index 65% rename from test/cmdlineTests/standard_no_experimental_eof/input.json rename to test/cmdlineTests/standard_eof_no_experimental/input.json index 8892caf27..6ba6f727b 100644 --- a/test/cmdlineTests/standard_no_experimental_eof/input.json +++ b/test/cmdlineTests/standard_eof_no_experimental/input.json @@ -2,7 +2,7 @@ "language": "Solidity", "sources": { "A.sol": { - "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" } }, "settings": { diff --git a/test/cmdlineTests/standard_eof_no_experimental/output.json b/test/cmdlineTests/standard_eof_no_experimental/output.json new file mode 100644 index 000000000..22be8bde1 --- /dev/null +++ b/test/cmdlineTests/standard_eof_no_experimental/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'eofVersion' setting is experimental and can only be used with the 'settings.experimental' option enabled.", + "message": "'eofVersion' setting is experimental and can only be used with the 'settings.experimental' option enabled.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/import_asm_json_standard_json_optimize/input.json b/test/cmdlineTests/standard_import_asm_json_no_optimize/input.json similarity index 100% rename from test/cmdlineTests/import_asm_json_standard_json_optimize/input.json rename to test/cmdlineTests/standard_import_asm_json_no_optimize/input.json diff --git a/test/cmdlineTests/import_asm_json_standard_json_optimize/output.json b/test/cmdlineTests/standard_import_asm_json_no_optimize/output.json similarity index 100% rename from test/cmdlineTests/import_asm_json_standard_json_optimize/output.json rename to test/cmdlineTests/standard_import_asm_json_no_optimize/output.json diff --git a/test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json b/test/cmdlineTests/standard_import_asm_json_optimize/input.json similarity index 100% rename from test/cmdlineTests/import_asm_json_standard_json_no_optimize/input.json rename to test/cmdlineTests/standard_import_asm_json_optimize/input.json diff --git a/test/cmdlineTests/import_asm_json_standard_json_no_optimize/output.json b/test/cmdlineTests/standard_import_asm_json_optimize/output.json similarity index 100% rename from test/cmdlineTests/import_asm_json_standard_json_no_optimize/output.json rename to test/cmdlineTests/standard_import_asm_json_optimize/output.json diff --git a/test/cmdlineTests/standard_no_experimental_ast_import/input.json b/test/cmdlineTests/standard_import_ast_no_experimental/input.json similarity index 100% rename from test/cmdlineTests/standard_no_experimental_ast_import/input.json rename to test/cmdlineTests/standard_import_ast_no_experimental/input.json diff --git a/test/cmdlineTests/standard_no_experimental_ast_import/output.json b/test/cmdlineTests/standard_import_ast_no_experimental/output.json similarity index 59% rename from test/cmdlineTests/standard_no_experimental_ast_import/output.json rename to test/cmdlineTests/standard_import_ast_no_experimental/output.json index 792d6b4c1..d9e6d8cac 100644 --- a/test/cmdlineTests/standard_no_experimental_ast_import/output.json +++ b/test/cmdlineTests/standard_import_ast_no_experimental/output.json @@ -2,8 +2,8 @@ "errors": [ { "component": "general", - "formattedMessage": "'SolidityAST' and 'EVMAssembly' inputs are experimental, and can only be used by toggling the 'settings.experimental' option.", - "message": "'SolidityAST' and 'EVMAssembly' inputs are experimental, and can only be used by toggling the 'settings.experimental' option.", + "formattedMessage": "'SolidityAST' and 'EVMAssembly' inputs are experimental and can only be used with the 'settings.experimental' option enabled.", + "message": "'SolidityAST' and 'EVMAssembly' inputs are experimental and can only be used with the 'settings.experimental' option enabled.", "severity": "error", "type": "FatalError" } diff --git a/test/cmdlineTests/standard_no_experimental_eof/output.json b/test/cmdlineTests/standard_no_experimental_eof/output.json deleted file mode 100644 index 653fbc85a..000000000 --- a/test/cmdlineTests/standard_no_experimental_eof/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "'eofVersion' is experimental, and can only be used by toggling the 'settings.experimental' option.", - "message": "'eofVersion' is experimental, and can only be used by toggling the 'settings.experimental' option.", - "severity": "error", - "type": "FatalError" - } - ] -} diff --git a/test/cmdlineTests/standard_no_experimental_ethdebug/output.json b/test/cmdlineTests/standard_no_experimental_ethdebug/output.json deleted file mode 100644 index 6f132c1cd..000000000 --- a/test/cmdlineTests/standard_no_experimental_ethdebug/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", - "message": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", - "severity": "error", - "type": "FatalError" - } - ] -} diff --git a/test/cmdlineTests/standard_no_experimental_ir_ast_output/output.json b/test/cmdlineTests/standard_no_experimental_ir_ast_output/output.json deleted file mode 100644 index 6f132c1cd..000000000 --- a/test/cmdlineTests/standard_no_experimental_ir_ast_output/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", - "message": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", - "severity": "error", - "type": "FatalError" - } - ] -} diff --git a/test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/output.json deleted file mode 100644 index 6f132c1cd..000000000 --- a/test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", - "message": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", - "severity": "error", - "type": "FatalError" - } - ] -} diff --git a/test/cmdlineTests/standard_no_experimental_yul_ethdebug/output.json b/test/cmdlineTests/standard_no_experimental_yul_ethdebug/output.json deleted file mode 100644 index 6f132c1cd..000000000 --- a/test/cmdlineTests/standard_no_experimental_yul_ethdebug/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", - "message": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", - "severity": "error", - "type": "FatalError" - } - ] -} diff --git a/test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/output.json b/test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/output.json deleted file mode 100644 index 6f132c1cd..000000000 --- a/test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", - "message": "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option.", - "severity": "error", - "type": "FatalError" - } - ] -} diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json index 963bcd8d7..9342b91f5 100644 --- a/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json @@ -2,8 +2,8 @@ "errors": [ { "component": "general", - "formattedMessage": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", - "message": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", + "formattedMessage": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", + "message": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", "severity": "error", "type": "FatalError" } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/input.json index ad74649f5..514012ee7 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "optimizer": { "enabled": true diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/input.json index ad74649f5..514012ee7 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "optimizer": { "enabled": true diff --git a/test/cmdlineTests/standard_no_experimental_ethdebug/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_no_experimental/input.json similarity index 79% rename from test/cmdlineTests/standard_no_experimental_ethdebug/input.json rename to test/cmdlineTests/standard_output_selection_ethdebug_no_experimental/input.json index b11fdac34..5fca11155 100644 --- a/test/cmdlineTests/standard_no_experimental_ethdebug/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_no_experimental/input.json @@ -12,7 +12,7 @@ }, "outputSelection": { "A.sol": { - "A": ["ethdebug","evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"] + "A": ["evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"] } } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_no_experimental/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_no_experimental/output.json new file mode 100644 index 000000000..9342b91f5 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ethdebug_no_experimental/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", + "message": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/input.json index a684e0dc0..e1084799b 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_ir/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "optimizer": { "enabled": true diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/input.json index 1f09e3a70..235e3c855 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_optimize_iroptimized/input.json @@ -9,6 +9,7 @@ } }, "settings": { + "experimental": true, "viaIR": true, "optimizer": { "enabled": true diff --git a/test/cmdlineTests/standard_no_experimental_ir_ast_output/input.json b/test/cmdlineTests/standard_output_selection_ir_ast_no_experimental/input.json similarity index 100% rename from test/cmdlineTests/standard_no_experimental_ir_ast_output/input.json rename to test/cmdlineTests/standard_output_selection_ir_ast_no_experimental/input.json diff --git a/test/cmdlineTests/standard_output_selection_ir_ast_no_experimental/output.json b/test/cmdlineTests/standard_output_selection_ir_ast_no_experimental/output.json new file mode 100644 index 000000000..c85e0af01 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_ir_ast_no_experimental/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson', and 'ethdebug' outputs are experimental and can only be used with the 'settings.experimental' option enabled.", + "message": "'irAst', 'irOptimizedAst', 'yulCFGJson', and 'ethdebug' outputs are experimental and can only be used with the 'settings.experimental' option enabled.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/input.json b/test/cmdlineTests/standard_output_selection_yul_cfg_json_no_experimental/input.json similarity index 100% rename from test/cmdlineTests/standard_no_experimental_yul_cfg_json_export/input.json rename to test/cmdlineTests/standard_output_selection_yul_cfg_json_no_experimental/input.json diff --git a/test/cmdlineTests/standard_output_selection_yul_cfg_json_no_experimental/output.json b/test/cmdlineTests/standard_output_selection_yul_cfg_json_no_experimental/output.json new file mode 100644 index 000000000..c85e0af01 --- /dev/null +++ b/test/cmdlineTests/standard_output_selection_yul_cfg_json_no_experimental/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson', and 'ethdebug' outputs are experimental and can only be used with the 'settings.experimental' option enabled.", + "message": "'irAst', 'irOptimizedAst', 'yulCFGJson', and 'ethdebug' outputs are experimental and can only be used with the 'settings.experimental' option enabled.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json index c2c501c96..e4c9d17e5 100644 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json @@ -8,6 +8,7 @@ } }, "settings": { + "experimental": true, "debug": {"debugInfo": ["ethdebug"]}, "outputSelection": { "*": {"*": ["evm.assembly"]} diff --git a/test/cmdlineTests/standard_no_experimental_yul_ethdebug/input.json b/test/cmdlineTests/standard_yul_ethdebug_no_experimental/input.json similarity index 100% rename from test/cmdlineTests/standard_no_experimental_yul_ethdebug/input.json rename to test/cmdlineTests/standard_yul_ethdebug_no_experimental/input.json diff --git a/test/cmdlineTests/standard_yul_ethdebug_no_experimental/output.json b/test/cmdlineTests/standard_yul_ethdebug_no_experimental/output.json new file mode 100644 index 000000000..9342b91f5 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_no_experimental/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", + "message": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json index d7aec1f08..8074135b4 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_ir/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.yul"]} }, "settings": { + "experimental": true, "optimizer": { "enabled": true }, diff --git a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json index eeabdbcb9..417a42a31 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_optimize_iroptimized/input.json @@ -4,6 +4,7 @@ "C": {"urls": ["in.yul"]} }, "settings": { + "experimental": true, "optimizer": { "enabled": true }, diff --git a/test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/input.json b/test/cmdlineTests/standard_yul_ir_ast_no_experimental/input.json similarity index 100% rename from test/cmdlineTests/standard_no_experimental_yul_ir_ast_requested/input.json rename to test/cmdlineTests/standard_yul_ir_ast_no_experimental/input.json diff --git a/test/cmdlineTests/standard_yul_ir_ast_no_experimental/output.json b/test/cmdlineTests/standard_yul_ir_ast_no_experimental/output.json new file mode 100644 index 000000000..c85e0af01 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ir_ast_no_experimental/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'irAst', 'irOptimizedAst', 'yulCFGJson', and 'ethdebug' outputs are experimental and can only be used with the 'settings.experimental' option enabled.", + "message": "'irAst', 'irOptimizedAst', 'yulCFGJson', and 'ethdebug' outputs are experimental and can only be used with the 'settings.experimental' option enabled.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 85d6a3982..107865054 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -66,7 +66,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr _sourceCode) BOOST_CHECK(!!sourceUnit); Scoper::assignScopes(*sourceUnit); - BOOST_REQUIRE(SyntaxChecker(errorReporter, false, false).checkSyntax(*sourceUnit)); + BOOST_REQUIRE(SyntaxChecker(errorReporter, false /* _useYulOptimizer */, false /* _experimental */).checkSyntax(*sourceUnit)); GlobalContext globalContext(solidity::test::CommonOptions::get().evmVersion()); NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter, false); DeclarationTypeChecker declarationTypeChecker(errorReporter, solidity::test::CommonOptions::get().evmVersion()); diff --git a/test/libsolidity/FunctionDependencyGraphTest.cpp b/test/libsolidity/FunctionDependencyGraphTest.cpp index ded643e68..ba03d6f11 100644 --- a/test/libsolidity/FunctionDependencyGraphTest.cpp +++ b/test/libsolidity/FunctionDependencyGraphTest.cpp @@ -42,7 +42,7 @@ TestCase::TestResult FunctionDependencyGraphTest::run(std::ostream& _stream, std compiler().setSources(StringMap{{"", m_source}}); compiler().setViaIR(true); compiler().setOptimiserSettings(OptimiserSettings::none()); - // Experimental on by default as this is an extension of the initial experimental Solidity + // Experimental on by default as function dependency analysis is a part of Generic Solidity implementation compiler().setExperimental(true); if (!compiler().compile(CompilerStack::AnalysisSuccessful)) { diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index 8b54acc66..683522693 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -104,7 +104,6 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize); compilerStack.setMetadataHash(metadataHash); - compilerStack.setExperimental(true); // Experimental pragma requires it BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; std::string const& metadata = compilerStack.metadata("test"); @@ -112,7 +111,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) auto const cborMetadata = requireParsedCBORMetadata(bytecode, metadataFormat); if (metadataHash == CompilerStack::MetadataHash::None) - BOOST_CHECK(cborMetadata.size() == (metadataFormat == CompilerStack::MetadataFormat::NoMetadata ? 0 : 2)); + BOOST_CHECK(cborMetadata.size() == (metadataFormat == CompilerStack::MetadataFormat::NoMetadata ? 0 : 1)); else { bytes hash; @@ -132,25 +131,22 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) if (metadataFormat != CompilerStack::MetadataFormat::NoMetadata) { - BOOST_CHECK(cborMetadata.size() == 3); + BOOST_CHECK(cborMetadata.size() == 2); BOOST_CHECK(cborMetadata.count(hashMethod) == 1); BOOST_CHECK(cborMetadata.at(hashMethod) == util::toHex(hash)); } } if (metadataFormat == CompilerStack::MetadataFormat::NoMetadata) - { - BOOST_CHECK(cborMetadata.count("solc") == 0); - BOOST_CHECK(cborMetadata.count("experimental") == 0); - } + BOOST_CHECK(cborMetadata.empty()); else { - BOOST_CHECK(cborMetadata.at("experimental") == "true"); BOOST_CHECK(cborMetadata.count("solc") == 1); if (metadataFormat == CompilerStack::MetadataFormat::WithReleaseVersionTag) BOOST_CHECK(cborMetadata.at("solc") == util::toHex(VersionCompactBytes)); else BOOST_CHECK(cborMetadata.at("solc") == VersionStringStrict); + BOOST_CHECK(!cborMetadata.contains("experimental")); } } } @@ -217,7 +213,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) } if (metadataFormat == CompilerStack::MetadataFormat::NoMetadata) - BOOST_CHECK(cborMetadata.count("solc") == 0); + BOOST_CHECK(cborMetadata.empty()); else { BOOST_CHECK(cborMetadata.count("solc") == 1); @@ -225,7 +221,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) BOOST_CHECK(cborMetadata.at("solc") == util::toHex(VersionCompactBytes)); else BOOST_CHECK(cborMetadata.at("solc") == VersionStringStrict); - BOOST_CHECK(cborMetadata.count("experimental") == 1); + BOOST_CHECK(cborMetadata.contains("experimental")); BOOST_CHECK(cborMetadata.at("experimental") == "true"); } } diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index d64ffac5b..103732b98 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -126,7 +126,7 @@ bytes compileFirstExpression( ErrorReporter errorReporter(errors); GlobalContext globalContext(solidity::test::CommonOptions::get().evmVersion()); Scoper::assignScopes(*sourceUnit); - BOOST_REQUIRE(SyntaxChecker(errorReporter, false, false).checkSyntax(*sourceUnit)); + BOOST_REQUIRE(SyntaxChecker(errorReporter, false /* _useYulOptimizer */, false /* _experimental */).checkSyntax(*sourceUnit)); NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter, false); resolver.registerDeclarations(*sourceUnit); BOOST_REQUIRE_MESSAGE(resolver.resolveNamesAndTypes(*sourceUnit), "Resolving names failed"); diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index cffddcfd0..43b68223b 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -297,9 +297,9 @@ Json generateStandardJson(bool _viaIr, Json const& _debugInfoSelection, Json con return result; } -Json generateExperimentalStandardJson(bool _viaIr, Json const& _debugInfoSelection, Json const& _outputSelection, Code const& _code = SolidityCode(), bool _advancedOutputSelection = false) +Json generateExperimentalStandardJson(bool _viaIR, Json const& _debugInfoSelection, Json const& _outputSelection, Code const& _code = SolidityCode(), bool _advancedOutputSelection = false) { - Json result = generateStandardJson(_viaIr, _debugInfoSelection, _outputSelection, _code, _advancedOutputSelection); + Json result = generateStandardJson(_viaIR, _debugInfoSelection, _outputSelection, _code, _advancedOutputSelection); result["settings"]["experimental"] = true; return result; } @@ -2269,23 +2269,6 @@ BOOST_DATA_TEST_CASE(ethdebug_output_instructions_smoketest, boost::unit_test::d BOOST_AUTO_TEST_CASE(no_experimental_import_ast_solidity_evmasm) { frontend::StandardCompiler compiler; - { - char const* input = R"( - { - "language": "SolidityAST", - "sources": { - "A.sol": { - "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" - } - } - } - )"; - - Json parsedInput; - BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); - Json result = compiler.compile(parsedInput); - BOOST_CHECK(containsError(result, "FatalError", "'SolidityAST' and 'EVMAssembly' inputs are experimental, and can only be used by toggling the 'settings.experimental' option.")); - } { char const* input = R"( { @@ -2305,102 +2288,11 @@ BOOST_AUTO_TEST_CASE(no_experimental_import_ast_solidity_evmasm) Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); Json result = compiler.compile(parsedInput); - BOOST_CHECK(containsError(result, "FatalError", "'SolidityAST' and 'EVMAssembly' inputs are experimental, and can only be used by toggling the 'settings.experimental' option.")); + BOOST_CHECK(containsError(result, "FatalError", "'SolidityAST' and 'EVMAssembly' inputs are experimental and can only be used with the 'settings.experimental' option enabled.")); } } BOOST_AUTO_TEST_CASE(no_experimental_invalid_output_selection) -{ - frontend::StandardCompiler compiler; - { - char const* input = R"( - { - "language": "Solidity", - "sources": { - "A.sol": { - "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" - } - }, - "settings": { - "outputSelection": { - "A.sol": { - "A": ["irAst"] - } - } - } - } - )"; - - Json parsedInput; - BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); - Json result = compiler.compile(parsedInput); - BOOST_CHECK( - containsError( - result, - "FatalError", "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option." - ) - ); - } - { - char const* input = R"( - { - "language": "Solidity", - "sources": { - "A.sol": { - "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" - } - }, - "settings": { - "outputSelection": { - "A.sol": { - "A": ["irOptimizedAst"] - } - } - } - } - )"; - - Json parsedInput; - BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); - Json result = compiler.compile(parsedInput); - BOOST_CHECK( - containsError( - result, - "FatalError", "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option." - ) - ); - } - { - char const* input = R"( - { - "language": "Solidity", - "sources": { - "A.sol": { - "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" - } - }, - "settings": { - "outputSelection": { - "A.sol": { - "A": ["yulCFGJson"] - } - } - } - } - )"; - - Json parsedInput; - BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); - Json result = compiler.compile(parsedInput); - BOOST_CHECK( - containsError( - result, - "FatalError", "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option." - ) - ); } -} - -BOOST_AUTO_TEST_CASE(no_experimental_ethdebug) { frontend::StandardCompiler compiler; char const* input = R"( @@ -2412,13 +2304,9 @@ BOOST_AUTO_TEST_CASE(no_experimental_ethdebug) } }, "settings": { - "viaIR": true, - "debug": { - "debugInfo": ["ethdebug"] - }, "outputSelection": { "A.sol": { - "A": ["evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"] + "A": ["irOptimizedAst"] } } } @@ -2431,32 +2319,9 @@ BOOST_AUTO_TEST_CASE(no_experimental_ethdebug) BOOST_CHECK( containsError( result, - "FatalError", "'irAst', 'irOptimizedAst', 'yulCFGJson' and 'debugInfo.ethdebug' outputs are experimental, and can only be used by toggling the 'settings.experimental' option." + "FatalError", "'irAst', 'irOptimizedAst', 'yulCFGJson', and 'ethdebug' outputs are experimental and can only be used with the 'settings.experimental' option enabled." ) - );} - -BOOST_AUTO_TEST_CASE(no_experimental_eof) -{ - frontend::StandardCompiler compiler; - char const* input = R"( - { - "language": "Solidity", - "sources": { - "A.sol": { - "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" - } - }, - "settings": { - "eofVersion": 1, - "evmVersion": "osaka" - } - } - )"; - - Json parsedInput; - BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); - Json result = compiler.compile(parsedInput); - BOOST_CHECK(containsError(result, "FatalError", "'eofVersion' is experimental, and can only be used by toggling the 'settings.experimental' option.")); + ); } BOOST_AUTO_TEST_CASE(experimental_non_boolean) @@ -2479,7 +2344,7 @@ BOOST_AUTO_TEST_CASE(experimental_non_boolean) Json parsedInput; BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); Json result = compiler.compile(parsedInput); - BOOST_CHECK(containsError(result, "JSONError", "\"settings.experimental\" must be a Boolean.")); + BOOST_CHECK(containsError(result, "JSONError", "'settings.experimental' must be a Boolean.")); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index 9c52acd9b..946ada94c 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -53,7 +53,7 @@ class SyntaxTest: public AnalysisFramework, public solidity::test::CommonSyntaxT virtual void filterObtainedErrors(); bool m_optimiseYul{}; - bool m_experimental{false}; + bool m_experimental{}; std::string m_compileViaYul{}; langutil::Error::Severity m_minSeverity{}; PipelineStage m_stopAfter; diff --git a/test/libsolidity/smtCheckerTests/options/pragma.sol b/test/libsolidity/smtCheckerTests/options/pragma.sol index af2f644ad..b3e35ee02 100644 --- a/test/libsolidity/smtCheckerTests/options/pragma.sol +++ b/test/libsolidity/smtCheckerTests/options/pragma.sol @@ -4,8 +4,6 @@ contract C { assert(x > 0); } } -// ==== -// experimental: true // ---- // Warning 5523: (0-31): The SMTChecker pragma has been deprecated and will be removed in the future. Please use the "model checker engine" compiler setting to activate the SMTChecker instead. If the pragma is enabled, all engines will be used. // Warning 6328: (90-103): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\n\nTransaction trace:\nC.constructor()\nC.f(0) diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_constructor_fixed_bytes_from_string_1.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_constructor_fixed_bytes_from_string_1.sol index f31b9ca88..aa0317959 100644 --- a/test/libsolidity/smtCheckerTests/types/struct/struct_constructor_fixed_bytes_from_string_1.sol +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_constructor_fixed_bytes_from_string_1.sol @@ -1,4 +1,3 @@ -pragma experimental SMTChecker; contract C { struct S { int a; @@ -9,9 +8,6 @@ contract C { assert(S({a:2, b:""}).a == 0); // should fail } } -// ==== -// experimental: true // ---- -// Warning 5523: (0-31): The SMTChecker pragma has been deprecated and will be removed in the future. Please use the "model checker engine" compiler setting to activate the SMTChecker instead. If the pragma is enabled, all engines will be used. -// Warning 6328: (178-207): CHC: Assertion violation happens here. +// Warning 6328: (146-175): CHC: Assertion violation happens here. // Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol index 19a29b524..feacbbeb3 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse.sol @@ -1,7 +1,5 @@ pragma abicoder v1; pragma abicoder v2; -// ==== -// experimental: true // ---- // Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // SyntaxError 3845: (20-39): ABI coder has already been selected for this source unit. diff --git a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol index 022aa76a2..884d03132 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/conflicting_settings_reverse_experimental.sol @@ -1,7 +1,5 @@ pragma abicoder v1; pragma experimental ABIEncoderV2; -// ==== -// experimental: true // ---- // Warning 9511: (0-19): ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. // SyntaxError 8273: (20-53): ABI coder v1 has already been selected through "pragma abicoder v1". diff --git a/test/libsolidity/syntaxTests/abiEncoder/same_setting_twice.sol b/test/libsolidity/syntaxTests/abiEncoder/same_setting_twice.sol index fcdc2d5bb..0303bcb14 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/same_setting_twice.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/same_setting_twice.sol @@ -1,6 +1,4 @@ pragma experimental ABIEncoderV2; pragma abicoder v2; -// ==== -// experimental: true // ---- // SyntaxError 3845: (34-53): ABI coder has already been selected for this source unit. diff --git a/test/libsolidity/syntaxTests/abiEncoder/selected_twice_v2.sol b/test/libsolidity/syntaxTests/abiEncoder/selected_twice_v2.sol index 848efa83e..0b296da3a 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/selected_twice_v2.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/selected_twice_v2.sol @@ -1,5 +1,3 @@ pragma abicoder v2; pragma experimental ABIEncoderV2; -// ==== -// experimental: true // ---- diff --git a/test/libsolidity/syntaxTests/pragma/experimental_empty_string_literal.sol b/test/libsolidity/syntaxTests/pragma/experimental_empty_string_literal.sol index c97f46495..963ef5884 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_empty_string_literal.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_empty_string_literal.sol @@ -1,5 +1,3 @@ pragma experimental ""; -// ==== -// experimental: true // ---- // SyntaxError 3250: (0-23): Empty experimental feature name is invalid. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol b/test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol index 204c4eada..49fe597ec 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_multiple_experimental.sol @@ -1,6 +1,4 @@ pragma experimental experimental __test; -// ==== -// experimental: true // ---- // SyntaxError 6022: (0-40): Stray arguments. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_multiple_same_line.sol b/test/libsolidity/syntaxTests/pragma/experimental_multiple_same_line.sol index f6210a871..f88c0e0d8 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_multiple_same_line.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_multiple_same_line.sol @@ -1,5 +1,3 @@ pragma experimental unsupportedName unsupportedName; -// ==== -// experimental: true // ---- // SyntaxError 6022: (0-52): Stray arguments. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_pragma_empty.sol b/test/libsolidity/syntaxTests/pragma/experimental_pragma_empty.sol index 2360d4e4d..d45e7e6af 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_pragma_empty.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_pragma_empty.sol @@ -1,5 +1,3 @@ pragma experimental; -// ==== -// experimental: true // ---- // SyntaxError 9679: (0-20): Experimental feature name is missing. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_pragma_unknown_string_literal.sol b/test/libsolidity/syntaxTests/pragma/experimental_pragma_unknown_string_literal.sol index 4a52ec831..76be60ce8 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_pragma_unknown_string_literal.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_pragma_unknown_string_literal.sol @@ -1,5 +1,3 @@ pragma experimental unsupportedName; -// ==== -// experimental: true // ---- // SyntaxError 8491: (0-36): Unsupported experimental feature name. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_pragma_without_experimental_mode.sol b/test/libsolidity/syntaxTests/pragma/experimental_pragma_without_experimental_mode.sol index d5ba45b70..1d5e0595e 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_pragma_without_experimental_mode.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_pragma_without_experimental_mode.sol @@ -1,4 +1,7 @@ pragma experimental __test; +pragma experimental solidity; +// ==== +// EVMVersion: >=constantinople // ---- -// SyntaxError 2816: (0-27): Experimental pragmas can only be used if the experimental mode has been enabled. -// Warning 2264: (0-27): Experimental features are turned on. Do not use experimental features on live deployments. +// SyntaxError 2816: (0-27): Experimental pragmas can only be used if experimental mode is enabled. To enable experimental mode, use the --experimental flag. +// SyntaxError 2816: (28-57): Experimental pragmas can only be used if experimental mode is enabled. To enable experimental mode, use the --experimental flag. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_unknown_number_literal.sol b/test/libsolidity/syntaxTests/pragma/experimental_unknown_number_literal.sol index 4329b387b..f8e8267a0 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_unknown_number_literal.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_unknown_number_literal.sol @@ -1,5 +1,3 @@ pragma experimental 123; -// ==== -// experimental: true // ---- // SyntaxError 8491: (0-24): Unsupported experimental feature name. diff --git a/test/libsolidity/syntaxTests/pragma/experimental_unknown_quoted_string_literal.sol b/test/libsolidity/syntaxTests/pragma/experimental_unknown_quoted_string_literal.sol index 9c6927510..a08a0489b 100644 --- a/test/libsolidity/syntaxTests/pragma/experimental_unknown_quoted_string_literal.sol +++ b/test/libsolidity/syntaxTests/pragma/experimental_unknown_quoted_string_literal.sol @@ -1,5 +1,3 @@ pragma experimental "unsupportedName"; -// ==== -// experimental: true // ---- // SyntaxError 8491: (0-38): Unsupported experimental feature name. diff --git a/test/lsp.py b/test/lsp.py index 266a29fcc..d5bff2132 100755 --- a/test/lsp.py +++ b/test/lsp.py @@ -883,10 +883,10 @@ def main(self) -> int: print(f"{SGR_TEST_BEGIN}Testing {title} ...{SGR_RESET}") try: with JsonRpcProcess( - self.solc_path, - ["--experimental", "--lsp"], - trace_io=self.trace_io, - print_pid=self.print_solc_pid + self.solc_path, + ["--experimental", "--lsp"], + trace_io=self.trace_io, + print_pid=self.print_solc_pid ) as solc: test_fn(solc) self.test_counter.passed += 1 diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index d1c43be5b..2141b9e63 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -1412,14 +1412,6 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_ambiguous_import) BOOST_REQUIRE(!result.success); } -BOOST_AUTO_TEST_CASE(cli_ethdebug_no_ethdebug_in_help) -{ - OptionsReaderAndMessages result = runCLI({"solc", "--help"}); - BOOST_REQUIRE(result.stdoutContent.find("ethdebug") == std::string::npos); - // just in case - BOOST_REQUIRE(result.stderrContent.find("ethdebug") == std::string::npos); -} - BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_outputs) { TemporaryDirectory tempDir(TEST_CASE_NAME); diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 705ae3f73..4a32b0044 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -702,7 +702,7 @@ BOOST_AUTO_TEST_CASE(experimental_features_without_experimental_flag) BOOST_AUTO_TEST_CASE(debug_info_ethdebug_without_experimental_flag) { - std::string const expectedErrorMessage { "--debug-info ethdebug can only be used by toggling the --experimental flag." }; + std::string const expectedErrorMessage {"Ethdebug annotations are experimental and can only be included in --debug-info in experimental mode. To enable experimental mode, use the --experimental flag."}; auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedErrorMessage; }; std::vector const commandLineOptions{"solc", "--debug-info", "ethdebug", "contract.sol"}; From c61a2aea2434c8ccdb9c574c03bd0b054bc9665c Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 3 Mar 2026 09:43:43 +0100 Subject: [PATCH 1152/1340] Help output changes --- docs/using-the-compiler.rst | 30 +++++--- libsolidity/interface/StandardCompiler.cpp | 4 +- solc/CommandLineParser.cpp | 71 +++++++++++-------- solc/CommandLineParser.h | 3 + .../err | 2 +- .../output.json | 4 +- .../output.json | 4 +- .../output.json | 4 +- test/solc/CommandLineParser.cpp | 26 ++++--- 9 files changed, 90 insertions(+), 58 deletions(-) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 15f4f859a..ce82aa077 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -387,8 +387,11 @@ Input Description // - `` is the index of the first byte after that location. // - `snippet`: A single-line code snippet from the location indicated by `@src`. // The snippet is quoted and follows the corresponding `@src` annotation. - // - `*`: Wildcard value that can be used to request everything. - "debugInfo": ["location", "snippet"] + // - `ast-id`: Annotations of the form `@ast-id ` over elements that can be mapped back to a definition in the original Solidity file. + // `` is a node ID in the Solidity AST ('ast' output). + // - `ethdebug`: Ethdebug annotations (experimental). + // - `*`: Wildcard value that can be used to request all non-experimental components. + "debugInfo": ["location", "snippet", "ast-id", "ethdebug"] }, // Metadata settings (optional) "metadata": { @@ -439,13 +442,15 @@ Input Description // userdoc - User documentation (natspec) // metadata - Metadata // ir - Yul intermediate representation of the code before optimization - // irAst - AST of Yul intermediate representation of the code before optimization + // irAst - AST of Yul intermediate representation of the code before optimization (experimental) // irOptimized - Intermediate representation after optimization - // irOptimizedAst - AST of intermediate representation after optimization - // storageLayout - Slots, offsets and types of the contract's state variables in storage. - // transientStorageLayout - Slots, offsets and types of the contract's state variables in transient storage. + // irOptimizedAst - AST of intermediate representation after optimization (experimental) + // storageLayout - Slots, offsets and types of the contract's state variables in storage + // transientStorageLayout - Slots, offsets and types of the contract's state variables in transient storage // evm.assembly - New assembly format // evm.legacyAssembly - Old-style assembly format in JSON + // evm.bytecode.ethdebug - Debug information in ethdebug format (ethdebug/format/program schema). Can only be requested when compiling via IR. (experimental) + // evm.deployedBytecode.ethdebug - Like evm.bytecode.ethdebug, but for the runtime part of the contract (experimental) // evm.bytecode.functionDebugData - Debugging information at function level // evm.bytecode.object - Bytecode object // evm.bytecode.opcodes - Opcodes list @@ -456,6 +461,7 @@ Input Description // evm.deployedBytecode.immutableReferences - Map from AST ids to bytecode ranges that reference immutables // evm.methodIdentifiers - The list of function hashes // evm.gasEstimates - Function gas estimates + // yulCFGJson - Control Flow Graph (CFG) of the Single Static Assignment (SSA) form of the contract (experimental) // // Note that using `evm`, `evm.bytecode`, etc. will select every // target part of that output. Additionally, `*` can be used as a wildcard to request everything. @@ -608,6 +614,8 @@ Output Description "legacyAssembly": {}, // Bytecode and related details. "bytecode": { + // Ethdebug output (experimental) + "ethdebug": {/* ... */}, // Debugging data at the level of functions. "functionDebugData": { // Now follows a set of functions including compiler-internal and @@ -650,6 +658,8 @@ Output Description } }, "deployedBytecode": { + // Ethdebug output (experimental) + "ethdebug": {/* ... */}, /* ..., */ // The same layout as above. "immutableReferences": { // There are two references to the immutable with AST ID 3, both 32 bytes long. One is @@ -674,11 +684,15 @@ Output Description "internal": { "heavyLifting()": "infinite" } - } + }, + // Yul CFG representation of the SSA form (experimental) + "yulCFGJson": {/* ... */} } } } - } + }, + // Global Ethdebug output (experimental) + "ethdebug": {/* ... */ } } diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 20e3fd45c..74307bbc0 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -300,7 +300,7 @@ bool isEthdebugRequested(Json const& _outputSelection) if (!_outputSelection.is_object()) return false; - static std::array const ethdebugArtifacts{"ethdebug", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"}; + static std::array const ethdebugArtifacts{"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"}; for (auto const& fileRequests: _outputSelection) for (auto const& requests: fileRequests) @@ -1233,7 +1233,7 @@ std::variant StandardCompiler::parseI if (ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug) { if (!ret.experimental) - return formatFatalError(Error::Type::FatalError, "Ethdebug annotations are experimental and can only be included in ‘settings.debug.debugInfo’ by enabling the ‘settings.experimental’ option."); + return formatFatalError(Error::Type::FatalError, "Ethdebug annotations are experimental and can only be included in 'settings.debug.debugInfo' by enabling the 'settings.experimental' option."); if (!pipelineConfig(ret.outputSelection)[""][""].irCodegen && !isEthdebugRequested(ret.outputSelection)) return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected."); } diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index b11adf037..7f143695d 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -167,7 +167,7 @@ void CommandLineParser::checkExperimental(std::vector const& _optio fmt::format( "The following options are only available in experimental mode: {}. " "To enable experimental mode, use the --{} flag.", - joinOptionNames(_optionNames), + joinOptionNames(enabledOptions(_optionNames)), g_strExperimental ) ); @@ -436,6 +436,12 @@ void CommandLineParser::parseLibraryOption(std::string const& _input) } } +std::vector CommandLineParser::enabledOptions(std::vector const& _optionList) const +{ + auto optionEnabled = [&](std::string const& _option) { return m_args.contains(_option); }; + return _optionList | ranges::views::filter(optionEnabled) | ranges::to_vector; +} + void CommandLineParser::parseOutputSelection() { static auto outputSupported = [](InputMode _mode, std::string_view _outputName) @@ -578,7 +584,7 @@ General Information)").c_str(), std::string annotatedEVMVersions = util::joinHumanReadable( allEVMVersions | ranges::views::transform(annotateEVMVersion), ", ", - " or " + ", or " ); po::options_description outputOptions("Output Options"); @@ -603,14 +609,14 @@ General Information)").c_str(), g_strEOFVersion.c_str(), // Declared as uint64_t, since uint8_t will be parsed as character by boost. po::value()->value_name("version")->implicit_value(1), - "Select desired EOF version. Currently the only valid value is 1. " - "If not specified, legacy non-EOF bytecode will be generated." + "(experimental) Select desired EOF version. Currently the only valid value is 1. " + "If not specified, non-EOF bytecode will be generated." ) ( - g_strYul.c_str(), "The typed Yul dialect is no longer supported. For regular Yul compilation use --strict-assembly instead." + g_strYul.c_str(), + "(disabled) Switch to typed Yul mode. The typed Yul dialect is no longer supported. " + "For regular Yul compilation use --strict-assembly instead." ) - ; - outputOptions.add_options() ( g_strExperimentalViaIR.c_str(), "Deprecated synonym of --via-ir." @@ -628,8 +634,10 @@ General Information)").c_str(), g_strDebugInfo.c_str(), po::value()->default_value(util::toString(DebugInfoSelection::Default())), ("Debug info components to be included in the produced EVM assembly and Yul code. " - "Value can be all, none or a comma-separated list containing one or more of the " - "following components: " + util::joinHumanReadable(DebugInfoSelection::Default().selectedNames()) + ".").c_str() + "Value can be 'all', 'none' or a comma-separated list containing one or more of the " + "following components: " + util::joinHumanReadable(DebugInfoSelection::AllExceptExperimental().selectedNames()) + + ", or ethdebug (experimental). " + "Note that 'all' does not include experimental components.").c_str() ) ( g_strStopAfter.c_str(), @@ -661,21 +669,25 @@ General Information)").c_str(), ) ( g_strImportAst.c_str(), - ("Import ASTs to be compiled, assumes input holds the AST in compact JSON format. " - "Supported Inputs is the output of the --" + g_strStandardJSON + " or the one produced by " - "--" + g_strCombinedJson + " " + CombinedJsonRequests::componentName(&CombinedJsonRequests::ast)).c_str() + ("(experimental) Resume compilation from an abstract syntax tree (AST) representing already parsed and analyzed Solidity code. " + "In this mode the compiler expects exactly one input file, containing an AST in compact JSON format, as produced by" + " --" + CompilerOutputs::componentName(&CompilerOutputs::astCompactJson) + ", --" + + CombinedJsonRequests::componentName(&CombinedJsonRequests::ast) + " ast or the 'ast' output in Standard JSON.").c_str() ) ( g_strImportEvmAssemblerJson.c_str(), - ("Import EVM assembly in JSON format produced by --asm-json. " - "WARNING: --asm-json output is already optimized according to settings stored in metadata. " + ("(experimental) Resume compilation from EVM assembly. " + "In this mode the compiler expects exactly one input file, containing assembly in JSON format, " + "as produced by --" + g_strImportEvmAssemblerJson + "or the 'evm.legacyAssembly' output in Standard JSON. " + "WARNING: --" + g_strImportEvmAssemblerJson + " output is already optimized according to settings stored in metadata. " "Using --" + g_strOptimize + " in this mode is allowed, but not necessary under normal circumstances. " - "It forces the optimizer to run again and can produce bytecode that is not reproducible from metadata.").c_str() + "--" + g_strOptimize + " forces the optimizer to run again and can produce bytecode that is not reproducible from metadata.").c_str() ) ( g_strLSP.c_str(), - "Switch to language server mode (\"LSP\"). Allows the compiler to be used as an analysis backend " - "for your favourite IDE." + "(experimental) Switch to the language server mode. " + "Allows the compiler to be used as an analysis backend for your favourite IDE. " + "In this mode no input files are accepted and the compiler expects language server protocol (LSP) messages on standard input." ) ; desc.add(alternativeInputModes); @@ -743,30 +755,27 @@ General Information)").c_str(), (CompilerOutputs::componentName(&CompilerOutputs::binaryRuntime).c_str(), "Binary of the runtime part of the contracts in hex.") (CompilerOutputs::componentName(&CompilerOutputs::abi).c_str(), "ABI specification of the contracts.") (CompilerOutputs::componentName(&CompilerOutputs::ir).c_str(), "Intermediate Representation (IR) of all contracts.") - (CompilerOutputs::componentName(&CompilerOutputs::irAstJson).c_str(), "AST of Intermediate Representation (IR) of all contracts in a compact JSON format.") + (CompilerOutputs::componentName(&CompilerOutputs::irAstJson).c_str(), "(experimental) AST of Intermediate Representation (IR) of all contracts in a compact JSON format.") (CompilerOutputs::componentName(&CompilerOutputs::irOptimized).c_str(), "Optimized Intermediate Representation (IR) of all contracts.") - (CompilerOutputs::componentName(&CompilerOutputs::irOptimizedAstJson).c_str(), "AST of optimized Intermediate Representation (IR) of all contracts in a compact JSON format.") + (CompilerOutputs::componentName(&CompilerOutputs::irOptimizedAstJson).c_str(), "(experimental) AST of optimized Intermediate Representation (IR) of all contracts in a compact JSON format.") (CompilerOutputs::componentName(&CompilerOutputs::signatureHashes).c_str(), "Function signature hashes of the contracts.") (CompilerOutputs::componentName(&CompilerOutputs::natspecUser).c_str(), "Natspec user documentation of all contracts.") (CompilerOutputs::componentName(&CompilerOutputs::natspecDev).c_str(), "Natspec developer documentation of all contracts.") (CompilerOutputs::componentName(&CompilerOutputs::metadata).c_str(), "Combined Metadata JSON whose IPFS hash is stored on-chain.") (CompilerOutputs::componentName(&CompilerOutputs::storageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in storage.") (CompilerOutputs::componentName(&CompilerOutputs::transientStorageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in transient storage.") - ; - outputComponents.add_options() ( CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson).c_str(), - "Control Flow Graph (CFG) of Yul code in JSON format." - ); - outputComponents.add_options() + "(experimental) Control Flow Graph (CFG) of Yul code in Static Single Assignment (SSA) form in JSON format." + ) ( CompilerOutputs::componentName(&CompilerOutputs::ethdebug).c_str(), - "Ethdebug output of all contracts." - ); - outputComponents.add_options() + "(experimental) Debug information in ethdebug format for all contracts (ethdebug/format/program schema). " + "When enabled, an extra global output containing the ethdebug/format/info/resources schema with information shared by all contracts is automatically enabled as well." + ) ( CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime).c_str(), - "Ethdebug output of the runtime part of all contracts." + ("(experimental) Like --" + CompilerOutputs::componentName(&CompilerOutputs::ethdebug) + ", but for the runtime part of the contracts.").c_str() ); desc.add(outputComponents); @@ -914,9 +923,9 @@ General Information)").c_str(), experimentalOptions.add_options() ( g_strExperimental.c_str(), - "Enable experimental mode. Note that enabling experimental mode by itself will not " - "enable any experimental features, but will simply allow for such features to be enabled in the " - "usual manner, whether by using specific flags or pragmas." + "Enable experimental mode. " + "This flag does not activate any experimental features on its own - " + "it unlocks the ability to use them through the usual flags and pragmas." ) ; desc.add(experimentalOptions); diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index bdb5fef2f..9d9dc28b6 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -324,6 +324,9 @@ class CommandLineParser void parseOutputSelection(); + /// Returns a list of enabled options from @_optionList + std::vector enabledOptions(std::vector const& _optionList) const; + void checkMutuallyExclusive(std::vector const& _optionNames); void checkExperimental(std::vector const& _optionNames) const; size_t countEnabledOptions(std::vector const& _optionNames) const; diff --git a/test/cmdlineTests/experimental_feature_without_experimental_flag/err b/test/cmdlineTests/experimental_feature_without_experimental_flag/err index 1b73066ce..b21b7318e 100644 --- a/test/cmdlineTests/experimental_feature_without_experimental_flag/err +++ b/test/cmdlineTests/experimental_feature_without_experimental_flag/err @@ -1 +1 @@ -Error: The following options are only available in experimental mode: --lsp, --import-ast, --import-asm-json, --ir-ast-json, --ir-optimized-ast-json, --yul-cfg-json, --ethdebug, --ethdebug-runtime, --experimental-eof-version. To enable experimental mode, use the --experimental flag. +Error: The following options are only available in experimental mode: --ir-ast-json. To enable experimental mode, use the --experimental flag. diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json index 9342b91f5..ab744acc1 100644 --- a/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_incompatible/output.json @@ -2,8 +2,8 @@ "errors": [ { "component": "general", - "formattedMessage": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", - "message": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", + "formattedMessage": "Ethdebug annotations are experimental and can only be included in 'settings.debug.debugInfo' by enabling the 'settings.experimental' option.", + "message": "Ethdebug annotations are experimental and can only be included in 'settings.debug.debugInfo' by enabling the 'settings.experimental' option.", "severity": "error", "type": "FatalError" } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_no_experimental/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_no_experimental/output.json index 9342b91f5..ab744acc1 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_no_experimental/output.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_no_experimental/output.json @@ -2,8 +2,8 @@ "errors": [ { "component": "general", - "formattedMessage": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", - "message": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", + "formattedMessage": "Ethdebug annotations are experimental and can only be included in 'settings.debug.debugInfo' by enabling the 'settings.experimental' option.", + "message": "Ethdebug annotations are experimental and can only be included in 'settings.debug.debugInfo' by enabling the 'settings.experimental' option.", "severity": "error", "type": "FatalError" } diff --git a/test/cmdlineTests/standard_yul_ethdebug_no_experimental/output.json b/test/cmdlineTests/standard_yul_ethdebug_no_experimental/output.json index 9342b91f5..ab744acc1 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_no_experimental/output.json +++ b/test/cmdlineTests/standard_yul_ethdebug_no_experimental/output.json @@ -2,8 +2,8 @@ "errors": [ { "component": "general", - "formattedMessage": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", - "message": "Ethdebug annotations are experimental and can only be included in \u2018settings.debug.debugInfo\u2019 by enabling the \u2018settings.experimental\u2019 option.", + "formattedMessage": "Ethdebug annotations are experimental and can only be included in 'settings.debug.debugInfo' by enabling the 'settings.experimental' option.", + "message": "Ethdebug annotations are experimental and can only be included in 'settings.debug.debugInfo' by enabling the 'settings.experimental' option.", "severity": "error", "type": "FatalError" } diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 4a32b0044..6d9153381 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -682,27 +682,33 @@ BOOST_AUTO_TEST_CASE(experimental_features_without_experimental_flag) "--ethdebug-runtime" }; - std::string const expectedErrorMessage { - "The following options are only available in experimental mode: --lsp, --import-ast, --import-asm-json, " - "--ir-ast-json, --ir-optimized-ast-json, --yul-cfg-json, --ethdebug, --ethdebug-runtime, --experimental-eof-version. " - "To enable experimental mode, use the --experimental flag." - }; - + std::string expectedErrorMessage; auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedErrorMessage; }; for (auto const& experimentalFeature: experimentalFeatures) { + expectedErrorMessage = + fmt::format( + "The following options are only available in experimental mode: {}. " + "To enable experimental mode, use the --experimental flag.", + experimentalFeature + ); + std::vector const commandLineOptions{"solc", experimentalFeature, "contract.sol"}; BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage); } std::vector const commandLineOptions{"solc", "--experimental-eof-version", "1", "contract.sol"}; + expectedErrorMessage = "The following options are only available in experimental mode: --experimental-eof-version. To enable experimental mode, use the --experimental flag."; BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage); } BOOST_AUTO_TEST_CASE(debug_info_ethdebug_without_experimental_flag) { - std::string const expectedErrorMessage {"Ethdebug annotations are experimental and can only be included in --debug-info in experimental mode. To enable experimental mode, use the --experimental flag."}; + std::string const expectedErrorMessage = + "Ethdebug annotations are experimental and can only be included in --debug-info in experimental mode. " + "To enable experimental mode, use the --experimental flag."; + auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedErrorMessage; }; std::vector const commandLineOptions{"solc", "--debug-info", "ethdebug", "contract.sol"}; @@ -711,10 +717,10 @@ BOOST_AUTO_TEST_CASE(debug_info_ethdebug_without_experimental_flag) BOOST_AUTO_TEST_CASE(experimental_flag_with_standard_json) { - std::string const expectedErrorMessage { + std::string const expectedErrorMessage = "Standard JSON input mode is incompatible with the --experimental flag. " - "Instead, please use the 'settings.experimental' setting in your Standard JSON input file to enable experimental mode." - }; + "Instead, please use the 'settings.experimental' setting in your Standard JSON input file to enable experimental mode."; + auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedErrorMessage; }; std::vector const commandLineOptions{"solc", "--experimental", "--standard-json", "input.json"}; From 5bd7117aa02a3fec90ecc55bc97cff9e1b50c668 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 11 Feb 2026 13:55:17 +0100 Subject: [PATCH 1153/1340] Add SSA CFG code transform --- libyul/CMakeLists.txt | 2 + libyul/backends/evm/ssa/CodeTransform.cpp | 385 ++++++++++++++++++ libyul/backends/evm/ssa/CodeTransform.h | 144 +++++++ .../backends/evm/ssa/StackLayoutGenerator.cpp | 65 ++- .../backends/evm/ssa/StackLayoutGenerator.h | 12 +- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 3 +- 6 files changed, 575 insertions(+), 36 deletions(-) create mode 100644 libyul/backends/evm/ssa/CodeTransform.cpp create mode 100644 libyul/backends/evm/ssa/CodeTransform.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index d52dbba0d..87cf8aaa4 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -74,6 +74,8 @@ add_library(yul backends/evm/VariableReferenceCounter.h backends/evm/VariableReferenceCounter.cpp backends/evm/ssa/BridgeFinder.h + backends/evm/ssa/CodeTransform.cpp + backends/evm/ssa/CodeTransform.h backends/evm/ssa/ControlFlow.cpp backends/evm/ssa/ControlFlow.h backends/evm/ssa/JunkAdmittingBlocksFinder.cpp diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp new file mode 100644 index 000000000..6dc33ad7b --- /dev/null +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -0,0 +1,385 @@ +/* + 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 + +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +using namespace solidity::yul; +using namespace solidity::yul::ssa; + +namespace +{ +void assertLayoutCompatibility(StackData const& _layout1, StackData const& _layout2) +{ + auto const compatibility = checkLayoutCompatibility(_layout1, _layout2); + yulAssert(compatibility.ok(), compatibility.formatErrors()); +} +} + +void CodeTransform::run +( + AbstractAssembly& _assembly, + ControlFlowLiveness const& _controlFlowLiveness, + BuiltinContext& _builtinContext +) +{ + yulAssert(!_controlFlowLiveness.cfgLiveness.empty()); + ControlFlow const& controlFlow = _controlFlowLiveness.controlFlow.get(); + yulAssert(controlFlow.functionGraphs.size() == _controlFlowLiveness.cfgLiveness.size()); + FunctionLabels const functionLabels = registerFunctionLabels(_assembly, controlFlow); + + for (std::size_t functionIndex = 0; functionIndex < controlFlow.functionGraphMapping.size(); ++functionIndex) + { + auto const& [function, cfg] = controlFlow.functionGraphMapping[functionIndex]; + yulAssert(cfg); + auto const callSites = gatherCallSites(*cfg); + auto const& liveness = _controlFlowLiveness.cfgLiveness[functionIndex]; + yulAssert(liveness); + auto const graphID = static_cast(functionIndex); + auto const& stackLayout = StackLayoutGenerator::generate(*liveness, callSites, graphID); + CodeTransform transform( + _assembly, + _builtinContext, + functionLabels, + callSites, + *cfg, + stackLayout, + function, + graphID + ); + transform(cfg->entry); + } +} + +CodeTransform::FunctionLabels CodeTransform::registerFunctionLabels( + AbstractAssembly& _assembly, ControlFlow const& _controlFlow) +{ + FunctionLabels functionLabels; + std::set assignedFunctionNames; + + for (auto const& [_function, _functionGraph]: _controlFlow.functionGraphMapping) + { + if (!_function) + continue; + bool nameAlreadySeen = !assignedFunctionNames.insert(_function->name).second; + functionLabels[_function] = !nameAlreadySeen ? + _assembly.namedLabel( + _function->name.str(), + _functionGraph->arguments.size(), + _functionGraph->returns.size(), + _functionGraph->debugData ? _functionGraph->debugData->astID : std::nullopt + ) : + _assembly.newLabelId(); + } + return functionLabels; +} + +CodeTransform::CodeTransform( + AbstractAssembly& _assembly, + BuiltinContext& _builtinContext, + FunctionLabels const& _functionLabels, + CallSites const& _callSites, + SSACFG const& _cfg, + SSACFGStackLayout const& _stackLayout, + Scope::Function const* _function, + ControlFlow::FunctionGraphID +): + m_assembly(_assembly), + m_builtinContext(_builtinContext), + m_functionLabels(_functionLabels), + m_callSites(_callSites), + m_cfg(_cfg), + m_stackLayout(_stackLayout), + m_blockIsTransformed(_cfg.numBlocks(), false), + m_blockLabels([this] { + std::vector blockLabels; + blockLabels.reserve(m_cfg.numBlocks()); + for (std::size_t i = 0; i < m_cfg.numBlocks(); ++i) + blockLabels.push_back(m_assembly.newLabelId()); + return blockLabels; + }()), + m_assemblyCallbacks{ + .cfg = &_cfg, + .assembly = &_assembly, + .callSites = &_callSites, + .returnLabels = &m_returnLabels + }, + m_stackData([&] + { + auto const& entryLayout = m_stackLayout[m_cfg.entry]; + yulAssert(entryLayout); + return entryLayout->stackIn; + }()), + m_stack(m_stackData, m_assemblyCallbacks) +{ + if (_function) + { + auto const findIt = m_functionLabels.find(_function); + yulAssert(findIt != m_functionLabels.end()); + m_assembly.appendLabel(findIt->second); + m_assembly.setStackHeight(static_cast(_function->numArguments)); + } + StackData expectedStackTop; + expectedStackTop.reserve(m_cfg.arguments.size()); + for (auto const& [_, valueID]: m_cfg.arguments | ranges::views::reverse) + expectedStackTop.push_back(StackSlot::makeValueID(valueID)); + assertLayoutCompatibility(m_stack.data(), expectedStackTop); +} + +void CodeTransform::operator()(SSACFG::BlockId const _blockId) +{ + yulAssert(!m_blockIsTransformed[_blockId.value], "Each block is transformed exactly once."); + m_blockIsTransformed[_blockId.value] = true; + + m_assembly.appendLabel(m_blockLabels[_blockId.value]); + + auto const& blockLayout = m_stackLayout[_blockId]; + yulAssert(blockLayout); + assertLayoutCompatibility(m_stack.data(), blockLayout->stackIn); + yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); + + auto const& block = m_cfg.block(_blockId); + yulAssert(block.operations.size() == blockLayout->operationIn.size(), "We need as many operation stack layouts as we have operations"); + + for (std::size_t operationIndex = 0; operationIndex < block.operations.size(); ++operationIndex) + { + SSACFG::Operation const& operation = block.operations[operationIndex]; + auto const& operationInLayout = blockLayout->operationIn[operationIndex]; + + // perform the operation + (*this)(operation, operationInLayout); + } + + // Shuffle to the block's exit layout before dispatching the exit. + // This ensures the condition is on top for ConditionalJump, phi pre-images are + // in the right positions for jumps, and return values are accessible for FunctionReturn. + StackShuffler::shuffle(m_stack, blockLayout->stackOut); + + // handle the block exit + std::visit(util::GenericVisitor{ [this, &_blockId](auto const& exit) { (*this)(_blockId, exit); } }, block.exit); +} + +void CodeTransform::operator()(SSACFG::Operation const& _operation, StackData const& _operationInputLayout) +{ + bool const hasReturnLabel = + std::holds_alternative(_operation.kind) && + std::get(_operation.kind).canContinue; + + if (hasReturnLabel) + { + auto const [it, inserted] = m_returnLabels.try_emplace(&std::get(_operation.kind).call.get(), 0); + yulAssert(inserted, "Call sites should be unique."); + it->second = m_assembly.newLabelId(); + } + + // check that the assembly stack height corresponds to the stack size before shuffling + yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); + + // prepare stack for operation + StackShuffler::shuffle(m_stack, _operationInputLayout); + + // check that the assembly stack height corresponds to the stack size after shuffling + yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); + + // check that the stack is compatible with the operation input layout + assertLayoutCompatibility(m_stack.data(), _operationInputLayout); + + // Assert that we have the inputs of the operation on stack top. + yulAssert(m_stack.size() >= _operation.inputs.size()); + for (auto const& [stackEntry, input]: ranges::views::zip( + m_stack | ranges::views::take_last(_operation.inputs.size()), + _operation.inputs + )) + yulAssert(stackEntry.isValueID() && stackEntry.valueID() == input); + + // if the function can continue (doesn't always abort), make sure we have the correct return label slot in place + if (hasReturnLabel) + { + yulAssert(m_stack.size() > _operation.inputs.size()); + auto const returnLabelSlot = m_stack.slot(StackDepth{_operation.inputs.size()}); + yulAssert(std::holds_alternative(_operation.kind)); + yulAssert( + returnLabelSlot.isFunctionCallReturnLabel() && + &m_callSites.functionCall(returnLabelSlot.functionCallReturnLabel()) == &std::get(_operation.kind).call.get() + ); + } + + // height of the stack sans function return label and operation inputs + std::size_t const baseHeight = m_stack.size() - _operation.inputs.size() - (hasReturnLabel ? 1 : 0); + + // generate code for the operation + std::visit(util::GenericVisitor{ + [&](SSACFG::BuiltinCall const& _builtin) { + m_assembly.setSourceLocation(originLocationOf(_builtin)); + static_cast(_builtin.builtin.get()).generateCode( + _builtin.call, + m_assembly, + m_builtinContext + ); + }, + [&](SSACFG::Call const& _call) { + auto const* returnLabel = util::valueOrNullptr(m_returnLabels, &_call.call.get()); + // check that if we have a return label, the call can continue + yulAssert(!!returnLabel == _call.canContinue); + m_assembly.setSourceLocation(originLocationOf(_call)); + m_assembly.appendJumpTo( + m_functionLabels.at(&_call.function.get()), + static_cast(_call.function.get().numReturns - _call.function.get().numArguments) - (_call.canContinue ? 1 : 0), + AbstractAssembly::JumpType::IntoFunction + ); + // if we have a return label, append it to assembly and pop the label from the stack + // it might also be one of the inputs that is popped here but then the label will be popped below with + // the other inputs + if (returnLabel) + { + m_assembly.appendLabel(*returnLabel); + m_stack.pop(); + } + }, + [&](SSACFG::LiteralAssignment const&){} + }, _operation.kind); + // simulate that the inputs are consumed + for (size_t i = 0; i < _operation.inputs.size(); ++i) + m_stack.pop(); + // simulate that the outputs are produced + for (auto value: _operation.outputs) + m_stack.push(StackSlot::makeValueID(value)); + + // Assert that the operation produced its proclaimed output. + yulAssert(m_stack.size() == baseHeight + _operation.outputs.size()); + for (auto const& [stackEntry, output]: ranges::views::zip( + m_stack.data() | ranges::views::take_last(_operation.outputs.size()), + _operation.outputs + )) + yulAssert(stackEntry.isValueID() && stackEntry.valueID() == output); + yulAssert( + static_cast(m_stack.size()) == m_assembly.stackHeight(), + fmt::format("symbolic stack size = {} =/= {} = assembly stack height", m_stack.size(), m_assembly.stackHeight()) + ); +} + +void CodeTransform::operator()(SSACFG::BlockId const&, SSACFG::BasicBlock::MainExit const&) +{ + yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); + m_assembly.appendInstruction(evmasm::Instruction::STOP); +} + +void CodeTransform::operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) +{ + yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); + // condition must be at the top of the stack + yulAssert(m_stack.top().isValueID() && m_stack.top().valueID() == _conditionalJump.condition); + // emit JUMPI to nonZero block + m_assembly.appendJumpToIf(m_blockLabels[_conditionalJump.nonZero.value]); + // update symbolic stack by popping the condition as it'll be consumed by JUMPI + m_stack.pop(); + + { + // restore stack to previous state once zero-path is handled + ScopedSaveAndRestore restoreStack(m_stackData, StackData(m_stackData)); + yulAssert(m_stackLayout[_conditionalJump.zero]); + + // transform stack to a state in which we can jump to the zero branch + prepareBlockExitStack( + m_stackLayout[_conditionalJump.zero]->stackIn, + PhiInverse(m_cfg, _currentBlock, _conditionalJump.zero) + ); + assertLayoutCompatibility(m_stack.data(), m_stackLayout[_conditionalJump.zero]->stackIn); + m_assembly.appendJumpTo(m_blockLabels[_conditionalJump.zero.value]); + + if (!m_blockIsTransformed[_conditionalJump.zero.value]) + (*this)(_conditionalJump.zero); + } + { + yulAssert(m_stackLayout[_conditionalJump.nonZero]); + assertLayoutCompatibility(m_stack.data(), m_stackLayout[_conditionalJump.nonZero]->stackIn); + + m_assembly.setStackHeight(static_cast(m_stack.size())); + if (!m_blockIsTransformed[_conditionalJump.nonZero.value]) + (*this)(_conditionalJump.nonZero); + } +} + +void CodeTransform::operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::Jump const& _jump) +{ + yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); + yulAssert(m_stackLayout[_jump.target]); + prepareBlockExitStack(m_stackLayout[_jump.target]->stackIn, PhiInverse(m_cfg, _currentBlock, _jump.target)); + assertLayoutCompatibility(m_stack.data(), m_stackLayout[_jump.target]->stackIn); + m_assembly.appendJumpTo(m_blockLabels[_jump.target.value]); + if (!m_blockIsTransformed[_jump.target.value]) + (*this)(_jump.target); +} + +void CodeTransform::operator()(SSACFG::BlockId const&, SSACFG::BasicBlock::FunctionReturn const& _functionReturn) +{ + yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); + yulAssert(m_cfg.function); + // The return label sits physically below the tracked virtual stack. + // Inform the assembler so SWAP can reach it. + m_assembly.setStackHeight(m_assembly.stackHeight() + 1); + // Build target: [rv1, rv2, ..., rvN-1, rv0] (rv0 at top). + // After shuffle: EVM = [label, rv1, ..., rvN-1, rv0]. + // After SWAP(N): EVM = [rv0, rv1, ..., rvN-1, label]. + // After JUMP: EVM = [rv0, rv1, ..., rvN-1]. + // TODO: it would be better to account for function return labels from the entry of the function to the end symbolically + StackData returnTarget; + if (!_functionReturn.returnValues.empty()) + { + returnTarget.reserve(_functionReturn.returnValues.size()); + for (std::size_t i = 1; i < _functionReturn.returnValues.size(); ++i) + returnTarget.push_back(StackSlot::makeValueID(_functionReturn.returnValues[i])); + returnTarget.push_back(StackSlot::makeValueID(_functionReturn.returnValues.front())); + StackShuffler::shuffle(m_stack, returnTarget, {}, returnTarget.size()); + m_assembly.appendInstruction(evmasm::swapInstruction( + static_cast(_functionReturn.returnValues.size()) + )); + } + else + StackShuffler::shuffle(m_stack, returnTarget, {}, 0); + m_assembly.appendJump(0, AbstractAssembly::JumpType::OutOfFunction); +} + +void CodeTransform::operator()(SSACFG::BlockId const&, SSACFG::BasicBlock::Terminated const&) +{ + yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); + // To be sure just emit another INVALID - should be removed by optimizer. + m_assembly.appendInstruction(evmasm::Instruction::INVALID); +} + +void CodeTransform::prepareBlockExitStack(StackData const& _target, PhiInverse const& _phiInverse) +{ + // pull back target to live in current variable space + auto const pulledBackTarget = stackPreImage(_target, _phiInverse); + // shuffle to target + StackShuffler::shuffle(m_stack, pulledBackTarget); + // check that shuffling was successful + assertLayoutCompatibility(m_stack.data(), pulledBackTarget); + // now we can simply set the target to the actual one which will take care of the application of phi functions + m_stackData = _target; +} diff --git a/libyul/backends/evm/ssa/CodeTransform.h b/libyul/backends/evm/ssa/CodeTransform.h new file mode 100644 index 000000000..03c50cbd7 --- /dev/null +++ b/libyul/backends/evm/ssa/CodeTransform.h @@ -0,0 +1,144 @@ +/* + 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 + +#pragma once + +#include +#include +#include + +#include + +#include + +namespace solidity::yul +{ +struct BuiltinContext; +} +namespace solidity::yul::ssa +{ + +struct AssemblyCallbacks +{ + void swap(std::size_t const _depth) + { + assembly->appendInstruction(evmasm::swapInstruction(static_cast(_depth))); + } + + void pop() + { + assembly->appendInstruction(evmasm::Instruction::POP); + } + + void push(StackSlot const& _slot) + { + switch (_slot.kind()) + { + case StackSlot::Kind::ValueID: + { + auto const id = _slot.valueID(); + yulAssert(id.isLiteral(), fmt::format("Tried bringing up v{}", id.value())); + assembly->appendConstant(cfg->literalInfo(id).value); + return; + } + case StackSlot::Kind::Junk: + { + if (assembly->evmVersion().hasPush0()) + assembly->appendConstant(0); + else + assembly->appendInstruction(evmasm::Instruction::CODESIZE); + return; + } + case StackSlot::Kind::FunctionCallReturnLabel: + { + auto const& call = callSites->functionCall(_slot.functionCallReturnLabel()); + assembly->appendLabelReference(returnLabels->at(&call)); + return; + } + case StackSlot::Kind::FunctionReturnLabel: + { + yulAssert(false, "Cannot produce function return label."); + } + } + } + + void dup(size_t const _depth) + { + assembly->appendInstruction(evmasm::dupInstruction(static_cast(_depth))); + } + + SSACFG const* cfg{}; + AbstractAssembly* assembly{}; + CallSites const* callSites{}; + std::map const* returnLabels{}; +}; +static_assert(StackManipulationCallbackConcept); + +class CodeTransform +{ +public: + static void run( + AbstractAssembly& _assembly, + ControlFlowLiveness const& _liveness, + BuiltinContext& _builtinContext + ); + +private: + using FunctionLabels = std::map; + + static FunctionLabels registerFunctionLabels( + AbstractAssembly& _assembly, + ControlFlow const& _controlFlow + ); + + CodeTransform( + AbstractAssembly& _assembly, + BuiltinContext& _builtinContext, + FunctionLabels const& _functionLabels, + CallSites const& _callSites, + SSACFG const& _cfg, + SSACFGStackLayout const& _stackLayout, + Scope::Function const* _function, + ControlFlow::FunctionGraphID _graphID); + + void operator()(SSACFG::BlockId _blockId); + void operator()(SSACFG::Operation const& _operation, StackData const& _operationInputLayout); + void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::MainExit const& _mainExit); + void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::ConditionalJump const& _conditionalJump); + void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::Jump const& _jump); + void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::FunctionReturn const& _functionReturn); + void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::Terminated const& _terminated); + + void prepareBlockExitStack(StackData const& _target, PhiInverse const& _phiInverse); + + AbstractAssembly& m_assembly; + BuiltinContext& m_builtinContext; + FunctionLabels const& m_functionLabels; + CallSites const& m_callSites; + SSACFG const& m_cfg; + SSACFGStackLayout const& m_stackLayout; + + std::vector m_blockIsTransformed; + std::vector m_blockLabels; + AssemblyCallbacks m_assemblyCallbacks; + StackData m_stackData; + Stack m_stack; + std::map m_returnLabels; +}; + +} diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 04abd8b64..8e5f9b07a 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include @@ -77,12 +77,12 @@ void declareJunk(StackType& _stack, LivenessAnalysis::LivenessData const& _live) } -SSACFGStackLayout StackLayoutGenerator::generate(LivenessAnalysis const& _liveness, CallSites const& _callSites) +SSACFGStackLayout StackLayoutGenerator::generate(LivenessAnalysis const& _liveness, CallSites const& _callSites, ControlFlow::FunctionGraphID _graphID) { - return StackLayoutGenerator(_liveness, _callSites).m_resultLayout; + return StackLayoutGenerator(_liveness, _callSites, _graphID).m_resultLayout; } -StackLayoutGenerator::StackLayoutGenerator(LivenessAnalysis const& _liveness, CallSites const& _callSites): +StackLayoutGenerator::StackLayoutGenerator(LivenessAnalysis const& _liveness, CallSites const& _callSites, ControlFlow::FunctionGraphID): m_cfg(_liveness.cfg()), m_liveness(_liveness), m_callSites(_callSites), @@ -132,11 +132,10 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) if (_blockId == m_cfg.entry) { if (m_cfg.function) - blockLayout.stackIn = - m_cfg.arguments | - ranges::views::reverse | - ranges::views::transform([](auto&& _variableAndValueId) -> Slot { return Slot::makeValueID(std::get<1>(_variableAndValueId)); }) | - ranges::to; + { + for (auto const& [_, valueID]: m_cfg.arguments | ranges::views::reverse) + blockLayout.stackIn.push_back(Slot::makeValueID(valueID)); + } m_resultLayout[_blockId] = blockLayout; return; } @@ -163,35 +162,38 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) { // we have more than one entry and need to unify or at the very least apply phi fct. auto const& liveIn = m_liveness.liveIn(_blockId); - std::vector cumulativeCosts(parentExits.size(), std::numeric_limits::max()); + // Pre-compute each parent's phi-term proposal (declareJunk + handlePhiFunctions) once + std::vector proposals(parentExits.size()); for (std::size_t i = 0; i < parentExits.size(); ++i) { if (!parentExits[i].second) continue; - std::size_t cumulativeCost = 0; - auto referenceStackIn = *parentExits[i].second; + proposals[i] = *parentExits[i].second; { - StackType stack(referenceStackIn, {}); + StackType stack(proposals[i], {}); declareJunk(stack, liveIn); } - handlePhiFunctions(referenceStackIn, PhiInverse(m_cfg, parentExits[i].first, _blockId), liveIn); + handlePhiFunctions(proposals[i], PhiInverse(m_cfg, parentExits[i].first, _blockId), liveIn); + } + std::vector cumulativeCosts(parentExits.size(), std::numeric_limits::max()); + for (std::size_t i = 0; i < parentExits.size(); ++i) + { + if (!parentExits[i].second) + continue; + std::size_t cumulativeCost = 0; for (std::size_t j = 0; j < parentExits.size(); ++j) { - if (j != i) - { - if (parentExits[j].second != nullptr) - { - auto otherStackIn = *parentExits[j].second; - StackType stack(otherStackIn, {}); - StackShuffler::shuffle( - stack, - stackPreImage(referenceStackIn, PhiInverse(m_cfg, parentExits[j].first, _blockId)), - {}, - referenceStackIn.size() - ); - cumulativeCost += stack.callbacks().numOps; - } - } + if (j == i || !parentExits[j].second) + continue; + auto proposalCopy = proposals[j]; + StackType stack(proposalCopy, {}); + StackShuffler::shuffle( + stack, + proposals[i], + {}, + proposals[i].size() + ); + cumulativeCost += stack.callbacks().numOps; } cumulativeCosts[i] = cumulativeCost; } @@ -199,10 +201,7 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) std::distance(cumulativeCosts.begin(), ranges::min_element(cumulativeCosts)) ); yulAssert(parentExits[argMin].second); - blockLayout.stackIn = *parentExits[argMin].second; - StackType stack(blockLayout.stackIn, {}); - declareJunk(stack, liveIn); - handlePhiFunctions(blockLayout.stackIn, PhiInverse(m_cfg, parentExits[argMin].first, _blockId), liveIn); + blockLayout.stackIn = std::move(proposals[argMin]); } m_resultLayout[_blockId] = blockLayout; } diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.h b/libyul/backends/evm/ssa/StackLayoutGenerator.h index c9d45c72a..a1acfa57d 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.h +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.h @@ -32,10 +32,18 @@ class StackLayoutGenerator { public: using Slot = StackSlot; - static SSACFGStackLayout generate(LivenessAnalysis const& _liveness, CallSites const& _callSites); + static SSACFGStackLayout generate( + LivenessAnalysis const& _liveness, + CallSites const& _callSites, + ControlFlow::FunctionGraphID _graphID + ); private: - explicit StackLayoutGenerator(LivenessAnalysis const& _liveness, CallSites const& _callSites); + explicit StackLayoutGenerator( + LivenessAnalysis const& _liveness, + CallSites const& _callSites, + ControlFlow::FunctionGraphID _graphID + ); void defineStackIn(SSACFG::BlockId const& _blockId); void visitBlock(SSACFG::BlockId const& _blockId); diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index a7ddad529..0066e8fa2 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -162,7 +162,8 @@ frontend::test::TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& auto const& cfg = *controlFlow->functionGraphs[index]; SSACFGStackLayout const layout = StackLayoutGenerator::generate( LivenessAnalysis(cfg), - gatherCallSites(cfg) + gatherCallSites(cfg), + static_cast(index) ); StackLayoutDotExporter exporter(cfg, index, layout); if (cfg.function) From 0f5f9ed64b1932d70400804d3c82d072248d6f76 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:57:50 +0100 Subject: [PATCH 1154/1340] Add ssa stack target validator --- libyul/backends/evm/ssa/StackUtils.cpp | 31 ++++++++++++++++++++++++++ libyul/backends/evm/ssa/StackUtils.h | 18 +++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index 3f2d28423..d15b45a16 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -21,9 +21,13 @@ #include #include +#include +#include #include +#include + using namespace solidity::yul::ssa; StackData solidity::yul::ssa::stackPreImage(StackData _stack, PhiInverse const& _phiInverse) @@ -141,3 +145,30 @@ CallSites solidity::yul::ssa::gatherCallSites(SSACFG const& _cfg) } return result; } + +std::string ValidationResult::formatErrors() const +{ + return fmt::format("{}", fmt::join(m_errors, "\n")); +} + +ValidationResult solidity::yul::ssa::checkLayoutCompatibility(StackData const& _current, StackData const& _desired) +{ + ValidationResult result; + if (_current.size() != _desired.size()) + return result.addError(fmt::format( + "size mismatch: {} = len({}) =/= len({}) = {}", + _current.size(), stackToString(_current), stackToString(_desired), _desired.size() + )); + for (auto&& [index, currentSlot, desiredSlot]: ranges::zip_view(ranges::views::iota(0), _current, _desired)) + if (!desiredSlot.isJunk() && currentSlot != desiredSlot) + result.addError(fmt::format( + "stack element mismatch: {} = {}[{}] =/= {}[{}] = {}", + slotToString(currentSlot), + stackToString(_current), + index, + stackToString(_desired), + index, + slotToString(desiredSlot) + )); + return result; +} diff --git a/libyul/backends/evm/ssa/StackUtils.h b/libyul/backends/evm/ssa/StackUtils.h index 6f5e991a0..eaaf8ad1b 100644 --- a/libyul/backends/evm/ssa/StackUtils.h +++ b/libyul/backends/evm/ssa/StackUtils.h @@ -21,9 +21,23 @@ #include #include +#include +#include + namespace solidity::yul::ssa { +class ValidationResult +{ +public: + bool ok() const { return m_errors.empty(); } + std::string formatErrors() const; + ValidationResult& addError(std::string _msg) { m_errors.push_back(std::move(_msg)); return *this; } + std::vector const& errors() const { return m_errors; } +private: + std::vector m_errors; +}; + struct CountingInstructionsCallbacks { std::size_t numOps = 0; @@ -40,4 +54,8 @@ std::size_t findOptimalTargetSize(StackData const& _stackData, StackData const& CallSites gatherCallSites(SSACFG const& _cfg); +/// Checks that _current and _desired have the same size and that each slot matches, +/// treating junk slots in _desired as wildcards. +ValidationResult checkLayoutCompatibility(StackData const& _current, StackData const& _desired); + } From fc1f03204e3990d5093fe34e15fc3d3fc9b096a7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:58:17 +0100 Subject: [PATCH 1155/1340] SSA stack shuffler: convenience method when no liveness is required --- libyul/backends/evm/ssa/StackShuffler.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 983505bb2..5dddf5e5a 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -169,6 +169,14 @@ class StackShuffler yulAssert(i < maxIterations, fmt::format("Maximum iterations reached on {}", stackToString(_stack.data()))); } + static void shuffle( + Stack& _stack, + StackData const& _target + ) + { + shuffle(_stack, _target, {}, _target.size()); + } + private: /// Make a local step in stack space that should bring us closer to the target. Returns true if more shuffling /// is required, returns false if finished. From 2e557869d282b84a2fab83e3be837b16ac55ab5c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 24 Feb 2026 10:43:25 +0100 Subject: [PATCH 1156/1340] SSA Stack callbacks use StackDepth --- libyul/backends/evm/ssa/CodeTransform.h | 8 ++-- libyul/backends/evm/ssa/Stack.h | 53 +++++++++++++------------ libyul/backends/evm/ssa/StackUtils.h | 4 +- test/libyul/ssa/StackShufflerTest.cpp | 8 ++-- 4 files changed, 38 insertions(+), 35 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.h b/libyul/backends/evm/ssa/CodeTransform.h index 03c50cbd7..0764731c9 100644 --- a/libyul/backends/evm/ssa/CodeTransform.h +++ b/libyul/backends/evm/ssa/CodeTransform.h @@ -35,9 +35,9 @@ namespace solidity::yul::ssa struct AssemblyCallbacks { - void swap(std::size_t const _depth) + void swap(StackDepth const _depth) { - assembly->appendInstruction(evmasm::swapInstruction(static_cast(_depth))); + assembly->appendInstruction(evmasm::swapInstruction(static_cast(_depth.value))); } void pop() @@ -77,9 +77,9 @@ struct AssemblyCallbacks } } - void dup(size_t const _depth) + void dup(StackDepth const _depth) { - assembly->appendInstruction(evmasm::dupInstruction(static_cast(_depth))); + assembly->appendInstruction(evmasm::dupInstruction(static_cast(_depth.value))); } SSACFG const* cfg{}; diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index 834e21078..ebeefe225 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -132,28 +132,6 @@ using StackData = std::vector; std::string slotToString(StackSlot const& _slot); std::string stackToString(StackData const& _stackData); -template -concept StackManipulationCallbackConcept = requires( - StackManipulationCallback& _callback, - StackSlot _slot, - size_t _depth -) -{ - { _callback.swap(_depth) } -> std::same_as; - { _callback.dup(_depth) } -> std::same_as; - { _callback.push(_slot) } -> std::same_as; - { _callback.pop() } -> std::same_as; -}; - -struct NoOpStackManipulationCallbacks -{ - static void swap(size_t) {} - static void dup(size_t) {} - static void push(StackSlot const&) {} - static void pop() {} -}; -static_assert(StackManipulationCallbackConcept); - /// Array index into stack from the bottom (offset 0 = bottom). /// Natural for array-like access and iteration; used when treating the stack as a data structure. struct StackOffset @@ -179,6 +157,28 @@ struct StackDepth constexpr auto operator<=>(StackDepth const lhs, size_t const rhs) noexcept { return lhs.value <=> rhs; } constexpr auto operator<=>(size_t const lhs, StackDepth const rhs) noexcept { return lhs <=> rhs.value; } +template +concept StackManipulationCallbackConcept = requires( + StackManipulationCallback& _callback, + StackSlot _slot, + StackDepth _depth +) +{ + { _callback.swap(_depth) } -> std::same_as; + { _callback.dup(_depth) } -> std::same_as; + { _callback.push(_slot) } -> std::same_as; + { _callback.pop() } -> std::same_as; +}; + +struct NoOpStackManipulationCallbacks +{ + static void swap(StackDepth) {} + static void dup(StackDepth) {} + static void push(StackSlot const&) {} + static void pop() {} +}; +static_assert(StackManipulationCallbackConcept); + template< StackManipulationCallbackConcept CallbacksType = NoOpStackManipulationCallbacks > @@ -213,7 +213,7 @@ class Stack yulAssert(swapReachable(_offset), "Stack too deep"); std::swap((*m_data)[_offset.value], m_data->back()); if constexpr (!std::is_same_v) - m_callbacks.swap(offsetToDepth(_offset).value); + m_callbacks.swap(offsetToDepth(_offset)); } /// if the stack state needs to be updated without notifying the callback, the template parameter can be set to false @@ -230,6 +230,7 @@ class Stack template void push(Slot const& _slot) { + yulAssert(!_slot.isFunctionReturnLabel(), "Cannot push function return label"); m_data->emplace_back(_slot); if constexpr (callback && !std::is_same_v) m_callbacks.push(_slot); @@ -240,9 +241,11 @@ class Stack { auto const depth = offsetToDepth(_offset); yulAssert(dupReachable(depth), "Stack too deep"); - m_data->push_back((*m_data)[_offset.value]); + auto const slot = (*m_data)[_offset.value]; + yulAssert(!slot.isFunctionReturnLabel(), "Cannot dup function return label"); + m_data->push_back(slot); if constexpr (!std::is_same_v) - m_callbacks.dup(depth.value + 1); + m_callbacks.dup(StackDepth{depth.value + 1}); } bool dupReachable(Offset const& _offset) const noexcept { return dupReachable(offsetToDepth(_offset)); } diff --git a/libyul/backends/evm/ssa/StackUtils.h b/libyul/backends/evm/ssa/StackUtils.h index eaaf8ad1b..7d3088873 100644 --- a/libyul/backends/evm/ssa/StackUtils.h +++ b/libyul/backends/evm/ssa/StackUtils.h @@ -41,8 +41,8 @@ class ValidationResult struct CountingInstructionsCallbacks { std::size_t numOps = 0; - void swap(std::size_t) { ++numOps; } - void dup(std::size_t) { ++numOps; } + void swap(StackDepth) { ++numOps; } + void dup(StackDepth) { ++numOps; } void push(StackSlot const&) { ++numOps; } void pop() { ++numOps; } }; diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index cd24b3b5e..62e0955bb 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -56,15 +56,15 @@ using Slot = StackSlot; using ValueId = SSACFG::ValueId; struct StackManipulationCallbacks { - void swap(size_t _depth) const + void swap(StackDepth _depth) const { if (hook) - (*hook)(fmt::format("SWAP{}", _depth)); + (*hook)(fmt::format("SWAP{}", _depth.value)); } - void dup(size_t const _depth) const + void dup(StackDepth const _depth) const { if (hook) - (*hook)(fmt::format("DUP{}", _depth)); + (*hook)(fmt::format("DUP{}", _depth.value)); } void push(Slot const& _slot) const { From ad675cbf76761df31e35f604dc8f71d69e675d62 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:50:35 +0100 Subject: [PATCH 1157/1340] Thread SSA CFG Codegen through compiler stack --- libsolidity/interface/CompilerStack.cpp | 9 ++- libsolidity/interface/CompilerStack.h | 5 ++ libyul/YulStack.cpp | 16 ++--- libyul/YulStack.h | 10 +-- libyul/backends/evm/EVMObjectCompiler.cpp | 79 +++++++++++++++-------- libyul/backends/evm/EVMObjectCompiler.h | 5 +- 6 files changed, 81 insertions(+), 43 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 3583ae535..7d25fcf0d 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -235,6 +235,12 @@ void CompilerStack::setExperimental(bool _experimental) m_experimental = _experimental; } +void CompilerStack::setViaSSACFG(bool _viaSSACFG) +{ + solAssert(m_stackState < CompilationSuccessful, "Must set SSA CFG codegen before compilation."); + m_viaSSACFG = _viaSSACFG; +} + void CompilerStack::setEVMVersion(langutil::EVMVersion _version) { solAssert(m_stackState < ParsedAndImported, "Must set EVM version before parsing."); @@ -325,6 +331,7 @@ void CompilerStack::reset(bool _keepSettings) m_importRemapper.clear(); m_libraries.clear(); m_viaIR = false; + m_viaSSACFG = false; m_evmVersion = langutil::EVMVersion(); m_eofVersion.reset(); m_modelCheckerSettings = ModelCheckerSettings{}; @@ -1672,7 +1679,7 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) std::string deployedName = IRNames::deployedObject(_contract); solAssert(!deployedName.empty(), ""); - tie(compiledContract.evmAssembly, compiledContract.evmRuntimeAssembly) = stack.assembleEVMWithDeployed(deployedName); + tie(compiledContract.evmAssembly, compiledContract.evmRuntimeAssembly) = stack.assembleEVMWithDeployed(deployedName, m_viaSSACFG); if (stack.hasErrors()) { diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index eb765d3c6..41f61ae4a 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -223,6 +223,10 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// Must be set before parsing. void setViaIR(bool _viaIR); + /// Sets the pipeline to use the SSA CFG code generator instead of OptimizedEVMCodeTransform. + /// Must be set before compilation. + void setViaSSACFG(bool _viaSSACFG); + /// Sets the experimental toggle to allow usage of experimental features. void setExperimental(bool _experimental); @@ -610,6 +614,7 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac RevertStrings m_revertStrings = RevertStrings::Default; State m_stopAfter = State::CompilationSuccessful; bool m_viaIR = false; + bool m_viaSSACFG = false; bool m_experimental = false; langutil::EVMVersion m_evmVersion; std::optional m_eofVersion; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index ae32c0f25..496f249a3 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -192,9 +192,9 @@ bool YulStack::analyzeParsed(Object& _object) return success; } -void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) const +void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize, bool _viaSSACFG) const { - EVMObjectCompiler::compile(*m_parserResult, _assembly, _optimize); + EVMObjectCompiler::compile(*m_parserResult, _assembly, _optimize, _viaSSACFG); } void YulStack::reparse() @@ -232,7 +232,7 @@ void YulStack::reparse() // locations and fewer warnings. } -MachineAssemblyObject YulStack::assemble(Machine _machine) +MachineAssemblyObject YulStack::assemble(Machine _machine, bool _viaSSACFG) { yulAssert(m_stackState >= AnalysisSuccessful); yulAssert(m_parserResult, ""); @@ -242,17 +242,17 @@ MachineAssemblyObject YulStack::assemble(Machine _machine) switch (_machine) { case Machine::EVM: - return assembleWithDeployed().first; + return assembleWithDeployed({}, _viaSSACFG).first; } unreachable(); } std::pair -YulStack::assembleWithDeployed(std::optional _deployName) +YulStack::assembleWithDeployed(std::optional _deployName, bool _viaSSACFG) { yulAssert(m_charStream); - auto [creationAssembly, deployedAssembly] = assembleEVMWithDeployed(_deployName); + auto [creationAssembly, deployedAssembly] = assembleEVMWithDeployed(_deployName, _viaSSACFG); if (!creationAssembly) { yulAssert(!deployedAssembly); @@ -307,7 +307,7 @@ YulStack::assembleWithDeployed(std::optional _deployName) } std::pair, std::shared_ptr> -YulStack::assembleEVMWithDeployed(std::optional _deployName) +YulStack::assembleEVMWithDeployed(std::optional _deployName, bool _viaSSACFG) { yulAssert(m_stackState >= AnalysisSuccessful); yulAssert(m_parserResult, ""); @@ -326,7 +326,7 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) ); try { - compileEVM(adapter, optimize); + compileEVM(adapter, optimize, _viaSSACFG); assembly.optimise(evmasm::Assembly::OptimiserSettings::translateSettings(m_optimiserSettings)); diff --git a/libyul/YulStack.h b/libyul/YulStack.h index e9d75b6ae..694c14e36 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -118,7 +118,7 @@ class YulStack: public langutil::CharStreamProvider void optimize(); /// Run the assembly step (should only be called after parseAndAnalyze). - MachineAssemblyObject assemble(Machine _machine); + MachineAssemblyObject assemble(Machine _machine, bool _viaSSACFG = false); /// Run the assembly step (should only be called after parseAndAnalyze). /// In addition to the value returned by @a assemble, returns @@ -126,7 +126,8 @@ class YulStack: public langutil::CharStreamProvider /// Only available for EVM. std::pair assembleWithDeployed( - std::optional _deployName = {} + std::optional _deployName = {}, + bool _viaSSACFG = false ); /// Run the assembly step (should only be called after parseAndAnalyze). @@ -134,7 +135,8 @@ class YulStack: public langutil::CharStreamProvider /// Only available for EVM. std::pair, std::shared_ptr> assembleEVMWithDeployed( - std::optional _deployName = {} + std::optional _deployName = {}, + bool _viaSSACFG = false ); /// @returns the errors generated during parsing, analysis (and potentially assembly). @@ -161,7 +163,7 @@ class YulStack: public langutil::CharStreamProvider bool analyzeParsed(); bool analyzeParsed(yul::Object& _object); - void compileEVM(yul::AbstractAssembly& _assembly, bool _optimize) const; + void compileEVM(yul::AbstractAssembly& _assembly, bool _optimize, bool _viaSSACFG) const; /// Prints the Yul object stored internally and parses it again. /// This ensures that the debug info in the AST matches the source that printing would produce diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index 830c32752..b476f2e09 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -21,6 +21,10 @@ #include +#include +#include +#include + #include #include #include @@ -37,14 +41,15 @@ using namespace solidity::yul; void EVMObjectCompiler::compile( Object const& _object, AbstractAssembly& _assembly, - bool _optimize + bool _optimize, + bool _viaSSACFG ) { EVMObjectCompiler compiler(_assembly); - compiler.run(_object, _optimize); + compiler.run(_object, _optimize, _viaSSACFG); } -void EVMObjectCompiler::run(Object const& _object, bool _optimize) +void EVMObjectCompiler::run(Object const& _object, bool _optimize, bool _viaSSACFG) { yulAssert(_object.dialect()); auto const* evmDialect = dynamic_cast(_object.dialect()); @@ -61,7 +66,7 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name); context.subIDs[subObject->name] = subAssemblyAndID.second; subObject->subId = subAssemblyAndID.second; - compile(*subObject, *subAssemblyAndID.first, _optimize); + compile(*subObject, *subAssemblyAndID.first, _optimize, _viaSSACFG); } else { @@ -82,33 +87,51 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize) } if (_optimize && evmDialect->evmVersion().canOverchargeGasForCall()) { - auto stackErrors = OptimizedEVMCodeTransform::run( - m_assembly, - *_object.analysisInfo, - _object.code()->root(), - *evmDialect, - context, - OptimizedEVMCodeTransform::UseNamedLabels::ForFirstFunctionOfEachName - ); - if (!stackErrors.empty()) + if (_viaSSACFG) { - yulAssert(evmDialect->providesObjectAccess()); - auto const memoryGuardHandle = evmDialect->findBuiltin("memoryguard"); - yulAssert(memoryGuardHandle, "Compiling with object access, memoryguard should be available as builtin."); - std::vector memoryGuardCalls = findFunctionCalls( + std::unique_ptr controlFlow = ssa::SSACFGBuilder::build( + *_object.analysisInfo, + *_object.dialect(), _object.code()->root(), - *memoryGuardHandle + false ); - auto stackError = stackErrors.front(); - std::string msg = stackError.comment() ? *stackError.comment() : ""; - if (memoryGuardCalls.empty()) - msg += "\nNo memoryguard was present. " - "Consider using memory-safe assembly only and annotating it via " - "'assembly (\"memory-safe\") { ... }'."; - else - msg += "\nmemoryguard was present."; - stackError << util::errinfo_comment(msg); - BOOST_THROW_EXCEPTION(stackError); + ssa::ControlFlowLiveness const liveness(*controlFlow); + ssa::CodeTransform::run( + m_assembly, + liveness, + context + ); + } + else + { + auto stackErrors = OptimizedEVMCodeTransform::run( + m_assembly, + *_object.analysisInfo, + _object.code()->root(), + *evmDialect, + context, + OptimizedEVMCodeTransform::UseNamedLabels::ForFirstFunctionOfEachName + ); + if (!stackErrors.empty()) + { + yulAssert(evmDialect->providesObjectAccess()); + auto const memoryGuardHandle = evmDialect->findBuiltin("memoryguard"); + yulAssert(memoryGuardHandle, "Compiling with object access, memoryguard should be available as builtin."); + std::vector memoryGuardCalls = findFunctionCalls( + _object.code()->root(), + *memoryGuardHandle + ); + auto stackError = stackErrors.front(); + std::string msg = stackError.comment() ? *stackError.comment() : ""; + if (memoryGuardCalls.empty()) + msg += "\nNo memoryguard was present. " + "Consider using memory-safe assembly only and annotating it via " + "'assembly (\"memory-safe\") { ... }'."; + else + msg += "\nmemoryguard was present."; + stackError << util::errinfo_comment(msg); + BOOST_THROW_EXCEPTION(stackError); + } } } else diff --git a/libyul/backends/evm/EVMObjectCompiler.h b/libyul/backends/evm/EVMObjectCompiler.h index cca346ae7..d7f983a31 100644 --- a/libyul/backends/evm/EVMObjectCompiler.h +++ b/libyul/backends/evm/EVMObjectCompiler.h @@ -36,12 +36,13 @@ class EVMObjectCompiler static void compile( Object const& _object, AbstractAssembly& _assembly, - bool _optimize + bool _optimize, + bool _viaSSACFG = false ); private: EVMObjectCompiler(AbstractAssembly& _assembly): m_assembly(_assembly) {} - void run(Object const& _object, bool _optimize); + void run(Object const& _object, bool _optimize, bool _viaSSACFG); AbstractAssembly& m_assembly; }; From 4687eeced72f44c4d2ead29a0f22471abe861fe9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:51:04 +0100 Subject: [PATCH 1158/1340] Add compileViaSSAYul option to semantic test suite --- test/libsolidity/SemanticTest.cpp | 31 ++++++++++++++----- test/libsolidity/SemanticTest.h | 8 +++-- .../SolidityExecutionFramework.cpp | 1 + test/libsolidity/SolidityExecutionFramework.h | 1 + test/libsolidity/util/TestFileParser.cpp | 4 +-- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 296467ae2..d9d44e628 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -112,6 +112,7 @@ SemanticTest::SemanticTest( m_revertStrings = revertStrings.value(); m_allowNonExistingFunctions = m_reader.boolSetting("allowNonExistingFunctions", false); + m_testCaseWantsSSACFGRun = m_reader.boolSetting("compileViaSSACFG", false); m_compiler.setExperimental(m_reader.boolSetting("experimental", false)); parseExpectations(m_reader.stream()); @@ -333,6 +334,14 @@ TestCase::TestResult SemanticTest::run(std::ostream& _stream, std::string const& result = tryRunTestWithYulOptimizer(_stream, _linePrefix, _formatted); } + if (m_testCaseWantsSSACFGRun && m_testCaseWantsYulRun && result == TestResult::Success) + { + if (solidity::test::CommonOptions::get().optimize) + result = runTest(_stream, _linePrefix, _formatted, true /* _isYulRun */, true /* _isSSACFGRun */); + else + result = tryRunTestWithYulOptimizer(_stream, _linePrefix, _formatted, true /* _isSSACFGRun */); + } + if (result != TestResult::Success) solidity::test::CommonOptions::get().printSelectedOptions( _stream, @@ -347,19 +356,24 @@ TestCase::TestResult SemanticTest::runTest( std::ostream& _stream, std::string const& _linePrefix, bool _formatted, - bool _isYulRun + bool _isYulRun, + bool _isSSACFGRun ) { bool success = true; m_gasCostFailure = false; + m_isSSACFGRun = _isSSACFGRun; selectVM(evmc_capabilities::EVMC_CAPABILITY_EVM1); reset(); m_compileViaYul = _isYulRun; + m_compileViaSSACFG = _isSSACFGRun; - if (_isYulRun) + if (_isSSACFGRun) + AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Running via SSA Yul: " << std::endl; + else if (_isYulRun) AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Running via Yul: " << std::endl; for (TestFunctionCall& test: m_tests) @@ -525,7 +539,8 @@ TestCase::TestResult SemanticTest::runTest( TestCase::TestResult SemanticTest::tryRunTestWithYulOptimizer( std::ostream& _stream, std::string const& _linePrefix, - bool _formatted + bool _formatted, + bool _isSSACFGRun ) { TestResult result{}; @@ -542,7 +557,7 @@ TestCase::TestResult SemanticTest::tryRunTestWithYulOptimizer( try { - result = runTest(_stream, _linePrefix, _formatted, true /* _isYulRun */); + result = runTest(_stream, _linePrefix, _formatted, true /* _isYulRun */, _isSSACFGRun); } catch (yul::StackTooDeepError const&) { @@ -571,9 +586,10 @@ TestCase::TestResult SemanticTest::tryRunTestWithYulOptimizer( bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _compileViaYul) const { - std::string setting = - (_compileViaYul ? "ir"s : "legacy"s) + - (m_optimiserSettings == OptimiserSettings::full() ? "Optimized" : ""); + std::string setting = m_isSSACFGRun + ? (m_optimiserSettings == OptimiserSettings::full() ? "ssaCFGOptimized"s : "ssaCFG"s) + : (_compileViaYul ? "ir"s : "legacy"s) + + (m_optimiserSettings == OptimiserSettings::full() ? "Optimized" : ""); soltestAssert( io_test.call().expectations.gasUsedExcludingCode.count(setting) == @@ -584,6 +600,7 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp m_gasUsed < m_enforceGasCostMinValue || // gas used less than threshold for enforcing feature m_gasUsed >= InitialGas || // test has used up all available gas (test will fail anyway) setting == "ir" || + setting == "ssaCFG" || io_test.call().kind == FunctionCall::Kind::Builtin; // isoltest builtin e.g. `smokeTest` or `storageEmpty` bool gasValueMissing = !io_test.call().expectations.gasUsedExcludingCode.contains(setting); if (!m_enforceGasCost || (gasValueMissing && uninteresting)) diff --git a/test/libsolidity/SemanticTest.h b/test/libsolidity/SemanticTest.h index efc2b5903..2421fdf29 100644 --- a/test/libsolidity/SemanticTest.h +++ b/test/libsolidity/SemanticTest.h @@ -96,12 +96,14 @@ class SemanticTest: public SolidityExecutionFramework, public EVMVersionRestrict std::ostream& _stream, std::string const& _linePrefix, bool _formatted, - bool _isYulRun + bool _isYulRun, + bool _isSSACFGRun = false ); TestResult tryRunTestWithYulOptimizer( std::ostream& _stream, std::string const& _linePrefix, - bool _formatted + bool _formatted, + bool _isSSACFGRun = false ); bool checkGasCostExpectation(TestFunctionCall& io_test, bool _compileViaYul) const; std::map makeBuiltins(); @@ -119,6 +121,8 @@ class SemanticTest: public SolidityExecutionFramework, public EVMVersionRestrict std::vector const m_sideEffectHooks; bool m_testCaseWantsYulRun = true; bool m_testCaseWantsLegacyRun = true; + bool m_testCaseWantsSSACFGRun = false; + bool m_isSSACFGRun = false; bool m_runWithABIEncoderV1Only = false; bool m_allowNonExistingFunctions = false; bool m_gasCostFailure = false; diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index 57d4d9d9b..fc9087e92 100644 --- a/test/libsolidity/SolidityExecutionFramework.cpp +++ b/test/libsolidity/SolidityExecutionFramework.cpp @@ -61,6 +61,7 @@ bytes SolidityExecutionFramework::multiSourceCompileContract( m_compiler.setEOFVersion(m_eofVersion); m_compiler.setOptimiserSettings(m_optimiserSettings); m_compiler.setViaIR(m_compileViaYul); + m_compiler.setViaSSACFG(m_compileViaSSACFG); m_compiler.setRevertStringBehaviour(m_revertStrings); if (!m_appendCBORMetadata) { m_compiler.setMetadataFormat(CompilerStack::MetadataFormat::NoMetadata); diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index 4caa4aa1e..306ac80ad 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -84,6 +84,7 @@ class SolidityExecutionFramework: public solidity::test::ExecutionFramework std::optional m_eofVersion; CompilerStack m_compiler; bool m_compileViaYul = false; + bool m_compileViaSSACFG = false; bool m_showMetadata = false; bool m_appendCBORMetadata = true; CompilerStack::MetadataHash m_metadataHash = CompilerStack::MetadataHash::IPFS; diff --git a/test/libsolidity/util/TestFileParser.cpp b/test/libsolidity/util/TestFileParser.cpp index 5a32a1591..247bd4d54 100644 --- a/test/libsolidity/util/TestFileParser.cpp +++ b/test/libsolidity/util/TestFileParser.cpp @@ -84,9 +84,9 @@ std::vector TestFileParser::parseFunctio BOOST_THROW_EXCEPTION(TestParserError("Expected function call before gas usage filter.")); std::string runType = m_scanner.currentLiteral(); - if (std::set{"ir", "irOptimized", "legacy", "legacyOptimized"}.count(runType) == 0) + if (std::set{"ir", "irOptimized", "legacy", "legacyOptimized", "ssaCFG", "ssaCFGOptimized"}.count(runType) == 0) BOOST_THROW_EXCEPTION(TestParserError( - "Expected \"ir\", \"irOptimized\", \"legacy\", or \"legacyOptimized\"." + "Expected \"ir\", \"irOptimized\", \"legacy\", \"legacyOptimized\", \"ssaCFG\", or \"ssaCFGOptimized\"." )); m_scanner.scanNextToken(); From 99a57b2dc6b78b70d26ab3575756b6946e6e3ddd Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:51:22 +0100 Subject: [PATCH 1159/1340] Enable compileViaSSAYul for deposit and snark contract --- .../semanticTests/externalContracts/deposit_contract.sol | 8 ++++++++ .../libsolidity/semanticTests/externalContracts/snark.sol | 3 +++ 2 files changed, 11 insertions(+) diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index c53e49f1f..b6b5a0924 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -174,6 +174,8 @@ contract DepositContract is IDepositContract, ERC165 { ret[7] = bytesValue[0]; } } +// ==== +// compileViaSSACFG: true // ---- // constructor() // gas irOptimized: 809570 @@ -182,6 +184,8 @@ contract DepositContract is IDepositContract, ERC165 { // gas legacy code: 1438800 // gas legacyOptimized: 848699 // gas legacyOptimized code: 878200 +// gas ssaCFGOptimized: 810764 +// gas ssaCFGOptimized code: 582000 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # @@ -190,12 +194,14 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 +// gas ssaCFGOptimized: 110211 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 +// gas ssaCFGOptimized: 110211 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 @@ -203,6 +209,7 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 +// gas ssaCFGOptimized: 110201 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 @@ -210,4 +217,5 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 +// gas ssaCFGOptimized: 110201 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index c073993e1..4d303926b 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -287,6 +287,7 @@ contract Test { // // ==== // EVMVersion: >=constantinople +// compileViaSSACFG: true // ---- // library: Pairing // f() -> true @@ -295,8 +296,10 @@ contract Test { // gas irOptimized: 275229 // gas legacy: 293579 // gas legacyOptimized: 276313 +// gas ssaCFGOptimized: 275439 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." // gas irOptimized: 818076 // gas legacy: 904397 // gas legacyOptimized: 816770 +// gas ssaCFGOptimized: 819542 From 08051cf43243e3a3d17435c4209ba232a90baf4a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 3 Mar 2026 18:22:52 +0100 Subject: [PATCH 1160/1340] Add ssa yul ir parsing capabilities to gas_diff_stats.py --- scripts/gas_diff_stats.py | 34 ++++++++++++++++------------- test/scripts/test_gas_diff_stats.py | 14 +++++++++--- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index ecb4cc912..cb90e7b38 100755 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -25,6 +25,7 @@ class Kind(Enum): IrOptimized = 2 Legacy = 3 LegacyOptimized = 4 + SsaCFGOptimized = 5 class Diff(Enum): Minus = 1 @@ -43,6 +44,7 @@ class Diff(Enum): gas_ir_optimized = string("gas irOptimized").result(Kind.IrOptimized) gas_legacy_optimized = string("gas legacyOptimized").result(Kind.LegacyOptimized) gas_legacy = string("gas legacy").result(Kind.Legacy) +gas_ssa_cfg_optimized = string("gas ssaCFGOptimized").result(Kind.SsaCFGOptimized) code_suffix = string("code") def number() -> int: @@ -61,7 +63,7 @@ def diff_string() -> (Kind, Diff, int): diff_kind = yield minus | plus yield comment yield space - codegen_kind = yield gas_ir_optimized ^ gas_ir ^ gas_legacy_optimized ^ gas_legacy + codegen_kind = yield gas_ssa_cfg_optimized ^ gas_ir_optimized ^ gas_ir ^ gas_legacy_optimized ^ gas_legacy yield optional(space) yield optional(code_suffix) yield colon @@ -69,11 +71,11 @@ def diff_string() -> (Kind, Diff, int): val = yield number() return (diff_kind, codegen_kind, val) -def collect_statistics(lines) -> (int, int, int, int, int, int): +def collect_statistics(lines) -> (int, int, int, int, int, int, int, int): """Returns - (old_ir_optimized, old_legacy_optimized, old_legacy, new_ir_optimized, - new_legacy_optimized, new_legacy) + (old_ir_optimized, old_legacy_optimized, old_legacy, old_ssa_cfg_optimized, + new_ir_optimized, new_legacy_optimized, new_legacy, new_ssa_cfg_optimized) All the values in the same file (in the diff) are summed up. @@ -88,7 +90,7 @@ def collect_statistics(lines) -> (int, int, int, int, int, int): if (parsed := diff_string.parse(line)) is not None ] diff_kinds = [Diff.Minus, Diff.Plus] - codegen_kinds = [Kind.IrOptimized, Kind.LegacyOptimized, Kind.Legacy] + codegen_kinds = [Kind.IrOptimized, Kind.LegacyOptimized, Kind.Legacy, Kind.SsaCFGOptimized] return tuple( sum( val @@ -141,23 +143,25 @@ def stat(old, new): parsed = parse_git_diff(fname) if parsed is None: continue - assert len(parsed) == 6 - ir_optimized = stat(parsed[0], parsed[3]) - legacy_optimized = stat(parsed[1], parsed[4]) - legacy = stat(parsed[2], parsed[5]) + assert len(parsed) == 8 + ir_optimized = stat(parsed[0], parsed[4]) + legacy_optimized = stat(parsed[1], parsed[5]) + legacy = stat(parsed[2], parsed[6]) + ssa_cfg_optimized = stat(parsed[3], parsed[7]) fname = f"`{fname.split('/', 3)[-1]}`" average = (( - percent_or_zero(parsed[0], parsed[3]) + - percent_or_zero(parsed[1], parsed[4]) + - percent_or_zero(parsed[2], parsed[5]) - ) / 3) - table += [[average, fname, ir_optimized, legacy_optimized, legacy]] + percent_or_zero(parsed[0], parsed[4]) + + percent_or_zero(parsed[1], parsed[5]) + + percent_or_zero(parsed[2], parsed[6]) + + percent_or_zero(parsed[3], parsed[7]) + ) / 4) + table += [[average, fname, ir_optimized, legacy_optimized, legacy, ssa_cfg_optimized]] sorted_table = [row[1:] for row in sorted(table, reverse=True)] if table: print("
Click for a table of gas differences\n") - table_header = ["File name", "IR optimized", "Legacy optimized", "Legacy"] + table_header = ["File name", "IR optimized", "Legacy optimized", "Legacy", "SSA CFG optimized"] print(tabulate(sorted_table, headers=table_header, tablefmt="github")) print("
") else: diff --git a/test/scripts/test_gas_diff_stats.py b/test/scripts/test_gas_diff_stats.py index e67bd0be8..4fe1576bf 100644 --- a/test/scripts/test_gas_diff_stats.py +++ b/test/scripts/test_gas_diff_stats.py @@ -11,13 +11,13 @@ class TestGasDiffStats(unittest.TestCase): def test_collect_statistics_should_fail_on_empty_diff(self): with self.assertRaises(RuntimeError): - self.assertEqual(collect_statistics(""), (0, 0, 0, 0, 0, 0)) + self.assertEqual(collect_statistics(""), (0, 0, 0, 0, 0, 0, 0, 0)) def test_collect_statistics_should_accept_whitespace_only_diff(self): # TODO: Should it really work this way? # If we're rejecting empty diff, not sure why whitespace is accepted. - self.assertEqual(collect_statistics("\n"), (0, 0, 0, 0, 0, 0)) - self.assertEqual(collect_statistics("\n \n\t\n\n"), (0, 0, 0, 0, 0, 0)) + self.assertEqual(collect_statistics("\n"), (0, 0, 0, 0, 0, 0, 0, 0)) + self.assertEqual(collect_statistics("\n \n\t\n\n"), (0, 0, 0, 0, 0, 0, 0, 0)) def test_collect_statistics_should_report_sum_of_gas_costs(self): diff_output = dedent(""" @@ -48,9 +48,11 @@ def test_collect_statistics_should_report_sum_of_gas_costs(self): 98438588 + 98438589, # -irOptimized 98438580 + 98438580, # -legacyOptimized 102095 + 98438774 + 98438774, # -legacy + 0, # -ssaCFGOptimized 25388 + 25389, # +irOptimized 25380 + 25380, # +legacyOptimized 76495 + 98413174 + 98413174, # +legacy + 0, # +ssaCFGOptimized )) def test_collect_statistics_should_ignore_ir_costs(self): @@ -65,9 +67,11 @@ def test_collect_statistics_should_ignore_ir_costs(self): 0, # -irOptimized 0, # -legacyOptimized 1, # -legacy + 0, # -ssaCFGOptimized 0, # +irOptimized 0, # +legacyOptimized 3, # +legacy + 0, # +ssaCFGOptimized )) def test_collect_statistics_should_ignore_unchanged_costs(self): @@ -81,9 +85,11 @@ def test_collect_statistics_should_ignore_unchanged_costs(self): 0, # -irOptimized 0, # -legacyOptimized 1, # -legacy + 0, # -ssaCFGOptimized 0, # +irOptimized 0, # +legacyOptimized 3, # +legacy + 0, # +ssaCFGOptimized )) def test_collect_statistics_should_include_code_deposit_in_total_cost(self): @@ -103,7 +109,9 @@ def test_collect_statistics_should_include_code_deposit_in_total_cost(self): 1, # -irOptimized 300, # -legacyOptimized 900000020, # -legacy + 0, # -ssaCFGOptimized 54000, # +irOptimized 87000000, # +legacyOptimized 600000, # +legacy + 0, # +ssaCFGOptimized )) From 436ccd5a09c6829d54f382378a8b72d781e942a6 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 5 Mar 2026 16:09:05 +0100 Subject: [PATCH 1161/1340] Make SSA CFG Codegen an experimental feature --- libsolidity/interface/CompilerStack.cpp | 3 +++ .../semanticTests/externalContracts/deposit_contract.sol | 1 + test/libsolidity/semanticTests/externalContracts/snark.sol | 1 + 3 files changed, 5 insertions(+) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 7d25fcf0d..a55b90719 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -780,6 +780,9 @@ CompilerStack::PipelineConfig CompilerStack::requestedPipelineConfig(ContractDef bool CompilerStack::compile(State _stopAfter) { m_stopAfter = _stopAfter; + + solAssert(!m_viaSSACFG || m_experimental, "SSA CFG code generation is an experimental feature. It requires experimental mode to be enabled."); + if (m_stackState < AnalysisSuccessful) if (!parseAndAnalyze(_stopAfter)) return false; diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index b6b5a0924..82d307cd5 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -176,6 +176,7 @@ contract DepositContract is IDepositContract, ERC165 { } // ==== // compileViaSSACFG: true +// experimental: true // ---- // constructor() // gas irOptimized: 809570 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index 4d303926b..0e6108c0f 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -288,6 +288,7 @@ contract Test { // ==== // EVMVersion: >=constantinople // compileViaSSACFG: true +// experimental: true // ---- // library: Pairing // f() -> true From d153bfe7d4694beceb7469cf4b6769fc7b2886ae Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:04:34 +0100 Subject: [PATCH 1162/1340] Stack shuffler: use mark-on-enqueue for bring up target slot stack traversal --- Changelog.md | 1 + libyul/backends/evm/StackHelpers.h | 7 +- ...huffler_bring_up_target_slot_bfs_dedup.yul | 83 +++++++++++++++++++ 3 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 test/libyul/yulOptimizerTests/fullSuite/stack_shuffler_bring_up_target_slot_bfs_dedup.yul diff --git a/Changelog.md b/Changelog.md index 823d346c7..aa3e2951f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: * General: Restrict the existing experimental features (`generic-solidity`, `lsp`, `ethdebug`, `eof`, `evm`, `ast-import`, `evmasm-import`, `ir-ast`, `ssa-cfg`) to experimental mode. * Metadata: Store the state of the experimental mode in JSON and CBOR metadata. In CBOR this broadens the meaning of the existing `experimental` field, which used to indicate only the presence of certain experimental pragmas in the source. * Standard JSON Interface: Introduce `settings.experimental` setting required for enabling the experimental mode. +* Yul EVM Code Transform: Improve stack shuffler performance by fixing a BFS deduplication issue. Bugfixes: diff --git a/libyul/backends/evm/StackHelpers.h b/libyul/backends/evm/StackHelpers.h index c5d638471..119642d12 100644 --- a/libyul/backends/evm/StackHelpers.h +++ b/libyul/backends/evm/StackHelpers.h @@ -186,13 +186,13 @@ class Shuffler static bool bringUpTargetSlot(ShuffleOperations& _ops, size_t _targetOffset) { std::list toVisit{_targetOffset}; - std::set visited; + // mark on enqueue + std::set visited{_targetOffset}; while (!toVisit.empty()) { auto offset = *toVisit.begin(); toVisit.erase(toVisit.begin()); - visited.emplace(offset); if (_ops.targetMultiplicity(offset) > 0) { _ops.pushOrDupTarget(offset); @@ -204,11 +204,12 @@ class Shuffler !_ops.isCompatible(nextOffset, nextOffset) && _ops.isCompatible(nextOffset, offset) ) - if (!visited.count(nextOffset)) + if (visited.insert(nextOffset).second) // insert returns false if already present toVisit.emplace_back(nextOffset); } return false; } + /// Performs a single stack operation, transforming the source layout closer to the target layout. template static bool shuffleStep(Args&&... args) diff --git a/test/libyul/yulOptimizerTests/fullSuite/stack_shuffler_bring_up_target_slot_bfs_dedup.yul b/test/libyul/yulOptimizerTests/fullSuite/stack_shuffler_bring_up_target_slot_bfs_dedup.yul new file mode 100644 index 000000000..53d64ca98 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/stack_shuffler_bring_up_target_slot_bfs_dedup.yul @@ -0,0 +1,83 @@ +// This is a regression test in context of https://github.com/argotorg/solidity/pull/16499: +// A BFS deduplication performance bug in `bringUpTargetSlot` where the same offset could be enqueued multiple times +// before being visited, by marking offsets as seen on enqueue rather than on dequeue. +{ + mstore(memoryguard(0x10000), 1) + sstore(mload(calldataload(0)), 1) + { + function foo_n_0(x_4, x_5) + { + if x_5 { + x_4 := 0x2000000000001 + } + x_4 := call( + call( + blockhash(0x200000000001), + 0x20000000001, + 0x2000000001, + mod("h", 32768), + mod(0x200000001, 32768), + mod(0x20000001, 32768), + mod(0x2000001, 32768) + ), + 0x200001, + 0x20001, + mod(0x2001, 32768), + mod(calldatasize(), 32768), + mod(calldatasize(), 32768), + mod( + call( + call( + x_4, + 0x201, + number(), + mod(0x21, 32768), + mod(0x3, 32768), + mod(0x3f, 32768), + mod(address(), 32768) + ), + 0x3ff, + 0x3fff, + mod(0x3ffff, 32768), + mod(9042383626829830, 32768), + mod(0x3fffff, 32768), + mod(0x3ffffff, 32768) + ), + 32768 + ) + ) + } + foo_n_0(0x200000000000000001, 0x20000000000000001) + foo_n_0(sload(224),calldataload(288)) + foo_n_0(0x3ffffffffffff, 0x3fffffffffffff) + foo_n_0(0x3fffffffffffffff, 0x3ffffffffffffffff) + foo_n_0(0x3ffffffffffffffffff, 0x3fffffffffffffffffff) + } +} +// ==== +// EVMVersion: >homestead +// ---- +// step: fullSuite +// +// { +// { +// mstore(memoryguard(0x010000), 1) +// sstore(mload(calldataload(0)), 1) +// let x := 0x200000000000000001 +// x := 0x2000000000001 +// let _1 := and(call(call(x, 0x201, number(), 0x21, 0x3, 0x3f, and(address(), 32767)), 0x3ff, 0x3fff, 32767, 6, 32767, 32767), 32767) +// pop(call(call(blockhash(0x200000000001), 0x20000000001, 0x2000000001, and("h", 32767), 1, 1, 1), 0x200001, 0x20001, 0x2001, and(calldatasize(), 32767), and(calldatasize(), 32767), _1)) +// let x_1 := sload(224) +// if calldataload(288) { x_1 := x } +// pop(call(call(blockhash(0x200000000001), 0x20000000001, 0x2000000001, and("h", 32767), 1, 1, 1), 0x200001, 0x20001, 0x2001, and(calldatasize(), 32767), and(calldatasize(), 32767), and(call(call(x_1, 0x201, number(), 0x21, 0x3, 0x3f, and(address(), 32767)), 0x3ff, 0x3fff, 32767, 6, 32767, 32767), 32767))) +// let x_2 := 0x3ffffffffffff +// x_2 := x +// pop(call(call(blockhash(0x200000000001), 0x20000000001, 0x2000000001, and("h", 32767), 1, 1, 1), 0x200001, 0x20001, 0x2001, and(calldatasize(), 32767), and(calldatasize(), 32767), and(call(call(x, 0x201, number(), 0x21, 0x3, 0x3f, and(address(), 32767)), 0x3ff, 0x3fff, 32767, 6, 32767, 32767), 32767))) +// let x_3 := 0x3fffffffffffffff +// x_3 := x +// pop(call(call(blockhash(0x200000000001), 0x20000000001, 0x2000000001, and("h", 32767), 1, 1, 1), 0x200001, 0x20001, 0x2001, and(calldatasize(), 32767), and(calldatasize(), 32767), and(call(call(x, 0x201, number(), 0x21, 0x3, 0x3f, and(address(), 32767)), 0x3ff, 0x3fff, 32767, 6, 32767, 32767), 32767))) +// let x_4 := 0x3ffffffffffffffffff +// x_4 := x +// pop(call(call(blockhash(0x200000000001), 0x20000000001, 0x2000000001, and("h", 32767), 1, 1, 1), 0x200001, 0x20001, 0x2001, and(calldatasize(), 32767), and(calldatasize(), 32767), and(call(call(x, 0x201, number(), 0x21, 0x3, 0x3f, and(address(), 32767)), 0x3ff, 0x3fff, 32767, 6, 32767, 32767), 32767))) +// } +// } From de054d1d44e4c530e0c89feb6eb7bb369648fb61 Mon Sep 17 00:00:00 2001 From: Masashi Takahashi <42906988+masshash@users.noreply.github.com> Date: Tue, 10 Mar 2026 19:31:13 +0900 Subject: [PATCH 1163/1340] docs: fix reentrancy vulnerability in micropayment close() example (#16497) Move freeze() call before external calls to follow the Checks-Effects-Interactions pattern and prevent reentrancy attacks in the SimplePaymentChannel contract. --- docs/examples/micropayment.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/micropayment.rst b/docs/examples/micropayment.rst index 373627c3d..377ee42f6 100644 --- a/docs/examples/micropayment.rst +++ b/docs/examples/micropayment.rst @@ -408,9 +408,9 @@ The full contract require(msg.sender == recipient); require(isValidSignature(amount, signature)); + freeze(); (bool success, ) = recipient.call{value: amount}(""); require(success); - freeze(); (success, ) = sender.call{value: address(this).balance}(""); require(success); } From 64e221f12a9342be3ca6017040d6de660caf7026 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 4 Mar 2026 10:22:22 +0100 Subject: [PATCH 1164/1340] ssa cfg codegen: make function return label slot handling explicit --- libyul/backends/evm/ssa/CodeTransform.cpp | 54 ++++++++------- libyul/backends/evm/ssa/CodeTransform.h | 2 + .../backends/evm/ssa/StackLayoutGenerator.cpp | 31 +++++++-- .../backends/evm/ssa/StackLayoutGenerator.h | 2 + libyul/backends/evm/ssa/StackUtils.cpp | 5 +- libyul/backends/evm/ssa/StackUtils.h | 2 +- .../ssa/stackLayoutGenerator/can_continue.yul | 67 +++++++++++++++++++ .../ssa/stackLayoutGenerator/function.yul | 24 +++---- .../ssa/stackLayoutGenerator/multi_return.yul | 12 ++-- .../ssa/stackLayoutGenerator/recursion.yul | 24 +++---- .../ssa/stackLayoutGenerator/simple_if.yul | 28 ++++---- 11 files changed, 176 insertions(+), 75 deletions(-) create mode 100644 test/libyul/ssa/stackLayoutGenerator/can_continue.yul diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 6dc33ad7b..ea8325694 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -107,7 +107,7 @@ CodeTransform::CodeTransform( SSACFG const& _cfg, SSACFGStackLayout const& _stackLayout, Scope::Function const* _function, - ControlFlow::FunctionGraphID + ControlFlow::FunctionGraphID _graphID ): m_assembly(_assembly), m_builtinContext(_builtinContext), @@ -115,6 +115,7 @@ CodeTransform::CodeTransform( m_callSites(_callSites), m_cfg(_cfg), m_stackLayout(_stackLayout), + m_graphID(_graphID), m_blockIsTransformed(_cfg.numBlocks(), false), m_blockLabels([this] { std::vector blockLabels; @@ -142,10 +143,12 @@ CodeTransform::CodeTransform( auto const findIt = m_functionLabels.find(_function); yulAssert(findIt != m_functionLabels.end()); m_assembly.appendLabel(findIt->second); - m_assembly.setStackHeight(static_cast(_function->numArguments)); + m_assembly.setStackHeight(static_cast(_function->numArguments) + (m_cfg.canContinue ? 1 : 0)); } StackData expectedStackTop; - expectedStackTop.reserve(m_cfg.arguments.size()); + expectedStackTop.reserve(m_cfg.arguments.size() + (m_cfg.function && m_cfg.canContinue ? 1 : 0)); + if (m_cfg.function && m_cfg.canContinue) + expectedStackTop.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); for (auto const& [_, valueID]: m_cfg.arguments | ranges::views::reverse) expectedStackTop.push_back(StackSlot::makeValueID(valueID)); assertLayoutCompatibility(m_stack.data(), expectedStackTop); @@ -339,35 +342,38 @@ void CodeTransform::operator()(SSACFG::BlockId const& _currentBlock, SSACFG::Bas void CodeTransform::operator()(SSACFG::BlockId const&, SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); + // Each CodeTransform instance handles exactly one function's CFG, so a FunctionReturn exit + // here necessarily belongs to m_cfg.function. No identity cross-check is needed. yulAssert(m_cfg.function); - // The return label sits physically below the tracked virtual stack. - // Inform the assembler so SWAP can reach it. - m_assembly.setStackHeight(m_assembly.stackHeight() + 1); - // Build target: [rv1, rv2, ..., rvN-1, rv0] (rv0 at top). - // After shuffle: EVM = [label, rv1, ..., rvN-1, rv0]. - // After SWAP(N): EVM = [rv0, rv1, ..., rvN-1, label]. - // After JUMP: EVM = [rv0, rv1, ..., rvN-1]. - // TODO: it would be better to account for function return labels from the entry of the function to the end symbolically - StackData returnTarget; - if (!_functionReturn.returnValues.empty()) + yulAssert(m_cfg.canContinue); + yulAssert(m_stack.size() == _functionReturn.returnValues.size() + 1, "There must be at least the function return label element on stack"); + yulAssert(m_stack.top().isFunctionReturnLabel()); + yulAssert(m_stack.top().functionReturnLabel() == m_graphID); + for (std::size_t i = 0; i < _functionReturn.returnValues.size(); ++i) { - returnTarget.reserve(_functionReturn.returnValues.size()); - for (std::size_t i = 1; i < _functionReturn.returnValues.size(); ++i) - returnTarget.push_back(StackSlot::makeValueID(_functionReturn.returnValues[i])); - returnTarget.push_back(StackSlot::makeValueID(_functionReturn.returnValues.front())); - StackShuffler::shuffle(m_stack, returnTarget, {}, returnTarget.size()); - m_assembly.appendInstruction(evmasm::swapInstruction( - static_cast(_functionReturn.returnValues.size()) - )); + auto const& returnValueSlot = m_stack.slot(StackOffset{i}); + yulAssert(returnValueSlot.isValueID()); + yulAssert(returnValueSlot.valueID() == _functionReturn.returnValues[i]); } - else - StackShuffler::shuffle(m_stack, returnTarget, {}, 0); m_assembly.appendJump(0, AbstractAssembly::JumpType::OutOfFunction); } -void CodeTransform::operator()(SSACFG::BlockId const&, SSACFG::BasicBlock::Terminated const&) +void CodeTransform::operator()(SSACFG::BlockId const& _blockId, SSACFG::BasicBlock::Terminated const&) { yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); + auto const& block = m_cfg.block(_blockId); + yulAssert(!block.operations.empty(), "Terminated block must have at least one operation."); + std::visit(util::GenericVisitor{ + [](SSACFG::BuiltinCall const& _builtin) { + yulAssert(_builtin.builtin.get().controlFlowSideEffects.terminatesOrReverts(), "Last operation of Terminated block must terminate or revert."); + }, + [](SSACFG::Call const& _call) { + yulAssert(!_call.canContinue, "Last operation of Terminated block must be a non-continuable call."); + }, + [](SSACFG::LiteralAssignment const&) { + yulAssert(false, "Terminated block cannot end with a literal assignment."); + } + }, block.operations.back().kind); // To be sure just emit another INVALID - should be removed by optimizer. m_assembly.appendInstruction(evmasm::Instruction::INVALID); } diff --git a/libyul/backends/evm/ssa/CodeTransform.h b/libyul/backends/evm/ssa/CodeTransform.h index 0764731c9..8898b41b5 100644 --- a/libyul/backends/evm/ssa/CodeTransform.h +++ b/libyul/backends/evm/ssa/CodeTransform.h @@ -67,6 +67,7 @@ struct AssemblyCallbacks case StackSlot::Kind::FunctionCallReturnLabel: { auto const& call = callSites->functionCall(_slot.functionCallReturnLabel()); + yulAssert(returnLabels->count(&call), "FunctionCallReturnLabel not pre-registered before shuffle."); assembly->appendLabelReference(returnLabels->at(&call)); return; } @@ -132,6 +133,7 @@ class CodeTransform CallSites const& m_callSites; SSACFG const& m_cfg; SSACFGStackLayout const& m_stackLayout; + ControlFlow::FunctionGraphID const m_graphID; std::vector m_blockIsTransformed; std::vector m_blockLabels; diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 8e5f9b07a..78d9dbfec 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -77,15 +78,25 @@ void declareJunk(StackType& _stack, LivenessAnalysis::LivenessData const& _live) } -SSACFGStackLayout StackLayoutGenerator::generate(LivenessAnalysis const& _liveness, CallSites const& _callSites, ControlFlow::FunctionGraphID _graphID) +SSACFGStackLayout StackLayoutGenerator::generate( + LivenessAnalysis const& _liveness, + CallSites const& _callSites, + ControlFlow::FunctionGraphID const _graphID +) { return StackLayoutGenerator(_liveness, _callSites, _graphID).m_resultLayout; } -StackLayoutGenerator::StackLayoutGenerator(LivenessAnalysis const& _liveness, CallSites const& _callSites, ControlFlow::FunctionGraphID): +StackLayoutGenerator::StackLayoutGenerator( + LivenessAnalysis const& _liveness, + CallSites const& _callSites, + ControlFlow::FunctionGraphID const _graphID +): m_cfg(_liveness.cfg()), m_liveness(_liveness), m_callSites(_callSites), + m_graphID(_graphID), + m_hasFunctionReturnLabel(_liveness.cfg().function && _liveness.cfg().canContinue), m_junkAdmittingBlocksFinder(std::make_unique(_liveness.cfg(), _liveness.topologicalSort())), m_resultLayout(m_cfg.numBlocks()) { @@ -133,6 +144,9 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) { if (m_cfg.function) { + blockLayout.stackIn.reserve(m_cfg.arguments.size() + (m_hasFunctionReturnLabel ? 1u : 0u)); + if (m_hasFunctionReturnLabel) + blockLayout.stackIn.push_back(Slot::makeFunctionReturnLabel(m_graphID)); for (auto const& [_, valueID]: m_cfg.arguments | ranges::views::reverse) blockLayout.stackIn.push_back(Slot::makeValueID(valueID)); } @@ -246,7 +260,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) ) stack.declareJunk(depth); - std::size_t const targetSize = findOptimalTargetSize(stack.data(), requiredStackTop, opLiveOutWithoutOutputs, junkCanBeAdded); + std::size_t const targetSize = findOptimalTargetSize(stack.data(), requiredStackTop, opLiveOutWithoutOutputs, junkCanBeAdded, m_hasFunctionReturnLabel); StackShuffler::shuffle( stack, requiredStackTop, @@ -274,7 +288,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) if (!conditionSlotAlreadyFinal) { auto const condition = Slot::makeValueID(cjump->condition); - auto const targetSize = findOptimalTargetSize(stack.data(), {condition}, blockLiveOut, false); + auto const targetSize = findOptimalTargetSize(stack.data(), {condition}, blockLiveOut, false, m_hasFunctionReturnLabel); StackShuffler::shuffle( stack, {condition}, blockLiveOut, targetSize ); @@ -306,5 +320,14 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) } } + if (auto const* functionReturn = std::get_if(&block.exit)) + { + yulAssert(m_hasFunctionReturnLabel, "When there is a proper function return, we need to have a label for it"); + // in case there are return values, let's bring the function return label to the top + StackData returnStack = functionReturn->returnValues | ranges::views::transform(StackSlot::makeValueID) | ranges::to; + returnStack.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); + StackShuffler::shuffle(stack, returnStack); + } + blockLayout.stackOut = currentStackData; } diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.h b/libyul/backends/evm/ssa/StackLayoutGenerator.h index a1acfa57d..b14586404 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.h +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.h @@ -51,6 +51,8 @@ class StackLayoutGenerator SSACFG const& m_cfg; LivenessAnalysis const& m_liveness; CallSites const& m_callSites; + ControlFlow::FunctionGraphID m_graphID; + bool m_hasFunctionReturnLabel; std::unique_ptr m_junkAdmittingBlocksFinder; SSACFGStackLayout m_resultLayout; diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index d15b45a16..7f7a79795 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -44,10 +44,11 @@ std::size_t solidity::yul::ssa::findOptimalTargetSize StackData const& _stackData, StackData const& _targetArgs, LivenessAnalysis::LivenessData const& _targetLiveOut, - bool const _canIntroduceJunk + bool const _canIntroduceJunk, + bool const _hasFunctionReturnLabel ) { - std::size_t const minSize = _targetLiveOut.size() + _targetArgs.size(); + std::size_t const minSize = _targetLiveOut.size() + _targetArgs.size() + (_hasFunctionReturnLabel ? 1 : 0); boost::container::flat_map deficit; for (auto const& v: _targetLiveOut | ranges::views::keys) deficit[StackSlot::makeValueID(v)]++; diff --git a/libyul/backends/evm/ssa/StackUtils.h b/libyul/backends/evm/ssa/StackUtils.h index 7d3088873..cfc3fa96b 100644 --- a/libyul/backends/evm/ssa/StackUtils.h +++ b/libyul/backends/evm/ssa/StackUtils.h @@ -50,7 +50,7 @@ struct CountingInstructionsCallbacks /// Transform stack data by replacing all its phi variables with their respective preimages. StackData stackPreImage(StackData _stack, PhiInverse const& _phiInverse); -std::size_t findOptimalTargetSize(StackData const& _stackData, StackData const& _targetArgs, LivenessAnalysis::LivenessData const& _targetLiveOut, bool _canIntroduceJunk); +std::size_t findOptimalTargetSize(StackData const& _stackData, StackData const& _targetArgs, LivenessAnalysis::LivenessData const& _targetLiveOut, bool _canIntroduceJunk, bool _hasFunctionReturnLabel); CallSites gatherCallSites(SSACFG const& _cfg); diff --git a/test/libyul/ssa/stackLayoutGenerator/can_continue.yul b/test/libyul/ssa/stackLayoutGenerator/can_continue.yul new file mode 100644 index 000000000..e04a9b6b6 --- /dev/null +++ b/test/libyul/ssa/stackLayoutGenerator/can_continue.yul @@ -0,0 +1,67 @@ +{ + // a function that can continue depending on condition + function revert_wrapper(val, condition) + { + if iszero(condition) + { + revert(val, val) + } + // if we don't revert, we return nothing and the stack out should contain nothing but the return label + } + + revert_wrapper(42, 1) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans", rankdir=LR] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry [label="Entry"]; +// Entry -> Block0_0; +// Block0_0 [label="\ +// IN: []\l\ +// \l\ +// [FunctionCallReturnLabel[0], lit0, lit1]\l\ +// revert_wrapper\l\ +// [FunctionCallReturnLabel[0]]\l\ +// \l\ +// OUT: []\l\ +// "]; +// Block0_0Exit [label="MainExit"]; +// Block0_0 -> Block0_0Exit; +// FunctionEntry_revert_wrapper_0 [label="function revert_wrapper: +// revert_wrapper(v0, v1)"]; +// FunctionEntry_revert_wrapper_0 -> Block1_0; +// Block1_0 [label="\ +// IN: [ReturnLabel[1], v1, v0]\l\ +// \l\ +// [ReturnLabel[1], v0, v1]\l\ +// iszero\l\ +// [ReturnLabel[1], v0, v2]\l\ +// \l\ +// OUT: [ReturnLabel[1], v0, v2]\l\ +// "]; +// Block1_0 -> Block1_0Exit; +// Block1_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_0Exit:0 -> Block1_2 [style="solid"]; +// Block1_0Exit:1 -> Block1_1 [style="solid"]; +// Block1_1 [label="\ +// IN: [ReturnLabel[1], v0]\l\ +// \l\ +// [ReturnLabel[1], v0, v0]\l\ +// revert\l\ +// [ReturnLabel[1]]\l\ +// \l\ +// OUT: [ReturnLabel[1]]\l\ +// "]; +// Block1_1Exit [label="Terminated"]; +// Block1_1 -> Block1_1Exit; +// Block1_2 [label="\ +// IN: [ReturnLabel[1], JUNK]\l\ +// \l\ +// OUT: [ReturnLabel[1]]\l\ +// "]; +// Block1_2Exit [label="FunctionReturn[]"]; +// Block1_2 -> Block1_2Exit; +// } diff --git a/test/libyul/ssa/stackLayoutGenerator/function.yul b/test/libyul/ssa/stackLayoutGenerator/function.yul index a134c36f8..c7e3c3209 100644 --- a/test/libyul/ssa/stackLayoutGenerator/function.yul +++ b/test/libyul/ssa/stackLayoutGenerator/function.yul @@ -47,17 +47,17 @@ // r := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// IN: [v1, v0]\l\ +// IN: [ReturnLabel[1], v1, v0]\l\ // \l\ -// [v0, v1, v0]\l\ +// [ReturnLabel[1], v0, v1, v0]\l\ // add\l\ -// [v0, v2]\l\ +// [ReturnLabel[1], v0, v2]\l\ // \l\ -// [v0, v2]\l\ +// [ReturnLabel[1], v0, v2]\l\ // sub\l\ -// [v3]\l\ +// [ReturnLabel[1], v3]\l\ // \l\ -// OUT: [v3]\l\ +// OUT: [v3, ReturnLabel[1]]\l\ // "]; // Block1_0Exit [label="FunctionReturn[v3]"]; // Block1_0 -> Block1_0Exit; @@ -65,13 +65,13 @@ // g()"]; // FunctionEntry_g_0 -> Block2_0; // Block2_0 [label="\ -// IN: []\l\ +// IN: [ReturnLabel[2]]\l\ // \l\ -// [lit0, lit1]\l\ +// [ReturnLabel[2], lit0, lit1]\l\ // sstore\l\ -// []\l\ +// [ReturnLabel[2]]\l\ // \l\ -// OUT: []\l\ +// OUT: [ReturnLabel[2]]\l\ // "]; // Block2_0Exit [label="FunctionReturn[]"]; // Block2_0 -> Block2_0Exit; @@ -97,9 +97,9 @@ // v, w := i()"]; // FunctionEntry_i_0 -> Block4_0; // Block4_0 [label="\ -// IN: []\l\ +// IN: [ReturnLabel[4]]\l\ // \l\ -// OUT: []\l\ +// OUT: [lit1, lit2, ReturnLabel[4]]\l\ // "]; // Block4_0Exit [label="FunctionReturn[0x0202, 0x0303]"]; // Block4_0 -> Block4_0Exit; diff --git a/test/libyul/ssa/stackLayoutGenerator/multi_return.yul b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul index c1f2b94d4..76d4c8808 100644 --- a/test/libyul/ssa/stackLayoutGenerator/multi_return.yul +++ b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul @@ -42,17 +42,17 @@ // x, y := pair(v0)"]; // FunctionEntry_pair_0 -> Block1_0; // Block1_0 [label="\ -// IN: [v0]\l\ +// IN: [ReturnLabel[1], v0]\l\ // \l\ -// [v0, lit1, v0]\l\ +// [ReturnLabel[1], v0, lit1, v0]\l\ // add\l\ -// [v0, v1]\l\ +// [ReturnLabel[1], v0, v1]\l\ // \l\ -// [v1, lit2, v0]\l\ +// [ReturnLabel[1], v1, lit2, v0]\l\ // add\l\ -// [v1, v2]\l\ +// [ReturnLabel[1], v1, v2]\l\ // \l\ -// OUT: [v1, v2]\l\ +// OUT: [v1, v2, ReturnLabel[1]]\l\ // "]; // Block1_0Exit [label="FunctionReturn[v1, v2]"]; // Block1_0 -> Block1_0Exit; diff --git a/test/libyul/ssa/stackLayoutGenerator/recursion.yul b/test/libyul/ssa/stackLayoutGenerator/recursion.yul index 4a33f172d..493532337 100644 --- a/test/libyul/ssa/stackLayoutGenerator/recursion.yul +++ b/test/libyul/ssa/stackLayoutGenerator/recursion.yul @@ -33,38 +33,38 @@ // s := sum(v0)"]; // FunctionEntry_sum_0 -> Block1_0; // Block1_0 [label="\ -// IN: [v0]\l\ +// IN: [ReturnLabel[1], v0]\l\ // \l\ -// OUT: [v0, v0]\l\ +// OUT: [ReturnLabel[1], v0, v0]\l\ // "]; // Block1_0 -> Block1_0Exit; // Block1_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_0Exit:0 -> Block1_2 [style="solid"]; // Block1_0Exit:1 -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// IN: [v0]\l\ +// IN: [ReturnLabel[1], v0]\l\ // \l\ -// [v0, lit1, v0]\l\ +// [ReturnLabel[1], v0, lit1, v0]\l\ // sub\l\ -// [v0, v1]\l\ +// [ReturnLabel[1], v0, v1]\l\ // \l\ -// [v0, FunctionCallReturnLabel[0], v1]\l\ +// [ReturnLabel[1], v0, FunctionCallReturnLabel[0], v1]\l\ // sum\l\ -// [v0, FunctionCallReturnLabel[0], v2]\l\ +// [ReturnLabel[1], v0, FunctionCallReturnLabel[0], v2]\l\ // \l\ -// [v2, v0]\l\ +// [ReturnLabel[1], v2, v0]\l\ // add\l\ -// [v3]\l\ +// [ReturnLabel[1], v3]\l\ // \l\ -// OUT: [v3]\l\ +// OUT: [ReturnLabel[1], v3]\l\ // "]; // Block1_1 -> Block1_1Exit [arrowhead=none]; // Block1_1Exit [label="Jump" shape=oval]; // Block1_1Exit -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// IN: [JUNK, phi0]\l\ +// IN: [ReturnLabel[1], JUNK, phi0]\l\ // \l\ -// OUT: [JUNK, phi0]\l\ +// OUT: [phi0, ReturnLabel[1]]\l\ // "]; // Block1_2Exit [label="FunctionReturn[phi0]"]; // Block1_2 -> Block1_2Exit; diff --git a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul index f9e0039e3..2b72e0cea 100644 --- a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul +++ b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul @@ -35,41 +35,41 @@ // c := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ -// IN: [v1, v0]\l\ +// IN: [ReturnLabel[1], v1, v0]\l\ // \l\ -// [v1, v0, v0]\l\ +// [ReturnLabel[1], v1, v0, v0]\l\ // mload\l\ -// [v1, v0, v2]\l\ +// [ReturnLabel[1], v1, v0, v2]\l\ // \l\ -// OUT: [v1, v0, v2]\l\ +// OUT: [ReturnLabel[1], v1, v0, v2]\l\ // "]; // Block1_0 -> Block1_0Exit; // Block1_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_0Exit:0 -> Block1_2 [style="solid"]; // Block1_0Exit:1 -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// IN: [v1, v0]\l\ +// IN: [ReturnLabel[1], v1, v0]\l\ // \l\ -// [JUNK, v0, lit1, v0]\l\ +// [ReturnLabel[1], JUNK, v0, lit1, v0]\l\ // add\l\ -// [JUNK, v0, v3]\l\ +// [ReturnLabel[1], JUNK, v0, v3]\l\ // \l\ -// [JUNK, JUNK, v3, v3]\l\ +// [ReturnLabel[1], JUNK, JUNK, v3, v3]\l\ // revert\l\ -// [JUNK, JUNK]\l\ +// [ReturnLabel[1], JUNK, JUNK]\l\ // \l\ -// OUT: [JUNK, JUNK]\l\ +// OUT: [ReturnLabel[1], JUNK, JUNK]\l\ // "]; // Block1_1Exit [label="Terminated"]; // Block1_1 -> Block1_1Exit; // Block1_2 [label="\ -// IN: [v1, v0]\l\ +// IN: [ReturnLabel[1], v1, v0]\l\ // \l\ -// [v1, v0]\l\ +// [ReturnLabel[1], v1, v0]\l\ // add\l\ -// [v4]\l\ +// [ReturnLabel[1], v4]\l\ // \l\ -// OUT: [v4]\l\ +// OUT: [v4, ReturnLabel[1]]\l\ // "]; // Block1_2Exit [label="FunctionReturn[v4]"]; // Block1_2 -> Block1_2Exit; From fab9d5c2bcc1078b7f6b97804a903623af5254ad Mon Sep 17 00:00:00 2001 From: Mate Soos Date: Tue, 10 Mar 2026 17:17:59 +0100 Subject: [PATCH 1165/1340] Fix invalid reference use --- libsolidity/interface/CompilerStack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index a55b90719..96c0d3f6c 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -379,7 +379,7 @@ bool CompilerStack::parse() for (size_t i = 0; i < sourcesToParse.size(); ++i) { - std::string const& path = sourcesToParse[i]; + std::string const path = sourcesToParse[i]; Source& source = m_sources[path]; source.ast = parser.parse(*source.charStream); if (!source.ast) From f47fa8da1628fb4d909fa790c7c384ef83bf26bd Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 18 Mar 2025 01:11:48 -0300 Subject: [PATCH 1166/1340] Add and update tests --- .../args | 1 + .../input.sol | 9 ++ .../output | 35 +++++++ .../yul_optimizer_erc7201_param_calldata/args | 1 + .../input.sol | 9 ++ .../output | 59 +++++++++++ .../yul_optimizer_erc7201_param_memory/args | 1 + .../input.sol | 10 ++ .../yul_optimizer_erc7201_param_memory/output | 48 +++++++++ .../yul_optimizer_erc7201_param_storage/args | 1 + .../input.sol | 10 ++ .../output | 97 +++++++++++++++++++ .../erc7201_equivalent_solidity_spec.sol | 26 +++++ ...7201_equivalent_solidity_spec_comptime.sol | 16 +++ ...1_layout_specifier_slot_match_comptime.sol | 19 ++++ .../erc7201_overflow_expression.sol | 7 ++ .../erc7201_param_abi_encode.sol | 20 ++++ .../erc7201_param_array_string_literal.sol | 7 ++ .../erc7201_param_locations.sol | 37 +++++++ .../erc7201_param_pure_function.sol | 17 ++++ .../erc7201_param_string_concat.sol | 15 +++ ...aram_string_literal_with_escaped_chars.sol | 18 ++++ .../erc7201_param_ternary_operator.sol | 18 ++++ .../erc7201_param_unicode_string_literal.sol | 14 +++ .../erc7201_param_unicode_string_variable.sol | 15 +++ ...aram_with_zero_last_byte_of_inner_hash.sol | 26 +++++ ..._zero_last_byte_of_inner_hash_comptime.sol | 24 +++++ .../array/length/builtin_erc7201_comptime.sol | 5 + .../array/length/string_as_array_length.sol | 8 ++ .../constantEvaluator/erc7201_builtin.sol | 6 ++ .../erc7201_builtin_abi_encode_comptime.sol | 3 + ...01_builtin_function_pointer_assignment.sol | 8 ++ ...rc7201_builtin_function_shadow_warning.sol | 5 + ...01_builtin_invalid_gas_function_option.sol | 7 ++ .../erc7201_builtin_no_call.sol | 7 ++ ...1_builtin_overflow_expression_comptime.sol | 5 + ...uiltin_param_bytes_converted_to_string.sol | 8 ++ ...in_param_constant_string_unitary_tuple.sol | 7 ++ .../erc7201_builtin_param_invalid_bytes.sol | 9 ++ ...7201_builtin_param_invalid_hex_literal.sol | 7 ++ ...1_builtin_param_invalid_number_literal.sol | 8 ++ .../erc7201_builtin_param_named.sol | 5 + ...in_param_string_unitary_tuple_comptime.sol | 2 + ...string_var_with_escaped_chars_comptime.sol | 3 + .../erc7201_builtin_param_string_variable.sol | 21 ++++ ...builtin_param_string_variable_comptime.sol | 6 ++ ...param_string_with_whitespaces_comptime.sol | 6 ++ .../erc7201_builtin_param_unicode_literal.sol | 6 ++ .../erc7201_builtin_param_wrong_count.sol | 9 ++ ...1_builtin_variable_name_shadow_warning.sol | 5 + .../erc7201_builtin_const_var_assignment.sol | 7 ++ .../erc7201_builtin_invalid_member_gas.sol | 7 ++ .../erc7201_builtin_invalid_member_value.sol | 7 ++ ...iltin_param_constant_variable_comptime.sol | 3 + ...am_imported_constant_variable_comptime.sol | 6 ++ ..._builtin_param_string_literal_comptime.sol | 2 + .../erc7201_builtin_as_custom_operator.sol | 3 + .../using/erc7201_builtin_using_for.sol | 3 + 58 files changed, 754 insertions(+) create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/args create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/input.sol create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/output create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_param_calldata/args create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_param_calldata/input.sol create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_param_calldata/output create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_param_memory/args create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_param_memory/input.sol create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_param_memory/output create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_param_storage/args create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_param_storage/input.sol create mode 100644 test/cmdlineTests/yul_optimizer_erc7201_param_storage/output create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_equivalent_solidity_spec.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_equivalent_solidity_spec_comptime.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_layout_specifier_slot_match_comptime.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_overflow_expression.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_param_abi_encode.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_param_array_string_literal.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_param_locations.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_param_pure_function.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_param_string_concat.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_param_string_literal_with_escaped_chars.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_param_ternary_operator.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_param_unicode_string_literal.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_param_unicode_string_variable.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_param_with_zero_last_byte_of_inner_hash.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/erc7201_param_with_zero_last_byte_of_inner_hash_comptime.sol create mode 100644 test/libsolidity/syntaxTests/array/length/builtin_erc7201_comptime.sol create mode 100644 test/libsolidity/syntaxTests/array/length/string_as_array_length.sol create mode 100644 test/libsolidity/syntaxTests/constantEvaluator/erc7201_builtin.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_abi_encode_comptime.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_function_pointer_assignment.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_function_shadow_warning.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_invalid_gas_function_option.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_no_call.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_overflow_expression_comptime.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_bytes_converted_to_string.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_constant_string_unitary_tuple.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_bytes.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_hex_literal.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_number_literal.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_named.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_unitary_tuple_comptime.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_var_with_escaped_chars_comptime.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_variable.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_variable_comptime.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_with_whitespaces_comptime.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_unicode_literal.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_wrong_count.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_variable_name_shadow_warning.sol create mode 100644 test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_const_var_assignment.sol create mode 100644 test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_invalid_member_gas.sol create mode 100644 test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_invalid_member_value.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_constant_variable_comptime.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_imported_constant_variable_comptime.sol create mode 100644 test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_string_literal_comptime.sol create mode 100644 test/libsolidity/syntaxTests/using/erc7201_builtin_as_custom_operator.sol create mode 100644 test/libsolidity/syntaxTests/using/erc7201_builtin_using_for.sol diff --git a/test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/args b/test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/args new file mode 100644 index 000000000..a536442c5 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/args @@ -0,0 +1 @@ +--ir-optimized --optimize --debug-info none diff --git a/test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/input.sol b/test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/input.sol new file mode 100644 index 000000000..2918637d6 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/input.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract C { + function f() public pure returns (uint) { + // IR output should contain the value calculated in compile time: + // 0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab500 + return erc7201("example.main"); + } +} diff --git a/test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/output b/test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/output new file mode 100644 index 000000000..c25f058dd --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_literal_comptime_evaluation/output @@ -0,0 +1,35 @@ +Optimized IR: +/// @use-src 0:"input.sol" +object "C_12" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_12_deployed") + codecopy(_1, dataoffset("C_12_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"input.sol" + object "C_12_deployed" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if iszero(lt(calldatasize(), 4)) + { + if eq(0x26121ff0, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + mstore(_1, 0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab500) + return(_1, 32) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/yul_optimizer_erc7201_param_calldata/args b/test/cmdlineTests/yul_optimizer_erc7201_param_calldata/args new file mode 100644 index 000000000..a536442c5 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_param_calldata/args @@ -0,0 +1 @@ +--ir-optimized --optimize --debug-info none diff --git a/test/cmdlineTests/yul_optimizer_erc7201_param_calldata/input.sol b/test/cmdlineTests/yul_optimizer_erc7201_param_calldata/input.sol new file mode 100644 index 000000000..3175540ec --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_param_calldata/input.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract C { + function f(string calldata id) public pure returns (uint) { + // Conversion of input from calldata to memory + // requires encoding which will appear in the IR output + return erc7201(id); + } +} diff --git a/test/cmdlineTests/yul_optimizer_erc7201_param_calldata/output b/test/cmdlineTests/yul_optimizer_erc7201_param_calldata/output new file mode 100644 index 000000000..4ab15b848 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_param_calldata/output @@ -0,0 +1,59 @@ +Optimized IR: +/// @use-src 0:"input.sol" +object "C_14" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_14_deployed") + codecopy(_1, dataoffset("C_14_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"input.sol" + object "C_14_deployed" { + code { + { + let _1 := memoryguard(0x80) + if iszero(lt(calldatasize(), 4)) + { + if eq(0x91e145ef, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 32) { revert(0, 0) } + let offset := calldataload(4) + if gt(offset, 0xffffffffffffffff) { revert(0, 0) } + if iszero(slt(add(offset, 35), calldatasize())) { revert(0, 0) } + let length := calldataload(add(4, offset)) + let _2 := gt(length, 0xffffffffffffffff) + if _2 { revert(0, 0) } + let _3 := gt(add(add(offset, length), 36), calldatasize()) + if _3 { revert(0, 0) } + _2 := 0 + let newFreePtr := add(_1, and(add(and(add(length, 0x1f), not(31)), 63), not(31))) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _1)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x41) + revert(0, 36) + } + mstore(64, newFreePtr) + mstore(_1, length) + let dst := add(_1, 32) + _3 := 0 + calldatacopy(dst, add(offset, 36), length) + mstore(add(add(_1, length), 32), 0) + mstore(0, add(keccak256(dst, mload(_1)), not(0))) + let slot := and(keccak256(0, 32), not(255)) + let memPos := mload(64) + mstore(memPos, slot) + return(memPos, 32) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/yul_optimizer_erc7201_param_memory/args b/test/cmdlineTests/yul_optimizer_erc7201_param_memory/args new file mode 100644 index 000000000..a536442c5 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_param_memory/args @@ -0,0 +1 @@ +--ir-optimized --optimize --debug-info none diff --git a/test/cmdlineTests/yul_optimizer_erc7201_param_memory/input.sol b/test/cmdlineTests/yul_optimizer_erc7201_param_memory/input.sol new file mode 100644 index 000000000..91ee533eb --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_param_memory/input.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract C { + function f() public pure returns (uint) { + // No encoding necessary, IR output will show value + // loaded directly from memory. + string memory namespaceID = "example.main"; + return erc7201(namespaceID); + } +} diff --git a/test/cmdlineTests/yul_optimizer_erc7201_param_memory/output b/test/cmdlineTests/yul_optimizer_erc7201_param_memory/output new file mode 100644 index 000000000..aa9f5871e --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_param_memory/output @@ -0,0 +1,48 @@ +Optimized IR: +/// @use-src 0:"input.sol" +object "C_16" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_16_deployed") + codecopy(_1, dataoffset("C_16_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"input.sol" + object "C_16_deployed" { + code { + { + let _1 := memoryguard(0x80) + if iszero(lt(calldatasize(), 4)) + { + if eq(0x26121ff0, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + let newFreePtr := add(_1, 64) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _1)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x41) + revert(0, 0x24) + } + mstore(64, newFreePtr) + mstore(_1, 12) + let _2 := add(_1, 32) + mstore(_2, "example.main") + mstore(0, add(keccak256(_2, 12), not(0))) + let slot := and(keccak256(0, 32), not(255)) + let memPos := mload(64) + mstore(memPos, slot) + return(memPos, 32) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/yul_optimizer_erc7201_param_storage/args b/test/cmdlineTests/yul_optimizer_erc7201_param_storage/args new file mode 100644 index 000000000..a536442c5 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_param_storage/args @@ -0,0 +1 @@ +--ir-optimized --optimize --debug-info none diff --git a/test/cmdlineTests/yul_optimizer_erc7201_param_storage/input.sol b/test/cmdlineTests/yul_optimizer_erc7201_param_storage/input.sol new file mode 100644 index 000000000..9aede654a --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_param_storage/input.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract C { + string namespace = "example.main"; + function f() public view returns (uint) { + // Conversion of input from storage to memory + // requires encoding which will appear in the IR output + return erc7201(namespace); + } +} diff --git a/test/cmdlineTests/yul_optimizer_erc7201_param_storage/output b/test/cmdlineTests/yul_optimizer_erc7201_param_storage/output new file mode 100644 index 000000000..dea93fb0d --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_erc7201_param_storage/output @@ -0,0 +1,97 @@ +Optimized IR: +/// @use-src 0:"input.sol" +object "C_15" { + code { + { + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := sload(0x00) + let length := 0x00 + length := shr(1, _2) + let outOfPlaceEncoding := and(_2, 1) + if iszero(outOfPlaceEncoding) { length := and(length, 0x7f) } + if eq(outOfPlaceEncoding, lt(length, 32)) + { + mstore(0x00, shl(224, 0x4e487b71)) + mstore(4, 0x22) + revert(0x00, 0x24) + } + if gt(length, 31) + { + if gt(length, 12) + { + mstore(0x00, 0x00) + let data := keccak256(0x00, 32) + let oldSlotCount := shr(5, add(length, 31)) + let i := 0x00 + for { } lt(i, oldSlotCount) { i := add(i, 1) } + { sstore(add(data, i), 0x00) } + } + } + sstore(0x00, add("example.main", 24)) + let _3 := datasize("C_15_deployed") + codecopy(_1, dataoffset("C_15_deployed"), _3) + return(_1, _3) + } + } + /// @use-src 0:"input.sol" + object "C_15_deployed" { + code { + { + let _1 := memoryguard(0x80) + if iszero(lt(calldatasize(), 4)) + { + if eq(0x26121ff0, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + let ret := 0 + let slotValue := sload(0) + let length := 0 + length := shr(1, slotValue) + let outOfPlaceEncoding := and(slotValue, 1) + if iszero(outOfPlaceEncoding) { length := and(length, 0x7f) } + if eq(outOfPlaceEncoding, lt(length, 32)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x22) + revert(0, 0x24) + } + mstore(_1, length) + let updated_pos := add(_1, 32) + switch outOfPlaceEncoding + case 0 { + mstore(updated_pos, and(slotValue, not(255))) + ret := add(add(_1, shl(5, iszero(iszero(length)))), 32) + } + case 1 { + mstore(0, 0) + let dataPos := 18569430475105882587588266137607568536673111973893317399460219858819262702947 + let i := 0 + for { } lt(i, length) { i := add(i, 32) } + { + mstore(add(add(_1, i), 32), sload(dataPos)) + dataPos := add(dataPos, 1) + } + ret := add(add(_1, i), 32) + } + let newFreePtr := add(_1, and(add(sub(ret, _1), 31), not(31))) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _1)) + { + mstore(0, shl(224, 0x4e487b71)) + mstore(4, 0x41) + revert(0, 0x24) + } + mstore(64, newFreePtr) + mstore(0, add(keccak256(updated_pos, mload(_1)), not(0))) + mstore(newFreePtr, and(keccak256(0, 32), not(255))) + return(newFreePtr, 32) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_equivalent_solidity_spec.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_equivalent_solidity_spec.sol new file mode 100644 index 000000000..32378c19c --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_equivalent_solidity_spec.sol @@ -0,0 +1,26 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + // value from EIP-7201 (https://eips.ethereum.org/EIPS/eip-7201) + uint expectedSlot = 0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab500; + string namespace = "example.main"; + + function builtinMatchesSolidityImplementation() public view returns (bool) { + assert(expectedSlot == erc7201Mock(namespace)); + + return + erc7201(namespace) == erc7201Mock("example.main") && + erc7201("example.main") == erc7201Mock("example.main"); + } + function builtinOutput() public view returns (uint) { + return erc7201(namespace); + } +} +// ---- +// builtinMatchesSolidityImplementation() -> true +// builtinOutput() -> 0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab500 diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_equivalent_solidity_spec_comptime.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_equivalent_solidity_spec_comptime.sol new file mode 100644 index 000000000..ca387f1ae --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_equivalent_solidity_spec_comptime.sol @@ -0,0 +1,16 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + uint8[erc7201("example.main")] array; + + function builtinMatchesSolidityImplementation() public view returns (bool) { + return array.length == erc7201Mock("example.main"); + } +} +// ---- +// builtinMatchesSolidityImplementation() -> true diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_layout_specifier_slot_match_comptime.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_layout_specifier_slot_match_comptime.sol new file mode 100644 index 000000000..88e9f2507 --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_layout_specifier_slot_match_comptime.sol @@ -0,0 +1,19 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C layout at erc7201("example.main") { + uint x; + function builtinMatchesSolidityImplementation() public pure returns (bool) { + uint firstSlot; + assembly { + firstSlot := x.slot + } + return firstSlot == erc7201Mock("example.main"); + } +} +// ---- +// builtinMatchesSolidityImplementation() -> true diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_overflow_expression.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_overflow_expression.sol new file mode 100644 index 000000000..9eb9af93d --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_overflow_expression.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns (uint) { + return erc7201("main:example") + erc7201("main:example"); + } +} +// ---- +// f() -> FAILURE, hex"4e487b71", 0x11 diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_abi_encode.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_abi_encode.sol new file mode 100644 index 000000000..e837564f9 --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_abi_encode.sol @@ -0,0 +1,20 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + function builtinMatchesSolidityImplementation() public pure returns (bool) { + return + erc7201(string(abi.encode("example.main"))) == + erc7201Mock(string(abi.encode("example.main"))); + } + function builtinOutput() public pure returns (uint) { + return erc7201(string(abi.encode("example.main"))); + } +} +// ---- +// builtinMatchesSolidityImplementation() -> true +// builtinOutput() -> -14651554186193368082021334953908208762193027200365752719897746810709432803072 diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_array_string_literal.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_array_string_literal.sol new file mode 100644 index 000000000..87f2477fd --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_array_string_literal.sol @@ -0,0 +1,7 @@ +contract C { + function test() public pure returns (bool) { + return erc7201(["x"][0]) == erc7201(["y", "x"][1]); + } +} +// ---- +// test() -> true diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_locations.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_locations.sol new file mode 100644 index 000000000..88f9f93c3 --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_locations.sol @@ -0,0 +1,37 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + string storageVarStr = "example.contract"; + string constant constStorageVarStr = "example.contract"; + function storageVar() public view returns (bool) { + return erc7201(storageVarStr) == erc7201Mock("example.contract"); + } + function constStorageVar() public pure returns (bool) { + return erc7201(constStorageVarStr) == erc7201Mock("example.contract"); + } + function memoryVar() public pure returns (bool) { + string memory memoryVarStr = "example.main"; + return erc7201(memoryVarStr) == erc7201Mock("example.main"); + } + function calldataParam(string calldata calldataVarStr) public pure returns (bool) { + return erc7201(calldataVarStr) == erc7201Mock("example.main"); + } + function calldataSlice(bytes calldata namespaceID) public pure returns (bool) { + return erc7201(string(namespaceID[2:5])) == erc7201Mock("amp"); + } + function literalParam() public pure returns (bool) { + return erc7201("example.main") == erc7201Mock("example.main"); + } +} +// ---- +// storageVar() -> true +// constStorageVar() -> true +// memoryVar() -> true +// calldataParam(string): 0x20, 12, "example.main" -> true +// calldataSlice(bytes): 0x20, 12, "example.main" -> true +// literalParam() -> true diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_pure_function.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_pure_function.sol new file mode 100644 index 000000000..31c4b871a --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_pure_function.sol @@ -0,0 +1,17 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + function f() public pure returns (string memory) { + return "example.main"; + } + function builtinMatchesSolidityImplementation() public pure returns (bool) { + return erc7201(f()) == erc7201Mock("example.main"); + } +} +// ---- +// builtinMatchesSolidityImplementation() -> true diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_string_concat.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_string_concat.sol new file mode 100644 index 000000000..c73746606 --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_string_concat.sol @@ -0,0 +1,15 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + function builtinMatchesSolidityImplementation() public view returns (bool) { + string memory first = "example."; + return erc7201(string.concat(first, "main")) == erc7201Mock("example.main"); + } +} +// ---- +// builtinMatchesSolidityImplementation() -> true diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_string_literal_with_escaped_chars.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_string_literal_with_escaped_chars.sol new file mode 100644 index 000000000..2ca4efd2c --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_string_literal_with_escaped_chars.sol @@ -0,0 +1,18 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + string constant CONST = "\n\"\'\\abc\ +def"; + function builtinMatchesSolidityImplementation() public pure returns (bool) { + return erc7201("\n\"\'\\abc\ +def") == erc7201Mock("\n\"\'\\abc\ +def"); + } +} +// ---- +// builtinMatchesSolidityImplementation() -> true diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_ternary_operator.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_ternary_operator.sol new file mode 100644 index 000000000..1c88c20ed --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_ternary_operator.sol @@ -0,0 +1,18 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + function simple() public pure returns (bool) { + return erc7201(true ? "x" : "y") == erc7201Mock("x"); + } + function compounded(bool c1, bool c2) public pure returns (bool) { + return erc7201(c1 ? "a" : (c2 ? "x" : "c")) == erc7201Mock("x"); + } +} +// ---- +// simple() -> true +// compounded(bool,bool): false, true -> true diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_unicode_string_literal.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_unicode_string_literal.sol new file mode 100644 index 000000000..2b4048e38 --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_unicode_string_literal.sol @@ -0,0 +1,14 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + function builtinMatchesSolidityImplementation() public pure returns (bool) { + return erc7201(unicode"Hello 😃") == erc7201Mock(unicode"Hello 😃"); + } +} +// ---- +// builtinMatchesSolidityImplementation() -> true diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_unicode_string_variable.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_unicode_string_variable.sol new file mode 100644 index 000000000..387623f9d --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_unicode_string_variable.sol @@ -0,0 +1,15 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + string unicodeStr = unicode"Hello 😃"; + function builtinMatchesSolidityImplementation() public view returns (bool) { + return erc7201(unicodeStr) == erc7201Mock(unicode"Hello 😃"); + } +} +// ---- +// builtinMatchesSolidityImplementation() -> true diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_with_zero_last_byte_of_inner_hash.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_with_zero_last_byte_of_inner_hash.sol new file mode 100644 index 000000000..8f27ae212 --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_with_zero_last_byte_of_inner_hash.sol @@ -0,0 +1,26 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + // The purpose of this test is to guarantee that the + // erc7201 implementation does not subtract 1 only from the + // last byte rather than the whole number during its intermediary operations. + function builtinMatchesSolidityImplementation() public pure returns (bool) { + string memory s = "85"; + bytes32 h = keccak256(bytes(s)); + + // "85" is intentionally chosen because it produces + // a keccak256 hash with the last byte zero + assert(uint8(h[31]) == 0); + + return + erc7201(s) == erc7201Mock(s) && + erc7201("85") == erc7201Mock("85"); + } +} +// ---- +// builtinMatchesSolidityImplementation() -> true diff --git a/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_with_zero_last_byte_of_inner_hash_comptime.sol b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_with_zero_last_byte_of_inner_hash_comptime.sol new file mode 100644 index 000000000..d44fc416d --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/erc7201_param_with_zero_last_byte_of_inner_hash_comptime.sol @@ -0,0 +1,24 @@ +function erc7201Mock(string memory id) pure returns (uint256) { + return uint256( + keccak256(bytes.concat(bytes32(uint256(keccak256(bytes(id))) - 1))) & + ~bytes32(uint256(0xff)) + ); +} + +contract C { + uint8[erc7201("85")] array; + // The purpose of this test is to guarantee that the + // erc7201 implementation does not subtract 1 only from the + // last byte rather than the whole number during its intermediary operations. + function builtinMatchesSolidityImplementation() public view returns (bool) { + bytes32 h = keccak256(bytes("85")); + + // "85" is intentionally chosen because it produces + // a keccak256 hash with the last byte zero + assert(uint8(h[31]) == 0); + + return array.length == erc7201Mock("85"); + } +} +// ---- +// builtinMatchesSolidityImplementation() -> true diff --git a/test/libsolidity/syntaxTests/array/length/builtin_erc7201_comptime.sol b/test/libsolidity/syntaxTests/array/length/builtin_erc7201_comptime.sol new file mode 100644 index 000000000..83fe820db --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/builtin_erc7201_comptime.sol @@ -0,0 +1,5 @@ +contract C { + uint[erc7201("length")] array; +} +// ---- +// Warning 7325: (17-40): Type uint256[91485909057496517105622548919236807895873764128784270125752891283919605191424] covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/array/length/string_as_array_length.sol b/test/libsolidity/syntaxTests/array/length/string_as_array_length.sol new file mode 100644 index 000000000..511b63ce4 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/string_as_array_length.sol @@ -0,0 +1,8 @@ +contract C { + string constant length = "length"; + uint["length"] literalString; + uint[length] variableString; +} +// ---- +// TypeError 5462: (61-69): Invalid array length, expected integer literal or constant expression. +// TypeError 5462: (95-101): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/constantEvaluator/erc7201_builtin.sol b/test/libsolidity/syntaxTests/constantEvaluator/erc7201_builtin.sol new file mode 100644 index 000000000..9878cb856 --- /dev/null +++ b/test/libsolidity/syntaxTests/constantEvaluator/erc7201_builtin.sol @@ -0,0 +1,6 @@ +contract C { + uint constant x = erc7201("A"); + uint[x] array; +} +// ---- +// Warning 7325: (53-60): Type uint256[36579005187129934694193755934841191771209741707776365283473783080460440925696] covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_abi_encode_comptime.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_abi_encode_comptime.sol new file mode 100644 index 000000000..728a794d5 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_abi_encode_comptime.sol @@ -0,0 +1,3 @@ +contract C layout at erc7201(string(abi.encodePacked(bytes32(uint256(2))))) {} +// ---- +// TypeError 1505: (21-75): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_function_pointer_assignment.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_function_pointer_assignment.sol new file mode 100644 index 000000000..6d100ebee --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_function_pointer_assignment.sol @@ -0,0 +1,8 @@ +contract C { + function (string memory) pure returns (uint256) functionPointer; + function f() public pure { + functionPointer = erc7201; + } +} +// ---- +// TypeError 7407: (139-146): Type function (string memory) pure returns (uint256) is not implicitly convertible to expected type function (string memory) pure returns (uint256). Special functions cannot be converted to function types. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_function_shadow_warning.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_function_shadow_warning.sol new file mode 100644 index 000000000..e66d69c15 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_function_shadow_warning.sol @@ -0,0 +1,5 @@ +function erc7201() pure returns (uint) { + return 42; +} +// ---- +// Warning 2319: (0-57): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_invalid_gas_function_option.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_invalid_gas_function_option.sol new file mode 100644 index 000000000..b31050f31 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_invalid_gas_function_option.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns (uint) { + return erc7201{gas: 10}("x"); + } +} +// ---- +// TypeError 2193: (74-90): Function call options can only be set on external function calls or contract creations. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_no_call.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_no_call.sol new file mode 100644 index 000000000..e761cc4b8 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_no_call.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + erc7201; + } +} +// ---- +// Warning 6133: (52-59): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_overflow_expression_comptime.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_overflow_expression_comptime.sol new file mode 100644 index 000000000..caf471a64 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_overflow_expression_comptime.sol @@ -0,0 +1,5 @@ +contract C { + uint[erc7201("main:example") + erc7201("main:example")] array; +} +// ---- +// TypeError 2643: (22-71): Arithmetic error when computing constant value. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_bytes_converted_to_string.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_bytes_converted_to_string.sol new file mode 100644 index 000000000..80dd2e57d --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_bytes_converted_to_string.sol @@ -0,0 +1,8 @@ +bytes constant bytesParam = "abcdef"; +contract C { + function f() public pure returns (uint256) { + uint256 x = erc7201(string(bytesParam)); + return x; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_constant_string_unitary_tuple.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_constant_string_unitary_tuple.sol new file mode 100644 index 000000000..273d0b45b --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_constant_string_unitary_tuple.sol @@ -0,0 +1,7 @@ +contract C { + string constant const = ("x"); + function constArg() public pure returns (uint) { + return erc7201(const); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_bytes.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_bytes.sol new file mode 100644 index 000000000..e38b7b9fa --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_bytes.sol @@ -0,0 +1,9 @@ +bytes constant bytesArg = "abcdef"; +contract C { + function f() public pure returns (uint256) { + return erc7201(bytesArg); + } +} +// ---- +// TypeError 6896: (121-129): The argument to erc7201 builtin must be a string. The supplied argument has type bytes. +// TypeError 9553: (121-129): Invalid type for argument in function call. Invalid implicit conversion from bytes memory to string memory requested. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_hex_literal.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_hex_literal.sol new file mode 100644 index 000000000..6613b20a0 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_hex_literal.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns (uint) { + return erc7201(hex"001122FF"); + } +} +// ---- +// TypeError 9553: (82-95): Invalid type for argument in function call. Invalid implicit conversion from literal_string hex"001122ff" to string memory requested. Contains invalid UTF-8 sequence at position 3. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_number_literal.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_number_literal.sol new file mode 100644 index 000000000..bc121fcbb --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_invalid_number_literal.sol @@ -0,0 +1,8 @@ +contract C { + function f() public pure returns (uint) { + return erc7201(123); + } +} +// ---- +// TypeError 6896: (82-85): The argument to erc7201 builtin must be a string. +// TypeError 9553: (82-85): Invalid type for argument in function call. Invalid implicit conversion from int_const 123 to string memory requested. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_named.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_named.sol new file mode 100644 index 000000000..87d608922 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_named.sol @@ -0,0 +1,5 @@ +contract C { + uint x = erc7201({namespaceID: "example.main"}); +} +// ---- +// TypeError 4974: (26-64): Named argument "namespaceID" does not match function declaration. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_unitary_tuple_comptime.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_unitary_tuple_comptime.sol new file mode 100644 index 000000000..c85cde093 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_unitary_tuple_comptime.sol @@ -0,0 +1,2 @@ +contract C layout at erc7201(("example.main")) {} +// ---- diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_var_with_escaped_chars_comptime.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_var_with_escaped_chars_comptime.sol new file mode 100644 index 000000000..65f6fd18e --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_var_with_escaped_chars_comptime.sol @@ -0,0 +1,3 @@ +contract C layout at erc7201("\n\"\'\\abc\ +def") {} +// ---- diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_variable.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_variable.sol new file mode 100644 index 000000000..4c39650d4 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_variable.sol @@ -0,0 +1,21 @@ +string constant fileLevelStr = "test.file"; +contract C { + string constant stateVarStr = "example.contract"; + function fileLevel() public pure returns (uint) { + return erc7201(fileLevelStr); + } + function stateVar() public pure returns (uint) { + return erc7201(stateVarStr); + } + function localVar() public pure returns (uint) { + string memory localVarStr = "example.main"; + return erc7201(localVarStr); + } + function funcMemParam(string memory paramStr) public pure returns (uint) { + return erc7201(paramStr); + } + function funcCallDataParam(string calldata paramStr) public pure returns (uint) { + return erc7201(paramStr); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_variable_comptime.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_variable_comptime.sol new file mode 100644 index 000000000..7d826ea7b --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_variable_comptime.sol @@ -0,0 +1,6 @@ +string constant CONST = "test.file"; +contract C { + uint8[erc7201(CONST)] array; +} +// ---- +// Warning 7325: (54-75): Type uint8[5237610212305498718603509572682216073844539971870822423088087032295879652864] covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_with_whitespaces_comptime.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_with_whitespaces_comptime.sol new file mode 100644 index 000000000..0382a95cd --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_string_with_whitespaces_comptime.sol @@ -0,0 +1,6 @@ +contract C { + function f() public pure returns (uint) { + return erc7201("\tstring with spaces\n\r"); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_unicode_literal.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_unicode_literal.sol new file mode 100644 index 000000000..5f22ae902 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_unicode_literal.sol @@ -0,0 +1,6 @@ +contract C { + function f() public pure returns (uint) { + return erc7201(unicode"Hello 😃"); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_wrong_count.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_wrong_count.sol new file mode 100644 index 000000000..1f62ae5ef --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_param_wrong_count.sol @@ -0,0 +1,9 @@ +contract C { + uint x = erc7201(); + uint y = erc7201("12", "34"); + uint z = erc7201("A", "BC", "D"); +} +// ---- +// TypeError 6160: (26-35): Wrong argument count for function call: 0 arguments given but expected 1. +// TypeError 6160: (50-69): Wrong argument count for function call: 2 arguments given but expected 1. +// TypeError 6160: (84-107): Wrong argument count for function call: 3 arguments given but expected 1. diff --git a/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_variable_name_shadow_warning.sol b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_variable_name_shadow_warning.sol new file mode 100644 index 000000000..59e62528b --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/erc7201_builtin_variable_name_shadow_warning.sol @@ -0,0 +1,5 @@ +contract C { + uint erc7201; +} +// ---- +// Warning 2319: (17-29): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_const_var_assignment.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_const_var_assignment.sol new file mode 100644 index 000000000..ec3357e10 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_const_var_assignment.sol @@ -0,0 +1,7 @@ +contract C { + uint constant x = erc7201("abc"); + function f() public pure returns(uint) { + return mulmod(x, 10, 37); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_invalid_member_gas.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_invalid_member_gas.sol new file mode 100644 index 000000000..d3eabc04f --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_invalid_member_gas.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + erc7201.gas(); + } +} +// ---- +// TypeError 9582: (47-58): Member "gas" not found or not visible after argument-dependent lookup in function (string memory) pure returns (uint256). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_invalid_member_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_invalid_member_value.sol new file mode 100644 index 000000000..a197e8151 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/erc7201_builtin_invalid_member_value.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + erc7201.value(); + } +} +// ---- +// TypeError 8820: (47-60): Member "value" is only available for payable functions. diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_constant_variable_comptime.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_constant_variable_comptime.sol new file mode 100644 index 000000000..3b32caae6 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_constant_variable_comptime.sol @@ -0,0 +1,3 @@ +string constant storageBase = "myStorageBase"; +contract C layout at erc7201(storageBase) { } +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_imported_constant_variable_comptime.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_imported_constant_variable_comptime.sol new file mode 100644 index 000000000..6f68f8c74 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_imported_constant_variable_comptime.sol @@ -0,0 +1,6 @@ +==== Source: A ==== +string constant storageBase = "myStorageBase"; +==== Source: B ==== +import "A"; +contract C layout at erc7201(storageBase) {} +// ---- diff --git a/test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_string_literal_comptime.sol b/test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_string_literal_comptime.sol new file mode 100644 index 000000000..e8175eae0 --- /dev/null +++ b/test/libsolidity/syntaxTests/storageLayoutSpecifier/erc7201_builtin_param_string_literal_comptime.sol @@ -0,0 +1,2 @@ +contract C layout at erc7201("storageBase") { } +// ---- diff --git a/test/libsolidity/syntaxTests/using/erc7201_builtin_as_custom_operator.sol b/test/libsolidity/syntaxTests/using/erc7201_builtin_as_custom_operator.sol new file mode 100644 index 000000000..282353ac5 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/erc7201_builtin_as_custom_operator.sol @@ -0,0 +1,3 @@ +using {erc7201 as -} for uint; +// ---- +// TypeError 8187: (7-14): Expected function name. diff --git a/test/libsolidity/syntaxTests/using/erc7201_builtin_using_for.sol b/test/libsolidity/syntaxTests/using/erc7201_builtin_using_for.sol new file mode 100644 index 000000000..5e1cf4fd9 --- /dev/null +++ b/test/libsolidity/syntaxTests/using/erc7201_builtin_using_for.sol @@ -0,0 +1,3 @@ +using {erc7201} for string; +// ---- +// TypeError 8187: (7-14): Expected function name. From 64893d8b9cfb126a6689176128a8d67b970049f1 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 18 Mar 2025 00:34:53 -0300 Subject: [PATCH 1167/1340] Introduce new builtin function erc7201 --- Changelog.md | 1 + libsolidity/analysis/ConstantEvaluator.cpp | 133 +++++++++++++----- libsolidity/analysis/ConstantEvaluator.h | 16 ++- .../analysis/DeclarationTypeChecker.cpp | 6 +- libsolidity/analysis/GlobalContext.cpp | 4 +- .../analysis/PostTypeContractLevelChecker.cpp | 9 +- libsolidity/analysis/StaticAnalyzer.cpp | 36 +++-- libsolidity/analysis/TypeChecker.cpp | 32 +++++ libsolidity/analysis/TypeChecker.h | 2 + libsolidity/ast/ASTUtils.cpp | 19 +++ libsolidity/ast/ASTUtils.h | 7 +- libsolidity/ast/Types.cpp | 4 +- libsolidity/ast/Types.h | 1 + libsolidity/codegen/ExpressionCompiler.cpp | 45 ++++++ libsolidity/codegen/YulUtilFunctions.cpp | 17 +++ libsolidity/codegen/YulUtilFunctions.h | 8 ++ .../codegen/ir/IRGeneratorForStatements.cpp | 31 ++++ libsolidity/formal/SMTEncoder.cpp | 7 +- 18 files changed, 310 insertions(+), 68 deletions(-) diff --git a/Changelog.md b/Changelog.md index aa3e2951f..d9f94b349 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.8.35 (unreleased) Language Features: +* General: Add a builtin that computes the base slot of a storage namespace using the `erc7201` formula from ERC-7201. Compiler Features: * Commandline Interface: Introduce `--experimental` flag required for enabling the experimental mode. diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 691d273d5..f094988d9 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -26,14 +26,18 @@ #include #include #include +#include +#include +#include #include using namespace solidity; using namespace solidity::frontend; using namespace solidity::langutil; +using namespace solidity::util; -using TypedRational = ConstantEvaluator::TypedRational; +using TypedValue = ConstantEvaluator::TypedValue; namespace { @@ -231,37 +235,59 @@ std::optional ConstantEvaluator::evaluateUnaryOperator(Token _operator namespace { -std::optional convertType(rational const& _value, Type const& _type) +TypedValue convertType(rational const& _value, Type const& _type) { if (_type.category() == Type::Category::RationalNumber) - return TypedRational{TypeProvider::rationalNumber(_value), _value}; + return TypedValue{TypeProvider::rationalNumber(_value), _value}; else if (auto const* integerType = dynamic_cast(&_type)) { if (_value > integerType->maxValue() || _value < integerType->minValue()) - return std::nullopt; + return TypedValue{}; else - return TypedRational{&_type, _value.numerator() / _value.denominator()}; + return TypedValue{&_type, _value.numerator() / _value.denominator()}; } else - return std::nullopt; + return TypedValue{}; +} + +TypedValue convertType(std::string const& _value, Type const& _type) +{ + if ( + _type.category() != Type::Category::StringLiteral && + _type.category() != Type::Category::Array + ) + return TypedValue{}; + return TypedValue{&_type, _value}; } -std::optional convertType(std::optional const& _value, Type const& _type) +TypedValue convertType(TypedValue const& _value, Type const& _type) { - return _value ? convertType(_value->value, _type) : std::nullopt; + return std::visit(util::GenericVisitor{ + [&](std::string const& value) { + return convertType(value, _type); + }, + [&](rational const& value) { + return convertType(value, _type); + }, + [&](std::monostate const&) { + return TypedValue{}; + } + }, _value.value); } -std::optional constantToTypedValue(Type const& _type) +TypedValue constantToTypedValue(Type const& _type) { if (_type.category() == Type::Category::RationalNumber) - return TypedRational{&_type, dynamic_cast(_type).value()}; - else - return std::nullopt; + return TypedValue{&_type, dynamic_cast(_type).value()}; + else if (_type.category() == Type::Category::StringLiteral) + return TypedValue{&_type, dynamic_cast(_type).value()}; + + return TypedValue{}; } } -std::optional ConstantEvaluator::evaluate( +TypedValue ConstantEvaluator::evaluate( langutil::ErrorReporter& _errorReporter, Expression const& _expr ) @@ -269,7 +295,7 @@ std::optional ConstantEvaluator::evaluate( return ConstantEvaluator{_errorReporter}.evaluate(_expr); } -std::optional ConstantEvaluator::tryEvaluate(Expression const& _expr) +TypedValue ConstantEvaluator::tryEvaluate(Expression const& _expr) { ErrorList errorList; ErrorReporter errorReporter(errorList); @@ -279,12 +305,12 @@ std::optional ConstantEvaluator::tryEvaluate(Expression const& _e } catch (FatalError const&) { - return std::nullopt; + return TypedValue{}; } } -std::optional ConstantEvaluator::evaluate(ASTNode const& _node) +TypedValue ConstantEvaluator::evaluate(ASTNode const& _node) { if (!m_values.count(&_node)) { @@ -293,7 +319,7 @@ std::optional ConstantEvaluator::evaluate(ASTNode const& _node) solAssert(varDecl->isConstant(), ""); // In some circumstances, we do not yet have a type for the variable. if (!varDecl->value() || !varDecl->type()) - m_values[&_node] = std::nullopt; + m_values[&_node] = TypedValue{}; else { m_depth++; @@ -311,7 +337,7 @@ std::optional ConstantEvaluator::evaluate(ASTNode const& _node) { expression->accept(*this); if (!m_values.count(&_node)) - m_values[&_node] = std::nullopt; + m_values[&_node] = TypedValue{}; } } return m_values.at(&_node); @@ -319,21 +345,21 @@ std::optional ConstantEvaluator::evaluate(ASTNode const& _node) void ConstantEvaluator::endVisit(UnaryOperation const& _operation) { - std::optional value = evaluate(_operation.subExpression()); - if (!value) + TypedValue value = evaluate(_operation.subExpression()); + if (!value.type) return; - Type const* resultType = value->type->unaryOperatorResult(_operation.getOperator()); + Type const* resultType = value.type->unaryOperatorResult(_operation.getOperator()); if (!resultType) return; value = convertType(value, *resultType); - if (!value) + if (!std::holds_alternative(value.value)) return; - if (std::optional result = evaluateUnaryOperator(_operation.getOperator(), value->value)) + if (std::optional result = evaluateUnaryOperator(_operation.getOperator(), std::get(value.value))) { - std::optional convertedValue = convertType(*result, *resultType); - if (!convertedValue) + TypedValue convertedValue = convertType(*result, *resultType); + if (!convertedValue.type) m_errorReporter.fatalTypeError( 3667_error, _operation.location(), @@ -345,9 +371,9 @@ void ConstantEvaluator::endVisit(UnaryOperation const& _operation) void ConstantEvaluator::endVisit(BinaryOperation const& _operation) { - std::optional left = evaluate(_operation.leftExpression()); - std::optional right = evaluate(_operation.rightExpression()); - if (!left || !right) + TypedValue left = evaluate(_operation.leftExpression()); + TypedValue right = evaluate(_operation.rightExpression()); + if (!left.type || !right.type) return; // If this is implemented in the future: Comparison operators have a "binaryOperatorResult" @@ -355,7 +381,7 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation) if (TokenTraits::isCompareOp(_operation.getOperator())) return; - Type const* resultType = left->type->binaryOperatorResult(_operation.getOperator(), right->type); + Type const* resultType = left.type->binaryOperatorResult(_operation.getOperator(), right.type); if (!resultType) { m_errorReporter.fatalTypeError( @@ -364,22 +390,29 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation) "Operator " + std::string(TokenTraits::toString(_operation.getOperator())) + " not compatible with types " + - left->type->toString() + + left.type->toString() + " and " + - right->type->toString() + right.type->toString() ); return; } left = convertType(left, *resultType); right = convertType(right, *resultType); - if (!left || !right) + if ( + !std::holds_alternative(left.value) || + !std::holds_alternative(right.value) + ) return; - if (std::optional value = evaluateBinaryOperator(_operation.getOperator(), left->value, right->value)) + if (std::optional value = evaluateBinaryOperator( + _operation.getOperator(), + std::get(left.value), + std::get(right.value) + )) { - std::optional convertedValue = convertType(*value, *resultType); - if (!convertedValue) + TypedValue convertedValue = convertType(*value, *resultType); + if (!convertedValue.type) m_errorReporter.fatalTypeError( 2643_error, _operation.location(), @@ -407,3 +440,33 @@ void ConstantEvaluator::endVisit(TupleExpression const& _tuple) if (!_tuple.isInlineArray() && _tuple.components().size() == 1) m_values[&_tuple] = evaluate(*_tuple.components().front()); } + +void ConstantEvaluator::endVisit(FunctionCall const& _functionCall) +{ + auto const* builtinFunction = dynamic_cast(ASTNode::referencedDeclaration(_functionCall.expression())); + if (!builtinFunction) + return; + + auto const* functionType = builtinFunction->functionType(true); + solAssert(functionType); + switch (functionType->kind()) + { + case FunctionType::Kind::ERC7201: + { + solAssert(_functionCall.arguments().size() == 1); + auto stringArg = evaluate(*(_functionCall.arguments()[0].get())); + if (!std::holds_alternative(stringArg.value)) + return; + + h256 innerKeccak = keccak256(std::get(stringArg.value)); + h256 outerKeccak = keccak256(h256(u256(innerKeccak) - 1)); + outerKeccak.data()[31] = 0; + u256 slot = outerKeccak; + solAssert(functionType->returnParameterTypes().size() == 1); + m_values[&_functionCall] = TypedValue{functionType->returnParameterTypes()[0], rational{slot}}; + break; + } + default: + break; + } +} diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index 297d5f6e8..67adc0be1 100644 --- a/libsolidity/analysis/ConstantEvaluator.h +++ b/libsolidity/analysis/ConstantEvaluator.h @@ -46,20 +46,21 @@ class TypeChecker; class ConstantEvaluator: private ASTConstVisitor { public: - struct TypedRational + struct TypedValue { + // Type may be RationalType or IntegerType for value rational Type const* type; - rational value; + std::variant value; }; - static std::optional evaluate( + static TypedValue evaluate( langutil::ErrorReporter& _errorReporter, Expression const& _expr ); /// Works the same as `evaluate` but swallows any errors that might occur in the evaluation and simply returns - /// `std::nullopt` instead. - static std::optional tryEvaluate(Expression const& _expr); + /// `TypedValue` containing `std::monostate` instead. + static TypedValue tryEvaluate(Expression const& _expr); /// Performs arbitrary-precision evaluation of a binary operator. Returns nullopt on cases like /// division by zero or e.g. bit operators applied to fractional values. @@ -72,19 +73,20 @@ class ConstantEvaluator: private ASTConstVisitor private: explicit ConstantEvaluator(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} - std::optional evaluate(ASTNode const& _node); + TypedValue evaluate(ASTNode const& _node); void endVisit(BinaryOperation const& _operation) override; void endVisit(UnaryOperation const& _operation) override; void endVisit(Literal const& _literal) override; void endVisit(Identifier const& _identifier) override; void endVisit(TupleExpression const& _tuple) override; + void endVisit(FunctionCall const& _functionCall) override; langutil::ErrorReporter& m_errorReporter; /// Current recursion depth. size_t m_depth = 0; /// Values of sub-expressions and variable declarations. - std::map> m_values; + std::map m_values; }; } diff --git a/libsolidity/analysis/DeclarationTypeChecker.cpp b/libsolidity/analysis/DeclarationTypeChecker.cpp index e5549f035..e2f0cf6e8 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.cpp +++ b/libsolidity/analysis/DeclarationTypeChecker.cpp @@ -338,8 +338,10 @@ void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName) std::optional lengthValue; if (length->annotation().type && length->annotation().type->category() == Type::Category::RationalNumber) lengthValue = dynamic_cast(*length->annotation().type).value(); - else if (std::optional value = ConstantEvaluator::evaluate(m_errorReporter, *length)) - lengthValue = value->value; + else if (ConstantEvaluator::TypedValue value = ConstantEvaluator::evaluate(m_errorReporter, *length); + std::holds_alternative(value.value) + ) + lengthValue = std::get(value.value); if (!lengthValue) m_errorReporter.typeError( diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index 0c265d245..58b8dac34 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -62,7 +62,8 @@ int magicVariableToID(std::string const& _name) {"tx", -26}, {"type", -27}, {"this", -28}, - {"blobhash", -29} + {"blobhash", -29}, + {"erc7201", -30} }; if (auto id = magicVariables.find(_name); id != magicVariables.end()) @@ -83,6 +84,7 @@ inline std::vector> constructMag magicVarDecl("block", TypeProvider::magic(MagicType::Kind::Block)), magicVarDecl("blockhash", TypeProvider::function(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, StateMutability::View)), magicVarDecl("ecrecover", TypeProvider::function(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, StateMutability::Pure)), + magicVarDecl("erc7201", TypeProvider::function(strings{"string memory"}, strings{"uint256"}, FunctionType::Kind::ERC7201, StateMutability::Pure)), magicVarDecl("gasleft", TypeProvider::function(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, StateMutability::View)), magicVarDecl("keccak256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, StateMutability::Pure)), magicVarDecl("msg", TypeProvider::magic(MagicType::Kind::Message)), diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.cpp b/libsolidity/analysis/PostTypeContractLevelChecker.cpp index f8f4b6ef6..be5d008a6 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.cpp +++ b/libsolidity/analysis/PostTypeContractLevelChecker.cpp @@ -92,7 +92,6 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinitio if (!*baseSlotExpression.annotation().isPure) { - // TODO: introduce and handle erc7201 as a builtin function m_errorReporter.typeError( 1139_error, baseSlotExpression.location(), @@ -137,8 +136,9 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinitio rational baseSlotRationalValue; if (integerType) { - std::optional typedRational = ConstantEvaluator::evaluate(m_errorReporter, baseSlotExpression); - if (!typedRational) + ConstantEvaluator::TypedValue typedRational = ConstantEvaluator::evaluate(m_errorReporter, baseSlotExpression); + solAssert(!typedRational.type || dynamic_cast(typedRational.type)); + if (!typedRational.type) { m_errorReporter.typeError( 1505_error, @@ -148,7 +148,8 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinitio ); return; } - baseSlotRationalValue = typedRational->value; + solAssert(std::holds_alternative(typedRational.value)); + baseSlotRationalValue = std::get(typedRational.value); } else { diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp index dfd262c8d..1ad3e7744 100644 --- a/libsolidity/analysis/StaticAnalyzer.cpp +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -314,15 +314,18 @@ bool StaticAnalyzer::visit(BinaryOperation const& _operation) if ( *_operation.rightExpression().annotation().isPure && (_operation.getOperator() == Token::Div || _operation.getOperator() == Token::Mod) && - ConstantEvaluator::evaluate(m_errorReporter, _operation.leftExpression()) + ConstantEvaluator::evaluate(m_errorReporter, _operation.leftExpression()).type ) - if (auto rhs = ConstantEvaluator::evaluate(m_errorReporter, _operation.rightExpression())) - if (rhs->value == 0) - m_errorReporter.typeError( - 1211_error, - _operation.location(), - (_operation.getOperator() == Token::Div) ? "Division by zero." : "Modulo zero." - ); + if ( + auto rhs = ConstantEvaluator::evaluate(m_errorReporter, _operation.rightExpression()); + std::holds_alternative(rhs.value) && + std::get(rhs.value) == 0 + ) + m_errorReporter.typeError( + 1211_error, + _operation.location(), + (_operation.getOperator() == Token::Div) ? "Division by zero." : "Modulo zero." + ); return true; } @@ -337,13 +340,16 @@ bool StaticAnalyzer::visit(FunctionCall const& _functionCall) { solAssert(_functionCall.arguments().size() == 3, ""); if (*_functionCall.arguments()[2]->annotation().isPure) - if (auto lastArg = ConstantEvaluator::evaluate(m_errorReporter, *(_functionCall.arguments())[2])) - if (lastArg->value == 0) - m_errorReporter.typeError( - 4195_error, - _functionCall.location(), - "Arithmetic modulo zero." - ); + if ( + auto lastArg = ConstantEvaluator::evaluate(m_errorReporter, *(_functionCall.arguments())[2]); + std::holds_alternative(lastArg.value) && + std::get(lastArg.value) == 0 + ) + m_errorReporter.typeError( + 4195_error, + _functionCall.location(), + "Arithmetic modulo zero." + ); } if ( m_currentContract && diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index b54e591d2..c613dd796 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2398,6 +2398,34 @@ void TypeChecker::typeCheckBytesConcatFunction( } } +void TypeChecker::typeCheckERC7201Builtin(FunctionCall const& _functionCall, FunctionType const* _functionType) +{ + // erc7201 builtin accepts only 1 argument. Invalid cases with different number + // of arguments are treated after by function `typeCheckFunctionGeneralChecks` + if (_functionCall.arguments().size() > 0) + { + Type const* argumentType = _functionCall.arguments()[0].get()->annotation().type; + solAssert(argumentType); + auto const* arrayType = dynamic_cast(argumentType); + + if ( + !dynamic_cast(argumentType) && + (!arrayType || !arrayType->isString()) + ) + { + std::string errorMsg = "The argument to erc7201 builtin must be a string."; + if (arrayType && arrayType->isByteArray()) + errorMsg += " The supplied argument has type bytes."; + m_errorReporter.typeError( + 6896_error, + _functionCall.arguments()[0]->location(), + errorMsg + ); + } + } + typeCheckFunctionGeneralChecks(_functionCall, _functionType); +} + void TypeChecker::typeCheckFunctionGeneralChecks( FunctionCall const& _functionCall, FunctionTypePointer _functionType @@ -2825,6 +2853,10 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) returnTypes = functionType->returnParameterTypes(); break; } + case FunctionType::Kind::ERC7201: + typeCheckERC7201Builtin(_functionCall, functionType); + returnTypes = functionType->returnParameterTypes(); + break; default: { typeCheckFunctionCall(_functionCall, functionType); diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index e4bc12705..de446b7d1 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -117,6 +117,8 @@ class TypeChecker: private ASTConstVisitor FunctionType const* _functionType ); + void typeCheckERC7201Builtin(FunctionCall const& _functionCall, FunctionType const* _functionType); + bool visit(ImportDirective const&) override; void endVisit(InheritanceSpecifier const& _inheritance) override; diff --git a/libsolidity/ast/ASTUtils.cpp b/libsolidity/ast/ASTUtils.cpp index 5ae336619..532b0bc7a 100644 --- a/libsolidity/ast/ASTUtils.cpp +++ b/libsolidity/ast/ASTUtils.cpp @@ -16,6 +16,7 @@ */ // SPDX-License-Identifier: GPL-3.0 +#include #include #include #include @@ -137,4 +138,22 @@ u256 layoutBaseForInheritanceHierarchy(ContractDefinition const& _topLevelContra return 0; } +std::optional erc7201CompileTimeValue(FunctionCall const& _erc7201Call) +{ + auto const* erc7201Function = dynamic_cast(ASTNode::referencedDeclaration(_erc7201Call.expression())); + solAssert(erc7201Function); + solAssert(erc7201Function->functionType(true /* internal */)->kind() == FunctionType::Kind::ERC7201); + + auto evaluatedResult = ConstantEvaluator::tryEvaluate(_erc7201Call); + + if (std::holds_alternative(evaluatedResult.value)) + return std::nullopt; + + solAssert(std::holds_alternative(evaluatedResult.value)); + auto rationalValue = std::get(evaluatedResult.value); + solAssert(rationalValue.denominator() == 1); + bigint baseSlot = rationalValue.numerator(); + solAssert(baseSlot <= std::numeric_limits::max()); + return u256(baseSlot); +} } diff --git a/libsolidity/ast/ASTUtils.h b/libsolidity/ast/ASTUtils.h index d29bda35f..cb54f5868 100644 --- a/libsolidity/ast/ASTUtils.h +++ b/libsolidity/ast/ASTUtils.h @@ -24,11 +24,12 @@ namespace solidity::frontend { class ASTNode; +class ContractDefinition; class Declaration; class Expression; +class FunctionCall; class SourceUnit; class VariableDeclaration; -class ContractDefinition; /// Find the topmost referenced constant variable declaration when the given variable /// declaration value is an identifier. Works only for constant variable declarations. @@ -61,4 +62,8 @@ bigint contractStorageSizeUpperBound(ContractDefinition const& _contract, Variab /// Assumes analysis was successful. u256 layoutBaseForInheritanceHierarchy(ContractDefinition const& _topLevelContract, DataLocation _location); +/// @returns The storage namespace base address using the ERC-7201 formula, if it can be calculated at compile time. +/// Assumes FunctionCall refers to erc7201 builtin. +std::optional erc7201CompileTimeValue(FunctionCall const& _erc7201Call); + } diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 8454fd130..601788eaf 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3125,6 +3125,7 @@ std::string FunctionType::richIdentifier() const case Kind::ABIDecode: id += "abidecode"; break; case Kind::BlobHash: id += "blobhash"; break; case Kind::MetaType: id += "metatype"; break; + case Kind::ERC7201: id += "erc7201"; break; } id += "_" + stateMutabilityToString(m_stateMutability); id += identifierList(m_parameterTypes) + "returns" + identifierList(m_returnParameterTypes); @@ -3715,7 +3716,8 @@ bool FunctionType::isPure() const m_kind == Kind::Wrap || m_kind == Kind::Unwrap || m_kind == Kind::BytesConcat || - m_kind == Kind::StringConcat; + m_kind == Kind::StringConcat || + m_kind == Kind::ERC7201; } TypePointers FunctionType::parseElementaryTypeVector(strings const& _types) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 8d2453d8d..cddedc0f8 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1267,6 +1267,7 @@ class FunctionType: public Type Send, ///< CALL, but without data and gas Transfer, ///< CALL, but without data and throws on error KECCAK256, ///< KECCAK256 + ERC7201, ///< erc7201(...) Selfdestruct, ///< SELFDESTRUCT Revert, ///< REVERT ECRecover, ///< CALL to special contract for ecrecover diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 49313c892..e7f8df859 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -32,6 +32,8 @@ #include #include +#include + #include #include #include @@ -926,6 +928,49 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) } break; } + case FunctionType::Kind::ERC7201: + { + solAssert(arguments.size() == 1); + Type const* argType = arguments.front()->annotation().type; + solAssert(argType); + arguments.front()->accept(*this); + if (dynamic_cast(argType)) + { + std::optional slot = erc7201CompileTimeValue(_functionCall); + solAssert(slot.has_value()); + m_context << *slot; + } + // `bytes memory` does not conform to ERC7201 spec, so analysis rejects it. + // Internally string and bytes have the same representation though, so generating code for it is still possible. + else if (*argType == *TypeProvider::stringMemory() || *argType == *TypeProvider::bytesMemory()) + { + // stack layout: string_mem + ArrayUtils(m_context).retrieveLength(*TypeProvider::bytesMemory()); + // stack layout: string_mem length + m_context << Instruction::SWAP1; + // stack layout: length string_mem + // adjust to start of string data, first slot is size + m_context << u256(32) << Instruction::ADD; + // stack layout: length string_data_ptr + m_context.callYulFunction(m_context.utilFunctions().erc7201(), 2, 1); + } + else + { + solAssert(!argType->dataStoredIn(DataLocation::Memory)); + solAssert(argType->isImplicitlyConvertibleTo(*TypeProvider::stringMemory())); + + // stack layout: string_ref + utils().fetchFreeMemoryPointer(); + // stack layout: string_ref mem_start_ptr + utils().packedEncode({argType}, TypePointers()); + // stack layout: mem_end_ptr + utils().toSizeAfterFreeMemoryPointer(); + // stack layout: length mem_ptr_start + + m_context.callYulFunction(m_context.utilFunctions().erc7201(), 2, 1); + } + break; + } case FunctionType::Kind::Event: { _functionCall.expression().accept(*this); diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index bb18217f2..f01420795 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -1297,6 +1297,23 @@ std::string YulUtilFunctions::wrappingIntExpFunction( }); } +std::string YulUtilFunctions::erc7201() +{ + std::string functionName = "erc7201"; + return m_functionCollector.createFunction(functionName, [&]() { + Whiskers templ(R"( + function erc7201(namespaceIDDataPtr, namespaceIDLength) -> slot { + let innerKeccak := keccak256(namespaceIDDataPtr, namespaceIDLength) + mstore(0, sub(innerKeccak, 1)) + // slot = keccak256(keccak256(id) - 1) & ~0xff + slot := and(keccak256(0, 32), not(0xff)) + } + )"); + + return templ.render(); + }); +} + std::string YulUtilFunctions::arrayLengthFunction(ArrayType const& _type) { std::string functionName = "array_length_" + _type.identifier(); diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index f4172017b..a5e547935 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -566,6 +566,14 @@ class YulUtilFunctions /// @return the name of a function that checks if two external functions pointers are equal or not std::string externalFunctionPointersEqualFunction(); + /// Generates a function that calculates storage namespace base address using the ERC-7201 formula. + /// The function expects an address pointing to the data of a byte array stored in memory + /// and the size of the data as its arguments. + /// The function uses scratch space. + /// @return The name of the function. + /// Signature: (namespaceIDDataPtr, namespaceIDLength) -> slot + std::string erc7201(); + private: /// @returns the name of a function that copies a struct from calldata or memory to storage /// signature: (slot, value) -> diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 66736da5f..d5cb27b6e 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -1424,6 +1425,36 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) } break; } + case FunctionType::Kind::ERC7201: + { + solAssert(arguments.size() == 1); + Type const* argType = arguments.front()->annotation().type; + solAssert(argType); + if (dynamic_cast(argType)) + { + std::optional slot = erc7201CompileTimeValue(_functionCall); + solAssert(slot.has_value()); + define(_functionCall) << formatNumber(*slot) << "\n"; + } + else + { + Whiskers templ(R"( + ((), ()) + )"); + + IRVariable stringArg = convert(*arguments[0], *TypeProvider::stringMemory()); + solAssert(stringArg.stackSlots().size() == 1); + std::string namespaceID = stringArg.stackSlots().front(); + + templ("arrayDataArea", m_utils.arrayDataAreaFunction(*TypeProvider::stringMemory())); + templ("arrayLength", m_utils.arrayLengthFunction(*TypeProvider::stringMemory())); + templ("namespaceID", namespaceID); + templ("erc7201Builtin", m_utils.erc7201()); + + define(_functionCall) << templ.render(); + } + break; + } case FunctionType::Kind::ArrayPop: { solAssert(functionType->hasBoundFirstArgument()); diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 6cf6cea93..df902fd86 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -3122,8 +3122,11 @@ RationalNumberType const* SMTEncoder::isConstant(Expression const& _expr) if (auto type = dynamic_cast(_expr.annotation().type)) return type; - if (auto typedRational = ConstantEvaluator::tryEvaluate(_expr)) - return TypeProvider::rationalNumber(typedRational->value); + if ( + auto typedValue = ConstantEvaluator::tryEvaluate(_expr); + std::holds_alternative(typedValue.value) + ) + return TypeProvider::rationalNumber(std::get(typedValue.value)); return nullptr; } From fcd94ee1d78a62c83f456e9335d79c7cc442d25e Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 2 Mar 2026 23:21:11 -0300 Subject: [PATCH 1168/1340] Update docs --- docs/cheatsheet.rst | 4 +++- docs/contracts/custom-storage-layout.rst | 3 ++- docs/units-and-global-variables.rst | 8 +++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index 1a3085f12..3a064fdf3 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -97,7 +97,7 @@ Validations and Assertions - ``revert()``: abort execution and revert state changes - ``revert(string memory message)``: abort execution and revert state changes providing an explanatory string -.. index:: cryptography, keccak256, sha256, ripemd160, ecrecover, addmod, mulmod +.. index:: cryptography, keccak256, sha256, ripemd160, ecrecover, addmod, mulmod, erc7201 Mathematical and Cryptographic Functions ======================================== @@ -111,6 +111,8 @@ Mathematical and Cryptographic Functions arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. - ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. +- ``erc7201(string memory id) returns (uint)``: compute the base slot of an ``erc7201`` storage namespace. + Can be used in compile time context. .. index:: this, super, selfdestruct diff --git a/docs/contracts/custom-storage-layout.rst b/docs/contracts/custom-storage-layout.rst index 72f281d7f..def06f3d5 100644 --- a/docs/contracts/custom-storage-layout.rst +++ b/docs/contracts/custom-storage-layout.rst @@ -25,7 +25,8 @@ and is located in the header of a contract definition. The layout specifier can be placed either before or after the inheritance specifier, and can appear at most once. The ``base-slot-expression`` must be an :ref:`integer literal` expression that can be evaluated at compilation time and yields a value in the range of ``uint256``. -The use of constants initialized using such expressions is also allowed. +The use of constants initialized using such expressions and +the :ref:`built-in function erc7201` is also allowed. A custom layout cannot make contract's storage "wrap around". If the selected base slot would push the static variables past the end of storage, diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 4d8fed283..d46bdaddf 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -193,7 +193,7 @@ more details on error handling and when to use which function. ``revert(string memory reason)`` abort execution and revert state changes, providing an explanatory string -.. index:: keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, +.. index:: keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, erc7201, .. _mathematical-and-cryptographic-functions: @@ -246,6 +246,12 @@ Mathematical and Cryptographic Functions When running ``sha256``, ``ripemd160`` or ``ecrecover`` on a *private blockchain*, you might encounter Out-of-Gas. This is because these functions are implemented as "precompiled contracts" and only really exist after they receive the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution might run into an Out-of-Gas error. A workaround for this problem is to first send Wei (1 for example) to each of the contracts before you use them in your actual contracts. This is not an issue on the main or test net. +``erc7201(string memory id) returns (uint)`` + compute the base slot of a storage namespace of a given ``id`` according to the ``erc7201`` formula defined by `ERC-7201`. + The formula is equivalent to ``keccak256(keccak256(id) - 1) & ~0xff``. + The builtin accepts arbitrary strings, including ones containing whitespace. + The function can be used in compile-time context. + .. index:: balance, codehash, send, transfer, call, callcode, delegatecall, staticcall .. _address_related: From 8c180694d1927e69cf069904c9124b4be8efe911 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 5 Mar 2026 22:47:00 +0100 Subject: [PATCH 1169/1340] Add experimental --via-ssa-cfg to CLI --- Changelog.md | 1 + docs/using-the-compiler.rst | 2 + solc/CommandLineInterface.cpp | 3 +- solc/CommandLineParser.cpp | 24 +++++++++++- solc/CommandLineParser.h | 1 + test/cmdlineTests/via_ssa_cfg_ethdebug/args | 1 + test/cmdlineTests/via_ssa_cfg_ethdebug/err | 1 + test/cmdlineTests/via_ssa_cfg_ethdebug/exit | 1 + .../via_ssa_cfg_ethdebug/input.sol | 4 ++ .../via_ssa_cfg_without_experimental/args | 1 + .../via_ssa_cfg_without_experimental/err | 1 + .../via_ssa_cfg_without_experimental/exit | 1 + .../input.sol | 6 +++ test/solc/CommandLineParser.cpp | 38 +++++++++++++++++-- 14 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 test/cmdlineTests/via_ssa_cfg_ethdebug/args create mode 100644 test/cmdlineTests/via_ssa_cfg_ethdebug/err create mode 100644 test/cmdlineTests/via_ssa_cfg_ethdebug/exit create mode 100644 test/cmdlineTests/via_ssa_cfg_ethdebug/input.sol create mode 100644 test/cmdlineTests/via_ssa_cfg_without_experimental/args create mode 100644 test/cmdlineTests/via_ssa_cfg_without_experimental/err create mode 100644 test/cmdlineTests/via_ssa_cfg_without_experimental/exit create mode 100644 test/cmdlineTests/via_ssa_cfg_without_experimental/input.sol diff --git a/Changelog.md b/Changelog.md index aa3e2951f..bac62ba18 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: * Commandline Interface: Introduce `--experimental` flag required for enabling the experimental mode. +* General: Introduce the SSA CFG codegen (experimental). * General: Restrict the existing experimental features (`generic-solidity`, `lsp`, `ethdebug`, `eof`, `evm`, `ast-import`, `evmasm-import`, `ir-ast`, `ssa-cfg`) to experimental mode. * Metadata: Store the state of the experimental mode in JSON and CBOR metadata. In CBOR this broadens the meaning of the existing `experimental` field, which used to indicate only the presence of certain experimental pragmas in the source. * Standard JSON Interface: Introduce `settings.experimental` setting required for enabling the experimental mode. diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index ce82aa077..485b70548 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -768,3 +768,5 @@ The table below details all currently available experimental features. +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ | Yul SSA CFG exporter | ``ssa-cfg`` | no | ``--yul-cfg-json`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ +| SSA CFG codegen | ``ssa-cfg-codegen`` | yes | ``--via-ssa-cfg``, ``settings.viaSSACFG`` | ++-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 90c67868d..a40853e49 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -937,6 +937,7 @@ void CommandLineInterface::compile() m_compiler->setRemappings(m_options.input.remappings); m_compiler->setLibraries(m_options.linker.libraries); m_compiler->setViaIR(m_options.output.viaIR); + m_compiler->setViaSSACFG(m_options.output.viaSSACFG); m_compiler->setEVMVersion(m_options.output.evmVersion); m_compiler->setEOFVersion(m_options.output.eofVersion); m_compiler->setRevertStringBehaviour(m_options.output.revertStrings); @@ -1322,7 +1323,7 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y stack.optimize(); - yul::MachineAssemblyObject object = stack.assemble(_targetMachine); + yul::MachineAssemblyObject object = stack.assemble(_targetMachine, m_options.output.viaSSACFG); if (object.bytecode) object.bytecode->link(m_options.linker.libraries); objects.insert({sourceUnitName, std::move(object)}); diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 7f143695d..2d4cc28df 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -49,6 +49,7 @@ static std::string const g_strEVM = "evm"; static std::string const g_strEVMVersion = "evm-version"; static std::string const g_strEOFVersion = "experimental-eof-version"; static std::string const g_strViaIR = "via-ir"; +static std::string const g_strViaSSACFG = "via-ssa-cfg"; static std::string const g_strExperimentalViaIR = "experimental-via-ir"; static std::string const g_strExperimental = "experimental"; static std::string const g_strGas = "gas"; @@ -625,6 +626,10 @@ General Information)").c_str(), g_strViaIR.c_str(), "Turn on compilation mode via the IR." ) + ( + g_strViaSSACFG.c_str(), + "(experimental) Turn on SSA CFG-based code generation. Implies compilation via IR." + ) ( g_strRevertStrings.c_str(), po::value()->value_name(util::joinHumanReadable(g_revertStringsArgs, ",")), @@ -999,6 +1004,7 @@ void CommandLineParser::processArgs() "ethdebug", "ethdebug-runtime", g_strEOFVersion, + g_strViaSSACFG, }); if (m_args.count(g_strHelp) > 0) @@ -1063,7 +1069,8 @@ void CommandLineParser::processArgs() {g_strModelCheckerTimeout, {InputMode::Compiler, InputMode::CompilerWithASTImport}}, {g_strModelCheckerBMCLoopIterations, {InputMode::Compiler, InputMode::CompilerWithASTImport}}, {g_strModelCheckerContracts, {InputMode::Compiler, InputMode::CompilerWithASTImport}}, - {g_strModelCheckerTargets, {InputMode::Compiler, InputMode::CompilerWithASTImport}} + {g_strModelCheckerTargets, {InputMode::Compiler, InputMode::CompilerWithASTImport}}, + {g_strViaSSACFG, {InputMode::Compiler, InputMode::CompilerWithASTImport, InputMode::Assembler}} }; std::vector invalidOptionsForCurrentInputMode; for (auto const& [optionName, inputModes]: validOptionInputModeCombinations) @@ -1372,8 +1379,17 @@ void CommandLineParser::processArgs() "Optimizer can only be used for strict assembly. Use --" + g_strStrictAssembly + "." ); + m_options.output.viaSSACFG = m_args.contains(g_strViaSSACFG); + if (m_options.output.viaSSACFG) + if (m_options.assembly.inputLanguage != Input::StrictAssembly) + solThrow( + CommandLineValidationError, + "--" + g_strViaSSACFG + " can only be used with strict assembly. Use --" + g_strStrictAssembly + "." + ); if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) { + if (m_options.output.viaSSACFG) + solUnimplemented("ethdebug is not yet supported with --" + g_strViaSSACFG + "."); if (m_options.optimiserSettings().runYulOptimiser) solUnimplemented( "Optimization (using --" + g_strOptimize + ") is not yet supported with ethdebug." @@ -1514,6 +1530,9 @@ void CommandLineParser::processArgs() m_args.count(g_strModelCheckerTargets) || m_args.count(g_strModelCheckerTimeout); m_options.output.viaIR = (m_args.count(g_strExperimentalViaIR) > 0 || m_args.count(g_strViaIR) > 0); + m_options.output.viaSSACFG = m_args.contains(g_strViaSSACFG); + if (m_options.output.viaSSACFG) + m_options.output.viaIR = true; solAssert( m_options.input.mode == InputMode::Compiler || @@ -1540,6 +1559,9 @@ void CommandLineParser::processArgs() enableEthdebugMessage + " output can only be selected, if --via-ir was specified." ); + if (m_options.output.viaSSACFG) + solUnimplemented("ethdebug is not yet supported with --" + g_strViaSSACFG + "."); + if (incompatibleEthdebugOutputs) solThrow( CommandLineValidationError, diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 9d9dc28b6..5f5527c61 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -200,6 +200,7 @@ struct CommandLineOptions bool overwriteFiles = false; langutil::EVMVersion evmVersion; bool viaIR = false; + bool viaSSACFG = false; RevertStrings revertStrings = RevertStrings::Default; std::optional debugInfoSelection; CompilerStack::State stopAfter = CompilerStack::State::CompilationSuccessful; diff --git a/test/cmdlineTests/via_ssa_cfg_ethdebug/args b/test/cmdlineTests/via_ssa_cfg_ethdebug/args new file mode 100644 index 000000000..fa8be093c --- /dev/null +++ b/test/cmdlineTests/via_ssa_cfg_ethdebug/args @@ -0,0 +1 @@ +--experimental --via-ssa-cfg --ethdebug diff --git a/test/cmdlineTests/via_ssa_cfg_ethdebug/err b/test/cmdlineTests/via_ssa_cfg_ethdebug/err new file mode 100644 index 000000000..170609e36 --- /dev/null +++ b/test/cmdlineTests/via_ssa_cfg_ethdebug/err @@ -0,0 +1 @@ +Error: ethdebug is not yet supported with --via-ssa-cfg. diff --git a/test/cmdlineTests/via_ssa_cfg_ethdebug/exit b/test/cmdlineTests/via_ssa_cfg_ethdebug/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/via_ssa_cfg_ethdebug/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/via_ssa_cfg_ethdebug/input.sol b/test/cmdlineTests/via_ssa_cfg_ethdebug/input.sol new file mode 100644 index 000000000..f123f6c8b --- /dev/null +++ b/test/cmdlineTests/via_ssa_cfg_ethdebug/input.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C {} diff --git a/test/cmdlineTests/via_ssa_cfg_without_experimental/args b/test/cmdlineTests/via_ssa_cfg_without_experimental/args new file mode 100644 index 000000000..fe15a47cb --- /dev/null +++ b/test/cmdlineTests/via_ssa_cfg_without_experimental/args @@ -0,0 +1 @@ +--via-ssa-cfg diff --git a/test/cmdlineTests/via_ssa_cfg_without_experimental/err b/test/cmdlineTests/via_ssa_cfg_without_experimental/err new file mode 100644 index 000000000..0d92cf265 --- /dev/null +++ b/test/cmdlineTests/via_ssa_cfg_without_experimental/err @@ -0,0 +1 @@ +Error: The following options are only available in experimental mode: --via-ssa-cfg. To enable experimental mode, use the --experimental flag. diff --git a/test/cmdlineTests/via_ssa_cfg_without_experimental/exit b/test/cmdlineTests/via_ssa_cfg_without_experimental/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/via_ssa_cfg_without_experimental/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/via_ssa_cfg_without_experimental/input.sol b/test/cmdlineTests/via_ssa_cfg_without_experimental/input.sol new file mode 100644 index 000000000..136e28fdf --- /dev/null +++ b/test/cmdlineTests/via_ssa_cfg_without_experimental/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 6d9153381..1e5896604 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -155,7 +155,8 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) "--model-checker-show-unsupported", "--model-checker-solvers=z3,smtlib2", "--model-checker-targets=underflow,divByZero", - "--model-checker-timeout=5" + "--model-checker-timeout=5", + "--via-ssa-cfg" }; if (inputMode == InputMode::CompilerWithASTImport) @@ -183,6 +184,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) expectedOptions.output.overwriteFiles = true; expectedOptions.output.evmVersion = EVMVersion::spuriousDragon(); expectedOptions.output.viaIR = true; + expectedOptions.output.viaSSACFG = true; expectedOptions.output.revertStrings = RevertStrings::Strip; expectedOptions.output.debugInfoSelection = DebugInfoSelection::fromString("location"); expectedOptions.formatting.json = JsonFormat{JsonFormat::Pretty, 7}; @@ -318,9 +320,11 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) commandLine += assemblyOptions; if (expectedLanguage == YulStack::Language::StrictAssembly) commandLine += std::vector{ + "--experimental", "--optimize", "--optimize-runs=1000", "--yul-optimizations=agf", + "--via-ssa-cfg", }; CommandLineOptions expectedOptions; @@ -357,10 +361,12 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) expectedOptions.compiler.outputs.astCompactJson = true; if (expectedLanguage == YulStack::Language::StrictAssembly) { + expectedOptions.experimental = true; expectedOptions.optimizer.optimizeEvmasm = true; expectedOptions.optimizer.optimizeYul = true; expectedOptions.optimizer.yulSteps = "agf"; expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000; + expectedOptions.output.viaSSACFG = true; } CommandLineOptions parsedOptions = parseCommandLine(commandLine); @@ -436,7 +442,8 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations) {"--model-checker-solvers=z3,smtlib2", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, {"--model-checker-timeout=5", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, {"--model-checker-contracts=contract1.yul:A,contract2.yul:B", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-targets=underflow,divByZero", {"--assemble", "--strict-assembly", "--standard-json", "--link"}} + {"--model-checker-targets=underflow,divByZero", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--via-ssa-cfg", {"--standard-json", "--link", "--import-asm-json"}} }; for (auto const& [optionName, inputModes]: invalidOptionInputModeCombinations) @@ -448,9 +455,24 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations) soltestAssert(!optionNameWithoutValue.empty()); std::vector commandLine = {"solc", optionName, "file", inputMode}; + bool experimentalMode = false; + if (optionNameWithoutValue == "--via-ssa-cfg") + { + commandLine.push_back("--experimental"); + experimentalMode = true; + } std::string expectedMessage = "The following options are not supported in the current input mode: " + optionNameWithoutValue; - auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedMessage; }; + // When --experimental is combined with --standard-json, a different error fires first + // (standard JSON mode is incompatible with --experimental flag). Accept that too. + auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) + { + std::string const what = _exception.what(); + return what == expectedMessage || ( + experimentalMode && + what.starts_with("Standard JSON input mode is incompatible with the --experimental flag.") + ); + }; BOOST_CHECK_EXCEPTION(parseCommandLine(commandLine), CommandLineValidationError, hasCorrectMessage); } @@ -679,7 +701,8 @@ BOOST_AUTO_TEST_CASE(experimental_features_without_experimental_flag) "--ir-optimized-ast-json", "--yul-cfg-json", "--ethdebug", - "--ethdebug-runtime" + "--ethdebug-runtime", + "--via-ssa-cfg" }; std::string expectedErrorMessage; @@ -703,6 +726,13 @@ BOOST_AUTO_TEST_CASE(experimental_features_without_experimental_flag) BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage); } +BOOST_AUTO_TEST_CASE(via_ssa_cfg_smoke) +{ + auto const commandLineOptions = parseCommandLine({"solc", "--experimental", "--via-ssa-cfg", "contract.sol"}); + BOOST_CHECK_EQUAL(commandLineOptions.output.viaSSACFG, true); + BOOST_CHECK_EQUAL(commandLineOptions.output.viaIR, true); +} + BOOST_AUTO_TEST_CASE(debug_info_ethdebug_without_experimental_flag) { std::string const expectedErrorMessage = From 5d9ba67b2cf87db1b40737b5cfdece0014c97fc8 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 5 Mar 2026 22:47:21 +0100 Subject: [PATCH 1170/1340] Add experimental settings.viaSSACFG to Standard JSON Interface --- docs/using-the-compiler.rst | 9 ++++-- libsolidity/interface/StandardCompiler.cpp | 28 +++++++++++++++++-- libsolidity/interface/StandardCompiler.h | 1 + .../standard_via_ssa_cfg_ethdebug/input.json | 15 ++++++++++ .../standard_via_ssa_cfg_ethdebug/output.json | 11 ++++++++ .../input.json | 11 ++++++++ .../output.json | 11 ++++++++ .../input.json | 13 +++++++++ .../output.json | 11 ++++++++ test/libsolidity/StandardCompiler.cpp | 26 +++++++++++++++++ 10 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 test/cmdlineTests/standard_via_ssa_cfg_ethdebug/input.json create mode 100644 test/cmdlineTests/standard_via_ssa_cfg_ethdebug/output.json create mode 100644 test/cmdlineTests/standard_via_ssa_cfg_no_experimental/input.json create mode 100644 test/cmdlineTests/standard_via_ssa_cfg_no_experimental/output.json create mode 100644 test/cmdlineTests/standard_via_ssa_cfg_via_ir_false/input.json create mode 100644 test/cmdlineTests/standard_via_ssa_cfg_via_ir_false/output.json diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 485b70548..604f8b05a 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -369,6 +369,9 @@ Input Description // Optional: Change compilation pipeline to go through the Yul intermediate representation. // This is false by default. "viaIR": true, + // Optional: Turn on SSA CFG-based code generation via the IR (experimental). + // Implies viaIR: true. This is false by default. + "viaSSACFG": false, // Optional: Debugging settings "debug": { // How to treat revert (and require) reason strings. Settings are @@ -766,7 +769,7 @@ The table below details all currently available experimental features. +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ | Ethdebug | ``ethdebug`` | no | ``--ethdebug``, ``--ethdebug-runtime``, ``--debug-info ethdebug`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| Yul SSA CFG exporter | ``ssa-cfg`` | no | ``--yul-cfg-json`` | -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| SSA CFG codegen | ``ssa-cfg-codegen`` | yes | ``--via-ssa-cfg``, ``settings.viaSSACFG`` | +| | | no | ``--yul-cfg-json`` | +| SSA CFG + ``ssa-cfg`` +------------------+-------------------------------------------------------------------+ +| | | yes | ``--via-ssa-cfg`` | +-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 74307bbc0..a556c74db 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -450,7 +450,7 @@ std::optional checkAuxiliaryInputKeys(Json const& _input) std::optional checkSettingsKeys(Json const& _input) { - static std::set keys{"debug", "evmVersion", "experimental", "eofVersion", "libraries", "metadata", "modelChecker", "optimizer", "outputSelection", "remappings", "stopAfter", "viaIR"}; + static std::set keys{"debug", "evmVersion", "experimental", "eofVersion", "libraries", "metadata", "modelChecker", "optimizer", "outputSelection", "remappings", "stopAfter", "viaIR", "viaSSACFG"}; return checkKeys(_input, keys, "settings"); } @@ -848,6 +848,22 @@ std::variant StandardCompiler::parseI ret.viaIR = settings["viaIR"].get(); } + if (settings.contains("viaSSACFG")) + { + if (!settings["viaSSACFG"].is_boolean()) + return formatFatalError(Error::Type::JSONError, "\"settings.viaSSACFG\" must be a Boolean."); + ret.viaSSACFG = settings["viaSSACFG"].get(); + if (ret.viaSSACFG) + { + if (settings.contains("viaIR") && !ret.viaIR) + return formatFatalError( + Error::Type::JSONError, + "\"settings.viaSSACFG\" requires compilation via IR." + ); + ret.viaIR = true; + } + } + if (settings.contains("evmVersion")) { if (!settings["evmVersion"].is_string()) @@ -1239,8 +1255,12 @@ std::variant StandardCompiler::parseI } if (isEthdebugRequested(ret.outputSelection)) + { if (ret.optimiserSettings.runYulOptimiser) solUnimplemented("Optimization is not yet supported with ethdebug."); + if (ret.viaSSACFG) + solUnimplemented("SSA CFG codegen does not yet support ethdebug."); + } if (!ret.experimental) { @@ -1256,6 +1276,9 @@ std::variant StandardCompiler::parseI if (ret.eofVersion.has_value()) return formatFatalError(Error::Type::FatalError, "'eofVersion' setting is experimental and can only be used with the 'settings.experimental' option enabled."); + + if (ret.viaSSACFG) + return formatFatalError(Error::Type::FatalError, "'viaSSACFG' setting is experimental and can only be used with the 'settings.experimental' option enabled."); } return {std::move(ret)}; @@ -1406,6 +1429,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu for (auto const& smtLib2Response: _inputsAndSettings.smtLib2Responses) compilerStack.addSMTLib2Response(smtLib2Response.first, smtLib2Response.second); compilerStack.setViaIR(_inputsAndSettings.viaIR); + compilerStack.setViaSSACFG(_inputsAndSettings.viaSSACFG); compilerStack.setEVMVersion(_inputsAndSettings.evmVersion); compilerStack.setEOFVersion(_inputsAndSettings.eofVersion); compilerStack.setRemappings(std::move(_inputsAndSettings.remappings)); @@ -1763,7 +1787,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) output["sources"][sourceName] = sourceResult; } stack.optimize(); - std::tie(object, deployedObject) = stack.assembleWithDeployed(); + std::tie(object, deployedObject) = stack.assembleWithDeployed({}, _inputsAndSettings.viaSSACFG); if (object.bytecode) object.bytecode->link(_inputsAndSettings.libraries); if (deployedObject.bytecode) diff --git a/libsolidity/interface/StandardCompiler.h b/libsolidity/interface/StandardCompiler.h index 493e637cd..0d184e139 100644 --- a/libsolidity/interface/StandardCompiler.h +++ b/libsolidity/interface/StandardCompiler.h @@ -89,6 +89,7 @@ class StandardCompiler Json outputSelection; ModelCheckerSettings modelCheckerSettings = ModelCheckerSettings{}; bool viaIR = false; + bool viaSSACFG = false; bool experimental = false; }; diff --git a/test/cmdlineTests/standard_via_ssa_cfg_ethdebug/input.json b/test/cmdlineTests/standard_via_ssa_cfg_ethdebug/input.json new file mode 100644 index 000000000..d5ad9153e --- /dev/null +++ b/test/cmdlineTests/standard_via_ssa_cfg_ethdebug/input.json @@ -0,0 +1,15 @@ +{ + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A {}" + } + }, + "settings": { + "experimental": true, + "viaSSACFG": true, + "outputSelection": { + "*": {"*": ["evm.bytecode.ethdebug"]} + } + } +} diff --git a/test/cmdlineTests/standard_via_ssa_cfg_ethdebug/output.json b/test/cmdlineTests/standard_via_ssa_cfg_ethdebug/output.json new file mode 100644 index 000000000..7e4cdbc8d --- /dev/null +++ b/test/cmdlineTests/standard_via_ssa_cfg_ethdebug/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "SSA CFG codegen does not yet support ethdebug.", + "message": "SSA CFG codegen does not yet support ethdebug.", + "severity": "error", + "type": "UnimplementedFeatureError" + } + ] +} diff --git a/test/cmdlineTests/standard_via_ssa_cfg_no_experimental/input.json b/test/cmdlineTests/standard_via_ssa_cfg_no_experimental/input.json new file mode 100644 index 000000000..4515a2489 --- /dev/null +++ b/test/cmdlineTests/standard_via_ssa_cfg_no_experimental/input.json @@ -0,0 +1,11 @@ +{ + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A { constructor() { uint x = 2; { uint y = 3; } } }" + } + }, + "settings": { + "viaSSACFG": true + } +} diff --git a/test/cmdlineTests/standard_via_ssa_cfg_no_experimental/output.json b/test/cmdlineTests/standard_via_ssa_cfg_no_experimental/output.json new file mode 100644 index 000000000..16de05ce3 --- /dev/null +++ b/test/cmdlineTests/standard_via_ssa_cfg_no_experimental/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "'viaSSACFG' setting is experimental and can only be used with the 'settings.experimental' option enabled.", + "message": "'viaSSACFG' setting is experimental and can only be used with the 'settings.experimental' option enabled.", + "severity": "error", + "type": "FatalError" + } + ] +} diff --git a/test/cmdlineTests/standard_via_ssa_cfg_via_ir_false/input.json b/test/cmdlineTests/standard_via_ssa_cfg_via_ir_false/input.json new file mode 100644 index 000000000..242883416 --- /dev/null +++ b/test/cmdlineTests/standard_via_ssa_cfg_via_ir_false/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "A.sol": { + "content": "contract A {}" + } + }, + "settings": { + "experimental": true, + "viaIR": false, + "viaSSACFG": true + } +} diff --git a/test/cmdlineTests/standard_via_ssa_cfg_via_ir_false/output.json b/test/cmdlineTests/standard_via_ssa_cfg_via_ir_false/output.json new file mode 100644 index 000000000..938367890 --- /dev/null +++ b/test/cmdlineTests/standard_via_ssa_cfg_via_ir_false/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "\"settings.viaSSACFG\" requires compilation via IR.", + "message": "\"settings.viaSSACFG\" requires compilation via IR.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 43b68223b..18c366e3e 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -2347,6 +2347,32 @@ BOOST_AUTO_TEST_CASE(experimental_non_boolean) BOOST_CHECK(containsError(result, "JSONError", "'settings.experimental' must be a Boolean.")); } +BOOST_AUTO_TEST_CASE(via_ssa_cfg_with_experimental) +{ + frontend::StandardCompiler compiler; + static auto constexpr input = R"( + { + "language": "Solidity", + "sources": { + "A.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\ncontract A { function f() public pure returns (uint) { return 1; } }" + } + }, + "settings": { + "experimental": true, + "viaSSACFG": true, + "outputSelection": {"*": {"*": ["evm.bytecode"]}} + } + } + )"; + + Json parsedInput; + BOOST_REQUIRE(util::jsonParseStrict(input, parsedInput)); + Json result = compiler.compile(parsedInput); + // Should compile without fatal errors (warnings are acceptable) + BOOST_CHECK(!containsError(result, "FatalError", "")); +} + BOOST_AUTO_TEST_SUITE_END() } // end namespaces From 92673f638630ca8071bdae970489c34c120397df Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 9 Mar 2026 09:29:59 +0100 Subject: [PATCH 1171/1340] Add viaSSACFG to compilation metadata --- libsolidity/interface/CompilerStack.cpp | 2 + test/cmdlineTests/metadata_via_ssa_cfg/args | 1 + .../metadata_via_ssa_cfg/input.sol | 4 ++ test/cmdlineTests/metadata_via_ssa_cfg/output | 4 ++ test/libsolidity/Metadata.cpp | 45 +++++++++++++++++++ 5 files changed, 56 insertions(+) create mode 100644 test/cmdlineTests/metadata_via_ssa_cfg/args create mode 100644 test/cmdlineTests/metadata_via_ssa_cfg/input.sol create mode 100644 test/cmdlineTests/metadata_via_ssa_cfg/output diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 96c0d3f6c..152a0059a 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1842,6 +1842,8 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR meta["settings"]["experimental"] = m_experimental; if (m_eofVersion.has_value()) meta["settings"]["eofVersion"] = *m_eofVersion; + if (m_viaSSACFG) + meta["settings"]["viaSSACFG"] = m_viaSSACFG; meta["settings"]["compilationTarget"][_contract.contract->sourceUnitName()] = *_contract.contract->annotation().canonicalName; diff --git a/test/cmdlineTests/metadata_via_ssa_cfg/args b/test/cmdlineTests/metadata_via_ssa_cfg/args new file mode 100644 index 000000000..565e51922 --- /dev/null +++ b/test/cmdlineTests/metadata_via_ssa_cfg/args @@ -0,0 +1 @@ +--metadata --experimental --via-ssa-cfg diff --git a/test/cmdlineTests/metadata_via_ssa_cfg/input.sol b/test/cmdlineTests/metadata_via_ssa_cfg/input.sol new file mode 100644 index 000000000..a3a86cc8d --- /dev/null +++ b/test/cmdlineTests/metadata_via_ssa_cfg/input.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; + +contract C {} diff --git a/test/cmdlineTests/metadata_via_ssa_cfg/output b/test/cmdlineTests/metadata_via_ssa_cfg/output new file mode 100644 index 000000000..575223726 --- /dev/null +++ b/test/cmdlineTests/metadata_via_ssa_cfg/output @@ -0,0 +1,4 @@ + +======= input.sol:C ======= +Metadata: +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"input.sol":"C"},"evmVersion":"osaka","experimental":true,"libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[],"viaIR":true,"viaSSACFG":true},"sources":{"input.sol":{"keccak256":"0x5cf617b1707a484e3c4bd59643013dec76ab7d75900b46855214729ae3e0ceb0","license":"GPL-3.0","urls":["bzz-raw://ac418a02dfadf87234150d3568f33269e3f49460345cb39300e017a6d755eff2","dweb:/ipfs/QmQq3owBu25x2WV46HB1WyKzJpxiAPecU7eMKqtXCF7eeS"]}},"version":1} diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index 683522693..476fcd3a0 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -423,6 +423,51 @@ BOOST_AUTO_TEST_CASE(metadata_viair) check(sourceCode, false); } +BOOST_AUTO_TEST_CASE(metadata_viassacfg) +{ + static auto constexpr sourceCode = R"( + pragma solidity >=0.0; + contract test { + } + )"; + + auto check = [](char const* _src, bool _viaSSACFG) + { + CompilerStack compilerStack; + compilerStack.setSources({{"", _src}}); + compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); + compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize); + compilerStack.setViaIR(true); + compilerStack.setExperimental(true); + compilerStack.setViaSSACFG(_viaSSACFG); + BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed"); + + Json metadata; + BOOST_REQUIRE(util::jsonParseStrict(compilerStack.metadata("test"), metadata)); + BOOST_CHECK(solidity::test::isValidMetadata(metadata)); + BOOST_CHECK(metadata.contains("settings")); + BOOST_CHECK(metadata["settings"].contains("viaIR")); + BOOST_CHECK(metadata["settings"]["viaIR"].get()); + if (_viaSSACFG) + { + BOOST_CHECK(metadata["settings"].contains("viaSSACFG")); + BOOST_CHECK(metadata["settings"]["viaSSACFG"].get()); + } + else + BOOST_CHECK(!metadata["settings"].contains("viaSSACFG")); + + std::map const parsedCBORMetadata = requireParsedCBORMetadata( + compilerStack.runtimeObject("test").bytecode, + CompilerStack::MetadataFormat::WithReleaseVersionTag + ); + + BOOST_CHECK(parsedCBORMetadata.contains("experimental")); + }; + + check(sourceCode, true); + check(sourceCode, false); +} + BOOST_AUTO_TEST_CASE(metadata_revert_strings) { CompilerStack compilerStack; From 11beecc016ca5a22a0200f2cd6d8f723f441221b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 10 Mar 2026 13:24:15 +0100 Subject: [PATCH 1172/1340] Update wording of --via-ir help message. --- solc/CommandLineParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 2d4cc28df..c40840a07 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -624,7 +624,7 @@ General Information)").c_str(), ) ( g_strViaIR.c_str(), - "Turn on compilation mode via the IR." + "Turn on compilation via IR." ) ( g_strViaSSACFG.c_str(), From 781aeb19d5855e728988c1c1c03514428eb69771 Mon Sep 17 00:00:00 2001 From: blishko Date: Wed, 11 Mar 2026 14:12:45 +0100 Subject: [PATCH 1173/1340] SSA: Tighten condition in shuffler The condition did not match the comment above it. This is the part of the algorithm that attempts to fix a slot in the arguments section of the target stack. But if the current stack size matches exactly the target tail size, we don't have any slot in the arguments section at that moment. I believe the comment is correct and we should enter this code only if there is a slot in args section. The condition has been tightened accordingly. --- libyul/backends/evm/ssa/StackShuffler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 5dddf5e5a..59b2bec6b 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -394,7 +394,7 @@ class StackShuffler return false; // if we have at least one slot in the args section, try to fix something there - if (!_stack.empty() && _stack.size() >= _state.target().tailSize) + if (_stack.size() > _state.target().tailSize) { StackOffset const stackTop{_stack.size() - 1}; // if the stack top isn't where it likes to be right now, try to put it somewhere more sensible From c18c5a4c839d53283fcf5fd8ee75f996a949fee7 Mon Sep 17 00:00:00 2001 From: Haowei Hsu Date: Thu, 12 Mar 2026 23:51:10 +0800 Subject: [PATCH 1174/1340] docs: move nav links to Jinja template for i18n (#16471) Move navigation link strings from constants.js to Jinja template using the `_()` function. This change enables the strings to be extracted by Sphinx's "Internationalization for Gettext" feature. --- docs/_static/js/constants.js | 12 ++++++------ docs/_templates/layout.html | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/docs/_static/js/constants.js b/docs/_static/js/constants.js index 67fa16cdb..c88d259b0 100644 --- a/docs/_static/js/constants.js +++ b/docs/_static/js/constants.js @@ -26,12 +26,12 @@ const CONTRIBUTE_PATH = `/en/latest/contributing.html`; const ABOUT_PATH = `${SOLIDITY_HOME_URL}/about`; const FORUM_URL = "https://forum.soliditylang.org/"; const NAV_LINKS = [ - { name: "Blog", href: BLOG_URL }, - { name: "Documentation", href: DOCS_URL }, - { name: "Use cases", href: USE_CASES_PATH }, - { name: "Contribute", href: CONTRIBUTE_PATH }, - { name: "About", href: ABOUT_PATH }, - { name: "Forum", href: FORUM_URL }, + { name: window.NAV_LINKS.blog, href: BLOG_URL }, + { name: window.NAV_LINKS.documentation, href: DOCS_URL }, + { name: window.NAV_LINKS.use_cases, href: USE_CASES_PATH }, + { name: window.NAV_LINKS.contribute, href: CONTRIBUTE_PATH }, + { name: window.NAV_LINKS.about, href: ABOUT_PATH }, + { name: window.NAV_LINKS.forum, href: FORUM_URL }, ]; const MOBILE_MENU_TOGGLE_CLASS = "shift"; diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html index 498c0e6e9..e4795757f 100644 --- a/docs/_templates/layout.html +++ b/docs/_templates/layout.html @@ -1,5 +1,19 @@ {% extends "!layout.html" %} +{% block scripts %} + + {{ super() }} +{% endblock %} + {% block menu %} {{ super() }}
    From f72c159914ec3963773e59c5f88911793fd5b65d Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 13 Mar 2026 13:28:17 +0100 Subject: [PATCH 1175/1340] Pin @uniswap/v3-sdk Fix euler --- test/externalTests/euler.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/test/externalTests/euler.sh b/test/externalTests/euler.sh index 9ccfcd781..eb547b41a 100755 --- a/test/externalTests/euler.sh +++ b/test/externalTests/euler.sh @@ -71,6 +71,7 @@ function euler_test force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" force_hardhat_unlimited_contract_size "$config_file" + npm install @uniswap/v3-sdk@3.29.1 # TODO: Remove after https://github.com/Uniswap/sdks/issues/557 is resolved npm install replace_version_pragmas neutralize_packaged_contracts From fa16df60225d8cd749e0740129260e7ee240d6c8 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 13 Mar 2026 14:19:01 +0100 Subject: [PATCH 1176/1340] Fix yield-liquidator --- test/externalTests/yield-liquidator.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/externalTests/yield-liquidator.sh b/test/externalTests/yield-liquidator.sh index 16a6287e5..df0c193b9 100755 --- a/test/externalTests/yield-liquidator.sh +++ b/test/externalTests/yield-liquidator.sh @@ -63,6 +63,23 @@ function yield_liquidator_test force_hardhat_compiler_binary "$config_file" "$BINARY_TYPE" "$BINARY_PATH" force_hardhat_compiler_settings "$config_file" "$(first_word "$SELECTED_PRESETS")" "$config_var" force_hardhat_unlimited_contract_size "$config_file" "$config_var" + # TODO: Remove after https://github.com/Uniswap/sdks/issues/557 is resolved + # Pin broken @uniswap/* packages via overrides. The following versions were published with + # 'workspace:*' deps that npm cannot resolve (EUNSUPPORTEDPROTOCOL), causing a silent exit-1: + # @uniswap/v3-sdk@3.29.2 (via smart-order-router -> ^3.7.0) + # @uniswap/v4-sdk@1.29.2 (via smart-order-router -> router-sdk -> ^1.20.0) + # @uniswap/v2-sdk@4.19.2 (via smart-order-router -> router-sdk -> ^4.14.0) + # Cannot just run npm install with unbroken version because these are indirect dependencies. + node -e " + const fs = require('fs'); + const p = JSON.parse(fs.readFileSync('package.json')); + p.overrides = Object.assign(p.overrides || {}, { + '@uniswap/v3-sdk': '3.29.1', + '@uniswap/v4-sdk': '1.29.1', + '@uniswap/v2-sdk': '4.19.1', + }); + fs.writeFileSync('package.json', JSON.stringify(p, null, 2)); + " npm install # The contract below is not used in any test and it depends on ISwapRouter which does not exists From d50fcadce40de8a18b0e242c6f08146771635dfc Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 12 Mar 2026 14:30:36 +0100 Subject: [PATCH 1177/1340] Test invalid import asm json input mode combinations with other cli options --- test/solc/CommandLineParser.cpp | 46 ++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 1e5896604..2233d0df3 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -31,6 +31,8 @@ #include #include +#include + #include #include #include @@ -429,20 +431,20 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations) { std::map> invalidOptionInputModeCombinations = { // TODO: This should eventually contain all options. - {"--experimental-via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--metadata-literal", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--metadata-hash=swarm", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-show-proved-safe", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-show-unproved", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-show-unsupported", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-div-mod-no-slacks", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-engine=bmc", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-invariants=contract,reentrancy", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-solvers=z3,smtlib2", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-timeout=5", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-contracts=contract1.yul:A,contract2.yul:B", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-targets=underflow,divByZero", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--experimental-via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--metadata-literal", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--metadata-hash=swarm", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-show-proved-safe", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-show-unproved", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-show-unsupported", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-div-mod-no-slacks", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-engine=bmc", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-invariants=contract,reentrancy", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-solvers=z3,smtlib2", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-timeout=5", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-contracts=contract1.yul:A,contract2.yul:B", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-targets=underflow,divByZero", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, {"--via-ssa-cfg", {"--standard-json", "--link", "--import-asm-json"}} }; @@ -455,12 +457,14 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations) soltestAssert(!optionNameWithoutValue.empty()); std::vector commandLine = {"solc", optionName, "file", inputMode}; - bool experimentalMode = false; - if (optionNameWithoutValue == "--via-ssa-cfg") - { - commandLine.push_back("--experimental"); - experimentalMode = true; - } + + static auto constexpr isExperimental = [](std::string_view const _cliFlag) -> bool { + auto const& experimentalOpts = CommandLineParser::experimentalOptionNames(); + return ranges::find(experimentalOpts, _cliFlag.substr(2)) != ranges::end(experimentalOpts); + }; + bool needsExperimentalMode = isExperimental(optionNameWithoutValue) || isExperimental(inputMode); + if (needsExperimentalMode) + commandLine.emplace_back("--experimental"); std::string expectedMessage = "The following options are not supported in the current input mode: " + optionNameWithoutValue; // When --experimental is combined with --standard-json, a different error fires first @@ -469,7 +473,7 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations) { std::string const what = _exception.what(); return what == expectedMessage || ( - experimentalMode && + needsExperimentalMode && what.starts_with("Standard JSON input mode is incompatible with the --experimental flag.") ); }; From bb64ae44fe60837bf92d631948b13d3b6edb9a58 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 12 Mar 2026 14:47:34 +0100 Subject: [PATCH 1178/1340] cli parser: expose set of experimental cli options --- solc/CommandLineParser.cpp | 30 ++++++++++++++++++------------ solc/CommandLineParser.h | 3 +++ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index c40840a07..297a2f497 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -159,6 +159,23 @@ void CommandLineParser::checkMutuallyExclusive(std::vector const& _ } } +std::vector const& CommandLineParser::experimentalOptionNames() +{ + static std::vector const names{ + g_strLSP, + g_strImportAst, + g_strImportEvmAssemblerJson, + "ir-ast-json", + "ir-optimized-ast-json", + "yul-cfg-json", + "ethdebug", + "ethdebug-runtime", + g_strEOFVersion, + g_strViaSSACFG, + }; + return names; +} + void CommandLineParser::checkExperimental(std::vector const& _optionNames) const { if (!m_args.contains(g_strExperimental) && countEnabledOptions(_optionNames) > 0) @@ -994,18 +1011,7 @@ void CommandLineParser::processArgs() g_strImportEvmAssemblerJson, }); - checkExperimental({ - g_strLSP, - g_strImportAst, - g_strImportEvmAssemblerJson, - "ir-ast-json", - "ir-optimized-ast-json", - "yul-cfg-json", - "ethdebug", - "ethdebug-runtime", - g_strEOFVersion, - g_strViaSSACFG, - }); + checkExperimental(experimentalOptionNames()); if (m_args.count(g_strHelp) > 0) m_options.input.mode = InputMode::Help; diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 5f5527c61..bc13acf9c 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -289,6 +289,9 @@ class CommandLineParser CommandLineOptions const& options() const { return m_options; } + /// yields CLI option names (without leading "--") that require --experimental. + static std::vector const& experimentalOptionNames(); + static void printHelp(std::ostream& _out) { _out << optionsDescription(); } private: From d5f9e38083858389e5a736a07d55d98ae1786c64 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 16 Mar 2026 10:35:08 +0100 Subject: [PATCH 1179/1340] repair changelog: move performance optimization from 0.8.34 to 0.8.35 and reclassify bfs deduplication issue as bugfix --- Changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index ec45b99c7..533a45628 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,9 +9,10 @@ Compiler Features: * General: Restrict the existing experimental features (`generic-solidity`, `lsp`, `ethdebug`, `eof`, `evm`, `ast-import`, `evmasm-import`, `ir-ast`, `ssa-cfg`) to experimental mode. * Metadata: Store the state of the experimental mode in JSON and CBOR metadata. In CBOR this broadens the meaning of the existing `experimental` field, which used to indicate only the presence of certain experimental pragmas in the source. * Standard JSON Interface: Introduce `settings.experimental` setting required for enabling the experimental mode. -* Yul EVM Code Transform: Improve stack shuffler performance by fixing a BFS deduplication issue. +* Yul Optimizer: Improve performance of control flow side effects collector and function references resolver. Bugfixes: +* Yul EVM Code Transform: Improve stack shuffler performance by fixing a BFS deduplication issue. ### 0.8.34 (2026-02-18) @@ -21,7 +22,6 @@ Important Bugfixes: Compiler Features: -* Yul Optimizer: Improve performance of control flow side effects collector and function references resolver. * Yul Optimizer: Remove redundant prerequisite steps from the default optimizer sequence. From 6e209e653b6c6bf7a51715aec9fbbe11612ca765 Mon Sep 17 00:00:00 2001 From: dxo Date: Mon, 16 Mar 2026 17:55:35 +0100 Subject: [PATCH 1180/1340] .gitignore: add .claude Claude creates this when e.g. whitelisting certain tools. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8d7ee768a..a34aaf514 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,6 @@ emscripten_build/ # OS specific local files .DS_Store Thumbs.db + +# AI tooling +/.claude/ From 0c2a84fa2134315f6ea02f07efdcd2c87160dd65 Mon Sep 17 00:00:00 2001 From: dxo Date: Mon, 16 Mar 2026 17:46:29 +0100 Subject: [PATCH 1181/1340] cmake: generate compile_commands.json makes clangd work out of the box. has no impact on configure times on my laptop. --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 410acd86f..685df9809 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.13.0) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + set(ETH_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}/cmake" CACHE PATH "The path to the cmake directory") list(APPEND CMAKE_MODULE_PATH ${ETH_CMAKE_DIR}) From 1a65349495ec9081fd3f2d79fba33fdffa5c59da Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 10 Mar 2026 19:01:41 +0100 Subject: [PATCH 1182/1340] remove `solidity::yul::Language::Assembly` --- libyul/ObjectOptimizer.cpp | 1 - libyul/ObjectOptimizer.h | 3 +-- libyul/YulStack.h | 4 ++-- solc/CommandLineParser.cpp | 2 +- test/libsolidity/InlineAssembly.cpp | 14 +++++++------- test/solc/CommandLineParser.cpp | 4 ++-- 6 files changed, 13 insertions(+), 15 deletions(-) diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index 63f372bf6..6ae716aa9 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -47,7 +47,6 @@ Dialect const& yul::languageToDialect(Language _language, EVMVersion _version, s { switch (_language) { - case Language::Assembly: case Language::StrictAssembly: return EVMDialect::strictAssemblyForEVMObjects(_version, _eofVersion); } diff --git a/libyul/ObjectOptimizer.h b/libyul/ObjectOptimizer.h index b2019d36b..c574c50dd 100644 --- a/libyul/ObjectOptimizer.h +++ b/libyul/ObjectOptimizer.h @@ -34,8 +34,7 @@ namespace solidity::yul enum class Language { - Assembly, - StrictAssembly, + StrictAssembly }; Dialect const& languageToDialect(Language _language, langutil::EVMVersion _version, std::optional _eofVersion); diff --git a/libyul/YulStack.h b/libyul/YulStack.h index 694c14e36..10e8dc781 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -81,7 +81,7 @@ class YulStack: public langutil::CharStreamProvider YulStack( langutil::EVMVersion{}, std::nullopt, - Language::Assembly, + Language::StrictAssembly, solidity::frontend::OptimiserSettings::none(), langutil::DebugInfoSelection::Default() ) @@ -174,7 +174,7 @@ class YulStack: public langutil::CharStreamProvider void reportUnimplementedFeatureError(langutil::UnimplementedFeatureError const& _error); - Language m_language = Language::Assembly; + Language m_language = Language::StrictAssembly; langutil::EVMVersion m_evmVersion; std::optional m_eofVersion; solidity::frontend::OptimiserSettings m_optimiserSettings; diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 297a2f497..46fc55979 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -1358,7 +1358,7 @@ void CommandLineParser::processArgs() // switch to assembly mode using Input = yul::YulStack::Language; using Machine = yul::YulStack::Machine; - m_options.assembly.inputLanguage = m_args.count(g_strStrictAssembly) ? Input::StrictAssembly : Input::Assembly; + m_options.assembly.inputLanguage = Input::StrictAssembly; if (m_args.count(g_strMachine)) { diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index fb08c667c..ae414ea7b 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -56,7 +56,7 @@ std::optional parseAndReturnFirstError( std::string const& _source, bool _assemble = false, bool _allowWarnings = true, - YulStack::Language _language = YulStack::Language::Assembly, + YulStack::Language _language = YulStack::Language::StrictAssembly, YulStack::Machine _machine = YulStack::Machine::EVM ) { @@ -93,14 +93,14 @@ bool successParse( std::string const& _source, bool _assemble = false, bool _allowWarnings = true, - YulStack::Language _language = YulStack::Language::Assembly, + YulStack::Language _language = YulStack::Language::StrictAssembly, YulStack::Machine _machine = YulStack::Machine::EVM ) { return !parseAndReturnFirstError(_source, _assemble, _allowWarnings, _language, _machine); } -bool successAssemble(std::string const& _source, bool _allowWarnings = true, YulStack::Language _language = YulStack::Language::Assembly) +bool successAssemble(std::string const& _source, bool _allowWarnings = true, YulStack::Language _language = YulStack::Language::StrictAssembly) { return successParse(_source, true, _allowWarnings, _language, YulStack::Machine::EVM); @@ -110,7 +110,7 @@ Error expectError( std::string const& _source, bool _assemble, bool _allowWarnings = false, - YulStack::Language _language = YulStack::Language::Assembly + YulStack::Language _language = YulStack::Language::StrictAssembly ) { @@ -124,7 +124,7 @@ void parsePrintCompare(std::string const& _source, bool _canWarn = false) YulStack stack( solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().eofVersion(), - YulStack::Language::Assembly, + YulStack::Language::StrictAssembly, OptimiserSettings::none(), DebugInfoSelection::None() ); @@ -148,7 +148,7 @@ do \ } while(0) #define CHECK_ERROR(text, assemble, typ, substring, warnings) \ -CHECK_ERROR_LANG(text, assemble, typ, substring, warnings, YulStack::Language::Assembly) +CHECK_ERROR_LANG(text, assemble, typ, substring, warnings, YulStack::Language::StrictAssembly) #define CHECK_PARSE_ERROR(text, type, substring) \ CHECK_ERROR(text, false, type, substring, false) @@ -215,7 +215,7 @@ BOOST_AUTO_TEST_CASE(print_string_literal_unicode) YulStack stack( solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().eofVersion(), - YulStack::Language::Assembly, + YulStack::Language::StrictAssembly, OptimiserSettings::none(), DebugInfoSelection::None() ); diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 2233d0df3..bf3e7ab1b 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -278,9 +278,9 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) static std::vector, YulStack::Machine, YulStack::Language>> const allowedCombinations = { {{"--machine=evm", "--yul-dialect=evm", "--assemble"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, {{"--machine=evm", "--yul-dialect=evm", "--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, - {{"--machine=evm", "--assemble"}, YulStack::Machine::EVM, YulStack::Language::Assembly}, + {{"--machine=evm", "--assemble"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, {{"--machine=evm", "--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, - {{"--assemble"}, YulStack::Machine::EVM, YulStack::Language::Assembly}, + {{"--assemble"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, {{"--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, }; From ff18b9867d54893bdd98a6074b692e237f7096dd Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 12 Mar 2026 16:35:06 +0100 Subject: [PATCH 1183/1340] deactivate --assemble CLI option --- Changelog.md | 1 + solc/CommandLineParser.cpp | 15 ++++++++-- test/cmdlineTests/~assembler_modes/test.sh | 13 +++++++-- test/solc/CommandLineInterface.cpp | 3 +- test/solc/CommandLineParser.cpp | 32 ++++++++++------------ 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/Changelog.md b/Changelog.md index 533a45628..02a6c1d10 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: * General: Add a builtin that computes the base slot of a storage namespace using the `erc7201` formula from ERC-7201. Compiler Features: +* Commandline Interface: Disallow selecting the deprecated assembly input mode that was only accessible via `--assemble` instead of treating it as equivalent to `--strict-assembly`. * Commandline Interface: Introduce `--experimental` flag required for enabling the experimental mode. * General: Introduce the SSA CFG codegen (experimental). * General: Restrict the existing experimental features (`generic-solidity`, `lsp`, `ethdebug`, `eof`, `evm`, `ast-import`, `evmasm-import`, `ir-ast`, `ssa-cfg`) to experimental mode. diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 46fc55979..c7c089b73 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -683,7 +683,10 @@ General Information)").c_str(), ) ( g_strAssemble.c_str(), - "Switch to assembly mode and assume input is assembly." + fmt::format( + "(disabled) Switch to assembly mode and assume input is assembly. No longer supported. Use --{} instead.", + g_strStrictAssembly + ).c_str() ) ( g_strStrictAssembly.c_str(), @@ -1004,7 +1007,6 @@ void CommandLineParser::processArgs() g_strVersion, g_strStandardJSON, g_strLink, - g_strAssemble, g_strStrictAssembly, g_strImportAst, g_strLSP, @@ -1023,7 +1025,7 @@ void CommandLineParser::processArgs() m_options.input.mode = InputMode::StandardJson; else if (m_args.count(g_strLSP)) m_options.input.mode = InputMode::LanguageServer; - else if (m_args.count(g_strAssemble) > 0 || m_args.count(g_strStrictAssembly) > 0) + else if (m_args.contains(g_strStrictAssembly)) m_options.input.mode = InputMode::Assembler; else if (m_args.count(g_strLink) > 0) m_options.input.mode = InputMode::Linker; @@ -1056,6 +1058,13 @@ void CommandLineParser::processArgs() "please use --strict-assembly instead." ); + if (m_args.contains(g_strAssemble)) + solThrow( + CommandLineValidationError, + "The assembly input mode formerly accessible via --assemble is no longer supported, " + "please use --strict-assembly instead." + ); + std::map> validOptionInputModeCombinations = { // TODO: This should eventually contain all options. {g_strExperimentalViaIR, {InputMode::Compiler, InputMode::CompilerWithASTImport}}, diff --git a/test/cmdlineTests/~assembler_modes/test.sh b/test/cmdlineTests/~assembler_modes/test.sh index 708c76395..655ceea5c 100755 --- a/test/cmdlineTests/~assembler_modes/test.sh +++ b/test/cmdlineTests/~assembler_modes/test.sh @@ -24,11 +24,18 @@ function test_solc_assembly_output fi } -echo '{}' | msg_on_error --silent "$SOLC" - --assemble echo '{}' | msg_on_error --silent "$SOLC" - --strict-assembly -# Test in conjunction with --optimize. Using both, --assemble and --optimize should fail. -echo '{}' | "$SOLC" - --assemble --optimize &>/dev/null && fail "solc --assemble --optimize did not fail as expected." +# Test that --assemble triggers an error +set +e +output=$(echo '{}' | "$SOLC" - --assemble 2>&1) +failed=$? +expected="Error: The assembly input mode formerly accessible via --assemble is no longer supported, please use --strict-assembly instead." +set -e +if [[ $output != "${expected}" ]] || (( failed == 0 )) +then + fail "Incorrect error response to --assemble flag: $output" +fi # Test strict assembly output # Non-empty code results in non-empty binary representation with optimizations turned off, diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 2141b9e63..720c3b154 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -154,14 +154,13 @@ BOOST_AUTO_TEST_CASE(multiple_input_modes) "--version", "--standard-json", "--link", - "--assemble", "--strict-assembly", "--import-ast", "--import-asm-json", }; std::string expectedMessage = "The following options are mutually exclusive: " - "--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --import-ast, --lsp, --import-asm-json. " + "--help, --license, --version, --standard-json, --link, --strict-assembly, --import-ast, --lsp, --import-asm-json. " "Select at most one."; for (auto const& mode1: inputModeOptions) diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index bf3e7ab1b..da3e4b138 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -253,7 +253,6 @@ BOOST_AUTO_TEST_CASE(no_import_callback) std::vector> commandLinePerInputMode = { {"solc", "--no-import-callback", "contract.sol"}, {"solc", "--standard-json", "--no-import-callback", "input.json"}, - {"solc", "--assemble", "--no-import-callback", "input.yul"}, {"solc", "--strict-assembly", "--no-import-callback", "input.yul"}, {"solc", "--experimental", "--import-ast", "--no-import-callback", "ast.json"}, {"solc", "--link", "--no-import-callback", "input.bin"}, @@ -276,11 +275,8 @@ BOOST_AUTO_TEST_CASE(via_ir_options) BOOST_AUTO_TEST_CASE(assembly_mode_options) { static std::vector, YulStack::Machine, YulStack::Language>> const allowedCombinations = { - {{"--machine=evm", "--yul-dialect=evm", "--assemble"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, {{"--machine=evm", "--yul-dialect=evm", "--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, - {{"--machine=evm", "--assemble"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, {{"--machine=evm", "--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, - {{"--assemble"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, {{"--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, }; @@ -431,20 +427,20 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations) { std::map> invalidOptionInputModeCombinations = { // TODO: This should eventually contain all options. - {"--experimental-via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--metadata-literal", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--metadata-hash=swarm", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--model-checker-show-proved-safe", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--model-checker-show-unproved", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--model-checker-show-unsupported", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--model-checker-div-mod-no-slacks", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--model-checker-engine=bmc", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--model-checker-invariants=contract,reentrancy", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--model-checker-solvers=z3,smtlib2", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--model-checker-timeout=5", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--model-checker-contracts=contract1.yul:A,contract2.yul:B", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, - {"--model-checker-targets=underflow,divByZero", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--experimental-via-ir", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--via-ir", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--metadata-literal", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--metadata-hash=swarm", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-show-proved-safe", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-show-unproved", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-show-unsupported", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-div-mod-no-slacks", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-engine=bmc", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-invariants=contract,reentrancy", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-solvers=z3,smtlib2", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-timeout=5", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-contracts=contract1.yul:A,contract2.yul:B", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-targets=underflow,divByZero", {"--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, {"--via-ssa-cfg", {"--standard-json", "--link", "--import-asm-json"}} }; From ab0c57194e03b333cd76d3ef1eba1c4564c1e542 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 13 Mar 2026 10:45:05 +0100 Subject: [PATCH 1184/1340] Remove `yul::Language` --- libsolidity/interface/CompilerStack.cpp | 1 - libsolidity/interface/StandardCompiler.cpp | 1 - libyul/ObjectOptimizer.cpp | 21 ++-------- libyul/ObjectOptimizer.h | 8 ---- libyul/YulStack.cpp | 8 ++-- libyul/YulStack.h | 5 --- solc/CommandLineInterface.cpp | 5 +-- solc/CommandLineInterface.h | 2 +- solc/CommandLineParser.cpp | 25 ++---------- solc/CommandLineParser.h | 1 - test/libsolidity/InlineAssembly.cpp | 29 +++++--------- test/libyul/Common.cpp | 1 - test/libyul/EVMCodeTransformTest.cpp | 1 - test/libyul/ObjectParser.cpp | 1 - test/solc/CommandLineParser.cpp | 39 ++++++++----------- test/tools/ossfuzz/YulEvmoneInterface.h | 1 - .../ossfuzz/strictasm_assembly_ossfuzz.cpp | 1 - test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 1 - test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp | 1 - test/tools/ossfuzz/yulProtoFuzzer.cpp | 1 - test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp | 1 - test/tools/yulrun.cpp | 1 - 22 files changed, 40 insertions(+), 115 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 152a0059a..bb38555ec 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -850,7 +850,6 @@ YulStack CompilerStack::loadGeneratedIR(std::string const& _ir) const YulStack stack( m_evmVersion, m_eofVersion, - YulStack::Language::StrictAssembly, m_optimiserSettings, m_debugInfoSelection, this, // _soliditySourceProvider diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index a556c74db..264ce55bb 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1755,7 +1755,6 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) YulStack stack( _inputsAndSettings.evmVersion, _inputsAndSettings.eofVersion, - YulStack::Language::StrictAssembly, _inputsAndSettings.optimiserSettings, _inputsAndSettings.debugInfoSelection.has_value() ? _inputsAndSettings.debugInfoSelection.value() : diff --git a/libyul/ObjectOptimizer.cpp b/libyul/ObjectOptimizer.cpp index 6ae716aa9..e0a0ddb24 100644 --- a/libyul/ObjectOptimizer.cpp +++ b/libyul/ObjectOptimizer.cpp @@ -43,16 +43,6 @@ using namespace solidity::util; using namespace solidity::yul; -Dialect const& yul::languageToDialect(Language _language, EVMVersion _version, std::optional _eofVersion) -{ - switch (_language) - { - case Language::StrictAssembly: - return EVMDialect::strictAssemblyForEVMObjects(_version, _eofVersion); - } - util::unreachable(); -} - void ObjectOptimizer::optimize(Object& _object, Settings const& _settings) { yulAssert(_object.subId.empty(), "Not a top-level object."); @@ -76,10 +66,8 @@ void ObjectOptimizer::optimize(Object& _object, Settings const& _settings, bool ); } - Dialect const& dialect = languageToDialect(_settings.language, _settings.evmVersion, _settings.eofVersion); - std::unique_ptr meter; - if (EVMDialect const* evmDialect = dynamic_cast(&dialect)) - meter = std::make_unique(*evmDialect, _isCreation, _settings.expectedExecutionsPerDeployment); + EVMDialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(_settings.evmVersion, _settings.eofVersion); + GasMeter const meter(dialect, _isCreation, _settings.expectedExecutionsPerDeployment); std::optional cacheKey = calculateCacheKey(_object.code()->root(), *_object.debugData, _settings, _isCreation); if (cacheKey.has_value() && m_cachedObjects.count(*cacheKey) != 0) @@ -89,7 +77,7 @@ void ObjectOptimizer::optimize(Object& _object, Settings const& _settings, bool } OptimiserSuite::run( - meter.get(), + &meter, _object, _settings.optimizeStackAllocation, _settings.yulOptimiserSteps, @@ -140,7 +128,7 @@ std::optional ObjectOptimizer::calculateCacheKey( ) { AsmPrinter asmPrinter( - languageToDialect(_settings.language, _settings.evmVersion, _settings.eofVersion), + EVMDialect::strictAssemblyForEVMObjects(_settings.evmVersion, _settings.eofVersion), _debugData.sourceNames, DebugInfoSelection::All() ); @@ -152,7 +140,6 @@ std::optional ObjectOptimizer::calculateCacheKey( // we just regenerate them by reparsing the object. rawKey += keccak256(asmPrinter(_ast)).asBytes(); rawKey += keccak256(_debugData.formatUseSrcComment()).asBytes(); - rawKey += h256(u256(_settings.language)).asBytes(); static_assert(static_cast(static_cast(2)) == 1); rawKey += FixedHash<1>(static_cast(_settings.optimizeStackAllocation)).asBytes(); rawKey += h256(u256(_settings.expectedExecutionsPerDeployment)).asBytes(); diff --git a/libyul/ObjectOptimizer.h b/libyul/ObjectOptimizer.h index c574c50dd..2cd9d7f98 100644 --- a/libyul/ObjectOptimizer.h +++ b/libyul/ObjectOptimizer.h @@ -32,13 +32,6 @@ namespace solidity::yul { -enum class Language -{ - StrictAssembly -}; - -Dialect const& languageToDialect(Language _language, langutil::EVMVersion _version, std::optional _eofVersion); - /// Encapsulates logic for applying @a yul::OptimiserSuite to a whole hierarchy of Yul objects. /// Also, acts as a transparent cache for optimized objects. /// @@ -55,7 +48,6 @@ class ObjectOptimizer /// must uniquely determine the result of optimization. struct Settings { - Language language; langutil::EVMVersion evmVersion; std::optional eofVersion; bool optimizeStackAllocation; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 496f249a3..246773bb6 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -58,7 +58,7 @@ bool YulStack::parse(std::string const& _sourceName, std::string const& _source) { m_charStream = std::make_unique(_source, _sourceName); std::shared_ptr scanner = std::make_shared(*m_charStream); - m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion, m_eofVersion)).parse(scanner, false); + m_parserResult = ObjectParser(m_errorReporter, EVMDialect::strictAssemblyForEVMObjects(m_evmVersion, m_eofVersion)).parse(scanner, false); } catch (UnimplementedFeatureError const& _error) { @@ -130,7 +130,6 @@ void YulStack::optimize() m_objectOptimizer->optimize( *m_parserResult, ObjectOptimizer::Settings{ - m_language, m_evmVersion, m_eofVersion, optimizeStackAllocation, @@ -166,7 +165,7 @@ bool YulStack::analyzeParsed(Object& _object) AsmAnalyzer analyzer( *_object.analysisInfo, m_errorReporter, - languageToDialect(m_language, m_evmVersion, m_eofVersion), + EVMDialect::strictAssemblyForEVMObjects(m_evmVersion, m_eofVersion), {}, _object.summarizeStructure() ); @@ -210,7 +209,6 @@ void YulStack::reparse() YulStack cleanStack( m_evmVersion, m_eofVersion, - m_language, m_optimiserSettings, m_debugInfoSelection, m_soliditySourceProvider, @@ -400,7 +398,7 @@ Json YulStack::cfgJson() const // NOTE: The block Ids are reset for each object std::unique_ptr controlFlow = ssa::SSACFGBuilder::build( *_object.analysisInfo, - languageToDialect(m_language, m_evmVersion, m_eofVersion), + EVMDialect::strictAssemblyForEVMObjects(m_evmVersion, m_eofVersion), _object.code()->root(), keepLiteralAssignments ); diff --git a/libyul/YulStack.h b/libyul/YulStack.h index 10e8dc781..66cd56c06 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -69,7 +69,6 @@ struct MachineAssemblyObject class YulStack: public langutil::CharStreamProvider { public: - using Language = yul::Language; enum class Machine { EVM }; enum State { Empty, @@ -81,7 +80,6 @@ class YulStack: public langutil::CharStreamProvider YulStack( langutil::EVMVersion{}, std::nullopt, - Language::StrictAssembly, solidity::frontend::OptimiserSettings::none(), langutil::DebugInfoSelection::Default() ) @@ -90,13 +88,11 @@ class YulStack: public langutil::CharStreamProvider YulStack( langutil::EVMVersion _evmVersion, std::optional _eofVersion, - Language _language, solidity::frontend::OptimiserSettings _optimiserSettings, langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider = nullptr, std::shared_ptr _objectOptimizer = nullptr ): - m_language(_language), m_evmVersion(_evmVersion), m_eofVersion(_eofVersion), m_optimiserSettings(std::move(_optimiserSettings)), @@ -174,7 +170,6 @@ class YulStack: public langutil::CharStreamProvider void reportUnimplementedFeatureError(langutil::UnimplementedFeatureError const& _error); - Language m_language = Language::StrictAssembly; langutil::EVMVersion m_evmVersion; std::optional m_eofVersion; solidity::frontend::OptimiserSettings m_optimiserSettings; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index a40853e49..a805ac3fe 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -848,7 +848,7 @@ void CommandLineInterface::processInput() serveLSP(); break; case InputMode::Assembler: - assembleYul(m_options.assembly.inputLanguage, m_options.assembly.targetMachine); + assembleYul(m_options.assembly.targetMachine); break; case InputMode::Linker: link(); @@ -1286,7 +1286,7 @@ std::string CommandLineInterface::objectWithLinkRefsHex(evmasm::LinkerObject con return out; } -void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::YulStack::Machine _targetMachine) +void CommandLineInterface::assembleYul(yul::YulStack::Machine _targetMachine) { solAssert(m_options.input.mode == InputMode::Assembler); @@ -1298,7 +1298,6 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y auto& stack = yulStacks[sourceUnitName] = yul::YulStack( m_options.output.evmVersion, m_options.output.eofVersion, - _language, m_options.optimiserSettings(), m_options.output.debugInfoSelection.has_value() ? m_options.output.debugInfoSelection.value() : diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index b8a10c372..e61bf359f 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -95,7 +95,7 @@ class CommandLineInterface /// @returns the full object with library placeholder hints in hex. static std::string objectWithLinkRefsHex(evmasm::LinkerObject const& _obj); - void assembleYul(yul::YulStack::Language _language, yul::YulStack::Machine _targetMachine); + void assembleYul(yul::YulStack::Machine _targetMachine); void outputCompilationResults(); diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index c7c089b73..f778fc27e 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -1365,9 +1365,7 @@ void CommandLineParser::processArgs() } // switch to assembly mode - using Input = yul::YulStack::Language; using Machine = yul::YulStack::Machine; - m_options.assembly.inputLanguage = Input::StrictAssembly; if (m_args.count(g_strMachine)) { @@ -1377,30 +1375,15 @@ void CommandLineParser::processArgs() else solThrow(CommandLineValidationError, "Invalid option for --" + g_strMachine + ": " + machine); } - if (m_args.count(g_strYulDialect)) + if (m_args.contains(g_strYulDialect)) { - std::string dialect = m_args[g_strYulDialect].as(); - if (dialect == g_strEVM) - m_options.assembly.inputLanguage = Input::StrictAssembly; - else + auto const& dialect = m_args[g_strYulDialect].as(); + if (dialect != g_strEVM) solThrow(CommandLineValidationError, "Invalid option for --" + g_strYulDialect + ": " + dialect); } - if ( - (m_options.optimizer.optimizeEvmasm || m_options.optimizer.optimizeYul) && - m_options.assembly.inputLanguage != Input::StrictAssembly - ) - solThrow( - CommandLineValidationError, - "Optimizer can only be used for strict assembly. Use --" + g_strStrictAssembly + "." - ); m_options.output.viaSSACFG = m_args.contains(g_strViaSSACFG); - if (m_options.output.viaSSACFG) - if (m_options.assembly.inputLanguage != Input::StrictAssembly) - solThrow( - CommandLineValidationError, - "--" + g_strViaSSACFG + " can only be used with strict assembly. Use --" + g_strStrictAssembly + "." - ); + if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) { if (m_options.output.viaSSACFG) diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index bc13acf9c..96dbb49c3 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -213,7 +213,6 @@ struct CommandLineOptions bool operator!=(Assembly const&) const noexcept = default; yul::YulStack::Machine targetMachine = yul::YulStack::Machine::EVM; - yul::YulStack::Language inputLanguage = yul::YulStack::Language::StrictAssembly; } assembly; struct Linker diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index ae414ea7b..05d4514f2 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -56,14 +56,12 @@ std::optional parseAndReturnFirstError( std::string const& _source, bool _assemble = false, bool _allowWarnings = true, - YulStack::Language _language = YulStack::Language::StrictAssembly, YulStack::Machine _machine = YulStack::Machine::EVM ) { YulStack stack( solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().eofVersion(), - _language, solidity::frontend::OptimiserSettings::none(), DebugInfoSelection::None() ); @@ -93,28 +91,26 @@ bool successParse( std::string const& _source, bool _assemble = false, bool _allowWarnings = true, - YulStack::Language _language = YulStack::Language::StrictAssembly, YulStack::Machine _machine = YulStack::Machine::EVM ) { - return !parseAndReturnFirstError(_source, _assemble, _allowWarnings, _language, _machine); + return !parseAndReturnFirstError(_source, _assemble, _allowWarnings, _machine); } -bool successAssemble(std::string const& _source, bool _allowWarnings = true, YulStack::Language _language = YulStack::Language::StrictAssembly) +bool successAssemble(std::string const& _source, bool _allowWarnings = true) { return - successParse(_source, true, _allowWarnings, _language, YulStack::Machine::EVM); + successParse(_source, true, _allowWarnings, YulStack::Machine::EVM); } Error expectError( std::string const& _source, bool _assemble, - bool _allowWarnings = false, - YulStack::Language _language = YulStack::Language::StrictAssembly + bool _allowWarnings = false ) { - auto error = parseAndReturnFirstError(_source, _assemble, _allowWarnings, _language); + auto error = parseAndReturnFirstError(_source, _assemble, _allowWarnings); BOOST_REQUIRE(error); return *error; } @@ -124,7 +120,6 @@ void parsePrintCompare(std::string const& _source, bool _canWarn = false) YulStack stack( solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, OptimiserSettings::none(), DebugInfoSelection::None() ); @@ -139,17 +134,14 @@ void parsePrintCompare(std::string const& _source, bool _canWarn = false) } -#define CHECK_ERROR_LANG(text, assemble, typ, substring, warnings, language) \ +#define CHECK_ERROR(text, assemble, typ, substring, warnings) \ do \ { \ - Error err = expectError((text), (assemble), warnings, (language)); \ + Error err = expectError((text), (assemble), warnings); \ BOOST_CHECK(err.type() == (Error::Type::typ)); \ BOOST_CHECK(searchErrorMessage(err, (substring))); \ } while(0) -#define CHECK_ERROR(text, assemble, typ, substring, warnings) \ -CHECK_ERROR_LANG(text, assemble, typ, substring, warnings, YulStack::Language::StrictAssembly) - #define CHECK_PARSE_ERROR(text, type, substring) \ CHECK_ERROR(text, false, type, substring, false) @@ -160,13 +152,13 @@ CHECK_ERROR(text, false, type, substring, false) CHECK_ERROR(text, true, type, substring, false) #define CHECK_STRICT_ERROR(text, type, substring) \ -CHECK_ERROR_LANG(text, false, type, substring, false, YulStack::Language::StrictAssembly) +CHECK_ERROR(text, false, type, substring, false) #define CHECK_STRICT_WARNING(text, type, substring) \ -CHECK_ERROR(text, false, type, substring, false, YulStack::Language::StrictAssembly) +CHECK_ERROR(text, false, type, substring, false) #define SUCCESS_STRICT(text) \ -do { successParse((text), false, false, YulStack::Language::StrictAssembly); } while (false) +do { successParse((text), false, false); } while (false) BOOST_AUTO_TEST_SUITE(SolidityInlineAssembly) @@ -215,7 +207,6 @@ BOOST_AUTO_TEST_CASE(print_string_literal_unicode) YulStack stack( solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, OptimiserSettings::none(), DebugInfoSelection::None() ); diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index a9f4c59a7..06f84d342 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -59,7 +59,6 @@ YulStack yul::test::parseYul( YulStack yulStack( CommonOptions::get().evmVersion(), CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, _optimiserSettings.has_value() ? *_optimiserSettings : (CommonOptions::get().optimize ? OptimiserSettings::standard() : OptimiserSettings::minimal()), diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 96699b109..1f814b53d 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -56,7 +56,6 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin YulStack yulStack( CommonOptions::get().evmVersion(), CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, settings, DebugInfoSelection::AllExceptExperimental() ); diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index 446348fa0..bc2361563 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -149,7 +149,6 @@ BOOST_AUTO_TEST_CASE(to_string) YulStack asmStack( solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().eofVersion(), - YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::none(), DebugInfoSelection::AllExceptExperimental() ); diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index da3e4b138..365944652 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -274,13 +274,13 @@ BOOST_AUTO_TEST_CASE(via_ir_options) BOOST_AUTO_TEST_CASE(assembly_mode_options) { - static std::vector, YulStack::Machine, YulStack::Language>> const allowedCombinations = { - {{"--machine=evm", "--yul-dialect=evm", "--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, - {{"--machine=evm", "--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, - {{"--strict-assembly"}, YulStack::Machine::EVM, YulStack::Language::StrictAssembly}, + static std::vector, YulStack::Machine>> const allowedCombinations = { + {{"--machine=evm", "--yul-dialect=evm", "--strict-assembly"}, YulStack::Machine::EVM}, + {{"--machine=evm", "--strict-assembly"}, YulStack::Machine::EVM}, + {{"--strict-assembly"}, YulStack::Machine::EVM}, }; - for (auto const& [assemblyOptions, expectedMachine, expectedLanguage]: allowedCombinations) + for (auto const& [assemblyOptions, expectedMachine]: allowedCombinations) { std::vector commandLine = { "solc", @@ -314,16 +314,13 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) "--bin", "--ir-optimized", "--ast-compact-json", + "--experimental", + "--optimize", + "--optimize-runs=1000", + "--yul-optimizations=agf", + "--via-ssa-cfg", }; commandLine += assemblyOptions; - if (expectedLanguage == YulStack::Language::StrictAssembly) - commandLine += std::vector{ - "--experimental", - "--optimize", - "--optimize-runs=1000", - "--yul-optimizations=agf", - "--via-ssa-cfg", - }; CommandLineOptions expectedOptions; expectedOptions.input.mode = InputMode::Assembler; @@ -345,7 +342,6 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) expectedOptions.output.debugInfoSelection = DebugInfoSelection::fromString("location"); expectedOptions.formatting.json = JsonFormat {JsonFormat::Pretty, 1}; expectedOptions.assembly.targetMachine = expectedMachine; - expectedOptions.assembly.inputLanguage = expectedLanguage; expectedOptions.linker.libraries = { {"dir1/file1.sol:L", h160("1234567890123456789012345678901234567890")}, {"dir2/file2.sol:L", h160("1111122222333334444455555666667777788888")}, @@ -357,15 +353,12 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) expectedOptions.compiler.outputs.binary = true; expectedOptions.compiler.outputs.irOptimized = true; expectedOptions.compiler.outputs.astCompactJson = true; - if (expectedLanguage == YulStack::Language::StrictAssembly) - { - expectedOptions.experimental = true; - expectedOptions.optimizer.optimizeEvmasm = true; - expectedOptions.optimizer.optimizeYul = true; - expectedOptions.optimizer.yulSteps = "agf"; - expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000; - expectedOptions.output.viaSSACFG = true; - } + expectedOptions.experimental = true; + expectedOptions.optimizer.optimizeEvmasm = true; + expectedOptions.optimizer.optimizeYul = true; + expectedOptions.optimizer.yulSteps = "agf"; + expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000; + expectedOptions.output.viaSSACFG = true; CommandLineOptions parsedOptions = parseCommandLine(commandLine); diff --git a/test/tools/ossfuzz/YulEvmoneInterface.h b/test/tools/ossfuzz/YulEvmoneInterface.h index 71a47507e..687d1b45d 100644 --- a/test/tools/ossfuzz/YulEvmoneInterface.h +++ b/test/tools/ossfuzz/YulEvmoneInterface.h @@ -39,7 +39,6 @@ class YulAssembler m_stack( _evmVersion, _eofVersion, - solidity::yul::YulStack::Language::StrictAssembly, _optSettings, langutil::DebugInfoSelection::All() ), diff --git a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp index 5a9192bc3..df5f2626c 100644 --- a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp @@ -39,7 +39,6 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) YulStack stack( langutil::EVMVersion(), std::nullopt, - YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::minimal(), langutil::DebugInfoSelection::AllExceptExperimental() ); diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index 9abf269c8..966c6d7a9 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -63,7 +63,6 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) YulStack stack( langutil::EVMVersion(), std::nullopt, - YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), DebugInfoSelection::AllExceptExperimental() ); diff --git a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp index 454380492..c469e2eae 100644 --- a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp @@ -40,7 +40,6 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) YulStack stack( langutil::EVMVersion(), std::nullopt, - YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), DebugInfoSelection::AllExceptExperimental() ); diff --git a/test/tools/ossfuzz/yulProtoFuzzer.cpp b/test/tools/ossfuzz/yulProtoFuzzer.cpp index 2f372c325..d8d8fb550 100644 --- a/test/tools/ossfuzz/yulProtoFuzzer.cpp +++ b/test/tools/ossfuzz/yulProtoFuzzer.cpp @@ -64,7 +64,6 @@ DEFINE_PROTO_FUZZER(Program const& _input) YulStack stack( version, std::nullopt, - YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), DebugInfoSelection::All() ); diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index 4edfbf7ba..8e8b3c1ca 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -64,7 +64,6 @@ DEFINE_PROTO_FUZZER(Program const& _input) YulStack stack( version, std::nullopt, - YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), DebugInfoSelection::All() ); diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index 99d9df1a9..ce3fbc843 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -59,7 +59,6 @@ std::pair, std::shared_ptr> parse(st YulStack stack( langutil::EVMVersion(), std::nullopt, - YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::none(), DebugInfoSelection::Default() ); From 1f5822fbbe3b91dbc92b7a891d4188b8b793395a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 13 Mar 2026 11:02:40 +0100 Subject: [PATCH 1185/1340] Hide `--yul` and `--assemble` from `solc --help` --- solc/CommandLineParser.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index f778fc27e..679cdce44 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -630,11 +630,6 @@ General Information)").c_str(), "(experimental) Select desired EOF version. Currently the only valid value is 1. " "If not specified, non-EOF bytecode will be generated." ) - ( - g_strYul.c_str(), - "(disabled) Switch to typed Yul mode. The typed Yul dialect is no longer supported. " - "For regular Yul compilation use --strict-assembly instead." - ) ( g_strExperimentalViaIR.c_str(), "Deprecated synonym of --via-ir." @@ -681,13 +676,6 @@ General Information)").c_str(), ("Switch to linker mode, ignoring all options apart from --" + g_strLibraries + " " "and modify binaries in place.").c_str() ) - ( - g_strAssemble.c_str(), - fmt::format( - "(disabled) Switch to assembly mode and assume input is assembly. No longer supported. Use --{} instead.", - g_strStrictAssembly - ).c_str() - ) ( g_strStrictAssembly.c_str(), "Switch to strict assembly mode and assume input is strict assembly." @@ -970,6 +958,12 @@ po::positional_options_description CommandLineParser::positionalOptionsDescripti void CommandLineParser::parseArgs(int _argc, char const* const* _argv) { po::options_description allOptions = optionsDescription(); + // Disabled options: still accepted for parsing so that we can produce a proper error message, + // but hidden from --help output. + allOptions.add_options() + (g_strAssemble.c_str(), "") + (g_strYul.c_str(), "") + ; po::positional_options_description filesPositions = positionalOptionsDescription(); m_options = {}; From 4e281a7f36fc2e9b4b7d786794b4b953089a03e5 Mon Sep 17 00:00:00 2001 From: "Mate Soos @ Argot" Date: Wed, 18 Mar 2026 11:37:15 +0100 Subject: [PATCH 1186/1340] Escape object/data names in Yul serializer (#16517) --- Changelog.md | 1 + libyul/Object.cpp | 4 ++-- .../objects/data_name_with_literal_newline.yul | 9 +++++++++ .../objects/data_name_with_special_chars.yul | 7 +++++++ .../objects/object_name_with_all_special_chars.yul | 7 +++++++ .../objects/object_name_with_special_chars.yul | 4 ++++ 6 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 test/libyul/yulSyntaxTests/objects/data_name_with_literal_newline.yul create mode 100644 test/libyul/yulSyntaxTests/objects/data_name_with_special_chars.yul create mode 100644 test/libyul/yulSyntaxTests/objects/object_name_with_all_special_chars.yul create mode 100644 test/libyul/yulSyntaxTests/objects/object_name_with_special_chars.yul diff --git a/Changelog.md b/Changelog.md index 02a6c1d10..c5a942281 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Compiler Features: * Yul Optimizer: Improve performance of control flow side effects collector and function references resolver. Bugfixes: +* Yul: Fix incorrect serialization of Yul object names containing double quotes and escape sequences, producing output that could not be parsed as valid Yul. * Yul EVM Code Transform: Improve stack shuffler performance by fixing a BFS deduplication issue. diff --git a/libyul/Object.cpp b/libyul/Object.cpp index bb0441287..b2fb582ae 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -40,7 +40,7 @@ using namespace solidity::yul; std::string Data::toString(DebugInfoSelection const&, CharStreamProvider const*) const { - return "data \"" + name + "\" hex\"" + util::toHex(data) + "\""; + return "data " + util::escapeAndQuoteString(name) + " hex\"" + util::toHex(data) + "\""; } std::string Object::toString( @@ -64,7 +64,7 @@ std::string Object::toString( return debugData->formatUseSrcComment() + - "object \"" + name + "\" {\n" + + "object " + util::escapeAndQuoteString(name) + " {\n" + indent(inner) + "\n" + "}"; } diff --git a/test/libyul/yulSyntaxTests/objects/data_name_with_literal_newline.yul b/test/libyul/yulSyntaxTests/objects/data_name_with_literal_newline.yul new file mode 100644 index 000000000..a6c861257 --- /dev/null +++ b/test/libyul/yulSyntaxTests/objects/data_name_with_literal_newline.yul @@ -0,0 +1,9 @@ +object "A" { + code { + sstore(0, datasize("B\nC")) + } + data "B +C" hex"1234" +} +// ---- +// ParserError 2314: (65-67): Expected 'StringLiteral' but got 'ILLEGAL' diff --git a/test/libyul/yulSyntaxTests/objects/data_name_with_special_chars.yul b/test/libyul/yulSyntaxTests/objects/data_name_with_special_chars.yul new file mode 100644 index 000000000..27962de55 --- /dev/null +++ b/test/libyul/yulSyntaxTests/objects/data_name_with_special_chars.yul @@ -0,0 +1,7 @@ +object "a" { + code { + pop(datasize("my\"data")) + } + data "my\"data" hex"deadbeef" +} +// ---- diff --git a/test/libyul/yulSyntaxTests/objects/object_name_with_all_special_chars.yul b/test/libyul/yulSyntaxTests/objects/object_name_with_all_special_chars.yul new file mode 100644 index 000000000..5719c8b4a --- /dev/null +++ b/test/libyul/yulSyntaxTests/objects/object_name_with_all_special_chars.yul @@ -0,0 +1,7 @@ +object "outer" { + code { + pop(datasize("a\\b\"c\nd\re\tf\x01g")) + } + data "a\\b\"c\nd\re\tf\x01g" hex"deadbeef" +} +// ---- diff --git a/test/libyul/yulSyntaxTests/objects/object_name_with_special_chars.yul b/test/libyul/yulSyntaxTests/objects/object_name_with_special_chars.yul new file mode 100644 index 000000000..f6c6882dd --- /dev/null +++ b/test/libyul/yulSyntaxTests/objects/object_name_with_special_chars.yul @@ -0,0 +1,4 @@ +object "3\"{code{}}e0003" { + code { {} } +} +// ---- From b5e2e78cf10dd3569f5577a663dc0044ee780ab3 Mon Sep 17 00:00:00 2001 From: blishko Date: Thu, 12 Mar 2026 10:59:15 +0100 Subject: [PATCH 1187/1340] SSA: Refactor shuffling helper `dupDeepSlotIfRequired` --- libyul/backends/evm/ssa/StackShuffler.cpp | 18 +++++ libyul/backends/evm/ssa/StackShuffler.h | 90 ++++++++--------------- 2 files changed, 49 insertions(+), 59 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.cpp b/libyul/backends/evm/ssa/StackShuffler.cpp index b42d2bb24..d1a85251a 100644 --- a/libyul/backends/evm/ssa/StackShuffler.cpp +++ b/libyul/backends/evm/ssa/StackShuffler.cpp @@ -159,6 +159,24 @@ bool State::isSourceCompatible(StackOffset const _sourceOffset1, StackOffset con m_stackData[_sourceOffset1.value] == m_stackData[_sourceOffset2.value]; } +bool State::isSafeToSwapWithTop(StackOffset const _offset) const +{ + auto const& top = m_stackData.back(); + yulAssert(_offset.value < size()); + auto const& slot = m_stackData[_offset.value]; + return !isArgsCompatible(_offset, _offset) && // the offset isn't already in the right position wrt args + !isArgsCompatible(StackOffset{size() - 1}, StackOffset{size() - 1}) && // the top isn't already in the right position wrt args + ( + !requiredInArgs(top) || // current top can go into tail, ie it's not required as arg or + countReachable(top) > 1 // there's more of it in reachable stack depth + ) && + ( + target().tailSize <= _offset.value || // sourceOffset not in tail + !requiredInTail(slot) || // we're in tail but sourceOffset not needed in tail + (countInTail(slot) > 1 && requiredInTail(slot)) // swapping source offset away from tail doesn't decrease tail correctness + ); +} + Target const& State::target() const { return m_target; diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 59b2bec6b..7ec54d461 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -85,6 +85,8 @@ class State bool targetArbitrary(StackOffset _targetOffset) const; /// Yields whether two slots on the current stack are same, respecting stack size limits bool isSourceCompatible(StackOffset _sourceOffset1, StackOffset _sourceOffset2) const; + /// Checks if swapping the current offset with top makes progress toward target + bool isSafeToSwapWithTop(StackOffset _offset) const; /// Shuffling target information Target const& target() const; @@ -314,74 +316,44 @@ class StackShuffler // no need to dup deep junk if (endangeredSlot.isJunk()) continue; - // check if we have more of the same slot further up in the stack bool const neededInArgs = _state.targetArgsCount(endangeredSlot) > _state.countInArgs(endangeredSlot); bool const needMore = _state.targetMinCount(endangeredSlot) > _state.count(endangeredSlot); - if (neededInArgs || needMore) - { - // if we ever need more of a slot then this can only happen if it is something we require - // in the arguments - yulAssert(_state.requiredInArgs(endangeredSlot)); - - auto const haveMoreAbove = [&] - { - for (StackOffset offset{sourceOffset.value + 1}; offset < _stack.size(); ++offset.value) - { - if (_stack[offset] == endangeredSlot) - return true; - } - return false; - }(); - - // if we have more of the same further above, just unconditionally skip this one - if (haveMoreAbove) - continue; + if (!neededInArgs && !needMore) + continue; + // if we ever need more of a slot then this can only happen if it is something we require in the arguments + yulAssert(_state.requiredInArgs(endangeredSlot)); + // if there's a shallower slot with the same info that is reachable, skip this one + std::optional depth = _stack.findSlotDepth(endangeredSlot); + yulAssert(depth); + bool const haveMoreAbove = *depth < _stack.offsetToDepth(sourceOffset); + if (haveMoreAbove) + continue; - if (_stack.dupReachable(sourceOffset)) + if (_stack.dupReachable(sourceOffset)) + { + // if we can safely swap the current stack top with the endangered slot, we do that instead of DUP + if (_state.isSafeToSwapWithTop(sourceOffset)) { - - // if we can safely swap the current stack top with the endangered slot, we do that instead of DUP - if ( - !_state.isArgsCompatible(sourceOffset, sourceOffset) && // the offset isn't already in the right position wrt args - !_state.isArgsCompatible(StackOffset{_stack.size() - 1}, StackOffset{_stack.size() - 1}) && // the top isn't already in the right position wrt args - ( - !_state.requiredInArgs(_stack.top()) || // current top can go into tail, ie it's not required as arg or - _state.countReachable(_stack.top()) > 1 // there's more of it in reachable stack depth - ) && - ( - _state.target().tailSize <= sourceOffset.value || // sourceOffset not in tail - !_state.requiredInTail(endangeredSlot) || // we're in tail but sourceOffset not needed in tail - (_state.countInTail(endangeredSlot) > 1 && _state.requiredInTail(endangeredSlot)) // swapping source offset away from tail doesn't decrease tail correctness - ) - ) - { - // top can go into the tail bit, swap it down - _stack.swap(sourceOffset); - return true; - } - else - { - // we need more of the slot that is about to go out of reach, dup it - _stack.dup(sourceOffset); - return true; - } + // top can go into the tail bit, swap it down + _stack.swap(sourceOffset); + return true; } else { - std::optional depth = _stack.findSlotDepth(_stack[sourceOffset]); - yulAssert(depth); - // if there's a shallower slot with the same info that is reachable, skip this one - if (*depth < _stack.offsetToDepth(sourceOffset)) - continue; - - // the slot we need something in the args region of is unreachable, try compressing the stack, - // first looking at the top - if (shrinkStack(_stack, _state)) - return true; - - yulAssert(false, fmt::format("Stack too deep, can't reach slot at depth {}", depth->value)); + // we need more of the slot that is about to go out of reach, dup it + _stack.dup(sourceOffset); + return true; } } + else + { + // the slot we need something in the args region of is unreachable, try compressing the stack, + // first looking at the top + if (shrinkStack(_stack, _state)) + return true; + + yulAssert(false, fmt::format("Stack too deep, can't reach slot at depth {}", depth->value)); + } } return false; } From 8a66e9f84aad4e0bb72900589b4f26b9ebe4bd4a Mon Sep 17 00:00:00 2001 From: blishko Date: Thu, 12 Mar 2026 11:04:58 +0100 Subject: [PATCH 1188/1340] SSA: Prefer swapping instead of shrinking followed by dupping Previously, if a slot is desirable to be dupped, but is out of reach, we would try to shrink the stack and then bringing it to reachable region. However, even if it is out-of-reach for dup, it might still be in reach for swap, so if it is safe to swap, we can do it directly. --- libyul/backends/evm/ssa/StackShuffler.h | 6 ++++++ .../ssa/stackShuffler/deep_argument_shrink.stack | 10 +++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 7ec54d461..3057fd3a3 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -347,6 +347,12 @@ class StackShuffler } else { + // even if it is not dup reachable, it still might be swappable + if (_stack.swapReachable(sourceOffset) && _state.isSafeToSwapWithTop(sourceOffset)) + { + _stack.swap(sourceOffset); + return true; + } // the slot we need something in the args region of is unreachable, try compressing the stack, // first looking at the top if (shrinkStack(_stack, _state)) diff --git a/test/libyul/ssa/stackShuffler/deep_argument_shrink.stack b/test/libyul/ssa/stackShuffler/deep_argument_shrink.stack index b7fdbcbaf..b7e2c582f 100644 --- a/test/libyul/ssa/stackShuffler/deep_argument_shrink.stack +++ b/test/libyul/ssa/stackShuffler/deep_argument_shrink.stack @@ -9,12 +9,8 @@ targetStackSize: 19 // (initial)| v12 * * * * * * * * * * * * v68 * phi111 v84 | v86 // SWAP3| v12 * * * * * * * * * * * * v68 v86 phi111 v84 | * // POP| v12 * * * * * * * * * * * * v68 v86 phi111 v84 -// SWAP2| v12 * * * * * * * * * * * * v68 v84 phi111 v86 -// SWAP4| v12 * * * * * * * * * * * v86 v68 v84 phi111 * -// POP| v12 * * * * * * * * * * * v86 v68 v84 phi111 -// SWAP15| phi111 * * * * * * * * * * * v86 v68 v84 v12 -// DUP4| phi111 * * * * * * * * * * * v86 v68 v84 v12 v86 -// DUP2| phi111 * * * * * * * * * * * v86 v68 v84 v12 v86 | v12 -// DUP2| phi111 * * * * * * * * * * * v86 v68 v84 v12 v86 | v12 v86 +// SWAP16| v84 * * * * * * * * * * * * v68 v86 phi111 v12 +// DUP1| v84 * * * * * * * * * * * * v68 v86 phi111 v12 | v12 +// DUP4| v84 * * * * * * * * * * * * v68 v86 phi111 v12 | v12 v86 // +----------------------------------------------------------------------------------------------------------------------- +-------------- // (target)| {v68, v84, phi111} | v12 v86 From 90eb849418b76779895e81e7f7c293dbdce97abd Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Thu, 12 Feb 2026 12:11:51 -0300 Subject: [PATCH 1189/1340] Refactor hardcoded reachable stack depth --- libevmasm/Assembly.cpp | 2 +- libevmasm/CommonSubexpressionEliminator.cpp | 18 +++++++++++------- libevmasm/CommonSubexpressionEliminator.h | 15 +++++++++++++-- liblangutil/EVMVersion.h | 2 ++ libsolidity/codegen/CompilerContext.cpp | 2 +- libsolidity/codegen/CompilerContext.h | 1 + libsolidity/codegen/CompilerUtils.cpp | 12 ++++++------ libsolidity/codegen/ContractCompiler.cpp | 6 +++--- libsolidity/codegen/ExpressionCompiler.cpp | 4 ++-- libsolidity/codegen/LValue.cpp | 4 ++-- libsolidity/interface/GasEstimator.cpp | 2 +- libyul/backends/evm/EVMCodeTransform.cpp | 12 +++++++----- libyul/backends/evm/EVMDialect.h | 2 +- libyul/optimiser/StackLimitEvader.cpp | 13 ++++++++++--- test/libevmasm/Optimiser.cpp | 8 ++++---- 15 files changed, 65 insertions(+), 38 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 3fe31771f..ef6c0bec9 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -951,7 +951,7 @@ std::map const& Assembly::optimiseInternal( while (iter != items.end()) { KnownState emptyState; - CommonSubexpressionEliminator eliminator{emptyState}; + CommonSubexpressionEliminator eliminator{emptyState, m_evmVersion}; auto orig = iter; iter = eliminator.feedItems(iter, items.end(), usesMSize); bool shouldReplace = false; diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index cb4eaebff..50aa3f009 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -62,7 +62,7 @@ std::vector CommonSubexpressionEliminator::getOptimizedItems() for (int height = minHeight; height <= m_state.stackHeight(); ++height) targetStackContents[height] = m_state.stackElement(height, langutil::DebugData::create()); - AssemblyItems items = CSECodeGenerator(m_state.expressionClasses(), m_storeOperations).generateCode( + AssemblyItems items = CSECodeGenerator(m_state.expressionClasses(), m_storeOperations, m_evmVersion).generateCode( m_initialState.sequenceNumber(), m_initialState.stackHeight(), initialStackContents, @@ -126,9 +126,11 @@ void CommonSubexpressionEliminator::optimizeBreakingItem() CSECodeGenerator::CSECodeGenerator( ExpressionClasses& _expressionClasses, - std::vector const& _storeOperations + std::vector const& _storeOperations, + langutil::EVMVersion _evmVersion ): - m_expressionClasses(_expressionClasses) + m_expressionClasses(_expressionClasses), + m_evmVersion(_evmVersion) { for (auto const& store: _storeOperations) m_storeOperations[std::make_pair(store.target, store.slot)].push_back(store); @@ -407,7 +409,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) m_stack.erase(m_stackHeight - static_cast(i)); } appendItem(*expr.item); - if (expr.item->type() != Operation || instructionInfo(expr.item->instruction(), EVMVersion()).ret == 1) + if (expr.item->type() != Operation || instructionInfo(expr.item->instruction(), m_evmVersion).ret == 1) { m_stack[m_stackHeight] = _c; m_classPositions[_c].insert(m_stackHeight); @@ -415,7 +417,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) else { assertThrow( - instructionInfo(expr.item->instruction(), EVMVersion()).ret == 0, + instructionInfo(expr.item->instruction(), m_evmVersion).ret == 0, OptimizerException, "Invalid number of return values." ); @@ -472,8 +474,9 @@ bool CSECodeGenerator::removeStackTopIfPossible() void CSECodeGenerator::appendDup(int _fromPosition, langutil::DebugData::ConstPtr _debugData) { assertThrow(_fromPosition != c_invalidPosition, OptimizerException, ""); + int reachableStackDepth = static_cast(m_evmVersion.reachableStackDepth()); int instructionNum = 1 + m_stackHeight - _fromPosition; - assertThrow(instructionNum <= 16, StackTooDeepException, util::stackTooDeepString); + assertThrow(instructionNum <= reachableStackDepth, StackTooDeepException, util::stackTooDeepString); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); appendItem(AssemblyItem(dupInstruction(static_cast(instructionNum)), std::move(_debugData))); m_stack[m_stackHeight] = m_stack[_fromPosition]; @@ -485,8 +488,9 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, langutil::DebugData assertThrow(_fromPosition != c_invalidPosition, OptimizerException, ""); if (_fromPosition == m_stackHeight) return; + int reachableStackDepth = static_cast(m_evmVersion.reachableStackDepth()); int instructionNum = m_stackHeight - _fromPosition; - assertThrow(instructionNum <= 16, StackTooDeepException, util::stackTooDeepString); + assertThrow(instructionNum <= reachableStackDepth, StackTooDeepException, util::stackTooDeepString); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); appendItem(AssemblyItem(swapInstruction(static_cast(instructionNum)), std::move(_debugData))); diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h index 3e963838a..e4b13593c 100644 --- a/libevmasm/CommonSubexpressionEliminator.h +++ b/libevmasm/CommonSubexpressionEliminator.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,11 @@ class CommonSubexpressionEliminator using Id = ExpressionClasses::Id; using StoreOperation = KnownState::StoreOperation; - explicit CommonSubexpressionEliminator(KnownState const& _state): m_initialState(_state), m_state(_state) {} + explicit CommonSubexpressionEliminator(KnownState const& _state, langutil::EVMVersion _evmVersion): + m_initialState(_state), + m_state(_state), + m_evmVersion(_evmVersion) + {} /// Feeds AssemblyItems into the eliminator and @returns the iterator pointing at the first /// item that must be fed into a new instance of the eliminator. @@ -93,6 +98,7 @@ class CommonSubexpressionEliminator /// The item that breaks the basic block, can be nullptr. /// It is usually appended to the block but can be optimized in some cases. AssemblyItem const* m_breakingItem = nullptr; + langutil::EVMVersion const m_evmVersion; }; /** @@ -108,7 +114,11 @@ class CSECodeGenerator /// Initializes the code generator with the given classes and store operations. /// The store operations have to be sorted by sequence number in ascending order. - CSECodeGenerator(ExpressionClasses& _expressionClasses, StoreOperations const& _storeOperations); + CSECodeGenerator( + ExpressionClasses& _expressionClasses, + StoreOperations const& _storeOperations, + langutil::EVMVersion _evmVersion + ); /// @returns the assembly items generated from the given requirements /// @param _initialSequenceNumber starting sequence number, do not generate sequenced operations @@ -169,6 +179,7 @@ class CSECodeGenerator /// The set of equivalence classes that should be present on the stack at the end. std::set m_finalClasses; std::map m_targetStack; + langutil::EVMVersion const m_evmVersion; }; template diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index d4b25e100..f72b71056 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -146,6 +147,7 @@ class EVMVersion bool hasMcopy() const { return *this >= cancun(); } bool supportsTransientStorage() const { return *this >= cancun(); } bool supportsEOF() const { return *this >= firstWithEOF(); } + constexpr size_t reachableStackDepth() const { return 16; } bool hasOpcode(evmasm::Instruction _opcode, std::optional _eofVersion) const; diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 4d53b9c23..82f5ea3dc 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -418,7 +418,7 @@ void CompilerContext::appendInlineAssembly( size_t stackDiff = static_cast(_assembly.stackHeight()) - startStackHeight + stackDepth; if (_context == yul::IdentifierContext::LValue) stackDiff -= 1; - if (stackDiff < 1 || stackDiff > 16) + if (stackDiff < 1 || stackDiff > reachableStackDepth()) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(nativeLocationOf(_identifier)) << diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 49a996c6c..72f611130 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -108,6 +108,7 @@ class CompilerContext void setStackOffset(int _offset) { m_asm->setDeposit(_offset); } void adjustStackOffset(int _adjustment) { m_asm->adjustDeposit(_adjustment); } unsigned stackHeight() const { solAssert(m_asm->deposit() >= 0, ""); return unsigned(m_asm->deposit()); } + size_t reachableStackDepth() const { return m_evmVersion.reachableStackDepth(); } bool isLocalVariable(Declaration const* _declaration) const; bool isStateVariable(Declaration const* _declaration) const { return m_stateVariables.count(_declaration) != 0; } diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 822d9d3da..c7c219cb2 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -474,7 +474,7 @@ void CompilerUtils::encodeToMemory( m_context << Instruction::DUP1 << u256(32) << Instruction::ADD; dynPointers++; assertThrow( - (argSize + dynPointers) < 16, + (argSize + dynPointers) < m_context.reachableStackDepth(), StackTooDeepError, util::stackTooDeepString ); @@ -535,7 +535,7 @@ void CompilerUtils::encodeToMemory( { // copy tail pointer (=mem_end - mem_start) to memory assertThrow( - (2 + dynPointers) <= 16, + (2 + dynPointers) <= m_context.reachableStackDepth(), StackTooDeepError, util::stackTooDeepString ); @@ -1423,7 +1423,7 @@ void CompilerUtils::moveToStackVariable(VariableDeclaration const& _variable) unsigned const size = _variable.annotation().type->sizeOnStack(); solAssert(stackPosition >= size, "Variable size and position mismatch."); // move variable starting from its top end in the stack - if (stackPosition - size + 1 > 16) + if (stackPosition - size + 1 > m_context.reachableStackDepth()) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_variable.location()) << @@ -1436,7 +1436,7 @@ void CompilerUtils::moveToStackVariable(VariableDeclaration const& _variable) void CompilerUtils::copyToStackTop(unsigned _stackDepth, unsigned _itemSize) { assertThrow( - _stackDepth <= 16, + _stackDepth <= m_context.reachableStackDepth(), StackTooDeepError, util::stackTooDeepString ); @@ -1462,7 +1462,7 @@ void CompilerUtils::moveIntoStack(unsigned _stackDepth, unsigned _itemSize) void CompilerUtils::rotateStackUp(unsigned _items) { assertThrow( - _items - 1 <= 16, + _items - 1 <= m_context.reachableStackDepth(), StackTooDeepError, util::stackTooDeepString ); @@ -1473,7 +1473,7 @@ void CompilerUtils::rotateStackUp(unsigned _items) void CompilerUtils::rotateStackDown(unsigned _items) { assertThrow( - _items - 1 <= 16, + _items - 1 <= m_context.reachableStackDepth(), StackTooDeepError, util::stackTooDeepString ); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index fc5ec2917..64b4e427d 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -672,7 +672,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function) for (size_t i = 0; i < c_returnValuesSize; ++i) stackLayout.push_back(static_cast(i)); - if (stackLayout.size() > 17) + if (stackLayout.size() > m_context.reachableStackDepth() + 1) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_function.location()) << @@ -842,7 +842,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) } else solAssert(variable->type()->sizeOnStack() == 1, ""); - if (stackDiff < 1 || stackDiff > 16) + if (stackDiff < 1 || stackDiff > m_context.reachableStackDepth()) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_inlineAssembly.location()) << @@ -916,7 +916,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) else solAssert(suffix.empty(), ""); - if (stackDiff > 16 || stackDiff < 1) + if (stackDiff > m_context.reachableStackDepth() || stackDiff < 1) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_inlineAssembly.location()) << diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index e7f8df859..dc46fa279 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -275,7 +275,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& retSizeOnStack = returnTypes.front()->sizeOnStack(); } solAssert(retSizeOnStack == utils().sizeOnStack(returnTypes), ""); - if (retSizeOnStack > 15) + if (retSizeOnStack + 1 > m_context.reachableStackDepth()) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_varDecl.location()) << @@ -357,7 +357,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) } if (lvalueSize > 0) { - if (itemSize + lvalueSize > 16) + if (itemSize + lvalueSize > m_context.reachableStackDepth()) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_assignment.location()) << diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index a1537f01f..e8f6ae61c 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -46,7 +46,7 @@ StackVariable::StackVariable(CompilerContext& _compilerContext, VariableDeclarat void StackVariable::retrieveValue(SourceLocation const& _location, bool) const { unsigned stackPos = m_context.baseToCurrentStackOffset(m_baseStackOffset); - if (stackPos + 1 > 16) //@todo correct this by fetching earlier or moving to memory + if (stackPos + 1 > m_context.reachableStackDepth()) //@todo correct this by fetching earlier or moving to memory BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_location) << @@ -60,7 +60,7 @@ void StackVariable::retrieveValue(SourceLocation const& _location, bool) const void StackVariable::storeValue(Type const&, SourceLocation const& _location, bool _move) const { unsigned stackDiff = m_context.baseToCurrentStackOffset(m_baseStackOffset) - m_size + 1; - if (stackDiff > 16) + if (stackDiff > m_context.reachableStackDepth()) BOOST_THROW_EXCEPTION( StackTooDeepError() << errinfo_sourceLocation(_location) << diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp index 4313fad7f..6ab4b87da 100644 --- a/libsolidity/interface/GasEstimator.cpp +++ b/libsolidity/interface/GasEstimator.cpp @@ -90,7 +90,7 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation( auto state = std::make_shared(); unsigned parametersSize = CompilerUtils::sizeOnStack(_function.parameters()); - if (parametersSize > 16) + if (parametersSize > m_evmVersion.reachableStackDepth()) return GasConsumption::infinite(); // Store an invalid return value on the stack, so that the path estimator breaks upon reaching diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index f77e4e047..83ec96ddc 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -179,7 +179,7 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl) bool foundUnusedSlot = false; for (auto it = m_unusedStackSlots.begin(); it != m_unusedStackSlots.end(); ++it) { - if (m_assembly.stackHeight() - *it > 17) + if (m_assembly.stackHeight() - *it > static_cast(m_dialect.reachableStackDepth() + 1)) continue; foundUnusedSlot = true; auto slot = static_cast(*it); @@ -454,16 +454,18 @@ void CodeTransform::operator()(FunctionDefinition const& _function) &std::get(virtualFunctionScope->identifiers.at(returnVariable.name)) )) = static_cast(n); - if (stackLayout.size() > 17) + size_t const reachableStackDepth = m_dialect.reachableStackDepth(); + if (stackLayout.size() > reachableStackDepth + 1) { + size_t const unreachableSlots = stackLayout.size() - (reachableStackDepth + 1); StackTooDeepError error( _function.name, YulName{}, - static_cast(stackLayout.size()) - 17, + static_cast(unreachableSlots), "The function " + _function.name.str() + " has " + - std::to_string(stackLayout.size() - 17) + + std::to_string(unreachableSlots) + " parameters or return variables too many to fit the stack size." ); stackError(std::move(error), m_assembly.stackHeight() - static_cast(_function.parameters.size())); @@ -777,7 +779,7 @@ size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulName _v yulAssert(m_context->variableStackHeights.count(&_var), ""); size_t heightDiff = static_cast(m_assembly.stackHeight()) - m_context->variableStackHeights[&_var]; yulAssert(heightDiff > (_forSwap ? 1 : 0), "Negative stack difference for variable."); - size_t limit = _forSwap ? 17 : 16; + size_t limit = m_dialect.reachableStackDepth() + (_forSwap ? 1 : 0); if (heightDiff > limit) { m_stackErrors.emplace_back( diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 9f5760089..fa92b1cf3 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -91,7 +91,7 @@ class EVMDialect: public Dialect langutil::EVMVersion evmVersion() const { return m_evmVersion; } std::optional eofVersion() const { return m_eofVersion; } - size_t reachableStackDepth() const { return m_eofVersion.has_value() ? 256 : 16; } + size_t reachableStackDepth() const { return m_eofVersion.has_value() ? 256 : m_evmVersion.reachableStackDepth(); } bool providesObjectAccess() const { return m_objectAccess; } diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index f70bc0c1d..91a9eb84f 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -78,12 +78,12 @@ struct MemoryOffsetAllocator if (FunctionDefinition const* functionDefinition = util::valueOrDefault(functionDefinitions, std::get(_function), nullptr, util::allow_copy)) if ( size_t totalArgCount = functionDefinition->returnVariables.size() + functionDefinition->parameters.size(); - totalArgCount > 16 + totalArgCount > reachableStackDepth ) for (NameWithDebugData const& var: ranges::concat_view( functionDefinition->parameters, functionDefinition->returnVariables - ) | ranges::views::take(totalArgCount - 16)) + ) | ranges::views::take(totalArgCount - reachableStackDepth)) slotAllocations[var.name] = requiredSlots++; // Assign slots for all variables that become unreachable in the function body, if the above did not @@ -105,6 +105,8 @@ struct MemoryOffsetAllocator std::map> const& callGraph; /// Maps the name of each user-defined function to its definition. std::map const& functionDefinitions; + /// Max stack slots reachable via DUP/SWAP for the current backend configuration. + size_t reachableStackDepth; /// Maps variable names to the memory slot the respective variable is assigned. std::map slotAllocations{}; @@ -228,7 +230,12 @@ void StackLimitEvader::run( std::map functionDefinitions = allFunctionDefinitions(_astRoot); - MemoryOffsetAllocator memoryOffsetAllocator{_unreachableVariables, callGraph.functionCalls, functionDefinitions}; + MemoryOffsetAllocator memoryOffsetAllocator{ + _unreachableVariables, + callGraph.functionCalls, + functionDefinitions, + evmDialect->reachableStackDepth() + }; uint64_t requiredSlots = memoryOffsetAllocator.run(); yulAssert(requiredSlots < (uint64_t(1) << 32) - 1, ""); diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 01e1f9ac6..2c9375183 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -72,7 +72,7 @@ namespace bool usesMsize = ranges::any_of(_input, [](AssemblyItem const& _i) { return _i == AssemblyItem{Instruction::MSIZE} || _i.type() == VerbatimBytecode; }); - evmasm::CommonSubexpressionEliminator cse(_state); + evmasm::CommonSubexpressionEliminator cse(_state, CommonOptions::get().evmVersion()); BOOST_REQUIRE(cse.feedItems(input.begin(), input.end(), usesMsize) == input.end()); AssemblyItems output = cse.getOptimizedItems(); @@ -107,7 +107,7 @@ namespace while (iter != _input.end()) { KnownState emptyState; - CommonSubexpressionEliminator eliminator{emptyState}; + CommonSubexpressionEliminator eliminator{emptyState, CommonOptions::get().evmVersion()}; auto orig = iter; iter = eliminator.feedItems(iter, _input.end(), usesMSize); bool shouldReplace = false; @@ -190,7 +190,7 @@ BOOST_AUTO_TEST_CASE(cse_assign_immutable_breaks) Instruction::ORIGIN }); - evmasm::CommonSubexpressionEliminator cse{evmasm::KnownState()}; + evmasm::CommonSubexpressionEliminator cse{evmasm::KnownState(), CommonOptions::get().evmVersion()}; // Make sure CSE breaks after AssignImmutable. BOOST_REQUIRE(cse.feedItems(input.begin(), input.end(), false) == input.begin() + 2); } @@ -198,7 +198,7 @@ BOOST_AUTO_TEST_CASE(cse_assign_immutable_breaks) BOOST_AUTO_TEST_CASE(cse_intermediate_swap) { evmasm::KnownState state; - evmasm::CommonSubexpressionEliminator cse(state); + evmasm::CommonSubexpressionEliminator cse(state, CommonOptions::get().evmVersion()); AssemblyItems input{ Instruction::SWAP1, Instruction::POP, Instruction::ADD, u256(0), Instruction::SWAP1, Instruction::SLOAD, Instruction::SWAP1, u256(100), Instruction::EXP, Instruction::SWAP1, From 699019225b39abf7c1eae07da2ba0c8a090373c9 Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Tue, 17 Feb 2026 04:10:46 +0100 Subject: [PATCH 1190/1340] Fix Foundry installation for external contributors --- .circleci/config.yml | 76 +++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1ca83b526..5c6298817 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -194,7 +194,7 @@ commands: parameters: version: type: string - default: "nightly" + default: "stable" install_path: type: string default: /home/circleci/bin @@ -204,41 +204,55 @@ commands: command: | FOUNDRY_REPO="foundry-rs/foundry" FOUNDRY_VERSION="<< parameters.version >>" - # Make authenticated requests when the Github token is available - if [[ -n "$GITHUB_READ_TOKEN" ]]; then - EXTRA_HEADERS=(--header 'Authorization: Bearer '"${GITHUB_READ_TOKEN}") + RELEASE_URL="https://github.com/${FOUNDRY_REPO}/releases/download/${FOUNDRY_VERSION}" + echo "export FOUNDRY_VERSION=${FOUNDRY_VERSION}" >> "$BASH_ENV" + echo "export RELEASE_URL=${RELEASE_URL}" >> "$BASH_ENV" + ATTESTATION_URL=$(curl --silent --location --fail "${RELEASE_URL}/foundry_${FOUNDRY_VERSION}_linux_amd64.attestation.txt") || { + echo "Failed to fetch attestation file" + exit 1 + } + ATTESTATION_JSON=$(curl --silent --location --fail --header "Accept: application/json" "${ATTESTATION_URL}") || { + echo "Failed to fetch attestation JSON" + exit 1 + } + RELEASE_SHA=$(echo "${ATTESTATION_JSON}" | jq --raw-output '.payload.attestation.sourceRepositoryDigest') + if [[ -z "$RELEASE_SHA" || "$RELEASE_SHA" == "null" ]]; then + echo "Failed to extract release SHA from attestation" + exit 1 fi - FOUNDRY_RELEASE_SHA=$(curl \ - --silent \ - --fail \ - --show-error \ - "${EXTRA_HEADERS[@]}" \ - "https://api.github.com/repos/${FOUNDRY_REPO}/git/refs/tags/${FOUNDRY_VERSION}" \ - | jq --raw-output .object.sha \ - ) - echo "export FOUNDRY_REPO=$FOUNDRY_REPO" >> "$BASH_ENV" - echo "export FOUNDRY_VERSION=$FOUNDRY_VERSION" >> "$BASH_ENV" - echo "export FOUNDRY_RELEASE_TAG='${FOUNDRY_VERSION}'" >> "$BASH_ENV" - # Save commit sha for caching - echo "$FOUNDRY_RELEASE_SHA" > /tmp/workspace/foundry-release-sha + echo "${RELEASE_SHA}" > /tmp/workspace/foundry-release-sha + # Extract forge checksum from the attestation + EXPECTED_FORGE_CHECKSUM=$(echo "${ATTESTATION_JSON}" | jq --raw-output '.payload.attestation.subjects[] | select(.subjectName=="forge") | .subjectDigest' | sed 's/sha256://') + if [[ -z "$EXPECTED_FORGE_CHECKSUM" || "$EXPECTED_FORGE_CHECKSUM" == "null" ]]; then + echo "Failed to extract forge checksum from attestation" + exit 1 + fi + echo "export EXPECTED_FORGE_CHECKSUM=${EXPECTED_FORGE_CHECKSUM}" >> "$BASH_ENV" - restore_cache: keys: - - foundry-<< parameters.version >>-{{ arch }}-{{ checksum "/tmp/workspace/foundry-release-sha" }} + - foundry-v1-<< parameters.version >>-{{ arch }}-{{ checksum "/tmp/workspace/foundry-release-sha" }} # WARNING! If you edit anything between here and save_cache, remember to invalidate the cache manually. - run: name: Install foundry command: | - ! forge --version 2> /dev/null - curl \ - --fail \ - --location \ - --output /tmp/foundry.tar.gz \ - "https://github.com/${FOUNDRY_REPO}/releases/download/${FOUNDRY_RELEASE_TAG}/foundry_${FOUNDRY_VERSION}_linux_amd64.tar.gz" - cd "<< parameters.install_path >>" - tar --extract --gzip --file /tmp/foundry.tar.gz --one-top-level - ln --symbolic --force foundry/{forge,anvil,cast,chisel} . + if forge --version 2> /dev/null; then + echo "Foundry already cached, skipping install" + else + curl --fail --location --output /tmp/foundry.tar.gz "${RELEASE_URL}/foundry_${FOUNDRY_VERSION}_linux_amd64.tar.gz" + cd "<< parameters.install_path >>" + tar --extract --gzip --file /tmp/foundry.tar.gz --one-top-level + # TODO: Use `gh attestation verify foundry/forge --owner foundry-rs` for signature verification. + # Current approach only verifies checksum without validating the signature. + # https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations/use-artifact-attestations#verifying-an-artifact-attestation-for-binaries + ACTUAL=$(sha256sum foundry/forge | cut --delimiter=' ' --fields=1) + if [[ "$EXPECTED_FORGE_CHECKSUM" != "$ACTUAL" ]]; then + echo "Checksum mismatch: expected $EXPECTED_FORGE_CHECKSUM, got $ACTUAL" + exit 1 + fi + ln --symbolic --force foundry/{forge,anvil,cast,chisel} . + fi - save_cache: - key: foundry-<< parameters.version >>-{{ arch }}-{{ checksum "/tmp/workspace/foundry-release-sha" }} + key: foundry-v1-<< parameters.version >>-{{ arch }}-{{ checksum "/tmp/workspace/foundry-release-sha" }} paths: - << parameters.install_path >> @@ -1646,9 +1660,6 @@ jobs: python2: type: boolean default: false - foundry_version: - type: string - default: "nightly" docker: - image: << parameters.image >> resource_class: << parameters.resource_class >> @@ -1662,8 +1673,7 @@ jobs: - checkout - attach_workspace: at: /tmp/workspace - - install_foundry: - version: << parameters.foundry_version >> + - install_foundry - run: name: Ensure pnpm is installed if npm is present command: | From 0b720134c4b2ede83dd544c9c4e364742ff97c07 Mon Sep 17 00:00:00 2001 From: Weixie Cui Date: Fri, 20 Mar 2026 21:26:36 +0800 Subject: [PATCH 1191/1340] fix shoulde be dup instuction not swap instruction --- libevmasm/GasMeter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index fde0819da..803fc825e 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -321,7 +321,7 @@ unsigned GasMeter::swapGas(size_t _depth, langutil::EVMVersion _evmVersion) unsigned GasMeter::dupGas(size_t _depth, langutil::EVMVersion _evmVersion) { if (_depth <= 16) - return runGas(evmasm::swapInstruction(static_cast(_depth)), _evmVersion); + return runGas(evmasm::dupInstruction(static_cast(_depth)), _evmVersion); auto gasCost = gasCostForTier(instructionInfo(evmasm::Instruction::DUPN, _evmVersion).gasPriceTier); solAssert(gasCost.has_value(), "Expected gas cost for DUPN to be defined."); return *gasCost; From 6e3ad1aea4b6c41ea2cdbddd99a58257f1e105d0 Mon Sep 17 00:00:00 2001 From: blishko Date: Sun, 22 Mar 2026 16:38:04 +0100 Subject: [PATCH 1192/1340] SSA: Add shuffler test This test captures a situation where we have a JUNK at the bottom of the source stack and we need to replace the JUNK with the same value that currently sits on top of the stack. All other slots in the stack must stay the same. This scenario demonstrates an inefficiency in the current implementation of the shuffler. For the given source and target stack, it produces a sequence of operations "SWAP3 + DUP4 + SWAP1 + POP" when shorter sequence is sufficient: "SWAP3 + POP + DUP3". --- .../replace_junk_with_top_value.stack | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack diff --git a/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack b/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack new file mode 100644 index 000000000..4cebfa222 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack @@ -0,0 +1,15 @@ +// we want to replace JUNK at the bottom of the stack with the top value, all other slots must be preserved exactly +initial: [JUNK, v2, v1, v0] +targetStackTop: [v0, v2, v1, v0] +targetStackTailSet: {} +targetStackSize: 4 +// ---- +// | 0 1 2 3 | 4 +// +---------------------------- +------- +// (initial)| * v2 v1 v0 +// SWAP3| v0 v2 v1 * +// DUP4| v0 v2 v1 * | v0 +// SWAP1| v0 v2 v1 v0 | * +// POP| v0 v2 v1 v0 +// +---------------------------- +------- +// (target)| v0 v2 v1 v0 | From 16381d32581d8668ef02a54aa11209a5e69977b3 Mon Sep 17 00:00:00 2001 From: blishko Date: Mon, 23 Mar 2026 09:51:11 +0100 Subject: [PATCH 1193/1340] SSA: Fix reachability check in stack shuffler In the method `allNecessarySlotsReachableOrFinal`, we want to check if arguments are in the right place or at least dup-reachable. Previously, in case the argument in target stack is not compatible with the same slot in current stack, the code would check if such a slot is at least reachable. However, it would use `swapReachable` check, which would return false for the top of the stack. However, for the purpose of this function, top slot should be considered reachable. This change improves shuffler on our test case that demonstrated the previous inefficiency. More importantly, it also improves code generation for the deposit and snark contracts. --- libyul/backends/evm/ssa/StackShuffler.h | 2 +- .../externalContracts/deposit_contract.sol | 12 ++++++------ .../semanticTests/externalContracts/snark.sol | 4 ++-- .../stackShuffler/replace_junk_with_top_value.stack | 5 ++--- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 3057fd3a3..e918c33cd 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -809,7 +809,7 @@ class StackShuffler } else { - if (!_stack.swapReachable(*depth)) + if (depth->value != 0 && !_stack.swapReachable(*depth)) return _stack.depthToOffset(*depth); } } diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index 82d307cd5..ce069d31f 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -185,8 +185,8 @@ contract DepositContract is IDepositContract, ERC165 { // gas legacy code: 1438800 // gas legacyOptimized: 848699 // gas legacyOptimized code: 878200 -// gas ssaCFGOptimized: 810764 -// gas ssaCFGOptimized code: 582000 +// gas ssaCFGOptimized: 810619 +// gas ssaCFGOptimized code: 581400 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # @@ -195,14 +195,14 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 -// gas ssaCFGOptimized: 110211 +// gas ssaCFGOptimized: 110115 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 -// gas ssaCFGOptimized: 110211 +// gas ssaCFGOptimized: 110115 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 @@ -210,7 +210,7 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 110201 +// gas ssaCFGOptimized: 110108 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 @@ -218,5 +218,5 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 110201 +// gas ssaCFGOptimized: 110108 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index 0e6108c0f..6d39096b9 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -297,10 +297,10 @@ contract Test { // gas irOptimized: 275229 // gas legacy: 293579 // gas legacyOptimized: 276313 -// gas ssaCFGOptimized: 275439 +// gas ssaCFGOptimized: 275420 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." // gas irOptimized: 818076 // gas legacy: 904397 // gas legacyOptimized: 816770 -// gas ssaCFGOptimized: 819542 +// gas ssaCFGOptimized: 819241 diff --git a/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack b/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack index 4cebfa222..8c8eb6285 100644 --- a/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack +++ b/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack @@ -7,9 +7,8 @@ targetStackSize: 4 // | 0 1 2 3 | 4 // +---------------------------- +------- // (initial)| * v2 v1 v0 -// SWAP3| v0 v2 v1 * -// DUP4| v0 v2 v1 * | v0 -// SWAP1| v0 v2 v1 v0 | * +// DUP1| * v2 v1 v0 | v0 +// SWAP4| v0 v2 v1 v0 | * // POP| v0 v2 v1 v0 // +---------------------------- +------- // (target)| v0 v2 v1 v0 | From 995499a10c0a24b503c04dd4f3ac60fdb075cfce Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 19 Mar 2026 11:52:50 +0100 Subject: [PATCH 1194/1340] Give operations in SSA CFGs stable IDs --- libyul/backends/evm/ssa/CodeTransform.cpp | 4 +-- libyul/backends/evm/ssa/LivenessAnalysis.cpp | 6 ++-- libyul/backends/evm/ssa/SSACFG.cpp | 3 +- libyul/backends/evm/ssa/SSACFG.h | 33 ++++++++++++++++++- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 14 ++++---- .../backends/evm/ssa/StackLayoutGenerator.cpp | 2 +- libyul/backends/evm/ssa/StackUtils.cpp | 4 +-- libyul/backends/evm/ssa/io/JSONExporter.cpp | 4 +-- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 2 +- 9 files changed, 54 insertions(+), 18 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index ea8325694..d5d161f4b 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -171,7 +171,7 @@ void CodeTransform::operator()(SSACFG::BlockId const _blockId) for (std::size_t operationIndex = 0; operationIndex < block.operations.size(); ++operationIndex) { - SSACFG::Operation const& operation = block.operations[operationIndex]; + SSACFG::Operation const& operation = m_cfg.operation(block.operations[operationIndex]); auto const& operationInLayout = blockLayout->operationIn[operationIndex]; // perform the operation @@ -373,7 +373,7 @@ void CodeTransform::operator()(SSACFG::BlockId const& _blockId, SSACFG::BasicBlo [](SSACFG::LiteralAssignment const&) { yulAssert(false, "Terminated block cannot end with a literal assignment."); } - }, block.operations.back().kind); + }, m_cfg.operation(block.operations.back()).kind); // To be sure just emit another INVALID - should be removed by optimizer. m_assembly.appendInstruction(evmasm::Instruction::INVALID); } diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp index 2e93a5f14..cf87a580b 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -243,8 +243,9 @@ void LivenessAnalysis::runDagDfs() // add value ids to the live set that are used in exit blocks live += blockExitValues(blockId); - for (auto const& op: block.operations | ranges::views::reverse) + for (auto const opId: block.operations | ranges::views::reverse) { + auto const& op = m_cfg.operation(opId); // remove variables defined at p from live live.eraseAll(op.outputs | ranges::views::filter(excludingLiteralsFilter()) | ranges::to); // add uses at p to live @@ -297,8 +298,9 @@ void LivenessAnalysis::fillOperationsLiveOut() auto live = m_liveOuts[blockId.value]; live += blockExitValues(blockId); auto rit = liveOuts.rbegin(); - for (auto const& op: operations | ranges::views::reverse) + for (auto const opId: operations | ranges::views::reverse) { + auto const& op = m_cfg.operation(opId); *rit = live; for (auto const& output: op.outputs | ranges::views::filter(excludingLiteralsFilter())) live.erase(output); diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 24cc77091..3935624d2 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -100,8 +100,9 @@ class SSACFGDotExporter: public io::DotExporterBase auto const& phiInfo = m_cfg.phiInfo(phi); _out << fmt::format("phi{} := {}\\l\\\n", phi.value(), formatPhi(m_cfg, phiInfo)); } - for (auto const& operation: block.operations) + for (auto const opId: block.operations) { + auto const& operation = m_cfg.operation(opId); std::string const label = std::visit(GenericVisitor{ [&](SSACFG::Call const& _call) { return _call.function.get().name.str(); diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index dcb0a2649..1f5c622d4 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -56,6 +56,13 @@ class SSACFG bool hasValue() const { return value != std::numeric_limits::max(); } auto operator<=>(BlockId const&) const = default; }; + struct OperationId + { + using ValueType = std::uint32_t; + ValueType value = std::numeric_limits::max(); + bool hasValue() const { return value != std::numeric_limits::max(); } + auto operator<=>(OperationId const&) const = default; + }; class ValueId { public: @@ -144,7 +151,7 @@ class SSACFG langutil::DebugData::ConstPtr debugData; std::set entries; std::set phis; - std::vector operations; + std::vector operations; std::variant exit = MainExit{}; template void forEachExit(Callable&& _callable) const @@ -188,8 +195,18 @@ class SSACFG BasicBlock const& block(BlockId _id) const { return m_blocks.at(_id.value); } size_t numBlocks() const { return m_blocks.size(); } + OperationId makeOperation(Operation _op) + { + OperationId id{static_cast(m_operations.size())}; + m_operations.emplace_back(std::move(_op)); + return id; + } + Operation& operation(OperationId _id) { return m_operations.at(_id.value); } + Operation const& operation(OperationId _id) const { return m_operations.at(_id.value); } + private: std::vector m_blocks; + std::vector m_operations; public: struct LiteralValue { langutil::DebugData::ConstPtr debugData; @@ -318,6 +335,20 @@ struct fmt::formatter } }; +template<> +struct fmt::formatter +{ + static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } + + template + auto format(solidity::yul::ssa::SSACFG::OperationId const& _opId, FormatContext& _ctx) const -> decltype(_ctx.out()) + { + if (!_opId.hasValue()) + return fmt::format_to(_ctx.out(), "empty"); + return fmt::format_to(_ctx.out(), "op{}", _opId.value); + } +}; + template<> struct fmt::formatter { diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index bc39c74fb..ce364ef10 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -129,8 +129,8 @@ SSACFG::ValueId SSACFGBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) if (usedInPhi) phiUses.push_back(blockPhi); } - for (auto& op: block.operations) - ranges::replace(op.inputs, _phi, same); + for (auto opId: block.operations) + ranges::replace(m_graph.operation(opId).inputs, _phi, same); std::visit(util::GenericVisitor{ [_phi, same](SSACFG::BasicBlock::FunctionReturn& _functionReturn) { ranges::replace(_functionReturn.returnValues,_phi, same); @@ -339,7 +339,7 @@ void SSACFGBuilder::operator()(Switch const& _switch) {*_case.value /* skip second argument */ } }); auto outputValue = m_graph.newVariable(m_currentBlock); - currentBlock().operations.emplace_back(SSACFG::Operation{ + auto opId = m_graph.makeOperation(SSACFG::Operation{ {outputValue}, SSACFG::BuiltinCall{ debugDataOf(_case), @@ -348,6 +348,7 @@ void SSACFGBuilder::operator()(Switch const& _switch) }, {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression} }); + currentBlock().operations.emplace_back(opId); return outputValue; }; @@ -534,8 +535,9 @@ void SSACFGBuilder::assign(std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const } }, _call.functionName); auto results = operation.outputs; - currentBlock().operations.emplace_back(std::move(operation)); + currentBlock().operations.emplace_back(m_graph.makeOperation(std::move(operation))); if (!canContinue) { currentBlock().exit = SSACFG::BasicBlock::Terminated{}; diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 78d9dbfec..82fdc5e2a 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -236,7 +236,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) blockLayout.operationIn.reserve(block.operations.size()); for (std::size_t operationIndex = 0; operationIndex < block.operations.size(); ++operationIndex) { - SSACFG::Operation const& operation = block.operations[operationIndex]; + SSACFG::Operation const& operation = m_cfg.operation(block.operations[operationIndex]); LivenessAnalysis::LivenessData opLiveOut = operationsLiveOut[operationIndex]; auto opLiveOutWithoutOutputs = opLiveOut; for (auto const& output: operation.outputs) diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index 7f7a79795..864315ccf 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -139,8 +139,8 @@ CallSites solidity::yul::ssa::gatherCallSites(SSACFG const& _cfg) } }); - for (auto const& operation: block.operations) - if (auto const* call = std::get_if(&operation.kind)) + for (auto const opId: block.operations) + if (auto const* call = std::get_if(&_cfg.operation(opId).kind)) if (call->canContinue) result.addCallSite(&call->call.get()); } diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index fdd400d94..a5119b2d3 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -123,8 +123,8 @@ Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const blockJson["instructions"].push_back(phiJson); } } - for (auto const& operation: block.operations) - blockJson["instructions"].push_back(toJson(blockJson, _cfg, operation)); + for (auto const opId: block.operations) + blockJson["instructions"].push_back(toJson(blockJson, _cfg, _cfg.operation(opId))); return blockJson; } diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index 0066e8fa2..4234be31c 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -74,7 +74,7 @@ class StackLayoutDotExporter: public io::DotExporterBase for (std::size_t i = 0; i < block.operations.size(); ++i) { - auto const& operation = block.operations[i]; + auto const& operation = m_cfg.operation(block.operations[i]); yulAssert(i < blockLayout->operationIn.size()); auto operationStack = blockLayout->operationIn[i]; From 6479b638b0579823cadc4ba0c26719f1c6f53fd5 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 19 Mar 2026 15:41:53 +0100 Subject: [PATCH 1195/1340] Extract SSA CFG ID types into SSACFGTypes.h --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/ssa/SSACFG.cpp | 2 +- libyul/backends/evm/ssa/SSACFG.h | 112 +------------------ libyul/backends/evm/ssa/SSACFGTypes.h | 149 ++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 108 deletions(-) create mode 100644 libyul/backends/evm/ssa/SSACFGTypes.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 87cf8aaa4..048da92b5 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -90,6 +90,7 @@ add_library(yul backends/evm/ssa/SSACFG.h backends/evm/ssa/SSACFGBuilder.cpp backends/evm/ssa/SSACFGBuilder.h + backends/evm/ssa/SSACFGTypes.h backends/evm/ssa/Stack.cpp backends/evm/ssa/Stack.h backends/evm/ssa/StackLayout.h diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 3935624d2..08f5f9453 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -156,7 +156,7 @@ class SSACFGDotExporter: public io::DotExporterBase } -std::string SSACFG::ValueId::str(SSACFG const& _cfg) const +std::string ValueId::str(SSACFG const& _cfg) const { if (!hasValue()) return "INVALID"; diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 1f5c622d4..10ee92ce4 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -21,6 +21,8 @@ #pragma once +#include + #include #include #include @@ -49,60 +51,9 @@ class SSACFG SSACFG& operator=(SSACFG&&) = delete; ~SSACFG() = default; - struct BlockId - { - using ValueType = std::uint32_t; - ValueType value = std::numeric_limits::max(); - bool hasValue() const { return value != std::numeric_limits::max(); } - auto operator<=>(BlockId const&) const = default; - }; - struct OperationId - { - using ValueType = std::uint32_t; - ValueType value = std::numeric_limits::max(); - bool hasValue() const { return value != std::numeric_limits::max(); } - auto operator<=>(OperationId const&) const = default; - }; - class ValueId - { - public: - enum class Kind: std::uint8_t - { - Literal, - Variable, - Phi, - Unreachable - }; - using ValueType = std::uint32_t; - - constexpr ValueId() = default; - constexpr ValueId(ValueType const _value, Kind const _kind): m_value(_value), m_kind(_kind) {} - constexpr ValueId(ValueId const&) = default; - constexpr ValueId(ValueId&&) = default; - constexpr ValueId& operator=(ValueId const&) = default; - constexpr ValueId& operator=(ValueId&&) = default; - - static ValueId constexpr makeLiteral(ValueType const& _value) { return ValueId{_value, Kind::Literal}; } - static ValueId constexpr makeVariable(ValueType const& _value) { return ValueId{_value, Kind::Variable}; } - static ValueId constexpr makePhi(ValueType const& _value) { return ValueId{_value, Kind::Phi}; } - static ValueId constexpr makeUnreachable() { return ValueId{0u, Kind::Unreachable}; } - - bool constexpr isLiteral() const noexcept { return m_kind == Kind::Literal; } - bool constexpr isVariable() const noexcept { return m_kind == Kind::Variable; } - bool constexpr isPhi() const noexcept { return m_kind == Kind::Phi; } - bool constexpr isUnreachable() const noexcept { return m_kind == Kind::Unreachable; } - - bool constexpr hasValue() const { return m_value != std::numeric_limits::max(); } - ValueType constexpr value() const noexcept { return m_value; } - Kind constexpr kind() const noexcept { return m_kind; } - std::string str(SSACFG const& _cfg) const; - - auto operator<=>(ValueId const&) const = default; - - private: - ValueType m_value{std::numeric_limits::max()}; - Kind m_kind{Kind::Unreachable}; - }; + using BlockId = ssa::BlockId; + using OperationId = ssa::OperationId; + using ValueId = ssa::ValueId; struct BuiltinCall { @@ -320,56 +271,3 @@ class SSACFG }; } - -template<> -struct fmt::formatter -{ - static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } - - template - auto format(solidity::yul::ssa::SSACFG::BlockId const& _blockId, FormatContext& _ctx) const -> decltype(_ctx.out()) - { - if (!_blockId.hasValue()) - return fmt::format_to(_ctx.out(), "empty"); - return fmt::format_to(_ctx.out(), "{}", _blockId.value); - } -}; - -template<> -struct fmt::formatter -{ - static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } - - template - auto format(solidity::yul::ssa::SSACFG::OperationId const& _opId, FormatContext& _ctx) const -> decltype(_ctx.out()) - { - if (!_opId.hasValue()) - return fmt::format_to(_ctx.out(), "empty"); - return fmt::format_to(_ctx.out(), "op{}", _opId.value); - } -}; - -template<> -struct fmt::formatter -{ - static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } - - template - auto format(solidity::yul::ssa::SSACFG::ValueId const& _valueId, FormatContext& _ctx) const -> decltype(_ctx.out()) - { - if (!_valueId.hasValue()) - return fmt::format_to(_ctx.out(), "empty"); - switch (_valueId.kind()) - { - case solidity::yul::ssa::SSACFG::ValueId::Kind::Literal: - return fmt::format_to(_ctx.out(), "lit{}", _valueId.value()); - case solidity::yul::ssa::SSACFG::ValueId::Kind::Variable: - return fmt::format_to(_ctx.out(), "v{}", _valueId.value()); - case solidity::yul::ssa::SSACFG::ValueId::Kind::Phi: - return fmt::format_to(_ctx.out(), "phi{}", _valueId.value()); - case solidity::yul::ssa::SSACFG::ValueId::Kind::Unreachable: - return fmt::format_to(_ctx.out(), "unreachable"); - } - solidity::util::unreachable(); - } -}; diff --git a/libyul/backends/evm/ssa/SSACFGTypes.h b/libyul/backends/evm/ssa/SSACFGTypes.h new file mode 100644 index 000000000..a2dde80d1 --- /dev/null +++ b/libyul/backends/evm/ssa/SSACFGTypes.h @@ -0,0 +1,149 @@ +/* + 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 +/** + * Lightweight ID types used throughout the SSA CFG. + */ + +#pragma once + +#include + +#include + +#include +#include +#include + +namespace solidity::yul::ssa +{ + +class SSACFG; + +struct BlockId +{ + using ValueType = std::uint32_t; + ValueType value = std::numeric_limits::max(); + bool hasValue() const { return value != std::numeric_limits::max(); } + auto operator<=>(BlockId const&) const = default; +}; + +struct OperationId +{ + using ValueType = std::uint32_t; + ValueType value = std::numeric_limits::max(); + bool hasValue() const { return value != std::numeric_limits::max(); } + auto operator<=>(OperationId const&) const = default; +}; + +class ValueId +{ +public: + enum class Kind: std::uint8_t + { + Literal, + Variable, + Phi, + Unreachable + }; + using ValueType = std::uint32_t; + + constexpr ValueId() = default; + constexpr ValueId(ValueType const _value, Kind const _kind): m_value(_value), m_kind(_kind) {} + constexpr ValueId(ValueId const&) = default; + constexpr ValueId(ValueId&&) = default; + constexpr ValueId& operator=(ValueId const&) = default; + constexpr ValueId& operator=(ValueId&&) = default; + + static ValueId constexpr makeLiteral(ValueType const& _value) { return ValueId{_value, Kind::Literal}; } + static ValueId constexpr makeVariable(ValueType const& _value) { return ValueId{_value, Kind::Variable}; } + static ValueId constexpr makePhi(ValueType const& _value) { return ValueId{_value, Kind::Phi}; } + static ValueId constexpr makeUnreachable() { return ValueId{0u, Kind::Unreachable}; } + + bool constexpr isLiteral() const noexcept { return m_kind == Kind::Literal; } + bool constexpr isVariable() const noexcept { return m_kind == Kind::Variable; } + bool constexpr isPhi() const noexcept { return m_kind == Kind::Phi; } + bool constexpr isUnreachable() const noexcept { return m_kind == Kind::Unreachable; } + + bool constexpr hasValue() const { return m_value != std::numeric_limits::max(); } + ValueType constexpr value() const noexcept { return m_value; } + Kind constexpr kind() const noexcept { return m_kind; } + + /// Returns a human-readable string representation. Requires the full SSACFG for literal values. + std::string str(SSACFG const& _cfg) const; + + auto operator<=>(ValueId const&) const = default; + +private: + ValueType m_value{std::numeric_limits::max()}; + Kind m_kind{Kind::Unreachable}; +}; + +} + +template<> +struct fmt::formatter +{ + static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } + + template + auto format(solidity::yul::ssa::BlockId const& _blockId, FormatContext& _ctx) const -> decltype(_ctx.out()) + { + if (!_blockId.hasValue()) + return fmt::format_to(_ctx.out(), "empty"); + return fmt::format_to(_ctx.out(), "{}", _blockId.value); + } +}; + +template<> +struct fmt::formatter +{ + static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } + + template + auto format(solidity::yul::ssa::OperationId const& _opId, FormatContext& _ctx) const -> decltype(_ctx.out()) + { + if (!_opId.hasValue()) + return fmt::format_to(_ctx.out(), "empty"); + return fmt::format_to(_ctx.out(), "op{}", _opId.value); + } +}; + +template<> +struct fmt::formatter +{ + static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } + + template + auto format(solidity::yul::ssa::ValueId const& _valueId, FormatContext& _ctx) const -> decltype(_ctx.out()) + { + if (!_valueId.hasValue()) + return fmt::format_to(_ctx.out(), "empty"); + switch (_valueId.kind()) + { + case solidity::yul::ssa::ValueId::Kind::Literal: + return fmt::format_to(_ctx.out(), "lit{}", _valueId.value()); + case solidity::yul::ssa::ValueId::Kind::Variable: + return fmt::format_to(_ctx.out(), "v{}", _valueId.value()); + case solidity::yul::ssa::ValueId::Kind::Phi: + return fmt::format_to(_ctx.out(), "phi{}", _valueId.value()); + case solidity::yul::ssa::ValueId::Kind::Unreachable: + return fmt::format_to(_ctx.out(), "unreachable"); + } + solidity::util::unreachable(); + } +}; From 082a19291cf6c51713ae338c56c1b55dafc1803f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 19 Mar 2026 15:44:44 +0100 Subject: [PATCH 1196/1340] Extract debug data from SSA CFG nodes into a separate side structure --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/ssa/CodeTransform.cpp | 24 +++- libyul/backends/evm/ssa/CodeTransform.h | 2 +- libyul/backends/evm/ssa/SSACFG.h | 54 +++++---- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 72 +++++++----- libyul/backends/evm/ssa/SSACFGBuilder.h | 11 +- libyul/backends/evm/ssa/SSACFGDebugInfo.h | 133 ++++++++++++++++++++++ 7 files changed, 232 insertions(+), 65 deletions(-) create mode 100644 libyul/backends/evm/ssa/SSACFGDebugInfo.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 048da92b5..898f67946 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -90,6 +90,7 @@ add_library(yul backends/evm/ssa/SSACFG.h backends/evm/ssa/SSACFGBuilder.cpp backends/evm/ssa/SSACFGBuilder.h + backends/evm/ssa/SSACFGDebugInfo.h backends/evm/ssa/SSACFGTypes.h backends/evm/ssa/Stack.cpp backends/evm/ssa/Stack.h diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index d5d161f4b..73a676330 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -87,12 +87,17 @@ CodeTransform::FunctionLabels CodeTransform::registerFunctionLabels( if (!_function) continue; bool nameAlreadySeen = !assignedFunctionNames.insert(_function->name).second; + auto const sourceID = [&]() -> std::optional { + if (_functionGraph->debugInfo && _functionGraph->debugInfo->graphDebugData) + return _functionGraph->debugInfo->graphDebugData->astID; + return std::nullopt; + }(); functionLabels[_function] = !nameAlreadySeen ? _assembly.namedLabel( _function->name.str(), _functionGraph->arguments.size(), _functionGraph->returns.size(), - _functionGraph->debugData ? _functionGraph->debugData->astID : std::nullopt + sourceID ) : _assembly.newLabelId(); } @@ -171,11 +176,10 @@ void CodeTransform::operator()(SSACFG::BlockId const _blockId) for (std::size_t operationIndex = 0; operationIndex < block.operations.size(); ++operationIndex) { - SSACFG::Operation const& operation = m_cfg.operation(block.operations[operationIndex]); auto const& operationInLayout = blockLayout->operationIn[operationIndex]; // perform the operation - (*this)(operation, operationInLayout); + (*this)(block.operations[operationIndex], operationInLayout); } // Shuffle to the block's exit layout before dispatching the exit. @@ -187,8 +191,9 @@ void CodeTransform::operator()(SSACFG::BlockId const _blockId) std::visit(util::GenericVisitor{ [this, &_blockId](auto const& exit) { (*this)(_blockId, exit); } }, block.exit); } -void CodeTransform::operator()(SSACFG::Operation const& _operation, StackData const& _operationInputLayout) +void CodeTransform::operator()(SSACFG::OperationId _opId, StackData const& _operationInputLayout) { + SSACFG::Operation const& _operation = m_cfg.operation(_opId); bool const hasReturnLabel = std::holds_alternative(_operation.kind) && std::get(_operation.kind).canContinue; @@ -235,10 +240,17 @@ void CodeTransform::operator()(SSACFG::Operation const& _operation, StackData co // height of the stack sans function return label and operation inputs std::size_t const baseHeight = m_stack.size() - _operation.inputs.size() - (hasReturnLabel ? 1 : 0); + auto const opOriginLocation = [&]() -> langutil::SourceLocation { + if (m_cfg.debugInfo) + if (auto const& dbg = m_cfg.debugInfo->operationDebugData(_opId)) + return dbg->originLocation; + return {}; + }(); + // generate code for the operation std::visit(util::GenericVisitor{ [&](SSACFG::BuiltinCall const& _builtin) { - m_assembly.setSourceLocation(originLocationOf(_builtin)); + m_assembly.setSourceLocation(opOriginLocation); static_cast(_builtin.builtin.get()).generateCode( _builtin.call, m_assembly, @@ -249,7 +261,7 @@ void CodeTransform::operator()(SSACFG::Operation const& _operation, StackData co auto const* returnLabel = util::valueOrNullptr(m_returnLabels, &_call.call.get()); // check that if we have a return label, the call can continue yulAssert(!!returnLabel == _call.canContinue); - m_assembly.setSourceLocation(originLocationOf(_call)); + m_assembly.setSourceLocation(opOriginLocation); m_assembly.appendJumpTo( m_functionLabels.at(&_call.function.get()), static_cast(_call.function.get().numReturns - _call.function.get().numArguments) - (_call.canContinue ? 1 : 0), diff --git a/libyul/backends/evm/ssa/CodeTransform.h b/libyul/backends/evm/ssa/CodeTransform.h index 8898b41b5..48d74ffd6 100644 --- a/libyul/backends/evm/ssa/CodeTransform.h +++ b/libyul/backends/evm/ssa/CodeTransform.h @@ -118,7 +118,7 @@ class CodeTransform ControlFlow::FunctionGraphID _graphID); void operator()(SSACFG::BlockId _blockId); - void operator()(SSACFG::Operation const& _operation, StackData const& _operationInputLayout); + void operator()(SSACFG::OperationId _opId, StackData const& _operationInputLayout); void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::MainExit const& _mainExit); void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::ConditionalJump const& _conditionalJump); void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::Jump const& _jump); diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 10ee92ce4..0404248f1 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -21,6 +21,7 @@ #pragma once +#include #include #include @@ -44,7 +45,12 @@ class LivenessAnalysis; class SSACFG { public: - SSACFG() = default; + using DebugInfo = SSACFGDebugInfo; + + explicit SSACFG(std::unique_ptr _debugInfo = std::make_unique()): + debugInfo(std::move(_debugInfo)) + {} + SSACFG(SSACFG const&) = delete; SSACFG(SSACFG&&) = delete; SSACFG& operator=(SSACFG const&) = delete; @@ -57,21 +63,16 @@ class SSACFG struct BuiltinCall { - langutil::DebugData::ConstPtr debugData; std::reference_wrapper builtin; std::reference_wrapper call; }; struct Call { - langutil::DebugData::ConstPtr debugData; std::reference_wrapper function; std::reference_wrapper call; bool canContinue; }; - struct LiteralAssignment - { - langutil::DebugData::ConstPtr debugData; - }; + struct LiteralAssignment {}; struct Operation { std::vector outputs{}; @@ -83,23 +84,19 @@ class SSACFG struct MainExit {}; struct ConditionalJump { - langutil::DebugData::ConstPtr debugData{}; ValueId condition; BlockId nonZero; BlockId zero; }; struct Jump { - langutil::DebugData::ConstPtr debugData{}; BlockId target; }; struct FunctionReturn { - langutil::DebugData::ConstPtr debugData{}; std::vector returnValues; }; struct Terminated {}; - langutil::DebugData::ConstPtr debugData; std::set entries; std::set phis; std::vector operations; @@ -136,20 +133,25 @@ class SSACFG return std::holds_alternative(exit); } }; + BlockId makeBlock(langutil::DebugData::ConstPtr _debugData) { BlockId blockId { static_cast(m_blocks.size()) }; - m_blocks.emplace_back(BasicBlock{std::move(_debugData), {}, {}, {}, BasicBlock::Terminated{}}); + m_blocks.emplace_back(BasicBlock{{}, {}, {}, BasicBlock::Terminated{}}); + if (debugInfo) + debugInfo->setBlockDebugData(blockId, std::move(_debugData)); return blockId; } BasicBlock& block(BlockId _id) { return m_blocks.at(_id.value); } BasicBlock const& block(BlockId _id) const { return m_blocks.at(_id.value); } size_t numBlocks() const { return m_blocks.size(); } - OperationId makeOperation(Operation _op) + OperationId makeOperation(Operation _op, langutil::DebugData::ConstPtr _debugData = {}) { OperationId id{static_cast(m_operations.size())}; m_operations.emplace_back(std::move(_op)); + if (debugInfo && _debugData) + debugInfo->setOperationDebugData(id, std::move(_debugData)); return id; } Operation& operation(OperationId _id) { return m_operations.at(_id.value); } @@ -160,34 +162,35 @@ class SSACFG std::vector m_operations; public: struct LiteralValue { - langutil::DebugData::ConstPtr debugData; u256 value; }; struct VariableValue { - langutil::DebugData::ConstPtr debugData; BlockId definingBlock; }; struct PhiValue { - langutil::DebugData::ConstPtr debugData; BlockId block; std::vector arguments; }; struct UnreachableValue {}; ValueId newPhi(BlockId const _definingBlock) { - auto const& block = m_blocks.at(_definingBlock.value); - m_phis.emplace_back(PhiValue{debugDataOf(block), _definingBlock, std::vector{}}); + m_phis.emplace_back(PhiValue{_definingBlock, std::vector{}}); auto const value = m_phis.size() - 1; yulAssert(value < std::numeric_limits::max()); - return ValueId::makePhi(static_cast(value)); + auto const id = ValueId::makePhi(static_cast(value)); + if (debugInfo) + debugInfo->setValueDebugData(id, debugInfo->blockDebugData(_definingBlock)); + return id; } ValueId newVariable(BlockId const _definingBlock) { - auto const& block = m_blocks.at(_definingBlock.value); - m_variables.emplace_back(VariableValue{debugDataOf(block), _definingBlock}); + m_variables.emplace_back(VariableValue{_definingBlock}); auto const value = m_variables.size() - 1; yulAssert(value < std::numeric_limits::max()); - return ValueId::makeVariable(static_cast(value)); + auto const id = ValueId::makeVariable(static_cast(value)); + if (debugInfo) + debugInfo->setValueDebugData(id, debugInfo->blockDebugData(_definingBlock)); + return id; } ValueId unreachableValue() @@ -207,11 +210,12 @@ class SSACFG return valueId; } - - m_literals.emplace_back(LiteralValue{std::move(_debugData), std::move(_value)}); + m_literals.emplace_back(LiteralValue{std::move(_value)}); auto const value = m_literals.size() - 1; yulAssert(value < std::numeric_limits::max()); auto const literalId = ValueId::makeLiteral(static_cast(value)); + if (debugInfo) + debugInfo->setValueDebugData(literalId, std::move(_debugData)); m_literalMapping.emplace(_value, literalId); return literalId; } @@ -258,7 +262,7 @@ class SSACFG std::vector m_variables; std::optional m_unreachableValue; public: - langutil::DebugData::ConstPtr debugData; + std::unique_ptr debugInfo; BlockId entry = BlockId{0}; std::set exits; Scope::Function const* function = nullptr; diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index ce364ef10..50523916d 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -51,14 +51,16 @@ SSACFGBuilder::SSACFGBuilder( AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, Dialect const& _dialect, - bool _keepLiteralAssignments + bool _keepLiteralAssignments, + bool _generateDebugInfo ): m_controlFlow(_controlFlow), m_graph(_graph), m_info(_analysisInfo), m_sideEffects(_sideEffects), m_dialect(_dialect), - m_keepLiteralAssignments(_keepLiteralAssignments) + m_keepLiteralAssignments(_keepLiteralAssignments), + m_generateDebugInfo(_generateDebugInfo) { } @@ -66,16 +68,19 @@ std::unique_ptr SSACFGBuilder::build( AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, Block const& _block, - bool _keepLiteralAssignments + bool _keepLiteralAssignments, + bool _generateDebugInfo ) { ControlFlowSideEffectsCollector sideEffects(_dialect, _block); auto controlFlow = std::make_unique(); - controlFlow->functionGraphs.emplace_back(std::make_unique()); + controlFlow->functionGraphs.emplace_back(std::make_unique( + _generateDebugInfo ? std::make_unique() : nullptr + )); controlFlow->functionGraphMapping.emplace_back(nullptr, controlFlow->functionGraphs.back().get()); SSACFG& mainGraph = *controlFlow->functionGraphs.back(); - SSACFGBuilder builder(*controlFlow, mainGraph, _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments); + SSACFGBuilder builder(*controlFlow, mainGraph, _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments, _generateDebugInfo); builder.m_currentBlock = mainGraph.makeBlock(debugDataOf(_block)); builder.sealBlock(builder.m_currentBlock); builder(_block); @@ -203,7 +208,9 @@ void SSACFGBuilder::buildFunctionGraph( FunctionDefinition const* _functionDefinition ) { - m_controlFlow.functionGraphs.emplace_back(std::make_unique()); + m_controlFlow.functionGraphs.emplace_back(std::make_unique( + m_generateDebugInfo ? std::make_unique() : nullptr + )); auto& cfg = *m_controlFlow.functionGraphs.back(); m_controlFlow.functionGraphMapping.emplace_back(_function, &cfg); @@ -221,13 +228,14 @@ void SSACFGBuilder::buildFunctionGraph( return std::cref(std::get(virtualFunctionScope->identifiers.at(_param.name))); }) | ranges::to; - cfg.debugData = _functionDefinition->debugData; + if (cfg.debugInfo) + cfg.debugInfo->graphDebugData = _functionDefinition->debugData; cfg.function = _function; cfg.canContinue = m_sideEffects.functionSideEffects().at(_functionDefinition).canContinue; cfg.arguments = arguments; cfg.returns = returns; - SSACFGBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_keepLiteralAssignments); + SSACFGBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_keepLiteralAssignments, m_generateDebugInfo); builder.m_currentBlock = cfg.entry; builder.m_functionDefinitions = m_functionDefinitions; for (auto&& [var, varId]: cfg.arguments) @@ -288,7 +296,7 @@ void SSACFGBuilder::operator()(If const& _if) { auto condition = std::visit(*this, *_if.condition); auto ifBranch = m_graph.makeBlock(debugDataOf(_if.body)); - auto afterIf = m_graph.makeBlock(debugDataOf(currentBlock())); + auto afterIf = m_graph.makeBlock(currentBlockDebugData()); conditionalJump( debugDataOf(_if), condition, @@ -342,17 +350,16 @@ void SSACFGBuilder::operator()(Switch const& _switch) auto opId = m_graph.makeOperation(SSACFG::Operation{ {outputValue}, SSACFG::BuiltinCall{ - debugDataOf(_case), m_dialect.builtin(*equalityBuiltinHandle), ghostCall }, {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression} - }); + }, debugDataOf(_case)); currentBlock().operations.emplace_back(opId); return outputValue; }; - auto afterSwitch = m_graph.makeBlock(debugDataOf(currentBlock())); + auto afterSwitch = m_graph.makeBlock(currentBlockDebugData()); yulAssert(!_switch.cases.empty(), ""); for (auto const& switchCase: _switch.cases | ranges::views::drop_last(1)) { @@ -384,7 +391,7 @@ void SSACFGBuilder::operator()(ForLoop const& _loop) { ScopedSaveAndRestore scopeRestore(m_scope, m_info.scopes.at(&_loop.pre).get()); (*this)(_loop.pre); - auto preLoopDebugData = debugDataOf(currentBlock()); + auto preLoopDebugData = currentBlockDebugData(); std::optional constantCondition; if (auto const* literalCondition = std::get_if(_loop.condition.get())) @@ -446,31 +453,32 @@ void SSACFGBuilder::operator()(ForLoop const& _loop) void SSACFGBuilder::operator()(Break const& _break) { yulAssert(!m_forLoopInfo.empty()); - auto currentBlockDebugData = debugDataOf(currentBlock()); + auto savedBlockDebugData = currentBlockDebugData(); jump(debugDataOf(_break), m_forLoopInfo.top().breakBlock); - m_currentBlock = m_graph.makeBlock(currentBlockDebugData); + m_currentBlock = m_graph.makeBlock(savedBlockDebugData); sealBlock(m_currentBlock); } void SSACFGBuilder::operator()(Continue const& _continue) { yulAssert(!m_forLoopInfo.empty()); - auto currentBlockDebugData = debugDataOf(currentBlock()); + auto const savedBlockDebugData = currentBlockDebugData(); jump(debugDataOf(_continue), m_forLoopInfo.top().continueBlock); - m_currentBlock = m_graph.makeBlock(currentBlockDebugData); + m_currentBlock = m_graph.makeBlock(savedBlockDebugData); sealBlock(m_currentBlock); } void SSACFGBuilder::operator()(Leave const& _leaveStatement) { - auto currentBlockDebugData = debugDataOf(currentBlock()); + auto const savedBlockDebugData = currentBlockDebugData(); + if (m_graph.debugInfo) + m_graph.debugInfo->setExitDebugData(m_currentBlock, debugDataOf(_leaveStatement)); currentBlock().exit = SSACFG::BasicBlock::FunctionReturn{ - debugDataOf(_leaveStatement), m_graph.returns | ranges::views::transform([&](auto _var) { return readVariable(_var, m_currentBlock); }) | ranges::to }; - m_currentBlock = m_graph.makeBlock(currentBlockDebugData); + m_currentBlock = m_graph.makeBlock(savedBlockDebugData); sealBlock(m_currentBlock); } @@ -512,7 +520,7 @@ SSACFG::ValueId SSACFGBuilder::operator()(Identifier const& _identifier) SSACFG::ValueId SSACFGBuilder::operator()(Literal const& _literal) { - return m_graph.newLiteral(debugDataOf(currentBlock()), _literal.value.value()); + return m_graph.newLiteral(currentBlockDebugData(), _literal.value.value()); } void SSACFGBuilder::assign(std::vector> _variables, Expression const* _expression) @@ -552,7 +560,7 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const [&](BuiltinName const& _builtinName) { auto const& builtin = m_dialect.builtin(_builtinName.handle); - SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData, builtin, _call}, {}}; + SSACFG::Operation result{{}, SSACFG::BuiltinCall{builtin, _call}, {}}; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) if (!builtin.literalArgument(idx).has_value()) result.inputs.emplace_back(std::visit(*this, arg)); @@ -568,7 +576,7 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const auto const* definition = findFunctionDefinition(&function); yulAssert(definition); canContinue = m_sideEffects.functionSideEffects().at(definition).canContinue; - SSACFG::Operation result{{}, SSACFG::Call{debugDataOf(_call), function, _call, canContinue}, {}}; + SSACFG::Operation result{{}, SSACFG::Call{function, _call, canContinue}, {}}; for (auto const& arg: _call.arguments | ranges::views::reverse) result.inputs.emplace_back(std::visit(*this, arg)); for (size_t i = 0; i < function.numReturns; ++i) @@ -577,11 +585,11 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const } }, _call.functionName); auto results = operation.outputs; - currentBlock().operations.emplace_back(m_graph.makeOperation(std::move(operation))); + currentBlock().operations.emplace_back(m_graph.makeOperation(std::move(operation), debugDataOf(_call))); if (!canContinue) { currentBlock().exit = SSACFG::BasicBlock::Terminated{}; - m_currentBlock = m_graph.makeBlock(debugDataOf(currentBlock())); + m_currentBlock = m_graph.makeBlock(currentBlockDebugData()); sealBlock(m_currentBlock); } return results; @@ -589,7 +597,7 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const SSACFG::ValueId SSACFGBuilder::zero() { - return m_graph.newLiteral(debugDataOf(currentBlock()), 0u); + return m_graph.newLiteral(currentBlockDebugData(), 0u); } SSACFG::ValueId SSACFGBuilder::readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block) @@ -695,8 +703,9 @@ void SSACFGBuilder::conditionalJump( SSACFG::BlockId _zero ) { + if (m_graph.debugInfo) + m_graph.debugInfo->setExitDebugData(m_currentBlock, std::move(_debugData)); currentBlock().exit = SSACFG::BasicBlock::ConditionalJump{ - std::move(_debugData), _condition, _nonZero, _zero @@ -711,7 +720,9 @@ void SSACFGBuilder::jump( SSACFG::BlockId _target ) { - currentBlock().exit = SSACFG::BasicBlock::Jump{std::move(_debugData), _target}; + if (m_graph.debugInfo) + m_graph.debugInfo->setExitDebugData(m_currentBlock, std::move(_debugData)); + currentBlock().exit = SSACFG::BasicBlock::Jump{_target}; yulAssert(!blockInfo(_target).sealed); m_graph.block(_target).entries.insert(m_currentBlock); m_currentBlock = _target; @@ -719,9 +730,8 @@ void SSACFGBuilder::jump( FunctionDefinition const* SSACFGBuilder::findFunctionDefinition(Scope::Function const* _function) const { - auto it = std::find_if( - m_functionDefinitions.begin(), - m_functionDefinitions.end(), + auto it = ranges::find_if( + m_functionDefinitions, [&_function](auto const& _entry) { return std::get<0>(_entry) == _function; } ); if (it != m_functionDefinitions.end()) diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index 331d8b52f..1acf03458 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -45,7 +45,8 @@ class SSACFGBuilder AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, Dialect const& _dialect, - bool _keepLiteralAssignments + bool _keepLiteralAssignments, + bool _generateDebugInfo ); public: SSACFGBuilder(SSACFGBuilder const&) = delete; @@ -54,7 +55,8 @@ class SSACFGBuilder AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, Block const& _block, - bool _keepLiteralAssignments + bool _keepLiteralAssignments, + bool _generateDebugInfo = true ); void operator()(ExpressionStatement const& _statement); @@ -95,9 +97,14 @@ class SSACFGBuilder ControlFlowSideEffectsCollector const& m_sideEffects; Dialect const& m_dialect; bool const m_keepLiteralAssignments; + bool const m_generateDebugInfo; std::vector> m_functionDefinitions; SSACFG::BlockId m_currentBlock; SSACFG::BasicBlock& currentBlock() { return m_graph.block(m_currentBlock); } + langutil::DebugData::ConstPtr currentBlockDebugData() const + { + return m_graph.debugInfo ? m_graph.debugInfo->blockDebugData(m_currentBlock) : nullptr; + } Scope* m_scope = nullptr; Scope::Function const& lookupFunction(YulName _name) const; Scope::Variable const& lookupVariable(YulName _name) const; diff --git a/libyul/backends/evm/ssa/SSACFGDebugInfo.h b/libyul/backends/evm/ssa/SSACFGDebugInfo.h new file mode 100644 index 000000000..d026147b1 --- /dev/null +++ b/libyul/backends/evm/ssa/SSACFGDebugInfo.h @@ -0,0 +1,133 @@ +/* + 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 + +#pragma once + +#include + +#include +#include + +#include + +namespace solidity::yul::ssa +{ + +/// Stores debug data for all SSACFG entities in parallel arrays indexed by the entities' stable IDs. +struct SSACFGDebugInfo +{ + void setBlockDebugData(BlockId _id, langutil::DebugData::ConstPtr _data) + { + yulAssert(_id.hasValue()); + ensureSize(m_blockDebugData, _id.value); + m_blockDebugData[_id.value] = std::move(_data); + } + + langutil::DebugData::ConstPtr const& blockDebugData(BlockId _id) const + { + return getOrEmpty(m_blockDebugData, _id.value); + } + + void setExitDebugData(BlockId _id, langutil::DebugData::ConstPtr _data) + { + yulAssert(_id.hasValue()); + ensureSize(m_exitDebugData, _id.value); + m_exitDebugData[_id.value] = std::move(_data); + } + + langutil::DebugData::ConstPtr const& exitDebugData(BlockId _id) const + { + return getOrEmpty(m_exitDebugData, _id.value); + } + + void setOperationDebugData(OperationId _id, langutil::DebugData::ConstPtr _data) + { + yulAssert(_id.hasValue()); + ensureSize(m_operationDebugData, _id.value); + m_operationDebugData[_id.value] = std::move(_data); + } + + langutil::DebugData::ConstPtr const& operationDebugData(OperationId _id) const + { + return getOrEmpty(m_operationDebugData, _id.value); + } + + void setValueDebugData(ValueId _id, langutil::DebugData::ConstPtr _data) + { + yulAssert(_id.hasValue()); + auto& vec = vectorForKind(_id.kind()); + ensureSize(vec, _id.value()); + vec[_id.value()] = std::move(_data); + } + + langutil::DebugData::ConstPtr const& valueDebugData(ValueId _id) const + { + return getOrEmpty(vectorForKind(_id.kind()), _id.value()); + } + + /// Top-level debug data for the SSACFG (e.g. the function definition's debug data). + langutil::DebugData::ConstPtr graphDebugData; + +private: + static void ensureSize(std::vector& _vec, std::size_t const _index) + { + if (_vec.size() <= _index) + _vec.resize(_index + 1); + } + + static langutil::DebugData::ConstPtr const& getOrEmpty( + std::vector const& _debugData, + std::size_t const _index + ) + { + static langutil::DebugData::ConstPtr const empty{nullptr}; + if (_index >= _debugData.size()) + return empty; + return _debugData[_index]; + } + + std::vector& vectorForKind(ValueId::Kind const _kind) + { + switch (_kind) + { + case ValueId::Kind::Literal: return m_literalDebugData; + case ValueId::Kind::Variable: return m_variableDebugData; + case ValueId::Kind::Phi: return m_phiDebugData; + default: yulAssert(false, "No debug data for unreachable values."); + } + } + std::vector const& vectorForKind(ValueId::Kind const _kind) const + { + switch (_kind) + { + case ValueId::Kind::Literal: return m_literalDebugData; + case ValueId::Kind::Variable: return m_variableDebugData; + case ValueId::Kind::Phi: return m_phiDebugData; + default: yulAssert(false, "No debug data for unreachable values."); + } + } + + std::vector m_blockDebugData; + std::vector m_exitDebugData; + std::vector m_operationDebugData; + std::vector m_literalDebugData; + std::vector m_variableDebugData; + std::vector m_phiDebugData; +}; + +} From fbae9e219501da843476f9b638ae860c5d46ca70 Mon Sep 17 00:00:00 2001 From: blishko Date: Mon, 23 Mar 2026 16:18:01 +0100 Subject: [PATCH 1197/1340] SSA: Rename method to determine if slot is a valid swap target --- libyul/backends/evm/ssa/Stack.h | 6 ++--- libyul/backends/evm/ssa/StackShuffler.h | 34 ++++++++++++------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index ebeefe225..0fcd43856 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -210,7 +210,7 @@ class Stack void swap(Depth const& _depth) { swap(depthToOffset(_depth)); } void swap(Offset const& _offset) { - yulAssert(swapReachable(_offset), "Stack too deep"); + yulAssert(isValidSwapTarget(_offset), "Stack too deep"); std::swap((*m_data)[_offset.value], m_data->back()); if constexpr (!std::is_same_v) m_callbacks.swap(offsetToDepth(_offset)); @@ -250,8 +250,8 @@ class Stack bool dupReachable(Offset const& _offset) const noexcept { return dupReachable(offsetToDepth(_offset)); } bool dupReachable(Depth const& _depth) const noexcept { return _depth < size() && _depth.value + 1 <= reachableStackDepth; } - bool swapReachable(Offset const& _offset) const noexcept { return swapReachable(offsetToDepth(_offset)); } - bool swapReachable(Depth const& _depth) const noexcept { return _depth < size() && 1 <= _depth.value && _depth.value <= reachableStackDepth; } + bool isValidSwapTarget(Offset const& _offset) const noexcept { return isValidSwapTarget(offsetToDepth(_offset)); } + bool isValidSwapTarget(Depth const& _depth) const noexcept { return _depth < size() && 1 <= _depth.value && _depth.value <= reachableStackDepth; } void declareJunk(Offset const& _offset) { (*m_data)[_offset.value] = Slot::makeJunk(); } void declareJunk(Depth const& _depth) { declareJunk(depthToOffset(_depth)); } diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index e918c33cd..dfa5347a3 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -348,7 +348,7 @@ class StackShuffler else { // even if it is not dup reachable, it still might be swappable - if (_stack.swapReachable(sourceOffset) && _state.isSafeToSwapWithTop(sourceOffset)) + if (_stack.isValidSwapTarget(sourceOffset) && _state.isSafeToSwapWithTop(sourceOffset)) { _stack.swap(sourceOffset); return true; @@ -387,28 +387,28 @@ class StackShuffler { // try swapping it with something in the tail that also fixes the top for (StackOffset offset: _state.stackTailRange()) - if (_stack.swapReachable(offset) && _state.isArgsCompatible(offset, stackTop)) + if (_stack.isValidSwapTarget(offset) && _state.isArgsCompatible(offset, stackTop)) { _stack.swap(offset); return true; } // otherwise try swapping it with something that needs to go into args for (StackOffset offset: _state.stackTailRange()) - if (_stack.swapReachable(offset) && _state.countInArgs(_stack[offset]) < _state.targetArgsCount(_stack[offset])) + if (_stack.isValidSwapTarget(offset) && _state.countInArgs(_stack[offset]) < _state.targetArgsCount(_stack[offset])) { _stack.swap(offset); return true; } // otherwise try swapping it with something that can be popped for (StackOffset offset: _state.stackTailRange()) - if (_stack.swapReachable(offset) && _stack.canBeFreelyGenerated(_stack[offset]) && !_stack[offset].isLiteralValueID()) + if (_stack.isValidSwapTarget(offset) && _stack.canBeFreelyGenerated(_stack[offset]) && !_stack[offset].isLiteralValueID()) { _stack.swap(offset); return true; } // otherwise try swapping it with a literal for (StackOffset offset: _state.stackTailRange()) - if (_stack.swapReachable(offset) && _stack[offset].isLiteralValueID()) + if (_stack.isValidSwapTarget(offset) && _stack[offset].isLiteralValueID()) { _stack.swap(offset); return true; @@ -421,7 +421,7 @@ class StackShuffler if ( offset != stackTop && _stack[offset] != _stack[stackTop] && // don't swap identical values (no-op) - _stack.swapReachable(offset) && + _stack.isValidSwapTarget(offset) && _state.isArgsCompatible(offset, stackTop) && _state.isArgsCompatible(stackTop, offset) && !_state.targetArbitrary(offset) @@ -436,7 +436,7 @@ class StackShuffler if ( offset != stackTop && _stack[offset] != _stack[stackTop] && // don't swap identical values (no-op) - _stack.swapReachable(offset) && + _stack.isValidSwapTarget(offset) && !_state.isArgsCompatible(offset, offset) && _state.isArgsCompatible(stackTop, offset) ) @@ -448,7 +448,7 @@ class StackShuffler // try swapping top with a tail slot that has what we need at top for (StackOffset tailOffset: _state.stackTailRange()) if ( - _stack.swapReachable(tailOffset) && + _stack.isValidSwapTarget(tailOffset) && _state.isArgsCompatible(tailOffset, stackTop) && (!_state.requiredInTail(_stack[tailOffset]) || _state.countInTail(_stack[tailOffset]) > 1) && // current top can safely go to tail (not needed in args, or we have excess) @@ -466,7 +466,7 @@ class StackShuffler // swap up any slot in args that is out of position and has a slot available in args that it can occupy for (StackOffset offset: _state.stackArgsRange()) { - bool const reachable = _stack.swapReachable(offset); + bool const reachable = _stack.isValidSwapTarget(offset); bool const identical = _state.isArgsCompatible(offset, stackTop) && !_state.targetArbitrary(stackTop); if ( reachable && @@ -481,7 +481,7 @@ class StackShuffler for (StackOffset targetOffset: _state.stackArgsRange()) if ( targetOffset != offset && // we shouldn't be looking at the very same offset - _stack.swapReachable(targetOffset) && // the target offset should be within reach + _stack.isValidSwapTarget(targetOffset) && // the target offset should be within reach _state.isArgsCompatible(offset, targetOffset) && // we can put offset -> targetOffset !_state.isArgsCompatible(targetOffset, targetOffset) // targetOffset doesn't like where it is ) @@ -562,7 +562,7 @@ class StackShuffler // within dup-reach or we can just push it if (auto depth = _stack.findSlotDepth(arg)) { - yulAssert(depth->value == 0 || _stack.swapReachable(*depth)); + yulAssert(depth->value == 0 || _stack.isValidSwapTarget(*depth)); // if we can't outright dup the slot, let's shrink the stack first if (!_stack.dupReachable(*depth)) { @@ -612,7 +612,7 @@ class StackShuffler { auto const& slotAtTailOffset = _stack[tailOffset]; if ( - _stack.swapReachable(tailOffset) && // we can swap that deep + _stack.isValidSwapTarget(tailOffset) && // we can swap that deep (!_state.requiredInTail(slotAtTailOffset) || _state.countInTail(slotAtTailOffset) > 1) && // dont need it in tail or it's available more than once _state.requiredInArgs(slotAtTailOffset) && // we need the tail offset slot in args _state.targetArgsCount(slotAtTailOffset) > _state.countInArgs(slotAtTailOffset) // we don't already have enough of it in args @@ -629,7 +629,7 @@ class StackShuffler // find the lowest swappable slot in tail that can be popped but is no literal, swap for (StackOffset tailOffset: _state.stackTailRange()) if ( - _stack.swapReachable(tailOffset) && + _stack.isValidSwapTarget(tailOffset) && _stack.canBeFreelyGenerated(_stack[tailOffset]) && !_stack[tailOffset].isLiteralValueID() ) @@ -644,7 +644,7 @@ class StackShuffler // find the lowest swappable slot in tail that is a literal, swap for (StackOffset tailOffset: _state.stackTailRange()) if ( - _stack.swapReachable(tailOffset) && + _stack.isValidSwapTarget(tailOffset) && _stack[tailOffset].isLiteralValueID() ) { @@ -704,7 +704,7 @@ class StackShuffler for (StackOffset argsOffset: _state.stackArgsRange()) if ( _stack[argsOffset] != _stack[stackTop] && // don't swap identical values (no-op) - _stack.swapReachable(argsOffset) && + _stack.isValidSwapTarget(argsOffset) && _state.isArgsCompatible(stackTop, argsOffset) && !_state.isArgsCompatible(argsOffset, argsOffset) ) @@ -734,7 +734,7 @@ class StackShuffler for (StackOffset tailOffset: _state.stackTailRange() | ranges::views::reverse) if ( _stack[tailOffset] != _stack[stackTop] && // don't swap identical values (no-op) - _stack.swapReachable(tailOffset) && // we can reach the offset + _stack.isValidSwapTarget(tailOffset) && // we can reach the offset !(_state.requiredInTail(_stack[tailOffset]) && _state.countInTail(_stack[tailOffset]) <= 1) // it's okay to swap the tail offset out ) { @@ -809,7 +809,7 @@ class StackShuffler } else { - if (depth->value != 0 && !_stack.swapReachable(*depth)) + if (depth->value != 0 && !_stack.isValidSwapTarget(*depth)) return _stack.depthToOffset(*depth); } } From 2f7307bdd819b643a58aee4ee9e012d9164a6801 Mon Sep 17 00:00:00 2001 From: blishko Date: Mon, 23 Mar 2026 16:33:59 +0100 Subject: [PATCH 1198/1340] SSA: Introduce and use new stack helper This helper checks if a slot depth is larger than the last (swap-) reachable slot. In some cases we are only interested in depth information and slot 0 is acceptable even though it is not a valid target for a swap instruction. --- libyul/backends/evm/ssa/Stack.h | 1 + libyul/backends/evm/ssa/StackShuffler.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index 0fcd43856..d4342426f 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -252,6 +252,7 @@ class Stack bool dupReachable(Depth const& _depth) const noexcept { return _depth < size() && _depth.value + 1 <= reachableStackDepth; } bool isValidSwapTarget(Offset const& _offset) const noexcept { return isValidSwapTarget(offsetToDepth(_offset)); } bool isValidSwapTarget(Depth const& _depth) const noexcept { return _depth < size() && 1 <= _depth.value && _depth.value <= reachableStackDepth; } + bool isBeyondSwapRange(Depth const& _depth) const noexcept { return _depth > reachableStackDepth; } void declareJunk(Offset const& _offset) { (*m_data)[_offset.value] = Slot::makeJunk(); } void declareJunk(Depth const& _depth) { declareJunk(depthToOffset(_depth)); } diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index dfa5347a3..6bdd47686 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -562,7 +562,7 @@ class StackShuffler // within dup-reach or we can just push it if (auto depth = _stack.findSlotDepth(arg)) { - yulAssert(depth->value == 0 || _stack.isValidSwapTarget(*depth)); + yulAssert(!_stack.isBeyondSwapRange(*depth)); // if we can't outright dup the slot, let's shrink the stack first if (!_stack.dupReachable(*depth)) { @@ -809,7 +809,7 @@ class StackShuffler } else { - if (depth->value != 0 && !_stack.isValidSwapTarget(*depth)) + if (_stack.isBeyondSwapRange(*depth)) return _stack.depthToOffset(*depth); } } From aaa8c503778019a598314a215a73296637e68e13 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 23 Mar 2026 17:52:57 +0100 Subject: [PATCH 1199/1340] Build SSA CFG in phi-upsilon form --- libyul/backends/evm/ssa/BridgeFinder.h | 8 +- libyul/backends/evm/ssa/LivenessAnalysis.cpp | 19 +--- libyul/backends/evm/ssa/PhiInverse.cpp | 9 +- libyul/backends/evm/ssa/SSACFG.cpp | 29 ++--- libyul/backends/evm/ssa/SSACFG.h | 29 ++--- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 111 +++++++++++-------- libyul/backends/evm/ssa/SSACFGBuilder.h | 16 ++- libyul/backends/evm/ssa/io/JSONExporter.cpp | 12 +- 8 files changed, 129 insertions(+), 104 deletions(-) diff --git a/libyul/backends/evm/ssa/BridgeFinder.h b/libyul/backends/evm/ssa/BridgeFinder.h index 6a7ebeef9..173e6105f 100644 --- a/libyul/backends/evm/ssa/BridgeFinder.h +++ b/libyul/backends/evm/ssa/BridgeFinder.h @@ -21,7 +21,7 @@ #include -#include +#include #include #include @@ -79,7 +79,7 @@ class BridgeFinder SSACFG::BlockId const& _neighbor, size_t& _time, SSACFG::BlockId const& _vertex, - std::set const& _vertexEntries, + std::vector const& _vertexEntries, std::optional const& _parent ) { @@ -93,8 +93,8 @@ class BridgeFinder if (m_low[_neighbor.value] > m_disc[_vertex.value]) { // vertex <-> neighbor is a bridge in the undirected graph - bool const edgeNeighborToVertex = _vertexEntries.contains(_neighbor); - bool const edgeVertexToNeighbor = m_cfg.block(_neighbor).entries.contains(_vertex); + bool const edgeNeighborToVertex = ranges::find(_vertexEntries, _neighbor) != _vertexEntries.end(); + bool const edgeVertexToNeighbor = ranges::find(m_cfg.block(_neighbor).entries, _vertex) != m_cfg.block(_neighbor).entries.end(); // special case: if it's the entry itself, we mark it as bridge vertex (provided correct orientation), // so that functions which do nothing but revert have their whole tree marked as such (sans loops) diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp index cf87a580b..9af5f861d 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -201,19 +201,12 @@ void LivenessAnalysis::runDagDfs() // live <- PhiUses(B) LivenessData live{}; - block.forEachExit( - [&](SSACFG::BlockId const& _successor) - { - for (auto const& phi: m_cfg.block(_successor).phis) - { - auto const& info = m_cfg.phiInfo(phi); - auto const& argIndex = m_cfg.phiArgumentIndex(blockId, _successor); - yulAssert(argIndex < info.arguments.size()); - auto const& arg = info.arguments.at(argIndex); - if (!arg.isLiteral()) - live.insert(arg); - } - }); + for (auto const& upsilon: block.upsilons) + { + yulAssert(!upsilon.value.isUnreachable()); + if (!upsilon.value.isLiteral()) + live.insert(upsilon.value); + } // for each S \in succs(B) s.t. (B, S) not a back edge: live <- live \cup (LiveIn(S) - PhiDefs(S)) block.forEachExit( diff --git a/libyul/backends/evm/ssa/PhiInverse.cpp b/libyul/backends/evm/ssa/PhiInverse.cpp index c88b132ad..f135746e1 100644 --- a/libyul/backends/evm/ssa/PhiInverse.cpp +++ b/libyul/backends/evm/ssa/PhiInverse.cpp @@ -22,12 +22,9 @@ using namespace solidity::yul::ssa; PhiInverse::PhiInverse(SSACFG const& _cfg, SSACFG::BlockId const& _from, SSACFG::BlockId const& _to) { - auto const argIndex = _cfg.phiArgumentIndex(_from, _to); - for (auto const& phiId: _cfg.block(_to).phis) - { - auto const& phiInfo = _cfg.phiInfo(phiId); - m_phiToPreImage[phiId] = phiInfo.arguments[argIndex]; - } + for (auto const& [phiValue, phi]: _cfg.block(_from).upsilons) + if (_cfg.phiInfo(phi).block == _to) + m_phiToPreImage[phi] = phiValue; } bool PhiInverse::noOp() const diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 08f5f9453..7fea15dda 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -40,17 +40,21 @@ using namespace solidity::yul::ssa; namespace { -std::string formatPhi(SSACFG const& _cfg, SSACFG::PhiValue const& _phiValue) +/// Build a human-readable Phi/Upsilon annotation for a phi value. +/// Shows which upsilons feed it, listed per predecessor block. +std::string formatPhi(SSACFG const& _cfg, SSACFG::ValueId _phiId) { - auto const transform = [&](SSACFG::ValueId const& valueId) { return valueId.str(_cfg); }; - std::vector formattedArgs; - formattedArgs.reserve(_phiValue.arguments.size()); - for (auto const& [arg, entry]: ranges::zip_view(_phiValue.arguments | ranges::views::transform(transform), _cfg.block(_phiValue.block).entries)) - formattedArgs.push_back(fmt::format("Block {} => {}", entry.value, arg)); - if (!formattedArgs.empty()) - return fmt::format("φ(\\l\\\n\t{}\\l\\\n)", fmt::join(formattedArgs, ",\\l\\\n\t")); - else - return "φ()"; + // Collect all upsilons targeting _phiId from the whole CFG. + std::vector formattedUpsilons; + for (SSACFG::BlockId::ValueType bv = 0; bv < _cfg.numBlocks(); ++bv) + for (auto const& u: _cfg.block(SSACFG::BlockId{bv}).upsilons) + if (u.phi == _phiId) + formattedUpsilons.push_back( + fmt::format("Block {} => {}", bv, u.value.str(_cfg)) + ); + if (!formattedUpsilons.empty()) + return fmt::format("φ(\\l\\\n\t{}\\l\\\n)", fmt::join(formattedUpsilons, ",\\l\\\n\t")); + return "φ()"; } class SSACFGDotExporter: public io::DotExporterBase @@ -96,10 +100,7 @@ class SSACFGDotExporter: public io::DotExporterBase _out << fmt::format("\\\nBlock {}\\n", _blockId.value); for (auto const& phi: block.phis) - { - auto const& phiInfo = m_cfg.phiInfo(phi); - _out << fmt::format("phi{} := {}\\l\\\n", phi.value(), formatPhi(m_cfg, phiInfo)); - } + _out << fmt::format("phi{} := {}\\l\\\n", phi.value(), formatPhi(m_cfg, phi)); for (auto const opId: block.operations) { auto const& operation = m_cfg.operation(opId); diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 0404248f1..d6ad20797 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -74,6 +74,15 @@ class SSACFG }; struct LiteralAssignment {}; + /// Upsilon records a phi pre-image at a block exit. + /// Upsilon(value, phi) means: the value flowing into `phi` from this block is `value`. + /// Lives in the predecessor block; the corresponding Phi lives in the successor. + struct Upsilon + { + ValueId value; ///< pre-image value for the phi + ValueId phi; ///< target phi + }; + struct Operation { std::vector outputs{}; std::variant kind; @@ -97,9 +106,12 @@ class SSACFG std::vector returnValues; }; struct Terminated {}; - std::set entries; - std::set phis; + std::vector entries; + std::vector phis; std::vector operations; + /// Upsilon assignments placed at the block exit (before the terminator). + /// They record the phi pre-images for successor blocks. + std::vector upsilons; std::variant exit = MainExit{}; template void forEachExit(Callable&& _callable) const @@ -137,7 +149,7 @@ class SSACFG BlockId makeBlock(langutil::DebugData::ConstPtr _debugData) { BlockId blockId { static_cast(m_blocks.size()) }; - m_blocks.emplace_back(BasicBlock{{}, {}, {}, BasicBlock::Terminated{}}); + m_blocks.emplace_back(BasicBlock{{}, {}, {}, {}, BasicBlock::Terminated{}}); if (debugInfo) debugInfo->setBlockDebugData(blockId, std::move(_debugData)); return blockId; @@ -169,12 +181,11 @@ class SSACFG }; struct PhiValue { BlockId block; - std::vector arguments; }; struct UnreachableValue {}; ValueId newPhi(BlockId const _definingBlock) { - m_phis.emplace_back(PhiValue{_definingBlock, std::vector{}}); + m_phis.emplace_back(PhiValue{_definingBlock}); auto const value = m_phis.size() - 1; yulAssert(value < std::numeric_limits::max()); auto const id = ValueId::makePhi(static_cast(value)); @@ -220,14 +231,6 @@ class SSACFG return literalId; } - size_t phiArgumentIndex(BlockId const _source, BlockId const _target) const - { - auto const& targetBlock = block(_target); - auto idx = util::findOffset(targetBlock.entries, _source); - yulAssert(idx, fmt::format("Target block {} not found as entry in one of the exits of the current block {}.", _target.value, _source.value)); - return *idx; - } - std::string toDot( bool _includeDiGraphDefinition=true, std::optional _functionIndex=std::nullopt, diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 50523916d..01dafc2e3 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -97,15 +97,18 @@ SSACFG::ValueId SSACFGBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) auto const& phiInfo = m_graph.phiInfo(_phi); yulAssert(blockInfo(phiInfo.block).sealed); + // Collect upsilon values targeting this phi. SSACFG::ValueId same; - for (SSACFG::ValueId arg: phiInfo.arguments) - { - if (arg == same || arg == _phi) - continue; // unique value or self-reference - if (same.hasValue()) - return _phi; // phi merges at least two distinct values -> not trivial - same = arg; - } + for (auto const& entry: m_graph.block(phiInfo.block).entries) + for (auto const& u: m_graph.block(entry).upsilons) + if (u.phi == _phi) + { + if (u.value == same || u.value == _phi) + continue; // unique value or self-reference + if (same.hasValue()) + return _phi; // phi merges at least two distinct values -> not trivial + same = u.value; + } if (!same.hasValue()) { // This will happen for unreachable paths. @@ -113,7 +116,7 @@ SSACFG::ValueId SSACFGBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) same = m_graph.unreachableValue(); } - m_graph.block(phiInfo.block).phis.erase(_phi); + std::erase(m_graph.block(phiInfo.block).phis, _phi); std::vector phiUses; for (SSACFG::BlockId::ValueType blockIdValue = 0; blockIdValue < m_graph.numBlocks(); ++blockIdValue) @@ -123,22 +126,21 @@ SSACFG::ValueId SSACFGBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) { yulAssert(blockPhi.hasValue()); yulAssert(blockPhi != _phi, "Phis should be defined in exactly one block, _phi was erased."); - auto& blockPhiInfo = m_graph.phiInfo(blockPhi); - bool usedInPhi = false; - for (auto& arg: blockPhiInfo.arguments) - if (arg == _phi) - { - arg = same; - usedInPhi = true; - } - if (usedInPhi) - phiUses.push_back(blockPhi); } + // Replace _phi with same in upsilon values and collect affected phis. + for (auto& u: block.upsilons) + if (u.value == _phi) + { + u.value = same; + phiUses.push_back(u.phi); + } + // Erase upsilons targeting _phi. + std::erase_if(block.upsilons, [_phi](auto const& u) { return u.phi == _phi; }); for (auto opId: block.operations) ranges::replace(m_graph.operation(opId).inputs, _phi, same); std::visit(util::GenericVisitor{ [_phi, same](SSACFG::BasicBlock::FunctionReturn& _functionReturn) { - ranges::replace(_functionReturn.returnValues,_phi, same); + ranges::replace(_functionReturn.returnValues, _phi, same); }, [_phi, same](SSACFG::BasicBlock::ConditionalJump& _condJump) { if (_condJump.condition == _phi) @@ -179,28 +181,34 @@ void SSACFGBuilder::cleanUnreachable() }, block.exit); }); - // Remove all entries from unreachable nodes from the graph. + // Remove unreachable predecessor entries. for (SSACFG::BlockId blockId: reachabilityCheck.visited) { auto& block = m_graph.block(blockId); - - std::vector maybeTrivialPhi; std::erase_if(block.entries, [&](auto const& entry) { return !reachabilityCheck.visited.contains(entry); }); - for (auto phi: block.phis) - { - yulAssert(phi.hasValue()); - auto& phiInfo = m_graph.phiInfo(phi); - auto const erasedCount = std::erase_if(phiInfo.arguments, [&](SSACFG::ValueId const _arg) { - return _arg.isUnreachable(); - }); - if (erasedCount > 0) - maybeTrivialPhi.push_back(phi); - } + } - // After removing a phi argument, we might end up with a trivial phi that can be removed. - for (auto phi: maybeTrivialPhi) - tryRemoveTrivialPhi(phi); + // Remove upsilons that are now invalid: + // - upsilons in unreachable blocks (their block will never execute), or + // - upsilons with an unreachable value (product of earlier trivial-phi removal). + // Collect the affected target phis so we can attempt trivial-phi removal afterward. + std::vector maybeTrivialPhi; + for (SSACFG::BlockId blockId{0}; blockId.value < m_graph.numBlocks(); ++blockId.value) + { + auto& block = m_graph.block(blockId); + bool const isReachable = reachabilityCheck.visited.contains(blockId); + + for (auto const& u: block.upsilons) + if (!isReachable || u.value.isUnreachable()) + maybeTrivialPhi.push_back(u.phi); + + std::erase_if(block.upsilons, [&](SSACFG::Upsilon const& u) { + return !isReachable || u.value.isUnreachable(); + }); } + + for (auto const phi: maybeTrivialPhi) + tryRemoveTrivialPhi(phi); } void SSACFGBuilder::buildFunctionGraph( @@ -615,9 +623,9 @@ SSACFG::ValueId SSACFGBuilder::readVariableRecursive(Scope::Variable const& _var SSACFG::ValueId val; if (!info.sealed) { - // incomplete block + // incomplete block: create a phi and defer upsilon emission until the block is sealed val = m_graph.newPhi(_block); - block.phis.insert(val); + block.phis.push_back(val); info.incompletePhis.emplace_back(val, _variable); } else if (block.entries.size() == 1) @@ -625,27 +633,32 @@ SSACFG::ValueId SSACFGBuilder::readVariableRecursive(Scope::Variable const& _var val = readVariable(_variable, *block.entries.begin()); else { - // Break potential cycles with operandless phi + // Break potential cycles with an argument-less phi; emit upsilons for all predecessors. val = m_graph.newPhi(_block); - block.phis.insert(val); + block.phis.push_back(val); writeVariable(_variable, _block, val); // we call tryRemoveTrivialPhi explicitly opposed to what is presented in Algorithm 2, as our implementation // does not call it in addPhiOperands to avoid removing phis in unsealed blocks - val = tryRemoveTrivialPhi(addPhiOperands(_variable, val)); + addPhiOperands(_variable, val); + val = tryRemoveTrivialPhi(val); } writeVariable(_variable, _block, val); return val; } -SSACFG::ValueId SSACFGBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi) +void SSACFGBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi) { for (auto const& pred: m_graph.block(m_graph.phiInfo(_phi).block).entries) { - auto const var = readVariable(_variable, pred); - m_graph.phiInfo(_phi).arguments.emplace_back(var); + auto const val = readVariable(_variable, pred); + emitUpsilon(pred, val, _phi); } - // we call tryRemoveTrivialPhi explicitly to avoid removing trivial phis in unsealed blocks - return _phi; +} + +void SSACFGBuilder::emitUpsilon(SSACFG::BlockId _block, SSACFG::ValueId _value, SSACFG::ValueId _phi) +{ + yulAssert(_phi.isPhi()); + m_graph.block(_block).upsilons.emplace_back(SSACFG::Upsilon{_value, _phi}); } void SSACFGBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value) @@ -710,8 +723,8 @@ void SSACFGBuilder::conditionalJump( _nonZero, _zero }; - m_graph.block(_nonZero).entries.insert(m_currentBlock); - m_graph.block(_zero).entries.insert(m_currentBlock); + m_graph.block(_nonZero).entries.push_back(m_currentBlock); + m_graph.block(_zero).entries.push_back(m_currentBlock); m_currentBlock = {}; } @@ -724,7 +737,7 @@ void SSACFGBuilder::jump( m_graph.debugInfo->setExitDebugData(m_currentBlock, std::move(_debugData)); currentBlock().exit = SSACFG::BasicBlock::Jump{_target}; yulAssert(!blockInfo(_target).sealed); - m_graph.block(_target).entries.insert(m_currentBlock); + m_graph.block(_target).entries.push_back(m_currentBlock); m_currentBlock = _target; } diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index 1acf03458..091bb0ba8 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -16,9 +16,9 @@ */ // SPDX-License-Identifier: GPL-3.0 /** -* Transformation of a Yul AST into a control flow graph. +* Transformation of a Yul AST into a control flow graph in Phi/Upsilon SSA form. * -* Based on https://doi.org/10.1007/978-3-642-37051-9_6 +* SSA construction is based on https://doi.org/10.1007/978-3-642-37051-9_6 * Braun, Matthias, et al. "Simple and efficient construction of static single assignment form." * Compiler Construction: 22nd International Conference, CC 2013, * ETAPS 2013, Rome, Italy, March 16-24, 2013. Proceedings 22. Springer Berlin Heidelberg, 2013. @@ -26,6 +26,13 @@ * We have small deviations in Algorithms 2 and 4, as the paper's presentation leads to trivial phis being spuriously * removed from not yet sealed blocks via a call to addPhiOperands in Algorithm 4. Instead, we perform the deletion * of trivial phis only after a block has been sealed, i.e., all block's predecessors are present. +* +* The IR uses Phi/Upsilon form (see https://gist.github.com/pizlonator/cf1e72b8600b1437dda8153ea3fdb963) rather than +* traditional phi nodes with explicit argument lists. +* In Phi/Upsilon form each predecessor block emits an Upsilon operation that records the phi pre-image +* for that edge; the Phi itself carries no argument list. This makes the phi pre-image relationship +* explicit in the IR and means that adding or removing a predecessor never requires reindexing +* phi arguments. */ #pragma once @@ -88,7 +95,10 @@ class SSACFGBuilder SSACFG::ValueId zero(); SSACFG::ValueId readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block); SSACFG::ValueId readVariableRecursive(Scope::Variable const& _variable, SSACFG::BlockId _block); - SSACFG::ValueId addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi); + /// Emit upsilons in each predecessor of _phi's block, recording the phi pre-images. + void addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi); + /// Emit a single Upsilon(_value -> _phi) into block _block. + void emitUpsilon(SSACFG::BlockId _block, SSACFG::ValueId _value, SSACFG::ValueId _phi); void writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value); ControlFlow& m_controlFlow; diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index a5119b2d3..5e7d51436 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -115,10 +115,18 @@ Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const | ranges::to(); for (auto const& phi: block.phis) { - auto const& phiInfo = _cfg.phiInfo(phi); + // Reconstruct phi arguments from upsilon nodes in predecessor blocks. + std::vector phiArgs; + for (auto const& entryId: block.entries) + for (auto const& upsilon: _cfg.block(entryId).upsilons) + if (upsilon.phi == phi) + { + phiArgs.push_back(upsilon.value); + break; + } Json phiJson = Json::object(); phiJson["op"] = "PhiFunction"; - phiJson["in"] = toJson(_cfg, phiInfo.arguments); + phiJson["in"] = toJson(_cfg, phiArgs); phiJson["out"] = toJson(_cfg, std::vector{phi}); blockJson["instructions"].push_back(phiJson); } From a99633adb114eeb5df1622427b2714969000fa66 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 9 Mar 2026 12:20:46 +0100 Subject: [PATCH 1200/1340] Introduce experimental EVM version --- docs/using-the-compiler.rst | 3 ++- liblangutil/EVMVersion.h | 7 ++++++- libsolidity/interface/StandardCompiler.cpp | 5 +++++ solc/CommandLineParser.cpp | 7 +++---- test/EVMHost.cpp | 2 ++ test/TestCase.cpp | 2 +- .../evm_version_future_no_experimental_mode/args | 1 + .../evm_version_future_no_experimental_mode/err | 1 + .../evm_version_future_no_experimental_mode/exit | 1 + .../input.sol | 0 .../evm_version_future_with_experimental_mode/args | 1 + .../input.sol | 2 ++ .../input.json | 9 +++++++++ .../output.json | 11 +++++++++++ .../input.json | 10 ++++++++++ .../output.json | 7 +++++++ test/libsolidity/StandardCompiler.cpp | 5 ++++- .../future_evm_version_smoke_test.sol | 12 ++++++++++++ 18 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 test/cmdlineTests/evm_version_future_no_experimental_mode/args create mode 100644 test/cmdlineTests/evm_version_future_no_experimental_mode/err create mode 100644 test/cmdlineTests/evm_version_future_no_experimental_mode/exit create mode 100644 test/cmdlineTests/evm_version_future_no_experimental_mode/input.sol create mode 100644 test/cmdlineTests/evm_version_future_with_experimental_mode/args create mode 100644 test/cmdlineTests/evm_version_future_with_experimental_mode/input.sol create mode 100644 test/cmdlineTests/standard_evm_version_future_no_experimental_mode/input.json create mode 100644 test/cmdlineTests/standard_evm_version_future_no_experimental_mode/output.json create mode 100644 test/cmdlineTests/standard_evm_version_future_with_experimental_mode/input.json create mode 100644 test/cmdlineTests/standard_evm_version_future_with_experimental_mode/output.json create mode 100644 test/libsolidity/semanticTests/isoltestTesting/future_evm_version_smoke_test.sol diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 604f8b05a..7a97fa54e 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -360,7 +360,8 @@ Input Description // Version of the EVM to compile for (optional). // Affects type checking and code generation. Can be homestead, // tangerineWhistle, spuriousDragon, byzantium, constantinople, - // petersburg, istanbul, berlin, london, paris, shanghai, cancun, prague or osaka (default). + // petersburg, istanbul, berlin, london, paris, shanghai, cancun, + // prague, osaka (default), or @future (experimental). "evmVersion": "osaka", // EVM Object Format version to compile for (optional, experimental). // Currently the only valid value is 1. If not specified, legacy non-EOF bytecode will be generated. diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index f72b71056..e2c7964c7 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include #include @@ -29,7 +30,6 @@ #include #include - namespace solidity::evmasm { /// Virtual machine bytecode instruction. Forward declared from libevmasm/Instruction.h @@ -64,6 +64,7 @@ class EVMVersion static EVMVersion constexpr cancun() { return {Version::Cancun}; } static EVMVersion constexpr prague() { return {Version::Prague}; } static EVMVersion constexpr osaka() { return {Version::Osaka}; } + static EVMVersion constexpr future() { return {Version::Future}; } static auto constexpr allVersions() { return std::array{ @@ -81,6 +82,7 @@ class EVMVersion cancun(), prague(), osaka(), + future(), }; } @@ -103,6 +105,7 @@ class EVMVersion static EVMVersion firstWithEOF() { return {Version::Osaka}; } bool isExperimental() const { + solAssert(Version::Future > currentVersion); return m_version > currentVersion; } @@ -126,6 +129,7 @@ class EVMVersion case Version::Cancun: return "cancun"; case Version::Prague: return "prague"; case Version::Osaka: return "osaka"; + case Version::Future: return "@future"; } util::unreachable(); } @@ -171,6 +175,7 @@ class EVMVersion Cancun, Prague, Osaka, + Future, }; static auto constexpr currentVersion = Version::Osaka; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 264ce55bb..c8dbeb317 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -877,6 +877,11 @@ std::variant StandardCompiler::parseI "general", "Support for EVM versions older than constantinople is deprecated and will be removed in the future." )); + if (version->isExperimental() && !ret.experimental) + return formatFatalError( + Error::Type::JSONError, + fmt::format("EVM version '{}' is experimental and can only be used with the 'settings.experimental' option enabled.", version->name()) + ); ret.evmVersion = *version; } diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 679cdce44..08260a6fb 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -191,19 +191,18 @@ void CommandLineParser::checkExperimental(std::vector const& _optio ); } - if (m_args.contains(g_strEVMVersion)) + if (!m_args.contains(g_strExperimental) && m_args.contains(g_strEVMVersion)) { std::string versionOptionStr = m_args[g_strEVMVersion].as(); std::optional versionOption = langutil::EVMVersion::fromString(versionOptionStr); if (versionOption.has_value() && versionOption->isExperimental()) - // TODO: Cover with test when the Amsterdam version is introduced solThrow( CommandLineValidationError, fmt::format( "EVM version '{}' is experimental and can only be selected in experimental mode. " - "To enable experimental mode, use the --{} flag", - m_options.output.evmVersion.name(), + "To enable experimental mode, use the --{} flag.", + versionOption->name(), g_strExperimental ) ); diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 6f64b703b..c4045965d 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -137,6 +137,8 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm): m_evmRevision = EVMC_PRAGUE; else if (_evmVersion == langutil::EVMVersion::osaka()) m_evmRevision = EVMC_OSAKA; + else if (_evmVersion == langutil::EVMVersion::future()) + m_evmRevision = EVMC_MAX_REVISION; else solRequire(false, Exception, "Unsupported EVM version"); diff --git a/test/TestCase.cpp b/test/TestCase.cpp index efc455ff6..c4a1f3b8a 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -106,7 +106,7 @@ void EVMVersionRestrictedTestCase::processEVMVersionSetting() std::string comparator; size_t versionBegin = 0; for (auto character: versionString) - if (!isalpha(character, std::locale::classic())) + if (!isalpha(character, std::locale::classic()) && character != '@') { comparator += character; versionBegin++; diff --git a/test/cmdlineTests/evm_version_future_no_experimental_mode/args b/test/cmdlineTests/evm_version_future_no_experimental_mode/args new file mode 100644 index 000000000..3e55424a2 --- /dev/null +++ b/test/cmdlineTests/evm_version_future_no_experimental_mode/args @@ -0,0 +1 @@ +--evm-version @future diff --git a/test/cmdlineTests/evm_version_future_no_experimental_mode/err b/test/cmdlineTests/evm_version_future_no_experimental_mode/err new file mode 100644 index 000000000..38c57e554 --- /dev/null +++ b/test/cmdlineTests/evm_version_future_no_experimental_mode/err @@ -0,0 +1 @@ +Error: EVM version '@future' is experimental and can only be selected in experimental mode. To enable experimental mode, use the --experimental flag. diff --git a/test/cmdlineTests/evm_version_future_no_experimental_mode/exit b/test/cmdlineTests/evm_version_future_no_experimental_mode/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/evm_version_future_no_experimental_mode/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/evm_version_future_no_experimental_mode/input.sol b/test/cmdlineTests/evm_version_future_no_experimental_mode/input.sol new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/evm_version_future_with_experimental_mode/args b/test/cmdlineTests/evm_version_future_with_experimental_mode/args new file mode 100644 index 000000000..ed86636ea --- /dev/null +++ b/test/cmdlineTests/evm_version_future_with_experimental_mode/args @@ -0,0 +1 @@ +--experimental --evm-version @future diff --git a/test/cmdlineTests/evm_version_future_with_experimental_mode/input.sol b/test/cmdlineTests/evm_version_future_with_experimental_mode/input.sol new file mode 100644 index 000000000..4bf9ea143 --- /dev/null +++ b/test/cmdlineTests/evm_version_future_with_experimental_mode/input.sol @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; diff --git a/test/cmdlineTests/standard_evm_version_future_no_experimental_mode/input.json b/test/cmdlineTests/standard_evm_version_future_no_experimental_mode/input.json new file mode 100644 index 000000000..d5afff8f9 --- /dev/null +++ b/test/cmdlineTests/standard_evm_version_future_no_experimental_mode/input.json @@ -0,0 +1,9 @@ +{ + "language": "Solidity", + "sources": { + "input.sol": {"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity *;"} + }, + "settings": { + "evmVersion": "@future" + } +} diff --git a/test/cmdlineTests/standard_evm_version_future_no_experimental_mode/output.json b/test/cmdlineTests/standard_evm_version_future_no_experimental_mode/output.json new file mode 100644 index 000000000..0ecccaf18 --- /dev/null +++ b/test/cmdlineTests/standard_evm_version_future_no_experimental_mode/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "EVM version '@future' is experimental and can only be used with the 'settings.experimental' option enabled.", + "message": "EVM version '@future' is experimental and can only be used with the 'settings.experimental' option enabled.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_evm_version_future_with_experimental_mode/input.json b/test/cmdlineTests/standard_evm_version_future_with_experimental_mode/input.json new file mode 100644 index 000000000..675b71750 --- /dev/null +++ b/test/cmdlineTests/standard_evm_version_future_with_experimental_mode/input.json @@ -0,0 +1,10 @@ +{ + "language": "Solidity", + "sources": { + "input.sol": {"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity *;"} + }, + "settings": { + "experimental": true, + "evmVersion": "@future" + } +} diff --git a/test/cmdlineTests/standard_evm_version_future_with_experimental_mode/output.json b/test/cmdlineTests/standard_evm_version_future_with_experimental_mode/output.json new file mode 100644 index 000000000..81fa23ff6 --- /dev/null +++ b/test/cmdlineTests/standard_evm_version_future_with_experimental_mode/output.json @@ -0,0 +1,7 @@ +{ + "sources": { + "input.sol": { + "id": 0 + } + } +} diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 18c366e3e..187ff53a6 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -1181,7 +1181,10 @@ BOOST_AUTO_TEST_CASE(evm_version) Json result; for (auto const& version: EVMVersion::allVersions()) { - result = compile(inputForVersion(fmt::format("\"evmVersion\": \"{}\",", version.name()))); + if (version.isExperimental()) + result = compile(inputForVersion(fmt::format("\"evmVersion\": \"{}\", \"experimental\": {},", version.name(), "true"))); + else + result = compile(inputForVersion(fmt::format("\"evmVersion\": \"{}\",", version.name()))); BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].get().find(fmt::format("\"evmVersion\":\"{}\"", version.name())) != std::string::npos); } // test default diff --git a/test/libsolidity/semanticTests/isoltestTesting/future_evm_version_smoke_test.sol b/test/libsolidity/semanticTests/isoltestTesting/future_evm_version_smoke_test.sol new file mode 100644 index 000000000..1e7701d20 --- /dev/null +++ b/test/libsolidity/semanticTests/isoltestTesting/future_evm_version_smoke_test.sol @@ -0,0 +1,12 @@ +contract C { + uint256 x = 10; + + function getX() external view returns (uint256) { + return x; + } +} +// ==== +// EVMVersion: =@future +// experimental: true +// ---- +// getX() -> 10 From 15b26e6fc99c327331ce0a5887731bba9c762a12 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 10 Mar 2026 14:55:55 +0100 Subject: [PATCH 1201/1340] Add a soltest run for experimental EVM versions --- .circleci/soltest_all.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 389061859..52eff469d 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -41,8 +41,9 @@ DEFAULT_EVM_VALUES=( shanghai cancun osaka + @future ) -EVMS_WITH_EOF=(osaka) +EVMS_WITH_EOF=(osaka @future) # Deserialize the EVM_VALUES array if it was provided as argument or # set EVM_VALUES to the default values. @@ -72,7 +73,6 @@ do if (( EOF_VERSION > 0 )) && [[ ! " ${EVMS_WITH_EOF[*]} " == *" $EVM "* ]]; then continue fi - ENFORCE_GAS_ARGS="" [ "${EVM}" = "${DEFAULT_EVM}" ] && ENFORCE_GAS_ARGS="--enforce-gas-cost" # Run SMTChecker tests only when OPTIMIZE == 0 From c2d2bc6ba8639d029096f1800a11c3c499bc60d4 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 18 Mar 2026 13:02:49 +0100 Subject: [PATCH 1202/1340] Changelog --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index c5a942281..b295b7bf4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Language Features: Compiler Features: * Commandline Interface: Disallow selecting the deprecated assembly input mode that was only accessible via `--assemble` instead of treating it as equivalent to `--strict-assembly`. * Commandline Interface: Introduce `--experimental` flag required for enabling the experimental mode. +* EVM: Introduce experimental EVM version `@future`. * General: Introduce the SSA CFG codegen (experimental). * General: Restrict the existing experimental features (`generic-solidity`, `lsp`, `ethdebug`, `eof`, `evm`, `ast-import`, `evmasm-import`, `ir-ast`, `ssa-cfg`) to experimental mode. * Metadata: Store the state of the experimental mode in JSON and CBOR metadata. In CBOR this broadens the meaning of the existing `experimental` field, which used to indicate only the presence of certain experimental pragmas in the source. From 59ebbe78bbb1daa341646d02138de31dee415dc1 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 24 Mar 2026 18:18:53 +0100 Subject: [PATCH 1203/1340] Move test/libyul/SSAControlFlowGraphTest to test/libyul/ssa/ControlFlowGraphTest --- test/CMakeLists.txt | 4 ++-- test/InteractiveTests.h | 4 ++-- .../ControlFlowGraphTest.cpp} | 18 +++++++++--------- .../ControlFlowGraphTest.h} | 6 +++--- .../controlFlowGraph}/complex.yul | 0 .../controlFlowGraph}/complex2.yul | 0 .../default_initialized_variable.yul | 0 .../controlFlowGraph}/function.yul | 0 .../controlFlowGraph}/if.yul | 0 .../controlFlowGraph}/if_const.yul | 0 .../controlFlowGraph}/nested_for.yul | 0 .../controlFlowGraph}/nested_function.yul | 0 .../controlFlowGraph}/switch.yul | 0 .../controlFlowGraph}/switch_const.yul | 0 test/tools/CMakeLists.txt | 3 ++- 15 files changed, 18 insertions(+), 17 deletions(-) rename test/libyul/{SSAControlFlowGraphTest.cpp => ssa/ControlFlowGraphTest.cpp} (83%) rename test/libyul/{SSAControlFlowGraphTest.h => ssa/ControlFlowGraphTest.h} (84%) rename test/libyul/{yulSSAControlFlowGraph => ssa/controlFlowGraph}/complex.yul (100%) rename test/libyul/{yulSSAControlFlowGraph => ssa/controlFlowGraph}/complex2.yul (100%) rename test/libyul/{yulSSAControlFlowGraph => ssa/controlFlowGraph}/default_initialized_variable.yul (100%) rename test/libyul/{yulSSAControlFlowGraph => ssa/controlFlowGraph}/function.yul (100%) rename test/libyul/{yulSSAControlFlowGraph => ssa/controlFlowGraph}/if.yul (100%) rename test/libyul/{yulSSAControlFlowGraph => ssa/controlFlowGraph}/if_const.yul (100%) rename test/libyul/{yulSSAControlFlowGraph => ssa/controlFlowGraph}/nested_for.yul (100%) rename test/libyul/{yulSSAControlFlowGraph => ssa/controlFlowGraph}/nested_function.yul (100%) rename test/libyul/{yulSSAControlFlowGraph => ssa/controlFlowGraph}/switch.yul (100%) rename test/libyul/{yulSSAControlFlowGraph => ssa/controlFlowGraph}/switch_const.yul (100%) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 02a45088f..c6c8040f8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -159,8 +159,6 @@ set(libyul_sources libyul/ObjectCompilerTest.h libyul/ObjectParser.cpp libyul/Parser.cpp - libyul/SSAControlFlowGraphTest.cpp - libyul/SSAControlFlowGraphTest.h libyul/StackLayoutGeneratorTest.cpp libyul/StackLayoutGeneratorTest.h libyul/StackShufflingTest.cpp @@ -173,6 +171,8 @@ set(libyul_sources libyul/YulOptimizerTest.h libyul/YulOptimizerTestCommon.cpp libyul/YulOptimizerTestCommon.h + libyul/ssa/ControlFlowGraphTest.cpp + libyul/ssa/ControlFlowGraphTest.h libyul/ssa/StackLayoutGeneratorTest.cpp libyul/ssa/StackLayoutGeneratorTest.h libyul/ssa/StackShufflerTest.cpp diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index 7930dc32d..063e21ccb 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -31,10 +31,10 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -74,7 +74,7 @@ Testsuite const g_interactiveTestsuites[] = { {"Yul Interpreter", "libyul", "yulInterpreterTests", false, false, &yul::test::YulInterpreterTest::create}, {"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create}, {"Yul Control Flow Graph", "libyul", "yulControlFlowGraph", false, false, &yul::test::ControlFlowGraphTest::create}, - {"Yul SSA Control Flow Graph", "libyul", "yulSSAControlFlowGraph", false, false, &yul::test::SSAControlFlowGraphTest::create}, + {"Yul SSA Control Flow Graph", "libyul", "ssa/controlFlowGraph", false, false, &yul::test::ssa::ControlFlowGraphTest::create}, {"Yul SSA StackShuffling", "libyul", "ssa/stackShuffler", false, false, &yul::test::ssa::ShufflingTest::create}, {"Yul SSA StackLayoutGenerator","libyul", "ssa/stackLayoutGenerator", false, false, &yul::test::ssa::StackLayoutGeneratorTest::create}, {"Yul Stack Layout", "libyul", "yulStackLayout", false, false, &yul::test::StackLayoutGeneratorTest::create}, diff --git a/test/libyul/SSAControlFlowGraphTest.cpp b/test/libyul/ssa/ControlFlowGraphTest.cpp similarity index 83% rename from test/libyul/SSAControlFlowGraphTest.cpp rename to test/libyul/ssa/ControlFlowGraphTest.cpp index 18f1c7c25..a2d43b23a 100644 --- a/test/libyul/SSAControlFlowGraphTest.cpp +++ b/test/libyul/ssa/ControlFlowGraphTest.cpp @@ -16,12 +16,12 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#include + #include #include #include -#include #include #include @@ -43,15 +43,15 @@ using namespace solidity; using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul; -using namespace solidity::yul::test; +using namespace solidity::yul::test::ssa; using namespace solidity::frontend; using namespace solidity::frontend::test; -std::unique_ptr SSAControlFlowGraphTest::create(TestCase::Config const& _config) { - return std::make_unique(_config.filename); +std::unique_ptr ControlFlowGraphTest::create(Config const& _config) { + return std::make_unique(_config.filename); } -SSAControlFlowGraphTest::SSAControlFlowGraphTest(std::string const& _filename): TestCase(_filename) +ControlFlowGraphTest::ControlFlowGraphTest(std::string const& _filename): TestCase(_filename) { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); @@ -59,7 +59,7 @@ SSAControlFlowGraphTest::SSAControlFlowGraphTest(std::string const& _filename): m_expectation = m_reader.simpleExpectations(); } -TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) +TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { YulStack yulStack = parseYul(m_source); solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); @@ -70,13 +70,13 @@ TestCase::TestResult SSAControlFlowGraphTest::run(std::ostream& _stream, std::st return TestResult::FatalError; } - std::unique_ptr controlFlow = ssa::SSACFGBuilder::build( + std::unique_ptr controlFlow = yul::ssa::SSACFGBuilder::build( *yulStack.parserResult()->analysisInfo, yulStack.dialect(), yulStack.parserResult()->code()->root(), true ); - ssa::ControlFlowLiveness liveness(*controlFlow); + yul::ssa::ControlFlowLiveness liveness(*controlFlow); m_obtainedResult = controlFlow->toDot(&liveness); auto result = checkResult(_stream, _linePrefix, _formatted); diff --git a/test/libyul/SSAControlFlowGraphTest.h b/test/libyul/ssa/ControlFlowGraphTest.h similarity index 84% rename from test/libyul/SSAControlFlowGraphTest.h rename to test/libyul/ssa/ControlFlowGraphTest.h index 51dd3c86d..78717f321 100644 --- a/test/libyul/SSAControlFlowGraphTest.h +++ b/test/libyul/ssa/ControlFlowGraphTest.h @@ -22,14 +22,14 @@ #include -namespace solidity::yul::test +namespace solidity::yul::test::ssa { -class SSAControlFlowGraphTest: public solidity::frontend::test::TestCase +class ControlFlowGraphTest: public solidity::frontend::test::TestCase { public: static std::unique_ptr create(Config const& _config); - explicit SSAControlFlowGraphTest(std::string const& _filename); + explicit ControlFlowGraphTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; }; diff --git a/test/libyul/yulSSAControlFlowGraph/complex.yul b/test/libyul/ssa/controlFlowGraph/complex.yul similarity index 100% rename from test/libyul/yulSSAControlFlowGraph/complex.yul rename to test/libyul/ssa/controlFlowGraph/complex.yul diff --git a/test/libyul/yulSSAControlFlowGraph/complex2.yul b/test/libyul/ssa/controlFlowGraph/complex2.yul similarity index 100% rename from test/libyul/yulSSAControlFlowGraph/complex2.yul rename to test/libyul/ssa/controlFlowGraph/complex2.yul diff --git a/test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul b/test/libyul/ssa/controlFlowGraph/default_initialized_variable.yul similarity index 100% rename from test/libyul/yulSSAControlFlowGraph/default_initialized_variable.yul rename to test/libyul/ssa/controlFlowGraph/default_initialized_variable.yul diff --git a/test/libyul/yulSSAControlFlowGraph/function.yul b/test/libyul/ssa/controlFlowGraph/function.yul similarity index 100% rename from test/libyul/yulSSAControlFlowGraph/function.yul rename to test/libyul/ssa/controlFlowGraph/function.yul diff --git a/test/libyul/yulSSAControlFlowGraph/if.yul b/test/libyul/ssa/controlFlowGraph/if.yul similarity index 100% rename from test/libyul/yulSSAControlFlowGraph/if.yul rename to test/libyul/ssa/controlFlowGraph/if.yul diff --git a/test/libyul/yulSSAControlFlowGraph/if_const.yul b/test/libyul/ssa/controlFlowGraph/if_const.yul similarity index 100% rename from test/libyul/yulSSAControlFlowGraph/if_const.yul rename to test/libyul/ssa/controlFlowGraph/if_const.yul diff --git a/test/libyul/yulSSAControlFlowGraph/nested_for.yul b/test/libyul/ssa/controlFlowGraph/nested_for.yul similarity index 100% rename from test/libyul/yulSSAControlFlowGraph/nested_for.yul rename to test/libyul/ssa/controlFlowGraph/nested_for.yul diff --git a/test/libyul/yulSSAControlFlowGraph/nested_function.yul b/test/libyul/ssa/controlFlowGraph/nested_function.yul similarity index 100% rename from test/libyul/yulSSAControlFlowGraph/nested_function.yul rename to test/libyul/ssa/controlFlowGraph/nested_function.yul diff --git a/test/libyul/yulSSAControlFlowGraph/switch.yul b/test/libyul/ssa/controlFlowGraph/switch.yul similarity index 100% rename from test/libyul/yulSSAControlFlowGraph/switch.yul rename to test/libyul/ssa/controlFlowGraph/switch.yul diff --git a/test/libyul/yulSSAControlFlowGraph/switch_const.yul b/test/libyul/ssa/controlFlowGraph/switch_const.yul similarity index 100% rename from test/libyul/yulSSAControlFlowGraph/switch_const.yul rename to test/libyul/ssa/controlFlowGraph/switch_const.yul diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 0a1c33873..46cd0eedb 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -42,7 +42,6 @@ add_executable(isoltest ../libsolidity/SMTCheckerTest.cpp ../libyul/Common.cpp ../libyul/ControlFlowGraphTest.cpp - ../libyul/SSAControlFlowGraphTest.cpp ../libyul/ControlFlowSideEffectsTest.cpp ../libyul/EVMCodeTransformTest.cpp ../libyul/FunctionSideEffects.cpp @@ -53,6 +52,8 @@ add_executable(isoltest ../libyul/YulOptimizerTest.cpp ../libyul/YulOptimizerTestCommon.cpp ../libyul/YulInterpreterTest.cpp + ../libyul/ssa/ControlFlowGraphTest.cpp + ../libyul/ssa/ControlFlowGraphTest.h ../libyul/ssa/StackLayoutGeneratorTest.cpp ../libyul/ssa/StackLayoutGeneratorTest.h ../libyul/ssa/StackShufflerTest.cpp From 67d60c015732f0d705caa51a2c69ae51a58d88e8 Mon Sep 17 00:00:00 2001 From: blishko Date: Wed, 25 Mar 2026 10:59:18 +0100 Subject: [PATCH 1204/1340] SSA: Add shuffler test This test demonstrates an inefficiency in the shuffler. We we have arguments in the right order but we need an extra copy of the top argument in the tail, the shuffler now creates a sequence of three instructions "DUP1 + SWAP2 + SWAP1" when the same result could be achieved with just two instructions "SWAP1 + DUP2". --- .../ssa/stackShuffler/keep_top_argument.stack | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 test/libyul/ssa/stackShuffler/keep_top_argument.stack diff --git a/test/libyul/ssa/stackShuffler/keep_top_argument.stack b/test/libyul/ssa/stackShuffler/keep_top_argument.stack new file mode 100644 index 000000000..5d891d329 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/keep_top_argument.stack @@ -0,0 +1,14 @@ +// We have arguments in the right order, but we need an extra copy of the top argument in the tail +initial: [v0, v1] +targetStackTop: [v0, v1] +targetStackTailSet: {v1} +targetStackSize: 3 +// ---- +// | 0 | 1 2 +// +------- +-------------- +// (initial)| v0 | v1 +// DUP1| v0 | v1 v1 +// SWAP2| v1 | v1 v0 +// SWAP1| v1 | v0 v1 +// +------- +-------------- +// (target)| {v1} | v0 v1 From c68928c9acac24f456495554ad440c18a2d79ec5 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 24 Mar 2026 16:12:21 +0100 Subject: [PATCH 1205/1340] Optimize SSA CFG Builder's trivial phi removal --- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 205 ++++++++++++++++------ libyul/backends/evm/ssa/SSACFGBuilder.h | 26 ++- 2 files changed, 179 insertions(+), 52 deletions(-) diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 01dafc2e3..59df22df4 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include #include @@ -88,73 +88,94 @@ std::unique_ptr SSACFGBuilder::build( builder.sealBlock(builder.m_currentBlock); mainGraph.block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; builder.cleanUnreachable(); + builder.applyPhiSubstitutions(); return controlFlow; } SSACFG::ValueId SSACFGBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) { - // TODO: double-check if this is sane auto const& phiInfo = m_graph.phiInfo(_phi); yulAssert(blockInfo(phiInfo.block).sealed); - // Collect upsilon values targeting this phi. + auto const phiIdx = _phi.value(); + + // early exit if this phi was already processed + if (phiIdx < m_phiSubstitution.size() && m_phiSubstitution[phiIdx].hasValue()) + return canonicalize(m_phiSubstitution[phiIdx]); + + // check triviality SSACFG::ValueId same; - for (auto const& entry: m_graph.block(phiInfo.block).entries) - for (auto const& u: m_graph.block(entry).upsilons) - if (u.phi == _phi) - { - if (u.value == same || u.value == _phi) - continue; // unique value or self-reference - if (same.hasValue()) - return _phi; // phi merges at least two distinct values -> not trivial - same = u.value; - } + if (phiIdx < m_upsilonValuesForPhi.size()) + for (auto const arg: m_upsilonValuesForPhi[phiIdx]) + { + if (arg == same || arg == _phi) + continue; // duplicate or self-reference + if (same.hasValue()) + return _phi; // two distinct values -> non-trivial + same = arg; + } + if (!same.hasValue()) - { - // This will happen for unreachable paths. - // TODO: check how best to deal with this + // phi has only self-references (unreachable cycle), or no upsilons at all same = m_graph.unreachableValue(); - } + // remove the phi from its defining block std::erase(m_graph.block(phiInfo.block).phis, _phi); + // record the substitution for deferred application to op.inputs / block exits. + if (phiIdx >= m_phiSubstitution.size()) + m_phiSubstitution.resize(phiIdx + 1); + m_phiSubstitution[phiIdx] = same; + + // update upsilon.value fields and `m_upsilonValuesForPhi` for all phis whose upsilons reference `_phi` as a value std::vector phiUses; - for (SSACFG::BlockId::ValueType blockIdValue = 0; blockIdValue < m_graph.numBlocks(); ++blockIdValue) + if (phiIdx < m_reversePhiUpsilonValues.size()) { - auto& block = m_graph.block(SSACFG::BlockId{blockIdValue}); - for (auto blockPhi: block.phis) + for (auto const targetPhi: m_reversePhiUpsilonValues[phiIdx]) { - yulAssert(blockPhi.hasValue()); - yulAssert(blockPhi != _phi, "Phis should be defined in exactly one block, _phi was erased."); - } - // Replace _phi with same in upsilon values and collect affected phis. - for (auto& u: block.upsilons) - if (u.value == _phi) + // update m_upsilonValuesForPhi[targetPhi]: _phi with same. { - u.value = same; - phiUses.push_back(u.phi); + auto& vals = m_upsilonValuesForPhi[targetPhi.value()]; + if ( + auto it = ranges::find(vals, _phi); + it != ranges::end(vals) + ) + *it = same; } - // Erase upsilons targeting _phi. - std::erase_if(block.upsilons, [_phi](auto const& u) { return u.phi == _phi; }); - for (auto opId: block.operations) - ranges::replace(m_graph.operation(opId).inputs, _phi, same); - std::visit(util::GenericVisitor{ - [_phi, same](SSACFG::BasicBlock::FunctionReturn& _functionReturn) { - ranges::replace(_functionReturn.returnValues, _phi, same); - }, - [_phi, same](SSACFG::BasicBlock::ConditionalJump& _condJump) { - if (_condJump.condition == _phi) - _condJump.condition = same; - }, - [](SSACFG::BasicBlock::Jump&) {}, - [](SSACFG::BasicBlock::MainExit&) {}, - [](SSACFG::BasicBlock::Terminated&) {} - }, block.exit); + // update the actual upsilon.value fields in targetPhi's predecessor blocks, needed for `cleanUnreachable` + if (targetPhi.value() < m_phiTargetBlocks.size()) + { + for (auto const blockId: m_phiTargetBlocks[targetPhi.value()]) + for (auto& u: m_graph.block(blockId).upsilons) + if (u.phi == targetPhi && u.value == _phi) + u.value = same; + } + // maintain reverse index: this upsilon's value changed from _phi to same. + if (same.isPhi()) + { + if (same.value() >= m_reversePhiUpsilonValues.size()) + m_reversePhiUpsilonValues.resize(same.value() + 1); + m_reversePhiUpsilonValues[same.value()].push_back(targetPhi); + } + phiUses.push_back(targetPhi); + } + m_reversePhiUpsilonValues[phiIdx].clear(); } - for (auto& currentVariableDefs: m_currentDef | ranges::views::values) - ranges::replace(currentVariableDefs, _phi, same); - for (auto phiUse: phiUses) + // now erase all upsilons targeting _phi + // m_upsilonValuesForPhi[phiIdx] is now stale but _phi is gone and never consulted again. + if (phiIdx < m_phiTargetBlocks.size()) + { + for (auto const blockId: m_phiTargetBlocks[phiIdx]) + std::erase_if(m_graph.block(blockId).upsilons, [_phi](auto const& u) { return u.phi == _phi; }); + m_phiTargetBlocks[phiIdx].clear(); + } + + // op.inputs, block exits, and m_currentDef are updated lazily: + // - readVariable() calls canonicalize() before returning any phi def. + // - applyPhiSubstitutions() does a single O(B×(U+O×I)) sweep at the end of build. + + for (auto const phiUse: phiUses) tryRemoveTrivialPhi(phiUse); return same; @@ -192,6 +213,7 @@ void SSACFGBuilder::cleanUnreachable() // - upsilons in unreachable blocks (their block will never execute), or // - upsilons with an unreachable value (product of earlier trivial-phi removal). // Collect the affected target phis so we can attempt trivial-phi removal afterward. + // Also remove the corresponding entries from the index to keep it consistent. std::vector maybeTrivialPhi; for (SSACFG::BlockId blockId{0}; blockId.value < m_graph.numBlocks(); ++blockId.value) { @@ -200,7 +222,29 @@ void SSACFGBuilder::cleanUnreachable() for (auto const& u: block.upsilons) if (!isReachable || u.value.isUnreachable()) + { maybeTrivialPhi.push_back(u.phi); + auto const phiIdx = u.phi.value(); + if (phiIdx < m_upsilonValuesForPhi.size()) + { + auto& vals = m_upsilonValuesForPhi[phiIdx]; + auto const it = ranges::find(vals, u.value); + if (it != ranges::end(vals)) + vals.erase(it); + } + // maintain reverse index: remove this upsilon from the reverse mapping + if (u.value.isPhi()) + { + auto const valIdx = u.value.value(); + if (valIdx < m_reversePhiUpsilonValues.size()) + { + auto& rev = m_reversePhiUpsilonValues[valIdx]; + auto const it = ranges::find(rev, u.phi); + if (it != ranges::end(rev)) + rev.erase(it); + } + } + } std::erase_if(block.upsilons, [&](SSACFG::Upsilon const& u) { return !isReachable || u.value.isUnreachable(); @@ -256,6 +300,7 @@ void SSACFGBuilder::buildFunctionGraph( // Artificial explicit function exit (`leave`) at the end of the body. builder(Leave{debugDataOf(*_functionDefinition)}); builder.cleanUnreachable(); + builder.applyPhiSubstitutions(); } void SSACFGBuilder::operator()(ExpressionStatement const& _expressionStatement) @@ -610,8 +655,9 @@ SSACFG::ValueId SSACFGBuilder::zero() SSACFG::ValueId SSACFGBuilder::readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block) { - if (auto const& def = currentDef(_variable, _block)) - return *def; + auto const& def = currentDef(_variable, _block); + if (def.hasValue()) + return canonicalize(def); return readVariableRecursive(_variable, _block); } @@ -659,6 +705,67 @@ void SSACFGBuilder::emitUpsilon(SSACFG::BlockId _block, SSACFG::ValueId _value, { yulAssert(_phi.isPhi()); m_graph.block(_block).upsilons.emplace_back(SSACFG::Upsilon{_value, _phi}); + + // maintain m_upsilonValuesForPhi (triviality check index) + auto const phiIdx = _phi.value(); + if (phiIdx >= m_upsilonValuesForPhi.size()) + m_upsilonValuesForPhi.resize(phiIdx + 1); + m_upsilonValuesForPhi[phiIdx].push_back(_value); + + // maintain m_phiTargetBlocks (to erase upsilons targeting _phi) + if (phiIdx >= m_phiTargetBlocks.size()) + m_phiTargetBlocks.resize(phiIdx + 1); + m_phiTargetBlocks[phiIdx].push_back(_block); + + // maintain m_reversePhiUpsilonValues (find dependency chains from _value) + if (_value.isPhi()) + { + auto const valIdx = _value.value(); + if (valIdx >= m_reversePhiUpsilonValues.size()) + m_reversePhiUpsilonValues.resize(valIdx + 1); + m_reversePhiUpsilonValues[valIdx].push_back(_phi); + } +} + +SSACFG::ValueId SSACFGBuilder::canonicalize(SSACFG::ValueId _v) +{ + if (!_v.isPhi()) + return _v; + auto const idx = _v.value(); + if (idx >= m_phiSubstitution.size()) + return _v; + auto& sub = m_phiSubstitution[idx]; + if (!sub.hasValue()) + return _v; + sub = canonicalize(sub); + return sub; +} + +void SSACFGBuilder::applyPhiSubstitutions() +{ + if (m_phiSubstitution.empty()) + return; + + for (SSACFG::BlockId blockId{0}; blockId.value < m_graph.numBlocks(); ++blockId.value) + { + auto& block = m_graph.block(blockId); + for (auto& u: block.upsilons) + u.value = canonicalize(u.value); + for (auto const opId: block.operations) + for (auto& input: m_graph.operation(opId).inputs) + input = canonicalize(input); + std::visit(util::GenericVisitor{ + [&](SSACFG::BasicBlock::FunctionReturn& r) + { + for (auto& v: r.returnValues) + v = canonicalize(v); + }, + [&](SSACFG::BasicBlock::ConditionalJump& c) { c.condition = canonicalize(c.condition); }, + [](SSACFG::BasicBlock::Jump&) {}, + [](SSACFG::BasicBlock::MainExit&) {}, + [](SSACFG::BasicBlock::Terminated&) {} + }, block.exit); + } } void SSACFGBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value) diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index 091bb0ba8..1ec35e00f 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -40,6 +40,7 @@ #include #include #include +#include namespace solidity::yul::ssa { @@ -91,6 +92,11 @@ class SSACFGBuilder std::vector visitFunctionCall(FunctionCall const& _call); void registerFunctionDefinition(FunctionDefinition const& _functionDefinition); void buildFunctionGraph(Scope::Function const* _function, FunctionDefinition const* _functionDefinition); + // performs path compression on substitution chains: phi1->phi2->literal becomes phi1->literal + SSACFG::ValueId canonicalize(SSACFG::ValueId _v); + // replaces phi references in operation inputs, block exits, and upsilon values with their final substitution + // targets in a single pass over the graph, after all trivial phi removals are complete + void applyPhiSubstitutions(); SSACFG::ValueId zero(); SSACFG::ValueId readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block); @@ -133,18 +139,32 @@ class SSACFGBuilder } void sealBlock(SSACFG::BlockId _block); - std::map< + std::unordered_map< Scope::Variable const*, - std::vector> + std::vector > m_currentDef; + /// Values of upsilons targeting phi_id: m_upsilonValuesForPhi[phi_id] = {upsilon1, upsilon2, ...}, + /// populated by calls to `emitUpsilon` + std::vector> m_upsilonValuesForPhi; + + /// phi_id -> canonical replacement (empty/default if not yet substituted) + std::vector m_phiSubstitution; + + /// phi_id -> block IDs that contain upsilons targeting this phi + std::vector> m_phiTargetBlocks; + + /// phi_id -> phis whose upsilon values include this phi_id, e.g.: + /// m_reversePhiUpsilonValues[phi_A] = {phi_X, phi_Y, ...}; phi_X and phi_Y have upsilons whose value is phi_A + std::vector> m_reversePhiUpsilonValues; + struct ForLoopInfo { SSACFG::BlockId breakBlock; SSACFG::BlockId continueBlock; }; std::stack m_forLoopInfo; - std::optional& currentDef(Scope::Variable const& _variable, SSACFG::BlockId _block) + SSACFG::ValueId& currentDef(Scope::Variable const& _variable, SSACFG::BlockId _block) { auto& varDefs = m_currentDef[&_variable]; if (varDefs.size() <= _block.value) From 3f38cc8be10fec3ad9a50a5b2be511dfd822ebd9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 24 Mar 2026 16:35:01 +0100 Subject: [PATCH 1206/1340] Extract trivial phi elimination from ssa cfg builder --- libyul/CMakeLists.txt | 2 + libyul/backends/evm/ssa/SSACFGBuilder.cpp | 241 +-------------- libyul/backends/evm/ssa/SSACFGBuilder.h | 21 -- .../evm/ssa/SSACFGTrivialPhiEliminator.cpp | 285 ++++++++++++++++++ .../evm/ssa/SSACFGTrivialPhiEliminator.h | 34 +++ 5 files changed, 326 insertions(+), 257 deletions(-) create mode 100644 libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.cpp create mode 100644 libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 898f67946..2e0f599aa 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -91,6 +91,8 @@ add_library(yul backends/evm/ssa/SSACFGBuilder.cpp backends/evm/ssa/SSACFGBuilder.h backends/evm/ssa/SSACFGDebugInfo.h + backends/evm/ssa/SSACFGTrivialPhiEliminator.cpp + backends/evm/ssa/SSACFGTrivialPhiEliminator.h backends/evm/ssa/SSACFGTypes.h backends/evm/ssa/Stack.cpp backends/evm/ssa/Stack.h diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 59df22df4..7c9ee1104 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -20,6 +20,7 @@ */ #include +#include #include @@ -32,7 +33,6 @@ #include #include -#include #include #include #include @@ -87,173 +87,10 @@ std::unique_ptr SSACFGBuilder::build( if (!builder.blockInfo(builder.m_currentBlock).sealed) builder.sealBlock(builder.m_currentBlock); mainGraph.block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; - builder.cleanUnreachable(); - builder.applyPhiSubstitutions(); + eliminateTrivialPhis(mainGraph); return controlFlow; } -SSACFG::ValueId SSACFGBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi) -{ - auto const& phiInfo = m_graph.phiInfo(_phi); - yulAssert(blockInfo(phiInfo.block).sealed); - - auto const phiIdx = _phi.value(); - - // early exit if this phi was already processed - if (phiIdx < m_phiSubstitution.size() && m_phiSubstitution[phiIdx].hasValue()) - return canonicalize(m_phiSubstitution[phiIdx]); - - // check triviality - SSACFG::ValueId same; - if (phiIdx < m_upsilonValuesForPhi.size()) - for (auto const arg: m_upsilonValuesForPhi[phiIdx]) - { - if (arg == same || arg == _phi) - continue; // duplicate or self-reference - if (same.hasValue()) - return _phi; // two distinct values -> non-trivial - same = arg; - } - - if (!same.hasValue()) - // phi has only self-references (unreachable cycle), or no upsilons at all - same = m_graph.unreachableValue(); - - // remove the phi from its defining block - std::erase(m_graph.block(phiInfo.block).phis, _phi); - - // record the substitution for deferred application to op.inputs / block exits. - if (phiIdx >= m_phiSubstitution.size()) - m_phiSubstitution.resize(phiIdx + 1); - m_phiSubstitution[phiIdx] = same; - - // update upsilon.value fields and `m_upsilonValuesForPhi` for all phis whose upsilons reference `_phi` as a value - std::vector phiUses; - if (phiIdx < m_reversePhiUpsilonValues.size()) - { - for (auto const targetPhi: m_reversePhiUpsilonValues[phiIdx]) - { - // update m_upsilonValuesForPhi[targetPhi]: _phi with same. - { - auto& vals = m_upsilonValuesForPhi[targetPhi.value()]; - if ( - auto it = ranges::find(vals, _phi); - it != ranges::end(vals) - ) - *it = same; - } - // update the actual upsilon.value fields in targetPhi's predecessor blocks, needed for `cleanUnreachable` - if (targetPhi.value() < m_phiTargetBlocks.size()) - { - for (auto const blockId: m_phiTargetBlocks[targetPhi.value()]) - for (auto& u: m_graph.block(blockId).upsilons) - if (u.phi == targetPhi && u.value == _phi) - u.value = same; - } - // maintain reverse index: this upsilon's value changed from _phi to same. - if (same.isPhi()) - { - if (same.value() >= m_reversePhiUpsilonValues.size()) - m_reversePhiUpsilonValues.resize(same.value() + 1); - m_reversePhiUpsilonValues[same.value()].push_back(targetPhi); - } - phiUses.push_back(targetPhi); - } - m_reversePhiUpsilonValues[phiIdx].clear(); - } - - // now erase all upsilons targeting _phi - // m_upsilonValuesForPhi[phiIdx] is now stale but _phi is gone and never consulted again. - if (phiIdx < m_phiTargetBlocks.size()) - { - for (auto const blockId: m_phiTargetBlocks[phiIdx]) - std::erase_if(m_graph.block(blockId).upsilons, [_phi](auto const& u) { return u.phi == _phi; }); - m_phiTargetBlocks[phiIdx].clear(); - } - - // op.inputs, block exits, and m_currentDef are updated lazily: - // - readVariable() calls canonicalize() before returning any phi def. - // - applyPhiSubstitutions() does a single O(B×(U+O×I)) sweep at the end of build. - - for (auto const phiUse: phiUses) - tryRemoveTrivialPhi(phiUse); - - return same; -} - -/// Removes edges to blocks that are not reachable. -void SSACFGBuilder::cleanUnreachable() -{ - // Determine which blocks are reachable from the entry. - util::BreadthFirstSearch reachabilityCheck{{m_graph.entry}}; - reachabilityCheck.run([&](SSACFG::BlockId _blockId, auto&& _addChild) { - auto const& block = m_graph.block(_blockId); - visit(util::GenericVisitor{ - [&](SSACFG::BasicBlock::Jump const& _jump) { - _addChild(_jump.target); - }, - [&](SSACFG::BasicBlock::ConditionalJump const& _jump) { - _addChild(_jump.zero); - _addChild(_jump.nonZero); - }, - [](SSACFG::BasicBlock::FunctionReturn const&) {}, - [](SSACFG::BasicBlock::Terminated const&) {}, - [](SSACFG::BasicBlock::MainExit const&) {} - }, block.exit); - }); - - // Remove unreachable predecessor entries. - for (SSACFG::BlockId blockId: reachabilityCheck.visited) - { - auto& block = m_graph.block(blockId); - std::erase_if(block.entries, [&](auto const& entry) { return !reachabilityCheck.visited.contains(entry); }); - } - - // Remove upsilons that are now invalid: - // - upsilons in unreachable blocks (their block will never execute), or - // - upsilons with an unreachable value (product of earlier trivial-phi removal). - // Collect the affected target phis so we can attempt trivial-phi removal afterward. - // Also remove the corresponding entries from the index to keep it consistent. - std::vector maybeTrivialPhi; - for (SSACFG::BlockId blockId{0}; blockId.value < m_graph.numBlocks(); ++blockId.value) - { - auto& block = m_graph.block(blockId); - bool const isReachable = reachabilityCheck.visited.contains(blockId); - - for (auto const& u: block.upsilons) - if (!isReachable || u.value.isUnreachable()) - { - maybeTrivialPhi.push_back(u.phi); - auto const phiIdx = u.phi.value(); - if (phiIdx < m_upsilonValuesForPhi.size()) - { - auto& vals = m_upsilonValuesForPhi[phiIdx]; - auto const it = ranges::find(vals, u.value); - if (it != ranges::end(vals)) - vals.erase(it); - } - // maintain reverse index: remove this upsilon from the reverse mapping - if (u.value.isPhi()) - { - auto const valIdx = u.value.value(); - if (valIdx < m_reversePhiUpsilonValues.size()) - { - auto& rev = m_reversePhiUpsilonValues[valIdx]; - auto const it = ranges::find(rev, u.phi); - if (it != ranges::end(rev)) - rev.erase(it); - } - } - } - - std::erase_if(block.upsilons, [&](SSACFG::Upsilon const& u) { - return !isReachable || u.value.isUnreachable(); - }); - } - - for (auto const phi: maybeTrivialPhi) - tryRemoveTrivialPhi(phi); -} void SSACFGBuilder::buildFunctionGraph( Scope::Function const* _function, @@ -299,8 +136,7 @@ void SSACFGBuilder::buildFunctionGraph( cfg.exits.insert(builder.m_currentBlock); // Artificial explicit function exit (`leave`) at the end of the body. builder(Leave{debugDataOf(*_functionDefinition)}); - builder.cleanUnreachable(); - builder.applyPhiSubstitutions(); + eliminateTrivialPhis(cfg); } void SSACFGBuilder::operator()(ExpressionStatement const& _expressionStatement) @@ -657,7 +493,7 @@ SSACFG::ValueId SSACFGBuilder::readVariable(Scope::Variable const& _variable, SS { auto const& def = currentDef(_variable, _block); if (def.hasValue()) - return canonicalize(def); + return def; return readVariableRecursive(_variable, _block); } @@ -683,10 +519,7 @@ SSACFG::ValueId SSACFGBuilder::readVariableRecursive(Scope::Variable const& _var val = m_graph.newPhi(_block); block.phis.push_back(val); writeVariable(_variable, _block, val); - // we call tryRemoveTrivialPhi explicitly opposed to what is presented in Algorithm 2, as our implementation - // does not call it in addPhiOperands to avoid removing phis in unsealed blocks addPhiOperands(_variable, val); - val = tryRemoveTrivialPhi(val); } writeVariable(_variable, _block, val); return val; @@ -705,67 +538,6 @@ void SSACFGBuilder::emitUpsilon(SSACFG::BlockId _block, SSACFG::ValueId _value, { yulAssert(_phi.isPhi()); m_graph.block(_block).upsilons.emplace_back(SSACFG::Upsilon{_value, _phi}); - - // maintain m_upsilonValuesForPhi (triviality check index) - auto const phiIdx = _phi.value(); - if (phiIdx >= m_upsilonValuesForPhi.size()) - m_upsilonValuesForPhi.resize(phiIdx + 1); - m_upsilonValuesForPhi[phiIdx].push_back(_value); - - // maintain m_phiTargetBlocks (to erase upsilons targeting _phi) - if (phiIdx >= m_phiTargetBlocks.size()) - m_phiTargetBlocks.resize(phiIdx + 1); - m_phiTargetBlocks[phiIdx].push_back(_block); - - // maintain m_reversePhiUpsilonValues (find dependency chains from _value) - if (_value.isPhi()) - { - auto const valIdx = _value.value(); - if (valIdx >= m_reversePhiUpsilonValues.size()) - m_reversePhiUpsilonValues.resize(valIdx + 1); - m_reversePhiUpsilonValues[valIdx].push_back(_phi); - } -} - -SSACFG::ValueId SSACFGBuilder::canonicalize(SSACFG::ValueId _v) -{ - if (!_v.isPhi()) - return _v; - auto const idx = _v.value(); - if (idx >= m_phiSubstitution.size()) - return _v; - auto& sub = m_phiSubstitution[idx]; - if (!sub.hasValue()) - return _v; - sub = canonicalize(sub); - return sub; -} - -void SSACFGBuilder::applyPhiSubstitutions() -{ - if (m_phiSubstitution.empty()) - return; - - for (SSACFG::BlockId blockId{0}; blockId.value < m_graph.numBlocks(); ++blockId.value) - { - auto& block = m_graph.block(blockId); - for (auto& u: block.upsilons) - u.value = canonicalize(u.value); - for (auto const opId: block.operations) - for (auto& input: m_graph.operation(opId).inputs) - input = canonicalize(input); - std::visit(util::GenericVisitor{ - [&](SSACFG::BasicBlock::FunctionReturn& r) - { - for (auto& v: r.returnValues) - v = canonicalize(v); - }, - [&](SSACFG::BasicBlock::ConditionalJump& c) { c.condition = canonicalize(c.condition); }, - [](SSACFG::BasicBlock::Jump&) {}, - [](SSACFG::BasicBlock::MainExit&) {}, - [](SSACFG::BasicBlock::Terminated&) {} - }, block.exit); - } } void SSACFGBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value) @@ -804,15 +576,12 @@ Scope::Variable const& SSACFGBuilder::lookupVariable(YulName _name) const void SSACFGBuilder::sealBlock(SSACFG::BlockId _block) { - // this method deviates from Algorithm 4 in the reference paper, - // as it would lead to tryRemoveTrivialPhi being called on unsealed blocks auto& info = blockInfo(_block); yulAssert(!info.sealed, "Trying to seal already sealed block."); + // emit upsilons for all incomplete phis before marking the block as sealed for (auto&& [phi, variable] : info.incompletePhis) addPhiOperands(variable, phi); info.sealed = true; - for (auto& [phi, _]: info.incompletePhis) - phi = tryRemoveTrivialPhi(phi); } diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index 1ec35e00f..e8c35652c 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -86,17 +86,10 @@ class SSACFGBuilder SSACFG::ValueId operator()(Literal const& _literal); private: - void cleanUnreachable(); - SSACFG::ValueId tryRemoveTrivialPhi(SSACFG::ValueId _phi); void assign(std::vector> _variables, Expression const* _expression); std::vector visitFunctionCall(FunctionCall const& _call); void registerFunctionDefinition(FunctionDefinition const& _functionDefinition); void buildFunctionGraph(Scope::Function const* _function, FunctionDefinition const* _functionDefinition); - // performs path compression on substitution chains: phi1->phi2->literal becomes phi1->literal - SSACFG::ValueId canonicalize(SSACFG::ValueId _v); - // replaces phi references in operation inputs, block exits, and upsilon values with their final substitution - // targets in a single pass over the graph, after all trivial phi removals are complete - void applyPhiSubstitutions(); SSACFG::ValueId zero(); SSACFG::ValueId readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block); @@ -144,20 +137,6 @@ class SSACFGBuilder std::vector > m_currentDef; - /// Values of upsilons targeting phi_id: m_upsilonValuesForPhi[phi_id] = {upsilon1, upsilon2, ...}, - /// populated by calls to `emitUpsilon` - std::vector> m_upsilonValuesForPhi; - - /// phi_id -> canonical replacement (empty/default if not yet substituted) - std::vector m_phiSubstitution; - - /// phi_id -> block IDs that contain upsilons targeting this phi - std::vector> m_phiTargetBlocks; - - /// phi_id -> phis whose upsilon values include this phi_id, e.g.: - /// m_reversePhiUpsilonValues[phi_A] = {phi_X, phi_Y, ...}; phi_X and phi_Y have upsilons whose value is phi_A - std::vector> m_reversePhiUpsilonValues; - struct ForLoopInfo { SSACFG::BlockId breakBlock; SSACFG::BlockId continueBlock; diff --git a/libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.cpp b/libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.cpp new file mode 100644 index 000000000..d90f9754b --- /dev/null +++ b/libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.cpp @@ -0,0 +1,285 @@ +/* + 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 + +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +using namespace solidity; +using namespace solidity::yul; +using namespace solidity::yul::ssa; + +namespace +{ + +struct TrivialPhiEliminator +{ + SSACFG& cfg; + + // phi_id -> values of upsilons targeting this phi + std::vector> upsilonValuesForPhi; + // phi_id -> blocks containing upsilons targeting this phi + std::vector> phiTargetBlocks; + // phi_id -> phis whose upsilon values reference this phi + std::vector> reversePhiUpsilonValues; + // phi_id -> canonical replacement (default = no substitution) + std::vector substitution; + + explicit TrivialPhiEliminator(SSACFG& _cfg): cfg(_cfg) {} + + void run() + { + cleanUnreachable(); + buildIndices(); + substituteDeadPhis(); + + // run elimination repeatedly until convergence + auto substitutionsBeforeEliminateAll = static_cast(ranges::count_if(substitution, [](auto const& s) { return s.hasValue(); })); + auto substitutionsAfterEliminateAll = substitutionsBeforeEliminateAll; + do + { + substitutionsBeforeEliminateAll = substitutionsAfterEliminateAll; + eliminateAll(); + substitutionsAfterEliminateAll = static_cast(ranges::count_if(substitution, [](auto const& s) { return s.hasValue(); })); + } while (substitutionsAfterEliminateAll > substitutionsBeforeEliminateAll); + applySubstitutions(); + } + +private: + void cleanUnreachable() + { + util::BreadthFirstSearch reachabilityCheck{{cfg.entry}}; + reachabilityCheck.run([&](SSACFG::BlockId _blockId, auto&& _addChild) { + auto const& block = cfg.block(_blockId); + visit(util::GenericVisitor{ + [&](SSACFG::BasicBlock::Jump const& _jump) { _addChild(_jump.target); }, + [&](SSACFG::BasicBlock::ConditionalJump const& _jump) { + _addChild(_jump.zero); + _addChild(_jump.nonZero); + }, + [](SSACFG::BasicBlock::FunctionReturn const&) {}, + [](SSACFG::BasicBlock::Terminated const&) {}, + [](SSACFG::BasicBlock::MainExit const&) {} + }, block.exit); + }); + + for (SSACFG::BlockId blockId: reachabilityCheck.visited) + { + auto& block = cfg.block(blockId); + std::erase_if(block.entries, [&](auto const& entry) { + return !reachabilityCheck.visited.contains(entry); + }); + } + + for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) + { + auto& block = cfg.block(blockId); + bool const isReachable = reachabilityCheck.visited.contains(blockId); + std::erase_if(block.upsilons, [&](SSACFG::Upsilon const& u) { + return !isReachable || u.value.isUnreachable(); + }); + } + } + + void buildIndices() + { + for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) + { + auto const& block = cfg.block(blockId); + for (auto const& u: block.upsilons) + { + auto const phiIdx = u.phi.value(); + if (phiIdx >= upsilonValuesForPhi.size()) + { + upsilonValuesForPhi.resize(phiIdx + 1); + phiTargetBlocks.resize(phiIdx + 1); + } + if (phiIdx >= reversePhiUpsilonValues.size()) + reversePhiUpsilonValues.resize(phiIdx + 1); + upsilonValuesForPhi[phiIdx].push_back(u.value); + phiTargetBlocks[phiIdx].push_back(blockId); + if (u.value.isPhi()) + { + auto const valIdx = u.value.value(); + if (valIdx >= reversePhiUpsilonValues.size()) + reversePhiUpsilonValues.resize(valIdx + 1); + reversePhiUpsilonValues[valIdx].push_back(u.phi); + } + } + } + substitution.resize(std::max(upsilonValuesForPhi.size(), size_t{1})); + } + + /// Phis that have no upsilons targeting them are dead — either in unreachable blocks + /// or orphaned from cycle-breaking. + /// Replace references to them with unreachableValue in the upsilon value index so they don't block triviality + /// detection. + void substituteDeadPhis() + { + auto const unreachable = cfg.unreachableValue(); + for (auto& upsilonValues: upsilonValuesForPhi) + for (auto& val: upsilonValues) + if (val.isPhi()) + { + auto const idx = val.value(); + bool const hasUpsilons = idx < upsilonValuesForPhi.size() && !upsilonValuesForPhi[idx].empty(); + if (!hasUpsilons) + val = unreachable; + } + } + + void eliminateAll() + { + for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) + { + auto const phis = cfg.block(blockId).phis; + for (auto const phi: phis) + tryRemove(phi); + } + } + + void tryRemove(SSACFG::ValueId _phi) + { + auto const phiIdx = _phi.value(); + + // early exit if this phi was already processed + if (phiIdx < substitution.size() && substitution[phiIdx].hasValue()) + return; + + // check triviality and canonicalize arguments to account for already-substituted phis; + // skip self-references and unreachable values + SSACFG::ValueId same; + if (phiIdx < upsilonValuesForPhi.size()) + for (auto const arg: upsilonValuesForPhi[phiIdx]) + { + auto const resolved = canonicalize(arg); + if (resolved == same || resolved == _phi || resolved.isUnreachable()) + continue; + if (same.hasValue()) + return; // non-trivial + same = resolved; + } + + if (!same.hasValue()) + // phi has only self-references (unreachable cycle), or no upsilons at all + same = cfg.unreachableValue(); + + // remove the phi from its defining block + std::erase(cfg.block(cfg.phiInfo(_phi).block).phis, _phi); + + // record the substitution + if (phiIdx >= substitution.size()) + substitution.resize(phiIdx + 1); + substitution[phiIdx] = same; + + // update upsilon.value fields and `upsilonValuesForPhi` for all phis whose upsilons reference `_phi` as a value + std::vector cascades; + if (phiIdx < reversePhiUpsilonValues.size()) + { + for (auto const targetPhi: reversePhiUpsilonValues[phiIdx]) + { + // update upsilonValuesForPhi[targetPhi]: _phi with same + auto& vals = upsilonValuesForPhi[targetPhi.value()]; + ranges::replace(vals, _phi, same); + if (targetPhi.value() < phiTargetBlocks.size()) + for (auto const blockId: phiTargetBlocks[targetPhi.value()]) + for (auto& u: cfg.block(blockId).upsilons) + if (u.phi == targetPhi && u.value == _phi) + u.value = same; + // maintain reverse index + if (same.isPhi()) + { + if (same.value() >= reversePhiUpsilonValues.size()) + reversePhiUpsilonValues.resize(same.value() + 1); + reversePhiUpsilonValues[same.value()].push_back(targetPhi); + } + cascades.push_back(targetPhi); + } + reversePhiUpsilonValues[phiIdx].clear(); + } + + // erase all upsilons targeting the removed phi. + if (phiIdx < phiTargetBlocks.size()) + { + for (auto const blockId: phiTargetBlocks[phiIdx]) + std::erase_if(cfg.block(blockId).upsilons, [_phi](auto const& u) { return u.phi == _phi; }); + phiTargetBlocks[phiIdx].clear(); + } + + for (auto const cascadingPhi: cascades) + tryRemove(cascadingPhi); + } + + SSACFG::ValueId canonicalize(SSACFG::ValueId const _v) + { + if (!_v.isPhi()) + return _v; + auto const idx = _v.value(); + if (idx >= substitution.size()) + return _v; + auto& sub = substitution[idx]; + if (!sub.hasValue()) + return _v; + // path compression + sub = canonicalize(sub); + return sub; + } + + void applySubstitutions() + { + if (!ranges::any_of(substitution, [](ValueId const& _sub) { return _sub.hasValue(); })) + return; + + for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) + { + auto& block = cfg.block(blockId); + for (auto& u: block.upsilons) + u.value = canonicalize(u.value); + for (auto const opId: block.operations) + for (auto& input: cfg.operation(opId).inputs) + input = canonicalize(input); + std::visit(util::GenericVisitor{ + [&](SSACFG::BasicBlock::FunctionReturn& r) { + for (auto& v: r.returnValues) + v = canonicalize(v); + }, + [&](SSACFG::BasicBlock::ConditionalJump& c) { c.condition = canonicalize(c.condition); }, + [](SSACFG::BasicBlock::Jump&) {}, + [](SSACFG::BasicBlock::MainExit&) {}, + [](SSACFG::BasicBlock::Terminated&) {} + }, block.exit); + } + } +}; + +} + +void ssa::eliminateTrivialPhis(SSACFG& _cfg) +{ + TrivialPhiEliminator(_cfg).run(); +} diff --git a/libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.h b/libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.h new file mode 100644 index 000000000..a4929d7b1 --- /dev/null +++ b/libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.h @@ -0,0 +1,34 @@ +/* + 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 +/** + * Removes trivial phis and unreachable blocks from an SSA CFG. + * + * A phi is trivial if all its upsilon operands provide the same value (modulo self-references). + * Removal may cascade: eliminating one trivial phi can make others trivial. + */ +#pragma once + +namespace solidity::yul::ssa +{ + +class SSACFG; + +/// Removes unreachable blocks and trivial phis from the SSA CFG +void eliminateTrivialPhis(SSACFG& _cfg); + +} From adfeac861e9f562c0d2977aa00021efebfac6d0b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:07:17 +0100 Subject: [PATCH 1207/1340] Move TrivialPhiEliminator into ssa::transform namespace --- libyul/CMakeLists.txt | 4 ++-- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 7 ++++--- .../TrivialPhiEliminator.cpp} | 4 ++-- .../TrivialPhiEliminator.h} | 3 +++ 4 files changed, 11 insertions(+), 7 deletions(-) rename libyul/backends/evm/ssa/{SSACFGTrivialPhiEliminator.cpp => transform/TrivialPhiEliminator.cpp} (98%) rename libyul/backends/evm/ssa/{SSACFGTrivialPhiEliminator.h => transform/TrivialPhiEliminator.h} (97%) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 2e0f599aa..01ce0e109 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -91,8 +91,6 @@ add_library(yul backends/evm/ssa/SSACFGBuilder.cpp backends/evm/ssa/SSACFGBuilder.h backends/evm/ssa/SSACFGDebugInfo.h - backends/evm/ssa/SSACFGTrivialPhiEliminator.cpp - backends/evm/ssa/SSACFGTrivialPhiEliminator.h backends/evm/ssa/SSACFGTypes.h backends/evm/ssa/Stack.cpp backends/evm/ssa/Stack.h @@ -107,6 +105,8 @@ add_library(yul backends/evm/ssa/io/DotExporterBase.h backends/evm/ssa/io/JSONExporter.cpp backends/evm/ssa/io/JSONExporter.h + backends/evm/ssa/transform/TrivialPhiEliminator.cpp + backends/evm/ssa/transform/TrivialPhiEliminator.h backends/evm/ssa/traversal/ForwardTopologicalSort.cpp backends/evm/ssa/traversal/ForwardTopologicalSort.h optimiser/ASTCopier.cpp diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 7c9ee1104..49ed036b1 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -20,7 +20,8 @@ */ #include -#include + +#include #include @@ -87,7 +88,7 @@ std::unique_ptr SSACFGBuilder::build( if (!builder.blockInfo(builder.m_currentBlock).sealed) builder.sealBlock(builder.m_currentBlock); mainGraph.block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; - eliminateTrivialPhis(mainGraph); + transform::eliminateTrivialPhis(mainGraph); return controlFlow; } @@ -136,7 +137,7 @@ void SSACFGBuilder::buildFunctionGraph( cfg.exits.insert(builder.m_currentBlock); // Artificial explicit function exit (`leave`) at the end of the body. builder(Leave{debugDataOf(*_functionDefinition)}); - eliminateTrivialPhis(cfg); + transform::eliminateTrivialPhis(cfg); } void SSACFGBuilder::operator()(ExpressionStatement const& _expressionStatement) diff --git a/libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.cpp b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp similarity index 98% rename from libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.cpp rename to libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp index d90f9754b..b6d28e6f4 100644 --- a/libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.cpp +++ b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp @@ -16,7 +16,7 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#include #include @@ -279,7 +279,7 @@ struct TrivialPhiEliminator } -void ssa::eliminateTrivialPhis(SSACFG& _cfg) +void transform::eliminateTrivialPhis(SSACFG& _cfg) { TrivialPhiEliminator(_cfg).run(); } diff --git a/libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.h b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.h similarity index 97% rename from libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.h rename to libyul/backends/evm/ssa/transform/TrivialPhiEliminator.h index a4929d7b1..d50d95e19 100644 --- a/libyul/backends/evm/ssa/SSACFGTrivialPhiEliminator.h +++ b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.h @@ -28,7 +28,10 @@ namespace solidity::yul::ssa class SSACFG; +namespace transform +{ /// Removes unreachable blocks and trivial phis from the SSA CFG void eliminateTrivialPhis(SSACFG& _cfg); +} } From 764ee9c93e131d3172d072eef2472fc944389823 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:07:55 +0100 Subject: [PATCH 1208/1340] Extract unreachable block cleaning into its own transform pass --- libyul/CMakeLists.txt | 2 + libyul/backends/evm/ssa/SSACFGBuilder.cpp | 3 + .../ssa/transform/TrivialPhiEliminator.cpp | 36 ++--------- .../evm/ssa/transform/TrivialPhiEliminator.h | 4 +- .../ssa/transform/UnreachableBlockCleaner.cpp | 59 +++++++++++++++++++ .../ssa/transform/UnreachableBlockCleaner.h | 34 +++++++++++ 6 files changed, 104 insertions(+), 34 deletions(-) create mode 100644 libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp create mode 100644 libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 01ce0e109..8e8ec56df 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -107,6 +107,8 @@ add_library(yul backends/evm/ssa/io/JSONExporter.h backends/evm/ssa/transform/TrivialPhiEliminator.cpp backends/evm/ssa/transform/TrivialPhiEliminator.h + backends/evm/ssa/transform/UnreachableBlockCleaner.cpp + backends/evm/ssa/transform/UnreachableBlockCleaner.h backends/evm/ssa/traversal/ForwardTopologicalSort.cpp backends/evm/ssa/traversal/ForwardTopologicalSort.h optimiser/ASTCopier.cpp diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 49ed036b1..63c014cfd 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -22,6 +22,7 @@ #include #include +#include #include @@ -88,6 +89,7 @@ std::unique_ptr SSACFGBuilder::build( if (!builder.blockInfo(builder.m_currentBlock).sealed) builder.sealBlock(builder.m_currentBlock); mainGraph.block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; + transform::cleanUnreachableBlocks(mainGraph); transform::eliminateTrivialPhis(mainGraph); return controlFlow; } @@ -137,6 +139,7 @@ void SSACFGBuilder::buildFunctionGraph( cfg.exits.insert(builder.m_currentBlock); // Artificial explicit function exit (`leave`) at the end of the body. builder(Leave{debugDataOf(*_functionDefinition)}); + transform::cleanUnreachableBlocks(cfg); transform::eliminateTrivialPhis(cfg); } diff --git a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp index b6d28e6f4..b913a5fc8 100644 --- a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp +++ b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp @@ -20,7 +20,6 @@ #include -#include #include #include @@ -54,7 +53,7 @@ struct TrivialPhiEliminator void run() { - cleanUnreachable(); + cleanUnreachableUpsilons(); buildIndices(); substituteDeadPhis(); @@ -71,39 +70,12 @@ struct TrivialPhiEliminator } private: - void cleanUnreachable() + void cleanUnreachableUpsilons() { - util::BreadthFirstSearch reachabilityCheck{{cfg.entry}}; - reachabilityCheck.run([&](SSACFG::BlockId _blockId, auto&& _addChild) { - auto const& block = cfg.block(_blockId); - visit(util::GenericVisitor{ - [&](SSACFG::BasicBlock::Jump const& _jump) { _addChild(_jump.target); }, - [&](SSACFG::BasicBlock::ConditionalJump const& _jump) { - _addChild(_jump.zero); - _addChild(_jump.nonZero); - }, - [](SSACFG::BasicBlock::FunctionReturn const&) {}, - [](SSACFG::BasicBlock::Terminated const&) {}, - [](SSACFG::BasicBlock::MainExit const&) {} - }, block.exit); - }); - - for (SSACFG::BlockId blockId: reachabilityCheck.visited) - { - auto& block = cfg.block(blockId); - std::erase_if(block.entries, [&](auto const& entry) { - return !reachabilityCheck.visited.contains(entry); - }); - } - for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) - { - auto& block = cfg.block(blockId); - bool const isReachable = reachabilityCheck.visited.contains(blockId); - std::erase_if(block.upsilons, [&](SSACFG::Upsilon const& u) { - return !isReachable || u.value.isUnreachable(); + std::erase_if(cfg.block(blockId).upsilons, [](SSACFG::Upsilon const& u) { + return u.value.isUnreachable(); }); - } } void buildIndices() diff --git a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.h b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.h index d50d95e19..7e2f5bb9d 100644 --- a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.h +++ b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.h @@ -16,7 +16,7 @@ */ // SPDX-License-Identifier: GPL-3.0 /** - * Removes trivial phis and unreachable blocks from an SSA CFG. + * Removes trivial phis from an SSA CFG. * * A phi is trivial if all its upsilon operands provide the same value (modulo self-references). * Removal may cascade: eliminating one trivial phi can make others trivial. @@ -30,7 +30,7 @@ class SSACFG; namespace transform { -/// Removes unreachable blocks and trivial phis from the SSA CFG +/// Removes trivial phis from the SSA CFG void eliminateTrivialPhis(SSACFG& _cfg); } diff --git a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp new file mode 100644 index 000000000..4a27cf609 --- /dev/null +++ b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp @@ -0,0 +1,59 @@ +/* + 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 + +#include + +#include + +#include +#include + +using namespace solidity; +using namespace solidity::yul; +using namespace solidity::yul::ssa; +using namespace solidity::yul::ssa::transform; + +void transform::cleanUnreachableBlocks(SSACFG& _cfg) +{ + util::BreadthFirstSearch reachabilityCheck{{_cfg.entry}}; + reachabilityCheck.run([&](SSACFG::BlockId const _blockId, auto&& _addChild) { + auto const& block = _cfg.block(_blockId); + visit(util::GenericVisitor{ + [&](SSACFG::BasicBlock::Jump const& _jump) { _addChild(_jump.target); }, + [&](SSACFG::BasicBlock::ConditionalJump const& _jump) { + _addChild(_jump.zero); + _addChild(_jump.nonZero); + }, + [](SSACFG::BasicBlock::FunctionReturn const&) {}, + [](SSACFG::BasicBlock::Terminated const&) {}, + [](SSACFG::BasicBlock::MainExit const&) {} + }, block.exit); + }); + + for (SSACFG::BlockId const blockId: reachabilityCheck.visited) + { + auto& block = _cfg.block(blockId); + std::erase_if(block.entries, [&](auto const& entry) { + return !reachabilityCheck.visited.contains(entry); + }); + } + + for (SSACFG::BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) + if (!reachabilityCheck.visited.contains(blockId)) + _cfg.block(blockId).upsilons.clear(); +} diff --git a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h new file mode 100644 index 000000000..cea9e91e8 --- /dev/null +++ b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h @@ -0,0 +1,34 @@ +/* + 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 +/** + * Removes unreachable blocks from an SSA CFG and cleans up entry lists and upsilons referencing them. + */ +#pragma once + +namespace solidity::yul::ssa +{ + +class SSACFG; + +namespace transform +{ +/// Removes unreachable blocks and cleans up references to them. +void cleanUnreachableBlocks(SSACFG& _cfg); +} + +} From 21b83829638eb31dad0bc8f7918b8a8d1b016dc9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:23:03 +0100 Subject: [PATCH 1209/1340] Optimize unreachable block cleaner --- .../ssa/transform/UnreachableBlockCleaner.cpp | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp index 4a27cf609..7cae6a809 100644 --- a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp +++ b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp @@ -20,8 +20,8 @@ #include -#include -#include +#include +#include using namespace solidity; using namespace solidity::yul; @@ -30,30 +30,29 @@ using namespace solidity::yul::ssa::transform; void transform::cleanUnreachableBlocks(SSACFG& _cfg) { - util::BreadthFirstSearch reachabilityCheck{{_cfg.entry}}; - reachabilityCheck.run([&](SSACFG::BlockId const _blockId, auto&& _addChild) { - auto const& block = _cfg.block(_blockId); - visit(util::GenericVisitor{ - [&](SSACFG::BasicBlock::Jump const& _jump) { _addChild(_jump.target); }, - [&](SSACFG::BasicBlock::ConditionalJump const& _jump) { - _addChild(_jump.zero); - _addChild(_jump.nonZero); - }, - [](SSACFG::BasicBlock::FunctionReturn const&) {}, - [](SSACFG::BasicBlock::Terminated const&) {}, - [](SSACFG::BasicBlock::MainExit const&) {} - }, block.exit); - }); - - for (SSACFG::BlockId const blockId: reachabilityCheck.visited) + std::vector reachable(_cfg.numBlocks(), false); + std::deque worklist{_cfg.entry}; + reachable[_cfg.entry.value] = true; + while (!worklist.empty()) { - auto& block = _cfg.block(blockId); - std::erase_if(block.entries, [&](auto const& entry) { - return !reachabilityCheck.visited.contains(entry); + auto const blockId = worklist.front(); + worklist.pop_front(); + auto const& block = _cfg.block(blockId); + block.forEachExit([&](BlockId const _exitBlock) { + if (!reachable[_exitBlock.value]) + { + reachable[_exitBlock.value] = true; + worklist.push_back(_exitBlock); + } }); } for (SSACFG::BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) - if (!reachabilityCheck.visited.contains(blockId)) - _cfg.block(blockId).upsilons.clear(); + { + auto& block = _cfg.block(blockId); + if (reachable[blockId.value]) + std::erase_if(block.entries, [&](auto const& entry) { return !reachable[entry.value]; }); + else + block.upsilons.clear(); + } } From 24593bb2bc7b939882edd62efae9f0b9613b0be7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:26:18 +0100 Subject: [PATCH 1210/1340] Unreachable block cleaner resets the block instead of only emptying upsilons --- libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp | 2 +- libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp index 7cae6a809..c5835f313 100644 --- a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp +++ b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp @@ -53,6 +53,6 @@ void transform::cleanUnreachableBlocks(SSACFG& _cfg) if (reachable[blockId.value]) std::erase_if(block.entries, [&](auto const& entry) { return !reachable[entry.value]; }); else - block.upsilons.clear(); + block = {}; } } diff --git a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h index cea9e91e8..f3edf5161 100644 --- a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h +++ b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h @@ -16,7 +16,8 @@ */ // SPDX-License-Identifier: GPL-3.0 /** - * Removes unreachable blocks from an SSA CFG and cleans up entry lists and upsilons referencing them. + * Removes unreachable blocks from an SSA CFG and cleans up entry lists referencing them. + * Note that this invalidates ValueIds and OperationIds pointing into the (unreachable) blocks. */ #pragma once From 5e0a4463c4dd4252df6bacf82bc2ab63d2bf223d Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:31:41 +0100 Subject: [PATCH 1211/1340] Use concept for `SSACFG::forEachExit` --- libyul/backends/evm/ssa/SSACFG.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index d6ad20797..af220566a 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -33,6 +33,8 @@ #include #include + +#include #include #include #include @@ -113,7 +115,8 @@ class SSACFG /// They record the phi pre-images for successor blocks. std::vector upsilons; std::variant exit = MainExit{}; - template + + template Callable> void forEachExit(Callable&& _callable) const { if (auto* jump = std::get_if(&exit)) From 9f6749582c66967aa40e76f29dc3962d5e36eed3 Mon Sep 17 00:00:00 2001 From: blishko Date: Thu, 26 Mar 2026 13:55:28 +0100 Subject: [PATCH 1212/1340] SSA: Add shuffler test This test checks behaviour at the edge when we need to fetch something from deep slot, while needing to duplicate another value. The current solution is not optimal, instead of the sequence currently found, "DUP1 + SWAP3 + POP + SWAP1 + SWAP16 + SWAP1", the same result can be obtained using 2 fewer instructions: "SWAP2 + POP + SWAP15 + DUP2". --- .../deep_argument_with_tail_values.stack | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack diff --git a/test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack b/test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack new file mode 100644 index 000000000..2e74573c3 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack @@ -0,0 +1,17 @@ +// We need to fetch v0 from depth while duplicating v1 for tail +initial: [v0, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v2, v1] +targetStackTop: [v0, v1] +targetStackTailSet: {v1,v2} +targetStackSize: 17 +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 15 16 | 17 +// +--------------------------------------------------------------------------------------------------------- +-------------- +------- +// (initial)| v0 * * * * * * * * * * * * * * | v2 v1 +// DUP1| v0 * * * * * * * * * * * * * * | v2 v1 | v1 +// SWAP3| v0 * * * * * * * * * * * * * v1 | v2 v1 | * +// POP| v0 * * * * * * * * * * * * * v1 | v2 v1 +// SWAP1| v0 * * * * * * * * * * * * * v1 | v1 v2 +// SWAP16| v2 * * * * * * * * * * * * * v1 | v1 v0 +// SWAP1| v2 * * * * * * * * * * * * * v1 | v0 v1 +// +--------------------------------------------------------------------------------------------------------- +-------------- +------- +// (target)| {v1, v2} | v0 v1 | From 41a57e7035695a9b0800cb4136718a0361404519 Mon Sep 17 00:00:00 2001 From: blishko Date: Thu, 26 Mar 2026 17:55:52 +0100 Subject: [PATCH 1213/1340] SSA: Simplify shuffler helper This refactor removes one nested level and simplifies the for header. --- libyul/backends/evm/ssa/StackShuffler.h | 33 +++++++++++-------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 6bdd47686..3db66ff2e 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -793,26 +793,23 @@ class StackShuffler static std::optional allNecessarySlotsReachableOrFinal(Stack const& _stack, detail::State const& _state) { // check that args are either in position or reachable - for (StackOffset offset{_state.target().tailSize}; offset < _state.target().size; ++offset.value) - if ( - offset < _state.size() && - !_state.isArgsCompatible(offset, offset) - ) + for (StackOffset const offset: _state.stackArgsRange()) + { + if (_state.isArgsCompatible(offset, offset)) + continue; + // find first occurrence of the slot + std::optional depth = _stack.findSlotDepth(_state.targetArg(offset)); + if (!depth) { - // find first occurrence of the slot - std::optional depth = _stack.findSlotDepth(_state.targetArg(offset)); - - if (!depth) - { - // if there is no occurrence of the slot anywhere, we must be able to freely generate it - yulAssert(_stack.canBeFreelyGenerated(_state.targetArg(offset))); - } - else - { - if (_stack.isBeyondSwapRange(*depth)) - return _stack.depthToOffset(*depth); - } + // if there is no occurrence of the slot anywhere, we must be able to freely generate it + yulAssert(_stack.canBeFreelyGenerated(_state.targetArg(offset))); + } + else + { + if (_stack.isBeyondSwapRange(*depth)) + return _stack.depthToOffset(*depth); } + } // distribution check: all we have to dup can be duped for (StackOffset const offset: _state.stackRange()) { From 2be29a9d076009946a1db1beb333a3c2f0858ddd Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 27 Mar 2026 10:13:26 +0100 Subject: [PATCH 1214/1340] relax conditions for a valid ssa stackShuffler test definition - target tail set is defaulted to empty - when target tail set is empty and target size is unset, it is derived from target stack top --- test/libyul/ssa/StackShufflerTest.cpp | 31 +++++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index 62e0955bb..0b1427eaf 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -166,15 +166,20 @@ struct ShuffleTestInput { std::optional initial; std::optional targetStackTop; - std::optional targetStackTailSet; + Liveness targetStackTailSet{}; std::optional targetStackSize; bool valid() const { - return initial.has_value() && + bool const fullySpecified = + initial.has_value() && targetStackTop.has_value() && - targetStackTailSet.has_value() && targetStackSize.has_value(); + bool const exactMode = + initial.has_value() && + targetStackTop.has_value() && + !targetStackSize.has_value(); + return fullySpecified || exactMode; } static ShuffleTestInput parse(std::string_view _source) @@ -223,6 +228,15 @@ struct ShuffleTestInput } } + + if (result.valid() && !result.targetStackSize) + { + yulAssert( + result.targetStackTailSet.empty(), + "Can only infer target stack size if targetStackTailSet is empty / unset." + ); + result.targetStackSize = result.targetStackTop->size(); + } return result; } }; @@ -399,7 +413,10 @@ Where is one of: lit - literal JUNK - junk slot -Lines starting with // are comments. Comments at the end of lines are supported, too.)"; +Lines starting with // are comments. Comments at the end of lines are supported, too. +The targetStackTailSet defaults to empty. +The targetStackSize defaults to the size of targetStackTop if targetStackTailSet is empty, otherwise it must be +explicitly provided.)"; util::AnsiColorized out(_stream, _formatted, {util::formatting::BOLD, util::formatting::RED}); out << _linePrefix << fmt::format("Error parsing source. Expected format:") << '\n'; @@ -418,13 +435,13 @@ Lines starting with // are comments. Comments at the end of lines are supported, auto stackData = *testConfig.initial; std::ostringstream oss; { - TraceRecorder trace(oss, *testConfig.targetStackTop, *testConfig.targetStackTailSet, *testConfig.targetStackSize); + TraceRecorder trace(oss, *testConfig.targetStackTop, testConfig.targetStackTailSet, *testConfig.targetStackSize); trace.record("(initial)", *testConfig.initial); TestStack stack(stackData, {.hook = [&](std::string const& op){ trace.record(op, stackData); }}); StackShuffler::shuffle( stack, *testConfig.targetStackTop, - *testConfig.targetStackTailSet, + testConfig.targetStackTailSet, *testConfig.targetStackSize ); } @@ -433,7 +450,7 @@ Lines starting with // are comments. Comments at the end of lines are supported, yulAssert(*testConfig.targetStackSize >= testConfig.targetStackTop->size()); auto const tailSize = *testConfig.targetStackSize - testConfig.targetStackTop->size(); yulAssert(stackData.size() == *testConfig.targetStackSize); - for (const auto& valueID: *testConfig.targetStackTailSet | ranges::views::keys) + for (const auto& valueID: testConfig.targetStackTailSet | ranges::views::keys) { auto const findIt = ranges::find( stackData.begin(), From 2bbe1277a66232b429e5150f350fb4115d97658e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 27 Mar 2026 10:17:39 +0100 Subject: [PATCH 1215/1340] simplify ssa stackShuffler test definitions --- test/libyul/ssa/stackShuffler/grow.stack | 2 -- test/libyul/ssa/stackShuffler/introduce_junk.stack | 2 -- test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack | 2 -- test/libyul/ssa/stackShuffler/superfluous_top_slots.stack | 2 -- test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack | 1 - 5 files changed, 9 deletions(-) diff --git a/test/libyul/ssa/stackShuffler/grow.stack b/test/libyul/ssa/stackShuffler/grow.stack index 4c07f8e36..6ad001c47 100644 --- a/test/libyul/ssa/stackShuffler/grow.stack +++ b/test/libyul/ssa/stackShuffler/grow.stack @@ -1,8 +1,6 @@ // need to grow the stack to reach target stack size but still fulfill args requirements initial: [JUNK, JUNK, JUNK, v15] targetStackTop: [JUNK, JUNK, JUNK, JUNK, v15] -targetStackTailSet: {} -targetStackSize: 5 // ---- // | 0 1 2 3 4 // +----------------------------------- diff --git a/test/libyul/ssa/stackShuffler/introduce_junk.stack b/test/libyul/ssa/stackShuffler/introduce_junk.stack index 54b29a9a3..de3d9e234 100644 --- a/test/libyul/ssa/stackShuffler/introduce_junk.stack +++ b/test/libyul/ssa/stackShuffler/introduce_junk.stack @@ -1,8 +1,6 @@ // some of the slots in the initial stack no longer appear in the target / are junk initial: [v189, phi112, JUNK, v204, JUNK, JUNK, JUNK, v185, JUNK, v188, v190, v191, JUNK, v199, phi112, phi112, v205, v206] targetStackTop: [v199, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v185, JUNK, v188, v190, v191, JUNK, v189, JUNK, v206, v205, v204] -targetStackTailSet: {} -targetStackSize: 18 // ---- // | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // +------------------------------------------------------------------------------------------------------------------------------ diff --git a/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack b/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack index 8c8eb6285..2a5f55972 100644 --- a/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack +++ b/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack @@ -1,8 +1,6 @@ // we want to replace JUNK at the bottom of the stack with the top value, all other slots must be preserved exactly initial: [JUNK, v2, v1, v0] targetStackTop: [v0, v2, v1, v0] -targetStackTailSet: {} -targetStackSize: 4 // ---- // | 0 1 2 3 | 4 // +---------------------------- +------- diff --git a/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack b/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack index 87d9ea9a8..ee8bf7784 100644 --- a/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack +++ b/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack @@ -1,8 +1,6 @@ // todo: The upper two junk slots should be popped immediately, they are completely superfluous. initial: [JUNK, JUNK, v56, v57, JUNK, JUNK] targetStackTop: [JUNK, JUNK, v56, v57, lit0, v56, lit11] -targetStackTailSet: {} -targetStackSize: 7 // ---- // | 0 1 2 3 4 5 6 | 7 // +------------------------------------------------- +------- diff --git a/test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack b/test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack index 56f623b75..dbf818ba2 100644 --- a/test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack +++ b/test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack @@ -1,7 +1,6 @@ // here, the algorithm should prefer a swap of junk into tail over pop and dup initial: [v0, JUNK, v2] targetStackTop: [lit2, v2, v0] -targetStackTailSet: {} targetStackSize: 4 // ---- // | 0 | 1 2 3 From 8ff95657d8d6e80fd1cbedfb364344df1350f6fe Mon Sep 17 00:00:00 2001 From: blishko Date: Fri, 27 Mar 2026 14:56:06 +0100 Subject: [PATCH 1216/1340] Tests: Run SSA-CFG on external contracts in semantic tests --- .../semanticTests/externalContracts/FixedFeeRegistrar.sol | 5 +++++ test/libsolidity/semanticTests/externalContracts/base64.sol | 6 ++++++ .../semanticTests/externalContracts/prbmath_signed.sol | 5 +++++ .../semanticTests/externalContracts/prbmath_unsigned.sol | 5 +++++ .../semanticTests/externalContracts/ramanujan_pi.sol | 5 +++++ .../libsolidity/semanticTests/externalContracts/strings.sol | 6 ++++++ 6 files changed, 32 insertions(+) diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index e89eeba98..857519609 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -72,6 +72,9 @@ contract FixedFeeRegistrar is Registrar { } uint constant c_fee = 69 ether; } +// ==== +// compileViaSSACFG: true +// experimental: true // ---- // constructor() // gas irOptimized: 78076 @@ -80,6 +83,8 @@ contract FixedFeeRegistrar is Registrar { // gas legacy code: 792400 // gas legacyOptimized: 84598 // gas legacyOptimized code: 388000 +// gas ssaCFGOptimized: 80860 +// gas ssaCFGOptimized code: 345400 // reserve(string), 69 ether: 0x20, 3, "abc" -> // ~ emit Changed(string): #0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 // gas irOptimized: 45741 diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol index 6e23da855..cc67d70df 100644 --- a/test/libsolidity/semanticTests/externalContracts/base64.sol +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -31,6 +31,8 @@ contract test { // // ==== // EVMVersion: >=constantinople +// compileViaSSACFG: true +// experimental: true // ---- // constructor() // gas irOptimized: 79076 @@ -39,6 +41,8 @@ contract test { // gas legacy code: 629800 // gas legacyOptimized: 87926 // gas legacyOptimized code: 429800 +// gas ssaCFGOptimized: 80162 +// gas ssaCFGOptimized code: 334800 // encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 // encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" // encode_inline_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8=" @@ -57,7 +61,9 @@ contract test { // gas irOptimized: 1406025 // gas legacy: 1554038 // gas legacyOptimized: 1132031 +// gas ssaCFGOptimized: 1391028 // encode_no_asm_large() // gas irOptimized: 3512081 // gas legacy: 4600082 // gas legacyOptimized: 2813075 +// gas ssaCFGOptimized: 3097084 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index 35e083d5c..6a91d5e31 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -46,6 +46,9 @@ contract test { assert(z1 == z2); } } +// ==== +// compileViaSSACFG: true +// experimental: true // ---- // constructor() // gas irOptimized: 177903 @@ -54,6 +57,8 @@ contract test { // gas legacy code: 2205000 // gas legacyOptimized: 178012 // gas legacyOptimized code: 1669600 +// gas ssaCFGOptimized: 177301 +// gas ssaCFGOptimized code: 1666800 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22045 // gas legacy: 22736 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index 38d2a20ba..8243a8b11 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -46,6 +46,9 @@ contract test { assert(z1 == z2); } } +// ==== +// compileViaSSACFG: true +// experimental: true // ---- // constructor() // gas irOptimized: 170626 @@ -54,6 +57,8 @@ contract test { // gas legacy code: 1999000 // gas legacyOptimized: 168857 // gas legacyOptimized code: 1556200 +// gas ssaCFGOptimized: 168323 +// gas ssaCFGOptimized code: 1553000 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 21912 // gas legacy: 22475 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index a98e83001..31ddc8487 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -31,6 +31,9 @@ contract test { ret = prb_scale(1).div(ret); } } +// ==== +// compileViaSSACFG: true +// experimental: true // ---- // constructor() // gas irOptimized: 77816 @@ -39,6 +42,8 @@ contract test { // gas legacy code: 523600 // gas legacyOptimized: 82667 // gas legacyOptimized code: 369200 +// gas ssaCFGOptimized: 80456 +// gas ssaCFGOptimized code: 344400 // prb_pi() -> 3141592656369545286 // gas irOptimized: 55036 // gas legacy: 100657 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 8deb86ed5..4709531ca 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -47,6 +47,9 @@ contract test { return d.toSlice().len(); } } +// ==== +// compileViaSSACFG: true +// experimental: true // ---- // constructor() // gas irOptimized: 95303 @@ -55,6 +58,8 @@ contract test { // gas legacy code: 932600 // gas legacyOptimized: 102639 // gas legacyOptimized code: 612400 +// gas ssaCFGOptimized: 97417 +// gas ssaCFGOptimized code: 547000 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22646 // gas legacy: 23168 @@ -75,3 +80,4 @@ contract test { // gas irOptimized: 1976778 // gas legacy: 4234020 // gas legacyOptimized: 2318668 +// gas ssaCFGOptimized: 2080148 From 5be42bfdefb1f1f52a50c27eddae09847f6ddbab Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 30 Mar 2026 17:53:00 +0200 Subject: [PATCH 1217/1340] CI: Add explicit boost-libs to Arch Linux build dependencies Arch Linux boost 1.90.0 moved static libraries from the `boost` package to `boost-libs` and dropped the dependency between them --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5c6298817..245edf3d8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1276,7 +1276,7 @@ jobs: - run: name: Install build dependencies command: | - pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake ccache git openssh tar + pacman --noconfirm -Syu --noprogressbar --needed base-devel boost boost-libs cmake ccache git openssh tar - checkout - run_build - store_artifacts_solc From d50cddacceeb65518c4768bed9cba69b415a3ed9 Mon Sep 17 00:00:00 2001 From: blishko Date: Fri, 27 Mar 2026 14:01:42 +0100 Subject: [PATCH 1218/1340] SSA: Shrink stack preemptively in shuffler When shuffling we can check if the stack would require shrinking at some point in the future and if that is the case, we can try to shrink it immediately. We can check if shrinking will be required in the following way: For each non-junk element we know what is it's minimal count in the target stack. If the current count of an element is lower then the minimal count, we have a "deficit" for this element. We will need more of it so it will require that the stack will grow. If the total deficit is larger than the space we have available (target size - current size), we are sure the stack will require shrinking at some point. --- libyul/backends/evm/ssa/StackShuffler.cpp | 14 ++++++++++++ libyul/backends/evm/ssa/StackShuffler.h | 6 +++++ .../externalContracts/deposit_contract.sol | 12 +++++----- .../externalContracts/prbmath_signed.sol | 4 ++-- .../externalContracts/prbmath_unsigned.sol | 4 ++-- .../externalContracts/ramanujan_pi.sol | 4 ++-- .../semanticTests/externalContracts/snark.sol | 4 ++-- .../externalContracts/strings.sol | 6 ++--- .../deep_argument_with_tail_values.stack | 18 +++++++-------- .../replace_junk_with_top_value.stack | 14 ++++++------ .../stackShuffler/superfluous_top_slots.stack | 22 +++++++++---------- 11 files changed, 62 insertions(+), 46 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.cpp b/libyul/backends/evm/ssa/StackShuffler.cpp index d1a85251a..01bf57c60 100644 --- a/libyul/backends/evm/ssa/StackShuffler.cpp +++ b/libyul/backends/evm/ssa/StackShuffler.cpp @@ -181,3 +181,17 @@ Target const& State::target() const { return m_target; } + +bool State::willRequireShrinking() const +{ + std::size_t deficit = 0u; + for (auto const& [slot, minCount]: target().minCount) + { + if (slot.isJunk()) + continue; + auto const currentCount = count(slot); + if (currentCount < minCount) + deficit += minCount - currentCount; + } + return deficit + size() > target().size; +} diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 3db66ff2e..54cd850e7 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -66,6 +66,8 @@ class State /// Obtain the amount of the provided slot that is required in target args std::size_t targetArgsCount(StackSlot const& _slot) const; + bool willRequireShrinking() const; + /// Checks if the state is compatible with the target bool admissible() const; @@ -194,6 +196,10 @@ class StackShuffler } yulAssert(_stack.size() <= _state.target().size, "I1 violated: Stack size too large"); + if (_state.willRequireShrinking()) + if (shrinkStack(_stack, _state)) + return true; + // after this, all current slots are either in acceptable positions or at least dup-reachable if (auto unreachableOffset = allNecessarySlotsReachableOrFinal(_stack, _state)) { diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index ce069d31f..e09373da0 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -185,8 +185,8 @@ contract DepositContract is IDepositContract, ERC165 { // gas legacy code: 1438800 // gas legacyOptimized: 848699 // gas legacyOptimized code: 878200 -// gas ssaCFGOptimized: 810619 -// gas ssaCFGOptimized code: 581400 +// gas ssaCFGOptimized: 810635 +// gas ssaCFGOptimized code: 581600 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # @@ -195,14 +195,14 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 -// gas ssaCFGOptimized: 110115 +// gas ssaCFGOptimized: 110019 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 -// gas ssaCFGOptimized: 110115 +// gas ssaCFGOptimized: 110019 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 @@ -210,7 +210,7 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 110108 +// gas ssaCFGOptimized: 110015 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 @@ -218,5 +218,5 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 110108 +// gas ssaCFGOptimized: 110015 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index 6a91d5e31..cb5ec7a45 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -57,8 +57,8 @@ contract test { // gas legacy code: 2205000 // gas legacyOptimized: 178012 // gas legacyOptimized code: 1669600 -// gas ssaCFGOptimized: 177301 -// gas ssaCFGOptimized code: 1666800 +// gas ssaCFGOptimized: 177237 +// gas ssaCFGOptimized code: 1666000 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22045 // gas legacy: 22736 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index 8243a8b11..0b48db02c 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -57,8 +57,8 @@ contract test { // gas legacy code: 1999000 // gas legacyOptimized: 168857 // gas legacyOptimized code: 1556200 -// gas ssaCFGOptimized: 168323 -// gas ssaCFGOptimized code: 1553000 +// gas ssaCFGOptimized: 168283 +// gas ssaCFGOptimized code: 1552800 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 21912 // gas legacy: 22475 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index 31ddc8487..5a334a3f0 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -42,8 +42,8 @@ contract test { // gas legacy code: 523600 // gas legacyOptimized: 82667 // gas legacyOptimized code: 369200 -// gas ssaCFGOptimized: 80456 -// gas ssaCFGOptimized code: 344400 +// gas ssaCFGOptimized: 80376 +// gas ssaCFGOptimized code: 344000 // prb_pi() -> 3141592656369545286 // gas irOptimized: 55036 // gas legacy: 100657 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index 6d39096b9..d1e3f5dfc 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -297,10 +297,10 @@ contract Test { // gas irOptimized: 275229 // gas legacy: 293579 // gas legacyOptimized: 276313 -// gas ssaCFGOptimized: 275420 +// gas ssaCFGOptimized: 275405 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." // gas irOptimized: 818076 // gas legacy: 904397 // gas legacyOptimized: 816770 -// gas ssaCFGOptimized: 819241 +// gas ssaCFGOptimized: 819277 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 4709531ca..662f15f3f 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -58,8 +58,8 @@ contract test { // gas legacy code: 932600 // gas legacyOptimized: 102639 // gas legacyOptimized code: 612400 -// gas ssaCFGOptimized: 97417 -// gas ssaCFGOptimized code: 547000 +// gas ssaCFGOptimized: 97425 +// gas ssaCFGOptimized code: 547400 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22646 // gas legacy: 23168 @@ -80,4 +80,4 @@ contract test { // gas irOptimized: 1976778 // gas legacy: 4234020 // gas legacyOptimized: 2318668 -// gas ssaCFGOptimized: 2080148 +// gas ssaCFGOptimized: 2080195 diff --git a/test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack b/test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack index 2e74573c3..729a8623a 100644 --- a/test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack +++ b/test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack @@ -4,14 +4,12 @@ targetStackTop: [v0, v1] targetStackTailSet: {v1,v2} targetStackSize: 17 // ---- -// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 15 16 | 17 -// +--------------------------------------------------------------------------------------------------------- +-------------- +------- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 15 16 +// +--------------------------------------------------------------------------------------------------------- +-------------- // (initial)| v0 * * * * * * * * * * * * * * | v2 v1 -// DUP1| v0 * * * * * * * * * * * * * * | v2 v1 | v1 -// SWAP3| v0 * * * * * * * * * * * * * v1 | v2 v1 | * -// POP| v0 * * * * * * * * * * * * * v1 | v2 v1 -// SWAP1| v0 * * * * * * * * * * * * * v1 | v1 v2 -// SWAP16| v2 * * * * * * * * * * * * * v1 | v1 v0 -// SWAP1| v2 * * * * * * * * * * * * * v1 | v0 v1 -// +--------------------------------------------------------------------------------------------------------- +-------------- +------- -// (target)| {v1, v2} | v0 v1 | +// SWAP2| v0 * * * * * * * * * * * * * v1 | v2 * +// POP| v0 * * * * * * * * * * * * * v1 | v2 +// SWAP15| v2 * * * * * * * * * * * * * v1 | v0 +// DUP2| v2 * * * * * * * * * * * * * v1 | v0 v1 +// +--------------------------------------------------------------------------------------------------------- +-------------- +// (target)| {v1, v2} | v0 v1 diff --git a/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack b/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack index 2a5f55972..5e58ef150 100644 --- a/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack +++ b/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack @@ -2,11 +2,11 @@ initial: [JUNK, v2, v1, v0] targetStackTop: [v0, v2, v1, v0] // ---- -// | 0 1 2 3 | 4 -// +---------------------------- +------- +// | 0 1 2 3 +// +---------------------------- // (initial)| * v2 v1 v0 -// DUP1| * v2 v1 v0 | v0 -// SWAP4| v0 v2 v1 v0 | * -// POP| v0 v2 v1 v0 -// +---------------------------- +------- -// (target)| v0 v2 v1 v0 | +// SWAP3| v0 v2 v1 * +// POP| v0 v2 v1 +// DUP3| v0 v2 v1 v0 +// +---------------------------- +// (target)| v0 v2 v1 v0 diff --git a/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack b/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack index ee8bf7784..7753735d7 100644 --- a/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack +++ b/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack @@ -1,16 +1,14 @@ -// todo: The upper two junk slots should be popped immediately, they are completely superfluous. +// The upper two junk slots should be popped immediately, they are completely superfluous. initial: [JUNK, JUNK, v56, v57, JUNK, JUNK] targetStackTop: [JUNK, JUNK, v56, v57, lit0, v56, lit11] // ---- -// | 0 1 2 3 4 5 6 | 7 -// +------------------------------------------------- +------- +// | 0 1 2 3 4 5 6 +// +------------------------------------------------- // (initial)| * * v56 v57 * * -// PUSH lit11| * * v56 v57 * * lit11 -// DUP5| * * v56 v57 * * lit11 | v56 -// SWAP2| * * v56 v57 * v56 lit11 | * -// POP| * * v56 v57 * v56 lit11 -// PUSH lit0| * * v56 v57 * v56 lit11 | lit0 -// SWAP3| * * v56 v57 lit0 v56 lit11 | * -// POP| * * v56 v57 lit0 v56 lit11 -// +------------------------------------------------- +------- -// (target)| * * v56 v57 lit0 v56 lit11 | +// POP| * * v56 v57 * +// POP| * * v56 v57 +// PUSH lit0| * * v56 v57 lit0 +// DUP3| * * v56 v57 lit0 v56 +// PUSH lit11| * * v56 v57 lit0 v56 lit11 +// +------------------------------------------------- +// (target)| * * v56 v57 lit0 v56 lit11 From 70c495e9a86d5ef6597f25c21e81a05a94339e9d Mon Sep 17 00:00:00 2001 From: blishko Date: Wed, 25 Mar 2026 15:41:35 +0100 Subject: [PATCH 1219/1340] SSA: Do not dup prematurely in shuffler It seems that we do not need to dup slots we will need in advance. We can first swap them into tail, and only dup them later when we have more information. --- libyul/backends/evm/ssa/StackShuffler.h | 10 ------ .../ssa/stackShuffler/keep_top_argument.stack | 5 ++- .../satisfy_tail_requirements.stack | 36 +++++++++---------- 3 files changed, 19 insertions(+), 32 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 54cd850e7..6d9cc01c8 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -603,16 +603,6 @@ class StackShuffler _state.countInTail(slotAtOffset) == 0 // if we don't have the slot in tail right now ) { - // If we don't have enough copies of this slot, dup first instead of swapping. - if (_state.count(slotAtOffset) < _state.targetMinCount(slotAtOffset)) - { - if (_stack.dupReachable(offset)) - { - _stack.dup(offset); - return true; - } - } - // find the lowest swappable slot in tail that needs to go to args, swap for (StackOffset tailOffset: _state.stackTailRange()) { diff --git a/test/libyul/ssa/stackShuffler/keep_top_argument.stack b/test/libyul/ssa/stackShuffler/keep_top_argument.stack index 5d891d329..4baa57757 100644 --- a/test/libyul/ssa/stackShuffler/keep_top_argument.stack +++ b/test/libyul/ssa/stackShuffler/keep_top_argument.stack @@ -7,8 +7,7 @@ targetStackSize: 3 // | 0 | 1 2 // +------- +-------------- // (initial)| v0 | v1 -// DUP1| v0 | v1 v1 -// SWAP2| v1 | v1 v0 -// SWAP1| v1 | v0 v1 +// SWAP1| v1 | v0 +// DUP2| v1 | v0 v1 // +------- +-------------- // (target)| {v1} | v0 v1 diff --git a/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack b/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack index e685f0660..4f59296e6 100644 --- a/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack +++ b/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack @@ -7,24 +7,22 @@ targetStackSize: 17 // | 0 1 2 3 4 5 6 | 7 8 9 10 11 12 13 14 15 16 // +------------------------------------------------- +---------------------------------------------------------------------- // (initial)| v2 v3 v4 v5 v6 v7 v8 | v9 v10 -// DUP1| v2 v3 v4 v5 v6 v7 v8 | v9 v10 v10 -// SWAP9| v10 v3 v4 v5 v6 v7 v8 | v9 v10 v2 -// SWAP2| v10 v3 v4 v5 v6 v7 v8 | v2 v10 v9 -// SWAP1| v10 v3 v4 v5 v6 v7 v8 | v2 v9 v10 -// PUSH lit3| v10 v3 v4 v5 v6 v7 v8 | v2 v9 v10 lit3 -// SWAP3| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v10 v2 -// DUP5| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v10 v2 v8 -// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v2 v10 -// DUP7| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v2 v10 v7 -// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v10 v2 -// DUP9| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v10 v2 v6 -// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v2 v10 -// DUP11| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v2 v10 v5 -// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v10 v2 -// DUP13| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v10 v2 v4 -// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v2 v10 -// DUP15| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v2 v10 v3 -// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v3 v10 v2 -// SWAP1| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v3 v2 v10 +// SWAP8| v10 v3 v4 v5 v6 v7 v8 | v9 v2 +// PUSH lit3| v10 v3 v4 v5 v6 v7 v8 | v9 v2 lit3 +// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v2 v9 +// SWAP1| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v2 +// DUP4| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v2 v8 +// SWAP1| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v2 +// DUP6| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v2 v7 +// SWAP1| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v2 +// DUP8| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v2 v6 +// SWAP1| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v2 +// DUP10| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v2 v5 +// SWAP1| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v2 +// DUP12| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v2 v4 +// SWAP1| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v2 +// DUP14| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v2 v3 +// SWAP1| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v3 v2 +// DUP16| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v3 v2 v10 // +------------------------------------------------- +---------------------------------------------------------------------- // (target)| {v10} | lit3 v9 v8 v7 v6 v5 v4 v3 v2 v10 From abe15610b52d7e45e11905fecb2b1de3787cdc71 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 26 Mar 2026 12:21:43 +0100 Subject: [PATCH 1220/1340] Optimize solThrow --- Changelog.md | 1 + libsolutil/Assertions.h | 2 +- libsolutil/Exceptions.h | 46 ++++++++++++++++++++++++++++++----------- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/Changelog.md b/Changelog.md index b295b7bf4..adf89b3ac 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: * Commandline Interface: Introduce `--experimental` flag required for enabling the experimental mode. * EVM: Introduce experimental EVM version `@future`. * General: Introduce the SSA CFG codegen (experimental). +* General: Improve performance of sanity checks throughout the compiler implementation. * General: Restrict the existing experimental features (`generic-solidity`, `lsp`, `ethdebug`, `eof`, `evm`, `ast-import`, `evmasm-import`, `ir-ast`, `ssa-cfg`) to experimental mode. * Metadata: Store the state of the experimental mode in JSON and CBOR metadata. In CBOR this broadens the meaning of the existing `experimental` field, which used to indicate only the presence of certain experimental pragmas in the source. * Standard JSON Interface: Introduce `settings.experimental` setting required for enabling the experimental mode. diff --git a/libsolutil/Assertions.h b/libsolutil/Assertions.h index dcceb1cfc..2c3239fb2 100644 --- a/libsolutil/Assertions.h +++ b/libsolutil/Assertions.h @@ -72,7 +72,7 @@ namespace solidity::util #define assertThrowWithDefaultDescription(_condition, _exceptionType, _description, _defaultDescription) \ do \ { \ - if (!(_condition)) \ + if (!(_condition)) [[unlikely]] \ solThrow( \ _exceptionType, \ ::solidity::util::stringOrDefault((_description), (_defaultDescription)) \ diff --git a/libsolutil/Exceptions.h b/libsolutil/Exceptions.h index 2ad2713c3..db934ef0f 100644 --- a/libsolutil/Exceptions.h +++ b/libsolutil/Exceptions.h @@ -22,15 +22,46 @@ #include #include -#include #include #include #include +#if defined(_MSC_VER) +#define SOL_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) || defined(__clang__) +#define SOL_NOINLINE __attribute__((noinline)) +#else +#define SOL_NOINLINE +#endif + namespace solidity::util { +// error information to be added to exceptions +using errinfo_comment = boost::error_info; + +namespace detail +{ +/// Helper that performs the actual exception throw out-of-line, keeping call sites small. +template +[[noreturn]] SOL_NOINLINE void solThrowImpl( + Description&& _description, + char const* _function, + char const* _file, + int const _line +) +{ + ::boost::throw_exception( + ExceptionType() << + ::solidity::util::errinfo_comment(std::forward(_description)) << + ::boost::throw_function(_function) << + ::boost::throw_file(_file) << + ::boost::throw_line(_line) + ); +} +} + /// Base class for all exceptions. struct Exception: virtual std::exception, virtual boost::exception { @@ -51,13 +82,7 @@ struct Exception: virtual std::exception, virtual boost::exception /// @param _exceptionType The type of the exception to throw (not an instance). /// @param _description The message that describes the error. #define solThrow(_exceptionType, _description) \ - ::boost::throw_exception( \ - _exceptionType() << \ - ::solidity::util::errinfo_comment((_description)) << \ - ::boost::throw_function(ETH_FUNC) << \ - ::boost::throw_file(__FILE__) << \ - ::boost::throw_line(__LINE__) \ - ) + ::solidity::util::detail::solThrowImpl<_exceptionType>((_description), ETH_FUNC, __FILE__, __LINE__) /// Throws an exception if condition is not met with a given description and extra information about the location the /// exception was thrown from. @@ -65,7 +90,7 @@ struct Exception: virtual std::exception, virtual boost::exception /// @param _exceptionType The type of the exception to throw (not an instance). /// @param _description The message that describes the error. #define solRequire(_condition, _exceptionType, _description) \ - if (!(_condition)) \ + if (!(_condition)) [[unlikely]] \ solThrow(_exceptionType, (_description)) /// Defines an exception type that's meant to signal a specific condition and be caught rather than @@ -83,7 +108,4 @@ DEV_SIMPLE_EXCEPTION(DataTooLong); DEV_SIMPLE_EXCEPTION(StringTooLong); DEV_SIMPLE_EXCEPTION(InvalidType); -// error information to be added to exceptions -using errinfo_comment = boost::error_info; - } From 71cee36f7373f153a07256d85c8a020835c1faa1 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 26 Mar 2026 13:24:18 +0100 Subject: [PATCH 1221/1340] Work around maybe-uninitialized FP in ConditionalSimplifier --- libyul/optimiser/ConditionalSimplifier.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libyul/optimiser/ConditionalSimplifier.cpp b/libyul/optimiser/ConditionalSimplifier.cpp index f81933f41..556411254 100644 --- a/libyul/optimiser/ConditionalSimplifier.cpp +++ b/libyul/optimiser/ConditionalSimplifier.cpp @@ -48,13 +48,12 @@ void ConditionalSimplifier::operator()(Switch& _switch) if (_case.value) { (*this)(*_case.value); - _case.body.statements.insert(_case.body.statements.begin(), - Assignment{ - _case.body.debugData, - {Identifier{_case.body.debugData, expr}}, - std::make_unique(*_case.value) - } - ); + auto assignment = Statement{Assignment{ + _case.body.debugData, + {Identifier{_case.body.debugData, expr}}, + std::make_unique(*_case.value) + }}; + _case.body.statements.insert(_case.body.statements.begin(), std::move(assignment)); } (*this)(_case.body); } From e8b15fe80605653f52ffb6335f3c1736d49d16a6 Mon Sep 17 00:00:00 2001 From: blishko Date: Tue, 31 Mar 2026 09:42:47 +0200 Subject: [PATCH 1222/1340] SSA: Prefer smaller stacks when searching for best stack size Previously we would only update the stack size if the cost associated with that size would strictly improve over the previously found cost. However, if the cost is the same, but we have smaller size, we should prefer the smaller size. This in general keeps the stack smaller during the whole stack layout generation and avoids some of stack-too-deep situations. --- libyul/backends/evm/ssa/StackUtils.cpp | 2 +- .../externalContracts/FixedFeeRegistrar.sol | 4 ++-- .../semanticTests/externalContracts/base64.sol | 8 ++++---- .../externalContracts/deposit_contract.sol | 12 ++++++------ .../externalContracts/prbmath_signed.sol | 4 ++-- .../externalContracts/prbmath_unsigned.sol | 4 ++-- .../externalContracts/ramanujan_pi.sol | 4 ++-- .../semanticTests/externalContracts/snark.sol | 4 ++-- .../semanticTests/externalContracts/strings.sol | 6 +++--- .../ssa/stackLayoutGenerator/dead_code.yul | 6 +++--- .../libyul/ssa/stackLayoutGenerator/function.yul | 16 ++++++++-------- .../ssa/stackLayoutGenerator/multi_return.yul | 10 +++++----- .../ssa/stackLayoutGenerator/simple_if.yul | 10 +++++----- 13 files changed, 45 insertions(+), 45 deletions(-) diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index 864315ccf..ab2bb93d5 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -87,7 +87,7 @@ std::size_t solidity::yul::ssa::findOptimalTargetSize { --size; auto const cost = evaluateCost(size); - if (cost < bestCost) + if (cost <= bestCost) { bestCost = cost; result = size; diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index 857519609..35e22c41c 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -83,8 +83,8 @@ contract FixedFeeRegistrar is Registrar { // gas legacy code: 792400 // gas legacyOptimized: 84598 // gas legacyOptimized code: 388000 -// gas ssaCFGOptimized: 80860 -// gas ssaCFGOptimized code: 345400 +// gas ssaCFGOptimized: 78828 +// gas ssaCFGOptimized code: 321600 // reserve(string), 69 ether: 0x20, 3, "abc" -> // ~ emit Changed(string): #0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 // gas irOptimized: 45741 diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol index cc67d70df..42f6a96c4 100644 --- a/test/libsolidity/semanticTests/externalContracts/base64.sol +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -41,8 +41,8 @@ contract test { // gas legacy code: 629800 // gas legacyOptimized: 87926 // gas legacyOptimized code: 429800 -// gas ssaCFGOptimized: 80162 -// gas ssaCFGOptimized code: 334800 +// gas ssaCFGOptimized: 80061 +// gas ssaCFGOptimized code: 334000 // encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 // encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" // encode_inline_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8=" @@ -61,9 +61,9 @@ contract test { // gas irOptimized: 1406025 // gas legacy: 1554038 // gas legacyOptimized: 1132031 -// gas ssaCFGOptimized: 1391028 +// gas ssaCFGOptimized: 1391025 // encode_no_asm_large() // gas irOptimized: 3512081 // gas legacy: 4600082 // gas legacyOptimized: 2813075 -// gas ssaCFGOptimized: 3097084 +// gas ssaCFGOptimized: 3097081 diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index e09373da0..8645cf4a2 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -185,8 +185,8 @@ contract DepositContract is IDepositContract, ERC165 { // gas legacy code: 1438800 // gas legacyOptimized: 848699 // gas legacyOptimized code: 878200 -// gas ssaCFGOptimized: 810635 -// gas ssaCFGOptimized code: 581600 +// gas ssaCFGOptimized: 809791 +// gas ssaCFGOptimized code: 571600 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # @@ -195,14 +195,14 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 -// gas ssaCFGOptimized: 110019 +// gas ssaCFGOptimized: 110004 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 -// gas ssaCFGOptimized: 110019 +// gas ssaCFGOptimized: 110004 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 @@ -210,7 +210,7 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 110015 +// gas ssaCFGOptimized: 110000 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 @@ -218,5 +218,5 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 110015 +// gas ssaCFGOptimized: 110000 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index cb5ec7a45..e9cb3dc2b 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -57,8 +57,8 @@ contract test { // gas legacy code: 2205000 // gas legacyOptimized: 178012 // gas legacyOptimized code: 1669600 -// gas ssaCFGOptimized: 177237 -// gas ssaCFGOptimized code: 1666000 +// gas ssaCFGOptimized: 176529 +// gas ssaCFGOptimized code: 1658000 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22045 // gas legacy: 22736 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index 0b48db02c..75b4fb432 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -57,8 +57,8 @@ contract test { // gas legacy code: 1999000 // gas legacyOptimized: 168857 // gas legacyOptimized code: 1556200 -// gas ssaCFGOptimized: 168283 -// gas ssaCFGOptimized code: 1552800 +// gas ssaCFGOptimized: 167966 +// gas ssaCFGOptimized code: 1549000 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 21912 // gas legacy: 22475 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index 5a334a3f0..5b2d8b559 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -42,8 +42,8 @@ contract test { // gas legacy code: 523600 // gas legacyOptimized: 82667 // gas legacyOptimized code: 369200 -// gas ssaCFGOptimized: 80376 -// gas ssaCFGOptimized code: 344000 +// gas ssaCFGOptimized: 79327 +// gas ssaCFGOptimized code: 330600 // prb_pi() -> 3141592656369545286 // gas irOptimized: 55036 // gas legacy: 100657 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index d1e3f5dfc..ff56e6017 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -297,10 +297,10 @@ contract Test { // gas irOptimized: 275229 // gas legacy: 293579 // gas legacyOptimized: 276313 -// gas ssaCFGOptimized: 275405 +// gas ssaCFGOptimized: 275803 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." // gas irOptimized: 818076 // gas legacy: 904397 // gas legacyOptimized: 816770 -// gas ssaCFGOptimized: 819277 +// gas ssaCFGOptimized: 820449 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 662f15f3f..536fd711c 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -58,8 +58,8 @@ contract test { // gas legacy code: 932600 // gas legacyOptimized: 102639 // gas legacyOptimized code: 612400 -// gas ssaCFGOptimized: 97425 -// gas ssaCFGOptimized code: 547400 +// gas ssaCFGOptimized: 97396 +// gas ssaCFGOptimized code: 547200 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22646 // gas legacy: 23168 @@ -80,4 +80,4 @@ contract test { // gas irOptimized: 1976778 // gas legacy: 4234020 // gas legacyOptimized: 2318668 -// gas ssaCFGOptimized: 2080195 +// gas ssaCFGOptimized: 2080190 diff --git a/test/libyul/ssa/stackLayoutGenerator/dead_code.yul b/test/libyul/ssa/stackLayoutGenerator/dead_code.yul index adba2a345..fa7623197 100644 --- a/test/libyul/ssa/stackLayoutGenerator/dead_code.yul +++ b/test/libyul/ssa/stackLayoutGenerator/dead_code.yul @@ -68,11 +68,11 @@ // Block0_5 [label="\ // IN: [v0, v1]\l\ // \l\ -// [v0, v1, v0]\l\ +// [v1, v0]\l\ // sstore\l\ -// [v0]\l\ +// []\l\ // \l\ -// OUT: [v0]\l\ +// OUT: []\l\ // "]; // Block0_5Exit [label="MainExit"]; // Block0_5 -> Block0_5Exit; diff --git a/test/libyul/ssa/stackLayoutGenerator/function.yul b/test/libyul/ssa/stackLayoutGenerator/function.yul index c7e3c3209..8ea0f691b 100644 --- a/test/libyul/ssa/stackLayoutGenerator/function.yul +++ b/test/libyul/ssa/stackLayoutGenerator/function.yul @@ -35,11 +35,11 @@ // i\l\ // [FunctionCallReturnLabel[0], v0, v1]\l\ // \l\ -// [v0, JUNK, v0]\l\ +// [v0]\l\ // h\l\ -// [v0, JUNK]\l\ +// []\l\ // \l\ -// OUT: [v0, JUNK]\l\ +// OUT: []\l\ // "]; // Block0_0Exit [label="Terminated"]; // Block0_0 -> Block0_0Exit; @@ -81,15 +81,15 @@ // Block3_0 [label="\ // IN: [v0]\l\ // \l\ -// [v0, FunctionCallReturnLabel[0], lit0, v0]\l\ +// [FunctionCallReturnLabel[0], lit0, v0]\l\ // f\l\ -// [v0, FunctionCallReturnLabel[0], v1]\l\ +// [FunctionCallReturnLabel[0], v1]\l\ // \l\ -// [JUNK, v1]\l\ +// [v1]\l\ // h\l\ -// [JUNK]\l\ +// []\l\ // \l\ -// OUT: [JUNK]\l\ +// OUT: []\l\ // "]; // Block3_0Exit [label="Terminated"]; // Block3_0 -> Block3_0Exit; diff --git a/test/libyul/ssa/stackLayoutGenerator/multi_return.yul b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul index 76d4c8808..2beb56b95 100644 --- a/test/libyul/ssa/stackLayoutGenerator/multi_return.yul +++ b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul @@ -26,15 +26,15 @@ // pair\l\ // [v0, v1, FunctionCallReturnLabel[1], v2, v3]\l\ // \l\ -// [JUNK, v1, v2, v3, v2]\l\ +// [JUNK, v1, v3, v2]\l\ // add\l\ -// [JUNK, v1, v2, v4]\l\ +// [JUNK, v1, v4]\l\ // \l\ -// [JUNK, v1, JUNK, v4, v1]\l\ +// [JUNK, v4, v1]\l\ // sstore\l\ -// [JUNK, v1, JUNK]\l\ +// [JUNK]\l\ // \l\ -// OUT: [JUNK, v1, JUNK]\l\ +// OUT: [JUNK]\l\ // "]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; diff --git a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul index 2b72e0cea..a93ced983 100644 --- a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul +++ b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul @@ -50,15 +50,15 @@ // Block1_1 [label="\ // IN: [ReturnLabel[1], v1, v0]\l\ // \l\ -// [ReturnLabel[1], JUNK, v0, lit1, v0]\l\ +// [ReturnLabel[1], JUNK, lit1, v0]\l\ // add\l\ -// [ReturnLabel[1], JUNK, v0, v3]\l\ +// [ReturnLabel[1], JUNK, v3]\l\ // \l\ -// [ReturnLabel[1], JUNK, JUNK, v3, v3]\l\ +// [ReturnLabel[1], JUNK, v3, v3]\l\ // revert\l\ -// [ReturnLabel[1], JUNK, JUNK]\l\ +// [ReturnLabel[1], JUNK]\l\ // \l\ -// OUT: [ReturnLabel[1], JUNK, JUNK]\l\ +// OUT: [ReturnLabel[1], JUNK]\l\ // "]; // Block1_1Exit [label="Terminated"]; // Block1_1 -> Block1_1Exit; From 1f9577ac4c02d53c0652b5c5f3996cc020459a42 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:04:59 +0200 Subject: [PATCH 1223/1340] Remove unused include from SSACFG --- libyul/backends/evm/ssa/ControlFlow.cpp | 1 + libyul/backends/evm/ssa/SSACFG.cpp | 4 +--- libyul/backends/evm/ssa/SSACFG.h | 2 -- libyul/backends/evm/ssa/Stack.cpp | 2 ++ libyul/backends/evm/ssa/StackShuffler.h | 2 ++ libyul/backends/evm/ssa/io/DotExporterBase.cpp | 2 ++ 6 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libyul/backends/evm/ssa/ControlFlow.cpp b/libyul/backends/evm/ssa/ControlFlow.cpp index 16026ab30..614406f2b 100644 --- a/libyul/backends/evm/ssa/ControlFlow.cpp +++ b/libyul/backends/evm/ssa/ControlFlow.cpp @@ -18,6 +18,7 @@ #include +#include #include using namespace solidity::yul::ssa; diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 7fea15dda..2c8195fe7 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -25,11 +25,9 @@ #include #include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtautological-compare" #include -#pragma GCC diagnostic pop +#include #include using namespace solidity; diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index af220566a..fd9c9f41b 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -32,8 +32,6 @@ #include -#include - #include #include #include diff --git a/libyul/backends/evm/ssa/Stack.cpp b/libyul/backends/evm/ssa/Stack.cpp index 59534019d..1e7dc2d18 100644 --- a/libyul/backends/evm/ssa/Stack.cpp +++ b/libyul/backends/evm/ssa/Stack.cpp @@ -18,6 +18,8 @@ #include +#include + #include #include diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 6d9cc01c8..f9f261dea 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -24,6 +24,8 @@ #include #include +#include +#include #include #include diff --git a/libyul/backends/evm/ssa/io/DotExporterBase.cpp b/libyul/backends/evm/ssa/io/DotExporterBase.cpp index 9a62dcc83..00b3fda30 100644 --- a/libyul/backends/evm/ssa/io/DotExporterBase.cpp +++ b/libyul/backends/evm/ssa/io/DotExporterBase.cpp @@ -21,6 +21,8 @@ #include #include +#include + #include #include From dab434754488bd70abda1d0acfb82bee3d0484c4 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:20:05 +0200 Subject: [PATCH 1224/1340] Store EVMDialect in SSACFG --- libyul/backends/evm/EVMObjectCompiler.cpp | 2 +- libyul/backends/evm/ssa/SSACFG.h | 9 ++++++++- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 6 ++++-- libyul/backends/evm/ssa/SSACFGBuilder.h | 12 ++++++++---- test/libyul/ssa/ControlFlowGraphTest.cpp | 5 ++++- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 5 ++++- 6 files changed, 29 insertions(+), 10 deletions(-) diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index b476f2e09..379a41926 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -91,7 +91,7 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize, bool _viaSSAC { std::unique_ptr controlFlow = ssa::SSACFGBuilder::build( *_object.analysisInfo, - *_object.dialect(), + *evmDialect, _object.code()->root(), false ); diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index fd9c9f41b..1b717c7c6 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -24,6 +24,8 @@ #include #include +#include + #include #include #include @@ -47,7 +49,11 @@ class SSACFG public: using DebugInfo = SSACFGDebugInfo; - explicit SSACFG(std::unique_ptr _debugInfo = std::make_unique()): + explicit SSACFG( + EVMDialect const& _evmVersion, + std::unique_ptr _debugInfo = nullptr + ): + evmDialect(_evmVersion), debugInfo(std::move(_debugInfo)) {} @@ -266,6 +272,7 @@ class SSACFG std::vector m_variables; std::optional m_unreachableValue; public: + EVMDialect const& evmDialect; std::unique_ptr debugInfo; BlockId entry = BlockId{0}; std::set exits; diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 63c014cfd..7b5f8e004 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -52,7 +52,7 @@ SSACFGBuilder::SSACFGBuilder( SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, - Dialect const& _dialect, + EVMDialect const& _dialect, bool _keepLiteralAssignments, bool _generateDebugInfo ): @@ -68,7 +68,7 @@ SSACFGBuilder::SSACFGBuilder( std::unique_ptr SSACFGBuilder::build( AsmAnalysisInfo const& _analysisInfo, - Dialect const& _dialect, + EVMDialect const& _dialect, Block const& _block, bool _keepLiteralAssignments, bool _generateDebugInfo @@ -78,6 +78,7 @@ std::unique_ptr SSACFGBuilder::build( auto controlFlow = std::make_unique(); controlFlow->functionGraphs.emplace_back(std::make_unique( + _dialect, _generateDebugInfo ? std::make_unique() : nullptr )); controlFlow->functionGraphMapping.emplace_back(nullptr, controlFlow->functionGraphs.back().get()); @@ -101,6 +102,7 @@ void SSACFGBuilder::buildFunctionGraph( ) { m_controlFlow.functionGraphs.emplace_back(std::make_unique( + m_dialect, m_generateDebugInfo ? std::make_unique() : nullptr )); auto& cfg = *m_controlFlow.functionGraphs.back(); diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index e8c35652c..4b685df84 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -36,9 +36,13 @@ */ #pragma once -#include #include + +#include + +#include #include + #include #include @@ -52,7 +56,7 @@ class SSACFGBuilder SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, - Dialect const& _dialect, + EVMDialect const& _dialect, bool _keepLiteralAssignments, bool _generateDebugInfo ); @@ -61,7 +65,7 @@ class SSACFGBuilder SSACFGBuilder& operator=(SSACFGBuilder const&) = delete; static std::unique_ptr build( AsmAnalysisInfo const& _analysisInfo, - Dialect const& _dialect, + EVMDialect const& _dialect, Block const& _block, bool _keepLiteralAssignments, bool _generateDebugInfo = true @@ -104,7 +108,7 @@ class SSACFGBuilder SSACFG& m_graph; AsmAnalysisInfo const& m_info; ControlFlowSideEffectsCollector const& m_sideEffects; - Dialect const& m_dialect; + EVMDialect const& m_dialect; bool const m_keepLiteralAssignments; bool const m_generateDebugInfo; std::vector> m_functionDefinitions; diff --git a/test/libyul/ssa/ControlFlowGraphTest.cpp b/test/libyul/ssa/ControlFlowGraphTest.cpp index a2d43b23a..1fa9d7447 100644 --- a/test/libyul/ssa/ControlFlowGraphTest.cpp +++ b/test/libyul/ssa/ControlFlowGraphTest.cpp @@ -70,9 +70,12 @@ TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::strin return TestResult::FatalError; } + auto const* evmDialect = dynamic_cast(&yulStack.dialect()); + yulAssert(evmDialect); + std::unique_ptr controlFlow = yul::ssa::SSACFGBuilder::build( *yulStack.parserResult()->analysisInfo, - yulStack.dialect(), + *evmDialect, yulStack.parserResult()->code()->root(), true ); diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index 4234be31c..1aaab7db0 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -145,9 +145,12 @@ frontend::test::TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& auto const& object = *toVisit.back(); toVisit.pop_back(); + auto const* evmDialect = dynamic_cast(object.dialect()); + yulAssert(evmDialect); + std::unique_ptr const controlFlow = SSACFGBuilder::build( *object.analysisInfo, - *object.dialect(), + *evmDialect, object.code()->root(), false ); From 2e274f834e7dd1013aa1a6a9ea88a0f983b3865a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 30 Mar 2026 17:47:47 +0200 Subject: [PATCH 1225/1340] SSACFG: use op counts to decide for a target stack size and gas for multi-entry blocks --- .../backends/evm/ssa/StackLayoutGenerator.cpp | 32 +++++++++----- libyul/backends/evm/ssa/StackUtils.cpp | 42 ++++++++++++++++++- libyul/backends/evm/ssa/StackUtils.h | 30 ++++++++++--- .../ssa/stackLayoutGenerator/switch.yul | 8 ++-- 4 files changed, 90 insertions(+), 22 deletions(-) diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 82fdc5e2a..978df0679 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -64,7 +64,7 @@ void handlePhiFunctions(StackData& _stackData, PhiInverse const& _phiInverse, Li } } -using StackType = Stack; +using StackType = Stack; void declareJunk(StackType& _stack, LivenessAnalysis::LivenessData const& _live) { @@ -184,7 +184,7 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) continue; proposals[i] = *parentExits[i].second; { - StackType stack(proposals[i], {}); + StackType stack(proposals[i], {.cfg = m_cfg}); declareJunk(stack, liveIn); } handlePhiFunctions(proposals[i], PhiInverse(m_cfg, parentExits[i].first, _blockId), liveIn); @@ -200,14 +200,14 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) if (j == i || !parentExits[j].second) continue; auto proposalCopy = proposals[j]; - StackType stack(proposalCopy, {}); + StackType stack(proposalCopy, {.cfg = m_cfg}); StackShuffler::shuffle( stack, proposals[i], {}, proposals[i].size() ); - cumulativeCost += stack.callbacks().numOps; + cumulativeCost += stack.callbacks().opGas; } cumulativeCosts[i] = cumulativeCost; } @@ -229,7 +229,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) SSACFG::BasicBlock const& block = m_cfg.block(_blockId); StackData currentStackData = blockLayout.stackIn; - StackType stack(currentStackData, {}); + StackType stack(currentStackData, {.cfg = m_cfg}); bool const junkCanBeAdded = m_junkAdmittingBlocksFinder->allowsAdditionOfJunk(_blockId); auto const& operationsLiveOut = m_liveness.operationsLiveOut(_blockId); @@ -260,7 +260,13 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) ) stack.declareJunk(depth); - std::size_t const targetSize = findOptimalTargetSize(stack.data(), requiredStackTop, opLiveOutWithoutOutputs, junkCanBeAdded, m_hasFunctionReturnLabel); + std::size_t const targetSize = findOptimalTargetSize( + stack.data(), + requiredStackTop, + opLiveOutWithoutOutputs, + junkCanBeAdded, + m_hasFunctionReturnLabel + ); StackShuffler::shuffle( stack, requiredStackTop, @@ -270,9 +276,9 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) blockLayout.operationIn.push_back(currentStackData); for (std::size_t i = 0; i < requiredStackTop.size(); ++i) - stack.pop(); + stack.pop(); for (auto const& val: operation.outputs) - stack.push(Slot::makeValueID(val)); + stack.push(Slot::makeValueID(val)); } if (auto const* cjump = std::get_if(&block.exit)) @@ -288,7 +294,13 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) if (!conditionSlotAlreadyFinal) { auto const condition = Slot::makeValueID(cjump->condition); - auto const targetSize = findOptimalTargetSize(stack.data(), {condition}, blockLiveOut, false, m_hasFunctionReturnLabel); + auto const targetSize = findOptimalTargetSize( + stack.data(), + {condition}, + blockLiveOut, + false, + m_hasFunctionReturnLabel + ); StackShuffler::shuffle( stack, {condition}, blockLiveOut, targetSize ); @@ -314,7 +326,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) // same as nonzero stack in initially zeroLayout = nonZeroLayout; handlePhiFunctions(zeroLayout->stackIn, PhiInverse(m_cfg, _blockId, cjump->zero), zeroLiveIn); - StackType zeroStack(zeroLayout->stackIn, {}); + StackType zeroStack(zeroLayout->stackIn, {.cfg = m_cfg}); declareJunk(zeroStack, zeroLiveIn); } } diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index ab2bb93d5..4cd401e67 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -20,6 +20,8 @@ #include +#include + #include #include #include @@ -30,6 +32,42 @@ using namespace solidity::yul::ssa; +void GasAccumulatingCallbacks::swap(StackDepth _depth) +{ + opGas += evmasm::GasMeter::swapGas(_depth.value, cfg.evmDialect.evmVersion()); +} + +void GasAccumulatingCallbacks::dup(StackDepth _depth) +{ + opGas += evmasm::GasMeter::dupGas(_depth.value, cfg.evmDialect.evmVersion()); +} + +void GasAccumulatingCallbacks::push(StackSlot const& _slot) +{ + if (_slot.isLiteralValueID()) + { + auto const size = numberEncodingSize(cfg.literalInfo(_slot.valueID()).value); + opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(size), cfg.evmDialect.evmVersion()); + } + else if (_slot.isJunk()) + { + auto const op = cfg.evmDialect.evmVersion().hasPush0() ? evmasm::Instruction::PUSH0 : evmasm::Instruction::CODESIZE; + opGas += evmasm::GasMeter::runGas(op, cfg.evmDialect.evmVersion()); + } + else + { + yulAssert(_slot.isFunctionCallReturnLabel(), "we can only push literals, junk, and function call return labels"); + // this is a jump dest, we don't really know yet how big it is going to be, just assume that it fits into + // a 2-byte number + opGas += evmasm::GasMeter::runGas(evmasm::Instruction::PUSH2, cfg.evmDialect.evmVersion()); + } +} + +void GasAccumulatingCallbacks::pop() +{ + opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP, cfg.evmDialect.evmVersion()); +} + StackData solidity::yul::ssa::stackPreImage(StackData _stack, PhiInverse const& _phiInverse) { if (!_phiInverse.noOp()) @@ -67,8 +105,8 @@ std::size_t solidity::yul::ssa::findOptimalTargetSize auto const evaluateCost = [&](std::size_t const _targetSize) -> std::size_t { data = _stackData; - Stack countOpsStack(data, {}); - StackShuffler::shuffle(countOpsStack, _targetArgs, _targetLiveOut, _targetSize); + Stack countOpsStack(data, {}); + StackShuffler::shuffle(countOpsStack, _targetArgs, _targetLiveOut, _targetSize); yulAssert(countOpsStack.size() == _targetSize); return countOpsStack.callbacks().numOps; }; diff --git a/libyul/backends/evm/ssa/StackUtils.h b/libyul/backends/evm/ssa/StackUtils.h index cfc3fa96b..47dc6711a 100644 --- a/libyul/backends/evm/ssa/StackUtils.h +++ b/libyul/backends/evm/ssa/StackUtils.h @@ -38,19 +38,37 @@ class ValidationResult std::vector m_errors; }; -struct CountingInstructionsCallbacks +struct OpsCountingCallbacks { std::size_t numOps = 0; - void swap(StackDepth) { ++numOps; } - void dup(StackDepth) { ++numOps; } - void push(StackSlot const&) { ++numOps; } - void pop() { ++numOps; } + + void swap(StackDepth) {numOps++;} + void dup(StackDepth) {numOps++;} + void push(StackSlot const&) {numOps++;} + void pop() {numOps++;} +}; + +struct GasAccumulatingCallbacks +{ + SSACFG const& cfg; + std::size_t opGas = 0; + + void swap(StackDepth _depth); + void dup(StackDepth _depth); + void push(StackSlot const& _slot); + void pop(); }; /// Transform stack data by replacing all its phi variables with their respective preimages. StackData stackPreImage(StackData _stack, PhiInverse const& _phiInverse); -std::size_t findOptimalTargetSize(StackData const& _stackData, StackData const& _targetArgs, LivenessAnalysis::LivenessData const& _targetLiveOut, bool _canIntroduceJunk, bool _hasFunctionReturnLabel); +std::size_t findOptimalTargetSize( + StackData const& _stackData, + StackData const& _targetArgs, + LivenessAnalysis::LivenessData const& _targetLiveOut, + bool _canIntroduceJunk, + bool _hasFunctionReturnLabel +); CallSites gatherCallSites(SSACFG const& _cfg); diff --git a/test/libyul/ssa/stackLayoutGenerator/switch.yul b/test/libyul/ssa/stackLayoutGenerator/switch.yul index 898944d37..3ed060236 100644 --- a/test/libyul/ssa/stackLayoutGenerator/switch.yul +++ b/test/libyul/ssa/stackLayoutGenerator/switch.yul @@ -62,13 +62,13 @@ // Block0_3Exit:0 -> Block0_5 [style="solid"]; // Block0_3Exit:1 -> Block0_4 [style="solid"]; // Block0_1 [label="\ -// IN: [JUNK, phi0]\l\ +// IN: [phi0]\l\ // \l\ -// [JUNK, phi0, lit6]\l\ +// [phi0, lit6]\l\ // sstore\l\ -// [JUNK]\l\ +// []\l\ // \l\ -// OUT: [JUNK]\l\ +// OUT: []\l\ // "]; // Block0_1Exit [label="MainExit"]; // Block0_1 -> Block0_1Exit; From a05041af04993bc45092297446aca6e7554ee38b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 1 Apr 2026 09:55:28 +0200 Subject: [PATCH 1226/1340] Fix SSACFG stack layout generator stack-in inefficiency --- .../backends/evm/ssa/StackLayoutGenerator.cpp | 4 +- .../externalContracts/base64.sol | 8 ++-- .../externalContracts/deposit_contract.sol | 12 +++--- .../externalContracts/prbmath_signed.sol | 4 +- .../externalContracts/prbmath_unsigned.sol | 4 +- .../externalContracts/ramanujan_pi.sol | 4 +- .../semanticTests/externalContracts/snark.sol | 4 +- .../externalContracts/strings.sol | 6 +-- .../ssa/stackLayoutGenerator/nested_for.yul | 40 +++++++++---------- 9 files changed, 43 insertions(+), 43 deletions(-) diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 978df0679..924723133 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -176,18 +176,18 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) { // we have more than one entry and need to unify or at the very least apply phi fct. auto const& liveIn = m_liveness.liveIn(_blockId); - // Pre-compute each parent's phi-term proposal (declareJunk + handlePhiFunctions) once + // Pre-compute each parent's proposal std::vector proposals(parentExits.size()); for (std::size_t i = 0; i < parentExits.size(); ++i) { if (!parentExits[i].second) continue; proposals[i] = *parentExits[i].second; + handlePhiFunctions(proposals[i], PhiInverse(m_cfg, parentExits[i].first, _blockId), liveIn); { StackType stack(proposals[i], {.cfg = m_cfg}); declareJunk(stack, liveIn); } - handlePhiFunctions(proposals[i], PhiInverse(m_cfg, parentExits[i].first, _blockId), liveIn); } std::vector cumulativeCosts(parentExits.size(), std::numeric_limits::max()); for (std::size_t i = 0; i < parentExits.size(); ++i) diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol index 42f6a96c4..ef7ef1ddf 100644 --- a/test/libsolidity/semanticTests/externalContracts/base64.sol +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -41,8 +41,8 @@ contract test { // gas legacy code: 629800 // gas legacyOptimized: 87926 // gas legacyOptimized code: 429800 -// gas ssaCFGOptimized: 80061 -// gas ssaCFGOptimized code: 334000 +// gas ssaCFGOptimized: 79851 +// gas ssaCFGOptimized code: 331600 // encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 // encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" // encode_inline_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8=" @@ -61,9 +61,9 @@ contract test { // gas irOptimized: 1406025 // gas legacy: 1554038 // gas legacyOptimized: 1132031 -// gas ssaCFGOptimized: 1391025 +// gas ssaCFGOptimized: 1388025 // encode_no_asm_large() // gas irOptimized: 3512081 // gas legacy: 4600082 // gas legacyOptimized: 2813075 -// gas ssaCFGOptimized: 3097081 +// gas ssaCFGOptimized: 3078081 diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index 8645cf4a2..baa951e71 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -185,8 +185,8 @@ contract DepositContract is IDepositContract, ERC165 { // gas legacy code: 1438800 // gas legacyOptimized: 848699 // gas legacyOptimized code: 878200 -// gas ssaCFGOptimized: 809791 -// gas ssaCFGOptimized code: 571600 +// gas ssaCFGOptimized: 809663 +// gas ssaCFGOptimized code: 570000 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # @@ -195,14 +195,14 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 -// gas ssaCFGOptimized: 110004 +// gas ssaCFGOptimized: 109748 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 -// gas ssaCFGOptimized: 110004 +// gas ssaCFGOptimized: 109748 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 @@ -210,7 +210,7 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 110000 +// gas ssaCFGOptimized: 109744 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 @@ -218,5 +218,5 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 110000 +// gas ssaCFGOptimized: 109744 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index e9cb3dc2b..ad32fdc15 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -57,8 +57,8 @@ contract test { // gas legacy code: 2205000 // gas legacyOptimized: 178012 // gas legacyOptimized code: 1669600 -// gas ssaCFGOptimized: 176529 -// gas ssaCFGOptimized code: 1658000 +// gas ssaCFGOptimized: 175048 +// gas ssaCFGOptimized code: 1639600 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22045 // gas legacy: 22736 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index 75b4fb432..a1455723b 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -57,8 +57,8 @@ contract test { // gas legacy code: 1999000 // gas legacyOptimized: 168857 // gas legacyOptimized code: 1556200 -// gas ssaCFGOptimized: 167966 -// gas ssaCFGOptimized code: 1549000 +// gas ssaCFGOptimized: 167591 +// gas ssaCFGOptimized code: 1544400 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 21912 // gas legacy: 22475 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index 5b2d8b559..8911b6bfb 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -42,8 +42,8 @@ contract test { // gas legacy code: 523600 // gas legacyOptimized: 82667 // gas legacyOptimized code: 369200 -// gas ssaCFGOptimized: 79327 -// gas ssaCFGOptimized code: 330600 +// gas ssaCFGOptimized: 77958 +// gas ssaCFGOptimized code: 313800 // prb_pi() -> 3141592656369545286 // gas irOptimized: 55036 // gas legacy: 100657 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index ff56e6017..79c5673d7 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -297,10 +297,10 @@ contract Test { // gas irOptimized: 275229 // gas legacy: 293579 // gas legacyOptimized: 276313 -// gas ssaCFGOptimized: 275803 +// gas ssaCFGOptimized: 275790 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." // gas irOptimized: 818076 // gas legacy: 904397 // gas legacyOptimized: 816770 -// gas ssaCFGOptimized: 820449 +// gas ssaCFGOptimized: 820095 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 536fd711c..b5a32db74 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -58,8 +58,8 @@ contract test { // gas legacy code: 932600 // gas legacyOptimized: 102639 // gas legacyOptimized code: 612400 -// gas ssaCFGOptimized: 97396 -// gas ssaCFGOptimized code: 547200 +// gas ssaCFGOptimized: 96272 +// gas ssaCFGOptimized code: 533600 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22646 // gas legacy: 23168 @@ -80,4 +80,4 @@ contract test { // gas irOptimized: 1976778 // gas legacy: 4234020 // gas legacyOptimized: 2318668 -// gas ssaCFGOptimized: 2080190 +// gas ssaCFGOptimized: 1882356 diff --git a/test/libyul/ssa/stackLayoutGenerator/nested_for.yul b/test/libyul/ssa/stackLayoutGenerator/nested_for.yul index f595c19b2..0d37b16e5 100644 --- a/test/libyul/ssa/stackLayoutGenerator/nested_for.yul +++ b/test/libyul/ssa/stackLayoutGenerator/nested_for.yul @@ -56,62 +56,62 @@ // Block0_4Exit [label="MainExit"]; // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ -// IN: [phi0, JUNK, phi1, phi3]\l\ +// IN: [phi0, phi3, phi1]\l\ // \l\ -// [phi0, JUNK, phi1, phi3, lit1, phi1]\l\ +// [phi0, phi3, phi1, lit1, phi1]\l\ // lt\l\ -// [phi0, JUNK, phi1, phi3, v1]\l\ +// [phi0, phi3, phi1, v1]\l\ // \l\ -// OUT: [phi0, JUNK, phi1, phi3, v1]\l\ +// OUT: [phi0, phi3, phi1, v1]\l\ // "]; // Block0_5 -> Block0_5Exit; // Block0_5Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_5Exit:0 -> Block0_8 [style="solid"]; // Block0_5Exit:1 -> Block0_6 [style="solid"]; // Block0_6 [label="\ -// IN: [phi0, JUNK, phi1, phi3]\l\ +// IN: [phi0, phi3, phi1]\l\ // \l\ -// [phi0, JUNK, phi1, phi3, phi1, phi0]\l\ +// [phi0, phi3, phi1, phi1, phi0]\l\ // mul\l\ -// [phi0, JUNK, phi1, phi3, v2]\l\ +// [phi0, phi3, phi1, v2]\l\ // \l\ -// [phi0, JUNK, phi1, v2, phi3]\l\ +// [phi0, phi1, v2, phi3]\l\ // add\l\ -// [phi0, JUNK, phi1, v3]\l\ +// [phi0, phi1, v3]\l\ // \l\ -// OUT: [phi0, JUNK, phi1, v3]\l\ +// OUT: [phi0, phi1, v3]\l\ // "]; // Block0_6 -> Block0_6Exit [arrowhead=none]; // Block0_6Exit [label="Jump" shape=oval]; // Block0_6Exit -> Block0_7 [style="solid"]; // Block0_8 [label="\ -// IN: [phi0, JUNK, JUNK, phi3]\l\ +// IN: [phi0, phi3, JUNK]\l\ // \l\ -// OUT: [phi0, JUNK, JUNK, phi3]\l\ +// OUT: [phi0, phi3, JUNK]\l\ // "]; // Block0_8 -> Block0_8Exit [arrowhead=none]; // Block0_8Exit [label="Jump" shape=oval]; // Block0_8Exit -> Block0_3 [style="solid"]; // Block0_7 [label="\ -// IN: [phi0, JUNK, phi1, v3]\l\ +// IN: [phi0, phi1, v3]\l\ // \l\ -// [phi0, JUNK, v3, lit2, phi1]\l\ +// [phi0, v3, lit2, phi1]\l\ // add\l\ -// [phi0, JUNK, v3, v4]\l\ +// [phi0, v3, v4]\l\ // \l\ -// OUT: [phi0, JUNK, v3, v4]\l\ +// OUT: [phi0, v3, v4]\l\ // "]; // Block0_7 -> Block0_7Exit [arrowhead=none]; // Block0_7Exit [label="Jump" shape=oval]; // Block0_7Exit -> Block0_5 [style="solid"]; // Block0_3 [label="\ -// IN: [phi0, JUNK, JUNK, phi3]\l\ +// IN: [phi0, phi3, JUNK]\l\ // \l\ -// [phi3, JUNK, JUNK, lit2, phi0]\l\ +// [JUNK, phi3, lit2, phi0]\l\ // add\l\ -// [phi3, JUNK, JUNK, v5]\l\ +// [JUNK, phi3, v5]\l\ // \l\ -// OUT: [phi3, JUNK, JUNK, v5]\l\ +// OUT: [JUNK, phi3, v5]\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; From 0cbd39c364eb64bf891359dfccbb96687d906da3 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 1 Apr 2026 11:06:34 +0200 Subject: [PATCH 1227/1340] Only use gas accumulating callbacks in stack layout generator where needed --- libyul/backends/evm/ssa/StackLayoutGenerator.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 924723133..7d3f0ae0a 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -64,7 +64,7 @@ void handlePhiFunctions(StackData& _stackData, PhiInverse const& _phiInverse, Li } } -using StackType = Stack; +using StackType = Stack<>; void declareJunk(StackType& _stack, LivenessAnalysis::LivenessData const& _live) { @@ -185,7 +185,7 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) proposals[i] = *parentExits[i].second; handlePhiFunctions(proposals[i], PhiInverse(m_cfg, parentExits[i].first, _blockId), liveIn); { - StackType stack(proposals[i], {.cfg = m_cfg}); + StackType stack(proposals[i], {}); declareJunk(stack, liveIn); } } @@ -200,8 +200,8 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) if (j == i || !parentExits[j].second) continue; auto proposalCopy = proposals[j]; - StackType stack(proposalCopy, {.cfg = m_cfg}); - StackShuffler::shuffle( + Stack stack(proposalCopy, {.cfg = m_cfg}); + StackShuffler::shuffle( stack, proposals[i], {}, @@ -214,7 +214,6 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) auto const argMin = static_cast( std::distance(cumulativeCosts.begin(), ranges::min_element(cumulativeCosts)) ); - yulAssert(parentExits[argMin].second); blockLayout.stackIn = std::move(proposals[argMin]); } m_resultLayout[_blockId] = blockLayout; @@ -229,7 +228,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) SSACFG::BasicBlock const& block = m_cfg.block(_blockId); StackData currentStackData = blockLayout.stackIn; - StackType stack(currentStackData, {.cfg = m_cfg}); + StackType stack(currentStackData, {}); bool const junkCanBeAdded = m_junkAdmittingBlocksFinder->allowsAdditionOfJunk(_blockId); auto const& operationsLiveOut = m_liveness.operationsLiveOut(_blockId); From a431a6695bbab332ab94eaea75978f7e063db54e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 1 Apr 2026 12:09:33 +0200 Subject: [PATCH 1228/1340] Change SSA stack layout to have exitIn instead of stackOut and save block successor proposals per-edge --- libyul/backends/evm/ssa/CodeTransform.cpp | 2 +- libyul/backends/evm/ssa/StackLayout.h | 4 +- .../backends/evm/ssa/StackLayoutGenerator.cpp | 187 +++++++++--------- .../backends/evm/ssa/StackLayoutGenerator.h | 4 + .../externalContracts/prbmath_signed.sol | 4 +- .../externalContracts/ramanujan_pi.sol | 4 +- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 2 +- 7 files changed, 110 insertions(+), 97 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 73a676330..8f3a51f47 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -185,7 +185,7 @@ void CodeTransform::operator()(SSACFG::BlockId const _blockId) // Shuffle to the block's exit layout before dispatching the exit. // This ensures the condition is on top for ConditionalJump, phi pre-images are // in the right positions for jumps, and return values are accessible for FunctionReturn. - StackShuffler::shuffle(m_stack, blockLayout->stackOut); + StackShuffler::shuffle(m_stack, blockLayout->exitIn); // handle the block exit std::visit(util::GenericVisitor{ [this, &_blockId](auto const& exit) { (*this)(_blockId, exit); } }, block.exit); diff --git a/libyul/backends/evm/ssa/StackLayout.h b/libyul/backends/evm/ssa/StackLayout.h index d0cd81972..4d3833932 100644 --- a/libyul/backends/evm/ssa/StackLayout.h +++ b/libyul/backends/evm/ssa/StackLayout.h @@ -31,8 +31,8 @@ struct BlockLayout StackData stackIn; // stack layout required to execute the i-th operation in the block std::vector operationIn; - // stack after the block was executed - StackData stackOut; + // stack layout required to handle the exit of the block + StackData exitIn; }; /// For each (reachable) block in the SSACFG one block layout diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 7d3f0ae0a..6e98e1a5a 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -23,8 +23,9 @@ #include #include +#include + #include -#include #include #include #include @@ -98,6 +99,7 @@ StackLayoutGenerator::StackLayoutGenerator( m_graphID(_graphID), m_hasFunctionReturnLabel(_liveness.cfg().function && _liveness.cfg().canContinue), m_junkAdmittingBlocksFinder(std::make_unique(_liveness.cfg(), _liveness.topologicalSort())), + m_inputStackProposalsPerBlock(m_cfg.numBlocks()), m_resultLayout(m_cfg.numBlocks()) { // traverse the cfg layer-wise using Kahn's algorithm: @@ -156,49 +158,37 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) auto const& block = m_cfg.block(_blockId); - std::vector> parentExits; - for (auto const& entry: block.entries) - if (m_resultLayout[entry]) - parentExits.emplace_back(entry, &m_resultLayout[entry]->stackOut); - - yulAssert(!parentExits.empty(), fmt::format("None of the parents of block {} were generated", _blockId)); + auto const& stackInProposals = m_inputStackProposalsPerBlock[_blockId.value]; + yulAssert(!stackInProposals.empty(), fmt::format("None of the parents of block {} were generated", _blockId)); if (block.entries.size() == 1) { // pass through - yulAssert(parentExits.size() == 1); - blockLayout.stackIn = *parentExits[0].second; - - if (!block.phis.empty()) - handlePhiFunctions(blockLayout.stackIn, PhiInverse(m_cfg, parentExits[0].first, _blockId), m_liveness.liveIn(_blockId)); + yulAssert(stackInProposals.size() == 1); + blockLayout.stackIn = stackInProposals[0].second; + handlePhiFunctions(blockLayout.stackIn, PhiInverse(m_cfg, stackInProposals[0].first, _blockId), m_liveness.liveIn(_blockId)); } else { // we have more than one entry and need to unify or at the very least apply phi fct. auto const& liveIn = m_liveness.liveIn(_blockId); // Pre-compute each parent's proposal - std::vector proposals(parentExits.size()); - for (std::size_t i = 0; i < parentExits.size(); ++i) + std::vector proposals(stackInProposals.size()); + for (std::size_t i = 0; i < stackInProposals.size(); ++i) { - if (!parentExits[i].second) - continue; - proposals[i] = *parentExits[i].second; - handlePhiFunctions(proposals[i], PhiInverse(m_cfg, parentExits[i].first, _blockId), liveIn); + proposals[i] = stackInProposals[i].second; + handlePhiFunctions(proposals[i], PhiInverse(m_cfg, stackInProposals[i].first, _blockId), liveIn); { StackType stack(proposals[i], {}); declareJunk(stack, liveIn); } } - std::vector cumulativeCosts(parentExits.size(), std::numeric_limits::max()); - for (std::size_t i = 0; i < parentExits.size(); ++i) + std::vector cumulativeCosts(stackInProposals.size(), std::numeric_limits::max()); + for (std::size_t i = 0; i < stackInProposals.size(); ++i) { - if (!parentExits[i].second) - continue; std::size_t cumulativeCost = 0; - for (std::size_t j = 0; j < parentExits.size(); ++j) + for (std::size_t j = 0; j < stackInProposals.size(); ++j) { - if (j == i || !parentExits[j].second) - continue; auto proposalCopy = proposals[j]; Stack stack(proposalCopy, {.cfg = m_cfg}); StackShuffler::shuffle( @@ -211,10 +201,12 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) } cumulativeCosts[i] = cumulativeCost; } - auto const argMin = static_cast( - std::distance(cumulativeCosts.begin(), ranges::min_element(cumulativeCosts)) - ); - blockLayout.stackIn = std::move(proposals[argMin]); + // Pick the proposal with the lowest cost; break ties by preferring smaller stacks + std::size_t best = 0; + for (std::size_t i = 1; i < stackInProposals.size(); ++i) + if (std::make_pair(cumulativeCosts[i], proposals[i].size()) < std::make_pair(cumulativeCosts[best], proposals[best].size())) + best = i; + blockLayout.stackIn = std::move(proposals[best]); } m_resultLayout[_blockId] = blockLayout; } @@ -280,65 +272,82 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) stack.push(Slot::makeValueID(val)); } - if (auto const* cjump = std::get_if(&block.exit)) - { - auto const& zeroLiveIn = m_liveness.liveIn(cjump->zero); - auto const& blockLiveOut = m_liveness.liveOut(_blockId); - - // check if we have to do anything (dup the condition, bring it to the top etc) - bool const conditionSlotAlreadyFinal = - !blockLiveOut.contains(cjump->condition) && // if our live out does not contain the condition (ie we dont have to dup it) - !stack.empty() && // our stack is not empty - stack.top().isValueID() && stack.top().valueID() == cjump->condition; // and the condition is already on top - if (!conditionSlotAlreadyFinal) - { - auto const condition = Slot::makeValueID(cjump->condition); - auto const targetSize = findOptimalTargetSize( - stack.data(), - {condition}, - blockLiveOut, - false, - m_hasFunctionReturnLabel - ); - StackShuffler::shuffle( - stack, {condition}, blockLiveOut, targetSize - ); - } - - yulAssert(!stack.empty() && stack.top().isValueID() && stack.top().valueID() == cjump->condition); - yulAssert(m_cfg.block(cjump->nonZero).phis.empty()); - - // define zero and non-zero stack in layouts - { - std::optional& nonZeroLayout = m_resultLayout[cjump->nonZero]; - yulAssert(!nonZeroLayout, "There should be no way to reach this block other than by going through the parent."); - nonZeroLayout = BlockLayout{}; - nonZeroLayout->stackIn = currentStackData; - // Remove condition; consumed by JUMPI - nonZeroLayout->stackIn.pop_back(); - - if ( - std::optional& zeroLayout = m_resultLayout[cjump->zero]; - !zeroLayout - ) - { - // same as nonzero stack in initially - zeroLayout = nonZeroLayout; - handlePhiFunctions(zeroLayout->stackIn, PhiInverse(m_cfg, _blockId, cjump->zero), zeroLiveIn); - StackType zeroStack(zeroLayout->stackIn, {.cfg = m_cfg}); - declareJunk(zeroStack, zeroLiveIn); + std::visit( + util::GenericVisitor{ + [&](SSACFG::BasicBlock::ConditionalJump const& _cJump) { + auto const& zeroLiveIn = m_liveness.liveIn(_cJump.zero); + auto const& blockLiveOut = m_liveness.liveOut(_blockId); + + // check if we have to do anything (dup the condition, bring it to the top etc) + bool const conditionSlotAlreadyFinal = + !blockLiveOut.contains(_cJump.condition) && // if our live out does not contain the condition (ie we dont have to dup it) + !stack.empty() && // our stack is not empty + stack.top().isValueID() && stack.top().valueID() == _cJump.condition; // and the condition is already on top + if (!conditionSlotAlreadyFinal) + { + auto const condition = Slot::makeValueID(_cJump.condition); + auto const targetSize = findOptimalTargetSize( + stack.data(), + {condition}, + blockLiveOut, + false, + m_hasFunctionReturnLabel + ); + StackShuffler::shuffle( + stack, {condition}, blockLiveOut, targetSize + ); + } + + yulAssert(!stack.empty() && stack.top().isValueID() && stack.top().valueID() == _cJump.condition); + yulAssert(m_cfg.block(_cJump.nonZero).phis.empty()); + + // exitIn = pre-JUMPI state (condition on top) for CodeTransform + blockLayout.exitIn = currentStackData; + + // Pop condition from symbolic stack (consumed by JUMPI). + // After this, currentStackData reflects the post-JUMPI stack. + stack.pop(); + + // Define successor stack-in layouts + { + // nonZero is always single-entry + std::optional& nonZeroLayout = m_resultLayout[_cJump.nonZero]; + yulAssert(!nonZeroLayout, "There should be no way to reach this block other than by going through the parent."); + nonZeroLayout = BlockLayout{}; + nonZeroLayout->stackIn = currentStackData; + + if ( + std::optional& zeroLayout = m_resultLayout[_cJump.zero]; + !zeroLayout + ) + { + zeroLayout = BlockLayout{}; + zeroLayout->stackIn = currentStackData; + handlePhiFunctions(zeroLayout->stackIn, PhiInverse(m_cfg, _blockId, _cJump.zero), zeroLiveIn); + StackType zeroStack(zeroLayout->stackIn, {}); + declareJunk(zeroStack, zeroLiveIn); + } + } + }, + [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { + yulAssert(m_hasFunctionReturnLabel, "When there is a proper function return, we need to have a label for it"); + // in case there are return values, let's bring the function return label to the top + StackData returnStack = _functionReturn.returnValues | ranges::views::transform(StackSlot::makeValueID) | ranges::to; + returnStack.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); + StackShuffler::shuffle(stack, returnStack); + blockLayout.exitIn = currentStackData; + }, + [&](SSACFG::BasicBlock::Jump const& _jump) { + blockLayout.exitIn = currentStackData; + m_inputStackProposalsPerBlock[_jump.target.value].emplace_back(_blockId, currentStackData); + }, + [&](SSACFG::BasicBlock::MainExit const&) { + blockLayout.exitIn = currentStackData; + }, + [&](SSACFG::BasicBlock::Terminated const&) { + blockLayout.exitIn = currentStackData; } - } - } - - if (auto const* functionReturn = std::get_if(&block.exit)) - { - yulAssert(m_hasFunctionReturnLabel, "When there is a proper function return, we need to have a label for it"); - // in case there are return values, let's bring the function return label to the top - StackData returnStack = functionReturn->returnValues | ranges::views::transform(StackSlot::makeValueID) | ranges::to; - returnStack.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); - StackShuffler::shuffle(stack, returnStack); - } - - blockLayout.stackOut = currentStackData; + }, + block.exit + ); } diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.h b/libyul/backends/evm/ssa/StackLayoutGenerator.h index b14586404..07af8d293 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.h +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.h @@ -55,6 +55,10 @@ class StackLayoutGenerator bool m_hasFunctionReturnLabel; std::unique_ptr m_junkAdmittingBlocksFinder; + // Per-edge stack proposals for defineStackIn. + // m_inputStackProposalsPerBlock[blockId] contains (predecessorId, edgeStack) pairs + // representing the stack state flowing from each predecessor into the block. + std::vector>> m_inputStackProposalsPerBlock; SSACFGStackLayout m_resultLayout; }; diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index ad32fdc15..3d635ce0f 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -57,8 +57,8 @@ contract test { // gas legacy code: 2205000 // gas legacyOptimized: 178012 // gas legacyOptimized code: 1669600 -// gas ssaCFGOptimized: 175048 -// gas ssaCFGOptimized code: 1639600 +// gas ssaCFGOptimized: 175028 +// gas ssaCFGOptimized code: 1639200 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22045 // gas legacy: 22736 diff --git a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol index 8911b6bfb..44208308a 100644 --- a/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol +++ b/test/libsolidity/semanticTests/externalContracts/ramanujan_pi.sol @@ -42,8 +42,8 @@ contract test { // gas legacy code: 523600 // gas legacyOptimized: 82667 // gas legacyOptimized code: 369200 -// gas ssaCFGOptimized: 77958 -// gas ssaCFGOptimized code: 313800 +// gas ssaCFGOptimized: 77956 +// gas ssaCFGOptimized code: 313400 // prb_pi() -> 3141592656369545286 // gas irOptimized: 55036 // gas legacy: 100657 diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index 1aaab7db0..34bbf70e4 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -104,7 +104,7 @@ class StackLayoutDotExporter: public io::DotExporterBase } _out << "\\l\\\n"; - _out << "OUT: " << stackToString(blockLayout->stackOut) << "\\l\\\n"; + _out << "OUT: " << stackToString(blockLayout->exitIn) << "\\l\\\n"; } private: From c9f62baf664752958f10a8125c114309fdf3cffd Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 1 Apr 2026 15:53:02 +0200 Subject: [PATCH 1229/1340] Add "exitIn" to codespell whitelist --- scripts/codespell_whitelist.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/codespell_whitelist.txt b/scripts/codespell_whitelist.txt index e3a45b947..bd0e201b6 100644 --- a/scripts/codespell_whitelist.txt +++ b/scripts/codespell_whitelist.txt @@ -3,3 +3,4 @@ compilability keypair wast slippy +exitIn From d211fb2aa405f72772fdc07e4c3b00436a50197b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 1 Apr 2026 14:39:54 +0200 Subject: [PATCH 1230/1340] handle conditional jump exits uniformly --- .../backends/evm/ssa/StackLayoutGenerator.cpp | 29 ++++--------------- .../externalContracts/FixedFeeRegistrar.sol | 4 +-- .../externalContracts/base64.sol | 6 ++-- .../externalContracts/prbmath_signed.sol | 4 +-- .../externalContracts/prbmath_unsigned.sol | 4 +-- .../semanticTests/externalContracts/snark.sol | 4 +-- .../externalContracts/strings.sol | 6 ++-- .../ssa/stackLayoutGenerator/dead_code.yul | 4 +-- .../ssa/stackLayoutGenerator/simple_if.yul | 2 +- .../ssa/stackLayoutGenerator/switch.yul | 4 +-- 10 files changed, 25 insertions(+), 42 deletions(-) diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 6e98e1a5a..d20ecaccb 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -157,6 +157,7 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) } auto const& block = m_cfg.block(_blockId); + auto const& liveIn = m_liveness.liveIn(_blockId); auto const& stackInProposals = m_inputStackProposalsPerBlock[_blockId.value]; yulAssert(!stackInProposals.empty(), fmt::format("None of the parents of block {} were generated", _blockId)); @@ -166,12 +167,12 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) // pass through yulAssert(stackInProposals.size() == 1); blockLayout.stackIn = stackInProposals[0].second; - handlePhiFunctions(blockLayout.stackIn, PhiInverse(m_cfg, stackInProposals[0].first, _blockId), m_liveness.liveIn(_blockId)); + handlePhiFunctions(blockLayout.stackIn, PhiInverse(m_cfg, stackInProposals[0].first, _blockId), liveIn); + StackType stack(blockLayout.stackIn, {}); + declareJunk(stack, liveIn); } else { - // we have more than one entry and need to unify or at the very least apply phi fct. - auto const& liveIn = m_liveness.liveIn(_blockId); // Pre-compute each parent's proposal std::vector proposals(stackInProposals.size()); for (std::size_t i = 0; i < stackInProposals.size(); ++i) @@ -275,7 +276,6 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) std::visit( util::GenericVisitor{ [&](SSACFG::BasicBlock::ConditionalJump const& _cJump) { - auto const& zeroLiveIn = m_liveness.liveIn(_cJump.zero); auto const& blockLiveOut = m_liveness.liveOut(_blockId); // check if we have to do anything (dup the condition, bring it to the top etc) @@ -309,25 +309,8 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) stack.pop(); // Define successor stack-in layouts - { - // nonZero is always single-entry - std::optional& nonZeroLayout = m_resultLayout[_cJump.nonZero]; - yulAssert(!nonZeroLayout, "There should be no way to reach this block other than by going through the parent."); - nonZeroLayout = BlockLayout{}; - nonZeroLayout->stackIn = currentStackData; - - if ( - std::optional& zeroLayout = m_resultLayout[_cJump.zero]; - !zeroLayout - ) - { - zeroLayout = BlockLayout{}; - zeroLayout->stackIn = currentStackData; - handlePhiFunctions(zeroLayout->stackIn, PhiInverse(m_cfg, _blockId, _cJump.zero), zeroLiveIn); - StackType zeroStack(zeroLayout->stackIn, {}); - declareJunk(zeroStack, zeroLiveIn); - } - } + m_inputStackProposalsPerBlock[_cJump.zero.value].emplace_back(_blockId, currentStackData); + m_inputStackProposalsPerBlock[_cJump.nonZero.value].emplace_back(_blockId, currentStackData); }, [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { yulAssert(m_hasFunctionReturnLabel, "When there is a proper function return, we need to have a label for it"); diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol index 35e22c41c..9ac85f9c8 100644 --- a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -83,8 +83,8 @@ contract FixedFeeRegistrar is Registrar { // gas legacy code: 792400 // gas legacyOptimized: 84598 // gas legacyOptimized code: 388000 -// gas ssaCFGOptimized: 78828 -// gas ssaCFGOptimized code: 321600 +// gas ssaCFGOptimized: 78844 +// gas ssaCFGOptimized code: 321800 // reserve(string), 69 ether: 0x20, 3, "abc" -> // ~ emit Changed(string): #0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 // gas irOptimized: 45741 diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol index ef7ef1ddf..93799e936 100644 --- a/test/libsolidity/semanticTests/externalContracts/base64.sol +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -41,8 +41,8 @@ contract test { // gas legacy code: 629800 // gas legacyOptimized: 87926 // gas legacyOptimized code: 429800 -// gas ssaCFGOptimized: 79851 -// gas ssaCFGOptimized code: 331600 +// gas ssaCFGOptimized: 79931 +// gas ssaCFGOptimized code: 332600 // encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 // encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" // encode_inline_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8=" @@ -66,4 +66,4 @@ contract test { // gas irOptimized: 3512081 // gas legacy: 4600082 // gas legacyOptimized: 2813075 -// gas ssaCFGOptimized: 3078081 +// gas ssaCFGOptimized: 3089081 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol index 3d635ce0f..ad32fdc15 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_signed.sol @@ -57,8 +57,8 @@ contract test { // gas legacy code: 2205000 // gas legacyOptimized: 178012 // gas legacyOptimized code: 1669600 -// gas ssaCFGOptimized: 175028 -// gas ssaCFGOptimized code: 1639200 +// gas ssaCFGOptimized: 175048 +// gas ssaCFGOptimized code: 1639600 // div(int256,int256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 22045 // gas legacy: 22736 diff --git a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol index a1455723b..2f681baa4 100644 --- a/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol +++ b/test/libsolidity/semanticTests/externalContracts/prbmath_unsigned.sol @@ -57,8 +57,8 @@ contract test { // gas legacy code: 1999000 // gas legacyOptimized: 168857 // gas legacyOptimized code: 1556200 -// gas ssaCFGOptimized: 167591 -// gas ssaCFGOptimized code: 1544400 +// gas ssaCFGOptimized: 167611 +// gas ssaCFGOptimized code: 1544800 // div(uint256,uint256): 3141592653589793238, 88714123 -> 35412542528203691288251815328 // gas irOptimized: 21912 // gas legacy: 22475 diff --git a/test/libsolidity/semanticTests/externalContracts/snark.sol b/test/libsolidity/semanticTests/externalContracts/snark.sol index 79c5673d7..f7e450487 100644 --- a/test/libsolidity/semanticTests/externalContracts/snark.sol +++ b/test/libsolidity/semanticTests/externalContracts/snark.sol @@ -297,10 +297,10 @@ contract Test { // gas irOptimized: 275229 // gas legacy: 293579 // gas legacyOptimized: 276313 -// gas ssaCFGOptimized: 275790 +// gas ssaCFGOptimized: 275795 // verifyTx() -> true // ~ emit Verified(string): 0x20, 0x16, "Successfully verified." // gas irOptimized: 818076 // gas legacy: 904397 // gas legacyOptimized: 816770 -// gas ssaCFGOptimized: 820095 +// gas ssaCFGOptimized: 820130 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index b5a32db74..9bd1f39a0 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -58,8 +58,8 @@ contract test { // gas legacy code: 932600 // gas legacyOptimized: 102639 // gas legacyOptimized code: 612400 -// gas ssaCFGOptimized: 96272 -// gas ssaCFGOptimized code: 533600 +// gas ssaCFGOptimized: 96160 +// gas ssaCFGOptimized code: 532200 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22646 // gas legacy: 23168 @@ -80,4 +80,4 @@ contract test { // gas irOptimized: 1976778 // gas legacy: 4234020 // gas legacyOptimized: 2318668 -// gas ssaCFGOptimized: 1882356 +// gas ssaCFGOptimized: 1882355 diff --git a/test/libyul/ssa/stackLayoutGenerator/dead_code.yul b/test/libyul/ssa/stackLayoutGenerator/dead_code.yul index fa7623197..c95ced760 100644 --- a/test/libyul/ssa/stackLayoutGenerator/dead_code.yul +++ b/test/libyul/ssa/stackLayoutGenerator/dead_code.yul @@ -31,7 +31,7 @@ // Block0_0Exit:0 -> Block0_2 [style="solid"]; // Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ -// IN: [v0]\l\ +// IN: [JUNK]\l\ // \l\ // [JUNK, lit0, lit0]\l\ // revert\l\ @@ -55,7 +55,7 @@ // Block0_2Exit:0 -> Block0_5 [style="solid"]; // Block0_2Exit:1 -> Block0_4 [style="solid"]; // Block0_4 [label="\ -// IN: [v0, v1]\l\ +// IN: [JUNK, JUNK]\l\ // \l\ // [JUNK, JUNK, lit0, lit0]\l\ // revert\l\ diff --git a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul index a93ced983..c2f6a6c83 100644 --- a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul +++ b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul @@ -48,7 +48,7 @@ // Block1_0Exit:0 -> Block1_2 [style="solid"]; // Block1_0Exit:1 -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// IN: [ReturnLabel[1], v1, v0]\l\ +// IN: [ReturnLabel[1], JUNK, v0]\l\ // \l\ // [ReturnLabel[1], JUNK, lit1, v0]\l\ // add\l\ diff --git a/test/libyul/ssa/stackLayoutGenerator/switch.yul b/test/libyul/ssa/stackLayoutGenerator/switch.yul index 3ed060236..ba7e841a0 100644 --- a/test/libyul/ssa/stackLayoutGenerator/switch.yul +++ b/test/libyul/ssa/stackLayoutGenerator/switch.yul @@ -41,9 +41,9 @@ // Block0_0Exit:0 -> Block0_3 [style="solid"]; // Block0_0Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// IN: [v0]\l\ +// IN: [JUNK]\l\ // \l\ -// OUT: [v0]\l\ +// OUT: [JUNK]\l\ // "]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; From ca7d54c3e058d12111c17978c7de8a820f1c3b8f Mon Sep 17 00:00:00 2001 From: r0qs <457348+r0qs@users.noreply.github.com> Date: Wed, 15 Oct 2025 16:51:45 +0200 Subject: [PATCH 1231/1340] Move coding-style check to GitHub actions Co-authored-by: Heath Dutton --- .circleci/config.yml | 20 ------ .github/workflows/code-style.yml | 81 +++++++++++++++++++++++ scripts/check_style.sh | 58 ++++++++-------- scripts/ci/post_style_errors_on_github.sh | 55 --------------- 4 files changed, 112 insertions(+), 102 deletions(-) create mode 100644 .github/workflows/code-style.yml delete mode 100755 scripts/ci/post_style_errors_on_github.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 245edf3d8..8f2dd5611 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1002,25 +1002,6 @@ jobs: command: test/docsCodeStyle.sh - matrix_notify_failure_unless_pr - chk_coding_style: - <<: *base_cimg_small - steps: - - checkout - - run: - name: Install shellcheck - command: | - sudo apt -q update - sudo apt install -y shellcheck - - run: - name: Check for C++ coding style - command: scripts/check_style.sh - - run: - name: checking shell scripts - command: scripts/chk_shellscripts/chk_shellscripts.sh - - run: - name: Check for broken symlinks - command: scripts/check_symlinks.sh - - matrix_notify_failure_unless_pr chk_errorcodes: <<: *base_ubuntu2404_small @@ -2094,7 +2075,6 @@ workflows: jobs: # basic checks - chk_spelling: *requires_nothing - - chk_coding_style: *requires_nothing # DISABLED FOR 0.6.0 - chk_docs_examples: *requires_nothing - chk_buglist: *requires_nothing - chk_proofs: *requires_nothing diff --git a/.github/workflows/code-style.yml b/.github/workflows/code-style.yml new file mode 100644 index 000000000..65a627478 --- /dev/null +++ b/.github/workflows/code-style.yml @@ -0,0 +1,81 @@ +name: Code Style Check + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + pull-requests: write + contents: read + +jobs: + chk_coding_style: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + + - name: Install dependencies + run: | + sudo apt --quiet update + sudo apt install --yes shellcheck git openssl + + - name: Check for C++ coding style + id: style-check + run: | + output=$(scripts/check_style.sh 2>&1) || { + delimiter="$(openssl rand -hex 8)" + { + echo "output<<${delimiter}" + echo "$output" + echo "${delimiter}" + } >> "$GITHUB_OUTPUT" + exit 1 + } + + - name: Comment PR on failure + if: ${{ failure() && steps.style-check.outcome == 'failure' }} + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd #v8.0.0 + env: + STYLE_OUTPUT: ${{ steps.style-check.outputs.output }} + with: + script: | + const output = process.env.STYLE_OUTPUT; + const headSha = context.payload.pull_request.head.sha; + const body = `There was an error when running \`Code Style Check\` for commit \`${headSha}\`: + \`\`\` + ${output} + \`\`\` + Please check that your changes are working as intended.`; + + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: body + }); + + for (const line of output.split('\n')) { + const match = line.match(/^\[([^\]]+)\]\s*([^:]+\.(cpp|h)):(\d+):/); + if (!match) continue; + const [, errorDescription, filePath, , lineNumber] = match; + try { + await github.rest.pulls.createReviewComment({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + commit_id: headSha, + path: filePath, + line: parseInt(lineNumber), + side: 'RIGHT', + body: `**Coding style error:** ${errorDescription}` + }); + } catch (error) { + console.log(`Could not add inline comment for ${filePath}:${lineNumber}: ${error.message}`); + } + } + + - name: checking shell scripts + run: scripts/chk_shellscripts/chk_shellscripts.sh + + - name: Check for broken symlinks + run: scripts/check_symlinks.sh diff --git a/scripts/check_style.sh b/scripts/check_style.sh index 5a744de78..1a16f6dca 100755 --- a/scripts/check_style.sh +++ b/scripts/check_style.sh @@ -25,6 +25,17 @@ EXCLUDE_FILES_JOINED=${EXCLUDE_FILES_JOINED%??} REPO_ROOT="$(dirname "$0")"/.. cd "$REPO_ROOT" || exit 1 +function preparedGrep +{ + git grep -nIE "$1" -- '*.h' '*.cpp' ':!test/' | grep -v "${EXCLUDE_FILES_JOINED}" + return $? +} + +function addPrefix +{ + sed "s/^/[$1] /" +} + WHITESPACE=$(git grep -n -I -E "^.*[[:space:]]+$" | grep -v "test/libsolidity/ASTJSON\|test/compilationTests/zeppelin/LICENSE\|${EXCLUDE_FILES_JOINED}" || true ) @@ -32,34 +43,24 @@ WHITESPACE=$(git grep -n -I -E "^.*[[:space:]]+$" | if [[ "$WHITESPACE" != "" ]] then echo "Error: Trailing whitespace found:" | tee -a "$ERROR_LOG" - echo "$WHITESPACE" | tee -a "$ERROR_LOG" - scripts/ci/post_style_errors_on_github.sh "$ERROR_LOG" - exit 1 + echo "$WHITESPACE" | addPrefix "Trailing whitespace" | tee -a "$ERROR_LOG" fi -function preparedGrep -{ - git grep -nIE "$1" -- '*.h' '*.cpp' | grep -v "${EXCLUDE_FILES_JOINED}" - return $? -} - FORMATERROR=$( ( - preparedGrep "#include \"" | grep -E -v -e "license.h" -e "BuildInfo.h" # Use include with <> characters - preparedGrep "\<(if|for|while|switch)\(" # no space after "if", "for", "while" or "switch" - preparedGrep "\[[:space:]]*\([^=]*\>[[:space:]]:[[:space:]].*\)" # no space before range based for-loop - preparedGrep "\[[:space:]]*\(.*\)[[:space:]]*\{[[:space:]]*$" # "{\n" on same line as "if" - preparedGrep "namespace .*\{" - preparedGrep "[,\(<][[:space:]]*const " # const on left side of type - preparedGrep "^[[:space:]]*(static)?[[:space:]]*const " # const on left side of type (beginning of line) - preparedGrep "^ [^*]|[^*] | [^*]" # uses spaces for indentation or mixes spaces and tabs - preparedGrep "[a-zA-Z0-9_][[:space:]]*[&][a-zA-Z_]" | grep -E -v "return [&]" # right-aligned reference ampersand (needs to exclude return) - # right-aligned reference pointer star (needs to exclude return and comments) - preparedGrep "[a-zA-Z0-9_][[:space:]]*[*][a-zA-Z_]" | grep -E -v -e "return [*]" -e ":[0-9]+:[[:space:]]*\*[[:space:]]" -e "//" - # unqualified move()/forward() checks, i.e. make sure that std::move() and std::forward() are used instead of move() and forward() - preparedGrep "move\(.+\)" | grep -v "std::move" | grep -E "[^a-z]move" - preparedGrep "forward\(.+\)" | grep -v "std::forward" | grep -E "[^a-z]forward" -) | grep -E -v -e "^[a-zA-Z./]*:[0-9]*:[[:space:]]*/[/*]" -e "^test/" || true + preparedGrep "#include \"" | grep -E -v -e "license.h" -e "BuildInfo.h" | addPrefix "Use angle brackets for includes" + preparedGrep "\<(if|for|while|switch)\(" | addPrefix "Missing space after keyword" + preparedGrep "\[[:space:]]*\([^=]*\>[[:space:]]:[[:space:]].*\)" | addPrefix "Missing space before range-based for colon" + preparedGrep "\[[:space:]]*\(.*\)[[:space:]]*\{[[:space:]]*$" | addPrefix "Opening brace on same line as if" + preparedGrep "namespace .*\{" | addPrefix "Missing space before opening brace in namespace" + preparedGrep "[,\(<][[:space:]]*const " | addPrefix "const should be on the right side of the type" + preparedGrep "^[[:space:]]*(static)?[[:space:]]*const " | addPrefix "const should be on the right side of the type" + preparedGrep "^ [^*]|[^*] | [^*]" | addPrefix "Use tabs for indentation" + preparedGrep "[a-zA-Z0-9_][[:space:]]*[&][a-zA-Z_]" | grep -E -v "return [&]" | addPrefix "Reference ampersand should be left-aligned" + preparedGrep "[a-zA-Z0-9_][[:space:]]*[*][a-zA-Z_]" | grep -E -v -e "return [*]" -e ":[0-9]+:[[:space:]]*\*[[:space:]]" -e "//" | addPrefix "Pointer star should be left-aligned" + preparedGrep "move\(.+\)" | grep -v "std::move" | grep -E "[^a-z]move" | addPrefix "Use std::move" + preparedGrep "forward\(.+\)" | grep -v "std::forward" | grep -E "[^a-z]forward" | addPrefix "Use std::forward" +) | grep -E -v -e "^\[[^]]*\] [a-zA-Z./]*:[0-9]*:[[:space:]]*/[/*]" || true ) # Special error handling for `using namespace std;` exclusion, since said statement can be present in the test directory @@ -67,18 +68,21 @@ FORMATERROR=$( # std namespace usage, test directory must also be covered. FORMATSTDERROR=$( ( - git grep -nIE "using namespace std;" -- '*.h' '*.cpp' + git grep -nIE "using namespace std;" -- '*.h' '*.cpp' | addPrefix "Do not use 'using namespace std'" ) || true ) # Merge errors into single string -FORMATEDERRORS="$FORMATERROR$FORMATSTDERROR" +FORMATEDERRORS=$(printf '%s\n' "$FORMATERROR" "$FORMATSTDERROR" | grep -v '^$' || true) if [[ "$FORMATEDERRORS" != "" ]] then echo "Coding style error:" | tee -a "$ERROR_LOG" echo "$FORMATEDERRORS" | tee -a "$ERROR_LOG" - scripts/ci/post_style_errors_on_github.sh "$ERROR_LOG" +fi + +if [[ -s "$ERROR_LOG" ]] +then exit 1 fi ) diff --git a/scripts/ci/post_style_errors_on_github.sh b/scripts/ci/post_style_errors_on_github.sh deleted file mode 100755 index db7614179..000000000 --- a/scripts/ci/post_style_errors_on_github.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env bash - -ERROR_LOG="$1" - -function report_error_to_github -{ - [[ $CIRCLE_PR_NUMBER != "" ]] || CIRCLE_PR_NUMBER="${CIRCLE_PULL_REQUEST//[^0-9]/}" - - if [[ $CI == "true" ]] - then - echo "posting error message to github" - post_error_to_github - post_review_comment_to_github - fi -} - -function post_error_to_github -{ - GITHUB_API_URL="https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/issues/$CIRCLE_PR_NUMBER/comments" - - ESCAPED_ERROR_MSG=$(cat -e "$ERROR_LOG" | sed 's/\\/\\\\/g' | sed 's/"/\\\"/g') - - FORMATTED_ERROR_MSG=$(echo "$ESCAPED_ERROR_MSG" | sed 's/\$/\\n/g' | tr -d '\n') - - curl --request POST \ - --url "$GITHUB_API_URL" \ - --header 'accept: application/vnd.github.v3+json' \ - --header 'content-type: application/json' \ - -u "stackenbotten3000:$GITHUB_ACCESS_TOKEN" \ - --data "{\"body\": \"There was an error when running \`$CIRCLE_JOB\` for commit \`$CIRCLE_SHA1\`:\n\`\`\`\n$FORMATTED_ERROR_MSG\n\`\`\`\nPlease check that your changes are working as intended.\"}" -} - -function post_review_comment_to_github -{ - GITHUB_API_URL="https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/pulls/$CIRCLE_PR_NUMBER/comments" - - sed -i 1d "$ERROR_LOG" - - while read -r line - do - ERROR_PATH=$(echo "$line" | grep -oE ".*\.cpp") - ERROR_LINE=$(echo "$line" | grep -oE "[0-9]*") - [[ $ERROR_PATH != "" ]] || { echo "ERROR: Error message does not contain file path."; exit 1; } - [[ $ERROR_LINE != "" ]] || { echo "ERROR: Error message does not contain line number."; exit 1; } - - curl --request POST \ - --url "$GITHUB_API_URL" \ - --header 'accept: application/vnd.github.v3+json, application/vnd.github.comfort-fade-preview+json' \ - --header 'content-type: application/json' \ - -u "stackenbotten3000:$GITHUB_ACCESS_TOKEN" \ - --data "{\"commit_id\": \"$CIRCLE_SHA1\", \"path\": \"$ERROR_PATH\", \"line\": $ERROR_LINE, \"side\": \"RIGHT\", \"body\": \"Coding style error\"}" - done < "$ERROR_LOG" -} - -report_error_to_github From c3466bbd0fdf6afff9da0cbc18f5ed43903c23bc Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 2 Apr 2026 14:39:41 +0200 Subject: [PATCH 1232/1340] ssa stack shuffler returns status --- libyul/backends/evm/ssa/CodeTransform.cpp | 13 +- .../backends/evm/ssa/StackLayoutGenerator.cpp | 24 ++- libyul/backends/evm/ssa/StackShuffler.h | 186 +++++++++++------- libyul/backends/evm/ssa/StackUtils.cpp | 3 +- 4 files changed, 138 insertions(+), 88 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 8f3a51f47..caca86153 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -185,7 +185,8 @@ void CodeTransform::operator()(SSACFG::BlockId const _blockId) // Shuffle to the block's exit layout before dispatching the exit. // This ensures the condition is on top for ConditionalJump, phi pre-images are // in the right positions for jumps, and return values are accessible for FunctionReturn. - StackShuffler::shuffle(m_stack, blockLayout->exitIn); + auto const shuffleResult = StackShuffler::shuffle(m_stack, blockLayout->exitIn); + yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); // handle the block exit std::visit(util::GenericVisitor{ [this, &_blockId](auto const& exit) { (*this)(_blockId, exit); } }, block.exit); @@ -209,7 +210,10 @@ void CodeTransform::operator()(SSACFG::OperationId _opId, StackData const& _oper yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); // prepare stack for operation - StackShuffler::shuffle(m_stack, _operationInputLayout); + { + auto const shuffleResult = StackShuffler::shuffle(m_stack, _operationInputLayout); + yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); + } // check that the assembly stack height corresponds to the stack size after shuffling yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); @@ -395,7 +399,10 @@ void CodeTransform::prepareBlockExitStack(StackData const& _target, PhiInverse c // pull back target to live in current variable space auto const pulledBackTarget = stackPreImage(_target, _phiInverse); // shuffle to target - StackShuffler::shuffle(m_stack, pulledBackTarget); + { + auto const shuffleResult = StackShuffler::shuffle(m_stack, pulledBackTarget); + yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); + } // check that shuffling was successful assertLayoutCompatibility(m_stack.data(), pulledBackTarget); // now we can simply set the target to the actual one which will take care of the application of phi functions diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index d20ecaccb..ff6b896c6 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -192,12 +192,13 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) { auto proposalCopy = proposals[j]; Stack stack(proposalCopy, {.cfg = m_cfg}); - StackShuffler::shuffle( + auto const shuffleResult = StackShuffler::shuffle( stack, proposals[i], {}, proposals[i].size() ); + yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); cumulativeCost += stack.callbacks().opGas; } cumulativeCosts[i] = cumulativeCost; @@ -259,12 +260,15 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) junkCanBeAdded, m_hasFunctionReturnLabel ); - StackShuffler::shuffle( - stack, - requiredStackTop, - opLiveOutWithoutOutputs, - targetSize - ); + { + auto const shuffleResult = StackShuffler::shuffle( + stack, + requiredStackTop, + opLiveOutWithoutOutputs, + targetSize + ); + yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); + } blockLayout.operationIn.push_back(currentStackData); for (std::size_t i = 0; i < requiredStackTop.size(); ++i) @@ -293,9 +297,10 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) false, m_hasFunctionReturnLabel ); - StackShuffler::shuffle( + auto const shuffleResult = StackShuffler::shuffle( stack, {condition}, blockLiveOut, targetSize ); + yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); } yulAssert(!stack.empty() && stack.top().isValueID() && stack.top().valueID() == _cJump.condition); @@ -317,7 +322,8 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) // in case there are return values, let's bring the function return label to the top StackData returnStack = _functionReturn.returnValues | ranges::views::transform(StackSlot::makeValueID) | ranges::to; returnStack.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); - StackShuffler::shuffle(stack, returnStack); + auto const shuffleResult = StackShuffler::shuffle(stack, returnStack); + yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); blockLayout.exitIn = currentStackData; }, [&](SSACFG::BasicBlock::Jump const& _jump) { diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index f9f261dea..ab9f5a78d 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -135,13 +135,20 @@ class State }; } +struct StackShufflerResult +{ + enum class Status { Continue, Admissible, StackTooDeep, MaxIterationsReached }; + Status status = Status::Admissible; + StackSlot culprit = StackSlot::makeJunk(); +}; + template class StackShuffler { using Slot = StackSlot; public: - static void shuffle( + [[nodiscard]] static StackShufflerResult shuffle( Stack& _stack, StackData const& _args, LivenessAnalysis::LivenessData const& _liveOut, @@ -161,61 +168,79 @@ class StackShuffler static std::size_t constexpr maxIterations = 1000; std::size_t i = 0; - while (i < maxIterations) + while (true) { detail::State const state(_stack.data(), target, ReachableStackDepth); - if (!shuffleStep(_stack, state)) + auto result = shuffleStep(_stack, state); + if (result.status == StackShufflerResult::Status::Admissible) { yulAssert(state.admissible()); - break; + return result; } + if (result.status == StackShufflerResult::Status::StackTooDeep) + return result; + yulAssert(result.status == StackShufflerResult::Status::Continue); ++i; + if (i == maxIterations) + { + result.status = StackShufflerResult::Status::MaxIterationsReached; + return result; + } } - - yulAssert(i < maxIterations, fmt::format("Maximum iterations reached on {}", stackToString(_stack.data()))); + yulAssert(false); } - static void shuffle( + [[nodiscard]] static StackShufflerResult shuffle( Stack& _stack, StackData const& _target ) { - shuffle(_stack, _target, {}, _target.size()); + return shuffle(_stack, _target, {}, _target.size()); } private: - /// Make a local step in stack space that should bring us closer to the target. Returns true if more shuffling - /// is required, returns false if finished. - static bool shuffleStep(Stack& _stack, detail::State const& _state) + struct ShuffleHelperResult + { + enum class Status { NoAction, StackModified, StackTooDeep }; + Status status = Status::NoAction; + StackSlot culprit = StackSlot::makeJunk(); + }; + + /// Make a local step in stack space that should bring us closer to the target. + static StackShufflerResult shuffleStep(Stack& _stack, detail::State const& _state) { // if the stack is too large, we try to shrink it if (_stack.size() > _state.target().size) { if (shrinkStack(_stack, _state)) - return true; + return {StackShufflerResult::Status::Continue}; // couldn't shrink to required size, need to spill to memory or increase target size - yulAssert(false, "stack too deep"); + return {StackShufflerResult::Status::StackTooDeep, _stack.top()}; } yulAssert(_stack.size() <= _state.target().size, "I1 violated: Stack size too large"); if (_state.willRequireShrinking()) if (shrinkStack(_stack, _state)) - return true; + return {StackShufflerResult::Status::Continue}; // after this, all current slots are either in acceptable positions or at least dup-reachable if (auto unreachableOffset = allNecessarySlotsReachableOrFinal(_stack, _state)) { // !allNecessarySlotsReachableOrFinal(ops) ≡ ¬(∀s: reachable(s) ∨ final(s)) ≡ ∃s: ¬reachable(s) ∧ ¬final(s) if (shrinkStack(_stack, _state)) - return true; + return {StackShufflerResult::Status::Continue}; - yulAssert(false, fmt::format("stack too deep, couldn't reach offset {}", unreachableOffset->value)); + return {StackShufflerResult::Status::StackTooDeep, _stack[*unreachableOffset]}; } // this will either grow the tail as needed, swap down something from args that needs to be in the tail, - // or return false when there's nothing to be done - if (fixTailSlot(_stack, _state)) - return true; + // or report NoAction when there's nothing to be done + if (auto result = fixTailSlot(_stack, _state); result.status != ShuffleHelperResult::Status::NoAction) + { + if (result.status == ShuffleHelperResult::Status::StackTooDeep) + return {StackShufflerResult::Status::StackTooDeep, result.culprit}; + return {StackShufflerResult::Status::Continue}; + } // fixing tail slot fills up the tail so that now the stack must reach into the args region but also not // exceed it as per our first invariant @@ -223,22 +248,26 @@ class StackShuffler // if the stack reaches into the args region try fixing a slot in there until there's nothing left to be fixed // within the target size constraints - if (fixArgsSlot(_stack, _state)) - return true; + if (auto result = fixArgsSlot(_stack, _state); result.status != ShuffleHelperResult::Status::NoAction) + { + if (result.status == ShuffleHelperResult::Status::StackTooDeep) + return {StackShufflerResult::Status::StackTooDeep, result.culprit}; + return {StackShufflerResult::Status::Continue}; + } // if there are no args, we should be done now if (_state.target().args.empty()) - return false; + return {StackShufflerResult::Status::Admissible}; yulAssert(_stack.size() == _state.target().size); // check whether we are done if (_state.admissible()) - return false; + return {StackShufflerResult::Status::Admissible}; // We couldn't improve the args tail or args situation, and we are not admissible yet, so try to reduce the // stack size and pop something that we don't need so we make space to dup/push stuff within target size if (shrinkStack(_stack, _state)) - return true; + return {StackShufflerResult::Status::Continue}; yulAssert(false, "reached final and forbidden state"); } @@ -281,7 +310,7 @@ class StackShuffler } /// Dups the deepest reachable slot in the tail that is required in args - static bool dupDeepestRelevantTailSlot(Stack& _stack, detail::State const& _state) + static ShuffleHelperResult dupDeepestRelevantTailSlot(Stack& _stack, detail::State const& _state) { // dup up the deepest slot that is required in args (or compress if unreachable) for (StackOffset offset: _state.stackRange()) @@ -296,26 +325,26 @@ class StackShuffler if (_stack.dupReachable(offset)) { _stack.dup(offset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } // try to compress if (shrinkStack(_stack, _state)) - return true; + return {ShuffleHelperResult::Status::StackModified}; - yulAssert(false, fmt::format("Stack too deep: can't reach slot at offset {}", offset.value)); + return {ShuffleHelperResult::Status::StackTooDeep, _stack[offset]}; } } - return false; + return {ShuffleHelperResult::Status::NoAction}; } /// If dupping an ideal slot causes a slot that will still be required to become unreachable, then dup /// the latter slot first - static bool dupDeepSlotIfRequired(Stack& _stack, detail::State const& _state) + static ShuffleHelperResult dupDeepSlotIfRequired(Stack& _stack, detail::State const& _state) { // Check if the stack is large enough for anything to potentially become unreachable. if (_stack.size() < ReachableStackDepth - 1) - return false; + return {ShuffleHelperResult::Status::NoAction}; // Check whether any deep slot might still be needed later (i.e. we still need to reach it with a DUP or SWAP). for (StackOffset sourceOffset{0u}; sourceOffset < _stack.size() - (ReachableStackDepth - 1); ++sourceOffset.value) { @@ -344,13 +373,13 @@ class StackShuffler { // top can go into the tail bit, swap it down _stack.swap(sourceOffset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } else { // we need more of the slot that is about to go out of reach, dup it _stack.dup(sourceOffset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } } else @@ -359,25 +388,25 @@ class StackShuffler if (_stack.isValidSwapTarget(sourceOffset) && _state.isSafeToSwapWithTop(sourceOffset)) { _stack.swap(sourceOffset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } // the slot we need something in the args region of is unreachable, try compressing the stack, // first looking at the top if (shrinkStack(_stack, _state)) - return true; + return {ShuffleHelperResult::Status::StackModified}; - yulAssert(false, fmt::format("Stack too deep, can't reach slot at depth {}", depth->value)); + return {ShuffleHelperResult::Status::StackTooDeep, _stack.slot(*depth)}; } } - return false; + return {ShuffleHelperResult::Status::NoAction}; } /// Tries to fix a slot in the args section of the stack - static bool fixArgsSlot(Stack& _stack, detail::State const& _state) + static ShuffleHelperResult fixArgsSlot(Stack& _stack, detail::State const& _state) { yulAssert(_stack.size() <= _state.target().size, "this method assumes that the stack isn't too large"); if (_stack.size() < _state.target().tailSize) - return false; + return {ShuffleHelperResult::Status::NoAction}; // if we have at least one slot in the args section, try to fix something there if (_stack.size() > _state.target().tailSize) @@ -398,28 +427,28 @@ class StackShuffler if (_stack.isValidSwapTarget(offset) && _state.isArgsCompatible(offset, stackTop)) { _stack.swap(offset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } // otherwise try swapping it with something that needs to go into args for (StackOffset offset: _state.stackTailRange()) if (_stack.isValidSwapTarget(offset) && _state.countInArgs(_stack[offset]) < _state.targetArgsCount(_stack[offset])) { _stack.swap(offset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } // otherwise try swapping it with something that can be popped for (StackOffset offset: _state.stackTailRange()) if (_stack.isValidSwapTarget(offset) && _stack.canBeFreelyGenerated(_stack[offset]) && !_stack[offset].isLiteralValueID()) { _stack.swap(offset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } // otherwise try swapping it with a literal for (StackOffset offset: _state.stackTailRange()) if (_stack.isValidSwapTarget(offset) && _stack[offset].isLiteralValueID()) { _stack.swap(offset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } } // try finding a slot that is compatible with the top and also admits the current top: @@ -436,7 +465,7 @@ class StackShuffler ) { _stack.swap(offset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } // try finding a slot in args that wants to have the top, swap that @@ -450,7 +479,7 @@ class StackShuffler ) { _stack.swap(offset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } // try swapping top with a tail slot that has what we need at top @@ -467,7 +496,7 @@ class StackShuffler ) { _stack.swap(tailOffset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } } @@ -499,7 +528,7 @@ class StackShuffler _stack.swap(offset); // bring slot at offset into fixed position _stack.swap(targetOffset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } } } @@ -508,8 +537,8 @@ class StackShuffler // dup up whatever is missing if (_stack.size() < _state.target().size) { - if (dupDeepSlotIfRequired(_stack, _state)) - return true; + if (auto result = dupDeepSlotIfRequired(_stack, _state); result.status != ShuffleHelperResult::Status::NoAction) + return result; { StackOffset const targetOffset{_stack.size()}; @@ -519,13 +548,13 @@ class StackShuffler if (!sourceDepth) { _stack.push(_state.targetArg(targetOffset)); - return true; + return {ShuffleHelperResult::Status::StackModified}; } if (!_stack.dupReachable(*sourceDepth)) - yulAssert(false, fmt::format("todo: stack too deep handling, couldn't dup up arg {}", slotToString(_state.targetArg(_stack.depthToOffset(*sourceDepth))))); + return {ShuffleHelperResult::Status::StackTooDeep, _state.targetArg(targetOffset)}; _stack.dup(*sourceDepth); - return true; + return {ShuffleHelperResult::Status::StackModified}; } } @@ -541,13 +570,14 @@ class StackShuffler if (_stack.dupReachable(*sourceDepth)) { _stack.dup(*sourceDepth); - return true; + return {ShuffleHelperResult::Status::StackModified}; } - yulAssert(false, "stack too deep handling"); + if (!_stack.canBeFreelyGenerated(arg)) + return {ShuffleHelperResult::Status::StackTooDeep, arg}; } yulAssert(_stack.canBeFreelyGenerated(arg)); _stack.push(arg); - return true; + return {ShuffleHelperResult::Status::StackModified}; } } @@ -557,7 +587,7 @@ class StackShuffler else // If no suitable slot found, push junk _stack.push(Slot::makeJunk()); - return true; + return {ShuffleHelperResult::Status::StackModified}; } // if we're at size and have to push or dup something to satisfy args @@ -570,31 +600,37 @@ class StackShuffler // within dup-reach or we can just push it if (auto depth = _stack.findSlotDepth(arg)) { - yulAssert(!_stack.isBeyondSwapRange(*depth)); + if (_stack.isBeyondSwapRange(*depth)) + return {ShuffleHelperResult::Status::StackTooDeep, arg}; // if we can't outright dup the slot, let's shrink the stack first if (!_stack.dupReachable(*depth)) { - yulAssert(shrinkStack(_stack, _state), "stack too deep, need to spill arg to memory"); - return true; + if (!shrinkStack(_stack, _state)) + return {ShuffleHelperResult::Status::StackTooDeep, arg}; + return {ShuffleHelperResult::Status::StackModified}; } _stack.dup(*depth); - return true; + return {ShuffleHelperResult::Status::StackModified}; } else { - yulAssert(_stack.canBeFreelyGenerated(arg)); - if (!dupDeepSlotIfRequired(_stack, _state)) + if (!_stack.canBeFreelyGenerated(arg)) + return {ShuffleHelperResult::Status::StackTooDeep, arg}; + auto result = dupDeepSlotIfRequired(_stack, _state); + if (result.status == ShuffleHelperResult::Status::StackTooDeep) + return result; + if (result.status == ShuffleHelperResult::Status::NoAction) _stack.push(arg); - return true; + return {ShuffleHelperResult::Status::StackModified}; } } } - return false; + return {ShuffleHelperResult::Status::NoAction}; } /// Grows the tail if too small, otherwise tries swapping something down from args if its required in tail but not /// there yet. - static bool fixTailSlot(Stack& _stack, detail::State const& _state) + static ShuffleHelperResult fixTailSlot(Stack& _stack, detail::State const& _state) { yulAssert(_stack.size() <= _state.target().size, "this method assumes that the stack isn't exceeding target size"); for (StackOffset offset: _state.stackArgsRange() | ranges::views::reverse) @@ -621,7 +657,7 @@ class StackShuffler _stack.swap(offset); // swap offset slot down into tail _stack.swap(tailOffset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } } // find the lowest swappable slot in tail that can be popped but is no literal, swap @@ -637,7 +673,7 @@ class StackShuffler _stack.swap(offset); // swap offset slot down into tail _stack.swap(tailOffset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } // find the lowest swappable slot in tail that is a literal, swap for (StackOffset tailOffset: _state.stackTailRange()) @@ -651,22 +687,22 @@ class StackShuffler _stack.swap(offset); // swap offset slot down into tail _stack.swap(tailOffset); - return true; + return {ShuffleHelperResult::Status::StackModified}; } // we needed to bring the slot into tail but couldn't, not enough stack target space -> spill to memory - yulAssert(false, "stack too deep: couldn't swap args slot into tail without moving something else out that is required there"); + return {ShuffleHelperResult::Status::StackTooDeep, _stack[offset]}; } } if (_stack.size() < _state.target().tailSize) { // if something is on the verge of going out of scope by duping something, dup that first - if (dupDeepSlotIfRequired(_stack, _state)) - return true; + if (auto result = dupDeepSlotIfRequired(_stack, _state); result.status != ShuffleHelperResult::Status::NoAction) + return result; // dup up the deepest slot that needs to go into args so we avoid having to fish it back up later - if (dupDeepestRelevantTailSlot(_stack, _state)) - return true; + if (auto result = dupDeepestRelevantTailSlot(_stack, _state); result.status != ShuffleHelperResult::Status::NoAction) + return result; // Try to dup the optimal slot based on liveness analysis if (auto slotToDup = selectOptimalSlotToDup(_stack, _state)) @@ -674,9 +710,9 @@ class StackShuffler else // If no suitable slot found, push junk _stack.push(Slot::makeJunk()); - return true; + return {ShuffleHelperResult::Status::StackModified}; } - return false; + return {ShuffleHelperResult::Status::NoAction}; } /// Tries to compress the stack diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index 4cd401e67..dbc9b1541 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -106,7 +106,8 @@ std::size_t solidity::yul::ssa::findOptimalTargetSize { data = _stackData; Stack countOpsStack(data, {}); - StackShuffler::shuffle(countOpsStack, _targetArgs, _targetLiveOut, _targetSize); + auto const shuffleResult = StackShuffler::shuffle(countOpsStack, _targetArgs, _targetLiveOut, _targetSize); + yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); yulAssert(countOpsStack.size() == _targetSize); return countOpsStack.callbacks().numOps; }; From f180112627cdc35c94c797ba9c7964e113a376dd Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 3 Apr 2026 10:23:16 +0200 Subject: [PATCH 1233/1340] ssa shuffler tests report final shuffler status --- test/libyul/ssa/StackShufflerTest.cpp | 48 ++++++++++++++++++- .../deep_argument_dup_order.stack | 1 + .../stackShuffler/deep_argument_shrink.stack | 1 + .../deep_argument_with_tail_values.stack | 1 + .../ssa/stackShuffler/dup_up_args.stack | 1 + test/libyul/ssa/stackShuffler/empty.stack | 1 + test/libyul/ssa/stackShuffler/grow.stack | 1 + .../ssa/stackShuffler/introduce_junk.stack | 1 + .../ssa/stackShuffler/keep_top_argument.stack | 1 + .../ssa/stackShuffler/reduce_size.stack | 1 + .../replace_junk_with_top_value.stack | 1 + .../satisfy_tail_requirements.stack | 1 + .../stackShuffler/shrink_and_grow_a_lot.stack | 1 + .../stackShuffler/superfluous_top_slots.stack | 1 + .../stackShuffler/swap_junk_over_pop.stack | 1 + 15 files changed, 60 insertions(+), 2 deletions(-) diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index 0b1427eaf..5daab1428 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -115,6 +115,16 @@ Slot parseSlot(std::string_view token) return Slot::makeValueID(ValueId::makeLiteral(*num)); throw std::runtime_error(fmt::format("Couldn't parse literal token: {}", token)); } + + static constexpr std::string_view returnLabelPrefix = "ReturnLabel["; + if (token.starts_with(returnLabelPrefix) && token.ends_with("]")) + { + auto const inner = token.substr(returnLabelPrefix.size(), token.size() - returnLabelPrefix.size() - 1); + if (auto const num = util::parseArithmetic(inner)) + return Slot::makeFunctionReturnLabel(*num); + throw std::runtime_error(fmt::format("Couldn't parse ReturnLabel token: {}", token)); + } + throw std::runtime_error(fmt::format("Unknown token: {}", token)); } @@ -267,6 +277,15 @@ class TraceRecorder m_entries.push_back(TraceEntry{_operation, _stack}); } + void truncate(size_t const _maxEntries) + { + if (m_entries.size() > _maxEntries) + { + m_entries.resize(_maxEntries); + m_truncated = true; + } + } + ~TraceRecorder() { if (m_entries.empty()) @@ -285,6 +304,8 @@ class TraceRecorder emitSeparatorLine(maxStackDepth, hasExcess); for (auto const& entry: m_entries) emitDataRow(entry, hasExcess); + if (m_truncated) + m_out << fmt::format("{:>{}}", "...", operationColumnWidth) << "|\n"; emitSeparatorLine(maxStackDepth, hasExcess); emitTargetRow(hasExcess); } @@ -297,6 +318,7 @@ class TraceRecorder std::ostream& m_out; std::vector m_entries; + bool m_truncated = false; TestStack::Data const& m_targetArgs; Liveness const& m_targetTail; size_t const m_targetStackSize; @@ -434,18 +456,40 @@ explicitly provided.)"; auto stackData = *testConfig.initial; std::ostringstream oss; + StackShufflerResult shuffleResult; { TraceRecorder trace(oss, *testConfig.targetStackTop, testConfig.targetStackTailSet, *testConfig.targetStackSize); trace.record("(initial)", *testConfig.initial); - TestStack stack(stackData, {.hook = [&](std::string const& op){ trace.record(op, stackData); }}); - StackShuffler::shuffle( + TestStack stack(stackData, {.hook = [&](std::string const& op) + { + trace.record(op, stackData); + }}); + shuffleResult = StackShuffler::shuffle( stack, *testConfig.targetStackTop, testConfig.targetStackTailSet, *testConfig.targetStackSize ); + if (shuffleResult.status == StackShufflerResult::Status::MaxIterationsReached) + trace.truncate(30); + } + + switch (shuffleResult.status) + { + case StackShufflerResult::Status::Admissible: + oss << "Status: Admissible\n"; + break; + case StackShufflerResult::Status::StackTooDeep: + oss << fmt::format("Status: StackTooDeep (culprit: {})\n", slotToString(shuffleResult.culprit)); + break; + case StackShufflerResult::Status::MaxIterationsReached: + oss << "Status: MaxIterationsReached\n"; + break; + case StackShufflerResult::Status::Continue: + yulAssert(false, "Unexpected Continue status from shuffle()"); } // check stack data + if (shuffleResult.status == StackShufflerResult::Status::Admissible) { yulAssert(*testConfig.targetStackSize >= testConfig.targetStackTop->size()); auto const tailSize = *testConfig.targetStackSize - testConfig.targetStackTop->size(); diff --git a/test/libyul/ssa/stackShuffler/deep_argument_dup_order.stack b/test/libyul/ssa/stackShuffler/deep_argument_dup_order.stack index 3dbbcf438..48f0d50e6 100644 --- a/test/libyul/ssa/stackShuffler/deep_argument_dup_order.stack +++ b/test/libyul/ssa/stackShuffler/deep_argument_dup_order.stack @@ -12,3 +12,4 @@ targetStackSize: 18 // SWAP1| v129 | v43 * * * * * * * * * * v101 * v130 v131 lit0 v129 // +------- +----------------------------------------------------------------------------------------------------------------------- // (target)| {v129} | v43 * * * * * * * * * * * * * * lit0 v129 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/deep_argument_shrink.stack b/test/libyul/ssa/stackShuffler/deep_argument_shrink.stack index b7e2c582f..413da2d00 100644 --- a/test/libyul/ssa/stackShuffler/deep_argument_shrink.stack +++ b/test/libyul/ssa/stackShuffler/deep_argument_shrink.stack @@ -14,3 +14,4 @@ targetStackSize: 19 // DUP4| v84 * * * * * * * * * * * * v68 v86 phi111 v12 | v12 v86 // +----------------------------------------------------------------------------------------------------------------------- +-------------- // (target)| {v68, v84, phi111} | v12 v86 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack b/test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack index 729a8623a..3173659b9 100644 --- a/test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack +++ b/test/libyul/ssa/stackShuffler/deep_argument_with_tail_values.stack @@ -13,3 +13,4 @@ targetStackSize: 17 // DUP2| v2 * * * * * * * * * * * * * v1 | v0 v1 // +--------------------------------------------------------------------------------------------------------- +-------------- // (target)| {v1, v2} | v0 v1 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/dup_up_args.stack b/test/libyul/ssa/stackShuffler/dup_up_args.stack index f3be04a89..eeb8eaf9d 100644 --- a/test/libyul/ssa/stackShuffler/dup_up_args.stack +++ b/test/libyul/ssa/stackShuffler/dup_up_args.stack @@ -16,3 +16,4 @@ targetStackSize: 21 // DUP7| * v12 phi9 phi13 * * * * * * * * v65 v67 v12 phi9 | lit27 phi13 phi9 v12 v67 // +---------------------------------------------------------------------------------------------------------------- +----------------------------------- // (target)| {phi9, v12, phi13, v65} | lit27 phi13 phi9 v12 v67 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/empty.stack b/test/libyul/ssa/stackShuffler/empty.stack index 077660d6f..be99a4628 100644 --- a/test/libyul/ssa/stackShuffler/empty.stack +++ b/test/libyul/ssa/stackShuffler/empty.stack @@ -12,3 +12,4 @@ targetStackSize: 3 // PUSH JUNK| * * * // +--------------------- // (target)| +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/grow.stack b/test/libyul/ssa/stackShuffler/grow.stack index 6ad001c47..78f7fb7bc 100644 --- a/test/libyul/ssa/stackShuffler/grow.stack +++ b/test/libyul/ssa/stackShuffler/grow.stack @@ -8,3 +8,4 @@ targetStackTop: [JUNK, JUNK, JUNK, JUNK, v15] // DUP1| * * * v15 v15 // +----------------------------------- // (target)| * * * * v15 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/introduce_junk.stack b/test/libyul/ssa/stackShuffler/introduce_junk.stack index de3d9e234..add7ef5b2 100644 --- a/test/libyul/ssa/stackShuffler/introduce_junk.stack +++ b/test/libyul/ssa/stackShuffler/introduce_junk.stack @@ -13,3 +13,4 @@ targetStackTop: [v199, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v185, JUNK, v188, v19 // DUP14| v199 phi112 * v204 * * * v185 * v188 v190 v191 * v189 phi112 v206 v205 v204 // +------------------------------------------------------------------------------------------------------------------------------ // (target)| v199 * * * * * * v185 * v188 v190 v191 * v189 * v206 v205 v204 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/keep_top_argument.stack b/test/libyul/ssa/stackShuffler/keep_top_argument.stack index 4baa57757..2cbe65fe7 100644 --- a/test/libyul/ssa/stackShuffler/keep_top_argument.stack +++ b/test/libyul/ssa/stackShuffler/keep_top_argument.stack @@ -11,3 +11,4 @@ targetStackSize: 3 // DUP2| v1 | v0 v1 // +------- +-------------- // (target)| {v1} | v0 v1 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/reduce_size.stack b/test/libyul/ssa/stackShuffler/reduce_size.stack index d6a670619..aee430efd 100644 --- a/test/libyul/ssa/stackShuffler/reduce_size.stack +++ b/test/libyul/ssa/stackShuffler/reduce_size.stack @@ -11,3 +11,4 @@ targetStackSize: 19 // POP| * v189 phi112 * * * * * * * v185 phi115 v188 v190 v191 phi113 v199 phi112 | v202 // +------------------------------------------------------------------------------------------------------------------------------ +------- +------- // (target)| {phi112, phi113, phi115, v185, v188, v189, v190, v191, v199} | v202 | +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack b/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack index 5e58ef150..181385a7d 100644 --- a/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack +++ b/test/libyul/ssa/stackShuffler/replace_junk_with_top_value.stack @@ -10,3 +10,4 @@ targetStackTop: [v0, v2, v1, v0] // DUP3| v0 v2 v1 v0 // +---------------------------- // (target)| v0 v2 v1 v0 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack b/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack index 4f59296e6..a97447af9 100644 --- a/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack +++ b/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack @@ -26,3 +26,4 @@ targetStackSize: 17 // DUP16| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v7 v6 v5 v4 v3 v2 v10 // +------------------------------------------------- +---------------------------------------------------------------------- // (target)| {v10} | lit3 v9 v8 v7 v6 v5 v4 v3 v2 v10 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/shrink_and_grow_a_lot.stack b/test/libyul/ssa/stackShuffler/shrink_and_grow_a_lot.stack index 7d4f68a8a..239ebec8b 100644 --- a/test/libyul/ssa/stackShuffler/shrink_and_grow_a_lot.stack +++ b/test/libyul/ssa/stackShuffler/shrink_and_grow_a_lot.stack @@ -120,3 +120,4 @@ targetStackSize: 54 // DUP2| v55 v71 * * * * * * * * * * * * * v94 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 v55 | lit11 v55 // +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-------------- // (target)| {v55, v71, v94} | lit11 v55 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack b/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack index 7753735d7..775a2d782 100644 --- a/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack +++ b/test/libyul/ssa/stackShuffler/superfluous_top_slots.stack @@ -12,3 +12,4 @@ targetStackTop: [JUNK, JUNK, v56, v57, lit0, v56, lit11] // PUSH lit11| * * v56 v57 lit0 v56 lit11 // +------------------------------------------------- // (target)| * * v56 v57 lit0 v56 lit11 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack b/test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack index dbf818ba2..b83cef92f 100644 --- a/test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack +++ b/test/libyul/ssa/stackShuffler/swap_junk_over_pop.stack @@ -11,3 +11,4 @@ targetStackSize: 4 // SWAP3| * | lit2 v2 v0 // +------- +--------------------- // (target)| {} | lit2 v2 v0 +// Status: Admissible From 2bc5e3001c3ce3d29fe59b4b52f2ecb9d18a9094 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 7 Apr 2026 09:17:20 +0200 Subject: [PATCH 1234/1340] allow broader columns in the ssa shuffler test output table --- test/libyul/ssa/StackShufflerTest.cpp | 52 ++++++++++++++++++--------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index 5daab1428..993ba4bb9 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -298,16 +298,30 @@ class TraceRecorder if (maxStackDepth == 0) return; + std::size_t const numColumns = std::max(maxStackDepth, m_targetStackSize); + std::vector columnWidths(numColumns, slotColumnWidth); + for (const auto& [operation, stackAfter]: m_entries) + for (std::size_t i = 0; i < stackAfter.size(); ++i) + { + std::string const slotStr = stackAfter[i].isJunk() ? std::string(1, junkSymbol) : slotToString(stackAfter[i]); + columnWidths[i] = std::max(columnWidths[i], slotStr.size() + 1); + } + for (std::size_t i = 0; i < m_targetArgs.size() && m_targetTailSize + i < numColumns; ++i) + { + std::string const slotStr = m_targetArgs[i].isJunk() ? std::string(1, junkSymbol) : slotToString(m_targetArgs[i]); + columnWidths[m_targetTailSize + i] = std::max(columnWidths[m_targetTailSize + i], slotStr.size() + 1); + } + bool const hasExcess = maxStackDepth > m_targetStackSize; - emitHeader(maxStackDepth, hasExcess); - emitSeparatorLine(maxStackDepth, hasExcess); + emitHeader(hasExcess, columnWidths); + emitSeparatorLine(hasExcess, columnWidths); for (auto const& entry: m_entries) - emitDataRow(entry, hasExcess); + emitDataRow(entry, hasExcess, columnWidths); if (m_truncated) m_out << fmt::format("{:>{}}", "...", operationColumnWidth) << "|\n"; - emitSeparatorLine(maxStackDepth, hasExcess); - emitTargetRow(hasExcess); + emitSeparatorLine(hasExcess, columnWidths); + emitTargetRow(hasExcess, columnWidths); } private: @@ -332,29 +346,29 @@ class TraceRecorder m_out << ' ' << _junction; } - void emitHeader(size_t const _maxStackDepth, bool const _hasExcess) const + void emitHeader(bool const _hasExcess, std::vector const& _columnWidths) const { m_out << fmt::format("{:>{}}", "", operationColumnWidth) << "|"; - for (size_t i = 0; i < _maxStackDepth; ++i) + for (std::size_t i = 0; i < _columnWidths.size(); ++i) { emitSeparator(i, _hasExcess, '|'); - m_out << fmt::format("{:>{}}", i, slotColumnWidth); + m_out << fmt::format("{:>{}}", i, _columnWidths[i]); } m_out << "\n"; } - void emitSeparatorLine(size_t const _maxStackDepth, bool const _hasExcess) const + void emitSeparatorLine(bool const _hasExcess, std::vector const& _columnWidths) const { m_out << fmt::format("{:>{}}", "", operationColumnWidth) << '+'; - for (size_t i = 0; i < _maxStackDepth; ++i) + for (std::size_t i = 0; i < _columnWidths.size(); ++i) { emitSeparator(i, _hasExcess, '+'); - m_out << std::string(slotColumnWidth, '-'); + m_out << std::string(_columnWidths[i], '-'); } m_out << '\n'; } - void emitDataRow(TraceEntry const& _entry, bool const _hasExcess) const + void emitDataRow(TraceEntry const& _entry, bool const _hasExcess, std::vector const& _columnWidths) const { m_out << fmt::format("{:>{}}", _entry.operation, operationColumnWidth) << "|"; for (size_t i = 0; i < _entry.stackAfter.size(); ++i) @@ -362,18 +376,21 @@ class TraceRecorder emitSeparator(i, _hasExcess, '|'); auto const& slot = _entry.stackAfter[i]; std::string slotStr = slot.isJunk() ? std::string(1, junkSymbol) : slotToString(slot); - m_out << fmt::format("{:>{}}", slotStr, slotColumnWidth); + m_out << fmt::format("{:>{}}", slotStr, _columnWidths[i]); } m_out << '\n'; } - void emitTargetRow(bool const _hasExcess) const + void emitTargetRow(bool const _hasExcess, std::vector const& _columnWidths) const { m_out << fmt::format("{:>{}}", "(target)", operationColumnWidth) << "|"; // Print tail region with set notation if (m_targetTailSize > 0 && !(m_targetTail.empty() && m_targetArgs.empty())) { + std::size_t tailWidth = 0; + for (std::size_t i = 0; i < m_targetTailSize; ++i) + tailWidth += _columnWidths[i]; std::string const tailSetStr = fmt::format( "{{{}}}", fmt::join( @@ -383,7 +400,7 @@ class TraceRecorder ", " ) ); - m_out << fmt::format("{:>{}}", tailSetStr, m_targetTailSize * slotColumnWidth); + m_out << fmt::format("{:>{}}", tailSetStr, tailWidth); } // Args separator @@ -391,10 +408,11 @@ class TraceRecorder m_out << " |"; // Print args region - for (auto const& slot: m_targetArgs) + for (std::size_t i = 0; i < m_targetArgs.size(); ++i) { + auto const& slot = m_targetArgs[i]; std::string slotStr = slot.isJunk() ? std::string(1, junkSymbol) : slotToString(slot); - m_out << fmt::format("{:>{}}", slotStr, slotColumnWidth); + m_out << fmt::format("{:>{}}", slotStr, _columnWidths[m_targetTailSize + i]); } // Excess separator From 8b505c3c54ed8302822d93f5389049def3679ff3 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 7 Apr 2026 09:17:29 +0200 Subject: [PATCH 1235/1340] add tests with cycles to ssa shuffler tests --- .../deep_values_grow_to_args.stack | 40 +++++++++++++++++++ .../dup_value_into_args_with_grow_1.stack | 40 +++++++++++++++++++ .../dup_value_into_tail_and_args.stack | 40 +++++++++++++++++++ .../multi_dup_with_phi_in_tail.stack | 40 +++++++++++++++++++ .../return_label_with_dup_and_grow.stack | 40 +++++++++++++++++++ .../ssa/stackShuffler/triple_dup_no_phi.stack | 40 +++++++++++++++++++ .../stackShuffler/triple_dup_with_phi.stack | 40 +++++++++++++++++++ 7 files changed, 280 insertions(+) create mode 100644 test/libyul/ssa/stackShuffler/deep_values_grow_to_args.stack create mode 100644 test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack create mode 100644 test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack create mode 100644 test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack create mode 100644 test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack create mode 100644 test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack create mode 100644 test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack diff --git a/test/libyul/ssa/stackShuffler/deep_values_grow_to_args.stack b/test/libyul/ssa/stackShuffler/deep_values_grow_to_args.stack new file mode 100644 index 000000000..e84310023 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/deep_values_grow_to_args.stack @@ -0,0 +1,40 @@ +// triple dup 2 values +initial: [JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v1, v2, JUNK] +targetStackTop: [JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, lit1, v2, lit2, v2, lit3, v1, JUNK] +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (initial)| * * * * * * * * * * * * * v1 v2 * +// POP| * * * * * * * * * * * * * v1 v2 +// PUSH lit2| * * * * * * * * * * * * * v1 v2 lit2 +// DUP2| * * * * * * * * * * * * * v1 v2 lit2 v2 +// PUSH lit3| * * * * * * * * * * * * * v1 v2 lit2 v2 lit3 +// DUP2| * * * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 +// PUSH lit1| * * * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 lit1 +// SWAP6| * * * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v2 v1 +// SWAP1| * * * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP7| * * * * * * * * * * * * v2 lit1 v2 lit2 v2 lit3 v1 * +// POP| * * * * * * * * * * * * v2 lit1 v2 lit2 v2 lit3 v1 +// DUP3| * * * * * * * * * * * * v2 lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP8| * * * * * * * * * * * v2 v2 lit1 v2 lit2 v2 lit3 v1 * +// POP| * * * * * * * * * * * v2 v2 lit1 v2 lit2 v2 lit3 v1 +// DUP3| * * * * * * * * * * * v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP9| * * * * * * * * * * v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 * +// POP| * * * * * * * * * * v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 +// DUP3| * * * * * * * * * * v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP10| * * * * * * * * * v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 * +// POP| * * * * * * * * * v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 +// DUP3| * * * * * * * * * v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP11| * * * * * * * * v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 * +// POP| * * * * * * * * v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 +// DUP3| * * * * * * * * v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP12| * * * * * * * v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 * +// POP| * * * * * * * v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 +// DUP3| * * * * * * * v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP13| * * * * * * v2 v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 * +// POP| * * * * * * v2 v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 +// DUP3| * * * * * * v2 v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 +// ...| +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (target)| * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 * +// Status: MaxIterationsReached diff --git a/test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack b/test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack new file mode 100644 index 000000000..5bbaeb2b4 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack @@ -0,0 +1,40 @@ +// dup a value multiple times into args while growing the stack +initial: [JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, phi1, JUNK, v1, v2, v3] +targetStackTop: [v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, phi1, JUNK, lit1, v2, lit2, v2, lit1, v1, v3] +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +// +------------------------------------------------------------------------------------------------------------------------------------- +// (initial)| * * * * * * * * * * phi1 * v1 v2 v3 +// SWAP14| v3 * * * * * * * * * phi1 * v1 v2 * +// POP| v3 * * * * * * * * * phi1 * v1 v2 +// PUSH lit2| v3 * * * * * * * * * phi1 * v1 v2 lit2 +// DUP2| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 +// PUSH lit1| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 lit1 +// DUP2| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 lit1 v2 +// DUP2| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 lit1 v2 lit1 +// SWAP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v2 v1 +// SWAP1| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 +// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 +// POP| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 +// DUP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 +// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 +// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 +// POP| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 +// DUP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 +// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 +// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 +// POP| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 +// DUP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 +// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 +// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 +// POP| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 +// DUP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 +// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 +// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 +// POP| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 +// DUP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 +// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 +// ...| +// +------------------------------------------------------------------------------------------------------------------------------------- +// (target)| v2 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v3 +// Status: MaxIterationsReached diff --git a/test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack b/test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack new file mode 100644 index 000000000..06d2df403 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack @@ -0,0 +1,40 @@ +// shifted triple dup +initial: [JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v1, v2, v3] +targetStackTop: [JUNK, JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, lit1, v2, lit2, v2, lit3, v1, v3] +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 +// +--------------------------------------------------------------------------------------------------------------------------------------------------- +// (initial)| * * * * * * * * * * * * * * v1 v2 v3 +// SWAP14| * * v3 * * * * * * * * * * * v1 v2 * +// POP| * * v3 * * * * * * * * * * * v1 v2 +// PUSH lit2| * * v3 * * * * * * * * * * * v1 v2 lit2 +// DUP2| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 +// PUSH lit3| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 +// DUP2| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 +// PUSH lit1| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 lit1 +// SWAP6| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v2 v1 +// SWAP1| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// ...| +// +--------------------------------------------------------------------------------------------------------------------------------------------------- +// (target)| * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v3 +// Status: MaxIterationsReached diff --git a/test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack b/test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack new file mode 100644 index 000000000..a72977f3b --- /dev/null +++ b/test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack @@ -0,0 +1,40 @@ +// multiple dups needed with phi values in tail +initial: [JUNK, JUNK, JUNK, v1, v2, JUNK, JUNK, JUNK, JUNK, phi1, JUNK, v3, phi2, v4, v5, v6] +targetStackTop: [JUNK, v5, JUNK, v1, v2, JUNK, JUNK, JUNK, JUNK, phi1, JUNK, v3, phi2, lit1, v5, lit2, v5, lit3, v4, v6] +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (initial)| * * * v1 v2 * * * * phi1 * v3 phi2 v4 v5 v6 +// SWAP14| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 * +// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 +// PUSH lit2| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 +// DUP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 +// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 lit3 +// DUP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 lit3 v5 +// PUSH lit1| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 lit3 v5 lit1 +// SWAP6| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v5 v4 +// SWAP1| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 +// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 +// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 +// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 +// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 +// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 +// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 +// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 +// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 +// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 +// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 +// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 +// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 +// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 +// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 +// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 +// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 +// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 +// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 +// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 +// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 +// ...| +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (target)| * v5 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v6 +// Status: MaxIterationsReached diff --git a/test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack b/test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack new file mode 100644 index 000000000..7c22e8f52 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack @@ -0,0 +1,40 @@ +// return label with dup and grow +initial: [ReturnLabel[1], JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v1, v2, v3] +targetStackTop: [ReturnLabel[1], JUNK, JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, lit1, v2, lit2, v2, lit1, v1, v3] +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 22 +// +------------------------------------------------------------------------------------------------------------------------------------------------------------------ +------- +// (initial)| ReturnLabel[1] * * * * * * * * * * * * * * * * * * * v1 v2 | v3 +// SWAP1| ReturnLabel[1] * * * * * * * * * * * * * * * * * * * v1 v3 | v2 +// SWAP6| ReturnLabel[1] * * * * * * * * * * * * * * * v2 * * * v1 v3 | * +// POP| ReturnLabel[1] * * * * * * * * * * * * * * * v2 * * * v1 v3 +// SWAP2| ReturnLabel[1] * * * * * * * * * * * * * * * v2 * * v3 v1 * +// POP| ReturnLabel[1] * * * * * * * * * * * * * * * v2 * * v3 v1 +// SWAP2| ReturnLabel[1] * * * * * * * * * * * * * * * v2 * v1 v3 * +// POP| ReturnLabel[1] * * * * * * * * * * * * * * * v2 * v1 v3 +// SWAP2| ReturnLabel[1] * * * * * * * * * * * * * * * v2 v3 v1 * +// POP| ReturnLabel[1] * * * * * * * * * * * * * * * v2 v3 v1 +// SWAP3| ReturnLabel[1] * * * * * * * * * * * * * * v1 v2 v3 * +// POP| ReturnLabel[1] * * * * * * * * * * * * * * v1 v2 v3 +// SWAP14| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 * +// POP| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 +// PUSH lit2| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 +// DUP2| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 +// PUSH lit1| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit1 +// DUP2| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit1 v2 +// DUP2| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit1 v2 lit1 +// SWAP6| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit1 v2 v1 +// SWAP1| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit1 v1 v2 +// SWAP2| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit1 +// POP| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// DUP6| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit1 +// SWAP2| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit1 v1 v2 +// SWAP2| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit1 +// POP| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// DUP6| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit1 +// SWAP2| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit1 v1 v2 +// SWAP2| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit1 +// ...| +// +------------------------------------------------------------------------------------------------------------------------------------------------------------------ +------- +// (target)| ReturnLabel[1] * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit1 v1 v3 | +// Status: MaxIterationsReached diff --git a/test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack b/test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack new file mode 100644 index 000000000..438ab16fb --- /dev/null +++ b/test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack @@ -0,0 +1,40 @@ +// value needs triple dup into args, no phi +initial: [JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, v1, v2, v3] +targetStackTop: [JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, lit1, v2, lit2, v2, lit3, v1, v3] +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (initial)| * * * * * * * * * * * * * v1 v2 v3 +// SWAP14| * v3 * * * * * * * * * * * v1 v2 * +// POP| * v3 * * * * * * * * * * * v1 v2 +// PUSH lit2| * v3 * * * * * * * * * * * v1 v2 lit2 +// DUP2| * v3 * * * * * * * * * * * v1 v2 lit2 v2 +// PUSH lit3| * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 +// DUP2| * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 +// PUSH lit1| * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 lit1 +// SWAP6| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v2 v1 +// SWAP1| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// ...| +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (target)| * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v3 +// Status: MaxIterationsReached diff --git a/test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack b/test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack new file mode 100644 index 000000000..0d3e5f867 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack @@ -0,0 +1,40 @@ +// triple dup with phi +initial: [JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, phi1, JUNK, JUNK, JUNK, JUNK, v1, v2, v3] +targetStackTop: [JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, phi1, JUNK, JUNK, JUNK, JUNK, lit1, v2, lit2, v2, lit3, v1, v3] +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (initial)| * * * * * * * * phi1 * * * * v1 v2 v3 +// SWAP14| * v3 * * * * * * phi1 * * * * v1 v2 * +// POP| * v3 * * * * * * phi1 * * * * v1 v2 +// PUSH lit2| * v3 * * * * * * phi1 * * * * v1 v2 lit2 +// DUP2| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 +// PUSH lit3| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 lit3 +// DUP2| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 lit3 v2 +// PUSH lit1| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 lit3 v2 lit1 +// SWAP6| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v2 v1 +// SWAP1| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// POP| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 +// PUSH lit3| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 +// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 +// ...| +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (target)| * v2 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v3 +// Status: MaxIterationsReached From a379310f0167b575aff01d80d450d14d3bd32ac9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 7 Apr 2026 10:28:44 +0200 Subject: [PATCH 1236/1340] Add ssa shuffler tests that run into stack too deep --- .../too_deep_cannot_dup_for_args.stack | 13 +++++++++++++ .../stackShuffler/too_deep_cannot_fix_tail.stack | 13 +++++++++++++ .../stackShuffler/too_deep_dup_deep_tail_slot.stack | 12 ++++++++++++ .../stackShuffler/too_deep_unreachable_slot.stack | 12 ++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 test/libyul/ssa/stackShuffler/too_deep_cannot_dup_for_args.stack create mode 100644 test/libyul/ssa/stackShuffler/too_deep_cannot_fix_tail.stack create mode 100644 test/libyul/ssa/stackShuffler/too_deep_dup_deep_tail_slot.stack create mode 100644 test/libyul/ssa/stackShuffler/too_deep_unreachable_slot.stack diff --git a/test/libyul/ssa/stackShuffler/too_deep_cannot_dup_for_args.stack b/test/libyul/ssa/stackShuffler/too_deep_cannot_dup_for_args.stack new file mode 100644 index 000000000..4e3d90a21 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/too_deep_cannot_dup_for_args.stack @@ -0,0 +1,13 @@ +// Value v1 is needed both in the tail set and in the args. It appears once on the stack at offset 17 (top). +// The tail at offset 0 (depth 17) is beyond swap range, so v1 cannot be moved there. +initial: [JUNK, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v1] +targetStackTop: [v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v1] +targetStackTailSet: {v1} +targetStackSize: 18 +// ---- +// | 0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +// +------- +----------------------------------------------------------------------------------------------------------------------- +// (initial)| * | v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v1 +// +------- +----------------------------------------------------------------------------------------------------------------------- +// (target)| {v1} | v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v1 +// Status: StackTooDeep (culprit: v1) diff --git a/test/libyul/ssa/stackShuffler/too_deep_cannot_fix_tail.stack b/test/libyul/ssa/stackShuffler/too_deep_cannot_fix_tail.stack new file mode 100644 index 000000000..6056cd723 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/too_deep_cannot_fix_tail.stack @@ -0,0 +1,13 @@ +// Value v1 is in the args region but needed in the tail (offset 0, depth 17). The tail position is beyond +// swap range so fixTailSlot cannot swap v1 down. All other args are already in their correct positions. +initial: [JUNK, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v1] +targetStackTop: [v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, JUNK] +targetStackTailSet: {v1} +targetStackSize: 18 +// ---- +// | 0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +// +------- +----------------------------------------------------------------------------------------------------------------------- +// (initial)| * | v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v1 +// +------- +----------------------------------------------------------------------------------------------------------------------- +// (target)| {v1} | v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 * +// Status: StackTooDeep (culprit: v1) diff --git a/test/libyul/ssa/stackShuffler/too_deep_dup_deep_tail_slot.stack b/test/libyul/ssa/stackShuffler/too_deep_dup_deep_tail_slot.stack new file mode 100644 index 000000000..79a02a199 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/too_deep_dup_deep_tail_slot.stack @@ -0,0 +1,12 @@ +// Shuffler needs to dup v1 but can't reach it. +initial: [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18] +targetStackTop: [v1] +targetStackTailSet: {v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18} +targetStackSize: 19 +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 18 +// +------------------------------------------------------------------------------------------------------------------------------ +------- +// (initial)| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 +// +------------------------------------------------------------------------------------------------------------------------------ +------- +// (target)| {v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18} | v1 +// Status: StackTooDeep (culprit: v1) diff --git a/test/libyul/ssa/stackShuffler/too_deep_unreachable_slot.stack b/test/libyul/ssa/stackShuffler/too_deep_unreachable_slot.stack new file mode 100644 index 000000000..67f1238a0 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/too_deep_unreachable_slot.stack @@ -0,0 +1,12 @@ +// A value at the bottom of an 18-slot stack is needed at the top, but is at depth 17. +// allNecessarySlotsReachableOrFinal detects the unreachable slot, shrinkStack fails since all values are unique +// and essential. Triggers StackTooDeep in shuffleStep (unreachable path). +initial: [v18, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v1] +targetStackTop: [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18] +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +// +------------------------------------------------------------------------------------------------------------------------------ +// (initial)| v18 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v1 +// +------------------------------------------------------------------------------------------------------------------------------ +// (target)| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 +// Status: StackTooDeep (culprit: v18) From 26d6ef1861dc6b2fa1e951b26962efad9a97ce41 Mon Sep 17 00:00:00 2001 From: blishko Date: Sat, 11 Apr 2026 14:32:14 +0200 Subject: [PATCH 1237/1340] SSA: Remove unnecessary shuffling logic After fixing tail, when we are trying to fix args, it is not possible anymore that the stack top would be required in tail but not present there yet. Thus, we can assert this and delete logic that assumed this could occur. --- libyul/backends/evm/ssa/StackShuffler.h | 37 +------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index ab9f5a78d..e8028db1a 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -415,42 +415,7 @@ class StackShuffler // if the stack top isn't where it likes to be right now, try to put it somewhere more sensible if (!_state.isArgsCompatible(stackTop, stackTop)) { - // if the stack top should go into the tail but isn't there yet and we have enough of it in args - if ( - _state.requiredInTail(_stack[stackTop]) && - _state.countInTail(_stack[stackTop]) == 0 && - _state.countInArgs(_stack[stackTop]) > _state.targetArgsCount(_stack[stackTop]) - ) - { - // try swapping it with something in the tail that also fixes the top - for (StackOffset offset: _state.stackTailRange()) - if (_stack.isValidSwapTarget(offset) && _state.isArgsCompatible(offset, stackTop)) - { - _stack.swap(offset); - return {ShuffleHelperResult::Status::StackModified}; - } - // otherwise try swapping it with something that needs to go into args - for (StackOffset offset: _state.stackTailRange()) - if (_stack.isValidSwapTarget(offset) && _state.countInArgs(_stack[offset]) < _state.targetArgsCount(_stack[offset])) - { - _stack.swap(offset); - return {ShuffleHelperResult::Status::StackModified}; - } - // otherwise try swapping it with something that can be popped - for (StackOffset offset: _state.stackTailRange()) - if (_stack.isValidSwapTarget(offset) && _stack.canBeFreelyGenerated(_stack[offset]) && !_stack[offset].isLiteralValueID()) - { - _stack.swap(offset); - return {ShuffleHelperResult::Status::StackModified}; - } - // otherwise try swapping it with a literal - for (StackOffset offset: _state.stackTailRange()) - if (_stack.isValidSwapTarget(offset) && _stack[offset].isLiteralValueID()) - { - _stack.swap(offset); - return {ShuffleHelperResult::Status::StackModified}; - } - } + yulAssert(!_state.requiredInTail(_stack[stackTop]) || _state.countInTail(_stack[stackTop]) > 0); // try finding a slot that is compatible with the top and also admits the current top: // - could be that the top slot is used elsewhere in the args (exclude junk) // - could be that the top slot is something that is only required in the tail From 47c83613b40dc0efd767d70047255ed68e1cb017 Mon Sep 17 00:00:00 2001 From: blishko Date: Tue, 14 Apr 2026 23:41:22 +0200 Subject: [PATCH 1238/1340] SSA: Fix cycle in stack shuffler Previously, when we were trying to detect if all slots are reachable or final, we were checking only target slots that are filled at the current moment. However, we need to check *all* the target slots, even those beoynd the current stack size. Previous behaviour meant we were not shrinking the stack as much as was required in some situations and the shuffling went into a loop. With this fix most of the examples that were looping previously are now successful. --- libyul/backends/evm/ssa/StackShuffler.h | 2 +- .../dup_value_into_args_with_grow_1.stack | 33 +++++-------------- .../dup_value_into_tail_and_args.stack | 33 +++++-------------- .../multi_dup_with_phi_in_tail.stack | 33 +++++-------------- .../return_label_with_dup_and_grow.stack | 22 +++++-------- .../ssa/stackShuffler/triple_dup_no_phi.stack | 33 +++++-------------- .../stackShuffler/triple_dup_with_phi.stack | 33 +++++-------------- 7 files changed, 49 insertions(+), 140 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index e8028db1a..70c381a89 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -792,7 +792,7 @@ class StackShuffler static std::optional allNecessarySlotsReachableOrFinal(Stack const& _stack, detail::State const& _state) { // check that args are either in position or reachable - for (StackOffset const offset: _state.stackArgsRange()) + for (StackOffset offset{_state.target().tailSize}; offset < _state.target().size; ++offset.value) { if (_state.isArgsCompatible(offset, offset)) continue; diff --git a/test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack b/test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack index 5bbaeb2b4..0b81b635f 100644 --- a/test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack +++ b/test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack @@ -11,30 +11,13 @@ targetStackTop: [v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, phi1, // DUP2| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 // PUSH lit1| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 lit1 // DUP2| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 lit1 v2 -// DUP2| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 lit1 v2 lit1 -// SWAP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v2 v1 -// SWAP1| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 -// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 -// POP| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 -// DUP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 -// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 -// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 -// POP| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 -// DUP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 -// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 -// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 -// POP| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 -// DUP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 -// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 -// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 -// POP| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 -// DUP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 -// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 -// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 -// POP| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 -// DUP6| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v2 v1 lit1 -// SWAP2| v3 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v2 -// ...| +// SWAP1| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 v2 lit1 +// POP| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 v2 +// SWAP16| v2 * * * * * * * * * phi1 * v1 v2 lit2 v2 v3 +// PUSH lit1| v2 * * * * * * * * * phi1 * v1 v2 lit2 v2 v3 lit1 +// SWAP5| v2 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v3 v1 +// DUP6| v2 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v3 v1 lit1 +// SWAP2| v2 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v3 // +------------------------------------------------------------------------------------------------------------------------------------- // (target)| v2 * * * * * * * * * phi1 * lit1 v2 lit2 v2 lit1 v1 v3 -// Status: MaxIterationsReached +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack b/test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack index 06d2df403..287ba86cf 100644 --- a/test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack +++ b/test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack @@ -11,30 +11,13 @@ targetStackTop: [JUNK, JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, // DUP2| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 // PUSH lit3| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 // DUP2| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 -// PUSH lit1| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 lit1 -// SWAP6| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v2 v1 -// SWAP1| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// ...| +// SWAP1| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 lit3 +// POP| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 +// SWAP16| * * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 +// PUSH lit1| * * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 lit1 +// SWAP5| * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 v3 v1 +// PUSH lit3| * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 v3 v1 lit3 +// SWAP2| * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v3 // +--------------------------------------------------------------------------------------------------------------------------------------------------- // (target)| * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v3 -// Status: MaxIterationsReached +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack b/test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack index a72977f3b..aa563e6f9 100644 --- a/test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack +++ b/test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack @@ -11,30 +11,13 @@ targetStackTop: [JUNK, v5, JUNK, v1, v2, JUNK, JUNK, JUNK, JUNK, phi1, JUNK, v3, // DUP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 // PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 lit3 // DUP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 lit3 v5 -// PUSH lit1| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 lit3 v5 lit1 -// SWAP6| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v5 v4 -// SWAP1| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 -// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 -// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 -// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 -// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 -// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 -// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 -// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 -// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 -// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 -// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 -// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 -// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 -// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 -// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 -// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 -// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 -// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 -// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 -// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v5 v4 lit3 -// SWAP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v5 -// ...| +// SWAP1| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 v5 lit3 +// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 v5 +// SWAP16| * v5 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 v6 +// PUSH lit1| * v5 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 v6 lit1 +// SWAP5| * v5 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v6 v4 +// PUSH lit3| * v5 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v6 v4 lit3 +// SWAP2| * v5 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v6 // +-------------------------------------------------------------------------------------------------------------------------------------------- // (target)| * v5 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 lit3 v4 v6 -// Status: MaxIterationsReached +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack b/test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack index 7c22e8f52..571ed4a24 100644 --- a/test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack +++ b/test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack @@ -22,19 +22,13 @@ targetStackTop: [ReturnLabel[1], JUNK, JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, J // DUP2| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 // PUSH lit1| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit1 // DUP2| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit1 v2 -// DUP2| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit1 v2 lit1 -// SWAP6| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit1 v2 v1 -// SWAP1| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit1 v1 v2 -// SWAP2| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit1 -// POP| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// DUP6| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit1 -// SWAP2| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit1 v1 v2 -// SWAP2| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit1 -// POP| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// DUP6| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit1 -// SWAP2| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit1 v1 v2 -// SWAP2| ReturnLabel[1] * * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit1 -// ...| +// SWAP1| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 lit1 +// POP| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 +// SWAP16| ReturnLabel[1] * * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 +// PUSH lit1| ReturnLabel[1] * * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 lit1 +// SWAP5| ReturnLabel[1] * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 v3 v1 +// DUP6| ReturnLabel[1] * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 v3 v1 lit1 +// SWAP2| ReturnLabel[1] * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit1 v1 v3 // +------------------------------------------------------------------------------------------------------------------------------------------------------------------ +------- // (target)| ReturnLabel[1] * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit1 v1 v3 | -// Status: MaxIterationsReached +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack b/test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack index 438ab16fb..845095016 100644 --- a/test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack +++ b/test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack @@ -11,30 +11,13 @@ targetStackTop: [JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, // DUP2| * v3 * * * * * * * * * * * v1 v2 lit2 v2 // PUSH lit3| * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 // DUP2| * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 -// PUSH lit1| * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 lit1 -// SWAP6| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v2 v1 -// SWAP1| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * v3 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// ...| +// SWAP1| * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 lit3 +// POP| * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 +// SWAP16| * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 +// PUSH lit1| * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 lit1 +// SWAP5| * v2 * * * * * * * * * * * lit1 v2 lit2 v2 v3 v1 +// PUSH lit3| * v2 * * * * * * * * * * * lit1 v2 lit2 v2 v3 v1 lit3 +// SWAP2| * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v3 // +-------------------------------------------------------------------------------------------------------------------------------------------- // (target)| * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v3 -// Status: MaxIterationsReached +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack b/test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack index 0d3e5f867..3d28212bd 100644 --- a/test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack +++ b/test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack @@ -11,30 +11,13 @@ targetStackTop: [JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, phi1, JUNK, JUNK, // DUP2| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 // PUSH lit3| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 lit3 // DUP2| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 lit3 v2 -// PUSH lit1| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 lit3 v2 lit1 -// SWAP6| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v2 v1 -// SWAP1| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// POP| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 -// PUSH lit3| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v2 v1 lit3 -// SWAP2| * v3 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// ...| +// SWAP1| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 v2 lit3 +// POP| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 v2 +// SWAP16| * v2 * * * * * * phi1 * * * * v1 v2 lit2 v2 v3 +// PUSH lit1| * v2 * * * * * * phi1 * * * * v1 v2 lit2 v2 v3 lit1 +// SWAP5| * v2 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v3 v1 +// PUSH lit3| * v2 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v3 v1 lit3 +// SWAP2| * v2 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v3 // +-------------------------------------------------------------------------------------------------------------------------------------------- // (target)| * v2 * * * * * * phi1 * * * * lit1 v2 lit2 v2 lit3 v1 v3 -// Status: MaxIterationsReached +// Status: Admissible From 65d9215f96148ddb76fd4127815f6bdae46a5557 Mon Sep 17 00:00:00 2001 From: blishko Date: Wed, 15 Apr 2026 23:49:44 +0200 Subject: [PATCH 1239/1340] SSA: Use ranges::contains to be more concise --- libyul/backends/evm/ssa/StackShuffler.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 70c381a89..d511fe115 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -23,6 +23,7 @@ #include +#include #include #include #include @@ -161,9 +162,9 @@ class StackShuffler // check that all required values are on stack detail::State const state(_stack.data(), target, ReachableStackDepth); for (auto const& liveVariable: _liveOut | ranges::views::keys | ranges::views::transform(Slot::makeValueID)) - yulAssert(_stack.canBeFreelyGenerated(liveVariable) || ranges::find(_stack.data(), liveVariable) != ranges::end(_stack.data())); + yulAssert(_stack.canBeFreelyGenerated(liveVariable) || ranges::contains(_stack.data(), liveVariable)); for (auto const& arg: _args) - yulAssert(_stack.canBeFreelyGenerated(arg) || ranges::find(_stack.data(), arg) != ranges::end(_stack.data())); + yulAssert(_stack.canBeFreelyGenerated(arg) || ranges::contains(_stack.data(), arg)); } static std::size_t constexpr maxIterations = 1000; From 1d0801461452d51995e92b348e81487da711b44b Mon Sep 17 00:00:00 2001 From: blishko Date: Wed, 15 Apr 2026 23:50:37 +0200 Subject: [PATCH 1240/1340] SSA: Only allow values in requested live variables --- libyul/backends/evm/ssa/StackShuffler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index d511fe115..974fd2386 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -162,7 +162,7 @@ class StackShuffler // check that all required values are on stack detail::State const state(_stack.data(), target, ReachableStackDepth); for (auto const& liveVariable: _liveOut | ranges::views::keys | ranges::views::transform(Slot::makeValueID)) - yulAssert(_stack.canBeFreelyGenerated(liveVariable) || ranges::contains(_stack.data(), liveVariable)); + yulAssert(!_stack.canBeFreelyGenerated(liveVariable) && ranges::contains(_stack.data(), liveVariable)); for (auto const& arg: _args) yulAssert(_stack.canBeFreelyGenerated(arg) || ranges::contains(_stack.data(), arg)); } From 6b611670625f846e9d176d1ac43fce4ee8238421 Mon Sep 17 00:00:00 2001 From: blishko Date: Thu, 16 Apr 2026 09:28:53 +0200 Subject: [PATCH 1241/1340] SSA: More controlled stack growing in shuffler Previously, when growing the current stack, we would always grow if we can put a slot on top that is expected there in the target. However, if we have something in the args that still need to be fixed and would go out of reach, we should skip this step and focus on fixing the deep arg first. This also fixes the last cycling behaviour in our tests. --- libyul/backends/evm/ssa/StackShuffler.cpp | 10 ++++++ libyul/backends/evm/ssa/StackShuffler.h | 5 +++ .../deep_values_grow_to_args.stack | 35 ++++--------------- .../dup_value_into_args_with_grow_1.stack | 5 +-- .../dup_value_into_tail_and_args.stack | 5 +-- .../multi_dup_with_phi_in_tail.stack | 5 +-- .../return_label_with_dup_and_grow.stack | 5 +-- .../ssa/stackShuffler/triple_dup_no_phi.stack | 5 +-- .../stackShuffler/triple_dup_with_phi.stack | 5 +-- 9 files changed, 28 insertions(+), 52 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.cpp b/libyul/backends/evm/ssa/StackShuffler.cpp index 01bf57c60..4d5c5dbc6 100644 --- a/libyul/backends/evm/ssa/StackShuffler.cpp +++ b/libyul/backends/evm/ssa/StackShuffler.cpp @@ -195,3 +195,13 @@ bool State::willRequireShrinking() const } return deficit + size() > target().size; } + +std::optional State::findDeepestIncorrectArgSlot() const +{ + for (StackOffset const offset: stackArgsRange()) + { + if (!isArgsCompatible(offset, offset)) + return StackDepth{m_stackData.size() - offset.value}; + } + return std::nullopt; +} diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 70c381a89..14c136a14 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -124,6 +124,9 @@ class State return ranges::views::iota(0u, std::min(m_stackData.size(), m_reachableStackDepth)) | ranges::views::transform([&](auto _i) { return StackOffset{m_stackData.size() - _i - 1}; }); } + /// Depth of the deepest arg slot incompatible with target or Nothing for no incompatibility in current state + std::optional findDeepestIncorrectArgSlot() const; + private: StackData const& m_stackData; Target const& m_target; @@ -505,6 +508,8 @@ class StackShuffler if (auto result = dupDeepSlotIfRequired(_stack, _state); result.status != ShuffleHelperResult::Status::NoAction) return result; + auto const maybeIncorrectArgSlotDepth = _state.findDeepestIncorrectArgSlot(); + if (!maybeIncorrectArgSlotDepth || maybeIncorrectArgSlotDepth->value < ReachableStackDepth - 1) { StackOffset const targetOffset{_stack.size()}; if (_state.count(_state.targetArg(targetOffset)) < _state.targetMinCount(_state.targetArg(targetOffset))) diff --git a/test/libyul/ssa/stackShuffler/deep_values_grow_to_args.stack b/test/libyul/ssa/stackShuffler/deep_values_grow_to_args.stack index e84310023..848d246fe 100644 --- a/test/libyul/ssa/stackShuffler/deep_values_grow_to_args.stack +++ b/test/libyul/ssa/stackShuffler/deep_values_grow_to_args.stack @@ -8,33 +8,12 @@ targetStackTop: [JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, // POP| * * * * * * * * * * * * * v1 v2 // PUSH lit2| * * * * * * * * * * * * * v1 v2 lit2 // DUP2| * * * * * * * * * * * * * v1 v2 lit2 v2 -// PUSH lit3| * * * * * * * * * * * * * v1 v2 lit2 v2 lit3 -// DUP2| * * * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 -// PUSH lit1| * * * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 lit1 -// SWAP6| * * * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v2 v1 -// SWAP1| * * * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP7| * * * * * * * * * * * * v2 lit1 v2 lit2 v2 lit3 v1 * -// POP| * * * * * * * * * * * * v2 lit1 v2 lit2 v2 lit3 v1 -// DUP3| * * * * * * * * * * * * v2 lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP8| * * * * * * * * * * * v2 v2 lit1 v2 lit2 v2 lit3 v1 * -// POP| * * * * * * * * * * * v2 v2 lit1 v2 lit2 v2 lit3 v1 -// DUP3| * * * * * * * * * * * v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP9| * * * * * * * * * * v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 * -// POP| * * * * * * * * * * v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 -// DUP3| * * * * * * * * * * v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP10| * * * * * * * * * v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 * -// POP| * * * * * * * * * v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 -// DUP3| * * * * * * * * * v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP11| * * * * * * * * v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 * -// POP| * * * * * * * * v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 -// DUP3| * * * * * * * * v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP12| * * * * * * * v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 * -// POP| * * * * * * * v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 -// DUP3| * * * * * * * v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 -// SWAP13| * * * * * * v2 v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 * -// POP| * * * * * * v2 v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 -// DUP3| * * * * * * v2 v2 v2 v2 v2 v2 v2 lit1 v2 lit2 v2 lit3 v1 v2 -// ...| +// DUP1| * * * * * * * * * * * * * v1 v2 lit2 v2 v2 +// SWAP16| * v2 * * * * * * * * * * * v1 v2 lit2 v2 * +// PUSH lit1| * v2 * * * * * * * * * * * v1 v2 lit2 v2 * lit1 +// SWAP5| * v2 * * * * * * * * * * * lit1 v2 lit2 v2 * v1 +// PUSH lit3| * v2 * * * * * * * * * * * lit1 v2 lit2 v2 * v1 lit3 +// SWAP2| * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 * // +-------------------------------------------------------------------------------------------------------------------------------------------- // (target)| * v2 * * * * * * * * * * * lit1 v2 lit2 v2 lit3 v1 * -// Status: MaxIterationsReached +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack b/test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack index 0b81b635f..4f27cf720 100644 --- a/test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack +++ b/test/libyul/ssa/stackShuffler/dup_value_into_args_with_grow_1.stack @@ -9,10 +9,7 @@ targetStackTop: [v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, phi1, // POP| v3 * * * * * * * * * phi1 * v1 v2 // PUSH lit2| v3 * * * * * * * * * phi1 * v1 v2 lit2 // DUP2| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 -// PUSH lit1| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 lit1 -// DUP2| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 lit1 v2 -// SWAP1| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 v2 lit1 -// POP| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 v2 +// DUP1| v3 * * * * * * * * * phi1 * v1 v2 lit2 v2 v2 // SWAP16| v2 * * * * * * * * * phi1 * v1 v2 lit2 v2 v3 // PUSH lit1| v2 * * * * * * * * * phi1 * v1 v2 lit2 v2 v3 lit1 // SWAP5| v2 * * * * * * * * * phi1 * lit1 v2 lit2 v2 v3 v1 diff --git a/test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack b/test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack index 287ba86cf..ae4266c6b 100644 --- a/test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack +++ b/test/libyul/ssa/stackShuffler/dup_value_into_tail_and_args.stack @@ -9,10 +9,7 @@ targetStackTop: [JUNK, JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, // POP| * * v3 * * * * * * * * * * * v1 v2 // PUSH lit2| * * v3 * * * * * * * * * * * v1 v2 lit2 // DUP2| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 -// PUSH lit3| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 -// DUP2| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 -// SWAP1| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 lit3 -// POP| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 +// DUP1| * * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 // SWAP16| * * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 // PUSH lit1| * * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 lit1 // SWAP5| * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 v3 v1 diff --git a/test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack b/test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack index aa563e6f9..f608f4b7f 100644 --- a/test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack +++ b/test/libyul/ssa/stackShuffler/multi_dup_with_phi_in_tail.stack @@ -9,10 +9,7 @@ targetStackTop: [JUNK, v5, JUNK, v1, v2, JUNK, JUNK, JUNK, JUNK, phi1, JUNK, v3, // POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 // PUSH lit2| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 // DUP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 -// PUSH lit3| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 lit3 -// DUP2| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 lit3 v5 -// SWAP1| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 v5 lit3 -// POP| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 v5 +// DUP1| * v6 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 v5 // SWAP16| * v5 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 v6 // PUSH lit1| * v5 * v1 v2 * * * * phi1 * v3 phi2 v4 v5 lit2 v5 v6 lit1 // SWAP5| * v5 * v1 v2 * * * * phi1 * v3 phi2 lit1 v5 lit2 v5 v6 v4 diff --git a/test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack b/test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack index 571ed4a24..d583b0d6d 100644 --- a/test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack +++ b/test/libyul/ssa/stackShuffler/return_label_with_dup_and_grow.stack @@ -20,10 +20,7 @@ targetStackTop: [ReturnLabel[1], JUNK, JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, J // POP| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 // PUSH lit2| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 // DUP2| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 -// PUSH lit1| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit1 -// DUP2| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit1 v2 -// SWAP1| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 lit1 -// POP| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 +// DUP1| ReturnLabel[1] * * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 // SWAP16| ReturnLabel[1] * * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 // PUSH lit1| ReturnLabel[1] * * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 lit1 // SWAP5| ReturnLabel[1] * * v2 * * * * * * * * * * * lit1 v2 lit2 v2 v3 v1 diff --git a/test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack b/test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack index 845095016..46dde8a40 100644 --- a/test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack +++ b/test/libyul/ssa/stackShuffler/triple_dup_no_phi.stack @@ -9,10 +9,7 @@ targetStackTop: [JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, // POP| * v3 * * * * * * * * * * * v1 v2 // PUSH lit2| * v3 * * * * * * * * * * * v1 v2 lit2 // DUP2| * v3 * * * * * * * * * * * v1 v2 lit2 v2 -// PUSH lit3| * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 -// DUP2| * v3 * * * * * * * * * * * v1 v2 lit2 v2 lit3 v2 -// SWAP1| * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 lit3 -// POP| * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 +// DUP1| * v3 * * * * * * * * * * * v1 v2 lit2 v2 v2 // SWAP16| * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 // PUSH lit1| * v2 * * * * * * * * * * * v1 v2 lit2 v2 v3 lit1 // SWAP5| * v2 * * * * * * * * * * * lit1 v2 lit2 v2 v3 v1 diff --git a/test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack b/test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack index 3d28212bd..60f890972 100644 --- a/test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack +++ b/test/libyul/ssa/stackShuffler/triple_dup_with_phi.stack @@ -9,10 +9,7 @@ targetStackTop: [JUNK, v2, JUNK, JUNK, JUNK, JUNK, JUNK, JUNK, phi1, JUNK, JUNK, // POP| * v3 * * * * * * phi1 * * * * v1 v2 // PUSH lit2| * v3 * * * * * * phi1 * * * * v1 v2 lit2 // DUP2| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 -// PUSH lit3| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 lit3 -// DUP2| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 lit3 v2 -// SWAP1| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 v2 lit3 -// POP| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 v2 +// DUP1| * v3 * * * * * * phi1 * * * * v1 v2 lit2 v2 v2 // SWAP16| * v2 * * * * * * phi1 * * * * v1 v2 lit2 v2 v3 // PUSH lit1| * v2 * * * * * * phi1 * * * * v1 v2 lit2 v2 v3 lit1 // SWAP5| * v2 * * * * * * phi1 * * * * lit1 v2 lit2 v2 v3 v1 From 5b79872b66b55e6d36ed20ec7d98350064f4ba87 Mon Sep 17 00:00:00 2001 From: "Mate Soos @ Argot" Date: Thu, 16 Apr 2026 20:54:05 +0200 Subject: [PATCH 1242/1340] Adding stack shuffler loop bug (#16605) --- .../ssa/stackShuffler/loop-fuzzer.stack | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/libyul/ssa/stackShuffler/loop-fuzzer.stack diff --git a/test/libyul/ssa/stackShuffler/loop-fuzzer.stack b/test/libyul/ssa/stackShuffler/loop-fuzzer.stack new file mode 100644 index 000000000..49e6cf819 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/loop-fuzzer.stack @@ -0,0 +1,41 @@ +initial: [v0, phi0, phi0, lit0, v0, v0] +targetStackTop: [phi0, v0, v0, JUNK, phi0] +targetStackTailSet: {v0} +targetStackSize: 7 +// ---- +// | 0 1 | 2 3 4 5 6 +// +-------------- +----------------------------------- +// (initial)| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// POP| v0 phi0 | phi0 lit0 v0 v0 +// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 +// ...| +// +-------------- +----------------------------------- +// (target)| {v0} | phi0 v0 v0 * phi0 +// Status: MaxIterationsReached From 476ee898b117ab5f5e15212491c454a4b888b474 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 16 Apr 2026 21:24:32 +0200 Subject: [PATCH 1243/1340] in the ssa shuffler fix args slot, when offset is already top no swap-up is needed, so it doesn't have to be a valid swap target itself --- libyul/backends/evm/ssa/Stack.h | 1 + libyul/backends/evm/ssa/StackShuffler.h | 3 +- .../ssa/stackShuffler/loop-fuzzer.stack | 34 ++----------------- 3 files changed, 6 insertions(+), 32 deletions(-) diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index d4342426f..50f58aeb4 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -252,6 +252,7 @@ class Stack bool dupReachable(Depth const& _depth) const noexcept { return _depth < size() && _depth.value + 1 <= reachableStackDepth; } bool isValidSwapTarget(Offset const& _offset) const noexcept { return isValidSwapTarget(offsetToDepth(_offset)); } bool isValidSwapTarget(Depth const& _depth) const noexcept { return _depth < size() && 1 <= _depth.value && _depth.value <= reachableStackDepth; } + bool isBeyondSwapRange(Offset const& _offset) const noexcept { return isBeyondSwapRange(offsetToDepth(_offset)); } bool isBeyondSwapRange(Depth const& _depth) const noexcept { return _depth > reachableStackDepth; } void declareJunk(Offset const& _offset) { (*m_data)[_offset.value] = Slot::makeJunk(); } diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 14c136a14..80d57c560 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -471,7 +471,8 @@ class StackShuffler // swap up any slot in args that is out of position and has a slot available in args that it can occupy for (StackOffset offset: _state.stackArgsRange()) { - bool const reachable = _stack.isValidSwapTarget(offset); + // when offset is already top no swap-up is needed, so it doesn't have to be a valid swap target itself + bool const reachable = !_stack.isBeyondSwapRange(offset); bool const identical = _state.isArgsCompatible(offset, stackTop) && !_state.targetArbitrary(stackTop); if ( reachable && diff --git a/test/libyul/ssa/stackShuffler/loop-fuzzer.stack b/test/libyul/ssa/stackShuffler/loop-fuzzer.stack index 49e6cf819..7ea19fd61 100644 --- a/test/libyul/ssa/stackShuffler/loop-fuzzer.stack +++ b/test/libyul/ssa/stackShuffler/loop-fuzzer.stack @@ -6,36 +6,8 @@ targetStackSize: 7 // | 0 1 | 2 3 4 5 6 // +-------------- +----------------------------------- // (initial)| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// POP| v0 phi0 | phi0 lit0 v0 v0 -// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0 -// ...| +// SWAP2| v0 phi0 | phi0 v0 v0 lit0 +// DUP4| v0 phi0 | phi0 v0 v0 lit0 phi0 // +-------------- +----------------------------------- // (target)| {v0} | phi0 v0 v0 * phi0 -// Status: MaxIterationsReached +// Status: Admissible From d4b07e4db63a3abaebb5d4ae9e8484c79bde2df7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 17 Apr 2026 12:13:17 +0200 Subject: [PATCH 1244/1340] Add oscillating test to shuffler tests a deep phi needs to be lifted into args but isn't as the stack is shrunk which leads to a different deficit --- .../shrink_lifting_deep_phi.stack | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/libyul/ssa/stackShuffler/shrink_lifting_deep_phi.stack diff --git a/test/libyul/ssa/stackShuffler/shrink_lifting_deep_phi.stack b/test/libyul/ssa/stackShuffler/shrink_lifting_deep_phi.stack new file mode 100644 index 000000000..ff501d18c --- /dev/null +++ b/test/libyul/ssa/stackShuffler/shrink_lifting_deep_phi.stack @@ -0,0 +1,41 @@ +initial: [phi0, v0, lit0, v0, lit0, v0, lit0, v0, v0, lit0, v0, v0] +targetStackTop: [JUNK, lit0, v0, phi0, v0, v0, lit0, v0, v0] +targetStackTailSet: {} +targetStackSize: 12 +// ---- +// | 0 1 2 | 3 4 5 6 7 8 9 10 11 +// +--------------------- +--------------------------------------------------------------- +// (initial)| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 +// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 +// ...| +// +--------------------- +--------------------------------------------------------------- +// (target)| {} | * lit0 v0 phi0 v0 v0 lit0 v0 v0 +// Status: MaxIterationsReached From 13c7d66566265021d852d0581f01bbba996b485d Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 17 Apr 2026 12:16:11 +0200 Subject: [PATCH 1245/1340] SSA shuffler: Tighten condition under which a slot is duped up in fixArgsSlot A slot should only be duped up if it isn't already in place while scanning from args low -> high what is missing. The fix is guarded by `dupDeepSlotIfRequired`, i.e., whatever is duped, nothing vital can go out of range. --- libyul/backends/evm/ssa/StackShuffler.h | 29 +++++++++------- .../externalContracts/base64.sol | 6 ++-- .../externalContracts/deposit_contract.sol | 8 ++--- .../externalContracts/strings.sol | 6 ++-- .../shrink_lifting_deep_phi.stack | 34 +++---------------- 5 files changed, 31 insertions(+), 52 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 80d57c560..5e88c700c 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -534,22 +534,27 @@ class StackShuffler for (StackOffset offset{_state.target().tailSize}; offset < _state.target().size; ++offset.value) { Slot const& arg = _state.targetArg(offset); - if (!arg.isJunk() && (_state.count(arg) < _state.targetMinCount(arg) || _state.countInArgs(arg) < _state.targetArgsCount(arg))) + // skip this arg, if + if ( + arg.isJunk() || // .. the target arg is junk, it doesn't matter what slot occupies it, skip + _state.isArgsCompatible(offset, offset) || // .. it's already in place + (_state.count(arg) >= _state.targetMinCount(arg) && _state.countInArgs(arg) >= _state.targetArgsCount(arg)) // .. we have enough of it + ) + continue; + + if (auto sourceDepth = _stack.findSlotDepth(arg)) { - if (auto sourceDepth = _stack.findSlotDepth(arg)) + if (_stack.dupReachable(*sourceDepth)) { - if (_stack.dupReachable(*sourceDepth)) - { - _stack.dup(*sourceDepth); - return {ShuffleHelperResult::Status::StackModified}; - } - if (!_stack.canBeFreelyGenerated(arg)) - return {ShuffleHelperResult::Status::StackTooDeep, arg}; + _stack.dup(*sourceDepth); + return {ShuffleHelperResult::Status::StackModified}; } - yulAssert(_stack.canBeFreelyGenerated(arg)); - _stack.push(arg); - return {ShuffleHelperResult::Status::StackModified}; + if (!_stack.canBeFreelyGenerated(arg)) + return {ShuffleHelperResult::Status::StackTooDeep, arg}; } + yulAssert(_stack.canBeFreelyGenerated(arg)); + _stack.push(arg); + return {ShuffleHelperResult::Status::StackModified}; } // Try to dup the optimal slot based on liveness analysis diff --git a/test/libsolidity/semanticTests/externalContracts/base64.sol b/test/libsolidity/semanticTests/externalContracts/base64.sol index 93799e936..0efcda12d 100644 --- a/test/libsolidity/semanticTests/externalContracts/base64.sol +++ b/test/libsolidity/semanticTests/externalContracts/base64.sol @@ -41,8 +41,8 @@ contract test { // gas legacy code: 629800 // gas legacyOptimized: 87926 // gas legacyOptimized code: 429800 -// gas ssaCFGOptimized: 79931 -// gas ssaCFGOptimized code: 332600 +// gas ssaCFGOptimized: 79879 +// gas ssaCFGOptimized code: 331800 // encode_inline_asm(bytes): 0x20, 0 -> 0x20, 0 // encode_inline_asm(bytes): 0x20, 1, "f" -> 0x20, 4, "Zg==" // encode_inline_asm(bytes): 0x20, 2, "fo" -> 0x20, 4, "Zm8=" @@ -66,4 +66,4 @@ contract test { // gas irOptimized: 3512081 // gas legacy: 4600082 // gas legacyOptimized: 2813075 -// gas ssaCFGOptimized: 3089081 +// gas ssaCFGOptimized: 3077081 diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index baa951e71..fb186b481 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -185,8 +185,8 @@ contract DepositContract is IDepositContract, ERC165 { // gas legacy code: 1438800 // gas legacyOptimized: 848699 // gas legacyOptimized code: 878200 -// gas ssaCFGOptimized: 809663 -// gas ssaCFGOptimized code: 570000 +// gas ssaCFGOptimized: 809592 +// gas ssaCFGOptimized code: 569200 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # @@ -210,7 +210,7 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 109744 +// gas ssaCFGOptimized: 109741 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 @@ -218,5 +218,5 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 109744 +// gas ssaCFGOptimized: 109741 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 9bd1f39a0..534b41710 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -58,8 +58,8 @@ contract test { // gas legacy code: 932600 // gas legacyOptimized: 102639 // gas legacyOptimized code: 612400 -// gas ssaCFGOptimized: 96160 -// gas ssaCFGOptimized code: 532200 +// gas ssaCFGOptimized: 96128 +// gas ssaCFGOptimized code: 531800 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22646 // gas legacy: 23168 @@ -80,4 +80,4 @@ contract test { // gas irOptimized: 1976778 // gas legacy: 4234020 // gas legacyOptimized: 2318668 -// gas ssaCFGOptimized: 1882355 +// gas ssaCFGOptimized: 1882325 diff --git a/test/libyul/ssa/stackShuffler/shrink_lifting_deep_phi.stack b/test/libyul/ssa/stackShuffler/shrink_lifting_deep_phi.stack index ff501d18c..4dc9c74e9 100644 --- a/test/libyul/ssa/stackShuffler/shrink_lifting_deep_phi.stack +++ b/test/libyul/ssa/stackShuffler/shrink_lifting_deep_phi.stack @@ -7,35 +7,9 @@ targetStackSize: 12 // +--------------------- +--------------------------------------------------------------- // (initial)| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 // POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// DUP1| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 v0 -// POP| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 -// ...| +// DUP11| phi0 v0 lit0 | v0 lit0 v0 lit0 v0 v0 lit0 v0 phi0 +// SWAP5| phi0 v0 lit0 | v0 lit0 v0 phi0 v0 v0 lit0 v0 lit0 +// SWAP10| phi0 lit0 lit0 | v0 lit0 v0 phi0 v0 v0 lit0 v0 v0 // +--------------------- +--------------------------------------------------------------- // (target)| {} | * lit0 v0 phi0 v0 v0 lit0 v0 v0 -// Status: MaxIterationsReached +// Status: Admissible From 2a55ec604b029a517a4592c803334707c00575e4 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 30 Mar 2026 09:59:15 +0200 Subject: [PATCH 1246/1340] Make ethdebug inputs/outputs consistent --- libevmasm/AbstractAssemblyStack.h | 1 + libevmasm/EVMAssemblyStack.cpp | 5 + libevmasm/EVMAssemblyStack.h | 1 + libevmasm/Ethdebug.cpp | 14 +- libevmasm/Ethdebug.h | 3 + libsolidity/interface/CompilerStack.cpp | 15 +- libsolidity/interface/CompilerStack.h | 8 + libsolidity/interface/StandardCompiler.cpp | 97 +- solc/CommandLineInterface.cpp | 43 +- solc/CommandLineParser.cpp | 77 +- solc/CommandLineParser.h | 12 +- test/cmdlineTests.sh | 6 +- .../ethdebug_debuginfo_ssa_cfg/args | 1 + .../ethdebug_debuginfo_ssa_cfg/err | 1 + .../ethdebug_debuginfo_ssa_cfg/exit | 1 + .../ethdebug_debuginfo_ssa_cfg/input.sol | 6 + .../ethdebug_eof_container_osaka/args | 2 +- .../ethdebug_eof_container_osaka/output | 1025 ++++++++++++++++- test/cmdlineTests/ethdebug_on_abstract/args | 2 +- test/cmdlineTests/ethdebug_on_abstract/output | 18 +- test/cmdlineTests/ethdebug_on_interface/args | 2 +- .../cmdlineTests/ethdebug_on_interface/output | 18 +- test/cmdlineTests/ethdebug_resources/args | 1 + .../cmdlineTests/ethdebug_resources/input.sol | 6 + test/cmdlineTests/ethdebug_resources/output | 17 + test/cmdlineTests/metadata_experimental/args | 2 +- .../cmdlineTests/metadata_experimental/output | 16 +- .../input.json | 3 +- .../input.json | 3 +- .../output.json | 30 +- .../input.json | 22 + .../output.json | 11 + .../input.json | 18 + .../output.json | 15 + .../input.json | 18 + .../output.json | 23 + .../input.json | 3 +- .../input.json | 3 +- .../input.json | 3 +- .../input.json | 3 +- .../input.json | 3 +- .../input.json | 3 +- .../input.json | 3 +- .../input.json | 3 +- .../input.json | 2 +- .../input.json | 2 +- .../input.json | 17 - .../output.json | 11 - .../input.json | 2 +- .../output.json | 24 +- .../input.json | 2 +- .../input.json | 2 +- .../args | 0 .../in.yul | 1 + .../input.json | 12 + .../output.json | 10 + .../input.json | 2 +- .../input.json | 2 +- .../standard_yul_ethdebug_eof/input.json | 2 +- .../standard_yul_ethdebug_ir/input.json | 2 +- .../input.json | 2 +- .../standard_yul_ethdebug_resources/args | 1 + .../standard_yul_ethdebug_resources/in.yul | 17 + .../input.json | 12 + .../output.json | 18 + test/cmdlineTests/via_ssa_cfg_ethdebug/args | 2 +- test/libsolidity/StandardCompiler.cpp | 20 +- test/solc/CommandLineInterface.cpp | 187 +-- test/solc/CommandLineParser.cpp | 60 +- 69 files changed, 1598 insertions(+), 381 deletions(-) create mode 100644 test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/args create mode 100644 test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/err create mode 100644 test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/exit create mode 100644 test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/input.sol create mode 100644 test/cmdlineTests/ethdebug_resources/args create mode 100644 test/cmdlineTests/ethdebug_resources/input.sol create mode 100644 test/cmdlineTests/ethdebug_resources/output create mode 100644 test/cmdlineTests/standard_output_ethdebug_parse_only_incompatible/input.json create mode 100644 test/cmdlineTests/standard_output_ethdebug_parse_only_incompatible/output.json create mode 100644 test/cmdlineTests/standard_output_ethdebug_selection_compilation/input.json create mode 100644 test/cmdlineTests/standard_output_ethdebug_selection_compilation/output.json create mode 100644 test/cmdlineTests/standard_output_ethdebug_selection_resources/input.json create mode 100644 test/cmdlineTests/standard_output_ethdebug_selection_resources/output.json delete mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json delete mode 100644 test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/output.json rename test/cmdlineTests/{standard_yul_debug_info_ethdebug_incompatible_output => standard_yul_ethdebug_compilation}/args (100%) rename test/cmdlineTests/{standard_yul_debug_info_ethdebug_incompatible_output => standard_yul_ethdebug_compilation}/in.yul (99%) create mode 100644 test/cmdlineTests/standard_yul_ethdebug_compilation/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_compilation/output.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_resources/args create mode 100644 test/cmdlineTests/standard_yul_ethdebug_resources/in.yul create mode 100644 test/cmdlineTests/standard_yul_ethdebug_resources/input.json create mode 100644 test/cmdlineTests/standard_yul_ethdebug_resources/output.json diff --git a/libevmasm/AbstractAssemblyStack.h b/libevmasm/AbstractAssemblyStack.h index c4eb804ee..584c42fdc 100644 --- a/libevmasm/AbstractAssemblyStack.h +++ b/libevmasm/AbstractAssemblyStack.h @@ -43,6 +43,7 @@ class AbstractAssemblyStack virtual Json ethdebug(std::string const& _contractName) const = 0; virtual Json ethdebugRuntime(std::string const& _contractName) const = 0; virtual Json ethdebug() const = 0; + virtual Json ethdebugCompilation() const = 0; virtual Json assemblyJSON(std::string const& _contractName) const = 0; virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const = 0; diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index 34a5c8a2a..be9142a8a 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -123,6 +123,11 @@ Json EVMAssemblyStack::ethdebug() const return {}; } +Json EVMAssemblyStack::ethdebugCompilation() const +{ + return {}; +} + Json EVMAssemblyStack::assemblyJSON() const { solAssert(m_evmAssembly); diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index 444d444ba..d5efef938 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -74,6 +74,7 @@ class EVMAssemblyStack: public AbstractAssemblyStack Json ethdebug(std::string const& _contractName) const override; Json ethdebugRuntime(std::string const& _contractName) const override; Json ethdebug() const override; + Json ethdebugCompilation() const override; Json assemblyJSON() const; Json assemblyJSON(std::string const& _contractName) const override; diff --git a/libevmasm/Ethdebug.cpp b/libevmasm/Ethdebug.cpp index 8b87aadd0..10ef28f0b 100644 --- a/libevmasm/Ethdebug.cpp +++ b/libevmasm/Ethdebug.cpp @@ -160,10 +160,16 @@ Json ethdebug::resources(std::vector const& _sources, std::string c sources.push_back(source); } Json result = Json::object(); - result["compilation"] = Json::object(); - result["compilation"]["compiler"] = Json::object(); - result["compilation"]["compiler"]["name"] = "solc"; - result["compilation"]["compiler"]["version"] = _version; + result["compilation"] = compilation(_version); result["compilation"]["sources"] = sources; return result; } + +Json ethdebug::compilation(std::string_view _version) +{ + Json result = Json::object(); + result["compiler"] = Json::object(); + result["compiler"]["name"] = "solc"; + result["compiler"]["version"] = _version; + return result; +} diff --git a/libevmasm/Ethdebug.h b/libevmasm/Ethdebug.h index 2e0df3484..80c9a7e9b 100644 --- a/libevmasm/Ethdebug.h +++ b/libevmasm/Ethdebug.h @@ -32,4 +32,7 @@ Json program(std::string_view _name, unsigned _sourceID, Assembly const& _assemb // returns ethdebug/format/info/resources Json resources(std::vector const& _sources, std::string const& _version); +// returns the 'compilation' object from ethdebug/format/info/resources +Json compilation(std::string_view _version); + } // namespace solidity::evmasm::ethdebug diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index bb38555ec..03eede8f3 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -792,6 +792,7 @@ bool CompilerStack::compile(State _stopAfter) // Only compile contracts individually which have been requested. std::map> otherCompilers; + bool requiresFullCompilation = false; for (Source const* source: m_sourceOrder) for (ASTPointer const& node: source->ast->nodes()) @@ -802,6 +803,11 @@ bool CompilerStack::compile(State _stopAfter) try { + // Skip if full compilation is not needed (i.e. no IR/bytecode requested) + if (!pipelineConfig.needsFullCompilation()) + continue; + requiresFullCompilation = true; + if (pipelineConfig.needIR(m_viaIR)) generateIR(*contract, pipelineConfig.needIRCodegenOnly(m_viaIR)); if (pipelineConfig.needBytecode()) @@ -831,7 +837,8 @@ bool CompilerStack::compile(State _stopAfter) solAssert(!m_errorReporter.hasErrors()); m_stackState = CompilationSuccessful; - this->link(); + if (requiresFullCompilation) + this->link(); return true; } @@ -1227,10 +1234,14 @@ Json CompilerStack::interfaceSymbols(std::string const& _contractName) const Json CompilerStack::ethdebug() const { solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); - solAssert(!m_contracts.empty()); return evmasm::ethdebug::resources(sourceNames(), VersionString); } +Json CompilerStack::ethdebugCompilation() const +{ + return evmasm::ethdebug::compilation(VersionString); +} + Json CompilerStack::ethdebug(std::string const& _contractName) const { return ethdebug(contract(_contractName), /* runtime */ false); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 41f61ae4a..383a933d1 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -160,6 +160,11 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac return bytecode; } + bool needsFullCompilation() const + { + return irCodegen || irOptimization || bytecode; + } + PipelineConfig operator|(PipelineConfig const& _other) const { return { @@ -410,6 +415,9 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// Prerequisite: Successful call to parse or compile. Json ethdebug() const override; + /// @returns a JSON representing the ethdebug compilation data (compiler name and version). + Json ethdebugCompilation() const override; + /// @returns the Contract Metadata matching the pipeline selected using the viaIR setting. std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); } diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index c8dbeb317..0314abc58 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -244,6 +244,18 @@ bool isArtifactRequested(Json const& _outputSelection, std::string const& _file, return false; } +/// @returns boolean indicating whether @_artifacts is contained in @_outputSelection. Helper function. +template +bool areArtifactsRequested(Json const& _outputSelection, Range&& _artifacts) +{ + for (auto const& fileRequests: _outputSelection) + for (auto const& requests: fileRequests) + for (auto const& request: requests) + if (ranges::contains(_artifacts, request.get())) + return true; + return false; +} + /// @returns all artifact names of the EVM object, either for creation or deploy time. std::vector evmObjectComponents(std::string const& _objectKind) { @@ -264,7 +276,7 @@ bool isBinaryRequested(Json const& _outputSelection) static std::vector const outputsThatRequireBinaries = std::vector{ "*", "ir", "irAst", "irOptimized", "irOptimizedAst", "yulCFGJson", - "evm.gasEstimates", "evm.legacyAssembly", "evm.assembly", "ethdebug" + "evm.gasEstimates", "evm.legacyAssembly", "evm.assembly" } + evmObjectComponents("bytecode") + evmObjectComponents("deployedBytecode"); for (auto const& fileRequests: _outputSelection) @@ -294,37 +306,60 @@ bool isEvmBytecodeRequested(Json const& _outputSelection) return false; } -/// @returns true if ethdebug was requested. -bool isEthdebugRequested(Json const& _outputSelection) +/// @returns true if any per-contract ethdebug program output was requested. +bool isEthdebugProgramRequested(Json const& _outputSelection) { if (!_outputSelection.is_object()) return false; - static std::array const ethdebugArtifacts{"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"}; + static std::array constexpr ethdebugArtifacts{"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"}; - for (auto const& fileRequests: _outputSelection) - for (auto const& requests: fileRequests) - for (auto const& request: requests) - if (ranges::contains(ethdebugArtifacts, request.get())) - return true; + return areArtifactsRequested(_outputSelection, ethdebugArtifacts); +} + +/// @returns true if any ethdebug output (global or per-contract) was requested. +bool isAnyEthdebugRequested(Json const& _outputSelection) +{ + if (!_outputSelection.is_object()) + return false; + + static std::array constexpr ethdebugArtifacts{ + "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", + "ethdebug.resources", "ethdebug.compilation" + }; + + return areArtifactsRequested(_outputSelection, ethdebugArtifacts); +} + +/// @returns true if the given global ethdebug output was requested via */*. +bool isEthdebugGlobalOutputRequested(Json const& _outputSelection, std::string const& _artifact) +{ + if (!_outputSelection.is_object()) + return false; + + static std::array constexpr globalEthdebugArtifacts{"ethdebug.resources", "ethdebug.compilation"}; + if (!ranges::contains(globalEthdebugArtifacts, _artifact)) + return false; + + for (auto const& [file, contracts]: _outputSelection.items()) + if (file == "*" && contracts.is_object()) + for (auto const& [contract, requests]: contracts.items()) + if (contract == "*" && requests.is_array()) + for (auto const& request: requests) + if (request.get() == _artifact) + return true; return false; } bool isExperimentalArtifactRequested(Json const& _outputSelection) { - static std::array const experimentalArtifacts{"irAst", "irOptimizedAst", "yulCFGJson"}; + static std::array constexpr experimentalArtifacts{"irAst", "irOptimizedAst", "yulCFGJson"}; - if (isEthdebugRequested(_outputSelection)) + if (isAnyEthdebugRequested(_outputSelection)) return true; - for (auto const& fileRequests: _outputSelection) - for (auto const& requests: fileRequests) - for (auto const& request: requests) - if (ranges::contains(experimentalArtifacts, request.get())) - return true; - - return false; + return areArtifactsRequested(_outputSelection, experimentalArtifacts); } /// @returns The set of selected contracts, along with their compiler pipeline configuration, based @@ -1228,13 +1263,13 @@ std::variant StandardCompiler::parseI ret.modelCheckerSettings.timeout = modelCheckerSettings["timeout"].get(); } - if ((ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug) || isEthdebugRequested(ret.outputSelection)) + if ((ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug) || isAnyEthdebugRequested(ret.outputSelection)) { if (ret.language != "Solidity" && ret.language != "Yul") return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' 'ethdebug' is only supported for languages 'Solidity' and 'Yul'."); } - if (isEthdebugRequested(ret.outputSelection)) + if (isEthdebugProgramRequested(ret.outputSelection)) { if (ret.language == "Solidity" && !ret.viaIR) return formatFatalError(Error::Type::FatalError, "'evm.bytecode.ethdebug' or 'evm.deployedBytecode.ethdebug' can only be selected as output, if 'viaIR' was set."); @@ -1255,11 +1290,9 @@ std::variant StandardCompiler::parseI { if (!ret.experimental) return formatFatalError(Error::Type::FatalError, "Ethdebug annotations are experimental and can only be included in 'settings.debug.debugInfo' by enabling the 'settings.experimental' option."); - if (!pipelineConfig(ret.outputSelection)[""][""].irCodegen && !isEthdebugRequested(ret.outputSelection)) - return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected."); } - if (isEthdebugRequested(ret.outputSelection)) + if (isEthdebugProgramRequested(ret.outputSelection)) { if (ret.optimiserSettings.runYulOptimiser) solUnimplemented("Optimization is not yet supported with ethdebug."); @@ -1703,8 +1736,13 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu } } - if (isEthdebugRequested(_inputsAndSettings.outputSelection)) - output["ethdebug"] = compilerStack.ethdebug(); + if (analysisSuccess) + { + if (isEthdebugGlobalOutputRequested(_inputsAndSettings.outputSelection, "ethdebug.resources")) + output["ethdebug"]["resources"] = compilerStack.ethdebug(); + if (isEthdebugGlobalOutputRequested(_inputsAndSettings.outputSelection, "ethdebug.compilation")) + output["ethdebug"]["compilation"] = compilerStack.ethdebugCompilation(); + } if (!contractsOutput.empty()) output["contracts"] = contractsOutput; @@ -1867,10 +1905,15 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) output["contracts"][sourceName][contractName]["yulCFGJson"] = stack.cfgJson(); } - if (isEthdebugRequested(_inputsAndSettings.outputSelection)) + if (isEthdebugGlobalOutputRequested(_inputsAndSettings.outputSelection, "ethdebug.resources")) + { + solAssert(_inputsAndSettings.experimental, ""); + output["ethdebug"]["resources"] = evmasm::ethdebug::resources({sourceName}, VersionString); + } + if (isEthdebugGlobalOutputRequested(_inputsAndSettings.outputSelection, "ethdebug.compilation")) { solAssert(_inputsAndSettings.experimental, ""); - output["ethdebug"] = evmasm::ethdebug::resources({sourceName}, VersionString); + output["ethdebug"]["compilation"] = evmasm::ethdebug::compilation(VersionString); } return output; } diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index a805ac3fe..7403d947d 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -151,8 +151,10 @@ static bool needsHumanTargetedStdout(CommandLineOptions const& _options) _options.compiler.outputs.yulCFGJson || _options.compiler.outputs.binary || _options.compiler.outputs.binaryRuntime || - _options.compiler.outputs.ethdebug || - _options.compiler.outputs.ethdebugRuntime || + _options.compiler.outputs.ethdebugResources || + _options.compiler.outputs.ethdebugCompilation || + _options.compiler.outputs.ethdebugProgram || + _options.compiler.outputs.ethdebugProgramRuntime || _options.compiler.outputs.metadata || _options.compiler.outputs.natspecUser || _options.compiler.outputs.natspecDev || @@ -555,24 +557,33 @@ void CommandLineInterface::handleGasEstimation(std::string const& _contract) void CommandLineInterface::handleEthdebug() { - if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + if (m_options.compiler.outputs.ethdebugResources) { - std::string ethdebug{jsonPrint(removeNullMembers(m_compiler->ethdebug()), m_options.formatting.json)}; + std::string const ethdebug{jsonPrint(removeNullMembers(m_compiler->ethdebug()), m_options.formatting.json)}; if (!m_options.output.dir.empty()) - createFile("ethdebug.json", ethdebug); + createFile("ethdebug_resources.json", ethdebug); else sout() << "======= Debug Data (ethdebug/format/info/resources) =======" << std::endl << ethdebug << std::endl; } + + if (m_options.compiler.outputs.ethdebugCompilation) + { + std::string const compilation{jsonPrint(removeNullMembers(m_compiler->ethdebugCompilation()), m_options.formatting.json)}; + if (!m_options.output.dir.empty()) + createFile("ethdebug_compilation.json", compilation); + else + sout() << "======= Debug Data (ethdebug compilation) =======" << std::endl << compilation << std::endl; + } } void CommandLineInterface::handleEthdebug(std::string const& _contract) { solAssert(CompilerInputModes.count(m_options.input.mode) == 1); - if (!(m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime)) + if (!(m_options.compiler.outputs.ethdebugProgram || m_options.compiler.outputs.ethdebugProgramRuntime)) return; - if (m_options.compiler.outputs.ethdebug) + if (m_options.compiler.outputs.ethdebugProgram) { std::string ethdebug{jsonPrint(removeNullMembers(m_compiler->ethdebug(_contract)), m_options.formatting.json)}; if (!m_options.output.dir.empty()) @@ -581,7 +592,7 @@ void CommandLineInterface::handleEthdebug(std::string const& _contract) sout() << "Debug Data (ethdebug/format/program):" << std::endl << ethdebug << std::endl; } - if (m_options.compiler.outputs.ethdebugRuntime) + if (m_options.compiler.outputs.ethdebugProgramRuntime) { std::string ethdebugRuntime{jsonPrint(removeNullMembers(m_compiler->ethdebugRuntime(_contract)), m_options.formatting.json)}; if (!m_options.output.dir.empty()) @@ -960,8 +971,8 @@ void CommandLineInterface::compile() m_options.compiler.outputs.opcodes || m_options.compiler.outputs.binary || m_options.compiler.outputs.binaryRuntime || - m_options.compiler.outputs.ethdebug || - m_options.compiler.outputs.ethdebugRuntime || + m_options.compiler.outputs.ethdebugProgram || + m_options.compiler.outputs.ethdebugProgramRuntime || (m_options.compiler.combinedJsonRequests && ( m_options.compiler.combinedJsonRequests->binary || m_options.compiler.combinedJsonRequests->binaryRuntime || @@ -1356,7 +1367,7 @@ void CommandLineInterface::assembleYul(yul::YulStack::Machine _targetMachine) yul::YulStack const& stack = yulStacks[sourceUnitName]; yul::MachineAssemblyObject const& object = objects[sourceUnitName]; - if (m_options.compiler.outputs.ethdebug) + if (m_options.compiler.outputs.ethdebugResources) { sout() << "======= Debug Data (ethdebug/format/info/resources) =======" << std::endl; sout() << util::jsonPrint( @@ -1364,6 +1375,14 @@ void CommandLineInterface::assembleYul(yul::YulStack::Machine _targetMachine) m_options.formatting.json ) << std::endl; } + if (m_options.compiler.outputs.ethdebugCompilation) + { + sout() << "======= Debug Data (ethdebug compilation) =======" << std::endl; + sout() << util::jsonPrint( + evmasm::ethdebug::compilation(VersionString), + m_options.formatting.json + ) << std::endl; + } std::string machine = "EVM"; sout() << std::endl << "======= " << sourceUnitName << " (" << machine << ") =======" << std::endl; @@ -1414,7 +1433,7 @@ void CommandLineInterface::assembleYul(yul::YulStack::Machine _targetMachine) m_options.formatting.json ) << std::endl; } - if (m_options.compiler.outputs.ethdebug) + if (m_options.compiler.outputs.ethdebugProgram) { sout() << std::endl << "Debug Data (ethdebug/format/program):" << std::endl; sout() << util::jsonPrint( diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 08260a6fb..e48849ea7 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -168,8 +168,10 @@ std::vector const& CommandLineParser::experimentalOptionNames() "ir-ast-json", "ir-optimized-ast-json", "yul-cfg-json", - "ethdebug", - "ethdebug-runtime", + "ethdebug-resources", + "ethdebug-compilation", + "ethdebug-program", + "ethdebug-program-runtime", g_strEOFVersion, g_strViaSSACFG, }; @@ -475,7 +477,9 @@ void CommandLineParser::parseOutputSelection() CompilerOutputs::componentName(&CompilerOutputs::astCompactJson), CompilerOutputs::componentName(&CompilerOutputs::asmJson), CompilerOutputs::componentName(&CompilerOutputs::yulCFGJson), - CompilerOutputs::componentName(&CompilerOutputs::ethdebug), + CompilerOutputs::componentName(&CompilerOutputs::ethdebugResources), + CompilerOutputs::componentName(&CompilerOutputs::ethdebugCompilation), + CompilerOutputs::componentName(&CompilerOutputs::ethdebugProgram), }; static std::set const evmAssemblyJsonImportModeOutputs = { CompilerOutputs::componentName(&CompilerOutputs::asm_), @@ -781,13 +785,20 @@ General Information)").c_str(), "(experimental) Control Flow Graph (CFG) of Yul code in Static Single Assignment (SSA) form in JSON format." ) ( - CompilerOutputs::componentName(&CompilerOutputs::ethdebug).c_str(), - "(experimental) Debug information in ethdebug format for all contracts (ethdebug/format/program schema). " - "When enabled, an extra global output containing the ethdebug/format/info/resources schema with information shared by all contracts is automatically enabled as well." + CompilerOutputs::componentName(&CompilerOutputs::ethdebugResources).c_str(), + "(experimental) Global ethdebug output (ethdebug/format/info/resources schema) containing source list and compiler info." ) ( - CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime).c_str(), - ("(experimental) Like --" + CompilerOutputs::componentName(&CompilerOutputs::ethdebug) + ", but for the runtime part of the contracts.").c_str() + CompilerOutputs::componentName(&CompilerOutputs::ethdebugCompilation).c_str(), + "(experimental) Global ethdebug compilation output (the 'compilation' key from ethdebug/format/info/resources schema)." + ) + ( + CompilerOutputs::componentName(&CompilerOutputs::ethdebugProgram).c_str(), + "(experimental) Debug information in ethdebug format for all contracts (ethdebug/format/program schema for creation bytecode)." + ) + ( + CompilerOutputs::componentName(&CompilerOutputs::ethdebugProgramRuntime).c_str(), + "(experimental) Debug information in ethdebug format for the runtime part of all contracts (ethdebug/format/program schema for deployed bytecode)." ); desc.add(outputComponents); @@ -1377,7 +1388,7 @@ void CommandLineParser::processArgs() m_options.output.viaSSACFG = m_args.contains(g_strViaSSACFG); - if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + if (m_options.compiler.outputs.ethdebugProgram || m_options.compiler.outputs.ethdebugProgramRuntime) { if (m_options.output.viaSSACFG) solUnimplemented("ethdebug is not yet supported with --" + g_strViaSSACFG + "."); @@ -1531,32 +1542,20 @@ void CommandLineParser::processArgs() m_options.input.mode == InputMode::EVMAssemblerJSON ); - bool incompatibleEthdebugOutputs = - m_options.compiler.outputs.asmJson || m_options.compiler.outputs.irAstJson || m_options.compiler.outputs.irOptimizedAstJson || - m_options.optimizer.optimizeYul || m_options.optimizer.optimizeEvmasm; - - bool incompatibleEthdebugInputs = m_options.input.mode != InputMode::Compiler; - - static std::string enableEthdebugMessage = - "--" + CompilerOutputs::componentName(&CompilerOutputs::ethdebug) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime); + bool ethdebugProgramRequested = m_options.compiler.outputs.ethdebugProgram || m_options.compiler.outputs.ethdebugProgramRuntime; - static std::string enableIrMessage = "--" + CompilerOutputs::componentName(&CompilerOutputs::ir) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::irOptimized); + std::string const enableEthdebugProgramMessage = fmt::format( + "--{} / --{}", + CompilerOutputs::componentName(&CompilerOutputs::ethdebugProgram), + CompilerOutputs::componentName(&CompilerOutputs::ethdebugProgramRuntime) + ); - if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + if (ethdebugProgramRequested) { if (!m_options.output.viaIR) solThrow( CommandLineValidationError, - enableEthdebugMessage + " output can only be selected, if --via-ir was specified." - ); - - if (m_options.output.viaSSACFG) - solUnimplemented("ethdebug is not yet supported with --" + g_strViaSSACFG + "."); - - if (incompatibleEthdebugOutputs) - solThrow( - CommandLineValidationError, - enableEthdebugMessage + " output can only be used with " + enableIrMessage + ". Optimization (using --" + g_strOptimize + ") is not yet supported with ethdebug." + enableEthdebugProgramMessage + " output can only be selected, if --via-ir was specified." ); if (!m_options.output.debugInfoSelection.has_value()) @@ -1569,25 +1568,29 @@ void CommandLineParser::processArgs() if (!m_options.output.debugInfoSelection->ethdebug) solThrow( CommandLineValidationError, - "--debug-info must contain ethdebug, when compiling with " + enableEthdebugMessage + "." + "--debug-info must contain ethdebug, when compiling with " + enableEthdebugProgramMessage + "." ); } } if ( m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug && - (!(m_options.compiler.outputs.ir || m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) || incompatibleEthdebugOutputs) + m_options.input.mode != InputMode::Compiler ) solThrow( CommandLineValidationError, - "--debug-info ethdebug can only be used with " + enableIrMessage + " and/or " + enableEthdebugMessage + ". Optimization (using --" + g_strOptimize + ") is not yet supported with ethdebug." + "Invalid input mode for --debug-info ethdebug." ); - if (m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug && incompatibleEthdebugInputs) - solThrow( - CommandLineValidationError, - "Invalid input mode for --debug-info ethdebug / --ethdebug / --ethdebug-runtime." - ); + if (m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug) + { + if (m_options.output.viaSSACFG) + solUnimplemented("ethdebug is not yet supported with --" + g_strViaSSACFG + "."); + if (m_options.optimizer.optimizeYul || m_options.optimizer.optimizeEvmasm) + solUnimplemented( + "Optimization (using --" + g_strOptimize + ") is not yet supported with ethdebug." + ); + } } void CommandLineParser::parseCombinedJsonOption() diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 96dbb49c3..515864c71 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -88,8 +88,10 @@ struct CompilerOutputs {"storage-layout", &CompilerOutputs::storageLayout}, {"transient-storage-layout", &CompilerOutputs::transientStorageLayout}, {"yul-cfg-json", &CompilerOutputs::yulCFGJson}, - {"ethdebug", &CompilerOutputs::ethdebug}, - {"ethdebug-runtime", &CompilerOutputs::ethdebugRuntime}, + {"ethdebug-resources", &CompilerOutputs::ethdebugResources}, + {"ethdebug-compilation", &CompilerOutputs::ethdebugCompilation}, + {"ethdebug-program", &CompilerOutputs::ethdebugProgram}, + {"ethdebug-program-runtime", &CompilerOutputs::ethdebugProgramRuntime}, }; return components; } @@ -112,8 +114,10 @@ struct CompilerOutputs bool metadata = false; bool storageLayout = false; bool transientStorageLayout = false; - bool ethdebug = false; - bool ethdebugRuntime = false; + bool ethdebugResources = false; + bool ethdebugCompilation = false; + bool ethdebugProgram = false; + bool ethdebugProgramRuntime = false; }; struct CombinedJsonRequests diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index b3327ea98..c01675a5a 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -222,7 +222,7 @@ open("$stdout_path", "w").write(json) EOF # Only do this to files that actually contain ethdebug output, because jq will reformat # the whole file and its formatting differs from `solc --pretty-json` - if jq 'has("ethdebug")' "$stdout_path" --exit-status > /dev/null; then + if jq '[.. | objects | has("ethdebug")] | any' "$stdout_path" --exit-status > /dev/null; then local temporary_file temporary_file=$(mktemp -t cmdline-ethdebug-XXXXXX.tmp) if [[ -e strip-ethdebug ]]; then @@ -231,7 +231,9 @@ EOF ' "$stdout_path" > "$temporary_file" else jq --indent 4 ' - if .ethdebug.compilation.compiler.version? != null then + if .ethdebug.resources.compilation.compiler.version? != null then + .ethdebug.resources.compilation.compiler.version = "" + elif .ethdebug.compilation.compiler.version? != null then .ethdebug.compilation.compiler.version = "" else . diff --git a/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/args b/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/args new file mode 100644 index 000000000..8dd599e3d --- /dev/null +++ b/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/args @@ -0,0 +1 @@ +--experimental --debug-info ethdebug --via-ssa-cfg diff --git a/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/err b/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/err new file mode 100644 index 000000000..170609e36 --- /dev/null +++ b/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/err @@ -0,0 +1 @@ +Error: ethdebug is not yet supported with --via-ssa-cfg. diff --git a/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/exit b/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/input.sol b/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/input.sol new file mode 100644 index 000000000..415509ef9 --- /dev/null +++ b/test/cmdlineTests/ethdebug_debuginfo_ssa_cfg/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/args b/test/cmdlineTests/ethdebug_eof_container_osaka/args index 49c5bc838..32d3c3fc0 100644 --- a/test/cmdlineTests/ethdebug_eof_container_osaka/args +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/args @@ -1 +1 @@ ---experimental --experimental-eof-version 1 --evm-version osaka --ethdebug --via-ir --pretty-json --json-indent 4 +--experimental --experimental-eof-version 1 --evm-version osaka --ethdebug-compilation --ethdebug-program --ethdebug-program-runtime --via-ir --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ethdebug_eof_container_osaka/output b/test/cmdlineTests/ethdebug_eof_container_osaka/output index e9b57d885..58f3ff95d 100644 --- a/test/cmdlineTests/ethdebug_eof_container_osaka/output +++ b/test/cmdlineTests/ethdebug_eof_container_osaka/output @@ -1,16 +1,8 @@ -======= Debug Data (ethdebug/format/info/resources) ======= +======= Debug Data (ethdebug compilation) ======= { - "compilation": { - "compiler": { - "name": "solc", - "version": "" - }, - "sources": [ - { - "id": 0, - "path": "input.sol" - } - ] + "compiler": { + "name": "solc", + "version": "" } } @@ -251,3 +243,1012 @@ Debug Data (ethdebug/format/program): } ] } +Debug Data of the runtime part (ethdebug/format/program): +{ + "contract": { + "definition": { + "source": { + "id": 0 + } + }, + "name": "C" + }, + "environment": "call", + "instructions": [ + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 67, + "operation": { + "arguments": [ + "0x80" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 69, + "operation": { + "arguments": [ + "0x40" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 71, + "operation": { + "mnemonic": "MSTORE" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 72, + "operation": { + "arguments": [ + "0x04" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 74, + "operation": { + "mnemonic": "CALLDATASIZE" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 75, + "operation": { + "mnemonic": "LT" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 76, + "operation": { + "mnemonic": "ISZERO" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 77, + "operation": { + "arguments": [ + "0x0003" + ], + "mnemonic": "RJUMPI" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 80, + "operation": { + "arguments": [ + "0x0008" + ], + "mnemonic": "JUMPF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 83, + "operation": { + "mnemonic": "PUSH0" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 84, + "operation": { + "mnemonic": "CALLDATALOAD" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 85, + "operation": { + "arguments": [ + "0x0001" + ], + "mnemonic": "CALLF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 88, + "operation": { + "arguments": [ + "0x26121ff0" + ], + "mnemonic": "PUSH4" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 93, + "operation": { + "mnemonic": "EQ" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 94, + "operation": { + "arguments": [ + "0x0003" + ], + "mnemonic": "RJUMPI" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 97, + "operation": { + "arguments": [ + "0xffec" + ], + "mnemonic": "RJUMP" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 100, + "operation": { + "arguments": [ + "0x0007" + ], + "mnemonic": "JUMPF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 103, + "operation": { + "arguments": [ + "0xe0" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 105, + "operation": { + "mnemonic": "SHR" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 106, + "operation": { + "mnemonic": "RETF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 107, + "operation": { + "arguments": [ + "0x40" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 109, + "operation": { + "mnemonic": "MLOAD" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 110, + "operation": { + "mnemonic": "RETF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 111, + "operation": { + "mnemonic": "PUSH0" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 112, + "operation": { + "mnemonic": "DUP1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 113, + "operation": { + "mnemonic": "REVERT" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 114, + "operation": { + "mnemonic": "PUSH0" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 115, + "operation": { + "mnemonic": "DUP1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 116, + "operation": { + "mnemonic": "REVERT" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 117, + "operation": { + "mnemonic": "PUSH0" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 118, + "operation": { + "mnemonic": "SWAP2" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 119, + "operation": { + "mnemonic": "SUB" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 120, + "operation": { + "mnemonic": "SLT" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 121, + "operation": { + "arguments": [ + "0x0001" + ], + "mnemonic": "RJUMPI" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 124, + "operation": { + "mnemonic": "RETF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 125, + "operation": { + "arguments": [ + "0x0004" + ], + "mnemonic": "JUMPF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 128, + "operation": { + "mnemonic": "PUSH0" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 129, + "operation": { + "mnemonic": "ADD" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 130, + "operation": { + "mnemonic": "RETF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 131, + "operation": { + "mnemonic": "CALLVALUE" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 132, + "operation": { + "arguments": [ + "0x0011" + ], + "mnemonic": "RJUMPI" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 135, + "operation": { + "mnemonic": "CALLDATASIZE" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 136, + "operation": { + "arguments": [ + "0x04" + ], + "mnemonic": "PUSH1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 138, + "operation": { + "arguments": [ + "0x0005" + ], + "mnemonic": "CALLF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 141, + "operation": { + "arguments": [ + "0x0002" + ], + "mnemonic": "CALLF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 144, + "operation": { + "mnemonic": "DUP1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 145, + "operation": { + "mnemonic": "DUP1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 146, + "operation": { + "arguments": [ + "0x0006" + ], + "mnemonic": "CALLF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 149, + "operation": { + "mnemonic": "SUB" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 150, + "operation": { + "mnemonic": "SWAP1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 151, + "operation": { + "mnemonic": "RETURN" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 152, + "operation": { + "arguments": [ + "0x0003" + ], + "mnemonic": "JUMPF" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 155, + "operation": { + "mnemonic": "PUSH0" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 156, + "operation": { + "mnemonic": "DUP1" + } + }, + { + "context": { + "code": { + "range": { + "length": 41, + "offset": 60 + }, + "source": { + "id": 0 + } + } + }, + "offset": 157, + "operation": { + "mnemonic": "REVERT" + } + } + ] +} diff --git a/test/cmdlineTests/ethdebug_on_abstract/args b/test/cmdlineTests/ethdebug_on_abstract/args index c345d483a..7a58d286f 100644 --- a/test/cmdlineTests/ethdebug_on_abstract/args +++ b/test/cmdlineTests/ethdebug_on_abstract/args @@ -1 +1 @@ ---experimental --ethdebug --via-ir --pretty-json --json-indent 4 +--experimental --ethdebug-compilation --ethdebug-program --ethdebug-program-runtime --via-ir --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ethdebug_on_abstract/output b/test/cmdlineTests/ethdebug_on_abstract/output index 744ec0e77..6731c36d8 100644 --- a/test/cmdlineTests/ethdebug_on_abstract/output +++ b/test/cmdlineTests/ethdebug_on_abstract/output @@ -1,19 +1,13 @@ -======= Debug Data (ethdebug/format/info/resources) ======= +======= Debug Data (ethdebug compilation) ======= { - "compilation": { - "compiler": { - "name": "solc", - "version": "" - }, - "sources": [ - { - "id": 0, - "path": "input.sol" - } - ] + "compiler": { + "name": "solc", + "version": "" } } ======= input.sol:C ======= Debug Data (ethdebug/format/program): null +Debug Data of the runtime part (ethdebug/format/program): +null diff --git a/test/cmdlineTests/ethdebug_on_interface/args b/test/cmdlineTests/ethdebug_on_interface/args index c345d483a..7a58d286f 100644 --- a/test/cmdlineTests/ethdebug_on_interface/args +++ b/test/cmdlineTests/ethdebug_on_interface/args @@ -1 +1 @@ ---experimental --ethdebug --via-ir --pretty-json --json-indent 4 +--experimental --ethdebug-compilation --ethdebug-program --ethdebug-program-runtime --via-ir --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ethdebug_on_interface/output b/test/cmdlineTests/ethdebug_on_interface/output index 744ec0e77..6731c36d8 100644 --- a/test/cmdlineTests/ethdebug_on_interface/output +++ b/test/cmdlineTests/ethdebug_on_interface/output @@ -1,19 +1,13 @@ -======= Debug Data (ethdebug/format/info/resources) ======= +======= Debug Data (ethdebug compilation) ======= { - "compilation": { - "compiler": { - "name": "solc", - "version": "" - }, - "sources": [ - { - "id": 0, - "path": "input.sol" - } - ] + "compiler": { + "name": "solc", + "version": "" } } ======= input.sol:C ======= Debug Data (ethdebug/format/program): null +Debug Data of the runtime part (ethdebug/format/program): +null diff --git a/test/cmdlineTests/ethdebug_resources/args b/test/cmdlineTests/ethdebug_resources/args new file mode 100644 index 000000000..2fe9dcb0a --- /dev/null +++ b/test/cmdlineTests/ethdebug_resources/args @@ -0,0 +1 @@ +--experimental --ethdebug-resources --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/ethdebug_resources/input.sol b/test/cmdlineTests/ethdebug_resources/input.sol new file mode 100644 index 000000000..415509ef9 --- /dev/null +++ b/test/cmdlineTests/ethdebug_resources/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/ethdebug_resources/output b/test/cmdlineTests/ethdebug_resources/output new file mode 100644 index 000000000..89adfc67c --- /dev/null +++ b/test/cmdlineTests/ethdebug_resources/output @@ -0,0 +1,17 @@ +======= Debug Data (ethdebug/format/info/resources) ======= +{ + "compilation": { + "compiler": { + "name": "solc", + "version": "" + }, + "sources": [ + { + "id": 0, + "path": "input.sol" + } + ] + } +} + +======= input.sol:C ======= diff --git a/test/cmdlineTests/metadata_experimental/args b/test/cmdlineTests/metadata_experimental/args index 4a834e560..fa925f16e 100644 --- a/test/cmdlineTests/metadata_experimental/args +++ b/test/cmdlineTests/metadata_experimental/args @@ -1 +1 @@ ---metadata --experimental --via-ir --ethdebug --no-cbor-metadata --pretty-json --json-indent 4 +--metadata --experimental --via-ir --ethdebug-program --ethdebug-compilation --no-cbor-metadata --pretty-json --json-indent 4 diff --git a/test/cmdlineTests/metadata_experimental/output b/test/cmdlineTests/metadata_experimental/output index dc9145d5e..19ed8dab0 100644 --- a/test/cmdlineTests/metadata_experimental/output +++ b/test/cmdlineTests/metadata_experimental/output @@ -1,16 +1,8 @@ -======= Debug Data (ethdebug/format/info/resources) ======= +======= Debug Data (ethdebug compilation) ======= { - "compilation": { - "compiler": { - "name": "solc", - "version": "" - }, - "sources": [ - { - "id": 0, - "path": "input.sol" - } - ] + "compiler": { + "name": "solc", + "version": "" } } diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json index 72f16c0ea..878b2b41f 100644 --- a/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_compatible/input.json @@ -22,7 +22,8 @@ "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir", - "irOptimized" + "irOptimized", + "ethdebug.resources" ] } } diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json index 8d85b0ffa..e1104f5b3 100644 --- a/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/input.json @@ -20,7 +20,8 @@ "*": { "*": [ "evm.bytecode.ethdebug", - "evm.deployedBytecode.ethdebug" + "evm.deployedBytecode.ethdebug", + "ethdebug.resources" ] } } diff --git a/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/output.json b/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/output.json index 57b266801..16b6fc2b1 100644 --- a/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/output.json +++ b/test/cmdlineTests/standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/output.json @@ -26,21 +26,23 @@ } }, "ethdebug": { - "compilation": { - "compiler": { - "name": "solc", - "version": "" - }, - "sources": [ - { - "id": 0, - "path": "a.sol" + "resources": { + "compilation": { + "compiler": { + "name": "solc", + "version": "" }, - { - "id": 1, - "path": "b.sol" - } - ] + "sources": [ + { + "id": 0, + "path": "a.sol" + }, + { + "id": 1, + "path": "b.sol" + } + ] + } } }, "sources": { diff --git a/test/cmdlineTests/standard_output_ethdebug_parse_only_incompatible/input.json b/test/cmdlineTests/standard_output_ethdebug_parse_only_incompatible/input.json new file mode 100644 index 000000000..17afe568d --- /dev/null +++ b/test/cmdlineTests/standard_output_ethdebug_parse_only_incompatible/input.json @@ -0,0 +1,22 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract C { function f() public pure {} }" + } + }, + "settings": { + "experimental": true, + "stopAfter": "parsing", + "outputSelection": { + "*": { + "*": [ + "evm.bytecode.ethdebug", + "evm.deployedBytecode.ethdebug", + "ethdebug.resources", + "ethdebug.compilation" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_ethdebug_parse_only_incompatible/output.json b/test/cmdlineTests/standard_output_ethdebug_parse_only_incompatible/output.json new file mode 100644 index 000000000..1699ed880 --- /dev/null +++ b/test/cmdlineTests/standard_output_ethdebug_parse_only_incompatible/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Requested output selection conflicts with \"settings.stopAfter\".", + "message": "Requested output selection conflicts with \"settings.stopAfter\".", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_output_ethdebug_selection_compilation/input.json b/test/cmdlineTests/standard_output_ethdebug_selection_compilation/input.json new file mode 100644 index 000000000..b0379b6b6 --- /dev/null +++ b/test/cmdlineTests/standard_output_ethdebug_selection_compilation/input.json @@ -0,0 +1,18 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract C { function f() public pure {} }" + } + }, + "settings": { + "experimental": true, + "outputSelection": { + "*": { + "*": [ + "ethdebug.compilation" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_ethdebug_selection_compilation/output.json b/test/cmdlineTests/standard_output_ethdebug_selection_compilation/output.json new file mode 100644 index 000000000..cd37d5fdb --- /dev/null +++ b/test/cmdlineTests/standard_output_ethdebug_selection_compilation/output.json @@ -0,0 +1,15 @@ +{ + "ethdebug": { + "compilation": { + "compiler": { + "name": "solc", + "version": "" + } + } + }, + "sources": { + "a.sol": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_output_ethdebug_selection_resources/input.json b/test/cmdlineTests/standard_output_ethdebug_selection_resources/input.json new file mode 100644 index 000000000..7731cef30 --- /dev/null +++ b/test/cmdlineTests/standard_output_ethdebug_selection_resources/input.json @@ -0,0 +1,18 @@ +{ + "language": "Solidity", + "sources": { + "a.sol": { + "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\ncontract C { function f() public pure {} }" + } + }, + "settings": { + "experimental": true, + "outputSelection": { + "*": { + "*": [ + "ethdebug.resources" + ] + } + } + } +} diff --git a/test/cmdlineTests/standard_output_ethdebug_selection_resources/output.json b/test/cmdlineTests/standard_output_ethdebug_selection_resources/output.json new file mode 100644 index 000000000..0cbba50a8 --- /dev/null +++ b/test/cmdlineTests/standard_output_ethdebug_selection_resources/output.json @@ -0,0 +1,23 @@ +{ + "ethdebug": { + "resources": { + "compilation": { + "compiler": { + "name": "solc", + "version": "" + }, + "sources": [ + { + "id": 0, + "path": "a.sol" + } + ] + } + } + }, + "sources": { + "a.sol": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json index 2fd0aecf8..b83cf6508 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/input.json @@ -19,7 +19,8 @@ "*": [ "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", - "ir" + "ir", + "ethdebug.resources" ] } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json index 58fb7b42f..ff8dd7140 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/input.json @@ -19,7 +19,8 @@ "*": [ "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", - "irOptimized" + "irOptimized", + "ethdebug.resources" ] } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json index 292c86e37..9bab955c8 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_ir/input.json @@ -18,7 +18,8 @@ "*": { "*": [ "evm.bytecode.ethdebug", - "ir" + "ir", + "ethdebug.resources" ] } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json index 2e4bb8ec9..1a3fb9098 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_bytecode_iroptimized/input.json @@ -18,7 +18,8 @@ "*": { "*": [ "evm.bytecode.ethdebug", - "irOptimized" + "irOptimized", + "ethdebug.resources" ] } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json index cd6a3d15b..23698d7c1 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_ir/input.json @@ -18,7 +18,8 @@ "*": { "*": [ "evm.deployedBytecode.ethdebug", - "ir" + "ir", + "ethdebug.resources" ] } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json index d9a5104f4..ce2ae6f33 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_deployedbytecode_iroptimized/input.json @@ -18,7 +18,8 @@ "*": { "*": [ "evm.deployedBytecode.ethdebug", - "irOptimized" + "irOptimized", + "ethdebug.resources" ] } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json index f60133269..1034d8d37 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_ir/input.json @@ -15,7 +15,8 @@ "*": { "*": [ "evm.bytecode.ethdebug", - "ir" + "ir", + "ethdebug.resources" ] } } diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json index fb1e11bbc..ba4046a64 100644 --- a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json +++ b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/input.json @@ -15,7 +15,8 @@ "*": { "*": [ "evm.bytecode.ethdebug", - "irOptimized" + "irOptimized", + "ethdebug.resources" ] } } diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json index 755d770fe..c459aadef 100644 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output/input.json @@ -11,7 +11,7 @@ "experimental": true, "debug": {"debugInfo": ["ethdebug"]}, "outputSelection": { - "*": {"*": ["ir", "irOptimized", "evm.bytecode.ethdebug"]} + "*": {"*": ["ir", "irOptimized", "evm.bytecode.ethdebug", "ethdebug.resources"]} } } } diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json index b83ec361c..7cf3af382 100644 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json +++ b/test/cmdlineTests/standard_yul_debug_info_ethdebug_compatible_output_eof/input.json @@ -13,7 +13,7 @@ "evmVersion": "osaka", "debug": {"debugInfo": ["ethdebug"]}, "outputSelection": { - "*": {"*": ["ir", "irOptimized", "evm.bytecode.ethdebug"]} + "*": {"*": ["ir", "irOptimized", "evm.bytecode.ethdebug", "ethdebug.resources"]} } } } diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json deleted file mode 100644 index e4c9d17e5..000000000 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/input.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "language": "Yul", - "sources": { - "C": { - "urls": [ - "in.yul" - ] - } - }, - "settings": { - "experimental": true, - "debug": {"debugInfo": ["ethdebug"]}, - "outputSelection": { - "*": {"*": ["evm.assembly"]} - } - } -} diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/output.json b/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/output.json deleted file mode 100644 index 963bcd8d7..000000000 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/output.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": [ - { - "component": "general", - "formattedMessage": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", - "message": "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized', 'evm.bytecode.ethdebug', or 'evm.deployedBytecode.ethdebug' was selected.", - "severity": "error", - "type": "FatalError" - } - ] -} diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json index 89127b977..c0ae2d50f 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/input.json @@ -6,7 +6,7 @@ "settings": { "experimental": true, "outputSelection": { - "*": {"*": ["evm.bytecode.ethdebug"]} + "*": {"*": ["evm.bytecode.ethdebug", "ethdebug.resources"]} } } } diff --git a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/output.json b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/output.json index 3af82e21d..f78f6ce7c 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/output.json +++ b/test/cmdlineTests/standard_yul_ethdebug_assign_immutable/output.json @@ -111,17 +111,19 @@ } }, "ethdebug": { - "compilation": { - "compiler": { - "name": "solc", - "version": "" - }, - "sources": [ - { - "id": 0, - "path": "C" - } - ] + "resources": { + "compilation": { + "compiler": { + "name": "solc", + "version": "" + }, + "sources": [ + { + "id": 0, + "path": "C" + } + ] + } } } } diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json index 9d5829df0..617c93f68 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_ir/input.json @@ -6,7 +6,7 @@ "settings": { "experimental": true, "outputSelection": { - "*": {"*": ["evm.bytecode.ethdebug", "ir"]} + "*": {"*": ["evm.bytecode.ethdebug", "ir", "ethdebug.resources"]} } } } diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json index da8378a8b..5abd87a0d 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/input.json @@ -6,7 +6,7 @@ "settings": { "experimental": true, "outputSelection": { - "*": {"*": ["evm.bytecode.ethdebug", "irOptimized"]} + "*": {"*": ["evm.bytecode.ethdebug", "irOptimized", "ethdebug.resources"]} } } } diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/args b/test/cmdlineTests/standard_yul_ethdebug_compilation/args similarity index 100% rename from test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/args rename to test/cmdlineTests/standard_yul_ethdebug_compilation/args diff --git a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/in.yul b/test/cmdlineTests/standard_yul_ethdebug_compilation/in.yul similarity index 99% rename from test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/in.yul rename to test/cmdlineTests/standard_yul_ethdebug_compilation/in.yul index aa564d00c..920aef8e9 100644 --- a/test/cmdlineTests/standard_yul_debug_info_ethdebug_incompatible_output/in.yul +++ b/test/cmdlineTests/standard_yul_ethdebug_compilation/in.yul @@ -14,3 +14,4 @@ object "C_6_deployed" { /// @src 0:60:101 "contract C {..." } } + diff --git a/test/cmdlineTests/standard_yul_ethdebug_compilation/input.json b/test/cmdlineTests/standard_yul_ethdebug_compilation/input.json new file mode 100644 index 000000000..66aff6b00 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_compilation/input.json @@ -0,0 +1,12 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["in.yul"]} + }, + "settings": { + "experimental": true, + "outputSelection": { + "*": {"*": ["ethdebug.compilation"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_compilation/output.json b/test/cmdlineTests/standard_yul_ethdebug_compilation/output.json new file mode 100644 index 000000000..d5037bd7d --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_compilation/output.json @@ -0,0 +1,10 @@ +{ + "ethdebug": { + "compilation": { + "compiler": { + "name": "solc", + "version": "" + } + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json index fcfcaf3bd..ff39d837e 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/input.json @@ -6,7 +6,7 @@ "settings": { "experimental": true, "outputSelection": { - "*": {"*": ["evm.deployedBytecode.ethdebug"]} + "*": {"*": ["evm.deployedBytecode.ethdebug", "ethdebug.resources"]} } } } diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json index 2bedd407b..713c5c842 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode_and_bytecode/input.json @@ -6,7 +6,7 @@ "settings": { "experimental": true, "outputSelection": { - "*": {"*": ["evm.deployedBytecode.ethdebug", "evm.bytecode.ethdebug"]} + "*": {"*": ["evm.deployedBytecode.ethdebug", "evm.bytecode.ethdebug", "ethdebug.resources"]} } } } diff --git a/test/cmdlineTests/standard_yul_ethdebug_eof/input.json b/test/cmdlineTests/standard_yul_ethdebug_eof/input.json index 3455e61d7..ebc74d66b 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_eof/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_eof/input.json @@ -8,7 +8,7 @@ "eofVersion": 1, "evmVersion": "osaka", "outputSelection": { - "*": {"*": ["evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir", "irOptimized"]} + "*": {"*": ["evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir", "irOptimized", "ethdebug.resources"]} } } } diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/input.json b/test/cmdlineTests/standard_yul_ethdebug_ir/input.json index 9d5829df0..617c93f68 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_ir/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_ir/input.json @@ -6,7 +6,7 @@ "settings": { "experimental": true, "outputSelection": { - "*": {"*": ["evm.bytecode.ethdebug", "ir"]} + "*": {"*": ["evm.bytecode.ethdebug", "ir", "ethdebug.resources"]} } } } diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json index 2d3610908..abcb5e96d 100644 --- a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json +++ b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/input.json @@ -6,7 +6,7 @@ "settings": { "experimental": true, "outputSelection": { - "*": {"*": ["evm.bytecode.ethdebug", "irOptimize"]} + "*": {"*": ["evm.bytecode.ethdebug", "irOptimize", "ethdebug.resources"]} } } } diff --git a/test/cmdlineTests/standard_yul_ethdebug_resources/args b/test/cmdlineTests/standard_yul_ethdebug_resources/args new file mode 100644 index 000000000..18532c5a6 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_resources/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_yul_ethdebug_resources/in.yul b/test/cmdlineTests/standard_yul_ethdebug_resources/in.yul new file mode 100644 index 000000000..920aef8e9 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_resources/in.yul @@ -0,0 +1,17 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + sstore(0, 42) + } + /// @src 0:60:101 "contract C {..." + } +} + diff --git a/test/cmdlineTests/standard_yul_ethdebug_resources/input.json b/test/cmdlineTests/standard_yul_ethdebug_resources/input.json new file mode 100644 index 000000000..65355e852 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_resources/input.json @@ -0,0 +1,12 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["in.yul"]} + }, + "settings": { + "experimental": true, + "outputSelection": { + "*": {"*": ["ethdebug.resources"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_ethdebug_resources/output.json b/test/cmdlineTests/standard_yul_ethdebug_resources/output.json new file mode 100644 index 000000000..4cd8c9c40 --- /dev/null +++ b/test/cmdlineTests/standard_yul_ethdebug_resources/output.json @@ -0,0 +1,18 @@ +{ + "ethdebug": { + "resources": { + "compilation": { + "compiler": { + "name": "solc", + "version": "" + }, + "sources": [ + { + "id": 0, + "path": "C" + } + ] + } + } + } +} diff --git a/test/cmdlineTests/via_ssa_cfg_ethdebug/args b/test/cmdlineTests/via_ssa_cfg_ethdebug/args index fa8be093c..7c85efbc7 100644 --- a/test/cmdlineTests/via_ssa_cfg_ethdebug/args +++ b/test/cmdlineTests/via_ssa_cfg_ethdebug/args @@ -1 +1 @@ ---experimental --via-ssa-cfg --ethdebug +--experimental --via-ssa-cfg --ethdebug-program --ethdebug-compilation diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 187ff53a6..c13704cc0 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -2099,21 +2099,21 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) generateExperimentalStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"})), [](const Json& result) { - return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + return result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); } }, { generateExperimentalStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"})), [](const Json& result) { - return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); + return result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); } }, { generateExperimentalStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { - return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && + return result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); } }, @@ -2121,21 +2121,21 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug"})), [](const Json& result) { - return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + return result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); } }, { generateExperimentalStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug"})), [](const Json& result) { - return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); + return result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); } }, { generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"})), [](const Json& result) { - return result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && + return result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); } }, @@ -2143,14 +2143,14 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "ir"})), [](const Json& result) { - return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); + return result.dump().find("/// ethdebug: enabled") != std::string::npos && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); } }, { generateExperimentalStandardJson(true, {}, Json::array({"evm.deployedBytecode.ethdebug", "ir"})), [](const Json& result) { - return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); + return result.dump().find("/// ethdebug: enabled") != std::string::npos && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug"); } }, { @@ -2165,7 +2165,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) generateExperimentalStandardJson(true, {}, Json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"})), [](const Json& result) { - return result.dump().find("/// ethdebug: enabled") != std::string::npos && result.contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && + return result.dump().find("/// ethdebug: enabled") != std::string::npos && result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug") && result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug"); } }, @@ -2212,7 +2212,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) [](const Json& result) { return result["contracts"]["fileA"]["contractA"]["evm"]["deployedBytecode"].contains("ethdebug") && - result["contracts"]["fileB"]["contractB"]["evm"]["bytecode"].contains("ethdebug") && result.contains("ethdebug"); + result["contracts"]["fileB"]["contractB"]["evm"]["bytecode"].contains("ethdebug"); } } }; diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 720c3b154..db78081d1 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -1414,73 +1414,36 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_ambiguous_import) BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_outputs) { TemporaryDirectory tempDir(TEST_CASE_NAME); - createFilesWithParentDirs({tempDir.path() / "input.sol"}); - static std::vector> tests{ - { - {"solc", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--via-ir", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--via-ir", "--ethdebug", "--optimize", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--via-ir", "--ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--via-ir", "--ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, - }, - { - {"solc", "--via-ir", "--ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--via-ir", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--via-ir", "--ethdebug-runtime", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--via-ir", "--ethdebug-runtime", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--ethdebug-runtime", "--import-asm-json", tempDir.path().string() + "/input.json"}, - }, + createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); + // The old incompatibility between ethdebug and --asm-json / --ir-ast-json / --ir-optimized-ast-json + // has been removed. These combinations are now valid as long as other requirements are met. + static std::vector> supportedCLIFlagCombinations{ { - {"solc", "--via-ir", "--ethdebug-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--via-ir", "--ethdebug-program", "--asm-json", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--via-ir", "--ethdebug-program-runtime", "--asm-json", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--via-ir", "--ethdebug-program", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--via-ir", "--ethdebug-program", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, }, - { - {"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.json"}, - } }; - for (auto const& test: tests) + for (auto const& test: supportedCLIFlagCombinations) { OptionsReaderAndMessages result = runCLI(test, ""); - BOOST_REQUIRE(!result.success); + BOOST_REQUIRE(result.success); } } @@ -1490,22 +1453,22 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_input_modes) createFilesWithParentDirs({tempDir.path() / "input.json"}); static std::vector> tests{ { - {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + {"solc", "--ethdebug-program", "--import-asm-json", tempDir.path().string() + "/input.json"}, }, { - {"solc", "--ethdebug", "--via-ir", "--import-asm-json", tempDir.path().string() + "/input.json"}, + {"solc", "--ethdebug-program", "--via-ir", "--import-asm-json", tempDir.path().string() + "/input.json"}, }, { - {"solc", "--ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, + {"solc", "--ethdebug-program-runtime", "--import-asm-json", tempDir.path().string() + "/input.json"}, }, { {"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, }, { - {"solc", "--ethdebug", "--import-ast", tempDir.path().string() + "/input.json"}, + {"solc", "--ethdebug-program", "--import-ast", tempDir.path().string() + "/input.json"}, }, { - {"solc", "--ethdebug", "--via-ir", "--import-ast", tempDir.path().string() + "/input.json"}, + {"solc", "--ethdebug-program", "--via-ir", "--import-ast", tempDir.path().string() + "/input.json"}, }, { {"solc", "--debug-info", "ethdebug", "--ir", "--import-ast", tempDir.path().string() + "/input.json"}, @@ -1524,50 +1487,18 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_debug_info_ethdebug) createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); createFilesWithParentDirs({tempDir.path() / "input.yul"}, "{}"); static std::vector> erroneousCLIFlagCombinations{ + // --debug-info ethdebug with --optimize is not supported { - {"solc", "--experimental", "--debug-info", "ethdebug", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--experimental", "--debug-info", "ethdebug", "--ir-optimized", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--experimental", "--debug-info", "ethdebug", "--optimize", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--experimental", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--optimize", "--ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug", "--ethdebug-runtime", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {"solc", "--experimental", "--debug-info", "location", "--ethdebug-program", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "location", "--ethdebug-program-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--experimental", "--debug-info", "location", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--experimental", "--debug-info", "location", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--experimental", "--debug-info", "location", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--experimental", "--debug-info", "all", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--experimental", "--debug-info", "all", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, - }, - { - {"solc", "--experimental", "--debug-info", "all", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "location", "--ethdebug-program", "--ethdebug-program-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, }, }; static std::vector> supportedCLIFlagCombinations{ @@ -1575,36 +1506,19 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_debug_info_ethdebug) {"solc", "--experimental", "--debug-info", "ethdebug", "--ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--debug-info", "ethdebug", tempDir.path().string() + "/input.sol"}, }, { - { - "solc", - "--experimental", - "--debug-info", - "ethdebug", - "--ethdebug-runtime", - "--via-ir", - tempDir.path().string() + "/input.sol" - }, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug-program", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--debug-info", "ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug-program-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, + {"solc", "--experimental", "--debug-info", "ethdebug", "--ethdebug-program", "--ethdebug-program-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, }, { - { - "solc", - "--experimental", - "--debug-info", - "ethdebug", - "--ethdebug", - "--ethdebug-runtime", - "--via-ir", - tempDir.path().string() + "/input.sol" - }, + {"solc", "--experimental", "--debug-info", "ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, }, }; @@ -1626,56 +1540,57 @@ BOOST_AUTO_TEST_CASE(cli_ethdebug_ethdebug_output) createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); static std::vector> erroneousCLIFlagCombinations{ { - {"solc", "--experimental", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-program", "--ethdebug-program-runtime", "--via-ir", "--optimize", tempDir.path().string() + "/input.sol"}, }, { - { - "solc", - "--experimental", - "--ethdebug-runtime", - "--via-ir", - "--ir-optimized", - "--optimize", - tempDir.path().string() + "/input.sol" - }, + {"solc", "--experimental", "--ethdebug-program-runtime", "--via-ir", "--optimize", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug", "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-program", "--via-ir", "--optimize", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-program", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-program", "--ethdebug-program-runtime", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug-runtime", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-program-runtime", tempDir.path().string() + "/input.sol"}, }, }; static std::vector> supportedCLIFlagCombinations{ { - {"solc", "--experimental", "--ethdebug", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-program", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--experimental", "--ethdebug-program-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--experimental", "--ethdebug-program", "--ethdebug-program-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + }, + { + {"solc", "--experimental", "--ethdebug-program", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-program-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug", "--ethdebug-runtime", "--via-ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-program", "--ethdebug-program-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-program", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-program-runtime", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug", "--ethdebug-runtime", "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-resources", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-compilation", tempDir.path().string() + "/input.sol"}, }, { - {"solc", "--experimental", "--ethdebug-runtime", "--via-ir", "--ir-optimized", tempDir.path().string() + "/input.sol"}, + {"solc", "--experimental", "--ethdebug-resources", "--ethdebug-compilation", tempDir.path().string() + "/input.sol"}, }, }; diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 365944652..f656f2eda 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -649,39 +649,55 @@ BOOST_AUTO_TEST_CASE(invalid_optimizer_sequence_without_optimize) BOOST_AUTO_TEST_CASE(ethdebug) { - CommandLineOptions commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--debug-info", "ethdebug", "--ethdebug", "--via-ir"}); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); + // --ethdebug-program with explicit debug-info + CommandLineOptions commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--debug-info", "ethdebug", "--ethdebug-program", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgram, true); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgramRuntime, false); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); - commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--debug-info", "ethdebug", "--ethdebug-runtime", "--via-ir"}); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); + // --ethdebug-program-runtime with explicit debug-info + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--debug-info", "ethdebug", "--ethdebug-program-runtime", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgram, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgramRuntime, true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); - commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--ethdebug", "--via-ir"}); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); - // debug-info "ethdebug" selected implicitly, - // if compiled with --ethdebug or --ethdebug-runtime and no debug-info was selected. + // --ethdebug-program implicitly enables debug-info ethdebug + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--ethdebug-program", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgram, true); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgramRuntime, false); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); - commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--ethdebug-runtime", "--via-ir"}); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); + // --ethdebug-program-runtime implicitly enables debug-info ethdebug + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--ethdebug-program-runtime", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgram, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgramRuntime, true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); - commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--ethdebug", "--ethdebug-runtime", "--via-ir"}); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, true); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, true); + // both --ethdebug-program and --ethdebug-program-runtime + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--ethdebug-program", "--ethdebug-program-runtime", "--via-ir"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgram, true); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgramRuntime, true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + // --debug-info ethdebug with --ir only (no program output) commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--debug-info", "ethdebug", "--ir"}); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebug, false); - BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugRuntime, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgram, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgramRuntime, false); BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ir, true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection.has_value(), true); BOOST_CHECK_EQUAL(commandLineOptions.output.debugInfoSelection->ethdebug, true); + // --ethdebug-resources does not require --via-ir + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--ethdebug-resources"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugResources, true); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugCompilation, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgram, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgramRuntime, false); + // --ethdebug-compilation does not require --via-ir + commandLineOptions = parseCommandLine({"solc", "contract.sol", "--experimental", "--ethdebug-compilation"}); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugResources, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugCompilation, true); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgram, false); + BOOST_CHECK_EQUAL(commandLineOptions.compiler.outputs.ethdebugProgramRuntime, false); } BOOST_AUTO_TEST_CASE(experimental_features_without_experimental_flag) @@ -693,8 +709,10 @@ BOOST_AUTO_TEST_CASE(experimental_features_without_experimental_flag) "--ir-ast-json", "--ir-optimized-ast-json", "--yul-cfg-json", - "--ethdebug", - "--ethdebug-runtime", + "--ethdebug-resources", + "--ethdebug-compilation", + "--ethdebug-program", + "--ethdebug-program-runtime", "--via-ssa-cfg" }; From d3444c2e34627682f9f0960bf529ca20374b1292 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Mon, 6 Apr 2026 13:34:13 +0200 Subject: [PATCH 1247/1340] Docs --- docs/using-the-compiler.rst | 63 +++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 7a97fa54e..478ccd146 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -393,7 +393,7 @@ Input Description // The snippet is quoted and follows the corresponding `@src` annotation. // - `ast-id`: Annotations of the form `@ast-id ` over elements that can be mapped back to a definition in the original Solidity file. // `` is a node ID in the Solidity AST ('ast' output). - // - `ethdebug`: Ethdebug annotations (experimental). + // - `ethdebug`: Ethdebug annotations (experimental). Automatically enabled when any ethdebug output is requested. // - `*`: Wildcard value that can be used to request all non-experimental components. "debugInfo": ["location", "snippet", "ast-id", "ethdebug"] }, @@ -453,8 +453,8 @@ Input Description // transientStorageLayout - Slots, offsets and types of the contract's state variables in transient storage // evm.assembly - New assembly format // evm.legacyAssembly - Old-style assembly format in JSON - // evm.bytecode.ethdebug - Debug information in ethdebug format (ethdebug/format/program schema). Can only be requested when compiling via IR. (experimental) - // evm.deployedBytecode.ethdebug - Like evm.bytecode.ethdebug, but for the runtime part of the contract (experimental) + // evm.bytecode.ethdebug - Debug information in ethdebug format (ethdebug/format/program schema for creation bytecode). Can only be requested when compiling via IR. (experimental) + // evm.deployedBytecode.ethdebug - Debug information in ethdebug format (ethdebug/format/program schema for deployed bytecode). Can only be requested when compiling via IR. (experimental) // evm.bytecode.functionDebugData - Debugging information at function level // evm.bytecode.object - Bytecode object // evm.bytecode.opcodes - Opcodes list @@ -467,6 +467,10 @@ Input Description // evm.gasEstimates - Function gas estimates // yulCFGJson - Control Flow Graph (CFG) of the Single Static Assignment (SSA) form of the contract (experimental) // + // Global level (needs "*" as file name and "*" as contract name): + // ethdebug.resources - Global ethdebug output (ethdebug/format/info/resources schema) containing source list and compiler info (experimental) + // ethdebug.compilation - Global ethdebug compilation output (the 'compilation' key from ethdebug/format/info/resources schema) (experimental) + // // Note that using `evm`, `evm.bytecode`, etc. will select every // target part of that output. Additionally, `*` can be used as a wildcard to request everything. // @@ -696,7 +700,12 @@ Output Description } }, // Global Ethdebug output (experimental) - "ethdebug": {/* ... */ } + "ethdebug": { + // Requested via ethdebug.resources output selection + "resources": {/* ... */}, + // Requested via ethdebug.compilation output selection + "compilation": {/* ... */} + } } @@ -751,26 +760,26 @@ Note that the use of this mode is recorded in the metadata: The table below details all currently available experimental features. -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| Feature | ID | Affects bytecode | Flag/pragma | -+=======================+==========================+==================+===================================================================+ -| AST import | ``ast-import`` | yes | ``--import-ast`` | -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| LSP | ``lsp`` | no | ``--lsp`` | -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| EVM Assembly import | ``evmasm-import`` | yes | ``--import-asm-json`` | -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| Generic Solidity | ``generic-solidity`` | yes | ``pragma experimental solidity`` | -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| IR AST | ``ir-ast`` | no | ``--ir-ast-json``, ``--ir-optimized-ast-json`` | -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| EOF | ``eof`` | yes | ``--experimental-eof-version`` | -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| Non-mainnet EVMs | ``evm`` | yes | ``--evm-version `` | -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| Ethdebug | ``ethdebug`` | no | ``--ethdebug``, ``--ethdebug-runtime``, ``--debug-info ethdebug`` | -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ -| | | no | ``--yul-cfg-json`` | -| SSA CFG + ``ssa-cfg`` +------------------+-------------------------------------------------------------------+ -| | | yes | ``--via-ssa-cfg`` | -+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+ ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| Feature | ID | Affects bytecode | Flag/pragma | ++=======================+==========================+==================+=========================================================================================================================================+ +| AST import | ``ast-import`` | yes | ``--import-ast`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| LSP | ``lsp`` | no | ``--lsp`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| EVM Assembly import | ``evmasm-import`` | yes | ``--import-asm-json`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| Generic Solidity | ``generic-solidity`` | yes | ``pragma experimental solidity`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| IR AST | ``ir-ast`` | no | ``--ir-ast-json``, ``--ir-optimized-ast-json`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| EOF | ``eof`` | yes | ``--experimental-eof-version`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| Non-mainnet EVMs | ``evm`` | yes | ``--evm-version `` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| Ethdebug | ``ethdebug`` | no | ``--ethdebug-resources``, ``--ethdebug-compilation``, ``--ethdebug-program``, ``--ethdebug-program-runtime``, ``--debug-info ethdebug`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| | | no | ``--yul-cfg-json`` | +| SSA CFG + ``ssa-cfg`` +------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| | | yes | ``--via-ssa-cfg`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ From 32a5a84ae62e446c67772b33c624c62d6b8ebc65 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Fri, 17 Apr 2026 14:46:33 +0200 Subject: [PATCH 1248/1340] Changelog --- Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index adf89b3ac..5c1420ca3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,12 +6,14 @@ Language Features: Compiler Features: * Commandline Interface: Disallow selecting the deprecated assembly input mode that was only accessible via `--assemble` instead of treating it as equivalent to `--strict-assembly`. * Commandline Interface: Introduce `--experimental` flag required for enabling the experimental mode. +* Commandline Interface: Replace ``--ethdebug`` and ``--ethdebug-runtime`` with more granular ``--ethdebug-resources``, ``--ethdebug-compilation``, ``--ethdebug-program`` and ``--ethdebug-program-runtime`` flags. Per-contract program outputs no longer force full binary compilation. * EVM: Introduce experimental EVM version `@future`. * General: Introduce the SSA CFG codegen (experimental). * General: Improve performance of sanity checks throughout the compiler implementation. * General: Restrict the existing experimental features (`generic-solidity`, `lsp`, `ethdebug`, `eof`, `evm`, `ast-import`, `evmasm-import`, `ir-ast`, `ssa-cfg`) to experimental mode. * Metadata: Store the state of the experimental mode in JSON and CBOR metadata. In CBOR this broadens the meaning of the existing `experimental` field, which used to indicate only the presence of certain experimental pragmas in the source. * Standard JSON Interface: Introduce `settings.experimental` setting required for enabling the experimental mode. +* Standard JSON Interface: Replace the top-level ``ethdebug`` output with ``ethdebug.resources`` and ``ethdebug.compilation``. Decouple ethdebug outputs from binary compilation so that global ethdebug outputs can be produced without generating bytecode. * Yul Optimizer: Improve performance of control flow side effects collector and function references resolver. Bugfixes: From b898e0cda85de01d5bbcff9f75f4eaa5c4beca8b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Sat, 18 Apr 2026 09:18:17 +0200 Subject: [PATCH 1249/1340] ssa shuffler: add tests where the stack has to grow by one by pulling something out of tail --- .../ssa/stackShuffler/stack_top_is_junk.stack | 41 +++++++++++++++++++ .../ssa/stackShuffler/stack_top_is_lit.stack | 18 ++++++++ .../ssa/stackShuffler/stack_top_is_var.stack | 18 ++++++++ 3 files changed, 77 insertions(+) create mode 100644 test/libyul/ssa/stackShuffler/stack_top_is_junk.stack create mode 100644 test/libyul/ssa/stackShuffler/stack_top_is_lit.stack create mode 100644 test/libyul/ssa/stackShuffler/stack_top_is_var.stack diff --git a/test/libyul/ssa/stackShuffler/stack_top_is_junk.stack b/test/libyul/ssa/stackShuffler/stack_top_is_junk.stack new file mode 100644 index 000000000..6daa90dad --- /dev/null +++ b/test/libyul/ssa/stackShuffler/stack_top_is_junk.stack @@ -0,0 +1,41 @@ +initial: [JUNK, JUNK, v0, v0, lit0, v0, lit0, v0, v0, v0, lit0, v0, v0, v0, lit0, v0, lit0, lit0, v0] +targetStackTop: [JUNK, lit0, v0, lit0, v0, JUNK, v0, lit0, JUNK, v0, v0, lit0, v0, JUNK, lit0, v0, JUNK] +targetStackTailSet: {v0} +targetStackSize: 20 +// ---- +// | 0 1 2 | 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +// +--------------------- +----------------------------------------------------------------------------------------------------------------------- +// (initial)| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 +// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 +// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 +// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 +// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 +// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 +// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 +// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 +// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// ...| +// +--------------------- +----------------------------------------------------------------------------------------------------------------------- +// (target)| {v0} | * lit0 v0 lit0 v0 * v0 lit0 * v0 v0 lit0 v0 * lit0 v0 * +// Status: MaxIterationsReached diff --git a/test/libyul/ssa/stackShuffler/stack_top_is_lit.stack b/test/libyul/ssa/stackShuffler/stack_top_is_lit.stack new file mode 100644 index 000000000..8b2301612 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/stack_top_is_lit.stack @@ -0,0 +1,18 @@ +initial: [lit1, lit1, v0, v0, lit0, v0, lit0, v0, v0, v0, lit0, v0, v0, v0, lit0, v0, lit0, lit0, v0] +targetStackTop: [JUNK, lit0, v0, lit0, v0, JUNK, v0, lit0, JUNK, v0, v0, lit0, v0, JUNK, lit0, v0, lit1] +targetStackTailSet: {v0} +targetStackSize: 20 +// ---- +// | 0 1 2 | 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +// +--------------------- +----------------------------------------------------------------------------------------------------------------------- +// (initial)| lit1 lit1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 +// SWAP1| lit1 lit1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// POP| lit1 lit1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 +// SWAP16| lit1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit1 +// DUP2| lit1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit1 lit0 +// SWAP1| lit1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 lit1 +// DUP4| lit1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 lit1 v0 +// SWAP1| lit1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 lit1 +// +--------------------- +----------------------------------------------------------------------------------------------------------------------- +// (target)| {v0} | * lit0 v0 lit0 v0 * v0 lit0 * v0 v0 lit0 v0 * lit0 v0 lit1 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/stack_top_is_var.stack b/test/libyul/ssa/stackShuffler/stack_top_is_var.stack new file mode 100644 index 000000000..597beabb9 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/stack_top_is_var.stack @@ -0,0 +1,18 @@ +initial: [v1, v1, v0, v0, lit0, v0, lit0, v0, v0, v0, lit0, v0, v0, v0, lit0, v0, lit0, lit0, v0] +targetStackTop: [JUNK, lit0, v0, lit0, v0, JUNK, v0, lit0, JUNK, v0, v0, lit0, v0, JUNK, lit0, v0, v1] +targetStackTailSet: {v0} +targetStackSize: 20 +// ---- +// | 0 1 2 | 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +// +--------------------- +----------------------------------------------------------------------------------------------------------------------- +// (initial)| v1 v1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 +// SWAP1| v1 v1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 +// POP| v1 v1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 +// SWAP16| v1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v1 +// DUP2| v1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v1 lit0 +// SWAP1| v1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v1 +// DUP4| v1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v1 v0 +// SWAP1| v1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 v1 +// +--------------------- +----------------------------------------------------------------------------------------------------------------------- +// (target)| {v0} | * lit0 v0 lit0 v0 * v0 lit0 * v0 v0 lit0 v0 * lit0 v0 v1 +// Status: Admissible From d0192f4cd0ceba166f8cb66035cb8a4a7947f733 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Sat, 18 Apr 2026 09:21:55 +0200 Subject: [PATCH 1250/1340] ssa shuffler: allNecessarySlotsReachableOrFinal ignores junk in target args --- libyul/backends/evm/ssa/StackShuffler.h | 10 ++++-- .../ssa/stackShuffler/stack_top_is_junk.stack | 33 ++----------------- 2 files changed, 10 insertions(+), 33 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 5e88c700c..9d75f8775 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -807,12 +807,18 @@ class StackShuffler { if (_state.isArgsCompatible(offset, offset)) continue; + + auto const& targetArg = _state.targetArg(offset); + // if the target arg is junk, we can simply push0 and it's fine + if (targetArg.isJunk()) + continue; + // find first occurrence of the slot - std::optional depth = _stack.findSlotDepth(_state.targetArg(offset)); + std::optional const depth = _stack.findSlotDepth(targetArg); if (!depth) { // if there is no occurrence of the slot anywhere, we must be able to freely generate it - yulAssert(_stack.canBeFreelyGenerated(_state.targetArg(offset))); + yulAssert(_stack.canBeFreelyGenerated(targetArg)); } else { diff --git a/test/libyul/ssa/stackShuffler/stack_top_is_junk.stack b/test/libyul/ssa/stackShuffler/stack_top_is_junk.stack index 6daa90dad..143c5c827 100644 --- a/test/libyul/ssa/stackShuffler/stack_top_is_junk.stack +++ b/test/libyul/ssa/stackShuffler/stack_top_is_junk.stack @@ -6,36 +6,7 @@ targetStackSize: 20 // | 0 1 2 | 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // +--------------------- +----------------------------------------------------------------------------------------------------------------------- // (initial)| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 -// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 -// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 -// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 -// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 -// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 -// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// POP| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 -// DUP2| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 -// SWAP1| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0 -// ...| +// PUSH JUNK| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 * // +--------------------- +----------------------------------------------------------------------------------------------------------------------- // (target)| {v0} | * lit0 v0 lit0 v0 * v0 lit0 * v0 v0 lit0 v0 * lit0 v0 * -// Status: MaxIterationsReached +// Status: Admissible From d06a8705325f2505fee03925e17ead720734c03b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 20 Apr 2026 09:32:25 +0200 Subject: [PATCH 1251/1340] ssa cfg shuffler: refactor `shrinkStack` to use priority score --- libyul/backends/evm/ssa/StackShuffler.h | 69 ++++++++++++------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index e80f92c71..fea6d00bf 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -754,49 +754,46 @@ class StackShuffler } } } - // pop junk (but not if JUNK is exactly what's needed at that position) - for (StackOffset offset: _state.stackSwapReachableRange()) - if (_stack[offset].isJunk() && !_state.isArgsCompatible(offset, offset)) - { - if (offset != stackTop && _stack[offset] != _stack[stackTop]) - _stack.swap(offset); - _stack.pop(); - return true; - } - // pop something that can be freely generated except for literals - // (but not if it's already in a compatible position) - for (StackOffset offset: _state.stackSwapReachableRange()) - if ( - _stack.canBeFreelyGenerated(_stack[offset]) && - !_stack[offset].isLiteralValueID() && - !_state.isArgsCompatible(offset, offset) - ) + { + auto const shrinkPriority = [&](StackOffset const _offset) -> std::uint32_t { - if (offset != stackTop && _stack[offset] != _stack[stackTop]) - _stack.swap(offset); - _stack.pop(); - return true; - } + auto const& slot = _stack[_offset]; + bool const notInPosition = !_state.isArgsCompatible(_offset, _offset); + bool const isJunk = slot.isJunk(); + bool const hasSurplus = _state.count(slot) > _state.targetMinCount(slot); + bool const canBeFreelyGenerated = _stack.canBeFreelyGenerated(slot); + bool const isLit = slot.isLiteralValueID(); + + if (isJunk && notInPosition) + return 4; + if (canBeFreelyGenerated && !isLit && notInPosition) + return 3; + if (hasSurplus) + return 2; + if (canBeFreelyGenerated) + return 1; + return 0; + }; + std::optional slotToPop{std::nullopt}; + std::uint32_t bestScore = 0; + for (StackOffset offset: _state.stackSwapReachableRange()) + if (std::uint32_t const score = shrinkPriority(offset); score > bestScore) + { + bestScore = score; + slotToPop = offset; + } - // pop anything that isn't in position and we have more than one of - for (StackOffset offset: _state.stackSwapReachableRange()) - if (_state.count(_stack[offset]) > _state.targetMinCount(_stack[offset])) + if (slotToPop) { - if (offset != stackTop && _stack[offset] != _stack[stackTop]) - _stack.swap(offset); - _stack.pop(); - return true; - } - // pop anything that can be freely generated - for (StackOffset offset: _state.stackSwapReachableRange()) - if (_stack.canBeFreelyGenerated(_stack[offset])) - { - if (offset != stackTop && _stack[offset] != _stack[stackTop]) - _stack.swap(offset); + if (*slotToPop != stackTop && _stack[*slotToPop] != _stack[stackTop]) + _stack.swap(*slotToPop); _stack.pop(); return true; } + + } + return false; } From 0a50dbe25731e2ee0d95ebed731e65681ce7f1e7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 20 Apr 2026 08:40:56 +0200 Subject: [PATCH 1252/1340] SSA CFG: Add shuffler test that runs into stack too deep although it should not --- .../ssa/stackShuffler/shrink_stack_to_reach_var.stack | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack diff --git a/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack new file mode 100644 index 000000000..53e8918ae --- /dev/null +++ b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack @@ -0,0 +1,10 @@ +initial: [v1, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0] +targetStackTop: [v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v1] +targetStackSize: 20 +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (initial)| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (target)| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v1 +// Status: StackTooDeep (culprit: v1) From 852b3aeaf4b7d3cfef139e9da70d5a3c536fdbb6 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 20 Apr 2026 10:13:41 +0200 Subject: [PATCH 1253/1340] ssa cfg shuffler: extend `shrinkStack` capabilities by allowing to pop reachable duplicates as last resort --- libyul/backends/evm/ssa/StackShuffler.h | 9 ++++-- .../shrink_stack_to_reach_var.stack | 32 ++++++++++++++++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index fea6d00bf..b64e186e9 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -762,16 +762,19 @@ class StackShuffler bool const notInPosition = !_state.isArgsCompatible(_offset, _offset); bool const isJunk = slot.isJunk(); bool const hasSurplus = _state.count(slot) > _state.targetMinCount(slot); + bool const hasReachableDuplicate = _state.countReachable(slot) > 1; bool const canBeFreelyGenerated = _stack.canBeFreelyGenerated(slot); bool const isLit = slot.isLiteralValueID(); if (isJunk && notInPosition) - return 4; + return 5; if (canBeFreelyGenerated && !isLit && notInPosition) - return 3; + return 4; if (hasSurplus) - return 2; + return 3; if (canBeFreelyGenerated) + return 2; + if (hasReachableDuplicate) return 1; return 0; }; diff --git a/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack index 53e8918ae..960d40827 100644 --- a/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack +++ b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack @@ -5,6 +5,36 @@ targetStackSize: 20 // | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // +-------------------------------------------------------------------------------------------------------------------------------------------- // (initial)| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// ...| // +-------------------------------------------------------------------------------------------------------------------------------------------- // (target)| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v1 -// Status: StackTooDeep (culprit: v1) +// Status: MaxIterationsReached From 988c3d2c65d6949552c02ba5442d59a8b0fdb7d6 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:07:38 +0200 Subject: [PATCH 1254/1340] ssa cfg shuffler: add special case to fixArgsSlot that can move an already fixed slot out of position to fix a deeper position in args --- libyul/backends/evm/ssa/StackShuffler.h | 36 +++++++++++++++-- .../shrink_stack_to_reach_junk.stack | 40 +++++++++++++++++++ .../shrink_stack_to_reach_lit.stack | 18 +++++++++ .../shrink_stack_to_reach_var.stack | 34 +++------------- 4 files changed, 97 insertions(+), 31 deletions(-) create mode 100644 test/libyul/ssa/stackShuffler/shrink_stack_to_reach_junk.stack create mode 100644 test/libyul/ssa/stackShuffler/shrink_stack_to_reach_lit.stack diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index b64e186e9..2f803c4f2 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -412,10 +412,10 @@ class StackShuffler if (_stack.size() < _state.target().tailSize) return {ShuffleHelperResult::Status::NoAction}; + StackOffset const stackTop{_stack.size() - 1}; // if we have at least one slot in the args section, try to fix something there if (_stack.size() > _state.target().tailSize) { - StackOffset const stackTop{_stack.size() - 1}; // if the stack top isn't where it likes to be right now, try to put it somewhere more sensible if (!_state.isArgsCompatible(stackTop, stackTop)) { @@ -484,7 +484,7 @@ class StackShuffler ) ) { - // for each `targetOffset` in target args, see if we can't swap the out of position `offset` to `targetOffset` + // for each `targetOffset` in stack args range, see if we can't swap the out of position `offset` to `targetOffset` for (StackOffset targetOffset: _state.stackArgsRange()) if ( targetOffset != offset && // we shouldn't be looking at the very same offset @@ -494,13 +494,43 @@ class StackShuffler ) { if (offset != stackTop) + { // swap up slot at offset - _stack.swap(offset); + _stack.swap(offset); + } // bring slot at offset into fixed position _stack.swap(targetOffset); return {ShuffleHelperResult::Status::StackModified}; } } + + if (!_state.targetArbitrary(offset) && _stack.isValidSwapTarget(offset)) + { + // for each `argOffset` in the stack args range, see if we can swap something into `offset`; reverse to prioritize shallow slots + for (StackOffset argOffset: _state.stackArgsRange() | ranges::views::reverse) + { + if ( + !_state.isSourceCompatible(offset, argOffset) && // we're not looking at the same thing + !_stack.isBeyondSwapRange(argOffset) && // the target offset should not be beyond reach + _state.isArgsCompatible(argOffset, offset) && // we can put argOffset -> offset + _state.countReachable(_stack[argOffset]) > 1 && // we still have another reachable copy so a subsequent dup is recoverable + ( // we only get a strict improvement if + !_state.isArgsCompatible(argOffset, argOffset) || // either the argOffset isn't in position anyway + _stack.offsetToDepth(offset).value == ReachableStackDepth // or offset is at the swap edge + ) + ) + { + if (argOffset != stackTop) + { + // swap up slot at offset + _stack.swap(argOffset); + } + // bring slot at offset into fixed position + _stack.swap(offset); + return {ShuffleHelperResult::Status::StackModified}; + } + } + } } } diff --git a/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_junk.stack b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_junk.stack new file mode 100644 index 000000000..727646dd4 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_junk.stack @@ -0,0 +1,40 @@ +initial: [JUNK, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0] +targetStackTop: [v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, JUNK] +targetStackSize: 20 +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (initial)| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// ...| +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (target)| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 * +// Status: MaxIterationsReached diff --git a/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_lit.stack b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_lit.stack new file mode 100644 index 000000000..a24b31c57 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_lit.stack @@ -0,0 +1,18 @@ +initial: [lit1, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0] +targetStackTop: [v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, v0, lit1] +targetStackSize: 20 +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (initial)| lit1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| lit1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| lit1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| lit1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// SWAP16| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 lit1 +// DUP2| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 lit1 v0 +// DUP1| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 lit1 v0 v0 +// DUP1| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 lit1 v0 v0 v0 +// SWAP3| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 lit1 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +// (target)| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 lit1 +// Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack index 960d40827..4f255c7e6 100644 --- a/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack +++ b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_var.stack @@ -8,33 +8,11 @@ targetStackSize: 20 // POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 // POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 // POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| v1 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// ...| +// SWAP16| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v1 +// DUP2| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v1 v0 +// DUP1| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v1 v0 v0 +// DUP1| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v1 v0 v0 v0 +// SWAP3| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v1 // +-------------------------------------------------------------------------------------------------------------------------------------------- // (target)| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v1 -// Status: MaxIterationsReached +// Status: Admissible From dc50cbef5ef63d107716ce614421f63711b58d3b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:18:02 +0200 Subject: [PATCH 1255/1340] ssa cfg shuffler: fix allNecessarySlotsReachableOrFinal to handle out of reach invalid slots --- libyul/backends/evm/ssa/StackShuffler.h | 4 ++ .../shrink_stack_to_reach_junk.stack | 38 ++++--------------- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 2f803c4f2..6ccb629cb 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -844,6 +844,10 @@ class StackShuffler if (targetArg.isJunk()) continue; + // the target offset itself is out of swap range, we must shrink to reach it + if (offset.value < _stack.size() && _stack.isBeyondSwapRange(offset)) + return offset; + // find first occurrence of the slot std::optional const depth = _stack.findSlotDepth(targetArg); if (!depth) diff --git a/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_junk.stack b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_junk.stack index 727646dd4..6b35c4199 100644 --- a/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_junk.stack +++ b/test/libyul/ssa/stackShuffler/shrink_stack_to_reach_junk.stack @@ -6,35 +6,13 @@ targetStackSize: 20 // +-------------------------------------------------------------------------------------------------------------------------------------------- // (initial)| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 // POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// DUP1| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 -// ...| +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// POP| * v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 +// SWAP16| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 * +// DUP2| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 * v0 +// DUP1| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 * v0 v0 +// DUP1| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 * v0 v0 v0 +// SWAP3| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 * // +-------------------------------------------------------------------------------------------------------------------------------------------- // (target)| v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 v0 * -// Status: MaxIterationsReached +// Status: Admissible From 34efa01ac11a108229958999297eac71ed051ed3 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 20 Apr 2026 11:08:53 +0200 Subject: [PATCH 1256/1340] Remove `annotation` variable. --- libsolidity/analysis/TypeChecker.cpp | 66 ++++++++++++++-------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index c613dd796..00fd0714a 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3098,10 +3098,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) Type const* exprType = type(_memberAccess.expression()); ASTString const& memberName = _memberAccess.memberName(); - auto& annotation = _memberAccess.annotation(); - // Retrieve the types of the arguments if this is used to call a function. - auto const& arguments = annotation.arguments; + auto const& arguments = _memberAccess.annotation().arguments; MemberList::MemberMap possibleMembers = exprType->members(currentDefinitionScope()).membersByName(memberName); size_t const initialMemberCount = possibleMembers.size(); if (initialMemberCount > 1 && arguments) @@ -3117,7 +3115,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) ++it; } - annotation.isConstant = false; + _memberAccess.annotation().isConstant = false; if (possibleMembers.empty()) { @@ -3212,12 +3210,12 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) (memberName == "value" ? " - did you forget the \"payable\" modifier?" : ".") ); - annotation.referencedDeclaration = possibleMembers.front().declaration; - annotation.type = possibleMembers.front().type; + _memberAccess.annotation().referencedDeclaration = possibleMembers.front().declaration; + _memberAccess.annotation().type = possibleMembers.front().type; VirtualLookup requiredLookup = VirtualLookup::Static; - if (auto funType = dynamic_cast(annotation.type)) + if (auto funType = dynamic_cast(_memberAccess.annotation().type)) { solAssert( !funType->hasBoundFirstArgument() || exprType->isImplicitlyConvertibleTo(*funType->selfType()), @@ -3227,7 +3225,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if ( dynamic_cast(exprType) && - !annotation.referencedDeclaration && + !_memberAccess.annotation().referencedDeclaration && (memberName == "value" || memberName == "gas") ) m_errorReporter.typeError( @@ -3269,36 +3267,36 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) ); } - annotation.requiredLookup = requiredLookup; + _memberAccess.annotation().requiredLookup = requiredLookup; if (auto const* structType = dynamic_cast(exprType)) - annotation.isLValue = !structType->dataStoredIn(DataLocation::CallData); + _memberAccess.annotation().isLValue = !structType->dataStoredIn(DataLocation::CallData); else if (exprType->category() == Type::Category::Array) - annotation.isLValue = false; + _memberAccess.annotation().isLValue = false; else if (exprType->category() == Type::Category::FixedBytes) - annotation.isLValue = false; + _memberAccess.annotation().isLValue = false; else if (TypeType const* typeType = dynamic_cast(exprType)) { if (ContractType const* contractType = dynamic_cast(typeType->actualType())) { - annotation.isLValue = annotation.referencedDeclaration->isLValue(); + _memberAccess.annotation().isLValue = _memberAccess.annotation().referencedDeclaration->isLValue(); if ( - auto const* functionType = dynamic_cast(annotation.type); + auto const* functionType = dynamic_cast(_memberAccess.annotation().type); functionType && functionType->kind() == FunctionType::Kind::Declaration ) - annotation.isPure = *_memberAccess.expression().annotation().isPure; + _memberAccess.annotation().isPure = *_memberAccess.expression().annotation().isPure; } else - annotation.isLValue = false; + _memberAccess.annotation().isLValue = false; } else if (exprType->category() == Type::Category::Module) { - annotation.isPure = *_memberAccess.expression().annotation().isPure; - annotation.isLValue = false; + _memberAccess.annotation().isPure = *_memberAccess.expression().annotation().isPure; + _memberAccess.annotation().isLValue = false; } else - annotation.isLValue = false; + _memberAccess.annotation().isLValue = false; // TODO some members might be pure, but for example `address(0x123).balance` is not pure // although every subexpression is, so leaving this limited for now. @@ -3308,21 +3306,21 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) tt->actualType()->category() == Type::Category::Enum || tt->actualType()->category() == Type::Category::UserDefinedValueType ) - annotation.isPure = true; + _memberAccess.annotation().isPure = true; // `concat` purity depends also on its arguments, but this is checked later, in visit(FunctionCall...) // This covers `bytes.concat` and `string.concat`. if (tt->actualType()->category() == Type::Category::Array) { if ( - auto const* funcType = dynamic_cast(annotation.type); + auto const* funcType = dynamic_cast(_memberAccess.annotation().type); funcType && ( funcType->kind() == FunctionType::Kind::StringConcat || funcType->kind() == FunctionType::Kind::BytesConcat ) ) - annotation.isPure = true; + _memberAccess.annotation().isPure = true; } } if ( @@ -3342,7 +3340,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if (exprInt->name() == "this" || exprInt->name() == "super") isPure = true; - annotation.isPure = isPure; + _memberAccess.annotation().isPure = isPure; } } // In case of event or error definition the selector is always compile-time constant, as it can be @@ -3351,26 +3349,26 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) dynamic_cast(&functionType->declaration()) || dynamic_cast(&functionType->declaration()) ) - annotation.isPure = true; + _memberAccess.annotation().isPure = true; } if ( - auto const* varDecl = dynamic_cast(annotation.referencedDeclaration); - !annotation.isPure.set() && + auto const* varDecl = dynamic_cast(_memberAccess.annotation().referencedDeclaration); + !_memberAccess.annotation().isPure.set() && varDecl && varDecl->isConstant() ) - annotation.isPure = true; + _memberAccess.annotation().isPure = true; if (auto magicType = dynamic_cast(exprType)) { if (magicType->kind() == MagicType::Kind::ABI) - annotation.isPure = true; + _memberAccess.annotation().isPure = true; else if (magicType->kind() == MagicType::Kind::MetaType && ( memberName == "creationCode" || memberName == "runtimeCode" )) { - annotation.isPure = true; + _memberAccess.annotation().isPure = true; ContractType const& accessedContractType = dynamic_cast(*magicType->typeArgument()); solAssert(!accessedContractType.isSuper(), ""); if ( @@ -3384,14 +3382,14 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) ); } else if (magicType->kind() == MagicType::Kind::MetaType && memberName == "name") - annotation.isPure = true; + _memberAccess.annotation().isPure = true; else if (magicType->kind() == MagicType::Kind::MetaType && memberName == "interfaceId") - annotation.isPure = true; + _memberAccess.annotation().isPure = true; else if ( magicType->kind() == MagicType::Kind::MetaType && (memberName == "min" || memberName == "max") ) - annotation.isPure = true; + _memberAccess.annotation().isPure = true; else if (magicType->kind() == MagicType::Kind::Block) { if (memberName == "chainid" && !m_evmVersion.hasChainID()) @@ -3438,8 +3436,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) "\"codehash\" is not supported by the VM version." ); - if (!annotation.isPure.set()) - annotation.isPure = false; + if (!_memberAccess.annotation().isPure.set()) + _memberAccess.annotation().isPure = false; return false; } From 331d4da9a394c04bca60a4a77aa0e165d1f31995 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 20 Apr 2026 11:09:41 +0200 Subject: [PATCH 1257/1340] Rename `exprType -> owningObjectType`. --- libsolidity/analysis/TypeChecker.cpp | 50 ++++++++++++++-------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 00fd0714a..20111d50e 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3095,12 +3095,12 @@ void TypeChecker::endVisit(NewExpression const& _newExpression) bool TypeChecker::visit(MemberAccess const& _memberAccess) { _memberAccess.expression().accept(*this); - Type const* exprType = type(_memberAccess.expression()); + Type const* owningObjectType = type(_memberAccess.expression()); ASTString const& memberName = _memberAccess.memberName(); // Retrieve the types of the arguments if this is used to call a function. auto const& arguments = _memberAccess.annotation().arguments; - MemberList::MemberMap possibleMembers = exprType->members(currentDefinitionScope()).membersByName(memberName); + MemberList::MemberMap possibleMembers = owningObjectType->members(currentDefinitionScope()).membersByName(memberName); size_t const initialMemberCount = possibleMembers.size(); if (initialMemberCount > 1 && arguments) { @@ -3108,7 +3108,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) for (auto it = possibleMembers.begin(); it != possibleMembers.end();) if ( it->type->category() == Type::Category::Function && - !dynamic_cast(*it->type).canTakeArguments(*arguments, exprType) + !dynamic_cast(*it->type).canTakeArguments(*arguments, owningObjectType) ) it = possibleMembers.erase(it); else @@ -3119,28 +3119,28 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if (possibleMembers.empty()) { - if (initialMemberCount == 0 && !dynamic_cast(exprType)) + if (initialMemberCount == 0 && !dynamic_cast(owningObjectType)) { // Try to see if the member was removed because it is only available for storage types. auto storageType = TypeProvider::withLocationIfReference( DataLocation::Storage, - exprType + owningObjectType ); if (!storageType->members(currentDefinitionScope()).membersByName(memberName).empty()) m_errorReporter.fatalTypeError( 4994_error, _memberAccess.location(), "Member \"" + memberName + "\" is not available in " + - exprType->humanReadableName() + + owningObjectType->humanReadableName() + " outside of storage." ); } auto [errorId, description] = [&]() -> std::tuple { std::string errorMsg = "Member \"" + memberName + "\" not found or not visible " - "after argument-dependent lookup in " + exprType->humanReadableName() + "."; + "after argument-dependent lookup in " + owningObjectType->humanReadableName() + "."; - if (auto const* funType = dynamic_cast(exprType)) + if (auto const* funType = dynamic_cast(owningObjectType)) { TypePointers const& t = funType->returnParameterTypes(); @@ -3167,7 +3167,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) ) return { 6005_error, errorMsg + " Did you intend to call the function?" }; } - else if (exprType->category() == Type::Category::Contract) + else if (owningObjectType->category() == Type::Category::Contract) { for (MemberList::Member const& addressMember: TypeProvider::payableAddress()->nativeMembers(nullptr)) if (addressMember.name == memberName) @@ -3178,7 +3178,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) return { 3125_error, errorMsg }; } } - else if (auto const* addressType = dynamic_cast(exprType)) + else if (auto const* addressType = dynamic_cast(owningObjectType)) { // Trigger error when using send or transfer with a non-payable fallback function. if (memberName == "send" || memberName == "transfer") @@ -3188,7 +3188,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) "Expected address not-payable as members were not found" ); - return { 9862_error, "\"send\" and \"transfer\" are only available for objects of type \"address payable\", not \"" + exprType->humanReadableName() + "\"." }; + return { 9862_error, "\"send\" and \"transfer\" are only available for objects of type \"address payable\", not \"" + owningObjectType->humanReadableName() + "\"." }; } } @@ -3206,7 +3206,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) 6675_error, _memberAccess.location(), "Member \"" + memberName + "\" not unique " - "after argument-dependent lookup in " + exprType->humanReadableName() + + "after argument-dependent lookup in " + owningObjectType->humanReadableName() + (memberName == "value" ? " - did you forget the \"payable\" modifier?" : ".") ); @@ -3218,13 +3218,13 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if (auto funType = dynamic_cast(_memberAccess.annotation().type)) { solAssert( - !funType->hasBoundFirstArgument() || exprType->isImplicitlyConvertibleTo(*funType->selfType()), + !funType->hasBoundFirstArgument() || owningObjectType->isImplicitlyConvertibleTo(*funType->selfType()), "Function \"" + memberName + "\" cannot be called on an object of type " + - exprType->humanReadableName() + " (expected " + funType->selfType()->humanReadableName() + ")." + owningObjectType->humanReadableName() + " (expected " + funType->selfType()->humanReadableName() + ")." ); if ( - dynamic_cast(exprType) && + dynamic_cast(owningObjectType) && !_memberAccess.annotation().referencedDeclaration && (memberName == "value" || memberName == "gas") ) @@ -3237,7 +3237,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if ( funType->kind() == FunctionType::Kind::ArrayPush && arguments.value().numArguments() != 0 && - exprType->containsNestedMapping() + owningObjectType->containsNestedMapping() ) m_errorReporter.typeError( 8871_error, @@ -3246,7 +3246,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) ); if (!funType->hasBoundFirstArgument()) - if (auto typeType = dynamic_cast(exprType)) + if (auto typeType = dynamic_cast(owningObjectType)) { auto contractType = dynamic_cast(typeType->actualType()); if (contractType && contractType->isSuper()) @@ -3269,13 +3269,13 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) _memberAccess.annotation().requiredLookup = requiredLookup; - if (auto const* structType = dynamic_cast(exprType)) + if (auto const* structType = dynamic_cast(owningObjectType)) _memberAccess.annotation().isLValue = !structType->dataStoredIn(DataLocation::CallData); - else if (exprType->category() == Type::Category::Array) + else if (owningObjectType->category() == Type::Category::Array) _memberAccess.annotation().isLValue = false; - else if (exprType->category() == Type::Category::FixedBytes) + else if (owningObjectType->category() == Type::Category::FixedBytes) _memberAccess.annotation().isLValue = false; - else if (TypeType const* typeType = dynamic_cast(exprType)) + else if (TypeType const* typeType = dynamic_cast(owningObjectType)) { if (ContractType const* contractType = dynamic_cast(typeType->actualType())) { @@ -3290,7 +3290,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) else _memberAccess.annotation().isLValue = false; } - else if (exprType->category() == Type::Category::Module) + else if (owningObjectType->category() == Type::Category::Module) { _memberAccess.annotation().isPure = *_memberAccess.expression().annotation().isPure; _memberAccess.annotation().isLValue = false; @@ -3300,7 +3300,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) // TODO some members might be pure, but for example `address(0x123).balance` is not pure // although every subexpression is, so leaving this limited for now. - if (auto tt = dynamic_cast(exprType)) + if (auto tt = dynamic_cast(owningObjectType)) { if ( tt->actualType()->category() == Type::Category::Enum || @@ -3324,7 +3324,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) } } if ( - auto const* functionType = dynamic_cast(exprType); + auto const* functionType = dynamic_cast(owningObjectType); functionType && functionType->hasDeclaration() && memberName == "selector" @@ -3360,7 +3360,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) ) _memberAccess.annotation().isPure = true; - if (auto magicType = dynamic_cast(exprType)) + if (auto magicType = dynamic_cast(owningObjectType)) { if (magicType->kind() == MagicType::Kind::ABI) _memberAccess.annotation().isPure = true; From 18307c09000ace960cc20e9aa00de47b6ae20921 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 20 Apr 2026 11:10:20 +0200 Subject: [PATCH 1258/1340] Rename `initialMemberCount -> possibleMemberCountBeforeOverloading`. --- libsolidity/analysis/TypeChecker.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 20111d50e..413ca90b9 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3101,8 +3101,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) // Retrieve the types of the arguments if this is used to call a function. auto const& arguments = _memberAccess.annotation().arguments; MemberList::MemberMap possibleMembers = owningObjectType->members(currentDefinitionScope()).membersByName(memberName); - size_t const initialMemberCount = possibleMembers.size(); - if (initialMemberCount > 1 && arguments) + size_t const possibleMemberCountBeforeOverloading = possibleMembers.size(); + if (possibleMemberCountBeforeOverloading > 1 && arguments) { // do overload resolution for (auto it = possibleMembers.begin(); it != possibleMembers.end();) @@ -3119,7 +3119,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if (possibleMembers.empty()) { - if (initialMemberCount == 0 && !dynamic_cast(owningObjectType)) + if (possibleMemberCountBeforeOverloading == 0 && !dynamic_cast(owningObjectType)) { // Try to see if the member was removed because it is only available for storage types. auto storageType = TypeProvider::withLocationIfReference( From 77cbe1ddd20ba1b44294a6a19d5424a2b1f91051 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 20 Apr 2026 11:18:49 +0200 Subject: [PATCH 1259/1340] Change messages strings to raw strings. --- libsolidity/analysis/TypeChecker.cpp | 76 +++++++++++++++++++--------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 413ca90b9..7fa0aead9 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3130,15 +3130,21 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) m_errorReporter.fatalTypeError( 4994_error, _memberAccess.location(), - "Member \"" + memberName + "\" is not available in " + - owningObjectType->humanReadableName() + - " outside of storage." + + fmt::format( + R"(Member "{}" is not available in {} outside of storage.)", + memberName, + owningObjectType->humanReadableName() + ) ); } auto [errorId, description] = [&]() -> std::tuple { - std::string errorMsg = "Member \"" + memberName + "\" not found or not visible " - "after argument-dependent lookup in " + owningObjectType->humanReadableName() + "."; + std::string errorMsg = fmt::format( + R"(Member "{}" not found or not visible after argument-dependent lookup in {}.)", + memberName, + owningObjectType->humanReadableName() + ); if (auto const* funType = dynamic_cast(owningObjectType)) { @@ -3149,15 +3155,18 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if (funType->kind() == FunctionType::Kind::Creation) return { 8827_error, - "Constructor for " + t.front()->humanReadableName() + " must be payable for member \"value\" to be available." + fmt::format( + R"(Constructor for {} must be payable for member "value" to be available.)", + t.front()->humanReadableName() + ) }; else if ( funType->kind() == FunctionType::Kind::DelegateCall || funType->kind() == FunctionType::Kind::BareDelegateCall ) - return { 8477_error, "Member \"value\" is not allowed in delegated calls due to \"msg.value\" persisting." }; + return {8477_error, R"(Member "value" is not allowed in delegated calls due to "msg.value" persisting.)"}; else - return { 8820_error, "Member \"value\" is only available for payable functions." }; + return {8820_error, R"(Member "value" is only available for payable functions.)"}; } else if ( t.size() == 1 && ( @@ -3174,7 +3183,11 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) { auto const* var = dynamic_cast(&_memberAccess.expression()); std::string varName = var ? var->name() : "..."; - errorMsg += " Use \"address(" + varName + ")." + memberName + "\" to access this address member."; + errorMsg += fmt::format( + R"( Use "address({}).{}" to access this address member.)", + varName, + memberName + ); return { 3125_error, errorMsg }; } } @@ -3188,7 +3201,13 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) "Expected address not-payable as members were not found" ); - return { 9862_error, "\"send\" and \"transfer\" are only available for objects of type \"address payable\", not \"" + owningObjectType->humanReadableName() + "\"." }; + return { + 9862_error, + fmt::format( + R"("send" and "transfer" are only available for objects of type "address payable", not "{}".)", + owningObjectType->humanReadableName() + ) + }; } } @@ -3205,9 +3224,12 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) m_errorReporter.fatalTypeError( 6675_error, _memberAccess.location(), - "Member \"" + memberName + "\" not unique " - "after argument-dependent lookup in " + owningObjectType->humanReadableName() + - (memberName == "value" ? " - did you forget the \"payable\" modifier?" : ".") + fmt::format( + R"(Member "{}" not unique after argument-dependent lookup in {}{})", + memberName, + owningObjectType->humanReadableName(), + memberName == "value" ? R"( - did you forget the "payable" modifier?)" : "." + ) ); _memberAccess.annotation().referencedDeclaration = possibleMembers.front().declaration; @@ -3219,8 +3241,12 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) { solAssert( !funType->hasBoundFirstArgument() || owningObjectType->isImplicitlyConvertibleTo(*funType->selfType()), - "Function \"" + memberName + "\" cannot be called on an object of type " + - owningObjectType->humanReadableName() + " (expected " + funType->selfType()->humanReadableName() + ")." + fmt::format( + R"(Function "{}" cannot be called on an object of type {} (expected {}).)", + memberName, + owningObjectType->humanReadableName(), + funType->selfType()->humanReadableName() + ) ); if ( @@ -3231,7 +3257,11 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) m_errorReporter.typeError( 1621_error, _memberAccess.location(), - "Using \"." + memberName + "(...)\" is deprecated. Use \"{" + memberName + ": ...}\" instead." + fmt::format( + R"abc(Using ".{}(...)" is deprecated. Use "{{{}: ...}}" instead.)abc", + memberName, + memberName + ) ); if ( @@ -3378,7 +3408,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) m_errorReporter.typeError( 9274_error, _memberAccess.location(), - "\"runtimeCode\" is not available for contracts containing immutable variables." + R"("runtimeCode" is not available for contracts containing immutable variables.)" ); } else if (magicType->kind() == MagicType::Kind::MetaType && memberName == "name") @@ -3396,31 +3426,31 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) m_errorReporter.typeError( 3081_error, _memberAccess.location(), - "\"chainid\" is not supported by the VM version." + R"("chainid" is not supported by the VM version.)" ); else if (memberName == "basefee" && !m_evmVersion.hasBaseFee()) m_errorReporter.typeError( 5921_error, _memberAccess.location(), - "\"basefee\" is not supported by the VM version." + R"("basefee" is not supported by the VM version.)" ); else if (memberName == "blobbasefee" && !m_evmVersion.hasBlobBaseFee()) m_errorReporter.typeError( 1006_error, _memberAccess.location(), - "\"blobbasefee\" is not supported by the VM version." + R"("blobbasefee" is not supported by the VM version.)" ); else if (memberName == "prevrandao" && !m_evmVersion.hasPrevRandao()) m_errorReporter.warning( 9432_error, _memberAccess.location(), - "\"prevrandao\" is not supported by the VM version and will be treated as \"difficulty\"." + R"("prevrandao" is not supported by the VM version and will be treated as "difficulty".)" ); else if (memberName == "difficulty" && m_evmVersion.hasPrevRandao()) m_errorReporter.warning( 8417_error, _memberAccess.location(), - "Since the VM version paris, \"difficulty\" was replaced by \"prevrandao\", which now returns a random number based on the beacon chain." + R"(Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain.)" ); } } @@ -3433,7 +3463,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) m_errorReporter.typeError( 7598_error, _memberAccess.location(), - "\"codehash\" is not supported by the VM version." + R"("codehash" is not supported by the VM version.)" ); if (!_memberAccess.annotation().isPure.set()) From 697262fe91b5cef388672d809a935a262a10f294 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 20 Apr 2026 11:20:28 +0200 Subject: [PATCH 1260/1340] Remove unnecessary includes. --- libsolidity/analysis/TypeChecker.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 7fa0aead9..59019463b 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -36,10 +36,6 @@ #include #include #include -#include - -#include -#include #include From 42a81f985a7ffeaabddf1c76d88a5a75965a1f5a Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 20 Apr 2026 11:39:51 +0200 Subject: [PATCH 1261/1340] Extract self-contained code fragments to functions `resolveOverloads` and `diagnoseUnresolvedMemberAccess` --- libsolidity/analysis/TypeChecker.cpp | 237 +++++++++++++++------------ libsolidity/analysis/TypeChecker.h | 17 ++ 2 files changed, 145 insertions(+), 109 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 59019463b..46fa83964 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3088,9 +3088,8 @@ void TypeChecker::endVisit(NewExpression const& _newExpression) } } -bool TypeChecker::visit(MemberAccess const& _memberAccess) +MemberList::Member TypeChecker::resolveOverloads(MemberAccess const& _memberAccess) const { - _memberAccess.expression().accept(*this); Type const* owningObjectType = type(_memberAccess.expression()); ASTString const& memberName = _memberAccess.memberName(); @@ -3098,10 +3097,11 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) auto const& arguments = _memberAccess.annotation().arguments; MemberList::MemberMap possibleMembers = owningObjectType->members(currentDefinitionScope()).membersByName(memberName); size_t const possibleMemberCountBeforeOverloading = possibleMembers.size(); - if (possibleMemberCountBeforeOverloading > 1 && arguments) + if (possibleMemberCountBeforeOverloading >= 2 && arguments) { // do overload resolution for (auto it = possibleMembers.begin(); it != possibleMembers.end();) + { if ( it->type->category() == Type::Category::Function && !dynamic_cast(*it->type).canTakeArguments(*arguments, owningObjectType) @@ -3109,114 +3109,15 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) it = possibleMembers.erase(it); else ++it; + } } - _memberAccess.annotation().isConstant = false; - if (possibleMembers.empty()) { - if (possibleMemberCountBeforeOverloading == 0 && !dynamic_cast(owningObjectType)) - { - // Try to see if the member was removed because it is only available for storage types. - auto storageType = TypeProvider::withLocationIfReference( - DataLocation::Storage, - owningObjectType - ); - if (!storageType->members(currentDefinitionScope()).membersByName(memberName).empty()) - m_errorReporter.fatalTypeError( - 4994_error, - _memberAccess.location(), - - fmt::format( - R"(Member "{}" is not available in {} outside of storage.)", - memberName, - owningObjectType->humanReadableName() - ) - ); - } - - auto [errorId, description] = [&]() -> std::tuple { - std::string errorMsg = fmt::format( - R"(Member "{}" not found or not visible after argument-dependent lookup in {}.)", - memberName, - owningObjectType->humanReadableName() - ); - - if (auto const* funType = dynamic_cast(owningObjectType)) - { - TypePointers const& t = funType->returnParameterTypes(); - - if (memberName == "value") - { - if (funType->kind() == FunctionType::Kind::Creation) - return { - 8827_error, - fmt::format( - R"(Constructor for {} must be payable for member "value" to be available.)", - t.front()->humanReadableName() - ) - }; - else if ( - funType->kind() == FunctionType::Kind::DelegateCall || - funType->kind() == FunctionType::Kind::BareDelegateCall - ) - return {8477_error, R"(Member "value" is not allowed in delegated calls due to "msg.value" persisting.)"}; - else - return {8820_error, R"(Member "value" is only available for payable functions.)"}; - } - else if ( - t.size() == 1 && ( - t.front()->category() == Type::Category::Struct || - t.front()->category() == Type::Category::Contract - ) - ) - return { 6005_error, errorMsg + " Did you intend to call the function?" }; - } - else if (owningObjectType->category() == Type::Category::Contract) - { - for (MemberList::Member const& addressMember: TypeProvider::payableAddress()->nativeMembers(nullptr)) - if (addressMember.name == memberName) - { - auto const* var = dynamic_cast(&_memberAccess.expression()); - std::string varName = var ? var->name() : "..."; - errorMsg += fmt::format( - R"( Use "address({}).{}" to access this address member.)", - varName, - memberName - ); - return { 3125_error, errorMsg }; - } - } - else if (auto const* addressType = dynamic_cast(owningObjectType)) - { - // Trigger error when using send or transfer with a non-payable fallback function. - if (memberName == "send" || memberName == "transfer") - { - solAssert( - addressType->stateMutability() != StateMutability::Payable, - "Expected address not-payable as members were not found" - ); - - return { - 9862_error, - fmt::format( - R"("send" and "transfer" are only available for objects of type "address payable", not "{}".)", - owningObjectType->humanReadableName() - ) - }; - } - } - - return { 9582_error, errorMsg }; - }(); - - m_errorReporter.fatalTypeError( - errorId, - _memberAccess.location(), - description - ); + auto [errorID, errorMsg] = diagnoseUnresolvedMemberAccess(_memberAccess, possibleMemberCountBeforeOverloading); + m_errorReporter.fatalTypeError(errorID, _memberAccess.location(), errorMsg); } - else if (possibleMembers.size() > 1) + else if (possibleMembers.size() >= 2) m_errorReporter.fatalTypeError( 6675_error, _memberAccess.location(), @@ -3228,9 +3129,127 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) ) ); - _memberAccess.annotation().referencedDeclaration = possibleMembers.front().declaration; - _memberAccess.annotation().type = possibleMembers.front().type; + return possibleMembers.front(); +} + +std::pair TypeChecker::diagnoseUnresolvedMemberAccess( + MemberAccess const& _memberAccess, + size_t const _possibleMemberCountBeforeOverloading +) const +{ + Type const* owningObjectType = type(_memberAccess.expression()); + ASTString const& memberName = _memberAccess.memberName(); + + if (_possibleMemberCountBeforeOverloading == 0 && !dynamic_cast(owningObjectType)) + { + // Try to see if the member was removed because it is only available for storage types. + auto storageType = TypeProvider::withLocationIfReference( + DataLocation::Storage, + owningObjectType + ); + if (!storageType->members(currentDefinitionScope()).membersByName(memberName).empty()) + return { + 4994_error, + fmt::format( + R"(Member "{}" is not available in {} outside of storage.)", + memberName, + owningObjectType->humanReadableName() + ) + }; + } + + std::string errorMsg = fmt::format( + R"(Member "{}" not found or not visible after argument-dependent lookup in {}.)", + memberName, + owningObjectType->humanReadableName() + ); + + if (auto const* funType = dynamic_cast(owningObjectType)) + { + TypePointers const& t = funType->returnParameterTypes(); + + if (memberName == "value") + { + if (funType->kind() == FunctionType::Kind::Creation) + return { + 8827_error, + fmt::format( + R"(Constructor for {} must be payable for member "value" to be available.)", + t.front()->humanReadableName() + ) + }; + else if ( + funType->kind() == FunctionType::Kind::DelegateCall || + funType->kind() == FunctionType::Kind::BareDelegateCall + ) + return { + 8477_error, + R"(Member "value" is not allowed in delegated calls due to "msg.value" persisting.)" + }; + else + return {8820_error, R"(Member "value" is only available for payable functions.)"}; + } + else if ( + t.size() == 1 && ( + t.front()->category() == Type::Category::Struct || + t.front()->category() == Type::Category::Contract + ) + ) + return {6005_error, errorMsg + " Did you intend to call the function?"}; + } + else if (owningObjectType->category() == Type::Category::Contract) + { + for (MemberList::Member const& addressMember: TypeProvider::payableAddress()->nativeMembers(nullptr)) + if (addressMember.name == memberName) + { + auto const* var = dynamic_cast(&_memberAccess.expression()); + std::string varName = var ? var->name() : "..."; + errorMsg += fmt::format( + R"( Use "address({}).{}" to access this address member.)", + varName, + memberName + ); + return {3125_error, errorMsg}; + } + } + else if (auto const* addressType = dynamic_cast(owningObjectType)) + { + // Trigger error when using `send` or `transfer` with a non-payable fallback function. + if (memberName == "send" || memberName == "transfer") + { + solAssert( + addressType->stateMutability() != StateMutability::Payable, + "Expected address not-payable as members were not found" + ); + + return { + 9862_error, + fmt::format( + R"("send" and "transfer" are only available for objects of type "address payable", not "{}".)", + owningObjectType->humanReadableName() + ) + }; + } + } + + // If no detailed error were reported, issues a general unresolved member error. + return {9582_error, errorMsg}; +} + +bool TypeChecker::visit(MemberAccess const& _memberAccess) +{ + _memberAccess.expression().accept(*this); + Type const* owningObjectType = type(_memberAccess.expression()); + ASTString const& memberName = _memberAccess.memberName(); + + // TODO: This should be probably deprecated. + _memberAccess.annotation().isConstant = false; + MemberList::Member const possibleMember = resolveOverloads(_memberAccess); + + _memberAccess.annotation().referencedDeclaration = possibleMember.declaration; + _memberAccess.annotation().type = possibleMember.type; + // Lookup type required to find the function declaration. VirtualLookup requiredLookup = VirtualLookup::Static; if (auto funType = dynamic_cast(_memberAccess.annotation().type)) @@ -3262,7 +3281,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if ( funType->kind() == FunctionType::Kind::ArrayPush && - arguments.value().numArguments() != 0 && + _memberAccess.annotation().arguments.value().numArguments() != 0 && owningObjectType->containsNestedMapping() ) m_errorReporter.typeError( diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index de446b7d1..eb1696c83 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -191,6 +191,23 @@ class TypeChecker: private ASTConstVisitor return m_currentSourceUnit; } + // MemberAccess visitor helpers: + + /// Resolves overloaded functions by filtering out inapplicable candidates based on the provided arguments + /// and the type of the owning object. + /// Reports an error in case of ambiguity or failure to resolve. + MemberList::Member resolveOverloads(MemberAccess const& _memberAccess) const; + + /// Uses heuristics to determine the cause of unresolved member access and + /// produce a more specific and helpful error. + /// @param _memberAccess The member access expression where the unresolved member access occurred. + /// @param _possibleMemberCountBeforeOverloading The initial count of possible members before overloading resolution. + /// @returns error ID and error message. + std::pair diagnoseUnresolvedMemberAccess( + MemberAccess const& _memberAccess, + size_t _possibleMemberCountBeforeOverloading + ) const; + SourceUnit const* m_currentSourceUnit = nullptr; ContractDefinition const* m_currentContract = nullptr; From 1d47c3cab2a8332e4e176089fccebcdc105483e2 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 20 Apr 2026 11:44:16 +0200 Subject: [PATCH 1262/1340] Extract self-contained code fragments to function `checkAccessedMemberFunction` --- libsolidity/analysis/TypeChecker.cpp | 121 +++++++++++++++------------ libsolidity/analysis/TypeChecker.h | 6 ++ 2 files changed, 74 insertions(+), 53 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 46fa83964..82dda0bd6 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3236,6 +3236,67 @@ std::pair TypeChecker::diagnoseUnresolvedMemberAccess( return {9582_error, errorMsg}; } +void TypeChecker::checkAccessedMemberFunction(MemberAccess const& _memberAccess) const +{ + auto const* accessedMemberFunctionType = dynamic_cast(type(_memberAccess)); + solAssert(accessedMemberFunctionType, "Expected function type."); + + Type const* owningObjectType = type(_memberAccess.expression()); + solAssert(owningObjectType); + + auto const& memberName = _memberAccess.memberName(); + + solAssert( + !accessedMemberFunctionType->hasBoundFirstArgument() || + owningObjectType->isImplicitlyConvertibleTo(*accessedMemberFunctionType->selfType()), + fmt::format( + R"(Function "{}" cannot be called on an object of type {} (expected {}).)", + memberName, + owningObjectType->humanReadableName(), + accessedMemberFunctionType->selfType()->humanReadableName() + ) + ); + + if ( + dynamic_cast(owningObjectType) && + _memberAccess.annotation().referencedDeclaration == nullptr && // It's not defined + (memberName == "value" || memberName == "gas") + ) + m_errorReporter.typeError( + 1621_error, + _memberAccess.location(), + fmt::format( + R"abc(Using ".{}(...)" is deprecated. Use "{{{}: ...}}" instead.)abc", + memberName, + memberName + ) + ); + + if ( + accessedMemberFunctionType->kind() == FunctionType::Kind::ArrayPush && + _memberAccess.annotation().arguments.value().numArguments() > 0 && + owningObjectType->containsNestedMapping() + ) + m_errorReporter.typeError( + 8871_error, + _memberAccess.location(), + "Storage arrays with nested mappings do not support .push()." + ); + + if ( + accessedMemberFunctionType->kind() == FunctionType::Kind::Send || + accessedMemberFunctionType->kind() == FunctionType::Kind::Transfer + ) + m_errorReporter.warning( + 9207_error, + _memberAccess.location(), + fmt::format( + R"('{}' is deprecated and scheduled for removal. Use 'call{{value: }}("")' instead.)", + accessedMemberFunctionType->kind() == FunctionType::Kind::Send ? "send" : "transfer" + ) + ); +} + bool TypeChecker::visit(MemberAccess const& _memberAccess) { _memberAccess.expression().accept(*this); @@ -3252,64 +3313,18 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) // Lookup type required to find the function declaration. VirtualLookup requiredLookup = VirtualLookup::Static; - if (auto funType = dynamic_cast(_memberAccess.annotation().type)) + if (auto const* accessedMemberFunctionType = dynamic_cast(type(_memberAccess))) { - solAssert( - !funType->hasBoundFirstArgument() || owningObjectType->isImplicitlyConvertibleTo(*funType->selfType()), - fmt::format( - R"(Function "{}" cannot be called on an object of type {} (expected {}).)", - memberName, - owningObjectType->humanReadableName(), - funType->selfType()->humanReadableName() - ) - ); - - if ( - dynamic_cast(owningObjectType) && - !_memberAccess.annotation().referencedDeclaration && - (memberName == "value" || memberName == "gas") - ) - m_errorReporter.typeError( - 1621_error, - _memberAccess.location(), - fmt::format( - R"abc(Using ".{}(...)" is deprecated. Use "{{{}: ...}}" instead.)abc", - memberName, - memberName - ) - ); - - if ( - funType->kind() == FunctionType::Kind::ArrayPush && - _memberAccess.annotation().arguments.value().numArguments() != 0 && - owningObjectType->containsNestedMapping() - ) - m_errorReporter.typeError( - 8871_error, - _memberAccess.location(), - "Storage arrays with nested mappings do not support .push()." - ); - - if (!funType->hasBoundFirstArgument()) - if (auto typeType = dynamic_cast(owningObjectType)) + // Update required lookup + if (!accessedMemberFunctionType->hasBoundFirstArgument()) + if (auto const* owningObjectTypeType = dynamic_cast(owningObjectType)) { - auto contractType = dynamic_cast(typeType->actualType()); - if (contractType && contractType->isSuper()) + auto const* owningObjectContractType = dynamic_cast(owningObjectTypeType->actualType()); + if (owningObjectContractType && owningObjectContractType->isSuper()) requiredLookup = VirtualLookup::Super; } - if ( - funType->kind() == FunctionType::Kind::Send || - funType->kind() == FunctionType::Kind::Transfer - ) - m_errorReporter.warning( - 9207_error, - _memberAccess.location(), - fmt::format( - "'{}' is deprecated and scheduled for removal. Use 'call{{value: }}(\"\")' instead.", - funType->kind() == FunctionType::Kind::Send ? "send" : "transfer" - ) - ); + checkAccessedMemberFunction(_memberAccess); } _memberAccess.annotation().requiredLookup = requiredLookup; diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index eb1696c83..34961ab34 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -208,6 +208,12 @@ class TypeChecker: private ASTConstVisitor size_t _possibleMemberCountBeforeOverloading ) const; + /// Validates access to a member function of a given type, ensuring that the invocation + /// is consistent with the expected types and semantics. Reports errors and warnings + /// for invalid access, use of deprecated features, and unsupported operations. + /// @param _memberAccess Member access expression. + void checkAccessedMemberFunction(MemberAccess const& _memberAccess) const; + SourceUnit const* m_currentSourceUnit = nullptr; ContractDefinition const* m_currentContract = nullptr; From e903693b3723573e29eac45b6a9e245a26e0b535 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 20 Apr 2026 14:18:22 +0200 Subject: [PATCH 1263/1340] Reorg owning object type category handling into switch statement. --- libsolidity/analysis/TypeChecker.cpp | 285 ++++++++++++++++----------- 1 file changed, 174 insertions(+), 111 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 82dda0bd6..25bd4a915 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3329,128 +3329,116 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) _memberAccess.annotation().requiredLookup = requiredLookup; - if (auto const* structType = dynamic_cast(owningObjectType)) - _memberAccess.annotation().isLValue = !structType->dataStoredIn(DataLocation::CallData); - else if (owningObjectType->category() == Type::Category::Array) - _memberAccess.annotation().isLValue = false; - else if (owningObjectType->category() == Type::Category::FixedBytes) - _memberAccess.annotation().isLValue = false; - else if (TypeType const* typeType = dynamic_cast(owningObjectType)) + switch (owningObjectType->category()) { - if (ContractType const* contractType = dynamic_cast(typeType->actualType())) - { - _memberAccess.annotation().isLValue = _memberAccess.annotation().referencedDeclaration->isLValue(); - if ( - auto const* functionType = dynamic_cast(_memberAccess.annotation().type); - functionType && - functionType->kind() == FunctionType::Kind::Declaration - ) - _memberAccess.annotation().isPure = *_memberAccess.expression().annotation().isPure; - } - else - _memberAccess.annotation().isLValue = false; - } - else if (owningObjectType->category() == Type::Category::Module) + case Type::Category::Struct: { - _memberAccess.annotation().isPure = *_memberAccess.expression().annotation().isPure; - _memberAccess.annotation().isLValue = false; + auto const* owningObjectStructType = dynamic_cast(owningObjectType); + solAssert(owningObjectStructType); + _memberAccess.annotation().isLValue = !owningObjectStructType->dataStoredIn(DataLocation::CallData); + break; } - else - _memberAccess.annotation().isLValue = false; - - // TODO some members might be pure, but for example `address(0x123).balance` is not pure - // although every subexpression is, so leaving this limited for now. - if (auto tt = dynamic_cast(owningObjectType)) + case Type::Category::Function: { - if ( - tt->actualType()->category() == Type::Category::Enum || - tt->actualType()->category() == Type::Category::UserDefinedValueType - ) - _memberAccess.annotation().isPure = true; + auto const* owningObjectFunctionType = dynamic_cast(owningObjectType); + solAssert(owningObjectFunctionType); - // `concat` purity depends also on its arguments, but this is checked later, in visit(FunctionCall...) - // This covers `bytes.concat` and `string.concat`. - if (tt->actualType()->category() == Type::Category::Array) - { - if ( - auto const* funcType = dynamic_cast(_memberAccess.annotation().type); - funcType && - ( - funcType->kind() == FunctionType::Kind::StringConcat || - funcType->kind() == FunctionType::Kind::BytesConcat - ) - ) - _memberAccess.annotation().isPure = true; - } - } - if ( - auto const* functionType = dynamic_cast(owningObjectType); - functionType && - functionType->hasDeclaration() && - memberName == "selector" - ) - { - if (dynamic_cast(&functionType->declaration())) + if (owningObjectFunctionType->hasDeclaration() && memberName == "selector") { - if (auto const* parentAccess = dynamic_cast(&_memberAccess.expression())) + if (dynamic_cast(&owningObjectFunctionType->declaration())) { - bool isPure = *parentAccess->expression().annotation().isPure; - // Accessing a function selector using `super|this.f.selector`. - if (auto const* exprInt = dynamic_cast(&parentAccess->expression())) - if (exprInt->name() == "this" || exprInt->name() == "super") - isPure = true; + if (auto const* parentMemberAccess = dynamic_cast(&_memberAccess.expression())) + { + bool isPure = *parentMemberAccess->expression().annotation().isPure; + // Accessing a function selector using `super|this.f.selector`. + if (auto const* exprInt = dynamic_cast(&parentMemberAccess->expression())) + if (exprInt->name() == "this" || exprInt->name() == "super") + isPure = true; - _memberAccess.annotation().isPure = isPure; + _memberAccess.annotation().isPure = isPure; + } } + // In case of event or error definition, the selector is always compile-time constant, as it can be + // a keccak256 hash of the event signature or a function selector in case of an error. + else if ( + dynamic_cast(&owningObjectFunctionType->declaration()) || + dynamic_cast(&owningObjectFunctionType->declaration()) + ) + _memberAccess.annotation().isPure = true; } - // In case of event or error definition the selector is always compile-time constant, as it can be - // a keccak256 hash of the event signature or a function selector in case of an error. - else if ( - dynamic_cast(&functionType->declaration()) || - dynamic_cast(&functionType->declaration()) - ) - _memberAccess.annotation().isPure = true; + + _memberAccess.annotation().isLValue = false; + break; } + case Type::Category::TypeType: + { + // TODO some members might be pure, but for example `address(0x123).balance` is not pure + // although every subexpression is, so leaving this limited for now. + auto const* owningObjectTypeType = dynamic_cast(owningObjectType); + solAssert(owningObjectTypeType); - if ( - auto const* varDecl = dynamic_cast(_memberAccess.annotation().referencedDeclaration); - !_memberAccess.annotation().isPure.set() && - varDecl && - varDecl->isConstant() - ) - _memberAccess.annotation().isPure = true; + switch (owningObjectTypeType->actualType()->category()) + { + case Type::Category::Array: + { + // `concat` purity depends also on its arguments, but this is checked later, in visit(FunctionCall...) + // This covers `bytes.concat` and `string.concat`. + auto const* accessedMemberFunctionType = dynamic_cast(type(_memberAccess)); + solAssert(accessedMemberFunctionType && ( + accessedMemberFunctionType->kind() == FunctionType::Kind::StringConcat || + accessedMemberFunctionType->kind() == FunctionType::Kind::BytesConcat + )); - if (auto magicType = dynamic_cast(owningObjectType)) - { - if (magicType->kind() == MagicType::Kind::ABI) _memberAccess.annotation().isPure = true; - else if (magicType->kind() == MagicType::Kind::MetaType && ( - memberName == "creationCode" || memberName == "runtimeCode" - )) + _memberAccess.annotation().isLValue = false; + break; + } + case Type::Category::Contract: { - _memberAccess.annotation().isPure = true; - ContractType const& accessedContractType = dynamic_cast(*magicType->typeArgument()); - solAssert(!accessedContractType.isSuper(), ""); + _memberAccess.annotation().isLValue = _memberAccess.annotation().referencedDeclaration->isLValue(); if ( - memberName == "runtimeCode" && - !accessedContractType.immutableVariables().empty() + auto const* accessedMemberFunctionType = dynamic_cast(type(_memberAccess)); + accessedMemberFunctionType && + accessedMemberFunctionType->kind() == FunctionType::Kind::Declaration ) - m_errorReporter.typeError( - 9274_error, - _memberAccess.location(), - R"("runtimeCode" is not available for contracts containing immutable variables.)" - ); + _memberAccess.annotation().isPure = *_memberAccess.expression().annotation().isPure; + break; } - else if (magicType->kind() == MagicType::Kind::MetaType && memberName == "name") - _memberAccess.annotation().isPure = true; - else if (magicType->kind() == MagicType::Kind::MetaType && memberName == "interfaceId") + case Type::Category::Enum: + case Type::Category::UserDefinedValueType: _memberAccess.annotation().isPure = true; - else if ( - magicType->kind() == MagicType::Kind::MetaType && - (memberName == "min" || memberName == "max") - ) - _memberAccess.annotation().isPure = true; - else if (magicType->kind() == MagicType::Kind::Block) + _memberAccess.annotation().isLValue = false; + break; + case Type::Category::Address: + case Type::Category::Integer: + case Type::Category::RationalNumber: + case Type::Category::StringLiteral: + case Type::Category::Bool: + case Type::Category::FixedPoint: + case Type::Category::ArraySlice: + case Type::Category::FixedBytes: + case Type::Category::Struct: + case Type::Category::Function: + case Type::Category::Tuple: + case Type::Category::Mapping: + case Type::Category::TypeType: + case Type::Category::Modifier: + case Type::Category::Magic: + case Type::Category::Module: + case Type::Category::InaccessibleDynamic: + _memberAccess.annotation().isLValue = false; + break; + } + break; + } + case Type::Category::Magic: + { + auto const* owningObjectMagicType = dynamic_cast(owningObjectType); + solAssert(owningObjectMagicType); + + switch (owningObjectMagicType->kind()) + { + case MagicType::Kind::Block: { if (memberName == "chainid" && !m_evmVersion.hasChainID()) m_errorReporter.typeError( @@ -3482,19 +3470,94 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) _memberAccess.location(), R"(Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain.)" ); + break; + } + case MagicType::Kind::ABI: + _memberAccess.annotation().isPure = true; + break; + case MagicType::Kind::MetaType: + { + if (memberName == "creationCode" || memberName == "runtimeCode") + { + _memberAccess.annotation().isPure = true; + ContractType const& accessedContractType = dynamic_cast(*owningObjectMagicType->typeArgument()); + solAssert(!accessedContractType.isSuper(), ""); + if ( + memberName == "runtimeCode" && + !accessedContractType.immutableVariables().empty() + ) + m_errorReporter.typeError( + 9274_error, + _memberAccess.location(), + R"("runtimeCode" is not available for contracts containing immutable variables.)" + ); + } + else if ( + memberName == "name" || + memberName == "interfaceId" || + memberName == "min" || + memberName == "max" + ) + _memberAccess.annotation().isPure = true; + break; + } + // Empty cases. + case MagicType::Kind::Message: + case MagicType::Kind::Transaction: + case MagicType::Kind::Error: + break; } + + _memberAccess.annotation().isLValue = false; + break; + } + case Type::Category::Module: + _memberAccess.annotation().isPure = *_memberAccess.expression().annotation().isPure; + _memberAccess.annotation().isLValue = false; + break; + case Type::Category::Address: + if (memberName == "codehash" && !m_evmVersion.hasExtCodeHash()) + m_errorReporter.typeError( + 7598_error, + _memberAccess.location(), + R"("codehash" is not supported by the VM version.)" + ); + _memberAccess.annotation().isLValue = false; + break; + case Type::Category::Integer: + case Type::Category::RationalNumber: + case Type::Category::StringLiteral: + case Type::Category::Bool: + case Type::Category::FixedPoint: + case Type::Category::FixedBytes: + case Type::Category::Array: + case Type::Category::ArraySlice: + case Type::Category::Contract: + case Type::Category::Enum: + case Type::Category::UserDefinedValueType: + case Type::Category::Tuple: + case Type::Category::Mapping: + case Type::Category::Modifier: + case Type::Category::InaccessibleDynamic: + _memberAccess.annotation().isLValue = false; + break; } + solAssert(_memberAccess.annotation().isLValue.set()); + + // TODO: Leave it for now, but it should be moved to TypeType -> Contract case. + // We do not want to change the logic in refactor PR. if ( - _memberAccess.expression().annotation().type->category() == Type::Category::Address && - memberName == "codehash" && - !m_evmVersion.hasExtCodeHash() + auto const* varDecl = dynamic_cast(_memberAccess.annotation().referencedDeclaration); + !_memberAccess.annotation().isPure.set() && + varDecl && + varDecl->isConstant() ) - m_errorReporter.typeError( - 7598_error, - _memberAccess.location(), - R"("codehash" is not supported by the VM version.)" - ); + { + solAssert(owningObjectType->category() != Type::Category::Magic); + _memberAccess.annotation().isPure = true; + } + if (!_memberAccess.annotation().isPure.set()) _memberAccess.annotation().isPure = false; From 748f1ac972890bee29bf168961a1ec2227a3c9be Mon Sep 17 00:00:00 2001 From: "Mate Soos @ Argot" Date: Mon, 20 Apr 2026 16:10:05 +0200 Subject: [PATCH 1264/1340] =?UTF-8?q?Fix=20O(n=C2=B2)=20in=20VarNameCleane?= =?UTF-8?q?r::findCleanName=20using=20per-base-name=20counter=20(#16563)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix O(n²) in VarNameCleaner::findCleanName using per-base-name counter When many variables share the same stripped base name, findCleanName would probe name_1, name_2, ..., name_N sequentially for each variable, resulting in O(n²) calls to isUsedName (which involves regex matching via isRestrictedIdentifier). This was the dominant cost in fuzzer timeouts where the optimizer generated many variables. Track a counter per base name (m_nextSuffix) so we resume from the last assigned suffix instead of reprobing from 1 each time. --- libyul/optimiser/VarNameCleaner.cpp | 16 ++++++++-- libyul/optimiser/VarNameCleaner.h | 3 ++ .../double_underscore_suffix.yul | 15 +++++++++ .../varNameCleaner/interleaved_bases.yul | 25 +++++++++++++++ .../varNameCleaner/many_same_base.yul | 25 +++++++++++++++ .../many_same_base_in_function.yul | 29 +++++++++++++++++ .../varNameCleaner/nested_suffixes.yul | 17 ++++++++++ .../references_after_rename.yul | 15 +++++++++ .../varNameCleaner/same_base_with_gap.yul | 19 +++++++++++ .../suffix_skips_function_name.yul | 20 ++++++++++++ .../varNameCleaner/suffix_skips_reserved.yul | 19 +++++++++++ .../two_functions_same_base.yul | 32 +++++++++++++++++++ 12 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 test/libyul/yulOptimizerTests/varNameCleaner/double_underscore_suffix.yul create mode 100644 test/libyul/yulOptimizerTests/varNameCleaner/interleaved_bases.yul create mode 100644 test/libyul/yulOptimizerTests/varNameCleaner/many_same_base.yul create mode 100644 test/libyul/yulOptimizerTests/varNameCleaner/many_same_base_in_function.yul create mode 100644 test/libyul/yulOptimizerTests/varNameCleaner/nested_suffixes.yul create mode 100644 test/libyul/yulOptimizerTests/varNameCleaner/references_after_rename.yul create mode 100644 test/libyul/yulOptimizerTests/varNameCleaner/same_base_with_gap.yul create mode 100644 test/libyul/yulOptimizerTests/varNameCleaner/suffix_skips_function_name.yul create mode 100644 test/libyul/yulOptimizerTests/varNameCleaner/suffix_skips_reserved.yul create mode 100644 test/libyul/yulOptimizerTests/varNameCleaner/two_functions_same_base.yul diff --git a/libyul/optimiser/VarNameCleaner.cpp b/libyul/optimiser/VarNameCleaner.cpp index 8d34ce85e..ad95e7ca4 100644 --- a/libyul/optimiser/VarNameCleaner.cpp +++ b/libyul/optimiser/VarNameCleaner.cpp @@ -55,6 +55,8 @@ void VarNameCleaner::operator()(FunctionDefinition& _funDef) m_usedNames = m_namesToKeep; std::map globalTranslatedNames; swap(globalTranslatedNames, m_translatedNames); + std::map globalNextSuffix; + swap(globalNextSuffix, m_nextSuffix); renameVariables(_funDef.parameters); renameVariables(_funDef.returnVariables); @@ -62,6 +64,7 @@ void VarNameCleaner::operator()(FunctionDefinition& _funDef) swap(globalUsedNames, m_usedNames); swap(globalTranslatedNames, m_translatedNames); + swap(globalNextSuffix, m_nextSuffix); m_insideFunction = false; } @@ -99,12 +102,19 @@ YulName VarNameCleaner::findCleanName(YulName const& _name) const if (!isUsedName(newName)) return newName; - // create new name with suffix (by finding a free identifier) - for (size_t i = 1; i < std::numeric_limits::max(); ++i) + // Use a per-base-name counter to avoid O(n²) probing when many + // variables share the same stripped base name. + size_t& nextSuffix = m_nextSuffix[newName]; + if (nextSuffix == 0) + nextSuffix = 1; + for (; nextSuffix < std::numeric_limits::max(); ++nextSuffix) { - YulName newNameSuffixed = YulName{newName.str() + "_" + std::to_string(i)}; + YulName newNameSuffixed = YulName{newName.str() + "_" + std::to_string(nextSuffix)}; if (!isUsedName(newNameSuffixed)) + { + ++nextSuffix; return newNameSuffixed; + } } yulAssert(false, "Exhausted by attempting to find an available suffix."); } diff --git a/libyul/optimiser/VarNameCleaner.h b/libyul/optimiser/VarNameCleaner.h index 47f3aca48..f61426008 100644 --- a/libyul/optimiser/VarNameCleaner.h +++ b/libyul/optimiser/VarNameCleaner.h @@ -89,6 +89,9 @@ class VarNameCleaner: public ASTModifier /// Set of names that are in use. std::set m_usedNames; + /// Next suffix to try per stripped base name, avoids O(n²) probing. + mutable std::map m_nextSuffix; + /// Maps old to new names. std::map m_translatedNames; diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/double_underscore_suffix.yul b/test/libyul/yulOptimizerTests/varNameCleaner/double_underscore_suffix.yul new file mode 100644 index 000000000..3f67b621e --- /dev/null +++ b/test/libyul/yulOptimizerTests/varNameCleaner/double_underscore_suffix.yul @@ -0,0 +1,15 @@ +{ + let x__1 := 1 + let x__2 := 2 + let x___3 := 3 +} +// ---- +// step: varNameCleaner +// +// { +// { +// let x := 1 +// let x_1 := 2 +// let x_2 := 3 +// } +// } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/interleaved_bases.yul b/test/libyul/yulOptimizerTests/varNameCleaner/interleaved_bases.yul new file mode 100644 index 000000000..1f7136ee6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varNameCleaner/interleaved_bases.yul @@ -0,0 +1,25 @@ +{ + let x_5 := 1 + let y_3 := 2 + let x_10 := 3 + let y_7 := 4 + let z_1 := 5 + let x_20 := 6 + let y_15 := 7 + let z_8 := 8 +} +// ---- +// step: varNameCleaner +// +// { +// { +// let x := 1 +// let y := 2 +// let x_1 := 3 +// let y_1 := 4 +// let z := 5 +// let x_2 := 6 +// let y_2 := 7 +// let z_1 := 8 +// } +// } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/many_same_base.yul b/test/libyul/yulOptimizerTests/varNameCleaner/many_same_base.yul new file mode 100644 index 000000000..b7fd6a09d --- /dev/null +++ b/test/libyul/yulOptimizerTests/varNameCleaner/many_same_base.yul @@ -0,0 +1,25 @@ +{ + let x_10 := 1 + let x_20 := 2 + let x_30 := 3 + let x_40 := 4 + let x_50 := 5 + let x_60 := 6 + let x_70 := 7 + let x_80 := 8 +} +// ---- +// step: varNameCleaner +// +// { +// { +// let x := 1 +// let x_1 := 2 +// let x_2 := 3 +// let x_3 := 4 +// let x_4 := 5 +// let x_5 := 6 +// let x_6 := 7 +// let x_7 := 8 +// } +// } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/many_same_base_in_function.yul b/test/libyul/yulOptimizerTests/varNameCleaner/many_same_base_in_function.yul new file mode 100644 index 000000000..b3fe26a9c --- /dev/null +++ b/test/libyul/yulOptimizerTests/varNameCleaner/many_same_base_in_function.yul @@ -0,0 +1,29 @@ +{ + let x_1 := 1 + function f() + { + let x_10 := 1 + let x_20 := 2 + let x_30 := 3 + let x_40 := 4 + let x_50 := 5 + } + let x_2 := 2 +} +// ---- +// step: varNameCleaner +// +// { +// { +// let x := 1 +// let x_1 := 2 +// } +// function f() +// { +// let x := 1 +// let x_1 := 2 +// let x_2 := 3 +// let x_3 := 4 +// let x_4 := 5 +// } +// } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/nested_suffixes.yul b/test/libyul/yulOptimizerTests/varNameCleaner/nested_suffixes.yul new file mode 100644 index 000000000..c3fcd2740 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varNameCleaner/nested_suffixes.yul @@ -0,0 +1,17 @@ +{ + let x_1_2 := 1 + let x_3_4_5 := 2 + let x_6 := 3 + let x_1_2_3_4 := 4 +} +// ---- +// step: varNameCleaner +// +// { +// { +// let x := 1 +// let x_1 := 2 +// let x_2 := 3 +// let x_3 := 4 +// } +// } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/references_after_rename.yul b/test/libyul/yulOptimizerTests/varNameCleaner/references_after_rename.yul new file mode 100644 index 000000000..4bdec4569 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varNameCleaner/references_after_rename.yul @@ -0,0 +1,15 @@ +{ + let x_5 := 42 + let y_3 := x_5 + let z_1 := add(x_5, y_3) +} +// ---- +// step: varNameCleaner +// +// { +// { +// let x := 42 +// let y := x +// let z := add(x, y) +// } +// } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/same_base_with_gap.yul b/test/libyul/yulOptimizerTests/varNameCleaner/same_base_with_gap.yul new file mode 100644 index 000000000..b8bc8e6ea --- /dev/null +++ b/test/libyul/yulOptimizerTests/varNameCleaner/same_base_with_gap.yul @@ -0,0 +1,19 @@ +{ + let x := 1 + let x_1 := 2 + let x_5 := 3 + let x_10 := 4 + let x_20 := 5 +} +// ---- +// step: varNameCleaner +// +// { +// { +// let x := 1 +// let x_1 := 2 +// let x_2 := 3 +// let x_3 := 4 +// let x_4 := 5 +// } +// } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/suffix_skips_function_name.yul b/test/libyul/yulOptimizerTests/varNameCleaner/suffix_skips_function_name.yul new file mode 100644 index 000000000..5ca68d9b6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varNameCleaner/suffix_skips_function_name.yul @@ -0,0 +1,20 @@ +{ + // x_1 is a function name, so the suffix counter must skip it + // when cleaning x_100 and x_200 which both strip to "x" + function x_1() {} + let x := 1 + let x_100 := 2 + let x_200 := 3 +} +// ---- +// step: varNameCleaner +// +// { +// { +// let x := 1 +// let x_2 := 2 +// let x_3 := 3 +// } +// function x_1() +// { } +// } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/suffix_skips_reserved.yul b/test/libyul/yulOptimizerTests/varNameCleaner/suffix_skips_reserved.yul new file mode 100644 index 000000000..33922df8b --- /dev/null +++ b/test/libyul/yulOptimizerTests/varNameCleaner/suffix_skips_reserved.yul @@ -0,0 +1,19 @@ +{ + let x := 1 + let x_2 := 2 + let x_100 := 3 + let x_200 := 4 + let x_300 := 5 +} +// ---- +// step: varNameCleaner +// +// { +// { +// let x := 1 +// let x_1 := 2 +// let x_2 := 3 +// let x_3 := 4 +// let x_4 := 5 +// } +// } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/two_functions_same_base.yul b/test/libyul/yulOptimizerTests/varNameCleaner/two_functions_same_base.yul new file mode 100644 index 000000000..b468b7671 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varNameCleaner/two_functions_same_base.yul @@ -0,0 +1,32 @@ +{ + function f() + { + let x_10 := 1 + let x_20 := 2 + let x_30 := 3 + } + function g() + { + let x_40 := 4 + let x_50 := 5 + let x_60 := 6 + } +} +// ---- +// step: varNameCleaner +// +// { +// { } +// function f() +// { +// let x := 1 +// let x_1 := 2 +// let x_2 := 3 +// } +// function g() +// { +// let x := 4 +// let x_1 := 5 +// let x_2 := 6 +// } +// } From 99ff1730c01a6ffef56c9959f5a45e35b8ce7e37 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 8 Apr 2026 15:14:58 +0200 Subject: [PATCH 1265/1340] Adapt ssa stack shuffler to be able to deal with spill set - SpilledVariables class to track what was spilled - target min counts / required in tail checks exclude spilled variables --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/ssa/StackShuffler.cpp | 23 +++-- libyul/backends/evm/ssa/StackShuffler.h | 97 ++++++++++++++----- .../backends/evm/ssa/StackToMemorySpilling.h | 59 +++++++++++ .../too_deep_unreachable_slot.stack | 2 +- 5 files changed, 152 insertions(+), 30 deletions(-) create mode 100644 libyul/backends/evm/ssa/StackToMemorySpilling.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 8e8ec56df..80584bf77 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -99,6 +99,7 @@ add_library(yul backends/evm/ssa/StackLayoutGenerator.h backends/evm/ssa/StackShuffler.cpp backends/evm/ssa/StackShuffler.h + backends/evm/ssa/StackToMemorySpilling.h backends/evm/ssa/StackUtils.cpp backends/evm/ssa/StackUtils.h backends/evm/ssa/io/DotExporterBase.cpp diff --git a/libyul/backends/evm/ssa/StackShuffler.cpp b/libyul/backends/evm/ssa/StackShuffler.cpp index 4d5c5dbc6..a9416a088 100644 --- a/libyul/backends/evm/ssa/StackShuffler.cpp +++ b/libyul/backends/evm/ssa/StackShuffler.cpp @@ -24,23 +24,31 @@ using namespace solidity::yul::ssa; using namespace solidity::yul::ssa::detail; -Target::Target(StackData const& _args, LivenessAnalysis::LivenessData const& _liveOut, std::size_t const _targetSize): +Target::Target( + StackData const& _args, + LivenessAnalysis::LivenessData const& _liveOut, + std::size_t const _targetSize, + SpilledVariables const* _spilledVariables +): args(_args), liveOut(_liveOut), + spilledVariables(_spilledVariables), size(_targetSize), tailSize(_targetSize - _args.size()) { minCount.reserve(_args.size() + _liveOut.size()); for (auto const& arg: _args) - if (!arg.isJunk()) + if (!arg.isJunk() && !slotIsSpilled(arg, _spilledVariables)) ++minCount[arg]; - for (auto const& _liveValueId: _liveOut | ranges::views::keys) - ++minCount[StackSlot::makeValueID(_liveValueId)]; + for (auto const& liveValueId: _liveOut | ranges::views::keys) + if (!(_spilledVariables && _spilledVariables->isSpilled(liveValueId))) + ++minCount[StackSlot::makeValueID(liveValueId)]; } -State::State(StackData const& _stackData, Target const& _target, std::size_t const _reachableStackDepth): +State::State(StackData const& _stackData, Target const& _target, SpilledVariables const* const _spilledVariables, std::size_t const _reachableStackDepth): m_stackData(_stackData), m_target(_target), + m_spilledVariables(_spilledVariables), m_reachableStackDepth(_reachableStackDepth) { m_histogram.reserve(_stackData.size()); @@ -125,7 +133,10 @@ bool State::requiredInArgs(StackSlot const& _slot) const bool State::requiredInTail(StackSlot const& _slot) const { - return _slot.isValueID() && m_target.liveOut.contains(_slot.valueID()); + if (!_slot.isValueID() || !m_target.liveOut.contains(_slot.valueID())) + return false; + // Spilled values can be rematerialized, so they need not occupy a tail slot. + return !slotIsSpilled(_slot); } bool State::offsetInTargetArgsRegion(StackOffset const _offset) const diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 6ccb629cb..ac095346e 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -19,6 +19,7 @@ #pragma once #include +#include #include #include @@ -36,14 +37,31 @@ namespace solidity::yul::ssa namespace detail { + +inline bool slotIsSpilled(StackSlot const& _slot, SpilledVariables const* const _spilledVariables) +{ + return _spilledVariables && _slot.isValueID() && _spilledVariables->isSpilled(_slot.valueID()); +} + +inline bool slotCanBeLoadedOrPushed(StackSlot const& _slot, SpilledVariables const* const _spilledVariables) +{ + return Stack<>::canBeFreelyGenerated(_slot) || slotIsSpilled(_slot, _spilledVariables); +} + /// Contains information about the shuffling target, aggregates over args and live out to /// provide a lower bound for the slot distribution. struct Target { - Target(StackData const& _args, LivenessAnalysis::LivenessData const& _liveOut, std::size_t _targetSize); + Target( + StackData const& _args, + LivenessAnalysis::LivenessData const& _liveOut, + std::size_t _targetSize, + SpilledVariables const* _spilledVariables = nullptr + ); StackData const& args; LivenessAnalysis::LivenessData const& liveOut; + SpilledVariables const* const spilledVariables; std::size_t const size; std::size_t const tailSize; boost::container::flat_map minCount; @@ -52,7 +70,7 @@ struct Target class State { public: - State(StackData const& _stackData, Target const& _target, std::size_t _reachableStackDepth); + State(StackData const& _stackData, Target const& _target, SpilledVariables const* const _spilledVariables, std::size_t _reachableStackDepth); std::size_t size() const; /// How many of `_slot` do we have on stack @@ -128,9 +146,20 @@ class State /// Depth of the deepest arg slot incompatible with target or Nothing for no incompatibility in current state std::optional findDeepestIncorrectArgSlot() const; + bool slotCanBeLoadedOrPushed(StackSlot const& _slot) const + { + return detail::slotCanBeLoadedOrPushed(_slot, m_spilledVariables); + } + + bool slotIsSpilled(StackSlot const& _slot) const + { + return detail::slotIsSpilled(_slot, m_spilledVariables); + } + private: StackData const& m_stackData; Target const& m_target; + SpilledVariables const* const m_spilledVariables; std::size_t const m_reachableStackDepth; boost::container::flat_map m_histogramTail; boost::container::flat_map m_histogramArgs; @@ -156,25 +185,32 @@ class StackShuffler Stack& _stack, StackData const& _args, LivenessAnalysis::LivenessData const& _liveOut, - std::size_t _targetStackSize + std::size_t _targetStackSize, + SpilledVariables const* const _spilledVariables = nullptr ) { - detail::Target const target(_args, _liveOut, _targetStackSize); - yulAssert(_liveOut.size() <= target.size, "not enough tail space"); + detail::Target const target(_args, _liveOut, _targetStackSize, _spilledVariables); + // If the caller has wired up a spill set, the shuffler can reduce the effective liveOut + // size by spilling; otherwise the liveOut must fit into the target up front. + if (!_spilledVariables) + yulAssert(_liveOut.size() <= target.size, "not enough tail space"); { // check that all required values are on stack - detail::State const state(_stack.data(), target, ReachableStackDepth); + detail::State const state(_stack.data(), target, _spilledVariables, ReachableStackDepth); for (auto const& liveVariable: _liveOut | ranges::views::keys | ranges::views::transform(Slot::makeValueID)) - yulAssert(!_stack.canBeFreelyGenerated(liveVariable) && ranges::contains(_stack.data(), liveVariable)); + yulAssert( + !_stack.canBeFreelyGenerated(liveVariable) && + (ranges::contains(_stack.data(), liveVariable) || detail::slotIsSpilled(liveVariable, _spilledVariables)) + ); for (auto const& arg: _args) - yulAssert(_stack.canBeFreelyGenerated(arg) || ranges::contains(_stack.data(), arg)); + yulAssert(detail::slotCanBeLoadedOrPushed(arg, _spilledVariables) || ranges::contains(_stack.data(), arg)); } static std::size_t constexpr maxIterations = 1000; std::size_t i = 0; while (true) { - detail::State const state(_stack.data(), target, ReachableStackDepth); + detail::State const state(_stack.data(), target, _spilledVariables, ReachableStackDepth); auto result = shuffleStep(_stack, state); if (result.status == StackShufflerResult::Status::Admissible) { @@ -228,13 +264,13 @@ class StackShuffler return {StackShufflerResult::Status::Continue}; // after this, all current slots are either in acceptable positions or at least dup-reachable - if (auto unreachableOffset = allNecessarySlotsReachableOrFinal(_stack, _state)) + if (auto culprit = allNecessarySlotsReachableOrFinal(_stack, _state)) { // !allNecessarySlotsReachableOrFinal(ops) ≡ ¬(∀s: reachable(s) ∨ final(s)) ≡ ∃s: ¬reachable(s) ∧ ¬final(s) if (shrinkStack(_stack, _state)) return {StackShufflerResult::Status::Continue}; - return {StackShufflerResult::Status::StackTooDeep, _stack[*unreachableOffset]}; + return {StackShufflerResult::Status::StackTooDeep, _stack.top()}; } // this will either grow the tail as needed, swap down something from args that needs to be in the tail, @@ -273,6 +309,18 @@ class StackShuffler if (shrinkStack(_stack, _state)) return {StackShufflerResult::Status::Continue}; + // if we couldn't shrink the stack we surface this failed state as stack too deep + for (StackOffset const offset: _state.stackRange() | ranges::views::reverse) + { + Slot const& candidate = _stack[offset]; + if ( + candidate.isValueID() && + !candidate.isLiteralValueID() && + !_state.slotIsSpilled(candidate) + ) + return {StackShufflerResult::Status::StackTooDeep, candidate}; + } + yulAssert(false, "reached final and forbidden state"); } @@ -580,10 +628,10 @@ class StackShuffler _stack.dup(*sourceDepth); return {ShuffleHelperResult::Status::StackModified}; } - if (!_stack.canBeFreelyGenerated(arg)) + if (!_state.slotCanBeLoadedOrPushed(arg)) return {ShuffleHelperResult::Status::StackTooDeep, arg}; } - yulAssert(_stack.canBeFreelyGenerated(arg)); + yulAssert(_state.slotCanBeLoadedOrPushed(arg)); _stack.push(arg); return {ShuffleHelperResult::Status::StackModified}; } @@ -621,7 +669,7 @@ class StackShuffler } else { - if (!_stack.canBeFreelyGenerated(arg)) + if (!_state.slotCanBeLoadedOrPushed(arg)) return {ShuffleHelperResult::Status::StackTooDeep, arg}; auto result = dupDeepSlotIfRequired(_stack, _state); if (result.status == ShuffleHelperResult::Status::StackTooDeep) @@ -671,7 +719,7 @@ class StackShuffler for (StackOffset tailOffset: _state.stackTailRange()) if ( _stack.isValidSwapTarget(tailOffset) && - _stack.canBeFreelyGenerated(_stack[tailOffset]) && + _state.slotCanBeLoadedOrPushed(_stack[tailOffset]) && !_stack[tailOffset].isLiteralValueID() ) { @@ -830,8 +878,11 @@ class StackShuffler return false; } - /// Checks if all current slots are either in a position that is compatible with the target or, if not, are dup-reachable. - static std::optional allNecessarySlotsReachableOrFinal(Stack const& _stack, detail::State const& _state) + /// Checks if all current slots are either in a position that is compatible with the target or, if not, are + /// dup-reachable. + /// Returns the culprit slot (guaranteed to be non-junk) that cannot be placed or duplicated, or `std::nullopt` + /// if every slot is reachable-or-final. + static std::optional allNecessarySlotsReachableOrFinal(Stack const& _stack, detail::State const& _state) { // check that args are either in position or reachable for (StackOffset offset{_state.target().tailSize}; offset < _state.target().size; ++offset.value) @@ -846,19 +897,19 @@ class StackShuffler // the target offset itself is out of swap range, we must shrink to reach it if (offset.value < _stack.size() && _stack.isBeyondSwapRange(offset)) - return offset; + return targetArg; // find first occurrence of the slot std::optional const depth = _stack.findSlotDepth(targetArg); if (!depth) { // if there is no occurrence of the slot anywhere, we must be able to freely generate it - yulAssert(_stack.canBeFreelyGenerated(targetArg)); + yulAssert(_state.slotCanBeLoadedOrPushed(targetArg)); } else { - if (_stack.isBeyondSwapRange(*depth)) - return _stack.depthToOffset(*depth); + if (_stack.isBeyondSwapRange(*depth) && !_state.slotCanBeLoadedOrPushed(targetArg)) + return targetArg; } } // distribution check: all we have to dup can be duped @@ -875,8 +926,8 @@ class StackShuffler std::optional depth = _stack.findSlotDepth(slotAtOffset); // it must exist yulAssert(depth); - if (!_stack.dupReachable(*depth)) - return _stack.depthToOffset(*depth); + if (!_stack.dupReachable(*depth) && !_state.slotCanBeLoadedOrPushed(slotAtOffset)) + return slotAtOffset; } } diff --git a/libyul/backends/evm/ssa/StackToMemorySpilling.h b/libyul/backends/evm/ssa/StackToMemorySpilling.h new file mode 100644 index 000000000..f4d869a9e --- /dev/null +++ b/libyul/backends/evm/ssa/StackToMemorySpilling.h @@ -0,0 +1,59 @@ +/* +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 + +#pragma once + +#include + +#include + +#include +#include + +namespace solidity::yul::ssa +{ +class SpilledVariables +{ +public: + + void spill(SSACFG::ValueId const _valueId) + { + bool const emplaced = m_spillSet.try_emplace(_valueId, m_currentSpillSlot).second; + yulAssert(emplaced, fmt::format("can't spill a value ({}) twice", _valueId)); + ++m_currentSpillSlot; + } + + bool isSpilled(SSACFG::ValueId const _valueId) const + { + return m_spillSet.contains(_valueId); + } + + std::size_t numSpilled() const + { + return m_spillSet.size(); + } + + auto spilledValues() const + { + return m_spillSet | ranges::views::keys; + } +private: + std::uint32_t m_currentSpillSlot{0}; + std::map m_spillSet; // map valueId -> ssa-cfg-local slot +}; +} diff --git a/test/libyul/ssa/stackShuffler/too_deep_unreachable_slot.stack b/test/libyul/ssa/stackShuffler/too_deep_unreachable_slot.stack index 67f1238a0..711b33aa5 100644 --- a/test/libyul/ssa/stackShuffler/too_deep_unreachable_slot.stack +++ b/test/libyul/ssa/stackShuffler/too_deep_unreachable_slot.stack @@ -9,4 +9,4 @@ targetStackTop: [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v1 // (initial)| v18 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v1 // +------------------------------------------------------------------------------------------------------------------------------ // (target)| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 -// Status: StackTooDeep (culprit: v18) +// Status: StackTooDeep (culprit: v1) From f9af4a0e34f5dd33ebbb8baf0ac51b8acd26d54f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 8 Apr 2026 15:15:11 +0200 Subject: [PATCH 1266/1340] findOptimalTargetSize pretends to do stack spilling --- libyul/backends/evm/ssa/StackUtils.cpp | 37 +++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index dbc9b1541..883a1f3b8 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -104,12 +104,37 @@ std::size_t solidity::yul::ssa::findOptimalTargetSize data.reserve(startSize + maxUpwardExpansion); auto const evaluateCost = [&](std::size_t const _targetSize) -> std::size_t { - data = _stackData; - Stack countOpsStack(data, {}); - auto const shuffleResult = StackShuffler::shuffle(countOpsStack, _targetArgs, _targetLiveOut, _targetSize); - yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); - yulAssert(countOpsStack.size() == _targetSize); - return countOpsStack.callbacks().numOps; + StackShufflerResult result; + SpilledVariables spillSet; + OpsCountingCallbacks callbacks; + do + { + data = _stackData; + Stack countOpsStack(data, {}); + result = StackShuffler::shuffle(countOpsStack, _targetArgs, _targetLiveOut, _targetSize, &spillSet); + callbacks = countOpsStack.callbacks(); + switch (result.status) + { + case StackShufflerResult::Status::Continue: + yulAssert(false); + case StackShufflerResult::Status::Admissible: + break; + case StackShufflerResult::Status::StackTooDeep: + { + yulAssert(result.culprit.isValueID() && !result.culprit.isLiteralValueID()); + yulAssert(!spillSet.isSpilled(result.culprit.valueID())); + spillSet.spill(result.culprit.valueID()); + break; + } + case StackShufflerResult::Status::MaxIterationsReached: + break; + } + } + while (result.status == StackShufflerResult::Status::StackTooDeep); + yulAssert(data.size() == _targetSize); + yulAssert(result.status == StackShufflerResult::Status::Admissible); + std::size_t const cost = callbacks.numOps + 1000 * spillSet.numSpilled(); + return cost; }; std::size_t bestCost = evaluateCost(startSize); From af7d8519a2304b2418faf0fc581ecb57eae9b3d9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:08:08 +0200 Subject: [PATCH 1267/1340] add stack spilling tests to ssa stack shuffler tests --- test/libyul/ssa/StackShufflerTest.cpp | 56 ++++++++++++++++++- .../ssa/stackShuffler/initial_spill_set.stack | 16 ++++++ .../stackShuffler/spill_arg_in_liveout.stack | 17 ++++++ .../spill_disabled_default.stack | 14 +++++ .../spill_many_for_small_target.stack | 17 ++++++ .../spill_to_pop_deep_junk.stack | 46 +++++++++++++++ .../spilled_to_pop_deep_junk.stack | 41 ++++++++++++++ .../too_deep_dup_deep_tail_slot.stack | 2 +- 8 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 test/libyul/ssa/stackShuffler/initial_spill_set.stack create mode 100644 test/libyul/ssa/stackShuffler/spill_arg_in_liveout.stack create mode 100644 test/libyul/ssa/stackShuffler/spill_disabled_default.stack create mode 100644 test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack create mode 100644 test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack create mode 100644 test/libyul/ssa/stackShuffler/spilled_to_pop_deep_junk.stack diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index 993ba4bb9..2a05187b6 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -50,6 +50,8 @@ std::string_view constexpr parserKeyInitialStack {"initial"}; std::string_view constexpr parserKeyStackTop {"targetStackTop"}; std::string_view constexpr parserKeyTailSet {"targetStackTailSet"}; std::string_view constexpr parserKeyStackSize {"targetStackSize"}; +std::string_view constexpr parserKeyAllowSpilling {"allowSpilling"}; +std::string_view constexpr parserKeyInitialSpilled {"initialSpilledSet"}; using Liveness = LivenessAnalysis::LivenessData; using Slot = StackSlot; @@ -178,6 +180,8 @@ struct ShuffleTestInput std::optional targetStackTop; Liveness targetStackTailSet{}; std::optional targetStackSize; + bool allowSpilling = false; + SpilledVariables initialSpilledSet{}; bool valid() const { @@ -236,6 +240,18 @@ struct ShuffleTestInput else throw std::runtime_error(fmt::format("Couldn't parse targetStackSize: {}", value)); } + else if (key == parserKeyAllowSpilling) + { + if (value == "true") + result.allowSpilling = true; + else if (value == "false") + result.allowSpilling = false; + else + throw std::runtime_error(fmt::format("Couldn't parse allowSpilling: {}", value)); + } + else if (key == parserKeyInitialSpilled) + for (auto const& [valueId, _]: parseLiveness(value)) + result.initialSpilledSet.spill(valueId); } @@ -475,6 +491,31 @@ explicitly provided.)"; auto stackData = *testConfig.initial; std::ostringstream oss; StackShufflerResult shuffleResult; + SpilledVariables spillSet = testConfig.initialSpilledSet; + + // First, when spilling is allowed, run the shuffler repeatedly without recording to determine + // the final spill set. Each iteration starts from the initial stack and adds the culprit of a + // recoverable StackTooDeep to the spill set. + if (testConfig.allowSpilling) + while (true) + { + auto scratch = *testConfig.initial; + TestStack stack(scratch, {}); + auto const result = StackShuffler::shuffle( + stack, + *testConfig.targetStackTop, + testConfig.targetStackTailSet, + *testConfig.targetStackSize, + &spillSet + ); + if ( + result.status != StackShufflerResult::Status::StackTooDeep + ) + break; + spillSet.spill(result.culprit.valueID()); + } + + // Final shuffle with the (possibly pre-populated) spill set, recording the trace. { TraceRecorder trace(oss, *testConfig.targetStackTop, testConfig.targetStackTailSet, *testConfig.targetStackSize); trace.record("(initial)", *testConfig.initial); @@ -486,7 +527,8 @@ explicitly provided.)"; stack, *testConfig.targetStackTop, testConfig.targetStackTailSet, - *testConfig.targetStackSize + *testConfig.targetStackSize, + &spillSet ); if (shuffleResult.status == StackShufflerResult::Status::MaxIterationsReached) trace.truncate(30); @@ -506,6 +548,16 @@ explicitly provided.)"; case StackShufflerResult::Status::Continue: yulAssert(false, "Unexpected Continue status from shuffle()"); } + if (testConfig.allowSpilling) + oss << fmt::format( + "Spilled: {{{}}}\n", + fmt::join( + spillSet.spilledValues() | ranges::views::transform( + [](auto const& id) { return slotToString(StackSlot::makeValueID(id)); } + ), + ", " + ) + ); // check stack data if (shuffleResult.status == StackShufflerResult::Status::Admissible) { @@ -514,6 +566,8 @@ explicitly provided.)"; yulAssert(stackData.size() == *testConfig.targetStackSize); for (const auto& valueID: testConfig.targetStackTailSet | ranges::views::keys) { + if (spillSet.isSpilled(valueID)) + continue; auto const findIt = ranges::find( stackData.begin(), stackData.begin() + static_cast(tailSize), diff --git a/test/libyul/ssa/stackShuffler/initial_spill_set.stack b/test/libyul/ssa/stackShuffler/initial_spill_set.stack new file mode 100644 index 000000000..5c1b30c83 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/initial_spill_set.stack @@ -0,0 +1,16 @@ +// Seeds the spill set with v1 from the start. Even though v1 is in the tail set and not on the stack, +// the shuffler treats it as freely generatable and finishes admissible without retries. +allowSpilling: true +initialSpilledSet: {v1} +initial: [v3, v4, v5] +targetStackTop: [v3, v4, v5] +targetStackTailSet: {v1} +targetStackSize: 3 +// ---- +// | 0 1 2 +// +--------------------- +// (initial)| v3 v4 v5 +// +--------------------- +// (target)| v3 v4 v5 +// Status: Admissible +// Spilled: {v1} diff --git a/test/libyul/ssa/stackShuffler/spill_arg_in_liveout.stack b/test/libyul/ssa/stackShuffler/spill_arg_in_liveout.stack new file mode 100644 index 000000000..bfc4d9386 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/spill_arg_in_liveout.stack @@ -0,0 +1,17 @@ +// v1 is needed both as an arg AND in the liveOut tail set, but appears only once on the stack at the top. +// The deep tail slots (depth 17 = offset 0) are beyond swap range, so v1 cannot be duplicated into the tail. +// With allowSpilling, the shuffler reports StackTooDeep with culprit v1, the test driver adds v1 to the spill +// set and retries; v1 is now freely generatable so the second iteration succeeds. +allowSpilling: true +initial: [JUNK, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v1] +targetStackTop: [v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v1] +targetStackTailSet: {v1} +targetStackSize: 18 +// ---- +// | 0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +// +------- +----------------------------------------------------------------------------------------------------------------------- +// (initial)| * | v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v1 +// +------- +----------------------------------------------------------------------------------------------------------------------- +// (target)| {v1} | v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v1 +// Status: Admissible +// Spilled: {v1} diff --git a/test/libyul/ssa/stackShuffler/spill_disabled_default.stack b/test/libyul/ssa/stackShuffler/spill_disabled_default.stack new file mode 100644 index 000000000..60dbc2da9 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/spill_disabled_default.stack @@ -0,0 +1,14 @@ +// Same setup as spill_arg_in_liveout but without allowSpilling: confirms the default behaviour is +// preserved and the shuffler reports StackTooDeep without retrying. +initial: [JUNK, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v1] +targetStackTop: [v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v1] +targetStackTailSet: {v1} +targetStackSize: 18 +allowSpilling: false +// ---- +// | 0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +// +------- +----------------------------------------------------------------------------------------------------------------------- +// (initial)| * | v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v1 +// +------- +----------------------------------------------------------------------------------------------------------------------- +// (target)| {v1} | v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v1 +// Status: StackTooDeep (culprit: v1) diff --git a/test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack b/test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack new file mode 100644 index 000000000..cbcc023f1 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack @@ -0,0 +1,17 @@ +// Every target arg is also in the tail set, but the tail region has zero room (tail size = 0). +// Each fix-tail iteration reports the deepest still-needed value as StackTooDeep; with allowSpilling +// the driver spills it and retries. After every value has been spilled, the stack is admissible +// because the spilled values can be regenerated freely. +allowSpilling: true +initial: [v1, v2, v3, v4, v5, v6, v7, v8] +targetStackTop: [v1, v2, v3, v4, v5, v6, v7, v8] +targetStackTailSet: {v1, v2, v3, v4, v5, v6, v7, v8} +targetStackSize: 8 +// ---- +// | 0 1 2 3 4 5 6 7 +// +-------------------------------------------------------- +// (initial)| v1 v2 v3 v4 v5 v6 v7 v8 +// +-------------------------------------------------------- +// (target)| v1 v2 v3 v4 v5 v6 v7 v8 +// Status: Admissible +// Spilled: {v1, v2, v3, v4, v5, v6, v7, v8} diff --git a/test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack b/test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack new file mode 100644 index 000000000..c66f09fc6 --- /dev/null +++ b/test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack @@ -0,0 +1,46 @@ +allowSpilling: true +initial: [JUNK, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20] +targetStackTop: [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20] +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 20 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +------- +// (initial)| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 | v20 +// SWAP1| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v20 | v19 +// SWAP2| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v19 v20 | v18 +// SWAP3| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v18 v19 v20 | v17 +// SWAP4| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v17 v18 v19 v20 | v16 +// SWAP5| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v16 v17 v18 v19 v20 | v15 +// SWAP6| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v15 v16 v17 v18 v19 v20 | v14 +// SWAP7| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v14 v15 v16 v17 v18 v19 v20 | v13 +// SWAP8| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v13 v14 v15 v16 v17 v18 v19 v20 | v12 +// SWAP9| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v11 +// SWAP10| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v10 +// SWAP11| * v1 v2 v3 v4 v5 v6 v7 v8 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v9 +// SWAP12| * v1 v2 v3 v4 v5 v6 v7 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v8 +// SWAP13| * v1 v2 v3 v4 v5 v6 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v7 +// SWAP14| * v1 v2 v3 v4 v5 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v6 +// SWAP15| * v1 v2 v3 v4 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v5 +// SWAP16| * v1 v2 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v4 +// POP| * v1 v2 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 +// POP| * v1 v2 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 +// POP| * v1 v2 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 +// POP| * v1 v2 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 +// SWAP15| * v17 v2 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v1 +// SWAP16| v1 v17 v2 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 * +// SWAP14| v1 v17 * v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v2 +// SWAP15| v1 v2 * v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 +// SWAP13| v1 v2 * v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v3 +// SWAP14| v1 v2 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 * +// PUSH v4| v1 v2 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 * v4 +// SWAP14| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 * v17 +// SWAP1| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 * +// PUSH v18| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 * v18 +// SWAP1| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 * +// PUSH v19| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 * v19 +// SWAP1| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 * +// POP| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 +// PUSH v20| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +------- +// (target)| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | +// Status: Admissible +// Spilled: {v4, v18, v19, v20} diff --git a/test/libyul/ssa/stackShuffler/spilled_to_pop_deep_junk.stack b/test/libyul/ssa/stackShuffler/spilled_to_pop_deep_junk.stack new file mode 100644 index 000000000..42fe6acfb --- /dev/null +++ b/test/libyul/ssa/stackShuffler/spilled_to_pop_deep_junk.stack @@ -0,0 +1,41 @@ +allowSpilling: false +initialSpilledSet: {v1, v2, v4, v20} +initial: [JUNK, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20] +targetStackTop: [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20] +// ---- +// | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 20 +// +-------------------------------------------------------------------------------------------------------------------------------------------- +------- +// (initial)| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 | v20 +// SWAP1| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v20 | v19 +// SWAP2| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v19 v20 | v18 +// SWAP3| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v18 v19 v20 | v17 +// SWAP4| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v17 v18 v19 v20 | v16 +// SWAP5| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v16 v17 v18 v19 v20 | v15 +// SWAP6| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v15 v16 v17 v18 v19 v20 | v14 +// SWAP7| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v14 v15 v16 v17 v18 v19 v20 | v13 +// SWAP8| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v13 v14 v15 v16 v17 v18 v19 v20 | v12 +// SWAP9| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v11 +// SWAP10| * v1 v2 v3 v4 v5 v6 v7 v8 v9 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v10 +// SWAP11| * v1 v2 v3 v4 v5 v6 v7 v8 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v9 +// SWAP12| * v1 v2 v3 v4 v5 v6 v7 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v8 +// SWAP13| * v1 v2 v3 v4 v5 v6 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v7 +// SWAP14| * v1 v2 v3 v4 v5 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v6 +// SWAP15| * v1 v2 v3 v4 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v5 +// SWAP16| * v1 v2 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | v4 +// POP| * v1 v2 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 +// POP| * v1 v2 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 +// SWAP16| * v1 v19 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v2 +// POP| * v1 v19 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 +// SWAP16| * v18 v19 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v1 +// POP| * v18 v19 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 +// SWAP13| * v18 v19 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v3 +// SWAP14| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 +// PUSH v1| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 v1 +// POP| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 +// PUSH v1| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 v1 +// POP| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 +// PUSH v1| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 v1 +// ...| +// +-------------------------------------------------------------------------------------------------------------------------------------------- +------- +// (target)| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | +// Status: MaxIterationsReached diff --git a/test/libyul/ssa/stackShuffler/too_deep_dup_deep_tail_slot.stack b/test/libyul/ssa/stackShuffler/too_deep_dup_deep_tail_slot.stack index 79a02a199..45fd50185 100644 --- a/test/libyul/ssa/stackShuffler/too_deep_dup_deep_tail_slot.stack +++ b/test/libyul/ssa/stackShuffler/too_deep_dup_deep_tail_slot.stack @@ -9,4 +9,4 @@ targetStackSize: 19 // (initial)| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 // +------------------------------------------------------------------------------------------------------------------------------ +------- // (target)| {v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18} | v1 -// Status: StackTooDeep (culprit: v1) +// Status: StackTooDeep (culprit: v18) From a4d3b4d7c38885214d8af13ad2a8808846fca5f7 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:23:55 +0200 Subject: [PATCH 1268/1340] ssa cfg stack shuffler test: fix visualization issue when the entire tail set has been spilled --- test/libyul/ssa/StackShufflerTest.cpp | 69 ++++++++++++++----- .../ssa/stackShuffler/initial_spill_set.stack | 10 +-- .../stackShuffler/spill_arg_in_liveout.stack | 2 +- .../spill_many_for_small_target.stack | 10 +-- 4 files changed, 64 insertions(+), 27 deletions(-) diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index 2a05187b6..045b755c2 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -275,16 +275,43 @@ class TraceRecorder static char constexpr junkSymbol = '*'; public: - TraceRecorder(std::ostream& _out, TestStack::Data const& _targetArgs, Liveness const& _targetTail, size_t _targetStackSize): + TraceRecorder( + std::ostream& _out, + TestStack::Data const& _targetArgs, + Liveness const& _targetTail, + size_t _targetStackSize, + SpilledVariables const& _spillSet + ): m_out(_out), m_targetArgs(_targetArgs), m_targetTail(_targetTail), + m_spillSet(_spillSet), m_targetStackSize(_targetStackSize), m_targetTailSize( [&] { yulAssert(_targetStackSize >= m_targetArgs.size()); return _targetStackSize - m_targetArgs.size(); }() + ), + m_tailSetStr( + fmt::format( + "{{{}}}", + fmt::join( + m_targetTail | ranges::views::keys | ranges::views::transform( + [this](auto const& id) { + std::string const suffix = m_spillSet.isSpilled(id) ? "*" : ""; + return slotToString(Slot::makeValueID(id)) + suffix; + } + ), + ", " + ) + ) + ), + // Width of the phantom "tail annotation" column, shown only when the set is non-empty + // but the tail region has zero real columns (all tail-set members spilled or coinciding + // with args) + m_tailAnnotationWidth( + m_targetTailSize == 0 && !m_targetTail.empty() ? m_tailSetStr.size() + 2 : 0 ) {} @@ -351,8 +378,22 @@ class TraceRecorder bool m_truncated = false; TestStack::Data const& m_targetArgs; Liveness const& m_targetTail; + SpilledVariables const& m_spillSet; size_t const m_targetStackSize; size_t const m_targetTailSize; + std::string const m_tailSetStr; + size_t const m_tailAnnotationWidth; + + void emitTailAnnotationColumn(std::string_view _content, char const _filler, char const _junction) const + { + if (m_tailAnnotationWidth == 0) + return; + if (_content.empty()) + m_out << std::string(m_tailAnnotationWidth, _filler); + else + m_out << fmt::format("{:>{}}", _content, m_tailAnnotationWidth); + m_out << ' ' << _junction; + } void emitSeparator(size_t const _index, bool const _hasExcess, char const _junction) const { @@ -365,6 +406,7 @@ class TraceRecorder void emitHeader(bool const _hasExcess, std::vector const& _columnWidths) const { m_out << fmt::format("{:>{}}", "", operationColumnWidth) << "|"; + emitTailAnnotationColumn({}, ' ', '|'); for (std::size_t i = 0; i < _columnWidths.size(); ++i) { emitSeparator(i, _hasExcess, '|'); @@ -376,6 +418,7 @@ class TraceRecorder void emitSeparatorLine(bool const _hasExcess, std::vector const& _columnWidths) const { m_out << fmt::format("{:>{}}", "", operationColumnWidth) << '+'; + emitTailAnnotationColumn({}, '-', '+'); for (std::size_t i = 0; i < _columnWidths.size(); ++i) { emitSeparator(i, _hasExcess, '+'); @@ -387,6 +430,7 @@ class TraceRecorder void emitDataRow(TraceEntry const& _entry, bool const _hasExcess, std::vector const& _columnWidths) const { m_out << fmt::format("{:>{}}", _entry.operation, operationColumnWidth) << "|"; + emitTailAnnotationColumn({}, ' ', '|'); for (size_t i = 0; i < _entry.stackAfter.size(); ++i) { emitSeparator(i, _hasExcess, '|'); @@ -407,21 +451,14 @@ class TraceRecorder std::size_t tailWidth = 0; for (std::size_t i = 0; i < m_targetTailSize; ++i) tailWidth += _columnWidths[i]; - std::string const tailSetStr = fmt::format( - "{{{}}}", - fmt::join( - m_targetTail | ranges::views::keys | ranges::views::transform( - [](auto const& id) { return slotToString(Slot::makeValueID(id)); } - ), - ", " - ) - ); - m_out << fmt::format("{:>{}}", tailSetStr, tailWidth); - } + m_out << fmt::format("{:>{}}", m_tailSetStr, tailWidth); - // Args separator - if (!m_targetArgs.empty() && m_targetTailSize > 0) - m_out << " |"; + // Args separator + if (!m_targetArgs.empty()) + m_out << " |"; + } + else if (m_targetTailSize == 0) + emitTailAnnotationColumn(m_tailSetStr, ' ', '|'); // Print args region for (std::size_t i = 0; i < m_targetArgs.size(); ++i) @@ -517,7 +554,7 @@ explicitly provided.)"; // Final shuffle with the (possibly pre-populated) spill set, recording the trace. { - TraceRecorder trace(oss, *testConfig.targetStackTop, testConfig.targetStackTailSet, *testConfig.targetStackSize); + TraceRecorder trace(oss, *testConfig.targetStackTop, testConfig.targetStackTailSet, *testConfig.targetStackSize, spillSet); trace.record("(initial)", *testConfig.initial); TestStack stack(stackData, {.hook = [&](std::string const& op) { diff --git a/test/libyul/ssa/stackShuffler/initial_spill_set.stack b/test/libyul/ssa/stackShuffler/initial_spill_set.stack index 5c1b30c83..cd6d7f8ed 100644 --- a/test/libyul/ssa/stackShuffler/initial_spill_set.stack +++ b/test/libyul/ssa/stackShuffler/initial_spill_set.stack @@ -7,10 +7,10 @@ targetStackTop: [v3, v4, v5] targetStackTailSet: {v1} targetStackSize: 3 // ---- -// | 0 1 2 -// +--------------------- -// (initial)| v3 v4 v5 -// +--------------------- -// (target)| v3 v4 v5 +// | | 0 1 2 +// +------- +--------------------- +// (initial)| | v3 v4 v5 +// +------- +--------------------- +// (target)| {v1*} | v3 v4 v5 // Status: Admissible // Spilled: {v1} diff --git a/test/libyul/ssa/stackShuffler/spill_arg_in_liveout.stack b/test/libyul/ssa/stackShuffler/spill_arg_in_liveout.stack index bfc4d9386..c55beea1d 100644 --- a/test/libyul/ssa/stackShuffler/spill_arg_in_liveout.stack +++ b/test/libyul/ssa/stackShuffler/spill_arg_in_liveout.stack @@ -12,6 +12,6 @@ targetStackSize: 18 // +------- +----------------------------------------------------------------------------------------------------------------------- // (initial)| * | v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v1 // +------- +----------------------------------------------------------------------------------------------------------------------- -// (target)| {v1} | v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v1 +// (target)| {v1*} | v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v1 // Status: Admissible // Spilled: {v1} diff --git a/test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack b/test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack index cbcc023f1..948dd8db8 100644 --- a/test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack +++ b/test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack @@ -8,10 +8,10 @@ targetStackTop: [v1, v2, v3, v4, v5, v6, v7, v8] targetStackTailSet: {v1, v2, v3, v4, v5, v6, v7, v8} targetStackSize: 8 // ---- -// | 0 1 2 3 4 5 6 7 -// +-------------------------------------------------------- -// (initial)| v1 v2 v3 v4 v5 v6 v7 v8 -// +-------------------------------------------------------- -// (target)| v1 v2 v3 v4 v5 v6 v7 v8 +// | | 0 1 2 3 4 5 6 7 +// +------------------------------------------ +-------------------------------------------------------- +// (initial)| | v1 v2 v3 v4 v5 v6 v7 v8 +// +------------------------------------------ +-------------------------------------------------------- +// (target)| {v1*, v2*, v3*, v4*, v5*, v6*, v7*, v8*} | v1 v2 v3 v4 v5 v6 v7 v8 // Status: Admissible // Spilled: {v1, v2, v3, v4, v5, v6, v7, v8} From 3171c73de290de33ab05680b5525919f4c22380a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 21 Apr 2026 17:14:08 +0200 Subject: [PATCH 1269/1340] ssa cfg: remove literal assignments --- libyul/backends/evm/ssa/CodeTransform.cpp | 6 +- libyul/backends/evm/ssa/SSACFG.cpp | 21 +--- libyul/backends/evm/ssa/SSACFG.h | 3 +- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 21 +--- libyul/backends/evm/ssa/SSACFGBuilder.h | 3 - libyul/backends/evm/ssa/io/JSONExporter.cpp | 5 - .../standard_yul_cfg_json_export/output.json | 105 +++++++----------- test/cmdlineTests/yul_cfg_json_export/output | 105 +++++++----------- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 4 - test/libyul/ssa/controlFlowGraph/complex.yul | 53 +++++---- test/libyul/ssa/controlFlowGraph/complex2.yul | 58 +++++----- .../default_initialized_variable.yul | 12 +- test/libyul/ssa/controlFlowGraph/function.yul | 6 +- .../ssa/controlFlowGraph/nested_for.yul | 85 +++++++------- .../ssa/controlFlowGraph/nested_function.yul | 10 +- 15 files changed, 199 insertions(+), 298 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index caca86153..1d2044f79 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -279,8 +279,7 @@ void CodeTransform::operator()(SSACFG::OperationId _opId, StackData const& _oper m_assembly.appendLabel(*returnLabel); m_stack.pop(); } - }, - [&](SSACFG::LiteralAssignment const&){} + } }, _operation.kind); // simulate that the inputs are consumed for (size_t i = 0; i < _operation.inputs.size(); ++i) @@ -385,9 +384,6 @@ void CodeTransform::operator()(SSACFG::BlockId const& _blockId, SSACFG::BasicBlo }, [](SSACFG::Call const& _call) { yulAssert(!_call.canContinue, "Last operation of Terminated block must be a non-continuable call."); - }, - [](SSACFG::LiteralAssignment const&) { - yulAssert(false, "Terminated block cannot end with a literal assignment."); } }, m_cfg.operation(block.operations.back()).kind); // To be sure just emit another INVALID - should be removed by optimizer. diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 2c8195fe7..582bfaf2e 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -108,11 +108,6 @@ class SSACFGDotExporter: public io::DotExporterBase }, [&](SSACFG::BuiltinCall const& _call) { return _call.builtin.get().name; - }, - [&](SSACFG::LiteralAssignment const&) - { - yulAssert(operation.inputs.size() == 1); - return operation.inputs.back().str(m_cfg); } }, operation.kind); if (!operation.outputs.empty()) @@ -120,17 +115,11 @@ class SSACFGDotExporter: public io::DotExporterBase "{} := ", fmt::join(operation.outputs | ranges::views::transform(valueToString), ", ") ); - if (std::holds_alternative(operation.kind)) - _out << fmt::format( - "{}\\l\\\n", - escapeLabel(label) - ); - else - _out << fmt::format( - "{}({})\\l\\\n", - escapeLabel(label), - fmt::join(operation.inputs | ranges::views::transform(valueToString), ", ") - ); + _out << fmt::format( + "{}({})\\l\\\n", + escapeLabel(label), + fmt::join(operation.inputs | ranges::views::transform(valueToString), ", ") + ); } } diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 1b717c7c6..e01f8078f 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -78,7 +78,6 @@ class SSACFG std::reference_wrapper call; bool canContinue; }; - struct LiteralAssignment {}; /// Upsilon records a phi pre-image at a block exit. /// Upsilon(value, phi) means: the value flowing into `phi` from this block is `value`. @@ -91,7 +90,7 @@ class SSACFG struct Operation { std::vector outputs{}; - std::variant kind; + std::variant kind; std::vector inputs{}; }; struct BasicBlock diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 7b5f8e004..cf1ddea7f 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -53,7 +53,6 @@ SSACFGBuilder::SSACFGBuilder( AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, EVMDialect const& _dialect, - bool _keepLiteralAssignments, bool _generateDebugInfo ): m_controlFlow(_controlFlow), @@ -61,7 +60,6 @@ SSACFGBuilder::SSACFGBuilder( m_info(_analysisInfo), m_sideEffects(_sideEffects), m_dialect(_dialect), - m_keepLiteralAssignments(_keepLiteralAssignments), m_generateDebugInfo(_generateDebugInfo) { } @@ -70,7 +68,6 @@ std::unique_ptr SSACFGBuilder::build( AsmAnalysisInfo const& _analysisInfo, EVMDialect const& _dialect, Block const& _block, - bool _keepLiteralAssignments, bool _generateDebugInfo ) { @@ -83,7 +80,7 @@ std::unique_ptr SSACFGBuilder::build( )); controlFlow->functionGraphMapping.emplace_back(nullptr, controlFlow->functionGraphs.back().get()); SSACFG& mainGraph = *controlFlow->functionGraphs.back(); - SSACFGBuilder builder(*controlFlow, mainGraph, _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments, _generateDebugInfo); + SSACFGBuilder builder(*controlFlow, mainGraph, _analysisInfo, sideEffects, _dialect, _generateDebugInfo); builder.m_currentBlock = mainGraph.makeBlock(debugDataOf(_block)); builder.sealBlock(builder.m_currentBlock); builder(_block); @@ -129,7 +126,7 @@ void SSACFGBuilder::buildFunctionGraph( cfg.arguments = arguments; cfg.returns = returns; - SSACFGBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_keepLiteralAssignments, m_generateDebugInfo); + SSACFGBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_generateDebugInfo); builder.m_currentBlock = cfg.entry; builder.m_functionDefinitions = m_functionDefinitions; for (auto&& [var, varId]: cfg.arguments) @@ -431,19 +428,7 @@ void SSACFGBuilder::assign(std::vector> m_functionDefinitions; SSACFG::BlockId m_currentBlock; diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index 5e7d51436..c916217b6 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -51,11 +51,6 @@ Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation) _ret["type"] = "FunctionCall"; opJson["op"] = _call.function.get().name.str(); }, - [&](SSACFG::LiteralAssignment const&) { - yulAssert(_operation.inputs.size() == 1); - yulAssert(_operation.inputs.back().isLiteral()); - opJson["op"] = "LiteralAssignment"; - }, [&](SSACFG::BuiltinCall const& _call) { _ret["type"] = "BuiltinCall"; Json builtinArgsJson = Json::array(); diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index 09674ec77..3bfae0a92 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -1221,24 +1221,13 @@ "type": "ConditionalJump" }, "id": "Block18", - "instructions": [ - { - "in": [ - "0x00" - ], - "op": "LiteralAssignment", - "out": [ - "v36" - ] - } - ], + "instructions": [], "liveness": { "in": [ "v25", "v31" ], "out": [ - "v36", "v25" ] } @@ -1308,8 +1297,8 @@ "instructions": [ { "in": [ - "v36", - "v52" + "0x00", + "v50" ], "op": "PhiFunction", "out": [ @@ -1322,13 +1311,13 @@ ], "op": "mload", "out": [ - "v53" + "v51" ] }, { "in": [ "phi26", - "v53" + "v51" ], "op": "mstore", "out": [] @@ -1336,7 +1325,7 @@ { "in": [ "0x20", - "v53" + "v51" ], "op": "return", "out": [] @@ -1352,7 +1341,7 @@ }, { "exit": { - "cond": "v39", + "cond": "v37", "targets": [ "Block23", "Block22" @@ -1361,30 +1350,21 @@ }, "id": "Block20", "instructions": [ - { - "in": [ - "0x20" - ], - "op": "LiteralAssignment", - "out": [ - "v37" - ] - }, { "in": [], "op": "returndatasize", "out": [ - "v38" + "v36" ] }, { "in": [ - "v38", + "v36", "0x20" ], "op": "gt", "out": [ - "v39" + "v37" ] } ], @@ -1393,7 +1373,6 @@ "v25" ], "out": [ - "v37", "v25" ] }, @@ -1405,7 +1384,7 @@ "Block22" ], "exit": { - "cond": "v47", + "cond": "v45", "targets": [ "Block25", "Block24" @@ -1416,8 +1395,8 @@ "instructions": [ { "in": [ - "v37", - "v40" + "0x20", + "v38" ], "op": "PhiFunction", "out": [ @@ -1430,7 +1409,7 @@ ], "op": "not", "out": [ - "v41" + "v39" ] }, { @@ -1440,57 +1419,57 @@ ], "op": "add", "out": [ - "v42" + "v40" ] }, { "in": [ - "v41", - "v42" + "v39", + "v40" ], "op": "and", "out": [ - "v43" + "v41" ] }, { "in": [ - "v43", + "v41", "v25" ], "op": "add", "out": [ - "v44" + "v42" ] }, { "in": [ "v25", - "v44" + "v42" ], "op": "lt", "out": [ - "v45" + "v43" ] }, { "in": [ "0xffffffffffffffff", - "v44" + "v42" ], "op": "gt", "out": [ - "v46" + "v44" ] }, { "in": [ - "v45", - "v46" + "v43", + "v44" ], "op": "or", "out": [ - "v47" + "v45" ] } ], @@ -1502,7 +1481,7 @@ "out": [ "v25", "phi14", - "v44" + "v42" ] }, "type": "BuiltinCall" @@ -1520,7 +1499,7 @@ "in": [], "op": "returndatasize", "out": [ - "v40" + "v38" ] } ], @@ -1529,7 +1508,7 @@ "v25" ], "out": [ - "v40", + "v38", "v25" ] }, @@ -1537,7 +1516,7 @@ }, { "exit": { - "cond": "v51", + "cond": "v49", "targets": [ "Block28", "Block27" @@ -1548,7 +1527,7 @@ "instructions": [ { "in": [ - "v44", + "v42", "0x40" ], "op": "mstore", @@ -1561,27 +1540,27 @@ ], "op": "add", "out": [ - "v49" + "v47" ] }, { "in": [ "v25", - "v49" + "v47" ], "op": "sub", "out": [ - "v50" + "v48" ] }, { "in": [ "0x20", - "v50" + "v48" ], "op": "slt", "out": [ - "v51" + "v49" ] } ], @@ -1589,7 +1568,7 @@ "in": [ "v25", "phi14", - "v44" + "v42" ], "out": [ "v25" @@ -1610,12 +1589,12 @@ ], "op": "shl", "out": [ - "v48" + "v46" ] }, { "in": [ - "v48", + "v46", "0x00" ], "op": "mstore", @@ -1659,7 +1638,7 @@ ], "op": "mload", "out": [ - "v52" + "v50" ] } ], @@ -1668,7 +1647,7 @@ "v25" ], "out": [ - "v52" + "v50" ] }, "type": "BuiltinCall" diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index d1aeaed52..44a30e2e7 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -1221,24 +1221,13 @@ Yul Control Flow Graph: "type": "ConditionalJump" }, "id": "Block18", - "instructions": [ - { - "in": [ - "0x00" - ], - "op": "LiteralAssignment", - "out": [ - "v36" - ] - } - ], + "instructions": [], "liveness": { "in": [ "v25", "v31" ], "out": [ - "v36", "v25" ] } @@ -1308,8 +1297,8 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v36", - "v52" + "0x00", + "v50" ], "op": "PhiFunction", "out": [ @@ -1322,13 +1311,13 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v53" + "v51" ] }, { "in": [ "phi26", - "v53" + "v51" ], "op": "mstore", "out": [] @@ -1336,7 +1325,7 @@ Yul Control Flow Graph: { "in": [ "0x20", - "v53" + "v51" ], "op": "return", "out": [] @@ -1352,7 +1341,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v39", + "cond": "v37", "targets": [ "Block23", "Block22" @@ -1361,30 +1350,21 @@ Yul Control Flow Graph: }, "id": "Block20", "instructions": [ - { - "in": [ - "0x20" - ], - "op": "LiteralAssignment", - "out": [ - "v37" - ] - }, { "in": [], "op": "returndatasize", "out": [ - "v38" + "v36" ] }, { "in": [ - "v38", + "v36", "0x20" ], "op": "gt", "out": [ - "v39" + "v37" ] } ], @@ -1393,7 +1373,6 @@ Yul Control Flow Graph: "v25" ], "out": [ - "v37", "v25" ] }, @@ -1405,7 +1384,7 @@ Yul Control Flow Graph: "Block22" ], "exit": { - "cond": "v47", + "cond": "v45", "targets": [ "Block25", "Block24" @@ -1416,8 +1395,8 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v37", - "v40" + "0x20", + "v38" ], "op": "PhiFunction", "out": [ @@ -1430,7 +1409,7 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v41" + "v39" ] }, { @@ -1440,57 +1419,57 @@ Yul Control Flow Graph: ], "op": "add", "out": [ - "v42" + "v40" ] }, { "in": [ - "v41", - "v42" + "v39", + "v40" ], "op": "and", "out": [ - "v43" + "v41" ] }, { "in": [ - "v43", + "v41", "v25" ], "op": "add", "out": [ - "v44" + "v42" ] }, { "in": [ "v25", - "v44" + "v42" ], "op": "lt", "out": [ - "v45" + "v43" ] }, { "in": [ "0xffffffffffffffff", - "v44" + "v42" ], "op": "gt", "out": [ - "v46" + "v44" ] }, { "in": [ - "v45", - "v46" + "v43", + "v44" ], "op": "or", "out": [ - "v47" + "v45" ] } ], @@ -1502,7 +1481,7 @@ Yul Control Flow Graph: "out": [ "v25", "phi14", - "v44" + "v42" ] }, "type": "BuiltinCall" @@ -1520,7 +1499,7 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v40" + "v38" ] } ], @@ -1529,7 +1508,7 @@ Yul Control Flow Graph: "v25" ], "out": [ - "v40", + "v38", "v25" ] }, @@ -1537,7 +1516,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v51", + "cond": "v49", "targets": [ "Block28", "Block27" @@ -1548,7 +1527,7 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v44", + "v42", "0x40" ], "op": "mstore", @@ -1561,27 +1540,27 @@ Yul Control Flow Graph: ], "op": "add", "out": [ - "v49" + "v47" ] }, { "in": [ "v25", - "v49" + "v47" ], "op": "sub", "out": [ - "v50" + "v48" ] }, { "in": [ "0x20", - "v50" + "v48" ], "op": "slt", "out": [ - "v51" + "v49" ] } ], @@ -1589,7 +1568,7 @@ Yul Control Flow Graph: "in": [ "v25", "phi14", - "v44" + "v42" ], "out": [ "v25" @@ -1610,12 +1589,12 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v48" + "v46" ] }, { "in": [ - "v48", + "v46", "0x00" ], "op": "mstore", @@ -1659,7 +1638,7 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v52" + "v50" ] } ], @@ -1668,7 +1647,7 @@ Yul Control Flow Graph: "v25" ], "out": [ - "v52" + "v50" ] }, "type": "BuiltinCall" diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index 34bbf70e4..5f0555fbd 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -87,10 +87,6 @@ class StackLayoutDotExporter: public io::DotExporterBase }, [&](SSACFG::BuiltinCall const& _call) { _out << escapeLabel(_call.builtin.get().name); - }, - [&](SSACFG::LiteralAssignment const&) { - yulAssert(operation.inputs.size() == 1); - _out << escapeLabel(operation.inputs.back().str(m_cfg)); } }, operation.kind); _out << "\\l\\\n"; diff --git a/test/libyul/ssa/controlFlowGraph/complex.yul b/test/libyul/ssa/controlFlowGraph/complex.yul index 4f16122e3..9dd78ae3a 100644 --- a/test/libyul/ssa/controlFlowGraph/complex.yul +++ b/test/libyul/ssa/controlFlowGraph/complex.yul @@ -63,30 +63,29 @@ // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 17)\nLiveIn: v1[1], v0[1]\l\ -// LiveOut: v2[1], v1[1], v0[1]\l\nUsed: \l\nv2 := 0x2a\l\ -// "]; +// LiveOut: v1[1], v0[1]\l\nUsed: \l\n"]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ // Block 1; (1, max 17)\nLiveIn: phi1[4], v1[1], v0[1]\l\ // LiveOut: phi1[2], v1[1], v0[1]\l\nUsed: phi1[2]\l\nphi1 := φ(\l\ -// Block 0 => v2,\l\ -// Block 21 => v10\l\ +// Block 0 => 0x2a,\l\ +// Block 21 => v9\l\ // )\l\ -// v3 := lt(v0, phi1)\l\ +// v2 := lt(v0, phi1)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_1Exit:0 -> Block1_4 [style="solid"]; // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ // Block 2; (2, max 17)\nLiveIn: phi1[2], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v4[3], v0[1]\l\nUsed: phi1[1]\l\nv4 := mload(phi1)\l\ -// v5 := eq(0x00, v4)\l\ +// LiveOut: phi1[1], v1[1], v3[3], v0[1]\l\nUsed: phi1[1]\l\nv3 := mload(phi1)\l\ +// v4 := eq(0x00, v3)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_2Exit:0 -> Block1_7 [style="solid"]; // Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ @@ -103,11 +102,11 @@ // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7; (5, max 17)\nLiveIn: phi1[1], v1[1], v4[3], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v4[2], v0[1]\l\nUsed: v4[1]\l\nv6 := eq(0x01, v4)\l\ +// Block 7; (5, max 17)\nLiveIn: phi1[1], v1[1], v3[3], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v3[2], v0[1]\l\nUsed: v3[1]\l\nv5 := eq(0x01, v3)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_7Exit:0 -> Block1_10 [style="solid"]; // Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ @@ -117,11 +116,11 @@ // Block1_9Exit [label="FunctionReturn[0x00]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10; (7, max 17)\nLiveIn: phi1[1], v1[1], v4[2], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v4[1], v0[1]\l\nUsed: v4[1]\l\nv7 := eq(0x02, v4)\l\ +// Block 10; (7, max 17)\nLiveIn: phi1[1], v1[1], v3[2], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v3[1], v0[1]\l\nUsed: v3[1]\l\nv6 := eq(0x02, v3)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_10Exit:0 -> Block1_13 [style="solid"]; // Block1_10Exit:1 -> Block1_12 [style="solid"]; // Block1_12 [fillcolor="#FF746C", style=filled, label="\ @@ -132,11 +131,11 @@ // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13; (9, max 17)\nLiveIn: phi1[1], v1[1], v4[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: v4[1]\l\nv8 := eq(0x03, v4)\l\ +// Block 13; (9, max 17)\nLiveIn: phi1[1], v1[1], v3[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: v3[1]\l\nv7 := eq(0x03, v3)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ @@ -148,10 +147,10 @@ // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ // Block 16; (15, max 17)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nv9 := mload(v1)\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nv8 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ @@ -176,22 +175,22 @@ // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ // Block 3; (12, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: v10[1], v1[1], v0[1]\l\nUsed: phi1[1]\l\nv10 := add(0x01, phi1)\l\ -// v11 := calldataload(v10)\l\ +// LiveOut: v9[1], v1[1], v0[1]\l\nUsed: phi1[1]\l\nv9 := add(0x01, phi1)\l\ +// v10 := calldataload(v9)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v11 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit [label="{ If v10 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v10[1]\l\ -// LiveOut: \l\nUsed: v10[1]\l\nsstore(v10, 0x00)\l\ +// Block 20; (13, max 13)\nLiveIn: v9[1]\l\ +// LiveOut: \l\nUsed: v9[1]\l\nsstore(v9, 0x00)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0x00]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v10[1], v1[1], v0[1]\l\ -// LiveOut: v10[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ +// Block 21; (14, max 14)\nLiveIn: v9[1], v1[1], v0[1]\l\ +// LiveOut: v9[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/ssa/controlFlowGraph/complex2.yul b/test/libyul/ssa/controlFlowGraph/complex2.yul index d82c400e8..806f540c5 100644 --- a/test/libyul/ssa/controlFlowGraph/complex2.yul +++ b/test/libyul/ssa/controlFlowGraph/complex2.yul @@ -79,38 +79,36 @@ // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 17)\nLiveIn: v1[1], v0[1]\l\ -// LiveOut: v2[1], v1[1], v0[1]\l\nUsed: \l\nv2 := 0x2a\l\ -// "]; +// LiveOut: v1[1], v0[1]\l\nUsed: \l\n"]; // Block1_0 -> Block1_0Exit [arrowhead=none]; // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ // Block 1; (1, max 17)\nLiveIn: phi1[4], v1[1], v0[1]\l\ // LiveOut: phi1[2], v1[1], v0[1]\l\nUsed: phi1[2]\l\nphi1 := φ(\l\ -// Block 0 => v2,\l\ -// Block 21 => v10\l\ +// Block 0 => 0x2a,\l\ +// Block 21 => v9\l\ // )\l\ -// v3 := lt(v0, phi1)\l\ +// v2 := lt(v0, phi1)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_1Exit:0 -> Block1_4 [style="solid"]; // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ // Block 2; (2, max 17)\nLiveIn: phi1[2], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v4[3], v0[1]\l\nUsed: phi1[1]\l\nv4 := mload(phi1)\l\ -// v5 := eq(0x00, v4)\l\ +// LiveOut: phi1[1], v1[1], v3[3], v0[1]\l\nUsed: phi1[1]\l\nv3 := mload(phi1)\l\ +// v4 := eq(0x00, v3)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_2Exit:0 -> Block1_7 [style="solid"]; // Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ // Block 4; (4, max 4)\nLiveIn: \l\ -// LiveOut: v12[1]\l\nUsed: \l\nsstore(0x0c0c, 0x0c)\l\ -// v12 := 0x1b\l\ +// LiveOut: \l\nUsed: \l\nsstore(0x0c0c, 0x0c)\l\ // "]; -// Block1_4Exit [label="FunctionReturn[v12]"]; +// Block1_4Exit [label="FunctionReturn[0x1b]"]; // Block1_4 -> Block1_4Exit; // Block1_6 [label="\ // Block 6; (3, max 4)\nLiveIn: \l\ @@ -120,11 +118,11 @@ // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7; (5, max 17)\nLiveIn: phi1[1], v1[1], v4[3], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v4[2], v0[1]\l\nUsed: v4[1]\l\nv6 := eq(0x01, v4)\l\ +// Block 7; (5, max 17)\nLiveIn: phi1[1], v1[1], v3[3], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v3[2], v0[1]\l\nUsed: v3[1]\l\nv5 := eq(0x01, v3)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_7Exit:0 -> Block1_10 [style="solid"]; // Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ @@ -134,11 +132,11 @@ // Block1_9Exit [label="FunctionReturn[0x00]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10; (7, max 17)\nLiveIn: phi1[1], v1[1], v4[2], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v4[1], v0[1]\l\nUsed: v4[1]\l\nv7 := eq(0x02, v4)\l\ +// Block 10; (7, max 17)\nLiveIn: phi1[1], v1[1], v3[2], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v3[1], v0[1]\l\nUsed: v3[1]\l\nv6 := eq(0x02, v3)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_10Exit:0 -> Block1_13 [style="solid"]; // Block1_10Exit:1 -> Block1_12 [style="solid"]; // Block1_12 [fillcolor="#FF746C", style=filled, label="\ @@ -149,11 +147,11 @@ // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13; (9, max 17)\nLiveIn: phi1[1], v1[1], v4[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: v4[1]\l\nv8 := eq(0x03, v4)\l\ +// Block 13; (9, max 17)\nLiveIn: phi1[1], v1[1], v3[1], v0[1]\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: v3[1]\l\nv7 := eq(0x03, v3)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ @@ -165,10 +163,10 @@ // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ // Block 16; (15, max 17)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nv9 := mload(v1)\l\ +// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nv8 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ @@ -193,22 +191,22 @@ // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ // Block 3; (12, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: v10[1], v1[1], v0[1]\l\nUsed: phi1[1]\l\nv10 := add(0x01, phi1)\l\ -// v11 := calldataload(v10)\l\ +// LiveOut: v9[1], v1[1], v0[1]\l\nUsed: phi1[1]\l\nv9 := add(0x01, phi1)\l\ +// v10 := calldataload(v9)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v11 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit [label="{ If v10 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v10[1]\l\ -// LiveOut: \l\nUsed: v10[1]\l\nsstore(v10, 0x00)\l\ +// Block 20; (13, max 13)\nLiveIn: v9[1]\l\ +// LiveOut: \l\nUsed: v9[1]\l\nsstore(v9, 0x00)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0x00]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v10[1], v1[1], v0[1]\l\ -// LiveOut: v10[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ +// Block 21; (14, max 14)\nLiveIn: v9[1], v1[1], v0[1]\l\ +// LiveOut: v9[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/ssa/controlFlowGraph/default_initialized_variable.yul b/test/libyul/ssa/controlFlowGraph/default_initialized_variable.yul index 45893e8ac..56e180fe4 100644 --- a/test/libyul/ssa/controlFlowGraph/default_initialized_variable.yul +++ b/test/libyul/ssa/controlFlowGraph/default_initialized_variable.yul @@ -15,25 +15,23 @@ // Entry -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: v0[1]\l\nUsed: \l\nv0 := 0x00\l\ -// v1 := mload(0x2a)\l\ +// LiveOut: \l\nUsed: \l\nv0 := mload(0x2a)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_0Exit:0 -> Block0_2 [style="solid"]; // Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v2[1]\l\nUsed: \l\nv2 := 0x05\l\ -// "]; +// LiveOut: \l\nUsed: \l\n"]; // Block0_1 -> Block0_1Exit [arrowhead=none]; // Block0_1Exit [label="Jump" shape=oval]; // Block0_1Exit -> Block0_2 [style="solid"]; // Block0_2 [label="\ // Block 2; (2, max 2)\nLiveIn: phi0[3]\l\ // LiveOut: \l\nUsed: phi0[3]\l\nphi0 := φ(\l\ -// Block 0 => v0,\l\ -// Block 1 => v2\l\ +// Block 0 => 0x00,\l\ +// Block 1 => 0x05\l\ // )\l\ // sstore(phi0, phi0)\l\ // "]; diff --git a/test/libyul/ssa/controlFlowGraph/function.yul b/test/libyul/ssa/controlFlowGraph/function.yul index e2140d316..a2e842699 100644 --- a/test/libyul/ssa/controlFlowGraph/function.yul +++ b/test/libyul/ssa/controlFlowGraph/function.yul @@ -67,9 +67,7 @@ // FunctionEntry_i_0 -> Block4_0; // Block4_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v0[1], v1[1]\l\nUsed: \l\nv0 := 0x0202\l\ -// v1 := 0x0303\l\ -// "]; -// Block4_0Exit [label="FunctionReturn[v0, v1]"]; +// LiveOut: \l\nUsed: \l\n"]; +// Block4_0Exit [label="FunctionReturn[0x0202, 0x0303]"]; // Block4_0 -> Block4_0Exit; // } diff --git a/test/libyul/ssa/controlFlowGraph/nested_for.yul b/test/libyul/ssa/controlFlowGraph/nested_for.yul index 55edb2ea6..0060ee30f 100644 --- a/test/libyul/ssa/controlFlowGraph/nested_for.yul +++ b/test/libyul/ssa/controlFlowGraph/nested_for.yul @@ -27,27 +27,25 @@ // Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 24)\nLiveIn: \l\ -// LiveOut: v0[1]\l\nUsed: \l\nv0 := 0x00\l\ -// "]; +// LiveOut: \l\nUsed: \l\n"]; // Block0_0 -> Block0_0Exit [arrowhead=none]; // Block0_0Exit [label="Jump" shape=oval]; // Block0_0Exit -> Block0_1 [style="solid"]; // Block0_1 [fillcolor="#FF746C", style=filled, label="\ // Block 1; (1, max 24)\nLiveIn: phi0[3]\l\ // LiveOut: phi0[1]\l\nUsed: phi0[2]\l\nphi0 := φ(\l\ -// Block 0 => v0,\l\ -// Block 3 => v20\l\ +// Block 0 => 0x00,\l\ +// Block 3 => v15\l\ // )\l\ -// v1 := lt(0x03, phi0)\l\ +// v0 := lt(0x03, phi0)\l\ // "]; // Block0_1 -> Block0_1Exit; -// Block0_1Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_1Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_1Exit:0 -> Block0_4 [style="solid"]; // Block0_1Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ // Block 2; (2, max 23)\nLiveIn: phi0[1]\l\ -// LiveOut: v2[1], phi0[1]\l\nUsed: \l\nv2 := 0x00\l\ -// "]; +// LiveOut: phi0[1]\l\nUsed: \l\n"]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; // Block0_2Exit -> Block0_5 [style="solid"]; @@ -59,19 +57,18 @@ // Block0_5 [label="\ // Block 5; (3, max 23)\nLiveIn: phi1[3], phi0[1]\l\ // LiveOut: phi1[1], phi0[1]\l\nUsed: phi1[2]\l\nphi1 := φ(\l\ -// Block 2 => v2,\l\ -// Block 7 => v19\l\ +// Block 2 => 0x00,\l\ +// Block 7 => v14\l\ // )\l\ -// v3 := lt(0x03, phi1)\l\ +// v1 := lt(0x03, phi1)\l\ // "]; // Block0_5 -> Block0_5Exit; -// Block0_5Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_5Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_5Exit:0 -> Block0_8 [style="solid"]; // Block0_5Exit:1 -> Block0_6 [style="solid"]; // Block0_6 [label="\ // Block 6; (4, max 21)\nLiveIn: phi1[1], phi0[1]\l\ -// LiveOut: v4[1], phi1[1], phi0[1]\l\nUsed: \l\nv4 := 0x00\l\ -// "]; +// LiveOut: phi1[1], phi0[1]\l\nUsed: \l\n"]; // Block0_6 -> Block0_6Exit [arrowhead=none]; // Block0_6Exit [label="Jump" shape=oval]; // Block0_6Exit -> Block0_9 [style="solid"]; @@ -84,28 +81,28 @@ // Block0_9 [label="\ // Block 9; (5, max 21)\nLiveIn: phi2[3], phi1[1], phi0[1]\l\ // LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: phi2[2]\l\nphi2 := φ(\l\ -// Block 6 => v4,\l\ -// Block 11 => v18\l\ +// Block 6 => 0x00,\l\ +// Block 11 => v13\l\ // )\l\ -// v5 := lt(0x03, phi2)\l\ +// v2 := lt(0x03, phi2)\l\ // "]; // Block0_9 -> Block0_9Exit; -// Block0_9Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_9Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_9Exit:0 -> Block0_12 [style="solid"]; // Block0_9Exit:1 -> Block0_10 [style="solid"]; // Block0_3 [label="\ // Block 3; (23, max 23)\nLiveIn: phi0[1]\l\ -// LiveOut: v20[1]\l\nUsed: phi0[1]\l\nv20 := add(0x01, phi0)\l\ +// LiveOut: v15[1]\l\nUsed: phi0[1]\l\nv15 := add(0x01, phi0)\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; // Block0_3Exit -> Block0_1 [style="dashed"]; // Block0_10 [label="\ // Block 10; (6, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv6 := mload(0x00)\l\ +// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv3 := mload(0x00)\l\ // "]; // Block0_10 -> Block0_10Exit; -// Block0_10Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_10Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_10Exit:0 -> Block0_14 [style="solid"]; // Block0_10Exit:1 -> Block0_13 [style="solid"]; // Block0_12 [label="\ @@ -116,22 +113,21 @@ // Block0_12Exit -> Block0_7 [style="solid"]; // Block0_13 [label="\ // Block 13; (7, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: v7[1], phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv7 := 0x00\l\ -// "]; +// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\n"]; // Block0_13 -> Block0_13Exit [arrowhead=none]; // Block0_13Exit [label="Jump" shape=oval]; // Block0_13Exit -> Block0_15 [style="solid"]; // Block0_14 [label="\ // Block 14; (12, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv12 := mload(0x01)\l\ +// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv8 := mload(0x01)\l\ // "]; // Block0_14 -> Block0_14Exit; -// Block0_14Exit [label="{ If v12 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_14Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_14Exit:0 -> Block0_20 [style="solid"]; // Block0_14Exit:1 -> Block0_19 [style="solid"]; // Block0_7 [label="\ // Block 7; (21, max 21)\nLiveIn: phi1[1], phi0[1]\l\ -// LiveOut: v19[1], phi0[1]\l\nUsed: phi1[1]\l\nv19 := add(0x01, phi1)\l\ +// LiveOut: v14[1], phi0[1]\l\nUsed: phi1[1]\l\nv14 := add(0x01, phi1)\l\ // "]; // Block0_7 -> Block0_7Exit [arrowhead=none]; // Block0_7Exit [label="Jump" shape=oval]; @@ -139,19 +135,18 @@ // Block0_15 [label="\ // Block 15; (8, max 19)\nLiveIn: phi3[4], phi2[1], phi1[1], phi0[1]\l\ // LiveOut: phi3[2], phi2[1], phi1[1], phi0[1]\l\nUsed: phi3[2]\l\nphi3 := φ(\l\ -// Block 13 => v7,\l\ -// Block 17 => v11\l\ +// Block 13 => 0x00,\l\ +// Block 17 => v7\l\ // )\l\ -// v8 := lt(0x03, phi3)\l\ +// v4 := lt(0x03, phi3)\l\ // "]; // Block0_15 -> Block0_15Exit; -// Block0_15Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_15Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_15Exit:0 -> Block0_18 [style="solid"]; // Block0_15Exit:1 -> Block0_16 [style="solid"]; // Block0_19 [label="\ // Block 19; (13, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: v13[1], phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv13 := 0x00\l\ -// "]; +// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\n"]; // Block0_19 -> Block0_19Exit [arrowhead=none]; // Block0_19Exit [label="Jump" shape=oval]; // Block0_19Exit -> Block0_21 [style="solid"]; @@ -163,9 +158,9 @@ // Block0_20Exit -> Block0_11 [style="solid"]; // Block0_16 [label="\ // Block 16; (9, max 10)\nLiveIn: phi3[2], phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi3[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi3[1]\l\nv9 := add(phi1, phi0)\l\ -// v10 := add(phi2, v9)\l\ -// sstore(v10, phi3)\l\ +// LiveOut: phi3[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi3[1]\l\nv5 := add(phi1, phi0)\l\ +// v6 := add(phi2, v5)\l\ +// sstore(v6, phi3)\l\ // "]; // Block0_16 -> Block0_16Exit [arrowhead=none]; // Block0_16Exit [label="Jump" shape=oval]; @@ -179,34 +174,34 @@ // Block0_21 [label="\ // Block 21; (14, max 19)\nLiveIn: phi9[4], phi2[1], phi1[1], phi0[1]\l\ // LiveOut: phi9[2], phi2[1], phi1[1], phi0[1]\l\nUsed: phi9[2]\l\nphi9 := φ(\l\ -// Block 19 => v13,\l\ -// Block 23 => v17\l\ +// Block 19 => 0x00,\l\ +// Block 23 => v12\l\ // )\l\ -// v14 := lt(0x03, phi9)\l\ +// v9 := lt(0x03, phi9)\l\ // "]; // Block0_21 -> Block0_21Exit; -// Block0_21Exit [label="{ If v14 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_21Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_21Exit:0 -> Block0_24 [style="solid"]; // Block0_21Exit:1 -> Block0_22 [style="solid"]; // Block0_11 [label="\ // Block 11; (19, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: v18[1], phi1[1], phi0[1]\l\nUsed: phi2[1]\l\nv18 := add(0x01, phi2)\l\ +// LiveOut: v13[1], phi1[1], phi0[1]\l\nUsed: phi2[1]\l\nv13 := add(0x01, phi2)\l\ // "]; // Block0_11 -> Block0_11Exit [arrowhead=none]; // Block0_11Exit [label="Jump" shape=oval]; // Block0_11Exit -> Block0_9 [style="dashed"]; // Block0_17 [label="\ // Block 17; (10, max 10)\nLiveIn: phi3[1], phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: v11[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi3[1]\l\nv11 := add(0x01, phi3)\l\ +// LiveOut: v7[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi3[1]\l\nv7 := add(0x01, phi3)\l\ // "]; // Block0_17 -> Block0_17Exit [arrowhead=none]; // Block0_17Exit [label="Jump" shape=oval]; // Block0_17Exit -> Block0_15 [style="dashed"]; // Block0_22 [label="\ // Block 22; (15, max 16)\nLiveIn: phi9[2], phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi9[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi9[1]\l\nv15 := add(phi1, phi0)\l\ -// v16 := add(phi2, v15)\l\ -// sstore(v16, phi9)\l\ +// LiveOut: phi9[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi9[1]\l\nv10 := add(phi1, phi0)\l\ +// v11 := add(phi2, v10)\l\ +// sstore(v11, phi9)\l\ // "]; // Block0_22 -> Block0_22Exit [arrowhead=none]; // Block0_22Exit [label="Jump" shape=oval]; @@ -219,7 +214,7 @@ // Block0_24Exit -> Block0_20 [style="solid"]; // Block0_23 [label="\ // Block 23; (16, max 16)\nLiveIn: phi9[1], phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: v17[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi9[1]\l\nv17 := add(0x01, phi9)\l\ +// LiveOut: v12[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi9[1]\l\nv12 := add(0x01, phi9)\l\ // "]; // Block0_23 -> Block0_23Exit [arrowhead=none]; // Block0_23Exit [label="Jump" shape=oval]; diff --git a/test/libyul/ssa/controlFlowGraph/nested_function.yul b/test/libyul/ssa/controlFlowGraph/nested_function.yul index 876768d66..743136adb 100644 --- a/test/libyul/ssa/controlFlowGraph/nested_function.yul +++ b/test/libyul/ssa/controlFlowGraph/nested_function.yul @@ -78,9 +78,8 @@ // FunctionEntry_w_0 -> Block4_0; // Block4_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v0[1]\l\nUsed: \l\nv0 := 0x01\l\ -// "]; -// Block4_0Exit [label="FunctionReturn[v0]"]; +// LiveOut: \l\nUsed: \l\n"]; +// Block4_0Exit [label="FunctionReturn[0x01]"]; // Block4_0 -> Block4_0Exit; // FunctionEntry_v_0 [label="function v: // r := v()"]; @@ -96,9 +95,8 @@ // FunctionEntry_w_0 -> Block6_0; // Block6_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v0[1]\l\nUsed: \l\nv0 := 0x11\l\ -// "]; -// Block6_0Exit [label="FunctionReturn[v0]"]; +// LiveOut: \l\nUsed: \l\n"]; +// Block6_0Exit [label="FunctionReturn[0x11]"]; // Block6_0 -> Block6_0Exit; // FunctionEntry_cycle1_0 [label="function cycle1: // r := cycle1()"]; From 454215a44a3389a6be794dcd908c693de90221f5 Mon Sep 17 00:00:00 2001 From: blishko Date: Wed, 22 Apr 2026 07:16:00 +0200 Subject: [PATCH 1270/1340] SSA: Add test case with suboptimal behaviour In this case, the shuffler is currently making too many swaps. --- .../ssa/stackShuffler/grow_and_shuffle.stack | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 test/libyul/ssa/stackShuffler/grow_and_shuffle.stack diff --git a/test/libyul/ssa/stackShuffler/grow_and_shuffle.stack b/test/libyul/ssa/stackShuffler/grow_and_shuffle.stack new file mode 100644 index 000000000..13349ce8c --- /dev/null +++ b/test/libyul/ssa/stackShuffler/grow_and_shuffle.stack @@ -0,0 +1,20 @@ +// Grow the stack and shuffle value to the correct places. Should be doable with 3 swaps, 3 dups and 1 push +initial: [v2, lit2, v3, v1] +targetStackTop: [v2, lit1, v2, lit2, v2, lit1, v1, v3] +// ---- +// | 0 1 2 3 4 5 6 7 +// +-------------------------------------------------------- +// (initial)| v2 lit2 v3 v1 +// DUP4| v2 lit2 v3 v1 v2 +// SWAP3| v2 v2 v3 v1 lit2 +// SWAP1| v2 v2 v3 lit2 v1 +// SWAP3| v2 v1 v3 lit2 v2 +// SWAP2| v2 v1 v2 lit2 v3 +// PUSH lit1| v2 v1 v2 lit2 v3 lit1 +// DUP1| v2 v1 v2 lit2 v3 lit1 lit1 +// SWAP5| v2 lit1 v2 lit2 v3 lit1 v1 +// DUP5| v2 lit1 v2 lit2 v3 lit1 v1 v2 +// SWAP3| v2 lit1 v2 lit2 v2 lit1 v1 v3 +// +-------------------------------------------------------- +// (target)| v2 lit1 v2 lit2 v2 lit1 v1 v3 +// Status: Admissible From 7fc062db2db0427b30ba2f59b963e44a92bec3c7 Mon Sep 17 00:00:00 2001 From: blishko Date: Wed, 22 Apr 2026 08:38:36 +0200 Subject: [PATCH 1271/1340] SSA: Improve shuffler When trying to fix the args portion of the stack, before we grow the stack, we are trying to locally improve by attempting to shuffle current args to the right place. We can add one more attempt: If everything else failed, we can try to fix the top slot, even if it does not fix the slot from which we are swapping to the top. The test case `grow_and_shuffle.stack` demonstrates the improvement. This change also improves the deposit contract. --- libyul/backends/evm/ssa/StackShuffler.h | 15 +++++++++++++++ .../externalContracts/deposit_contract.sol | 12 ++++++------ .../ssa/stackShuffler/grow_and_shuffle.stack | 17 +++++++---------- .../satisfy_tail_requirements.stack | 6 +++--- .../stackShuffler/spill_to_pop_deep_junk.stack | 6 +++--- .../spilled_to_pop_deep_junk.stack | 10 +++++----- 6 files changed, 39 insertions(+), 27 deletions(-) diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index ac095346e..0d77c9556 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -580,6 +580,21 @@ class StackShuffler } } } + // If there were no other swapping opportunities, try fixing at least the top before we start pushing + // more stuff on stack + if (!_state.isArgsCompatible(stackTop, stackTop)) + for (StackOffset offset: _state.stackArgsRange()) + if ( + offset != stackTop && + _stack[offset] != _stack[stackTop] && // don't swap identical values (no-op) + _stack.isValidSwapTarget(offset) && + !_state.isArgsCompatible(offset, offset) && + _state.isArgsCompatible(offset, stackTop) + ) + { + _stack.swap(offset); + return {ShuffleHelperResult::Status::StackModified}; + } } // dup up whatever is missing diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol index fb186b481..6755c79ee 100644 --- a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -185,8 +185,8 @@ contract DepositContract is IDepositContract, ERC165 { // gas legacy code: 1438800 // gas legacyOptimized: 848699 // gas legacyOptimized code: 878200 -// gas ssaCFGOptimized: 809592 -// gas ssaCFGOptimized code: 569200 +// gas ssaCFGOptimized: 809403 +// gas ssaCFGOptimized code: 568200 // supportsInterface(bytes4): 0x0 -> 0 // supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # // supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # @@ -195,14 +195,14 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 -// gas ssaCFGOptimized: 109748 +// gas ssaCFGOptimized: 109652 // get_deposit_count() -> 0x20, 8, 0 # TODO: check balance and logs after each deposit # // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # // get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e // gas irOptimized: 109178 // gas legacy: 142741 // gas legacyOptimized: 117558 -// gas ssaCFGOptimized: 109748 +// gas ssaCFGOptimized: 109652 // get_deposit_count() -> 0x20, 8, 0 // deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0xf50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x08, 0xca9a3b00000000000000000000000000000000000000000000000000000000, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8, 0x08, 0x00 @@ -210,7 +210,7 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 109741 +// gas ssaCFGOptimized: 109645 // get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 // deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # // ~ emit DepositEvent(bytes,bytes,bytes,bytes,bytes): 0xa0, 0x0100, 0x0140, 0x0180, 0x0200, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x08, 0x40597307000000000000000000000000000000000000000000000000000000, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d, 0x08, 0x0100000000000000000000000000000000000000000000000000000000000000 @@ -218,5 +218,5 @@ contract DepositContract is IDepositContract, ERC165 { // gas irOptimized: 109174 // gas legacy: 142750 // gas legacyOptimized: 117570 -// gas ssaCFGOptimized: 109741 +// gas ssaCFGOptimized: 109645 // get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/libyul/ssa/stackShuffler/grow_and_shuffle.stack b/test/libyul/ssa/stackShuffler/grow_and_shuffle.stack index 13349ce8c..bcd06607d 100644 --- a/test/libyul/ssa/stackShuffler/grow_and_shuffle.stack +++ b/test/libyul/ssa/stackShuffler/grow_and_shuffle.stack @@ -5,16 +5,13 @@ targetStackTop: [v2, lit1, v2, lit2, v2, lit1, v1, v3] // | 0 1 2 3 4 5 6 7 // +-------------------------------------------------------- // (initial)| v2 lit2 v3 v1 -// DUP4| v2 lit2 v3 v1 v2 -// SWAP3| v2 v2 v3 v1 lit2 -// SWAP1| v2 v2 v3 lit2 v1 -// SWAP3| v2 v1 v3 lit2 v2 -// SWAP2| v2 v1 v2 lit2 v3 -// PUSH lit1| v2 v1 v2 lit2 v3 lit1 -// DUP1| v2 v1 v2 lit2 v3 lit1 lit1 -// SWAP5| v2 lit1 v2 lit2 v3 lit1 v1 -// DUP5| v2 lit1 v2 lit2 v3 lit1 v1 v2 -// SWAP3| v2 lit1 v2 lit2 v2 lit1 v1 v3 +// SWAP2| v2 v1 v3 lit2 +// DUP4| v2 v1 v3 lit2 v2 +// PUSH lit1| v2 v1 v3 lit2 v2 lit1 +// DUP1| v2 v1 v3 lit2 v2 lit1 lit1 +// SWAP5| v2 lit1 v3 lit2 v2 lit1 v1 +// DUP3| v2 lit1 v3 lit2 v2 lit1 v1 v2 +// SWAP5| v2 lit1 v2 lit2 v2 lit1 v1 v3 // +-------------------------------------------------------- // (target)| v2 lit1 v2 lit2 v2 lit1 v1 v3 // Status: Admissible diff --git a/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack b/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack index a97447af9..55870a238 100644 --- a/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack +++ b/test/libyul/ssa/stackShuffler/satisfy_tail_requirements.stack @@ -8,9 +8,9 @@ targetStackSize: 17 // +------------------------------------------------- +---------------------------------------------------------------------- // (initial)| v2 v3 v4 v5 v6 v7 v8 | v9 v10 // SWAP8| v10 v3 v4 v5 v6 v7 v8 | v9 v2 -// PUSH lit3| v10 v3 v4 v5 v6 v7 v8 | v9 v2 lit3 -// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v2 v9 -// SWAP1| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v2 +// SWAP1| v10 v3 v4 v5 v6 v7 v8 | v2 v9 +// PUSH lit3| v10 v3 v4 v5 v6 v7 v8 | v2 v9 lit3 +// SWAP2| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v2 // DUP4| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v2 v8 // SWAP1| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v2 // DUP6| v10 v3 v4 v5 v6 v7 v8 | lit3 v9 v8 v2 v7 diff --git a/test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack b/test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack index c66f09fc6..c491f6b52 100644 --- a/test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack +++ b/test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack @@ -31,9 +31,9 @@ targetStackTop: [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v1 // SWAP15| v1 v2 * v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 // SWAP13| v1 v2 * v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v3 // SWAP14| v1 v2 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 * -// PUSH v4| v1 v2 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 * v4 -// SWAP14| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 * v17 -// SWAP1| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 * +// SWAP13| v1 v2 v3 * v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 +// PUSH v4| v1 v2 v3 * v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v4 +// SWAP14| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 * // PUSH v18| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 * v18 // SWAP1| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 * // PUSH v19| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 * v19 diff --git a/test/libyul/ssa/stackShuffler/spilled_to_pop_deep_junk.stack b/test/libyul/ssa/stackShuffler/spilled_to_pop_deep_junk.stack index 42fe6acfb..a688e3b1a 100644 --- a/test/libyul/ssa/stackShuffler/spilled_to_pop_deep_junk.stack +++ b/test/libyul/ssa/stackShuffler/spilled_to_pop_deep_junk.stack @@ -30,11 +30,11 @@ targetStackTop: [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v1 // POP| * v18 v19 v3 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 // SWAP13| * v18 v19 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v3 // SWAP14| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 -// PUSH v1| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 v1 -// POP| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 -// PUSH v1| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 v1 -// POP| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 -// PUSH v1| * v18 v3 v17 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v19 v1 +// SWAP13| * v18 v3 v19 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 +// PUSH v1| * v18 v3 v19 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v1 +// POP| * v18 v3 v19 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 +// PUSH v1| * v18 v3 v19 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v1 +// POP| * v18 v3 v19 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 // ...| // +-------------------------------------------------------------------------------------------------------------------------------------------- +------- // (target)| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | From 607a379b41cb14edca5fda6a9c646129e8197b0a Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:08:04 +0200 Subject: [PATCH 1272/1340] SSA CFG: introduce SSACFG::name and isMainGraph() --- libyul/backends/evm/ssa/CodeTransform.cpp | 6 +++--- libyul/backends/evm/ssa/ControlFlow.h | 2 +- libyul/backends/evm/ssa/SSACFG.cpp | 4 ++-- libyul/backends/evm/ssa/SSACFG.h | 4 +++- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 1 + libyul/backends/evm/ssa/SSACFGTypes.h | 2 ++ libyul/backends/evm/ssa/StackLayoutGenerator.cpp | 4 ++-- 7 files changed, 14 insertions(+), 9 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 1d2044f79..7e41b58ab 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -151,8 +151,8 @@ CodeTransform::CodeTransform( m_assembly.setStackHeight(static_cast(_function->numArguments) + (m_cfg.canContinue ? 1 : 0)); } StackData expectedStackTop; - expectedStackTop.reserve(m_cfg.arguments.size() + (m_cfg.function && m_cfg.canContinue ? 1 : 0)); - if (m_cfg.function && m_cfg.canContinue) + expectedStackTop.reserve(m_cfg.arguments.size() + (!m_cfg.isMainGraph() && m_cfg.canContinue ? 1 : 0)); + if (!m_cfg.isMainGraph() && m_cfg.canContinue) expectedStackTop.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); for (auto const& [_, valueID]: m_cfg.arguments | ranges::views::reverse) expectedStackTop.push_back(StackSlot::makeValueID(valueID)); @@ -359,7 +359,7 @@ void CodeTransform::operator()(SSACFG::BlockId const&, SSACFG::BasicBlock::Funct yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); // Each CodeTransform instance handles exactly one function's CFG, so a FunctionReturn exit // here necessarily belongs to m_cfg.function. No identity cross-check is needed. - yulAssert(m_cfg.function); + yulAssert(!m_cfg.isMainGraph()); yulAssert(m_cfg.canContinue); yulAssert(m_stack.size() == _functionReturn.returnValues.size() + 1, "There must be at least the function return label element on stack"); yulAssert(m_stack.top().isFunctionReturnLabel()); diff --git a/libyul/backends/evm/ssa/ControlFlow.h b/libyul/backends/evm/ssa/ControlFlow.h index ea07d4d4e..9c744ee8b 100644 --- a/libyul/backends/evm/ssa/ControlFlow.h +++ b/libyul/backends/evm/ssa/ControlFlow.h @@ -42,7 +42,7 @@ struct ControlFlowLiveness{ struct ControlFlow { - using FunctionGraphID = std::uint32_t; + using FunctionGraphID = ssa::FunctionGraphID; static FunctionGraphID constexpr mainGraphID() noexcept { return 0; } diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 582bfaf2e..8b89d9f4b 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -165,8 +165,8 @@ std::string SSACFG::toDot( LivenessAnalysis const* _liveness ) const { - SSACFGDotExporter exporter(*this, _functionIndex.value_or(function ? 1 : 0), _liveness); - if (function) + SSACFGDotExporter exporter(*this, _functionIndex.value_or(isMainGraph() ? 0 : 1), _liveness); + if (!isMainGraph()) return exporter.exportFunction(*function, _includeDiGraphDefinition); else return exporter.exportBlocks(entry, _includeDiGraphDefinition); diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index e01f8078f..ac269d390 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -275,13 +275,15 @@ class SSACFG std::unique_ptr debugInfo; BlockId entry = BlockId{0}; std::set exits; - Scope::Function const* function = nullptr; + std::string name{}; bool canContinue = true; std::vector, ValueId>> arguments; std::vector> returns; std::vector> functions; // Container for artificial calls generated for switch statements. std::list ghostCalls; + + bool isMainGraph() const { return name.empty(); } }; } diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index cf1ddea7f..70495e35d 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -122,6 +122,7 @@ void SSACFGBuilder::buildFunctionGraph( if (cfg.debugInfo) cfg.debugInfo->graphDebugData = _functionDefinition->debugData; cfg.function = _function; + cfg.name = _function->name.str(); cfg.canContinue = m_sideEffects.functionSideEffects().at(_functionDefinition).canContinue; cfg.arguments = arguments; cfg.returns = returns; diff --git a/libyul/backends/evm/ssa/SSACFGTypes.h b/libyul/backends/evm/ssa/SSACFGTypes.h index a2dde80d1..6be70af7f 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.h +++ b/libyul/backends/evm/ssa/SSACFGTypes.h @@ -34,6 +34,8 @@ namespace solidity::yul::ssa class SSACFG; +using FunctionGraphID = std::uint32_t; + struct BlockId { using ValueType = std::uint32_t; diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index ff6b896c6..a7076edc0 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -97,7 +97,7 @@ StackLayoutGenerator::StackLayoutGenerator( m_liveness(_liveness), m_callSites(_callSites), m_graphID(_graphID), - m_hasFunctionReturnLabel(_liveness.cfg().function && _liveness.cfg().canContinue), + m_hasFunctionReturnLabel(!_liveness.cfg().isMainGraph() && _liveness.cfg().canContinue), m_junkAdmittingBlocksFinder(std::make_unique(_liveness.cfg(), _liveness.topologicalSort())), m_inputStackProposalsPerBlock(m_cfg.numBlocks()), m_resultLayout(m_cfg.numBlocks()) @@ -144,7 +144,7 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) if (_blockId == m_cfg.entry) { - if (m_cfg.function) + if (!m_cfg.isMainGraph()) { blockLayout.stackIn.reserve(m_cfg.arguments.size() + (m_hasFunctionReturnLabel ? 1u : 0u)); if (m_hasFunctionReturnLabel) From bac374de7841b549a32928b27aa037627bad7d26 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:13:23 +0200 Subject: [PATCH 1273/1340] SSA CFG: replace Call::function (Scope::Function ref) with FunctionGraphID Calls now identify the callee by FunctionGraphID instead of by a Scope::Function reference: - SSACFGBuilder allocates the graph slot up front in registerFunctionDefinition - ControlFlow drops functionGraphMapping and the functionGraph(Scope::Function const*) lookup - CodeTransform's FunctionLabels are re-keyed by FunctionGraphID - Dot and JSON exporters thread a ControlFlow reference so names can be resolved from the graph. --- libyul/backends/evm/ssa/CodeTransform.cpp | 61 +++++---- libyul/backends/evm/ssa/CodeTransform.h | 5 +- libyul/backends/evm/ssa/ControlFlow.h | 15 +-- libyul/backends/evm/ssa/SSACFG.cpp | 20 ++- libyul/backends/evm/ssa/SSACFG.h | 6 +- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 30 +++-- libyul/backends/evm/ssa/SSACFGBuilder.h | 3 + libyul/backends/evm/ssa/io/JSONExporter.cpp | 33 +++-- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 17 ++- .../ssa/controlFlowGraph/nested_function.yul | 120 +++++++++--------- 10 files changed, 174 insertions(+), 136 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 7e41b58ab..041d674c7 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -53,11 +53,12 @@ void CodeTransform::run yulAssert(controlFlow.functionGraphs.size() == _controlFlowLiveness.cfgLiveness.size()); FunctionLabels const functionLabels = registerFunctionLabels(_assembly, controlFlow); - for (std::size_t functionIndex = 0; functionIndex < controlFlow.functionGraphMapping.size(); ++functionIndex) + for (std::size_t functionIndex = 0; functionIndex < controlFlow.functionGraphs.size(); ++functionIndex) { - auto const& [function, cfg] = controlFlow.functionGraphMapping[functionIndex]; - yulAssert(cfg); - auto const callSites = gatherCallSites(*cfg); + std::unique_ptr const& functionGraphPtr = controlFlow.functionGraphs[functionIndex]; + yulAssert(functionGraphPtr); + SSACFG const& cfg = *functionGraphPtr; + auto const callSites = gatherCallSites(cfg); auto const& liveness = _controlFlowLiveness.cfgLiveness[functionIndex]; yulAssert(liveness); auto const graphID = static_cast(functionIndex); @@ -65,14 +66,14 @@ void CodeTransform::run CodeTransform transform( _assembly, _builtinContext, + controlFlow, functionLabels, callSites, - *cfg, + cfg, stackLayout, - function, graphID ); - transform(cfg->entry); + transform(cfg.entry); } } @@ -80,23 +81,27 @@ CodeTransform::FunctionLabels CodeTransform::registerFunctionLabels( AbstractAssembly& _assembly, ControlFlow const& _controlFlow) { FunctionLabels functionLabels; - std::set assignedFunctionNames; + std::set assignedFunctionNames; - for (auto const& [_function, _functionGraph]: _controlFlow.functionGraphMapping) + for (std::size_t index = 0; index < _controlFlow.functionGraphs.size(); ++index) { - if (!_function) + std::unique_ptr const& functionGraphPtr = _controlFlow.functionGraphs[index]; + yulAssert(functionGraphPtr); + SSACFG const& functionGraph = *functionGraphPtr; + if (functionGraph.isMainGraph()) continue; - bool nameAlreadySeen = !assignedFunctionNames.insert(_function->name).second; + auto const graphID = static_cast(index); + bool const nameAlreadySeen = !assignedFunctionNames.insert(functionGraph.name).second; auto const sourceID = [&]() -> std::optional { - if (_functionGraph->debugInfo && _functionGraph->debugInfo->graphDebugData) - return _functionGraph->debugInfo->graphDebugData->astID; + if (functionGraph.debugInfo && functionGraph.debugInfo->graphDebugData) + return functionGraph.debugInfo->graphDebugData->astID; return std::nullopt; }(); - functionLabels[_function] = !nameAlreadySeen ? + functionLabels[graphID] = !nameAlreadySeen ? _assembly.namedLabel( - _function->name.str(), - _functionGraph->arguments.size(), - _functionGraph->returns.size(), + functionGraph.name, + functionGraph.arguments.size(), + functionGraph.returns.size(), sourceID ) : _assembly.newLabelId(); @@ -107,15 +112,16 @@ CodeTransform::FunctionLabels CodeTransform::registerFunctionLabels( CodeTransform::CodeTransform( AbstractAssembly& _assembly, BuiltinContext& _builtinContext, + ControlFlow const& _controlFlow, FunctionLabels const& _functionLabels, CallSites const& _callSites, SSACFG const& _cfg, SSACFGStackLayout const& _stackLayout, - Scope::Function const* _function, ControlFlow::FunctionGraphID _graphID ): m_assembly(_assembly), m_builtinContext(_builtinContext), + m_controlFlow(_controlFlow), m_functionLabels(_functionLabels), m_callSites(_callSites), m_cfg(_cfg), @@ -143,17 +149,18 @@ CodeTransform::CodeTransform( }()), m_stack(m_stackData, m_assemblyCallbacks) { - if (_function) + bool const isFunctionGraph = !m_cfg.isMainGraph(); + if (isFunctionGraph) { - auto const findIt = m_functionLabels.find(_function); + auto const findIt = m_functionLabels.find(_graphID); yulAssert(findIt != m_functionLabels.end()); m_assembly.appendLabel(findIt->second); - m_assembly.setStackHeight(static_cast(_function->numArguments) + (m_cfg.canContinue ? 1 : 0)); + m_assembly.setStackHeight(static_cast(m_cfg.arguments.size()) + (m_cfg.canContinue ? 1 : 0)); } StackData expectedStackTop; - expectedStackTop.reserve(m_cfg.arguments.size() + (!m_cfg.isMainGraph() && m_cfg.canContinue ? 1 : 0)); - if (!m_cfg.isMainGraph() && m_cfg.canContinue) - expectedStackTop.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); + expectedStackTop.reserve(m_cfg.arguments.size() + (isFunctionGraph && m_cfg.canContinue ? 1 : 0)); + if (isFunctionGraph && m_cfg.canContinue) + expectedStackTop.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); for (auto const& [_, valueID]: m_cfg.arguments | ranges::views::reverse) expectedStackTop.push_back(StackSlot::makeValueID(valueID)); assertLayoutCompatibility(m_stack.data(), expectedStackTop); @@ -266,9 +273,11 @@ void CodeTransform::operator()(SSACFG::OperationId _opId, StackData const& _oper // check that if we have a return label, the call can continue yulAssert(!!returnLabel == _call.canContinue); m_assembly.setSourceLocation(opOriginLocation); + SSACFG const* calleeCFG = m_controlFlow.functionGraph(_call.graphID); + yulAssert(calleeCFG); m_assembly.appendJumpTo( - m_functionLabels.at(&_call.function.get()), - static_cast(_call.function.get().numReturns - _call.function.get().numArguments) - (_call.canContinue ? 1 : 0), + m_functionLabels.at(_call.graphID), + static_cast(calleeCFG->numReturns) - static_cast(calleeCFG->arguments.size()) - (_call.canContinue ? 1 : 0), AbstractAssembly::JumpType::IntoFunction ); // if we have a return label, append it to assembly and pop the label from the stack diff --git a/libyul/backends/evm/ssa/CodeTransform.h b/libyul/backends/evm/ssa/CodeTransform.h index 48d74ffd6..be72effed 100644 --- a/libyul/backends/evm/ssa/CodeTransform.h +++ b/libyul/backends/evm/ssa/CodeTransform.h @@ -100,7 +100,7 @@ class CodeTransform ); private: - using FunctionLabels = std::map; + using FunctionLabels = std::map; static FunctionLabels registerFunctionLabels( AbstractAssembly& _assembly, @@ -110,11 +110,11 @@ class CodeTransform CodeTransform( AbstractAssembly& _assembly, BuiltinContext& _builtinContext, + ControlFlow const& _controlFlow, FunctionLabels const& _functionLabels, CallSites const& _callSites, SSACFG const& _cfg, SSACFGStackLayout const& _stackLayout, - Scope::Function const* _function, ControlFlow::FunctionGraphID _graphID); void operator()(SSACFG::BlockId _blockId); @@ -129,6 +129,7 @@ class CodeTransform AbstractAssembly& m_assembly; BuiltinContext& m_builtinContext; + ControlFlow const& m_controlFlow; FunctionLabels const& m_functionLabels; CallSites const& m_callSites; SSACFG const& m_cfg; diff --git a/libyul/backends/evm/ssa/ControlFlow.h b/libyul/backends/evm/ssa/ControlFlow.h index 9c744ee8b..21abfe274 100644 --- a/libyul/backends/evm/ssa/ControlFlow.h +++ b/libyul/backends/evm/ssa/ControlFlow.h @@ -22,9 +22,6 @@ #include #include -#include - -#include namespace solidity::yul::ssa { @@ -48,14 +45,6 @@ struct ControlFlow SSACFG const* mainGraph() const { return functionGraph(mainGraphID()); } - SSACFG const* functionGraph(Scope::Function const* _function) const - { - auto it = ranges::find_if(functionGraphMapping, [_function](auto const& tup) { return _function == std::get<0>(tup); }); - if (it != functionGraphMapping.end()) - return std::get<1>(*it); - return nullptr; - } - SSACFG const* functionGraph(FunctionGraphID const _id) const { return functionGraphs.at(_id).get(); @@ -72,7 +61,8 @@ struct ControlFlow output << functionGraphs[index]->toDot( false, index, - _liveness ? _liveness->cfgLiveness[index].get() : nullptr + _liveness ? _liveness->cfgLiveness[index].get() : nullptr, + this ); output << "}\n"; @@ -80,7 +70,6 @@ struct ControlFlow } std::vector> functionGraphs{}; - std::vector> functionGraphMapping{}; }; } diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 8b89d9f4b..b65acfc17 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -18,6 +18,7 @@ #include +#include #include #include #include @@ -58,9 +59,10 @@ std::string formatPhi(SSACFG const& _cfg, SSACFG::ValueId _phiId) class SSACFGDotExporter: public io::DotExporterBase { public: - SSACFGDotExporter(SSACFG const& _cfg, size_t _functionIndex, LivenessAnalysis const* _liveness): + SSACFGDotExporter(SSACFG const& _cfg, size_t _functionIndex, LivenessAnalysis const* _liveness, ControlFlow const* _controlFlow): DotExporterBase(_cfg, _functionIndex), - m_liveness(_liveness) + m_liveness(_liveness), + m_controlFlow(_controlFlow) { if (_liveness) m_junkAdmittingBlocks = std::make_unique(_cfg, _liveness->topologicalSort()); @@ -103,10 +105,12 @@ class SSACFGDotExporter: public io::DotExporterBase { auto const& operation = m_cfg.operation(opId); std::string const label = std::visit(GenericVisitor{ - [&](SSACFG::Call const& _call) { - return _call.function.get().name.str(); + [&](SSACFG::Call const& _call) -> std::string { + if (m_controlFlow) + return m_controlFlow->functionGraph(_call.graphID)->name; + return fmt::format("func{}", _call.graphID); }, - [&](SSACFG::BuiltinCall const& _call) { + [&](SSACFG::BuiltinCall const& _call) -> std::string { return _call.builtin.get().name; } }, operation.kind); @@ -139,6 +143,7 @@ class SSACFGDotExporter: public io::DotExporterBase private: LivenessAnalysis const* m_liveness; + ControlFlow const* m_controlFlow; std::unique_ptr m_junkAdmittingBlocks; }; @@ -162,10 +167,11 @@ std::string ValueId::str(SSACFG const& _cfg) const std::string SSACFG::toDot( bool _includeDiGraphDefinition, std::optional _functionIndex, - LivenessAnalysis const* _liveness + LivenessAnalysis const* _liveness, + ControlFlow const* _controlFlow ) const { - SSACFGDotExporter exporter(*this, _functionIndex.value_or(isMainGraph() ? 0 : 1), _liveness); + SSACFGDotExporter exporter(*this, _functionIndex.value_or(isMainGraph() ? 0 : 1), _liveness, _controlFlow); if (!isMainGraph()) return exporter.exportFunction(*function, _includeDiGraphDefinition); else diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index ac269d390..8ef29b5fc 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -43,6 +43,7 @@ namespace solidity::yul::ssa { class LivenessAnalysis; +struct ControlFlow; class SSACFG { @@ -74,7 +75,7 @@ class SSACFG }; struct Call { - std::reference_wrapper function; + FunctionGraphID graphID; std::reference_wrapper call; bool canContinue; }; @@ -240,7 +241,8 @@ class SSACFG std::string toDot( bool _includeDiGraphDefinition=true, std::optional _functionIndex=std::nullopt, - LivenessAnalysis const* _liveness=nullptr + LivenessAnalysis const* _liveness=nullptr, + ControlFlow const* _controlFlow=nullptr ) const; PhiValue const& phiInfo(ValueId const& _valueId) const diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 70495e35d..df4da16ba 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -78,7 +79,6 @@ std::unique_ptr SSACFGBuilder::build( _dialect, _generateDebugInfo ? std::make_unique() : nullptr )); - controlFlow->functionGraphMapping.emplace_back(nullptr, controlFlow->functionGraphs.back().get()); SSACFG& mainGraph = *controlFlow->functionGraphs.back(); SSACFGBuilder builder(*controlFlow, mainGraph, _analysisInfo, sideEffects, _dialect, _generateDebugInfo); builder.m_currentBlock = mainGraph.makeBlock(debugDataOf(_block)); @@ -98,12 +98,11 @@ void SSACFGBuilder::buildFunctionGraph( FunctionDefinition const* _functionDefinition ) { - m_controlFlow.functionGraphs.emplace_back(std::make_unique( - m_dialect, - m_generateDebugInfo ? std::make_unique() : nullptr - )); - auto& cfg = *m_controlFlow.functionGraphs.back(); - m_controlFlow.functionGraphMapping.emplace_back(_function, &cfg); + // The graph slot and the FunctionGraphID have already been allocated in + // `registerFunctionDefinition`; this call builds the body into that slot. + auto const graphIt = m_functionScopeToID.find(_function); + yulAssert(graphIt != m_functionScopeToID.end(), "Function graph must be registered before building."); + auto& cfg = *m_controlFlow.functionGraphs[graphIt->second]; yulAssert(m_info.scopes.at(&_functionDefinition->body), ""); Scope* virtualFunctionScope = m_info.scopes.at(m_info.virtualBlocks.at(_functionDefinition).get()).get(); @@ -122,7 +121,6 @@ void SSACFGBuilder::buildFunctionGraph( if (cfg.debugInfo) cfg.debugInfo->graphDebugData = _functionDefinition->debugData; cfg.function = _function; - cfg.name = _function->name.str(); cfg.canContinue = m_sideEffects.functionSideEffects().at(_functionDefinition).canContinue; cfg.arguments = arguments; cfg.returns = returns; @@ -130,6 +128,7 @@ void SSACFGBuilder::buildFunctionGraph( SSACFGBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_generateDebugInfo); builder.m_currentBlock = cfg.entry; builder.m_functionDefinitions = m_functionDefinitions; + builder.m_functionScopeToID = m_functionScopeToID; for (auto&& [var, varId]: cfg.arguments) builder.currentDef(var, cfg.entry) = varId; for (auto const& var: cfg.returns) @@ -382,6 +381,17 @@ void SSACFGBuilder::registerFunctionDefinition(FunctionDefinition const& _functi auto& function = std::get(m_scope->identifiers.at(_functionDefinition.name)); m_graph.functions.emplace_back(function); m_functionDefinitions.emplace_back(&function, &_functionDefinition); + + // Allocate the graph slot up front so sibling functions (and mutually-recursive pairs) can + // reference this function by its FunctionGraphID when their bodies are built later. + m_controlFlow.functionGraphs.emplace_back(std::make_unique( + m_dialect, + m_generateDebugInfo ? std::make_unique() : nullptr + )); + auto const graphID = static_cast(m_controlFlow.functionGraphs.size() - 1); + auto& cfg = *m_controlFlow.functionGraphs.back(); + cfg.name = function.name.str(); + m_functionScopeToID[&function] = graphID; } void SSACFGBuilder::operator()(Block const& _block) @@ -457,7 +467,9 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const auto const* definition = findFunctionDefinition(&function); yulAssert(definition); canContinue = m_sideEffects.functionSideEffects().at(definition).canContinue; - SSACFG::Operation result{{}, SSACFG::Call{function, _call, canContinue}, {}}; + auto const calleeIt = m_functionScopeToID.find(&function); + yulAssert(calleeIt != m_functionScopeToID.end(), "Called function has no registered graph id."); + SSACFG::Operation result{{}, SSACFG::Call{calleeIt->second, _call, canContinue}, {}}; for (auto const& arg: _call.arguments | ranges::views::reverse) result.inputs.emplace_back(std::visit(*this, arg)); for (size_t i = 0; i < function.numReturns; ++i) diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index 5478e3d94..c38931626 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -109,6 +110,8 @@ class SSACFGBuilder EVMDialect const& m_dialect; bool const m_generateDebugInfo; std::vector> m_functionDefinitions; + /// Translation map from Yul-AST function scopes to their corresponding FunctionGraphIDs + std::map m_functionScopeToID; SSACFG::BlockId m_currentBlock; SSACFG::BasicBlock& currentBlock() { return m_graph.block(m_currentBlock); } langutil::DebugData::ConstPtr currentBlockDebugData() const diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index c916217b6..55ba45300 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -43,13 +43,13 @@ Json toJson(SSACFG const& _cfg, std::vector const& _values) return ret; } -Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation) +Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation, ControlFlow const& _controlFlow) { Json opJson = Json::object(); std::visit(util::GenericVisitor{ [&](SSACFG::Call const& _call) { _ret["type"] = "FunctionCall"; - opJson["op"] = _call.function.get().name.str(); + opJson["op"] = _controlFlow.functionGraph(_call.graphID)->name; }, [&](SSACFG::BuiltinCall const& _call) { _ret["type"] = "BuiltinCall"; @@ -83,7 +83,7 @@ Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation) return opJson; } -Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness) +Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness, ControlFlow const& _controlFlow) { auto const valueToString = [&](LivenessAnalysis::LivenessData::LiveCounts::value_type const& _live) { return _live.first.str(_cfg); }; @@ -127,17 +127,17 @@ Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const } } for (auto const opId: block.operations) - blockJson["instructions"].push_back(toJson(blockJson, _cfg, _cfg.operation(opId))); + blockJson["instructions"].push_back(toJson(blockJson, _cfg, _cfg.operation(opId), _controlFlow)); return blockJson; } -Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis const* _liveness) +Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis const* _liveness, ControlFlow const& _controlFlow) { Json blocksJson = Json::array(); util::BreadthFirstSearch bfs{{{_entryId}}}; bfs.run([&](SSACFG::BlockId _blockId, auto _addChild) { - Json blockJson = toJson(_cfg, _blockId, _liveness); + Json blockJson = toJson(_cfg, _blockId, _liveness, _controlFlow); Json exitBlockJson = Json::object(); std::visit(util::GenericVisitor{ @@ -172,7 +172,7 @@ Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis return blocksJson; } -Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness) +Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness, ControlFlow const& _controlFlow) { Json functionJson = Json::object(); functionJson["type"] = "Function"; @@ -180,7 +180,7 @@ Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness) static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", std::get<1>(_arg).value()); }; functionJson["arguments"] = _cfg.arguments | ranges::views::transform(argsTransform) | ranges::to; functionJson["numReturns"] = _cfg.returns.size(); - functionJson["blocks"] = exportBlock(_cfg, _cfg.entry, _liveness); + functionJson["blocks"] = exportBlock(_cfg, _cfg.entry, _liveness, _controlFlow); return functionJson; } @@ -192,13 +192,22 @@ Json io::json::exportControlFlow(ControlFlow const& _controlFlow, ControlFlowLiv yulAssert(&_liveness->controlFlow.get() == &_controlFlow); Json yulObjectJson = Json::object(); - yulObjectJson["blocks"] = exportBlock(*_controlFlow.mainGraph(), SSACFG::BlockId{0}, _liveness ? _liveness->cfgLiveness.front().get() : nullptr); + yulObjectJson["blocks"] = exportBlock( + *_controlFlow.mainGraph(), + SSACFG::BlockId{0}, + _liveness ? _liveness->cfgLiveness.front().get() : nullptr, + _controlFlow + ); Json functionsJson = Json::object(); - size_t index = 1; - for (auto const& [function, functionGraph]: _controlFlow.functionGraphMapping | ranges::views::drop(1)) + for (std::size_t index = 1; index < _controlFlow.functionGraphs.size(); ++index) { - functionsJson[function->name.str()] = exportFunction(*functionGraph, _liveness ? _liveness->cfgLiveness[index++].get() : nullptr); + SSACFG const& functionGraph = *_controlFlow.functionGraphs[index]; + functionsJson[functionGraph.name] = exportFunction( + functionGraph, + _liveness ? _liveness->cfgLiveness[index].get() : nullptr, + _controlFlow + ); } yulObjectJson["functions"] = functionsJson; diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index 5f0555fbd..8284d97f8 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -56,9 +56,15 @@ namespace class StackLayoutDotExporter: public io::DotExporterBase { public: - StackLayoutDotExporter(SSACFG const& _cfg, std::size_t _functionIndex, SSACFGStackLayout const& _layout): + StackLayoutDotExporter( + SSACFG const& _cfg, + std::size_t _functionIndex, + SSACFGStackLayout const& _layout, + ControlFlow const& _controlFlow + ): DotExporterBase(_cfg, _functionIndex), - m_layout(_layout) + m_layout(_layout), + m_controlFlow(_controlFlow) { } @@ -83,7 +89,7 @@ class StackLayoutDotExporter: public io::DotExporterBase std::visit(GenericVisitor{ [&](SSACFG::Call const& _call) { - _out << escapeLabel(_call.function.get().name.str()); + _out << escapeLabel(m_controlFlow.functionGraph(_call.graphID)->name); }, [&](SSACFG::BuiltinCall const& _call) { _out << escapeLabel(_call.builtin.get().name); @@ -105,6 +111,7 @@ class StackLayoutDotExporter: public io::DotExporterBase private: SSACFGStackLayout const& m_layout; + ControlFlow const& m_controlFlow; }; } @@ -164,8 +171,8 @@ frontend::test::TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& gatherCallSites(cfg), static_cast(index) ); - StackLayoutDotExporter exporter(cfg, index, layout); - if (cfg.function) + StackLayoutDotExporter exporter(cfg, index, layout, *controlFlow); + if (!cfg.isMainGraph()) m_obtainedResult += exporter.exportFunction(*cfg.function, false); else m_obtainedResult += exporter.exportBlocks(cfg.entry, false); diff --git a/test/libyul/ssa/controlFlowGraph/nested_function.yul b/test/libyul/ssa/controlFlowGraph/nested_function.yul index 743136adb..d8e701027 100644 --- a/test/libyul/ssa/controlFlowGraph/nested_function.yul +++ b/test/libyul/ssa/controlFlowGraph/nested_function.yul @@ -64,92 +64,92 @@ // "]; // Block2_0Exit [label="FunctionReturn[]"]; // Block2_0 -> Block2_0Exit; -// FunctionEntry_z_0 [label="function z: -// r := z()"]; -// FunctionEntry_z_0 -> Block3_0; -// Block3_0 [label="\ -// Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v0[1]\l\nUsed: \l\nv0 := w()\l\ -// "]; -// Block3_0Exit [label="FunctionReturn[v0]"]; -// Block3_0 -> Block3_0Exit; -// FunctionEntry_w_0 [label="function w: -// rw1 := w()"]; -// FunctionEntry_w_0 -> Block4_0; -// Block4_0 [label="\ -// Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nUsed: \l\n"]; -// Block4_0Exit [label="FunctionReturn[0x01]"]; -// Block4_0 -> Block4_0Exit; -// FunctionEntry_v_0 [label="function v: -// r := v()"]; -// FunctionEntry_v_0 -> Block5_0; -// Block5_0 [label="\ -// Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v0[1]\l\nUsed: \l\nv0 := w()\l\ -// "]; -// Block5_0Exit [label="FunctionReturn[v0]"]; -// Block5_0 -> Block5_0Exit; -// FunctionEntry_w_0 [label="function w: -// rw2 := w()"]; -// FunctionEntry_w_0 -> Block6_0; -// Block6_0 [label="\ -// Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nUsed: \l\n"]; -// Block6_0Exit [label="FunctionReturn[0x11]"]; -// Block6_0 -> Block6_0Exit; // FunctionEntry_cycle1_0 [label="function cycle1: // r := cycle1()"]; -// FunctionEntry_cycle1_0 -> Block7_0; -// Block7_0 [label="\ +// FunctionEntry_cycle1_0 -> Block3_0; +// Block3_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ // LiveOut: \l\nUsed: \l\nv0 := mload(0x03)\l\ // "]; -// Block7_0 -> Block7_0Exit; -// Block7_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block7_0Exit:0 -> Block7_2 [style="solid"]; -// Block7_0Exit:1 -> Block7_1 [style="solid"]; -// Block7_1 [label="\ +// Block3_0 -> Block3_0Exit; +// Block3_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block3_0Exit:0 -> Block3_2 [style="solid"]; +// Block3_0Exit:1 -> Block3_1 [style="solid"]; +// Block3_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ // LiveOut: v1[1]\l\nUsed: \l\nv1 := cycle2()\l\ // "]; -// Block7_1 -> Block7_1Exit [arrowhead=none]; -// Block7_1Exit [label="Jump" shape=oval]; -// Block7_1Exit -> Block7_2 [style="solid"]; -// Block7_2 [label="\ +// Block3_1 -> Block3_1Exit [arrowhead=none]; +// Block3_1Exit [label="Jump" shape=oval]; +// Block3_1Exit -> Block3_2 [style="solid"]; +// Block3_2 [label="\ // Block 2; (2, max 2)\nLiveIn: phi0[3]\l\ // LiveOut: phi0[1]\l\nUsed: phi0[2]\l\nphi0 := φ(\l\ // Block 0 => 0x00,\l\ // Block 1 => v1\l\ // )\l\ // "]; -// Block7_2Exit [label="FunctionReturn[phi0]"]; -// Block7_2 -> Block7_2Exit; +// Block3_2Exit [label="FunctionReturn[phi0]"]; +// Block3_2 -> Block3_2Exit; // FunctionEntry_cycle2_0 [label="function cycle2: // r := cycle2()"]; -// FunctionEntry_cycle2_0 -> Block8_0; -// Block8_0 [label="\ +// FunctionEntry_cycle2_0 -> Block4_0; +// Block4_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ // LiveOut: \l\nUsed: \l\nv0 := mload(0x04)\l\ // "]; -// Block8_0 -> Block8_0Exit; -// Block8_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; -// Block8_0Exit:0 -> Block8_2 [style="solid"]; -// Block8_0Exit:1 -> Block8_1 [style="solid"]; -// Block8_1 [label="\ +// Block4_0 -> Block4_0Exit; +// Block4_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block4_0Exit:0 -> Block4_2 [style="solid"]; +// Block4_0Exit:1 -> Block4_1 [style="solid"]; +// Block4_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ // LiveOut: v1[1]\l\nUsed: \l\nv1 := cycle1()\l\ // "]; -// Block8_1 -> Block8_1Exit [arrowhead=none]; -// Block8_1Exit [label="Jump" shape=oval]; -// Block8_1Exit -> Block8_2 [style="solid"]; -// Block8_2 [label="\ +// Block4_1 -> Block4_1Exit [arrowhead=none]; +// Block4_1Exit [label="Jump" shape=oval]; +// Block4_1Exit -> Block4_2 [style="solid"]; +// Block4_2 [label="\ // Block 2; (2, max 2)\nLiveIn: phi0[3]\l\ // LiveOut: phi0[1]\l\nUsed: phi0[2]\l\nphi0 := φ(\l\ // Block 0 => 0x00,\l\ // Block 1 => v1\l\ // )\l\ // "]; -// Block8_2Exit [label="FunctionReturn[phi0]"]; -// Block8_2 -> Block8_2Exit; +// Block4_2Exit [label="FunctionReturn[phi0]"]; +// Block4_2 -> Block4_2Exit; +// FunctionEntry_z_0 [label="function z: +// r := z()"]; +// FunctionEntry_z_0 -> Block5_0; +// Block5_0 [label="\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: v0[1]\l\nUsed: \l\nv0 := w()\l\ +// "]; +// Block5_0Exit [label="FunctionReturn[v0]"]; +// Block5_0 -> Block5_0Exit; +// FunctionEntry_v_0 [label="function v: +// r := v()"]; +// FunctionEntry_v_0 -> Block6_0; +// Block6_0 [label="\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: v0[1]\l\nUsed: \l\nv0 := w()\l\ +// "]; +// Block6_0Exit [label="FunctionReturn[v0]"]; +// Block6_0 -> Block6_0Exit; +// FunctionEntry_w_0 [label="function w: +// rw1 := w()"]; +// FunctionEntry_w_0 -> Block7_0; +// Block7_0 [label="\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nUsed: \l\n"]; +// Block7_0Exit [label="FunctionReturn[0x01]"]; +// Block7_0 -> Block7_0Exit; +// FunctionEntry_w_0 [label="function w: +// rw2 := w()"]; +// FunctionEntry_w_0 -> Block8_0; +// Block8_0 [label="\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nUsed: \l\n"]; +// Block8_0Exit [label="FunctionReturn[0x11]"]; +// Block8_0 -> Block8_0Exit; // } From 1a3ed139cbbcc0a8533e1a1a67b24d86f697e2e9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:15:05 +0200 Subject: [PATCH 1274/1340] SSA CFG: drop unused SSACFG::functions vector --- libyul/backends/evm/ssa/SSACFG.h | 1 - libyul/backends/evm/ssa/SSACFGBuilder.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 8ef29b5fc..eb89eeb0f 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -281,7 +281,6 @@ class SSACFG bool canContinue = true; std::vector, ValueId>> arguments; std::vector> returns; - std::vector> functions; // Container for artificial calls generated for switch statements. std::list ghostCalls; diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index df4da16ba..92d3b9183 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -379,7 +379,6 @@ void SSACFGBuilder::registerFunctionDefinition(FunctionDefinition const& _functi yulAssert(m_scope, ""); yulAssert(m_scope->identifiers.count(_functionDefinition.name), ""); auto& function = std::get(m_scope->identifiers.at(_functionDefinition.name)); - m_graph.functions.emplace_back(function); m_functionDefinitions.emplace_back(&function, &_functionDefinition); // Allocate the graph slot up front so sibling functions (and mutually-recursive pairs) can From fbccc5b9ac21a2f682338ae23d22f305b4f0f96f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:18:58 +0200 Subject: [PATCH 1275/1340] SSA CFG: drop remaining Scope::* refs from the IR --- libyul/backends/evm/ssa/CodeTransform.cpp | 6 ++-- libyul/backends/evm/ssa/SSACFG.cpp | 2 +- libyul/backends/evm/ssa/SSACFG.h | 6 ++-- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 20 +++++++------ libyul/backends/evm/ssa/SSACFGBuilder.h | 2 ++ .../backends/evm/ssa/StackLayoutGenerator.cpp | 2 +- .../backends/evm/ssa/io/DotExporterBase.cpp | 29 +++++++++---------- libyul/backends/evm/ssa/io/DotExporterBase.h | 2 +- libyul/backends/evm/ssa/io/JSONExporter.cpp | 4 +-- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 2 +- test/libyul/ssa/controlFlowGraph/complex.yul | 2 +- test/libyul/ssa/controlFlowGraph/complex2.yul | 2 +- test/libyul/ssa/controlFlowGraph/function.yul | 4 +-- .../ssa/controlFlowGraph/nested_function.yul | 14 ++++----- .../ssa/stackLayoutGenerator/function.yul | 4 +-- .../ssa/stackLayoutGenerator/multi_return.yul | 2 +- .../ssa/stackLayoutGenerator/recursion.yul | 2 +- .../ssa/stackLayoutGenerator/simple_if.yul | 2 +- 18 files changed, 55 insertions(+), 52 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 041d674c7..86da85a6c 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -101,7 +101,7 @@ CodeTransform::FunctionLabels CodeTransform::registerFunctionLabels( _assembly.namedLabel( functionGraph.name, functionGraph.arguments.size(), - functionGraph.returns.size(), + functionGraph.numReturns, sourceID ) : _assembly.newLabelId(); @@ -161,7 +161,7 @@ CodeTransform::CodeTransform( expectedStackTop.reserve(m_cfg.arguments.size() + (isFunctionGraph && m_cfg.canContinue ? 1 : 0)); if (isFunctionGraph && m_cfg.canContinue) expectedStackTop.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); - for (auto const& [_, valueID]: m_cfg.arguments | ranges::views::reverse) + for (auto const& valueID: m_cfg.arguments | ranges::views::reverse) expectedStackTop.push_back(StackSlot::makeValueID(valueID)); assertLayoutCompatibility(m_stack.data(), expectedStackTop); } @@ -367,7 +367,7 @@ void CodeTransform::operator()(SSACFG::BlockId const&, SSACFG::BasicBlock::Funct { yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); // Each CodeTransform instance handles exactly one function's CFG, so a FunctionReturn exit - // here necessarily belongs to m_cfg.function. No identity cross-check is needed. + // here necessarily belongs to a function graph. No identity cross-check is needed. yulAssert(!m_cfg.isMainGraph()); yulAssert(m_cfg.canContinue); yulAssert(m_stack.size() == _functionReturn.returnValues.size() + 1, "There must be at least the function return label element on stack"); diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index b65acfc17..42e07df08 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -173,7 +173,7 @@ std::string SSACFG::toDot( { SSACFGDotExporter exporter(*this, _functionIndex.value_or(isMainGraph() ? 0 : 1), _liveness, _controlFlow); if (!isMainGraph()) - return exporter.exportFunction(*function, _includeDiGraphDefinition); + return exporter.exportFunction(*this, _includeDiGraphDefinition); else return exporter.exportBlocks(entry, _includeDiGraphDefinition); } diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index eb89eeb0f..63bcc6542 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -30,7 +30,6 @@ #include #include #include -#include #include @@ -38,6 +37,7 @@ #include #include #include +#include #include namespace solidity::yul::ssa @@ -279,8 +279,8 @@ class SSACFG std::set exits; std::string name{}; bool canContinue = true; - std::vector, ValueId>> arguments; - std::vector> returns; + std::vector arguments; + std::size_t numReturns = 0; // Container for artificial calls generated for switch statements. std::list ghostCalls; diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 92d3b9183..a74a329d5 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -109,29 +109,30 @@ void SSACFGBuilder::buildFunctionGraph( yulAssert(virtualFunctionScope, ""); cfg.entry = cfg.makeBlock(debugDataOf(_functionDefinition->body)); - auto arguments = _functionDefinition->parameters | ranges::views::transform([&](auto const& _param) { + auto argumentBindings = _functionDefinition->parameters | ranges::views::transform([&](auto const& _param) { auto const& var = std::get(virtualFunctionScope->identifiers.at(_param.name)); // Note: cannot use std::make_tuple since it unwraps reference wrappers. return std::tuple{std::cref(var), cfg.newVariable(cfg.entry)}; }) | ranges::to; - auto returns = _functionDefinition->returnVariables | ranges::views::transform([&](auto const& _param) { + auto returnVars = _functionDefinition->returnVariables | ranges::views::transform([&](auto const& _param) { return std::cref(std::get(virtualFunctionScope->identifiers.at(_param.name))); - }) | ranges::to; + }) | ranges::to>>(); if (cfg.debugInfo) cfg.debugInfo->graphDebugData = _functionDefinition->debugData; - cfg.function = _function; cfg.canContinue = m_sideEffects.functionSideEffects().at(_functionDefinition).canContinue; - cfg.arguments = arguments; - cfg.returns = returns; + cfg.arguments = argumentBindings + | ranges::views::transform([](auto const& _binding) { return std::get<1>(_binding); }) + | ranges::to; SSACFGBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_generateDebugInfo); builder.m_currentBlock = cfg.entry; builder.m_functionDefinitions = m_functionDefinitions; builder.m_functionScopeToID = m_functionScopeToID; - for (auto&& [var, varId]: cfg.arguments) + builder.m_currentReturnVars = returnVars; + for (auto&& [var, varId]: argumentBindings) builder.currentDef(var, cfg.entry) = varId; - for (auto const& var: cfg.returns) + for (auto const& var: returnVars) builder.currentDef(var.get(), cfg.entry) = builder.zero(); builder.sealBlock(cfg.entry); builder(_functionDefinition->body); @@ -366,7 +367,7 @@ void SSACFGBuilder::operator()(Leave const& _leaveStatement) if (m_graph.debugInfo) m_graph.debugInfo->setExitDebugData(m_currentBlock, debugDataOf(_leaveStatement)); currentBlock().exit = SSACFG::BasicBlock::FunctionReturn{ - m_graph.returns | ranges::views::transform([&](auto _var) { + m_currentReturnVars | ranges::views::transform([&](auto _var) { return readVariable(_var, m_currentBlock); }) | ranges::to }; @@ -390,6 +391,7 @@ void SSACFGBuilder::registerFunctionDefinition(FunctionDefinition const& _functi auto const graphID = static_cast(m_controlFlow.functionGraphs.size() - 1); auto& cfg = *m_controlFlow.functionGraphs.back(); cfg.name = function.name.str(); + cfg.numReturns = _functionDefinition.returnVariables.size(); m_functionScopeToID[&function] = graphID; } diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index c38931626..8db9cfc6c 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -112,6 +112,8 @@ class SSACFGBuilder std::vector> m_functionDefinitions; /// Translation map from Yul-AST function scopes to their corresponding FunctionGraphIDs std::map m_functionScopeToID; + /// Return variable scopes of the function currently being built + std::vector> m_currentReturnVars; SSACFG::BlockId m_currentBlock; SSACFG::BasicBlock& currentBlock() { return m_graph.block(m_currentBlock); } langutil::DebugData::ConstPtr currentBlockDebugData() const diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index a7076edc0..d9a2aba6b 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -149,7 +149,7 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) blockLayout.stackIn.reserve(m_cfg.arguments.size() + (m_hasFunctionReturnLabel ? 1u : 0u)); if (m_hasFunctionReturnLabel) blockLayout.stackIn.push_back(Slot::makeFunctionReturnLabel(m_graphID)); - for (auto const& [_, valueID]: m_cfg.arguments | ranges::views::reverse) + for (auto const& valueID: m_cfg.arguments | ranges::views::reverse) blockLayout.stackIn.push_back(Slot::makeValueID(valueID)); } m_resultLayout[_blockId] = blockLayout; diff --git a/libyul/backends/evm/ssa/io/DotExporterBase.cpp b/libyul/backends/evm/ssa/io/DotExporterBase.cpp index 00b3fda30..bd4d8be23 100644 --- a/libyul/backends/evm/ssa/io/DotExporterBase.cpp +++ b/libyul/backends/evm/ssa/io/DotExporterBase.cpp @@ -171,28 +171,27 @@ std::string DotExporterBase::exportBlocks(SSACFG::BlockId _entry, bool _wrapInDi return out.str(); } -std::string DotExporterBase::exportFunction(Scope::Function const& _function, bool _wrapInDigraph) +std::string DotExporterBase::exportFunction(SSACFG const& _function, bool _wrapInDigraph) { std::ostringstream out; if (_wrapInDigraph) out << fmt::format("digraph SSACFG {{\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\", rankdir={}]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n", m_rankDir); - static auto constexpr returnsTransform = [](auto const& functionReturnValue) { return escapeLabel(functionReturnValue.get().name.str()); }; - static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", std::get<1>(arg).value()); }; - auto const entryHandle = fmt::format("FunctionEntry_{}_{}", escapeId(_function.name.str()), m_cfg.entry.value); - if (!m_cfg.returns.empty()) - out << fmt::format("{} [label=\"function {}:\n {} := {}({})\"];\n", - entryHandle, escapeLabel(_function.name.str()), - fmt::join(m_cfg.returns | ranges::views::transform(returnsTransform), ", "), - escapeLabel(_function.name.str()), - fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); + static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", arg.value()); }; + auto const entryHandle = fmt::format("FunctionEntry_{}_{}", escapeId(_function.name), _function.entry.value); + if (_function.numReturns > 0) + out << fmt::format("{} [label=\"function {}:\n [{} returns] := {}({})\"];\n", + entryHandle, escapeLabel(_function.name), + _function.numReturns, + escapeLabel(_function.name), + fmt::join(_function.arguments | ranges::views::transform(argsTransform), ", ")); else out << fmt::format("{} [label=\"function {}:\n {}({})\"];\n", - entryHandle, escapeLabel(_function.name.str()), - escapeLabel(_function.name.str()), - fmt::join(m_cfg.arguments | ranges::views::transform(argsTransform), ", ")); - out << fmt::format("{} -> {};\n", entryHandle, formatBlockHandle(m_cfg.entry)); - traverse(out, m_cfg.entry); + entryHandle, escapeLabel(_function.name), + escapeLabel(_function.name), + fmt::join(_function.arguments | ranges::views::transform(argsTransform), ", ")); + out << fmt::format("{} -> {};\n", entryHandle, formatBlockHandle(_function.entry)); + traverse(out, _function.entry); if (_wrapInDigraph) out << "}\n"; diff --git a/libyul/backends/evm/ssa/io/DotExporterBase.h b/libyul/backends/evm/ssa/io/DotExporterBase.h index f7fcdcda2..e800e8b73 100644 --- a/libyul/backends/evm/ssa/io/DotExporterBase.h +++ b/libyul/backends/evm/ssa/io/DotExporterBase.h @@ -43,7 +43,7 @@ class DotExporterBase virtual ~DotExporterBase() = default; std::string exportBlocks(SSACFG::BlockId _entry, bool _wrapInDigraph = true); - std::string exportFunction(Scope::Function const& _function, bool _wrapInDigraph = true); + std::string exportFunction(SSACFG const& _function, bool _wrapInDigraph = true); protected: /// Override to write the content inside a block's dot label. diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index 55ba45300..b459a334d 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -177,9 +177,9 @@ Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness, Contr Json functionJson = Json::object(); functionJson["type"] = "Function"; functionJson["entry"] = "Block" + std::to_string(_cfg.entry.value); - static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", std::get<1>(_arg).value()); }; + static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", _arg.value()); }; functionJson["arguments"] = _cfg.arguments | ranges::views::transform(argsTransform) | ranges::to; - functionJson["numReturns"] = _cfg.returns.size(); + functionJson["numReturns"] = _cfg.numReturns; functionJson["blocks"] = exportBlock(_cfg, _cfg.entry, _liveness, _controlFlow); return functionJson; } diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index 8284d97f8..4ad4893b0 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -173,7 +173,7 @@ frontend::test::TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& ); StackLayoutDotExporter exporter(cfg, index, layout, *controlFlow); if (!cfg.isMainGraph()) - m_obtainedResult += exporter.exportFunction(*cfg.function, false); + m_obtainedResult += exporter.exportFunction(cfg, false); else m_obtainedResult += exporter.exportBlocks(cfg.entry, false); } diff --git a/test/libyul/ssa/controlFlowGraph/complex.yul b/test/libyul/ssa/controlFlowGraph/complex.yul index 9dd78ae3a..eff75590c 100644 --- a/test/libyul/ssa/controlFlowGraph/complex.yul +++ b/test/libyul/ssa/controlFlowGraph/complex.yul @@ -59,7 +59,7 @@ // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_f_0 [label="function f: -// c := f(v0, v1)"]; +// [1 returns] := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 17)\nLiveIn: v1[1], v0[1]\l\ diff --git a/test/libyul/ssa/controlFlowGraph/complex2.yul b/test/libyul/ssa/controlFlowGraph/complex2.yul index 806f540c5..dccc91e59 100644 --- a/test/libyul/ssa/controlFlowGraph/complex2.yul +++ b/test/libyul/ssa/controlFlowGraph/complex2.yul @@ -75,7 +75,7 @@ // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_f_0 [label="function f: -// c := f(v0, v1)"]; +// [1 returns] := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 17)\nLiveIn: v1[1], v0[1]\l\ diff --git a/test/libyul/ssa/controlFlowGraph/function.yul b/test/libyul/ssa/controlFlowGraph/function.yul index a2e842699..bcc75c975 100644 --- a/test/libyul/ssa/controlFlowGraph/function.yul +++ b/test/libyul/ssa/controlFlowGraph/function.yul @@ -34,7 +34,7 @@ // Block0_0Exit [label="Terminated"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_f_0 [label="function f: -// r := f(v0, v1)"]; +// [1 returns] := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 0)\nLiveIn: v0[2], v1[1]\l\ @@ -63,7 +63,7 @@ // Block3_0Exit [label="Terminated"]; // Block3_0 -> Block3_0Exit; // FunctionEntry_i_0 [label="function i: -// v, w := i()"]; +// [2 returns] := i()"]; // FunctionEntry_i_0 -> Block4_0; // Block4_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ diff --git a/test/libyul/ssa/controlFlowGraph/nested_function.yul b/test/libyul/ssa/controlFlowGraph/nested_function.yul index d8e701027..6fcd0a114 100644 --- a/test/libyul/ssa/controlFlowGraph/nested_function.yul +++ b/test/libyul/ssa/controlFlowGraph/nested_function.yul @@ -43,7 +43,7 @@ // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_f_0 [label="function f: -// r := f(v0, v1)"]; +// [1 returns] := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 0)\nLiveIn: v0[2], v1[1]\l\ @@ -65,7 +65,7 @@ // Block2_0Exit [label="FunctionReturn[]"]; // Block2_0 -> Block2_0Exit; // FunctionEntry_cycle1_0 [label="function cycle1: -// r := cycle1()"]; +// [1 returns] := cycle1()"]; // FunctionEntry_cycle1_0 -> Block3_0; // Block3_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ @@ -92,7 +92,7 @@ // Block3_2Exit [label="FunctionReturn[phi0]"]; // Block3_2 -> Block3_2Exit; // FunctionEntry_cycle2_0 [label="function cycle2: -// r := cycle2()"]; +// [1 returns] := cycle2()"]; // FunctionEntry_cycle2_0 -> Block4_0; // Block4_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ @@ -119,7 +119,7 @@ // Block4_2Exit [label="FunctionReturn[phi0]"]; // Block4_2 -> Block4_2Exit; // FunctionEntry_z_0 [label="function z: -// r := z()"]; +// [1 returns] := z()"]; // FunctionEntry_z_0 -> Block5_0; // Block5_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ @@ -128,7 +128,7 @@ // Block5_0Exit [label="FunctionReturn[v0]"]; // Block5_0 -> Block5_0Exit; // FunctionEntry_v_0 [label="function v: -// r := v()"]; +// [1 returns] := v()"]; // FunctionEntry_v_0 -> Block6_0; // Block6_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ @@ -137,7 +137,7 @@ // Block6_0Exit [label="FunctionReturn[v0]"]; // Block6_0 -> Block6_0Exit; // FunctionEntry_w_0 [label="function w: -// rw1 := w()"]; +// [1 returns] := w()"]; // FunctionEntry_w_0 -> Block7_0; // Block7_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ @@ -145,7 +145,7 @@ // Block7_0Exit [label="FunctionReturn[0x01]"]; // Block7_0 -> Block7_0Exit; // FunctionEntry_w_0 [label="function w: -// rw2 := w()"]; +// [1 returns] := w()"]; // FunctionEntry_w_0 -> Block8_0; // Block8_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ diff --git a/test/libyul/ssa/stackLayoutGenerator/function.yul b/test/libyul/ssa/stackLayoutGenerator/function.yul index 8ea0f691b..a668eb94f 100644 --- a/test/libyul/ssa/stackLayoutGenerator/function.yul +++ b/test/libyul/ssa/stackLayoutGenerator/function.yul @@ -44,7 +44,7 @@ // Block0_0Exit [label="Terminated"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_f_0 [label="function f: -// r := f(v0, v1)"]; +// [1 returns] := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // IN: [ReturnLabel[1], v1, v0]\l\ @@ -94,7 +94,7 @@ // Block3_0Exit [label="Terminated"]; // Block3_0 -> Block3_0Exit; // FunctionEntry_i_0 [label="function i: -// v, w := i()"]; +// [2 returns] := i()"]; // FunctionEntry_i_0 -> Block4_0; // Block4_0 [label="\ // IN: [ReturnLabel[4]]\l\ diff --git a/test/libyul/ssa/stackLayoutGenerator/multi_return.yul b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul index 2beb56b95..aa774e457 100644 --- a/test/libyul/ssa/stackLayoutGenerator/multi_return.yul +++ b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul @@ -39,7 +39,7 @@ // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_pair_0 [label="function pair: -// x, y := pair(v0)"]; +// [2 returns] := pair(v0)"]; // FunctionEntry_pair_0 -> Block1_0; // Block1_0 [label="\ // IN: [ReturnLabel[1], v0]\l\ diff --git a/test/libyul/ssa/stackLayoutGenerator/recursion.yul b/test/libyul/ssa/stackLayoutGenerator/recursion.yul index 493532337..c12de066a 100644 --- a/test/libyul/ssa/stackLayoutGenerator/recursion.yul +++ b/test/libyul/ssa/stackLayoutGenerator/recursion.yul @@ -30,7 +30,7 @@ // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_sum_0 [label="function sum: -// s := sum(v0)"]; +// [1 returns] := sum(v0)"]; // FunctionEntry_sum_0 -> Block1_0; // Block1_0 [label="\ // IN: [ReturnLabel[1], v0]\l\ diff --git a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul index c2f6a6c83..2d0cbf67d 100644 --- a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul +++ b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul @@ -32,7 +32,7 @@ // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; // FunctionEntry_f_0 [label="function f: -// c := f(v0, v1)"]; +// [1 returns] := f(v0, v1)"]; // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // IN: [ReturnLabel[1], v1, v0]\l\ From 062d9e8e6286b1d4467e1b0d190803466361be25 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 22 Apr 2026 16:56:09 +0200 Subject: [PATCH 1276/1340] SSA CFG: rename ControlFlow to ControlFlowGraphs --- libyul/CMakeLists.txt | 4 ++-- libyul/YulStack.cpp | 6 ++--- libyul/backends/evm/EVMObjectCompiler.cpp | 6 ++--- libyul/backends/evm/ssa/CodeTransform.cpp | 24 +++++++++---------- libyul/backends/evm/ssa/CodeTransform.h | 14 +++++------ ...{ControlFlow.cpp => ControlFlowGraphs.cpp} | 10 ++++---- .../{ControlFlow.h => ControlFlowGraphs.h} | 14 +++++------ libyul/backends/evm/ssa/SSACFG.cpp | 8 +++---- libyul/backends/evm/ssa/SSACFG.h | 4 ++-- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 16 ++++++------- libyul/backends/evm/ssa/SSACFGBuilder.h | 8 +++---- libyul/backends/evm/ssa/Stack.h | 8 +++---- .../backends/evm/ssa/StackLayoutGenerator.cpp | 4 ++-- .../backends/evm/ssa/StackLayoutGenerator.h | 6 ++--- libyul/backends/evm/ssa/io/JSONExporter.cpp | 12 +++++----- libyul/backends/evm/ssa/io/JSONExporter.h | 4 ++-- test/libyul/ssa/ControlFlowGraphTest.cpp | 6 ++--- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 16 ++++++------- test/libyul/ssa/StackShufflerTest.cpp | 2 +- 19 files changed, 86 insertions(+), 86 deletions(-) rename libyul/backends/evm/ssa/{ControlFlow.cpp => ControlFlowGraphs.cpp} (77%) rename libyul/backends/evm/ssa/{ControlFlow.h => ControlFlowGraphs.h} (82%) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 80584bf77..bdcd157ab 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -76,8 +76,8 @@ add_library(yul backends/evm/ssa/BridgeFinder.h backends/evm/ssa/CodeTransform.cpp backends/evm/ssa/CodeTransform.h - backends/evm/ssa/ControlFlow.cpp - backends/evm/ssa/ControlFlow.h + backends/evm/ssa/ControlFlowGraphs.cpp + backends/evm/ssa/ControlFlowGraphs.h backends/evm/ssa/JunkAdmittingBlocksFinder.cpp backends/evm/ssa/JunkAdmittingBlocksFinder.h backends/evm/ssa/LivenessAnalysis.cpp diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 246773bb6..faa563596 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -396,14 +396,14 @@ Json YulStack::cfgJson() const // operations to the control flow graphs bool constexpr keepLiteralAssignments = true; // NOTE: The block Ids are reset for each object - std::unique_ptr controlFlow = ssa::SSACFGBuilder::build( + std::unique_ptr controlFlowGraphs = ssa::SSACFGBuilder::build( *_object.analysisInfo, EVMDialect::strictAssemblyForEVMObjects(m_evmVersion, m_eofVersion), _object.code()->root(), keepLiteralAssignments ); - std::unique_ptr liveness = std::make_unique(*controlFlow); - return ssa::io::json::exportControlFlow(*controlFlow, liveness.get()); + std::unique_ptr liveness = std::make_unique(*controlFlowGraphs); + return ssa::io::json::exportControlFlow(*controlFlowGraphs, liveness.get()); }; std::function>)> exportCFGFromSubObjects; diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index 379a41926..4f857a229 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include @@ -89,13 +89,13 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize, bool _viaSSAC { if (_viaSSACFG) { - std::unique_ptr controlFlow = ssa::SSACFGBuilder::build( + std::unique_ptr controlFlowGraphs = ssa::SSACFGBuilder::build( *_object.analysisInfo, *evmDialect, _object.code()->root(), false ); - ssa::ControlFlowLiveness const liveness(*controlFlow); + ssa::ControlFlowGraphsLiveness const liveness(*controlFlowGraphs); ssa::CodeTransform::run( m_assembly, liveness, diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 86da85a6c..90f1072d9 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -44,29 +44,29 @@ void assertLayoutCompatibility(StackData const& _layout1, StackData const& _layo void CodeTransform::run ( AbstractAssembly& _assembly, - ControlFlowLiveness const& _controlFlowLiveness, + ControlFlowGraphsLiveness const& _controlFlowLiveness, BuiltinContext& _builtinContext ) { yulAssert(!_controlFlowLiveness.cfgLiveness.empty()); - ControlFlow const& controlFlow = _controlFlowLiveness.controlFlow.get(); - yulAssert(controlFlow.functionGraphs.size() == _controlFlowLiveness.cfgLiveness.size()); - FunctionLabels const functionLabels = registerFunctionLabels(_assembly, controlFlow); + ControlFlowGraphs const& controlFlowGraphs = _controlFlowLiveness.controlFlowGraphs.get(); + yulAssert(controlFlowGraphs.functionGraphs.size() == _controlFlowLiveness.cfgLiveness.size()); + FunctionLabels const functionLabels = registerFunctionLabels(_assembly, controlFlowGraphs); - for (std::size_t functionIndex = 0; functionIndex < controlFlow.functionGraphs.size(); ++functionIndex) + for (std::size_t functionIndex = 0; functionIndex < controlFlowGraphs.functionGraphs.size(); ++functionIndex) { - std::unique_ptr const& functionGraphPtr = controlFlow.functionGraphs[functionIndex]; + std::unique_ptr const& functionGraphPtr = controlFlowGraphs.functionGraphs[functionIndex]; yulAssert(functionGraphPtr); SSACFG const& cfg = *functionGraphPtr; auto const callSites = gatherCallSites(cfg); auto const& liveness = _controlFlowLiveness.cfgLiveness[functionIndex]; yulAssert(liveness); - auto const graphID = static_cast(functionIndex); + auto const graphID = static_cast(functionIndex); auto const& stackLayout = StackLayoutGenerator::generate(*liveness, callSites, graphID); CodeTransform transform( _assembly, _builtinContext, - controlFlow, + controlFlowGraphs, functionLabels, callSites, cfg, @@ -78,7 +78,7 @@ void CodeTransform::run } CodeTransform::FunctionLabels CodeTransform::registerFunctionLabels( - AbstractAssembly& _assembly, ControlFlow const& _controlFlow) + AbstractAssembly& _assembly, ControlFlowGraphs const& _controlFlow) { FunctionLabels functionLabels; std::set assignedFunctionNames; @@ -90,7 +90,7 @@ CodeTransform::FunctionLabels CodeTransform::registerFunctionLabels( SSACFG const& functionGraph = *functionGraphPtr; if (functionGraph.isMainGraph()) continue; - auto const graphID = static_cast(index); + auto const graphID = static_cast(index); bool const nameAlreadySeen = !assignedFunctionNames.insert(functionGraph.name).second; auto const sourceID = [&]() -> std::optional { if (functionGraph.debugInfo && functionGraph.debugInfo->graphDebugData) @@ -112,12 +112,12 @@ CodeTransform::FunctionLabels CodeTransform::registerFunctionLabels( CodeTransform::CodeTransform( AbstractAssembly& _assembly, BuiltinContext& _builtinContext, - ControlFlow const& _controlFlow, + ControlFlowGraphs const& _controlFlow, FunctionLabels const& _functionLabels, CallSites const& _callSites, SSACFG const& _cfg, SSACFGStackLayout const& _stackLayout, - ControlFlow::FunctionGraphID _graphID + ControlFlowGraphs::FunctionGraphID _graphID ): m_assembly(_assembly), m_builtinContext(_builtinContext), diff --git a/libyul/backends/evm/ssa/CodeTransform.h b/libyul/backends/evm/ssa/CodeTransform.h index be72effed..2a1e19f4e 100644 --- a/libyul/backends/evm/ssa/CodeTransform.h +++ b/libyul/backends/evm/ssa/CodeTransform.h @@ -95,27 +95,27 @@ class CodeTransform public: static void run( AbstractAssembly& _assembly, - ControlFlowLiveness const& _liveness, + ControlFlowGraphsLiveness const& _liveness, BuiltinContext& _builtinContext ); private: - using FunctionLabels = std::map; + using FunctionLabels = std::map; static FunctionLabels registerFunctionLabels( AbstractAssembly& _assembly, - ControlFlow const& _controlFlow + ControlFlowGraphs const& _controlFlow ); CodeTransform( AbstractAssembly& _assembly, BuiltinContext& _builtinContext, - ControlFlow const& _controlFlow, + ControlFlowGraphs const& _controlFlow, FunctionLabels const& _functionLabels, CallSites const& _callSites, SSACFG const& _cfg, SSACFGStackLayout const& _stackLayout, - ControlFlow::FunctionGraphID _graphID); + ControlFlowGraphs::FunctionGraphID _graphID); void operator()(SSACFG::BlockId _blockId); void operator()(SSACFG::OperationId _opId, StackData const& _operationInputLayout); @@ -129,12 +129,12 @@ class CodeTransform AbstractAssembly& m_assembly; BuiltinContext& m_builtinContext; - ControlFlow const& m_controlFlow; + ControlFlowGraphs const& m_controlFlow; FunctionLabels const& m_functionLabels; CallSites const& m_callSites; SSACFG const& m_cfg; SSACFGStackLayout const& m_stackLayout; - ControlFlow::FunctionGraphID const m_graphID; + ControlFlowGraphs::FunctionGraphID const m_graphID; std::vector m_blockIsTransformed; std::vector m_blockLabels; diff --git a/libyul/backends/evm/ssa/ControlFlow.cpp b/libyul/backends/evm/ssa/ControlFlowGraphs.cpp similarity index 77% rename from libyul/backends/evm/ssa/ControlFlow.cpp rename to libyul/backends/evm/ssa/ControlFlowGraphs.cpp index 614406f2b..3a7df09cd 100644 --- a/libyul/backends/evm/ssa/ControlFlow.cpp +++ b/libyul/backends/evm/ssa/ControlFlowGraphs.cpp @@ -16,19 +16,19 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#include #include #include using namespace solidity::yul::ssa; -ControlFlowLiveness::ControlFlowLiveness(ControlFlow const& _controlFlow): - controlFlow(_controlFlow), +ControlFlowGraphsLiveness::ControlFlowGraphsLiveness(ControlFlowGraphs const& _controlFlow): + controlFlowGraphs(_controlFlow), cfgLiveness(_controlFlow.functionGraphs | ranges::views::transform([](auto const& _cfg) { return std::make_unique(*_cfg); }) | ranges::to) { } -std::string ControlFlowLiveness::toDot() const +std::string ControlFlowGraphsLiveness::toDot() const { - return controlFlow.get().toDot(this); + return controlFlowGraphs.get().toDot(this); } diff --git a/libyul/backends/evm/ssa/ControlFlow.h b/libyul/backends/evm/ssa/ControlFlowGraphs.h similarity index 82% rename from libyul/backends/evm/ssa/ControlFlow.h rename to libyul/backends/evm/ssa/ControlFlowGraphs.h index 21abfe274..0b0c273f5 100644 --- a/libyul/backends/evm/ssa/ControlFlow.h +++ b/libyul/backends/evm/ssa/ControlFlowGraphs.h @@ -26,18 +26,18 @@ namespace solidity::yul::ssa { -struct ControlFlow; +struct ControlFlowGraphs; -struct ControlFlowLiveness{ - explicit ControlFlowLiveness(ControlFlow const& _controlFlow); +struct ControlFlowGraphsLiveness{ + explicit ControlFlowGraphsLiveness(ControlFlowGraphs const& _controlFlow); - std::reference_wrapper controlFlow; + std::reference_wrapper controlFlowGraphs; std::vector> cfgLiveness; std::string toDot() const; }; -struct ControlFlow +struct ControlFlowGraphs { using FunctionGraphID = ssa::FunctionGraphID; @@ -50,10 +50,10 @@ struct ControlFlow return functionGraphs.at(_id).get(); } - std::string toDot(ControlFlowLiveness const* _liveness=nullptr) const + std::string toDot(ControlFlowGraphsLiveness const* _liveness=nullptr) const { if (_liveness) - yulAssert(&_liveness->controlFlow.get() == this); + yulAssert(&_liveness->controlFlowGraphs.get() == this); std::ostringstream output; output << "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 42e07df08..fde268607 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -18,7 +18,7 @@ #include -#include +#include #include #include #include @@ -59,7 +59,7 @@ std::string formatPhi(SSACFG const& _cfg, SSACFG::ValueId _phiId) class SSACFGDotExporter: public io::DotExporterBase { public: - SSACFGDotExporter(SSACFG const& _cfg, size_t _functionIndex, LivenessAnalysis const* _liveness, ControlFlow const* _controlFlow): + SSACFGDotExporter(SSACFG const& _cfg, size_t _functionIndex, LivenessAnalysis const* _liveness, ControlFlowGraphs const* _controlFlow): DotExporterBase(_cfg, _functionIndex), m_liveness(_liveness), m_controlFlow(_controlFlow) @@ -143,7 +143,7 @@ class SSACFGDotExporter: public io::DotExporterBase private: LivenessAnalysis const* m_liveness; - ControlFlow const* m_controlFlow; + ControlFlowGraphs const* m_controlFlow; std::unique_ptr m_junkAdmittingBlocks; }; @@ -168,7 +168,7 @@ std::string SSACFG::toDot( bool _includeDiGraphDefinition, std::optional _functionIndex, LivenessAnalysis const* _liveness, - ControlFlow const* _controlFlow + ControlFlowGraphs const* _controlFlow ) const { SSACFGDotExporter exporter(*this, _functionIndex.value_or(isMainGraph() ? 0 : 1), _liveness, _controlFlow); diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 63bcc6542..7540201e8 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -43,7 +43,7 @@ namespace solidity::yul::ssa { class LivenessAnalysis; -struct ControlFlow; +struct ControlFlowGraphs; class SSACFG { @@ -242,7 +242,7 @@ class SSACFG bool _includeDiGraphDefinition=true, std::optional _functionIndex=std::nullopt, LivenessAnalysis const* _liveness=nullptr, - ControlFlow const* _controlFlow=nullptr + ControlFlowGraphs const* _controlFlow=nullptr ) const; PhiValue const& phiInfo(ValueId const& _valueId) const diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index a74a329d5..7feed5dba 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include @@ -49,7 +49,7 @@ using namespace solidity::yul; using namespace solidity::yul::ssa; SSACFGBuilder::SSACFGBuilder( - ControlFlow& _controlFlow, + ControlFlowGraphs& _controlFlow, SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, @@ -65,7 +65,7 @@ SSACFGBuilder::SSACFGBuilder( { } -std::unique_ptr SSACFGBuilder::build( +std::unique_ptr SSACFGBuilder::build( AsmAnalysisInfo const& _analysisInfo, EVMDialect const& _dialect, Block const& _block, @@ -74,13 +74,13 @@ std::unique_ptr SSACFGBuilder::build( { ControlFlowSideEffectsCollector sideEffects(_dialect, _block); - auto controlFlow = std::make_unique(); - controlFlow->functionGraphs.emplace_back(std::make_unique( + auto controlFlowGraphs = std::make_unique(); + controlFlowGraphs->functionGraphs.emplace_back(std::make_unique( _dialect, _generateDebugInfo ? std::make_unique() : nullptr )); - SSACFG& mainGraph = *controlFlow->functionGraphs.back(); - SSACFGBuilder builder(*controlFlow, mainGraph, _analysisInfo, sideEffects, _dialect, _generateDebugInfo); + SSACFG& mainGraph = *controlFlowGraphs->functionGraphs.back(); + SSACFGBuilder builder(*controlFlowGraphs, mainGraph, _analysisInfo, sideEffects, _dialect, _generateDebugInfo); builder.m_currentBlock = mainGraph.makeBlock(debugDataOf(_block)); builder.sealBlock(builder.m_currentBlock); builder(_block); @@ -89,7 +89,7 @@ std::unique_ptr SSACFGBuilder::build( mainGraph.block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; transform::cleanUnreachableBlocks(mainGraph); transform::eliminateTrivialPhis(mainGraph); - return controlFlow; + return controlFlowGraphs; } diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index 8db9cfc6c..aed9e2c61 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -40,7 +40,7 @@ #include -#include +#include #include #include @@ -53,7 +53,7 @@ namespace solidity::yul::ssa class SSACFGBuilder { SSACFGBuilder( - ControlFlow& _controlFlow, + ControlFlowGraphs& _controlFlow, SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, @@ -63,7 +63,7 @@ class SSACFGBuilder public: SSACFGBuilder(SSACFGBuilder const&) = delete; SSACFGBuilder& operator=(SSACFGBuilder const&) = delete; - static std::unique_ptr build( + static std::unique_ptr build( AsmAnalysisInfo const& _analysisInfo, EVMDialect const& _dialect, Block const& _block, @@ -103,7 +103,7 @@ class SSACFGBuilder void emitUpsilon(SSACFG::BlockId _block, SSACFG::ValueId _value, SSACFG::ValueId _phi); void writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value); - ControlFlow& m_controlFlow; + ControlFlowGraphs& m_controlFlow; SSACFG& m_graph; AsmAnalysisInfo const& m_info; ControlFlowSideEffectsCollector const& m_sideEffects; diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index 50f58aeb4..6430ffb4b 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -18,7 +18,7 @@ #pragma once -#include +#include #include #include @@ -85,7 +85,7 @@ class StackSlot ValueID, // u32 Junk, // empty FunctionCallReturnLabel, // index into corresponding stack layout's call sites - FunctionReturnLabel // identifying the function graph via ControlFlow + FunctionReturnLabel // identifying the function graph via ControlFlowGraphs }; constexpr StackSlot() = default; @@ -101,13 +101,13 @@ class StackSlot constexpr bool isJunk() const noexcept { return kind() == Kind::Junk; } constexpr Kind kind() const noexcept { return m_kind; } - ControlFlow::FunctionGraphID functionReturnLabel() const { yulAssert(isFunctionReturnLabel()); return m_payload; } + ControlFlowGraphs::FunctionGraphID functionReturnLabel() const { yulAssert(isFunctionReturnLabel()); return m_payload; } CallSites::CallSiteID functionCallReturnLabel() const { yulAssert(isFunctionCallReturnLabel()); return m_payload; } SSACFG::ValueId valueID() const { yulAssert(isValueID()); return {m_payload, m_valueIdKind}; } static constexpr StackSlot makeJunk() { return {0, Kind::Junk}; } static constexpr StackSlot makeValueID(SSACFG::ValueId const& _valueID) { return {_valueID.value(), Kind::ValueID, _valueID.kind()}; } - static constexpr StackSlot makeFunctionReturnLabel(ControlFlow::FunctionGraphID const _graphID) { return {_graphID, Kind::FunctionReturnLabel}; } + static constexpr StackSlot makeFunctionReturnLabel(ControlFlowGraphs::FunctionGraphID const _graphID) { return {_graphID, Kind::FunctionReturnLabel}; } static constexpr StackSlot makeFunctionCallReturnLabel(CallSites::CallSiteID const _callSiteID) { return {_callSiteID, Kind::FunctionCallReturnLabel}; } auto operator<=>(StackSlot const&) const = default; diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index d9a2aba6b..5685a1bb9 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -82,7 +82,7 @@ void declareJunk(StackType& _stack, LivenessAnalysis::LivenessData const& _live) SSACFGStackLayout StackLayoutGenerator::generate( LivenessAnalysis const& _liveness, CallSites const& _callSites, - ControlFlow::FunctionGraphID const _graphID + ControlFlowGraphs::FunctionGraphID const _graphID ) { return StackLayoutGenerator(_liveness, _callSites, _graphID).m_resultLayout; @@ -91,7 +91,7 @@ SSACFGStackLayout StackLayoutGenerator::generate( StackLayoutGenerator::StackLayoutGenerator( LivenessAnalysis const& _liveness, CallSites const& _callSites, - ControlFlow::FunctionGraphID const _graphID + ControlFlowGraphs::FunctionGraphID const _graphID ): m_cfg(_liveness.cfg()), m_liveness(_liveness), diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.h b/libyul/backends/evm/ssa/StackLayoutGenerator.h index 07af8d293..cf9ef36ab 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.h +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.h @@ -35,14 +35,14 @@ class StackLayoutGenerator static SSACFGStackLayout generate( LivenessAnalysis const& _liveness, CallSites const& _callSites, - ControlFlow::FunctionGraphID _graphID + ControlFlowGraphs::FunctionGraphID _graphID ); private: explicit StackLayoutGenerator( LivenessAnalysis const& _liveness, CallSites const& _callSites, - ControlFlow::FunctionGraphID _graphID + ControlFlowGraphs::FunctionGraphID _graphID ); void defineStackIn(SSACFG::BlockId const& _blockId); @@ -51,7 +51,7 @@ class StackLayoutGenerator SSACFG const& m_cfg; LivenessAnalysis const& m_liveness; CallSites const& m_callSites; - ControlFlow::FunctionGraphID m_graphID; + ControlFlowGraphs::FunctionGraphID m_graphID; bool m_hasFunctionReturnLabel; std::unique_ptr m_junkAdmittingBlocksFinder; diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index b459a334d..e33e102eb 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -43,7 +43,7 @@ Json toJson(SSACFG const& _cfg, std::vector const& _values) return ret; } -Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation, ControlFlow const& _controlFlow) +Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation, ControlFlowGraphs const& _controlFlow) { Json opJson = Json::object(); std::visit(util::GenericVisitor{ @@ -83,7 +83,7 @@ Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation, return opJson; } -Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness, ControlFlow const& _controlFlow) +Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness, ControlFlowGraphs const& _controlFlow) { auto const valueToString = [&](LivenessAnalysis::LivenessData::LiveCounts::value_type const& _live) { return _live.first.str(_cfg); }; @@ -132,7 +132,7 @@ Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const return blockJson; } -Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis const* _liveness, ControlFlow const& _controlFlow) +Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis const* _liveness, ControlFlowGraphs const& _controlFlow) { Json blocksJson = Json::array(); util::BreadthFirstSearch bfs{{{_entryId}}}; @@ -172,7 +172,7 @@ Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis return blocksJson; } -Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness, ControlFlow const& _controlFlow) +Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness, ControlFlowGraphs const& _controlFlow) { Json functionJson = Json::object(); functionJson["type"] = "Function"; @@ -186,10 +186,10 @@ Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness, Contr } -Json io::json::exportControlFlow(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness) +Json io::json::exportControlFlow(ControlFlowGraphs const& _controlFlow, ControlFlowGraphsLiveness const* _liveness) { if (_liveness) - yulAssert(&_liveness->controlFlow.get() == &_controlFlow); + yulAssert(&_liveness->controlFlowGraphs.get() == &_controlFlow); Json yulObjectJson = Json::object(); yulObjectJson["blocks"] = exportBlock( diff --git a/libyul/backends/evm/ssa/io/JSONExporter.h b/libyul/backends/evm/ssa/io/JSONExporter.h index 5cca634aa..3e1045bc4 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.h +++ b/libyul/backends/evm/ssa/io/JSONExporter.h @@ -18,12 +18,12 @@ #pragma once -#include +#include #include namespace solidity::yul::ssa::io::json { -Json exportControlFlow(ControlFlow const& _controlFlow, ControlFlowLiveness const* _liveness); +Json exportControlFlow(ControlFlowGraphs const& _controlFlow, ControlFlowGraphsLiveness const* _liveness); } diff --git a/test/libyul/ssa/ControlFlowGraphTest.cpp b/test/libyul/ssa/ControlFlowGraphTest.cpp index 1fa9d7447..1e3e66919 100644 --- a/test/libyul/ssa/ControlFlowGraphTest.cpp +++ b/test/libyul/ssa/ControlFlowGraphTest.cpp @@ -73,14 +73,14 @@ TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::strin auto const* evmDialect = dynamic_cast(&yulStack.dialect()); yulAssert(evmDialect); - std::unique_ptr controlFlow = yul::ssa::SSACFGBuilder::build( + std::unique_ptr controlFlowGraphs = yul::ssa::SSACFGBuilder::build( *yulStack.parserResult()->analysisInfo, *evmDialect, yulStack.parserResult()->code()->root(), true ); - yul::ssa::ControlFlowLiveness liveness(*controlFlow); - m_obtainedResult = controlFlow->toDot(&liveness); + yul::ssa::ControlFlowGraphsLiveness liveness(*controlFlowGraphs); + m_obtainedResult = controlFlowGraphs->toDot(&liveness); auto result = checkResult(_stream, _linePrefix, _formatted); diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index 4ad4893b0..673ce31ea 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include @@ -60,7 +60,7 @@ class StackLayoutDotExporter: public io::DotExporterBase SSACFG const& _cfg, std::size_t _functionIndex, SSACFGStackLayout const& _layout, - ControlFlow const& _controlFlow + ControlFlowGraphs const& _controlFlow ): DotExporterBase(_cfg, _functionIndex), m_layout(_layout), @@ -111,7 +111,7 @@ class StackLayoutDotExporter: public io::DotExporterBase private: SSACFGStackLayout const& m_layout; - ControlFlow const& m_controlFlow; + ControlFlowGraphs const& m_controlFlow; }; } @@ -151,7 +151,7 @@ frontend::test::TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& auto const* evmDialect = dynamic_cast(object.dialect()); yulAssert(evmDialect); - std::unique_ptr const controlFlow = SSACFGBuilder::build( + std::unique_ptr const controlFlowGraphs = SSACFGBuilder::build( *object.analysisInfo, *evmDialect, object.code()->root(), @@ -163,15 +163,15 @@ frontend::test::TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& m_obtainedResult += "digraph SSACFG {\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\", rankdir=LR]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n"; - for (std::size_t index = 0; index < controlFlow->functionGraphs.size(); ++index) + for (std::size_t index = 0; index < controlFlowGraphs->functionGraphs.size(); ++index) { - auto const& cfg = *controlFlow->functionGraphs[index]; + auto const& cfg = *controlFlowGraphs->functionGraphs[index]; SSACFGStackLayout const layout = StackLayoutGenerator::generate( LivenessAnalysis(cfg), gatherCallSites(cfg), - static_cast(index) + static_cast(index) ); - StackLayoutDotExporter exporter(cfg, index, layout, *controlFlow); + StackLayoutDotExporter exporter(cfg, index, layout, *controlFlowGraphs); if (!cfg.isMainGraph()) m_obtainedResult += exporter.exportFunction(cfg, false); else diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index 045b755c2..6d8588d37 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -122,7 +122,7 @@ Slot parseSlot(std::string_view token) if (token.starts_with(returnLabelPrefix) && token.ends_with("]")) { auto const inner = token.substr(returnLabelPrefix.size(), token.size() - returnLabelPrefix.size() - 1); - if (auto const num = util::parseArithmetic(inner)) + if (auto const num = util::parseArithmetic(inner)) return Slot::makeFunctionReturnLabel(*num); throw std::runtime_error(fmt::format("Couldn't parse ReturnLabel token: {}", token)); } From af0afaeb065e9196ff31b87196375db390e0bb78 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:01:03 +0200 Subject: [PATCH 1277/1340] ssa cfg: remove FunctionCall yul AST pointers from (Builtin)Calls and drop ghost calls --- libyul/backends/evm/ssa/CodeTransform.cpp | 27 +++++++++++------- libyul/backends/evm/ssa/CodeTransform.h | 10 +++---- libyul/backends/evm/ssa/SSACFG.cpp | 2 +- libyul/backends/evm/ssa/SSACFG.h | 11 ++------ libyul/backends/evm/ssa/SSACFGBuilder.cpp | 22 +++++++-------- libyul/backends/evm/ssa/Stack.h | 28 ++++++++----------- .../backends/evm/ssa/StackLayoutGenerator.cpp | 2 +- libyul/backends/evm/ssa/StackUtils.cpp | 2 +- libyul/backends/evm/ssa/io/JSONExporter.cpp | 19 ++----------- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 2 +- 10 files changed, 54 insertions(+), 71 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 90f1072d9..30d1cfbd9 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -208,7 +208,7 @@ void CodeTransform::operator()(SSACFG::OperationId _opId, StackData const& _oper if (hasReturnLabel) { - auto const [it, inserted] = m_returnLabels.try_emplace(&std::get(_operation.kind).call.get(), 0); + auto const [it, inserted] = m_returnLabels.try_emplace(_opId, 0); yulAssert(inserted, "Call sites should be unique."); it->second = m_assembly.newLabelId(); } @@ -244,7 +244,7 @@ void CodeTransform::operator()(SSACFG::OperationId _opId, StackData const& _oper yulAssert(std::holds_alternative(_operation.kind)); yulAssert( returnLabelSlot.isFunctionCallReturnLabel() && - &m_callSites.functionCall(returnLabelSlot.functionCallReturnLabel()) == &std::get(_operation.kind).call.get() + m_callSites.operationId(returnLabelSlot.functionCallReturnLabel()) == _opId ); } @@ -262,14 +262,21 @@ void CodeTransform::operator()(SSACFG::OperationId _opId, StackData const& _oper std::visit(util::GenericVisitor{ [&](SSACFG::BuiltinCall const& _builtin) { m_assembly.setSourceLocation(opOriginLocation); - static_cast(_builtin.builtin.get()).generateCode( - _builtin.call, - m_assembly, - m_builtinContext - ); + auto const& builtin = m_cfg.evmDialect.builtin(_builtin.builtin); + // build up the call with transient args to handle literal arguments as needed + std::vector transientArgs; + transientArgs.reserve(builtin.literalArguments.size()); + auto litIt = _builtin.literalArguments.begin(); + for (size_t i = 0; i < builtin.literalArguments.size(); ++i) + if (builtin.literalArgument(i).has_value()) + transientArgs.emplace_back(*litIt++); + else + transientArgs.emplace_back(Identifier{}); + FunctionCall const transient{{}, BuiltinName{{}, _builtin.builtin}, std::move(transientArgs)}; + builtin.generateCode(transient, m_assembly, m_builtinContext); }, [&](SSACFG::Call const& _call) { - auto const* returnLabel = util::valueOrNullptr(m_returnLabels, &_call.call.get()); + auto const* returnLabel = util::valueOrNullptr(m_returnLabels, _opId); // check that if we have a return label, the call can continue yulAssert(!!returnLabel == _call.canContinue); m_assembly.setSourceLocation(opOriginLocation); @@ -388,8 +395,8 @@ void CodeTransform::operator()(SSACFG::BlockId const& _blockId, SSACFG::BasicBlo auto const& block = m_cfg.block(_blockId); yulAssert(!block.operations.empty(), "Terminated block must have at least one operation."); std::visit(util::GenericVisitor{ - [](SSACFG::BuiltinCall const& _builtin) { - yulAssert(_builtin.builtin.get().controlFlowSideEffects.terminatesOrReverts(), "Last operation of Terminated block must terminate or revert."); + [&](SSACFG::BuiltinCall const& _builtin) { + yulAssert(m_cfg.evmDialect.builtin(_builtin.builtin).controlFlowSideEffects.terminatesOrReverts(), "Last operation of Terminated block must terminate or revert."); }, [](SSACFG::Call const& _call) { yulAssert(!_call.canContinue, "Last operation of Terminated block must be a non-continuable call."); diff --git a/libyul/backends/evm/ssa/CodeTransform.h b/libyul/backends/evm/ssa/CodeTransform.h index 2a1e19f4e..7631c3154 100644 --- a/libyul/backends/evm/ssa/CodeTransform.h +++ b/libyul/backends/evm/ssa/CodeTransform.h @@ -66,9 +66,9 @@ struct AssemblyCallbacks } case StackSlot::Kind::FunctionCallReturnLabel: { - auto const& call = callSites->functionCall(_slot.functionCallReturnLabel()); - yulAssert(returnLabels->count(&call), "FunctionCallReturnLabel not pre-registered before shuffle."); - assembly->appendLabelReference(returnLabels->at(&call)); + auto const opId = callSites->operationId(_slot.functionCallReturnLabel()); + yulAssert(returnLabels->count(opId), "FunctionCallReturnLabel not pre-registered before shuffle."); + assembly->appendLabelReference(returnLabels->at(opId)); return; } case StackSlot::Kind::FunctionReturnLabel: @@ -86,7 +86,7 @@ struct AssemblyCallbacks SSACFG const* cfg{}; AbstractAssembly* assembly{}; CallSites const* callSites{}; - std::map const* returnLabels{}; + std::map const* returnLabels{}; }; static_assert(StackManipulationCallbackConcept); @@ -141,7 +141,7 @@ class CodeTransform AssemblyCallbacks m_assemblyCallbacks; StackData m_stackData; Stack m_stack; - std::map m_returnLabels; + std::map m_returnLabels; }; } diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index fde268607..d58f47035 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -111,7 +111,7 @@ class SSACFGDotExporter: public io::DotExporterBase return fmt::format("func{}", _call.graphID); }, [&](SSACFG::BuiltinCall const& _call) -> std::string { - return _call.builtin.get().name; + return m_cfg.evmDialect.builtin(_call.builtin).name; } }, operation.kind); if (!operation.outputs.empty()) diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 7540201e8..9d47070ea 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -34,9 +34,6 @@ #include #include -#include -#include -#include #include #include @@ -70,13 +67,13 @@ class SSACFG struct BuiltinCall { - std::reference_wrapper builtin; - std::reference_wrapper call; + BuiltinHandle builtin; + /// Literal-kind arguments + std::vector literalArguments; }; struct Call { FunctionGraphID graphID; - std::reference_wrapper call; bool canContinue; }; @@ -281,8 +278,6 @@ class SSACFG bool canContinue = true; std::vector arguments; std::size_t numReturns = 0; - // Container for artificial calls generated for switch statements. - std::list ghostCalls; bool isMainGraph() const { return name.empty(); } }; diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 7feed5dba..7f9a9c5e6 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -234,18 +234,10 @@ void SSACFGBuilder::operator()(Switch const& _switch) yulAssert(equalityBuiltinHandle); auto makeValueCompare = [&](Case const& _case) { - FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(FunctionCall{ - debugDataOf(_case), - BuiltinName{{}, *equalityBuiltinHandle}, - {*_case.value /* skip second argument */ } - }); auto outputValue = m_graph.newVariable(m_currentBlock); auto opId = m_graph.makeOperation(SSACFG::Operation{ {outputValue}, - SSACFG::BuiltinCall{ - m_dialect.builtin(*equalityBuiltinHandle), - ghostCall - }, + SSACFG::BuiltinCall{*equalityBuiltinHandle, {}}, {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression} }, debugDataOf(_case)); currentBlock().operations.emplace_back(opId); @@ -452,7 +444,15 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const [&](BuiltinName const& _builtinName) { auto const& builtin = m_dialect.builtin(_builtinName.handle); - SSACFG::Operation result{{}, SSACFG::BuiltinCall{builtin, _call}, {}}; + yulAssert(_call.arguments.size() == builtin.numParameters); + std::vector literalArguments; + for (auto&& [kind, arg]: ranges::views::zip(builtin.literalArguments, _call.arguments)) + if (kind.has_value()) + { + yulAssert(std::holds_alternative(arg)); + literalArguments.emplace_back(std::get(arg)); + } + SSACFG::Operation result{{}, SSACFG::BuiltinCall{_builtinName.handle, std::move(literalArguments)}, {}}; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) if (!builtin.literalArgument(idx).has_value()) result.inputs.emplace_back(std::visit(*this, arg)); @@ -470,7 +470,7 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const canContinue = m_sideEffects.functionSideEffects().at(definition).canContinue; auto const calleeIt = m_functionScopeToID.find(&function); yulAssert(calleeIt != m_functionScopeToID.end(), "Called function has no registered graph id."); - SSACFG::Operation result{{}, SSACFG::Call{calleeIt->second, _call, canContinue}, {}}; + SSACFG::Operation result{{}, SSACFG::Call{calleeIt->second, canContinue}, {}}; for (auto const& arg: _call.arguments | ranges::views::reverse) result.inputs.emplace_back(std::visit(*this, arg)); for (size_t i = 0; i < function.numReturns; ++i) diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index 6430ffb4b..085edef1b 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -27,46 +27,41 @@ #include #include -namespace solidity::yul -{ - -struct FunctionCall; - -namespace ssa +namespace solidity::yul::ssa { /// Registry for tracking function call sites. /// -/// Maps FunctionCall AST nodes to unique numeric IDs. These IDs are used +/// Maps user-function-call operations to unique numeric IDs. These IDs are used /// to generate return labels for function calls in the EVM bytecode. class CallSites { public: using CallSiteID = std::uint32_t; - std::optional callSiteID(FunctionCall const* _functionCall) const + std::optional callSiteID(OperationId _op) const { - if (auto const it = ranges::find(m_data, _functionCall); it != m_data.end()) + if (auto const it = ranges::find(m_data, _op); it != m_data.end()) return static_cast(std::distance(m_data.begin(), it)); return std::nullopt; } - FunctionCall const& functionCall(CallSiteID _callSite) const + OperationId operationId(CallSiteID _callSite) const { yulAssert(_callSite < m_data.size()); - return *m_data[_callSite]; + return m_data[_callSite]; } - CallSiteID addCallSite(FunctionCall const* _functionCall) + CallSiteID addCallSite(OperationId _op) { - if (auto const id = callSiteID(_functionCall)) + if (auto const id = callSiteID(_op)) return *id; - yulAssert(_functionCall); - m_data.emplace_back(_functionCall); + yulAssert(_op.hasValue()); + m_data.emplace_back(_op); return static_cast(m_data.size() - 1); } private: - std::vector m_data; + std::vector m_data; }; /// A discriminated union corresponding to a single EVM stack slot. @@ -309,4 +304,3 @@ class Stack }; } -} diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 5685a1bb9..d835d26dd 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -239,7 +239,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) if (auto const* call = std::get_if(&operation.kind)) if (call->canContinue) { - auto const callSiteID = m_callSites.callSiteID(&call->call.get()); + auto const callSiteID = m_callSites.callSiteID(block.operations[operationIndex]); yulAssert(callSiteID.has_value()); requiredStackTop.emplace_back(Slot::makeFunctionCallReturnLabel(*callSiteID)); } diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index 883a1f3b8..3b0c183ee 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -206,7 +206,7 @@ CallSites solidity::yul::ssa::gatherCallSites(SSACFG const& _cfg) for (auto const opId: block.operations) if (auto const* call = std::get_if(&_cfg.operation(opId).kind)) if (call->canContinue) - result.addCallSite(&call->call.get()); + result.addCallSite(opId); } return result; } diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index e33e102eb..3d0de2f04 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -54,26 +54,13 @@ Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation, [&](SSACFG::BuiltinCall const& _call) { _ret["type"] = "BuiltinCall"; Json builtinArgsJson = Json::array(); - auto const& builtin = _call.builtin.get(); - if (!builtin.literalArguments.empty()) - { - auto const& functionCallArgs = _call.call.get().arguments; - for (size_t i = 0; i < builtin.literalArguments.size(); ++i) - { - std::optional const& argument = builtin.literalArguments[i]; - if (argument.has_value() && i < functionCallArgs.size()) - { - // The function call argument at index i must be a literal if builtin.literalArguments[i] is not nullopt - yulAssert(std::holds_alternative(functionCallArgs[i])); - builtinArgsJson.push_back(formatLiteral(std::get(functionCallArgs[i]))); - } - } - } + for (auto const& literal: _call.literalArguments) + builtinArgsJson.push_back(formatLiteral(literal)); if (!builtinArgsJson.empty()) opJson["literalArgs"] = builtinArgsJson; - opJson["op"] = _call.builtin.get().name; + opJson["op"] = _cfg.evmDialect.builtin(_call.builtin).name; }, }, _operation.kind); diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index 673ce31ea..d54a0a40d 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -92,7 +92,7 @@ class StackLayoutDotExporter: public io::DotExporterBase _out << escapeLabel(m_controlFlow.functionGraph(_call.graphID)->name); }, [&](SSACFG::BuiltinCall const& _call) { - _out << escapeLabel(_call.builtin.get().name); + _out << escapeLabel(m_cfg.evmDialect.builtin(_call.builtin).name); } }, operation.kind); _out << "\\l\\\n"; From d4cb9cdefb510013316ebaa8683ab754109a61d0 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 27 Apr 2026 11:57:15 +0200 Subject: [PATCH 1278/1340] SSA CFG: rename OperationId to InstId Pure type rename. Method names (operation(), makeOperation, operationId, setOperationDebugData, etc.) and the formatter's "op{}" output are left unchanged. This is preparation for the upcoming Operation/Phi/Literal/Upsilon unification under a single Inst type. --- libyul/backends/evm/ssa/CodeTransform.cpp | 2 +- libyul/backends/evm/ssa/CodeTransform.h | 6 +++--- libyul/backends/evm/ssa/SSACFG.h | 12 ++++++------ libyul/backends/evm/ssa/SSACFGDebugInfo.h | 4 ++-- libyul/backends/evm/ssa/SSACFGTypes.h | 8 ++++---- libyul/backends/evm/ssa/Stack.h | 8 ++++---- .../evm/ssa/transform/UnreachableBlockCleaner.h | 2 +- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 30d1cfbd9..c66505fe8 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -199,7 +199,7 @@ void CodeTransform::operator()(SSACFG::BlockId const _blockId) std::visit(util::GenericVisitor{ [this, &_blockId](auto const& exit) { (*this)(_blockId, exit); } }, block.exit); } -void CodeTransform::operator()(SSACFG::OperationId _opId, StackData const& _operationInputLayout) +void CodeTransform::operator()(SSACFG::InstId _opId, StackData const& _operationInputLayout) { SSACFG::Operation const& _operation = m_cfg.operation(_opId); bool const hasReturnLabel = diff --git a/libyul/backends/evm/ssa/CodeTransform.h b/libyul/backends/evm/ssa/CodeTransform.h index 7631c3154..ad2a60575 100644 --- a/libyul/backends/evm/ssa/CodeTransform.h +++ b/libyul/backends/evm/ssa/CodeTransform.h @@ -86,7 +86,7 @@ struct AssemblyCallbacks SSACFG const* cfg{}; AbstractAssembly* assembly{}; CallSites const* callSites{}; - std::map const* returnLabels{}; + std::map const* returnLabels{}; }; static_assert(StackManipulationCallbackConcept); @@ -118,7 +118,7 @@ class CodeTransform ControlFlowGraphs::FunctionGraphID _graphID); void operator()(SSACFG::BlockId _blockId); - void operator()(SSACFG::OperationId _opId, StackData const& _operationInputLayout); + void operator()(SSACFG::InstId _opId, StackData const& _operationInputLayout); void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::MainExit const& _mainExit); void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::ConditionalJump const& _conditionalJump); void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::Jump const& _jump); @@ -141,7 +141,7 @@ class CodeTransform AssemblyCallbacks m_assemblyCallbacks; StackData m_stackData; Stack m_stack; - std::map m_returnLabels; + std::map m_returnLabels; }; } diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 9d47070ea..e0bbd63d7 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -62,7 +62,7 @@ class SSACFG ~SSACFG() = default; using BlockId = ssa::BlockId; - using OperationId = ssa::OperationId; + using InstId = ssa::InstId; using ValueId = ssa::ValueId; struct BuiltinCall @@ -111,7 +111,7 @@ class SSACFG struct Terminated {}; std::vector entries; std::vector phis; - std::vector operations; + std::vector operations; /// Upsilon assignments placed at the block exit (before the terminator). /// They record the phi pre-images for successor blocks. std::vector upsilons; @@ -162,16 +162,16 @@ class SSACFG BasicBlock const& block(BlockId _id) const { return m_blocks.at(_id.value); } size_t numBlocks() const { return m_blocks.size(); } - OperationId makeOperation(Operation _op, langutil::DebugData::ConstPtr _debugData = {}) + InstId makeOperation(Operation _op, langutil::DebugData::ConstPtr _debugData = {}) { - OperationId id{static_cast(m_operations.size())}; + InstId id{static_cast(m_operations.size())}; m_operations.emplace_back(std::move(_op)); if (debugInfo && _debugData) debugInfo->setOperationDebugData(id, std::move(_debugData)); return id; } - Operation& operation(OperationId _id) { return m_operations.at(_id.value); } - Operation const& operation(OperationId _id) const { return m_operations.at(_id.value); } + Operation& operation(InstId _id) { return m_operations.at(_id.value); } + Operation const& operation(InstId _id) const { return m_operations.at(_id.value); } private: std::vector m_blocks; diff --git a/libyul/backends/evm/ssa/SSACFGDebugInfo.h b/libyul/backends/evm/ssa/SSACFGDebugInfo.h index d026147b1..d308da6b4 100644 --- a/libyul/backends/evm/ssa/SSACFGDebugInfo.h +++ b/libyul/backends/evm/ssa/SSACFGDebugInfo.h @@ -55,14 +55,14 @@ struct SSACFGDebugInfo return getOrEmpty(m_exitDebugData, _id.value); } - void setOperationDebugData(OperationId _id, langutil::DebugData::ConstPtr _data) + void setOperationDebugData(InstId _id, langutil::DebugData::ConstPtr _data) { yulAssert(_id.hasValue()); ensureSize(m_operationDebugData, _id.value); m_operationDebugData[_id.value] = std::move(_data); } - langutil::DebugData::ConstPtr const& operationDebugData(OperationId _id) const + langutil::DebugData::ConstPtr const& operationDebugData(InstId _id) const { return getOrEmpty(m_operationDebugData, _id.value); } diff --git a/libyul/backends/evm/ssa/SSACFGTypes.h b/libyul/backends/evm/ssa/SSACFGTypes.h index 6be70af7f..7b322eddb 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.h +++ b/libyul/backends/evm/ssa/SSACFGTypes.h @@ -44,12 +44,12 @@ struct BlockId auto operator<=>(BlockId const&) const = default; }; -struct OperationId +struct InstId { using ValueType = std::uint32_t; ValueType value = std::numeric_limits::max(); bool hasValue() const { return value != std::numeric_limits::max(); } - auto operator<=>(OperationId const&) const = default; + auto operator<=>(InstId const&) const = default; }; class ValueId @@ -112,12 +112,12 @@ struct fmt::formatter }; template<> -struct fmt::formatter +struct fmt::formatter { static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } template - auto format(solidity::yul::ssa::OperationId const& _opId, FormatContext& _ctx) const -> decltype(_ctx.out()) + auto format(solidity::yul::ssa::InstId const& _opId, FormatContext& _ctx) const -> decltype(_ctx.out()) { if (!_opId.hasValue()) return fmt::format_to(_ctx.out(), "empty"); diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index 085edef1b..e415bfab6 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -39,20 +39,20 @@ class CallSites public: using CallSiteID = std::uint32_t; - std::optional callSiteID(OperationId _op) const + std::optional callSiteID(InstId _op) const { if (auto const it = ranges::find(m_data, _op); it != m_data.end()) return static_cast(std::distance(m_data.begin(), it)); return std::nullopt; } - OperationId operationId(CallSiteID _callSite) const + InstId operationId(CallSiteID _callSite) const { yulAssert(_callSite < m_data.size()); return m_data[_callSite]; } - CallSiteID addCallSite(OperationId _op) + CallSiteID addCallSite(InstId _op) { if (auto const id = callSiteID(_op)) return *id; @@ -61,7 +61,7 @@ class CallSites return static_cast(m_data.size() - 1); } private: - std::vector m_data; + std::vector m_data; }; /// A discriminated union corresponding to a single EVM stack slot. diff --git a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h index f3edf5161..f3ef1592c 100644 --- a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h +++ b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h @@ -17,7 +17,7 @@ // SPDX-License-Identifier: GPL-3.0 /** * Removes unreachable blocks from an SSA CFG and cleans up entry lists referencing them. - * Note that this invalidates ValueIds and OperationIds pointing into the (unreachable) blocks. + * Note that this invalidates ValueIds and InstIds pointing into the (unreachable) blocks. */ #pragma once From 34069ac587cd09ab045c654a07423bf1ee86f870 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 27 Apr 2026 12:01:11 +0200 Subject: [PATCH 1279/1340] SSA CFG: move ValueId::str into its own SSACFGTypes.cpp --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/ssa/SSACFG.cpp | 15 --------- libyul/backends/evm/ssa/SSACFGTypes.cpp | 41 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 libyul/backends/evm/ssa/SSACFGTypes.cpp diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index bdcd157ab..210fad779 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -91,6 +91,7 @@ add_library(yul backends/evm/ssa/SSACFGBuilder.cpp backends/evm/ssa/SSACFGBuilder.h backends/evm/ssa/SSACFGDebugInfo.h + backends/evm/ssa/SSACFGTypes.cpp backends/evm/ssa/SSACFGTypes.h backends/evm/ssa/Stack.cpp backends/evm/ssa/Stack.h diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index d58f47035..8c54d89d2 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -149,21 +149,6 @@ class SSACFGDotExporter: public io::DotExporterBase } -std::string ValueId::str(SSACFG const& _cfg) const -{ - if (!hasValue()) - return "INVALID"; - switch (kind()) - { - case Kind::Literal: return toCompactHexWithPrefix(_cfg.literalInfo(*this).value); - case Kind::Variable: return fmt::format("v{}", value()); - case Kind::Phi: return fmt::format("phi{}", value()); - case Kind::Unreachable: return "[unreachable]"; - } - unreachable(); -} - - std::string SSACFG::toDot( bool _includeDiGraphDefinition, std::optional _functionIndex, diff --git a/libyul/backends/evm/ssa/SSACFGTypes.cpp b/libyul/backends/evm/ssa/SSACFGTypes.cpp new file mode 100644 index 000000000..466afe5b9 --- /dev/null +++ b/libyul/backends/evm/ssa/SSACFGTypes.cpp @@ -0,0 +1,41 @@ +/* + 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 + +#include + +#include + +#include +#include + +using namespace solidity::util; +using namespace solidity::yul::ssa; + +std::string ValueId::str(SSACFG const& _cfg) const +{ + if (!hasValue()) + return "INVALID"; + switch (kind()) + { + case Kind::Literal: return toCompactHexWithPrefix(_cfg.literalInfo(*this).value); + case Kind::Variable: return fmt::format("v{}", value()); + case Kind::Phi: return fmt::format("phi{}", value()); + case Kind::Unreachable: return "[unreachable]"; + } + unreachable(); +} From 815fadc639271c0fca35aa4e444291c074835ab0 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 27 Apr 2026 12:08:09 +0200 Subject: [PATCH 1280/1340] SSA CFG: record defining block on Operation --- libyul/backends/evm/ssa/SSACFG.h | 11 ++++++++++- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index e0bbd63d7..8d23b7a88 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -90,6 +90,8 @@ class SSACFG std::vector outputs{}; std::variant kind; std::vector inputs{}; + /// Block this operation lives in. Set by `makeOperation`. + BlockId block{}; }; struct BasicBlock { @@ -162,8 +164,15 @@ class SSACFG BasicBlock const& block(BlockId _id) const { return m_blocks.at(_id.value); } size_t numBlocks() const { return m_blocks.size(); } - InstId makeOperation(Operation _op, langutil::DebugData::ConstPtr _debugData = {}) + InstId makeOperation(BlockId _block, Operation _op, langutil::DebugData::ConstPtr _debugData = {}) { + yulAssert(_block.hasValue()); + for (ValueId const& output: _op.outputs) + { + yulAssert(output.isVariable()); + yulAssert(m_variables.at(output.value()).definingBlock == _block); + } + _op.block = _block; InstId id{static_cast(m_operations.size())}; m_operations.emplace_back(std::move(_op)); if (debugInfo && _debugData) diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 7f9a9c5e6..f136206c6 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -235,7 +235,7 @@ void SSACFGBuilder::operator()(Switch const& _switch) auto makeValueCompare = [&](Case const& _case) { auto outputValue = m_graph.newVariable(m_currentBlock); - auto opId = m_graph.makeOperation(SSACFG::Operation{ + auto opId = m_graph.makeOperation(m_currentBlock, SSACFG::Operation{ {outputValue}, SSACFG::BuiltinCall{*equalityBuiltinHandle, {}}, {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression} @@ -479,7 +479,7 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const } }, _call.functionName); auto results = operation.outputs; - currentBlock().operations.emplace_back(m_graph.makeOperation(std::move(operation), debugDataOf(_call))); + currentBlock().operations.emplace_back(m_graph.makeOperation(m_currentBlock, std::move(operation), debugDataOf(_call))); if (!canContinue) { currentBlock().exit = SSACFG::BasicBlock::Terminated{}; From 7d8c383dae1dd16a5ef26947f2e68e03d6adf49d Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 27 Apr 2026 12:49:24 +0200 Subject: [PATCH 1281/1340] SSA CFG: relocate value storage into InstructionStore --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/ssa/InstructionStore.h | 176 +++++++++++++++++++++ libyul/backends/evm/ssa/SSACFG.h | 160 +++++-------------- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 10 +- 4 files changed, 219 insertions(+), 128 deletions(-) create mode 100644 libyul/backends/evm/ssa/InstructionStore.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 210fad779..ca23f622c 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -78,6 +78,7 @@ add_library(yul backends/evm/ssa/CodeTransform.h backends/evm/ssa/ControlFlowGraphs.cpp backends/evm/ssa/ControlFlowGraphs.h + backends/evm/ssa/InstructionStore.h backends/evm/ssa/JunkAdmittingBlocksFinder.cpp backends/evm/ssa/JunkAdmittingBlocksFinder.h backends/evm/ssa/LivenessAnalysis.cpp diff --git a/libyul/backends/evm/ssa/InstructionStore.h b/libyul/backends/evm/ssa/InstructionStore.h new file mode 100644 index 000000000..64fb0feea --- /dev/null +++ b/libyul/backends/evm/ssa/InstructionStore.h @@ -0,0 +1,176 @@ +/* + 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 +/** + * Owns the instruction table of an SSACFG: hands out InstIds, stores opcode + * payloads, and provides lookups. Has no knowledge of basic blocks or debug + * information; SSACFG composes those on top. + */ + +#pragma once + +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace solidity::yul::ssa +{ + +class InstructionStore +{ +public: + struct BuiltinCall + { + BuiltinHandle builtin; + /// Literal-kind arguments + std::vector literalArguments; + }; + struct Call + { + FunctionGraphID graphID; + bool canContinue; + }; + struct Operation + { + std::vector outputs{}; + std::variant kind; + BlockId block{}; + std::vector inputs{}; + }; + struct LiteralValue + { + u256 value; + }; + struct VariableValue + { + BlockId definingBlock; + }; + struct PhiValue + { + BlockId block; + }; + struct UnreachableValue {}; + + InstructionStore() = default; + InstructionStore(InstructionStore const&) = delete; + InstructionStore(InstructionStore&&) = default; + InstructionStore& operator=(InstructionStore const&) = delete; + InstructionStore& operator=(InstructionStore&&) = default; + ~InstructionStore() = default; + + Operation& operation(InstId const _id) { return m_operations.at(_id.value); } + Operation const& operation(InstId const _id) const { return m_operations.at(_id.value); } + + LiteralValue const& literalInfo(ValueId const& _valueId) const + { + yulAssert(_valueId.hasValue() && _valueId.isLiteral()); + return m_literals.at(_valueId.value()); + } + + PhiValue const& phiInfo(ValueId const& _valueId) const + { + yulAssert(_valueId.hasValue() && _valueId.isPhi()); + return m_phis.at(_valueId.value()); + } + PhiValue& phiInfo(ValueId const& _valueId) + { + yulAssert(_valueId.hasValue() && _valueId.isPhi()); + return m_phis.at(_valueId.value()); + } + + VariableValue const& variableInfo(ValueId const& _valueId) const + { + yulAssert(_valueId.hasValue() && _valueId.isVariable()); + return m_variables.at(_valueId.value()); + } + + ValueId newPhi(BlockId const _definingBlock) + { + yulAssert(_definingBlock.hasValue()); + m_phis.emplace_back(PhiValue{_definingBlock}); + auto const value = m_phis.size() - 1; + yulAssert(value < std::numeric_limits::max()); + return ValueId::makePhi(static_cast(value)); + } + + ValueId newVariable(BlockId const _definingBlock) + { + yulAssert(_definingBlock.hasValue()); + m_variables.emplace_back(VariableValue{_definingBlock}); + auto const value = m_variables.size() - 1; + yulAssert(value < std::numeric_limits::max()); + return ValueId::makeVariable(static_cast(value)); + } + + ValueId unreachableValue() + { + if (!m_unreachableValue) + m_unreachableValue = ValueId::makeUnreachable(); + return *m_unreachableValue; + } + + /// Look up or allocate a Literal ValueId for `_value`. Returns the ValueId and + /// whether a new entry was allocated (false if it was deduplicated). + std::pair newLiteral(u256 _value) + { + if (auto const it = m_literalMapping.find(_value); it != m_literalMapping.end()) + { + yulAssert(it->second.hasValue() && m_literals[it->second.value()].value == _value); + return {it->second, false}; + } + m_literals.emplace_back(LiteralValue{std::move(_value)}); + auto const idx = m_literals.size() - 1; + yulAssert(idx < std::numeric_limits::max()); + auto const id = ValueId::makeLiteral(static_cast(idx)); + m_literalMapping.emplace(m_literals.back().value, id); + return {id, true}; + } + + InstId makeOperation(BlockId const _block, Operation _op) + { + yulAssert(_block.hasValue()); + for (ValueId const& output: _op.outputs) + { + yulAssert(output.isVariable()); + yulAssert(m_variables.at(output.value()).definingBlock == _block); + } + _op.block = _block; + InstId const id{static_cast(m_operations.size())}; + m_operations.emplace_back(std::move(_op)); + return id; + } + +private: + std::vector m_operations; + std::vector m_literals; + std::map m_literalMapping; + std::vector m_phis; + std::vector m_variables; + std::optional m_unreachableValue; +}; + +} diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 8d23b7a88..51da0db72 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -21,6 +21,7 @@ #pragma once +#include #include #include @@ -65,17 +66,9 @@ class SSACFG using InstId = ssa::InstId; using ValueId = ssa::ValueId; - struct BuiltinCall - { - BuiltinHandle builtin; - /// Literal-kind arguments - std::vector literalArguments; - }; - struct Call - { - FunctionGraphID graphID; - bool canContinue; - }; + using BuiltinCall = InstructionStore::BuiltinCall; + using Call = InstructionStore::Call; + using Operation = InstructionStore::Operation; /// Upsilon records a phi pre-image at a block exit. /// Upsilon(value, phi) means: the value flowing into `phi` from this block is `value`. @@ -86,13 +79,6 @@ class SSACFG ValueId phi; ///< target phi }; - struct Operation { - std::vector outputs{}; - std::variant kind; - std::vector inputs{}; - /// Block this operation lives in. Set by `makeOperation`. - BlockId block{}; - }; struct BasicBlock { struct MainExit {}; @@ -131,30 +117,17 @@ class SSACFG } } - bool isMainExitBlock() const - { - return std::holds_alternative(exit); - } - - bool isTerminationBlock() const - { - return std::holds_alternative(exit); - } - - bool isFunctionReturnBlock() const - { - return std::holds_alternative(exit); - } - - bool isJumpBlock() const - { - return std::holds_alternative(exit); - } + bool isMainExitBlock() const { return std::holds_alternative(exit); } + bool isTerminationBlock() const { return std::holds_alternative(exit); } + bool isFunctionReturnBlock() const { return std::holds_alternative(exit); } + bool isJumpBlock() const { return std::holds_alternative(exit); } }; BlockId makeBlock(langutil::DebugData::ConstPtr _debugData) { - BlockId blockId { static_cast(m_blocks.size()) }; + // max itself is reserved for the 'empty' block + yulAssert(m_blocks.size() < std::numeric_limits::max()); + BlockId const blockId{static_cast(m_blocks.size())}; m_blocks.emplace_back(BasicBlock{{}, {}, {}, {}, BasicBlock::Terminated{}}); if (debugInfo) debugInfo->setBlockDebugData(blockId, std::move(_debugData)); @@ -164,84 +137,49 @@ class SSACFG BasicBlock const& block(BlockId _id) const { return m_blocks.at(_id.value); } size_t numBlocks() const { return m_blocks.size(); } - InstId makeOperation(BlockId _block, Operation _op, langutil::DebugData::ConstPtr _debugData = {}) - { - yulAssert(_block.hasValue()); - for (ValueId const& output: _op.outputs) - { - yulAssert(output.isVariable()); - yulAssert(m_variables.at(output.value()).definingBlock == _block); - } - _op.block = _block; - InstId id{static_cast(m_operations.size())}; - m_operations.emplace_back(std::move(_op)); - if (debugInfo && _debugData) - debugInfo->setOperationDebugData(id, std::move(_debugData)); - return id; - } - Operation& operation(InstId _id) { return m_operations.at(_id.value); } - Operation const& operation(InstId _id) const { return m_operations.at(_id.value); } + InstructionStore& instructionStore() { return m_instructions; } + InstructionStore const& instructionStore() const { return m_instructions; } + + Operation& operation(InstId _id) { return m_instructions.operation(_id); } + Operation const& operation(InstId _id) const { return m_instructions.operation(_id); } + + InstructionStore::LiteralValue const& literalInfo(ValueId const& _valueId) const { return m_instructions.literalInfo(_valueId); } + InstructionStore::PhiValue const& phiInfo(ValueId const& _valueId) const { return m_instructions.phiInfo(_valueId); } + InstructionStore::PhiValue& phiInfo(ValueId const& _valueId) { return m_instructions.phiInfo(_valueId); } + InstructionStore::VariableValue const& variableInfo(ValueId const& _valueId) const { return m_instructions.variableInfo(_valueId); } -private: - std::vector m_blocks; - std::vector m_operations; -public: - struct LiteralValue { - u256 value; - }; - struct VariableValue { - BlockId definingBlock; - }; - struct PhiValue { - BlockId block; - }; - struct UnreachableValue {}; ValueId newPhi(BlockId const _definingBlock) { - m_phis.emplace_back(PhiValue{_definingBlock}); - auto const value = m_phis.size() - 1; - yulAssert(value < std::numeric_limits::max()); - auto const id = ValueId::makePhi(static_cast(value)); + auto const id = m_instructions.newPhi(_definingBlock); if (debugInfo) debugInfo->setValueDebugData(id, debugInfo->blockDebugData(_definingBlock)); return id; } + ValueId newVariable(BlockId const _definingBlock) { - m_variables.emplace_back(VariableValue{_definingBlock}); - auto const value = m_variables.size() - 1; - yulAssert(value < std::numeric_limits::max()); - auto const id = ValueId::makeVariable(static_cast(value)); + auto const id = m_instructions.newVariable(_definingBlock); if (debugInfo) debugInfo->setValueDebugData(id, debugInfo->blockDebugData(_definingBlock)); return id; } - ValueId unreachableValue() - { - if (!m_unreachableValue) - m_unreachableValue = ValueId::makeUnreachable(); - return *m_unreachableValue; - } + ValueId unreachableValue() { return m_instructions.unreachableValue(); } ValueId newLiteral(langutil::DebugData::ConstPtr _debugData, u256 _value) { - auto const it = m_literalMapping.find(_value); - if (it != m_literalMapping.end()) - { - ValueId const& valueId = it->second; - yulAssert(valueId.hasValue() && m_literals[valueId.value()].value == _value); - return valueId; - } + auto const [id, allocated] = m_instructions.newLiteral(std::move(_value)); + if (debugInfo && allocated) + debugInfo->setValueDebugData(id, std::move(_debugData)); + return id; + } - m_literals.emplace_back(LiteralValue{std::move(_value)}); - auto const value = m_literals.size() - 1; - yulAssert(value < std::numeric_limits::max()); - auto const literalId = ValueId::makeLiteral(static_cast(value)); + InstId makeOperation(BlockId _block, Operation _op, langutil::DebugData::ConstPtr _debugData = {}) + { + auto const id = m_instructions.makeOperation(_block, std::move(_op)); if (debugInfo) - debugInfo->setValueDebugData(literalId, std::move(_debugData)); - m_literalMapping.emplace(_value, literalId); - return literalId; + debugInfo->setOperationDebugData(id, std::move(_debugData)); + return id; } std::string toDot( @@ -251,33 +189,9 @@ class SSACFG ControlFlowGraphs const* _controlFlow=nullptr ) const; - PhiValue const& phiInfo(ValueId const& _valueId) const - { - yulAssert(_valueId.hasValue() && _valueId.isPhi()); - return m_phis.at(_valueId.value()); - } - PhiValue& phiInfo(ValueId const& _valueId) - { - yulAssert(_valueId.hasValue() && _valueId.isPhi()); - return m_phis.at(_valueId.value()); - } - LiteralValue const& literalInfo(ValueId const& _valueId) const - { - yulAssert(_valueId.hasValue() && _valueId.isLiteral()); - return m_literals.at(_valueId.value()); - } - VariableValue const& variableInfo(ValueId const& _valueId) const - { - yulAssert(_valueId.hasValue() && _valueId.isVariable()); - return m_variables.at(_valueId.value()); - } - private: - std::vector m_literals; - std::map m_literalMapping; - std::vector m_phis; - std::vector m_variables; - std::optional m_unreachableValue; + std::vector m_blocks; + InstructionStore m_instructions; public: EVMDialect const& evmDialect; std::unique_ptr debugInfo; diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index f136206c6..1e1fb479f 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -236,9 +236,9 @@ void SSACFGBuilder::operator()(Switch const& _switch) auto makeValueCompare = [&](Case const& _case) { auto outputValue = m_graph.newVariable(m_currentBlock); auto opId = m_graph.makeOperation(m_currentBlock, SSACFG::Operation{ - {outputValue}, - SSACFG::BuiltinCall{*equalityBuiltinHandle, {}}, - {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression} + .outputs = {outputValue}, + .kind = SSACFG::BuiltinCall{*equalityBuiltinHandle, {}}, + .inputs = {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression}, }, debugDataOf(_case)); currentBlock().operations.emplace_back(opId); return outputValue; @@ -452,7 +452,7 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const yulAssert(std::holds_alternative(arg)); literalArguments.emplace_back(std::get(arg)); } - SSACFG::Operation result{{}, SSACFG::BuiltinCall{_builtinName.handle, std::move(literalArguments)}, {}}; + SSACFG::Operation result{.kind = SSACFG::BuiltinCall{_builtinName.handle, std::move(literalArguments)}}; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) if (!builtin.literalArgument(idx).has_value()) result.inputs.emplace_back(std::visit(*this, arg)); @@ -470,7 +470,7 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const canContinue = m_sideEffects.functionSideEffects().at(definition).canContinue; auto const calleeIt = m_functionScopeToID.find(&function); yulAssert(calleeIt != m_functionScopeToID.end(), "Called function has no registered graph id."); - SSACFG::Operation result{{}, SSACFG::Call{calleeIt->second, canContinue}, {}}; + SSACFG::Operation result{.kind = SSACFG::Call{calleeIt->second, canContinue}}; for (auto const& arg: _call.arguments | ranges::views::reverse) result.inputs.emplace_back(std::visit(*this, arg)); for (size_t i = 0; i < function.numReturns; ++i) From bf1a1e990241cf20878def5901073074094752e1 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 27 Apr 2026 16:27:21 +0200 Subject: [PATCH 1282/1340] SSA CFG: extract UseCountSet from LivenessData --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/ssa/CodeTransform.cpp | 8 +- libyul/backends/evm/ssa/LivenessAnalysis.cpp | 112 +------------ libyul/backends/evm/ssa/LivenessAnalysis.h | 71 +-------- libyul/backends/evm/ssa/PhiInverse.cpp | 2 +- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 6 +- libyul/backends/evm/ssa/Stack.cpp | 2 +- .../backends/evm/ssa/StackLayoutGenerator.cpp | 2 +- libyul/backends/evm/ssa/StackShuffler.cpp | 10 +- libyul/backends/evm/ssa/io/JSONExporter.cpp | 8 +- .../ssa/transform/TrivialPhiEliminator.cpp | 2 +- libyul/backends/evm/ssa/util/UseCountSet.h | 150 ++++++++++++++++++ test/libyul/ssa/StackShufflerTest.cpp | 10 +- 13 files changed, 182 insertions(+), 202 deletions(-) create mode 100644 libyul/backends/evm/ssa/util/UseCountSet.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index ca23f622c..974df3138 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -102,6 +102,7 @@ add_library(yul backends/evm/ssa/StackShuffler.cpp backends/evm/ssa/StackShuffler.h backends/evm/ssa/StackToMemorySpilling.h + backends/evm/ssa/util/UseCountSet.h backends/evm/ssa/StackUtils.cpp backends/evm/ssa/StackUtils.h backends/evm/ssa/io/DotExporterBase.cpp diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index c66505fe8..4b0bcf50d 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -196,7 +196,7 @@ void CodeTransform::operator()(SSACFG::BlockId const _blockId) yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); // handle the block exit - std::visit(util::GenericVisitor{ [this, &_blockId](auto const& exit) { (*this)(_blockId, exit); } }, block.exit); + std::visit(solidity::util::GenericVisitor{ [this, &_blockId](auto const& exit) { (*this)(_blockId, exit); } }, block.exit); } void CodeTransform::operator()(SSACFG::InstId _opId, StackData const& _operationInputLayout) @@ -259,7 +259,7 @@ void CodeTransform::operator()(SSACFG::InstId _opId, StackData const& _operation }(); // generate code for the operation - std::visit(util::GenericVisitor{ + std::visit(solidity::util::GenericVisitor{ [&](SSACFG::BuiltinCall const& _builtin) { m_assembly.setSourceLocation(opOriginLocation); auto const& builtin = m_cfg.evmDialect.builtin(_builtin.builtin); @@ -276,7 +276,7 @@ void CodeTransform::operator()(SSACFG::InstId _opId, StackData const& _operation builtin.generateCode(transient, m_assembly, m_builtinContext); }, [&](SSACFG::Call const& _call) { - auto const* returnLabel = util::valueOrNullptr(m_returnLabels, _opId); + auto const* returnLabel = solidity::util::valueOrNullptr(m_returnLabels, _opId); // check that if we have a return label, the call can continue yulAssert(!!returnLabel == _call.canContinue); m_assembly.setSourceLocation(opOriginLocation); @@ -394,7 +394,7 @@ void CodeTransform::operator()(SSACFG::BlockId const& _blockId, SSACFG::BasicBlo yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); auto const& block = m_cfg.block(_blockId); yulAssert(!block.operations.empty(), "Terminated block must have at least one operation."); - std::visit(util::GenericVisitor{ + std::visit(solidity::util::GenericVisitor{ [&](SSACFG::BuiltinCall const& _builtin) { yulAssert(m_cfg.evmDialect.builtin(_builtin.builtin).controlFlowSideEffects.terminatesOrReverts(), "Last operation of Terminated block must terminate or revert."); }, diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp index 9af5f861d..5ea1cf9f7 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -20,8 +20,6 @@ #include -#include -#include #include #include @@ -33,112 +31,17 @@ namespace { constexpr auto excludingLiteralsFilter() { - return [](LivenessAnalysis::LivenessData::Value const& _valueId) -> bool + return [](SSACFG::ValueId const& _valueId) -> bool { return !_valueId.isLiteral(); }; } } -bool LivenessAnalysis::LivenessData::contains(Value const& _valueId) const -{ - return findEntry(_valueId) != m_liveCounts.end(); -} - -LivenessAnalysis::LivenessData::Count LivenessAnalysis::LivenessData::count(Value const& _valueId) const -{ - if ( - auto const it = findEntry(_valueId); - it != m_liveCounts.end() - ) - return it->second; - return 0; -} - -LivenessAnalysis::LivenessData::LiveCounts::const_iterator LivenessAnalysis::LivenessData::begin() const -{ - return m_liveCounts.begin(); -} - -LivenessAnalysis::LivenessData::LiveCounts::const_iterator LivenessAnalysis::LivenessData::end() const -{ - return m_liveCounts.end(); -} - -LivenessAnalysis::LivenessData::LiveCounts::size_type LivenessAnalysis::LivenessData::size() const -{ - return m_liveCounts.size(); -} - -bool LivenessAnalysis::LivenessData::empty() const { return m_liveCounts.empty(); } - -void LivenessAnalysis::LivenessData::insert(Value const& _value, Count _count) -{ - if (_count == 0) - return; - - auto it = findEntry(_value); - if (it != m_liveCounts.end()) - it->second += _count; - else - m_liveCounts.emplace_back(_value, _count); -} - -LivenessAnalysis::LivenessData& LivenessAnalysis::LivenessData::maxUnion(LivenessData const& _other) -{ - for (auto const& [value, count]: _other.m_liveCounts) - { - auto it = findEntry(value); - if (it != m_liveCounts.end()) - it->second = std::max(it->second, count); - else - m_liveCounts.emplace_back(value, count); - } - return *this; -} - -LivenessAnalysis::LivenessData& LivenessAnalysis::LivenessData::operator+=(LivenessData const& _other) -{ - for (auto const& [valueId, count]: _other.m_liveCounts) - insert(valueId, count); - return *this; -} - -LivenessAnalysis::LivenessData& LivenessAnalysis::LivenessData::operator-=(LivenessData const& _other) -{ - std::erase_if(m_liveCounts, [&](auto const& entry) { return _other.contains(entry.first); }); - return *this; -} - -void LivenessAnalysis::LivenessData::erase(Value const& _value) -{ - if ( - auto const it = findEntry(_value); - it != m_liveCounts.end() - ) - m_liveCounts.erase(it); -} - -void LivenessAnalysis::LivenessData::remove(Value const& _value, Count _count) -{ - if (_count == 0) - return; - - auto it = findEntry(_value); - if (it != m_liveCounts.end()) - { - if (it->second <= _count) - m_liveCounts.erase(it); - else - it->second -= _count; - } -} - - LivenessAnalysis::LivenessData LivenessAnalysis::blockExitValues(SSACFG::BlockId const& _blockId) const { LivenessData result; - util::GenericVisitor exitVisitor{ + solidity::util::GenericVisitor exitVisitor{ [](SSACFG::BasicBlock::MainExit const&) {}, [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { @@ -156,17 +59,6 @@ LivenessAnalysis::LivenessData LivenessAnalysis::blockExitValues(SSACFG::BlockId return result; } - -LivenessAnalysis::LivenessData::LiveCounts::iterator LivenessAnalysis::LivenessData::findEntry(Value const& _value) -{ - return ranges::find_if(m_liveCounts, [&](auto const& _entry) { return _entry.first == _value; }); -} - -LivenessAnalysis::LivenessData::LiveCounts::const_iterator LivenessAnalysis::LivenessData::findEntry(Value const& _value) const -{ - return ranges::find_if(m_liveCounts, [&](auto const& _entry) { return _entry.first == _value; }); -} - LivenessAnalysis::LivenessAnalysis(SSACFG const& _cfg): m_cfg(_cfg), m_topologicalSort(_cfg), diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.h b/libyul/backends/evm/ssa/LivenessAnalysis.h index 5a19cb0bd..91596072d 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.h +++ b/libyul/backends/evm/ssa/LivenessAnalysis.h @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -33,74 +34,10 @@ namespace solidity::yul::ssa class LivenessAnalysis { public: - class LivenessData - { - public: - using Count = std::uint32_t; - using Value = SSACFG::ValueId; - using LiveCounts = std::vector>; + /// Per-program-point liveness: each value's use count is the total number + /// of times the value will be read along all paths downstream of that point. + using LivenessData = util::UseCountSet; - LivenessData() = default; - template Sentinel> - LivenessData(Iter begin, Sentinel end): m_liveCounts(begin, end) {} - explicit LivenessData(LiveCounts&& _liveCounts): m_liveCounts(std::move(_liveCounts)) {} - - bool contains(Value const& _valueId) const; - Count count(Value const& _valueId) const; - LiveCounts::const_iterator begin() const; - LiveCounts::const_iterator end() const; - LiveCounts::size_type size() const; - bool empty() const; - - // Core modification - /// Add value with count (default 1), incrementing if already present - void insert(Value const& _value, Count _count = 1); - /// Remove value completely regardless of count - void erase(Value const& _value); - /// Decrement value count, removing if count reaches zero - void remove(Value const& _value, Count _count = 1); - - // Set operations - /// Add all entries from other, summing counts - LivenessData& operator+=(LivenessData const& _other); - /// Remove all values present in other - LivenessData& operator-=(LivenessData const& _other); - /// Union with other, taking max count for each value - LivenessData& maxUnion(LivenessData const& _other); - - // Bulk operations - /// Insert all values from range with count 1 each - template - void insertAll(Range const& _values) - { - for (auto const& value: _values) - insert(value); - } - - /// Erase all values from range - template - void eraseAll(Range const& _values) - { - for (auto const& value: _values) - erase(value); - } - - // Conditional removal - /// Remove all entries matching predicate - template - void eraseIf(Predicate&& _predicate) - { - std::erase_if(m_liveCounts, std::forward(_predicate)); - } - - private: - LiveCounts::iterator findEntry(Value const& _value); - LiveCounts::const_iterator findEntry(Value const& _value) const; - - /// Usage counts represent the total number of times each variable will be used - /// downstream across all possible execution paths from this program point. - LiveCounts m_liveCounts; - }; explicit LivenessAnalysis(SSACFG const& _cfg); LivenessData const& liveIn(SSACFG::BlockId const _blockId) const { return m_liveIns[_blockId.value]; } diff --git a/libyul/backends/evm/ssa/PhiInverse.cpp b/libyul/backends/evm/ssa/PhiInverse.cpp index f135746e1..b8be70e64 100644 --- a/libyul/backends/evm/ssa/PhiInverse.cpp +++ b/libyul/backends/evm/ssa/PhiInverse.cpp @@ -34,7 +34,7 @@ bool PhiInverse::noOp() const SSACFG::ValueId PhiInverse::operator()(SSACFG::ValueId _valueId) const { - return util::valueOrDefault(m_phiToPreImage, _valueId, _valueId); + return solidity::util::valueOrDefault(m_phiToPreImage, _valueId, _valueId); } std::map const& PhiInverse::data() const diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 1e1fb479f..0ed9c7219 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -440,7 +440,7 @@ void SSACFGBuilder::assign(std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const& _call) { bool canContinue = true; - SSACFG::Operation operation = std::visit(util::GenericVisitor{ + SSACFG::Operation operation = std::visit(solidity::util::GenericVisitor{ [&](BuiltinName const& _builtinName) { auto const& builtin = m_dialect.builtin(_builtinName.handle); @@ -553,7 +553,7 @@ void SSACFGBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::Bloc Scope::Function const& SSACFGBuilder::lookupFunction(YulName _name) const { Scope::Function const* function = nullptr; - yulAssert(m_scope->lookup(_name, util::GenericVisitor{ + yulAssert(m_scope->lookup(_name, solidity::util::GenericVisitor{ [](Scope::Variable&) { yulAssert(false, "Expected function name."); }, [&](Scope::Function& _function) { function = &_function; } }), "Function name not found."); @@ -565,7 +565,7 @@ Scope::Variable const& SSACFGBuilder::lookupVariable(YulName _name) const { yulAssert(m_scope, ""); Scope::Variable const* var = nullptr; - if (m_scope->lookup(_name, util::GenericVisitor{ + if (m_scope->lookup(_name, solidity::util::GenericVisitor{ [&](Scope::Variable const& _var) { var = &_var; }, [](Scope::Function const&) { diff --git a/libyul/backends/evm/ssa/Stack.cpp b/libyul/backends/evm/ssa/Stack.cpp index 1e7dc2d18..3edf4e862 100644 --- a/libyul/backends/evm/ssa/Stack.cpp +++ b/libyul/backends/evm/ssa/Stack.cpp @@ -39,7 +39,7 @@ std::string slotToString(StackSlot const& _slot) case StackSlot::Kind::FunctionReturnLabel: return fmt::format("ReturnLabel[{}]", _slot.functionReturnLabel()); } - util::unreachable(); + solidity::util::unreachable(); } std::string stackToString(StackData const& _stackData) diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index d835d26dd..ab68443f5 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -278,7 +278,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) } std::visit( - util::GenericVisitor{ + solidity::util::GenericVisitor{ [&](SSACFG::BasicBlock::ConditionalJump const& _cJump) { auto const& blockLiveOut = m_liveness.liveOut(_blockId); diff --git a/libyul/backends/evm/ssa/StackShuffler.cpp b/libyul/backends/evm/ssa/StackShuffler.cpp index a9416a088..caf86cf94 100644 --- a/libyul/backends/evm/ssa/StackShuffler.cpp +++ b/libyul/backends/evm/ssa/StackShuffler.cpp @@ -81,27 +81,27 @@ std::size_t State::size() const std::size_t State::count(StackSlot const& _slot) const { - return util::valueOrDefault(m_histogram, _slot, static_cast(0)); + return solidity::util::valueOrDefault(m_histogram, _slot, static_cast(0)); } std::size_t State::countInArgs(StackSlot const& _slot) const { - return util::valueOrDefault(m_histogramArgs, _slot, static_cast(0)); + return solidity::util::valueOrDefault(m_histogramArgs, _slot, static_cast(0)); } std::size_t State::countInTail(StackSlot const& _slot) const { - return util::valueOrDefault(m_histogramTail, _slot, static_cast(0)); + return solidity::util::valueOrDefault(m_histogramTail, _slot, static_cast(0)); } std::size_t State::countReachable(StackSlot const& _slot) const { - return util::valueOrDefault(m_histogramReachable, _slot, static_cast(0)); + return solidity::util::valueOrDefault(m_histogramReachable, _slot, static_cast(0)); } std::size_t State::targetMinCount(StackSlot const& _slot) const { - return util::valueOrDefault(m_target.minCount, _slot, static_cast(0)); + return solidity::util::valueOrDefault(m_target.minCount, _slot, static_cast(0)); } std::size_t State::targetArgsCount(StackSlot const& _slot) const diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index 3d0de2f04..a1433bc42 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -46,7 +46,7 @@ Json toJson(SSACFG const& _cfg, std::vector const& _values) Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation, ControlFlowGraphs const& _controlFlow) { Json opJson = Json::object(); - std::visit(util::GenericVisitor{ + std::visit(solidity::util::GenericVisitor{ [&](SSACFG::Call const& _call) { _ret["type"] = "FunctionCall"; opJson["op"] = _controlFlow.functionGraph(_call.graphID)->name; @@ -72,7 +72,7 @@ Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation, Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const* _liveness, ControlFlowGraphs const& _controlFlow) { - auto const valueToString = [&](LivenessAnalysis::LivenessData::LiveCounts::value_type const& _live) { return _live.first.str(_cfg); }; + auto const valueToString = [&](auto const& _live) { return _live.first.str(_cfg); }; Json blockJson = Json::object(); auto const& block = _cfg.block(_blockId); @@ -122,12 +122,12 @@ Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const Json exportBlock(SSACFG const& _cfg, SSACFG::BlockId _entryId, LivenessAnalysis const* _liveness, ControlFlowGraphs const& _controlFlow) { Json blocksJson = Json::array(); - util::BreadthFirstSearch bfs{{{_entryId}}}; + solidity::util::BreadthFirstSearch bfs{{{_entryId}}}; bfs.run([&](SSACFG::BlockId _blockId, auto _addChild) { Json blockJson = toJson(_cfg, _blockId, _liveness, _controlFlow); Json exitBlockJson = Json::object(); - std::visit(util::GenericVisitor{ + std::visit(solidity::util::GenericVisitor{ [&](SSACFG::BasicBlock::MainExit const&) { exitBlockJson["type"] = "MainExit"; }, diff --git a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp index b913a5fc8..3301aa135 100644 --- a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp +++ b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp @@ -235,7 +235,7 @@ struct TrivialPhiEliminator for (auto const opId: block.operations) for (auto& input: cfg.operation(opId).inputs) input = canonicalize(input); - std::visit(util::GenericVisitor{ + std::visit(solidity::util::GenericVisitor{ [&](SSACFG::BasicBlock::FunctionReturn& r) { for (auto& v: r.returnValues) v = canonicalize(v); diff --git a/libyul/backends/evm/ssa/util/UseCountSet.h b/libyul/backends/evm/ssa/util/UseCountSet.h new file mode 100644 index 000000000..e6e94062d --- /dev/null +++ b/libyul/backends/evm/ssa/util/UseCountSet.h @@ -0,0 +1,150 @@ +/* + 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 + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace solidity::yul::ssa::util +{ + +/// Vector-backed reference-counted set keyed on `Key`. Each entry carries a non-zero use count; absent keys have +/// effective count 0. Designed for small working sets such that linear scan beats the constant overhead +/// of a hashed or tree-based associative container. +template +class UseCountSet +{ +public: + using Value = Key; + using Count = std::uint32_t; + using Entries = std::vector>; + + UseCountSet() = default; + template Sentinel> + UseCountSet(Iter _begin, Sentinel _end): m_entries(_begin, _end) {} + explicit UseCountSet(Entries _entries): m_entries(std::move(_entries)) {} + + bool contains(Key const& _key) const + { + return findEntry(_key) != m_entries.end(); + } + Count count(Key const& _key) const + { + auto const it = findEntry(_key); + return it == m_entries.end() ? Count{0} : it->second; + } + typename Entries::const_iterator begin() const { return m_entries.begin(); } + typename Entries::const_iterator end() const { return m_entries.end(); } + typename Entries::size_type size() const { return m_entries.size(); } + bool empty() const { return m_entries.empty(); } + + /// Add `_count` to existing entry or insert a new one. No-op if `_count == 0`. + void insert(Key const& _key, Count _count = 1) + { + if (_count == 0) + return; + auto it = findEntry(_key); + if (it != m_entries.end()) + it->second += _count; + else + m_entries.emplace_back(_key, _count); + } + + /// Remove the entry for `_key` if present. + void erase(Key const& _key) + { + if (auto const it = findEntry(_key); it != m_entries.end()) + m_entries.erase(it); + } + + /// Subtract `_count` from the entry for `_key`, removing it if the count + /// drops to zero. No-op if `_key` is absent or `_count == 0`. + void remove(Key const& _key, Count _count = 1) + { + if (_count == 0) + return; + auto it = findEntry(_key); + if (it == m_entries.end()) + return; + if (it->second <= _count) + m_entries.erase(it); + else + it->second -= _count; + } + + /// Sum-merge counts from `_other` into this. + UseCountSet& operator+=(UseCountSet const& _other) + { + for (auto const& [key, count]: _other.m_entries) + insert(key, count); + return *this; + } + + /// Union with `_other`, taking max count per key. + UseCountSet& maxUnion(UseCountSet const& _other) + { + for (auto const& [key, count]: _other.m_entries) + { + auto it = findEntry(key); + if (it != m_entries.end()) + it->second = std::max(it->second, count); + else + m_entries.emplace_back(key, count); + } + return *this; + } + + template + void insertAll(Range const& _values) + { + for (auto const& value: _values) + insert(value); + } + + template + void eraseAll(Range const& _values) + { + for (auto const& value: _values) + erase(value); + } + + template + void eraseIf(Predicate&& _predicate) + { + std::erase_if(m_entries, std::forward(_predicate)); + } + +private: + typename Entries::iterator findEntry(Key const& _key) + { + return std::find_if(m_entries.begin(), m_entries.end(), [&](auto const& _entry) { return _entry.first == _key; }); + } + typename Entries::const_iterator findEntry(Key const& _key) const + { + return std::find_if(m_entries.begin(), m_entries.end(), [&](auto const& _entry) { return _entry.first == _key; }); + } + + Entries m_entries; +}; + +} diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index 6d8588d37..0cd7e1365 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -99,21 +99,21 @@ Slot parseSlot(std::string_view token) if (token.starts_with("v")) { - if (auto const num = util::parseArithmetic(token.substr(1))) + if (auto const num = solidity::util::parseArithmetic(token.substr(1))) return Slot::makeValueID(ValueId::makeVariable(*num)); throw std::runtime_error(fmt::format("Couldn't parse variable token: {}", token)); } if (token.starts_with("phi")) { - if (auto const num = util::parseArithmetic(token.substr(3))) + if (auto const num = solidity::util::parseArithmetic(token.substr(3))) return Slot::makeValueID(ValueId::makePhi(*num)); throw std::runtime_error(fmt::format("Couldn't parse phi token: {}", token)); } if (token.starts_with("lit")) { - if (auto const num = util::parseArithmetic(token.substr(3))) + if (auto const num = solidity::util::parseArithmetic(token.substr(3))) return Slot::makeValueID(ValueId::makeLiteral(*num)); throw std::runtime_error(fmt::format("Couldn't parse literal token: {}", token)); } @@ -122,7 +122,7 @@ Slot parseSlot(std::string_view token) if (token.starts_with(returnLabelPrefix) && token.ends_with("]")) { auto const inner = token.substr(returnLabelPrefix.size(), token.size() - returnLabelPrefix.size() - 1); - if (auto const num = util::parseArithmetic(inner)) + if (auto const num = solidity::util::parseArithmetic(inner)) return Slot::makeFunctionReturnLabel(*num); throw std::runtime_error(fmt::format("Couldn't parse ReturnLabel token: {}", token)); } @@ -235,7 +235,7 @@ struct ShuffleTestInput result.targetStackTailSet = parseLiveness(value); else if (key == parserKeyStackSize) { - if (auto num = util::parseArithmetic(value)) + if (auto num = solidity::util::parseArithmetic(value)) result.targetStackSize = *num; else throw std::runtime_error(fmt::format("Couldn't parse targetStackSize: {}", value)); From a75fb6b6e103904827b88e5dd7daa0abd474f97d Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 27 Apr 2026 16:30:53 +0200 Subject: [PATCH 1283/1340] SSA CFG: introduce StackSlotLiveness for the stack shuffler --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/ssa/LivenessAnalysis.h | 4 +- .../backends/evm/ssa/StackLayoutGenerator.cpp | 10 +++-- libyul/backends/evm/ssa/StackShuffler.cpp | 10 ++--- libyul/backends/evm/ssa/StackShuffler.h | 18 ++++---- libyul/backends/evm/ssa/StackSlotLiveness.h | 40 +++++++++++++++++ libyul/backends/evm/ssa/StackUtils.cpp | 6 +-- libyul/backends/evm/ssa/StackUtils.h | 3 +- test/libyul/ssa/StackShufflerTest.cpp | 43 +++++++++++-------- 9 files changed, 92 insertions(+), 43 deletions(-) create mode 100644 libyul/backends/evm/ssa/StackSlotLiveness.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 974df3138..db0d30356 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -101,6 +101,7 @@ add_library(yul backends/evm/ssa/StackLayoutGenerator.h backends/evm/ssa/StackShuffler.cpp backends/evm/ssa/StackShuffler.h + backends/evm/ssa/StackSlotLiveness.h backends/evm/ssa/StackToMemorySpilling.h backends/evm/ssa/util/UseCountSet.h backends/evm/ssa/StackUtils.cpp diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.h b/libyul/backends/evm/ssa/LivenessAnalysis.h index 91596072d..066659ba1 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.h +++ b/libyul/backends/evm/ssa/LivenessAnalysis.h @@ -34,8 +34,8 @@ namespace solidity::yul::ssa class LivenessAnalysis { public: - /// Per-program-point liveness: each value's use count is the total number - /// of times the value will be read along all paths downstream of that point. + /// Per-program-point liveness, each value's use count is the max number of times the value will be read along + /// all paths downstream of that point using LivenessData = util::UseCountSet; explicit LivenessAnalysis(SSACFG const& _cfg); diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index ab68443f5..454fc62f1 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -253,10 +253,11 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) ) stack.declareJunk(depth); + StackSlotLiveness const opLiveOutSlots = toStackSlotLiveness(opLiveOutWithoutOutputs); std::size_t const targetSize = findOptimalTargetSize( stack.data(), requiredStackTop, - opLiveOutWithoutOutputs, + opLiveOutSlots, junkCanBeAdded, m_hasFunctionReturnLabel ); @@ -264,7 +265,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) auto const shuffleResult = StackShuffler::shuffle( stack, requiredStackTop, - opLiveOutWithoutOutputs, + opLiveOutSlots, targetSize ); yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); @@ -290,15 +291,16 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) if (!conditionSlotAlreadyFinal) { auto const condition = Slot::makeValueID(_cJump.condition); + StackSlotLiveness const blockLiveOutSlots = toStackSlotLiveness(blockLiveOut); auto const targetSize = findOptimalTargetSize( stack.data(), {condition}, - blockLiveOut, + blockLiveOutSlots, false, m_hasFunctionReturnLabel ); auto const shuffleResult = StackShuffler::shuffle( - stack, {condition}, blockLiveOut, targetSize + stack, {condition}, blockLiveOutSlots, targetSize ); yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); } diff --git a/libyul/backends/evm/ssa/StackShuffler.cpp b/libyul/backends/evm/ssa/StackShuffler.cpp index caf86cf94..18daa4892 100644 --- a/libyul/backends/evm/ssa/StackShuffler.cpp +++ b/libyul/backends/evm/ssa/StackShuffler.cpp @@ -26,7 +26,7 @@ using namespace solidity::yul::ssa::detail; Target::Target( StackData const& _args, - LivenessAnalysis::LivenessData const& _liveOut, + StackSlotLiveness const& _liveOut, std::size_t const _targetSize, SpilledVariables const* _spilledVariables ): @@ -40,9 +40,9 @@ Target::Target( for (auto const& arg: _args) if (!arg.isJunk() && !slotIsSpilled(arg, _spilledVariables)) ++minCount[arg]; - for (auto const& liveValueId: _liveOut | ranges::views::keys) - if (!(_spilledVariables && _spilledVariables->isSpilled(liveValueId))) - ++minCount[StackSlot::makeValueID(liveValueId)]; + for (auto const& liveSlot: _liveOut | ranges::views::keys) + if (!slotIsSpilled(liveSlot, _spilledVariables)) + ++minCount[liveSlot]; } State::State(StackData const& _stackData, Target const& _target, SpilledVariables const* const _spilledVariables, std::size_t const _reachableStackDepth): @@ -133,7 +133,7 @@ bool State::requiredInArgs(StackSlot const& _slot) const bool State::requiredInTail(StackSlot const& _slot) const { - if (!_slot.isValueID() || !m_target.liveOut.contains(_slot.valueID())) + if (!_slot.isValueID() || !m_target.liveOut.contains(_slot)) return false; // Spilled values can be rematerialized, so they need not occupy a tail slot. return !slotIsSpilled(_slot); diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 0d77c9556..6c8bb9c1a 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -18,7 +18,7 @@ #pragma once -#include +#include #include #include @@ -54,13 +54,13 @@ struct Target { Target( StackData const& _args, - LivenessAnalysis::LivenessData const& _liveOut, + StackSlotLiveness const& _liveOut, std::size_t _targetSize, SpilledVariables const* _spilledVariables = nullptr ); StackData const& args; - LivenessAnalysis::LivenessData const& liveOut; + StackSlotLiveness const& liveOut; SpilledVariables const* const spilledVariables; std::size_t const size; std::size_t const tailSize; @@ -184,7 +184,7 @@ class StackShuffler [[nodiscard]] static StackShufflerResult shuffle( Stack& _stack, StackData const& _args, - LivenessAnalysis::LivenessData const& _liveOut, + StackSlotLiveness const& _liveOut, std::size_t _targetStackSize, SpilledVariables const* const _spilledVariables = nullptr ) @@ -197,10 +197,10 @@ class StackShuffler { // check that all required values are on stack detail::State const state(_stack.data(), target, _spilledVariables, ReachableStackDepth); - for (auto const& liveVariable: _liveOut | ranges::views::keys | ranges::views::transform(Slot::makeValueID)) + for (auto const& liveSlot: _liveOut | ranges::views::keys) yulAssert( - !_stack.canBeFreelyGenerated(liveVariable) && - (ranges::contains(_stack.data(), liveVariable) || detail::slotIsSpilled(liveVariable, _spilledVariables)) + !_stack.canBeFreelyGenerated(liveSlot) && + (ranges::contains(_stack.data(), liveSlot) || detail::slotIsSpilled(liveSlot, _spilledVariables)) ); for (auto const& arg: _args) yulAssert(detail::slotCanBeLoadedOrPushed(arg, _spilledVariables) || ranges::contains(_stack.data(), arg)); @@ -346,8 +346,8 @@ class StackShuffler int currentCount = static_cast(_state.count(slot)); int liveOutCount = 0; - if (slot.isValueID() && _state.target().liveOut.contains(slot.valueID())) - liveOutCount = static_cast(_state.target().liveOut.count(slot.valueID())); + if (slot.isValueID() && _state.target().liveOut.contains(slot)) + liveOutCount = static_cast(_state.target().liveOut.count(slot)); int deficit = liveOutCount - currentCount; // Update best if this deficit is higher diff --git a/libyul/backends/evm/ssa/StackSlotLiveness.h b/libyul/backends/evm/ssa/StackSlotLiveness.h new file mode 100644 index 000000000..57da7115b --- /dev/null +++ b/libyul/backends/evm/ssa/StackSlotLiveness.h @@ -0,0 +1,40 @@ +/* + 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 + +#pragma once + +#include +#include +#include + +namespace solidity::yul::ssa +{ + +/// Liveness counts keyed on StackSlot +using StackSlotLiveness = util::UseCountSet; + +inline StackSlotLiveness toStackSlotLiveness(LivenessAnalysis::LivenessData const& _liveness) +{ + StackSlotLiveness::Entries entries; + entries.reserve(_liveness.size()); + for (auto const& [valueId, count]: _liveness) + entries.emplace_back(StackSlot::makeValueID(valueId), count); + return StackSlotLiveness{std::move(entries)}; +} + +} diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index 3b0c183ee..71c972ce6 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -81,15 +81,15 @@ std::size_t solidity::yul::ssa::findOptimalTargetSize ( StackData const& _stackData, StackData const& _targetArgs, - LivenessAnalysis::LivenessData const& _targetLiveOut, + StackSlotLiveness const& _targetLiveOut, bool const _canIntroduceJunk, bool const _hasFunctionReturnLabel ) { std::size_t const minSize = _targetLiveOut.size() + _targetArgs.size() + (_hasFunctionReturnLabel ? 1 : 0); boost::container::flat_map deficit; - for (auto const& v: _targetLiveOut | ranges::views::keys) - deficit[StackSlot::makeValueID(v)]++; + for (auto const& slot: _targetLiveOut | ranges::views::keys) + deficit[slot]++; for (auto const& arg: _targetArgs) deficit[arg]++; for (auto const& slot: _stackData) diff --git a/libyul/backends/evm/ssa/StackUtils.h b/libyul/backends/evm/ssa/StackUtils.h index 47dc6711a..79eeb215a 100644 --- a/libyul/backends/evm/ssa/StackUtils.h +++ b/libyul/backends/evm/ssa/StackUtils.h @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -65,7 +66,7 @@ StackData stackPreImage(StackData _stack, PhiInverse const& _phiInverse); std::size_t findOptimalTargetSize( StackData const& _stackData, StackData const& _targetArgs, - LivenessAnalysis::LivenessData const& _targetLiveOut, + StackSlotLiveness const& _targetLiveOut, bool _canIntroduceJunk, bool _hasFunctionReturnLabel ); diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index 0cd7e1365..3b6999908 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -18,9 +18,9 @@ #include -#include #include #include +#include #include @@ -53,7 +53,6 @@ std::string_view constexpr parserKeyStackSize {"targetStackSize"}; std::string_view constexpr parserKeyAllowSpilling {"allowSpilling"}; std::string_view constexpr parserKeyInitialSpilled {"initialSpilledSet"}; -using Liveness = LivenessAnalysis::LivenessData; using Slot = StackSlot; using ValueId = SSACFG::ValueId; struct StackManipulationCallbacks @@ -160,25 +159,25 @@ TestStack::Data parseSlots(std::string_view _input, char const brackBegin = '[', } /// Parse liveness like "{phi109, phi150, v172}" -/// Returns Liveness with reference count 1 for each value -Liveness parseLiveness(std::string_view _input) +/// Returns StackSlotLiveness with reference count 1 for each value +StackSlotLiveness parseLiveness(std::string_view _input) { auto const slots = parseSlots(_input, '{', '}'); - std::vector> liveCounts; - liveCounts.reserve(slots.size()); + StackSlotLiveness::Entries entries; + entries.reserve(slots.size()); for (auto const& slot: slots) { yulAssert(slot.isValueID(), "Only value IDs are permitted in liveness definition."); - liveCounts.emplace_back(slot.valueID(), 1); + entries.emplace_back(slot, 1u); } - return {liveCounts.begin(), liveCounts.end()}; + return StackSlotLiveness{std::move(entries)}; } struct ShuffleTestInput { std::optional initial; std::optional targetStackTop; - Liveness targetStackTailSet{}; + StackSlotLiveness targetStackTailSet{}; std::optional targetStackSize; bool allowSpilling = false; SpilledVariables initialSpilledSet{}; @@ -250,8 +249,14 @@ struct ShuffleTestInput throw std::runtime_error(fmt::format("Couldn't parse allowSpilling: {}", value)); } else if (key == parserKeyInitialSpilled) - for (auto const& [valueId, _]: parseLiveness(value)) - result.initialSpilledSet.spill(valueId); + { + auto const spillSet = parseLiveness(value); + for (auto const& slot: spillSet | ranges::views::keys) + { + yulAssert(slot.isValueID()); + result.initialSpilledSet.spill(slot.valueID()); + } + } } @@ -278,7 +283,7 @@ class TraceRecorder TraceRecorder( std::ostream& _out, TestStack::Data const& _targetArgs, - Liveness const& _targetTail, + StackSlotLiveness const& _targetTail, size_t _targetStackSize, SpilledVariables const& _spillSet ): @@ -298,9 +303,9 @@ class TraceRecorder "{{{}}}", fmt::join( m_targetTail | ranges::views::keys | ranges::views::transform( - [this](auto const& id) { - std::string const suffix = m_spillSet.isSpilled(id) ? "*" : ""; - return slotToString(Slot::makeValueID(id)) + suffix; + [this](Slot const& _slot) { + std::string const suffix = (_slot.isValueID() && m_spillSet.isSpilled(_slot.valueID())) ? "*" : ""; + return slotToString(_slot) + suffix; } ), ", " @@ -377,7 +382,7 @@ class TraceRecorder std::vector m_entries; bool m_truncated = false; TestStack::Data const& m_targetArgs; - Liveness const& m_targetTail; + StackSlotLiveness const& m_targetTail; SpilledVariables const& m_spillSet; size_t const m_targetStackSize; size_t const m_targetTailSize; @@ -601,14 +606,14 @@ explicitly provided.)"; yulAssert(*testConfig.targetStackSize >= testConfig.targetStackTop->size()); auto const tailSize = *testConfig.targetStackSize - testConfig.targetStackTop->size(); yulAssert(stackData.size() == *testConfig.targetStackSize); - for (const auto& valueID: testConfig.targetStackTailSet | ranges::views::keys) + for (const auto& slot: testConfig.targetStackTailSet | ranges::views::keys) { - if (spillSet.isSpilled(valueID)) + if (slot.isValueID() && spillSet.isSpilled(slot.valueID())) continue; auto const findIt = ranges::find( stackData.begin(), stackData.begin() + static_cast(tailSize), - StackSlot::makeValueID(valueID) + slot ); yulAssert(findIt != ranges::end(stackData)); } From b34f63595afe8303a9683065526a797c5033fff3 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:12:19 +0200 Subject: [PATCH 1284/1340] Docs: Add AI-assisted contribution guidelines --- docs/contributing.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/contributing.rst b/docs/contributing.rst index b5eb3c08e..ce29cbaed 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -88,6 +88,20 @@ We thoroughly review every PR and will help you get it right, but there are many Thank you for your help! +AI-Assisted Contributions +========================= + +We do not ban the use of AI tools, but we hold all contributions to the same high standard +regardless of how they are produced, and we require full transparency about their use. + +Submitting AI-generated code means you have reviewed it, understand it, can explain it, and have +tested it as thoroughly as if you had written it by hand. + +If you used AI tools to generate code, tests, or documentation in any part of your contribution, +disclosure in the pull request is mandatory. +If we determine that a PR contains undisclosed AI-generated content, we may close it. + + Running the Compiler Tests ========================== From 01621a6d9e02ba1c5d021408d2504b0eb1f77bad Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:14:27 +0200 Subject: [PATCH 1285/1340] Add GitHub PR template --- .github/PULL_REQUEST_TEMPLATE.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..16955ac4b --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,28 @@ + + +## Description + + + +## Checklist +- [ ] I have read the [contributing guidelines](https://docs.soliditylang.org/en/latest/contributing.html) and + the [review checklist](https://github.com/argotorg/solidity/blob/develop/ReviewChecklist.md) +- [ ] I have personally reviewed, understood, and tested every change in this PR + +## AI Disclosure + + +- [ ] No AI tools were used +- [ ] AI tools were used (details below) + + From 28afc58788c499418ae2749c36d5f33aade21070 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 13 Apr 2026 14:54:18 +0200 Subject: [PATCH 1286/1340] Remove external PR greeter bot comment It is folded into the PR template. --- .github/workflows/welcome-external-pr.yml | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/.github/workflows/welcome-external-pr.yml b/.github/workflows/welcome-external-pr.yml index 035e2bf5b..a7b19f3bc 100644 --- a/.github/workflows/welcome-external-pr.yml +++ b/.github/workflows/welcome-external-pr.yml @@ -18,24 +18,13 @@ jobs: steps: # Note: this step requires that the INTERNAL_CONTRIBUTORS environment variable # is already defined in the repository with the current json list of internal contributors. - - name: Comment on external contribution PR + - name: Labeling external contribution PR if: "!contains(fromJSON(vars.INTERNAL_CONTRIBUTORS), github.event.pull_request.user.login)" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR: ${{ github.event.pull_request.html_url }} run: | - echo "Commenting in a newly submitted or reopened external PR: $PR" + echo "Labeling a newly submitted or reopened external PR: $PR" if [[ $DRY_RUN == 'false' ]]; then gh pr edit "$PR" --add-label "external contribution :star:" - comment_body=( - "Thank you for your contribution to the Solidity compiler! A team member will follow up shortly." - "\n\n" - "If you haven't read our [contributing guidelines](https://docs.soliditylang.org/en/latest/contributing.html) and our " - "[review checklist](https://github.com/argotorg/solidity/blob/develop/ReviewChecklist.md) before, " - "please do it now, this makes the reviewing process and accepting your contribution smoother." - "\n\n" - "If you have any questions or need our help, feel free to post them in the PR or talk to us directly on the " - "[#solidity-dev](https://matrix.to/#/#ethereum_solidity-dev:gitter.im) channel on Matrix." - ) - gh pr comment $PR --body "$(IFS='' ; echo -e "${comment_body[*]}")" fi From ffac8c973d9ee082c4478c140549794b72ab5f89 Mon Sep 17 00:00:00 2001 From: jstcz Date: Tue, 28 Apr 2026 18:10:11 +0200 Subject: [PATCH 1287/1340] update solidity version in docs --- docs/using-the-compiler.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 478ccd146..84fd13350 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -753,7 +753,7 @@ Note that the use of this mode is recorded in the metadata: - ``settings.experimental`` in JSON metadata is set to ``true``, .. note:: - Prior to version 0.8.34, most of the experimental features were usable without any extra safeguards. + Prior to version 0.8.35, most of the experimental features were usable without any extra safeguards. Some were gated behind ``pragma experimental``, but this was not done consistently. The information about them was also only recorded in CBOR metadata and even then not always. The main goal of the experimental mode is to systematize this and make users fully aware when relying on features which are unfinished or not production-ready. From e9490a3e85d3311abe820702e048abc9613e7690 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 28 Apr 2026 22:48:51 +0200 Subject: [PATCH 1288/1340] fix rendering issue with the github pr template --- .github/PULL_REQUEST_TEMPLATE.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 16955ac4b..83abde44b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,8 +10,7 @@ If you have any questions or need our help, feel free to post them in the PR or ## Checklist -- [ ] I have read the [contributing guidelines](https://docs.soliditylang.org/en/latest/contributing.html) and - the [review checklist](https://github.com/argotorg/solidity/blob/develop/ReviewChecklist.md) +- [ ] I have read the [contributing guidelines](https://docs.soliditylang.org/en/latest/contributing.html) and the [review checklist](https://github.com/argotorg/solidity/blob/develop/ReviewChecklist.md) - [ ] I have personally reviewed, understood, and tested every change in this PR ## AI Disclosure From 250ced99464f7e825a28dd6b1f7455ab35e137fd Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 24 Feb 2026 03:55:15 -0300 Subject: [PATCH 1289/1340] Add tests --- .../args | 1 + .../input.sol | 11 + .../output | 173 +++++++++++ .../args | 1 + .../input.sol | 12 + .../output | 271 ++++++++++++++++++ .../args | 1 + .../input.sol | 11 + .../output | 146 ++++++++++ .../args | 1 + .../input.sol | 12 + .../output | 183 ++++++++++++ ...nd_string_literal_revert_strings_strip.sol | 14 + ...e_custom_error_constructor_side_effect.sol | 15 + ...uctor_side_effect_revert_strings_strip.sol | 17 ++ ...tom_error_no_args_revert_strings_strip.sol | 13 + ...uire_custom_error_revert_strings_strip.sol | 14 + ...aluated_only_once_revert_strings_strip.sol | 25 ++ ..._evaluation_order_revert_strings_strip.sol | 22 ++ ...error_stack_check_revert_strings_strip.sol | 21 ++ ...e_inherited_error_revert_strings_strip.sol | 16 ++ ...t_statement_error_revert_strings_strip.sol | 10 + 22 files changed, 990 insertions(+) create mode 100644 test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/args create mode 100644 test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/input.sol create mode 100644 test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/output create mode 100644 test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/args create mode 100644 test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/input.sol create mode 100644 test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/output create mode 100644 test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/args create mode 100644 test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/input.sol create mode 100644 test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/output create mode 100644 test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/args create mode 100644 test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/input.sol create mode 100644 test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/output create mode 100644 test/libsolidity/semanticTests/errors/require_custom_error_and_string_literal_revert_strings_strip.sol create mode 100644 test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect.sol create mode 100644 test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect_revert_strings_strip.sol create mode 100644 test/libsolidity/semanticTests/errors/require_custom_error_no_args_revert_strings_strip.sol create mode 100644 test/libsolidity/semanticTests/errors/require_custom_error_revert_strings_strip.sol create mode 100644 test/libsolidity/semanticTests/errors/require_error_condition_evaluated_only_once_revert_strings_strip.sol create mode 100644 test/libsolidity/semanticTests/errors/require_error_evaluation_order_revert_strings_strip.sol create mode 100644 test/libsolidity/semanticTests/errors/require_error_stack_check_revert_strings_strip.sol create mode 100644 test/libsolidity/semanticTests/errors/require_inherited_error_revert_strings_strip.sol create mode 100644 test/libsolidity/semanticTests/errors/revert_statement_error_revert_strings_strip.sol diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/args b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/args new file mode 100644 index 000000000..46e3d60a5 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/args @@ -0,0 +1 @@ +--revert-strings strip --debug-info none --asm --optimize diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/input.sol b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/input.sol new file mode 100644 index 000000000..bec04be05 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/input.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract C { + error MyError(uint errorCode, string errorMsg, bool flag); + function flag() pure public returns (bool) { return false; } + function f() pure external { + uint code = 8; + string memory eMsg = "error"; + require(false, MyError(code, eMsg, flag())); + } +} diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/output b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/output new file mode 100644 index 000000000..b478056ce --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error/output @@ -0,0 +1,173 @@ + +======= input.sol:C ======= +EVM assembly: + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + dup1 + 0x890eba68 + eq + tag_4 + jumpi + tag_2: + revert(0x00, 0x00) + tag_3: + tag_5 + tag_6 + jump // in + tag_5: + stop + tag_4: + 0x40 + dup1 + mload + 0x00 + dup2 + mstore + swap1 + mload + swap1 + dup2 + swap1 + sub + 0x20 + add + swap1 + return + tag_6: + 0x40 + dup1 + mload + dup1 + dup3 + add + swap1 + swap2 + mstore + 0x05 + dup2 + mstore + shl(0xd9, 0x32b93937b9) + 0x20 + dup3 + add + mstore + 0x08 + swap1 + dup2 + dup2 + 0x00 + mload(0x40) + shl(0xe5, 0x01676c8b) + dup2 + mstore + 0x04 + add + tag_14 + swap4 + swap3 + swap2 + swap1 + tag_15 + jump // in + tag_14: + mload(0x40) + dup1 + swap2 + sub + swap1 + revert + tag_15: + dup4 + dup2 + mstore + 0x60 + 0x20 + dup3 + add + mstore + 0x00 + dup4 + mload + dup1 + 0x60 + dup5 + add + mstore + dup1 + 0x20 + dup7 + add + 0x80 + dup6 + add + mcopy + 0x00 + 0x80 + dup3 + dup6 + add + add + mstore + 0x80 + 0x1f + not + 0x1f + dup4 + add + and + dup5 + add + add + swap2 + pop + pop + dup3 + iszero + iszero + 0x40 + dup4 + add + mstore + swap5 + swap4 + pop + pop + pop + pop + jump // out + + auxdata: +} diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/args b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/args new file mode 100644 index 000000000..46e3d60a5 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/args @@ -0,0 +1 @@ +--revert-strings strip --debug-info none --asm --optimize diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/input.sol b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/input.sol new file mode 100644 index 000000000..06f42d8c3 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/input.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract C { + error MyError(uint errorCode, string errorMsg); + uint public counter = 0; + function count() public returns (uint) { return ++counter; } + function f() external { + string memory eMsg = "error"; + require(false, MyError(count(), eMsg)); + counter += 2; + } +} diff --git a/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/output b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/output new file mode 100644 index 000000000..b11a94d25 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_legacy_require_custom_error_constructor_param_side_effect/output @@ -0,0 +1,271 @@ + +======= input.sol:C ======= +EVM assembly: + mstore(0x40, 0x80) + 0x00 + 0x00 + sstore + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + revert(0x00, 0x00) + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x06661abd + eq + tag_3 + jumpi + dup1 + 0x26121ff0 + eq + tag_4 + jumpi + dup1 + 0x61bc221a + eq + tag_5 + jumpi + tag_2: + revert(0x00, 0x00) + tag_3: + tag_6 + tag_7 + jump // in + tag_6: + mload(0x40) + swap1 + dup2 + mstore + 0x20 + add + mload(0x40) + dup1 + swap2 + sub + swap1 + return + tag_4: + tag_10 + tag_11 + jump // in + tag_10: + stop + tag_5: + tag_6 + sload(0x00) + dup2 + jump + tag_7: + 0x00 + 0x00 + 0x00 + dup2 + sload + tag_16 + swap1 + tag_17 + jump // in + tag_16: + swap2 + dup3 + swap1 + sstore + pop + swap2 + swap1 + pop + jump // out + tag_11: + 0x40 + dup1 + mload + dup1 + dup3 + add + swap1 + swap2 + mstore + 0x05 + dup2 + mstore + shl(0xd9, 0x32b93937b9) + 0x20 + dup3 + add + mstore + 0x00 + tag_19 + tag_7 + jump // in + tag_19: + dup3 + swap1 + swap2 + tag_20 + jumpi + mload(0x40) + shl(0xe1, 0x05c9a271) + dup2 + mstore + 0x04 + add + tag_21 + swap3 + swap2 + swap1 + tag_22 + jump // in + tag_21: + mload(0x40) + dup1 + swap2 + sub + swap1 + revert + tag_20: + pop + pop + 0x02 + 0x00 + 0x00 + dup3 + dup3 + sload + tag_23 + swap2 + swap1 + tag_24 + jump // in + tag_23: + swap1 + swap2 + sstore + pop + pop + pop + jump // out + tag_25: + 0x4e487b71 + 0xe0 + shl + 0x00 + mstore + 0x11 + 0x04 + mstore + 0x24 + 0x00 + revert + tag_17: + 0x00 + 0x01 + dup3 + add + tag_31 + jumpi + tag_31 + tag_25 + jump // in + tag_31: + pop + 0x01 + add + swap1 + jump // out + tag_22: + dup3 + dup2 + mstore + 0x40 + 0x20 + dup3 + add + mstore + 0x00 + dup3 + mload + dup1 + 0x40 + dup5 + add + mstore + dup1 + 0x20 + dup6 + add + 0x60 + dup6 + add + mcopy + 0x00 + 0x60 + dup3 + dup6 + add + add + mstore + 0x60 + 0x1f + not + 0x1f + dup4 + add + and + dup5 + add + add + swap2 + pop + pop + swap4 + swap3 + pop + pop + pop + jump // out + tag_24: + dup1 + dup3 + add + dup1 + dup3 + gt + iszero + tag_35 + jumpi + tag_35 + tag_25 + jump // in + tag_35: + swap3 + swap2 + pop + pop + jump // out + + auxdata: +} diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/args b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/args new file mode 100644 index 000000000..2b930b856 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/args @@ -0,0 +1 @@ +--revert-strings strip --debug-info none --asm --optimize --via-ir diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/input.sol b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/input.sol new file mode 100644 index 000000000..bec04be05 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/input.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract C { + error MyError(uint errorCode, string errorMsg, bool flag); + function flag() pure public returns (bool) { return false; } + function f() pure external { + uint code = 8; + string memory eMsg = "error"; + require(false, MyError(code, eMsg, flag())); + } +} diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/output b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/output new file mode 100644 index 000000000..7cdf2289b --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error/output @@ -0,0 +1,146 @@ + +======= input.sol:C ======= +EVM assembly: + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_1, callvalue) + dataSize(sub_0) + swap1 + dup2 + dataOffset(sub_0) + dup3 + codecopy + return +tag_1: + 0x00 + dup1 + revert +stop + +sub_0: assembly { + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_1, iszero(lt(calldatasize, 0x04))) + 0x00 + dup1 + revert + tag_1: + shr(0xe0, calldataload(0x00)) + swap1 + dup2 + 0x26121ff0 + eq + tag_3 + jumpi + pop + 0x890eba68 + eq + tag_5 + jumpi + 0x00 + dup1 + revert + tag_5: + jumpi(tag_9, callvalue) + jumpi(tag_9, slt(add(not(0x03), calldatasize), 0x00)) + 0x20 + mload(0x40) + 0x00 + dup2 + mstore + return + tag_9: + 0x00 + dup1 + revert + tag_3: + jumpi(tag_9, callvalue) + jumpi(tag_9, slt(add(not(0x03), calldatasize), 0x00)) + 0x40 + dup2 + add + dup2 + dup2 + lt + 0xffffffffffffffff + dup3 + gt + or + tag_15 + jumpi + 0x40 + mstore + 0x05 + dup2 + mstore + 0x84 + 0x20 + dup3 + add + swap2 + shl(0xd9, 0x32b93937b9) + dup4 + mstore + mload(0x40) + swap3 + dup4 + swap2 + shl(0xe5, 0x01676c8b) + dup4 + mstore + 0x08 + 0x04 + dup5 + add + mstore + 0x60 + 0x24 + dup5 + add + mstore + mload + dup1 + swap2 + dup2 + 0x64 + dup6 + add + mstore + dup5 + dup5 + add + mcopy + 0x00 + dup3 + dup3 + add + dup5 + add + dup2 + swap1 + mstore + 0x44 + dup4 + add + mstore + 0x1f + add + not(0x1f) + and + dup2 + add + sub + add + swap1 + revert + tag_15: + mstore(0x00, shl(0xe0, 0x4e487b71)) + mstore(0x04, 0x41) + revert(0x00, 0x24) + + auxdata: +} diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/args b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/args new file mode 100644 index 000000000..2b930b856 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/args @@ -0,0 +1 @@ +--revert-strings strip --debug-info none --asm --optimize --via-ir diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/input.sol b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/input.sol new file mode 100644 index 000000000..eb97b426e --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/input.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; +contract C { + error MyError(uint errorCode, string errorMsg); + uint public counter = 0; + function genCode() public returns (uint) { return ++counter; } + function f() external { + string memory eMsg = "error"; + require(false, MyError(genCode(), eMsg)); + counter += 2; + } +} diff --git a/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/output b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/output new file mode 100644 index 000000000..d1749e308 --- /dev/null +++ b/test/cmdlineTests/revert_strings_strip_via_ir_require_custom_error_constructor_param_side_effect/output @@ -0,0 +1,183 @@ + +======= input.sol:C ======= +EVM assembly: + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_1, callvalue) + 0x00 + dup1 + sstore + dataSize(sub_0) + swap1 + dup2 + dataOffset(sub_0) + dup3 + codecopy + return +tag_1: + 0x00 + dup1 + revert +stop + +sub_0: assembly { + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_2, iszero(lt(calldatasize, 0x04))) + 0x00 + dup1 + revert + tag_2: + shr(0xe0, calldataload(0x00)) + swap1 + dup2 + 0x26121ff0 + eq + tag_4 + jumpi + pop + dup1 + 0x61bc221a + eq + tag_6 + jumpi + 0xaefa573d + eq + tag_8 + jumpi + 0x00 + dup1 + revert + tag_8: + jumpi(tag_12, callvalue) + jumpi(tag_12, slt(add(not(0x03), calldatasize), 0x00)) + 0x20 + tag_14 + tag_1 + jump // in + tag_14: + mload(0x40) + swap1 + dup2 + mstore + return + tag_12: + 0x00 + dup1 + revert + tag_6: + jumpi(tag_12, callvalue) + jumpi(tag_12, slt(add(not(0x03), calldatasize), 0x00)) + 0x20 + sload(0x00) + mload(0x40) + swap1 + dup2 + mstore + return + tag_4: + jumpi(tag_12, callvalue) + jumpi(tag_12, slt(add(not(0x03), calldatasize), 0x00)) + 0x40 + dup2 + add + dup2 + dup2 + lt + 0xffffffffffffffff + dup3 + gt + or + tag_23 + jumpi + 0x40 + mstore + 0x05 + dup2 + mstore + 0x64 + 0x20 + dup3 + add + shl(0xd9, 0x32b93937b9) + dup2 + mstore + tag_25 + tag_1 + jump // in + tag_25: + swap1 + mload(0x40) + swap4 + dup5 + swap3 + shl(0xe1, 0x05c9a271) + dup5 + mstore + 0x04 + dup5 + add + mstore + 0x40 + 0x24 + dup5 + add + mstore + mload + dup1 + swap2 + dup2 + 0x44 + dup6 + add + mstore + dup5 + dup5 + add + mcopy + 0x00 + dup3 + dup3 + add + dup5 + add + mstore + 0x1f + add + not(0x1f) + and + dup2 + add + sub + add + swap1 + revert + tag_23: + mstore(0x00, shl(0xe0, 0x4e487b71)) + mstore(0x04, 0x41) + revert(0x00, 0x24) + tag_1: + sload(0x00) + not(0x00) + dup2 + eq + tag_26 + jumpi + 0x01 + add + dup1 + 0x00 + sstore + swap1 + jump // out + tag_26: + mstore(0x00, shl(0xe0, 0x4e487b71)) + mstore(0x04, 0x11) + revert(0x00, 0x24) + + auxdata: +} diff --git a/test/libsolidity/semanticTests/errors/require_custom_error_and_string_literal_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_custom_error_and_string_literal_revert_strings_strip.sol new file mode 100644 index 000000000..52b215ed3 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_custom_error_and_string_literal_revert_strings_strip.sol @@ -0,0 +1,14 @@ +contract C { + error MyError(string message); + function customError() pure external { + require(false, MyError("Error")); + } + function stringLiteral() pure external { + require(false, "Error"); + } +} +// ==== +// revertStrings: strip +// ---- +// customError() -> FAILURE, hex"8b3d2d43", 0x20, 5, "Error" +// stringLiteral() -> FAILURE diff --git a/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect.sol b/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect.sol new file mode 100644 index 000000000..ae2540d77 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect.sol @@ -0,0 +1,15 @@ +// The purpose of this test is to check that the side-effect of +// the error parameter occurs, i.e, MyError is constructed with errorCode = 1 +// and also confirm the state is properly reverted +contract C { + error MyError(uint errorCode); + uint public counter = 0; + function count() public returns (uint) { return ++counter; } + function f() external { + require(false, MyError(count())); + counter = 42; + } +} +// ---- +// f() -> FAILURE, hex"30b1b565", 1 +// counter() -> 0 diff --git a/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect_revert_strings_strip.sol new file mode 100644 index 000000000..99ff9f6e1 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_custom_error_constructor_side_effect_revert_strings_strip.sol @@ -0,0 +1,17 @@ +// The purpose of this test is to check that the side-effect of +// the error parameter occurs, i.e, MyError is constructed with errorCode = 1 +// and also confirm the state is properly reverted +contract C { + error MyError(uint errorCode); + uint public counter = 0; + function count() public returns (uint) { return ++counter; } + function f() external { + require(false, MyError(count())); + counter = 42; + } +} +// ==== +// revertStrings: strip +// ---- +// f() -> FAILURE, hex"30b1b565", 1 +// counter() -> 0 diff --git a/test/libsolidity/semanticTests/errors/require_custom_error_no_args_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_custom_error_no_args_revert_strings_strip.sol new file mode 100644 index 000000000..e92b62393 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_custom_error_no_args_revert_strings_strip.sol @@ -0,0 +1,13 @@ +contract C { + error MyError(); + function flag() pure public returns (bool) { return false; } + function f(int param) pure external returns (int) { + require(param % 2 == 0, MyError()); + return param / 2; + } +} +// ==== +// revertStrings: strip +// ---- +// f(int256): 3 -> FAILURE, hex"dd6c951c" +// f(int256): 4 -> 2 diff --git a/test/libsolidity/semanticTests/errors/require_custom_error_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_custom_error_revert_strings_strip.sol new file mode 100644 index 000000000..35235b179 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_custom_error_revert_strings_strip.sol @@ -0,0 +1,14 @@ +contract C { + error MyError(uint errorCode, string errorMsg, bool flag); + function flag() pure public returns (bool) { return false; } + function f(int param) pure external { + uint code = 8; + string memory eMsg = "error"; + require(param % 2 == 0, MyError(code, eMsg, flag())); + } +} +// ==== +// revertStrings: strip +// ---- +// f(int256): 3 -> FAILURE, hex"2ced9160", 8, 0x60, false, 5, "error" +// f(int256): 4 -> diff --git a/test/libsolidity/semanticTests/errors/require_error_condition_evaluated_only_once_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_error_condition_evaluated_only_once_revert_strings_strip.sol new file mode 100644 index 000000000..383dfdd87 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_condition_evaluated_only_once_revert_strings_strip.sol @@ -0,0 +1,25 @@ +contract C { + uint256 counter = 0; + + error CustomError(uint256); + + function getCounter() public view returns (uint256) { + return counter; + } + + function g(bool condition) internal returns (bool) { + counter++; + return condition; + } + + function f(bool condition) external { + require(g(condition), CustomError(counter)); + } +} +// ==== +// revertStrings: strip +// ---- +// f(bool): false -> FAILURE, hex"110b3655", 1 +// getCounter() -> 0 +// f(bool): true -> +// getCounter() -> 1 diff --git a/test/libsolidity/semanticTests/errors/require_error_evaluation_order_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_error_evaluation_order_revert_strings_strip.sol new file mode 100644 index 000000000..c51f9255f --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_evaluation_order_revert_strings_strip.sol @@ -0,0 +1,22 @@ +contract C { + error E(uint256); + + uint counter = 0; + + function even() internal returns (bool) { + return counter % 2 == 0; + } + + function inc() internal returns (uint256) { + return ++counter; + } + + function flip() public { + require(even(), E(inc())); + } +} +// ==== +// revertStrings: strip +// ---- +// flip() -> +// flip() -> FAILURE, hex"002ff067", 2 diff --git a/test/libsolidity/semanticTests/errors/require_error_stack_check_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_error_stack_check_revert_strings_strip.sol new file mode 100644 index 000000000..7dcdb1cc6 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_error_stack_check_revert_strings_strip.sol @@ -0,0 +1,21 @@ +// The purpose of this test is to make sure that error constructor call +// stack items are popped from the stack in the success branch, i.e. when +// require condition is true. +contract C { + error E(uint, uint, uint, function(uint256) external pure returns (uint256)); + uint public x; + + function e(uint256 y) external pure returns (uint256) { + return y; + } + + function f(bool condition, uint a, uint b, uint c) public { + require(condition, E(a, b, c, this.e)); + x = b; + } +} +// ==== +// revertStrings: strip +// ---- +// f(bool,uint256,uint256,uint256): true, 42, 4242, 424242 -> +// x() -> 4242 diff --git a/test/libsolidity/semanticTests/errors/require_inherited_error_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/require_inherited_error_revert_strings_strip.sol new file mode 100644 index 000000000..05c9372c8 --- /dev/null +++ b/test/libsolidity/semanticTests/errors/require_inherited_error_revert_strings_strip.sol @@ -0,0 +1,16 @@ +contract Base +{ + error CustomError(uint256, string, uint256); +} + +contract C is Base +{ + function f() external pure + { + require(false, CustomError(1, "two", 3)); + } +} +// ==== +// revertStrings: strip +// ---- +// f() -> FAILURE, hex"11a1077e", 1, 0x60, 3, 3, "two" diff --git a/test/libsolidity/semanticTests/errors/revert_statement_error_revert_strings_strip.sol b/test/libsolidity/semanticTests/errors/revert_statement_error_revert_strings_strip.sol new file mode 100644 index 000000000..2a14def8a --- /dev/null +++ b/test/libsolidity/semanticTests/errors/revert_statement_error_revert_strings_strip.sol @@ -0,0 +1,10 @@ +contract C { + error MyError(string message); + function revertStatement() pure external { + revert MyError("Error"); + } +} +// ==== +// revertStrings: strip +// ---- +// revertStatement() -> FAILURE, hex"8b3d2d43", 0x20, 5, "Error" From 6b15aca710676279a492fa7ec64f509f2325d500 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 26 Feb 2026 02:21:55 -0300 Subject: [PATCH 1290/1340] Do not remove custom errors in IR pipeline when strip revert strings is requested --- Changelog.md | 1 + libsolidity/codegen/ir/IRGeneratorForStatements.cpp | 8 ++++---- solc/CommandLineParser.cpp | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index 5c1420ca3..640c6e779 100644 --- a/Changelog.md +++ b/Changelog.md @@ -19,6 +19,7 @@ Compiler Features: Bugfixes: * Yul: Fix incorrect serialization of Yul object names containing double quotes and escape sequences, producing output that could not be parsed as valid Yul. * Yul EVM Code Transform: Improve stack shuffler performance by fixing a BFS deduplication issue. +* Yul IR Code Generation: Preserve custom error argument of `require` when stripping of revert strings is selected via `--revert-strings strip`. ### 0.8.34 (2026-02-18) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index d5cb27b6e..398cc6af6 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1158,10 +1158,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) solAssert(arguments.size() > 0, "Expected at least one parameter for require/assert"); solAssert(arguments.size() <= 2, "Expected no more than two parameters for require/assert"); - Type const* messageArgumentType = - arguments.size() > 1 && m_context.revertStrings() != RevertStrings::Strip ? - arguments[1]->annotation().type : - nullptr; + Type const* messageArgumentType = arguments.size() == 2 ? arguments[1]->annotation().type : nullptr; auto const* magicType = dynamic_cast(messageArgumentType); if (magicType && magicType->kind() == MagicType::Kind::Error) @@ -1175,6 +1172,9 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) } else { + // This option only removes strings, not custom errors + if (m_context.revertStrings() == RevertStrings::Strip) + messageArgumentType = nullptr; ASTPointer stringArgumentExpression = messageArgumentType ? arguments[1] : nullptr; std::string requireOrAssertFunction = m_utils.requireOrAssertFunction( functionType->kind() == FunctionType::Kind::Assert, diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index e48849ea7..f29faedec 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -648,7 +648,8 @@ General Information)").c_str(), ( g_strRevertStrings.c_str(), po::value()->value_name(util::joinHumanReadable(g_revertStringsArgs, ",")), - "Strip revert (and require) reason strings or add additional debugging information." + "Strip revert (and require) reason strings or add additional debugging information. " + "Note that 'strip' does not remove custom errors." ) ( g_strDebugInfo.c_str(), From 03486ef73d1eb6eb16d37b330528706a1c2f45b6 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Fri, 27 Mar 2026 20:12:56 -0300 Subject: [PATCH 1291/1340] Update docs --- docs/using-the-compiler.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 84fd13350..fcc8da248 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -378,7 +378,8 @@ Input Description // How to treat revert (and require) reason strings. Settings are // "default", "strip", "debug" and "verboseDebug". // "default" does not inject compiler-generated revert strings and keeps user-supplied ones. - // "strip" removes all revert strings (if possible, i.e. if literals are used) keeping side-effects + // "strip" removes all revert strings (if possible, i.e. if literals are used) keeping side-effects. + // NOTE: "strip" does not remove custom errors. // "debug" injects strings for compiler-generated internal reverts, implemented for ABI encoders V1 and V2 for now. // "verboseDebug" even appends further information to user-supplied revert strings (not yet implemented) "revertStrings": "default", From 37633cc3cc877f4a799201612afdf39081d791cc Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Tue, 23 Sep 2025 14:57:19 -0300 Subject: [PATCH 1292/1340] Add and update tests --- scripts/test_antlr_grammar.sh | 3 ++- .../err | 23 +++++++++++++++++++ ...onstant_state_variable_named_transient.sol | 1 + .../data_location_in_function_type_fail.sol | 1 + ...tion_specifier_test_external_transient.sol | 1 + ...tion_specifier_test_internal_transient.sol | 1 + ..._function_with_data_location_transient.sol | 8 +++++++ ...tion_specifier_test_external_transient.sol | 1 + ...tion_specifier_test_internal_transient.sol | 1 + ...function_parameters_location_transient.sol | 1 + ...n_return_parameters_location_transient.sol | 1 + ...cation_specifier_test_public_transient.sol | 1 + ...n_return_parameters_location_transient.sol | 1 + .../transient_function_type_parameter.sol | 1 + .../illegal_names_exception.sol | 2 ++ .../enum_name_future_keyword_warning.sol | 5 ++++ .../syntaxTests/errors/struct_named_error.sol | 1 + .../events/illegal_names_exception.sol | 2 ++ .../illegal_names_exception_file_level.sol | 3 +++ .../function_type_with_transient_param.sol | 2 ++ .../immutable_state_var_named_transient.sol | 1 + ...port_alias_name_future_keyword_warning.sol | 7 ++++++ .../import_name_future_keyword_warning.sol | 9 ++++++++ .../inlineAssembly/basefee_pre_london.sol | 12 ++++++++++ .../blobhash_pre_cancun_not_reserved.sol | 2 ++ ...ash_with_non_reserved_pure_yul_builtin.sol | 5 ++++ .../prevrandao_allowed_function_pre_paris.sol | 2 ++ .../inlineAssembly/solidity_keywords.sol | 3 ++- .../modifiers/transient_parameter.sol | 1 + .../parsing/contract_named_transient.sol | 2 ++ .../contract_named_at.sol | 1 + .../contract_named_layout.sol | 1 + ...tract_with_members_named_layout_and_at.sol | 2 ++ .../hex_string_cast.sol | 4 ++-- .../storageLayoutSpecifier/literal_cast.sol | 4 ++-- .../storageLayoutSpecifier/type_uint_max.sol | 4 ++-- .../struct_name_future_keyword_warning.sol | 6 +++++ .../syntaxTests/unusedVariables/try_catch.sol | 1 + .../udvt_name_future_keyword_warning.sol | 5 ++++ .../transient_as_identifier.sol | 8 +++++++ .../variable_named_leave.sol | 5 ++++ .../basefee_identifier_pre_london.yul | 7 ++++++ .../blobbasefee_identifier_pre_cancun.yul | 1 + .../yulSyntaxTests/blobhash_pre_cancun.yul | 2 ++ test/libyul/yulSyntaxTests/clz_pre_osaka.yul | 2 ++ .../mcopy_as_identifier_pre_cancun.yul | 3 +++ .../yulSyntaxTests/mcopy_pre_cancun.yul | 3 +++ .../yulSyntaxTests/solidity_keywords.yul | 1 + ...tstore_tload_as_identifiers_pre_cancun.yul | 3 +++ 49 files changed, 159 insertions(+), 8 deletions(-) create mode 100644 test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/err create mode 100644 test/libsolidity/syntaxTests/enums/enum_name_future_keyword_warning.sol create mode 100644 test/libsolidity/syntaxTests/imports/import_alias_name_future_keyword_warning.sol create mode 100644 test/libsolidity/syntaxTests/imports/import_name_future_keyword_warning.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/basefee_pre_london.sol create mode 100644 test/libsolidity/syntaxTests/structs/struct_name_future_keyword_warning.sol create mode 100644 test/libsolidity/syntaxTests/userDefinedValueType/udvt_name_future_keyword_warning.sol create mode 100644 test/libsolidity/syntaxTests/variableDeclaration/variable_named_leave.sol create mode 100644 test/libyul/yulSyntaxTests/basefee_identifier_pre_london.yul diff --git a/scripts/test_antlr_grammar.sh b/scripts/test_antlr_grammar.sh index c8e008c06..2a33f684d 100755 --- a/scripts/test_antlr_grammar.sh +++ b/scripts/test_antlr_grammar.sh @@ -66,8 +66,9 @@ done < <( # Skipping a test with "revert E;" because ANTLR cannot distinguish it from # a variable declaration. grep -v -E 'revertStatement/non_called.sol' | - # Skipping a test with "let basefee := ..." + # Skipping tests with "let basefee := ..." grep -v -E 'inlineAssembly/basefee_berlin_function.sol' | + grep -v -E 'inlineAssembly/basefee_pre_london.sol' | # Skipping a test with "let blobbasefee := ..." grep -v -E 'inlineAssembly/blobbasefee_shanghai_function.sol' | # Skipping a test with "let mcopy := ..." diff --git a/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/err b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/err new file mode 100644 index 000000000..df13b8572 --- /dev/null +++ b/test/cmdlineTests/memoryguard_shadowing_by_inline_assembly_identifiers/err @@ -0,0 +1,23 @@ +Warning: "memoryguard" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. + --> input.sol:10:20: + | +10 | assembly { function memoryguard() {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +Warning: "memoryguard" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. + --> input.sol:11:31: + | +11 | assembly { function f(memoryguard) {} } + | ^^^^^^^^^^^ + +Warning: "memoryguard" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. + --> input.sol:12:36: + | +12 | assembly { function f() -> memoryguard {} } + | ^^^^^^^^^^^ + +Warning: "memoryguard" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. + --> input.sol:13:24: + | +13 | assembly { let memoryguard } + | ^^^^^^^^^^^ diff --git a/test/libsolidity/syntaxTests/constants/constant_state_variable_named_transient.sol b/test/libsolidity/syntaxTests/constants/constant_state_variable_named_transient.sol index 4d9873d36..953dcda41 100644 --- a/test/libsolidity/syntaxTests/constants/constant_state_variable_named_transient.sol +++ b/test/libsolidity/syntaxTests/constants/constant_state_variable_named_transient.sol @@ -2,3 +2,4 @@ contract C { int constant public transient = 0; } // ---- +// Warning 6335: (17-50): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. diff --git a/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol b/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol index cd46b15b0..440ade0ec 100644 --- a/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol +++ b/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol @@ -7,5 +7,6 @@ library L { // ---- // Warning 6162: (251-267): Naming function type parameters is deprecated. +// Warning 6335: (251-267): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // TypeError 6651: (159-173): Data location must be "memory" or "calldata" for parameter in function, but "storage" was given. // TypeError 6651: (251-267): Data location must be "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_transient.sol b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_transient.sol index 98fbb2d5e..087c027d7 100644 --- a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_transient.sol +++ b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_transient.sol @@ -2,4 +2,5 @@ contract test { function f(bytes transient) external; } // ---- +// Warning 6335: (31-46): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // TypeError 6651: (31-46): Data location must be "memory" or "calldata" for parameter in external function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_transient.sol b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_transient.sol index 4a5b6f999..161b6e71f 100644 --- a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_transient.sol +++ b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_transient.sol @@ -2,4 +2,5 @@ contract test { function f(bytes transient) internal {} } // ---- +// Warning 6335: (31-46): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // TypeError 6651: (31-46): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_transient.sol b/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_transient.sol index 75253342c..e14212b2a 100644 --- a/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_transient.sol +++ b/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_transient.sol @@ -9,6 +9,14 @@ library L { function i2() external pure returns (uint[] transient) { } } // ---- +// Warning 6335: (28-44): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (103-119): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (141-157): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (218-234): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (256-272): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (329-345): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (367-383): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (444-460): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // TypeError 6651: (28-44): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. // TypeError 6651: (103-119): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given. // TypeError 6651: (141-157): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_transient.sol b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_transient.sol index 1dcedf49a..0fa3a452a 100644 --- a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_transient.sol +++ b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_transient.sol @@ -2,4 +2,5 @@ library test { function f(bytes transient) external {} } // ---- +// Warning 6335: (30-45): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // TypeError 6651: (30-45): Data location must be "storage", "memory" or "calldata" for parameter in external function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_transient.sol b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_transient.sol index d66fa7fad..e611d3a7c 100644 --- a/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_transient.sol +++ b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_transient.sol @@ -2,4 +2,5 @@ library test { function f(bytes transient) internal pure {} } // ---- +// Warning 6335: (30-45): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // TypeError 6651: (30-45): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_parameters_location_transient.sol b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_parameters_location_transient.sol index 750aa4fee..7acc7f0be 100644 --- a/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_parameters_location_transient.sol +++ b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_parameters_location_transient.sol @@ -2,4 +2,5 @@ contract C { function f(uint[] transient) private pure {} } // ---- +// Warning 6335: (28-44): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // TypeError 6651: (28-44): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_return_parameters_location_transient.sol b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_return_parameters_location_transient.sol index d1bf87624..1020d986d 100644 --- a/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_return_parameters_location_transient.sol +++ b/test/libsolidity/syntaxTests/dataLocations/privateFunction/private_function_return_parameters_location_transient.sol @@ -2,4 +2,5 @@ contract C { function f() private pure returns (uint[] transient) {} } // ---- +// Warning 6335: (52-68): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // TypeError 6651: (52-68): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_transient.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_transient.sol index ce4f42f46..498faf821 100644 --- a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_transient.sol +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_transient.sol @@ -2,4 +2,5 @@ contract test { function f(bytes transient) public; } // ---- +// Warning 6335: (31-46): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // TypeError 6651: (31-46): Data location must be "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_return_parameters_location_transient.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_return_parameters_location_transient.sol index 862b7d236..53f66a1d3 100644 --- a/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_return_parameters_location_transient.sol +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/public_function_return_parameters_location_transient.sol @@ -2,4 +2,5 @@ contract C { function h() public pure returns(uint[] transient) {} } // ---- +// Warning 6335: (50-66): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // TypeError 6651: (50-66): Data location must be "memory" or "calldata" for return parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/transient_function_type_parameter.sol b/test/libsolidity/syntaxTests/dataLocations/transient_function_type_parameter.sol index 04f20e85c..f307b39ab 100644 --- a/test/libsolidity/syntaxTests/dataLocations/transient_function_type_parameter.sol +++ b/test/libsolidity/syntaxTests/dataLocations/transient_function_type_parameter.sol @@ -3,3 +3,4 @@ contract C { } // ---- // Warning 6162: (27-41): Naming function type parameters is deprecated. +// Warning 6335: (27-41): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. diff --git a/test/libsolidity/syntaxTests/duplicateFunctions/illegal_names_exception.sol b/test/libsolidity/syntaxTests/duplicateFunctions/illegal_names_exception.sol index e7541fe23..b9eeeabcf 100644 --- a/test/libsolidity/syntaxTests/duplicateFunctions/illegal_names_exception.sol +++ b/test/libsolidity/syntaxTests/duplicateFunctions/illegal_names_exception.sol @@ -8,5 +8,7 @@ contract C { } } // ---- +// Warning 6335: (61-88): "this" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (90-118): "super" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // Warning 2319: (61-88): This declaration shadows a builtin symbol. // Warning 2319: (90-118): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/enums/enum_name_future_keyword_warning.sol b/test/libsolidity/syntaxTests/enums/enum_name_future_keyword_warning.sol new file mode 100644 index 000000000..78dbbd182 --- /dev/null +++ b/test/libsolidity/syntaxTests/enums/enum_name_future_keyword_warning.sol @@ -0,0 +1,5 @@ +enum error { layout, at } +// ---- +// Warning 6335: (0-25): "error" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (13-19): "layout" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (21-23): "at" will be promoted to keyword in the future and will not be allowed as an identifier anymore. diff --git a/test/libsolidity/syntaxTests/errors/struct_named_error.sol b/test/libsolidity/syntaxTests/errors/struct_named_error.sol index 0ee82ead6..8ced340b2 100644 --- a/test/libsolidity/syntaxTests/errors/struct_named_error.sol +++ b/test/libsolidity/syntaxTests/errors/struct_named_error.sol @@ -4,3 +4,4 @@ contract C { error x; } // ---- +// Warning 6335: (52-74): "error" will be promoted to keyword in the future and will not be allowed as an identifier anymore. diff --git a/test/libsolidity/syntaxTests/events/illegal_names_exception.sol b/test/libsolidity/syntaxTests/events/illegal_names_exception.sol index c45db8d7d..61c9ab79d 100644 --- a/test/libsolidity/syntaxTests/events/illegal_names_exception.sol +++ b/test/libsolidity/syntaxTests/events/illegal_names_exception.sol @@ -5,5 +5,7 @@ contract C { event _(); } // ---- +// Warning 6335: (80-93): "this" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (95-109): "super" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // Warning 2319: (80-93): This declaration shadows a builtin symbol. // Warning 2319: (95-109): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/events/illegal_names_exception_file_level.sol b/test/libsolidity/syntaxTests/events/illegal_names_exception_file_level.sol index 48b23dc38..57da93d05 100644 --- a/test/libsolidity/syntaxTests/events/illegal_names_exception_file_level.sol +++ b/test/libsolidity/syntaxTests/events/illegal_names_exception_file_level.sol @@ -2,3 +2,6 @@ event this(); event super(); event _(); +// ---- +// Warning 6335: (66-79): "this" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (80-94): "super" will be promoted to keyword in the future and will not be allowed as an identifier anymore. diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_with_transient_param.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_with_transient_param.sol index b38e37177..a7e47cdba 100644 --- a/test/libsolidity/syntaxTests/functionTypes/function_type_with_transient_param.sol +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_with_transient_param.sol @@ -5,4 +5,6 @@ contract C { // ---- // Warning 6162: (27-41): Naming function type parameters is deprecated. // Warning 6162: (69-85): Naming function type parameters is deprecated. +// Warning 6335: (27-41): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (69-85): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // TypeError 6651: (69-85): Data location must be "memory" or "calldata" for parameter in function, but none was given. diff --git a/test/libsolidity/syntaxTests/immutable/immutable_state_var_named_transient.sol b/test/libsolidity/syntaxTests/immutable/immutable_state_var_named_transient.sol index c0ac3a8ab..31b08b5d8 100644 --- a/test/libsolidity/syntaxTests/immutable/immutable_state_var_named_transient.sol +++ b/test/libsolidity/syntaxTests/immutable/immutable_state_var_named_transient.sol @@ -2,3 +2,4 @@ contract C { address public immutable transient; } // ---- +// Warning 6335: (17-51): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. diff --git a/test/libsolidity/syntaxTests/imports/import_alias_name_future_keyword_warning.sol b/test/libsolidity/syntaxTests/imports/import_alias_name_future_keyword_warning.sol new file mode 100644 index 000000000..b62914cbe --- /dev/null +++ b/test/libsolidity/syntaxTests/imports/import_alias_name_future_keyword_warning.sol @@ -0,0 +1,7 @@ +==== Source: a ==== +contract A {} +==== Source: b ==== +import {A as layout} from "a"; +contract C is layout {} +// ---- +// Warning 6335: (b:13-19): "layout" will be promoted to keyword in the future and will not be allowed as an identifier anymore. diff --git a/test/libsolidity/syntaxTests/imports/import_name_future_keyword_warning.sol b/test/libsolidity/syntaxTests/imports/import_name_future_keyword_warning.sol new file mode 100644 index 000000000..a5e012a08 --- /dev/null +++ b/test/libsolidity/syntaxTests/imports/import_name_future_keyword_warning.sol @@ -0,0 +1,9 @@ +==== Source: a ==== +uint constant CONST = 10; +==== Source: b ==== +import "a" as transient; +contract C { + uint x = transient.CONST; +} +// ---- +// Warning 6335: (b:0-24): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/basefee_pre_london.sol b/test/libsolidity/syntaxTests/inlineAssembly/basefee_pre_london.sol new file mode 100644 index 000000000..80021b803 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/basefee_pre_london.sol @@ -0,0 +1,12 @@ +contract C { + function f() public view returns (uint ret) { + assembly { + let basefee := sload(0) + ret := basefee + } + } +} +// ==== +// EVMVersion: <=berlin +// ---- +// Warning 5470: (98-105): "basefee" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_reserved.sol b/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_reserved.sol index 1ac24cc64..ee9445ff3 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_reserved.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_reserved.sol @@ -17,3 +17,5 @@ contract C { // ==== // EVMVersion: <=shanghai // ---- +// Warning 5470: (98-106): "blobhash" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. +// Warning 5470: (237-303): "blobhash" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_non_reserved_pure_yul_builtin.sol b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_non_reserved_pure_yul_builtin.sol index 9b6ee266c..8f834dbbf 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/clash_with_non_reserved_pure_yul_builtin.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/clash_with_non_reserved_pure_yul_builtin.sol @@ -8,3 +8,8 @@ contract C { assembly { let memoryguard } } } +// ---- +// Warning 5470: (207-232): "memoryguard" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. +// Warning 5470: (265-276): "memoryguard" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. +// Warning 5470: (318-329): "memoryguard" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. +// Warning 5470: (358-369): "memoryguard" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_allowed_function_pre_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_allowed_function_pre_paris.sol index d85e77a45..07bb28c2a 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_allowed_function_pre_paris.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_allowed_function_pre_paris.sol @@ -18,3 +18,5 @@ contract C { // ==== // EVMVersion: =byzantium // ---- +// Warning 6335: (165-183): "error" will be promoted to keyword in the future and will not be allowed as an identifier anymore. // Warning 5667: (49-55): Unused function parameter. Remove or comment out the variable name to silence this warning. // Warning 5667: (89-95): Unused try/catch parameter. Remove or comment out the variable name to silence this warning. // Warning 5667: (122-143): Unused try/catch parameter. Remove or comment out the variable name to silence this warning. diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/udvt_name_future_keyword_warning.sol b/test/libsolidity/syntaxTests/userDefinedValueType/udvt_name_future_keyword_warning.sol new file mode 100644 index 000000000..1132185d4 --- /dev/null +++ b/test/libsolidity/syntaxTests/userDefinedValueType/udvt_name_future_keyword_warning.sol @@ -0,0 +1,5 @@ +type error is int; +type layout is uint; +// ---- +// Warning 6335: (0-18): "error" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (19-39): "layout" will be promoted to keyword in the future and will not be allowed as an identifier anymore. diff --git a/test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier.sol b/test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier.sol index ced189faf..b6680a966 100644 --- a/test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier.sol +++ b/test/libsolidity/syntaxTests/variableDeclaration/transient_as_identifier.sol @@ -23,3 +23,11 @@ contract D { } } // ---- +// Warning 6335: (17-53): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (75-89): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (101-115): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (127-149): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (168-181): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (253-267): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (321-334): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. +// Warning 6335: (368-385): "transient" will be promoted to keyword in the future and will not be allowed as an identifier anymore. diff --git a/test/libsolidity/syntaxTests/variableDeclaration/variable_named_leave.sol b/test/libsolidity/syntaxTests/variableDeclaration/variable_named_leave.sol new file mode 100644 index 000000000..f6651bc18 --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/variable_named_leave.sol @@ -0,0 +1,5 @@ +contract C { + uint leave = 1; +} +// ---- +// Warning 6335: (17-31): "leave" will be promoted to keyword in the future and will not be allowed as an identifier anymore. diff --git a/test/libyul/yulSyntaxTests/basefee_identifier_pre_london.yul b/test/libyul/yulSyntaxTests/basefee_identifier_pre_london.yul new file mode 100644 index 000000000..65551461c --- /dev/null +++ b/test/libyul/yulSyntaxTests/basefee_identifier_pre_london.yul @@ -0,0 +1,7 @@ +{ + function basefee() {} +} +// ==== +// EVMVersion: <=berlin +// ---- +// Warning 5470: (6-27): "basefee" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. diff --git a/test/libyul/yulSyntaxTests/blobbasefee_identifier_pre_cancun.yul b/test/libyul/yulSyntaxTests/blobbasefee_identifier_pre_cancun.yul index 42c1f2c0a..11a5bacf6 100644 --- a/test/libyul/yulSyntaxTests/blobbasefee_identifier_pre_cancun.yul +++ b/test/libyul/yulSyntaxTests/blobbasefee_identifier_pre_cancun.yul @@ -4,3 +4,4 @@ // ==== // EVMVersion: <=shanghai // ---- +// Warning 5470: (6-31): "blobbasefee" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. diff --git a/test/libyul/yulSyntaxTests/blobhash_pre_cancun.yul b/test/libyul/yulSyntaxTests/blobhash_pre_cancun.yul index 777024cda..4bed582b3 100644 --- a/test/libyul/yulSyntaxTests/blobhash_pre_cancun.yul +++ b/test/libyul/yulSyntaxTests/blobhash_pre_cancun.yul @@ -11,3 +11,5 @@ // ==== // EVMVersion: <=shanghai // ---- +// Warning 5470: (20-28): "blobhash" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. +// Warning 5470: (55-77): "blobhash" will be promoted to Yul reserved identifier in the future and will not be allowed anymore as an identifier. diff --git a/test/libyul/yulSyntaxTests/clz_pre_osaka.yul b/test/libyul/yulSyntaxTests/clz_pre_osaka.yul index 738096598..be4e41a89 100644 --- a/test/libyul/yulSyntaxTests/clz_pre_osaka.yul +++ b/test/libyul/yulSyntaxTests/clz_pre_osaka.yul @@ -12,3 +12,5 @@ // ==== // EVMVersion: Date: Mon, 15 Sep 2025 13:23:13 -0300 Subject: [PATCH 1293/1340] Warning about Solidity/Yul future keywords and reserved identifiers --- Changelog.md | 2 + liblangutil/Token.cpp | 33 ++++++++++++++- liblangutil/Token.h | 8 +++- libsolidity/analysis/NameAndTypeResolver.cpp | 44 ++++++++++++-------- libyul/AsmAnalysis.cpp | 21 ++++++++++ libyul/AsmAnalysis.h | 2 + libyul/optimiser/OptimizerUtilities.cpp | 7 +++- 7 files changed, 97 insertions(+), 20 deletions(-) diff --git a/Changelog.md b/Changelog.md index 640c6e779..1e26c89f9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,8 @@ Language Features: * General: Add a builtin that computes the base slot of a storage namespace using the `erc7201` formula from ERC-7201. +* Name Resolver: Warn about identifiers selected for future promotion to Solidity or Yul keywords (`at`, `error`, `layout`, `leave`, `super`, `transient`, `this`). +* Yul Analyzer: Warn about identifiers selected for future promotion to Yul keywords and reserved identifiers (`basefee`, `blobbasefee`, `blobhash`, `clz`, `leave`, `memoryguard`, `mcopy`, `prevrandao`, `tload`, `tstore`). Compiler Features: * Commandline Interface: Disallow selecting the deprecated assembly input mode that was only accessible via `--assemble` instead of treating it as equivalent to `--strict-assembly`. diff --git a/liblangutil/Token.cpp b/liblangutil/Token.cpp index 1c5ae6f4e..0a75e06d3 100644 --- a/liblangutil/Token.cpp +++ b/liblangutil/Token.cpp @@ -149,7 +149,38 @@ static Token keywordByName(std::string_view const _name) bool isYulKeyword(std::string_view const _literal) { - return _literal == "leave" || isYulKeyword(keywordByName(_literal)); + return isYulKeyword(keywordByName(_literal)); +} + +bool isFutureSolidityKeyword(std::string_view const _literal) +{ + return + _literal == "transient" || + _literal == "layout" || + _literal == "at" || + _literal == "error" || + _literal == "super" || + _literal == "this" || + isFutureYulKeyword(_literal); +} + +bool isFutureYulKeyword(std::string_view const _literal) +{ + return _literal == "leave"; +} + +bool isFutureYulReservedIdentifier(std::string_view const _literal) +{ + return + _literal == "basefee" || + _literal == "blobbasefee" || + _literal == "blobhash" || + _literal == "clz" || + _literal == "mcopy" || + _literal == "memoryguard" || + _literal == "prevrandao" || + _literal == "tload" || + _literal == "tstore"; } std::tuple fromIdentifierOrKeyword(std::string const& _literal) diff --git a/liblangutil/Token.h b/liblangutil/Token.h index bfbc89bb4..b9ae18ceb 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -377,7 +377,13 @@ namespace TokenTraits return _token > Token::NonExperimentalEnd && _token < Token::ExperimentalEnd; } - bool isYulKeyword(std::string_view _literal); + bool isYulKeyword(std::string_view const _literal); + + bool isFutureSolidityKeyword(std::string_view const _literal); + + bool isFutureYulKeyword(std::string_view const _literal); + + bool isFutureYulReservedIdentifier(std::string_view const _literal); Token AssignmentToBinaryOp(Token op); diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 2d55b46fc..ed5061b5d 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -537,28 +537,38 @@ bool DeclarationRegistrationHelper::registerDeclaration( static std::set illegalNames{"_", "super", "this"}; - if (illegalNames.count(name)) + auto isPublicFunctionOrEvent = [](Declaration const* _d) -> bool { - auto isPublicFunctionOrEvent = [](Declaration const* _d) -> bool + if (auto functionDefinition = dynamic_cast(_d)) { - if (auto functionDefinition = dynamic_cast(_d)) - { - if (!functionDefinition->isFree() && functionDefinition->isPublic()) - return true; - } - else if (dynamic_cast(_d)) + if (!functionDefinition->isFree() && functionDefinition->isPublic()) return true; + } + else if (dynamic_cast(_d)) + return true; - return false; - }; - + return false; + }; + if (illegalNames.count(name) && !isPublicFunctionOrEvent(&_declaration)) + { // We allow an exception for public functions or events. - if (!isPublicFunctionOrEvent(&_declaration)) - _errorReporter.declarationError( - 3726_error, - *_errorLocation, - "The name \"" + name + "\" is reserved." - ); + _errorReporter.declarationError( + 3726_error, + *_errorLocation, + "The name \"" + name + "\" is reserved." + ); + } + else if (TokenTraits::isFutureSolidityKeyword(name)) + { + _errorReporter.warning( + 6335_error, + *_errorLocation, + fmt::format( + "\"{}\" will be promoted to keyword in the future" + " and will not be allowed as an identifier anymore.", + name + ) + ); } if (!_container.registerDeclaration(_declaration, _name, _errorLocation, !_declaration.isVisibleInContract() || _inactive, false)) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 79d8bfd26..8166331d8 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -745,6 +746,8 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons _location, fmt::format("The identifier \"{}\" is reserved and can not be used.", label) ); + + warnIfFutureKeywordOrReservedIdentifier(_identifier, _location); } bool AsmAnalyzer::validateInstructions(std::string_view _instructionIdentifier, langutil::SourceLocation const& _location) @@ -953,3 +956,21 @@ void AsmAnalyzer::validateObjectStructure(langutil::SourceLocation const& _astRo } } } + +void AsmAnalyzer::warnIfFutureKeywordOrReservedIdentifier(YulName _identifier, langutil::SourceLocation const& _location) +{ + if ( + TokenTraits::isFutureYulKeyword(_identifier.str()) || + TokenTraits::isFutureYulReservedIdentifier(_identifier.str()) + ) + m_errorReporter.warning( + 5470_error, + _location, + fmt::format( + "\"{}\" will be promoted to Yul {} in the future " + "and will not be allowed anymore as an identifier.", + _identifier.str(), + (TokenTraits::isFutureYulKeyword(_identifier.str()) ? "keyword" : "reserved identifier") + ) + ); +} diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 51b8cde2b..6ffa0576e 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -128,6 +128,8 @@ class AsmAnalyzer void validateObjectStructure(langutil::SourceLocation const& _astRootLocation); + void warnIfFutureKeywordOrReservedIdentifier(YulName _identifier, langutil::SourceLocation const& _location); + yul::ExternalIdentifierAccess::Resolver m_resolver; Scope* m_currentScope = nullptr; /// Variables that are active at the current point in assembly (as opposed to diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index 3001d43f8..63097a673 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -58,7 +58,12 @@ void yul::removeEmptyBlocks(Block& _block) bool yul::isRestrictedIdentifier(Dialect const& _dialect, std::string_view const _identifier) { - return _identifier.empty() || hasLeadingOrTrailingDot(_identifier) || TokenTraits::isYulKeyword(_identifier) || _dialect.reservedIdentifier(_identifier); + return + _identifier.empty() || + hasLeadingOrTrailingDot(_identifier) || + TokenTraits::isYulKeyword(_identifier) || + TokenTraits::isFutureYulKeyword(_identifier) || + _dialect.reservedIdentifier(_identifier); } std::optional yul::toEVMInstruction(Dialect const& _dialect, FunctionName const& _name) From 35a9b30ff3f361ca6866b5c3066cf8d6096baf2a Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Wed, 24 Sep 2025 16:35:49 -0300 Subject: [PATCH 1294/1340] Update docs --- docs/assembly.rst | 1 + docs/units-and-global-variables.rst | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/docs/assembly.rst b/docs/assembly.rst index 0458e3196..30f451c4b 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -46,6 +46,7 @@ Solidity language without a compiler change. pragma solidity >=0.4.16 <0.9.0; library GetCode { + // This will report a warning - `at` will be promoted to reserved keyword function at(address addr) public view returns (bytes memory code) { assembly { // retrieve the size of the code, this needs assembly diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index d46bdaddf..88b5017b3 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -436,3 +436,11 @@ These keywords are reserved in Solidity. They might become part of the syntax in ``mutable``, ``null``, ``of``, ``partial``, ``promise``, ``reference``, ``relocatable``, ``sealed``, ``sizeof``, ``static``, ``supports``, ``switch``, ``typedef``, ``typeof``, ``var``. + +.. note:: + The following identifiers will become keywords in the future and will no longer be usable as names: + ``at``, ``error``, ``layout``, ``leave``, ``super``, ``transient``, ``this``. + + There are also names which will be considered Yul reserved identifiers in the future: + ``basefee``, ``blobbasefee``, ``blobhash``, ``clz``, ``memoryguard``, ``mcopy``, ``prevrandao``, ``tload``, ``tstore``. + From ad2fda2049a25f285012dfec4f9106373fa9ca19 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 2 Mar 2026 17:24:35 -0300 Subject: [PATCH 1295/1340] workaround for openzeppelin external tests --- test/externalTests/zeppelin.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalTests/zeppelin.sh b/test/externalTests/zeppelin.sh index aca8311ac..c26038e0b 100755 --- a/test/externalTests/zeppelin.sh +++ b/test/externalTests/zeppelin.sh @@ -116,7 +116,7 @@ function zeppelin_test const result = await runSuper(args); result.output.errors = (result.output.errors || []).filter(err => { - if (err.severity === "warning" && err.message.includes("deprecated")) { + if (err.severity === "warning" && (err.message.includes("deprecated") || err.message.includes("promoted"))) { return false; // suppress this warning } return true; From 392c5f9d79bbadd5f4a5dda2ef14238bc0eb0064 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Wed, 29 Apr 2026 00:09:34 -0300 Subject: [PATCH 1296/1340] Docs: fix ERC 7201 link --- docs/units-and-global-variables.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index d46bdaddf..e633fbe91 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -247,7 +247,7 @@ Mathematical and Cryptographic Functions When running ``sha256``, ``ripemd160`` or ``ecrecover`` on a *private blockchain*, you might encounter Out-of-Gas. This is because these functions are implemented as "precompiled contracts" and only really exist after they receive the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution might run into an Out-of-Gas error. A workaround for this problem is to first send Wei (1 for example) to each of the contracts before you use them in your actual contracts. This is not an issue on the main or test net. ``erc7201(string memory id) returns (uint)`` - compute the base slot of a storage namespace of a given ``id`` according to the ``erc7201`` formula defined by `ERC-7201`. + compute the base slot of a storage namespace of a given ``id`` according to the ``erc7201`` formula defined by `ERC-7201 `_. The formula is equivalent to ``keccak256(keccak256(id) - 1) & ~0xff``. The builtin accepts arbitrary strings, including ones containing whitespace. The function can be used in compile-time context. From b8e1e41b86a05c34f10f24a34f2e554a2f7a98ff Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 28 Apr 2026 15:27:46 +0200 Subject: [PATCH 1297/1340] Sort changelog and add date for 0.8.35 release --- Changelog.md | 8 ++++---- docs/bugs_by_version.json | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index 1e26c89f9..072a7014c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.8.35 (unreleased) +### 0.8.35 (2026-04-29) Language Features: * General: Add a builtin that computes the base slot of a storage namespace using the `erc7201` formula from ERC-7201. @@ -8,14 +8,14 @@ Language Features: Compiler Features: * Commandline Interface: Disallow selecting the deprecated assembly input mode that was only accessible via `--assemble` instead of treating it as equivalent to `--strict-assembly`. * Commandline Interface: Introduce `--experimental` flag required for enabling the experimental mode. -* Commandline Interface: Replace ``--ethdebug`` and ``--ethdebug-runtime`` with more granular ``--ethdebug-resources``, ``--ethdebug-compilation``, ``--ethdebug-program`` and ``--ethdebug-program-runtime`` flags. Per-contract program outputs no longer force full binary compilation. +* Commandline Interface: Replace the experimental `--ethdebug` and `--ethdebug-runtime` outputs with the more granular `--ethdebug-resources`, `--ethdebug-compilation`, `--ethdebug-program` and `--ethdebug-program-runtime`. Producing `ethdebug/format/info/resources` no longer forces full binary compilation. * EVM: Introduce experimental EVM version `@future`. -* General: Introduce the SSA CFG codegen (experimental). * General: Improve performance of sanity checks throughout the compiler implementation. +* General: Introduce the SSA CFG codegen (experimental). * General: Restrict the existing experimental features (`generic-solidity`, `lsp`, `ethdebug`, `eof`, `evm`, `ast-import`, `evmasm-import`, `ir-ast`, `ssa-cfg`) to experimental mode. * Metadata: Store the state of the experimental mode in JSON and CBOR metadata. In CBOR this broadens the meaning of the existing `experimental` field, which used to indicate only the presence of certain experimental pragmas in the source. * Standard JSON Interface: Introduce `settings.experimental` setting required for enabling the experimental mode. -* Standard JSON Interface: Replace the top-level ``ethdebug`` output with ``ethdebug.resources`` and ``ethdebug.compilation``. Decouple ethdebug outputs from binary compilation so that global ethdebug outputs can be produced without generating bytecode. +* Standard JSON Interface: Replace the experimental top-level `ethdebug` output with `ethdebug.resources` and `ethdebug.compilation`. Decouple ethdebug outputs from binary compilation so that requesting the `ethdebug/format/info/resources` schema artifacts does not trigger bytecode generation. * Yul Optimizer: Improve performance of control flow side effects collector and function references resolver. Bugfixes: diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index c5576d4b2..d7e28ab78 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -2069,6 +2069,10 @@ "bugs": [], "released": "2026-02-18" }, + "0.8.35": { + "bugs": [], + "released": "2026-04-29" + }, "0.8.4": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", From 45c484ebc08df071b36e60c4e4884c489a525245 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Wed, 29 Apr 2026 12:16:32 +0200 Subject: [PATCH 1298/1340] Bump version to 0.8.36 and add changelog skeleton --- CMakeLists.txt | 2 +- Changelog.md | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 685df9809..44ef6dbcd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.35") +set(PROJECT_VERSION "0.8.36") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index 072a7014c..ea6999ec5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,12 @@ +### 0.8.36 (unreleased) + +Language Features: + +Compiler Features: + +Bugfixes: + + ### 0.8.35 (2026-04-29) Language Features: From 9895088a6411f504130f66aaea9b3f172f598c5f Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 28 Apr 2026 09:22:44 +0200 Subject: [PATCH 1299/1340] SSA CFG: mark BlockId/InstId hasValue() as constexpr noexcept --- libyul/backends/evm/ssa/SSACFGTypes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libyul/backends/evm/ssa/SSACFGTypes.h b/libyul/backends/evm/ssa/SSACFGTypes.h index 7b322eddb..b3adb8f5f 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.h +++ b/libyul/backends/evm/ssa/SSACFGTypes.h @@ -40,7 +40,7 @@ struct BlockId { using ValueType = std::uint32_t; ValueType value = std::numeric_limits::max(); - bool hasValue() const { return value != std::numeric_limits::max(); } + constexpr bool hasValue() const noexcept { return value != std::numeric_limits::max(); } auto operator<=>(BlockId const&) const = default; }; @@ -48,7 +48,7 @@ struct InstId { using ValueType = std::uint32_t; ValueType value = std::numeric_limits::max(); - bool hasValue() const { return value != std::numeric_limits::max(); } + constexpr bool hasValue() const noexcept { return value != std::numeric_limits::max(); } auto operator<=>(InstId const&) const = default; }; From 033dca28fe21936b4bfb0edc8e6af4d8d99ce7b5 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 28 Apr 2026 09:24:13 +0200 Subject: [PATCH 1300/1340] SSA CFG: collapse per-kind value debug data into a single map --- libyul/backends/evm/ssa/SSACFGDebugInfo.h | 36 +++++------------------ 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/libyul/backends/evm/ssa/SSACFGDebugInfo.h b/libyul/backends/evm/ssa/SSACFGDebugInfo.h index d308da6b4..42be2b373 100644 --- a/libyul/backends/evm/ssa/SSACFGDebugInfo.h +++ b/libyul/backends/evm/ssa/SSACFGDebugInfo.h @@ -23,6 +23,7 @@ #include #include +#include #include namespace solidity::yul::ssa @@ -70,14 +71,16 @@ struct SSACFGDebugInfo void setValueDebugData(ValueId _id, langutil::DebugData::ConstPtr _data) { yulAssert(_id.hasValue()); - auto& vec = vectorForKind(_id.kind()); - ensureSize(vec, _id.value()); - vec[_id.value()] = std::move(_data); + m_valueDebugData[_id] = std::move(_data); } langutil::DebugData::ConstPtr const& valueDebugData(ValueId _id) const { - return getOrEmpty(vectorForKind(_id.kind()), _id.value()); + static langutil::DebugData::ConstPtr const empty{nullptr}; + auto const it = m_valueDebugData.find(_id); + if (it == m_valueDebugData.end()) + return empty; + return it->second; } /// Top-level debug data for the SSACFG (e.g. the function definition's debug data). @@ -101,33 +104,10 @@ struct SSACFGDebugInfo return _debugData[_index]; } - std::vector& vectorForKind(ValueId::Kind const _kind) - { - switch (_kind) - { - case ValueId::Kind::Literal: return m_literalDebugData; - case ValueId::Kind::Variable: return m_variableDebugData; - case ValueId::Kind::Phi: return m_phiDebugData; - default: yulAssert(false, "No debug data for unreachable values."); - } - } - std::vector const& vectorForKind(ValueId::Kind const _kind) const - { - switch (_kind) - { - case ValueId::Kind::Literal: return m_literalDebugData; - case ValueId::Kind::Variable: return m_variableDebugData; - case ValueId::Kind::Phi: return m_phiDebugData; - default: yulAssert(false, "No debug data for unreachable values."); - } - } - std::vector m_blockDebugData; std::vector m_exitDebugData; std::vector m_operationDebugData; - std::vector m_literalDebugData; - std::vector m_variableDebugData; - std::vector m_phiDebugData; + std::map m_valueDebugData; }; } From 230f3a2d641dc2dc0f65506f24a99d8f139a4679 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 28 Apr 2026 09:26:11 +0200 Subject: [PATCH 1301/1340] SSA CFG: unify per-kind values into a single Inst table Replaces the tagged-union ValueId (Literal / Variable / Phi / Unreachable) with a (InstId, output position) reference into a uniform Inst table. The InstructionStore now holds one std::vector with an InstOpcode discriminator (Const, Phi, Upsilon, BuiltinCall, Call, Unreachable, FunctionArg) and side-tables for each opcode's payload. BasicBlock loses its separate phis / operations / upsilons vectors in favor of a single `instructions` vector, so iterating a block now visits all Insts in program order. --- libyul/backends/evm/ssa/CodeTransform.cpp | 168 ++++--- libyul/backends/evm/ssa/CodeTransform.h | 16 +- libyul/backends/evm/ssa/InstructionStore.h | 217 +++++---- libyul/backends/evm/ssa/LivenessAnalysis.cpp | 79 ++-- libyul/backends/evm/ssa/LivenessAnalysis.h | 5 + libyul/backends/evm/ssa/PhiInverse.cpp | 10 +- libyul/backends/evm/ssa/SSACFG.cpp | 67 +-- libyul/backends/evm/ssa/SSACFG.h | 185 ++++++-- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 99 ++-- libyul/backends/evm/ssa/SSACFGBuilder.h | 2 +- libyul/backends/evm/ssa/SSACFGDebugInfo.h | 38 +- libyul/backends/evm/ssa/SSACFGTypes.cpp | 26 +- libyul/backends/evm/ssa/SSACFGTypes.h | 82 ++-- libyul/backends/evm/ssa/Stack.cpp | 4 + libyul/backends/evm/ssa/Stack.h | 42 +- .../backends/evm/ssa/StackLayoutGenerator.cpp | 67 +-- libyul/backends/evm/ssa/StackSlotLiveness.h | 5 +- libyul/backends/evm/ssa/StackUtils.cpp | 21 +- libyul/backends/evm/ssa/StackUtils.h | 2 +- .../backends/evm/ssa/io/DotExporterBase.cpp | 2 +- libyul/backends/evm/ssa/io/JSONExporter.cpp | 104 +++-- .../ssa/transform/TrivialPhiEliminator.cpp | 93 ++-- libyul/backends/evm/ssa/util/UseCountSet.h | 9 +- .../standard_yul_cfg_json_export/output.json | 434 +++++++++--------- .../strict_asm_yul_cfg_json_export/output | 58 +-- test/cmdlineTests/yul_cfg_json_export/output | 434 +++++++++--------- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 28 +- test/libyul/ssa/StackShufflerTest.cpp | 190 ++++---- test/libyul/ssa/controlFlowGraph/complex.yul | 74 +-- test/libyul/ssa/controlFlowGraph/complex2.yul | 90 ++-- .../default_initialized_variable.yul | 10 +- test/libyul/ssa/controlFlowGraph/function.yul | 12 +- test/libyul/ssa/controlFlowGraph/if.yul | 20 +- test/libyul/ssa/controlFlowGraph/if_const.yul | 8 +- .../ssa/controlFlowGraph/nested_for.yul | 134 +++--- .../ssa/controlFlowGraph/nested_function.yul | 50 +- test/libyul/ssa/controlFlowGraph/switch.yul | 32 +- .../ssa/controlFlowGraph/switch_const.yul | 8 +- .../ssa/stackLayoutGenerator/dead_code.yul | 20 +- .../ssa/stackLayoutGenerator/function.yul | 18 +- .../ssa/stackLayoutGenerator/multi_return.yul | 24 +- .../ssa/stackLayoutGenerator/nested_for.yul | 60 +-- .../ssa/stackLayoutGenerator/recursion.yul | 24 +- .../ssa/stackLayoutGenerator/simple_for.yul | 52 +-- .../ssa/stackLayoutGenerator/simple_if.yul | 22 +- .../ssa/stackLayoutGenerator/switch.yul | 24 +- .../spill_many_for_small_target.stack | 2 +- .../spill_to_pop_deep_junk.stack | 2 +- 48 files changed, 1716 insertions(+), 1457 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 4b0bcf50d..6976f3ace 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -162,7 +162,7 @@ CodeTransform::CodeTransform( if (isFunctionGraph && m_cfg.canContinue) expectedStackTop.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); for (auto const& valueID: m_cfg.arguments | ranges::views::reverse) - expectedStackTop.push_back(StackSlot::makeValueID(valueID)); + expectedStackTop.push_back(StackSlot::makeValueID(_cfg, valueID)); assertLayoutCompatibility(m_stack.data(), expectedStackTop); } @@ -179,15 +179,15 @@ void CodeTransform::operator()(SSACFG::BlockId const _blockId) yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); auto const& block = m_cfg.block(_blockId); - yulAssert(block.operations.size() == blockLayout->operationIn.size(), "We need as many operation stack layouts as we have operations"); - for (std::size_t operationIndex = 0; operationIndex < block.operations.size(); ++operationIndex) - { + std::size_t operationIndex = 0; + m_cfg.forEachOperation(block, [&](InstId const instId, SSACFG::Inst const&) { + yulAssert(operationIndex < blockLayout->operationIn.size()); auto const& operationInLayout = blockLayout->operationIn[operationIndex]; - - // perform the operation - (*this)(block.operations[operationIndex], operationInLayout); - } + (*this)(instId, operationInLayout); + ++operationIndex; + }); + yulAssert(operationIndex == blockLayout->operationIn.size()); // Shuffle to the block's exit layout before dispatching the exit. // This ensures the condition is on top for ConditionalJump, phi pre-images are @@ -199,16 +199,16 @@ void CodeTransform::operator()(SSACFG::BlockId const _blockId) std::visit(solidity::util::GenericVisitor{ [this, &_blockId](auto const& exit) { (*this)(_blockId, exit); } }, block.exit); } -void CodeTransform::operator()(SSACFG::InstId _opId, StackData const& _operationInputLayout) +void CodeTransform::operator()(InstId _instId, StackData const& _operationInputLayout) { - SSACFG::Operation const& _operation = m_cfg.operation(_opId); - bool const hasReturnLabel = - std::holds_alternative(_operation.kind) && - std::get(_operation.kind).canContinue; + SSACFG::Inst const& _inst = m_cfg.inst(_instId); + yulAssert(_inst.isOperation()); + bool const isCall = _inst.opcode == InstOpcode::Call; + bool const hasReturnLabel = isCall && m_cfg.callPayload(_instId).canContinue; if (hasReturnLabel) { - auto const [it, inserted] = m_returnLabels.try_emplace(_opId, 0); + auto const [it, inserted] = m_returnLabels.try_emplace(_instId, 0); yulAssert(inserted, "Call sites should be unique."); it->second = m_assembly.newLabelId(); } @@ -229,86 +229,94 @@ void CodeTransform::operator()(SSACFG::InstId _opId, StackData const& _operation assertLayoutCompatibility(m_stack.data(), _operationInputLayout); // Assert that we have the inputs of the operation on stack top. - yulAssert(m_stack.size() >= _operation.inputs.size()); + yulAssert(m_stack.size() >= _inst.inputs.size()); for (auto const& [stackEntry, input]: ranges::views::zip( - m_stack | ranges::views::take_last(_operation.inputs.size()), - _operation.inputs + m_stack | ranges::views::take_last(_inst.inputs.size()), + _inst.inputs )) yulAssert(stackEntry.isValueID() && stackEntry.valueID() == input); // if the function can continue (doesn't always abort), make sure we have the correct return label slot in place if (hasReturnLabel) { - yulAssert(m_stack.size() > _operation.inputs.size()); - auto const returnLabelSlot = m_stack.slot(StackDepth{_operation.inputs.size()}); - yulAssert(std::holds_alternative(_operation.kind)); + yulAssert(m_stack.size() > _inst.inputs.size()); + auto const returnLabelSlot = m_stack.slot(StackDepth{_inst.inputs.size()}); + yulAssert(isCall); yulAssert( returnLabelSlot.isFunctionCallReturnLabel() && - m_callSites.operationId(returnLabelSlot.functionCallReturnLabel()) == _opId + m_callSites.instId(returnLabelSlot.functionCallReturnLabel()) == _instId ); } // height of the stack sans function return label and operation inputs - std::size_t const baseHeight = m_stack.size() - _operation.inputs.size() - (hasReturnLabel ? 1 : 0); + std::size_t const baseHeight = m_stack.size() - _inst.inputs.size() - (hasReturnLabel ? 1 : 0); auto const opOriginLocation = [&]() -> langutil::SourceLocation { if (m_cfg.debugInfo) - if (auto const& dbg = m_cfg.debugInfo->operationDebugData(_opId)) + if (auto const& dbg = m_cfg.debugInfo->instDebugData(_instId)) return dbg->originLocation; return {}; }(); // generate code for the operation - std::visit(solidity::util::GenericVisitor{ - [&](SSACFG::BuiltinCall const& _builtin) { - m_assembly.setSourceLocation(opOriginLocation); - auto const& builtin = m_cfg.evmDialect.builtin(_builtin.builtin); - // build up the call with transient args to handle literal arguments as needed - std::vector transientArgs; - transientArgs.reserve(builtin.literalArguments.size()); - auto litIt = _builtin.literalArguments.begin(); - for (size_t i = 0; i < builtin.literalArguments.size(); ++i) - if (builtin.literalArgument(i).has_value()) - transientArgs.emplace_back(*litIt++); - else - transientArgs.emplace_back(Identifier{}); - FunctionCall const transient{{}, BuiltinName{{}, _builtin.builtin}, std::move(transientArgs)}; - builtin.generateCode(transient, m_assembly, m_builtinContext); - }, - [&](SSACFG::Call const& _call) { - auto const* returnLabel = solidity::util::valueOrNullptr(m_returnLabels, _opId); - // check that if we have a return label, the call can continue - yulAssert(!!returnLabel == _call.canContinue); - m_assembly.setSourceLocation(opOriginLocation); - SSACFG const* calleeCFG = m_controlFlow.functionGraph(_call.graphID); - yulAssert(calleeCFG); - m_assembly.appendJumpTo( - m_functionLabels.at(_call.graphID), - static_cast(calleeCFG->numReturns) - static_cast(calleeCFG->arguments.size()) - (_call.canContinue ? 1 : 0), - AbstractAssembly::JumpType::IntoFunction - ); - // if we have a return label, append it to assembly and pop the label from the stack - // it might also be one of the inputs that is popped here but then the label will be popped below with - // the other inputs - if (returnLabel) - { - m_assembly.appendLabel(*returnLabel); - m_stack.pop(); - } + m_assembly.setSourceLocation(opOriginLocation); + switch (_inst.opcode) + { + case InstOpcode::Call: + { + SSACFG::Call const& call = m_cfg.callPayload(_instId); + auto const* returnLabel = solidity::util::valueOrNullptr(m_returnLabels, _instId); + // check that if we have a return label, the call can continue + yulAssert(!!returnLabel == call.canContinue); + SSACFG const* calleeCFG = m_controlFlow.functionGraph(call.graphID); + yulAssert(calleeCFG); + m_assembly.appendJumpTo( + m_functionLabels.at(call.graphID), + static_cast(calleeCFG->numReturns) - static_cast(calleeCFG->arguments.size()) - (call.canContinue ? 1 : 0), + AbstractAssembly::JumpType::IntoFunction + ); + // if we have a return label, append it to assembly and pop the label from the stack + // it might also be one of the inputs that is popped here but then the label will be popped below with + // the other inputs + if (returnLabel) + { + m_assembly.appendLabel(*returnLabel); + m_stack.pop(); } - }, _operation.kind); + break; + } + case InstOpcode::BuiltinCall: + { + SSACFG::BuiltinCall const& builtinCall = m_cfg.builtinPayload(_instId); + auto const& builtin = m_cfg.evmDialect.builtin(builtinCall.builtin); + // build up the call with transient args to handle literal arguments as needed + std::vector transientArgs; + transientArgs.reserve(builtin.literalArguments.size()); + auto litIt = builtinCall.literalArguments.begin(); + for (size_t i = 0; i < builtin.literalArguments.size(); ++i) + if (builtin.literalArgument(i).has_value()) + transientArgs.emplace_back(*litIt++); + else + transientArgs.emplace_back(Identifier{}); + FunctionCall const transient{{}, BuiltinName{{}, builtinCall.builtin}, std::move(transientArgs)}; + builtin.generateCode(transient, m_assembly, m_builtinContext); + break; + } + default: + yulAssert(false); + } // simulate that the inputs are consumed - for (size_t i = 0; i < _operation.inputs.size(); ++i) + for (size_t i = 0; i < _inst.inputs.size(); ++i) m_stack.pop(); // simulate that the outputs are produced - for (auto value: _operation.outputs) - m_stack.push(StackSlot::makeValueID(value)); + for (auto value: SSACFG::outputsOf(_instId, _inst.numOutputs)) + m_stack.push(StackSlot::makeValueID(m_cfg, value)); // Assert that the operation produced its proclaimed output. - yulAssert(m_stack.size() == baseHeight + _operation.outputs.size()); + yulAssert(m_stack.size() == baseHeight + _inst.numOutputs); for (auto const& [stackEntry, output]: ranges::views::zip( - m_stack.data() | ranges::views::take_last(_operation.outputs.size()), - _operation.outputs + m_stack.data() | ranges::views::take_last(_inst.numOutputs), + SSACFG::outputsOf(_instId, _inst.numOutputs) )) yulAssert(stackEntry.isValueID() && stackEntry.valueID() == output); yulAssert( @@ -393,15 +401,25 @@ void CodeTransform::operator()(SSACFG::BlockId const& _blockId, SSACFG::BasicBlo { yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); auto const& block = m_cfg.block(_blockId); - yulAssert(!block.operations.empty(), "Terminated block must have at least one operation."); - std::visit(solidity::util::GenericVisitor{ - [&](SSACFG::BuiltinCall const& _builtin) { - yulAssert(m_cfg.evmDialect.builtin(_builtin.builtin).controlFlowSideEffects.terminatesOrReverts(), "Last operation of Terminated block must terminate or revert."); - }, - [](SSACFG::Call const& _call) { - yulAssert(!_call.canContinue, "Last operation of Terminated block must be a non-continuable call."); + // Find the last BuiltinCall/Call Inst in the block. + InstId lastOpInstId{}; + for (InstId const instId: block.instructions | ranges::views::reverse) + if (m_cfg.inst(instId).isOperation()) + { + lastOpInstId = instId; + break; } - }, m_cfg.operation(block.operations.back()).kind); + yulAssert(lastOpInstId.hasValue(), "Terminated block must have at least one operation."); + if (m_cfg.inst(lastOpInstId).opcode == InstOpcode::BuiltinCall) + yulAssert( + m_cfg.evmDialect.builtin(m_cfg.builtinPayload(lastOpInstId).builtin).controlFlowSideEffects.terminatesOrReverts(), + "Last operation of Terminated block must terminate or revert." + ); + else + yulAssert( + !m_cfg.callPayload(lastOpInstId).canContinue, + "Last operation of Terminated block must be a non-continuable call." + ); // To be sure just emit another INVALID - should be removed by optimizer. m_assembly.appendInstruction(evmasm::Instruction::INVALID); } @@ -409,7 +427,7 @@ void CodeTransform::operator()(SSACFG::BlockId const& _blockId, SSACFG::BasicBlo void CodeTransform::prepareBlockExitStack(StackData const& _target, PhiInverse const& _phiInverse) { // pull back target to live in current variable space - auto const pulledBackTarget = stackPreImage(_target, _phiInverse); + auto const pulledBackTarget = stackPreImage(m_cfg, _target, _phiInverse); // shuffle to target { auto const shuffleResult = StackShuffler::shuffle(m_stack, pulledBackTarget); diff --git a/libyul/backends/evm/ssa/CodeTransform.h b/libyul/backends/evm/ssa/CodeTransform.h index ad2a60575..6e5ab808d 100644 --- a/libyul/backends/evm/ssa/CodeTransform.h +++ b/libyul/backends/evm/ssa/CodeTransform.h @@ -52,8 +52,8 @@ struct AssemblyCallbacks case StackSlot::Kind::ValueID: { auto const id = _slot.valueID(); - yulAssert(id.isLiteral(), fmt::format("Tried bringing up v{}", id.value())); - assembly->appendConstant(cfg->literalInfo(id).value); + yulAssert(cfg->inst(id.instId()).isLiteral(), fmt::format("Tried bringing up non-const {}", id)); + assembly->appendConstant(cfg->literalPayload(id.instId())); return; } case StackSlot::Kind::Junk: @@ -66,9 +66,9 @@ struct AssemblyCallbacks } case StackSlot::Kind::FunctionCallReturnLabel: { - auto const opId = callSites->operationId(_slot.functionCallReturnLabel()); - yulAssert(returnLabels->count(opId), "FunctionCallReturnLabel not pre-registered before shuffle."); - assembly->appendLabelReference(returnLabels->at(opId)); + auto const instId = callSites->instId(_slot.functionCallReturnLabel()); + yulAssert(returnLabels->count(instId), "FunctionCallReturnLabel not pre-registered before shuffle."); + assembly->appendLabelReference(returnLabels->at(instId)); return; } case StackSlot::Kind::FunctionReturnLabel: @@ -86,7 +86,7 @@ struct AssemblyCallbacks SSACFG const* cfg{}; AbstractAssembly* assembly{}; CallSites const* callSites{}; - std::map const* returnLabels{}; + std::map const* returnLabels{}; }; static_assert(StackManipulationCallbackConcept); @@ -118,7 +118,7 @@ class CodeTransform ControlFlowGraphs::FunctionGraphID _graphID); void operator()(SSACFG::BlockId _blockId); - void operator()(SSACFG::InstId _opId, StackData const& _operationInputLayout); + void operator()(InstId _instId, StackData const& _operationInputLayout); void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::MainExit const& _mainExit); void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::ConditionalJump const& _conditionalJump); void operator()(SSACFG::BlockId const& _currentBlock, SSACFG::BasicBlock::Jump const& _jump); @@ -141,7 +141,7 @@ class CodeTransform AssemblyCallbacks m_assemblyCallbacks; StackData m_stackData; Stack m_stack; - std::map m_returnLabels; + std::map m_returnLabels; }; } diff --git a/libyul/backends/evm/ssa/InstructionStore.h b/libyul/backends/evm/ssa/InstructionStore.h index 64fb0feea..1b4d82a1f 100644 --- a/libyul/backends/evm/ssa/InstructionStore.h +++ b/libyul/backends/evm/ssa/InstructionStore.h @@ -18,7 +18,7 @@ /** * Owns the instruction table of an SSACFG: hands out InstIds, stores opcode * payloads, and provides lookups. Has no knowledge of basic blocks or debug - * information; SSACFG composes those on top. + * information; SSACFG composes those concerns on top. */ #pragma once @@ -31,10 +31,12 @@ #include +#include +#include + +#include #include #include -#include -#include #include namespace solidity::yul::ssa @@ -43,6 +45,9 @@ namespace solidity::yul::ssa class InstructionStore { public: + /// Sentinel value for `Inst::payloadIndex` when the opcode has no side-table payload. + static constexpr std::uint32_t NoPayload = std::numeric_limits::max(); + struct BuiltinCall { BuiltinHandle builtin; @@ -54,26 +59,25 @@ class InstructionStore FunctionGraphID graphID; bool canContinue; }; - struct Operation + struct Inst { - std::vector outputs{}; - std::variant kind; + InstOpcode opcode; + ValueId::OutputSize numOutputs; + std::uint32_t payloadIndex = NoPayload; BlockId block{}; std::vector inputs{}; + + constexpr bool isPhi() const noexcept { return opcode == InstOpcode::Phi; } + constexpr bool isUpsilon() const noexcept { return opcode == InstOpcode::Upsilon; } + constexpr bool isLiteral() const noexcept { return opcode == InstOpcode::Const; } + constexpr bool isUnreachable() const noexcept { return opcode == InstOpcode::Unreachable; } + constexpr bool isFunctionArg() const noexcept { return opcode == InstOpcode::FunctionArg; } + /// Operation = a Call or BuiltinCall. + constexpr bool isOperation() const noexcept + { + return opcode == InstOpcode::Call || opcode == InstOpcode::BuiltinCall; + } }; - struct LiteralValue - { - u256 value; - }; - struct VariableValue - { - BlockId definingBlock; - }; - struct PhiValue - { - BlockId block; - }; - struct UnreachableValue {}; InstructionStore() = default; InstructionStore(InstructionStore const&) = delete; @@ -82,95 +86,148 @@ class InstructionStore InstructionStore& operator=(InstructionStore&&) = default; ~InstructionStore() = default; - Operation& operation(InstId const _id) { return m_operations.at(_id.value); } - Operation const& operation(InstId const _id) const { return m_operations.at(_id.value); } + Inst& inst(InstId _id) { return m_insts.at(_id.value); } + Inst const& inst(InstId _id) const { return m_insts.at(_id.value); } + std::size_t numInsts() const { return m_insts.size(); } + std::vector const& instructions() const { return m_insts; } + + static auto outputsOf(InstId const _id, ValueId::OutputSize const _numOutputs) + { + return + ranges::views::iota(ValueId::OutputSize{0}, _numOutputs) | + ranges::views::transform([_id](ValueId::OutputSize const _pos) { return ValueId{_id, _pos}; }); + } - LiteralValue const& literalInfo(ValueId const& _valueId) const + auto instOutputs(InstId const _id) const { - yulAssert(_valueId.hasValue() && _valueId.isLiteral()); - return m_literals.at(_valueId.value()); + return outputsOf(_id, inst(_id).numOutputs); } - PhiValue const& phiInfo(ValueId const& _valueId) const + /// Returns the opcode category for a given ValueId. + InstOpcode kindOf(ValueId const _v) const { return inst(_v.instId()).opcode; } + + /// Returns the phi targeted by an Upsilon Inst. + ValueId upsilonPhi(InstId const _id) const { return payloadAs(_id, m_upsilonPhis); } + + /// Returns the u256 payload of a Const Inst. + u256 const& literalPayload(InstId const _id) const { return payloadAs(_id, m_literalPayloads); } + + BuiltinCall const& builtinPayload(InstId const _id) const { return payloadAs(_id, m_builtinPayloads); } + + Call const& callPayload(InstId const _id) const { return payloadAs(_id, m_callPayloads); } + + /// Allocates a new Phi Inst defined in `_definingBlock`. Returns the new InstId. + InstId appendPhi(BlockId const _definingBlock) { - yulAssert(_valueId.hasValue() && _valueId.isPhi()); - return m_phis.at(_valueId.value()); + return appendInst(Inst{InstOpcode::Phi, 1, NoPayload, _definingBlock, {}}); } - PhiValue& phiInfo(ValueId const& _valueId) + + /// Allocates a new FunctionArg Inst defined in `_entryBlock`. Returns the new InstId. + InstId appendFunctionArg(BlockId const _entryBlock) { - yulAssert(_valueId.hasValue() && _valueId.isPhi()); - return m_phis.at(_valueId.value()); + return appendInst(Inst{InstOpcode::FunctionArg, 1, NoPayload, _entryBlock, {}}); } - VariableValue const& variableInfo(ValueId const& _valueId) const + /// Allocates a new Unreachable Inst. Not pinned to any block (see class comment). + InstId appendUnreachable() { - yulAssert(_valueId.hasValue() && _valueId.isVariable()); - return m_variables.at(_valueId.value()); + return appendInst(Inst{InstOpcode::Unreachable, 1, NoPayload, BlockId{}, {}}); } - ValueId newPhi(BlockId const _definingBlock) + /// Allocates a new Const Inst with payload `_value`, pinned to `_entryBlock`. + /// Literals are deduplicated by value (see class comment). + InstId appendLiteral(BlockId const _entryBlock, u256 _value) { - yulAssert(_definingBlock.hasValue()); - m_phis.emplace_back(PhiValue{_definingBlock}); - auto const value = m_phis.size() - 1; - yulAssert(value < std::numeric_limits::max()); - return ValueId::makePhi(static_cast(value)); + yulAssert(_entryBlock.hasValue()); + if (auto const it = m_literalDedup.find(_value); it != m_literalDedup.end()) + return it->second; + auto const payloadIdx = allocPayload(m_literalPayloads, _value); + InstId const id = appendInst(Inst{InstOpcode::Const, 1, payloadIdx, _entryBlock, {}}); + m_literalDedup.emplace(std::move(_value), id); + return id; } - ValueId newVariable(BlockId const _definingBlock) + /// Allocates a new BuiltinCall Inst. Returns the new InstId. + InstId appendBuiltinCall( + BlockId const _block, + BuiltinCall _payload, + std::vector _inputs, + std::size_t const _numOutputs + ) { - yulAssert(_definingBlock.hasValue()); - m_variables.emplace_back(VariableValue{_definingBlock}); - auto const value = m_variables.size() - 1; - yulAssert(value < std::numeric_limits::max()); - return ValueId::makeVariable(static_cast(value)); + yulAssert(_block.hasValue()); + yulAssert(_numOutputs <= std::numeric_limits::max()); + return appendInst(Inst{ + InstOpcode::BuiltinCall, + static_cast(_numOutputs), + allocPayload(m_builtinPayloads, std::move(_payload)), + _block, + std::move(_inputs) + }); } - ValueId unreachableValue() + /// Allocates a new Call Inst. Returns the new InstId. + InstId appendCall( + BlockId const _block, + Call _payload, + std::vector _inputs, + std::size_t const _numOutputs + ) { - if (!m_unreachableValue) - m_unreachableValue = ValueId::makeUnreachable(); - return *m_unreachableValue; + yulAssert(_block.hasValue()); + yulAssert(_numOutputs <= std::numeric_limits::max()); + return appendInst(Inst{ + InstOpcode::Call, + static_cast(_numOutputs), + allocPayload(m_callPayloads, std::move(_payload)), + _block, + std::move(_inputs) + }); } - /// Look up or allocate a Literal ValueId for `_value`. Returns the ValueId and - /// whether a new entry was allocated (false if it was deduplicated). - std::pair newLiteral(u256 _value) + /// Allocates a new Upsilon Inst targeting `_phi`, feeding `_value` from `_block`. + InstId appendUpsilon(BlockId const _block, ValueId const _value, ValueId const _phi) { - if (auto const it = m_literalMapping.find(_value); it != m_literalMapping.end()) - { - yulAssert(it->second.hasValue() && m_literals[it->second.value()].value == _value); - return {it->second, false}; - } - m_literals.emplace_back(LiteralValue{std::move(_value)}); - auto const idx = m_literals.size() - 1; - yulAssert(idx < std::numeric_limits::max()); - auto const id = ValueId::makeLiteral(static_cast(idx)); - m_literalMapping.emplace(m_literals.back().value, id); - return {id, true}; + yulAssert(inst(_phi.instId()).isPhi()); + return appendInst(Inst{InstOpcode::Upsilon, 0, allocPayload(m_upsilonPhis, _phi), _block, {_value}}); } - InstId makeOperation(BlockId const _block, Operation _op) +private: + InstId appendInst(Inst _inst) { - yulAssert(_block.hasValue()); - for (ValueId const& output: _op.outputs) - { - yulAssert(output.isVariable()); - yulAssert(m_variables.at(output.value()).definingBlock == _block); - } - _op.block = _block; - InstId const id{static_cast(m_operations.size())}; - m_operations.emplace_back(std::move(_op)); + // max itself is reserved for the 'empty' inst + yulAssert(m_insts.size() < std::numeric_limits::max()); + InstId const id{static_cast(m_insts.size())}; + m_insts.emplace_back(std::move(_inst)); return id; } -private: - std::vector m_operations; - std::vector m_literals; - std::map m_literalMapping; - std::vector m_phis; - std::vector m_variables; - std::optional m_unreachableValue; + /// Asserts that the Inst at `_id` has opcode `Expected`, then returns its payload from `_store`. + template + typename Store::value_type const& payloadAs(InstId const _id, Store const& _store) const + { + auto const& i = inst(_id); + yulAssert(i.opcode == Expected); + return _store.at(i.payloadIndex); + } + + /// Pushes `_payload` into `_store` and returns the resulting payload index. Asserts + /// the index fits in payloadIndex's u32 representation (max is reserved for NoPayload). + template + std::uint32_t allocPayload(std::vector& _store, T _payload) + { + yulAssert(_store.size() < NoPayload); + auto const idx = static_cast(_store.size()); + _store.push_back(std::move(_payload)); + return idx; + } + + std::vector m_insts; + std::vector m_literalPayloads; + std::map m_literalDedup; + std::vector m_upsilonPhis; + std::vector m_builtinPayloads; + std::vector m_callPayloads; }; } diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp index 5ea1cf9f7..ce3ff1496 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -20,6 +20,7 @@ #include +#include #include #include @@ -27,17 +28,6 @@ using namespace solidity::yul::ssa; -namespace -{ -constexpr auto excludingLiteralsFilter() -{ - return [](SSACFG::ValueId const& _valueId) -> bool - { - return !_valueId.isLiteral(); - }; -} -} - LivenessAnalysis::LivenessData LivenessAnalysis::blockExitValues(SSACFG::BlockId const& _blockId) const { LivenessData result; @@ -45,8 +35,7 @@ LivenessAnalysis::LivenessData LivenessAnalysis::blockExitValues(SSACFG::BlockId [](SSACFG::BasicBlock::MainExit const&) {}, [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { - for (auto const& valueId: _functionReturn.returnValues | ranges::views::filter(excludingLiteralsFilter())) - result.insert(valueId); + result.insertAll(_functionReturn.returnValues | ranges::views::filter(excludingLiteralsFilter())); }, [](SSACFG::BasicBlock::Jump const&) {}, [&](SSACFG::BasicBlock::ConditionalJump const& _conditionalJump) @@ -93,12 +82,12 @@ void LivenessAnalysis::runDagDfs() // live <- PhiUses(B) LivenessData live{}; - for (auto const& upsilon: block.upsilons) - { - yulAssert(!upsilon.value.isUnreachable()); - if (!upsilon.value.isLiteral()) - live.insert(upsilon.value); - } + m_cfg.forEachUpsilon(block, [&](InstId, SSACFG::Inst const& inst) { + SSACFG::ValueId const v = inst.inputs.at(0); + yulAssert(!m_cfg.inst(v.instId()).isUnreachable()); + if (!m_cfg.inst(v.instId()).isLiteral()) + live.insert(v); + }); // for each S \in succs(B) s.t. (B, S) not a back edge: live <- live \cup (LiveIn(S) - PhiDefs(S)) block.forEachExit( @@ -107,18 +96,18 @@ void LivenessAnalysis::runDagDfs() { // LiveIn(S) - PhiDefs(S) auto liveInWithoutPhiDefs = m_liveIns[_successor.value]; - for (auto const& phiId: m_cfg.block(_successor).phis) - liveInWithoutPhiDefs.erase(phiId); + m_cfg.forEachPhi(m_cfg.block(_successor), [&](InstId const succInstId, SSACFG::Inst const&) { + liveInWithoutPhiDefs.erase(ValueId{succInstId}); + }); live.maxUnion(liveInWithoutPhiDefs); } }); if (std::holds_alternative(block.exit)) - for (auto const& returnValue: std::get(block.exit).returnValues | ranges::views::filter(excludingLiteralsFilter())) - live.insert(returnValue); + live.insertAll(std::get(block.exit).returnValues | ranges::views::filter(excludingLiteralsFilter())); // clean out unreachables - live.eraseIf([&](auto const& _entry) { return _entry.first.isUnreachable(); }); + live.eraseIf([&](auto const& _entry) { return m_cfg.inst(_entry.first.instId()).isUnreachable(); }); // LiveOut(B) <- live m_liveOuts[blockId.value] = live; @@ -128,19 +117,22 @@ void LivenessAnalysis::runDagDfs() // add value ids to the live set that are used in exit blocks live += blockExitValues(blockId); - for (auto const opId: block.operations | ranges::views::reverse) + for (InstId const instId: block.instructions | ranges::views::reverse) { - auto const& op = m_cfg.operation(opId); + auto const& inst = m_cfg.inst(instId); + if (!inst.isOperation()) + continue; // remove variables defined at p from live - live.eraseAll(op.outputs | ranges::views::filter(excludingLiteralsFilter()) | ranges::to); + live.eraseAll(SSACFG::outputsOf(instId, inst.numOutputs) | ranges::views::filter(excludingLiteralsFilter())); // add uses at p to live - live.insertAll(op.inputs | ranges::views::filter(excludingLiteralsFilter()) | ranges::to); + live.insertAll(inst.inputs | ranges::views::filter(excludingLiteralsFilter())); } } // livein(b) <- live \cup PhiDefs(B) - for (auto const& phi: block.phis) - live.insert(phi); + m_cfg.forEachPhi(block, [&](InstId const instId, SSACFG::Inst const&) { + live.insert(ValueId{instId}); + }); m_liveIns[blockId.value] = live; } } @@ -154,8 +146,9 @@ void LivenessAnalysis::runLoopTreeDfs(SSACFG::BlockId::ValueType const _loopHead auto const& block = m_cfg.block(SSACFG::BlockId{_loopHeader}); // LiveLoop <- LiveIn(B_N) - PhiDefs(B_N) auto liveLoop = m_liveIns[_loopHeader]; - for (auto const& phi: block.phis) - liveLoop.erase(phi); + m_cfg.forEachPhi(block, [&](InstId const instId, SSACFG::Inst const&) { + liveLoop.erase(ValueId{instId}); + }); // must be live out of header if live in of children m_liveOuts[_loopHeader].maxUnion(liveLoop); // for each blockId \in children(loopHeader) @@ -175,22 +168,26 @@ void LivenessAnalysis::fillOperationsLiveOut() { for (SSACFG::BlockId blockId{0}; blockId.value < m_cfg.numBlocks(); ++blockId.value) { - auto const& operations = m_cfg.block(blockId).operations; + auto const& block = m_cfg.block(blockId); + auto const opCount = static_cast(ranges::count_if( + block.instructions, + [&](InstId const _id) { return m_cfg.inst(_id).isOperation(); } + )); auto& liveOuts = m_operationLiveOuts[blockId.value]; - liveOuts.resize(operations.size()); - if (!operations.empty()) + liveOuts.resize(opCount); + if (opCount > 0) { auto live = m_liveOuts[blockId.value]; live += blockExitValues(blockId); auto rit = liveOuts.rbegin(); - for (auto const opId: operations | ranges::views::reverse) + for (InstId const instId: block.instructions | ranges::views::reverse) { - auto const& op = m_cfg.operation(opId); + auto const& inst = m_cfg.inst(instId); + if (!inst.isOperation()) + continue; *rit = live; - for (auto const& output: op.outputs | ranges::views::filter(excludingLiteralsFilter())) - live.erase(output); - for (auto const& input: op.inputs | ranges::views::filter(excludingLiteralsFilter())) - live.insert(input); + live.eraseAll(SSACFG::outputsOf(instId, inst.numOutputs) | ranges::views::filter(excludingLiteralsFilter())); + live.insertAll(inst.inputs | ranges::views::filter(excludingLiteralsFilter())); ++rit; } } diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.h b/libyul/backends/evm/ssa/LivenessAnalysis.h index 066659ba1..05f4cde0a 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.h +++ b/libyul/backends/evm/ssa/LivenessAnalysis.h @@ -53,6 +53,11 @@ class LivenessAnalysis void fillOperationsLiveOut(); LivenessData blockExitValues(SSACFG::BlockId const& _blockId) const; + auto excludingLiteralsFilter() const + { + return [this](SSACFG::ValueId _v) { return !m_cfg.inst(_v.instId()).isLiteral(); }; + } + SSACFG const& m_cfg; traversal::ForwardTopologicalSort m_topologicalSort; SSACFGLoopNestingForest m_loopNestingForest; diff --git a/libyul/backends/evm/ssa/PhiInverse.cpp b/libyul/backends/evm/ssa/PhiInverse.cpp index b8be70e64..f686a1bfb 100644 --- a/libyul/backends/evm/ssa/PhiInverse.cpp +++ b/libyul/backends/evm/ssa/PhiInverse.cpp @@ -22,9 +22,13 @@ using namespace solidity::yul::ssa; PhiInverse::PhiInverse(SSACFG const& _cfg, SSACFG::BlockId const& _from, SSACFG::BlockId const& _to) { - for (auto const& [phiValue, phi]: _cfg.block(_from).upsilons) - if (_cfg.phiInfo(phi).block == _to) - m_phiToPreImage[phi] = phiValue; + _cfg.forEachUpsilon(_cfg.block(_from), [&](InstId const instId, SSACFG::Inst const& inst) { + if ( + ValueId const phi = _cfg.upsilonPhi(instId); + _cfg.inst(phi.instId()).block == _to + ) + m_phiToPreImage[phi] = inst.inputs.at(0); + }); } bool PhiInverse::noOp() const diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 8c54d89d2..a38dac770 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -19,15 +19,15 @@ #include #include -#include #include +#include #include #include -#include #include +#include #include #include @@ -41,16 +41,17 @@ namespace /// Build a human-readable Phi/Upsilon annotation for a phi value. /// Shows which upsilons feed it, listed per predecessor block. -std::string formatPhi(SSACFG const& _cfg, SSACFG::ValueId _phiId) +std::string formatPhi(SSACFG const& _cfg, ValueId _phiId) { // Collect all upsilons targeting _phiId from the whole CFG. std::vector formattedUpsilons; - for (SSACFG::BlockId::ValueType bv = 0; bv < _cfg.numBlocks(); ++bv) - for (auto const& u: _cfg.block(SSACFG::BlockId{bv}).upsilons) - if (u.phi == _phiId) + for (BlockId::ValueType bv = 0; bv < _cfg.numBlocks(); ++bv) + _cfg.forEachUpsilon(_cfg.block(BlockId{bv}), [&](InstId const instId, SSACFG::Inst const& inst) { + if (_cfg.upsilonPhi(instId) == _phiId) formattedUpsilons.push_back( - fmt::format("Block {} => {}", bv, u.value.str(_cfg)) + fmt::format("Block {} => {}", bv, inst.inputs.at(0).str(_cfg)) ); + }); if (!formattedUpsilons.empty()) return fmt::format("φ(\\l\\\n\t{}\\l\\\n)", fmt::join(formattedUpsilons, ",\\l\\\n\t")); return "φ()"; @@ -69,10 +70,10 @@ class SSACFGDotExporter: public io::DotExporterBase } protected: - void writeBlockLabel(std::ostream& _out, SSACFG::BlockId _blockId) override + void writeBlockLabel(std::ostream& _out, BlockId _blockId) override { auto const& block = m_cfg.block(_blockId); - auto const valueToString = [&](SSACFG::ValueId const& valueId) { return valueId.str(m_cfg); }; + auto const valueToString = [&](ValueId const& valueId) { return valueId.str(m_cfg); }; if (m_liveness) { @@ -84,57 +85,57 @@ class SSACFGDotExporter: public io::DotExporterBase ); _out << fmt::format( "LiveIn: {}\\l\\\n", - fmt::join(m_liveness->liveIn(_blockId) | ranges::views::transform([&](auto const& liveIn) { return valueToString(SSACFG::ValueId{liveIn.first}) + fmt::format("[{}]", liveIn.second); }), ", ") + fmt::join(m_liveness->liveIn(_blockId) | ranges::views::transform([&](auto const& liveIn) { return valueToString(liveIn.first) + fmt::format("[{}]", liveIn.second); }), ", ") ); _out << fmt::format( "LiveOut: {}\\l\\n", - fmt::join(m_liveness->liveOut(_blockId) | ranges::views::transform([&](auto const& liveOut) { return valueToString(SSACFG::ValueId{liveOut.first}) + fmt::format("[{}]", liveOut.second); }), ", ") + fmt::join(m_liveness->liveOut(_blockId) | ranges::views::transform([&](auto const& liveOut) { return valueToString(liveOut.first) + fmt::format("[{}]", liveOut.second); }), ", ") ); auto const usedVariables = m_liveness->used(_blockId); _out << fmt::format( "Used: {}\\l\\n", - fmt::join(usedVariables | ranges::views::transform([&](auto const& used) { return valueToString(SSACFG::ValueId{used.first}) + fmt::format("[{}]", used.second); }), ", ") + fmt::join(usedVariables | ranges::views::transform([&](auto const& used) { return valueToString(used.first) + fmt::format("[{}]", used.second); }), ", ") ); } else _out << fmt::format("\\\nBlock {}\\n", _blockId.value); - for (auto const& phi: block.phis) - _out << fmt::format("phi{} := {}\\l\\\n", phi.value(), formatPhi(m_cfg, phi)); - for (auto const opId: block.operations) - { - auto const& operation = m_cfg.operation(opId); - std::string const label = std::visit(GenericVisitor{ - [&](SSACFG::Call const& _call) -> std::string { - if (m_controlFlow) - return m_controlFlow->functionGraph(_call.graphID)->name; - return fmt::format("func{}", _call.graphID); - }, - [&](SSACFG::BuiltinCall const& _call) -> std::string { - return m_cfg.evmDialect.builtin(_call.builtin).name; - } - }, operation.kind); - if (!operation.outputs.empty()) + // Phis first, then BuiltinCall / Call in program order. Upsilons are rendered + // under successor phis (via formatPhi) and skipped here. + m_cfg.forEachPhi(block, [&](InstId const instId, SSACFG::Inst const&) { + ValueId const phi{instId}; + _out << fmt::format("phi{} := {}\\l\\\n", instId.value, formatPhi(m_cfg, phi)); + }); + m_cfg.forEachOperation(block, [&](InstId const instId, SSACFG::Inst const& inst) { + std::string label; + if (inst.opcode == InstOpcode::Call) + { + auto const graphID = m_cfg.callPayload(instId).graphID; + label = m_controlFlow ? m_controlFlow->functionGraph(graphID)->name : fmt::format("func{}", graphID); + } + else + label = m_cfg.evmDialect.builtin(m_cfg.builtinPayload(instId).builtin).name; + if (inst.numOutputs > 0) _out << fmt::format( "{} := ", - fmt::join(operation.outputs | ranges::views::transform(valueToString), ", ") + fmt::join(SSACFG::outputsOf(instId, inst.numOutputs) | ranges::views::transform(valueToString), ", ") ); _out << fmt::format( "{}({})\\l\\\n", escapeLabel(label), - fmt::join(operation.inputs | ranges::views::transform(valueToString), ", ") + fmt::join(inst.inputs | ranges::views::transform(valueToString), ", ") ); - } + }); } - std::vector> blockNodeAttributes(SSACFG::BlockId _blockId) override + std::vector> blockNodeAttributes(BlockId _blockId) override { if (m_junkAdmittingBlocks && m_junkAdmittingBlocks->allowsAdditionOfJunk(_blockId)) return {{"fillcolor", "\"#FF746C\""}, {"style", "filled"}}; return {}; } - EdgeStyle edgeStyle(SSACFG::BlockId _source, SSACFG::BlockId _target) override + EdgeStyle edgeStyle(BlockId _source, BlockId _target) override { if (m_liveness && m_liveness->topologicalSort().backEdge(_source, _target)) return EdgeStyle::Dashed; diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 51da0db72..b38737cf6 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -63,21 +64,11 @@ class SSACFG ~SSACFG() = default; using BlockId = ssa::BlockId; - using InstId = ssa::InstId; using ValueId = ssa::ValueId; using BuiltinCall = InstructionStore::BuiltinCall; using Call = InstructionStore::Call; - using Operation = InstructionStore::Operation; - - /// Upsilon records a phi pre-image at a block exit. - /// Upsilon(value, phi) means: the value flowing into `phi` from this block is `value`. - /// Lives in the predecessor block; the corresponding Phi lives in the successor. - struct Upsilon - { - ValueId value; ///< pre-image value for the phi - ValueId phi; ///< target phi - }; + using Inst = InstructionStore::Inst; struct BasicBlock { @@ -98,11 +89,7 @@ class SSACFG }; struct Terminated {}; std::vector entries; - std::vector phis; - std::vector operations; - /// Upsilon assignments placed at the block exit (before the terminator). - /// They record the phi pre-images for successor blocks. - std::vector upsilons; + std::vector instructions; std::variant exit = MainExit{}; template Callable> @@ -128,7 +115,7 @@ class SSACFG // max itself is reserved for the 'empty' block yulAssert(m_blocks.size() < std::numeric_limits::max()); BlockId const blockId{static_cast(m_blocks.size())}; - m_blocks.emplace_back(BasicBlock{{}, {}, {}, {}, BasicBlock::Terminated{}}); + m_blocks.emplace_back(BasicBlock{{}, {}, BasicBlock::Terminated{}}); if (debugInfo) debugInfo->setBlockDebugData(blockId, std::move(_debugData)); return blockId; @@ -140,48 +127,113 @@ class SSACFG InstructionStore& instructionStore() { return m_instructions; } InstructionStore const& instructionStore() const { return m_instructions; } - Operation& operation(InstId _id) { return m_instructions.operation(_id); } - Operation const& operation(InstId _id) const { return m_instructions.operation(_id); } + Inst& inst(InstId _id) { return m_instructions.inst(_id); } + Inst const& inst(InstId _id) const { return m_instructions.inst(_id); } + size_t numInsts() const { return m_instructions.numInsts(); } + std::vector const& instructions() const { return m_instructions.instructions(); } + + static auto outputsOf(InstId const _id, ValueId::OutputSize const _numOutputs) + { + return InstructionStore::outputsOf(_id, _numOutputs); + } + + auto instOutputs(InstId const _id) const + { + return m_instructions.instOutputs(_id); + } + + /// Returns the opcode category for a given ValueId. + InstOpcode kindOf(ValueId const _v) const { return m_instructions.kindOf(_v); } + + /// Returns the phi targeted by an Upsilon Inst. + ValueId upsilonPhi(InstId const _id) const { return m_instructions.upsilonPhi(_id); } + + /// Returns the u256 payload of a Const Inst. + u256 const& literalPayload(InstId const _id) const { return m_instructions.literalPayload(_id); } + + BuiltinCall const& builtinPayload(InstId const _id) const { return m_instructions.builtinPayload(_id); } - InstructionStore::LiteralValue const& literalInfo(ValueId const& _valueId) const { return m_instructions.literalInfo(_valueId); } - InstructionStore::PhiValue const& phiInfo(ValueId const& _valueId) const { return m_instructions.phiInfo(_valueId); } - InstructionStore::PhiValue& phiInfo(ValueId const& _valueId) { return m_instructions.phiInfo(_valueId); } - InstructionStore::VariableValue const& variableInfo(ValueId const& _valueId) const { return m_instructions.variableInfo(_valueId); } + Call const& callPayload(InstId const _id) const { return m_instructions.callPayload(_id); } + /// Creates a Phi Inst in the given block and returns its output ValueId. ValueId newPhi(BlockId const _definingBlock) { - auto const id = m_instructions.newPhi(_definingBlock); + InstId const id = scheduleInBlock(m_instructions.appendPhi(_definingBlock), _definingBlock); + ValueId const v{id}; if (debugInfo) - debugInfo->setValueDebugData(id, debugInfo->blockDebugData(_definingBlock)); - return id; + debugInfo->setValueDebugData(v, debugInfo->blockDebugData(_definingBlock)); + return v; } - ValueId newVariable(BlockId const _definingBlock) + ValueId newFunctionArgument() { - auto const id = m_instructions.newVariable(_definingBlock); + InstId const id = scheduleInBlock(m_instructions.appendFunctionArg(entry), entry); + ValueId const v{id}; if (debugInfo) - debugInfo->setValueDebugData(id, debugInfo->blockDebugData(_definingBlock)); - return id; + debugInfo->setValueDebugData(v, debugInfo->blockDebugData(entry)); + return v; } - ValueId unreachableValue() { return m_instructions.unreachableValue(); } + ValueId unreachableValue() + { + return ValueId{m_instructions.appendUnreachable()}; + } + /// Literal ValueIds are deduplicated. Const Insts are pinned to the entry block. ValueId newLiteral(langutil::DebugData::ConstPtr _debugData, u256 _value) { - auto const [id, allocated] = m_instructions.newLiteral(std::move(_value)); - if (debugInfo && allocated) - debugInfo->setValueDebugData(id, std::move(_debugData)); + auto const beforeCount = m_instructions.numInsts(); + InstId const id = m_instructions.appendLiteral(entry, std::move(_value)); + ValueId const v{id}; + // Newly allocated (not deduplicated): schedule in entry and attach debug data. + if (m_instructions.numInsts() > beforeCount) + { + scheduleInBlock(id, entry); + if (debugInfo) + debugInfo->setValueDebugData(v, std::move(_debugData)); + } + return v; + } + + InstId makeBuiltinCall( + BlockId const _block, + BuiltinCall _payload, + std::vector _inputs, + std::size_t const _numOutputs, + langutil::DebugData::ConstPtr _debugData = {} + ) + { + InstId const id = scheduleInBlock( + m_instructions.appendBuiltinCall(_block, std::move(_payload), std::move(_inputs), _numOutputs), + _block + ); + if (debugInfo && _debugData) + debugInfo->setInstDebugData(id, std::move(_debugData)); return id; } - InstId makeOperation(BlockId _block, Operation _op, langutil::DebugData::ConstPtr _debugData = {}) + InstId makeCall( + BlockId const _block, + Call _payload, + std::vector _inputs, + std::size_t const _numOutputs, + langutil::DebugData::ConstPtr _debugData = {} + ) { - auto const id = m_instructions.makeOperation(_block, std::move(_op)); - if (debugInfo) - debugInfo->setOperationDebugData(id, std::move(_debugData)); + InstId const id = scheduleInBlock( + m_instructions.appendCall(_block, std::move(_payload), std::move(_inputs), _numOutputs), + _block + ); + if (debugInfo && _debugData) + debugInfo->setInstDebugData(id, std::move(_debugData)); return id; } + InstId emitUpsilon(BlockId const _block, ValueId _value, ValueId const _phi) + { + return scheduleInBlock(m_instructions.appendUpsilon(_block, _value, _phi), _block); + } + std::string toDot( bool _includeDiGraphDefinition=true, std::optional _functionIndex=std::nullopt, @@ -190,6 +242,12 @@ class SSACFG ) const; private: + InstId scheduleInBlock(InstId const _id, BlockId const _block) + { + m_blocks.at(_block.value).instructions.push_back(_id); + return _id; + } + std::vector m_blocks; InstructionStore m_instructions; public: @@ -203,6 +261,57 @@ class SSACFG std::size_t numReturns = 0; bool isMainGraph() const { return name.empty(); } + + /// Iterates `_block.instructions`, invoking `_fn(instId, inst)` for every Phi. + template + void forEachPhi(BasicBlock const& _block, Callable&& _fn) + { + forEachInstWhere(*this, _block, &Inst::isPhi, std::forward(_fn)); + } + template + void forEachPhi(BasicBlock const& _block, Callable&& _fn) const + { + forEachInstWhere(*this, _block, &Inst::isPhi, std::forward(_fn)); + } + + /// Iterates `_block.instructions`, invoking `_fn(instId, inst)` for every Upsilon. + template + void forEachUpsilon(BasicBlock const& _block, Callable&& _fn) + { + forEachInstWhere(*this, _block, &Inst::isUpsilon, std::forward(_fn)); + } + template + void forEachUpsilon(BasicBlock const& _block, Callable&& _fn) const + { + forEachInstWhere(*this, _block, &Inst::isUpsilon, std::forward(_fn)); + } + + /// Iterates `_block.instructions`, invoking `_fn(instId, inst)` for every operation + /// (Call or BuiltinCall). + template + void forEachOperation(BasicBlock const& _block, Callable&& _fn) + { + forEachInstWhere(*this, _block, &Inst::isOperation, std::forward(_fn)); + } + template + void forEachOperation(BasicBlock const& _block, Callable&& _fn) const + { + forEachInstWhere(*this, _block, &Inst::isOperation, std::forward(_fn)); + } + +private: + /// Shared implementation for the public `forEach*` overloads; works for both + /// `SSACFG&` and `SSACFG const&` since `_self.inst(id)` propagates const-ness. + template + static void forEachInstWhere(Self& _self, BasicBlock const& _block, Pred _pred, Callable&& _fn) + { + for (InstId const id: _block.instructions) + { + auto& inst = _self.inst(id); + if (std::invoke(_pred, inst)) + _fn(id, inst); + } + } }; } diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 0ed9c7219..3498a3c97 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -112,7 +112,7 @@ void SSACFGBuilder::buildFunctionGraph( auto argumentBindings = _functionDefinition->parameters | ranges::views::transform([&](auto const& _param) { auto const& var = std::get(virtualFunctionScope->identifiers.at(_param.name)); // Note: cannot use std::make_tuple since it unwraps reference wrappers. - return std::tuple{std::cref(var), cfg.newVariable(cfg.entry)}; + return std::tuple{std::cref(var), cfg.newFunctionArgument()}; }) | ranges::to; auto returnVars = _functionDefinition->returnVariables | ranges::views::transform([&](auto const& _param) { return std::cref(std::get(virtualFunctionScope->identifiers.at(_param.name))); @@ -147,8 +147,8 @@ void SSACFGBuilder::operator()(ExpressionStatement const& _expressionStatement) { auto const* functionCall = std::get_if(&_expressionStatement.expression); yulAssert(functionCall); - auto results = visitFunctionCall(*functionCall); - yulAssert(results.empty()); + InstId const id = visitFunctionCall(*functionCall); + yulAssert(m_graph.inst(id).numOutputs == 0); } void SSACFGBuilder::operator()(Assignment const& _assignment) @@ -234,14 +234,14 @@ void SSACFGBuilder::operator()(Switch const& _switch) yulAssert(equalityBuiltinHandle); auto makeValueCompare = [&](Case const& _case) { - auto outputValue = m_graph.newVariable(m_currentBlock); - auto opId = m_graph.makeOperation(m_currentBlock, SSACFG::Operation{ - .outputs = {outputValue}, - .kind = SSACFG::BuiltinCall{*equalityBuiltinHandle, {}}, - .inputs = {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression}, - }, debugDataOf(_case)); - currentBlock().operations.emplace_back(opId); - return outputValue; + InstId const id = m_graph.makeBuiltinCall( + m_currentBlock, + SSACFG::BuiltinCall{*equalityBuiltinHandle, {}}, + {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression}, + 1, + debugDataOf(_case) + ); + return ValueId{id}; }; auto afterSwitch = m_graph.makeBlock(currentBlockDebugData()); @@ -403,9 +403,9 @@ void SSACFGBuilder::operator()(Block const& _block) SSACFG::ValueId SSACFGBuilder::operator()(FunctionCall const& _call) { - auto results = visitFunctionCall(_call); - yulAssert(results.size() == 1); - return results.front(); + InstId const id = visitFunctionCall(_call); + yulAssert(m_graph.inst(id).numOutputs == 1); + return SSACFG::ValueId{id}; } SSACFG::ValueId SSACFGBuilder::operator()(Identifier const& _identifier) @@ -421,27 +421,27 @@ SSACFG::ValueId SSACFGBuilder::operator()(Literal const& _literal) void SSACFGBuilder::assign(std::vector> _variables, Expression const* _expression) { - auto rhs = [&]() -> std::vector { - if (auto const* functionCall = std::get_if(_expression)) - return visitFunctionCall(*functionCall); - if (_expression) - return {std::visit(*this, *_expression)}; - return {_variables.size(), zero()}; - }(); + if (auto const* functionCall = std::get_if(_expression)) + { + InstId const id = visitFunctionCall(*functionCall); + yulAssert(m_graph.inst(id).numOutputs == _variables.size()); + for (auto const& [var, value]: ranges::zip_view(_variables, m_graph.instOutputs(id))) + writeVariable(var, m_currentBlock, value); + return; + } + auto const rhs = _expression ? + std::vector{std::visit(*this, *_expression)} : + std::vector(_variables.size(), zero()); yulAssert(rhs.size() == _variables.size()); - for (auto const& [var, value]: ranges::zip_view(_variables, rhs)) - { writeVariable(var, m_currentBlock, value); - } - } -std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const& _call) +InstId SSACFGBuilder::visitFunctionCall(FunctionCall const& _call) { bool canContinue = true; - SSACFG::Operation operation = std::visit(solidity::util::GenericVisitor{ - [&](BuiltinName const& _builtinName) + InstId const id = std::visit(solidity::util::GenericVisitor{ + [&](BuiltinName const& _builtinName) -> InstId { auto const& builtin = m_dialect.builtin(_builtinName.handle); yulAssert(_call.arguments.size() == builtin.numParameters); @@ -452,16 +452,20 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const yulAssert(std::holds_alternative(arg)); literalArguments.emplace_back(std::get(arg)); } - SSACFG::Operation result{.kind = SSACFG::BuiltinCall{_builtinName.handle, std::move(literalArguments)}}; + std::vector inputs; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) if (!builtin.literalArgument(idx).has_value()) - result.inputs.emplace_back(std::visit(*this, arg)); - for (size_t i = 0; i < builtin.numReturns; ++i) - result.outputs.emplace_back(m_graph.newVariable(m_currentBlock)); + inputs.emplace_back(std::visit(*this, arg)); canContinue = builtin.controlFlowSideEffects.canContinue; - return result; + return m_graph.makeBuiltinCall( + m_currentBlock, + SSACFG::BuiltinCall{_builtinName.handle, std::move(literalArguments)}, + std::move(inputs), + builtin.numReturns, + debugDataOf(_call) + ); }, - [&](Identifier const& _identifier) + [&](Identifier const& _identifier) -> InstId { YulName const& functionName = _identifier.name; Scope::Function const& function = lookupFunction(functionName); @@ -470,23 +474,25 @@ std::vector SSACFGBuilder::visitFunctionCall(FunctionCall const canContinue = m_sideEffects.functionSideEffects().at(definition).canContinue; auto const calleeIt = m_functionScopeToID.find(&function); yulAssert(calleeIt != m_functionScopeToID.end(), "Called function has no registered graph id."); - SSACFG::Operation result{.kind = SSACFG::Call{calleeIt->second, canContinue}}; + std::vector inputs; for (auto const& arg: _call.arguments | ranges::views::reverse) - result.inputs.emplace_back(std::visit(*this, arg)); - for (size_t i = 0; i < function.numReturns; ++i) - result.outputs.emplace_back(m_graph.newVariable(m_currentBlock)); - return result; + inputs.emplace_back(std::visit(*this, arg)); + return m_graph.makeCall( + m_currentBlock, + SSACFG::Call{calleeIt->second, canContinue}, + std::move(inputs), + function.numReturns, + debugDataOf(_call) + ); } }, _call.functionName); - auto results = operation.outputs; - currentBlock().operations.emplace_back(m_graph.makeOperation(m_currentBlock, std::move(operation), debugDataOf(_call))); if (!canContinue) { currentBlock().exit = SSACFG::BasicBlock::Terminated{}; m_currentBlock = m_graph.makeBlock(currentBlockDebugData()); sealBlock(m_currentBlock); } - return results; + return id; } SSACFG::ValueId SSACFGBuilder::zero() @@ -512,7 +518,6 @@ SSACFG::ValueId SSACFGBuilder::readVariableRecursive(Scope::Variable const& _var { // incomplete block: create a phi and defer upsilon emission until the block is sealed val = m_graph.newPhi(_block); - block.phis.push_back(val); info.incompletePhis.emplace_back(val, _variable); } else if (block.entries.size() == 1) @@ -522,7 +527,6 @@ SSACFG::ValueId SSACFGBuilder::readVariableRecursive(Scope::Variable const& _var { // Break potential cycles with an argument-less phi; emit upsilons for all predecessors. val = m_graph.newPhi(_block); - block.phis.push_back(val); writeVariable(_variable, _block, val); addPhiOperands(_variable, val); } @@ -532,7 +536,8 @@ SSACFG::ValueId SSACFGBuilder::readVariableRecursive(Scope::Variable const& _var void SSACFGBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi) { - for (auto const& pred: m_graph.block(m_graph.phiInfo(_phi).block).entries) + SSACFG::BlockId const phiBlock = m_graph.inst(_phi.instId()).block; + for (auto const& pred: m_graph.block(phiBlock).entries) { auto const val = readVariable(_variable, pred); emitUpsilon(pred, val, _phi); @@ -541,8 +546,8 @@ void SSACFGBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::Val void SSACFGBuilder::emitUpsilon(SSACFG::BlockId _block, SSACFG::ValueId _value, SSACFG::ValueId _phi) { - yulAssert(_phi.isPhi()); - m_graph.block(_block).upsilons.emplace_back(SSACFG::Upsilon{_value, _phi}); + yulAssert(m_graph.inst(_phi.instId()).isPhi()); + m_graph.emitUpsilon(_block, _value, _phi); } void SSACFGBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value) diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index aed9e2c61..2cbf07da4 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -90,7 +90,7 @@ class SSACFGBuilder private: void assign(std::vector> _variables, Expression const* _expression); - std::vector visitFunctionCall(FunctionCall const& _call); + InstId visitFunctionCall(FunctionCall const& _call); void registerFunctionDefinition(FunctionDefinition const& _functionDefinition); void buildFunctionGraph(Scope::Function const* _function, FunctionDefinition const* _functionDefinition); diff --git a/libyul/backends/evm/ssa/SSACFGDebugInfo.h b/libyul/backends/evm/ssa/SSACFGDebugInfo.h index 42be2b373..9d8ed0686 100644 --- a/libyul/backends/evm/ssa/SSACFGDebugInfo.h +++ b/libyul/backends/evm/ssa/SSACFGDebugInfo.h @@ -39,10 +39,7 @@ struct SSACFGDebugInfo m_blockDebugData[_id.value] = std::move(_data); } - langutil::DebugData::ConstPtr const& blockDebugData(BlockId _id) const - { - return getOrEmpty(m_blockDebugData, _id.value); - } + langutil::DebugData::ConstPtr blockDebugData(BlockId _id) const { return lookup(m_blockDebugData, _id.value); } void setExitDebugData(BlockId _id, langutil::DebugData::ConstPtr _data) { @@ -51,22 +48,16 @@ struct SSACFGDebugInfo m_exitDebugData[_id.value] = std::move(_data); } - langutil::DebugData::ConstPtr const& exitDebugData(BlockId _id) const - { - return getOrEmpty(m_exitDebugData, _id.value); - } + langutil::DebugData::ConstPtr exitDebugData(BlockId _id) const { return lookup(m_exitDebugData, _id.value); } - void setOperationDebugData(InstId _id, langutil::DebugData::ConstPtr _data) + void setInstDebugData(InstId _id, langutil::DebugData::ConstPtr _data) { yulAssert(_id.hasValue()); - ensureSize(m_operationDebugData, _id.value); - m_operationDebugData[_id.value] = std::move(_data); + ensureSize(m_instDebugData, _id.value); + m_instDebugData[_id.value] = std::move(_data); } - langutil::DebugData::ConstPtr const& operationDebugData(InstId _id) const - { - return getOrEmpty(m_operationDebugData, _id.value); - } + langutil::DebugData::ConstPtr instDebugData(InstId _id) const { return lookup(m_instDebugData, _id.value); } void setValueDebugData(ValueId _id, langutil::DebugData::ConstPtr _data) { @@ -74,12 +65,11 @@ struct SSACFGDebugInfo m_valueDebugData[_id] = std::move(_data); } - langutil::DebugData::ConstPtr const& valueDebugData(ValueId _id) const + langutil::DebugData::ConstPtr valueDebugData(ValueId _id) const { - static langutil::DebugData::ConstPtr const empty{nullptr}; auto const it = m_valueDebugData.find(_id); if (it == m_valueDebugData.end()) - return empty; + return nullptr; return it->second; } @@ -93,20 +83,14 @@ struct SSACFGDebugInfo _vec.resize(_index + 1); } - static langutil::DebugData::ConstPtr const& getOrEmpty( - std::vector const& _debugData, - std::size_t const _index - ) + static langutil::DebugData::ConstPtr lookup(std::vector const& _vec, std::size_t const _index) { - static langutil::DebugData::ConstPtr const empty{nullptr}; - if (_index >= _debugData.size()) - return empty; - return _debugData[_index]; + return _index < _vec.size() ? _vec[_index] : nullptr; } std::vector m_blockDebugData; std::vector m_exitDebugData; - std::vector m_operationDebugData; + std::vector m_instDebugData; std::map m_valueDebugData; }; diff --git a/libyul/backends/evm/ssa/SSACFGTypes.cpp b/libyul/backends/evm/ssa/SSACFGTypes.cpp index 466afe5b9..1a4ee04e8 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.cpp +++ b/libyul/backends/evm/ssa/SSACFGTypes.cpp @@ -20,22 +20,28 @@ #include -#include -#include - -using namespace solidity::util; using namespace solidity::yul::ssa; std::string ValueId::str(SSACFG const& _cfg) const { if (!hasValue()) return "INVALID"; - switch (kind()) + switch (_cfg.kindOf(*this)) { - case Kind::Literal: return toCompactHexWithPrefix(_cfg.literalInfo(*this).value); - case Kind::Variable: return fmt::format("v{}", value()); - case Kind::Phi: return fmt::format("phi{}", value()); - case Kind::Unreachable: return "[unreachable]"; + case InstOpcode::Const: + return toCompactHexWithPrefix(_cfg.literalPayload(instId())); + case InstOpcode::BuiltinCall: + case InstOpcode::Call: + case InstOpcode::FunctionArg: + if (m_outputPos == 0) + return fmt::format("v{}", m_instId.value); + return fmt::format("v{}.{}", m_instId.value, m_outputPos); + case InstOpcode::Phi: + return fmt::format("phi{}", m_instId.value); + case InstOpcode::Unreachable: + return "[unreachable]"; + case InstOpcode::Upsilon: + yulAssert(false, "Upsilon Insts have no output ValueId"); } - unreachable(); + util::unreachable(); } diff --git a/libyul/backends/evm/ssa/SSACFGTypes.h b/libyul/backends/evm/ssa/SSACFGTypes.h index b3adb8f5f..50bd26fc6 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.h +++ b/libyul/backends/evm/ssa/SSACFGTypes.h @@ -16,13 +16,11 @@ */ // SPDX-License-Identifier: GPL-3.0 /** - * Lightweight ID types used throughout the SSA CFG. + * Types used throughout the SSA CFG. */ #pragma once -#include - #include #include @@ -52,47 +50,42 @@ struct InstId auto operator<=>(InstId const&) const = default; }; +enum class InstOpcode : std::uint8_t +{ + Const, // literal u256 + Phi, // no inputs, retrieves value by mapping + Upsilon, // records phi pre-image at a phi predecessor block + BuiltinCall, // dialect builtin + Call, // user-defined function call + Unreachable, // dead code + FunctionArg, // function param without inputs and a single output valueid +}; + +/// Identifies a specific produced value of an Inst. class ValueId { public: - enum class Kind: std::uint8_t - { - Literal, - Variable, - Phi, - Unreachable - }; - using ValueType = std::uint32_t; + // this value refers to the n-th return value of an operation + using OutputSize = std::uint8_t; constexpr ValueId() = default; - constexpr ValueId(ValueType const _value, Kind const _kind): m_value(_value), m_kind(_kind) {} - constexpr ValueId(ValueId const&) = default; - constexpr ValueId(ValueId&&) = default; - constexpr ValueId& operator=(ValueId const&) = default; - constexpr ValueId& operator=(ValueId&&) = default; - - static ValueId constexpr makeLiteral(ValueType const& _value) { return ValueId{_value, Kind::Literal}; } - static ValueId constexpr makeVariable(ValueType const& _value) { return ValueId{_value, Kind::Variable}; } - static ValueId constexpr makePhi(ValueType const& _value) { return ValueId{_value, Kind::Phi}; } - static ValueId constexpr makeUnreachable() { return ValueId{0u, Kind::Unreachable}; } - - bool constexpr isLiteral() const noexcept { return m_kind == Kind::Literal; } - bool constexpr isVariable() const noexcept { return m_kind == Kind::Variable; } - bool constexpr isPhi() const noexcept { return m_kind == Kind::Phi; } - bool constexpr isUnreachable() const noexcept { return m_kind == Kind::Unreachable; } - - bool constexpr hasValue() const { return m_value != std::numeric_limits::max(); } - ValueType constexpr value() const noexcept { return m_value; } - Kind constexpr kind() const noexcept { return m_kind; } - - /// Returns a human-readable string representation. Requires the full SSACFG for literal values. + constexpr ValueId(InstId const _instId, OutputSize const _outputPos = 0): + m_instId(_instId), + m_outputPos(_outputPos) + {} + + bool constexpr hasValue() const noexcept { return m_instId.hasValue(); } + OutputSize constexpr outputPos() const noexcept { return m_outputPos; } + InstId constexpr instId() const noexcept { return m_instId; } + + /// Returns a human-readable string representation std::string str(SSACFG const& _cfg) const; auto operator<=>(ValueId const&) const = default; private: - ValueType m_value{std::numeric_limits::max()}; - Kind m_kind{Kind::Unreachable}; + InstId m_instId{}; + OutputSize m_outputPos{0}; }; } @@ -117,11 +110,11 @@ struct fmt::formatter static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } template - auto format(solidity::yul::ssa::InstId const& _opId, FormatContext& _ctx) const -> decltype(_ctx.out()) + auto format(solidity::yul::ssa::InstId const& _instId, FormatContext& _ctx) const -> decltype(_ctx.out()) { - if (!_opId.hasValue()) + if (!_instId.hasValue()) return fmt::format_to(_ctx.out(), "empty"); - return fmt::format_to(_ctx.out(), "op{}", _opId.value); + return fmt::format_to(_ctx.out(), "i{}", _instId.value); } }; @@ -135,17 +128,8 @@ struct fmt::formatter { if (!_valueId.hasValue()) return fmt::format_to(_ctx.out(), "empty"); - switch (_valueId.kind()) - { - case solidity::yul::ssa::ValueId::Kind::Literal: - return fmt::format_to(_ctx.out(), "lit{}", _valueId.value()); - case solidity::yul::ssa::ValueId::Kind::Variable: - return fmt::format_to(_ctx.out(), "v{}", _valueId.value()); - case solidity::yul::ssa::ValueId::Kind::Phi: - return fmt::format_to(_ctx.out(), "phi{}", _valueId.value()); - case solidity::yul::ssa::ValueId::Kind::Unreachable: - return fmt::format_to(_ctx.out(), "unreachable"); - } - solidity::util::unreachable(); + if (_valueId.outputPos() == 0) + return fmt::format_to(_ctx.out(), "v{}", _valueId.instId().value); + return fmt::format_to(_ctx.out(), "v{}.{}", _valueId.instId().value, _valueId.outputPos()); } }; diff --git a/libyul/backends/evm/ssa/Stack.cpp b/libyul/backends/evm/ssa/Stack.cpp index 3edf4e862..14ed28222 100644 --- a/libyul/backends/evm/ssa/Stack.cpp +++ b/libyul/backends/evm/ssa/Stack.cpp @@ -31,6 +31,10 @@ std::string slotToString(StackSlot const& _slot) switch (_slot.kind()) { case StackSlot::Kind::ValueID: + if (_slot.isLiteralValueID()) + return fmt::format("lit{}", _slot.valueID().instId().value); + if (_slot.isPhiValueID()) + return fmt::format("phi{}", _slot.valueID().instId().value); return fmt::format("{}", _slot.valueID()); case StackSlot::Kind::Junk: return "JUNK"; diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index e415bfab6..1e5b6caf9 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -39,25 +39,25 @@ class CallSites public: using CallSiteID = std::uint32_t; - std::optional callSiteID(InstId _op) const + std::optional callSiteID(InstId _instId) const { - if (auto const it = ranges::find(m_data, _op); it != m_data.end()) + if (auto const it = ranges::find(m_data, _instId); it != m_data.end()) return static_cast(std::distance(m_data.begin(), it)); return std::nullopt; } - InstId operationId(CallSiteID _callSite) const + InstId instId(CallSiteID _callSite) const { yulAssert(_callSite < m_data.size()); return m_data[_callSite]; } - CallSiteID addCallSite(InstId _op) + CallSiteID addCallSite(InstId _instId) { - if (auto const id = callSiteID(_op)) + if (auto const id = callSiteID(_instId)) return *id; - yulAssert(_op.hasValue()); - m_data.emplace_back(_op); + yulAssert(_instId.hasValue()); + m_data.emplace_back(_instId); return static_cast(m_data.size() - 1); } private: @@ -90,7 +90,8 @@ class StackSlot constexpr StackSlot& operator=(StackSlot&&) = default; constexpr bool isValueID() const noexcept { return kind() == Kind::ValueID; } - constexpr bool isLiteralValueID() const noexcept { return m_valueIdKind == SSACFG::ValueId::Kind::Literal; } + constexpr bool isLiteralValueID() const noexcept { return m_valueIdOpcode == InstOpcode::Const; } + constexpr bool isPhiValueID() const noexcept { return m_valueIdOpcode == InstOpcode::Phi; } constexpr bool isFunctionReturnLabel() const noexcept { return kind() == Kind::FunctionReturnLabel; } constexpr bool isFunctionCallReturnLabel() const noexcept { return kind() == Kind::FunctionCallReturnLabel; } constexpr bool isJunk() const noexcept { return kind() == Kind::Junk; } @@ -98,25 +99,40 @@ class StackSlot ControlFlowGraphs::FunctionGraphID functionReturnLabel() const { yulAssert(isFunctionReturnLabel()); return m_payload; } CallSites::CallSiteID functionCallReturnLabel() const { yulAssert(isFunctionCallReturnLabel()); return m_payload; } - SSACFG::ValueId valueID() const { yulAssert(isValueID()); return {m_payload, m_valueIdKind}; } + SSACFG::ValueId valueID() const + { + yulAssert(isValueID()); + return {InstId{m_payload}, m_valueIdOutputPos}; + } static constexpr StackSlot makeJunk() { return {0, Kind::Junk}; } - static constexpr StackSlot makeValueID(SSACFG::ValueId const& _valueID) { return {_valueID.value(), Kind::ValueID, _valueID.kind()}; } + static StackSlot makeValueID(SSACFG const& _cfg, SSACFG::ValueId _valueID) + { + return {_valueID.instId().value, Kind::ValueID, _valueID.outputPos(), _cfg.kindOf(_valueID)}; + } + static StackSlot makeValueID(InstructionStore const& _store, SSACFG::ValueId _valueID) + { + return {_valueID.instId().value, Kind::ValueID, _valueID.outputPos(), _store.kindOf(_valueID)}; + } static constexpr StackSlot makeFunctionReturnLabel(ControlFlowGraphs::FunctionGraphID const _graphID) { return {_graphID, Kind::FunctionReturnLabel}; } static constexpr StackSlot makeFunctionCallReturnLabel(CallSites::CallSiteID const _callSiteID) { return {_callSiteID, Kind::FunctionCallReturnLabel}; } auto operator<=>(StackSlot const&) const = default; private: - constexpr StackSlot(std::uint32_t const _payload, Kind const _kind, SSACFG::ValueId::Kind const _valueIdKind = SSACFG::ValueId::Kind::Unreachable): + constexpr StackSlot(std::uint32_t const _payload, Kind const _kind, ValueId::OutputSize const _valueIdOutputPos = 0, InstOpcode const _valueIdOpcode = InstOpcode::Unreachable): m_payload(_payload), m_kind(_kind), - m_valueIdKind(_valueIdKind) + m_valueIdOutputPos(_valueIdOutputPos), + m_valueIdOpcode(_valueIdOpcode) {} /// interpretation depends on kind std::uint32_t m_payload; Kind m_kind; - SSACFG::ValueId::Kind m_valueIdKind; + /// for Kind::ValueID: output position of the referenced value within its Inst + ValueId::OutputSize m_valueIdOutputPos; + /// for Kind::ValueID: cached Opcode of the defining Inst + InstOpcode m_valueIdOpcode; }; static_assert(sizeof(StackSlot) == 8, "Want cache efficiency, benchmark this if you go beyond 8 bytes"); static_assert(std::is_trivially_copyable_v, "Should be able to use memcpy semantics"); diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 454fc62f1..9b9d82432 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -37,30 +38,32 @@ using namespace solidity::yul::ssa; namespace { -void handlePhiFunctions(StackData& _stackData, PhiInverse const& _phiInverse, LivenessAnalysis::LivenessData const& _liveness) +void handlePhiFunctions(StackData& _stackData, PhiInverse const& _phiInverse, LivenessAnalysis::LivenessData const& _liveness, SSACFG const& _cfg) { // add any phi function values here that are not already contained in the stack for (auto const& [phi, preImage]: _phiInverse.data()) { auto reversedStackData = _stackData | ranges::views::reverse; - auto it = ranges::find(reversedStackData, StackSlot::makeValueID(preImage)); + auto const phiSlot = StackSlot::makeValueID(_cfg, phi); + auto const preImageSlot = StackSlot::makeValueID(_cfg, preImage); + auto it = ranges::find(reversedStackData, preImageSlot); if (_liveness.contains(preImage)) { // Both the phi function and the preimage are part of the live-in set. // If the preimage occurs more than once on the stack, one occurrence is // symbolically replaced by the phi function; otherwise, we push the phi value. - if (ranges::count(_stackData, StackSlot::makeValueID(preImage)) > 1) - *it = StackSlot::makeValueID(phi); + if (ranges::count(_stackData, preImageSlot) > 1) + *it = phiSlot; else - _stackData.emplace_back(StackSlot::makeValueID(phi)); + _stackData.emplace_back(phiSlot); } else { // replace all occurrences of the preimage with the phi value - ranges::replace(_stackData, StackSlot::makeValueID(preImage), StackSlot::makeValueID(phi)); + ranges::replace(_stackData, preImageSlot, phiSlot); // if it's not contained, push it (could be derived from a literal) if (it == ranges::end(reversedStackData)) - _stackData.emplace_back(StackSlot::makeValueID(phi)); + _stackData.emplace_back(phiSlot); } } } @@ -150,7 +153,7 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) if (m_hasFunctionReturnLabel) blockLayout.stackIn.push_back(Slot::makeFunctionReturnLabel(m_graphID)); for (auto const& valueID: m_cfg.arguments | ranges::views::reverse) - blockLayout.stackIn.push_back(Slot::makeValueID(valueID)); + blockLayout.stackIn.push_back(Slot::makeValueID(m_cfg, valueID)); } m_resultLayout[_blockId] = blockLayout; return; @@ -167,7 +170,7 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) // pass through yulAssert(stackInProposals.size() == 1); blockLayout.stackIn = stackInProposals[0].second; - handlePhiFunctions(blockLayout.stackIn, PhiInverse(m_cfg, stackInProposals[0].first, _blockId), liveIn); + handlePhiFunctions(blockLayout.stackIn, PhiInverse(m_cfg, stackInProposals[0].first, _blockId), liveIn, m_cfg); StackType stack(blockLayout.stackIn, {}); declareJunk(stack, liveIn); } @@ -178,7 +181,7 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) for (std::size_t i = 0; i < stackInProposals.size(); ++i) { proposals[i] = stackInProposals[i].second; - handlePhiFunctions(proposals[i], PhiInverse(m_cfg, stackInProposals[i].first, _blockId), liveIn); + handlePhiFunctions(proposals[i], PhiInverse(m_cfg, stackInProposals[i].first, _blockId), liveIn, m_cfg); { StackType stack(proposals[i], {}); declareJunk(stack, liveIn); @@ -226,24 +229,24 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) bool const junkCanBeAdded = m_junkAdmittingBlocksFinder->allowsAdditionOfJunk(_blockId); auto const& operationsLiveOut = m_liveness.operationsLiveOut(_blockId); - blockLayout.operationIn.reserve(block.operations.size()); - for (std::size_t operationIndex = 0; operationIndex < block.operations.size(); ++operationIndex) - { - SSACFG::Operation const& operation = m_cfg.operation(block.operations[operationIndex]); - LivenessAnalysis::LivenessData opLiveOut = operationsLiveOut[operationIndex]; - auto opLiveOutWithoutOutputs = opLiveOut; - for (auto const& output: operation.outputs) - opLiveOutWithoutOutputs.erase(output); + blockLayout.operationIn.reserve(operationsLiveOut.size()); + std::size_t operationIndex = 0; + m_cfg.forEachOperation(block, [&](InstId const instId, SSACFG::Inst const& inst) { + auto opLiveOutWithoutOutputs = operationsLiveOut[operationIndex]; + opLiveOutWithoutOutputs.eraseAll(SSACFG::outputsOf(instId, inst.numOutputs)); std::vector requiredStackTop; - if (auto const* call = std::get_if(&operation.kind)) - if (call->canContinue) + if (inst.opcode == InstOpcode::Call) + { + auto const& callPayload = m_cfg.callPayload(instId); + if (callPayload.canContinue) { - auto const callSiteID = m_callSites.callSiteID(block.operations[operationIndex]); + auto const callSiteID = m_callSites.callSiteID(instId); yulAssert(callSiteID.has_value()); requiredStackTop.emplace_back(Slot::makeFunctionCallReturnLabel(*callSiteID)); } - requiredStackTop += operation.inputs | ranges::views::transform(Slot::makeValueID); + } + requiredStackTop += inst.inputs | ranges::views::transform([this](ValueId const& _id) { return StackSlot::makeValueID(m_cfg, _id); }); for (StackType::Depth depth{0}; depth < stack.size(); ++depth.value) if ( @@ -253,7 +256,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) ) stack.declareJunk(depth); - StackSlotLiveness const opLiveOutSlots = toStackSlotLiveness(opLiveOutWithoutOutputs); + StackSlotLiveness const opLiveOutSlots = toStackSlotLiveness(m_cfg, opLiveOutWithoutOutputs); std::size_t const targetSize = findOptimalTargetSize( stack.data(), requiredStackTop, @@ -274,9 +277,11 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) blockLayout.operationIn.push_back(currentStackData); for (std::size_t i = 0; i < requiredStackTop.size(); ++i) stack.pop(); - for (auto const& val: operation.outputs) - stack.push(Slot::makeValueID(val)); - } + for (auto const& val: SSACFG::outputsOf(instId, inst.numOutputs)) + stack.push(Slot::makeValueID(m_cfg, val)); + ++operationIndex; + }); + yulAssert(operationIndex == operationsLiveOut.size()); std::visit( solidity::util::GenericVisitor{ @@ -290,8 +295,8 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) stack.top().isValueID() && stack.top().valueID() == _cJump.condition; // and the condition is already on top if (!conditionSlotAlreadyFinal) { - auto const condition = Slot::makeValueID(_cJump.condition); - StackSlotLiveness const blockLiveOutSlots = toStackSlotLiveness(blockLiveOut); + auto const condition = Slot::makeValueID(m_cfg, _cJump.condition); + StackSlotLiveness const blockLiveOutSlots = toStackSlotLiveness(m_cfg, blockLiveOut); auto const targetSize = findOptimalTargetSize( stack.data(), {condition}, @@ -306,7 +311,9 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) } yulAssert(!stack.empty() && stack.top().isValueID() && stack.top().valueID() == _cJump.condition); - yulAssert(m_cfg.block(_cJump.nonZero).phis.empty()); + yulAssert(ranges::none_of(m_cfg.block(_cJump.nonZero).instructions, [this](InstId const _id) { + return m_cfg.inst(_id).isPhi(); + })); // exitIn = pre-JUMPI state (condition on top) for CodeTransform blockLayout.exitIn = currentStackData; @@ -322,7 +329,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { yulAssert(m_hasFunctionReturnLabel, "When there is a proper function return, we need to have a label for it"); // in case there are return values, let's bring the function return label to the top - StackData returnStack = _functionReturn.returnValues | ranges::views::transform(StackSlot::makeValueID) | ranges::to; + StackData returnStack = _functionReturn.returnValues | ranges::views::transform([this](ValueId const _id) { return StackSlot::makeValueID(m_cfg, _id); }) | ranges::to; returnStack.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); auto const shuffleResult = StackShuffler::shuffle(stack, returnStack); yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); diff --git a/libyul/backends/evm/ssa/StackSlotLiveness.h b/libyul/backends/evm/ssa/StackSlotLiveness.h index 57da7115b..3d233cfef 100644 --- a/libyul/backends/evm/ssa/StackSlotLiveness.h +++ b/libyul/backends/evm/ssa/StackSlotLiveness.h @@ -19,6 +19,7 @@ #pragma once #include +#include #include #include @@ -28,12 +29,12 @@ namespace solidity::yul::ssa /// Liveness counts keyed on StackSlot using StackSlotLiveness = util::UseCountSet; -inline StackSlotLiveness toStackSlotLiveness(LivenessAnalysis::LivenessData const& _liveness) +inline StackSlotLiveness toStackSlotLiveness(SSACFG const& _cfg, LivenessAnalysis::LivenessData const& _liveness) { StackSlotLiveness::Entries entries; entries.reserve(_liveness.size()); for (auto const& [valueId, count]: _liveness) - entries.emplace_back(StackSlot::makeValueID(valueId), count); + entries.emplace_back(StackSlot::makeValueID(_cfg, valueId), count); return StackSlotLiveness{std::move(entries)}; } diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index 71c972ce6..79568931d 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -46,7 +46,7 @@ void GasAccumulatingCallbacks::push(StackSlot const& _slot) { if (_slot.isLiteralValueID()) { - auto const size = numberEncodingSize(cfg.literalInfo(_slot.valueID()).value); + auto const size = numberEncodingSize(cfg.literalPayload(_slot.valueID().instId())); opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(size), cfg.evmDialect.evmVersion()); } else if (_slot.isJunk()) @@ -68,12 +68,15 @@ void GasAccumulatingCallbacks::pop() opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP, cfg.evmDialect.evmVersion()); } -StackData solidity::yul::ssa::stackPreImage(StackData _stack, PhiInverse const& _phiInverse) +StackData solidity::yul::ssa::stackPreImage(SSACFG const& _cfg, StackData _stack, PhiInverse const& _phiInverse) { if (!_phiInverse.noOp()) for (auto& slot: _stack) if (slot.isValueID()) - slot = StackSlot::makeValueID(_phiInverse(slot.valueID())); + { + auto const preImage = _phiInverse(slot.valueID()); + slot = StackSlot::makeValueID(_cfg, preImage); + } return _stack; } @@ -203,10 +206,14 @@ CallSites solidity::yul::ssa::gatherCallSites(SSACFG const& _cfg) } }); - for (auto const opId: block.operations) - if (auto const* call = std::get_if(&_cfg.operation(opId).kind)) - if (call->canContinue) - result.addCallSite(opId); + for (InstId const instId: block.instructions) + { + auto const& inst = _cfg.inst(instId); + if (inst.opcode != InstOpcode::Call) + continue; + if (_cfg.callPayload(instId).canContinue) + result.addCallSite(instId); + } } return result; } diff --git a/libyul/backends/evm/ssa/StackUtils.h b/libyul/backends/evm/ssa/StackUtils.h index 79eeb215a..b4d5c66a6 100644 --- a/libyul/backends/evm/ssa/StackUtils.h +++ b/libyul/backends/evm/ssa/StackUtils.h @@ -61,7 +61,7 @@ struct GasAccumulatingCallbacks }; /// Transform stack data by replacing all its phi variables with their respective preimages. -StackData stackPreImage(StackData _stack, PhiInverse const& _phiInverse); +StackData stackPreImage(SSACFG const& _cfg, StackData _stack, PhiInverse const& _phiInverse); std::size_t findOptimalTargetSize( StackData const& _stackData, diff --git a/libyul/backends/evm/ssa/io/DotExporterBase.cpp b/libyul/backends/evm/ssa/io/DotExporterBase.cpp index bd4d8be23..0c5eff764 100644 --- a/libyul/backends/evm/ssa/io/DotExporterBase.cpp +++ b/libyul/backends/evm/ssa/io/DotExporterBase.cpp @@ -177,7 +177,7 @@ std::string DotExporterBase::exportFunction(SSACFG const& _function, bool _wrapI if (_wrapInDigraph) out << fmt::format("digraph SSACFG {{\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\", rankdir={}]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n", m_rankDir); - static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", arg.value()); }; + static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", arg.instId().value); }; auto const entryHandle = fmt::format("FunctionEntry_{}_{}", escapeId(_function.name), _function.entry.value); if (_function.numReturns > 0) out << fmt::format("{} [label=\"function {}:\n [{} returns] := {}({})\"];\n", diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index a1433bc42..1b50a8a3d 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -35,37 +36,41 @@ using namespace solidity::yul::ssa::io::json; namespace { -Json toJson(SSACFG const& _cfg, std::vector const& _values) +Json toJson(SSACFG const& _cfg, ranges::input_range auto&& _values) requires std::convertible_to, SSACFG::ValueId> { Json ret = Json::array(); - for (auto const& value: _values) + for (SSACFG::ValueId const value: _values) ret.push_back(value.str(_cfg)); return ret; } -Json toJson(Json& _ret, SSACFG const& _cfg, SSACFG::Operation const& _operation, ControlFlowGraphs const& _controlFlow) +Json toJson(Json& _ret, SSACFG const& _cfg, InstId const _instId, ControlFlowGraphs const& _controlFlow) { + auto const& inst = _cfg.inst(_instId); Json opJson = Json::object(); - std::visit(solidity::util::GenericVisitor{ - [&](SSACFG::Call const& _call) { - _ret["type"] = "FunctionCall"; - opJson["op"] = _controlFlow.functionGraph(_call.graphID)->name; - }, - [&](SSACFG::BuiltinCall const& _call) { - _ret["type"] = "BuiltinCall"; - Json builtinArgsJson = Json::array(); - for (auto const& literal: _call.literalArguments) - builtinArgsJson.push_back(formatLiteral(literal)); - - if (!builtinArgsJson.empty()) - opJson["literalArgs"] = builtinArgsJson; - - opJson["op"] = _cfg.evmDialect.builtin(_call.builtin).name; - }, - }, _operation.kind); - - opJson["in"] = toJson(_cfg, _operation.inputs); - opJson["out"] = toJson(_cfg, _operation.outputs); + if (inst.opcode == InstOpcode::Call) + { + auto const& callPayload = _cfg.callPayload(_instId); + _ret["type"] = "FunctionCall"; + opJson["op"] = _controlFlow.functionGraph(callPayload.graphID)->name; + } + else + { + yulAssert(inst.opcode == InstOpcode::BuiltinCall); + auto const& builtinPayload = _cfg.builtinPayload(_instId); + _ret["type"] = "BuiltinCall"; + Json builtinArgsJson = Json::array(); + for (auto const& literal: builtinPayload.literalArguments) + builtinArgsJson.push_back(formatLiteral(literal)); + + if (!builtinArgsJson.empty()) + opJson["literalArgs"] = builtinArgsJson; + + opJson["op"] = _cfg.evmDialect.builtin(builtinPayload.builtin).name; + } + + opJson["in"] = toJson(_cfg, inst.inputs); + opJson["out"] = toJson(_cfg, SSACFG::outputsOf(_instId, inst.numOutputs)); return opJson; } @@ -90,31 +95,38 @@ Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const blockJson["liveness"] = livenessJson; } blockJson["instructions"] = Json::array(); - if (!block.phis.empty()) - { + bool const hasPhis = ranges::any_of(block.instructions, [&](InstId id) { + return _cfg.inst(id).isPhi(); + }); + if (hasPhis) blockJson["entries"] = block.entries | ranges::views::transform([](auto const& entry) { return "Block" + std::to_string(entry.value); }) | ranges::to(); - for (auto const& phi: block.phis) - { - // Reconstruct phi arguments from upsilon nodes in predecessor blocks. - std::vector phiArgs; - for (auto const& entryId: block.entries) - for (auto const& upsilon: _cfg.block(entryId).upsilons) - if (upsilon.phi == phi) - { - phiArgs.push_back(upsilon.value); - break; - } - Json phiJson = Json::object(); - phiJson["op"] = "PhiFunction"; - phiJson["in"] = toJson(_cfg, phiArgs); - phiJson["out"] = toJson(_cfg, std::vector{phi}); - blockJson["instructions"].push_back(phiJson); - } - } - for (auto const opId: block.operations) - blockJson["instructions"].push_back(toJson(blockJson, _cfg, _cfg.operation(opId), _controlFlow)); + _cfg.forEachPhi(block, [&](InstId const instId, SSACFG::Inst const&) { + SSACFG::ValueId const phi{instId, 0}; + // Reconstruct phi arguments from upsilon Insts in predecessor blocks. + std::vector phiArgs; + for (auto const& entryId: block.entries) + for (InstId const predInstId: _cfg.block(entryId).instructions) + { + auto const& predInst = _cfg.inst(predInstId); + if (!predInst.isUpsilon()) + continue; + if (_cfg.upsilonPhi(predInstId) == phi) + { + phiArgs.push_back(predInst.inputs.at(0)); + break; + } + } + Json phiJson = Json::object(); + phiJson["op"] = "PhiFunction"; + phiJson["in"] = toJson(_cfg, phiArgs); + phiJson["out"] = toJson(_cfg, std::vector{phi}); + blockJson["instructions"].push_back(phiJson); + }); + _cfg.forEachOperation(block, [&](InstId const instId, SSACFG::Inst const&) { + blockJson["instructions"].push_back(toJson(blockJson, _cfg, instId, _controlFlow)); + }); return blockJson; } @@ -164,7 +176,7 @@ Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness, Contr Json functionJson = Json::object(); functionJson["type"] = "Function"; functionJson["entry"] = "Block" + std::to_string(_cfg.entry.value); - static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", _arg.value()); }; + static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", _arg.instId().value); }; functionJson["arguments"] = _cfg.arguments | ranges::views::transform(argsTransform) | ranges::to; functionJson["numReturns"] = _cfg.numReturns; functionJson["blocks"] = exportBlock(_cfg, _cfg.entry, _liveness, _controlFlow); diff --git a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp index 3301aa135..bd0fa004d 100644 --- a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp +++ b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp @@ -73,19 +73,23 @@ struct TrivialPhiEliminator void cleanUnreachableUpsilons() { for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) - std::erase_if(cfg.block(blockId).upsilons, [](SSACFG::Upsilon const& u) { - return u.value.isUnreachable(); + { + auto& block = cfg.block(blockId); + std::erase_if(block.instructions, [this](InstId const _id) { + auto const& inst = cfg.inst(_id); + return inst.isUpsilon() && cfg.inst(inst.inputs.at(0).instId()).isUnreachable(); }); + } } void buildIndices() { for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) { - auto const& block = cfg.block(blockId); - for (auto const& u: block.upsilons) - { - auto const phiIdx = u.phi.value(); + cfg.forEachUpsilon(cfg.block(blockId), [&](InstId const instId, SSACFG::Inst const& inst) { + SSACFG::ValueId const phi = cfg.upsilonPhi(instId); + SSACFG::ValueId const value = inst.inputs.at(0); + auto const phiIdx = phi.instId().value; if (phiIdx >= upsilonValuesForPhi.size()) { upsilonValuesForPhi.resize(phiIdx + 1); @@ -93,16 +97,16 @@ struct TrivialPhiEliminator } if (phiIdx >= reversePhiUpsilonValues.size()) reversePhiUpsilonValues.resize(phiIdx + 1); - upsilonValuesForPhi[phiIdx].push_back(u.value); + upsilonValuesForPhi[phiIdx].push_back(value); phiTargetBlocks[phiIdx].push_back(blockId); - if (u.value.isPhi()) + if (cfg.inst(value.instId()).isPhi()) { - auto const valIdx = u.value.value(); + auto const valIdx = value.instId().value; if (valIdx >= reversePhiUpsilonValues.size()) reversePhiUpsilonValues.resize(valIdx + 1); - reversePhiUpsilonValues[valIdx].push_back(u.phi); + reversePhiUpsilonValues[valIdx].push_back(phi); } - } + }); } substitution.resize(std::max(upsilonValuesForPhi.size(), size_t{1})); } @@ -116,9 +120,9 @@ struct TrivialPhiEliminator auto const unreachable = cfg.unreachableValue(); for (auto& upsilonValues: upsilonValuesForPhi) for (auto& val: upsilonValues) - if (val.isPhi()) + if (cfg.inst(val.instId()).isPhi()) { - auto const idx = val.value(); + auto const idx = val.instId().value; bool const hasUpsilons = idx < upsilonValuesForPhi.size() && !upsilonValuesForPhi[idx].empty(); if (!hasUpsilons) val = unreachable; @@ -129,7 +133,11 @@ struct TrivialPhiEliminator { for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) { - auto const phis = cfg.block(blockId).phis; + // Snapshot the phi ValueIds because tryRemove mutates block.instructions. + std::vector phis; + cfg.forEachPhi(cfg.block(blockId), [&](InstId const instId, SSACFG::Inst const&) { + phis.push_back(ValueId{instId}); + }); for (auto const phi: phis) tryRemove(phi); } @@ -137,7 +145,7 @@ struct TrivialPhiEliminator void tryRemove(SSACFG::ValueId _phi) { - auto const phiIdx = _phi.value(); + auto const phiIdx = _phi.instId().value; // early exit if this phi was already processed if (phiIdx < substitution.size() && substitution[phiIdx].hasValue()) @@ -150,7 +158,7 @@ struct TrivialPhiEliminator for (auto const arg: upsilonValuesForPhi[phiIdx]) { auto const resolved = canonicalize(arg); - if (resolved == same || resolved == _phi || resolved.isUnreachable()) + if (resolved == same || resolved == _phi || cfg.inst(resolved.instId()).isUnreachable()) continue; if (same.hasValue()) return; // non-trivial @@ -162,7 +170,11 @@ struct TrivialPhiEliminator same = cfg.unreachableValue(); // remove the phi from its defining block - std::erase(cfg.block(cfg.phiInfo(_phi).block).phis, _phi); + { + auto& block = cfg.block(cfg.inst(_phi.instId()).block); + yulAssert(cfg.inst(_phi.instId()).isPhi()); + std::erase(block.instructions, _phi.instId()); + } // record the substitution if (phiIdx >= substitution.size()) @@ -176,19 +188,20 @@ struct TrivialPhiEliminator for (auto const targetPhi: reversePhiUpsilonValues[phiIdx]) { // update upsilonValuesForPhi[targetPhi]: _phi with same - auto& vals = upsilonValuesForPhi[targetPhi.value()]; + auto& vals = upsilonValuesForPhi[targetPhi.instId().value]; ranges::replace(vals, _phi, same); - if (targetPhi.value() < phiTargetBlocks.size()) - for (auto const blockId: phiTargetBlocks[targetPhi.value()]) - for (auto& u: cfg.block(blockId).upsilons) - if (u.phi == targetPhi && u.value == _phi) - u.value = same; + if (targetPhi.instId().value < phiTargetBlocks.size()) + for (auto const blockId: phiTargetBlocks[targetPhi.instId().value]) + cfg.forEachUpsilon(cfg.block(blockId), [&](InstId const instId, SSACFG::Inst& inst) { + if (cfg.upsilonPhi(instId) == targetPhi && inst.inputs.at(0) == _phi) + inst.inputs[0] = same; + }); // maintain reverse index - if (same.isPhi()) + if (cfg.inst(same.instId()).isPhi()) { - if (same.value() >= reversePhiUpsilonValues.size()) - reversePhiUpsilonValues.resize(same.value() + 1); - reversePhiUpsilonValues[same.value()].push_back(targetPhi); + if (same.instId().value >= reversePhiUpsilonValues.size()) + reversePhiUpsilonValues.resize(same.instId().value + 1); + reversePhiUpsilonValues[same.instId().value].push_back(targetPhi); } cascades.push_back(targetPhi); } @@ -199,7 +212,13 @@ struct TrivialPhiEliminator if (phiIdx < phiTargetBlocks.size()) { for (auto const blockId: phiTargetBlocks[phiIdx]) - std::erase_if(cfg.block(blockId).upsilons, [_phi](auto const& u) { return u.phi == _phi; }); + { + auto& block = cfg.block(blockId); + std::erase_if(block.instructions, [this, _phi](InstId _id) { + auto const& ins = cfg.inst(_id); + return ins.isUpsilon() && cfg.upsilonPhi(_id) == _phi; + }); + } phiTargetBlocks[phiIdx].clear(); } @@ -209,9 +228,7 @@ struct TrivialPhiEliminator SSACFG::ValueId canonicalize(SSACFG::ValueId const _v) { - if (!_v.isPhi()) - return _v; - auto const idx = _v.value(); + auto const idx = _v.instId().value; if (idx >= substitution.size()) return _v; auto& sub = substitution[idx]; @@ -230,11 +247,15 @@ struct TrivialPhiEliminator for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) { auto& block = cfg.block(blockId); - for (auto& u: block.upsilons) - u.value = canonicalize(u.value); - for (auto const opId: block.operations) - for (auto& input: cfg.operation(opId).inputs) - input = canonicalize(input); + for (InstId const instId: block.instructions) + { + auto& inst = cfg.inst(instId); + if (inst.isUpsilon()) + inst.inputs[0] = canonicalize(inst.inputs[0]); + else if (inst.isOperation()) + for (auto& input: inst.inputs) + input = canonicalize(input); + } std::visit(solidity::util::GenericVisitor{ [&](SSACFG::BasicBlock::FunctionReturn& r) { for (auto& v: r.returnValues) diff --git a/libyul/backends/evm/ssa/util/UseCountSet.h b/libyul/backends/evm/ssa/util/UseCountSet.h index e6e94062d..16aaf3f69 100644 --- a/libyul/backends/evm/ssa/util/UseCountSet.h +++ b/libyul/backends/evm/ssa/util/UseCountSet.h @@ -18,6 +18,9 @@ #pragma once +#include +#include + #include #include #include @@ -114,15 +117,13 @@ class UseCountSet return *this; } - template - void insertAll(Range const& _values) + void insertAll(ranges::input_range auto&& _values) requires std::convertible_to, Key> { for (auto const& value: _values) insert(value); } - template - void eraseAll(Range const& _values) + void eraseAll(ranges::input_range auto&& _values) requires std::convertible_to, Key> { for (auto const& value: _values) erase(value); diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index 3bfae0a92..98ae4a464 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -7,7 +7,7 @@ "blocks": [ { "exit": { - "cond": "v1", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -38,7 +38,7 @@ "in": [], "op": "callvalue", "out": [ - "v1" + "v3" ] } ], @@ -63,7 +63,7 @@ ], "op": "datasize", "out": [ - "v2" + "v6" ] }, { @@ -73,13 +73,13 @@ ], "op": "dataoffset", "out": [ - "v3" + "v7" ] }, { "in": [ - "v2", - "v3", + "v6", + "v7", "v0" ], "op": "codecopy", @@ -87,7 +87,7 @@ }, { "in": [ - "v2", + "v6", "v0" ], "op": "return", @@ -130,7 +130,7 @@ "blocks": [ { "exit": { - "cond": "v3", + "cond": "v6", "targets": [ "Block2", "Block1" @@ -161,26 +161,26 @@ "in": [], "op": "calldatasize", "out": [ - "v1" + "v4" ] }, { "in": [ "0x04", - "v1" + "v4" ], "op": "lt", "out": [ - "v2" + "v5" ] }, { "in": [ - "v2" + "v5" ], "op": "iszero", "out": [ - "v3" + "v6" ] } ], @@ -215,7 +215,7 @@ }, { "exit": { - "cond": "v6", + "cond": "v12", "targets": [ "Block4", "Block3" @@ -230,27 +230,27 @@ ], "op": "calldataload", "out": [ - "v4" + "v8" ] }, { "in": [ - "v4", + "v8", "0xe0" ], "op": "shr", "out": [ - "v5" + "v10" ] }, { "in": [ - "v5", + "v10", "0x26121ff0" ], "op": "eq", "out": [ - "v6" + "v12" ] } ], @@ -280,7 +280,7 @@ }, { "exit": { - "cond": "v7", + "cond": "v13", "targets": [ "Block6", "Block5" @@ -293,7 +293,7 @@ "in": [], "op": "callvalue", "out": [ - "v7" + "v13" ] } ], @@ -309,7 +309,7 @@ }, { "exit": { - "cond": "v11", + "cond": "v19", "targets": [ "Block9", "Block8" @@ -324,34 +324,34 @@ ], "op": "not", "out": [ - "v8" + "v16" ] }, { "in": [], "op": "calldatasize", "out": [ - "v9" + "v17" ] }, { "in": [ - "v8", - "v9" + "v16", + "v17" ], "op": "add", "out": [ - "v10" + "v18" ] }, { "in": [ "0x00", - "v10" + "v18" ], "op": "slt", "out": [ - "v11" + "v19" ] } ], @@ -454,7 +454,7 @@ "blocks": [ { "exit": { - "cond": "v1", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -485,7 +485,7 @@ "in": [], "op": "callvalue", "out": [ - "v1" + "v3" ] } ], @@ -510,7 +510,7 @@ ], "op": "datasize", "out": [ - "v2" + "v6" ] }, { @@ -520,13 +520,13 @@ ], "op": "dataoffset", "out": [ - "v3" + "v7" ] }, { "in": [ - "v2", - "v3", + "v6", + "v7", "v0" ], "op": "codecopy", @@ -534,7 +534,7 @@ }, { "in": [ - "v2", + "v6", "v0" ], "op": "return", @@ -577,7 +577,7 @@ "blocks": [ { "exit": { - "cond": "v3", + "cond": "v6", "targets": [ "Block2", "Block1" @@ -608,26 +608,26 @@ "in": [], "op": "calldatasize", "out": [ - "v1" + "v4" ] }, { "in": [ "0x04", - "v1" + "v4" ], "op": "lt", "out": [ - "v2" + "v5" ] }, { "in": [ - "v2" + "v5" ], "op": "iszero", "out": [ - "v3" + "v6" ] } ], @@ -662,7 +662,7 @@ }, { "exit": { - "cond": "v6", + "cond": "v12", "targets": [ "Block4", "Block3" @@ -677,27 +677,27 @@ ], "op": "calldataload", "out": [ - "v4" + "v8" ] }, { "in": [ - "v4", + "v8", "0xe0" ], "op": "shr", "out": [ - "v5" + "v10" ] }, { "in": [ - "v5", + "v10", "0x26121ff0" ], "op": "eq", "out": [ - "v6" + "v12" ] } ], @@ -727,7 +727,7 @@ }, { "exit": { - "cond": "v7", + "cond": "v13", "targets": [ "Block6", "Block5" @@ -740,7 +740,7 @@ "in": [], "op": "callvalue", "out": [ - "v7" + "v13" ] } ], @@ -756,7 +756,7 @@ }, { "exit": { - "cond": "v11", + "cond": "v19", "targets": [ "Block9", "Block8" @@ -771,34 +771,34 @@ ], "op": "not", "out": [ - "v8" + "v16" ] }, { "in": [], "op": "calldatasize", "out": [ - "v9" + "v17" ] }, { "in": [ - "v8", - "v9" + "v16", + "v17" ], "op": "add", "out": [ - "v10" + "v18" ] }, { "in": [ "0x00", - "v10" + "v18" ], "op": "slt", "out": [ - "v11" + "v19" ] } ], @@ -835,7 +835,7 @@ }, { "exit": { - "cond": "v16", + "cond": "v34", "targets": [ "Block12", "Block11" @@ -851,47 +851,47 @@ ], "op": "datasize", "out": [ - "v12" + "v21" ] }, { "in": [ - "v12", + "v21", "v0" ], "op": "add", "out": [ - "v13" + "v30" ] }, { "in": [ "v0", - "v13" + "v30" ], "op": "lt", "out": [ - "v14" + "v31" ] }, { "in": [ "0xffffffffffffffff", - "v13" + "v30" ], "op": "gt", "out": [ - "v15" + "v33" ] }, { "in": [ - "v14", - "v15" + "v31", + "v33" ], "op": "or", "out": [ - "v16" + "v34" ] } ], @@ -901,8 +901,8 @@ ], "out": [ "v0", - "v13", - "v12" + "v30", + "v21" ] }, "type": "BuiltinCall" @@ -930,7 +930,7 @@ }, { "exit": { - "cond": "v21", + "cond": "v58", "targets": [ "Block15", "Block14" @@ -946,13 +946,13 @@ ], "op": "dataoffset", "out": [ - "v18" + "v46" ] }, { "in": [ - "v12", - "v18", + "v21", + "v46", "v0" ], "op": "datacopy", @@ -961,42 +961,42 @@ { "in": [ "v0", - "v13" + "v30" ], "op": "sub", "out": [ - "v19" + "v56" ] }, { "in": [ - "v19", + "v56", "v0", "0x00" ], "op": "create", "out": [ - "v20" + "v57" ] }, { "in": [ - "v20" + "v57" ], "op": "iszero", "out": [ - "v21" + "v58" ] } ], "liveness": { "in": [ "v0", - "v13", - "v12" + "v30", + "v21" ], "out": [ - "v20" + "v57" ] }, "type": "BuiltinCall" @@ -1014,12 +1014,12 @@ ], "op": "shl", "out": [ - "v17" + "v36" ] }, { "in": [ - "v17", + "v36", "0x00" ], "op": "mstore", @@ -1050,7 +1050,7 @@ }, { "exit": { - "cond": "v32", + "cond": "v81", "targets": [ "Block18", "Block17" @@ -1065,7 +1065,7 @@ ], "op": "mload", "out": [ - "v25" + "v64" ] }, { @@ -1075,13 +1075,13 @@ ], "op": "shl", "out": [ - "v26" + "v67" ] }, { "in": [ - "v26", - "v25" + "v67", + "v64" ], "op": "mstore", "out": [] @@ -1093,67 +1093,67 @@ ], "op": "shl", "out": [ - "v27" + "v72" ] }, { "in": [ "0x01", - "v27" + "v72" ], "op": "sub", "out": [ - "v28" + "v73" ] }, { "in": [ - "v28", - "v20" + "v73", + "v57" ], "op": "and", "out": [ - "v29" + "v78" ] }, { "in": [], "op": "gas", "out": [ - "v30" + "v79" ] }, { "in": [ "0x20", - "v25", + "v64", "0x04", - "v25", - "v29", - "v30" + "v64", + "v78", + "v79" ], "op": "staticcall", "out": [ - "v31" + "v80" ] }, { "in": [ - "v31" + "v80" ], "op": "iszero", "out": [ - "v32" + "v81" ] } ], "liveness": { "in": [ - "v20" + "v57" ], "out": [ - "v25", - "v31" + "v64", + "v80" ] }, "type": "BuiltinCall" @@ -1170,21 +1170,21 @@ ], "op": "mload", "out": [ - "v22" + "v59" ] }, { "in": [], "op": "returndatasize", "out": [ - "v23" + "v60" ] }, { "in": [ - "v23", + "v60", "0x00", - "v22" + "v59" ], "op": "returndatacopy", "out": [] @@ -1193,13 +1193,13 @@ "in": [], "op": "returndatasize", "out": [ - "v24" + "v62" ] }, { "in": [ - "v24", - "v22" + "v62", + "v59" ], "op": "revert", "out": [] @@ -1213,7 +1213,7 @@ }, { "exit": { - "cond": "v31", + "cond": "v80", "targets": [ "Block21", "Block20" @@ -1224,11 +1224,11 @@ "instructions": [], "liveness": { "in": [ - "v25", - "v31" + "v64", + "v80" ], "out": [ - "v25" + "v64" ] } }, @@ -1244,21 +1244,21 @@ ], "op": "mload", "out": [ - "v33" + "v82" ] }, { "in": [], "op": "returndatasize", "out": [ - "v34" + "v83" ] }, { "in": [ - "v34", + "v83", "0x00", - "v33" + "v82" ], "op": "returndatacopy", "out": [] @@ -1267,13 +1267,13 @@ "in": [], "op": "returndatasize", "out": [ - "v35" + "v85" ] }, { "in": [ - "v35", - "v33" + "v85", + "v82" ], "op": "revert", "out": [] @@ -1298,11 +1298,11 @@ { "in": [ "0x00", - "v50" + "v137" ], "op": "PhiFunction", "out": [ - "phi26" + "phi139" ] }, { @@ -1311,13 +1311,13 @@ ], "op": "mload", "out": [ - "v51" + "v138" ] }, { "in": [ - "phi26", - "v51" + "phi139", + "v138" ], "op": "mstore", "out": [] @@ -1325,7 +1325,7 @@ { "in": [ "0x20", - "v51" + "v138" ], "op": "return", "out": [] @@ -1333,7 +1333,7 @@ ], "liveness": { "in": [ - "phi26" + "phi139" ], "out": [] }, @@ -1341,7 +1341,7 @@ }, { "exit": { - "cond": "v37", + "cond": "v92", "targets": [ "Block23", "Block22" @@ -1354,26 +1354,26 @@ "in": [], "op": "returndatasize", "out": [ - "v36" + "v91" ] }, { "in": [ - "v36", + "v91", "0x20" ], "op": "gt", "out": [ - "v37" + "v92" ] } ], "liveness": { "in": [ - "v25" + "v64" ], "out": [ - "v25" + "v64" ] }, "type": "BuiltinCall" @@ -1384,7 +1384,7 @@ "Block22" ], "exit": { - "cond": "v45", + "cond": "v111", "targets": [ "Block25", "Block24" @@ -1396,11 +1396,11 @@ { "in": [ "0x20", - "v38" + "v93" ], "op": "PhiFunction", "out": [ - "phi14" + "phi96" ] }, { @@ -1409,79 +1409,79 @@ ], "op": "not", "out": [ - "v39" + "v95" ] }, { "in": [ "0x1f", - "phi14" + "phi96" ], "op": "add", "out": [ - "v40" + "v99" ] }, { "in": [ - "v39", - "v40" + "v95", + "v99" ], "op": "and", "out": [ - "v41" + "v100" ] }, { "in": [ - "v41", - "v25" + "v100", + "v64" ], "op": "add", "out": [ - "v42" + "v108" ] }, { "in": [ - "v25", - "v42" + "v64", + "v108" ], "op": "lt", "out": [ - "v43" + "v109" ] }, { "in": [ "0xffffffffffffffff", - "v42" + "v108" ], "op": "gt", "out": [ - "v44" + "v110" ] }, { "in": [ - "v43", - "v44" + "v109", + "v110" ], "op": "or", "out": [ - "v45" + "v111" ] } ], "liveness": { "in": [ - "v25", - "phi14" + "v64", + "phi96" ], "out": [ - "v25", - "phi14", - "v42" + "v64", + "phi96", + "v108" ] }, "type": "BuiltinCall" @@ -1499,24 +1499,24 @@ "in": [], "op": "returndatasize", "out": [ - "v38" + "v93" ] } ], "liveness": { "in": [ - "v25" + "v64" ], "out": [ - "v38", - "v25" + "v93", + "v64" ] }, "type": "BuiltinCall" }, { "exit": { - "cond": "v49", + "cond": "v131", "targets": [ "Block28", "Block27" @@ -1527,7 +1527,7 @@ "instructions": [ { "in": [ - "v42", + "v108", "0x40" ], "op": "mstore", @@ -1535,43 +1535,43 @@ }, { "in": [ - "phi14", - "v25" + "phi96", + "v64" ], "op": "add", "out": [ - "v47" + "v129" ] }, { "in": [ - "v25", - "v47" + "v64", + "v129" ], "op": "sub", "out": [ - "v48" + "v130" ] }, { "in": [ "0x20", - "v48" + "v130" ], "op": "slt", "out": [ - "v49" + "v131" ] } ], "liveness": { "in": [ - "v25", - "phi14", - "v42" + "v64", + "phi96", + "v108" ], "out": [ - "v25" + "v64" ] }, "type": "BuiltinCall" @@ -1589,12 +1589,12 @@ ], "op": "shl", "out": [ - "v46" + "v112" ] }, { "in": [ - "v46", + "v112", "0x00" ], "op": "mstore", @@ -1634,20 +1634,20 @@ "instructions": [ { "in": [ - "v25" + "v64" ], "op": "mload", "out": [ - "v50" + "v137" ] } ], "liveness": { "in": [ - "v25" + "v64" ], "out": [ - "v50" + "v137" ] }, "type": "BuiltinCall" @@ -1680,7 +1680,7 @@ "blocks": [ { "exit": { - "cond": "v1", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -1711,7 +1711,7 @@ "in": [], "op": "callvalue", "out": [ - "v1" + "v3" ] } ], @@ -1736,7 +1736,7 @@ ], "op": "datasize", "out": [ - "v2" + "v6" ] }, { @@ -1746,13 +1746,13 @@ ], "op": "dataoffset", "out": [ - "v3" + "v7" ] }, { "in": [ - "v2", - "v3", + "v6", + "v7", "v0" ], "op": "codecopy", @@ -1760,7 +1760,7 @@ }, { "in": [ - "v2", + "v6", "v0" ], "op": "return", @@ -1803,7 +1803,7 @@ "blocks": [ { "exit": { - "cond": "v3", + "cond": "v6", "targets": [ "Block2", "Block1" @@ -1834,26 +1834,26 @@ "in": [], "op": "calldatasize", "out": [ - "v1" + "v4" ] }, { "in": [ "0x04", - "v1" + "v4" ], "op": "lt", "out": [ - "v2" + "v5" ] }, { "in": [ - "v2" + "v5" ], "op": "iszero", "out": [ - "v3" + "v6" ] } ], @@ -1888,7 +1888,7 @@ }, { "exit": { - "cond": "v6", + "cond": "v12", "targets": [ "Block4", "Block3" @@ -1903,27 +1903,27 @@ ], "op": "calldataload", "out": [ - "v4" + "v8" ] }, { "in": [ - "v4", + "v8", "0xe0" ], "op": "shr", "out": [ - "v5" + "v10" ] }, { "in": [ - "v5", + "v10", "0x26121ff0" ], "op": "eq", "out": [ - "v6" + "v12" ] } ], @@ -1953,7 +1953,7 @@ }, { "exit": { - "cond": "v7", + "cond": "v13", "targets": [ "Block6", "Block5" @@ -1966,7 +1966,7 @@ "in": [], "op": "callvalue", "out": [ - "v7" + "v13" ] } ], @@ -1982,7 +1982,7 @@ }, { "exit": { - "cond": "v11", + "cond": "v19", "targets": [ "Block9", "Block8" @@ -1997,34 +1997,34 @@ ], "op": "not", "out": [ - "v8" + "v16" ] }, { "in": [], "op": "calldatasize", "out": [ - "v9" + "v17" ] }, { "in": [ - "v8", - "v9" + "v16", + "v17" ], "op": "add", "out": [ - "v10" + "v18" ] }, { "in": [ "0x00", - "v10" + "v18" ], "op": "slt", "out": [ - "v11" + "v19" ] } ], diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output index 7554c2340..75110c57c 100644 --- a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -7,7 +7,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v1", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -38,7 +38,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v1" + "v3" ] } ], @@ -63,7 +63,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v2" + "v6" ] }, { @@ -73,13 +73,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v3" + "v7" ] }, { "in": [ - "v2", - "v3", + "v6", + "v7", "v0" ], "op": "codecopy", @@ -87,7 +87,7 @@ Yul Control Flow Graph: }, { "in": [ - "v2", + "v6", "v0" ], "op": "return", @@ -130,7 +130,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v3", + "cond": "v6", "targets": [ "Block2", "Block1" @@ -161,26 +161,26 @@ Yul Control Flow Graph: "in": [], "op": "calldatasize", "out": [ - "v1" + "v4" ] }, { "in": [ "0x04", - "v1" + "v4" ], "op": "lt", "out": [ - "v2" + "v5" ] }, { "in": [ - "v2" + "v5" ], "op": "iszero", "out": [ - "v3" + "v6" ] } ], @@ -215,7 +215,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v6", + "cond": "v12", "targets": [ "Block4", "Block3" @@ -230,27 +230,27 @@ Yul Control Flow Graph: ], "op": "calldataload", "out": [ - "v4" + "v8" ] }, { "in": [ - "v4", + "v8", "0xe0" ], "op": "shr", "out": [ - "v5" + "v10" ] }, { "in": [ - "v5", + "v10", "0x26121ff0" ], "op": "eq", "out": [ - "v6" + "v12" ] } ], @@ -280,7 +280,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v7", + "cond": "v13", "targets": [ "Block6", "Block5" @@ -293,7 +293,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v7" + "v13" ] } ], @@ -309,7 +309,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v11", + "cond": "v19", "targets": [ "Block9", "Block8" @@ -324,34 +324,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v8" + "v16" ] }, { "in": [], "op": "calldatasize", "out": [ - "v9" + "v17" ] }, { "in": [ - "v8", - "v9" + "v16", + "v17" ], "op": "add", "out": [ - "v10" + "v18" ] }, { "in": [ "0x00", - "v10" + "v18" ], "op": "slt", "out": [ - "v11" + "v19" ] } ], diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index 44a30e2e7..464ba9b3d 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -6,7 +6,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v1", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -37,7 +37,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v1" + "v3" ] } ], @@ -62,7 +62,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v2" + "v6" ] }, { @@ -72,13 +72,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v3" + "v7" ] }, { "in": [ - "v2", - "v3", + "v6", + "v7", "v0" ], "op": "codecopy", @@ -86,7 +86,7 @@ Yul Control Flow Graph: }, { "in": [ - "v2", + "v6", "v0" ], "op": "return", @@ -129,7 +129,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v3", + "cond": "v6", "targets": [ "Block2", "Block1" @@ -160,26 +160,26 @@ Yul Control Flow Graph: "in": [], "op": "calldatasize", "out": [ - "v1" + "v4" ] }, { "in": [ "0x04", - "v1" + "v4" ], "op": "lt", "out": [ - "v2" + "v5" ] }, { "in": [ - "v2" + "v5" ], "op": "iszero", "out": [ - "v3" + "v6" ] } ], @@ -214,7 +214,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v6", + "cond": "v12", "targets": [ "Block4", "Block3" @@ -229,27 +229,27 @@ Yul Control Flow Graph: ], "op": "calldataload", "out": [ - "v4" + "v8" ] }, { "in": [ - "v4", + "v8", "0xe0" ], "op": "shr", "out": [ - "v5" + "v10" ] }, { "in": [ - "v5", + "v10", "0x26121ff0" ], "op": "eq", "out": [ - "v6" + "v12" ] } ], @@ -279,7 +279,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v7", + "cond": "v13", "targets": [ "Block6", "Block5" @@ -292,7 +292,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v7" + "v13" ] } ], @@ -308,7 +308,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v11", + "cond": "v19", "targets": [ "Block9", "Block8" @@ -323,34 +323,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v8" + "v16" ] }, { "in": [], "op": "calldatasize", "out": [ - "v9" + "v17" ] }, { "in": [ - "v8", - "v9" + "v16", + "v17" ], "op": "add", "out": [ - "v10" + "v18" ] }, { "in": [ "0x00", - "v10" + "v18" ], "op": "slt", "out": [ - "v11" + "v19" ] } ], @@ -454,7 +454,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v1", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -485,7 +485,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v1" + "v3" ] } ], @@ -510,7 +510,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v2" + "v6" ] }, { @@ -520,13 +520,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v3" + "v7" ] }, { "in": [ - "v2", - "v3", + "v6", + "v7", "v0" ], "op": "codecopy", @@ -534,7 +534,7 @@ Yul Control Flow Graph: }, { "in": [ - "v2", + "v6", "v0" ], "op": "return", @@ -577,7 +577,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v3", + "cond": "v6", "targets": [ "Block2", "Block1" @@ -608,26 +608,26 @@ Yul Control Flow Graph: "in": [], "op": "calldatasize", "out": [ - "v1" + "v4" ] }, { "in": [ "0x04", - "v1" + "v4" ], "op": "lt", "out": [ - "v2" + "v5" ] }, { "in": [ - "v2" + "v5" ], "op": "iszero", "out": [ - "v3" + "v6" ] } ], @@ -662,7 +662,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v6", + "cond": "v12", "targets": [ "Block4", "Block3" @@ -677,27 +677,27 @@ Yul Control Flow Graph: ], "op": "calldataload", "out": [ - "v4" + "v8" ] }, { "in": [ - "v4", + "v8", "0xe0" ], "op": "shr", "out": [ - "v5" + "v10" ] }, { "in": [ - "v5", + "v10", "0x26121ff0" ], "op": "eq", "out": [ - "v6" + "v12" ] } ], @@ -727,7 +727,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v7", + "cond": "v13", "targets": [ "Block6", "Block5" @@ -740,7 +740,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v7" + "v13" ] } ], @@ -756,7 +756,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v11", + "cond": "v19", "targets": [ "Block9", "Block8" @@ -771,34 +771,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v8" + "v16" ] }, { "in": [], "op": "calldatasize", "out": [ - "v9" + "v17" ] }, { "in": [ - "v8", - "v9" + "v16", + "v17" ], "op": "add", "out": [ - "v10" + "v18" ] }, { "in": [ "0x00", - "v10" + "v18" ], "op": "slt", "out": [ - "v11" + "v19" ] } ], @@ -835,7 +835,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v16", + "cond": "v34", "targets": [ "Block12", "Block11" @@ -851,47 +851,47 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v12" + "v21" ] }, { "in": [ - "v12", + "v21", "v0" ], "op": "add", "out": [ - "v13" + "v30" ] }, { "in": [ "v0", - "v13" + "v30" ], "op": "lt", "out": [ - "v14" + "v31" ] }, { "in": [ "0xffffffffffffffff", - "v13" + "v30" ], "op": "gt", "out": [ - "v15" + "v33" ] }, { "in": [ - "v14", - "v15" + "v31", + "v33" ], "op": "or", "out": [ - "v16" + "v34" ] } ], @@ -901,8 +901,8 @@ Yul Control Flow Graph: ], "out": [ "v0", - "v13", - "v12" + "v30", + "v21" ] }, "type": "BuiltinCall" @@ -930,7 +930,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v21", + "cond": "v58", "targets": [ "Block15", "Block14" @@ -946,13 +946,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v18" + "v46" ] }, { "in": [ - "v12", - "v18", + "v21", + "v46", "v0" ], "op": "datacopy", @@ -961,42 +961,42 @@ Yul Control Flow Graph: { "in": [ "v0", - "v13" + "v30" ], "op": "sub", "out": [ - "v19" + "v56" ] }, { "in": [ - "v19", + "v56", "v0", "0x00" ], "op": "create", "out": [ - "v20" + "v57" ] }, { "in": [ - "v20" + "v57" ], "op": "iszero", "out": [ - "v21" + "v58" ] } ], "liveness": { "in": [ "v0", - "v13", - "v12" + "v30", + "v21" ], "out": [ - "v20" + "v57" ] }, "type": "BuiltinCall" @@ -1014,12 +1014,12 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v17" + "v36" ] }, { "in": [ - "v17", + "v36", "0x00" ], "op": "mstore", @@ -1050,7 +1050,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v32", + "cond": "v81", "targets": [ "Block18", "Block17" @@ -1065,7 +1065,7 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v25" + "v64" ] }, { @@ -1075,13 +1075,13 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v26" + "v67" ] }, { "in": [ - "v26", - "v25" + "v67", + "v64" ], "op": "mstore", "out": [] @@ -1093,67 +1093,67 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v27" + "v72" ] }, { "in": [ "0x01", - "v27" + "v72" ], "op": "sub", "out": [ - "v28" + "v73" ] }, { "in": [ - "v28", - "v20" + "v73", + "v57" ], "op": "and", "out": [ - "v29" + "v78" ] }, { "in": [], "op": "gas", "out": [ - "v30" + "v79" ] }, { "in": [ "0x20", - "v25", + "v64", "0x04", - "v25", - "v29", - "v30" + "v64", + "v78", + "v79" ], "op": "staticcall", "out": [ - "v31" + "v80" ] }, { "in": [ - "v31" + "v80" ], "op": "iszero", "out": [ - "v32" + "v81" ] } ], "liveness": { "in": [ - "v20" + "v57" ], "out": [ - "v25", - "v31" + "v64", + "v80" ] }, "type": "BuiltinCall" @@ -1170,21 +1170,21 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v22" + "v59" ] }, { "in": [], "op": "returndatasize", "out": [ - "v23" + "v60" ] }, { "in": [ - "v23", + "v60", "0x00", - "v22" + "v59" ], "op": "returndatacopy", "out": [] @@ -1193,13 +1193,13 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v24" + "v62" ] }, { "in": [ - "v24", - "v22" + "v62", + "v59" ], "op": "revert", "out": [] @@ -1213,7 +1213,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v31", + "cond": "v80", "targets": [ "Block21", "Block20" @@ -1224,11 +1224,11 @@ Yul Control Flow Graph: "instructions": [], "liveness": { "in": [ - "v25", - "v31" + "v64", + "v80" ], "out": [ - "v25" + "v64" ] } }, @@ -1244,21 +1244,21 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v33" + "v82" ] }, { "in": [], "op": "returndatasize", "out": [ - "v34" + "v83" ] }, { "in": [ - "v34", + "v83", "0x00", - "v33" + "v82" ], "op": "returndatacopy", "out": [] @@ -1267,13 +1267,13 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v35" + "v85" ] }, { "in": [ - "v35", - "v33" + "v85", + "v82" ], "op": "revert", "out": [] @@ -1298,11 +1298,11 @@ Yul Control Flow Graph: { "in": [ "0x00", - "v50" + "v137" ], "op": "PhiFunction", "out": [ - "phi26" + "phi139" ] }, { @@ -1311,13 +1311,13 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v51" + "v138" ] }, { "in": [ - "phi26", - "v51" + "phi139", + "v138" ], "op": "mstore", "out": [] @@ -1325,7 +1325,7 @@ Yul Control Flow Graph: { "in": [ "0x20", - "v51" + "v138" ], "op": "return", "out": [] @@ -1333,7 +1333,7 @@ Yul Control Flow Graph: ], "liveness": { "in": [ - "phi26" + "phi139" ], "out": [] }, @@ -1341,7 +1341,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v37", + "cond": "v92", "targets": [ "Block23", "Block22" @@ -1354,26 +1354,26 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v36" + "v91" ] }, { "in": [ - "v36", + "v91", "0x20" ], "op": "gt", "out": [ - "v37" + "v92" ] } ], "liveness": { "in": [ - "v25" + "v64" ], "out": [ - "v25" + "v64" ] }, "type": "BuiltinCall" @@ -1384,7 +1384,7 @@ Yul Control Flow Graph: "Block22" ], "exit": { - "cond": "v45", + "cond": "v111", "targets": [ "Block25", "Block24" @@ -1396,11 +1396,11 @@ Yul Control Flow Graph: { "in": [ "0x20", - "v38" + "v93" ], "op": "PhiFunction", "out": [ - "phi14" + "phi96" ] }, { @@ -1409,79 +1409,79 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v39" + "v95" ] }, { "in": [ "0x1f", - "phi14" + "phi96" ], "op": "add", "out": [ - "v40" + "v99" ] }, { "in": [ - "v39", - "v40" + "v95", + "v99" ], "op": "and", "out": [ - "v41" + "v100" ] }, { "in": [ - "v41", - "v25" + "v100", + "v64" ], "op": "add", "out": [ - "v42" + "v108" ] }, { "in": [ - "v25", - "v42" + "v64", + "v108" ], "op": "lt", "out": [ - "v43" + "v109" ] }, { "in": [ "0xffffffffffffffff", - "v42" + "v108" ], "op": "gt", "out": [ - "v44" + "v110" ] }, { "in": [ - "v43", - "v44" + "v109", + "v110" ], "op": "or", "out": [ - "v45" + "v111" ] } ], "liveness": { "in": [ - "v25", - "phi14" + "v64", + "phi96" ], "out": [ - "v25", - "phi14", - "v42" + "v64", + "phi96", + "v108" ] }, "type": "BuiltinCall" @@ -1499,24 +1499,24 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v38" + "v93" ] } ], "liveness": { "in": [ - "v25" + "v64" ], "out": [ - "v38", - "v25" + "v93", + "v64" ] }, "type": "BuiltinCall" }, { "exit": { - "cond": "v49", + "cond": "v131", "targets": [ "Block28", "Block27" @@ -1527,7 +1527,7 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v42", + "v108", "0x40" ], "op": "mstore", @@ -1535,43 +1535,43 @@ Yul Control Flow Graph: }, { "in": [ - "phi14", - "v25" + "phi96", + "v64" ], "op": "add", "out": [ - "v47" + "v129" ] }, { "in": [ - "v25", - "v47" + "v64", + "v129" ], "op": "sub", "out": [ - "v48" + "v130" ] }, { "in": [ "0x20", - "v48" + "v130" ], "op": "slt", "out": [ - "v49" + "v131" ] } ], "liveness": { "in": [ - "v25", - "phi14", - "v42" + "v64", + "phi96", + "v108" ], "out": [ - "v25" + "v64" ] }, "type": "BuiltinCall" @@ -1589,12 +1589,12 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v46" + "v112" ] }, { "in": [ - "v46", + "v112", "0x00" ], "op": "mstore", @@ -1634,20 +1634,20 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v25" + "v64" ], "op": "mload", "out": [ - "v50" + "v137" ] } ], "liveness": { "in": [ - "v25" + "v64" ], "out": [ - "v50" + "v137" ] }, "type": "BuiltinCall" @@ -1680,7 +1680,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v1", + "cond": "v3", "targets": [ "Block2", "Block1" @@ -1711,7 +1711,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v1" + "v3" ] } ], @@ -1736,7 +1736,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v2" + "v6" ] }, { @@ -1746,13 +1746,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v3" + "v7" ] }, { "in": [ - "v2", - "v3", + "v6", + "v7", "v0" ], "op": "codecopy", @@ -1760,7 +1760,7 @@ Yul Control Flow Graph: }, { "in": [ - "v2", + "v6", "v0" ], "op": "return", @@ -1803,7 +1803,7 @@ Yul Control Flow Graph: "blocks": [ { "exit": { - "cond": "v3", + "cond": "v6", "targets": [ "Block2", "Block1" @@ -1834,26 +1834,26 @@ Yul Control Flow Graph: "in": [], "op": "calldatasize", "out": [ - "v1" + "v4" ] }, { "in": [ "0x04", - "v1" + "v4" ], "op": "lt", "out": [ - "v2" + "v5" ] }, { "in": [ - "v2" + "v5" ], "op": "iszero", "out": [ - "v3" + "v6" ] } ], @@ -1888,7 +1888,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v6", + "cond": "v12", "targets": [ "Block4", "Block3" @@ -1903,27 +1903,27 @@ Yul Control Flow Graph: ], "op": "calldataload", "out": [ - "v4" + "v8" ] }, { "in": [ - "v4", + "v8", "0xe0" ], "op": "shr", "out": [ - "v5" + "v10" ] }, { "in": [ - "v5", + "v10", "0x26121ff0" ], "op": "eq", "out": [ - "v6" + "v12" ] } ], @@ -1953,7 +1953,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v7", + "cond": "v13", "targets": [ "Block6", "Block5" @@ -1966,7 +1966,7 @@ Yul Control Flow Graph: "in": [], "op": "callvalue", "out": [ - "v7" + "v13" ] } ], @@ -1982,7 +1982,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v11", + "cond": "v19", "targets": [ "Block9", "Block8" @@ -1997,34 +1997,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v8" + "v16" ] }, { "in": [], "op": "calldatasize", "out": [ - "v9" + "v17" ] }, { "in": [ - "v8", - "v9" + "v16", + "v17" ], "op": "add", "out": [ - "v10" + "v18" ] }, { "in": [ "0x00", - "v10" + "v18" ], "op": "slt", "out": [ - "v11" + "v19" ] } ], diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index d54a0a40d..20bddfad2 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -78,32 +78,28 @@ class StackLayoutDotExporter: public io::DotExporterBase _out << "\\\n"; _out << "IN: " << stackToString(blockLayout->stackIn) << "\\l\\\n"; - for (std::size_t i = 0; i < block.operations.size(); ++i) - { - auto const& operation = m_cfg.operation(block.operations[i]); + std::size_t i = 0; + m_cfg.forEachOperation(block, [&](InstId const instId, SSACFG::Inst const& inst) { yulAssert(i < blockLayout->operationIn.size()); auto operationStack = blockLayout->operationIn[i]; _out << "\\l\\\n"; _out << stackToString(operationStack) << "\\l\\\n"; - std::visit(GenericVisitor{ - [&](SSACFG::Call const& _call) { - _out << escapeLabel(m_controlFlow.functionGraph(_call.graphID)->name); - }, - [&](SSACFG::BuiltinCall const& _call) { - _out << escapeLabel(m_cfg.evmDialect.builtin(_call.builtin).name); - } - }, operation.kind); + if (inst.opcode == InstOpcode::Call) + _out << escapeLabel(m_controlFlow.functionGraph(m_cfg.callPayload(instId).graphID)->name); + else + _out << escapeLabel(m_cfg.evmDialect.builtin(m_cfg.builtinPayload(instId).builtin).name); _out << "\\l\\\n"; - yulAssert(operation.inputs.size() <= operationStack.size()); - for (std::size_t j = 0; j < operation.inputs.size(); ++j) + yulAssert(inst.inputs.size() <= operationStack.size()); + for (std::size_t j = 0; j < inst.inputs.size(); ++j) operationStack.pop_back(); - for (auto const& output: operation.outputs) - operationStack.push_back(StackSlot::makeValueID(output)); + for (auto const& output: SSACFG::outputsOf(instId, inst.numOutputs)) + operationStack.push_back(StackSlot::makeValueID(m_cfg, output)); _out << stackToString(operationStack) << "\\l\\\n"; - } + ++i; + }); _out << "\\l\\\n"; _out << "OUT: " << stackToString(blockLayout->exitIn) << "\\l\\\n"; diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index 3b6999908..9a0bf9bf2 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -18,6 +18,8 @@ #include +#include +#include #include #include #include @@ -29,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -55,30 +58,31 @@ std::string_view constexpr parserKeyInitialSpilled {"initialSpilledSet"}; using Slot = StackSlot; using ValueId = SSACFG::ValueId; -struct StackManipulationCallbacks + +struct ParsedIdentifierTable { - void swap(StackDepth _depth) const - { - if (hook) - (*hook)(fmt::format("SWAP{}", _depth.value)); - } - void dup(StackDepth const _depth) const - { - if (hook) - (*hook)(fmt::format("DUP{}", _depth.value)); - } - void push(Slot const& _slot) const - { - if (hook) - (*hook)(fmt::format("PUSH {}", slotToString(_slot))); - } - void pop() const + InstructionStore store; + std::map tokenToId; + std::map idToToken; + + std::string render(StackSlot const& _slot) const { - if (hook) - (*hook)("POP"); + if (_slot.isValueID()) + if (auto const it = idToToken.find(_slot.valueID().instId()); it != idToToken.end()) + return it->second; + return slotToString(_slot); } +}; + +struct StackManipulationCallbacks +{ + void swap(StackDepth _depth) const { hook(fmt::format("SWAP{}", _depth.value)); } + void dup(StackDepth const _depth) const { hook(fmt::format("DUP{}", _depth.value)); } + void push(Slot const& _slot) const { hook(fmt::format("PUSH {}", table.render(_slot))); } + void pop() const { hook("POP"); } - std::optional> hook = std::nullopt; + ParsedIdentifierTable const& table; + std::function hook; }; using TestStack = Stack; @@ -91,46 +95,56 @@ std::string_view trim(std::string_view s) } /// Parse a value ID token like "v172", "phi109", "lit7", or "JUNK". -Slot parseSlot(std::string_view token) +Slot parseSlot(ParsedIdentifierTable& _table, std::string_view _token) { - if (token == "JUNK") + if (_token == "JUNK") return Slot::makeJunk(); - if (token.starts_with("v")) - { - if (auto const num = solidity::util::parseArithmetic(token.substr(1))) - return Slot::makeValueID(ValueId::makeVariable(*num)); - throw std::runtime_error(fmt::format("Couldn't parse variable token: {}", token)); - } - - if (token.starts_with("phi")) + static constexpr std::string_view returnLabelPrefix = "ReturnLabel["; + if (_token.starts_with(returnLabelPrefix) && _token.ends_with("]")) { - if (auto const num = solidity::util::parseArithmetic(token.substr(3))) - return Slot::makeValueID(ValueId::makePhi(*num)); - throw std::runtime_error(fmt::format("Couldn't parse phi token: {}", token)); + auto const inner = _token.substr(returnLabelPrefix.size(), _token.size() - returnLabelPrefix.size() - 1); + if (auto const num = solidity::util::parseArithmetic(inner)) + return Slot::makeFunctionReturnLabel(*num); + throw std::runtime_error(fmt::format("Couldn't parse ReturnLabel token: {}", _token)); } - if (token.starts_with("lit")) + auto const allocateInst = [&]() -> InstId { - if (auto const num = solidity::util::parseArithmetic(token.substr(3))) - return Slot::makeValueID(ValueId::makeLiteral(*num)); - throw std::runtime_error(fmt::format("Couldn't parse literal token: {}", token)); - } + if (_token.starts_with("phi")) + { + if (!solidity::util::parseArithmetic(_token.substr(3))) + throw std::runtime_error(fmt::format("Couldn't parse phi token: {}", _token)); + return _table.store.appendPhi({0}); + } + if (_token.starts_with("lit")) + { + if (auto const num = solidity::util::parseArithmetic(_token.substr(3))) + return _table.store.appendLiteral({0}, u256(*num)); + throw std::runtime_error(fmt::format("Couldn't parse literal token: {}", _token)); + } + if (_token.starts_with("v")) + { + if (!solidity::util::parseArithmetic(_token.substr(1))) + throw std::runtime_error(fmt::format("Couldn't parse variable token: {}", _token)); + return _table.store.appendBuiltinCall({0}, {}, {}, /*numOutputs*/ 1); + } + throw std::runtime_error(fmt::format("Unknown token: {}", _token)); + }; - static constexpr std::string_view returnLabelPrefix = "ReturnLabel["; - if (token.starts_with(returnLabelPrefix) && token.ends_with("]")) + std::string const tokenStr{_token}; + auto const it = _table.tokenToId.find(tokenStr); + InstId const id = it != _table.tokenToId.end() ? it->second : allocateInst(); + if (it == _table.tokenToId.end()) { - auto const inner = token.substr(returnLabelPrefix.size(), token.size() - returnLabelPrefix.size() - 1); - if (auto const num = solidity::util::parseArithmetic(inner)) - return Slot::makeFunctionReturnLabel(*num); - throw std::runtime_error(fmt::format("Couldn't parse ReturnLabel token: {}", token)); + _table.tokenToId.emplace(tokenStr, id); + _table.idToToken.emplace(id, tokenStr); } - - throw std::runtime_error(fmt::format("Unknown token: {}", token)); + return Slot::makeValueID(_table.store, ValueId{id, 0}); } /// Parse a string like "[v172, phi109, lit7, JUNK]" into Stack::Data -TestStack::Data parseSlots(std::string_view _input, char const brackBegin = '[', char const brackEnd = ']') +TestStack::Data parseSlots(ParsedIdentifierTable& _table, std::string_view _input, char const brackBegin = '[', char const brackEnd = ']') { TestStack::Data result; @@ -153,16 +167,17 @@ TestStack::Data parseSlots(std::string_view _input, char const brackBegin = '[', token = {&*slotTokenBegin, static_cast(ranges::distance(slotTokenBegin, slotTokenEnd))}; token = trim(token); yulAssert(!token.empty(), "Empty token."); - result.push_back(parseSlot(token)); + result.push_back(parseSlot(_table, token)); } return result; } /// Parse liveness like "{phi109, phi150, v172}" -/// Returns StackSlotLiveness with reference count 1 for each value -StackSlotLiveness parseLiveness(std::string_view _input) +/// Returns a StackSlotLiveness with reference count 1 for each value, plus the parsed slots +/// (handy for printing). +std::pair parseLiveness(ParsedIdentifierTable& _table, std::string_view _input) { - auto const slots = parseSlots(_input, '{', '}'); + auto const slots = parseSlots(_table, _input, '{', '}'); StackSlotLiveness::Entries entries; entries.reserve(slots.size()); for (auto const& slot: slots) @@ -170,7 +185,7 @@ StackSlotLiveness parseLiveness(std::string_view _input) yulAssert(slot.isValueID(), "Only value IDs are permitted in liveness definition."); entries.emplace_back(slot, 1u); } - return StackSlotLiveness{std::move(entries)}; + return {StackSlotLiveness{std::move(entries)}, slots}; } struct ShuffleTestInput @@ -178,9 +193,11 @@ struct ShuffleTestInput std::optional initial; std::optional targetStackTop; StackSlotLiveness targetStackTailSet{}; + TestStack::Data targetStackTailSetSlots{}; std::optional targetStackSize; bool allowSpilling = false; SpilledVariables initialSpilledSet{}; + TestStack::Data initialSpilledSetSlots{}; bool valid() const { @@ -195,7 +212,7 @@ struct ShuffleTestInput return fullySpecified || exactMode; } - static ShuffleTestInput parse(std::string_view _source) + static ShuffleTestInput parse(ParsedIdentifierTable& _table, std::string_view _source) { ShuffleTestInput result; @@ -227,11 +244,15 @@ struct ShuffleTestInput auto const value = trim(line.substr(colonPos + 1)); if (key == parserKeyInitialStack) - result.initial = parseSlots(value, '[', ']'); + result.initial = parseSlots(_table, value, '[', ']'); else if (key == parserKeyStackTop) - result.targetStackTop = parseSlots(value, '[', ']'); + result.targetStackTop = parseSlots(_table, value, '[', ']'); else if (key == parserKeyTailSet) - result.targetStackTailSet = parseLiveness(value); + { + auto [liveness, slots] = parseLiveness(_table, value); + result.targetStackTailSet = std::move(liveness); + result.targetStackTailSetSlots = std::move(slots); + } else if (key == parserKeyStackSize) { if (auto num = solidity::util::parseArithmetic(value)) @@ -250,12 +271,10 @@ struct ShuffleTestInput } else if (key == parserKeyInitialSpilled) { - auto const spillSet = parseLiveness(value); - for (auto const& slot: spillSet | ranges::views::keys) - { - yulAssert(slot.isValueID()); + auto [liveness, slots] = parseLiveness(_table, value); + for (auto const& [slot, _]: liveness) result.initialSpilledSet.spill(slot.valueID()); - } + result.initialSpilledSetSlots = std::move(slots); } } @@ -282,14 +301,16 @@ class TraceRecorder public: TraceRecorder( std::ostream& _out, + ParsedIdentifierTable const& _table, TestStack::Data const& _targetArgs, - StackSlotLiveness const& _targetTail, + TestStack::Data const& _targetTailSlots, size_t _targetStackSize, SpilledVariables const& _spillSet ): m_out(_out), + m_table(_table), m_targetArgs(_targetArgs), - m_targetTail(_targetTail), + m_targetTail(_targetTailSlots), m_spillSet(_spillSet), m_targetStackSize(_targetStackSize), m_targetTailSize( @@ -302,10 +323,10 @@ class TraceRecorder fmt::format( "{{{}}}", fmt::join( - m_targetTail | ranges::views::keys | ranges::views::transform( - [this](Slot const& _slot) { - std::string const suffix = (_slot.isValueID() && m_spillSet.isSpilled(_slot.valueID())) ? "*" : ""; - return slotToString(_slot) + suffix; + m_targetTail | ranges::views::transform( + [this](StackSlot const& _slot) { + std::string const suffix = m_spillSet.isSpilled(_slot.valueID()) ? "*" : ""; + return m_table.render(_slot) + suffix; } ), ", " @@ -351,12 +372,12 @@ class TraceRecorder for (const auto& [operation, stackAfter]: m_entries) for (std::size_t i = 0; i < stackAfter.size(); ++i) { - std::string const slotStr = stackAfter[i].isJunk() ? std::string(1, junkSymbol) : slotToString(stackAfter[i]); + std::string const slotStr = stackAfter[i].isJunk() ? std::string(1, junkSymbol) : m_table.render(stackAfter[i]); columnWidths[i] = std::max(columnWidths[i], slotStr.size() + 1); } for (std::size_t i = 0; i < m_targetArgs.size() && m_targetTailSize + i < numColumns; ++i) { - std::string const slotStr = m_targetArgs[i].isJunk() ? std::string(1, junkSymbol) : slotToString(m_targetArgs[i]); + std::string const slotStr = m_targetArgs[i].isJunk() ? std::string(1, junkSymbol) : m_table.render(m_targetArgs[i]); columnWidths[m_targetTailSize + i] = std::max(columnWidths[m_targetTailSize + i], slotStr.size() + 1); } @@ -379,10 +400,11 @@ class TraceRecorder }; std::ostream& m_out; + ParsedIdentifierTable const& m_table; std::vector m_entries; bool m_truncated = false; TestStack::Data const& m_targetArgs; - StackSlotLiveness const& m_targetTail; + TestStack::Data const& m_targetTail; SpilledVariables const& m_spillSet; size_t const m_targetStackSize; size_t const m_targetTailSize; @@ -440,7 +462,7 @@ class TraceRecorder { emitSeparator(i, _hasExcess, '|'); auto const& slot = _entry.stackAfter[i]; - std::string slotStr = slot.isJunk() ? std::string(1, junkSymbol) : slotToString(slot); + std::string slotStr = slot.isJunk() ? std::string(1, junkSymbol) : m_table.render(slot); m_out << fmt::format("{:>{}}", slotStr, _columnWidths[i]); } m_out << '\n'; @@ -469,7 +491,7 @@ class TraceRecorder for (std::size_t i = 0; i < m_targetArgs.size(); ++i) { auto const& slot = m_targetArgs[i]; - std::string slotStr = slot.isJunk() ? std::string(1, junkSymbol) : slotToString(slot); + std::string slotStr = slot.isJunk() ? std::string(1, junkSymbol) : m_table.render(slot); m_out << fmt::format("{:>{}}", slotStr, _columnWidths[m_targetTailSize + i]); } @@ -497,7 +519,8 @@ ShufflingTest::ShufflingTest(std::string const& _filename): TestCase(_filename) ShufflingTest::TestResult ShufflingTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { - auto const testConfig = ShuffleTestInput::parse(m_source); + ParsedIdentifierTable table; + auto const testConfig = ShuffleTestInput::parse(table, m_source); if (!testConfig.valid()) { static constexpr std::string_view formatHelp = R"(initial: [, ...] @@ -534,6 +557,8 @@ explicitly provided.)"; std::ostringstream oss; StackShufflerResult shuffleResult; SpilledVariables spillSet = testConfig.initialSpilledSet; + // Tracks the kind of each spilled value + std::vector spilledSlotList = testConfig.initialSpilledSetSlots; // First, when spilling is allowed, run the shuffler repeatedly without recording to determine // the final spill set. Each iteration starts from the initial stack and adds the culprit of a @@ -542,8 +567,8 @@ explicitly provided.)"; while (true) { auto scratch = *testConfig.initial; - TestStack stack(scratch, {}); - auto const result = StackShuffler::shuffle( + Stack<> stack(scratch, {}); + auto const result = StackShuffler::shuffle( stack, *testConfig.targetStackTop, testConfig.targetStackTailSet, @@ -555,13 +580,14 @@ explicitly provided.)"; ) break; spillSet.spill(result.culprit.valueID()); + spilledSlotList.push_back(result.culprit); } // Final shuffle with the (possibly pre-populated) spill set, recording the trace. { - TraceRecorder trace(oss, *testConfig.targetStackTop, testConfig.targetStackTailSet, *testConfig.targetStackSize, spillSet); + TraceRecorder trace(oss, table, *testConfig.targetStackTop, testConfig.targetStackTailSetSlots, *testConfig.targetStackSize, spillSet); trace.record("(initial)", *testConfig.initial); - TestStack stack(stackData, {.hook = [&](std::string const& op) + TestStack stack(stackData, {.table = table, .hook = [&](std::string const& op) { trace.record(op, stackData); }}); @@ -582,7 +608,7 @@ explicitly provided.)"; oss << "Status: Admissible\n"; break; case StackShufflerResult::Status::StackTooDeep: - oss << fmt::format("Status: StackTooDeep (culprit: {})\n", slotToString(shuffleResult.culprit)); + oss << fmt::format("Status: StackTooDeep (culprit: {})\n", table.render(shuffleResult.culprit)); break; case StackShufflerResult::Status::MaxIterationsReached: oss << "Status: MaxIterationsReached\n"; @@ -594,9 +620,7 @@ explicitly provided.)"; oss << fmt::format( "Spilled: {{{}}}\n", fmt::join( - spillSet.spilledValues() | ranges::views::transform( - [](auto const& id) { return slotToString(StackSlot::makeValueID(id)); } - ), + spilledSlotList | ranges::views::transform([&](StackSlot const& _slot) { return table.render(_slot); }), ", " ) ); @@ -606,9 +630,9 @@ explicitly provided.)"; yulAssert(*testConfig.targetStackSize >= testConfig.targetStackTop->size()); auto const tailSize = *testConfig.targetStackSize - testConfig.targetStackTop->size(); yulAssert(stackData.size() == *testConfig.targetStackSize); - for (const auto& slot: testConfig.targetStackTailSet | ranges::views::keys) + for (auto const& slot: testConfig.targetStackTailSet | ranges::views::keys) { - if (slot.isValueID() && spillSet.isSpilled(slot.valueID())) + if (spillSet.isSpilled(slot.valueID())) continue; auto const findIt = ranges::find( stackData.begin(), diff --git a/test/libyul/ssa/controlFlowGraph/complex.yul b/test/libyul/ssa/controlFlowGraph/complex.yul index eff75590c..44fb7e614 100644 --- a/test/libyul/ssa/controlFlowGraph/complex.yul +++ b/test/libyul/ssa/controlFlowGraph/complex.yul @@ -53,8 +53,8 @@ // Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nUsed: \l\nv0 := f(0x02, 0x01)\l\ -// pop(v0)\l\ +// LiveOut: \l\nUsed: \l\nv2 := f(0x02, 0x01)\l\ +// pop(v2)\l\ // "]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; @@ -68,24 +68,24 @@ // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1; (1, max 17)\nLiveIn: phi1[4], v1[1], v0[1]\l\ -// LiveOut: phi1[2], v1[1], v0[1]\l\nUsed: phi1[2]\l\nphi1 := φ(\l\ +// Block 1; (1, max 17)\nLiveIn: phi5[4], v1[1], v0[1]\l\ +// LiveOut: phi5[2], v1[1], v0[1]\l\nUsed: phi5[2]\l\nphi5 := φ(\l\ // Block 0 => 0x2a,\l\ -// Block 21 => v9\l\ +// Block 21 => v61\l\ // )\l\ -// v2 := lt(v0, phi1)\l\ +// v6 := lt(v0, phi5)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_1Exit:0 -> Block1_4 [style="solid"]; // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2; (2, max 17)\nLiveIn: phi1[2], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v3[3], v0[1]\l\nUsed: phi1[1]\l\nv3 := mload(phi1)\l\ -// v4 := eq(0x00, v3)\l\ +// Block 2; (2, max 17)\nLiveIn: phi5[2], v1[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v7[3], v0[1]\l\nUsed: phi5[1]\l\nv7 := mload(phi5)\l\ +// v8 := eq(0x00, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_2Exit:0 -> Block1_7 [style="solid"]; // Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ @@ -102,11 +102,11 @@ // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7; (5, max 17)\nLiveIn: phi1[1], v1[1], v3[3], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v3[2], v0[1]\l\nUsed: v3[1]\l\nv5 := eq(0x01, v3)\l\ +// Block 7; (5, max 17)\nLiveIn: phi5[1], v1[1], v7[3], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v7[2], v0[1]\l\nUsed: v7[1]\l\nv16 := eq(0x01, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit [label="{ If v16 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_7Exit:0 -> Block1_10 [style="solid"]; // Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ @@ -116,11 +116,11 @@ // Block1_9Exit [label="FunctionReturn[0x00]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10; (7, max 17)\nLiveIn: phi1[1], v1[1], v3[2], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v3[1], v0[1]\l\nUsed: v3[1]\l\nv6 := eq(0x02, v3)\l\ +// Block 10; (7, max 17)\nLiveIn: phi5[1], v1[1], v7[2], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v7[1], v0[1]\l\nUsed: v7[1]\l\nv24 := eq(0x02, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit [label="{ If v24 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_10Exit:0 -> Block1_13 [style="solid"]; // Block1_10Exit:1 -> Block1_12 [style="solid"]; // Block1_12 [fillcolor="#FF746C", style=filled, label="\ @@ -131,31 +131,31 @@ // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13; (9, max 17)\nLiveIn: phi1[1], v1[1], v3[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: v3[1]\l\nv7 := eq(0x03, v3)\l\ +// Block 13; (9, max 17)\nLiveIn: phi5[1], v1[1], v7[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: v7[1]\l\nv32 := eq(0x03, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit [label="{ If v32 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15; (10, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0808, 0x08)\l\ +// Block 15; (10, max 14)\nLiveIn: phi5[1], v1[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0808, 0x08)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16; (15, max 17)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nv8 := mload(v1)\l\ +// Block 16; (15, max 17)\nLiveIn: phi5[1], v1[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nv37 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit [label="{ If v37 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5; (11, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0b0b, 0x0b)\l\ +// Block 5; (11, max 14)\nLiveIn: phi5[1], v1[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0b0b, 0x0b)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; @@ -167,30 +167,30 @@ // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18; (17, max 17)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0a0a, 0x0a)\l\ +// Block 18; (17, max 17)\nLiveIn: phi5[1], v1[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0a0a, 0x0a)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3; (12, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: v9[1], v1[1], v0[1]\l\nUsed: phi1[1]\l\nv9 := add(0x01, phi1)\l\ -// v10 := calldataload(v9)\l\ +// Block 3; (12, max 14)\nLiveIn: phi5[1], v1[1], v0[1]\l\ +// LiveOut: v61[1], v1[1], v0[1]\l\nUsed: phi5[1]\l\nv61 := add(0x01, phi5)\l\ +// v62 := calldataload(v61)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v10 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit [label="{ If v62 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v9[1]\l\ -// LiveOut: \l\nUsed: v9[1]\l\nsstore(v9, 0x00)\l\ +// Block 20; (13, max 13)\nLiveIn: v61[1]\l\ +// LiveOut: \l\nUsed: v61[1]\l\nsstore(v61, 0x00)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0x00]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v9[1], v1[1], v0[1]\l\ -// LiveOut: v9[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ +// Block 21; (14, max 14)\nLiveIn: v61[1], v1[1], v0[1]\l\ +// LiveOut: v61[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/ssa/controlFlowGraph/complex2.yul b/test/libyul/ssa/controlFlowGraph/complex2.yul index dccc91e59..ceb645374 100644 --- a/test/libyul/ssa/controlFlowGraph/complex2.yul +++ b/test/libyul/ssa/controlFlowGraph/complex2.yul @@ -61,16 +61,16 @@ // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ // LiveOut: \l\nUsed: \l\nsstore(0x01, 0x01)\l\ -// v0 := f(0x02, 0x01)\l\ -// pop(v0)\l\ -// v1 := sload(0x00)\l\ -// v2 := add(v1, 0x05)\l\ -// v3 := sload(0x04)\l\ -// v4 := f(v3, v2)\l\ -// sstore(v4, v2)\l\ -// v5 := sload(0x05)\l\ -// v6 := f(v5, v4)\l\ -// sstore(v6, 0x01)\l\ +// v3 := f(0x02, 0x01)\l\ +// pop(v3)\l\ +// v6 := sload(0x00)\l\ +// v8 := add(v6, 0x05)\l\ +// v10 := sload(0x04)\l\ +// v11 := f(v10, v8)\l\ +// sstore(v11, v8)\l\ +// v13 := sload(0x05)\l\ +// v14 := f(v13, v11)\l\ +// sstore(v14, 0x01)\l\ // "]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; @@ -84,24 +84,24 @@ // Block1_0Exit [label="Jump" shape=oval]; // Block1_0Exit -> Block1_1 [style="solid"]; // Block1_1 [label="\ -// Block 1; (1, max 17)\nLiveIn: phi1[4], v1[1], v0[1]\l\ -// LiveOut: phi1[2], v1[1], v0[1]\l\nUsed: phi1[2]\l\nphi1 := φ(\l\ +// Block 1; (1, max 17)\nLiveIn: phi5[4], v1[1], v0[1]\l\ +// LiveOut: phi5[2], v1[1], v0[1]\l\nUsed: phi5[2]\l\nphi5 := φ(\l\ // Block 0 => 0x2a,\l\ -// Block 21 => v9\l\ +// Block 21 => v61\l\ // )\l\ -// v2 := lt(v0, phi1)\l\ +// v6 := lt(v0, phi5)\l\ // "]; // Block1_1 -> Block1_1Exit; -// Block1_1Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_1Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_1Exit:0 -> Block1_4 [style="solid"]; // Block1_1Exit:1 -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// Block 2; (2, max 17)\nLiveIn: phi1[2], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v3[3], v0[1]\l\nUsed: phi1[1]\l\nv3 := mload(phi1)\l\ -// v4 := eq(0x00, v3)\l\ +// Block 2; (2, max 17)\nLiveIn: phi5[2], v1[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v7[3], v0[1]\l\nUsed: phi5[1]\l\nv7 := mload(phi5)\l\ +// v8 := eq(0x00, v7)\l\ // "]; // Block1_2 -> Block1_2Exit; -// Block1_2Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_2Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_2Exit:0 -> Block1_7 [style="solid"]; // Block1_2Exit:1 -> Block1_6 [style="solid"]; // Block1_4 [label="\ @@ -118,11 +118,11 @@ // Block1_6Exit [label="Jump" shape=oval]; // Block1_6Exit -> Block1_4 [style="solid"]; // Block1_7 [label="\ -// Block 7; (5, max 17)\nLiveIn: phi1[1], v1[1], v3[3], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v3[2], v0[1]\l\nUsed: v3[1]\l\nv5 := eq(0x01, v3)\l\ +// Block 7; (5, max 17)\nLiveIn: phi5[1], v1[1], v7[3], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v7[2], v0[1]\l\nUsed: v7[1]\l\nv16 := eq(0x01, v7)\l\ // "]; // Block1_7 -> Block1_7Exit; -// Block1_7Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_7Exit [label="{ If v16 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_7Exit:0 -> Block1_10 [style="solid"]; // Block1_7Exit:1 -> Block1_9 [style="solid"]; // Block1_9 [label="\ @@ -132,11 +132,11 @@ // Block1_9Exit [label="FunctionReturn[0x00]"]; // Block1_9 -> Block1_9Exit; // Block1_10 [label="\ -// Block 10; (7, max 17)\nLiveIn: phi1[1], v1[1], v3[2], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v3[1], v0[1]\l\nUsed: v3[1]\l\nv6 := eq(0x02, v3)\l\ +// Block 10; (7, max 17)\nLiveIn: phi5[1], v1[1], v7[2], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v7[1], v0[1]\l\nUsed: v7[1]\l\nv24 := eq(0x02, v7)\l\ // "]; // Block1_10 -> Block1_10Exit; -// Block1_10Exit [label="{ If v6 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_10Exit [label="{ If v24 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_10Exit:0 -> Block1_13 [style="solid"]; // Block1_10Exit:1 -> Block1_12 [style="solid"]; // Block1_12 [fillcolor="#FF746C", style=filled, label="\ @@ -147,31 +147,31 @@ // Block1_12Exit [label="Terminated"]; // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ -// Block 13; (9, max 17)\nLiveIn: phi1[1], v1[1], v3[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: v3[1]\l\nv7 := eq(0x03, v3)\l\ +// Block 13; (9, max 17)\nLiveIn: phi5[1], v1[1], v7[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: v7[1]\l\nv32 := eq(0x03, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit [label="{ If v32 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ -// Block 15; (10, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0808, 0x08)\l\ +// Block 15; (10, max 14)\nLiveIn: phi5[1], v1[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0808, 0x08)\l\ // "]; // Block1_15 -> Block1_15Exit [arrowhead=none]; // Block1_15Exit [label="Jump" shape=oval]; // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ -// Block 16; (15, max 17)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nv8 := mload(v1)\l\ +// Block 16; (15, max 17)\nLiveIn: phi5[1], v1[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nv37 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit [label="{ If v37 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ -// Block 5; (11, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0b0b, 0x0b)\l\ +// Block 5; (11, max 14)\nLiveIn: phi5[1], v1[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0b0b, 0x0b)\l\ // "]; // Block1_5 -> Block1_5Exit [arrowhead=none]; // Block1_5Exit [label="Jump" shape=oval]; @@ -183,30 +183,30 @@ // Block1_17Exit [label="Terminated"]; // Block1_17 -> Block1_17Exit; // Block1_18 [label="\ -// Block 18; (17, max 17)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: phi1[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0a0a, 0x0a)\l\ +// Block 18; (17, max 17)\nLiveIn: phi5[1], v1[1], v0[1]\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0x0a0a, 0x0a)\l\ // "]; // Block1_18 -> Block1_18Exit [arrowhead=none]; // Block1_18Exit [label="Jump" shape=oval]; // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ -// Block 3; (12, max 14)\nLiveIn: phi1[1], v1[1], v0[1]\l\ -// LiveOut: v9[1], v1[1], v0[1]\l\nUsed: phi1[1]\l\nv9 := add(0x01, phi1)\l\ -// v10 := calldataload(v9)\l\ +// Block 3; (12, max 14)\nLiveIn: phi5[1], v1[1], v0[1]\l\ +// LiveOut: v61[1], v1[1], v0[1]\l\nUsed: phi5[1]\l\nv61 := add(0x01, phi5)\l\ +// v62 := calldataload(v61)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v10 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit [label="{ If v62 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v9[1]\l\ -// LiveOut: \l\nUsed: v9[1]\l\nsstore(v9, 0x00)\l\ +// Block 20; (13, max 13)\nLiveIn: v61[1]\l\ +// LiveOut: \l\nUsed: v61[1]\l\nsstore(v61, 0x00)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0x00]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v9[1], v1[1], v0[1]\l\ -// LiveOut: v9[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ +// Block 21; (14, max 14)\nLiveIn: v61[1], v1[1], v0[1]\l\ +// LiveOut: v61[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/ssa/controlFlowGraph/default_initialized_variable.yul b/test/libyul/ssa/controlFlowGraph/default_initialized_variable.yul index 56e180fe4..81f78dc9c 100644 --- a/test/libyul/ssa/controlFlowGraph/default_initialized_variable.yul +++ b/test/libyul/ssa/controlFlowGraph/default_initialized_variable.yul @@ -15,10 +15,10 @@ // Entry -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: \l\nUsed: \l\nv0 := mload(0x2a)\l\ +// LiveOut: \l\nUsed: \l\nv2 := mload(0x2a)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_0Exit:0 -> Block0_2 [style="solid"]; // Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ @@ -28,12 +28,12 @@ // Block0_1Exit [label="Jump" shape=oval]; // Block0_1Exit -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: phi0[3]\l\ -// LiveOut: \l\nUsed: phi0[3]\l\nphi0 := φ(\l\ +// Block 2; (2, max 2)\nLiveIn: phi4[3]\l\ +// LiveOut: \l\nUsed: phi4[3]\l\nphi4 := φ(\l\ // Block 0 => 0x00,\l\ // Block 1 => 0x05\l\ // )\l\ -// sstore(phi0, phi0)\l\ +// sstore(phi4, phi4)\l\ // "]; // Block0_2Exit [label="MainExit"]; // Block0_2 -> Block0_2Exit; diff --git a/test/libyul/ssa/controlFlowGraph/function.yul b/test/libyul/ssa/controlFlowGraph/function.yul index bcc75c975..d9832b064 100644 --- a/test/libyul/ssa/controlFlowGraph/function.yul +++ b/test/libyul/ssa/controlFlowGraph/function.yul @@ -28,7 +28,7 @@ // Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nUsed: \l\nv0, v1 := i()\l\ +// LiveOut: \l\nUsed: \l\nv0, v0.1 := i()\l\ // h(v0)\l\ // "]; // Block0_0Exit [label="Terminated"]; @@ -38,10 +38,10 @@ // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 0)\nLiveIn: v0[2], v1[1]\l\ -// LiveOut: v3[1]\l\nUsed: v0[2], v1[1]\l\nv2 := add(v1, v0)\l\ -// v3 := sub(v0, v2)\l\ +// LiveOut: v4[1]\l\nUsed: v0[2], v1[1]\l\nv3 := add(v1, v0)\l\ +// v4 := sub(v0, v3)\l\ // "]; -// Block1_0Exit [label="FunctionReturn[v3]"]; +// Block1_0Exit [label="FunctionReturn[v4]"]; // Block1_0 -> Block1_0Exit; // FunctionEntry_g_0 [label="function g: // g()"]; @@ -57,8 +57,8 @@ // FunctionEntry_h_0 -> Block3_0; // Block3_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: v0[1]\l\ -// LiveOut: \l\nUsed: v0[1]\l\nv1 := f(0x00, v0)\l\ -// h(v1)\l\ +// LiveOut: \l\nUsed: v0[1]\l\nv2 := f(0x00, v0)\l\ +// h(v2)\l\ // "]; // Block3_0Exit [label="Terminated"]; // Block3_0 -> Block3_0Exit; diff --git a/test/libyul/ssa/controlFlowGraph/if.yul b/test/libyul/ssa/controlFlowGraph/if.yul index f884d3348..038c196da 100644 --- a/test/libyul/ssa/controlFlowGraph/if.yul +++ b/test/libyul/ssa/controlFlowGraph/if.yul @@ -16,28 +16,28 @@ // Entry -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: v0[1]\l\nUsed: \l\nv0 := calldataload(0x03)\l\ -// v1 := mload(0x2a)\l\ +// LiveOut: v1[1]\l\nUsed: \l\nv1 := calldataload(0x03)\l\ +// v3 := mload(0x2a)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_0Exit:0 -> Block0_2 [style="solid"]; // Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v2[1]\l\nUsed: \l\nv2 := calldataload(0x4d)\l\ +// LiveOut: v5[1]\l\nUsed: \l\nv5 := calldataload(0x4d)\l\ // "]; // Block0_1 -> Block0_1Exit [arrowhead=none]; // Block0_1Exit [label="Jump" shape=oval]; // Block0_1Exit -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: phi0[2]\l\ -// LiveOut: \l\nUsed: phi0[2]\l\nphi0 := φ(\l\ -// Block 0 => v0,\l\ -// Block 1 => v2\l\ +// Block 2; (2, max 2)\nLiveIn: phi6[2]\l\ +// LiveOut: \l\nUsed: phi6[2]\l\nphi6 := φ(\l\ +// Block 0 => v1,\l\ +// Block 1 => v5\l\ // )\l\ -// v3 := calldataload(phi0)\l\ -// sstore(0x00, v3)\l\ +// v9 := calldataload(phi6)\l\ +// sstore(0x00, v9)\l\ // "]; // Block0_2Exit [label="MainExit"]; // Block0_2 -> Block0_2Exit; diff --git a/test/libyul/ssa/controlFlowGraph/if_const.yul b/test/libyul/ssa/controlFlowGraph/if_const.yul index f8bab3f48..48b240a17 100644 --- a/test/libyul/ssa/controlFlowGraph/if_const.yul +++ b/test/libyul/ssa/controlFlowGraph/if_const.yul @@ -21,10 +21,10 @@ // Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nUsed: \l\nv0 := calldataload(0x03)\l\ -// v1 := calldataload(0x2a)\l\ -// v2 := calldataload(v1)\l\ -// sstore(0x00, v2)\l\ +// LiveOut: \l\nUsed: \l\nv1 := calldataload(0x03)\l\ +// v3 := calldataload(0x2a)\l\ +// v4 := calldataload(v3)\l\ +// sstore(0x00, v4)\l\ // "]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; diff --git a/test/libyul/ssa/controlFlowGraph/nested_for.yul b/test/libyul/ssa/controlFlowGraph/nested_for.yul index 0060ee30f..e3c1ef7e6 100644 --- a/test/libyul/ssa/controlFlowGraph/nested_for.yul +++ b/test/libyul/ssa/controlFlowGraph/nested_for.yul @@ -32,20 +32,20 @@ // Block0_0Exit [label="Jump" shape=oval]; // Block0_0Exit -> Block0_1 [style="solid"]; // Block0_1 [fillcolor="#FF746C", style=filled, label="\ -// Block 1; (1, max 24)\nLiveIn: phi0[3]\l\ -// LiveOut: phi0[1]\l\nUsed: phi0[2]\l\nphi0 := φ(\l\ +// Block 1; (1, max 24)\nLiveIn: phi2[3]\l\ +// LiveOut: phi2[1]\l\nUsed: phi2[2]\l\nphi2 := φ(\l\ // Block 0 => 0x00,\l\ -// Block 3 => v15\l\ +// Block 3 => v78\l\ // )\l\ -// v0 := lt(0x03, phi0)\l\ +// v3 := lt(0x03, phi2)\l\ // "]; // Block0_1 -> Block0_1Exit; -// Block0_1Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_1Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_1Exit:0 -> Block0_4 [style="solid"]; // Block0_1Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// Block 2; (2, max 23)\nLiveIn: phi0[1]\l\ -// LiveOut: phi0[1]\l\nUsed: \l\n"]; +// Block 2; (2, max 23)\nLiveIn: phi2[1]\l\ +// LiveOut: phi2[1]\l\nUsed: \l\n"]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; // Block0_2Exit -> Block0_5 [style="solid"]; @@ -55,166 +55,166 @@ // Block0_4Exit [label="MainExit"]; // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ -// Block 5; (3, max 23)\nLiveIn: phi1[3], phi0[1]\l\ -// LiveOut: phi1[1], phi0[1]\l\nUsed: phi1[2]\l\nphi1 := φ(\l\ +// Block 5; (3, max 23)\nLiveIn: phi4[3], phi2[1]\l\ +// LiveOut: phi4[1], phi2[1]\l\nUsed: phi4[2]\l\nphi4 := φ(\l\ // Block 2 => 0x00,\l\ -// Block 7 => v14\l\ +// Block 7 => v73\l\ // )\l\ -// v1 := lt(0x03, phi1)\l\ +// v5 := lt(0x03, phi4)\l\ // "]; // Block0_5 -> Block0_5Exit; -// Block0_5Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_5Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_5Exit:0 -> Block0_8 [style="solid"]; // Block0_5Exit:1 -> Block0_6 [style="solid"]; // Block0_6 [label="\ -// Block 6; (4, max 21)\nLiveIn: phi1[1], phi0[1]\l\ -// LiveOut: phi1[1], phi0[1]\l\nUsed: \l\n"]; +// Block 6; (4, max 21)\nLiveIn: phi4[1], phi2[1]\l\ +// LiveOut: phi4[1], phi2[1]\l\nUsed: \l\n"]; // Block0_6 -> Block0_6Exit [arrowhead=none]; // Block0_6Exit [label="Jump" shape=oval]; // Block0_6Exit -> Block0_9 [style="solid"]; // Block0_8 [label="\ -// Block 8; (22, max 23)\nLiveIn: phi0[1]\l\ -// LiveOut: phi0[1]\l\nUsed: \l\n"]; +// Block 8; (22, max 23)\nLiveIn: phi2[1]\l\ +// LiveOut: phi2[1]\l\nUsed: \l\n"]; // Block0_8 -> Block0_8Exit [arrowhead=none]; // Block0_8Exit [label="Jump" shape=oval]; // Block0_8Exit -> Block0_3 [style="solid"]; // Block0_9 [label="\ -// Block 9; (5, max 21)\nLiveIn: phi2[3], phi1[1], phi0[1]\l\ -// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: phi2[2]\l\nphi2 := φ(\l\ +// Block 9; (5, max 21)\nLiveIn: phi6[3], phi4[1], phi2[1]\l\ +// LiveOut: phi6[1], phi4[1], phi2[1]\l\nUsed: phi6[2]\l\nphi6 := φ(\l\ // Block 6 => 0x00,\l\ -// Block 11 => v13\l\ +// Block 11 => v59\l\ // )\l\ -// v2 := lt(0x03, phi2)\l\ +// v7 := lt(0x03, phi6)\l\ // "]; // Block0_9 -> Block0_9Exit; -// Block0_9Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_9Exit [label="{ If v7 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_9Exit:0 -> Block0_12 [style="solid"]; // Block0_9Exit:1 -> Block0_10 [style="solid"]; // Block0_3 [label="\ -// Block 3; (23, max 23)\nLiveIn: phi0[1]\l\ -// LiveOut: v15[1]\l\nUsed: phi0[1]\l\nv15 := add(0x01, phi0)\l\ +// Block 3; (23, max 23)\nLiveIn: phi2[1]\l\ +// LiveOut: v78[1]\l\nUsed: phi2[1]\l\nv78 := add(0x01, phi2)\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; // Block0_3Exit -> Block0_1 [style="dashed"]; // Block0_10 [label="\ -// Block 10; (6, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv3 := mload(0x00)\l\ +// Block 10; (6, max 19)\nLiveIn: phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: phi6[1], phi4[1], phi2[1]\l\nUsed: \l\nv8 := mload(0x00)\l\ // "]; // Block0_10 -> Block0_10Exit; -// Block0_10Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_10Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_10Exit:0 -> Block0_14 [style="solid"]; // Block0_10Exit:1 -> Block0_13 [style="solid"]; // Block0_12 [label="\ -// Block 12; (20, max 21)\nLiveIn: phi1[1], phi0[1]\l\ -// LiveOut: phi1[1], phi0[1]\l\nUsed: \l\n"]; +// Block 12; (20, max 21)\nLiveIn: phi4[1], phi2[1]\l\ +// LiveOut: phi4[1], phi2[1]\l\nUsed: \l\n"]; // Block0_12 -> Block0_12Exit [arrowhead=none]; // Block0_12Exit [label="Jump" shape=oval]; // Block0_12Exit -> Block0_7 [style="solid"]; // Block0_13 [label="\ -// Block 13; (7, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\n"]; +// Block 13; (7, max 19)\nLiveIn: phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: phi6[1], phi4[1], phi2[1]\l\nUsed: \l\n"]; // Block0_13 -> Block0_13Exit [arrowhead=none]; // Block0_13Exit [label="Jump" shape=oval]; // Block0_13Exit -> Block0_15 [style="solid"]; // Block0_14 [label="\ -// Block 14; (12, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\nv8 := mload(0x01)\l\ +// Block 14; (12, max 19)\nLiveIn: phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: phi6[1], phi4[1], phi2[1]\l\nUsed: \l\nv29 := mload(0x01)\l\ // "]; // Block0_14 -> Block0_14Exit; -// Block0_14Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_14Exit [label="{ If v29 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_14Exit:0 -> Block0_20 [style="solid"]; // Block0_14Exit:1 -> Block0_19 [style="solid"]; // Block0_7 [label="\ -// Block 7; (21, max 21)\nLiveIn: phi1[1], phi0[1]\l\ -// LiveOut: v14[1], phi0[1]\l\nUsed: phi1[1]\l\nv14 := add(0x01, phi1)\l\ +// Block 7; (21, max 21)\nLiveIn: phi4[1], phi2[1]\l\ +// LiveOut: v73[1], phi2[1]\l\nUsed: phi4[1]\l\nv73 := add(0x01, phi4)\l\ // "]; // Block0_7 -> Block0_7Exit [arrowhead=none]; // Block0_7Exit [label="Jump" shape=oval]; // Block0_7Exit -> Block0_5 [style="dashed"]; // Block0_15 [label="\ -// Block 15; (8, max 19)\nLiveIn: phi3[4], phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi3[2], phi2[1], phi1[1], phi0[1]\l\nUsed: phi3[2]\l\nphi3 := φ(\l\ +// Block 15; (8, max 19)\nLiveIn: phi9[4], phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: phi9[2], phi6[1], phi4[1], phi2[1]\l\nUsed: phi9[2]\l\nphi9 := φ(\l\ // Block 13 => 0x00,\l\ -// Block 17 => v7\l\ +// Block 17 => v18\l\ // )\l\ -// v4 := lt(0x03, phi3)\l\ +// v10 := lt(0x03, phi9)\l\ // "]; // Block0_15 -> Block0_15Exit; -// Block0_15Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_15Exit [label="{ If v10 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_15Exit:0 -> Block0_18 [style="solid"]; // Block0_15Exit:1 -> Block0_16 [style="solid"]; // Block0_19 [label="\ -// Block 19; (13, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\n"]; +// Block 19; (13, max 19)\nLiveIn: phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: phi6[1], phi4[1], phi2[1]\l\nUsed: \l\n"]; // Block0_19 -> Block0_19Exit [arrowhead=none]; // Block0_19Exit [label="Jump" shape=oval]; // Block0_19Exit -> Block0_21 [style="solid"]; // Block0_20 [label="\ -// Block 20; (18, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\n"]; +// Block 20; (18, max 19)\nLiveIn: phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: phi6[1], phi4[1], phi2[1]\l\nUsed: \l\n"]; // Block0_20 -> Block0_20Exit [arrowhead=none]; // Block0_20Exit [label="Jump" shape=oval]; // Block0_20Exit -> Block0_11 [style="solid"]; // Block0_16 [label="\ -// Block 16; (9, max 10)\nLiveIn: phi3[2], phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi3[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi3[1]\l\nv5 := add(phi1, phi0)\l\ -// v6 := add(phi2, v5)\l\ -// sstore(v6, phi3)\l\ +// Block 16; (9, max 10)\nLiveIn: phi9[2], phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: phi9[1], phi6[1], phi4[1], phi2[1]\l\nUsed: phi9[1]\l\nv14 := add(phi4, phi2)\l\ +// v15 := add(phi6, v14)\l\ +// sstore(v15, phi9)\l\ // "]; // Block0_16 -> Block0_16Exit [arrowhead=none]; // Block0_16Exit [label="Jump" shape=oval]; // Block0_16Exit -> Block0_17 [style="solid"]; // Block0_18 [label="\ -// Block 18; (11, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\n"]; +// Block 18; (11, max 19)\nLiveIn: phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: phi6[1], phi4[1], phi2[1]\l\nUsed: \l\n"]; // Block0_18 -> Block0_18Exit [arrowhead=none]; // Block0_18Exit [label="Jump" shape=oval]; // Block0_18Exit -> Block0_14 [style="solid"]; // Block0_21 [label="\ -// Block 21; (14, max 19)\nLiveIn: phi9[4], phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi9[2], phi2[1], phi1[1], phi0[1]\l\nUsed: phi9[2]\l\nphi9 := φ(\l\ +// Block 21; (14, max 19)\nLiveIn: phi30[4], phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: phi30[2], phi6[1], phi4[1], phi2[1]\l\nUsed: phi30[2]\l\nphi30 := φ(\l\ // Block 19 => 0x00,\l\ -// Block 23 => v12\l\ +// Block 23 => v38\l\ // )\l\ -// v9 := lt(0x03, phi9)\l\ +// v31 := lt(0x03, phi30)\l\ // "]; // Block0_21 -> Block0_21Exit; -// Block0_21Exit [label="{ If v9 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_21Exit [label="{ If v31 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_21Exit:0 -> Block0_24 [style="solid"]; // Block0_21Exit:1 -> Block0_22 [style="solid"]; // Block0_11 [label="\ -// Block 11; (19, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: v13[1], phi1[1], phi0[1]\l\nUsed: phi2[1]\l\nv13 := add(0x01, phi2)\l\ +// Block 11; (19, max 19)\nLiveIn: phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: v59[1], phi4[1], phi2[1]\l\nUsed: phi6[1]\l\nv59 := add(0x01, phi6)\l\ // "]; // Block0_11 -> Block0_11Exit [arrowhead=none]; // Block0_11Exit [label="Jump" shape=oval]; // Block0_11Exit -> Block0_9 [style="dashed"]; // Block0_17 [label="\ -// Block 17; (10, max 10)\nLiveIn: phi3[1], phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: v7[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi3[1]\l\nv7 := add(0x01, phi3)\l\ +// Block 17; (10, max 10)\nLiveIn: phi9[1], phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: v18[1], phi6[1], phi4[1], phi2[1]\l\nUsed: phi9[1]\l\nv18 := add(0x01, phi9)\l\ // "]; // Block0_17 -> Block0_17Exit [arrowhead=none]; // Block0_17Exit [label="Jump" shape=oval]; // Block0_17Exit -> Block0_15 [style="dashed"]; // Block0_22 [label="\ -// Block 22; (15, max 16)\nLiveIn: phi9[2], phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi9[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi9[1]\l\nv10 := add(phi1, phi0)\l\ -// v11 := add(phi2, v10)\l\ -// sstore(v11, phi9)\l\ +// Block 22; (15, max 16)\nLiveIn: phi30[2], phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: phi30[1], phi6[1], phi4[1], phi2[1]\l\nUsed: phi30[1]\l\nv35 := add(phi4, phi2)\l\ +// v36 := add(phi6, v35)\l\ +// sstore(v36, phi30)\l\ // "]; // Block0_22 -> Block0_22Exit [arrowhead=none]; // Block0_22Exit [label="Jump" shape=oval]; // Block0_22Exit -> Block0_23 [style="solid"]; // Block0_24 [label="\ -// Block 24; (17, max 19)\nLiveIn: phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: phi2[1], phi1[1], phi0[1]\l\nUsed: \l\n"]; +// Block 24; (17, max 19)\nLiveIn: phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: phi6[1], phi4[1], phi2[1]\l\nUsed: \l\n"]; // Block0_24 -> Block0_24Exit [arrowhead=none]; // Block0_24Exit [label="Jump" shape=oval]; // Block0_24Exit -> Block0_20 [style="solid"]; // Block0_23 [label="\ -// Block 23; (16, max 16)\nLiveIn: phi9[1], phi2[1], phi1[1], phi0[1]\l\ -// LiveOut: v12[1], phi2[1], phi1[1], phi0[1]\l\nUsed: phi9[1]\l\nv12 := add(0x01, phi9)\l\ +// Block 23; (16, max 16)\nLiveIn: phi30[1], phi6[1], phi4[1], phi2[1]\l\ +// LiveOut: v38[1], phi6[1], phi4[1], phi2[1]\l\nUsed: phi30[1]\l\nv38 := add(0x01, phi30)\l\ // "]; // Block0_23 -> Block0_23Exit [arrowhead=none]; // Block0_23Exit [label="Jump" shape=oval]; diff --git a/test/libyul/ssa/controlFlowGraph/nested_function.yul b/test/libyul/ssa/controlFlowGraph/nested_function.yul index 6fcd0a114..607397815 100644 --- a/test/libyul/ssa/controlFlowGraph/nested_function.yul +++ b/test/libyul/ssa/controlFlowGraph/nested_function.yul @@ -47,20 +47,20 @@ // FunctionEntry_f_0 -> Block1_0; // Block1_0 [label="\ // Block 0; (0, max 0)\nLiveIn: v0[2], v1[1]\l\ -// LiveOut: v3[1]\l\nUsed: v0[2], v1[1]\l\nv2 := add(v1, v0)\l\ -// v3 := sub(v0, v2)\l\ +// LiveOut: v4[1]\l\nUsed: v0[2], v1[1]\l\nv3 := add(v1, v0)\l\ +// v4 := sub(v0, v3)\l\ // "]; -// Block1_0Exit [label="FunctionReturn[v3]"]; +// Block1_0Exit [label="FunctionReturn[v4]"]; // Block1_0 -> Block1_0Exit; // FunctionEntry_g_0 [label="function g: // g()"]; // FunctionEntry_g_0 -> Block2_0; // Block2_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nUsed: \l\nv0 := v()\l\ -// v1 := f(0x02, v0)\l\ -// v2 := z()\l\ -// sstore(v1, v2)\l\ +// LiveOut: \l\nUsed: \l\nv1 := v()\l\ +// v2 := f(0x02, v1)\l\ +// v3 := z()\l\ +// sstore(v2, v3)\l\ // "]; // Block2_0Exit [label="FunctionReturn[]"]; // Block2_0 -> Block2_0Exit; @@ -69,72 +69,72 @@ // FunctionEntry_cycle1_0 -> Block3_0; // Block3_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: \l\nUsed: \l\nv0 := mload(0x03)\l\ +// LiveOut: \l\nUsed: \l\nv2 := mload(0x03)\l\ // "]; // Block3_0 -> Block3_0Exit; -// Block3_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block3_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block3_0Exit:0 -> Block3_2 [style="solid"]; // Block3_0Exit:1 -> Block3_1 [style="solid"]; // Block3_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v1[1]\l\nUsed: \l\nv1 := cycle2()\l\ +// LiveOut: v3[1]\l\nUsed: \l\nv3 := cycle2()\l\ // "]; // Block3_1 -> Block3_1Exit [arrowhead=none]; // Block3_1Exit [label="Jump" shape=oval]; // Block3_1Exit -> Block3_2 [style="solid"]; // Block3_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: phi0[3]\l\ -// LiveOut: phi0[1]\l\nUsed: phi0[2]\l\nphi0 := φ(\l\ +// Block 2; (2, max 2)\nLiveIn: phi4[3]\l\ +// LiveOut: phi4[1]\l\nUsed: phi4[2]\l\nphi4 := φ(\l\ // Block 0 => 0x00,\l\ -// Block 1 => v1\l\ +// Block 1 => v3\l\ // )\l\ // "]; -// Block3_2Exit [label="FunctionReturn[phi0]"]; +// Block3_2Exit [label="FunctionReturn[phi4]"]; // Block3_2 -> Block3_2Exit; // FunctionEntry_cycle2_0 [label="function cycle2: // [1 returns] := cycle2()"]; // FunctionEntry_cycle2_0 -> Block4_0; // Block4_0 [label="\ // Block 0; (0, max 2)\nLiveIn: \l\ -// LiveOut: \l\nUsed: \l\nv0 := mload(0x04)\l\ +// LiveOut: \l\nUsed: \l\nv2 := mload(0x04)\l\ // "]; // Block4_0 -> Block4_0Exit; -// Block4_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block4_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block4_0Exit:0 -> Block4_2 [style="solid"]; // Block4_0Exit:1 -> Block4_1 [style="solid"]; // Block4_1 [label="\ // Block 1; (1, max 2)\nLiveIn: \l\ -// LiveOut: v1[1]\l\nUsed: \l\nv1 := cycle1()\l\ +// LiveOut: v3[1]\l\nUsed: \l\nv3 := cycle1()\l\ // "]; // Block4_1 -> Block4_1Exit [arrowhead=none]; // Block4_1Exit [label="Jump" shape=oval]; // Block4_1Exit -> Block4_2 [style="solid"]; // Block4_2 [label="\ -// Block 2; (2, max 2)\nLiveIn: phi0[3]\l\ -// LiveOut: phi0[1]\l\nUsed: phi0[2]\l\nphi0 := φ(\l\ +// Block 2; (2, max 2)\nLiveIn: phi4[3]\l\ +// LiveOut: phi4[1]\l\nUsed: phi4[2]\l\nphi4 := φ(\l\ // Block 0 => 0x00,\l\ -// Block 1 => v1\l\ +// Block 1 => v3\l\ // )\l\ // "]; -// Block4_2Exit [label="FunctionReturn[phi0]"]; +// Block4_2Exit [label="FunctionReturn[phi4]"]; // Block4_2 -> Block4_2Exit; // FunctionEntry_z_0 [label="function z: // [1 returns] := z()"]; // FunctionEntry_z_0 -> Block5_0; // Block5_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v0[1]\l\nUsed: \l\nv0 := w()\l\ +// LiveOut: v1[1]\l\nUsed: \l\nv1 := w()\l\ // "]; -// Block5_0Exit [label="FunctionReturn[v0]"]; +// Block5_0Exit [label="FunctionReturn[v1]"]; // Block5_0 -> Block5_0Exit; // FunctionEntry_v_0 [label="function v: // [1 returns] := v()"]; // FunctionEntry_v_0 -> Block6_0; // Block6_0 [label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: v0[1]\l\nUsed: \l\nv0 := w()\l\ +// LiveOut: v1[1]\l\nUsed: \l\nv1 := w()\l\ // "]; -// Block6_0Exit [label="FunctionReturn[v0]"]; +// Block6_0Exit [label="FunctionReturn[v1]"]; // Block6_0 -> Block6_0Exit; // FunctionEntry_w_0 [label="function w: // [1 returns] := w()"]; diff --git a/test/libyul/ssa/controlFlowGraph/switch.yul b/test/libyul/ssa/controlFlowGraph/switch.yul index 3114bbca3..2aa31f0e3 100644 --- a/test/libyul/ssa/controlFlowGraph/switch.yul +++ b/test/libyul/ssa/controlFlowGraph/switch.yul @@ -23,50 +23,50 @@ // Entry -> Block0_0; // Block0_0 [label="\ // Block 0; (0, max 5)\nLiveIn: \l\ -// LiveOut: v1[1]\l\nUsed: \l\nv0 := calldataload(0x03)\l\ -// v1 := sload(0x00)\l\ -// v2 := eq(0x00, v1)\l\ +// LiveOut: v3[1]\l\nUsed: \l\nv1 := calldataload(0x03)\l\ +// v3 := sload(0x00)\l\ +// v4 := eq(0x00, v3)\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_0Exit:0 -> Block0_3 [style="solid"]; // Block0_0Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ // Block 2; (1, max 2)\nLiveIn: \l\ -// LiveOut: v3[1]\l\nUsed: \l\nv3 := calldataload(0x4d)\l\ +// LiveOut: v6[1]\l\nUsed: \l\nv6 := calldataload(0x4d)\l\ // "]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; // Block0_2Exit -> Block0_1 [style="solid"]; // Block0_3 [label="\ -// Block 3; (3, max 5)\nLiveIn: v1[1]\l\ -// LiveOut: \l\nUsed: v1[1]\l\nv4 := eq(0x01, v1)\l\ +// Block 3; (3, max 5)\nLiveIn: v3[1]\l\ +// LiveOut: \l\nUsed: v3[1]\l\nv8 := eq(0x01, v3)\l\ // "]; // Block0_3 -> Block0_3Exit; -// Block0_3Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_3Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_3Exit:0 -> Block0_5 [style="solid"]; // Block0_3Exit:1 -> Block0_4 [style="solid"]; // Block0_1 [label="\ -// Block 1; (2, max 2)\nLiveIn: phi0[2]\l\ -// LiveOut: \l\nUsed: phi0[2]\l\nphi0 := φ(\l\ -// Block 2 => v3,\l\ -// Block 4 => v5,\l\ -// Block 5 => v6\l\ +// Block 1; (2, max 2)\nLiveIn: phi13[2]\l\ +// LiveOut: \l\nUsed: phi13[2]\l\nphi13 := φ(\l\ +// Block 2 => v6,\l\ +// Block 4 => v10,\l\ +// Block 5 => v12\l\ // )\l\ -// sstore(0x00, phi0)\l\ +// sstore(0x00, phi13)\l\ // "]; // Block0_1Exit [label="MainExit"]; // Block0_1 -> Block0_1Exit; // Block0_4 [label="\ // Block 4; (4, max 4)\nLiveIn: \l\ -// LiveOut: v5[1]\l\nUsed: \l\nv5 := calldataload(0x58)\l\ +// LiveOut: v10[1]\l\nUsed: \l\nv10 := calldataload(0x58)\l\ // "]; // Block0_4 -> Block0_4Exit [arrowhead=none]; // Block0_4Exit [label="Jump" shape=oval]; // Block0_4Exit -> Block0_1 [style="solid"]; // Block0_5 [label="\ // Block 5; (5, max 5)\nLiveIn: \l\ -// LiveOut: v6[1]\l\nUsed: \l\nv6 := calldataload(0x63)\l\ +// LiveOut: v12[1]\l\nUsed: \l\nv12 := calldataload(0x63)\l\ // "]; // Block0_5 -> Block0_5Exit [arrowhead=none]; // Block0_5Exit [label="Jump" shape=oval]; diff --git a/test/libyul/ssa/controlFlowGraph/switch_const.yul b/test/libyul/ssa/controlFlowGraph/switch_const.yul index 56116eb3b..1dd9dca9b 100644 --- a/test/libyul/ssa/controlFlowGraph/switch_const.yul +++ b/test/libyul/ssa/controlFlowGraph/switch_const.yul @@ -45,10 +45,10 @@ // Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nUsed: \l\nv0 := calldataload(0x03)\l\ -// v1 := calldataload(0x58)\l\ -// v2 := calldataload(0x63)\l\ -// sstore(0x00, v2)\l\ +// LiveOut: \l\nUsed: \l\nv1 := calldataload(0x03)\l\ +// v4 := calldataload(0x58)\l\ +// v7 := calldataload(0x63)\l\ +// sstore(0x00, v7)\l\ // "]; // Block0_0Exit [label="MainExit"]; // Block0_0 -> Block0_0Exit; diff --git a/test/libyul/ssa/stackLayoutGenerator/dead_code.yul b/test/libyul/ssa/stackLayoutGenerator/dead_code.yul index c95ced760..156baf27b 100644 --- a/test/libyul/ssa/stackLayoutGenerator/dead_code.yul +++ b/test/libyul/ssa/stackLayoutGenerator/dead_code.yul @@ -22,12 +22,12 @@ // \l\ // [lit0]\l\ // calldataload\l\ -// [v0]\l\ +// [v1]\l\ // \l\ -// OUT: [v0, v0]\l\ +// OUT: [v1, v1]\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_0Exit:0 -> Block0_2 [style="solid"]; // Block0_0Exit:1 -> Block0_1 [style="solid"]; // Block0_1 [label="\ @@ -42,16 +42,16 @@ // Block0_1Exit [label="Terminated"]; // Block0_1 -> Block0_1Exit; // Block0_2 [label="\ -// IN: [v0]\l\ +// IN: [v1]\l\ // \l\ -// [v0, lit1]\l\ +// [v1, lit3]\l\ // calldataload\l\ -// [v0, v1]\l\ +// [v1, v4]\l\ // \l\ -// OUT: [v0, v1, v1]\l\ +// OUT: [v1, v4, v4]\l\ // "]; // Block0_2 -> Block0_2Exit; -// Block0_2Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_2Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_2Exit:0 -> Block0_5 [style="solid"]; // Block0_2Exit:1 -> Block0_4 [style="solid"]; // Block0_4 [label="\ @@ -66,9 +66,9 @@ // Block0_4Exit [label="Terminated"]; // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ -// IN: [v0, v1]\l\ +// IN: [v1, v4]\l\ // \l\ -// [v1, v0]\l\ +// [v4, v1]\l\ // sstore\l\ // []\l\ // \l\ diff --git a/test/libyul/ssa/stackLayoutGenerator/function.yul b/test/libyul/ssa/stackLayoutGenerator/function.yul index a668eb94f..3fc70f0f6 100644 --- a/test/libyul/ssa/stackLayoutGenerator/function.yul +++ b/test/libyul/ssa/stackLayoutGenerator/function.yul @@ -33,7 +33,7 @@ // \l\ // [FunctionCallReturnLabel[0]]\l\ // i\l\ -// [FunctionCallReturnLabel[0], v0, v1]\l\ +// [FunctionCallReturnLabel[0], v0, v0.1]\l\ // \l\ // [v0]\l\ // h\l\ @@ -51,15 +51,15 @@ // \l\ // [ReturnLabel[1], v0, v1, v0]\l\ // add\l\ -// [ReturnLabel[1], v0, v2]\l\ +// [ReturnLabel[1], v0, v3]\l\ // \l\ -// [ReturnLabel[1], v0, v2]\l\ +// [ReturnLabel[1], v0, v3]\l\ // sub\l\ -// [ReturnLabel[1], v3]\l\ +// [ReturnLabel[1], v4]\l\ // \l\ -// OUT: [v3, ReturnLabel[1]]\l\ +// OUT: [v4, ReturnLabel[1]]\l\ // "]; -// Block1_0Exit [label="FunctionReturn[v3]"]; +// Block1_0Exit [label="FunctionReturn[v4]"]; // Block1_0 -> Block1_0Exit; // FunctionEntry_g_0 [label="function g: // g()"]; @@ -81,11 +81,11 @@ // Block3_0 [label="\ // IN: [v0]\l\ // \l\ -// [FunctionCallReturnLabel[0], lit0, v0]\l\ +// [FunctionCallReturnLabel[0], lit1, v0]\l\ // f\l\ -// [FunctionCallReturnLabel[0], v1]\l\ +// [FunctionCallReturnLabel[0], v2]\l\ // \l\ -// [v1]\l\ +// [v2]\l\ // h\l\ // []\l\ // \l\ diff --git a/test/libyul/ssa/stackLayoutGenerator/multi_return.yul b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul index aa774e457..e7a5bb015 100644 --- a/test/libyul/ssa/stackLayoutGenerator/multi_return.yul +++ b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul @@ -20,17 +20,17 @@ // \l\ // [FunctionCallReturnLabel[0], lit0]\l\ // pair\l\ -// [FunctionCallReturnLabel[0], v0, v1]\l\ +// [FunctionCallReturnLabel[0], v1, v1.1]\l\ // \l\ -// [v0, v1, FunctionCallReturnLabel[1], v0]\l\ +// [v1, v1.1, FunctionCallReturnLabel[1], v1]\l\ // pair\l\ -// [v0, v1, FunctionCallReturnLabel[1], v2, v3]\l\ +// [v1, v1.1, FunctionCallReturnLabel[1], v2, v2.1]\l\ // \l\ -// [JUNK, v1, v3, v2]\l\ +// [JUNK, v1.1, v2.1, v2]\l\ // add\l\ -// [JUNK, v1, v4]\l\ +// [JUNK, v1.1, v3]\l\ // \l\ -// [JUNK, v4, v1]\l\ +// [JUNK, v3, v1.1]\l\ // sstore\l\ // [JUNK]\l\ // \l\ @@ -44,16 +44,16 @@ // Block1_0 [label="\ // IN: [ReturnLabel[1], v0]\l\ // \l\ -// [ReturnLabel[1], v0, lit1, v0]\l\ +// [ReturnLabel[1], v0, lit2, v0]\l\ // add\l\ -// [ReturnLabel[1], v0, v1]\l\ +// [ReturnLabel[1], v0, v3]\l\ // \l\ -// [ReturnLabel[1], v1, lit2, v0]\l\ +// [ReturnLabel[1], v3, lit4, v0]\l\ // add\l\ -// [ReturnLabel[1], v1, v2]\l\ +// [ReturnLabel[1], v3, v5]\l\ // \l\ -// OUT: [v1, v2, ReturnLabel[1]]\l\ +// OUT: [v3, v5, ReturnLabel[1]]\l\ // "]; -// Block1_0Exit [label="FunctionReturn[v1, v2]"]; +// Block1_0Exit [label="FunctionReturn[v3, v5]"]; // Block1_0 -> Block1_0Exit; // } diff --git a/test/libyul/ssa/stackLayoutGenerator/nested_for.yul b/test/libyul/ssa/stackLayoutGenerator/nested_for.yul index 0d37b16e5..5220d2cef 100644 --- a/test/libyul/ssa/stackLayoutGenerator/nested_for.yul +++ b/test/libyul/ssa/stackLayoutGenerator/nested_for.yul @@ -24,30 +24,30 @@ // Block0_0Exit [label="Jump" shape=oval]; // Block0_0Exit -> Block0_1 [style="solid"]; // Block0_1 [label="\ -// IN: [phi0, phi4]\l\ +// IN: [phi2, phi16]\l\ // \l\ -// [phi0, phi4, lit1, phi0]\l\ +// [phi2, phi16, lit1, phi2]\l\ // lt\l\ -// [phi0, phi4, v0]\l\ +// [phi2, phi16, v3]\l\ // \l\ -// OUT: [phi0, phi4, v0]\l\ +// OUT: [phi2, phi16, v3]\l\ // "]; // Block0_1 -> Block0_1Exit; -// Block0_1Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_1Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_1Exit:0 -> Block0_4 [style="solid"]; // Block0_1Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// IN: [phi0, phi4]\l\ +// IN: [phi2, phi16]\l\ // \l\ -// OUT: [phi0, phi4]\l\ +// OUT: [phi2, phi16]\l\ // "]; // Block0_2 -> Block0_2Exit [arrowhead=none]; // Block0_2Exit [label="Jump" shape=oval]; // Block0_2Exit -> Block0_5 [style="solid"]; // Block0_4 [label="\ -// IN: [JUNK, phi4]\l\ +// IN: [JUNK, phi16]\l\ // \l\ -// [JUNK, phi4, lit0]\l\ +// [JUNK, phi16, lit0]\l\ // mstore\l\ // [JUNK]\l\ // \l\ @@ -56,62 +56,62 @@ // Block0_4Exit [label="MainExit"]; // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ -// IN: [phi0, phi3, phi1]\l\ +// IN: [phi2, phi8, phi4]\l\ // \l\ -// [phi0, phi3, phi1, lit1, phi1]\l\ +// [phi2, phi8, phi4, lit1, phi4]\l\ // lt\l\ -// [phi0, phi3, phi1, v1]\l\ +// [phi2, phi8, phi4, v5]\l\ // \l\ -// OUT: [phi0, phi3, phi1, v1]\l\ +// OUT: [phi2, phi8, phi4, v5]\l\ // "]; // Block0_5 -> Block0_5Exit; -// Block0_5Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_5Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_5Exit:0 -> Block0_8 [style="solid"]; // Block0_5Exit:1 -> Block0_6 [style="solid"]; // Block0_6 [label="\ -// IN: [phi0, phi3, phi1]\l\ +// IN: [phi2, phi8, phi4]\l\ // \l\ -// [phi0, phi3, phi1, phi1, phi0]\l\ +// [phi2, phi8, phi4, phi4, phi2]\l\ // mul\l\ -// [phi0, phi3, phi1, v2]\l\ +// [phi2, phi8, phi4, v7]\l\ // \l\ -// [phi0, phi1, v2, phi3]\l\ +// [phi2, phi4, v7, phi8]\l\ // add\l\ -// [phi0, phi1, v3]\l\ +// [phi2, phi4, v9]\l\ // \l\ -// OUT: [phi0, phi1, v3]\l\ +// OUT: [phi2, phi4, v9]\l\ // "]; // Block0_6 -> Block0_6Exit [arrowhead=none]; // Block0_6Exit [label="Jump" shape=oval]; // Block0_6Exit -> Block0_7 [style="solid"]; // Block0_8 [label="\ -// IN: [phi0, phi3, JUNK]\l\ +// IN: [phi2, phi8, JUNK]\l\ // \l\ -// OUT: [phi0, phi3, JUNK]\l\ +// OUT: [phi2, phi8, JUNK]\l\ // "]; // Block0_8 -> Block0_8Exit [arrowhead=none]; // Block0_8Exit [label="Jump" shape=oval]; // Block0_8Exit -> Block0_3 [style="solid"]; // Block0_7 [label="\ -// IN: [phi0, phi1, v3]\l\ +// IN: [phi2, phi4, v9]\l\ // \l\ -// [phi0, v3, lit2, phi1]\l\ +// [phi2, v9, lit10, phi4]\l\ // add\l\ -// [phi0, v3, v4]\l\ +// [phi2, v9, v11]\l\ // \l\ -// OUT: [phi0, v3, v4]\l\ +// OUT: [phi2, v9, v11]\l\ // "]; // Block0_7 -> Block0_7Exit [arrowhead=none]; // Block0_7Exit [label="Jump" shape=oval]; // Block0_7Exit -> Block0_5 [style="solid"]; // Block0_3 [label="\ -// IN: [phi0, phi3, JUNK]\l\ +// IN: [phi2, phi8, JUNK]\l\ // \l\ -// [JUNK, phi3, lit2, phi0]\l\ +// [JUNK, phi8, lit10, phi2]\l\ // add\l\ -// [JUNK, phi3, v5]\l\ +// [JUNK, phi8, v19]\l\ // \l\ -// OUT: [JUNK, phi3, v5]\l\ +// OUT: [JUNK, phi8, v19]\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; diff --git a/test/libyul/ssa/stackLayoutGenerator/recursion.yul b/test/libyul/ssa/stackLayoutGenerator/recursion.yul index c12de066a..a67441e9a 100644 --- a/test/libyul/ssa/stackLayoutGenerator/recursion.yul +++ b/test/libyul/ssa/stackLayoutGenerator/recursion.yul @@ -19,9 +19,9 @@ // \l\ // [FunctionCallReturnLabel[0], lit0]\l\ // sum\l\ -// [FunctionCallReturnLabel[0], v0]\l\ +// [FunctionCallReturnLabel[0], v1]\l\ // \l\ -// [v0, lit1]\l\ +// [v1, lit2]\l\ // mstore\l\ // []\l\ // \l\ @@ -44,28 +44,28 @@ // Block1_1 [label="\ // IN: [ReturnLabel[1], v0]\l\ // \l\ -// [ReturnLabel[1], v0, lit1, v0]\l\ +// [ReturnLabel[1], v0, lit2, v0]\l\ // sub\l\ -// [ReturnLabel[1], v0, v1]\l\ +// [ReturnLabel[1], v0, v3]\l\ // \l\ -// [ReturnLabel[1], v0, FunctionCallReturnLabel[0], v1]\l\ +// [ReturnLabel[1], v0, FunctionCallReturnLabel[0], v3]\l\ // sum\l\ -// [ReturnLabel[1], v0, FunctionCallReturnLabel[0], v2]\l\ +// [ReturnLabel[1], v0, FunctionCallReturnLabel[0], v4]\l\ // \l\ -// [ReturnLabel[1], v2, v0]\l\ +// [ReturnLabel[1], v4, v0]\l\ // add\l\ -// [ReturnLabel[1], v3]\l\ +// [ReturnLabel[1], v5]\l\ // \l\ -// OUT: [ReturnLabel[1], v3]\l\ +// OUT: [ReturnLabel[1], v5]\l\ // "]; // Block1_1 -> Block1_1Exit [arrowhead=none]; // Block1_1Exit [label="Jump" shape=oval]; // Block1_1Exit -> Block1_2 [style="solid"]; // Block1_2 [label="\ -// IN: [ReturnLabel[1], JUNK, phi0]\l\ +// IN: [ReturnLabel[1], JUNK, phi6]\l\ // \l\ -// OUT: [phi0, ReturnLabel[1]]\l\ +// OUT: [phi6, ReturnLabel[1]]\l\ // "]; -// Block1_2Exit [label="FunctionReturn[phi0]"]; +// Block1_2Exit [label="FunctionReturn[phi6]"]; // Block1_2 -> Block1_2Exit; // } diff --git a/test/libyul/ssa/stackLayoutGenerator/simple_for.yul b/test/libyul/ssa/stackLayoutGenerator/simple_for.yul index f245c5f17..dbaf45e46 100644 --- a/test/libyul/ssa/stackLayoutGenerator/simple_for.yul +++ b/test/libyul/ssa/stackLayoutGenerator/simple_for.yul @@ -25,74 +25,74 @@ // Block0_0Exit [label="Jump" shape=oval]; // Block0_0Exit -> Block0_1 [style="solid"]; // Block0_1 [label="\ -// IN: [phi0, phi1]\l\ +// IN: [phi1, phi2]\l\ // \l\ -// OUT: [phi0, phi1, phi0]\l\ +// OUT: [phi1, phi2, phi1]\l\ // "]; // Block0_1 -> Block0_1Exit; -// Block0_1Exit [label="{ If phi0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_1Exit [label="{ If phi1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_1Exit:0 -> Block0_4 [style="solid"]; // Block0_1Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ -// IN: [phi0, phi1]\l\ +// IN: [phi1, phi2]\l\ // \l\ -// [phi0, phi1, phi1]\l\ +// [phi1, phi2, phi2]\l\ // mload\l\ -// [phi0, phi1, v0]\l\ +// [phi1, phi2, v3]\l\ // \l\ -// OUT: [phi0, phi1, v0]\l\ +// OUT: [phi1, phi2, v3]\l\ // "]; // Block0_2 -> Block0_2Exit; -// Block0_2Exit [label="{ If v0 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_2Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_2Exit:0 -> Block0_6 [style="solid"]; // Block0_2Exit:1 -> Block0_5 [style="solid"]; // Block0_4 [label="\ -// IN: [phi0, JUNK]\l\ +// IN: [phi1, JUNK]\l\ // \l\ -// [phi0, JUNK, lit3, phi0]\l\ +// [phi1, JUNK, lit20, phi1]\l\ // mstore\l\ -// [phi0, JUNK]\l\ +// [phi1, JUNK]\l\ // \l\ -// OUT: [phi0, JUNK]\l\ +// OUT: [phi1, JUNK]\l\ // "]; // Block0_4Exit [label="MainExit"]; // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ -// IN: [phi0, phi1]\l\ +// IN: [phi1, phi2]\l\ // \l\ -// [phi1, phi1, phi0]\l\ +// [phi2, phi2, phi1]\l\ // add\l\ -// [phi1, v1]\l\ +// [phi2, v4]\l\ // \l\ -// [phi1, v1, lit1]\l\ +// [phi2, v4, lit5]\l\ // mload\l\ -// [phi1, v1, v2]\l\ +// [phi2, v4, v6]\l\ // \l\ -// [phi1, v2, v1]\l\ +// [phi2, v6, v4]\l\ // add\l\ -// [phi1, v3]\l\ +// [phi2, v7]\l\ // \l\ -// OUT: [phi1, v3]\l\ +// OUT: [phi2, v7]\l\ // "]; // Block0_5 -> Block0_5Exit [arrowhead=none]; // Block0_5Exit [label="Jump" shape=oval]; // Block0_5Exit -> Block0_6 [style="solid"]; // Block0_6 [label="\ -// IN: [phi3, phi1]\l\ +// IN: [phi14, phi2]\l\ // \l\ -// OUT: [phi3, phi1]\l\ +// OUT: [phi14, phi2]\l\ // "]; // Block0_6 -> Block0_6Exit [arrowhead=none]; // Block0_6Exit [label="Jump" shape=oval]; // Block0_6Exit -> Block0_3 [style="solid"]; // Block0_3 [label="\ -// IN: [phi3, phi1]\l\ +// IN: [phi14, phi2]\l\ // \l\ -// [phi3, lit2, phi1]\l\ +// [phi14, lit8, phi2]\l\ // add\l\ -// [phi3, v4]\l\ +// [phi14, v12]\l\ // \l\ -// OUT: [phi3, v4]\l\ +// OUT: [phi14, v12]\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; diff --git a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul index 2d0cbf67d..7a7afcd3e 100644 --- a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul +++ b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul @@ -21,9 +21,9 @@ // \l\ // [FunctionCallReturnLabel[0], lit0, lit1]\l\ // f\l\ -// [FunctionCallReturnLabel[0], v0]\l\ +// [FunctionCallReturnLabel[0], v2]\l\ // \l\ -// [v0, lit2]\l\ +// [v2, lit3]\l\ // mstore\l\ // []\l\ // \l\ @@ -39,22 +39,22 @@ // \l\ // [ReturnLabel[1], v1, v0, v0]\l\ // mload\l\ -// [ReturnLabel[1], v1, v0, v2]\l\ +// [ReturnLabel[1], v1, v0, v3]\l\ // \l\ -// OUT: [ReturnLabel[1], v1, v0, v2]\l\ +// OUT: [ReturnLabel[1], v1, v0, v3]\l\ // "]; // Block1_0 -> Block1_0Exit; -// Block1_0Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_0Exit [label="{ If v3 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_0Exit:0 -> Block1_2 [style="solid"]; // Block1_0Exit:1 -> Block1_1 [style="solid"]; // Block1_1 [label="\ // IN: [ReturnLabel[1], JUNK, v0]\l\ // \l\ -// [ReturnLabel[1], JUNK, lit1, v0]\l\ +// [ReturnLabel[1], JUNK, lit4, v0]\l\ // add\l\ -// [ReturnLabel[1], JUNK, v3]\l\ +// [ReturnLabel[1], JUNK, v5]\l\ // \l\ -// [ReturnLabel[1], JUNK, v3, v3]\l\ +// [ReturnLabel[1], JUNK, v5, v5]\l\ // revert\l\ // [ReturnLabel[1], JUNK]\l\ // \l\ @@ -67,10 +67,10 @@ // \l\ // [ReturnLabel[1], v1, v0]\l\ // add\l\ -// [ReturnLabel[1], v4]\l\ +// [ReturnLabel[1], v15]\l\ // \l\ -// OUT: [v4, ReturnLabel[1]]\l\ +// OUT: [v15, ReturnLabel[1]]\l\ // "]; -// Block1_2Exit [label="FunctionReturn[v4]"]; +// Block1_2Exit [label="FunctionReturn[v15]"]; // Block1_2 -> Block1_2Exit; // } diff --git a/test/libyul/ssa/stackLayoutGenerator/switch.yul b/test/libyul/ssa/stackLayoutGenerator/switch.yul index ba7e841a0..5b2fe1bce 100644 --- a/test/libyul/ssa/stackLayoutGenerator/switch.yul +++ b/test/libyul/ssa/stackLayoutGenerator/switch.yul @@ -28,16 +28,16 @@ // \l\ // [lit0]\l\ // sload\l\ -// [v0]\l\ +// [v3]\l\ // \l\ -// [v0, lit3, v0]\l\ +// [v3, lit4, v3]\l\ // eq\l\ -// [v0, v1]\l\ +// [v3, v5]\l\ // \l\ -// OUT: [v0, v1]\l\ +// OUT: [v3, v5]\l\ // "]; // Block0_0 -> Block0_0Exit; -// Block0_0Exit [label="{ If v1 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_0Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_0Exit:0 -> Block0_3 [style="solid"]; // Block0_0Exit:1 -> Block0_2 [style="solid"]; // Block0_2 [label="\ @@ -49,22 +49,22 @@ // Block0_2Exit [label="Jump" shape=oval]; // Block0_2Exit -> Block0_1 [style="solid"]; // Block0_3 [label="\ -// IN: [v0]\l\ +// IN: [v3]\l\ // \l\ -// [lit5, v0]\l\ +// [lit7, v3]\l\ // eq\l\ -// [v2]\l\ +// [v8]\l\ // \l\ -// OUT: [v2]\l\ +// OUT: [v8]\l\ // "]; // Block0_3 -> Block0_3Exit; -// Block0_3Exit [label="{ If v2 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_3Exit [label="{ If v8 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_3Exit:0 -> Block0_5 [style="solid"]; // Block0_3Exit:1 -> Block0_4 [style="solid"]; // Block0_1 [label="\ -// IN: [phi0]\l\ +// IN: [phi10]\l\ // \l\ -// [phi0, lit6]\l\ +// [phi10, lit14]\l\ // sstore\l\ // []\l\ // \l\ diff --git a/test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack b/test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack index 948dd8db8..a75ffd07b 100644 --- a/test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack +++ b/test/libyul/ssa/stackShuffler/spill_many_for_small_target.stack @@ -14,4 +14,4 @@ targetStackSize: 8 // +------------------------------------------ +-------------------------------------------------------- // (target)| {v1*, v2*, v3*, v4*, v5*, v6*, v7*, v8*} | v1 v2 v3 v4 v5 v6 v7 v8 // Status: Admissible -// Spilled: {v1, v2, v3, v4, v5, v6, v7, v8} +// Spilled: {v8, v7, v6, v5, v4, v3, v2, v1} diff --git a/test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack b/test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack index c491f6b52..ef977f7f5 100644 --- a/test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack +++ b/test/libyul/ssa/stackShuffler/spill_to_pop_deep_junk.stack @@ -43,4 +43,4 @@ targetStackTop: [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v1 // +-------------------------------------------------------------------------------------------------------------------------------------------- +------- // (target)| v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 | // Status: Admissible -// Spilled: {v4, v18, v19, v20} +// Spilled: {v4, v20, v19, v18} From efb9db2debf66653244a3e1677e9ef0684d96d45 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:50:53 +0200 Subject: [PATCH 1302/1340] SSA CFG: assert maximum number of outputs for builtin and user-defined functions --- libyul/backends/evm/ssa/SSACFG.h | 8 ++++++++ libyul/backends/evm/ssa/SSACFGTypes.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index b38737cf6..21b692410 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -203,6 +203,10 @@ class SSACFG langutil::DebugData::ConstPtr _debugData = {} ) { + yulAssert( + _numOutputs <= ValueId::maxOutputs, + fmt::format("SSA CFG: BuiltinCall with {} outputs exceeds the maximum of {}.", _numOutputs, ValueId::maxOutputs) + ); InstId const id = scheduleInBlock( m_instructions.appendBuiltinCall(_block, std::move(_payload), std::move(_inputs), _numOutputs), _block @@ -220,6 +224,10 @@ class SSACFG langutil::DebugData::ConstPtr _debugData = {} ) { + yulAssert( + _numOutputs <= ValueId::maxOutputs, + fmt::format("SSA CFG: Call with {} outputs exceeds the maximum of {}.", _numOutputs, ValueId::maxOutputs) + ); InstId const id = scheduleInBlock( m_instructions.appendCall(_block, std::move(_payload), std::move(_inputs), _numOutputs), _block diff --git a/libyul/backends/evm/ssa/SSACFGTypes.h b/libyul/backends/evm/ssa/SSACFGTypes.h index 50bd26fc6..2a7861ff5 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.h +++ b/libyul/backends/evm/ssa/SSACFGTypes.h @@ -67,6 +67,8 @@ class ValueId public: // this value refers to the n-th return value of an operation using OutputSize = std::uint8_t; + /// Maximum number of outputs an Inst may produce. Bounded by the encoding of `OutputSize`. + static constexpr std::size_t maxOutputs = std::numeric_limits::max(); constexpr ValueId() = default; constexpr ValueId(InstId const _instId, OutputSize const _outputPos = 0): From b0e2a13dcffeebadd217e9069db2d1d1af880f93 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Wed, 29 Apr 2026 13:06:11 +0200 Subject: [PATCH 1303/1340] SSA CFG: Add helper functions to SSA CFG to assess type of instruction and value id --- libyul/backends/evm/ssa/CodeTransform.cpp | 2 +- libyul/backends/evm/ssa/CodeTransform.h | 2 +- libyul/backends/evm/ssa/LivenessAnalysis.cpp | 8 ++++---- libyul/backends/evm/ssa/LivenessAnalysis.h | 2 +- libyul/backends/evm/ssa/SSACFG.h | 13 +++++++++++++ libyul/backends/evm/ssa/SSACFGBuilder.cpp | 2 +- libyul/backends/evm/ssa/StackLayoutGenerator.cpp | 2 +- libyul/backends/evm/ssa/io/JSONExporter.cpp | 2 +- .../evm/ssa/transform/TrivialPhiEliminator.cpp | 12 ++++++------ 9 files changed, 29 insertions(+), 16 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 6976f3ace..2be3eb0c2 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -404,7 +404,7 @@ void CodeTransform::operator()(SSACFG::BlockId const& _blockId, SSACFG::BasicBlo // Find the last BuiltinCall/Call Inst in the block. InstId lastOpInstId{}; for (InstId const instId: block.instructions | ranges::views::reverse) - if (m_cfg.inst(instId).isOperation()) + if (m_cfg.isOperation(instId)) { lastOpInstId = instId; break; diff --git a/libyul/backends/evm/ssa/CodeTransform.h b/libyul/backends/evm/ssa/CodeTransform.h index 6e5ab808d..6a141a70d 100644 --- a/libyul/backends/evm/ssa/CodeTransform.h +++ b/libyul/backends/evm/ssa/CodeTransform.h @@ -52,7 +52,7 @@ struct AssemblyCallbacks case StackSlot::Kind::ValueID: { auto const id = _slot.valueID(); - yulAssert(cfg->inst(id.instId()).isLiteral(), fmt::format("Tried bringing up non-const {}", id)); + yulAssert(cfg->isLiteral(id), fmt::format("Tried bringing up non-const {}", id)); assembly->appendConstant(cfg->literalPayload(id.instId())); return; } diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp index ce3ff1496..e5c2e7f57 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -84,8 +84,8 @@ void LivenessAnalysis::runDagDfs() LivenessData live{}; m_cfg.forEachUpsilon(block, [&](InstId, SSACFG::Inst const& inst) { SSACFG::ValueId const v = inst.inputs.at(0); - yulAssert(!m_cfg.inst(v.instId()).isUnreachable()); - if (!m_cfg.inst(v.instId()).isLiteral()) + yulAssert(!m_cfg.isUnreachable(v)); + if (!m_cfg.isLiteral(v)) live.insert(v); }); @@ -107,7 +107,7 @@ void LivenessAnalysis::runDagDfs() live.insertAll(std::get(block.exit).returnValues | ranges::views::filter(excludingLiteralsFilter())); // clean out unreachables - live.eraseIf([&](auto const& _entry) { return m_cfg.inst(_entry.first.instId()).isUnreachable(); }); + live.eraseIf([&](auto const& _entry) { return m_cfg.isUnreachable(_entry.first); }); // LiveOut(B) <- live m_liveOuts[blockId.value] = live; @@ -171,7 +171,7 @@ void LivenessAnalysis::fillOperationsLiveOut() auto const& block = m_cfg.block(blockId); auto const opCount = static_cast(ranges::count_if( block.instructions, - [&](InstId const _id) { return m_cfg.inst(_id).isOperation(); } + [&](InstId const _id) { return m_cfg.isOperation(_id); } )); auto& liveOuts = m_operationLiveOuts[blockId.value]; liveOuts.resize(opCount); diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.h b/libyul/backends/evm/ssa/LivenessAnalysis.h index 05f4cde0a..db8eedf80 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.h +++ b/libyul/backends/evm/ssa/LivenessAnalysis.h @@ -55,7 +55,7 @@ class LivenessAnalysis auto excludingLiteralsFilter() const { - return [this](SSACFG::ValueId _v) { return !m_cfg.inst(_v.instId()).isLiteral(); }; + return [this](SSACFG::ValueId _v) { return !m_cfg.isLiteral(_v); }; } SSACFG const& m_cfg; diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 21b692410..3bf03f98e 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -145,6 +145,19 @@ class SSACFG /// Returns the opcode category for a given ValueId. InstOpcode kindOf(ValueId const _v) const { return m_instructions.kindOf(_v); } + bool isPhi(InstId const _id) const { return inst(_id).isPhi(); } + bool isPhi(ValueId const _v) const { return isPhi(_v.instId()); } + bool isUpsilon(InstId const _id) const { return inst(_id).isUpsilon(); } + bool isUpsilon(ValueId const _v) const { return isUpsilon(_v.instId()); } + bool isLiteral(InstId const _id) const { return inst(_id).isLiteral(); } + bool isLiteral(ValueId const _v) const { return isLiteral(_v.instId()); } + bool isUnreachable(InstId const _id) const { return inst(_id).isUnreachable(); } + bool isUnreachable(ValueId const _v) const { return isUnreachable(_v.instId()); } + bool isFunctionArg(InstId const _id) const { return inst(_id).isFunctionArg(); } + bool isFunctionArg(ValueId const _v) const { return isFunctionArg(_v.instId()); } + bool isOperation(InstId const _id) const { return inst(_id).isOperation(); } + bool isOperation(ValueId const _v) const { return isOperation(_v.instId()); } + /// Returns the phi targeted by an Upsilon Inst. ValueId upsilonPhi(InstId const _id) const { return m_instructions.upsilonPhi(_id); } diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 3498a3c97..9e530f55b 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -546,7 +546,7 @@ void SSACFGBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::Val void SSACFGBuilder::emitUpsilon(SSACFG::BlockId _block, SSACFG::ValueId _value, SSACFG::ValueId _phi) { - yulAssert(m_graph.inst(_phi.instId()).isPhi()); + yulAssert(m_graph.isPhi(_phi)); m_graph.emitUpsilon(_block, _value, _phi); } diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 9b9d82432..836ed25c5 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -312,7 +312,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) yulAssert(!stack.empty() && stack.top().isValueID() && stack.top().valueID() == _cJump.condition); yulAssert(ranges::none_of(m_cfg.block(_cJump.nonZero).instructions, [this](InstId const _id) { - return m_cfg.inst(_id).isPhi(); + return m_cfg.isPhi(_id); })); // exitIn = pre-JUMPI state (condition on top) for CodeTransform diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index 1b50a8a3d..8c1cfd4f7 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -96,7 +96,7 @@ Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const } blockJson["instructions"] = Json::array(); bool const hasPhis = ranges::any_of(block.instructions, [&](InstId id) { - return _cfg.inst(id).isPhi(); + return _cfg.isPhi(id); }); if (hasPhis) blockJson["entries"] = block.entries diff --git a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp index bd0fa004d..9499c82ee 100644 --- a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp +++ b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp @@ -77,7 +77,7 @@ struct TrivialPhiEliminator auto& block = cfg.block(blockId); std::erase_if(block.instructions, [this](InstId const _id) { auto const& inst = cfg.inst(_id); - return inst.isUpsilon() && cfg.inst(inst.inputs.at(0).instId()).isUnreachable(); + return inst.isUpsilon() && cfg.isUnreachable(inst.inputs.at(0)); }); } } @@ -99,7 +99,7 @@ struct TrivialPhiEliminator reversePhiUpsilonValues.resize(phiIdx + 1); upsilonValuesForPhi[phiIdx].push_back(value); phiTargetBlocks[phiIdx].push_back(blockId); - if (cfg.inst(value.instId()).isPhi()) + if (cfg.isPhi(value)) { auto const valIdx = value.instId().value; if (valIdx >= reversePhiUpsilonValues.size()) @@ -120,7 +120,7 @@ struct TrivialPhiEliminator auto const unreachable = cfg.unreachableValue(); for (auto& upsilonValues: upsilonValuesForPhi) for (auto& val: upsilonValues) - if (cfg.inst(val.instId()).isPhi()) + if (cfg.isPhi(val)) { auto const idx = val.instId().value; bool const hasUpsilons = idx < upsilonValuesForPhi.size() && !upsilonValuesForPhi[idx].empty(); @@ -158,7 +158,7 @@ struct TrivialPhiEliminator for (auto const arg: upsilonValuesForPhi[phiIdx]) { auto const resolved = canonicalize(arg); - if (resolved == same || resolved == _phi || cfg.inst(resolved.instId()).isUnreachable()) + if (resolved == same || resolved == _phi || cfg.isUnreachable(resolved)) continue; if (same.hasValue()) return; // non-trivial @@ -172,7 +172,7 @@ struct TrivialPhiEliminator // remove the phi from its defining block { auto& block = cfg.block(cfg.inst(_phi.instId()).block); - yulAssert(cfg.inst(_phi.instId()).isPhi()); + yulAssert(cfg.isPhi(_phi)); std::erase(block.instructions, _phi.instId()); } @@ -197,7 +197,7 @@ struct TrivialPhiEliminator inst.inputs[0] = same; }); // maintain reverse index - if (cfg.inst(same.instId()).isPhi()) + if (cfg.isPhi(same)) { if (same.instId().value >= reversePhiUpsilonValues.size()) reversePhiUpsilonValues.resize(same.instId().value + 1); From 0993ab1f94e817b2767ab15469941ebcc317f09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 19 Feb 2026 15:38:13 +0100 Subject: [PATCH 1304/1340] Reorganize calldata and abicoder semantic tests --- .../abi_decode_from_calldata.sol} | 0 .../abi_decode_from_calldata_dynamic_array.sol} | 0 .../abi_decode_from_calldata_static_array.sol} | 0 .../abi_decode_from_calldata_static_array_v2.sol} | 0 .../abi_decode_from_calldata_struct_v2.sol} | 0 .../abi_decode_from_memory_struct_v2.sol} | 0 .../abi_decode_from_storage_struct_v2.sol} | 0 .../abi_decode_offset_overflow_in_array.sol} | 0 .../abi_decode_offset_overflow_in_array_2.sol} | 0 .../abi_decode_offset_overflow_in_array_3.sol} | 0 .../abi_decode_overlapping_dynamic_arrays.sol} | 0 .../{abiEncodeDecode => abicoder}/abi_decode_simple.sol | 0 .../{abiEncodeDecode => abicoder}/abi_decode_simple_storage.sol | 0 .../decode_slice.sol => abicoder/abi_decode_slice.sol} | 0 .../{abiEncoderV1 => abicoder}/abi_decode_trivial.sol | 0 .../semanticTests/{abiEncoderV1 => abicoder}/abi_encode.sol | 0 .../semanticTests/{abiEncoderV1 => abicoder}/abi_encode_call.sol | 0 .../abi_encode_call_declaration_v2.sol} | 0 .../abi_encode_call_is_consistent_v2.sol} | 0 .../abi_encode_call_memory_v2.sol} | 0 .../abi_encode_call_special_args_v2.sol} | 0 .../{abiEncodeDecode => abicoder}/abi_encode_call_uint_bytes.sol | 0 .../abi_encode_call.sol => abicoder/abi_encode_call_v2.sol} | 0 .../{abiEncoderV1 => abicoder}/abi_encode_calldata_slice.sol | 0 .../abi_encode_calldata_slice_v2.sol} | 0 .../{abiEncoderV1 => abicoder}/abi_encode_decode_simple.sol | 0 .../abi_encode_empty_string_not_bytes0_v1.sol} | 0 .../abi_encode_empty_string_not_bytes0_v2.sol} | 0 .../abi_encode_empty_string_v1.sol} | 0 .../abi_encode_memory_dynamic_array_and_calldata_bytes_v1.sol} | 0 .../{abiEncoderV1 => abicoder}/abi_encode_rational.sol | 0 .../{abiEncoderV2 => abicoder}/abi_encode_rational_v2.sol | 0 .../abi_encode_storage_array_v2.sol} | 0 .../semanticTests/{abiEncoderV2 => abicoder}/abi_encode_v2.sol | 0 .../abi_encode_v2_in_function_inherited_in_v1_contract.sol | 0 .../abi_encode_v2_in_modifier_used_in_v1_contract.sol | 0 .../abi_encode_with_selector_v1.sol} | 0 .../abi_encode_with_selector_v2.sol} | 0 .../abi_encode_with_signature_v1.sol} | 0 .../abi_encode_with_signature_v2.sol} | 0 ...ug_abi_encoder_v2_head_overflow_with_static_array_cleanup.sol} | 0 .../calldataDecoding/array}/byte_arrays.sol | 0 .../array/calldata_array_2d_dynamic_dynamic_v2.sol} | 0 .../array/calldata_array_2d_dynamic_static_v2.sol} | 0 .../calldataDecoding/array/calldata_array_bytes_v2.sol} | 0 .../calldataDecoding/array/calldata_array_dynamic_of_uint_v2.sol} | 0 .../array/calldata_array_dynamic_of_value_types_v2.sol} | 0 .../array/calldata_array_dynamic_static_dynamic_v2.sol} | 0 .../array/calldata_array_dynamic_static_in_library_v2.sol} | 0 .../array/calldata_array_dynamic_static_short_decode_v2.sol} | 0 .../array/calldata_array_dynamic_static_short_reencode_v2.sol} | 0 .../calldataDecoding/array/calldata_array_function_types_v2.sol} | 0 .../calldataDecoding/array/calldata_array_indexing_1d_2d_v2.sol} | 0 .../array/calldata_array_indexing_3d_dynamic_v2.sol} | 0 .../calldataDecoding/array/calldata_array_indexing_3d_v2.sol} | 0 .../array/calldata_array_indexing_dynamic_bytes_v2.sol} | 0 .../array/calldata_array_indexing_dynamic_v2.sol} | 0 .../calldataDecoding/array/calldata_array_indexing_static_v2.sol} | 0 .../calldataDecoding/array/calldata_array_length_v2.sol} | 0 .../calldataDecoding/array/calldata_array_multi_dynamic_v2.sol} | 0 .../calldataDecoding/array/calldata_array_slicing_v2.sol} | 0 .../array/calldata_array_static_dynamic_static_v2.sol} | 0 .../calldataDecoding/array/calldata_array_static_of_uint_v2.sol} | 0 .../array/calldata_array_static_of_value_types_v2.sol} | 0 .../calldataDecoding/array/calldata_array_struct_dynamic_v2.sol} | 0 .../calldataDecoding/array/calldata_array_struct_static_v2.sol} | 0 .../calldataDecoding/array/calldata_array_two_dynamic_v2.sol} | 0 .../calldataDecoding/array/calldata_array_two_static_v2.sol} | 0 .../calldataDecoding/array/calldata_bytes_bytes32_arrays_v1.sol} | 0 .../array/calldata_dynamic_array_to_memory_v2.sol} | 0 .../calldataDecoding/array/calldata_nested_array_reencode_v2.sol} | 0 .../array/calldata_nested_array_static_reencode_v2.sol} | 0 .../array/calldata_overlapping_dynamic_arrays_v2.sol} | 0 .../array/calldata_overlapping_nested_dynamic_arrays_v2.sol} | 0 .../calldataDecoding/array/calldata_string_array_v2.sol} | 0 .../calldataDecoding/array/calldata_struct_array_reencode_v2.sol} | 0 .../calldataDecoding/array/memory_arrays_static.sol} | 0 .../array}/memory_dynamic_array_and_calldata_bytes.sol | 0 .../array}/memory_dynamic_array_and_calldata_static_array.sol | 0 .../calldataDecoding/array/memory_dynamic_arrays.sol} | 0 .../calldataDecoding/array/memory_dynamic_arrays_v2.sol} | 0 .../calldataDecoding/array/memory_dynamic_nested_arrays_v2.sol} | 0 .../array}/memory_params_in_external_function.sol | 0 .../array/memory_params_in_external_function_v2.sol} | 0 .../calldataDecoding}/copy_from_calldata_removes_bytes_data.sol | 0 .../calldataDecoding/struct/mediocre_dynamic_v2.sol} | 0 .../calldataDecoding/struct/mediocre_static_v2.sol} | 0 .../calldataDecoding/struct/member_array_dynamic2_v2.sol} | 0 .../struct/member_array_dynamic_multiple_fields_v2.sol} | 0 .../calldataDecoding/struct/member_array_dynamic_v2.sol} | 0 .../struct/member_array_static_mulitple_fields_v2.sol} | 0 .../calldataDecoding/struct/member_external_function_v2.sol} | 0 .../calldataDecoding/struct/member_offset_v2.sol} | 0 .../calldataDecoding/struct/multiple_structs_v2.sol} | 0 .../calldataDecoding/struct/nested_static_3_fields_v2.sol} | 0 .../calldataDecoding/struct/nested_static_4_fields_v2.sol} | 0 .../calldataDecoding/struct/nested_with_bytes_v2.sol} | 0 .../calldataDecoding/struct/nested_with_dynamic_array_v2.sol} | 0 .../struct/nested_with_dynamic_struct_array_v2.sol} | 0 .../calldataDecoding/struct/short_v2.sol} | 0 .../struct/simple_multiple_fields_short_types_v2.sol} | 0 .../calldataDecoding/struct/simple_multiple_fields_v2.sol} | 0 .../calldataDecoding/struct/simple_single_field_v2.sol} | 0 .../calldataDecoding/struct/struct_and_ints_v2.sol} | 0 .../cleanup/address.sol => abicoder/cleanup/address_v2.sol} | 0 .../bool_out_of_bounds.sol => abicoder/cleanup/bool_v1.sol} | 0 .../bool_out_of_bounds.sol => abicoder/cleanup/bool_v2.sol} | 0 .../bool.sol => abicoder/cleanup/bool_with_sanity_check_v2.sol} | 0 .../cleanup/bytesx.sol => abicoder/cleanup/bytesx_v2.sol} | 0 .../cleanup/cleanup.sol => abicoder/cleanup/cleanup_v1.sol} | 0 .../cleanup/cleanup.sol => abicoder/cleanup/cleanup_v2.sol} | 0 .../dynamic_array.sol => abicoder/cleanup/dynamic_array_v2.sol} | 0 .../{abiEncoderV1/enums.sol => abicoder/cleanup/enum_v1.sol} | 0 .../{abiEncoderV2/enums.sol => abicoder/cleanup/enum_v2.sol} | 0 .../cleanup/function.sol => abicoder/cleanup/function_v2.sol} | 0 .../cleanup/intx.sol => abicoder/cleanup/intx_v2.sol} | 0 .../cleanup/reencoded_calldata_string.sol | 0 .../static_array.sol => abicoder/cleanup/static_array_v2.sol} | 0 .../cleanup/struct2_v2.sol} | 0 .../cleanup/simple_struct.sol => abicoder/cleanup/struct_v2.sol} | 0 .../cleanup/uintx.sol => abicoder/cleanup/uintx_v2.sol} | 0 .../{abiEncodeDecode => abicoder}/contract_array.sol | 0 .../{abiEncodeDecode => abicoder}/contract_array_v2.sol | 0 .../libraryABI/storage_ptr.sol} | 0 .../return_dynamic_types_cross_call_advanced.sol | 0 .../return_dynamic_types_cross_call_out_of_range_homestead.sol} | 0 ...turn_dynamic_types_cross_call_out_of_range_post_homestead.sol} | 0 .../return_dynamic_types_cross_call_simple.sol | 0 .../validation/array_exceeds_calldatasize_no_revert_string.sol} | 0 .../validation/array_exceeds_calldatasize_v2.sol} | 0 .../validation/array_exceeds_size_limit_for_calldata_types.sol} | 0 .../calldata_array_dynamic_invalid_static_middle_v2.sol} | 0 .../validation/calldata_array_dynamic_invalid_v2.sol} | 0 .../validation/calldata_with_garbage_v2.sol} | 0 .../validation/external_function_type_inside_struct_v2.sol} | 0 .../validation/static_struct_v2.sol} | 0 .../calldata_array_bounds_check_nested_bytes.sol} | 0 ...y_bounds.sol => calldata_array_bounds_check_nested_bytes2.sol} | 0 ...calldata_to_memory.sol => nested_array_calldata_to_memory.sol} | 0 ...lldata_to_storage.sol => nested_array_calldata_to_storage.sol} | 0 .../nested_array_dynamic_dynamic_calldata_to_storage.sol} | 0 .../nested_array_dynamic_static_calldata_to_storage.sol} | 0 ...d_memory_to_storage.sol => nested_array_memory_to_storage.sol} | 0 ...d_storage_to_memory.sol => nested_array_storage_to_memory.sol} | 0 .../calldata_array_slicing.sol} | 0 .../{calldata => conversions}/calldata_bytes_to_memory.sol | 0 .../calldata_bytes_to_memory_reencode.sol} | 0 .../calldata_and_memory_arguments.sol} | 0 .../calldata_argument_external_bytes.sol} | 0 .../calldata_argument_internal_bytes.sol} | 0 .../calldata_argument_internal_dynamic_array_v2.sol} | 0 .../calldata_argument_internal_library_bytes.sol} | 0 .../calldata_argument_internal_library_dynamic_struct_v2.sol} | 0 .../calldata_argument_internal_library_static_struct_v2.sol} | 0 .../calldata_argument_internal_multi_array_v2.sol} | 0 .../calldata_argument_internal_multi_static_array_v2.sol} | 0 .../calldata_argument_internal_struct_as_memory_v2.sol} | 0 .../calldata_argument_internal_struct_v2.sol} | 0 .../internal_function_pointer_with_calldata_args.sol} | 0 ...ary_function_accepting_calldata_dynamic_array_or_slice_v2.sol} | 0 ...ernal_library_function_accepting_calldata_static_array_v2.sol} | 0 ...ed_internal_library_function_accepting_calldata_struct_v2.sol} | 0 .../attached_internal_library_function_accepting_calldata_v2.sol} | 0 ...ol => attached_public_library_function_accepting_calldata.sol} | 0 .../copy_struct_with_nested_struct_from_calldata_to_memory.sol} | 0 ...ory.sol => struct_copy_calldata_to_memory_nested_bytes_v2.sol} | 0 ...=> struct_copy_calldata_to_memory_nested_dynamic_array_v2.sol} | 0 ... => struct_copy_calldata_to_memory_nested_static_array_v2.sol} | 0 ...le_assignment.sol => struct_copy_calldata_to_memory_tuple.sol} | 0 ...struct_to_memory.sol => struct_copy_calldata_to_memory_v2.sol} | 0 ...> struct_copy_calldata_to_storage_nested_dynamic_array_v2.sol} | 0 ...ruct_to_storage.sol => struct_copy_calldata_to_storage_v2.sol} | 0 172 files changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/semanticTests/{abiEncodeDecode/abi_decode_calldata.sol => abicoder/abi_decode_from_calldata.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/abi_decode_dynamic_array.sol => abicoder/abi_decode_from_calldata_dynamic_array.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/abi_decode_static_array.sol => abicoder/abi_decode_from_calldata_static_array.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/abi_decode_static_array_v2.sol => abicoder/abi_decode_from_calldata_static_array_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/abi_decode_v2_calldata.sol => abicoder/abi_decode_from_calldata_struct_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/abi_decode_v2.sol => abicoder/abi_decode_from_memory_struct_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/abi_decode_v2_storage.sol => abicoder/abi_decode_from_storage_struct_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/offset_overflow_in_array_decoding.sol => abicoder/abi_decode_offset_overflow_in_array.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/offset_overflow_in_array_decoding_2.sol => abicoder/abi_decode_offset_overflow_in_array_2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/offset_overflow_in_array_decoding_3.sol => abicoder/abi_decode_offset_overflow_in_array_3.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/dynamic_memory_copy.sol => abicoder/abi_decode_overlapping_dynamic_arrays.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode => abicoder}/abi_decode_simple.sol (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode => abicoder}/abi_decode_simple_storage.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/decode_slice.sol => abicoder/abi_decode_slice.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1 => abicoder}/abi_decode_trivial.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV1 => abicoder}/abi_encode.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV1 => abicoder}/abi_encode_call.sol (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/abi_encode_call_declaration.sol => abicoder/abi_encode_call_declaration_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/abi_encode_call_is_consistent.sol => abicoder/abi_encode_call_is_consistent_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/abi_encode_call_memory.sol => abicoder/abi_encode_call_memory_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/abi_encode_call_special_args.sol => abicoder/abi_encode_call_special_args_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode => abicoder}/abi_encode_call_uint_bytes.sol (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/abi_encode_call.sol => abicoder/abi_encode_call_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1 => abicoder}/abi_encode_calldata_slice.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/abi_encode_calldata_slice.sol => abicoder/abi_encode_calldata_slice_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1 => abicoder}/abi_encode_decode_simple.sol (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/abi_encode_empty_string_v1.sol => abicoder/abi_encode_empty_string_not_bytes0_v1.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/abi_encode_empty_string_v2.sol => abicoder/abi_encode_empty_string_not_bytes0_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/abi_encode_empty_string.sol => abicoder/abi_encode_empty_string_v1.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/memory_dynamic_array_and_calldata_bytes.sol => abicoder/abi_encode_memory_dynamic_array_and_calldata_bytes_v1.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1 => abicoder}/abi_encode_rational.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV2 => abicoder}/abi_encode_rational_v2.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/storage_array_encoding.sol => abicoder/abi_encode_storage_array_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2 => abicoder}/abi_encode_v2.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV2 => abicoder}/abi_encode_v2_in_function_inherited_in_v1_contract.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV2 => abicoder}/abi_encode_v2_in_modifier_used_in_v1_contract.sol (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/abi_encode_with_selector.sol => abicoder/abi_encode_with_selector_v1.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/abi_encode_with_selectorv2.sol => abicoder/abi_encode_with_selector_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/abi_encode_with_signature.sol => abicoder/abi_encode_with_signature_v1.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode/abi_encode_with_signaturev2.sol => abicoder/abi_encode_with_signature_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/abi_encoder_v2_head_overflow_with_static_array_cleanup_bug.sol => abicoder/bug_abi_encoder_v2_head_overflow_with_static_array_cleanup.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1 => abicoder/calldataDecoding/array}/byte_arrays.sol (100%) rename test/libsolidity/semanticTests/{array/calldata_array_two_dimensional_1.sol => abicoder/calldataDecoding/array/calldata_array_2d_dynamic_dynamic_v2.sol} (100%) rename test/libsolidity/semanticTests/{array/calldata_array_two_dimensional.sol => abicoder/calldataDecoding/array/calldata_array_2d_dynamic_static_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/byte_arrays.sol => abicoder/calldataDecoding/array/calldata_array_bytes_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array.sol => abicoder/calldataDecoding/array/calldata_array_dynamic_of_uint_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_dynamic.sol => abicoder/calldataDecoding/array/calldata_array_dynamic_of_value_types_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_dynamic_static_dynamic.sol => abicoder/calldataDecoding/array/calldata_array_dynamic_static_dynamic_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_dynamic_static_in_library.sol => abicoder/calldataDecoding/array/calldata_array_dynamic_static_in_library_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_dynamic_static_short_decode.sol => abicoder/calldataDecoding/array/calldata_array_dynamic_static_short_decode_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_dynamic_static_short_reencode.sol => abicoder/calldataDecoding/array/calldata_array_dynamic_static_short_reencode_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_function_types.sol => abicoder/calldataDecoding/array/calldata_array_function_types_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_array_access.sol => abicoder/calldataDecoding/array/calldata_array_indexing_1d_2d_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_three_dimensional_dynamic_array_index_access.sol => abicoder/calldataDecoding/array/calldata_array_indexing_3d_dynamic_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_array_three_dimensional.sol => abicoder/calldataDecoding/array/calldata_array_indexing_3d_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_array_dynamic_bytes.sol => abicoder/calldataDecoding/array/calldata_array_indexing_dynamic_bytes_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_dynamic_index_access.sol => abicoder/calldataDecoding/array/calldata_array_indexing_dynamic_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_static_index_access.sol => abicoder/calldataDecoding/array/calldata_array_indexing_static_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_array_length.sol => abicoder/calldataDecoding/array/calldata_array_length_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_multi_dynamic.sol => abicoder/calldataDecoding/array/calldata_array_multi_dynamic_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_array_index_range_access.sol => abicoder/calldataDecoding/array/calldata_array_slicing_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_static_dynamic_static.sol => abicoder/calldataDecoding/array/calldata_array_static_dynamic_static_v2.sol} (100%) rename test/libsolidity/semanticTests/{array/calldata_array.sol => abicoder/calldataDecoding/array/calldata_array_static_of_uint_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_static.sol => abicoder/calldataDecoding/array/calldata_array_static_of_value_types_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_struct_dynamic.sol => abicoder/calldataDecoding/array/calldata_array_struct_dynamic_v2.sol} (100%) rename test/libsolidity/semanticTests/{array/calldata_array_of_struct.sol => abicoder/calldataDecoding/array/calldata_array_struct_static_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_two_dynamic.sol => abicoder/calldataDecoding/array/calldata_array_two_dynamic_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_two_static.sol => abicoder/calldataDecoding/array/calldata_array_two_static_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/calldata_bytes_bytes32_arrays.sol => abicoder/calldataDecoding/array/calldata_bytes_bytes32_arrays_v1.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_dynamic_array_to_memory.sol => abicoder/calldataDecoding/array/calldata_dynamic_array_to_memory_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_nested_array_reencode.sol => abicoder/calldataDecoding/array/calldata_nested_array_reencode_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_nested_array_static_reencode.sol => abicoder/calldataDecoding/array/calldata_nested_array_static_reencode_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_overlapped_dynamic_arrays.sol => abicoder/calldataDecoding/array/calldata_overlapping_dynamic_arrays_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_overlapped_nested_dynamic_arrays.sol => abicoder/calldataDecoding/array/calldata_overlapping_nested_dynamic_arrays_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_string_array.sol => abicoder/calldataDecoding/array/calldata_string_array_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_struct_array_reencode.sol => abicoder/calldataDecoding/array/calldata_struct_array_reencode_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/abi_decode_fixed_arrays.sol => abicoder/calldataDecoding/array/memory_arrays_static.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2 => abicoder/calldataDecoding/array}/memory_dynamic_array_and_calldata_bytes.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV2 => abicoder/calldataDecoding/array}/memory_dynamic_array_and_calldata_static_array.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/dynamic_arrays.sol => abicoder/calldataDecoding/array/memory_dynamic_arrays.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/dynamic_arrays.sol => abicoder/calldataDecoding/array/memory_dynamic_arrays_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/dynamic_nested_arrays.sol => abicoder/calldataDecoding/array/memory_dynamic_nested_arrays_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1 => abicoder/calldataDecoding/array}/memory_params_in_external_function.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/memory_params_in_external_function.sol => abicoder/calldataDecoding/array/memory_params_in_external_function_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata => abicoder/calldataDecoding}/copy_from_calldata_removes_bytes_data.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/struct/mediocre2_struct.sol => abicoder/calldataDecoding/struct/mediocre_dynamic_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/struct/mediocre_struct.sol => abicoder/calldataDecoding/struct/mediocre_static_v2.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/dynamically_encoded.sol => abicoder/calldataDecoding/struct/member_array_dynamic2_v2.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/calldata_struct_array_member_dynamic.sol => abicoder/calldataDecoding/struct/member_array_dynamic_multiple_fields_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_struct_dynamic.sol => abicoder/calldataDecoding/struct/member_array_dynamic_v2.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/calldata_struct_array_member.sol => abicoder/calldataDecoding/struct/member_array_static_mulitple_fields_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/struct/struct_function.sol => abicoder/calldataDecoding/struct/member_external_function_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_struct_member_offset.sol => abicoder/calldataDecoding/struct/member_offset_v2.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/calldata_structs.sol => abicoder/calldataDecoding/struct/multiple_structs_v2.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/calldata_struct_struct_member.sol => abicoder/calldataDecoding/struct/nested_static_3_fields_v2.sol} (100%) rename test/libsolidity/semanticTests/{various/nested_calldata_struct.sol => abicoder/calldataDecoding/struct/nested_static_4_fields_v2.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/calldata_struct_struct_member_dynamic.sol => abicoder/calldataDecoding/struct/nested_with_bytes_v2.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/calldata_nested_structs.sol => abicoder/calldataDecoding/struct/nested_with_dynamic_array_v2.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/dynamic_nested.sol => abicoder/calldataDecoding/struct/nested_with_dynamic_struct_array_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/struct/struct_short.sol => abicoder/calldataDecoding/struct/short_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/struct/struct_simple.sol => abicoder/calldataDecoding/struct/simple_multiple_fields_short_types_v2.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/calldata_struct.sol => abicoder/calldataDecoding/struct/simple_multiple_fields_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_struct_simple.sol => abicoder/calldataDecoding/struct/simple_single_field_v2.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/calldata_struct_and_ints.sol => abicoder/calldataDecoding/struct/struct_and_ints_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/cleanup/address.sol => abicoder/cleanup/address_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/bool_out_of_bounds.sol => abicoder/cleanup/bool_v1.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/bool_out_of_bounds.sol => abicoder/cleanup/bool_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/cleanup/bool.sol => abicoder/cleanup/bool_with_sanity_check_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/cleanup/bytesx.sol => abicoder/cleanup/bytesx_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/cleanup/cleanup.sol => abicoder/cleanup/cleanup_v1.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/cleanup/cleanup.sol => abicoder/cleanup/cleanup_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/cleanup/dynamic_array.sol => abicoder/cleanup/dynamic_array_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/enums.sol => abicoder/cleanup/enum_v1.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/enums.sol => abicoder/cleanup/enum_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/cleanup/function.sol => abicoder/cleanup/function_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/cleanup/intx.sol => abicoder/cleanup/intx_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2 => abicoder}/cleanup/reencoded_calldata_string.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/cleanup/static_array.sol => abicoder/cleanup/static_array_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_struct_cleaning.sol => abicoder/cleanup/struct2_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/cleanup/simple_struct.sol => abicoder/cleanup/struct_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/cleanup/uintx.sol => abicoder/cleanup/uintx_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode => abicoder}/contract_array.sol (100%) rename test/libsolidity/semanticTests/{abiEncodeDecode => abicoder}/contract_array_v2.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/struct/struct_storage_ptr.sol => abicoder/libraryABI/storage_ptr.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1 => abicoder}/return_dynamic_types_cross_call_advanced.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/return_dynamic_types_cross_call_out_of_range_1.sol => abicoder/return_dynamic_types_cross_call_out_of_range_homestead.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/return_dynamic_types_cross_call_out_of_range_2.sol => abicoder/return_dynamic_types_cross_call_out_of_range_post_homestead.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1 => abicoder}/return_dynamic_types_cross_call_simple.sol (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_short_no_revert_string.sol => abicoder/validation/array_exceeds_calldatasize_no_revert_string.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_array_short.sol => abicoder/validation/array_exceeds_calldatasize_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV1/calldata_arrays_too_large.sol => abicoder/validation/array_exceeds_size_limit_for_calldata_types.sol} (100%) rename test/libsolidity/semanticTests/{array/calldata_array_dynamic_invalid_static_middle.sol => abicoder/validation/calldata_array_dynamic_invalid_static_middle_v2.sol} (100%) rename test/libsolidity/semanticTests/{array/calldata_array_dynamic_invalid.sol => abicoder/validation/calldata_array_dynamic_invalid_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/calldata_with_garbage.sol => abicoder/validation/calldata_with_garbage_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/struct/validation_function_type_inside_struct.sol => abicoder/validation/external_function_type_inside_struct_v2.sol} (100%) rename test/libsolidity/semanticTests/{abiEncoderV2/struct/struct_validation.sol => abicoder/validation/static_struct_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_bytes_array_bounds.sol => array/calldata_array_bounds_check_nested_bytes.sol} (100%) rename test/libsolidity/semanticTests/array/{calldata_bytes_array_bounds.sol => calldata_array_bounds_check_nested_bytes2.sol} (100%) rename test/libsolidity/semanticTests/array/copying/{array_nested_calldata_to_memory.sol => nested_array_calldata_to_memory.sol} (100%) rename test/libsolidity/semanticTests/array/copying/{array_nested_calldata_to_storage.sol => nested_array_calldata_to_storage.sol} (100%) rename test/libsolidity/semanticTests/array/{nested_calldata_storage2.sol => copying/nested_array_dynamic_dynamic_calldata_to_storage.sol} (100%) rename test/libsolidity/semanticTests/array/{nested_calldata_storage.sol => copying/nested_array_dynamic_static_calldata_to_storage.sol} (100%) rename test/libsolidity/semanticTests/array/copying/{array_nested_memory_to_storage.sol => nested_array_memory_to_storage.sol} (100%) rename test/libsolidity/semanticTests/array/copying/{array_nested_storage_to_memory.sol => nested_array_storage_to_memory.sol} (100%) rename test/libsolidity/semanticTests/array/{calldata_slice_access.sol => slices/calldata_array_slicing.sol} (100%) rename test/libsolidity/semanticTests/{calldata => conversions}/calldata_bytes_to_memory.sol (100%) rename test/libsolidity/semanticTests/{calldata/calldata_bytes_to_memory_encode.sol => conversions/calldata_bytes_to_memory_reencode.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_memory_mixed.sol => functionCall/calldata_and_memory_arguments.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_bytes_external.sol => functionCall/calldata_argument_external_bytes.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_bytes_internal.sol => functionCall/calldata_argument_internal_bytes.sol} (100%) rename test/libsolidity/semanticTests/{array/calldata_array_as_argument_internal_function.sol => functionCall/calldata_argument_internal_dynamic_array_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_internal_library.sol => functionCall/calldata_argument_internal_library_bytes.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/calldata_struct_as_argument_of_lib_function.sol => functionCall/calldata_argument_internal_library_dynamic_struct_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_struct.sol => functionCall/calldata_argument_internal_library_static_struct_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_internal_multi_array.sol => functionCall/calldata_argument_internal_multi_array_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_internal_multi_fixed_array.sol => functionCall/calldata_argument_internal_multi_static_array_v2.sol} (100%) rename test/libsolidity/semanticTests/{structs/calldata/calldata_struct_as_memory_argument.sol => functionCall/calldata_argument_internal_struct_as_memory_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_struct_internal.sol => functionCall/calldata_argument_internal_struct_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_internal_function_pointer.sol => functionTypes/internal_function_pointer_with_calldata_args.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_attached_to_dynamic_array_or_slice.sol => libraries/attached_internal_library_function_accepting_calldata_dynamic_array_or_slice_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_attached_to_static_array.sol => libraries/attached_internal_library_function_accepting_calldata_static_array_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_attached_to_struct.sol => libraries/attached_internal_library_function_accepting_calldata_struct_v2.sol} (100%) rename test/libsolidity/semanticTests/{calldata/calldata_attached_to_bytes.sol => libraries/attached_internal_library_function_accepting_calldata_v2.sol} (100%) rename test/libsolidity/semanticTests/libraries/{attached_public_library_function_accepting_calldata.sol.sol => attached_public_library_function_accepting_calldata.sol} (100%) rename test/libsolidity/semanticTests/{various/nested_calldata_struct_to_memory.sol => structs/copy_struct_with_nested_struct_from_calldata_to_memory.sol} (100%) rename test/libsolidity/semanticTests/structs/{calldata/calldata_struct_with_bytes_to_memory.sol => struct_copy_calldata_to_memory_nested_bytes_v2.sol} (100%) rename test/libsolidity/semanticTests/structs/{calldata/calldata_struct_with_nested_array_to_memory.sol => struct_copy_calldata_to_memory_nested_dynamic_array_v2.sol} (100%) rename test/libsolidity/semanticTests/structs/{calldata/calldata_struct_with_array_to_memory.sol => struct_copy_calldata_to_memory_nested_static_array_v2.sol} (100%) rename test/libsolidity/semanticTests/structs/{calldata/calldata_struct_to_memory_tuple_assignment.sol => struct_copy_calldata_to_memory_tuple.sol} (100%) rename test/libsolidity/semanticTests/structs/{calldata/calldata_struct_to_memory.sol => struct_copy_calldata_to_memory_v2.sol} (100%) rename test/libsolidity/semanticTests/structs/{calldata/calldata_struct_with_nested_array_to_storage.sol => struct_copy_calldata_to_storage_nested_dynamic_array_v2.sol} (100%) rename test/libsolidity/semanticTests/structs/{calldata/calldata_struct_to_storage.sol => struct_copy_calldata_to_storage_v2.sol} (100%) diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_calldata.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_calldata.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_dynamic_array.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_dynamic_array.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_decode_dynamic_array.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_dynamic_array.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_static_array.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_static_array.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_decode_static_array.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_static_array.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_static_array_v2.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_static_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_decode_static_array_v2.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_static_array_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_calldata.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_struct_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_calldata.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_struct_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_from_memory_struct_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_from_memory_struct_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_from_storage_struct_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_storage.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_from_storage_struct_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_2.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_2.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_2.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_3.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_3.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/offset_overflow_in_array_decoding_3.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_3.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/dynamic_memory_copy.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_overlapping_dynamic_arrays.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/dynamic_memory_copy.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_overlapping_dynamic_arrays.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_simple.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_simple.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple_storage.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_simple_storage.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_decode_simple_storage.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_simple_storage.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/decode_slice.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_slice.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/decode_slice.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_slice.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_trivial.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_trivial.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_decode_trivial.sol rename to test/libsolidity/semanticTests/abicoder/abi_decode_trivial.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode.sol b/test/libsolidity/semanticTests/abicoder/abi_encode.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_encode.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_call.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_call.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_encode_call.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_call.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_declaration.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_call_declaration_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_declaration.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_call_declaration_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_is_consistent.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_call_is_consistent_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_is_consistent.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_call_is_consistent_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_memory.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_call_memory_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_memory.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_call_memory_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_special_args.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_call_special_args_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_special_args.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_call_special_args_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_uint_bytes.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_call_uint_bytes.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call_uint_bytes.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_call_uint_bytes.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_call_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_call.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_call_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_calldata_slice.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_encode_calldata_slice.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_calldata_slice.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_calldata_slice_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/abi_encode_calldata_slice.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_calldata_slice_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_decode_simple.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_decode_simple.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_encode_decode_simple.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_decode_simple.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_empty_string_v1.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0_v1.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_empty_string_v1.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0_v1.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_empty_string_v2.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/abi_encode_empty_string_v2.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_empty_string.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_v1.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_encode_empty_string.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_v1.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/memory_dynamic_array_and_calldata_bytes.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_memory_dynamic_array_and_calldata_bytes_v1.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/memory_dynamic_array_and_calldata_bytes.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_memory_dynamic_array_and_calldata_bytes_v1.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_encode_rational.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_rational.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_encode_rational.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_rational.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_rational_v2.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_rational_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/abi_encode_rational_v2.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_rational_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_storage_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/storage_array_encoding.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_storage_array_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_v2_in_function_inherited_in_v1_contract.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_function_inherited_in_v1_contract.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_v2_in_function_inherited_in_v1_contract.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_v2_in_modifier_used_in_v1_contract.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2_in_modifier_used_in_v1_contract.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_v2_in_modifier_used_in_v1_contract.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selector.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_with_selector_v1.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selector.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_with_selector_v1.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selectorv2.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_with_selector_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_selectorv2.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_with_selector_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signature.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_with_signature_v1.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signature.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_with_signature_v1.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signaturev2.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_with_signature_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/abi_encode_with_signaturev2.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_with_signature_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encoder_v2_head_overflow_with_static_array_cleanup_bug.sol b/test/libsolidity/semanticTests/abicoder/bug_abi_encoder_v2_head_overflow_with_static_array_cleanup.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/abi_encoder_v2_head_overflow_with_static_array_cleanup_bug.sol rename to test/libsolidity/semanticTests/abicoder/bug_abi_encoder_v2_head_overflow_with_static_array_cleanup.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/byte_arrays.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/byte_arrays.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/byte_arrays.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/byte_arrays.sol diff --git a/test/libsolidity/semanticTests/array/calldata_array_two_dimensional_1.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_2d_dynamic_dynamic_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/array/calldata_array_two_dimensional_1.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_2d_dynamic_dynamic_v2.sol diff --git a/test/libsolidity/semanticTests/array/calldata_array_two_dimensional.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_2d_dynamic_static_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/array/calldata_array_two_dimensional.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_2d_dynamic_static_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/byte_arrays.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_bytes_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/byte_arrays.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_bytes_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_of_uint_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_of_uint_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_of_value_types_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_of_value_types_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic_static_dynamic.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_static_dynamic_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic_static_dynamic.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_static_dynamic_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic_static_in_library.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_static_in_library_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic_static_in_library.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_static_in_library_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic_static_short_decode.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_static_short_decode_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic_static_short_decode.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_static_short_decode_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic_static_short_reencode.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_static_short_reencode_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic_static_short_reencode.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_dynamic_static_short_reencode_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_function_types.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_function_types_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_function_types.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_function_types_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_array_access.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_1d_2d_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_array_access.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_1d_2d_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_three_dimensional_dynamic_array_index_access.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_3d_dynamic_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_three_dimensional_dynamic_array_index_access.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_3d_dynamic_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_array_three_dimensional.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_3d_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_array_three_dimensional.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_3d_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_array_dynamic_bytes.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_dynamic_bytes_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_array_dynamic_bytes.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_dynamic_bytes_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic_index_access.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_dynamic_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_dynamic_index_access.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_dynamic_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_static_index_access.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_static_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_static_index_access.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_static_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_array_length.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_length_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_array_length.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_length_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_multi_dynamic.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_multi_dynamic_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_multi_dynamic.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_multi_dynamic_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_array_index_range_access.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_slicing_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_array_index_range_access.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_slicing_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_static_dynamic_static.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_static_dynamic_static_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_static_dynamic_static.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_static_dynamic_static_v2.sol diff --git a/test/libsolidity/semanticTests/array/calldata_array.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_static_of_uint_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/array/calldata_array.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_static_of_uint_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_static.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_static_of_value_types_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_static.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_static_of_value_types_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_struct_dynamic.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_struct_dynamic_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_struct_dynamic.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_struct_dynamic_v2.sol diff --git a/test/libsolidity/semanticTests/array/calldata_array_of_struct.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_struct_static_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/array/calldata_array_of_struct.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_struct_static_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_two_dynamic.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_two_dynamic_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_two_dynamic.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_two_dynamic_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_two_static.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_two_static_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_two_static.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_two_static_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/calldata_bytes_bytes32_arrays.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_bytes_bytes32_arrays_v1.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/calldata_bytes_bytes32_arrays.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_bytes_bytes32_arrays_v1.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_dynamic_array_to_memory.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_dynamic_array_to_memory_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_dynamic_array_to_memory.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_dynamic_array_to_memory_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_nested_array_reencode.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_nested_array_reencode_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_nested_array_reencode.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_nested_array_reencode_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_nested_array_static_reencode.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_nested_array_static_reencode_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_nested_array_static_reencode.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_nested_array_static_reencode_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_overlapping_dynamic_arrays_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_dynamic_arrays.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_overlapping_dynamic_arrays_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_nested_dynamic_arrays.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_overlapping_nested_dynamic_arrays_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_overlapped_nested_dynamic_arrays.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_overlapping_nested_dynamic_arrays_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_string_array.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_string_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_string_array.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_string_array_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_array_reencode.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_struct_array_reencode_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_array_reencode.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_struct_array_reencode_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_fixed_arrays.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_arrays_static.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/abi_decode_fixed_arrays.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_arrays_static.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/memory_dynamic_array_and_calldata_bytes.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_array_and_calldata_bytes.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/memory_dynamic_array_and_calldata_bytes.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_array_and_calldata_bytes.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/memory_dynamic_array_and_calldata_static_array.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_array_and_calldata_static_array.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/memory_dynamic_array_and_calldata_static_array.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_array_and_calldata_static_array.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/dynamic_arrays.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_arrays.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/dynamic_arrays.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_arrays.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/dynamic_arrays.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_arrays_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/dynamic_arrays.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_arrays_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/dynamic_nested_arrays.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_nested_arrays_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/dynamic_nested_arrays.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_nested_arrays_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/memory_params_in_external_function.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_params_in_external_function.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/memory_params_in_external_function.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_params_in_external_function.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/memory_params_in_external_function.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_params_in_external_function_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/memory_params_in_external_function.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_params_in_external_function_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/copy_from_calldata_removes_bytes_data.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/copy_from_calldata_removes_bytes_data.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/copy_from_calldata_removes_bytes_data.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/struct/mediocre2_struct.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/mediocre_dynamic_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/struct/mediocre2_struct.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/mediocre_dynamic_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/struct/mediocre_struct.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/mediocre_static_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/struct/mediocre_struct.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/mediocre_static_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/dynamically_encoded.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_array_dynamic2_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/dynamically_encoded.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_array_dynamic2_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_array_member_dynamic.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_array_dynamic_multiple_fields_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_array_member_dynamic.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_array_dynamic_multiple_fields_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_dynamic.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_array_dynamic_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_dynamic.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_array_dynamic_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_array_member.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_array_static_mulitple_fields_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_array_member.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_array_static_mulitple_fields_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/struct/struct_function.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_external_function_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/struct/struct_function.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_external_function_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_member_offset.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_offset_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_member_offset.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/member_offset_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_structs.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/multiple_structs_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_structs.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/multiple_structs_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_struct_member.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/nested_static_3_fields_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_struct_member.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/nested_static_3_fields_v2.sol diff --git a/test/libsolidity/semanticTests/various/nested_calldata_struct.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/nested_static_4_fields_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/various/nested_calldata_struct.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/nested_static_4_fields_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_struct_member_dynamic.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/nested_with_bytes_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_struct_member_dynamic.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/nested_with_bytes_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_nested_structs.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/nested_with_dynamic_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_nested_structs.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/nested_with_dynamic_array_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/dynamic_nested.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/nested_with_dynamic_struct_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/dynamic_nested.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/nested_with_dynamic_struct_array_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/struct/struct_short.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/short_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/struct/struct_short.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/short_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/struct/struct_simple.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/simple_multiple_fields_short_types_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/struct/struct_simple.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/simple_multiple_fields_short_types_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/simple_multiple_fields_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/simple_multiple_fields_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_simple.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/simple_single_field_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_simple.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/simple_single_field_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_and_ints.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/struct_and_ints_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_and_ints.sol rename to test/libsolidity/semanticTests/abicoder/calldataDecoding/struct/struct_and_ints_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/cleanup/address.sol b/test/libsolidity/semanticTests/abicoder/cleanup/address_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/cleanup/address.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/address_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/bool_out_of_bounds.sol b/test/libsolidity/semanticTests/abicoder/cleanup/bool_v1.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/bool_out_of_bounds.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/bool_v1.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/bool_out_of_bounds.sol b/test/libsolidity/semanticTests/abicoder/cleanup/bool_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/bool_out_of_bounds.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/bool_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/cleanup/bool.sol b/test/libsolidity/semanticTests/abicoder/cleanup/bool_with_sanity_check_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/cleanup/bool.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/bool_with_sanity_check_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/cleanup/bytesx.sol b/test/libsolidity/semanticTests/abicoder/cleanup/bytesx_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/cleanup/bytesx.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/bytesx_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/cleanup/cleanup.sol b/test/libsolidity/semanticTests/abicoder/cleanup/cleanup_v1.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/cleanup/cleanup.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/cleanup_v1.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/cleanup/cleanup.sol b/test/libsolidity/semanticTests/abicoder/cleanup/cleanup_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/cleanup/cleanup.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/cleanup_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/cleanup/dynamic_array.sol b/test/libsolidity/semanticTests/abicoder/cleanup/dynamic_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/cleanup/dynamic_array.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/dynamic_array_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/enums.sol b/test/libsolidity/semanticTests/abicoder/cleanup/enum_v1.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/enums.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/enum_v1.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/enums.sol b/test/libsolidity/semanticTests/abicoder/cleanup/enum_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/enums.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/enum_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/cleanup/function.sol b/test/libsolidity/semanticTests/abicoder/cleanup/function_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/cleanup/function.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/function_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/cleanup/intx.sol b/test/libsolidity/semanticTests/abicoder/cleanup/intx_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/cleanup/intx.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/intx_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/cleanup/reencoded_calldata_string.sol b/test/libsolidity/semanticTests/abicoder/cleanup/reencoded_calldata_string.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/cleanup/reencoded_calldata_string.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/reencoded_calldata_string.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/cleanup/static_array.sol b/test/libsolidity/semanticTests/abicoder/cleanup/static_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/cleanup/static_array.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/static_array_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_struct_cleaning.sol b/test/libsolidity/semanticTests/abicoder/cleanup/struct2_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_struct_cleaning.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/struct2_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/cleanup/simple_struct.sol b/test/libsolidity/semanticTests/abicoder/cleanup/struct_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/cleanup/simple_struct.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/struct_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/cleanup/uintx.sol b/test/libsolidity/semanticTests/abicoder/cleanup/uintx_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/cleanup/uintx.sol rename to test/libsolidity/semanticTests/abicoder/cleanup/uintx_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/contract_array.sol b/test/libsolidity/semanticTests/abicoder/contract_array.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/contract_array.sol rename to test/libsolidity/semanticTests/abicoder/contract_array.sol diff --git a/test/libsolidity/semanticTests/abiEncodeDecode/contract_array_v2.sol b/test/libsolidity/semanticTests/abicoder/contract_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncodeDecode/contract_array_v2.sol rename to test/libsolidity/semanticTests/abicoder/contract_array_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol b/test/libsolidity/semanticTests/abicoder/libraryABI/storage_ptr.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/struct/struct_storage_ptr.sol rename to test/libsolidity/semanticTests/abicoder/libraryABI/storage_ptr.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/return_dynamic_types_cross_call_advanced.sol b/test/libsolidity/semanticTests/abicoder/return_dynamic_types_cross_call_advanced.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/return_dynamic_types_cross_call_advanced.sol rename to test/libsolidity/semanticTests/abicoder/return_dynamic_types_cross_call_advanced.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/return_dynamic_types_cross_call_out_of_range_1.sol b/test/libsolidity/semanticTests/abicoder/return_dynamic_types_cross_call_out_of_range_homestead.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/return_dynamic_types_cross_call_out_of_range_1.sol rename to test/libsolidity/semanticTests/abicoder/return_dynamic_types_cross_call_out_of_range_homestead.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/return_dynamic_types_cross_call_out_of_range_2.sol b/test/libsolidity/semanticTests/abicoder/return_dynamic_types_cross_call_out_of_range_post_homestead.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/return_dynamic_types_cross_call_out_of_range_2.sol rename to test/libsolidity/semanticTests/abicoder/return_dynamic_types_cross_call_out_of_range_post_homestead.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/return_dynamic_types_cross_call_simple.sol b/test/libsolidity/semanticTests/abicoder/return_dynamic_types_cross_call_simple.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/return_dynamic_types_cross_call_simple.sol rename to test/libsolidity/semanticTests/abicoder/return_dynamic_types_cross_call_simple.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_short_no_revert_string.sol b/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_no_revert_string.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_short_no_revert_string.sol rename to test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_no_revert_string.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_array_short.sol b/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_array_short.sol rename to test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV1/calldata_arrays_too_large.sol b/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV1/calldata_arrays_too_large.sol rename to test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types.sol diff --git a/test/libsolidity/semanticTests/array/calldata_array_dynamic_invalid_static_middle.sol b/test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_static_middle_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/array/calldata_array_dynamic_invalid_static_middle.sol rename to test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_static_middle_v2.sol diff --git a/test/libsolidity/semanticTests/array/calldata_array_dynamic_invalid.sol b/test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/array/calldata_array_dynamic_invalid.sol rename to test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_with_garbage.sol b/test/libsolidity/semanticTests/abicoder/validation/calldata_with_garbage_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/calldata_with_garbage.sol rename to test/libsolidity/semanticTests/abicoder/validation/calldata_with_garbage_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/struct/validation_function_type_inside_struct.sol b/test/libsolidity/semanticTests/abicoder/validation/external_function_type_inside_struct_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/struct/validation_function_type_inside_struct.sol rename to test/libsolidity/semanticTests/abicoder/validation/external_function_type_inside_struct_v2.sol diff --git a/test/libsolidity/semanticTests/abiEncoderV2/struct/struct_validation.sol b/test/libsolidity/semanticTests/abicoder/validation/static_struct_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/abiEncoderV2/struct/struct_validation.sol rename to test/libsolidity/semanticTests/abicoder/validation/static_struct_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_bytes_array_bounds.sol b/test/libsolidity/semanticTests/array/calldata_array_bounds_check_nested_bytes.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_bytes_array_bounds.sol rename to test/libsolidity/semanticTests/array/calldata_array_bounds_check_nested_bytes.sol diff --git a/test/libsolidity/semanticTests/array/calldata_bytes_array_bounds.sol b/test/libsolidity/semanticTests/array/calldata_array_bounds_check_nested_bytes2.sol similarity index 100% rename from test/libsolidity/semanticTests/array/calldata_bytes_array_bounds.sol rename to test/libsolidity/semanticTests/array/calldata_array_bounds_check_nested_bytes2.sol diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_memory.sol b/test/libsolidity/semanticTests/array/copying/nested_array_calldata_to_memory.sol similarity index 100% rename from test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_memory.sol rename to test/libsolidity/semanticTests/array/copying/nested_array_calldata_to_memory.sol diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_calldata_to_storage.sol similarity index 100% rename from test/libsolidity/semanticTests/array/copying/array_nested_calldata_to_storage.sol rename to test/libsolidity/semanticTests/array/copying/nested_array_calldata_to_storage.sol diff --git a/test/libsolidity/semanticTests/array/nested_calldata_storage2.sol b/test/libsolidity/semanticTests/array/copying/nested_array_dynamic_dynamic_calldata_to_storage.sol similarity index 100% rename from test/libsolidity/semanticTests/array/nested_calldata_storage2.sol rename to test/libsolidity/semanticTests/array/copying/nested_array_dynamic_dynamic_calldata_to_storage.sol diff --git a/test/libsolidity/semanticTests/array/nested_calldata_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_dynamic_static_calldata_to_storage.sol similarity index 100% rename from test/libsolidity/semanticTests/array/nested_calldata_storage.sol rename to test/libsolidity/semanticTests/array/copying/nested_array_dynamic_static_calldata_to_storage.sol diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol b/test/libsolidity/semanticTests/array/copying/nested_array_memory_to_storage.sol similarity index 100% rename from test/libsolidity/semanticTests/array/copying/array_nested_memory_to_storage.sol rename to test/libsolidity/semanticTests/array/copying/nested_array_memory_to_storage.sol diff --git a/test/libsolidity/semanticTests/array/copying/array_nested_storage_to_memory.sol b/test/libsolidity/semanticTests/array/copying/nested_array_storage_to_memory.sol similarity index 100% rename from test/libsolidity/semanticTests/array/copying/array_nested_storage_to_memory.sol rename to test/libsolidity/semanticTests/array/copying/nested_array_storage_to_memory.sol diff --git a/test/libsolidity/semanticTests/array/calldata_slice_access.sol b/test/libsolidity/semanticTests/array/slices/calldata_array_slicing.sol similarity index 100% rename from test/libsolidity/semanticTests/array/calldata_slice_access.sol rename to test/libsolidity/semanticTests/array/slices/calldata_array_slicing.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_bytes_to_memory.sol b/test/libsolidity/semanticTests/conversions/calldata_bytes_to_memory.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_bytes_to_memory.sol rename to test/libsolidity/semanticTests/conversions/calldata_bytes_to_memory.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_bytes_to_memory_encode.sol b/test/libsolidity/semanticTests/conversions/calldata_bytes_to_memory_reencode.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_bytes_to_memory_encode.sol rename to test/libsolidity/semanticTests/conversions/calldata_bytes_to_memory_reencode.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_memory_mixed.sol b/test/libsolidity/semanticTests/functionCall/calldata_and_memory_arguments.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_memory_mixed.sol rename to test/libsolidity/semanticTests/functionCall/calldata_and_memory_arguments.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_bytes_external.sol b/test/libsolidity/semanticTests/functionCall/calldata_argument_external_bytes.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_bytes_external.sol rename to test/libsolidity/semanticTests/functionCall/calldata_argument_external_bytes.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_bytes_internal.sol b/test/libsolidity/semanticTests/functionCall/calldata_argument_internal_bytes.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_bytes_internal.sol rename to test/libsolidity/semanticTests/functionCall/calldata_argument_internal_bytes.sol diff --git a/test/libsolidity/semanticTests/array/calldata_array_as_argument_internal_function.sol b/test/libsolidity/semanticTests/functionCall/calldata_argument_internal_dynamic_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/array/calldata_array_as_argument_internal_function.sol rename to test/libsolidity/semanticTests/functionCall/calldata_argument_internal_dynamic_array_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_internal_library.sol b/test/libsolidity/semanticTests/functionCall/calldata_argument_internal_library_bytes.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_internal_library.sol rename to test/libsolidity/semanticTests/functionCall/calldata_argument_internal_library_bytes.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_as_argument_of_lib_function.sol b/test/libsolidity/semanticTests/functionCall/calldata_argument_internal_library_dynamic_struct_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_as_argument_of_lib_function.sol rename to test/libsolidity/semanticTests/functionCall/calldata_argument_internal_library_dynamic_struct_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_struct.sol b/test/libsolidity/semanticTests/functionCall/calldata_argument_internal_library_static_struct_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_struct.sol rename to test/libsolidity/semanticTests/functionCall/calldata_argument_internal_library_static_struct_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_internal_multi_array.sol b/test/libsolidity/semanticTests/functionCall/calldata_argument_internal_multi_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_internal_multi_array.sol rename to test/libsolidity/semanticTests/functionCall/calldata_argument_internal_multi_array_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_internal_multi_fixed_array.sol b/test/libsolidity/semanticTests/functionCall/calldata_argument_internal_multi_static_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_internal_multi_fixed_array.sol rename to test/libsolidity/semanticTests/functionCall/calldata_argument_internal_multi_static_array_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_as_memory_argument.sol b/test/libsolidity/semanticTests/functionCall/calldata_argument_internal_struct_as_memory_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_as_memory_argument.sol rename to test/libsolidity/semanticTests/functionCall/calldata_argument_internal_struct_as_memory_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_struct_internal.sol b/test/libsolidity/semanticTests/functionCall/calldata_argument_internal_struct_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_struct_internal.sol rename to test/libsolidity/semanticTests/functionCall/calldata_argument_internal_struct_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_internal_function_pointer.sol b/test/libsolidity/semanticTests/functionTypes/internal_function_pointer_with_calldata_args.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_internal_function_pointer.sol rename to test/libsolidity/semanticTests/functionTypes/internal_function_pointer_with_calldata_args.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_attached_to_dynamic_array_or_slice.sol b/test/libsolidity/semanticTests/libraries/attached_internal_library_function_accepting_calldata_dynamic_array_or_slice_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_attached_to_dynamic_array_or_slice.sol rename to test/libsolidity/semanticTests/libraries/attached_internal_library_function_accepting_calldata_dynamic_array_or_slice_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_attached_to_static_array.sol b/test/libsolidity/semanticTests/libraries/attached_internal_library_function_accepting_calldata_static_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_attached_to_static_array.sol rename to test/libsolidity/semanticTests/libraries/attached_internal_library_function_accepting_calldata_static_array_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_attached_to_struct.sol b/test/libsolidity/semanticTests/libraries/attached_internal_library_function_accepting_calldata_struct_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_attached_to_struct.sol rename to test/libsolidity/semanticTests/libraries/attached_internal_library_function_accepting_calldata_struct_v2.sol diff --git a/test/libsolidity/semanticTests/calldata/calldata_attached_to_bytes.sol b/test/libsolidity/semanticTests/libraries/attached_internal_library_function_accepting_calldata_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/calldata/calldata_attached_to_bytes.sol rename to test/libsolidity/semanticTests/libraries/attached_internal_library_function_accepting_calldata_v2.sol diff --git a/test/libsolidity/semanticTests/libraries/attached_public_library_function_accepting_calldata.sol.sol b/test/libsolidity/semanticTests/libraries/attached_public_library_function_accepting_calldata.sol similarity index 100% rename from test/libsolidity/semanticTests/libraries/attached_public_library_function_accepting_calldata.sol.sol rename to test/libsolidity/semanticTests/libraries/attached_public_library_function_accepting_calldata.sol diff --git a/test/libsolidity/semanticTests/various/nested_calldata_struct_to_memory.sol b/test/libsolidity/semanticTests/structs/copy_struct_with_nested_struct_from_calldata_to_memory.sol similarity index 100% rename from test/libsolidity/semanticTests/various/nested_calldata_struct_to_memory.sol rename to test/libsolidity/semanticTests/structs/copy_struct_with_nested_struct_from_calldata_to_memory.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_bytes_to_memory.sol b/test/libsolidity/semanticTests/structs/struct_copy_calldata_to_memory_nested_bytes_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_bytes_to_memory.sol rename to test/libsolidity/semanticTests/structs/struct_copy_calldata_to_memory_nested_bytes_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_memory.sol b/test/libsolidity/semanticTests/structs/struct_copy_calldata_to_memory_nested_dynamic_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_memory.sol rename to test/libsolidity/semanticTests/structs/struct_copy_calldata_to_memory_nested_dynamic_array_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_array_to_memory.sol b/test/libsolidity/semanticTests/structs/struct_copy_calldata_to_memory_nested_static_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_array_to_memory.sol rename to test/libsolidity/semanticTests/structs/struct_copy_calldata_to_memory_nested_static_array_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_to_memory_tuple_assignment.sol b/test/libsolidity/semanticTests/structs/struct_copy_calldata_to_memory_tuple.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_to_memory_tuple_assignment.sol rename to test/libsolidity/semanticTests/structs/struct_copy_calldata_to_memory_tuple.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_to_memory.sol b/test/libsolidity/semanticTests/structs/struct_copy_calldata_to_memory_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_to_memory.sol rename to test/libsolidity/semanticTests/structs/struct_copy_calldata_to_memory_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol b/test/libsolidity/semanticTests/structs/struct_copy_calldata_to_storage_nested_dynamic_array_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_with_nested_array_to_storage.sol rename to test/libsolidity/semanticTests/structs/struct_copy_calldata_to_storage_nested_dynamic_array_v2.sol diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_to_storage.sol b/test/libsolidity/semanticTests/structs/struct_copy_calldata_to_storage_v2.sol similarity index 100% rename from test/libsolidity/semanticTests/structs/calldata/calldata_struct_to_storage.sol rename to test/libsolidity/semanticTests/structs/struct_copy_calldata_to_storage_v2.sol From c0a83bcacf73df34898883c2355b9ffe69d46e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 19 Feb 2026 15:25:59 +0100 Subject: [PATCH 1305/1340] calldata_array_dynamic_bytes.sol: Enable testing via Yul - The test does seem to pass now via both pipelines. --- .../array/calldata_array_indexing_dynamic_bytes_v2.sol | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_dynamic_bytes_v2.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_dynamic_bytes_v2.sol index 932f19610..d850d3812 100644 --- a/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_dynamic_bytes_v2.sol +++ b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/calldata_array_indexing_dynamic_bytes_v2.sol @@ -63,10 +63,6 @@ contract C { } } -// via yul disabled because of stack issues. - -// ==== -// compileViaYul: false // ---- // f1(bytes[1]): 0x20, 0x20, 0x3, hex"0102030000000000000000000000000000000000000000000000000000000000" -> 0x3, 0x1, 0x2, 0x3 // f2(bytes[1],bytes[1]): 0x40, 0xa0, 0x20, 0x3, hex"0102030000000000000000000000000000000000000000000000000000000000", 0x20, 0x2, hex"0102000000000000000000000000000000000000000000000000000000000000" -> 0x3, 0x1, 0x2, 0x3, 0x2, 0x1, 0x2 From 388b75d20b6b3ff0ef81bbf6823a575017111075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 19 Feb 2026 15:44:37 +0100 Subject: [PATCH 1306/1340] Fix whitespace in some abiEncodeDecode tests --- .../abi_decode_offset_overflow_in_array.sol | 19 +++++++++--------- .../abi_decode_offset_overflow_in_array_2.sol | 20 +++++++++---------- .../abi_decode_offset_overflow_in_array_3.sol | 8 ++++---- ..._exceeds_calldatasize_no_revert_string.sol | 1 - 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array.sol index 02937aced..e7de18d7a 100644 --- a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array.sol +++ b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array.sol @@ -6,16 +6,17 @@ contract Test { function test() public pure returns (uint) { uint[] memory before = new uint[](1); // at offset 0x80 // Two problems here: The first offset is zero, the second offset is missing. - bytes memory corrupt = abi.encode(uint(32), // offset to "tuple" - uint(0)); // bogus first element - /* - At this point the free pointer is 0x80 + 64 (size of before) + 32 (length field of corrupt) + 64 (two encoded words) + bytes memory corrupt = abi.encode( + uint(32), // offset to "tuple" + uint(0) // bogus first element + ); - Now let's put random junk into memory immediately after the bogus first element. Our goal is to overflow the read pointer to point to before. - The value read out at this point will be added to beginning of the encoded tuple, AKA corrupt + 64. We need then to write x where: - x + 0x80 + 64 (before) + 32 (length of corrupt) + 32 (first word of corrupt) = 0x80 (mod 2^256) - that is MAX_UINT - 128 - */ + // At this point the free pointer is 0x80 + 64 (size of before) + 32 (length field of corrupt) + 64 (two encoded words) + // + // Now let's put random junk into memory immediately after the bogus first element. Our goal is to overflow the read pointer to point to before. + // The value read out at this point will be added to beginning of the encoded tuple, AKA corrupt + 64. We need then to write x where: + // x + 0x80 + 64 (before) + 32 (length of corrupt) + 32 (first word of corrupt) = 0x80 (mod 2^256) + // that is MAX_UINT - 128 MemoryUint memory afterCorrupt; afterCorrupt.field = uint(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80); before[0] = 123456; diff --git a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_2.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_2.sol index 0a874914a..539f3f277 100644 --- a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_2.sol +++ b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_2.sol @@ -6,21 +6,21 @@ contract Test { } function withinArray() public pure returns (uint) { uint[] memory before = new uint[](1); - bytes memory corrupt = abi.encode(uint(32), - uint(2)); + bytes memory corrupt = abi.encode( + uint(32), + uint(2) + ); MemoryTuple memory afterCorrupt; before[0] = 123456; - /* - As above, but in this case we are adding to: - 0x80 + 64 (before) + 32 (length of corrupt) + 32 (offset) + 32 (field pointer) - giving MAX_UINT - 96 - */ + + // As above, but in this case we are adding to: + // 0x80 + 64 (before) + 32 (length of corrupt) + 32 (offset) + 32 (field pointer) + // giving MAX_UINT - 96 afterCorrupt.field1 = uint(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60); afterCorrupt.field2 = uint(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60); uint[][] memory decoded = abi.decode(corrupt, (uint[][])); - /* - Will return 123456 * 2, AKA before has been copied twice - */ + + //Will return 123456 * 2, AKA before has been copied twice return decoded[0][0] + decoded[1][0]; } } diff --git a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_3.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_3.sol index a20e9ae49..acd00e2b0 100644 --- a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_3.sol +++ b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_3.sol @@ -6,10 +6,10 @@ contract Test { function test() public pure returns (uint) { uint[] memory before = new uint[](1); // at offset 0x80 bytes memory corrupt = abi.encode( - uint(32), - uint(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80), - uint(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80) - ); + uint(32), + uint(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80), + uint(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80) + ); MemoryUint memory afterCorrupt; afterCorrupt.field = uint(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80); before[0] = 123456; diff --git a/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_no_revert_string.sol b/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_no_revert_string.sol index 7fc08caaf..f51c79ad3 100644 --- a/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_no_revert_string.sol +++ b/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_no_revert_string.sol @@ -5,4 +5,3 @@ contract C { // f(uint256[]): 0x20, 0 -> // f(uint256[]): 0x20, 1 -> FAILURE // f(uint256[]): 0x20, 2 -> FAILURE - From f5e733b80db2d58b83e6c1ff76ff5401ee4db480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 19 Feb 2026 19:23:58 +0100 Subject: [PATCH 1307/1340] Remove redundant ABI coder tests --- ...i_decode_from_calldata_static_array_v2.sol | 14 ---- .../abicoder/abi_encode_calldata_slice_v2.sol | 69 ------------------- ...=> abi_encode_empty_string_not_bytes0.sol} | 2 - .../abi_encode_empty_string_not_bytes0_v1.sol | 13 ---- .../abicoder/abi_encode_rational_v2.sol | 11 --- .../array/memory_dynamic_arrays_v2.sol | 10 --- .../memory_params_in_external_function_v2.sol | 18 ----- ...ldata_array_bounds_check_nested_bytes2.sol | 10 --- 8 files changed, 147 deletions(-) delete mode 100644 test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_static_array_v2.sol delete mode 100644 test/libsolidity/semanticTests/abicoder/abi_encode_calldata_slice_v2.sol rename test/libsolidity/semanticTests/abicoder/{abi_encode_empty_string_not_bytes0_v2.sol => abi_encode_empty_string_not_bytes0.sol} (88%) delete mode 100644 test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0_v1.sol delete mode 100644 test/libsolidity/semanticTests/abicoder/abi_encode_rational_v2.sol delete mode 100644 test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_arrays_v2.sol delete mode 100644 test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_params_in_external_function_v2.sol delete mode 100644 test/libsolidity/semanticTests/array/calldata_array_bounds_check_nested_bytes2.sol diff --git a/test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_static_array_v2.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_static_array_v2.sol deleted file mode 100644 index e228099c4..000000000 --- a/test/libsolidity/semanticTests/abicoder/abi_decode_from_calldata_static_array_v2.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma abicoder v2; - - -contract C { - function f(bytes calldata data) - external - pure - returns (uint256[2][3] memory) - { - return abi.decode(data, (uint256[2][3])); - } -} -// ---- -// f(bytes): 0x20, 0xc0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 -> 1, 2, 3, 4, 5, 6 diff --git a/test/libsolidity/semanticTests/abicoder/abi_encode_calldata_slice_v2.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_calldata_slice_v2.sol deleted file mode 100644 index 0c59c33c4..000000000 --- a/test/libsolidity/semanticTests/abicoder/abi_encode_calldata_slice_v2.sol +++ /dev/null @@ -1,69 +0,0 @@ -pragma abicoder v2; -contract C { - function enc_packed_bytes(bytes calldata data, uint256 start, uint256 end) external returns (bytes memory) { - return abi.encodePacked(data[start:end]); - } - function enc_packed_bytes_reference(bytes calldata data, uint256 start, uint256 end) external returns (bytes memory) { - return abi.encodePacked(bytes(data[start:end])); - } - - function enc_bytes(bytes calldata data, uint256 start, uint256 end) external returns (bytes memory) { - return abi.encode(data[start:end]); - } - function enc_bytes_reference(bytes calldata data, uint256 start, uint256 end) external returns (bytes memory) { - return abi.encode(bytes(data[start:end])); - } - - function enc_uint256(uint256[] calldata x, uint256 start, uint256 end) external returns (bytes memory) { - return abi.encode(x[start:end]); - } - function enc_uint256_reference(uint256[] calldata x, uint256 start, uint256 end) external returns (bytes memory) { - return abi.encode(x[start:end]); - } - - function enc_packed_uint256(uint256[] calldata x, uint256 start, uint256 end) external returns (bytes memory) { - return abi.encodePacked(x[start:end]); - } - function enc_packed_uint256_reference(uint256[] calldata x, uint256 start, uint256 end) external returns (bytes memory) { - return abi.encodePacked(x[start:end]); - } - - function compare(bytes memory x, bytes memory y) internal { - assert(x.length == y.length); - for (uint i = 0; i < x.length; ++i) - assert(x[i] == y[i]); - } - - function test_bytes() public { - bytes memory test = new bytes(3); - test[0] = 0x41; test[1] = 0x42; test[2] = 0x42; - for (uint i = 0; i < test.length; i++) - for (uint j = i; j <= test.length; j++) - { - compare(this.enc_packed_bytes(test, i, j), this.enc_packed_bytes_reference(test, i, j)); - compare(this.enc_bytes(test, i, j), this.enc_bytes_reference(test, i, j)); - } - } - - function test_uint256() public { - uint256[] memory test = new uint256[](3); - test[0] = 0x41; test[1] = 0x42; test[2] = 0x42; - for (uint i = 0; i < test.length; i++) - for (uint j = i; j <= test.length; j++) - { - compare(this.enc_packed_uint256(test, i, j), this.enc_packed_uint256_reference(test, i, j)); - compare(this.enc_uint256(test, i, j), this.enc_uint256_reference(test, i, j)); - } - } -} -// ==== -// EVMVersion: >homestead -// ---- -// test_bytes() -> -// gas irOptimized: 314884 -// gas legacy: 305816 -// gas legacyOptimized: 253573 -// test_uint256() -> -// gas irOptimized: 448346 -// gas legacy: 421304 -// gas legacyOptimized: 351544 diff --git a/test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0_v2.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0.sol similarity index 88% rename from test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0_v2.sol rename to test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0.sol index 849c24a91..4b88c099b 100644 --- a/test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0_v2.sol +++ b/test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0.sol @@ -1,7 +1,5 @@ // Tests that this will not end up using a "bytes0" type // (which would assert) -pragma abicoder v2; - contract C { function f() public pure returns (bytes memory, bytes memory) { diff --git a/test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0_v1.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0_v1.sol deleted file mode 100644 index 9f7216e6b..000000000 --- a/test/libsolidity/semanticTests/abicoder/abi_encode_empty_string_not_bytes0_v1.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma abicoder v1; -// Tests that this will not end up using a "bytes0" type -// (which would assert) -contract C { - function f() public pure returns (bytes memory, bytes memory) { - return (abi.encode(""), abi.encodePacked("")); - } -} -// ==== -// ABIEncoderV1Only: true -// compileViaYul: false -// ---- -// f() -> 0x40, 0xa0, 0x40, 0x20, 0x0, 0x0 diff --git a/test/libsolidity/semanticTests/abicoder/abi_encode_rational_v2.sol b/test/libsolidity/semanticTests/abicoder/abi_encode_rational_v2.sol deleted file mode 100644 index edd319d45..000000000 --- a/test/libsolidity/semanticTests/abicoder/abi_encode_rational_v2.sol +++ /dev/null @@ -1,11 +0,0 @@ -// Tests that rational numbers (even negative ones) are encoded properly. -pragma abicoder v2; - - -contract C { - function f() public pure returns (bytes memory) { - return abi.encode(1, -2); - } -} -// ---- -// f() -> 0x20, 0x40, 0x1, -2 diff --git a/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_arrays_v2.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_arrays_v2.sol deleted file mode 100644 index e8b64a108..000000000 --- a/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_dynamic_arrays_v2.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma abicoder v2; - -contract C { - function f(uint a, uint16[] memory b, uint c) - public pure returns (uint, uint, uint) { - return (b.length, b[a], c); - } -} -// ---- -// f(uint256,uint16[],uint256): 6, 0x60, 9, 7, 11, 12, 13, 14, 15, 16, 17 -> 7, 17, 9 diff --git a/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_params_in_external_function_v2.sol b/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_params_in_external_function_v2.sol deleted file mode 100644 index f8beb5703..000000000 --- a/test/libsolidity/semanticTests/abicoder/calldataDecoding/array/memory_params_in_external_function_v2.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma abicoder v2; - -contract C { - function f(bytes memory a, bytes calldata b, uint[] memory c) - external - pure - returns (uint, bytes1, uint, bytes1, uint, uint) - { - return (a.length, a[1], b.length, b[2], c.length, c[3]); - } - function g() public returns (uint, bytes1, uint, bytes1, uint, uint) { - uint[] memory x = new uint[](4); - x[3] = 7; - return this.f("abc", "def", x); - } -} -// ---- -// g() -> 3, 0x6200000000000000000000000000000000000000000000000000000000000000, 3, 0x6600000000000000000000000000000000000000000000000000000000000000, 4, 7 diff --git a/test/libsolidity/semanticTests/array/calldata_array_bounds_check_nested_bytes2.sol b/test/libsolidity/semanticTests/array/calldata_array_bounds_check_nested_bytes2.sol deleted file mode 100644 index d6ff4679f..000000000 --- a/test/libsolidity/semanticTests/array/calldata_array_bounds_check_nested_bytes2.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma abicoder v2; -contract C { - function f(bytes[] calldata a, uint256 i) external returns (uint) { - return uint8(a[0][i]); - } -} -// ---- -// f(bytes[],uint256): 0x40, 0, 1, 0x20, 2, 0x6162000000000000000000000000000000000000000000000000000000000000 -> 0x61 -// f(bytes[],uint256): 0x40, 1, 1, 0x20, 2, 0x6162000000000000000000000000000000000000000000000000000000000000 -> 0x62 -// f(bytes[],uint256): 0x40, 2, 1, 0x20, 2, 0x6162000000000000000000000000000000000000000000000000000000000000 -> FAILURE, hex"4e487b71", 0x32 From 511cdc067c56f51328ce3a31bfd4dbdb85a46ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 19 Feb 2026 15:46:49 +0100 Subject: [PATCH 1308/1340] Enable debug revert strings in some of the existing calldata/encoding tests --- .../abi_decode_offset_overflow_in_array.sol | 4 +++- .../abi_decode_offset_overflow_in_array_2.sol | 4 +++- .../abi_decode_offset_overflow_in_array_3.sol | 4 +++- .../validation/array_exceeds_calldatasize_v1.sol | 13 +++++++++++++ ..._exceeds_size_limit_for_calldata_types_v1.sol | 13 +++++++++++++ ...exceeds_size_limit_for_calldata_types_v2.sol} | 6 +++++- ...ta_array_dynamic_invalid_static_middle_v2.sol | 13 +++++++------ .../calldata_array_dynamic_invalid_v2.sol | 11 ++++++----- .../validation/calldata_with_garbage_v2.sol | 16 +++++++++------- .../external_function_type_inside_struct_v2.sol | 4 +++- .../abicoder/validation/static_struct_v2.sol | 4 +++- 11 files changed, 68 insertions(+), 24 deletions(-) create mode 100644 test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_v1.sol create mode 100644 test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types_v1.sol rename test/libsolidity/semanticTests/abicoder/validation/{array_exceeds_size_limit_for_calldata_types.sol => array_exceeds_size_limit_for_calldata_types_v2.sol} (66%) diff --git a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array.sol index e7de18d7a..29eb1483c 100644 --- a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array.sol +++ b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array.sol @@ -24,5 +24,7 @@ contract Test { return decoded[1][0]; } } +// ==== +// revertStrings: debug // ---- -// test() -> FAILURE +// test() -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray stride" diff --git a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_2.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_2.sol index 539f3f277..78bf581f0 100644 --- a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_2.sol +++ b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_2.sol @@ -24,5 +24,7 @@ contract Test { return decoded[0][0] + decoded[1][0]; } } +// ==== +// revertStrings: debug // ---- -// withinArray() -> FAILURE +// withinArray() -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray stride" diff --git a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_3.sol b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_3.sol index acd00e2b0..4eb871c2a 100644 --- a/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_3.sol +++ b/test/libsolidity/semanticTests/abicoder/abi_decode_offset_overflow_in_array_3.sol @@ -17,5 +17,7 @@ contract Test { return decoded[1][0]; } } +// ==== +// revertStrings: debug // ---- -// test() -> FAILURE +// test() -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray offset" diff --git a/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_v1.sol b/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_v1.sol new file mode 100644 index 000000000..ba4394247 --- /dev/null +++ b/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_calldatasize_v1.sol @@ -0,0 +1,13 @@ +pragma abicoder v1; + +contract C { + function f(uint[] calldata) public {} +} +// ==== +// ABIEncoderV1Only: true +// compileViaYul: false +// revertStrings: debug +// ---- +// f(uint256[]): 0x20, 0 -> +// f(uint256[]): 0x20, 1 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI calldata decoding: invalid d", "ata pointer" +// f(uint256[]): 0x20, 2 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI calldata decoding: invalid d", "ata pointer" diff --git a/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types_v1.sol b/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types_v1.sol new file mode 100644 index 000000000..44eade500 --- /dev/null +++ b/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types_v1.sol @@ -0,0 +1,13 @@ +pragma abicoder v1; + +contract C { + function f(uint a, uint[] calldata b, uint c) external pure returns (uint) { + return 7; + } +} +// ==== +// ABIEncoderV1Only: true +// compileViaYul: false +// revertStrings: debug +// ---- +// f(uint256,uint256[],uint256): 6, 0x60, 9, 0x8000000000000000000000000000000000000000000000000000000000000002, 1, 2 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI calldata decoding: invalid d", "ata pointer" diff --git a/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types.sol b/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types_v2.sol similarity index 66% rename from test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types.sol rename to test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types_v2.sol index 49bee94ea..01573d614 100644 --- a/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types.sol +++ b/test/libsolidity/semanticTests/abicoder/validation/array_exceeds_size_limit_for_calldata_types_v2.sol @@ -1,7 +1,11 @@ +pragma abicoder v2; + contract C { function f(uint a, uint[] calldata b, uint c) external pure returns (uint) { return 7; } } +// ==== +// revertStrings: debug // ---- -// f(uint256,uint256[],uint256): 6, 0x60, 9, 0x8000000000000000000000000000000000000000000000000000000000000002, 1, 2 -> FAILURE +// f(uint256,uint256[],uint256): 6, 0x60, 9, 0x8000000000000000000000000000000000000000000000000000000000000002, 1, 2 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray length" diff --git a/test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_static_middle_v2.sol b/test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_static_middle_v2.sol index 93470f1d2..117ea020a 100644 --- a/test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_static_middle_v2.sol +++ b/test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_static_middle_v2.sol @@ -1,5 +1,4 @@ -pragma abicoder v2; - +pragma abicoder v2; contract C { function f(uint256[][1][] calldata a) external returns (uint256) { @@ -16,14 +15,16 @@ contract C { return 42; } } +// ==== +// revertStrings: debug // ---- // f(uint256[][1][]): 0x20, 0x0 -> 42 # valid access stub # -// f(uint256[][1][]): 0x20, 0x1 -> FAILURE # invalid on argument decoding # +// f(uint256[][1][]): 0x20, 0x1 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray stride" # invalid on argument decoding # // f(uint256[][1][]): 0x20, 0x1, 0x20 -> 42 # invalid on outer access # -// g(uint256[][1][]): 0x20, 0x1, 0x20 -> FAILURE +// g(uint256[][1][]): 0x20, 0x1, 0x20 -> FAILURE, hex"08c379a0", 0x20, 0x1c, "Invalid calldata tail offset" // f(uint256[][1][]): 0x20, 0x1, 0x20, 0x20 -> 42 # invalid on inner access # // g(uint256[][1][]): 0x20, 0x1, 0x20, 0x20 -> 42 -// h(uint256[][1][]): 0x20, 0x1, 0x20, 0x20 -> FAILURE +// h(uint256[][1][]): 0x20, 0x1, 0x20, 0x20 -> FAILURE, hex"08c379a0", 0x20, 0x1c, "Invalid calldata tail offset" // f(uint256[][1][]): 0x20, 0x1, 0x20, 0x20, 0x1 -> 42 // g(uint256[][1][]): 0x20, 0x1, 0x20, 0x20, 0x1 -> 42 -// h(uint256[][1][]): 0x20, 0x1, 0x20, 0x20, 0x1 -> FAILURE +// h(uint256[][1][]): 0x20, 0x1, 0x20, 0x20, 0x1 -> FAILURE, hex"08c379a0", 0x20, 0x17, "Calldata tail too short" diff --git a/test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_v2.sol b/test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_v2.sol index dc1d1c31a..e3fd7d6fc 100644 --- a/test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_v2.sol +++ b/test/libsolidity/semanticTests/abicoder/validation/calldata_array_dynamic_invalid_v2.sol @@ -1,5 +1,4 @@ -pragma abicoder v2; - +pragma abicoder v2; contract C { function f(uint256[][] calldata a) external returns (uint256) { @@ -11,10 +10,12 @@ contract C { return 42; } } +// ==== +// revertStrings: debug // ---- // f(uint256[][]): 0x20, 0x0 -> 42 # valid access stub # -// f(uint256[][]): 0x20, 0x1 -> FAILURE # invalid on argument decoding # +// f(uint256[][]): 0x20, 0x1 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray stride" # invalid on argument decoding # // f(uint256[][]): 0x20, 0x1, 0x20 -> 42 # invalid on outer access # -// g(uint256[][]): 0x20, 0x1, 0x20 -> FAILURE +// g(uint256[][]): 0x20, 0x1, 0x20 -> FAILURE, hex"08c379a0", 0x20, 0x1c, "Invalid calldata tail offset" // f(uint256[][]): 0x20, 0x1, 0x20, 0x2, 0x42 -> 42 # invalid on inner access # -// g(uint256[][]): 0x20, 0x1, 0x20, 0x2, 0x42 -> FAILURE +// g(uint256[][]): 0x20, 0x1, 0x20, 0x2, 0x42 -> FAILURE, hex"08c379a0", 0x20, 0x17, "Calldata tail too short" diff --git a/test/libsolidity/semanticTests/abicoder/validation/calldata_with_garbage_v2.sol b/test/libsolidity/semanticTests/abicoder/validation/calldata_with_garbage_v2.sol index 58f68b8cc..3c759b00b 100644 --- a/test/libsolidity/semanticTests/abicoder/validation/calldata_with_garbage_v2.sol +++ b/test/libsolidity/semanticTests/abicoder/validation/calldata_with_garbage_v2.sol @@ -39,28 +39,30 @@ contract C { return (a[which], b[0]); } } +// ==== +// revertStrings: debug // ---- // f_memory(uint256[]): 0x80, 9, 9, 9, 0 -> 0x20, 0 // f_memory(uint256[]): 0x80, 9, 9, 9, 1, 7 -> 0x20, 1, 7 -// f_memory(uint256[]): 0x80, 9, 9, 9, 2, 7 -> FAILURE +// f_memory(uint256[]): 0x80, 9, 9, 9, 2, 7 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray stride" // f_encode(uint256[]): 0x80, 9, 9, 9, 0 -> 0x20, 0x40, 0x20, 0 // f_encode(uint256[]): 0x80, 9, 9, 9, 1, 7 -> 0x20, 0x60, 0x20, 1, 7 -// f_encode(uint256[]): 0x80, 9, 9, 9, 2, 7 -> FAILURE +// f_encode(uint256[]): 0x80, 9, 9, 9, 2, 7 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray stride" // f_storage(uint256[]): 0x80, 9, 9, 9, 0 -> 0x20, 0x40, 0x20, 0 // f_storage(uint256[]): 0x80, 9, 9, 9, 1, 7 -> 0x20, 0x60, 0x20, 1, 7 -// f_storage(uint256[]): 0x80, 9, 9, 9, 2, 7 -> FAILURE +// f_storage(uint256[]): 0x80, 9, 9, 9, 2, 7 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray stride" // f_index(uint256[],uint256): 0xa0, 0, 9, 9, 9, 2, 7, 8 -> 7 // f_index(uint256[],uint256): 0xa0, 1, 9, 9, 9, 2, 7, 8 -> 8 // f_index(uint256[],uint256): 0xa0, 2, 9, 9, 9, 2, 7, 8 -> FAILURE, hex"4e487b71", 0x32 // g_memory(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 0 -> 0x60, 1, 2, 0 // g_memory(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 1, 7 -> 0x60, 1, 2, 1, 7 -// g_memory(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 2, 7 -> FAILURE +// g_memory(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 2, 7 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray stride" // g_encode(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 0 -> 0x20, 0x80, 0x60, 1, 2, 0 // g_encode(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 1, 7 -> 0x20, 0xa0, 0x60, 1, 2, 1, 7 -// g_encode(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 2, 7 -> FAILURE +// g_encode(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 2, 7 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray stride" // g_storage(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 0 -> 0x20, 0x80, 0x60, 1, 2, 0 // g_storage(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 1, 7 -> 0x20, 0xa0, 0x60, 1, 2, 1, 7 -// g_storage(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 2, 7 -> FAILURE +// g_storage(uint256[],uint256[2]): 0xc0, 1, 2, 9, 9, 9, 2, 7 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray stride" // g_index(uint256[],uint256[2],uint256): 0xe0, 1, 2, 0, 9, 9, 9, 2, 7, 8 -> 7, 1 // g_index(uint256[],uint256[2],uint256): 0xe0, 1, 2, 1, 9, 9, 9, 2, 7, 8 -> 8, 1 -// g_index(uint256[],uint256[2],uint256): 0xe0, 1, 2, 1, 9, 9, 9, 2, 7 -> FAILURE +// g_index(uint256[],uint256[2],uint256): 0xe0, 1, 2, 1, 9, 9, 9, 2, 7 -> FAILURE, hex"08c379a0", 0x20, 43, "ABI decoding: invalid calldata a", "rray stride" diff --git a/test/libsolidity/semanticTests/abicoder/validation/external_function_type_inside_struct_v2.sol b/test/libsolidity/semanticTests/abicoder/validation/external_function_type_inside_struct_v2.sol index 8a22b037f..d405711de 100644 --- a/test/libsolidity/semanticTests/abicoder/validation/external_function_type_inside_struct_v2.sol +++ b/test/libsolidity/semanticTests/abicoder/validation/external_function_type_inside_struct_v2.sol @@ -1,4 +1,4 @@ -pragma abicoder v2; +pragma abicoder v2; contract C { struct S { function () external x; } @@ -6,6 +6,8 @@ contract C { function g(S calldata) external pure returns (uint r) { r = 2; } function h(S calldata s) external pure returns (uint r) { s.x; r = 3; } } +// ==== +// revertStrings: debug // ---- // f((function)): "01234567890123456789abcd" -> 1 // f((function)): "01234567890123456789abcdX" -> FAILURE diff --git a/test/libsolidity/semanticTests/abicoder/validation/static_struct_v2.sol b/test/libsolidity/semanticTests/abicoder/validation/static_struct_v2.sol index 57e218f7d..2197d3ed2 100644 --- a/test/libsolidity/semanticTests/abicoder/validation/static_struct_v2.sol +++ b/test/libsolidity/semanticTests/abicoder/validation/static_struct_v2.sol @@ -1,4 +1,4 @@ -pragma abicoder v2; +pragma abicoder v2; contract C { struct S { int16 a; uint8 b; bytes2 c; } @@ -10,6 +10,8 @@ contract C { } } } +// ==== +// revertStrings: debug // ---- // f((int16,uint8,bytes2)): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01, 0xff, "ab" -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01, 0xff, "ab" // f((int16,uint8,bytes2)): 0xff010, 0xff, "ab" -> FAILURE From 21fe3315d84fc62619a82c957f9d406392d807ec Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 4 May 2026 11:42:52 +0200 Subject: [PATCH 1309/1340] SSA CFG: introduce projections for functions with multiple return values --- libyul/backends/evm/ssa/CodeTransform.cpp | 28 +- libyul/backends/evm/ssa/CodeTransform.h | 6 +- libyul/backends/evm/ssa/InstructionStore.h | 75 ++-- libyul/backends/evm/ssa/LivenessAnalysis.cpp | 16 +- libyul/backends/evm/ssa/LivenessAnalysis.h | 4 +- libyul/backends/evm/ssa/PhiInverse.cpp | 8 +- libyul/backends/evm/ssa/PhiInverse.h | 6 +- libyul/backends/evm/ssa/SSACFG.cpp | 24 +- libyul/backends/evm/ssa/SSACFG.h | 246 +++++++++---- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 62 ++-- libyul/backends/evm/ssa/SSACFGBuilder.h | 30 +- libyul/backends/evm/ssa/SSACFGDebugInfo.h | 6 +- libyul/backends/evm/ssa/SSACFGTypes.cpp | 13 +- libyul/backends/evm/ssa/SSACFGTypes.h | 51 +-- libyul/backends/evm/ssa/Stack.cpp | 12 +- libyul/backends/evm/ssa/Stack.h | 35 +- .../backends/evm/ssa/StackLayoutGenerator.cpp | 53 +-- libyul/backends/evm/ssa/StackShuffler.cpp | 2 +- libyul/backends/evm/ssa/StackShuffler.h | 14 +- libyul/backends/evm/ssa/StackSlotLiveness.h | 2 +- .../backends/evm/ssa/StackToMemorySpilling.h | 6 +- libyul/backends/evm/ssa/StackUtils.cpp | 16 +- .../backends/evm/ssa/io/DotExporterBase.cpp | 4 +- libyul/backends/evm/ssa/io/JSONExporter.cpp | 17 +- .../ssa/transform/TrivialPhiEliminator.cpp | 52 +-- .../standard_yul_cfg_json_export/output.json | 332 +++++++++--------- .../strict_asm_yul_cfg_json_export/output | 24 +- test/cmdlineTests/yul_cfg_json_export/output | 332 +++++++++--------- test/libyul/ssa/StackLayoutGeneratorTest.cpp | 17 +- test/libyul/ssa/StackShufflerTest.cpp | 19 +- test/libyul/ssa/controlFlowGraph/complex.yul | 24 +- test/libyul/ssa/controlFlowGraph/complex2.yul | 24 +- test/libyul/ssa/controlFlowGraph/function.yul | 6 +- .../ssa/stackLayoutGenerator/dead_code.yul | 12 +- .../ssa/stackLayoutGenerator/function.yul | 4 +- .../ssa/stackLayoutGenerator/multi_return.yul | 12 +- .../ssa/stackLayoutGenerator/simple_if.yul | 6 +- 37 files changed, 834 insertions(+), 766 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 2be3eb0c2..07a9f24a4 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -161,8 +161,8 @@ CodeTransform::CodeTransform( expectedStackTop.reserve(m_cfg.arguments.size() + (isFunctionGraph && m_cfg.canContinue ? 1 : 0)); if (isFunctionGraph && m_cfg.canContinue) expectedStackTop.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); - for (auto const& valueID: m_cfg.arguments | ranges::views::reverse) - expectedStackTop.push_back(StackSlot::makeValueID(_cfg, valueID)); + for (auto const& arg: m_cfg.arguments | ranges::views::reverse) + expectedStackTop.push_back(StackSlot::makeValue(_cfg, arg)); assertLayoutCompatibility(m_stack.data(), expectedStackTop); } @@ -234,7 +234,7 @@ void CodeTransform::operator()(InstId _instId, StackData const& _operationInputL m_stack | ranges::views::take_last(_inst.inputs.size()), _inst.inputs )) - yulAssert(stackEntry.isValueID() && stackEntry.valueID() == input); + yulAssert(stackEntry.isValue() && stackEntry.value() == input); // if the function can continue (doesn't always abort), make sure we have the correct return label slot in place if (hasReturnLabel) @@ -309,16 +309,18 @@ void CodeTransform::operator()(InstId _instId, StackData const& _operationInputL for (size_t i = 0; i < _inst.inputs.size(); ++i) m_stack.pop(); // simulate that the outputs are produced - for (auto value: SSACFG::outputsOf(_instId, _inst.numOutputs)) - m_stack.push(StackSlot::makeValueID(m_cfg, value)); + std::vector outputs; + outputs.reserve(m_cfg.numReturnsOf(_instId)); + m_cfg.forEachOutput(_instId, [&](InstId const id) { outputs.push_back(id); }); + for (InstId const id: outputs) + m_stack.push(StackSlot::makeValue(m_cfg, id)); - // Assert that the operation produced its proclaimed output. - yulAssert(m_stack.size() == baseHeight + _inst.numOutputs); + yulAssert(m_stack.size() == baseHeight + outputs.size()); for (auto const& [stackEntry, output]: ranges::views::zip( - m_stack.data() | ranges::views::take_last(_inst.numOutputs), - SSACFG::outputsOf(_instId, _inst.numOutputs) + m_stack.data() | ranges::views::take_last(outputs.size()), + outputs )) - yulAssert(stackEntry.isValueID() && stackEntry.valueID() == output); + yulAssert(stackEntry.isValue() && stackEntry.value() == output); yulAssert( static_cast(m_stack.size()) == m_assembly.stackHeight(), fmt::format("symbolic stack size = {} =/= {} = assembly stack height", m_stack.size(), m_assembly.stackHeight()) @@ -335,7 +337,7 @@ void CodeTransform::operator()(SSACFG::BlockId const& _currentBlock, SSACFG::Bas { yulAssert(static_cast(m_stack.size()) == m_assembly.stackHeight()); // condition must be at the top of the stack - yulAssert(m_stack.top().isValueID() && m_stack.top().valueID() == _conditionalJump.condition); + yulAssert(m_stack.top().isValue() && m_stack.top().value() == _conditionalJump.condition); // emit JUMPI to nonZero block m_assembly.appendJumpToIf(m_blockLabels[_conditionalJump.nonZero.value]); // update symbolic stack by popping the condition as it'll be consumed by JUMPI @@ -391,8 +393,8 @@ void CodeTransform::operator()(SSACFG::BlockId const&, SSACFG::BasicBlock::Funct for (std::size_t i = 0; i < _functionReturn.returnValues.size(); ++i) { auto const& returnValueSlot = m_stack.slot(StackOffset{i}); - yulAssert(returnValueSlot.isValueID()); - yulAssert(returnValueSlot.valueID() == _functionReturn.returnValues[i]); + yulAssert(returnValueSlot.isValue()); + yulAssert(returnValueSlot.value() == _functionReturn.returnValues[i]); } m_assembly.appendJump(0, AbstractAssembly::JumpType::OutOfFunction); } diff --git a/libyul/backends/evm/ssa/CodeTransform.h b/libyul/backends/evm/ssa/CodeTransform.h index 6a141a70d..a11fd1df9 100644 --- a/libyul/backends/evm/ssa/CodeTransform.h +++ b/libyul/backends/evm/ssa/CodeTransform.h @@ -49,11 +49,11 @@ struct AssemblyCallbacks { switch (_slot.kind()) { - case StackSlot::Kind::ValueID: + case StackSlot::Kind::Value: { - auto const id = _slot.valueID(); + auto const id = _slot.value(); yulAssert(cfg->isLiteral(id), fmt::format("Tried bringing up non-const {}", id)); - assembly->appendConstant(cfg->literalPayload(id.instId())); + assembly->appendConstant(cfg->literalPayload(id)); return; } case StackSlot::Kind::Junk: diff --git a/libyul/backends/evm/ssa/InstructionStore.h b/libyul/backends/evm/ssa/InstructionStore.h index 1b4d82a1f..ba134ac47 100644 --- a/libyul/backends/evm/ssa/InstructionStore.h +++ b/libyul/backends/evm/ssa/InstructionStore.h @@ -31,9 +31,6 @@ #include -#include -#include - #include #include #include @@ -48,6 +45,8 @@ class InstructionStore /// Sentinel value for `Inst::payloadIndex` when the opcode has no side-table payload. static constexpr std::uint32_t NoPayload = std::numeric_limits::max(); + using NumReturnsSizeType = std::uint8_t; + struct BuiltinCall { BuiltinHandle builtin; @@ -58,20 +57,21 @@ class InstructionStore { FunctionGraphID graphID; bool canContinue; + std::size_t numReturns; }; struct Inst { InstOpcode opcode; - ValueId::OutputSize numOutputs; std::uint32_t payloadIndex = NoPayload; BlockId block{}; - std::vector inputs{}; + std::vector inputs{}; constexpr bool isPhi() const noexcept { return opcode == InstOpcode::Phi; } constexpr bool isUpsilon() const noexcept { return opcode == InstOpcode::Upsilon; } constexpr bool isLiteral() const noexcept { return opcode == InstOpcode::Const; } constexpr bool isUnreachable() const noexcept { return opcode == InstOpcode::Unreachable; } constexpr bool isFunctionArg() const noexcept { return opcode == InstOpcode::FunctionArg; } + constexpr bool isProjection() const noexcept { return opcode == InstOpcode::Projection; } /// Operation = a Call or BuiltinCall. constexpr bool isOperation() const noexcept { @@ -91,23 +91,11 @@ class InstructionStore std::size_t numInsts() const { return m_insts.size(); } std::vector const& instructions() const { return m_insts; } - static auto outputsOf(InstId const _id, ValueId::OutputSize const _numOutputs) - { - return - ranges::views::iota(ValueId::OutputSize{0}, _numOutputs) | - ranges::views::transform([_id](ValueId::OutputSize const _pos) { return ValueId{_id, _pos}; }); - } - - auto instOutputs(InstId const _id) const - { - return outputsOf(_id, inst(_id).numOutputs); - } - - /// Returns the opcode category for a given ValueId. - InstOpcode kindOf(ValueId const _v) const { return inst(_v.instId()).opcode; } + /// Returns the opcode category for a given InstId. + InstOpcode kindOf(InstId const _id) const { return inst(_id).opcode; } /// Returns the phi targeted by an Upsilon Inst. - ValueId upsilonPhi(InstId const _id) const { return payloadAs(_id, m_upsilonPhis); } + InstId upsilonPhi(InstId const _id) const { return payloadAs(_id, m_upsilonPhis); } /// Returns the u256 payload of a Const Inst. u256 const& literalPayload(InstId const _id) const { return payloadAs(_id, m_literalPayloads); } @@ -116,22 +104,35 @@ class InstructionStore Call const& callPayload(InstId const _id) const { return payloadAs(_id, m_callPayloads); } + /// Returns the projection index of a Projection Inst + NumReturnsSizeType projectionIndex(InstId const _id) const + { + Inst const& projectionInst = inst(_id); + yulAssert(projectionInst.opcode == InstOpcode::Projection); + yulAssert(projectionInst.inputs.size() == 1); + InstId const producer = projectionInst.inputs.front(); + yulAssert(_id.value > producer.value); + std::size_t const offset = static_cast(_id.value) - static_cast(producer.value) - 1; + yulAssert(offset <= std::numeric_limits::max()); + return static_cast(offset); + } + /// Allocates a new Phi Inst defined in `_definingBlock`. Returns the new InstId. InstId appendPhi(BlockId const _definingBlock) { - return appendInst(Inst{InstOpcode::Phi, 1, NoPayload, _definingBlock, {}}); + return appendInst(Inst{InstOpcode::Phi, NoPayload, _definingBlock, {}}); } /// Allocates a new FunctionArg Inst defined in `_entryBlock`. Returns the new InstId. InstId appendFunctionArg(BlockId const _entryBlock) { - return appendInst(Inst{InstOpcode::FunctionArg, 1, NoPayload, _entryBlock, {}}); + return appendInst(Inst{InstOpcode::FunctionArg, NoPayload, _entryBlock, {}}); } /// Allocates a new Unreachable Inst. Not pinned to any block (see class comment). InstId appendUnreachable() { - return appendInst(Inst{InstOpcode::Unreachable, 1, NoPayload, BlockId{}, {}}); + return appendInst(Inst{InstOpcode::Unreachable, NoPayload, BlockId{}, {}}); } /// Allocates a new Const Inst with payload `_value`, pinned to `_entryBlock`. @@ -142,7 +143,7 @@ class InstructionStore if (auto const it = m_literalDedup.find(_value); it != m_literalDedup.end()) return it->second; auto const payloadIdx = allocPayload(m_literalPayloads, _value); - InstId const id = appendInst(Inst{InstOpcode::Const, 1, payloadIdx, _entryBlock, {}}); + InstId const id = appendInst(Inst{InstOpcode::Const, payloadIdx, _entryBlock, {}}); m_literalDedup.emplace(std::move(_value), id); return id; } @@ -151,15 +152,12 @@ class InstructionStore InstId appendBuiltinCall( BlockId const _block, BuiltinCall _payload, - std::vector _inputs, - std::size_t const _numOutputs + std::vector _inputs ) { yulAssert(_block.hasValue()); - yulAssert(_numOutputs <= std::numeric_limits::max()); return appendInst(Inst{ InstOpcode::BuiltinCall, - static_cast(_numOutputs), allocPayload(m_builtinPayloads, std::move(_payload)), _block, std::move(_inputs) @@ -170,26 +168,31 @@ class InstructionStore InstId appendCall( BlockId const _block, Call _payload, - std::vector _inputs, - std::size_t const _numOutputs + std::vector _inputs ) { yulAssert(_block.hasValue()); - yulAssert(_numOutputs <= std::numeric_limits::max()); return appendInst(Inst{ InstOpcode::Call, - static_cast(_numOutputs), allocPayload(m_callPayloads, std::move(_payload)), _block, std::move(_inputs) }); } + /// Allocates a new Projection Inst projecting output `_index` of `_producer`. + InstId appendProjection(BlockId const _block, InstId const _producer) + { + yulAssert(_block.hasValue()); + yulAssert(_producer.hasValue()); + return appendInst(Inst{InstOpcode::Projection, NoPayload, _block, {_producer}}); + } + /// Allocates a new Upsilon Inst targeting `_phi`, feeding `_value` from `_block`. - InstId appendUpsilon(BlockId const _block, ValueId const _value, ValueId const _phi) + InstId appendUpsilon(BlockId const _block, InstId const _value, InstId const _phi) { - yulAssert(inst(_phi.instId()).isPhi()); - return appendInst(Inst{InstOpcode::Upsilon, 0, allocPayload(m_upsilonPhis, _phi), _block, {_value}}); + yulAssert(inst(_phi).isPhi()); + return appendInst(Inst{InstOpcode::Upsilon, allocPayload(m_upsilonPhis, _phi), _block, {_value}}); } private: @@ -225,7 +228,7 @@ class InstructionStore std::vector m_insts; std::vector m_literalPayloads; std::map m_literalDedup; - std::vector m_upsilonPhis; + std::vector m_upsilonPhis; std::vector m_builtinPayloads; std::vector m_callPayloads; }; diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp index e5c2e7f57..2eba9b19e 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -83,7 +84,7 @@ void LivenessAnalysis::runDagDfs() // live <- PhiUses(B) LivenessData live{}; m_cfg.forEachUpsilon(block, [&](InstId, SSACFG::Inst const& inst) { - SSACFG::ValueId const v = inst.inputs.at(0); + InstId const v = inst.inputs.at(0); yulAssert(!m_cfg.isUnreachable(v)); if (!m_cfg.isLiteral(v)) live.insert(v); @@ -97,7 +98,7 @@ void LivenessAnalysis::runDagDfs() // LiveIn(S) - PhiDefs(S) auto liveInWithoutPhiDefs = m_liveIns[_successor.value]; m_cfg.forEachPhi(m_cfg.block(_successor), [&](InstId const succInstId, SSACFG::Inst const&) { - liveInWithoutPhiDefs.erase(ValueId{succInstId}); + liveInWithoutPhiDefs.erase(succInstId); }); live.maxUnion(liveInWithoutPhiDefs); } @@ -123,15 +124,15 @@ void LivenessAnalysis::runDagDfs() if (!inst.isOperation()) continue; // remove variables defined at p from live - live.eraseAll(SSACFG::outputsOf(instId, inst.numOutputs) | ranges::views::filter(excludingLiteralsFilter())); - // add uses at p to live + live.eraseAll(m_cfg.projectionsOf(instId)); + live.erase(instId); live.insertAll(inst.inputs | ranges::views::filter(excludingLiteralsFilter())); } } // livein(b) <- live \cup PhiDefs(B) m_cfg.forEachPhi(block, [&](InstId const instId, SSACFG::Inst const&) { - live.insert(ValueId{instId}); + live.insert(instId); }); m_liveIns[blockId.value] = live; } @@ -147,7 +148,7 @@ void LivenessAnalysis::runLoopTreeDfs(SSACFG::BlockId::ValueType const _loopHead // LiveLoop <- LiveIn(B_N) - PhiDefs(B_N) auto liveLoop = m_liveIns[_loopHeader]; m_cfg.forEachPhi(block, [&](InstId const instId, SSACFG::Inst const&) { - liveLoop.erase(ValueId{instId}); + liveLoop.erase(instId); }); // must be live out of header if live in of children m_liveOuts[_loopHeader].maxUnion(liveLoop); @@ -186,7 +187,8 @@ void LivenessAnalysis::fillOperationsLiveOut() if (!inst.isOperation()) continue; *rit = live; - live.eraseAll(SSACFG::outputsOf(instId, inst.numOutputs) | ranges::views::filter(excludingLiteralsFilter())); + live.eraseAll(m_cfg.projectionsOf(instId)); + live.erase(instId); live.insertAll(inst.inputs | ranges::views::filter(excludingLiteralsFilter())); ++rit; } diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.h b/libyul/backends/evm/ssa/LivenessAnalysis.h index db8eedf80..548366538 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.h +++ b/libyul/backends/evm/ssa/LivenessAnalysis.h @@ -36,7 +36,7 @@ class LivenessAnalysis public: /// Per-program-point liveness, each value's use count is the max number of times the value will be read along /// all paths downstream of that point - using LivenessData = util::UseCountSet; + using LivenessData = util::UseCountSet; explicit LivenessAnalysis(SSACFG const& _cfg); @@ -55,7 +55,7 @@ class LivenessAnalysis auto excludingLiteralsFilter() const { - return [this](SSACFG::ValueId _v) { return !m_cfg.isLiteral(_v); }; + return [this](InstId _v) { return !m_cfg.isLiteral(_v); }; } SSACFG const& m_cfg; diff --git a/libyul/backends/evm/ssa/PhiInverse.cpp b/libyul/backends/evm/ssa/PhiInverse.cpp index f686a1bfb..ad7506f51 100644 --- a/libyul/backends/evm/ssa/PhiInverse.cpp +++ b/libyul/backends/evm/ssa/PhiInverse.cpp @@ -24,8 +24,8 @@ PhiInverse::PhiInverse(SSACFG const& _cfg, SSACFG::BlockId const& _from, SSACFG: { _cfg.forEachUpsilon(_cfg.block(_from), [&](InstId const instId, SSACFG::Inst const& inst) { if ( - ValueId const phi = _cfg.upsilonPhi(instId); - _cfg.inst(phi.instId()).block == _to + InstId const phi = _cfg.upsilonPhi(instId); + _cfg.inst(phi).block == _to ) m_phiToPreImage[phi] = inst.inputs.at(0); }); @@ -36,12 +36,12 @@ bool PhiInverse::noOp() const return m_phiToPreImage.empty(); } -SSACFG::ValueId PhiInverse::operator()(SSACFG::ValueId _valueId) const +InstId PhiInverse::operator()(InstId _valueId) const { return solidity::util::valueOrDefault(m_phiToPreImage, _valueId, _valueId); } -std::map const& PhiInverse::data() const +std::map const& PhiInverse::data() const { return m_phiToPreImage; } diff --git a/libyul/backends/evm/ssa/PhiInverse.h b/libyul/backends/evm/ssa/PhiInverse.h index 3f29aae46..7ecdf2446 100644 --- a/libyul/backends/evm/ssa/PhiInverse.h +++ b/libyul/backends/evm/ssa/PhiInverse.h @@ -35,12 +35,12 @@ class PhiInverse /// whether the transform is guaranteed to be a no-op, ie, there is no phi function in `_to` bool noOp() const; - SSACFG::ValueId operator()(SSACFG::ValueId _valueId) const; + InstId operator()(InstId _valueId) const; - std::map const& data() const; + std::map const& data() const; private: - std::map m_phiToPreImage = {}; + std::map m_phiToPreImage = {}; }; } diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index a38dac770..35389a9d8 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -41,7 +41,7 @@ namespace /// Build a human-readable Phi/Upsilon annotation for a phi value. /// Shows which upsilons feed it, listed per predecessor block. -std::string formatPhi(SSACFG const& _cfg, ValueId _phiId) +std::string formatPhi(SSACFG const& _cfg, InstId _phiId) { // Collect all upsilons targeting _phiId from the whole CFG. std::vector formattedUpsilons; @@ -73,7 +73,7 @@ class SSACFGDotExporter: public io::DotExporterBase void writeBlockLabel(std::ostream& _out, BlockId _blockId) override { auto const& block = m_cfg.block(_blockId); - auto const valueToString = [&](ValueId const& valueId) { return valueId.str(m_cfg); }; + auto const valueToString = [&](InstId const& valueId) { return valueId.str(m_cfg); }; if (m_liveness) { @@ -101,10 +101,10 @@ class SSACFGDotExporter: public io::DotExporterBase _out << fmt::format("\\\nBlock {}\\n", _blockId.value); // Phis first, then BuiltinCall / Call in program order. Upsilons are rendered - // under successor phis (via formatPhi) and skipped here. + // under successor phis (via formatPhi) and skipped here. Trailing Projections of + // multi-return calls are rendered as standalone lines following their producer. m_cfg.forEachPhi(block, [&](InstId const instId, SSACFG::Inst const&) { - ValueId const phi{instId}; - _out << fmt::format("phi{} := {}\\l\\\n", instId.value, formatPhi(m_cfg, phi)); + _out << fmt::format("phi{} := {}\\l\\\n", instId.value, formatPhi(m_cfg, instId)); }); m_cfg.forEachOperation(block, [&](InstId const instId, SSACFG::Inst const& inst) { std::string label; @@ -115,16 +115,20 @@ class SSACFGDotExporter: public io::DotExporterBase } else label = m_cfg.evmDialect.builtin(m_cfg.builtinPayload(instId).builtin).name; - if (inst.numOutputs > 0) - _out << fmt::format( - "{} := ", - fmt::join(SSACFG::outputsOf(instId, inst.numOutputs) | ranges::views::transform(valueToString), ", ") - ); + if (m_cfg.numReturnsOf(instId) >= 1) + _out << fmt::format("{} := ", valueToString(instId)); _out << fmt::format( "{}({})\\l\\\n", escapeLabel(label), fmt::join(inst.inputs | ranges::views::transform(valueToString), ", ") ); + for (InstId const projId: m_cfg.projectionsOf(instId)) + _out << fmt::format( + "{} := {}.proj({})\\l\\\n", + valueToString(projId), + valueToString(instId), + static_cast(m_cfg.projectionIndex(projId)) + ); }); } diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 3bf03f98e..a71748267 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -27,13 +27,16 @@ #include -#include -#include #include #include #include +#include +#include +#include +#include + #include #include #include @@ -64,7 +67,6 @@ class SSACFG ~SSACFG() = default; using BlockId = ssa::BlockId; - using ValueId = ssa::ValueId; using BuiltinCall = InstructionStore::BuiltinCall; using Call = InstructionStore::Call; @@ -75,7 +77,7 @@ class SSACFG struct MainExit {}; struct ConditionalJump { - ValueId condition; + InstId condition; BlockId nonZero; BlockId zero; }; @@ -85,7 +87,7 @@ class SSACFG }; struct FunctionReturn { - std::vector returnValues; + std::vector returnValues; }; struct Terminated {}; std::vector entries; @@ -132,34 +134,19 @@ class SSACFG size_t numInsts() const { return m_instructions.numInsts(); } std::vector const& instructions() const { return m_instructions.instructions(); } - static auto outputsOf(InstId const _id, ValueId::OutputSize const _numOutputs) - { - return InstructionStore::outputsOf(_id, _numOutputs); - } - - auto instOutputs(InstId const _id) const - { - return m_instructions.instOutputs(_id); - } - - /// Returns the opcode category for a given ValueId. - InstOpcode kindOf(ValueId const _v) const { return m_instructions.kindOf(_v); } + /// Returns the opcode category for a given InstId. + InstOpcode kindOf(InstId const _id) const { return m_instructions.kindOf(_id); } bool isPhi(InstId const _id) const { return inst(_id).isPhi(); } - bool isPhi(ValueId const _v) const { return isPhi(_v.instId()); } bool isUpsilon(InstId const _id) const { return inst(_id).isUpsilon(); } - bool isUpsilon(ValueId const _v) const { return isUpsilon(_v.instId()); } bool isLiteral(InstId const _id) const { return inst(_id).isLiteral(); } - bool isLiteral(ValueId const _v) const { return isLiteral(_v.instId()); } bool isUnreachable(InstId const _id) const { return inst(_id).isUnreachable(); } - bool isUnreachable(ValueId const _v) const { return isUnreachable(_v.instId()); } bool isFunctionArg(InstId const _id) const { return inst(_id).isFunctionArg(); } - bool isFunctionArg(ValueId const _v) const { return isFunctionArg(_v.instId()); } + bool isProjection(InstId const _id) const { return inst(_id).isProjection(); } bool isOperation(InstId const _id) const { return inst(_id).isOperation(); } - bool isOperation(ValueId const _v) const { return isOperation(_v.instId()); } /// Returns the phi targeted by an Upsilon Inst. - ValueId upsilonPhi(InstId const _id) const { return m_instructions.upsilonPhi(_id); } + InstId upsilonPhi(InstId const _id) const { return m_instructions.upsilonPhi(_id); } /// Returns the u256 payload of a Const Inst. u256 const& literalPayload(InstId const _id) const { return m_instructions.literalPayload(_id); } @@ -168,89 +155,81 @@ class SSACFG Call const& callPayload(InstId const _id) const { return m_instructions.callPayload(_id); } - /// Creates a Phi Inst in the given block and returns its output ValueId. - ValueId newPhi(BlockId const _definingBlock) + /// Returns the projection index of a Projection Inst. + InstructionStore::NumReturnsSizeType projectionIndex(InstId const _id) const { return m_instructions.projectionIndex(_id); } + + /// Creates a Phi Inst in the given block and returns its InstId. + InstId newPhi(BlockId const _definingBlock) { InstId const id = scheduleInBlock(m_instructions.appendPhi(_definingBlock), _definingBlock); - ValueId const v{id}; if (debugInfo) - debugInfo->setValueDebugData(v, debugInfo->blockDebugData(_definingBlock)); - return v; + debugInfo->setValueDebugData(id, debugInfo->blockDebugData(_definingBlock)); + return id; } - ValueId newFunctionArgument() + InstId newFunctionArgument() { InstId const id = scheduleInBlock(m_instructions.appendFunctionArg(entry), entry); - ValueId const v{id}; if (debugInfo) - debugInfo->setValueDebugData(v, debugInfo->blockDebugData(entry)); - return v; + debugInfo->setValueDebugData(id, debugInfo->blockDebugData(entry)); + return id; } - ValueId unreachableValue() + InstId unreachableValue() { - return ValueId{m_instructions.appendUnreachable()}; + return m_instructions.appendUnreachable(); } - /// Literal ValueIds are deduplicated. Const Insts are pinned to the entry block. - ValueId newLiteral(langutil::DebugData::ConstPtr _debugData, u256 _value) + /// Literal InstIds are deduplicated. Const Insts are pinned to the entry block. + InstId newLiteral(langutil::DebugData::ConstPtr _debugData, u256 _value) { - auto const beforeCount = m_instructions.numInsts(); + auto const previousNumInsts = m_instructions.numInsts(); InstId const id = m_instructions.appendLiteral(entry, std::move(_value)); - ValueId const v{id}; // Newly allocated (not deduplicated): schedule in entry and attach debug data. - if (m_instructions.numInsts() > beforeCount) + if (m_instructions.numInsts() > previousNumInsts) { scheduleInBlock(id, entry); if (debugInfo) - debugInfo->setValueDebugData(v, std::move(_debugData)); + debugInfo->setValueDebugData(id, std::move(_debugData)); } - return v; + return id; } - InstId makeBuiltinCall( + /// Allocates a BuiltinCall at `_block` and, for `_numReturns >= 2`, the `_numReturns` matching + /// Projections immediately after it in `m_insts`. + InstId makeBuiltinCallWithProjections( BlockId const _block, BuiltinCall _payload, - std::vector _inputs, - std::size_t const _numOutputs, + std::vector _inputs, + InstructionStore::NumReturnsSizeType const _numReturns, langutil::DebugData::ConstPtr _debugData = {} ) { - yulAssert( - _numOutputs <= ValueId::maxOutputs, - fmt::format("SSA CFG: BuiltinCall with {} outputs exceeds the maximum of {}.", _numOutputs, ValueId::maxOutputs) - ); - InstId const id = scheduleInBlock( - m_instructions.appendBuiltinCall(_block, std::move(_payload), std::move(_inputs), _numOutputs), - _block - ); - if (debugInfo && _debugData) - debugInfo->setInstDebugData(id, std::move(_debugData)); - return id; + InstId const producer = makeBuiltinCall(_block, std::move(_payload), std::move(_inputs), _debugData); + if (_numReturns >= 2) + for (InstructionStore::NumReturnsSizeType i = 0; i < _numReturns; ++i) + makeProjection(_block, producer, _debugData); + return producer; } - InstId makeCall( + /// Allocates a user Call at `_block` and, for `_numReturns >= 2`, the `_numReturns` matching + /// Projections immediately after it in `m_insts`. See `makeBuiltinCallWithProjections`. + InstId makeCallWithProjections( BlockId const _block, Call _payload, - std::vector _inputs, - std::size_t const _numOutputs, + std::vector _inputs, + InstructionStore::NumReturnsSizeType const _numReturns, langutil::DebugData::ConstPtr _debugData = {} ) { - yulAssert( - _numOutputs <= ValueId::maxOutputs, - fmt::format("SSA CFG: Call with {} outputs exceeds the maximum of {}.", _numOutputs, ValueId::maxOutputs) - ); - InstId const id = scheduleInBlock( - m_instructions.appendCall(_block, std::move(_payload), std::move(_inputs), _numOutputs), - _block - ); - if (debugInfo && _debugData) - debugInfo->setInstDebugData(id, std::move(_debugData)); - return id; + InstId const producer = makeCall(_block, std::move(_payload), std::move(_inputs), _debugData); + if (_numReturns >= 2) + for (InstructionStore::NumReturnsSizeType i = 0; i < _numReturns; ++i) + makeProjection(_block, producer, _debugData); + return producer; } - InstId emitUpsilon(BlockId const _block, ValueId _value, ValueId const _phi) + InstId emitUpsilon(BlockId const _block, InstId const _value, InstId const _phi) { return scheduleInBlock(m_instructions.appendUpsilon(_block, _value, _phi), _block); } @@ -278,7 +257,7 @@ class SSACFG std::set exits; std::string name{}; bool canContinue = true; - std::vector arguments; + std::vector arguments; std::size_t numReturns = 0; bool isMainGraph() const { return name.empty(); } @@ -307,20 +286,135 @@ class SSACFG forEachInstWhere(*this, _block, &Inst::isUpsilon, std::forward(_fn)); } - /// Iterates `_block.instructions`, invoking `_fn(instId, inst)` for every operation - /// (Call or BuiltinCall). - template + /// Iterates `_block.instructions`, invoking `_fn(instId, inst)` for every operation. Trailing + /// Projections are skipped here; access them via `projectionsOf(instId)` / `forEachOutput(instId, ...)`. + template Callable> void forEachOperation(BasicBlock const& _block, Callable&& _fn) { forEachInstWhere(*this, _block, &Inst::isOperation, std::forward(_fn)); } - template + template Callable> void forEachOperation(BasicBlock const& _block, Callable&& _fn) const { forEachInstWhere(*this, _block, &Inst::isOperation, std::forward(_fn)); } + std::size_t numReturnsOf(InstId _op) const + { + auto const& i = inst(_op); + switch (i.opcode) + { + case InstOpcode::Call: + return callPayload(_op).numReturns; + case InstOpcode::BuiltinCall: + return evmDialect.builtin(builtinPayload(_op).builtin).numReturns; + default: + yulAssert(false, fmt::format("numReturnsOf called on non-operation inst {}", _op)); + } + } + + /// View over the contiguous trailing Projections of `_producer` in `m_insts`. Empty for ops with <= 1 returns. + /// Note this relies on the m_insts-contiguity invariant established by `make(Builtin)CallWithProjections`: + /// projections live at `m_insts[_producer.value+1..+numReturns]`. + auto projectionsOf(InstId const _producer) const + { + std::size_t const n = numReturnsOf(_producer); + std::size_t const count = n >= 2 ? n : 0; + std::size_t const firstIdx = static_cast(_producer.value) + 1; + std::size_t const lastIdx = firstIdx + count; + // `appendInst` already caps `numInsts()` below `max(InstId::ValueType)`, so this also guarantees + // the casts to `InstId::ValueType` below cannot wrap. + yulAssert( + lastIdx <= numInsts(), + fmt::format( + "Producer {} declares {} returns but only {} trailing m_insts slots are available", + _producer, n, numInsts() - firstIdx + ) + ); + for (std::size_t v = firstIdx; v < lastIdx; ++v) + { + auto const& trailing = inst(InstId{static_cast(v)}); + yulAssert( + trailing.isProjection() && trailing.inputs.size() == 1 && trailing.inputs.front() == _producer, + fmt::format("Trailing slot {} is not a Projection of producer {}", InstId{static_cast(v)}, _producer) + ); + } + return + ranges::views::iota(static_cast(firstIdx), static_cast(lastIdx)) | + ranges::views::transform([](InstId::ValueType const _idVal) { return InstId{_idVal}; }); + } + + /// Invokes `_fn(InstId)` once per logical output of `_producer` in stack order. + template Fn> + void forEachOutput(InstId const _producer, Fn&& _fn) const + { + auto const n = numReturnsOf(_producer); + if (n == 0) + return; + if (n == 1) + { + _fn(_producer); + return; + } + for (InstId const id: projectionsOf(_producer)) + _fn(id); + } + private: + InstId makeBuiltinCall( + BlockId const _block, + BuiltinCall _payload, + std::vector _inputs, + langutil::DebugData::ConstPtr _debugData = {} + ) + { + InstId const id = scheduleInBlock( + m_instructions.appendBuiltinCall(_block, std::move(_payload), std::move(_inputs)), + _block + ); + if (debugInfo && _debugData) + debugInfo->setInstDebugData(id, std::move(_debugData)); + return id; + } + + InstId makeCall( + BlockId const _block, + Call _payload, + std::vector _inputs, + langutil::DebugData::ConstPtr _debugData = {} + ) + { + InstId const id = scheduleInBlock( + m_instructions.appendCall(_block, std::move(_payload), std::move(_inputs)), + _block + ); + if (debugInfo && _debugData) + debugInfo->setInstDebugData(id, std::move(_debugData)); + return id; + } + + InstId makeProjection( + BlockId const _block, + InstId const _producer, + langutil::DebugData::ConstPtr _debugData = {} + ) + { + yulAssert( + _block == m_instructions.inst(_producer).block, + fmt::format( + "Projection must live in the producer's block (producer block={}, requested block={})", + m_instructions.inst(_producer).block.value, _block.value + ) + ); + InstId const id = scheduleInBlock( + m_instructions.appendProjection(_block, _producer), + _block + ); + if (debugInfo && _debugData) + debugInfo->setValueDebugData(id, std::move(_debugData)); + return id; + } + /// Shared implementation for the public `forEach*` overloads; works for both /// `SSACFG&` and `SSACFG const&` since `_self.inst(id)` propagates const-ness. template diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 9e530f55b..d65c28460 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -147,8 +147,7 @@ void SSACFGBuilder::operator()(ExpressionStatement const& _expressionStatement) { auto const* functionCall = std::get_if(&_expressionStatement.expression); yulAssert(functionCall); - InstId const id = visitFunctionCall(*functionCall); - yulAssert(m_graph.inst(id).numOutputs == 0); + visitFunctionCall(*functionCall); } void SSACFGBuilder::operator()(Assignment const& _assignment) @@ -233,15 +232,15 @@ void SSACFGBuilder::operator()(Switch const& _switch) std::optional equalityBuiltinHandle = m_dialect.equalityFunctionHandle(); yulAssert(equalityBuiltinHandle); + auto const& equalityBuiltin = m_dialect.builtin(*equalityBuiltinHandle); auto makeValueCompare = [&](Case const& _case) { - InstId const id = m_graph.makeBuiltinCall( + return m_graph.makeBuiltinCallWithProjections( m_currentBlock, SSACFG::BuiltinCall{*equalityBuiltinHandle, {}}, {m_graph.newLiteral(debugDataOf(_case), _case.value->value.value()), expression}, - 1, + static_cast(equalityBuiltin.numReturns), debugDataOf(_case) ); - return ValueId{id}; }; auto afterSwitch = m_graph.makeBlock(currentBlockDebugData()); @@ -401,20 +400,19 @@ void SSACFGBuilder::operator()(Block const& _block) std::visit(*this, statement); } -SSACFG::ValueId SSACFGBuilder::operator()(FunctionCall const& _call) +InstId SSACFGBuilder::operator()(FunctionCall const& _call) { - InstId const id = visitFunctionCall(_call); - yulAssert(m_graph.inst(id).numOutputs == 1); - return SSACFG::ValueId{id}; + // Single-output expression context: the call's InstId is itself the value handle. + return visitFunctionCall(_call); } -SSACFG::ValueId SSACFGBuilder::operator()(Identifier const& _identifier) +InstId SSACFGBuilder::operator()(Identifier const& _identifier) { auto const& var = lookupVariable(_identifier.name); return readVariable(var, m_currentBlock); } -SSACFG::ValueId SSACFGBuilder::operator()(Literal const& _literal) +InstId SSACFGBuilder::operator()(Literal const& _literal) { return m_graph.newLiteral(currentBlockDebugData(), _literal.value.value()); } @@ -423,10 +421,12 @@ void SSACFGBuilder::assign(std::vector(_expression)) { - InstId const id = visitFunctionCall(*functionCall); - yulAssert(m_graph.inst(id).numOutputs == _variables.size()); - for (auto const& [var, value]: ranges::zip_view(_variables, m_graph.instOutputs(id))) - writeVariable(var, m_currentBlock, value); + InstId const callId = visitFunctionCall(*functionCall); + std::vector outputs; + m_graph.forEachOutput(callId, [&](InstId const id) { outputs.push_back(id); }); + yulAssert(outputs.size() == _variables.size()); + for (auto const& [var, output]: ranges::zip_view(_variables, outputs)) + writeVariable(var, m_currentBlock, output); return; } auto const rhs = _expression ? @@ -452,16 +452,16 @@ InstId SSACFGBuilder::visitFunctionCall(FunctionCall const& _call) yulAssert(std::holds_alternative(arg)); literalArguments.emplace_back(std::get(arg)); } - std::vector inputs; + std::vector inputs; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) if (!builtin.literalArgument(idx).has_value()) inputs.emplace_back(std::visit(*this, arg)); canContinue = builtin.controlFlowSideEffects.canContinue; - return m_graph.makeBuiltinCall( + return m_graph.makeBuiltinCallWithProjections( m_currentBlock, SSACFG::BuiltinCall{_builtinName.handle, std::move(literalArguments)}, std::move(inputs), - builtin.numReturns, + static_cast(builtin.numReturns), debugDataOf(_call) ); }, @@ -474,14 +474,14 @@ InstId SSACFGBuilder::visitFunctionCall(FunctionCall const& _call) canContinue = m_sideEffects.functionSideEffects().at(definition).canContinue; auto const calleeIt = m_functionScopeToID.find(&function); yulAssert(calleeIt != m_functionScopeToID.end(), "Called function has no registered graph id."); - std::vector inputs; + std::vector inputs; for (auto const& arg: _call.arguments | ranges::views::reverse) inputs.emplace_back(std::visit(*this, arg)); - return m_graph.makeCall( + return m_graph.makeCallWithProjections( m_currentBlock, - SSACFG::Call{calleeIt->second, canContinue}, + SSACFG::Call{calleeIt->second, canContinue, function.numReturns}, std::move(inputs), - function.numReturns, + static_cast(function.numReturns), debugDataOf(_call) ); } @@ -495,12 +495,12 @@ InstId SSACFGBuilder::visitFunctionCall(FunctionCall const& _call) return id; } -SSACFG::ValueId SSACFGBuilder::zero() +InstId SSACFGBuilder::zero() { return m_graph.newLiteral(currentBlockDebugData(), 0u); } -SSACFG::ValueId SSACFGBuilder::readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block) +InstId SSACFGBuilder::readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block) { auto const& def = currentDef(_variable, _block); if (def.hasValue()) @@ -508,12 +508,12 @@ SSACFG::ValueId SSACFGBuilder::readVariable(Scope::Variable const& _variable, SS return readVariableRecursive(_variable, _block); } -SSACFG::ValueId SSACFGBuilder::readVariableRecursive(Scope::Variable const& _variable, SSACFG::BlockId _block) +InstId SSACFGBuilder::readVariableRecursive(Scope::Variable const& _variable, SSACFG::BlockId _block) { auto& block = m_graph.block(_block); auto& info = blockInfo(_block); - SSACFG::ValueId val; + InstId val; if (!info.sealed) { // incomplete block: create a phi and defer upsilon emission until the block is sealed @@ -534,9 +534,9 @@ SSACFG::ValueId SSACFGBuilder::readVariableRecursive(Scope::Variable const& _var return val; } -void SSACFGBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi) +void SSACFGBuilder::addPhiOperands(Scope::Variable const& _variable, InstId _phi) { - SSACFG::BlockId const phiBlock = m_graph.inst(_phi.instId()).block; + SSACFG::BlockId const phiBlock = m_graph.inst(_phi).block; for (auto const& pred: m_graph.block(phiBlock).entries) { auto const val = readVariable(_variable, pred); @@ -544,13 +544,13 @@ void SSACFGBuilder::addPhiOperands(Scope::Variable const& _variable, SSACFG::Val } } -void SSACFGBuilder::emitUpsilon(SSACFG::BlockId _block, SSACFG::ValueId _value, SSACFG::ValueId _phi) +void SSACFGBuilder::emitUpsilon(SSACFG::BlockId _block, InstId _value, InstId _phi) { yulAssert(m_graph.isPhi(_phi)); m_graph.emitUpsilon(_block, _value, _phi); } -void SSACFGBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value) +void SSACFGBuilder::writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, InstId _value) { currentDef(_variable, _block) = _value; } @@ -597,7 +597,7 @@ void SSACFGBuilder::sealBlock(SSACFG::BlockId _block) void SSACFGBuilder::conditionalJump( langutil::DebugData::ConstPtr _debugData, - SSACFG::ValueId _condition, + InstId _condition, SSACFG::BlockId _nonZero, SSACFG::BlockId _zero ) diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index 2cbf07da4..a5fc326b8 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -43,6 +43,8 @@ #include #include +#include + #include #include #include @@ -84,24 +86,26 @@ class SSACFGBuilder void operator()(Block const& _block); - SSACFG::ValueId operator()(FunctionCall const& _call); - SSACFG::ValueId operator()(Identifier const& _identifier); - SSACFG::ValueId operator()(Literal const& _literal); + InstId operator()(FunctionCall const& _call); + InstId operator()(Identifier const& _identifier); + InstId operator()(Literal const& _literal); private: void assign(std::vector> _variables, Expression const* _expression); + /// Visits a function call expression and returns the InstId of the producing operation. + /// For multi-output operations the call inserts projection operations into the current block. InstId visitFunctionCall(FunctionCall const& _call); void registerFunctionDefinition(FunctionDefinition const& _functionDefinition); void buildFunctionGraph(Scope::Function const* _function, FunctionDefinition const* _functionDefinition); - SSACFG::ValueId zero(); - SSACFG::ValueId readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block); - SSACFG::ValueId readVariableRecursive(Scope::Variable const& _variable, SSACFG::BlockId _block); + InstId zero(); + InstId readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block); + InstId readVariableRecursive(Scope::Variable const& _variable, SSACFG::BlockId _block); /// Emit upsilons in each predecessor of _phi's block, recording the phi pre-images. - void addPhiOperands(Scope::Variable const& _variable, SSACFG::ValueId _phi); + void addPhiOperands(Scope::Variable const& _variable, InstId _phi); /// Emit a single Upsilon(_value -> _phi) into block _block. - void emitUpsilon(SSACFG::BlockId _block, SSACFG::ValueId _value, SSACFG::ValueId _phi); - void writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, SSACFG::ValueId _value); + void emitUpsilon(SSACFG::BlockId _block, InstId _value, InstId _phi); + void writeVariable(Scope::Variable const& _variable, SSACFG::BlockId _block, InstId _value); ControlFlowGraphs& m_controlFlow; SSACFG& m_graph; @@ -126,7 +130,7 @@ class SSACFGBuilder struct BlockInfo { bool sealed = false; - std::vector>> incompletePhis; + std::vector>> incompletePhis; }; std::vector m_blockInfo; @@ -140,7 +144,7 @@ class SSACFGBuilder std::unordered_map< Scope::Variable const*, - std::vector + std::vector > m_currentDef; struct ForLoopInfo { @@ -149,7 +153,7 @@ class SSACFGBuilder }; std::stack m_forLoopInfo; - SSACFG::ValueId& currentDef(Scope::Variable const& _variable, SSACFG::BlockId _block) + InstId& currentDef(Scope::Variable const& _variable, SSACFG::BlockId _block) { auto& varDefs = m_currentDef[&_variable]; if (varDefs.size() <= _block.value) @@ -159,7 +163,7 @@ class SSACFGBuilder void conditionalJump( langutil::DebugData::ConstPtr _debugData, - SSACFG::ValueId _condition, + InstId _condition, SSACFG::BlockId _nonZero, SSACFG::BlockId _zero ); diff --git a/libyul/backends/evm/ssa/SSACFGDebugInfo.h b/libyul/backends/evm/ssa/SSACFGDebugInfo.h index 9d8ed0686..eab9b07de 100644 --- a/libyul/backends/evm/ssa/SSACFGDebugInfo.h +++ b/libyul/backends/evm/ssa/SSACFGDebugInfo.h @@ -59,13 +59,13 @@ struct SSACFGDebugInfo langutil::DebugData::ConstPtr instDebugData(InstId _id) const { return lookup(m_instDebugData, _id.value); } - void setValueDebugData(ValueId _id, langutil::DebugData::ConstPtr _data) + void setValueDebugData(InstId _id, langutil::DebugData::ConstPtr _data) { yulAssert(_id.hasValue()); m_valueDebugData[_id] = std::move(_data); } - langutil::DebugData::ConstPtr valueDebugData(ValueId _id) const + langutil::DebugData::ConstPtr valueDebugData(InstId _id) const { auto const it = m_valueDebugData.find(_id); if (it == m_valueDebugData.end()) @@ -91,7 +91,7 @@ struct SSACFGDebugInfo std::vector m_blockDebugData; std::vector m_exitDebugData; std::vector m_instDebugData; - std::map m_valueDebugData; + std::map m_valueDebugData; }; } diff --git a/libyul/backends/evm/ssa/SSACFGTypes.cpp b/libyul/backends/evm/ssa/SSACFGTypes.cpp index 1a4ee04e8..965c8e042 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.cpp +++ b/libyul/backends/evm/ssa/SSACFGTypes.cpp @@ -22,26 +22,25 @@ using namespace solidity::yul::ssa; -std::string ValueId::str(SSACFG const& _cfg) const +std::string InstId::str(SSACFG const& _cfg) const { if (!hasValue()) return "INVALID"; switch (_cfg.kindOf(*this)) { case InstOpcode::Const: - return toCompactHexWithPrefix(_cfg.literalPayload(instId())); + return toCompactHexWithPrefix(_cfg.literalPayload(*this)); case InstOpcode::BuiltinCall: case InstOpcode::Call: case InstOpcode::FunctionArg: - if (m_outputPos == 0) - return fmt::format("v{}", m_instId.value); - return fmt::format("v{}.{}", m_instId.value, m_outputPos); + case InstOpcode::Projection: + return fmt::format("v{}", value); case InstOpcode::Phi: - return fmt::format("phi{}", m_instId.value); + return fmt::format("phi{}", value); case InstOpcode::Unreachable: return "[unreachable]"; case InstOpcode::Upsilon: - yulAssert(false, "Upsilon Insts have no output ValueId"); + yulAssert(false, "Upsilon Insts have no output value"); } util::unreachable(); } diff --git a/libyul/backends/evm/ssa/SSACFGTypes.h b/libyul/backends/evm/ssa/SSACFGTypes.h index 2a7861ff5..dfb590d6f 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.h +++ b/libyul/backends/evm/ssa/SSACFGTypes.h @@ -48,6 +48,9 @@ struct InstId ValueType value = std::numeric_limits::max(); constexpr bool hasValue() const noexcept { return value != std::numeric_limits::max(); } auto operator<=>(InstId const&) const = default; + + /// Returns a human-readable string representation + std::string str(SSACFG const& _cfg) const; }; enum class InstOpcode : std::uint8_t @@ -59,35 +62,7 @@ enum class InstOpcode : std::uint8_t Call, // user-defined function call Unreachable, // dead code FunctionArg, // function param without inputs and a single output valueid -}; - -/// Identifies a specific produced value of an Inst. -class ValueId -{ -public: - // this value refers to the n-th return value of an operation - using OutputSize = std::uint8_t; - /// Maximum number of outputs an Inst may produce. Bounded by the encoding of `OutputSize`. - static constexpr std::size_t maxOutputs = std::numeric_limits::max(); - - constexpr ValueId() = default; - constexpr ValueId(InstId const _instId, OutputSize const _outputPos = 0): - m_instId(_instId), - m_outputPos(_outputPos) - {} - - bool constexpr hasValue() const noexcept { return m_instId.hasValue(); } - OutputSize constexpr outputPos() const noexcept { return m_outputPos; } - InstId constexpr instId() const noexcept { return m_instId; } - - /// Returns a human-readable string representation - std::string str(SSACFG const& _cfg) const; - - auto operator<=>(ValueId const&) const = default; - -private: - InstId m_instId{}; - OutputSize m_outputPos{0}; + Projection, // projection: single InstId input (multi-output producer) plus immediate index }; } @@ -116,22 +91,6 @@ struct fmt::formatter { if (!_instId.hasValue()) return fmt::format_to(_ctx.out(), "empty"); - return fmt::format_to(_ctx.out(), "i{}", _instId.value); - } -}; - -template<> -struct fmt::formatter -{ - static auto constexpr parse(format_parse_context& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } - - template - auto format(solidity::yul::ssa::ValueId const& _valueId, FormatContext& _ctx) const -> decltype(_ctx.out()) - { - if (!_valueId.hasValue()) - return fmt::format_to(_ctx.out(), "empty"); - if (_valueId.outputPos() == 0) - return fmt::format_to(_ctx.out(), "v{}", _valueId.instId().value); - return fmt::format_to(_ctx.out(), "v{}.{}", _valueId.instId().value, _valueId.outputPos()); + return fmt::format_to(_ctx.out(), "v{}", _instId.value); } }; diff --git a/libyul/backends/evm/ssa/Stack.cpp b/libyul/backends/evm/ssa/Stack.cpp index 14ed28222..cbdc62b45 100644 --- a/libyul/backends/evm/ssa/Stack.cpp +++ b/libyul/backends/evm/ssa/Stack.cpp @@ -30,12 +30,12 @@ std::string slotToString(StackSlot const& _slot) { switch (_slot.kind()) { - case StackSlot::Kind::ValueID: - if (_slot.isLiteralValueID()) - return fmt::format("lit{}", _slot.valueID().instId().value); - if (_slot.isPhiValueID()) - return fmt::format("phi{}", _slot.valueID().instId().value); - return fmt::format("{}", _slot.valueID()); + case StackSlot::Kind::Value: + if (_slot.isLiteralValue()) + return fmt::format("lit{}", _slot.value().value); + if (_slot.isPhiValue()) + return fmt::format("phi{}", _slot.value().value); + return fmt::format("{}", _slot.value()); case StackSlot::Kind::Junk: return "JUNK"; case StackSlot::Kind::FunctionCallReturnLabel: diff --git a/libyul/backends/evm/ssa/Stack.h b/libyul/backends/evm/ssa/Stack.h index 1e5b6caf9..ce1e8c3d9 100644 --- a/libyul/backends/evm/ssa/Stack.h +++ b/libyul/backends/evm/ssa/Stack.h @@ -77,7 +77,7 @@ class StackSlot public: enum struct Kind: std::uint8_t { - ValueID, // u32 + Value, // u32 InstId Junk, // empty FunctionCallReturnLabel, // index into corresponding stack layout's call sites FunctionReturnLabel // identifying the function graph via ControlFlowGraphs @@ -89,9 +89,9 @@ class StackSlot constexpr StackSlot& operator=(StackSlot const&) = default; constexpr StackSlot& operator=(StackSlot&&) = default; - constexpr bool isValueID() const noexcept { return kind() == Kind::ValueID; } - constexpr bool isLiteralValueID() const noexcept { return m_valueIdOpcode == InstOpcode::Const; } - constexpr bool isPhiValueID() const noexcept { return m_valueIdOpcode == InstOpcode::Phi; } + constexpr bool isValue() const noexcept { return kind() == Kind::Value; } + constexpr bool isLiteralValue() const noexcept { return m_valueOpcode == InstOpcode::Const; } + constexpr bool isPhiValue() const noexcept { return m_valueOpcode == InstOpcode::Phi; } constexpr bool isFunctionReturnLabel() const noexcept { return kind() == Kind::FunctionReturnLabel; } constexpr bool isFunctionCallReturnLabel() const noexcept { return kind() == Kind::FunctionCallReturnLabel; } constexpr bool isJunk() const noexcept { return kind() == Kind::Junk; } @@ -99,40 +99,37 @@ class StackSlot ControlFlowGraphs::FunctionGraphID functionReturnLabel() const { yulAssert(isFunctionReturnLabel()); return m_payload; } CallSites::CallSiteID functionCallReturnLabel() const { yulAssert(isFunctionCallReturnLabel()); return m_payload; } - SSACFG::ValueId valueID() const + InstId value() const { - yulAssert(isValueID()); - return {InstId{m_payload}, m_valueIdOutputPos}; + yulAssert(isValue()); + return InstId{m_payload}; } static constexpr StackSlot makeJunk() { return {0, Kind::Junk}; } - static StackSlot makeValueID(SSACFG const& _cfg, SSACFG::ValueId _valueID) + static StackSlot makeValue(SSACFG const& _cfg, InstId _value) { - return {_valueID.instId().value, Kind::ValueID, _valueID.outputPos(), _cfg.kindOf(_valueID)}; + return {_value.value, Kind::Value, _cfg.kindOf(_value)}; } - static StackSlot makeValueID(InstructionStore const& _store, SSACFG::ValueId _valueID) + static StackSlot makeValue(InstructionStore const& _store, InstId _value) { - return {_valueID.instId().value, Kind::ValueID, _valueID.outputPos(), _store.kindOf(_valueID)}; + return {_value.value, Kind::Value, _store.kindOf(_value)}; } static constexpr StackSlot makeFunctionReturnLabel(ControlFlowGraphs::FunctionGraphID const _graphID) { return {_graphID, Kind::FunctionReturnLabel}; } static constexpr StackSlot makeFunctionCallReturnLabel(CallSites::CallSiteID const _callSiteID) { return {_callSiteID, Kind::FunctionCallReturnLabel}; } auto operator<=>(StackSlot const&) const = default; private: - constexpr StackSlot(std::uint32_t const _payload, Kind const _kind, ValueId::OutputSize const _valueIdOutputPos = 0, InstOpcode const _valueIdOpcode = InstOpcode::Unreachable): + constexpr StackSlot(std::uint32_t const _payload, Kind const _kind, InstOpcode const _valueOpcode = InstOpcode::Unreachable): m_payload(_payload), m_kind(_kind), - m_valueIdOutputPos(_valueIdOutputPos), - m_valueIdOpcode(_valueIdOpcode) + m_valueOpcode(_valueOpcode) {} /// interpretation depends on kind std::uint32_t m_payload; Kind m_kind; - /// for Kind::ValueID: output position of the referenced value within its Inst - ValueId::OutputSize m_valueIdOutputPos; - /// for Kind::ValueID: cached Opcode of the defining Inst - InstOpcode m_valueIdOpcode; + /// for Kind::Value: cached Opcode of the defining Inst + InstOpcode m_valueOpcode; }; static_assert(sizeof(StackSlot) == 8, "Want cache efficiency, benchmark this if you go beyond 8 bytes"); static_assert(std::is_trivially_copyable_v, "Should be able to use memcpy semantics"); @@ -287,7 +284,7 @@ class Stack static bool constexpr canBeFreelyGenerated(Slot const& _slot) { - return _slot.isLiteralValueID() || _slot.isJunk() || _slot.isFunctionCallReturnLabel(); + return _slot.isLiteralValue() || _slot.isJunk() || _slot.isFunctionCallReturnLabel(); } Slot const& operator[](Offset const& _index) const noexcept { return (*m_data)[_index.value]; } diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 836ed25c5..0c6618121 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -44,8 +44,8 @@ void handlePhiFunctions(StackData& _stackData, PhiInverse const& _phiInverse, Li for (auto const& [phi, preImage]: _phiInverse.data()) { auto reversedStackData = _stackData | ranges::views::reverse; - auto const phiSlot = StackSlot::makeValueID(_cfg, phi); - auto const preImageSlot = StackSlot::makeValueID(_cfg, preImage); + auto const phiSlot = StackSlot::makeValue(_cfg, phi); + auto const preImageSlot = StackSlot::makeValue(_cfg, preImage); auto it = ranges::find(reversedStackData, preImageSlot); if (_liveness.contains(preImage)) { @@ -75,7 +75,7 @@ void declareJunk(StackType& _stack, LivenessAnalysis::LivenessData const& _live) for (StackOffset offset{0}; offset < _stack.size(); ++offset.value) { auto const& slot = _stack[offset]; - if (slot.isValueID() && !_live.contains(slot.valueID())) + if (slot.isValue() && !_live.contains(slot.value())) _stack.declareJunk(offset); } } @@ -152,8 +152,8 @@ void StackLayoutGenerator::defineStackIn(SSACFG::BlockId const& _blockId) blockLayout.stackIn.reserve(m_cfg.arguments.size() + (m_hasFunctionReturnLabel ? 1u : 0u)); if (m_hasFunctionReturnLabel) blockLayout.stackIn.push_back(Slot::makeFunctionReturnLabel(m_graphID)); - for (auto const& valueID: m_cfg.arguments | ranges::views::reverse) - blockLayout.stackIn.push_back(Slot::makeValueID(m_cfg, valueID)); + for (auto const& arg: m_cfg.arguments | ranges::views::reverse) + blockLayout.stackIn.push_back(Slot::makeValue(m_cfg, arg)); } m_resultLayout[_blockId] = blockLayout; return; @@ -231,40 +231,40 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) auto const& operationsLiveOut = m_liveness.operationsLiveOut(_blockId); blockLayout.operationIn.reserve(operationsLiveOut.size()); std::size_t operationIndex = 0; - m_cfg.forEachOperation(block, [&](InstId const instId, SSACFG::Inst const& inst) { + m_cfg.forEachOperation(block, [&](InstId const _instId, SSACFG::Inst const& _inst){ auto opLiveOutWithoutOutputs = operationsLiveOut[operationIndex]; - opLiveOutWithoutOutputs.eraseAll(SSACFG::outputsOf(instId, inst.numOutputs)); + m_cfg.forEachOutput(_instId, [&](InstId const id) { opLiveOutWithoutOutputs.erase(id); }); std::vector requiredStackTop; - if (inst.opcode == InstOpcode::Call) + if (_inst.opcode == InstOpcode::Call) { - auto const& callPayload = m_cfg.callPayload(instId); + auto const& callPayload = m_cfg.callPayload(_instId); if (callPayload.canContinue) { - auto const callSiteID = m_callSites.callSiteID(instId); + auto const callSiteID = m_callSites.callSiteID(_instId); yulAssert(callSiteID.has_value()); requiredStackTop.emplace_back(Slot::makeFunctionCallReturnLabel(*callSiteID)); } } - requiredStackTop += inst.inputs | ranges::views::transform([this](ValueId const& _id) { return StackSlot::makeValueID(m_cfg, _id); }); + requiredStackTop += _inst.inputs | ranges::views::transform([this](InstId const& _id) { return StackSlot::makeValue(m_cfg, _id); }); for (StackType::Depth depth{0}; depth < stack.size(); ++depth.value) if ( - stack.slot(depth).isValueID() && - !opLiveOutWithoutOutputs.contains(stack.slot(depth).valueID()) && + stack.slot(depth).isValue() && + !opLiveOutWithoutOutputs.contains(stack.slot(depth).value()) && ranges::find(requiredStackTop, stack.slot(depth)) == ranges::end(requiredStackTop) ) stack.declareJunk(depth); StackSlotLiveness const opLiveOutSlots = toStackSlotLiveness(m_cfg, opLiveOutWithoutOutputs); - std::size_t const targetSize = findOptimalTargetSize( - stack.data(), - requiredStackTop, - opLiveOutSlots, - junkCanBeAdded, - m_hasFunctionReturnLabel - ); { + std::size_t const targetSize = findOptimalTargetSize( + stack.data(), + requiredStackTop, + opLiveOutSlots, + junkCanBeAdded, + m_hasFunctionReturnLabel + ); auto const shuffleResult = StackShuffler::shuffle( stack, requiredStackTop, @@ -277,8 +277,9 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) blockLayout.operationIn.push_back(currentStackData); for (std::size_t i = 0; i < requiredStackTop.size(); ++i) stack.pop(); - for (auto const& val: SSACFG::outputsOf(instId, inst.numOutputs)) - stack.push(Slot::makeValueID(m_cfg, val)); + m_cfg.forEachOutput(_instId, [&](InstId const id) { + stack.push(Slot::makeValue(m_cfg, id)); + }); ++operationIndex; }); yulAssert(operationIndex == operationsLiveOut.size()); @@ -292,10 +293,10 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) bool const conditionSlotAlreadyFinal = !blockLiveOut.contains(_cJump.condition) && // if our live out does not contain the condition (ie we dont have to dup it) !stack.empty() && // our stack is not empty - stack.top().isValueID() && stack.top().valueID() == _cJump.condition; // and the condition is already on top + stack.top().isValue() && stack.top().value() == _cJump.condition; // and the condition is already on top if (!conditionSlotAlreadyFinal) { - auto const condition = Slot::makeValueID(m_cfg, _cJump.condition); + auto const condition = Slot::makeValue(m_cfg, _cJump.condition); StackSlotLiveness const blockLiveOutSlots = toStackSlotLiveness(m_cfg, blockLiveOut); auto const targetSize = findOptimalTargetSize( stack.data(), @@ -310,7 +311,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); } - yulAssert(!stack.empty() && stack.top().isValueID() && stack.top().valueID() == _cJump.condition); + yulAssert(!stack.empty() && stack.top().isValue() && stack.top().value() == _cJump.condition); yulAssert(ranges::none_of(m_cfg.block(_cJump.nonZero).instructions, [this](InstId const _id) { return m_cfg.isPhi(_id); })); @@ -329,7 +330,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) [&](SSACFG::BasicBlock::FunctionReturn const& _functionReturn) { yulAssert(m_hasFunctionReturnLabel, "When there is a proper function return, we need to have a label for it"); // in case there are return values, let's bring the function return label to the top - StackData returnStack = _functionReturn.returnValues | ranges::views::transform([this](ValueId const _id) { return StackSlot::makeValueID(m_cfg, _id); }) | ranges::to; + StackData returnStack = _functionReturn.returnValues | ranges::views::transform([this](InstId const _id) { return StackSlot::makeValue(m_cfg, _id); }) | ranges::to; returnStack.push_back(StackSlot::makeFunctionReturnLabel(m_graphID)); auto const shuffleResult = StackShuffler::shuffle(stack, returnStack); yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); diff --git a/libyul/backends/evm/ssa/StackShuffler.cpp b/libyul/backends/evm/ssa/StackShuffler.cpp index 18daa4892..1d40cbb72 100644 --- a/libyul/backends/evm/ssa/StackShuffler.cpp +++ b/libyul/backends/evm/ssa/StackShuffler.cpp @@ -133,7 +133,7 @@ bool State::requiredInArgs(StackSlot const& _slot) const bool State::requiredInTail(StackSlot const& _slot) const { - if (!_slot.isValueID() || !m_target.liveOut.contains(_slot)) + if (!_slot.isValue() || !m_target.liveOut.contains(_slot)) return false; // Spilled values can be rematerialized, so they need not occupy a tail slot. return !slotIsSpilled(_slot); diff --git a/libyul/backends/evm/ssa/StackShuffler.h b/libyul/backends/evm/ssa/StackShuffler.h index 6c8bb9c1a..91f828859 100644 --- a/libyul/backends/evm/ssa/StackShuffler.h +++ b/libyul/backends/evm/ssa/StackShuffler.h @@ -40,7 +40,7 @@ namespace detail inline bool slotIsSpilled(StackSlot const& _slot, SpilledVariables const* const _spilledVariables) { - return _spilledVariables && _slot.isValueID() && _spilledVariables->isSpilled(_slot.valueID()); + return _spilledVariables && _slot.isValue() && _spilledVariables->isSpilled(_slot.value()); } inline bool slotCanBeLoadedOrPushed(StackSlot const& _slot, SpilledVariables const* const _spilledVariables) @@ -314,8 +314,8 @@ class StackShuffler { Slot const& candidate = _stack[offset]; if ( - candidate.isValueID() && - !candidate.isLiteralValueID() && + candidate.isValue() && + !candidate.isLiteralValue() && !_state.slotIsSpilled(candidate) ) return {StackShufflerResult::Status::StackTooDeep, candidate}; @@ -346,7 +346,7 @@ class StackShuffler int currentCount = static_cast(_state.count(slot)); int liveOutCount = 0; - if (slot.isValueID() && _state.target().liveOut.contains(slot)) + if (slot.isValue() && _state.target().liveOut.contains(slot)) liveOutCount = static_cast(_state.target().liveOut.count(slot)); int deficit = liveOutCount - currentCount; @@ -735,7 +735,7 @@ class StackShuffler if ( _stack.isValidSwapTarget(tailOffset) && _state.slotCanBeLoadedOrPushed(_stack[tailOffset]) && - !_stack[tailOffset].isLiteralValueID() + !_stack[tailOffset].isLiteralValue() ) { // bring up offset slot if necessary @@ -749,7 +749,7 @@ class StackShuffler for (StackOffset tailOffset: _state.stackTailRange()) if ( _stack.isValidSwapTarget(tailOffset) && - _stack[tailOffset].isLiteralValueID() + _stack[tailOffset].isLiteralValue() ) { // bring up offset slot if necessary @@ -857,7 +857,7 @@ class StackShuffler bool const hasSurplus = _state.count(slot) > _state.targetMinCount(slot); bool const hasReachableDuplicate = _state.countReachable(slot) > 1; bool const canBeFreelyGenerated = _stack.canBeFreelyGenerated(slot); - bool const isLit = slot.isLiteralValueID(); + bool const isLit = slot.isLiteralValue(); if (isJunk && notInPosition) return 5; diff --git a/libyul/backends/evm/ssa/StackSlotLiveness.h b/libyul/backends/evm/ssa/StackSlotLiveness.h index 3d233cfef..880b3c459 100644 --- a/libyul/backends/evm/ssa/StackSlotLiveness.h +++ b/libyul/backends/evm/ssa/StackSlotLiveness.h @@ -34,7 +34,7 @@ inline StackSlotLiveness toStackSlotLiveness(SSACFG const& _cfg, LivenessAnalysi StackSlotLiveness::Entries entries; entries.reserve(_liveness.size()); for (auto const& [valueId, count]: _liveness) - entries.emplace_back(StackSlot::makeValueID(_cfg, valueId), count); + entries.emplace_back(StackSlot::makeValue(_cfg, valueId), count); return StackSlotLiveness{std::move(entries)}; } diff --git a/libyul/backends/evm/ssa/StackToMemorySpilling.h b/libyul/backends/evm/ssa/StackToMemorySpilling.h index f4d869a9e..443c9e7c5 100644 --- a/libyul/backends/evm/ssa/StackToMemorySpilling.h +++ b/libyul/backends/evm/ssa/StackToMemorySpilling.h @@ -31,14 +31,14 @@ class SpilledVariables { public: - void spill(SSACFG::ValueId const _valueId) + void spill(InstId const _valueId) { bool const emplaced = m_spillSet.try_emplace(_valueId, m_currentSpillSlot).second; yulAssert(emplaced, fmt::format("can't spill a value ({}) twice", _valueId)); ++m_currentSpillSlot; } - bool isSpilled(SSACFG::ValueId const _valueId) const + bool isSpilled(InstId const _valueId) const { return m_spillSet.contains(_valueId); } @@ -54,6 +54,6 @@ class SpilledVariables } private: std::uint32_t m_currentSpillSlot{0}; - std::map m_spillSet; // map valueId -> ssa-cfg-local slot + std::map m_spillSet; // map valueId -> ssa-cfg-local slot }; } diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index 79568931d..1844bada7 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -44,9 +44,9 @@ void GasAccumulatingCallbacks::dup(StackDepth _depth) void GasAccumulatingCallbacks::push(StackSlot const& _slot) { - if (_slot.isLiteralValueID()) + if (_slot.isLiteralValue()) { - auto const size = numberEncodingSize(cfg.literalPayload(_slot.valueID().instId())); + auto const size = numberEncodingSize(cfg.literalPayload(_slot.value())); opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(size), cfg.evmDialect.evmVersion()); } else if (_slot.isJunk()) @@ -72,10 +72,10 @@ StackData solidity::yul::ssa::stackPreImage(SSACFG const& _cfg, StackData _stack { if (!_phiInverse.noOp()) for (auto& slot: _stack) - if (slot.isValueID()) + if (slot.isValue()) { - auto const preImage = _phiInverse(slot.valueID()); - slot = StackSlot::makeValueID(_cfg, preImage); + auto const preImage = _phiInverse(slot.value()); + slot = StackSlot::makeValue(_cfg, preImage); } return _stack; } @@ -124,9 +124,9 @@ std::size_t solidity::yul::ssa::findOptimalTargetSize break; case StackShufflerResult::Status::StackTooDeep: { - yulAssert(result.culprit.isValueID() && !result.culprit.isLiteralValueID()); - yulAssert(!spillSet.isSpilled(result.culprit.valueID())); - spillSet.spill(result.culprit.valueID()); + yulAssert(result.culprit.isValue() && !result.culprit.isLiteralValue()); + yulAssert(!spillSet.isSpilled(result.culprit.value())); + spillSet.spill(result.culprit.value()); break; } case StackShufflerResult::Status::MaxIterationsReached: diff --git a/libyul/backends/evm/ssa/io/DotExporterBase.cpp b/libyul/backends/evm/ssa/io/DotExporterBase.cpp index 0c5eff764..83a562a01 100644 --- a/libyul/backends/evm/ssa/io/DotExporterBase.cpp +++ b/libyul/backends/evm/ssa/io/DotExporterBase.cpp @@ -117,7 +117,7 @@ void DotExporterBase::writeBlock(std::ostream& _out, SSACFG::BlockId const _id) }, [&](SSACFG::BasicBlock::FunctionReturn const& fr) { - auto const valueToString = [&](SSACFG::ValueId const& valueId) { return valueId.str(m_cfg); }; + auto const valueToString = [&](InstId const& valueId) { return valueId.str(m_cfg); }; _out << fmt::format("{}Exit [label=\"FunctionReturn[{}]\"];\n", formatBlockHandle(_id), fmt::join(fr.returnValues | ranges::views::transform(valueToString), ", ") @@ -177,7 +177,7 @@ std::string DotExporterBase::exportFunction(SSACFG const& _function, bool _wrapI if (_wrapInDigraph) out << fmt::format("digraph SSACFG {{\nnodesep=0.7;\ngraph[fontname=\"DejaVu Sans\", rankdir={}]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n", m_rankDir); - static auto constexpr argsTransform = [](auto const& arg) { return fmt::format("v{}", arg.instId().value); }; + static auto constexpr argsTransform = [](InstId const& arg) { return fmt::format("v{}", arg.value); }; auto const entryHandle = fmt::format("FunctionEntry_{}_{}", escapeId(_function.name), _function.entry.value); if (_function.numReturns > 0) out << fmt::format("{} [label=\"function {}:\n [{} returns] := {}({})\"];\n", diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index 8c1cfd4f7..4570dca2b 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -36,10 +36,10 @@ using namespace solidity::yul::ssa::io::json; namespace { -Json toJson(SSACFG const& _cfg, ranges::input_range auto&& _values) requires std::convertible_to, SSACFG::ValueId> +Json toJson(SSACFG const& _cfg, ranges::input_range auto&& _values) requires std::convertible_to, InstId> { Json ret = Json::array(); - for (SSACFG::ValueId const value: _values) + for (InstId const value: _values) ret.push_back(value.str(_cfg)); return ret; } @@ -70,7 +70,9 @@ Json toJson(Json& _ret, SSACFG const& _cfg, InstId const _instId, ControlFlowGra } opJson["in"] = toJson(_cfg, inst.inputs); - opJson["out"] = toJson(_cfg, SSACFG::outputsOf(_instId, inst.numOutputs)); + std::vector outputs; + _cfg.forEachOutput(_instId, [&](InstId const id) { outputs.push_back(id); }); + opJson["out"] = toJson(_cfg, outputs); return opJson; } @@ -103,16 +105,15 @@ Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const | ranges::views::transform([](auto const& entry) { return "Block" + std::to_string(entry.value); }) | ranges::to(); _cfg.forEachPhi(block, [&](InstId const instId, SSACFG::Inst const&) { - SSACFG::ValueId const phi{instId, 0}; // Reconstruct phi arguments from upsilon Insts in predecessor blocks. - std::vector phiArgs; + std::vector phiArgs; for (auto const& entryId: block.entries) for (InstId const predInstId: _cfg.block(entryId).instructions) { auto const& predInst = _cfg.inst(predInstId); if (!predInst.isUpsilon()) continue; - if (_cfg.upsilonPhi(predInstId) == phi) + if (_cfg.upsilonPhi(predInstId) == instId) { phiArgs.push_back(predInst.inputs.at(0)); break; @@ -121,7 +122,7 @@ Json toJson(SSACFG const& _cfg, SSACFG::BlockId _blockId, LivenessAnalysis const Json phiJson = Json::object(); phiJson["op"] = "PhiFunction"; phiJson["in"] = toJson(_cfg, phiArgs); - phiJson["out"] = toJson(_cfg, std::vector{phi}); + phiJson["out"] = toJson(_cfg, std::vector{instId}); blockJson["instructions"].push_back(phiJson); }); _cfg.forEachOperation(block, [&](InstId const instId, SSACFG::Inst const&) { @@ -176,7 +177,7 @@ Json exportFunction(SSACFG const& _cfg, LivenessAnalysis const* _liveness, Contr Json functionJson = Json::object(); functionJson["type"] = "Function"; functionJson["entry"] = "Block" + std::to_string(_cfg.entry.value); - static auto constexpr argsTransform = [](auto const& _arg) { return fmt::format("v{}", _arg.instId().value); }; + static auto constexpr argsTransform = [](InstId const& _arg) { return fmt::format("v{}", _arg.value); }; functionJson["arguments"] = _cfg.arguments | ranges::views::transform(argsTransform) | ranges::to; functionJson["numReturns"] = _cfg.numReturns; functionJson["blocks"] = exportBlock(_cfg, _cfg.entry, _liveness, _controlFlow); diff --git a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp index 9499c82ee..d445168ab 100644 --- a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp +++ b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp @@ -41,13 +41,13 @@ struct TrivialPhiEliminator SSACFG& cfg; // phi_id -> values of upsilons targeting this phi - std::vector> upsilonValuesForPhi; + std::vector> upsilonValuesForPhi; // phi_id -> blocks containing upsilons targeting this phi std::vector> phiTargetBlocks; // phi_id -> phis whose upsilon values reference this phi - std::vector> reversePhiUpsilonValues; + std::vector> reversePhiUpsilonValues; // phi_id -> canonical replacement (default = no substitution) - std::vector substitution; + std::vector substitution; explicit TrivialPhiEliminator(SSACFG& _cfg): cfg(_cfg) {} @@ -87,9 +87,9 @@ struct TrivialPhiEliminator for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) { cfg.forEachUpsilon(cfg.block(blockId), [&](InstId const instId, SSACFG::Inst const& inst) { - SSACFG::ValueId const phi = cfg.upsilonPhi(instId); - SSACFG::ValueId const value = inst.inputs.at(0); - auto const phiIdx = phi.instId().value; + InstId const phi = cfg.upsilonPhi(instId); + InstId const value = inst.inputs.at(0); + auto const phiIdx = phi.value; if (phiIdx >= upsilonValuesForPhi.size()) { upsilonValuesForPhi.resize(phiIdx + 1); @@ -101,7 +101,7 @@ struct TrivialPhiEliminator phiTargetBlocks[phiIdx].push_back(blockId); if (cfg.isPhi(value)) { - auto const valIdx = value.instId().value; + auto const valIdx = value.value; if (valIdx >= reversePhiUpsilonValues.size()) reversePhiUpsilonValues.resize(valIdx + 1); reversePhiUpsilonValues[valIdx].push_back(phi); @@ -122,7 +122,7 @@ struct TrivialPhiEliminator for (auto& val: upsilonValues) if (cfg.isPhi(val)) { - auto const idx = val.instId().value; + auto const idx = val.value; bool const hasUpsilons = idx < upsilonValuesForPhi.size() && !upsilonValuesForPhi[idx].empty(); if (!hasUpsilons) val = unreachable; @@ -133,19 +133,19 @@ struct TrivialPhiEliminator { for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) { - // Snapshot the phi ValueIds because tryRemove mutates block.instructions. - std::vector phis; + // Snapshot the phi InstIds because tryRemove mutates block.instructions. + std::vector phis; cfg.forEachPhi(cfg.block(blockId), [&](InstId const instId, SSACFG::Inst const&) { - phis.push_back(ValueId{instId}); + phis.push_back(instId); }); for (auto const phi: phis) tryRemove(phi); } } - void tryRemove(SSACFG::ValueId _phi) + void tryRemove(InstId _phi) { - auto const phiIdx = _phi.instId().value; + auto const phiIdx = _phi.value; // early exit if this phi was already processed if (phiIdx < substitution.size() && substitution[phiIdx].hasValue()) @@ -153,7 +153,7 @@ struct TrivialPhiEliminator // check triviality and canonicalize arguments to account for already-substituted phis; // skip self-references and unreachable values - SSACFG::ValueId same; + InstId same; if (phiIdx < upsilonValuesForPhi.size()) for (auto const arg: upsilonValuesForPhi[phiIdx]) { @@ -171,9 +171,9 @@ struct TrivialPhiEliminator // remove the phi from its defining block { - auto& block = cfg.block(cfg.inst(_phi.instId()).block); + auto& block = cfg.block(cfg.inst(_phi).block); yulAssert(cfg.isPhi(_phi)); - std::erase(block.instructions, _phi.instId()); + std::erase(block.instructions, _phi); } // record the substitution @@ -182,16 +182,16 @@ struct TrivialPhiEliminator substitution[phiIdx] = same; // update upsilon.value fields and `upsilonValuesForPhi` for all phis whose upsilons reference `_phi` as a value - std::vector cascades; + std::vector cascades; if (phiIdx < reversePhiUpsilonValues.size()) { for (auto const targetPhi: reversePhiUpsilonValues[phiIdx]) { // update upsilonValuesForPhi[targetPhi]: _phi with same - auto& vals = upsilonValuesForPhi[targetPhi.instId().value]; + auto& vals = upsilonValuesForPhi[targetPhi.value]; ranges::replace(vals, _phi, same); - if (targetPhi.instId().value < phiTargetBlocks.size()) - for (auto const blockId: phiTargetBlocks[targetPhi.instId().value]) + if (targetPhi.value < phiTargetBlocks.size()) + for (auto const blockId: phiTargetBlocks[targetPhi.value]) cfg.forEachUpsilon(cfg.block(blockId), [&](InstId const instId, SSACFG::Inst& inst) { if (cfg.upsilonPhi(instId) == targetPhi && inst.inputs.at(0) == _phi) inst.inputs[0] = same; @@ -199,9 +199,9 @@ struct TrivialPhiEliminator // maintain reverse index if (cfg.isPhi(same)) { - if (same.instId().value >= reversePhiUpsilonValues.size()) - reversePhiUpsilonValues.resize(same.instId().value + 1); - reversePhiUpsilonValues[same.instId().value].push_back(targetPhi); + if (same.value >= reversePhiUpsilonValues.size()) + reversePhiUpsilonValues.resize(same.value + 1); + reversePhiUpsilonValues[same.value].push_back(targetPhi); } cascades.push_back(targetPhi); } @@ -226,9 +226,9 @@ struct TrivialPhiEliminator tryRemove(cascadingPhi); } - SSACFG::ValueId canonicalize(SSACFG::ValueId const _v) + InstId canonicalize(InstId const _v) { - auto const idx = _v.instId().value; + auto const idx = _v.value; if (idx >= substitution.size()) return _v; auto& sub = substitution[idx]; @@ -241,7 +241,7 @@ struct TrivialPhiEliminator void applySubstitutions() { - if (!ranges::any_of(substitution, [](ValueId const& _sub) { return _sub.hasValue(); })) + if (!ranges::any_of(substitution, [](InstId const& _sub) { return _sub.hasValue(); })) return; for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index 98ae4a464..fcbc710f1 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -63,7 +63,7 @@ ], "op": "datasize", "out": [ - "v6" + "v7" ] }, { @@ -73,13 +73,13 @@ ], "op": "dataoffset", "out": [ - "v7" + "v8" ] }, { "in": [ - "v6", "v7", + "v8", "v0" ], "op": "codecopy", @@ -87,7 +87,7 @@ }, { "in": [ - "v6", + "v7", "v0" ], "op": "return", @@ -309,7 +309,7 @@ }, { "exit": { - "cond": "v19", + "cond": "v20", "targets": [ "Block9", "Block8" @@ -324,34 +324,34 @@ ], "op": "not", "out": [ - "v16" + "v17" ] }, { "in": [], "op": "calldatasize", "out": [ - "v17" + "v18" ] }, { "in": [ - "v16", - "v17" + "v17", + "v18" ], "op": "add", "out": [ - "v18" + "v19" ] }, { "in": [ "0x00", - "v18" + "v19" ], "op": "slt", "out": [ - "v19" + "v20" ] } ], @@ -510,7 +510,7 @@ ], "op": "datasize", "out": [ - "v6" + "v7" ] }, { @@ -520,13 +520,13 @@ ], "op": "dataoffset", "out": [ - "v7" + "v8" ] }, { "in": [ - "v6", "v7", + "v8", "v0" ], "op": "codecopy", @@ -534,7 +534,7 @@ }, { "in": [ - "v6", + "v7", "v0" ], "op": "return", @@ -756,7 +756,7 @@ }, { "exit": { - "cond": "v19", + "cond": "v20", "targets": [ "Block9", "Block8" @@ -771,34 +771,34 @@ ], "op": "not", "out": [ - "v16" + "v17" ] }, { "in": [], "op": "calldatasize", "out": [ - "v17" + "v18" ] }, { "in": [ - "v16", - "v17" + "v17", + "v18" ], "op": "add", "out": [ - "v18" + "v19" ] }, { "in": [ "0x00", - "v18" + "v19" ], "op": "slt", "out": [ - "v19" + "v20" ] } ], @@ -835,7 +835,7 @@ }, { "exit": { - "cond": "v34", + "cond": "v36", "targets": [ "Block12", "Block11" @@ -851,47 +851,47 @@ ], "op": "datasize", "out": [ - "v21" + "v23" ] }, { "in": [ - "v21", + "v23", "v0" ], "op": "add", "out": [ - "v30" + "v32" ] }, { "in": [ "v0", - "v30" + "v32" ], "op": "lt", "out": [ - "v31" + "v33" ] }, { "in": [ "0xffffffffffffffff", - "v30" + "v32" ], "op": "gt", "out": [ - "v33" + "v35" ] }, { "in": [ - "v31", - "v33" + "v33", + "v35" ], "op": "or", "out": [ - "v34" + "v36" ] } ], @@ -901,8 +901,8 @@ ], "out": [ "v0", - "v30", - "v21" + "v32", + "v23" ] }, "type": "BuiltinCall" @@ -930,7 +930,7 @@ }, { "exit": { - "cond": "v58", + "cond": "v61", "targets": [ "Block15", "Block14" @@ -946,13 +946,13 @@ ], "op": "dataoffset", "out": [ - "v46" + "v49" ] }, { "in": [ - "v21", - "v46", + "v23", + "v49", "v0" ], "op": "datacopy", @@ -961,42 +961,42 @@ { "in": [ "v0", - "v30" + "v32" ], "op": "sub", "out": [ - "v56" + "v59" ] }, { "in": [ - "v56", + "v59", "v0", "0x00" ], "op": "create", "out": [ - "v57" + "v60" ] }, { "in": [ - "v57" + "v60" ], "op": "iszero", "out": [ - "v58" + "v61" ] } ], "liveness": { "in": [ "v0", - "v30", - "v21" + "v32", + "v23" ], "out": [ - "v57" + "v60" ] }, "type": "BuiltinCall" @@ -1014,12 +1014,12 @@ ], "op": "shl", "out": [ - "v36" + "v38" ] }, { "in": [ - "v36", + "v38", "0x00" ], "op": "mstore", @@ -1050,7 +1050,7 @@ }, { "exit": { - "cond": "v81", + "cond": "v85", "targets": [ "Block18", "Block17" @@ -1065,7 +1065,7 @@ ], "op": "mload", "out": [ - "v64" + "v68" ] }, { @@ -1075,13 +1075,13 @@ ], "op": "shl", "out": [ - "v67" + "v71" ] }, { "in": [ - "v67", - "v64" + "v71", + "v68" ], "op": "mstore", "out": [] @@ -1093,67 +1093,67 @@ ], "op": "shl", "out": [ - "v72" + "v76" ] }, { "in": [ "0x01", - "v72" + "v76" ], "op": "sub", "out": [ - "v73" + "v77" ] }, { "in": [ - "v73", - "v57" + "v77", + "v60" ], "op": "and", "out": [ - "v78" + "v82" ] }, { "in": [], "op": "gas", "out": [ - "v79" + "v83" ] }, { "in": [ "0x20", - "v64", + "v68", "0x04", - "v64", - "v78", - "v79" + "v68", + "v82", + "v83" ], "op": "staticcall", "out": [ - "v80" + "v84" ] }, { "in": [ - "v80" + "v84" ], "op": "iszero", "out": [ - "v81" + "v85" ] } ], "liveness": { "in": [ - "v57" + "v60" ], "out": [ - "v64", - "v80" + "v68", + "v84" ] }, "type": "BuiltinCall" @@ -1170,21 +1170,21 @@ ], "op": "mload", "out": [ - "v59" + "v62" ] }, { "in": [], "op": "returndatasize", "out": [ - "v60" + "v63" ] }, { "in": [ - "v60", + "v63", "0x00", - "v59" + "v62" ], "op": "returndatacopy", "out": [] @@ -1193,13 +1193,13 @@ "in": [], "op": "returndatasize", "out": [ - "v62" + "v65" ] }, { "in": [ - "v62", - "v59" + "v65", + "v62" ], "op": "revert", "out": [] @@ -1213,7 +1213,7 @@ }, { "exit": { - "cond": "v80", + "cond": "v84", "targets": [ "Block21", "Block20" @@ -1224,11 +1224,11 @@ "instructions": [], "liveness": { "in": [ - "v64", - "v80" + "v68", + "v84" ], "out": [ - "v64" + "v68" ] } }, @@ -1244,21 +1244,21 @@ ], "op": "mload", "out": [ - "v82" + "v86" ] }, { "in": [], "op": "returndatasize", "out": [ - "v83" + "v87" ] }, { "in": [ - "v83", + "v87", "0x00", - "v82" + "v86" ], "op": "returndatacopy", "out": [] @@ -1267,13 +1267,13 @@ "in": [], "op": "returndatasize", "out": [ - "v85" + "v89" ] }, { "in": [ - "v85", - "v82" + "v89", + "v86" ], "op": "revert", "out": [] @@ -1298,11 +1298,11 @@ { "in": [ "0x00", - "v137" + "v144" ], "op": "PhiFunction", "out": [ - "phi139" + "phi146" ] }, { @@ -1311,13 +1311,13 @@ ], "op": "mload", "out": [ - "v138" + "v145" ] }, { "in": [ - "phi139", - "v138" + "phi146", + "v145" ], "op": "mstore", "out": [] @@ -1325,7 +1325,7 @@ { "in": [ "0x20", - "v138" + "v145" ], "op": "return", "out": [] @@ -1333,7 +1333,7 @@ ], "liveness": { "in": [ - "phi139" + "phi146" ], "out": [] }, @@ -1341,7 +1341,7 @@ }, { "exit": { - "cond": "v92", + "cond": "v97", "targets": [ "Block23", "Block22" @@ -1354,26 +1354,26 @@ "in": [], "op": "returndatasize", "out": [ - "v91" + "v96" ] }, { "in": [ - "v91", + "v96", "0x20" ], "op": "gt", "out": [ - "v92" + "v97" ] } ], "liveness": { "in": [ - "v64" + "v68" ], "out": [ - "v64" + "v68" ] }, "type": "BuiltinCall" @@ -1384,7 +1384,7 @@ "Block22" ], "exit": { - "cond": "v111", + "cond": "v116", "targets": [ "Block25", "Block24" @@ -1396,11 +1396,11 @@ { "in": [ "0x20", - "v93" + "v98" ], "op": "PhiFunction", "out": [ - "phi96" + "phi101" ] }, { @@ -1409,79 +1409,79 @@ ], "op": "not", "out": [ - "v95" + "v100" ] }, { "in": [ "0x1f", - "phi96" + "phi101" ], "op": "add", "out": [ - "v99" + "v104" ] }, { "in": [ - "v95", - "v99" + "v100", + "v104" ], "op": "and", "out": [ - "v100" + "v105" ] }, { "in": [ - "v100", - "v64" + "v105", + "v68" ], "op": "add", "out": [ - "v108" + "v113" ] }, { "in": [ - "v64", - "v108" + "v68", + "v113" ], "op": "lt", "out": [ - "v109" + "v114" ] }, { "in": [ "0xffffffffffffffff", - "v108" + "v113" ], "op": "gt", "out": [ - "v110" + "v115" ] }, { "in": [ - "v109", - "v110" + "v114", + "v115" ], "op": "or", "out": [ - "v111" + "v116" ] } ], "liveness": { "in": [ - "v64", - "phi96" + "v68", + "phi101" ], "out": [ - "v64", - "phi96", - "v108" + "v68", + "phi101", + "v113" ] }, "type": "BuiltinCall" @@ -1499,24 +1499,24 @@ "in": [], "op": "returndatasize", "out": [ - "v93" + "v98" ] } ], "liveness": { "in": [ - "v64" + "v68" ], "out": [ - "v93", - "v64" + "v98", + "v68" ] }, "type": "BuiltinCall" }, { "exit": { - "cond": "v131", + "cond": "v137", "targets": [ "Block28", "Block27" @@ -1527,7 +1527,7 @@ "instructions": [ { "in": [ - "v108", + "v113", "0x40" ], "op": "mstore", @@ -1535,43 +1535,43 @@ }, { "in": [ - "phi96", - "v64" + "phi101", + "v68" ], "op": "add", "out": [ - "v129" + "v135" ] }, { "in": [ - "v64", - "v129" + "v68", + "v135" ], "op": "sub", "out": [ - "v130" + "v136" ] }, { "in": [ "0x20", - "v130" + "v136" ], "op": "slt", "out": [ - "v131" + "v137" ] } ], "liveness": { "in": [ - "v64", - "phi96", - "v108" + "v68", + "phi101", + "v113" ], "out": [ - "v64" + "v68" ] }, "type": "BuiltinCall" @@ -1589,12 +1589,12 @@ ], "op": "shl", "out": [ - "v112" + "v117" ] }, { "in": [ - "v112", + "v117", "0x00" ], "op": "mstore", @@ -1634,20 +1634,20 @@ "instructions": [ { "in": [ - "v64" + "v68" ], "op": "mload", "out": [ - "v137" + "v144" ] } ], "liveness": { "in": [ - "v64" + "v68" ], "out": [ - "v137" + "v144" ] }, "type": "BuiltinCall" @@ -1736,7 +1736,7 @@ ], "op": "datasize", "out": [ - "v6" + "v7" ] }, { @@ -1746,13 +1746,13 @@ ], "op": "dataoffset", "out": [ - "v7" + "v8" ] }, { "in": [ - "v6", "v7", + "v8", "v0" ], "op": "codecopy", @@ -1760,7 +1760,7 @@ }, { "in": [ - "v6", + "v7", "v0" ], "op": "return", @@ -1982,7 +1982,7 @@ }, { "exit": { - "cond": "v19", + "cond": "v20", "targets": [ "Block9", "Block8" @@ -1997,34 +1997,34 @@ ], "op": "not", "out": [ - "v16" + "v17" ] }, { "in": [], "op": "calldatasize", "out": [ - "v17" + "v18" ] }, { "in": [ - "v16", - "v17" + "v17", + "v18" ], "op": "add", "out": [ - "v18" + "v19" ] }, { "in": [ "0x00", - "v18" + "v19" ], "op": "slt", "out": [ - "v19" + "v20" ] } ], diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output index 75110c57c..bc8d8327d 100644 --- a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -63,7 +63,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v6" + "v7" ] }, { @@ -73,13 +73,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v7" + "v8" ] }, { "in": [ - "v6", "v7", + "v8", "v0" ], "op": "codecopy", @@ -87,7 +87,7 @@ Yul Control Flow Graph: }, { "in": [ - "v6", + "v7", "v0" ], "op": "return", @@ -309,7 +309,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v19", + "cond": "v20", "targets": [ "Block9", "Block8" @@ -324,34 +324,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v16" + "v17" ] }, { "in": [], "op": "calldatasize", "out": [ - "v17" + "v18" ] }, { "in": [ - "v16", - "v17" + "v17", + "v18" ], "op": "add", "out": [ - "v18" + "v19" ] }, { "in": [ "0x00", - "v18" + "v19" ], "op": "slt", "out": [ - "v19" + "v20" ] } ], diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index 464ba9b3d..023da3678 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -62,7 +62,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v6" + "v7" ] }, { @@ -72,13 +72,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v7" + "v8" ] }, { "in": [ - "v6", "v7", + "v8", "v0" ], "op": "codecopy", @@ -86,7 +86,7 @@ Yul Control Flow Graph: }, { "in": [ - "v6", + "v7", "v0" ], "op": "return", @@ -308,7 +308,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v19", + "cond": "v20", "targets": [ "Block9", "Block8" @@ -323,34 +323,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v16" + "v17" ] }, { "in": [], "op": "calldatasize", "out": [ - "v17" + "v18" ] }, { "in": [ - "v16", - "v17" + "v17", + "v18" ], "op": "add", "out": [ - "v18" + "v19" ] }, { "in": [ "0x00", - "v18" + "v19" ], "op": "slt", "out": [ - "v19" + "v20" ] } ], @@ -510,7 +510,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v6" + "v7" ] }, { @@ -520,13 +520,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v7" + "v8" ] }, { "in": [ - "v6", "v7", + "v8", "v0" ], "op": "codecopy", @@ -534,7 +534,7 @@ Yul Control Flow Graph: }, { "in": [ - "v6", + "v7", "v0" ], "op": "return", @@ -756,7 +756,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v19", + "cond": "v20", "targets": [ "Block9", "Block8" @@ -771,34 +771,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v16" + "v17" ] }, { "in": [], "op": "calldatasize", "out": [ - "v17" + "v18" ] }, { "in": [ - "v16", - "v17" + "v17", + "v18" ], "op": "add", "out": [ - "v18" + "v19" ] }, { "in": [ "0x00", - "v18" + "v19" ], "op": "slt", "out": [ - "v19" + "v20" ] } ], @@ -835,7 +835,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v34", + "cond": "v36", "targets": [ "Block12", "Block11" @@ -851,47 +851,47 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v21" + "v23" ] }, { "in": [ - "v21", + "v23", "v0" ], "op": "add", "out": [ - "v30" + "v32" ] }, { "in": [ "v0", - "v30" + "v32" ], "op": "lt", "out": [ - "v31" + "v33" ] }, { "in": [ "0xffffffffffffffff", - "v30" + "v32" ], "op": "gt", "out": [ - "v33" + "v35" ] }, { "in": [ - "v31", - "v33" + "v33", + "v35" ], "op": "or", "out": [ - "v34" + "v36" ] } ], @@ -901,8 +901,8 @@ Yul Control Flow Graph: ], "out": [ "v0", - "v30", - "v21" + "v32", + "v23" ] }, "type": "BuiltinCall" @@ -930,7 +930,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v58", + "cond": "v61", "targets": [ "Block15", "Block14" @@ -946,13 +946,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v46" + "v49" ] }, { "in": [ - "v21", - "v46", + "v23", + "v49", "v0" ], "op": "datacopy", @@ -961,42 +961,42 @@ Yul Control Flow Graph: { "in": [ "v0", - "v30" + "v32" ], "op": "sub", "out": [ - "v56" + "v59" ] }, { "in": [ - "v56", + "v59", "v0", "0x00" ], "op": "create", "out": [ - "v57" + "v60" ] }, { "in": [ - "v57" + "v60" ], "op": "iszero", "out": [ - "v58" + "v61" ] } ], "liveness": { "in": [ "v0", - "v30", - "v21" + "v32", + "v23" ], "out": [ - "v57" + "v60" ] }, "type": "BuiltinCall" @@ -1014,12 +1014,12 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v36" + "v38" ] }, { "in": [ - "v36", + "v38", "0x00" ], "op": "mstore", @@ -1050,7 +1050,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v81", + "cond": "v85", "targets": [ "Block18", "Block17" @@ -1065,7 +1065,7 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v64" + "v68" ] }, { @@ -1075,13 +1075,13 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v67" + "v71" ] }, { "in": [ - "v67", - "v64" + "v71", + "v68" ], "op": "mstore", "out": [] @@ -1093,67 +1093,67 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v72" + "v76" ] }, { "in": [ "0x01", - "v72" + "v76" ], "op": "sub", "out": [ - "v73" + "v77" ] }, { "in": [ - "v73", - "v57" + "v77", + "v60" ], "op": "and", "out": [ - "v78" + "v82" ] }, { "in": [], "op": "gas", "out": [ - "v79" + "v83" ] }, { "in": [ "0x20", - "v64", + "v68", "0x04", - "v64", - "v78", - "v79" + "v68", + "v82", + "v83" ], "op": "staticcall", "out": [ - "v80" + "v84" ] }, { "in": [ - "v80" + "v84" ], "op": "iszero", "out": [ - "v81" + "v85" ] } ], "liveness": { "in": [ - "v57" + "v60" ], "out": [ - "v64", - "v80" + "v68", + "v84" ] }, "type": "BuiltinCall" @@ -1170,21 +1170,21 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v59" + "v62" ] }, { "in": [], "op": "returndatasize", "out": [ - "v60" + "v63" ] }, { "in": [ - "v60", + "v63", "0x00", - "v59" + "v62" ], "op": "returndatacopy", "out": [] @@ -1193,13 +1193,13 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v62" + "v65" ] }, { "in": [ - "v62", - "v59" + "v65", + "v62" ], "op": "revert", "out": [] @@ -1213,7 +1213,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v80", + "cond": "v84", "targets": [ "Block21", "Block20" @@ -1224,11 +1224,11 @@ Yul Control Flow Graph: "instructions": [], "liveness": { "in": [ - "v64", - "v80" + "v68", + "v84" ], "out": [ - "v64" + "v68" ] } }, @@ -1244,21 +1244,21 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v82" + "v86" ] }, { "in": [], "op": "returndatasize", "out": [ - "v83" + "v87" ] }, { "in": [ - "v83", + "v87", "0x00", - "v82" + "v86" ], "op": "returndatacopy", "out": [] @@ -1267,13 +1267,13 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v85" + "v89" ] }, { "in": [ - "v85", - "v82" + "v89", + "v86" ], "op": "revert", "out": [] @@ -1298,11 +1298,11 @@ Yul Control Flow Graph: { "in": [ "0x00", - "v137" + "v144" ], "op": "PhiFunction", "out": [ - "phi139" + "phi146" ] }, { @@ -1311,13 +1311,13 @@ Yul Control Flow Graph: ], "op": "mload", "out": [ - "v138" + "v145" ] }, { "in": [ - "phi139", - "v138" + "phi146", + "v145" ], "op": "mstore", "out": [] @@ -1325,7 +1325,7 @@ Yul Control Flow Graph: { "in": [ "0x20", - "v138" + "v145" ], "op": "return", "out": [] @@ -1333,7 +1333,7 @@ Yul Control Flow Graph: ], "liveness": { "in": [ - "phi139" + "phi146" ], "out": [] }, @@ -1341,7 +1341,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v92", + "cond": "v97", "targets": [ "Block23", "Block22" @@ -1354,26 +1354,26 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v91" + "v96" ] }, { "in": [ - "v91", + "v96", "0x20" ], "op": "gt", "out": [ - "v92" + "v97" ] } ], "liveness": { "in": [ - "v64" + "v68" ], "out": [ - "v64" + "v68" ] }, "type": "BuiltinCall" @@ -1384,7 +1384,7 @@ Yul Control Flow Graph: "Block22" ], "exit": { - "cond": "v111", + "cond": "v116", "targets": [ "Block25", "Block24" @@ -1396,11 +1396,11 @@ Yul Control Flow Graph: { "in": [ "0x20", - "v93" + "v98" ], "op": "PhiFunction", "out": [ - "phi96" + "phi101" ] }, { @@ -1409,79 +1409,79 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v95" + "v100" ] }, { "in": [ "0x1f", - "phi96" + "phi101" ], "op": "add", "out": [ - "v99" + "v104" ] }, { "in": [ - "v95", - "v99" + "v100", + "v104" ], "op": "and", "out": [ - "v100" + "v105" ] }, { "in": [ - "v100", - "v64" + "v105", + "v68" ], "op": "add", "out": [ - "v108" + "v113" ] }, { "in": [ - "v64", - "v108" + "v68", + "v113" ], "op": "lt", "out": [ - "v109" + "v114" ] }, { "in": [ "0xffffffffffffffff", - "v108" + "v113" ], "op": "gt", "out": [ - "v110" + "v115" ] }, { "in": [ - "v109", - "v110" + "v114", + "v115" ], "op": "or", "out": [ - "v111" + "v116" ] } ], "liveness": { "in": [ - "v64", - "phi96" + "v68", + "phi101" ], "out": [ - "v64", - "phi96", - "v108" + "v68", + "phi101", + "v113" ] }, "type": "BuiltinCall" @@ -1499,24 +1499,24 @@ Yul Control Flow Graph: "in": [], "op": "returndatasize", "out": [ - "v93" + "v98" ] } ], "liveness": { "in": [ - "v64" + "v68" ], "out": [ - "v93", - "v64" + "v98", + "v68" ] }, "type": "BuiltinCall" }, { "exit": { - "cond": "v131", + "cond": "v137", "targets": [ "Block28", "Block27" @@ -1527,7 +1527,7 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v108", + "v113", "0x40" ], "op": "mstore", @@ -1535,43 +1535,43 @@ Yul Control Flow Graph: }, { "in": [ - "phi96", - "v64" + "phi101", + "v68" ], "op": "add", "out": [ - "v129" + "v135" ] }, { "in": [ - "v64", - "v129" + "v68", + "v135" ], "op": "sub", "out": [ - "v130" + "v136" ] }, { "in": [ "0x20", - "v130" + "v136" ], "op": "slt", "out": [ - "v131" + "v137" ] } ], "liveness": { "in": [ - "v64", - "phi96", - "v108" + "v68", + "phi101", + "v113" ], "out": [ - "v64" + "v68" ] }, "type": "BuiltinCall" @@ -1589,12 +1589,12 @@ Yul Control Flow Graph: ], "op": "shl", "out": [ - "v112" + "v117" ] }, { "in": [ - "v112", + "v117", "0x00" ], "op": "mstore", @@ -1634,20 +1634,20 @@ Yul Control Flow Graph: "instructions": [ { "in": [ - "v64" + "v68" ], "op": "mload", "out": [ - "v137" + "v144" ] } ], "liveness": { "in": [ - "v64" + "v68" ], "out": [ - "v137" + "v144" ] }, "type": "BuiltinCall" @@ -1736,7 +1736,7 @@ Yul Control Flow Graph: ], "op": "datasize", "out": [ - "v6" + "v7" ] }, { @@ -1746,13 +1746,13 @@ Yul Control Flow Graph: ], "op": "dataoffset", "out": [ - "v7" + "v8" ] }, { "in": [ - "v6", "v7", + "v8", "v0" ], "op": "codecopy", @@ -1760,7 +1760,7 @@ Yul Control Flow Graph: }, { "in": [ - "v6", + "v7", "v0" ], "op": "return", @@ -1982,7 +1982,7 @@ Yul Control Flow Graph: }, { "exit": { - "cond": "v19", + "cond": "v20", "targets": [ "Block9", "Block8" @@ -1997,34 +1997,34 @@ Yul Control Flow Graph: ], "op": "not", "out": [ - "v16" + "v17" ] }, { "in": [], "op": "calldatasize", "out": [ - "v17" + "v18" ] }, { "in": [ - "v16", - "v17" + "v17", + "v18" ], "op": "add", "out": [ - "v18" + "v19" ] }, { "in": [ "0x00", - "v18" + "v19" ], "op": "slt", "out": [ - "v19" + "v20" ] } ], diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index 20bddfad2..21836ee2a 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -79,24 +79,25 @@ class StackLayoutDotExporter: public io::DotExporterBase _out << "IN: " << stackToString(blockLayout->stackIn) << "\\l\\\n"; std::size_t i = 0; - m_cfg.forEachOperation(block, [&](InstId const instId, SSACFG::Inst const& inst) { + m_cfg.forEachOperation(block, [&](InstId const _instId, SSACFG::Inst const& _inst) { yulAssert(i < blockLayout->operationIn.size()); auto operationStack = blockLayout->operationIn[i]; _out << "\\l\\\n"; _out << stackToString(operationStack) << "\\l\\\n"; - if (inst.opcode == InstOpcode::Call) - _out << escapeLabel(m_controlFlow.functionGraph(m_cfg.callPayload(instId).graphID)->name); + if (_inst.opcode == InstOpcode::Call) + _out << escapeLabel(m_controlFlow.functionGraph(m_cfg.callPayload(_instId).graphID)->name); else - _out << escapeLabel(m_cfg.evmDialect.builtin(m_cfg.builtinPayload(instId).builtin).name); + _out << escapeLabel(m_cfg.evmDialect.builtin(m_cfg.builtinPayload(_instId).builtin).name); _out << "\\l\\\n"; - yulAssert(inst.inputs.size() <= operationStack.size()); - for (std::size_t j = 0; j < inst.inputs.size(); ++j) + yulAssert(_inst.inputs.size() <= operationStack.size()); + for (std::size_t j = 0; j < _inst.inputs.size(); ++j) operationStack.pop_back(); - for (auto const& output: SSACFG::outputsOf(instId, inst.numOutputs)) - operationStack.push_back(StackSlot::makeValueID(m_cfg, output)); + m_cfg.forEachOutput(_instId, [&](InstId const output) { + operationStack.push_back(StackSlot::makeValue(m_cfg, output)); + }); _out << stackToString(operationStack) << "\\l\\\n"; ++i; }); diff --git a/test/libyul/ssa/StackShufflerTest.cpp b/test/libyul/ssa/StackShufflerTest.cpp index 9a0bf9bf2..87aebdbf5 100644 --- a/test/libyul/ssa/StackShufflerTest.cpp +++ b/test/libyul/ssa/StackShufflerTest.cpp @@ -57,7 +57,6 @@ std::string_view constexpr parserKeyAllowSpilling {"allowSpilling"}; std::string_view constexpr parserKeyInitialSpilled {"initialSpilledSet"}; using Slot = StackSlot; -using ValueId = SSACFG::ValueId; struct ParsedIdentifierTable { @@ -67,8 +66,8 @@ struct ParsedIdentifierTable std::string render(StackSlot const& _slot) const { - if (_slot.isValueID()) - if (auto const it = idToToken.find(_slot.valueID().instId()); it != idToToken.end()) + if (_slot.isValue()) + if (auto const it = idToToken.find(_slot.value()); it != idToToken.end()) return it->second; return slotToString(_slot); } @@ -127,7 +126,7 @@ Slot parseSlot(ParsedIdentifierTable& _table, std::string_view _token) { if (!solidity::util::parseArithmetic(_token.substr(1))) throw std::runtime_error(fmt::format("Couldn't parse variable token: {}", _token)); - return _table.store.appendBuiltinCall({0}, {}, {}, /*numOutputs*/ 1); + return _table.store.appendBuiltinCall({0}, {}, {}); } throw std::runtime_error(fmt::format("Unknown token: {}", _token)); }; @@ -140,7 +139,7 @@ Slot parseSlot(ParsedIdentifierTable& _table, std::string_view _token) _table.tokenToId.emplace(tokenStr, id); _table.idToToken.emplace(id, tokenStr); } - return Slot::makeValueID(_table.store, ValueId{id, 0}); + return Slot::makeValue(_table.store, id); } /// Parse a string like "[v172, phi109, lit7, JUNK]" into Stack::Data @@ -182,7 +181,7 @@ std::pair parseLiveness(ParsedIdentifierTabl entries.reserve(slots.size()); for (auto const& slot: slots) { - yulAssert(slot.isValueID(), "Only value IDs are permitted in liveness definition."); + yulAssert(slot.isValue(), "Only value IDs are permitted in liveness definition."); entries.emplace_back(slot, 1u); } return {StackSlotLiveness{std::move(entries)}, slots}; @@ -273,7 +272,7 @@ struct ShuffleTestInput { auto [liveness, slots] = parseLiveness(_table, value); for (auto const& [slot, _]: liveness) - result.initialSpilledSet.spill(slot.valueID()); + result.initialSpilledSet.spill(slot.value()); result.initialSpilledSetSlots = std::move(slots); } @@ -325,7 +324,7 @@ class TraceRecorder fmt::join( m_targetTail | ranges::views::transform( [this](StackSlot const& _slot) { - std::string const suffix = m_spillSet.isSpilled(_slot.valueID()) ? "*" : ""; + std::string const suffix = m_spillSet.isSpilled(_slot.value()) ? "*" : ""; return m_table.render(_slot) + suffix; } ), @@ -579,7 +578,7 @@ explicitly provided.)"; result.status != StackShufflerResult::Status::StackTooDeep ) break; - spillSet.spill(result.culprit.valueID()); + spillSet.spill(result.culprit.value()); spilledSlotList.push_back(result.culprit); } @@ -632,7 +631,7 @@ explicitly provided.)"; yulAssert(stackData.size() == *testConfig.targetStackSize); for (auto const& slot: testConfig.targetStackTailSet | ranges::views::keys) { - if (spillSet.isSpilled(slot.valueID())) + if (spillSet.isSpilled(slot.value())) continue; auto const findIt = ranges::find( stackData.begin(), diff --git a/test/libyul/ssa/controlFlowGraph/complex.yul b/test/libyul/ssa/controlFlowGraph/complex.yul index 44fb7e614..c1bc8f16e 100644 --- a/test/libyul/ssa/controlFlowGraph/complex.yul +++ b/test/libyul/ssa/controlFlowGraph/complex.yul @@ -71,7 +71,7 @@ // Block 1; (1, max 17)\nLiveIn: phi5[4], v1[1], v0[1]\l\ // LiveOut: phi5[2], v1[1], v0[1]\l\nUsed: phi5[2]\l\nphi5 := φ(\l\ // Block 0 => 0x2a,\l\ -// Block 21 => v61\l\ +// Block 21 => v63\l\ // )\l\ // v6 := lt(v0, phi5)\l\ // "]; @@ -132,10 +132,10 @@ // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ // Block 13; (9, max 17)\nLiveIn: phi5[1], v1[1], v7[1], v0[1]\l\ -// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: v7[1]\l\nv32 := eq(0x03, v7)\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: v7[1]\l\nv33 := eq(0x03, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v32 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit [label="{ If v33 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ @@ -147,10 +147,10 @@ // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ // Block 16; (15, max 17)\nLiveIn: phi5[1], v1[1], v0[1]\l\ -// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nv37 := mload(v1)\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nv38 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v37 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit [label="{ If v38 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ @@ -175,22 +175,22 @@ // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ // Block 3; (12, max 14)\nLiveIn: phi5[1], v1[1], v0[1]\l\ -// LiveOut: v61[1], v1[1], v0[1]\l\nUsed: phi5[1]\l\nv61 := add(0x01, phi5)\l\ -// v62 := calldataload(v61)\l\ +// LiveOut: v63[1], v1[1], v0[1]\l\nUsed: phi5[1]\l\nv63 := add(0x01, phi5)\l\ +// v64 := calldataload(v63)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v62 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit [label="{ If v64 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v61[1]\l\ -// LiveOut: \l\nUsed: v61[1]\l\nsstore(v61, 0x00)\l\ +// Block 20; (13, max 13)\nLiveIn: v63[1]\l\ +// LiveOut: \l\nUsed: v63[1]\l\nsstore(v63, 0x00)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0x00]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v61[1], v1[1], v0[1]\l\ -// LiveOut: v61[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ +// Block 21; (14, max 14)\nLiveIn: v63[1], v1[1], v0[1]\l\ +// LiveOut: v63[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/ssa/controlFlowGraph/complex2.yul b/test/libyul/ssa/controlFlowGraph/complex2.yul index ceb645374..6f8f5fbc7 100644 --- a/test/libyul/ssa/controlFlowGraph/complex2.yul +++ b/test/libyul/ssa/controlFlowGraph/complex2.yul @@ -87,7 +87,7 @@ // Block 1; (1, max 17)\nLiveIn: phi5[4], v1[1], v0[1]\l\ // LiveOut: phi5[2], v1[1], v0[1]\l\nUsed: phi5[2]\l\nphi5 := φ(\l\ // Block 0 => 0x2a,\l\ -// Block 21 => v61\l\ +// Block 21 => v63\l\ // )\l\ // v6 := lt(v0, phi5)\l\ // "]; @@ -148,10 +148,10 @@ // Block1_12 -> Block1_12Exit; // Block1_13 [label="\ // Block 13; (9, max 17)\nLiveIn: phi5[1], v1[1], v7[1], v0[1]\l\ -// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: v7[1]\l\nv32 := eq(0x03, v7)\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: v7[1]\l\nv33 := eq(0x03, v7)\l\ // "]; // Block1_13 -> Block1_13Exit; -// Block1_13Exit [label="{ If v32 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_13Exit [label="{ If v33 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_13Exit:0 -> Block1_16 [style="solid"]; // Block1_13Exit:1 -> Block1_15 [style="solid"]; // Block1_15 [label="\ @@ -163,10 +163,10 @@ // Block1_15Exit -> Block1_5 [style="solid"]; // Block1_16 [label="\ // Block 16; (15, max 17)\nLiveIn: phi5[1], v1[1], v0[1]\l\ -// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nv37 := mload(v1)\l\ +// LiveOut: phi5[1], v1[1], v0[1]\l\nUsed: \l\nv38 := mload(v1)\l\ // "]; // Block1_16 -> Block1_16Exit; -// Block1_16Exit [label="{ If v37 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_16Exit [label="{ If v38 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_16Exit:0 -> Block1_18 [style="solid"]; // Block1_16Exit:1 -> Block1_17 [style="solid"]; // Block1_5 [label="\ @@ -191,22 +191,22 @@ // Block1_18Exit -> Block1_5 [style="solid"]; // Block1_3 [label="\ // Block 3; (12, max 14)\nLiveIn: phi5[1], v1[1], v0[1]\l\ -// LiveOut: v61[1], v1[1], v0[1]\l\nUsed: phi5[1]\l\nv61 := add(0x01, phi5)\l\ -// v62 := calldataload(v61)\l\ +// LiveOut: v63[1], v1[1], v0[1]\l\nUsed: phi5[1]\l\nv63 := add(0x01, phi5)\l\ +// v64 := calldataload(v63)\l\ // "]; // Block1_3 -> Block1_3Exit; -// Block1_3Exit [label="{ If v62 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block1_3Exit [label="{ If v64 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block1_3Exit:0 -> Block1_21 [style="solid"]; // Block1_3Exit:1 -> Block1_20 [style="solid"]; // Block1_20 [label="\ -// Block 20; (13, max 13)\nLiveIn: v61[1]\l\ -// LiveOut: \l\nUsed: v61[1]\l\nsstore(v61, 0x00)\l\ +// Block 20; (13, max 13)\nLiveIn: v63[1]\l\ +// LiveOut: \l\nUsed: v63[1]\l\nsstore(v63, 0x00)\l\ // "]; // Block1_20Exit [label="FunctionReturn[0x00]"]; // Block1_20 -> Block1_20Exit; // Block1_21 [label="\ -// Block 21; (14, max 14)\nLiveIn: v61[1], v1[1], v0[1]\l\ -// LiveOut: v61[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ +// Block 21; (14, max 14)\nLiveIn: v63[1], v1[1], v0[1]\l\ +// LiveOut: v63[1], v1[1], v0[1]\l\nUsed: \l\nsstore(0xffff, 0xff)\l\ // "]; // Block1_21 -> Block1_21Exit [arrowhead=none]; // Block1_21Exit [label="Jump" shape=oval]; diff --git a/test/libyul/ssa/controlFlowGraph/function.yul b/test/libyul/ssa/controlFlowGraph/function.yul index d9832b064..b91d9f652 100644 --- a/test/libyul/ssa/controlFlowGraph/function.yul +++ b/test/libyul/ssa/controlFlowGraph/function.yul @@ -28,8 +28,10 @@ // Entry -> Block0_0; // Block0_0 [fillcolor="#FF746C", style=filled, label="\ // Block 0; (0, max 0)\nLiveIn: \l\ -// LiveOut: \l\nUsed: \l\nv0, v0.1 := i()\l\ -// h(v0)\l\ +// LiveOut: \l\nUsed: \l\nv0 := i()\l\ +// v1 := v0.proj(0)\l\ +// v2 := v0.proj(1)\l\ +// h(v1)\l\ // "]; // Block0_0Exit [label="Terminated"]; // Block0_0 -> Block0_0Exit; diff --git a/test/libyul/ssa/stackLayoutGenerator/dead_code.yul b/test/libyul/ssa/stackLayoutGenerator/dead_code.yul index 156baf27b..88c962fc1 100644 --- a/test/libyul/ssa/stackLayoutGenerator/dead_code.yul +++ b/test/libyul/ssa/stackLayoutGenerator/dead_code.yul @@ -44,14 +44,14 @@ // Block0_2 [label="\ // IN: [v1]\l\ // \l\ -// [v1, lit3]\l\ +// [v1, lit4]\l\ // calldataload\l\ -// [v1, v4]\l\ +// [v1, v5]\l\ // \l\ -// OUT: [v1, v4, v4]\l\ +// OUT: [v1, v5, v5]\l\ // "]; // Block0_2 -> Block0_2Exit; -// Block0_2Exit [label="{ If v4 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; +// Block0_2Exit [label="{ If v5 | { <0> Zero | <1> NonZero }}" shape=Mrecord]; // Block0_2Exit:0 -> Block0_5 [style="solid"]; // Block0_2Exit:1 -> Block0_4 [style="solid"]; // Block0_4 [label="\ @@ -66,9 +66,9 @@ // Block0_4Exit [label="Terminated"]; // Block0_4 -> Block0_4Exit; // Block0_5 [label="\ -// IN: [v1, v4]\l\ +// IN: [v1, v5]\l\ // \l\ -// [v4, v1]\l\ +// [v5, v1]\l\ // sstore\l\ // []\l\ // \l\ diff --git a/test/libyul/ssa/stackLayoutGenerator/function.yul b/test/libyul/ssa/stackLayoutGenerator/function.yul index 3fc70f0f6..53f81ab91 100644 --- a/test/libyul/ssa/stackLayoutGenerator/function.yul +++ b/test/libyul/ssa/stackLayoutGenerator/function.yul @@ -33,9 +33,9 @@ // \l\ // [FunctionCallReturnLabel[0]]\l\ // i\l\ -// [FunctionCallReturnLabel[0], v0, v0.1]\l\ +// [FunctionCallReturnLabel[0], v1, v2]\l\ // \l\ -// [v0]\l\ +// [v1]\l\ // h\l\ // []\l\ // \l\ diff --git a/test/libyul/ssa/stackLayoutGenerator/multi_return.yul b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul index e7a5bb015..e6c38d47a 100644 --- a/test/libyul/ssa/stackLayoutGenerator/multi_return.yul +++ b/test/libyul/ssa/stackLayoutGenerator/multi_return.yul @@ -20,17 +20,17 @@ // \l\ // [FunctionCallReturnLabel[0], lit0]\l\ // pair\l\ -// [FunctionCallReturnLabel[0], v1, v1.1]\l\ +// [FunctionCallReturnLabel[0], v2, v3]\l\ // \l\ -// [v1, v1.1, FunctionCallReturnLabel[1], v1]\l\ +// [v2, v3, FunctionCallReturnLabel[1], v2]\l\ // pair\l\ -// [v1, v1.1, FunctionCallReturnLabel[1], v2, v2.1]\l\ +// [v2, v3, FunctionCallReturnLabel[1], v5, v6]\l\ // \l\ -// [JUNK, v1.1, v2.1, v2]\l\ +// [JUNK, v3, v6, v5]\l\ // add\l\ -// [JUNK, v1.1, v3]\l\ +// [JUNK, v3, v7]\l\ // \l\ -// [JUNK, v3, v1.1]\l\ +// [JUNK, v7, v3]\l\ // sstore\l\ // [JUNK]\l\ // \l\ diff --git a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul index 7a7afcd3e..2f6afb2c9 100644 --- a/test/libyul/ssa/stackLayoutGenerator/simple_if.yul +++ b/test/libyul/ssa/stackLayoutGenerator/simple_if.yul @@ -67,10 +67,10 @@ // \l\ // [ReturnLabel[1], v1, v0]\l\ // add\l\ -// [ReturnLabel[1], v15]\l\ +// [ReturnLabel[1], v16]\l\ // \l\ -// OUT: [v15, ReturnLabel[1]]\l\ +// OUT: [v16, ReturnLabel[1]]\l\ // "]; -// Block1_2Exit [label="FunctionReturn[v15]"]; +// Block1_2Exit [label="FunctionReturn[v16]"]; // Block1_2 -> Block1_2Exit; // } From f61f32ab9773750337f9b03e56b17dbe523f05fc Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 4 May 2026 11:43:26 +0200 Subject: [PATCH 1310/1340] SSA CFG: bind variables to unreachable for non-continuing multi-return calls --- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 34 +++++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index d65c28460..9c7817221 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -422,11 +422,20 @@ void SSACFGBuilder::assign(std::vector(_expression)) { InstId const callId = visitFunctionCall(*functionCall); - std::vector outputs; - m_graph.forEachOutput(callId, [&](InstId const id) { outputs.push_back(id); }); - yulAssert(outputs.size() == _variables.size()); - for (auto const& [var, output]: ranges::zip_view(_variables, outputs)) - writeVariable(var, m_currentBlock, output); + if (m_graph.isUnreachable(callId)) + { + // The callee did not continue: post-call block is unreachable. Bind variables to unreachable. + for (auto const& var: _variables) + writeVariable(var, m_currentBlock, callId); + } + else + { + std::vector outputs; + m_graph.forEachOutput(callId, [&](InstId const id) { outputs.push_back(id); }); + yulAssert(outputs.size() == _variables.size()); + for (auto const& [var, output]: ranges::zip_view(_variables, outputs)) + writeVariable(var, m_currentBlock, output); + } return; } auto const rhs = _expression ? @@ -486,13 +495,14 @@ InstId SSACFGBuilder::visitFunctionCall(FunctionCall const& _call) ); } }, _call.functionName); - if (!canContinue) - { - currentBlock().exit = SSACFG::BasicBlock::Terminated{}; - m_currentBlock = m_graph.makeBlock(currentBlockDebugData()); - sealBlock(m_currentBlock); - } - return id; + if (canContinue) + return id; + // `id` lives in the now-Terminated call block and won't dominate the successor, + // so terminate, open a fresh successor and signal non-continuation via unreachableValue. + currentBlock().exit = SSACFG::BasicBlock::Terminated{}; + m_currentBlock = m_graph.makeBlock(currentBlockDebugData()); + sealBlock(m_currentBlock); + return m_graph.unreachableValue(); } InstId SSACFGBuilder::zero() From d25627fbf81f6ae3dbfae21e3545a19c55e8629b Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 4 May 2026 11:43:38 +0200 Subject: [PATCH 1311/1340] SSA CFG: add test for multi-return non-continuing function --- .../multi_return_non_continuing_function.yul | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 test/libyul/ssa/controlFlowGraph/multi_return_non_continuing_function.yul diff --git a/test/libyul/ssa/controlFlowGraph/multi_return_non_continuing_function.yul b/test/libyul/ssa/controlFlowGraph/multi_return_non_continuing_function.yul new file mode 100644 index 000000000..e4ffc858a --- /dev/null +++ b/test/libyul/ssa/controlFlowGraph/multi_return_non_continuing_function.yul @@ -0,0 +1,32 @@ +{ + function reverter() -> a, b { revert(0, 0) } + // the cfg should reflect that reverter has two output variables although it cannot continue + let x, y := reverter() + sstore(x, y) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans"] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry [label="Entry"]; +// Entry -> Block0_0; +// Block0_0 [fillcolor="#FF746C", style=filled, label="\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nUsed: \l\nv0 := reverter()\l\ +// v1 := v0.proj(0)\l\ +// v2 := v0.proj(1)\l\ +// "]; +// Block0_0Exit [label="Terminated"]; +// Block0_0 -> Block0_0Exit; +// FunctionEntry_reverter_0 [label="function reverter: +// [2 returns] := reverter()"]; +// FunctionEntry_reverter_0 -> Block1_0; +// Block1_0 [fillcolor="#FF746C", style=filled, label="\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nUsed: \l\nrevert(0x00, 0x00)\l\ +// "]; +// Block1_0Exit [label="Terminated"]; +// Block1_0 -> Block1_0Exit; +// } From b0ff7b9268db53d5407a72467231c81e4cc85833 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 4 May 2026 15:12:41 +0200 Subject: [PATCH 1312/1340] SSA CFG: Add `outputsOf` helper that returns a range over inst id --- libyul/backends/evm/ssa/CodeTransform.cpp | 12 +++---- libyul/backends/evm/ssa/SSACFG.h | 35 ++++++++++++------- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 6 ++-- .../backends/evm/ssa/StackLayoutGenerator.cpp | 2 +- libyul/backends/evm/ssa/io/JSONExporter.cpp | 4 +-- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 07a9f24a4..b2601790d 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -309,16 +309,14 @@ void CodeTransform::operator()(InstId _instId, StackData const& _operationInputL for (size_t i = 0; i < _inst.inputs.size(); ++i) m_stack.pop(); // simulate that the outputs are produced - std::vector outputs; - outputs.reserve(m_cfg.numReturnsOf(_instId)); - m_cfg.forEachOutput(_instId, [&](InstId const id) { outputs.push_back(id); }); - for (InstId const id: outputs) + auto const numOutputs = m_cfg.numReturnsOf(_instId); + for (InstId const id: m_cfg.outputsOf(_instId)) m_stack.push(StackSlot::makeValue(m_cfg, id)); - yulAssert(m_stack.size() == baseHeight + outputs.size()); + yulAssert(m_stack.size() == baseHeight + numOutputs); for (auto const& [stackEntry, output]: ranges::views::zip( - m_stack.data() | ranges::views::take_last(outputs.size()), - outputs + m_stack.data() | ranges::views::take_last(numOutputs), + m_cfg.outputsOf(_instId) )) yulAssert(stackEntry.isValue() && stackEntry.value() == output); yulAssert( diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index a71748267..986127f87 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -32,9 +32,10 @@ #include +#include #include +#include #include -#include #include #include @@ -47,6 +48,9 @@ namespace solidity::yul::ssa class LivenessAnalysis; struct ControlFlowGraphs; +template +concept InputRangeOf = ranges::input_range && std::same_as, T>; + class SSACFG { public: @@ -316,7 +320,7 @@ class SSACFG /// View over the contiguous trailing Projections of `_producer` in `m_insts`. Empty for ops with <= 1 returns. /// Note this relies on the m_insts-contiguity invariant established by `make(Builtin)CallWithProjections`: /// projections live at `m_insts[_producer.value+1..+numReturns]`. - auto projectionsOf(InstId const _producer) const + InputRangeOf auto projectionsOf(InstId const _producer) const { std::size_t const n = numReturnsOf(_producer); std::size_t const count = n >= 2 ? n : 0; @@ -341,26 +345,33 @@ class SSACFG } return ranges::views::iota(static_cast(firstIdx), static_cast(lastIdx)) | - ranges::views::transform([](InstId::ValueType const _idVal) { return InstId{_idVal}; }); + ranges::views::transform(&toInstId); + } + + /// View over the logical outputs of `_producer` in stack order: the producer itself if it has a single return, + /// the trailing Projections if it has multiple, and an empty range otherwise. + InputRangeOf auto outputsOf(InstId const _producer) const + { + std::size_t const n = numReturnsOf(_producer); + if (n >= 2) + return projectionsOf(_producer); + auto const firstIdx = static_cast(_producer.value); + return + ranges::views::iota(firstIdx, static_cast(firstIdx + n)) | + ranges::views::transform(&toInstId); } /// Invokes `_fn(InstId)` once per logical output of `_producer` in stack order. template Fn> void forEachOutput(InstId const _producer, Fn&& _fn) const { - auto const n = numReturnsOf(_producer); - if (n == 0) - return; - if (n == 1) - { - _fn(_producer); - return; - } - for (InstId const id: projectionsOf(_producer)) + for (InstId const id: outputsOf(_producer)) _fn(id); } private: + static InstId toInstId(InstId::ValueType const _v) { return InstId{_v}; } + InstId makeBuiltinCall( BlockId const _block, BuiltinCall _payload, diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 9c7817221..acc3a6277 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -430,10 +430,10 @@ void SSACFGBuilder::assign(std::vector outputs; - m_graph.forEachOutput(callId, [&](InstId const id) { outputs.push_back(id); }); + yulAssert(m_graph.numReturnsOf(callId) == _variables.size()); + auto const outputs = m_graph.outputsOf(callId); yulAssert(outputs.size() == _variables.size()); - for (auto const& [var, output]: ranges::zip_view(_variables, outputs)) + for (auto const& [var, output]: ranges::views::zip(_variables, outputs)) writeVariable(var, m_currentBlock, output); } return; diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 0c6618121..e74761be5 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -231,7 +231,7 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) auto const& operationsLiveOut = m_liveness.operationsLiveOut(_blockId); blockLayout.operationIn.reserve(operationsLiveOut.size()); std::size_t operationIndex = 0; - m_cfg.forEachOperation(block, [&](InstId const _instId, SSACFG::Inst const& _inst){ + m_cfg.forEachOperation(block, [&](InstId const _instId, SSACFG::Inst const& _inst) { auto opLiveOutWithoutOutputs = operationsLiveOut[operationIndex]; m_cfg.forEachOutput(_instId, [&](InstId const id) { opLiveOutWithoutOutputs.erase(id); }); diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index 4570dca2b..ade3dd4a5 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -70,9 +70,7 @@ Json toJson(Json& _ret, SSACFG const& _cfg, InstId const _instId, ControlFlowGra } opJson["in"] = toJson(_cfg, inst.inputs); - std::vector outputs; - _cfg.forEachOutput(_instId, [&](InstId const id) { outputs.push_back(id); }); - opJson["out"] = toJson(_cfg, outputs); + opJson["out"] = toJson(_cfg, _cfg.outputsOf(_instId)); return opJson; } From 4e2e89750cf25b8ab96e44f8ec187de1d84ab87b Mon Sep 17 00:00:00 2001 From: Weixie Cui Date: Thu, 30 Apr 2026 20:20:30 +0800 Subject: [PATCH 1313/1340] NatSpec: Disallow `@return` tag on events. Ethereum events do not declare return parameters, unlike functions. The event branch of callable documentation incorrectly accepted the same tag set as functions, allowing misleading `@return` markup. Restrict event validation to `dev`, `notice`, and `param`, consistent with errors. --- Changelog.md | 1 + libsolidity/analysis/DocStringTagParser.cpp | 2 +- .../natspecJSON/invalid/docstring_event_return.sol | 6 ++++++ .../invalid/docstring_event_return_inheritance.sol | 10 ++++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/natspecJSON/invalid/docstring_event_return.sol create mode 100644 test/libsolidity/natspecJSON/invalid/docstring_event_return_inheritance.sol diff --git a/Changelog.md b/Changelog.md index ea6999ec5..65411ced9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: Bugfixes: +* NatSpec: Disallow ``@return`` tags on event documentation; events do not have return parameters (consistent with errors). ### 0.8.35 (2026-04-29) diff --git a/libsolidity/analysis/DocStringTagParser.cpp b/libsolidity/analysis/DocStringTagParser.cpp index b7fef128d..255686932 100644 --- a/libsolidity/analysis/DocStringTagParser.cpp +++ b/libsolidity/analysis/DocStringTagParser.cpp @@ -285,7 +285,7 @@ void DocStringTagParser::handleCallable( StructurallyDocumentedAnnotation& _annotation ) { - static std::set const validEventTags = std::set{"dev", "notice", "return", "param"}; + static std::set const validEventTags = std::set{"dev", "notice", "param"}; static std::set const validErrorTags = std::set{"dev", "notice", "param"}; static std::set const validModifierTags = std::set{"dev", "notice", "param", "inheritdoc"}; static std::set const validTags = std::set{"dev", "notice", "return", "param", "inheritdoc"}; diff --git a/test/libsolidity/natspecJSON/invalid/docstring_event_return.sol b/test/libsolidity/natspecJSON/invalid/docstring_event_return.sol new file mode 100644 index 000000000..2d499ef1d --- /dev/null +++ b/test/libsolidity/natspecJSON/invalid/docstring_event_return.sol @@ -0,0 +1,6 @@ +contract C { + /// @return foo + event E(uint x); +} +// ---- +// DocstringParsingError 6546: (14-29): Documentation tag @return not valid for events. diff --git a/test/libsolidity/natspecJSON/invalid/docstring_event_return_inheritance.sol b/test/libsolidity/natspecJSON/invalid/docstring_event_return_inheritance.sol new file mode 100644 index 000000000..e6d6183eb --- /dev/null +++ b/test/libsolidity/natspecJSON/invalid/docstring_event_return_inheritance.sol @@ -0,0 +1,10 @@ +interface I { + event E(uint x); +} +contract C is I { + /// @return bar + event E(uint x); +} +// ---- +// DocstringParsingError 6546: (53-68): Documentation tag @return not valid for events. +// DeclarationError 5883: (70-86): Event with same name and parameter types defined twice. From f3cc13d699099c0021b1ce6f4a174bc2d2e55e2c Mon Sep 17 00:00:00 2001 From: cui Date: Tue, 5 May 2026 16:13:05 +0800 Subject: [PATCH 1314/1340] Update Changelog.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nikola Matić --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 65411ced9..5112c051c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,7 +5,7 @@ Language Features: Compiler Features: Bugfixes: -* NatSpec: Disallow ``@return`` tags on event documentation; events do not have return parameters (consistent with errors). +* NatSpec: Disallow `@return` tag in event documentation. ### 0.8.35 (2026-04-29) From 0aff263cc5e4328e1f2fe8bbe802917396797259 Mon Sep 17 00:00:00 2001 From: blishko Date: Tue, 5 May 2026 17:49:32 +0200 Subject: [PATCH 1315/1340] SSA: Update assumptions made by CodeTransform about stack layouts Code transform has still been assuming that non-zero successor of a conditional jump does not have any other predecessor. It has been assuming that no modification was needed when moving from the out layout of the predecessor to the in layout of the non-zero successor. This assumption does not necessarily hold when non-zero successor can have other predecessors. We have dropped the assumption about single predecessor of a non-zero successor elsewhere. As we want to enable trasformations that will not uphold this assumption, we should update the code transformation as well. The fix is to ensure the stack is updated, if necessary, when moving from the predecessor to the non-zero successor. We already do the same in case of the zero successor. In addition, we also drop an assertion in StackLayoutGenerator that non-zero successor has no phi instructions. This is not an invariant of the CFG we want to maintain. --- libyul/backends/evm/ssa/CodeTransform.cpp | 5 +++++ libyul/backends/evm/ssa/StackLayoutGenerator.cpp | 3 --- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index b2601790d..7f997d680 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -359,6 +359,11 @@ void CodeTransform::operator()(SSACFG::BlockId const& _currentBlock, SSACFG::Bas } { yulAssert(m_stackLayout[_conditionalJump.nonZero]); + // transform stack to a state in which we can jump to the nonZero branch + prepareBlockExitStack( + m_stackLayout[_conditionalJump.nonZero]->stackIn, + PhiInverse(m_cfg, _currentBlock, _conditionalJump.nonZero) + ); assertLayoutCompatibility(m_stack.data(), m_stackLayout[_conditionalJump.nonZero]->stackIn); m_assembly.setStackHeight(static_cast(m_stack.size())); diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index e74761be5..44307f41c 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -312,9 +312,6 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) } yulAssert(!stack.empty() && stack.top().isValue() && stack.top().value() == _cJump.condition); - yulAssert(ranges::none_of(m_cfg.block(_cJump.nonZero).instructions, [this](InstId const _id) { - return m_cfg.isPhi(_id); - })); // exitIn = pre-JUMPI state (condition on top) for CodeTransform blockLayout.exitIn = currentStackData; From 9b2533d53a6ad77e0871e9712f0d07c54db7676e Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:44:32 +0200 Subject: [PATCH 1316/1340] SSA CFG: add identity, nop, and tombstone inst opcodes --- libyul/backends/evm/ssa/InstructionStore.h | 170 ++++++++++++++++----- libyul/backends/evm/ssa/SSACFG.h | 34 +++++ libyul/backends/evm/ssa/SSACFGTypes.cpp | 5 +- libyul/backends/evm/ssa/SSACFGTypes.h | 3 + 4 files changed, 176 insertions(+), 36 deletions(-) diff --git a/libyul/backends/evm/ssa/InstructionStore.h b/libyul/backends/evm/ssa/InstructionStore.h index ba134ac47..07a43ff6a 100644 --- a/libyul/backends/evm/ssa/InstructionStore.h +++ b/libyul/backends/evm/ssa/InstructionStore.h @@ -19,6 +19,13 @@ * Owns the instruction table of an SSACFG: hands out InstIds, stores opcode * payloads, and provides lookups. Has no knowledge of basic blocks or debug * information; SSACFG composes those concerns on top. + * + * Each Inst owns its payload directly via `std::unique_ptr`. Tombstoning + * an Inst (or flipping it via `replaceWith*`) resets the unique_ptr, releasing + * the variant and any heap memory it transitively held — most importantly + * `BuiltinCall::literalArguments`. Free `m_insts` slots are tracked in + * `m_freeInsts` and reused by future allocations; literal payloads are + * deduplicated through `m_literalDedup`. */ #pragma once @@ -34,6 +41,8 @@ #include #include #include +#include +#include #include namespace solidity::yul::ssa @@ -42,11 +51,10 @@ namespace solidity::yul::ssa class InstructionStore { public: - /// Sentinel value for `Inst::payloadIndex` when the opcode has no side-table payload. - static constexpr std::uint32_t NoPayload = std::numeric_limits::max(); - using NumReturnsSizeType = std::uint8_t; + struct LiteralPayload { u256 value; }; + struct UpsilonPayload { InstId targetPhi; }; struct BuiltinCall { BuiltinHandle builtin; @@ -59,12 +67,20 @@ class InstructionStore bool canContinue; std::size_t numReturns; }; + + using Payload = std::variant< + LiteralPayload, + UpsilonPayload, + BuiltinCall, + Call + >; + struct Inst { InstOpcode opcode; - std::uint32_t payloadIndex = NoPayload; BlockId block{}; std::vector inputs{}; + std::unique_ptr payload{}; constexpr bool isPhi() const noexcept { return opcode == InstOpcode::Phi; } constexpr bool isUpsilon() const noexcept { return opcode == InstOpcode::Upsilon; } @@ -72,6 +88,9 @@ class InstructionStore constexpr bool isUnreachable() const noexcept { return opcode == InstOpcode::Unreachable; } constexpr bool isFunctionArg() const noexcept { return opcode == InstOpcode::FunctionArg; } constexpr bool isProjection() const noexcept { return opcode == InstOpcode::Projection; } + constexpr bool isIdentity() const noexcept { return opcode == InstOpcode::Identity; } + constexpr bool isNop() const noexcept { return opcode == InstOpcode::Nop; } + constexpr bool isTombstone() const noexcept { return opcode == InstOpcode::Tombstone; } /// Operation = a Call or BuiltinCall. constexpr bool isOperation() const noexcept { @@ -95,14 +114,14 @@ class InstructionStore InstOpcode kindOf(InstId const _id) const { return inst(_id).opcode; } /// Returns the phi targeted by an Upsilon Inst. - InstId upsilonPhi(InstId const _id) const { return payloadAs(_id, m_upsilonPhis); } + InstId upsilonPhi(InstId const _id) const { return payloadAs(_id).targetPhi; } /// Returns the u256 payload of a Const Inst. - u256 const& literalPayload(InstId const _id) const { return payloadAs(_id, m_literalPayloads); } + u256 const& literalPayload(InstId const _id) const { return payloadAs(_id).value; } - BuiltinCall const& builtinPayload(InstId const _id) const { return payloadAs(_id, m_builtinPayloads); } + BuiltinCall const& builtinPayload(InstId const _id) const { return payloadAs(_id); } - Call const& callPayload(InstId const _id) const { return payloadAs(_id, m_callPayloads); } + Call const& callPayload(InstId const _id) const { return payloadAs(_id); } /// Returns the projection index of a Projection Inst NumReturnsSizeType projectionIndex(InstId const _id) const @@ -120,19 +139,19 @@ class InstructionStore /// Allocates a new Phi Inst defined in `_definingBlock`. Returns the new InstId. InstId appendPhi(BlockId const _definingBlock) { - return appendInst(Inst{InstOpcode::Phi, NoPayload, _definingBlock, {}}); + return appendInst(Inst{InstOpcode::Phi, _definingBlock, {}, nullptr}); } /// Allocates a new FunctionArg Inst defined in `_entryBlock`. Returns the new InstId. InstId appendFunctionArg(BlockId const _entryBlock) { - return appendInst(Inst{InstOpcode::FunctionArg, NoPayload, _entryBlock, {}}); + return appendInst(Inst{InstOpcode::FunctionArg, _entryBlock, {}, nullptr}); } /// Allocates a new Unreachable Inst. Not pinned to any block (see class comment). InstId appendUnreachable() { - return appendInst(Inst{InstOpcode::Unreachable, NoPayload, BlockId{}, {}}); + return appendInst(Inst{InstOpcode::Unreachable, BlockId{}, {}, nullptr}); } /// Allocates a new Const Inst with payload `_value`, pinned to `_entryBlock`. @@ -142,8 +161,12 @@ class InstructionStore yulAssert(_entryBlock.hasValue()); if (auto const it = m_literalDedup.find(_value); it != m_literalDedup.end()) return it->second; - auto const payloadIdx = allocPayload(m_literalPayloads, _value); - InstId const id = appendInst(Inst{InstOpcode::Const, payloadIdx, _entryBlock, {}}); + InstId const id = appendInst(Inst{ + InstOpcode::Const, + _entryBlock, + {}, + std::make_unique(LiteralPayload{_value}) + }); m_literalDedup.emplace(std::move(_value), id); return id; } @@ -158,9 +181,9 @@ class InstructionStore yulAssert(_block.hasValue()); return appendInst(Inst{ InstOpcode::BuiltinCall, - allocPayload(m_builtinPayloads, std::move(_payload)), _block, - std::move(_inputs) + std::move(_inputs), + std::make_unique(std::move(_payload)) }); } @@ -174,9 +197,9 @@ class InstructionStore yulAssert(_block.hasValue()); return appendInst(Inst{ InstOpcode::Call, - allocPayload(m_callPayloads, std::move(_payload)), _block, - std::move(_inputs) + std::move(_inputs), + std::make_unique(std::move(_payload)) }); } @@ -185,19 +208,97 @@ class InstructionStore { yulAssert(_block.hasValue()); yulAssert(_producer.hasValue()); - return appendInst(Inst{InstOpcode::Projection, NoPayload, _block, {_producer}}); + return appendInst(Inst{InstOpcode::Projection, _block, {_producer}, nullptr}); } /// Allocates a new Upsilon Inst targeting `_phi`, feeding `_value` from `_block`. InstId appendUpsilon(BlockId const _block, InstId const _value, InstId const _phi) { yulAssert(inst(_phi).isPhi()); - return appendInst(Inst{InstOpcode::Upsilon, allocPayload(m_upsilonPhis, _phi), _block, {_value}}); + return appendInst(Inst{ + InstOpcode::Upsilon, + _block, + {_value}, + std::make_unique(UpsilonPayload{_phi}) + }); } + /// Flips _target to Identity forwarding _forward. + void replaceWithIdentity(InstId const _target, InstId const _forward) + { + yulAssert(_target.hasValue()); + yulAssert(_forward.hasValue()); + yulAssert(_target != _forward, "Cannot replace value with itself"); + auto& i = inst(_target); + // every Const InstId is the unique handle for its value, so flipping it to Identity would silently rebind + // every other user of that literal to _forward; almost certainly not what the caller intended + yulAssert(!i.isLiteral(), "replaceWithIdentity must not morph a deduped Const slot"); + i.opcode = InstOpcode::Identity; + i.inputs.assign(1, _forward); + i.payload.reset(); + } + + /// Flips _target to Const carrying _value. If _value is already deduped to another slot, + /// flips _target to Identity forwarding to that slot instead. + void replaceWithConst(InstId _target, u256 _value) + { + yulAssert(_target.hasValue()); + auto& i = inst(_target); + // No-op if already this value. + if (i.opcode == InstOpcode::Const && std::get(*i.payload).value == _value) + return; + dropDedupIfConst(i); + if (auto const it = m_literalDedup.find(_value); it != m_literalDedup.end()) + { + i.opcode = InstOpcode::Identity; + i.inputs.assign(1, it->second); + i.payload.reset(); + return; + } + i.opcode = InstOpcode::Const; + i.inputs.clear(); + i.payload = std::make_unique(LiteralPayload{_value}); + m_literalDedup.emplace(std::move(_value), _target); + } + + /// Flips _target to Nop. Caller must ensure _target produces no observable value + /// (e.g., an Upsilon, or a void Call). + void replaceWithNop(InstId _target) + { + yulAssert(_target.hasValue()); + auto& i = inst(_target); + dropDedupIfConst(i); + i.opcode = InstOpcode::Nop; + i.inputs.clear(); + i.payload.reset(); + } + + /// Tombstones the slot at `_id`, releasing it for reuse by future appendInst calls. + void tombstone(InstId const _id) + { + yulAssert(_id.hasValue()); + auto& i = inst(_id); + dropDedupIfConst(i); + i.opcode = InstOpcode::Tombstone; + i.inputs.clear(); + i.payload.reset(); + i.block = BlockId{}; + m_freeInsts.push_back(_id.value); + } + + std::vector const& freeInsts() const { return m_freeInsts; } + private: InstId appendInst(Inst _inst) { + if (!m_freeInsts.empty()) + { + std::uint32_t const idx = m_freeInsts.back(); + m_freeInsts.pop_back(); + yulAssert(m_insts[idx].opcode == InstOpcode::Tombstone); + m_insts[idx] = std::move(_inst); + return InstId{idx}; + } // max itself is reserved for the 'empty' inst yulAssert(m_insts.size() < std::numeric_limits::max()); InstId const id{static_cast(m_insts.size())}; @@ -205,32 +306,31 @@ class InstructionStore return id; } - /// Asserts that the Inst at `_id` has opcode `Expected`, then returns its payload from `_store`. - template - typename Store::value_type const& payloadAs(InstId const _id, Store const& _store) const + /// Asserts that the Inst at `_id` has opcode `Expected`, then returns its payload as `T`. + template + T const& payloadAs(InstId const _id) const { auto const& i = inst(_id); yulAssert(i.opcode == Expected); - return _store.at(i.payloadIndex); + yulAssert(i.payload); + return std::get(*i.payload); } - /// Pushes `_payload` into `_store` and returns the resulting payload index. Asserts - /// the index fits in payloadIndex's u32 representation (max is reserved for NoPayload). - template - std::uint32_t allocPayload(std::vector& _store, T _payload) + /// If `_inst` is a Const, removes its entry from the literal dedup table. Used by + /// the replaceWith* primitives and tombstone() before overwriting the slot. + void dropDedupIfConst(Inst const& _inst) { - yulAssert(_store.size() < NoPayload); - auto const idx = static_cast(_store.size()); - _store.push_back(std::move(_payload)); - return idx; + if (_inst.opcode != InstOpcode::Const) + return; + yulAssert(_inst.payload); + u256 const& value = std::get(*_inst.payload).value; + m_literalDedup.erase(value); } std::vector m_insts; - std::vector m_literalPayloads; + /// Indices of tombstoned slots in `m_insts`, available for reuse by appendInst. + std::vector m_freeInsts; std::map m_literalDedup; - std::vector m_upsilonPhis; - std::vector m_builtinPayloads; - std::vector m_callPayloads; }; } diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 986127f87..9457e510c 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -147,6 +147,9 @@ class SSACFG bool isUnreachable(InstId const _id) const { return inst(_id).isUnreachable(); } bool isFunctionArg(InstId const _id) const { return inst(_id).isFunctionArg(); } bool isProjection(InstId const _id) const { return inst(_id).isProjection(); } + bool isIdentity(InstId const _id) const { return inst(_id).isIdentity(); } + bool isNop(InstId const _id) const { return inst(_id).isNop(); } + bool isTombstone(InstId const _id) const { return inst(_id).isTombstone(); } bool isOperation(InstId const _id) const { return inst(_id).isOperation(); } /// Returns the phi targeted by an Upsilon Inst. @@ -238,6 +241,37 @@ class SSACFG return scheduleInBlock(m_instructions.appendUpsilon(_block, _value, _phi), _block); } + /// Flips _target's opcode to Identity forwarding _forward + void replaceWithIdentity(InstId const _target, InstId const _forward) + { + m_instructions.replaceWithIdentity(_target, _forward); + } + + /// Flips _target to Const carrying _value + void replaceWithConst(InstId const _target, u256 _value) + { + m_instructions.replaceWithConst(_target, std::move(_value)); + } + + /// Flips _target to Nop. Caller must ensure _target produces no observable value + void replaceWithNop(InstId const _target) + { + m_instructions.replaceWithNop(_target); + } + + /// Tombstones an Inst, sweeping any trailing Projection cluster too + void tombstone(InstId const _id) + { + m_instructions.tombstone(_id); + } + + /// Returns the number of Projections trailing `_producer` in `m_insts` (0 for + /// non-multi-return slots). Thin wrapper around `InstructionStore::numTrailingProjections`. + InstructionStore::NumReturnsSizeType numTrailingProjections(InstId const _producer) const + { + return m_instructions.numTrailingProjections(_producer); + } + std::string toDot( bool _includeDiGraphDefinition=true, std::optional _functionIndex=std::nullopt, diff --git a/libyul/backends/evm/ssa/SSACFGTypes.cpp b/libyul/backends/evm/ssa/SSACFGTypes.cpp index 965c8e042..58d306544 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.cpp +++ b/libyul/backends/evm/ssa/SSACFGTypes.cpp @@ -34,13 +34,16 @@ std::string InstId::str(SSACFG const& _cfg) const case InstOpcode::Call: case InstOpcode::FunctionArg: case InstOpcode::Projection: + case InstOpcode::Identity: return fmt::format("v{}", value); case InstOpcode::Phi: return fmt::format("phi{}", value); case InstOpcode::Unreachable: return "[unreachable]"; case InstOpcode::Upsilon: - yulAssert(false, "Upsilon Insts have no output value"); + case InstOpcode::Nop: + case InstOpcode::Tombstone: + yulAssert(false, "Inst has no output value"); } util::unreachable(); } diff --git a/libyul/backends/evm/ssa/SSACFGTypes.h b/libyul/backends/evm/ssa/SSACFGTypes.h index dfb590d6f..8a0c6414a 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.h +++ b/libyul/backends/evm/ssa/SSACFGTypes.h @@ -63,6 +63,9 @@ enum class InstOpcode : std::uint8_t Unreachable, // dead code FunctionArg, // function param without inputs and a single output valueid Projection, // projection: single InstId input (multi-output producer) plus immediate index + Identity, // forwards its single input, resolved away by transform::removeIdentities, + Nop, // used to turn a void-typed Inst (eg an upsilon whose phi was eliminated) into a deletable placeholder + Tombstone, // marks a free slot in InstructionStore::m_insts, must never appear in block instructions }; } From 07f602608c26d8a6384f9262de2826ceab93f70c Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 5 May 2026 01:18:35 +0200 Subject: [PATCH 1317/1340] SSA CFG: add TLSF free list implementation --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/ssa/util/TLSFFreeList.h | 424 ++++++++++++++++++++ 2 files changed, 425 insertions(+) create mode 100644 libyul/backends/evm/ssa/util/TLSFFreeList.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index db0d30356..6898fe58c 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -104,6 +104,7 @@ add_library(yul backends/evm/ssa/StackSlotLiveness.h backends/evm/ssa/StackToMemorySpilling.h backends/evm/ssa/util/UseCountSet.h + backends/evm/ssa/util/TLSFFreeList.h backends/evm/ssa/StackUtils.cpp backends/evm/ssa/StackUtils.h backends/evm/ssa/io/DotExporterBase.cpp diff --git a/libyul/backends/evm/ssa/util/TLSFFreeList.h b/libyul/backends/evm/ssa/util/TLSFFreeList.h new file mode 100644 index 000000000..fb06aac53 --- /dev/null +++ b/libyul/backends/evm/ssa/util/TLSFFreeList.h @@ -0,0 +1,424 @@ +/* + 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 + +/** + * Two-Level Segregated Fit (TLSF) slot pool optimized for uint32_t. Owns a collection of T and grows it on miss. + * Constant-time `allocate` via bitmap-indexed FL/SL bins, constant-time `deallocate` with immediate coalescing. + * + * Reference: M. Masmano, I. Ripoll, A. Crespo, J. Real, "TLSF: a New Dynamic + * Memory Allocator for Real-Time Systems", ECRTS 2004. + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include + +namespace solidity::yul::ssa::util +{ + +template +concept TombstoneTrait = requires(T const& _t) +{ + { TS::make() } -> std::same_as; + { TS::isTombstone(_t) } -> std::convertible_to; +}; + +template Tombstone> +class TLSFFreeList +{ +public: + using Index = std::uint32_t; + using Length = std::uint32_t; + + TLSFFreeList() + { + for (auto& row: m_binHead) + row.fill(EMPTY); + } + TLSFFreeList(TLSFFreeList const&) = delete; + TLSFFreeList(TLSFFreeList&&) = default; + TLSFFreeList& operator=(TLSFFreeList const&) = delete; + TLSFFreeList& operator=(TLSFFreeList&&) = default; + ~TLSFFreeList() = default; + + /// Returns the start index of a contiguous run of `_length` slots + Index allocate(Length const _length) + { + yulAssert(_length >= 1); + yulAssert(_length <= MAX_ALLOCATE_LENGTH, "length exceeds safe range (would overflow round-up in mappingForRequest)"); + yulAssert(m_data.size() < EMPTY - _length, "container can't grow anymore"); + Index const blockStart = findFreeBlock(_length); + // couldn't find anything, we should grow + if (blockStart == EMPTY) + return growStorage(_length); + + yulAssert(hasHeader(blockStart)); + BlockHeader& block = m_headers[blockStart]; + yulAssert(block.isFree && block.length >= _length); + // unlink formerly free block from its segregated free list. + unlinkFromBin(blockStart); + + // trailing remainder goes back into bins + if (block.length > _length) + split(blockStart, _length); + + // mark block as used + block.isFree = false; + yulAssert(static_cast(blockStart) + _length <= m_data.size()); + for (Length k = 0; k < _length; ++k) + yulAssert(Tombstone::isTombstone(m_data[blockStart + k])); + return blockStart; + } + + /// Releases `[_start, _start + _length)` to the pool, overwriting the slots with `Tombstone::make()` and + /// immediately coalescing with adjacent free physical neighbors + void deallocate(Index const _start, Length const _length) + { + yulAssert(_length >= 1); + yulAssert(static_cast(_start) + _length <= m_data.size()); + yulAssert(hasHeader(_start), "deallocate: no header at start index"); + BlockHeader& self = m_headers[_start]; + yulAssert(!self.isFree, "deallocate: block is already free"); + yulAssert(self.length == _length, "deallocate: length mismatch with recorded block length"); + + for (Length k = 0; k < _length; ++k) + m_data[_start + k] = Tombstone::make(); + + // merge (§7.2 "Coalesce blocks", §8): check both physical neighbors via the boundary-tag links, absorb if free + Index mergedStart = _start; + Length mergedLength = _length; + Index endOfMerged = _start + _length; // address right after the merged block + Index prevPhys = self.prevPhys; + + // Right physical neighbor + if (endOfMerged < m_data.size()) + { + yulAssert(hasHeader(endOfMerged), "deallocate: missing right neighbor"); + BlockHeader const& right = m_headers[endOfMerged]; + if (right.isFree) + { + // coalesce (see §7.2) + Length const rLen = right.length; + unlinkFromBin(endOfMerged); + mergedLength += rLen; + // unset the header + m_headers[endOfMerged] = {}; + endOfMerged += rLen; + } + } + + // Left physical neighbor + if (prevPhys != EMPTY) + { + yulAssert(hasHeader(prevPhys), "deallocate: missing left neighbor"); + BlockHeader const& left = m_headers[prevPhys]; + if (left.isFree) + { + Length const lLen = left.length; + Index const lPrev = left.prevPhys; + unlinkFromBin(prevPhys); + mergedStart = prevPhys; + mergedLength += lLen; + prevPhys = lPrev; + // coalesced into left, remove this header + m_headers[_start] = {}; + } + } + + m_headers[mergedStart] = BlockHeader { + .length = mergedLength, + .prevPhys = prevPhys, + .isFree = true, + .prevFreeInBin = EMPTY, + .nextFreeInBin = EMPTY + }; + + // Update the physical successor's `prevPhys` + if (endOfMerged < m_data.size()) + m_headers[endOfMerged].prevPhys = mergedStart; + else + m_tailBlock = mergedStart; + + // insert free block into corresponding bin (see §7.2 "Insert a free block"). + linkIntoBin(mergedStart, mergedLength); + } + + T& operator[](Index const _i) { return m_data[_i]; } + T const& operator[](Index const _i) const { return m_data[_i]; } + + std::size_t size() const noexcept { return m_data.size(); } + + std::vector const& data() const noexcept { return m_data; } + + bool noFreeIntervals() const noexcept + { + // Bit `fl` of m_flBitmap is set iff some bin in row `fl` is non-empty; + // row 0 covers the small-size linear range, so a single bitmap check + // is sufficient. + return m_flBitmap == 0; + } + +private: + /// Sentinel for an empty/unset index + static constexpr Index EMPTY = std::numeric_limits::max(); + + /// Number of bits for the second level index (SLI) + static constexpr std::uint32_t SL_BITS = 5; + + /// Actual number of bins per FL class (2^SL_BITS) + static constexpr std::uint32_t SL_COUNT = std::uint32_t{1} << SL_BITS; + + /// First level index count. Denotes bins `[2^0, 2^1), ..., [2^(FLI-1), 2^FLI)`. Using 32 for `std::uint32_t` + static constexpr std::uint32_t FL_COUNT = 32; + + /// Considering that + /// fl_index = floor(log2(size)) + /// being the position of the leading 1 in `size`s binary representation, + /// sl_index = (size >> (fl_index - SL_BITS)) - 2^SL_BITS + /// being the index of which of the linear 2^SL_BITS below fl_index the size falls into, + /// this protects against `fl_index - SL_BITS` becoming negative + static constexpr Length SMALL_THRESHOLD = SL_COUNT; + + /// An upper bound on `allocate(_length)`. Above this, the round-up `_length + (subBinSpan - 1)` in + /// `mappingForRequest` can overflow `Length` + static constexpr Length MAX_ALLOCATE_LENGTH = std::numeric_limits::max() - (Length{1} << (FL_COUNT - 1 - SL_BITS)) + Length{1}; + + /// Per-block header describing a contiguous run of slots in `m_data`. Can be allocated or free. They are + /// densely packed. + struct BlockHeader + { + Length length{0}; // length of the run + Index prevPhys{EMPTY}; // begin index of left-hand side neighbor in block linked list used for coalescing + bool isFree{false}; // whether this run of slots is free + // indices to link free blocks of the same length class in a segregated free list + Index prevFreeInBin{EMPTY}; + Index nextFreeInBin{EMPTY}; + }; + + struct BinIdx { std::uint32_t fl; std::uint32_t sl; }; + + /// Rounded-up variant of the paper's mapping function (§7.2). Used on allocate so the chosen bin + /// guarantees `block_size >= _length`. + static BinIdx mappingForRequest(Length const _length) noexcept + { + if (_length < SMALL_THRESHOLD) + return {std::uint32_t{0}, static_cast(_length)}; + // computes `floor(log2(_length))`, the position of the left-most bit that is 1 + auto const fl = static_cast(std::bit_width(_length) - 1); + // width of a second-level bin under fl + // fl_width / SL_COUNT = 2^fl / 2^SL_BITS = 2^(fl - SL_BITS) + Length const subBinSpan = Length{1} << (fl - SL_BITS); + // round up length to the next bin to guarantee that any block in the new bucket satisfies that its size >= _length + Length const rounded = _length + (subBinSpan - 1); + return mappingForExact(rounded); + } + + /// Paper's exact mapping function (§7.2). Picks the `(fl,sl)`-bin whose size range contains _length. + static BinIdx mappingForExact(Length const _length) noexcept + { + if (_length < SMALL_THRESHOLD) + return {std::uint32_t{0}, static_cast(_length)}; + auto const fl = static_cast(std::bit_width(_length) - 1); + std::uint32_t const shift = fl - SL_BITS; + auto const sl = static_cast((_length >> shift) - (Length{1} << SL_BITS)); + yulAssert(fl < FL_COUNT); + yulAssert(sl < SL_COUNT); + return {fl, sl}; + } + + /// `search_suitable_block` from the paper (§7.2 "Get a free block"): + /// 1) compute (f, s) from the requested size + /// 2) try `m_binHead[f][s]`; if non-empty, return its first block + /// 3) otherwise find the next non-empty list in the bitmap structure + Index findFreeBlock(Length const _length) const noexcept + { + // bit mask with the lower _numUnsetBits` being set to zero + static auto constexpr upperBitMask = [](std::uint32_t const _numUnsetBits) + { + if (_numUnsetBits >= 32) + return std::uint32_t{0}; + return ~std::uint32_t{0} << _numUnsetBits; + }; + + BinIdx const target = mappingForRequest(_length); + + // Try the segregated list at (target.fl, target.sl). Mask out bins that correspond to too small lengths. + std::uint32_t const slMaskAtFl = m_slBitmap[target.fl] & upperBitMask(target.sl); + if (slMaskAtFl != 0) + { + // smallest qualifying bin + auto const sl = static_cast(std::countr_zero(slMaskAtFl)); + return m_binHead[target.fl][sl]; + } + // Search the next non-empty FL class via the first-level bitmap + std::uint32_t const flMask = m_flBitmap & upperBitMask(target.fl + 1); + if (flMask == 0) + return EMPTY; + // smallest fl with at least one nonempty sl bin + auto const fl = static_cast(std::countr_zero(flMask)); + std::uint32_t const slMask = m_slBitmap[fl]; + yulAssert(slMask != 0); + // smallest non-empty sl bin + auto const sl = static_cast(std::countr_zero(slMask)); + return m_binHead[fl][sl]; + } + + /// Paper §7.2 "Insert a free block": push onto the head of the segregated double-linked list for the block's + /// exact size class, and mark the bin non-empty in the bitmaps + void linkIntoBin(Index const _start, Length const _length) + { + BlockHeader& self = m_headers[_start]; + self.isFree = true; + BinIdx const bin = mappingForExact(_length); + Index& head = m_binHead[bin.fl][bin.sl]; + Index const oldHead = head; + self.prevFreeInBin = EMPTY; + self.nextFreeInBin = oldHead; + if (oldHead != EMPTY) + m_headers[oldHead].prevFreeInBin = _start; + head = _start; + setBinBitmap(bin, true); + } + + /// Paper §8 `remove(found_block)`: splice the block out of its segregated double-linked list and clear + /// the bin's bitmap bits if it became empty + void unlinkFromBin(Index const _start) + { + BlockHeader& self = m_headers[_start]; + yulAssert(self.isFree); + BinIdx const bin = mappingForExact(self.length); + Index& head = m_binHead[bin.fl][bin.sl]; + Index const prev = self.prevFreeInBin; + Index const next = self.nextFreeInBin; + if (prev != EMPTY) + m_headers[prev].nextFreeInBin = next; + else + { + yulAssert(head == _start); + head = next; + } + if (next != EMPTY) + m_headers[next].prevFreeInBin = prev; + self.prevFreeInBin = EMPTY; + self.nextFreeInBin = EMPTY; + self.isFree = false; + if (head == EMPTY) + setBinBitmap(bin, false); + } + + /// Paper §7.4 "Bitmaps are used to track non-empty lists": each FL class has a 32-bit `m_slBitmap[fl]` indicating + /// which SL sub-bins are non-empty, and a 32-bit `m_flBitmap` indicating which FL classes have any non-empty SL. + void setBinBitmap(BinIdx const _bin, bool const _on) + { + std::uint32_t const slMask = std::uint32_t{1} << _bin.sl; + std::uint32_t const flMask = std::uint32_t{1} << _bin.fl; + if (_on) + { + m_slBitmap[_bin.fl] |= slMask; + m_flBitmap |= flMask; + } + else + { + m_slBitmap[_bin.fl] &= ~slMask; + if (m_slBitmap[_bin.fl] == 0) + m_flBitmap &= ~flMask; + } + } + + /// Paper §8 `split(found_block, size)` followed by `insert(remaining_block)`: chop off the leading `_length` + /// slots for the caller and re-link the trailing remainder as a fresh free block + void split(Index const _start, Length const _length) + { + BlockHeader& self = m_headers[_start]; + yulAssert(self.length > _length); + Length const originalLength = self.length; + Length const remainderLength = originalLength - _length; + Index const remainderStart = _start + _length; + Index const oldEnd = _start + originalLength; + + self.length = _length; + + // `remainderStart` becomes a proper block head + m_headers[remainderStart] = BlockHeader{ + .length = remainderLength, + .prevPhys = _start, + .isFree = false, + .prevFreeInBin = EMPTY, + .nextFreeInBin = EMPTY + }; + if (oldEnd < m_data.size()) + m_headers[oldEnd].prevPhys = remainderStart; + else + m_tailBlock = remainderStart; + + linkIntoBin(remainderStart, remainderLength); + } + + /// Extend storage and append a fresh used block at the end + Index growStorage(Length const _length) + { + auto const start = static_cast(m_data.size()); + m_data.reserve(m_data.size() + _length); + for (Length k = 0; k < _length; ++k) + m_data.emplace_back(Tombstone::make()); + m_headers.resize(m_data.size()); + // link up new tail + m_headers[start] = BlockHeader{ + .length = _length, + .prevPhys = m_tailBlock, + .isFree = false, + .prevFreeInBin = EMPTY, + .nextFreeInBin = EMPTY + }; + m_tailBlock = start; + return start; + } + + /// Yields true if `_s` points to a valid header + bool hasHeader(Index const _s) const noexcept + { + return _s < m_headers.size() && m_headers[_s].length != 0; + } + + /// The actual data + std::vector m_data; + + /// Block headers, parallel to `m_data` (one entry per slot). Contains only valid data for indices pointing to + /// actual block heads + std::vector m_headers; + + /// Tail of the physical-address-ordered block list (`empty` when empty) + Index m_tailBlock{EMPTY}; + + /// Heads of the segregated free lists (paper §7 figure 1) + std::array, FL_COUNT> m_binHead{}; + + /// The bit `fl`is set iff some SL bin under that FL class is non-empty; + std::uint32_t m_flBitmap{0}; + + /// For first level bin `fl`, `m_slBitmap[fl]` bit `sl` is set iff bin `(fl, sl)` is non-empty + std::array m_slBitmap{}; +}; + +} From d18c89fac119bbef97031e0cbc0e22b7c716d4fb Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 4 May 2026 18:13:29 +0200 Subject: [PATCH 1318/1340] SSA CFG: integrate TLSF free list as backing structure for the instruction store Treat a multi-return Call/BuiltinCall (numReturns >= 2) and its trailing Projections as a single allocation/release unit --- libyul/backends/evm/ssa/InstructionStore.h | 237 +++++++++++++----- libyul/backends/evm/ssa/SSACFG.h | 65 ++--- .../evm/ssa/SSACFGLoopNestingForest.h | 2 +- libyul/backends/evm/ssa/SSACFGTypes.cpp | 2 +- 4 files changed, 210 insertions(+), 96 deletions(-) diff --git a/libyul/backends/evm/ssa/InstructionStore.h b/libyul/backends/evm/ssa/InstructionStore.h index 07a43ff6a..dd8b0f4eb 100644 --- a/libyul/backends/evm/ssa/InstructionStore.h +++ b/libyul/backends/evm/ssa/InstructionStore.h @@ -22,14 +22,13 @@ * * Each Inst owns its payload directly via `std::unique_ptr`. Tombstoning * an Inst (or flipping it via `replaceWith*`) resets the unique_ptr, releasing - * the variant and any heap memory it transitively held — most importantly - * `BuiltinCall::literalArguments`. Free `m_insts` slots are tracked in - * `m_freeInsts` and reused by future allocations; literal payloads are - * deduplicated through `m_literalDedup`. + * the variant and any heap memory it transitively held. Slot storage and the free-list bookkeeping + * live together in `m_insts`. Literal payloads are deduplicated through `m_literalDedup`. */ #pragma once +#include #include #include @@ -42,6 +41,7 @@ #include #include #include +#include #include #include @@ -105,10 +105,10 @@ class InstructionStore InstructionStore& operator=(InstructionStore&&) = default; ~InstructionStore() = default; - Inst& inst(InstId _id) { return m_insts.at(_id.value); } - Inst const& inst(InstId _id) const { return m_insts.at(_id.value); } + Inst& inst(InstId _id) { return m_insts[_id.value]; } + Inst const& inst(InstId _id) const { return m_insts[_id.value]; } std::size_t numInsts() const { return m_insts.size(); } - std::vector const& instructions() const { return m_insts; } + std::vector const& instructions() const { return m_insts.data(); } /// Returns the opcode category for a given InstId. InstOpcode kindOf(InstId const _id) const { return inst(_id).opcode; } @@ -136,6 +136,31 @@ class InstructionStore return static_cast(offset); } + /// Counts the trailing Projections immediately following `_producer` in `m_insts` + NumReturnsSizeType numTrailingProjections(InstId const _producer) const + { + auto const& producerInst = inst(_producer); + if (!producerInst.isOperation()) + return 0; + std::size_t count = 0; + while (true) + { + std::size_t const idx = static_cast(_producer.value) + 1u + count; + if (idx >= m_insts.size()) + break; + using IndexType = util::TLSFFreeList::Index; + yulAssert(idx < std::numeric_limits::max()); + auto const& trailing = m_insts[static_cast(idx)]; + if (!trailing.isProjection()) + break; + yulAssert(trailing.inputs.size() == 1); + yulAssert(trailing.inputs.front() == _producer); + ++count; + yulAssert(count <= std::numeric_limits::max()); + } + return static_cast(count); + } + /// Allocates a new Phi Inst defined in `_definingBlock`. Returns the new InstId. InstId appendPhi(BlockId const _definingBlock) { @@ -171,7 +196,9 @@ class InstructionStore return id; } - /// Allocates a new BuiltinCall Inst. Returns the new InstId. + /// Allocates a new single-output BuiltinCall Inst. Returns the new InstId. + /// For multi-output BuiltinCalls, use `appendBuiltinCallWithProjections` so the + /// producer + projections land in a contiguous cluster. InstId appendBuiltinCall( BlockId const _block, BuiltinCall _payload, @@ -187,7 +214,9 @@ class InstructionStore }); } - /// Allocates a new Call Inst. Returns the new InstId. + /// Allocates a new single-output Call Inst. Returns the new InstId. + /// For multi-output Calls, use `appendCallWithProjections` so the producer + + /// projections land in a contiguous cluster. InstId appendCall( BlockId const _block, Call _payload, @@ -195,6 +224,7 @@ class InstructionStore ) { yulAssert(_block.hasValue()); + yulAssert(_payload.numReturns < 2, "Multi-return Call must use appendCallWithProjections"); return appendInst(Inst{ InstOpcode::Call, _block, @@ -203,12 +233,57 @@ class InstructionStore }); } - /// Allocates a new Projection Inst projecting output `_index` of `_producer`. - InstId appendProjection(BlockId const _block, InstId const _producer) + /// Allocates a multi-return BuiltinCall along with its `_numReturns` trailing + /// Projections in a contiguous cluster (length `1 + _numReturns`). Returns the + /// producer's InstId; projections live at `producer.value + 1 .. + _numReturns` + /// and the caller can read them via `SSACFG::projectionsOf`. + InstId appendBuiltinCallWithProjections( + BlockId const _block, + BuiltinCall _payload, + std::vector _inputs, + NumReturnsSizeType const _numReturns + ) { yulAssert(_block.hasValue()); - yulAssert(_producer.hasValue()); - return appendInst(Inst{InstOpcode::Projection, _block, {_producer}, nullptr}); + yulAssert(_numReturns >= 2, "appendBuiltinCallWithProjections requires _numReturns >= 2"); + std::uint32_t const length = static_cast(_numReturns) + 1u; + std::uint32_t const start = reserveRun(length); + InstId const producerId{start}; + m_insts[start] = Inst{ + InstOpcode::BuiltinCall, + _block, + std::move(_inputs), + std::make_unique(std::move(_payload)) + }; + for (NumReturnsSizeType k = 0; k < _numReturns; ++k) + m_insts[start + 1u + k] = Inst{InstOpcode::Projection, _block, {producerId}, nullptr}; + return producerId; + } + + /// Allocates a multi-return Call along with its `_payload.numReturns` trailing + /// Projections in a contiguous cluster. See `appendBuiltinCallWithProjections`. + InstId appendCallWithProjections( + BlockId const _block, + Call _payload, + std::vector _inputs + ) + { + yulAssert(_block.hasValue()); + yulAssert(_payload.numReturns >= 2, "appendCallWithProjections requires _payload.numReturns >= 2"); + yulAssert(_payload.numReturns <= std::numeric_limits::max()); + auto const numReturns = static_cast(_payload.numReturns); + std::uint32_t const length = static_cast(numReturns) + 1u; + std::uint32_t const start = reserveRun(length); + InstId const producerId{start}; + m_insts[start] = Inst{ + InstOpcode::Call, + _block, + std::move(_inputs), + std::make_unique(std::move(_payload)) + }; + for (NumReturnsSizeType k = 0; k < numReturns; ++k) + m_insts[start + 1u + k] = Inst{InstOpcode::Projection, _block, {producerId}, nullptr}; + return producerId; } /// Allocates a new Upsilon Inst targeting `_phi`, feeding `_value` from `_block`. @@ -229,81 +304,109 @@ class InstructionStore yulAssert(_target.hasValue()); yulAssert(_forward.hasValue()); yulAssert(_target != _forward, "Cannot replace value with itself"); - auto& i = inst(_target); + auto& instruction = inst(_target); // every Const InstId is the unique handle for its value, so flipping it to Identity would silently rebind - // every other user of that literal to _forward; almost certainly not what the caller intended - yulAssert(!i.isLiteral(), "replaceWithIdentity must not morph a deduped Const slot"); - i.opcode = InstOpcode::Identity; - i.inputs.assign(1, _forward); - i.payload.reset(); + // every other user of that literal to _forward; almost certainly not what was intended + yulAssert(!instruction.isLiteral(), "replaceWithIdentity must not morph a deduped Const slot"); + yulAssert( + numTrailingProjections(_target) == 0, + "replaceWithIdentity must not morph a multi-return producer slot" + ); + instruction.opcode = InstOpcode::Identity; + instruction.inputs.assign(1, _forward); + instruction.payload.reset(); } /// Flips _target to Const carrying _value. If _value is already deduped to another slot, /// flips _target to Identity forwarding to that slot instead. - void replaceWithConst(InstId _target, u256 _value) + void replaceWithConst(InstId const _target, u256 const& _value) { yulAssert(_target.hasValue()); - auto& i = inst(_target); + auto& instruction = inst(_target); + yulAssert( + numTrailingProjections(_target) == 0, + "replaceWithConst must not morph a multi-return producer slot" + ); // No-op if already this value. - if (i.opcode == InstOpcode::Const && std::get(*i.payload).value == _value) + if (instruction.opcode == InstOpcode::Const && std::get(*instruction.payload).value == _value) return; - dropDedupIfConst(i); + dropDedupIfConst(instruction); if (auto const it = m_literalDedup.find(_value); it != m_literalDedup.end()) { - i.opcode = InstOpcode::Identity; - i.inputs.assign(1, it->second); - i.payload.reset(); + instruction.opcode = InstOpcode::Identity; + instruction.inputs.assign(1, it->second); + instruction.payload.reset(); return; } - i.opcode = InstOpcode::Const; - i.inputs.clear(); - i.payload = std::make_unique(LiteralPayload{_value}); + instruction.opcode = InstOpcode::Const; + instruction.inputs.clear(); + instruction.payload = std::make_unique(LiteralPayload{_value}); m_literalDedup.emplace(std::move(_value), _target); } - /// Flips _target to Nop. Caller must ensure _target produces no observable value - /// (e.g., an Upsilon, or a void Call). - void replaceWithNop(InstId _target) + /// Flips _target to Nop. Caller must ensure _target produces no observable value (e.g., an Upsilon, or a void Call). + void replaceWithNop(InstId const _target) { yulAssert(_target.hasValue()); - auto& i = inst(_target); - dropDedupIfConst(i); - i.opcode = InstOpcode::Nop; - i.inputs.clear(); - i.payload.reset(); + auto& instruction = inst(_target); + yulAssert( + numTrailingProjections(_target) == 0, + "replaceWithNop must not morph a multi-return producer slot" + ); + dropDedupIfConst(instruction); + instruction.opcode = InstOpcode::Nop; + instruction.inputs.clear(); + instruction.payload.reset(); } - /// Tombstones the slot at `_id`, releasing it for reuse by future appendInst calls. + /// Tombstones an Inst, releasing its slot(s) to the free pool. If `_id` is a + /// multi-return producer (i.e. has trailing Projections), the entire cluster + /// is swept and released as one contiguous run. void tombstone(InstId const _id) { yulAssert(_id.hasValue()); - auto& i = inst(_id); - dropDedupIfConst(i); - i.opcode = InstOpcode::Tombstone; - i.inputs.clear(); - i.payload.reset(); - i.block = BlockId{}; - m_freeInsts.push_back(_id.value); - } + auto const& instruction = inst(_id); + if (instruction.isTombstone()) + return; - std::vector const& freeInsts() const { return m_freeInsts; } + yulAssert( + !instruction.isProjection(), + "illegal call of tombstone(_id) on a Projection, tombstone the producer instead" + ); + std::uint32_t const trailingCount = numTrailingProjections(_id); + dropDedupIfConst(instruction); + // tombstone this inst and all trailing projections + m_insts.deallocate(_id.value, trailingCount + 1u); + } private: + /// Allocates a new Projection Inst projecting output of `_producer`. + InstId appendProjection(BlockId const _block, InstId const _producer) + { + yulAssert(_block.hasValue()); + yulAssert(_producer.hasValue()); + return appendInst(Inst{InstOpcode::Projection, _block, {_producer}, nullptr}); + } + + /// Single-slot append: takes a length-1 run from the free pool if available, else + /// tail-extends. InstId appendInst(Inst _inst) { - if (!m_freeInsts.empty()) - { - std::uint32_t const idx = m_freeInsts.back(); - m_freeInsts.pop_back(); - yulAssert(m_insts[idx].opcode == InstOpcode::Tombstone); - m_insts[idx] = std::move(_inst); - return InstId{idx}; - } - // max itself is reserved for the 'empty' inst yulAssert(m_insts.size() < std::numeric_limits::max()); - InstId const id{static_cast(m_insts.size())}; - m_insts.emplace_back(std::move(_inst)); - return id; + std::uint32_t const idx = m_insts.allocate(1); + m_insts[idx] = std::move(_inst); + return InstId{idx}; + } + + /// Reserves a contiguous run of `_length` slots in `m_insts`, returning the start + /// index. The façade applies a smallest-fit policy with split-on-take and + /// tail-extends with Tombstone placeholders on miss; reused cluster slots + /// arrive already in tombstoned state. + std::uint32_t reserveRun(std::uint32_t const _length) + { + yulAssert(_length >= 2, "reserveRun is for clusters; use appendInst for single slots"); + yulAssert(m_insts.size() < std::numeric_limits::max() - _length); + return m_insts.allocate(_length); } /// Asserts that the Inst at `_id` has opcode `Expected`, then returns its payload as `T`. @@ -327,9 +430,19 @@ class InstructionStore m_literalDedup.erase(value); } - std::vector m_insts; - /// Indices of tombstoned slots in `m_insts`, available for reuse by appendInst. - std::vector m_freeInsts; + struct InstTombstone + { + static Inst make() noexcept + { + return Inst{InstOpcode::Tombstone, BlockId{}, {}, nullptr}; + } + static bool isTombstone(Inst const& _i) noexcept + { + return _i.opcode == InstOpcode::Tombstone; + } + }; + + util::TLSFFreeList m_insts; std::map m_literalDedup; }; diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 9457e510c..24dec18d5 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -203,7 +203,7 @@ class SSACFG } /// Allocates a BuiltinCall at `_block` and, for `_numReturns >= 2`, the `_numReturns` matching - /// Projections immediately after it in `m_insts`. + /// Projections immediately after it in `m_insts` as a single contiguous cluster. InstId makeBuiltinCallWithProjections( BlockId const _block, BuiltinCall _payload, @@ -212,15 +212,26 @@ class SSACFG langutil::DebugData::ConstPtr _debugData = {} ) { - InstId const producer = makeBuiltinCall(_block, std::move(_payload), std::move(_inputs), _debugData); - if (_numReturns >= 2) - for (InstructionStore::NumReturnsSizeType i = 0; i < _numReturns; ++i) - makeProjection(_block, producer, _debugData); + if (_numReturns < 2) + return makeBuiltinCall(_block, std::move(_payload), std::move(_inputs), _debugData); + InstId const producer = m_instructions.appendBuiltinCallWithProjections( + _block, std::move(_payload), std::move(_inputs), _numReturns + ); + scheduleInBlock(producer, _block); + if (debugInfo && _debugData) + debugInfo->setInstDebugData(producer, _debugData); + for (InstructionStore::NumReturnsSizeType k = 0; k < _numReturns; ++k) + { + InstId const projId{producer.value + 1u + k}; + scheduleInBlock(projId, _block); + if (debugInfo && _debugData) + debugInfo->setValueDebugData(projId, _debugData); + } return producer; } /// Allocates a user Call at `_block` and, for `_numReturns >= 2`, the `_numReturns` matching - /// Projections immediately after it in `m_insts`. See `makeBuiltinCallWithProjections`. + /// Projections immediately after it in `m_insts` as a single contiguous cluster. InstId makeCallWithProjections( BlockId const _block, Call _payload, @@ -229,10 +240,22 @@ class SSACFG langutil::DebugData::ConstPtr _debugData = {} ) { - InstId const producer = makeCall(_block, std::move(_payload), std::move(_inputs), _debugData); - if (_numReturns >= 2) - for (InstructionStore::NumReturnsSizeType i = 0; i < _numReturns; ++i) - makeProjection(_block, producer, _debugData); + if (_numReturns < 2) + return makeCall(_block, std::move(_payload), std::move(_inputs), _debugData); + yulAssert(_payload.numReturns == _numReturns, "Call payload's numReturns disagrees with caller's _numReturns"); + InstId const producer = m_instructions.appendCallWithProjections( + _block, std::move(_payload), std::move(_inputs) + ); + scheduleInBlock(producer, _block); + if (debugInfo && _debugData) + debugInfo->setInstDebugData(producer, _debugData); + for (InstructionStore::NumReturnsSizeType k = 0; k < _numReturns; ++k) + { + InstId const projId{producer.value + 1u + k}; + scheduleInBlock(projId, _block); + if (debugInfo && _debugData) + debugInfo->setValueDebugData(projId, _debugData); + } return producer; } @@ -438,28 +461,6 @@ class SSACFG return id; } - InstId makeProjection( - BlockId const _block, - InstId const _producer, - langutil::DebugData::ConstPtr _debugData = {} - ) - { - yulAssert( - _block == m_instructions.inst(_producer).block, - fmt::format( - "Projection must live in the producer's block (producer block={}, requested block={})", - m_instructions.inst(_producer).block.value, _block.value - ) - ); - InstId const id = scheduleInBlock( - m_instructions.appendProjection(_block, _producer), - _block - ); - if (debugInfo && _debugData) - debugInfo->setValueDebugData(id, std::move(_debugData)); - return id; - } - /// Shared implementation for the public `forEach*` overloads; works for both /// `SSACFG&` and `SSACFG const&` since `_self.inst(id)` propagates const-ness. template diff --git a/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h index 2ee833335..641945d11 100644 --- a/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h +++ b/libyul/backends/evm/ssa/SSACFGLoopNestingForest.h @@ -54,7 +54,7 @@ class SSACFGLoopNestingForest traversal::ForwardTopologicalSort const& m_sort; SSACFG const& m_cfg; - util::ContiguousDisjointSet m_vertexPartition; + solidity::util::ContiguousDisjointSet m_vertexPartition; std::vector m_loopParents; std::set m_loopNodes; std::set m_loopRootNodes; diff --git a/libyul/backends/evm/ssa/SSACFGTypes.cpp b/libyul/backends/evm/ssa/SSACFGTypes.cpp index 58d306544..27d5cc00b 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.cpp +++ b/libyul/backends/evm/ssa/SSACFGTypes.cpp @@ -45,5 +45,5 @@ std::string InstId::str(SSACFG const& _cfg) const case InstOpcode::Tombstone: yulAssert(false, "Inst has no output value"); } - util::unreachable(); + solidity::util::unreachable(); } From ae448dbbf9914eb568a1894ec31e093a502c2a29 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:53:05 +0200 Subject: [PATCH 1319/1340] SSA CFG: add identity remover transform --- libyul/CMakeLists.txt | 2 + .../evm/ssa/transform/IdentityRemover.cpp | 121 ++++++++++++++++++ .../evm/ssa/transform/IdentityRemover.h | 38 ++++++ 3 files changed, 161 insertions(+) create mode 100644 libyul/backends/evm/ssa/transform/IdentityRemover.cpp create mode 100644 libyul/backends/evm/ssa/transform/IdentityRemover.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 6898fe58c..5d50c9570 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -111,6 +111,8 @@ add_library(yul backends/evm/ssa/io/DotExporterBase.h backends/evm/ssa/io/JSONExporter.cpp backends/evm/ssa/io/JSONExporter.h + backends/evm/ssa/transform/IdentityRemover.cpp + backends/evm/ssa/transform/IdentityRemover.h backends/evm/ssa/transform/TrivialPhiEliminator.cpp backends/evm/ssa/transform/TrivialPhiEliminator.h backends/evm/ssa/transform/UnreachableBlockCleaner.cpp diff --git a/libyul/backends/evm/ssa/transform/IdentityRemover.cpp b/libyul/backends/evm/ssa/transform/IdentityRemover.cpp new file mode 100644 index 000000000..b5104c979 --- /dev/null +++ b/libyul/backends/evm/ssa/transform/IdentityRemover.cpp @@ -0,0 +1,121 @@ +/* + 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 + +#include + +#include + +#include + +using namespace solidity; +using namespace solidity::yul; +using namespace solidity::yul::ssa; + +namespace +{ + +/// Path-compresses Identity chains starting at `_id`. Returns the terminal +/// (non-Identity) target. Self-loops in the chain are forbidden by the +/// replaceWith* contract. +InstId resolve(SSACFG const& _cfg, InstId _id) +{ + while (_id.hasValue() && _cfg.kindOf(_id) == InstOpcode::Identity) + { + auto const& inst = _cfg.inst(_id); + yulAssert(inst.inputs.size() == 1); + yulAssert(inst.inputs[0] != _id, "Identity self-loop"); + _id = inst.inputs[0]; + } + return _id; +} + +void rewriteInputs(SSACFG const& _cfg, std::vector& _inputs) +{ + for (auto& input: _inputs) + input = resolve(_cfg, input); +} + +} + +void transform::removeIdentities(SSACFG& _cfg) +{ + // rewrite every Identity reference reachable from the IR to its terminal target + auto& store = _cfg.instructionStore(); + for (std::uint32_t i = 0; i < store.numInsts(); ++i) + { + InstId const id{i}; + auto& inst = _cfg.inst(id); + switch (inst.opcode) + { + case InstOpcode::Identity: + case InstOpcode::Nop: + case InstOpcode::Tombstone: + case InstOpcode::Const: + case InstOpcode::Phi: + case InstOpcode::FunctionArg: + case InstOpcode::Unreachable: + // Identity / Nop / Tombstone: rewriting their inputs is pointless as they will be tombstoned + // Const / Phi / FunctionArg / Unreachable: can't have identity inputs by construction + break; + case InstOpcode::Upsilon: + { + yulAssert(inst.inputs.size() == 1); + inst.inputs[0] = resolve(_cfg, inst.inputs[0]); + // The Upsilon's targetPhi never becomes Identity: the trivial-phi pass + // turns dead upsilons into Nops before flipping the phi to Identity, so by + // the time we observe a live Upsilon its phi is still a real Phi. + yulAssert(_cfg.kindOf(_cfg.upsilonPhi(id)) == InstOpcode::Phi); + break; + } + case InstOpcode::Projection: + case InstOpcode::BuiltinCall: + case InstOpcode::Call: + rewriteInputs(_cfg, inst.inputs); + break; + } + } + + // Rewrite block-exit references that name InstIds outside `inst.inputs`. + for (BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) + std::visit(solidity::util::GenericVisitor{ + [&](SSACFG::BasicBlock::ConditionalJump& c) { c.condition = resolve(_cfg, c.condition); }, + [&](SSACFG::BasicBlock::FunctionReturn& r) { rewriteInputs(_cfg, r.returnValues); }, + [](SSACFG::BasicBlock::Jump&) {}, + [](SSACFG::BasicBlock::MainExit&) {}, + [](SSACFG::BasicBlock::Terminated&) {} + }, _cfg.block(blockId).exit); + + // Drop Identity / Nop entries from each block and tombstone their slots. No live reference reads through any of + // these slots, so reusing them is safe. + for (BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) + { + auto& block = _cfg.block(blockId); + std::vector toTombstone; + std::erase_if(block.instructions, [&](InstId const _id) { + auto const op = _cfg.kindOf(_id); + if (op == InstOpcode::Identity || op == InstOpcode::Nop) + { + toTombstone.push_back(_id); + return true; + } + return false; + }); + for (InstId const id: toTombstone) + store.tombstone(id); + } +} diff --git a/libyul/backends/evm/ssa/transform/IdentityRemover.h b/libyul/backends/evm/ssa/transform/IdentityRemover.h new file mode 100644 index 000000000..144cbca14 --- /dev/null +++ b/libyul/backends/evm/ssa/transform/IdentityRemover.h @@ -0,0 +1,38 @@ +/* + 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 +/** + * Resolves Identity / Nop placeholder Insts left behind by in-place opcode mutations. + * + * After running: + * - No Inst has an Identity input + * - No Identity or Nop appears in any `BasicBlock::instructions` + */ +#pragma once + +namespace solidity::yul::ssa +{ + +class SSACFG; + +namespace transform +{ +/// Resolves Identity / Nop Insts and tombstones their slots +void removeIdentities(SSACFG& _cfg); +} + +} From 4eea30f2644d262e9d5f8094ae92e017727ca309 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:58:34 +0200 Subject: [PATCH 1320/1340] SSA CFG: rewrite trivial phi eliminator to work with identities and nops --- libyul/CMakeLists.txt | 4 +- libyul/backends/evm/ssa/SSACFG.h | 13 + libyul/backends/evm/ssa/SSACFGBuilder.cpp | 3 + ...yRemover.cpp => IdentityAndNopRemover.cpp} | 25 +- ...ntityRemover.h => IdentityAndNopRemover.h} | 2 +- .../ssa/transform/TrivialPhiEliminator.cpp | 286 ++++-------------- 6 files changed, 88 insertions(+), 245 deletions(-) rename libyul/backends/evm/ssa/transform/{IdentityRemover.cpp => IdentityAndNopRemover.cpp} (80%) rename libyul/backends/evm/ssa/transform/{IdentityRemover.h => IdentityAndNopRemover.h} (95%) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 5d50c9570..f25b261d1 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -111,8 +111,8 @@ add_library(yul backends/evm/ssa/io/DotExporterBase.h backends/evm/ssa/io/JSONExporter.cpp backends/evm/ssa/io/JSONExporter.h - backends/evm/ssa/transform/IdentityRemover.cpp - backends/evm/ssa/transform/IdentityRemover.h + backends/evm/ssa/transform/IdentityAndNopRemover.cpp + backends/evm/ssa/transform/IdentityAndNopRemover.h backends/evm/ssa/transform/TrivialPhiEliminator.cpp backends/evm/ssa/transform/TrivialPhiEliminator.h backends/evm/ssa/transform/UnreachableBlockCleaner.cpp diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 24dec18d5..8e933eb86 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -152,6 +152,19 @@ class SSACFG bool isTombstone(InstId const _id) const { return inst(_id).isTombstone(); } bool isOperation(InstId const _id) const { return inst(_id).isOperation(); } + /// Walks the Identity chain starting at `_id` and returns the terminal (non-Identity) target. + InstId resolveIdentity(InstId _id) const + { + while (_id.hasValue() && kindOf(_id) == InstOpcode::Identity) + { + auto const& i = inst(_id); + yulAssert(i.inputs.size() == 1); + yulAssert(i.inputs[0] != _id, "Identity self-loop"); + _id = i.inputs[0]; + } + return _id; + } + /// Returns the phi targeted by an Upsilon Inst. InstId upsilonPhi(InstId const _id) const { return m_instructions.upsilonPhi(_id); } diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index acc3a6277..dcc767265 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -21,6 +21,7 @@ #include +#include #include #include @@ -89,6 +90,7 @@ std::unique_ptr SSACFGBuilder::build( mainGraph.block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; transform::cleanUnreachableBlocks(mainGraph); transform::eliminateTrivialPhis(mainGraph); + transform::removeIdentitiesAndNops(mainGraph); return controlFlowGraphs; } @@ -141,6 +143,7 @@ void SSACFGBuilder::buildFunctionGraph( builder(Leave{debugDataOf(*_functionDefinition)}); transform::cleanUnreachableBlocks(cfg); transform::eliminateTrivialPhis(cfg); + transform::removeIdentitiesAndNops(cfg); } void SSACFGBuilder::operator()(ExpressionStatement const& _expressionStatement) diff --git a/libyul/backends/evm/ssa/transform/IdentityRemover.cpp b/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp similarity index 80% rename from libyul/backends/evm/ssa/transform/IdentityRemover.cpp rename to libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp index b5104c979..ee61d4b39 100644 --- a/libyul/backends/evm/ssa/transform/IdentityRemover.cpp +++ b/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp @@ -16,7 +16,7 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include +#include #include @@ -29,30 +29,15 @@ using namespace solidity::yul::ssa; namespace { -/// Path-compresses Identity chains starting at `_id`. Returns the terminal -/// (non-Identity) target. Self-loops in the chain are forbidden by the -/// replaceWith* contract. -InstId resolve(SSACFG const& _cfg, InstId _id) -{ - while (_id.hasValue() && _cfg.kindOf(_id) == InstOpcode::Identity) - { - auto const& inst = _cfg.inst(_id); - yulAssert(inst.inputs.size() == 1); - yulAssert(inst.inputs[0] != _id, "Identity self-loop"); - _id = inst.inputs[0]; - } - return _id; -} - void rewriteInputs(SSACFG const& _cfg, std::vector& _inputs) { for (auto& input: _inputs) - input = resolve(_cfg, input); + input = _cfg.resolveIdentity(input); } } -void transform::removeIdentities(SSACFG& _cfg) +void transform::removeIdentitiesAndNops(SSACFG& _cfg) { // rewrite every Identity reference reachable from the IR to its terminal target auto& store = _cfg.instructionStore(); @@ -75,7 +60,7 @@ void transform::removeIdentities(SSACFG& _cfg) case InstOpcode::Upsilon: { yulAssert(inst.inputs.size() == 1); - inst.inputs[0] = resolve(_cfg, inst.inputs[0]); + inst.inputs[0] = _cfg.resolveIdentity(inst.inputs[0]); // The Upsilon's targetPhi never becomes Identity: the trivial-phi pass // turns dead upsilons into Nops before flipping the phi to Identity, so by // the time we observe a live Upsilon its phi is still a real Phi. @@ -93,7 +78,7 @@ void transform::removeIdentities(SSACFG& _cfg) // Rewrite block-exit references that name InstIds outside `inst.inputs`. for (BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) std::visit(solidity::util::GenericVisitor{ - [&](SSACFG::BasicBlock::ConditionalJump& c) { c.condition = resolve(_cfg, c.condition); }, + [&](SSACFG::BasicBlock::ConditionalJump& c) { c.condition = _cfg.resolveIdentity(c.condition); }, [&](SSACFG::BasicBlock::FunctionReturn& r) { rewriteInputs(_cfg, r.returnValues); }, [](SSACFG::BasicBlock::Jump&) {}, [](SSACFG::BasicBlock::MainExit&) {}, diff --git a/libyul/backends/evm/ssa/transform/IdentityRemover.h b/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.h similarity index 95% rename from libyul/backends/evm/ssa/transform/IdentityRemover.h rename to libyul/backends/evm/ssa/transform/IdentityAndNopRemover.h index 144cbca14..e90ef8083 100644 --- a/libyul/backends/evm/ssa/transform/IdentityRemover.h +++ b/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.h @@ -32,7 +32,7 @@ class SSACFG; namespace transform { /// Resolves Identity / Nop Insts and tombstones their slots -void removeIdentities(SSACFG& _cfg); +void removeIdentitiesAndNops(SSACFG& _cfg); } } diff --git a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp index d445168ab..5f093b981 100644 --- a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp +++ b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp @@ -20,259 +20,101 @@ #include -#include - -#include -#include -#include - -#include +#include +#include #include using namespace solidity; using namespace solidity::yul; using namespace solidity::yul::ssa; -namespace -{ - -struct TrivialPhiEliminator +void transform::eliminateTrivialPhis(SSACFG& _cfg) { - SSACFG& cfg; - - // phi_id -> values of upsilons targeting this phi - std::vector> upsilonValuesForPhi; - // phi_id -> blocks containing upsilons targeting this phi - std::vector> phiTargetBlocks; - // phi_id -> phis whose upsilon values reference this phi - std::vector> reversePhiUpsilonValues; - // phi_id -> canonical replacement (default = no substitution) - std::vector substitution; - - explicit TrivialPhiEliminator(SSACFG& _cfg): cfg(_cfg) {} - - void run() - { - cleanUnreachableUpsilons(); - buildIndices(); - substituteDeadPhis(); - - // run elimination repeatedly until convergence - auto substitutionsBeforeEliminateAll = static_cast(ranges::count_if(substitution, [](auto const& s) { return s.hasValue(); })); - auto substitutionsAfterEliminateAll = substitutionsBeforeEliminateAll; - do - { - substitutionsBeforeEliminateAll = substitutionsAfterEliminateAll; - eliminateAll(); - substitutionsAfterEliminateAll = static_cast(ranges::count_if(substitution, [](auto const& s) { return s.hasValue(); })); - } while (substitutionsAfterEliminateAll > substitutionsBeforeEliminateAll); - applySubstitutions(); - } - -private: - void cleanUnreachableUpsilons() - { - for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) + // Drop upsilons whose value is Unreachable (dead control-flow predecessor) + for (BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) + for (InstId const id: _cfg.block(blockId).instructions) { - auto& block = cfg.block(blockId); - std::erase_if(block.instructions, [this](InstId const _id) { - auto const& inst = cfg.inst(_id); - return inst.isUpsilon() && cfg.isUnreachable(inst.inputs.at(0)); - }); + auto const& inst = _cfg.inst(id); + if (inst.isUpsilon() && _cfg.isUnreachable(inst.inputs[0])) + _cfg.replaceWithNop(id); } - } - void buildIndices() + // Build per-phi indices + std::map> upsilonsTargeting; + std::map> phisReferencing; + std::vector worklist; + for (std::uint32_t i = 0; i < _cfg.instructionStore().numInsts(); ++i) { - for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) + InstId const id{i}; + auto const& inst = _cfg.inst(id); + if (inst.isPhi()) + worklist.push_back(id); + else if (inst.isUpsilon()) { - cfg.forEachUpsilon(cfg.block(blockId), [&](InstId const instId, SSACFG::Inst const& inst) { - InstId const phi = cfg.upsilonPhi(instId); - InstId const value = inst.inputs.at(0); - auto const phiIdx = phi.value; - if (phiIdx >= upsilonValuesForPhi.size()) - { - upsilonValuesForPhi.resize(phiIdx + 1); - phiTargetBlocks.resize(phiIdx + 1); - } - if (phiIdx >= reversePhiUpsilonValues.size()) - reversePhiUpsilonValues.resize(phiIdx + 1); - upsilonValuesForPhi[phiIdx].push_back(value); - phiTargetBlocks[phiIdx].push_back(blockId); - if (cfg.isPhi(value)) - { - auto const valIdx = value.value; - if (valIdx >= reversePhiUpsilonValues.size()) - reversePhiUpsilonValues.resize(valIdx + 1); - reversePhiUpsilonValues[valIdx].push_back(phi); - } - }); + InstId const phi = _cfg.upsilonPhi(id); + upsilonsTargeting[phi].push_back(id); + InstId const value = inst.inputs[0]; + if (_cfg.kindOf(value) == InstOpcode::Phi) + phisReferencing[value].push_back(phi); } - substitution.resize(std::max(upsilonValuesForPhi.size(), size_t{1})); - } - - /// Phis that have no upsilons targeting them are dead — either in unreachable blocks - /// or orphaned from cycle-breaking. - /// Replace references to them with unreachableValue in the upsilon value index so they don't block triviality - /// detection. - void substituteDeadPhis() - { - auto const unreachable = cfg.unreachableValue(); - for (auto& upsilonValues: upsilonValuesForPhi) - for (auto& val: upsilonValues) - if (cfg.isPhi(val)) - { - auto const idx = val.value; - bool const hasUpsilons = idx < upsilonValuesForPhi.size() && !upsilonValuesForPhi[idx].empty(); - if (!hasUpsilons) - val = unreachable; - } } - void eliminateAll() - { - for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) - { - // Snapshot the phi InstIds because tryRemove mutates block.instructions. - std::vector phis; - cfg.forEachPhi(cfg.block(blockId), [&](InstId const instId, SSACFG::Inst const&) { - phis.push_back(instId); - }); - for (auto const phi: phis) - tryRemove(phi); - } - } + // All orphan phis can share a single Unreachable sentinel, only allocate lazily if needed + InstId orphanUnreachable; - void tryRemove(InstId _phi) + while (!worklist.empty()) { - auto const phiIdx = _phi.value; + InstId const phi = worklist.back(); + worklist.pop_back(); + if (_cfg.kindOf(phi) != InstOpcode::Phi) + continue; - // early exit if this phi was already processed - if (phiIdx < substitution.size() && substitution[phiIdx].hasValue()) - return; - - // check triviality and canonicalize arguments to account for already-substituted phis; - // skip self-references and unreachable values InstId same; - if (phiIdx < upsilonValuesForPhi.size()) - for (auto const arg: upsilonValuesForPhi[phiIdx]) + bool nontrivial = false; + auto const it = upsilonsTargeting.find(phi); + if (it != upsilonsTargeting.end()) + for (InstId const ups: it->second) { - auto const resolved = canonicalize(arg); - if (resolved == same || resolved == _phi || cfg.isUnreachable(resolved)) + if (_cfg.kindOf(ups) == InstOpcode::Nop) continue; - if (same.hasValue()) - return; // non-trivial - same = resolved; - } - - if (!same.hasValue()) - // phi has only self-references (unreachable cycle), or no upsilons at all - same = cfg.unreachableValue(); - - // remove the phi from its defining block - { - auto& block = cfg.block(cfg.inst(_phi).block); - yulAssert(cfg.isPhi(_phi)); - std::erase(block.instructions, _phi); - } - - // record the substitution - if (phiIdx >= substitution.size()) - substitution.resize(phiIdx + 1); - substitution[phiIdx] = same; - - // update upsilon.value fields and `upsilonValuesForPhi` for all phis whose upsilons reference `_phi` as a value - std::vector cascades; - if (phiIdx < reversePhiUpsilonValues.size()) - { - for (auto const targetPhi: reversePhiUpsilonValues[phiIdx]) - { - // update upsilonValuesForPhi[targetPhi]: _phi with same - auto& vals = upsilonValuesForPhi[targetPhi.value]; - ranges::replace(vals, _phi, same); - if (targetPhi.value < phiTargetBlocks.size()) - for (auto const blockId: phiTargetBlocks[targetPhi.value]) - cfg.forEachUpsilon(cfg.block(blockId), [&](InstId const instId, SSACFG::Inst& inst) { - if (cfg.upsilonPhi(instId) == targetPhi && inst.inputs.at(0) == _phi) - inst.inputs[0] = same; - }); - // maintain reverse index - if (cfg.isPhi(same)) + InstId const value = _cfg.resolveIdentity(_cfg.inst(ups).inputs[0]); + if (value == phi || _cfg.isUnreachable(value)) + continue; + if (same.hasValue() && value != same) { - if (same.value >= reversePhiUpsilonValues.size()) - reversePhiUpsilonValues.resize(same.value + 1); - reversePhiUpsilonValues[same.value].push_back(targetPhi); + nontrivial = true; + break; } - cascades.push_back(targetPhi); + same = value; } - reversePhiUpsilonValues[phiIdx].clear(); - } - - // erase all upsilons targeting the removed phi. - if (phiIdx < phiTargetBlocks.size()) + if (nontrivial) + continue; + if (!same.hasValue()) { - for (auto const blockId: phiTargetBlocks[phiIdx]) - { - auto& block = cfg.block(blockId); - std::erase_if(block.instructions, [this, _phi](InstId _id) { - auto const& ins = cfg.inst(_id); - return ins.isUpsilon() && cfg.upsilonPhi(_id) == _phi; - }); - } - phiTargetBlocks[phiIdx].clear(); + // Phi has no live, non-self upsilons — it's an orphan in dead code. + if (!orphanUnreachable.hasValue()) + orphanUnreachable = _cfg.unreachableValue(); + same = orphanUnreachable; } - for (auto const cascadingPhi: cascades) - tryRemove(cascadingPhi); - } - - InstId canonicalize(InstId const _v) - { - auto const idx = _v.value; - if (idx >= substitution.size()) - return _v; - auto& sub = substitution[idx]; - if (!sub.hasValue()) - return _v; - // path compression - sub = canonicalize(sub); - return sub; - } - - void applySubstitutions() - { - if (!ranges::any_of(substitution, [](InstId const& _sub) { return _sub.hasValue(); })) - return; + _cfg.replaceWithIdentity(phi, same); + if (it != upsilonsTargeting.end()) + for (InstId const ups: it->second) + if (_cfg.kindOf(ups) == InstOpcode::Upsilon) + _cfg.replaceWithNop(ups); - for (SSACFG::BlockId blockId{0}; blockId.value < cfg.numBlocks(); ++blockId.value) + // Re-queue dependents and forward `phi`'s reverse-dep entries onto `same`. If `same` is itself a Phi that + // gets eliminated later, those dependents must be reevaluated + auto const depsIt = phisReferencing.find(phi); + if (depsIt != phisReferencing.end()) { - auto& block = cfg.block(blockId); - for (InstId const instId: block.instructions) + for (InstId const dep: depsIt->second) + worklist.push_back(dep); + if (_cfg.kindOf(same) == InstOpcode::Phi) { - auto& inst = cfg.inst(instId); - if (inst.isUpsilon()) - inst.inputs[0] = canonicalize(inst.inputs[0]); - else if (inst.isOperation()) - for (auto& input: inst.inputs) - input = canonicalize(input); + auto& sameDeps = phisReferencing[same]; + sameDeps.insert(sameDeps.end(), depsIt->second.begin(), depsIt->second.end()); } - std::visit(solidity::util::GenericVisitor{ - [&](SSACFG::BasicBlock::FunctionReturn& r) { - for (auto& v: r.returnValues) - v = canonicalize(v); - }, - [&](SSACFG::BasicBlock::ConditionalJump& c) { c.condition = canonicalize(c.condition); }, - [](SSACFG::BasicBlock::Jump&) {}, - [](SSACFG::BasicBlock::MainExit&) {}, - [](SSACFG::BasicBlock::Terminated&) {} - }, block.exit); } } -}; - -} - -void transform::eliminateTrivialPhis(SSACFG& _cfg) -{ - TrivialPhiEliminator(_cfg).run(); } From c45d441abbec088043d0d4c6eb6e145ef561cecc Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 30 Apr 2026 10:49:07 +0200 Subject: [PATCH 1321/1340] SSA CFG: free up insts in unreachable blocks --- .../backends/evm/ssa/transform/UnreachableBlockCleaner.cpp | 5 +++++ libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp index c5835f313..83da235b3 100644 --- a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp +++ b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp @@ -47,12 +47,17 @@ void transform::cleanUnreachableBlocks(SSACFG& _cfg) }); } + auto& store = _cfg.instructionStore(); for (SSACFG::BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) { auto& block = _cfg.block(blockId); if (reachable[blockId.value]) std::erase_if(block.entries, [&](auto const& entry) { return !reachable[entry.value]; }); else + { + for (InstId const id: block.instructions) + store.tombstone(id); block = {}; + } } } diff --git a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h index f3ef1592c..ea414ac9e 100644 --- a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h +++ b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.h @@ -17,7 +17,6 @@ // SPDX-License-Identifier: GPL-3.0 /** * Removes unreachable blocks from an SSA CFG and cleans up entry lists referencing them. - * Note that this invalidates ValueIds and InstIds pointing into the (unreachable) blocks. */ #pragma once From ea0a8c137ff832bf2ffabe3a44464e5a8976c473 Mon Sep 17 00:00:00 2001 From: Tavian Dev Date: Thu, 2 Apr 2026 21:46:40 +0000 Subject: [PATCH 1322/1340] Preserve failAfter directive in isoltest ASTJSON reformatting When isoltest updates test expectations for ASTJSON tests, it calls printSource() to rewrite the .sol input file. The function was not outputting the failAfter directive that was parsed and stored in m_expectedFailAfter, causing the directive to be silently dropped. Fixes #14093 --- test/libsolidity/ASTJSONTest.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/libsolidity/ASTJSONTest.cpp b/test/libsolidity/ASTJSONTest.cpp index daf4a9ea4..feb4f443b 100644 --- a/test/libsolidity/ASTJSONTest.cpp +++ b/test/libsolidity/ASTJSONTest.cpp @@ -295,6 +295,9 @@ void ASTJSONTest::printSource(std::ostream& _stream, std::string const& _linePre printPrefixed(_stream, source.second, _linePrefix); _stream << std::endl; } + + if (m_expectedFailAfter.has_value()) + printPrefixed(_stream, "// failAfter: " + compilerStateToString(m_expectedFailAfter.value()) + "\n", _linePrefix); } void ASTJSONTest::printUpdatedExpectations(std::ostream&, std::string const&) const From ee6668e9899345ce20c97c31ace0a9dfa7e87418 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Thu, 7 May 2026 13:27:35 +0200 Subject: [PATCH 1323/1340] SSA CFG: add shared function registry across nested builders --- libyul/backends/evm/ssa/SSACFGBuilder.cpp | 43 ++++++++--------------- libyul/backends/evm/ssa/SSACFGBuilder.h | 23 ++++++++---- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index dcc767265..06d758ad7 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -36,7 +36,6 @@ #include #include -#include #include #include #include @@ -55,14 +54,16 @@ SSACFGBuilder::SSACFGBuilder( AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, EVMDialect const& _dialect, - bool _generateDebugInfo + bool _generateDebugInfo, + FunctionRegistry& _functionRegistry ): m_controlFlow(_controlFlow), m_graph(_graph), m_info(_analysisInfo), m_sideEffects(_sideEffects), m_dialect(_dialect), - m_generateDebugInfo(_generateDebugInfo) + m_generateDebugInfo(_generateDebugInfo), + m_functionRegistry(_functionRegistry) { } @@ -81,7 +82,8 @@ std::unique_ptr SSACFGBuilder::build( _generateDebugInfo ? std::make_unique() : nullptr )); SSACFG& mainGraph = *controlFlowGraphs->functionGraphs.back(); - SSACFGBuilder builder(*controlFlowGraphs, mainGraph, _analysisInfo, sideEffects, _dialect, _generateDebugInfo); + FunctionRegistry functionRegistry; + SSACFGBuilder builder(*controlFlowGraphs, mainGraph, _analysisInfo, sideEffects, _dialect, _generateDebugInfo, functionRegistry); builder.m_currentBlock = mainGraph.makeBlock(debugDataOf(_block)); builder.sealBlock(builder.m_currentBlock); builder(_block); @@ -102,9 +104,9 @@ void SSACFGBuilder::buildFunctionGraph( { // The graph slot and the FunctionGraphID have already been allocated in // `registerFunctionDefinition`; this call builds the body into that slot. - auto const graphIt = m_functionScopeToID.find(_function); - yulAssert(graphIt != m_functionScopeToID.end(), "Function graph must be registered before building."); - auto& cfg = *m_controlFlow.functionGraphs[graphIt->second]; + auto const regIt = m_functionRegistry.find(_function); + yulAssert(regIt != m_functionRegistry.end(), "Function graph must be registered before building."); + auto& cfg = *m_controlFlow.functionGraphs[regIt->second.id]; yulAssert(m_info.scopes.at(&_functionDefinition->body), ""); Scope* virtualFunctionScope = m_info.scopes.at(m_info.virtualBlocks.at(_functionDefinition).get()).get(); @@ -127,10 +129,8 @@ void SSACFGBuilder::buildFunctionGraph( | ranges::views::transform([](auto const& _binding) { return std::get<1>(_binding); }) | ranges::to; - SSACFGBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_generateDebugInfo); + SSACFGBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_generateDebugInfo, m_functionRegistry); builder.m_currentBlock = cfg.entry; - builder.m_functionDefinitions = m_functionDefinitions; - builder.m_functionScopeToID = m_functionScopeToID; builder.m_currentReturnVars = returnVars; for (auto&& [var, varId]: argumentBindings) builder.currentDef(var, cfg.entry) = varId; @@ -374,7 +374,6 @@ void SSACFGBuilder::registerFunctionDefinition(FunctionDefinition const& _functi yulAssert(m_scope, ""); yulAssert(m_scope->identifiers.count(_functionDefinition.name), ""); auto& function = std::get(m_scope->identifiers.at(_functionDefinition.name)); - m_functionDefinitions.emplace_back(&function, &_functionDefinition); // Allocate the graph slot up front so sibling functions (and mutually-recursive pairs) can // reference this function by its FunctionGraphID when their bodies are built later. @@ -386,7 +385,7 @@ void SSACFGBuilder::registerFunctionDefinition(FunctionDefinition const& _functi auto& cfg = *m_controlFlow.functionGraphs.back(); cfg.name = function.name.str(); cfg.numReturns = _functionDefinition.returnVariables.size(); - m_functionScopeToID[&function] = graphID; + m_functionRegistry[&function] = {graphID, &_functionDefinition}; } void SSACFGBuilder::operator()(Block const& _block) @@ -481,17 +480,15 @@ InstId SSACFGBuilder::visitFunctionCall(FunctionCall const& _call) { YulName const& functionName = _identifier.name; Scope::Function const& function = lookupFunction(functionName); - auto const* definition = findFunctionDefinition(&function); - yulAssert(definition); - canContinue = m_sideEffects.functionSideEffects().at(definition).canContinue; - auto const calleeIt = m_functionScopeToID.find(&function); - yulAssert(calleeIt != m_functionScopeToID.end(), "Called function has no registered graph id."); + auto const calleeIt = m_functionRegistry.find(&function); + yulAssert(calleeIt != m_functionRegistry.end(), "Called function has no registered graph id."); + canContinue = m_sideEffects.functionSideEffects().at(calleeIt->second.definition).canContinue; std::vector inputs; for (auto const& arg: _call.arguments | ranges::views::reverse) inputs.emplace_back(std::visit(*this, arg)); return m_graph.makeCallWithProjections( m_currentBlock, - SSACFG::Call{calleeIt->second, canContinue, function.numReturns}, + SSACFG::Call{calleeIt->second.id, canContinue, function.numReturns}, std::move(inputs), static_cast(function.numReturns), debugDataOf(_call) @@ -640,13 +637,3 @@ void SSACFGBuilder::jump( m_currentBlock = _target; } -FunctionDefinition const* SSACFGBuilder::findFunctionDefinition(Scope::Function const* _function) const -{ - auto it = ranges::find_if( - m_functionDefinitions, - [&_function](auto const& _entry) { return std::get<0>(_entry) == _function; } - ); - if (it != m_functionDefinitions.end()) - return std::get<1>(*it); - return nullptr; -} diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index a5fc326b8..ffa9265d9 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -45,7 +45,6 @@ #include -#include #include #include @@ -54,13 +53,25 @@ namespace solidity::yul::ssa class SSACFGBuilder { +public: + struct FunctionRegistration + { + FunctionGraphID id; + FunctionDefinition const* definition; + }; + /// Lookup table for user-defined functions encountered during build, shared across + /// all SSACFGBuilder instances (one per function body) so they don't copy it. + using FunctionRegistry = std::unordered_map; + +private: SSACFGBuilder( ControlFlowGraphs& _controlFlow, SSACFG& _graph, AsmAnalysisInfo const& _analysisInfo, ControlFlowSideEffectsCollector const& _sideEffects, EVMDialect const& _dialect, - bool _generateDebugInfo + bool _generateDebugInfo, + FunctionRegistry& _functionRegistry ); public: SSACFGBuilder(SSACFGBuilder const&) = delete; @@ -113,9 +124,9 @@ class SSACFGBuilder ControlFlowSideEffectsCollector const& m_sideEffects; EVMDialect const& m_dialect; bool const m_generateDebugInfo; - std::vector> m_functionDefinitions; - /// Translation map from Yul-AST function scopes to their corresponding FunctionGraphIDs - std::map m_functionScopeToID; + /// Shared function lookup, populated as `registerFunctionDefinition` is called. + /// Owned by the topmost `build()` invocation; nested builders just reference it. + FunctionRegistry& m_functionRegistry; /// Return variable scopes of the function currently being built std::vector> m_currentReturnVars; SSACFG::BlockId m_currentBlock; @@ -172,8 +183,6 @@ class SSACFGBuilder langutil::DebugData::ConstPtr _debugData, SSACFG::BlockId _target ); - - FunctionDefinition const* findFunctionDefinition(Scope::Function const* _function) const; }; } From 49e295d3169eb90b82eae74af127190cd5ff96db Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Wed, 29 Apr 2026 22:32:55 -0300 Subject: [PATCH 1324/1340] Fix SMT Encoder treatment of constant operands of unary operations --- libsolidity/formal/SMTEncoder.cpp | 7 ++++--- .../constant_evaluation_unary_minus_bmc.sol | 13 +++++++++++++ .../constant_evaluation_unary_minus_chc.sol | 13 +++++++++++++ ...onstant_evaluation_unary_operations_compound.sol | 10 ++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_minus_bmc.sol create mode 100644 test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_minus_chc.sol create mode 100644 test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_operations_compound.sol diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index df902fd86..c8e0cdc92 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -451,9 +451,10 @@ void SMTEncoder::endVisit(TupleExpression const& _tuple) void SMTEncoder::endVisit(UnaryOperation const& _op) { - /// We need to shortcut here due to potentially unknown - /// rational number sizes. - if (_op.annotation().type->category() == Type::Category::RationalNumber) + /// For constant expressions, we need to shortcut here + /// due to potentially unknown rational number sizes that + /// can appear in intermediary operations, e.g., ~(2**256 - 1). + if (isConstant(_op)) return; if (TokenTraits::isBitOp(_op.getOperator()) && !*_op.annotation().userDefinedFunction) diff --git a/test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_minus_bmc.sol b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_minus_bmc.sol new file mode 100644 index 000000000..546b26b33 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_minus_bmc.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; +contract C { + int256 constant signedConstant = 42; + + function testComptime() public pure { + assert(-signedConstant == -42); + } +} +// ==== +// SMTEngine: bmc +// ---- +// Info 6002: BMC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_minus_chc.sol b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_minus_chc.sol new file mode 100644 index 000000000..b6fb71c0d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_minus_chc.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; +contract C { + int256 constant signedConstant = 42; + + function testComptime() public pure { + assert(-signedConstant == -42); + } +} +// ==== +// SMTEngine: chc +// ---- +// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. diff --git a/test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_operations_compound.sol b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_operations_compound.sol new file mode 100644 index 000000000..f4d33e813 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/constant_evaluation_unary_operations_compound.sol @@ -0,0 +1,10 @@ +contract C { + int256 constant CONST = 42; + function test() public pure { + assert(~-CONST == ~-42); + } +} +// ==== +// SMTEngine: chc +// ---- +// Info 1391: CHC: 1 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. From 78ab5f857a37fb1e72e30dd657afb186e463b809 Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 7 May 2026 15:21:48 +0200 Subject: [PATCH 1325/1340] Pin node to exact versions instead of lts to fix failing jobs --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8f2dd5611..9e10e6ba8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -863,7 +863,7 @@ defaults: name: t_native_test_ext_ens project: ens binary_type: native - image: cimg/node:lts + image: cimg/node:22.13 - job_native_compile_ext_trident: &job_native_compile_ext_trident <<: *requires_b_ubu_static @@ -914,7 +914,7 @@ defaults: name: t_native_test_ext_uniswap project: uniswap binary_type: native - image: cimg/node:lts + image: cimg/node:22.13 resource_class: large # Tests run out of memory on a smaller machine - job_native_test_ext_prb_math: &job_native_test_ext_prb_math @@ -922,7 +922,7 @@ defaults: name: t_native_test_ext_prb_math project: prb-math binary_type: native - image: cimg/rust:1.74.0-node + image: cimg/node:22.13 resource_class: large # Tests run out of memory on a smaller machine - job_native_test_ext_elementfi: &job_native_test_ext_elementfi @@ -938,7 +938,7 @@ defaults: name: t_native_test_ext_brink project: brink binary_type: native - image: cimg/node:lts + image: cimg/node:22.13 - job_native_compile_ext_chainlink: &job_native_compile_ext_chainlink <<: *requires_b_ubu_static From 4bb9689ba7728a051f1799c9179ded5dc29b081b Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Thu, 7 May 2026 16:00:43 +0200 Subject: [PATCH 1326/1340] Pin pnpm to v9 --- .circleci/config.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9e10e6ba8..3f13cf11d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1585,7 +1585,8 @@ jobs: at: /tmp/workspace - run: name: Ensure pnpm is installed if npm is present - command: sudo npm install -g pnpm + # Pin to pnpm v9 as v10 introduces additional safe guards and causes failures + command: sudo npm install -g pnpm@9 - run: name: Retrieve EDR latest release tag command: | @@ -1659,7 +1660,8 @@ jobs: name: Ensure pnpm is installed if npm is present command: | if command -v npm &> /dev/null; then - sudo npm install -g pnpm + # Pin to pnpm v9 as v10 introduces additional safe guards and causes failures + sudo npm install -g pnpm@9 fi - when: condition: << parameters.python2 >> From 7da228deda8a8eb9292dded91e0b7b4adecb4931 Mon Sep 17 00:00:00 2001 From: blishko Date: Thu, 7 May 2026 17:08:21 +0200 Subject: [PATCH 1327/1340] SSA-CFG: Fix stack adjustments for codegen on conditional jump When running codegen on a block which ends in a conditional jump, we save the stack before we continue with zero branch and then we restore it when come back and continue with non-zero branch. Notifying the assebly about the restored stack size is part of resetting the state and needs to happen before we attempt any stack shuffling. `prepareBlockExitStack` might shuffle the stack and so assembly notification must happen before that. --- libyul/backends/evm/ssa/CodeTransform.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index 7f997d680..de2d3a8ea 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -359,14 +359,13 @@ void CodeTransform::operator()(SSACFG::BlockId const& _currentBlock, SSACFG::Bas } { yulAssert(m_stackLayout[_conditionalJump.nonZero]); + m_assembly.setStackHeight(static_cast(m_stack.size())); // transform stack to a state in which we can jump to the nonZero branch prepareBlockExitStack( m_stackLayout[_conditionalJump.nonZero]->stackIn, PhiInverse(m_cfg, _currentBlock, _conditionalJump.nonZero) ); assertLayoutCompatibility(m_stack.data(), m_stackLayout[_conditionalJump.nonZero]->stackIn); - - m_assembly.setStackHeight(static_cast(m_stack.size())); if (!m_blockIsTransformed[_conditionalJump.nonZero.value]) (*this)(_conditionalJump.nonZero); } From 7c0b91c2f6342f4c598c3bca59d3ec61c38eb6ea Mon Sep 17 00:00:00 2001 From: blishko Date: Thu, 7 May 2026 17:40:35 +0200 Subject: [PATCH 1328/1340] SSA-CFG: Set up basic optimization pipeline --- libyul/CMakeLists.txt | 2 + .../ssa/transform/OptimizationPipeline.cpp | 37 +++++++++++++++++++ .../evm/ssa/transform/OptimizationPipeline.h | 30 +++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 libyul/backends/evm/ssa/transform/OptimizationPipeline.cpp create mode 100644 libyul/backends/evm/ssa/transform/OptimizationPipeline.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index f25b261d1..f3789f140 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -113,6 +113,8 @@ add_library(yul backends/evm/ssa/io/JSONExporter.h backends/evm/ssa/transform/IdentityAndNopRemover.cpp backends/evm/ssa/transform/IdentityAndNopRemover.h + backends/evm/ssa/transform/OptimizationPipeline.cpp + backends/evm/ssa/transform/OptimizationPipeline.h backends/evm/ssa/transform/TrivialPhiEliminator.cpp backends/evm/ssa/transform/TrivialPhiEliminator.h backends/evm/ssa/transform/UnreachableBlockCleaner.cpp diff --git a/libyul/backends/evm/ssa/transform/OptimizationPipeline.cpp b/libyul/backends/evm/ssa/transform/OptimizationPipeline.cpp new file mode 100644 index 000000000..7485833e1 --- /dev/null +++ b/libyul/backends/evm/ssa/transform/OptimizationPipeline.cpp @@ -0,0 +1,37 @@ +/* + 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 + +#include + +#include +#include +#include + +#include + +using namespace solidity::yul::ssa; + +void transform::optimize(ControlFlowGraphs& _cfgs) +{ + for (auto& cfg: _cfgs.functionGraphs) + { + transform::cleanUnreachableBlocks(*cfg); + transform::eliminateTrivialPhis(*cfg); + transform::removeIdentitiesAndNops(*cfg); + } +} diff --git a/libyul/backends/evm/ssa/transform/OptimizationPipeline.h b/libyul/backends/evm/ssa/transform/OptimizationPipeline.h new file mode 100644 index 000000000..81a3d117c --- /dev/null +++ b/libyul/backends/evm/ssa/transform/OptimizationPipeline.h @@ -0,0 +1,30 @@ +/* + 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 + +#pragma once + +namespace solidity::yul::ssa +{ +struct ControlFlowGraphs; + +namespace transform +{ +void optimize(ControlFlowGraphs&); +} + +} From d2207e0444a35b58f9e04e034006be074077068d Mon Sep 17 00:00:00 2001 From: blishko Date: Thu, 7 May 2026 17:43:24 +0200 Subject: [PATCH 1329/1340] SSA-CFG: Separate building and optimizing phase --- libyul/YulStack.cpp | 2 ++ libyul/backends/evm/EVMObjectCompiler.cpp | 3 +++ libyul/backends/evm/ssa/SSACFGBuilder.cpp | 10 ---------- test/libyul/ssa/ControlFlowGraphTest.cpp | 3 +++ test/libyul/ssa/StackLayoutGeneratorTest.cpp | 3 +++ 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index faa563596..0633836d1 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -402,6 +403,7 @@ Json YulStack::cfgJson() const _object.code()->root(), keepLiteralAssignments ); + ssa::transform::optimize(*controlFlowGraphs); std::unique_ptr liveness = std::make_unique(*controlFlowGraphs); return ssa::io::json::exportControlFlow(*controlFlowGraphs, liveness.get()); }; diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index 4f857a229..3d5562b51 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -25,6 +25,8 @@ #include #include +#include + #include #include #include @@ -95,6 +97,7 @@ void EVMObjectCompiler::run(Object const& _object, bool _optimize, bool _viaSSAC _object.code()->root(), false ); + ssa::transform::optimize(*controlFlowGraphs); ssa::ControlFlowGraphsLiveness const liveness(*controlFlowGraphs); ssa::CodeTransform::run( m_assembly, diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 06d758ad7..268742ca6 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -21,10 +21,6 @@ #include -#include -#include -#include - #include #include @@ -90,9 +86,6 @@ std::unique_ptr SSACFGBuilder::build( if (!builder.blockInfo(builder.m_currentBlock).sealed) builder.sealBlock(builder.m_currentBlock); mainGraph.block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{}; - transform::cleanUnreachableBlocks(mainGraph); - transform::eliminateTrivialPhis(mainGraph); - transform::removeIdentitiesAndNops(mainGraph); return controlFlowGraphs; } @@ -141,9 +134,6 @@ void SSACFGBuilder::buildFunctionGraph( cfg.exits.insert(builder.m_currentBlock); // Artificial explicit function exit (`leave`) at the end of the body. builder(Leave{debugDataOf(*_functionDefinition)}); - transform::cleanUnreachableBlocks(cfg); - transform::eliminateTrivialPhis(cfg); - transform::removeIdentitiesAndNops(cfg); } void SSACFGBuilder::operator()(ExpressionStatement const& _expressionStatement) diff --git a/test/libyul/ssa/ControlFlowGraphTest.cpp b/test/libyul/ssa/ControlFlowGraphTest.cpp index 1e3e66919..8e921b219 100644 --- a/test/libyul/ssa/ControlFlowGraphTest.cpp +++ b/test/libyul/ssa/ControlFlowGraphTest.cpp @@ -23,6 +23,8 @@ #include +#include + #include #include #include @@ -79,6 +81,7 @@ TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::strin yulStack.parserResult()->code()->root(), true ); + yul::ssa::transform::optimize(*controlFlowGraphs); yul::ssa::ControlFlowGraphsLiveness liveness(*controlFlowGraphs); m_obtainedResult = controlFlowGraphs->toDot(&liveness); diff --git a/test/libyul/ssa/StackLayoutGeneratorTest.cpp b/test/libyul/ssa/StackLayoutGeneratorTest.cpp index 21836ee2a..98e7c9955 100644 --- a/test/libyul/ssa/StackLayoutGeneratorTest.cpp +++ b/test/libyul/ssa/StackLayoutGeneratorTest.cpp @@ -26,6 +26,8 @@ #include #include +#include + #include #include @@ -154,6 +156,7 @@ frontend::test::TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& object.code()->root(), false ); + yul::ssa::transform::optimize(*controlFlowGraphs); // insert separator if (!m_obtainedResult.empty()) m_obtainedResult += SUBOBJECT_GRAPH_SEPARATOR; From 0766c57087dfb5781a2d16a833f6011095a6e1fd Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Mon, 11 May 2026 16:03:43 +0200 Subject: [PATCH 1330/1340] SSA CFG: lift the memoryguard value out of the instruction argument into the parent ControlFlowGraphs structure --- libyul/backends/evm/ssa/CodeTransform.cpp | 13 ++++++++-- libyul/backends/evm/ssa/ControlFlowGraphs.h | 9 ++++++- libyul/backends/evm/ssa/InstructionStore.h | 18 +++++++++++-- libyul/backends/evm/ssa/SSACFG.cpp | 17 ++++++++++-- libyul/backends/evm/ssa/SSACFG.h | 12 +++++++++ libyul/backends/evm/ssa/SSACFGBuilder.cpp | 26 ++++++++++++++++++- libyul/backends/evm/ssa/SSACFGBuilder.h | 1 + libyul/backends/evm/ssa/SSACFGTypes.cpp | 1 + libyul/backends/evm/ssa/SSACFGTypes.h | 1 + libyul/backends/evm/ssa/io/JSONExporter.cpp | 18 ++++++++++--- .../ssa/transform/IdentityAndNopRemover.cpp | 3 ++- .../standard_yul_cfg_json_export/output.json | 24 +++++------------ .../strict_asm_yul_cfg_json_export/output | 10 +++---- test/cmdlineTests/yul_cfg_json_export/output | 24 +++++------------ .../ssa/controlFlowGraph/memoryguard.yul | 24 +++++++++++++++++ 15 files changed, 146 insertions(+), 55 deletions(-) create mode 100644 test/libyul/ssa/controlFlowGraph/memoryguard.yul diff --git a/libyul/backends/evm/ssa/CodeTransform.cpp b/libyul/backends/evm/ssa/CodeTransform.cpp index de2d3a8ea..f885cf6d3 100644 --- a/libyul/backends/evm/ssa/CodeTransform.cpp +++ b/libyul/backends/evm/ssa/CodeTransform.cpp @@ -302,6 +302,12 @@ void CodeTransform::operator()(InstId _instId, StackData const& _operationInputL builtin.generateCode(transient, m_assembly, m_builtinContext); break; } + case InstOpcode::MemoryGuard: + { + yulAssert(m_controlFlow.memoryGuard.has_value()); + m_assembly.appendConstant(*m_controlFlow.memoryGuard); + break; + } default: yulAssert(false); } @@ -414,16 +420,19 @@ void CodeTransform::operator()(SSACFG::BlockId const& _blockId, SSACFG::BasicBlo break; } yulAssert(lastOpInstId.hasValue(), "Terminated block must have at least one operation."); - if (m_cfg.inst(lastOpInstId).opcode == InstOpcode::BuiltinCall) + auto const lastOpcode = m_cfg.inst(lastOpInstId).opcode; + if (lastOpcode == InstOpcode::BuiltinCall) yulAssert( m_cfg.evmDialect.builtin(m_cfg.builtinPayload(lastOpInstId).builtin).controlFlowSideEffects.terminatesOrReverts(), "Last operation of Terminated block must terminate or revert." ); - else + else if (lastOpcode == InstOpcode::Call) yulAssert( !m_cfg.callPayload(lastOpInstId).canContinue, "Last operation of Terminated block must be a non-continuable call." ); + else + yulAssert(false, "Last operation of Terminated block must be a non-continuable Call or terminating BuiltinCall."); // To be sure just emit another INVALID - should be removed by optimizer. m_assembly.appendInstruction(evmasm::Instruction::INVALID); } diff --git a/libyul/backends/evm/ssa/ControlFlowGraphs.h b/libyul/backends/evm/ssa/ControlFlowGraphs.h index 0b0c273f5..789dd7077 100644 --- a/libyul/backends/evm/ssa/ControlFlowGraphs.h +++ b/libyul/backends/evm/ssa/ControlFlowGraphs.h @@ -21,7 +21,9 @@ #include #include -#include +#include + +#include namespace solidity::yul::ssa { @@ -69,6 +71,11 @@ struct ControlFlowGraphs return output.str(); } + /// Memoryguard boundary for this subobject. + /// - empty: no `memoryguard(N)` call appears in the source + /// - set: every MemoryGuard Inst lowers to a `pushN ` of this constant + std::optional memoryGuard{}; + std::vector> functionGraphs{}; }; diff --git a/libyul/backends/evm/ssa/InstructionStore.h b/libyul/backends/evm/ssa/InstructionStore.h index dd8b0f4eb..5d8719f6d 100644 --- a/libyul/backends/evm/ssa/InstructionStore.h +++ b/libyul/backends/evm/ssa/InstructionStore.h @@ -90,11 +90,15 @@ class InstructionStore constexpr bool isProjection() const noexcept { return opcode == InstOpcode::Projection; } constexpr bool isIdentity() const noexcept { return opcode == InstOpcode::Identity; } constexpr bool isNop() const noexcept { return opcode == InstOpcode::Nop; } + constexpr bool isMemoryGuard() const noexcept { return opcode == InstOpcode::MemoryGuard; } constexpr bool isTombstone() const noexcept { return opcode == InstOpcode::Tombstone; } - /// Operation = a Call or BuiltinCall. + /// Operation = a Call, BuiltinCall, or MemoryGuard constexpr bool isOperation() const noexcept { - return opcode == InstOpcode::Call || opcode == InstOpcode::BuiltinCall; + return + opcode == InstOpcode::Call || + opcode == InstOpcode::BuiltinCall || + opcode == InstOpcode::MemoryGuard; } }; @@ -173,6 +177,13 @@ class InstructionStore return appendInst(Inst{InstOpcode::FunctionArg, _entryBlock, {}, nullptr}); } + /// Allocates a new MemoryGuard Inst defined in `_block`. The boundary value lives in `ControlFlowGraphs::memoryGuard`. + InstId appendMemoryGuard(BlockId const _block) + { + yulAssert(_block.hasValue()); + return appendInst(Inst{InstOpcode::MemoryGuard, _block, {}, nullptr}); + } + /// Allocates a new Unreachable Inst. Not pinned to any block (see class comment). InstId appendUnreachable() { @@ -308,6 +319,7 @@ class InstructionStore // every Const InstId is the unique handle for its value, so flipping it to Identity would silently rebind // every other user of that literal to _forward; almost certainly not what was intended yulAssert(!instruction.isLiteral(), "replaceWithIdentity must not morph a deduped Const slot"); + yulAssert(!instruction.isMemoryGuard(), "replaceWithIdentity must not morph a MemoryGuard slot"); yulAssert( numTrailingProjections(_target) == 0, "replaceWithIdentity must not morph a multi-return producer slot" @@ -323,6 +335,7 @@ class InstructionStore { yulAssert(_target.hasValue()); auto& instruction = inst(_target); + yulAssert(!instruction.isMemoryGuard(), "replaceWithConst must not morph a MemoryGuard slot"); yulAssert( numTrailingProjections(_target) == 0, "replaceWithConst must not morph a multi-return producer slot" @@ -349,6 +362,7 @@ class InstructionStore { yulAssert(_target.hasValue()); auto& instruction = inst(_target); + yulAssert(!instruction.isMemoryGuard(), "replaceWithNop must not morph a MemoryGuard slot"); yulAssert( numTrailingProjections(_target) == 0, "replaceWithNop must not morph a multi-return producer slot" diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 35389a9d8..9590e5c6c 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -108,13 +108,26 @@ class SSACFGDotExporter: public io::DotExporterBase }); m_cfg.forEachOperation(block, [&](InstId const instId, SSACFG::Inst const& inst) { std::string label; - if (inst.opcode == InstOpcode::Call) + switch (inst.opcode) + { + case InstOpcode::Call: { auto const graphID = m_cfg.callPayload(instId).graphID; label = m_controlFlow ? m_controlFlow->functionGraph(graphID)->name : fmt::format("func{}", graphID); + break; } - else + case InstOpcode::BuiltinCall: label = m_cfg.evmDialect.builtin(m_cfg.builtinPayload(instId).builtin).name; + break; + case InstOpcode::MemoryGuard: + if (m_controlFlow && m_controlFlow->memoryGuard) + label = fmt::format("memoryguard<{}>", toCompactHexWithPrefix(*m_controlFlow->memoryGuard)); + else + label = "memoryguard"; + break; + default: + yulAssert(false); + } if (m_cfg.numReturnsOf(instId) >= 1) _out << fmt::format("{} := ", valueToString(instId)); _out << fmt::format( diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 8e933eb86..d88b77b3e 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -149,6 +149,7 @@ class SSACFG bool isProjection(InstId const _id) const { return inst(_id).isProjection(); } bool isIdentity(InstId const _id) const { return inst(_id).isIdentity(); } bool isNop(InstId const _id) const { return inst(_id).isNop(); } + bool isMemoryGuard(InstId const _id) const { return inst(_id).isMemoryGuard(); } bool isTombstone(InstId const _id) const { return inst(_id).isTombstone(); } bool isOperation(InstId const _id) const { return inst(_id).isOperation(); } @@ -195,6 +196,15 @@ class SSACFG return id; } + /// Allocates a MemoryGuard Inst at `_block`. The boundary value lives in `ControlFlowGraphs::memoryGuard`. + InstId makeMemoryGuard(BlockId const _block, langutil::DebugData::ConstPtr _debugData = {}) + { + InstId const id = scheduleInBlock(m_instructions.appendMemoryGuard(_block), _block); + if (debugInfo && _debugData) + debugInfo->setValueDebugData(id, std::move(_debugData)); + return id; + } + InstId unreachableValue() { return m_instructions.appendUnreachable(); @@ -382,6 +392,8 @@ class SSACFG return callPayload(_op).numReturns; case InstOpcode::BuiltinCall: return evmDialect.builtin(builtinPayload(_op).builtin).numReturns; + case InstOpcode::MemoryGuard: + return 1; default: yulAssert(false, fmt::format("numReturnsOf called on non-operation inst {}", _op)); } diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.cpp b/libyul/backends/evm/ssa/SSACFGBuilder.cpp index 268742ca6..f055f6e0e 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.cpp +++ b/libyul/backends/evm/ssa/SSACFGBuilder.cpp @@ -59,7 +59,12 @@ SSACFGBuilder::SSACFGBuilder( m_sideEffects(_sideEffects), m_dialect(_dialect), m_generateDebugInfo(_generateDebugInfo), - m_functionRegistry(_functionRegistry) + m_functionRegistry(_functionRegistry), + m_memoryGuardHandle([&] { + auto const memoryGuardHandle = m_dialect.findBuiltin("memoryguard"); + yulAssert(memoryGuardHandle.has_value(), "We only support EVM dialects that contain memoryguard"); + return *memoryGuardHandle; + }()) { } @@ -444,6 +449,25 @@ InstId SSACFGBuilder::visitFunctionCall(FunctionCall const& _call) InstId const id = std::visit(solidity::util::GenericVisitor{ [&](BuiltinName const& _builtinName) -> InstId { + // memoryguard(N) is represented as a dedicated MemoryGuard Inst; the boundary value lives in the + // corresponding ControlFlowGraphs instance + if (_builtinName.handle == m_memoryGuardHandle) + { + yulAssert(_call.arguments.size() == 1); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal && literal->kind == LiteralKind::Number); + u256 const value = literal->value.value(); + if (m_controlFlow.memoryGuard) + yulAssert( + *m_controlFlow.memoryGuard == value, + "memoryguard: inconsistent literal across subobject" + ); + else + m_controlFlow.memoryGuard = value; + canContinue = m_dialect.builtin(m_memoryGuardHandle).controlFlowSideEffects.canContinue; + return m_graph.makeMemoryGuard(m_currentBlock, debugDataOf(_call)); + } + auto const& builtin = m_dialect.builtin(_builtinName.handle); yulAssert(_call.arguments.size() == builtin.numParameters); std::vector literalArguments; diff --git a/libyul/backends/evm/ssa/SSACFGBuilder.h b/libyul/backends/evm/ssa/SSACFGBuilder.h index ffa9265d9..b55575d27 100644 --- a/libyul/backends/evm/ssa/SSACFGBuilder.h +++ b/libyul/backends/evm/ssa/SSACFGBuilder.h @@ -127,6 +127,7 @@ class SSACFGBuilder /// Shared function lookup, populated as `registerFunctionDefinition` is called. /// Owned by the topmost `build()` invocation; nested builders just reference it. FunctionRegistry& m_functionRegistry; + BuiltinHandle const m_memoryGuardHandle; /// Return variable scopes of the function currently being built std::vector> m_currentReturnVars; SSACFG::BlockId m_currentBlock; diff --git a/libyul/backends/evm/ssa/SSACFGTypes.cpp b/libyul/backends/evm/ssa/SSACFGTypes.cpp index 27d5cc00b..ddccb5695 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.cpp +++ b/libyul/backends/evm/ssa/SSACFGTypes.cpp @@ -35,6 +35,7 @@ std::string InstId::str(SSACFG const& _cfg) const case InstOpcode::FunctionArg: case InstOpcode::Projection: case InstOpcode::Identity: + case InstOpcode::MemoryGuard: return fmt::format("v{}", value); case InstOpcode::Phi: return fmt::format("phi{}", value); diff --git a/libyul/backends/evm/ssa/SSACFGTypes.h b/libyul/backends/evm/ssa/SSACFGTypes.h index 8a0c6414a..d0afa9ba9 100644 --- a/libyul/backends/evm/ssa/SSACFGTypes.h +++ b/libyul/backends/evm/ssa/SSACFGTypes.h @@ -65,6 +65,7 @@ enum class InstOpcode : std::uint8_t Projection, // projection: single InstId input (multi-output producer) plus immediate index Identity, // forwards its single input, resolved away by transform::removeIdentities, Nop, // used to turn a void-typed Inst (eg an upsilon whose phi was eliminated) into a deletable placeholder + MemoryGuard, // emits the subobject's memoryguard boundary; value is held on the enclosing ControlFlowGraphs Tombstone, // marks a free slot in InstructionStore::m_insts, must never appear in block instructions }; diff --git a/libyul/backends/evm/ssa/io/JSONExporter.cpp b/libyul/backends/evm/ssa/io/JSONExporter.cpp index ade3dd4a5..7ff2a8e1e 100644 --- a/libyul/backends/evm/ssa/io/JSONExporter.cpp +++ b/libyul/backends/evm/ssa/io/JSONExporter.cpp @@ -48,15 +48,17 @@ Json toJson(Json& _ret, SSACFG const& _cfg, InstId const _instId, ControlFlowGra { auto const& inst = _cfg.inst(_instId); Json opJson = Json::object(); - if (inst.opcode == InstOpcode::Call) + switch (inst.opcode) + { + case InstOpcode::Call: { auto const& callPayload = _cfg.callPayload(_instId); _ret["type"] = "FunctionCall"; opJson["op"] = _controlFlow.functionGraph(callPayload.graphID)->name; + break; } - else + case InstOpcode::BuiltinCall: { - yulAssert(inst.opcode == InstOpcode::BuiltinCall); auto const& builtinPayload = _cfg.builtinPayload(_instId); _ret["type"] = "BuiltinCall"; Json builtinArgsJson = Json::array(); @@ -67,6 +69,14 @@ Json toJson(Json& _ret, SSACFG const& _cfg, InstId const _instId, ControlFlowGra opJson["literalArgs"] = builtinArgsJson; opJson["op"] = _cfg.evmDialect.builtin(builtinPayload.builtin).name; + break; + } + case InstOpcode::MemoryGuard: + _ret["type"] = "MemoryGuard"; + opJson["op"] = "memoryguard"; + break; + default: + yulAssert(false); } opJson["in"] = toJson(_cfg, inst.inputs); @@ -190,6 +200,8 @@ Json io::json::exportControlFlow(ControlFlowGraphs const& _controlFlow, ControlF yulAssert(&_liveness->controlFlowGraphs.get() == &_controlFlow); Json yulObjectJson = Json::object(); + if (_controlFlow.memoryGuard) + yulObjectJson["memoryGuard"] = toCompactHexWithPrefix(*_controlFlow.memoryGuard); yulObjectJson["blocks"] = exportBlock( *_controlFlow.mainGraph(), SSACFG::BlockId{0}, diff --git a/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp b/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp index ee61d4b39..5a804970f 100644 --- a/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp +++ b/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp @@ -54,8 +54,9 @@ void transform::removeIdentitiesAndNops(SSACFG& _cfg) case InstOpcode::Phi: case InstOpcode::FunctionArg: case InstOpcode::Unreachable: + case InstOpcode::MemoryGuard: // Identity / Nop / Tombstone: rewriting their inputs is pointless as they will be tombstoned - // Const / Phi / FunctionArg / Unreachable: can't have identity inputs by construction + // Const / Phi / FunctionArg / Unreachable / MemoryGuard: can't have identity inputs by construction break; case InstOpcode::Upsilon: { diff --git a/test/cmdlineTests/standard_yul_cfg_json_export/output.json b/test/cmdlineTests/standard_yul_cfg_json_export/output.json index fcbc710f1..1142cdf73 100644 --- a/test/cmdlineTests/standard_yul_cfg_json_export/output.json +++ b/test/cmdlineTests/standard_yul_cfg_json_export/output.json @@ -18,9 +18,6 @@ "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -125,6 +122,7 @@ } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": { "C_19_deployed": { "blocks": [ @@ -141,9 +139,6 @@ "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -440,6 +435,7 @@ } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": {} }, "type": "subObject" @@ -465,9 +461,6 @@ "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -572,6 +565,7 @@ } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": { "D_38_deployed": { "blocks": [ @@ -588,9 +582,6 @@ "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -1675,6 +1666,7 @@ } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": { "C_19": { "blocks": [ @@ -1691,9 +1683,6 @@ "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -1798,6 +1787,7 @@ } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": { "C_19_deployed": { "blocks": [ @@ -1814,9 +1804,6 @@ "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -2113,6 +2100,7 @@ } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": {} }, "type": "subObject" diff --git a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output index bc8d8327d..39ae2f1fa 100644 --- a/test/cmdlineTests/strict_asm_yul_cfg_json_export/output +++ b/test/cmdlineTests/strict_asm_yul_cfg_json_export/output @@ -18,9 +18,6 @@ Yul Control Flow Graph: "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -125,6 +122,7 @@ Yul Control Flow Graph: } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": { "C_19_deployed": { "blocks": [ @@ -141,9 +139,6 @@ Yul Control Flow Graph: "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -439,7 +434,8 @@ Yul Control Flow Graph: "type": "BuiltinCall" } ], - "functions": {} + "functions": {}, + "memoryGuard": "0x80" }, "type": "subObject" } diff --git a/test/cmdlineTests/yul_cfg_json_export/output b/test/cmdlineTests/yul_cfg_json_export/output index 023da3678..3cc42ee64 100644 --- a/test/cmdlineTests/yul_cfg_json_export/output +++ b/test/cmdlineTests/yul_cfg_json_export/output @@ -17,9 +17,6 @@ Yul Control Flow Graph: "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -124,6 +121,7 @@ Yul Control Flow Graph: } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": { "C_19_deployed": { "blocks": [ @@ -140,9 +138,6 @@ Yul Control Flow Graph: "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -439,6 +434,7 @@ Yul Control Flow Graph: } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": {} }, "type": "subObject" @@ -465,9 +461,6 @@ Yul Control Flow Graph: "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -572,6 +565,7 @@ Yul Control Flow Graph: } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": { "D_38_deployed": { "blocks": [ @@ -588,9 +582,6 @@ Yul Control Flow Graph: "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -1675,6 +1666,7 @@ Yul Control Flow Graph: } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": { "C_19": { "blocks": [ @@ -1691,9 +1683,6 @@ Yul Control Flow Graph: "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -1798,6 +1787,7 @@ Yul Control Flow Graph: } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": { "C_19_deployed": { "blocks": [ @@ -1814,9 +1804,6 @@ Yul Control Flow Graph: "instructions": [ { "in": [], - "literalArgs": [ - "0x80" - ], "op": "memoryguard", "out": [ "v0" @@ -2113,6 +2100,7 @@ Yul Control Flow Graph: } ], "functions": {}, + "memoryGuard": "0x80", "subObjects": {} }, "type": "subObject" diff --git a/test/libyul/ssa/controlFlowGraph/memoryguard.yul b/test/libyul/ssa/controlFlowGraph/memoryguard.yul new file mode 100644 index 000000000..e7dac6076 --- /dev/null +++ b/test/libyul/ssa/controlFlowGraph/memoryguard.yul @@ -0,0 +1,24 @@ +{ + let p := memoryguard(0x80) + mstore(p, 42) + let q := memoryguard(0x80) + sstore(q, 1) +} +// ---- +// digraph SSACFG { +// nodesep=0.7; +// graph[fontname="DejaVu Sans"] +// node[shape=box,fontname="DejaVu Sans"]; +// +// Entry [label="Entry"]; +// Entry -> Block0_0; +// Block0_0 [fillcolor="#FF746C", style=filled, label="\ +// Block 0; (0, max 0)\nLiveIn: \l\ +// LiveOut: \l\nUsed: \l\nv0 := memoryguard<0x80>()\l\ +// mstore(0x2a, v0)\l\ +// v3 := memoryguard<0x80>()\l\ +// sstore(0x01, v3)\l\ +// "]; +// Block0_0Exit [label="MainExit"]; +// Block0_0 -> Block0_0Exit; +// } From 88fb1a1791dbb6cd631c2f117ec3febab037b37d Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 12 May 2026 10:18:40 +0200 Subject: [PATCH 1331/1340] SSA CFG Stack layout generator: Determine optimal target (not just size) --- libyul/backends/evm/ssa/StackLayoutGenerator.cpp | 15 ++++----------- libyul/backends/evm/ssa/StackUtils.cpp | 11 ++++++----- libyul/backends/evm/ssa/StackUtils.h | 5 ++++- .../ssa/stackLayoutGenerator/nested_for.yul | 6 +++--- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 44307f41c..fee1615ad 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -258,19 +258,14 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) StackSlotLiveness const opLiveOutSlots = toStackSlotLiveness(m_cfg, opLiveOutWithoutOutputs); { - std::size_t const targetSize = findOptimalTargetSize( + StackData const target = findOptimalTarget( stack.data(), requiredStackTop, opLiveOutSlots, junkCanBeAdded, m_hasFunctionReturnLabel ); - auto const shuffleResult = StackShuffler::shuffle( - stack, - requiredStackTop, - opLiveOutSlots, - targetSize - ); + auto const shuffleResult = StackShuffler::shuffle(stack, target); yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); } @@ -298,16 +293,14 @@ void StackLayoutGenerator::visitBlock(SSACFG::BlockId const& _blockId) { auto const condition = Slot::makeValue(m_cfg, _cJump.condition); StackSlotLiveness const blockLiveOutSlots = toStackSlotLiveness(m_cfg, blockLiveOut); - auto const targetSize = findOptimalTargetSize( + StackData const target = findOptimalTarget( stack.data(), {condition}, blockLiveOutSlots, false, m_hasFunctionReturnLabel ); - auto const shuffleResult = StackShuffler::shuffle( - stack, {condition}, blockLiveOutSlots, targetSize - ); + auto const shuffleResult = StackShuffler::shuffle(stack, target); yulAssert(shuffleResult.status == StackShufflerResult::Status::Admissible); } diff --git a/libyul/backends/evm/ssa/StackUtils.cpp b/libyul/backends/evm/ssa/StackUtils.cpp index 1844bada7..1edcf2ead 100644 --- a/libyul/backends/evm/ssa/StackUtils.cpp +++ b/libyul/backends/evm/ssa/StackUtils.cpp @@ -80,7 +80,7 @@ StackData solidity::yul::ssa::stackPreImage(SSACFG const& _cfg, StackData _stack return _stack; } -std::size_t solidity::yul::ssa::findOptimalTargetSize +StackData solidity::yul::ssa::findOptimalTarget ( StackData const& _stackData, StackData const& _targetArgs, @@ -141,7 +141,7 @@ std::size_t solidity::yul::ssa::findOptimalTargetSize }; std::size_t bestCost = evaluateCost(startSize); - auto result = startSize; + StackData bestData = data; // On non-reverting paths, only search downward from pivot to avoid growing the stack. // On reverting paths, search in both directions since stack cleanup doesn't matter. @@ -157,7 +157,7 @@ std::size_t solidity::yul::ssa::findOptimalTargetSize if (cost <= bestCost) { bestCost = cost; - result = size; + bestData = data; consecutiveIncreases = 0; } else if (++consecutiveIncreases >= stopAfter) @@ -174,14 +174,15 @@ std::size_t solidity::yul::ssa::findOptimalTargetSize if (cost < bestCost) { bestCost = cost; - result = size; + bestData = data; consecutiveIncreases = 0; } else if (++consecutiveIncreases >= stopAfter) break; } } - return result; + + return bestData; } CallSites solidity::yul::ssa::gatherCallSites(SSACFG const& _cfg) diff --git a/libyul/backends/evm/ssa/StackUtils.h b/libyul/backends/evm/ssa/StackUtils.h index b4d5c66a6..f77192838 100644 --- a/libyul/backends/evm/ssa/StackUtils.h +++ b/libyul/backends/evm/ssa/StackUtils.h @@ -63,7 +63,10 @@ struct GasAccumulatingCallbacks /// Transform stack data by replacing all its phi variables with their respective preimages. StackData stackPreImage(SSACFG const& _cfg, StackData _stack, PhiInverse const& _phiInverse); -std::size_t findOptimalTargetSize( +/// Searches for the cheapest target stack size for shuffling _stackData towards +/// (_targetArgs on top, _targetLiveOut anywhere in the tail), then realizes that size and +/// returns the resolved post-shuffle StackData +StackData findOptimalTarget( StackData const& _stackData, StackData const& _targetArgs, StackSlotLiveness const& _targetLiveOut, diff --git a/test/libyul/ssa/stackLayoutGenerator/nested_for.yul b/test/libyul/ssa/stackLayoutGenerator/nested_for.yul index 5220d2cef..bd9970292 100644 --- a/test/libyul/ssa/stackLayoutGenerator/nested_for.yul +++ b/test/libyul/ssa/stackLayoutGenerator/nested_for.yul @@ -107,11 +107,11 @@ // Block0_3 [label="\ // IN: [phi2, phi8, JUNK]\l\ // \l\ -// [JUNK, phi8, lit10, phi2]\l\ +// [phi2, phi8, lit10, phi2]\l\ // add\l\ -// [JUNK, phi8, v19]\l\ +// [phi2, phi8, v19]\l\ // \l\ -// OUT: [JUNK, phi8, v19]\l\ +// OUT: [phi2, phi8, v19]\l\ // "]; // Block0_3 -> Block0_3Exit [arrowhead=none]; // Block0_3Exit [label="Jump" shape=oval]; From 0fe919c750afc185cfa1eca48b142c33c3b76dea Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 12 May 2026 13:42:58 +0200 Subject: [PATCH 1332/1340] SSA CFG: Make basic blocks optional and add a free list to them --- libyul/backends/evm/ssa/LivenessAnalysis.cpp | 4 +- libyul/backends/evm/ssa/SSACFG.cpp | 4 ++ libyul/backends/evm/ssa/SSACFG.h | 55 ++++++++++++++++--- .../backends/evm/ssa/StackLayoutGenerator.cpp | 4 ++ .../ssa/transform/IdentityAndNopRemover.cpp | 6 ++ .../ssa/transform/TrivialPhiEliminator.cpp | 4 ++ .../ssa/transform/UnreachableBlockCleaner.cpp | 14 +++-- 7 files changed, 76 insertions(+), 15 deletions(-) diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp index 2eba9b19e..5bfa81b4c 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -154,7 +154,7 @@ void LivenessAnalysis::runLoopTreeDfs(SSACFG::BlockId::ValueType const _loopHead m_liveOuts[_loopHeader].maxUnion(liveLoop); // for each blockId \in children(loopHeader) for (SSACFG::BlockId::ValueType blockIdValue = 0u; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) - if (m_loopNestingForest.loopParents()[blockIdValue] == _loopHeader) + if (m_cfg.hasBlock(SSACFG::BlockId{blockIdValue}) && m_loopNestingForest.loopParents()[blockIdValue] == _loopHeader) { // propagate loop liveness information down to the loop header's children m_liveIns[blockIdValue].maxUnion(liveLoop); @@ -169,6 +169,8 @@ void LivenessAnalysis::fillOperationsLiveOut() { for (SSACFG::BlockId blockId{0}; blockId.value < m_cfg.numBlocks(); ++blockId.value) { + if (!m_cfg.hasBlock(blockId)) + continue; auto const& block = m_cfg.block(blockId); auto const opCount = static_cast(ranges::count_if( block.instructions, diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 9590e5c6c..1323ca076 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -46,12 +46,16 @@ std::string formatPhi(SSACFG const& _cfg, InstId _phiId) // Collect all upsilons targeting _phiId from the whole CFG. std::vector formattedUpsilons; for (BlockId::ValueType bv = 0; bv < _cfg.numBlocks(); ++bv) + { + if (!_cfg.hasBlock(BlockId{bv})) + continue; _cfg.forEachUpsilon(_cfg.block(BlockId{bv}), [&](InstId const instId, SSACFG::Inst const& inst) { if (_cfg.upsilonPhi(instId) == _phiId) formattedUpsilons.push_back( fmt::format("Block {} => {}", bv, inst.inputs.at(0).str(_cfg)) ); }); + } if (!formattedUpsilons.empty()) return fmt::format("φ(\\l\\\n\t{}\\l\\\n)", fmt::join(formattedUpsilons, ",\\l\\\n\t")); return "φ()"; diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index d88b77b3e..81c63bb9d 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -32,6 +32,7 @@ #include +#include #include #include #include @@ -40,6 +41,7 @@ #include #include +#include #include #include @@ -118,17 +120,52 @@ class SSACFG BlockId makeBlock(langutil::DebugData::ConstPtr _debugData) { - // max itself is reserved for the 'empty' block - yulAssert(m_blocks.size() < std::numeric_limits::max()); - BlockId const blockId{static_cast(m_blocks.size())}; - m_blocks.emplace_back(BasicBlock{{}, {}, BasicBlock::Terminated{}}); + BlockId blockId; + if (!m_freeBlocks.empty()) + { + blockId = m_freeBlocks.back(); + yulAssert(blockId.value < m_freeBlocks.size()); + std::optional& block = m_blocks[blockId.value]; + yulAssert(!block.has_value()); + m_freeBlocks.pop_back(); + block.emplace(BasicBlock{{}, {}, BasicBlock::Terminated{}}); + } + else + { + yulAssert(m_blocks.size() < std::numeric_limits::max()); + blockId = BlockId{static_cast(m_blocks.size())}; + m_blocks.emplace_back(BasicBlock{{}, {}, BasicBlock::Terminated{}}); + } if (debugInfo) debugInfo->setBlockDebugData(blockId, std::move(_debugData)); return blockId; } - BasicBlock& block(BlockId _id) { return m_blocks.at(_id.value); } - BasicBlock const& block(BlockId _id) const { return m_blocks.at(_id.value); } + BasicBlock& block(BlockId _id) + { + auto& slot = m_blocks.at(_id.value); + yulAssert(slot.has_value(), fmt::format("Access of dead block #{}", _id.value)); + return *slot; + } + BasicBlock const& block(BlockId _id) const + { + auto const& slot = m_blocks.at(_id.value); + yulAssert(slot.has_value(), fmt::format("Access of dead block #{}", _id.value)); + return *slot; + } size_t numBlocks() const { return m_blocks.size(); } + bool hasBlock(BlockId const _id) const { return _id.value < m_blocks.size() && m_blocks[_id.value].has_value(); } + void resetBlock(BlockId const _id) + { + yulAssert(_id.value < m_blocks.size()); + auto& block = m_blocks[_id.value]; + yulAssert(block.has_value(), "double reset"); + yulAssert( + ranges::all_of(block->instructions, [this](InstId const _instId) { return isTombstone(_instId); }), + "can only reset blocks that have no live instructions left" + ); + block.reset(); + m_freeBlocks.push_back(_id); + } InstructionStore& instructionStore() { return m_instructions; } InstructionStore const& instructionStore() const { return m_instructions; } @@ -328,11 +365,13 @@ class SSACFG private: InstId scheduleInBlock(InstId const _id, BlockId const _block) { - m_blocks.at(_block.value).instructions.push_back(_id); + block(_block).instructions.push_back(_id); return _id; } - std::vector m_blocks; + std::vector> m_blocks; + // free list of blocks + std::vector m_freeBlocks; InstructionStore m_instructions; public: EVMDialect const& evmDialect; diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index fee1615ad..58c20bdde 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -113,9 +113,13 @@ StackLayoutGenerator::StackLayoutGenerator( std::vector inDegreesIgnoringBackedges(m_cfg.numBlocks(), 0); for (SSACFG::BlockId id{0}; id.value < m_cfg.numBlocks(); ++id.value) + { + if (!m_cfg.hasBlock(id)) + continue; for (auto const& entry: m_cfg.block(id).entries) if (!m_liveness.topologicalSort().backEdge(entry, id)) inDegreesIgnoringBackedges[id.value] += 1; + } std::queue traversalQueue; traversalQueue.push(m_cfg.entry); diff --git a/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp b/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp index 5a804970f..937f8ee71 100644 --- a/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp +++ b/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp @@ -78,6 +78,9 @@ void transform::removeIdentitiesAndNops(SSACFG& _cfg) // Rewrite block-exit references that name InstIds outside `inst.inputs`. for (BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) + { + if (!_cfg.hasBlock(blockId)) + continue; std::visit(solidity::util::GenericVisitor{ [&](SSACFG::BasicBlock::ConditionalJump& c) { c.condition = _cfg.resolveIdentity(c.condition); }, [&](SSACFG::BasicBlock::FunctionReturn& r) { rewriteInputs(_cfg, r.returnValues); }, @@ -85,11 +88,14 @@ void transform::removeIdentitiesAndNops(SSACFG& _cfg) [](SSACFG::BasicBlock::MainExit&) {}, [](SSACFG::BasicBlock::Terminated&) {} }, _cfg.block(blockId).exit); + } // Drop Identity / Nop entries from each block and tombstone their slots. No live reference reads through any of // these slots, so reusing them is safe. for (BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) { + if (!_cfg.hasBlock(blockId)) + continue; auto& block = _cfg.block(blockId); std::vector toTombstone; std::erase_if(block.instructions, [&](InstId const _id) { diff --git a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp index 5f093b981..ae8be9af1 100644 --- a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp +++ b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp @@ -32,12 +32,16 @@ void transform::eliminateTrivialPhis(SSACFG& _cfg) { // Drop upsilons whose value is Unreachable (dead control-flow predecessor) for (BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) + { + if (!_cfg.hasBlock(blockId)) + continue; for (InstId const id: _cfg.block(blockId).instructions) { auto const& inst = _cfg.inst(id); if (inst.isUpsilon() && _cfg.isUnreachable(inst.inputs[0])) _cfg.replaceWithNop(id); } + } // Build per-phi indices std::map> upsilonsTargeting; diff --git a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp index 83da235b3..cd498f414 100644 --- a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp +++ b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp @@ -37,8 +37,9 @@ void transform::cleanUnreachableBlocks(SSACFG& _cfg) { auto const blockId = worklist.front(); worklist.pop_front(); - auto const& block = _cfg.block(blockId); - block.forEachExit([&](BlockId const _exitBlock) { + if (!_cfg.hasBlock(blockId)) + continue; + _cfg.block(blockId).forEachExit([&](BlockId const _exitBlock) { if (!reachable[_exitBlock.value]) { reachable[_exitBlock.value] = true; @@ -50,14 +51,15 @@ void transform::cleanUnreachableBlocks(SSACFG& _cfg) auto& store = _cfg.instructionStore(); for (SSACFG::BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) { - auto& block = _cfg.block(blockId); + if (!_cfg.hasBlock(blockId)) + continue; if (reachable[blockId.value]) - std::erase_if(block.entries, [&](auto const& entry) { return !reachable[entry.value]; }); + std::erase_if(_cfg.block(blockId).entries, [&](auto const& entry) { return !reachable[entry.value]; }); else { - for (InstId const id: block.instructions) + for (InstId const id: _cfg.block(blockId).instructions) store.tombstone(id); - block = {}; + _cfg.resetBlock(blockId); } } } From c4df5896b1d790b33838f8bc7ddc4c16154db686 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 12 May 2026 14:08:55 +0200 Subject: [PATCH 1333/1340] SSA CFG: Add lazy live blocks range helper --- libyul/backends/evm/ssa/LivenessAnalysis.cpp | 14 ++++++-------- libyul/backends/evm/ssa/SSACFG.cpp | 10 +++------- libyul/backends/evm/ssa/SSACFG.h | 9 +++++++++ libyul/backends/evm/ssa/StackLayoutGenerator.cpp | 6 +----- .../evm/ssa/transform/IdentityAndNopRemover.cpp | 10 ++-------- .../evm/ssa/transform/TrivialPhiEliminator.cpp | 6 +----- .../evm/ssa/transform/UnreachableBlockCleaner.cpp | 4 +--- 7 files changed, 23 insertions(+), 36 deletions(-) diff --git a/libyul/backends/evm/ssa/LivenessAnalysis.cpp b/libyul/backends/evm/ssa/LivenessAnalysis.cpp index 5bfa81b4c..54c5e4cf5 100644 --- a/libyul/backends/evm/ssa/LivenessAnalysis.cpp +++ b/libyul/backends/evm/ssa/LivenessAnalysis.cpp @@ -153,24 +153,22 @@ void LivenessAnalysis::runLoopTreeDfs(SSACFG::BlockId::ValueType const _loopHead // must be live out of header if live in of children m_liveOuts[_loopHeader].maxUnion(liveLoop); // for each blockId \in children(loopHeader) - for (SSACFG::BlockId::ValueType blockIdValue = 0u; blockIdValue < m_cfg.numBlocks(); ++blockIdValue) - if (m_cfg.hasBlock(SSACFG::BlockId{blockIdValue}) && m_loopNestingForest.loopParents()[blockIdValue] == _loopHeader) + for (SSACFG::BlockId const blockId: m_cfg.liveBlocks()) + if (m_loopNestingForest.loopParents()[blockId.value] == _loopHeader) { // propagate loop liveness information down to the loop header's children - m_liveIns[blockIdValue].maxUnion(liveLoop); - m_liveOuts[blockIdValue].maxUnion(liveLoop); + m_liveIns[blockId.value].maxUnion(liveLoop); + m_liveOuts[blockId.value].maxUnion(liveLoop); - runLoopTreeDfs(blockIdValue); + runLoopTreeDfs(blockId.value); } } } void LivenessAnalysis::fillOperationsLiveOut() { - for (SSACFG::BlockId blockId{0}; blockId.value < m_cfg.numBlocks(); ++blockId.value) + for (SSACFG::BlockId const blockId: m_cfg.liveBlocks()) { - if (!m_cfg.hasBlock(blockId)) - continue; auto const& block = m_cfg.block(blockId); auto const opCount = static_cast(ranges::count_if( block.instructions, diff --git a/libyul/backends/evm/ssa/SSACFG.cpp b/libyul/backends/evm/ssa/SSACFG.cpp index 1323ca076..ae7b05b4b 100644 --- a/libyul/backends/evm/ssa/SSACFG.cpp +++ b/libyul/backends/evm/ssa/SSACFG.cpp @@ -45,17 +45,13 @@ std::string formatPhi(SSACFG const& _cfg, InstId _phiId) { // Collect all upsilons targeting _phiId from the whole CFG. std::vector formattedUpsilons; - for (BlockId::ValueType bv = 0; bv < _cfg.numBlocks(); ++bv) - { - if (!_cfg.hasBlock(BlockId{bv})) - continue; - _cfg.forEachUpsilon(_cfg.block(BlockId{bv}), [&](InstId const instId, SSACFG::Inst const& inst) { + for (BlockId const blockId: _cfg.liveBlocks()) + _cfg.forEachUpsilon(_cfg.block(blockId), [&](InstId const instId, SSACFG::Inst const& inst) { if (_cfg.upsilonPhi(instId) == _phiId) formattedUpsilons.push_back( - fmt::format("Block {} => {}", bv, inst.inputs.at(0).str(_cfg)) + fmt::format("Block {} => {}", blockId.value, inst.inputs.at(0).str(_cfg)) ); }); - } if (!formattedUpsilons.empty()) return fmt::format("φ(\\l\\\n\t{}\\l\\\n)", fmt::join(formattedUpsilons, ",\\l\\\n\t")); return "φ()"; diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 81c63bb9d..7881013db 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -167,6 +168,14 @@ class SSACFG m_freeBlocks.push_back(_id); } + InputRangeOf auto liveBlocks() const + { + return + ranges::views::iota(BlockId::ValueType{0}, static_cast(m_blocks.size())) | + ranges::views::filter([this](BlockId::ValueType const _v) { return m_blocks[_v].has_value(); }) | + ranges::views::transform([](BlockId::ValueType const _v) { return BlockId{_v}; }); + } + InstructionStore& instructionStore() { return m_instructions; } InstructionStore const& instructionStore() const { return m_instructions; } diff --git a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp index 58c20bdde..6cbc2054b 100644 --- a/libyul/backends/evm/ssa/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/ssa/StackLayoutGenerator.cpp @@ -112,14 +112,10 @@ StackLayoutGenerator::StackLayoutGenerator( // Future optimization: it might be beneficial to revisit the loop heads (back edge targets) after the first iteration std::vector inDegreesIgnoringBackedges(m_cfg.numBlocks(), 0); - for (SSACFG::BlockId id{0}; id.value < m_cfg.numBlocks(); ++id.value) - { - if (!m_cfg.hasBlock(id)) - continue; + for (SSACFG::BlockId const id: m_cfg.liveBlocks()) for (auto const& entry: m_cfg.block(id).entries) if (!m_liveness.topologicalSort().backEdge(entry, id)) inDegreesIgnoringBackedges[id.value] += 1; - } std::queue traversalQueue; traversalQueue.push(m_cfg.entry); diff --git a/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp b/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp index 937f8ee71..fea2f09d3 100644 --- a/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp +++ b/libyul/backends/evm/ssa/transform/IdentityAndNopRemover.cpp @@ -77,10 +77,7 @@ void transform::removeIdentitiesAndNops(SSACFG& _cfg) } // Rewrite block-exit references that name InstIds outside `inst.inputs`. - for (BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) - { - if (!_cfg.hasBlock(blockId)) - continue; + for (BlockId const blockId: _cfg.liveBlocks()) std::visit(solidity::util::GenericVisitor{ [&](SSACFG::BasicBlock::ConditionalJump& c) { c.condition = _cfg.resolveIdentity(c.condition); }, [&](SSACFG::BasicBlock::FunctionReturn& r) { rewriteInputs(_cfg, r.returnValues); }, @@ -88,14 +85,11 @@ void transform::removeIdentitiesAndNops(SSACFG& _cfg) [](SSACFG::BasicBlock::MainExit&) {}, [](SSACFG::BasicBlock::Terminated&) {} }, _cfg.block(blockId).exit); - } // Drop Identity / Nop entries from each block and tombstone their slots. No live reference reads through any of // these slots, so reusing them is safe. - for (BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) + for (BlockId const blockId: _cfg.liveBlocks()) { - if (!_cfg.hasBlock(blockId)) - continue; auto& block = _cfg.block(blockId); std::vector toTombstone; std::erase_if(block.instructions, [&](InstId const _id) { diff --git a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp index ae8be9af1..1669c244c 100644 --- a/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp +++ b/libyul/backends/evm/ssa/transform/TrivialPhiEliminator.cpp @@ -31,17 +31,13 @@ using namespace solidity::yul::ssa; void transform::eliminateTrivialPhis(SSACFG& _cfg) { // Drop upsilons whose value is Unreachable (dead control-flow predecessor) - for (BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) - { - if (!_cfg.hasBlock(blockId)) - continue; + for (BlockId const blockId: _cfg.liveBlocks()) for (InstId const id: _cfg.block(blockId).instructions) { auto const& inst = _cfg.inst(id); if (inst.isUpsilon() && _cfg.isUnreachable(inst.inputs[0])) _cfg.replaceWithNop(id); } - } // Build per-phi indices std::map> upsilonsTargeting; diff --git a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp index cd498f414..483278470 100644 --- a/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp +++ b/libyul/backends/evm/ssa/transform/UnreachableBlockCleaner.cpp @@ -49,10 +49,8 @@ void transform::cleanUnreachableBlocks(SSACFG& _cfg) } auto& store = _cfg.instructionStore(); - for (SSACFG::BlockId blockId{0}; blockId.value < _cfg.numBlocks(); ++blockId.value) + for (SSACFG::BlockId const blockId: _cfg.liveBlocks()) { - if (!_cfg.hasBlock(blockId)) - continue; if (reachable[blockId.value]) std::erase_if(_cfg.block(blockId).entries, [&](auto const& entry) { return !reachable[entry.value]; }); else From ed0c4268a0344bc1a022eda6be79d0f37e1706a9 Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 12 May 2026 09:54:34 +0200 Subject: [PATCH 1334/1340] SSA CFG: Add call graph --- libyul/CMakeLists.txt | 2 ++ libyul/backends/evm/ssa/CallGraph.cpp | 40 +++++++++++++++++++++++ libyul/backends/evm/ssa/CallGraph.h | 47 +++++++++++++++++++++++++++ libyul/backends/evm/ssa/SSACFG.h | 6 ++++ 4 files changed, 95 insertions(+) create mode 100644 libyul/backends/evm/ssa/CallGraph.cpp create mode 100644 libyul/backends/evm/ssa/CallGraph.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index f3789f140..fd78a53d9 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -74,6 +74,8 @@ add_library(yul backends/evm/VariableReferenceCounter.h backends/evm/VariableReferenceCounter.cpp backends/evm/ssa/BridgeFinder.h + backends/evm/ssa/CallGraph.cpp + backends/evm/ssa/CallGraph.h backends/evm/ssa/CodeTransform.cpp backends/evm/ssa/CodeTransform.h backends/evm/ssa/ControlFlowGraphs.cpp diff --git a/libyul/backends/evm/ssa/CallGraph.cpp b/libyul/backends/evm/ssa/CallGraph.cpp new file mode 100644 index 000000000..9f6614c3a --- /dev/null +++ b/libyul/backends/evm/ssa/CallGraph.cpp @@ -0,0 +1,40 @@ +/* + 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 + +#include + +#include + +#include +#include +#include +#include + +solidity::yul::ssa::CallGraph::CallGraph(ControlFlowGraphs const& _cfgs): m_callees(_cfgs.functionGraphs.size()) +{ + for (auto const& [index, cfgPtr]: _cfgs.functionGraphs | ranges::views::enumerate) + for (auto const& [instId, inst]: ranges::views::zip(cfgPtr->instructionIds(), cfgPtr->instructions())) + if (inst.opcode == InstOpcode::Call) + m_callees[index].push_back(cfgPtr->callPayload(instId).graphID); + + for (auto& row: m_callees) + { + ranges::sort(row); + row.erase(ranges::unique(row), row.end()); + } +} diff --git a/libyul/backends/evm/ssa/CallGraph.h b/libyul/backends/evm/ssa/CallGraph.h new file mode 100644 index 000000000..e9aab9e8d --- /dev/null +++ b/libyul/backends/evm/ssa/CallGraph.h @@ -0,0 +1,47 @@ +/* + 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 + +#pragma once + +#include + +#include +#include + +namespace solidity::yul::ssa +{ + +struct ControlFlowGraphs; + +class CallGraph +{ +public: + explicit CallGraph(ControlFlowGraphs const& _cfgs); + + std::size_t numFunctions() const { return m_callees.size(); } + + std::vector const& callees(FunctionGraphID const _function) const + { + return m_callees[_function]; + } + +private: + std::vector> m_callees; +}; + +} diff --git a/libyul/backends/evm/ssa/SSACFG.h b/libyul/backends/evm/ssa/SSACFG.h index 7881013db..98aa85e83 100644 --- a/libyul/backends/evm/ssa/SSACFG.h +++ b/libyul/backends/evm/ssa/SSACFG.h @@ -182,6 +182,12 @@ class SSACFG Inst& inst(InstId _id) { return m_instructions.inst(_id); } Inst const& inst(InstId _id) const { return m_instructions.inst(_id); } size_t numInsts() const { return m_instructions.numInsts(); } + InputRangeOf auto instructionIds() const + { + return + ranges::views::iota(static_cast(0), static_cast(numInsts())) | + ranges::views::transform([](auto const _value) { return InstId{_value}; }); + } std::vector const& instructions() const { return m_instructions.instructions(); } /// Returns the opcode category for a given InstId. From 2ccd8e4943b4982a2223b41d719f7e9a6f2f86ac Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 12 May 2026 17:16:44 +0200 Subject: [PATCH 1335/1340] SSA CFG: Add Tarjan's algorithm for SCCs to call graph --- libyul/CMakeLists.txt | 1 + libyul/backends/evm/ssa/CallGraph.cpp | 6 + libyul/backends/evm/ssa/CallGraph.h | 2 + libyul/backends/evm/ssa/util/TarjanSCC.h | 154 +++++++++++++++++++++++ test/CMakeLists.txt | 1 + test/libyul/ssa/TarjanSCC.cpp | 149 ++++++++++++++++++++++ 6 files changed, 313 insertions(+) create mode 100644 libyul/backends/evm/ssa/util/TarjanSCC.h create mode 100644 test/libyul/ssa/TarjanSCC.cpp diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index fd78a53d9..a0ca285eb 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -107,6 +107,7 @@ add_library(yul backends/evm/ssa/StackToMemorySpilling.h backends/evm/ssa/util/UseCountSet.h backends/evm/ssa/util/TLSFFreeList.h + backends/evm/ssa/util/TarjanSCC.h backends/evm/ssa/StackUtils.cpp backends/evm/ssa/StackUtils.h backends/evm/ssa/io/DotExporterBase.cpp diff --git a/libyul/backends/evm/ssa/CallGraph.cpp b/libyul/backends/evm/ssa/CallGraph.cpp index 9f6614c3a..54eebc89f 100644 --- a/libyul/backends/evm/ssa/CallGraph.cpp +++ b/libyul/backends/evm/ssa/CallGraph.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -38,3 +39,8 @@ solidity::yul::ssa::CallGraph::CallGraph(ControlFlowGraphs const& _cfgs): m_call row.erase(ranges::unique(row), row.end()); } } + +std::vector> solidity::yul::ssa::CallGraph::computeSCCs() const +{ + return util::computeStronglyConnectedComponents(m_callees); +} diff --git a/libyul/backends/evm/ssa/CallGraph.h b/libyul/backends/evm/ssa/CallGraph.h index e9aab9e8d..82a360605 100644 --- a/libyul/backends/evm/ssa/CallGraph.h +++ b/libyul/backends/evm/ssa/CallGraph.h @@ -40,6 +40,8 @@ class CallGraph return m_callees[_function]; } + std::vector> computeSCCs() const; + private: std::vector> m_callees; }; diff --git a/libyul/backends/evm/ssa/util/TarjanSCC.h b/libyul/backends/evm/ssa/util/TarjanSCC.h new file mode 100644 index 000000000..af4b32456 --- /dev/null +++ b/libyul/backends/evm/ssa/util/TarjanSCC.h @@ -0,0 +1,154 @@ +/* + 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 + +#pragma once + +#include + +#include +#include +#include +#include +#include + +namespace solidity::yul::ssa::util +{ + +namespace detail +{ + +/// Callers must supply a dense `[0, N)` remapping; this struct conflates the node's +/// identity with its position in `adjacency` for performance. +template +struct TarjanSCC +{ + static constexpr std::size_t undefined = std::numeric_limits::max(); + + struct Frame + { + NodeIndex node; + std::size_t childIdx; + }; + + std::vector> const& adjacency; + /// numbers the nodes consecutively in the order in which they are discovered + std::vector discoveryIndex; + /// lowlink[v] corresponds to the smallest index of a node reachable through v's DFS subtree + std::vector lowlink; + std::vector onStack; + std::vector nodeStack; + std::vector workStack; + std::size_t nextIndex = 0; + std::vector> sccs; + + explicit TarjanSCC(std::vector> const& _adjacency): + adjacency(_adjacency), + discoveryIndex(_adjacency.size(), undefined), + lowlink(_adjacency.size(), 0), + onStack(_adjacency.size(), false) + {} + + void enter(NodeIndex const _v) + { + discoveryIndex[_v] = nextIndex; + lowlink[_v] = nextIndex; + ++nextIndex; + nodeStack.push_back(_v); + onStack[_v] = true; + workStack.push_back({_v, 0}); + } + + void emitSCC(NodeIndex const _root) + { + yulAssert(!nodeStack.empty()); + std::vector scc; + NodeIndex w; + do + { + w = nodeStack.back(); + nodeStack.pop_back(); + onStack[w] = false; + scc.push_back(w); + } + while (w != _root); + sccs.push_back(std::move(scc)); + } + + std::vector> run() && + { + for (NodeIndex root = 0; root < discoveryIndex.size(); ++root) + { + if (discoveryIndex[root] != undefined) + continue; + + // start new DFS tree + enter(root); + while (!workStack.empty()) + { + NodeIndex const v = workStack.back().node; + std::size_t const childIdx = workStack.back().childIdx; + if (childIdx < adjacency[v].size()) + { + // process next outgoing edge + NodeIndex const w = adjacency[v][childIdx]; + // advance v's currently handled edge before pushing w, so v resumes at the next child when w finishes + workStack.back().childIdx = childIdx + 1; + if (discoveryIndex[w] == undefined) + // Successor w has not yet been visited; recurse on it + enter(w); + else if (onStack[w]) + // Successor w is in stack S and hence in the current SCC + lowlink[v] = std::min(lowlink[v], discoveryIndex[w]); + } + else + { + // if v is a root node + if (lowlink[v] == discoveryIndex[v]) + // generate an SCC and pop the node stack + emitSCC(v); + + // pop v and propagate its lowlink to the parent (post-recursion update) + workStack.pop_back(); + if (!workStack.empty()) + { + NodeIndex const parent = workStack.back().node; + lowlink[parent] = std::min(lowlink[parent], lowlink[v]); + } + } + } + } + return std::move(sccs); + } +}; + +} + +/// Tarjan's strongly-connected-components algorithm. +/// Takes an adjacency list where `_adjacency[v]` is the list of successors of node `v`. Node IDs must lie in `[0, _adjacency.size())`. +/// Implementation based on the Wikipedia pseudocode. +/// +/// Wikipedia contributors, "Tarjan's strongly connected components algorithm," Wikipedia, The Free Encyclopedia, +/// https://en.wikipedia.org/w/index.php?title=Tarjan%27s_strongly_connected_components_algorithm&oldid=1341352351 +/// Tarjan, R.E., "Depth-First Search and Linear Graph Algorithms", https://doi.org/10.1137/0201010 +template +std::vector> computeStronglyConnectedComponents(std::vector> const& _adjacency) +{ + return detail::TarjanSCC(_adjacency).run(); +} + +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c6c8040f8..5003917c2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -177,6 +177,7 @@ set(libyul_sources libyul/ssa/StackLayoutGeneratorTest.h libyul/ssa/StackShufflerTest.cpp libyul/ssa/StackShufflerTest.h + libyul/ssa/TarjanSCC.cpp ) detect_stray_source_files("${libyul_sources}" "libyul/") diff --git a/test/libyul/ssa/TarjanSCC.cpp b/test/libyul/ssa/TarjanSCC.cpp new file mode 100644 index 000000000..d02ec2cc3 --- /dev/null +++ b/test/libyul/ssa/TarjanSCC.cpp @@ -0,0 +1,149 @@ +/* + 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 . +*/ +/** + * Unit tests for the Tarjan SCC utility. + */ + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace solidity::yul::test::ssa +{ + +using NodeID = std::uint32_t; +using Graph = std::vector>; +using SCCList = std::vector>; + +namespace +{ + +namespace bdata = boost::unit_test::data; + +SCCList compute(Graph const& _g) +{ + return solidity::yul::ssa::util::computeStronglyConnectedComponents(_g); +} + +SCCList canonicalize(SCCList _sccs) +{ + for (auto& scc: _sccs) + ranges::sort(scc); + ranges::sort(_sccs); + return _sccs; +} + +std::string formatSCCs(SCCList const& _sccs) +{ + auto const formatScc = [](std::vector const& _scc) { + return fmt::format("{{{}}}", fmt::join(_scc, ", ")); + }; + return fmt::format("{{{}}}", fmt::join(_sccs | ranges::views::transform(formatScc), ", ")); +} + +boost::test_tools::predicate_result sccsEqual(SCCList const& _actual, SCCList const& _expected) +{ + SCCList const canonicalActual = canonicalize(_actual); + SCCList const canonicalExpected = canonicalize(_expected); + if (canonicalActual == canonicalExpected) + return true; + boost::test_tools::predicate_result result(false); + result.message() + << "SCC partitions differ (compared as sets of sets).\n" + << " actual: " << formatSCCs(canonicalActual) << "\n" + << " expected: " << formatSCCs(canonicalExpected); + return result; +} + +struct PartitionCase +{ + std::string name; + Graph graph; + SCCList expectedSCCs; +}; + +std::ostream& operator<<(std::ostream& _os, PartitionCase const& _case) +{ + return _os << _case.name; +} + +std::vector const partitionCases = { + {"empty_graph", {}, {}}, + {"single_node_no_edges", Graph(1), {{0}}}, + {"single_node_self_loop", {{0}}, {{0}}}, + {"two_cycle", {{1}, {0}}, {{0, 1}}}, + {"three_cycle", {{1}, {2}, {0}}, {{0, 1, 2}}}, + {"linear_chain", {{1}, {2}, {3}, {}}, {{0}, {1}, {2}, {3}}}, + // 0 <-> 1, plus self-loop on 0. Yields one SCC {0, 1}. + {"self_loop_inside_two_cycle", {{0, 1}, {0}}, {{0, 1}}}, + // 0 -> 2, 1 -> 2: three singleton SCCs. + {"dag_with_shared_successor", {{2}, {2}, {}}, {{0}, {1}, {2}}}, + { + "clrs_example", + // CLRS, 3rd ed., Fig. 22.9 (relabeled a..h -> 0..7). + // 0 -> 1 + // 1 -> 2, 4, 5 + // 2 -> 3, 6 + // 3 -> 2, 7 + // 4 -> 0, 5 + // 5 -> 6 + // 6 -> 5, 7 + // 7 -> 7 + {{1}, {2, 4, 5}, {3, 6}, {2, 7}, {0, 5}, {6}, {5, 7}, {7}}, + {{0, 1, 4}, {2, 3}, {5, 6}, {7}}, + }, + { + "multiple_disjoint_components", + // Four components: 0 <-> 1, 2 <-> 3, 4 -> 5. + {{1}, {0}, {3}, {2}, {5}, {}}, + {{0, 1}, {2, 3}, {4}, {5}}, + }, + { + "nested_sccs_with_cross_edges", + // Two SCCs connected by an inter-SCC edge: 0 <-> 1 (A), 2 <-> 3 (B), 1 -> 2. + {{1}, {0, 2}, {3}, {2}}, + {{0, 1}, {2, 3}}, + }, + // 0 -> 1, node 2 isolated: 2 still emitted as its own SCC. + {"unreachable_node_still_emitted", {{1}, {}, {}}, {{0}, {1}, {2}}}, +}; + +} + +BOOST_AUTO_TEST_SUITE(TarjanSCC) + +BOOST_DATA_TEST_CASE(partition, bdata::make(partitionCases), testCase) +{ + BOOST_CHECK(sccsEqual(compute(testCase.graph), testCase.expectedSCCs)); +} + +BOOST_AUTO_TEST_SUITE_END() + +} From e0b9da8bc6b38f3bbe3734e7630d8b030bf590cf Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 12 May 2026 17:23:30 +0200 Subject: [PATCH 1336/1340] SSA CFG: Add `isRecursive` to call graph --- libyul/backends/evm/ssa/CallGraph.cpp | 31 +++++++++++++++++++++--- libyul/backends/evm/ssa/CallGraph.h | 8 ++++++ libyul/backends/evm/ssa/util/TarjanSCC.h | 1 + 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/libyul/backends/evm/ssa/CallGraph.cpp b/libyul/backends/evm/ssa/CallGraph.cpp index 54eebc89f..2fe352256 100644 --- a/libyul/backends/evm/ssa/CallGraph.cpp +++ b/libyul/backends/evm/ssa/CallGraph.cpp @@ -21,6 +21,9 @@ #include #include +#include + +#include #include #include #include @@ -33,10 +36,10 @@ solidity::yul::ssa::CallGraph::CallGraph(ControlFlowGraphs const& _cfgs): m_call if (inst.opcode == InstOpcode::Call) m_callees[index].push_back(cfgPtr->callPayload(instId).graphID); - for (auto& row: m_callees) + for (auto& callees: m_callees) { - ranges::sort(row); - row.erase(ranges::unique(row), row.end()); + ranges::sort(callees); + callees.erase(ranges::unique(callees), callees.end()); } } @@ -44,3 +47,25 @@ std::vector> solidity::yul::ssa { return util::computeStronglyConnectedComponents(m_callees); } + +bool solidity::yul::ssa::CallGraph::isRecursive(FunctionGraphID const _function) const +{ + if (!m_recursiveFunctions) + computeRecursiveFunctions(); + return (*m_recursiveFunctions)[_function]; +} + +void solidity::yul::ssa::CallGraph::computeRecursiveFunctions() const +{ + std::vector result(m_callees.size(), false); + for (auto const& scc: computeSCCs()) + { + yulAssert(!scc.empty()); + if (scc.size() > 1) + for (FunctionGraphID const f: scc) + result[f] = true; + else if (ranges::binary_search(m_callees[scc.front()], scc.front())) + result[scc.front()] = true; + } + m_recursiveFunctions = std::move(result); +} diff --git a/libyul/backends/evm/ssa/CallGraph.h b/libyul/backends/evm/ssa/CallGraph.h index 82a360605..3a22eb9f1 100644 --- a/libyul/backends/evm/ssa/CallGraph.h +++ b/libyul/backends/evm/ssa/CallGraph.h @@ -21,6 +21,7 @@ #include #include +#include #include namespace solidity::yul::ssa @@ -42,8 +43,15 @@ class CallGraph std::vector> computeSCCs() const; + /// True iff `_function` participates in a recursive chain. Either directly (self-edge) or as part of a + /// mutual-recursion cycle of any length + bool isRecursive(FunctionGraphID _function) const; + private: + void computeRecursiveFunctions() const; + std::vector> m_callees; + mutable std::optional> m_recursiveFunctions; }; } diff --git a/libyul/backends/evm/ssa/util/TarjanSCC.h b/libyul/backends/evm/ssa/util/TarjanSCC.h index af4b32456..befbde50f 100644 --- a/libyul/backends/evm/ssa/util/TarjanSCC.h +++ b/libyul/backends/evm/ssa/util/TarjanSCC.h @@ -65,6 +65,7 @@ struct TarjanSCC void enter(NodeIndex const _v) { + yulAssert(_v < adjacency.size()); discoveryIndex[_v] = nextIndex; lowlink[_v] = nextIndex; ++nextIndex; From 193db0338c989ffa6b41abfd57b5a18fd25ad5ca Mon Sep 17 00:00:00 2001 From: clonker <1685266+clonker@users.noreply.github.com> Date: Tue, 12 May 2026 17:40:43 +0200 Subject: [PATCH 1337/1340] SSA CFG: Add call graph tests --- test/CMakeLists.txt | 2 + test/InteractiveTests.h | 2 + test/libyul/ssa/CallGraphTest.cpp | 89 +++++++++++++++++++ test/libyul/ssa/CallGraphTest.h | 36 ++++++++ .../branching_into_and_out_of_scc.yul | 13 +++ test/libyul/ssa/callGraph/caller_into_scc.yul | 10 +++ .../ssa/callGraph/direct_plus_mutual.yul | 10 +++ .../libyul/ssa/callGraph/direct_self_call.yul | 6 ++ .../ssa/callGraph/duplicate_callees.yul | 11 +++ test/libyul/ssa/callGraph/leaf.yul | 6 ++ test/libyul/ssa/callGraph/mixed.yul | 10 +++ .../ssa/callGraph/multi_callee_three_scc.yul | 13 +++ .../callGraph/multiple_distinct_callees.yul | 13 +++ .../ssa/callGraph/mutual_three_cycle.yul | 10 +++ .../libyul/ssa/callGraph/mutual_two_cycle.yul | 8 ++ .../ssa/callGraph/non_recursive_chain.yul | 10 +++ test/libyul/ssa/callGraph/self_and_other.yul | 11 +++ test/libyul/ssa/callGraph/shared_callee.yul | 10 +++ test/tools/CMakeLists.txt | 2 + 19 files changed, 272 insertions(+) create mode 100644 test/libyul/ssa/CallGraphTest.cpp create mode 100644 test/libyul/ssa/CallGraphTest.h create mode 100644 test/libyul/ssa/callGraph/branching_into_and_out_of_scc.yul create mode 100644 test/libyul/ssa/callGraph/caller_into_scc.yul create mode 100644 test/libyul/ssa/callGraph/direct_plus_mutual.yul create mode 100644 test/libyul/ssa/callGraph/direct_self_call.yul create mode 100644 test/libyul/ssa/callGraph/duplicate_callees.yul create mode 100644 test/libyul/ssa/callGraph/leaf.yul create mode 100644 test/libyul/ssa/callGraph/mixed.yul create mode 100644 test/libyul/ssa/callGraph/multi_callee_three_scc.yul create mode 100644 test/libyul/ssa/callGraph/multiple_distinct_callees.yul create mode 100644 test/libyul/ssa/callGraph/mutual_three_cycle.yul create mode 100644 test/libyul/ssa/callGraph/mutual_two_cycle.yul create mode 100644 test/libyul/ssa/callGraph/non_recursive_chain.yul create mode 100644 test/libyul/ssa/callGraph/self_and_other.yul create mode 100644 test/libyul/ssa/callGraph/shared_callee.yul diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5003917c2..6ccf2fcbb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -171,6 +171,8 @@ set(libyul_sources libyul/YulOptimizerTest.h libyul/YulOptimizerTestCommon.cpp libyul/YulOptimizerTestCommon.h + libyul/ssa/CallGraphTest.cpp + libyul/ssa/CallGraphTest.h libyul/ssa/ControlFlowGraphTest.cpp libyul/ssa/ControlFlowGraphTest.h libyul/ssa/StackLayoutGeneratorTest.cpp diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index 063e21ccb..ac8fbbbcd 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -75,6 +76,7 @@ Testsuite const g_interactiveTestsuites[] = { {"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create}, {"Yul Control Flow Graph", "libyul", "yulControlFlowGraph", false, false, &yul::test::ControlFlowGraphTest::create}, {"Yul SSA Control Flow Graph", "libyul", "ssa/controlFlowGraph", false, false, &yul::test::ssa::ControlFlowGraphTest::create}, + {"Yul SSA Call Graph", "libyul", "ssa/callGraph", false, false, &yul::test::ssa::CallGraphTest::create}, {"Yul SSA StackShuffling", "libyul", "ssa/stackShuffler", false, false, &yul::test::ssa::ShufflingTest::create}, {"Yul SSA StackLayoutGenerator","libyul", "ssa/stackLayoutGenerator", false, false, &yul::test::ssa::StackLayoutGeneratorTest::create}, {"Yul Stack Layout", "libyul", "yulStackLayout", false, false, &yul::test::StackLayoutGeneratorTest::create}, diff --git a/test/libyul/ssa/CallGraphTest.cpp b/test/libyul/ssa/CallGraphTest.cpp new file mode 100644 index 000000000..958e0b648 --- /dev/null +++ b/test/libyul/ssa/CallGraphTest.cpp @@ -0,0 +1,89 @@ +/* + 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 + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace solidity; +using namespace solidity::util; +using namespace solidity::langutil; +using namespace solidity::yul; +using namespace solidity::yul::test::ssa; +using namespace solidity::frontend; +using namespace solidity::frontend::test; + +std::unique_ptr CallGraphTest::create(Config const& _config) +{ + return std::make_unique(_config.filename); +} + +CallGraphTest::CallGraphTest(std::string const& _filename): TestCase(_filename) +{ + m_source = m_reader.source(); + auto dialectName = m_reader.stringSetting("dialect", "evm"); + soltestAssert(dialectName == "evm"); + m_expectation = m_reader.simpleExpectations(); +} + +TestCase::TestResult CallGraphTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) +{ + YulStack const yulStack = parseYul(m_source); + solUnimplementedAssert(yulStack.parserResult()->subObjects.empty(), "Tests with subobjects not supported."); + + if (yulStack.hasErrors()) + { + printYulErrors(yulStack, _stream, _linePrefix, _formatted); + return TestResult::FatalError; + } + + auto const* evmDialect = dynamic_cast(&yulStack.dialect()); + solAssert(evmDialect); + + std::unique_ptr const controlFlowGraphs = yul::ssa::SSACFGBuilder::build( + *yulStack.parserResult()->analysisInfo, + *evmDialect, + yulStack.parserResult()->code()->root(), + true + ); + + yul::ssa::CallGraph const callGraph(*controlFlowGraphs); + std::ostringstream out; + for (yul::ssa::FunctionGraphID id = 0; id < controlFlowGraphs->functionGraphs.size(); ++id) + { + auto const& cfg = *controlFlowGraphs->functionGraphs[id]; + std::string const label = cfg.isMainGraph() ? "
    " : cfg.name; + out << label << ": " << (callGraph.isRecursive(id) ? "recursive" : "non-recursive") << "\n"; + } + m_obtainedResult = out.str(); + + return checkResult(_stream, _linePrefix, _formatted); +} diff --git a/test/libyul/ssa/CallGraphTest.h b/test/libyul/ssa/CallGraphTest.h new file mode 100644 index 000000000..383a81737 --- /dev/null +++ b/test/libyul/ssa/CallGraphTest.h @@ -0,0 +1,36 @@ +/* + 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 + +#pragma once + +#include + +#include + +namespace solidity::yul::test::ssa +{ + +class CallGraphTest: public frontend::test::TestCase +{ +public: + static std::unique_ptr create(Config const& _config); + explicit CallGraphTest(std::string const& _filename); + TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; +}; + +} diff --git a/test/libyul/ssa/callGraph/branching_into_and_out_of_scc.yul b/test/libyul/ssa/callGraph/branching_into_and_out_of_scc.yul new file mode 100644 index 000000000..82eccf25b --- /dev/null +++ b/test/libyul/ssa/callGraph/branching_into_and_out_of_scc.yul @@ -0,0 +1,13 @@ +{ + function f() { + g() + h() + } + function g() { f() } + function h() {} +} +// ---- +//
    : non-recursive +// f: recursive +// g: recursive +// h: non-recursive diff --git a/test/libyul/ssa/callGraph/caller_into_scc.yul b/test/libyul/ssa/callGraph/caller_into_scc.yul new file mode 100644 index 000000000..4167f3caf --- /dev/null +++ b/test/libyul/ssa/callGraph/caller_into_scc.yul @@ -0,0 +1,10 @@ +{ + function f() { g() } + function g() { h() } + function h() { g() } +} +// ---- +//
    : non-recursive +// f: non-recursive +// g: recursive +// h: recursive diff --git a/test/libyul/ssa/callGraph/direct_plus_mutual.yul b/test/libyul/ssa/callGraph/direct_plus_mutual.yul new file mode 100644 index 000000000..f75690c6b --- /dev/null +++ b/test/libyul/ssa/callGraph/direct_plus_mutual.yul @@ -0,0 +1,10 @@ +{ + function f() { f() } + function g() { h() } + function h() { g() } +} +// ---- +//
    : non-recursive +// f: recursive +// g: recursive +// h: recursive diff --git a/test/libyul/ssa/callGraph/direct_self_call.yul b/test/libyul/ssa/callGraph/direct_self_call.yul new file mode 100644 index 000000000..7a57413da --- /dev/null +++ b/test/libyul/ssa/callGraph/direct_self_call.yul @@ -0,0 +1,6 @@ +{ + function f() { f() } +} +// ---- +//
    : non-recursive +// f: recursive diff --git a/test/libyul/ssa/callGraph/duplicate_callees.yul b/test/libyul/ssa/callGraph/duplicate_callees.yul new file mode 100644 index 000000000..549ca59da --- /dev/null +++ b/test/libyul/ssa/callGraph/duplicate_callees.yul @@ -0,0 +1,11 @@ +{ + function f() { + g() + g() + } + function g() {} +} +// ---- +//
    : non-recursive +// f: non-recursive +// g: non-recursive diff --git a/test/libyul/ssa/callGraph/leaf.yul b/test/libyul/ssa/callGraph/leaf.yul new file mode 100644 index 000000000..b44705017 --- /dev/null +++ b/test/libyul/ssa/callGraph/leaf.yul @@ -0,0 +1,6 @@ +{ + function f() {} +} +// ---- +//
    : non-recursive +// f: non-recursive diff --git a/test/libyul/ssa/callGraph/mixed.yul b/test/libyul/ssa/callGraph/mixed.yul new file mode 100644 index 000000000..e1bd7247f --- /dev/null +++ b/test/libyul/ssa/callGraph/mixed.yul @@ -0,0 +1,10 @@ +{ + function f() { g() } + function g() { f() } + function h() {} +} +// ---- +//
    : non-recursive +// f: recursive +// g: recursive +// h: non-recursive diff --git a/test/libyul/ssa/callGraph/multi_callee_three_scc.yul b/test/libyul/ssa/callGraph/multi_callee_three_scc.yul new file mode 100644 index 000000000..dd1396a6e --- /dev/null +++ b/test/libyul/ssa/callGraph/multi_callee_three_scc.yul @@ -0,0 +1,13 @@ +{ + function a() { + b() + c() + } + function b() { a() } + function c() { b() } +} +// ---- +//
    : non-recursive +// a: recursive +// b: recursive +// c: recursive diff --git a/test/libyul/ssa/callGraph/multiple_distinct_callees.yul b/test/libyul/ssa/callGraph/multiple_distinct_callees.yul new file mode 100644 index 000000000..e67e01ca9 --- /dev/null +++ b/test/libyul/ssa/callGraph/multiple_distinct_callees.yul @@ -0,0 +1,13 @@ +{ + function f() { + g() + h() + } + function g() {} + function h() {} +} +// ---- +//
    : non-recursive +// f: non-recursive +// g: non-recursive +// h: non-recursive diff --git a/test/libyul/ssa/callGraph/mutual_three_cycle.yul b/test/libyul/ssa/callGraph/mutual_three_cycle.yul new file mode 100644 index 000000000..1cdeb220d --- /dev/null +++ b/test/libyul/ssa/callGraph/mutual_three_cycle.yul @@ -0,0 +1,10 @@ +{ + function f() { g() } + function g() { h() } + function h() { f() } +} +// ---- +//
    : non-recursive +// f: recursive +// g: recursive +// h: recursive diff --git a/test/libyul/ssa/callGraph/mutual_two_cycle.yul b/test/libyul/ssa/callGraph/mutual_two_cycle.yul new file mode 100644 index 000000000..123e26698 --- /dev/null +++ b/test/libyul/ssa/callGraph/mutual_two_cycle.yul @@ -0,0 +1,8 @@ +{ + function f() { g() } + function g() { f() } +} +// ---- +//
    : non-recursive +// f: recursive +// g: recursive diff --git a/test/libyul/ssa/callGraph/non_recursive_chain.yul b/test/libyul/ssa/callGraph/non_recursive_chain.yul new file mode 100644 index 000000000..20086c873 --- /dev/null +++ b/test/libyul/ssa/callGraph/non_recursive_chain.yul @@ -0,0 +1,10 @@ +{ + function f() { g() } + function g() { h() } + function h() {} +} +// ---- +//
    : non-recursive +// f: non-recursive +// g: non-recursive +// h: non-recursive diff --git a/test/libyul/ssa/callGraph/self_and_other.yul b/test/libyul/ssa/callGraph/self_and_other.yul new file mode 100644 index 000000000..be843421f --- /dev/null +++ b/test/libyul/ssa/callGraph/self_and_other.yul @@ -0,0 +1,11 @@ +{ + function f() { + f() + g() + } + function g() {} +} +// ---- +//
    : non-recursive +// f: recursive +// g: non-recursive diff --git a/test/libyul/ssa/callGraph/shared_callee.yul b/test/libyul/ssa/callGraph/shared_callee.yul new file mode 100644 index 000000000..4b28e34f2 --- /dev/null +++ b/test/libyul/ssa/callGraph/shared_callee.yul @@ -0,0 +1,10 @@ +{ + function f() { h() } + function g() { h() } + function h() {} +} +// ---- +//
    : non-recursive +// f: non-recursive +// g: non-recursive +// h: non-recursive diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 46cd0eedb..fc2e3512a 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -52,6 +52,8 @@ add_executable(isoltest ../libyul/YulOptimizerTest.cpp ../libyul/YulOptimizerTestCommon.cpp ../libyul/YulInterpreterTest.cpp + ../libyul/ssa/CallGraphTest.cpp + ../libyul/ssa/CallGraphTest.h ../libyul/ssa/ControlFlowGraphTest.cpp ../libyul/ssa/ControlFlowGraphTest.h ../libyul/ssa/StackLayoutGeneratorTest.cpp From f5df12f11c50587f221f8f2fe6f844df78f19528 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Thu, 19 Mar 2026 13:11:19 +0100 Subject: [PATCH 1338/1340] Rework `typeViaContractName` and `nativeMembers` fragment. --- libsolidity/analysis/TypeChecker.cpp | 2 +- libsolidity/ast/AST.cpp | 54 ++++++++++++++++++++++------ libsolidity/ast/AST.h | 18 +++++++--- libsolidity/ast/Types.cpp | 44 +++++++++++++++-------- 4 files changed, 88 insertions(+), 30 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 25bd4a915..8a1b4171e 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -4054,7 +4054,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) FunctionType const* functionType = dynamic_cast( functionDefinition.libraryFunction() ? - functionDefinition.typeViaContractName() : + functionDefinition.typeViaContractName(Declaration::ContractNameAccessKind::Library) : functionDefinition.type() ); diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index b59273b18..614de9f04 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -491,17 +491,51 @@ Type const* FunctionDefinition::type() const return TypeProvider::function(*this, FunctionType::Kind::Internal); } -Type const* FunctionDefinition::typeViaContractName() const +Type const* FunctionDefinition::typeViaContractName(ContractNameAccessKind const _accessKind) const { - if (libraryFunction()) + switch (_accessKind) { - if (isPublic()) - return FunctionType(*this).asExternallyCallableFunction(true); - else - return TypeProvider::function(*this, FunctionType::Kind::Internal); + case ContractNameAccessKind::Local: + { + solAssert(!libraryFunction(), "Library member cannot be accessed from local/deriving scope"); + solAssert(visibility() > Visibility::Private, "Private non-library member is not visible via contract type name"); + + if (!Declaration::isVisibleInContract() || !isImplemented()) + // If is external or has no implementation, it cannot be called using contract type name. In case of accessing + // via contract type name, only declaration is available, to be used in non calling context. I.e. to access + // function selector `C.foo.selector` where foo has external visibility. + return TypeProvider::function(*this, FunctionType::Kind::Declaration); + else + // If call is in local (or deriving) scope, function is visible in contract (non-external) and it has an + // implementation, internal call is used. + return type(); + } + case ContractNameAccessKind::Foreign: + { + solAssert(!libraryFunction(), "Library members can only be accessed via library name."); + solAssert(isVisibleViaContractTypeAccess(), "Externally invisible member accessed via contract name."); + // Foreign contract member function being accessed via contract type name, cannot be called. + return TypeProvider::function(*this, FunctionType::Kind::Declaration); + } + case ContractNameAccessKind::Library: + { + // We could theoretically distinguish local and foreign scope for libraries but it does not affect the type, + // so we don't. Access to private members from foreign scopes is not allowed by the type checker, so if we + // get such a function here, we assume the scope is local. Note that access to private library members via + // library name is not allowed, but you can (sometimes, see issue [#16721](#16721)) attach them via `using` + // statement. + solAssert(libraryFunction(), "Non-library members cannot be accessed via library name."); + // In case of library contract, member call kind depends on its visibility. + if (isPublic()) + // When Lib.foo is public or external, an external call (delegate call) is used. + return FunctionType(*this).asExternallyCallableFunction(true /* _inLibrary */); + else + // For private or internal visibility, internal call is used. + // Private library members can be accessed in context of `using` statement. + return type(); + } } - else - return TypeProvider::function(*this, FunctionType::Kind::Declaration); + util::unreachable(); } std::string FunctionDefinition::externalSignature() const @@ -952,7 +986,7 @@ FunctionType const* UnaryOperation::userDefinedFunctionType() const FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction; return dynamic_cast( userDefinedFunction->libraryFunction() ? - userDefinedFunction->typeViaContractName() : + userDefinedFunction->typeViaContractName(Declaration::ContractNameAccessKind::Library) : userDefinedFunction->type() ); } @@ -965,7 +999,7 @@ FunctionType const* BinaryOperation::userDefinedFunctionType() const FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction; return dynamic_cast( userDefinedFunction->libraryFunction() ? - userDefinedFunction->typeViaContractName() : + userDefinedFunction->typeViaContractName(Declaration::ContractNameAccessKind::Library) : userDefinedFunction->type() ); } diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index a4e19582b..a471b9c22 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -297,9 +297,19 @@ class Declaration: public ASTNode, public Scopable /// This can only be called once types of variable declarations have already been resolved. virtual Type const* type() const = 0; - /// @returns the type for members of the containing contract type that refer to this declaration. + /// Additional context for expressions that refer to contract members via the contract name. + /// Indicates whether the contract is a contract/interface or a library + /// and whether the access happens in a scope that belongs to that contract or outside (which affects visibility of members). + enum class ContractNameAccessKind { + Local, ///< Via contract name, from within that contract or one deriving from it. + Foreign, ///< Via contract name, from foreign (unrelated) contract. + Library, ///< Via library name (no distinction between local or foreign access). + }; + + /// @returns the type for members of the containing contract type that refer to this declaration. Depends on access + /// context defined by `ContractNameAccessKind`. /// This can only be called once types of variable declarations have already been resolved. - virtual Type const* typeViaContractName() const { return type(); } + virtual Type const* typeViaContractName(ContractNameAccessKind const) const { return type(); } /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. /// @returns null when it is not accessible as a function. @@ -1040,7 +1050,7 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen bool isVisibleViaContractTypeAccess() const override { solAssert(!isFree(), ""); - return isOrdinary() && visibility() >= Visibility::Public; + return isPartOfExternalInterface(); } bool isPartOfExternalInterface() const override { return isOrdinary() && isPublic(); } @@ -1053,7 +1063,7 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen std::string externalIdentifierHex() const; Type const* type() const override; - Type const* typeViaContractName() const override; + Type const* typeViaContractName(ContractNameAccessKind const _accessKind) const override; /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. /// @returns null when it is not accessible as a function. diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 601788eaf..f7bd9e7ac 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -404,7 +404,9 @@ std::set Type::operatorDefiniti *identifierPath->annotation().referencedDeclaration ); auto const* functionType = dynamic_cast( - functionDefinition.libraryFunction() ? functionDefinition.typeViaContractName() : functionDefinition.type() + functionDefinition.libraryFunction() ? + functionDefinition.typeViaContractName(Declaration::ContractNameAccessKind::Library) : + functionDefinition.type() ); solAssert(functionType && !functionType->parameterTypes().empty()); @@ -426,7 +428,7 @@ MemberList::MemberMap Type::attachedFunctions(Type const& _type, ASTNode const& if (!_name) _name = _function.name(); Type const* functionType = - _function.libraryFunction() ? _function.typeViaContractName() : _function.type(); + _function.libraryFunction() ? _function.typeViaContractName(Declaration::ContractNameAccessKind::Library) : _function.type(); solAssert(functionType, ""); FunctionType const* withBoundFirstArgument = dynamic_cast(*functionType).withBoundFirstArgument(); @@ -3978,21 +3980,33 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons if (declaration->name().empty()) continue; - if (!contract.isLibrary() && inDerivingScope && declaration->isVisibleInDerivedContracts()) + if (contract.isLibrary() && declaration->isVisibleAsLibraryMember()) { - if ( - auto const* functionDefinition = dynamic_cast(declaration); - functionDefinition && !functionDefinition->isImplemented() - ) - members.emplace_back(declaration, declaration->typeViaContractName()); - else - members.emplace_back(declaration, declaration->type()); + // In case the contract is library, add only visible library members. visibility >= Internal. + members.emplace_back( + declaration, + declaration->typeViaContractName(Declaration::ContractNameAccessKind::Library) + ); + } + else if (!contract.isLibrary() && inDerivingScope && declaration->visibility() > Visibility::Private) + { + // In case of regular contract (not library) and member is in the same deriving scope, add all + // members which are not private. Private members cannot be accessed via contract type name + // i.e C.fooPrivate. + members.emplace_back( + declaration, + declaration->typeViaContractName(Declaration::ContractNameAccessKind::Local) + ); + } + else if (!contract.isLibrary() && !inDerivingScope && declaration->isVisibleViaContractTypeAccess()) + { + // In case of regular contract (not library) being accessed from foreign contract (not in deriving + // scope), add only externally visible members. + members.emplace_back( + declaration, + declaration->typeViaContractName(Declaration::ContractNameAccessKind::Foreign) + ); } - else if ( - (contract.isLibrary() && declaration->isVisibleAsLibraryMember()) || - declaration->isVisibleViaContractTypeAccess() - ) - members.emplace_back(declaration, declaration->typeViaContractName()); } } } From 70106fd675672e9f98c3fb469ac073a4f3dff9b3 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 21 Apr 2026 16:28:54 +0200 Subject: [PATCH 1339/1340] Introduce `typeWhenAttached` helper --- libsolidity/analysis/TypeChecker.cpp | 7 +------ libsolidity/ast/AST.cpp | 18 ++++++++---------- libsolidity/ast/AST.h | 1 + libsolidity/ast/Types.cpp | 9 ++------- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 8a1b4171e..2af45a311 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -4052,12 +4052,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) FunctionDefinition const& functionDefinition = dynamic_cast(*path->annotation().referencedDeclaration); - FunctionType const* functionType = dynamic_cast( - functionDefinition.libraryFunction() ? - functionDefinition.typeViaContractName(Declaration::ContractNameAccessKind::Library) : - functionDefinition.type() - ); - + FunctionType const* functionType = dynamic_cast(functionDefinition.typeWhenAttached()); solAssert(functionType); if (functionDefinition.parameters().empty()) diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 614de9f04..3b699d2bc 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -538,6 +538,12 @@ Type const* FunctionDefinition::typeViaContractName(ContractNameAccessKind const util::unreachable(); } +Type const* FunctionDefinition::typeWhenAttached() const +{ + solAssert(isFree() || libraryFunction()); + return libraryFunction() ? typeViaContractName(ContractNameAccessKind::Library) : type(); +} + std::string FunctionDefinition::externalSignature() const { return TypeProvider::function(*this)->externalSignature(); @@ -984,11 +990,7 @@ FunctionType const* UnaryOperation::userDefinedFunctionType() const return nullptr; FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction; - return dynamic_cast( - userDefinedFunction->libraryFunction() ? - userDefinedFunction->typeViaContractName(Declaration::ContractNameAccessKind::Library) : - userDefinedFunction->type() - ); + return dynamic_cast(userDefinedFunction->typeWhenAttached()); } FunctionType const* BinaryOperation::userDefinedFunctionType() const @@ -997,11 +999,7 @@ FunctionType const* BinaryOperation::userDefinedFunctionType() const return nullptr; FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction; - return dynamic_cast( - userDefinedFunction->libraryFunction() ? - userDefinedFunction->typeViaContractName(Declaration::ContractNameAccessKind::Library) : - userDefinedFunction->type() - ); + return dynamic_cast(userDefinedFunction->typeWhenAttached()); } BinaryOperationAnnotation& BinaryOperation::annotation() const diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index a471b9c22..b84882191 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1064,6 +1064,7 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen Type const* type() const override; Type const* typeViaContractName(ContractNameAccessKind const _accessKind) const override; + Type const* typeWhenAttached() const; /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. /// @returns null when it is not accessible as a function. diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index f7bd9e7ac..3713ac37a 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -403,11 +403,7 @@ std::set Type::operatorDefiniti auto const& functionDefinition = dynamic_cast( *identifierPath->annotation().referencedDeclaration ); - auto const* functionType = dynamic_cast( - functionDefinition.libraryFunction() ? - functionDefinition.typeViaContractName(Declaration::ContractNameAccessKind::Library) : - functionDefinition.type() - ); + auto const* functionType = dynamic_cast(functionDefinition.typeWhenAttached()); solAssert(functionType && !functionType->parameterTypes().empty()); size_t parameterCount = functionDefinition.parameterList().parameters().size(); @@ -427,8 +423,7 @@ MemberList::MemberMap Type::attachedFunctions(Type const& _type, ASTNode const& { if (!_name) _name = _function.name(); - Type const* functionType = - _function.libraryFunction() ? _function.typeViaContractName(Declaration::ContractNameAccessKind::Library) : _function.type(); + Type const* functionType = _function.typeWhenAttached(); solAssert(functionType, ""); FunctionType const* withBoundFirstArgument = dynamic_cast(*functionType).withBoundFirstArgument(); From f6b841d1b453c78cbe9a986e108817471810cd3a Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 13 May 2026 12:13:24 +0200 Subject: [PATCH 1340/1340] Introduce `isVisibleViaContractName` --- libsolidity/ast/AST.cpp | 6 +++-- libsolidity/ast/AST.h | 20 ++++++++++++++- libsolidity/ast/Types.cpp | 51 +++++++++++++++++++++------------------ 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 3b699d2bc..af5175435 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -493,11 +493,13 @@ Type const* FunctionDefinition::type() const Type const* FunctionDefinition::typeViaContractName(ContractNameAccessKind const _accessKind) const { + // TODO: Fails because private library functions are attachable but not visible (issue #16721) + //solAssert(isVisibleViaContractName(_accessKind)); switch (_accessKind) { case ContractNameAccessKind::Local: { - solAssert(!libraryFunction(), "Library member cannot be accessed from local/deriving scope"); + solAssert(!libraryFunction(), "Library members can only be accessed via library name."); solAssert(visibility() > Visibility::Private, "Private non-library member is not visible via contract type name"); if (!Declaration::isVisibleInContract() || !isImplemented()) @@ -513,7 +515,7 @@ Type const* FunctionDefinition::typeViaContractName(ContractNameAccessKind const case ContractNameAccessKind::Foreign: { solAssert(!libraryFunction(), "Library members can only be accessed via library name."); - solAssert(isVisibleViaContractTypeAccess(), "Externally invisible member accessed via contract name."); + solAssert(isVisibleViaContractTypeAccess(), "Invisible member accessed via contract name."); // Foreign contract member function being accessed via contract type name, cannot be called. return TypeProvider::function(*this, FunctionType::Kind::Declaration); } diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index b84882191..1566d3440 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -306,10 +306,28 @@ class Declaration: public ASTNode, public Scopable Library, ///< Via library name (no distinction between local or foreign access). }; + bool isVisibleViaContractName(ContractNameAccessKind const _accessKind) const + { + switch (_accessKind) + { + case ContractNameAccessKind::Local: + return visibility() > Visibility::Private; + case ContractNameAccessKind::Foreign: + return isVisibleViaContractTypeAccess(); + case ContractNameAccessKind::Library: + return isVisibleAsLibraryMember(); + } + + util::unreachable(); + } /// @returns the type for members of the containing contract type that refer to this declaration. Depends on access /// context defined by `ContractNameAccessKind`. /// This can only be called once types of variable declarations have already been resolved. - virtual Type const* typeViaContractName(ContractNameAccessKind const) const { return type(); } + virtual Type const* typeViaContractName(ContractNameAccessKind const _accessKind) const + { + solAssert(isVisibleViaContractName(_accessKind)); + return type(); + } /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. /// @returns null when it is not accessible as a function. diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 3713ac37a..3fa068491 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3975,32 +3975,37 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons if (declaration->name().empty()) continue; - if (contract.isLibrary() && declaration->isVisibleAsLibraryMember()) + if (!contract.isLibrary()) { - // In case the contract is library, add only visible library members. visibility >= Internal. - members.emplace_back( - declaration, - declaration->typeViaContractName(Declaration::ContractNameAccessKind::Library) - ); - } - else if (!contract.isLibrary() && inDerivingScope && declaration->visibility() > Visibility::Private) - { - // In case of regular contract (not library) and member is in the same deriving scope, add all - // members which are not private. Private members cannot be accessed via contract type name - // i.e C.fooPrivate. - members.emplace_back( - declaration, - declaration->typeViaContractName(Declaration::ContractNameAccessKind::Local) - ); + if (inDerivingScope) + { + if (declaration->isVisibleViaContractName(Declaration::ContractNameAccessKind::Local)) + { + members.emplace_back( + declaration, + declaration->typeViaContractName(Declaration::ContractNameAccessKind::Local)); + } + } + else // !inDerivingScope + { + if (declaration->isVisibleViaContractName(Declaration::ContractNameAccessKind::Foreign)) + { + members.emplace_back( + declaration, + declaration->typeViaContractName(Declaration::ContractNameAccessKind::Foreign) + ); + } + } } - else if (!contract.isLibrary() && !inDerivingScope && declaration->isVisibleViaContractTypeAccess()) + else // isLibrary { - // In case of regular contract (not library) being accessed from foreign contract (not in deriving - // scope), add only externally visible members. - members.emplace_back( - declaration, - declaration->typeViaContractName(Declaration::ContractNameAccessKind::Foreign) - ); + if (declaration->isVisibleViaContractName(Declaration::ContractNameAccessKind::Library)) + { + members.emplace_back( + declaration, + declaration->typeViaContractName(Declaration::ContractNameAccessKind::Library) + ); + } } } }